pcm.h
#pragma once
#include <cstdio>
#include <cstdint>
#include <Windows.h>
#pragma comment(lib,"winmm.lib")
class pcm
{
public:
pcm();
~pcm();
void startRecording();
void endRecording();
private:
struct WavPCMFileHeader
{
struct RIFF
{
const char rift[4] = { 'R','I', 'F', 'F' };
uint32_t fileLength;
const char wave[4] = { 'W','A', 'V', 'E' };
}riff;
struct Format
{
const char fmt[4] = { 'f','m', 't', ' ' };
uint32_t blockSize = 16;
uint16_t formatTag;
uint16_t channels;
uint32_t samplesPerSec;
uint32_t avgBytesPerSec;
uint16_t blockAlign;
uint16_t bitsPerSample;
}format;
struct Data
{
const char data[4] = { 'd','a', 't', 'a' };
uint32_t dataLength;
}data;
WavPCMFileHeader() {}
WavPCMFileHeader(int nCh, int nSampleRate, int bitsPerSample, int dataSize)
{
riff.fileLength = 36 + dataSize;
format.formatTag = 1;
format.channels = nCh;
format.samplesPerSec = nSampleRate;
format.avgBytesPerSec = nSampleRate * nCh * bitsPerSample / 8;
format.blockAlign = nCh * bitsPerSample / 8;
format.bitsPerSample = bitsPerSample;
data.dataLength = dataSize;
}
};
HWAVEIN m_hWaveIn; //输入设备
WAVEFORMATEX m_waveform; //定义音频流格式
BYTE* m_pBuffer1; //输入音频缓冲区(单声道)
WAVEHDR m_whdr_i1; //输入音频头
FILE* m_pFile = nullptr;
uint32_t m_iTotalDataLength = 0;
void initRecord();
};
pcm.cpp
#include "pcm.h"
pcm::pcm()
{
initRecord();
}
void pcm::initRecord()
{
// 设置音频流格式
m_waveform.nSamplesPerSec = 16000; // 采样率
m_waveform.wBitsPerSample = 16; // 采样精度
m_waveform.nChannels = 1; // 声道个数
m_waveform.cbSize = 0; // 额外空间
m_waveform.wFormatTag = WAVE_FORMAT_PCM; // 音频格式
m_waveform.nBlockAlign = 2; // 块对齐
m_waveform.nAvgBytesPerSec = 32000; // 传输速率
//最大60秒
int buffer_len = 16000 * 16 * 60;
m_pBuffer1 = new BYTE[buffer_len];
memset(m_pBuffer1, 0, buffer_len); // 内存置0
// 设置音频头
m_whdr_i1.lpData = (LPSTR)m_pBuffer1; // 指向buffer
m_whdr_i1.dwBufferLength = buffer_len; // buffer大小
m_whdr_i1.dwBytesRecorded = 0; // buffer存放大小
m_whdr_i1.dwUser = 0;
m_whdr_i1.dwFlags = 0;
m_whdr_i1.dwLoops = 1;
}
void pcm::startRecording()
{
MMRESULT mRet = waveInOpen(&m_hWaveIn, WAVE_MAPPER, &m_waveform, (DWORD_PTR)nullptr, NULL, CALLBACK_FUNCTION);
waveInPrepareHeader(m_hWaveIn, &m_whdr_i1, sizeof(WAVEHDR));//准备buffer
waveInAddBuffer(m_hWaveIn, &m_whdr_i1, sizeof(WAVEHDR)); //添加buffer
waveInStart(m_hWaveIn);
}
void pcm::endRecording()
{
waveInReset(m_hWaveIn);
waveInClose(m_hWaveIn);
//创建时预留头部信息
if (!m_pFile)
{
m_iTotalDataLength = 0;
fopen_s(&m_pFile, "sound.pcm", "wb+");
//预留头部位置
fseek(static_cast<FILE*>(m_pFile), sizeof(WavPCMFileHeader), SEEK_SET);
}
//写入声音数据
fwrite(m_pBuffer1, 1, m_whdr_i1.dwBytesRecorded, static_cast<FILE*>(m_pFile));
m_iTotalDataLength += m_whdr_i1.dwBytesRecorded;
//关闭时写入.wav文件头部信息
if (m_pFile)
{
if (m_iTotalDataLength > 0)
{
fseek(static_cast<FILE*>(m_pFile), 0, SEEK_SET);
WavPCMFileHeader h(1, 16000, 16, m_iTotalDataLength);
fwrite(&h, 1, sizeof(h), static_cast<FILE*>(m_pFile));
}
fclose(static_cast<FILE*>(m_pFile));
m_pFile = nullptr;
}
}
pcm::~pcm()
{
if (m_pFile != nullptr)
{
delete m_pFile;
}
if (m_pBuffer1 != nullptr)
{
delete[]m_pBuffer1;
}
}
main函数调用:
#include <iostream>
#include "pcm.h"
int main()
{
pcm* p = new pcm();
int i;
std::cin >> i;
if (i == 1)
{
p->startRecording();
getchar();
}
std::cin >> i;
if (i == 2)
{
p->endRecording();
getchar();
}
}
标签:pFile,windows,i1,api,buffer,pcm,waveform,whdr
From: https://www.cnblogs.com/horizonhz/p/17614568.html