Domanda

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

Questo è possibile con le API Windows integrate?O in alternativa, qualche buona libreria là fuori può aiutarti in questo?

È stato utile?

Soluzione

L'analisi audio è una cosa difficile che richiede molti calcoli complessi (si pensi alle trasformate di Fourier).La domanda che devi porti è "cos'è il silenzio".Se l'audio che stai tentando di modificare viene catturato da una sorgente analogica, è probabile che non ci sia silenzio...saranno solo aree di rumore lieve (ronzio di linea, rumore di fondo ambientale, ecc.).

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

Altri suggerimenti

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

Questo contiene tutto il codice necessario per eliminare il silenzio e mixare file wave.

Godere.

Se vuoi calcolare in modo efficiente la potenza media su una finestra scorrevole:quadrare ciascun campione, quindi aggiungerlo al totale parziale.Sottrarre il valore al quadrato dagli N campioni precedenti.Quindi vai al passaggio successivo.Questa è la forma più semplice di a CIC Filtro. Teorema di Parseval ci dice che questo calcolo della potenza è applicabile sia al dominio del tempo che a quello della frequenza.

Inoltre potresti voler aggiungere Isteresi al sistema per evitare accensioni e spegnimenti rapidi quando il livello di potenza oscilla attorno al livello di soglia.

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

Dopo molte ricerche, sono arrivato a questa implementazione di base.Quindi, ho scritto un metodo di estensione per il file AudioFileReader classe 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.

Utilizzo:

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

Riferimenti:

Non penso che troverai API integrate per il rilevamento del silenzio.Ma puoi sempre usare la buona vecchia matematica/elaborazione discreta del segnale per scoprire il volume.Ecco un piccolo esempio: http://msdn.microsoft.com/en-us/magazine/cc163341.aspx

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

Vedi il codice qui sotto da Rilevamento del silenzio audio nei file WAV utilizzando 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();
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top