0

I have to copy first 64 bytes from input file in.wav into output file out.wav. (I've downloaded a program which shows .wav file's header (chunks): first 44 bytes and first 20 bytes of data_subchunk)

My code fills out.wav file with some values, but (I'm convinced) it to be a garbage. (The values that program shows don't match.)

I have to copy a part of in.wav file into out.wav:

#include <stdio.h>
#include <stdlib.h>

typedef struct FMT
{
    char        Subchunk1ID[4];
    int         Subchunk1Size;
    short int   AudioFormat;
    short int   NumChannels;
    int         SampleRate;
    int         ByteRate;
    short int   BlockAlign;
    short int   BitsPerSample;

} fmt;

typedef struct DATA
{
    char        Subchunk2ID[4];
    int         Subchunk2Size;
    int         Data[441000]; // 10 secs of garbage. he-he)
} data;

struct HEADER
{
    char        ChunkId[4];
    int         ChunkSize;
    char        Format[4];
    fmt         S1;
    data        S2;
} header;


int main()
{
    FILE *input = fopen("in.wav", "r");
    FILE *output = fopen("out.wav", "w");

    if(input == NULL)
    {
        printf("Unable to open wave file\n");
        exit(EXIT_FAILURE);
    }

        fwrite(&input, sizeof(int), 16, output); // 16'ints' * 4 = 64 bytes

    fclose(input);
    fclose(output);

    return 0;
}

What is wrong?

Grzegorz Piwowarek
  • 13,172
  • 8
  • 62
  • 93
yulian
  • 1,601
  • 3
  • 21
  • 49
  • When copying binary data, preferably use `open`, `read`, and `write` instead of their `f-` equivalents! – bash.d May 06 '13 at 11:44
  • 1
    Why are you `fopen()`ing `in.waw` **twice?** –  May 06 '13 at 11:46
  • 1
    You have to _read_ your 64 bytes from input file first (into a memory buffer), and then write this buffer to the output file. In your code you just copy the content of output pointer, that has nothing to do with file content. – Archie May 06 '13 at 11:46
  • I'll delete one 'fopen' now.. – yulian May 06 '13 at 11:46
  • Or at least open the files in _binary_ mode. – Some programmer dude May 06 '13 at 11:46
  • You have a few potential bugs here ; first, your are `fopen`ing "in.wav" twice into `input`, which is bag. Next, you are not checking whether `output` contains something or not, which might be disastrous. `fwrite` might fail, too. – Fabien May 06 '13 at 11:49
  • `fwrite(&input, sizeof(int), 16, output);` doesn't look appropriate. – Rohan May 06 '13 at 11:50
  • 2
    Don't use open/read/write unless you have a reason to do so, since they are Linux (unix?) specific. fopen/fread/fwrite are C standard and available on all platforms. – Stefano Sanfilippo May 06 '13 at 11:54

3 Answers3

3

You are writing data to opened output file from input

fwrite(&input, sizeof(int), 16, output); 

I am not sure, if you can use FILE pointer this way. I would do that this way

unsigned char buf[64];
fread(&buf, sizeof(char), 64, input);
fwrite(&buf, sizeof(char), 64, output); 

Also open files in binary mode: fopen("in.wav", "rb") and fopen("out.wav", "wb")

rubenvb
  • 74,642
  • 33
  • 187
  • 332
Martin Perry
  • 9,232
  • 8
  • 46
  • 114
3

You can't use a FILE pointer as input to fwrite. You actually have to read the data first into a buffer, before you write that buffer.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
1

First, use binary mode for fopen ("wb" instead of "w"). Second, you are making an unsafe assumption, that is sizeof (int) == 4, which is not always true. Third, input is already a pointer, you don't need the & befor input on the fwrite line.

And, most importantly, you cannot use fwrite from one file handle to another. You need to copy to a char[] buffer before, like:

char buffer[40];
if (fread(buffer, sizeof (char), 40, input) != 40) {
    printf("Error!");
}
if (fwrite(buffer, sizeof (char), 40, output) != 40) {
    printf("Error!");
}
Stefano Sanfilippo
  • 32,265
  • 7
  • 79
  • 80