-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathAudioSpectrumPlayer.swift
97 lines (73 loc) · 3.04 KB
/
AudioSpectrumPlayer.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
//
// AudioSpectrumPlayer.swift
// Pinna
///
// Created by Matt Chen on 2022/3/20.
//
import Foundation
import AVFoundation
import Accelerate
protocol AudioSpectrumPlayerDelegate: AnyObject {
func player(_ player: AudioSpectrumPlayer, didGenerateSpectrum spectra: [[Float]])
}
class AudioSpectrumPlayer {
weak var delegate: AudioSpectrumPlayerDelegate?
private let engine = AVAudioEngine()
private let player = AVAudioPlayerNode()
let volumeEffect = AVAudioUnitEQ()
public var bufferSize: Int? {
didSet {
if let bufferSize = self.bufferSize {
analyzer = RealtimeAnalyzer(fftSize: bufferSize)
engine.mainMixerNode.removeTap(onBus: 0)
engine.mainMixerNode.installTap(onBus: 0, bufferSize: AVAudioFrameCount(bufferSize), format: nil, block: {[weak self](buffer, when) in
guard let strongSelf = self else { return }
if !strongSelf.player.isPlaying { return }
buffer.frameLength = AVAudioFrameCount(bufferSize)
let spectra = strongSelf.analyzer.analyse(with: buffer)
self!.volumeEffect.globalGain = 0
let amplitudes = spectra[0]
let index = self!.analyzer.findMajorFrequency(amplitudes: spectra[0])
print(amplitudes[index])
if index > 0 && index < 15 {
self!.volumeEffect.globalGain = (0.5-UserSetting.shared.low) * 40
}
else if index > 15 && index < 150 {
self!.volumeEffect.globalGain = (0.5-UserSetting.shared.medium) * 40
}
else if index > 150 {
self!.volumeEffect.globalGain = (0.5-UserSetting.shared.high) * 40
}
else{
self!.volumeEffect.globalGain = 0
}
if strongSelf.delegate != nil {
strongSelf.delegate!.player(strongSelf, didGenerateSpectrum: spectra)
}
})
}
}
}
public var analyzer: RealtimeAnalyzer!
init(bufferSize: Int = 2048) {
engine.attach(volumeEffect)
engine.attach(player)
engine.connect(player, to: volumeEffect, format: nil)
engine.connect(volumeEffect, to: engine.mainMixerNode, format: nil)
engine.prepare()
try! engine.start()
defer {
self.bufferSize = bufferSize
}
}
func play(withFileName fileName: String) {
guard let audioFileURL = URL(string: fileName),
let audioFile = try? AVAudioFile(forReading: audioFileURL) else { return }
player.stop()
player.scheduleFile(audioFile, at: nil, completionHandler: nil)
player.play()
}
func stop() {
player.stop()
}
}