Author Topic: Detect silence?  (Read 18203 times)

shadow2xp

  • Posts: 20
Re: Detect silence?
« Reply #25 on: 2 Sep '02 - 15:43 »
k..... :-/

big_gun

  • Posts: 352
Re: Detect silence?
« Reply #26 on: 18 Sep '02 - 20:56 »
You can exit a while/wend loop with exit while.

Here is code that works just fine for me.

It assumes you've opened the file and the stream id is stored in the variable mvarStreamID. IsCueing  is also a public variable. It returns a value into the mvarAudioCueInitial variable. If it is a CD Track, it returns 0.


Public Sub AudioCue()
   Dim lLev As Long
   Dim rLev As Long
   Dim aLev As Long
       
   IsCueing = True
   
   If mvarStreamID = CDCHANNEL Then
       mvarAudioCueInitial = 0
       IsCueing = False
       Exit Sub
   End If
   If mvarAudioCueInitial = 0 Then
       Call BASS_ChannelStop(mvarStreamID)
       Call BASS_ChannelSetAttributes(mvarStreamID, -1, 0, -101)
       Call BASS_StreamPlay(mvarStreamID, BASSTRUE, 0)
       
       Do While aLev < 3
           lLev = GetLoWord(BASS_ChannelGetLevel(mvarStreamID))
           rLev = GetHiWord(BASS_ChannelGetLevel(mvarStreamID))
           If lLev > rLev Then
               aLev = lLev
           Else
               aLev = rLev
           End If
           DoEvents
       Loop
       Call BASS_ChannelPause(mvarStreamID)
       mvarAudioCueInitial = BASS_ChannelBytes2Seconds(mvarStreamID, BASS_ChannelGetPosition(mvarStreamID)) - 0.2
       If mvarAudioCueInitial < 0 Then mvarAudioCueInitial = 0
       mvarAudioCueInitial = CSng(CInt(mvarAudioCueInitial))
       Call BASS_ChannelSetPosition(mvarStreamID, BASS_ChannelSeconds2Bytes(mvarStreamID, mvarAudioCueInitial))
   Else
       Call BASS_ChannelPause(mvarStreamID)
       Call BASS_ChannelSetPosition(mvarStreamID, BASS_ChannelSeconds2Bytes(mvarStreamID, mvarAudioCueInitial))
   End If
   Call BASS_StreamPreBuf(mvarStreamID)
   IsCueing = False
End Sub

CvMaRTY

  • Posts: 13
Re: Detect silence?
« Reply #27 on: 24 May '11 - 01:18 »
Just to post a few corrections to an older post:
Probably because since it was posted, there must have been changes in the Bass syntax.

a small correction somewhere and it work...

Code: [Select]
Public Sub GetSilenceLength(ByVal file As String, ByVal threshold As Long, ByRef startp As Long, ByRef endp As Long)
    Dim buf(50000) As Integer
    Dim count As Long, pos As Long
    Dim chan As Long
    Dim a As Long, b As Long
    Dim c As Long, d As Long
    count = 0

    ' this method was called without StrPtr() so vb reports a type mismatch
    chan = BASS_StreamCreateFile(BASSFALSE, StrPtr(file), 0, 0, BASS_STREAM_DECODE) 'create decoding channel


    If (chan = 0) Then Exit Sub

    Do
          b = BASS_ChannelGetData(chan, buf(0), 20000) 'decode some data
          b = b / 2 'bytes -> samples
          a = 0
          Do      'count silent samples
                a = a + 1
          Loop While ((a < b) And (Abs(buf(a)) <= threshold))
          count = count + (a * 2)
          If (a < b) Then 'sound has bagun
                'move back to a quieter sample (to avoid "click")
                Do
                      a = a - 1
                      count = count - 2
                Loop While ((a) And (Abs(buf(a)) > threshold / 4))
                Exit Do
          End If
    Loop While (BASS_ChannelIsActive(chan))

    startp = count

    'pos = BASS_StreamGetLength(chan)  << method does not exist anymore
    pos = BASS_ChannelGetLength(chan, BASS_POS_BYTE)
    
    Do
          pos = IIf(pos < 100000, 0, pos - 100000) 'step back a bit
          BASS_ChannelSetPosition chan, pos
          d = BASS_ChannelGetData(chan, buf(0), 100000) ' decode some data
          d = d / 2 'bytes -> samples
          c = d
          Do
                c = c - 1  'count silent samples
          Loop While (c > 0) And (Abs(buf(c)) <= threshold / 2) 'Here is the correction
          If (c > 0) Then   'sound has begun
                count = pos + c * 2
                Exit Do
          End If
    Loop While (pos > count)
    endp = count
    BASS_StreamFree (chan)
End Sub


I also urge anyone to add BASS_STREAM_PRESCAN to BASS_STREAM_DECODE because if you fall on a vbr file that reports less length than the actual time, this part of the code will raise an error:

Code: [Select]
Loop While (c > 0) And (Abs(buf(c)) <= threshold / 2)
Anyway, GREAT code!! :)) I have a small question though, as I am a little bit stupid with mathematics, what are the threshold values representing? I dont exactly know how to convert Db to this threshold number.

vpnmaster

  • Posts: 2
Re: Detect silence?
« Reply #28 on: 24 May '11 - 22:45 »
Mmm Jazler with bass! Perfect!

Ian @ un4seen

  • Administrator
  • Posts: 20389
Re: Detect silence?
« Reply #29 on: 25 May '11 - 16:26 »
I have a small question though, as I am a little bit stupid with mathematics, what are the threshold values representing? I dont exactly know how to convert Db to this threshold number.

The "threshold" is the minimum sample level to be considered as the end of any silence at the start of the file. Note the threshold is halved for the silence detection at the end of the file, but a separate threshold level could be used if wanted.

You can use a dB threshold like this...

Code: [Select]
threshold = pow10(dB/20) * 32768;

That's assuming that "threshold" ranges from 0 to 32768, for comparison with 16-bit sample data.

BaseHead

  • Posts: 136
Re: Detect silence?
« Reply #30 on: 2 Jun '11 - 02:48 »
My coder Vic converted Ian's code to C# for me to use.
thought I'd contribute also for all the C# guys out there.........8)



 /// <summary>
        /// Get file silence length
        /// </summary>
        /// <param name="file">file name</param>
        /// <param name="threshold">threshold</param>
        /// <returns>Point(-1, -1) on error or Point(start, end) </returns>
        System.Windows.Point GetSilenceLength(string file, int threshold)
        {
            short[] buf = new short[50000];
            long count = 0;
            int chan = 0;
            long pos = 0;

            System.Windows.Point rc = new System.Windows.Point(-1, -1);
            try
            {
                chan = Bass.BASS_StreamCreateFile(file, 0, 0, BASSFlag.BASS_STREAM_DECODE);
                if (chan == 0)
                {
                    Utils.LogWrite(LogEventType.Error, string.Format("GetSilenceLength: Couldn't create BASS stream (error = %{0})", Bass.BASS_ErrorGetCode()));
                    return rc;
                }

                while (Bass.BASS_ChannelIsActive(chan) != BASSActive.BASS_ACTIVE_STOPPED)
                {
                    int a;
                    int b = Bass.BASS_ChannelGetData(chan, buf, 20000); // decode some data
                    b /= 2; // bytes -> samples
                    for (a = 0; a < b && Math.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 != 0) && Math.Abs(buf[a]) > threshold / 4; a--,count-=2) ;
                        break;
                    }
                }
                rc.X = count;

                pos = Bass.BASS_StreamGetFilePosition(chan, BASSStreamFilePosition.BASS_FILEPOS_END);
                while (pos > count)
                {
                    int a, b;
                    pos = (pos < 100000)? 0: pos - 100000; // step back a bit
                    Bass.BASS_ChannelSetPosition(chan,pos);
                    b = Bass.BASS_ChannelGetData(chan,buf,100000); // decode some data
                    b /= 2; // bytes -> samples

                    for (a = b; a > 0 && Math.Abs(buf[a - 1]) <= threshold / 2; a--)
                        ; // count silent samples

                    if (a > 0)
                    {
                        // sound has begun!
                        count = pos + a * 2; // silence begins here
                        break;
                    }
                }
                rc.Y = count;

            }
            catch (Exception ex)
            {
                Utils.LogWrite(LogEventType.Error, "GetSilenceLength:" + ex.Message);
            }
            finally
            {
                if (chan != 0)
                    Bass.BASS_StreamFree(chan);
            }

            return rc;
            
        }
« Last Edit: 21 Nov '11 - 02:00 by BaseHead »

Erazer

  • Posts: 441
Re: Detect silence?
« Reply #31 on: 31 Oct '17 - 16:04 »
I didn't thought "threshold" has such big  importance.
« Last Edit: 31 Oct '17 - 21:15 by Erazer »