标签:android   blog   http   os   io   文件   数据   for   
http://blog.csdn.net/azloong/article/details/6140824
 
这段时间在探索ALSA架构,从ALSA Core到ALSA Lib,再到Android Audio System。在看ALSA Lib时,写了一个比较典型的基于ALSA的播放录音程序。程序包包含四个部分:
WAV Parser是对WAV文件的分析和封装,这里只针对Standard WAV File;
SND Common是Playback 和Record共同操作,如SetParams、ReadPCM和WritePCM等;
Playback和Record就分别是播放录音的主体了。
 
原理很简单,以Playback为例:从WAV文件读取PCM数据,通过I2S或AC97依次送到Audio Codec。难点在于对snd_pcm_hw_params_t的设置,尤其要确定每次要送到Audio Codec的数据帧大小(peroid_size),这个稍后解释。
1、从WAV文件的头信息可以分析出:sample_format、channels number、sample_rate、sample_length,这些参数要通过snd_pcm_hw_params_set_XXX()接口设置到snd_pcm_hw_params_t中。
2、接着我们要设置buffer_time 和peroid_time。通过snd_pcm_hw_params_get_buffer_time_max()接口可以获取该Audio Codec可以支持的最大buffer_time,这里我们设置buffer_time = (MAX_BUFFER_TIME > 500000) ? 500000 : MAX_BUFFER_TIME; peroid_time = buffer_time/4。
关于peroid的概念有这样的描述:The “period” is a term that corresponds to a fragment in the OSS world. The period defines the size at which a PCM interrupt is generated. 从底层驱动看来,应该是PCM DMA单次传送数据帧的大小。其实真正关注底层驱动的话,它并不是关心peroid_time,它关心的是peroid_size,这两者有转换关系。具体见struct snd_pcm_hardware结构体。
3、通过snd_pcm_hw_params_get_period_size()取得peroid_size,注意在ALSA中peroid_size是以frame为单位的。The configured buffer and period sizes are stored in “frames” in the runtime. 1 frame = channels * sample_size. 所以要对peroid_size进行转换:chunk_bytes = peroid_size * sample_length / 8。chunk_bytes就是我们单次从WAV读PCM数据的大小。
之后的过程就乏善可陈了。唯一要留意的是snd_pcm_writei()和snd_pcm_readi()的第三个参数size也是以frame为单位,不要忘记frames和bytes的转换。
-   
 
- #ifndef __WAV_PARSER_H  
 
- #define __WAV_PARSER_H  
 
-   
 
- typedef unsigned char  uint8_t;  
 
- typedef unsigned short uint16_t;  
 
- typedef unsigned int   uint32_t;  
 
-   
 
- #if __BYTE_ORDER == __LITTLE_ENDIAN  
 
- #define COMPOSE_ID(a,b,c,d) ((a) | ((b)<<8) | ((c)<<16) | ((d)<<24))  
 
- #define LE_SHORT(v)           (v)  
 
- #define LE_INT(v)               (v)  
 
- #define BE_SHORT(v)           bswap_16(v)  
 
- #define BE_INT(v)               bswap_32(v)  
 
- #elif __BYTE_ORDER == __BIG_ENDIAN  
 
- #define COMPOSE_ID(a,b,c,d) ((d) | ((c)<<8) | ((b)<<16) | ((a)<<24))  
 
- #define LE_SHORT(v)           bswap_16(v)  
 
- #define LE_INT(v)               bswap_32(v)  
 
- #define BE_SHORT(v)           (v)  
 
- #define BE_INT(v)               (v)  
 
- #else  
 
- #error "Wrong endian"  
 
- #endif  
 
-   
 
- #define WAV_RIFF        COMPOSE_ID(‘R‘,‘I‘,‘F‘,‘F‘)  
 
- #define WAV_WAVE        COMPOSE_ID(‘W‘,‘A‘,‘V‘,‘E‘)  
 
- #define WAV_FMT         COMPOSE_ID(‘f‘,‘m‘,‘t‘,‘ ‘)  
 
- #define WAV_DATA        COMPOSE_ID(‘d‘,‘a‘,‘t‘,‘a‘)  
 
-   
 
- #define WAV_FMT_PCM             0x0001  
 
- #define WAV_FMT_IEEE_FLOAT      0x0003  
 
- #define WAV_FMT_DOLBY_AC3_SPDIF 0x0092  
 
- #define WAV_FMT_EXTENSIBLE      0xfffe  
 
-   
 
- #define WAV_GUID_TAG        "/x00/x00/x00/x00/x10/x00/x80/x00/x00/xAA/x00/x38/x9B/x71"  
 
-   
 
- typedef struct WAVHeader {  
 
-     uint32_t magic;     
 
-     uint32_t length;        
 
-     uint32_t type;      
 
- } WAVHeader_t;  
 
-   
 
- typedef struct WAVFmt {  
 
-     uint32_t magic;  
 
-     uint32_t fmt_size; 
 
-     uint16_t format;        
 
-     uint16_t channels;  
 
-     uint32_t sample_rate;   
 
-     uint32_t bytes_p_second;  
 
-     uint16_t blocks_align;  
 
-     uint16_t sample_length; 
 
- } WAVFmt_t;  
 
-   
 
- typedef struct WAVFmtExtensible {  
 
-     WAVFmt_t format;  
 
-     uint16_t ext_size;  
 
-     uint16_t bit_p_spl;  
 
-     uint32_t channel_mask;  
 
-     uint16_t guid_format;   
 
-     uint8_t guid_tag[14];   
 
- } WAVFmtExtensible_t;  
 
-   
 
- typedef struct WAVChunkHeader {  
 
-     uint32_t type;      
 
-     uint32_t length;        
 
- } WAVChunkHeader_t;  
 
-   
 
- typedef struct WAVContainer {  
 
-     WAVHeader_t header;  
 
-     WAVFmt_t format;  
 
-     WAVChunkHeader_t chunk;  
 
- } WAVContainer_t;  
 
-   
 
- int WAV_ReadHeader(int fd, WAVContainer_t *container);  
 
-   
 
- int WAV_WriteHeader(int fd, WAVContainer_t *container);  
 
-   
 
- #endif /* #ifndef __WAV_PARSER_H */  
 
 
-   
 
- #include <assert.h>  
 
- #include <stdio.h>  
 
- #include <stdlib.h>  
 
- #include <unistd.h>  
 
- #include <fcntl.h>  
 
-   
 
- #include "wav_parser.h"  
 
-   
 
- #define WAV_PRINT_MSG  
 
-   
 
- char *WAV_P_FmtString(uint16_t fmt)  
 
- {  
 
-     switch (fmt) {  
 
-     case WAV_FMT_PCM:  
 
-         return "PCM";  
 
-         break;  
 
-     case WAV_FMT_IEEE_FLOAT:  
 
-         return "IEEE FLOAT";  
 
-         break;  
 
-     case WAV_FMT_DOLBY_AC3_SPDIF:  
 
-         return "DOLBY AC3 SPDIF";  
 
-         break;  
 
-     case WAV_FMT_EXTENSIBLE:  
 
-         return "EXTENSIBLE";  
 
-         break;  
 
-     default:  
 
-         break;  
 
-     }  
 
-   
 
-     return "NON Support Fmt";  
 
- }  
 
-   
 
- void WAV_P_PrintHeader(WAVContainer_t *container)  
 
- {  
 
-     printf("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++/n");  
 
-     printf("/n");  
 
-       
 
-     printf("File Magic:         [%c%c%c%c]/n",   
 
-         (char)(container->header.magic),   
 
-         (char)(container->header.magic>>8),   
 
-         (char)(container->header.magic>>16),   
 
-         (char)(container->header.magic>>24));  
 
-     printf("File Length:        [%d]/n", container->header.length);  
 
-     printf("File Type:          [%c%c%c%c]/n",  
 
-         (char)(container->header.type),   
 
-         (char)(container->header.type>>8),   
 
-         (char)(container->header.type>>16),   
 
-         (char)(container->header.type>>24));  
 
-           
 
-     printf("/n");  
 
-   
 
-     printf("Fmt Magic:          [%c%c%c%c]/n",  
 
-         (char)(container->format.magic),   
 
-         (char)(container->format.magic>>8),   
 
-         (char)(container->format.magic>>16),   
 
-         (char)(container->format.magic>>24));  
 
-     printf("Fmt Size:           [%d]/n", container->format.fmt_size);  
 
-     printf("Fmt Format:         [%s]/n", WAV_P_FmtString(container->format.format));  
 
-     printf("Fmt Channels:       [%d]/n", container->format.channels);  
 
-     printf("Fmt Sample_rate:    [%d](HZ)/n", container->format.sample_rate);  
 
-     printf("Fmt Bytes_p_second: [%d]/n", container->format.bytes_p_second);  
 
-     printf("Fmt Blocks_align:   [%d]/n", container->format.blocks_align);  
 
-     printf("Fmt Sample_length:  [%d]/n", container->format.sample_length);  
 
-       
 
-     printf("/n");  
 
-   
 
-     printf("Chunk Type:         [%c%c%c%c]/n",  
 
-         (char)(container->chunk.type),   
 
-         (char)(container->chunk.type>>8),   
 
-         (char)(container->chunk.type>>16),   
 
-         (char)(container->chunk.type>>24));  
 
-     printf("Chunk Length:       [%d]/n", container->chunk.length);  
 
-       
 
-     printf("/n");  
 
-     printf("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++/n");  
 
- }  
 
-   
 
- int WAV_P_CheckValid(WAVContainer_t *container)  
 
- {  
 
-     if (container->header.magic != WAV_RIFF ||  
 
-         container->header.type != WAV_WAVE ||  
 
-         container->format.magic != WAV_FMT ||  
 
-         container->format.fmt_size != LE_INT(16) ||  
 
-         (container->format.channels != LE_SHORT(1) && container->format.channels != LE_SHORT(2)) ||  
 
-         container->chunk.type != WAV_DATA) {  
 
-           
 
-         fprintf(stderr, "non standard wav file./n");  
 
-         return -1;  
 
-     }  
 
-   
 
-     return 0;  
 
- }  
 
-   
 
- int WAV_ReadHeader(int fd, WAVContainer_t *container)  
 
- {  
 
-     assert((fd >=0) && container);  
 
-   
 
-     if (read(fd, &container->header, sizeof(container->header)) != sizeof(container->header) ||   
 
-         read(fd, &container->format, sizeof(container->format)) != sizeof(container->format) ||  
 
-         read(fd, &container->chunk, sizeof(container->chunk)) != sizeof(container->chunk)) {  
 
-   
 
-         fprintf(stderr, "Error WAV_ReadHeader/n");  
 
-         return -1;  
 
-     }  
 
-   
 
-     if (WAV_P_CheckValid(container) < 0)  
 
-         return -1;  
 
-   
 
- #ifdef WAV_PRINT_MSG  
 
-     WAV_P_PrintHeader(container);  
 
- #endif  
 
-   
 
-     return 0;  
 
- }  
 
-   
 
- int WAV_WriteHeader(int fd, WAVContainer_t *container)  
 
- {  
 
-     assert((fd >=0) && container);  
 
-       
 
-     if (WAV_P_CheckValid(container) < 0)  
 
-         return -1;  
 
-   
 
-     if (write(fd, &container->header, sizeof(container->header)) != sizeof(container->header) ||   
 
-         write(fd, &container->format, sizeof(container->format)) != sizeof(container->format) ||  
 
-         write(fd, &container->chunk, sizeof(container->chunk)) != sizeof(container->chunk)) {  
 
-           
 
-         fprintf(stderr, "Error WAV_WriteHeader/n");  
 
-         return -1;  
 
-     }  
 
-   
 
- #ifdef WAV_PRINT_MSG  
 
-     WAV_P_PrintHeader(container);  
 
- #endif  
 
-   
 
-     return 0;  
 
- }  
 
 
 
-   
 
- #ifndef __SNDWAV_COMMON_H  
 
- #define __SNDWAV_COMMON_H  
 
-   
 
- #include <stdio.h>  
 
- #include <stdlib.h>  
 
- #include <unistd.h>  
 
- #include <fcntl.h>  
 
- #include "wav_parser.h"  
 
-   
 
- typedef long long off64_t;  
 
-   
 
- typedef struct SNDPCMContainer {  
 
-     snd_pcm_t *handle;  
 
-     snd_output_t *log;  
 
-     snd_pcm_uframes_t chunk_size;  
 
-     snd_pcm_uframes_t buffer_size;  
 
-     snd_pcm_format_t format;  
 
-     uint16_t channels;  
 
-     size_t chunk_bytes;  
 
-     size_t bits_per_sample;  
 
-     size_t bits_per_frame;  
 
-   
 
-     uint8_t *data_buf;  
 
- } SNDPCMContainer_t;  
 
-   
 
- ssize_t SNDWAV_ReadPcm(SNDPCMContainer_t *sndpcm, size_t rcount);  
 
-   
 
- ssize_t SNDWAV_WritePcm(SNDPCMContainer_t *sndpcm, size_t wcount);  
 
-   
 
- int SNDWAV_SetParams(SNDPCMContainer_t *sndpcm, WAVContainer_t *wav);  
 
- #endif /* #ifndef __SNDWAV_COMMON_H */  
 
 
 
-   
 
- #include <assert.h>  
 
- #include <stdio.h>  
 
- #include <stdlib.h>  
 
- #include <unistd.h>  
 
- #include <fcntl.h>  
 
- #include <alsa/asoundlib.h>  
 
-   
 
- #include "sndwav_common.h"  
 
-   
 
- int SNDWAV_P_GetFormat(WAVContainer_t *wav, snd_pcm_format_t *snd_format)  
 
- {     
 
-     if (LE_SHORT(wav->format.format) != WAV_FMT_PCM)  
 
-         return -1;  
 
-       
 
-     switch (LE_SHORT(wav->format.sample_length)) {  
 
-     case 16:  
 
-         *snd_format = SND_PCM_FORMAT_S16_LE;  
 
-         break;  
 
-     case 8:  
 
-         *snd_format = SND_PCM_FORMAT_U8;  
 
-         break;  
 
-     default:  
 
-         *snd_format = SND_PCM_FORMAT_UNKNOWN;  
 
-         break;  
 
-     }  
 
-   
 
-     return 0;  
 
- }  
 
-   
 
- ssize_t SNDWAV_ReadPcm(SNDPCMContainer_t *sndpcm, size_t rcount)  
 
- {  
 
-     ssize_t r;  
 
-     size_t result = 0;  
 
-     size_t count = rcount;  
 
-     uint8_t *data = sndpcm->data_buf;  
 
-   
 
-     if (count != sndpcm->chunk_size) {  
 
-         count = sndpcm->chunk_size;  
 
-     }  
 
-   
 
-     while (count > 0) {  
 
-         r = snd_pcm_readi(sndpcm->handle, data, count);  
 
-           
 
-         if (r == -EAGAIN || (r >= 0 && (size_t)r < count)) {  
 
-             snd_pcm_wait(sndpcm->handle, 1000);  
 
-         } else if (r == -EPIPE) {  
 
-             snd_pcm_prepare(sndpcm->handle);  
 
-             fprintf(stderr, "<<<<<<<<<<<<<<< Buffer Underrun >>>>>>>>>>>>>>>/n");  
 
-         } else if (r == -ESTRPIPE) {  
 
-             fprintf(stderr, "<<<<<<<<<<<<<<< Need suspend >>>>>>>>>>>>>>>/n");  
 
-         } else if (r < 0) {  
 
-             fprintf(stderr, "Error snd_pcm_writei: [%s]", snd_strerror(r));  
 
-             exit(-1);  
 
-         }  
 
-           
 
-         if (r > 0) {  
 
-             result += r;  
 
-             count -= r;  
 
-             data += r * sndpcm->bits_per_frame / 8;  
 
-         }  
 
-     }  
 
-     return rcount;  
 
- }  
 
-   
 
- ssize_t SNDWAV_WritePcm(SNDPCMContainer_t *sndpcm, size_t wcount)  
 
- {  
 
-     ssize_t r;  
 
-     ssize_t result = 0;  
 
-     uint8_t *data = sndpcm->data_buf;  
 
-   
 
-     if (wcount < sndpcm->chunk_size) {  
 
-         snd_pcm_format_set_silence(sndpcm->format,   
 
-             data + wcount * sndpcm->bits_per_frame / 8,   
 
-             (sndpcm->chunk_size - wcount) * sndpcm->channels);  
 
-         wcount = sndpcm->chunk_size;  
 
-     }  
 
-     while (wcount > 0) {  
 
-         r = snd_pcm_writei(sndpcm->handle, data, wcount);  
 
-         if (r == -EAGAIN || (r >= 0 && (size_t)r < wcount)) {  
 
-             snd_pcm_wait(sndpcm->handle, 1000);  
 
-         } else if (r == -EPIPE) {  
 
-             snd_pcm_prepare(sndpcm->handle);  
 
-             fprintf(stderr, "<<<<<<<<<<<<<<< Buffer Underrun >>>>>>>>>>>>>>>/n");  
 
-         } else if (r == -ESTRPIPE) {              
 
-             fprintf(stderr, "<<<<<<<<<<<<<<< Need suspend >>>>>>>>>>>>>>>/n");          
 
-         } else if (r < 0) {  
 
-             fprintf(stderr, "Error snd_pcm_writei: [%s]", snd_strerror(r));  
 
-             exit(-1);  
 
-         }  
 
-         if (r > 0) {  
 
-             result += r;  
 
-             wcount -= r;  
 
-             data += r * sndpcm->bits_per_frame / 8;  
 
-         }  
 
-     }  
 
-     return result;  
 
- }  
 
-   
 
- int SNDWAV_SetParams(SNDPCMContainer_t *sndpcm, WAVContainer_t *wav)  
 
- {  
 
-     snd_pcm_hw_params_t *hwparams;  
 
-     snd_pcm_format_t format;  
 
-     uint32_t exact_rate;  
 
-     uint32_t buffer_time, period_time;  
 
-   
 
-     
 
-     snd_pcm_hw_params_alloca(&hwparams);  
 
-       
 
-     
 
-     if (snd_pcm_hw_params_any(sndpcm->handle, hwparams) < 0) {  
 
-         fprintf(stderr, "Error snd_pcm_hw_params_any/n");  
 
-         goto ERR_SET_PARAMS;  
 
-     }  
 
-   
 
-     if (snd_pcm_hw_params_set_access(sndpcm->handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED) < 0) {  
 
-         fprintf(stderr, "Error snd_pcm_hw_params_set_access/n");  
 
-         goto ERR_SET_PARAMS;  
 
-     }  
 
-   
 
-     
 
-     if (SNDWAV_P_GetFormat(wav, &format) < 0) {  
 
-         fprintf(stderr, "Error get_snd_pcm_format/n");  
 
-         goto ERR_SET_PARAMS;  
 
-     }  
 
-     if (snd_pcm_hw_params_set_format(sndpcm->handle, hwparams, format) < 0) {  
 
-         fprintf(stderr, "Error snd_pcm_hw_params_set_format/n");  
 
-         goto ERR_SET_PARAMS;  
 
-     }  
 
-     sndpcm->format = format;  
 
-   
 
-     
 
-     if (snd_pcm_hw_params_set_channels(sndpcm->handle, hwparams, LE_SHORT(wav->format.channels)) < 0) {  
 
-         fprintf(stderr, "Error snd_pcm_hw_params_set_channels/n");  
 
-         goto ERR_SET_PARAMS;  
 
-     }  
 
-     sndpcm->channels = LE_SHORT(wav->format.channels);  
 
-   
 
-     
 
-     
 
-     exact_rate = LE_INT(wav->format.sample_rate);  
 
-     if (snd_pcm_hw_params_set_rate_near(sndpcm->handle, hwparams, &exact_rate, 0) < 0) {  
 
-         fprintf(stderr, "Error snd_pcm_hw_params_set_rate_near/n");  
 
-         goto ERR_SET_PARAMS;  
 
-     }  
 
-     if (LE_INT(wav->format.sample_rate) != exact_rate) {  
 
-         fprintf(stderr, "The rate %d Hz is not supported by your hardware./n ==> Using %d Hz instead./n",   
 
-             LE_INT(wav->format.sample_rate), exact_rate);  
 
-     }  
 
-   
 
-     if (snd_pcm_hw_params_get_buffer_time_max(hwparams, &buffer_time, 0) < 0) {  
 
-         fprintf(stderr, "Error snd_pcm_hw_params_get_buffer_time_max/n");  
 
-         goto ERR_SET_PARAMS;  
 
-     }  
 
-     if (buffer_time > 500000) buffer_time = 500000;  
 
-     period_time = buffer_time / 4;  
 
-   
 
-     if (snd_pcm_hw_params_set_buffer_time_near(sndpcm->handle, hwparams, &buffer_time, 0) < 0) {  
 
-         fprintf(stderr, "Error snd_pcm_hw_params_set_buffer_time_near/n");  
 
-         goto ERR_SET_PARAMS;  
 
-     }  
 
-   
 
-     if (snd_pcm_hw_params_set_period_time_near(sndpcm->handle, hwparams, &period_time, 0) < 0) {  
 
-         fprintf(stderr, "Error snd_pcm_hw_params_set_period_time_near/n");  
 
-         goto ERR_SET_PARAMS;  
 
-     }  
 
-   
 
-     
 
-     if (snd_pcm_hw_params(sndpcm->handle, hwparams) < 0) {  
 
-         fprintf(stderr, "Error snd_pcm_hw_params(handle, params)/n");  
 
-         goto ERR_SET_PARAMS;  
 
-     }  
 
-   
 
-     snd_pcm_hw_params_get_period_size(hwparams, &sndpcm->chunk_size, 0);   
 
-     snd_pcm_hw_params_get_buffer_size(hwparams, &sndpcm->buffer_size);  
 
-     if (sndpcm->chunk_size == sndpcm->buffer_size) {        
 
-         fprintf(stderr, ("Can‘t use period equal to buffer size (%lu == %lu)/n"), sndpcm->chunk_size, sndpcm->buffer_size);         
 
-         goto ERR_SET_PARAMS;  
 
-     }  
 
-   
 
-     sndpcm->bits_per_sample = snd_pcm_format_physical_width(format);  
 
-     sndpcm->bits_per_frame = sndpcm->bits_per_sample * LE_SHORT(wav->format.channels);  
 
-       
 
-     sndpcm->chunk_bytes = sndpcm->chunk_size * sndpcm->bits_per_frame / 8;  
 
-   
 
-     
 
-     sndpcm->data_buf = (uint8_t *)malloc(sndpcm->chunk_bytes);  
 
-     if (!sndpcm->data_buf) {  
 
-         fprintf(stderr, "Error malloc: [data_buf]/n");  
 
-         goto ERR_SET_PARAMS;  
 
-     }  
 
-   
 
-     return 0;  
 
-   
 
- ERR_SET_PARAMS:  
 
-     return -1;  
 
- }  
 
 
 
-   
 
- #include <stdio.h>  
 
- #include <malloc.h>  
 
- #include <unistd.h>  
 
- #include <stdlib.h>  
 
- #include <string.h>  
 
- #include <getopt.h>  
 
- #include <fcntl.h>  
 
- #include <ctype.h>  
 
- #include <errno.h>  
 
- #include <limits.h>  
 
- #include <time.h>  
 
- #include <locale.h>  
 
- #include <sys/unistd.h>  
 
- #include <sys/stat.h>  
 
- #include <sys/types.h>  
 
- #include <alsa/asoundlib.h>  
 
- #include <assert.h>  
 
- #include "wav_parser.h"  
 
- #include "sndwav_common.h"  
 
-   
 
- ssize_t SNDWAV_P_SaveRead(int fd, void *buf, size_t count)  
 
- {  
 
-     ssize_t result = 0, res;  
 
-   
 
-     while (count > 0) {  
 
-         if ((res = read(fd, buf, count)) == 0)  
 
-             break;  
 
-         if (res < 0)  
 
-             return result > 0 ? result : res;  
 
-         count -= res;  
 
-         result += res;  
 
-         buf = (char *)buf + res;  
 
-     }  
 
-     return result;  
 
- }  
 
-   
 
- void SNDWAV_Play(SNDPCMContainer_t *sndpcm, WAVContainer_t *wav, int fd)  
 
- {  
 
-     int load, ret;  
 
-     off64_t written = 0;  
 
-     off64_t c;  
 
-     off64_t count = LE_INT(wav->chunk.length);  
 
-   
 
-     load = 0;  
 
-     while (written < count) {  
 
-         
 
-         do {  
 
-             c = count - written;  
 
-             if (c > sndpcm->chunk_bytes)  
 
-                 c = sndpcm->chunk_bytes;  
 
-             c -= load;  
 
-   
 
-             if (c == 0)  
 
-                 break;  
 
-             ret = SNDWAV_P_SaveRead(fd, sndpcm->data_buf + load, c);  
 
-             if (ret < 0) {  
 
-                 fprintf(stderr, "Error safe_read/n");  
 
-                 exit(-1);  
 
-             }  
 
-             if (ret == 0)  
 
-                 break;  
 
-             load += ret;  
 
-         } while ((size_t)load < sndpcm->chunk_bytes);  
 
-   
 
-         
 
-         load = load * 8 / sndpcm->bits_per_frame;  
 
-         ret = SNDWAV_WritePcm(sndpcm, load);  
 
-         if (ret != load)  
 
-             break;  
 
-           
 
-         ret = ret * sndpcm->bits_per_frame / 8;  
 
-         written += ret;  
 
-         load = 0;  
 
-     }  
 
- }  
 
-   
 
- int main(int argc, char *argv[])  
 
- {  
 
-     char *filename;  
 
-     char *devicename = "default";  
 
-     int fd;  
 
-     WAVContainer_t wav;  
 
-     SNDPCMContainer_t playback;  
 
-       
 
-     if (argc != 2) {  
 
-         fprintf(stderr, "Usage: ./lplay <FILENAME>/n");  
 
-         return -1;  
 
-     }  
 
-       
 
-     memset(&playback, 0x0, sizeof(playback));  
 
-   
 
-     filename = argv[1];  
 
-     fd = open(filename, O_RDONLY);  
 
-     if (fd < 0) {  
 
-         fprintf(stderr, "Error open [%s]/n", filename);  
 
-         return -1;  
 
-     }  
 
-       
 
-     if (WAV_ReadHeader(fd, &wav) < 0) {  
 
-         fprintf(stderr, "Error WAV_Parse [%s]/n", filename);  
 
-         goto Err;  
 
-     }  
 
-   
 
-     if (snd_output_stdio_attach(&playback.log, stderr, 0) < 0) {  
 
-         fprintf(stderr, "Error snd_output_stdio_attach/n");  
 
-         goto Err;  
 
-     }  
 
-   
 
-     if (snd_pcm_open(&playback.handle, devicename, SND_PCM_STREAM_PLAYBACK, 0) < 0) {  
 
-         fprintf(stderr, "Error snd_pcm_open [ %s]/n", devicename);  
 
-         goto Err;  
 
-     }  
 
-   
 
-     if (SNDWAV_SetParams(&playback, &wav) < 0) {  
 
-         fprintf(stderr, "Error set_snd_pcm_params/n");  
 
-         goto Err;  
 
-     }  
 
-     snd_pcm_dump(playback.handle, playback.log);  
 
-   
 
-     SNDWAV_Play(&playback, &wav, fd);  
 
-   
 
-     snd_pcm_drain(playback.handle);  
 
-   
 
-     close(fd);  
 
-     free(playback.data_buf);  
 
-     snd_output_close(playback.log);  
 
-     snd_pcm_close(playback.handle);  
 
-     return 0;  
 
-   
 
- Err:  
 
-     close(fd);  
 
-     if (playback.data_buf) free(playback.data_buf);  
 
-     if (playback.log) snd_output_close(playback.log);  
 
-     if (playback.handle) snd_pcm_close(playback.handle);  
 
-     return -1;  
 
- }  
 
 
 
-   
 
- #include <stdio.h>  
 
- #include <malloc.h>  
 
- #include <unistd.h>  
 
- #include <stdlib.h>  
 
- #include <string.h>  
 
- #include <getopt.h>  
 
- #include <fcntl.h>  
 
- #include <ctype.h>  
 
- #include <errno.h>  
 
- #include <limits.h>  
 
- #include <time.h>  
 
- #include <locale.h>  
 
- #include <sys/unistd.h>  
 
- #include <sys/stat.h>  
 
- #include <sys/types.h>  
 
- #include <alsa/asoundlib.h>  
 
- #include <assert.h>  
 
- #include "wav_parser.h"  
 
- #include "sndwav_common.h"  
 
-   
 
- #define DEFAULT_CHANNELS         (2)  
 
- #define DEFAULT_SAMPLE_RATE      (8000)  
 
- #define DEFAULT_SAMPLE_LENGTH    (16)  
 
- #define DEFAULT_DURATION_TIME    (10)  
 
-   
 
- int SNDWAV_PrepareWAVParams(WAVContainer_t *wav)  
 
- {  
 
-     assert(wav);  
 
-   
 
-     uint16_t channels = DEFAULT_CHANNELS;  
 
-     uint16_t sample_rate = DEFAULT_SAMPLE_RATE;  
 
-     uint16_t sample_length = DEFAULT_SAMPLE_LENGTH;  
 
-     uint32_t duration_time = DEFAULT_DURATION_TIME;  
 
-   
 
-     
 
-     wav->header.magic = WAV_RIFF;  
 
-     wav->header.type = WAV_WAVE;  
 
-     wav->format.magic = WAV_FMT;  
 
-     wav->format.fmt_size = LE_INT(16);  
 
-     wav->format.format = LE_SHORT(WAV_FMT_PCM);  
 
-     wav->chunk.type = WAV_DATA;  
 
-   
 
-     
 
-     wav->format.channels = LE_SHORT(channels);  
 
-     wav->format.sample_rate = LE_INT(sample_rate);  
 
-     wav->format.sample_length = LE_SHORT(sample_length);  
 
-   
 
-     
 
-     wav->format.blocks_align = LE_SHORT(channels * sample_length / 8);  
 
-     wav->format.bytes_p_second = LE_INT((uint16_t)(wav->format.blocks_align) * sample_rate);  
 
-       
 
-     wav->chunk.length = LE_INT(duration_time * (uint32_t)(wav->format.bytes_p_second));  
 
-     wav->header.length = LE_INT((uint32_t)(wav->chunk.length) +/  
 
-         sizeof(wav->chunk) + sizeof(wav->format) + sizeof(wav->header) - 8);  
 
-   
 
-     return 0;  
 
- }  
 
-   
 
- void SNDWAV_Record(SNDPCMContainer_t *sndpcm, WAVContainer_t *wav, int fd)  
 
- {  
 
-     off64_t rest;  
 
-     size_t c, frame_size;  
 
-       
 
-     if (WAV_WriteHeader(fd, wav) < 0) {  
 
-         exit(-1);  
 
-     }  
 
-   
 
-     rest = wav->chunk.length;  
 
-     while (rest > 0) {  
 
-         c = (rest <= (off64_t)sndpcm->chunk_bytes) ? (size_t)rest : sndpcm->chunk_bytes;  
 
-         frame_size = c * 8 / sndpcm->bits_per_frame;  
 
-         if (SNDWAV_ReadPcm(sndpcm, frame_size) != frame_size)  
 
-             break;  
 
-           
 
-         if (write(fd, sndpcm->data_buf, c) != c) {  
 
-             fprintf(stderr, "Error SNDWAV_Record[write]/n");  
 
-             exit(-1);  
 
-         }  
 
-   
 
-         rest -= c;  
 
-     }  
 
- }  
 
-   
 
- int main(int argc, char *argv[])  
 
- {  
 
-     char *filename;  
 
-     char *devicename = "default";  
 
-     int fd;  
 
-     WAVContainer_t wav;  
 
-     SNDPCMContainer_t record;  
 
-       
 
-     if (argc != 2) {  
 
-         fprintf(stderr, "Usage: ./lrecord <FILENAME>/n");  
 
-         return -1;  
 
-     }  
 
-       
 
-     memset(&record, 0x0, sizeof(record));  
 
-   
 
-     filename = argv[1];  
 
-     remove(filename);  
 
-     if ((fd = open(filename, O_WRONLY | O_CREAT, 0644)) == -1) {  
 
-         fprintf(stderr, "Error open: [%s]/n", filename);  
 
-         return -1;  
 
-     }  
 
-   
 
-     if (snd_output_stdio_attach(&record.log, stderr, 0) < 0) {  
 
-         fprintf(stderr, "Error snd_output_stdio_attach/n");  
 
-         goto Err;  
 
-     }  
 
-   
 
-     if (snd_pcm_open(&record.handle, devicename, SND_PCM_STREAM_CAPTURE, 0) < 0) {  
 
-         fprintf(stderr, "Error snd_pcm_open [ %s]/n", devicename);  
 
-         goto Err;  
 
-     }  
 
-   
 
-     if (SNDWAV_PrepareWAVParams(&wav) < 0) {  
 
-         fprintf(stderr, "Error SNDWAV_PrepareWAVParams/n");  
 
-         goto Err;  
 
-     }  
 
-   
 
-     if (SNDWAV_SetParams(&record, &wav) < 0) {  
 
-         fprintf(stderr, "Error set_snd_pcm_params/n");  
 
-         goto Err;  
 
-     }  
 
-     snd_pcm_dump(record.handle, record.log);  
 
-   
 
-     SNDWAV_Record(&record, &wav, fd);  
 
-   
 
-     snd_pcm_drain(record.handle);  
 
-   
 
-     close(fd);  
 
-     free(record.data_buf);  
 
-     snd_output_close(record.log);  
 
-     snd_pcm_close(record.handle);  
 
-     return 0;  
 
-   
 
- Err:  
 
-     close(fd);  
 
-     remove(filename);  
 
-     if (record.data_buf) free(record.data_buf);  
 
-     if (record.log) snd_output_close(record.log);  
 
-     if (record.handle) snd_pcm_close(record.handle);  
 
-     return -1;  
 
- }  
 
基于ALSA的WAV播放和录音程序,布布扣,bubuko.com
基于ALSA的WAV播放和录音程序
标签:android   blog   http   os   io   文件   数据   for   
原文地址:http://www.cnblogs.com/cainiaoaixuexi/p/3920437.html