Author Topic: Understand Bass_ChannelGetData  (Read 633 times)

muntablues

  • Posts: 201
Understand Bass_ChannelGetData
« on: 26 Mar '18 - 08:45 »
Hi there

I am trying to implement the beat detection and waveform rendering to a C# project and after some time, I got it working to get the same values as the demo project does.

My problem at the moment is, that i sometimes get OutOfMemoryException if I load a song. This is caused because I create a byte buffer for the whole song. So I've tried to read only small chunks of a song and use this chunks to do the calculation. Now I dont understand the result of ChannelGetData.

If I use eg. BASS_ChannelGetData(chan, buffer, 1024) and compare the buffer with fullBuffer from BASS_ChannelGetData(chan, fullBuffer, songLength) it is not the same? What am I missing here, to get the same results if I read only small chunks.

Here is the code what is done in the orig. project and I would like to replace this to avoid the out of memory exception!

Code: [Select]
var length=BASS_ChannelGetLength(chan,BASS_POS_BYTE);
int* leftData;
leftData=new int[Length];

check=BASS_ChannelGetData(chan, leftData, Length);

Regards MB

Ian @ un4seen

  • Administrator
  • Posts: 21358
Re: Understand Bass_ChannelGetData
« Reply #1 on: 26 Mar '18 - 17:02 »
Are you calling BASS_ChannelSetPosition between the BASS_ChannelGetData calls? If so, depending on the file format and flags used (eg. MP3 without BASS_STREAM_PRESCAN flag), that can result in different data than decoding straight through. Otherwise, you should get the same data whether you decode the file in a single or multiple BASS_ChannelGetData calls.

Note your code above is allocating 4x as much memory as needed. You should use a "char" array rather than an "int" array to avoid that.

Code: [Select]
char* leftData = new char[Length];

muntablues

  • Posts: 201
Re: Understand Bass_ChannelGetData
« Reply #2 on: 27 Mar '18 - 07:05 »
No I just call ChannelGetData until i reach the end and I create the stream with PRESCAN flag.

I will try to create a little test project where I can compare the different data arrays, will come back with the results!

Thanks so far!
MB

muntablues

  • Posts: 201
Re: Understand Bass_ChannelGetData
« Reply #3 on: 2 May '18 - 17:14 »
Hi Ian

Sorry for the delay, but did not find time to create a test for this issue...

Ok here is what I testet, the two tests are equal, i just changed the file (Mp3 and WAV):

Code: [Select]
[TestMethod]
public void TestGetData()
{
    Bass.Init();
    var stream = Bass.CreateStream(@"ring.mp3", Flags: BassFlags.Decode);
    var length = Bass.ChannelGetLength(stream);
    var full = new int[length];
    Bass.ChannelGetData(stream, full, (int) length);
    var c = full.Any(x => x > 0);

    var stream2 = Bass.CreateStream(@"ring.mp3", Flags: BassFlags.Decode);
    var temp = new int[1024];
    var splitRead = new List<int>();
    int read = 0;
    do
    {
        read = Bass.ChannelGetData(stream2, temp, temp.Length);
        splitRead.AddRange(read == temp.Length ? temp : temp.Take(read));
    } while (read > 0);

    Debug.Print("Full lenght: " + full.Length);
    Debug.Print("Split lenght: " + splitRead.Count);

    for (int i = 0; i < 4096; i++)
    {
        Debug.Print($"Full/Split ({i}): {full[i]}/{splitRead[i]}");
    }
}

and

Code: [Select]
[TestMethod]
public void TestGetData()
{
    Bass.Init();
    var stream = Bass.CreateStream(@"C:\windows\media\Alarm10.wav", Flags: BassFlags.Decode);
    var length = Bass.ChannelGetLength(stream);
    var full = new int[length];
    Bass.ChannelGetData(stream, full, (int) length);
    var c = full.Any(x => x > 0);

    var stream2 = Bass.CreateStream(@"C:\windows\media\Alarm10.wav", Flags: BassFlags.Decode);
    var temp = new int[1024];
    var splitRead = new List<int>();
    int read = 0;
    do
    {
        read = Bass.ChannelGetData(stream2, temp, temp.Length);
        splitRead.AddRange(read == temp.Length ? temp : temp.Take(read));
    } while (read > 0);

    Debug.Print("Full lenght: " + full.Length);
    Debug.Print("Split lenght: " + splitRead.Count);

    for (int i = 0; i < 4096; i++)
    {
        Debug.Print($"Full/Split ({i}): {full[i]}/{splitRead[i]}");
    }
}

I attached two text files from the debug output and you cann see that the mp3 is never equal. The wav file is equal until index 256 then it differs...

Maybe I make something wrong here, but that is the reason why I dont understand the whole stuff.

Thankd for your help!

Regards MB



Ian @ un4seen

  • Administrator
  • Posts: 21358
Re: Understand Bass_ChannelGetData
« Reply #4 on: 3 May '18 - 13:37 »
Try using "char" arrays instead of "int" arrays to hold the data, and see if that makes a difference.

muntablues

  • Posts: 201
Re: Understand Bass_ChannelGetData
« Reply #5 on: 3 May '18 - 15:40 »
Hi Ian

If I use byte[] both arrays are equal.

If I use short[] (16bit) they are equal until index 512.

So I think there is a bug isn't it?

Ian @ un4seen

  • Administrator
  • Posts: 21358
Re: Understand Bass_ChannelGetData
« Reply #6 on: 3 May '18 - 17:08 »
It looks to me like the issue is that the amount of data stored by the "splitRead.AddRange" call depends on the type of the array, ie. "int" is 4x as much as "byte" and "short" is 2x as much as "byte". BASS_ChannelGetData deals in bytes, so if you're going to use "int" or "short" arrays, you will need to adjust the return value accordingly.

muntablues

  • Posts: 201
Re: Understand Bass_ChannelGetData
« Reply #7 on: 3 May '18 - 18:16 »
Ahhh ok, now I understand!

If I read an array of int with length of 1024, I have to read 4096 to fill the whole array, then the results are equal.

Thx for you help!!!

Regads MB