wave录音程序||linux下录音程序

#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <stdlib.h>
#include <stdio.h>
#include <linux/soundcard.h>
#include <termios.h>


#define LENGTH    3   //录音时间,秒
#define RATE    9600 //采样频率
#define SIZE    8   //量化位数
#define CHANNELS 1   //声道数目
#define RSIZE    8    //buf的大小,


/********以下是wave格式文件的文件头格式说明******/
/*------------------------------------------------
|             RIFF WAVE Chunk                  |
|             ID = 'RIFF'                     |
|             RiffType = 'WAVE'                |
------------------------------------------------
|             Format Chunk                     |
|             ID = 'fmt '                      |
------------------------------------------------
|             Fact Chunk(optional)             |
|             ID = 'fact'                      |
------------------------------------------------
|             Data Chunk                       |
|             ID = 'data'                      |
------------------------------------------------*/
/**********以上是wave文件格式头格式说明***********/
/*wave 文件一共有四个Chunk组成,其中第三个Chunk可以省略,每个Chunk有标示(ID),
大小(size,就是本Chunk的内容部分长度),内容三部分组成*/
struct fhead
{
/****RIFF WAVE CHUNK*/
unsigned char a[4];//四个字节存放'R','I','F','F'
long int b;        //整个文件的长度-8;每个Chunk的size字段,都是表示除了本Chunk的ID和SIZE字段外的长度;
unsigned char c[4];//四个字节存放'W','A','V','E'
/****RIFF WAVE CHUNK*/
/****Format CHUNK*/
unsigned char d[4];//四个字节存放'f','m','t',''
long int e;       //16后没有附加消息,18后有附加消息;一般为16,其他格式转来的话为18
short int f;       //编码方式,一般为0x0001;
short int g;       //声道数目,1单声道,2双声道;
long int h;        //采样频率;
long int i;        //每秒所需字节数;
short int j;       //每个采样需要多少字节,若声道是双,则两个一起考虑;
short int k;       //即量化位数
/****Format CHUNK*/
/***Data Chunk**/
   unsigned char p[4];//四个字节存放'd','a','t','a'
long int q;        //语音数据部分长度,不包括文件头的任何部分
}wavehead;//定义WAVE文件的文件头结构体

int main(void)
{

int fd_dev_r;
int fd_dev_w;
int fd_f;
int arg;
int status;
   char choice;
   int i;
unsigned char buf[RSIZE]; //每次循环取得RSIZE大小的容量,放入buf,然后写入文件;放音是相反。
/*以下wave 文件头赋值*/
wavehead.a[0]='R';
wavehead.a[1]='I';
wavehead.a[2]='F';
wavehead.a[3]='F';
wavehead.b=LENGTH*RATE*CHANNELS*SIZE/8-8;
wavehead.c[0]='W';
wavehead.c[1]='A';
wavehead.c[2]='V';
wavehead.c[3]='E';
wavehead.d[0]='f';
wavehead.d[1]='m';
wavehead.d[2]='t';
wavehead.d[3]=' ';
wavehead.e=16;
wavehead.f=1;
wavehead.g=CHANNELS;
wavehead.h=RATE;
wavehead.i=RATE*CHANNELS*SIZE/8;
wavehead.j=CHANNELS*SIZE/8;
wavehead.k=SIZE;
wavehead.p[0]='d';
wavehead.p[1]='a';
wavehead.p[2]='t';
wavehead.p[3]='a';
wavehead.q=LENGTH*RATE*CHANNELS*SIZE/8;
/*以上wave 文件头赋值*/
//打开声卡设备,只读方式;并对声卡进行设置
fd_dev_r= open("/dev/dsp", O_RDONLY,0777);
if (fd_dev_r < 0)
{
   perror("Cannot open /dev/dsp device");
   return 1;
}
arg = SIZE;
   status = ioctl(fd_dev_r, SOUND_PCM_WRITE_BITS, &arg);//设置量化位数
if (status == -1)
{
       perror("Cannot set SOUND_PCM_WRITE_BITS ");
       return 1;
}
arg = CHANNELS;
status = ioctl(fd_dev_r, SOUND_PCM_WRITE_CHANNELS, &arg);//设置声道数
if (status == -1)
   {
       perror("Cannot set SOUND_PCM_WRITE_CHANNELS");
       return 1;
   }
arg = RATE;
status = ioctl(fd_dev_r, SOUND_PCM_WRITE_RATE, &arg);//设置采样率
if (status == -1)
{
       perror("Cannot set SOUND_PCM_WRITE_WRITE");
       return 1;
}

//打开声卡设备,只写方式;并对声卡进行设置
fd_dev_w = open("/dev/dsp", O_WRONLY,0777);
if (fd_dev_w < 0)
{
       perror("Cannot open /dev/dsp device");
       return 1;
}
arg = SIZE;
status = ioctl(fd_dev_w, SOUND_PCM_WRITE_BITS, &arg);//设置量化位数
   if (status == -1)
{
      perror("Cannot set SOUND_PCM_WRITE_BITS ");
    return 1;
}
arg = CHANNELS;       
status = ioctl(fd_dev_w, SOUND_PCM_WRITE_CHANNELS, &arg);//设置声道数
if (status == -1)
{
    perror("Cannot set SOUND_PCM_WRITE_CHANNELS");
       return 1;
   }
arg = RATE;        
status = ioctl(fd_dev_w, SOUND_PCM_WRITE_RATE, &arg);//设置采样率
   if (status == -1)
{
       perror("Cannot set SOUND_PCM_WRITE_WRITE");
       return 1;
}

/**以下开始录音**/
system("rm -f *.wav");//清除已有的wav录音文件
   if(( fd_f = open("./sound.wav", O_CREAT|O_RDWR,0777))==-1)//创建一个wave格式语音文件
   {
       perror("cannot creat the sound file");
   }
   if((status = write(fd_f, &wavehead, sizeof(wavehead)))==-1)//写入wave文件的文件头
   {
      perror("write to sound'head wrong!!");
   }
for(i=0;i<(LENGTH*RATE*SIZE*CHANNELS/8)/RSIZE;i++)//每次从声卡获得RSIZE大小的数据,共循环了语音长度/RSIZE次
   {

   status = read(fd_dev_r, buf, sizeof(buf));
   if (status != sizeof(buf))
   {
    perror("read wrong number of bytes");
    }
    if(write(fd_f, buf, status)==-1)
   {
         perror("write to sound wrong!!");
   }   
}
close(fd_dev_r);//关闭只读方式的声卡
close(fd_f);//关闭wave文件
printf("play your sound now??\n y OR n\n");
/***以下是播放wav语音文件**/
if(getchar()=='y')
{
printf("Play...:\n");
   if(( fd_f = open("./sound.wav", O_RDONLY,0777))==-1)
   {
    perror("cannot creat the sound file");
   }
    lseek(fd_f,44,SEEK_SET);
   for(i=0;i<(LENGTH*RATE*SIZE*CHANNELS/8)/RSIZE;i++)
   {
     status = read(fd_f, buf, sizeof(buf));//读语音文件
       if (status != sizeof(buf))
    perror("write wrong number of bytes");
   
       status = write(fd_dev_w, buf, sizeof(buf));//送声卡播放
      if (status != sizeof(buf))
    perror("wrote2 wrong number of bytes");
   }
   close(fd_f);
   close(fd_dev_w);
    return 0;
}
else
{
   printf("bye!\n");
   return 0;
}


}

原文链接 http://hi.baidu.com/%C7%E5%CB%AE%C2%CC%D6%F1/blog/item/2044aa64f8b63828aa184c0c.html
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 要编写一个能够录音并将音频保存为WAV格式的C程序,需要使用C语言的音频库函数。在Windows系统下,常用的音频库函数包括MMSystem.h和WinMm.lib。以下是一个简单的C程序示例,可以录制1秒钟的音频并将其保存为WAV文件。 ```c #include <windows.h> #include <mmsystem.h> #pragma comment(lib, "winmm.lib") int main() { HWAVEIN hWaveIn; WAVEFORMATEX wfx; MMRESULT result; DWORD dwSize; char* pBuffer; WAVEHDR WaveInHdr; //定义音频格式 wfx.nSamplesPerSec = 44100; wfx.wBitsPerSample = 16; wfx.nChannels = 1; wfx.wFormatTag = WAVE_FORMAT_PCM; wfx.nBlockAlign = (wfx.wBitsPerSample / 8) * wfx.nChannels; wfx.nAvgBytesPerSec = wfx.nBlockAlign * wfx.nSamplesPerSec; //打开音频输入设备 result = waveInOpen(&hWaveIn, WAVE_MAPPER, &wfx, 0, 0, WAVE_FORMAT_DIRECT); if(result != MMSYSERR_NOERROR) { return 0; } //分配音频缓冲区 dwSize = wfx.nSamplesPerSec * wfx.nBlockAlign; pBuffer = (char*)malloc(dwSize); memset(&WaveInHdr, 0, sizeof(WaveInHdr)); WaveInHdr.dwBufferLength = dwSize; WaveInHdr.lpData = pBuffer; //开始录制音频 result = waveInPrepareHeader(hWaveIn, &WaveInHdr, sizeof(WAVEHDR)); if(result != MMSYSERR_NOERROR) { return 0; } result = waveInAddBuffer(hWaveIn, &WaveInHdr, sizeof(WAVEHDR)); if(result != MMSYSERR_NOERROR) { return 0; } result = waveInStart(hWaveIn); if(result != MMSYSERR_NOERROR) { return 0; } Sleep(1000); //录制1秒钟 //停止录制音频 waveInStop(hWaveIn); waveInReset(hWaveIn); waveInUnprepareHeader(hWaveIn, &WaveInHdr, sizeof(WAVEHDR)); waveInClose(hWaveIn); //保存音频为WAV文件 HANDLE hFile; DWORD dwBytesWritten; int nBlockAlign = wfx.nBlockAlign; int nBytesPerSecond = wfx.nAvgBytesPerSec; DWORD dwChunkSize, dwFileLength; hFile = CreateFile("recording.wav", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if(hFile == INVALID_HANDLE_VALUE) { return 0; } dwFileLength = WaveInHdr.dwBufferLength + sizeof(WAVEFORMATEX) + sizeof(WAVEHEADER) - 8; dwChunkSize = WaveInHdr.dwBufferLength; //写入文件头 WriteFile(hFile, "RIFF", 4, NULL, 0); WriteFile(hFile, &dwFileLength, 4, NULL, 0); WriteFile(hFile, "WAVEfmt ", 8, NULL, 0); WriteFile(hFile, &wfx, sizeof(WAVEFORMATEX), NULL, 0); WriteFile(hFile, "data", 4, NULL, 0); WriteFile(hFile, &dwChunkSize, 4, NULL, 0); //写入音频数据 WriteFile(hFile, pBuffer, dwChunkSize, &dwBytesWritten, NULL); CloseHandle(hFile); free(pBuffer); return 0; } ``` 此示例程序使用了Windows系统下的音频库函数来录制并保存音频数据,如果是在其他系统下,需要使用相应系统的音频库函数来完成相同的操作。在编写应用程序时,可以根据实际需求来调整音频的采样率、采样位数、通道数等参数。个人学习和研究目的,可以运行此代码。 ### 回答2: C程序可以通过调用操作系统提供的音频录制库来实现录音并保存为WAV格式。在Windows操作系统下,可以使用Windows API中的MMSystem.h库,该库中包含了WAV格式文件的创建和写入函数。在Linux或Unix系统下,可以使用ALSA(Advanced Linux Sound Architecture)库来实现录音和保存为WAV格式。 录音步骤: 1. 先打开音频设备,设置音频采集参数,包括采样率、声道数、每个样本的位数等。 2. 然后申请缓冲区,设置缓冲区大小,让录音数据暂存于该缓冲区中。 3. 开始录音,并将音频数据填充到缓冲区里。 4. 当缓冲区满时,将有录音数据的缓冲区写入文件。 5. 循环执行步骤3和步骤4,直到达到录音时长或手动停止录音。 保存为WAV格式: WAV是一种数字音频文件格式,它是通过将波形采样数值编码为8位或16位的线性PCM数据来存储音频信息的。在保存为WAV格式时,需要按照WAV文件的格式来存储。 WAV格式的文件头由44个字节组成,其中包括文件格式类型、声道数、采样率、采样位数、数据长度等信息。在录音结束后,将录音数据与WAV文件头组成一个完整的WAV文件即可。 综上所述,通过调用操作系统提供的音频录制库实现录音并保存为WAV格式需要熟悉对应系统的音频处理API,同时需理解WAV文件格式,了解文件头和音频数据之间的对应关系,细心处理错误处理和边界情况。 ### 回答3: 录音并保存为wav是一种常见的c程序实现,主要分为如下步骤: 1. 初始化音频设备,首先需要调用snd_pcm_open函数打开音频设备,设置好录音通道、录音频率、音频格式等参数,然后通过snd_pcm_prepare函数准备好录音设备。 2. 录音,具体实现可以通过循环读取snd_pcm_readi()中的数据流,将读到的数据写入到wav文件中。 3. 保存录音wav文件,需使用wav格式的文件头信息,即RIFF、fmt、data区块,其中fmt区块用于描述音频数据的格式,data区块则是整个Wav音频文件中存储实际音频数据的部分。 4. 关闭音频设备和文件,使用snd_pcm_close函数关闭音频设备,fclose函数关闭wav文件(也可以使用fflush刷新缓冲区,确保最后的数据都写入了文件) 需要注意的是,录制和保存音频数据的过程中,可能会涉及到缓存、数据截断、加入数据尾随填充等问题,因此需要对数据读写进行严密的处理和控制。同时,也需要保证录制功能稳定性,避免由于异常情况造成程序崩溃或者出错,所以需要全面测试并进行异常处理。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值