2013-12-08 22:44:43 +01:00
|
|
|
/*
|
|
|
|
* Author: Harry van Haaren 2013
|
|
|
|
* harryhaaren@gmail.com
|
2016-12-27 13:47:19 +01:00
|
|
|
*
|
2013-12-08 22:44:43 +01:00
|
|
|
* 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 3 of the License, or
|
|
|
|
* (at your option) any later version.
|
2016-12-27 13:47:19 +01:00
|
|
|
*
|
2013-12-08 22:44:43 +01:00
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
2016-12-27 13:47:19 +01:00
|
|
|
*
|
2013-12-08 22:44:43 +01:00
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
2013-08-15 18:17:16 +02:00
|
|
|
|
|
|
|
#include "trackoutput.hxx"
|
|
|
|
|
2013-09-17 14:11:11 +02:00
|
|
|
#include "jack.hxx"
|
|
|
|
extern Jack* jack;
|
2013-08-15 23:45:05 +02:00
|
|
|
|
2013-08-15 18:17:16 +02:00
|
|
|
TrackOutput::TrackOutput(int t, AudioProcessor* ap) :
|
2016-12-27 13:47:19 +01:00
|
|
|
AudioProcessor(),
|
|
|
|
track(t),
|
|
|
|
_recordArm(false),
|
|
|
|
previousInChain(ap)
|
2013-08-15 18:17:16 +02:00
|
|
|
{
|
2016-12-27 13:47:19 +01:00
|
|
|
// UI update
|
|
|
|
uiUpdateConstant = jack->getSamplerate() / 30;
|
|
|
|
uiUpdateCounter = jack->getSamplerate() / 30;
|
|
|
|
|
|
|
|
dbMeter = new DBMeter( jack->getSamplerate() );
|
|
|
|
|
|
|
|
_toMaster = 0.8;
|
|
|
|
_toMasterLag = 0.8;
|
2018-04-29 14:05:53 +02:00
|
|
|
|
2018-05-04 13:57:07 +02:00
|
|
|
_panL = 1.0f;
|
|
|
|
_panR = 1.0f;
|
|
|
|
_panLLag = 1.0f;
|
|
|
|
_panRLag = 1.0f;
|
|
|
|
|
2018-05-04 14:14:00 +02:00
|
|
|
_toSend = 0.0;
|
|
|
|
_toSendLag = 0.0;
|
|
|
|
|
2018-05-12 17:55:12 +02:00
|
|
|
// TODO this is unused and can be removed
|
2016-12-27 13:47:19 +01:00
|
|
|
_toSidechain = 0.0;
|
2018-05-12 17:55:12 +02:00
|
|
|
|
|
|
|
_toPostSidechain = 0.0;
|
|
|
|
_toPostSidechainLag = 0.0;
|
2016-12-27 13:47:19 +01:00
|
|
|
|
|
|
|
_toPostfaderActive = 0;
|
2018-07-09 11:30:47 +02:00
|
|
|
_toPostfaderActiveLag = 0;
|
2018-07-09 11:40:14 +02:00
|
|
|
|
2016-12-27 13:47:19 +01:00
|
|
|
_toKeyActive = 0;
|
2018-07-09 11:40:14 +02:00
|
|
|
_toKeyActiveLag = 0;
|
|
|
|
|
2016-12-27 13:47:19 +01:00
|
|
|
_toXSideActive = true;
|
2013-08-15 18:17:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void TrackOutput::setMaster(float value)
|
|
|
|
{
|
2016-12-27 13:47:19 +01:00
|
|
|
if(value < 0.01)
|
|
|
|
value = 0.f;
|
|
|
|
_toMaster = value;
|
2013-08-15 18:17:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
float TrackOutput::getMaster()
|
|
|
|
{
|
2016-12-27 13:47:19 +01:00
|
|
|
return _toMaster;
|
2013-08-15 18:17:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-09-23 13:51:41 +02:00
|
|
|
bool TrackOutput::recordArm()
|
|
|
|
{
|
2016-12-27 13:47:19 +01:00
|
|
|
return _recordArm;
|
2013-09-23 13:51:41 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void TrackOutput::recordArm(bool r)
|
|
|
|
{
|
2016-12-27 13:47:19 +01:00
|
|
|
_recordArm = r;
|
2013-09-23 13:51:41 +02:00
|
|
|
}
|
|
|
|
|
2013-09-23 16:23:48 +02:00
|
|
|
void TrackOutput::setSendActive( int send, bool a )
|
|
|
|
{
|
2016-12-27 13:47:19 +01:00
|
|
|
switch( send ) {
|
|
|
|
case SEND_POSTFADER:
|
|
|
|
_toPostfaderActive = a;
|
|
|
|
break;
|
|
|
|
case SEND_KEY:
|
|
|
|
_toKeyActive = a;
|
|
|
|
break;
|
|
|
|
//case SEND_XSIDE:
|
|
|
|
// _toXSideActive = a;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2013-09-23 16:23:48 +02:00
|
|
|
}
|
|
|
|
|
2017-01-09 15:11:16 +01:00
|
|
|
void TrackOutput::setPan( float pan )
|
|
|
|
{
|
2018-05-04 13:57:07 +02:00
|
|
|
/* Trial + Error leads to this algo - its cheap and cheerful */
|
|
|
|
if (pan <= 0)
|
|
|
|
{
|
|
|
|
// pan to left channel, lower right one
|
|
|
|
_panR = pan + 1.0f;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// pan to right channel, lower left one
|
|
|
|
_panL = (pan * -1) + 1.0f;
|
|
|
|
}
|
2017-01-09 15:11:16 +01:00
|
|
|
}
|
|
|
|
|
2013-08-15 18:17:16 +02:00
|
|
|
void TrackOutput::setSend( int send, float value )
|
|
|
|
{
|
2016-12-27 13:47:19 +01:00
|
|
|
switch( send ) {
|
|
|
|
case SEND_POSTFADER:
|
2018-05-04 14:14:00 +02:00
|
|
|
_toSend = value;
|
2016-12-27 13:47:19 +01:00
|
|
|
break;
|
|
|
|
case SEND_KEY:
|
|
|
|
// setSendActive() handles on/off for this send
|
|
|
|
//_toSidechain = value;
|
|
|
|
break;
|
|
|
|
case SEND_XSIDE:
|
|
|
|
_toPostSidechain = value;
|
|
|
|
break;
|
|
|
|
}
|
2013-08-15 18:17:16 +02:00
|
|
|
}
|
|
|
|
|
2013-08-16 00:51:09 +02:00
|
|
|
void TrackOutput::process(unsigned int nframes, Buffers* buffers)
|
2013-08-15 18:17:16 +02:00
|
|
|
{
|
2018-04-13 22:24:45 +02:00
|
|
|
// index = first-track + (track * channels)
|
|
|
|
int trackoffset = track * NCHANNELS;
|
2018-04-11 21:19:05 +02:00
|
|
|
|
2016-12-27 13:47:19 +01:00
|
|
|
//compute master volume lag;
|
2018-07-09 14:38:52 +02:00
|
|
|
_toMasterLag += jack->smoothing_value * (_toMaster - _toMasterLag);
|
2018-05-04 13:57:07 +02:00
|
|
|
|
2016-12-27 13:47:19 +01:00
|
|
|
// get & zero track buffer
|
2018-04-11 21:19:05 +02:00
|
|
|
float* trackBufferL = buffers->audio[Buffers::RETURN_TRACK_0_L + trackoffset];
|
|
|
|
float* trackBufferR = buffers->audio[Buffers::RETURN_TRACK_0_R + trackoffset];
|
2017-03-19 15:58:28 +01:00
|
|
|
memset( trackBufferL, 0, sizeof(float)*nframes );
|
|
|
|
memset( trackBufferR, 0, sizeof(float)*nframes );
|
2016-12-27 13:47:19 +01:00
|
|
|
|
|
|
|
// call process() up the chain
|
|
|
|
previousInChain->process( nframes, buffers );
|
|
|
|
|
|
|
|
// run the meter
|
2017-03-19 15:58:28 +01:00
|
|
|
dbMeter->process( nframes, trackBufferL, trackBufferR );
|
2016-12-27 13:47:19 +01:00
|
|
|
|
|
|
|
if (uiUpdateCounter > uiUpdateConstant ) {
|
|
|
|
float l = dbMeter->getLeftDB() * _toMasterLag;
|
|
|
|
float r = dbMeter->getRightDB() * _toMasterLag;
|
|
|
|
EventTrackSignalLevel e( track, l, r );
|
|
|
|
writeToGuiRingbuffer( &e );
|
|
|
|
uiUpdateCounter = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
uiUpdateCounter += nframes;
|
|
|
|
|
2018-05-04 14:14:00 +02:00
|
|
|
// copy audio data into send / sidechain / master buffers
|
|
|
|
float* sendL = buffers->audio[Buffers::SEND_L];
|
|
|
|
float* sendR = buffers->audio[Buffers::SEND_R];
|
2017-03-19 15:58:28 +01:00
|
|
|
float* sidechainL = buffers->audio[Buffers::SIDECHAIN_KEY_L];
|
|
|
|
float* sidechainR = buffers->audio[Buffers::SIDECHAIN_KEY_R];
|
|
|
|
float* postSidechainL = buffers->audio[Buffers::SIDECHAIN_SIGNAL_L];
|
|
|
|
float* postSidechainR = buffers->audio[Buffers::SIDECHAIN_SIGNAL_R];
|
2016-12-27 13:47:19 +01:00
|
|
|
|
|
|
|
float* masterL = buffers->audio[Buffers::MASTER_OUT_L];
|
|
|
|
float* masterR = buffers->audio[Buffers::MASTER_OUT_R];
|
|
|
|
|
|
|
|
|
2018-04-11 21:19:05 +02:00
|
|
|
float* jackoutputL = buffers->audio[Buffers::JACK_TRACK_0_L + trackoffset];
|
|
|
|
float* jackoutputR = buffers->audio[Buffers::JACK_TRACK_0_R + trackoffset];
|
2016-12-27 13:47:19 +01:00
|
|
|
|
|
|
|
for(unsigned int i = 0; i < nframes; i++) {
|
2018-04-29 14:05:53 +02:00
|
|
|
|
|
|
|
//compute master volume lag;
|
2018-07-09 14:38:52 +02:00
|
|
|
_toMasterLag += jack->smoothing_value * (_toMaster - _toMasterLag);
|
2018-04-29 14:05:53 +02:00
|
|
|
|
2018-05-04 14:14:00 +02:00
|
|
|
// compute pan lag:
|
2018-07-09 14:38:52 +02:00
|
|
|
_panLLag += jack->smoothing_value * (_panL - _panLLag);
|
|
|
|
_panRLag += jack->smoothing_value * (_panR - _panRLag);
|
2018-05-04 13:57:07 +02:00
|
|
|
|
2018-05-04 14:14:00 +02:00
|
|
|
// compute send volume lag:
|
2018-07-09 14:38:52 +02:00
|
|
|
_toSendLag += jack->smoothing_value * (_toSend - _toSendLag);
|
2018-05-04 14:14:00 +02:00
|
|
|
|
2018-05-12 17:55:12 +02:00
|
|
|
// compute sidechain signal lag
|
2018-07-09 14:38:52 +02:00
|
|
|
_toPostSidechainLag += jack->smoothing_value * (_toPostSidechain - _toPostSidechainLag);
|
2018-07-09 11:30:47 +02:00
|
|
|
|
|
|
|
// compute discrete lag values
|
2018-07-09 14:38:52 +02:00
|
|
|
_toPostfaderActiveLag += jack->smoothing_value * (float(_toPostfaderActive) - _toPostfaderActiveLag);
|
|
|
|
_toKeyActiveLag += jack->smoothing_value * (float(_toKeyActive) - _toKeyActiveLag);
|
2018-07-09 11:40:14 +02:00
|
|
|
|
2016-12-27 13:47:19 +01:00
|
|
|
// * master for "post-fader" sends
|
2017-03-19 15:58:28 +01:00
|
|
|
float tmpL = trackBufferL[i];
|
2018-05-12 17:55:12 +02:00
|
|
|
float tmpR = trackBufferR[i];
|
2016-12-27 13:47:19 +01:00
|
|
|
|
|
|
|
// post-sidechain *moves* signal between "before/after" ducking, not add!
|
2018-05-12 17:55:12 +02:00
|
|
|
masterL[i] += tmpL * _toMasterLag * (1-_toPostSidechainLag) * _panLLag;
|
|
|
|
masterR[i] += tmpR * _toMasterLag * (1-_toPostSidechainLag) * _panRLag;
|
2017-03-19 15:58:28 +01:00
|
|
|
if(jackoutputL)
|
2018-05-12 17:55:12 +02:00
|
|
|
jackoutputL[i] = tmpL * _toMasterLag * (1-_toPostSidechainLag);
|
2017-03-19 15:58:28 +01:00
|
|
|
if(jackoutputR)
|
2018-05-12 17:55:12 +02:00
|
|
|
jackoutputR[i] = tmpR * _toMasterLag * (1-_toPostSidechainLag);
|
2018-07-09 11:30:47 +02:00
|
|
|
|
|
|
|
sendL[i] += tmpL * _toSendLag * _toMasterLag * _toPostfaderActiveLag;
|
|
|
|
sendR[i] += tmpR * _toSendLag * _toMasterLag * _toPostfaderActiveLag;
|
|
|
|
|
2017-03-19 15:58:28 +01:00
|
|
|
if ( _toXSideActive ) {
|
2018-05-12 17:55:12 +02:00
|
|
|
postSidechainL[i] += tmpL * _toPostSidechainLag * _toMasterLag;
|
|
|
|
postSidechainR[i] += tmpR * _toPostSidechainLag * _toMasterLag;
|
2017-03-27 22:15:35 +02:00
|
|
|
}
|
2016-12-27 13:47:19 +01:00
|
|
|
|
|
|
|
// turning down an element in the mix should *NOT* influence sidechaining
|
2018-07-09 11:40:14 +02:00
|
|
|
sidechainL[i] += tmpL * _toKeyActiveLag;
|
|
|
|
sidechainR[i] += tmpR * _toKeyActiveLag;
|
2016-12-27 13:47:19 +01:00
|
|
|
}
|
2013-08-15 18:17:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
TrackOutput::~TrackOutput()
|
|
|
|
{
|
2016-12-27 13:47:19 +01:00
|
|
|
delete dbMeter;
|
2013-08-15 18:17:16 +02:00
|
|
|
}
|