From 03ad906fb4ef5b378ff0207df624e5de905f2320 Mon Sep 17 00:00:00 2001 From: vspader Date: Sun, 30 Mar 2008 15:43:28 +0000 Subject: [PATCH] Fixed shorten and cue sheet decoders so they conform with the updated protocols. --- Plugins/CueSheet/CueSheetDecoder.h | 6 +- Plugins/CueSheet/CueSheetDecoder.m | 67 ++++++++----------- Plugins/CueSheet/CueSheetTrack.h | 2 +- .../Shorten/Shorten.xcodeproj/project.pbxproj | 2 + Plugins/Shorten/ShortenDecoder.h | 2 +- Plugins/Shorten/ShortenDecoder.mm | 55 +++++---------- 6 files changed, 53 insertions(+), 81 deletions(-) diff --git a/Plugins/CueSheet/CueSheetDecoder.h b/Plugins/CueSheet/CueSheetDecoder.h index 3bdd5c0cb..00b1c7702 100644 --- a/Plugins/CueSheet/CueSheetDecoder.h +++ b/Plugins/CueSheet/CueSheetDecoder.h @@ -18,11 +18,11 @@ id decoder; int bytesPerFrame; //Number of bytes per frame, ie channels * (bitsPerSample/8) - int bytesPerSecond; //Number of bytes per second, ie bytesPerFrame * sampleRate - int bytePosition; //Current position in bytes. + long framePosition; //Current position in frames. - double trackEnd; //Seconds until end of track. + long trackStart; //Starting frame of track. + long trackEnd; //Frames until end of track. CueSheet *cuesheet; CueSheetTrack *track; diff --git a/Plugins/CueSheet/CueSheetDecoder.m b/Plugins/CueSheet/CueSheetDecoder.m index 8cf75ac1a..6d281484d 100644 --- a/Plugins/CueSheet/CueSheetDecoder.m +++ b/Plugins/CueSheet/CueSheetDecoder.m @@ -29,7 +29,7 @@ NSMutableDictionary *properties = [[decoder properties] mutableCopy]; //Need to alter length - [properties setObject:[NSNumber numberWithDouble:((trackEnd - [track time]) * 1000)] forKey:@"totalFrames"]; + [properties setObject:[NSNumber numberWithLong:(trackEnd - trackStart)] forKey:@"totalFrames"]; return [properties autorelease]; } @@ -82,18 +82,19 @@ float sampleRate = [[properties objectForKey:@"sampleRate"] floatValue]; bytesPerFrame = (bitsPerSample/8) * channels; - bytesPerSecond = (int)(bytesPerFrame * sampleRate); + + trackStart = [track time] * sampleRate; if (nextTrack && [[[nextTrack url] absoluteString] isEqualToString:[[track url] absoluteString]]) { - trackEnd = [nextTrack time]; + trackEnd = [nextTrack time] * sampleRate; } else { - trackEnd = [[properties objectForKey:@"length"] doubleValue]/1000.0; + trackEnd = [[properties objectForKey:@"totalFrames"] doubleValue]; } - [self seekToTime: 0.0]; + [self seek: 0]; - //Note: Should register for observations of the decoder, but laziness consumes all. + //Note: Should register for observations of the decoder [self willChangeValueForKey:@"properties"]; [self didChangeValueForKey:@"properties"]; @@ -127,7 +128,8 @@ - (BOOL)setTrack:(NSURL *)url { - if ([[url fragment] intValue] == [[track track] intValue] + 1) { + //Same file, just next track...this may be unnecessary since frame-based decoding is done now... + if ([[[track url] path] isEqualToString:[url path]] && [[[track url] host] isEqualToString:[url host]] && [[url fragment] intValue] == [[track track] intValue] + 1) { NSArray *tracks = [cuesheet tracks]; int i; @@ -137,16 +139,20 @@ track = [tracks objectAtIndex:i]; [track retain]; + float sampleRate = [[[decoder properties] objectForKey:@"sampleRate"] floatValue]; + + trackStart = [track time] * sampleRate; + CueSheetTrack *nextTrack = nil; if (i + 1 < [tracks count]) { nextTrack = [tracks objectAtIndex:i + 1]; } if (nextTrack && [[[nextTrack url] absoluteString] isEqualToString:[[track url] absoluteString]]) { - trackEnd = [nextTrack time]; + trackEnd = [nextTrack time] * sampleRate; } else { - trackEnd = [[[decoder properties] objectForKey:@"length"] doubleValue]/1000.0; + trackEnd = [[[decoder properties] objectForKey:@"totalFrames"] longValue]; } NSLog(@"CHANGING TRACK!"); @@ -158,50 +164,35 @@ return NO; } -- (double)seekToTime:(double)time //milliseconds +- (long)seek:(long)frame { - double trackStartMs = [track time] * 1000.0; - double trackEndMs = trackEnd * 1000.0; - - if (time > trackEndMs - trackStartMs) { + if (frame > trackEnd - trackStart) { //need a better way of returning fail. - return -1.0; + return -1; } - time += trackStartMs; + frame += trackStart; - bytePosition = (time/1000.0) * bytesPerSecond; - - NSLog(@"Before: %li", bytePosition); - bytePosition -= bytePosition % bytesPerFrame; - NSLog(@"After: %li", bytePosition); + framePosition = [decoder seek:frame]; - return [decoder seekToTime:time]; + return framePosition; } -- (int)fillBuffer:(void *)buf ofSize:(UInt32)size +- (int)readAudio:(void *)buf frames:(UInt32)frames { - long trackByteEnd = trackEnd * bytesPerSecond; - trackByteEnd -= trackByteEnd % (bytesPerFrame); - -// NSLog(@"Position: %i/%i", bytePosition, trackByteEnd); -// NSLog(@"Requested: %i", size); - if (bytePosition + size > trackByteEnd) { - size = trackByteEnd - bytePosition; + if (framePosition + frames > trackEnd) { + frames = trackEnd - framePosition; } -// NSLog(@"Revised size: %i", size); - - if (!size) { - NSLog(@"Returning 0"); + if (!frames) + { + NSLog(@"Returning 0"); return 0; } - int n = [decoder fillBuffer:buf ofSize:size]; + int n = [decoder readAudio:buf frames:frames]; -// NSLog(@"Received: %i", n); - - bytePosition += n; + framePosition += n; return n; } diff --git a/Plugins/CueSheet/CueSheetTrack.h b/Plugins/CueSheet/CueSheetTrack.h index cedc0e8f3..11106c987 100644 --- a/Plugins/CueSheet/CueSheetTrack.h +++ b/Plugins/CueSheet/CueSheetTrack.h @@ -19,7 +19,7 @@ NSString *genre; NSString *year; - double time; + double time; //Starting time for the track } + (id)trackWithURL:(NSURL *)u track:(NSString *)t time:(double)s artist:(NSString *)a album:(NSString *)b title:(NSString *)l genre:(NSString *)g year:(NSString *)y; diff --git a/Plugins/Shorten/Shorten.xcodeproj/project.pbxproj b/Plugins/Shorten/Shorten.xcodeproj/project.pbxproj index e9201d211..1e44ca0fa 100644 --- a/Plugins/Shorten/Shorten.xcodeproj/project.pbxproj +++ b/Plugins/Shorten/Shorten.xcodeproj/project.pbxproj @@ -183,6 +183,7 @@ 089C1669FE841209C02AAC07 /* Project object */ = { isa = PBXProject; buildConfigurationList = 1DEB913E08733D840010E9CD /* Build configuration list for PBXProject "Shorten" */; + compatibilityVersion = "Xcode 2.4"; hasScannedForEncodings = 1; mainGroup = 089C166AFE841209C02AAC07 /* Shorten */; projectDirPath = ""; @@ -192,6 +193,7 @@ ProjectRef = 17F563DD0C3BDBF10019975C /* Shorten.xcodeproj */; }, ); + projectRoot = ""; targets = ( 8D5B49AC048680CD000E48DA /* Shorten Plugin */, ); diff --git a/Plugins/Shorten/ShortenDecoder.h b/Plugins/Shorten/ShortenDecoder.h index db7083e49..f06453fa2 100644 --- a/Plugins/Shorten/ShortenDecoder.h +++ b/Plugins/Shorten/ShortenDecoder.h @@ -21,7 +21,7 @@ int channels; int bitsPerSample; float frequency; - double length; + long totalFrames; BOOL seekable; } diff --git a/Plugins/Shorten/ShortenDecoder.mm b/Plugins/Shorten/ShortenDecoder.mm index 313de0504..213bf4679 100644 --- a/Plugins/Shorten/ShortenDecoder.mm +++ b/Plugins/Shorten/ShortenDecoder.mm @@ -34,7 +34,7 @@ seekable = seekTable == true ? YES : NO; - length = decoder->shn_get_song_length(); + totalFrames = (decoder->shn_get_song_length() * frequency)/1000.0; decoder->go(); @@ -44,49 +44,28 @@ return YES; } -- (int)fillBuffer:(void *)buf ofSize:(UInt32)size +- (int)readAudio:(void *)buf frames:(UInt32)frames { - long totalRead, amountRead, amountToRead; - - totalRead = 0; - - //For some reason the 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. -// while (totalRead < size) { - amountToRead = size - totalRead; - if (amountToRead > bufferSize) { - amountToRead = bufferSize; - } - - do - { - amountRead = decoder->read(buf, amountToRead); - } while(amountRead == -1 && totalRead == 0); + int bytesPerFrame = channels * (bitsPerSample/8); + int 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); -// if (amountRead <= 0) { -// return totalRead; -// } - totalRead += amountRead; -// buf = (void *)((char *)buf + amountRead); -// } - - return totalRead; + return amountRead/bytesPerFrame; } -- (double)seekToTime:(double)milliseconds +- (long)seek:(long)sample { - unsigned int sec; - - /*if (!shn_seekable(handle)) - return -1.0;*/ - - sec = (int)(milliseconds/1000.0); - - //shn_seek(handle, sec); - + unsigned int sec = sample/frequency; + decoder->seek(sec); - return (sec * 1000.0); + return sample; } - (void)close @@ -108,7 +87,7 @@ [NSNumber numberWithInt:channels],@"channels", [NSNumber numberWithInt:bitsPerSample],@"bitsPerSample", [NSNumber numberWithFloat:frequency],@"sampleRate", - [NSNumber numberWithDouble:length],@"length", + [NSNumber numberWithDouble:totalFrames],@"totalFrames", [NSNumber numberWithBool:seekable ],@"seekable", @"little",@"endian", nil]; @@ -121,7 +100,7 @@ + (NSArray *)mimeTypes { - return [NSArray arrayWithObjects:@"application/x-shorten", nil]; //This is basically useless + return [NSArray arrayWithObjects:@"application/x-shorten", nil]; //This is basically useless, since we cant stream shorten yet }