Fixed shorten and cue sheet decoders so they conform with the updated protocols.

CQTexperiment
vspader 2008-03-30 15:43:28 +00:00
parent 7314c6cba1
commit 03ad906fb4
6 changed files with 53 additions and 81 deletions

View File

@ -18,11 +18,11 @@
id<CogDecoder> 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;

View File

@ -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;
}

View File

@ -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;

View File

@ -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 */,
);

View File

@ -21,7 +21,7 @@
int channels;
int bitsPerSample;
float frequency;
double length;
long totalFrames;
BOOL seekable;
}

View File

@ -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
}