Author Topic: Pull stream in mixer: Initial frames not adhering to granule  (Read 549 times)

saga

  • Posts: 2654
I plugged a pull stream into a mixer that requires to be processed in chunks of 960 frames or multiples thereof; before using a mixer, I simply set its BASS_ATTRIB_GRANULE to 960 and all was fine. After adding a mixer (on which I also set BASS_ATTRIB_GRANULE and BASS_ATTRIB_BUFFER accordingly), I now observe that the first call to the pull stream's callback typically requests 240 frames, followed by 720 frames, and after that it always requests 960 frames. Is there a way to consistently get 960 frames as before, even if may mean that the stream will start a few ms later? I'd really like to avoid adding yet another internal buffer to this stream if it's possible. Alternatively, if there is a guarantee that those "incomplete" frames will only happen at the start of the stream like I observed, then I think it's okay too because I can simply fill them with silence until I have enough data to process.
« Last Edit: 9 Nov '21 - 13:37 by saga »

Ian @ un4seen

  • Administrator
  • Posts: 25275
The BASS_ATTRIB_GRANULE setting isn't currently available on decoding channels, so it isn't possible to use that on mixer sources. You can use it on the mixer, but the mixer may break the source data requests down to smaller amounts (eg. when ramping volume/pan changes) or even larger amounts when resampling. In your case, it sounds like it may be the initial ramp-in at the start of the source that you're seeing. Does adding the BASS_MIXER_CHAN_NORAMPIN flag to your BASS_Mixer_StreamAddChannel call prevent it?

saga

  • Posts: 2654
Disabling the ramp-in does seem to avoid the problem for now. As I don't think I really need the ramp-in, I will keep it disabled for now. Thanks!

The main problem with breaking down the requests into smaller chunks is that the audio to fill the pull stream arrives in 20ms packets - and as it's a continuous audio stream, it isn't really possible to fill it with silence if I get two 10ms requests in a row - hence I always appreciated the existence of BASS_ATTRIB_GRANULE.

Ian @ un4seen

  • Administrator
  • Posts: 25275
You could perhaps emulate the BASS_ATTRIB_GRANULE option by using an intermediate custom stream (created with BASS_StreamCreate), and have the STREAMPROC first check how much data is available from the source and round that down to a whole number of units, eg. return nothing if there is less than 960 sample frames available.

saga

  • Posts: 2654
I tried something like just now. My pull stream already happens to be a custom stream, and now I observed that when returning 0 for the initial request of 240 frames, BASS will keep calling the stream callback with a request of 240 frames, so it never ends up putting anything into the stream. Is this not what you meant?

Ian @ un4seen

  • Administrator
  • Posts: 25275
Oops, I didn't quite think it through :)

BASSmix doesn't buffer data from sources (except a small resampling buffer) so it will just keep requesting exactly the required amount, as you saw. So to have the source processed in fixed blocks, you would need to implement the buffering in the STREAMPROC, ie. get a block of data from the source and keep any remainder for the next call after returning the requested amount.