Skip to content

Commit

Permalink
Add CV control and update synth example.
Browse files Browse the repository at this point in the history
  • Loading branch information
DatanoiseTV committed Dec 4, 2022
1 parent f29308c commit e23a617
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 39 deletions.
20 changes: 16 additions & 4 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
#define DEBUG_MIDI 1

// Set to 0 if you want to play notes via USB MIDI
#define PLAY_RANDOM_NOTES 0
#define PLAY_RANDOM_NOTES 1

audio_buffer_pool_t *ap;
Dsp_process_type ctx;
Expand Down Expand Up @@ -176,9 +176,9 @@ extern "C"
xTaskCreate(usb_midi_task, "USBMIDI", 8192, NULL, configMAX_PRIORITIES, NULL);
xTaskCreate(print_task, "TASKLIST", 4096, NULL, configMAX_PRIORITIES - 1, NULL);
xTaskCreate(blinker_task, "BLINKER", 4096, NULL, configMAX_PRIORITIES - 1, NULL);
#ifdef PLAY_RANDOM_NOTES
#ifdef PLAY_RANDOM_NOTES
xTaskCreate(play_task, "PLAY", 4096, NULL, configMAX_PRIORITIES - 1, NULL);
#endif
#endif
vTaskStartScheduler();

// Idle loop.
Expand All @@ -201,6 +201,12 @@ extern "C"
return out << 15u;
}

int rev_log_scale(int x)
{
// Calculate reverse logarithmic value from linear input
return (int)(pow(10, abs(x) / 2048.0) / 10.0 * 2048.0 - 2048.0);
}

// This function is called by the audio subsystem when it needs more audio data.
void i2s_callback_func()
{
Expand All @@ -213,12 +219,18 @@ extern "C"

dsp_start = to_us_since_boot(get_absolute_time());

// convert 12-bit adc value to 16-bit signed int
uint32_t cv0 = adc128_read(0) * 16;
uint32_t cv1 = rev_log_scale(adc128_read(1)) * 16;
uint32_t cv2 = adc128_read(2) * 16;
uint32_t cv3 = adc128_read(3) * 16;

// We are filling the buffer with 32-bit samples (2 channels)
for (uint i = 0; i < buffer->max_sample_count; i++)
{
// smp should be the output of your processing code.
// In case of the Vult Example, this is Dsp_process(ctx);
Dsp_process(ctx);
Dsp_process(ctx, cv0, cv1, cv2, cv3);
fix16_t left_out = Dsp_process_ret_0(ctx);
fix16_t right_out = Dsp_process_ret_1(ctx);
samples[i * 2 + 0] = fix16_to_int32(left_out); // LEFT
Expand Down
47 changes: 12 additions & 35 deletions vultsrc/dsp.vult
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
/*
= A simple synthesizer with one LFO and a Delay effect
CC30 - Volume
CC31 - Detune/Resonance
CC32 - LFO rate
CC33 - LFO amount (bipolar)
CC34 - Delay time
CC35 - Delay feedback
*/
fun smooth_cv(input:real) : real {
mem x;
x = x+(input-x)*0.001;
return x;
}

// Returns true every 'n' calls
fun each(n:int) : bool {
Expand Down Expand Up @@ -381,7 +377,7 @@ fun reverb(x) {
}

// Main processing function
fun process() {
fun process(cv0:real, cv1:real, cv2:real, cv3:real) {
mem volume,detune; // values set in 'controlChange'
mem pitch;
mem lfo_rate,lfo_amt;
Expand All @@ -399,40 +395,21 @@ fun process() {
val lfo_val = lfo(lfo_rate,gate)*lfo_amt;

// creates two oscillators
val o1 = Sawcore.process(Util.pitchToCv(pitch+pitchBend+lfo_val), 0.0) * 0.5;
val o1 = Sawcore.process(Util.pitchToCv( pitch+pitchBend+lfo_val), 0.0) * 0.5;
val o2 = Sawcore.process(Util.pitchToCv(pitch+detune+lfo_val+pitchBend)-0.1, 0.0) * 0.5;
val osc_mix = o1 + o2;

// gets the amplification by using a low-pass on the gate
val amp = Util.smooth(if gate then 1.0 else 0.0);
val osc_out = osc_mix * amp;


// ADSR env for filter


val gate_real = if gate then 1.0 else 0.0;
val env_vcf = Adsr.do(gate_real, filter_attack, filter_decay, filter_sustain, filter_release) * 4.0;
val env_vca = Adsr.do(gate_real, vca_attack, vca_decay, vca_sustain, vca_release) * 4.0;

val filter_frequency = clip(filter_cutoff+(env_vcf*filter_env_amt), 0.0, 1.0);
val filter_out = Svf.process(osc_out, filter_frequency, filter_resonance, 0);

val delay_out = delay(filter_out, Util.smooth(time), Util.smooth(feedback));
/*
val lfo_time_a = Swept.process(gate_real, 1.0, 0.0, 0.01);
val lfo_time_b = Swept.process(gate_real, 1.0, 0.0, 0.024);
val osc_out = Fold.process(osc_mix, smooth_cv(cv2));

val comb_out_a = combFilter(osc_out, lfo_time_a);
val comb_out_b = combFilter(osc_out, clip(lfo_time_b+0.1, 0.0, 1.0));

val out = reverb((comb_out_a*0.5 + comb_out_b*0.5)*env_vca)/4.0;
*/
//val out = unit_drum(gate_real, 4.0, 0.01, 0.7, 0.5);
val filter_frequency = clip(smooth_cv(cv1)+(env_vcf*smooth_cv(cv3)), 0.0, 1.0);
val filter_out_pre = Svf.process(osc_out, filter_frequency, smooth_cv(cv0)*5.5, 0);
val filter_out = Saturate.process(filter_out_pre);

// mute workaround to avoid noise at startup
val mono_output = ((delay_out*0.5) + filter_out*0.5);

val mono_output = filter_out * env_vca;
val left = mono_output;
val right = mono_output;
return left, right;
Expand Down

0 comments on commit e23a617

Please sign in to comment.