Search code examples
iosswiftaudiokit

AudioKit Swift 5 - How do I stop shrieking noise when starting/stopping AKFMOscillator?


I am using Swift 5 and AudioKit to develop an application where the user can play tones at different frequencies. When starting my Oscillator there is a hideous noise almost like scratching but very high pitched. In my code below you can see I have outline the ramp duration, I was under the impression that this would resolve the popping/clicking you get when working with waveform audio but instead of a click there is now this ugly noise. This happens on both the IOS Simulator inside Xcode and when building to my device.

func playTone(){

     let osc = AKFMOscillator(waveform:AKTable(.sine), amplitude: 0)
     osc.rampDuration = 0.1 //Changing ramp duration makes the scratch noise last longer.
     osc.baseFrequency = 1
     osc.carrierMultiplier = 1000 //Frequency of tone
     osc.modulatingMultiplier = 5
     osc.modulationIndex = osc.carrierMultiplier/100*4

     AudioKit.output = osc

     try? AudioKit.start()
     osc.start()
     osc.amplitude = 1.0
     sleep(3)
     osc.amplitude = 0
     try? AudioKit.stop()
}

Is this a bug with AudioKit? Or is there something I can change in my code to fix this?


Solution

  • So, what's happening is that your initializing the FM Oscillator with certain default values and then changing them, but not actually right away, because the rampDuration is applied between the initialization values and the values you've set afterwards. This can be a little confusing because as you read the code, it seems like you set the values before AudioKit is started. Next, the ramping is happening in a linear fashion over time, which passes through a heck of a lot of different values of the carrier multiplier basically giving you a vastly different sound on every minor increment. So, I would suggest you initialize the oscillator with values close to or identical to your final result, and only let the amplitude be ramped to avoid clicking:

    let osc = AKFMOscillator(waveform:AKTable(.sine),
                             baseFrequency: 1,
                             carrierMultiplier: 1000,
                             modulatingMultiplier: 5,
                             modulationIndex: 5.0/400.0,
                             amplitude: 0)
    
    osc.rampDuration = 5 //Changing ramp duration makes the scratch noise last longer.
    
    AudioKit.output = oscillator
    
    ...
    

    "scratchy" sound gone.