Exposed remaining AudioChannel parameters
This commit is contained in:
parent
2695982182
commit
df79caf34e
|
@ -68,7 +68,7 @@ int main() {
|
|||
i++;
|
||||
graphics.set_pen(0, 0, 0);
|
||||
graphics.clear();
|
||||
|
||||
|
||||
float s = 0.8f;//0.65f + (sin(i / 25.0f) * 0.15f);
|
||||
float a = 1.0f;// (sin(i / 25.0f) * 100.0f);
|
||||
|
||||
|
@ -76,7 +76,7 @@ int main() {
|
|||
float y = (cos((i) / 40.0f) * 5.0f);
|
||||
graphics.set_pen(255, 255, 255);
|
||||
text("Galactic Unicorn", Point(x, y), s, a);
|
||||
|
||||
|
||||
uint8_t *p = (uint8_t *)graphics.frame_buffer;
|
||||
for(size_t i = 0; i < 53 * 11; i++) {
|
||||
int x = i % 53;
|
||||
|
@ -92,14 +92,11 @@ int main() {
|
|||
b = hue_map[x][2];
|
||||
}
|
||||
|
||||
galactic_unicorn.set_pixel(x, y, r, g, b);
|
||||
graphics.set_pen(r, g, b);
|
||||
graphics.pixel(Point(x, y));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
printf("done\n");
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -56,6 +56,20 @@ namespace pimoroni {
|
|||
adsr_step = 0;
|
||||
}
|
||||
|
||||
void AudioChannel::restore() {
|
||||
// Put all the parameters back to their initial values
|
||||
waveforms = 0;
|
||||
frequency = 660;
|
||||
volume = 0xffff;
|
||||
|
||||
attack_ms = 2;
|
||||
decay_ms = 6;
|
||||
sustain = 0xffff;
|
||||
release_ms = 1;
|
||||
pulse_width = 0x7fff;
|
||||
noise = 0;
|
||||
}
|
||||
|
||||
bool PicoSynth::is_audio_playing() {
|
||||
if(volume == 0) {
|
||||
return false;
|
||||
|
|
|
@ -69,11 +69,11 @@ namespace pimoroni {
|
|||
struct AudioChannel {
|
||||
uint8_t waveforms = 0; // bitmask for enabled waveforms (see Waveform enum for values)
|
||||
uint16_t frequency = 660; // frequency of the voice (Hz)
|
||||
uint16_t volume = 0xffff; // channel volume
|
||||
uint16_t volume = UINT16_MAX; // channel volume
|
||||
|
||||
uint16_t attack_ms = 2; // attack period (cannot be zero)
|
||||
uint16_t decay_ms = 6; // decay period (cannot be zero)
|
||||
uint16_t sustain = 0xffff; // sustain volume
|
||||
uint16_t sustain = UINT16_MAX; // sustain volume
|
||||
uint16_t release_ms = 1; // release period
|
||||
uint16_t pulse_width = 0x7fff; // duty cycle of square wave (default 50%)
|
||||
int16_t noise = 0; // current noise value
|
||||
|
@ -101,6 +101,7 @@ namespace pimoroni {
|
|||
void trigger_sustain();
|
||||
void trigger_release();
|
||||
void off();
|
||||
void restore();
|
||||
};
|
||||
|
||||
class PicoSynth {
|
||||
|
|
|
@ -712,7 +712,7 @@ def next_beat():
|
|||
global beat
|
||||
for i in range(5):
|
||||
if notes[i][beat] > 0:
|
||||
channels[i].freq(notes[i][beat])
|
||||
channels[i].frequency(notes[i][beat])
|
||||
channels[i].trigger_attack()
|
||||
elif notes[i][beat] == -1:
|
||||
channels[i].trigger_release()
|
||||
|
@ -736,36 +736,36 @@ while True:
|
|||
|
||||
if gu.is_pressed(GalacticUnicorn.SWITCH_A):
|
||||
if not was_a_pressed:
|
||||
channel0.configure(Channel.TRIANGLE + Channel.SQUARE,
|
||||
16,
|
||||
168,
|
||||
0,
|
||||
168,
|
||||
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)
|
||||
channel0.configure(waveforms=Channel.TRIANGLE + Channel.SQUARE,
|
||||
attack=0.016,
|
||||
decay=0.168,
|
||||
sustain=0,
|
||||
release=0.168,
|
||||
volume=0)
|
||||
channel1.configure(waveforms=Channel.SINE + Channel.SQUARE,
|
||||
attack=0.038,
|
||||
decay=0.300,
|
||||
sustain=0,
|
||||
release=0,
|
||||
volume=12000/65535)
|
||||
channel2.configure(waveforms=Channel.NOISE,
|
||||
attack=0.005,
|
||||
decay=0.010,
|
||||
sustain=16000/65535,
|
||||
release=0.100,
|
||||
volume=0)
|
||||
channel3.configure(waveforms=Channel.NOISE,
|
||||
attack=0.005,
|
||||
decay=0.005,
|
||||
sustain=8000/65535,
|
||||
release=0.040,
|
||||
volume=0)
|
||||
channel4.configure(waveforms=Channel.SQUARE,
|
||||
attack=0.010,
|
||||
decay=0.100,
|
||||
sustain=0,
|
||||
release=0.500,
|
||||
volume=0)
|
||||
if not synthing:
|
||||
beat = 0
|
||||
next_beat()
|
||||
|
@ -797,7 +797,7 @@ while True:
|
|||
timer.deinit()
|
||||
freq_b = 600
|
||||
|
||||
channel1.play_tone(freq_b, 0.06, fade_in=0.5)
|
||||
channel1.play_tone(freq_b, 0.06, attack=0.5)
|
||||
|
||||
gu.play_synth()
|
||||
synthing = False
|
||||
|
@ -822,57 +822,57 @@ while True:
|
|||
if gu.is_pressed(GalacticUnicorn.SWITCH_BRIGHTNESS_UP):
|
||||
# gu.adjust_brightness(+0.01)
|
||||
if bool_playing:
|
||||
freq_b += 10
|
||||
channel1.freq(freq_b)
|
||||
freq_b = min(freq_b + 10, 20000)
|
||||
channel1.frequency(freq_b)
|
||||
|
||||
if gu.is_pressed(GalacticUnicorn.SWITCH_BRIGHTNESS_DOWN):
|
||||
# gu.adjust_brightness(-0.01)
|
||||
if bool_playing:
|
||||
freq_b -= 10
|
||||
channel1.freq(freq_b)
|
||||
freq_b = max(freq_b - 10, 10)
|
||||
channel1.frequency(max(freq_b, 10))
|
||||
|
||||
if gu.is_pressed(GalacticUnicorn.SWITCH_VOLUME_UP):
|
||||
if bool_playing:
|
||||
freq_a += 10
|
||||
channel0.freq(freq_a)
|
||||
freq_a = min(freq_a + 10, 20000)
|
||||
channel0.frequency(freq_a)
|
||||
|
||||
if gu.is_pressed(GalacticUnicorn.SWITCH_VOLUME_DOWN):
|
||||
if bool_playing:
|
||||
freq_a -= 10
|
||||
channel0.freq(freq_a)
|
||||
freq_a = max(freq_a - 10, 10)
|
||||
channel0.frequency(freq_a)
|
||||
|
||||
if gu.is_pressed(GalacticUnicorn.SWITCH_SLEEP):
|
||||
if not was_z_pressed:
|
||||
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)
|
||||
channel0.configure(waveforms=Channel.TRIANGLE + Channel.SQUARE,
|
||||
attack=0.016,
|
||||
decay=0.168,
|
||||
sustain=0xafff/65535,
|
||||
release=0.168,
|
||||
volume=10000/65535)
|
||||
channel1.configure(waveforms=Channel.SINE + Channel.SQUARE,
|
||||
attack=0.038,
|
||||
decay=0.300,
|
||||
sustain=0,
|
||||
release=0,
|
||||
volume=12000/65535)
|
||||
channel2.configure(waveforms=Channel.NOISE,
|
||||
attack=0.005,
|
||||
decay=0.010,
|
||||
sustain=16000/65535,
|
||||
release=0.100,
|
||||
volume=18000/65535)
|
||||
channel3.configure(waveforms=Channel.NOISE,
|
||||
attack=0.005,
|
||||
decay=0.005,
|
||||
sustain=8000/65535,
|
||||
release=0.040,
|
||||
volume=8000/65535)
|
||||
channel4.configure(waveforms=Channel.SQUARE,
|
||||
attack=0.010,
|
||||
decay=0.100,
|
||||
sustain=0,
|
||||
release=0.500,
|
||||
volume=12000/65535)
|
||||
if not synthing:
|
||||
beat = 0
|
||||
next_beat()
|
||||
|
|
|
@ -3,11 +3,20 @@
|
|||
|
||||
/***** 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_KW(Channel_configure_obj, 1, Channel_configure);
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(Channel_restore_obj, Channel_restore);
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(Channel_waveforms_obj, 1, 2, Channel_waveforms);
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(Channel_frequency_obj, 1, 2, Channel_frequency);
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(Channel_volume_obj, 1, 2, Channel_volume);
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(Channel_attack_duration_obj, 1, 2, Channel_attack_duration);
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(Channel_decay_duration_obj, 1, 2, Channel_decay_duration);
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(Channel_sustain_level_obj, 1, 2, Channel_sustain_level);
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(Channel_release_duration_obj, 1, 2, Channel_release_duration);
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(Channel_pulse_width_obj, 1, 2, Channel_pulse_width);
|
||||
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(Channel_stop_playing_obj, Channel_stop_playing);
|
||||
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(GalacticUnicorn___del___obj, GalacticUnicorn___del__);
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(GalacticUnicorn_clear_obj, GalacticUnicorn_clear);
|
||||
|
@ -29,7 +38,15 @@ MP_DEFINE_CONST_FUN_OBJ_2(GalacticUnicorn_synth_channel_obj, GalacticUnicorn_syn
|
|||
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_restore), MP_ROM_PTR(&Channel_restore_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_waveforms), MP_ROM_PTR(&Channel_waveforms_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_frequency), MP_ROM_PTR(&Channel_frequency_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_volume), MP_ROM_PTR(&Channel_volume_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_attack_duration), MP_ROM_PTR(&Channel_attack_duration_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_decay_duration), MP_ROM_PTR(&Channel_decay_duration_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_sustain_level), MP_ROM_PTR(&Channel_sustain_level_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_release_duration), MP_ROM_PTR(&Channel_release_duration_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_pulse_width), MP_ROM_PTR(&Channel_pulse_width_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) },
|
||||
|
|
|
@ -45,17 +45,86 @@ mp_obj_t Channel___del__(mp_obj_t self_in) {
|
|||
}
|
||||
|
||||
|
||||
/***** Helper Functions *****/
|
||||
void set_channel_waveforms(AudioChannel& channel, mp_obj_t in) {
|
||||
int waveforms = mp_obj_get_int(in);
|
||||
const int mask = (NOISE | SQUARE | SAW | TRIANGLE | SINE | WAVE);
|
||||
if(waveforms < 0 || (waveforms & mask) == 0) {
|
||||
mp_raise_ValueError("waveforms invalid. Expected a combination of NOISE, SQUARE, SAW, TRIANGLE, SINE, or WAVE");
|
||||
}
|
||||
channel.waveforms = (uint8_t)waveforms;
|
||||
}
|
||||
|
||||
void set_channel_frequency(AudioChannel& channel, mp_obj_t in) {
|
||||
int freq = mp_obj_get_int(in);
|
||||
if(freq <= 0 || freq > UINT16_MAX) {
|
||||
mp_raise_ValueError("frequency out of range. Expected greater than 0Hz to 65535Hz");
|
||||
}
|
||||
channel.frequency = (uint16_t)freq;
|
||||
}
|
||||
|
||||
void set_channel_volume(AudioChannel& channel, mp_obj_t in) {
|
||||
float volume = mp_obj_get_float(in);
|
||||
if(volume < 0.0f || volume > 1.0f) {
|
||||
mp_raise_ValueError("volume out of range. Expected 0.0 to 1.0");
|
||||
}
|
||||
channel.volume = (uint16_t)(volume * UINT16_MAX);
|
||||
}
|
||||
|
||||
void set_channel_attack(AudioChannel& channel, mp_obj_t in) {
|
||||
int attack_ms = (int)(mp_obj_get_float(in) * 1000.0f);
|
||||
if(attack_ms < 0 || attack_ms > UINT16_MAX) {
|
||||
mp_raise_ValueError("attack out of range. Expected 0.0s to 65.5s");
|
||||
}
|
||||
channel.attack_ms = MAX(attack_ms, 1);
|
||||
}
|
||||
|
||||
void set_channel_decay(AudioChannel& channel, mp_obj_t in) {
|
||||
int decay_ms = (int)(mp_obj_get_float(in) * 1000.0f);
|
||||
if(decay_ms < 0 || decay_ms > UINT16_MAX) {
|
||||
mp_raise_ValueError("decay out of range. Expected 0.0s to 65.5s");
|
||||
}
|
||||
channel.decay_ms = MAX(decay_ms, 1);
|
||||
}
|
||||
|
||||
void set_channel_sustain(AudioChannel& channel, mp_obj_t in) {
|
||||
float sustain = mp_obj_get_float(in);
|
||||
if(sustain < 0.0f || sustain > 1.0f) {
|
||||
mp_raise_ValueError("sustain out of range. Expected 0.0 to 1.0");
|
||||
}
|
||||
channel.sustain = (uint16_t)(sustain * UINT16_MAX);
|
||||
}
|
||||
|
||||
void set_channel_release(AudioChannel& channel, mp_obj_t in) {
|
||||
int release_ms = (int)(mp_obj_get_float(in) * 1000.0f);
|
||||
if(release_ms < 0 || release_ms > UINT16_MAX) {
|
||||
mp_raise_ValueError("release out of range. Expected 0.0s to 65.5s");
|
||||
}
|
||||
channel.release_ms = MAX(release_ms, 1);
|
||||
}
|
||||
|
||||
void set_channel_pulse_width(AudioChannel& channel, mp_obj_t in) {
|
||||
float pulse_width = mp_obj_get_float(in);
|
||||
if(pulse_width < 0.0f || pulse_width > 1.0f) {
|
||||
mp_raise_ValueError("pulse_width out of range. Expected 0.0 to 1.0");
|
||||
}
|
||||
channel.pulse_width = (uint16_t)(pulse_width * UINT16_MAX);
|
||||
}
|
||||
|
||||
|
||||
/***** 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 };
|
||||
enum { ARG_self, ARG_waveforms, ARG_frequency, ARG_volume, ARG_attack, ARG_decay, ARG_sustain, ARG_release, ARG_pulse_width };
|
||||
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 },
|
||||
{ MP_QSTR_waveforms, MP_ARG_OBJ, {.u_obj = mp_const_none} },
|
||||
{ MP_QSTR_frequency, MP_ARG_OBJ, {.u_obj = mp_const_none} },
|
||||
{ MP_QSTR_volume, MP_ARG_OBJ, {.u_obj = mp_const_none} },
|
||||
{ MP_QSTR_attack, MP_ARG_OBJ, {.u_obj = mp_const_none} },
|
||||
{ MP_QSTR_decay, MP_ARG_OBJ, {.u_obj = mp_const_none} },
|
||||
{ MP_QSTR_sustain, MP_ARG_OBJ, {.u_obj = mp_const_none} },
|
||||
{ MP_QSTR_release, MP_ARG_OBJ, {.u_obj = mp_const_none} },
|
||||
{ MP_QSTR_pulse_width, MP_ARG_OBJ, {.u_obj = mp_const_none} }
|
||||
};
|
||||
|
||||
// Parse args.
|
||||
|
@ -64,25 +133,140 @@ mp_obj_t Channel_configure(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw
|
|||
|
||||
_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;
|
||||
mp_obj_t waveforms = args[ARG_waveforms].u_obj;
|
||||
if(waveforms != mp_const_none) {
|
||||
set_channel_waveforms(*self->channel, waveforms);
|
||||
}
|
||||
|
||||
mp_obj_t frequency = args[ARG_frequency].u_obj;
|
||||
if(frequency != mp_const_none) {
|
||||
set_channel_frequency(*self->channel, frequency);
|
||||
}
|
||||
|
||||
mp_obj_t volume = args[ARG_volume].u_obj;
|
||||
if(volume != mp_const_none) {
|
||||
set_channel_volume(*self->channel, volume);
|
||||
}
|
||||
|
||||
mp_obj_t attack = args[ARG_attack].u_obj;
|
||||
if(attack != mp_const_none) {
|
||||
set_channel_attack(*self->channel, attack);
|
||||
}
|
||||
|
||||
mp_obj_t decay = args[ARG_decay].u_obj;
|
||||
if(decay != mp_const_none) {
|
||||
set_channel_decay(*self->channel, decay);
|
||||
}
|
||||
|
||||
mp_obj_t sustain = args[ARG_sustain].u_obj;
|
||||
if(sustain != mp_const_none) {
|
||||
set_channel_sustain(*self->channel, sustain);
|
||||
}
|
||||
|
||||
mp_obj_t release = args[ARG_release].u_obj;
|
||||
if(release != mp_const_none) {
|
||||
set_channel_release(*self->channel, release);
|
||||
}
|
||||
|
||||
mp_obj_t pulse_width = args[ARG_pulse_width].u_obj;
|
||||
if(pulse_width != mp_const_none) {
|
||||
set_channel_pulse_width(*self->channel, pulse_width);
|
||||
}
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
mp_obj_t Channel_freq(mp_obj_t self_in, mp_obj_t freq_in) {
|
||||
mp_obj_t Channel_restore(mp_obj_t self_in) {
|
||||
_Channel_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Channel_obj_t);
|
||||
self->channel->restore();
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
float freq = mp_obj_get_float(freq_in);
|
||||
if(freq <= 0.0f) {
|
||||
mp_raise_ValueError("freq out of range. Expected greater than 0.0");
|
||||
mp_obj_t Channel_waveforms(size_t n_args, const mp_obj_t *args) {
|
||||
_Channel_obj_t *self = MP_OBJ_TO_PTR2(args[0], _Channel_obj_t);
|
||||
|
||||
if(n_args == 1) {
|
||||
return mp_obj_new_int(self->channel->waveforms);
|
||||
}
|
||||
self->channel->frequency = freq;
|
||||
|
||||
set_channel_waveforms(*self->channel, args[1]);
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
mp_obj_t Channel_frequency(size_t n_args, const mp_obj_t *args) {
|
||||
_Channel_obj_t *self = MP_OBJ_TO_PTR2(args[0], _Channel_obj_t);
|
||||
|
||||
if(n_args == 1) {
|
||||
return mp_obj_new_int(self->channel->frequency);
|
||||
}
|
||||
|
||||
set_channel_frequency(*self->channel, args[1]);
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
mp_obj_t Channel_volume(size_t n_args, const mp_obj_t *args) {
|
||||
_Channel_obj_t *self = MP_OBJ_TO_PTR2(args[0], _Channel_obj_t);
|
||||
|
||||
if(n_args == 1) {
|
||||
return mp_obj_new_float((float)self->channel->volume / UINT16_MAX);
|
||||
}
|
||||
|
||||
set_channel_volume(*self->channel, args[1]);
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
mp_obj_t Channel_attack_duration(size_t n_args, const mp_obj_t *args) {
|
||||
_Channel_obj_t *self = MP_OBJ_TO_PTR2(args[0], _Channel_obj_t);
|
||||
|
||||
if(n_args == 1) {
|
||||
return mp_obj_new_float((float)self->channel->attack_ms / 1000.0f);
|
||||
}
|
||||
|
||||
set_channel_attack(*self->channel, args[1]);
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
mp_obj_t Channel_decay_duration(size_t n_args, const mp_obj_t *args) {
|
||||
_Channel_obj_t *self = MP_OBJ_TO_PTR2(args[0], _Channel_obj_t);
|
||||
|
||||
if(n_args == 1) {
|
||||
return mp_obj_new_float((float)self->channel->decay_ms / 1000.0f);
|
||||
}
|
||||
|
||||
set_channel_decay(*self->channel, args[1]);
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
mp_obj_t Channel_sustain_level(size_t n_args, const mp_obj_t *args) {
|
||||
_Channel_obj_t *self = MP_OBJ_TO_PTR2(args[0], _Channel_obj_t);
|
||||
|
||||
if(n_args == 1) {
|
||||
return mp_obj_new_float((float)self->channel->sustain / UINT16_MAX);
|
||||
}
|
||||
|
||||
set_channel_sustain(*self->channel, args[1]);
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
mp_obj_t Channel_release_duration(size_t n_args, const mp_obj_t *args) {
|
||||
_Channel_obj_t *self = MP_OBJ_TO_PTR2(args[0], _Channel_obj_t);
|
||||
|
||||
if(n_args == 1) {
|
||||
return mp_obj_new_float((float)self->channel->release_ms / 1000.0f);
|
||||
}
|
||||
|
||||
set_channel_release(*self->channel, args[1]);
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
mp_obj_t Channel_pulse_width(size_t n_args, const mp_obj_t *args) {
|
||||
_Channel_obj_t *self = MP_OBJ_TO_PTR2(args[0], _Channel_obj_t);
|
||||
|
||||
if(n_args == 1) {
|
||||
return mp_obj_new_float((float)self->channel->pulse_width / 0xffff);
|
||||
}
|
||||
|
||||
set_channel_pulse_width(*self->channel, args[1]);
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
|
@ -104,10 +288,10 @@ mp_obj_t Channel_play_tone(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw
|
|||
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_frequency, 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} },
|
||||
{ MP_QSTR_attack, MP_ARG_OBJ, {.u_obj = mp_const_none} },
|
||||
{ MP_QSTR_release, MP_ARG_OBJ, {.u_obj = mp_const_none} },
|
||||
};
|
||||
|
||||
// Parse args.
|
||||
|
@ -116,45 +300,35 @@ mp_obj_t Channel_play_tone(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw
|
|||
|
||||
_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");
|
||||
set_channel_frequency(*self->channel, args[ARG_freq].u_obj);
|
||||
|
||||
mp_obj_t volume = args[ARG_volume].u_obj;
|
||||
if(volume != mp_const_none) {
|
||||
set_channel_volume(*self->channel, volume);
|
||||
}
|
||||
else {
|
||||
self->channel->volume = UINT16_MAX;
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
mp_obj_t attack_ms = args[ARG_fade_in].u_obj;
|
||||
if(attack_ms != mp_const_none) {
|
||||
set_channel_attack(*self->channel, attack_ms);
|
||||
}
|
||||
else {
|
||||
self->channel->attack_ms = 1;
|
||||
}
|
||||
|
||||
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);
|
||||
mp_obj_t release_ms = args[ARG_fade_out].u_obj;
|
||||
if(release_ms != mp_const_none) {
|
||||
set_channel_release(*self->channel, release_ms);
|
||||
}
|
||||
else {
|
||||
self->channel->release_ms = 1;
|
||||
}
|
||||
|
||||
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->sustain = UINT16_MAX;
|
||||
|
||||
self->channel->trigger_attack();
|
||||
|
||||
|
|
|
@ -10,11 +10,19 @@ extern void Channel_print(const mp_print_t *print, mp_obj_t self_in, mp_print_ki
|
|||
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_restore(mp_obj_t self_in);
|
||||
extern mp_obj_t Channel_waveforms(size_t n_args, const mp_obj_t *args);
|
||||
extern mp_obj_t Channel_frequency(size_t n_args, const mp_obj_t *args);
|
||||
extern mp_obj_t Channel_volume(size_t n_args, const mp_obj_t *args);
|
||||
extern mp_obj_t Channel_attack_duration(size_t n_args, const mp_obj_t *args);
|
||||
extern mp_obj_t Channel_decay_duration(size_t n_args, const mp_obj_t *args);
|
||||
extern mp_obj_t Channel_sustain_level(size_t n_args, const mp_obj_t *args);
|
||||
extern mp_obj_t Channel_release_duration(size_t n_args, const mp_obj_t *args);
|
||||
extern mp_obj_t Channel_pulse_width(size_t n_args, const mp_obj_t *args);
|
||||
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 mp_obj_t Channel_stop_playing(mp_obj_t self_in);
|
||||
|
||||
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);
|
||||
|
|
Loading…
Reference in New Issue