On wav file format and wav reading and writing (c code)

A rehash topic.

Basically, the standard 44-byte header can be compared with this table

The difference between the two record sizes is 36 2084 = 2048 +36

But there are also less headers with more than 44 bytes, such as this one:

This article makes it very clear

https://sites.google.com/site/musicgapi/technical-documents/wav-file-format

There are other chunkIDs

The extra ones are not 44 of their own heads, but these IDs are the ghosts. We are engaged in signal processing and don't care much about other additional information, so we can just skip over these data

They all follow the 4-byte chunkID, 4-byte Chunk DATAsize, we fread read here, just go directly

    if(!((header->data_tag[0]=='d')
        &&(header->data_tag[1]=='a')
        &&(header->data_tag[2]=='t')
        &&(header->data_tag[3]=='a')))
    {
        printf("Chunck ID: %s detected\n",header->data_tag);

        printf("Non-Data Chunk detected\n");
        fseek(fp,-4,SEEK_CUR);

        do{             fread(&ChunkLen,1,4,fp);//read the length             fseek(fp,ChunkLen,SEEK_CUR);//skip directly

            fread(&c1,1,1,fp);
            fread(&c2,1,1,fp);
            fread(&c3,1,1,fp);
            fread(&c4,1,1,fp);

            printf("Chunck ID: %c%c%c%c detected\n",c1,c2,c3,c4);
            
        }
        while(!((c1=='d')&&(c2=='a')&&(c3=='t')&&(c4=='a')));        

        header->data_tag[0] = 'd';
        header->data_tag[1] = 'a';
        header->data_tag[2] = 't';
        header->data_tag[3] = 'a';

        fread(&header->data_length,sizeof(header->data_length),1,fp);
    }

Corresponding to Matlab, there is a wavread2 dedicated to this

https://www.mathworks.com/matlabcentral/mlc-downloads/downloads/submissions/46271/versions/1/previews/wavread2.m/index.html

Process the above files

Additional information is recorded in info

//wave 写
typedef struct WaveHeader
{
    char  riff_id[4];                       //"RIFF"
    int   riff_datasize;                   // RIFF chunk data size,exclude riff_id[4] and riff_datasize,total - 8

    char  riff_type[4];                     // "WAVE"

    char  fmt_id[4];                        // "fmt "
    int   fmt_datasize;                     // fmt chunk data size,16 for pcm
    short fmt_compression_code;             // 1 for PCM
    short fmt_channels;                     // 1(mono) or 2(stereo)
    int   fmt_sample_rate;                  // samples per second
    int   fmt_avg_bytes_per_sec;            // sample_rate * channels * bit_per_sample / 8
    short fmt_block_align;                  // number bytes per sample, bit_per_sample * channels / 8
    short fmt_bit_per_sample;               // bits of each sample(8,16,32).

    char  data_id[4];                       // "data"
    int   data_datasize;                    // data chunk size,pcm_size - 44
}WaveHeader_t;

//Quickly write wav files, mono 16khz


char header[]= {82,73,70,70, //"RIFF"
                0x37,0x00,0x00,0x00,//FileSize-8
                87,65,86,69,//"WAVE"
                102,109,116,32,/ /"fmt "
                16,0,0,0,//Data segment 16bit
                1,0,//PCM format
                1,0,//Mono
                0x80,0x3e,0x00,0x00,//Sampling rate 16kHz
                0x00,0x7d ,0x00,0x00,//audio code rate=sampling rate*channel number*bit number/8                    
                2,0,//sampling takes 2 bytes at a time
                16,0,//16bit data for each channel
                100,97,116,97 ,//"data"
                0x01,0x00,0x00,0x00//data length 6s
               };
             

FILE *fp1,*fp2; // File pointers
int i;

printf("Exp. 1.2 --- file IO\n");

fp1 = fopen("1.wav", "rb"); // Open input file
fp2 = fopen("2.wav","wb");

if (fp1 == NULL) // Check if the input file exists
{
printf("Failed to open input file \n");
exit(0);
}

fseek(fp1, 44, 0);

fwrite(header,sizeof(header),1,fp2);


i=0;

while (fread(ch, sizeof(Uint8), SIZE, fp1) == SIZE) // Read in SIZE of input data bytes
{
fread(ch, sizeof(Uint8), SIZE, fp1);
fwrite(ch, sizeof(Uint8), SIZE, fp2); // Write SIZE of data bytes to output file
i += SIZE;
printf("%ld bytes processed\n", i); // Show the number of data is processed
}


waveHeader[40] = (Uint8)(i&0xff); // Update the size parameter into WAV header
waveHeader[41] = (Uint8)(i>>8)&0xff;
waveHeader[42] = (Uint8)(i>>16)&0xff;
waveHeader[43] = (Uint8)(i>>24)&0xff;

i = i +36;
waveHeader[4] = (Uint8)(i&0xff);
waveHeader[5] = (Uint8)(i>>8)&0xff;
waveHeader[6] = (Uint8)(i>>16)&0xff;
waveHeader[7] = (Uint8)(i>>24)&0xff;

rewind(fp2); // Adjust output file point to beginning
fwrite(waveHeader, sizeof(Uint8), 44, fp2); // Write 44 bytes of WAV header to output file

fclose(fp1); // Close input file
fclose(fp2); // Close output file

printf("\nExp --- completed\n");

//--------------------------- simplified writing

    char header[] = { 82,73,70,70, //"RIFF"
                0x37,0x00,0x00,0x00,//FileSize-8
                87,65,86,69,//"WAVE"
                102,109,116,32,/ /"fmt "
                16,0,0,0,//Data segment 16bit
                1,0,//PCM format
                1,0,//Mono
                0x80,0x3e,0x00,0x00,//Sampling rate 16kHz
                0x00,0x7d ,0x00,0x00,//audio code rate=sampling rate*channel number*bit number/8                    
                2,0,//sampling takes 2 bytes at a time
                16,0,//16bit data for each channel
                100,97,116,97 ,//"data"
                0x01,0x00,0x00,0x00//data length 6s
    };

//Open

    FILE* fp = fopen(wavfile,"wb");
    if (!fp) return;

//write head

fwrite(header, sizeof(header), 1, fp);

//Write data, len is the length (number of bytes)

fwrite(data,sizeof(data),1,fp);........

//Rewrite the number of data length bytes,

    int len = size;
    fseek(fp, 40, SEEK_SET);
    fwrite(&len, sizeof(int), 1, fp); 
    len = size + 36;
    fseek(fp, 4, SEEK_SET);
    fwrite(&len,sizeof(int),1,fp);

// close the file

fclose(fp);

/---------------------------------------------------------------------------/

Simple code to read wav files, especially for wavs that are not standard 44-byte headers

    if( filename == NULL) return false;
    
    FILE* fp_wave = fopen(filename,"rb");
    if(fp_wave == NULL) return false;
    
    fseek(fp_wave,22L,0);//Move to the number of channels
    short temp1;
    fread(&temp1,1,sizeof(short),fp_wave);
    if(!(temp1 == REC_CHANNEL_NUM)) return false;
    
    fseek(fp_wave,24L,0);//Move to the sampling rate position
    long temp2;
    fread (&temp2,1,sizeof(long),fp_wave);
    if(temp2 != SAMPLE_RATE) return false;

    rewind(fp_wave);

    //The head of the dedicated wave is not the standard 44 bytes
    while(!feof(fp_wave))//seek to the real data behind the data
    {         short temp;         fread(&temp,1,sizeof(short),fp_wave) ;         if(temp==24932)//'d''a' of 'data'         {             fread(&temp,1,sizeof(short),fp_wave);//read 't''a'             fread(&temp ,1,sizeof(short),fp_wave);//Read the following data-len as well             fread(&temp,1,sizeof(short),fp_wave);             break;         }     }     //It can actually use the following directly sentence instead, of course it must be a standard header     //fseek(fp_wave,44L,0);//standard 44-byte header     short TmpXChframe[FIFO_LEN*REC_CHANNEL_NUM];     int n_frame =0;












    

    while(!feof(fp_wave))//read in real pcm data
    {         //read in FIFO_LEN data each time, 1 frame of chanN channel data         //read data of specified length         fread(TmpXChframe,REC_CHANNEL_NUM * FIFO_LEN, sizeof(short), fp_wave);


        //deal with

        n_frame++;

   }

fclose(fp_wav);

Guess you like

Origin blog.csdn.net/book_bbyuan/article/details/110188074