-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathold_phase_gen.py
92 lines (68 loc) · 3.88 KB
/
old_phase_gen.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#This python script acts a function library used by the other files to the generate phases.
# coding: utf-8
# In[13]:
#inport nessessary libraries.
import os
import numpy as np
import librosa
# In[9]:
#Polar to read convertion of numpy matricies
def polar2real(mag, angle):
#Matrix of magnitudes * the exponent of 1j(imaginary value) * the phase values (-3.14, 3.14)
return mag * np.exp(1j*angle)
# In[10]:
#this function output the frequency increment of each bin, highest freq/bin = [0], lowest freq/bin = [n_fft/2]
def phase_angle_inc_generator(_fftFrameSize, _hop_length, sampleRate):
#Finding the period of each bin's central frequency of my fft.
#to stop a divide by 0.
fft_frequencies = librosa.fft_frequencies(sr=sampleRate, n_fft=_fftFrameSize)
# print("Phase_gen: ", fft_frequencies.shape, fft_frequencies[0], fft_frequencies[1], fft_frequencies[1024])
fft_frequencies[0] = 1
fft_freq_period_sample = sampleRate/fft_frequencies
#Stopping the 0's element of fft_freq_period_sample from being "inf".
#MAJOR ISSUE: 0th element is inf, 1st element is 2048, 1024th element is 2. What is the 0th element and why does this STFT return 1 more value than half the frameSize.
# the answer is probably the reason the phase vocoding sounds lame.
#Going to make the 0th bin phase 0 later in this code.
fft_freq_period_sample[0] = _fftFrameSize
#dividing the hoplength by the period of the bins
# to create an value to increment the phase by for each hop.
# and scaling the the value to a number between 2*PI.
fft_freq_period_angle_hopInc = (_hop_length / fft_freq_period_sample) * 2*np.pi
fft_freq_period_angle_hopInc[0] = 0.0
#return the array of hop incrememnts.
return fft_freq_period_angle_hopInc
# In[11]:
#this function generates an frame of phase values for every frame of magnitude values (numFrames)
def gen_phases(numFrames, _fftFrameSize, _hop_length, sampleRate):
#Get the ammount we are going to increment every bin's phase value by.
phase_angle_inc = phase_angle_inc_generator(_fftFrameSize, _hop_length, sampleRate)
#Initialize a random array of the number of phases in each set with a value between 0 and 2*Pi.
#if we don't start with with random values then we get a sweeping effect when they all start
# from 0 at the begining of the audio.
#this array will be incrememted in the forloop below.
current_phase = np.random.rand(int(_fftFrameSize/2)+1) * 2*np.pi
current_phase[0] = 0.0
#this array holds 0.0 values for every phase value we need.
#This array will be over written with the actual phase values in the forloop below.
new_phases = np.zeros((numFrames, int(_fftFrameSize/2)+1))
#Get an integer i for every frame of phases that we need.
for i in range(numFrames):
#Allocate the array full of 0's with the phase values.
new_phases[i] = current_phase
#Increment current phase but the increment values.
current_phase = current_phase + phase_angle_inc
#Modulo the incremented phase by 2*pi to make sure it stays in the range of phases.
current_phase = current_phase % 2*np.pi
#Minus all the new phase values by Pi so they are a range of -Pi to Pi
new_phases = new_phases-(np.pi)
#Return an array full of frames of phase values (as many frames as numFrames)
return new_phases
# In[12]:
#fft2samples takes in sets of magnitudes and phases and inverts them back into amplitude values.
def fft2samples(_mags, _phases, _hop_length):
#First one must convert the magnitudes and phases in to their real and imaginary values using the polar2real function defined above.
real = polar2real(_mags, _phases)
#Transpose the new matricies and librosa like it the shape (fftSize, numFrames)
real = real.T
#Take the ifft of the data using librosa and the correct hoplength.
return librosa.istft(real, hop_length=_hop_length)