Peter Iakovlev e9a4a9347a Revert "Rename directories [skip ci]"
This reverts commit 789438a27450dcbdee6065ebf096198ed3b90fec
2020-03-01 10:06:51 +00:00

98 lines
2.6 KiB
Swift

import Foundation
import AVFoundation
import SwiftSignalKit
final class TonePlayerData {
fileprivate let file: AVAudioFile
fileprivate init(file: AVAudioFile) {
self.file = file
}
}
func loadTonePlayerData(path: String) -> TonePlayerData? {
guard let file = try? AVAudioFile(forReading: URL(fileURLWithPath: path)) else {
return nil
}
return TonePlayerData(file: file)
}
private final class TonePlayerContext {
private let queue: Queue
private let audioEngine: AVAudioEngine
private let playerNode: AVAudioPlayerNode
private var scheduledData: (TonePlayerData, () -> Void)?
private let initialVolume: Float
init(queue: Queue) {
self.initialVolume = AVAudioSession.sharedInstance().outputVolume
self.queue = queue
self.audioEngine = AVAudioEngine()
self.playerNode = AVAudioPlayerNode()
self.audioEngine.attach(self.playerNode)
self.audioEngine.connect(self.playerNode, to: self.audioEngine.mainMixerNode, format: nil)
let gainFactor = self.initialVolume
print("gain \(gainFactor)")
self.audioEngine.mainMixerNode.outputVolume = gainFactor
self.audioEngine.prepare()
}
func play(data: TonePlayerData, completed: @escaping () -> Void) {
self.scheduledData = (data, completed)
}
func start() {
do {
let currentVolume = AVAudioSession.sharedInstance().outputVolume
//let gainFactor = max(0.1, min(1.5, self.initialVolume / currentVolume))
try self.audioEngine.start()
if let (data, completion) = self.scheduledData {
self.playerNode.scheduleFile(data.file, at: nil, completionHandler: {})
self.playerNode.play()
completion()
}
} catch let e {
print("Couldn't start tone engine: \(e)")
}
}
func stop() {
self.audioEngine.stop()
}
}
final class TonePlayer {
private let queue: Queue
private let impl: QueueLocalObject<TonePlayerContext>
init() {
let queue = Queue()
self.queue = queue
self.impl = .init(queue: queue, generate: {
return TonePlayerContext(queue: queue)
})
}
func play(data: TonePlayerData, completed: @escaping () -> Void) {
self.impl.with { impl in
impl.play(data: data, completed: completed)
}
}
func start() {
self.impl.with({ impl in
impl.start()
})
}
func stop() {
self.impl.with({ impl in
impl.stop()
})
}
}