Cog/Audio/Chain/ChunkList.m
Christopher Snowhill 728c44242c Do not reset output sample rate automatically
This was buggy as hell, and resulted in errors. Now the user should
restart playback if they change output device formats.

Signed-off-by: Christopher Snowhill <kode54@gmail.com>
2022-02-07 22:02:17 -08:00

113 lines
2.1 KiB
Objective-C

//
// ChunkList.m
// CogAudio Framework
//
// Created by Christopher Snowhill on 2/5/22.
//
#import "ChunkList.h"
@implementation ChunkList
@synthesize listDuration;
@synthesize maxDuration;
- (id)initWithMaximumDuration:(double)duration {
self = [super init];
if(self) {
chunkList = [[NSMutableArray alloc] init];
listDuration = 0.0;
maxDuration = duration;
inAdder = NO;
inRemover = NO;
inPeeker = NO;
stopping = NO;
}
return self;
}
- (void)dealloc {
stopping = YES;
while(inAdder || inRemover || inPeeker) {
usleep(500);
}
}
- (void)reset {
@synchronized(chunkList) {
[chunkList removeAllObjects];
listDuration = 0.0;
}
}
- (BOOL)isEmpty {
@synchronized(chunkList) {
return [chunkList count] == 0;
}
}
- (BOOL)isFull {
return (maxDuration - listDuration) < 0.05;
}
- (void)addChunk:(AudioChunk *)chunk {
if(stopping) return;
inAdder = YES;
const double chunkDuration = [chunk duration];
@synchronized(chunkList) {
[chunkList addObject:chunk];
listDuration += chunkDuration;
}
inAdder = NO;
}
- (AudioChunk *)removeSamples:(size_t)maxFrameCount {
if(stopping) {
return [[AudioChunk alloc] init];
}
@synchronized(chunkList) {
inRemover = YES;
if(![chunkList count]) {
inRemover = NO;
return [[AudioChunk alloc] init];
}
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]];
[ret setChannelConfig:[chunk channelConfig]];
[ret assignSamples:[removedData bytes] frameCount:maxFrameCount];
listDuration -= [ret duration];
inRemover = NO;
return ret;
}
}
- (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;
}
@end