diff --git a/ExampleApp/ExampleApp.xcodeproj/project.pbxproj b/ExampleApp/ExampleApp.xcodeproj/project.pbxproj index 046b397..c1d509c 100644 --- a/ExampleApp/ExampleApp.xcodeproj/project.pbxproj +++ b/ExampleApp/ExampleApp.xcodeproj/project.pbxproj @@ -27,6 +27,7 @@ A17FFB6318A0028300BAA7FF /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A17FFB6218A0028300BAA7FF /* AudioToolbox.framework */; }; A17FFB6918A002E400BAA7FF /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1F5E491189EB3F20070B03F /* AVFoundation.framework */; }; A1EBEE64188DE34500681B04 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1EBEE63188DE34500681B04 /* SystemConfiguration.framework */; }; + A1F3410A1908185900CA7755 /* Accelerate.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1F341091908185900CA7755 /* Accelerate.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -65,6 +66,7 @@ A142571C18907861005F0129 /* airplane.aac */ = {isa = PBXFileReference; lastKnownFileType = file; path = airplane.aac; sourceTree = ""; }; A17FFB6218A0028300BAA7FF /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; }; A1EBEE63188DE34500681B04 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; + A1F341091908185900CA7755 /* Accelerate.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Accelerate.framework; path = System/Library/Frameworks/Accelerate.framework; sourceTree = SDKROOT; }; A1F5E48F189EB3CB0070B03F /* AudioUnit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioUnit.framework; path = System/Library/Frameworks/AudioUnit.framework; sourceTree = SDKROOT; }; A1F5E491189EB3F20070B03F /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = System/Library/Frameworks/AVFoundation.framework; sourceTree = SDKROOT; }; /* End PBXFileReference section */ @@ -74,6 +76,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + A1F3410A1908185900CA7755 /* Accelerate.framework in Frameworks */, A17FFB6918A002E400BAA7FF /* AVFoundation.framework in Frameworks */, A17FFB6318A0028300BAA7FF /* AudioToolbox.framework in Frameworks */, A1EBEE64188DE34500681B04 /* SystemConfiguration.framework in Frameworks */, @@ -119,6 +122,7 @@ A1115933188D686000641365 /* Frameworks */ = { isa = PBXGroup; children = ( + A1F341091908185900CA7755 /* Accelerate.framework */, A17FFB6218A0028300BAA7FF /* AudioToolbox.framework */, A1F5E491189EB3F20070B03F /* AVFoundation.framework */, A1F5E48F189EB3CB0070B03F /* AudioUnit.framework */, diff --git a/StreamingKit/StreamingKit.xcodeproj/project.pbxproj b/StreamingKit/StreamingKit.xcodeproj/project.pbxproj index bc96c98..db84c6c 100644 --- a/StreamingKit/StreamingKit.xcodeproj/project.pbxproj +++ b/StreamingKit/StreamingKit.xcodeproj/project.pbxproj @@ -37,6 +37,8 @@ A1E7C503188D5E550010896F /* STKDataSourceWrapper.m in Sources */ = {isa = PBXBuildFile; fileRef = A1E7C4FA188D5E550010896F /* STKDataSourceWrapper.m */; }; A1E7C504188D5E550010896F /* STKHTTPDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = A1E7C4FC188D5E550010896F /* STKHTTPDataSource.m */; }; A1E7C505188D5E550010896F /* STKLocalFileDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = A1E7C4FE188D5E550010896F /* STKLocalFileDataSource.m */; }; + A1F341041908183300CA7755 /* Accelerate.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1F341031908183300CA7755 /* Accelerate.framework */; }; + A1F341081908183A00CA7755 /* Accelerate.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1F341071908183A00CA7755 /* Accelerate.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -125,6 +127,8 @@ A1E7C4FD188D5E550010896F /* STKLocalFileDataSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STKLocalFileDataSource.h; sourceTree = ""; }; A1E7C4FE188D5E550010896F /* STKLocalFileDataSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STKLocalFileDataSource.m; sourceTree = ""; }; A1E7C507188D62D20010896F /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; + A1F341031908183300CA7755 /* Accelerate.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Accelerate.framework; path = System/Library/Frameworks/Accelerate.framework; sourceTree = SDKROOT; }; + A1F341071908183A00CA7755 /* Accelerate.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Accelerate.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk/System/Library/Frameworks/Accelerate.framework; sourceTree = DEVELOPER_DIR; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -132,6 +136,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + A1F341081908183A00CA7755 /* Accelerate.framework in Frameworks */, A1A4996B189E744400E2A2E2 /* Cocoa.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -150,6 +155,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + A1F341041908183300CA7755 /* Accelerate.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -248,6 +254,8 @@ A1E7C4CA188D57F50010896F /* Frameworks */ = { isa = PBXGroup; children = ( + A1F341071908183A00CA7755 /* Accelerate.framework */, + A1F341031908183300CA7755 /* Accelerate.framework */, A1A499F6189E79EA00E2A2E2 /* AudioToolbox.framework */, A1C9767618981BFE0057F881 /* AudioUnit.framework */, A1E7C507188D62D20010896F /* UIKit.framework */, diff --git a/StreamingKit/StreamingKit/STKAudioPlayer.h b/StreamingKit/StreamingKit/STKAudioPlayer.h index 0ce6d53..577f298 100644 --- a/StreamingKit/StreamingKit/STKAudioPlayer.h +++ b/StreamingKit/StreamingKit/STKAudioPlayer.h @@ -146,6 +146,8 @@ typedef void(^STKFrameFilter)(UInt32 channelsPerFrame, UInt32 bytesPerFrame, UIn @property (readwrite) BOOL meteringEnabled; /// Enables or disables the EQ @property (readwrite) BOOL equalizerEnabled; +/// Enables or disables the spectrum analyzer (fft) +@property (readwrite) BOOL spectrumAnalyzerEnabled; /// Returns an array of STKFrameFilterEntry objects representing the filters currently in use @property (readonly) NSArray* frameFilters; /// Returns the items pending to be played (includes buffering and upcoming items but does not include the current item) diff --git a/StreamingKit/StreamingKit/STKAudioPlayer.m b/StreamingKit/StreamingKit/STKAudioPlayer.m index 30ded81..9f7ac6d 100644 --- a/StreamingKit/StreamingKit/STKAudioPlayer.m +++ b/StreamingKit/StreamingKit/STKAudioPlayer.m @@ -40,6 +40,7 @@ #import "STKQueueEntry.h" #import "NSMutableArray+STKAudioPlayer.h" #import "libkern/OSAtomic.h" +#include #import #ifndef DBL_MAX @@ -189,6 +190,7 @@ static AudioStreamBasicDescription canonicalAudioStreamBasicDescription; BOOL meteringEnabled; BOOL equalizerOn; BOOL equalizerEnabled; + BOOL spectrumAnalyzerEnabled; STKAudioPlayerOptions options; NSMutableArray* converterNodes; @@ -253,6 +255,12 @@ static AudioStreamBasicDescription canonicalAudioStreamBasicDescription; pthread_mutex_t mainThreadSyncCallMutex; pthread_cond_t mainThreadSyncCallReadyCondition; + float* obtainedReal; + float* originalReal; + int fftStride; + FFTSetup setupReal; + DSPSplitComplex fftInput; + volatile BOOL waiting; volatile double requestedSeekTime; volatile BOOL disposeWasRequested; @@ -470,6 +478,7 @@ static void AudioFileStreamPacketsProc(void* clientData, UInt32 numberBytes, UIn self->volume = 1.0; self->equalizerEnabled = optionsIn.equalizerBandFrequencies[0] != 0; + self->spectrumAnalyzerEnabled = NO; PopulateOptionsWithDefault(&options); @@ -578,6 +587,8 @@ static void AudioFileStreamPacketsProc(void* clientData, UInt32 numberBytes, UIn pthread_cond_destroy(&mainThreadSyncCallReadyCondition); free(readBuffer); + free(originalReal); + free(obtainedReal); } -(void) startSystemBackgroundTask @@ -2912,6 +2923,50 @@ static OSStatus OutputRenderCallback(void* inRefCon, AudioUnitRenderActionFlags* return averagePowerDb[channelNumber]; } +-(BOOL) spectrumAnalyzerEnabled +{ + return self->spectrumAnalyzerEnabled; +} + +-(void) setSpectrumAnalyzerEnabled:(BOOL)value +{ + if (self->spectrumAnalyzerEnabled == value) + { + return; + } + + self->spectrumAnalyzerEnabled = value; + + if (!value) + { + [self removeFrameFilterWithName:@"STKSpectrumAnalyzerFilter"]; + } + else + { + if (!obtainedReal) + { + int maxSamples = 4096; + int log2n = log2f(maxSamples); + int n = 1 << log2n; + + fftStride = 1; + int nOver2 = maxSamples / 2; + + fftInput.realp = (float*)calloc(nOver2, sizeof(float)); + fftInput.imagp =(float*)calloc(nOver2, sizeof(float)); + + obtainedReal = (float*)calloc(n, sizeof(float)); + originalReal = (float*)calloc(n, sizeof(float)); + + setupReal = vDSP_create_fftsetup(log2n, FFT_RADIX2); + } + + [self appendFrameFilterWithName:@"STKSpectrumAnalyzerFilter" block:^(UInt32 channelsPerFrame, UInt32 bytesPerFrame, UInt32 frameCount, void* frames) + { + }]; + } +} + -(BOOL) meteringEnabled { return self->meteringEnabled; @@ -2941,11 +2996,12 @@ static OSStatus OutputRenderCallback(void* inRefCon, AudioUnitRenderActionFlags* { return; } + + self->meteringEnabled = value; if (!value) { [self removeFrameFilterWithName:@"STKMeteringFilter"]; - self->meteringEnabled = NO; } else {