G4UFS
Posts: 10
Joined: Tue Jan 08, 2013 1:24 am

Help Please. Realtime audio FFT display using Python

Sat Jun 20, 2015 1:16 pm

Hi,

I am trying to build the basics of an audio FFT display with Python. With the help of code from another forum post, I have managed to get something going but the resolution of the FFT display is only around 100Hz. I need the resolution to be much better than this - around a couple of Hz. I really don know how I can increase it but the reading I have done about FFT certainly suggests its possible.

Can anyone help me?

Regards
Dave

Code: Select all


#!/usr/bin/env python

import alsaaudio as aa
from time import sleep
from struct import unpack
import numpy as np

# Set up audio
sample_rate = 9600
no_channels = 1
chunk = 4096 # Use a multiple of 8
data_in = aa.PCM(aa.PCM_CAPTURE, aa.PCM_NORMAL)
data_in.setchannels(no_channels)
data_in.setrate(sample_rate)
data_in.setformat(aa.PCM_FORMAT_S16_LE)
data_in.setperiodsize(chunk)

def calculate_levels(data):
   # Convert raw data to numpy array
    data = unpack("%dh"%((len(data)/2)),data)
    data = np.array(data, dtype='h')
   # Apply FFT - real data so rfft used
    fourier=np.fft.rfft(data)
   # Remove last element in array to make it the same size as chunk
    fourier=np.delete(fourier,len(fourier)-1)
   # Find amplitude
    power = (np.log10(np.abs(fourier))**2)-5
#    for i in range (0,len(fourier)):
    for i in range (4,50):
        for stars in range(0,int(power[i])):
                print "*",
        print ""
    print "End"
    return

while True:
   # Read data
   data_in.setperiodsize(chunk)
   l,data = data_in.read()
   calculate_levels(data)

/code]

User avatar
PeterO
Posts: 5878
Joined: Sun Jul 22, 2012 4:14 pm

Re: Help Please. Realtime audio FFT display using Python

Sat Jun 20, 2015 1:29 pm

Before I try to answer your questions.... How well do you understand what an FFT does ?

PeterO
Discoverer of the PI2 XENON DEATH FLASH!
Interests: C,Python,PIC,Electronics,Ham Radio (G0DZB),1960s British Computers.
"The primary requirement (as we've always seen in your examples) is that the code is readable. " Dougie Lawson

User avatar
PeterO
Posts: 5878
Joined: Sun Jul 22, 2012 4:14 pm

Re: Help Please. Realtime audio FFT display using Python

Sat Jun 20, 2015 1:37 pm

code tag fixed

Code: Select all


#!/usr/bin/env python

import alsaaudio as aa
from time import sleep
from struct import unpack
import numpy as np

# Set up audio
sample_rate = 9600
no_channels = 1
chunk = 4096 # Use a multiple of 8
data_in = aa.PCM(aa.PCM_CAPTURE, aa.PCM_NORMAL)
data_in.setchannels(no_channels)
data_in.setrate(sample_rate)
data_in.setformat(aa.PCM_FORMAT_S16_LE)
data_in.setperiodsize(chunk)

def calculate_levels(data):
   # Convert raw data to numpy array
    data = unpack("%dh"%((len(data)/2)),data)
    data = np.array(data, dtype='h')
   # Apply FFT - real data so rfft used
    fourier=np.fft.rfft(data)
   # Remove last element in array to make it the same size as chunk
    fourier=np.delete(fourier,len(fourier)-1)
   # Find amplitude
    power = (np.log10(np.abs(fourier))**2)-5
#    for i in range (0,len(fourier)):
    for i in range (4,50):
        for stars in range(0,int(power[i])):
                print "*",
        print ""
    print "End"
    return

while True:
   # Read data
   data_in.setperiodsize(chunk)
   l,data = data_in.read()
   calculate_levels(data)

Discoverer of the PI2 XENON DEATH FLASH!
Interests: C,Python,PIC,Electronics,Ham Radio (G0DZB),1960s British Computers.
"The primary requirement (as we've always seen in your examples) is that the code is readable. " Dougie Lawson

G4UFS
Posts: 10
Joined: Tue Jan 08, 2013 1:24 am

Re: Help Please. Realtime audio FFT display using Python

Sat Jun 20, 2015 1:42 pm

Hi Peter,

I know that the FFT will convert my audio stream in the time domain to the frequency domain. I understand it does this by sampling the values of the audio stream at intervals and builds a frame of numbers that can be manipulated by mathematical magic into a corresponding set of numbers that represent aptitude of the frequencies present in the original audio stream in the frequency domain.

I understand that the sample rate has to be at least twice that of the frequencies present in the audio stream. Since my application should not contain frequencies above around 3kHz, I the code I included sets the sample rate at 9600. However, I don't understand the 'chunk' and the line :-

data = unpack("%dh"%((len(data)/2)),data)

Thank you so much for your response so far

Regards
Dave

osol52
Posts: 4
Joined: Thu Jun 18, 2015 1:52 pm

Re: Help Please. Realtime audio FFT display using Python

Sat Jun 20, 2015 1:50 pm

I need quite a bit of help with the fft's. I understand the general concept but also have questions when it comes to F.M. radio and the conversion into audio, then taking showing an fft. (by the way, do you think that it is an fft or a fft, since f- sounds like it starts with a vowel but is in fact a consonant?)

User avatar
PeterO
Posts: 5878
Joined: Sun Jul 22, 2012 4:14 pm

Re: Help Please. Realtime audio FFT display using Python

Sat Jun 20, 2015 1:54 pm

First problem I see it that you are not windowing your input in anyway, so spectral leakage will probably be a problem.
https://en.wikipedia.org/wiki/Window_function

To increase frequency resolution you have to decrease temporal resolution, in other words sample for longer which means a bigger "chunk" size.

However if my "back of an envelope" calculations are correct I think with your current sampling rate and chunk size you should already have a fft bucket size of 2-3 Hz.

PeterO
G0DZB

PS:

In my experience it is best to get the FFT and display part of programs working with programatically generated "known input" data such as a square wave or sine wave before even thinking about trying to transform real world data such as samples from a sound card.
You might find this useful http://www.peteronion.org.uk/FFT/FastFourier.html
Discoverer of the PI2 XENON DEATH FLASH!
Interests: C,Python,PIC,Electronics,Ham Radio (G0DZB),1960s British Computers.
"The primary requirement (as we've always seen in your examples) is that the code is readable. " Dougie Lawson

G4UFS
Posts: 10
Joined: Tue Jan 08, 2013 1:24 am

Re: Help Please. Realtime audio FFT display using Python

Sat Jun 20, 2015 2:45 pm

Thanks Peter,

I thought 9600 / 4096 = 2.3Hz too but no matter what I do the chunk size, I still get a resolution of around 100Hz.

I have a frequency generator which is inputting AF into a USB sound card on the Pi. I run the code above and can see a 'graphical' representation of the sine wave (or square wave) from the signal generator. You are right in that something is not right with the distribution of the graph and I will read up on windowing but I would still have thought that the distribution would have been more granular. Its not until I start to move the frequency in 100Hz steps that I start to see the chart move. Its as if the chunk size is doing nothing - I assume the greater the chunk size would give me more bins which would have a smaller frequency increment?

User avatar
PeterO
Posts: 5878
Joined: Sun Jul 22, 2012 4:14 pm

Re: Help Please. Realtime audio FFT display using Python

Sat Jun 20, 2015 3:00 pm

G4UFS wrote:Thanks Peter,

I thought 9600 / 4096 = 2.3Hz too but no matter what I do the chunk size, I still get a resolution of around 100Hz.
Yes that is my thought as well.
I have a frequency generator which is inputting AF into a USB sound card on the Pi. I run the code above and can see a 'graphical' representation of the sine wave (or square wave) from the signal generator.
Have you tried plotting the raw, un-transformed data ? That will help you to see if the signal level is appropriate. Your sig gen's output could be too low (in the noise) or too high (clipping).
You are right in that something is not right with the distribution of the graph and I will read up on windowing but I would still have thought that the distribution would have been more granular. Its not until I start to move the frequency in 100Hz steps that I start to see the chart move. Its as if the chunk size is doing nothing - I assume the greater the chunk size would give me more bins which would have a smaller frequency increment?
If I get a chance later on I'll try running your code here and see what it produces. (I have USB sound card I can use on my PI)

PeterO
G0DZB
Discoverer of the PI2 XENON DEATH FLASH!
Interests: C,Python,PIC,Electronics,Ham Radio (G0DZB),1960s British Computers.
"The primary requirement (as we've always seen in your examples) is that the code is readable. " Dougie Lawson

G4UFS
Posts: 10
Joined: Tue Jan 08, 2013 1:24 am

Re: Help Please. Realtime audio FFT display using Python

Sat Jun 20, 2015 3:08 pm

Not sure how to analyse the un-transformed data but I have the signal generator set for 2 volts input and have adjusted it from zero up to 3V. I don't want to over drive it so have not gone beyond this level.

You will note that there is a little manipulation applied to the transformed data in the line :-

power = (np.log10(np.abs(fourier))**2)-5

This was a very rough method of getting rid of the noise and only displaying the peaks where the signal is

Thanks again for looking

Regards
Dave

User avatar
PeterO
Posts: 5878
Joined: Sun Jul 22, 2012 4:14 pm

Re: Help Please. Realtime audio FFT display using Python

Sat Jun 20, 2015 4:46 pm

To start with I would remove ALL processing on the samples, and try to get a meaningful display of the raw data. That will let you see if the amplitude is about right, and that one cycle takes the number of samples you expect. Once you know that you can move on to trying to transform them.

I always take very small steps when doing these sorts of things for the first time. It allows you to build confidence that each step is working correctly before moving on to the next bit of the problem/solution.
I rarely write more that a dozen lines of code without testing them.

PeterO
G0DZB
Discoverer of the PI2 XENON DEATH FLASH!
Interests: C,Python,PIC,Electronics,Ham Radio (G0DZB),1960s British Computers.
"The primary requirement (as we've always seen in your examples) is that the code is readable. " Dougie Lawson

User avatar
PeterO
Posts: 5878
Joined: Sun Jul 22, 2012 4:14 pm

Re: Help Please. Realtime audio FFT display using Python

Sat Jun 20, 2015 6:55 pm

I've spent some time playing with your code on my desktop machine (Mint 17 AMD_64). I'm not sure what I'm seeing, but it is not what I expected. Data from alsa seems mostly OK but first few values in every buffer are wrong. MOre investigation needed but that will have to wait.

PeterO
Discoverer of the PI2 XENON DEATH FLASH!
Interests: C,Python,PIC,Electronics,Ham Radio (G0DZB),1960s British Computers.
"The primary requirement (as we've always seen in your examples) is that the code is readable. " Dougie Lawson

G4UFS
Posts: 10
Joined: Tue Jan 08, 2013 1:24 am

Re: Help Please. Realtime audio FFT display using Python

Sat Jun 20, 2015 7:00 pm

Thanks Peter,

I am new to Python and am reading up on how to view the values of the data array. What I see from the length of the data returned from the alsaaudio read line is that the its the same no matter what chunk size I use. It only changes when I change the sample rate. Am I wrong or should the length change?

Regards
Dave

User avatar
davef21370
Posts: 897
Joined: Fri Sep 21, 2012 4:13 pm
Location: Earth But Not Grounded

Re: Help Please. Realtime audio FFT display using Python

Sun Jun 21, 2015 5:49 am

viewtopic.php?f=32&t=35838#
Similar project that someone got working.

Dave.
Apple say... Monkey do !!

Return to “Python”