Replaced my simple wave loader with rxi's

This commit is contained in:
rnlf
2017-01-23 22:43:23 +01:00
parent ccc5a29ef8
commit 28f78fb9c1
5 changed files with 124 additions and 120 deletions

View File

@@ -9,16 +9,52 @@
#include <string.h>
#include <stdint.h>
#include "source.h"
#include "filesystem.h"
#include "lib/dmt/dmt.h"
#include "wavefile.h"
#include "wav.h"
char const* source_init(source_t *self, char const* filename) {
return wavefile_load(self, filename);
int fileSize;
void *waveData = filesystem_read(filename, &fileSize);
char const *err = NULL;
wav_t wav;
int res = wav_read(&wav, waveData, fileSize);
if(res != WAV_ESUCCESS) {
err = wav_strerror(res);
goto fail;
}
if(wav.bitdepth != 16) {
err = "Invalid Audio Format (only 16 Bit supported)";
goto fail;
}
if(wav.samplerate != 22050) {
err = "Invalid Audio Format (only 22050Hz supported)";
goto fail;
}
if(wav.channels != 1) {
err = "Invalid Audio Format (only mono supported)";
goto fail;
}
self->sampleCount = wav.length;
self->data = waveData;
self->samples = (int16_t*)wav.data;
return NULL;
fail:
filesystem_free(waveData);
return err;
}
void source_deinit(source_t *self) {
dmt_free(self->samples);
filesystem_free(self->data);
}

View File

@@ -13,6 +13,7 @@
typedef struct {
int sampleCount;
int16_t *samples;
void *data;
} source_t;
char const* source_init(source_t *self, char const* filename);

84
src/wav.c Normal file
View File

@@ -0,0 +1,84 @@
/**
* Copyright (c) 2015 rxi
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the MIT license. See LICENSE for details.
*/
#include <stdio.h>
#include <stddef.h>
#include <string.h>
#include "wav.h"
typedef unsigned short Uint16;
typedef unsigned int Uint32;
static const char *findSubChunk(
const char *data, size_t len, const char *id, size_t *size
) {
/* TODO : Error handling on malformed wav file */
size_t idLen = strlen(id);
const char *p = data + 12;
next:
*size = *((Uint32*) (p + 4));
if (memcmp(p, id, idLen)) {
p += 8 + *size;
if (p > data + len) return NULL;
goto next;
}
return p + 8;
}
int wav_read(wav_t *w, const void *data, size_t len) {
int bitdepth, channels, samplerate, format;
size_t sz;
const char *p = data;
memset(w, 0, sizeof(*w));
/* Check header */
if (memcmp(p, "RIFF", 4) || memcmp(p + 8, "WAVE", 4)) {
return WAV_EBADHEADER;
}
/* Find fmt subchunk */
p = findSubChunk(data, len, "fmt", &sz);
if (!p) return WAV_ENOFMT;
/* Load fmt info */
format = *((Uint16*) (p));
channels = *((Uint16*) (p + 2));
samplerate = *((Uint32*) (p + 4));
bitdepth = *((Uint16*) (p + 14));
if (format != 1) {
return WAV_ENOSUPPORT;
}
if (channels == 0 || samplerate == 0 || bitdepth == 0) {
return WAV_EBADFMT;
}
/* Find data subchunk */
p = findSubChunk(data, len, "data", &sz);
if (!p) return WAV_ENODATA;
/* Init wav_t struct */
w->data = p;
w->samplerate = samplerate;
w->channels = channels;
w->length = (sz / (bitdepth / 8)) / channels;
w->bitdepth = bitdepth;
/* Done! */
return WAV_ESUCCESS;
}
const char *wav_strerror(int err) {
switch (err) {
case WAV_ESUCCESS : return "success";
case WAV_EFAILURE : return "failure";
case WAV_EBADHEADER : return "bad header data";
case WAV_EBADFMT : return "bad fmt data";
case WAV_ENOFMT : return "missing 'fmt' subchunk";
case WAV_ENODATA : return "missing 'data' subchunk";
case WAV_ENOSUPPORT : return "unsupported format; "
"expected uncompressed PCM";
}
return "unknown error";
}

View File

@@ -1,102 +0,0 @@
/**
* Copyright (c) 2017 Florian Kesseler
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the MIT license. See LICENSE for details.
*/
#include <string.h>
#include "filesystem.h"
#include "wavefile.h"
#include "source.h"
#include "lib/dmt/dmt.h"
typedef struct {
uint32_t chunkId;
uint32_t chunkSize;
uint32_t format;
uint32_t subchunk1Id;
uint32_t subchunk1Size;
uint16_t audioFormat;
uint16_t numChannels;
uint32_t sampleRate;
uint32_t byteRate;
uint16_t blockAlign;
uint16_t bitsPerSample;
uint32_t subchunk2Id;
uint32_t subchunk2Size;
} waveheader_t;
#define RIFF_CHUNK_ID 0x46464952
#define WAVE_FORMAT 0x45564157
#define FORMAT_CHUNK_ID 0x20746d66
#define DATA_CHUNK_ID 0x61746164
#define FORMAT_CHUNK_SIZE 16
#define AUDIO_FORMAT_PCM 1
char const* wavefile_load(source_t *source, char const *filename) {
int fileSize;
char const *err = 0;
uint8_t *waveData = filesystem_read(filename, &fileSize);
if(waveData == NULL) {
err = "Could not read WAV file";
goto fail;
}
waveheader_t const* header = (waveheader_t const*)waveData;
if(header->chunkId != RIFF_CHUNK_ID
|| header->format != WAVE_FORMAT
|| header->subchunk1Id != FORMAT_CHUNK_ID
|| header->subchunk2Id != DATA_CHUNK_ID) {
err = "Invalid WAV header";
goto fail;
}
if(header->subchunk1Size != FORMAT_CHUNK_SIZE
|| header->audioFormat != AUDIO_FORMAT_PCM) {
err = "Invalid Audio Format (only PCM supported)";
goto fail;
}
if(header->numChannels != 1) {
err = "Invalid Audio Format (only 1 channel supported)";
goto fail;
}
if(header->sampleRate != 22050) {
err = "Invalid Audio Format (only 22050Hz supported)";
goto fail;
}
if(header->bitsPerSample != 16) {
err = "Invalid Audio Format (only 16 Bit supported)";
goto fail;
}
if(header->byteRate != header->sampleRate * header->numChannels * header->bitsPerSample / 8) {
err = "Byte rate doesn't match header info";
goto fail;
}
if(header->blockAlign != header->numChannels * header->bitsPerSample / 8) {
err = "Block alignment doesn't match header info";
goto fail;
}
if(fileSize < sizeof(waveheader_t) + header->subchunk2Size) {
err = "Short read while reading samples";
goto fail;
}
source->sampleCount = header->subchunk2Size / 2;
source->samples = (int16_t*)dmt_malloc(header->subchunk2Size);
memcpy(source->samples, ((uint8_t*)waveData) + sizeof(waveheader_t), header->subchunk2Size);
fail:
filesystem_free(waveData);
return err;
}

View File

@@ -1,15 +0,0 @@
/**
* Copyright (c) 2017 Florian Kesseler
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the MIT license. See LICENSE for details.
*/
#ifndef WAVEFILE_H
#define WAVEFILE_H
#include "source.h"
char const* wavefile_load(source_t *source, char const *filename);
#endif