lostromb/concentus.oggfile

Can't play Opus file

Closed this issue · 6 comments

Hello

I've been trying to decode an opus file now without success. I also read the other ticket where the problem was, that it was a WebM file or something. Now I'm pretty sure what I have a real opus file. I tried deocding it two ways. With the "normal" concentus library like this:

var bytes = File.ReadAllBytes("Opus Test.opus"); var frameSize = OpusPacketInfo.GetNumSamples(decode, bytes, 0, bytes.Length); var @out = new short[frameSize]; var thisFrameSize = decode.Decode(bytes, 0, bytes.Length, @out, 0, frameSize, false);

Which always give me a "Corrupt stream" error.

The second try was with this library:

var decode = new OpusDecoder(48000, 2); var stream = new OpusOggReadStream(decode, File.OpenRead(@"G:\Ace Attorney Online\Case Cafe\base\sounds\music\A Cornered Heart ~ SOJ.opus")); using (var f = File.OpenWrite(@"Test.raw")) { while (stream.HasNextPacket) { var shorts = stream.DecodeNextPacket(); var outBytes = ShortsToBytes(shorts); f.Write(outBytes, 0, outBytes.Length); } }

Which didn't raise an exception, but the File couldn't be read or played at all in the end.
I'm definetely doing something wrong but I don't know what.

Opus Test.zip
Forgot uploading the file

I think this just comes down to confusion about containerization.

Your input file is an .opus file, which means it is an .ogg container file containing opus encoded packets.
Your first code is incorrect because it attempts to read the .ogg container data directly and interpret it as opus packets, which rightly gives you a corrupted stream error.

The second code is fine because the OpusOggReadStream parses the ogg container and decodes the packets properly. I don't see any problem there.

I'm guessing when you playback the .raw output file (which should be 37,804,800 bytes large, correct?) the player doesn't understand it because there's no container info on the output, it's just the raw audio samples (normally, uncompressed audio is in the .wav format, which has a few dozen bytes of header data and then the raw audio data afterwards).

You can resolve this by either opening the output file in a player like WavePad or Audacity which lets you open / interpret a "raw" audio file- in which case you'd have to specify 48000Hz, Stereo, 16-bit little-endian - or alter your code to add the .wav container data automatically. For that I would recommend pulling the NAudio library and using their WaveFileWriter

Oh man, I have no idea how audio files work. No clue why I'm even working with them. But thank you. I tried exporting the raw bytes via NAudio's WaveFileWriter and now it's a propper WAV that can get played. You just saved me from failing my deadline.

Okay, there's still a small issue. While it can be played now, it adds a lot of silence at the end. The original opus file is 03:16 long. But the decoded wav file is 05:27 long. After the 03:16 mark it's just silent for the rest of the time. Any idea how I can remove that?

Not sure. I'd guess it's something in NAudio, because in the earlier code that just dumped the raw audio after decoding, that data was 3:16 long. Does the audio sound correct? Does it play back at the right pitch and in stereo?
The ratio of actual data / total file length is exactly 0.60 so I would start looking for anything which uses that ratio in code. Make sure the output file is also set to 48000Hz / 2 channels / 16 bits per channel

I investigated and it is not NAudio. I imported the raw output, as you mentioned, in Audacity. And yes, I put the settings to 48000, 2 and 16. It sounds correct but there's over 2 minutes of silence at the end. So the issue has to be somewhere else.