Author Topic: BASS 2.4 and BASS_ChannelGetData()  (Read 2496 times)

3delite

  • Posts: 907
BASS 2.4 and BASS_ChannelGetData()
« on: 12 Apr '08 - 15:28 »
Hi!

Upgraded my app to BASS 2.4 and I am getting something strange.
With BASS 2.3 I get a sample display like I should:



But with BASS 2.4 I get:



This only happens with mono files. Stereo files seems good.
Did something change between the two versions with BASS_ChannelGetData()?
The code uses:

Code: [Select]
GotData := BASS_ChannelGetData(Channel, @Buffer, BASS_DATA_FFT512 OR BASS_DATA_FFT_INDIVIDUAL);

Full code:

Code: [Select]
procedure TSampleDisplay3D.SampleDataCache(Index: Cardinal; Force: Boolean);
var
  i, k: Integer;
  GotData: Cardinal;
  Offset: Single;
  SDSize: Int64;
  lSample, rSample: Single;
  Channel: DWORD;
  Buffer: array [0..512] of Float;
  SampleAll: Boolean;
  StreamLength: Int64;
  ChanInfo: BASS_CHANNELINFO;
  NeedFree: Boolean;
  // PrevCaption: String;
  Chanz: Integer;
  SampleCount: Int64;
begin
    SampleAll := False;
    NeedFree := True;
    // PrevCaption := FPanelSample.Caption;
    try
        if (Length(Streams.Index[Index].SampleCache) = 0)
        OR Force
        then begin

            if Force
            OR (NOT StreamLoadSESC(Index))
            then

            begin

                SetLength(Streams.Index[Index].SampleCache, 0);

                If Assigned(OnNeedSESC)
                    then OnNeedSESC(Self, Index);

                if Length(Streams.Index[Index].SampleCache) = 0 then begin

                    Channel := 0;

                    if Assigned(OnNeedBASSDecodeChannelHandle)
                        then OnNeedBASSDecodeChannelHandle(Self, Index, Channel);

                    if Channel = 0 then begin
                        Channel := BASS_MusicLoad(FALSE, PChar(Streams.Index[Index].Name), 0, 0, BASS_MUSIC_DECODE OR BASS_MUSIC_STOPBACK OR BASS_MUSIC_CALCLEN , 0);   // BASS_SAMPLE_MONO
                        if Channel = 0
                            then Channel := BASS_StreamCreateFile(False, PChar(Streams.Index[Index].Name), 0, 0, BASS_STREAM_DECODE OR BASS_MP3_SETPOS);
                    end else begin
                        NeedFree := False;
                    end;

                    if Channel = 0
                        then Exit;

                    Chanz := (ChanInfo.chans - 1);
                    StreamLength := BASS_ChannelGetLength(Channel, BASS_POS_BYTE);

                    try
                        if StreamLength > High(Integer)
                            then StreamLength := High(Integer) - 1;
                    except
                        //*
                    end;
                    if StreamLength < 64000 then begin
                        SDSize := StreamLength + 10;
                        SetLength(Streams.Index[Index].SampleCache, SDSize);
                        SampleAll := True;
                    end else begin
                        Offset := (StreamLength / 256);
                        //* Thanx to Eva Freimannova
                        //SetLength(Streams.Index[Index].SampleCache, Trunc(Offset / 2));
                        SampleCount := Trunc(Offset / 2);
                        if odd(SampleCount)
                            then Inc(SampleCount);
                        SetLength(Streams.Index[Index].SampleCache, SampleCount);
                    end;

                    BASS_ChannelGetInfo(Channel, ChanInfo);

                    i := 0;
                    while (BASS_ChannelIsActive(Channel) <> BASS_ACTIVE_STOPPED) do begin

                        GotData := 0;
                        try
                            GotData := BASS_ChannelGetData(Channel, @Buffer, BASS_DATA_FFT512 OR BASS_DATA_FFT_INDIVIDUAL);
                        except
                            // Showmessage('STR_ERROR_EXCEPTION_SamplingSTREAM: ' + FileName);
                        end;

                        if GotData < 1
                            then Break;

                        if NOT SampleAll then begin

                            lSample := Buffer[0];
                            rSample := Buffer[Chanz];

                            k := 0;
                            for k := 1 to (GotData div 16)
                                do lSample := lSample + Buffer[k * 2];
                            k := 0;
                            for k := 1 to (GotData div 16) - 1
                                do rSample := rSample + Buffer[k * 2 + Chanz];

                            lSample := lSample * 16;
                            rSample := rSample * 16;

                            if lSample > 255
                                then lSample := 255;
                            if rSample > 255
                                then rSample := 255;

                            Streams.Index[Index].SampleCache[i] := Trunc(lSample);
                            Inc(i);
                            Streams.Index[Index].SampleCache[i] := Trunc(rSample);

                        end else begin

                            k := 0;
                            for k := 0 to 128 do begin
                                if Buffer[k * 2] > 255
                                    then Buffer[k * 2] := 255;
                                Streams.Index[Index].SampleCache[i * k * 2] := Trunc(Buffer[k * 2] * 100);
                            end;
                            k := 0;
                            for k := 0 to 127 do begin
                                if Buffer[k * 2 + Chanz] > 255
                                    then Buffer[k * 2 + Chanz] := 255;
                                Streams.Index[Index].SampleCache[i * k * 2 + 1] := Trunc(Buffer[k * 2 + 1] * 100);
                            end;

                        end;
                        Inc(i);
                        if i mod 256 = 0 then begin
                            bProgress := Trunc(100 * (BASS_ChannelGetPosition(Channel, BASS_POS_BYTE) / StreamLength));
                            // FPanelSample.Caption := 'Caching... ' + IntToStr(bProgress) + '%';
                            Application.ProcessMessages;
                        end;
                        if (NOT SampleAll)
                        AND (i > High(Streams.Index[Index].SampleCache))
                            then Break;
                        if SampleAll
                        AND (i*k > High(Streams.Index[Index].SampleCache))
                            then Break;
                        if bCancel
                            then Break;
                    end;

                    if NeedFree then begin
                        BASS_MusicFree(Channel);
                        BASS_StreamFree(Channel);
                    end;

                    if NOT SampleAll
                        then SetLength(Streams.Index[Index].SampleCache, i)
                        else SetLength(Streams.Index[Index].SampleCache, i * k);
                end;

                bProgress := 0;
                // FPanelSample.Caption := PrevCaption;
                if bWriteSESC
                AND (NOT Cancel)
                then begin

                    // FPanelSample.Caption := 'Saving ID3v2 SESC...';
                    // Application.ProcessMessages;
                    ID3v2_SetSESC(Index, False);

                end;
            end;
            Streams.Index[Index].GfxZoom_EndPos := Length(Streams.Index[Index].SampleCache);
        end;
        bCancel := False;

    except
        if NOT bSuppressErrors
            then MessageDlg('Error: Exception Sampling Stream: ' + Streams.Index[Index].Name, mtError, [mbOk], 0);

        try
            bProgress := 0;
            if NeedFree then begin
                BASS_MusicFree(Channel);
                BASS_StreamFree(Channel);
            end;
            if NOT SampleAll
                then SetLength(Streams.Index[Index].SampleCache, i)
                else SetLength(Streams.Index[Index].SampleCache, i*k);
        except
            //*
        end;
    end;
end;

Any help would be appreciated.

Thanx!
3delite

Ian @ un4seen

  • Administrator
  • Posts: 20427
Re: BASS 2.4 and BASS_ChannelGetData()
« Reply #1 on: 14 Apr '08 - 15:19 »
This only happens with mono files. Stereo files seems good.
Did something change between the two versions with BASS_ChannelGetData()?

I don't recall any changes that would affect that stuff. The only change I can think of is that the BASS_DATA_FFT flag values changed, to make space for the new BASS_DATA_FFT256 flag.

It looks like your code is expecting to receive stereo data from BASS_ChannelGetData? Note that the BASS_DATA_FFT_INDIVIDUAL flag will only result in stereo data if the channel is stereo.

Btw, when requesting FFT data, a fixed amount of data will be returned (as listed in the BASS_ChannelGetData docs), regardless of how much sample data was read from the channel. So you can pretty much ignore the return value (except to check for an error), ie. you probably shouldn't use "GotData" in your processing of the data.

3delite

  • Posts: 907
Re: BASS 2.4 and BASS_ChannelGetData()
« Reply #2 on: 14 Apr '08 - 17:18 »
This is more than strange then. :)

I didn't modify one line of code (except that adding that new BASS_POS_BYTE flag) you didn't change anything and...
I don't know what to say. I put a little workaround for mono files (simply mirrors the good side), but I think you better note that there may be some bug or something left in still. If it changed from one day to another.

Thanx for the info!
It now works as expected.

3delite