Rilevamento del silenzio audio nei file WAV utilizzando C#


24

Ho il compito di creare un'applicazione client .NET per rilevare il silenzio in un file WAV.

Ciò è possibile con le API di Windows integrate? O alternativamente, qualche buona libreria là fuori per aiutare con questo?

13

L'analisi audio è una cosa difficile che richiede un sacco di matematica complessa (si pensi alle trasformate di Fourier). La domanda che devi porre è "cos'è il silenzio". Se l'audio che si sta tentando di modificare viene catturato da una sorgente analogica, è probabile che non ci sia silenzio ... saranno solo aree di soft noise (ronzio di linea, rumore di sottofondo ambientale, ecc.).

Detto questo, un algoritmo che dovrebbe funzionare sarebbe quello di determinare una soglia minima del volume (ampiezza) e la durata (ad esempio, < 10dbA per più di 2 secondi) e quindi semplicemente fare un'analisi del volume della forma d'onda alla ricerca di aree che soddisfano questi criteri (con forse alcuni filtri per picchi al millisecondo). Non ho mai scritto questo in C#, ma questo CodeProject article sembra interessante; descrive il codice C# per disegnare una forma d'onda ... è lo stesso tipo di codice che potrebbe essere usato per fare altre analisi di ampiezza.

  0

Link è morto. Si tratta di 6 anni più tardi. 02 set. 142014-09-02 14:33:56

  0

Non è, è vivo e vegeto! Non sono sicuro se il progetto sta lavorando bene però. Questo è di 8 anni più tardi. 13 giu. 162016-06-13 11:57:23


9

http://www.codeproject.com/Articles/19590/WAVE-File-Processor-in-C

Questo ha tutto il codice necessario per mettere a nudo il silenzio, e mescolare file wave.

Divertiti.


1

Non penso che troverete le API integrate per il rilevamento del silenzio. Ma puoi sempre usare l'elaborazione del buon calcolo matematico/discreto per scoprire il volume. Ecco un piccolo esempio: http://msdn.microsoft.com/en-us/magazine/cc163341.aspx

  0

questo link è rotto ... :( 06 gen. 182018-01-06 17:42:34


7

Se si desidera calcolare in modo efficiente la potenza media su una finestra scorrevole: quadrare ogni campione, quindi aggiungerlo a un totale parziale. Sottrarre il valore al quadrato da N campioni precedenti. Quindi vai al passaggio successivo. Questa è la forma più semplice di un filtro CIC. Parseval's Theorem ci dice che questo calcolo di potenza è applicabile sia ai domini di tempo che di frequenza.

Inoltre, è possibile aggiungere Hysteresis al sistema per evitare di accendere lo & rapidamente quando il livello di potenza sta ballando attorno al livello di soglia.


0

Utilizzare Sox. Può rimuovere i silenzi iniziali e finali, ma dovrai chiamarlo come un exe dalla tua app.


-1

See codice qui sotto da Detecting audio silence in WAV files using C#

private static void SkipSilent(string fileName, short silentLevel) 
{ 
    WaveReader wr = new WaveReader(File.OpenRead(fileName)); 
    IntPtr format = wr.ReadFormat(); 
    WaveWriter ww = new WaveWriter(File.Create(fileName + ".wav"), 
     AudioCompressionManager.FormatBytes(format)); 
    int i = 0; 
    while (true) 
    { 
     byte[] data = wr.ReadData(i, 1); 
     if (data.Length == 0) 
     { 
      break; 
     } 
     if (!AudioCompressionManager.CheckSilent(format, data, silentLevel)) 
     { 
      ww.WriteData(data); 
     } 
    } 
    ww.Close(); 
    wr.Close(); 
} 
+2

Il codice sopra riportato utilizza Alvas.Audio 04 feb. 142014-02-04 15:45:28

+4

Il codice sopra richiede una libreria di terze parti (Alvas Audio) che non è esattamente economica. 28 feb. 142014-02-28 18:52:48


0

sto usando NAudio, e volevo rilevare il silenzio in file audio in modo da poter segnalare sia o troncare.

Dopo molte ricerche, ho realizzato questa implementazione di base. Quindi, ho scritto un metodo di estensione per la classe AudioFileReader che restituisce la durata del silenzio all'inizio/fine del file, oppure a partire da una posizione specifica.

Qui:

static class AudioFileReaderExt 
{ 
    public enum SilenceLocation { Start, End } 

    private static bool IsSilence(float amplitude, sbyte threshold) 
    { 
     double dB = 20 * Math.Log10(Math.Abs(amplitude)); 
     return dB < threshold; 
    } 
    public static TimeSpan GetSilenceDuration(this AudioFileReader reader, 
               SilenceLocation location, 
               sbyte silenceThreshold = -40) 
    { 
     int counter = 0; 
     bool volumeFound = false; 
     bool eof = false; 
     long oldPosition = reader.Position; 

     var buffer = new float[reader.WaveFormat.SampleRate * 4]; 
     while (!volumeFound && !eof) 
     { 
      int samplesRead = reader.Read(buffer, 0, buffer.Length); 
      if (samplesRead == 0) 
       eof = true; 

      for (int n = 0; n < samplesRead; n++) 
      { 
       if (IsSilence(buffer[n], silenceThreshold)) 
       { 
        counter++; 
       } 
       else 
       { 
        if (location == SilenceLocation.Start) 
        { 
         volumeFound = true; 
         break; 
        } 
        else if (location == SilenceLocation.End) 
        { 
         counter = 0; 
        } 
       } 
      } 
     } 

     // reset position 
     reader.Position = oldPosition; 

     double silenceSamples = (double)counter/reader.WaveFormat.Channels; 
     double silenceDuration = (silenceSamples/reader.WaveFormat.SampleRate) * 1000; 
     return TimeSpan.FromMilliseconds(silenceDuration); 
    } 
} 

Questo accetterà quasi tutti i formati di file audio non solo WAV.

Usage:

using (AudioFileReader reader = new AudioFileReader(filePath)) 
{ 
    TimeSpan duration = reader.GetSilenceDuration(AudioFileReaderExt.SilenceLocation.Start); 
    Console.WriteLine(duration.TotalMilliseconds); 
} 

Riferimenti: