Started splitting out synth into separate channel objects

feature/galactic_unicorn
ZodiusInfuser 2022-08-25 17:27:53 +01:00 zatwierdzone przez Phil Howard
rodzic 882f76dcbc
commit 53dfb9866d
6 zmienionych plików z 287 dodań i 159 usunięć

Wyświetl plik

@ -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) { 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; if(x < 0 || x >= WIDTH || y < 0 || y >= HEIGHT) return;

Wyświetl plik

@ -75,10 +75,8 @@ namespace pimoroni {
int16_t tone_buffers[NUM_TONE_BUFFERS][TONE_BUFFER_SIZE] = {0}; int16_t tone_buffers[NUM_TONE_BUFFERS][TONE_BUFFER_SIZE] = {0};
uint current_buffer = 0; uint current_buffer = 0;
public:
PicoSynth synth; PicoSynth synth;
private:
enum PlayMode { enum PlayMode {
PLAYING_BUFFER, PLAYING_BUFFER,
//PLAYING_TONE, //PLAYING_TONE,
@ -116,6 +114,7 @@ namespace pimoroni {
void play_sample(uint8_t *data, uint32_t length); void play_sample(uint8_t *data, uint32_t length);
void play_synth(); void play_synth();
void stop_playing(); void stop_playing();
AudioChannel& synth_channel(uint channel);
private: private:
void next_bitstream_sequence(); void next_bitstream_sequence();

Wyświetl plik

@ -2,7 +2,7 @@ import gc
import time import time
import math import math
from machine import Timer from machine import Timer
from galactic import GalacticUnicorn from galactic import GalacticUnicorn, Channel
from picographics import PicoGraphics, DISPLAY_GALACTIC_UNICORN as DISPLAY from picographics import PicoGraphics, DISPLAY_GALACTIC_UNICORN as DISPLAY
gc.collect() gc.collect()
@ -700,15 +700,22 @@ freq_b = 0
beat = 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(): def next_beat():
global beat global beat
for i in range(5): for i in range(5):
if notes[i][beat] > 0: if notes[i][beat] > 0:
gu.channel_freq(i, notes[i][beat]) channels[i].freq(notes[i][beat])
gu.channel_trigger_attack(i) channels[i].trigger_attack()
elif notes[i][beat] == -1: elif notes[i][beat] == -1:
gu.channel_trigger_release(i) channels[i].trigger_release()
beat = (beat + 1) % SONG_LENGTH beat = (beat + 1) % SONG_LENGTH
@ -729,36 +736,36 @@ while True:
if gu.is_pressed(GalacticUnicorn.SWITCH_A): if gu.is_pressed(GalacticUnicorn.SWITCH_A):
if not was_a_pressed: if not was_a_pressed:
gu.channel_configure(0, gu.WF_TRIANGLE + gu.WF_SQUARE, channel0.configure(Channel.TRIANGLE + Channel.SQUARE,
16, 16,
168, 168,
0, 0,
168, 168,
0) 0)
gu.channel_configure(1, gu.WF_SINE + gu.WF_SQUARE, channel1.configure(Channel.SINE + Channel.SQUARE,
38, 38,
300, 300,
0, 0,
0, 0,
12000) 12000)
gu.channel_configure(2, gu.WF_NOISE, channel2.configure(Channel.NOISE,
5, 5,
10, 10,
16000, 16000,
100, 100,
0) 0)
gu.channel_configure(3, gu.WF_NOISE, channel3.configure(Channel.NOISE,
5, 5,
5, 5,
8000, 8000,
40, 40,
0) 0)
gu.channel_configure(4, gu.WF_SQUARE, channel4.configure(Channel.SQUARE,
10, 10,
100, 100,
0, 0,
500, 500,
0) 0)
if not synthing: if not synthing:
beat = 0 beat = 0
next_beat() next_beat()
@ -774,21 +781,8 @@ while True:
if not was_b_pressed: if not was_b_pressed:
timer.deinit() timer.deinit()
freq_a = 400 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() gu.play_synth()
synthing = False synthing = False
@ -803,21 +797,8 @@ while True:
timer.deinit() timer.deinit()
freq_b = 600 freq_b = 600
gu.channel_freq(1, freq_b) channel1.play_tone(freq_b, 0.06, fade_in=0.5)
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(1)
gu.play_synth() gu.play_synth()
synthing = False synthing = False
@ -842,56 +823,56 @@ while True:
# gu.adjust_brightness(+0.01) # gu.adjust_brightness(+0.01)
if bool_playing: if bool_playing:
freq_b += 10 freq_b += 10
gu.channel_freq(1, freq_b) channel1.freq(freq_b)
if gu.is_pressed(GalacticUnicorn.SWITCH_BRIGHTNESS_DOWN): if gu.is_pressed(GalacticUnicorn.SWITCH_BRIGHTNESS_DOWN):
# gu.adjust_brightness(-0.01) # gu.adjust_brightness(-0.01)
if bool_playing: if bool_playing:
freq_b -= 10 freq_b -= 10
gu.channel_freq(1, freq_b) channel1.freq(freq_b)
if gu.is_pressed(GalacticUnicorn.SWITCH_VOLUME_UP): if gu.is_pressed(GalacticUnicorn.SWITCH_VOLUME_UP):
if bool_playing: if bool_playing:
freq_a += 10 freq_a += 10
gu.channel_freq(0, freq_a) channel0.freq(freq_a)
if gu.is_pressed(GalacticUnicorn.SWITCH_VOLUME_DOWN): if gu.is_pressed(GalacticUnicorn.SWITCH_VOLUME_DOWN):
if bool_playing: if bool_playing:
freq_a -= 10 freq_a -= 10
gu.channel_freq(0, freq_a) channel0.freq(freq_a)
if gu.is_pressed(GalacticUnicorn.SWITCH_SLEEP): if gu.is_pressed(GalacticUnicorn.SWITCH_SLEEP):
if not was_z_pressed: if not was_z_pressed:
gu.channel_configure(0, gu.WF_TRIANGLE + gu.WF_SQUARE, channel0.configure(Channel.TRIANGLE + Channel.SQUARE,
16, 16,
168, 168,
0xafff, 0xafff,
168, 168,
10000) 10000)
gu.channel_configure(1, gu.WF_SINE + gu.WF_SQUARE, channel1.configure(Channel.SINE + Channel.SQUARE,
38, 38,
300, 300,
0, 0,
0, 0,
12000) 12000)
gu.channel_configure(2, gu.WF_NOISE, channel2.configure(Channel.NOISE,
5, 5,
10, 10,
16000, 16000,
100, 100,
18000) 18000)
gu.channel_configure(3, gu.WF_NOISE, channel3.configure(Channel.NOISE,
5, 5,
5, 5,
8000, 8000,
40, 40,
8000) 8000)
gu.channel_configure(4, gu.WF_SQUARE, channel4.configure(Channel.SQUARE,
10, 10,
100, 100,
0, 0,
500, 500,
12000) 12000)
if not synthing: if not synthing:
beat = 0 beat = 0
next_beat() next_beat()

Wyświetl plik

@ -2,6 +2,13 @@
/***** Methods *****/ /***** 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___del___obj, GalacticUnicorn___del__);
MP_DEFINE_CONST_FUN_OBJ_1(GalacticUnicorn_clear_obj, GalacticUnicorn_clear); MP_DEFINE_CONST_FUN_OBJ_1(GalacticUnicorn_clear_obj, GalacticUnicorn_clear);
MP_DEFINE_CONST_FUN_OBJ_2(GalacticUnicorn_update_obj, GalacticUnicorn_update); 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_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_play_synth_obj, GalacticUnicorn_play_synth);
MP_DEFINE_CONST_FUN_OBJ_1(GalacticUnicorn_stop_playing_obj, GalacticUnicorn_stop_playing); 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_2(GalacticUnicorn_synth_channel_obj, GalacticUnicorn_synth_channel);
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);
/***** Binding of Methods *****/ /***** 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[] = { 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___del__), MP_ROM_PTR(&GalacticUnicorn___del___obj) },
{ MP_ROM_QSTR(MP_QSTR_clear), MP_ROM_PTR(&GalacticUnicorn_clear_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_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_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_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_synth_channel), MP_ROM_PTR(&GalacticUnicorn_synth_channel_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_WIDTH), MP_ROM_INT(53) }, { MP_ROM_QSTR(MP_QSTR_WIDTH), MP_ROM_INT(53) },
{ MP_ROM_QSTR(MP_QSTR_HEIGHT), MP_ROM_INT(11) }, { 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_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_UP), MP_ROM_INT(21) },
{ MP_ROM_QSTR(MP_QSTR_SWITCH_BRIGHTNESS_DOWN), MP_ROM_INT(26) }, { 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); STATIC MP_DEFINE_CONST_DICT(GalacticUnicorn_locals_dict, GalacticUnicorn_locals_dict_table);
/***** Class Definition *****/ /***** 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 = { const mp_obj_type_t GalacticUnicorn_type = {
{ &mp_type_type }, { &mp_type_type },
.name = MP_QSTR_GalacticUnicorn, .name = MP_QSTR_GalacticUnicorn,
@ -77,6 +96,7 @@ const mp_obj_type_t GalacticUnicorn_type = {
/***** Globals Table *****/ /***** Globals Table *****/
STATIC const mp_map_elem_t galactic_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___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 }, { MP_OBJ_NEW_QSTR(MP_QSTR_GalacticUnicorn), (mp_obj_t)&GalacticUnicorn_type },
}; };
STATIC MP_DEFINE_CONST_DICT(mp_module_galactic_globals, galactic_globals_table); STATIC MP_DEFINE_CONST_DICT(mp_module_galactic_globals, galactic_globals_table);

Wyświetl plik

@ -13,6 +13,155 @@ extern "C" {
#include "py/builtin.h" #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 **********/ /********** GalacticUnicorn **********/
/***** Variables Struct *****/ /***** Variables Struct *****/
@ -173,55 +322,21 @@ extern mp_obj_t GalacticUnicorn_stop_playing(mp_obj_t self_in) {
return mp_const_none; 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) { extern mp_obj_t GalacticUnicorn_synth_channel(mp_obj_t self_in, mp_obj_t channel_in) {
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) {
_GalacticUnicorn_obj_t *self = MP_OBJ_TO_PTR2(self_in, _GalacticUnicorn_obj_t); _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) { return MP_OBJ_FROM_PTR(channel_obj);
_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;
} }
} }

Wyświetl plik

@ -2,9 +2,20 @@
#include "py/runtime.h" #include "py/runtime.h"
/***** Extern of Class Definition *****/ /***** Extern of Class Definition *****/
extern const mp_obj_type_t Channel_type;
extern const mp_obj_type_t GalacticUnicorn_type; extern const mp_obj_type_t GalacticUnicorn_type;
/***** Extern of Class Methods *****/ /***** 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 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_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); 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_play_synth(mp_obj_t self_in);
extern mp_obj_t GalacticUnicorn_stop_playing(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_synth_channel(mp_obj_t self_in, mp_obj_t channel_in);
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);