gavv / signal-estimator

Measure characteristics of a looped back signal.
MIT License
63 stars 17 forks source link

Support various [USB] soundcards that do not support signed 16bit #78

Closed x42 closed 10 months ago

x42 commented 10 months ago

Currently signal-estimator hardcodes SND_PCM_FORMAT_S16_LE `in AlsaUtils.cpp and hence fails to work with all soundcards here (except for the onboard HDA intel, which is not interesting for pro-audio):

build/x86_64-linux-gnu/signal-estimator -i hw:1 -o hw:1 --out-latency 1024 --in-latency 1024
[EE] can't set hw params: snd_pcm_hw_params_set_format(): Invalid argument

Please consider adding support for other formats. Thanks in advance!

(Also the default buffersize of 8000 is rather large. Many USB devices bail with buffers > 4096).

gavv commented 10 months ago

I see, will look into it!

Regarding buffer size, just to be sure, do you mean 4096 microseconds or samples? (--out-latency and --in-latency are in microseconds).

x42 commented 10 months ago

I see, will look into it!

Thanks. If you need some inspiration, perhaps look at

https://github.com/Ardour/ardour/blob/49abbe57778b9ad301410eae064f054a00c0dd9d/libs/backends/alsa/zita-alsa-pcmi.cc#L981-L1048

which is based on http://kokkinizita.linuxaudio.org/linuxaudio/downloads/zita-alsa-pcmi-0.6.1.tar.bz2

Regarding buffer size, just to be sure, do you mean 4096 microseconds or samples?

oops. I meant sample/cycle

gavv commented 10 months ago

Regarding buffer size, if you run s-e with default parameters and with -vv, you'll see:

./bin/x86_64-linux-gnu/signal-estimator -vv -i hw:0 -o hw:0
[II] opening alsa writer for device hw:0
[DD] requested_latency: 8000 us
[DD] requested_buffer_size: 384 samples
[DD] selected_buffer_time: 8000 us
[DD] selected_buffer_size: 384 samples
[DD] selected_period_time: 4000 us
[DD] selected_period_size: 192 samples
[DD] selected_channel_count: 2

i.e. 8000 us corresponds to 384 samples/cycles. I wonder what minimum and maximum values are supported by your cards? I selected 8000us because it's minimum value that is supported by all my cards (all consumer-grade).

gavv commented 10 months ago

If you need some inspiration, perhaps look at

I actually already have pcm mapper in another project, which covers all ALSA PCM encodings (I think), so I ported it to s-e:

You can now use options like --out-format s24_3le or --in-format s32.

To get list of supported formats:

./bin/x86_64-linux-gnu/signal-estimator -L                                     
Device formats:
  s8 u8
  s16 s16_be s16_le u16 u16_be u16_le
  s18_3 s18_3be s18_3le u18_3 u18_3be u18_3le
  s20_3 s20_3be s20_3le u20_3 u20_3be u20_3le
  s20 s20_be s20_le u20 u20_be u20_le
  s24_3 s24_3be s24_3le u24_3 u24_3be u24_3le
  s24 s24_be s24_le u24 u24_be u24_le
  s32 s32_be s32_le u32 u32_be u32_le
  float float_be float_le
  float64 float64_be float64_le

s-e now will first try to use format that you specified (or s16 if you didn't provide option) and then will search for any format accepted by card. After it finds working format, it will automatically perform conversion to/from its internal format (still s16). With -vv, you will see what format was selected in logs.

Unfortunately cards that I have currently support only s16 and s32, so I can't test most of the formats. So it would be nice if you could test a few of them on your hardware.

gavv commented 10 months ago

Also added format selection to GUI: 8f514b9db4adbae18b311221fb0dc1378f2b1172

x42 commented 10 months ago

Nice. Works now with the UA-25. Thanks!

I did not have to change the options in the GUI. It automatically used 24_3LE even though the GUI still read s16.

I did however change the I/O ringbuffer size to 21333uSec (1024 sample/cycle) to compare against jack_delay.

image

Card 1 (UA25):
  * Playback Device 0 (USB Audio):
    - Subdevice 0 (hw:UA25,0,0):
      used by: signal-estimato (PID 2923945)
      access: RW_INTERLEAVED
      format: S24_3LE
      subformat: STD
      channels: 2
      rate: 48000 (48000/1)
      period_size: 512
      buffer_size: 1024

  * Recording Device 0 (USB Audio):
    - Subdevice 0 (hw:UA25,0,0):
      used by: signal-estimato (PID 2923945)
      access: RW_INTERLEAVED
      format: S24_3LE
      subformat: STD
      channels: 2
      rate: 48000 (48000/1)
      period_size: 512
      buffer_size: 1024

With identical settings, jack_delay (and Ardour's built-in ALSA latency measurement tool) reliably measures a systemic latency of 1016 samples (21.167ms), and I can confirm this by using Ardour to record overdubs using a loopback cable. The difference is that those use MMAP (and not RW).

The jitter with your tool is also an order or magnitude larger. With jackd it is was around +/- 100us last time I measured it with the UA-25. but that was a few years ago, I'll have to do this again since the system changed as did the USB kernel driver. I''ll open another bug report for this.

With USB URBs timed at 1ms intervals it is certainly believable that it is +/-500usec like your tool shows.

Kudos, signal-estimator makes measurement a lot simpler than https://hal.science/hal-02158923/file/Timing.pdf which took me a day to setup.

x42 commented 10 months ago

Also works with the Presonus 1818VSL

image

Card 1 (VSL):
  * Playback Device 0 (USB Audio):
    - Subdevice 0 (hw:VSL,0,0):
      used by: signal-estimato (PID 2926042)
      access: RW_INTERLEAVED
      format: S32_LE
      subformat: STD
      channels: 14
      rate: 48000 (48000/1)
      period_size: 192
      buffer_size: 384

  * Recording Device 0 (USB Audio):
    - Subdevice 0 (hw:VSL,0,0):
      used by: signal-estimato (PID 2926042)
      access: RW_INTERLEAVED
      format: S32_LE
      subformat: STD
      channels: 14
      rate: 48000 (48000/1)
      period_size: 192
      buffer_size: 384
x42 commented 10 months ago

Thanks for addressing this so fast!

gavv commented 10 months ago

Thanks for testing it!

With identical settings, jack_delay (and Ardour's built-in ALSA latency measurement tool) reliably measures a systemic latency of 1016 samples (21.167ms), and I can confirm this by using Ardour to record overdubs using a loopback cable. The difference is that those use MMAP (and not RW).

The jitter with your tool is also an order or magnitude larger. With jackd it is was around +/- 100us last time I measured it with the UA-25. but that was a few years ago, I'll have to do this again since the system changed as did the USB kernel driver. I''ll open another bug report for this.

Interesting. Probably we could try mmap approach too and see if there are differences. (Patches are welcome BTW)

I'm not very familiar with JACK, so a stupid question: in your setup, does signal-estimator work with ALSA hw devices directly, or via jackd? If that was the case, it would make sense to try raw devices instead.

Also, since you selected quite big buffer size, you can try increasing number of periods in buffer (--out-periods and --in-periods). This will increase granularity of timestamping and probably will give better precision.

I'd appreciate if you'll be able to run s-e and jack_delay in same setup and post comparison. Not sure when I'll be able to work on this closely, but I think this data can help. You could also capture dump using --dump-file option (doc).

It would be also interesting to run -m io_jitter and -m io_delay modes on your card. These modes measure jitter of time when ALSA wakes up us, and also ring buffer and hw delay reported by alsa (doc). I wonder if jitter reported by io_jitter would be comparable which jitter you're observing.