windows音频PCM采集及简单编码

音频编码方式采用G711(应该是a-law,不确认),音频需要16位量化,8位量化编码音频失真。


#include <stdio.h>    
#include <Windows.h>    
#pragma comment(lib, "winmm.lib")    

#define MAX (32635)
unsigned char encode(short pcm)
{
int sign = (pcm & 0x8000) >> 8;
if (sign != 0)
pcm = -pcm;
if (pcm > MAX) pcm = MAX;
int exponent = 7;
int expMask;
for (expMask = 0x4000; (pcm & expMask) == 0 
&& exponent>0; exponent--, expMask >>= 1) { }
int mantissa = (pcm >> ((exponent == 0) ? 4 : (exponent + 3))) & 0x0f;
unsigned char alaw = (unsigned char)(sign | exponent << 4 | mantissa);
return (unsigned char)(alaw^0xD5);
}

short decode(unsigned char alaw)
{
alaw ^= 0xD5;
int sign = alaw & 0x80;
int exponent = (alaw & 0x70) >> 4;
int data = alaw & 0x0f;
data <<= 4;
data += 8;
if (exponent != 0)
data += 0x100;
if (exponent > 1)
data <<= (exponent - 1);

return (short)(sign == 0 ? data : -data);
}


//编码
int G711_EnCode(unsigned char* pCodecBits, const unsigned char* pBuffer, int nBufferSize)
{
short* buffer = (short*)pBuffer;
for(int i=0; i<nBufferSize/2; i++)
{
pCodecBits[i] = encode(buffer[i]);
}

return nBufferSize/2;



//解码
int G711_Decode(unsigned char* pRawData, const unsigned char* pBuffer, int nBufferSize)
{
short *out_data = (short*)pRawData;
for(int i=0; i<nBufferSize; i++)
{
out_data[i] = decode(pBuffer[i]);
}

return nBufferSize*2;
}


HWAVEIN hWaveIn;  //输入设备  
WAVEFORMATEX waveform; //采集音频的格式,结构体  
BYTE *pBuffer1;//采集音频时的数据缓存  
WAVEHDR wHdr1; //采集音频时包含数据缓存的结构体  
FILE *pf;  
int main(int argc, char * argv[])  
{  
    HANDLE          wait;  
    waveform.wFormatTag = WAVE_FORMAT_PCM;//声音格式为PCM  
    waveform.nSamplesPerSec = 8000;//采样率,16000次/秒  
    waveform.wBitsPerSample = 16;//采样比特,16bits/次  
    waveform.nChannels = 1;//采样声道数,1为单声道,2为双声道  
    waveform.nAvgBytesPerSec = 16000;//每秒的数据率,就是每秒能采集多少字节的数据 
    waveform.nBlockAlign = 2;//一个块的大小,采样bit的字节数乘以声道数  再除以8
    waveform.cbSize = 0;//一般为0  

    wait = CreateEvent(NULL, 0, 0, NULL);  
    //使用waveInOpen函数开启音频采集  
    MMRESULT Result = waveInOpen(&hWaveIn, WAVE_MAPPER, &waveform,(DWORD)wait, 0L, CALLBACK_EVENT);  
if (MMSYSERR_NOERROR  == Result)
{
printf("Open Wave Success!\n");
}
else if (MMSYSERR_INVALHANDLE == Result)
{
printf("Get MMSYSERR_INVALHANDLE Error\n");

return 0;
}
else if (MMSYSERR_NODRIVER == Result)
{
printf("No Driver!\n");

return 0;
}
else if (MMSYSERR_NOMEM == Result)
{
printf("No Mem!\n");

return 0;
}


    //建立两个数组(这里可以建立多个数组)用来缓冲音频数据  
    DWORD bufsize = 1024*1000;//每次开辟10k的缓存存储录音数据  
    int i = 20;  

pf= fopen("录音测试.pcm", "wb");  
FILE *pfEn = fopen("编码.pcm", "wb");
FILE *pfDe = fopen("解码.pcm", "wb");
    while (i--)//录制20左右秒声音,结合音频解码和网络传输可以修改为实时录音播放的机制以实现对讲功能  
    {  
        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);//停止录音  
unsigned char *pData = new unsigned char[bufsize];
unsigned char *pDataDe = new unsigned char[bufsize];
memset(pData,0, sizeof(pData));
int nRet = G711_EnCode(pData, pBuffer1, wHdr1.dwBytesRecorded);

        fwrite(pBuffer1, 1, wHdr1.dwBytesRecorded, pf);  
fwrite(pData, 1, nRet, pfEn);  
int nTemp = nRet;
nRet = G711_Decode(pDataDe, pData, nTemp);
fwrite(pDataDe, 1, nRet, pfDe);  

        delete pBuffer1;   
delete pData;
delete pDataDe;
        printf("%ds  ", i);  
    }  
    fclose(pf);  

    waveInClose(hWaveIn);  
    return 0;  
}  

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值