// // OutputNode.m // Cog // // Created by Vincent Spader on 8/2/05. // Copyright 2005 Vincent Spader. All rights reserved. // #import "OutputNode.h" #import "OutputCoreAudio.h" #import "AudioPlayer.h" #import "BufferChain.h" #import "Logging.h" @implementation OutputNode - (void)setup { amountPlayed = 0.0; sampleRatio = 0.0; paused = YES; output = [[OutputCoreAudio alloc] initWithController:self]; [output setup]; } - (void)seek:(double)time { // [output pause]; amountPlayed = time; } - (void)process { paused = NO; [output start]; } - (void)pause { paused = YES; [output pause]; } - (void)resume { paused = NO; [output resume]; } - (int)readData:(void *)ptr amount:(int)amount { @autoreleasepool { int n; [self setPreviousNode:[[controller bufferChain] finalNode]]; n = [super readData:ptr amount:amount]; amountPlayed += (double)n * sampleRatio; if (endOfStream == YES && !n) { amountPlayed = 0.0; [controller endOfInputPlayed]; //Updates shouldContinue appropriately? } /* if (n == 0) { DLog(@"Output Buffer dry!"); } */ return n; } } - (double)amountPlayed { return amountPlayed; } - (AudioStreamBasicDescription) format { return format; } - (void)setFormat:(AudioStreamBasicDescription *)f { format = *f; // Calculate a ratio and add to double(seconds) instead, as format may change double oldSampleRatio = sampleRatio; sampleRatio = 1.0 / (format.mSampleRate * format.mBytesPerPacket); BufferChain *bufferChain = [controller bufferChain]; if (bufferChain) { ConverterNode *converter = [bufferChain converter]; if (converter) { // This clears the resampler buffer, but not the input buffer // We also have to jump the play position ahead accounting for // the data we are flushing if (oldSampleRatio) amountPlayed += oldSampleRatio * [[converter buffer] bufferedLength]; [converter setOutputFormat:format]; [converter inputFormatDidChange:[bufferChain inputFormat]]; } } } - (void)close { [output stop]; } - (void)setVolume:(double) v { [output setVolume:v]; } - (void)setShouldContinue:(BOOL)s { [super setShouldContinue:s]; // if (s == NO) // [output stop]; } - (BOOL)isPaused { return paused; } @end