GNOME Bugzilla – Bug 791771
opusenc, opusdec: add option to disable phase inversion
Last modified: 2018-11-03 12:02:25 UTC
http://opus-codec.org/docs/opus_api-1.2/group__opus__genericctls.html#ga10fa1f6eab136baf83c232afa989b6a8 When downmixing stereo streams to mono, having phase inversion enabled produces terrible audio quality (it sounds like a low bitrate MP3), since frequency bands randomly cancel out. This should be exposed in the encoder (to produce bitstreams that always sound good when downmixed to mono, regardless of what the decoder does), and in the decoder (to allow any arbitrary bitstream to sound good when downmixed to mono, regardless of what the encoder did). On the decoder, additionally, it should probably default to disabled (i.e. OPUS_SET_PHASE_INVERSION_DISABLED(1)) when the output channel count is 1. Here's a sample of just how bad decoding opus to mono without this enabled sounds: https://mrcn.st/t/opus_decoding_test.ogg . This is 6 seconds of stereo decoding, 3 seconds of mono decoding, repeatedly. The input bitstream is the same in both cases, with phase inversion enabled, as is the case right now in gstreamer. It gets *really* bad at 0:50 or so. See also: https://tools.ietf.org/html/rfc8251#section-10
After some googling and testing, your report is a bit off. So if the output channels count is 1, this setting have just no effect (I just tested it). Which makes sense, since in this case the decoder is aware of this side effect and can avoid it. The problem is when we produce let's say a stereo stream and downmix outside of the decoder. That's where you can ear the bad audio. gst-launch-1.0 filesrc location=stereo.wav ! wavparse ! opusenc ! opusdec ! audio/x-raw,channels=2 ! audioconvert ! audio/x-raw,channels=1 ! pulsesink Now, what the doc says is that stereo quality will be decrease, but marginally, while the stream will be down sampler friendly.
Created attachment 373234 [details] [review] opusdec: Add property to control phase inversion When enabled, phase-inversion slightly increase stereo quality, but produce a stream that when downmixed to mono will present important audio distortion. This patch disables this feature by default and introduce a property that let user enable it if desired.
Attachment 373234 [details] pushed as d2aff7b - opusdec: Add property to control phase inversion
Thanks for the fix. Yes, I wasn't clear in my report: the problem occurs when the stream is downmixed outside the decoder itself. If libopus is downmixing the stream itself then it knows how to do the right thing. The issue is that pretty often downmixing happens later and the decoder has no idea.
I see the patch is for opusdec only. Can we get the same feature implemented for opusenc? That was actually my use case: I'm encoding audio with gstreamer for WebRTC distribution, and Chrome was spuriously downmixing it (due to a bad RTP descriptor, but that's another story), causing extremely bad audio quality. I want to ensure that regardless of what clients do, I don't get this effect. In fact disabling phase inversion by default (unconditionally, not just for mono output) in the decoder may not be the best idea, since it'll reduce stereo imaging for streams that use it. I was thinking disabling it in the encoder might be a good idea, since it ensures streams sound good regardless of what the decoder does or any downmixing that occurs. But if the decoder thinks the channel count is 2 then it probably makes sense to leave it on, so that if the encoder relied on the feature it is used. Of course, if something downstream ends up downmixing the audio to mono then it'll sound bad, so I guess it depends on how likely we think that will be.
-- GitLab Migration Automatic Message -- This bug has been migrated to freedesktop.org's GitLab instance and has been closed from further activity. You can subscribe and participate further through the new bug through this link to our GitLab instance: https://gitlab.freedesktop.org/gstreamer/gst-plugins-base/issues/409.