簡單裸流pcm聲音的錄制和播放


一、裸流pcm文件的錄制源碼

#include "stdafx.h"
#include <stdio.h>
#include <Windows.h>
//使用了windows的“winmm.lib”自帶的庫
#pragma comment(lib,"winmm.lib")

HWAVEIN hWaveIn;                                        //輸入設備
WAVEFORMATEX waveform;                                    //采樣音頻的格式,結構體
BYTE *pBuffer1;                                            //采樣音頻時的數據緩存
WAVEHDR wHdr1;                                            //采樣音頻時包含數據緩存的結構體
FILE *pf;

//unicode版的main函數,由windows定義
int _tmain(int argc, _TCHAR* argv[])
{
    HANDLE wait;
    waveform.wFormatTag = WAVE_FORMAT_PCM;                //聲音格式為PCM
    waveform.nSamplesPerSec = 8000;                        //采樣率,8000次/秒
    waveform.wBitsPerSample = 16;                        //采樣比特,16bits/次
    waveform.nChannels = 1;                                //采樣聲道數

    waveform.nAvgBytesPerSec = 16000;                    //每秒的數據率,就是每秒能采集多少自己的數據
    waveform.nBlockAlign = 2;                            //一個塊的大小,采樣bit的字節數乘以聲道數
    waveform.cbSize = 0;                                //一般為0;
    wait = CreateEvent(NULL,0,0,NULL);

    //使用waveInOpen函數開啟音頻采集
    waveInOpen(&hWaveIn, WAVE_MAPPER, &waveform, (DWORD_PTR)wait, 0L, CALLBACK_EVENT);
    //建立兩個數組(這里可以建立多個數組)用來緩沖音頻數據
    DWORD bufsize = 1024 * 100;                            //每次開辟10k的緩存存儲錄音數據
    int i = 20;
    fopen_s(&pf,"錄音測試。pcm","wb");
    
    //錄制20秒左右聲音,結合音頻解碼和網絡傳輸,可以修改為實時錄音播放的機制以實現對講功能
    while (i--)
    {
        pBuffer1 = new BYTE[bufsize];
        wHdr1.lpData = (LPSTR)pBuffer1;
        wHdr1.dwBufferLength = bufsize;
        wHdr1.dwBytesRecorded = 0;
        wHdr1.dwUser = 0;
        wHdr1.dwFlags = 0;
        wHdr1.dwLoops = 1;
        waveInPrepareHeader(hWaveIn, &wHdr1, sizeof(WAVEHDR));//准備一個波形數據塊頭用於錄音
        waveInAddBuffer(hWaveIn, &wHdr1, sizeof(WAVEHDR));//指定波形數據塊為錄音輸入緩存
        waveInStart(hWaveIn);//開始錄音
        Sleep(1000);//等待聲音錄制1s
        waveInReset(hWaveIn);//停止錄音
        fwrite(pBuffer1, 1, wHdr1.dwBytesRecorded, pf);
        delete pBuffer1;
        printf("%ds  ", i);
    }
    fclose(pf);

    waveInClose(hWaveIn);
    return 0;
}
View Code

 

源碼的使用在工程中有時需要加上mmeapi.h的頭文件(不同的vs,在不同的頭文件中)

 

二、裸流pcm文件的播放源碼

 

#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;
}
View Code

 

 

 

原文:https ://blog.csdn.net/weixinhum/article/details/31155985 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM