您的位置:首页 > 运维架构 > Linux

Linux下OSS音频录制和播放

2015-05-20 15:38 197 查看
OSS(Open Sound System,开放声音系统),是unix或类unix环境中的音频接口,是一种音频驱动结构。

OSS标准中包括两个基本的音频设备:mixer(混音器)和dsp(数字信号处理器)。

混音器对应的应用程序操作接口/dev/mixer。
dsp对应的应用程序操作接口/dev/dsp或/dev/audio

虽然多数硬件都能够支持此音频驱动,但OSS十多年没有更新和大的修动,Linux系统中又出现一种新的音频架构(ALSA Advanced Linux Sound Architecture)。

===================================================
数据音频基础知识

数字音频设备:播放或录制数字化的声音,它的指标主要有:

采样速率 :每秒钟的采样点个数。有8KHz,44.8KHz,48KHz等等。采样频率越高,描述的声波频率就越高。
采样分辨率:即量化精度,对模拟信号转数字信号量化值。有8bit和16bit,一般使用16bit小端模式。精度超高,声音数字化越逼真。
channel数 :分为单通道1和立体声2。

mixer(混频器):用来控制多个输入、输出的音量,也控制输入(microphone,line-in,CD)之间的切换。

synthesizer(合成器):通过一些预先定义好的波形来合成声音,有时用在游戏中声音效果的产生。

MIDI 接口:MIDI接口是为了连接舞台上的synthesizer、键盘、道具、灯光控制器的一种串行接口。

原始(未编码)音频数据的大小计算:

公式:采样频率*采样分辨率*通道数 / 8 = 每秒音频数据

常用的音频压缩编码有G711,G729, MEPG-layer3。

常用的音频封装格式有MP3、WMA、MP4等等。

========================================
如果通过编程的方式来使用这些设备,那么unix平台通过文件系统提供了统一的访问接口。
程序员可以通过文件的操作函数直接控制这些设备,这些操作函数包括:open、close、read、write、ioctl等。
下面我们就分别讨论打开音频设备、放音、录音和参数调整。

音频编程的流程:

1.打开音频设备 (对于有些设备 存放于/dev/sound/下)
open_mode有三种选择:O_RDONLY,O_WRONLY和O_RDWR,分别表示只读、只写和读写。
OSS建议尽量使用只读或只写,只有在全双工的情况下(即录音和放音同时)才使用读写模式。
if ((audio_fd = open(AUDIO_DEV, O_RDONLY, 0)) == -1)
{
perror(AUDIO_DEV);
<span style="white-space:pre">	</span>exit(1);
}


2.设定音频参数
采样取值及请求宏(request):

采样频率:请求宏:SNDCTL_DSP_SPEED 值:48000

量化位数:请求宏:SNDCTL_DSP_SETFMT 值:AFMT_S16_LE

通道数 : 请求宏:SNDCTL_DSP_CHANNELS 值:单通道1,立体声2

void set_param(int fd)
{
int param;
printf("set params!\n");
//----------------------------------
param = 48000;
ioctl(fd,SNDCTL_DSP_SPEED,¶m);
param = AFMT_S16_LE;
ioctl(fd,SNDCTL_DSP_SETFMT,¶m);
param = 2;
ioctl(fd,SNDCTL_DSP_CHANNELS,¶m);
}


3.采集音频数据or 播放音频数据
采集数据并存放到文件当中

if ((len = read(audio_fd,audio_buffer,AUDIO_BUF)) == -1)
{
perror("audio read");
exit(1);
}
int filefd = open("a.wav",O_CREAT|O_WRONLY|O_APPEND|O_TRUNC,0666);
len=0;
if ((len = write(filefd,audio_buffer,AUDIO_BUF)) == -1)
{
perror("audio store");
exit(1);
}
close(filefd);



读取文件并播放数据

int filefd = open("a.wav",O_RDONLY);
if ((len = read(filefd,audio_buffer,AUDIO_BUF)) == -1)
{
perror("audio read");
exit(1);
}
close(filefd);
if ((audio_fd = open(AUDIO_DEV, O_WRONLY, 0)) == -1)
{
perror(AUDIO_DEV);
exit(1);
}
set_param(audio_fd);
len=0;
if ((len = write(audio_fd,audio_buffer,AUDIO_BUF)) == -1)
{
perror("audio write");
exit(1);
}
printf("play ended!\n");

close(audio_fd);


4.关闭音频设备
======================源码(录音5秒播放5秒)===========================

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

#define AUDIO_DEV "/dev/dsp"
#define AUDIO_BUF 48000*2*2*5//sampling,16bit,2channels ,2second
char audio_buffer[AUDIO_BUF];
void set_param(int fd) { int param; printf("set params!\n"); //---------------------------------- param = 48000; ioctl(fd,SNDCTL_DSP_SPEED,¶m); param = AFMT_S16_LE; ioctl(fd,SNDCTL_DSP_SETFMT,¶m); param = 2; ioctl(fd,SNDCTL_DSP_CHANNELS,¶m); }

void record()
{
int len=0;
int audio_fd;
if ((audio_fd = open(AUDIO_DEV, O_RDONLY, 0)) == -1)
{
perror(AUDIO_DEV);
exit(1);
}
set_param(audio_fd);
//creat a tmp file to store datas
usleep(500000);
printf("begin to record...\n");
if ((len = read(audio_fd,audio_buffer,AUDIO_BUF)) == -1) { perror("audio read"); exit(1); }
close(audio_fd);

int filefd = open("a.wav",O_CREAT|O_WRONLY|O_APPEND|O_TRUNC,0666); len=0; if ((len = write(filefd,audio_buffer,AUDIO_BUF)) == -1) { perror("audio store"); exit(1); } close(filefd);

printf("record ended!\n");
}

void play()
{
int len=0;
int audio_fd;
printf("voice play...\n");

int filefd = open("a.wav",O_RDONLY); if ((len = read(filefd,audio_buffer,AUDIO_BUF)) == -1) { perror("audio read"); exit(1); } close(filefd); if ((audio_fd = open(AUDIO_DEV, O_WRONLY, 0)) == -1) { perror(AUDIO_DEV); exit(1); } set_param(audio_fd); len=0; if ((len = write(audio_fd,audio_buffer,AUDIO_BUF)) == -1) { perror("audio write"); exit(1); } printf("play ended!\n"); close(audio_fd);
}
int main()
{

//open_mode :O_RDONLY,O_WRONLY,O_RDWR
printf("open %s!\n",AUDIO_DEV);
record();
//--------------------------------------
sleep(1);
play();

return 0;
}



============================播放一个WAV格式的音频文件===========================

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

#define AUDIO_DEV "/dev/dsp"
#define AUDIO_BUF 48000*2*2*2//sampling,16bit,2channels ,2second
char audio_buffer[AUDIO_BUF];
void set_param(int fd) { int param; printf("set params!\n"); //---------------------------------- param = 48000; ioctl(fd,SNDCTL_DSP_SPEED,¶m); param = AFMT_S16_LE; ioctl(fd,SNDCTL_DSP_SETFMT,¶m); param = 2; ioctl(fd,SNDCTL_DSP_CHANNELS,¶m); }
void play(char *file)
{
int len=0;
int audio_fd;
printf("voice play...\n");
if ((audio_fd = open(AUDIO_DEV, O_WRONLY, 0)) == -1)
{
perror(AUDIO_DEV);
exit(1);
}
set_param(audio_fd);

int filefd = open(file,O_RDONLY);
if(filefd<0)
{
perror("open snd file ");

}
while((len = read(filefd,audio_buffer,AUDIO_BUF))>0)
{
//len=0;
if ((len = write(audio_fd,audio_buffer,AUDIO_BUF)) == -1)
{
perror("audio write");
exit(1);
}
}
printf("play ended!\n");
close(filefd);
close(audio_fd);
}
int main(int argc,char *argv[])
{

//open_mode :O_RDONLY,O_WRONLY,O_RDWR
printf("open %s!\n",AUDIO_DEV);
play(argv[1]);

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: