Downmix: Move downmix to DSP chain and fix a bug
The downmix filter also had a bug related to the channel configuration used by the HRTF filter. Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This commit is contained in:
parent
d3778f92fc
commit
4cd5cb8fa7
12 changed files with 291 additions and 34 deletions
|
@ -15,6 +15,7 @@
|
||||||
#import "DSPHRTFNode.h"
|
#import "DSPHRTFNode.h"
|
||||||
#import "DSPEqualizerNode.h"
|
#import "DSPEqualizerNode.h"
|
||||||
#import "VisualizationNode.h"
|
#import "VisualizationNode.h"
|
||||||
|
#import "DSPDownmixNode.h"
|
||||||
#import "InputNode.h"
|
#import "InputNode.h"
|
||||||
|
|
||||||
@interface BufferChain : NSObject {
|
@interface BufferChain : NSObject {
|
||||||
|
@ -24,6 +25,7 @@
|
||||||
DSPFSurroundNode *fsurroundNode;
|
DSPFSurroundNode *fsurroundNode;
|
||||||
DSPHRTFNode *hrtfNode;
|
DSPHRTFNode *hrtfNode;
|
||||||
DSPEqualizerNode *equalizerNode;
|
DSPEqualizerNode *equalizerNode;
|
||||||
|
DSPDownmixNode *downmixNode;
|
||||||
VisualizationNode *visualizationNode;
|
VisualizationNode *visualizationNode;
|
||||||
|
|
||||||
NSURL *streamURL;
|
NSURL *streamURL;
|
||||||
|
@ -89,6 +91,8 @@
|
||||||
|
|
||||||
- (DSPEqualizerNode *)equalizer;
|
- (DSPEqualizerNode *)equalizer;
|
||||||
|
|
||||||
|
- (DSPDownmixNode *)downmix;
|
||||||
|
|
||||||
- (VisualizationNode *)visualization;
|
- (VisualizationNode *)visualization;
|
||||||
|
|
||||||
- (double)secondsBuffered;
|
- (double)secondsBuffered;
|
||||||
|
|
|
@ -11,6 +11,8 @@
|
||||||
#import "CoreAudioUtils.h"
|
#import "CoreAudioUtils.h"
|
||||||
#import "OutputNode.h"
|
#import "OutputNode.h"
|
||||||
|
|
||||||
|
#import "AudioPlayer.h"
|
||||||
|
|
||||||
#import "Logging.h"
|
#import "Logging.h"
|
||||||
|
|
||||||
@implementation BufferChain
|
@implementation BufferChain
|
||||||
|
@ -30,6 +32,7 @@
|
||||||
fsurroundNode = nil;
|
fsurroundNode = nil;
|
||||||
equalizerNode = nil;
|
equalizerNode = nil;
|
||||||
hrtfNode = nil;
|
hrtfNode = nil;
|
||||||
|
downmixNode = nil;
|
||||||
|
|
||||||
visualizationNode = nil;
|
visualizationNode = nil;
|
||||||
}
|
}
|
||||||
|
@ -47,9 +50,10 @@
|
||||||
fsurroundNode = [[DSPFSurroundNode alloc] initWithController:self previous:rubberbandNode latency:0.03];
|
fsurroundNode = [[DSPFSurroundNode alloc] initWithController:self previous:rubberbandNode latency:0.03];
|
||||||
equalizerNode = [[DSPEqualizerNode alloc] initWithController:self previous:fsurroundNode latency:0.03];
|
equalizerNode = [[DSPEqualizerNode alloc] initWithController:self previous:fsurroundNode latency:0.03];
|
||||||
hrtfNode = [[DSPHRTFNode alloc] initWithController:self previous:equalizerNode latency:0.03];
|
hrtfNode = [[DSPHRTFNode alloc] initWithController:self previous:equalizerNode latency:0.03];
|
||||||
|
downmixNode = [[DSPDownmixNode alloc] initWithController:self previous:hrtfNode latency:0.03];
|
||||||
|
|
||||||
// Approximately five frames
|
// Approximately five frames
|
||||||
visualizationNode = [[VisualizationNode alloc] initWithController:self previous:hrtfNode latency:5.0 / 60.0];
|
visualizationNode = [[VisualizationNode alloc] initWithController:self previous:downmixNode latency:5.0 / 60.0];
|
||||||
|
|
||||||
finalNode = visualizationNode;
|
finalNode = visualizationNode;
|
||||||
}
|
}
|
||||||
|
@ -86,6 +90,7 @@
|
||||||
|
|
||||||
if(![converterNode setupWithInputFormat:inputFormat withInputConfig:inputChannelConfig outputFormat:outputFormat isLossless:[[properties valueForKey:@"encoding"] isEqualToString:@"lossless"]])
|
if(![converterNode setupWithInputFormat:inputFormat withInputConfig:inputChannelConfig outputFormat:outputFormat isLossless:[[properties valueForKey:@"encoding"] isEqualToString:@"lossless"]])
|
||||||
return NO;
|
return NO;
|
||||||
|
[self initDownmixer];
|
||||||
|
|
||||||
[self setRGInfo:rgi];
|
[self setRGInfo:rgi];
|
||||||
|
|
||||||
|
@ -116,6 +121,7 @@
|
||||||
DLog(@"Input Properties: %@", properties);
|
DLog(@"Input Properties: %@", properties);
|
||||||
if(![converterNode setupWithInputFormat:inputFormat withInputConfig:inputChannelConfig outputFormat:outputFormat isLossless:[[properties objectForKey:@"encoding"] isEqualToString:@"lossless"]])
|
if(![converterNode setupWithInputFormat:inputFormat withInputConfig:inputChannelConfig outputFormat:outputFormat isLossless:[[properties objectForKey:@"encoding"] isEqualToString:@"lossless"]])
|
||||||
return NO;
|
return NO;
|
||||||
|
[self initDownmixer];
|
||||||
|
|
||||||
[self setRGInfo:rgi];
|
[self setRGInfo:rgi];
|
||||||
|
|
||||||
|
@ -149,12 +155,19 @@
|
||||||
|
|
||||||
if(![converterNode setupWithInputFormat:inputFormat withInputConfig:inputChannelConfig outputFormat:outputFormat isLossless:[[properties objectForKey:@"encoding"] isEqualToString:@"lossless"]])
|
if(![converterNode setupWithInputFormat:inputFormat withInputConfig:inputChannelConfig outputFormat:outputFormat isLossless:[[properties objectForKey:@"encoding"] isEqualToString:@"lossless"]])
|
||||||
return NO;
|
return NO;
|
||||||
|
[self initDownmixer];
|
||||||
|
|
||||||
[self setRGInfo:rgi];
|
[self setRGInfo:rgi];
|
||||||
|
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)initDownmixer {
|
||||||
|
AudioPlayer * audioPlayer = controller;
|
||||||
|
OutputNode *outputNode = [audioPlayer output];
|
||||||
|
[downmixNode setOutputFormat:[outputNode deviceFormat] withChannelConfig:[outputNode deviceChannelConfig]];
|
||||||
|
}
|
||||||
|
|
||||||
- (void)launchThreads {
|
- (void)launchThreads {
|
||||||
DLog(@"Properties: %@", [inputNode properties]);
|
DLog(@"Properties: %@", [inputNode properties]);
|
||||||
|
|
||||||
|
@ -164,6 +177,7 @@
|
||||||
[fsurroundNode launchThread];
|
[fsurroundNode launchThread];
|
||||||
[equalizerNode launchThread];
|
[equalizerNode launchThread];
|
||||||
[hrtfNode launchThread];
|
[hrtfNode launchThread];
|
||||||
|
[downmixNode launchThread];
|
||||||
[visualizationNode launchThread];
|
[visualizationNode launchThread];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -239,6 +253,7 @@
|
||||||
[fsurroundNode setShouldContinue:s];
|
[fsurroundNode setShouldContinue:s];
|
||||||
[equalizerNode setShouldContinue:s];
|
[equalizerNode setShouldContinue:s];
|
||||||
[hrtfNode setShouldContinue:s];
|
[hrtfNode setShouldContinue:s];
|
||||||
|
[downmixNode setShouldContinue:s];
|
||||||
[visualizationNode setShouldContinue:s];
|
[visualizationNode setShouldContinue:s];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -274,6 +289,10 @@
|
||||||
return equalizerNode;
|
return equalizerNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (DSPDownmixNode *)downmix {
|
||||||
|
return downmixNode;
|
||||||
|
}
|
||||||
|
|
||||||
- (VisualizationNode *)visualization {
|
- (VisualizationNode *)visualization {
|
||||||
return visualizationNode;
|
return visualizationNode;
|
||||||
}
|
}
|
||||||
|
|
32
Audio/Chain/DSP/DSPDownmixNode.h
Normal file
32
Audio/Chain/DSP/DSPDownmixNode.h
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
//
|
||||||
|
// DSPDownmixNode.h
|
||||||
|
// CogAudio
|
||||||
|
//
|
||||||
|
// Created by Christopher Snowhill on 2/13/25.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef DSPDownmixNode_h
|
||||||
|
#define DSPDownmixNode_h
|
||||||
|
|
||||||
|
#import <AudioToolbox/AudioToolbox.h>
|
||||||
|
|
||||||
|
#import "DSPNode.h"
|
||||||
|
|
||||||
|
@interface DSPDownmixNode : DSPNode {
|
||||||
|
}
|
||||||
|
|
||||||
|
- (id _Nullable)initWithController:(id _Nonnull)c previous:(id _Nullable)p latency:(double)latency;
|
||||||
|
|
||||||
|
- (BOOL)setup;
|
||||||
|
- (void)cleanUp;
|
||||||
|
|
||||||
|
- (void)resetBuffer;
|
||||||
|
|
||||||
|
- (void)process;
|
||||||
|
- (AudioChunk * _Nullable)convert;
|
||||||
|
|
||||||
|
- (void)setOutputFormat:(AudioStreamBasicDescription)format withChannelConfig:(uint32_t)config;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
#endif /* DSPDownmixNode_h */
|
184
Audio/Chain/DSP/DSPDownmixNode.m
Normal file
184
Audio/Chain/DSP/DSPDownmixNode.m
Normal file
|
@ -0,0 +1,184 @@
|
||||||
|
//
|
||||||
|
// DSPDownmixNode.m
|
||||||
|
// CogAudio Framework
|
||||||
|
//
|
||||||
|
// Created by Christopher Snowhill on 2/13/25.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
#import "Downmix.h"
|
||||||
|
|
||||||
|
#import "Logging.h"
|
||||||
|
|
||||||
|
#import "DSPDownmixNode.h"
|
||||||
|
|
||||||
|
@implementation DSPDownmixNode {
|
||||||
|
DownmixProcessor *downmix;
|
||||||
|
|
||||||
|
BOOL stopping, paused;
|
||||||
|
BOOL processEntered;
|
||||||
|
BOOL formatSet;
|
||||||
|
|
||||||
|
AudioStreamBasicDescription lastInputFormat;
|
||||||
|
AudioStreamBasicDescription inputFormat;
|
||||||
|
AudioStreamBasicDescription outputFormat;
|
||||||
|
|
||||||
|
uint32_t lastInputChannelConfig, inputChannelConfig;
|
||||||
|
uint32_t outputChannelConfig;
|
||||||
|
|
||||||
|
float outBuffer[4096 * 32];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (id _Nullable)initWithController:(id _Nonnull)c previous:(id _Nullable)p latency:(double)latency {
|
||||||
|
self = [super initWithController:c previous:p latency:latency];
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)dealloc {
|
||||||
|
DLog(@"Downmix dealloc");
|
||||||
|
[self cleanUp];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)fullInit {
|
||||||
|
if(formatSet) {
|
||||||
|
downmix = [[DownmixProcessor alloc] initWithInputFormat:inputFormat inputConfig:inputChannelConfig andOutputFormat:outputFormat outputConfig:outputChannelConfig];
|
||||||
|
if(!downmix) {
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)fullShutdown {
|
||||||
|
downmix = nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)setup {
|
||||||
|
if(stopping)
|
||||||
|
return NO;
|
||||||
|
[self fullShutdown];
|
||||||
|
return [self fullInit];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)cleanUp {
|
||||||
|
stopping = YES;
|
||||||
|
while(processEntered) {
|
||||||
|
usleep(500);
|
||||||
|
}
|
||||||
|
[self fullShutdown];
|
||||||
|
formatSet = NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)resetBuffer {
|
||||||
|
paused = YES;
|
||||||
|
while(processEntered) {
|
||||||
|
usleep(500);
|
||||||
|
}
|
||||||
|
[super resetBuffer];
|
||||||
|
[self fullShutdown];
|
||||||
|
paused = NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setOutputFormat:(AudioStreamBasicDescription)format withChannelConfig:(uint32_t)config {
|
||||||
|
outputFormat = format;
|
||||||
|
outputChannelConfig = config;
|
||||||
|
formatSet = YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)process {
|
||||||
|
while([self shouldContinue] == YES) {
|
||||||
|
if(paused) {
|
||||||
|
usleep(500);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
@autoreleasepool {
|
||||||
|
AudioChunk *chunk = nil;
|
||||||
|
chunk = [self convert];
|
||||||
|
if(!chunk || ![chunk frameCount]) {
|
||||||
|
if([self endOfStream] == YES) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(paused) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
usleep(500);
|
||||||
|
} else {
|
||||||
|
[self writeChunk:chunk];
|
||||||
|
chunk = nil;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (AudioChunk *)convert {
|
||||||
|
if(stopping)
|
||||||
|
return nil;
|
||||||
|
|
||||||
|
processEntered = YES;
|
||||||
|
|
||||||
|
if(stopping || [self endOfStream] == YES || [self shouldContinue] == NO) {
|
||||||
|
processEntered = NO;
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(![self peekFormat:&inputFormat channelConfig:&inputChannelConfig]) {
|
||||||
|
processEntered = NO;
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!inputFormat.mSampleRate ||
|
||||||
|
!inputFormat.mBitsPerChannel ||
|
||||||
|
!inputFormat.mChannelsPerFrame ||
|
||||||
|
!inputFormat.mBytesPerFrame ||
|
||||||
|
!inputFormat.mFramesPerPacket ||
|
||||||
|
!inputFormat.mBytesPerPacket) {
|
||||||
|
processEntered = NO;
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((formatSet && !downmix) ||
|
||||||
|
memcmp(&inputFormat, &lastInputFormat, sizeof(inputFormat)) != 0 ||
|
||||||
|
inputChannelConfig != lastInputChannelConfig) {
|
||||||
|
lastInputFormat = inputFormat;
|
||||||
|
lastInputChannelConfig = inputChannelConfig;
|
||||||
|
[self fullShutdown];
|
||||||
|
if(formatSet && ![self setup]) {
|
||||||
|
processEntered = NO;
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!downmix) {
|
||||||
|
processEntered = NO;
|
||||||
|
return [self readChunk:4096];
|
||||||
|
}
|
||||||
|
|
||||||
|
AudioChunk *chunk = [self readChunkAsFloat32:4096];
|
||||||
|
if(!chunk || ![chunk frameCount]) {
|
||||||
|
processEntered = NO;
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
double streamTimestamp = [chunk streamTimestamp];
|
||||||
|
|
||||||
|
size_t frameCount = [chunk frameCount];
|
||||||
|
NSData *sampleData = [chunk removeSamples:frameCount];
|
||||||
|
|
||||||
|
[downmix process:[sampleData bytes] frameCount:frameCount output:&outBuffer[0]];
|
||||||
|
|
||||||
|
AudioChunk *outputChunk = [[AudioChunk alloc] init];
|
||||||
|
[outputChunk setFormat:outputFormat];
|
||||||
|
if(outputChannelConfig) {
|
||||||
|
[outputChunk setChannelConfig:outputChannelConfig];
|
||||||
|
}
|
||||||
|
if([chunk isHDCD]) [outputChunk setHDCD];
|
||||||
|
[outputChunk setStreamTimestamp:streamTimestamp];
|
||||||
|
[outputChunk setStreamTimeRatio:[chunk streamTimeRatio]];
|
||||||
|
[outputChunk assignSamples:&outBuffer[0] frameCount:frameCount];
|
||||||
|
|
||||||
|
processEntered = NO;
|
||||||
|
return outputChunk;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
|
@ -283,7 +283,11 @@ static void *kDownmixProcessorContext = &kDownmixProcessorContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)process:(const void *)inBuffer frameCount:(size_t)frames output:(void *)outBuffer {
|
- (void)process:(const void *)inBuffer frameCount:(size_t)frames output:(void *)outBuffer {
|
||||||
if(inputFormat.mChannelsPerFrame > 2 && outConfig == AudioConfigStereo) {
|
if(inputFormat.mChannelsPerFrame == 2 && outConfig == AudioConfigStereo &&
|
||||||
|
inConfig == (AudioChannelSideLeft | AudioChannelSideRight)) {
|
||||||
|
// Workaround for HRTF output
|
||||||
|
memcpy(outBuffer, inBuffer, frames * outputFormat.mBytesPerPacket);
|
||||||
|
} else if(inputFormat.mChannelsPerFrame > 2 && outConfig == AudioConfigStereo) {
|
||||||
downmix_to_stereo((const float *)inBuffer, inputFormat.mChannelsPerFrame, inConfig, (float *)outBuffer, frames);
|
downmix_to_stereo((const float *)inBuffer, inputFormat.mChannelsPerFrame, inConfig, (float *)outBuffer, frames);
|
||||||
} else if(inputFormat.mChannelsPerFrame > 1 && outConfig == AudioConfigMono) {
|
} else if(inputFormat.mChannelsPerFrame > 1 && outConfig == AudioConfigMono) {
|
||||||
downmix_to_mono((const float *)inBuffer, inputFormat.mChannelsPerFrame, inConfig, (float *)outBuffer, frames);
|
downmix_to_mono((const float *)inBuffer, inputFormat.mChannelsPerFrame, inConfig, (float *)outBuffer, frames);
|
|
@ -166,6 +166,7 @@ static void *kInputNodeContext = &kInputNodeContext;
|
||||||
DSPFSurroundNode *fsurround = [bufferChain fsurround];
|
DSPFSurroundNode *fsurround = [bufferChain fsurround];
|
||||||
DSPEqualizerNode *equalizer = [bufferChain equalizer];
|
DSPEqualizerNode *equalizer = [bufferChain equalizer];
|
||||||
DSPHRTFNode *hrtf = [bufferChain hrtf];
|
DSPHRTFNode *hrtf = [bufferChain hrtf];
|
||||||
|
DSPDownmixNode *downmix = [bufferChain downmix];
|
||||||
DLog(@"SEEKING! Resetting Buffer");
|
DLog(@"SEEKING! Resetting Buffer");
|
||||||
|
|
||||||
// This resets the converter's buffer
|
// This resets the converter's buffer
|
||||||
|
@ -177,6 +178,7 @@ static void *kInputNodeContext = &kInputNodeContext;
|
||||||
[fsurround resetBuffer];
|
[fsurround resetBuffer];
|
||||||
[equalizer resetBuffer];
|
[equalizer resetBuffer];
|
||||||
[hrtf resetBuffer];
|
[hrtf resetBuffer];
|
||||||
|
[downmix resetBuffer];
|
||||||
|
|
||||||
DLog(@"Reset buffer!");
|
DLog(@"Reset buffer!");
|
||||||
|
|
||||||
|
|
|
@ -56,6 +56,9 @@
|
||||||
- (AudioStreamBasicDescription)format;
|
- (AudioStreamBasicDescription)format;
|
||||||
- (uint32_t)config;
|
- (uint32_t)config;
|
||||||
|
|
||||||
|
- (AudioStreamBasicDescription)deviceFormat;
|
||||||
|
- (uint32_t)deviceChannelConfig;
|
||||||
|
|
||||||
- (void)setVolume:(double)v;
|
- (void)setVolume:(double)v;
|
||||||
|
|
||||||
- (void)setShouldContinue:(BOOL)s;
|
- (void)setShouldContinue:(BOOL)s;
|
||||||
|
|
|
@ -136,6 +136,14 @@
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (AudioStreamBasicDescription)deviceFormat {
|
||||||
|
return [output deviceFormat];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (uint32_t)deviceChannelConfig {
|
||||||
|
return [output deviceChannelConfig];
|
||||||
|
}
|
||||||
|
|
||||||
- (void)setFormat:(AudioStreamBasicDescription *)f channelConfig:(uint32_t)channelConfig {
|
- (void)setFormat:(AudioStreamBasicDescription *)f channelConfig:(uint32_t)channelConfig {
|
||||||
format = *f;
|
format = *f;
|
||||||
config = channelConfig;
|
config = channelConfig;
|
||||||
|
@ -161,6 +169,10 @@
|
||||||
[converter setOutputFormat:format];
|
[converter setOutputFormat:format];
|
||||||
[converter inputFormatDidChange:[bufferChain inputFormat] inputConfig:[bufferChain inputConfig]];
|
[converter inputFormatDidChange:[bufferChain inputFormat] inputConfig:[bufferChain inputConfig]];
|
||||||
}
|
}
|
||||||
|
DSPDownmixNode *downmix = [bufferChain downmix];
|
||||||
|
if(downmix && output) {
|
||||||
|
[downmix setOutputFormat:[output deviceFormat] withChannelConfig:[output deviceChannelConfig]];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,6 +47,10 @@
|
||||||
8328995727CB51B700D7F028 /* SHA256Digest.h in Headers */ = {isa = PBXBuildFile; fileRef = 8328995527CB51B700D7F028 /* SHA256Digest.h */; };
|
8328995727CB51B700D7F028 /* SHA256Digest.h in Headers */ = {isa = PBXBuildFile; fileRef = 8328995527CB51B700D7F028 /* SHA256Digest.h */; };
|
||||||
8328995827CB51B700D7F028 /* SHA256Digest.m in Sources */ = {isa = PBXBuildFile; fileRef = 8328995627CB51B700D7F028 /* SHA256Digest.m */; };
|
8328995827CB51B700D7F028 /* SHA256Digest.m in Sources */ = {isa = PBXBuildFile; fileRef = 8328995627CB51B700D7F028 /* SHA256Digest.m */; };
|
||||||
8328995A27CB51C900D7F028 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8328995927CB51C900D7F028 /* Security.framework */; };
|
8328995A27CB51C900D7F028 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8328995927CB51C900D7F028 /* Security.framework */; };
|
||||||
|
833738EA2D5EA52500278628 /* DSPDownmixNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 833738E92D5EA52500278628 /* DSPDownmixNode.h */; };
|
||||||
|
833738EC2D5EA53500278628 /* DSPDownmixNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 833738EB2D5EA53500278628 /* DSPDownmixNode.m */; };
|
||||||
|
833738EF2D5EA5B700278628 /* Downmix.m in Sources */ = {isa = PBXBuildFile; fileRef = 833738EE2D5EA5B700278628 /* Downmix.m */; };
|
||||||
|
833738F02D5EA5B700278628 /* Downmix.h in Headers */ = {isa = PBXBuildFile; fileRef = 833738ED2D5EA5B700278628 /* Downmix.h */; };
|
||||||
8347C7412796C58800FA8A7D /* NSFileHandle+CreateFile.h in Headers */ = {isa = PBXBuildFile; fileRef = 8347C73F2796C58800FA8A7D /* NSFileHandle+CreateFile.h */; };
|
8347C7412796C58800FA8A7D /* NSFileHandle+CreateFile.h in Headers */ = {isa = PBXBuildFile; fileRef = 8347C73F2796C58800FA8A7D /* NSFileHandle+CreateFile.h */; };
|
||||||
8347C7422796C58800FA8A7D /* NSFileHandle+CreateFile.m in Sources */ = {isa = PBXBuildFile; fileRef = 8347C7402796C58800FA8A7D /* NSFileHandle+CreateFile.m */; };
|
8347C7422796C58800FA8A7D /* NSFileHandle+CreateFile.m in Sources */ = {isa = PBXBuildFile; fileRef = 8347C7402796C58800FA8A7D /* NSFileHandle+CreateFile.m */; };
|
||||||
834A41A9287A90AB00EB9D9B /* freesurround_decoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 834A41A5287A90AB00EB9D9B /* freesurround_decoder.h */; };
|
834A41A9287A90AB00EB9D9B /* freesurround_decoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 834A41A5287A90AB00EB9D9B /* freesurround_decoder.h */; };
|
||||||
|
@ -57,8 +61,6 @@
|
||||||
834FD4ED27AF91220063BC83 /* AudioChunk.m in Sources */ = {isa = PBXBuildFile; fileRef = 834FD4EC27AF91220063BC83 /* AudioChunk.m */; };
|
834FD4ED27AF91220063BC83 /* AudioChunk.m in Sources */ = {isa = PBXBuildFile; fileRef = 834FD4EC27AF91220063BC83 /* AudioChunk.m */; };
|
||||||
834FD4F027AF93680063BC83 /* ChunkList.h in Headers */ = {isa = PBXBuildFile; fileRef = 834FD4EE27AF93680063BC83 /* ChunkList.h */; };
|
834FD4F027AF93680063BC83 /* ChunkList.h in Headers */ = {isa = PBXBuildFile; fileRef = 834FD4EE27AF93680063BC83 /* ChunkList.h */; };
|
||||||
834FD4F127AF93680063BC83 /* ChunkList.m in Sources */ = {isa = PBXBuildFile; fileRef = 834FD4EF27AF93680063BC83 /* ChunkList.m */; };
|
834FD4F127AF93680063BC83 /* ChunkList.m in Sources */ = {isa = PBXBuildFile; fileRef = 834FD4EF27AF93680063BC83 /* ChunkList.m */; };
|
||||||
83504165286447DA006B32CC /* Downmix.h in Headers */ = {isa = PBXBuildFile; fileRef = 83504163286447DA006B32CC /* Downmix.h */; };
|
|
||||||
83504166286447DA006B32CC /* Downmix.m in Sources */ = {isa = PBXBuildFile; fileRef = 83504164286447DA006B32CC /* Downmix.m */; };
|
|
||||||
8350416D28646149006B32CC /* CoreMedia.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8350416C28646149006B32CC /* CoreMedia.framework */; };
|
8350416D28646149006B32CC /* CoreMedia.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8350416C28646149006B32CC /* CoreMedia.framework */; };
|
||||||
835C88B1279811A500E28EAE /* hdcd_decode2.h in Headers */ = {isa = PBXBuildFile; fileRef = 835C88AF279811A500E28EAE /* hdcd_decode2.h */; };
|
835C88B1279811A500E28EAE /* hdcd_decode2.h in Headers */ = {isa = PBXBuildFile; fileRef = 835C88AF279811A500E28EAE /* hdcd_decode2.h */; };
|
||||||
835C88B2279811A500E28EAE /* hdcd_decode2.c in Sources */ = {isa = PBXBuildFile; fileRef = 835C88B0279811A500E28EAE /* hdcd_decode2.c */; };
|
835C88B2279811A500E28EAE /* hdcd_decode2.c in Sources */ = {isa = PBXBuildFile; fileRef = 835C88B0279811A500E28EAE /* hdcd_decode2.c */; };
|
||||||
|
@ -173,6 +175,10 @@
|
||||||
8328995527CB51B700D7F028 /* SHA256Digest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SHA256Digest.h; path = ../../Utils/SHA256Digest.h; sourceTree = "<group>"; };
|
8328995527CB51B700D7F028 /* SHA256Digest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SHA256Digest.h; path = ../../Utils/SHA256Digest.h; sourceTree = "<group>"; };
|
||||||
8328995627CB51B700D7F028 /* SHA256Digest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SHA256Digest.m; path = ../../Utils/SHA256Digest.m; sourceTree = "<group>"; };
|
8328995627CB51B700D7F028 /* SHA256Digest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SHA256Digest.m; path = ../../Utils/SHA256Digest.m; sourceTree = "<group>"; };
|
||||||
8328995927CB51C900D7F028 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; };
|
8328995927CB51C900D7F028 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; };
|
||||||
|
833738E92D5EA52500278628 /* DSPDownmixNode.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DSPDownmixNode.h; sourceTree = "<group>"; };
|
||||||
|
833738EB2D5EA53500278628 /* DSPDownmixNode.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = DSPDownmixNode.m; sourceTree = "<group>"; };
|
||||||
|
833738ED2D5EA5B700278628 /* Downmix.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Downmix.h; sourceTree = "<group>"; };
|
||||||
|
833738EE2D5EA5B700278628 /* Downmix.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Downmix.m; sourceTree = "<group>"; };
|
||||||
8347C73F2796C58800FA8A7D /* NSFileHandle+CreateFile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSFileHandle+CreateFile.h"; path = "../../Utils/NSFileHandle+CreateFile.h"; sourceTree = "<group>"; };
|
8347C73F2796C58800FA8A7D /* NSFileHandle+CreateFile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSFileHandle+CreateFile.h"; path = "../../Utils/NSFileHandle+CreateFile.h"; sourceTree = "<group>"; };
|
||||||
8347C7402796C58800FA8A7D /* NSFileHandle+CreateFile.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSFileHandle+CreateFile.m"; path = "../../Utils/NSFileHandle+CreateFile.m"; sourceTree = "<group>"; };
|
8347C7402796C58800FA8A7D /* NSFileHandle+CreateFile.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSFileHandle+CreateFile.m"; path = "../../Utils/NSFileHandle+CreateFile.m"; sourceTree = "<group>"; };
|
||||||
834A41A5287A90AB00EB9D9B /* freesurround_decoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = freesurround_decoder.h; sourceTree = "<group>"; };
|
834A41A5287A90AB00EB9D9B /* freesurround_decoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = freesurround_decoder.h; sourceTree = "<group>"; };
|
||||||
|
@ -183,8 +189,6 @@
|
||||||
834FD4EC27AF91220063BC83 /* AudioChunk.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AudioChunk.m; sourceTree = "<group>"; };
|
834FD4EC27AF91220063BC83 /* AudioChunk.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AudioChunk.m; sourceTree = "<group>"; };
|
||||||
834FD4EE27AF93680063BC83 /* ChunkList.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ChunkList.h; sourceTree = "<group>"; };
|
834FD4EE27AF93680063BC83 /* ChunkList.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ChunkList.h; sourceTree = "<group>"; };
|
||||||
834FD4EF27AF93680063BC83 /* ChunkList.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ChunkList.m; sourceTree = "<group>"; };
|
834FD4EF27AF93680063BC83 /* ChunkList.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ChunkList.m; sourceTree = "<group>"; };
|
||||||
83504163286447DA006B32CC /* Downmix.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Downmix.h; sourceTree = "<group>"; };
|
|
||||||
83504164286447DA006B32CC /* Downmix.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Downmix.m; sourceTree = "<group>"; };
|
|
||||||
8350416C28646149006B32CC /* CoreMedia.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMedia.framework; path = System/Library/Frameworks/CoreMedia.framework; sourceTree = SDKROOT; };
|
8350416C28646149006B32CC /* CoreMedia.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMedia.framework; path = System/Library/Frameworks/CoreMedia.framework; sourceTree = SDKROOT; };
|
||||||
835C88AF279811A500E28EAE /* hdcd_decode2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = hdcd_decode2.h; sourceTree = "<group>"; };
|
835C88AF279811A500E28EAE /* hdcd_decode2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = hdcd_decode2.h; sourceTree = "<group>"; };
|
||||||
835C88B0279811A500E28EAE /* hdcd_decode2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = hdcd_decode2.c; sourceTree = "<group>"; };
|
835C88B0279811A500E28EAE /* hdcd_decode2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = hdcd_decode2.c; sourceTree = "<group>"; };
|
||||||
|
@ -378,8 +382,6 @@
|
||||||
834FD4EF27AF93680063BC83 /* ChunkList.m */,
|
834FD4EF27AF93680063BC83 /* ChunkList.m */,
|
||||||
8EC1225D0B993BD500C5B3AD /* ConverterNode.h */,
|
8EC1225D0B993BD500C5B3AD /* ConverterNode.h */,
|
||||||
8EC1225E0B993BD500C5B3AD /* ConverterNode.m */,
|
8EC1225E0B993BD500C5B3AD /* ConverterNode.m */,
|
||||||
83504163286447DA006B32CC /* Downmix.h */,
|
|
||||||
83504164286447DA006B32CC /* Downmix.m */,
|
|
||||||
17D21C7A0B8BE4BA00D1EBDE /* InputNode.h */,
|
17D21C7A0B8BE4BA00D1EBDE /* InputNode.h */,
|
||||||
17D21C7B0B8BE4BA00D1EBDE /* InputNode.m */,
|
17D21C7B0B8BE4BA00D1EBDE /* InputNode.m */,
|
||||||
17D21C7C0B8BE4BA00D1EBDE /* Node.h */,
|
17D21C7C0B8BE4BA00D1EBDE /* Node.h */,
|
||||||
|
@ -538,6 +540,8 @@
|
||||||
83A349692D5C3F430096D530 /* DSP */ = {
|
83A349692D5C3F430096D530 /* DSP */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
833738ED2D5EA5B700278628 /* Downmix.h */,
|
||||||
|
833738EE2D5EA5B700278628 /* Downmix.m */,
|
||||||
83F8431E2D5C6272008C123B /* HeadphoneFilter.h */,
|
83F8431E2D5C6272008C123B /* HeadphoneFilter.h */,
|
||||||
83F8431F2D5C6272008C123B /* HeadphoneFilter.mm */,
|
83F8431F2D5C6272008C123B /* HeadphoneFilter.mm */,
|
||||||
83A349702D5C41810096D530 /* FSurroundFilter.h */,
|
83A349702D5C41810096D530 /* FSurroundFilter.h */,
|
||||||
|
@ -550,6 +554,8 @@
|
||||||
83A349762D5C50B20096D530 /* DSPHRTFNode.m */,
|
83A349762D5C50B20096D530 /* DSPHRTFNode.m */,
|
||||||
83F843222D5C66DA008C123B /* DSPEqualizerNode.h */,
|
83F843222D5C66DA008C123B /* DSPEqualizerNode.h */,
|
||||||
83F843242D5C66E9008C123B /* DSPEqualizerNode.m */,
|
83F843242D5C66E9008C123B /* DSPEqualizerNode.m */,
|
||||||
|
833738E92D5EA52500278628 /* DSPDownmixNode.h */,
|
||||||
|
833738EB2D5EA53500278628 /* DSPDownmixNode.m */,
|
||||||
);
|
);
|
||||||
path = DSP;
|
path = DSP;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -575,9 +581,9 @@
|
||||||
8399CF2C27B5D1D5008751F1 /* NSDictionary+Merge.h in Headers */,
|
8399CF2C27B5D1D5008751F1 /* NSDictionary+Merge.h in Headers */,
|
||||||
17D21CA90B8BE4BA00D1EBDE /* OutputNode.h in Headers */,
|
17D21CA90B8BE4BA00D1EBDE /* OutputNode.h in Headers */,
|
||||||
8328995427CB511000D7F028 /* RedundantPlaylistDataStore.h in Headers */,
|
8328995427CB511000D7F028 /* RedundantPlaylistDataStore.h in Headers */,
|
||||||
83504165286447DA006B32CC /* Downmix.h in Headers */,
|
|
||||||
839E56E52879450300DFB5F4 /* HrtfData.h in Headers */,
|
839E56E52879450300DFB5F4 /* HrtfData.h in Headers */,
|
||||||
83B74281289E027F005AAC28 /* CogAudio-Bridging-Header.h in Headers */,
|
83B74281289E027F005AAC28 /* CogAudio-Bridging-Header.h in Headers */,
|
||||||
|
833738F02D5EA5B700278628 /* Downmix.h in Headers */,
|
||||||
17D21CC70B8BE4BA00D1EBDE /* Status.h in Headers */,
|
17D21CC70B8BE4BA00D1EBDE /* Status.h in Headers */,
|
||||||
17D21CF30B8BE5EF00D1EBDE /* CogSemaphore.h in Headers */,
|
17D21CF30B8BE5EF00D1EBDE /* CogSemaphore.h in Headers */,
|
||||||
835DD2682ACAF1D90057E319 /* OutputCoreAudio.h in Headers */,
|
835DD2682ACAF1D90057E319 /* OutputCoreAudio.h in Headers */,
|
||||||
|
@ -611,6 +617,7 @@
|
||||||
835FAC5E27BCA14D00BA8562 /* BadSampleCleaner.h in Headers */,
|
835FAC5E27BCA14D00BA8562 /* BadSampleCleaner.h in Headers */,
|
||||||
8E8D3D2F0CBAEE6E00135C1B /* AudioContainer.h in Headers */,
|
8E8D3D2F0CBAEE6E00135C1B /* AudioContainer.h in Headers */,
|
||||||
B0575F2D0D687A0800411D77 /* Helper.h in Headers */,
|
B0575F2D0D687A0800411D77 /* Helper.h in Headers */,
|
||||||
|
833738EA2D5EA52500278628 /* DSPDownmixNode.h in Headers */,
|
||||||
07DB5F3E0ED353A900C2E3EF /* AudioMetadataWriter.h in Headers */,
|
07DB5F3E0ED353A900C2E3EF /* AudioMetadataWriter.h in Headers */,
|
||||||
839E56EA28794F6300DFB5F4 /* HrtfTypes.h in Headers */,
|
839E56EA28794F6300DFB5F4 /* HrtfTypes.h in Headers */,
|
||||||
);
|
);
|
||||||
|
@ -692,16 +699,17 @@
|
||||||
83A349772D5C50B20096D530 /* DSPHRTFNode.m in Sources */,
|
83A349772D5C50B20096D530 /* DSPHRTFNode.m in Sources */,
|
||||||
17D21CA60B8BE4BA00D1EBDE /* InputNode.m in Sources */,
|
17D21CA60B8BE4BA00D1EBDE /* InputNode.m in Sources */,
|
||||||
83A3496A2D5C3F430096D530 /* DSPRubberbandNode.m in Sources */,
|
83A3496A2D5C3F430096D530 /* DSPRubberbandNode.m in Sources */,
|
||||||
83504166286447DA006B32CC /* Downmix.m in Sources */,
|
|
||||||
8399CF2D27B5D1D5008751F1 /* NSDictionary+Merge.m in Sources */,
|
8399CF2D27B5D1D5008751F1 /* NSDictionary+Merge.m in Sources */,
|
||||||
83F843252D5C66E9008C123B /* DSPEqualizerNode.m in Sources */,
|
83F843252D5C66E9008C123B /* DSPEqualizerNode.m in Sources */,
|
||||||
834A41AB287A90AB00EB9D9B /* channelmaps.cpp in Sources */,
|
834A41AB287A90AB00EB9D9B /* channelmaps.cpp in Sources */,
|
||||||
|
833738EC2D5EA53500278628 /* DSPDownmixNode.m in Sources */,
|
||||||
831A50162865A8800049CFE4 /* rsstate.cpp in Sources */,
|
831A50162865A8800049CFE4 /* rsstate.cpp in Sources */,
|
||||||
17D21CA80B8BE4BA00D1EBDE /* Node.m in Sources */,
|
17D21CA80B8BE4BA00D1EBDE /* Node.m in Sources */,
|
||||||
17D21CAA0B8BE4BA00D1EBDE /* OutputNode.m in Sources */,
|
17D21CAA0B8BE4BA00D1EBDE /* OutputNode.m in Sources */,
|
||||||
835C88B2279811A500E28EAE /* hdcd_decode2.c in Sources */,
|
835C88B2279811A500E28EAE /* hdcd_decode2.c in Sources */,
|
||||||
835FAC5F27BCA14D00BA8562 /* BadSampleCleaner.m in Sources */,
|
835FAC5F27BCA14D00BA8562 /* BadSampleCleaner.m in Sources */,
|
||||||
834FD4ED27AF91220063BC83 /* AudioChunk.m in Sources */,
|
834FD4ED27AF91220063BC83 /* AudioChunk.m in Sources */,
|
||||||
|
833738EF2D5EA5B700278628 /* Downmix.m in Sources */,
|
||||||
17D21CF40B8BE5EF00D1EBDE /* CogSemaphore.m in Sources */,
|
17D21CF40B8BE5EF00D1EBDE /* CogSemaphore.m in Sources */,
|
||||||
839B83FA286D91ED00F529EE /* VisualizationController.swift in Sources */,
|
839B83FA286D91ED00F529EE /* VisualizationController.swift in Sources */,
|
||||||
839E89A02D5DBA1700A13526 /* VisualizationNode.m in Sources */,
|
839E89A02D5DBA1700A13526 /* VisualizationNode.m in Sources */,
|
||||||
|
|
|
@ -22,8 +22,6 @@ using std::atomic_long;
|
||||||
#import <stdatomic.h>
|
#import <stdatomic.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#import "Downmix.h"
|
|
||||||
|
|
||||||
#import <CogAudio/CogAudio-Swift.h>
|
#import <CogAudio/CogAudio-Swift.h>
|
||||||
|
|
||||||
#import <simd/simd.h>
|
#import <simd/simd.h>
|
||||||
|
@ -93,8 +91,6 @@ using std::atomic_long;
|
||||||
|
|
||||||
size_t _bufferSize;
|
size_t _bufferSize;
|
||||||
|
|
||||||
DownmixProcessor *downmixer;
|
|
||||||
|
|
||||||
VisualizationController *visController;
|
VisualizationController *visController;
|
||||||
|
|
||||||
int inputRemain;
|
int inputRemain;
|
||||||
|
@ -108,7 +104,6 @@ using std::atomic_long;
|
||||||
float *samplePtr;
|
float *samplePtr;
|
||||||
float tempBuffer[512 * 32];
|
float tempBuffer[512 * 32];
|
||||||
float inputBuffer[4096 * 32]; // 4096 samples times maximum supported channel count
|
float inputBuffer[4096 * 32]; // 4096 samples times maximum supported channel count
|
||||||
float downmixBuffer[4096 * 8];
|
|
||||||
|
|
||||||
#ifdef OUTPUT_LOG
|
#ifdef OUTPUT_LOG
|
||||||
FILE *_logFile;
|
FILE *_logFile;
|
||||||
|
@ -133,4 +128,7 @@ using std::atomic_long;
|
||||||
|
|
||||||
- (void)sustainHDCD;
|
- (void)sustainHDCD;
|
||||||
|
|
||||||
|
- (AudioStreamBasicDescription)deviceFormat;
|
||||||
|
- (uint32_t)deviceChannelConfig;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -41,16 +41,6 @@ static void *kOutputCoreAudioContext = &kOutputCoreAudioContext;
|
||||||
uint32_t origConfig = config;
|
uint32_t origConfig = config;
|
||||||
origFormat = format;
|
origFormat = format;
|
||||||
|
|
||||||
UInt32 srcChannels = format.mChannelsPerFrame;
|
|
||||||
UInt32 dstChannels = deviceFormat.mChannelsPerFrame;
|
|
||||||
if(srcChannels != dstChannels) {
|
|
||||||
format.mChannelsPerFrame = dstChannels;
|
|
||||||
format.mBytesPerFrame = ((format.mBitsPerChannel + 7) / 8) * dstChannels;
|
|
||||||
format.mBytesPerPacket = format.mBytesPerFrame * format.mFramesPerPacket;
|
|
||||||
downmixer = [[DownmixProcessor alloc] initWithInputFormat:origFormat inputConfig:origConfig andOutputFormat:format outputConfig:deviceChannelConfig];
|
|
||||||
} else {
|
|
||||||
downmixer = nil;
|
|
||||||
}
|
|
||||||
if(!streamFormatStarted || config != realStreamChannelConfig || memcmp(&realStreamFormat, &format, sizeof(format)) != 0) {
|
if(!streamFormatStarted || config != realStreamChannelConfig || memcmp(&realStreamFormat, &format, sizeof(format)) != 0) {
|
||||||
realStreamFormat = format;
|
realStreamFormat = format;
|
||||||
realStreamChannelConfig = config;
|
realStreamChannelConfig = config;
|
||||||
|
@ -598,18 +588,13 @@ current_device_listener(AudioObjectID inObjectID, UInt32 inNumberAddresses, cons
|
||||||
|
|
||||||
samplePtr = &inputBuffer[0];
|
samplePtr = &inputBuffer[0];
|
||||||
|
|
||||||
if(samplesRendered) {
|
|
||||||
if(downmixer) {
|
|
||||||
[downmixer process:samplePtr frameCount:samplesRendered output:&downmixBuffer[0]];
|
|
||||||
samplePtr = &downmixBuffer[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef OUTPUT_LOG
|
#ifdef OUTPUT_LOG
|
||||||
|
if(samplesRendered) {
|
||||||
size_t dataByteSize = samplesRendered * sizeof(float) * deviceFormat.mChannelsPerFrame;
|
size_t dataByteSize = samplesRendered * sizeof(float) * deviceFormat.mChannelsPerFrame;
|
||||||
|
|
||||||
fwrite(samplePtr, 1, dataByteSize, _logFile);
|
fwrite(samplePtr, 1, dataByteSize, _logFile);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return samplesRendered;
|
return samplesRendered;
|
||||||
}
|
}
|
||||||
|
@ -687,8 +672,6 @@ current_device_listener(AudioObjectID inObjectID, UInt32 inNumberAddresses, cons
|
||||||
outputDeviceID = -1;
|
outputDeviceID = -1;
|
||||||
restarted = NO;
|
restarted = NO;
|
||||||
|
|
||||||
downmixer = nil;
|
|
||||||
|
|
||||||
lastClippedSampleRate = 0.0;
|
lastClippedSampleRate = 0.0;
|
||||||
|
|
||||||
inputRemain = 0;
|
inputRemain = 0;
|
||||||
|
@ -856,4 +839,12 @@ current_device_listener(AudioObjectID inObjectID, UInt32 inNumberAddresses, cons
|
||||||
shouldPlayOutBuffer = s;
|
shouldPlayOutBuffer = s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (AudioStreamBasicDescription)deviceFormat {
|
||||||
|
return deviceFormat;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (uint32_t)deviceChannelConfig {
|
||||||
|
return deviceChannelConfig;
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
Loading…
Reference in a new issue