经典alsa 录音和播放程序

摘要:
此外,还可以在终端中输入alsaMixer进行调整。以前,我的耳机只能播放,不能录制。由于某些设置未打开,在进入alsaMixer界面后,按F4(这是捕获选项)打开声音,然后录制。有两种类型的模式测试。一种是使用fread和fwrite来读取和写入文件。从声卡收集的帧通过dma发送到应用程序的缓存。首先/捕获被记录,然后/播放。此外,播放只能播放原始wav文件。

这里贴上虚拟机ubuntu下alsa的录音程序(capture.c)和播放程序(playback.c)的源码。

首先要测试一下自己的ubuntu是否打开了声音。这个可以打开/系统/首选项/声音  来调节。另外也可以在终端下输入alsaMixer 来调节,之前我的耳机就是只能放音不能录音,因为没有打开一些设置,在进入alsamixer界面后,按F4也就是capture选项,把声音调大就可以录音了。其中有两种模式测验,一种是使用fread和fwrite以读写文件的方式操作,把声卡里的采集到的frame通过dma发送到应用程序的缓存中,先./capture 录音再./playback 放音。另一种是read和write来操作,把输入输出重定向到标准输入和标准输出,下面的程序就可以用./capture > sound.wav 把输出定向到sound.wav文件中,然后./playback < sound.wav 把声音文件传输到playback的输入端。

另外playback只能播放原始的wav文件。不能播放如MP3类型的编码过的音频文件。

capture.c

/* 
This example reads from the default PCM device 
and writes to standard output for 5 seconds of data. 
*/  
/* Use the newer ALSA API */  
#include <stdio.h>
#define ALSA_PCM_NEW_HW_PARAMS_API  
#include <alsa/asoundlib.h>  
int main() {  
long loops;  
int rc,i = 0;  
int size;  
FILE *fp ;
snd_pcm_t *handle;  
snd_pcm_hw_params_t *params;  
unsigned int val,val2;  
int dir;  
snd_pcm_uframes_t frames;  
char *buffer;  
if(  (fp =fopen("sound.wav","w")) < 0)
printf("open sound.wav fial ");
/* Open PCM device for recording (capture). */  
rc = snd_pcm_open(&handle, "default",  
SND_PCM_STREAM_CAPTURE, 0);  
if (rc < 0) {  
fprintf(stderr,  "unable to open pcm device: %s/n",  snd_strerror(rc));  
exit(1);  
}  
/* Allocate a hardware parameters object. */  
snd_pcm_hw_params_alloca(&params);  
/* Fill it in with default values. */  
snd_pcm_hw_params_any(handle, params);  
/* Set the desired hardware parameters. */  
/* Interleaved mode */  
snd_pcm_hw_params_set_access(handle, params,  
SND_PCM_ACCESS_RW_INTERLEAVED);  
/* Signed 16-bit little-endian format */  
snd_pcm_hw_params_set_format(handle, params,  
SND_PCM_FORMAT_S16_LE);  
/* Two channels (stereo) */  
snd_pcm_hw_params_set_channels(handle, params, 2);  
/* 44100 bits/second sampling rate (CD quality) */  
val = 44100;  
snd_pcm_hw_params_set_rate_near(handle, params,  &val, &dir);  
/* Set period size to 32 frames. */  
frames = 32;  
snd_pcm_hw_params_set_period_size_near(handle,  params, &frames, &dir);  
/* Write the parameters to the driver */  
rc = snd_pcm_hw_params(handle, params);  
if (rc < 0) {  
fprintf(stderr,  "unable to set hw parameters: %s/n",  
snd_strerror(rc));  
exit(1);  
}  
/* Use a buffer large enough to hold one period */  
snd_pcm_hw_params_get_period_size(params,  &frames, &dir);  
size = frames * 4; /* 2 bytes/sample, 2 channels */  
printf("size = %d ",size);
buffer = (char *) malloc(size);  
/* We want to loop for 5 seconds */  
snd_pcm_hw_params_get_period_time(params,  &val, &dir);  
loops = 10000000 / val;  
while (loops > 0) {  
loops--;  
rc = snd_pcm_readi(handle, buffer, frames); 
printf("%d ",i++); 
if (rc == -EPIPE) {  
/* EPIPE means overrun */  
fprintf(stderr, "overrun occurred/n");  
snd_pcm_prepare(handle);  
} else if (rc < 0) {  
fprintf(stderr,  
"error from read: %s/n",  
snd_strerror(rc));  
} else if (rc != (int)frames) {  
fprintf(stderr, "short read, read %d frames/n", rc);  
}  
//rc = fwrite( buffer,1, size,fp);  
rc = write(1,buffer,size);
if (rc != size)  
fprintf(stderr,  "short write: wrote %d bytes/n", rc);  
else printf("fwrite buffer success ");
}  
/******************打印参数*********************/
snd_pcm_hw_params_get_channels(params, &val);  
printf("channels = %d ", val);  
snd_pcm_hw_params_get_rate(params, &val, &dir);  
printf("rate = %d bps ", val);  
snd_pcm_hw_params_get_period_time(params,  
&val, &dir);  
printf("period time = %d us ", val);  
snd_pcm_hw_params_get_period_size(params,  
&frames, &dir);  
printf("period size = %d frames ", (int)frames);  
snd_pcm_hw_params_get_buffer_time(params,  
&val, &dir);  
printf("buffer time = %d us ", val);  
snd_pcm_hw_params_get_buffer_size(params,  
(snd_pcm_uframes_t *) &val);  
printf("buffer size = %d frames ", val);  
snd_pcm_hw_params_get_periods(params, &val, &dir);  
printf("periods per buffer = %d frames ", val);  
snd_pcm_hw_params_get_rate_numden(params,  
&val, &val2);  
printf("exact rate = %d/%d bps ", val, val2);  
val = snd_pcm_hw_params_get_sbits(params);  
printf("significant bits = %d ", val);  
//snd_pcm_hw_params_get_tick_time(params,  &val, &dir);  
printf("tick time = %d us ", val);  
val = snd_pcm_hw_params_is_batch(params);  
printf("is batch = %d ", val);  
val = snd_pcm_hw_params_is_block_transfer(params);  
printf("is block transfer = %d ", val);  
val = snd_pcm_hw_params_is_double(params);  
printf("is double = %d ", val);  
val = snd_pcm_hw_params_is_half_duplex(params);  
printf("is half duplex = %d ", val);  
val = snd_pcm_hw_params_is_joint_duplex(params);  
printf("is joint duplex = %d ", val);  
val = snd_pcm_hw_params_can_overrange(params);  
printf("can overrange = %d ", val);  
val = snd_pcm_hw_params_can_mmap_sample_resolution(params);  
printf("can mmap = %d ", val);  
val = snd_pcm_hw_params_can_pause(params);  
printf("can pause = %d ", val);  
val = snd_pcm_hw_params_can_resume(params);  
printf("can resume = %d ", val);  
val = snd_pcm_hw_params_can_sync_start(params);  
printf("can sync start = %d ", val);  
/*******************************************************************/
snd_pcm_drain(handle);  
snd_pcm_close(handle); 
fclose(fp); 
free(buffer);  
return 0

}

playback.c

/* 
This example reads standard from input and writes 
to the default PCM device for 5 seconds of data. 
*/  
/* Use the newer ALSA API */  
#define ALSA_PCM_NEW_HW_PARAMS_API  
#include <alsa/asoundlib.h>  
#include <stdio.h>
int main() {  
long loops;  
int rc,j = 0;  
int size;  
snd_pcm_t *handle;  
snd_pcm_hw_params_t *params;  
unsigned int val,val2;  
int dir;  
snd_pcm_uframes_t frames;  
char *buffer;  
FILE *fp ;
if( (fp = fopen("sound.wav","r")) < 0)//南拳妈妈 - 你不像她.wav
printf("open sound.wav fial ");
//if(fseek(fp,0,SEEK_SET) < 0)
// printf("put fp start to first error ");


/* Open PCM device for playback. */  
rc = snd_pcm_open(&handle, "default",  
SND_PCM_STREAM_PLAYBACK, 0);  
if (rc < 0) {  
fprintf(stderr,  "unable to open pcm device: %s/n",  
snd_strerror(rc));  
exit(1);  
}  
/* Allocate a hardware parameters object. */  
snd_pcm_hw_params_alloca(&params);  
/* Fill it in with default values. */  
snd_pcm_hw_params_any(handle, params);  
/* Set the desired hardware parameters. */  
/* Interleaved mode */  
snd_pcm_hw_params_set_access(handle, params,  
SND_PCM_ACCESS_RW_INTERLEAVED);  
/* Signed 16-bit little-endian format */  
snd_pcm_hw_params_set_format(handle, params,  
SND_PCM_FORMAT_S16_LE);  
/* Two channels (stereo) */  
snd_pcm_hw_params_set_channels(handle, params, 2);  
/* 44100 bits/second sampling rate (CD quality) */  
val = 44100;  
snd_pcm_hw_params_set_rate_near(handle, params,  
&val, &dir);  
/* Set period size to 32 frames. */  
frames = 16;  //设置的值没有反应
snd_pcm_hw_params_set_period_size_near(handle,  params, &frames, &dir); // 
printf("frames is %d ",(int)frames);
/* Write the parameters to the driver */  
rc = snd_pcm_hw_params(handle, params);  
if (rc < 0) {  
fprintf(stderr,  "unable to set hw parameters: %s/n",  snd_strerror(rc));  
exit(1);  
}  
/* Use a buffer large enough to hold one period */  
snd_pcm_hw_params_get_period_size(params, &frames,  
&dir);  
size = frames * 4; /* 2 bytes/sample, 2 channels */  

buffer = (char *) malloc(size);  

/* We want to loop for 5 seconds */  
snd_pcm_hw_params_get_period_time(params,  &val, &dir);  

/* 5 seconds in microseconds divided by * period time */  
loops = 10000000 / val;  
while (loops > 0) {  
loops--;  
//rc = fread(buffer,1, size,fp); 


rc = read(0,buffer,size);

//printf("%d ",j++); 
if (rc == 0) {  
fprintf(stderr, "end of file on input ");  
break;  
} else if (rc != size) {  
fprintf(stderr,  "short read: read %d bytes ", rc);  


}  
//else printf("fread to buffer success ");
rc = snd_pcm_writei(handle, buffer, frames);  


if (rc == -EPIPE) {  
/* EPIPE means underrun */  
fprintf(stderr, "underrun occurred ");  
snd_pcm_prepare(handle);  
} else if (rc < 0) {  
fprintf(stderr,  "error from writei: %s ",  
snd_strerror(rc));  
}  else if (rc != (int)frames) {  
fprintf(stderr,  "short write, write %d frames ", rc);  
}  
}  
/******************打印参数*********************/
snd_pcm_hw_params_get_channels(params, &val);  
printf("channels = %d ", val);  
snd_pcm_hw_params_get_rate(params, &val, &dir);  
printf("rate = %d bps ", val);  
snd_pcm_hw_params_get_period_time(params,  
&val, &dir);  
printf("period time = %d us ", val);  
snd_pcm_hw_params_get_period_size(params,  
&frames, &dir);  
printf("period size = %d frames ", (int)frames);  
snd_pcm_hw_params_get_buffer_time(params,  
&val, &dir);  
printf("buffer time = %d us ", val);  
snd_pcm_hw_params_get_buffer_size(params,  
(snd_pcm_uframes_t *) &val);  
printf("buffer size = %d frames ", val);  
snd_pcm_hw_params_get_periods(params, &val, &dir);  
printf("periods per buffer = %d frames ", val);  
snd_pcm_hw_params_get_rate_numden(params,  
&val, &val2);  
printf("exact rate = %d/%d bps ", val, val2);  
val = snd_pcm_hw_params_get_sbits(params);  
printf("significant bits = %d ", val);  
//snd_pcm_hw_params_get_tick_time(params,  &val, &dir);  
printf("tick time = %d us ", val);  
val = snd_pcm_hw_params_is_batch(params);  
printf("is batch = %d ", val);  
val = snd_pcm_hw_params_is_block_transfer(params);  
printf("is block transfer = %d ", val);  
val = snd_pcm_hw_params_is_double(params);  
printf("is double = %d ", val);  
val = snd_pcm_hw_params_is_half_duplex(params);  
printf("is half duplex = %d ", val);  
val = snd_pcm_hw_params_is_joint_duplex(params);  
printf("is joint duplex = %d ", val);  
val = snd_pcm_hw_params_can_overrange(params);  
printf("can overrange = %d ", val);  
val = snd_pcm_hw_params_can_mmap_sample_resolution(params);  
printf("can mmap = %d ", val);  
val = snd_pcm_hw_params_can_pause(params);  
printf("can pause = %d ", val);  
val = snd_pcm_hw_params_can_resume(params);  
printf("can resume = %d ", val);  
val = snd_pcm_hw_params_can_sync_start(params);  
printf("can sync start = %d ", val);  
/*******************************************************************/
snd_pcm_drain(handle);  
snd_pcm_close(handle);  
free(buf);

fclose(fp);

return 0;

}

免责声明:文章转载自《经典alsa 录音和播放程序》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇scrapy——8 scrapyd使用unity游戏中存档和读档的方法下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

win10下ndk编译arm可执行体

编译参考文章 http://blog.csdn.net/john_1984/article/details/12622215 一、编写soLoader主文件 soLoader.c内容: #include <stdio.h>typedef int (*MAIN_FN)(int,char**); int main(int argc,char*arg...

在C#中什么时候用分号?

1、在函数体,也就是 { } 这个大括号里的东西,函数调用声明和定义自变量结束时需要加分号 函数声明:比如intmax(a,b,c); 定义自变量:比如floatx,y; 2、在一句话结束时必须加分号(分号用于结束完成的语句) 比如输入输出函数:printf("a word "); scanf("a"); 3、函数的赋值结束后必加分号 比如c=a*b;...

2.1 Linux中wait、system 分析

wait与waitpid: 当子进程退出的时候,内核会向父进程发送SIGCHID信号,子进程的退出是一个异步事件(子进程可以在父进程运行的任何时刻终止)。 子进程退出时,内核将子进程置为僵尸状态,这个进程称为僵尸进程,它只保留最小的一些内核数据结构,以便父进程查询子进程的退出状态。 父进程查询子进程的退出状态可以用wait/waitpid函数。 当我们用f...

linux C sscanf()函数

linux sscanf() 类似正则表达式,又不完全是正则表达式。    分割 ”/“ 或 "@" 或空格 要用 [^/] 例如:  sscanf("iios/12DDWDFF@122", "%*[^/]/%[^@]", buf); printf("%s ", buf); 结果为:12DDWDFF  分割"," 或 ":"或"-"。  sscanf(“h...

《Linux 应用编程》—第13章 Linux 多线程编程

目录 1 多线程概述 1.1 什么是线程 1.2 线程与进程的关系 1.3 为什么使用多线程 2 POSIX Threads 概述 3 线程管理 3.1 线程ID 3.2 创建与终止 1. 创建线程 2. 终止线程 3. 线程范例1 3.3 连接与分离 1. 线程分离 2. 线程连接 3. 线程范例2 3.4 线程属性 属性对象...

符号表示

%d 十进制有符号整数    %u 十进制无符号整数    %f 浮点数    %s 字符串     (是指的输出字符串,在printf中能够输出字符串的值,后面的参数为 “数组的指针”)     举例: #include<stdio.h>struct student{ char a[20]; char id[20];             ...