2006-01-20 12:34:02 -03:00
|
|
|
//
|
2006-04-02 11:44:08 -04:00
|
|
|
// Node.m
|
2006-01-20 12:34:02 -03:00
|
|
|
// CogNew
|
|
|
|
//
|
2006-09-04 14:46:18 -04:00
|
|
|
// Created by Vincent Spader on 1/4/06.
|
|
|
|
// Copyright 2006 Vincent Spader. All rights reserved.
|
2006-01-20 12:34:02 -03:00
|
|
|
//
|
|
|
|
|
|
|
|
#import "Node.h"
|
|
|
|
|
2013-10-11 09:03:55 -03:00
|
|
|
#import "Logging.h"
|
2021-01-26 23:12:07 -03:00
|
|
|
#import "BufferChain.h"
|
2013-10-11 09:03:55 -03:00
|
|
|
|
2006-01-20 12:34:02 -03:00
|
|
|
@implementation Node
|
|
|
|
|
|
|
|
- (id)initWithController:(id)c previous:(id)p
|
|
|
|
{
|
|
|
|
self = [super init];
|
|
|
|
if (self)
|
|
|
|
{
|
2022-02-06 08:08:34 -03:00
|
|
|
buffer = [[ChunkList alloc] initWithMaximumDuration:3.0];
|
|
|
|
semaphore = [[Semaphore alloc] init];
|
|
|
|
|
|
|
|
accessLock = [[NSRecursiveLock alloc] init];
|
2006-01-20 12:34:02 -03:00
|
|
|
|
2007-03-18 20:19:47 -04:00
|
|
|
initialBufferFilled = NO;
|
|
|
|
|
2008-02-15 23:52:49 -03:00
|
|
|
controller = c;
|
2006-04-02 11:44:08 -04:00
|
|
|
endOfStream = NO;
|
|
|
|
shouldContinue = YES;
|
2022-02-06 08:08:34 -03:00
|
|
|
|
|
|
|
nodeLossless = NO;
|
2008-02-15 23:46:19 -03:00
|
|
|
|
|
|
|
[self setPreviousNode:p];
|
2006-01-20 12:34:02 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
2022-02-06 08:08:34 -03:00
|
|
|
- (AudioStreamBasicDescription)nodeFormat
|
2006-01-20 12:34:02 -03:00
|
|
|
{
|
2022-02-06 08:08:34 -03:00
|
|
|
return nodeFormat;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (BOOL)nodeLossless
|
|
|
|
{
|
|
|
|
return nodeLossless;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)writeData:(const void *)ptr amount:(size_t)amount
|
|
|
|
{
|
|
|
|
[accessLock lock];
|
|
|
|
|
|
|
|
AudioChunk * chunk = [[AudioChunk alloc] init];
|
|
|
|
[chunk setFormat:nodeFormat];
|
|
|
|
[chunk setLossless:nodeLossless];
|
|
|
|
[chunk assignSamples:ptr frameCount:amount / nodeFormat.mBytesPerPacket];
|
|
|
|
|
|
|
|
const double chunkDuration = [chunk duration];
|
|
|
|
double durationLeft = [buffer maxDuration] - [buffer listDuration];
|
|
|
|
|
|
|
|
while (shouldContinue == YES && chunkDuration > durationLeft)
|
|
|
|
{
|
|
|
|
if (durationLeft < chunkDuration) {
|
|
|
|
if (initialBufferFilled == NO) {
|
|
|
|
initialBufferFilled = YES;
|
|
|
|
if ([controller respondsToSelector:@selector(initialBufferFilled:)])
|
|
|
|
[controller performSelector:@selector(initialBufferFilled:) withObject:self];
|
2022-01-24 00:36:33 -03:00
|
|
|
}
|
2022-02-06 08:08:34 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
if (durationLeft < chunkDuration || shouldReset) {
|
|
|
|
[accessLock unlock];
|
|
|
|
[semaphore wait];
|
|
|
|
[accessLock lock];
|
|
|
|
}
|
|
|
|
|
|
|
|
durationLeft = [buffer maxDuration] - [buffer listDuration];
|
|
|
|
}
|
|
|
|
|
|
|
|
[buffer addChunk:chunk];
|
|
|
|
|
|
|
|
[accessLock unlock];
|
2006-01-20 12:34:02 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
//Should be overwriten by subclass.
|
|
|
|
- (void)process
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)threadEntry:(id)arg
|
|
|
|
{
|
2016-05-05 17:05:39 -03:00
|
|
|
@autoreleasepool {
|
|
|
|
[self process];
|
|
|
|
}
|
2006-01-20 12:34:02 -03:00
|
|
|
}
|
|
|
|
|
2022-02-06 08:08:34 -03:00
|
|
|
- (AudioChunk *)readChunk:(size_t)maxFrames
|
2006-01-20 12:34:02 -03:00
|
|
|
{
|
2022-02-06 08:08:34 -03:00
|
|
|
[accessLock lock];
|
2022-01-13 04:15:23 -03:00
|
|
|
|
|
|
|
if ([[previousNode buffer] isEmpty] && [previousNode endOfStream] == YES)
|
|
|
|
{
|
|
|
|
endOfStream = YES;
|
2022-02-06 08:08:34 -03:00
|
|
|
[accessLock unlock];
|
|
|
|
return [[AudioChunk alloc] init];
|
2022-01-13 04:15:23 -03:00
|
|
|
}
|
2022-02-06 08:08:34 -03:00
|
|
|
|
2022-01-24 00:36:33 -03:00
|
|
|
if ([previousNode shouldReset] == YES) {
|
2022-02-06 08:08:34 -03:00
|
|
|
[buffer reset];
|
2007-10-03 16:23:14 -04:00
|
|
|
|
|
|
|
shouldReset = YES;
|
|
|
|
[previousNode setShouldReset: NO];
|
2022-02-06 08:08:34 -03:00
|
|
|
|
|
|
|
[[previousNode semaphore] signal];
|
2007-10-03 16:23:14 -04:00
|
|
|
}
|
|
|
|
|
2022-02-06 08:08:34 -03:00
|
|
|
AudioChunk * ret = [[previousNode buffer] removeSamples:maxFrames];
|
|
|
|
|
|
|
|
[accessLock unlock];
|
2022-01-24 00:36:33 -03:00
|
|
|
|
2022-02-06 08:08:34 -03:00
|
|
|
if ([ret frameCount])
|
|
|
|
{
|
|
|
|
[[previousNode semaphore] signal];
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
2006-01-20 12:34:02 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void)launchThread
|
|
|
|
{
|
|
|
|
[NSThread detachNewThreadSelector:@selector(threadEntry:) toTarget:self withObject:nil];
|
|
|
|
}
|
|
|
|
|
2008-02-15 23:46:19 -03:00
|
|
|
- (void)setPreviousNode:(id)p
|
|
|
|
{
|
|
|
|
previousNode = p;
|
|
|
|
}
|
|
|
|
|
2006-01-20 12:34:02 -03:00
|
|
|
- (id)previousNode
|
|
|
|
{
|
|
|
|
return previousNode;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (BOOL)shouldContinue
|
|
|
|
{
|
|
|
|
return shouldContinue;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)setShouldContinue:(BOOL)s
|
|
|
|
{
|
|
|
|
shouldContinue = s;
|
|
|
|
}
|
|
|
|
|
2022-02-06 08:08:34 -03:00
|
|
|
- (ChunkList *)buffer
|
2006-01-20 12:34:02 -03:00
|
|
|
{
|
|
|
|
return buffer;
|
|
|
|
}
|
|
|
|
|
2006-04-02 16:03:12 -04:00
|
|
|
- (void)resetBuffer
|
|
|
|
{
|
2007-10-03 16:23:14 -04:00
|
|
|
shouldReset = YES; //Will reset on next write.
|
|
|
|
if (previousNode == nil) {
|
2022-02-06 08:08:34 -03:00
|
|
|
[accessLock lock];
|
|
|
|
[buffer reset];
|
|
|
|
[accessLock unlock];
|
2007-10-03 16:23:14 -04:00
|
|
|
}
|
2006-04-02 16:03:12 -04:00
|
|
|
}
|
|
|
|
|
2006-01-20 12:34:02 -03:00
|
|
|
- (Semaphore *)semaphore
|
|
|
|
{
|
|
|
|
return semaphore;
|
|
|
|
}
|
|
|
|
|
2006-04-02 11:44:08 -04:00
|
|
|
- (BOOL)endOfStream
|
2006-01-20 12:34:02 -03:00
|
|
|
{
|
2006-04-02 11:44:08 -04:00
|
|
|
return endOfStream;
|
2006-01-20 12:34:02 -03:00
|
|
|
}
|
|
|
|
|
2006-04-02 11:44:08 -04:00
|
|
|
- (void)setEndOfStream:(BOOL)e
|
2006-01-20 12:34:02 -03:00
|
|
|
{
|
2006-04-02 11:44:08 -04:00
|
|
|
endOfStream = e;
|
2006-01-20 12:34:02 -03:00
|
|
|
}
|
|
|
|
|
2007-10-03 16:23:14 -04:00
|
|
|
- (void)setShouldReset:(BOOL)s
|
|
|
|
{
|
|
|
|
shouldReset = s;
|
|
|
|
}
|
|
|
|
- (BOOL)shouldReset
|
|
|
|
{
|
|
|
|
return shouldReset;
|
|
|
|
}
|
|
|
|
|
2022-01-14 04:05:32 -03:00
|
|
|
// Buffering nodes should implement this
|
|
|
|
- (double)secondsBuffered
|
|
|
|
{
|
|
|
|
return 0.0;
|
|
|
|
}
|
|
|
|
|
2007-10-03 16:23:14 -04:00
|
|
|
|
2006-01-20 12:34:02 -03:00
|
|
|
@end
|