WAV audio files

Source: Internet
Author: User
Tags printf
WAV audio files

Chess Boy 1048272975

WAV is a file format for saving audio information that is widely used in Windows and its applications, and today the mainstream audio player supports the playback of WAV audio files. 1. WAV Audio Format

WAV is the standard Windows file format used for recording, the file extension ". wav", the format of the data itself is PCM or compression type, it is developed jointly by Microsoft and IBM for audio digital storage standards, using the riff file format structure.

The riff Full Name resource Interchange file format is a file structure that most multimedia files under Windows follow, in addition to the waveform format data (. wav) described herein, files in the riff format are also available in Audio Video interleaved format (. avi), bitmap format (. rdi), MIDI format ( . rmi), color palette format (. pal), multimedia movie (. rmn), animation cursor (. ani).

The basic unit of the riff structure is chunk, and each chunk must contain a 4-byte chunk ID, a 4-byte data size, and the corresponding chunk data. It is structured as follows:

struct Chunk {

unsigned int id; /* Block Flag */

Unsignedint size; /* Block Size */

unsigned chardata[size]; /* Block content */

}

The ID is comprised of 4 ASCII characters that identify the data contained in the block, such as "RIFF", "WAV", "Data", "FMT", and so on, and the size is the length of the data stored in the information field, not including the ID of the sized field, and Data[size] The data saved for that block. arranged in words.

WAV audio file as a RIFF structure, which consists of several chunk, according to the location in the file includes: RIFF chunk,fmt chunk,fact Chunk (optional), data chunk. All RIFF structure files will first contain the riff chunk and indicate the riff type, which is "WAVE". WAV files indicate the audio format information in the FMT chunk, such as the number of sample bits, sampling frequency, number of channels, encoding method, etc. For compressed WAV audio, such as ADPCM, A-law, U-law, and so on, there will also be a fact chunk to indicate the size of the extracted audio data, for PCM uncompressed WAV file, and there is no such chunk. The audio data is stored in chunk, and the WAV audio data is stored in different ways depending on the number of channels indicated in the FMT chunk and the number of sample bits.

A simple PCM format WAV structure is defined as follows:

#define PCM_WAVE_FORMAT 1

typedef struct RIFF_HEADER {

CHARRIFFID[4];

Uint32_triffsize;

CHARRIFFFORMAT[4];

} Riff_header;

typedef struct WAVE_FORMAT {

Uint16_tformattag; Format code for Sound

Uint16_tchannels; Sound Channel

Uint32_tsamplespersec; Sample Rate

Uint32_tavgbytespersec; Sample rate * Block Alignment units

Uint16_tblockalign; Block Alignment unit = number of bits required per sample * Sound Channel/8

Uint16_tbitspersample; The number of bits required per sample

} Wave_format;

typedef struct FMT_CHUNK {

CHARFMTID[4];

Uint32_tfmtsize;

Wave_formatwaveformat;

} Fmt_chunk;

typedef struct DATA_CHUNK {

CHARDATAID[4];

uint32_t datasize;

} Data_chunk;

typedef struct WAVE_HEADER {

Riff_headerriffheader;

Fmt_chunk Fmtchunk;

Data_chunk Datachunk;

} Wave_header;

Static Wave_header Waveheader = {

' R ', ' I ', ' f ', ' F ',

0,

' W ', ' A ', ' V ', ' E ',

' F ', ' m ', ' t ', ',

16,

pcm_wave_format,//PCM Encoding

1,//Mono

0,//Sample Rate Initialization 0

0,//byte stream initialization 0 per second

2,//2 bytes per sample

16,//sampling 16-bit

' d ', ' a ', ' t ', ' a ',

0

}; 2. WAV Audio playback

WAV audio playback involves audio driver, SD card read-write file implementation, you can refer to the previous chapters. The main process of playback implementation is as follows:

A. Use F_open () to open the WAV file in the SD card.

B. Use the Wave_readheader () function to parse the WAV header, get the number of sample bits, sample frequency, number of channels and other audio formats, only PCM 16-bit audio format is supported here.

int Wave_readheader (FIL *file,wave_format *waveformat)

{

uint32_t Byteread;

int databytes;

Char buffer[512];

Char *pbuffer;

if (F_lseek (File, 0)! = RES_OK) {

return-1;

}

if (F_read (File, buffer, sizeof (buffer), &byteread)! = RES_OK) {

Return-2;

}

if (! Wav_findchunk (buffer, "RIFF", sizeof (buffer))) {

return-3;

}

if (! Wav_findchunk (buffer, "WAVE", sizeof (buffer))) {

return-4;

}

pbuffer = wav_findchunk (buffer, "FMT", sizeof (buffer));

if (!pbuffer) {

return-5;

}

Pbuffer + = 8; Move Past "FMT", FMT size

memcpy (Waveformat, pbuffer,sizeof (Wave_format));

if (Waveformat->formattag!=pcm_wave_format) {

return-6;

}

pbuffer = wav_findchunk (buffer, "data", sizeof (buffer));

if (!pbuffer) {

return-7;

}

Pbuffer + = 4; Move Past "Data"

memcpy (&databytes, pbuffer,sizeof (uint32_t));

if (waveformat->bitspersample! = 16) {

return-8;

}

return databytes;

}

C. Initialize the I2S audio driver based on the parsed audio format.

PRINTF ("Playing%s\r\n", Wavfileslist[fileindex]);

PRINTF ("Mode:%s\r\n", waveformat.channels==1?) Mono ":" Stereo ");

PRINTF ("Samplerate:%dhz\r\n", waveformat.samplespersec);

PRINTF ("bitrate:%d bps\r\n", waveformat.avgbytespersec*8);

PRINTF ("Samples:%d\r\n", databytes/waveformat.blockalign);

I2s_setsamplerate (WAVEFORMAT.SAMPLESPERSEC);

I2s_txstart ();

D. The use of dual-cache (cache 0 and Cache 1) to achieve the continuous reading of SD card audio data, when any one cache empty, using F_read () from the SD card to read the audio data to the empty cache, if the cache is full, then wait for the audio frame data to play, and then the data in the cache to the audio output stream.

if (Playing && (! Bufferstate.buffer0full | | ! Bufferstate.buffer1full)) {

Res= F_read (&file, bufferstate.buffer[bufferstate.writeindex],sizeof (Bufferstate.buffer[0]), &ByteRead);

if (Res! = RES_OK) {

F_close (&file);

PRINTF ("ReadData error\r\n");

State= 0;

Break

}

if (Byteread < sizeof (bufferstate.buffer[0])) {

F_close (&file);//End of File

playing= 0; End Play

}

if (Bufferstate.writeindex) {

Bufferstate.buffer1full= 1;

bufferstate.writeindex= 0;

}else {

Bufferstate.buffer0full= 1;

bufferstate.writeindex= 1;

}

}

The audio data read by the SD card needs to be continuously loaded into the audio output cache for continuous audio playback. When the I2S audio output stream finishes a frame, it is possible to load one frame of audio data into the output frame from a double cache of ready data until the cache is loaded and the cache is empty, informing the SD card that it can read the data to this empty cache.

if (writeindex! = I2sstate.txreadindex) {

if (Bufferstate.readindex <buffer_num*2) {

if (! Bufferstate.buffer0full) {

Break

}

} else {

if (! Bufferstate.buffer1full) {

Break

}

}

pbuffer = (int16_t *) bufferstate.buffer+ Audio_frame_size*bufferstate.readindex;

if (waveformat.channels = = 1) {

for (i=0; i<audio_frame_size; i++) {

I2sstate.txbuffer[i2sstate.txwriteindex][i]= ((int16_t *) pbuffer) [i];

}

totalsize+= audio_frame_size * sizeof (int16_t);

bufferstate.readindex++;

} else {

for (i=0; i<audio_frame_size; i++) {

I2sstate.txbuffer[i2sstate.txwriteindex][i]= ((int32_t *) pbuffer) [i];

}

totalsize+= audio_frame_size * sizeof (int32_t);

bufferstate.readindex+= 2;

}

if (Bufferstate.readindex ==buffer_num*2) {

Bufferstate.buffer0full= 0;

} else if (Bufferstate.readindex ==buffer_num*4) {

Bufferstate.buffer1full= 0;

bufferstate.readindex= 0;

}

I2sstate.txwriteindex = Writeindex;

if (Writeindex >=audio_num_buffers-1) {

writeindex= 0;

} else {

writeindex++;

}

if (! Playing) {

if (totalsize >= databytes) {

I2s_txstop ();

PRINTF ("Play over\r\n");

state = 0;

}

}

}

3. WAV Audio recording

WAV audio recording involves the digital microphone driver, SD card read-write file implementation, you can refer to the previous chapters. The main process for recording is as follows:

A. Use F_open () to create a WAV audio file in the SD card.

B. Start writing data from the audio data location using F_lseek (). 16K sample rate, mono-initialized digital microphone.

if (F_lseek (&file,sizeof (wave_header)) = RES_OK) {

F_close (&file);

State= 0;

Break

}

PRINTF ("recordingsound.wav\r\n");

PRINTF ("mode:mono\r\n");

PRINTF ("samplerate:16000hz\r\n");

PRINTF ("bitrate:%d bps\r\n", 16000*2*8);

Dmic_start ();

C. Constantly save the frame data recorded in the microphone to the empty double cache, when a buffer fills up, set the corresponding cache channel, tell the SD card can write this cache channel data to empty.

if (dmicstate.event) {

pbuffer = (int16_t *) bufferstate.buffer+ Audio_frame_size*bufferstate.writeindex;

for (i=0; i<audio_frame_size; i++) {

((int16_t*) pbuffer) [i] = dmicstate.buffer[dmicstate.readindex][i];

}

bufferstate.writeindex++;

if (Bufferstate.writeindex ==buffer_num*2) {

Bufferstate.buffer0full= 1;

} else if (Bufferstate.writeindex = = buffer_num*4) {

Bufferstate.buffer1full= 1;

bufferstate.writeindex= 0;

}

if (Dmicstate.readindex >=audio_num_buffers-1) {

dmicstate.readindex=0;

}else {

dmicstate.readindex++;

}

Dmicstate.event= 0;

}

With a double cache, the recorded audio data is continuously written to the SD card, when a cache fills up in a double cache, the audio data is written to the SD card with F_write (), and the cache is emptied, informing the microphone that the recording frame data can be saved to this empty cache.

if ((Bufferstate.buffer0full | | Bufferstate.buffer1full)) {

Res= F_write (&file, bufferstate.buffer[bufferstate.readindex],sizeof (Bufferstate.buffer[0]), &ByteWrite);

if (Res! = RES_OK) {

Dmic_stop ();

F_close (&file);

PRINTF ("WriteData error\r\n");

State= 0;

Break

}

if (Bufferstate.readindex) {

Bufferstate.buffer1full= 0;

bufferstate.readindex= 0;

}else {

Bufferstate.buffer0full= 0;

bufferstate.readindex= 1;

}

Databytes + = sizeof (bufferstate.buffer[0]);

}

D. After the recording is finished (by pressing the key), the WAV file header is updated with Wave_writeheader () based on the actual recorded audio data size.

int Wave_writeheader (FIL *file, uint32_tsamplerate, uint32_t databytes)

{

uint32_t Bytewrite;

if (F_lseek (File, 0)! = RES_OK) {

return-1;

}

Waveheader.fmtchunk.waveformat.samplespersec= samplerate;

waveheader.fmtchunk.waveformat.avgbytespersec= samplerate * 2;

WaveHeader.DataChunk.DataSize =databytes;

WaveHeader.RiffHeader.RiffSize =databytes + sizeof (Waveheader)-8;

if (F_write (File, (uint8_t*) &waveheader, sizeof (Waveheader), &bytewrite)! = RES_OK) {

Return-2;

}

return 0;

} 4. Appendix

MDK project, including SD card file reading and writing code, I2S, digital microphone audio recording playback driver, WAV audio file playback, recording implementation.

Https://pan.baidu.com/s/1c6kxdk

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

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.