【问题标题】:how can i record and play my voice in real time using c/c++如何使用 C/C++ 实时录制和播放我的声音
【发布时间】:2015-10-17 05:21:03
【问题描述】:

我正在使用麦克风录制我的声音。为此,我使用了 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;
}  

【问题讨论】:

    标签: c++ multithreading real-time audio-streaming audio-recording


    【解决方案1】:

    从技术上讲,如果分配缓冲区,则可以将输入和输出分配到同一个缓冲区,并运行一个线程进行播放和一个线程进行记录。但是,我预计您将需要更多的数量。

    问题是缓冲区内容将通过某种机制从内存加载到硬件中,这会“预读取”数据以小块播放,以及“缓冲”记录端。驱动程序和硬件都会有一些这种“缓存”机制。这意味着回放将在数据存储到内存之前从录制中读取数据,这当然不会正常工作。

    大多数音频处理系统的工作方式是稍微延迟输出,所以你输入一点,处理它,输出它。当然,这会导致一点延迟,这可能会很烦人。

    【讨论】:

    • 延迟对我来说不是问题,但我不能错过任何数据在播放音频期间,我所说的任何内容都不会被记录下来,我会错过那些数据:(
    【解决方案2】:

    在调用 waveInStart 之前,您可以准备多个缓冲区并将其添加到音频驱动程序。驱动程序将对它们进行排队,并从一个缓冲区到另一个缓冲区进行排序,而不会丢失任何数据。您必须在 waveInOpen 中使用 fdwOpen 标志,这样每次缓冲区被填满时都会收到通知。

    waveOut 具有相同的排队能力:您可以在播放前一个缓冲区时输出一个缓冲区,它会在缓冲区之间平滑排序。

    因此,您可以使用 10 个 0.3 秒的缓冲区,而不是一个大的 3 秒缓冲区,并编写代码来处理这些缓冲区从记录到播放,因为它们被填满。结果将是没有暂停但有 0.3 秒延迟的音频。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多