Skip to content
Snippets Groups Projects
Commit 65f14260 authored by moon2's avatar moon2 :speech_balloon:
Browse files

bl00mbox updates

parent 63c44a11
Branches
Tags
No related merge requests found
......@@ -242,10 +242,7 @@ class sampler(_Patch):
class sequencer(_Patch):
def __init__(self, chan, num_tracks, num_steps):
super().__init__(chan)
self.num_steps = num_steps
self.num_tracks = num_tracks
init_var = (self.num_steps * 256) + (self.num_tracks) # magic
self.plugins.seq = chan.new(bl00mbox.plugins.sequencer, init_var)
self.plugins.seq = chan.new(bl00mbox.plugins.sequencer, num_tracks, num_steps)
self.signals.bpm = self.plugins.seq.signals.bpm
self.signals.beat_div = self.plugins.seq.signals.beat_div
......@@ -254,6 +251,8 @@ class sequencer(_Patch):
self.signals.step_start = self.plugins.seq.signals.step_start
self.signals.sync_in = self.plugins.seq.signals.sync_in
self.num_tracks = num_tracks
self.num_steps = num_steps
tracktable = [-32767] + ([0] * self.num_steps)
self.plugins.seq.table = tracktable * self.num_tracks
......@@ -380,28 +379,28 @@ class karplus_strong(_Patch):
self.plugins.flanger = chan._new_plugin(bl00mbox.plugins.flanger)
self.plugins.flanger.signals.resonance = 32500
self.plugins.flanger.signals.resonance = 0
self.plugins.flanger.signals.decay = 1000
self.plugins.flanger.signals.manual.tone = "A2"
self.plugins.flanger.signals.input = self.plugins.noise.signals.output
self.signals.trigger = self.plugins.noise.signals.trigger
self.signals.trigger_length = self.plugins.noise.signals.length
self.signals.pitch = self.plugins.flanger.signals.manual
self.signals.output = self.plugins.flanger.signals.output
self.signals.level = self.plugins.flanger.signals.level
self.signals.decay = self.plugins.flanger.signals.decay
self.decay = 1000
self.signals.resonance = self.plugins.flanger.signals.resonance
@property
def decay(self):
return self._decay
# deprecated
return self.plugins.flanger.signals.decay.value
@decay.setter
def decay(self, val):
tone = self.plugins.flanger.signals.manual.tone
loss = (50 * (2 ** (-tone / 12))) // (val / 1000)
if loss < 2:
loss = 2
self.plugins.flanger.signals.resonance = 32767 - loss
self._decay = val
# deprecated
self.plugins.flanger.signals.resonance = -2
self.plugins.flanger.signals.decay = int(val)
......@@ -39,10 +39,12 @@ def _fill():
for name, value in plugins_list.items():
setattr(plugins, name, _PluginDescriptor(value))
# legacy
if name == "sequencer":
if name == "sequencer" or name == "distortion":
setattr(plugins, "_" + name, _PluginDescriptor(value))
if name == "sampler":
elif name == "sampler":
setattr(plugins, "_sampler_ram", _PluginDescriptor(value))
elif name == "delay_static":
setattr(plugins, "delay", _PluginDescriptor(value))
_fill()
......@@ -431,12 +433,12 @@ class _Sampler(_Plugin):
table[self._SAMPLE_RATE] = int(val)
"""
@_plugin_set_subclass(9000)
class _Distortion(_Plugin):
def symmetric_power(self, power=2, volume=32767, gate=0):
table = list(range(129))
for num in table:
def curve_set_power(self, power=2, volume=32767, gate=0):
volume = min(max(volume, -32767), 32767)
table = [0] * 129
for num in range(len(table)):
if num < 64:
ret = num / 64 # scale to [0..1[ range
ret = ret**power
......@@ -447,11 +449,46 @@ class _Distortion(_Plugin):
ret = (128 - num) / 64 # scale to [0..1] range
ret = ret**power
table[num] = int(volume * (1 - ret))
gate = int(gate) >> 9
gate = min(abs(int(gate)), 32767) >> 9
for i in range(64 - gate, 64 + gate):
table[i] = 0
self.table = table
@property
def _secret_sauce(self):
table = self.table_int16_array
return table[129]
@_secret_sauce.setter
def _secret_sauce(self, val):
val = min(max(int(val), 0), 7)
table = self.table_int16_array
table[129] = val
@property
def curve(self):
return self.table[:129]
@curve.setter
def curve(self, points):
# interpolation only implemented for len(points) <= 129,
# for longer lists data may be dropped.
points_size = len(points)
if not points_size:
return
table = [0] * 129
for x, num in enumerate(table):
position = x * points_size / 129
lower = int(position)
lerp = position - lower
if position < points_size - 1:
table[x] = int(
(1 - lerp) * points[position] + lerp * points[position + 1]
)
else:
table[x] = int(points[points_size - 1])
self.table = table
def __repr__(self):
ret = super().__repr__()
wave = self.table[:129]
......@@ -475,7 +512,18 @@ class _Distortion(_Plugin):
ret += line
ret += " |" + "_" * 67 + "|"
return ret
"""
@_plugin_set_subclass(172)
class _PolySqueeze(_Plugin):
def __init__(self, channel, plugin_id, bud_num, num_outputs=3, num_inputs=10):
if bud_num is None:
outs = min(max(num_outputs, 16), 1)
ins = min(max(num_inputs, 32), num_outputs)
init_var = outs + (ins * 256)
super().__init__(channel, plugin_id, init_var=init_var)
else:
super().__init__(channel, plugin_id, bud_num=bud_num)
@_plugin_set_subclass(420)
......@@ -516,15 +564,11 @@ class _Osc(_Plugin):
@_plugin_set_subclass(56709)
class _Sequencer(_Plugin):
def __init__(self, channel, plugin_id, bud_num, init_var=None, tracks=4, steps=16):
def __init__(self, channel, plugin_id, bud_num, num_tracks=4, num_steps=16):
if bud_num is None:
if init_var is None:
self.num_steps = steps % 256
self.num_tracks = tracks % 256
self.num_steps = num_steps % 256
self.num_tracks = num_tracks % 256
init_var = (self.num_steps * 256) + (self.num_tracks)
else:
self.num_tracks = init_var % 256
self.num_steps = (init_var // 256) % 256
super().__init__(channel, plugin_id, init_var=init_var)
......@@ -593,3 +637,37 @@ class _Sequencer(_Plugin):
self.trigger_start(track, step)
else:
self.trigger_clear(track, step)
def save_track_pattern(self, track_index):
start = track_index * (self.num_steps + 1)
stop = start + self.num_steps + 1
track = {}
table = self.table
if self.table[start] == -32767:
track["type"] = "trigger"
else:
track["type"] = "value"
track["steps"] = list(table[start + 1 : stop])
return track
def load_track_pattern(self, track, track_index):
start = track_index * (self.num_steps + 1)
table = self.table_int16_array
stop = start + 1 + min(self.num_steps, len(track["steps"]))
for i in range(start + 1, stop):
x = track["steps"][i - start - 1]
assert (x < 32768) and (x > -32768)
table[i] = x
if track["type"] == "trigger":
table[start] = -32767
else:
table[start] = 32767
def save_pattern(self):
beat = {}
beat["tracks"] = [self.save_track_pattern(i) for i in range(self.num_tracks)]
return beat
def load_pattern(self, beat):
num_tracks = min(len(beat["tracks"]), self.num_tracks)
[self.load_track_pattern(beat["tracks"][i], i) for i in range(num_tracks)]
......@@ -2,7 +2,7 @@
radspa_t * delay_create(uint32_t init_var);
radspa_descriptor_t delay_desc = {
.name = "delay",
.name = "delay_static",
.id = 42069,
.description = "simple delay with ms input and feedback\n"
"init_var: delay buffer length in ms, default 500",
......
......@@ -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,
......@@ -13,28 +13,36 @@ radspa_descriptor_t distortion_desc = {
#define DISTORTION_OUTPUT 0
#define DISTORTION_INPUT 1
static inline int32_t distort(int32_t input, int16_t * dist, uint8_t lerp_glitch){
// lerp glitch is a legacy feature from a math error of the 0th gen
// pass 9 normally, pass 7 for legacy glitch
input += 32768;
uint8_t index = input >> 9;
int32_t blend = input & ((1<<lerp_glitch)-1);
int32_t ret = dist[index]*((1<<lerp_glitch)-blend) + dist[index+1]*blend;
return ret >> lerp_glitch;
}
void distortion_run(radspa_t * distortion, uint16_t num_samples, uint32_t render_pass_id){
radspa_signal_t * output_sig = radspa_signal_get_by_index(distortion, DISTORTION_OUTPUT);
if(output_sig->buffer == NULL) return;
int16_t * dist = distortion->plugin_table;
radspa_signal_t * input_sig = radspa_signal_get_by_index(distortion, DISTORTION_INPUT);
static int32_t ret = 0;
int32_t input = radspa_signal_get_const_value(input_sig, render_pass_id);
uint8_t lerp_glitch = 9 - ((dist[129]) & 7); // legacy glitch
if(input != RADSPA_SIGNAL_NONCONST){
radspa_signal_set_const_value(output_sig, distort(input, dist, lerp_glitch));
} else {
for(uint16_t i = 0; i < num_samples; i++){
int32_t input = radspa_signal_get_value(input_sig, i, render_pass_id);
input += 32768;
uint8_t index = input>>9;
int32_t blend = input & ((1<<7)-1);
ret = dist[index]*((1<<7)-blend) + dist[index+1]*blend;
ret = ret >> 7;
radspa_signal_set_value(output_sig, i, ret);
radspa_signal_set_value(output_sig, i, distort(input, dist, lerp_glitch));
}
}
}
radspa_t * distortion_create(uint32_t init_var){
radspa_t * distortion = radspa_standard_plugin_create(&distortion_desc, DISTORTION_NUM_SIGNALS, 0, (1<<7) + 1);
radspa_t * distortion = radspa_standard_plugin_create(&distortion_desc, DISTORTION_NUM_SIGNALS, 0, (1<<7) + 2);
if(distortion == NULL) return NULL;
distortion->render = distortion_run;
radspa_signal_set(distortion, DISTORTION_OUTPUT, "output", RADSPA_SIGNAL_HINT_OUTPUT, 0);
......@@ -49,6 +57,7 @@ radspa_t * distortion_create(uint32_t init_var){
dist[i] = -((128-i)*(128-i)*32767>>12) + 32767;
}
}
dist[129] = 0;
return distortion;
}
......@@ -22,6 +22,8 @@ radspa_descriptor_t filter_desc = {
#define FILTER_MODE_BANDPASS 1
#define FILTER_MODE_HIGHPASS 2
#define INV_NORM_BOOST 5
static inline int32_t approx_cos(uint32_t x){
// x: full circle: 1<<32
// return val: 1<<30 <=> 1
......@@ -37,17 +39,17 @@ static inline int32_t approx_cos(uint32_t x){
static inline void get_mode_coeffs(uint8_t mode, filter_data_t * data, int32_t * coeffs){
switch(mode){
case FILTER_MODE_LOWPASS:
coeffs[1] = ((1L<<21) - data->cos_omega) * data->inv_norm;
coeffs[0] = coeffs[1]/2;
coeffs[1] = ((((1L<<21) - data->cos_omega)>>INV_NORM_BOOST) * data->inv_norm)>>1;
coeffs[0] = coeffs[1]>>1;
coeffs[2] = coeffs[0];
break;
case FILTER_MODE_BANDPASS:
coeffs[0] = data->alpha * data->inv_norm;
coeffs[0] = (data->alpha>>INV_NORM_BOOST) * data->inv_norm;
coeffs[1] = 0;
coeffs[2] = -coeffs[0];
break;
case FILTER_MODE_HIGHPASS:
coeffs[1] = -((1L<<21) + data->cos_omega) * data->inv_norm;
coeffs[1] = ((-((1L<<21) + data->cos_omega)>>INV_NORM_BOOST) * data->inv_norm)>>1;
coeffs[0] = -coeffs[1]/2;
coeffs[2] = coeffs[0];
break;
......@@ -64,29 +66,28 @@ static inline void get_coeffs(filter_data_t * data, int16_t pitch, int16_t reso,
if(freq > (3UL<<29)) freq = 3UL<<29;
// unit: 1<<21 <=> 1, range: [0..1<<21]
data->cos_omega = approx_cos(freq)>>9;
int32_t cos_omega = approx_cos(freq)>>9;
// unit: 1<<21 <=> 1, range: [0..3<<21]
data->alpha = approx_cos(freq + (3UL<<30))/mqi;
// unit transform from 1<<21 to 1<<29 <=> 1
data->inv_norm = (1L<<29)/((1L<<21) + data->alpha);
int32_t alpha = approx_cos(freq + (3UL<<30))/mqi;
// unit transform from 1<<21 to 1<<30 <=> 1
int32_t inv_norm = (1L<<30)/(((1L<<(21)) + alpha)>>INV_NORM_BOOST);
data->cos_omega = cos_omega;
data->alpha = alpha;
data->inv_norm = inv_norm;
data->pitch_prev = pitch;
data->reso_prev = reso;
}
if((pitch != data->pitch_prev) || (reso != data->reso_prev) || (mode != data->mode_prev)){
// unit for {in/out}_coeffs: 1<<29 <=> 1, range: full
data->out_coeffs[1] = -2*data->cos_omega * data->inv_norm;
data->out_coeffs[2] = ((1<<21) - data->alpha) * data->inv_norm;
data->out_coeffs[1] = (-data->cos_omega>>INV_NORM_BOOST) * data->inv_norm;
data->out_coeffs[2] = ((((1<<21) - data->alpha)>>INV_NORM_BOOST) * data->inv_norm) >> 1;
if(mode == -32767){
get_mode_coeffs(FILTER_MODE_LOWPASS, data, data->in_coeffs);
return;
} else if(mode == 0){
get_mode_coeffs(FILTER_MODE_BANDPASS, data, data->in_coeffs);
return;
} else if(mode == 32767){
get_mode_coeffs(FILTER_MODE_HIGHPASS, data, data->in_coeffs);
return;
}
} else {
int32_t a[3];
int32_t b[3];
int32_t blend = mode;
......@@ -106,6 +107,15 @@ static inline void get_coeffs(filter_data_t * data, int16_t pitch, int16_t reso,
}
data->const_output = RADSPA_SIGNAL_NONCONST;
}
/*
printf("cos_omega: %ld alpha: %ld inv_norm: %ld\n",data->cos_omega, data->alpha, data->inv_norm);
printf("in_coeffs: %ld %ld %ld\n",data->in_coeffs[0], data->in_coeffs[1], data->in_coeffs[2]);
printf("out_coeffs: %ld %ld\n", data->out_coeffs[1], data->out_coeffs[2]);
*/
}
data->pitch_prev = pitch;
data->reso_prev = reso;
data->mode_prev = mode;
}
void filter_run(radspa_t * filter, uint16_t num_samples, uint32_t render_pass_id){
......@@ -131,7 +141,7 @@ void filter_run(radspa_t * filter, uint16_t num_samples, uint32_t render_pass_id
int16_t reso = reso_const;
int16_t mode = mode_const;
int16_t mix = mix_const;
int16_t input = input_const;
int32_t input = input_const;
bool always_update_coeffs = true;
if((pitch_const != RADSPA_SIGNAL_NONCONST) && (reso_const != RADSPA_SIGNAL_NONCONST) && (mode_const != RADSPA_SIGNAL_NONCONST)){
......@@ -159,12 +169,11 @@ void filter_run(radspa_t * filter, uint16_t num_samples, uint32_t render_pass_id
}
if(input_const == RADSPA_SIGNAL_NONCONST) input = radspa_signal_get_value(input_sig, i, render_pass_id);
int32_t in = radspa_clip(radspa_gain(input, gain));
data->pos++;
if(data->pos >= 3) data->pos = 0;
data->in_history[data->pos] = in << 12;
data->in_history[data->pos] = input << 12;
int32_t ret = ((int64_t) data->in_coeffs[0] * data->in_history[data->pos]) >> 32;
......@@ -179,10 +188,9 @@ void filter_run(radspa_t * filter, uint16_t num_samples, uint32_t render_pass_id
} else if(ret <= -(1L<<28)){
ret = 1-(1L<<28);
}
ret = ret << 3;
data->out_history[data->pos] = ret;
data->out_history[data->pos] = ret << 3;
ret = ret >> 12;
ret = ret >> 9;
if(reso < 0) ret = input - (ret<<1); //allpass mode
if(mix == -32767){
......@@ -192,10 +200,10 @@ void filter_run(radspa_t * filter, uint16_t num_samples, uint32_t render_pass_id
} else if(mix != 32767){
ret *= mix;
int32_t dry_vol = mix > 0 ? 32767 - mix : 32767 + mix;
ret += radspa_gain(dry_vol, gain) * input;
ret += dry_vol * input;
ret = ret >> 15;
}
out[i] = radspa_clip(ret);
out[i] = radspa_clip(radspa_gain(ret, gain));
}
if(input_const == RADSPA_SIGNAL_NONCONST){
......
......@@ -22,13 +22,13 @@ radspa_descriptor_t flanger_desc = {
#define FLANGER_LEVEL 5
#define FLANGER_MIX 6
static inline int16_t fixed_point_list_access(int32_t * buf, uint32_t fp_index, uint32_t buf_len){
uint32_t index = (fp_index) >> (FIXED_POINT_DIGITS);
static inline int32_t fixed_point_list_access(int32_t * buf, int32_t fp_index, uint32_t buf_len){
int32_t index = (fp_index) >> (FIXED_POINT_DIGITS);
while(index >= buf_len) index -= buf_len;
uint32_t next_index = index + 1;
int32_t next_index = index + 1;
while(next_index >= buf_len) next_index -= buf_len;
uint32_t subindex = (fp_index) & ((1<<(FIXED_POINT_DIGITS)) - 1);
int32_t subindex = (fp_index) & ((1<<(FIXED_POINT_DIGITS)) - 1);
int32_t ret = buf[index] * ((1<<(FIXED_POINT_DIGITS)) - subindex);
ret += (buf[next_index]) * subindex;
ret = ret >> (FIXED_POINT_DIGITS);
......@@ -61,7 +61,7 @@ void flanger_run(radspa_t * flanger, uint16_t num_samples, uint32_t render_pass_
radspa_signal_t * mix_sig = radspa_signal_get_by_index(flanger, FLANGER_MIX);
int32_t reso = radspa_signal_get_value(reso_sig, 0, render_pass_id);
reso = reso << 16;
reso = reso << 14;
int32_t level = radspa_signal_get_value(level_sig, 0, render_pass_id);
int32_t mix = radspa_signal_get_value(mix_sig, 0, render_pass_id);
int32_t decay = radspa_signal_get_value(decay_sig, 0, render_pass_id);
......@@ -78,9 +78,9 @@ void flanger_run(radspa_t * flanger, uint16_t num_samples, uint32_t render_pass_
int32_t sgn_decay = decay > 0 ? 1 : -1;
int32_t abs_decay = decay * sgn_decay;
if((abs_decay != data->abs_decay_prev) || (manual != data->manual_prev)){
int32_t decay_invert = - ((data->read_head_offset * 50) >> FIXED_POINT_DIGITS)/decay;
decay_invert += 34614; // magic number
data->decay_reso = radspa_sct_to_rel_freq(radspa_clip(decay_invert), 0) >> 1;
int32_t decay_invert = - ((data->read_head_offset * 50) >> FIXED_POINT_DIGITS)/abs_decay;
decay_invert += 34614 - 4800 - 2400; // magic number
data->decay_reso = radspa_sct_to_rel_freq(radspa_clip(decay_invert), 0);
}
int32_t tmp = reso + sgn_decay * data->decay_reso;
if((sgn_decay == 1) && (tmp < reso)){
......@@ -103,8 +103,14 @@ void flanger_run(radspa_t * flanger, uint16_t num_samples, uint32_t render_pass_
while(data->read_head_position < 0) data->read_head_position += VARIABLE_NAME; //underflow
buf[data->write_head_position] = dry;
int32_t wet = fixed_point_list_access(buf, data->read_head_position, FLANGER_BUFFER_SIZE) << 1;
int32_t wet = fixed_point_list_access(buf, data->read_head_position, FLANGER_BUFFER_SIZE) << 3;
bool sgn_wet = wet > 0;
bool sgn_reso = reso > 0;
if(sgn_wet != sgn_reso){
buf[data->write_head_position] -= ((int64_t) (-wet) * reso) >> 32;
} else {
buf[data->write_head_position] += ((int64_t) wet * reso) >> 32;
}
int32_t ret = radspa_add_sat(radspa_mult_shift(dry, dry_vol), radspa_mult_shift(radspa_clip(wet), mix));
ret = radspa_clip(radspa_gain(ret, level));
......
......@@ -86,7 +86,7 @@ void mixer_run(radspa_t * mixer, uint16_t num_samples, uint32_t render_pass_id){
for(uint16_t i = 0; i < num_samples; i++){
bool invert = data->dc < 0;
if(invert) data->dc = -data->dc;
data->dc = ((uint64_t) data->dc * (((1<<12) - 1)<<20)) >> 32;
data->dc = ((uint64_t) data->dc * (((1UL<<12) - 1)<<20)) >> 32;
if(invert) data->dc = -data->dc;
data->dc += ret[i];
ret[i] -= (data->dc >> 12);
......@@ -96,7 +96,7 @@ void mixer_run(radspa_t * mixer, uint16_t num_samples, uint32_t render_pass_id){
for(uint16_t i = 0; i < num_samples; i++){
bool invert = data->dc < 0;
if(invert) data->dc = -data->dc;
data->dc = ((uint64_t) data->dc * (((1<<12) - 1)<<20)) >> 32;
data->dc = ((uint64_t) data->dc * (((1UL<<12) - 1)<<20)) >> 32;
if(invert) data->dc = -data->dc;
ret[i] = -(data->dc >> 12);
ret_init = true;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment