ALSA lib调用实例

1. Display Some PCM Types and Formats

#include <alsa/asoundlib.h>  
  
int main() {  
  int val;  
  
  printf("ALSA library version: %s\n",  
          SND_LIB_VERSION_STR);  
  
  printf("\nPCM stream types:\n");  
  for (val = 0; val <= SND_PCM_STREAM_LAST; val++)  
    printf("  %s\n",  
      snd_pcm_stream_name((snd_pcm_stream_t)val));  
  
  printf("\nPCM access types:\n");  
  for (val = 0; val <= SND_PCM_ACCESS_LAST; val++)  
    printf("  %s\n",  
      snd_pcm_access_name((snd_pcm_access_t)val));  
  
  printf("\nPCM formats:\n");  
  for (val = 0; val <= SND_PCM_FORMAT_LAST; val++)  
    if (snd_pcm_format_name((snd_pcm_format_t)val)  
      != NULL)  
      printf("  %s (%s)\n",  
        snd_pcm_format_name((snd_pcm_format_t)val),  
        snd_pcm_format_description(  
                           (snd_pcm_format_t)val));  
  
  printf("\nPCM subformats:\n");  
  for (val = 0; val <= SND_PCM_SUBFORMAT_LAST;  
       val++)  
    printf("  %s (%s)\n",  
      snd_pcm_subformat_name((  
        snd_pcm_subformat_t)val),  
      snd_pcm_subformat_description((  
        snd_pcm_subformat_t)val));  
  
  printf("\nPCM states:\n");  
  for (val = 0; val <= SND_PCM_STATE_LAST; val++)  
    printf("  %s\n",  
           snd_pcm_state_name((snd_pcm_state_t)val));  
  
  return 0;  
}  

 


2. Opening PCM Device and Setting Parameters

/* 
 
This example opens the default PCM device, sets 
some parameters, and then displays the value 
of most of the hardware parameters. It does not 
perform any sound playback or recording. 
 
*/  
  
/* Use the newer ALSA API */  
#define ALSA_PCM_NEW_HW_PARAMS_API  
  
/* All of the ALSA library API is defined 
 * in this header */  
#include <alsa/asoundlib.h>  
  
int main() {  
  int rc;  
  snd_pcm_t *handle;  
  snd_pcm_hw_params_t *params;  
  unsigned int val, val2;  
  int dir;  
  snd_pcm_uframes_t frames;  
  
  /* 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);  
  
  /* 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);  
  }  
  
  /* Display information about the PCM interface */  
  
  printf("PCM handle name = '%s'\n",  
         snd_pcm_name(handle));  
  
  printf("PCM state = %s\n",  
         snd_pcm_state_name(snd_pcm_state(handle)));  
  
  snd_pcm_hw_params_get_access(params,  
                          (snd_pcm_access_t *) &val);  
  printf("access type = %s\n",  
         snd_pcm_access_name((snd_pcm_access_t)val));  
  
  snd_pcm_hw_params_get_format(params, &val);  
  printf("format = '%s' (%s)\n",  
    snd_pcm_format_name((snd_pcm_format_t)val),  
    snd_pcm_format_description(  
                             (snd_pcm_format_t)val));  
  
  snd_pcm_hw_params_get_subformat(params,  
                        (snd_pcm_subformat_t *)&val);  
  printf("subformat = '%s' (%s)\n",  
    snd_pcm_subformat_name((snd_pcm_subformat_t)val),  
    snd_pcm_subformat_description(  
                          (snd_pcm_subformat_t)val));  
  
  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_close(handle);  
  
  return 0;  
}  

 


3. Simple Sound Playback

/* 
 
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>  
  
int main() {  
  long loops;  
  int rc;  
  int size;  
  snd_pcm_t *handle;  
  snd_pcm_hw_params_t *params;  
  unsigned int val;  
  int dir;  
  snd_pcm_uframes_t frames;  
  char *buffer;  
  
  /* 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 = 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 */  
  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 = 5000000 / val;  
  
  while (loops > 0) {  
    loops--;  
    rc = read(0, buffer, size);  
    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);  
    }  
    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_drain(handle);  
  snd_pcm_close(handle);  
  free(buffer);  
  
  return 0;  
}  
 

 

编译之后,可以用下面的命令来测试:
./example3 < /dev/urandom

4. Simple Sound Recording

/* 
 
This example reads from the default PCM device 
and writes to standard output for 5 seconds of data. 
 
*/  
  
/* Use the newer ALSA API */  
#define ALSA_PCM_NEW_HW_PARAMS_API  
  
#include <alsa/asoundlib.h>  
  
int main() {  
  long loops;  
  int rc;  
  int size;  
  snd_pcm_t *handle;  
  snd_pcm_hw_params_t *params;  
  unsigned int val;  
  int dir;  
  snd_pcm_uframes_t frames;  
  char *buffer;  
  
  /* 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 */  
  buffer = (char *) malloc(size);  
  
  /* We want to loop for 5 seconds */  
  snd_pcm_hw_params_get_period_time(params,  
                                         &val, &dir);  
  loops = 5000000 / val;  
  
  while (loops > 0) {  
    loops--;  
    rc = snd_pcm_readi(handle, buffer, frames);  
    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 = write(1, buffer, size);  
    if (rc != size)  
      fprintf(stderr,  
              "short write: wrote %d bytes\n", rc);  
  }  
  
  snd_pcm_drain(handle);  
  snd_pcm_close(handle);  
  free(buffer);  
  
  return 0;  
}  

 

录音使用下面的命令测试:
./listing4 > sound.raw
./listing3 < sound.raw

5. wav格式文件播放测试
这个例子是我根据例子3修改而来的,用来播放wav格式音频文件,注意wav文件格式必须是44100、16bit, 2通道。

#include <alsa/asoundlib.h>  
  
int main(int argc, char *argv[])  
{  
    int rc;  
    int size;  
    snd_pcm_t *handle;  
    snd_pcm_hw_params_t *params;  
    unsigned int val;  
    int dir;  
    snd_pcm_uframes_t frames;  
    char *buffer;  
    FILE *fp;  
      
    fp = fopen(argv[1], "rb");  
    if (!fp) {  
        fprintf(stderr,  
            "can't open sound file\n");  
        exit(1);  
    }  
  
    /* 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 = 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 */  
    buffer = (char *)malloc(size);  
  
    fseek(fp, 44, SEEK_SET);  
    while (1) {  
        rc = fread(buffer, 1, size, fp);  
        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);  
        }  
        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_drain(handle);  
    snd_pcm_close(handle);  
    fclose(fp);  
    free(buffer);  
  
    return 0;  
}  
 

 


参考:http://www.linuxjournal.com/article/6735

posted @ 2017-05-03 16:32  瘋耔  阅读(1159)  评论(0编辑  收藏  举报
跳至侧栏