summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMitya Selivanov <automainint@guattari.tech>2023-09-30 13:19:12 +0200
committerMitya Selivanov <automainint@guattari.tech>2023-09-30 13:19:12 +0200
commit82eee593d157c08618b57fdf5358679c9389995e (patch)
tree7504501e2184e584bfd80df686db4aa03cbb8e50
parent5a38fcf873c9a507b79ab799edf264c2e0654460 (diff)
downloadsaw-82eee593d157c08618b57fdf5358679c9389995e.zip
Sawtooth and square oscillators
-rw-r--r--source/saw/main.c62
1 files 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: