Reputation: 16715
I'm attempting to filter out frequencies below a specified threshold with AudioKit. I'm using AKHighPassFilter
to accomplish this.
func playSound(duration: Int, frequencyRange: Range<Double>) {
generator = AKOperationGenerator() { parameters in
let volume = AKOperation.sineWave(frequency: parameters[0]).scale(minimum: 0, maximum: 0.1)
let jitter = AKOperation.jitter(amplitude: parameters[1], minimumFrequency: lowerFrequency, maximumFrequency: upperFrequency)
return AKOperation.sineWave(frequency: jitter, amplitude: volume)
}
generator!.parameters = [baseFrequency, amplitude]
// Exception thrown at this line after method called 1 time
var highPassFilter = AKHighPassFilter(generator)
highPassFilter.cutoffFrequency = frequencyRange.lowerBound
highPassFilter.resonance = 0
AudioKit.output = highPassFilter
AudioKit.start()
generator?.play()
}
The first time I call playSound(duration:, frequencyRange:)
, it works fine. Once I stop AudioKit and attempt to play a sound a second time, an exception is thrown at this line:
var highPassFilter = AKHighPassFilter(generator)
Here is the console output from the crash:
2017-05-01 14:32:01.169 MyApp[18123:3459824] *** Terminating app due to uncaught exception 'com.apple.coreaudio.avfaudio', reason: 'required condition is false: [_nodes containsObject: node]'
*** First throw call stack:
(
0 CoreFoundation 0x0000000109ea7b0b __exceptionPreprocess + 171
1 libobjc.A.dylib 0x000000010990c141 objc_exception_throw + 48
2 CoreFoundation 0x0000000109eabcf2 +[NSException raise:format:arguments:] + 98
3 AVFAudio 0x000000010cdc3a9e _Z19AVAE_RaiseExceptionP8NSStringz + 158
4 AVFAudio 0x000000010cdc9cbb _ZN17AVAudioEngineImpl10DetachNodeEP11AVAudioNodeb + 421
5 AVFAudio 0x000000010cdc9ad0 -[AVAudioEngine detachNode:] + 67
6 AudioKit 0x0000000108d3bee4 _TToFC8AudioKit6AKNodeD + 84
7 libobjc.A.dylib 0x0000000109920b8e _ZN11objc_object17sidetable_releaseEb + 202
8 AudioKit 0x0000000108d39a99 _TToFC8AudioKit16AKHighPassFilterE + 25
9 libobjc.A.dylib 0x000000010990a9bc _ZL27object_cxxDestructFromClassP11objc_objectP10objc_class + 127
10 libobjc.A.dylib 0x0000000109916d34 objc_destructInstance + 129
11 libobjc.A.dylib 0x0000000109916d66 object_dispose + 22
12 AudioKit 0x0000000108d3bf1b _TToFC8AudioKit6AKNodeD + 139
13 libobjc.A.dylib 0x0000000109920b8e _ZN11objc_object17sidetable_releaseEb + 202
14 MyApp 0x00000001087301ec _TFC7MyApp11SoundPlayerClass9playSoundfT8durationSi14frequencyRangeGVs5RangeSd__T_ + 988
15 MyApp 0x000000010873a1a4 _TFC7MyApp18MainViewController13playFrequencyfCS_12FrostyButtonT_ + 2276
16 MyApp 0x000000010873a4fa _TToFC7MyApp18MainViewController13playFrequencyfCS_12FrostyButtonT_ + 58
17 UIKit 0x000000010ab63d22 -[UIApplication sendAction:to:from:forEvent:] + 83
18 UIKit 0x000000010ace825c -[UIControl sendAction:to:forEvent:] + 67
19 UIKit 0x000000010ace8577 -[UIControl _sendActionsForEvents:withEvent:] + 450
20 UIKit 0x000000010ace74b2 -[UIControl touchesEnded:withEvent:] + 618
21 UIKit 0x000000010abd149a -[UIWindow _sendTouchesForEvent:] + 2707
22 UIKit 0x000000010abd2bb0 -[UIWindow sendEvent:] + 4114
23 UIKit 0x000000010ab7f7b0 -[UIApplication sendEvent:] + 352
24 UIKit 0x000000011e3c075c -[UIApplicationAccessibility sendEvent:] + 85
25 UIKit 0x000000010b362adc __dispatchPreprocessedEventFromEventQueue + 2926
26 UIKit 0x000000010b35aa3a __handleEventQueue + 1122
27 UIKit 0x000000010b35bd08 __handleEventQueue + 5936
28 CoreFoundation 0x0000000109e4dc01 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
29 CoreFoundation 0x0000000109e330cf __CFRunLoopDoSources0 + 527
30 CoreFoundation 0x0000000109e325ff __CFRunLoopRun + 911
31 CoreFoundation 0x0000000109e32016 CFRunLoopRunSpecific + 406
32 GraphicsServices 0x000000010ecd4a24 GSEventRunModal + 62
33 UIKit 0x000000010ab620d4 UIApplicationMain + 159
34 MyApp 0x000000010872cb77 main + 55
35 libdyld.dylib 0x000000010fbaf65d start + 1
36 ??? 0x0000000000000001 0x0 + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
Prior to adding AKHighPassFilter
, the method worked fine. I welcome suggestions re: how to resolve this crash. Thank you for reading.
Upvotes: 2
Views: 457
Reputation: 1006
I think the main problem here is that you are recreating all your objects on every playSound call as well as setting the AudioKit.output in your play method everytime it's called. What you want to do is to create your object chain in an initialization routine, then just change parameters as needed after that. All the connections only need to be established once. One technique is to use AKMixer as your input or output and add and remove nodes from it. For example a high pass filter could be filters the output of an AKMixer. This mixer could have any number of nodes attached to it. AVAudioEngine can be somewhat touchy about nodes removed or added when it's running.
Upvotes: 1