Author Topic: Small pops when looping  (Read 5992 times)

Tiamat

  • Guest
Small pops when looping
« on: 20 Mar '03 - 06:04 »
I am working with some friends on a C++ program, and we are having a very frustrating problem.  We are using Bass to play audio, and it works great.  However, there is one spot where it is coming up short: looping to a point.  We are taking msuic, waiting until we reach the end of the stream, and then looping back to a specified point in the song to make an "infinite loop after a certain introduction spot" more or less.  For example, say we have a song that is 10000 milliseconds long (10 seconds).  After playing through once, we want it to loop back to 4000 milliseconds after the start, then continue until it hits the end, then loop back, and so on.

However, every time Bass goes back to the loop point, we get an audible pop.  We have tried many different formats and techniques to deal with this problem; our most revealing test involves loading an uncompressed WAV into a resource.  This is a pure sine wave, so there are never any breaks or pops.  Now, we start playing it as a stream, and as soon as it hits the end there is a very short, but very noticable, click/pop before it goes back to the loop point.  But it's a pure sine wave... it shouldn't do that!

I was wondering if this issue has ever come up here, and if so if there is a known workaround.  Either that, or if there is someone who uses Bass with C++ and can get such described looping to work just fine and can help us with this problem that would be great.

kode54

  • Posts: 124
Re: Small pops when looping
« Reply #1 on: 20 Mar '03 - 06:20 »
Have you verified your loop points in a sound editor, such as Sound Forge?

Tiamat

  • Guest
Re: Small pops when looping
« Reply #2 on: 20 Mar '03 - 06:21 »
Yes, the loop points do not cause any clicks or pops.  Plus, looping an uncompressed, pure sinusoidal .wav file (just about as perfect a sound as you can get) shouldn't produce any clicks anyway...

bigjim

  • Posts: 232
Re: Small pops when looping
« Reply #3 on: 20 Mar '03 - 08:35 »
How are you detecting the end of the stream?
and are you initializing the stream with accurate positioning using the flags?

Wouter Alink

  • Guest
Re: Small pops when looping
« Reply #4 on: 20 Mar '03 - 08:38 »
the end point sample (probably a 0) has to match the point where-you-want-to-loop-to sample, so it should also be zero.
If these samples are not equal you would hear a plop, because of the sudden change in level. Maybe you should add a few samples to gradually change to the other level to avoid the 'plop'ing or you could search for a nearby 'zero-crossing'-point.

Ian @ un4seen

  • Administrator
  • Posts: 26140
Re: Small pops when looping
« Reply #5 on: 20 Mar '03 - 13:50 »
The problem is due to a tiny delay between the end position being heard and your sync being called, and then a little more delay while your sync changes the position. The sync latency is generally a fraction of a millisecond, which is perfectly good for syncing visuals, but is plenty enough to hear it in what you're trying to do.

The solution is to use a decoding channel and custom stream. That way you have full control over what's played. For example...

Code: [Select]

HSTREAM stream2loop; // the decoding channel
HSTREAM stream2play; // the custom stream
QWORD loopstart;

DWORD CALLBACK StreamProc(HSTREAM handle, BYTE *buffer, DWORD length, DWORD user)
{
     int count=length;
     while (count) {
           int r=BASS_ChannelGetData(stream2loop,buffer,count);
           if (r==-1) // it's ended, go to start of loop
                 BASS_ChannelSetPosition(stream2loop,loopstart);
           else {
                 buffer+=r;
                 count-=r;
           }
     }
     return length;
}

...

// create the decoding channel
stream2loop=BASS_StreamCreateFile(FALSE,"a_file",0,0,BASS_STREAM_DECODE);

// create a custom stream with the same sample format
DWORD flags,freq;
BASS_ChannelGetAttributes(stream2loop,&freq,NULL,NULL);
flags=BASS_ChannelGetFlags(stream2loop)&~BASS_STREAM_DECODE;
stream2play=BASS_StreamCreate(freq,flags,(STREAMPROC*)&StreamProc,0);

loopstart=some_place_to_start_looping;
BASS_StreamPlay(stream2play,0,0);

Tiamat

  • Guest
Re: Small pops when looping
« Reply #6 on: 20 Mar '03 - 14:21 »
We wrote an audio class that takes care of all this, but here are some code snippets that essentially are all the looping function is about:

BASS_StreamCreateFile(sizeOf, source, 0, sizeOf, BASS_MP3_SETPOS | BASS_SAMPLE_FLOAT);

(sizeOf and source are used to create a stream from a file or a resource; at the moment, we're testing with a resource)

BASS_ChannelSetSync(_hstr_music, BASS_SYNC_END, 0, &musLoopSyncProc, loopPosMillisec);

We're synching to the end of the stream, then moving to loopPosMillisec.  Here is the musLoopSyncProc callback function:

void CALLBACK musLoopSyncProc(HSYNC handle, DWORD channel, DWORD data, DWORD user)

{
     BASS_ChannelSetPosition(channel, BASS_ChannelSeconds2Bytes(channel, (float)user/1000.0f));
     BASS_StreamPreBuf(channel);
}

user is the loop position in milliseconds.  Is there something wrong with this code?

Also, if the problem is in the audio file, how would I go about setting the exact sample location to play from (as in, start from sample #45477 or something)?

Tiamat

  • Guest
Re: Small pops when looping
« Reply #7 on: 20 Mar '03 - 14:22 »
Whoops... I posted the above message after Ian's message... let me try what you suggested.  Thanks!

Tiamat

  • Guest
Re: Small pops when looping
« Reply #8 on: 20 Mar '03 - 15:05 »
The line

flags=BASS_ChannelGetFlags(stream2loop)&~BASS_STREAM_DECODE;

is giving me problems.  When I run the program (after copy-pasting the code you gave me and putting the snippets in the right spots), I get an unhandled exception error on that line.  Any ideas?

Tiamat

  • Guest
Re: Small pops when looping
« Reply #9 on: 20 Mar '03 - 15:14 »
Er, sorry... that last one was my fault.  Now I'm getting an error on this line:

int r=BASS_ChannelGetData(stream2loop,buffer,count);

Again, I'm getting an "unhandled exception".  Any ideas why this might be happening?

Tiamat

  • Guest
Re: Small pops when looping
« Reply #10 on: 20 Mar '03 - 15:53 »
Okay, last post, I promise.  ;)

Thanks for the code... we finally got it to work!  The pops still come up when loading the sound from a file, but when loading from memory there's no problm.  Thanks a lot for your help everyone, and I'm sorry for filling up this board so much!