自己关于写wave音频文件得源代码(备忘录)

头文件:SoundRecord.h
#ifndef _SOUND_RECORD_H__
#define _SOUND_RECORD_H__
#include <Windows.h>
#include <mmsystem.h>
#include <string>

#define MAX_BUFFERS 3
#define m_samplefreq 44100  //采样频率
#define m_channels 2        //通道数
#define m_channelbits 8     //通道字节数

class CSoundRecord
{
public:
    CSoundRecord(void);
    ~CSoundRecord(void);
    void startRecording(float time);
    void stopRecording();
private:
    void printStartInfo(std::string Tip,int time);
    void printEndInfo();
    static void CALLBACK waveInProc(HWAVEIN hwi, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1,DWORD_PTR dwParam2);
    bool initDevice();

    void prepareBuffers();
    void unPrepareBuffers();
    void closeDevice();
    void processHeader(WAVEHDR * pHdr);
private:
    bool m_bPlay;
    HWAVEIN m_hWaveIn;
    WAVEFORMATEX m_stWFEX;
    WAVEHDR m_stWHDR[MAX_BUFFERS];
    HANDLE m_hThread;
    HMMIO m_hOPFile;
    MMIOINFO m_stmmIF;
    MMCKINFO m_stckOut,m_stckOutRIFF;
    std::string m_FileName;
    int    m_Time;

};

#endif  // _SOUND_RECORD_H__
//源文件:SoundRecord.cpp
#include "SoundRecord.h"
#include <iostream>



CSoundRecord::CSoundRecord(void):m_bPlay(false),
                                 m_Time(0),
                                 m_hOPFile(nullptr)
{
    m_hWaveIn=NULL;
    ZeroMemory(&m_stWFEX,sizeof(WAVEFORMATEX));
    ZeroMemory(m_stWHDR,MAX_BUFFERS*sizeof(WAVEHDR));
}


CSoundRecord::~CSoundRecord(void)
{
}

bool CSoundRecord::initDevice()
{
    MMRESULT mRes=0;
    int nT1=0;
    //填充数据头结构体
    m_stWFEX.nSamplesPerSec =  m_samplefreq;
    m_stWFEX.nAvgBytesPerSec =   m_samplefreq * m_channels * m_channelbits / 8;//每秒所需字节数
    m_stWFEX.nBlockAlign =   m_channels * m_channelbits / 8;//一个采样的字节数
    m_stWFEX.nChannels = m_channels; //1为单通道,2为双通道
    m_stWFEX.wFormatTag =  0x0001;//编码方式
    m_stWFEX.wBitsPerSample =   m_channelbits;//16位,即设置PCM的方式为16位立体声(双通道)
    m_stWFEX.cbSize = sizeof(WAVEFORMATEX);

    mRes=waveInOpen(&m_hWaveIn,WAVE_MAPPER,&m_stWFEX,(DWORD_PTR)waveInProc,(DWORD_PTR)this,CALLBACK_FUNCTION);
    if(mRes!=MMSYSERR_NOERROR)
    {
        std::cout << "打开音频设备失败...." << std::endl;
        return false;
    }
    //新建存储文件
    //设置保存的音频文件名称
    SYSTEMTIME sysTime; 
    GetLocalTime( &sysTime ); 
    char fileName[512];
    memset(fileName,0,512);
    sprintf_s(fileName,"%d_%d_%d_%d_%d_%d.wav",sysTime.wYear,sysTime.wMonth,sysTime.wDay,sysTime.wHour,sysTime.wMinute,sysTime.wSecond);
    ZeroMemory(&m_stmmIF,sizeof(MMIOINFO));
    //转换 stringTolpwstr
    m_FileName = fileName;
    std::wstring widstr;   
    widstr = std::wstring(m_FileName.begin(), m_FileName.end());  
    LPWSTR ff = (LPWSTR)widstr.c_str();

    m_hOPFile=mmioOpen(ff,&m_stmmIF,MMIO_WRITE | MMIO_CREATE);
    if(m_hOPFile==NULL)
    {
        std::cout <<  "创建文件失败..." << std::endl;
        return false;
    }
    ZeroMemory(&m_stckOutRIFF,sizeof(MMCKINFO));
    m_stckOutRIFF.fccType = mmioFOURCC('W', 'A', 'V', 'E'); 
    mRes=mmioCreateChunk(m_hOPFile, &m_stckOutRIFF, MMIO_CREATERIFF);
    if(mRes!=MMSYSERR_NOERROR)
    {
         std::cout << "创建RIFF-WAVE数据块失败" << std::endl;
    }
    ZeroMemory(&m_stckOut,sizeof(MMCKINFO));
    m_stckOut.ckid = mmioFOURCC('f', 'm', 't', ' ');
    m_stckOut.cksize = sizeof(m_stWFEX);
    mRes=mmioCreateChunk(m_hOPFile, &m_stckOut, 0);
    if(mRes!=MMSYSERR_NOERROR)
    {
        std::cout << "创建fmt数据块失败" << std::endl;     
    }
    nT1=mmioWrite(m_hOPFile, (HPSTR) &m_stWFEX, sizeof(m_stWFEX));
    if(nT1!=sizeof(m_stWFEX))
    {
        std::cout << "写音频数据格式失败" << std::endl;              
    }
    mRes=mmioAscend(m_hOPFile, &m_stckOut, 0);
    if(mRes!=MMSYSERR_NOERROR)
    {
        std::cout << "升序排列数据" << std::endl;             
    }
    m_stckOut.ckid = mmioFOURCC('d', 'a', 't', 'a');
    mRes=mmioCreateChunk(m_hOPFile, &m_stckOut, 0);
    if(mRes!=MMSYSERR_NOERROR)
    {
        std::cout << "创建data数据块失败" << std::endl;                
    }
}

void CSoundRecord::closeDevice()
{
    MMRESULT mRes=0;

    if(m_hWaveIn)
    {
        unPrepareBuffers();
        mRes=waveInClose(m_hWaveIn);
    }
    if(m_hOPFile)
    {
        mRes=mmioAscend(m_hOPFile, &m_stckOut, 0);
        if(mRes!=MMSYSERR_NOERROR)
        {
            std::cout << "重定向音频头数据失败" << std::endl;
            return ;
        }
        mRes=mmioAscend(m_hOPFile, &m_stckOutRIFF, 0);
        if(mRes!=MMSYSERR_NOERROR)
        {
            std::cout << "重定向音频数据头失败" << std::endl;
            return ;
        }
        mmioClose(m_hOPFile,0);
        m_hOPFile=NULL;
    }
    m_hWaveIn=NULL;
}

void CSoundRecord::prepareBuffers()
{
    MMRESULT mRes=0;


    for(int nT1=0;nT1<MAX_BUFFERS;++nT1)
    {
        m_stWHDR[nT1].lpData=(LPSTR)HeapAlloc(GetProcessHeap(),8,m_stWFEX.nAvgBytesPerSec);
        m_stWHDR[nT1].dwBufferLength=m_stWFEX.nAvgBytesPerSec;
        m_stWHDR[nT1].dwUser=nT1;
        mRes=waveInPrepareHeader(m_hWaveIn,&m_stWHDR[nT1],sizeof(WAVEHDR));
        if(mRes!=0)
        {
            std::cout << "准备头部数据失败" << std::endl;
            return ;
        }
        mRes=waveInAddBuffer(m_hWaveIn,&m_stWHDR[nT1],sizeof(WAVEHDR));
        if(mRes!=0)
        {
            std::cout << "准备缓存数据失败" << std::endl;
            return ;
        }
    }
}


void CSoundRecord::startRecording(float time)
{
    MMRESULT mRes;
    m_bPlay = true;
    m_Time = time;
    try
    {
        initDevice();
        prepareBuffers();
        mRes=waveInStart(m_hWaveIn);
        if(mRes!=0)
        {
            std::cout << "无法进行录音" << std::endl;
        }
        while(m_bPlay)
        {
            static int i = 0;
            printStartInfo("录音开始",i);
            SleepEx(100,FALSE);
            i++;
        }
    }
    catch(PCHAR pErrorMsg)
    {
          std::cout << "异常---->"<< pErrorMsg << std::endl;
    }
    closeDevice();
    printEndInfo();
}

void CSoundRecord::stopRecording()
{
    m_bPlay = false;
}

void CALLBACK CSoundRecord::waveInProc(HWAVEIN hwi, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1,DWORD_PTR dwParam2)
{
    static int count = 0;
    CSoundRecord *pSoundRecord = (CSoundRecord*)dwInstance;
    if(!pSoundRecord)
        return ;
     WAVEHDR* hdr = (WAVEHDR*)dwParam1;
    if(pSoundRecord->m_Time == count)
    {
        pSoundRecord->stopRecording();
    }
    if(uMsg == WIM_DATA)
    {

        pSoundRecord->processHeader(hdr);


        count++;
    }

}

void CSoundRecord::processHeader(WAVEHDR * pHdr)
{
    MMRESULT mRes=0;


    if(WHDR_DONE==(WHDR_DONE &pHdr->dwFlags))
    {
        mmioWrite(m_hOPFile,pHdr->lpData,pHdr->dwBytesRecorded);
        mRes=waveInAddBuffer(m_hWaveIn,pHdr,sizeof(WAVEHDR));
        if(mRes!=0)
        {
            std::cout << "file: " << __FILE__ << "Line Number: " << __LINE__ << std::endl; 
        }
    }
}

void CSoundRecord::unPrepareBuffers()
{
    MMRESULT mRes=0;
    int nT1=0;

    if(m_hWaveIn)
    {
        mRes=waveInStop(m_hWaveIn);
        for(nT1=0;nT1<3;++nT1)
        {
            if(m_stWHDR[nT1].lpData)
            {
                mRes=waveInUnprepareHeader(m_hWaveIn,&m_stWHDR[nT1],sizeof(WAVEHDR));
                HeapFree(GetProcessHeap(),0,m_stWHDR[nT1].lpData);
                ZeroMemory(&m_stWHDR[nT1],sizeof(WAVEHDR));
            }
        }
    }
}


void CSoundRecord::printStartInfo(std::string Tip,int time)
{
    static bool bfirst = true;
    if(bfirst)
    {
        std::cout << "************************"<< std::endl;
        std::cout << Tip << std::endl;
        bfirst = false;
    }
    COORD coord = { 0, 4 };
    CONSOLE_SCREEN_BUFFER_INFO info;
    GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &info);

    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
    float per = (float)time / 100;
    std::cout<<"录音进度: "<< per << " %";

    //Sleep(100);
    std::cout << std::endl;


}

void CSoundRecord::printEndInfo()
{
    CONSOLE_SCREEN_BUFFER_INFO info;
    GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &info);
    std::cout<<"录音结束"<<std::endl;
    std::cout << "************************"<< std::endl;
    COORD coord1 = { 0, 8} ;
    info.dwCursorPosition =  coord1;
    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), info.dwCursorPosition);
}
调用: main
 CSoundRecord* pSound = new CSoundRecord;

   std::cout << "请输入时间,单位:秒" << std::endl;
   int time;
   std::cin >> time;
   pSound->startRecording(time);//时间单位:秒

结果图:
这里写图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值