How do I read binary data, convert it to an int, then convert it back in C++?

758 views Asked by At

I'm trying to open a wav file, read it, convert the buffer to an integer array, then convert it back and write it.

int main(){

    ifstream file ("C:\\Documents\\ParadigmE3-shortened.wav",std::ios_base::out | std::ios_base::binary);

    char * header = new char[50000044];
    file.read(header, 50000044);

    cout << header[0] << endl;

    unsigned int * header_int = new unsigned int[50000044];

    for(unsigned int i = 0; i < sizeof(header); i++){
        header_int[i] = header[i];
    }



    char * writefile = new char[50000044];

    for(unsigned int i = 0; i < sizeof(header); i++){
        itoa(header_int[i], &writefile[i], 10);
    }


    cout << writefile[0] << endl;
    ofstream newfile ("C:\\Documents\\ParadigmE3-modified.wav", std::ios_base::out | std::ios_base::binary);



    newfile.write(writefile, 50000044);

}

Currently, this prints:

R
8

Indicating that it changed the data in the process of converting it. How would I get this to work properly?


After some suggestions, and learning I can perform calculations on char variables, I reformulated the code, and now it is:

int main(){

    // Create file variable with file
    ifstream file ("C:\\Documents\\ParadigmE3-shortened.wav",std::ios_base::out | std::ios_base::binary);

    // Read the first 15040512 bytes to char array pointer, called header
    char * header = new char[15040512];
    file.read(header, 15040512);

    // Copy contents of header to writefile, after the 44'th byte, multiply the value by 2
    char * writefile = new char[15040512];
    for(int i = 0; i < sizeof(header); i++){
        if(i<44) writefile[i] = header[i];
        if(i>=44) writefile[i] = 2 * header[i];
    }

    // Copy the contents of writefile, but at the 44th byte, divide it by 2, returning it to its original value
    for(int i = 0; i < sizeof(header); i++){
        if(i<44) writefile[i] = writefile[i];
        if(i>=44) writefile[i] = .5 * writefile[i];
    }

    // Create file to write to
    ofstream newfile ("C:\\Documents\\ParadigmE3-modified.wav", std::ios_base::out | std::ios_base::binary);

    // Write writefile to file
    newfile.write(writefile, 15040512);

}

However, upon playing (in Windows Media Player), it does not play, so it is clearly not the original file, as I was going for.

1

There are 1 answers

7
JVE999 On

I figured it out. A couple things I learned were that you can perform calculations on 8-bit char variables (with a max value of 255 unsigned), so I didn't need to change it to an int array, however, I did because it gave me more headroom to work with (without worrying about clipping the values at 255).

I have included the entire program (with the header include list), as I also think this is a common question, and this by far is the simplest way I've seen to do it (the other ways I couldn't figure out -- they were much more complicated than this to do the same thing).

It reads the wav file, then it performs an operation on the data portion (beginning at the 45'th byte), then it does the reverse, and writes the file, which is a copy of the original.

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <fstream>
#include <string>
#include <bitset>
#include <string.h>

using namespace std;

int main(){


    ifstream file ("C:\\Documents\\ParadigmE3-shortened.wav",std::ios_base::out | std::ios_base::binary);

    char * header = new char[15040512];
    file.read(header, 15040512);


    int * writefile = new int[15040512];
    for(int i = 0; i < 15040512; i++){
        if(i<44) writefile[i] = header[i];
        if(i>=44) writefile[i] = 2 * header[i];
    }

    for(int i = 0; i < 15040512; i++){
        if(i<44) header[i] = writefile[i];
        if(i>=44) header[i] = .5 * writefile[i];
    }

    ofstream newfile ("C:\\Documents\\ParadigmE3-modified.wav", std::ios_base::out | std::ios_base::binary);


    newfile.write(header, 15040512);

}