Started splitting out synth into separate channel objects
This commit is contained in:
parent
882f76dcbc
commit
53dfb9866d
|
@ -444,6 +444,11 @@ namespace pimoroni {
|
|||
}
|
||||
}
|
||||
|
||||
AudioChannel& GalacticUnicorn::synth_channel(uint channel) {
|
||||
assert(channel < PicoSynth::CHANNEL_COUNT);
|
||||
return synth.channels[channel];
|
||||
}
|
||||
|
||||
void GalacticUnicorn::set_pixel(int x, int y, uint8_t r, uint8_t g, uint8_t b) {
|
||||
if(x < 0 || x >= WIDTH || y < 0 || y >= HEIGHT) return;
|
||||
|
||||
|
|
|
@ -75,10 +75,8 @@ namespace pimoroni {
|
|||
int16_t tone_buffers[NUM_TONE_BUFFERS][TONE_BUFFER_SIZE] = {0};
|
||||
uint current_buffer = 0;
|
||||
|
||||
public:
|
||||
PicoSynth synth;
|
||||
|
||||
private:
|
||||
enum PlayMode {
|
||||
PLAYING_BUFFER,
|
||||
//PLAYING_TONE,
|
||||
|
@ -116,6 +114,7 @@ namespace pimoroni {
|
|||
void play_sample(uint8_t *data, uint32_t length);
|
||||
void play_synth();
|
||||
void stop_playing();
|
||||
AudioChannel& synth_channel(uint channel);
|
||||
|
||||
private:
|
||||
void next_bitstream_sequence();
|
||||
|
|
|
@ -2,7 +2,7 @@ import gc
|
|||
import time
|
||||
import math
|
||||
from machine import Timer
|
||||
from galactic import GalacticUnicorn
|
||||
from galactic import GalacticUnicorn, Channel
|
||||
from picographics import PicoGraphics, DISPLAY_GALACTIC_UNICORN as DISPLAY
|
||||
|
||||
gc.collect()
|
||||
|
@ -700,15 +700,22 @@ freq_b = 0
|
|||
|
||||
beat = 0
|
||||
|
||||
channel0 = gu.synth_channel(0)
|
||||
channel1 = gu.synth_channel(1)
|
||||
channel2 = gu.synth_channel(2)
|
||||
channel3 = gu.synth_channel(3)
|
||||
channel4 = gu.synth_channel(7)
|
||||
channels = [channel0, channel1, channel2, channel3, channel4]
|
||||
|
||||
|
||||
def next_beat():
|
||||
global beat
|
||||
for i in range(5):
|
||||
if notes[i][beat] > 0:
|
||||
gu.channel_freq(i, notes[i][beat])
|
||||
gu.channel_trigger_attack(i)
|
||||
channels[i].freq(notes[i][beat])
|
||||
channels[i].trigger_attack()
|
||||
elif notes[i][beat] == -1:
|
||||
gu.channel_trigger_release(i)
|
||||
channels[i].trigger_release()
|
||||
|
||||
beat = (beat + 1) % SONG_LENGTH
|
||||
|
||||
|
@ -729,36 +736,36 @@ while True:
|
|||
|
||||
if gu.is_pressed(GalacticUnicorn.SWITCH_A):
|
||||
if not was_a_pressed:
|
||||
gu.channel_configure(0, gu.WF_TRIANGLE + gu.WF_SQUARE,
|
||||
16,
|
||||
channel0.configure(Channel.TRIANGLE + Channel.SQUARE,
|
||||
16,
|
||||
168,
|
||||
0,
|
||||
168,
|
||||
0)
|
||||
gu.channel_configure(1, gu.WF_SINE + gu.WF_SQUARE,
|
||||
38,
|
||||
300,
|
||||
0,
|
||||
0,
|
||||
12000)
|
||||
gu.channel_configure(2, gu.WF_NOISE,
|
||||
5,
|
||||
10,
|
||||
16000,
|
||||
100,
|
||||
0)
|
||||
gu.channel_configure(3, gu.WF_NOISE,
|
||||
5,
|
||||
5,
|
||||
8000,
|
||||
40,
|
||||
0)
|
||||
gu.channel_configure(4, gu.WF_SQUARE,
|
||||
10,
|
||||
100,
|
||||
0,
|
||||
500,
|
||||
0)
|
||||
channel1.configure(Channel.SINE + Channel.SQUARE,
|
||||
38,
|
||||
300,
|
||||
0,
|
||||
0,
|
||||
12000)
|
||||
channel2.configure(Channel.NOISE,
|
||||
5,
|
||||
10,
|
||||
16000,
|
||||
100,
|
||||
0)
|
||||
channel3.configure(Channel.NOISE,
|
||||
5,
|
||||
5,
|
||||
8000,
|
||||
40,
|
||||
0)
|
||||
channel4.configure(Channel.SQUARE,
|
||||
10,
|
||||
100,
|
||||
0,
|
||||
500,
|
||||
0)
|
||||
if not synthing:
|
||||
beat = 0
|
||||
next_beat()
|
||||
|
@ -774,21 +781,8 @@ while True:
|
|||
if not was_b_pressed:
|
||||
timer.deinit()
|
||||
freq_a = 400
|
||||
channel0.play_tone(freq_a, 0.06)
|
||||
|
||||
gu.channel_freq(0, freq_a)
|
||||
gu.channel_configure(0, gu.WF_SINE,
|
||||
1,
|
||||
1,
|
||||
0xffff,
|
||||
1,
|
||||
4000)
|
||||
gu.channel_configure(1, gu.WF_SINE,
|
||||
1,
|
||||
1,
|
||||
0xffff,
|
||||
1,
|
||||
4000)
|
||||
gu.channel_trigger_attack(0)
|
||||
gu.play_synth()
|
||||
synthing = False
|
||||
|
||||
|
@ -803,21 +797,8 @@ while True:
|
|||
timer.deinit()
|
||||
freq_b = 600
|
||||
|
||||
gu.channel_freq(1, freq_b)
|
||||
gu.channel_configure(0, gu.WF_SINE,
|
||||
1,
|
||||
1,
|
||||
0xffff,
|
||||
1,
|
||||
4000)
|
||||
gu.channel_configure(1, gu.WF_SINE,
|
||||
1,
|
||||
1,
|
||||
0xffff,
|
||||
1,
|
||||
4000)
|
||||
channel1.play_tone(freq_b, 0.06, fade_in=0.5)
|
||||
|
||||
gu.channel_trigger_attack(1)
|
||||
gu.play_synth()
|
||||
synthing = False
|
||||
|
||||
|
@ -842,56 +823,56 @@ while True:
|
|||
# gu.adjust_brightness(+0.01)
|
||||
if bool_playing:
|
||||
freq_b += 10
|
||||
gu.channel_freq(1, freq_b)
|
||||
channel1.freq(freq_b)
|
||||
|
||||
if gu.is_pressed(GalacticUnicorn.SWITCH_BRIGHTNESS_DOWN):
|
||||
# gu.adjust_brightness(-0.01)
|
||||
if bool_playing:
|
||||
freq_b -= 10
|
||||
gu.channel_freq(1, freq_b)
|
||||
channel1.freq(freq_b)
|
||||
|
||||
if gu.is_pressed(GalacticUnicorn.SWITCH_VOLUME_UP):
|
||||
if bool_playing:
|
||||
freq_a += 10
|
||||
gu.channel_freq(0, freq_a)
|
||||
channel0.freq(freq_a)
|
||||
|
||||
if gu.is_pressed(GalacticUnicorn.SWITCH_VOLUME_DOWN):
|
||||
if bool_playing:
|
||||
freq_a -= 10
|
||||
gu.channel_freq(0, freq_a)
|
||||
channel0.freq(freq_a)
|
||||
|
||||
if gu.is_pressed(GalacticUnicorn.SWITCH_SLEEP):
|
||||
if not was_z_pressed:
|
||||
gu.channel_configure(0, gu.WF_TRIANGLE + gu.WF_SQUARE,
|
||||
16,
|
||||
168,
|
||||
0xafff,
|
||||
168,
|
||||
10000)
|
||||
gu.channel_configure(1, gu.WF_SINE + gu.WF_SQUARE,
|
||||
38,
|
||||
300,
|
||||
0,
|
||||
0,
|
||||
12000)
|
||||
gu.channel_configure(2, gu.WF_NOISE,
|
||||
5,
|
||||
10,
|
||||
16000,
|
||||
100,
|
||||
18000)
|
||||
gu.channel_configure(3, gu.WF_NOISE,
|
||||
5,
|
||||
5,
|
||||
8000,
|
||||
40,
|
||||
8000)
|
||||
gu.channel_configure(4, gu.WF_SQUARE,
|
||||
10,
|
||||
100,
|
||||
0,
|
||||
500,
|
||||
12000)
|
||||
channel0.configure(Channel.TRIANGLE + Channel.SQUARE,
|
||||
16,
|
||||
168,
|
||||
0xafff,
|
||||
168,
|
||||
10000)
|
||||
channel1.configure(Channel.SINE + Channel.SQUARE,
|
||||
38,
|
||||
300,
|
||||
0,
|
||||
0,
|
||||
12000)
|
||||
channel2.configure(Channel.NOISE,
|
||||
5,
|
||||
10,
|
||||
16000,
|
||||
100,
|
||||
18000)
|
||||
channel3.configure(Channel.NOISE,
|
||||
5,
|
||||
5,
|
||||
8000,
|
||||
40,
|
||||
8000)
|
||||
channel4.configure(Channel.SQUARE,
|
||||
10,
|
||||
100,
|
||||
0,
|
||||
500,
|
||||
12000)
|
||||
if not synthing:
|
||||
beat = 0
|
||||
next_beat()
|
||||
|
|
|
@ -2,6 +2,13 @@
|
|||
|
||||
|
||||
/***** Methods *****/
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(Channel___del___obj, Channel___del__);
|
||||
MP_DEFINE_CONST_FUN_OBJ_KW(Channel_configure_obj, 6, Channel_configure);
|
||||
MP_DEFINE_CONST_FUN_OBJ_2(Channel_freq_obj, Channel_freq);
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(Channel_trigger_attack_obj, Channel_trigger_attack);
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(Channel_trigger_release_obj, Channel_trigger_release);
|
||||
MP_DEFINE_CONST_FUN_OBJ_KW(Channel_play_tone_obj, 2, Channel_play_tone);
|
||||
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(GalacticUnicorn___del___obj, GalacticUnicorn___del__);
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(GalacticUnicorn_clear_obj, GalacticUnicorn_clear);
|
||||
MP_DEFINE_CONST_FUN_OBJ_2(GalacticUnicorn_update_obj, GalacticUnicorn_update);
|
||||
|
@ -16,12 +23,25 @@ MP_DEFINE_CONST_FUN_OBJ_2(GalacticUnicorn_is_pressed_obj, GalacticUnicorn_is_pre
|
|||
MP_DEFINE_CONST_FUN_OBJ_2(GalacticUnicorn_play_sample_obj, GalacticUnicorn_play_sample);
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(GalacticUnicorn_play_synth_obj, GalacticUnicorn_play_synth);
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(GalacticUnicorn_stop_playing_obj, GalacticUnicorn_stop_playing);
|
||||
MP_DEFINE_CONST_FUN_OBJ_KW(GalacticUnicorn_channel_configure_obj, 7, GalacticUnicorn_channel_configure);
|
||||
MP_DEFINE_CONST_FUN_OBJ_3(GalacticUnicorn_channel_freq_obj, GalacticUnicorn_channel_freq);
|
||||
MP_DEFINE_CONST_FUN_OBJ_2(GalacticUnicorn_channel_trigger_attack_obj, GalacticUnicorn_channel_trigger_attack);
|
||||
MP_DEFINE_CONST_FUN_OBJ_2(GalacticUnicorn_channel_trigger_release_obj, GalacticUnicorn_channel_trigger_release);
|
||||
MP_DEFINE_CONST_FUN_OBJ_2(GalacticUnicorn_synth_channel_obj, GalacticUnicorn_synth_channel);
|
||||
|
||||
/***** Binding of Methods *****/
|
||||
STATIC const mp_rom_map_elem_t Channel_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&Channel___del___obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_configure), MP_ROM_PTR(&Channel_configure_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_freq), MP_ROM_PTR(&Channel_freq_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_trigger_attack), MP_ROM_PTR(&Channel_trigger_attack_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_trigger_release), MP_ROM_PTR(&Channel_trigger_release_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_play_tone), MP_ROM_PTR(&Channel_play_tone_obj) },
|
||||
|
||||
{ MP_ROM_QSTR(MP_QSTR_NOISE), MP_ROM_INT(128) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_SQUARE), MP_ROM_INT(64) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_SAW), MP_ROM_INT(32) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_TRIANGLE), MP_ROM_INT(16) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_SINE), MP_ROM_INT(8) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_WAVE), MP_ROM_INT(1) },
|
||||
};
|
||||
|
||||
STATIC const mp_rom_map_elem_t GalacticUnicorn_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&GalacticUnicorn___del___obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_clear), MP_ROM_PTR(&GalacticUnicorn_clear_obj) },
|
||||
|
@ -37,10 +57,7 @@ STATIC const mp_rom_map_elem_t GalacticUnicorn_locals_dict_table[] = {
|
|||
{ MP_ROM_QSTR(MP_QSTR_play_sample), MP_ROM_PTR(&GalacticUnicorn_play_sample_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_play_synth), MP_ROM_PTR(&GalacticUnicorn_play_synth_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_stop_playing), MP_ROM_PTR(&GalacticUnicorn_stop_playing_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_channel_configure), MP_ROM_PTR(&GalacticUnicorn_channel_configure_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_channel_freq), MP_ROM_PTR(&GalacticUnicorn_channel_freq_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_channel_trigger_attack), MP_ROM_PTR(&GalacticUnicorn_channel_trigger_attack_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_channel_trigger_release), MP_ROM_PTR(&GalacticUnicorn_channel_trigger_release_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_synth_channel), MP_ROM_PTR(&GalacticUnicorn_synth_channel_obj) },
|
||||
|
||||
{ MP_ROM_QSTR(MP_QSTR_WIDTH), MP_ROM_INT(53) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_HEIGHT), MP_ROM_INT(11) },
|
||||
|
@ -54,18 +71,20 @@ STATIC const mp_rom_map_elem_t GalacticUnicorn_locals_dict_table[] = {
|
|||
{ MP_ROM_QSTR(MP_QSTR_SWITCH_VOLUME_DOWN), MP_ROM_INT(8) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_SWITCH_BRIGHTNESS_UP), MP_ROM_INT(21) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_SWITCH_BRIGHTNESS_DOWN), MP_ROM_INT(26) },
|
||||
|
||||
{ MP_ROM_QSTR(MP_QSTR_WF_NOISE), MP_ROM_INT(128) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_WF_SQUARE), MP_ROM_INT(64) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_WF_SAW), MP_ROM_INT(32) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_WF_TRIANGLE), MP_ROM_INT(16) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_WF_SINE), MP_ROM_INT(8) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_WF_WAVE), MP_ROM_INT(1) },
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(Channel_locals_dict, Channel_locals_dict_table);
|
||||
STATIC MP_DEFINE_CONST_DICT(GalacticUnicorn_locals_dict, GalacticUnicorn_locals_dict_table);
|
||||
|
||||
/***** Class Definition *****/
|
||||
const mp_obj_type_t Channel_type = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_Channel,
|
||||
.print = Channel_print,
|
||||
.make_new = Channel_make_new,
|
||||
.locals_dict = (mp_obj_dict_t*)&Channel_locals_dict,
|
||||
};
|
||||
|
||||
const mp_obj_type_t GalacticUnicorn_type = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_GalacticUnicorn,
|
||||
|
@ -77,6 +96,7 @@ const mp_obj_type_t GalacticUnicorn_type = {
|
|||
/***** Globals Table *****/
|
||||
STATIC const mp_map_elem_t galactic_globals_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_galactic) },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_Channel), (mp_obj_t)&Channel_type },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_GalacticUnicorn), (mp_obj_t)&GalacticUnicorn_type },
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(mp_module_galactic_globals, galactic_globals_table);
|
||||
|
|
|
@ -13,6 +13,155 @@ extern "C" {
|
|||
#include "py/builtin.h"
|
||||
|
||||
|
||||
/********** Channel **********/
|
||||
|
||||
/***** Variables Struct *****/
|
||||
typedef struct _Channel_obj_t {
|
||||
mp_obj_base_t base;
|
||||
AudioChannel* channel;
|
||||
} _Channel_obj_t;
|
||||
|
||||
|
||||
/***** Print *****/
|
||||
void Channel_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
|
||||
(void)kind; //Unused input parameter
|
||||
//_Channel_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Channel_obj_t);
|
||||
//AudioChannel* channel = self->channel;
|
||||
mp_print_str(print, "Channel(");
|
||||
mp_print_str(print, ")");
|
||||
}
|
||||
|
||||
|
||||
/***** Constructor *****/
|
||||
mp_obj_t Channel_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
|
||||
mp_raise_msg(&mp_type_RuntimeError, "Cannot create Channel objects. They can only be accessed from GalacticUnicorn.synth_channel()");
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
|
||||
/***** Destructor ******/
|
||||
mp_obj_t Channel___del__(mp_obj_t self_in) {
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
|
||||
/***** Methods *****/
|
||||
mp_obj_t Channel_configure(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
enum { ARG_self, ARG_waveforms, ARG_attack_ms, ARG_decay_ms, ARG_sustain, ARG_release_ms, ARG_volume };
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_, MP_ARG_REQUIRED | MP_ARG_OBJ },
|
||||
{ MP_QSTR_waveforms, MP_ARG_REQUIRED | MP_ARG_INT },
|
||||
{ MP_QSTR_attack_ms, MP_ARG_REQUIRED | MP_ARG_INT },
|
||||
{ MP_QSTR_decay_ms, MP_ARG_REQUIRED | MP_ARG_INT },
|
||||
{ MP_QSTR_sustain, MP_ARG_REQUIRED | MP_ARG_INT },
|
||||
{ MP_QSTR_release_ms, MP_ARG_REQUIRED | MP_ARG_INT },
|
||||
{ MP_QSTR_volumes, MP_ARG_REQUIRED | MP_ARG_INT },
|
||||
};
|
||||
|
||||
// Parse args.
|
||||
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
||||
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||
|
||||
_Channel_obj_t *self = MP_OBJ_TO_PTR2(args[ARG_self].u_obj, _Channel_obj_t);
|
||||
|
||||
self->channel->waveforms = args[ARG_waveforms].u_int;
|
||||
self->channel->attack_ms = args[ARG_attack_ms].u_int;
|
||||
self->channel->decay_ms = args[ARG_decay_ms].u_int;
|
||||
self->channel->sustain = args[ARG_sustain].u_int;
|
||||
self->channel->release_ms = args[ARG_release_ms].u_int;
|
||||
self->channel->volume = args[ARG_volume].u_int;
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
mp_obj_t Channel_freq(mp_obj_t self_in, mp_obj_t freq_in) {
|
||||
_Channel_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Channel_obj_t);
|
||||
|
||||
float freq = mp_obj_get_float(freq_in);
|
||||
if(freq <= 0.0f) {
|
||||
mp_raise_ValueError("freq out of range. Expected greater than 0.0");
|
||||
}
|
||||
self->channel->frequency = freq;
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
mp_obj_t Channel_trigger_attack(mp_obj_t self_in) {
|
||||
_Channel_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Channel_obj_t);
|
||||
self->channel->trigger_attack();
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
mp_obj_t Channel_trigger_release(mp_obj_t self_in) {
|
||||
_Channel_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Channel_obj_t);
|
||||
self->channel->trigger_release();
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
mp_obj_t Channel_play_tone(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
enum { ARG_self, ARG_freq, ARG_volume, ARG_fade_in, ARG_fade_out };
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_, MP_ARG_REQUIRED | MP_ARG_OBJ },
|
||||
{ MP_QSTR_freq, MP_ARG_REQUIRED | MP_ARG_OBJ },
|
||||
{ MP_QSTR_volume, MP_ARG_OBJ, {.u_obj = mp_const_none} },
|
||||
{ MP_QSTR_fade_in, MP_ARG_OBJ, {.u_obj = mp_const_none} },
|
||||
{ MP_QSTR_fade_out, MP_ARG_OBJ, {.u_obj = mp_const_none} },
|
||||
};
|
||||
|
||||
// Parse args.
|
||||
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
||||
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||
|
||||
_Channel_obj_t *self = MP_OBJ_TO_PTR2(args[ARG_self].u_obj, _Channel_obj_t);
|
||||
|
||||
float freq = mp_obj_get_float(args[ARG_freq].u_obj);
|
||||
if(freq <= 0.0f) {
|
||||
mp_raise_ValueError("freq out of range. Expected greater than 0.0");
|
||||
}
|
||||
|
||||
float volume = 1.0f;
|
||||
if(args[ARG_volume].u_obj != mp_const_none) {
|
||||
volume = mp_obj_get_float(args[ARG_volume].u_obj);
|
||||
if(volume < 0.0f || volume > 1.0f) {
|
||||
mp_raise_ValueError("volume out of range. Expected 0.0 to 1.0");
|
||||
}
|
||||
}
|
||||
|
||||
int fade_in_ms = 1;
|
||||
if(args[ARG_fade_in].u_obj != mp_const_none) {
|
||||
float fade_in = mp_obj_get_float(args[ARG_fade_in].u_obj);
|
||||
if(fade_in <= 0.0f) {
|
||||
mp_raise_ValueError("fade_in out of range. Expected greater than 0.0");
|
||||
}
|
||||
fade_in_ms = (uint16_t)(fade_in * 1000.0f);
|
||||
}
|
||||
|
||||
int fade_out_ms = 1;
|
||||
if(args[ARG_fade_out].u_obj != mp_const_none) {
|
||||
float fade_out = mp_obj_get_float(args[ARG_fade_out].u_obj);
|
||||
if(fade_out <= 0.0f) {
|
||||
mp_raise_ValueError("fade_out out of range. Expected greater than 0.0");
|
||||
}
|
||||
fade_out_ms = (uint16_t)(fade_out * 1000.0f);
|
||||
}
|
||||
|
||||
|
||||
self->channel->frequency = freq;
|
||||
self->channel->waveforms = Waveform::SINE;
|
||||
self->channel->attack_ms = MAX(fade_in_ms, 1);
|
||||
self->channel->decay_ms = 1;
|
||||
self->channel->sustain = 0xffff;
|
||||
self->channel->release_ms = MAX(fade_out_ms, 1);
|
||||
self->channel->volume = (uint16_t)(volume * 0xffff);
|
||||
|
||||
self->channel->trigger_attack();
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
|
||||
/********** GalacticUnicorn **********/
|
||||
|
||||
/***** Variables Struct *****/
|
||||
|
@ -173,55 +322,21 @@ extern mp_obj_t GalacticUnicorn_stop_playing(mp_obj_t self_in) {
|
|||
return mp_const_none;
|
||||
}
|
||||
|
||||
extern mp_obj_t GalacticUnicorn_channel_configure(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
enum { ARG_self, ARG_channel, ARG_waveforms, ARG_attack_ms, ARG_decay_ms, ARG_sustain, ARG_release_ms, ARG_volume };
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_, MP_ARG_REQUIRED | MP_ARG_OBJ },
|
||||
{ MP_QSTR_channel, MP_ARG_REQUIRED | MP_ARG_INT },
|
||||
{ MP_QSTR_waveforms, MP_ARG_REQUIRED | MP_ARG_INT },
|
||||
{ MP_QSTR_attack_ms, MP_ARG_REQUIRED | MP_ARG_INT },
|
||||
{ MP_QSTR_decay_ms, MP_ARG_REQUIRED | MP_ARG_INT },
|
||||
{ MP_QSTR_sustain, MP_ARG_REQUIRED | MP_ARG_INT },
|
||||
{ MP_QSTR_release_ms, MP_ARG_REQUIRED | MP_ARG_INT },
|
||||
{ MP_QSTR_volumes, MP_ARG_REQUIRED | MP_ARG_INT },
|
||||
};
|
||||
|
||||
// Parse args.
|
||||
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
||||
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||
|
||||
_GalacticUnicorn_obj_t *self = MP_OBJ_TO_PTR2(args[ARG_self].u_obj, _GalacticUnicorn_obj_t);
|
||||
|
||||
int c = args[ARG_channel].u_int;
|
||||
self->galactic->synth.channels[c].waveforms = args[ARG_waveforms].u_int;
|
||||
self->galactic->synth.channels[c].attack_ms = args[ARG_attack_ms].u_int;
|
||||
self->galactic->synth.channels[c].decay_ms = args[ARG_decay_ms].u_int;
|
||||
self->galactic->synth.channels[c].sustain = args[ARG_sustain].u_int;
|
||||
self->galactic->synth.channels[c].release_ms = args[ARG_release_ms].u_int;
|
||||
self->galactic->synth.channels[c].volume = args[ARG_volume].u_int;
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
extern mp_obj_t GalacticUnicorn_channel_freq(mp_obj_t self_in, mp_obj_t channel, mp_obj_t freq) {
|
||||
extern mp_obj_t GalacticUnicorn_synth_channel(mp_obj_t self_in, mp_obj_t channel_in) {
|
||||
_GalacticUnicorn_obj_t *self = MP_OBJ_TO_PTR2(self_in, _GalacticUnicorn_obj_t);
|
||||
|
||||
self->galactic->synth.channels[mp_obj_get_int(channel)].frequency = mp_obj_get_float(freq);
|
||||
// Check that the channel is valid
|
||||
int channel = mp_obj_get_int(channel_in);
|
||||
if(channel < 0 || channel >= (int)PicoSynth::CHANNEL_COUNT) {
|
||||
mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("channel out of range. Expected 0 to %d"), PicoSynth::CHANNEL_COUNT - 1);
|
||||
}
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
// NOTE This seems to work, in that it give MP access to the calibration object
|
||||
// Could very easily mess up in weird ways once object deletion is considered?
|
||||
_Channel_obj_t *channel_obj = m_new_obj_with_finaliser(_Channel_obj_t);
|
||||
channel_obj->base.type = &Channel_type;
|
||||
channel_obj->channel = &self->galactic->synth_channel(channel);
|
||||
|
||||
extern mp_obj_t GalacticUnicorn_channel_trigger_attack(mp_obj_t self_in, mp_obj_t channel) {
|
||||
_GalacticUnicorn_obj_t *self = MP_OBJ_TO_PTR2(self_in, _GalacticUnicorn_obj_t);
|
||||
self->galactic->synth.channels[mp_obj_get_int(channel)].trigger_attack();
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
extern mp_obj_t GalacticUnicorn_channel_trigger_release(mp_obj_t self_in, mp_obj_t channel) {
|
||||
_GalacticUnicorn_obj_t *self = MP_OBJ_TO_PTR2(self_in, _GalacticUnicorn_obj_t);
|
||||
self->galactic->synth.channels[mp_obj_get_int(channel)].trigger_release();
|
||||
|
||||
return mp_const_none;
|
||||
return MP_OBJ_FROM_PTR(channel_obj);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,9 +2,20 @@
|
|||
#include "py/runtime.h"
|
||||
|
||||
/***** Extern of Class Definition *****/
|
||||
extern const mp_obj_type_t Channel_type;
|
||||
extern const mp_obj_type_t GalacticUnicorn_type;
|
||||
|
||||
/***** Extern of Class Methods *****/
|
||||
extern void Channel_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind);
|
||||
extern mp_obj_t Channel_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args);
|
||||
extern mp_obj_t Channel___del__(mp_obj_t self_in);
|
||||
extern mp_obj_t Channel_configure(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
|
||||
extern mp_obj_t Channel_freq(mp_obj_t self_in, mp_obj_t freq_in);
|
||||
extern mp_obj_t Channel_trigger_attack(mp_obj_t self_in);
|
||||
extern mp_obj_t Channel_trigger_release(mp_obj_t self_in);
|
||||
extern mp_obj_t Channel_play_tone(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
|
||||
|
||||
|
||||
extern void GalacticUnicorn_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind);
|
||||
extern mp_obj_t GalacticUnicorn_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args);
|
||||
extern mp_obj_t GalacticUnicorn___del__(mp_obj_t self_in);
|
||||
|
@ -28,7 +39,4 @@ extern mp_obj_t GalacticUnicorn_play_sample(mp_obj_t self_in, mp_obj_t data);
|
|||
extern mp_obj_t GalacticUnicorn_play_synth(mp_obj_t self_in);
|
||||
extern mp_obj_t GalacticUnicorn_stop_playing(mp_obj_t self_in);
|
||||
|
||||
extern mp_obj_t GalacticUnicorn_channel_configure(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);;
|
||||
extern mp_obj_t GalacticUnicorn_channel_freq(mp_obj_t self_in, mp_obj_t channel, mp_obj_t freq);
|
||||
extern mp_obj_t GalacticUnicorn_channel_trigger_attack(mp_obj_t self_in, mp_obj_t channel);
|
||||
extern mp_obj_t GalacticUnicorn_channel_trigger_release(mp_obj_t self_in, mp_obj_t channel);
|
||||
extern mp_obj_t GalacticUnicorn_synth_channel(mp_obj_t self_in, mp_obj_t channel_in);
|
Loading…
Reference in New Issue