SID: Add exception handling

Exception handling was quite missing from this code
as well. Let's fix that too.

Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This commit is contained in:
Christopher Snowhill 2025-01-30 01:16:58 -08:00
parent 8eddb7bf40
commit 034b0d20b8
3 changed files with 177 additions and 117 deletions

View file

@ -35,31 +35,44 @@
id<CogSource> source = [audioSourceClass audioSourceForURL:url]; id<CogSource> source = [audioSourceClass audioSourceForURL:url];
if(![source open:url]) if(![source open:url])
return 0; return @[];
if(![source seekable]) if(![source seekable])
return 0; return @[];
[source seek:0 whence:SEEK_END]; [source seek:0 whence:SEEK_END];
long size = [source tell]; long size = [source tell];
[source seek:0 whence:SEEK_SET]; [source seek:0 whence:SEEK_SET];
if(!size)
return @[];
void *data = malloc(size); void *data = malloc(size);
if(!data)
return @[];
[source read:data amount:size]; [source read:data amount:size];
SidTune *tune = new SidTune((const uint_least8_t *)data, (uint_least32_t)size); unsigned int subsongs = 0;
try {
SidTune *tune = new SidTune((const uint_least8_t *)data, (uint_least32_t)size);
if(!tune->getStatus()) {
delete tune;
return 0;
}
const SidTuneInfo *info = tune->getInfo();
subsongs = info->songs();
if(!tune->getStatus()) {
delete tune; delete tune;
return 0; } catch (std::exception &e) {
ALog(@"Exception caught processing SID file for song count: %s", e.what());
return @[];
} }
const SidTuneInfo *info = tune->getInfo();
unsigned int subsongs = info->songs();
delete tune;
NSMutableArray *tracks = [NSMutableArray array]; NSMutableArray *tracks = [NSMutableArray array];
for(unsigned int i = 1; i <= subsongs; ++i) { for(unsigned int i = 1; i <= subsongs; ++i) {

View file

@ -85,6 +85,8 @@ static const char *extListStr[] = { ".str", NULL };
[source seek:0 whence:SEEK_END]; [source seek:0 whence:SEEK_END];
size_t fileSize = [source tell]; size_t fileSize = [source tell];
if(!fileSize)
return;
void *dataBytes = malloc(fileSize); void *dataBytes = malloc(fileSize);
if(!dataBytes) if(!dataBytes)
@ -162,17 +164,21 @@ static void sidTuneLoader(const char *fileName, std::vector<uint8_t> &bufferRef)
// Need this static initializer to create the static global tables that sidplayfp doesn't really lock access to // Need this static initializer to create the static global tables that sidplayfp doesn't really lock access to
+ (void)initialize { + (void)initialize {
ReSIDfpBuilder *builder = new ReSIDfpBuilder("ReSIDfp"); try {
ReSIDfpBuilder *builder = new ReSIDfpBuilder("ReSIDfp");
if(builder) { if(builder) {
builder->create(1); builder->create(1);
if(builder->getStatus()) { if(builder->getStatus()) {
builder->filter(true); builder->filter(true);
builder->filter6581Curve(0.5); builder->filter6581Curve(0.5);
builder->filter8580Curve(0.5); builder->filter8580Curve(0.5);
}
delete builder;
} }
} catch (std::exception &e) {
delete builder; ALog(@"Exception caught while doing one-time initialization of SID player: %s", e.what());
} }
} }
@ -204,61 +210,66 @@ static void sidTuneLoader(const char *fileName, std::vector<uint8_t> &bufferRef)
const char **extList = [extension isEqualToString:@"mus"] ? extListStr : extListEmpty; const char **extList = [extension isEqualToString:@"mus"] ? extListStr : extListEmpty;
tune = new SidTune(sidTuneLoader, [currentUrl UTF8String], extList, true); try {
tune = new SidTune(sidTuneLoader, [currentUrl UTF8String], extList, true);
if(!tune->getStatus()) if(!tune->getStatus())
return NO;
NSURL *url = [s url];
int track_num;
if([[url fragment] length] == 0)
track_num = 1;
else
track_num = [[url fragment] intValue];
n_channels = 1;
double defaultLength = [[[[NSUserDefaultsController sharedUserDefaultsController] defaults] valueForKey:@"synthDefaultSeconds"] doubleValue];
length = (int)ceil(sampleRate * defaultLength);
tune->selectSong(track_num);
engine = new sidplayfp;
engine->setRoms(kernel, basic, chargen);
if(!engine->load(tune))
return NO;
ReSIDfpBuilder *_builder = new ReSIDfpBuilder("ReSIDfp");
builder = _builder;
if(_builder) {
_builder->create((engine->info()).maxsids());
if(_builder->getStatus()) {
_builder->filter(true);
_builder->filter6581Curve(0.5);
_builder->filter8580Curve(0.5);
}
if(!_builder->getStatus())
return NO; return NO;
} else
NSURL *url = [s url];
int track_num;
if([[url fragment] length] == 0)
track_num = 1;
else
track_num = [[url fragment] intValue];
n_channels = 1;
double defaultLength = [[[[NSUserDefaultsController sharedUserDefaultsController] defaults] valueForKey:@"synthDefaultSeconds"] doubleValue];
length = (int)ceil(sampleRate * defaultLength);
tune->selectSong(track_num);
engine = new sidplayfp;
engine->setRoms(kernel, basic, chargen);
if(!engine->load(tune))
return NO;
ReSIDfpBuilder *_builder = new ReSIDfpBuilder("ReSIDfp");
builder = _builder;
if(_builder) {
_builder->create((engine->info()).maxsids());
if(_builder->getStatus()) {
_builder->filter(true);
_builder->filter6581Curve(0.5);
_builder->filter8580Curve(0.5);
}
if(!_builder->getStatus())
return NO;
} else
return NO;
const SidTuneInfo *tuneInfo = tune->getInfo();
SidConfig conf = engine->config();
conf.frequency = (int)ceil(sampleRate);
conf.sidEmulation = builder;
conf.playback = SidConfig::MONO;
if(tuneInfo && (tuneInfo->sidChips() > 1))
conf.playback = SidConfig::STEREO;
if(!engine->config(conf))
return NO;
if(conf.playback == SidConfig::STEREO) {
n_channels = 2;
}
} catch (std::exception &e) {
ALog(@"Exception caught loading SID file: %s", e.what());
return NO; return NO;
const SidTuneInfo *tuneInfo = tune->getInfo();
SidConfig conf = engine->config();
conf.frequency = (int)ceil(sampleRate);
conf.sidEmulation = builder;
conf.playback = SidConfig::MONO;
if(tuneInfo && (tuneInfo->sidChips() > 1))
conf.playback = SidConfig::STEREO;
if(!engine->config(conf))
return NO;
if(conf.playback == SidConfig::STEREO) {
n_channels = 2;
} }
double defaultFade = [[[[NSUserDefaultsController sharedUserDefaultsController] defaults] valueForKey:@"synthDefaultFadeSeconds"] doubleValue]; double defaultFade = [[[[NSUserDefaultsController sharedUserDefaultsController] defaults] valueForKey:@"synthDefaultFadeSeconds"] doubleValue];
@ -299,7 +310,13 @@ static void sidTuneLoader(const char *fileName, std::vector<uint8_t> &bufferRef)
int16_t buffer[1024 * n_channels]; int16_t buffer[1024 * n_channels];
int framesToRender = 1024; int framesToRender = 1024;
int rendered = engine->play(buffer, framesToRender * n_channels) / n_channels; int rendered = 0;
try {
rendered = engine->play(buffer, framesToRender * n_channels) / n_channels;
} catch (std::exception &e) {
ALog(@"Exception caught while playing SID file: %s", e.what());
return nil;
}
if(rendered <= 0) if(rendered <= 0)
return nil; return nil;
@ -343,8 +360,13 @@ static void sidTuneLoader(const char *fileName, std::vector<uint8_t> &bufferRef)
- (long)seek:(long)frame { - (long)seek:(long)frame {
if(frame < renderedTotal) { if(frame < renderedTotal) {
engine->load(tune);
renderedTotal = 0; renderedTotal = 0;
try {
engine->load(tune);
} catch (std::exception &e) {
ALog(@"Exception caught reloading SID tune for seeking: %s", e.what());
return -1;
}
} }
int16_t sampleBuffer[1024 * 2]; int16_t sampleBuffer[1024 * 2];
@ -352,48 +374,58 @@ static void sidTuneLoader(const char *fileName, std::vector<uint8_t> &bufferRef)
long remain = (frame - renderedTotal) % 32; long remain = (frame - renderedTotal) % 32;
frame /= 32; frame /= 32;
renderedTotal /= 32; renderedTotal /= 32;
engine->fastForward(100 * 32);
while(renderedTotal < frame) { try {
long todo = frame - renderedTotal; engine->fastForward(100 * 32);
if(todo > 1024)
todo = 1024;
int done = engine->play(sampleBuffer, (uint_least32_t)(todo * n_channels)) / n_channels;
if(done < todo) { while(renderedTotal < frame) {
if(engine->error()) long todo = frame - renderedTotal;
return -1; if(todo > 1024)
todo = 1024;
int done = engine->play(sampleBuffer, (uint_least32_t)(todo * n_channels)) / n_channels;
renderedTotal = length; if(done < todo) {
break; if(engine->error())
return -1;
renderedTotal = length;
break;
}
renderedTotal += todo;
} }
renderedTotal += todo; renderedTotal *= 32;
engine->fastForward(100);
if(remain)
renderedTotal += engine->play(sampleBuffer, (uint_least32_t)(remain * n_channels)) / n_channels;
} catch (std::exception &e) {
ALog(@"Exception caught while brute force seeking SID file: %s", e.what());
return -1;
} }
renderedTotal *= 32;
engine->fastForward(100);
if(remain)
renderedTotal += engine->play(sampleBuffer, (uint_least32_t)(remain * n_channels)) / n_channels;
return renderedTotal; return renderedTotal;
} }
- (void)cleanUp { - (void)cleanUp {
if(builder) { try {
delete builder; if(builder) {
builder = NULL; delete builder;
} builder = NULL;
}
if(engine) { if(engine) {
delete engine; delete engine;
engine = NULL; engine = NULL;
} }
if(tune) { if(tune) {
delete tune; delete tune;
tune = NULL; tune = NULL;
}
} catch (std::exception &e) {
ALog(@"Exception caught while deleting SID player instances: %s", e.what());
} }
source = nil; source = nil;

View file

@ -30,34 +30,49 @@
id<CogSource> source = [audioSourceClass audioSourceForURL:url]; id<CogSource> source = [audioSourceClass audioSourceForURL:url];
if(![source open:url]) if(![source open:url])
return 0; return @{};
if(![source seekable]) if(![source seekable])
return 0; return @{};
[source seek:0 whence:SEEK_END]; [source seek:0 whence:SEEK_END];
long size = [source tell]; long size = [source tell];
[source seek:0 whence:SEEK_SET]; [source seek:0 whence:SEEK_SET];
if(!size)
return @{};
void *data = malloc(size); void *data = malloc(size);
if(!data)
return @{};
[source read:data amount:size]; [source read:data amount:size];
SidTune *tune = new SidTune((const uint_least8_t *)data, (uint_least32_t)size); NSString *title = @"";
NSString *titletag = @"title";
NSString *artist = @"";
try {
SidTune *tune = new SidTune((const uint_least8_t *)data, (uint_least32_t)size);
if(!tune->getStatus()) {
delete tune;
return 0;
}
const SidTuneInfo *info = tune->getInfo();
unsigned int count = info->numberOfInfoStrings();
title = count >= 1 ? [guess_encoding_of_string(info->infoString(0)) stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]] : @"";
titletag = info->songs() > 1 ? @"album" : @"title";
artist = count >= 2 ? [guess_encoding_of_string(info->infoString(1)) stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]] : @"";
if(!tune->getStatus()) {
delete tune; delete tune;
return 0; } catch (std::exception &e) {
ALog(@"Exception caught while reading SID tags: %s", e.what());
return @{};
} }
const SidTuneInfo *info = tune->getInfo();
unsigned int count = info->numberOfInfoStrings();
NSString *title = count >= 1 ? [guess_encoding_of_string(info->infoString(0)) stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]] : @"";
NSString *titletag = info->songs() > 1 ? @"album" : @"title";
NSString *artist = count >= 2 ? [guess_encoding_of_string(info->infoString(1)) stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]] : @"";
delete tune;
return @{titletag: title, @"artist": artist}; return @{titletag: title, @"artist": artist};
} }