2022-06-30 09:28:16 +00:00
|
|
|
//
|
|
|
|
// VisualizationController.swift
|
|
|
|
// CogAudio Framework
|
|
|
|
//
|
|
|
|
// Created by Christopher Snowhill on 6/30/22.
|
|
|
|
//
|
|
|
|
|
|
|
|
import Foundation
|
|
|
|
|
|
|
|
@objc(VisualizationController)
|
2022-08-06 04:38:13 +00:00
|
|
|
class VisualizationController : NSObject {
|
2022-06-30 09:28:16 +00:00
|
|
|
var serialQueue = DispatchQueue(label: "Visualization Queue")
|
2022-08-06 04:38:13 +00:00
|
|
|
var sampleRate = 0.0
|
2022-06-30 09:28:16 +00:00
|
|
|
var latency = 0.0
|
|
|
|
var visAudio: [Float] = Array(repeating: 0.0, count: 44100 * 45)
|
|
|
|
var visAudioCursor = 0
|
|
|
|
var visAudioSize = 0
|
|
|
|
|
2022-08-06 04:38:13 +00:00
|
|
|
private static var sharedVisualizationController: VisualizationController = {
|
2022-06-30 09:28:16 +00:00
|
|
|
let visualizationController = VisualizationController()
|
|
|
|
return visualizationController
|
|
|
|
}()
|
2022-08-06 04:38:13 +00:00
|
|
|
|
|
|
|
@objc
|
|
|
|
class func sharedController() -> VisualizationController {
|
|
|
|
return sharedVisualizationController
|
2022-06-30 09:28:16 +00:00
|
|
|
}
|
|
|
|
|
2022-08-06 04:38:13 +00:00
|
|
|
@objc
|
2022-06-30 09:28:16 +00:00
|
|
|
func postLatency(_ latency: Double) {
|
|
|
|
self.latency = latency
|
|
|
|
}
|
|
|
|
|
2022-08-06 04:38:13 +00:00
|
|
|
@objc
|
2022-06-30 09:28:16 +00:00
|
|
|
func postSampleRate(_ sampleRate: Double) {
|
|
|
|
serialQueue.sync {
|
|
|
|
if(self.sampleRate != sampleRate) {
|
|
|
|
self.sampleRate = sampleRate
|
|
|
|
visAudioSize = (Int)(sampleRate * 45.0)
|
|
|
|
visAudio = Array(repeating: 0.0, count: visAudioSize)
|
|
|
|
visAudioCursor = 0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-08-06 04:38:13 +00:00
|
|
|
@objc
|
2022-06-30 09:28:16 +00:00
|
|
|
func postVisPCM(_ inPCM: UnsafePointer<Float>?, amount: Int) {
|
|
|
|
serialQueue.sync {
|
2022-08-06 04:38:13 +00:00
|
|
|
let bufferPointer = UnsafeBufferPointer<Float>(start: inPCM, count: amount)
|
|
|
|
var j = self.visAudioCursor
|
|
|
|
let k = self.visAudioSize
|
|
|
|
for i in 0..<amount {
|
|
|
|
let x = bufferPointer[i]
|
|
|
|
self.visAudio[j] = x
|
|
|
|
j += 1; if j >= k { j = 0 }
|
2022-06-30 09:28:16 +00:00
|
|
|
}
|
2022-08-06 04:38:13 +00:00
|
|
|
self.visAudioCursor = j
|
2022-06-30 09:28:16 +00:00
|
|
|
}
|
|
|
|
}
|
2022-08-06 04:38:13 +00:00
|
|
|
|
|
|
|
@objc
|
2022-06-30 09:28:16 +00:00
|
|
|
func readSampleRate() -> Double {
|
|
|
|
serialQueue.sync {
|
|
|
|
return self.sampleRate
|
|
|
|
}
|
|
|
|
}
|
2022-08-06 04:38:13 +00:00
|
|
|
|
|
|
|
@objc
|
|
|
|
func copyVisPCM(_ outPCM: UnsafeMutablePointer<Float>?, visFFT: UnsafeMutablePointer<Float>?, latencyOffset: Double) {
|
|
|
|
if(self.visAudioSize == 0) {
|
|
|
|
if(outPCM != nil) {
|
|
|
|
let pcmPointer = UnsafeMutableBufferPointer<Float>(start: outPCM, count: 4096)
|
|
|
|
for i in 0...4095 {
|
|
|
|
pcmPointer[i] = 0.0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(visFFT != nil) {
|
|
|
|
let fftPointer = UnsafeMutableBufferPointer<Float>(start: visFFT, count: 2048)
|
|
|
|
for i in 0...2047 {
|
|
|
|
fftPointer[i] = 0.0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
var outPCMCopy = Array<Float>(repeating: 0.0, count: 4096)
|
2022-06-30 09:28:16 +00:00
|
|
|
|
|
|
|
serialQueue.sync {
|
2022-08-06 04:38:13 +00:00
|
|
|
let latencySamples = (Int)(self.latency * self.sampleRate)
|
2022-06-30 09:28:16 +00:00
|
|
|
var j = self.visAudioCursor - latencySamples
|
2022-08-06 04:38:13 +00:00
|
|
|
let k = self.visAudioSize
|
2022-06-30 09:28:16 +00:00
|
|
|
if j < 0 { j += k }
|
2022-08-06 04:38:13 +00:00
|
|
|
for i in 0...4095 {
|
2022-06-30 09:28:16 +00:00
|
|
|
let x = self.visAudio[j]
|
|
|
|
outPCMCopy[i] = x
|
2022-08-06 04:38:13 +00:00
|
|
|
j += 1; if j >= k { j = 0 }
|
2022-06-30 09:28:16 +00:00
|
|
|
}
|
|
|
|
}
|
2022-08-06 04:38:13 +00:00
|
|
|
|
|
|
|
if(outPCM != nil) {
|
|
|
|
let pcmPointer = UnsafeMutableBufferPointer<Float>(start: outPCM, count: 4096)
|
|
|
|
for i in 0...4095 {
|
2022-06-30 09:28:16 +00:00
|
|
|
let x = outPCMCopy[i]
|
2022-08-06 04:38:13 +00:00
|
|
|
pcmPointer[i] = x
|
2022-06-30 09:28:16 +00:00
|
|
|
}
|
|
|
|
}
|
2022-08-06 04:38:13 +00:00
|
|
|
|
|
|
|
if(visFFT != nil) {
|
2022-06-30 09:28:16 +00:00
|
|
|
serialQueue.sync {
|
2022-08-06 04:38:13 +00:00
|
|
|
fft_calculate(outPCMCopy, visFFT, 2048)
|
2022-06-30 09:28:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|