Mercurial > hg > easaier-soundaccess
view sv/filter/MultiRealTimeFilter.cpp @ 282:d9319859a4cf tip
(none)
author | benoitrigolleau |
---|---|
date | Fri, 31 Oct 2008 11:00:24 +0000 |
parents | 65dfc1027ed6 |
children |
line wrap: on
line source
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ /* Sound Access EASAIER client application. Silogic 2007. Laure Bajard. Integration of the filter provided by: Dublin Institute of Technology - Audio Research Group 2007 www.audioresearchgroup.com Author: Dan Barry This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. See the file COPYING included with this distribution for more information. */ #include <math.h> #include <iostream> #include "MultiRealTimeFilter.h" #include "FFTReal.h" #include "DSP.h" #include "system/System.h" #include "main/MainWindow.h" // DAN added float *L_mags; ///CURRENT FRAME MAGNITUDES float *R_mags; ///CURRENT FRAME MAGNITUDES float *pL_mags; ///PREVIOUS FRAME MAGNITUDES float *pR_mags; ///PREVIOUS FRAME MAGNITUDES float *plotarray; ///STORES HISTOGRAM PLOT FOR SEPARATOR float *grapharray; ///HIGHER RESOLUTION VERSION OF ABOVE FOR SCREEN PLOTTING float *L_FFTframe; //Left FFT Frame float *R_FFTframe; //Right FFT Frame extern float hopfactor; //need in DSP.cpp float lastfactor; int numpeaks; float *peak_locations; int currentposition; // MultiRealTimeFilter::MultiRealTimeFilter() : Filter(), m_framesize(4096), m_transhold(0) { m_hop = m_framesize/4; currentposition = m_hop; m_mutex = new QMutex; m_timeStretchFilter = new TimeStretchFilter(); m_equalizerFilter = new EqualizerFilter(m_framesize, m_mutex); m_filterCollection.push_back(m_timeStretchFilter); m_filterCollection.push_back(m_equalizerFilter); connect(m_timeStretchFilter, SIGNAL(filterEnabled(bool)), this, SLOT(setFilterEnabled(bool))); connect(m_equalizerFilter, SIGNAL(filterEnabled(bool)), this, SLOT(setFilterEnabled(bool))); m_inputBufferL = (float *)calloc(m_framesize*(m_timeStretchFilter->getMaxPitchFactor()+1), sizeof(float)); m_inputBufferR = (float *)calloc(m_framesize*(m_timeStretchFilter->getMaxPitchFactor()+1), sizeof(float)); /**********malloc***********/ //This block specifically sets up the buffers required to do a 75% overlap scheme window=(float *)calloc((m_framesize), sizeof(float)); //Window L_FFTframe=(float *)calloc((m_framesize), sizeof(float)); R_FFTframe=(float *)calloc((m_framesize), sizeof(float)); L_audioframe=(float *)calloc((m_framesize), sizeof(float)); //The current frame R_audioframe=(float *)calloc((m_framesize), sizeof(float)); pL_audioframe=(float *)calloc((m_framesize), sizeof(float)); // pR_audioframe=(float *)calloc((m_framesize), sizeof(float)); L_processedframe=(float *)calloc((m_framesize), sizeof(float)); //The current frame R_processedframe=(float *)calloc((m_framesize), sizeof(float)); L_outbuffer=(float *)calloc((m_framesize/4), sizeof(float)); //The current output segment which is 1/4 framesize for 75% overlap L_holdbuffer3=(float *)calloc((m_framesize*0.75), sizeof(float)); //The hold buffer for the previous frame segment L_holdbuffer2=(float *)calloc((m_framesize/2), sizeof(float)); //The fold buffer for the frame segment 2 frames ago L_holdbuffer1=(float *)calloc((m_framesize/4), sizeof(float)); //The fold buffer for the frame segment 3 frames ago R_outbuffer=(float *)calloc((m_framesize/4), sizeof(float)); //The current output segment which is 1/4 framesize for 75% overlap R_holdbuffer3=(float *)calloc((m_framesize*0.75), sizeof(float)); //The hold buffer for the previous frame segment R_holdbuffer2=(float *)calloc((m_framesize/2), sizeof(float)); //The fold buffer for the frame segment 2 frames ago R_holdbuffer1=(float *)calloc((m_framesize/4), sizeof(float)); L_mags=(float *)calloc((m_framesize/2), sizeof(float)); //The magnitude and phase arrays R_mags=(float *)calloc((m_framesize/2), sizeof(float)); L_phase=(float *)calloc((m_framesize/2), sizeof(float)); R_phase=(float *)calloc((m_framesize/2), sizeof(float)); pL_mags=(float *)calloc((m_framesize/2), sizeof(float)); //The magnitude and phase arrays pR_mags=(float *)calloc((m_framesize/2), sizeof(float)); pL_phase=(float *)calloc((m_framesize/2), sizeof(float)); //The magnitude and phase arrays pR_phase=(float *)calloc((m_framesize/2), sizeof(float)); cL_synthphase=(float *)calloc((m_framesize/2), sizeof(float)); cR_synthphase=(float *)calloc((m_framesize/2), sizeof(float)); pL_synthphase=(float *)calloc((m_framesize/2), sizeof(float)); pR_synthphase=(float *)calloc((m_framesize/2), sizeof(float)); peak_locations=(float *)calloc((m_framesize/2), sizeof(float)); plotarray=(float *)calloc((200), sizeof(float)); grapharray=(float *)calloc((400), sizeof(float)); hanning(window, m_framesize); connect(this, SIGNAL(playSpeedChanged(float)), MainWindow::instance(), SLOT(playSpeedChanged(float))); hopfactor = 1; /***************************/ } MultiRealTimeFilter::~MultiRealTimeFilter() { /**********de-alloc***********/ delete m_inputBufferL; delete m_inputBufferR; delete L_mags; ///CURRENT FRAME MAGNITUDES delete R_mags; ///CURRENT FRAME MAGNITUDES delete pL_mags; ///PREVIOUS FRAME MAGNITUDES delete pR_mags; ///PREVIOUS FRAME MAGNITUDES delete L_FFTframe; //Left FFT Frame delete R_FFTframe; //delete FFTframe; delete L_audioframe; // delete R_audioframe; // delete pL_audioframe; // delete pR_audioframe; // delete L_processedframe; // delete R_processedframe; delete window; delete L_outbuffer; delete L_holdbuffer3; delete L_holdbuffer2; delete L_holdbuffer1; delete R_outbuffer; delete R_holdbuffer3; delete R_holdbuffer2; delete R_holdbuffer1; delete L_phase; delete R_phase; delete pL_phase; delete pR_phase; delete cL_synthphase; delete cR_synthphase; delete pL_synthphase; delete pR_synthphase; delete peak_locations; hopfactor = 1; emit playSpeedChanged(1); delete m_mutex; m_mutex = 0; /***************************/ } void MultiRealTimeFilter::putInput(float **input, size_t samples) { int dd; float sampdiff; float difratio; float interpsample; bool drum = 0; float drumthresh = 65; int delta = m_hop; //the "current position" is shifted of m_hop if ( samples < ( (size_t) floor(m_framesize*(m_timeStretchFilter->getPitchFactor() + 1)) ) ) return; int channel = getSourceChannelCount(); for (int i=0; i< ((int) samples); i++){ if (channel > 1) { m_inputBufferL[i] = input[0][i]; //real-time biffer taken from left ring buffer m_inputBufferR[i] = input[1][i]; //real-time biffer taken from right ring buffer } else { m_inputBufferL[i] = input[0][i]; //If file is mono we copy same channel into both buffers into both buffers m_inputBufferR[i] = input[0][i]; } } for (int i = 0; i< ((int) m_framesize); i++) { //This block was specifically written to do resampling interpolation for crude pitch shifting //if it's not being used the audioframe line after the else should be used which is also used in bypass mode //At if (m_timeStretchFilter->bypass() == false) { dd = floor(double(i*m_timeStretchFilter->getPitchFactor())); difratio = (double(i*m_timeStretchFilter->getPitchFactor())) - floor(double(i*m_timeStretchFilter->getPitchFactor())); // this block loads a frame as normal sampdiff=m_inputBufferL[dd+delta+1]-m_inputBufferL[dd+delta]; interpsample = (difratio*sampdiff)+m_inputBufferL[dd+delta]; L_audioframe[i] = interpsample*window[i]; sampdiff=m_inputBufferL[dd+delta+1-m_hop]-m_inputBufferL[dd+delta-m_hop]; interpsample = (difratio*sampdiff)+m_inputBufferL[dd+delta-m_hop]; pL_audioframe[i] = interpsample*window[i]; sampdiff=m_inputBufferR[dd+delta+1]-m_inputBufferR[dd+delta]; interpsample = (difratio*sampdiff)+m_inputBufferR[dd+delta]; R_audioframe[i] = interpsample*window[i]; sampdiff=m_inputBufferR[dd+delta+1-m_hop]-m_inputBufferR[dd+delta-m_hop]; interpsample = (difratio*sampdiff)+m_inputBufferR[dd+delta-m_hop]; pR_audioframe[i] = interpsample*window[i]; } else { L_audioframe[i] = m_inputBufferL[i+delta+1]*window[i]; R_audioframe[i] = m_inputBufferR[i+delta+1]*window[i]; L_processedframe[i] = L_audioframe[i]*window[i]; R_processedframe[i] = R_audioframe[i]*window[i]; } } FFTReal fft_object(m_framesize); //if (m_timeStretchFilter->bypass() == false)//DAN This bypass would stop all processing...need to replace this with a master bypass instead of just timestretch bypass if (filterEnabled) { //CURRENT FRAME LEFT AND RIGHT TIME 2 FREQUENCY ***** THIS IS REQUIRED BY ALL PROCESSES fft_object.do_fft(L_FFTframe,L_audioframe); fft_object.do_fft(R_FFTframe,R_audioframe); cart2pol(L_FFTframe, L_mags, L_phase, m_framesize); cart2pol(R_FFTframe, R_mags, R_phase, m_framesize); //CURRENT FRAME LEFT AND RIGHT TIME 2 FREQUENCY ***** THIS IS REQUIRED BY ALL PROCESSES fft_object.do_fft (L_FFTframe,pL_audioframe); fft_object.do_fft (R_FFTframe,pR_audioframe); cart2pol(L_FFTframe, pL_mags, pL_phase, m_framesize); cart2pol(R_FFTframe, pR_mags, pR_phase, m_framesize); //-------------------------------------------- //EQUALISER CALLS - //Will need a bypass " m_equalizerFilter->bypass()" as below //Will need a simplemode " m_equalizerFilter->simplemode_bypass() " to switch between draw and slider control if (m_equalizerFilter->bypass() == false) { m_mutex->lock(); if (m_equalizerFilter->simpleMode()) { //m_equalizerFilter->create_filterbands(); bandeq(L_mags, R_mags, m_equalizerFilter->curve(), m_framesize); //Gainband 1 - 5 values from EQ sliders //log10plot2(bandcurve,plotbandcurve, m_framesize, 400); //Converts linear band curve to log band curve only for plot } else { applyEQ(L_mags, R_mags, m_framesize, m_equalizerFilter->curve().size(), m_equalizerFilter->curve()); //Takes "eqcurve" which is what user draws in advanced mode } m_equalizerFilter->emitPlotFFTArray(L_mags, m_framesize); m_mutex->unlock(); } if (m_timeStretchFilter->bypass() == false) { //TRANSIENT DETECTION FOR TIME STRETCHER drum=transient_detect(L_mags, R_mags, pL_mags, pR_mags, drumthresh, m_framesize); if (m_timeStretchFilter->transcheck()) { if (drum && m_transhold==0){ // FOR TIME STRETCHER cur2last(L_phase, cL_synthphase, pL_synthphase, m_framesize); cur2last(R_phase, cR_synthphase, pR_synthphase, m_framesize); m_transhold=4; } else{ if(m_timeStretchFilter->peakcheck()){ // FOR TIME STRETCHER rotatephases_peaklocked(L_phase, pL_phase, cL_synthphase, pL_synthphase, L_mags, m_framesize, m_timeStretchFilter->getPitchFactor()); rotatephases_peaklocked(R_phase, pR_phase, cR_synthphase, pR_synthphase, R_mags, m_framesize, m_timeStretchFilter->getPitchFactor()); } else{ // FOR TIME STRETCHER rotatephases(L_phase, pL_phase, cL_synthphase, pL_synthphase, m_framesize, m_timeStretchFilter->getPitchFactor()); rotatephases(R_phase, pR_phase, cR_synthphase, pR_synthphase, m_framesize, m_timeStretchFilter->getPitchFactor()); } } } else { if(m_timeStretchFilter->peakcheck()){ // FOR TIME STRETCHER rotatephases_peaklocked(L_phase, pL_phase, cL_synthphase, pL_synthphase, L_mags, m_framesize, m_timeStretchFilter->getPitchFactor()); rotatephases_peaklocked(R_phase, pR_phase, cR_synthphase, pR_synthphase, R_mags, m_framesize, m_timeStretchFilter->getPitchFactor()); } else{ // FOR TIME STRETCHER rotatephases(L_phase, pL_phase, cL_synthphase, pL_synthphase, m_framesize, m_timeStretchFilter->getPitchFactor()); rotatephases(R_phase, pR_phase, cR_synthphase, pR_synthphase, m_framesize, m_timeStretchFilter->getPitchFactor()); } } // FOR TIME STRETCHER if(m_transhold != 0){ m_transhold = m_transhold - 1; } drum = 0; pol2cart(L_FFTframe, L_mags, cL_synthphase, m_framesize); pol2cart(R_FFTframe, R_mags, cR_synthphase, m_framesize); } else { pol2cart(L_FFTframe, L_mags, L_phase, m_framesize); pol2cart(R_FFTframe, R_mags, R_phase, m_framesize); } fft_object.do_ifft (L_FFTframe,L_processedframe); fft_object.do_ifft (R_FFTframe,R_processedframe); fft_object.rescale (L_processedframe); fft_object.rescale (R_processedframe); } for (int p = 0; p < ((int) m_framesize); p++){ L_processedframe[p]=L_processedframe[p]*window[p]; R_processedframe[p]=R_processedframe[p]*window[p]; } for (int j = 0; j< ((int) m_framesize); j++) { //This block deals with the buffers for a 75% overlap scheme AND IS NOW STEREO if (j < ((int) m_framesize)/4){ L_outbuffer[j]=(L_processedframe[j]+L_holdbuffer1[j]+L_holdbuffer2[j]+L_holdbuffer3[j])*0.5; L_holdbuffer1[j]=L_holdbuffer2[j+(m_framesize/4)]; R_outbuffer[j]=(R_processedframe[j]+R_holdbuffer1[j]+R_holdbuffer2[j]+R_holdbuffer3[j])*0.5; R_holdbuffer1[j]=R_holdbuffer2[j+(m_framesize/4)]; } if (j < ((int) m_framesize)/2){ L_holdbuffer2[j]=L_holdbuffer3[j+(m_framesize/4)]; R_holdbuffer2[j]=R_holdbuffer3[j+(m_framesize/4)]; } if (j < ((int) m_framesize)*0.75){ L_holdbuffer3[j]=L_processedframe[j+(m_framesize/4)]; R_holdbuffer3[j]=R_processedframe[j+(m_framesize/4)]; } } } void MultiRealTimeFilter::getOutput(float **output, size_t samples) { if (samples > m_framesize/4) return; int channel = getSourceChannelCount(); for (size_t i = 0; i < samples; ++i) // Now that there are 2 out buffers, the output is filled according to channel count { output[0][i] = L_outbuffer[i]; if (channel > 1) { output[1][i] = R_outbuffer[i]; } } } size_t MultiRealTimeFilter::getRequiredInputSamples(size_t outputSamplesNeeded) { size_t need = (size_t) (floor(m_framesize*(m_timeStretchFilter->getPitchFactor() + 1))); return need; } size_t MultiRealTimeFilter::getRequiredSkipSamples() { size_t skip = 1024; if (m_timeStretchFilter->bypass() == false && m_transhold==0) { skip = floor(m_hop*hopfactor); currentposition += floor(m_hop*hopfactor); } else { skip = m_hop; currentposition += m_hop; } if (m_timeStretchFilter->bypass() == false && m_timeStretchFilter->isFreezed() == true) { skip = 0; currentposition += 0; } return skip; } void MultiRealTimeFilter::setFilterEnabled(bool b) { filterEnabled = (m_timeStretchFilter->isEnabled() || m_equalizerFilter->isEnabled()); } void MultiRealTimeFilter::setFilterEnabled(int b) { filterEnabled = (m_timeStretchFilter->isEnabled() || m_equalizerFilter->isEnabled()); }