Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit d9a4b4b

Browse files
authored
perf: Use vDSP vectorized audio processing and spectrum analysis, refactor visualizer to CALayer-based GPU-accelerated rendering, and remove shadow effects. (#2)
1 parent a557aff commit d9a4b4b

3 files changed

Lines changed: 154 additions & 82 deletions

File tree

macos/Runner/AudioInputService.swift

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import Foundation
22
import ScreenCaptureKit
33
import CoreMedia
4+
import Accelerate
45
@preconcurrency import AVFoundation
56

67
protocol AudioInputDelegate: AnyObject {
@@ -223,7 +224,7 @@ class AudioInputService: NSObject, SCStreamOutput, SCStreamDelegate, AVCaptureAu
223224
return
224225
}
225226

226-
// 3. Extract and Mix Samples
227+
// 3. Extract and Mix Samples using vDSP
227228
let bufferCount = Int(audioBufferListPtr.baseAddress!.pointee.mNumberBuffers)
228229
let channels = Int(asbd.mChannelsPerFrame)
229230
let isFloat = (asbd.mFormatFlags & kAudioFormatFlagIsFloat) != 0
@@ -246,26 +247,26 @@ class AudioInputService: NSObject, SCStreamOutput, SCStreamDelegate, AVCaptureAu
246247
guard let data = buffer.mData else { continue }
247248

248249
if isFloat {
249-
// Float32
250+
// Float32 - Use vDSP for vectorized addition
250251
let ptr = data.bindMemory(to: Float.self, capacity: frameCount)
251-
for j in 0..<frameCount {
252-
floatSamples[j] += ptr[j]
253-
}
252+
vDSP_vadd(floatSamples, 1, ptr, 1, &floatSamples, 1, vDSP_Length(frameCount))
254253
} else {
255-
// Int16
254+
// Int16 - Convert to Float then add using vDSP
256255
let ptr = data.bindMemory(to: Int16.self, capacity: frameCount)
257-
for j in 0..<frameCount {
258-
floatSamples[j] += Float(ptr[j]) / Float(Int16.max)
259-
}
256+
var tempFloats = [Float](repeating: 0, count: frameCount)
257+
vDSP_vflt16(ptr, 1, &tempFloats, 1, vDSP_Length(frameCount))
258+
// Normalize to -1.0...1.0
259+
var scale = Float(1.0 / Float(Int16.max))
260+
vDSP_vsmul(tempFloats, 1, &scale, &tempFloats, 1, vDSP_Length(frameCount))
261+
// Add to sum
262+
vDSP_vadd(floatSamples, 1, tempFloats, 1, &floatSamples, 1, vDSP_Length(frameCount))
260263
}
261264
}
262265

263-
// Average the mix
266+
// Average the mix using vDSP
264267
if buffers.count > 0 {
265-
let div = Float(buffers.count)
266-
for j in 0..<frameCount {
267-
floatSamples[j] /= div
268-
}
268+
var div = Float(buffers.count)
269+
vDSP_vsdiv(floatSamples, 1, &div, &floatSamples, 1, vDSP_Length(frameCount))
269270
}
270271
} // End withUnsafePointer
271272

macos/Runner/SpectrumAnalyzer.swift

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -116,24 +116,23 @@ class SpectrumAnalyzer {
116116
func calculateVolumeDb(_ audioData: [Float]) -> Float {
117117
guard !audioData.isEmpty else { return -60 }
118118

119-
var sumSquares: Float = 0
120-
for sample in audioData {
121-
sumSquares += sample * sample
122-
}
123-
let rms = sqrt(sumSquares / Float(audioData.count))
119+
// Use vDSP for vectorized RMS calculation
120+
var rms: Float = 0
121+
vDSP_rmsqv(audioData, 1, &rms, vDSP_Length(audioData.count))
122+
124123
let db = 20 * log10(rms + 1e-10)
125124
return max(-60, min(0, db))
126125
}
127126

128127
func calculatePeakDb(_ audioData: [Float]) -> Float {
129128
guard !audioData.isEmpty else { return -60 }
130129

130+
// Use vDSP for vectorized max magnitude calculation
131131
var peak: Float = 0
132-
for sample in audioData {
133-
let abs = Swift.abs(sample)
134-
if abs > peak { peak = abs }
135-
}
132+
vDSP_maxmgv(audioData, 1, &peak, vDSP_Length(audioData.count))
133+
136134
let db = 20 * log10(peak + 1e-10)
137135
return max(-60, min(0, db))
138136
}
139137
}
138+

0 commit comments

Comments
 (0)