0

I've set up a python audio stream and fft using bits of code for an audio spectrum analyser https://github.com/markjay4k/Audio-Spectrum-Analyzer-in-Python/blob/master/audio%20spectrum_pt2_spectrum_analyzer.ipynb (I removed all the plotting code), I want to find the most prominent frequency from my fft.

import numpy as np
import pyaudio
import struct
from scipy.fftpack import fft
import sys
import time


class AudioStream(object):
    def __init__(self):

        # stream constants
        self.CHUNK = 1024 * 2
        self.FORMAT = pyaudio.paInt16
        self.CHANNELS = 1
        self.RATE = 44100
        self.pause = False

        # stream object
        self.p = pyaudio.PyAudio()
        self.stream = self.p.open(
            format=self.FORMAT,
            channels=self.CHANNELS,
            rate=self.RATE,
            input=True,
            output=True,
            frames_per_buffer=self.CHUNK,
        )
        self.start_recording()

    def start_recording(self):

        print('stream started')

        while True:
            #Get data from stream and unpack to data_int
            data = self.stream.read(self.CHUNK)
            data_int = struct.unpack(str(2 * self.CHUNK) + 'B', data)

            # compute FFT
            yf = fft(data_int)

            # find the most prominent frequency from this fft


if __name__ == '__main__':
    AudioStream()

Below is a screenshot of the output from the non-adapted audio spectrum analyzer on github, showing the value I want to get from the fft (most prominent frequency). In this case, the value is around 1555Hz.

Image of desired value

Peter
  • 848
  • 8
  • 14
  • 1
    Related to [Find value and bin of fft max](https://stackoverflow.com/questions/37049887/print-highest-peak-value-of-the-frequency-domain-plot) – DarrylG Jun 03 '20 at 15:57
  • here is a crisp concise example of what the FFT means and how to handle its output https://www.youtube.com/watch?v=mkGsMWi_j4Q – Scott Stensland Jun 04 '20 at 14:57

2 Answers2

1

I found some code that does this using the question Audio Frequencies in Python, I'll leave it bellow:

            # compute FFT
            fftData=abs(np.fft.rfft(data_int))**2
            # find the maximum
            which = fftData[1:].argmax() + 1
            # use quadratic interpolation around the max
            if which != len(fftData)-1:
                y0,y1,y2 = np.log(fftData[which-1:which+2:])
                x1 = (y2 - y0) * .5 / (2 * y1 - y2 - y0)
                # find the frequency and output it
                thefreq = (which+x1)*self.RATE/self.CHUNK
                print(f"The freq is {thefreq} Hz.")
            else:
                thefreq = which*self.RATE/self.CHUNK
                print (f"The freq is {thefreq} Hz.")
Peter
  • 848
  • 8
  • 14
0

If yf is the result from the fft, then you need to find the maximum value in it, correct? If it is a numpy array, the amax() function will help you here. @DarrylG points you in the right direction; Print highest peak value of the frequency domain plot

asylumax
  • 781
  • 1
  • 8
  • 34
  • This just returns a load of complex numbers :/ – Peter Jun 03 '20 at 15:56
  • 1
    @Peter if you aspire to becoming a productive independent software engineer you need to muster up the horns to master knowing how to handle an array of complex numbers – Scott Stensland Jun 03 '20 at 16:37
  • @ScottStensland Yep, you're right. I don't even know what an fft is. I was trying to build a piano tuner for a friend, but I guess this isn't for me. – Peter Jun 04 '20 at 14:09
  • 2
    Don't give up! The FFT part isn't too horrible. https://math.stackexchange.com/questions/1002/fourier-transform-for-dummies – asylumax Jun 04 '20 at 14:27
  • @asylumax Thanks a lot! I'll read this and give it another shot. – Peter Jun 04 '20 at 15:51