基於Linux下的開源wavplay播放器

來源:互聯網
上載者:User

***************************************************************************************************************************
作者:EasyWave                                                                                 時間:2013.02.05

類別:Linux 應用之wavplay播放器                                                      聲明:轉載,請保留連結

注意:如有錯誤,歡迎指正。這些是我學習的日誌文章......

***************************************************************************************************************************

       因為客戶需要用到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 */static const char rcsid[] = "$Id: wavfile.c,v 1.3 2009/11/30 15:02:31 ve3wwg Exp $";#include  <stdio.h>#include<errno.h>#include<sys/types.h>#include<unistd.h>#include  <string.h>#include "wavplay.h"#defineBUFFERSIZE   1024#definePCM_WAVE_FORMAT   1#defineTRUE1#defineFALSE0typedef  struct{u_long     dwSize ;u_short    wFormatTag ;u_short    wChannels ;u_long     dwSamplesPerSec ;u_long     dwAvgBytesPerSec ;u_short    wBlockAlign ;u_short    wBitsPerSample ;} WAVEFORMAT ;typedef  struct{char    RiffID [4] ;u_long    RiffSize ;char    WaveID [4] ;char    FmtID  [4] ;u_long    FmtSize ;u_short   wFormatTag ;u_short   nChannels ;u_longnSamplesPerSec ;u_longnAvgBytesPerSec ;u_shortnBlockAlign ;u_shortwBitsPerSample ;charDataID [4] ;u_longnDataBytes ;} WAVE_HEADER ;/*=================================================================================================*/char*  findchunk (char* s1, char* s2, size_t n) ;/*=================================================================================================*/static  WAVE_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*/static ErrFunc v_erf;/* wwg: Error reporting function *//* * Error reporting function for this source module: */static voiderr(const char *format,...) {va_list ap;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);}int  WaveWriteHeader (int wavefile, int channels, u_long samplerate, int sampbits, u_long samples, ErrFunc erf){ u_longdatabytes ;u_shortblockalign ;v_erf = erf;/* wwg: Set error reporting function */if ( wavefile < 0 ) {err("Invalid file descriptor");return WW_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 */return  WW_BADWRITEHEADER ;}  return 0 ;} ; /* WaveWriteHeader*/int  WaveReadHeader  (int wavefile, int* channels, u_long* samplerate, int* samplebits, u_long* samples, u_long* datastart,ErrFunc erf){static  WAVEFORMAT  waveformat ;staticchar   buffer [ 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 */return  WR_BADSEEK ;}read (wavefile, buffer, BUFFERSIZE) ;if (findchunk (buffer, "RIFF", BUFFERSIZE) != buffer) {err("Bad format: Cannot find RIFF file marker");/* wwg: Report error */return  WR_BADRIFF ;}if (! findchunk (buffer, "WAVE", BUFFERSIZE)) {err("Bad format: Cannot find WAVE file marker");/* wwg: report error */return  WR_BADWAVE ;}ptr = findchunk (buffer, "fmt ", BUFFERSIZE) ;if (! ptr) {err("Bad format: Cannot find 'fmt' file marker");/* wwg: report error */return  WR_BADFORMAT ;}ptr += 4 ;/* Move past "fmt ".*/memcpy (&waveformat, ptr, sizeof (WAVEFORMAT)) ;if (waveformat.dwSize < (sizeof (WAVEFORMAT) - sizeof (u_long))) {err("Bad format: Bad fmt size");/* wwg: report error */return  WR_BADFORMATSIZE ;}if (waveformat.wFormatTag != PCM_WAVE_FORMAT) {err("Only supports PCM wave format");/* wwg: report error */return  WR_NOTPCMFORMAT ;}ptr = findchunk (buffer, "data", BUFFERSIZE) ;if (! ptr) {err("Bad format: unable to find 'data' file marker");/* wwg: report error */return  WR_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 */return  WR_BADFORMATDATA ;}if (waveformat.dwSamplesPerSec != waveformat.dwAvgBytesPerSec / waveformat.wChannels / ((waveformat.wBitsPerSample == 16) ? 2 : 1)) {err("Bad file format");/* wwg: report error */return  WR_BADFORMATDATA ;}  return  0 ;} ; /* WaveReadHeader*//*===========================================================================================*/#if 0char*  WaveFileError (int  errno){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_t n){char*pend ;intk, test ;pend = pstart + n ;while (pstart < pend){ 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)return  pstart ;} ; /* if*/pstart ++ ;} ; /* while lpstart*/return  NULL ;} ; /* findchuck*//* $Source: /cvsroot/wavplay/code/wavfile.c,v $ */


具體的解碼分析,俺就不分析了。不是很難的代碼,至於其它部分的代碼,就不貼出來了,可以自己去下載代碼來分析,我下載的是1.5B版本,最新的是2.0版本。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.