2

I'm trying to analyze a sound file (.m4a) to get the amplitudes over time and make a graph. I found some code online that works great (below). However, I would like to additionally filter out all sounds that are not in a targeted frequency range. E.g. I want to only graph the sounds that are between 1900-2100 Hz. How can I do this?

    var processingBuffer = [Float](repeating: 0.0, count: Int(readFile.arrayFloatValues.count))
    let sampleCount = vDSP_Length(readFile.arrayFloatValues.count)

    vDSP_vabs(readFile.arrayFloatValues, 1, &processingBuffer, 1, sampleCount);

    let samplesPerPixel = 1
    let filter = [Float](repeating: 1.0 / Float(samplesPerPixel), count: Int(samplesPerPixel))
    let downSampledLength = Int(readFile.arrayFloatValues.count / samplesPerPixel)
    var downSampledData = [Float](repeating:0.0, count:downSampledLength)

    vDSP_desamp(processingBuffer,
                vDSP_Stride(samplesPerPixel),
                filter, &downSampledData,
                vDSP_Length(downSampledLength),
                vDSP_Length(samplesPerPixel))

    readFile.points = downSampledData.map{CGFloat($0)}

Edit

The recording is actually recorded from the device's microphone at an earlier time. Is it perhaps easier to apply a filter at the recording stage?

Anters Bear
  • 1,816
  • 1
  • 15
  • 41
  • you would convert that amplitude/time data you got into the frequency domain, edit it, and convert it back to the time domain. FFT would work. – meggar Dec 03 '17 at 23:01
  • any hints as to how to do that? I'm really new to sound processing – Anters Bear Dec 03 '17 at 23:02
  • it looks like you're using the Accelerate framework, maybe this will help: https://developer.apple.com/library/content/documentation/Performance/Conceptual/vDSP_Programming_Guide/Introduction/Introduction.html – meggar Dec 04 '17 at 00:34

1 Answers1

2

A possible way would be to apply a discrete fourier transformation to the sampled file. Fourier transformation transfers audio data from time-domain to frequency-domain. Once you have that data in frequency domain, you simply can "cut out" the frequency that you don't want to have and do a inverse Fourier transformation with your reduced data, so that you have it in time domain again and proceed with the code you mentioned. Have a look at https://github.com/christopherhelf/Swift-FFT-Example, it provides example code how to deal with swift and Fast Fourier transformation (FFT). Hope this gives you a direction.

Silvan
  • 93
  • 1
  • 8
  • This is actually a terrible approach: i) Either a FIR or IIR filter in the time domain is far cheaper compute than FFT and then IFFT ii) It sounds awful (see https://en.wikipedia.org/wiki/Gibbs_phenomenon) and iii) It makes for a really sloppy filter because the pass-band would be far wider than wanted (6dB/octave if memory serves). iv) BTW - all lossy codecs operate on the frequency domain to start with - why would you convert to base-band then calculate FFT again? The orthodox approach - that works - is IIR band-pass filter. – marko Dec 04 '17 at 23:57