如何使用c/c++实时录制和播放我的声音
how can i record and play my voice in real time using c/c++
我正在用麦克风录音。为此,我使用了waveIn()和waveOut()函数。当我开始使用waveInStart()函数录音时,它首先在指定的时间内完整地记录我的声音,并将其存储在()缓冲区中,然后从该缓冲区中播放我的声音。在录制和播放期间,它不做任何事情。我想同时录音和演奏。为此,我想在记录期间访问缓冲区。这怎么可能呢?或者其他建议会有帮助的。
Here is the code :
#include <iostream>
#include <Windows.h>
using namespace std;
#pragma comment(lib, "winmm.lib")
short int waveIn[8000 * 3];
void PlayRecord();
void writedataTofile(LPSTR lpData,DWORD dwBufferLength);
void StartRecord()
{
const int NUMPTS = 8000 * 3; // 3 seconds
int sampleRate = 8000;
// 'short int' is a 16-bit type; I request 16-bit samples below
// for 8-bit capture, you'd use 'unsigned char' or 'BYTE' 8-bit types
HWAVEIN hWaveIn;
MMRESULT result;
WAVEFORMATEX pFormat;
pFormat.wFormatTag=WAVE_FORMAT_PCM; // simple, uncompressed format
pFormat.nChannels=1; // 1=mono, 2=stereo
pFormat.nSamplesPerSec=sampleRate; // 8.0 kHz, 11.025 kHz, 22.05 kHz, and 44.1 kHz
pFormat.nAvgBytesPerSec=sampleRate*2; // = nSamplesPerSec × nBlockAlign
pFormat.nBlockAlign=2; // = (nChannels × wBitsPerSample) / 8
pFormat.wBitsPerSample=16; // 16 for high quality, 8 for telephone-grade
pFormat.cbSize=0;
// Specify recording parameters
result = waveInOpen(&hWaveIn, WAVE_MAPPER,&pFormat,
0L, 0L, WAVE_FORMAT_DIRECT);
WAVEHDR WaveInHdr;
// Set up and prepare header for input
WaveInHdr.lpData = (LPSTR)waveIn;
WaveInHdr.dwBufferLength = NUMPTS*2;
WaveInHdr.dwBytesRecorded=0;
WaveInHdr.dwUser = 0L;
WaveInHdr.dwFlags = 0L;
WaveInHdr.dwLoops = 0L;
waveInPrepareHeader(hWaveIn, &WaveInHdr, sizeof(WAVEHDR));
// Insert a wave input buffer
result = waveInAddBuffer(hWaveIn, &WaveInHdr, sizeof(WAVEHDR));
// Commence sampling input
result = waveInStart(hWaveIn);
cout << "recording..." << endl;
Sleep(3 * 1000);
// Wait until finished recording
waveInClose(hWaveIn);
PlayRecord();
}
void PlayRecord()
{
const int NUMPTS = 8000 * 3; // 3 seconds
int sampleRate = 8000;
// 'short int' is a 16-bit type; I request 16-bit samples below
// for 8-bit capture, you'd use 'unsigned char' or 'BYTE' 8-bit types
HWAVEIN hWaveIn;
WAVEFORMATEX pFormat;
pFormat.wFormatTag=WAVE_FORMAT_PCM; // simple, uncompressed format
pFormat.nChannels=1; // 1=mono, 2=stereo
pFormat.nSamplesPerSec=sampleRate; // 44100
pFormat.nAvgBytesPerSec=sampleRate*2; // = nSamplesPerSec * n.Channels * wBitsPerSample/8
pFormat.nBlockAlign=2; // = n.Channels * wBitsPerSample/8
pFormat.wBitsPerSample=16; // 16 for high quality, 8 for telephone-grade
pFormat.cbSize=0;
// Specify recording parameters
waveInOpen(&hWaveIn, WAVE_MAPPER,&pFormat, 0L, 0L, WAVE_FORMAT_DIRECT);
WAVEHDR WaveInHdr;
// Set up and prepare header for input
WaveInHdr.lpData = (LPSTR)waveIn;
WaveInHdr.dwBufferLength = NUMPTS*2;
WaveInHdr.dwBytesRecorded=0;
WaveInHdr.dwUser = 0L;
WaveInHdr.dwFlags = 0L;
WaveInHdr.dwLoops = 0L;
waveInPrepareHeader(hWaveIn, &WaveInHdr, sizeof(WAVEHDR));
HWAVEOUT hWaveOut;
cout << "playing..." << endl;
waveOutOpen(&hWaveOut, WAVE_MAPPER, &pFormat, 0, 0, WAVE_FORMAT_DIRECT);
waveOutWrite(hWaveOut, &WaveInHdr, sizeof(WaveInHdr)); // Playing the data
Sleep(3 * 1000); //Sleep for as long as there was recorded
waveInClose(hWaveIn);
waveOutClose(hWaveOut);
}
int main()
{
StartRecord();
return 0;
}
从技术上讲,如果您分配缓冲区,您可以将输入和输出分配到同一个缓冲区,并运行一个线程来执行播放,一个线程来执行录制。然而,我预计你需要的会比这多得多。
问题是缓冲区内容将通过某种机制从内存加载到硬件中,并且这将"预读取"数据以便在小块中播放,以及"缓冲"记录端。驱动程序和硬件都有这种"缓存"机制。这意味着回放将在数据从记录中存储到内存之前读取数据,这当然不会正常工作。
大多数音频处理系统的工作方式是稍微延迟输出,所以你输入一点,处理它,输出它。当然,这会导致一个小的延迟,这是相当恼人的。
在调用waveInStart之前,您可以准备并添加几个缓冲区到音频驱动程序。驱动程序将对它们进行排队,并在不丢失任何数据的情况下对缓冲区进行排序。你必须在waveInOpen中使用fdwOpen标志,这样每次缓冲区被填满时你都会得到一个通知。
waveOut具有相同的排队能力:您可以在播放前一个缓冲区时输出缓冲区,并且它将在缓冲区之间平滑地排序。
所以比起一个3秒的大缓冲区,你可以使用10个0.3秒的缓冲区,并编写代码来在这些缓冲区被填满时从记录到播放。结果将是没有暂停的音频,但有0.3秒的延迟。
相关文章:
- 如何收听Windows当前正在播放的声音?
- SFML c ++ 当包含文件内游戏中发生事件时,如何使用铃声函数为我的游戏创建声音类?
- Qt - 重新实现QIODevice,实时听到我自己的声音
- Portaudio:通过调用功能播放多个生成的声音
- WASAPI:以最小的延迟播放正弦波声音,无毛刺(专用事件驱动模式)
- 播放加载到一半的声音缓冲区,同时在C++中快速加载其余部分
- 使用C 在Windows上播放编程生成的声音
- 我正在尝试获取媒体播放器的元数据,但QT中不断出现C2228错误
- 如何在Qt中重复/循环播放来自资源文件的声音
- 主机中同一 VST 乐器的多个实例播放相同的 MIDI 声音
- mciSendString 不会暂停从线程播放的声音
- 我如何使用libavfilter在我的视频播放器软件中去交错帧
- 听起来没有在我的代码上播放
- 想知道我的代码有什么问题?一旦播放器名称达到 100,应该输出获胜者,但在之后再次循环
- 播放产生的音频数据在声音中有噪音和周期性的咔嗒声
- SDL_mixer不会播放树莓派的声音
- 如何使用c/c++实时录制和播放我的声音
- PlaySound() mmslib不播放现有的声音
- 如何在播放节目的同时播放声音
- 如何通知我的应用程序默认声音播放设备已更改