From 001f3e53ea05cbb5f9afaf4f59e4ad0f1d4416a3 Mon Sep 17 00:00:00 2001 From: Christopher Snowhill Date: Mon, 3 Mar 2025 22:24:17 -0800 Subject: [PATCH] Debugging: Implement buffer chain logging code This optional code, disabled at compile time by default, allows finding weird issues with the sample decoding chain. Signed-off-by: Christopher Snowhill --- Audio/Chain/ConverterNode.m | 4 ++ Audio/Chain/DSPNode.m | 4 ++ Audio/Chain/Node.h | 11 ++++++ Audio/Chain/Node.m | 79 +++++++++++++++++++++++++++++++++++++ 4 files changed, 98 insertions(+) diff --git a/Audio/Chain/ConverterNode.m b/Audio/Chain/ConverterNode.m index 3e4ac572c..e9520ae0d 100644 --- a/Audio/Chain/ConverterNode.m +++ b/Audio/Chain/ConverterNode.m @@ -67,6 +67,10 @@ static void *kConverterNodeContext = &kConverterNodeContext; extrapolateBufferSize = 0; [[NSUserDefaultsController sharedUserDefaultsController] addObserver:self forKeyPath:@"values.volumeScaling" options:0 context:kConverterNodeContext]; + +#ifdef LOG_CHAINS + [self initLogFiles]; +#endif } return self; diff --git a/Audio/Chain/DSPNode.m b/Audio/Chain/DSPNode.m index b6503f71d..8c5386188 100644 --- a/Audio/Chain/DSPNode.m +++ b/Audio/Chain/DSPNode.m @@ -38,6 +38,10 @@ inMerge = NO; [self setPreviousNode:p]; + +#ifdef LOG_CHAINS + [self initLogFiles]; +#endif } return self; diff --git a/Audio/Chain/Node.h b/Audio/Chain/Node.h index 81f5d0d0f..4f1e90cca 100644 --- a/Audio/Chain/Node.h +++ b/Audio/Chain/Node.h @@ -15,6 +15,8 @@ #define BUFFER_SIZE 1024 * 1024 #define CHUNK_SIZE 16 * 1024 +//#define LOG_CHAINS 1 + @interface Node : NSObject { ChunkList *buffer; Semaphore *writeSemaphore; @@ -41,9 +43,18 @@ BOOL nodeLossless; double durationPrebuffer; + +#ifdef LOG_CHAINS + NSFileHandle *logFileOut; + NSFileHandle *logFileIn; +#endif } - (id _Nullable)initWithController:(id _Nonnull)c previous:(id _Nullable)p; +#ifdef LOG_CHAINS +- (void)initLogFiles; +#endif + - (void)cleanUp; - (BOOL)paused; diff --git a/Audio/Chain/Node.m b/Audio/Chain/Node.m index aca67d826..84eab9ff3 100644 --- a/Audio/Chain/Node.m +++ b/Audio/Chain/Node.m @@ -17,8 +17,33 @@ #import +#ifdef LOG_CHAINS +#import "NSFileHandle+CreateFile.h" + +static NSLock * _Node_lock = nil; +static uint64_t _Node_serial; +#endif + @implementation Node +#ifdef LOG_CHAINS ++ (void)initialize { + @synchronized (_Node_lock) { + if(!_Node_lock) { + _Node_lock = [[NSLock alloc] init]; + _Node_serial = 0; + } + } +} + +- (void)initLogFiles { + [_Node_lock lock]; + logFileOut = [NSFileHandle fileHandleForWritingAtPath:[NSTemporaryDirectory() stringByAppendingPathComponent:[NSString stringWithFormat:@"%@_output_%08lld.raw", [self className], _Node_serial++]] createFile:YES]; + logFileIn = [NSFileHandle fileHandleForWritingAtPath:[NSTemporaryDirectory() stringByAppendingPathComponent:[NSString stringWithFormat:@"%@_input_%08lld.raw", [self className], _Node_serial++]] createFile:YES]; + [_Node_lock unlock]; +} +#endif + - (id)initWithController:(id)c previous:(id)p { self = [super init]; if(self) { @@ -45,6 +70,10 @@ inMerge = NO; [self setPreviousNode:p]; + +#ifdef LOG_CHAINS + [self initLogFiles]; +#endif } return self; @@ -94,6 +123,12 @@ [chunk setLossless:nodeLossless]; [chunk assignSamples:ptr frameCount:amount / nodeFormat.mBytesPerPacket]; +#ifdef LOG_CHAINS + if(logFileOut) { + [logFileOut writeData:[NSData dataWithBytes:ptr length:amount]]; + } +#endif + double durationList = [buffer listDuration]; double durationLeft = [buffer maxDuration] - durationList; @@ -167,6 +202,14 @@ BOOL doSignal = NO; if([chunk frameCount]) { +#ifdef LOG_CHAINS + if(logFileOut) { + AudioChunk *chunkCopy = [chunk copy]; + size_t frameCount = [chunkCopy frameCount]; + NSData *chunkData = [chunkCopy removeSamples:frameCount]; + [logFileOut writeData:chunkData]; + } +#endif [buffer addChunk:chunk]; doSignal = YES; } @@ -324,6 +367,15 @@ [[previousNode writeSemaphore] signal]; } +#ifdef LOG_CHAINS + if(logFileIn) { + AudioChunk *chunkCopy = [ret copy]; + size_t frameCount = [chunkCopy frameCount]; + NSData *chunkData = [chunkCopy removeSamples:frameCount]; + [logFileIn writeData:chunkData]; + } +#endif + inRead = NO; return ret; @@ -385,6 +437,15 @@ [[previousNode writeSemaphore] signal]; } +#ifdef LOG_CHAINS + if(logFileIn) { + AudioChunk *chunkCopy = [ret copy]; + size_t frameCount = [chunkCopy frameCount]; + NSData *chunkData = [chunkCopy removeSamples:frameCount]; + [logFileIn writeData:chunkData]; + } +#endif + inRead = NO; return ret; @@ -432,6 +493,15 @@ if([ret frameCount]) { [[previousNode writeSemaphore] signal]; + +#ifdef LOG_CHAINS + if(logFileIn) { + AudioChunk *chunkCopy = [ret copy]; + size_t frameCount = [chunkCopy frameCount]; + NSData *chunkData = [chunkCopy removeSamples:frameCount]; + [logFileIn writeData:chunkData]; + } +#endif } inMerge = NO; @@ -481,6 +551,15 @@ if([ret frameCount]) { [[previousNode writeSemaphore] signal]; + +#ifdef LOG_CHAINS + if(logFileIn) { + AudioChunk *chunkCopy = [ret copy]; + size_t frameCount = [chunkCopy frameCount]; + NSData *chunkData = [chunkCopy removeSamples:frameCount]; + [logFileIn writeData:chunkData]; + } +#endif } inMerge = NO;