diff --git a/ampler.c b/ampler.c index 4b157f1..ce43656 100644 --- a/ampler.c +++ b/ampler.c @@ -30,7 +30,8 @@ Ampler_state *init() { puts(SDL_GetError()); // TODO: iterate a directory to load samples - load_track(state); + load_sample(state, "loop2.wav"); + load_sample(state, "chord.wav"); puts("init."); return state; diff --git a/ampler.h b/ampler.h index f69be8b..ad4d78f 100644 --- a/ampler.h +++ b/ampler.h @@ -24,6 +24,7 @@ typedef double f64; #define do ) #define or || +#define and && #define arraylen(a) (sizeof (a) / sizeof ((a)[0])) @@ -45,6 +46,8 @@ struct Sound_src { f32 speed; // in samples, per sample, can be negative s32 start; // play start 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; }; @@ -61,6 +64,7 @@ struct Ampler_state { Sound_src sounds[64]; s32 played_audio_last_frame; Udp_msg messages[64]; + s8 frame_mix[CHANNELS][FRAME_SAMPLES]; }; diff --git a/audio.c b/audio.c index 686ca85..0b124d8 100644 --- a/audio.c +++ b/audio.c @@ -24,12 +24,14 @@ void trigger_sounds(Ampler_state *state) { } 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 c = 0; c < CHANNELS; c += 1 do 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 { while s -> pos < s -> start do @@ -58,13 +60,14 @@ int audio_frame(Ampler_state *state) { trigger_sounds(state); // TODO: We should use CHANNELS here - static s8 mix_l[FRAME_SAMPLES] = { 0 }, mix_r[FRAME_SAMPLES] = { 0 }; - SDL_memset(mix_l, 0, sizeof mix_l); - SDL_memset(mix_r, 0, sizeof mix_r); + // static s8 mix_l[FRAME_SAMPLES] = { 0 }, mix_r[FRAME_SAMPLES] = { 0 }; + s8 *mix_l = state->frame_mix[0], *mix_r = state->frame_mix[1]; + SDL_memset(mix_l, 0, FRAME_SAMPLES / sizeof s8); + SDL_memset(mix_r, 0, FRAME_SAMPLES / sizeof s8); s8 *mix[] = { mix_l, mix_r }; - foreach_ptr(Sound_src, snd, state -> sounds) //for int s = 0; s < arraylen(state -> sounds); s += 1 do - sound_src_frame(snd, mix); //sound_src_frame(&(state -> sounds[s]), mix); + foreach_ptr(Sound_src, snd, state -> sounds) + sound_src_frame(snd, mix); const int vol = 100; static s16 frame[FRAME_SAMPLES * CHANNELS] = { 0 }; @@ -78,7 +81,7 @@ int audio_frame(Ampler_state *state) { 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; foreach_ptr(Sound_src, s, state -> sounds) if s -> state == SND_FREE do { @@ -94,7 +97,7 @@ void load_track(Ampler_state *state) { s16 *buffer = NULL; u32 bytes = 0; - SDL_LoadWAV("sample.wav", &spec, &buffer, &bytes); + SDL_LoadWAV(file_name, &spec, &buffer, &bytes); if spec.format != AUDIO_S16 do { puts("error: sample.wav is not s16"); @@ -110,14 +113,20 @@ void load_track(Ampler_state *state) { snd -> start = 0; snd -> end = snd->track_len; 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; - snd -> end /= 2; - snd -> start = snd -> end / 2; + if snd == &(state->sounds[0]) do + snd -> state = SND_LOOPING; for int i = 0; i < CHANNELS; i += 1 do 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 if !(snd -> tracks[i]) do puts("fffuuuck"); diff --git a/draw.c b/draw.c index 6a2035d..f7db4e1 100644 --- a/draw.c +++ b/draw.c @@ -2,31 +2,68 @@ void draw_frame(SDL_Window *w, SDL_Renderer *r, Ampler_state *state) { 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 SMOLER SDL_SetRenderDrawColor(r, 0xFF, 0x00, 0x4D, 255); const space = (44100 * 8) / 512; - // TODO: DRAW L / R OVERLAPPED IN DIFF COLORS ? - const int t = 0; + const int t = 0; // TODO: DRAW L / R OVERLAPPED IN DIFF COLORS ? + const int wav_h = 128; + if 0 do foreach_ptr(Sound_src, snd, state -> sounds) - if snd -> state != SND_FREE do - for int x = 0; x < 512; x += 1 do { - const int y = 128 + 256 * snd_i; + if snd -> state != SND_FREE do { + const int y = wav_h / 2 + (wav_h + 4) * 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]; - SDL_RenderDrawLine(r, x, y + val / 8, x, y + val); - //SDL_RenderDrawPoint(r, x, y + val); + const int sign = val < 0 ? -1 : 1; + 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; - SDL_RenderDrawLine(r, x, 0, x, 512); - SDL_RenderDrawLine(r, snd->start / space, 0, snd->start / space, 512); - SDL_RenderDrawLine(r, snd->end / space, 0, snd->end / space, 512); + if state -> played_audio_last_frame do + SDL_RenderDrawLine(r, x, top, x, bot); + 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);