Fixed shorten and cue sheet decoders so they conform with the updated protocols.
parent
7314c6cba1
commit
03ad906fb4
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */,
|
||||
);
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
int channels;
|
||||
int bitsPerSample;
|
||||
float frequency;
|
||||
double length;
|
||||
long totalFrames;
|
||||
BOOL seekable;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue