Hi all, I have an implementation question for all you audio gurus. I am implementing the following setup:
View attachment 1459829
I want to use CamillaDSP for room correction + multi-subwoofer setup.
The issue is that the I2S source can switch between 2 channel 16 bit PCM stereo at 48kHz or 5.1 channel IEC 61937-3 (E)AC3 bitstream at 196 kHz.
So far, I modified this code that does a similar detection to work with alsa instead of pulseaudio and also decode EAC3 with libavcodec:
https://github.com/jakemoroni/audio_async_loopback
However, I need to further modify the code to:
Before I start doing so, I keep thinking if there is not a simple way to monitor for a change in v4l-ctrl and reconfigure an audio capture (and decoder pipeline):
View attachment 1459829
I want to use CamillaDSP for room correction + multi-subwoofer setup.
The issue is that the I2S source can switch between 2 channel 16 bit PCM stereo at 48kHz or 5.1 channel IEC 61937-3 (E)AC3 bitstream at 196 kHz.
So far, I modified this code that does a similar detection to work with alsa instead of pulseaudio and also decode EAC3 with libavcodec:
https://github.com/jakemoroni/audio_async_loopback
However, I need to further modify the code to:
- remove the Secret Rabbit Code sample rate converter since I believe the buffering that takes place interferes with Camilla DSP and is not necessary
- detect a sample rate change by monitoring a change in audio_sampling_rate v4l control to dynamically reconfigure Camilla DSP to not output 48kHz, but 196kHz (since both my capture and playback are on the same I2S bus and need to share the same clocks)
Before I start doing so, I keep thinking if there is not a simple way to monitor for a change in v4l-ctrl and reconfigure an audio capture (and decoder pipeline):
- ffmpeg: arecord -D hw:tc358743 -c 2 -t raw -f S16_LE -r 48000 | ffmpeg -hide_banner -loglevel debug -vn -drc_scale 0 timeout=-1 -rw_timeout=-1 -i pipe: -ac 6 -f alsa plughw:CARD=Loopback,DEV=1
- gstreamer: gst-launch-1.0 filesrc location=/mnt/code/ac3/ChID_voices_6ch_256kbps_ddp.ec3 ! ac3parse ! avdec_eac3 ! audioconvert ! "audio/x-raw,channels=6" ! alsasink device=plughw:CARD=Loopback,DEV=1
- others?
A python solution subscribing to the v4l2 control which would start the desired chain should not be complicated. IIUC perhaps this example does the subscription https://github.com/tiagocoutinho/li...3518d3342193a/tests/test_video.py#L1048-L1050 . No idea if it works, but simple to test, best with a good IDE to directly see what is going on (I find PyCharm extremely helpful in situations like this).
I wrote a similar project in Rust https://github.com/pavhofman/gaudio_ctl which subscribes to alsa controls of USB audio gadget and runs/kills a configured subprocess based on notifications from the control. Writing a similar feature in python should be easier.
Henrik has https://github.com/HEnquist/camilladsp-controller in Python which also subscribes to alsa controls but it does not start any subprocess. It sends websocket commands to running CDSP process instead. IIUC you need to restart the whole chain instead.
I wrote a similar project in Rust https://github.com/pavhofman/gaudio_ctl which subscribes to alsa controls of USB audio gadget and runs/kills a configured subprocess based on notifications from the control. Writing a similar feature in python should be easier.
Henrik has https://github.com/HEnquist/camilladsp-controller in Python which also subscribes to alsa controls but it does not start any subprocess. It sends websocket commands to running CDSP process instead. IIUC you need to restart the whole chain instead.
Ok, will have a look at the examples and should consider Python. Funny - I originally started in Rust, but got stuck on how to use a wrapper for libavcodec. Whatever I use, I would need to have 2 pipelines: 1 for PCM stereo audio and 1 to unwrap (demux) IEC 61937-3 (AC3 and EAC3) bitstreams and decode them. Then dynamically switch between them. It seems that all roads always lead back to using libavcodec and alsa.
My fear with Python and subprocesses is latency: what is the method to use libavcodec with the lowest latency possible?
My fear with Python and subprocesses is latency: what is the method to use libavcodec with the lowest latency possible?
- ffmpeg uses libavcodec, so why not use it directly
- gstreamer looks really promising, but misses demuxing of IEC 61937-3 (AC3 and EAC3) bitstreams (see issue #8, issue #942, issue #3589)
Is the PCM decoded from the AC3/EAC3 bitstream actually synchronous to the incoming I2S clock? IIRC players generate the non-audio SPDIF stream by stuffing zeroes to fill the free bandwidth provided by the 48kHz/16bit/2ch channel used for the transfer. DTS takes the whole 1.536Mbps, but AC3 is variable and runs at some 650kbps max (?). If not, then for long-running streams the decoded PCM would cause buffer issues with the output consumer, despite both interfaces being clocked synchronously. But maybe it's not the case.
Related info e.g. https://github.com/philipl/mplayer/blob/5622893acc148a134ff66e18544154f7483e3182/DOCS/tech/hwac3.txt
Related info e.g. https://github.com/philipl/mplayer/blob/5622893acc148a134ff66e18544154f7483e3182/DOCS/tech/hwac3.txt
Last edited: