Обнаружение звука тишины в файлах WAV с использованием C #

Мне поручено создать клиентское приложение .NET для обнаружения тишины в файлах WAV.

Возможно ли это с помощью встроенных API-интерфейсов Windows? Или, альтернативно, есть какие-нибудь хорошие библиотеки, чтобы помочь с этим?

21.08.2008 04:56:33
8 ОТВЕТОВ
РЕШЕНИЕ

Аудиоанализ - это сложная вещь, требующая много сложной математики (вспомним преобразования Фурье). Вопрос, который вы должны задать, это «что такое тишина». Если аудио, которое вы пытаетесь редактировать, получено из аналогового источника, есть вероятность, что тишины нет ... они будут только областями с мягким шумом (гул линии, фоновый шум и т. Д.).

Все это говорит о том, что алгоритм, который должен работать, должен определить минимальный порог громкости (амплитуды) и длительность (скажем, <10 дБА в течение более 2 секунд), а затем просто выполнить анализ объема сигнала, ища области, которые соответствуют этим критериям. (возможно с некоторыми фильтрами для пиков в миллисекундах). Я никогда не писал этого на C #, но эта статья CodeProject выглядит интересно; он описывает код C # для рисования формы сигнала ... это тот же код, который можно использовать для другого анализа амплитуды.

14
10.09.2015 17:16:59
Ссылка мертва. Это 6 лет спустя.
yazanpro 2.09.2014 14:33:56
Это не так, он жив и здоров! Не уверен, что проект работает хорошо, хотя. Это 8 лет спустя.
Saleem 13.06.2016 11:57:23

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

Здесь есть весь код, необходимый для удаления тишины и микширования волновых файлов.

Наслаждаться.

10
23.12.2012 09:28:27

Я не думаю, что вы найдете какие-либо встроенные API для обнаружения тишины. Но вы всегда можете использовать хорошую математическую / дискретную обработку сигналов для определения громкости. Вот небольшой пример: http://msdn.microsoft.com/en-us/magazine/cc163341.aspx

1
21.08.2008 05:07:14
эта ссылка не работает ... :(
Oleg Melnikov 6.01.2018 17:42:34

Если вы хотите эффективно рассчитать среднюю мощность по скользящему окну: возведите в квадрат каждую выборку, а затем добавьте ее к промежуточной сумме. Вычтите значение квадрата из N выборок предыдущего. Затем перейдите к следующему шагу. Это самая простая форма фильтра CIC . Теорема Парсеваля говорит нам, что этот расчет мощности применим как во временной, так и в частотной областях.

Также вы можете захотеть добавить гистерезис в систему, чтобы избежать быстрого включения и выключения, когда уровень мощности превышает пороговый уровень.

9
21.08.2011 11:18:16

Используйте Сокс . Он может удалить начальное и конечное молчание, но вам придется называть его exe из вашего приложения.

1
22.10.2009 12:55:43
Вызов внешних процессов иногда может показаться непослушным. Но более важно, что вы используете лучшие инструменты.
Todd 7.11.2018 23:47:58

См. Код ниже в разделе « Обнаружение звука тишины в файлах WAV с использованием 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
2.02.2014 13:26:35
Код выше требует сторонней библиотеки (Alvas Audio), которая не совсем дешево.
Saverio Terracciano 28.02.2014 18:52:48
Выглядит как реклама Alvas Audioбиблиотеки с открытым исходным кодом .
V. Panchenko 24.03.2018 20:41:13
Я не уверен, почему коммерческие решения отвергаются как ответы. Есть ли так политика для этого? В этом программном обеспечении может быть много качеств, которые другие не смогут достичь, что может понадобиться ОП или будущему посетителю. Вы должны критиковать ответ за его актуальность для вопроса, а не для вашей идеологии.
Todd 7.11.2018 23:48:59
Я уверен, что если бы в посте содержалась информация об использовании сторонней несвободной библиотеки, за нее не проголосовали бы, вместо того, чтобы случайно прокрасться в такой рекламе.
Francois Zard 18.12.2018 11:50:31

Я использую NAudio , и я хотел обнаружить тишину в аудиофайлах, чтобы я мог либо сообщить, либо усечь.

После долгих исследований я придумал эту базовую реализацию. Итак, я написал метод расширения для AudioFileReaderкласса, который возвращает длительность паузы в начале / конце файла или начиная с определенной позиции.

Вот:

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);
    }
}

Это позволит принять практически любой формат аудиофайла, а не только WAV .

Использование:

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

Ссылки:

3
3.09.2017 23:53:04
что находится amplitudeв формуле БД? Я работаю над обнаружением и удалением тишины из записанного аудио в течение 1,5 месяцев, но мне это еще не удалось ... это мои вопросы по этому вопросу в стеке, вопрос 1 и вопрос 2, я буду благодарен, если вы поможете Я, чтобы решить эту проблему, я студент, и это мой домашний проект, и я не профессионал в этом предмете
j.doe 10.04.2019 09:28:21

Вот хороший вариант для определения пороговых чередований:

static class AudioFileReaderExt
{


    private static bool IsSilence(float amplitude, sbyte threshold)
    {
        double dB = 20 * Math.Log10(Math.Abs(amplitude));
        return dB < threshold;
    }

    private static bool IsBeep(float amplitude, sbyte threshold)
    {
        double dB = 20 * Math.Log10(Math.Abs(amplitude));
        return dB > threshold;
    }

    public static double GetBeepDuration(this AudioFileReader reader,
                                              double StartPosition, sbyte silenceThreshold = -40)
    {
        int counter = 0;
        bool eof = false;
        int initial = (int)(StartPosition * reader.WaveFormat.Channels * reader.WaveFormat.SampleRate / 1000);
        if (initial > reader.Length) return -1;
        reader.Position = initial;
        var buffer = new float[reader.WaveFormat.SampleRate * 4];
        while (!eof)
        {
            int samplesRead = reader.Read(buffer, 0, buffer.Length);
            if (samplesRead == 0)
                eof = true;

            for (int n = initial; n < samplesRead; n++)
            {
                if (IsBeep(buffer[n], silenceThreshold))
                {
                    counter++;
                }
                else
                {
                    eof=true; break;
                }
            }
        }


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

        return TimeSpan.FromMilliseconds(silenceDuration).TotalMilliseconds;
    }

    public static double GetSilenceDuration(this AudioFileReader reader,
                                              double StartPosition, sbyte silenceThreshold = -40)
    {
        int counter = 0;
        bool eof = false;
        int initial = (int)(StartPosition * reader.WaveFormat.Channels * reader.WaveFormat.SampleRate / 1000);
        if (initial > reader.Length) return -1;
        reader.Position = initial;
        var buffer = new float[reader.WaveFormat.SampleRate * 4];
        while (!eof)
        {
            int samplesRead = reader.Read(buffer, 0, buffer.Length);
            if (samplesRead == 0)                    
                eof=true;

            for (int n = initial; n < samplesRead; n++)
            {
                if (IsSilence(buffer[n], silenceThreshold))
                {
                    counter++;
                }
                else
                {
                    eof=true; break;
                }
            }
        }


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

        return TimeSpan.FromMilliseconds(silenceDuration).TotalMilliseconds;
    }


}

Основное использование:

using (AudioFileReader reader = new AudioFileReader("test.wav"))
        {
            double duratioff = 1;
            double duration = 1;
            double position = 1;
            while (duratioff >-1 && duration >-1)
            {
                duration = reader.GetBeepDuration(position);
                Console.WriteLine(duration);
                position = position + duration;
                duratioff = reader.GetSilenceDuration(position);
                Console.WriteLine(-duratioff);
                position = position + duratioff;
            }
        }
3
17.02.2020 13:31:56