Skip to content

It's not working anymore!  #5

@Treata11

Description

@Treata11

Greetings

The sample project isn't working anymore ... Many of the AudioKit's APIs have changed since then.
I've actually read the AudioKit's migration guide & changed the Conductor accordingly:

import AudioKit
import Foundation

/// The persistent data object of the application (it does the audio processing and publishes changes to the UI)
final class Conductor : ObservableObject {

    /// Single shared data model
    static let shared = Conductor()
    
    /// default microphone
//    let mic = Microphone()
    let engine = AudioEngine()
    // No usage for now?
    static let player = AudioPlayer()
    
    let mic: AudioEngine.InputNode
    
    /// mixing node for microphone input - routes to plotting and recording paths
    let micMixer = Mixer()
    
    /// time interval in seconds for repeating timer callback
    let refreshTimeInterval : Double = 0.02
    
    /// tap for the fft data
    let fft : FFTTap
    
    /// size of fft
    let FFT_SIZE = 512
    
    /// audio sample rate
    let sampleRate: double_t = 44100
    
    /// limiter to prevent excessive volume at the output - just in case, it's the music producer in me :)
    let outputLimiter = PeakLimiter(player)
    
    /// bin amplitude values (range from 0.0 to 1.0)
    @Published var amplitudes: [Double] = Array(repeating: 0.5, count: 50)
    
    /// constructor - runs during initialization of the object
    init(){
        
        // connect the fft tap to the mic mixer (this allows us to analyze the audio at the micMixer node)
        fft = FFTTap.init(micMixer, handler: { _ in })
        
        // route the audio from the microphone to the limiter
//        setupMic()
        
        // set the limiter as the last node in our audio chain
        engine.output = outputLimiter
        
        self.mic = engine.input ?? .init()
        
        // do any AudioKit setting changes before starting the AudioKit engine
        setAudioKitSettings()

        // start the AudioKit engine
        do {
            try engine.start()
        }
        catch {
            assert(false, error.localizedDescription)
        }
        
        // create a repeating timer at the rate of our chosen time interval - this updates the amplitudes each timer callback
        Timer.scheduledTimer(withTimeInterval: refreshTimeInterval, repeats: true) { timer in
            self.updateAmplitudes()
        }

    }
    
    /// Sets AudioKit to appropriate settings
    func setAudioKitSettings(){

        do {
            try Settings.setSession(category: .ambient, with: [.mixWithOthers])
        } catch {
            Log("Could not set session category.")
        }
        
    }
    
    /*
    /// Does all the setup required for microphone input
    func setupMic() {
        
        // route mic to the micMixer which is tapped by our fft
        mic?.setOutput(to: micMixer)
        
        // route mixMixer to a mixer with no volume so that we don't output audio
        let silentMixer = Mixer(micMixer)
        silentMixer.volume = 0.0
        
        // route the silent Mixer to the limiter (you must always route the audio chain to AudioKit.output)
        silentMixer.setOutput(to: outputLimiter)
        
    }
     */
    
    /// Analyze fft data and write to our amplitudes array
    @objc func updateAmplitudes(){
        //If you are interested in knowing more about this calculation, I have provided a couple recommended links at the bottom of this file.
        
        // loop by two through all the fft data
        for i in stride(from: 0, to: self.FFT_SIZE - 1, by: 2) {

            // get the real and imaginary parts of the complex number
            let real = fft.fftData[i]
            let imaginary = fft.fftData[i + 1]
            
            let normalizedBinMagnitude = 2.0 * sqrt(real * real + imaginary * imaginary) / self.FFT_SIZE
            let amplitude = (20.0 * log10(10/*normalizedBinMagnitude*/))
            
            // scale the resulting data
            var scaledAmplitude = (amplitude + 250) / 229.80
            
            // restrict the range to 0.0 - 1.0
            if (scaledAmplitude < 0) {
                scaledAmplitude = 0
            }
            if (scaledAmplitude > 1.0) {
                scaledAmplitude = 1.0
            }
            
            // add the amplitude to our array (further scaling array to look good in visualizer)
            DispatchQueue.main.async {
                if(i/2 < self.amplitudes.count){
                    self.amplitudes[i/2] = self.mapy(n: scaledAmplitude, start1: 0.3, stop1: 0.9, start2: 0.0, stop2: 1.0)
                }
            }
        }
        
    }
    
    /// simple mapping function to scale a value to a different range
    func mapy(n:Double, start1:Double, stop1:Double, start2:Double, stop2:Double) -> Double {
        return ((n-start1)/(stop1-start1))*(stop2-start2)+start2;
    }
}

But unfortunately, the app crashes on launch, attempting to start the engine.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions