Seeking now takes the true nuclear approach to output, and should no longer have glitches

CQTexperiment
Christopher Snowhill 2021-12-26 02:01:02 -08:00
parent d22ee14a36
commit dfeca7aa97
6 changed files with 146 additions and 10 deletions

View File

@ -10,6 +10,7 @@
@class BufferChain;
@class OutputNode;
@protocol CogDecoder;
@interface AudioPlayer : NSObject
{
@ -19,6 +20,10 @@
double volume;
NSMutableArray *chainQueue;
NSURL *currentStream;
id currentUserInfo;
NSDictionary *currentRGInfo;
NSURL *nextStream;
id nextStreamUserInfo;
@ -30,6 +35,7 @@
BOOL endOfInputReached;
BOOL startedPaused;
BOOL initialBufferFilled;
BOOL paused;
}
- (id)init;
@ -40,6 +46,7 @@
- (void)play:(NSURL *)url;
- (void)play:(NSURL *)url withUserInfo:(id)userInfo withRGInfo:(NSDictionary*)rgi;
- (void)play:(NSURL *)url withUserInfo:(id)userInfo withRGInfo:(NSDictionary*)rgi startPaused:(BOOL)paused;
- (void)play:(id<CogDecoder>)decoder startPaused:(BOOL)paused;
- (void)stop;
- (void)pause;

View File

@ -55,9 +55,9 @@
- (void)play:(NSURL *)url withUserInfo:(id)userInfo withRGInfo:(NSDictionary *)rgi startPaused:(BOOL)paused
{
output = [[OutputNode alloc] initWithController:self previous:nil];
[output setup];
[output setVolume: volume];
if (output) {
[output close];
}
@synchronized(chainQueue) {
for (id anObject in chainQueue)
{
@ -72,9 +72,16 @@
bufferChain = nil;
}
}
output = [[OutputNode alloc] initWithController:self previous:nil];
[output setup];
[output setVolume: volume];
bufferChain = [[BufferChain alloc] initWithController:self];
[self notifyStreamChanged:userInfo];
currentStream = url;
currentUserInfo = userInfo;
currentRGInfo = rgi;
while (![bufferChain open:url withOutputFormat:[output format] withRGInfo:rgi])
{
@ -87,10 +94,14 @@
{
return;
}
userInfo = nextStreamUserInfo;
rgi = nextStreamRGInfo;
currentStream = url;
currentUserInfo = userInfo;
currentRGInfo = rgi;
[self notifyStreamChanged:userInfo];
bufferChain = [[BufferChain alloc] initWithController:self];
@ -108,6 +119,78 @@
if (paused)
[self setPlaybackStatus:CogStatusPaused waitUntilDone:YES];
self->paused = paused;
}
- (void)play:(id<CogDecoder>)decoder startPaused:(BOOL)paused
{
if (output) {
[output close];
}
@synchronized(chainQueue) {
for (id anObject in chainQueue)
{
[anObject setShouldContinue:NO];
}
[chainQueue removeAllObjects];
endOfInputReached = NO;
if (bufferChain)
{
[bufferChain setShouldContinue:NO];
bufferChain = nil;
}
}
output = [[OutputNode alloc] initWithController:self previous:nil];
[output setup];
[output setVolume: volume];
bufferChain = [[BufferChain alloc] initWithController:self];
[self notifyStreamChanged:currentUserInfo];
NSURL *url = currentStream;
id userInfo = currentUserInfo;
NSDictionary *rgi = currentRGInfo;
while (![bufferChain openWithDecoder:decoder withOutputFormat:[output format] withRGInfo:currentRGInfo])
{
bufferChain = nil;
[self requestNextStream: userInfo];
url = nextStream;
if (url == nil)
{
return;
}
userInfo = nextStreamUserInfo;
rgi = nextStreamRGInfo;
currentStream = url;
currentUserInfo = userInfo;
currentRGInfo = rgi;
[self notifyStreamChanged:userInfo];
bufferChain = [[BufferChain alloc] initWithController:self];
}
[bufferChain setUserInfo:userInfo];
[self setShouldContinue:YES];
outputLaunched = NO;
startedPaused = paused;
initialBufferFilled = NO;
[bufferChain launchThreads];
if (paused)
[self setPlaybackStatus:CogStatusPaused waitUntilDone:YES];
self->paused = paused;
}
- (void)stop
@ -122,6 +205,8 @@
[output pause];
[self setPlaybackStatus:CogStatusPaused waitUntilDone:YES];
paused = YES;
}
- (void)resume
@ -136,12 +221,15 @@
[output resume];
[self setPlaybackStatus:CogStatusPlaying waitUntilDone:YES];
paused = NO;
}
- (void)seekToTime:(double)time
{
//Need to reset everything's buffers, and then seek?
/*HACK TO TEST HOW WELL THIS WOULD WORK*/
[self play:[[bufferChain inputNode] stealDecoder] startPaused:paused];
[output seek:time];
[bufferChain seek:time];
/*END HACK*/

View File

@ -16,7 +16,7 @@
InputNode *inputNode;
ConverterNode *converterNode;
AudioStreamBasicDescription _inputFormat;
AudioStreamBasicDescription inputFormat;
NSURL *streamURL;
id userInfo;
@ -35,11 +35,17 @@
//Used when changing tracks to reuse the same decoder
- (BOOL)openWithInput:(InputNode *)i withOutputFormat:(AudioStreamBasicDescription)outputFormat withRGInfo:(NSDictionary*)rgi;
//Used when resetting the decoder on seek
- (BOOL)openWithDecoder:(id<CogDecoder>)decoder
withOutputFormat:(AudioStreamBasicDescription)outputFormat
withRGInfo:(NSDictionary*)rgi;
- (void)seek:(double)time;
- (void)launchThreads;
- (InputNode *)inputNode;
- (InputNode *)stealInputNode;
- (id)finalNode;

View File

@ -63,7 +63,7 @@
if (![inputNode openWithSource:source])
return NO;
if (![converterNode setupWithInputFormat:(_inputFormat = propertiesToASBD([inputNode properties])) outputFormat:outputFormat])
if (![converterNode setupWithInputFormat:(inputFormat = propertiesToASBD([inputNode properties])) outputFormat:outputFormat])
return NO;
[self setRGInfo:rgi];
@ -82,7 +82,7 @@
return NO;
DLog(@"Input Properties: %@", [inputNode properties]);
if (![converterNode setupWithInputFormat:(_inputFormat = propertiesToASBD([inputNode properties])) outputFormat:outputFormat])
if (![converterNode setupWithInputFormat:(inputFormat = propertiesToASBD([inputNode properties])) outputFormat:outputFormat])
return NO;
[self setRGInfo:rgi];
@ -90,6 +90,25 @@
return YES;
}
- (BOOL)openWithDecoder:(id<CogDecoder>)decoder
withOutputFormat:(AudioStreamBasicDescription)outputFormat
withRGInfo:(NSDictionary*)rgi;
{
DLog(@"New buffer chain!");
[self buildChain];
if (![inputNode openWithDecoder:decoder])
return NO;
DLog(@"Input Properties: %@", [inputNode properties]);
if (![converterNode setupWithInputFormat:(inputFormat = propertiesToASBD([inputNode properties])) outputFormat:outputFormat])
return NO;
[self setRGInfo:rgi];
return YES;
}
- (void)launchThreads
{
DLog(@"Properties: %@", [inputNode properties]);
@ -206,7 +225,7 @@
- (AudioStreamBasicDescription)inputFormat
{
return _inputFormat;
return inputFormat;
}
@end

View File

@ -36,6 +36,8 @@
- (BOOL)openWithSource:(id<CogSource>)source;
- (BOOL)openWithDecoder:(id<CogDecoder>) d;
- (id<CogDecoder>)stealDecoder;
- (void)process;
- (NSDictionary *) properties;
- (void)seek:(long)frame;

View File

@ -215,11 +215,16 @@
return NO;
}
- (void)removeObservers
{
[decoder removeObserver:self forKeyPath:@"properties"];
[decoder removeObserver:self forKeyPath:@"metadata"];
}
- (void)dealloc
{
DLog(@"Input Node dealloc");
[decoder removeObserver:self forKeyPath:@"properties"];
[decoder removeObserver:self forKeyPath:@"metadata"];
[self removeObservers];
}
- (NSDictionary *) properties
@ -232,4 +237,13 @@
return decoder;
}
- (id<CogDecoder>) stealDecoder
{
[self removeObservers];
id<CogDecoder> decoder = self->decoder;
self->decoder = [[NSClassFromString(@"SilenceDecoder") alloc] init];
[self registerObservers];
return decoder;
}
@end