1

I am using the following code to record audio and produce a magnitude float data. But I am not sure if the data is correct. Could someone please verify?

The main program used for recording audio is similar to the example AudioQueueRecorder.

In there once I create the queue, I add AudioQueueProcessingTapNew with callback as:

guard let queue = queue else { return }        

var maxFrames : UInt32 = 0;
var tapFormat = AudioStreamBasicDescription()
var tap : AudioQueueProcessingTapRef? = nil
var player = MyInfo()

utils.checkError(AudioQueueProcessingTapNew(queue, tapCallback, &player, AudioQueueProcessingTapFlags.preEffects, &maxFrames, &tapFormat, &tap),
                 "Failed to create audio queue tap")

In the tap callback (linked above), I use the code to get the magnitude:

let info = userData.assumingMemoryBound(to: MyInfo.self)
var sourceFlags: AudioQueueProcessingTapFlags = AudioQueueProcessingTapFlags(rawValue: 0)
var sourceNumFrames: UInt32 = 0
AudioQueueProcessingTapGetSourceAudio(tap, inNumFrames, ts, &sourceFlags, &sourceNumFrames, ioData)

print("ts:", ts.pointee)
print("num frames:", inNumFrames)

let numBuffers = ioData.pointee.mNumberBuffers
print("num buffers:", numBuffers)

if numBuffers > 0 {
    let numChans = ioData.pointee.mBuffers.mNumberChannels
    let size = ioData.pointee.mBuffers.mDataByteSize / 4 //Size of a float is 4
    let data: [Float] = Array(UnsafeMutableBufferPointer(start: ioData.pointee.mBuffers.mData!.assumingMemoryBound(to: Float.self), count: Int(size)))

    print("num chans:", numChans)
    print("size:", size)

    let fft = TempiFFT(withSize: Int(size), sampleRate: 44100.0)
    fft.windowType = TempiFFTWindowType.hamming
    fft.fftForward(data)
    fft.calculateLinearBands(minFrequency: 0, maxFrequency: fft.nyquistFrequency, numberOfBands: 20)

    var magnitudeArr = [Float](repeating: Float(0), count: 20)
    var magnitudeDBArr = [Float](repeating: Float(0), count: 20)
    for i in 0..<20 {
        magnitudeArr[i] = fft.magnitudeAtBand(i)
        //var magnitudeDB = TempiFFT.toDB(fft.magnitudeAtBand(i))
        log.debug("fft.magnitudeAtBand(\(i)) = \(fft.magnitudeAtBand(i))")
    }
}

I am getting the following output. I want to draw a plot for the amplitude.

ts: AudioTimeStamp(mSampleTime: 359433.0, mHostTime: 7385045310414, mRateScalar: 0.9999903367259503, mWordClockTime: 4424786032, mSMPTETime: __C.SMPTETime(mSubframes: 0, mSubframeDivisor: 16384, mCounter: 0, mType: __C.SMPTETimeType, mFlags: __C.SMPTETimeFlags(rawValue: 1), mHours: 4800, mMinutes: 179, mSeconds: 1, mFrames: 0), mFlags: __C.AudioTimeStampFlags(rawValue: 7), mReserved: 28672)
num frames: 2048
num buffers: 2
num chans: 1
size: 2048
data: [-0.00013435386, 4.471163e-05, 2.5250512e-07, -0.00013112863, -4.2305917e-05, -6.0883203e-06, -6.9609705e-05, 1.3280656e-05, 2.6565194e-06, -7.048986e-05, -4.371278e-05, -0.00012498278, -0.00015581526, 2.6477476e-06, 0.00014767727, 0.00015129645, 0.0002481592, 0.00020998582, 7.0496775e-05, 0.00023169718, 0.00032023923, 9.4876516e-05, 3.0334933e-05, -0.00010365831, -0.00012052287, -3.4284778e-06, -8.221614e-05, -0.00013551829, -8.154745e-05, -8.845353e-06, -5.211319e-05, 6.356722e-05, 0.00014827582] ...

fft.magnitudeAtBand(0) = 0.0019885404
fft.magnitudeAtBand(1) = 0.0002433162
fft.magnitudeAtBand(2) = 0.00011211308
fft.magnitudeAtBand(3) = 0.00019586945
fft.magnitudeAtBand(4) = 0.00015595475
fft.magnitudeAtBand(5) = 1.6589744e-05
fft.magnitudeAtBand(6) = 0.0019934585
fft.magnitudeAtBand(7) = 0.00035403066
fft.magnitudeAtBand(8) = 0.0020195032
fft.magnitudeAtBand(9) = 0.0019526586
fft.magnitudeAtBand(10) = 0.0010482509
fft.magnitudeAtBand(11) = 0.0015899779
fft.magnitudeAtBand(12) = 0.00021513038
fft.magnitudeAtBand(13) = 8.8768e-05
fft.magnitudeAtBand(14) = 0.00088070636
fft.magnitudeAtBand(15) = 3.6925994e-05
fft.magnitudeAtBand(16) = 0.0013688633
fft.magnitudeAtBand(17) = 0.0020811968
fft.magnitudeAtBand(18) = 0.00039211413
fft.magnitudeAtBand(19) = 1.50605065e-05

stop record did tap

But the magnitudeAtBand value seems to be very small value. Is this correct? How to draw a plot of amplitude?


In the data value, there are negatives. Why is it negative?

John Doe
  • 2,225
  • 6
  • 16
  • 44

1 Answers1

1

The range on OS X for 32 bit floating point samples is -1.0f to 1.0f. The negative numbers are there because the (row of) samples describe an analog waveform signal.

To verify the validity of the data I would suggest to play it back so you can hear if the data is correct.

More complex solutions to verify are to feed a testsignal and view it on an oscilloscope or spectrum analyser.

Ruurd Adema
  • 920
  • 7
  • 17