mirror of
				https://github.com/AquaMorph/Droplets.git
				synced 2025-10-31 08:23:18 +00:00 
			
		
		
		
	AD envelope with splitting
This commit is contained in:
		| @@ -2,16 +2,15 @@ | ||||
|  | ||||
| void AD::Init(DaisyPatch* m_patch, | ||||
| 	      float sample_rate, | ||||
| 	      AnalogControl attack_knob, | ||||
| 	      AnalogControl decay_knob) { | ||||
| 	      DropletState* m_state) { | ||||
|     patch = m_patch; | ||||
|     state = m_state; | ||||
|     env.Init(sample_rate); | ||||
|     env.SetMax(1.0f); | ||||
|     env.SetMin(0.0f); | ||||
|     env.SetCurve(0.0f); | ||||
|     attack_param.Init(attack_knob, .01f, 3.0f, Parameter::EXPONENTIAL); | ||||
|     decay_param.Init(decay_knob, .01f, 3.0f, Parameter::EXPONENTIAL); | ||||
|     curve_param.Init(attack_knob, -10.f, 10.0f, Parameter::LINEAR); | ||||
|  | ||||
|     SetControls(); | ||||
|   } | ||||
|  | ||||
| void AD::Process(DacHandle::Channel chn, | ||||
| @@ -19,19 +18,26 @@ void AD::Process(DacHandle::Channel chn, | ||||
|   if(patch->gate_input[gate].Trig()) { | ||||
|     env.Trigger(); | ||||
|   } | ||||
|   if (curve_menu) { | ||||
|   if (*state == DropletState::kFull) { | ||||
|     attack = attack_param.Process(); | ||||
|     decay = decay_param.Process(); | ||||
|     curve = curve_param.Process(); | ||||
|     amp = amp_param.Process(); | ||||
|   } else if (curve_menu) { | ||||
|     curve = curve_param.Process(); | ||||
|     amp = amp_param.Process(); | ||||
|   } else { | ||||
|     attack = attack_param.Process(); | ||||
|     decay = decay_param.Process(); | ||||
|   } | ||||
|   decay = decay_param.Process(); | ||||
|    | ||||
|   env.SetTime(ADENV_SEG_ATTACK, attack); | ||||
|   env.SetTime(ADENV_SEG_DECAY, decay); | ||||
|   env.SetCurve(curve); | ||||
|    | ||||
|   sig = env.Process(); | ||||
|   patch->seed.dac.WriteValue(chn, | ||||
| 			     sig * 4095.0f); | ||||
|   sig * amp * 4095.0f); | ||||
| } | ||||
|  | ||||
| float AD::GetSignal() { | ||||
| @@ -50,6 +56,10 @@ float AD::GetCurve() { | ||||
|   return curve; | ||||
| } | ||||
|  | ||||
| float AD::GetAmp() { | ||||
|   return amp; | ||||
| } | ||||
|  | ||||
| bool AD::GetMenu() { | ||||
|   return curve_menu; | ||||
| } | ||||
| @@ -58,36 +68,51 @@ void AD::ToggleCurve() { | ||||
|   curve_menu = !curve_menu; | ||||
| } | ||||
|  | ||||
| ADDroplet::ADDroplet(DaisyPatch* m_patch, | ||||
| 		       DropletState m_state, | ||||
| 		       float sample_rate) : | ||||
|   Droplet(m_patch, | ||||
| 	  m_state) { | ||||
|   switch (GetState()) { | ||||
| void AD::SetControls() { | ||||
|   AnalogControl attack_knob, decay_knob, curve_knob, amp_knob; | ||||
|  | ||||
|   switch (*state) { | ||||
|   default: | ||||
|   case DropletState::kFull: | ||||
|     ad[0].Init(Patch(), | ||||
| 		sample_rate, | ||||
| 		Patch()->controls[Patch()->CTRL_1], | ||||
| 		Patch()->controls[Patch()->CTRL_2]); | ||||
|     ad[1].Init(Patch(), | ||||
| 		sample_rate, | ||||
| 		Patch()->controls[Patch()->CTRL_3], | ||||
| 		Patch()->controls[Patch()->CTRL_4]); | ||||
|     attack_knob = patch->controls[patch->CTRL_1]; | ||||
|     decay_knob = patch->controls[patch->CTRL_2]; | ||||
|     curve_knob = patch->controls[patch->CTRL_3]; | ||||
|     amp_knob = patch->controls[patch->CTRL_4]; | ||||
|     break; | ||||
|   case DropletState::kLeft: | ||||
|     ad[0].Init(Patch(), | ||||
| 		sample_rate, | ||||
| 		Patch()->controls[Patch()->CTRL_1], | ||||
| 		Patch()->controls[Patch()->CTRL_2]); | ||||
|     attack_knob = patch->controls[patch->CTRL_1]; | ||||
|     decay_knob = patch->controls[patch->CTRL_2]; | ||||
|     curve_knob = patch->controls[patch->CTRL_1]; | ||||
|     amp_knob = patch->controls[patch->CTRL_2]; | ||||
|     break; | ||||
|   case DropletState::kRight: | ||||
|     ad[0].Init(Patch(), | ||||
| 		sample_rate, | ||||
| 		Patch()->controls[Patch()->CTRL_3], | ||||
| 		Patch()->controls[Patch()->CTRL_4]); | ||||
|     attack_knob = patch->controls[patch->CTRL_3]; | ||||
|     decay_knob = patch->controls[patch->CTRL_4]; | ||||
|     curve_knob = patch->controls[patch->CTRL_3]; | ||||
|     amp_knob = patch->controls[patch->CTRL_4]; | ||||
|     break; | ||||
|   } | ||||
|    | ||||
|   attack_param.Init(attack_knob, .01f, 3.0f, Parameter::EXPONENTIAL); | ||||
|   decay_param.Init(decay_knob, .01f, 3.0f, Parameter::EXPONENTIAL); | ||||
|   curve_param.Init(curve_knob, -10.f, 10.0f, Parameter::LINEAR); | ||||
|   amp_param.Init(amp_knob, 0.0f, 1.0f, Parameter::LINEAR); | ||||
| } | ||||
|  | ||||
| ADDroplet::ADDroplet(DaisyPatch* m_patch, | ||||
| 		       DropletState m_state, | ||||
| 		       float m_sample_rate) : | ||||
|   Droplet(m_patch, | ||||
| 	  m_state) { | ||||
|   sample_rate = m_sample_rate; | ||||
|   ad[0].Init(Patch(), | ||||
| 	     sample_rate, | ||||
| 	     &m_state); | ||||
|   if (m_state == DropletState::kFull) { | ||||
|     ad[1].Init(Patch(), | ||||
| 	       sample_rate, | ||||
| 	       &m_state); | ||||
|   } | ||||
| } | ||||
|  | ||||
| ADDroplet::~ADDroplet() {} | ||||
| @@ -105,7 +130,6 @@ void ADDroplet::Control() { | ||||
|  | ||||
| void ADDroplet::Process(AudioHandle::InputBuffer in, AudioHandle::OutputBuffer out, size_t size) { | ||||
|   Patch()->ProcessAnalogControls(); | ||||
|  | ||||
|   for(size_t i = 0; i < size; i++) { | ||||
|     if (GetState() == DropletState::kRight) { | ||||
|       ad[0].Process(DacHandle::Channel::TWO, DaisyPatch::GATE_IN_2); | ||||
| @@ -120,7 +144,8 @@ void ADDroplet::Process(AudioHandle::InputBuffer in, AudioHandle::OutputBuffer o | ||||
|       if(GetState() == DropletState::kFull && chn > 1) { | ||||
| 	env_sel = 1; | ||||
|       } | ||||
|       out[chn][i] = in[chn][i] * ad[env_sel].GetSignal(); | ||||
|       out[chn][i] = in[chn][i] * ad[env_sel].GetSignal() * | ||||
| 	ad[env_sel].GetAmp(); | ||||
|     } | ||||
|   } | ||||
| } | ||||
| @@ -146,36 +171,31 @@ void ADDroplet::Draw() { | ||||
| 	      Font_6x8, | ||||
| 	      "C: " + | ||||
| 	      FloatToString(ad[0].GetCurve(), 2)); | ||||
|   if(GetState() == DropletState::kFull) { | ||||
|     int mid = (GetScreenMax() - GetScreenMin())/2; | ||||
|     WriteString(Patch(), | ||||
| 	        mid, | ||||
| 		11, | ||||
| 		Font_6x8, | ||||
| 		"A: " + | ||||
| 		FloatToString(ad[1].GetAttack(), 2) + | ||||
| 		"s"); | ||||
|     WriteString(Patch(), | ||||
| 		mid, | ||||
| 		21, | ||||
| 		Font_6x8, | ||||
| 		"D: " + | ||||
| 		FloatToString(ad[1].GetDecay(), 2) + | ||||
| 		"s"); | ||||
|     WriteString(Patch(), | ||||
| 		mid, | ||||
| 		31, | ||||
| 		Font_6x8, | ||||
| 		"C: " + | ||||
| 		FloatToString(ad[1].GetCurve(), 2)); | ||||
|   } | ||||
|   WriteString(Patch(), | ||||
| 	      GetScreenMin()+3, | ||||
| 	      41, | ||||
| 	      Font_6x8, | ||||
| 	      "Amp: " + | ||||
| 	      FloatToString(ad[0].GetAmp(), 2)); | ||||
|  | ||||
|   if (ad[0].GetMenu()) { | ||||
|     DrawSolidRect(Patch(), GetScreenMin(), 30, GetScreenMin()+1, 39, true); | ||||
|   } else { | ||||
|     DrawSolidRect(Patch(), GetScreenMin(), 10, GetScreenMin()+1, 19, true); | ||||
|   if (GetState() != DropletState::kFull) { | ||||
|     if (ad[0].GetMenu()) { | ||||
|       DrawSolidRect(Patch(), GetScreenMin(), 30, GetScreenMin()+1, 49, true); | ||||
|     } else { | ||||
|       DrawSolidRect(Patch(), GetScreenMin(), 10, GetScreenMin()+1, 29, true); | ||||
|     } | ||||
|   } | ||||
|   DrawSolidRect(Patch(), GetScreenMin(), 20, GetScreenMin()+1, 29, true); | ||||
|    | ||||
|   DrawName("AD"); | ||||
| } | ||||
|  | ||||
| void ADDroplet::UpdateStateCallback() { | ||||
|   ad[0].Init(Patch(), | ||||
| 	     sample_rate, | ||||
| 	     State()); | ||||
|   if (GetState() == DropletState::kFull) { | ||||
|     ad[1].Init(Patch(), | ||||
| 	       sample_rate, | ||||
| 	       State()); | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -16,17 +16,20 @@ class AD { | ||||
| private: | ||||
|   AdEnv         env; | ||||
|   float         attack, decay, curve = 0; | ||||
|   float         amp = 1.0f; | ||||
|   Parameter     attack_param; | ||||
|   Parameter     decay_param; | ||||
|   Parameter     curve_param; | ||||
|   Parameter     amp_param; | ||||
|   float         sig; | ||||
|   DaisyPatch*   patch; | ||||
|   bool          curve_menu = false; | ||||
|   DropletState* state; | ||||
|    | ||||
| public: | ||||
|   void Init(DaisyPatch* m_patch, | ||||
| 	    float sample_rate, | ||||
| 	    AnalogControl attack_knob, | ||||
| 	    AnalogControl decay_knob); | ||||
| 	    DropletState* state); | ||||
|  | ||||
|   void Process(DacHandle::Channel chn, DaisyPatch::GateInput gate); | ||||
|  | ||||
| @@ -34,13 +37,16 @@ public: | ||||
|   float GetAttack(); | ||||
|   float GetDecay(); | ||||
|   float GetCurve(); | ||||
|   float GetAmp(); | ||||
|   bool GetMenu(); | ||||
|   void ToggleCurve(); | ||||
|   void SetControls(); | ||||
| }; | ||||
|  | ||||
| class ADDroplet: public Droplet { | ||||
| private: | ||||
|   AD ad[2]; | ||||
|   float sample_rate; | ||||
|  | ||||
| public: | ||||
|   /* | ||||
| @@ -78,6 +84,11 @@ public: | ||||
|    * Processes information to be shown on the display.  | ||||
|    */ | ||||
|   void Draw(); | ||||
|    | ||||
|   /* | ||||
|    * Runs when droplet state is updated. | ||||
|    */ | ||||
|   void UpdateStateCallback(); | ||||
| }; | ||||
|  | ||||
| #endif // CASCADE_DROPLETS_AD_DROPLET_H_ | ||||
|   | ||||
| @@ -9,6 +9,10 @@ DaisyPatch* Droplet::Patch() { | ||||
|   return patch; | ||||
| } | ||||
|  | ||||
| DropletState* Droplet::State() { | ||||
|   return &state; | ||||
| } | ||||
|  | ||||
| DropletState Droplet::GetState() { | ||||
|   return state; | ||||
| } | ||||
| @@ -51,6 +55,7 @@ void Droplet::UpdateState(DropletState m_state) { | ||||
|     chn_min = 2; | ||||
|     screen_min = SSD1309_WIDTH / 2; | ||||
|   } | ||||
|   UpdateStateCallback(); | ||||
| } | ||||
|  | ||||
| void Droplet::AnimationInc() { | ||||
|   | ||||
| @@ -47,7 +47,7 @@ public: | ||||
|  | ||||
|   /* | ||||
|    * Processes audio input and outputs. | ||||
|    * | ||||
| 2   * | ||||
|    * @param in the audio inputs for the patch | ||||
|    * @param out the audio outputs for the patch | ||||
|    * @param size the number of inputs and outputs | ||||
| @@ -62,12 +62,24 @@ public: | ||||
|   virtual void Draw()=0; | ||||
|  | ||||
|   /* | ||||
|    * Returns patch | ||||
|    * Runs when droplet state is updated. | ||||
|    */ | ||||
|   virtual void UpdateStateCallback() {} | ||||
|  | ||||
|   /* | ||||
|    * Returns patch. | ||||
|    * | ||||
|    * @return pointer to patch | ||||
|    */ | ||||
|   DaisyPatch* Patch(); | ||||
|  | ||||
|   /* | ||||
|    * Returns droplet state. | ||||
|    * | ||||
|    * @return pointer to state | ||||
|    */ | ||||
|   DropletState* State(); | ||||
|  | ||||
|   /* | ||||
|    * Returns the size of the droplet. | ||||
|    * | ||||
|   | ||||
| @@ -106,3 +106,5 @@ void LFODroplet::Draw() { | ||||
|   } | ||||
|   DrawName("LFO"); | ||||
| } | ||||
|  | ||||
| void LFODroplet::UpdateStateCallback() {} | ||||
|   | ||||
| @@ -77,6 +77,11 @@ public: | ||||
|    * Processes information to be shown on the display.  | ||||
|    */ | ||||
|   void Draw(); | ||||
|  | ||||
|   /* | ||||
|    * Runs when droplet state is updated. | ||||
|    */ | ||||
|   void UpdateStateCallback(); | ||||
| }; | ||||
|  | ||||
| #endif // CASCADE_DROPLETS_LFO_DROPLET_H_ | ||||
|   | ||||
| @@ -58,3 +58,5 @@ void MixerDroplet::Process(AudioHandle::InputBuffer in, AudioHandle::OutputBuffe | ||||
| void MixerDroplet::Draw() { | ||||
|   DrawName("Mixer"); | ||||
| } | ||||
|  | ||||
| void MixerDroplet::UpdateStateCallback() {} | ||||
|   | ||||
| @@ -51,6 +51,11 @@ public: | ||||
|    * Processes information to be shown on the display.  | ||||
|    */ | ||||
|   void Draw(); | ||||
|  | ||||
|   /* | ||||
|    * Runs when droplet state is updated. | ||||
|    */ | ||||
|   void UpdateStateCallback(); | ||||
| }; | ||||
|  | ||||
| #endif // CASCADE_DROPLETS_VCA_DROPLET_H_ | ||||
|   | ||||
| @@ -26,3 +26,5 @@ void NoiseDroplet::Draw() { | ||||
|   } | ||||
|   DrawName("Noise"); | ||||
| } | ||||
|  | ||||
| void NoiseDroplet::UpdateStateCallback() {} | ||||
|   | ||||
| @@ -41,6 +41,11 @@ public: | ||||
|    * Processes information to be shown on the display.  | ||||
|    */ | ||||
|   void Draw(); | ||||
|    | ||||
|   /* | ||||
|    * Runs when droplet state is updated. | ||||
|    */ | ||||
|   void UpdateStateCallback(); | ||||
| }; | ||||
|  | ||||
| #endif // CASCADE_DROPLETS_NOISE_DROPLET_H_ | ||||
|   | ||||
| @@ -109,3 +109,5 @@ void VCADroplet::Draw() { | ||||
|   } | ||||
|   DrawName("VCA"); | ||||
| } | ||||
|  | ||||
| void VCADroplet::UpdateStateCallback() {} | ||||
|   | ||||
| @@ -51,6 +51,11 @@ public: | ||||
|    * Processes information to be shown on the display.  | ||||
|    */ | ||||
|   void Draw(); | ||||
|  | ||||
|   /* | ||||
|    * Runs when droplet state is updated. | ||||
|    */ | ||||
|   void UpdateStateCallback(); | ||||
| }; | ||||
|  | ||||
| #endif // CASCADE_DROPLETS_VCA_DROPLET_H_ | ||||
|   | ||||
| @@ -144,3 +144,5 @@ void VCODroplet::SetWaveShape(int ws) { | ||||
|   wave = ws % Oscillator::WAVE_LAST; | ||||
|   last_wave_ctrl = ws; | ||||
| } | ||||
|  | ||||
| void VCODroplet::UpdateStateCallback() {} | ||||
|   | ||||
| @@ -68,6 +68,12 @@ public: | ||||
|    */ | ||||
|   void Draw(); | ||||
|  | ||||
|    | ||||
|   /* | ||||
|    * Runs when droplet state is updated. | ||||
|    */ | ||||
|   void UpdateStateCallback(); | ||||
|  | ||||
|   /* | ||||
|    * Changes the wave shape of the VCO. | ||||
|    * | ||||
|   | ||||
		Reference in New Issue
	
	Block a user