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,31 +736,31 @@ while True:
 | 
			
		|||
 | 
			
		||||
    if gu.is_pressed(GalacticUnicorn.SWITCH_A):
 | 
			
		||||
        if not was_a_pressed:
 | 
			
		||||
            gu.channel_configure(0, gu.WF_TRIANGLE + gu.WF_SQUARE,
 | 
			
		||||
            channel0.configure(Channel.TRIANGLE + Channel.SQUARE,
 | 
			
		||||
                               16,
 | 
			
		||||
                                 168,
 | 
			
		||||
                                 0,
 | 
			
		||||
                                 168,
 | 
			
		||||
                                 0)
 | 
			
		||||
            gu.channel_configure(1, gu.WF_SINE + gu.WF_SQUARE,
 | 
			
		||||
            channel1.configure(Channel.SINE + Channel.SQUARE,
 | 
			
		||||
                               38,
 | 
			
		||||
                               300,
 | 
			
		||||
                               0,
 | 
			
		||||
                               0,
 | 
			
		||||
                               12000)
 | 
			
		||||
            gu.channel_configure(2, gu.WF_NOISE,
 | 
			
		||||
            channel2.configure(Channel.NOISE,
 | 
			
		||||
                               5,
 | 
			
		||||
                               10,
 | 
			
		||||
                               16000,
 | 
			
		||||
                               100,
 | 
			
		||||
                               0)
 | 
			
		||||
            gu.channel_configure(3, gu.WF_NOISE,
 | 
			
		||||
            channel3.configure(Channel.NOISE,
 | 
			
		||||
                               5,
 | 
			
		||||
                               5,
 | 
			
		||||
                               8000,
 | 
			
		||||
                               40,
 | 
			
		||||
                               0)
 | 
			
		||||
            gu.channel_configure(4, gu.WF_SQUARE,
 | 
			
		||||
            channel4.configure(Channel.SQUARE,
 | 
			
		||||
                               10,
 | 
			
		||||
                               100,
 | 
			
		||||
                               0,
 | 
			
		||||
| 
						 | 
				
			
			@ -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,51 +823,51 @@ 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,
 | 
			
		||||
            channel0.configure(Channel.TRIANGLE + Channel.SQUARE,
 | 
			
		||||
                               16,
 | 
			
		||||
                               168,
 | 
			
		||||
                               0xafff,
 | 
			
		||||
                               168,
 | 
			
		||||
                               10000)
 | 
			
		||||
            gu.channel_configure(1, gu.WF_SINE + gu.WF_SQUARE,
 | 
			
		||||
            channel1.configure(Channel.SINE + Channel.SQUARE,
 | 
			
		||||
                               38,
 | 
			
		||||
                               300,
 | 
			
		||||
                               0,
 | 
			
		||||
                               0,
 | 
			
		||||
                               12000)
 | 
			
		||||
            gu.channel_configure(2, gu.WF_NOISE,
 | 
			
		||||
            channel2.configure(Channel.NOISE,
 | 
			
		||||
                               5,
 | 
			
		||||
                               10,
 | 
			
		||||
                               16000,
 | 
			
		||||
                               100,
 | 
			
		||||
                               18000)
 | 
			
		||||
            gu.channel_configure(3, gu.WF_NOISE,
 | 
			
		||||
            channel3.configure(Channel.NOISE,
 | 
			
		||||
                               5,
 | 
			
		||||
                               5,
 | 
			
		||||
                               8000,
 | 
			
		||||
                               40,
 | 
			
		||||
                               8000)
 | 
			
		||||
            gu.channel_configure(4, gu.WF_SQUARE,
 | 
			
		||||
            channel4.configure(Channel.SQUARE,
 | 
			
		||||
                               10,
 | 
			
		||||
                               100,
 | 
			
		||||
                               0,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
 | 
			
		||||
    return mp_const_none;
 | 
			
		||||
    // 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);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
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();
 | 
			
		||||
    // 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);
 | 
			
		||||
 | 
			
		||||
    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