-2

I am trying to recreate musical note using top 10 frequencies returned by Fourier Transform (FFT). Resulting sound does not match the original sound. Not sure if I am not finding frequencies correctly or not generating sound from it correctly. The goal of this code is to match the original sound. Here is my code:

import numpy as np
from scipy.io import wavfile
from scipy.fftpack import fft
import matplotlib.pyplot as plt

i_framerate = 44100
fs, data = wavfile.read('./Flute.nonvib.ff.A4.stereo.wav') # load the data

def findFrequencies(arr_data, i_framerate = 44100, i_top_n =5):
    a = arr_data.T[0] # this is a two channel soundtrack, I get the first track
#        b=[(ele/2**8.)*2-1 for ele in a] # this is 8-bit track, b is now normalized on [-1,1)
    y = fft(a) # calculate fourier transform (complex numbers list)

    xf = np.linspace(0,int(i_framerate/2.0),int((i_framerate/2.0))+1) /2 # Need to find out this last /2 part
    yf = np.abs(y[:int((i_framerate//2.0))+1])

    plt.plot(xf,yf)

    yf_top_n = np.argsort(yf)[-i_top_n:][::-1]
    amp_top_n =  yf[yf_top_n] / np.max(yf[yf_top_n])
    freq_top_n = xf[yf_top_n]

    return freq_top_n, amp_top_n

def createSoundData(a_freq, a_amp, i_framerate=44100, i_time = 1, f_amp = 1000.0):
    n_samples = i_time * i_framerate

    x = np.linspace(0,i_time, n_samples)
    y = np.zeros(n_samples)
    for i in range(len(a_freq)):
        y += np.sin(2 * np.pi * a_freq[i] * x)* f_amp * a_amp[i]
    data2 = np.c_[y,y] # 2 Channel sound
    return data2

top_freq , top_freq_amp = findFrequencies(data, i_framerate = 44100 , i_top_n = 200)

print('Frequencies: ',top_freq)
print('Amplitudes : ',top_freq_amp) 

soundData = createSoundData(top_freq, top_freq_amp,i_time = 2, f_amp = 50 / len(top_freq))
wavfile.write('createsound_A4_v6.wav',i_framerate,soundData)

1 Answers1

1

The top 10 spectral frequencies in a musical note are not the same as the center frequencies of the top 10 FFT result bin magnitudes. The actual frequency peaks can be between the FFT bins.

Not only can the frequency peak information be between FFT bins, but the phase information required to reproduce any note transients (attack, decay, etc.) can also be between bins. Spectral information that is between FFT bins is carried by a span (up to the full width) of the complex FFT result.

hotpaw2
  • 70,107
  • 14
  • 90
  • 153