text/plain
•
2.34 KB
•
75 lines
#include "../audio_metadata.h"
#include "helper.h"
#include <stdio.h>
#include <string.h>
bool parse_wav(const char *path, audio_metadata_t *meta) {
FILE *f = fopen(path, "rb");
if (!f) return false;
// Read RIFF header (12 bytes)
uint8_t header[12];
if (fread(header, 1, 12, f) != 12) {
fclose(f);
return false;
}
// Verify "RIFF" and "WAVE"
if (memcmp(header, "RIFF", 4) != 0 || memcmp(header + 8, "WAVE", 4) != 0) {
fclose(f);
return false;
}
uint32_t byte_rate = 0;
uint32_t data_size = 0;
bool got_fmt = false;
bool got_data = false;
// Parse sub-chunks
while (!got_fmt || !got_data) {
uint8_t chunk_header[8];
if (fread(chunk_header, 1, 8, f) != 8) break;
char chunk_id[5] = {chunk_header[0], chunk_header[1], chunk_header[2], chunk_header[3], 0};
uint32_t chunk_size = (uint32_t)chunk_header[4] |
((uint32_t)chunk_header[5] << 8) |
((uint32_t)chunk_header[6] << 16) |
((uint32_t)chunk_header[7] << 24);
if (strcmp(chunk_id, "fmt ") == 0) {
if (chunk_size < 16) break;
uint8_t fmt[16];
if (fread(fmt, 1, 16, f) != 16) break;
meta->channels = (uint8_t)(fmt[2] | (fmt[3] << 8));
meta->sample_rate = (uint32_t)fmt[4] | ((uint32_t)fmt[5] << 8) |
((uint32_t)fmt[6] << 16) | ((uint32_t)fmt[7] << 24);
byte_rate = (uint32_t)fmt[8] | ((uint32_t)fmt[9] << 8) |
((uint32_t)fmt[10] << 16) | ((uint32_t)fmt[11] << 24);
// Skip remaining fmt data
if (chunk_size > 16) {
fseek(f, chunk_size - 16, SEEK_CUR);
}
got_fmt = true;
} else if (strcmp(chunk_id, "data") == 0) {
data_size = chunk_size;
got_data = true;
// Don't need to read data, just skip
fseek(f, chunk_size, SEEK_CUR);
} else {
// Skip unknown chunk
fseek(f, chunk_size, SEEK_CUR);
}
}
fclose(f);
if (!got_fmt || !got_data || byte_rate == 0) return false;
meta->bitrate = byte_rate * 8;
meta->duration_ms = (uint32_t)((uint64_t)data_size * 1000 / byte_rate);
meta->valid = true;
return true;
}