I'm following a course about programming and went smooth so far. Now I'm stuck into this exercise which asks us to reverse a WAV file in C.
I have two questions about it:
It seems to work and correctly reverse few seconds audios but on longer ones it doesn't anymore. Why?
I previously added a get_data_size function to know a value to use later in the program, but after discovering the fseek() function it wasn't needed anymore. So I wanted to delete it, but if I do I get the "segmentation fault" error, while if I keep it it just runs ok. Why?
EDIT: Ok, now MAGICALLY, I tried to delete the get_data size function again and compiled it... and it doesn't go to segfault anymore. without changing anything. It still doesn't reverse the longer files though.
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include "wav.h"
int check_format(WAVHEADER header);
int get_block_size(WAVHEADER header);
long get_data_size(FILE *input, int size);
int main(int argc, char *argv[])
{
// Ensure proper usage
if (argc != 3)
{
printf("insert input and output names");
return 2;
}
// Open input file for reading
char *infile = argv[1];
char *outfile = argv[2];
FILE *input = fopen(infile, "r");
if (input == NULL)
{
printf("could not open the file\n");
return 1;
}
// Read header into an array
WAVHEADER inwav;
fread(&inwav, sizeof(WAVHEADER), 1, input);
// Use check_format to ensure WAV format
if (check_format(inwav) != 0)
{
fclose(input);
printf("not a valid format");
return 3;
}
// Open output file for writing
FILE *output = fopen(outfile, "w");
if (output == NULL)
{
printf("could not open the file\n");
return 1;
}
// Write header to file
fwrite(&inwav, sizeof(WAVHEADER), 1, output);
// Use get_block_size to calculate size of block
int n = get_block_size(inwav);
//not needed anymore
long s = get_data_size(input, n);
//Sets it to the end of the file
fseek(input, n, SEEK_END);
// Write audio to file from the last block to the first
while (ftell(input) != sizeof(WAVHEADER))
{
WORD temp;
fread(&temp, n, 1, input);
fwrite(&temp, n , 1, output);
fseek(input, -2 * n, SEEK_CUR);
}
fclose(input);
fclose(output);
return 0;
}
int check_format(WAVHEADER header)
{
// Checks for the WAVE spelt in the header
if (header.format[0] != 'W' && header.format[1] != 'A' && header.format[2] != 'V' && header.format[3] != 'E')
{
return 1;
}
return 0;
}
int get_block_size(WAVHEADER header)
{
//Double checks the channels are either 1 or 2 and calculates the BYTES per audio block
if (header.numChannels == 1 || header.numChannels ==2)
{
int size = (header.bitsPerSample / 8) * header.numChannels;
return size;
}
else
{
printf("not supported\n");
return 0;
}
return 0;
}
//not needed anymore
long get_data_size(FILE *input, int size)
{
long data = 0;
int temp;
while (!feof(input))
{
fread (&temp, 1, 1, input);
data++;
}
return data;
}
```
#include <stdint.h>
typedef uint8_t BYTE;
typedef uint16_t WORD;
typedef uint32_t DWORD;
typedef struct
{
BYTE chunkID[4];
DWORD chunkSize;
BYTE format[4];
BYTE subchunk1ID[4];
DWORD subchunk1Size;
WORD audioFormat;
WORD numChannels;
DWORD sampleRate;
DWORD byteRate;
WORD blockAlign;
WORD bitsPerSample;
BYTE subchunk2ID[4];
DWORD subchunk2Size;
} __attribute__((__packed__))
WAVHEADER;