parent
548bbe3a02
commit
4fc98cde0b
@ -1,938 +0,0 @@ |
|||||||
/** |
|
||||||
* |
|
||||||
* Copyright (c) 2016-2017 Holger Wirtz <dcoredump@googlemail.com> |
|
||||||
* |
|
||||||
* 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. |
|
||||||
* |
|
||||||
* 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. |
|
||||||
* |
|
||||||
* You should have received a copy of the GNU General Public License |
|
||||||
* along with this program; if not, write to the Free Software Foundation, |
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
|
||||||
* |
|
||||||
*/ |
|
||||||
|
|
||||||
#include <lvtk/synth.hpp> |
|
||||||
#include "dexed.h" |
|
||||||
#include "dexed_ttl.h" |
|
||||||
#include "EngineMkI.h" |
|
||||||
#include "EngineOpl.h" |
|
||||||
#include "msfa/fm_core.h" |
|
||||||
#include "msfa/exp2.h" |
|
||||||
#include "msfa/sin.h" |
|
||||||
#include "msfa/freqlut.h" |
|
||||||
#include "msfa/controllers.h" |
|
||||||
#include "PluginFx.h" |
|
||||||
#include <unistd.h> |
|
||||||
#include <limits.h> |
|
||||||
|
|
||||||
Dexed::Dexed(double rate) : lvtk::Synth<DexedVoice, Dexed>(p_n_ports, p_midi_in) |
|
||||||
{ |
|
||||||
uint8_t i; |
|
||||||
|
|
||||||
TRACE("--------------------------------------------------------------------------------"); |
|
||||||
TRACE("Hi"); |
|
||||||
|
|
||||||
Exp2::init(); |
|
||||||
Tanh::init(); |
|
||||||
Sin::init(); |
|
||||||
|
|
||||||
Freqlut::init(rate); |
|
||||||
Lfo::init(rate); |
|
||||||
PitchEnv::init(rate); |
|
||||||
Env::init_sr(rate); |
|
||||||
fx.init(rate); |
|
||||||
|
|
||||||
if(!(engineMkI=new EngineMkI)) |
|
||||||
{ |
|
||||||
TRACE("Cannot not create engine EngineMkI"); |
|
||||||
exit(400); |
|
||||||
} |
|
||||||
if(!(engineOpl=new EngineOpl)) |
|
||||||
{ |
|
||||||
if(engineMkI) |
|
||||||
delete(engineMkI); |
|
||||||
TRACE("Cannot not create engine EngineOpl"); |
|
||||||
exit(401); |
|
||||||
} |
|
||||||
if(!(engineMsfa=new FmCore)) |
|
||||||
{ |
|
||||||
if(engineMkI) |
|
||||||
delete(engineMkI); |
|
||||||
if(engineOpl) |
|
||||||
delete(engineOpl); |
|
||||||
TRACE("Cannot create engine FmCore"); |
|
||||||
exit(402); |
|
||||||
} |
|
||||||
|
|
||||||
for(i=0; i<MAX_ACTIVE_NOTES; i++) { |
|
||||||
if(!(voices[i].dx7_note = new Dx7Note)) |
|
||||||
{ |
|
||||||
TRACE("Cannot create DX7Note [%d]",i); |
|
||||||
exit(403); |
|
||||||
} |
|
||||||
voices[i].keydown = false; |
|
||||||
voices[i].sustained = false; |
|
||||||
voices[i].live = false; |
|
||||||
} |
|
||||||
|
|
||||||
for(i=0;i<sizeof(data);++i) |
|
||||||
{ |
|
||||||
data_float[i]=static_cast<float>(data[i]); |
|
||||||
TRACE("%d->%f",i,data_float[i]); |
|
||||||
} |
|
||||||
|
|
||||||
max_notes=16; |
|
||||||
currentNote = 0; |
|
||||||
controllers.values_[kControllerPitch] = 0x2000; |
|
||||||
controllers.values_[kControllerPitchRange] = 0; |
|
||||||
controllers.values_[kControllerPitchStep] = 0; |
|
||||||
controllers.modwheel_cc = 0; |
|
||||||
controllers.foot_cc = 0; |
|
||||||
controllers.breath_cc = 0; |
|
||||||
controllers.aftertouch_cc = 0; |
|
||||||
controllers.masterTune=0; |
|
||||||
controllers.opSwitch=0x3f; // enable all operators |
|
||||||
//controllers.opSwitch=0x00; |
|
||||||
|
|
||||||
bufsize_=256; |
|
||||||
|
|
||||||
if(!(outbuf_=new float[bufsize_])) |
|
||||||
{ |
|
||||||
TRACE("Cannot create outbuf_ buffer"); |
|
||||||
exit(404); |
|
||||||
} |
|
||||||
|
|
||||||
lfo.reset(data+137); |
|
||||||
|
|
||||||
|
|
||||||
setMonoMode(false); |
|
||||||
|
|
||||||
sustain = false; |
|
||||||
|
|
||||||
extra_buf_size_ = 0; |
|
||||||
|
|
||||||
memset(&voiceStatus, 0, sizeof(VoiceStatus)); |
|
||||||
|
|
||||||
setEngineType(DEXED_ENGINE_MODERN); |
|
||||||
|
|
||||||
//add_voices(new DexedVoice(rate)); |
|
||||||
|
|
||||||
add_audio_outputs(p_audio_out); |
|
||||||
|
|
||||||
TRACE("Bye"); |
|
||||||
} |
|
||||||
|
|
||||||
Dexed::~Dexed() |
|
||||||
{ |
|
||||||
TRACE("Hi"); |
|
||||||
|
|
||||||
if(outbuf_!=NULL) |
|
||||||
delete [] outbuf_; |
|
||||||
|
|
||||||
currentNote = -1; |
|
||||||
|
|
||||||
for (uint8_t note = 0; note < MAX_ACTIVE_NOTES; ++note) |
|
||||||
{ |
|
||||||
if ( voices[note].dx7_note != NULL ) |
|
||||||
{ |
|
||||||
delete voices[note].dx7_note; |
|
||||||
voices[note].dx7_note = NULL; |
|
||||||
} |
|
||||||
voices[note].keydown = false; |
|
||||||
voices[note].sustained = false; |
|
||||||
voices[note].live = false; |
|
||||||
} |
|
||||||
|
|
||||||
if(engineMsfa) |
|
||||||
delete(engineMkI); |
|
||||||
if(engineOpl) |
|
||||||
delete(engineMkI); |
|
||||||
if(engineMkI) |
|
||||||
delete(engineMkI); |
|
||||||
|
|
||||||
TRACE("Bye"); |
|
||||||
TRACE("--------------------------------------------------------------------------------"); |
|
||||||
} |
|
||||||
|
|
||||||
void Dexed::activate(void) |
|
||||||
{ |
|
||||||
TRACE("Hi"); |
|
||||||
|
|
||||||
Plugin::activate(); |
|
||||||
panic(); |
|
||||||
controllers.values_[kControllerPitchRange] = data[155]; |
|
||||||
controllers.values_[kControllerPitchStep] = data[156]; |
|
||||||
|
|
||||||
TRACE("Bye"); |
|
||||||
} |
|
||||||
|
|
||||||
void Dexed::deactivate(void) |
|
||||||
{ |
|
||||||
TRACE("Hi"); |
|
||||||
|
|
||||||
Plugin::deactivate(); |
|
||||||
|
|
||||||
TRACE("Bye"); |
|
||||||
} |
|
||||||
|
|
||||||
void Dexed::set_params(void) |
|
||||||
{ |
|
||||||
//TRACE("Hi"); |
|
||||||
|
|
||||||
_param_change_counter=0; |
|
||||||
|
|
||||||
bool polymono=bool(*p(p_polymono)); |
|
||||||
uint8_t engine=uint8_t(*p(p_engine)); |
|
||||||
float f_gain=*p(p_output); |
|
||||||
float f_cutoff=*p(p_cutoff); |
|
||||||
float f_reso=*p(p_resonance); |
|
||||||
|
|
||||||
// Dexed-Unisono |
|
||||||
if(isMonoMode()!=polymono) |
|
||||||
setMonoMode(polymono); |
|
||||||
|
|
||||||
// Dexed-Engine |
|
||||||
if(controllers.core==NULL || getEngineType()!=engine) |
|
||||||
{ |
|
||||||
setEngineType(engine); |
|
||||||
refreshVoice=true; |
|
||||||
} |
|
||||||
|
|
||||||
// Dexed-Filter |
|
||||||
if(fx.uiCutoff!=f_cutoff) |
|
||||||
{ |
|
||||||
fx.uiCutoff=f_cutoff; |
|
||||||
refreshVoice=true; |
|
||||||
} |
|
||||||
if(fx.uiReso!=f_reso) |
|
||||||
{ |
|
||||||
fx.uiReso=f_reso; |
|
||||||
refreshVoice=true; |
|
||||||
} |
|
||||||
if(fx.uiGain!=f_gain) |
|
||||||
{ |
|
||||||
fx.uiGain=f_gain; |
|
||||||
refreshVoice=true; |
|
||||||
} |
|
||||||
|
|
||||||
// OP6 |
|
||||||
onParam(0,*p(p_op6_eg_rate_1)); |
|
||||||
onParam(1,*p(p_op6_eg_rate_2)); |
|
||||||
onParam(2,*p(p_op6_eg_rate_3)); |
|
||||||
onParam(3,*p(p_op6_eg_rate_4)); |
|
||||||
onParam(4,*p(p_op6_eg_level_1)); |
|
||||||
onParam(5,*p(p_op6_eg_level_2)); |
|
||||||
onParam(6,*p(p_op6_eg_level_3)); |
|
||||||
onParam(7,*p(p_op6_eg_level_4)); |
|
||||||
onParam(8,*p(p_op6_kbd_lev_scl_brk_pt)); |
|
||||||
onParam(9,*p(p_op6_kbd_lev_scl_lft_depth)); |
|
||||||
onParam(10,*p(p_op6_kbd_lev_scl_rht_depth)); |
|
||||||
onParam(11,*p(p_op6_kbd_lev_scl_lft_curve)); |
|
||||||
onParam(12,*p(p_op6_kbd_lev_scl_rht_curve)); |
|
||||||
onParam(13,*p(p_op6_kbd_rate_scaling)); |
|
||||||
onParam(14,*p(p_op6_amp_mod_sensitivity)); |
|
||||||
onParam(15,*p(p_op6_key_vel_sensitivity)); |
|
||||||
onParam(16,*p(p_op6_operator_output_level)); |
|
||||||
onParam(17,*p(p_op6_osc_mode)); |
|
||||||
onParam(18,*p(p_op6_osc_freq_coarse)); |
|
||||||
onParam(19,*p(p_op6_osc_freq_fine)); |
|
||||||
onParam(20,*p(p_op6_osc_detune)+7); |
|
||||||
// OP5 |
|
||||||
onParam(21,*p(p_op5_eg_rate_1)); |
|
||||||
onParam(22,*p(p_op5_eg_rate_2)); |
|
||||||
onParam(23,*p(p_op5_eg_rate_3)); |
|
||||||
onParam(24,*p(p_op5_eg_rate_4)); |
|
||||||
onParam(25,*p(p_op5_eg_level_1)); |
|
||||||
onParam(26,*p(p_op5_eg_level_2)); |
|
||||||
onParam(27,*p(p_op5_eg_level_3)); |
|
||||||
onParam(28,*p(p_op5_eg_level_4)); |
|
||||||
onParam(29,*p(p_op5_kbd_lev_scl_brk_pt)); |
|
||||||
onParam(30,*p(p_op5_kbd_lev_scl_lft_depth)); |
|
||||||
onParam(31,*p(p_op5_kbd_lev_scl_rht_depth)); |
|
||||||
onParam(32,*p(p_op5_kbd_lev_scl_lft_curve)); |
|
||||||
onParam(33,*p(p_op5_kbd_lev_scl_rht_curve)); |
|
||||||
onParam(34,*p(p_op5_kbd_rate_scaling)); |
|
||||||
onParam(35,*p(p_op5_amp_mod_sensitivity)); |
|
||||||
onParam(36,*p(p_op5_key_vel_sensitivity)); |
|
||||||
onParam(37,*p(p_op5_operator_output_level)); |
|
||||||
onParam(38,*p(p_op5_osc_mode)); |
|
||||||
onParam(39,*p(p_op5_osc_freq_coarse)); |
|
||||||
onParam(40,*p(p_op5_osc_freq_fine)); |
|
||||||
onParam(41,*p(p_op5_osc_detune)+7); |
|
||||||
// OP4 |
|
||||||
onParam(42,*p(p_op4_eg_rate_1)); |
|
||||||
onParam(43,*p(p_op4_eg_rate_2)); |
|
||||||
onParam(44,*p(p_op4_eg_rate_3)); |
|
||||||
onParam(45,*p(p_op4_eg_rate_4)); |
|
||||||
onParam(46,*p(p_op4_eg_level_1)); |
|
||||||
onParam(47,*p(p_op4_eg_level_2)); |
|
||||||
onParam(48,*p(p_op4_eg_level_3)); |
|
||||||
onParam(49,*p(p_op4_eg_level_4)); |
|
||||||
onParam(50,*p(p_op4_kbd_lev_scl_brk_pt)); |
|
||||||
onParam(51,*p(p_op4_kbd_lev_scl_lft_depth)); |
|
||||||
onParam(52,*p(p_op4_kbd_lev_scl_rht_depth)); |
|
||||||
onParam(53,*p(p_op4_kbd_lev_scl_lft_curve)); |
|
||||||
onParam(54,*p(p_op4_kbd_lev_scl_rht_curve)); |
|
||||||
onParam(55,*p(p_op4_kbd_rate_scaling)); |
|
||||||
onParam(56,*p(p_op4_amp_mod_sensitivity)); |
|
||||||
onParam(57,*p(p_op4_key_vel_sensitivity)); |
|
||||||
onParam(58,*p(p_op4_operator_output_level)); |
|
||||||
onParam(59,*p(p_op4_osc_mode)); |
|
||||||
onParam(60,*p(p_op4_osc_freq_coarse)); |
|
||||||
onParam(61,*p(p_op4_osc_freq_fine)); |
|
||||||
onParam(62,*p(p_op4_osc_detune)+7); |
|
||||||
// OP3 |
|
||||||
onParam(63,*p(p_op3_eg_rate_1)); |
|
||||||
onParam(64,*p(p_op3_eg_rate_2)); |
|
||||||
onParam(65,*p(p_op3_eg_rate_3)); |
|
||||||
onParam(66,*p(p_op3_eg_rate_4)); |
|
||||||
onParam(67,*p(p_op3_eg_level_1)); |
|
||||||
onParam(68,*p(p_op3_eg_level_2)); |
|
||||||
onParam(69,*p(p_op3_eg_level_3)); |
|
||||||
onParam(70,*p(p_op3_eg_level_4)); |
|
||||||
onParam(71,*p(p_op3_kbd_lev_scl_brk_pt)); |
|
||||||
onParam(72,*p(p_op3_kbd_lev_scl_lft_depth)); |
|
||||||
onParam(73,*p(p_op3_kbd_lev_scl_rht_depth)); |
|
||||||
onParam(74,*p(p_op3_kbd_lev_scl_lft_curve)); |
|
||||||
onParam(75,*p(p_op3_kbd_lev_scl_rht_curve)); |
|
||||||
onParam(76,*p(p_op3_kbd_rate_scaling)); |
|
||||||
onParam(77,*p(p_op3_amp_mod_sensitivity)); |
|
||||||
onParam(78,*p(p_op3_key_vel_sensitivity)); |
|
||||||
onParam(79,*p(p_op3_operator_output_level)); |
|
||||||
onParam(80,*p(p_op3_osc_mode)); |
|
||||||
onParam(81,*p(p_op3_osc_freq_coarse)); |
|
||||||
onParam(82,*p(p_op3_osc_freq_fine)); |
|
||||||
onParam(83,*p(p_op3_osc_detune)+7); |
|
||||||
// OP2 |
|
||||||
onParam(84,*p(p_op2_eg_rate_1)); |
|
||||||
onParam(85,*p(p_op2_eg_rate_2)); |
|
||||||
onParam(86,*p(p_op2_eg_rate_3)); |
|
||||||
onParam(87,*p(p_op2_eg_rate_4)); |
|
||||||
onParam(88,*p(p_op2_eg_level_1)); |
|
||||||
onParam(89,*p(p_op2_eg_level_2)); |
|
||||||
onParam(90,*p(p_op2_eg_level_3)); |
|
||||||
onParam(91,*p(p_op2_eg_level_4)); |
|
||||||
onParam(92,*p(p_op2_kbd_lev_scl_brk_pt)); |
|
||||||
onParam(93,*p(p_op2_kbd_lev_scl_lft_depth)); |
|
||||||
onParam(94,*p(p_op2_kbd_lev_scl_rht_depth)); |
|
||||||
onParam(95,*p(p_op2_kbd_lev_scl_lft_curve)); |
|
||||||
onParam(96,*p(p_op2_kbd_lev_scl_rht_curve)); |
|
||||||
onParam(97,*p(p_op2_kbd_rate_scaling)); |
|
||||||
onParam(98,*p(p_op2_amp_mod_sensitivity)); |
|
||||||
onParam(99,*p(p_op2_key_vel_sensitivity)); |
|
||||||
onParam(100,*p(p_op2_operator_output_level)); |
|
||||||
onParam(101,*p(p_op2_osc_mode)); |
|
||||||
onParam(102,*p(p_op2_osc_freq_coarse)); |
|
||||||
onParam(103,*p(p_op2_osc_freq_fine)); |
|
||||||
onParam(104,*p(p_op2_osc_detune)+7); |
|
||||||
// OP1 |
|
||||||
onParam(105,*p(p_op1_eg_rate_1)); |
|
||||||
onParam(106,*p(p_op1_eg_rate_2)); |
|
||||||
onParam(107,*p(p_op1_eg_rate_3)); |
|
||||||
onParam(108,*p(p_op1_eg_rate_4)); |
|
||||||
onParam(109,*p(p_op1_eg_level_1)); |
|
||||||
onParam(110,*p(p_op1_eg_level_2)); |
|
||||||
onParam(111,*p(p_op1_eg_level_3)); |
|
||||||
onParam(112,*p(p_op1_eg_level_4)); |
|
||||||
onParam(113,*p(p_op1_kbd_lev_scl_brk_pt)); |
|
||||||
onParam(114,*p(p_op1_kbd_lev_scl_lft_depth)); |
|
||||||
onParam(115,*p(p_op1_kbd_lev_scl_rht_depth)); |
|
||||||
onParam(116,*p(p_op1_kbd_lev_scl_lft_curve)); |
|
||||||
onParam(117,*p(p_op1_kbd_lev_scl_rht_curve)); |
|
||||||
onParam(118,*p(p_op1_kbd_rate_scaling)); |
|
||||||
onParam(119,*p(p_op1_amp_mod_sensitivity)); |
|
||||||
onParam(120,*p(p_op1_key_vel_sensitivity)); |
|
||||||
onParam(121,*p(p_op1_operator_output_level)); |
|
||||||
onParam(122,*p(p_op1_osc_mode)); |
|
||||||
onParam(123,*p(p_op1_osc_freq_coarse)); |
|
||||||
onParam(124,*p(p_op1_osc_freq_fine)); |
|
||||||
onParam(125,*p(p_op1_osc_detune)+7); |
|
||||||
// Global for all OPs |
|
||||||
onParam(126,*p(p_pitch_eg_rate_1)); |
|
||||||
onParam(127,*p(p_pitch_eg_rate_2)); |
|
||||||
onParam(128,*p(p_pitch_eg_rate_3)); |
|
||||||
onParam(129,*p(p_pitch_eg_rate_4)); |
|
||||||
onParam(130,*p(p_pitch_eg_level_1)); |
|
||||||
onParam(131,*p(p_pitch_eg_level_2)); |
|
||||||
onParam(132,*p(p_pitch_eg_level_3)); |
|
||||||
onParam(133,*p(p_pitch_eg_level_4)); |
|
||||||
onParam(134,*p(p_algorithm_num)-1); |
|
||||||
onParam(135,*p(p_feedback)); |
|
||||||
onParam(136,*p(p_oscillator_sync)); |
|
||||||
onParam(137,*p(p_lfo_speed)); |
|
||||||
onParam(138,*p(p_lfo_delay)); |
|
||||||
onParam(139,*p(p_lfo_pitch_mod_depth)); |
|
||||||
onParam(140,*p(p_lfo_amp_mod_depth)); |
|
||||||
onParam(141,*p(p_lfo_sync)); |
|
||||||
onParam(142,*p(p_lfo_waveform)); |
|
||||||
onParam(143,*p(p_pitch_mod_sensitivity)); |
|
||||||
onParam(144,*p(p_transpose)); |
|
||||||
// 10 bytes (145-154) are the name of the patch |
|
||||||
// Controllers (added at the end of the data[]) |
|
||||||
onParam(155,*p(p_pitch_bend_range)); |
|
||||||
onParam(156,*p(p_pitch_bend_step)); |
|
||||||
onParam(157,*p(p_mod_wheel_range)); |
|
||||||
onParam(158,*p(p_mod_wheel_assign)); |
|
||||||
onParam(159,*p(p_foot_ctrl_range)); |
|
||||||
onParam(160,*p(p_foot_ctrl_assign)); |
|
||||||
onParam(161,*p(p_breath_ctrl_range)); |
|
||||||
onParam(162,*p(p_breath_ctrl_assign)); |
|
||||||
onParam(163,*p(p_aftertouch_range)); |
|
||||||
onParam(164,*p(p_aftertouch_assign)); |
|
||||||
onParam(165,*p(p_master_tune)); |
|
||||||
onParam(166,*p(p_op1_enable)); |
|
||||||
onParam(167,*p(p_op2_enable)); |
|
||||||
onParam(168,*p(p_op3_enable)); |
|
||||||
onParam(169,*p(p_op4_enable)); |
|
||||||
onParam(170,*p(p_op5_enable)); |
|
||||||
onParam(171,*p(p_op6_enable)); |
|
||||||
onParam(172,*p(p_number_of_voices)); |
|
||||||
|
|
||||||
if(_param_change_counter>PARAM_CHANGE_LEVEL) |
|
||||||
{ |
|
||||||
panic(); |
|
||||||
controllers.refresh(); |
|
||||||
} |
|
||||||
|
|
||||||
//TRACE("Bye"); |
|
||||||
} |
|
||||||
|
|
||||||
// override the run() method |
|
||||||
void Dexed::run (uint32_t sample_count) |
|
||||||
{ |
|
||||||
const LV2_Atom_Sequence* seq = p<LV2_Atom_Sequence> (p_midi_in); |
|
||||||
float* output = p(p_audio_out); |
|
||||||
uint32_t last_frame = 0, num_this_time = 0; |
|
||||||
bool drop_next_events=false; |
|
||||||
|
|
||||||
Plugin::run(sample_count); |
|
||||||
|
|
||||||
if(++_k_rate_counter%16) |
|
||||||
set_params(); // pre_process: copy actual voice params |
|
||||||
|
|
||||||
for (LV2_Atom_Event* ev = lv2_atom_sequence_begin (&seq->body); |
|
||||||
!lv2_atom_sequence_is_end(&seq->body, seq->atom.size, ev); |
|
||||||
ev = lv2_atom_sequence_next (ev)) |
|
||||||
{ |
|
||||||
num_this_time = ev->time.frames - last_frame; |
|
||||||
|
|
||||||
// If it's midi, send it to the engine |
|
||||||
if (ev->body.type == m_midi_type) |
|
||||||
{ |
|
||||||
drop_next_events|=ProcessMidiMessage((uint8_t*) LV2_ATOM_BODY (&ev->body),ev->body.size); |
|
||||||
if(drop_next_events==true) |
|
||||||
continue; |
|
||||||
} |
|
||||||
|
|
||||||
// render audio from the last frame until the timestamp of this event |
|
||||||
GetSamples (num_this_time, outbuf_); |
|
||||||
|
|
||||||
// i is the index of the engine's buf, which always starts at 0 (i think) |
|
||||||
// j is the index of the plugin's float output buffer which will be the timestamp |
|
||||||
// of the last processed atom event. |
|
||||||
for (uint32_t i = 0, j = last_frame; i < num_this_time; ++i, ++j) |
|
||||||
output[j]=outbuf_[i]; |
|
||||||
|
|
||||||
last_frame = ev->time.frames; |
|
||||||
} |
|
||||||
|
|
||||||
// render remaining samples if any left |
|
||||||
if (last_frame < sample_count) |
|
||||||
{ |
|
||||||
// do the same thing as above except from last frame until the end of |
|
||||||
// the processing cycles last sample. at this point, all events have |
|
||||||
// already been handled. |
|
||||||
|
|
||||||
num_this_time = sample_count - last_frame; |
|
||||||
GetSamples (num_this_time, outbuf_); |
|
||||||
for (uint32_t i = 0, j = last_frame; i < num_this_time; ++i, ++j) |
|
||||||
output[j] = outbuf_[i]; |
|
||||||
} |
|
||||||
|
|
||||||
fx.process(output, sample_count); |
|
||||||
} |
|
||||||
|
|
||||||
void Dexed::GetSamples(uint32_t n_samples, float* buffer) |
|
||||||
{ |
|
||||||
uint32_t i; |
|
||||||
|
|
||||||
if(refreshVoice) { |
|
||||||
for(i=0;i < max_notes;i++) { |
|
||||||
if ( voices[i].live ) |
|
||||||
voices[i].dx7_note->update(data, voices[i].midi_note, voices[i].velocity); |
|
||||||
} |
|
||||||
lfo.reset(data+137); |
|
||||||
refreshVoice = false; |
|
||||||
} |
|
||||||
|
|
||||||
// flush first events |
|
||||||
for (i=0; i < n_samples && i < extra_buf_size_; i++) { |
|
||||||
buffer[i] = extra_buf_[i]; |
|
||||||
} |
|
||||||
|
|
||||||
// remaining buffer is still to be processed |
|
||||||
if (extra_buf_size_ > n_samples) { |
|
||||||
for (uint32_t j = 0; j < extra_buf_size_ - n_samples; j++) { |
|
||||||
extra_buf_[j] = extra_buf_[j + n_samples]; |
|
||||||
} |
|
||||||
extra_buf_size_ -= n_samples; |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
for (; i < n_samples; i += N) { |
|
||||||
AlignedBuf<int32_t, N> audiobuf; |
|
||||||
float sumbuf[N]; |
|
||||||
|
|
||||||
for (uint32_t j = 0; j < N; ++j) { |
|
||||||
audiobuf.get()[j] = 0; |
|
||||||
sumbuf[j] = 0.0; |
|
||||||
} |
|
||||||
|
|
||||||
int32_t lfovalue = lfo.getsample(); |
|
||||||
int32_t lfodelay = lfo.getdelay(); |
|
||||||
|
|
||||||
for (uint8_t note = 0; note < max_notes; ++note) { |
|
||||||
if (voices[note].live) { |
|
||||||
voices[note].dx7_note->compute(audiobuf.get(), lfovalue, lfodelay, &controllers); |
|
||||||
for (uint32_t j=0; j < N; ++j) { |
|
||||||
int32_t val = audiobuf.get()[j]; |
|
||||||
val = val >> 4; |
|
||||||
int32_t clip_val = val < -(1 << 24) ? 0x8000 : val >= (1 << 24) ? 0x7fff : val >> 9; |
|
||||||
float f = static_cast<float>(clip_val>>1)/0x8000; |
|
||||||
if(f>1) f=1; |
|
||||||
if(f<-1) f=-1; |
|
||||||
sumbuf[j]+=f; |
|
||||||
audiobuf.get()[j]=0; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
uint32_t jmax = n_samples - i; |
|
||||||
for (uint32_t j = 0; j < N; ++j) { |
|
||||||
if (j < jmax) |
|
||||||
buffer[i + j] = sumbuf[j]; |
|
||||||
else |
|
||||||
extra_buf_[j - jmax] = sumbuf[j]; |
|
||||||
} |
|
||||||
} |
|
||||||
extra_buf_size_ = i - n_samples; |
|
||||||
} |
|
||||||
|
|
||||||
if(++_k_rate_counter%32 && !monoMode) |
|
||||||
{ |
|
||||||
uint8_t op_carrier=controllers.core->get_carrier_operators(data[134]); // look for carriers |
|
||||||
|
|
||||||
for(i=0;i < max_notes;i++) |
|
||||||
{ |
|
||||||
if(voices[i].live==true) |
|
||||||
{ |
|
||||||
uint8_t op_amp=0; |
|
||||||
uint8_t op_carrier_num=0; |
|
||||||
|
|
||||||
voices[i].dx7_note->peekVoiceStatus(voiceStatus); |
|
||||||
|
|
||||||
for(uint8_t op=0;op<6;op++) |
|
||||||
{ |
|
||||||
uint8_t op_bit=static_cast<uint8_t>(pow(2,op)); |
|
||||||
|
|
||||||
if((op_carrier&op_bit)>0) |
|
||||||
{ |
|
||||||
// this voice is a carrier! |
|
||||||
op_carrier_num++; |
|
||||||
|
|
||||||
//TRACE("Voice[%2d] OP [%d] amp=%ld,amp_step=%d,pitch_step=%d",i,op,voiceStatus.amp[op],voiceStatus.ampStep[op],voiceStatus.pitchStep); |
|
||||||
|
|
||||||
if(voiceStatus.amp[op]<=1069 && voiceStatus.ampStep[op]==4) // this voice produces no audio output |
|
||||||
op_amp++; |
|
||||||
} |
|
||||||
} |
|
||||||
if(op_amp==op_carrier_num) |
|
||||||
{ |
|
||||||
// all carrier-operators are silent -> disable the voice |
|
||||||
voices[i].live=false; |
|
||||||
voices[i].sustained=false; |
|
||||||
voices[i].keydown=false; |
|
||||||
TRACE("Shutted down Voice[%2d]",i); |
|
||||||
} |
|
||||||
} |
|
||||||
// TRACE("Voice[%2d] live=%d keydown=%d",i,voices[i].live,voices[i].keydown); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
bool Dexed::ProcessMidiMessage(const uint8_t *buf, uint32_t buf_size) { |
|
||||||
TRACE("Hi"); |
|
||||||
|
|
||||||
uint8_t cmd = buf[0]; |
|
||||||
|
|
||||||
switch(cmd & 0xf0) { |
|
||||||
case 0x80 : |
|
||||||
TRACE("MIDI keyup event: %d",buf[1]); |
|
||||||
keyup(buf[1]); |
|
||||||
return(false); |
|
||||||
break; |
|
||||||
case 0x90 : |
|
||||||
TRACE("MIDI keydown event: %d %d",buf[1],buf[2]); |
|
||||||
keydown(buf[1], buf[2]); |
|
||||||
return(false); |
|
||||||
break; |
|
||||||
case 0xb0 : { |
|
||||||
uint8_t ctrl = buf[1]; |
|
||||||
uint8_t value = buf[2]; |
|
||||||
|
|
||||||
switch(ctrl) { |
|
||||||
case 1: |
|
||||||
TRACE("MIDI modwheel event: %d %d",ctrl,value); |
|
||||||
controllers.modwheel_cc = value; |
|
||||||
controllers.refresh(); |
|
||||||
break; |
|
||||||
case 2: |
|
||||||
TRACE("MIDI breath event: %d %d",ctrl,value); |
|
||||||
controllers.breath_cc = value; |
|
||||||
controllers.refresh(); |
|
||||||
break; |
|
||||||
case 4: |
|
||||||
TRACE("MIDI footsw event: %d %d",ctrl,value); |
|
||||||
controllers.foot_cc = value; |
|
||||||
controllers.refresh(); |
|
||||||
break; |
|
||||||
case 64: |
|
||||||
TRACE("MIDI sustain event: %d %d",ctrl,value); |
|
||||||
sustain = value > 63; |
|
||||||
if (!sustain) { |
|
||||||
for (uint8_t note = 0; note < max_notes; note++) { |
|
||||||
if (voices[note].sustained && !voices[note].keydown) { |
|
||||||
voices[note].dx7_note->keyup(); |
|
||||||
voices[note].sustained = false; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
break; |
|
||||||
case 120: |
|
||||||
TRACE("MIDI all-sound-off: %d %d",ctrl,value); |
|
||||||
panic(); |
|
||||||
return(true); |
|
||||||
break; |
|
||||||
case 123: |
|
||||||
TRACE("MIDI all-notes-off: %d %d",ctrl,value); |
|
||||||
notes_off(); |
|
||||||
return(true); |
|
||||||
break; |
|
||||||
} |
|
||||||
break; |
|
||||||
} |
|
||||||
|
|
||||||
// case 0xc0 : |
|
||||||
// setCurrentProgram(buf[1]); |
|
||||||
// break; |
|
||||||
|
|
||||||
// channel aftertouch |
|
||||||
case 0xd0 : |
|
||||||
TRACE("MIDI aftertouch 0xd0 event: %d %d",buf[1]); |
|
||||||
controllers.aftertouch_cc = buf[1]; |
|
||||||
controllers.refresh(); |
|
||||||
break; |
|
||||||
// pitchbend |
|
||||||
case 0xe0 : |
|
||||||
TRACE("MIDI pitchbend 0xe0 event: %d %d",buf[1],buf[2]); |
|
||||||
controllers.values_[kControllerPitch] = buf[1] | (buf[2] << 7); |
|
||||||
break; |
|
||||||
|
|
||||||
default: |
|
||||||
TRACE("MIDI event unknown: cmd=%d, val1=%d, val2=%d",buf[0],buf[1],buf[2]); |
|
||||||
break; |
|
||||||
} |
|
||||||
|
|
||||||
TRACE("Bye"); |
|
||||||
return(false); |
|
||||||
} |
|
||||||
|
|
||||||
void Dexed::keydown(uint8_t pitch, uint8_t velo) { |
|
||||||
TRACE("Hi"); |
|
||||||
TRACE("pitch=%d, velo=%d\n",pitch,velo); |
|
||||||
if ( velo == 0 ) { |
|
||||||
keyup(pitch); |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
pitch += data[144] - 24; |
|
||||||
|
|
||||||
uint8_t note = currentNote; |
|
||||||
uint8_t keydown_counter=0; |
|
||||||
|
|
||||||
for (uint8_t i=0; i<max_notes; i++) { |
|
||||||
if (!voices[note].keydown) { |
|
||||||
currentNote = (note + 1) % max_notes; |
|
||||||
voices[note].midi_note = pitch; |
|
||||||
voices[note].velocity = velo; |
|
||||||
voices[note].sustained = sustain; |
|
||||||
voices[note].keydown = true; |
|
||||||
voices[note].dx7_note->init(data, pitch, velo); |
|
||||||
if ( data[136] ) |
|
||||||
voices[note].dx7_note->oscSync(); |
|
||||||
break; |
|
||||||
} |
|
||||||
else |
|
||||||
keydown_counter++; |
|
||||||
|
|
||||||
note = (note + 1) % max_notes; |
|
||||||
} |
|
||||||
|
|
||||||
if(keydown_counter==0) |
|
||||||
lfo.keydown(); |
|
||||||
if ( monoMode ) { |
|
||||||
for(uint8_t i=0; i<max_notes; i++) { |
|
||||||
if ( voices[i].live ) { |
|
||||||
// all keys are up, only transfer signal |
|
||||||
if ( ! voices[i].keydown ) { |
|
||||||
voices[i].live = false; |
|
||||||
voices[note].dx7_note->transferSignal(*voices[i].dx7_note); |
|
||||||
break; |
|
||||||
} |
|
||||||
if ( voices[i].midi_note < pitch ) { |
|
||||||
voices[i].live = false; |
|
||||||
voices[note].dx7_note->transferState(*voices[i].dx7_note); |
|
||||||
break; |
|
||||||
} |
|
||||||
return; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
voices[note].live = true; |
|
||||||
TRACE("Bye"); |
|
||||||
} |
|
||||||
|
|
||||||
void Dexed::keyup(uint8_t pitch) { |
|
||||||
TRACE("Hi"); |
|
||||||
TRACE("pitch=%d\n",pitch); |
|
||||||
|
|
||||||
pitch += data[144] - 24; |
|
||||||
|
|
||||||
uint8_t note; |
|
||||||
for (note=0; note<max_notes; ++note) { |
|
||||||
if ( voices[note].midi_note == pitch && voices[note].keydown ) { |
|
||||||
voices[note].keydown = false; |
|
||||||
break; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// note not found ? |
|
||||||
if ( note >= max_notes ) { |
|
||||||
TRACE("note-off not found???"); |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
if ( monoMode ) { |
|
||||||
int8_t highNote = -1; |
|
||||||
int8_t target = 0; |
|
||||||
for (int8_t i=0; i<max_notes;i++) { |
|
||||||
if ( voices[i].keydown && voices[i].midi_note > highNote ) { |
|
||||||
target = i; |
|
||||||
highNote = voices[i].midi_note; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
if ( highNote != -1 ) { |
|
||||||
voices[note].live = false; |
|
||||||
voices[target].live = true; |
|
||||||
voices[target].dx7_note->transferState(*voices[note].dx7_note); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
if ( sustain ) { |
|
||||||
voices[note].sustained = true; |
|
||||||
} else { |
|
||||||
voices[note].dx7_note->keyup(); |
|
||||||
} |
|
||||||
TRACE("Bye"); |
|
||||||
} |
|
||||||
|
|
||||||
void Dexed::onParam(uint8_t param_num,float param_val) |
|
||||||
{ |
|
||||||
int32_t tune; |
|
||||||
|
|
||||||
if(param_val!=data_float[param_num]) |
|
||||||
{ |
|
||||||
TRACE("Parameter %d change from %f to %f",param_num, data_float[param_num], param_val); |
|
||||||
#ifdef DEBUG |
|
||||||
uint8_t tmp=data[param_num]; |
|
||||||
#endif |
|
||||||
|
|
||||||
_param_change_counter++; |
|
||||||
|
|
||||||
if(param_num==144 || param_num==134 || param_num==172) |
|
||||||
panic(); |
|
||||||
|
|
||||||
refreshVoice=true; |
|
||||||
data[param_num]=static_cast<uint8_t>(param_val); |
|
||||||
data_float[param_num]=param_val; |
|
||||||
|
|
||||||
switch(param_num) |
|
||||||
{ |
|
||||||
case 155: |
|
||||||
controllers.values_[kControllerPitchRange]=data[param_num]; |
|
||||||
break; |
|
||||||
case 156: |
|
||||||
controllers.values_[kControllerPitchStep]=data[param_num]; |
|
||||||
break; |
|
||||||
case 157: |
|
||||||
TRACE("wheel.setRange(%d)",data[param_num]); |
|
||||||
controllers.wheel.setRange(data[param_num]); |
|
||||||
break; |
|
||||||
case 158: |
|
||||||
controllers.wheel.setTarget(data[param_num]); |
|
||||||
break; |
|
||||||
case 159: |
|
||||||
controllers.foot.setRange(data[param_num]); |
|
||||||
break; |
|
||||||
case 160: |
|
||||||
controllers.foot.setTarget(data[param_num]); |
|
||||||
break; |
|
||||||
case 161: |
|
||||||
controllers.breath.setRange(data[param_num]); |
|
||||||
break; |
|
||||||
case 162: |
|
||||||
controllers.breath.setTarget(data[param_num]); |
|
||||||
break; |
|
||||||
case 163: |
|
||||||
controllers.at.setRange(data[param_num]); |
|
||||||
break; |
|
||||||
case 164: |
|
||||||
controllers.at.setTarget(data[param_num]); |
|
||||||
break; |
|
||||||
case 165: |
|
||||||
tune=param_val*0x4000; |
|
||||||
controllers.masterTune=(tune<<11)*(1.0/12); |
|
||||||
break; |
|
||||||
case 166: |
|
||||||
case 167: |
|
||||||
case 168: |
|
||||||
case 169: |
|
||||||
case 170: |
|
||||||
case 171: |
|
||||||
controllers.opSwitch=(data[166]<<5)|(data[167]<<4)|(data[168]<<3)|(data[169]<<2)|(data[170]<<1)|data[171]; |
|
||||||
break; |
|
||||||
case 172: |
|
||||||
max_notes=data[param_num]; |
|
||||||
break; |
|
||||||
} |
|
||||||
|
|
||||||
TRACE("Done: Parameter %d changed from %d to %d",param_num, tmp, data[param_num]); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
uint8_t Dexed::getEngineType() { |
|
||||||
return engineType; |
|
||||||
} |
|
||||||
|
|
||||||
void Dexed::setEngineType(uint8_t tp) { |
|
||||||
TRACE("settings engine %d", tp); |
|
||||||
|
|
||||||
if(engineType==tp && controllers.core!=NULL) |
|
||||||
return; |
|
||||||
|
|
||||||
switch (tp) { |
|
||||||
case DEXED_ENGINE_MARKI: |
|
||||||
TRACE("DEXED_ENGINE_MARKI:%d",DEXED_ENGINE_MARKI); |
|
||||||
controllers.core = engineMkI; |
|
||||||
break; |
|
||||||
case DEXED_ENGINE_OPL: |
|
||||||
TRACE("DEXED_ENGINE_OPL:%d",DEXED_ENGINE_OPL); |
|
||||||
controllers.core = engineOpl; |
|
||||||
break; |
|
||||||
default: |
|
||||||
TRACE("DEXED_ENGINE_MODERN:%d",DEXED_ENGINE_MODERN); |
|
||||||
controllers.core = engineMsfa; |
|
||||||
tp=DEXED_ENGINE_MODERN; |
|
||||||
break; |
|
||||||
} |
|
||||||
engineType = tp; |
|
||||||
panic(); |
|
||||||
controllers.refresh(); |
|
||||||
} |
|
||||||
|
|
||||||
bool Dexed::isMonoMode(void) { |
|
||||||
return monoMode; |
|
||||||
} |
|
||||||
|
|
||||||
void Dexed::setMonoMode(bool mode) { |
|
||||||
if(monoMode==mode) |
|
||||||
return; |
|
||||||
|
|
||||||
monoMode = mode; |
|
||||||
} |
|
||||||
|
|
||||||
void Dexed::panic(void) { |
|
||||||
for(uint8_t i=0;i<MAX_ACTIVE_NOTES;i++) |
|
||||||
{ |
|
||||||
if(voices[i].live == true) { |
|
||||||
voices[i].keydown = false; |
|
||||||
voices[i].live = false; |
|
||||||
voices[i].sustained = false; |
|
||||||
if ( voices[i].dx7_note != NULL ) { |
|
||||||
voices[i].dx7_note->oscSync(); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
void Dexed::notes_off(void) { |
|
||||||
for(uint8_t i=0;i<MAX_ACTIVE_NOTES;i++) { |
|
||||||
if(voices[i].live==true&&voices[i].keydown==true) { |
|
||||||
voices[i].keydown=false; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
//============================================================================== |
|
||||||
|
|
||||||
DexedVoice::DexedVoice(double rate) : m_key(lvtk::INVALID_KEY), m_rate(rate) |
|
||||||
{ |
|
||||||
TRACE("Hi"); |
|
||||||
|
|
||||||
TRACE("Bye"); |
|
||||||
} |
|
||||||
|
|
||||||
DexedVoice::~DexedVoice() |
|
||||||
{ |
|
||||||
TRACE("Hi"); |
|
||||||
|
|
||||||
TRACE("Bye"); |
|
||||||
} |
|
||||||
|
|
||||||
void DexedVoice::on(unsigned char key, unsigned char velocity) |
|
||||||
{ |
|
||||||
TRACE("Hi"); |
|
||||||
|
|
||||||
m_key = key; |
|
||||||
|
|
||||||
TRACE("Bye"); |
|
||||||
} |
|
||||||
|
|
||||||
void DexedVoice::off(unsigned char velocity) |
|
||||||
{ |
|
||||||
TRACE("Hi"); |
|
||||||
|
|
||||||
m_key = lvtk::INVALID_KEY; |
|
||||||
|
|
||||||
TRACE("Bye"); |
|
||||||
} |
|
||||||
|
|
||||||
unsigned char DexedVoice::get_key(void) const |
|
||||||
{ |
|
||||||
TRACE("Hi"); |
|
||||||
|
|
||||||
return m_key; |
|
||||||
|
|
||||||
TRACE("Bye"); |
|
||||||
} |
|
||||||
|
|
||||||
static int _ = Dexed::register_class(p_uri); |
|
@ -1,931 +0,0 @@ |
|||||||
/** |
|
||||||
* |
|
||||||
* Copyright (c) 2016-2017 Holger Wirtz <dcoredump@googlemail.com> |
|
||||||
* |
|
||||||
* 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. |
|
||||||
* |
|
||||||
* 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. |
|
||||||
* |
|
||||||
* You should have received a copy of the GNU General Public License |
|
||||||
* along with this program; if not, write to the Free Software Foundation, |
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
|
||||||
* |
|
||||||
*/ |
|
||||||
|
|
||||||
#include "synth.h" |
|
||||||
#include "dexed.h" |
|
||||||
#include "EngineMkI.h" |
|
||||||
#include "EngineOpl.h" |
|
||||||
#include "fm_core.h" |
|
||||||
#include "exp2.h" |
|
||||||
#include "sin.h" |
|
||||||
#include "freqlut.h" |
|
||||||
#include "controllers.h" |
|
||||||
#include <unistd.h> |
|
||||||
#include <limits.h> |
|
||||||
|
|
||||||
Dexed::Dexed(double rate) : lvtk::Synth<DexedVoice, Dexed>(p_n_ports, p_midi_in) |
|
||||||
{ |
|
||||||
uint8_t i; |
|
||||||
|
|
||||||
TRACE("--------------------------------------------------------------------------------"); |
|
||||||
TRACE("Hi"); |
|
||||||
|
|
||||||
Exp2::init(); |
|
||||||
Tanh::init(); |
|
||||||
Sin::init(); |
|
||||||
|
|
||||||
Freqlut::init(rate); |
|
||||||
Lfo::init(rate); |
|
||||||
PitchEnv::init(rate); |
|
||||||
Env::init_sr(rate); |
|
||||||
fx.init(rate); |
|
||||||
|
|
||||||
engineMkI=new EngineMkI; |
|
||||||
engineOpl=new EngineOpl; |
|
||||||
engineMsfa=new FmCore; |
|
||||||
|
|
||||||
/* |
|
||||||
if(!(engineMkI=new (std::nothrow) EngineMkI)) |
|
||||||
TRACE("Cannot not create engine EngineMkI"); |
|
||||||
if(!(engineOpl=new (std::nothrow) EngineOpl)) |
|
||||||
{ |
|
||||||
delete(engineMkI); |
|
||||||
TRACE("Cannot not create engine EngineOpl"); |
|
||||||
} |
|
||||||
if(!(engineMsfa=new (std::nothrow) FmCore)) |
|
||||||
{ |
|
||||||
delete(engineMkI); |
|
||||||
delete(engineOpl); |
|
||||||
TRACE("Cannot create engine FmCore"); |
|
||||||
} |
|
||||||
*/ |
|
||||||
|
|
||||||
for(i=0; i<MAX_ACTIVE_NOTES; i++) { |
|
||||||
// if(!(voices[i].dx7_note = new (std::nothrow) Dx7Note)) |
|
||||||
// TRACE("Cannot create DX7Note [%d]",i); |
|
||||||
voices[i].dx7_note = new Dx7Note; |
|
||||||
voices[i].keydown = false; |
|
||||||
voices[i].sustained = false; |
|
||||||
voices[i].live = false; |
|
||||||
} |
|
||||||
|
|
||||||
for(i=0;i<sizeof(data);++i) |
|
||||||
{ |
|
||||||
data_float[i]=static_cast<float>(data[i]); |
|
||||||
TRACE("%d->%f",i,data_float[i]); |
|
||||||
} |
|
||||||
|
|
||||||
max_notes=16; |
|
||||||
currentNote = 0; |
|
||||||
controllers.values_[kControllerPitch] = 0x2000; |
|
||||||
controllers.values_[kControllerPitchRange] = 0; |
|
||||||
controllers.values_[kControllerPitchStep] = 0; |
|
||||||
controllers.modwheel_cc = 0; |
|
||||||
controllers.foot_cc = 0; |
|
||||||
controllers.breath_cc = 0; |
|
||||||
controllers.aftertouch_cc = 0; |
|
||||||
controllers.masterTune=0; |
|
||||||
controllers.opSwitch=0x3f; // enable all operators |
|
||||||
//controllers.opSwitch=0x00; |
|
||||||
|
|
||||||
bufsize_=256; |
|
||||||
|
|
||||||
outbuf_=new float[bufsize_]; |
|
||||||
//if(!(outbuf_=new (std::nothrow) float[bufsize_])) |
|
||||||
// TRACE("Cannot create outbuf_ buffer"); |
|
||||||
|
|
||||||
lfo.reset(data+137); |
|
||||||
|
|
||||||
setMonoMode(false); |
|
||||||
|
|
||||||
sustain = false; |
|
||||||
|
|
||||||
extra_buf_size_ = 0; |
|
||||||
|
|
||||||
memset(&voiceStatus, 0, sizeof(VoiceStatus)); |
|
||||||
|
|
||||||
setEngineType(DEXED_ENGINE_MODERN); |
|
||||||
|
|
||||||
//add_voices(new DexedVoice(rate)); |
|
||||||
|
|
||||||
add_audio_outputs(p_audio_out); |
|
||||||
|
|
||||||
TRACE("Bye"); |
|
||||||
} |
|
||||||
|
|
||||||
Dexed::~Dexed() |
|
||||||
{ |
|
||||||
TRACE("Hi"); |
|
||||||
|
|
||||||
delete [] outbuf_; |
|
||||||
|
|
||||||
currentNote = -1; |
|
||||||
|
|
||||||
for (uint8_t note = 0; note < MAX_ACTIVE_NOTES; ++note) |
|
||||||
delete voices[note].dx7_note; |
|
||||||
|
|
||||||
delete(engineMsfa); |
|
||||||
delete(engineOpl); |
|
||||||
delete(engineMkI); |
|
||||||
|
|
||||||
TRACE("Bye"); |
|
||||||
TRACE("--------------------------------------------------------------------------------"); |
|
||||||
} |
|
||||||
|
|
||||||
void Dexed::activate(void) |
|
||||||
{ |
|
||||||
TRACE("Hi"); |
|
||||||
|
|
||||||
Plugin::activate(); |
|
||||||
panic(); |
|
||||||
controllers.values_[kControllerPitchRange] = data[155]; |
|
||||||
controllers.values_[kControllerPitchStep] = data[156]; |
|
||||||
|
|
||||||
TRACE("Bye"); |
|
||||||
} |
|
||||||
|
|
||||||
void Dexed::deactivate(void) |
|
||||||
{ |
|
||||||
TRACE("Hi"); |
|
||||||
|
|
||||||
Plugin::deactivate(); |
|
||||||
|
|
||||||
TRACE("Bye"); |
|
||||||
} |
|
||||||
|
|
||||||
void Dexed::set_params(void) |
|
||||||
{ |
|
||||||
//TRACE("Hi"); |
|
||||||
|
|
||||||
_param_change_counter=0; |
|
||||||
|
|
||||||
bool polymono=bool(*p(p_polymono)); |
|
||||||
uint8_t engine=uint8_t(*p(p_engine)); |
|
||||||
float f_gain=*p(p_output); |
|
||||||
float f_cutoff=*p(p_cutoff); |
|
||||||
float f_reso=*p(p_resonance); |
|
||||||
|
|
||||||
// Dexed-Unisono |
|
||||||
if(isMonoMode()!=polymono) |
|
||||||
setMonoMode(polymono); |
|
||||||
|
|
||||||
// Dexed-Engine |
|
||||||
if(controllers.core==NULL || getEngineType()!=engine) |
|
||||||
{ |
|
||||||
setEngineType(engine); |
|
||||||
refreshVoice=true; |
|
||||||
} |
|
||||||
|
|
||||||
// Dexed-Filter |
|
||||||
if(fx.uiCutoff!=f_cutoff) |
|
||||||
{ |
|
||||||
fx.uiCutoff=f_cutoff; |
|
||||||
refreshVoice=true; |
|
||||||
} |
|
||||||
if(fx.uiReso!=f_reso) |
|
||||||
{ |
|
||||||
fx.uiReso=f_reso; |
|
||||||
refreshVoice=true; |
|
||||||
} |
|
||||||
if(fx.uiGain!=f_gain) |
|
||||||
{ |
|
||||||
fx.uiGain=f_gain; |
|
||||||
refreshVoice=true; |
|
||||||
} |
|
||||||
|
|
||||||
// OP6 |
|
||||||
onParam(0,*p(p_op6_eg_rate_1)); |
|
||||||
onParam(1,*p(p_op6_eg_rate_2)); |
|
||||||
onParam(2,*p(p_op6_eg_rate_3)); |
|
||||||
onParam(3,*p(p_op6_eg_rate_4)); |
|
||||||
onParam(4,*p(p_op6_eg_level_1)); |
|
||||||
onParam(5,*p(p_op6_eg_level_2)); |
|
||||||
onParam(6,*p(p_op6_eg_level_3)); |
|
||||||
onParam(7,*p(p_op6_eg_level_4)); |
|
||||||
onParam(8,*p(p_op6_kbd_lev_scl_brk_pt)); |
|
||||||
onParam(9,*p(p_op6_kbd_lev_scl_lft_depth)); |
|
||||||
onParam(10,*p(p_op6_kbd_lev_scl_rht_depth)); |
|
||||||
onParam(11,*p(p_op6_kbd_lev_scl_lft_curve)); |
|
||||||
onParam(12,*p(p_op6_kbd_lev_scl_rht_curve)); |
|
||||||
onParam(13,*p(p_op6_kbd_rate_scaling)); |
|
||||||
onParam(14,*p(p_op6_amp_mod_sensitivity)); |
|
||||||
onParam(15,*p(p_op6_key_vel_sensitivity)); |
|
||||||
onParam(16,*p(p_op6_operator_output_level)); |
|
||||||
onParam(17,*p(p_op6_osc_mode)); |
|
||||||
onParam(18,*p(p_op6_osc_freq_coarse)); |
|
||||||
onParam(19,*p(p_op6_osc_freq_fine)); |
|
||||||
onParam(20,*p(p_op6_osc_detune)+7); |
|
||||||
// OP5 |
|
||||||
onParam(21,*p(p_op5_eg_rate_1)); |
|
||||||
onParam(22,*p(p_op5_eg_rate_2)); |
|
||||||
onParam(23,*p(p_op5_eg_rate_3)); |
|
||||||
onParam(24,*p(p_op5_eg_rate_4)); |
|
||||||
onParam(25,*p(p_op5_eg_level_1)); |
|
||||||
onParam(26,*p(p_op5_eg_level_2)); |
|
||||||
onParam(27,*p(p_op5_eg_level_3)); |
|
||||||
onParam(28,*p(p_op5_eg_level_4)); |
|
||||||
onParam(29,*p(p_op5_kbd_lev_scl_brk_pt)); |
|
||||||
onParam(30,*p(p_op5_kbd_lev_scl_lft_depth)); |
|
||||||
onParam(31,*p(p_op5_kbd_lev_scl_rht_depth)); |
|
||||||
onParam(32,*p(p_op5_kbd_lev_scl_lft_curve)); |
|
||||||
onParam(33,*p(p_op5_kbd_lev_scl_rht_curve)); |
|
||||||
onParam(34,*p(p_op5_kbd_rate_scaling)); |
|
||||||
onParam(35,*p(p_op5_amp_mod_sensitivity)); |
|
||||||
onParam(36,*p(p_op5_key_vel_sensitivity)); |
|
||||||
onParam(37,*p(p_op5_operator_output_level)); |
|
||||||
onParam(38,*p(p_op5_osc_mode)); |
|
||||||
onParam(39,*p(p_op5_osc_freq_coarse)); |
|
||||||
onParam(40,*p(p_op5_osc_freq_fine)); |
|
||||||
onParam(41,*p(p_op5_osc_detune)+7); |
|
||||||
// OP4 |
|
||||||
onParam(42,*p(p_op4_eg_rate_1)); |
|
||||||
onParam(43,*p(p_op4_eg_rate_2)); |
|
||||||
onParam(44,*p(p_op4_eg_rate_3)); |
|
||||||
onParam(45,*p(p_op4_eg_rate_4)); |
|
||||||
onParam(46,*p(p_op4_eg_level_1)); |
|
||||||
onParam(47,*p(p_op4_eg_level_2)); |
|
||||||
onParam(48,*p(p_op4_eg_level_3)); |
|
||||||
onParam(49,*p(p_op4_eg_level_4)); |
|
||||||
onParam(50,*p(p_op4_kbd_lev_scl_brk_pt)); |
|
||||||
onParam(51,*p(p_op4_kbd_lev_scl_lft_depth)); |
|
||||||
onParam(52,*p(p_op4_kbd_lev_scl_rht_depth)); |
|
||||||
onParam(53,*p(p_op4_kbd_lev_scl_lft_curve)); |
|
||||||
onParam(54,*p(p_op4_kbd_lev_scl_rht_curve)); |
|
||||||
onParam(55,*p(p_op4_kbd_rate_scaling)); |
|
||||||
onParam(56,*p(p_op4_amp_mod_sensitivity)); |
|
||||||
onParam(57,*p(p_op4_key_vel_sensitivity)); |
|
||||||
onParam(58,*p(p_op4_operator_output_level)); |
|
||||||
onParam(59,*p(p_op4_osc_mode)); |
|
||||||
onParam(60,*p(p_op4_osc_freq_coarse)); |
|
||||||
onParam(61,*p(p_op4_osc_freq_fine)); |
|
||||||
onParam(62,*p(p_op4_osc_detune)+7); |
|
||||||
// OP3 |
|
||||||
onParam(63,*p(p_op3_eg_rate_1)); |
|
||||||
onParam(64,*p(p_op3_eg_rate_2)); |
|
||||||
onParam(65,*p(p_op3_eg_rate_3)); |
|
||||||
onParam(66,*p(p_op3_eg_rate_4)); |
|
||||||
onParam(67,*p(p_op3_eg_level_1)); |
|
||||||
onParam(68,*p(p_op3_eg_level_2)); |
|
||||||
onParam(69,*p(p_op3_eg_level_3)); |
|
||||||
onParam(70,*p(p_op3_eg_level_4)); |
|
||||||
onParam(71,*p(p_op3_kbd_lev_scl_brk_pt)); |
|
||||||
onParam(72,*p(p_op3_kbd_lev_scl_lft_depth)); |
|
||||||
onParam(73,*p(p_op3_kbd_lev_scl_rht_depth)); |
|
||||||
onParam(74,*p(p_op3_kbd_lev_scl_lft_curve)); |
|
||||||
onParam(75,*p(p_op3_kbd_lev_scl_rht_curve)); |
|
||||||
onParam(76,*p(p_op3_kbd_rate_scaling)); |
|
||||||
onParam(77,*p(p_op3_amp_mod_sensitivity)); |
|
||||||
onParam(78,*p(p_op3_key_vel_sensitivity)); |
|
||||||
onParam(79,*p(p_op3_operator_output_level)); |
|
||||||
onParam(80,*p(p_op3_osc_mode)); |
|
||||||
onParam(81,*p(p_op3_osc_freq_coarse)); |
|
||||||
onParam(82,*p(p_op3_osc_freq_fine)); |
|
||||||
onParam(83,*p(p_op3_osc_detune)+7); |
|
||||||
// OP2 |
|
||||||
onParam(84,*p(p_op2_eg_rate_1)); |
|
||||||
onParam(85,*p(p_op2_eg_rate_2)); |
|
||||||
onParam(86,*p(p_op2_eg_rate_3)); |
|
||||||
onParam(87,*p(p_op2_eg_rate_4)); |
|
||||||
onParam(88,*p(p_op2_eg_level_1)); |
|
||||||
onParam(89,*p(p_op2_eg_level_2)); |
|
||||||
onParam(90,*p(p_op2_eg_level_3)); |
|
||||||
onParam(91,*p(p_op2_eg_level_4)); |
|
||||||
onParam(92,*p(p_op2_kbd_lev_scl_brk_pt)); |
|
||||||
onParam(93,*p(p_op2_kbd_lev_scl_lft_depth)); |
|
||||||
onParam(94,*p(p_op2_kbd_lev_scl_rht_depth)); |
|
||||||
onParam(95,*p(p_op2_kbd_lev_scl_lft_curve)); |
|
||||||
onParam(96,*p(p_op2_kbd_lev_scl_rht_curve)); |
|
||||||
onParam(97,*p(p_op2_kbd_rate_scaling)); |
|
||||||
onParam(98,*p(p_op2_amp_mod_sensitivity)); |
|
||||||
onParam(99,*p(p_op2_key_vel_sensitivity)); |
|
||||||
onParam(100,*p(p_op2_operator_output_level)); |
|
||||||
onParam(101,*p(p_op2_osc_mode)); |
|
||||||
onParam(102,*p(p_op2_osc_freq_coarse)); |
|
||||||
onParam(103,*p(p_op2_osc_freq_fine)); |
|
||||||
onParam(104,*p(p_op2_osc_detune)+7); |
|
||||||
// OP1 |
|
||||||
onParam(105,*p(p_op1_eg_rate_1)); |
|
||||||
onParam(106,*p(p_op1_eg_rate_2)); |
|
||||||
onParam(107,*p(p_op1_eg_rate_3)); |
|
||||||
onParam(108,*p(p_op1_eg_rate_4)); |
|
||||||
onParam(109,*p(p_op1_eg_level_1)); |
|
||||||
onParam(110,*p(p_op1_eg_level_2)); |
|
||||||
onParam(111,*p(p_op1_eg_level_3)); |
|
||||||
onParam(112,*p(p_op1_eg_level_4)); |
|
||||||
onParam(113,*p(p_op1_kbd_lev_scl_brk_pt)); |
|
||||||
onParam(114,*p(p_op1_kbd_lev_scl_lft_depth)); |
|
||||||
onParam(115,*p(p_op1_kbd_lev_scl_rht_depth)); |
|
||||||
onParam(116,*p(p_op1_kbd_lev_scl_lft_curve)); |
|
||||||
onParam(117,*p(p_op1_kbd_lev_scl_rht_curve)); |
|
||||||
onParam(118,*p(p_op1_kbd_rate_scaling)); |
|
||||||
onParam(119,*p(p_op1_amp_mod_sensitivity)); |
|
||||||
onParam(120,*p(p_op1_key_vel_sensitivity)); |
|
||||||
onParam(121,*p(p_op1_operator_output_level)); |
|
||||||
onParam(122,*p(p_op1_osc_mode)); |
|
||||||
onParam(123,*p(p_op1_osc_freq_coarse)); |
|
||||||
onParam(124,*p(p_op1_osc_freq_fine)); |
|
||||||
onParam(125,*p(p_op1_osc_detune)+7); |
|
||||||
// Global for all OPs |
|
||||||
onParam(126,*p(p_pitch_eg_rate_1)); |
|
||||||
onParam(127,*p(p_pitch_eg_rate_2)); |
|
||||||
onParam(128,*p(p_pitch_eg_rate_3)); |
|
||||||
onParam(129,*p(p_pitch_eg_rate_4)); |
|
||||||
onParam(130,*p(p_pitch_eg_level_1)); |
|
||||||
onParam(131,*p(p_pitch_eg_level_2)); |
|
||||||
onParam(132,*p(p_pitch_eg_level_3)); |
|
||||||
onParam(133,*p(p_pitch_eg_level_4)); |
|
||||||
onParam(134,*p(p_algorithm_num)-1); |
|
||||||
onParam(135,*p(p_feedback)); |
|
||||||
onParam(136,*p(p_oscillator_sync)); |
|
||||||
onParam(137,*p(p_lfo_speed)); |
|
||||||
onParam(138,*p(p_lfo_delay)); |
|
||||||
onParam(139,*p(p_lfo_pitch_mod_depth)); |
|
||||||
onParam(140,*p(p_lfo_amp_mod_depth)); |
|
||||||
onParam(141,*p(p_lfo_sync)); |
|
||||||
onParam(142,*p(p_lfo_waveform)); |
|
||||||
onParam(143,*p(p_pitch_mod_sensitivity)); |
|
||||||
onParam(144,*p(p_transpose)); |
|
||||||
// 10 bytes (145-154) are the name of the patch |
|
||||||
// Controllers (added at the end of the data[]) |
|
||||||
onParam(155,*p(p_pitch_bend_range)); |
|
||||||
onParam(156,*p(p_pitch_bend_step)); |
|
||||||
onParam(157,*p(p_mod_wheel_range)); |
|
||||||
onParam(158,*p(p_mod_wheel_assign)); |
|
||||||
onParam(159,*p(p_foot_ctrl_range)); |
|
||||||
onParam(160,*p(p_foot_ctrl_assign)); |
|
||||||
onParam(161,*p(p_breath_ctrl_range)); |
|
||||||
onParam(162,*p(p_breath_ctrl_assign)); |
|
||||||
onParam(163,*p(p_aftertouch_range)); |
|
||||||
onParam(164,*p(p_aftertouch_assign)); |
|
||||||
onParam(165,*p(p_master_tune)); |
|
||||||
onParam(166,*p(p_op1_enable)); |
|
||||||
onParam(167,*p(p_op2_enable)); |
|
||||||
onParam(168,*p(p_op3_enable)); |
|
||||||
onParam(169,*p(p_op4_enable)); |
|
||||||
onParam(170,*p(p_op5_enable)); |
|
||||||
onParam(171,*p(p_op6_enable)); |
|
||||||
onParam(172,*p(p_number_of_voices)); |
|
||||||
|
|
||||||
if(_param_change_counter>PARAM_CHANGE_LEVEL) |
|
||||||
{ |
|
||||||
panic(); |
|
||||||
controllers.refresh(); |
|
||||||
} |
|
||||||
|
|
||||||
//TRACE("Bye"); |
|
||||||
} |
|
||||||
|
|
||||||
// override the run() method |
|
||||||
void Dexed::run (uint32_t sample_count) |
|
||||||
{ |
|
||||||
const LV2_Atom_Sequence* seq = p<LV2_Atom_Sequence> (p_midi_in); |
|
||||||
float* output = p(p_audio_out); |
|
||||||
uint32_t last_frame = 0, num_this_time = 0; |
|
||||||
bool drop_next_events=false; |
|
||||||
|
|
||||||
Plugin::run(sample_count); |
|
||||||
|
|
||||||
if(++_k_rate_counter%16) |
|
||||||
set_params(); // pre_process: copy actual voice params |
|
||||||
|
|
||||||
for (LV2_Atom_Event* ev = lv2_atom_sequence_begin (&seq->body); |
|
||||||
!lv2_atom_sequence_is_end(&seq->body, seq->atom.size, ev); |
|
||||||
ev = lv2_atom_sequence_next (ev)) |
|
||||||
{ |
|
||||||
num_this_time = ev->time.frames - last_frame; |
|
||||||
|
|
||||||
// If it's midi, send it to the engine |
|
||||||
if (ev->body.type == m_midi_type) |
|
||||||
{ |
|
||||||
drop_next_events|=ProcessMidiMessage((uint8_t*) LV2_ATOM_BODY (&ev->body),ev->body.size); |
|
||||||
if(drop_next_events==true) |
|
||||||
continue; |
|
||||||
} |
|
||||||
|
|
||||||
// render audio from the last frame until the timestamp of this event |
|
||||||
GetSamples (num_this_time, outbuf_); |
|
||||||
|
|
||||||
// i is the index of the engine's buf, which always starts at 0 (i think) |
|
||||||
// j is the index of the plugin's float output buffer which will be the timestamp |
|
||||||
// of the last processed atom event. |
|
||||||
for (uint32_t i = 0, j = last_frame; i < num_this_time; ++i, ++j) |
|
||||||
output[j]=outbuf_[i]; |
|
||||||
|
|
||||||
last_frame = ev->time.frames; |
|
||||||
} |
|
||||||
|
|
||||||
// render remaining samples if any left |
|
||||||
if (last_frame < sample_count) |
|
||||||
{ |
|
||||||
// do the same thing as above except from last frame until the end of |
|
||||||
// the processing cycles last sample. at this point, all events have |
|
||||||
// already been handled. |
|
||||||
|
|
||||||
num_this_time = sample_count - last_frame; |
|
||||||
GetSamples (num_this_time, outbuf_); |
|
||||||
for (uint32_t i = 0, j = last_frame; i < num_this_time; ++i, ++j) |
|
||||||
output[j] = outbuf_[i]; |
|
||||||
} |
|
||||||
|
|
||||||
fx.process(output, sample_count); |
|
||||||
} |
|
||||||
|
|
||||||
void Dexed::GetSamples(uint32_t n_samples, float* buffer) |
|
||||||
{ |
|
||||||
uint32_t i; |
|
||||||
|
|
||||||
if(refreshVoice) { |
|
||||||
for(i=0;i < max_notes;i++) { |
|
||||||
if ( voices[i].live ) |
|
||||||
voices[i].dx7_note->update(data, voices[i].midi_note, voices[i].velocity); |
|
||||||
} |
|
||||||
lfo.reset(data+137); |
|
||||||
refreshVoice = false; |
|
||||||
} |
|
||||||
|
|
||||||
// flush first events |
|
||||||
for (i=0; i < n_samples && i < extra_buf_size_; i++) { |
|
||||||
buffer[i] = extra_buf_[i]; |
|
||||||
} |
|
||||||
|
|
||||||
// remaining buffer is still to be processed |
|
||||||
if (extra_buf_size_ > n_samples) { |
|
||||||
for (uint32_t j = 0; j < extra_buf_size_ - n_samples; j++) { |
|
||||||
extra_buf_[j] = extra_buf_[j + n_samples]; |
|
||||||
} |
|
||||||
extra_buf_size_ -= n_samples; |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
for (; i < n_samples; i += N) { |
|
||||||
AlignedBuf<int32_t, N> audiobuf; |
|
||||||
float sumbuf[N]; |
|
||||||
|
|
||||||
for (uint32_t j = 0; j < N; ++j) { |
|
||||||
audiobuf.get()[j] = 0; |
|
||||||
sumbuf[j] = 0.0; |
|
||||||
} |
|
||||||
|
|
||||||
int32_t lfovalue = lfo.getsample(); |
|
||||||
int32_t lfodelay = lfo.getdelay(); |
|
||||||
|
|
||||||
for (uint8_t note = 0; note < max_notes; ++note) { |
|
||||||
if (voices[note].live) { |
|
||||||
voices[note].dx7_note->compute(audiobuf.get(), lfovalue, lfodelay, &controllers); |
|
||||||
for (uint32_t j=0; j < N; ++j) { |
|
||||||
int32_t val = audiobuf.get()[j]; |
|
||||||
val = val >> 4; |
|
||||||
int32_t clip_val = val < -(1 << 24) ? 0x8000 : val >= (1 << 24) ? 0x7fff : val >> 9; |
|
||||||
float f = static_cast<float>(clip_val>>1)/0x8000; |
|
||||||
if(f>1) f=1; |
|
||||||
if(f<-1) f=-1; |
|
||||||
sumbuf[j]+=f; |
|
||||||
audiobuf.get()[j]=0; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
uint32_t jmax = n_samples - i; |
|
||||||
for (uint32_t j = 0; j < N; ++j) { |
|
||||||
if (j < jmax) |
|
||||||
buffer[i + j] = sumbuf[j]; |
|
||||||
else |
|
||||||
extra_buf_[j - jmax] = sumbuf[j]; |
|
||||||
} |
|
||||||
} |
|
||||||
extra_buf_size_ = i - n_samples; |
|
||||||
} |
|
||||||
|
|
||||||
if(++_k_rate_counter%32 && !monoMode) |
|
||||||
{ |
|
||||||
uint8_t op_carrier=controllers.core->get_carrier_operators(data[134]); // look for carriers |
|
||||||
|
|
||||||
for(i=0;i < max_notes;i++) |
|
||||||
{ |
|
||||||
if(voices[i].live==true) |
|
||||||
{ |
|
||||||
uint8_t op_amp=0; |
|
||||||
uint8_t op_carrier_num=0; |
|
||||||
|
|
||||||
voices[i].dx7_note->peekVoiceStatus(voiceStatus); |
|
||||||
|
|
||||||
for(uint8_t op=0;op<6;op++) |
|
||||||
{ |
|
||||||
uint8_t op_bit=static_cast<uint8_t>(pow(2,op)); |
|
||||||
|
|
||||||
if((op_carrier&op_bit)>0) |
|
||||||
{ |
|
||||||
// this voice is a carrier! |
|
||||||
op_carrier_num++; |
|
||||||
|
|
||||||
//TRACE("Voice[%2d] OP [%d] amp=%ld,amp_step=%d,pitch_step=%d",i,op,voiceStatus.amp[op],voiceStatus.ampStep[op],voiceStatus.pitchStep); |
|
||||||
|
|
||||||
if(voiceStatus.amp[op]<=1069 && voiceStatus.ampStep[op]==4) // this voice produces no audio output |
|
||||||
op_amp++; |
|
||||||
} |
|
||||||
} |
|
||||||
if(op_amp==op_carrier_num) |
|
||||||
{ |
|
||||||
// all carrier-operators are silent -> disable the voice |
|
||||||
voices[i].live=false; |
|
||||||
voices[i].sustained=false; |
|
||||||
voices[i].keydown=false; |
|
||||||
TRACE("Shutted down Voice[%2d]",i); |
|
||||||
} |
|
||||||
} |
|
||||||
// TRACE("Voice[%2d] live=%d keydown=%d",i,voices[i].live,voices[i].keydown); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
bool Dexed::ProcessMidiMessage(const uint8_t *buf, uint32_t buf_size) { |
|
||||||
TRACE("Hi"); |
|
||||||
|
|
||||||
uint8_t cmd = buf[0]; |
|
||||||
|
|
||||||
switch(cmd & 0xf0) { |
|
||||||
case 0x80 : |
|
||||||
TRACE("MIDI keyup event: %d",buf[1]); |
|
||||||
keyup(buf[1]); |
|
||||||
return(false); |
|
||||||
break; |
|
||||||
case 0x90 : |
|
||||||
TRACE("MIDI keydown event: %d %d",buf[1],buf[2]); |
|
||||||
keydown(buf[1], buf[2]); |
|
||||||
return(false); |
|
||||||
break; |
|
||||||
case 0xb0 : { |
|
||||||
uint8_t ctrl = buf[1]; |
|
||||||
uint8_t value = buf[2]; |
|
||||||
|
|
||||||
switch(ctrl) { |
|
||||||
case 1: |
|
||||||
TRACE("MIDI modwheel event: %d %d",ctrl,value); |
|
||||||
controllers.modwheel_cc = value; |
|
||||||
controllers.refresh(); |
|
||||||
break; |
|
||||||
case 2: |
|
||||||
TRACE("MIDI breath event: %d %d",ctrl,value); |
|
||||||
controllers.breath_cc = value; |
|
||||||
controllers.refresh(); |
|
||||||
break; |
|
||||||
case 4: |
|
||||||
TRACE("MIDI footsw event: %d %d",ctrl,value); |
|
||||||
controllers.foot_cc = value; |
|
||||||
controllers.refresh(); |
|
||||||
break; |
|
||||||
case 64: |
|
||||||
TRACE("MIDI sustain event: %d %d",ctrl,value); |
|
||||||
sustain = value > 63; |
|
||||||
if (!sustain) { |
|
||||||
for (uint8_t note = 0; note < max_notes; note++) { |
|
||||||
if (voices[note].sustained && !voices[note].keydown) { |
|
||||||
voices[note].dx7_note->keyup(); |
|
||||||
voices[note].sustained = false; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
break; |
|
||||||
case 120: |
|
||||||
TRACE("MIDI all-sound-off: %d %d",ctrl,value); |
|
||||||
panic(); |
|
||||||
return(true); |
|
||||||
break; |
|
||||||
case 123: |
|
||||||
TRACE("MIDI all-notes-off: %d %d",ctrl,value); |
|
||||||
notes_off(); |
|
||||||
return(true); |
|
||||||
break; |
|
||||||
} |
|
||||||
break; |
|
||||||
} |
|
||||||
|
|
||||||
// case 0xc0 : |
|
||||||
// setCurrentProgram(buf[1]); |
|
||||||
// break; |
|
||||||
|
|
||||||
// channel aftertouch |
|
||||||
case 0xd0 : |
|
||||||
TRACE("MIDI aftertouch 0xd0 event: %d %d",buf[1]); |
|
||||||
controllers.aftertouch_cc = buf[1]; |
|
||||||
controllers.refresh(); |
|
||||||
break; |
|
||||||
// pitchbend |
|
||||||
case 0xe0 : |
|
||||||
TRACE("MIDI pitchbend 0xe0 event: %d %d",buf[1],buf[2]); |
|
||||||
controllers.values_[kControllerPitch] = buf[1] | (buf[2] << 7); |
|
||||||
break; |
|
||||||
|
|
||||||
default: |
|
||||||
TRACE("MIDI event unknown: cmd=%d, val1=%d, val2=%d",buf[0],buf[1],buf[2]); |
|
||||||
break; |
|
||||||
} |
|
||||||
|
|
||||||
TRACE("Bye"); |
|
||||||
return(false); |
|
||||||
} |
|
||||||
|
|
||||||
void Dexed::keydown(uint8_t pitch, uint8_t velo) { |
|
||||||
TRACE("Hi"); |
|
||||||
TRACE("pitch=%d, velo=%d\n",pitch,velo); |
|
||||||
if ( velo == 0 ) { |
|
||||||
keyup(pitch); |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
pitch += data[144] - 24; |
|
||||||
|
|
||||||
uint8_t note = currentNote; |
|
||||||
uint8_t keydown_counter=0; |
|
||||||
|
|
||||||
for (uint8_t i=0; i<max_notes; i++) { |
|
||||||
if (!voices[note].keydown) { |
|
||||||
currentNote = (note + 1) % max_notes; |
|
||||||
voices[note].midi_note = pitch; |
|
||||||
voices[note].velocity = velo; |
|
||||||
voices[note].sustained = sustain; |
|
||||||
voices[note].keydown = true; |
|
||||||
voices[note].dx7_note->init(data, pitch, velo); |
|
||||||
if ( data[136] ) |
|
||||||
voices[note].dx7_note->oscSync(); |
|
||||||
break; |
|
||||||
} |
|
||||||
else |
|
||||||
keydown_counter++; |
|
||||||
|
|
||||||
note = (note + 1) % max_notes; |
|
||||||
} |
|
||||||
|
|
||||||
if(keydown_counter==0) |
|
||||||
lfo.keydown(); |
|
||||||
if ( monoMode ) { |
|
||||||
for(uint8_t i=0; i<max_notes; i++) { |
|
||||||
if ( voices[i].live ) { |
|
||||||
// all keys are up, only transfer signal |
|
||||||
if ( ! voices[i].keydown ) { |
|
||||||
voices[i].live = false; |
|
||||||
voices[note].dx7_note->transferSignal(*voices[i].dx7_note); |
|
||||||
break; |
|
||||||
} |
|
||||||
if ( voices[i].midi_note < pitch ) { |
|
||||||
voices[i].live = false; |
|
||||||
voices[note].dx7_note->transferState(*voices[i].dx7_note); |
|
||||||
break; |
|
||||||
} |
|
||||||
return; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
voices[note].live = true; |
|
||||||
TRACE("Bye"); |
|
||||||
} |
|
||||||
|
|
||||||
void Dexed::keyup(uint8_t pitch) { |
|
||||||
TRACE("Hi"); |
|
||||||
TRACE("pitch=%d\n",pitch); |
|
||||||
|
|
||||||
pitch += data[144] - 24; |
|
||||||
|
|
||||||
uint8_t note; |
|
||||||
for (note=0; note<max_notes; ++note) { |
|
||||||
if ( voices[note].midi_note == pitch && voices[note].keydown ) { |
|
||||||
voices[note].keydown = false; |
|
||||||
break; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// note not found ? |
|
||||||
if ( note >= max_notes ) { |
|
||||||
TRACE("note-off not found???"); |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
if ( monoMode ) { |
|
||||||
int8_t highNote = -1; |
|
||||||
int8_t target = 0; |
|
||||||
for (int8_t i=0; i<max_notes;i++) { |
|
||||||
if ( voices[i].keydown && voices[i].midi_note > highNote ) { |
|
||||||
target = i; |
|
||||||
highNote = voices[i].midi_note; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
if ( highNote != -1 && voices[note].live ) { |
|
||||||
voices[note].live = false; |
|
||||||
voices[target].live = true; |
|
||||||
voices[target].dx7_note->transferState(*voices[note].dx7_note); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
if ( sustain ) { |
|
||||||
voices[note].sustained = true; |
|
||||||
} else { |
|
||||||
voices[note].dx7_note->keyup(); |
|
||||||
} |
|
||||||
TRACE("Bye"); |
|
||||||
} |
|
||||||
|
|
||||||
void Dexed::onParam(uint8_t param_num,float param_val) |
|
||||||
{ |
|
||||||
int32_t tune; |
|
||||||
|
|
||||||
if(param_val!=data_float[param_num]) |
|
||||||
{ |
|
||||||
TRACE("Parameter %d change from %f to %f",param_num, data_float[param_num], param_val); |
|
||||||
#ifdef DEBUG |
|
||||||
uint8_t tmp=data[param_num]; |
|
||||||
#endif |
|
||||||
|
|
||||||
_param_change_counter++; |
|
||||||
|
|
||||||
if(param_num==144 || param_num==134 || param_num==172) |
|
||||||
panic(); |
|
||||||
|
|
||||||
refreshVoice=true; |
|
||||||
data[param_num]=static_cast<uint8_t>(param_val); |
|
||||||
data_float[param_num]=param_val; |
|
||||||
|
|
||||||
switch(param_num) |
|
||||||
{ |
|
||||||
case 155: |
|
||||||
controllers.values_[kControllerPitchRange]=data[param_num]; |
|
||||||
break; |
|
||||||
case 156: |
|
||||||
controllers.values_[kControllerPitchStep]=data[param_num]; |
|
||||||
break; |
|
||||||
case 157: |
|
||||||
controllers.wheel.setRange(data[param_num]); |
|
||||||
controllers.wheel.setTarget(data[param_num+1]); |
|
||||||
controllers.refresh(); |
|
||||||
break; |
|
||||||
case 158: |
|
||||||
controllers.wheel.setRange(data[param_num-1]); |
|
||||||
controllers.wheel.setTarget(data[param_num]); |
|
||||||
controllers.refresh(); |
|
||||||
break; |
|
||||||
case 159: |
|
||||||
controllers.foot.setRange(data[param_num]); |
|
||||||
controllers.foot.setTarget(data[param_num+1]); |
|
||||||
controllers.refresh(); |
|
||||||
break; |
|
||||||
case 160: |
|
||||||
controllers.foot.setRange(data[param_num-1]); |
|
||||||
controllers.foot.setTarget(data[param_num]); |
|
||||||
controllers.refresh(); |
|
||||||
break; |
|
||||||
case 161: |
|
||||||
controllers.breath.setRange(data[param_num]); |
|
||||||
controllers.breath.setTarget(data[param_num+1]); |
|
||||||
controllers.refresh(); |
|
||||||
break; |
|
||||||
case 162: |
|
||||||
controllers.breath.setRange(data[param_num-1]); |
|
||||||
controllers.breath.setTarget(data[param_num]); |
|
||||||
controllers.refresh(); |
|
||||||
break; |
|
||||||
case 163: |
|
||||||
controllers.at.setRange(data[param_num]); |
|
||||||
controllers.at.setTarget(data[param_num+1]); |
|
||||||
controllers.refresh(); |
|
||||||
break; |
|
||||||
case 164: |
|
||||||
controllers.at.setRange(data[param_num-1]); |
|
||||||
controllers.at.setTarget(data[param_num]); |
|
||||||
controllers.refresh(); |
|
||||||
break; |
|
||||||
case 165: |
|
||||||
tune=param_val*0x4000; |
|
||||||
controllers.masterTune=(tune<<11)*(1.0/12); |
|
||||||
break; |
|
||||||
case 166: |
|
||||||
case 167: |
|
||||||
case 168: |
|
||||||
case 169: |
|
||||||
case 170: |
|
||||||
case 171: |
|
||||||
controllers.opSwitch=(data[166]<<5)|(data[167]<<4)|(data[168]<<3)|(data[169]<<2)|(data[170]<<1)|data[171]; |
|
||||||
break; |
|
||||||
case 172: |
|
||||||
max_notes=data[param_num]; |
|
||||||
break; |
|
||||||
} |
|
||||||
|
|
||||||
TRACE("Done: Parameter %d changed from %d to %d",param_num, tmp, data[param_num]); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
uint8_t Dexed::getEngineType() { |
|
||||||
return engineType; |
|
||||||
} |
|
||||||
|
|
||||||
void Dexed::setEngineType(uint8_t tp) { |
|
||||||
TRACE("settings engine %d", tp); |
|
||||||
|
|
||||||
if(engineType==tp && controllers.core!=NULL) |
|
||||||
return; |
|
||||||
|
|
||||||
switch (tp) { |
|
||||||
case DEXED_ENGINE_MARKI: |
|
||||||
TRACE("DEXED_ENGINE_MARKI:%d",DEXED_ENGINE_MARKI); |
|
||||||
controllers.core = engineMkI; |
|
||||||
break; |
|
||||||
case DEXED_ENGINE_OPL: |
|
||||||
TRACE("DEXED_ENGINE_OPL:%d",DEXED_ENGINE_OPL); |
|
||||||
controllers.core = engineOpl; |
|
||||||
break; |
|
||||||
default: |
|
||||||
TRACE("DEXED_ENGINE_MODERN:%d",DEXED_ENGINE_MODERN); |
|
||||||
controllers.core = engineMsfa; |
|
||||||
tp=DEXED_ENGINE_MODERN; |
|
||||||
break; |
|
||||||
} |
|
||||||
engineType = tp; |
|
||||||
panic(); |
|
||||||
controllers.refresh(); |
|
||||||
} |
|
||||||
|
|
||||||
bool Dexed::isMonoMode(void) { |
|
||||||
return monoMode; |
|
||||||
} |
|
||||||
|
|
||||||
void Dexed::setMonoMode(bool mode) { |
|
||||||
if(monoMode==mode) |
|
||||||
return; |
|
||||||
|
|
||||||
monoMode = mode; |
|
||||||
} |
|
||||||
|
|
||||||
void Dexed::panic(void) { |
|
||||||
for(uint8_t i=0;i<MAX_ACTIVE_NOTES;i++) |
|
||||||
{ |
|
||||||
if(voices[i].live == true) { |
|
||||||
voices[i].keydown = false; |
|
||||||
voices[i].live = false; |
|
||||||
voices[i].sustained = false; |
|
||||||
if ( voices[i].dx7_note != NULL ) { |
|
||||||
voices[i].dx7_note->oscSync(); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
void Dexed::notes_off(void) { |
|
||||||
for(uint8_t i=0;i<MAX_ACTIVE_NOTES;i++) { |
|
||||||
if(voices[i].live==true&&voices[i].keydown==true) { |
|
||||||
voices[i].keydown=false; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
//============================================================================== |
|
||||||
|
|
||||||
DexedVoice::DexedVoice(double rate) : m_key(lvtk::INVALID_KEY), m_rate(rate) |
|
||||||
{ |
|
||||||
TRACE("Hi"); |
|
||||||
|
|
||||||
TRACE("Bye"); |
|
||||||
} |
|
||||||
|
|
||||||
DexedVoice::~DexedVoice() |
|
||||||
{ |
|
||||||
TRACE("Hi"); |
|
||||||
|
|
||||||
TRACE("Bye"); |
|
||||||
} |
|
||||||
|
|
||||||
void DexedVoice::on(unsigned char key, unsigned char velocity) |
|
||||||
{ |
|
||||||
TRACE("Hi"); |
|
||||||
|
|
||||||
m_key = key; |
|
||||||
|
|
||||||
TRACE("Bye"); |
|
||||||
} |
|
||||||
|
|
||||||
void DexedVoice::off(unsigned char velocity) |
|
||||||
{ |
|
||||||
TRACE("Hi"); |
|
||||||
|
|
||||||
m_key = lvtk::INVALID_KEY; |
|
||||||
|
|
||||||
TRACE("Bye"); |
|
||||||
} |
|
||||||
|
|
||||||
unsigned char DexedVoice::get_key(void) const |
|
||||||
{ |
|
||||||
TRACE("Hi"); |
|
||||||
|
|
||||||
return m_key; |
|
||||||
|
|
||||||
TRACE("Bye"); |
|
||||||
} |
|
||||||
|
|
||||||
static int _ = Dexed::register_class(p_uri); |
|
@ -1,369 +0,0 @@ |
|||||||
#ifndef dexed_ttl_h |
|
||||||
#define dexed_ttl_h |
|
||||||
|
|
||||||
|
|
||||||
#ifndef PEG_STRUCT |
|
||||||
#define PEG_STRUCT |
|
||||||
typedef struct { |
|
||||||
float min; |
|
||||||
float max; |
|
||||||
float default_value; |
|
||||||
char toggled; |
|
||||||
char integer; |
|
||||||
char logarithmic; |
|
||||||
} peg_data_t; |
|
||||||
#endif |
|
||||||
|
|
||||||
/* <https://github.com/dcoredump/dexed.lv2> */ |
|
||||||
|
|
||||||
static const char p_uri[] = "https://github.com/dcoredump/dexed.lv2"; |
|
||||||
|
|
||||||
enum p_port_enum { |
|
||||||
p_midi_in, |
|
||||||
p_audio_out, |
|
||||||
p_cutoff, |
|
||||||
p_resonance, |
|
||||||
p_output, |
|
||||||
p_engine, |
|
||||||
p_number_of_voices, |
|
||||||
p_polymono, |
|
||||||
p_pitch_bend_range, |
|
||||||
p_pitch_bend_step, |
|
||||||
p_mod_wheel_range, |
|
||||||
p_mod_wheel_assign, |
|
||||||
p_foot_ctrl_range, |
|
||||||
p_foot_ctrl_assign, |
|
||||||
p_breath_ctrl_range, |
|
||||||
p_breath_ctrl_assign, |
|
||||||
p_aftertouch_range, |
|
||||||
p_aftertouch_assign, |
|
||||||
p_master_tune, |
|
||||||
p_algorithm_num, |
|
||||||
p_feedback, |
|
||||||
p_oscillator_sync, |
|
||||||
p_lfo_speed, |
|
||||||
p_lfo_delay, |
|
||||||
p_lfo_pitch_mod_depth, |
|
||||||
p_lfo_amp_mod_depth, |
|
||||||
p_lfo_sync, |
|
||||||
p_lfo_waveform, |
|
||||||
p_transpose, |
|
||||||
p_pitch_mod_sensitivity, |
|
||||||
p_pitch_eg_rate_1, |
|
||||||
p_pitch_eg_rate_2, |
|
||||||
p_pitch_eg_rate_3, |
|
||||||
p_pitch_eg_rate_4, |
|
||||||
p_pitch_eg_level_1, |
|
||||||
p_pitch_eg_level_2, |
|
||||||
p_pitch_eg_level_3, |
|
||||||
p_pitch_eg_level_4, |
|
||||||
p_op1_eg_rate_1, |
|
||||||
p_op1_eg_rate_2, |
|
||||||
p_op1_eg_rate_3, |
|
||||||
p_op1_eg_rate_4, |
|
||||||
p_op1_eg_level_1, |
|
||||||
p_op1_eg_level_2, |
|
||||||
p_op1_eg_level_3, |
|
||||||
p_op1_eg_level_4, |
|
||||||
p_op1_operator_output_level, |
|
||||||
p_op1_osc_mode, |
|
||||||
p_op1_osc_freq_coarse, |
|
||||||
p_op1_osc_freq_fine, |
|
||||||
p_op1_osc_detune, |
|
||||||
p_op1_kbd_lev_scl_brk_pt, |
|
||||||
p_op1_kbd_lev_scl_lft_depth, |
|
||||||
p_op1_kbd_lev_scl_rht_depth, |
|
||||||
p_op1_kbd_lev_scl_lft_curve, |
|
||||||
p_op1_kbd_lev_scl_rht_curve, |
|
||||||
p_op1_kbd_rate_scaling, |
|
||||||
p_op1_amp_mod_sensitivity, |
|
||||||
p_op1_key_vel_sensitivity, |
|
||||||
p_op2_eg_rate_1, |
|
||||||
p_op2_eg_rate_2, |
|
||||||
p_op2_eg_rate_3, |
|
||||||
p_op2_eg_rate_4, |
|
||||||
p_op2_eg_level_1, |
|
||||||
p_op2_eg_level_2, |
|
||||||
p_op2_eg_level_3, |
|
||||||
p_op2_eg_level_4, |
|
||||||
p_op2_operator_output_level, |
|
||||||
p_op2_osc_mode, |
|
||||||
p_op2_osc_freq_coarse, |
|
||||||
p_op2_osc_freq_fine, |
|
||||||
p_op2_osc_detune, |
|
||||||
p_op2_kbd_lev_scl_brk_pt, |
|
||||||
p_op2_kbd_lev_scl_lft_depth, |
|
||||||
p_op2_kbd_lev_scl_rht_depth, |
|
||||||
p_op2_kbd_lev_scl_lft_curve, |
|
||||||
p_op2_kbd_lev_scl_rht_curve, |
|
||||||
p_op2_kbd_rate_scaling, |
|
||||||
p_op2_amp_mod_sensitivity, |
|
||||||
p_op2_key_vel_sensitivity, |
|
||||||
p_op3_eg_rate_1, |
|
||||||
p_op3_eg_rate_2, |
|
||||||
p_op3_eg_rate_3, |
|
||||||
p_op3_eg_rate_4, |
|
||||||
p_op3_eg_level_1, |
|
||||||
p_op3_eg_level_2, |
|
||||||
p_op3_eg_level_3, |
|
||||||
p_op3_eg_level_4, |
|
||||||
p_op3_operator_output_level, |
|
||||||
p_op3_osc_mode, |
|
||||||
p_op3_osc_freq_coarse, |
|
||||||
p_op3_osc_freq_fine, |
|
||||||
p_op3_osc_detune, |
|
||||||
p_op3_kbd_lev_scl_brk_pt, |
|
||||||
p_op3_kbd_lev_scl_lft_depth, |
|
||||||
p_op3_kbd_lev_scl_rht_depth, |
|
||||||
p_op3_kbd_lev_scl_lft_curve, |
|
||||||
p_op3_kbd_lev_scl_rht_curve, |
|
||||||
p_op3_kbd_rate_scaling, |
|
||||||
p_op3_amp_mod_sensitivity, |
|
||||||
p_op3_key_vel_sensitivity, |
|
||||||
p_op4_eg_rate_1, |
|
||||||
p_op4_eg_rate_2, |
|
||||||
p_op4_eg_rate_3, |
|
||||||
p_op4_eg_rate_4, |
|
||||||
p_op4_eg_level_1, |
|
||||||
p_op4_eg_level_2, |
|
||||||
p_op4_eg_level_3, |
|
||||||
p_op4_eg_level_4, |
|
||||||
p_op4_operator_output_level, |
|
||||||
p_op4_osc_mode, |
|
||||||
p_op4_osc_freq_coarse, |
|
||||||
p_op4_osc_freq_fine, |
|
||||||
p_op4_osc_detune, |
|
||||||
p_op4_kbd_lev_scl_brk_pt, |
|
||||||
p_op4_kbd_lev_scl_lft_depth, |
|
||||||
p_op4_kbd_lev_scl_rht_depth, |
|
||||||
p_op4_kbd_lev_scl_lft_curve, |
|
||||||
p_op4_kbd_lev_scl_rht_curve, |
|
||||||
p_op4_kbd_rate_scaling, |
|
||||||
p_op4_amp_mod_sensitivity, |
|
||||||
p_op4_key_vel_sensitivity, |
|
||||||
p_op5_eg_rate_1, |
|
||||||
p_op5_eg_rate_2, |
|
||||||
p_op5_eg_rate_3, |
|
||||||
p_op5_eg_rate_4, |
|
||||||
p_op5_eg_level_1, |
|
||||||
p_op5_eg_level_2, |
|
||||||
p_op5_eg_level_3, |
|
||||||
p_op5_eg_level_4, |
|
||||||
p_op5_operator_output_level, |
|
||||||
p_op5_osc_mode, |
|
||||||
p_op5_osc_freq_coarse, |
|
||||||
p_op5_osc_freq_fine, |
|
||||||
p_op5_osc_detune, |
|
||||||
p_op5_kbd_lev_scl_brk_pt, |
|
||||||
p_op5_kbd_lev_scl_lft_depth, |
|
||||||
p_op5_kbd_lev_scl_rht_depth, |
|
||||||
p_op5_kbd_lev_scl_lft_curve, |
|
||||||
p_op5_kbd_lev_scl_rht_curve, |
|
||||||
p_op5_kbd_rate_scaling, |
|
||||||
p_op5_amp_mod_sensitivity, |
|
||||||
p_op5_key_vel_sensitivity, |
|
||||||
p_op6_eg_rate_1, |
|
||||||
p_op6_eg_rate_2, |
|
||||||
p_op6_eg_rate_3, |
|
||||||
p_op6_eg_rate_4, |
|
||||||
p_op6_eg_level_1, |
|
||||||
p_op6_eg_level_2, |
|
||||||
p_op6_eg_level_3, |
|
||||||
p_op6_eg_level_4, |
|
||||||
p_op6_operator_output_level, |
|
||||||
p_op6_osc_mode, |
|
||||||
p_op6_osc_freq_coarse, |
|
||||||
p_op6_osc_freq_fine, |
|
||||||
p_op6_osc_detune, |
|
||||||
p_op6_kbd_lev_scl_brk_pt, |
|
||||||
p_op6_kbd_lev_scl_lft_depth, |
|
||||||
p_op6_kbd_lev_scl_rht_depth, |
|
||||||
p_op6_kbd_lev_scl_lft_curve, |
|
||||||
p_op6_kbd_lev_scl_rht_curve, |
|
||||||
p_op6_kbd_rate_scaling, |
|
||||||
p_op6_amp_mod_sensitivity, |
|
||||||
p_op6_key_vel_sensitivity, |
|
||||||
p_op1_enable, |
|
||||||
p_op2_enable, |
|
||||||
p_op3_enable, |
|
||||||
p_op4_enable, |
|
||||||
p_op5_enable, |
|
||||||
p_op6_enable, |
|
||||||
p_n_ports |
|
||||||
}; |
|
||||||
|
|
||||||
static const peg_data_t p_ports[] = { |
|
||||||
{ -3.40282e+38, 3.40282e+38, -3.40282e+38, 0, 0, 0 }, |
|
||||||
{ -3.40282e+38, 3.40282e+38, -3.40282e+38, 0, 0, 0 }, |
|
||||||
{ 0, 1, 1, 0, 0, 0 }, |
|
||||||
{ 0, 1, 0, 0, 0, 0 }, |
|
||||||
{ 0, 2, 1, 0, 0, 0 }, |
|
||||||
{ 0, 2, 0, 0, 1, 0 }, |
|
||||||
{ 1, 32, 16, 0, 1, 0 }, |
|
||||||
{ 0, 1, 0, 1, 1, 0 }, |
|
||||||
{ 0, 12, 1, 0, 1, 0 }, |
|
||||||
{ 0, 12, 0, 0, 1, 0 }, |
|
||||||
{ 0, 99, 99, 0, 1, 0 }, |
|
||||||
{ 0, 7, 0, 0, 1, 0 }, |
|
||||||
{ 0, 99, 99, 0, 1, 0 }, |
|
||||||
{ 0, 7, 0, 0, 1, 0 }, |
|
||||||
{ 0, 99, 99, 0, 1, 0 }, |
|
||||||
{ 0, 7, 0, 0, 1, 0 }, |
|
||||||
{ 0, 99, 99, 0, 1, 0 }, |
|
||||||
{ 0, 7, 0, 0, 1, 0 }, |
|
||||||
{ -1, 1, 0, 0, 0, 0 }, |
|
||||||
{ 1, 32, 5, 0, 1, 0 }, |
|
||||||
{ 0, 7, 6, 0, 1, 0 }, |
|
||||||
{ 0, 1, 0, 1, 1, 0 }, |
|
||||||
{ 0, 99, 34, 0, 1, 0 }, |
|
||||||
{ 0, 99, 33, 0, 1, 0 }, |
|
||||||
{ 0, 99, 0, 0, 1, 0 }, |
|
||||||
{ 0, 99, 0, 0, 1, 0 }, |
|
||||||
{ 0, 1, 0, 1, 1, 0 }, |
|
||||||
{ 0, 5, 4, 0, 1, 0 }, |
|
||||||
{ 0, 48, 24, 0, 1, 0 }, |
|
||||||
{ 0, 7, 3, 0, 1, 0 }, |
|
||||||
{ 0, 99, 94, 0, 1, 0 }, |
|
||||||
{ 0, 99, 67, 0, 1, 0 }, |
|
||||||
{ 0, 99, 95, 0, 1, 0 }, |
|
||||||
{ 0, 99, 60, 0, 1, 0 }, |
|
||||||
{ 0, 99, 50, 0, 1, 0 }, |
|
||||||
{ 0, 99, 50, 0, 1, 0 }, |
|
||||||
{ 0, 99, 50, 0, 1, 0 }, |
|
||||||
{ 0, 99, 50, 0, 1, 0 }, |
|
||||||
{ 0, 99, 96, 0, 1, 0 }, |
|
||||||
{ 0, 99, 25, 0, 1, 0 }, |
|
||||||
{ 0, 99, 25, 0, 1, 0 }, |
|
||||||
{ 0, 99, 67, 0, 1, 0 }, |
|
||||||
{ 0, 99, 99, 0, 1, 0 }, |
|
||||||
{ 0, 99, 75, 0, 1, 0 }, |
|
||||||
{ 0, 99, 0, 0, 1, 0 }, |
|
||||||
{ 0, 99, 0, 0, 1, 0 }, |
|
||||||
{ 0, 99, 99, 0, 1, 0 }, |
|
||||||
{ 0, 1, 0, 0, 1, 0 }, |
|
||||||
{ 0, 31, 1, 0, 1, 0 }, |
|
||||||
{ 0, 99, 0, 0, 1, 0 }, |
|
||||||
{ -7, 7, 3, 0, 1, 0 }, |
|
||||||
{ 0, 99, 0, 0, 1, 0 }, |
|
||||||
{ 0, 99, 0, 0, 1, 0 }, |
|
||||||
{ 0, 99, 0, 0, 1, 0 }, |
|
||||||
{ 0, 3, 0, 0, 1, 0 }, |
|
||||||
{ 0, 3, 0, 0, 1, 0 }, |
|
||||||
{ 0, 7, 3, 0, 1, 0 }, |
|
||||||
{ 0, 3, 0, 0, 1, 0 }, |
|
||||||
{ 0, 7, 2, 0, 1, 0 }, |
|
||||||
{ 0, 99, 95, 0, 1, 0 }, |
|
||||||
{ 0, 99, 50, 0, 1, 0 }, |
|
||||||
{ 0, 99, 35, 0, 1, 0 }, |
|
||||||
{ 0, 99, 78, 0, 1, 0 }, |
|
||||||
{ 0, 99, 99, 0, 1, 0 }, |
|
||||||
{ 0, 99, 75, 0, 1, 0 }, |
|
||||||
{ 0, 99, 0, 0, 1, 0 }, |
|
||||||
{ 0, 99, 0, 0, 1, 0 }, |
|
||||||
{ 0, 99, 58, 0, 1, 0 }, |
|
||||||
{ 0, 1, 0, 0, 1, 0 }, |
|
||||||
{ 0, 31, 14, 0, 1, 0 }, |
|
||||||
{ 0, 100, 0, 0, 1, 0 }, |
|
||||||
{ -7, 7, 0, 0, 1, 0 }, |
|
||||||
{ 0, 100, 0, 0, 1, 0 }, |
|
||||||
{ 0, 100, 0, 0, 1, 0 }, |
|
||||||
{ 0, 100, 0, 0, 1, 0 }, |
|
||||||
{ 0, 3, 0, 0, 1, 0 }, |
|
||||||
{ 0, 3, 0, 0, 1, 0 }, |
|
||||||
{ 0, 7, 3, 0, 1, 0 }, |
|
||||||
{ 0, 3, 0, 0, 1, 0 }, |
|
||||||
{ 0, 7, 7, 0, 1, 0 }, |
|
||||||
{ 0, 99, 95, 0, 1, 0 }, |
|
||||||
{ 0, 99, 20, 0, 1, 0 }, |
|
||||||
{ 0, 99, 20, 0, 1, 0 }, |
|
||||||
{ 0, 99, 50, 0, 1, 0 }, |
|
||||||
{ 0, 99, 99, 0, 1, 0 }, |
|
||||||
{ 0, 99, 95, 0, 1, 0 }, |
|
||||||
{ 0, 99, 0, 0, 1, 0 }, |
|
||||||
{ 0, 99, 0, 0, 1, 0 }, |
|
||||||
{ 0, 99, 99, 0, 1, 0 }, |
|
||||||
{ 0, 1, 0, 0, 1, 0 }, |
|
||||||
{ 0, 31, 1, 0, 1, 0 }, |
|
||||||
{ 0, 99, 0, 0, 1, 0 }, |
|
||||||
{ -7, 7, 0, 0, 1, 0 }, |
|
||||||
{ 0, 99, 0, 0, 1, 0 }, |
|
||||||
{ 0, 99, 0, 0, 1, 0 }, |
|
||||||
{ 0, 99, 0, 0, 1, 0 }, |
|
||||||
{ 0, 3, 0, 0, 1, 0 }, |
|
||||||
{ 0, 3, 0, 0, 1, 0 }, |
|
||||||
{ 0, 7, 3, 0, 1, 0 }, |
|
||||||
{ 0, 3, 0, 0, 1, 0 }, |
|
||||||
{ 0, 7, 2, 0, 1, 0 }, |
|
||||||
{ 0, 99, 95, 0, 1, 0 }, |
|
||||||
{ 0, 99, 29, 0, 1, 0 }, |
|
||||||
{ 0, 99, 20, 0, 1, 0 }, |
|
||||||
{ 0, 99, 50, 0, 1, 0 }, |
|
||||||
{ 0, 99, 99, 0, 1, 0 }, |
|
||||||
{ 0, 99, 95, 0, 1, 0 }, |
|
||||||
{ 0, 99, 0, 0, 1, 0 }, |
|
||||||
{ 0, 99, 0, 0, 1, 0 }, |
|
||||||
{ 0, 99, 89, 0, 1, 0 }, |
|
||||||
{ 0, 1, 0, 0, 1, 0 }, |
|
||||||
{ 0, 31, 1, 0, 1, 0 }, |
|
||||||
{ 0, 99, 0, 0, 1, 0 }, |
|
||||||
{ -7, 7, 0, 0, 1, 0 }, |
|
||||||
{ 0, 99, 0, 0, 1, 0 }, |
|
||||||
{ 0, 99, 0, 0, 1, 0 }, |
|
||||||
{ 0, 99, 0, 0, 1, 0 }, |
|
||||||
{ 0, 3, 0, 0, 1, 0 }, |
|
||||||
{ 0, 3, 0, 0, 1, 0 }, |
|
||||||
{ 0, 7, 3, 0, 1, 0 }, |
|
||||||
{ 0, 3, 0, 0, 1, 0 }, |
|
||||||
{ 0, 7, 6, 0, 1, 0 }, |
|
||||||
{ 0, 99, 95, 0, 1, 0 }, |
|
||||||
{ 0, 99, 20, 0, 1, 0 }, |
|
||||||
{ 0, 99, 20, 0, 1, 0 }, |
|
||||||
{ 0, 99, 50, 0, 1, 0 }, |
|
||||||
{ 0, 99, 99, 0, 1, 0 }, |
|
||||||
{ 0, 99, 95, 0, 1, 0 }, |
|
||||||
{ 0, 99, 0, 0, 1, 0 }, |
|
||||||
{ 0, 99, 0, 0, 1, 0 }, |
|
||||||
{ 0, 99, 99, 0, 1, 0 }, |
|
||||||
{ 0, 1, 0, 0, 1, 0 }, |
|
||||||
{ 0, 31, 1, 0, 1, 0 }, |
|
||||||
{ 0, 99, 0, 0, 1, 0 }, |
|
||||||
{ -7, 7, -7, 0, 1, 0 }, |
|
||||||
{ 0, 99, 0, 0, 1, 0 }, |
|
||||||
{ 0, 99, 0, 0, 1, 0 }, |
|
||||||
{ 0, 99, 0, 0, 1, 0 }, |
|
||||||
{ 0, 3, 0, 0, 1, 0 }, |
|
||||||
{ 0, 3, 0, 0, 1, 0 }, |
|
||||||
{ 0, 7, 3, 0, 1, 0 }, |
|
||||||
{ 0, 3, 0, 0, 1, 0 }, |
|
||||||
{ 0, 7, 0, 0, 1, 0 }, |
|
||||||
{ 0, 99, 95, 0, 1, 0 }, |
|
||||||
{ 0, 99, 29, 0, 1, 0 }, |
|
||||||
{ 0, 99, 20, 0, 1, 0 }, |
|
||||||
{ 0, 99, 50, 0, 1, 0 }, |
|
||||||
{ 0, 99, 99, 0, 1, 0 }, |
|
||||||
{ 0, 99, 95, 0, 1, 0 }, |
|
||||||
{ 0, 99, 0, 0, 1, 0 }, |
|
||||||
{ 0, 99, 0, 0, 1, 0 }, |
|
||||||
{ 0, 99, 79, 0, 1, 0 }, |
|
||||||
{ 0, 1, 0, 0, 1, 0 }, |
|
||||||
{ 0, 31, 1, 0, 1, 0 }, |
|
||||||
{ 0, 99, 0, 0, 1, 0 }, |
|
||||||
{ -7, 7, 7, 0, 1, 0 }, |
|
||||||
{ 0, 99, 41, 0, 1, 0 }, |
|
||||||
{ 0, 99, 0, 0, 1, 0 }, |
|
||||||
{ 0, 99, 19, 0, 1, 0 }, |
|
||||||
{ 0, 3, 0, 0, 1, 0 }, |
|
||||||
{ 0, 3, 0, 0, 1, 0 }, |
|
||||||
{ 0, 7, 3, 0, 1, 0 }, |
|
||||||
{ 0, 3, 0, 0, 1, 0 }, |
|
||||||
{ 0, 7, 6, 0, 1, 0 }, |
|
||||||
{ 0, 1, 1, 0, 1, 0 }, |
|
||||||
{ 0, 1, 1, 0, 1, 0 }, |
|
||||||
{ 0, 1, 1, 0, 1, 0 }, |
|
||||||
{ 0, 1, 1, 0, 1, 0 }, |
|
||||||
{ 0, 1, 1, 0, 1, 0 }, |
|
||||||
{ 0, 1, 1, 0, 1, 0 }, |
|
||||||
}; |
|
||||||
|
|
||||||
|
|
||||||
#endif /* dexed_ttl_h */ |
|
@ -1,216 +0,0 @@ |
|||||||
/**
|
|
||||||
* |
|
||||||
* Copyright (c) 2013-2014 Pascal Gauthier. |
|
||||||
* Copyright (c) 2013-2014 Filatov Vadim. |
|
||||||
*
|
|
||||||
* Filter taken from the Obxd project : |
|
||||||
* https://github.com/2DaT/Obxd
|
|
||||||
* |
|
||||||
* 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. |
|
||||||
* |
|
||||||
* 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. |
|
||||||
* |
|
||||||
* You should have received a copy of the GNU General Public License |
|
||||||
* along with this program; if not, write to the Free Software Foundation, |
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
|
||||||
* |
|
||||||
*/ |
|
||||||
|
|
||||||
#define _USE_MATH_DEFINES |
|
||||||
#include <math.h> |
|
||||||
#include "PluginFx.h" |
|
||||||
|
|
||||||
const float dc = 1e-18; |
|
||||||
|
|
||||||
inline static float tptpc(float& state,float inp,float cutoff) { |
|
||||||
double v = (inp - state) * cutoff / (1 + cutoff); |
|
||||||
double res = v + state; |
|
||||||
state = res + v; |
|
||||||
return res; |
|
||||||
} |
|
||||||
|
|
||||||
inline static float tptlpupw(float & state , float inp , float cutoff , float srInv) { |
|
||||||
cutoff = (cutoff * srInv)*M_PI; |
|
||||||
double v = (inp - state) * cutoff / (1 + cutoff); |
|
||||||
double res = v + state; |
|
||||||
state = res + v; |
|
||||||
return res; |
|
||||||
} |
|
||||||
|
|
||||||
//static float linsc(float param,const float min,const float max) {
|
|
||||||
// return (param) * (max - min) + min;
|
|
||||||
//}
|
|
||||||
|
|
||||||
static float logsc(float param, const float min,const float max,const float rolloff = 19.0f) { |
|
||||||
return ((expf(param * logf(rolloff+1)) - 1.0f) / (rolloff)) * (max-min) + min; |
|
||||||
} |
|
||||||
|
|
||||||
PluginFx::PluginFx() { |
|
||||||
uiCutoff = 1; |
|
||||||
uiReso = 0; |
|
||||||
uiGain = 1; |
|
||||||
} |
|
||||||
|
|
||||||
void PluginFx::init(int sr) { |
|
||||||
mm=0; |
|
||||||
s1=s2=s3=s4=c=d=0; |
|
||||||
R24=0; |
|
||||||
|
|
||||||
mmch = (int)(mm * 3); |
|
||||||
mmt = mm*3-mmch; |
|
||||||
|
|
||||||
sampleRate = sr; |
|
||||||
sampleRateInv = 1/sampleRate; |
|
||||||
float rcrate =sqrt((44000/sampleRate)); |
|
||||||
rcor24 = (970.0 / 44000)*rcrate; |
|
||||||
rcor24Inv = 1 / rcor24; |
|
||||||
|
|
||||||
bright = tan((sampleRate*0.5f-10) * M_PI * sampleRateInv); |
|
||||||
|
|
||||||
R = 1; |
|
||||||
rcor = (480.0 / 44000)*rcrate; |
|
||||||
rcorInv = 1 / rcor; |
|
||||||
bandPassSw = false; |
|
||||||
|
|
||||||
pCutoff = -1; |
|
||||||
pReso = -1; |
|
||||||
|
|
||||||
dc_r = 1.0-(126.0/sr); |
|
||||||
dc_id = 0; |
|
||||||
dc_od = 0; |
|
||||||
} |
|
||||||
|
|
||||||
inline float PluginFx::NR24(float sample,float g,float lpc) { |
|
||||||
float ml = 1 / (1+g); |
|
||||||
float S = (lpc*(lpc*(lpc*s1 + s2) + s3) +s4)*ml; |
|
||||||
float G = lpc*lpc*lpc*lpc; |
|
||||||
float y = (sample - R24 * S) / (1 + R24*G); |
|
||||||
return y + 1e-8; |
|
||||||
}; |
|
||||||
|
|
||||||
inline float PluginFx::NR(float sample, float g) { |
|
||||||
float y = ((sample- R * s1*2 - g*s1 - s2)/(1+ g*(2*R + g))) + dc; |
|
||||||
return y; |
|
||||||
} |
|
||||||
|
|
||||||
void PluginFx::process(float *work, int sampleSize) { |
|
||||||
// very basic DC filter
|
|
||||||
float t_fd = work[0]; |
|
||||||
work[0] = work[0] - dc_id + dc_r * dc_od; |
|
||||||
dc_id = t_fd; |
|
||||||
for (int i=1; i<sampleSize; i++) { |
|
||||||
t_fd = work[i]; |
|
||||||
work[i] = work[i] - dc_id + dc_r * work[i-1]; |
|
||||||
dc_id = t_fd; |
|
||||||
|
|
||||||
} |
|
||||||
dc_od = work[sampleSize-1]; |
|
||||||
|
|
||||||
if ( uiGain != 1 ) { |
|
||||||
for(int i=0; i < sampleSize; i++ ) |
|
||||||
work[i] *= uiGain; |
|
||||||
} |
|
||||||
|
|
||||||
// don't apply the LPF if the cutoff is to maximum
|
|
||||||
if ( uiCutoff == 1 ) |
|
||||||
return; |
|
||||||
|
|
||||||
if ( uiCutoff != pCutoff || uiReso != pReso ) { |
|
||||||
rReso = (0.991-logsc(1-uiReso,0,0.991)); |
|
||||||
R24 = 3.5 * rReso; |
|
||||||
|
|
||||||
float cutoffNorm = logsc(uiCutoff,60,19000); |
|
||||||
rCutoff = (float)tan(cutoffNorm * sampleRateInv * M_PI); |
|
||||||
|
|
||||||
pCutoff = uiCutoff; |
|
||||||
pReso = uiReso; |
|
||||||
|
|
||||||
R = 1 - rReso; |
|
||||||
} |
|
||||||
|
|
||||||
// THIS IS MY FAVORITE 4POLE OBXd filter
|
|
||||||
|
|
||||||
// maybe smooth this value
|
|
||||||
float g = rCutoff; |
|
||||||
float lpc = g / (1 + g); |
|
||||||
|
|
||||||
for(int i=0; i < sampleSize; i++ ) { |
|
||||||
float s = work[i]; |
|
||||||
s = s - 0.45*tptlpupw(c,s,15,sampleRateInv); |
|
||||||
s = tptpc(d,s,bright); |
|
||||||
|
|
||||||
float y0 = NR24(s,g,lpc); |
|
||||||
|
|
||||||
//first low pass in cascade
|
|
||||||
double v = (y0 - s1) * lpc; |
|
||||||
double res = v + s1; |
|
||||||
s1 = res + v; |
|
||||||
|
|
||||||
//damping
|
|
||||||
s1 =atan(s1*rcor24)*rcor24Inv; |
|
||||||
float y1= res; |
|
||||||
float y2 = tptpc(s2,y1,g); |
|
||||||
float y3 = tptpc(s3,y2,g); |
|
||||||
float y4 = tptpc(s4,y3,g); |
|
||||||
float mc=0.0; |
|
||||||
|
|
||||||
switch(mmch) { |
|
||||||
case 0: |
|
||||||
mc = ((1 - mmt) * y4 + (mmt) * y3); |
|
||||||
break; |
|
||||||
case 1: |
|
||||||
mc = ((1 - mmt) * y3 + (mmt) * y2); |
|
||||||
break; |
|
||||||
case 2: |
|
||||||
mc = ((1 - mmt) * y2 + (mmt) * y1); |
|
||||||
break; |
|
||||||
case 3: |
|
||||||
mc = y1; |
|
||||||
break; |
|
||||||
} |
|
||||||
|
|
||||||
//half volume comp
|
|
||||||
work[i] = mc * (1 + R24 * 0.45); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
// THIS IS THE 2POLE FILTER
|
|
||||||
|
|
||||||
for(int i=0; i < sampleSize; i++ ) { |
|
||||||
float s = work[i]; |
|
||||||
s = s - 0.45*tptlpupw(c,s,15,sampleRateInv); |
|
||||||
s = tptpc(d,s,bright); |
|
||||||
|
|
||||||
//float v = ((sample- R * s1*2 - g2*s1 - s2)/(1+ R*g1*2 + g1*g2));
|
|
||||||
float v = NR(s,g); |
|
||||||
float y1 = v*g + s1; |
|
||||||
//damping
|
|
||||||
s1 = atan(s1 * rcor) * rcorInv; |
|
||||||
|
|
||||||
float y2 = y1*g + s2; |
|
||||||
s2 = y2 + y1*g; |
|
||||||
|
|
||||||
double mc; |
|
||||||
if(!bandPassSw) |
|
||||||
mc = (1-mm)*y2 + (mm)*v; |
|
||||||
else |
|
||||||
{ |
|
||||||
|
|
||||||
mc =2 * ( mm < 0.5 ? |
|
||||||
((0.5 - mm) * y2 + (mm) * y1): |
|
||||||
((1-mm) * y1 + (mm-0.5) * v) |
|
||||||
); |
|
||||||
} |
|
||||||
|
|
||||||
work[i] = mc; |
|
||||||
} |
|
||||||
|
|
||||||
*/ |
|
@ -1,72 +0,0 @@ |
|||||||
/**
|
|
||||||
* |
|
||||||
* Copyright (c) 2013 Pascal Gauthier. |
|
||||||
* |
|
||||||
* 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. |
|
||||||
* |
|
||||||
* 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. |
|
||||||
* |
|
||||||
* You should have received a copy of the GNU General Public License |
|
||||||
* along with this program; if not, write to the Free Software Foundation, |
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
|
||||||
* |
|
||||||
*/ |
|
||||||
|
|
||||||
#ifndef PLUGINFX_H_INCLUDED |
|
||||||
#define PLUGINFX_H_INCLUDED |
|
||||||
|
|
||||||
class PluginFx { |
|
||||||
float s1,s2,s3,s4; |
|
||||||
float sampleRate; |
|
||||||
float sampleRateInv; |
|
||||||
float d, c; |
|
||||||
float R24; |
|
||||||
float rcor24,rcor24Inv; |
|
||||||
float bright; |
|
||||||
|
|
||||||
// 24 db multimode
|
|
||||||
float mm; |
|
||||||
float mmt; |
|
||||||
int mmch; |
|
||||||
inline float NR24(float sample,float g,float lpc); |
|
||||||
|
|
||||||
// preprocess values taken the UI
|
|
||||||
float rCutoff; |
|
||||||
float rReso; |
|
||||||
float rGain; |
|
||||||
|
|
||||||
// thread values; if these are different from the UI,
|
|
||||||
// it needs to be recalculated.
|
|
||||||
float pReso; |
|
||||||
float pCutoff; |
|
||||||
float pGain; |
|
||||||
|
|
||||||
// I am still keeping the 2pole w/multimode filter
|
|
||||||
inline float NR(float sample, float g); |
|
||||||
bool bandPassSw; |
|
||||||
float rcor,rcorInv; |
|
||||||
int R; |
|
||||||
|
|
||||||
float dc_id; |
|
||||||
float dc_od; |
|
||||||
float dc_r; |
|
||||||
|
|
||||||
public: |
|
||||||
PluginFx(); |
|
||||||
|
|
||||||
// this is set directly by the ui / parameter
|
|
||||||
float uiCutoff; |
|
||||||
float uiReso; |
|
||||||
float uiGain; |
|
||||||
|
|
||||||
void init(int sampleRate); |
|
||||||
void process(float *work, int sampleSize); |
|
||||||
}; |
|
||||||
|
|
||||||
#endif // PLUGINFX_H_INCLUDED
|
|
Loading…
Reference in new issue