1

I want to determine frequencies present in a music file. It will retrive a chunk of data from music file and print the frequencies present in it. then it will pick another chunk of data. Is it possible to make it using python? I am new in this domain. If anyone could help me to do this I will be highly thankfull to him.My target device is raspberry pi.

import pyaudio
import wave
import numpy as np

chunk = 2048
wf = wave.open('/home/pi/music.wav', 'rb')
swidth = wf.getsampwidth()
RATE = wf.getframerate()
window = np.blackman(chunk)
p = pyaudio.PyAudio()
stream = p.open(format =
    p.get_format_from_width(wf.getsampwidth()),
    channels = wf.getnchannels(),
    rate = RATE,
    output = True)
data = wf.readframes(chunk)
while len(data) != '':
stream.write(data)
indata = np.array(wave.struct.unpack("%dh"%(len(data)/swidth),\
                             data))*window
fftdata=abs(np.fft.rfft(indata))**2
fftData=abs(np.fft.rfft(indata))**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)*RATE/chunk
    print "The freq is %f Hz." % (thefreq)
else:
    thefreq = which*RATE/chunk
    print "The freq is %f Hz." % (thefreq)
# read some more data
  data = wf.readframes(chunk)
if data:
    stream.write(data)
stream.close()
p.terminate()

my above program is working fine for single frequency sample. but for a song it shows an error at the line indata = np.array(wave.struct.unpack("%dh"%(len(data)/swidth),data))*window . error msg is operands could not be broadcast together with shapes. how to fix the problem??

Akash Nil
  • 693
  • 10
  • 26
  • 2
    So you basically want to perform a fft with python? – meneldal Jun 12 '15 at 07:04
  • If you provide one example it will be helpfull to understand. @ meneldal – Anup Sarkar Jun 12 '15 at 07:11
  • You might want to read a bit into the Fourier transforms so you can understand the output. Unless you have a perfect sine wave you won't have something simple. – meneldal Jun 12 '15 at 07:13
  • 2
    you now have 3 questions asking essentially the same thing: see [here](http://stackoverflow.com/questions/30728737/separate-frequencies-from-music) and [here](http://stackoverflow.com/questions/30637384/how-to-separate-frequency-of-audiofile). If you are not satified with the answers to your previous questions, please improve the original question instead of asking again. – tmdavison Jun 12 '15 at 09:10

1 Answers1

1

To determine the frequencies in a signal (for example an audio signal) you can use a Fourier Transform. The most common numerical implementation is called fft (for Fast Fourier Transform).

Python does have what you need for this: Discrete Fourier Transform (numpy.fft).

So the first thing to do is put your data in an array and then send it to the function.

Then you need to do a little math to get the frequency. Thankfully you can look up Wikipedia for converting between time and frequency. Since you didn't say the sampling frequency I can't give you a number but you can follow the formula:

f=1/T*i with T the total time and i the table index.

meneldal
  • 1,717
  • 1
  • 21
  • 30
  • I edited my post with a code but it is not working. what is the problem in this code. @ meneldal – Akash Nil Jun 12 '15 at 07:24
  • Please say what is not working exactly. Does it crash? Returns nothing? Do you even know what the fft transform of your audio should return? – meneldal Jun 12 '15 at 07:29
  • It prints all the frequiencies near 10 Hz. The instructions I am using to convert fftdata into frequency is it correct? I think the problem lies in the conversion process.@ meneldal – Akash Nil Jun 12 '15 at 07:38
  • I don't know what is your input signal so I don't know if it's what you should get. 10z does seem small. I'll take another look at the code for some math mistake. – meneldal Jun 12 '15 at 07:43
  • there are many friequencies present in the file some may be around 250 Hz.. I also want to set a threshold. suppose a chunk contains 50 frequencies. if 8 of them amplitute is above threshold then i want to print 8 values.@ meneldal – Akash Nil Jun 12 '15 at 07:59
  • Well usually a frequency is more than a single value peak so if you compare to a treshold you would get some very close frequencies. The easiest fix around this is to select only peaks after some filtering to remove the noise. It would make the scope of your question much larger and would work better as a different question. – meneldal Jun 12 '15 at 09:22