def __init__(self, chord, first_single, second_single, third_single):
        self.audio_reader = Audio_Reader()
        self.chord = self.audio_reader.read_sample(chord)
        self.first_single = self.audio_reader.read_sample(first_single)
        self.second_single = self.audio_reader.read_sample(second_single)
        self.third_single = self.audio_reader.read_sample(third_single)

        self.chord_file = chord
        self.first_single_file = first_single
        self.second_single_file = second_single
        self.third_single_file = third_single
    def __init__(self, chord, first_single, second_single, third_single):
        self.audio_reader = Audio_Reader()
        self.chord = self.audio_reader.read_sample(chord)
        self.first_single = self.audio_reader.read_sample(first_single)
        self.second_single = self.audio_reader.read_sample(second_single)
        self.third_single = self.audio_reader.read_sample(third_single)

        self.chord_file = chord
        self.first_single_file = first_single
        self.second_single_file = second_single
        self.third_single_file = third_single
class Threshold_Finder(object):
    def __init__(self, chord, first_single, second_single, third_single):
        self.audio_reader = Audio_Reader()
        self.chord = self.audio_reader.read_sample(chord)
        self.first_single = self.audio_reader.read_sample(first_single)
        self.second_single = self.audio_reader.read_sample(second_single)
        self.third_single = self.audio_reader.read_sample(third_single)

        self.chord_file = chord
        self.first_single_file = first_single
        self.second_single_file = second_single
        self.third_single_file = third_single

    def get_FFT(self, sample):
        # TODO: check if the fft_lengths are the same and if not decide what to do with it...
        fft_length = int(
            self.audio_reader.get_duration(self.chord_file) *
            self.audio_reader.get_framerate(self.chord_file))

        if is_Prime(fft_length):
            FFT = numpy.fft.fft(sample, n=fft_length - 1)
        else:
            FFT = numpy.fft.fft(sample, n=fft_length)
        return FFT

    def find_least_squares(self):

        fft_chord = self.get_FFT(self.chord)
        fft_first = self.get_FFT(self.first_single)
        fft_second = self.get_FFT(self.second_single)
        fft_third = self.get_FFT(self.third_single)

        chord_array = []
        first_array = []
        second_array = []
        third_array = []
        for i in range(len(fft_chord)):
            chord_array.append(fft_chord[i].real)
            chord_array.append(fft_chord[i].imag)
            first_array.append(fft_first[i].real)
            first_array.append(fft_first[i].imag)
            second_array.append(fft_second[i].real)
            second_array.append(fft_second[i].imag)
            third_array.append(fft_third[i].real)
            third_array.append(fft_third[i].imag)

        A = numpy.array([first_array, second_array, third_array]).T
        b = chord_array

        # x: coefficients for each transform for single notes, rnorm: sum of squares of magnitudes of the noise.
        x, rnorm = scipy.optimize.nnls(A, b)
        average_noise_power = rnorm**2 / len(fft_chord)
        return (x, rnorm, average_noise_power)

    def get_FFT_of_noise(self, x, rnorm):
        sum_of_singles = x[0] * self.get_FFT(
            self.first_single) + x[1] * self.get_FFT(
                self.second_single) + x[2] * self.get_FFT(self.third_single)
        fft = scipy.absolute(self.get_FFT(self.chord) - sum_of_singles)
        return fft

    def get_sum_of_squares(self, fft):
        sum_of_squares = 0.0
        for i in range(len(fft)):
            sum_of_squares += scipy.absolute(fft[i]) * sscipy.absolute(fft[i])
        return sum_of_squares

    def plot_power_spectrum(self, fft):
        T = int(600)

        pylab.figure('Power spectrum')
        pylab.plot(scipy.absolute(fft[:T]) * scipy.absolute(fft[:T]), )
        pylab.xlabel('Frequency [Hz]')
        pylab.ylabel('Power spectrum []')
        pylab.show()
class Threshold_Finder(object):

    def __init__(self, chord, first_single, second_single, third_single):
        self.audio_reader = Audio_Reader()
        self.chord = self.audio_reader.read_sample(chord)
        self.first_single = self.audio_reader.read_sample(first_single)
        self.second_single = self.audio_reader.read_sample(second_single)
        self.third_single = self.audio_reader.read_sample(third_single)

        self.chord_file = chord
        self.first_single_file = first_single
        self.second_single_file = second_single
        self.third_single_file = third_single

    def get_FFT(self, sample):
        # TODO: check if the fft_lengths are the same and if not decide what to do with it...
        fft_length = int(self.audio_reader.get_duration(self.chord_file) * self.audio_reader.get_framerate(self.chord_file))

        if is_Prime(fft_length):
            FFT = numpy.fft.fft(sample, n=fft_length-1)
        else:
            FFT = numpy.fft.fft(sample, n=fft_length)
        return FFT

    def find_least_squares(self):
        
        fft_chord = self.get_FFT(self.chord)
        fft_first = self.get_FFT(self.first_single)
        fft_second = self.get_FFT(self.second_single)
        fft_third = self.get_FFT(self.third_single)
        
        chord_array = []
        first_array = []
        second_array = []
        third_array = []
        for i in range(len(fft_chord)):
            chord_array.append(fft_chord[i].real)
            chord_array.append(fft_chord[i].imag)
            first_array.append(fft_first[i].real)
            first_array.append(fft_first[i].imag)
            second_array.append(fft_second[i].real)
            second_array.append(fft_second[i].imag)
            third_array.append(fft_third[i].real)
            third_array.append(fft_third[i].imag)

        A = numpy.array([first_array, second_array, third_array]).T
        b = chord_array
        
        # x: coefficients for each transform for single notes, rnorm: sum of squares of magnitudes of the noise.
        x, rnorm = scipy.optimize.nnls(A, b)
        average_noise_power = rnorm ** 2 / len(fft_chord)
        return (x, rnorm, average_noise_power)

    def get_FFT_of_noise(self, x, rnorm):
        sum_of_singles = x[0] * self.get_FFT(self.first_single) + x[1] * self.get_FFT(self.second_single) + x[2] * self.get_FFT(self.third_single)
        fft = scipy.absolute(self.get_FFT(self.chord) - sum_of_singles)
        return fft

    def get_sum_of_squares(self, fft):
        sum_of_squares = 0.0
        for i in range(len(fft)):
            sum_of_squares += scipy.absolute(fft[i]) * sscipy.absolute(fft[i])
        return sum_of_squares

    def plot_power_spectrum(self, fft):
        T = int(600)

        pylab.figure('Power spectrum')
        pylab.plot(scipy.absolute(fft[:T]) * scipy.absolute(fft[:T]),)
        pylab.xlabel('Frequency [Hz]')
        pylab.ylabel('Power spectrum []')
        pylab.show()