This seems like it would be very straight forward but I can't seem to figure out how to map angles between -Pi and Pi to the range 0 to 2Pi. I tried using np.select but it freezes my program for some reason. I need the angles in this range since they will be used as training data for a neural net which can not output negative numbers.
audio = wav.read('/home/chase/Desktop/ge.wav')[1].astype(np.float32)
audio = np.mean(audio, 1)
audio /= np.max(np.abs(audio))
audio = np.array([np.fft.rfft(audio[i:i + FRAME_SIZE]) for i in range(0, len(audio) - len(audio) % FRAME_SIZE, FRAME_SIZE)])
audio /= FRAME_SIZE
audio_mag = np.abs(audio)
audio_phase = np.angle(audio)
#this line freezes the program
audio_phase = np.select(audio_phase < 0 , 2 * np.pi + audio_phase, audio_phase)
I need the audio
Numpy is a scientific computation library in python and has values for a number of numerical constants including pi. You can use numpy. pi or np. pi depending on how you import the library to get the value of pi.
angle() function is used when we want to compute the angle of the complex argument. A complex number is represented by “ x + yi ” where x and y are real number and i= (-1)^1/2 . The angle is calculated by the formula tan-1(x/y).
Here are several different methods complete with timing:
In [1]: import numpy as np; from numpy import linspace, pi
In [2]: N=10000
In [3]: %timeit x=linspace(-pi, pi, N); np.where(x<0 , 2*pi+x, x)
10000 loops, best of 3: 79.1 µs per loop
In [4]: %timeit x=linspace(-pi, pi, N); np.select(x<0 , 2*pi+x, x)
1 loops, best of 3: 354 ms per loop
In [5]: %timeit x=linspace(-pi, pi, N); x[x<0] += 2*pi
10000 loops, best of 3: 82.5 µs per loop
In [6]: %timeit x=linspace(-pi, pi, N); (x + 2*pi)*(x<0) + x*(x>=0)
10000 loops, best of 3: 149 µs per loop
In [7]: %timeit x=linspace(-pi, pi, N); (x + 2*pi)%(2*pi)
10000 loops, best of 3: 192 µs per loop
I find x[x<0] += 2*pi
the most readable, but where(x<0, x+2*pi, x)
is slightly faster. The select
form is by far the slowest.
For comparison, here is the plain linspace function on the same machine:
In [8]: %timeit x=linspace(-pi, pi, N)
10000 loops, best of 3: 35.9 µs per loop
Given that the program is failing on the select and not the far more expensive fft function, you may be running into a low memory condition, with the array paging to disk (both x<0
and 2*pi+x
generate arrays, plus you have the original x
and the return value created by select
). If this is the case, then you may be better off correcting phase frame by frame.
Let us say you have these angles:
>>> angles = np.linspace(-np.pi, np.pi, 10)
>>> angles
array([-3.14159265, -2.44346095, -1.74532925, -1.04719755, -0.34906585,
0.34906585, 1.04719755, 1.74532925, 2.44346095, 3.14159265])
There are two possible ways of doing this ...
numpy
expressions for finding the negative values ... The ones less than zero should be converted to the right value. Something like this:
>>> (2*np.pi + angles) * (angles < 0) + angles*(angles > 0)
array([ 3.14159265, 3.83972435, 4.53785606, 5.23598776, 5.93411946,
0.34906585, 1.04719755, 1.74532925, 2.44346095, 3.14159265])
Remember that in numpy, you can do logical tests ... angles < 0
is a boolean array. However, 1*(angles < 0)
is a numeric array, where True
values are mapped to 1
and False
values are mapped to 0
. You can combine the two concepts to get your answer.
So for that, simply add 2*np.pi
to everything and take the mod. This is exactly like finding the "units place", or converting a number into an octal number etc ...
>>> (angles + 2 * np.pi) % (2 * np.pi)
array([ 3.14159265, 3.83972435, 4.53785606, 5.23598776, 5.93411946,
0.34906585, 1.04719755, 1.74532925, 2.44346095, 3.14159265])
I hope this helps.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With