Opus gapless issue

Started by elan, 7 Mar '25 - 20:56

elan

We've had reports of Opus playback not being properly gapless, and it appears that when decoding using the Opus plug-in it is not using pre-skip or total number of samples to skip data at the starts/ends of the file.

Is this something we need to do manually, or perhaps I've missed a way to configure it to do so?

Many thanks!

Edit: Alternately, is there a way for me to register to handle the Opus format? Our app includes libopus and uses BASS_StreamCreate to make a custom stream which decodes Opus (for various special scenarios), but I'm not sure how to plug it in and say "please use this instead of BASSOPUS for general usage.

Ian @ un4seen

Quote from: elan on  7 Mar '25 - 20:56We've had reports of Opus playback not being properly gapless, and it appears that when decoding using the Opus plug-in it is not using pre-skip or total number of samples to skip data at the starts/ends of the file.

Is this something we need to do manually, or perhaps I've missed a way to configure it to do so?

BASSOPUS does support the pre-skip and total samples values (no config needed). Please upload a file that you're having the problem with to have a look at here:

   ftp.un4seen.com/incoming/

Please also check that BASSOPUS is being used to decode the file, rather than the OS's codecs (eg. Media Foundation), via the "ctype" value from BASS_ChannelGetInfo.

Quote from: elan on  7 Mar '25 - 20:56Edit: Alternately, is there a way for me to register to handle the Opus format? Our app includes libopus and uses BASS_StreamCreate to make a custom stream which decodes Opus (for various special scenarios), but I'm not sure how to plug it in and say "please use this instead of BASSOPUS for general usage.

You could do that by creating your own add-on to use instead of BASSOPUS. It would basically involve adding a few extra functions around your existing STREAMPROC. If you would like to try doing that, the add-on API is available here:

   www.un4seen.com/files/bass-addon.zip

elan

I uploaded ftp://ftp.un4seen.com//incoming/plexamp-opus-gap.zip to your FTP server.

It appears from what our testers are reporting that the pre-skip is handled properly, but the end padding samples from the first track aren't properly elided from the stream.

elan

Quick followup, I managed to get a plugin working as well, a few quick quesrions:

1. Is it OK to use the BASS_PLUGIN_PROC route across all OSs if I want to link the plugin code in?

2. I can't seem to get BASS_ChannelBytes2Seconds to work properly, how do I communicate the duration from the plugin? I've followed the example raw code, and I never get have GetLength called with a mode other than BASS_POS_BYTE so I'm not sure what I'm missing.

Ian @ un4seen

Quote from: elan on 12 Mar '25 - 05:59I uploaded ftp://ftp.un4seen.com//incoming/plexamp-opus-gap.zip to your FTP server.

It appears from what our testers are reporting that the pre-skip is handled properly, but the end padding samples from the first track aren't properly elided from the stream.

The issue is that these OPUS files don't have the EOS flag set in their final page, so it looks like there should be more to come and BASSOPUS doesn't crop it. I believe this is standard behaviour, as the reference OPUSDEC tool does the same. If you would like to use that for reference yourself, you can get it (opus-tools) here:

   https://opus-codec.org/downloads/

Quote from: elan on 12 Mar '25 - 09:471. Is it OK to use the BASS_PLUGIN_PROC route across all OSs if I want to link the plugin code in?

Yes, the BASS_PLUGIN_PROC option is available on all platforms.

Quote from: elan on 12 Mar '25 - 09:472. I can't seem to get BASS_ChannelBytes2Seconds to work properly, how do I communicate the duration from the plugin? I've followed the example raw code, and I never get have GetLength called with a mode other than BASS_POS_BYTE so I'm not sure what I'm missing.

A plugin's GetLength function is only called by BASS_ChannelGetLength (with the same "mode" parameter). BASS_ChannelBytes2Seconds is always handled by BASS, using the stream's sample format, ie. seconds = bytes / bytespersecond

In case by "how do I communicate the duration from the plugin" you meant how to tell BASS when to end the stream, that is done by setting the BASS_STREAMPROC_END flag in the STREAMPROC's return value.

elan

In terms of the EOS flag, this may be because the Opus files are being generated on-the-fly in a streamed transcode. We've been able to skip end padding by comparing total number of pcm samples on the files (once fully downloaded) using op_pcm_total which accounts for the padding.

In any event, I have our custom plugin working quite well now, the confusion I had over length/duration was that I was returning the file size and not the actual stream length, silly me.

Thanks as always for the help!