• 使用 ALSAlib 播放 wav


    在 ARM 2440 开发板上正常播放 16bit  44100 采样率的wav , 为了程序简单,没有判断返回值。

    补充,在 ubunto 上也能正常播放。

    编译方法: arm-linux-gcc -lasound wplay.c -o wplay  或在 ubuntu 上编译 gcc -lasound wplay.c -o wplay 

      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 #include <string.h>
      4 #include <sys/types.h>
      5 #include <sys/stat.h>
      6 #include <fcntl.h>
      7 #include <sys/mman.h>
      8 #include <alsa/asoundlib.h>
      9 #ifndef WORD
     10 #define WORD unsigned short
     11 #endif
     12 
     13 #ifndef DWORD
     14 #define DWORD unsigned int
     15 #endif
     16     
     17 struct RIFF_HEADER
     18 {
     19     char szRiffID[4];  // 'R','I','F','F'
     20     DWORD dwRiffSize;
     21     char szRiffFormat[4]; // 'W','A','V','E'
     22 };
     23 
     24 struct WAVE_FORMAT
     25 {
     26     WORD wFormatTag;
     27     WORD wChannels;
     28     DWORD dwSamplesPerSec;
     29     DWORD dwAvgBytesPerSec;
     30     WORD wBlockAlign;
     31     WORD wBitsPerSample;
     32 };
     33 
     34 struct FMT_BLOCK
     35 {
     36     char  szFmtID[4]; // 'f','m','t',' '
     37     DWORD  dwFmtSize;
     38     struct WAVE_FORMAT wavFormat;
     39 };
     40 
     41 struct DATA_BLOCK
     42 {
     43     char szDataID[4]; // 'd','a','t','a'
     44     DWORD dwDataSize;
     45 };
     46 
     47 void read_wav(unsigned char *wav_buf, int *fs, int *channels, int *bits_per_sample, int *wav_size, int *file_size)
     48 {
     49     struct RIFF_HEADER *headblk;
     50     struct FMT_BLOCK   *fmtblk;
     51     struct DATA_BLOCK  *datblk;
     52 
     53     headblk = (struct RIFF_HEADER *) wav_buf;
     54     fmtblk  = (struct FMT_BLOCK *) &headblk[1];
     55     datblk  = (struct DATA_BLOCK *) &fmtblk[1];
     56     
     57     *file_size = headblk->dwRiffSize;
     58 
     59     //采样频率
     60     *fs         = fmtblk->wavFormat.dwSamplesPerSec;
     61 
     62     //通道数
     63     *channels  = fmtblk->wavFormat.wChannels;
     64     
     65     *wav_size  = datblk->dwDataSize;
     66     //采样bit数 16 24
     67     *bits_per_sample = fmtblk->wavFormat.wBitsPerSample;
     68 }
     69 
     70 int main(int argc, char ** argv)
     71 {
     72     int fs, channels, bits_per_sample, wav_size, file_size;
     73     unsigned char *wav_buf;
     74     unsigned char *audio_buf;
     75     unsigned char *audio_p;
     76     int fd;
     77     struct stat stat;
     78     
     79     int size;
     80     snd_pcm_t *playback_handle;
     81     snd_pcm_hw_params_t *hw_params;//硬件信息和PCM流配置
     82     
     83     snd_pcm_uframes_t chunk_size = 0;
     84     unsigned int rate;
     85     snd_pcm_format_t format;
     86 
     87     if(2 != argc)
     88     {
     89         printf("usage:%s wav file
    ", argv[0]);
     90         return -1;
     91     }
     92 
     93     fd = open(argv[1], O_RDONLY);
     94     fstat(fd, &stat);
     95     wav_buf = mmap(NULL, stat.st_size, PROT_READ, MAP_SHARED, fd, 0);
     96     read_wav(wav_buf, &fs, &channels, &bits_per_sample, &wav_size, &file_size);
     97     printf("wav format: fs = %d, channels = %d, bits_per_sample = %d, wav_size = %d file_size = %d
    
    ", fs, channels, bits_per_sample, wav_size, file_size);
     98     
     99     //真实wav 跳过头部
    100     audio_buf = wav_buf + sizeof(struct RIFF_HEADER) + sizeof(struct FMT_BLOCK) + sizeof(struct DATA_BLOCK);
    101     
    102     rate = fs;
    103     //初始化声卡
    104     //1. 打开PCM,最后一个参数为0意味着标准配置
    105     if (0 > snd_pcm_open(&playback_handle, "default", SND_PCM_STREAM_PLAYBACK, 0)) 
    106     {
    107         printf("snd_pcm_open err
    ");
    108         return -1;
    109     }
    110     //2. 分配snd_pcm_hw_params_t结构体
    111     if(0 > snd_pcm_hw_params_malloc (&hw_params))
    112     {
    113         printf("snd_pcm_hw_params_malloc err
    ");
    114         return -1;
    115     }
    116     //3. 初始化hw_params
    117     if(0 > snd_pcm_hw_params_any (playback_handle, hw_params))
    118     {
    119         printf("snd_pcm_hw_params_any err
    ");
    120         return -1;
    121     }
    122     //4. 初始化访问权限
    123     if (0 > snd_pcm_hw_params_set_access (playback_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) 
    124     {
    125         printf("snd_pcm_hw_params_any err
    ");
    126         return -1;
    127     }
    128     //5. 初始化采样格式SND_PCM_FORMAT_U8,8位
    129     if(8 == bits_per_sample)
    130     {
    131         if (0 > snd_pcm_hw_params_set_format (playback_handle, hw_params, SND_PCM_FORMAT_U8)) 
    132         {
    133             printf("snd_pcm_hw_params_set_format err
    ");
    134             return -1;
    135         }
    136         format = SND_PCM_FORMAT_U8;
    137     }
    138     
    139     if(16 == bits_per_sample)
    140     {
    141         if (0 > snd_pcm_hw_params_set_format (playback_handle, hw_params, SND_PCM_FORMAT_S16_LE)) 
    142         {
    143             printf("snd_pcm_hw_params_set_format err
    ");
    144             return -1;
    145         }
    146         format = SND_PCM_FORMAT_S16_LE;
    147     }
    148     //6. 设置采样率
    149     if (0 > snd_pcm_hw_params_set_rate_near (playback_handle, hw_params, &rate, 0)) 
    150     {
    151         printf("snd_pcm_hw_params_set_rate_near err
    ");
    152         return -1;
    153     }
    154     //7. 设置通道数量
    155     if (0 > snd_pcm_hw_params_set_channels(playback_handle, hw_params, 2)) 
    156     {
    157         printf("snd_pcm_hw_params_set_channels err
    ");
    158         return -1;
    159     }
    160     
    161     //8. 设置hw_params    
    162     if (0 > snd_pcm_hw_params (playback_handle, hw_params)) 
    163     {
    164         printf("snd_pcm_hw_params err
    ");
    165         return -1;
    166     }
    167 
    168     snd_pcm_hw_params_get_period_size(hw_params, &chunk_size, 0);
    169     
    170     snd_pcm_hw_params_free (hw_params);
    171     if (0 > snd_pcm_prepare (playback_handle)) 
    172     {
    173         printf("snd_pcm_prepare err
    ");
    174         return -1;
    175     }
    176     //chunk_size = ?;
    177     printf("chunk_size:%ld 
    ", chunk_size);
    178     audio_p = audio_buf;
    179     while((audio_p - audio_buf) <= stat.st_size)
    180     {
    181         snd_pcm_writei(playback_handle, audio_p, chunk_size);
    182         audio_p += chunk_size * 4; //16位 双声道
    183     }
    184     printf("play ok 
    ");
    185     snd_pcm_close(playback_handle);
    186     return 0;
    187 }
  • 相关阅读:
    javaScript对象
    javaScript基础
    使用javaScript和JQuery制作经典面试题:光棒效果
    Animate自定义动画
    使用jQuery快速高效制作网页交互特效
    jQuery中绑定事件bind() on() live() one()的异同
    小笔记1(Get请求)

    this关键字
    Eclipse断点调试(下)
  • 原文地址:https://www.cnblogs.com/ningci/p/6857043.html
Copyright © 2020-2023  润新知