Cog/Audio/Chain/Node.m

202 lines
3.5 KiB
Mathematica
Raw Normal View History

2006-01-20 12:34:02 -03:00
//
// Node.m
2006-01-20 12:34:02 -03:00
// CogNew
//
// 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"
#import "Logging.h"
2021-01-26 23:12:07 -03:00
#import "BufferChain.h"
2006-01-20 12:34:02 -03:00
@implementation Node
- (id)initWithController:(id)c previous:(id)p
{
self = [super init];
if (self)
{
buffer = [[ChunkList alloc] initWithMaximumDuration:3.0];
semaphore = [[Semaphore alloc] init];
accessLock = [[NSRecursiveLock alloc] init];
2006-01-20 12:34:02 -03:00
initialBufferFilled = NO;
controller = c;
endOfStream = NO;
shouldContinue = YES;
nodeLossless = NO;
[self setPreviousNode:p];
2006-01-20 12:34:02 -03:00
}
return self;
}
- (AudioStreamBasicDescription)nodeFormat
2006-01-20 12:34:02 -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];
}
}
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
{
@autoreleasepool {
[self process];
}
2006-01-20 12:34:02 -03:00
}
- (AudioChunk *)readChunk:(size_t)maxFrames
2006-01-20 12:34:02 -03:00
{
[accessLock lock];
if ([[previousNode buffer] isEmpty] && [previousNode endOfStream] == YES)
{
endOfStream = YES;
[accessLock unlock];
return [[AudioChunk alloc] init];
}
if ([previousNode shouldReset] == YES) {
[buffer reset];
shouldReset = YES;
[previousNode setShouldReset: NO];
[[previousNode semaphore] signal];
}
AudioChunk * ret = [[previousNode buffer] removeSamples:maxFrames];
[accessLock unlock];
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];
}
- (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;
}
- (ChunkList *)buffer
2006-01-20 12:34:02 -03:00
{
return buffer;
}
2006-04-02 16:03:12 -04:00
- (void)resetBuffer
{
shouldReset = YES; //Will reset on next write.
if (previousNode == nil) {
[accessLock lock];
[buffer reset];
[accessLock unlock];
}
2006-04-02 16:03:12 -04:00
}
2006-01-20 12:34:02 -03:00
- (Semaphore *)semaphore
{
return semaphore;
}
- (BOOL)endOfStream
2006-01-20 12:34:02 -03:00
{
return endOfStream;
2006-01-20 12:34:02 -03:00
}
- (void)setEndOfStream:(BOOL)e
2006-01-20 12:34:02 -03:00
{
endOfStream = e;
2006-01-20 12:34:02 -03:00
}
- (void)setShouldReset:(BOOL)s
{
shouldReset = s;
}
- (BOOL)shouldReset
{
return shouldReset;
}
// Buffering nodes should implement this
- (double)secondsBuffered
{
return 0.0;
}
2006-01-20 12:34:02 -03:00
@end