• 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;
    }
  • 相关阅读:
    干掉你的老板(小游戏)
    SEO优化数据系列表(图)
    javascript动态加载三
    javascript动态加载二
    截屏
    vimdiff
    pscp scp ftp samba windows send files to linux
    login windows 10 with passwd instead of pin
    modify requirements.txt
    整片注释 ,shell
  • 原文地址:https://www.cnblogs.com/ikodota/p/2922636.html
Copyright © 2020-2023  润新知