@@ -13,19 +13,21 @@ import Foundation
1313final class AudioEngine : ObservableObject {
1414 private var audioEngine : AVAudioEngine ?
1515 private var inputNode : AVAudioInputNode ?
16-
17- @Published private( set) var isRunning = false
18- @Published private( set) var hasPermission = false
19-
16+
17+ @Published
18+ private( set) var isRunning = false
19+ @Published
20+ private( set) var hasPermission = false
21+
2022 var onBufferReceived : ( ( [ Float ] , Double ) -> Void ) ?
21-
23+
2224 // Buffer size for audio capture
2325 private let bufferSize : AVAudioFrameCount = 1024
24-
26+
2527 init ( ) {
2628 checkPermission ( )
2729 }
28-
30+
2931 func checkPermission( ) {
3032 let session = AVAudioSession . sharedInstance ( )
3133 switch session. recordPermission {
@@ -39,56 +41,56 @@ final class AudioEngine: ObservableObject {
3941 hasPermission = false
4042 }
4143 }
42-
44+
4345 func requestPermission( ) {
4446 AVAudioSession . sharedInstance ( ) . requestRecordPermission { [ weak self] granted in
4547 DispatchQueue . main. async {
4648 self ? . hasPermission = granted
4749 }
4850 }
4951 }
50-
52+
5153 func start( ) {
5254 guard hasPermission else {
5355 requestPermission ( )
5456 return
5557 }
56-
58+
5759 guard !isRunning else { return }
58-
60+
5961 do {
6062 let session = AVAudioSession . sharedInstance ( )
6163 try session. setCategory ( . playAndRecord, mode: . measurement, options: [ . defaultToSpeaker, . allowBluetooth] )
6264 try session. setActive ( true )
63-
65+
6466 guard session. isInputAvailable else { return }
65-
67+
6668 audioEngine = AVAudioEngine ( )
67- guard let audioEngine = audioEngine else { return }
68-
69+ guard let audioEngine else { return }
70+
6971 inputNode = audioEngine. inputNode
70- guard let inputNode = inputNode else { return }
71-
72+ guard let inputNode else { return }
73+
7274 inputNode. installTap ( onBus: 0 , bufferSize: bufferSize, format: nil ) { [ weak self] buffer, _ in
73- guard let self = self else { return }
75+ guard let self else { return }
7476 guard let channelData = buffer. floatChannelData else { return }
75-
77+
7678 let channelDataValue = channelData. pointee
7779 let frameLength = Int ( buffer. frameLength)
7880 let sampleRate = Double ( buffer. format. sampleRate)
79-
81+
8082 // Copy samples
8183 var samples = [ Float] ( repeating: 0 , count: frameLength)
82- for i in 0 ..< frameLength {
84+ for i in 0 ..< frameLength {
8385 samples [ i] = channelDataValue [ i]
8486 }
85-
87+
8688 // Call the callback
8789 self . onBufferReceived ? ( samples, sampleRate)
8890 }
89-
91+
9092 try audioEngine. start ( )
91-
93+
9294 DispatchQueue . main. async {
9395 self . isRunning = true
9496 }
@@ -99,18 +101,18 @@ final class AudioEngine: ObservableObject {
99101 }
100102 }
101103 }
102-
104+
103105 func stop( ) {
104106 inputNode? . removeTap ( onBus: 0 )
105107 audioEngine? . stop ( )
106108 audioEngine = nil
107109 inputNode = nil
108-
110+
109111 DispatchQueue . main. async {
110112 self . isRunning = false
111113 }
112114 }
113-
115+
114116 deinit {
115117 inputNode? . removeTap ( onBus: 0 )
116118 audioEngine? . stop ( )
0 commit comments