diff --git a/components/bl00mbox/.clang-tidy b/components/bl00mbox/.clang-tidy index 8797ef9f00e0c9fa8a20af5f8ee4e1931ea5b1e4..96260e90c56d5e0f433f914043042cfa7ca8e769 100644 --- a/components/bl00mbox/.clang-tidy +++ b/components/bl00mbox/.clang-tidy @@ -1 +1 @@ -Checks: '-clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling,-clang-diagnostic-deprecated-declarations,-clang-diagnostic-incompatible-pointer-types' +Checks: '-clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling,-clang-diagnostic-deprecated-declarations,-clang-diagnostic-incompatible-pointer-types,-clang-analyzer-core.NullDereference' diff --git a/components/bl00mbox/CMakeLists.txt b/components/bl00mbox/CMakeLists.txt index 1a99b66feaec5b10d458c4161c9c242c56c3f271..487573d07d7c21d2b1a1899ce40bd2bb3dfad316 100644 --- a/components/bl00mbox/CMakeLists.txt +++ b/components/bl00mbox/CMakeLists.txt @@ -13,6 +13,7 @@ idf_component_register( plugins/sampler.c plugins/delay.c plugins/flanger.c + plugins/multipitch.c plugins/sequencer.c plugins/noise.c plugins/noise_burst.c diff --git a/components/bl00mbox/bl00mbox_plugin_registry.c b/components/bl00mbox/bl00mbox_plugin_registry.c index c3f9fa0eecec967b009ffb56bbd2949acde1ea6f..46edee771b4ed457d07a7e2709ad4e14ab7cdbb6 100644 --- a/components/bl00mbox/bl00mbox_plugin_registry.c +++ b/components/bl00mbox/bl00mbox_plugin_registry.c @@ -99,6 +99,7 @@ radspa_descriptor_t * bl00mbox_plugin_registry_get_id_from_index(uint32_t index) #include "noise_burst.h" #include "distortion.h" #include "mixer.h" +#include "multipitch.h" #include "slew_rate_limiter.h" void bl00mbox_plugin_registry_init(void){ @@ -116,4 +117,5 @@ void bl00mbox_plugin_registry_init(void){ plugin_add(&distortion_desc); plugin_add(&mixer_desc); plugin_add(&slew_rate_limiter_desc); + plugin_add(&multipitch_desc); } diff --git a/components/bl00mbox/plugins/distortion.c b/components/bl00mbox/plugins/distortion.c index 4dfcb404b8be7c4a7656fa0b3240b70ed8bd78c7..7effbea2d26cc96eee55e494a9103079c4b50c6d 100644 --- a/components/bl00mbox/plugins/distortion.c +++ b/components/bl00mbox/plugins/distortion.c @@ -2,7 +2,7 @@ radspa_t * distortion_create(uint32_t init_var); radspa_descriptor_t distortion_desc = { - .name = "distortion", + .name = "_distortion", .id = 9000, .description = "distortion with linear interpolation between int16 values in plugin_table[129]", .create_plugin_instance = distortion_create, diff --git a/components/bl00mbox/plugins/mixer.c b/components/bl00mbox/plugins/mixer.c index 501662c77a962cf313891cba77e3d38925505d73..397fd142cc54c982e529367bd409ec63865aa0d7 100644 --- a/components/bl00mbox/plugins/mixer.c +++ b/components/bl00mbox/plugins/mixer.c @@ -45,7 +45,7 @@ radspa_t * mixer_create(uint32_t init_var){ radspa_signal_set(mixer, 0, "output", RADSPA_SIGNAL_HINT_OUTPUT, 0); int16_t gain = RADSPA_SIGNAL_VAL_UNITY_GAIN/init_var; radspa_signal_set(mixer, 1, "gain", RADSPA_SIGNAL_HINT_INPUT | RADSPA_SIGNAL_HINT_GAIN, gain); - radspa_signal_set_group(mixer, init_var, 2, "input", RADSPA_SIGNAL_HINT_INPUT, 0); + radspa_signal_set_group(mixer, init_var, 1, 2, "input", RADSPA_SIGNAL_HINT_INPUT, 0); int32_t * dc_acc = mixer->plugin_data; (* dc_acc) = 0; return mixer; diff --git a/components/bl00mbox/plugins/multipitch.c b/components/bl00mbox/plugins/multipitch.c new file mode 100644 index 0000000000000000000000000000000000000000..50ff80ec208050c8355b4df012a679765a6fe7a5 --- /dev/null +++ b/components/bl00mbox/plugins/multipitch.c @@ -0,0 +1,72 @@ +#include "multipitch.h" + +radspa_descriptor_t multipitch_desc = { + .name = "multipitch", + .id = 37, + .description = "takes a pitch input and provides a number of shifted outputs.\ninit_var: number of outputs, default 0", + .create_plugin_instance = multipitch_create, + .destroy_plugin_instance = radspa_standard_plugin_destroy +}; + +void multipitch_run(radspa_t * multipitch, uint16_t num_samples, uint32_t render_pass_id){ + bool output_request = false; + radspa_signal_t * thru_sig = radspa_signal_get_by_index(multipitch, 0); + if(thru_sig->buffer != NULL) output_request = true; + radspa_signal_t * input_sig = radspa_signal_get_by_index(multipitch, 1); + + uint8_t num_outputs = (multipitch->len_signals - 2)/2; + radspa_signal_t * output_sigs[num_outputs]; + radspa_signal_t * pitch_sigs[num_outputs]; + for(uint8_t j = 0; j < num_outputs; j++){ + output_sigs[j] = radspa_signal_get_by_index(multipitch, 2 + j); + pitch_sigs[j] = radspa_signal_get_by_index(multipitch, 3 + j); + if(output_sigs[j]->buffer != NULL) output_request = true; + } + if(!output_request) return; + + int32_t ret = 0; + int32_t rets[num_outputs]; + + for(uint16_t i = 0; i < num_samples; i++){ + int32_t input = input_sig->get_value(input_sig, i, num_samples, render_pass_id); + ret = input; + + if(thru_sig->buffer != NULL) (thru_sig->buffer)[i] = ret; + + int32_t pitch; + for(uint8_t j = 0; j < num_outputs; j++){ + pitch = pitch_sigs[j]->get_value(pitch_sigs[j], i, num_samples, render_pass_id); + rets[j] = pitch + input - RADSPA_SIGNAL_VAL_SCT_A440; + if(output_sigs[j]->buffer != NULL) (output_sigs[j]->buffer)[i] = rets[j]; + } + } + + // clang-tidy only, num_samples is always nonzero + if(!num_samples){ + for(uint8_t j = 0; j < num_outputs; j++){ + rets[j] = 0; + } + } + + for(uint8_t j = 0; j < num_outputs; j++){ + output_sigs[j]->value = rets[j]; + } + thru_sig->value = ret; +} + +radspa_t * multipitch_create(uint32_t init_var){ + if(init_var > 127) init_var = 127; + radspa_t * multipitch = radspa_standard_plugin_create(&multipitch_desc, 2 + 2*init_var, sizeof(int32_t), 0); + if(multipitch == NULL) return NULL; + multipitch->render = multipitch_run; + + radspa_signal_set(multipitch, 0, "thru", RADSPA_SIGNAL_HINT_OUTPUT | RADSPA_SIGNAL_HINT_SCT, RADSPA_SIGNAL_VAL_SCT_A440); + radspa_signal_set(multipitch, 1, "input", RADSPA_SIGNAL_HINT_INPUT | RADSPA_SIGNAL_HINT_SCT, RADSPA_SIGNAL_VAL_SCT_A440); + + radspa_signal_set_group(multipitch, init_var, 2, 2, "output", RADSPA_SIGNAL_HINT_OUTPUT | RADSPA_SIGNAL_HINT_SCT, + RADSPA_SIGNAL_VAL_SCT_A440); + radspa_signal_set_group(multipitch, init_var, 2, 3, "shift", RADSPA_SIGNAL_HINT_INPUT | RADSPA_SIGNAL_HINT_SCT, + RADSPA_SIGNAL_VAL_SCT_A440); + + return multipitch; +} diff --git a/components/bl00mbox/plugins/multipitch.h b/components/bl00mbox/plugins/multipitch.h new file mode 100644 index 0000000000000000000000000000000000000000..7e830c8024688eb2f3895353860a938b125e1add --- /dev/null +++ b/components/bl00mbox/plugins/multipitch.h @@ -0,0 +1,8 @@ +#pragma once +#include <radspa.h> +#include <radspa_helpers.h> + +extern radspa_descriptor_t multipitch_desc; +radspa_t * multipitch_create(uint32_t init_var); +void multipitch_run(radspa_t * osc, uint16_t num_samples, uint32_t render_pass_id); + diff --git a/components/bl00mbox/plugins/sampler.c b/components/bl00mbox/plugins/sampler.c index 8c7d65711c87edb8d2e89adb662f0b13f6805e02..e5ed7ac51fe442c3bf329cf560bb250cb048c14f 100644 --- a/components/bl00mbox/plugins/sampler.c +++ b/components/bl00mbox/plugins/sampler.c @@ -2,7 +2,7 @@ radspa_t * sampler_create(uint32_t init_var); radspa_descriptor_t sampler_desc = { - .name = "sampler_ram", + .name = "_sampler_ram", .id = 696969, .description = "simple sampler that stores a copy of the sample in ram", .create_plugin_instance = sampler_create, diff --git a/components/bl00mbox/plugins/sequencer.c b/components/bl00mbox/plugins/sequencer.c index 6bdaefb2aadabd7215b3699571957ea5ca317cbf..c137271430281f5430c86c4c32ee020d54df9766 100644 --- a/components/bl00mbox/plugins/sequencer.c +++ b/components/bl00mbox/plugins/sequencer.c @@ -1,9 +1,12 @@ #include "sequencer.h" radspa_descriptor_t sequencer_desc = { - .name = "sequencer", + .name = "_sequencer", .id = 56709, - .description = "i.o.u.", + .description = "sequencer that can output triggers or general control signals, best enjoyed through the " + "'sequencer' patch.\ninit_var: 1st byte (lsb): number of tracks, 2nd byte: number of steps" + "\ntable encoding (all int16_t): index 0: track type (-32767: trigger track, 32767: direct " + "track). next 'number of steps' indices: track data (repeat for number of tracks)", .create_plugin_instance = sequencer_create, .destroy_plugin_instance = radspa_standard_plugin_destroy }; @@ -22,67 +25,27 @@ static uint64_t target(uint64_t step_len, uint64_t bpm, uint64_t beat_div){ return (48000ULL * 60 * 4) / (bpm * beat_div); } -radspa_t * sequencer_create(uint32_t init_var){ - //init_var: - // lsbyte: number of channels - // lsbyte+1: number of pixels in channel (>= bars*beats_div) - uint32_t num_tracks = 1; - uint32_t num_pixels = 16; - if(init_var){ - num_tracks = init_var & 0xFF; - num_pixels = (init_var>>8) & 0xFF; - } - uint32_t table_size = num_tracks * (num_pixels + 1); - uint32_t num_signals = num_tracks + SEQUENCER_NUM_SIGNALS; //one for each channel output - radspa_t * sequencer = radspa_standard_plugin_create(&sequencer_desc, num_signals, sizeof(sequencer_data_t), table_size); - sequencer->render = sequencer_run; - +void sequencer_run(radspa_t * sequencer, uint16_t num_samples, uint32_t render_pass_id){ + bool output_request = false; sequencer_data_t * data = sequencer->plugin_data; - data->track_step_len = num_pixels; - data->num_tracks = num_tracks; - data->bpm_prev = 120; - data->beat_div_prev = 16; - data->counter_target = target(data->track_step_len, data->bpm_prev, data->beat_div_prev); - radspa_signal_set(sequencer, SEQUENCER_STEP, "step", RADSPA_SIGNAL_HINT_OUTPUT, 0); - radspa_signal_set(sequencer, SEQUENCER_STEP_LEN, "step_len", RADSPA_SIGNAL_HINT_INPUT, num_pixels); - radspa_signal_set(sequencer, SEQUENCER_SYNC_OUT, "sync_out", RADSPA_SIGNAL_HINT_OUTPUT, 0); - radspa_signal_set(sequencer, SEQUENCER_SYNC_IN, "sync_in", RADSPA_SIGNAL_HINT_INPUT | RADSPA_SIGNAL_HINT_TRIGGER, 0); - radspa_signal_set(sequencer, SEQUENCER_BPM, "bpm", RADSPA_SIGNAL_HINT_INPUT, data->bpm_prev); - radspa_signal_set(sequencer, SEQUENCER_BEAT_DIV, "beat_div", RADSPA_SIGNAL_HINT_INPUT, data->beat_div_prev); - radspa_signal_set(sequencer, SEQUENCER_OUTPUT, "output", RADSPA_SIGNAL_HINT_OUTPUT, 0); + radspa_signal_t * track_sigs[data->num_tracks]; - /* - for(uint8_t i = 0; i < num_signals; i++){ - radspa_signal_set(sequencer, SEQUENCER_NUM_SIGNALS + i, "track", RADSPA_SIGNAL_HINT_OUTPUT, 0); + for(uint8_t j = 0; j < data->num_tracks; j++){ + track_sigs[j] = radspa_signal_get_by_index(sequencer, SEQUENCER_OUTPUT+j); + if(track_sigs[j]->buffer != NULL) output_request = true; } - */ - - data->counter = 0; - data->sync_in_prev = 0; - data->sync_out = 32767; - - return sequencer; -} - -/* ~table encoding~ - * first int16_t: track type: - * -32767 : trigger track - * 32767 : direct track - * in between: slew rate - */ - -void sequencer_run(radspa_t * sequencer, uint16_t num_samples, uint32_t render_pass_id){ radspa_signal_t * step_sig = radspa_signal_get_by_index(sequencer, SEQUENCER_STEP); + if(step_sig->buffer != NULL) output_request = true; + radspa_signal_t * step_len_sig = radspa_signal_get_by_index(sequencer, SEQUENCER_STEP_LEN); radspa_signal_t * sync_out_sig = radspa_signal_get_by_index(sequencer, SEQUENCER_SYNC_OUT); - radspa_signal_t * output_sig = radspa_signal_get_by_index(sequencer, SEQUENCER_OUTPUT); - if((output_sig->buffer == NULL) && (sync_out_sig->buffer == NULL) && (step_sig->buffer == NULL)) return; + if(sync_out_sig->buffer != NULL) output_request = true; + if(!output_request) return; - radspa_signal_t * step_len_sig = radspa_signal_get_by_index(sequencer, SEQUENCER_STEP_LEN); radspa_signal_t * sync_in_sig = radspa_signal_get_by_index(sequencer, SEQUENCER_SYNC_IN); radspa_signal_t * bpm_sig = radspa_signal_get_by_index(sequencer, SEQUENCER_BPM); radspa_signal_t * beat_div_sig = radspa_signal_get_by_index(sequencer, SEQUENCER_BEAT_DIV); - sequencer_data_t * data = sequencer->plugin_data; + int16_t * table = sequencer->plugin_table; int16_t s1 = radspa_signal_get_value(step_len_sig, 0, num_samples, render_pass_id); @@ -117,24 +80,68 @@ void sequencer_run(radspa_t * sequencer, uint16_t num_samples, uint32_t render_p data->sync_in_prev = sync_in; if(!data->counter){ //event just happened - for(uint8_t track = 0; track < data->num_tracks; track++){ - int16_t type = table[track*data->track_step_len]; - int16_t stage_val = table[data->step + 1 + data->track_step_len * track]; + for(uint8_t j = 0; j < data->num_tracks; j++){ + int16_t type = table[j * (data->track_step_len + 1)]; + int16_t stage_val = table[data->step + 1 + (1 + data->track_step_len) * j]; if(type == 32767){ - data->track_fill[track] = stage_val; + data->tracks[j].track_fill = stage_val; } else if(type == -32767){ - if(stage_val > 0) data->track_fill[track] = radspa_trigger_start(stage_val, &(data->trigger_hist[track])); - if(stage_val < 0) data->track_fill[track] = radspa_trigger_stop(&(data->trigger_hist[track])); + if(stage_val > 0) data->tracks[j].track_fill = radspa_trigger_start(stage_val, &(data->tracks[j].trigger_hist)); + if(stage_val < 0) data->tracks[j].track_fill = radspa_trigger_stop(&(data->tracks[j].trigger_hist)); } } } - if(output_sig->buffer != NULL) (output_sig->buffer)[i] = data->track_fill[0]; + for(uint8_t j = 0; j < data->num_tracks; j++){ + if(track_sigs[j]->buffer != NULL) (track_sigs[j]->buffer)[i] = data->tracks[j].track_fill; + } if(sync_out_sig->buffer != NULL) (sync_out_sig->buffer)[i] = data->sync_out; if(step_sig->buffer != NULL) (step_sig->buffer)[i] = data->step; } } + for(uint8_t j = 0; j < data->num_tracks; j++){ + track_sigs[j]->value = data->tracks[j].track_fill; + } sync_out_sig->value = data->sync_out; - output_sig->value = data->track_fill[0]; step_sig->value = data->step; } + +radspa_t * sequencer_create(uint32_t init_var){ + uint32_t num_tracks = 4; + uint32_t num_pixels = 16; + if(init_var){ + num_tracks = init_var & 0xFF; + num_pixels = (init_var>>8) & 0xFF; + } + if(!num_tracks) return NULL; + if(!num_pixels) return NULL; + + uint32_t table_size = num_tracks * (num_pixels + 1); + uint32_t num_signals = num_tracks + SEQUENCER_NUM_SIGNALS; //one for each channel output + size_t data_size = sizeof(sequencer_data_t) + sizeof(sequencer_track_data_t) * (num_tracks - 1); + radspa_t * sequencer = radspa_standard_plugin_create(&sequencer_desc, num_signals, data_size, table_size); + if(sequencer == NULL) return NULL; + + sequencer->render = sequencer_run; + + sequencer_data_t * data = sequencer->plugin_data; + data->track_step_len = num_pixels; + data->num_tracks = num_tracks; + data->bpm_prev = 120; + data->beat_div_prev = 16; + data->counter_target = target(data->track_step_len, data->bpm_prev, data->beat_div_prev); + radspa_signal_set(sequencer, SEQUENCER_STEP, "step", RADSPA_SIGNAL_HINT_OUTPUT, 0); + radspa_signal_set(sequencer, SEQUENCER_STEP_LEN, "step_len", RADSPA_SIGNAL_HINT_INPUT, num_pixels); + radspa_signal_set(sequencer, SEQUENCER_SYNC_OUT, "sync_out", RADSPA_SIGNAL_HINT_OUTPUT, 0); + radspa_signal_set(sequencer, SEQUENCER_SYNC_IN, "sync_in", RADSPA_SIGNAL_HINT_INPUT | RADSPA_SIGNAL_HINT_TRIGGER, 0); + radspa_signal_set(sequencer, SEQUENCER_BPM, "bpm", RADSPA_SIGNAL_HINT_INPUT, data->bpm_prev); + radspa_signal_set(sequencer, SEQUENCER_BEAT_DIV, "beat_div", RADSPA_SIGNAL_HINT_INPUT, data->beat_div_prev); + radspa_signal_set_group(sequencer, data->num_tracks, 1, SEQUENCER_OUTPUT, "track", + RADSPA_SIGNAL_HINT_OUTPUT | RADSPA_SIGNAL_HINT_TRIGGER, 0); + + data->counter = 0; + data->sync_in_prev = 0; + data->sync_out = 32767; + + return sequencer; +} diff --git a/components/bl00mbox/plugins/sequencer.h b/components/bl00mbox/plugins/sequencer.h index a6b5748af15ae359ca111fc08feea3a9403792b8..bed48c15a79788bbb53ff5dc9ce8c24df14ba9ee 100644 --- a/components/bl00mbox/plugins/sequencer.h +++ b/components/bl00mbox/plugins/sequencer.h @@ -3,6 +3,11 @@ #include "radspa.h" #include "radspa_helpers.h" +typedef struct { + int16_t track_fill; + int16_t trigger_hist; +} sequencer_track_data_t; + typedef struct { uint8_t num_tracks; uint16_t track_step_len; @@ -14,10 +19,10 @@ typedef struct { int16_t sync_out; int16_t bpm_prev; int16_t beat_div_prev; - int16_t track_fill[1]; - int16_t trigger_hist[1]; + sequencer_track_data_t tracks[]; } sequencer_data_t; + extern radspa_descriptor_t sequencer_desc; radspa_t * sequencer_create(uint32_t init_var); void sequencer_run(radspa_t * osc, uint16_t num_samples, uint32_t render_pass_id); diff --git a/components/bl00mbox/radspa/radspa_helpers.c b/components/bl00mbox/radspa/radspa_helpers.c index 4d9f3d01d9a1d7be14eabb728cb09d3cc6b78f67..91b6deae494edb75de929075379ccedc2bdab132 100644 --- a/components/bl00mbox/radspa/radspa_helpers.c +++ b/components/bl00mbox/radspa/radspa_helpers.c @@ -1,12 +1,32 @@ //SPDX-License-Identifier: CC0-1.0 #include "radspa_helpers.h" +#define RADSPA_SIGNAL_CACHING + radspa_signal_t * radspa_signal_get_by_index(radspa_t * plugin, uint16_t signal_index){ - radspa_signal_t * ret = plugin->signals; - for(uint16_t i = 0; i < signal_index; i++){ - ret = ret->next; - if(ret == NULL) break; + radspa_signal_t * ret = NULL; + if(plugin == NULL) return ret; // clang-tidy +#ifdef RADSPA_SIGNAL_CACHING + static radspa_signal_t * cache_s = NULL; + static radspa_t * cache_p = NULL; + static uint16_t cache_i = 0; + + if((plugin == cache_p) && (signal_index == cache_i + 1) && (cache_s != NULL)){ + ret = cache_s->next; + } + if(ret == NULL){ +#endif + ret = plugin->signals; + for(uint16_t i = 0; i < signal_index; i++){ + ret = ret->next; + if(ret == NULL) break; + } +#ifdef RADSPA_SIGNAL_CACHING } + cache_s = ret; + cache_p = plugin; + cache_i = signal_index; +#endif return ret; } @@ -18,10 +38,16 @@ void radspa_signal_set(radspa_t * plugin, uint8_t signal_index, char * name, uin sig->value = value; } -void radspa_signal_set_group(radspa_t * plugin, uint8_t group_len, uint8_t signal_index, char * name, +void radspa_signal_set_description(radspa_t * plugin, uint8_t signal_index, char * description){ + radspa_signal_t * sig = radspa_signal_get_by_index(plugin, signal_index); + if(sig == NULL) return; + sig->description = description; +} + +void radspa_signal_set_group(radspa_t * plugin, uint8_t group_len, uint8_t step, uint8_t signal_index, char * name, uint32_t hints, int16_t value){ for(uint8_t i = 0; i < group_len; i++){ - radspa_signal_t * sig = radspa_signal_get_by_index(plugin, signal_index + i); + radspa_signal_t * sig = radspa_signal_get_by_index(plugin, signal_index + i * step); if(sig == NULL) return; sig->name = name; sig->hints = hints; @@ -30,6 +56,15 @@ void radspa_signal_set_group(radspa_t * plugin, uint8_t group_len, uint8_t signa } } +void radspa_signal_set_group_description(radspa_t * plugin, uint8_t group_len, uint8_t step, uint8_t signal_index, + char * description){ + for(uint8_t i = 0; i < group_len; i++){ + radspa_signal_t * sig = radspa_signal_get_by_index(plugin, signal_index + i * step); + if(sig == NULL) return; + sig->description = description; + } +} + int16_t radspa_signal_add(radspa_t * plugin, char * name, uint32_t hints, int16_t value){ radspa_signal_t * sig = calloc(1,sizeof(radspa_signal_t)); if(sig == NULL) return -1; // allocation failed diff --git a/components/bl00mbox/radspa/radspa_helpers.h b/components/bl00mbox/radspa/radspa_helpers.h index 11b9709ac5ae220e25891fd192a2129880cdc103..c8e3717629225ae671c5b073f694ed88c4feac9b 100644 --- a/components/bl00mbox/radspa/radspa_helpers.h +++ b/components/bl00mbox/radspa/radspa_helpers.h @@ -6,8 +6,11 @@ int16_t radspa_signal_add(radspa_t * plugin, char * name, uint32_t hints, int16_t value); // as above, but sets parameters of an already existing signal with at list position signal_index void radspa_signal_set(radspa_t * plugin, uint8_t signal_index, char * name, uint32_t hints, int16_t value); -void radspa_signal_set_group(radspa_t * plugin, uint8_t group_len, uint8_t signal_index, char * name, +void radspa_signal_set_group(radspa_t * plugin, uint8_t group_len, uint8_t step, uint8_t signal_index, char * name, uint32_t hints, int16_t value); +void radspa_signal_set_description(radspa_t * plugin, uint8_t signal_index, char * description); +void radspa_signal_set_group_description(radspa_t * plugin, uint8_t group_len, uint8_t step, uint8_t signal_index, + char * description); // get signal struct from a signal index diff --git a/python_payload/apps/simple_drums/__init__.py b/python_payload/apps/simple_drums/__init__.py index b17027a918623a190299dab34f1c1e15311c0640..b9ade9a3a060cfa9041b3a73fa25c93cb67fc0b2 100644 --- a/python_payload/apps/simple_drums/__init__.py +++ b/python_payload/apps/simple_drums/__init__.py @@ -41,7 +41,7 @@ class SimpleDrums(Application): super().__init__(app_ctx) # ctx.rgb(0, 0, 0).rectangle(-120, -120, 240, 240).fill() self.blm = bl00mbox.Channel("simple drums") - self.seq = self.blm.new(bl00mbox.patches.step_sequencer) + self.seq = self.blm.new(bl00mbox.patches.sequencer) self.hat = self.blm.new(bl00mbox.patches.sampler, "hihat.wav") # Dot(10, 10, -30, 0, self._track_col(0)).draw(0,ctx) self.kick = self.blm.new(bl00mbox.patches.sampler, "kick.wav") @@ -51,9 +51,9 @@ class SimpleDrums(Application): self.kick.signals.output = self.blm.mixer self.snare.signals.output = self.blm.mixer self.hat.signals.output = self.blm.mixer - self.kick.signals.trigger = self.seq.plugins.sequencer0.signals.output - self.hat.signals.trigger = self.seq.plugins.sequencer1.signals.output - self.snare.signals.trigger = self.seq.plugins.sequencer2.signals.output + self.kick.signals.trigger = self.seq.plugins.seq.signals.track0 + self.hat.signals.trigger = self.seq.plugins.seq.signals.track1 + self.snare.signals.trigger = self.seq.plugins.seq.signals.track2 self.seq.signals.bpm.value = 80 self.track_names = ["kick", "hihat", "snare"] diff --git a/python_payload/bl00mbox/_patches.py b/python_payload/bl00mbox/_patches.py index bf7fb5895b1171dbe9572d3bd995f20f69397ba2..97ea3bc24886f32090f73c8d761f0b74421dd467 100644 --- a/python_payload/bl00mbox/_patches.py +++ b/python_payload/bl00mbox/_patches.py @@ -17,8 +17,8 @@ class _Patch: def __repr__(self): ret = "[patch] " + type(self).__name__ - ret += "\n [signals:]\n " + "\n ".join(repr(self.signals).split("\n")) - ret += "\n [plugins:]\n " + "\n ".join(repr(self.plugins).split("\n")) + ret += "\n [signals:] " + "\n ".join(repr(self.signals).split("\n")) + ret += "\n [plugins:] " + "\n ".join(repr(self.plugins).split("\n")) return ret @@ -30,7 +30,12 @@ class _PatchItemList: return iter(self._items) def __repr__(self): - return "\n".join([x + ": " + repr(getattr(self, x)) for x in self._items]) + rets = "" + for x in self._items: + a = "\n" + repr(getattr(self, x)).split("]") + a[0] += ": " + x + ret += "]".join(a) + return ret def __setattr__(self, key, value): current_value = getattr(self, key, None) @@ -82,18 +87,20 @@ class tinysynth_fm(tinysynth): def __init__(self, chan): super().__init__(chan) self.plugins.mod_osc = self._channel.new(bl00mbox.plugins.osc_fm) + self.plugins.mult = self._channel.new(bl00mbox.plugins.multipitch, 1) self.plugins.mod_osc.signals.output = self.plugins.osc.signals.lin_fm self.signals.fm_waveform = self.plugins.mod_osc.signals.waveform - self.signals.fm_pitch = self.plugins.mod_osc.signals.pitch + self.plugins.mod_osc.signals.pitch = self.plugins.mult.signals.output0 + self.plugins.osc.signals.pitch = self.plugins.mult.signals.thru + + self.signals.fm = self.plugins.mult.signals.shift0 + self.signals.pitch = self.plugins.mult.signals.input self.signals.decay = 1000 self.signals.attack = 20 self.signals.waveform = -1 self.signals.fm_waveform = 0 - self.sync_mod_osc(2.5) - - def sync_mod_osc(self, val): - self.signals.fm_pitch.freq = int(val) * self.signals.pitch.freq + self.signals.fm = 3173 # weird but eh class sampler(_Patch): @@ -109,7 +116,7 @@ class sampler(_Patch): f = wave.open("/flash/sys/samples/" + filename, "r") self.len_frames = f.getnframes() - self.plugins.sampler = chan._new_plugin(696969, self.len_frames) + self.plugins.sampler = chan.new(bl00mbox.plugins._sampler_ram, self.len_frames) assert f.getsampwidth() == 2 assert f.getnchannels() in (1, 2) @@ -138,7 +145,7 @@ class sampler(_Patch): return self._filename -class step_sequencer(_Patch): +class sequencer(_Patch): def __init__(self, chan, num=4): super().__init__(chan) if num > 32: @@ -147,19 +154,16 @@ class step_sequencer(_Patch): num = 0 self.seqs = [] prev_seq = None - for i in range(num): - seq = chan._new_plugin(56709) - seq.table = [-32767] + ([0] * 16) - if prev_seq is None: - self.signals.bpm = seq.signals.bpm - self.signals.beat_div = seq.signals.beat_div - self.signals.step = seq.signals.step - self.signals.step_len = seq.signals.step_len - else: - prev_seq.signals.sync_out = seq.signals.sync_in - prev_seq = seq - self.seqs += [seq] - setattr(self.plugins, "sequencer" + str(i), seq) + self.num_pixels = 16 + self.num_tracks = num + init_var = (self.num_pixels * 256) + (self.num_tracks) # magic + self.plugins.seq = chan.new(bl00mbox.plugins._sequencer, init_var) + self.signals.bpm = self.plugins.seq.signals.bpm + self.signals.beat_div = self.plugins.seq.signals.beat_div + self.signals.step = self.plugins.seq.signals.step + self.signals.step_len = self.plugins.seq.signals.step_len + tracktable = [-32767] + ([0] * self.num_pixels) + self.plugins.seq.table = tracktable * self.num_tracks def __repr__(self): ret = "[patch] step sequencer" @@ -188,19 +192,22 @@ class step_sequencer(_Patch): ret += "\n" + "\n".join(super().__repr__().split("\n")[1:]) return ret + def _get_table_index(self, track, step): + return step + 1 + track * (self.num_pixels + 1) + def trigger_start(self, track, step): - a = self.seqs[track].table - a[step + 1] = 32767 - self.seqs[track].table = a + a = self.plugins.seq.table + a[self._get_table_index(track, step)] = 32767 + self.plugins.seq.table = a def trigger_stop(self, track, step): - a = self.seqs[track].table - a[step + 1] = 0 - self.seqs[track].table = a + a = self.plugins.seq.table + a[self._get_table_index(track, step)] = 0 + self.plugins.seq.table = a def trigger_state(self, track, step): - a = self.seqs[track].table - return a[step + 1] + a = self.plugins.seq.table + return a[self._get_table_index(track, step)] def trigger_toggle(self, track, step): if self.trigger_state(track, step) == 0: @@ -212,7 +219,7 @@ class step_sequencer(_Patch): class fuzz(_Patch): def __init__(self, chan): super().__init__(chan) - self.plugins.dist = chan.new(bl00mbox.plugins.distortion) + self.plugins.dist = chan.new(bl00mbox.plugins._distortion) self.signals.input = self.plugins.dist.signals.input self.signals.output = self.plugins.dist.signals.output self._intensity = 2 diff --git a/python_payload/mypystubs/bl00mbox/_patches.pyi b/python_payload/mypystubs/bl00mbox/_patches.pyi index 50581ef2e28c190f132425a3d21a718ce9284849..8ae4f41df8e1a2d9b4ffd5682a1a3519b6913768 100644 --- a/python_payload/mypystubs/bl00mbox/_patches.pyi +++ b/python_payload/mypystubs/bl00mbox/_patches.pyi @@ -25,8 +25,7 @@ class _PatchPluginList: class tinysynth(_Patch): ... class tinysynth_fm(tinysynth): ... -class step_sequencer(_Patch): - seqs: List[bl00mbox.Plugin] +class sequencer(_Patch): bpm: int def trigger_state(self, track: int, i: int) -> bool: ...