|
shadow2xp
Posts: 20
|
 |
« on: 25 Aug '02 - 10:35 » |
Quote
|
I'm trying to detect the silence at the beginning of a song... Any ideas? 
|
|
|
|
|
Logged
|
|
|
|
|
Ryzer
Posts: 73
|
 |
« Reply #1 on: 25 Aug '02 - 11:31 » |
Quote
|
levelmeters...
|
|
|
|
|
Logged
|
|
|
|
|
shadow2xp
Posts: 20
|
 |
« Reply #2 on: 25 Aug '02 - 17:52 » |
Quote
|
That is brilliant, but wouldn't that only work when the file is playing?
|
|
|
|
|
Logged
|
|
|
|
|
Keyman
Posts: 167
|
 |
« Reply #3 on: 26 Aug '02 - 13:00 » |
Quote
|
That is brilliant, but wouldn't that only work when the file is playing?
Just as briiliant. If it ain't playing you can be pretty sure that it is silent as well...  Somehow I do get the feeling that this isn't the answer you were looking for. What exactly do you want to do? Getlevels & DSP's (In a DSP you can check if all values in the buffer are zero; if so then it's pretty silent) indeed work only when the file is beeing played. Maybe you can overcome this by opening a seperate decoding-only channel to run in the background?! Have Fun Now! Cris
|
|
|
|
|
Logged
|
|
|
|
|
shadow2xp
Posts: 20
|
 |
« Reply #4 on: 27 Aug '02 - 17:32 » |
Quote
|
I want to auto cue in my program. So that would be detecting a silence before a song starts and skipping that silence.
Opening a seperate decoding channel could work.
What exactly does DSP mean and how would i go about setting up a decode only channel?
|
|
|
|
|
Logged
|
|
|
|
|
Keyman
Posts: 167
|
 |
« Reply #5 on: 27 Aug '02 - 18:54 » |
Quote
|
Opening a seperate decoding channel could work.
What exactly does DSP mean and how would i go about setting up a decode only channel?
DSP = Digital Sound (or Signal) Processing. This means that you can process the sound in it's digital representation (bits & bytes). As opposed to Analog Sound Processing. You can create a decode-ony channel with BASS_StreamCreateFile() in conjunction of the BASS_STREAM_DECODE flag. Please refer to the helpfile for more info... Mind that you cannot play a decode-only channel. Maybe an easier alternative is opening the file as you would normally do and set the volume to zero. Then you can play it and use getlevels as well. Have Fun Now! Cris
|
|
|
|
« Last Edit: 27 Aug '02 - 18:56 by keyman »
|
Logged
|
|
|
|
|
Ian @ un4seen
Administrator
Posts: 15269
|
 |
« Reply #6 on: 28 Aug '02 - 12:57 » |
Quote
|
This function will detect the silence at the start of a file stream... DWORD GetSilenceLength(char *file) { BYTE buf[10000]; DWORD count=0; HSTREAM chan=BASS_StreamCreateFile(FALSE,file,0,0,BASS_STREAM_DECODE); // create decoding channel while (BASS_ChannelIsActive(chan)) { int a,b=BASS_ChannelGetData(chan,buf,10000); // decode some data for (a=0;a<b && !buf[a];a++) ; // count silent bytes count+=a; // add number of silent bytes if (a<b) break; // sound has begun! } BASS_StreamFree(chan); return count; } Use it something like this... HSTREAM stream=BASS_StreamCreateFile(FALSE,file,0,0,0); // create stream DWORD silence=GetSilenceLength(file); // get silence BASS_ChannelSetPosition(stream,silence); // seek past it BASS_StreamPlay(stream); // start playing
|
|
|
|
|
Logged
|
|
|
|
|
shadow2xp
Posts: 20
|
 |
« Reply #7 on: 28 Aug '02 - 19:11 » |
Quote
|
sweet  However, I am a VB user and do not know much c++ (learning). I can't convert all of the code you put there. DWORD GetSilenceLength(char *file) { BYTE buf[10000]; DWORD count=0; HSTREAM chan=BASS_StreamCreateFile(FALSE,file,0,0,BASS_STREAM_DECODE); // create decoding channel while (BASS_ChannelIsActive(chan)) { int a,b=BASS_ChannelGetData(chan,buf,10000); // decode some data for (a=0;a<b && !buf[a];a++) ; // count silent bytes count+=a; // add number of silent bytes if (a<b) break; // sound has begun! } BASS_StreamFree(chan); return count; }
|
|
|
|
|
Logged
|
|
|
|
|
(: JOBnik! :)
Posts: 984
|
 |
« Reply #8 on: 28 Aug '02 - 20:18 » |
Quote
|
Hi  That's my quick [not tested] translation: public function GetSilenceLength(byval file as string) as long dim buf(10000) as byte dim count as long dim chan as long
chan=BASS_StreamCreateFile(BASSFALSE,file,0,0,BASS_STREAM_DECODE) ' create decoding channel while (BASS_ChannelIsActive(chan)) dim a as long, b as long b=BASS_ChannelGetData(chan,buf(0),10000) ' decode some data do 'count silent bytes count=count+a 'add number of silent bytes a=a+1 loop while ((a<b) AND (buf(a)=0)) if(a<b) exit while 'sound has begun! wend call BASS_StreamFree(chan) GetSilenceLength =count end function
* Tell me if it doesn't work... Have fun!  JOBnik! 
|
|
|
|
« Last Edit: 28 Aug '02 - 20:21 by JOBnik »
|
Logged
|
|
|
|
|
Keyman
Posts: 167
|
 |
« Reply #9 on: 29 Aug '02 - 03:04 » |
Quote
|
I don't think that's right JobNik, the Count gets increased to much... It now says: count = count+1 ' count = 1 count = count+2 ' count = 3 count = count+3 ' count = 6 etc. With a little change it should work fine: while (BASS_ChannelIsActive(chan)) dim a as long, b as long b=BASS_ChannelGetData(chan,buf(0),10000) ' decode some data a = 0 do while ((a<b) AND (buf(a)=0)) a=a+1 loop count=count+a 'add number of silent bytes if(a<b) exit while 'sound has begun! wend
BTW, I have assumed that buf is zero based... Have Fun Now! Cris
|
|
|
|
|
Logged
|
|
|
|
|
(: JOBnik! :)
Posts: 984
|
 |
« Reply #10 on: 29 Aug '02 - 03:13 » |
Quote
|
Hi  Yep, you're absolutely right  I didn't notice that sign ";" in the end of: for(..) ; (as I said [not tested] quick translation  ) Thanx! Have fun!  JOBnik! 
|
|
|
|
« Last Edit: 30 Aug '02 - 02:10 by JOBnik »
|
Logged
|
|
|
|
|
albertos
Posts: 29
|
 |
« Reply #11 on: 29 Aug '02 - 11:56 » |
Quote
|
A small change and will work....
Public Function GetSilenceLength(ByVal file As String) As Long Dim buf(10000) As Byte Dim count As Long Dim chan As Long
chan = BASS_StreamCreateFile(BASSFALSE, file, 0, 0, BASS_STREAM_DECODE) ' create decoding channel Do While (BASS_ChannelIsActive(chan)) Dim a As Long, b As Long b = BASS_ChannelGetData(chan, buf(0), 10000) ' decode some data a = 0 Do While ((a < b) And (buf(a) = 0)) a = a + 1 Loop count = count + a 'add number of silent bytes If (a < b) Then Exit Do 'sound has begun! Loop Call BASS_StreamFree(chan) GetSilenceLength = count End Function
Ps. i was wondering... if u have a stream that has scratches in the beggining... how to detect the real music start not the first sound to appear... kinda like a sensitivity thing.
|
|
|
|
|
Logged
|
|
|
|
|
MB_SOFT
Posts: 246
|
 |
« Reply #12 on: 29 Aug '02 - 14:01 » |
Quote
|
Yes, how to optimize this function checking for average audio level in a second, instead to detect only the first incoming peak?
I tested this function but is not effective for real usage....it detect the first waveform change...not the real sound....
At the moment it's still better to play the stream at 0 volume and check for ChannelGetLevel.....
Maurizio
|
|
|
|
|
Logged
|
|
|
|
|
albertos
Posts: 29
|
 |
« Reply #13 on: 29 Aug '02 - 15:23 » |
Quote
|
another question also... how to determine silence at the end of stream?
|
|
|
|
|
Logged
|
|
|
|
|
Keyman
Posts: 167
|
 |
« Reply #14 on: 29 Aug '02 - 16:31 » |
Quote
|
At the moment it's still better to play the stream at 0 volume and check for ChannelGetLevel.....
I think that was my whole point some reply's agoo  To determine silence at the end of the stream (you're probably playing it and want to know when it becomes silent) the easiest way would be to check the ChannelGetLevels again. You can create a callback that notifies you say 10 seconds before the end of file. In the callback you start a timer that monitors the output level. To make sure it's ending en not only one dip in the output level you could use something like this (pseudo code) CallBackEvent (10 seconds before EOF) Init DelayCounter to 0 Start TimerX, interval 20 ms or so End of CallBackEvent
TimerX-TimerEvent GetChannelLevels if both LeftLevel & RightLevel < 5 then ' ** increase DelayCounter by 1 if DelayCounter > 10 then ' ** Sound is almost silent... Start another file or so end if else DelayCounter = 0 end if end of TimerXEvent
** You can of course change these values to your needs. With an interval of 20ms & a MaxDelay of 10 it takes MINIMAL 200 ms before you know that it's silent... (silent is defined as levels < 5 in the example) Have Fun Now! Cris ps. Please tell me you VB guys (pure curiousity), doesn't "while-wend" no longer exist in VB or can't you just exit a while-wend loop?
|
|
|
|
« Last Edit: 29 Aug '02 - 16:43 by keyman »
|
Logged
|
|
|
|
|
Ian @ un4seen
Administrator
Posts: 15269
|
 |
« Reply #15 on: 29 Aug '02 - 20:24 » |
Quote
|
Here's an update with a "threshold" setting, and ending silence detection too... void GetSilenceLength(char *file, int threshold, DWORD *start, DWORD *end) { short buf[50000]; DWORD count=0,pos; HSTREAM chan=BASS_StreamCreateFile(FALSE,file,0,0,BASS_STREAM_DECODE); // create decoding channel if (!chan) return;
while (BASS_ChannelIsActive(chan)) { int a,b=BASS_ChannelGetData(chan,buf,20000); // decode some data b/=2; // bytes -> samples for (a=0;a<b && abs(buf[a])<=threshold;a++) ; // count silent samples count+=a*2; // add number of silent bytes if (a<b) { // sound has begun! // move back to a quieter sample (to avoid "click") for (;a && abs(buf[a])>threshold/4;a--,count-=2) ; break; } } *start=count;
pos=BASS_StreamGetLength(chan); while (pos>count) { int a,b; pos=pos<100000?0:pos-100000; // step back a bit BASS_ChannelSetPosition(chan,pos); b=BASS_ChannelGetData(chan,buf,100000); // decode some data b/=2; // bytes -> samples for (a=b;a>0 && abs(buf[a-1])<=threshold/2;a--) ; // count silent samples if (a>0) { // sound has begun! count=pos+a*2; // silence begins here break; } } *end=count;
BASS_StreamFree(chan); } Example... DWORD start,end; GetSilenceLength(file,500,&start,&end); The positions could be QWORDs (for massive stream support  ), but I've used DWORD for the benefit of VB users. The ending silence detection will not be exact for MP3 files without using the BASS_MP3_SETPOS flag when creating the decoding channel, but that's obviously slower too.
|
|
|
|
|
Logged
|
|
|
|
|
shadow2xp
Posts: 20
|
 |
« Reply #16 on: 29 Aug '02 - 23:02 » |
Quote
|
Thank you all...
Oh and yes VB still has the "while-wend" loop.
|
|
|
|
|
Logged
|
|
|
|
|
Keyman
Posts: 167
|
 |
« Reply #17 on: 30 Aug '02 - 00:33 » |
Quote
|
Very cool solution Ian !!  Cris
|
|
|
|
|
Logged
|
|
|
|
|
albertos
Posts: 29
|
 |
« Reply #18 on: 30 Aug '02 - 01:20 » |
Quote
|
@Shadow2xp:
yes vb still has while-wend loop structure... but u can't break the loop. Only for-next and do while-loop can exit loop with exit for and exit do commands... that's what i know so far...
|
|
|
|
|
Logged
|
|
|
|
|
shadow2xp
Posts: 20
|
 |
« Reply #19 on: 30 Aug '02 - 04:19 » |
Quote
|
A "while-wend" loop can be broken with "Do Events".
Also can I get that code above translated into VB?
|
|
|
|
« Last Edit: 30 Aug '02 - 04:20 by shadow2xp »
|
Logged
|
|
|
|
|