Skip to content

Instantly share code, notes, and snippets.

@chapayGhub
Last active March 3, 2017 18:01
Show Gist options
  • Save chapayGhub/98f5c09b005f15eb9c3a7e9405960d9d to your computer and use it in GitHub Desktop.
Save chapayGhub/98f5c09b005f15eb9c3a7e9405960d9d to your computer and use it in GitHub Desktop.
//
// AudioPlayer.swift
//
// Created by Andrei on 3/2/17.
//
import Foundation
import AVFoundation
public typealias CommonAction = () -> Void
@objc
class AudioPlayer: NSObject {
var trackStopped: CommonAction?
var audioPlayer: AVAudioPlayer?
var audioEngine:AVAudioEngine?
var audioFile:AVAudioFile?
override init() {
let fileURL = Bundle.main.url(forResource: "daffyduck1", withExtension: ".wav")!
audioPlayer=try? AVAudioPlayer(contentsOf: fileURL as URL)
audioPlayer?.enableRate=true
audioEngine=AVAudioEngine()
audioFile=try? AVAudioFile(forReading: fileURL as URL)
}
func stop() {
trackStopped = nil
audioPlayer?.stop()
}
func playsWith(rate: Float = 0) {
audioPlayer?.stop()
audioPlayer?.rate=0.5
audioPlayer?.play()
}
func playsWith(pitch: Float = 0, trackStopped: CommonAction?) {
guard let audioPlayer = audioPlayer, let audioEngine = audioEngine, let audioFile = audioFile else {
return
}
self.trackStopped = trackStopped
audioPlayer.stop()
audioEngine.stop()
audioEngine.reset()
let audioNode=AVAudioPlayerNode()
audioEngine.attach(audioNode)
let audioPitch=AVAudioUnitTimePitch()
audioPitch.pitch=pitch
audioEngine.attach(audioPitch)
audioEngine.connect(audioNode, to: audioPitch, format: nil)
audioEngine.connect(audioPitch, to: audioEngine.outputNode, format: nil)
audioNode.scheduleFile(audioFile, at: nil) { [weak self] in
DispatchQueue.main.async {
self?.trackStopped?()
self?.trackStopped = nil
}
}
try? audioEngine.start()
audioNode.play()
}
func saveWithEffect() {
let pitch = -800.0
let rate = 0.5
let reverb = 1.0
let echo = 1.0
// Initialize variables
// These are global variables . if you want you can just (let audioEngine = etc ..) init here these variables
let audioEngine = AVAudioEngine()
let audioPlayerNode = AVAudioPlayerNode()
audioEngine.attach(audioPlayerNode)
let playerB = AVAudioPlayerNode()
audioEngine.attach(playerB)
// Setting the pitch
let pitchEffect = AVAudioUnitTimePitch()
pitchEffect.pitch = Float(pitch)
audioEngine.attach(pitchEffect)
// Setting the platback-rate
let playbackRateEffect = AVAudioUnitVarispeed()
playbackRateEffect.rate = Float(rate)
audioEngine.attach(playbackRateEffect)
// Setting the reverb effect
let reverbEffect = AVAudioUnitReverb()
reverbEffect.loadFactoryPreset(AVAudioUnitReverbPreset.cathedral)
reverbEffect.wetDryMix = Float(reverb)
audioEngine.attach(reverbEffect)
// Setting the echo effect on a specific interval
let echoEffect = AVAudioUnitDelay()
echoEffect.delayTime = TimeInterval(echo)
audioEngine.attach(echoEffect)
// Chain all these up, ending with the output
// audioEngine.connect(audioPlayerNode, to: playbackRateEffect, format: nil)
// audioEngine.connect(playbackRateEffect, to: pitchEffect, format: nil)
// audioEngine.connect(pitchEffect, to: reverbEffect, format: nil)
// audioEngine.connect(reverbEffect, to: echoEffect, format: nil)
// audioEngine.connect(echoEffect, to: audioEngine.mainMixerNode, format: nil)
audioEngine.connect(audioPlayerNode, to: pitchEffect, format: nil)
audioEngine.connect(pitchEffect, to: audioEngine.mainMixerNode, format: nil)
// Good practice to stop before starting
audioPlayerNode.stop()
audioPlayer?.stop()
// audioFile here is our original audio
audioPlayerNode.scheduleFile(audioFile!, at: nil, completionHandler: {[weak self] in
print("Complete")
self?.done = true
})
try! audioEngine.start()
let dirPath=NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as String
let currentDateTime=Date()
let formatter = DateFormatter()
formatter.dateFormat="yyyyMMdd-HHmmss"
let recordingName=formatter.string(from: currentDateTime)+".wav"
let pathArray=[dirPath,recordingName]
let tmpFileUrl = URL(string: pathArray.joined(separator: "/"))
//Save the tmpFileUrl into global varibale to not lose it (not important if you want to do something else)
print(tmpFileUrl!)
do{
print(audioFile!.fileFormat.settings)
let newAudio = try! AVAudioFile(forWriting: tmpFileUrl!, settings: self.audioEngine!.outputNode.inputFormat(forBus: 0).settings)
let length = self.audioFile?.length
audioEngine.mainMixerNode.installTap(onBus: 0, bufferSize: 8192, format: self.audioEngine?.outputNode.inputFormat(forBus: 0)) {(buffer: AVAudioPCMBuffer!, time: AVAudioTime!) -> Void in
print(newAudio.length)
print("=====================")
print(length!)
print("**************************")
do{
//print(buffer)
try newAudio.write(from: buffer)
}catch _{
print("Problem Writing Buffer")
}
if self.done == .some(true) {
audioEngine.mainMixerNode.removeTap(onBus: 0)
}
}
}catch _{
print("Problem")
}
audioPlayerNode.play()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment