#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
typedef struct
{
uint32_t id;
uint32_t size;
} Chunk;
typedef struct
{
Chunk super;
uint32_t type;
} RIFF;
typedef struct
{
uint16_t compressionCode;
uint16_t numChannels;
uint32_t sampleRate;
uint32_t avgBytesPerSecond;
uint16_t blockAlign;
uint16_t bitsPerSample;
uint16_t extraFormatBytes;
} FMT;
void displaySample(int16_t sample, int columns)
{
int32_t value = (columns * (sample - INT16_MIN)) / (INT16_MAX - INT16_MIN);
char buffer[columns + 1];
memset(buffer, ' ', columns);
buffer[columns] = '\0';
buffer[value] = '@';
printf("%s\n", buffer);
}
int main(int argc, char* argv[])
{
FILE* f = fopen(argv[1], "rb");
FILE* o = fopen(argv[2], "wb");
RIFF riff;
fread(&riff, 1, sizeof(riff), f);
if(riff.super.id != 0x46464952 || riff.type != 0x45564157)
{
printf("Bad WAV magic! %x %x\n", riff.super.id, riff.type);
fclose(f);
return 1;
}
off_t cur = 4;
int columns;
if(argc > 3)
columns = atoi(argv[3]);
Chunk chunk;
FMT fmt;
while(cur < riff.super.size)
{
fread(&chunk, 1, sizeof(chunk), f);
cur += sizeof(chunk);
printf("Chunk: %x\n", chunk.id);
uint8_t* data = (uint8_t*) malloc(chunk.size);
fread(data, 1, chunk.size, f);
cur += chunk.size;
if(chunk.id == 0x20746D66)
{
memcpy(&fmt, data, sizeof(fmt));
printf("Compression code: %d\n", fmt.compressionCode);
printf("Channels: %d\n", fmt.numChannels);
printf("Sample rate: %d\n", fmt.sampleRate);
printf("Average bytes per second: %d\n", fmt.avgBytesPerSecond);
printf("Block align: %d\n", fmt.blockAlign);
printf("Bits per sample: %d\n", fmt.bitsPerSample);
printf("Extra format bytes: %d\n", fmt.extraFormatBytes);
} else if(chunk.id == 0x61746164)
{
if(fmt.bitsPerSample == 16 && fmt.numChannels == 2)
{
if(argc > 3)
{
int i;
for(i = 0; i < (chunk.size / fmt.blockAlign); ++i)
{
int16_t sample = *((int16_t*)(data + (i * 4)));
displaySample(sample, columns);
}
}
}
fwrite(data, 1, chunk.size, o);
}
free(data);
}
fclose(o);
fclose(f);
}