summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
Diffstat (limited to 'source')
-rw-r--r--source/saw/main.c226
1 files changed, 151 insertions, 75 deletions
diff --git a/source/saw/main.c b/source/saw/main.c
index e20b702..47c6a31 100644
--- a/source/saw/main.c
+++ b/source/saw/main.c
@@ -122,12 +122,23 @@ enum {
TINT_WHITE = 0,
TINT_ORANGE,
TINT_PINK,
+
+ UI_MAIN = 0,
+ UI_DEV,
+
+ UI_TAB_COUNT,
};
// Data types
//
typedef struct {
+ i64 value;
+ i64 num; // numerator
+ i64 den; // denominator
+} saw_rate_t;
+
+typedef struct {
b8 enabled;
i64 time;
f64 duration;
@@ -227,9 +238,31 @@ typedef struct {
} saw_ui_color_t;
typedef struct {
- i8 type;
- str_t data;
-} saw_project_token_t;
+ b8 enabled;
+ b8 selected;
+ i64 row;
+ f64 position;
+ f64 size;
+} saw_ui_grid_item_t;
+
+typedef struct {
+ f64 x0;
+ f64 y0;
+ f64 width;
+ f64 height;
+ f64 offset_x;
+ f64 offset_y;
+ f64 scale_x;
+ f64 scale_y;
+ i64 time_begin;
+ i64 time_end;
+ i64 time_cursor;
+ i64 time_rate;
+ i64 time_num; // numerator
+ i64 time_den; // denominator
+ i64 items_size;
+ saw_ui_grid_item_t *items;
+} saw_ui_grid_t;
// ================================================================
//
@@ -340,6 +373,8 @@ static i64 saw_ui_input_index = 0;
static i64 saw_ui_input_active = -1;
static f64 saw_ui_input_buffer = 0.;
+static i32 saw_ui_tab = UI_MAIN;
+
// ================================================================
//
// Sound
@@ -348,6 +383,11 @@ static f64 saw_ui_input_buffer = 0.;
// When music and signal processing procedures become stable enough
// we will separate them into a library and add tests.
//
+// TODO
+// - Apply volume during sound generation.
+// - Implement proper frequency shift.
+// - Unify similar logic for Oscillators and Samplers.
+//
// ================================================================
#ifdef __GNUC__
@@ -411,7 +451,7 @@ static void saw_tuning_pythagorean(f64 *tuning, i64 base_pitch) {
}
static f64 saw_random(f64 min, f64 max) {
- if (max - min < .000001)
+ if (max - min < EPS)
return min;
u64 x = mt64_generate(&saw_rng_mt64);
u64 range = (u64) ((max - min) * 10000 + 0.5);
@@ -434,10 +474,6 @@ static f64 saw_envelope(f64 t, f64 attack, f64 decay, f64 sustain,
return a;
}
-static f64 saw_pitch_frequency(i64 pitch) {
- return pow(2., 5.5 + pitch / 12.);
-}
-
static f64 saw_pitch_amplitude(i64 pitch) {
return .2 / exp(0.02 * pitch);
}
@@ -457,9 +493,6 @@ static void saw_play_voice(saw_track_t *track, saw_roll_t *roll,
f64 frequency = roll->tuning[pitch];
switch (track->instrument) {
- // FIXME
- // Apply volume during sound generation.
-
case INSTRUMENT_OSCILLATOR: {
saw_oscillator_t *osc = &track->oscillator;
@@ -529,9 +562,6 @@ static f64 saw_oscillator(i32 type, f64 frequency, f64 phase,
static f64 saw_sampler(saw_sampler_t *sam, i32 channel, f64 frequency,
i64 t) {
- // FIXME
- // Implement proper frequency shift.
-
i64 i = (i64) floor((t * frequency) / sam->base_frequency + .5) *
2 +
channel;
@@ -543,9 +573,6 @@ static f64 saw_sampler(saw_sampler_t *sam, i32 channel, f64 frequency,
}
static void saw_audio_render(void) {
- // FIXME
- // Improve performance.
-
i64 frame_count = (BUFFER_SIZE / CHANNEL_COUNT);
if (mtx_lock(&saw_playback_mutex) != thrd_success) {
@@ -608,9 +635,6 @@ static void saw_audio_render(void) {
saw_track_t *track = saw_tracks + saw_voices[n].track;
switch (track->instrument) {
- // FIXME
- // Unify similar logic for Oscillators and Samplers.
-
case INSTRUMENT_OSCILLATOR: {
saw_oscillator_t *osc = &track->oscillator;
@@ -1863,6 +1887,11 @@ static void saw_ui_value_list(f64 x0, f64 y0, f64 width, f64 height,
++saw_ui_input_index;
}
+static void saw_ui_grid(saw_ui_grid_t *grid) {
+ // TODO
+ //
+}
+
static void saw_ui_reset_offset(void) {
if (saw_current_roll != -1) {
saw_rolls[saw_current_roll].ui_offset_x = 0.;
@@ -3345,18 +3374,23 @@ static void saw_frame(void) {
// Process input
//
{
+ // Playback
+ //
if (saw_key_pressed[SAPP_KEYCODE_SPACE])
saw_playback_on = !saw_playback_on;
if (saw_key_pressed[SAPP_KEYCODE_ENTER])
saw_playback_frame = 0;
- if (saw_key_pressed[SAPP_KEYCODE_ESCAPE])
- saw_ui_reset_offset();
+
+ // Duplicate
+ //
if (saw_key_pressed[SAPP_KEYCODE_D] ||
(saw_edit_mode == EDIT_MODE_CLONE && saw_lbutton_click))
saw_compose.duplicate_input = 1;
// Panning control
//
+ if (saw_key_pressed[SAPP_KEYCODE_ESCAPE])
+ saw_ui_reset_offset();
for (i64 i = 0; i < ROLL_COUNT; i++) {
if (saw_rolls[i].ui_offset_x_input)
saw_rolls[i].ui_offset_x += saw_mouse_dx;
@@ -3367,6 +3401,11 @@ static void saw_frame(void) {
saw_compose.ui_offset_x += saw_mouse_dx;
saw_compose.ui_offset_y += saw_mouse_dy;
}
+
+ // Tabs
+ //
+ if (saw_key_pressed[SAPP_KEYCODE_TAB])
+ saw_ui_tab = (saw_ui_tab + 1) % UI_TAB_COUNT;
}
// Render UI
@@ -3378,66 +3417,103 @@ static void saw_frame(void) {
// correctly.
saw_ui_begin();
- // Adjust UI layout
- //
- i64 track_width = frame_width / 5;
- if (track_width < 330)
- track_width = 330;
- if (track_width > frame_width / 2)
- track_width = frame_width / 2;
-
- i64 header_height = 80;
- i64 roll_height = (frame_height * 3) / 5;
- i64 compose_height = frame_height - roll_height - header_height;
- i64 track_height = frame_height - header_height;
-
- // Render header
- //
+ switch (saw_ui_tab) {
+ case UI_MAIN: {
+ // Adjust UI layout
+ //
+ i64 track_width = frame_width / 5;
+ if (track_width < 330)
+ track_width = 330;
+ if (track_width > frame_width / 2)
+ track_width = frame_width / 2;
+
+ i64 header_height = 80;
+ i64 roll_height = (frame_height * 3) / 5;
+ i64 compose_height = frame_height - roll_height -
+ header_height;
+ i64 track_height = frame_height - header_height;
+
+ // Render header
+ //
- saw_ui_header(0, // x0
- frame_height - header_height, // y0
- frame_width, // width
- header_height // height
- );
+ saw_ui_header(0, // x0
+ frame_height - header_height, // y0
+ frame_width, // width
+ header_height // height
+ );
- // Render compose view
- //
- saw_ui_compose(0, // x0
- roll_height, // y0
- frame_width - track_width, // width
- compose_height // height
- );
-
- if (saw_current_track != -1) {
- // Render track view
- //
+ // Render compose view
+ //
+ saw_ui_compose(0, // x0
+ roll_height, // y0
+ frame_width - track_width, // width
+ compose_height // height
+ );
+
+ if (saw_current_track != -1) {
+ // Render track view
+ //
+
+ c8 buf[64];
+ sprintf(buf, "Track %lld", saw_current_track + 1);
+
+ saw_ui_track(saw_tracks + saw_current_track, // track
+ frame_width - track_width, // x0
+ 0, // y0
+ track_width, // width
+ track_height, // height
+ kit_str(strlen(buf), buf) // label
+ );
+ }
- c8 buf[64];
- sprintf(buf, "Track %lld", saw_current_track + 1);
+ if (saw_current_roll != -1) {
+ // Render roll view
+ //
- saw_ui_track(saw_tracks + saw_current_track, // track
- frame_width - track_width, // x0
- 0, // y0
- track_width, // width
- track_height, // height
- kit_str(strlen(buf), buf) // label
- );
- }
+ c8 buf[64];
+ sprintf(buf, "Sheet %lld", saw_current_roll + 1);
- if (saw_current_roll != -1) {
- // Render roll view
- //
+ saw_ui_roll(saw_rolls + saw_current_roll, // roll
+ 0, // x0
+ 0, // y0
+ frame_width - track_width, // width
+ roll_height, // height
+ kit_str(strlen(buf), buf) // label
+ );
+ }
- c8 buf[64];
- sprintf(buf, "Sheet %lld", saw_current_roll + 1);
+ } break;
+
+ case UI_DEV: {
+ // FIXME
+
+ i64 time_rate = 256;
+ saw_ui_grid_item_t items[100] = { 0 };
+
+ saw_ui_grid_t grid = {
+ .x0 = 20.,
+ .y0 = 20.,
+ .width = frame_width - 40.,
+ .height = frame_height - 40.,
+ .offset_x = 0.,
+ .offset_y = 0.,
+ .scale_x = 1.,
+ .scale_y = 1.,
+ .time_begin = 0,
+ .time_end = time_rate * 10,
+ .time_cursor = (saw_playback_frame * time_rate) /
+ SAMPLE_RATE,
+ .time_rate = time_rate,
+ .time_num = 4,
+ .time_den = 4,
+ .items_size = sizeof items / sizeof *items,
+ .items = items,
+ };
- saw_ui_roll(saw_rolls + saw_current_roll, // roll
- 0, // x0
- 0, // y0
- frame_width - track_width, // width
- roll_height, // height
- kit_str(strlen(buf), buf) // label
- );
+ saw_ui_grid(&grid);
+ } break;
+
+ default:;
}
saw_ui_end();