void MedianSeparator::convertToSpectrogram() { // create STFT object to perform FFT ScopedPointer<STFT> stft = new STFT(WINDOW_SIZE); stft->initWindow(1); // initialise hann window // 2d array to hold pointer to sample data float* bufferData[2]; // 2d array of complex floats to hold complex spectrogram data after fft std::complex<float>* spectrogramData[2]; for (int i = 0; i < 2; i++) { // initialise structures to hold audio data in different forms bufferData[i] = new float[WINDOW_SIZE]; spectrogram[i] = MatrixXcf::Zero((WINDOW_SIZE / 2) + 1, numCols); // holds entire spectrogram spectrogramData[i] = new std::complex<float>[(WINDOW_SIZE/2) + 1]; } // loop through each column of spectrogram for (int column = 0; column < numCols; column++) { // for each channel for (int i = 0; i < numChannels; i++) { // get pointer to sample data bufferData[i] = (float*)samples.getReadPointer(i, startSample); // perform FFT float* fftData = stft->performForwardTransform(bufferData[i]); // convert from real to complex spectum data spectrogramData[i] = stft->realToComplex(fftData, WINDOW_SIZE); // fill column in spectrogram with complex data from FFT for (int sample = 0; sample < 2049; sample++) { spectrogram[i](sample, column) = spectrogramData[i][sample]; } } // increment beginning sample by HOP_SIZE (1024) startSample += HOP_SIZE; } }
void MedianSeparator::writeFiles() { ScopedPointer<ISTFT> istft = new ISTFT(); istft->initWindow(1); // Matrices to hold real number data after conversion Eigen::MatrixXf harmonicSpectrogramReal_Left; Eigen::MatrixXf harmonicSpectrogramReal_Right; Eigen::MatrixXf percussiveSpectrogramReal_Left; Eigen::MatrixXf percussiveSpectrogramReal_Right; // initialise with zeros harmonicSpectrogramReal_Left = MatrixXf::Zero(WINDOW_SIZE, numCols); harmonicSpectrogramReal_Right = MatrixXf::Zero(WINDOW_SIZE, numCols); percussiveSpectrogramReal_Left = MatrixXf::Zero(WINDOW_SIZE, numCols); percussiveSpectrogramReal_Right = MatrixXf::Zero(WINDOW_SIZE, numCols); // convert complex spectrogram data to real spectrogram data harmonicSpectrogramReal_Left = istft->complexToReal(resynthSpectrogram_H[0]); harmonicSpectrogramReal_Right = istft->complexToReal(resynthSpectrogram_H[1]); percussiveSpectrogramReal_Left = istft->complexToReal(resynthSpectrogram_P[0]); percussiveSpectrogramReal_Right = istft->complexToReal(resynthSpectrogram_P[1]); // arrays to hold output signals for harmonic and percussive files Array<float> outputSignal_P[2]; Array<float> outputSignal_H[2]; // fill with zeros (faster than looping through) outputSignal_P[0].insertMultiple(0, 0.0f, numSamples); outputSignal_P[1].insertMultiple(0, 0.0f, numSamples); outputSignal_H[0].insertMultiple(0, 0.0f, numSamples); outputSignal_H[1].insertMultiple(0, 0.0f, numSamples); // add-overlap ==================== int offset = 0; float temp_L[WINDOW_SIZE] = {}; float temp_R[WINDOW_SIZE] = {}; float ifftResults_Left[WINDOW_SIZE] = {}; float ifftResults_Right[WINDOW_SIZE] = {}; // loop through each column in spectrograms for (int col = 0; col < numCols; col++) { // insert 4096 samples into temp arrays from harmonic spectrogram for (int row = 0; row < WINDOW_SIZE; row++) { temp_L[row] = harmonicSpectrogramReal_Left(row, col); temp_R[row] = harmonicSpectrogramReal_Right(row, col); } // inverse short time fourier transform on temp_L and temp_R istft->performInverseTransform(temp_L, ifftResults_Left); istft->rescale(ifftResults_Left); istft->performInverseTransform(temp_R, ifftResults_Right); istft->rescale(ifftResults_Right); // set values in output signal arrays for Harmonic output signal for (int i = 0; i < WINDOW_SIZE; i++) { outputSignal_H[0].set(offset + i, (outputSignal_H[0][offset + i] + (ifftResults_Left[i] * istft->window[i]))); outputSignal_H[1].set(offset + i, (outputSignal_H[1][offset + i] + (ifftResults_Right[i] * istft->window[i]))); } // insert 4096 samples into temp arrays from percussive spectrogram for (int row = 0; row < WINDOW_SIZE; row++) { temp_L[row] = percussiveSpectrogramReal_Left(row, col); temp_R[row] = percussiveSpectrogramReal_Right(row, col); } // inverse short time fourier transform on temp arrays istft->performInverseTransform(temp_L, ifftResults_Left); istft->rescale(ifftResults_Left); istft->performInverseTransform(temp_R, ifftResults_Right); istft->rescale(ifftResults_Right); // set values in output arrays for Percussive output signal for (int i = 0; i < WINDOW_SIZE; i++) { outputSignal_P[0].set(offset + i, (outputSignal_P[0][offset + i] + (ifftResults_Left[i] * istft->window[i]))); outputSignal_P[1].set(offset + i, (outputSignal_P[1][offset + i] + (ifftResults_Right[i] * istft->window[i]))); } offset += HOP_SIZE; // increment offset by HOP_SIZE (1024) } //===================================================== WRITE FILES == float gain = 0.5f; // 1.0f divided by num of output files (2) AudioSampleBuffer outSamples_H(2, numSamples); AudioSampleBuffer outSamples_P(2, numSamples); outSamples_H.clear(); outSamples_P.clear(); const float* leftData_H = outputSignal_H[0].getRawDataPointer(); const float* rightData_H = outputSignal_H[1].getRawDataPointer(); const float* leftData_P = outputSignal_P[0].getRawDataPointer(); const float* rightData_P = outputSignal_P[1].getRawDataPointer(); outSamples_H.addFrom(0, 0, leftData_H, numSamples, gain); outSamples_H.addFrom(1, 0, rightData_H, numSamples, gain); outSamples_P.addFrom(0, 0, leftData_P, numSamples, gain); outSamples_P.addFrom(1, 0, rightData_P, numSamples, gain); File* outputFile_H = new File(File::getCurrentWorkingDirectory().getChildFile(fileNameNoExt + "_harmonic.wav")); File* outputFile_P = new File(File::getCurrentWorkingDirectory().getChildFile(fileNameNoExt + "_percussive.wav")); if (outputFile_H->exists()) { outputFile_H->deleteFile(); } if (outputFile_P->exists()) { outputFile_P->deleteFile(); } FileOutputStream* output_H; FileOutputStream* output_P; output_H = outputFile_H->createOutputStream(); output_P = outputFile_P->createOutputStream(); // write from sample buffer WavAudioFormat* wavFormat = new WavAudioFormat(); AudioFormatWriter* writer = wavFormat->createWriterFor(output_H, 44100.0, numChannels, 16, NULL, 0); writer->flush(); writer->writeFromAudioSampleBuffer(outSamples_H, 0, numSamples); delete writer; writer = wavFormat->createWriterFor(output_P, 44100.0, numChannels, 16, NULL, 0); writer->flush(); writer->writeFromAudioSampleBuffer(outSamples_P, 0, numSamples); // cleanup delete writer; delete wavFormat; wavFormat = nullptr; writer = nullptr; outSamples_H.clear(); outSamples_P.clear(); outputSignal_H[0].clear(); outputSignal_H[1].clear(); outputSignal_P[0].clear(); outputSignal_P[1].clear(); }