added cool markovy visualiser
parent
0bb207bbca
commit
5909dad9f8
3
ampler.c
3
ampler.c
|
@ -30,7 +30,8 @@ Ampler_state *init() {
|
||||||
puts(SDL_GetError());
|
puts(SDL_GetError());
|
||||||
|
|
||||||
// TODO: iterate a directory to load samples
|
// TODO: iterate a directory to load samples
|
||||||
load_track(state);
|
load_sample(state, "loop2.wav");
|
||||||
|
load_sample(state, "chord.wav");
|
||||||
|
|
||||||
puts("init.");
|
puts("init.");
|
||||||
return state;
|
return state;
|
||||||
|
|
4
ampler.h
4
ampler.h
|
@ -24,6 +24,7 @@ typedef double f64;
|
||||||
#define do )
|
#define do )
|
||||||
|
|
||||||
#define or ||
|
#define or ||
|
||||||
|
#define and &&
|
||||||
|
|
||||||
|
|
||||||
#define arraylen(a) (sizeof (a) / sizeof ((a)[0]))
|
#define arraylen(a) (sizeof (a) / sizeof ((a)[0]))
|
||||||
|
@ -45,6 +46,8 @@ struct Sound_src {
|
||||||
f32 speed; // in samples, per sample, can be negative
|
f32 speed; // in samples, per sample, can be negative
|
||||||
s32 start; // play start in samples
|
s32 start; // play start in samples
|
||||||
s32 end; // play end in samples
|
s32 end; // play end in samples
|
||||||
|
s8 name[32]; // includes null terminator
|
||||||
|
f32 note_speed; // multiplies with base speed, CANNOT be negative
|
||||||
enum { SND_FREE = 0, SND_STOPPED, SND_PLAYING, SND_LOOPING, } state;
|
enum { SND_FREE = 0, SND_STOPPED, SND_PLAYING, SND_LOOPING, } state;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -61,6 +64,7 @@ struct Ampler_state {
|
||||||
Sound_src sounds[64];
|
Sound_src sounds[64];
|
||||||
s32 played_audio_last_frame;
|
s32 played_audio_last_frame;
|
||||||
Udp_msg messages[64];
|
Udp_msg messages[64];
|
||||||
|
s8 frame_mix[CHANNELS][FRAME_SAMPLES];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
33
audio.c
33
audio.c
|
@ -24,12 +24,14 @@ void trigger_sounds(Ampler_state *state) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void sound_src_frame(Sound_src *s, s8 *mix[]) {
|
void sound_src_frame(Sound_src *s, s8 *mix[]) {
|
||||||
if s -> state == SND_LOOPING or s -> state == SND_PLAYING do
|
if s->state != SND_LOOPING and s->state != SND_PLAYING do
|
||||||
|
return;
|
||||||
|
|
||||||
for int i = 0; i < FRAME_SAMPLES; i += 1 do {
|
for int i = 0; i < FRAME_SAMPLES; i += 1 do {
|
||||||
for int c = 0; c < CHANNELS; c += 1 do
|
for int c = 0; c < CHANNELS; c += 1 do
|
||||||
mix[c][i] += s -> tracks[c][(int) s -> pos];
|
mix[c][i] += s -> tracks[c][(int) s -> pos];
|
||||||
|
|
||||||
s -> pos += s -> speed;
|
s -> pos += s->speed * s->note_speed;
|
||||||
|
|
||||||
if s -> state == SND_LOOPING do {
|
if s -> state == SND_LOOPING do {
|
||||||
while s -> pos < s -> start do
|
while s -> pos < s -> start do
|
||||||
|
@ -58,13 +60,14 @@ int audio_frame(Ampler_state *state) {
|
||||||
trigger_sounds(state);
|
trigger_sounds(state);
|
||||||
|
|
||||||
// TODO: We should use CHANNELS here
|
// TODO: We should use CHANNELS here
|
||||||
static s8 mix_l[FRAME_SAMPLES] = { 0 }, mix_r[FRAME_SAMPLES] = { 0 };
|
// static s8 mix_l[FRAME_SAMPLES] = { 0 }, mix_r[FRAME_SAMPLES] = { 0 };
|
||||||
SDL_memset(mix_l, 0, sizeof mix_l);
|
s8 *mix_l = state->frame_mix[0], *mix_r = state->frame_mix[1];
|
||||||
SDL_memset(mix_r, 0, sizeof mix_r);
|
SDL_memset(mix_l, 0, FRAME_SAMPLES / sizeof s8);
|
||||||
|
SDL_memset(mix_r, 0, FRAME_SAMPLES / sizeof s8);
|
||||||
|
|
||||||
s8 *mix[] = { mix_l, mix_r };
|
s8 *mix[] = { mix_l, mix_r };
|
||||||
foreach_ptr(Sound_src, snd, state -> sounds) //for int s = 0; s < arraylen(state -> sounds); s += 1 do
|
foreach_ptr(Sound_src, snd, state -> sounds)
|
||||||
sound_src_frame(snd, mix); //sound_src_frame(&(state -> sounds[s]), mix);
|
sound_src_frame(snd, mix);
|
||||||
|
|
||||||
const int vol = 100;
|
const int vol = 100;
|
||||||
static s16 frame[FRAME_SAMPLES * CHANNELS] = { 0 };
|
static s16 frame[FRAME_SAMPLES * CHANNELS] = { 0 };
|
||||||
|
@ -78,7 +81,7 @@ int audio_frame(Ampler_state *state) {
|
||||||
return 1; // audio was qued
|
return 1; // audio was qued
|
||||||
}
|
}
|
||||||
|
|
||||||
void load_track(Ampler_state *state) {
|
void load_sample(Ampler_state *state, const char *file_name) {
|
||||||
Sound_src *snd = NULL;
|
Sound_src *snd = NULL;
|
||||||
foreach_ptr(Sound_src, s, state -> sounds)
|
foreach_ptr(Sound_src, s, state -> sounds)
|
||||||
if s -> state == SND_FREE do {
|
if s -> state == SND_FREE do {
|
||||||
|
@ -94,7 +97,7 @@ void load_track(Ampler_state *state) {
|
||||||
s16 *buffer = NULL;
|
s16 *buffer = NULL;
|
||||||
u32 bytes = 0;
|
u32 bytes = 0;
|
||||||
|
|
||||||
SDL_LoadWAV("sample.wav", &spec, &buffer, &bytes);
|
SDL_LoadWAV(file_name, &spec, &buffer, &bytes);
|
||||||
|
|
||||||
if spec.format != AUDIO_S16 do {
|
if spec.format != AUDIO_S16 do {
|
||||||
puts("error: sample.wav is not s16");
|
puts("error: sample.wav is not s16");
|
||||||
|
@ -110,14 +113,20 @@ void load_track(Ampler_state *state) {
|
||||||
snd -> start = 0;
|
snd -> start = 0;
|
||||||
snd -> end = snd->track_len;
|
snd -> end = snd->track_len;
|
||||||
snd -> state = SND_STOPPED;
|
snd -> state = SND_STOPPED;
|
||||||
|
snd -> note_speed = 1.0f; // TODO: Look up a note ?
|
||||||
|
SDL_memset(snd->name, 0, sizeof snd->name);
|
||||||
|
for int i = 0; i < arraylen(snd->name) - 1; i += 1 do
|
||||||
|
if file_name[i] == '\0' or file_name[i] == '.' do break;
|
||||||
|
else snd->name[i] = file_name[i];
|
||||||
|
|
||||||
snd -> state = SND_LOOPING;
|
if snd == &(state->sounds[0]) do
|
||||||
snd -> end /= 2;
|
snd -> state = SND_LOOPING;
|
||||||
snd -> start = snd -> end / 2;
|
|
||||||
|
|
||||||
for int i = 0; i < CHANNELS; i += 1 do
|
for int i = 0; i < CHANNELS; i += 1 do
|
||||||
snd -> tracks[i] = malloc(snd -> track_len);
|
snd -> tracks[i] = malloc(snd -> track_len);
|
||||||
|
|
||||||
|
// TODO: Change to a malloc wrapper that does gur error
|
||||||
|
// checking for us and also adds ptrs to gur half gc
|
||||||
for int i = 0; i < CHANNELS; i += 1 do
|
for int i = 0; i < CHANNELS; i += 1 do
|
||||||
if !(snd -> tracks[i]) do
|
if !(snd -> tracks[i]) do
|
||||||
puts("fffuuuck");
|
puts("fffuuuck");
|
||||||
|
|
67
draw.c
67
draw.c
|
@ -2,31 +2,68 @@
|
||||||
|
|
||||||
void draw_frame(SDL_Window *w, SDL_Renderer *r, Ampler_state *state) {
|
void draw_frame(SDL_Window *w, SDL_Renderer *r, Ampler_state *state) {
|
||||||
SDL_SetRenderDrawColor(r, 0x1D, 0x2B, 0x53, 255);
|
SDL_SetRenderDrawColor(r, 0x1D, 0x2B, 0x53, 255);
|
||||||
//SDL_SetRenderDrawColor(r, 10, 10, 10, 100);
|
|
||||||
SDL_RenderClear(r);
|
SDL_SetRenderDrawBlendMode(r, SDL_BLENDMODE_BLEND);
|
||||||
|
SDL_SetRenderDrawColor(r, 10, 10, 10, 20);
|
||||||
|
SDL_Rect screen = { 0, 0, 512, 512 };
|
||||||
|
SDL_RenderFillRect(r, &screen);
|
||||||
|
// SDL_RenderClear(r);
|
||||||
|
|
||||||
// TODO: DRAW WITH X SCALE FACTOR
|
// TODO: DRAW WITH X SCALE FACTOR
|
||||||
// TODO: DRAW SMOLER
|
// TODO: DRAW SMOLER
|
||||||
SDL_SetRenderDrawColor(r, 0xFF, 0x00, 0x4D, 255);
|
SDL_SetRenderDrawColor(r, 0xFF, 0x00, 0x4D, 255);
|
||||||
const space = (44100 * 8) / 512;
|
const space = (44100 * 8) / 512;
|
||||||
// TODO: DRAW L / R OVERLAPPED IN DIFF COLORS ?
|
const int t = 0; // TODO: DRAW L / R OVERLAPPED IN DIFF COLORS ?
|
||||||
const int t = 0;
|
const int wav_h = 128;
|
||||||
|
if 0 do
|
||||||
foreach_ptr(Sound_src, snd, state -> sounds)
|
foreach_ptr(Sound_src, snd, state -> sounds)
|
||||||
if snd -> state != SND_FREE do
|
if snd -> state != SND_FREE do {
|
||||||
for int x = 0; x < 512; x += 1 do {
|
const int y = wav_h / 2 + (wav_h + 4) * snd_i;
|
||||||
const int y = 128 + 256 * snd_i;
|
const int top = y - 64, bot = y + 64;
|
||||||
|
for int x = 0; x < 512 and x * space < snd->track_len; x += 1 do {
|
||||||
const int val = snd -> tracks[t][x * space];
|
const int val = snd -> tracks[t][x * space];
|
||||||
SDL_RenderDrawLine(r, x, y + val / 8, x, y + val);
|
const int sign = val < 0 ? -1 : 1;
|
||||||
//SDL_RenderDrawPoint(r, x, y + val);
|
SDL_RenderDrawLine(r, x, y + sign, x, y + val / 2);
|
||||||
|
//SDL_RenderDrawPoint(r, x, y + val / 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
if state -> played_audio_last_frame do
|
|
||||||
foreach_ptr(Sound_src, snd, state -> sounds)
|
|
||||||
if snd->state == SND_PLAYING or snd->state == SND_LOOPING do {
|
|
||||||
const int x = snd -> pos / space;
|
const int x = snd -> pos / space;
|
||||||
SDL_RenderDrawLine(r, x, 0, x, 512);
|
if state -> played_audio_last_frame do
|
||||||
SDL_RenderDrawLine(r, snd->start / space, 0, snd->start / space, 512);
|
SDL_RenderDrawLine(r, x, top, x, bot);
|
||||||
SDL_RenderDrawLine(r, snd->end / space, 0, snd->end / space, 512);
|
SDL_RenderDrawLine(r, snd->start / space, top, snd->start / space, bot);
|
||||||
|
SDL_RenderDrawLine(r, snd->end / space, top, snd->end / space, bot);
|
||||||
|
}
|
||||||
|
|
||||||
|
static u8 markov[256][256];
|
||||||
|
SDL_memset(markov, 0, sizeof markov);
|
||||||
|
for int x = 0; x < FRAME_SAMPLES - 1; x += 1 do {
|
||||||
|
u8 cur = state->frame_mix[0][x] + 128;
|
||||||
|
u8 next = state->frame_mix[0][x + 1] + 128;
|
||||||
|
markov[cur][255 - next] += 1;
|
||||||
|
}
|
||||||
|
for int x = 0; x < 256; x += 1 do {
|
||||||
|
u8 to = 0;
|
||||||
|
for int y = 0; y < 255; y += 1 do to += markov[x][y];
|
||||||
|
markov[x][255] = to;
|
||||||
|
}
|
||||||
|
for int x = 0; x < 256; x += 1 do {
|
||||||
|
u8 to = markov[x][255];
|
||||||
|
if to == 0 do continue;
|
||||||
|
for int y = 0; y < 255; y += 1 do
|
||||||
|
; //markov[x][y] *= to;
|
||||||
|
}
|
||||||
|
|
||||||
|
for int x = 0; x < 256; x += 1 do
|
||||||
|
for int y = 0; y < 256; y += 1 do {
|
||||||
|
u8 m = markov[x][y];
|
||||||
|
const int s = 20;
|
||||||
|
SDL_SetRenderDrawColor(r, m * s, m * s, m * s, 255);
|
||||||
|
if m != 0 do {
|
||||||
|
SDL_RenderDrawPoint(r, x * 2, y * 2);
|
||||||
|
SDL_RenderDrawPoint(r, x * 2 + 1, y * 2);
|
||||||
|
SDL_RenderDrawPoint(r, x * 2, y * 2 + 1);
|
||||||
|
SDL_RenderDrawPoint(r, x * 2 + 1, y * 2 + 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_RenderPresent(r);
|
SDL_RenderPresent(r);
|
||||||
|
|
Loading…
Reference in New Issue