210 lines
4.0 KiB
Objective-C
210 lines
4.0 KiB
Objective-C
//
|
|
// 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;
|
|
started = NO;
|
|
|
|
formatSetup = NO;
|
|
formatChanged = NO;
|
|
|
|
output = [[OutputCoreAudio alloc] initWithController:self];
|
|
|
|
[output setup];
|
|
}
|
|
|
|
- (void)seek:(double)time
|
|
{
|
|
// [output pause];
|
|
[self resetBuffer];
|
|
|
|
amountPlayed = time;
|
|
}
|
|
|
|
- (void)process
|
|
{
|
|
paused = NO;
|
|
[output start];
|
|
}
|
|
|
|
- (void)pause
|
|
{
|
|
paused = YES;
|
|
[output pause];
|
|
}
|
|
|
|
- (void)resume
|
|
{
|
|
paused = NO;
|
|
[output resume];
|
|
}
|
|
|
|
- (void)incrementAmountPlayed:(long)count
|
|
{
|
|
amountPlayed += (double)count * sampleRatio;
|
|
}
|
|
|
|
- (void)resetAmountPlayed
|
|
{
|
|
amountPlayed = 0;
|
|
}
|
|
|
|
- (void)endOfInputPlayed
|
|
{
|
|
[controller endOfInputPlayed];
|
|
}
|
|
|
|
- (BOOL)chainQueueHasTracks
|
|
{
|
|
return [controller chainQueueHasTracks];
|
|
}
|
|
|
|
- (double)secondsBuffered
|
|
{
|
|
return (double)([buffer bufferedLength]) / (format.mSampleRate * format.mBytesPerPacket);
|
|
}
|
|
|
|
- (int)readData:(void *)ptr amount:(int)amount
|
|
{
|
|
@autoreleasepool {
|
|
int n;
|
|
[self setPreviousNode:[[controller bufferChain] finalNode]];
|
|
|
|
n = [super readData:ptr amount:amount];
|
|
|
|
/* 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 0
|
|
// We no longer need to do this, because outputchanged converter
|
|
// now uses the RefillNode to slap the previous samples into
|
|
// itself
|
|
if (oldSampleRatio)
|
|
amountPlayed += oldSampleRatio * [[converter buffer] bufferedLength];
|
|
#endif
|
|
AudioStreamBasicDescription inf = [bufferChain inputFormat];
|
|
|
|
format.mChannelsPerFrame = inf.mChannelsPerFrame;
|
|
format.mBytesPerFrame = ((format.mBitsPerChannel + 7) / 8) * format.mChannelsPerFrame;
|
|
format.mBytesPerPacket = format.mBytesPerFrame * format.mFramesPerPacket;
|
|
|
|
sampleRatio = 1.0 / (format.mSampleRate * format.mBytesPerPacket);
|
|
|
|
[converter setOutputFormat:format];
|
|
[converter inputFormatDidChange:[bufferChain inputFormat]];
|
|
}
|
|
}
|
|
}
|
|
|
|
- (void)close
|
|
{
|
|
[output stop];
|
|
output = nil;
|
|
}
|
|
|
|
- (void)setVolume:(double) v
|
|
{
|
|
[output setVolume:v];
|
|
}
|
|
|
|
- (void)setShouldContinue:(BOOL)s
|
|
{
|
|
[super setShouldContinue:s];
|
|
|
|
// if (s == NO)
|
|
// [output stop];
|
|
}
|
|
|
|
- (BOOL)isPaused
|
|
{
|
|
return paused;
|
|
}
|
|
|
|
- (void)beginEqualizer:(AudioUnit)eq
|
|
{
|
|
[controller beginEqualizer:eq];
|
|
}
|
|
|
|
- (void)refreshEqualizer:(AudioUnit)eq
|
|
{
|
|
[controller refreshEqualizer:eq];
|
|
}
|
|
|
|
- (void)endEqualizer:(AudioUnit)eq
|
|
{
|
|
[controller endEqualizer:eq];
|
|
}
|
|
|
|
- (void)sustainHDCD
|
|
{
|
|
[output sustainHDCD];
|
|
}
|
|
|
|
- (BOOL)formatChanged
|
|
{
|
|
[self setPreviousNode:[[controller bufferChain] finalNode]];
|
|
|
|
AudioStreamBasicDescription inf = [[self previousNode] nodeFormat];
|
|
|
|
if (!formatSetup || memcmp(&nodeFormat, &inf, sizeof(nodeFormat)) != 0) {
|
|
nodeFormat = inf;
|
|
formatSetup = YES;
|
|
formatChanged = YES;
|
|
}
|
|
|
|
BOOL copyFormatChanged = formatChanged;
|
|
formatChanged = NO;
|
|
return copyFormatChanged;
|
|
}
|
|
|
|
@end
|