C++オーディオストリームの再生(PCM裸ストリーム)


直接コードをつけて、必要があればwin 32コンソールプログラムを直接建てて、コードをコピーしてファイル名を変えることができます(チャネルと周波数を自分のファイルに対応することに注意してください).もちろん私自身もVS 2008で例を書いてアップロードしましたが、ダウンロードする必要があるアドレスがあれば以下の通りです:クリックしてリンクを開きます.
このコードはファイルを開いてデータを切り取って再生し、簡単にスレッドを追加してネットワーク伝送の形式に変更することができますが、本人のテストを経て、キャッシュメカニズムがないと「ダダ」のノイズがあるため、つまりこのコードはネットワークのリアルタイムオーディオでの表現があまりよくありません.この問題を解決するために、キャッシュメカニズムを加えることができ、本人は最初はイベント応答方式を使っていたので、ずっとこのフレームワークに閉じ込められていて、キャッシュメカニズムをうまく利用して上記の問題を解決することができず、その後、コールバック関数でデータ再生完了のメッセージに応答しようと試みたが、問題は簡単に解決した.その部分のコードはしばらくお待ちください.
#include "stdafx.h"
#include <stdio.h>
#include <Windows.h>
#pragma comment(lib, "winmm.lib")

char buf[1024 * 1024 * 4];

int _tmain(int argc, _TCHAR* argv[]) {
	FILE*           thbgm;//  
	int             cnt;
	HWAVEOUT        hwo;
	WAVEHDR         wh;
	WAVEFORMATEX    wfx;
	HANDLE          wait;

	wfx.wFormatTag = WAVE_FORMAT_PCM;//         
	wfx.nChannels = 1;//           
	wfx.nSamplesPerSec = 8000;//                 
	wfx.nAvgBytesPerSec = 16000;//            ,  byte/s。                
	wfx.nBlockAlign = 2;//           
	wfx.wBitsPerSample = 16;
	wfx.cbSize = 0;//       
	wait = CreateEvent(NULL, 0, 0, NULL);
	waveOutOpen(&hwo, WAVE_MAPPER, &wfx, (DWORD_PTR)wait, 0L, CALLBACK_EVENT);//                    
	fopen_s(&thbgm, "paomo.pcm", "rb");
	cnt = fread(buf, sizeof(char), 1024 * 1024 * 4, thbgm);//    4M           ,         ,                  。               ,           
	int dolenght = 0;
	int playsize = 1024;
	while (cnt) {//                                      ,            “  ”   
		wh.lpData = buf + dolenght;
		wh.dwBufferLength = playsize;
		wh.dwFlags = 0L;
		wh.dwLoops = 1L;
		waveOutPrepareHeader(hwo, &wh, sizeof(WAVEHDR));//             
		waveOutWrite(hwo, &wh, sizeof(WAVEHDR));//             wh     
		WaitForSingleObject(wait, INFINITE);//    hHandle       ,            ,      ,      INFINITE   ,               ,        
		dolenght = dolenght + playsize;
		cnt = cnt - playsize;
	}
	waveOutClose(hwo);
	fclose(thbgm);
	return 0;
}

上の部分を書くのからもうすぐ1年になりますが、今、前に書いたコードを振り返ると少し穴が開いているような気がします.進歩したのかもしれません.前に二重キャッシュのコードを出すと言っていたが、後で他のプロジェクトに忙しくなったとは知らなかった.この部分は置き去りにして、古いプロジェクトからコードを抽出するのはうんざりしていた.この1年で多くの人が私にこのコードについてどう書くかと私信を送ってくれたが、今オーディオをしている人が多いとは思わなかった.Ok、穴を掘った以上記入しなければならないので、今日は週末にダブルキャッシュのDemoプロジェクトを書きました.コードは以下の通りです.
#include <stdio.h>
#include <Windows.h>

#pragma comment(lib, "winmm.lib")

#define DATASIZE 1024*512 //        
FILE*			pcmfile;  //    
HWAVEOUT        hwo;

void CALLBACK WaveCallback(HWAVEOUT hWave, UINT uMsg, DWORD dwInstance, DWORD dw1, DWORD dw2)//    
{
	switch (uMsg)
	{
		case WOM_DONE://        ,     
		{
			LPWAVEHDR pWaveHeader = (LPWAVEHDR)dw1;
			pWaveHeader->dwBufferLength = fread(pWaveHeader->lpData, 1, DATASIZE, pcmfile);;
			waveOutPrepareHeader(hwo, pWaveHeader, sizeof(WAVEHDR));
			waveOutWrite(hwo, pWaveHeader, sizeof(WAVEHDR));
			break;
		}
	}
}

void main() 
{
	int             cnt;
	WAVEHDR         wh1;
	WAVEHDR         wh2;
	WAVEFORMATEX    wfx;

	fopen_s(&pcmfile, "paomo.pcm", "rb");//    

	wfx.wFormatTag = WAVE_FORMAT_PCM;//         
	wfx.nChannels = 1;//           
	wfx.nSamplesPerSec = 8000;//                 
	wfx.nAvgBytesPerSec = 16000;//            ,  byte/s。                
	wfx.nBlockAlign = 2;//           
	wfx.wBitsPerSample = 16;
	wfx.cbSize = 0;//       

	waveOutOpen(&hwo, WAVE_MAPPER, &wfx, (DWORD)WaveCallback, 0L, CALLBACK_FUNCTION);//                      ,         。        ,          (DWORD)this,    Demo    

	wh1.dwLoops = 0L;//    
	wh1.lpData = new char[DATASIZE];
	wh1.dwBufferLength = DATASIZE; 
	fread(wh1.lpData, 1, DATASIZE, pcmfile);
	wh1.dwFlags = 0L;
	waveOutPrepareHeader(hwo, &wh1, sizeof(WAVEHDR));//             
	waveOutWrite(hwo, &wh1, sizeof(WAVEHDR));//                  ,              

	wh2.dwLoops = 0L;//    ,    
	wh2.lpData = new char[DATASIZE];
	wh2.dwBufferLength = DATASIZE;
	fread(wh2.lpData, 1, DATASIZE, pcmfile);
	wh2.dwFlags = 0L;
	waveOutPrepareHeader(hwo, &wh2, sizeof(WAVEHDR));
	waveOutWrite(hwo, &wh2, sizeof(WAVEHDR));

	while (wh1.dwBufferLength != 0 || wh2.dwBufferLength != 0)//             500ms
	{
		Sleep(500);
	}
	waveOutUnprepareHeader(hwo, &wh1, sizeof(WAVEHDR));//    
	waveOutUnprepareHeader(hwo, &wh2, sizeof(WAVEHDR));

	delete []wh1.lpData;
	delete []wh2.lpData;
	fclose(pcmfile);//    
	return;
}

上と同じように、このプロジェクトがほしいならこのリンクでダウンロードしてもいいです.しかし注意して、私はすでにVS 2008を舍てて、直接VS 2013を使って、もしまだ古いプラットフォームを使うならばやはりしばらく振り回さなければなりません.