diff --git a/Audio/Chain/BufferChain.h b/Audio/Chain/BufferChain.h index 4e3a359c2..e6cfdfd15 100644 --- a/Audio/Chain/BufferChain.h +++ b/Audio/Chain/BufferChain.h @@ -9,11 +9,12 @@ #import #import "InputNode.h" - +#import "ConverterNode.h" #import "AudioPlayer.h" @interface BufferChain : NSObject { InputNode *inputNode; + ConverterNode *converterNode; NSURL *streamURL; id userInfo; diff --git a/Audio/Chain/BufferChain.m b/Audio/Chain/BufferChain.m index c648f45c4..88a64eae2 100644 --- a/Audio/Chain/BufferChain.m +++ b/Audio/Chain/BufferChain.m @@ -23,6 +23,7 @@ userInfo = nil; inputNode = nil; + converterNode = nil; } return self; @@ -31,10 +32,12 @@ - (void)buildChain { [inputNode release]; + [converterNode release]; inputNode = [[InputNode alloc] initWithController:self previous:nil]; - - finalNode = inputNode; + converterNode = [[ConverterNode alloc] initWithController:self previous:inputNode]; + + finalNode = converterNode; } - (BOOL)open:(NSURL *)url withOutputFormat:(AudioStreamBasicDescription)outputFormat @@ -54,6 +57,9 @@ if (![inputNode openURL:url withSource:source outputFormat:outputFormat]) return NO; + + if (![converterNode setupWithInputFormat:propertiesToASBD([inputNode properties]) outputFormat:outputFormat]) + return NO; return YES; } @@ -61,6 +67,7 @@ - (void)launchThreads { [inputNode launchThread]; + [converterNode launchThread]; } - (void)setUserInfo:(id)i @@ -80,6 +87,7 @@ [userInfo release]; [inputNode release]; + [converterNode release]; [super dealloc]; } @@ -120,6 +128,7 @@ - (void)setShouldContinue:(BOOL)s { [inputNode setShouldContinue:s]; + [converterNode setShouldContinue:s]; } @end diff --git a/Audio/Chain/Converter.h b/Audio/Chain/Converter.h deleted file mode 100644 index c23053529..000000000 --- a/Audio/Chain/Converter.h +++ /dev/null @@ -1,44 +0,0 @@ -// -// ConverterNode.h -// Cog -// -// Created by Vincent Spader on 8/2/05. -// Copyright 2005 Vincent Spader. All rights reserved. -// - -#import - -#import -#import -#import -@interface Converter : NSObject -{ - AudioConverterRef converter; - - void *outputBuffer; - int outputBufferSize; - - //Temporary for callback use - void *inputBuffer; - int inputBufferSize; - BOOL needsReset; - //end - - int outputSize; - - AudioStreamBasicDescription inputFormat; - AudioStreamBasicDescription outputFormat; -} - -- (void *)outputBuffer; -- (int)outputBufferSize; - -- (void)setupWithInputFormat:(AudioStreamBasicDescription)inputFormat outputFormat:(AudioStreamBasicDescription)outputFormat; -- (void)cleanUp; - -- (void)reset; - -//Returns the amount actually read from input -- (int)convert:(void *)input amount:(int)inputSize; - -@end diff --git a/Audio/Chain/Converter.m b/Audio/Chain/Converter.m deleted file mode 100644 index 909032faa..000000000 --- a/Audio/Chain/Converter.m +++ /dev/null @@ -1,167 +0,0 @@ -// -// ConverterNode.m -// Cog -// -// Created by Vincent Spader on 8/2/05. -// Copyright 2005 Vincent Spader. All rights reserved. -// - -#import "Converter.h" -#import "Node.h" - -void PrintStreamDesc (AudioStreamBasicDescription *inDesc) -{ - if (!inDesc) { - printf ("Can't print a NULL desc!\n"); - return; - } - printf ("- - - - - - - - - - - - - - - - - - - -\n"); - printf (" Sample Rate:%f\n", inDesc->mSampleRate); - printf (" Format ID:%s\n", (char*)&inDesc->mFormatID); - printf (" Format Flags:%lX\n", inDesc->mFormatFlags); - printf (" Bytes per Packet:%ld\n", inDesc->mBytesPerPacket); - printf (" Frames per Packet:%ld\n", inDesc->mFramesPerPacket); - printf (" Bytes per Frame:%ld\n", inDesc->mBytesPerFrame); - printf (" Channels per Frame:%ld\n", inDesc->mChannelsPerFrame); - printf (" Bits per Channel:%ld\n", inDesc->mBitsPerChannel); - printf ("- - - - - - - - - - - - - - - - - - - -\n"); -} - -@implementation Converter - -//called from the complexfill when the audio is converted...good clean fun -static OSStatus ACInputProc(AudioConverterRef inAudioConverter, UInt32* ioNumberDataPackets, AudioBufferList* ioData, AudioStreamPacketDescription** outDataPacketDescription, void* inUserData) -{ - Converter *converter = (Converter *)inUserData; - OSStatus err = noErr; - - if (converter->inputBufferSize > 0) { - int amountConverted = *ioNumberDataPackets * converter->inputFormat.mBytesPerPacket; - if (amountConverted > converter->inputBufferSize) { - amountConverted = converter->inputBufferSize; - } - - ioData->mBuffers[0].mData = converter->inputBuffer; - ioData->mBuffers[0].mDataByteSize = amountConverted; - ioData->mBuffers[0].mNumberChannels = (converter->inputFormat.mChannelsPerFrame); - ioData->mNumberBuffers = 1; - - *ioNumberDataPackets = amountConverted / converter->inputFormat.mBytesPerPacket; - - converter->inputBufferSize -= amountConverted; - converter->inputBuffer = ((char *)converter->inputBuffer) + amountConverted; - } - else { - ioData->mBuffers[0].mData = NULL; - ioData->mBuffers[0].mDataByteSize = 0; - ioData->mNumberBuffers = 1; - *ioNumberDataPackets = 0; - - //Reset the converter's internal bufferrs. - converter->needsReset = YES; - } - - return err; -} - -- (void)reset -{ - AudioConverterReset(converter); -} - -- (int)convert:(void *)input amount:(int)inputSize -{ - AudioBufferList ioData; - UInt32 ioNumberFrames; - - if (inputSize <= 0) { - outputBufferSize = inputSize; - return inputSize; - } - - OSStatus err; - - needsReset = NO; - - ioNumberFrames = inputSize/inputFormat.mBytesPerFrame; - ioData.mBuffers[0].mData = outputBuffer; - ioData.mBuffers[0].mDataByteSize = outputSize; - ioData.mBuffers[0].mNumberChannels = outputFormat.mChannelsPerFrame; - ioData.mNumberBuffers = 1; - inputBuffer = input; - inputBufferSize = inputSize; - - err = AudioConverterFillComplexBuffer(converter, ACInputProc, self, &ioNumberFrames, &ioData, NULL); - if (err != noErr || needsReset) //It returns insz at EOS at times...so run it again to make sure all data is converted - { - [self reset]; - } - - outputBufferSize = ioData.mBuffers[0].mDataByteSize; - - return inputSize - inputBufferSize; -} - -- (void)setupWithInputFormat:(AudioStreamBasicDescription)inf outputFormat:(AudioStreamBasicDescription)outf -{ - //Make the converter - OSStatus stat = noErr; - - inputFormat = inf; - outputFormat = outf; - - stat = AudioConverterNew ( &inputFormat, &outputFormat, &converter); - if (stat != noErr) - { - NSLog(@"Error creating converter %i", stat); - } - - if (inputFormat.mChannelsPerFrame == 1) - { - SInt32 channelMap[2] = { 0, 0 }; - - stat = AudioConverterSetProperty(converter,kAudioConverterChannelMap,sizeof(channelMap),channelMap); - if (stat != noErr) - { - NSLog(@"Error mapping channels %i", stat); - } - } - - outputSize = CHUNK_SIZE; - UInt32 dataSize = sizeof(outputSize); - AudioConverterGetProperty(converter, - kAudioConverterPropertyCalculateOutputBufferSize, - &dataSize, - (void*)&outputSize); - - if (outputBuffer) - { - free(outputBuffer); - } - outputBuffer = malloc(outputSize); - - //PrintStreamDesc(&inf); - //PrintStreamDesc(&outf); -} - - -- (void *)outputBuffer -{ - return outputBuffer; -} - -- (int)outputBufferSize -{ - return outputBufferSize; -} - -- (void)cleanUp -{ - if (outputBuffer) { - free(outputBuffer); - outputBuffer = NULL; - } - AudioConverterDispose(converter); -} - -@end diff --git a/Audio/Chain/ConverterNode.h b/Audio/Chain/ConverterNode.h new file mode 100644 index 000000000..e537e3067 --- /dev/null +++ b/Audio/Chain/ConverterNode.h @@ -0,0 +1,31 @@ +// +// ConverterNode.h +// Cog +// +// Created by Zaphod Beeblebrox on 8/2/05. +// Copyright 2005 __MyCompanyName__. All rights reserved. +// + +#import + +#import +#import +#import + +#import "Node.h" + +@interface ConverterNode : Node { + AudioConverterRef converter; + void *callbackBuffer; + + AudioStreamBasicDescription inputFormat; + AudioStreamBasicDescription outputFormat; +} + +- (BOOL)setupWithInputFormat:(AudioStreamBasicDescription)inputFormat outputFormat:(AudioStreamBasicDescription)outputFormat; +- (void)cleanUp; + +- (void)process; +- (int)convert:(void *)dest amount:(int)amount; + +@end diff --git a/Audio/Chain/ConverterNode.m b/Audio/Chain/ConverterNode.m new file mode 100644 index 000000000..a84ea873f --- /dev/null +++ b/Audio/Chain/ConverterNode.m @@ -0,0 +1,431 @@ +// +// ConverterNode.m +// Cog +// +// Created by Vincent Spader on 8/2/05. +// Copyright 2005 Vincent Spader. All rights reserved. +// + +#import "Converter.h" +#import "Node.h" + +void PrintStreamDesc (AudioStreamBasicDescription *inDesc) +{ + if (!inDesc) { + printf ("Can't print a NULL desc!\n"); + return; + } + printf ("- - - - - - - - - - - - - - - - - - - -\n"); + printf (" Sample Rate:%f\n", inDesc->mSampleRate); + printf (" Format ID:%s\n", (char*)&inDesc->mFormatID); + printf (" Format Flags:%lX\n", inDesc->mFormatFlags); + printf (" Bytes per Packet:%ld\n", inDesc->mBytesPerPacket); + printf (" Frames per Packet:%ld\n", inDesc->mFramesPerPacket); + printf (" Bytes per Frame:%ld\n", inDesc->mBytesPerFrame); + printf (" Channels per Frame:%ld\n", inDesc->mChannelsPerFrame); + printf (" Bits per Channel:%ld\n", inDesc->mBitsPerChannel); + printf ("- - - - - - - - - - - - - - - - - - - -\n"); +} + +@implementation Converter + +//called from the complexfill when the audio is converted...good clean fun +static OSStatus ACInputProc(AudioConverterRef inAudioConverter, UInt32* ioNumberDataPackets, AudioBufferList* ioData, AudioStreamPacketDescription** outDataPacketDescription, void* inUserData) +{ + Converter *converter = (Converter *)inUserData; + OSStatus err = noErr; + + if (converter->inputBufferSize > 0) { + int amountConverted = *ioNumberDataPackets * converter->inputFormat.mBytesPerPacket; + if (amountConverted > converter->inputBufferSize) { + amountConverted = converter->inputBufferSize; + } + + ioData->mBuffers[0].mData = converter->inputBuffer; + ioData->mBuffers[0].mDataByteSize = amountConverted; + ioData->mBuffers[0].mNumberChannels = (converter->inputFormat.mChannelsPerFrame); + ioData->mNumberBuffers = 1; + + *ioNumberDataPackets = amountConverted / converter->inputFormat.mBytesPerPacket; + + converter->inputBufferSize -= amountConverted; + converter->inputBuffer = ((char *)converter->inputBuffer) + amountConverted; + } + else { + ioData->mBuffers[0].mData = NULL; + ioData->mBuffers[0].mDataByteSize = 0; + ioData->mNumberBuffers = 1; + *ioNumberDataPackets = 0; + + //Reset the converter's internal bufferrs. + converter->needsReset = YES; + } + + return err; +} + +- (void)reset +{ + AudioConverterReset(converter); +} + +- (int)convert:(void *)input amount:(int)inputSize +{ + AudioBufferList ioData; + UInt32 ioNumberFrames; + + if (inputSize <= 0) { + outputBufferSize = inputSize; + return inputSize; + } + + OSStatus err; + + needsReset = NO; + + ioNumberFrames = inputSize/inputFormat.mBytesPerFrame; + ioData.mBuffers[0].mData = outputBuffer; + ioData.mBuffers[0].mDataByteSize = outputSize; + ioData.mBuffers[0].mNumberChannels = outputFormat.mChannelsPerFrame; + ioData.mNumberBuffers = 1; + inputBuffer = input; + inputBufferSize = inputSize; + + err = AudioConverterFillComplexBuffer(converter, ACInputProc, self, &ioNumberFrames, &ioData, NULL); + if (err != noErr || needsReset) //It returns insz at EOS at times...so run it again to make sure all data is converted + { + [self reset]; + } + + outputBufferSize = ioData.mBuffers[0].mDataByteSize; + + return inputSize - inputBufferSize; +} + +- (void)setupWithInputFormat:(AudioStreamBasicDescription)inf outputFormat:(AudioStreamBasicDescription)outf +{ + //Make the converter + OSStatus stat = noErr; + + inputFormat = inf; + outputFormat = outf; + + stat = AudioConverterNew ( &inputFormat, &outputFormat, &converter); + if (stat != noErr) + { + NSLog(@"Error creating converter %i", stat); + } + + if (inputFormat.mChannelsPerFrame == 1) + { + SInt32 channelMap[2] = { 0, 0 }; + + stat = AudioConverterSetProperty(converter,kAudioConverterChannelMap,sizeof(channelMap),channelMap); + if (stat != noErr) + { + NSLog(@"Error mapping channels %i", stat); + } + } + + outputSize = CHUNK_SIZE; + UInt32 dataSize = sizeof(outputSize); + AudioConverterGetProperty(converter, + kAudioConverterPropertyCalculateOutputBufferSize, + &dataSize, + (void*)&outputSize); + + if (outputBuffer) + { + free(outputBuffer); + } + outputBuffer = malloc(outputSize);// +// ConverterNode.m +// Cog +// +// Created by Zaphod Beeblebrox on 8/2/05. +// Copyright 2005 __MyCompanyName__. All rights reserved. +// + +#import "ConverterNode.h" + +#define BUFFER_SIZE 512 * 1024 +#define CHUNK_SIZE 16 * 1024 + + +void PrintStreamDesc (AudioStreamBasicDescription *inDesc) +{ + if (!inDesc) { + printf ("Can't print a NULL desc!\n"); + return; + } + printf ("- - - - - - - - - - - - - - - - - - - -\n"); + printf (" Sample Rate:%f\n", inDesc->mSampleRate); + printf (" Format ID:%s\n", (char*)&inDesc->mFormatID); + printf (" Format Flags:%lX\n", inDesc->mFormatFlags); + printf (" Bytes per Packet:%ld\n", inDesc->mBytesPerPacket); + printf (" Frames per Packet:%ld\n", inDesc->mFramesPerPacket); + printf (" Bytes per Frame:%ld\n", inDesc->mBytesPerFrame); + printf (" Channels per Frame:%ld\n", inDesc->mChannelsPerFrame); + printf (" Bits per Channel:%ld\n", inDesc->mBitsPerChannel); + printf ("- - - - - - - - - - - - - - - - - - - -\n"); +} + +@implementation ConverterNode + +//called from the complexfill when the audio is converted...good clean fun +static OSStatus ACInputProc(AudioConverterRef inAudioConverter, UInt32* ioNumberDataPackets, AudioBufferList* ioData, AudioStreamPacketDescription** outDataPacketDescription, void* inUserData) +{ + ConverterNode *converter = (ConverterNode *)inUserData; + id previousNode = [converter previousNode]; + OSStatus err = noErr; + void *readPtr; + int amountToWrite; + int availInput; + int amountRead; + + if ([converter shouldContinue] == NO || [converter endOfStream] == YES) + { +// NSLog(@"END OF STREAM IN CONV"); + ioData->mBuffers[0].mDataByteSize = 0; + *ioNumberDataPackets = 0; + + return noErr; + } + + amountToWrite = (*ioNumberDataPackets)*(converter->inputFormat.mBytesPerPacket); + + if (converter->callbackBuffer != NULL) + free(converter->callbackBuffer); + converter->callbackBuffer = malloc(amountToWrite); + + amountRead = [converter readData:converter->callbackBuffer amount:amountToWrite]; +/* if ([converter endOfStream] == YES) + { + ioData->mBuffers[0].mDataByteSize = 0; + *ioNumberDataPackets = 0; + + return noErr; + } +*/ if (amountRead == 0) + { + ioData->mBuffers[0].mDataByteSize = 0; + *ioNumberDataPackets = 0; + + return 100; //Keep asking for data + } + + /* + availInput = [[previousNode buffer] lengthAvailableToReadReturningPointer:&readPtr]; + if (availInput == 0 ) + { +// NSLog(@"0 INPUT"); + ioData->mBuffers[0].mDataByteSize = 0; + *ioNumberDataPackets = 0; + + if ([previousNode endOfStream] == YES) + { + NSLog(@"END OF CONVERTER INPUT"); + [converter setEndOfStream:YES]; + [converter setShouldContinue:NO]; + + return noErr; + } + + return 100; //Keep asking for data + } + + if (amountToWrite > availInput) + amountToWrite = availInput; + + *ioNumberDataPackets = amountToWrite/(converter->inputFormat.mBytesPerPacket); + + if (converter->callbackBuffer != NULL) + free(converter->callbackBuffer); + converter->callbackBuffer = malloc(amountToWrite); + memcpy(converter->callbackBuffer, readPtr, amountToWrite); + + if (amountToWrite > 0) + { + [[previousNode buffer] didReadLength:amountToWrite]; + [[previousNode semaphore] signal]; + } +*/ +// NSLog(@"Amount read: %@ %i", converter, amountRead); + ioData->mBuffers[0].mData = converter->callbackBuffer; + ioData->mBuffers[0].mDataByteSize = amountRead; + ioData->mBuffers[0].mNumberChannels = (converter->inputFormat.mChannelsPerFrame); + ioData->mNumberBuffers = 1; + + return err; +} + +-(void)process +{ + char writeBuf[CHUNK_SIZE]; + int amountConverted; + + + while ([self shouldContinue] == YES) //Need to watch EOS somehow.... + { + amountConverted = [self convert:writeBuf amount:CHUNK_SIZE]; + +// NSLog(@"Amount converted %@: %i %i", self, amountConverted, [self endOfStream]); + if (amountConverted == 0 && [self endOfStream] == YES) + { +// NSLog(@"END OF STREAM FOR ZINE DINNER!!!!"); + return; + } + + [self writeData:writeBuf amount:amountConverted]; + } + +/* void *writePtr; + int availOutput; + int amountConverted; + + while ([self shouldContinue] == YES) + { + + availOutput = [buffer lengthAvailableToWriteReturningPointer:&writePtr]; + + while (availOutput == 0) + { + [semaphore wait]; + + if (shouldContinue == NO) + { + return; + } + + availOutput = [buffer lengthAvailableToWriteReturningPointer:&writePtr]; + } + + amountConverted = [self convert:writePtr amount:availOutput]; + + if (amountConverted > 0) + [buffer didWriteLength:amountConverted]; + } + */ +} + +- (int)convert:(void *)dest amount:(int)amount +{ + AudioBufferList ioData; + UInt32 ioNumberFrames; + OSStatus err; + + ioNumberFrames = amount/outputFormat.mBytesPerFrame; + ioData.mBuffers[0].mData = dest; + ioData.mBuffers[0].mDataByteSize = amount; + ioData.mBuffers[0].mNumberChannels = outputFormat.mChannelsPerFrame; + ioData.mNumberBuffers = 1; + + err = AudioConverterFillComplexBuffer(converter, ACInputProc, self, &ioNumberFrames, &ioData, NULL); + if (err == kAudioConverterErr_InvalidInputSize) //It returns insz at EOS at times...so run it again to make sure all data is converted + { + return [self convert:dest amount:amount]; + } +// if (err != noErr) +// NSLog(@"Converter error: %i", err); + + return ioData.mBuffers[0].mDataByteSize; +/* + void *readPtr; + int availInput; + + availInput = [[previousLink buffer] lengthAvailableToReadReturningPointer:&readPtr]; +// NSLog(@"AMOUNT: %i %i", amount, availInput); + + if (availInput == 0) + { + if ([previousLink endOfInput] == YES) + { + endOfInput = YES; + NSLog(@"EOI"); + shouldContinue = NO; + return 0; + } + } + + + if (availInput < amount) + amount = availInput; + + memcpy(dest, readPtr, amount); + + if (amount > 0) + { +// NSLog(@"READ: %i", amount); + [[previousLink buffer] didReadLength:amount]; + [[previousLink semaphore] signal]; + } + + return amount; + */ +} + +- (BOOL)setupWithInputFormat:(AudioStreamBasicDescription)inf outputFormat:(AudioStreamBasicDescription)outf +{ + //Make the converter + OSStatus stat = noErr; + + inputFormat = inf; + outputFormat = outf; + + stat = AudioConverterNew ( &inputFormat, &outputFormat, &converter); + if (stat != noErr) + { + DBLog(@"Error creating converter %i", stat); + } + + if (inputFormat.mChannelsPerFrame == 1) + { + SInt32 channelMap[2] = { 0, 0 }; + + stat = AudioConverterSetProperty(converter,kAudioConverterChannelMap,sizeof(channelMap),channelMap); + if (stat != noErr) + { + DBLog(@"Error mapping channels %i", stat); + } + } + + // DBLog(@"Created converter"); + PrintStreamDesc(&inf); + PrintStreamDesc(&outf); + + return YES; +} + +- (void)cleanUp +{ + AudioConverterDispose(converter); +} + +@end + + + //PrintStreamDesc(&inf); + //PrintStreamDesc(&outf); +} + + +- (void *)outputBuffer +{ + return outputBuffer; +} + +- (int)outputBufferSize +{ + return outputBufferSize; +} + +- (void)cleanUp +{ + if (outputBuffer) { + free(outputBuffer); + outputBuffer = NULL; + } + AudioConverterDispose(converter); +} + +@end diff --git a/Audio/Chain/InputNode.h b/Audio/Chain/InputNode.h index 883e82c8e..c4ca72c11 100644 --- a/Audio/Chain/InputNode.h +++ b/Audio/Chain/InputNode.h @@ -13,13 +13,11 @@ #import #import "AudioDecoder.h" -#import "Converter.h" #import "Node.h" #import "Plugin.h" @interface InputNode : Node { id decoder; - Converter *converter; AudioStreamBasicDescription outputFormat; diff --git a/Audio/Chain/InputNode.m b/Audio/Chain/InputNode.m index 76e275dfc..9946af3b8 100644 --- a/Audio/Chain/InputNode.m +++ b/Audio/Chain/InputNode.m @@ -20,10 +20,6 @@ decoder = [AudioDecoder audioDecoderForURL:url]; [decoder retain]; - converter = [[Converter alloc] init]; - if (converter == nil) - return NO; - [self registerObservers]; if (decoder == nil) @@ -61,8 +57,6 @@ { if ([keyPath isEqual:@"properties"]) { //Setup converter! - [converter cleanUp]; - [converter setupWithInputFormat:propertiesToASBD([decoder properties]) outputFormat:outputFormat]; //Inform something of properties change } else if ([keyPath isEqual:@"metadata"]) { @@ -72,47 +66,46 @@ - (void)process { - int amountRead = 0, amountConverted = 0, amountInBuffer = 0; + int amountRead = 0, amountInBuffer = 0; void *inputBuffer = malloc(CHUNK_SIZE); while ([self shouldContinue] == YES && [self endOfStream] == NO) { if (shouldSeek == YES) { + NSLog(@"SEEKING!"); [decoder seekToTime:seekTime]; + NSLog(@"Har"); shouldSeek = NO; - + NSLog(@"Seeked! Resetting Buffer"); + [self resetBuffer]; + + NSLog(@"Reset buffer!"); initialBufferFilled = NO; } if (amountInBuffer < CHUNK_SIZE) { amountRead = [decoder fillBuffer:((char *)inputBuffer) + amountInBuffer ofSize:CHUNK_SIZE - amountInBuffer]; amountInBuffer += amountRead; - } - amountConverted = [converter convert:inputBuffer amount:amountInBuffer]; //Convert fills in converter buffer, til the next call - if (amountInBuffer - amountConverted > 0) { - memmove(inputBuffer,((char *)inputBuffer) + amountConverted, amountInBuffer - amountConverted); - } - amountInBuffer -= amountConverted; - - if ([converter outputBufferSize] <= 0) - { - if (initialBufferFilled == NO) { - [controller initialBufferFilled]; + if (amountRead <= 0) + { + if (initialBufferFilled == NO) { + [controller initialBufferFilled]; + } + + endOfStream = YES; + [controller endOfInputReached]; + break; //eof } - - endOfStream = YES; - [controller endOfInputReached]; - break; //eof + + [self writeData:inputBuffer amount:amountInBuffer]; + amountInBuffer = 0; } - - [self writeData:[converter outputBuffer] amount:[converter outputBufferSize]]; } [decoder close]; - [converter cleanUp]; free(inputBuffer); } @@ -121,7 +114,7 @@ { seekTime = time; shouldSeek = YES; - [self resetBuffer]; + NSLog(@"Should seek!"); [semaphore signal]; } diff --git a/Audio/Chain/Node.h b/Audio/Chain/Node.h index 226430655..b9bdd35b1 100644 --- a/Audio/Chain/Node.h +++ b/Audio/Chain/Node.h @@ -22,6 +22,8 @@ id previousNode; id controller; + BOOL shouldReset; + BOOL shouldContinue; BOOL endOfStream; //All data is now in buffer BOOL initialBufferFilled; @@ -36,6 +38,9 @@ - (void)launchThread; +- (void)setShouldReset:(BOOL)s; +- (BOOL)shouldReset; + - (NSLock *)readLock; - (NSLock *)writeLock; @@ -49,6 +54,8 @@ - (Semaphore *)semaphore; +-(void)resetBuffer; + - (BOOL)endOfStream; - (void)setEndOfStream:(BOOL)e; diff --git a/Audio/Chain/Node.m b/Audio/Chain/Node.m index 7a1b84cbb..e3b82160d 100644 --- a/Audio/Chain/Node.m +++ b/Audio/Chain/Node.m @@ -41,15 +41,17 @@ while (shouldContinue == YES && amountLeft > 0) { availOutput = [buffer lengthAvailableToWriteReturningPointer:&writePtr]; - - if (availOutput == 0) - { - [writeLock unlock]; + if (availOutput == 0) { if (initialBufferFilled == NO) { - initialBufferFilled = YES;\ + initialBufferFilled = YES; if ([controller respondsToSelector:@selector(initialBufferFilled)]) [controller performSelector:@selector(initialBufferFilled)]; } + } + + if (availOutput == 0 || shouldReset) + { + [writeLock unlock]; [semaphore wait]; [writeLock lock]; } @@ -115,6 +117,19 @@ NSLog(@"BUFFER IN DANGER"); } */ + + if ([previousNode shouldReset] == YES) { + [writeLock lock]; + + [buffer empty]; + + shouldReset = YES; + [previousNode setShouldReset: NO]; + [writeLock unlock]; + + [[previousNode semaphore] signal]; + } + amountToCopy = availInput; if (amountToCopy > amount) { @@ -161,13 +176,12 @@ - (void)resetBuffer { - [readLock lock]; - [writeLock lock]; - - [buffer empty]; - - [writeLock unlock]; - [readLock unlock]; + shouldReset = YES; //Will reset on next write. + if (previousNode == nil) { + [readLock lock]; + [buffer empty]; + [readLock unlock]; + } } - (NSLock *)readLock @@ -195,4 +209,14 @@ endOfStream = e; } +- (void)setShouldReset:(BOOL)s +{ + shouldReset = s; +} +- (BOOL)shouldReset +{ + return shouldReset; +} + + @end diff --git a/Audio/Chain/OutputNode.m b/Audio/Chain/OutputNode.m index 42f2f3c57..98364afeb 100644 --- a/Audio/Chain/OutputNode.m +++ b/Audio/Chain/OutputNode.m @@ -24,7 +24,7 @@ - (void)seek:(double)time { - [output pause]; +// [output pause]; amountPlayed = time*format.mBytesPerFrame*(format.mSampleRate/1000.0); } diff --git a/Audio/CogAudio.xcodeproj/project.pbxproj b/Audio/CogAudio.xcodeproj/project.pbxproj index 388516537..5e590ce00 100644 --- a/Audio/CogAudio.xcodeproj/project.pbxproj +++ b/Audio/CogAudio.xcodeproj/project.pbxproj @@ -44,8 +44,8 @@ 17F94DD60B8D0F7000A34E87 /* PluginController.m in Sources */ = {isa = PBXBuildFile; fileRef = 17F94DD40B8D0F7000A34E87 /* PluginController.m */; }; 17F94DDD0B8D101100A34E87 /* Plugin.h in Headers */ = {isa = PBXBuildFile; fileRef = 17F94DDC0B8D101100A34E87 /* Plugin.h */; settings = {ATTRIBUTES = (Public, ); }; }; 8DC2EF570486A6940098B216 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7B1FEA5585E11CA2CBB /* Cocoa.framework */; }; - 8EC1225F0B993BD500C5B3AD /* Converter.h in Headers */ = {isa = PBXBuildFile; fileRef = 8EC1225D0B993BD500C5B3AD /* Converter.h */; }; - 8EC122600B993BD500C5B3AD /* Converter.m in Sources */ = {isa = PBXBuildFile; fileRef = 8EC1225E0B993BD500C5B3AD /* Converter.m */; }; + 8EC1225F0B993BD500C5B3AD /* ConverterNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 8EC1225D0B993BD500C5B3AD /* ConverterNode.h */; }; + 8EC122600B993BD500C5B3AD /* ConverterNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 8EC1225E0B993BD500C5B3AD /* ConverterNode.m */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -103,8 +103,8 @@ 32DBCF5E0370ADEE00C91783 /* CogAudio_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CogAudio_Prefix.pch; sourceTree = ""; }; 8DC2EF5A0486A6940098B216 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; 8DC2EF5B0486A6940098B216 /* CogAudio.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = CogAudio.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 8EC1225D0B993BD500C5B3AD /* Converter.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Converter.h; sourceTree = ""; }; - 8EC1225E0B993BD500C5B3AD /* Converter.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = Converter.m; sourceTree = ""; }; + 8EC1225D0B993BD500C5B3AD /* ConverterNode.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ConverterNode.h; sourceTree = ""; }; + 8EC1225E0B993BD500C5B3AD /* ConverterNode.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = ConverterNode.m; sourceTree = ""; }; D2F7E79907B2D74100F64583 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = /System/Library/Frameworks/CoreData.framework; sourceTree = ""; }; /* End PBXFileReference section */ @@ -213,8 +213,8 @@ children = ( 17D21C760B8BE4BA00D1EBDE /* BufferChain.h */, 17D21C770B8BE4BA00D1EBDE /* BufferChain.m */, - 8EC1225D0B993BD500C5B3AD /* Converter.h */, - 8EC1225E0B993BD500C5B3AD /* Converter.m */, + 8EC1225D0B993BD500C5B3AD /* ConverterNode.h */, + 8EC1225E0B993BD500C5B3AD /* ConverterNode.m */, 17D21C7A0B8BE4BA00D1EBDE /* InputNode.h */, 17D21C7B0B8BE4BA00D1EBDE /* InputNode.m */, 17D21C7C0B8BE4BA00D1EBDE /* Node.h */, @@ -304,7 +304,7 @@ 17C940230B900909008627D6 /* AudioMetadataReader.h in Headers */, 17B619300B909BC300BC003F /* AudioPropertiesReader.h in Headers */, 17ADB13C0B97926D00257CA2 /* AudioSource.h in Headers */, - 8EC1225F0B993BD500C5B3AD /* Converter.h in Headers */, + 8EC1225F0B993BD500C5B3AD /* ConverterNode.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -377,7 +377,7 @@ 17C940240B900909008627D6 /* AudioMetadataReader.m in Sources */, 17B619310B909BC300BC003F /* AudioPropertiesReader.m in Sources */, 17ADB13D0B97926D00257CA2 /* AudioSource.m in Sources */, - 8EC122600B993BD500C5B3AD /* Converter.m in Sources */, + 8EC122600B993BD500C5B3AD /* ConverterNode.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Cog.xcodeproj/project.pbxproj b/Cog.xcodeproj/project.pbxproj index 7cf0196dd..96fe6fd7c 100644 --- a/Cog.xcodeproj/project.pbxproj +++ b/Cog.xcodeproj/project.pbxproj @@ -1516,7 +1516,7 @@ ); PRODUCT_NAME = Cog; WRAPPER_EXTENSION = app; - ZERO_LINK = YES; + ZERO_LINK = NO; }; name = Debug; };