关于waveInReset/waveOutReset锁死问题

在使用waveInReset/waveOutReset时,若需在发出停止指令后让回调函数立即返回,可通过设置bStop标志实现。避免了回调函数在停止指令后继续执行可能产生的意外行为。
  在调用waveInReset/waveOutReset期间,系统调用了回调函数,如果设置bStop标志,使回调函数在这时什么都不做直接返回,问题就解决了。
         注意,发出了停止指令后,回调函数所做的第一件事就是返回,哪怕做了一件与声音无关的事,也要产生意外 。
完善该代码,并列出详细的注释语句 #include <windows.h> #include <mmsystem.h> #include <fstream> #include <NXOpen/UI.hxx> #include <NXOpen/NXException.hxx> // WAV文件头结构 struct WAVHeader { char riff[4] = { 'R','I','F','F' }; DWORD fileSize; char wave[4] = { 'W','A','V','E' }; char fmt[4] = { 'f','m','t',' ' }; DWORD fmtSize = 16; WORD audioFormat = 1; // PCM WORD numChannels; DWORD sampleRate; DWORD byteRate; WORD blockAlign; WORD bitsPerSample; char data[4] = { 'd','a','t','a' }; DWORD dataSize; }; // 全局变量 HWAVEIN hWaveIn; WAVEFORMATEX waveFormat; char* recordingBuffer; WAVEHDR waveHeader; std::ofstream wavFile; bool isRecording = false; // 回调函数 void CALLBACK waveInProc(HWAVEIN hwi, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2) { if (uMsg == WIM_DATA) { LPWAVEHDR pHeader = (LPWAVEHDR)dwParam1; if (isRecording) { // 写入音频数据到文件 wavFile.write(pHeader->lpData, pHeader->dwBytesRecorded); // 重新提交缓冲区 waveInAddBuffer(hWaveIn, pHeader, sizeof(WAVEHDR)); } } } // 开始录音 void StartRecording() { if (isRecording) return; // 打开输出文件 wavFile.open("C:/recorded_audio.wav", std::ios::binary); // 设置音频格式 waveFormat.wFormatTag = WAVE_FORMAT_PCM; waveFormat.nChannels = 1; // 单声道 waveFormat.nSamplesPerSec = 44100; // 44.1kHz waveFormat.wBitsPerSample = 16; // 16位 waveFormat.nBlockAlign = waveFormat.nChannels * waveFormat.wBitsPerSample / 8; waveFormat.nAvgBytesPerSec = waveFormat.nSamplesPerSec * waveFormat.nBlockAlign; waveFormat.cbSize = 0; // 打开录音设备 if (waveInOpen(&hWaveIn, WAVE_MAPPER, &waveFormat, (DWORD_PTR)waveInProc, 0, CALLBACK_FUNCTION) != MMSYSERR_NOERROR) { throw std::runtime_error("无法打开录音设备"); } // 准备缓冲区 recordingBuffer = new char[waveFormat.nAvgBytesPerSec * 2]; // 2秒缓冲区 waveHeader.lpData = recordingBuffer; waveHeader.dwBufferLength = waveFormat.nAvgBytesPerSec * 2; waveHeader.dwFlags = 0; waveHeader.dwLoops = 0; if (waveInPrepareHeader(hWaveIn, &waveHeader, sizeof(WAVEHDR)) { throw std::runtime_error("准备缓冲区失败"); } // 写入WAV文件头 WAVHeader header; header.numChannels = waveFormat.nChannels; header.sampleRate = waveFormat.nSamplesPerSec; header.bitsPerSample = waveFormat.wBitsPerSample; header.byteRate = waveFormat.nAvgBytesPerSec; header.blockAlign = waveFormat.nBlockAlign; wavFile.write(reinterpret_cast<char*>(&header), sizeof(WAVHeader)); // 开始录音 if (waveInAddBuffer(hWaveIn, &waveHeader, sizeof(WAVEHDR)) { throw std::runtime_error("添加缓冲区失败"); } waveInStart(hWaveIn); isRecording = true; } // 停止录音 void StopRecording() { if (!isRecording) return; waveInStop(hWaveIn); isRecording = false; // 更新WAV文件头 DWORD dataSize = wavFile.tellp() - sizeof(WAVHeader); wavFile.seekp(4); DWORD fileSize = dataSize + sizeof(WAVHeader) - 8; wavFile.write(reinterpret_cast<char*>(&fileSize), 4); wavFile.seekp(40); wavFile.write(reinterpret_cast<char*>(&dataSize), 4); // 清理资源 waveInReset(hWaveIn); waveInUnprepareHeader(hWaveIn, &waveHeader, sizeof(WAVEHDR)); waveInClose(hWaveIn); wavFile.close(); delete[] recordingBuffer; }
最新发布
08-16
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值