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

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

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

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
28
0
28 760
8
Перейти к ответу Данный вопрос помечен как решенный

Ответы 8

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

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

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

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

ссылка не работает ... :(

Oleg Melnikov 06.01.2018 20:42
Ответ принят как подходящий

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

Все это говорит о том, что алгоритм, который должен работать, будет определять минимальный порог громкости (амплитуды) и длительность (скажем, статья CodeProject выглядит интересной; в ней описывается код C# для рисования формы волны ... это тот же самый код, который может использоваться для другого амплитудного анализа.

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

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

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

Вызов внешних процессов иногда может показаться непослушным. Но важнее использовать лучшие инструменты.

Todd 08.11.2018 02:47

См. Код ниже из Обнаружение тишины звука в файлах 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();
}

Для приведенного выше кода требуется сторонняя библиотека (Alvas Audio), что не совсем дешево.

Saverio Terracciano 28.02.2014 22:52

Похоже на рекламу библиотеки Alvas Audio без открытого кода.

V. Panchenko 24.03.2018 23:41

Я не уверен, почему коммерческие решения отвергаются как ответы. Есть ли для этого политика SO? В этом программном обеспечении может быть много качеств, которых не могут достичь другие, которые могут понадобиться OP или будущему посетителю. Вы должны критиковать ответ за его отношение к вопросу, а не вашей идеологии.

Todd 08.11.2018 02:48

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

Francois Zard 18.12.2018 14:50

Я использую 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);
}

Рекомендации:

что такое amplitude в формуле db? Я работаю над обнаружением и удалением тишины из записанного звука около 1,5 месяца, но мне это еще не удалось ... это мои вопросы по этой теме в стеке, Вопрос 1 и вопрос 2 Буду признателен, если вы поможете мне реши эту проблему, я студент и это моя домашняя работа и я не профессионал в этом предмете

j.doe 10.04.2019 12:28

Когда я запускаю этот код на видео mp4, значения находятся в диапазоне от -96 до 0. 0 - максимальная громкость.

Josh Graham 04.01.2021 02:31

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

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

Другие вопросы по теме