2

I have the following function where I'm trying to do FFT on a audio file and reset the phases and putting it all back together as a new audio file. First I do the FFT on both channels and then normalize the amplitudes. When I'm trying to do the final matrix from which to save the audio file it says:

ValueError: matrix must be 2-dimensional

even though it is 2-dimensional. Also I'm getting this warning:

ComplexWarning: Casting complex values to real discards the imaginary part arr = N.array(data, dtype=dtype, copy=copy)

I'm not sure if my approach to deal with amplitudes and phases is the best anyway so I'd appreciate any tips how to get my code working.

import scipy.fftpack as fft
from scipy.io import wavfile
import numpy as np
from scipy.signal import hanning
import math



def readNormalize(location):

    samplerate, data = wavfile.read(location)

    leftChan = data.T[0] # first track of audio
    rightChan = data.T[1]

    length = len(leftChan)
    fftLeft = fft.fft(leftChan[0:], length)
    fftRight = fft.fft(rightChan[0:], length)

    #length is half(positive frequency) of the the fft data, because other half is negative (complex conjugate)
    length = int(length/2)

    #getting the normalization value
    ownSum = 0;
    for i in range(0, length):
        ownSum += abs(fftLeft[i])
    normalizer = 1/ownSum

    amplitudesRight = []
    phasesRight = []

    phasesLeft = []
    amplitudesLeft = []

    #normalizing and setting the phases
    for i in range(0,length):
        #LEFT CHAN
        amplitudesLeft.append((abs(fftLeft[i])*normalizer))
        phasesLeft.append(0)
        #RIGHT CHAN
        amplitudesRight.append((abs(fftRight[i])*normalizer))
        phasesRight.append((math.pi/2))

        #TRIED THIS ASWELL BUT CAN'T APPEND LIKE THIS
        #fftLeft[i] = (abs(fftLeft[i])*normalizer)
        #fftLeft[i][i] = 0

        #fftRight[i] = (abs(fftRight[i])*normalizer)
        #fftRight[i][i] = math.pi/2


    #putting the phases and amps back to complex form(at least trying)
    matrixLeft = np.matrix([amplitudesLeft, phasesLeft], dtype=np.complex128)
    matrixRight = np.matrix([amplitudesRight, phasesRight], dtype=np.complex128)

    #ifft for the complex
    ifftLeft = fft.ifft(matrixLeft)
    ifftRight = fft.ifft(matrixRight)

    #putting all the data back together, 
    #doesn't work, says that matrix has to be 2-dimensional
    outputMatrix = np.matrix([ifftLeft, ifftRight],dtype=np.int16)

    wavfile.write('test.wav',samplerate, outputMatrix)

Any ideas? Thanks!

Biffen
  • 6,249
  • 6
  • 28
  • 36
bnc
  • 57
  • 2
  • 14
  • >If the data type of x is real, a “real FFT” algorithm is automatically used – f5r5e5d Oct 08 '17 at 00:07
  • I'm not sure if I understand what yo mean, can you clarify it a little bit? Like where I'm doing the mistake? – bnc Oct 08 '17 at 10:43
  • And also if somebody can suggest a better way to manipulate phases and amplitudes I'd be happy to hear. My solution seems to involve quite many steps and ending up with many arrays so I feel there is probably a lot effective way to do what I'm trying to do. – bnc Oct 08 '17 at 12:06
  • sorry, confusing numpy's fft with scipy fftpack, I'd use `np.fft.rfft` `irfft`. Then you only have to modify phase of the 1st N/2 frequencies and not worry about reversing and conjugating. FFT phase is best modified by multiplying each frequency complex point/bin by `np.exp(1j*d_phase)` where `d_phase` is the radian phase shift you want to apply at each frequency – f5r5e5d Oct 08 '17 at 12:57
  • Okay thanks, I will try that! Does the rfft accept stereo or do I have to have the channels separated? Also if I want to set all the phases to to some specific values can i do np.exp(0j) or np.exp((math.pi/2)j)? I'm trying to recreate an algorithm used by this one sound artist where left channel is set to 90 degree phase and right channel 0 degree. – bnc Oct 08 '17 at 14:34

0 Answers0