Author Topic: Record PCM data to memory stream or byte array  (Read 1905 times)

kafffee

  • Posts: 291
Re: Record PCM data to memory stream or byte array
« Reply #50 on: 14 Nov '24 - 18:48 »
Quote
Is your SyncTrackEnd function is getting called?

No, oddly not...

Quote
If not, are you calling BASS_ChannelStop on the stream or BASS_Stop?

No. I start and stop recoprding, then I hit "play", which will execute PlayPause_Execute. It should actually be called PlayStopExecute, I did not rename that yet. For pausing playback, I have another button.

In my opinion we should take a closer look at these lines of code (you can find this in my StartPlayBack() procedure):

Code: [Select]

 Dim Rest As Long = PlayBackPositionInBytes Mod BytesPerSample()       'get remainder of division PlayBackPositionInBytes / BytesPerSample; BytesPerSample = number of channels * bit resolution / 8
PlayBackArray = New Byte(CInt(BytesWritten - PlayBackPositionInBytes - Rest) - 1) {}  'initializing PlayBackArray to the right required size; only whole samples because of Rest; BytesWritten: total amount of bytes recorded in RecordedData

 Array.Copy(RecordedData, PlayBackPositionInBytes, PlayBackArray, 0, PlayBackArray.Length)  'copy data from the recording to PlayBackArray; RecordedData= complete recording; PlayBackPositionInBytes = starting position of playback in RecordedData

 Bass.BASS_ChannelSetPosition(PlayBackChannel, 0)
 Bass.BASS_StreamPutData(PlayBackChannel, PlayBackArray, PlayBackArray.Length Or CInt(BASSStreamProc.BASS_STREAMPROC_END))  'as you are not a .NET user, are you sure this is right? CInt will convert value to integer, Or is true when one of the two or both values are true;
'also: sometimes I still get BASS_ERROR_ILLPARAM. even though this should not happen anymore, because I cut off the remainder of not complete samples with Rest in line 2
 Debug.WriteLine("streamputdata: " & Bass.BASS_ErrorGetCode.ToString)

 Bass.BASS_ChannelPlay(PlayBackChannel, False)

Does this code seem correct to you?
« Last Edit: 14 Nov '24 - 19:09 by kafffee »

Ian @ un4seen

  • Administrator
  • Posts: 26172
Re: Record PCM data to memory stream or byte array
« Reply #51 on: 15 Nov '24 - 13:31 »
Quote
Is your SyncTrackEnd function is getting called?

No, oddly not...

Try also setting a BASS_SYNC_FREE sync on the stream and put a breakpoint in the callback function to see if/when that gets called when running in the debugger. If you then check the callstack (make sure you have mixed-mode debugging enabled), perhaps it'll lead back to an unintentionally early BASS_StreamFree call to explain why playback never reaches the end.

In my opinion we should take a closer look at these lines of code (you can find this in my StartPlayBack() procedure):

Code: [Select]

 Dim Rest As Long = PlayBackPositionInBytes Mod BytesPerSample()       'get remainder of division PlayBackPositionInBytes / BytesPerSample; BytesPerSample = number of channels * bit resolution / 8
PlayBackArray = New Byte(CInt(BytesWritten - PlayBackPositionInBytes - Rest) - 1) {}  'initializing PlayBackArray to the right required size; only whole samples because of Rest; BytesWritten: total amount of bytes recorded in RecordedData

 Array.Copy(RecordedData, PlayBackPositionInBytes, PlayBackArray, 0, PlayBackArray.Length)  'copy data from the recording to PlayBackArray; RecordedData= complete recording; PlayBackPositionInBytes = starting position of playback in RecordedData

 Bass.BASS_ChannelSetPosition(PlayBackChannel, 0)
 Bass.BASS_StreamPutData(PlayBackChannel, PlayBackArray, PlayBackArray.Length Or CInt(BASSStreamProc.BASS_STREAMPROC_END))  'as you are not a .NET user, are you sure this is right? CInt will convert value to integer, Or is true when one of the two or both values are true;
'also: sometimes I still get BASS_ERROR_ILLPARAM. even though this should not happen anymore, because I cut off the remainder of not complete samples with Rest in line 2
 Debug.WriteLine("streamputdata: " & Bass.BASS_ErrorGetCode.ToString)

 Bass.BASS_ChannelPlay(PlayBackChannel, False)

Does this code seem correct to you?

That seems OK, but note the playback stream would need to be recreated (not reused) whenever the sample format changes. Not doing so could explain the BASS_ERROR_ILLPARAM error because your "BytesPerSample" value doesn't match the stream's.

kafffee

  • Posts: 291
Re: Record PCM data to memory stream or byte array
« Reply #52 on: 15 Nov '24 - 15:46 »
Okay, did that and I found out about it, but there is something else not right.

After I removed the BASS_STREAM_AUTOFREE flag, it seemed to work three or four times (my SyncTrackEnd function was called and my waveform was okay, too), and then there I was at it again.

I tried a thousand times now, but so far I never got to get it working again.

I still get that BASS_ERROR_ILLPARAM randomly, as it seems... Even though there is no change in BytesPerSample.

Edit:
I put PlayBackPositionInBytes = 0, so there cant't be no ILL_PARAM and that worked.

After playback has stopped (automatically), I checked again as you said in the previous reply:

ChannelIsActive: BASS_ACTIVE_STOPPED
ChannelGetPosition (BASS_POS_BYTE): 0
PlayBackArray Length: 643860
RecordedData Length: 10584000
BytesWritten: 643860
StartPosition in Bytes (sample-locked): 0



But still it stops before all audio data has been played, that is audible and my SyncTrackEnd function is not being called either...
« Last Edit: 15 Nov '24 - 16:11 by kafffee »

Ian @ un4seen

  • Administrator
  • Posts: 26172
Re: Record PCM data to memory stream or byte array
« Reply #53 on: 15 Nov '24 - 17:15 »
I still get that BASS_ERROR_ILLPARAM randomly, as it seems... Even though there is no change in BytesPerSample.

Ah. Looking at the code again, you need to change it like this:

Code: [Select]
Dim Rest As Long = PlayBackPositionInBytes Mod BytesPerSample()       'get remainder of division PlayBackPositionInBytes / BytesPerSample; BytesPerSample = number of channels * bit resolution / 8
PlayBackPositionInBytes = PlayBackPositionInBytes - Rest
PlayBackArray = New Byte(CInt(BytesWritten - PlayBackPositionInBytes) - 1) {}  'initializing PlayBackArray to the right required size; only whole samples because of Rest; BytesWritten: total amount of bytes recorded in RecordedData

After playback has stopped (automatically), I checked again as you said in the previous reply:

ChannelIsActive: BASS_ACTIVE_STOPPED
ChannelGetPosition (BASS_POS_BYTE): 0


BASS_ChannelGetPosition will return the position where the stream stopped at, so that 0 looks like the stream has been rewound with BASS_ChannelSetPosition afterwards or it was recreated?

kafffee

  • Posts: 291
Re: Record PCM data to memory stream or byte array
« Reply #54 on: 16 Nov '24 - 09:35 »
Quote
you need to change it like this

Okay that works, thanks :-)

Quote
BASS_ChannelGetPosition will return the position where the stream stopped at, so that 0 looks like the stream has been rewound with BASS_ChannelSetPosition afterwards or it was recreated?

Okay, done some changes, now I get this:

ChannelIsActive: BASS_ACTIVE_STOPPED
ChannelGetPosition (BASS_POS_BYTE): 589176
PlayBackArray Length: 589176
RecordedData Length: 10584000
BytesWritten: 589176
StartPosition in Bytes (sample-locked): 0


There is still something wrong: I get these values when I set PlayBackPositionInBytes = 0.
So PlayBackArray Length should be the same as RecordedData Length, right?
The playback position marker moves too fast and stops before it reaches the end.

My SyncTrackEnd is being called the right way now...

What's wrong with that now?

Ian @ un4seen

  • Administrator
  • Posts: 26172
Re: Record PCM data to memory stream or byte array
« Reply #55 on: 18 Nov '24 - 16:48 »
Shouldn't "BytesWritten" and "RecordedData Length" be the same? Note that you're calculating "PlayBackArray Length" from "BytesWritten", so the latter's value seems to be where the problem is.