3

I am familiar with python but new to numpy, so please pardon me if I am wrong.

I am trying to read a .wav file having multiple frequencies (separated by silence). So far I've been able to read the values and find the various parts in the file where there is a sound. Then, I am trying to find the Discrete Cosine Transform and calculate the frequencies from it (ref: how to extract frequency associated with fft values in python)

However, I'm getting an error:

index 46392 is out of bounds for axis 0 with size 25

Here's my code:

import wave
import struct
import numpy as np

def isSilence(windowPosition):
    sumVal = sum( [ x*x for x in sound[windowPosition:windowPosition+windowSize+1] ] )
    avg = sumVal/(windowSize)
    if avg <= 0.0001:
        return True
    else:
        return False

#read from wav file
sound_file = wave.open('test.wav', 'r')
file_length = sound_file.getnframes()
data = sound_file.readframes(file_length)
sound_file.close()
#data = struct.unpack("<h", data)
data = struct.unpack('{n}h'.format(n=file_length), data)
sound = np.array(data)
#sound is now a list of values

#detect silence and notes
i=0
windowSize = 2205
windowPosition = 0
listOfLists = []
listOfLists.append([])
maxVal = len(sound) - windowSize
while True:
    if windowPosition >= maxVal:
        break
    if not isSilence(windowPosition):
        while not isSilence(windowPosition):
            listOfLists[i].append(sound[windowPosition:windowPosition+ windowSize+1])
            windowPosition += windowSize
        listOfLists.append([]) #empty list
        i += 1
    windowPosition += windowSize

frequencies = []
#Calculating the frequency of each detected note by using DFT
for signal in listOfLists:
    if not signal:
        break
    w = np.fft.fft(signal)
    freqs = np.fft.fftfreq(len(w))
    l = len(signal)

    #imax = index of first peak in w
    imax = np.argmax(np.abs(w))
    fs = freqs[imax]

    freq = imax*fs/l
    frequencies.append(freq)

print frequencies

Edit: Here is the traceback:

Traceback (most recent call last):
  File "final.py", line 61, in <module>
    fs = freqs[imax]
IndexError: index 46392 is out of bounds for axis 0 with size 21
Community
  • 1
  • 1
Nikhil Sardana
  • 365
  • 1
  • 4
  • 14
  • 2
    *" I'm getting an error:..."* Always include the *complete* error message (i.e. the full traceback) in your question. The traceback shows which line triggered the error. – Warren Weckesser Dec 06 '16 at 17:06
  • @WarrenWeckesser okay. The line `fs = freqs[imax]` was causing the error. In the link I provided above, the fourier transform was one dimensional. But my test file gave a multi-dimensional list. – Nikhil Sardana Dec 06 '16 at 17:09
  • Probably multi-channel (stereo)? If so, reduce to mono by taking the mean of the two channels. – Ahmed Fasih Dec 06 '16 at 17:31

1 Answers1

0

The problem was that I assumed listOfLists was actually a list of lists, but actually it was a list of list of lists. The line:

        listOfLists[i].append(sound[windowPosition:windowPosition+ windowSize+1])

was appending a list everytime, but I assumed it was appending the elements to existing list.

For instance, if listOfLists was:

[ [1,2,3] ]

Then, listOfLists[0].append([4,5,6]) would give:

[ [ [1,2,3],[4,5,6] ] ]

But I was expecting:

[ [1,2,3,4,5,6] ]

Replacing the problematic line with the code below worked for me:

for v in sound[windowPosition:windowPosition+windowSize+1]:
            listOfLists[i].append(v)
Nikhil Sardana
  • 365
  • 1
  • 4
  • 14