Author Topic: Bass_ChannelStop() broken?  (Read 4135 times)

3delite

  • Posts: 904
Bass_ChannelStop() broken?
« on: 10 Apr '06 - 15:34 »
Hi!

Recently I am experiencing jerkiness in sound when crossfading between streams. I traced the problem to Bass_ChannelStop().
Here's the code:

Code: [Select]
{$IFDEF _DEBUG}
    QueryPerformanceFrequency(PerfFreq);
    QueryPerformanceCounter(FreqCountS);
    Log('SyncEnd: ' + IntToStr(OccSync), True);
{$ENDIF}
{$IFDEF _DEBUG}
    QueryPerformanceCounter(FreqCountE);
    Log('CallbackStreamEnd()1 took: ' + IntToStr(Round((FreqCountE - FreqCountS) / PerfFreq * 1000)) + ' ms', True);
{$ENDIF}
    Index := FindStreamByChannel(Channel);
    //*  if CallbackCrossFade didn't advance or MOD
{$IFDEF _DEBUG}
    QueryPerformanceCounter(FreqCountE);
    Log('CallbackStreamEnd()2 took: ' + IntToStr(Round((FreqCountE - FreqCountS) / PerfFreq * 1000)) + ' ms', True);
{$ENDIF}
    Bass_ChannelStop(Channel);
    //* ASIO unplug channel
{$IFDEF _DEBUG}
    QueryPerformanceCounter(FreqCountE);
    Log('CallbackStreamEnd()3 took: ' + IntToStr(Round((FreqCountE - FreqCountS) / PerfFreq * 1000)) + ' ms', True);
{$ENDIF}
    if SettingsWindow.RadioButtonASIO.Checked
        then BASS_Mixer_ChannelRemove(Channel);
    Streams.Index[Index].Playing := plStoped;
{$IFDEF _DEBUG}
    QueryPerformanceCounter(FreqCountE);
    Log('CallbackStreamEnd()4 took: ' + IntToStr(Round((FreqCountE - FreqCountS) / PerfFreq * 1000)) + ' ms', True);
{$ENDIF}

And the Log says:

Quote
16:27:06 CallbackStreamEnd()1 took: 3 ms
16:27:06 CallbackStreamEnd()2 took: 5 ms
16:27:07 CallbackStreamEnd()3 took: 917 ms
16:27:07 CallbackStreamEnd()4 took: 920 ms

It seems like sometimes (it looks like not always) Bass_ChannelStop() takes nearly a whole second to accomplish. I think this has been introduced in a recent update, please check!
Just tell me if you need more info! :)

3delite

  • Posts: 904
Re: Bass_ChannelStop() broken?
« Reply #1 on: 10 Apr '06 - 16:20 »
Oh I see! I found it under DSPPROC: "I shouldn't call Bass_ChannelStop() in a callback..." ::)
Still got the problem tough... tracing... :)

3delite

  • Posts: 904
Re: Bass_ChannelStop() broken?
« Reply #2 on: 10 Apr '06 - 16:31 »
Now it's Bass_ChannelSetPosition() ::)

Code: [Select]
{$IFDEF _DEBUG}
    QueryPerformanceCounter(FreqCountE);
    Log('CallbackStreamEnd()1 took: ' + IntToStr(Round((FreqCountE - FreqCountS) / PerfFreq * 1000)) + ' ms', True);
{$ENDIF}
            Bass_ChannelSetPosition(Channel, 0);
{$IFDEF _DEBUG}
    QueryPerformanceCounter(FreqCountE);
    Log('CallbackStreamEnd()2 took: ' + IntToStr(Round((FreqCountE - FreqCountS) / PerfFreq * 1000)) + ' ms', True);
{$ENDIF}
            if (MainForm.ListViewSL.Items.Count = 1) then begin
                if (NOT MainForm.CheckBoxLoop.Checked)
                    then CallbackFreeStream := Streams.Index[Index].Name;
            end else CallbackFreeStream := Streams.Index[Index].Name;
        end else begin
            Bass_ChannelSetPosition(Channel, 0);
            if (Streams.Index[Index].sType = 'URL')
                then MainForm.URLStreamFree(Index);
        end;
    end;
    MainForm.SetItem(StreamsFindItem(Streams.Index[Index].Name), False);
{$IFDEF _DEBUG}
    QueryPerformanceCounter(FreqCountE);
    Log('CallbackStreamEnd() finished, took: ' + IntToStr(Round((FreqCountE - FreqCountS) / PerfFreq * 1000)) + ' ms', True);
{$ENDIF}

Log:

Quote
17:29:56 CallbackStreamEnd()1 took: 3 ms
17:29:56 CallbackStreamEnd()2 took: 929 ms
17:29:56 CallbackStreamEnd() finished, took: 959 ms

Ian @ un4seen

  • Administrator
  • Posts: 20425
Re: Bass_ChannelStop() broken?
« Reply #3 on: 10 Apr '06 - 17:13 »
Is it happening with a particular file or format? If so, please upload an example file to have a look at...

   ftp.un4seen.com/incoming/

Btw, I presume that code is in a SYNCPROC for a mix-time END sync? Have you tried reproducing the problem with the precompiled CUSTLOOP example? If you don't set loop points, it does the same thing (BASS_ChannelSetPosition(0) at the end). If there's a 900ms delay, the end sound should repeat when it loops (due to buffer underrun).

3delite

  • Posts: 904
Re: Bass_ChannelStop() broken?
« Reply #4 on: 10 Apr '06 - 17:42 »
I took out all those functions from the callback, now in most cases it's good

Quote
17:49:04 CallbackStreamEnd() finished, took: 40 ms
17:54:03 CallbackStreamEnd() finished, took: 8 ms
17:57:39 CallbackStreamEnd() finished, took: 7 ms

but still got sometimes jumps, after advancing to the next stream. Don't know why. It must be something I spoiled in an update or sliped in in one of the BASS updates.
This is my last bug in MP3SE (the last one that I want to fix), so it'll surely be some time to fix it... :)
I look into what you suggested... I don't think the 1 sec execution time is file specific, it happens with every MP3 file I tested.
I'll report what I have found out tomorrow...

3delite

  • Posts: 904
Re: Bass_ChannelStop() broken?
« Reply #5 on: 10 Apr '06 - 19:32 »
First of all, I was using version 2.2.0.2 now I changed to 2.2.0.4 (and hoping it will fix it, as I recall there was a topic on BASS_StreamFree() taking too much time? or something) but I've got the same problem still.

The custloop example seems fine, you'll understand why, just read ahead...

The sync could be either:

Code: [Select]
    SyncEnd := BASS_ChannelSetSync(Channel, BASS_SYNC_ONETIME OR BASS_SYNC_SLIDE, BASS_SLIDE_VOL, @CallbackStreamEnd, 0);
    SyncEnd := BASS_ChannelSetSync(Channel, BASS_SYNC_END, 0, @CallbackStreamEnd, 0);

I tried and switched all my timers off (in case some timer interfered), without success.

If I take out the BASS_ChannelStop() and BASS_ChannelSetPosition() from the callback the callback is ok. But! In this case the other BASS_ChannelStop() is delaying (my StreamStop(), I found out):

Code: [Select]
{$IFDEF _DEBUG}
    QueryPerformanceFrequency(PerfFreq);
    QueryPerformanceCounter(FreqCountS);
    Log('StreamStop(): ' + IntToStr(Index), True);
{$ENDIF}
    if Assigned(Streams.Index) then begin
        BASS_ChannelStop(Streams.Index[Index].Channel);
{$IFDEF _DEBUG}
    QueryPerformanceCounter(FreqCountE);
    Log('StreamStop()1 took: ' + IntToStr(Round((FreqCountE - FreqCountS) / PerfFreq * 1000)) + ' ms', True);
{$ENDIF}
        BASS_ChannelSetPosition(Streams.Index[Index].Channel, 0);
{$IFDEF _DEBUG}
    QueryPerformanceCounter(FreqCountE);
    Log('StreamStop()2 took: ' + IntToStr(Round((FreqCountE - FreqCountS) / PerfFreq * 1000)) + ' ms', True);
{$ENDIF}

Quote
20:15:49 StreamStop(): 1
20:15:49 StreamStop()1 took: 536 ms
20:15:49 StreamStop()2 took: 540 ms

So it looks like it is BASS_ChannelStop()'s fault, regardless I was calling it from a callback. It looks to me like BASS is doing some processing in some cases (maybe the same processing is needed for BASS_ChannelSetPosition() that was why it delays too sometimes)?
Hope I could help!
Uploaded a file to test: Afterlife - DubInYaMind(BeachClubMix).mp3

EDIT: I was still curious and put a button on the custloop example with a simple BASS_ChannelStop() and measuring it, says: 0ms ;D
I am really excited now what the problem will be! :)
Oh! Maybe this is my opportunity to put my hand on one of those debug versions of BASS.dll!!! Yippiiiii!!! :D

So Ian, where do you want the bug today? ;D
« Last Edit: 10 Apr '06 - 23:23 by 3delite »

3delite

  • Posts: 904
Re: Bass_ChannelStop() broken?
« Reply #6 on: 11 Apr '06 - 22:13 »
I think this will be a threading problem... :'(

3delite

  • Posts: 904
Re: Bass_ChannelStop() broken?
« Reply #7 on: 18 Apr '06 - 20:34 »
For those who were following the topic:

In the end it looks like there is a problem with the Windows's MP3 decoder.
The case was the following: I switched to using basswma's:

Code: [Select]
    BASS_WMA_StreamCreateFile()

for MP3 files too, with the

Code: [Select]
    BASS_SetConfig(BASS_CONFIG_WMA_PRECHECK, 0);

config option recently. With some files the decoding is problematic, and can cause jerks in playback and for some BASS functions to execute in 500-1000ms. :(
This is not a usual problem, only happens with some of the MP3 files...