Author Topic: Setting a play point when playing from a memory stream  (Read 63 times)

Ballinger

  • Posts: 52
I am using BASS to record audio.
The user can then play-back from a user selected position in the recording. The user clicks on a visual representation of the recorded waveform to select an approximate in-point.
So, from the recorded data, I create a Playback stream as follows (for 32 bit):
<PlaybackStream :=  BASS_StreamCreate(SampleFreq, ChannelCount, BASS_SAMPLE_FLOAT, @PlaybackCallback, Pointer(MemoryStream));>
Play-back is commenced from the stream as follows:
<BASS_ChannelSetPosition(PlaybackStream, Position, BASS_POS_BYTE);>
<BASS_ChannelStart(PlaybackStream);>
The problem is that the calculated In-Point is not always on an exact sample... sometimes just playing shash.
So in order to fix this, I do some maths to do a block align and make sure that the start point (Position) matches the CHANNEL COUNT and BIT DEPTH as follows:
<Position = Position + (Position mod (WaveHeader.NumChans * WaveHeader.BitsPerSamp)>
But on commencing play-back I still seem to get an occasional Left / Right channel reversal which I just don't understand!
Any ideas how can I ensure that I always hit a first byte of a Ch.1 sample when playing back from memory?
Any help much appreciated!

Ian @ un4seen

  • Administrator
  • Posts: 26264
So in order to fix this, I do some maths to do a block align and make sure that the start point (Position) matches the CHANNEL COUNT and BIT DEPTH as follows:
<Position = Position + (Position mod (WaveHeader.NumChans * WaveHeader.BitsPerSamp)>
But on commencing play-back I still seem to get an occasional Left / Right channel reversal which I just don't understand!

It should be "-" rather than "+" in that calculation, and also "BytesPerSamp" rather than "BitsPerSamp". If you happen to be starting with a time-based position (eg. in seconds) then you could use BASS_ChannelSeconds2Bytes to get the byte position from that.

But note it isn't possible to seek with BASS_ChannelSetPosition (except with BASS_POS_DECODETO) in a stream created with BASS_StreamCreate, so that call would be failing. You should instead just set your STREAMPROC's (PlaybackCallback) read pointer to the wanted position. For example:

Code: [Select]
HSTREAM stream;
BYTE *data;
DWORD datalen;
DWORD datapos;

...

stream = BASS_StreamCreate(freq, chans, BASS_SAMPLE_FLOAT, StreamProc, 0); // create stream
datapos = ...; // set start position
BASS_ChannelStart(stream); // start it

...

DWORD CALLBACK StreamProc(HSTREAM handle, void *buffer, DWORD length, void *user)
{
if (length > datalen - datapos) length = datalen - datapos; // limit it to the available amount
memcpy(buffer, data + datapos, length); // read data
datapos += length; // advance read position
if (datapos == datalen) return length | BASS_STREAMPROC_END; // reached the end
return length;
}

The data/etc variables could be put in a struct/class, and passed to the STREAMPROC via the BASS_StreamCreate "user" parameter, to allow the same code to be used simultaneously with multiple streams.

Ballinger

  • Posts: 52
Thanks for your help Ian... that seems to have fixed it!