kopia lustrzana https://github.com/pimoroni/pimoroni-pico
				
				
				
			Started splitting out synth into separate channel objects
							rodzic
							
								
									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); | ||||
		Ładowanie…
	
		Reference in New Issue
	
	 ZodiusInfuser
						ZodiusInfuser