linux c语言录音程序,windows C语言录音

不怎么喜欢windows,一个windows创建线程的API让我找了半天,在linux上分分钟的事。。。但由于需要用,所以。。。。

我在代码中写了注释,看懂应该没问题。

代码如下:程序作用在当前目录下,产生一个test.wav的音频文件保存录音。

#include 

#include 

#include 

#include 

#include 

#include 

#include 

#include 

#include "mmsystem.h"

#include 

#include 

#include 

#pragma comment(lib, "winmm.lib")//必须包含这个lib

#define BUFFSIZE 1024 * 1024 //环形缓冲区的大小,你可以定义大一些

/*WAV音频文件头*/

#define LENGTH    10   //录音时间,秒

#define RATE    16000 //采样频率

#define SIZE    16   //量化位数

#define CHANNELS 1   //声道数目

#define RSIZE    8    //buf的大小,

#defineBUFFER_SIZE4096

#define FRAME_LEN640

#define HINTS_SIZE  100

//#define min(x, y) ((x) 

typedef int SR_DWORD;

typedef short int SR_WORD ;

typedef long long SR_LWORD;

//wav的音频头

typedef struct wave_pcm_hdr

{

char                riff[4];               // = "RIFF"

SR_DWORDsize_8;              // = FileSize - 8

char                wave[4];            // = "WAVE"

char                fmt[4];          // = "fmt "

SR_DWORDdwFmtSize;        // = 下一个结构体的大小 : 16

SR_WORDformat_tag;        // = PCM : 1

SR_WORDchannels;               // = 通道数 : 1

SR_DWORDsamples_per_sec;        // = 采样率

SR_DWORDavg_bytes_per_sec;        // = 每秒字节数

SR_WORDblock_align;              // = 每采样点字节数

SR_WORDbits_per_sample;        // = 量化比特数: 8 | 16

char                data[4];                    // = "data";

SR_DWORDdata_size;        // = 纯数据长度 : FileSize - 44

} wave_header;

//默认音频头部数据

struct wave_pcm_hdr wav_hdr=

{

{ 'R', 'I', 'F', 'F' },

LENGTH*RATE*CHANNELS*SIZE/8+36,

{'W', 'A', 'V', 'E'},

{'f', 'm', 't', ' '},

16,

1,

CHANNELS,

RATE,

RATE*CHANNELS*SIZE/8,

CHANNELS*SIZE/8,

SIZE,

{'d', 'a', 't', 'a'},

LENGTH*RATE*CHANNELS*SIZE/8

};

//环形缓冲区的的数据结构

struct cycle_buffer {

char *buf;

unsigned int size;

unsigned int in;

unsigned int out;

};

static struct cycle_buffer *fifo = NULL;//定义全局FIFO

FILE *fp;

CRITICAL_SECTION cs;

//初始化环形缓冲区

static int init_cycle_buffer(void)

{

int size = BUFFSIZE, ret;

ret = size & (size - 1);

if (ret)

return ret;

fifo = (struct cycle_buffer *) malloc(sizeof(struct cycle_buffer));

if (!fifo)

return -1;

memset(fifo, 0, sizeof(struct cycle_buffer));

fifo->size = size;

fifo->in = fifo->out = 0;

fifo->buf = (char *) malloc(size);

if (!fifo->buf)

free(fifo);

else

memset(fifo->buf, 0, size);

return 0;

}

unsigned int fifo_get(char *buf, unsigned int len)  //从环形缓冲区中取数据

{

unsigned int l;

len = min(len, fifo->in - fifo->out);

l = min(len, fifo->size - (fifo->out & (fifo->size - 1)));

memcpy(buf, fifo->buf + (fifo->out & (fifo->size - 1)), l);

memcpy(buf + l, fifo->buf, len - l);

fifo->out += len;

return len;

}

unsigned int fifo_put(char *buf, unsigned int len) //将数据放入环形缓冲区

{

unsigned int l;

len = min(len, fifo->size - fifo->in + fifo->out);

l = min(len, fifo->size - (fifo->in & (fifo->size - 1)));

memcpy(fifo->buf + (fifo->in & (fifo->size - 1)), buf, l);

memcpy(fifo->buf, buf + l, len - l);

fifo->in += len;

return len;

}

void WaveInitFormat(LPWAVEFORMATEX m_WaveFormat, WORD nCh,DWORD nSampleRate,WORD BitsPerSample)//初始化音频格式

{

m_WaveFormat->wFormatTag = WAVE_FORMAT_PCM;

m_WaveFormat->nChannels = nCh;

m_WaveFormat->nSamplesPerSec = nSampleRate;

m_WaveFormat->nAvgBytesPerSec = nSampleRate * nCh * BitsPerSample/8;

m_WaveFormat->nBlockAlign = m_WaveFormat->nChannels * BitsPerSample/8;

m_WaveFormat->wBitsPerSample = BitsPerSample;

m_WaveFormat->cbSize = 0;

}

DWORD CALLBACK MicCallback(HWAVEIN hwavein, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2)//回调函数当数据缓冲区慢的时候就会触发,回调函数,执行下面的RecordWave函数之后相当于创建了一个线程

{

int len=0;

switch(uMsg)

{

case WIM_OPEN://打开设备时这个分支会执行。

printf("\n设备已经打开...\n");

break;

case WIM_DATA://当缓冲区满的时候这个分支会执行,不要再这个分支中出现阻塞语句,会丢数据,waveform audio本身没有缓冲机制。

printf("\n缓冲区%d存满...\n",((LPWAVEHDR)dwParam1)->dwUser);

waveInAddBuffer(hwavein, (LPWAVEHDR)dwParam1, sizeof(WAVEHDR));

EnterCriticalSection(&cs); //进入临界区

len=fifo_put(((LPWAVEHDR)dwParam1)->lpData, 10240);将缓冲区的数据写入环形fifo

LeaveCriticalSection(&cs);//退出临界区

//fwrite(((LPWAVEHDR)dwParam1)->lpData,10240, 1, fp);

//printf("lens=%d", len);

break;

case WIM_CLOSE:

printf("\n设备已经关闭...\n");

break;

default:

break;

}

return 0;

}

void RecordWave()

{

HWAVEIN phwi;

WAVEINCAPS waveIncaps;

int count=0;

MMRESULT mmResult;

count= waveInGetNumDevs();//获取系统有多少个声卡

mmResult = waveInGetDevCaps(0, &waveIncaps, sizeof(WAVEINCAPS));//查看系统声卡设备参数,不用太在意这两个函数。

printf("\ncount = %d\n", count);

printf("\nwaveIncaps.szPname=%s\n",waveIncaps.szPname);

if(MMSYSERR_NOERROR==mmResult)

{

WAVEFORMATEX pwfx;

WaveInitFormat(&pwfx,1,16000,16);

printf("\n请求打开音频输入设备");

printf("\n采样参数:单声道 8kHz 8bit\n");

mmResult=waveInOpen(&phwi,WAVE_MAPPER,&pwfx,(DWORD)(MicCallback),NULL,CALLBACK_FUNCTION);//打开音频设备,设置回调函数

if(MMSYSERR_NOERROR==mmResult)

{

WAVEHDR pwh1;

char buffer1[10240];

WAVEHDR pwh2;

char buffer2[10240];

pwh1.lpData = buffer1;

pwh1.dwBufferLength = 10240;

pwh1.dwUser = 1;

pwh1.dwFlags = 0;

mmResult = waveInPrepareHeader(phwi,&pwh1,sizeof(WAVEHDR));//准备缓冲区

printf("\n准备缓冲区1");

pwh2.lpData=buffer2;

pwh2.dwBufferLength=10240;

pwh2.dwUser=2;

pwh2.dwFlags=0;

mmResult=waveInPrepareHeader(phwi,&pwh2,sizeof(WAVEHDR));//

printf("\n准备缓冲区2\n");

if(MMSYSERR_NOERROR==mmResult)

{

mmResult=waveInAddBuffer(phwi,&pwh1,sizeof(WAVEHDR));//添加缓冲区

mmResult=waveInAddBuffer(phwi,&pwh2,sizeof(WAVEHDR));

printf("\n将缓冲区2加入音频输入设备\n");

if(MMSYSERR_NOERROR==mmResult)

{

mmResult=waveInStart(phwi);

printf("\n请求开始录音\n");

/*

Sleep(10000);

waveInStop(phwi);//停止录音

//waveInReset(phwi);

waveInClose(phwi);//关闭音频设备

waveInUnprepareHeader(phwi,&pwh1, sizeof(WAVEHDR));//释放buffer

waveInUnprepareHeader(phwi,&pwh2, sizeof(WAVEHDR));

printf("stop capture!\n");

fflush(stdout);

*/

}

}

}

}

}

void forRec(void * ptr)//新建的另一个线程用于将数据写入文件

{

char buff[10240]={0};

int len=0;

while(1)

{

//printf("sdafsadf");

//if()

EnterCriticalSection(&cs); //进入临界区

len=fifo_get(buff, 10240);//从fifo中获取数据

LeaveCriticalSection(&cs);//离开临界区

//printf("len=%d\n", len);

fwrite(buff,len, 1, fp);//将音频数据写入音频文件

Sleep(100);

}

}

int main(int argc, char* argv[])

{

int len=0;

char buff[10240]={0};

InitializeCriticalSection(&cs);//初始化临界区

init_cycle_buffer();//初始化缓冲区

fp = fopen("test.wav","wb");//打开音频文件

if (NULL == fp)

{

printf("open %s error.\n", "test.wav");

return 1;

}

fwrite(&wav_hdr, sizeof(wav_hdr) ,1, fp); //添加写入wav音频头,使用采样率为16000

_beginthread(forRec, 0, NULL);//创建线程

RecordWave();//开启录音,一旦录音数据buffer满,就会触发回调函数,所以下面要有while阻塞不然程序就会结束掉。

while(1)

{

}

return 0;

}

每个函数参数的意义就去MSDN上查一下吧,会用就好。

MicCallback是一个回调函数这一点要注意,还有在MicCallback中不要出现阻塞的语句,会丢数据。

环行缓冲区的思想值得学习。

RecotdWave之后要阻塞,在回调函数中处理数据。

如果仅仅是录制一个音频文件的话就不需要重新创建一个线程,只要在回调函数中写入就行了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值