Pitch Shifting in Real Time With AVAudioEngine using Swift
Asked Answered
S

2

10

I am developing an Audio effects application on OSX using Swift, and I'm interested in integrating a pitch-shift effect.

I would like in real-time, to change the tone up or down an octave. Currently I am only getting a dry signal.

I am not sure if this is possible at all and would like to know if this is even possible or any help or suggestions anyone may have.

Current code relevant to the problem is as follows:

import Cocoa
import AVFoundation


class ViewController: NSViewController {
       var engine = AVAudioEngine()
       var timePitch = AVAudioUnitTimePitch()


    override func viewDidLoad() {
         timePitch.pitch = 1200

        // Setup engine and node instances
        var mixer = engine.mainMixerNode
        var input = engine.inputNode
        var output = engine.outputNode
        var format = input.inputFormatForBus(0)
        var error:NSError?

       engine.attachNode(timePitch)

       engine.connect(input, to: timePitch, format: format)
       engine.connect(timePitch, to: output, format: format)

      engine.startAndReturnError(&error)

        super.viewDidLoad()
    }

   override var representedObject: AnyObject? {
        didSet {
        // Update the view, if already loaded.
        }
    }


}
Standpipe answered 30/8, 2015 at 9:4 Comment(0)
S
5
timePitch.pitch = -500 //Rude man voice
timePitch.rate = 1.5 //In 1.5 times faster

Check this tutorial. And direct link to example from tutorial for more info.

Example for Swift 2.0:

import UIKit
import AVFoundation

class ViewController: UIViewController {

    var engine: AVAudioEngine!
    var player: AVAudioPlayerNode!

    var file = AVAudioFile()

    override func viewDidLoad() {
        super.viewDidLoad()

        engine = AVAudioEngine()
        player = AVAudioPlayerNode()
        player.volume = 1.0

        let path = NSBundle.mainBundle().pathForResource("in", ofType: "caf")!
        let url = NSURL.fileURLWithPath(path)

        let file = try? AVAudioFile(forReading: url)
        let buffer = AVAudioPCMBuffer(PCMFormat: file!.processingFormat, frameCapacity: AVAudioFrameCount(file!.length))
        do {
            try file!.readIntoBuffer(buffer)
        } catch _ {
        }

        let pitch = AVAudioUnitTimePitch()

        //
        pitch.pitch = -500 //Distortion
        pitch.rate = 1.5 //Voice speed
        //

        engine.attachNode(player)

        engine.attachNode(pitch)

        engine.connect(player, to: pitch, format: buffer.format)

        engine.connect(pitch, to: engine.mainMixerNode, format: buffer.format)
        player.scheduleBuffer(buffer, atTime: nil, options: AVAudioPlayerNodeBufferOptions.Loops, completionHandler: nil)

        engine.prepare()
        do {
            try engine.start()
        } catch _ {
        }

        player.play()

    }
}
Schuck answered 30/8, 2015 at 17:36 Comment(2)
Thanks a lot for sharing it.Bozovich
Quality changing when i'm changing pitch.rate. is there any way to maintain same quality when rate changeUntouchable
O
0
timePitch.pitch = 1000 //Filtered Voice
timePitch.rate = 1 //Normal rate
Oscitancy answered 8/2, 2017 at 11:51 Comment(2)
While this code may answer the question, providing additional context regarding how and/or why it solves the problem would improve the answer's long-term value.Catheycathi
thank you for your suggestion @Donald duck. i will keep this in mind from next timeOscitancy

© 2022 - 2024 — McMap. All rights reserved.