使用 NAudio 录制固定长度的 wav,它会因“System.AccessViolationException”而崩溃在第一个文件之后

发布于 2025-01-17 09:42:31 字数 4126 浏览 3 评论 0原文

我正在使用naudio记录固定的长度音频文件,但是在第一个文件 方法之后,它在第一个文件后崩溃。

  • 我正在使用一个计时器,该计时器在Interval经过之后停止并启动新录制。
  • 每次新录制后,更改文件名。

这是我遇到的错误。

System.AccessViolationException
  HResult=0x80004003
  Message=Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
  Source=<Cannot evaluate the exception source>
  StackTrace:
<Cannot evaluate the exception stack trace>

班级代码在这里:

namespace AudioService
{

    public class AudioRecorder
    {
        public string Location
        {
            get => location;
            set
            {
                location = value;
                Filename = $"{Location}/test001.wav";
            }
        }

        public string Filename { get; set; }
        public double Interval { get; set; } = 10000;

        public int DeviceNumber { get; set; } = 0;

        private WaveInEvent waveSource = null;
        private WaveFileWriter waveFile = null;

        public bool LoopRecord { get; set; } = true;
        public bool Recording { get; set; } = false;

        private System.Timers.Timer timer;
        private string location;

        public AudioRecorder()
        {
            Location = Environment.GetEnvironmentVariable("userprofile");
            Filename = $"{Location}/test001.wav";

            if (LoopRecord) setTimer();
        }



        private void setTimer()
        {
            timer = new System.Timers.Timer(Interval);

            timer.Elapsed += Timer_Elapsed;
            timer.AutoReset = true;

        }

        private void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            /// ****************
            /// CRASHES HERE
            /// ****************
            waveSource?.StopRecording();

            Filename = GetNewFileName();
            StartRecording(Filename);
        }

        public void StartRecording()
        {
            if (timer != null)
                timer.Enabled = true;
            StartRecording(Filename);
        }

        public async void StartRecording(string filename)
        {
            if (waveSource == null)
            {
                waveSource = new WaveInEvent
                {
                    DeviceNumber = DeviceNumber,
                    WaveFormat = new WaveFormat(44100, 1)
                };

                waveSource.DataAvailable += new EventHandler<WaveInEventArgs>(waveSource_DataAvailable);
                waveSource.RecordingStopped += new EventHandler<StoppedEventArgs>(waveSource_RecordingStopped);
            }
            
            waveFile = await Task.Run(() => new WaveFileWriter(filename, waveSource.WaveFormat));

            waveSource.StartRecording();

            Recording = true;
        }

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

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

            Recording = false;

        }

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

        public void StopRecording()
        {
            waveSource?.StopRecording();
            timer.Enabled = false;
        }

        public string GetNewFileName()
        {
            var tempLocation = $"{Location}/{DateTime.Now:yyMMdd}/";

            bool folderExists = Directory.Exists(tempLocation);
            if (!folderExists)
                Directory.CreateDirectory(tempLocation);

            string date = DateTime.Now.ToString("HH.mm.ss");
            return $"{tempLocation}{date}.wav";
        }
    }
}

感谢您的帮助

I'm using NAudio to record a fixed length audio file, but it crashes after the first file at the TimerElapsed method.

  • I'm using a Timer that stops and starts a new recording after the Interval has elapsed.
  • The filename is changed after each new recording.

This is the error I get.

System.AccessViolationException
  HResult=0x80004003
  Message=Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
  Source=<Cannot evaluate the exception source>
  StackTrace:
<Cannot evaluate the exception stack trace>

The class code is here :

namespace AudioService
{

    public class AudioRecorder
    {
        public string Location
        {
            get => location;
            set
            {
                location = value;
                Filename = 
quot;{Location}/test001.wav";
            }
        }

        public string Filename { get; set; }
        public double Interval { get; set; } = 10000;

        public int DeviceNumber { get; set; } = 0;

        private WaveInEvent waveSource = null;
        private WaveFileWriter waveFile = null;

        public bool LoopRecord { get; set; } = true;
        public bool Recording { get; set; } = false;

        private System.Timers.Timer timer;
        private string location;

        public AudioRecorder()
        {
            Location = Environment.GetEnvironmentVariable("userprofile");
            Filename = 
quot;{Location}/test001.wav";

            if (LoopRecord) setTimer();
        }



        private void setTimer()
        {
            timer = new System.Timers.Timer(Interval);

            timer.Elapsed += Timer_Elapsed;
            timer.AutoReset = true;

        }

        private void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            /// ****************
            /// CRASHES HERE
            /// ****************
            waveSource?.StopRecording();

            Filename = GetNewFileName();
            StartRecording(Filename);
        }

        public void StartRecording()
        {
            if (timer != null)
                timer.Enabled = true;
            StartRecording(Filename);
        }

        public async void StartRecording(string filename)
        {
            if (waveSource == null)
            {
                waveSource = new WaveInEvent
                {
                    DeviceNumber = DeviceNumber,
                    WaveFormat = new WaveFormat(44100, 1)
                };

                waveSource.DataAvailable += new EventHandler<WaveInEventArgs>(waveSource_DataAvailable);
                waveSource.RecordingStopped += new EventHandler<StoppedEventArgs>(waveSource_RecordingStopped);
            }
            
            waveFile = await Task.Run(() => new WaveFileWriter(filename, waveSource.WaveFormat));

            waveSource.StartRecording();

            Recording = true;
        }

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

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

            Recording = false;

        }

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

        public void StopRecording()
        {
            waveSource?.StopRecording();
            timer.Enabled = false;
        }

        public string GetNewFileName()
        {
            var tempLocation = 
quot;{Location}/{DateTime.Now:yyMMdd}/";

            bool folderExists = Directory.Exists(tempLocation);
            if (!folderExists)
                Directory.CreateDirectory(tempLocation);

            string date = DateTime.Now.ToString("HH.mm.ss");
            return 
quot;{tempLocation}{date}.wav";
        }
    }
}

Thanks for helping

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

绝對不後悔。 2025-01-24 09:42:31

该例外基本上意味着您可能是通过尝试访问它正在忙于使用或已经关闭的对象的第三方未托管代码崩溃的。

您的计时器每次间隔都会发射,但是您没有任何代码来确保在开始新的录音之前完成。换句话说,StarTrecorting将被召集到一个计时器。如果您想散布一次,那么Timer.Autoreset应该是错误的。

解决这些问题的解决方案是用控制台替换对Naudio对象的所有调用的好方法。Writelines描述正在发生的事情,然后运行程序并观察输出。

That exception basically means that you are crashing the 3rd party unmanaged code in NAudio, probably by trying to access an object that it is busy using or that it has already closed.

Your timer is going to fire every time your interval elapses, but you don't have any code to make sure that the previous recording is complete before starting a new one. In other words, StartRecording will get called over and over one the timer is started. If you want StartRecording to fire ONCE, then timer.AutoReset should be false.

A good way to troubleshoot these kind of issues is to replace all the calls to NAudio objects with console.writelines describing what is happening, and then run your program and observe the output.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文