jketterl / openwebrx

Open source, multi-user SDR receiver software with a web interface
https://www.openwebrx.de
GNU Affero General Public License v3.0
1.03k stars 147 forks source link

OPUS codec instead ADPCM #220

Open zygmund2000 opened 3 years ago

zygmund2000 commented 3 years ago

Hi,

My suggestion is to replace ADPCM codec to OPUS, I think it is better for streaming audio and in future can easily allow to provide stereo audio for receiving eg. FM ord DAB+.

jketterl commented 3 years ago

there's currently neither stereo FM nor DAB support in OpenWebRX, so I don't really see any reason to do this now. How is the CPU consumption on the encoding side in comparison with ADPCM?

zygmund2000 commented 3 years ago

Opus encoder is light and designed for streaming various audio content, I think you know that, but if you don't see reasons to implement so maybe can you give some hint how do that?

jketterl commented 3 years ago

Doesn't really answer my question. I wanted to know how it compares to ADPCM since that achieves a 1:4 reduction with very little CPU on the server. Client CPU isn't that much of my concern.

Hints:

zygmund2000 commented 3 years ago

I don't know how to answer your question about performacne at servers side, I can't compare it right now. I know how to put any encoder into pipelilne chain (audio data are ancoding) but don't how setup it to decode it at client side, I tried view all files and understand it but for me is too complicated yet

jketterl commented 3 years ago

That makes two of us then. I don't know exactly how the client integration would look like either, I have never worked with browser audio codecs. The ADPCM implementation is custom stuff that doesn't follow the official API.

voice06 commented 3 years ago

I'd like to see this at least in terms of reducing bandwidth consumption. Right now with ADPCM according to OpenWebRX its taking 177kbps for the audio stream, could probably get the same audio quality in a 56kbps opus stream.

Not a great 1 to 1 comparison to this app but if I pass nrsc5 through to ffmpeg for ogg opus encoding ffmpeg doesn't exceed 2% CPU, nrsc5 is the cpu intensive end at 6-7% cpu. ffmpeg command: /usr/bin/ffmpeg -loglevel quiet -i - -c:a libopus -b:a 56k -f ogg -

If I swap out ffmpeg for opusenc with the following settings: opusenc --bitrate 56 --raw - - I don't see opusenc exceeding 1.3% cpu

jketterl commented 2 years ago

I have been playing with this a bit today. As expected, implementing an encoder on the server end was easy. Decoding the audio data on the client side however turns out to be troublesome. The data cannot be decoded by decodeAudioData() in Chrome or Firefox, presumably because that expects a surrounding container format. Also, as far as I understand, this method is intended to decoded a complete file, and not a chunked stream.

There is a Javascript/WASM/emscripten implementation (or is it more of a port?) for the opus codec, but it has two problems: It is a big download, and it doesn't declare a license.

If anybody wants to have a go at this, my work is available in the opus branches of csdr, pycsdr and this repository.

jketterl commented 2 years ago

update: the WebCodecs API may be the way to go. i have chunky audio, not good enough, looking for mistakes i made. and i probably broke the playback for adpcm / uncompressed...

sample rates are a problem, opus only supports selected rates... on the client side, the decoder does its own upsampling, which doesn't fit the current setup...

jketterl commented 2 years ago

I'm not necessarily impressed with the results right now. My personal impression is that the audio quality of ADPCM is superior at the same effective network bandwidth (48kbit). I will need to experiment some more with different modulation types.

The main problem right now is that the client decoder seems to crash for unknown reasons, and it seems like this is related to the amount of noise present on the signal. Listening to weak AM or SSB stations is therefor strongly affected by this, and since the decoder needs to be reset everytime, this also leads to a reset of the decoder state. The results are "glitchy" dropouts...

Other problems: The audio rate after the decoder on my system is always 48kHz, even when the data sent to the encoder is 12kHz. I don't really understand the reasoning behind this since the sample rate of the audio context is 44.1kHz, meaning that additional resampling would need to be implemented. I have reconfigured my soundcard to 48kHz to make it work, but there's a number of questions related to this.

Undersampling the encoder seems to lead to weird glitches, which suggests that the encoder does some internal timing to determine lost samples, so the encoder must be used at the fixed sample rates available on the codec. Also, the internal timekeeping may become confused if pipeline data is delayed during times of high load. I have not found documentation related to this, so not sure if it can be disabled.

jketterl commented 2 years ago

Browser support for the WebCodecs API is also lacking... Most notably, Firefox does not seem to support it at all right now...

jketterl commented 2 years ago

Another setback (yep they keep coming): Presumably thanks once again to the secure web advocates, the WebCodecs API is only available on https encrypted websites. Yay! This makes so much sense! /s

jketterl commented 2 years ago

Tried this on a number of signals today. Anything that's analog causes client decoder errors, digital signals seem to be unaffected surprisingly. Unfortunately, the error is pretty generic, it only says "receiver.js:3076 DOMException: Decoding error." so I have very little chance to work out what's actually wrong.

Keeping all the other problems in mind, I can only conclude that this is simply not viable at this point in time.