Author Topic: BASS_StreamPutData and bpm detection  (Read 3701 times)

DS

  • Guest
BASS_StreamPutData and bpm detection
« on: 21 Dec '11 - 22:36 »
Hi all,
I want to analyze the bpm of a 20 second PCM array using Bass FX. Here is what I'm doing:

Code: [Select]
HSTREAM decodingChannel = BASS_StreamCreate(44100, 2, BASS_STREAM_DECODE, STREAMPROC_PUSH, 0);
BASS_StreamPutData(decodingChannel, bytes, bytesWritten);
//bytes is an array of PCM data (44.1khz, stereo, 16bit), obtained using the AVFoundation Framework of the iOS SDK. I'm pretty sure the PCM data is correct, since I can play the stream just fine if I remove the BASS_STREAM_DECODE flag.
//bytesWritten is an integer with the number of bytes contained in the bytes array

float trackBPM = BASS_FX_BPM_DecodeGet(decodingChannel, 5.0, 15.0, 0, BASS_FX_BPM_MULT2 | BASS_FX_FREESOURCE, NULL);
//returns -1 instead of a bpm value

BASS_ErrorGetCode() returns error code 7 BASS_ERROR_POSITION. I've got no idea what this means for me. Can someone please help me figure it out?
I'm using bass 2.4 and bass fx 2.4 on the iOS platform.

Thanks,
Daniel

gnag

  • Posts: 160
Re: BASS_StreamPutData and bpm detection
« Reply #1 on: 21 Dec '11 - 23:08 »
If you want to get a reliable, realistic BPM Value, dont use that function which is included in BassFx, it relies on the SoundTouch Library and has no settings to finetune/optimize it which is making lots of errors,outputting sometines double/half BPM values, I tested with min/max 50/200 and two pop songs which are from 2011 and got totally wrong values, theres a commercial software which detected the correct,exact values for both songs!

There are tools and algorithms out there which can detect BPM a lot more accurately, I am already playing around for more than 1 week to make myself a working BPM detection, I thought its easy because with manual bpm tapping I could see the correct BPM within seconds, so a computer should be able to do the same even havings lots of more power.

I would be happy if someone implements an alternative BPM detection function, I
a colleague recommendended me to use "Rayshooting", he says its easy to implement/understand and works very well compared to other methods.

Im having a hard time understanding the way this is done, you can take a look at this website where it is explained, it would be awesome if someone finally can port a good bpm detection algorithm from the "C++ World" to C#, sadly Im not good at understanding the mathematic backgrounds.If you want to get a reliable, realistic BPM Value, dont use that function which is included in BassFx, it relies on the SoundTouch Library and has no settings to finetune/optimize it which is making lots of errors,outputting sometines double/half BPM values, I tested with min/max 50/200 and two pop songs which are from 2011 and got totally wrong values, theres a commercial software which detected the correct,exact values for both songs!

There are tools and algorithms out there which can detect BPM a lot more accurately, I am already playing around for more than 1 week to make myself a working BPM detection, I thought its easy because which manual bpm tapping I could see the correct BPM within seconds, so a computer should be able to do the same even havings lots of more power.

I would be happy if someone implements an alternative BPM detection function.
A colleague recommendended me to use If you want to get a reliable, realistic BPM Value, dont use that function which is included in BassFx, it relies on the SoundTouch Library and has no settings to finetune/optimize it which is making lots of errors,outputting sometines double/half BPM values, I tested with min/max 50/200 and two pop songs which are from 2011 and got totally wrong values, theres a commercial software which detected the correct,exact values for both songs!

There are tools and algorithms out there which can detect BPM a lot more accurately, I am already playing around for more than 1 week to make myself a working BPM detection, I thought its easy because with manual bpm tapping I could see the correct BPM within seconds, so a computer should be able to do the same even havings lots of more power.

I would be happy if someone implements an alternative BPM detection function, somone who has more mathematic skills than me.

DS

  • Guest
Re: BASS_StreamPutData and bpm detection
« Reply #2 on: 22 Dec '11 - 07:30 »
Thanks for your replay. Yes, implementing a bpm detection algorithm myself would be an option. But I'm not sure whether I have the necessary maths skills to do that.
While I try to understand how bpm detection algorithms actually work, does anybody know what's wrong with my code?

Ian @ un4seen

  • Administrator
  • Posts: 20389
Re: BASS_StreamPutData and bpm detection
« Reply #3 on: 22 Dec '11 - 15:07 »
Code: [Select]
HSTREAM decodingChannel = BASS_StreamCreate(44100, 2, BASS_STREAM_DECODE, STREAMPROC_PUSH, 0);
BASS_StreamPutData(decodingChannel, bytes, bytesWritten);
//bytes is an array of PCM data (44.1khz, stereo, 16bit), obtained using the AVFoundation Framework of the iOS SDK. I'm pretty sure the PCM data is correct, since I can play the stream just fine if I remove the BASS_STREAM_DECODE flag.
//bytesWritten is an integer with the number of bytes contained in the bytes array

float trackBPM = BASS_FX_BPM_DecodeGet(decodingChannel, 5.0, 15.0, 0, BASS_FX_BPM_MULT2 | BASS_FX_FREESOURCE, NULL);
//returns -1 instead of a bpm value

BASS_ErrorGetCode() returns error code 7 BASS_ERROR_POSITION. I've got no idea what this means for me. Can someone please help me figure it out?

The problem there is that "push" streams don't support seeking, so BASS_FX_BPM_DecodeGet is unable to seek to the start position (5 seconds). Perhaps an option can be added to have BASS_FX_BPM_DecodeGet process the stream from its current position. In the meantime, one way to do that could be to use BASS_FX_BPM_CallbackSet instead. Something like this...

Code: [Select]
float bpm;
BASS_FX_BPM_CallbackSet(decodingChannel, BpmProc, 10, 0, BASS_FX_BPM_MULT2, &bpm); // set BPM processing on the stream
DWORD block=BASS_ChannelSeconds2Bytes(decodingChannel, 1); // process the stream in 1s blocks
BYTE *buf=(BYTE*)malloc(block); // allocate a processing buffer
for (int a=0; a<10; a++) // process 10 blocks/seconds
BASS_ChannelGetData(decodingChannel, buf, block);
free(buf);
BASS_FX_BPM_Free(decodingChannel); // remove BPM processing from the stream
// do something with "bpm" value

...

void CALLBACK BpmProc(DWORD chan, float bpm, void *user)
{
*(float*)user=bpm; // store the BPM value
}