23 May '13 - 07:59 *
Welcome, Guest. Please login or register.
Did you miss your activation email?

Login with username, password and session length
 
   Home   Help Search Login Register  
Pages: [1] 2  All
  Reply  |  Print  
Author Topic: Detect silence?  (Read 11629 times)
shadow2xp
Posts: 20


« on: 25 Aug '02 - 10:35 »
Reply with quoteQuote

I'm trying to detect the silence at the beginning of a song... Any ideas? Huh
Logged
Ryzer
Posts: 73


« Reply #1 on: 25 Aug '02 - 11:31 »
Reply with quoteQuote

levelmeters...
Logged
shadow2xp
Posts: 20


« Reply #2 on: 25 Aug '02 - 17:52 »
Reply with quoteQuote

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 »
Reply with quoteQuote


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...  Grin
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 »
Reply with quoteQuote

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 »
Reply with quoteQuote

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 »
Reply with quoteQuote

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 »
Reply with quoteQuote

sweet Cheesy

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 »
Reply with quoteQuote

Hi Grin

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!

Cool JOBnik! Cool
« Last Edit: 28 Aug '02 - 20:21 by JOBnik » Logged
Keyman
Posts: 167


« Reply #9 on: 29 Aug '02 - 03:04 »
Reply with quoteQuote

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 »
Reply with quoteQuote

Hi Grin

Yep, you're absolutely right Smiley
I didn't notice that sign ";" in the end of: for(..) ;
(as I said [not tested] quick translation Smiley)

Thanx!

Have fun!

Cool JOBnik! Cool
« Last Edit: 30 Aug '02 - 02:10 by JOBnik » Logged
albertos
Posts: 29


« Reply #11 on: 29 Aug '02 - 11:56 »
Reply with quoteQuote

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 »
Reply with quoteQuote

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 »
Reply with quoteQuote

another question also...
how to determine silence at the end of stream?
Logged
Keyman
Posts: 167


« Reply #14 on: 29 Aug '02 - 16:31 »
Reply with quoteQuote

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  Tongue

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 »
Reply with quoteQuote

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 Smiley), 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 »
Reply with quoteQuote

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 »
Reply with quoteQuote

Very cool solution Ian !!   Smiley

Cris
Logged
albertos
Posts: 29


« Reply #18 on: 30 Aug '02 - 01:20 »
Reply with quoteQuote

@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 »
Reply with quoteQuote

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
Pages: [1] 2  All
  Reply  |  Print  
 
Jump to:  

Powered by SMF 1.1.18 | SMF © 2013, Simple Machines