// // ShnFile.mm // Cog // // Created by Vincent Spader on 6/6/05. // Copyright 2005 Vincent Spader All rights reserved. // #import "ShortenDecoder.h" @implementation ShortenDecoder - (BOOL)open:(id)source { NSURL *url = [source url]; if(![[url scheme] isEqualToString:@"file"]) return NO; decoder = new shn_reader; if(!decoder) { return NO; } decoder->open([[url path] UTF8String], true); bufferSize = decoder->shn_get_buffer_block_size(NUM_DEFAULT_BUFFER_BLOCKS); bool seekTable; decoder->file_info(NULL, &channels, &frequency, NULL, &bitsPerSample, &seekTable); seekable = seekTable == true ? YES : NO; totalFrames = (decoder->shn_get_song_length() * frequency) / 1000.0; decoder->go(); [self willChangeValueForKey:@"properties"]; [self didChangeValueForKey:@"properties"]; return YES; } - (int)readAudio:(void *)buf frames:(UInt32)frames { long bytesPerFrame = channels * (bitsPerSample / 8); long amountRead; // For some reason a busy loop is causing pops when output is set to 48000. Probably CPU starvation, since the SHN decoder seems to use a multithreaded nonblocking approach. do { amountRead = decoder->read(buf, frames * bytesPerFrame); } while(amountRead == -1); return (int)(amountRead / bytesPerFrame); } - (long)seek:(long)sample { unsigned int sec = sample / frequency; decoder->seek(sec); return sample; } - (void)close { if(decoder) { decoder->exit(); delete decoder; decoder = NULL; } /*if (shn_cleanup_decoder(handle)) shn_unload(handle);*/ } - (void)dealloc { [self close]; } - (NSDictionary *)properties { return @{@"channels": [NSNumber numberWithInt:channels], @"bitsPerSample": [NSNumber numberWithInt:bitsPerSample], @"sampleRate": [NSNumber numberWithFloat:frequency], @"totalFrames": [NSNumber numberWithDouble:totalFrames], @"seekable": [NSNumber numberWithBool:seekable], @"codec": @"Shorten", @"endian": @"little", @"encoding": @"lossless"}; } + (NSArray *)fileTypes { return @[@"shn"]; } + (NSArray *)mimeTypes { return @[@"application/x-shorten"]; // This is basically useless, since we cant stream shorten yet } + (float)priority { return 1.0; } + (NSArray *)fileTypeAssociations { return @[ @[@"Shorten File", @"shn.icns", @"shn"] ]; } @end