您的位置:首页 > 其它

经典alsa 录音和播放程序

2012-12-15 22:55 423 查看
这里贴上虚拟机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\n");

/* 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(¶ms);

/* 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\n",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\n",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\n");

}

/******************打印参数*********************/

snd_pcm_hw_params_get_channels(params, &val);

printf("channels = %d\n", val);

snd_pcm_hw_params_get_rate(params, &val, &dir);

printf("rate = %d bps\n", val);

snd_pcm_hw_params_get_period_time(params,

&val, &dir);

printf("period time = %d us\n", val);

snd_pcm_hw_params_get_period_size(params,

&frames, &dir);

printf("period size = %d frames\n", (int)frames);

snd_pcm_hw_params_get_buffer_time(params,

&val, &dir);

printf("buffer time = %d us\n", val);

snd_pcm_hw_params_get_buffer_size(params,

(snd_pcm_uframes_t *) &val);

printf("buffer size = %d frames\n", val);

snd_pcm_hw_params_get_periods(params, &val, &dir);

printf("periods per buffer = %d frames\n", val);

snd_pcm_hw_params_get_rate_numden(params,

&val, &val2);

printf("exact rate = %d/%d bps\n", val, val2);

val = snd_pcm_hw_params_get_sbits(params);

printf("significant bits = %d\n", val);

//snd_pcm_hw_params_get_tick_time(params, &val, &dir);

printf("tick time = %d us\n", val);

val = snd_pcm_hw_params_is_batch(params);

printf("is batch = %d\n", val);

val = snd_pcm_hw_params_is_block_transfer(params);

printf("is block transfer = %d\n", val);

val = snd_pcm_hw_params_is_double(params);

printf("is double = %d\n", val);

val = snd_pcm_hw_params_is_half_duplex(params);

printf("is half duplex = %d\n", val);

val = snd_pcm_hw_params_is_joint_duplex(params);

printf("is joint duplex = %d\n", val);

val = snd_pcm_hw_params_can_overrange(params);

printf("can overrange = %d\n", val);

val = snd_pcm_hw_params_can_mmap_sample_resolution(params);

printf("can mmap = %d\n", val);

val = snd_pcm_hw_params_can_pause(params);

printf("can pause = %d\n", val);

val = snd_pcm_hw_params_can_resume(params);

printf("can resume = %d\n", val);

val = snd_pcm_hw_params_can_sync_start(params);

printf("can sync start = %d\n", 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\n");

//if(fseek(fp,0,SEEK_SET) < 0)

// printf("put fp start to first error\n ");

/* 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(¶ms);

/* 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\n",(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\n",j++);

if (rc == 0) {

fprintf(stderr, "end of file on input\n");

break;

} else if (rc != size) {

fprintf(stderr, "short read: read %d bytes\n", rc);

}

//else printf("fread to buffer success\n");

rc = snd_pcm_writei(handle, buffer, frames);

if (rc == -EPIPE) {

/* EPIPE means underrun */

fprintf(stderr, "underrun occurred\n");

snd_pcm_prepare(handle);

} else if (rc < 0) {

fprintf(stderr, "error from writei: %s\n",

snd_strerror(rc));

} else if (rc != (int)frames) {

fprintf(stderr, "short write, write %d frames\n", rc);

}

}

/******************打印参数*********************/

snd_pcm_hw_params_get_channels(params, &val);

printf("channels = %d\n", val);

snd_pcm_hw_params_get_rate(params, &val, &dir);

printf("rate = %d bps\n", val);

snd_pcm_hw_params_get_period_time(params,

&val, &dir);

printf("period time = %d us\n", val);

snd_pcm_hw_params_get_period_size(params,

&frames, &dir);

printf("period size = %d frames\n", (int)frames);

snd_pcm_hw_params_get_buffer_time(params,

&val, &dir);

printf("buffer time = %d us\n", val);

snd_pcm_hw_params_get_buffer_size(params,

(snd_pcm_uframes_t *) &val);

printf("buffer size = %d frames\n", val);

snd_pcm_hw_params_get_periods(params, &val, &dir);

printf("periods per buffer = %d frames\n", val);

snd_pcm_hw_params_get_rate_numden(params,

&val, &val2);

printf("exact rate = %d/%d bps\n", val, val2);

val = snd_pcm_hw_params_get_sbits(params);

printf("significant bits = %d\n", val);

//snd_pcm_hw_params_get_tick_time(params, &val, &dir);

printf("tick time = %d us\n", val);

val = snd_pcm_hw_params_is_batch(params);

printf("is batch = %d\n", val);

val = snd_pcm_hw_params_is_block_transfer(params);

printf("is block transfer = %d\n", val);

val = snd_pcm_hw_params_is_double(params);

printf("is double = %d\n", val);

val = snd_pcm_hw_params_is_half_duplex(params);

printf("is half duplex = %d\n", val);

val = snd_pcm_hw_params_is_joint_duplex(params);

printf("is joint duplex = %d\n", val);

val = snd_pcm_hw_params_can_overrange(params);

printf("can overrange = %d\n", val);

val = snd_pcm_hw_params_can_mmap_sample_resolution(params);

printf("can mmap = %d\n", val);

val = snd_pcm_hw_params_can_pause(params);

printf("can pause = %d\n", val);

val = snd_pcm_hw_params_can_resume(params);

printf("can resume = %d\n", val);

val = snd_pcm_hw_params_can_sync_start(params);

printf("can sync start = %d\n", val);

/*******************************************************************/

snd_pcm_drain(handle);

snd_pcm_close(handle);

free(buf);

fclose(fp);

return 0;

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