72 lines
2.0 KiB
C
72 lines
2.0 KiB
C
#include "sound/wav.h"
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
|
|
|
|
static void write_u16(FILE *f, uint16_t v) {
|
|
uint8_t b[2];
|
|
b[0] = (uint8_t)(v & 0xff);
|
|
b[1] = (uint8_t)((v >> 8) & 0xff);
|
|
fwrite(b, 1, 2, f);
|
|
}
|
|
|
|
static void write_u32(FILE *f, uint32_t v) {
|
|
uint8_t b[4];
|
|
b[0] = (uint8_t)(v & 0xff);
|
|
b[1] = (uint8_t)((v >> 8) & 0xff);
|
|
b[2] = (uint8_t)((v >> 16) & 0xff);
|
|
b[3] = (uint8_t)((v >> 24) & 0xff);
|
|
fwrite(b, 1, 4, f);
|
|
}
|
|
|
|
int wave_open(wav_t *wav, const char *filename, uint32_t sample_rate) {
|
|
|
|
wav->file = fopen(filename, "wb");
|
|
if (!wav->file)
|
|
return 0;
|
|
|
|
wav->sample_rate = sample_rate;
|
|
wav->samples_written = 0;
|
|
|
|
/* RIFF header */
|
|
fwrite((uint8_t[]){'R','I','F','F'}, 1, 4, wav->file);
|
|
write_u32(wav->file, 0); // Placeholder for file size
|
|
fwrite((uint8_t[]){'W','A','V','E'}, 1, 4, wav->file);
|
|
|
|
/* fmt chunk */
|
|
fwrite((uint8_t[]){'f','m','t',' '}, 1, 4, wav->file);
|
|
write_u32(wav->file, 16); // PCM chunk size
|
|
write_u16(wav->file, 1); // Audio format (1 = PCM)
|
|
write_u16(wav->file, 1); // Channels (1 = mono)
|
|
write_u32(wav->file, sample_rate); // Sample rate
|
|
write_u32(wav->file, sample_rate * 2); // Byte rate (sr * block_align)
|
|
write_u16(wav->file, 2); // Block align (mono 16-bit = 2)
|
|
write_u16(wav->file, 16); // Bits per sample
|
|
|
|
/* data chunk */
|
|
fwrite((uint8_t[]){'d','a','t','a'}, 1, 4, wav->file);
|
|
write_u32(wav->file, 0); // Placeholder for data size
|
|
|
|
return 1;
|
|
}
|
|
void wave_write_sample(wav_t *wav, int16_t sample) {
|
|
write_u16(wav->file, (uint16_t)sample);
|
|
wav->samples_written++;
|
|
}
|
|
|
|
void wave_close(wav_t *wav) {
|
|
|
|
uint32_t data_size = wav->samples_written * 2;
|
|
uint32_t file_size = 36 + data_size;
|
|
|
|
/* Patch RIFF size */
|
|
fseek(wav->file, 4, SEEK_SET);
|
|
write_u32(wav->file, file_size);
|
|
|
|
/* Patch data chunk size */
|
|
fseek(wav->file, 40, SEEK_SET);
|
|
write_u32(wav->file, data_size);
|
|
|
|
fclose(wav->file);
|
|
}
|