C语言-从声卡录音的一个demo

/*
http://sdr-reu.wikispaces.com/file/view/SoundIn.c
File to read sound from sound card and record it to a file in PCM format.
*/

#include <windows.h>
#include <mmsystem.h>
#include <stdio.h>
#include <conio.h>

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

#define IN_BUFFERS_NUMBER  4           //开辟三个数据缓冲区
#define REC_STATUS_STARTING_RECORD 1
#define REC_STATUS_RECORDING 2
#define REC_STATUS_ALL_DONE -2        //录音完成
#define REC_STATUS_FINISHING  -1      //即将完成
#define REC_STATUS_FAIL  -3
#define SIZE_OF_WAVEHDR 32            //wave头大小

//函数
void FreeBuffers(WAVEHDR * buffers);
DWORD WINAPI waveInProc(LPVOID threadControls);

typedef struct soundInDataAndControls
{
    WAVEHDR buffers[IN_BUFFERS_NUMBER];  //开辟三个数据缓冲区
    int recordingStatus;                 //录音状态
    HWAVEIN inWaveDevice;
    int buffers_left;                    //可用内存数目
}SoundThreadInfo;


WAVEFORMATEX sampleFormat; //全局变量
char *  outfilename;
HMMIO        m_hFile;
MMCKINFO    m_MMCKInfoData;
MMCKINFO    m_MMCKInfoParent;
MMCKINFO    m_MMCKInfoChild;

int main()
{
    MMRESULT errorResult = 0 ;
    SoundThreadInfo soundIn;
    HANDLE inWaveThreadHandle;                //线程
    int x = 0;                                //计数器
    soundIn.recordingStatus = 0;              //设置录音状态
    soundIn.buffers_left = IN_BUFFERS_NUMBER; //设置预期缓冲数量
    outfilename = ".\\1.wav";

    inWaveThreadHandle = CreateThread(0 ,0,(LPTHREAD_START_ROUTINE)waveInProc,/*参数*/ &soundIn, 0, &errorResult);   //创建线程
    if(!inWaveThreadHandle)
    {
        printf("Can't create sound in thread! -- %08X\n",GetLastError());
        return 0;
    }
    CloseHandle(inWaveThreadHandle);        //关闭线程

    for (x = 0; x<IN_BUFFERS_NUMBER; x++)   //清空缓存
    {
        ZeroMemory(&soundIn.buffers[x], SIZE_OF_WAVEHDR);
    }

    //设置 waveFormat
    sampleFormat.wFormatTag = WAVE_FORMAT_PCM;
    sampleFormat.nChannels = 2;  //声道
    sampleFormat.nSamplesPerSec = 44100;
    sampleFormat.wBitsPerSample = 16;
    sampleFormat.nBlockAlign =  sampleFormat.nChannels * (sampleFormat.wBitsPerSample >> 3);
    sampleFormat.nAvgBytesPerSec = sampleFormat.nSamplesPerSec * sampleFormat.nBlockAlign;

    if(!CreateWaveFile())
    {
        return getchar();
    }


    //分配 memory sound in buffers.
    for(x = 0; x < IN_BUFFERS_NUMBER; x++)  //this loop is not need after testing
    {                                        //can be replaced with hard coded buffer allocation
        //clear waveheaders
        ZeroMemory(&soundIn.buffers[x],SIZE_OF_WAVEHDR);
        soundIn.buffers[x].dwBufferLength = sampleFormat.nAvgBytesPerSec << 2;  //内存大小估计一块
        soundIn.buffers[x].dwFlags = 0;
        soundIn.buffers[x].lpData = (char *) VirtualAlloc(NULL, soundIn.buffers[0].dwBufferLength, MEM_COMMIT, PAGE_READWRITE);  //申请内存

        if(soundIn.buffers[x].lpData == NULL)
        {
            printf("Sound In Buffer number %d failed to get allocate memory.\n",x);

            for(--x;x;x--) // start 1 down, and while x!=0 x--
            {
                VirtualFree(soundIn.buffers[x].lpData, 0, MEM_RELEASE); //释放内存
            }
            return 0;
        }
        else
        {
            printf(" %d Buffer Application  sucsess\n",x);
        }
    }

    //open wave device
    errorResult = waveInOpen(&soundIn.inWaveDevice, WAVE_MAPPER, &sampleFormat, (DWORD)errorResult, 0, CALLBACK_THREAD);
    if(errorResult != MMSYSERR_NOERROR)
    {
        FreeBuffers(soundIn.buffers);
        return getchar();
    }

    // buffers and queue them
    for(x=0;x<IN_BUFFERS_NUMBER;x++)
    {
        errorResult = waveInPrepareHeader(soundIn.inWaveDevice, &soundIn.buffers[x],SIZE_OF_WAVEHDR);
        if(errorResult != MMSYSERR_NOERROR)
        {
            printf("Failed to prepare header %d. Error %d\n",x,errorResult);
            //fprintf(std,"Last was %s
            FreeBuffers(soundIn.buffers);
            errorResult= waveInClose(soundIn.inWaveDevice);
            if(errorResult)
            {
                printf("Can't Close Wave Device!\n");
                getchar();
            }
            return 0;
        }

        errorResult = waveInAddBuffer(soundIn.inWaveDevice, &soundIn.buffers[x],SIZE_OF_WAVEHDR);
        if(errorResult != MMSYSERR_NOERROR )
        {
            printf("Failed to queue wave buffer %d.\n",x);
            soundIn.buffers_left--;
            if(soundIn.buffers_left < 2)
            {
                FreeBuffers(soundIn.buffers);
                errorResult= waveInClose(soundIn.inWaveDevice);
                if(errorResult)
                {
                    printf("Can't Close Wave Device!\n");
                    getchar();
                }
                return 0;
            }

        }
    }
    //set record flag
    printf("Hit any key to begin recording.\n");
    getchar();
    soundIn.recordingStatus = 1;  //1 == starting recording

    //start recording
    errorResult = waveInStart(soundIn.inWaveDevice);
    if(errorResult == MMSYSERR_NOERROR)
    {
        //wait for user to stop recording
        printf("Hit any key to stop recording.\n");
        getchar();
        soundIn.recordingStatus = REC_STATUS_FINISHING;
    }
    else
    {
        //Recording never started.
        soundIn.recordingStatus = REC_STATUS_ALL_DONE;
    }
    //reset headers
    waveInReset(soundIn.inWaveDevice); //this should send a MM_WIM_DONE for each of the buffers/headers

    //wait thread
    while( (soundIn.recordingStatus != REC_STATUS_ALL_DONE) ) //status -2 is finished
    {
        Sleep(100); //tenth of a second
        printf("Waiting for all done.\n");
        printf("Recording status = %d\n",soundIn.recordingStatus);
    }

    //un prepare the buffers
    for(x=0;x<IN_BUFFERS_NUMBER;x++)
    {
        errorResult = waveInUnprepareHeader(soundIn.inWaveDevice, &soundIn.buffers[x], SIZE_OF_WAVEHDR);
        if(errorResult != 0)
        {
            printf("Failed to unprepare wave header.\n");
        }
    }
    //deallocate memory
    FreeBuffers(soundIn.buffers);

    mmioAscend(m_hFile, &m_MMCKInfoChild, 0);
    mmioAscend(m_hFile, &m_MMCKInfoParent, 0);

    //close wave device
    errorResult= waveInClose(soundIn.inWaveDevice);
    if(errorResult)
    {
        printf("Can't Close Wave Device!\n");
        getchar();
    }
    return getchar();
}

void FreeBuffers(WAVEHDR * buffers)
{
    int x;
    for(x=0;x<IN_BUFFERS_NUMBER;x++)
    {
        VirtualFree(buffers[x].lpData, 0, MEM_RELEASE); //zero meams all memory
    }
}

int CreateWaveFile()
{
    MMRESULT    mmResult = 0;

    ZeroMemory(&m_MMCKInfoParent,sizeof(MMCKINFO));
    ZeroMemory(&m_MMCKInfoChild,sizeof(MMCKINFO));
    ZeroMemory(&m_MMCKInfoData,sizeof(MMCKINFO));

    m_hFile = mmioOpen(outfilename,NULL, MMIO_CREATE|MMIO_WRITE|MMIO_EXCLUSIVE | MMIO_ALLOCBUF);
    if(m_hFile == NULL)
    {
        return getchar();
    }

    m_MMCKInfoParent.fccType = mmioFOURCC('W','A','V','E');
    mmResult = mmioCreateChunk( m_hFile,&m_MMCKInfoParent, MMIO_CREATERIFF);
    m_MMCKInfoChild.ckid = mmioFOURCC('f','m','t',' ');
    m_MMCKInfoChild.cksize = sizeof(WAVEFORMATEX) + sampleFormat.cbSize;
    mmResult = mmioCreateChunk(m_hFile, &m_MMCKInfoChild, 0);
    mmResult = mmioWrite(m_hFile, (char*)&sampleFormat, sizeof(WAVEFORMATEX) + sampleFormat.cbSize);
    mmResult = mmioAscend(m_hFile, &m_MMCKInfoChild, 0);
    m_MMCKInfoChild.ckid = mmioFOURCC('d', 'a', 't', 'a');
    mmResult = mmioCreateChunk(m_hFile, &m_MMCKInfoChild, 0);
    return 1;
}

DWORD WINAPI waveInProc(void *threadControls)
{
    MSG msg;
    SoundThreadInfo *inFORMATION = (SoundThreadInfo *) threadControls;
    MMRESULT errorResult;
    int outputlenth = 0;

    while(GetMessage(&msg,0,0,0)== 1)             //得到一消息
    {
        if (msg.message == MM_WIM_DATA )
        {
            printf("Data amount %d\n",((WAVEHDR *)msg.lParam)->dwBytesRecorded);
            //collect data
            if(inFORMATION->recordingStatus != 0) //recording not began or stopped只有0 ,-1 -2 三个值
            {

                if(inFORMATION->recordingStatus == REC_STATUS_ALL_DONE)
                {
                    printf("Possible error recieving WIM_DATA during condition ALL_DONE\n");
                    break;  //time for thread to end
                }

                outputlenth = mmioWrite(m_hFile, ((WAVEHDR *) msg.lParam)->lpData,((WAVEHDR *)msg.lParam)->dwBytesRecorded);
                if(outputlenth == ((WAVEHDR *)msg.lParam)->dwBytesRecorded)
                {
                    printf("sucsess save data_dwBytesRecorded %d\n",outputlenth);
                    printf("sucsess save data_dwBufferLength  %d\n",((WAVEHDR *)msg.lParam)->dwBufferLength);
                }

                //was this that last block the user wanted.
                if(inFORMATION->recordingStatus == REC_STATUS_FINISHING)
                {
                    //the buffers are each sent back, but not requeue
                    if(--inFORMATION->buffers_left == 0)
                    {
                        inFORMATION->recordingStatus = REC_STATUS_ALL_DONE;
                    }
                    printf("Buffer finished.\n");
                    continue;
                }
            }
            //if stopped it only requeue s the buffer and continues.
            //requeue buffer
            if(!waveInAddBuffer(inFORMATION->inWaveDevice, (WAVEHDR *) msg.lParam, SIZE_OF_WAVEHDR))
            {
                if(!waveInAddBuffer(inFORMATION->inWaveDevice, (WAVEHDR *) msg.lParam, SIZE_OF_WAVEHDR))
                {
                    printf("Buffer requeue error.\n");

                    if(--inFORMATION->buffers_left < 2)
                    {
                        FreeBuffers(inFORMATION->buffers);
                        printf("in requeue error device.");
                        errorResult = waveInClose(inFORMATION->inWaveDevice);
                        if(errorResult)
                        {
                            printf("Can't Close Wave Device!\n");
                            getchar();
                        }
                        return 0;
                        inFORMATION->recordingStatus = REC_STATUS_FINISHING;
                        //finishing means takes the queued blocks and no more
                        //in thoery the next block (the last one) that was queue
                        //previously
                        mmioAscend(m_hFile, &m_MMCKInfoChild, 0);
                        mmioAscend(m_hFile, &m_MMCKInfoParent, 0);
                        return -1;
                    }
                }
            }
        }
    }
    return 1;
}

 

转载于:https://www.cnblogs.com/ikodota/archive/2013/02/22/2922636.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
录音程序,可在DEC++vc++6.0编译环境下成功运行 部分代码: int main() { creat_file(); //新建文件,原文件数据被删除 RecordWave(); //录音函数 simplest_pcm16le_to_wave("NocturneNo2inEflat_44.1k_s16le.pcm", 1, 44100, "output_nocture.wav"); //将二进制录音信息从内存中提取,并生成 wav 文件 测控 1602 DEV C ++ 环境下 控制台应用程序 善解人意 成员:王帅、赵永玻、侯雅茹 3 return 0; } void RecordWave() { int count = waveInGetNumDevs(); //检测录音设备 printf("\n 音频输入数量:%d\n", count); WAVEINCAPS waveIncaps; MMRESULT mmResult = waveInGetDevCaps(0, &waveIncaps;, sizeof(WAVEINCAPS)); printf("\n 音频输入设备:%s\n", waveIncaps.szPname); if (MMSYSERR_NOERROR == mmResult) { //HWAVEIN phwi; WAVEFORMATEX pwfx; //录音格式指针 WaveInitFormat (&pwfx;, //波形声音的格式,单声道双声道使用 WAVE_FORMAT_PCM.当包含在 WAVEFORMATEXTENSIBLE 结构中时,使用 WAVE_FORMAT_EXTENSIBLE 1, //声道数量 44100, //采样率 16 // 采样位数 ); printf("\n 正在打开音频输入设备"); printf("\n 采样参数:声道 44.1kHz 16bit\n"); mmResult = waveInOpen( &phwi;, WAVE_MAPPER, &pwfx;, (DWORD)(MicCallback), NULL, CALLBACK_FUNCTION );//3 if (MMSYSERR_NOERROR == mmResult) { //WAVEHDR pwh1; char buffer1[10240]; pwh1.lpData = buffer1; pwh1.dwBufferLength = 10240; pwh1.dwUser = 1; pwh1.dwFlags = 0; 测控 1602 DEV C ++ 环境下 控制台应用程序 善解人意 成员:王帅、赵永玻、侯雅茹 4 mmResult = waveInPrepareHeader(phwi, &pwh1;, sizeof(WAVEHDR));//为波形输 入设备准备缓冲区 printf("\n 准备缓冲区 1"); //WAVEHDR pwh2; char buffer2[10240]; pwh2.lpData = buffer2; pwh2.dwBufferLength = 10240; pwh2.dwUser = 2; pwh2.dwFlags = 0; mmResult = waveInPrepareHeader(phwi, &pwh2;, sizeof(WAVEHDR));//为波形输 入设备准备缓冲区 printf("\n 准备缓冲区 2\n"); // WAVEHDR pwh3; char buffer3[10240]; pwh3.lpData = buffer3; pwh3.dwBufferLength = 10240; pwh3.dwUser = 3; pwh3.dwFlags = 0; mmResult = waveInPrepareHeader(phwi, &pwh3;, sizeof(WAVEHDR));//为波形输 入设备准备缓冲区 printf("准备缓冲区 3\n"); if (MMSYSERR_NOERROR == mmResult) { mmResult = waveInAddBuffer(phwi, &pwh1;, sizeof(WAVEHDR));//给输入设 备增加一个缓存 printf("\n 将缓冲区 1 加入音频输入设备"); mmResult = waveInAddBuffer(phwi, &pwh2;, sizeof(WAVEHDR));//给输入设 备增加一个缓存 printf("\n 将缓冲区 2 加入音频输入设备\n"); mmResult = waveInAddBuffer(phwi, &pwh3;, sizeof(WAVEHDR));//给输入设 备增加一个缓存 printf("将缓冲区 3 加入音频输入设备\n");
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值