From 82eee593d157c08618b57fdf5358679c9389995e Mon Sep 17 00:00:00 2001 From: Mitya Selivanov Date: Sat, 30 Sep 2023 13:19:12 +0200 Subject: Sawtooth and square oscillators --- source/saw/main.c | 62 +++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 47 insertions(+), 15 deletions(-) diff --git a/source/saw/main.c b/source/saw/main.c index 3c9accc..d8f0aa6 100644 --- a/source/saw/main.c +++ b/source/saw/main.c @@ -42,6 +42,11 @@ enum { ROLL_DEFAULT_OFFSET_Y = 710, INSTRUMENT_SINE = 0, + INSTRUMENT_SAW_UP, + INSTRUMENT_SAW_DOWN, + INSTRUMENT_SQUARE_UP, + INSTRUMENT_SQUARE_DOWN, + INSTRUMENT_COUNT, TRACK_INPUT_NONE = 0, TRACK_INPUT_INSTRUMENT, @@ -259,6 +264,21 @@ static void saw_playback(i32 frame_count) { saw_playback_frame += frame_count; } +static f64 saw_oscillator(i32 type, f64 t, f64 warp) { + f64 n = t - floor(t); + + switch (type) { + case INSTRUMENT_SINE: return sin(n * (M_PI * 2)); + case INSTRUMENT_SAW_UP: return -1. + n * 2.; + case INSTRUMENT_SAW_DOWN: return 1. - n * 2.; + case INSTRUMENT_SQUARE_UP: return n < .5 + warp / 2. ? -1. : 1.; + case INSTRUMENT_SQUARE_DOWN: return n < .5 + warp / 2. ? 1. : -1.; + default:; + } + + return 0.; +} + static void saw_audio(ma_device *device, void *void_out_, void const *void_in_, ma_uint32 frame_count) { saw_playback(frame_count); @@ -276,7 +296,8 @@ static void saw_audio(ma_device *device, void *void_out_, saw_track_t *track = saw_tracks + saw_voices[n].track; - f64 period = M_PI * 2.; + i32 wave_type = track->instrument; + f64 warp = track->warp; f64 frequency = saw_voices[n].frequency; f64 amplitude = saw_voices[n].amplitude; f64 phase_l = track->phase + saw_voices[n].phase[0]; @@ -292,10 +313,14 @@ static void saw_audio(ma_device *device, void *void_out_, f64 t = (f64) saw_voices[n].time / (f64) SAW_SAMPLE_RATE; f64 a = amplitude * saw_envelope(t, attack, decay, sustain, duration, release); - out[i * 2] += (f32) (sin((t * frequency + phase_l) * period) * + out[i * 2] += (f32) (saw_oscillator(wave_type, + t * frequency + phase_l, + warp) * a); - out[i * 2 + 1] += - (f32) (sin((t * frequency + phase_r) * period) * a); + out[i * 2 + 1] += (f32) (saw_oscillator(wave_type, + t * frequency + phase_r, + warp) * + a); saw_voices[n].time++; @@ -683,7 +708,7 @@ static void saw_ui_track(saw_track_t *track, i64 x0, i64 y0, switch (input_index) { case TRACK_INPUT_INSTRUMENT: - track->value_buffer = track->instrument * 100; + track->value_buffer = track->instrument * 500; break; case TRACK_INPUT_UNISON: @@ -748,11 +773,12 @@ static void saw_ui_track(saw_track_t *track, i64 x0, i64 y0, title.values, title.values + title.size); next_y = header_offset + text_height; - char buf_instr[][100] = { "Sine" }; + char buf_instr[][100] = { "Sine", "Saw up", "Saw down", "Square up", + "Square down" }; nvgText(saw_nvg, x0 + border * 2, frame_height - y0 - height + next_y - border * 2, "Instrument", 0); - if (track->instrument >= 0 && track->instrument <= INSTRUMENT_SINE) + if (track->instrument >= 0 && track->instrument < INSTRUMENT_COUNT) nvgText(saw_nvg, x0 + column_width + border * 2, frame_height - y0 - height + next_y - border * 2, buf_instr[track->instrument], 0); @@ -954,9 +980,9 @@ static void saw_ui_roll(saw_roll_t *roll, i64 x0, i64 y0, i64 width, i32 y = frame_height - y0 - (pitch + 1) * pianokey_height + roll->offset_y; - if (y + border > frame_height - y0 - pianokey_height) + if (y > frame_height - y0 - pianokey_height) continue; - if (y + border < frame_height - y0 - height + text_height) + if (y < frame_height - y0 - height + text_height) break; i32 h = pianokey_height; @@ -1041,10 +1067,10 @@ static void saw_ui_roll(saw_roll_t *roll, i64 x0, i64 y0, i64 width, i32 y = frame_height - y0 - (note->pitch + 1) * pianokey_height + roll->offset_y; - if (y + border > frame_height - y0 - pianokey_height) + if (y + pianokey_height > frame_height - y0) + continue; + if (y < frame_height - y0 - height + text_height) continue; - if (y + border < frame_height - y0 - height + text_height) - break; i64 x = x0 + pianokey_width + sheet_offset + roll->offset_x + (note->time * roll->rate * sheet_scale) / SAW_SAMPLE_RATE; @@ -1056,6 +1082,8 @@ static void saw_ui_roll(saw_roll_t *roll, i64 x0, i64 y0, i64 width, (saw_mouse_x >= x && saw_mouse_x < x + w && saw_mouse_y >= y && saw_mouse_y < y + h); + if (x >= x0 + width) + continue; if (x + w - sheet_scale < x0 + pianokey_width + sheet_offset) continue; @@ -1256,7 +1284,7 @@ static void saw_init(void) { for (i32 i = 0; i < TRACK_COUNT; i++) saw_tracks[i] = (saw_track_t) { .instrument = INSTRUMENT_SINE, - .warp = .5, + .warp = .0, .phase = .0, .unison = 1, .spread = .1, @@ -1618,8 +1646,12 @@ static void saw_event(sapp_event const *event) { switch (track->value_input) { case TRACK_INPUT_INSTRUMENT: - // TODO - // + track->instrument = (i64) (track->value_buffer * .002 + + 0.5); + if (track->instrument < 0) + track->instrument = 0; + if (track->instrument >= INSTRUMENT_COUNT) + track->instrument = INSTRUMENT_COUNT - 1; break; case TRACK_INPUT_WARP: -- cgit v1.2.3