Bug Fix: Handle gaplessness for headphone filter
The filter uses a pre-buffer of input audio, so extrapolate from the actual input to fill the buffer. Fixes clicking on non-zero-crossing track endings. Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This commit is contained in:
parent
ea7eff40e0
commit
68a146f6b8
3 changed files with 33 additions and 0 deletions
|
@ -13,6 +13,8 @@
|
||||||
|
|
||||||
#import "DSPHRTFNode.h"
|
#import "DSPHRTFNode.h"
|
||||||
|
|
||||||
|
#import "lpc.h"
|
||||||
|
|
||||||
#import "HeadphoneFilter.h"
|
#import "HeadphoneFilter.h"
|
||||||
|
|
||||||
static void * kDSPHRTFNodeContext = &kDSPHRTFNodeContext;
|
static void * kDSPHRTFNodeContext = &kDSPHRTFNodeContext;
|
||||||
|
@ -75,6 +77,8 @@ static void unregisterMotionListener(void) {
|
||||||
BOOL processEntered;
|
BOOL processEntered;
|
||||||
BOOL resetFilter;
|
BOOL resetFilter;
|
||||||
|
|
||||||
|
size_t needPrefill;
|
||||||
|
|
||||||
BOOL observersapplied;
|
BOOL observersapplied;
|
||||||
|
|
||||||
AudioStreamBasicDescription lastInputFormat;
|
AudioStreamBasicDescription lastInputFormat;
|
||||||
|
@ -89,7 +93,11 @@ static void unregisterMotionListener(void) {
|
||||||
simd_float4x4 rotationMatrix;
|
simd_float4x4 rotationMatrix;
|
||||||
simd_float4x4 referenceMatrix;
|
simd_float4x4 referenceMatrix;
|
||||||
|
|
||||||
|
float prefillBuffer[4096 * 32];
|
||||||
float outBuffer[4096 * 2];
|
float outBuffer[4096 * 2];
|
||||||
|
|
||||||
|
void *extrapolate_buffer;
|
||||||
|
size_t extrapolate_buffer_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (void)initialize {
|
+ (void)initialize {
|
||||||
|
@ -131,6 +139,11 @@ static void unregisterMotionListener(void) {
|
||||||
[self cleanUp];
|
[self cleanUp];
|
||||||
[self removeObservers];
|
[self removeObservers];
|
||||||
[super cleanUp];
|
[super cleanUp];
|
||||||
|
if(extrapolate_buffer) {
|
||||||
|
free(extrapolate_buffer);
|
||||||
|
extrapolate_buffer = NULL;
|
||||||
|
extrapolate_buffer_size = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)addObservers {
|
- (void)addObservers {
|
||||||
|
@ -210,6 +223,8 @@ static void unregisterMotionListener(void) {
|
||||||
outputChannelConfig = AudioChannelSideLeft | AudioChannelSideRight;
|
outputChannelConfig = AudioChannelSideLeft | AudioChannelSideRight;
|
||||||
|
|
||||||
resetFilter = NO;
|
resetFilter = NO;
|
||||||
|
|
||||||
|
needPrefill = [hrtf needPrefill];
|
||||||
} else {
|
} else {
|
||||||
if(lastEnableHeadTracking) {
|
if(lastEnableHeadTracking) {
|
||||||
lastEnableHeadTracking = NO;
|
lastEnableHeadTracking = NO;
|
||||||
|
@ -359,6 +374,18 @@ static void unregisterMotionListener(void) {
|
||||||
size_t frameCount = [chunk frameCount];
|
size_t frameCount = [chunk frameCount];
|
||||||
NSData *sampleData = [chunk removeSamples:frameCount];
|
NSData *sampleData = [chunk removeSamples:frameCount];
|
||||||
|
|
||||||
|
if(needPrefill) {
|
||||||
|
size_t maxToUse = 4096 - needPrefill;
|
||||||
|
if(maxToUse > frameCount) {
|
||||||
|
maxToUse = frameCount;
|
||||||
|
}
|
||||||
|
size_t channels = inputFormat.mChannelsPerFrame;
|
||||||
|
memcpy(&prefillBuffer[needPrefill * channels], [sampleData bytes], maxToUse * sizeof(float) * channels);
|
||||||
|
lpc_extrapolate_bkwd(&prefillBuffer[needPrefill * channels], maxToUse, maxToUse, (int)channels, LPC_ORDER, needPrefill, &extrapolate_buffer, &extrapolate_buffer_size);
|
||||||
|
[hrtf process:&prefillBuffer[0] sampleCount:(int)needPrefill toBuffer:&outBuffer[0]];
|
||||||
|
needPrefill = 0;
|
||||||
|
}
|
||||||
|
|
||||||
[hrtf process:(const float *)[sampleData bytes] sampleCount:(int)frameCount toBuffer:&outBuffer[0]];
|
[hrtf process:(const float *)[sampleData bytes] sampleCount:(int)frameCount toBuffer:&outBuffer[0]];
|
||||||
|
|
||||||
AudioChunk *outputChunk = [[AudioChunk alloc] init];
|
AudioChunk *outputChunk = [[AudioChunk alloc] init];
|
||||||
|
|
|
@ -39,6 +39,8 @@
|
||||||
|
|
||||||
- (void)reset;
|
- (void)reset;
|
||||||
|
|
||||||
|
- (size_t)needPrefill;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
#endif /* HeadphoneFilter_h */
|
#endif /* HeadphoneFilter_h */
|
||||||
|
|
|
@ -379,4 +379,8 @@ static impulseSetCache *_sharedController = nil;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (size_t)needPrefill {
|
||||||
|
return paddedBufferSize;
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
Loading…
Reference in a new issue