diff --git a/Cog.xcodeproj/project.pbxproj b/Cog.xcodeproj/project.pbxproj index a3809e973..6f527c22a 100644 --- a/Cog.xcodeproj/project.pbxproj +++ b/Cog.xcodeproj/project.pbxproj @@ -149,6 +149,8 @@ 8D1107320486CEB800E47090 /* Cog.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Cog.app; sourceTree = BUILT_PRODUCTS_DIR; }; 8E4C7F060A0509FC003BE25F /* DragScrollView.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DragScrollView.h; sourceTree = ""; }; 8E4C7F070A0509FC003BE25F /* DragScrollView.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = DragScrollView.m; sourceTree = ""; }; + 8E643DF20A2B585600844A28 /* GameFile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GameFile.h; sourceTree = ""; }; + 8E643DF30A2B585600844A28 /* GameFile.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = GameFile.mm; sourceTree = ""; }; 8E6A8E270A0D8A68002ABE9C /* CoreAudioFile.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CoreAudioFile.h; sourceTree = ""; }; 8E6A8E280A0D8A68002ABE9C /* CoreAudioFile.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = CoreAudioFile.m; sourceTree = ""; }; 8E6A8E350A0D8AD8002ABE9C /* CoreAudioUtils.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CoreAudioUtils.h; sourceTree = ""; }; @@ -488,6 +490,8 @@ 8E75755609F31D5A0080F1EE /* WaveFile.m */, 8E75755709F31D5A0080F1EE /* WavPackFile.h */, 8E75755809F31D5A0080F1EE /* WavPackFile.m */, + 8E643DF20A2B585600844A28 /* GameFile.h */, + 8E643DF30A2B585600844A28 /* GameFile.mm */, ); path = SoundFile; sourceTree = ""; @@ -755,6 +759,7 @@ "$(SRCROOT)/Libraries/Vorbis/build/Release", "$(SRCROOT)/Libraries/WavPack/build/Release", "$(SRCROOT)/Libraries/SndFile/build/Release", + "$(SRCROOT)/Libraries/GME/build/Release", ); GCC_DYNAMIC_NO_PIC = NO; GCC_ENABLE_FIX_AND_CONTINUE = YES; @@ -792,6 +797,7 @@ "$(SRCROOT)/Libraries/Vorbis/build/Release", "$(SRCROOT)/Libraries/WavPack/build/Release", "$(SRCROOT)/Libraries/SndFile/build/Release", + "$(SRCROOT)/Libraries/GME/build/Release", ); GCC_GENERATE_DEBUGGING_SYMBOLS = NO; GCC_MODEL_TUNING = G5; diff --git a/Sound/SoundFile/CoreAudioFile.h b/Sound/SoundFile/CoreAudioFile.h index 437e65586..b66d5c80a 100644 --- a/Sound/SoundFile/CoreAudioFile.h +++ b/Sound/SoundFile/CoreAudioFile.h @@ -23,7 +23,6 @@ #include #import "SoundFile.h" - #define _USE_WRAPPER_ @interface CoreAudioFile : SoundFile @@ -31,10 +30,11 @@ ExtAudioFileRef _in; #ifdef _USE_WRAPPER_ - FILE * _inFd; + int _inFd; AudioFileID _audioID; SInt64 _fileSize; + SInt64 _startOffset; #endif } diff --git a/Sound/SoundFile/CoreAudioFile.m b/Sound/SoundFile/CoreAudioFile.m index 4389cd4fa..667015e32 100644 --- a/Sound/SoundFile/CoreAudioFile.m +++ b/Sound/SoundFile/CoreAudioFile.m @@ -18,6 +18,8 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include + #import "CoreAudioFile.h" @interface CoreAudioFile (Private) @@ -30,11 +32,13 @@ OSStatus readFunc(void * inRefCon, SInt64 inPosition, ByteCount requestCount, void *buffer, ByteCount* actualCount) { CoreAudioFile *caf = (CoreAudioFile *)inRefCon; - FILE *fd = caf->_inFd; + int fd = caf->_inFd; - fseek(fd, inPosition, SEEK_SET); + // fseek(fd, inPosition, SEEK_SET); +// NSLog(@"Requesting %u", requestCount); +// NSLog(@"Currently at %lli", inPosition); - *actualCount = fread(buffer, 1, requestCount, fd); + *actualCount = pread(fd, buffer, requestCount, inPosition+caf->_startOffset); if (*actualCount <= 0) { @@ -47,15 +51,14 @@ OSStatus readFunc(void * inRefCon, SInt64 inPosition, ByteCount requestCount, vo SInt64 getSizeFunc(void *inRefCon) { CoreAudioFile *caf = (CoreAudioFile *)inRefCon; - FILE *fd = caf->_inFd; - - + int fd = caf->_inFd; + if (caf->_fileSize != 0) { return caf->_fileSize; } - long curPos; + /* long curPos; curPos = ftell(fd); @@ -64,7 +67,12 @@ SInt64 getSizeFunc(void *inRefCon) caf->_fileSize = ftell(fd); fseek(fd, curPos, SEEK_SET); - + */ + + caf->_fileSize = lseek(fd, 0, SEEK_END) - caf->_startOffset; + NSLog(@"SIZE at %lli", caf->_fileSize); + + NSLog(@"ERROR: %i = %i %i %i", errno, EBADF, ESPIPE, EINVAL); return caf->_fileSize; } @@ -90,9 +98,10 @@ OSStatus writeFunc(void * inRefCon, SInt64 inPosition, ByteCount requestCount, c - (void) close { OSStatus err; - + #ifdef _USE_WRAPPER_ - fclose(_inFd); + if (_inFd) + close(_inFd); AudioFileClose(_audioID); #endif @@ -105,31 +114,73 @@ OSStatus writeFunc(void * inRefCon, SInt64 inPosition, ByteCount requestCount, c - (BOOL) readInfo:(const char *)filename { OSStatus err; - + AudioFileTypeID type = 0; + NSString *ext; + #ifdef _USE_WRAPPER_ // Open the input file - _inFd = fopen(filename, "r"); - if (!_inFd) + _inFd = open(filename, O_RDONLY, 0777); + if (_inFd < 0) { NSLog(@"Error operning file: %s", filename); return NO; } + _startOffset = 0; + ext = [[NSString stringWithCString:filename encoding:NSASCIIStringEncoding] pathExtension]; + //Find first sync frame for MP3 + if([ext caseInsensitiveCompare:@"mp3"] == NSOrderedSame) { + size_t bytesRead; + uint8_t buf[2]; + + type = kAudioFileMP3Type; + + for(;;) { + bytesRead = read(_inFd, buf, 2); + + + if(2 != bytesRead) { + NSLog(@"Error finding mp3 sync frame"); + close(_inFd); + return NO; + } + + + // found some kind of data + if(0x00 != buf[0] || 0x00 != buf[1]) { + _startOffset = lseek(_inFd, 0, SEEK_CUR) - 2; + NSLog(@"Found sync frame at: %llx", _startOffset); + break; + } + } + } + else if([ext caseInsensitiveCompare:@"aac"] == NSOrderedSame) { + type = kAudioFileAAC_ADTSType; + } + else if([ext caseInsensitiveCompare:@"m4a"] == NSOrderedSame) { + type = kAudioFileM4AType; + } + else if([ext caseInsensitiveCompare:@"mp4"] == NSOrderedSame) { + type = kAudioFileMPEG4Type; + } + //Using callbacks with fopen, ftell, fseek, fclose, because the default pread hangs when accessing the same file from multiple threads. - err = AudioFileOpenWithCallbacks(self, readFunc, writeFunc, getSizeFunc, setSizeFunc, 0, &_audioID); + err = AudioFileOpenWithCallbacks(self, readFunc, writeFunc, getSizeFunc, setSizeFunc, type, &_audioID); if(noErr != err) { + NSLog(@"Error opening with callbacks, falling back: %s", (char *)&err); FSRef ref; - fclose(_inFd); + close(_inFd); + _inFd = 0; err = FSPathMakeRef((const UInt8 *)filename, &ref, NULL); if(noErr != err) { return NO; } - err = AudioFileOpen(&ref, fsRdPerm, 0, &_audioID); + err = AudioFileOpen(&ref, fsRdPerm, type, &_audioID); if(noErr != err) { - NSLog(@"Error opening AudioFile: %i", (char *)&err); + NSLog(@"Error opening AudioFile: %s", (char *)&err); return NO; } } @@ -141,7 +192,7 @@ OSStatus writeFunc(void * inRefCon, SInt64 inPosition, ByteCount requestCount, c #else FSRef ref; - + // Open the input file err = FSPathMakeRef((const UInt8 *)filename, &ref, NULL); if(noErr != err) { @@ -150,6 +201,7 @@ OSStatus writeFunc(void * inRefCon, SInt64 inPosition, ByteCount requestCount, c err = ExtAudioFileOpen(&ref, &_in); if(noErr != err) { + NSLog(@"Error opening file: %s", &err); return NO; } #endif @@ -162,7 +214,7 @@ OSStatus writeFunc(void * inRefCon, SInt64 inPosition, ByteCount requestCount, c UInt32 size; SInt64 totalFrames; AudioStreamBasicDescription asbd; - + // Get input file information size = sizeof(asbd); err = ExtAudioFileGetProperty(_in, kExtAudioFileProperty_FileDataFormat, &size, &asbd); @@ -170,14 +222,14 @@ OSStatus writeFunc(void * inRefCon, SInt64 inPosition, ByteCount requestCount, c err = ExtAudioFileDispose(_in); return NO; } - + size = sizeof(totalFrames); err = ExtAudioFileGetProperty(_in, kExtAudioFileProperty_FileLengthFrames, &size, &totalFrames); if(err != noErr) { err = ExtAudioFileDispose(_in); return NO; } - + #ifdef _USE_WRAPPER_ SInt64 totalBytes; @@ -205,7 +257,7 @@ OSStatus writeFunc(void * inRefCon, SInt64 inPosition, ByteCount requestCount, c } totalSize = totalFrames * channels * (bitsPerSample / 8); - + // Set output format AudioStreamBasicDescription result; @@ -221,7 +273,7 @@ OSStatus writeFunc(void * inRefCon, SInt64 inPosition, ByteCount requestCount, c result.mBytesPerPacket = channels * (bitsPerSample / 8); result.mFramesPerPacket = 1; result.mBytesPerFrame = channels * (bitsPerSample / 8); - + err = ExtAudioFileSetProperty(_in, kExtAudioFileProperty_ClientDataFormat, sizeof(result), &result); if(noErr != err) { err = ExtAudioFileDispose(_in); @@ -231,7 +283,7 @@ OSStatus writeFunc(void * inRefCon, SInt64 inPosition, ByteCount requestCount, c // Further properties isBigEndian = YES; isUnsigned = NO; - + return YES; } @@ -260,7 +312,7 @@ OSStatus writeFunc(void * inRefCon, SInt64 inPosition, ByteCount requestCount, c - (double) seekToTime:(double)milliseconds { OSStatus err; - + err = ExtAudioFileSeek(_in, ((milliseconds / 1000.f) * frequency)); if(noErr != err) { return -1.f; diff --git a/Sound/SoundFile/GameFile.h b/Sound/SoundFile/GameFile.h new file mode 100644 index 000000000..6f79d0093 --- /dev/null +++ b/Sound/SoundFile/GameFile.h @@ -0,0 +1,19 @@ +// +// GameFile.h +// Cog +// +// Created by Zaphod Beeblebrox on 5/29/06. +// Copyright 2006 __MyCompanyName__. All rights reserved. +// + +#import +#import "SoundFile.h" + +#undef HAVE_CONFIG_H + +#import "GME/Music_Emu.h" +@interface GameFile : SoundFile { + Music_Emu* emu; +} + +@end diff --git a/Sound/SoundFile/GameFile.mm b/Sound/SoundFile/GameFile.mm new file mode 100644 index 000000000..c3acf7046 --- /dev/null +++ b/Sound/SoundFile/GameFile.mm @@ -0,0 +1,110 @@ +// +// GameFile.m +// Cog +// +// Created by Zaphod Beeblebrox on 5/29/06. +// Copyright 2006 __MyCompanyName__. All rights reserved. +// + +#import "GameFile.h" + +#include "GME/Nsf_Emu.h" +#include "GME/Gbs_Emu.h" +#include "GME/Spc_Emu.h" +#include "GME/Vgm_Emu.h" +#include "GME/Gym_Emu.h" + +@implementation GameFile + +- (BOOL)open:(const char *)filename +{ + int i; + const char* p; + char ext[3]; + + p = strrchr( (char*) filename, '.' )+1; + NSLog(@"OPENING GAME FILE: %s", filename); + NSLog(@"Extension: %s", p); + + if (!p || strlen(p) != 3) + return NO; + + for (i = 0; i < 4; i++) + ext[i] = toupper(p[i]); + ext[3] = 0; + + if (!ext) + emu = NULL; + else if ( !strcmp( ext, "NSF" ) ) + emu = new Nsf_Emu; + else if ( !strcmp( ext, "GBS" ) ) + emu = new Gbs_Emu; + else if ( !strcmp( ext, "SPC" ) ) + emu = new Spc_Emu; + else if ( !strcmp( ext, "VGM" ) || !strcmp( ext, "VGZ" ) ) + emu = new Vgm_Emu; + else if ( !strcmp( ext, "GYM" ) ) + emu = new Gym_Emu; + else + emu = NULL; + + NSLog(@"EMU IS: %i", emu); + if (!emu) + return NO; + + emu->set_sample_rate(44100); + emu->load_file(filename); + emu->start_track( 0 ); + frequency = 44100; + channels = 2; + + bitsPerSample = 8 * sizeof(Music_Emu::sample_t); + + totalSize = emu->track_count() * frequency*(bitsPerSample/8)*channels; + + isBigEndian = YES; + + NSLog(@"OPENED GAME FILE:"); + + return YES; +} + +- (BOOL)readInfo:(const char *)filename +{ + return [self open:filename]; +} + +- (int)fillBuffer:(void *)buf ofSize:(UInt32)size +{ + int numSamples = size / ((bitsPerSample/8)); + + emu->play(numSamples, (short int *)buf); + + return size; //No such thing as EOF +} + +//Cheap hack until I figure out how to actually support multiple tracks in a single file. +- (double)seekToTime:(double)milliseconds +{ + int track; + track = (int)(milliseconds/1000.0); + NSLog(@"Track: %i", track); + if (track > emu->track_count()) + { + track = emu->track_count(); + } + emu->start_track( track ); + + + return -1.0; +} + +- (void)close +{ + if (emu) + delete emu; + +} + + +@end diff --git a/Sound/SoundFile/SoundFile.mm b/Sound/SoundFile/SoundFile.mm index 5d65fa07b..e7af6fec4 100644 --- a/Sound/SoundFile/SoundFile.mm +++ b/Sound/SoundFile/SoundFile.mm @@ -18,6 +18,7 @@ #import "WavPackFile.h" #import "ShnFile.h" #import "CoreAudioFile.h" +#import "GameFile.h" extern "C" { BOOL hostIsBigEndian()