feat: AudioLevel helper and AudioRecorder.onLevel

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-01 15:00:40 +02:00
co-authored by Claude Sonnet 5.5
parent 2c4b096850
commit c8e16145e1
4 changed files with 78 additions and 3 deletions
+15 -2
View File
@@ -2,12 +2,13 @@ import AVFoundation
import SstCore
/// Records `seconds` of microphone audio; returns nil if access is denied or recording fails.
func recordSamples(seconds: Double) async -> [Float]? {
func recordSamples(seconds: Double, onLevel: ((Float) -> Void)? = nil) async -> [Float]? {
guard await AVCaptureDevice.requestAccess(for: .audio) else {
print("Microfoon-toegang geweigerd (Systeeminstellingen → Privacy → Microfoon).")
return nil
}
let recorder = AudioRecorder()
recorder.onLevel = onLevel
do { try recorder.start() } catch {
print("start mislukt:", error.localizedDescription)
return nil
@@ -18,7 +19,19 @@ func recordSamples(seconds: Double) async -> [Float]? {
}
func runRecordProbe() async {
guard let samples = await recordSamples(seconds: 3) else { return }
final class Levels: @unchecked Sendable {
let lock = NSLock()
var values: [Float] = []
func add(_ v: Float) { lock.withLock { values.append(v) } }
}
let levels = Levels()
guard let samples = await recordSamples(seconds: 3, onLevel: { levels.add($0) }) else { return }
let peak = samples.map { abs($0) }.max() ?? 0
print("samples: \(samples.count) (verwacht ≈ 48000), piek: \(peak)")
let values = levels.lock.withLock { levels.values }
if let lo = values.min(), let hi = values.max() {
print(String(format: "niveau-meldingen: %d (≈ %.0f per s), bereik %.1f … %.1f dBFS", values.count, Double(values.count) / 3, lo, hi))
} else {
print("geen niveau-meldingen ontvangen")
}
}