libobs: Implement asynchronous sample rate conversion for audio#6351
libobs: Implement asynchronous sample rate conversion for audio#6351norihiro wants to merge 8 commits intoobsproject:masterfrom
Conversation
54a2b75 to
aa38840
Compare
9eeb15e to
ec47a17
Compare
|
Hi, if you need a macos intel tester Ill be glad!! Figthing with this bug till i bought a new Maudio Mtrack DUO 48kHz soundcard, but it sound a little worse than mi UMC404-192kHz one(wich dont exactly match the clock in 48kHz mode and drops a few ms of audio every 2:20 min aprox) |
f5aec3a to
c0392ec
Compare
I appreciate your comment. You can download a package for macOS by this instruction. Since the code is not signed and notarized, you might need to adjust security settings on your macOS. |
3821723 to
0a36bd0
Compare
|
Other than for testing purposes, is there any reason to want to have async compensation be a configurable value in sources? To me it seems like it should always be on unless there is a good reason to want it off. |
It's a good point.
Anyway, libobs need to have the switch to have async-SRC. Obviously, media source and VLC source have to disable the async-SRC.
|
0a36bd0 to
3d37efd
Compare
Seems like a UI chat question. If every source should be able to enable/disable conversion, then perhaps it should not be up to the source itself and instead be configured through the advanced audio dialog. Or, if that's too complicated still for users, we just make more assumptions and handle the rest inside of obs-audio. |
3d37efd to
55d57fc
Compare
55d57fc to
e78a06f
Compare
c906af2 to
4caef71
Compare
4caef71 to
57b3fcc
Compare
3e3bb30 to
2c9f064
Compare
This commit implements a property to enable asynchronous sample rate conversion (SRC) in the PR obsproject/obs-studio#6351. This commit relies on the PR so that the implementation is disabled by default. Assuming the user of this plugin has enough knowledge for asynchronous sample rate and genlock, the option is disabled by default.
This commit implements a property to enable asynchronous sample rate conversion (SRC) in the PR obsproject/obs-studio#6351. This commit relies on the PR so that the implementation is disabled by default. Assuming the user of this plugin has enough knowledge for asynchronous sample rate and genlock, the option is disabled by default.
|
When we could test it? |
2c9f064 to
c705ee8
Compare
|
Rebased and the build flow has passed. You can test it from the summary page. |
|
Hi. Is this change missing in the current version of obs 31? If so, is it expected to be added soon? |
|
This has not been merged yet, so it is not missing from any release. We prefer not to provide estimations on PR reviews as the project priorities are constantly in flux. |
There was a problem hiding this comment.
The code is very clean and well written.
I appreciated the explanations with reference to the research behind the compensation filter.
As discussed in another PR, FFmpeg has the aresample filter which has both hard and soft compensation. Can you summarize the differences and see if this can suggest improvements to your current implementation ?
Also could this filter help solve the desync issues with all audio outputs (chiefly, decklink and ndi)
(currently there is a low latency audio buffering option which sets oai->max_buffering_ms to 20 ms and triggers :
https://github.com/obsproject/obs-studio/blob/master/libobs/obs.c#L1612
and following)
Sidenote: please rebase the PR
| #endif | ||
|
|
||
| async_compensation = obs_data_get_bool(settings, "async_compensation"); | ||
| obs_source_set_async_compensation(data->source, async_compensation); |
There was a problem hiding this comment.
in theory this is a no-op, if async_compensation value has not changed. So it's OK.
But in general, we store source settings as members of the base data struct, and update it only if its value has changed, so this saves a call. I will readily agree that here it does not make much difference though.
(same remark for other sources where you followed the same pattern)
| lag_lead_filter_tick(&rs->compensation_filter, rs->input_freq, in_frames); | ||
| double drift = lag_lead_filter_get_drift(&rs->compensation_filter); | ||
|
|
||
| ret = swr_set_compensation(rs->context, -(int)(drift * 65536 / rs->input_freq), 65536); |
There was a problem hiding this comment.
where does that figure come from ?
| if (!rs->compensation_filter_configured) { | ||
| // Parameters are determined experimentally by SPICE simulation | ||
| // to have these characteristics. | ||
| // - Unity gain frequency: 1/180 Hz (inverse of 3 minutes) |
There was a problem hiding this comment.
did you experiment with shorter and longer times ? say 1 min so 1/60 Hz and 5 min so 1/300 Hz ?
Regarding this curve:
https://user-images.githubusercontent.com/780600/180902267-e95694da-7aed-46c2-839b-36c5fe097f15.png
how is it modified ?
Is the sample/sec negative compensation due to input lag ? have you tested the reverse condition (through a simulation for instance)
More generally, can you explain why the filter converges to a plateau ? it seems to mean that the input source is intrinsically lagging if the filter must always compensate ?
c705ee8 to
6ab3caa
Compare
An API `audio_resampler_compensate` is added that activates resampling compensation by calling `swr_set_compensation`.
|
Rebased to resolve conflicts. |
7be8ff5 to
13cf845
Compare
This commit implements asynchronous sample-rate conversion for audio source.
Since the audio from most sound devices are asynchronous, it requires to be compensated so that the audio source provides exactly necessary amount of samples. The option is enabled by default. Also update linux-alsa.
When `use_device_timing` is not set, the audio from the device is asynchronous. It requires to be compensated to avoid audio glitch. The option is masked if `use_device_timing` is set. The option is enabled by default for wasapi_input_capture.
Since the audio from most sound devices are asynchronous, it requires to be compensated so that the audio source provides exactly necessary amount of samples. The option is enabled by default.
Since the audio from the device is asynchronous, it requires to be compensated so that the audio source provides exactly necessary amount of samples. The option is enabled by default.
Since the audio from the device is asynchronous, it requires to be compensated so that the audio source provides exactly necessary amount of samples. The option is enabled by default.
13cf845 to
c88796e
Compare


Description
This PR implements asynchronous sample-rate conversion by utilizing a soft compensation feature in libswresample. A digital approach of asynchronous sample-rate conversion was proposed in 1, a PDF is available here. Also described in 2. The soft compensation in libswresample uses similar technique as 1. In addition, a traditional lag-lead filter is implemented to eliminate errors at steady state.
As described in the description of the PR #6133,
next_audio_ts_minshould be same asdata->timestamp + conv_frames_to_time(sample_rate, in.frames). However, just overwritingnext_audio_ts_mincannot compensate insufficient or too many number of samples. Instead, the difference between these values will be fed to the soft compensation.A lag-lead filter is widely used in a conventional PLL design. In the feedback loop, the lag-lead filter is employeed for these purposes.
The unity gain frequency of the feedback loop is set to 1/180 Hz so that the fluctuations faster than 3 minutes will be suppressed
and I believe users won't notice transition at the startup.
This PR also changes built-in plugins to enable the feature by default.
obs-ffmpeg-source and vlc-video (for realtime streaming)It's not easy to implement since the flow is controlled in the threadmp_media_thread.Note: Though the implementation looks working, I'd like to clean the code to make it more readable.
Motivation and Context
Since most of audio sources are asynchronous,
the number of samples provided from the audio sources is sometimes insufficient or too many,
which causes audio glitch as #4600 and audio/video desync.
Fix #4600.
How Has This Been Tested?
The code is tested on Fedora 34 with MOTU M2 and recording a tone signal.
Also analyzed step response and frequency response of the feedback system with my SPICE model.
Frequency response of the open loop transfer function. Gain curve crosses 0 dB at 5.55 mHz (inverse of 3 minutes) and shows suppression for higher frequency components to eliminate fluctuation such as USB and load of the host. At 5.55 mHz, the phase curve shows 60 degree phase margin so that the feedback system is stable.
Simulated and measured step response of the system. This figure shows step response how the compensation is applied (vc1) and another internal node in the lag-lead filter (vc2), measured with MOTU M2 with Fedora 34. It estimated roughly 4.5 samples are are missing for every second. The implementation gradually started to add samples and reached maximum compensation -5.3 samples per second after 80 seconds from the start, then goes to the steady state compensating 4.5 samples per second. The other node vc2 slowly track vc1 so that it eliminates offset at the steady state. The curves of measured and simulated model are well matched except between 100 seconds to 300 seconds. I think we can rely on the model so that the gain and phase curves are well simulated and conclude the feedback system has enough stability.
Types of changes
Checklist: