summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorMitya Selivanov <automainint@guattari.tech>2024-03-02 00:59:38 +0100
committerMitya Selivanov <automainint@guattari.tech>2024-03-02 00:59:38 +0100
commit7eb5ff91b2778e38dac27ddb402fd741f9614256 (patch)
treeadd7841f47d51fe80113e05a4a056e111d1d78e5 /source
parentce2639d06244e3692ddda0e773ad88428c7dfcca (diff)
downloadsaw-7eb5ff91b2778e38dac27ddb402fd741f9614256.zip
Refactor: use float for UI coordinates
Diffstat (limited to 'source')
-rw-r--r--source/saw/main.c609
1 files changed, 313 insertions, 296 deletions
diff --git a/source/saw/main.c b/source/saw/main.c
index 8b29fd4..d278187 100644
--- a/source/saw/main.c
+++ b/source/saw/main.c
@@ -25,6 +25,7 @@
#include "../kit/input_buffer.h"
#include "../kit/threads.h"
#include "../kit/status.h"
+#include <math.h>
#if defined(__EMSCRIPTEN__)
# include <GLES3/gl3.h>
@@ -64,7 +65,7 @@
// Constants
//
-#define TIME_EPS 0.0001
+#define EPS 0.00001
#define REFERENCE_PITCH 440.0 // A_4
#define EQUAL_TEMPERAMENT_FACTOR 1.05946309436 // 2^(1/12)
#define GLOBAL_VOLUME 2.0
@@ -156,8 +157,8 @@ typedef struct {
i64 time;
i64 duration;
i64 loop_duration;
- i64 ui_offset_x;
- i64 ui_offset_y;
+ f64 ui_offset_x;
+ f64 ui_offset_y;
// dynamic properties
//
@@ -215,8 +216,8 @@ typedef struct {
i32 grid_roll;
i32 grid_cell;
b8 ui_offset_input;
- i64 ui_offset_x;
- i64 ui_offset_y;
+ f64 ui_offset_x;
+ f64 ui_offset_y;
b8 duplicate_input;
} saw_compose_t;
@@ -310,8 +311,8 @@ static saw_compose_t saw_compose = {
.grid_roll = 0,
.grid_cell = 0,
.ui_offset_input = 0,
- .ui_offset_x = 0,
- .ui_offset_y = 0,
+ .ui_offset_x = 0.,
+ .ui_offset_y = 0.,
.duplicate_input = 0,
};
@@ -666,7 +667,7 @@ static void saw_audio_render(void) {
sustain, duration,
release);
- if (frequency < TIME_EPS)
+ if (frequency < EPS)
break;
f64 crossfade = (sam->crossfade * sam->base_frequency) /
@@ -684,15 +685,14 @@ static void saw_audio_render(void) {
//
f64 q = t;
- if (sample_duration > TIME_EPS)
+ if (sample_duration > EPS)
q -= sample_duration * floor(q / sample_duration);
q += sample_begin;
f64 u0 = 1.;
- if (sample_duration > TIME_EPS &&
- crossfade > TIME_EPS && t >= sample_duration &&
- q < crossfade) {
+ if (sample_duration > EPS && crossfade > EPS &&
+ t >= sample_duration && q < crossfade) {
// Play the body crossfade
//
@@ -714,7 +714,7 @@ static void saw_audio_render(void) {
f64 u = u0;
if (t >= sample_duration && q < crossfade &&
- crossfade > TIME_EPS)
+ crossfade > EPS)
u *= q / crossfade;
f64 r = sample_begin + q;
@@ -1086,9 +1086,9 @@ static ib_token_t saw_parse_roll(ib_token_t tok, saw_roll_t *roll) {
tok = next;
}
else if (AR_EQUAL(ib_str(name), SZ("ui_offset"))) {
- i64 x, y;
- ib_token_t next = saw_parse_int(tok, &x);
- next = saw_parse_int(next, &y);
+ f64 x, y;
+ ib_token_t next = saw_parse_float(tok, &x);
+ next = saw_parse_float(next, &y);
if (next.status == KIT_OK) {
tok = next;
@@ -1463,8 +1463,8 @@ static void saw_project_print_to_file(str_t file_name) {
fprintf(f, " time %lld\n", roll->time);
fprintf(f, " duration %lld\n", roll->duration);
fprintf(f, " loop_duration %lld\n", roll->loop_duration);
- fprintf(f, " ui_offset %lld %lld\n\n",
- roll->ui_offset_x, roll->ui_offset_y);
+ fprintf(f, " ui_offset %f %f\n\n", roll->ui_offset_x,
+ roll->ui_offset_y);
}
fprintf(f, "}\n");
@@ -1529,7 +1529,7 @@ static void saw_project_print_to_file(str_t file_name) {
//
// TODO
// - UI library and tests.
-// - Use floating-point values for coordinates.
+// - Fix Y-axis inconsistency.
//
// ================================================================
@@ -1541,6 +1541,9 @@ static void saw_ui_end(void) {
if (saw_ui_input_active != -1 && !saw_lbutton_down) {
assert(0);
+ // Make sure to deactivate the input when the mouse button is not
+ // down.
+
saw_ui_input_active = -1;
#ifndef __EMSCRIPTEN__
@@ -1549,11 +1552,11 @@ static void saw_ui_end(void) {
}
}
-static b8 saw_ui_button(i64 x0, i64 y0, i64 width, i64 height,
+static b8 saw_ui_button(f64 x0, f64 y0, f64 width, f64 height,
i64 color_index, str_t icon, str_t label,
b8 is_active) {
- i64 frame_height = sapp_height();
- i64 y = frame_height - y0 - height;
+ f64 frame_height = sapp_height();
+ f64 y = frame_height - y0 - height;
b8 has_cursor = saw_mouse_x >= x0 && saw_mouse_x < x0 + width &&
saw_mouse_y >= y && saw_mouse_y < y + height;
saw_ui_color_t c = saw_ui_colors[color_index];
@@ -1569,36 +1572,36 @@ static b8 saw_ui_button(i64 x0, i64 y0, i64 width, i64 height,
c.normal[2], c.normal[3]));
if (icon.size > 0) {
- nvgFontSize(saw_nvg, (height * 3) / 5);
+ nvgFontSize(saw_nvg, height * .6);
nvgFontFaceId(saw_nvg, saw_font_icons);
nvgTextAlign(saw_nvg, NVG_ALIGN_CENTER | NVG_ALIGN_MIDDLE);
- nvgText(saw_nvg, x0 + height / 2, y + height / 2, icon.values,
+ nvgText(saw_nvg, x0 + height * .5, y + height * .5, icon.values,
icon.values + icon.size);
x0 += height;
- width -= height * 2;
+ width -= height * 2.;
}
if (label.size > 0) {
- nvgFontSize(saw_nvg, (height * 4) / 5);
+ nvgFontSize(saw_nvg, height * .8);
nvgFontFaceId(saw_nvg, saw_font_text);
nvgTextAlign(saw_nvg, NVG_ALIGN_CENTER | NVG_ALIGN_MIDDLE);
- nvgText(saw_nvg, x0 + width / 2, y + height / 2, label.values,
+ nvgText(saw_nvg, x0 + width * .5, y + height * .5, label.values,
label.values + label.size);
}
return saw_lbutton_click && has_cursor;
}
-static void saw_ui_value_float(i64 x0, i64 y0, i64 width, i64 height,
+static void saw_ui_value_float(f64 x0, f64 y0, f64 width, f64 height,
i64 color_index, str_t label,
f64 scale, f64 min, f64 max,
f64 *data) {
- assert(data != NULL && scale != .0);
- if (data == NULL || scale == .0)
+ assert(data != NULL && (scale < -EPS || scale > EPS));
+ if (data == NULL || !(scale < -EPS || scale > EPS))
return;
- i64 frame_height = sapp_height();
- i64 y = frame_height - y0 - height;
+ f64 frame_height = sapp_height();
+ f64 y = frame_height - y0 - height;
b8 has_cursor = saw_mouse_x >= x0 && saw_mouse_x < x0 + width &&
saw_mouse_y >= y && saw_mouse_y < y + height;
saw_ui_color_t c = saw_ui_colors[color_index];
@@ -1618,9 +1621,9 @@ static void saw_ui_value_float(i64 x0, i64 y0, i64 width, i64 height,
if (saw_ui_input_active == saw_ui_input_index) {
if (saw_lbutton_down) {
- saw_ui_input_buffer -= saw_shift_on ? saw_mouse_dy * 300
+ saw_ui_input_buffer -= saw_shift_on ? saw_mouse_dy * 300.
: saw_ctrl_on ? saw_mouse_dy
- : saw_mouse_dy * 20;
+ : saw_mouse_dy * 20.;
} else {
saw_ui_input_active = -1;
@@ -1644,19 +1647,19 @@ static void saw_ui_value_float(i64 x0, i64 y0, i64 width, i64 height,
if (saw_ui_input_active == saw_ui_input_index ||
(saw_ui_input_active == -1 && has_cursor)) {
nvgBeginPath(saw_nvg);
- nvgRect(saw_nvg, x0 + width / 2, y, width / 2, height);
+ nvgRect(saw_nvg, x0 + width * .5, y, width * .5, height);
nvgFillColor(saw_nvg, nvgRGBAf(.9f, .95f, .9f, .5f));
nvgFill(saw_nvg);
}
- nvgFontSize(saw_nvg, (height * 4) / 5);
+ nvgFontSize(saw_nvg, height * .8);
nvgFontFaceId(saw_nvg, saw_font_text);
if (label.size > 0) {
nvgFillColor(saw_nvg, nvgRGBAf(c.normal[0], c.normal[1],
c.normal[2], c.normal[3]));
nvgTextAlign(saw_nvg, NVG_ALIGN_LEFT | NVG_ALIGN_MIDDLE);
- nvgText(saw_nvg, x0, y + (height * 5) / 8, label.values,
+ nvgText(saw_nvg, x0, y + height * 5. * .125, label.values,
label.values + label.size);
x0 += width / 2;
}
@@ -1670,7 +1673,8 @@ static void saw_ui_value_float(i64 x0, i64 y0, i64 width, i64 height,
nvgTextAlign(saw_nvg, NVG_ALIGN_CENTER | NVG_ALIGN_MIDDLE);
c8 buf[256];
sprintf(buf, "%.3f", (f32) *data);
- nvgText(saw_nvg, x0 + width / 4, y + (height * 5) / 8, buf, NULL);
+ nvgText(saw_nvg, x0 + width * .25, y + height * 5. * .125, buf,
+ NULL);
}
// Increment UI element input index
@@ -1679,15 +1683,15 @@ static void saw_ui_value_float(i64 x0, i64 y0, i64 width, i64 height,
++saw_ui_input_index;
}
-static void saw_ui_value_int(i64 x0, i64 y0, i64 width, i64 height,
+static void saw_ui_value_int(f64 x0, f64 y0, f64 width, f64 height,
i64 color_index, str_t label, f64 scale,
i64 min, i64 max, i64 *data) {
- assert(data != NULL && scale != .0);
- if (data == NULL || scale == .0)
+ assert(data != NULL && (scale < -EPS || scale > EPS));
+ if (data == NULL || !(scale < -EPS || scale > EPS))
return;
- i64 frame_height = sapp_height();
- i64 y = frame_height - y0 - height;
+ f64 frame_height = sapp_height();
+ f64 y = frame_height - y0 - height;
b8 has_cursor = saw_mouse_x >= x0 && saw_mouse_x < x0 + width &&
saw_mouse_y >= y && saw_mouse_y < y + height;
saw_ui_color_t c = saw_ui_colors[color_index];
@@ -1707,9 +1711,9 @@ static void saw_ui_value_int(i64 x0, i64 y0, i64 width, i64 height,
if (saw_ui_input_active == saw_ui_input_index) {
if (saw_lbutton_down) {
- saw_ui_input_buffer -= saw_shift_on ? saw_mouse_dy * 300
+ saw_ui_input_buffer -= saw_shift_on ? saw_mouse_dy * 300.
: saw_ctrl_on ? saw_mouse_dy
- : saw_mouse_dy * 20;
+ : saw_mouse_dy * 20.;
} else {
saw_ui_input_active = -1;
@@ -1733,7 +1737,7 @@ static void saw_ui_value_int(i64 x0, i64 y0, i64 width, i64 height,
if (saw_ui_input_active == saw_ui_input_index ||
(saw_ui_input_active == -1 && has_cursor)) {
nvgBeginPath(saw_nvg);
- nvgRect(saw_nvg, x0 + width / 2, y, width / 2, height);
+ nvgRect(saw_nvg, x0 + width * .5, y, width * .5, height);
nvgFillColor(saw_nvg, nvgRGBAf(.9f, .95f, .9f, .5f));
nvgFill(saw_nvg);
}
@@ -1759,7 +1763,8 @@ static void saw_ui_value_int(i64 x0, i64 y0, i64 width, i64 height,
nvgTextAlign(saw_nvg, NVG_ALIGN_CENTER | NVG_ALIGN_MIDDLE);
c8 buf[256];
sprintf(buf, "%lld", *data);
- nvgText(saw_nvg, x0 + width / 4, y + (height * 5) / 8, buf, NULL);
+ nvgText(saw_nvg, x0 + width * .25, y + (height * 5.) * .125, buf,
+ NULL);
}
// Increment UI element input index
@@ -1768,11 +1773,12 @@ static void saw_ui_value_int(i64 x0, i64 y0, i64 width, i64 height,
++saw_ui_input_index;
}
-static void saw_ui_value_list(i64 x0, i64 y0, i64 width, i64 height,
+static void saw_ui_value_list(f64 x0, f64 y0, f64 width, f64 height,
i64 color_index, str_t label, f64 scale,
i64 size, str_t *names, i32 *data) {
- assert(data != NULL && names != NULL && scale != .0);
- if (data == NULL || names == NULL || scale == .0)
+ assert(data != NULL && names != NULL &&
+ (scale < -EPS || scale > EPS));
+ if (data == NULL || names == NULL || !(scale < -EPS || scale > EPS))
return;
i64 frame_height = sapp_height();
@@ -1796,9 +1802,9 @@ static void saw_ui_value_list(i64 x0, i64 y0, i64 width, i64 height,
if (saw_ui_input_active == saw_ui_input_index) {
if (saw_lbutton_down) {
- saw_ui_input_buffer -= saw_shift_on ? saw_mouse_dy * 300
+ saw_ui_input_buffer -= saw_shift_on ? saw_mouse_dy * 300.
: saw_ctrl_on ? saw_mouse_dy
- : saw_mouse_dy * 20;
+ : saw_mouse_dy * 20.;
} else {
saw_ui_input_active = -1;
@@ -1822,19 +1828,19 @@ static void saw_ui_value_list(i64 x0, i64 y0, i64 width, i64 height,
if (saw_ui_input_active == saw_ui_input_index ||
(saw_ui_input_active == -1 && has_cursor)) {
nvgBeginPath(saw_nvg);
- nvgRect(saw_nvg, x0 + width / 2, y, width / 2, height);
+ nvgRect(saw_nvg, x0 + width * .5, y, width * .5, height);
nvgFillColor(saw_nvg, nvgRGBAf(.9f, .95f, .9f, .5f));
nvgFill(saw_nvg);
}
- nvgFontSize(saw_nvg, (height * 4) / 5);
+ nvgFontSize(saw_nvg, height * .8);
nvgFontFaceId(saw_nvg, saw_font_text);
if (label.size > 0) {
nvgFillColor(saw_nvg, nvgRGBAf(c.normal[0], c.normal[1],
c.normal[2], c.normal[3]));
nvgTextAlign(saw_nvg, NVG_ALIGN_LEFT | NVG_ALIGN_MIDDLE);
- nvgText(saw_nvg, x0, y + (height * 5) / 8, label.values,
+ nvgText(saw_nvg, x0, y + height * 5 * .125, label.values,
label.values + label.size);
x0 += width / 2;
}
@@ -1847,8 +1853,8 @@ static void saw_ui_value_list(i64 x0, i64 y0, i64 width, i64 height,
c.active[2], c.active[3]));
nvgTextAlign(saw_nvg, NVG_ALIGN_CENTER | NVG_ALIGN_MIDDLE);
str_t s = names[*data];
- nvgText(saw_nvg, x0 + width / 4, y + (height * 5) / 8, s.values,
- s.values + s.size);
+ nvgText(saw_nvg, x0 + width * .25, y + height * 5 * .125,
+ s.values, s.values + s.size);
}
// Increment UI element input index
@@ -1859,21 +1865,21 @@ static void saw_ui_value_list(i64 x0, i64 y0, i64 width, i64 height,
static void saw_ui_reset_offset(void) {
if (saw_current_roll != -1) {
- saw_rolls[saw_current_roll].ui_offset_x = 0;
+ saw_rolls[saw_current_roll].ui_offset_x = 0.;
saw_rolls[saw_current_roll].ui_offset_y =
ROLL_DEFAULT_UI_OFFSET_Y;
}
- saw_compose.ui_offset_x = 0;
- saw_compose.ui_offset_y = 0;
+ saw_compose.ui_offset_x = 0.;
+ saw_compose.ui_offset_y = 0.;
}
-static void saw_ui_header(i64 x0, u64 y0, u64 width, i64 height) {
- if (height > (2 * width) / 15)
- height = (2 * width) / 15;
+static void saw_ui_header(f64 x0, f64 y0, f64 width, f64 height) {
+ if (height > 2. * width / 15.)
+ height = 2. * width / 15.;
- i64 x = x0;
- i64 s = height;
+ f64 x = x0;
+ f64 s = height;
c8 backward_fast[] = "\uf049";
c8 play[] = "\uf04b";
@@ -1924,24 +1930,26 @@ static void saw_ui_header(i64 x0, u64 y0, u64 width, i64 height) {
saw_edit_mode = EDIT_MODE_CLONE;
}
-static void saw_ui_compose(i64 x0, i64 y0, i64 width, i64 height) {
- i64 frame_height = sapp_height();
+static void saw_ui_compose(f64 x0, f64 y0, f64 width, f64 height) {
+ f64 frame_height = sapp_height();
+ f64 track_height = 60.;
+ f64 grid_scale = 50.;
+ f64 grid_rate = 3.;
+ f64 border = 2.;
- i64 track_height = 60;
- i64 grid_scale = 50;
- i64 grid_rate = 3;
- i64 border = 2;
+ assert(track_height > EPS);
+ assert(grid_rate > EPS);
+ assert(grid_scale > EPS);
// Time bar
//
nvgBeginPath(saw_nvg);
nvgRect(saw_nvg, x0, frame_height - y0 - height + border, width,
- track_height / 5 - border * 2);
+ track_height * .2 - border * 2.);
nvgRect(saw_nvg, x0,
- frame_height - y0 - height + border +
- (track_height * 4) / 5,
- width, track_height / 5 - border * 2);
+ frame_height - y0 - height + border + track_height * .8,
+ width, track_height * .2 - border * 2.);
nvgFillColor(saw_nvg, nvgRGBA(180, 140, 120, 160));
nvgFill(saw_nvg);
@@ -1956,20 +1964,23 @@ static void saw_ui_compose(i64 x0, i64 y0, i64 width, i64 height) {
if (!roll->enabled)
continue;
- i64 top = frame_height - y0 - height + track_height;
- i64 bottom = frame_height - y0;
- i64 dx = x0 + saw_compose.ui_offset_x;
- i64 l = dx + (roll->time * grid_scale) / SAMPLE_RATE;
- i64 r = l + (roll->duration * grid_scale) / SAMPLE_RATE;
- i64 u = frame_height - y0 - height + track_height +
+ f64 top = frame_height - y0 - height + track_height;
+ f64 bottom = frame_height - y0;
+ f64 dx = x0 + saw_compose.ui_offset_x;
+ f64 l = dx + (roll->time * grid_scale) / SAMPLE_RATE;
+ f64 r = l + (roll->duration * grid_scale) / SAMPLE_RATE;
+ f64 u = frame_height - y0 - height + track_height +
saw_compose.ui_offset_y + roll->track * track_height;
- i64 d = u + track_height;
- i64 s = grid_scale / grid_rate;
+ f64 d = u + track_height;
+
+ f64 s = grid_scale / grid_rate;
+
+ assert(s > EPS);
if (l < x0)
- l = dx + ((x0 - dx + (s - 1)) / s) * s;
+ l = x0;
if (r >= x0 + width)
- r = dx + ((x0 + width - dx) / s) * s;
+ r = x0 + width;
if (u < top)
u = top;
if (d > bottom)
@@ -1978,10 +1989,10 @@ static void saw_ui_compose(i64 x0, i64 y0, i64 width, i64 height) {
if (l >= r || u >= d)
continue;
- i64 x = l;
- i64 w = r - l;
- i64 y = u;
- i64 h = d - u;
+ f64 x = l;
+ f64 w = r - l;
+ f64 y = u;
+ f64 h = d - u;
b8 is_choosen = (saw_current_roll == i);
@@ -1995,8 +2006,8 @@ static void saw_ui_compose(i64 x0, i64 y0, i64 width, i64 height) {
saw_mouse_y >= y && saw_mouse_y < y + h);
nvgBeginPath(saw_nvg);
- nvgRect(saw_nvg, x + border, y + border, w - border * 2,
- h - border * 2);
+ nvgRect(saw_nvg, x + border, y + border, w - border * 2.,
+ h - border * 2.);
nvgFillColor(saw_nvg, is_choosen ? nvgRGBA(240, 230, 200, 255)
: is_playing ? nvgRGBA(240, 210, 180, 240)
: has_cursor ? nvgRGBA(210, 210, 255, 255)
@@ -2012,21 +2023,24 @@ static void saw_ui_compose(i64 x0, i64 y0, i64 width, i64 height) {
} else {
if (saw_edit_mode == EDIT_MODE_HAND && saw_lbutton_click) {
if (saw_current_roll == i) {
- i64 cell = ((saw_mouse_x - saw_compose.ui_offset_x) *
- grid_rate) /
- grid_scale;
- i64 c0 = (roll->time * grid_rate) / SAMPLE_RATE;
- i64 c1 = c0 + (roll->duration * grid_rate) / SAMPLE_RATE;
+ i64 cell = (i64) floor(
+ ((saw_mouse_x - saw_compose.ui_offset_x) *
+ grid_rate) /
+ grid_scale);
+ i64 c0 = (i64) floor((roll->time * grid_rate) /
+ SAMPLE_RATE);
+ i64 c1 = c0 + (i64) floor((roll->duration * grid_rate) /
+ SAMPLE_RATE);
saw_compose.grid_input = 1;
saw_compose.grid_roll = saw_current_roll;
if (cell - c0 > c1 - cell) {
saw_compose.grid_cell = c0;
- roll->duration = ((cell - c0 + 1) * SAMPLE_RATE) /
- grid_rate;
+ roll->duration = (i64) floor(
+ ((cell - c0 + 1) * SAMPLE_RATE) / grid_rate);
} else {
saw_compose.grid_cell = c1 - 1;
- roll->duration = ((c1 - cell + 1) * SAMPLE_RATE) /
- grid_rate;
+ roll->duration = (i64) floor(
+ ((c1 - cell + 1) * SAMPLE_RATE) / grid_rate);
}
} else {
saw_current_roll = i;
@@ -2055,14 +2069,14 @@ static void saw_ui_compose(i64 x0, i64 y0, i64 width, i64 height) {
saw_mouse_y >=
frame_height - y0 - height + track_height &&
saw_mouse_y < frame_height - y0) {
- i64 track = (saw_mouse_y - saw_compose.ui_offset_y -
- frame_height + y0 + height) /
- track_height -
+ i64 track = (i64) floor((saw_mouse_y - saw_compose.ui_offset_y -
+ frame_height + y0 + height) /
+ track_height) -
1;
- i64 cell = ((saw_mouse_x - saw_compose.ui_offset_x) *
- grid_rate) /
- grid_scale;
- i64 frame = (cell * SAMPLE_RATE) / grid_rate;
+ i64 cell = (i64) floor(
+ ((saw_mouse_x - saw_compose.ui_offset_x) * grid_rate) /
+ grid_scale);
+ i64 frame = (i64) floor((cell * SAMPLE_RATE) / grid_rate);
i64 n = -1;
@@ -2072,9 +2086,9 @@ static void saw_ui_compose(i64 x0, i64 y0, i64 width, i64 height) {
break;
}
- i64 x = x0 + saw_compose.ui_offset_x +
+ f64 x = x0 + saw_compose.ui_offset_x +
(frame * grid_scale) / SAMPLE_RATE;
- i64 y = frame_height - y0 - height + track_height +
+ f64 y = frame_height - y0 - height + track_height +
saw_compose.ui_offset_y + track * track_height;
if (track < 0 || track >= TRACK_COUNT || x < x0 ||
@@ -2097,7 +2111,8 @@ static void saw_ui_compose(i64 x0, i64 y0, i64 width, i64 height) {
.rate = ROLL_DEFAULT_RATE,
.notes = { 0 },
.time = frame,
- .duration = (ROLL_DEFAULT_RATE * SAMPLE_RATE) / grid_rate,
+ .duration = (i64) floor((ROLL_DEFAULT_RATE * SAMPLE_RATE) /
+ grid_rate),
.loop_duration = 0,
.ui_offset_x = 0,
.ui_offset_y = ROLL_DEFAULT_UI_OFFSET_Y,
@@ -2121,18 +2136,18 @@ static void saw_ui_compose(i64 x0, i64 y0, i64 width, i64 height) {
if (saw_current_roll == -1)
break;
- i64 track = (saw_mouse_y - saw_compose.ui_offset_y -
- frame_height + y0 + height) /
- track_height -
+ i64 track = (i64) floor((saw_mouse_y - saw_compose.ui_offset_y -
+ frame_height + y0 + height) /
+ track_height) -
1;
- i64 cell = ((saw_mouse_x - saw_compose.ui_offset_x) *
- grid_rate) /
- grid_scale;
+ i64 cell = (i64) floor(
+ ((saw_mouse_x - saw_compose.ui_offset_x) * grid_rate) /
+ grid_scale);
if (cell < 0 || track < 0 || track >= TRACK_COUNT)
break;
- i64 frame = (cell * SAMPLE_RATE) / grid_rate;
+ i64 frame = (i64) floor((cell * SAMPLE_RATE) / grid_rate);
i64 n = -1;
@@ -2189,22 +2204,22 @@ static void saw_ui_compose(i64 x0, i64 y0, i64 width, i64 height) {
if (saw_compose.grid_input) {
if (saw_edit_mode == EDIT_MODE_HAND && saw_lbutton_down) {
- i64 cell = ((saw_mouse_x - saw_compose.ui_offset_x) *
- grid_rate) /
- grid_scale;
+ i64 cell = (i64) floor(
+ ((saw_mouse_x - saw_compose.ui_offset_x) * grid_rate) /
+ grid_scale);
saw_roll_t *p = saw_rolls + saw_compose.grid_roll;
if (cell >= 0) {
if (saw_compose.grid_cell <= cell) {
p->time = (saw_compose.grid_cell * SAMPLE_RATE) / grid_rate;
- p->duration = ((1 + cell - saw_compose.grid_cell) *
- SAMPLE_RATE) /
- grid_rate;
+ p->duration = (i64) floor(
+ ((1 + cell - saw_compose.grid_cell) * SAMPLE_RATE) /
+ grid_rate);
} else {
p->time = (cell * SAMPLE_RATE) / grid_rate;
- p->duration = ((1 + saw_compose.grid_cell - cell) *
- SAMPLE_RATE) /
- grid_rate;
+ p->duration = (i64) floor(
+ ((1 + saw_compose.grid_cell - cell) * SAMPLE_RATE) /
+ grid_rate);
}
}
@@ -2214,28 +2229,31 @@ static void saw_ui_compose(i64 x0, i64 y0, i64 width, i64 height) {
saw_roll_t *q = saw_rolls + i;
if (!q->enabled || p->track != q->track)
continue;
- i64 q_cell = (q->time * grid_rate) / SAMPLE_RATE;
- i64 q_size = (q->duration * grid_rate) / SAMPLE_RATE;
+ i64 q_cell = (i64) floor((q->time * grid_rate) / SAMPLE_RATE);
+ i64 q_size = (i64) floor((q->duration * grid_rate) /
+ SAMPLE_RATE);
if (saw_compose.grid_cell < q_cell && cell >= q_cell) {
cell = q_cell - 1;
- p->time = (saw_compose.grid_cell * SAMPLE_RATE) / grid_rate;
- p->duration = ((q_cell - saw_compose.grid_cell) *
- SAMPLE_RATE) /
- grid_rate;
+ p->time = (i64) floor(
+ (saw_compose.grid_cell * SAMPLE_RATE) / grid_rate);
+ p->duration = (i64) floor(
+ ((q_cell - saw_compose.grid_cell) * SAMPLE_RATE) /
+ grid_rate);
}
if (saw_compose.grid_cell > q_cell &&
cell < q_cell + q_size) {
- cell = q_cell + q_size;
- p->time = ((q_cell + q_size) * SAMPLE_RATE) / grid_rate;
- p->duration = ((1 + saw_compose.grid_cell - q_cell -
- q_size) *
- SAMPLE_RATE) /
- grid_rate;
+ cell = q_cell + q_size;
+ p->time = (i64) floor(((q_cell + q_size) * SAMPLE_RATE) /
+ grid_rate);
+ p->duration = (i64) floor(
+ ((1 + saw_compose.grid_cell - q_cell - q_size) *
+ SAMPLE_RATE) /
+ grid_rate);
}
}
if (p->duration <= 0)
- p->duration = SAMPLE_RATE / grid_rate;
+ p->duration = (i64) floor(SAMPLE_RATE / grid_rate);
} else
saw_compose.grid_input = 0;
}
@@ -2243,10 +2261,9 @@ static void saw_ui_compose(i64 x0, i64 y0, i64 width, i64 height) {
// Playback indicator
//
- i64 x = x0 + saw_compose.ui_offset_x - border * 2 +
- (saw_playback_frame * grid_scale + SAMPLE_RATE / 2) /
- SAMPLE_RATE;
- i64 w = border * 4;
+ f64 x = x0 + saw_compose.ui_offset_x - border * 2. +
+ (saw_playback_frame * grid_scale) / SAMPLE_RATE;
+ f64 w = border * 4.;
if (x >= x0 - border * 2 && x < x0 + width) {
nvgBeginPath(saw_nvg);
@@ -2264,13 +2281,14 @@ static void saw_ui_compose(i64 x0, i64 y0, i64 width, i64 height) {
frame_height + y0 + height) /
track_height -
1;
- i64 cell = ((saw_mouse_x - saw_compose.ui_offset_x) * grid_rate) /
- grid_scale;
- i64 x = x0 + saw_compose.ui_offset_x +
+ i64 cell = (i64) floor(
+ ((saw_mouse_x - saw_compose.ui_offset_x) * grid_rate) /
+ grid_scale);
+ f64 x = x0 + saw_compose.ui_offset_x +
(cell * grid_scale) / grid_rate;
- i64 y = frame_height - y0 - height + track_height +
+ f64 y = frame_height - y0 - height + track_height +
saw_compose.ui_offset_y + track * track_height;
- i64 w = grid_scale / grid_rate;
+ f64 w = grid_scale / grid_rate;
if (track >= 0 && track < TRACK_COUNT && x >= x0 &&
x + w < x0 + width &&
@@ -2291,10 +2309,10 @@ static void saw_ui_compose(i64 x0, i64 y0, i64 width, i64 height) {
saw_mouse_x < x0 + width &&
saw_mouse_y >= frame_height - y0 - height &&
saw_mouse_y < frame_height - y0) {
- i64 dx = x0 + saw_compose.ui_offset_x;
- i64 s = grid_scale / grid_rate;
- i64 x = dx + ((saw_mouse_x - dx + s / 2) / s) * s;
- i64 w = border * 4;
+ f64 dx = x0 + saw_compose.ui_offset_x;
+ f64 s = grid_scale / grid_rate;
+ f64 x = dx + ((saw_mouse_x - dx + s / 2) / s) * s;
+ f64 w = border * 4;
nvgBeginPath(saw_nvg);
nvgRect(saw_nvg, x - w / 2, frame_height - y0 - height, w,
@@ -2304,13 +2322,13 @@ static void saw_ui_compose(i64 x0, i64 y0, i64 width, i64 height) {
}
}
-static void saw_ui_choose_instrument(saw_track_t *track, i64 x0,
- i64 y0, i64 width, i64 height) {
- i64 text_height = 40;
- i64 y = y0 + height - text_height;
+static void saw_ui_choose_instrument(saw_track_t *track, f64 x0,
+ f64 y0, f64 width, f64 height) {
+ f64 text_height = 40.;
+ f64 y = y0 + height - text_height;
- x0 += width / 8;
- width = (width * 3) / 4;
+ x0 += width * .125;
+ width *= .75;
if (saw_ui_button(x0, y, width, text_height, TINT_ORANGE,
SZ("\uf83e"), SZ("Oscillator"), 1)) {
@@ -2363,12 +2381,12 @@ static void saw_ui_choose_instrument(saw_track_t *track, i64 x0,
}
}
-static void saw_ui_oscillator(saw_oscillator_t *osc, i64 x0, i64 y0,
- i64 width, i64 height) {
- i64 frame_height = sapp_height();
- i64 text_height = 33;
- i64 x = x0 + width / 12;
- i64 w = (width * 5) / 6;
+static void saw_ui_oscillator(saw_oscillator_t *osc, f64 x0, f64 y0,
+ f64 width, f64 height) {
+ f64 frame_height = sapp_height();
+ f64 text_height = 33.;
+ f64 x = x0 + width / 12.;
+ f64 w = width * 5. / 6.;
str_t wave_names[] = {
SZ("Sine"), SZ("Saw up"), SZ("Saw down"),
@@ -2379,50 +2397,49 @@ static void saw_ui_oscillator(saw_oscillator_t *osc, i64 x0, i64 y0,
TINT_WHITE, SZ("Wave"), 500.,
sizeof wave_names / sizeof *wave_names,
wave_names, &osc->wave);
- saw_ui_value_float(x, y0 + height - text_height * 2, w, text_height,
- TINT_WHITE, SZ("Warp"), 10000, -1., 1.,
- &osc->warp);
+ saw_ui_value_float(x, y0 + height - text_height * 2., w,
+ text_height, TINT_WHITE, SZ("Warp"), 10000, -1.,
+ 1., &osc->warp);
// FIXME
// Looping phase value.
- saw_ui_value_float(x, y0 + height - text_height * 3, w, text_height,
- TINT_WHITE, SZ("Phase"), 10000, 0., 1.,
- &osc->phase);
- saw_ui_value_float(x, y0 + height - text_height * 4, w, text_height,
- TINT_WHITE, SZ("Stereo"), 10000, 0., 2.,
- &osc->stereo_width);
- saw_ui_value_float(x, y0 + height - text_height * 5, w, text_height,
- TINT_WHITE, SZ("Volume"), 10000, 0., 2.,
- &osc->volume);
+ saw_ui_value_float(x, y0 + height - text_height * 3., w,
+ text_height, TINT_WHITE, SZ("Phase"), 10000, 0.,
+ 1., &osc->phase);
+ saw_ui_value_float(x, y0 + height - text_height * 4., w,
+ text_height, TINT_WHITE, SZ("Stereo"), 10000, 0.,
+ 2., &osc->stereo_width);
+ saw_ui_value_float(x, y0 + height - text_height * 5., w,
+ text_height, TINT_WHITE, SZ("Volume"), 10000, 0.,
+ 2., &osc->volume);
nvgFontSize(saw_nvg, text_height);
nvgFontFaceId(saw_nvg, saw_font_text);
nvgFillColor(saw_nvg, nvgRGBA(255, 255, 255, 255));
nvgTextAlign(saw_nvg, NVG_ALIGN_LEFT | NVG_ALIGN_BASELINE);
- nvgText(saw_nvg, x,
- frame_height - y0 - height + (text_height * 13) / 2,
+ nvgText(saw_nvg, x, frame_height - y0 - height + text_height * 6.5,
"Envelope", 0);
- saw_ui_value_float(x, y0 + height - text_height * 8, w, text_height,
- TINT_WHITE, SZ("Sustain"), 10000, 0., 1.,
- &osc->envelope.sustain);
- saw_ui_value_float(x, y0 + height - text_height * 9, w, text_height,
- TINT_WHITE, SZ("Attack"), 100000, 0., 6.,
- &osc->envelope.attack);
- saw_ui_value_float(x, y0 + height - text_height * 10, w,
+ saw_ui_value_float(x, y0 + height - text_height * 8., w,
+ text_height, TINT_WHITE, SZ("Sustain"), 10000,
+ 0., 1., &osc->envelope.sustain);
+ saw_ui_value_float(x, y0 + height - text_height * 9., w,
+ text_height, TINT_WHITE, SZ("Attack"), 100000,
+ 0., 6., &osc->envelope.attack);
+ saw_ui_value_float(x, y0 + height - text_height * 10., w,
text_height, TINT_WHITE, SZ("Decay"), 100000, 0.,
6., &osc->envelope.decay);
- saw_ui_value_float(x, y0 + height - text_height * 11, w,
+ saw_ui_value_float(x, y0 + height - text_height * 11., w,
text_height, TINT_WHITE, SZ("Release"), 100000,
0., 6., &osc->envelope.release);
}
-static void saw_ui_sampler(saw_sampler_t *sampler, i64 x0, i64 y0,
- i64 width, i64 height) {
- i64 frame_height = sapp_height();
- i64 text_height = 33;
- i64 x = x0 + width / 12;
- i64 w = (width * 5) / 6;
- i64 sample_height = text_height * 4;
+static void saw_ui_sampler(saw_sampler_t *sampler, f64 x0, f64 y0,
+ f64 width, f64 height) {
+ f64 frame_height = sapp_height();
+ f64 text_height = 33.;
+ f64 x = x0 + width / 12.;
+ f64 w = width * 5. / 6.;
+ f64 sample_height = text_height * 4.;
if (saw_drop_file_data.size != 0) {
// Load the audio sample from memory
@@ -2495,7 +2512,7 @@ static void saw_ui_sampler(saw_sampler_t *sampler, i64 x0, i64 y0,
nvgBeginPath(saw_nvg);
f64 dw = (f64) w / SAMPLER_OUTLINE_SIZE;
- f64 h = sample_height / 2;
+ f64 h = sample_height * .5;
f64 y = frame_height - y0 - height + h;
assert(dw > .0001);
@@ -2508,28 +2525,32 @@ static void saw_ui_sampler(saw_sampler_t *sampler, i64 x0, i64 y0,
nvgFill(saw_nvg);
}
} else {
- nvgFontSize(saw_nvg, text_height / 2);
+ nvgFontSize(saw_nvg, text_height * .5);
nvgFontFaceId(saw_nvg, saw_font_text);
nvgFillColor(saw_nvg, nvgRGBAf(1.f, .7f, .2f, .5f));
nvgTextAlign(saw_nvg, NVG_ALIGN_CENTER | NVG_ALIGN_MIDDLE);
- nvgText(saw_nvg, x0 + width / 2,
- frame_height - y0 - height + sample_height / 2,
+ nvgText(saw_nvg, x0 + width * .5,
+ frame_height - y0 - height + sample_height * .5,
"Drop a WAV file here", NULL);
}
saw_ui_value_float(x, y0 + height - sample_height - text_height, w,
text_height, TINT_WHITE, SZ("Begin"), 100000, 0.,
60., &sampler->begin);
- saw_ui_value_float(x, y0 + height - sample_height - text_height * 2,
+ saw_ui_value_float(x,
+ y0 + height - sample_height - text_height * 2.,
w, text_height, TINT_WHITE, SZ("End"), 100000,
0., 60., &sampler->end);
- saw_ui_value_float(x, y0 + height - sample_height - text_height * 3,
+ saw_ui_value_float(x,
+ y0 + height - sample_height - text_height * 3.,
w, text_height, TINT_WHITE, SZ("Crossfade"),
100000, 0., 60., &sampler->crossfade);
- saw_ui_value_float(x, y0 + height - sample_height - text_height * 4,
+ saw_ui_value_float(x,
+ y0 + height - sample_height - text_height * 4.,
w, text_height, TINT_WHITE, SZ("Base freq."),
500, 1., 44100., &sampler->base_frequency);
- saw_ui_value_float(x, y0 + height - sample_height - text_height * 5,
+ saw_ui_value_float(x,
+ y0 + height - sample_height - text_height * 5.,
w, text_height, TINT_WHITE, SZ("Volume."), 10000,
0., 2., &sampler->volume);
@@ -2539,46 +2560,47 @@ static void saw_ui_sampler(saw_sampler_t *sampler, i64 x0, i64 y0,
nvgTextAlign(saw_nvg, NVG_ALIGN_LEFT | NVG_ALIGN_BASELINE);
nvgText(saw_nvg, x,
frame_height - y0 - height + sample_height +
- (text_height * 13) / 2,
+ text_height * 6.5,
"Envelope", NULL);
- saw_ui_value_float(x, y0 + height - sample_height - text_height * 8,
+ saw_ui_value_float(x,
+ y0 + height - sample_height - text_height * 8.,
w, text_height, TINT_WHITE, SZ("Sustain"), 10000,
0., 1., &sampler->envelope.sustain);
- saw_ui_value_float(x, y0 + height - sample_height - text_height * 9,
+ saw_ui_value_float(x,
+ y0 + height - sample_height - text_height * 9.,
w, text_height, TINT_WHITE, SZ("Attack"), 100000,
0., 6., &sampler->envelope.attack);
saw_ui_value_float(x,
- y0 + height - sample_height - text_height * 10,
+ y0 + height - sample_height - text_height * 10.,
w, text_height, TINT_WHITE, SZ("Decay"), 100000,
0., 6., &sampler->envelope.decay);
saw_ui_value_float(x,
- y0 + height - sample_height - text_height * 11,
+ y0 + height - sample_height - text_height * 11.,
w, text_height, TINT_WHITE, SZ("Release"),
100000, 0., 6., &sampler->envelope.release);
}
-static void saw_ui_track(saw_track_t *track, i64 x0, i64 y0,
- i64 width, i64 height, str_t title) {
- i64 frame_height = sapp_height();
-
- i64 text_height = 33;
- i64 header_offset = 60;
- i64 border = 2;
+static void saw_ui_track(saw_track_t *track, f64 x0, f64 y0,
+ f64 width, f64 height, str_t title) {
+ f64 frame_height = sapp_height();
+ f64 text_height = 33.;
+ f64 header_offset = 60.;
+ f64 border = 2.;
nvgFontSize(saw_nvg, text_height - border);
nvgFontFaceId(saw_nvg, saw_font_text);
nvgTextAlign(saw_nvg, NVG_ALIGN_LEFT | NVG_ALIGN_BASELINE);
nvgFillColor(saw_nvg, nvgRGBA(255, 255, 255, 255));
- nvgText(saw_nvg, x0 + border * 2,
- frame_height - y0 - height + text_height - border * 2,
+ nvgText(saw_nvg, x0 + border * 2.,
+ frame_height - y0 - height + text_height - border * 2.,
title.values, title.values + title.size);
if (track->instrument != INSTRUMENT_NONE) {
- i64 x = x0 + width - (text_height * 3) / 2;
- i64 y = frame_height - y0 - height;
- i64 s = text_height;
+ f64 x = x0 + width - text_height * 1.5;
+ f64 y = frame_height - y0 - height;
+ f64 s = text_height;
b8 has_cursor = saw_mouse_x >= x && saw_mouse_y >= y &&
saw_mouse_x < x + s && saw_mouse_y < y + s;
@@ -2621,18 +2643,19 @@ static void saw_ui_track(saw_track_t *track, i64 x0, i64 y0,
}
}
-static void saw_ui_roll(saw_roll_t *roll, i64 x0, i64 y0, i64 width,
- i64 height, str_t title) {
- i64 frame_height = sapp_height();
+static void saw_ui_roll(saw_roll_t *roll, f64 x0, f64 y0, f64 width,
+ f64 height, str_t title) {
+ f64 frame_height = sapp_height();
+ f64 text_height = 35.;
+ f64 header_height = 35.;
+ f64 pianokey_height = 35.;
+ f64 pianokey_width = 100.;
+ f64 border = 2.;
- i64 text_height = 35;
- i64 header_height = 35;
- i64 pianokey_height = 35;
- i64 pianokey_width = 100;
- i64 border = 2;
+ f64 sheet_offset = 40.;
+ f64 sheet_scale = (40. * SAMPLE_RATE) / (10000. * roll->rate);
- i64 sheet_offset = 40;
- i64 sheet_scale = (40 * SAMPLE_RATE) / (10000 * roll->rate);
+ assert(sheet_scale > EPS);
// Title text
//
@@ -2648,7 +2671,7 @@ static void saw_ui_roll(saw_roll_t *roll, i64 x0, i64 y0, i64 width,
nvgFontFaceId(saw_nvg, saw_font_text);
nvgTextAlign(saw_nvg, NVG_ALIGN_LEFT | NVG_ALIGN_BASELINE);
nvgFillColor(saw_nvg, nvgRGBA(255, 255, 255, 255));
- nvgText(saw_nvg, x0 + border * 2,
+ nvgText(saw_nvg, x0 + border * 2.,
frame_height - y0 - height + text_height - border * 2,
title.values, title.values + title.size);
nvgFill(saw_nvg);
@@ -2656,19 +2679,20 @@ static void saw_ui_roll(saw_roll_t *roll, i64 x0, i64 y0, i64 width,
// Tuning control
//
{
- i64 x = x0 + border;
- i64 y = y0 + height - text_height - header_height;
- i64 w = pianokey_width;
- i64 h = header_height;
+ f64 x = x0 + border;
+ f64 y = y0 + height - text_height - header_height;
+ f64 w = pianokey_width;
+ f64 h = header_height;
- if (saw_ui_button(x, y, w / 2, h, TINT_PINK, SZ("\uf52d"), SZ(""),
+ if (saw_ui_button(x, y, w * .5, h, TINT_PINK, SZ("\uf52d"),
+ SZ(""),
roll->tuning_tag == TUNING_PYTHAGOREAN)) {
saw_tuning_pythagorean(roll->tuning, roll->mark_pitch);
roll->tuning_tag = TUNING_PYTHAGOREAN;
}
- if (saw_ui_button(x + w / 2, y, w / 2, h, TINT_PINK, SZ("\uf5ac"),
- SZ(""),
+ if (saw_ui_button(x + w * .5, y, w * .5, h, TINT_PINK,
+ SZ("\uf5ac"), SZ(""),
roll->tuning_tag == TUNING_EQUAL_TEMPERAMENT)) {
saw_tuning_equal_temperament(roll->tuning);
roll->tuning_tag = TUNING_EQUAL_TEMPERAMENT;
@@ -2678,15 +2702,15 @@ static void saw_ui_roll(saw_roll_t *roll, i64 x0, i64 y0, i64 width,
// Loop control
//
{
- i64 x = x0 + pianokey_width + sheet_offset;
- i64 y = frame_height - y0 - height + text_height;
- i64 w = width - pianokey_width - sheet_offset;
- i64 h = header_height / 5;
- i64 border = 5;
+ f64 x = x0 + pianokey_width + sheet_offset;
+ f64 y = frame_height - y0 - height + text_height;
+ f64 w = width - pianokey_width - sheet_offset;
+ f64 h = header_height * .2;
+ f64 border = 5.;
c8 repeat[] = "\uf363";
- nvgFontSize(saw_nvg, header_height - border * 2);
+ nvgFontSize(saw_nvg, header_height - border * 2.);
nvgFontFaceId(saw_nvg, saw_font_icons);
if (roll->loop_duration == 0)
nvgFillColor(saw_nvg, nvgRGBA(80, 80, 80, 160));
@@ -2697,8 +2721,7 @@ static void saw_ui_roll(saw_roll_t *roll, i64 x0, i64 y0, i64 width,
y + header_height / 2, repeat,
repeat + (sizeof repeat - 1));
- i64 rw = (roll->loop_duration * roll->rate * sheet_scale +
- SAMPLE_RATE / 2) /
+ i64 rw = (roll->loop_duration * roll->rate * sheet_scale) /
SAMPLE_RATE;
i64 rx = roll->ui_offset_x;
@@ -2713,7 +2736,7 @@ static void saw_ui_roll(saw_roll_t *roll, i64 x0, i64 y0, i64 width,
if (rw > 0) {
nvgBeginPath(saw_nvg);
nvgRect(saw_nvg, x + rx, y, rw, h);
- nvgRect(saw_nvg, x + rx, y + h * 4, rw, h);
+ nvgRect(saw_nvg, x + rx, y + h * 4., rw, h);
nvgFillColor(saw_nvg, nvgRGBA(180, 80, 40, 160));
nvgFill(saw_nvg);
}
@@ -2721,10 +2744,10 @@ static void saw_ui_roll(saw_roll_t *roll, i64 x0, i64 y0, i64 width,
nvgBeginPath(saw_nvg);
if (rx > 0) {
nvgRect(saw_nvg, x, y, rx, h);
- nvgRect(saw_nvg, x, y + h * 4, rx, h);
+ nvgRect(saw_nvg, x, y + h * 4., rx, h);
}
nvgRect(saw_nvg, x + rx + rw, y, w - rx - rw, h);
- nvgRect(saw_nvg, x + rx + rw, y + h * 4, w - rx - rw, h);
+ nvgRect(saw_nvg, x + rx + rw, y + h * 4., w - rx - rw, h);
nvgFillColor(saw_nvg, nvgRGBA(80, 80, 80, 160));
nvgFill(saw_nvg);
@@ -2734,15 +2757,15 @@ static void saw_ui_roll(saw_roll_t *roll, i64 x0, i64 y0, i64 width,
roll->loop_input = 1;
if (roll->loop_input && saw_lbutton_down) {
- i64 t = (saw_mouse_x - x0 - pianokey_width - sheet_offset -
- roll->ui_offset_x + sheet_scale / 2) /
+ f64 t = (saw_mouse_x - x0 - pianokey_width - sheet_offset -
+ roll->ui_offset_x) /
sheet_scale;
if (t <= 0)
roll->loop_duration = 0;
else
- roll->loop_duration = (t * SAMPLE_RATE + roll->rate / 2) /
- roll->rate;
+ roll->loop_duration = (i64) floor(
+ (t * SAMPLE_RATE) / roll->rate + .5);
}
}
@@ -2752,14 +2775,14 @@ static void saw_ui_roll(saw_roll_t *roll, i64 x0, i64 y0, i64 width,
// Piano roll
//
{
- i64 w = pianokey_width - border * 2;
- i64 h = pianokey_height - border * 2;
+ f64 w = pianokey_width - border * 2.;
+ f64 h = pianokey_height - border * 2.;
b8 hover_any = 0;
for (i64 pitch = 0; pitch < PITCH_COUNT; pitch++) {
- i64 x = x0 + border;
- i64 y = frame_height - y0 - (pitch + 1) * pianokey_height +
+ f64 x = x0 + border;
+ f64 y = frame_height - y0 - (pitch + 1) * pianokey_height +
border + roll->ui_offset_y;
if (y > frame_height - y0 - pianokey_height)
continue;
@@ -2779,7 +2802,7 @@ static void saw_ui_roll(saw_roll_t *roll, i64 x0, i64 y0, i64 width,
: nvgRGBA(220, 220, 220, 255));
nvgFill(saw_nvg);
- nvgFontSize(saw_nvg, h / 2);
+ nvgFontSize(saw_nvg, h * .5);
if (pitch == roll->mark_pitch) {
nvgFontFaceId(saw_nvg, saw_font_icons);
@@ -2806,10 +2829,10 @@ static void saw_ui_roll(saw_roll_t *roll, i64 x0, i64 y0, i64 width,
memset(buf, 0, sizeof buf);
sprintf(buf, "%.1f", (f32) roll->tuning[pitch]);
- nvgFontSize(saw_nvg, (h * 2) / 3);
+ nvgFontSize(saw_nvg, h * 2. / 3.);
nvgFillColor(saw_nvg, nvgRGBAf(.1f, .1f, .1f, 1.f));
nvgTextAlign(saw_nvg, NVG_ALIGN_RIGHT | NVG_ALIGN_MIDDLE);
- nvgText(saw_nvg, x + w, y + h / 2, buf, NULL);
+ nvgText(saw_nvg, x + w, y + h * .5, buf, NULL);
// Piano roll input
//
@@ -2865,7 +2888,7 @@ static void saw_ui_roll(saw_roll_t *roll, i64 x0, i64 y0, i64 width,
//
for (i64 pitch = 0; pitch < PITCH_COUNT; pitch++) {
- i64 y = frame_height - y0 - (pitch + 1) * pianokey_height +
+ f64 y = frame_height - y0 - (pitch + 1) * pianokey_height +
roll->ui_offset_y;
if (y > frame_height - y0 - pianokey_height)
@@ -2873,14 +2896,14 @@ static void saw_ui_roll(saw_roll_t *roll, i64 x0, i64 y0, i64 width,
if (y < frame_height - y0 - height + text_height + header_height)
break;
- i64 h = pianokey_height;
+ f64 h = pianokey_height;
for (i64 t = 0; t < (roll->duration * roll->rate) / SAMPLE_RATE;
t++) {
- i64 x = x0 + pianokey_width + sheet_offset + t * sheet_scale +
+ f64 x = x0 + pianokey_width + sheet_offset + t * sheet_scale +
roll->ui_offset_x;
- if (x >= x0 + width - sheet_scale - border)
+ if (x >= x0 + width - sheet_scale)
break;
i64 note = -1;
@@ -2907,11 +2930,11 @@ static void saw_ui_roll(saw_roll_t *roll, i64 x0, i64 y0, i64 width,
if (x < x0 + pianokey_width + sheet_offset)
continue;
- i64 w = sheet_scale;
+ f64 w = sheet_scale;
nvgBeginPath(saw_nvg);
- nvgRect(saw_nvg, x + border, y + border, w - border * 2,
- h - border * 2);
+ nvgRect(saw_nvg, x + border, y + border, w - border * 2.,
+ h - border * 2.);
b8 turned_off = roll->pitch_turned_off[pitch] ||
(roll->loop_duration > 0 &&
@@ -2959,7 +2982,7 @@ static void saw_ui_roll(saw_roll_t *roll, i64 x0, i64 y0, i64 width,
if (!note->enabled)
continue;
- i64 y = frame_height - y0 - (note->pitch + 1) * pianokey_height +
+ f64 y = frame_height - y0 - (note->pitch + 1) * pianokey_height +
roll->ui_offset_y;
if (y + pianokey_height > frame_height - y0)
@@ -2967,14 +2990,10 @@ static void saw_ui_roll(saw_roll_t *roll, i64 x0, i64 y0, i64 width,
if (y < frame_height - y0 - height + text_height + header_height)
continue;
- i64 x = x0 + pianokey_width + sheet_offset + roll->ui_offset_x +
- (note->time * roll->rate * sheet_scale +
- SAMPLE_RATE / 2) /
- SAMPLE_RATE;
- i64 w = (note->duration * roll->rate * sheet_scale +
- SAMPLE_RATE / 2) /
- SAMPLE_RATE;
- i64 h = pianokey_height;
+ f64 x = x0 + pianokey_width + sheet_offset + roll->ui_offset_x +
+ (note->time * roll->rate * sheet_scale) / SAMPLE_RATE;
+ f64 w = (note->duration * roll->rate * sheet_scale) / SAMPLE_RATE;
+ f64 h = pianokey_height;
b8 has_cursor = (roll->grid_input && roll->grid_note == n) ||
(saw_mouse_x >= x && saw_mouse_x < x + w &&
@@ -2999,11 +3018,10 @@ static void saw_ui_roll(saw_roll_t *roll, i64 x0, i64 y0, i64 width,
frame >= roll->time + note->time &&
frame < roll->time + note->time + note->duration;
- i64 underflow = (x0 + pianokey_width + sheet_offset +
- sheet_scale - 1 - x) /
- sheet_scale;
- i64 overflow = (x + w + sheet_scale + 1 - x0 - width) /
- sheet_scale;
+ f64 underflow = ceil((x0 + pianokey_width + sheet_offset - x) /
+ sheet_scale);
+ f64 overflow = floor((x + w + sheet_scale - x0 - width) /
+ sheet_scale);
if (underflow > 0) {
x += underflow * sheet_scale;
@@ -3014,8 +3032,8 @@ static void saw_ui_roll(saw_roll_t *roll, i64 x0, i64 y0, i64 width,
w -= overflow * sheet_scale;
nvgBeginPath(saw_nvg);
- nvgRect(saw_nvg, x + border, y + border, w - border * 2,
- h - border * 2);
+ nvgRect(saw_nvg, x + border, y + border, w - border * 2.,
+ h - border * 2.);
nvgFillColor(saw_nvg, is_playing ? nvgRGBA(255, 230, 200, 255)
: has_cursor ? nvgRGBA(190, 190, 230, 255)
@@ -3036,9 +3054,10 @@ static void saw_ui_roll(saw_roll_t *roll, i64 x0, i64 y0, i64 width,
if (roll->grid_input) {
if (saw_edit_mode == EDIT_MODE_HAND && saw_lbutton_down) {
- i64 t = (saw_mouse_x - x0 - pianokey_width - sheet_offset -
- roll->ui_offset_x) /
- sheet_scale;
+ i64 t = (i64) floor((saw_mouse_x - x0 - pianokey_width -
+ sheet_offset - roll->ui_offset_x) /
+ sheet_scale +
+ .5);
saw_roll_note_t *p = roll->notes + roll->grid_note;
@@ -3092,14 +3111,13 @@ static void saw_ui_roll(saw_roll_t *roll, i64 x0, i64 y0, i64 width,
frame -= ((frame - roll->time) / roll->loop_duration) *
roll->loop_duration;
- i64 x = x0 + pianokey_width + sheet_offset + roll->ui_offset_x -
- border * 2 +
- ((frame - roll->time) * roll->rate * sheet_scale +
- SAMPLE_RATE / 2) /
+ f64 x = x0 + pianokey_width + sheet_offset + roll->ui_offset_x -
+ border * 2. +
+ ((frame - roll->time) * roll->rate * sheet_scale) /
SAMPLE_RATE;
- i64 w = border * 4;
+ f64 w = border * 4;
- if (x >= x0 + pianokey_width + sheet_offset - border * 2 &&
+ if (x >= x0 + pianokey_width + sheet_offset - border * 2. &&
x < x0 + width) {
nvgBeginPath(saw_nvg);
nvgRect(saw_nvg, x, frame_height - y0 - height + text_height, w,
@@ -3116,14 +3134,13 @@ static void saw_ui_roll(saw_roll_t *roll, i64 x0, i64 y0, i64 width,
saw_mouse_x < x0 + width &&
saw_mouse_y >= frame_height - y0 - height &&
saw_mouse_y < frame_height - y0) {
- i64 dx = x0 + pianokey_width + sheet_offset + roll->ui_offset_x;
- i64 x = dx +
- ((saw_mouse_x - dx + sheet_scale / 2) / sheet_scale) *
- sheet_scale;
- i64 w = border * 4;
+ f64 dx = x0 + pianokey_width + sheet_offset + roll->ui_offset_x;
+ f64 x = dx + floor((saw_mouse_x - dx) / sheet_scale + .5) *
+ sheet_scale;
+ f64 w = border * 4.;
nvgBeginPath(saw_nvg);
- nvgRect(saw_nvg, x - w / 2,
+ nvgRect(saw_nvg, x - w * .5,
frame_height - y0 - height + text_height, w,
height - text_height);
nvgFillColor(saw_nvg, nvgRGBA(80, 80, 240, 160));