cog/Audio/Chain/OutputNode.m

202 lines
3.9 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 "AudioPlayer.h"
#import "BufferChain.h"
#import "OutputAVFoundation.h"
#import "Logging.h"
@implementation OutputNode
- (void)setup {
amountPlayed = 0.0;
amountPlayedInterval = 0.0;
paused = YES;
started = NO;
intervalReported = NO;
output = [[OutputAVFoundation 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:(double)seconds {
amountPlayed += seconds;
amountPlayedInterval += seconds;
if(!intervalReported && amountPlayedInterval >= 60.0) {
intervalReported = YES;
[controller reportPlayCount];
}
}
- (void)resetAmountPlayed {
amountPlayed = 0;
}
- (void)resetAmountPlayedInterval {
amountPlayedInterval = 0;
intervalReported = NO;
}
- (BOOL)selectNextBuffer {
return [controller selectNextBuffer];
}
- (void)endOfInputPlayed {
if(!intervalReported) {
intervalReported = YES;
[controller reportPlayCount];
}
[controller endOfInputPlayed];
[self resetAmountPlayedInterval];
}
- (BOOL)chainQueueHasTracks {
return [controller chainQueueHasTracks];
}
- (double)secondsBuffered {
return [buffer listDuration];
}
- (AudioChunk *)readChunk:(size_t)amount {
@autoreleasepool {
[self setPreviousNode:[[controller bufferChain] finalNode]];
AudioChunk *ret = [super readChunk:amount];
/* if (n == 0) {
DLog(@"Output Buffer dry!");
}
*/
return ret;
}
}
- (BOOL)peekFormat:(nonnull AudioStreamBasicDescription *)format channelConfig:(nonnull uint32_t *)config {
@autoreleasepool {
[self setPreviousNode:[[controller bufferChain] finalNode]];
return [super peekFormat:format channelConfig:config];
}
}
- (double)amountPlayed {
return amountPlayed;
}
- (double)amountPlayedInterval {
return amountPlayedInterval;
}
- (AudioStreamBasicDescription)format {
return format;
}
- (uint32_t)config {
return config;
}
- (void)setFormat:(AudioStreamBasicDescription *)f channelConfig:(uint32_t)channelConfig {
format = *f;
config = channelConfig;
// Calculate a ratio and add to double(seconds) instead, as format may change
// double oldSampleRatio = sampleRatio;
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
amountPlayed += [[converter buffer] listDuration];
AudioStreamBasicDescription inf = [bufferChain inputFormat];
uint32_t config = [bufferChain inputConfig];
format.mChannelsPerFrame = inf.mChannelsPerFrame;
format.mBytesPerFrame = ((inf.mBitsPerChannel + 7) / 8) * format.mChannelsPerFrame;
format.mBytesPerPacket = format.mBytesPerFrame * format.mFramesPerPacket;
channelConfig = config;
[converter inputFormatDidChange:[bufferChain inputFormat] inputConfig:[bufferChain inputConfig]];
}
}
}
- (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];
}
- (void)restartPlaybackAtCurrentPosition {
[controller restartPlaybackAtCurrentPosition];
}
- (double)latency {
return [output latency];
}
@end