简体   繁体   English

使用录制的波形文件(NAudio)

[英]Using recorded wave file (NAudio)

This is the code I use to record an audio file: 这是我用来录制音频文件的代码:

internal class AudioRecorder
{
    public WaveIn waveSource = null;
    public WaveFileWriter waveFile = null;
    public string RECORDING_PATH;

    public AudioRecorder(string fileName)
    {
        RECORDING_PATH = fileName;
    }

    public void Start()
    {
        waveSource = new WaveIn();
        waveSource.WaveFormat = new WaveFormat(44100, 1);
        waveSource.DeviceNumber = 0;
        waveSource.DataAvailable += new EventHandler<WaveInEventArgs>(waveSource_DataAvailable);
        waveSource.RecordingStopped += new EventHandler<StoppedEventArgs>(waveSource_RecordingStopped);

        waveFile = new WaveFileWriter(RECORDING_PATH, waveSource.WaveFormat);

        System.Timers.Timer t = new System.Timers.Timer(30000);

        t.Elapsed += new ElapsedEventHandler(Stop);

        waveSource.StartRecording();

        t.Start();


    }

    private void Stop(object sender, ElapsedEventArgs args)
    {
        waveSource.StopRecording();
    }

    private void waveSource_DataAvailable(object sender, WaveInEventArgs e)
    {
        if (waveFile != null)
        {
            waveFile.Write(e.Buffer, 0, e.BytesRecorded);
            waveFile.Flush();
        }
    }

    private void waveSource_RecordingStopped(object sender, StoppedEventArgs e)
    {
        if (waveSource != null)
        {
            waveSource.Dispose();
            waveSource = null;
        }

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

    }
}

In the main method I do: 在主要方法中,我这样做:

AudioRecorder r = new AudioRecorder(dialog.FileName);
r.Start();
FileInfo file = new FileInfo(r.RECORDING_PATH);
// Do somehting with the recorded audio //

The problem is that when I do r.Start() the thread does not block and keeps running. 问题是当我执行r.Start() ,线程不会阻塞并保持运行。 So I get a corrupt file error. 所以我收到了损坏的文件错误。 When I try things like Thread.Sleep to keep the thread waiting until recording finishes, this time the AudioRecorder code does not work well (ie recording never finishes). 当我尝试使用Thread.Sleep方法使线程等待直到录制完成时,这次AudioRecorder代码无法正常工作(即,录制永远不会完成)。

Any ideas about what should I do to correctly wait the recording to finish so that I can safely use the recorded file ? 有关如何正确等待录制完成以便可以安全使用录制文件的任何想法?

If you want to record for 30 seconds exactly, just call StopRecording in the DataAvailable event handler once you have enough data. 如果要精确记录30秒,则一旦有足够的数据,只需在DataAvailable事件处理程序中调用StopRecording。 There is absolutely no need for a complicated threading strategy. 绝对不需要复杂的线程策略。 I do exactly this in the open source .NET voice recorder application . 我正是在开源.NET录音机应用程序中执行此操作的

Dispose the WaveFileWriter in the RecordingStopped event. 将WaveFileWriter放置在RecordingStopped事件中。

If you absolutely must have a blocking call, then use WaveInEvent, and wait on an event which is set in the RecordingStopped handler, as suggested by Rene. 如果您绝对必须进行阻塞调用,则使用WaveInEvent,然后等待Rene建议的在RecordingStopped处理程序中设置的事件。 By using WaveInEvent, you remove the need for windows message pump to be operational. 通过使用WaveInEvent,您无需运行Windows消息泵。

You use a ManualResetEvent to wait for the Stop event to be called, giving other threads a change to proceed. 您可以使用ManualResetEvent等待Stop事件被调用,从而使其他线程可以继续进行更改。 I've only added the new bits... 我只添加了新位...

internal class AudioRecorder
{  
    private ManualResetEvent mre = new ManualResetEvent(false);

    public void Start()
    {

        t.Start();
        while (!mre.WaitOne(200))
        {   
            // NAudio requires the windows message pump to be operational
            // this works but you better raise an event
            Application.DoEvents(); 
        }
    }

    private void Stop(object sender, ElapsedEventArgs args)
    {
        // better: raise an event from here!
        waveSource.StopRecording();
    }

    private void waveSource_RecordingStopped(object sender, EventArgs e)
    {
       /// ... your code here

       mre.Set();  // signal thread we're done!
    }

It is good idea to avoid any multi-threaded code if it is not required and Mark's answer is explaining this perfectly. 最好避免使用任何不需要的多线程代码,而Mark的答案很好地说明了这一点。

However, if you are writing a windows application and the requirement is to record 30 seconds than it is a must not to block a main thread in waiting (for 30 seconds). 但是,如果您正在编写Windows应用程序,并且要求记录30秒,那么必须等待30秒才能阻止主线程。 The new async C# feature can be very handy here. 新的异步C#功能在这里非常方便。 It will allow you to keep code logic straightforward and implement waiting in a very efficient way. 这将使您保持代码逻辑简单明了,并以非常有效的方式实现等待。

I have modified your code slightly to show how the async feature can be used in this case. 我已经稍微修改了您的代码,以显示在这种情况下如何使用异步功能。

Here is the Record method: 这是Record方法:

    public async Task RecordFixedTime(TimeSpan span)
    {
        waveSource = new WaveIn {WaveFormat = new WaveFormat(44100, 1), DeviceNumber = 0};
        waveSource.DataAvailable += new EventHandler<WaveInEventArgs>(waveSource_DataAvailable);
        waveSource.RecordingStopped += new EventHandler<StoppedEventArgs>(waveSource_RecordingStopped);

        waveFile = new WaveFileWriter(RECORDING_PATH, waveSource.WaveFormat);

        waveSource.StartRecording();
        await Task.Delay(span);
        waveSource.StopRecording();
    }

Example of using Record from click handler of WPF app: 从WPF应用的点击处理程序中使用记录的示例:

    private async void btnRecord_Click(object sender, RoutedEventArgs e)
    {
        try
        {
            btnRecord.IsEnabled = false;
            var fileName = Path.GetTempFileName() + ".wav";
            var recorder = new AudioRecorder(fileName);
            await recorder.RecordFixedTime(TimeSpan.FromSeconds(5));
            Process.Start(fileName);
        }
        finally
        {
            btnRecord.IsEnabled = true;
        }
    }

However, you have to watch out for timing here. 但是,您必须注意此处的时间安排。 Task.Delay does not guarantee that it will continue execution after the exact specified time span. Task.Delay不保证它将在指定的确切时间间隔后继续执行。 You might get records slightly longer than is required. 您可能会得到比所需时间稍长的记录。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM