• 经典alsa 录音和播放程序


    这里贴上虚拟机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;

    }

  • 相关阅读:
    Leo程序员羊皮卷文摘(更新ing)
    ubuntu下的yuv播放器
    浏览器之一
    海量数据处理常用思路和方法(zh)
    我本将心向明月,奈何明月照沟渠
    转载光纤通信之父
    重装系统或是更换电脑之后,Foxmail的恢复
    关于录制Linux视频
    Linux之路(原发表于07年,现在搬到博客)
    Gentoo安装 miniCD+stage3
  • 原文地址:https://www.cnblogs.com/cainiaoaixuexi/p/3920429.html
Copyright © 2020-2023  润新知