Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • flow3r/flow3r-firmware
  • Vespasian/flow3r-firmware
  • alxndr42/flow3r-firmware
  • pl/flow3r-firmware
  • Kari/flow3r-firmware
  • raimue/flow3r-firmware
  • grandchild/flow3r-firmware
  • mu5tach3/flow3r-firmware
  • Nervengift/flow3r-firmware
  • arachnist/flow3r-firmware
  • TheNewCivilian/flow3r-firmware
  • alibi/flow3r-firmware
  • manuel_v/flow3r-firmware
  • xeniter/flow3r-firmware
  • maxbachmann/flow3r-firmware
  • yGifoom/flow3r-firmware
  • istobic/flow3r-firmware
  • EiNSTeiN_/flow3r-firmware
  • gnudalf/flow3r-firmware
  • 999eagle/flow3r-firmware
  • toerb/flow3r-firmware
  • pandark/flow3r-firmware
  • teal/flow3r-firmware
  • x42/flow3r-firmware
  • alufers/flow3r-firmware
  • dos/flow3r-firmware
  • yrlf/flow3r-firmware
  • LuKaRo/flow3r-firmware
  • ThomasElRubio/flow3r-firmware
  • ai/flow3r-firmware
  • T_X/flow3r-firmware
  • highTower/flow3r-firmware
  • beanieboi/flow3r-firmware
  • Woazboat/flow3r-firmware
  • gooniesbro/flow3r-firmware
  • marvino/flow3r-firmware
  • kressnerd/flow3r-firmware
  • quazgar/flow3r-firmware
  • aoid/flow3r-firmware
  • jkj/flow3r-firmware
  • naomi/flow3r-firmware
41 results
Show changes
Commits on Source (27)
Showing
with 194 additions and 75 deletions
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## [Unreleased]
## [1.1.0] - 2023-08-17
### Added
- Added _Comic Mono_ font.
- Added a setting for automatically connecting to Camp WiFi.
- Added a *System**Get Apps* App for downloading apps directly from <https://flow3r.garden/apps/>.
- Added `ApplicationContext.bundle_path` so apps can find out what directory
they live in. This should be used for loading app assets from the correct
path.
- Added TLS support for MicroPython.
- Added modules for `.tar.gz` extraction.
- Added `aioble` module (Bluetooth Low Energy).
- Added line-in support to bl00mbox.
- Added pronoun support in the Nick app.
- Added color options in the Nick app.
- Added IMU-based rotation in the Nick app.
### Changed
- `ctx.get_font_name()` now raises an exception for unknown fonts.
- Raised umber of concurrent textures to 32.
### Fixed
- Fixed PNG without alpha and JPEG support by enabling `CTX_FORMAT_RGB8`.
- Fixed image cache eviction by introducing a ctx frameclock.
- Fixed incorrect merging of settings dicts in `st3m.settings`.
- Fixed some USB problems.
- Fixed sound filenames not working when they start with `/flash/` or `/sd/`.
- Fixed syntax errors in `flow3r.toml` crashing the menu.
## [1.0.0] - 2023-08-13
Initial Release
[unreleased]: https://git.flow3r.garden/flow3r/flow3r-firmware/-/compare/v1.1.0...main
[1.1.0]: https://git.flow3r.garden/flow3r/flow3r-firmware/-/compare/v1.0.0...v1.1.0
[1.0.0]: https://git.flow3r.garden/flow3r/flow3r-firmware/-/tags/v1.0.0
......@@ -21,11 +21,13 @@ idf_component_register(
plugins/lowpass.c
plugins/mixer.c
plugins/slew_rate_limiter.c
plugins/bl00mbox/bl00mbox_line_in.c
radspa/radspa_helpers.c
extern/xoroshiro64star.c
INCLUDE_DIRS
include
plugins
plugins/bl00mbox
radspa
extern
REQUIRES
......
......@@ -8,6 +8,8 @@ void bl00mbox_audio_disable(){ bl00mbox_audio_run = false; }
static uint32_t render_pass_id;
int16_t * bl00mbox_line_in_interlaced = NULL;
// fixed-length list of channels
static bl00mbox_channel_t channels[BL00MBOX_CHANNELS];
static int8_t last_chan_event = 0;
......@@ -97,7 +99,7 @@ bool bl00mbox_channel_set_free(uint8_t channel_index, bool free){
}
uint8_t bl00mbox_channel_get_free_index(){
uint8_t ret = 1;
uint8_t ret = 1; // never return system channel
for(; ret < BL00MBOX_CHANNELS; ret++){
if(bl00mbox_get_channel(ret)->is_free){
bl00mbox_get_channel(ret)->is_free = false;
......@@ -226,6 +228,7 @@ void bl00mbox_audio_render(int16_t * rx, int16_t * tx, uint16_t len){
render_pass_id++; // fresh pass, all relevant sources must be recomputed
uint16_t mono_len = len/2;
bl00mbox_line_in_interlaced = rx;
int16_t acc[mono_len];
// system channel always runs non-adding
bl00mbox_audio_channel_render(&(channels[0]), acc, mono_len, 0);
......
......@@ -101,6 +101,7 @@ radspa_descriptor_t * bl00mbox_plugin_registry_get_id_from_index(uint32_t index)
#include "mixer.h"
#include "multipitch.h"
#include "slew_rate_limiter.h"
#include "bl00mbox_line_in.h"
void bl00mbox_plugin_registry_init(void){
if(bl00mbox_plugin_registry_is_initialized) return;
......@@ -118,4 +119,5 @@ void bl00mbox_plugin_registry_init(void){
plugin_add(&mixer_desc);
plugin_add(&slew_rate_limiter_desc);
plugin_add(&multipitch_desc);
plugin_add(&bl00mbox_line_in_desc);
}
......@@ -705,6 +705,9 @@ int16_t bl00mbox_channel_bud_get_signal_value(uint8_t channel, uint32_t bud_inde
radspa_signal_t * sig = radspa_signal_get_by_index(bud->plugin, bud_signal_index);
if(sig == NULL) return false;
if((sig->hints & RADSPA_SIGNAL_HINT_OUTPUT) && (sig->buffer != NULL)){
return sig->buffer[0];
}
return sig->value;
}
......
......@@ -21,6 +21,8 @@ struct _bl00mbox_connection_source_t;
struct _bl00mbox_channel_root_t;
struct _bl00mbox_channel_t;
extern int16_t * bl00mbox_line_in_interlaced;
typedef struct _bl00mbox_bud_t{
radspa_t * plugin; // plugin
char * name;
......
......@@ -50,10 +50,8 @@ void ampliverter_run(radspa_t * ampliverter, uint16_t num_samples, uint32_t rend
ret = radspa_mult_shift(ret, gain);
ret = radspa_add_sat(ret, bias);
}
(output_sig->buffer)[i] = ret;
output_sig->set_value(output_sig, i, ret, num_samples, render_pass_id);
}
output_sig->value = ret;
}
radspa_t * ampliverter_create(uint32_t init_var){
......
#include "bl00mbox_line_in.h"
radspa_descriptor_t bl00mbox_line_in_desc = {
.name = "line_in",
.id = 4001,
.description = "connects to the line input of bl00mbox",
.create_plugin_instance = bl00mbox_line_in_create,
.destroy_plugin_instance = radspa_standard_plugin_destroy
};
void bl00mbox_line_in_run(radspa_t * line_in, uint16_t num_samples, uint32_t render_pass_id){
if(bl00mbox_line_in_interlaced == NULL) return;
radspa_signal_t * left_sig = radspa_signal_get_by_index(line_in, 0);
radspa_signal_t * right_sig = radspa_signal_get_by_index(line_in, 1);
radspa_signal_t * mid_sig = radspa_signal_get_by_index(line_in, 2);
radspa_signal_t * gain_sig = radspa_signal_get_by_index(line_in, 3);
for(uint16_t i = 0; i < num_samples; i++){
int32_t gain = gain_sig->get_value(gain_sig, i, num_samples, render_pass_id);
if(left_sig->buffer != NULL){
int16_t left = radspa_gain(bl00mbox_line_in_interlaced[2*i], gain);
left_sig->set_value(left_sig, i, left, num_samples, render_pass_id);
}
if(right_sig->buffer != NULL){
int16_t right = radspa_gain(bl00mbox_line_in_interlaced[2*i], gain);
right_sig->set_value(right_sig, i, right, num_samples, render_pass_id);
}
if(mid_sig->buffer != NULL){
int16_t mid = bl00mbox_line_in_interlaced[2*i]>>1;
mid += bl00mbox_line_in_interlaced[2*i]>>1;
mid = radspa_gain(mid, gain);
mid_sig->set_value(mid_sig, i, mid, num_samples, render_pass_id);
}
}
}
radspa_t * bl00mbox_line_in_create(uint32_t init_var){
radspa_t * line_in = radspa_standard_plugin_create(&bl00mbox_line_in_desc, 4, 0, 0);
if(line_in == NULL) return NULL;
line_in->render = bl00mbox_line_in_run;
radspa_signal_set(line_in, 0, "left", RADSPA_SIGNAL_HINT_OUTPUT, 0);
radspa_signal_set(line_in, 1, "right", RADSPA_SIGNAL_HINT_OUTPUT, 0);
radspa_signal_set(line_in, 2, "mid", RADSPA_SIGNAL_HINT_OUTPUT, 0);
radspa_signal_set(line_in, 3, "gain", RADSPA_SIGNAL_HINT_GAIN, RADSPA_SIGNAL_VAL_UNITY_GAIN);
return line_in;
}
#pragma once
#include "radspa.h"
#include "radspa_helpers.h"
// SPECIAL REQUIREMENTS
#include "bl00mbox_audio.h"
extern radspa_descriptor_t bl00mbox_line_in_desc;
radspa_t * bl00mbox_line_in_create(uint32_t init_var);
void bl00mbox_line_in_run(radspa_t * line_in, uint16_t num_samples, uint32_t render_pass_id);
......@@ -67,9 +67,8 @@ void delay_run(radspa_t * delay, uint16_t num_samples, uint32_t render_pass_id){
ret = radspa_add_sat(radspa_mult_shift(dry_vol,dry), radspa_mult_shift(wet,level));
(output_sig->buffer)[i] = ret;
output_sig->set_value(output_sig, i, ret, num_samples, render_pass_id);
}
output_sig->value = ret;
}
radspa_t * delay_create(uint32_t init_var){
......
......@@ -29,9 +29,8 @@ void distortion_run(radspa_t * distortion, uint16_t num_samples, uint32_t render
int32_t blend = input & ((1<<7)-1);
ret = dist[index]*((1<<7)-blend) + dist[index+1]*blend;
ret = ret >> 7;
(output_sig->buffer)[i] = ret;
output_sig->set_value(output_sig, i, ret, num_samples, render_pass_id);
}
output_sig->value = ret;
}
radspa_t * distortion_create(uint32_t init_var){
......
......@@ -129,10 +129,9 @@ void env_adsr_run(radspa_t * env_adsr, uint16_t num_samples, uint32_t render_pas
radspa_signal_t * release_sig = NULL;
radspa_signal_t * gate_sig = NULL;
int16_t ret = output_sig->value;
int16_t env = 0;
for(uint16_t i = 0; i < num_samples; i++){
static int16_t env = 0;
int16_t ret = 0;
int16_t trigger = trigger_sig->get_value(trigger_sig, i, num_samples, render_pass_id);
int16_t vel = radspa_trigger_get(trigger, &(plugin_data->trigger_prev));
......@@ -214,12 +213,8 @@ void env_adsr_run(radspa_t * env_adsr, uint16_t num_samples, uint32_t render_pas
if(env){
int16_t input = input_sig->get_value(input_sig, i, num_samples, render_pass_id);
ret = radspa_mult_shift(env, input);
} else {
ret = 0;
}
if(phase_sig->buffer != NULL) (phase_sig->buffer)[i] = plugin_data->env_phase;
if(output_sig->buffer != NULL) (output_sig->buffer)[i] = ret;
phase_sig->set_value(phase_sig, i, plugin_data->env_phase, num_samples, render_pass_id);
output_sig->set_value(output_sig, i, ret, num_samples, render_pass_id);
}
phase_sig->value = plugin_data->env_phase;
output_sig->value = ret;
}
......@@ -78,9 +78,8 @@ void flanger_run(radspa_t * flanger, uint16_t num_samples, uint32_t render_pass_
ret = radspa_add_sat(radspa_mult_shift(dry, dry_vol), radspa_mult_shift(radspa_clip(wet), mix));
ret = radspa_clip(radspa_gain(ret, level));
(output_sig->buffer)[i] = ret;
output_sig->set_value(output_sig, i, ret, num_samples, render_pass_id);
}
output_sig->value = ret;
}
radspa_t * flanger_create(uint32_t init_var){
......
......@@ -98,8 +98,6 @@ void lowpass_run(radspa_t * lowpass, uint16_t num_samples, uint32_t render_pass_
radspa_signal_t * q_sig = radspa_signal_get_by_index(lowpass, LOWPASS_Q);
radspa_signal_t * gain_sig = radspa_signal_get_by_index(lowpass, LOWPASS_GAIN);
static int16_t ret = 0;
for(uint16_t i = 0; i < num_samples; i++){
int16_t input = input_sig->get_value(input_sig, i, num_samples, render_pass_id);
int32_t freq = freq_sig->get_value(freq_sig, i, num_samples, render_pass_id);
......@@ -114,9 +112,8 @@ void lowpass_run(radspa_t * lowpass, uint16_t num_samples, uint32_t render_pass_
float out = apply_lowpass(data, input) + 0.5;
int16_t ret = radspa_clip(radspa_gain((int32_t) out, gain));
(output_sig->buffer)[i] = ret;
output_sig->set_value(output_sig, i, ret, num_samples, render_pass_id);
}
output_sig->value = ret;
}
radspa_t * lowpass_create(uint32_t real_init_var){
......
......@@ -31,9 +31,9 @@ void mixer_run(radspa_t * mixer, uint16_t num_samples, uint32_t render_pass_id){
// remove dc
(* dc_acc) = (ret + (* dc_acc)*1023) >> 10;
ret -= (* dc_acc);
(output_sig->buffer)[i] = radspa_clip(radspa_gain(ret, gain));
ret = radspa_clip(radspa_gain(ret, gain));
output_sig->set_value(output_sig, i, ret, num_samples, render_pass_id);
}
output_sig->value = ret;
}
radspa_t * mixer_create(uint32_t init_var){
......
......@@ -18,40 +18,27 @@ void multipitch_run(radspa_t * multipitch, uint16_t num_samples, uint32_t render
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);
output_sigs[j] = radspa_signal_get_by_index(multipitch, 2 + 2 * j);
pitch_sigs[j] = radspa_signal_get_by_index(multipitch, 3 + 2 * 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 ret = 0;
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;
thru_sig->set_value(thru_sig, i, ret, num_samples, render_pass_id);
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;
ret = pitch + input - RADSPA_SIGNAL_VAL_SCT_A440;
output_sigs[j]->set_value(output_sigs[j], i, ret, num_samples, render_pass_id);
}
}
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){
......
......@@ -16,12 +16,10 @@ void noise_run(radspa_t * noise, uint16_t num_samples, uint32_t render_pass_id){
radspa_signal_t * output_sig = radspa_signal_get_by_index(noise, NOISE_OUTPUT);
if(output_sig->buffer == NULL) return;
static int16_t ret = 0;
for(uint16_t i = 0; i < num_samples; i++){
(output_sig->buffer)[i] = radspa_random();
int16_t ret = radspa_random();
output_sig->set_value(output_sig, i, ret, num_samples, render_pass_id);
}
output_sig->value = ret;
}
radspa_t * noise_create(uint32_t init_var){
......
......@@ -38,9 +38,8 @@ void noise_burst_run(radspa_t * noise_burst, uint16_t num_samples, uint32_t rend
radspa_signal_t * trigger_sig = radspa_signal_get_by_index(noise_burst, NOISE_BURST_TRIGGER);
radspa_signal_t * length_ms_sig = radspa_signal_get_by_index(noise_burst, NOISE_BURST_LENGTH_MS);
int16_t ret = output_sig->value;
for(uint16_t i = 0; i < num_samples; i++){
int16_t ret = 0;
int16_t trigger = trigger_sig->get_value(trigger_sig, i, num_samples, render_pass_id);
int16_t vel = radspa_trigger_get(trigger, &(plugin_data->trigger_prev));
......@@ -55,10 +54,7 @@ void noise_burst_run(radspa_t * noise_burst, uint16_t num_samples, uint32_t rend
if(plugin_data->counter < plugin_data->limit){
ret = radspa_random();
plugin_data->counter++;
} else {
ret = 0;
}
if(output_sig->buffer != NULL) (output_sig->buffer)[i] = ret;
output_sig->set_value(output_sig, i, ret, num_samples, render_pass_id);
}
output_sig->value = ret;
}
......@@ -52,9 +52,8 @@ void osc_fm_run(radspa_t * osc_fm, uint16_t num_samples, uint32_t render_pass_id
int32_t tmp = (plugin_data->counter) >> 17;
tmp = (tmp*2) - 32767;
ret = waveshaper(tmp, wave);
(output_sig->buffer)[i] = ret;
output_sig->set_value(output_sig, i, ret, num_samples, render_pass_id);
}
output_sig->value = ret;
}
static inline int16_t triangle(int16_t saw){
......
......@@ -4,14 +4,16 @@ radspa_t * sampler_create(uint32_t init_var);
radspa_descriptor_t sampler_desc = {
.name = "_sampler_ram",
.id = 696969,
.description = "simple sampler that stores a copy of the sample in ram",
.description = "simple sampler that stores a copy of the sample in ram and has basic recording functionality",
.create_plugin_instance = sampler_create,
.destroy_plugin_instance = radspa_standard_plugin_destroy
};
#define SAMPLER_NUM_SIGNALS 2
#define SAMPLER_NUM_SIGNALS 4
#define SAMPLER_OUTPUT 0
#define SAMPLER_TRIGGER 1
#define SAMPLER_REC_IN 2
#define SAMPLER_REC_TRIGGER 3
void sampler_run(radspa_t * sampler, uint16_t num_samples, uint32_t render_pass_id){
radspa_signal_t * output_sig = radspa_signal_get_by_index(sampler, SAMPLER_OUTPUT);
......@@ -19,35 +21,61 @@ void sampler_run(radspa_t * sampler, uint16_t num_samples, uint32_t render_pass_
sampler_data_t * data = sampler->plugin_data;
int16_t * buf = sampler->plugin_table;
radspa_signal_t * trigger_sig = radspa_signal_get_by_index(sampler, SAMPLER_TRIGGER);
radspa_signal_t * rec_in_sig = radspa_signal_get_by_index(sampler, SAMPLER_REC_IN);
radspa_signal_t * rec_trigger_sig = radspa_signal_get_by_index(sampler, SAMPLER_REC_TRIGGER);
static int32_t ret = 0;
uint32_t buffer_size = sampler->plugin_table_len;
for(uint16_t i = 0; i < num_samples; i++){
int16_t rec_trigger = radspa_trigger_get(rec_trigger_sig->get_value(rec_trigger_sig, i, num_samples, render_pass_id), &(data->rec_trigger_prev));
int16_t trigger = radspa_trigger_get(trigger_sig->get_value(trigger_sig, i, num_samples, render_pass_id), &(data->trigger_prev));
int16_t trigger = trigger_sig->get_value(trigger_sig, i, num_samples, render_pass_id);
int16_t vel = radspa_trigger_get(trigger, &(data->trigger_prev));
if(vel > 0){
data->read_head_position = 0;
data->volume = vel;
} else if(vel < 0){
data->read_head_position = buffer_size;
if(rec_trigger > 0){
if(!(data->rec_active)){
data->read_head_position = data->sample_len; // reset sample player into off
data->write_head_position = 0;
data->sample_len = 0;
data->rec_active = true;
}
} else if(rec_trigger < 0){
if(data->rec_active){
if(data->sample_len == buffer_size){
data->sample_start = data->write_head_position;
} else {
data->sample_start = 0;
}
data->rec_active = false;
}
}
if(data->read_head_position < buffer_size){
ret = radspa_mult_shift(buf[data->read_head_position], data->volume);
data->read_head_position++;
if(data->rec_active){
int16_t rec_in = rec_in_sig->get_value(rec_in_sig, i, num_samples, render_pass_id);
buf[data->write_head_position] = rec_in;
data->write_head_position++;
if(data->write_head_position >= buffer_size) data->write_head_position = 0;
if(data->sample_len < buffer_size) data->sample_len++;
} else {
//ret = (ret * 255)>>8; // avoid dc clicks with bad samples
ret = 0;
}
if(trigger > 0){
data->read_head_position = 0;
data->volume = trigger;
} else if(trigger < 0){
data->read_head_position = data->sample_len;
}
(output_sig->buffer)[i] = ret;
if(data->read_head_position < data->sample_len){
uint32_t sample_offset_pos = data->read_head_position + data->sample_start;
if(sample_offset_pos >= data->sample_len) sample_offset_pos -= data->sample_len;
ret = radspa_mult_shift(buf[sample_offset_pos], data->volume);
data->read_head_position++;
} else {
//ret = (ret * 255)>>8; // avoid dc clicks with bad samples
ret = 0;
}
output_sig->set_value(output_sig, i, ret, num_samples, render_pass_id);
}
}
output_sig->value = ret;
}
radspa_t * sampler_create(uint32_t init_var){
......@@ -58,5 +86,13 @@ radspa_t * sampler_create(uint32_t init_var){
sampler->render = sampler_run;
radspa_signal_set(sampler, SAMPLER_OUTPUT, "output", RADSPA_SIGNAL_HINT_OUTPUT, 0);
radspa_signal_set(sampler, SAMPLER_TRIGGER, "trigger", RADSPA_SIGNAL_HINT_INPUT | RADSPA_SIGNAL_HINT_TRIGGER, 0);
radspa_signal_set(sampler, SAMPLER_REC_IN, "rec_in", RADSPA_SIGNAL_HINT_INPUT, 0);
radspa_signal_set(sampler, SAMPLER_REC_TRIGGER, "rec_trigger", RADSPA_SIGNAL_HINT_INPUT | RADSPA_SIGNAL_HINT_TRIGGER, 0);
sampler_data_t * data = sampler->plugin_data;
data->trigger_prev = 0;
data->rec_trigger_prev = 0;
data->rec_active = false;
data->sample_start = 0;
data->sample_len = sampler->plugin_table_len;
return sampler;
}