bidule97
bidule97

Reputation: 1

Regenerate sound from spectrum analysis

I am trying to code in Python a tool that allows me to regenerate a sound from the spectrum analysis done with Audacity. I record a sound and do the spectrum analysis which I export to a text file.

Then I the use the program to store the frequencies and amplitudes in two lists freq and amp.

Then I ask the user how many frequencies he wants to use to regenerate the sound to calculate the step variable I then pick in freq and amp the data to regenerate each sine wave which I add.

Then I plot the final wave unfortunately I never get a wave close to the recording even with using all frequencies. (the graph is always a pure sine wave).

What am I doing wrong?

#!/usr/bin/env python3

import numpy as np
from scipy.io import wavfile

#open and read spectrum export file
filename = input("Enter spectrum export filename: ")
file=open(filename, "r")
values = file.readlines()

#stores freq and amp
freq=[]
amp=[]
count=1
while count<len(values) :
  temp=values[count].split("\t")
  freq.append(float(temp[0]))
  amp.append(10**(float(temp[1])/20))
  count=count+1

# Define the frequency and sampling rate
sampleRate = 44100

t = np.arange(sampleRate*5)  #  Produces a 5 second Audio-File

y = amp[0]*np.sin(2 * np.pi * freq[0] * t)
step=int(len(values)/int(input("how many frequencies to use: ")))
count=step
while count<len(freq) :
    y=y+amp[count]*np.sin(2 * np.pi * freq[count] * t)
    count=count+step

output=input("Enter output filename: ")
wavfile.write(output+".wav", sampleRate, y)

import matplotlib.pyplot as plt
plt.plot(t,y)
plt.show()

Among other tries, I used a very low sample rate (10) and it seemed to work, but the sound was only a few ms

Upvotes: 0

Views: 50

Answers (1)

Tim Roberts
Tim Roberts

Reputation: 54733

You need to divide your timeline by the frequency. That is, t should be seconds, not samples.

Also, when you're selecting frequencies, you don't want to choose every Nth frequency bin. The frequencies have less and less meaning as they go up, so if you only use N, use the first N.

This seems to get pretty close to what you want.

#!/usr/bin/env python3

import sys
import numpy as np
from scipy.io import wavfile

#open and read spectrum export file
if len(sys.argv) > 1:
    filename = sys.argv[1]
else:
    filename = input("Enter spectrum export filename: ")
file=open(filename, "r")

#stores freq and amp
freq=[]
amp=[]
for line in file:
    if not line[0].isdigit():
        continue
    temp=line.split("\t")
    freq.append(float(temp[0]))
    amp.append(10**(float(temp[1])/20))

# Define the frequency and sampling rate
sampleRate = 44100

t = np.arange(sampleRate*5) / sampleRate

step=int(input("how many frequencies to use: "))
y = np.zeros(len(t))
for count in range(step):
    y=y+amp[count]*np.sin(2 * np.pi * freq[count] * t)

output=input("Enter output filename: ")
wavfile.write(output+".wav", sampleRate, y)

import matplotlib.pyplot as plt
plt.plot(t,y)
plt.show()

Purists may like the loop better as:

step=int(input("how many frequencies to use: "))
y = np.zeros(len(t))
for a,f,_ in zip(amp,freq,range(step)):
    y = y + a * np.sin(2 * np.pi * f * t)

Upvotes: 1

Related Questions