Author Topic: Detect silence?  (Read 19783 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: 15
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: 21529
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: 147
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 »

GertK

  • Guest
Re: Detect silence?
« Reply #32 on: 16 Feb '19 - 14:25 »
I Tried the codes above (C converted to VB.net) but none of them seems to work
I must not have the begin or end silence, but silence in the mp3-file (news-file and place a 'ping' where  silence is 1 sec.
so I only used a part of the code > Set Position +10) to were previous silence was detected. Only thing... It does not find the long silences.

       

        chan = Bass.BASS_StreamCreateFile(FILE, 0, 0, BASSFlag.BASS_STREAM_DECODE Or BASSFlag.BASS_STREAM_PRESCAN)
        Bass.BASS_ChannelSetPosition(chan, POSITION + 10)

        If (chan = 0) Then Exit Sub
        While Bass.BASS_ChannelIsActive(chan)
            B = Bass.BASS_ChannelGetData(chan, buf, 20000)
            ' decode some data
            B /= 2
            ' bytes -> samples
            a = 0
            While a < B AndAlso Math.Abs(buf(a)) > THRESHOLD
                a += 1
            End While
            ' count silent samples
            count += a * 2
            ' add number of silent bytes
        End While

        START = count
        POSITION = POSITION + count
        Exit Sub