Audio: Make chunk merging abortable

The merge function should be able to tell when the caller has no audio
left to process, such as on end of stream.

Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This commit is contained in:
Christopher Snowhill 2025-02-13 13:51:46 -08:00
parent 86ce3cf69b
commit aba5b8d120
3 changed files with 17 additions and 7 deletions

View file

@ -76,8 +76,8 @@ NS_ASSUME_NONNULL_BEGIN
- (BOOL)peekTimestamp:(nonnull double *)timestamp timeRatio:(nonnull double *)timeRatio;
// Helpers
- (AudioChunk *)removeAndMergeSamples:(size_t)maxFrameCount;
- (AudioChunk *)removeAndMergeSamplesAsFloat32:(size_t)maxFrameCount;
- (AudioChunk *)removeAndMergeSamples:(size_t)maxFrameCount callBlock:(BOOL(NS_NOESCAPE ^ _Nonnull)(void))block;
- (AudioChunk *)removeAndMergeSamplesAsFloat32:(size_t)maxFrameCount callBlock:(BOOL(NS_NOESCAPE ^ _Nonnull)(void))block;
@end

View file

@ -556,7 +556,7 @@ static void convert_be_to_le(uint8_t *buffer, size_t bitsPerSample, size_t bytes
}
}
- (AudioChunk *)removeAndMergeSamples:(size_t)maxFrameCount {
- (AudioChunk *)removeAndMergeSamples:(size_t)maxFrameCount callBlock:(BOOL(NS_NOESCAPE ^ _Nonnull)(void))block {
if(stopping) {
return [[AudioChunk alloc] init];
}
@ -585,6 +585,9 @@ static void convert_be_to_le(uint8_t *buffer, size_t bitsPerSample, size_t bytes
AudioStreamBasicDescription newFormat;
uint32_t newChannelConfig;
if(![self peekFormat:&newFormat channelConfig:&newChannelConfig]) {
if(block()) {
break;
}
usleep(500);
continue;
}
@ -602,6 +605,9 @@ static void convert_be_to_le(uint8_t *buffer, size_t bitsPerSample, size_t bytes
chunk = [self removeSamples:maxFrameCount - totalFrameCount];
if(!chunk || ![chunk frameCount]) {
if(block()) {
break;
}
usleep(500);
continue;
}
@ -627,8 +633,8 @@ static void convert_be_to_le(uint8_t *buffer, size_t bitsPerSample, size_t bytes
return outputChunk;
}
- (AudioChunk *)removeAndMergeSamplesAsFloat32:(size_t)maxFrameCount {
AudioChunk *ret = [self removeAndMergeSamples:maxFrameCount];
- (AudioChunk *)removeAndMergeSamplesAsFloat32:(size_t)maxFrameCount callBlock:(BOOL(NS_NOESCAPE ^ _Nonnull)(void))block {
AudioChunk *ret = [self removeAndMergeSamples:maxFrameCount callBlock:block];
return [self convertChunk:ret];
}

View file

@ -264,7 +264,9 @@
AudioChunk *ret;
@autoreleasepool {
ret = [[previousNode buffer] removeAndMergeSamples:maxFrames];
ret = [[previousNode buffer] removeAndMergeSamples:maxFrames callBlock:^BOOL{
return [[previousNode buffer] isEmpty] && [previousNode endOfStream] == YES;
}];
}
if([ret frameCount]) {
@ -299,7 +301,9 @@
AudioChunk *ret;
@autoreleasepool {
ret = [[previousNode buffer] removeAndMergeSamplesAsFloat32:maxFrames];
ret = [[previousNode buffer] removeAndMergeSamplesAsFloat32:maxFrames callBlock:^BOOL{
return [[previousNode buffer] isEmpty] && [previousNode endOfStream] == YES;
}];
}
if([ret frameCount]) {