131 lines
3.8 KiB
C
131 lines
3.8 KiB
C
|
|
||
|
#include <stdio.h>
|
||
|
|
||
|
#define SOKOL_IMPL
|
||
|
#define SOKOL_GLCORE
|
||
|
#include "sokol_app.h"
|
||
|
#include "sokol_audio.h"
|
||
|
#include "sokol_log.h"
|
||
|
|
||
|
#include "../config.h"
|
||
|
#include "../oscillators.c"
|
||
|
#include "../phaser.c"
|
||
|
|
||
|
static struct stfu_sinewave sine0;
|
||
|
static struct stfu_phaser phaser0;
|
||
|
static struct stfu_phaser phaser1;
|
||
|
|
||
|
static float key_frequency = STFU_C4_FREQUENCY;
|
||
|
|
||
|
static void stream(float *buffer, int num_frames, int num_channels) {
|
||
|
for (int i = 0; i < num_frames; ++i) {
|
||
|
// sine0 = stfu_pump_sinewave(sine0); // Carrier
|
||
|
phaser0 = stfu_pump_phaser(phaser0);
|
||
|
phaser1 = stfu_pump_phaser(phaser1);
|
||
|
buffer[2 * i + 0] = sinf(phaser0.v + sinf(phaser1.v));
|
||
|
buffer[2 * i + 1] = sinf(phaser0.v + sinf(phaser1.v));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void init(void) {
|
||
|
saudio_setup(&(saudio_desc){
|
||
|
.sample_rate = STFU_AUDIO_FRAME_RATE,
|
||
|
.num_channels = STFU_AUDIO_CHANNEL_COUNT,
|
||
|
// .stream_cb = stream,
|
||
|
});
|
||
|
|
||
|
// sine0 = stfu_init_sinewave(STFU_A4_FREQUENCY / 2.0f, 0.0f, 0.8f);
|
||
|
phaser0 = stfu_init_phaser(key_frequency);
|
||
|
phaser1 = stfu_init_phaser(key_frequency * 0.25);
|
||
|
}
|
||
|
|
||
|
static void cleanup(void) { saudio_shutdown(); }
|
||
|
|
||
|
static void event(const sapp_event *e) {
|
||
|
switch (e->type) {
|
||
|
case SAPP_EVENTTYPE_KEY_DOWN: {
|
||
|
if (e->key_repeat)
|
||
|
break;
|
||
|
|
||
|
switch (e->key_code) {
|
||
|
case SAPP_KEYCODE_Z:
|
||
|
key_frequency = STFU_C4_FREQUENCY;
|
||
|
break;
|
||
|
case SAPP_KEYCODE_X:
|
||
|
key_frequency = STFU_C4_FREQUENCY * STFU_NOTE_UPSCALE_FACTOR;
|
||
|
break;
|
||
|
case SAPP_KEYCODE_C:
|
||
|
key_frequency = STFU_C4_FREQUENCY * STFU_NOTE_UPSCALE_FACTOR *
|
||
|
STFU_NOTE_UPSCALE_FACTOR;
|
||
|
break;
|
||
|
case SAPP_KEYCODE_V:
|
||
|
key_frequency = STFU_C4_FREQUENCY * STFU_NOTE_UPSCALE_FACTOR *
|
||
|
STFU_NOTE_UPSCALE_FACTOR * STFU_NOTE_UPSCALE_FACTOR;
|
||
|
break;
|
||
|
case SAPP_KEYCODE_B:
|
||
|
key_frequency = STFU_C4_FREQUENCY * STFU_NOTE_UPSCALE_FACTOR *
|
||
|
STFU_NOTE_UPSCALE_FACTOR * STFU_NOTE_UPSCALE_FACTOR *
|
||
|
STFU_NOTE_UPSCALE_FACTOR;
|
||
|
break;
|
||
|
case SAPP_KEYCODE_N:
|
||
|
key_frequency = STFU_A4_FREQUENCY * STFU_NOTE_DOWNSCALE_FACTOR *
|
||
|
STFU_NOTE_DOWNSCALE_FACTOR * STFU_NOTE_DOWNSCALE_FACTOR *
|
||
|
STFU_NOTE_DOWNSCALE_FACTOR;
|
||
|
break;
|
||
|
case SAPP_KEYCODE_M:
|
||
|
key_frequency = STFU_A4_FREQUENCY * STFU_NOTE_DOWNSCALE_FACTOR *
|
||
|
STFU_NOTE_DOWNSCALE_FACTOR * STFU_NOTE_DOWNSCALE_FACTOR;
|
||
|
break;
|
||
|
case SAPP_KEYCODE_COMMA:
|
||
|
key_frequency = STFU_A4_FREQUENCY * STFU_NOTE_DOWNSCALE_FACTOR *
|
||
|
STFU_NOTE_DOWNSCALE_FACTOR;
|
||
|
break;
|
||
|
case SAPP_KEYCODE_PERIOD:
|
||
|
key_frequency = STFU_A4_FREQUENCY * STFU_NOTE_DOWNSCALE_FACTOR;
|
||
|
break;
|
||
|
case SAPP_KEYCODE_SLASH:
|
||
|
key_frequency = STFU_A4_FREQUENCY;
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
phaser0 = stfu_set_phaser_frequency(phaser0, key_frequency);
|
||
|
phaser1 = stfu_set_phaser_frequency(phaser1, key_frequency * 0.25);
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void frame(void) {
|
||
|
int frames = (int)(sapp_frame_duration() * (float)STFU_AUDIO_FRAME_RATE);
|
||
|
int expected = saudio_expect();
|
||
|
frames = frames > expected ? expected : frames;
|
||
|
// todo: Prevent drifting apart.
|
||
|
static float buffer[STFU_AUDIO_FRAME_RATE * STFU_AUDIO_CHANNEL_COUNT];
|
||
|
while (frames > 0) {
|
||
|
int now = frames > STFU_AUDIO_FRAME_RATE ? STFU_AUDIO_FRAME_RATE : frames;
|
||
|
stream(buffer, now, STFU_AUDIO_CHANNEL_COUNT);
|
||
|
saudio_push(buffer, now);
|
||
|
frames -= now;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
sapp_desc sokol_main(int argc, char *argv[]) {
|
||
|
return (sapp_desc){
|
||
|
.width = 640,
|
||
|
.height = 480,
|
||
|
.init_cb = init,
|
||
|
.frame_cb = frame,
|
||
|
.cleanup_cb = cleanup,
|
||
|
.event_cb = event,
|
||
|
.logger.func = slog_func,
|
||
|
.gl_major_version = 2,
|
||
|
.gl_minor_version = 0,
|
||
|
// .swap_interval = 0,
|
||
|
};
|
||
|
}
|