Skip to content

Commit

Permalink
add wav codec
Browse files Browse the repository at this point in the history
  • Loading branch information
kingsunc committed Jul 25, 2017
1 parent d7bf264 commit e85187c
Show file tree
Hide file tree
Showing 10 changed files with 687 additions and 0 deletions.
32 changes: 32 additions & 0 deletions WAV_Codec/AudioInfo.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#pragma once
#include <windows.h>
#include <stdio.h>
#include <assert.h>
#include <time.h>

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

#define AUDIO_AVGBYTESPERSEC 96000
#define AUDIO_SAMPLESPERSEC 44100
#define AUDIO_CHANNELS 2
#define AUDIO_BITSPERSAMPLE 16

#define AUDIO_BUFF_MAXCOUNT 3 // 3个缓冲区;
#define AUDIO_BUFF_MAXSIZE 176400 // 每个缓冲区的最大录音数据(最大值);

class AudioInfo
{
public:
AudioInfo()
{
iAvgBytesPerSec = AUDIO_AVGBYTESPERSEC;
iChannels = AUDIO_CHANNELS;
iBitsPerSample = AUDIO_BITSPERSAMPLE;
iSamplesPerSec = AUDIO_SAMPLESPERSEC;
}

int iAvgBytesPerSec; // 码率;
int iChannels; // 通道数;
int iBitsPerSample; // 采样位数;
int iSamplesPerSec; // 采样频率;
};
122 changes: 122 additions & 0 deletions WAV_Codec/WAVDecoder.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
#include "WAVDecoder.h"

CWAVDecoder::CWAVDecoder()
{
m_bStop = true;
m_pCallBack = NULL;
}

CWAVDecoder::~CWAVDecoder()
{
}

void CWAVDecoder::SetAudioBack(OnSetAudioBuff pCallBack)
{
m_pCallBack = pCallBack;
}

void CWAVDecoder::SetAudioInfo(const AudioInfo& info)
{
m_audioInfo = info;
}

int CWAVDecoder::Start()
{
memset(&m_waveform, 0, sizeof(WAVEFORMATEX));
int iChannels = m_audioInfo.iChannels;
int iBitsPerSample = m_audioInfo.iBitsPerSample;
m_waveform.wFormatTag = WAVE_FORMAT_PCM; // 声音格式为PCM;
m_waveform.nSamplesPerSec = m_audioInfo.iSamplesPerSec; // 采样率;
m_waveform.wBitsPerSample = iBitsPerSample; // 采样比特,16bits/次;
m_waveform.nChannels = iChannels; // 采样声道数,2声道;
m_waveform.nAvgBytesPerSec = m_audioInfo.iAvgBytesPerSec; // 每秒的数据率,就是每秒能采集多少字节的数据;
m_waveform.nBlockAlign = (iChannels * iBitsPerSample) / 8; // 一个块的大小,采样bit的bits数乘以声道数/8;
m_waveform.cbSize = 0; // 额外外信息大小, 一般为0;

// 打开设备;
MMRESULT iRes = waveOutOpen(&m_hWaveOut, WAVE_MAPPER, &m_waveform, (DWORD)(WaveOutProc), (DWORD)this, CALLBACK_FUNCTION);
if (iRes != 0)
{
printf("open waveIn err!\n");
exit(0);
}

for (int i = 0; i < AUDIO_BUFF_MAXCOUNT; i++) // 设置内存块格式;
{
m_arrHdr[i].lpData = m_BuffOut[i];
m_arrHdr[i].dwBufferLength = AUDIO_BUFF_MAXSIZE;
m_arrHdr[i].dwBytesRecorded = 0;
m_arrHdr[i].dwUser = i;
m_arrHdr[i].dwFlags = 0;
waveOutPrepareHeader(m_hWaveOut, &m_arrHdr[i], sizeof(WAVEHDR)); // 准备内存块录音;
waveOutWrite(m_hWaveOut, &m_arrHdr[i], sizeof(WAVEHDR)); // 增加内存块;
}

m_bStop = false;

return 0;
}

int CWAVDecoder::Stop()
{
// 此处不能释放, 去线程结束时释放;
m_bStop = true;

return 0;
}

DWORD CALLBACK CWAVDecoder::WaveOutProc(HWAVEIN hwi, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2)
{
CWAVDecoder* pThis = reinterpret_cast<CWAVDecoder*>(dwInstance);
assert(pThis);

if (uMsg == WOM_DONE)
{
WAVEHDR*p = (WAVEHDR*)dwParam1;
int i = p->dwUser;
waveOutUnprepareHeader(pThis->m_hWaveOut, p, sizeof(WAVEHDR));

int iDataSize = 0;
if (pThis->m_pCallBack)
{
iDataSize = pThis->m_pCallBack(pThis->m_BuffOut[i], AUDIO_BUFF_MAXSIZE);
}
if (iDataSize < AUDIO_BUFF_MAXSIZE)
{
printf("play over!\n");
pThis->m_bStop = true;
return 0;
}

p->lpData = pThis->m_BuffOut[i];
p->dwBufferLength = iDataSize;
p->dwBytesRecorded = 0;
p->dwUser = i;
p->dwFlags = 0;

waveOutPrepareHeader(pThis->m_hWaveOut, p, sizeof(WAVEHDR)); //准备内存块录音
waveOutWrite(pThis->m_hWaveOut, p, sizeof(WAVEHDR));
}
if (uMsg == WOM_OPEN)
{
printf("wom open\n");
}
if (uMsg == WOM_CLOSE)
{
printf("wom close\n");
}
return 0;
}

int CWAVDecoder::Clear()
{
waveOutRestart(m_hWaveOut);
for (int i = 0; i < AUDIO_BUFF_MAXCOUNT; i++)
{
waveOutUnprepareHeader(m_hWaveOut, &m_arrHdr[i], sizeof(WAVEHDR));
}
printf("Start Close\n");
waveOutClose(m_hWaveOut);

return 1;
}
32 changes: 32 additions & 0 deletions WAV_Codec/WAVDecoder.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#pragma once
#include "AudioInfo.h"

// 获取AudioBuff的回调函数 原始PCM数据;
typedef int(*OnSetAudioBuff)(char* pBuff, int iBuffSize);

class CWAVDecoder
{
public:
CWAVDecoder();
~CWAVDecoder();

void SetAudioBack(OnSetAudioBuff pCallBack);
void SetAudioInfo(const AudioInfo& info);

int Start();
int Stop();
int Clear();

// 回调函数,需要时由外部传入数据;
static DWORD CALLBACK WaveOutProc(HWAVEIN hwi, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2);

private:
bool m_bStop;
AudioInfo m_audioInfo;

HWAVEOUT m_hWaveOut; // 输出设备;
WAVEFORMATEX m_waveform; // 采集音频的格式,结构体;
WAVEHDR m_arrHdr[AUDIO_BUFF_MAXCOUNT]; // 采集音频时包含数据缓存的结构体;
char m_BuffOut[AUDIO_BUFF_MAXCOUNT][AUDIO_BUFF_MAXSIZE];
OnSetAudioBuff m_pCallBack;
};
124 changes: 124 additions & 0 deletions WAV_Codec/WAVEncoder.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
#include "WAVEncoder.h"

CWAVEncoder::CWAVEncoder()
{
m_bStop = true;
m_pCallBack = NULL;
}

CWAVEncoder::~CWAVEncoder()
{
}

void CWAVEncoder::SetAudioBack(OnGetAudioBuff pCallBack)
{
m_pCallBack = pCallBack;
}

void CWAVEncoder::SetAudioInfo(const AudioInfo& info)
{
m_audioInfo = info;
}

int CWAVEncoder::Start()
{
memset(&waveform, 0, sizeof(WAVEFORMATEX));
int iChannels = m_audioInfo.iChannels;
int iBitsPerSample = m_audioInfo.iBitsPerSample;
waveform.wFormatTag = WAVE_FORMAT_PCM; // 声音格式为PCM;
waveform.nSamplesPerSec = m_audioInfo.iSamplesPerSec; // 采样率;
waveform.wBitsPerSample = iBitsPerSample; // 采样比特,16bits/次;
waveform.nChannels = iChannels; // 采样声道数,2声道;
waveform.nAvgBytesPerSec = m_audioInfo.iAvgBytesPerSec; // 每秒的数据率,就是每秒能采集多少字节的数据;
waveform.nBlockAlign = (iChannels * iBitsPerSample) / 8; // 一个块的大小,采样bit的bits数乘以声道数/8;
waveform.cbSize = 0; // 额外外信息大小, 一般为0;

// 打开设备;
MMRESULT iRes = waveInOpen(&hWaveIn, WAVE_MAPPER, &waveform, (DWORD)(WaveInProc), (DWORD)this, CALLBACK_FUNCTION);
if (iRes != 0)
{
printf("open waveIn err!\n");
exit(0);
}
unsigned int iWaveID = -1;
waveInGetID(hWaveIn, &iWaveID); // 你所使用的输入设备ID,-1为默认;
printf("you use waveid: %d \n", iWaveID);

for (int i = 0; i < AUDIO_BUFF_MAXCOUNT; i++) // 设置内存块格式;
{
wHdr[i].lpData = chBuff[i];
wHdr[i].dwBufferLength = AUDIO_BUFF_MAXSIZE;
wHdr[i].dwBytesRecorded = 0;
wHdr[i].dwUser = i;
wHdr[i].dwFlags = 0;
waveInPrepareHeader(hWaveIn, &wHdr[i], sizeof(WAVEHDR)); // 准备内存块录音;
waveInAddBuffer(hWaveIn, &wHdr[i], sizeof(WAVEHDR)); // 增加内存块;
}

m_bStop = false;
waveInStart(hWaveIn); //开始录音;

return 0;
}

int CWAVEncoder::Stop()
{
// 此处不能释放, 去线程结束时释放;
m_bStop = true;

return 0;
}

DWORD CALLBACK CWAVEncoder::WaveInProc(HWAVEIN hwi, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2)
{
CWAVEncoder* pThis = reinterpret_cast<CWAVEncoder*>(dwInstance);
assert(pThis);

if (uMsg == WIM_DATA)
{
WAVEHDR* p = (WAVEHDR*)dwParam1; // dwParam1指向WAVEHDR的地址;
printf("getdate id: %d size:%d timestemp:%d\n", p->dwUser, p->dwBytesRecorded, clock());
int iIndex = p->dwUser;
if (pThis->m_bStop) //0表示停止了
{
waveInUnprepareHeader(pThis->hWaveIn, p, sizeof(WAVEHDR)); // 释放;
return 0;
}
else
{
if (pThis->m_pCallBack)
{
pThis->m_pCallBack(pThis->chBuff[iIndex], p->dwBytesRecorded);
}
waveInUnprepareHeader(pThis->hWaveIn, p, sizeof(WAVEHDR)); // 释放;
}
p->lpData = pThis->chBuff[iIndex];
p->dwBufferLength = AUDIO_BUFF_MAXSIZE;
p->dwBytesRecorded = 0;
p->dwUser = iIndex;
p->dwFlags = 0;
waveInPrepareHeader(pThis->hWaveIn, p, sizeof(WAVEHDR)); // 准备内存块录音;
waveInAddBuffer(pThis->hWaveIn, p, sizeof(WAVEHDR)); // 增加内存块;
}
if (uMsg == WIM_OPEN)
{
printf("open\n");
}
if (uMsg == WIM_CLOSE)
{
printf("close\n");
}
return 0;
}

int CWAVEncoder::Clear()
{
printf("Start Stop\n");
waveInStop(hWaveIn);
printf("Start Reset\n");
waveInReset(hWaveIn);
printf("Start Close\n");
waveInClose(hWaveIn);

return 1;
}
34 changes: 34 additions & 0 deletions WAV_Codec/WAVEncoder.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#pragma once
#include <windows.h>
#include <stdio.h>
#include "AudioInfo.h"

// 获取AudioBuff的回调函数 原始PCM数据;
typedef int(*OnGetAudioBuff)(const char* pBuff, const int& iBuffSize);

class CWAVEncoder
{
public:
CWAVEncoder();
~CWAVEncoder();

void SetAudioBack(OnGetAudioBuff pCallBack);
void SetAudioInfo(const AudioInfo& info);

int Start();
int Stop();
int Clear();

// 回调函数,当缓冲区录满就会调用该函数;
static DWORD CALLBACK WaveInProc(HWAVEIN hwi, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2);

private:
bool m_bStop;
AudioInfo m_audioInfo;

HWAVEIN hWaveIn; // 输入设备;
WAVEFORMATEX waveform; // 采集音频的格式,结构体;
WAVEHDR wHdr[AUDIO_BUFF_MAXCOUNT]; // 采集音频时包含数据缓存的结构体;
char chBuff[AUDIO_BUFF_MAXCOUNT][AUDIO_BUFF_MAXSIZE];
OnGetAudioBuff m_pCallBack;
};
22 changes: 22 additions & 0 deletions WAV_Codec/WAV_Codec.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013
VisualStudioVersion = 12.0.21005.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WAV_Codec", "WAV_Codec.vcxproj", "{015D9418-85CA-4049-8BD0-2FE794F991BB}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{015D9418-85CA-4049-8BD0-2FE794F991BB}.Debug|Win32.ActiveCfg = Debug|Win32
{015D9418-85CA-4049-8BD0-2FE794F991BB}.Debug|Win32.Build.0 = Debug|Win32
{015D9418-85CA-4049-8BD0-2FE794F991BB}.Release|Win32.ActiveCfg = Release|Win32
{015D9418-85CA-4049-8BD0-2FE794F991BB}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
Loading

0 comments on commit e85187c

Please sign in to comment.