2022-02-06 11:08:34 +00:00
|
|
|
//
|
|
|
|
// ChunkList.m
|
|
|
|
// CogAudio Framework
|
|
|
|
//
|
|
|
|
// Created by Christopher Snowhill on 2/5/22.
|
|
|
|
//
|
|
|
|
|
|
|
|
#import "ChunkList.h"
|
|
|
|
|
|
|
|
@implementation ChunkList
|
|
|
|
|
|
|
|
@synthesize listDuration;
|
|
|
|
@synthesize maxDuration;
|
|
|
|
|
2022-02-07 05:49:27 +00:00
|
|
|
- (id)initWithMaximumDuration:(double)duration {
|
|
|
|
self = [super init];
|
|
|
|
|
|
|
|
if(self) {
|
|
|
|
chunkList = [[NSMutableArray alloc] init];
|
|
|
|
listDuration = 0.0;
|
|
|
|
maxDuration = duration;
|
|
|
|
|
|
|
|
inAdder = NO;
|
|
|
|
inRemover = NO;
|
2022-02-08 03:18:45 +00:00
|
|
|
inPeeker = NO;
|
2022-02-07 05:49:27 +00:00
|
|
|
stopping = NO;
|
|
|
|
}
|
|
|
|
|
|
|
|
return self;
|
2022-02-06 11:08:34 +00:00
|
|
|
}
|
|
|
|
|
2022-02-07 05:49:27 +00:00
|
|
|
- (void)dealloc {
|
|
|
|
stopping = YES;
|
2022-02-08 03:18:45 +00:00
|
|
|
while(inAdder || inRemover || inPeeker) {
|
2022-02-07 05:49:27 +00:00
|
|
|
usleep(500);
|
|
|
|
}
|
2022-02-06 11:08:34 +00:00
|
|
|
}
|
|
|
|
|
2022-02-07 05:49:27 +00:00
|
|
|
- (void)reset {
|
|
|
|
@synchronized(chunkList) {
|
|
|
|
[chunkList removeAllObjects];
|
|
|
|
listDuration = 0.0;
|
|
|
|
}
|
2022-02-06 11:08:34 +00:00
|
|
|
}
|
|
|
|
|
2022-02-07 05:49:27 +00:00
|
|
|
- (BOOL)isEmpty {
|
|
|
|
@synchronized(chunkList) {
|
|
|
|
return [chunkList count] == 0;
|
|
|
|
}
|
2022-02-06 11:08:34 +00:00
|
|
|
}
|
|
|
|
|
2022-02-07 05:49:27 +00:00
|
|
|
- (BOOL)isFull {
|
2022-02-08 06:02:17 +00:00
|
|
|
return (maxDuration - listDuration) < 0.05;
|
2022-02-06 11:08:34 +00:00
|
|
|
}
|
|
|
|
|
2022-02-07 05:49:27 +00:00
|
|
|
- (void)addChunk:(AudioChunk *)chunk {
|
|
|
|
if(stopping) return;
|
|
|
|
|
|
|
|
inAdder = YES;
|
|
|
|
|
|
|
|
const double chunkDuration = [chunk duration];
|
|
|
|
|
|
|
|
@synchronized(chunkList) {
|
|
|
|
[chunkList addObject:chunk];
|
|
|
|
listDuration += chunkDuration;
|
|
|
|
}
|
|
|
|
|
|
|
|
inAdder = NO;
|
2022-02-06 11:08:34 +00:00
|
|
|
}
|
|
|
|
|
2022-02-07 05:49:27 +00:00
|
|
|
- (AudioChunk *)removeSamples:(size_t)maxFrameCount {
|
|
|
|
if(stopping) {
|
|
|
|
return [[AudioChunk alloc] init];
|
|
|
|
}
|
|
|
|
|
|
|
|
@synchronized(chunkList) {
|
|
|
|
inRemover = YES;
|
2022-02-07 23:31:57 +00:00
|
|
|
if(![chunkList count]) {
|
|
|
|
inRemover = NO;
|
2022-02-07 05:49:27 +00:00
|
|
|
return [[AudioChunk alloc] init];
|
2022-02-07 23:31:57 +00:00
|
|
|
}
|
2022-02-07 05:49:27 +00:00
|
|
|
AudioChunk *chunk = [chunkList objectAtIndex:0];
|
|
|
|
if([chunk frameCount] <= maxFrameCount) {
|
|
|
|
[chunkList removeObjectAtIndex:0];
|
|
|
|
listDuration -= [chunk duration];
|
|
|
|
inRemover = NO;
|
|
|
|
return chunk;
|
|
|
|
}
|
|
|
|
NSData *removedData = [chunk removeSamples:maxFrameCount];
|
|
|
|
AudioChunk *ret = [[AudioChunk alloc] init];
|
|
|
|
[ret setFormat:[chunk format]];
|
2022-02-07 08:56:05 +00:00
|
|
|
[ret setChannelConfig:[chunk channelConfig]];
|
2022-02-07 05:49:27 +00:00
|
|
|
[ret assignSamples:[removedData bytes] frameCount:maxFrameCount];
|
|
|
|
listDuration -= [ret duration];
|
|
|
|
inRemover = NO;
|
|
|
|
return ret;
|
|
|
|
}
|
2022-02-06 11:08:34 +00:00
|
|
|
}
|
|
|
|
|
2022-02-08 03:18:45 +00:00
|
|
|
- (BOOL)peekFormat:(AudioStreamBasicDescription *)format channelConfig:(uint32_t *)config {
|
|
|
|
if(stopping) return NO;
|
|
|
|
@synchronized(chunkList) {
|
|
|
|
if([chunkList count]) {
|
|
|
|
AudioChunk *chunk = [chunkList objectAtIndex:0];
|
|
|
|
*format = [chunk format];
|
|
|
|
*config = [chunk channelConfig];
|
|
|
|
return YES;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return NO;
|
|
|
|
}
|
|
|
|
|
2022-02-06 11:08:34 +00:00
|
|
|
@end
|