play - Detectando silencio de audio en archivos WAV usando C#
naudio vb net (7)
Tengo la tarea de crear una aplicación cliente .NET para detectar el silencio en un archivo WAV.
¿Es esto posible con las API integradas de Windows? O, alternativamente, ¿hay buenas bibliotecas para ayudar con esto?
El análisis de audio es algo difícil que requiere mucha matemática compleja (piense en las transformadas de Fourier). La pregunta que debe hacerse es "qué es el silencio". Si el audio que está tratando de editar se captura desde una fuente analógica, existe la posibilidad de que no haya ningún silencio ... solo serán áreas de ruido suave (zumbido de línea, ruido de fondo ambiental, etc.).
Dicho todo esto, un algoritmo que debería funcionar sería determinar un umbral y duración de volumen (amplitud) mínimo (por ejemplo, <10dbA durante más de 2 segundos) y luego hacer un análisis de volumen de la forma de onda buscando áreas que cumplan este criterio (con quizás algunos filtros para picos de milisegundos). Nunca escribí esto en C #, pero este artículo de CodeProject parece interesante; describe el código C # para dibujar una forma de onda ... ese es el mismo tipo de código que podría usarse para hacer otro análisis de amplitud.
Estoy usando NAudio y quería detectar el silencio en los archivos de audio para poder informar o truncar.
Después de mucha investigación, se me ocurrió esta implementación básica. Entonces, escribí un método de extensión para la clase AudioFileReader
que devuelve la duración del silencio al inicio / final del archivo, o comenzando desde una posición específica.
Aquí:
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);
}
}
Esto aceptará casi cualquier formato de archivo de audio, no solo WAV .
Uso:
using (AudioFileReader reader = new AudioFileReader(filePath))
{
TimeSpan duration = reader.GetSilenceDuration(AudioFileReaderExt.SilenceLocation.Start);
Console.WriteLine(duration.TotalMilliseconds);
}
Referencias
- Cómo se calculan los niveles de audio en dB .
- Rango de muestras de punto flotante .
- Más sobre la amplitud
No creo que encuentres ninguna API integrada para la detección del silencio. Pero siempre se puede usar un buen procesamiento de señal matemática / discordante para averiguar el volumen. Aquí hay un pequeño ejemplo: http://msdn.microsoft.com/en-us/magazine/cc163341.aspx
Si desea calcular de manera eficiente la potencia promedio sobre una ventana deslizante: cuadre cada muestra, luego agréguela a un total acumulado. Reste el valor cuadrado de N muestras anteriores. Luego avance al siguiente paso. Esta es la forma más simple de un filtro CIC . El teorema de Parseval nos dice que este cálculo de potencia es aplicable tanto a los dominios de tiempo como a los de frecuencia.
También es posible que desee agregar Hysteresis al sistema para evitar encender y apagar rápidamente cuando el nivel de potencia esté bailando alrededor del nivel del umbral.
Usa Sox . Puede eliminar silencios iniciales y finales, pero tendrá que llamarlo como un exe de su aplicación.
Vea el código a continuación desde Detección de silencio de audio en archivos WAV usando 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();
}
http://www.codeproject.com/Articles/19590/WAVE-File-Processor-in-C
Esto tiene todo el código necesario para eliminar el silencio y mezclar archivos de onda.
Disfrutar.