**************************************** **************************************** **************************************** ***
Author: EasyWave time: 2013.02.05
Category: wavplay player Declaration for Linux applications: reprinted. Please keep the link
NOTE: If any error occurs, please correct it. These are my Learning Log articles ......
**************************************** **************************************** **************************************** ***
Because the customer needs to use wav files to test and play our platform, and the customer's applications are used on our platform, there will be some problems, so, I need to find an open source wav player on the network and finally find the wavplay player on the network. although it is a wav Player Based on the OSS architecture, it does not matter. You should first familiarize yourself with this open-source code. The latest version is 2.0. The source code is as follows:
Http://sourceforge.net/projects/wavplay? Source = dlp take a moment to transplant it to the ARM platform after the festival. This software is used for testing or porting to actual projects. For us, is a good reference source code. Do you mean no?
I. wav file format[Network referenced, modified]
As one of the acoustic file formats used in multimedia, the wave file is in the RIFF format as the standard. RIFF is short for Resource Interchange File Format. The first four bytes of each WAVE File are "RIFF", and the WAVE File is composed of several chunks. The location where the file appears includes riff wave Chunk, Format Chunk, Fact Chunk (optional), and Data Chunk. As shown in:
Three other chunks except Fact Chunk are required. Each Chunk has its own ID, which is located at the very beginning of the Chunk and serves as an identifier. Each Chunk contains 4 bytes. In addition, the Chunk Size follows the ID (the remaining number of other bytes after removing the number of bytes occupied by ID and Size), 4 bytes, and low bytes indicate the low value, high byte indicates a high value. The following describes the content of each Chunk.Note: All values indicate low bytes, and high bytes indicate high.
1): riff wave Chunk
Use '0000f' as the marker, followed by the size field. The size is the Size of the whole wav file minus the number of bytes occupied by ID and Size, that is, FileLen-8 = size. Then the Type field, which is 'wave ', indicates a wav file.
2): Format Chunk
Use 'fmt' as the flag. Generally, the Size is 16, and no additional information is added at the end. If the value is 18, two additional bytes are added at the end. The wav format made mainly by some software contains the additional information of the two bytes.
3): Fact Chunk
Fact Chunk is an optional field. Generally, when a wav file is converted from some software, it contains the Chunk.
4): Data Chunk
The Data Chunk is the place where the wav data is actually stored. 'data' is used as the Chunk identifier. Then the data size. Followed by wav data. Based on the number of channels in the Format Chunk and the number of sampled bits, the bit location of wav data can be divided into the following forms:
Ii. wav File Format Decoding
For specific code, you can carefully study the wavfile. c and wavfile. H files in the source code of wavplay. These two files mainly decode the wav file format. The specific code is as follows:
/* $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 $ */
I will not analyze the specific decoding analysis. The code is not very difficult. As for other parts of the code, it will not be posted. You can download the code for analysis. I downloaded version 1.5B, and the latest version is version 2.0.