0

I have tried to create a spectrogram using this apple tutorial but it uses live audio input from the microphone. I want to create one from an existing file. I have tried to convert apples example from live input to existing files with no luck, so I am wondering if there are any better resources out there.

Here is how I am getting the samples:

let samples: (naturalTimeScale: Int32, data: [Float]) = {
        guard let samples = AudioUtilities.getAudioSamples(
            forResource: resource,
            withExtension: wExtension) else {
                fatalError("Unable to parse the audio resource.")
        }
        return samples
    }()

    // Returns an array of single-precision values for the specified audio resource.
    static func getAudioSamples(forResource: String,
                                withExtension: String) -> (naturalTimeScale: CMTimeScale,
                                                           data: [Float])? {
        guard let path = Bundle.main.url(forResource: forResource,
                                         withExtension: withExtension) else {
                                            return nil
        }

        let asset = AVAsset(url: path.absoluteURL)
        
        guard
            let reader = try? AVAssetReader(asset: asset),
            let track = asset.tracks.first else {
                return nil
        }
        
        let outputSettings: [String: Int] = [
            AVFormatIDKey: Int(kAudioFormatLinearPCM),
            AVNumberOfChannelsKey: 1,
            AVLinearPCMIsBigEndianKey: 0,
            AVLinearPCMIsFloatKey: 1,
            AVLinearPCMBitDepthKey: 32,
            AVLinearPCMIsNonInterleaved: 1
        ]
        
        let output = AVAssetReaderTrackOutput(track: track,
                                              outputSettings: outputSettings)

        reader.add(output)
        reader.startReading()
        
        var samplesData = [Float]()
        
        while reader.status == .reading {
            if
                let sampleBuffer = output.copyNextSampleBuffer(),
                let dataBuffer = CMSampleBufferGetDataBuffer(sampleBuffer) {
                
                    let bufferLength = CMBlockBufferGetDataLength(dataBuffer)
                
                    var data = [Float](repeating: 0,
                                       count: bufferLength / 4)
                    CMBlockBufferCopyDataBytes(dataBuffer,
                                               atOffset: 0,
                                               dataLength: bufferLength,
                                               destination: &data)
                
                    samplesData.append(contentsOf: data)
            }
        }

        return (naturalTimeScale: track.naturalTimeScale, data: samplesData)
    }

And here is how I am performing the "fft" or dct in this case:

static var sampleCount = 1024
let forwardDCT = vDSP.DCT(count: sampleCount,
                              transformType: .II)
guard let freqs = forwardDCT?.transform(samples.data) else { return } 

This is the part where I begin to get lost/stuck in the apple tutorial. How can I create the spectrogram from here?

Trevor
  • 580
  • 5
  • 16

0 Answers0