// // FileSpectrum.swift // PrySDR // // Created by Jacky Jack on 01/01/2025. // import Accelerate import AppKit import Combine import CoreImage class FileSpectrum: NSObject, ObservableObject { static let default_width = 512 static let default_height = 512 static let defaultSleepTime:UInt32 = 1 var offset:Int=0 let fileReader = FileReader() var dataBuffer:[Int8] = .init(repeating: 0, count: FileSpectrum.default_width) var allData:[Int8]? = nil let fft512 = NaiveFFT512() var line_counter:Int = 0 let sessionQueue = DispatchQueue(label: "sessionQueue", attributes: [], autoreleaseFrequency: .workItem) @Published var outputImage = emptyCGImage let simpleImage = SimpleImage(width: 512, height: 512) /// A 1x1 Core Graphics image. static var emptyCGImage: CGImage = { let buffer = vImage.PixelBuffer( pixelValues: [0], size: .init(width: 1, height: 1), pixelFormat: vImage.Planar8.self) let fmt = vImage_CGImageFormat( bitsPerComponent: 8, bitsPerPixel: 8 , colorSpace: CGColorSpaceCreateDeviceGray(), bitmapInfo: CGBitmapInfo(rawValue: CGImageAlphaInfo.none.rawValue), renderingIntent: .defaultIntent) return buffer.makeCGImage(cgImageFormat: fmt!)! }() init(_ input_filename: String) { //get data from u8 file do { try fileReader.open(filename: input_filename) } catch { print("Cant open file \(input_filename)") exit(0) } var i8_arr:[Int8]? = nil do { try i8_arr = fileReader.readAll() allData = i8_arr } catch { print("Got error \(error)") } fileReader.close() } func makeSpectrogramImage() -> NSImage { return NSImage(cgImage: FileSpectrum.emptyCGImage, size: .zero) } //just get data time to time from databuffer and pretend to be realtime data func dataFileProcessor() { //all now is about 512pixels let processingSlice = allData![offset...offset+FileSpectrum.default_width-1] let dataBuffer = Array(processingSlice) var transform_result:[Float] = .init(repeating: 0.0, count: FileSpectrum.default_width) //DispatchQueue.main.async { transform_result = self.fft512.computeLine(dataBuffer) self.simpleImage.drawPalletLine(line: self.line_counter, pixelLine: transform_result) if self.offset+FileSpectrum.default_width < allData!.count { self.offset += FileSpectrum.default_width self.line_counter += 1 } //} } func startRunning() { sessionQueue.async { print("lets start the task for spectrum analysis") for i in 0..<512 { print("Process the task \(i)") self.simpleImage.drawPixel(i, i, PixelData(a: 255, r: 255, g: 0, b: 0)) DispatchQueue.main.async { self.dataFileProcessor() self.outputImage = self.simpleImage.toCGImage()! } sleep(FileSpectrum.defaultSleepTime) } } } }