diff --git a/buildtools b/buildtools index 29ab223..78acb42 160000 --- a/buildtools +++ b/buildtools @@ -1 +1 @@ -Subproject commit 29ab2234e7376807d154a2a06b5d3d49ad50f631 +Subproject commit 78acb42849b6d8316a2a9de52c4cc41b784d4508 diff --git a/source/cmd.cpp b/source/cmd.cpp index 05e07e6..a3658eb 100644 --- a/source/cmd.cpp +++ b/source/cmd.cpp @@ -45,7 +45,7 @@ u8* convert_to_cwav(const std::string& file, u32* size) { cwav.channels = wav->format.numChannels; cwav.sampleRate = wav->format.sampleRate; cwav.bitsPerSample = wav->format.bitsPerSample; - cwav.dataSize = wav->data.chunkSize; + cwav.dataSize = wav->data.size; cwav.data = wav->data.data; ret = cwav_build(cwav, size); @@ -59,10 +59,10 @@ u8* convert_to_cwav(const std::string& file, u32* size) { stb_vorbis_info info = stb_vorbis_get_info(vorb); CWAV cwav; - cwav.channels = info.channels; + cwav.channels = (u32) info.channels; cwav.sampleRate = info.sample_rate; cwav.bitsPerSample = 16; // stb_vorbis always outputs 16 bit samples - int sampleCount = stb_vorbis_stream_length_in_samples(vorb) * info.channels; + u32 sampleCount = stb_vorbis_stream_length_in_samples(vorb) * info.channels; cwav.dataSize = sampleCount * 2; cwav.data = (u8*) calloc(sampleCount, 2); stb_vorbis_get_samples_short_interleaved(vorb, info.channels, (short*) cwav.data, sampleCount); diff --git a/source/pc/wav.cpp b/source/pc/wav.cpp index 1d1be60..d369a86 100644 --- a/source/pc/wav.cpp +++ b/source/pc/wav.cpp @@ -4,17 +4,35 @@ #include #include -bool wav_find_chunk(FILE* fd, const char* magic) { - char curr[5] = {0}; - for(long pos = ftell(fd); strcmp(curr, magic) != 0; pos++) { - fseek(fd, pos, SEEK_SET); - size_t read = fread(curr, 1, 4, fd); - if(read <= 0) { - return false; - } +typedef struct { + FILE* fd; + WavChunkHeader currChunk; + long currChunkDataPos; +} WavContext; + +static bool wav_next_chunk(WavContext* context) { + if(fseek(context->fd, context->currChunkDataPos + (memcmp(context->currChunk.chunkId, "RIFF", 4) == 0 ? 4 : context->currChunk.chunkSize), SEEK_SET) < 0) { + return false; + } + + if(fread(&context->currChunk, sizeof(WavChunkHeader), 1, context->fd) <= 0) { + return false; + } + + context->currChunkDataPos = ftell(context->fd); + return true; +} + +static bool wav_read_chunk_data(WavContext* context, void* data, size_t maxSize) { + if(fseek(context->fd, context->currChunkDataPos, SEEK_SET) < 0) { + return false; + } + + size_t size = context->currChunk.chunkSize < maxSize ? context->currChunk.chunkSize : maxSize; + if(fread(data, size, 1, context->fd) <= 0) { + return false; } - fseek(fd, -4, SEEK_CUR); return true; } @@ -24,43 +42,48 @@ WAV* wav_read(FILE* fd) { return NULL; } - if(!wav_find_chunk(fd, "RIFF")) { - printf("ERROR: Could not find WAV RIFF chunk.\n"); + WAV* wav = (WAV*) calloc(1, sizeof(WAV)); + + WavContext context; + memset(&context, 0, sizeof(context)); + context.fd = fd; + + u32 foundChunks = 0; + while(wav_next_chunk(&context)) { + if(memcmp(context.currChunk.chunkId, "RIFF", 4) == 0) { + if(wav_read_chunk_data(&context, &wav->riff, sizeof(WavRiffChunk))) { + foundChunks++; + } + } else if(memcmp(context.currChunk.chunkId, "fmt ", 4) == 0) { + if(wav_read_chunk_data(&context, &wav->format, sizeof(WavFormatChunk))) { + foundChunks++; + } + } else if(memcmp(context.currChunk.chunkId, "data", 4) == 0) { + wav->data.size = context.currChunk.chunkSize; + wav->data.data = (u8*) malloc(wav->data.size); + if(wav_read_chunk_data(&context, wav->data.data, wav->data.size)) { + foundChunks++; + } + } + } + + if(foundChunks != 3) { + wav_free(wav); + + printf("ERROR: Failed to read WAV chunks: %s\n", errno != 0 ? strerror(errno) : "Not enough chunks."); return NULL; } - Riff riff; - fread(&riff, sizeof(Riff), 1, fd); - - if(!wav_find_chunk(fd, "fmt ")) { - printf("ERROR: Could not find WAV format chunk.\n"); - return NULL; - } - - Format format; - fread(&format, sizeof(Format), 1, fd); - - if(!wav_find_chunk(fd, "data")) { - printf("ERROR: Could not find WAV data chunk.\n"); - return NULL; - } - - Data data; - fread(&(data.chunkId), sizeof(data.chunkId), 1, fd); - fread(&(data.chunkSize), sizeof(data.chunkSize), 1, fd); - data.data = (u8*) malloc(data.chunkSize); - fread(data.data, 1, data.chunkSize, fd); - - WAV* wav = (WAV*) malloc(sizeof(WAV)); - wav->riff = riff; - wav->format = format; - wav->data = data; return wav; } void wav_free(WAV* wav) { if(wav != NULL) { - free(wav->data.data); + if(wav->data.data != NULL) { + free(wav->data.data); + wav->data.data = NULL; + } + free(wav); } } diff --git a/source/pc/wav.h b/source/pc/wav.h index 25f33d2..a4dc866 100644 --- a/source/pc/wav.h +++ b/source/pc/wav.h @@ -8,30 +8,30 @@ typedef struct { char chunkId[4]; u32 chunkSize; - char format[4]; -} Riff; +} WavChunkHeader; + +typedef struct { + char format[4]; +} WavRiffChunk; typedef struct { - char chunkId[4]; - u32 chunkSize; u16 format; u16 numChannels; u32 sampleRate; u32 byteRate; u16 align; u16 bitsPerSample; -} Format; +} WavFormatChunk; typedef struct { - char chunkId[4]; - u32 chunkSize; + u32 size; u8* data; -} Data; +} WavDataChunk; typedef struct { - Riff riff; - Format format; - Data data; + WavRiffChunk riff; + WavFormatChunk format; + WavDataChunk data; } WAV; WAV* wav_read(FILE* fd);