diff --git a/src/fx_tube.cpp b/src/fx_tube.cpp index 0b91bb7..b79bdd4 100644 --- a/src/fx_tube.cpp +++ b/src/fx_tube.cpp @@ -22,29 +22,35 @@ void Tube::reset() void Tube::processSample(float32_t inL, float32_t inR, float32_t& outL, float32_t& outR) { - float32_t x = inL * this->saturator_factor_; - float32_t abs_x = abs(x); - float32_t sat_x = log(1.0f + abs_x) * this->gain_factor_; - - outL = inL > 0 ? sat_x : -sat_x; - - x = inR * this->saturator_factor_; - abs_x = abs(x); - sat_x = log(1.0f + abs_x) * this->gain_factor_; + if(inL == 0.0f) + { + outL = 0.0f; + } + else + { + outL = std::tanh(this->saturator_factor_ * inL) * this->gain_factor_; + } - outR = inR > 0 ? sat_x : -sat_x; + if(inR == 0.0f) + { + outR = 0.0f; + } + else + { + outR = std::tanh(this->saturator_factor_ * inR) * this->gain_factor_; + } } void Tube::setOverdrive(float32_t overdrive) { - static const float32_t N = 200.0f; + static const float32_t N = 3.0f; overdrive = constrain(overdrive, 0.0f, 1.0f); if(this->overdrive_ != overdrive) { this->overdrive_ = overdrive; - this->saturator_factor_ = 1.0f + N * overdrive; - this->gain_factor_ = this->OutputLevelCorrector / log(1.0f + this->saturator_factor_); + this->saturator_factor_ = 1.0 + N * overdrive; + this->gain_factor_ = this->OutputLevelCorrector / std::tanh(this->saturator_factor_); } } diff --git a/src/fx_tube.h b/src/fx_tube.h index e749c23..8512d62 100644 --- a/src/fx_tube.h +++ b/src/fx_tube.h @@ -78,4 +78,4 @@ private: return nb_errors; ) -}; \ No newline at end of file +}; diff --git a/src/minidexed.cpp b/src/minidexed.cpp index 1a13925..4c0e922 100644 --- a/src/minidexed.cpp +++ b/src/minidexed.cpp @@ -149,7 +149,7 @@ CMiniDexed::CMiniDexed ( this->setMasterVolume(1.0); #if defined(MIXING_CONSOLE_ENABLE) - this->mixing_console_ = new Mixer(static_cast(pConfig->GetSampleRate()), CConfig::MaxChunkSize); + this->mixing_console_ = new Mixer(static_cast(pConfig->GetSampleRate()), CConfig::MaxChunkSize, this->m_bChannelsSwapped); for (uint8_t i = 0; i < CConfig::ToneGenerators; i++) { memset(this->m_OutputLevel[i], 0, CConfig::MaxChunkSize * sizeof(float32_t)); @@ -327,7 +327,7 @@ bool CMiniDexed::Initialize (void) m_pSoundDevice->Start (); -#ifdef ARM_ALLOW_MULTI_CORE +#if defined(ARM_ALLOW_MULTI_CORE) // start secondary cores if (!CMultiCoreSupport::Initialize ()) { @@ -1786,45 +1786,30 @@ void CMiniDexed::ProcessSound (void) // // Audio signal path after tone generators starts here - // - float32_t tmp_float[nFrames * 2]; int16_t tmp_int[nFrames * 2]; #if defined(MIXING_CONSOLE_ENABLE) - // // swap stereo channels if needed - uint8_t indexL = StereoChannels::Left; - uint8_t indexR = StereoChannels::Right; - if(this->m_bChannelsSwapped) - { - indexL = StereoChannels::Right; - indexR = StereoChannels::Left; - } - - // BEGIN TG mixing + // BEGIN mixing if(this->nMasterVolume > 0.0f) { - float32_t SampleBuffer[StereoChannels::kNumChannels][nFrames]; + // temp buffering and channel indexing + float32_t interlacedSampleBuffer[nFrames << 1]; + this->m_FXSpinLock.Acquire(); - this->mixing_console_->process(SampleBuffer[indexL], SampleBuffer[indexR]); + this->mixing_console_->process(interlacedSampleBuffer); this->m_FXSpinLock.Release(); - // Convert dual float array (left, right) to single int16 array (left/right) - this->nMasterVolume = constrain(this->nMasterVolume, 0.0f, 1.0f); - if(this->nMasterVolume == 1.0f) - { - memcpy(tmp_float, SampleBuffer[indexL], nFrames * sizeof(float32_t)); - memcpy(tmp_float + nFrames, SampleBuffer[indexR], nFrames * sizeof(float32_t)); - } - else // 0.0 < this->nMasterVolume < 1.0 + if(this->nMasterVolume < 1.0f) { - arm_scale_f32(SampleBuffer[indexL], this->nMasterVolume, tmp_float, nFrames); - arm_scale_f32(SampleBuffer[indexR], this->nMasterVolume, tmp_float + nFrames, nFrames); + arm_scale_f32(interlacedSampleBuffer, this->nMasterVolume, interlacedSampleBuffer, nFrames << 1); } - arm_float_to_q15(tmp_float, tmp_int, nFrames * 2); + + // Convert float array (left, right) to single int16 array (left/right) + arm_float_to_q15(interlacedSampleBuffer, tmp_int, nFrames << 1); } else // this->nMasterVolume == 0.0f { - arm_fill_q15(0, tmp_int, nFrames * 2); + arm_fill_q15(0, tmp_int, nFrames << 1); } #elif defined(PLATE_REVERB_ENABLE) @@ -2332,12 +2317,7 @@ void CMiniDexed::getSysExVoiceDump(uint8_t* dest, uint8_t nTG) void CMiniDexed::setMasterVolume (float32_t vol) { - if(vol < 0.0) - vol = 0.0; - else if(vol > 1.0) - vol = 1.0; - - nMasterVolume=vol; + this->nMasterVolume = constrain(vol, 0.0f, 1.0f); } std::string CMiniDexed::GetPerformanceFileName(unsigned nID) diff --git a/src/mixing_console.hpp b/src/mixing_console.hpp index 96b3c25..e93d3c2 100644 --- a/src/mixing_console.hpp +++ b/src/mixing_console.hpp @@ -40,7 +40,7 @@ class MixingConsole : public FXBase DISALLOW_COPY_AND_ASSIGN(MixingConsole); public: - MixingConsole(float32_t sampling_rate, size_t buffer_size); + MixingConsole(float32_t sampling_rate, size_t buffer_size, bool swapStereoImage = false); ~MixingConsole(); inline size_t getChannelNumber() const; @@ -48,6 +48,7 @@ public: // Send section inline void setChannelLevel(size_t in, float32_t lvl); inline void setPan(size_t in, float32_t pan); + inline void swapStereoImage(bool swap); inline void setSendLevel(size_t in, MixerOutput fx, float32_t lvl); inline void setInputSample(size_t in, float32_t sampleL, float32_t sampleR); inline void setInputSampleBuffer(size_t in, float32_t* samples); @@ -75,6 +76,7 @@ public: inline void injectInputSamples(size_t in, float32_t* samplesL, float32_t* samplesR, size_t nSamples); inline void processSample(float32_t& outL, float32_t& outR); void process(float32_t* outL, float32_t* outR); + void process(float32_t* outLR); protected: inline void updatePan(size_t in); @@ -88,6 +90,7 @@ private: float32_t channel_level_[nb_inputs]; float32_t pan_[StereoChannels::kNumChannels + 1][nb_inputs]; + bool swap_stereo_image_; float32_t* tg_input_sample_buffer_[nb_inputs]; float32_t* input_sample_buffer_[StereoChannels::kNumChannels][nb_inputs]; float32_t input_samples_[StereoChannels::kNumChannels][nb_inputs + MixerOutput::kFXCount - 1]; @@ -106,7 +109,7 @@ private: FXUnit2* dry_; IMPLEMENT_DUMP( - const size_t space = 10; + const size_t space = 9; const size_t precision = 5; std::stringstream ss; @@ -328,9 +331,10 @@ float32_t MixingConsole::weighted_sum(const float32_t* data, const fl } template -MixingConsole::MixingConsole(float32_t sampling_rate, size_t buffer_size) : +MixingConsole::MixingConsole(float32_t sampling_rate, size_t buffer_size, bool swapStereoImage) : FXBase(sampling_rate), BufferSize(buffer_size), + swap_stereo_image_(swapStereoImage), m_nSamples(0) { for(size_t i = 0; i < nb_inputs; ++i) @@ -406,6 +410,12 @@ void MixingConsole::setPan(size_t in, float32_t pan) this->updatePan(in); } +template +void MixingConsole::swapStereoImage(bool swap) +{ + this->swap_stereo_image_ = swap; +} + template void MixingConsole::setSendLevel(size_t in, MixerOutput fx, float32_t lvl) { @@ -669,7 +679,14 @@ void MixingConsole::process(float32_t* outL, float32_t* outR) ); } - this->processSample(*outL, *outR); + if(this->swap_stereo_image_) + { + this->processSample(*outR, *outL); + } + else + { + this->processSample(*outL, *outR); + } ++outL; ++outR; } @@ -677,6 +694,37 @@ void MixingConsole::process(float32_t* outL, float32_t* outR) this->m_nSamples = 0; } +template +void MixingConsole::process(float32_t* outLR) +{ + size_t nSamples = this->m_nSamples; + for(size_t s = 0; s < nSamples; ++s) + { + for(size_t in = 0; in < nb_inputs; ++in) + { + this->setSample( + in, + this->input_sample_buffer_[StereoChannels::Left ][in][s], + this->input_sample_buffer_[StereoChannels::Right][in][s] + ); + } + + if(this->swap_stereo_image_) + { + this->processSample(*(outLR + 1), *outLR); + } + else + { + this->processSample(*outLR, *(outLR + 1)); + + } + + outLR += 2; + } + + this->m_nSamples = 0; +} + template void MixingConsole::updatePan(size_t in) { diff --git a/src/test/test_fx_mixing_console.cpp b/src/test/test_fx_mixing_console.cpp index a82b3ee..41cb772 100644 --- a/src/test/test_fx_mixing_console.cpp +++ b/src/test/test_fx_mixing_console.cpp @@ -31,7 +31,7 @@ void setupMixingConsoleFX(Mixer* mixer) mixer->setPan(0, 0.5f); mixer->getTube()->setMute(false); - mixer->getTube()->setOverdrive(0.45f); + mixer->getTube()->setOverdrive(0.85f); mixer->getChorus()->setMute(false); mixer->getChorus()->setRate(0.4f); @@ -53,8 +53,8 @@ void setupMixingConsoleFX(Mixer* mixer) mixer->getPhaser()->setNbStages(12); mixer->getDelay()->setMute(false); - mixer->getDelay()->setLeftDelayTime(0.25f); - mixer->getDelay()->setLeftDelayTime(0.30f); + mixer->getDelay()->setLeftDelayTime(0.15f); + mixer->getDelay()->setLeftDelayTime(0.20f); mixer->getDelay()->setFeedback(0.7f); mixer->getDelay()->setFlutterRate(0.2f); mixer->getDelay()->setFlutterAmount(0.5f); @@ -118,8 +118,8 @@ void setupMixingConsoleFX(Mixer* mixer, int scenarioId, size_t channel) } else { - mixer->setSendLevel(channel, MixerOutput::MainOutput, 0.3f); - mixer->setReturnLevel(previousActivatedFX, MixerOutput::MainOutput, 0.8f); + mixer->setSendLevel(channel, MixerOutput::MainOutput, 0.25f); + mixer->setReturnLevel(previousActivatedFX, MixerOutput::MainOutput, 0.75f); } } @@ -520,13 +520,6 @@ TEST_P(FXScenarioTest, FXProcessingScenario) int scenarioId = this->GetParam(); setupMixingConsoleFX((&mixer), scenarioId); - for(size_t i = 0; i < NB_MIXER_CHANNELS; ++i) - { - mixer.setSendLevel(i, static_cast(i), 1.0f); - mixer.setReturnLevel(static_cast(i), MixerOutput::MainOutput, 0.5f); - mixer.setSendLevel(i, MixerOutput::MainOutput, 0.5f); - } - float32_t* inS = inSamples[StereoChannels::Left]; float32_t* outS[StereoChannels::kNumChannels]; outS[StereoChannels::Left ] = outSamples[StereoChannels::Left ];