Search code examples
c++structfwritefreadfile-header

Write struct to file but wrong value when read back with C++


I write some code to read .wav file and do some algorithm then write to a new .wav file.I use a struct to stand for wav header,before writing the struct to the file,the values in it are all correct,but when I read back ,some values in it changged,I don't know why,here is my struct:

struct WavHeader{
    public:
            char RIFF[4]={'R','I','F','F'};
            int32_t size0;
            char  WAVE[4]={'W','A','V','E'};
            char FMT[4]={'f','m','t',' '};
            int32_t size1;
            int16_t fmttag;
            int16_t channel;
            int32_t samplespersec;
            int32_t bytepersec;
            int16_t blockalign;
            int32_t bitsEvrSample;
            char DATA[4]={'d','a','t','a'};
            int32_t size2;

            WavHeader(){
                    size0=0;
                    size1=0;
                    fmttag=0;
                    channel=1;
                    samplespersec=0;
                    bytepersec=0;
                    blockalign=0;
                    bitsEvrSample=0;
                    size2=0;
            }
};

here is my function to write to wav(pz ignore the WavData):

void MTools::write2Wav(const char* fname,WavData* data,WavHeader* wavhead){
    FILE* fid=fopen(fname,"ab+");
    fwrite(wavhead,1,sizeof(WavHeader),fid);
    fclose(fid);
}

The last is my function to read the wav header :

void MTools::loadWavFile(const char* fname,WavData* ret,WavHeader* head){
    FILE* fp=fopen(fname,"rb");
    size_t result;
    if(fp){
            char id[5];
        format_length,sample_rate,avg_bytes_sec,data_size,bits_per_sample;

            result=fread(id,sizeof(char),4,fp);
            id[4]='\0';

            if(!strcmp(id,"RIFF")){

                    result=fread(&(head->size0),sizeof(int16_t),2,fp);
                    result=fread(id,sizeof(char),4,fp);
                    id[4]='\0';

                    if(!strcmp(id,"WAVE")){
                            result=fread(id,sizeof(char),4,fp);

                            result=fread(&(head->size1),sizeof(int16_t),2,fp);


                            result=fread(&(head->fmttag),sizeof(int16_t),1,fp);

                            result=fread(&(head->channel),sizeof(int16_t),1,fp);

                            result=fread(&(head->samplespersec),sizeof(int16_t),2,fp);

                            result=fread(&(head->bytepersec),sizeof(int16_t),2,fp);

                            result=fread(&(head->blockalign),sizeof(int16_t),1,fp);

                            result=fread(&(head->bitsEvrSample),sizeof(int16_t),2,fp);
                            result=fread(id,sizeof(char),4,fp);

                            result=fread(&(head->size2),sizeof(int16_t),2,fp);


                            ret->size=head->size2/sizeof(int16_t);


                            ret->data=(int16_t*)malloc(head->size2);
                            result=fread(ret->data,sizeof(int16_t),ret->size,fp);
                     }      
                    else{
                            cout<<"Error: RIFF File but not a wave file\n";
                    }       
            }       
    else{   
            cout<<"ERROR: not a RIFF file\n";
    }       
    }
    fclose(fp);

}

before writing(with gdb): enter image description here

after writing and read back: enter image description here


Solution

  • You need to rewrite your write2wav as explicitly as your loadWavFile, because you never know how the data is packed (memory alignment issues) in the struct as you would expect (depends on compilers on compiler options).