diff --git a/src/audioprocessor.hxx b/src/audioprocessor.hxx index 56a8c85..b682bfa 100644 --- a/src/audioprocessor.hxx +++ b/src/audioprocessor.hxx @@ -8,23 +8,21 @@ class AudioProcessor AudioProcessor(){} /// copies the track output to master buffer, sidechain & post-side buffer - virtual void process(int nframes, Buffers* buffers) - { - - - } + virtual void process(int nframes, Buffers* buffers){} + + /// set main mix, 0-1 + virtual void setMaster(float value){} + + /// set sidechain mix, 0-1 + virtual void setSidechain(float value){} + + /// set post sidechain mix, 0-1 + virtual void setPostSidechain(float value){} + + /// set reverb mix, 0-1 + virtual void setReverb(float value){} virtual ~AudioProcessor(){}; - - private: - int track; - - float _toMaster; - - float _toReverb; - float _toSidechain; - float _toPostSidechain; - }; #endif // LUPPP_AUDIO_PROCESSOR_H diff --git a/src/dsp/dsp_reverb.hxx b/src/dsp/dsp_reverb.hxx new file mode 100644 index 0000000..c6edf8f --- /dev/null +++ b/src/dsp/dsp_reverb.hxx @@ -0,0 +1,441 @@ + + +#ifndef OPENAV_DSP_REVERB_H +#define OPENAV_DSP_REVERB_H + +#include +#include +#include + +template inline float faustpower(float x) { return powf(x,N); } +template inline double faustpower(double x) { return pow(x,N); } +template inline int faustpower(int x) { return faustpower(x) * faustpower(x); } +template <> inline int faustpower<0>(int x) { return 1; } +template <> inline int faustpower<1>(int x) { return x; } + +class Reverb // : Effect +{ + public: + Reverb(int sr) + { + init( sr ); + } + + int getNumInputs() { return 2; } + int getNumOutputs(){ return 2; } + + /// set HF damping, 0-1 + void damping(float d) + { + if( d > 1.0 ) d = 1.0f; + if( d < 0.0 ) d = 0.0f; + + fslider1 = d * 18500 + 1500.f; + } + + /// set size, 0-1 + void rt60(float rt) + { + if( rt > 1.0 ) rt = 1.0f; + if( rt < 0.0 ) rt = 0.0f; + + fslider0 = 1 + rt * 5; + } + + void process(int count, float** input, float** output) + { + float fSlow0 = fslider0; + float fSlow1 = expf((fConst2 / fSlow0)); + float fSlow2 = faustpower<2>(fSlow1); + float fSlow3 = (1.0f - fSlow2); + float fSlow4 = cosf((fConst3 * fslider1)); + float fSlow5 = (1.0f - (fSlow4 * fSlow2)); + float fSlow6 = sqrtf(max(0.f, ((faustpower<2>(fSlow5) / faustpower<2>(fSlow3)) - 1.0f))); + float fSlow7 = (fSlow5 / fSlow3); + float fSlow8 = (fSlow7 - fSlow6); + float fSlow9 = (fSlow0 - 0.5f); + float fSlow10 = ((expf((fConst2 / fSlow9)) / fSlow1) - 1); + float fSlow11 = (fSlow1 * ((1.0f + fSlow6) - fSlow7)); + float fSlow12 = expf((fConst12 / fSlow0)); + float fSlow13 = faustpower<2>(fSlow12); + float fSlow14 = (1.0f - fSlow13); + float fSlow15 = (1.0f - (fSlow4 * fSlow13)); + float fSlow16 = sqrtf(max(0.f, ((faustpower<2>(fSlow15) / faustpower<2>(fSlow14)) - 1.0f))); + float fSlow17 = (fSlow15 / fSlow14); + float fSlow18 = (fSlow17 - fSlow16); + float fSlow19 = ((expf((fConst12 / fSlow9)) / fSlow12) - 1); + float fSlow20 = (fSlow12 * ((1.0f + fSlow16) - fSlow17)); + float fSlow21 = expf((fConst17 / fSlow0)); + float fSlow22 = faustpower<2>(fSlow21); + float fSlow23 = (1.0f - fSlow22); + float fSlow24 = (1.0f - (fSlow4 * fSlow22)); + float fSlow25 = sqrtf(max(0.f, ((faustpower<2>(fSlow24) / faustpower<2>(fSlow23)) - 1.0f))); + float fSlow26 = (fSlow24 / fSlow23); + float fSlow27 = (fSlow26 - fSlow25); + float fSlow28 = ((expf((fConst17 / fSlow9)) / fSlow21) - 1); + float fSlow29 = (fSlow21 * ((1.0f + fSlow25) - fSlow26)); + float fSlow30 = expf((fConst22 / fSlow0)); + float fSlow31 = faustpower<2>(fSlow30); + float fSlow32 = (1.0f - fSlow31); + float fSlow33 = (1.0f - (fSlow4 * fSlow31)); + float fSlow34 = sqrtf(max(0.f, ((faustpower<2>(fSlow33) / faustpower<2>(fSlow32)) - 1.0f))); + float fSlow35 = (fSlow33 / fSlow32); + float fSlow36 = (fSlow35 - fSlow34); + float fSlow37 = ((expf((fConst22 / fSlow9)) / fSlow30) - 1); + float fSlow38 = (fSlow30 * ((1.0f + fSlow34) - fSlow35)); + float fSlow39 = expf((fConst27 / fSlow0)); + float fSlow40 = faustpower<2>(fSlow39); + float fSlow41 = (1.0f - fSlow40); + float fSlow42 = (1.0f - (fSlow4 * fSlow40)); + float fSlow43 = sqrtf(max(0.f, ((faustpower<2>(fSlow42) / faustpower<2>(fSlow41)) - 1.0f))); + float fSlow44 = (fSlow42 / fSlow41); + float fSlow45 = (fSlow44 - fSlow43); + float fSlow46 = ((expf((fConst27 / fSlow9)) / fSlow39) - 1); + float fSlow47 = (fSlow39 * ((1.0f + fSlow43) - fSlow44)); + float fSlow48 = expf((fConst32 / fSlow0)); + float fSlow49 = faustpower<2>(fSlow48); + float fSlow50 = (1.0f - fSlow49); + float fSlow51 = (1.0f - (fSlow4 * fSlow49)); + float fSlow52 = sqrtf(max(0.f, ((faustpower<2>(fSlow51) / faustpower<2>(fSlow50)) - 1.0f))); + float fSlow53 = (fSlow51 / fSlow50); + float fSlow54 = (fSlow53 - fSlow52); + float fSlow55 = ((expf((fConst32 / fSlow9)) / fSlow48) - 1); + float fSlow56 = (fSlow48 * ((1.0f + fSlow52) - fSlow53)); + float fSlow57 = expf((fConst37 / fSlow0)); + float fSlow58 = faustpower<2>(fSlow57); + float fSlow59 = (1.0f - fSlow58); + float fSlow60 = (1.0f - (fSlow4 * fSlow58)); + float fSlow61 = sqrtf(max(0.f, ((faustpower<2>(fSlow60) / faustpower<2>(fSlow59)) - 1.0f))); + float fSlow62 = (fSlow60 / fSlow59); + float fSlow63 = (fSlow62 - fSlow61); + float fSlow64 = ((expf((fConst37 / fSlow9)) / fSlow57) - 1); + float fSlow65 = (fSlow57 * ((1.0f + fSlow61) - fSlow62)); + float fSlow66 = expf((fConst42 / fSlow0)); + float fSlow67 = faustpower<2>(fSlow66); + float fSlow68 = (1.0f - fSlow67); + float fSlow69 = (1.0f - (fSlow67 * fSlow4)); + float fSlow70 = sqrtf(max(0.f, ((faustpower<2>(fSlow69) / faustpower<2>(fSlow68)) - 1.0f))); + float fSlow71 = (fSlow69 / fSlow68); + float fSlow72 = (fSlow71 - fSlow70); + float fSlow73 = ((expf((fConst42 / fSlow9)) / fSlow66) - 1); + float fSlow74 = (fSlow66 * ((1.0f + fSlow70) - fSlow71)); + float* input0 = input[0]; + float* input1 = input[1]; + float* output0 = output[0]; + float* output1 = output[1]; + for (int i=0; i= sizeof(EventTrackSignalLevel) ) { EventTrackSignalLevel ev; jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventTrackSignalLevel) ); - gui->getTrack(ev.track)->getVolume()->amplitude( ev.left, ev.right ); + if ( ev.track < 0 ) { + gui->getMasterTrack()->getVolume()->amplitude( ev.left, ev.right ); + } else { + gui->getTrack(ev.track)->getVolume()->amplitude( ev.left, ev.right ); } } break; } case Event::TRACK_VOLUME: { if ( availableRead >= sizeof(EventTrackVol) ) { EventTrackVol ev; jack_ringbuffer_read( rbToGui, (char*)&ev, sizeof(EventTrackVol) ); - gui->getTrack(ev.track)->getVolume()->value( ev.vol ); + if ( ev.track < 0 ) + { + gui->getMasterTrack()->getVolume()->value( ev.vol ); + } + else + gui->getTrack(ev.track)->getVolume()->value( ev.vol ); } break; } case Event::GUI_PRINT: { diff --git a/src/gmastertrack.hxx b/src/gmastertrack.hxx index d866db3..0083399 100644 --- a/src/gmastertrack.hxx +++ b/src/gmastertrack.hxx @@ -148,6 +148,11 @@ class GMasterTrack : public Fl_Group } + Avtk::Volume* getVolume() + { + return &volume; + } + ~GMasterTrack() { free(title); diff --git a/src/jack.cxx b/src/jack.cxx index c4bb746..7455a67 100644 --- a/src/jack.cxx +++ b/src/jack.cxx @@ -19,6 +19,8 @@ Jack::Jack() buffers.nframes = jack_get_buffer_size( client ); buffers.samplerate = jack_get_sample_rate( client ); + uiUpdateCounter = buffers.samplerate / 30; + uiUpdateConstant = buffers.samplerate / 30; masterOutput = jack_port_register( client, "master_out", @@ -60,8 +62,6 @@ Jack::Jack() { loopers.push_back( new Looper(i) ); timeManager.registerObserver( loopers.back() ); - - // allocate working buffers for each track buffers.audio[Buffers::TRACK_0 + i] = (float*) malloc( sizeof(float) * nframes ); } @@ -72,6 +72,11 @@ Jack::Jack() timeManager.registerObserver( &metronome ); + /// setup FX + reverb = new Reverb( buffers.samplerate ); + reverbMeter = new DBMeter( buffers.samplerate ); + + /// setup JACK callbacks if ( jack_set_process_callback( client, static_process, static_cast(this)) ) @@ -107,6 +112,9 @@ int Jack::process (jack_nframes_t nframes) // pre-zero output buffers memset( buffers.audio[Buffers::MASTER_OUTPUT], 0, sizeof(float) * nframes ); + memset( buffers.audio[Buffers::REVERB] , 0, sizeof(float) * nframes ); + memset( buffers.audio[Buffers::SIDECHAIN] , 0, sizeof(float) * nframes ); + memset( buffers.audio[Buffers::POST_SIDECHAIN],0, sizeof(float) * nframes ); for(int i = 0; i < NTRACKS; i++) memset( buffers.audio[Buffers::TRACK_0 + i], 0, sizeof(float) * nframes ); @@ -140,10 +148,20 @@ int Jack::process (jack_nframes_t nframes) masterMidiInputIndex++; } - /// process each track, starting at output and working up signal path + // process each track, starting at output and working up signal path for(uint i = 0; i < loopers.size(); i++) trackOutputs.at(i)->process( nframes, &buffers ); + // process fx + float* buf[] = { + buffers.audio[Buffers::REVERB], + buffers.audio[Buffers::REVERB], + buffers.audio[Buffers::REVERB], + buffers.audio[Buffers::REVERB], + }; + + reverbMeter->process(nframes, buffers.audio[Buffers::REVERB], buffers.audio[Buffers::REVERB] ); + reverb->process( nframes, &buf[0], &buf[2] ); // mixdown tracks into master output buffer float* output = buffers.audio[Buffers::MASTER_OUTPUT]; @@ -161,6 +179,15 @@ int Jack::process (jack_nframes_t nframes) metronome.process( nframes, &buffers ); + if ( uiUpdateCounter > uiUpdateConstant ) + { + EventTrackSignalLevel e(-1, reverbMeter->getLeftDB(),reverbMeter->getRightDB() ); + writeToGuiRingbuffer( &e ); + + uiUpdateCounter = 0; + } + + uiUpdateCounter += nframes; return false; } diff --git a/src/jack.hxx b/src/jack.hxx index e861068..2b3e7fe 100644 --- a/src/jack.hxx +++ b/src/jack.hxx @@ -23,6 +23,9 @@ #include "metronome.hxx" #include "timemanager.hxx" +#include "dsp/dsp_reverb.hxx" +#include "dsp/dsp_dbmeter.hxx" + #include "controllerupdater.hxx" using namespace std; @@ -70,6 +73,10 @@ class Jack int nframes; int samplerate; + // FX + Reverb* reverb; + DBMeter* reverbMeter; + // JACK member variables jack_client_t* client; @@ -97,6 +104,9 @@ class Jack int, void* ); + // UI update variables + int uiUpdateCounter; + int uiUpdateConstant; }; #endif // LUPPP_JACK_H diff --git a/src/looper.hxx b/src/looper.hxx index 30c04c0..0a42bcf 100644 --- a/src/looper.hxx +++ b/src/looper.hxx @@ -9,7 +9,7 @@ #include "audioprocessor.hxx" #include "observer/observer.hxx" -#define SAMPLE_SIZE 44100*60 +#define SAMPLE_SIZE 44100*20 class AudioBuffer; diff --git a/src/trackoutput.hxx b/src/trackoutput.hxx index bdc8234..b662fae 100644 --- a/src/trackoutput.hxx +++ b/src/trackoutput.hxx @@ -18,6 +18,8 @@ class TrackOutput : public AudioProcessor // UI update uiUpdateConstant = 44100 / 20; uiUpdateCounter = 44100 / 30; + + _toReverb = 1.0; } /// set main mix, 0-1