本设计思路:先打开一个普通wav音频文件,从定义的文件头前面的44个字节中,取出文件头的定义消息,置于一个文件头的结构体中。然后打开alsa音频驱动,从文件头结构体取出采样精度,声道数,采样频率三个重要参数,利用alsa音频驱动的API设置好参数,最后打开wav文件,定位到数据区,把音频数据依次写到音频驱动中去,开始播放,当写入完成后,退出写入的循环。

注意:本设计需要alsa的libasound-dev的库,编译链接时需要连接 —lasound.

#include<stdio.h>
#include<stdlib.h>
#include <string.h>
#include <alsa/asoundlib.h>

struct WAV_HEADER
{
    char rld[4];    //riff 标志符号
    int rLen;   
    char wld[4];    //格式类型(wave)
    char fld[4];    //"fmt"

int fLen;   //sizeof(wave format matex)
    
    short wFormatTag;   //编码格式
    short wChannels;    //声道数
    int   nSamplesPersec ;  //采样频率
    int   nAvgBitsPerSample;//WAVE文件采样大小
    short  wBlockAlign; //块对齐
    short wBitsPerSample;   //WAVE文件采样大小
    
    char dld[4];        //”data“
    int wSampleLength;  //音频数据的大小

} wav_header;

int set_pcm_play(FILE *fp);

int main(int argc,char *argv[])
{

if(argc!=2)
    {
        printf("Usage:wav-player+wav file name\n");
        exit(1);
    }

int nread;
    FILE *fp;
    fp=fopen(argv[1],"rb");
    if(fp==NULL)
    {
        perror("open file failed:\n");
        exit(1);
    }
    
    nread=fread(&wav_header,1,sizeof(wav_header),fp);
    printf("nread=%d\n",nread);
    
    //printf("RIFF 标志%s\n",wav_header.rld);
    printf("文件大小rLen:%d\n",wav_header.rLen);
    //printf("wld=%s\n",wav_header.wld);
    //printf("fld=%s\n",wav_header.fld);
    
   // printf("fLen=%d\n",wav_header.fLen);
    
    //printf("wFormatTag=%d\n",wav_header.wFormatTag);
    printf("声道数:%d\n",wav_header.wChannels);
    printf("采样频率:%d\n",wav_header.nSamplesPersec);
    //printf("nAvgBitsPerSample=%d\n",wav_header.nAvgBitsPerSample);
    //printf("wBlockAlign=%d\n",wav_header.wBlockAlign);
    printf("采样的位数:%d\n",wav_header.wBitsPerSample);
    
   // printf("data=%s\n",wav_header.dld);
    printf("wSampleLength=%d\n",wav_header.wSampleLength);
    
    
    
    
    
    set_pcm_play(fp);
    return 0;
}

int set_pcm_play(FILE *fp)
{
        int    rc;
        int    ret;
        int    size;
        snd_pcm_t*       handle;        //PCI设备句柄
        snd_pcm_hw_params_t*      params;//硬件信息和PCM流配置
        unsigned int       val;
        int                dir=0;
        snd_pcm_uframes_t  frames;
        char   *buffer;
        int channels=wav_header.wChannels;
        int frequency=wav_header.nSamplesPersec;
        int bit=wav_header.wBitsPerSample;
        int datablock=wav_header.wBlockAlign;
        unsigned char ch[100];  //用来存储wav文件的头信息
    
    
        
        rc=snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, 0);
        if(rc<0)
        {
                perror("\nopen PCM device failed:");
                exit(1);
        }

snd_pcm_hw_params_alloca(&params); //分配params结构体
        if(rc<0)
        {
                perror("\nsnd_pcm_hw_params_alloca:");
                exit(1);
        }
         rc=snd_pcm_hw_params_any(handle, params);//初始化params
        if(rc<0)
        {
                perror("\nsnd_pcm_hw_params_any:");
                exit(1);
        }
        rc=snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED);                                 //初始化访问权限
        if(rc<0)
        {
                perror("\nsed_pcm_hw_set_access:");
                exit(1);

}

//采样位数
        switch(bit/8)
        {
        case 1:snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_U8);
                break ;
        case 2:snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE);
                break ;
        case 3:snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S24_LE);
                break ;

}
        rc=snd_pcm_hw_params_set_channels(handle, params, channels);  //设置声道,1表示单声>道,2表示立体声
        if(rc<0)
        {
                perror("\nsnd_pcm_hw_params_set_channels:");
                exit(1);
        }
        val = frequency;
        rc=snd_pcm_hw_params_set_rate_near(handle, params, &val, &dir);  //设置>频率
        if(rc<0)
        {
                perror("\nsnd_pcm_hw_params_set_rate_near:");
                exit(1);
        }

rc = snd_pcm_hw_params(handle, params);
        if(rc<0)
        {
        perror("\nsnd_pcm_hw_params: ");
        exit(1);
        }

rc=snd_pcm_hw_params_get_period_size(params, &frames, &dir);  /*获取周期
长度*/
        if(rc<0)
        {
                perror("\nsnd_pcm_hw_params_get_period_size:");
                exit(1);
        }

size = frames * datablock;   /*4 代表数据快长度*/

buffer =(char*)malloc(size);
    fseek(fp,58,SEEK_SET);  //定位歌曲到数据区

while (1)
        {
                memset(buffer,0,sizeof(buffer));
                ret = fread(buffer, 1, size, fp);
                if(ret == 0)
                {
                        printf("歌曲写入结束\n");
                        break;
                }
                 else if (ret != size)
                {
                 }
                // 写音频数据到PCM设备  
        while(ret = snd_pcm_writei(handle, buffer, frames)<0)
           {
                 usleep(2000);  
                 if (ret == -EPIPE)
                {
                  /* EPIPE means underrun */
                  fprintf(stderr, "underrun occurred\n");
                  //完成硬件参数设置,使设备准备好  
                  snd_pcm_prepare(handle);
                 }
                 else if (ret < 0)
                 {
                          fprintf(stderr,
                      "error from writei: %s\n",
                      snd_strerror(ret));
                 }
            }

}

snd_pcm_drain(handle);
        snd_pcm_close(handle);
        free(buffer);
        return 0;
}

基于Linux ALSA音频驱动的wav文件解析及播放程序 作者:东方钰

基于Linux ALSA音频驱动的wav文件解析及播放程序 2012的更多相关文章

  1. 嵌入式驱动开发之---Linux ALSA音频驱动(一)

    本文的部分内容参考来自DroidPhone的博客(http://blog.csdn.net/droidphone/article/details/6271122),关于ALSA写得很不错的文章,只是少 ...

  2. Linux ALSA声卡驱动之二:声卡的创建

    1. struct snd_card 1.1. snd_card是什么 snd_card可以说是整个ALSA音频驱动最顶层的一个结构,整个声卡的软件逻辑结构开始于该结构,几乎所有与声音相关的逻辑设备都 ...

  3. Linux ALSA声卡驱动之八:ASoC架构中的Platform

    1.  Platform驱动在ASoC中的作用 前面几章内容已经说过,ASoC被分为Machine,Platform和Codec三大部件,Platform驱动的主要作用是完成音频数据的管理,最终通过C ...

  4. Linux ALSA声卡驱动之七:ASoC架构中的Codec

    1.  Codec简介(ad/da) 在移动设备中,Codec的作用可以归结为4种,分别是: 对PCM等信号进行D/A转换,把数字的音频信号转换为模拟信号 对Mic.Linein或者其他输入源的模拟信 ...

  5. Linux ALSA声卡驱动之六:ASoC架构中的Machine

    前面一节的内容我们提到,ASoC被分为Machine.Platform和Codec三大部分,其中的Machine驱动负责Platform和Codec之间的耦合以及部分和设备或板子特定的代码,再次引用上 ...

  6. Linux ALSA 音频库 配置和使用

    ALSA应用库是核心功能,而alsa-utils是一些工具功能集合库.单纯地播放一个wav文件,使用alsa-utils即可,如果还需要合成音频.调试音频质量,那么就需要ALSA应用库. 欲安装使用A ...

  7. alsa音频驱动科普第一课

    做linux音频编程对alsa应该不陌生. 但是对于刚接触这块技术的同学来说是一件困难的事情.原因在于:网上关于alsa的资料太少了,特别国内的资料更是大部分重复.对于初学者来说特别苦恼. 由于笔者经 ...

  8. Linux ALSA声卡驱动之三:PCM设备的创建

    声明:本博内容均由http://blog.csdn.net/droidphone原创,转载请注明出处,谢谢! 1. PCM是什么 模数转换 模拟信号经过pcm(脉冲编码调制)后为pcm数据: PCM是 ...

  9. Linux ALSA声卡驱动之四:Control设备的创建

    声明:本博内容均由http://blog.csdn.net/droidphone原创,转载请注明出处,谢谢! Control接口 Control接口主要让用户空间的应用程序(alsa-lib)可以访问 ...

随机推荐

  1. 公众号和app和web都是客户端,都可以对接一个后台

    1.公众号和app和web都是客户端,都可以对接一个后台 2.域名中包含端口号吗?:不包括,不包括 3.目前在IIS服务器上搭建了一个网站,域名也申请了,可是80端口不能使用,可以使用8000,每次访 ...

  2. springmvc 监听器getWriter() has already been called for this response问题

    springmvc 监听器getWriter() has already been called for this response问题 在监听器中,如果return true,就不要使用 respo ...

  3. HDU 3104 Combination Lock(数学题)

    题目链接:http://acm.hdu.edu.cn/showproblem.php? pid=3104 Problem Description A combination lock consists ...

  4. iOS 在 ARC 环境下 dealloc 的使用、理解误区

    iOS 在 ARC 环境下 dealloc 的使用.理解误区 太阳火神的漂亮人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商业用途-保持一致&qu ...

  5. Oracle 11gR2 List-Range分区实验

    一.实验目的 採用List-Range分区,对主分区指定表空间或者对子分区指定表空的不同情况,測试例如以下内容: 1.对List主分区不指定表空间.对Range子分区指定表空间,数据实际存储在哪个表空 ...

  6. DotNetBar.Bar菜单的使用

    DotNetBar.Bar菜单的使用 老帅     在C#中使用控件DevComponents.DotNetBar.Bar时,怎样设计菜单呢?      1.拖放生成一个菜单容器      拖放一个D ...

  7. JavaScript:DOM对象

    ylbtech-JavaScript:DOM对象 1. HTML DOM Document 对象返回顶部 1. HTML DOM Document 对象 HTML DOM 节点 在 HTML DOM ...

  8. PIE加载自定义服务数据详细介绍

    这段时间我一直在研究如何用PIE加载在线地图服务,遇到了许多问题,多亏了技术员小姐姐的帮助,才让我能正确加载ArcGIS Online在线服务.天地图在线地图和谷歌在线地图.我是根据博客园PIE官方博 ...

  9. Windows下配置SVN服务器

    2013-09-03 21:40:34 1. 下载安装svn软件 1.1 服务端svn 下载地址:http://subversion.apache.org/packages.html 默认安装路径:D ...

  10. Socket server

    Socket server的使用方法(精华部分),仅供自用. class MyServer(socketserver.BaseRequestHandler): def handle(self): wh ...