none
How to Trim Silence at the Beginning and End of a Wave File Lightning Fast in VB or C# .Net RRS feed

  • General discussion

  • This is not a question it is a topic of discussion and an alternate solution to an age old problem.

    I used to use ffmpeg and shell out to the exe.  Other methods I tried using various libraries were all just as slow.

    Finally I solved the problem and it works for me in my Speech to Text application for IBM Watson.  It should work with any WAV file stereo or mono.  Here is the simple function in VB and C#.

    Sometimes simple basic commands from 20 years ago just work faster, runs in a fraction of a second.

    Visual Basic .Net (Tested and Works Great)

    Option Explicit On
    Option Strict On
    Imports System.IO
    Public Class Form1
        Private mstrAppDataPath As String = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) & "\Your Project Name"
    
        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
            Dim pstrInputFilename As String = mstrAppDataPath & "\watson_request_1_original.wav"
            Dim strOutputFilename As String = mstrAppDataPath & "\watson_request_1_trimmed.wav"
            TrimWave(pstrInputFilename, strOutputFilename)
        End Sub
    
        Public Sub TrimWave(pstrInputFilename As String, pstrOutputFilename As String)
            If File.Exists(pstrOutputFilename) Then
                File.Delete(pstrOutputFilename)
            End If
            Dim intInputFileNumber As Integer = FreeFile()
            FileOpen(intInputFileNumber, pstrInputFilename, OpenMode.Binary)
            Dim intLOF As Integer = CInt(LOF(intInputFileNumber))
            Dim strInputData As String = Space(intLOF)
            FileGet(intInputFileNumber, strInputData)
            FileClose(intInputFileNumber)
            Dim strHeader As String = strInputData.Substring(0, 40)
    
            ' Beginning Silence
            ' Find the first indicator character that implies non silent audio at the earliest position in the file
            Dim intLowestStartingOffset As Integer = 0
            For intCharValue As Integer = 254 To 240 Step -1
                Dim intStartingOffset As Integer = InStr(44, strInputData, Chr(intCharValue), CompareMethod.Binary) - 1
                If intCharValue = 254 Then
                    intLowestStartingOffset = intStartingOffset
                Else
                    If intStartingOffset < intLowestStartingOffset Then
                        intLowestStartingOffset = intStartingOffset
                    End If
                End If
            Next
    
            'Trailing Silence
            ' Find the last indicator character that implies non silent audio at the last position in the file
            Dim intHighestEndingOffset As Integer = 0
            Dim intCharValueOuter As Integer = 0
            For intCharValue As Integer = 30 To 2 Step -1
                intCharValueOuter = intCharValue
                Dim intEndingOffset As Integer = InStrRev(strInputData, Chr(intCharValue), intLOF - 1, CompareMethod.Binary) - 1
                If intCharValue = 30 Then
                    intHighestEndingOffset = intEndingOffset
                Else
                    If intEndingOffset > intHighestEndingOffset Then
                        intHighestEndingOffset = intEndingOffset
                    End If
                End If
            Next
    
            Dim intDataLength As Integer = CType(intHighestEndingOffset - intLowestStartingOffset, Integer)
            Dim strData As String = strInputData.Substring(intLowestStartingOffset, intDataLength)
            Dim intRowCount As Integer = 0
            FileOpen(intInputFileNumber, pstrOutputFilename, OpenMode.Binary)
            FilePut(intInputFileNumber, strHeader)
            FilePut(intInputFileNumber, intDataLength - 4)
            FilePut(intInputFileNumber, strData)
            FileClose(intInputFileNumber)
        End Sub
    End Class

    C# .Net (Untested I just converted the VB to C# Using an Online Tool)

    using System;
    using System.IO;
    using Microsoft.VisualBasic;
    
    public class Form1
    {
        private string mstrAppDataPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + @"\Your Project Name";
    
        private void Button1_Click(object sender, EventArgs e)
        {
            string pstrInputFilename = mstrAppDataPath + @"\watson_request_1_original.wav";
            string strOutputFilename = mstrAppDataPath + @"\watson_request_1_trimmed.wav";
            TrimWave(pstrInputFilename, strOutputFilename);
        }
    
        public void TrimWave(string pstrInputFilename, string pstrOutputFilename)
        {
            if (File.Exists(pstrOutputFilename))
                File.Delete(pstrOutputFilename);
            int intInputFileNumber = FileSystem.FreeFile();
            FileSystem.FileOpen(intInputFileNumber, pstrInputFilename, OpenMode.Binary);
            int intLOF = System.Convert.ToInt32(FileSystem.LOF(intInputFileNumber));
            string strInputData = Strings.Space(intLOF);
            FileSystem.FileGet(intInputFileNumber, ref strInputData);
            FileSystem.FileClose(intInputFileNumber);
            string strHeader = strInputData.Substring(0, 40);
    
            // Beginning Silence
            // Find the first indicator character that implies non silent audio at the earliest position in the file
            int intLowestStartingOffset = 0;
            for (int intCharValue = 254; intCharValue >= 240; intCharValue += -1)
            {
                int intStartingOffset = Strings.InStr(44, strInputData, Strings.Chr(intCharValue), CompareMethod.Binary) - 1;
                if (intCharValue == 254)
                    intLowestStartingOffset = intStartingOffset;
                else if (intStartingOffset < intLowestStartingOffset)
                    intLowestStartingOffset = intStartingOffset;
            }
    
            // Trailing Silence
            // Find the last indicator character that implies non silent audio at the earliest position in the file
            int intHighestEndingOffset = 0;
            int intCharValueOuter = 0;
            for (int intCharValue = 30; intCharValue >= 2; intCharValue += -1)
            {
                intCharValueOuter = intCharValue;
                int intEndingOffset = Strings.InStrRev(strInputData, Strings.Chr(intCharValue), intLOF - 1, CompareMethod.Binary) - 1;
                if (intCharValue == 30)
                    intHighestEndingOffset = intEndingOffset;
                else if (intEndingOffset > intHighestEndingOffset)
                    intHighestEndingOffset = intEndingOffset;
            }
    
            int intDataLength = System.Convert.ToInt32(intHighestEndingOffset - intLowestStartingOffset);
            string strData = strInputData.Substring(intLowestStartingOffset, intDataLength);
            int intRowCount = 0;
            FileSystem.FileOpen(intInputFileNumber, pstrOutputFilename, OpenMode.Binary);
            FileSystem.FilePut(intInputFileNumber, strHeader);
            FileSystem.FilePut(intInputFileNumber, intDataLength - 4);
            FileSystem.FilePut(intInputFileNumber, strData);
            FileSystem.FileClose(intInputFileNumber);
        }
    }



    Tuesday, September 10, 2019 2:07 AM

All replies

  • Dear Moderator,

    I posted this in the forum and don't know how to move it. Could you please move it to .Net or VB.Net?

    Thank You

    Tuesday, September 10, 2019 2:46 AM