Author Topic: Intro silence detection  (Read 394 times)

smoodilo

  • Posts: 4
Intro silence detection
« on: 26 Feb '24 - 20:35 »
I found this c# code in this forum for detecting the silence at the beginning of a track. I tried converting the code to vb.net and ended up with the following code, but somehow this always just returns 0. Anyone have a clue as to what I am missing?:

 Public Function IntroSilence(BassStream As Integer) As Integer
     Dim buffer As Single() = New Single(49999) {}
     Dim count As Long = 0
     Const threshold As Single = 0.25F
     Dim Silence As Integer = 0.0

     Dim length = Bass.BASS_ChannelGetLength(BassStream)

     Try
         'detect start silence
         Dim b As Integer
         Do
             'decode some data
             b = Bass.BASS_ChannelGetData(BassStream, buffer, 40000)
             If b <= 0 Then Exit Do
             'bytes -> samples
             b \= 4
             'count silent samples
             Dim a As Integer
             For a = 0 To b - 1
                 If Math.Abs(buffer(a)) <= threshold Then Exit For
             Next
             'add number of silent bytes
             count += a * 4
             'if sound has begun...
             If a < b Then
                 'move back to a quieter sample (to avoid "click")
                 For a = a To threshold / 4 Step -1
                     If Math.Abs(buffer(a)) > threshold / 4 Then Exit For
                     count -= 4
                 Next
                 Exit Do
             End If
         Loop While b > 0
         Silence = Bass.BASS_ChannelBytes2Seconds(BassStream, count)

     Catch ex As Exception
         Silence = 0.0
     End Try

     Return Silence

 End Function

MB_SOFT

  • Posts: 496
Re: Intro silence detection
« Reply #1 on: 26 Feb '24 - 22:28 »
you should show how you create the BassStream before to call Function IntroSilence

smoodilo

  • Posts: 4
Re: Intro silence detection
« Reply #2 on: 26 Feb '24 - 23:04 »
Here you go:

STREAM_MAIN1 = Bass.BASS_StreamCreateURL("https://xxxxxxx", 0, BASSFlag.BASS_STREAM_DECODE Or BASSFlag.BASS_SAMPLE_FLOAT, DownProc, IntPtr.Zero)

MB_SOFT

  • Posts: 496
Re: Intro silence detection
« Reply #3 on: 26 Feb '24 - 23:23 »
i guess the IntroSilence function you found is intended for local files not for internet streams

smoodilo

  • Posts: 4
Re: Intro silence detection
« Reply #4 on: 27 Feb '24 - 07:59 »
I see,

But the function also doesn't seem to do anything for local files:

STREAM_MAIN1 = Bass.BASS_StreamCreateFile(SongPath, 0, 0, BASSFlag.BASS_STREAM_DECODE Or BASSFlag.BASS_SAMPLE_FLOAT)

Ian @ un4seen

  • Administrator
  • Posts: 26083
Re: Intro silence detection
« Reply #5 on: 27 Feb '24 - 17:23 »
...
                 If Math.Abs(buffer(a)) <= threshold Then Exit For
...

I'm not a VB.Net user myself, but this comparison seems the wrong way round, ie. you want to exit the loop when above the threshold, not below it. The same goes for the later "If...Exit For" line too.

smoodilo

  • Posts: 4
Re: Intro silence detection
« Reply #6 on: 2 Mar '24 - 12:06 »
You were right about that Ian. Changing it made it work. Now I am pulling my hairs out to get the 'end silece' detection workiing. It somehow alway returns 0. If anybody could have a look it would be greatly appreciated. Also I don't know what a feasible value for Cueout should be:

Code: [Select]
Private Function GetQueuePointsFromFile(myfile As String) As Tuple(Of Long, Long)
    Dim bassstream As Integer = Bass.BASS_StreamCreateFile(myfile, 0, 0, BASSFlag.BASS_STREAM_DECODE Or BASSFlag.BASS_SAMPLE_FLOAT)

    If bassstream <> 0 Then
        Dim buffer As Single() = New Single(49999) {}
        Dim cueIn As Long = 0L
        Dim cueOut As Long = 0L
        Dim bufferSize As Integer = 4096
        Const InThreshold As Single = 0.005F
        Const OutThreshold As Double = 0.005F

        Try
            ' Detect start silence
            Dim bytesRead As Integer
            Do
                bytesRead = Bass.BASS_ChannelGetData(bassstream, buffer, bufferSize)
                If bytesRead <= 0 Then Exit Do

                Dim silentSamples As Integer = 0
                For i As Integer = 0 To bytesRead - 1 Step 4
                    If Math.Abs(buffer(i)) < InThreshold Then
                        silentSamples += 1
                    Else
                        Exit Do
                    End If
                Next

                cueIn += silentSamples * 4
            Loop While bytesRead > 0

            ' Detect trailing silence
            Dim lengthInBytes As Long = Bass.BASS_ChannelGetLength(bassstream, BASSMode.BASS_POS_BYTES)
            Dim position As Long = lengthInBytes - bufferSize

            Dim trailingSilenceStart As Long = 0

            While position >= 0
                Bass.BASS_ChannelSetPosition(bassstream, position, BASSMode.BASS_POS_BYTES)

                bytesRead = Bass.BASS_ChannelGetData(bassstream, buffer, bufferSize)
                If bytesRead <= 0 Then
                    Console.WriteLine("Failed to read bytes from the stream")
                    Exit While
                End If

                Dim hasAudio As Boolean = False
                For i As Integer = 0 To bytesRead - 1
                    If Math.Abs(buffer(i)) > OutThreshold Then
                        hasAudio = True
                        Exit For
                    End If
                Next

                If hasAudio Then
                    trailingSilenceStart = position
                    Exit While
                End If

                position -= bufferSize
            End While

            cueOut = trailingSilenceStart

            Console.WriteLine("leading: " & Bass.BASS_ChannelBytes2Seconds(bassstream, cueIn))
            Console.WriteLine("trailing: " & Bass.BASS_ChannelBytes2Seconds(bassstream, cueOut))

        Catch ex As Exception
            Console.WriteLine("Error: " & ex.ToString())
        End Try

        Bass.BASS_StreamFree(bassstream)
    Else
        Console.WriteLine("Failed to create BASS stream")
    End If

    Return Tuple.Create(cueIn, cueOut)
End Function



jpf

  • Posts: 196
Re: Intro silence detection
« Reply #7 on: 2 Mar '24 - 17:40 »
I did something similar some years ago. For the trailing silence you'd better scan the file backwards, from the end of the stream toward the begining. You should reverse the For...Next loop and set the stream position to a previous point located the lenght of the buffer behind the last requested position before calling Bass_GetData.

Nowadays I don't use peak values to detect silence; I use instead Bass_Loud the get a more human-like detection of silence.

Hope you get the picture.

radio42

  • Posts: 4839
Re: Intro silence detection
« Reply #8 on: 3 Mar '24 - 10:55 »
When you use Bass.Net, the Utils namespace hosts a DetectCuePoints method, which might do what you are looking for...
https://www.bass.radio42.com/help/html/f4f3dc62-6c4c-ecd0-d4f7-af6ad73a07c1.htm