最近在試Camera Digital Microphone, 它基本上是走Alsa的架構,
因此找個Alsa Audio Capture的範例程式來做實驗.
參考資料來自於: 
Linux Journal Introduction to Sound Programming with ALSA
/*
   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;
}
目前錄出來的PCM聲音檔, 我是在ubuntu上用mplayer去播放
mplayer -rawaudio samplesize=2:channels=2:rate=11025 -demuxer rawaudio test.raw
使用ffmpeg將PCM檔轉WAV檔
ffmpeg -f s16le -ar 11025 -ac 2 -i ./test.pcm ./test.wav
-f s16le … signed 16-bit little endian samples 
-ar 11025 … sample rate 11025Hz 
-ac 2 … 2 channels (stereo) 
-i test.pcm … input file 
test.wav … output file 
在snd_pcm_readi這裏有遇到一個有趣的問題, 它回傳的值是audio frames的數量.
當你的資料是設定為16bits, 2 channles時, 一個frames的大小為4 bytes.