基於 WaveIn/WaveOut API 的錄音/播放,配合多執行緒實現「錄音 → 網路傳輸 → 播放」管線並行,採用循環緩衝區與指標追蹤機制處理網路擁塞與速率不匹配。
struct CAudioData {
PBYTE lpdata; // 動態分配的音訊資料指標
DWORD dwLength; // 資料長度
};
// 兩個循環隊列:輸入(錄音)與輸出(播放)
CAudioData m_AudioDataIn[InBlocks], m_AudioDataOut[OutBlocks];
int nAudioIn, nSend; // 錄入、發送指標
int nAudioOut, nReceive; // 接收、播放指標
四個指標在循環緩衝區中追逐,形成自我調節的流控:

void CRecTestDlg::OnMM_WIM_DATA(UINT wParam, LONG lParam) {
int nextBlock = (nAudioIn+1) % InBlocks;
PWAVEHDR pHdr = (PWAVEHDR)lParam;
if (m_AudioDataIn[nextBlock].dwLength != 0) { // 下一塊未發走,追加至當前塊
m_AudioDataIn[nAudioIn].lpdata = (PBYTE)realloc(
m_AudioDataIn[nAudioIn].lpdata,
pHdr->dwBytesRecorded + m_AudioDataIn[nAudioIn].dwLength);
CopyMemory(m_AudioDataIn[nAudioIn].lpdata + m_AudioDataIn[nAudioIn].dwLength,
pHdr->lpData, pHdr->dwBytesRecorded);
m_AudioDataIn[nAudioIn].dwLength += pHdr->dwBytesRecorded;
} else { // 移至下一塊
nAudioIn = nextBlock;
m_AudioDataIn[nAudioIn].lpdata = (PBYTE)realloc(0, pHdr->dwBytesRecorded);
CopyMemory(m_AudioDataIn[nAudioIn].lpdata, pHdr->lpData, pHdr->dwBytesRecorded);
m_AudioDataIn[nAudioIn].dwLength = pHdr->dwBytesRecorded;
}
waveInAddBuffer(hWaveIn, pHdr, sizeof(WAVEHDR)); // 重新排隊緩衝區
}
void CRecTestDlg::OnMM_WOM_DONE(UINT wParam, LONG lParam) {
free(m_AudioDataOut[nAudioOut].lpdata);
m_AudioDataOut[nAudioOut].lpdata = (PBYTE)malloc(1);
m_AudioDataOut[nAudioOut].dwLength = 0;
nAudioOut = (nAudioOut+1) % OutBlocks;
PWAVEHDR pHdr = (PWAVEHDR)lParam;
pHdr->lpData = (LPTSTR)m_AudioDataOut[nAudioOut].lpdata;
pHdr->dwBufferLength = m_AudioDataOut[nAudioOut].dwLength;
waveOutPrepareHeader(hWaveOut, pHdr, sizeof(WAVEHDR));
waveOutWrite(hWaveOut, pHdr, sizeof(WAVEHDR));
}
nReceiverecSo.Receive 回傳值檢測實際收到位元組數,確保完整接收nSend 指向的區塊是否有資料 (dwLength != 0)nSend