Skip to content

Instantly share code, notes, and snippets.

@opsJson
Last active March 19, 2022 02:52
Show Gist options
  • Save opsJson/3c7460c39fe52235aff4ea69433d615c to your computer and use it in GitHub Desktop.
Save opsJson/3c7460c39fe52235aff4ea69433d615c to your computer and use it in GitHub Desktop.
Easily read and write WAV sound files.
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
typedef struct riff {
unsigned char chunkID[4];
unsigned int chunkSize;
unsigned char format[4];
} Riff;
typedef struct fmt {
unsigned char chunkID[4];
unsigned int chunkSize;
unsigned short audioFormat;
unsigned short numChannels;
unsigned int sampleRate;
unsigned int byteRate;
unsigned short blockAlign;
unsigned short bitsPerSample;
} Fmt;
typedef struct data {
unsigned char chunkID[4];
unsigned int chunkSize;
void *sound;
} Data;
typedef struct wave {
Riff riff;
Fmt fmt;
Data data;
} Wave;
Wave *LoadWAV(const char *file) {
FILE *fp;
Wave *audio;
unsigned int size;
if ((fp = fopen(file, "rb")) == NULL) return NULL;
if ((audio = malloc(sizeof(Wave))) == NULL)
{
fclose(fp);
return NULL;
}
fread(audio->riff.chunkID, sizeof(audio->riff.chunkID), 1, fp);
fread(&audio->riff.chunkSize, sizeof(audio->riff.chunkSize), 1, fp);
fread(audio->riff.format, sizeof(audio->riff.format), 1, fp);
fread(audio->fmt.chunkID, sizeof(audio->fmt.chunkID), 1, fp);
fread(&audio->fmt.chunkSize, sizeof(audio->fmt.chunkSize), 1, fp);
fread(&audio->fmt.audioFormat, sizeof(audio->fmt.audioFormat), 1, fp);
fread(&audio->fmt.numChannels, sizeof(audio->fmt.numChannels), 1, fp);
fread(&audio->fmt.sampleRate, sizeof(audio->fmt.sampleRate), 1, fp);
fread(&audio->fmt.byteRate, sizeof(audio->fmt.byteRate), 1, fp);
fread(&audio->fmt.blockAlign, sizeof(audio->fmt.blockAlign), 1, fp);
fread(&audio->fmt.bitsPerSample, sizeof(audio->fmt.bitsPerSample), 1, fp);
fread(audio->data.chunkID, sizeof(audio->data.chunkID), 1, fp);
fread(&audio->data.chunkSize, sizeof(audio->data.chunkSize), 1, fp);
size = audio->data.chunkSize;
audio->data.sound = malloc(size);
fread(audio->data.sound, size, 1, fp);
fclose(fp);
return audio;
}
void FreeWAV(Wave *audio) {
free(audio->data.sound);
free(audio);
}
bool WriteWAV(const char *file, Wave audio) {
FILE *fp;
if ((fp = fopen(file, "wb")) == NULL) return false;
fwrite(audio.riff.chunkID, sizeof(audio.riff.chunkID), 1, fp);
fwrite(&audio.riff.chunkSize, sizeof(audio.riff.chunkSize), 1, fp);
fwrite(audio.riff.format, sizeof(audio.riff.format), 1, fp);
fwrite(audio.fmt.chunkID, sizeof(audio.fmt.chunkID), 1, fp);
fwrite(&audio.fmt.chunkSize, sizeof(audio.fmt.chunkSize), 1, fp);
fwrite(&audio.fmt.audioFormat, sizeof(audio.fmt.audioFormat), 1, fp);
fwrite(&audio.fmt.numChannels, sizeof(audio.fmt.numChannels), 1, fp);
fwrite(&audio.fmt.sampleRate, sizeof(audio.fmt.sampleRate), 1, fp);
fwrite(&audio.fmt.byteRate, sizeof(audio.fmt.byteRate), 1, fp);
fwrite(&audio.fmt.blockAlign, sizeof(audio.fmt.blockAlign), 1, fp);
fwrite(&audio.fmt.bitsPerSample, sizeof(audio.fmt.bitsPerSample), 1, fp);
fwrite(audio.data.chunkID, sizeof(audio.data.chunkID), 1, fp);
fwrite(&audio.data.chunkSize, sizeof(audio.data.chunkSize), 1, fp);
fwrite(audio.data.sound, audio.data.chunkSize, 1, fp);
fclose(fp);
return true;
}
/*///////////////////////////////////
Testing:
///////////////////////////////////*/
int main(void) {
Wave *audio = LoadWAV("audio.wav");
if (audio == NULL) return 1;
printf("%s\n", (audio->fmt.numChannels == 1) ? "Mono" : "Stereo");
printf("audio size: %i bits\n", audio->riff.chunkSize);
printf("sample rate: %i\n", audio->fmt.sampleRate);
if (WriteWAV("audio_copy.wav", *audio))
{
printf("done!\n");
}
FreeWAV(audio);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment