Last active
March 3, 2017 18:01
-
-
Save chapayGhub/98f5c09b005f15eb9c3a7e9405960d9d to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// 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