因为客户需要用到wav文件来测试播放我们的平台,而客户的应用程序,用在我们的平台上,会有一些问题,所以,我需要从网络上找开源的wav的播放器,终于在网络上找到了wavplay播放器.虽然是基于OSS架构的wav的播放器,不过没有关系,自己还是先来熟悉这个开源的代码吧, 最新的版本是2.0版本,源码的下载地址如下:

http://sourceforge.net/projects/wavplay/?source=dlp 节后抽个时间将其移植到ARM平台上去,这个小软件不管是用来测试,还是用来移植到实际的项目,对我们来说,都是很好的一个参考源码。你说是不?

一:wav文件格式 [引用网络,已做过修改]

wave文件作为多媒体中使用的声波文件格式之一,它是以RIFF格式为标准的。RIFF是英文Resource Interchange File Format的缩写,每个WAVE文件的头四个字节便是“RIFF”,WAVE文件是由若干个Chunk组成的。按照在文件中的出现位置包括:RIFF WAVE Chunk, Format Chunk, Fact Chunk(可选), Data Chunk。如下图所示:

其中除了Fact Chunk外,其他三个Chunk是必须的。每个Chunk有各自的ID,位于Chunk最开始位置,作为标示,而且均为4个字节。并且紧跟在ID后面的是Chunk大小(去除ID和Size所占的字节数后剩下的其他字节数目),4个字节表示,低字节表示数值低位,高字节表示数值高位。下面具体介绍各个Chunk内容。注意: 所有数值表示均为低字节表示低位,高字节表示高位。

1):RIFF WAVE Chunk

以'FIFF'作为标示,然后紧跟着为size字段,该size是整个wav文件大小减去ID和Size所占用的字节数,即FileLen - 8 = Size。然后是Type字段,为'WAVE',表示是wav文件。

2):Format Chunk

以'fmt '作为标示。一般情况下Size为16,此时最后附加信息没有;如果为18,则最后多了2个字节的附加信息。主要由一些软件制成的wav格式中含有该2个字节的附加信息。

3):Fact Chunk

Fact Chunk是可选字段,一般当wav文件由某些软件转化而成,则包含该Chunk。

4):Data Chunk

Data Chunk是真正保存wav数据的地方,以'data'作为该Chunk的标示。然后是数据的大小。紧接着就是wav数据。根据Format Chunk中的声道数以及采样bit数,wav数据的bit位置可以分成以下几种形式:

二:wav文件格式解码

具体的代码,可以仔细研究wavplay的源码中的wavfile.c和wavfile.h文件,这两个文件主要是对wav文件格式进行解码,具体的部分代码如下:

/* $Id: wavfile.c,v 1.3 2009/11/30 15:02:31 ve3wwg Exp $

* Copyright: wavfile.c (c) Erik de Castro Lopo  erikd@zip.com.au

*

* wavfile.c - Functions for reading and writing MS-Windoze .WAV files.

*

* This  program is free software; you can redistribute it and/or modify it

* under the  terms  of  the GNU General Public License as published by the

* Free Software Foundation.

*

* This  program  is  distributed  in  the hope that it will be useful, but

* WITHOUT   ANY   WARRANTY;   without   even  the   implied   warranty  of

* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General

* Public License for more details (licensed by file COPYING or GPLv*).

*

* This code was originally written to manipulate Windoze .WAV files

* under i386 Linux (erikd@zip.com.au).

*

* ve3wwg@gmail.com

*/

staticconstcharrcsid[] ="$Id: wavfile.c,v 1.3 2009/11/30 15:02:31 ve3wwg Exp $";

#include

#include

#include

#include

#include

#include "wavplay.h"

#define     BUFFERSIZE          1024

#define     PCM_WAVE_FORMAT     1

#define     TRUE            1

#define     FALSE           0

typedefstruct

{   u_long     dwSize ;

u_short    wFormatTag ;

u_short    wChannels ;

u_long     dwSamplesPerSec ;

u_long     dwAvgBytesPerSec ;

u_short    wBlockAlign ;

u_short    wBitsPerSample ;

} WAVEFORMAT ;

typedefstruct

{   charRiffID [4] ;

u_long      RiffSize ;

charWaveID [4] ;

charFmtID  [4] ;

u_long      FmtSize ;

u_short     wFormatTag ;

u_short     nChannels ;

u_long      nSamplesPerSec ;

u_long      nAvgBytesPerSec ;

u_short     nBlockAlign ;

u_short     wBitsPerSample ;

charDataID [4] ;

u_long      nDataBytes ;

} WAVE_HEADER ;

/*=================================================================================================*/

char*  findchunk (char* s1,char* s2,size_tn) ;

/*=================================================================================================*/

staticWAVE_HEADER  waveheader =

{   { 'R','I','F','F'},

0,

{ 'W','A','V','E'},

{ 'f','m','t',' '},

16,                             /* FmtSize*/

PCM_WAVE_FORMAT,                        /* wFormatTag*/

0,                              /* nChannels*/

0,

0,

0,

0,

{ 'd','a','t','a'},

0

} ; /* waveheader*/

staticErrFunc v_erf;/* wwg: Error reporting function */

/*

* Error reporting function for this source module:

*/

staticvoid

err(constchar*format,...) {

va_listap;

if( v_erf == NULL )

return;/* Only report error if we have function */

va_start(ap,format);

v_erf(format,ap);           /* Use caller's supplied function */

va_end(ap);

}

intWaveWriteHeader (intwavefile,intchannels, u_long samplerate,intsampbits, u_long samples, ErrFunc erf)

{   u_long      databytes ;

u_short     blockalign ;

v_erf = erf;                /* wwg: Set error reporting function */

if( wavefile

err("Invalid file descriptor");

returnWW_BADOUTPUTFILE ;

}

sampbits   = (sampbits == 16) ? 16 : 8 ;

blockalign = ((sampbits == 16) ? 2 : 1) * channels ;

databytes  = samples * (u_long) blockalign ;

waveheader.RiffSize        = sizeof(WAVE_HEADER) + databytes - 8 ;

waveheader.wFormatTag      = PCM_WAVE_FORMAT ;

waveheader.nChannels       = channels ;

waveheader.nSamplesPerSec  = samplerate ;

waveheader.nAvgBytesPerSec = samplerate * (u_long) blockalign ;

waveheader.nBlockAlign     = blockalign ;

waveheader.wBitsPerSample  = sampbits ;

waveheader.nDataBytes      = databytes;

if(write (wavefile, &waveheader,sizeof(WAVE_HEADER)) !=sizeof(WAVE_HEADER)) {

err("%s",strerror(errno));/* wwg: report the error */

returnWW_BADWRITEHEADER ;

}

return0 ;

} ; /* WaveWriteHeader*/

intWaveReadHeader  (intwavefile,int* channels, u_long* samplerate,int* samplebits, u_long* samples, u_long* datastart,ErrFunc erf)

{   staticWAVEFORMAT  waveformat ;

staticcharbuffer [ BUFFERSIZE ] ;/* Function is not reentrant.*/

char*   ptr ;

u_long  databytes ;

v_erf = erf;                    /* wwg: Set error reporting function */

if(lseek (wavefile, 0L, SEEK_SET)) {

err("%s",strerror(errno));/* wwg: Report error */

returnWR_BADSEEK ;

}

read (wavefile, buffer, BUFFERSIZE) ;

if(findchunk (buffer,"RIFF", BUFFERSIZE) != buffer) {

err("Bad format: Cannot find RIFF file marker");/* wwg: Report error */

returnWR_BADRIFF ;

}

if(! findchunk (buffer,"WAVE", BUFFERSIZE)) {

err("Bad format: Cannot find WAVE file marker");/* wwg: report error */

returnWR_BADWAVE ;

}

ptr = findchunk (buffer, "fmt ", BUFFERSIZE) ;

if(! ptr) {

err("Bad format: Cannot find 'fmt' file marker");/* wwg: report error */

returnWR_BADFORMAT ;

}

ptr += 4 ;  /* Move past "fmt ".*/

memcpy (&waveformat, ptr, sizeof(WAVEFORMAT)) ;

if(waveformat.dwSize

err("Bad format: Bad fmt size");/* wwg: report error */

returnWR_BADFORMATSIZE ;

}

if(waveformat.wFormatTag != PCM_WAVE_FORMAT) {

err("Only supports PCM wave format");/* wwg: report error */

returnWR_NOTPCMFORMAT ;

}

ptr = findchunk (buffer, "data", BUFFERSIZE) ;

if(! ptr) {

err("Bad format: unable to find 'data' file marker");/* wwg: report error */

returnWR_NODATACHUNK ;

}

ptr += 4 ;  /* Move past "data".*/

memcpy (&databytes, ptr, sizeof(u_long)) ;

/* Everything is now cool, so fill in output data.*/

*channels   = waveformat.wChannels ;

*samplerate = waveformat.dwSamplesPerSec ;

*samplebits = waveformat.wBitsPerSample ;

*samples    = databytes / waveformat.wBlockAlign ;

*datastart  = ((u_long) (ptr + 4)) - ((u_long) (&(buffer[0]))) ;

if(waveformat.dwSamplesPerSec != waveformat.dwAvgBytesPerSec / waveformat.wBlockAlign) {

err("Bad file format");/* wwg: report error */

returnWR_BADFORMATDATA ;

}

if(waveformat.dwSamplesPerSec != waveformat.dwAvgBytesPerSec / waveformat.wChannels / ((waveformat.wBitsPerSample == 16) ? 2 : 1)) {

err("Bad file format");/* wwg: report error */

returnWR_BADFORMATDATA ;

}

return0 ;

} ; /* WaveReadHeader*/

/*===========================================================================================*/

#if 0

char*  WaveFileError (interrno)

{   switch(errno)

{   caseWW_BADOUTPUTFILE    :return"Bad output file.\n";

caseWW_BADWRITEHEADER   :return"Not able to write WAV header.\n";

caseWR_BADALLOC         :return"Not able to allocate memory.\n";

caseWR_BADSEEK          :return"fseek failed.\n";

caseWR_BADRIFF          :return"Not able to find 'RIFF' file marker.\n";

caseWR_BADWAVE          :return"Not able to find 'WAVE' file marker.\n";

caseWR_BADFORMAT        :return"Not able to find 'fmt ' file marker.\n";

caseWR_BADFORMATSIZE    :return"Format size incorrect.\n";

caseWR_NOTPCMFORMAT     :return"Not PCM format WAV file.\n";

caseWR_NODATACHUNK      :return"Not able to find 'data' file marker.\n";

caseWR_BADFORMATDATA    :return"Format data questionable.\n";

default:return"No error\n";

} ;

returnNULL ;

} ; /* WaveFileError*/

#endif

/*===========================================================================================*/

char* findchunk  (char* pstart,char* fourcc,size_tn)

{   char*pend ;

intk, test ;

pend = pstart + n ;

while(pstart

{   if(*pstart == *fourcc)/* found match for first char*/

{   test = TRUE ;

for(k = 1 ; fourcc [k] != 0 ; k++)

test = (test ? ( pstart [k] == fourcc [k] ) : FALSE) ;

if(test)

returnpstart ;

} ; /* if*/

pstart ++ ;

} ; /* while lpstart*/

returnNULL ;

} ; /* findchuck*/

/* $Source: /cvsroot/wavplay/code/wavfile.c,v $ */

具体的解码分析,俺就不分析了。不是很难的代码,至于其它部分的代码,就不贴出来了,可以自己去下载代码来分析,我下载的是1.5B版本,最新的是2.0版本。

基于linux的mplay的mp3程序,基于Linux下的开源wavplay播放器相关推荐

  1. linux开源视频播放器_什么定义了Linux的顶级开源音乐播放器?

    linux开源视频播放器 在我撰写此音乐专栏的两年左右的时间里,Linux发烧友的世界得到了发展. 出现了新的Linux发行版和开源音频播放器,旧的已经消失了,随着高质量的数字下载,新的和高质量的播放 ...

  2. linux开源视频播放器_8个适用于Linux的开源音乐播放器

    linux开源视频播放器 在本系列的第一部分中,我写了一个发烧友数字音乐播放器的关键要求,并分享了我用来评估开源音乐播放器的标准. 在第二部分中,我将使用这些条件来帮助您选择适合您需求的软件. 首先, ...

  3. linux 命令行 播放器,linux下的命令行播放器moc

    linux下的命令行播放器moc 安装:直接APT-GET sudo apt-get install moc 安装完成后在终端用命令mocp(注意不是命令moc啊)打开moc播放器. 他默认是没有配置 ...

  4. html mp3默认播放器,Win7系统下设置默认音乐播放器的两种方法

    可能很多新手用户不知道Win7系统下怎么设置默认音乐播放器?我们习惯将某一程序设置为默认打开方式,音乐播放器也可以这样子的.一些用户想把酷狗播放器.或者qq音乐设置为默认音乐播放器,只要打开音乐文件, ...

  5. linux 命令行视频播放器,linux下的命令行播放器moc

    linux下的命令行播放器moc 安裝:直接APT-GET sudo apt-get install moc 安裝完成后在終端用命令mocp(注意不是命令moc啊)打開moc播放器. 他默認是沒有配置 ...

  6. linux ubuntu10.10下最好的音乐播放器deadbeef

    linux ubuntu10.10下最好的音乐播放器deadbeef 十一 18 无冷 Linux , Ubuntu 1,162 viewsGo to comment 推荐一款播放器Deadbeef ...

  7. linux执行可执行命令程序ls,linux运行可执行程序命令

    linux 命令行如何运行程序 我用的是Ubuntu,安装了一个分子模拟软件,但是不知道如何运行程序,比cd到目录下,然后ls -l tleap,如果有x权限,直接./tleap,如果没有x,就先执行 ...

  8. linux 命令美丽,美丽的程序猿-Linux下那些查找文件的小技巧-find

    原标题:美丽的程序猿-Linux下那些查找文件的小技巧-find 一.按照文件名匹配查找 1. 查找当前目录下的文件tmp.sh find . –name tmp.sh 可以看出,使用.查找是查找当前 ...

  9. linux下的网络音乐播放器,Linux_Songbird离开后 Linux下可以替代它的10个音乐播放器推荐,正如我们早先提到的一样, Son - phpStudy...

    Songbird离开后 Linux下可以替代它的10个音乐播放器推荐 正如我们早先提到的一样, Songbird 已经离开了Linux羊群而开源的牧草地将变得更加翠绿.但是,Linux将用什么来取代这 ...

  10. 移动应用程序设计基础——安卓动画与视音频播放器的实现

    <移动应用程序设计基础>实验6 安卓动画与视音频播放器的实现 实验名称: 实验6 安卓动画与视音频播放器的实现 所使用的工具软件及环境: JDK1.8,Android Studio 一.实 ...

最新文章

  1. Sql Server函数全解(四)日期和时间函数
  2. python名称由来_Python的由来与使用介绍
  3. Unity中那些事半功倍的好插件
  4. 深度神经网络(DNN)的正则化
  5. CNN结构基元:纹理结构和纹理基元方程化GLOH、Gabor...(Code)
  6. js pug 代码_pug模版学习(一)
  7. python实验原理_Python实验报告八
  8. [Objective-C语言教程]动态绑定(32)
  9. Ajax补充之serialize
  10. 【恋上数据结构】冒泡排序、选择排序、堆排序
  11. SpringBoot 多语言切换
  12. ENVI学习总结(十)——遥感图像监督分类
  13. android 让程序在后台运行,android – 如何让我的应用程序在后台运行?
  14. hdu 6184 三元环数目
  15. vmware反复触发numlock问题
  16. CDN加速技术可以解决网络客户的哪些痛点问题?
  17. Python数据分析与可视化案例解析
  18. 如何用php 图片合成一张图片,PHP 文字生成图片并与两张图片合成一张图片
  19. CSS 实现音频loding动画
  20. CLRS 16.2贪心算法的原理

热门文章

  1. 英语单词常用前缀(21-40)
  2. 全球及中国仿制药产业未来发展走势及营销产量规模预测报告2021-2027年
  3. 手机蛙站长分享百度下拉技术原理
  4. 一周学习总结:vue学前准备知识
  5. 微信小程序Post方法提交数据
  6. HTML---网络编程基础知识(2)
  7. MySQL复制一张表数据到另一张新表
  8. 英语口语 每日一句 小红书TroyChina
  9. AcWing:176. 装满的油箱(bfs + dijiskla思想)
  10. 计算机出现假桌面怎么解决办法,win10专业版系统桌面经常假死解决办法