由于我的程序(C#,NAudio)正在播放音频文件,如果它遇到1分钟的沉默,我想跳过它

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了由于我的程序(C#,NAudio)正在播放音频文件,如果它遇到1分钟的沉默,我想跳过它相关的知识,希望对你有一定的参考价值。

我的应用播放音频文件。当它播放时,我想检查下一分钟将播放的内容,看看它是否全部都是沉默;如果是这样,我想跳过沉默。

我试图找到一种方法来查看流之前传递给WaveOutEvent。我正在链接AudioFileReader,SampleChannel和OffsetSampleProvider。我还没有找到一种方法可以让我简单地“窥视”即将到来的数据。我看过Mark Heath的PluralSight课程和NAudio源代码。

//此代码基于Mark Health在PluralSight上的NAudo课程的示例。

...

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

你可以通过实现包装你的ISampleProvider的自定义AudioFileReader来实现这一点。在Read方法中,您需要从源AudioFileReader中提前阅读,以确定是否存在需要跳过的静音。所以你需要一个包含一分钟音频的内存缓冲区。然后Read方法应该返回下一个非静默样本。除非您已到达源文件的末尾,否则Read应始终返回所请求的样本数。

以上是关于由于我的程序(C#,NAudio)正在播放音频文件,如果它遇到1分钟的沉默,我想跳过它的主要内容,如果未能解决你的问题,请参考以下文章

使用 NAUDIO 播放 Dialogic ADPCM 音频文件

在 UWP 中使用 NAudio 播放多个音频文件

NAudio:在保持声卡打开的同时播放许多音频文件

来自流的NAudio?播放音频

使用 NAudio 发送正在播放的音频

我可以同时从音频流缓冲区写入和播放(在 NAudio 中)吗?