/*************************************************************************** * Copyright (C) 2010 * by Dimok * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any * damages arising from the use of this software. * * Permission is granted to anyone to use this software for any * purpose, including commercial applications, and to alter it and * redistribute it freely, subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you * must not claim that you wrote the original software. If you use * this software in a product, an acknowledgment in the product * documentation would be appreciated but is not required. * * 2. Altered source versions must be plainly marked as such, and * must not be misrepresented as being the original software. * * 3. This notice may not be removed or altered from any source * distribution. * * for WiiXplorer 2010 ***************************************************************************/ #include #include #include "AifDecoder.hpp" #include "gecko.h" typedef struct { u32 fccCOMM; u32 size; u16 channels; u8 frames[4]; u16 bps; u8 freq[10]; } SAIFFCommChunk; typedef struct { u32 fccSSND; u32 size; u32 offset; u32 blockSize; } SAIFFSSndChunk; // ------ // Copyright (C) 1988-1991 Apple Computer, Inc. #ifndef HUGE_VAL # define HUGE_VAL HUGE #endif # define UnsignedToFloat(u) (((double)((long)(u - 2147483647L - 1))) + 2147483648.0) static double ConvertFromIeeeExtended(const unsigned char* bytes) { double f; int expon; unsigned long hiMant, loMant; expon = ((bytes[0] & 0x7F) << 8) | (bytes[1] & 0xFF); hiMant = ((unsigned long)(bytes[2] & 0xFF) << 24) | ((unsigned long)(bytes[3] & 0xFF) << 16) | ((unsigned long)(bytes[4] & 0xFF) << 8) | ((unsigned long)(bytes[5] & 0xFF)); loMant = ((unsigned long)(bytes[6] & 0xFF) << 24) | ((unsigned long)(bytes[7] & 0xFF) << 16) | ((unsigned long)(bytes[8] & 0xFF) << 8) | ((unsigned long)(bytes[9] & 0xFF)); if (expon == 0 && hiMant == 0 && loMant == 0) { f = 0; } else { if (expon == 0x7FFF) { f = HUGE_VAL; } else { expon -= 16383; f = ldexp(UnsignedToFloat(hiMant), expon-=31); f += ldexp(UnsignedToFloat(loMant), expon-=32); } } if (bytes[0] & 0x80) return -f; else return f; } AifDecoder::AifDecoder(const char * filepath) : SoundDecoder(filepath) { SoundType = SOUND_AIF; if(!file_fd) return; OpenFile(); } AifDecoder::AifDecoder(const u8 * snd, int len) : SoundDecoder(snd, len) { SoundType = SOUND_AIF; if(!file_fd) return; OpenFile(); } AifDecoder::~AifDecoder() { } void AifDecoder::OpenFile() { SWaveHdr Header; file_fd->read((u8 *) &Header, sizeof(SWaveHdr)); if (Header.magicRIFF != 'FORM') { CloseFile(); return; } else if(Header.magicWAVE != 'AIFF') { CloseFile(); return; } SWaveChunk WaveChunk; u32 limit = 0; while(limit != 60) { int ret = file_fd->read((u8 *) &WaveChunk, sizeof(SWaveChunk)); if(ret <= 0) { CloseFile(); return; } if(WaveChunk.magicDATA == 'COMM') break; file_fd->seek(-sizeof(SWaveChunk)+1, SEEK_CUR); limit++; } DataOffset = file_fd->tell()+WaveChunk.size; SAIFFCommChunk CommHdr; file_fd->seek(file_fd->tell()-sizeof(SWaveChunk), SEEK_SET); file_fd->read((u8 *) &CommHdr, sizeof(SAIFFCommChunk)); if(CommHdr.fccCOMM != 'COMM') { CloseFile(); return; } file_fd->seek(DataOffset, SEEK_SET); SAIFFSSndChunk SSndChunk; limit = 0; while(limit != 60) { file_fd->read((u8 *) &SSndChunk, sizeof(SAIFFSSndChunk)); if(SSndChunk.fccSSND == 'SSND') break; file_fd->seek(-sizeof(SAIFFSSndChunk)+1, SEEK_CUR); DataOffset += 1; limit++; } DataOffset += sizeof(SAIFFSSndChunk); DataSize = SSndChunk.size-8; SampleRate = (u32) ConvertFromIeeeExtended(CommHdr.freq); Format = VOICE_STEREO_16BIT; if(CommHdr.channels == 1 && CommHdr.bps == 8) Format = VOICE_MONO_8BIT; else if (CommHdr.channels == 1 && CommHdr.bps == 16) Format = VOICE_MONO_16BIT; else if (CommHdr.channels == 2 && CommHdr.bps == 8) Format = VOICE_STEREO_8BIT; else if (CommHdr.channels == 2 && CommHdr.bps == 16) Format = VOICE_STEREO_16BIT; Decode(); } void AifDecoder::CloseFile() { if(file_fd) delete file_fd; file_fd = NULL; } int AifDecoder::Read(u8 * buffer, int buffer_size, int) { if(!file_fd) return -1; if(CurPos >= (int) DataSize) return 0; file_fd->seek(DataOffset+CurPos, SEEK_SET); if(buffer_size > (int) DataSize-CurPos) buffer_size = DataSize-CurPos; int read = file_fd->read(buffer, buffer_size); if(read > 0) { CurPos += read; } return read; }