Поскольку моя программа (C #, NAudio) воспроизводит аудиофайл, если он встречает 1 минуту тишины, я хочу пропустить его - PullRequest
0 голосов
/ 11 февраля 2019

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

Я пытаюсь найти способ посмотреть поток перед его передачей в WaveOutEvent.Я подключаю AudioFileReader, SampleChannel и OffsetSampleProvider.Я не нашел метод, который позволил бы мне просто «посмотреть» на предстоящие данные.Я просмотрел курсы PluralSight Марка Хита и исходный код NAudio.

// Этот код основан на примерах курса NAudo Марка Здоровья по PluralSight.

...

    private string fileName;
    private IWavePlayer waveOut;
    ISampleProvider sampleProvider;

    private ISampleProvider CreateInputStream(string fileName)
    {
        audioFileReader = new AudioFileReader(fileName);
        var sampleChannel = new SampleChannel(audioFileReader, true);
        var offsetSampleProvider = new OffsetSampleProvider(sampleChannel);
        return offsetSampleProvider;
    }

    private void Play()
    {
        ...

        if (waveOut != null)
        {
            if (waveOut.PlaybackState == PlaybackState.Playing)
            {
                return;
            }
            else if (waveOut.PlaybackState == PlaybackState.Paused)
            {
                waveOut.Play();
                return;
            }
        }

        if (string.IsNullOrEmpty(fileName)) GetFileName();
        if (string.IsNullOrEmpty(fileName)) return;

        try
        {
            CreateWaveOut();
        }
        catch (Exception driverCreateException)
        {
            MessageBox.Show(String.Format("{0}", driverCreateException.Message));
            return;
        }

        try
        {
            sampleProvider = CreateInputStream(fileName);
        }
        catch (Exception createException)
        {
            MessageBox.Show(String.Format("{0}", createException.Message), "Error Loading File");
            return;
        }

       ...

        try
        {
            waveOut.Init(sampleProvider);
        }
        catch (Exception initException)
        {
            MessageBox.Show(String.Format("{0}", initException.Message), "Error Initializing Output");
            return;
        }

        SetVolume(); 
        waveOut.Play();
    }

    private void CreateWaveOut()
    {
        CloseWaveOut();
        waveOut = new WaveOutEvent();
        waveOut.PlaybackStopped += OnPlaybackStopped;
    }

    private void OnPlaybackStopped(object sender, StoppedEventArgs e)
    {
        if (e.Exception != null) MessageBox.Show(e.Exception.Message, "Playback Device Error");
        if (audioFileReader != null) audioFileReader.Position = 0;
    }

    private AudioFileReader audioFileReader;

    private void CloseWaveOut()
    {
        if (waveOut != null) waveOut.Stop();

        if (audioFileReader != null)
        {
            audioFileReader.Dispose();
            audioFileReader = null;
        }

        if (waveOut != null)
        {
            waveOut.Dispose();
            waveOut = null;
        }
    }

   ...

    private void playToolStripButton_Click(object sender, EventArgs e)
    {
        Play();
    }

   ...

    private void stopToolStripButton_Click(object sender, EventArgs e)
    {
        if (waveOut != null) waveOut.Stop();
    }

    private void openToolStripButton_Click(object sender, EventArgs e)
    {
        GetFileName();
    }

    private void timer1_Tick(object sender, EventArgs e)
    {
        if (waveOut != null && audioFileReader != null)
        {
            TimeSpan currentTime = (waveOut.PlaybackState == PlaybackState.Stopped) ? TimeSpan.Zero : audioFileReader.CurrentTime;
            trackBar1.Value = Math.Min(trackBar1.Maximum, (int)(100 * currentTime.TotalSeconds / audioFileReader.TotalTime.TotalSeconds));
            currentTimeStripLabel.Text = String.Format("{0:00}:{1:00}", (int)currentTime.TotalMinutes, currentTime.Seconds);
        }
        else
        {
            trackBar1.Value = 0;
        }
    }

    private void pauseToolStripButton_Click(object sender, EventArgs e)
    {
        if (waveOut != null)
        {
            if (waveOut.PlaybackState == PlaybackState.Playing) waveOut.Pause();
        }
    }

    private void trackBar1_Scroll(object sender, EventArgs e)
    {
        if (waveOut != null)
        {
            audioFileReader.CurrentTime = TimeSpan.FromSeconds(audioFileReader.TotalTime.TotalSeconds * trackBar1.Value / 100.0);
        }
    }
}

}

Когда пользователь слушает диктовку, пропускается тишина продолжительностью более 1 минуты.

--- это дополнительная информация по моему вопросу ---

Я смотрел раздел вашего PluralSight о том, как реализовать ISampleProvider.Довольно просто, спасибо!Вот что у меня есть.(См. Ниже.) Но не знаю, как создать буфер в памяти, о котором вы говорили.Должен ли я использовать BufferedWaveProvider?

открытый класс SkipSilenceSampleProvider: ISampleProvider {public WaveFormat WaveFormat {get {return sourceProvider.WaveFormat;}}

    private readonly ISampleProvider sourceProvider;

    public SkipSilenceSampleProvider(ISampleProvider sourceProvider)
    {
        this.sourceProvider = sourceProvider;
    }

    public int Read(float[] buffer, int offset, int count)
    {
        // Extract samples for the next minute and determine if the whole range is silence.
        int readCount = sourceProvider.Read(buffer, offset, count);
        return readCount;
    }
}

1 Ответ

0 голосов
/ 12 февраля 2019

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

...