Compare commits
2 Commits
4039d4edf8
...
6b3c8210b5
Author | SHA1 | Date |
---|---|---|
bx | 6b3c8210b5 | |
bx | 6f01e60b10 |
|
@ -3,3 +3,5 @@
|
||||||
*.dll
|
*.dll
|
||||||
reload-trigger
|
reload-trigger
|
||||||
*.wav
|
*.wav
|
||||||
|
*.so
|
||||||
|
core
|
||||||
|
|
28
ampler.c
28
ampler.c
|
@ -6,10 +6,10 @@
|
||||||
#include "draw.c"
|
#include "draw.c"
|
||||||
|
|
||||||
Ampler_state *init() {
|
Ampler_state *init() {
|
||||||
Ampler_state *state = malloc(sizeof Ampler_state);
|
Ampler_state *state = malloc(sizeof (Ampler_state));
|
||||||
SDL_memset(state, 0, sizeof Ampler_state);
|
SDL_memset(state, 0, sizeof (Ampler_state));
|
||||||
|
|
||||||
state -> size = sizeof Ampler_state;
|
state -> size = sizeof (Ampler_state);
|
||||||
|
|
||||||
SDL_AudioSpec want = { 0 }, have = { 0 };
|
SDL_AudioSpec want = { 0 }, have = { 0 };
|
||||||
want.freq = SAMPLE_RATE;
|
want.freq = SAMPLE_RATE;
|
||||||
|
@ -29,11 +29,21 @@ Ampler_state *init() {
|
||||||
if !(state -> playdev) do
|
if !(state -> playdev) do
|
||||||
puts(SDL_GetError());
|
puts(SDL_GetError());
|
||||||
|
|
||||||
|
state -> recdev = SDL_OpenAudioDevice(
|
||||||
|
NULL, // default device
|
||||||
|
1, // is capture
|
||||||
|
&want,
|
||||||
|
&have,
|
||||||
|
0 // no changes allowed
|
||||||
|
);
|
||||||
|
if !(state -> playdev) do
|
||||||
|
puts(SDL_GetError());
|
||||||
|
|
||||||
// TODO: iterate a directory to load samples
|
// TODO: iterate a directory to load samples
|
||||||
//load_sample(state, "mix.wav");
|
//load_sample(state, "./mix.wav");
|
||||||
//load_sample(state, "loop2.wav");
|
//load_sample(state, "./loop2.wav");
|
||||||
//load_sample(state, "loop.wav");
|
//load_sample(state, "./loop.wav");
|
||||||
//load_sample(state, "chord.wav");
|
//load_sample(state, "./chord.wav");
|
||||||
|
|
||||||
puts("init.");
|
puts("init.");
|
||||||
return state;
|
return state;
|
||||||
|
@ -42,7 +52,7 @@ Ampler_state *init() {
|
||||||
int ampler_main(SDL_Window *w, SDL_Renderer *r, Ampler_state **u_data) {
|
int ampler_main(SDL_Window *w, SDL_Renderer *r, Ampler_state **u_data) {
|
||||||
if *u_data == NULL do *u_data = init();
|
if *u_data == NULL do *u_data = init();
|
||||||
|
|
||||||
u32 old_size = (*u_data) -> size, new_size = sizeof Ampler_state;
|
u32 old_size = (*u_data) -> size, new_size = sizeof(Ampler_state);
|
||||||
if old_size < new_size do {
|
if old_size < new_size do {
|
||||||
printf("increasing size. %i to %i\n", old_size, new_size);
|
printf("increasing size. %i to %i\n", old_size, new_size);
|
||||||
Ampler_state *nu = malloc(new_size);
|
Ampler_state *nu = malloc(new_size);
|
||||||
|
@ -60,6 +70,7 @@ int ampler_main(SDL_Window *w, SDL_Renderer *r, Ampler_state **u_data) {
|
||||||
// put results in state for last frame's perf, so that we can draw it
|
// put results in state for last frame's perf, so that we can draw it
|
||||||
SDL_SetWindowTitle(w, "ampler");
|
SDL_SetWindowTitle(w, "ampler");
|
||||||
SDL_PauseAudioDevice(state -> playdev, 0); // unpause audio
|
SDL_PauseAudioDevice(state -> playdev, 0); // unpause audio
|
||||||
|
SDL_PauseAudioDevice(state -> recdev, 0); // unpause audio
|
||||||
udp_init(state);
|
udp_init(state);
|
||||||
while 1 do {
|
while 1 do {
|
||||||
SDL_Event e;
|
SDL_Event e;
|
||||||
|
@ -80,6 +91,7 @@ int ampler_main(SDL_Window *w, SDL_Renderer *r, Ampler_state **u_data) {
|
||||||
|
|
||||||
if !remove("reload-trigger") do {
|
if !remove("reload-trigger") do {
|
||||||
SDL_PauseAudioDevice(state -> playdev, 1); // pause audio
|
SDL_PauseAudioDevice(state -> playdev, 1); // pause audio
|
||||||
|
SDL_PauseAudioDevice(state -> recdev, 1); // pause audio
|
||||||
udp_quit(state);
|
udp_quit(state);
|
||||||
puts("removed reload-trigger, reloading...");
|
puts("removed reload-trigger, reloading...");
|
||||||
return 0;
|
return 0;
|
||||||
|
|
2
ampler.h
2
ampler.h
|
@ -63,10 +63,12 @@ typedef struct Ampler_state Ampler_state;
|
||||||
struct Ampler_state {
|
struct Ampler_state {
|
||||||
u32 size; // in bytes, off this struct
|
u32 size; // in bytes, off this struct
|
||||||
SDL_AudioDeviceID playdev;
|
SDL_AudioDeviceID playdev;
|
||||||
|
SDL_AudioDeviceID recdev;
|
||||||
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];
|
s8 frame_mix[CHANNELS][FRAME_SAMPLES];
|
||||||
|
s8 frame_rec[CHANNELS][FRAME_SAMPLES];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
38
audio.c
38
audio.c
|
@ -60,9 +60,33 @@ void sound_src_frame(Sound_src *s, s8 *mix[]) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void rec_frame(Ampler_state *state) {
|
||||||
|
// const int frame_bytes = FRAME_SAMPLES * CHANNELS * sizeof(s16);
|
||||||
|
static s16 buf[FRAME_SAMPLES * CHANNELS * sizeof(s16)];
|
||||||
|
|
||||||
|
u32 samps = SDL_GetQueuedAudioSize(state->recdev) / sizeof(s16);
|
||||||
|
|
||||||
|
// TODO: this introduces a frame of lag, but should make sure we always
|
||||||
|
// deque a full frame, maybe find a less laggy way ?
|
||||||
|
if samps > FRAME_SAMPLES * CHANNELS * 2 do {
|
||||||
|
u32 bytes = SDL_DequeueAudio(state->recdev, buf, sizeof(buf));
|
||||||
|
// printf("%i %i %i samples\n", samps, bytes / sizeof(s16), sizeof(buf) / 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: test with stero recording input to make sure this works
|
||||||
|
for int i = 0; i < FRAME_SAMPLES; i += 1 do
|
||||||
|
for int c = 0; c < CHANNELS; c += 1 do {
|
||||||
|
state->frame_rec[c][i] = buf[i * CHANNELS + c] >> 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int audio_frame(Ampler_state *state) {
|
int audio_frame(Ampler_state *state) {
|
||||||
|
// TODO: it's unlikely but possible that we can miss recorded data because
|
||||||
|
// gur rec buffer was filled on a frame where we didn't play anything
|
||||||
|
rec_frame(state);
|
||||||
|
|
||||||
int queued = SDL_GetQueuedAudioSize(state -> playdev);
|
int queued = SDL_GetQueuedAudioSize(state -> playdev);
|
||||||
queued /= sizeof s16; // queued is in bytes
|
queued /= sizeof (s16); // queued is in bytes
|
||||||
|
|
||||||
if queued > FRAME_SAMPLES * CHANNELS * 2 do return 0;
|
if queued > FRAME_SAMPLES * CHANNELS * 2 do return 0;
|
||||||
// else puts("queued audio.");
|
// else puts("queued audio.");
|
||||||
|
@ -72,8 +96,8 @@ int audio_frame(Ampler_state *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 };
|
||||||
s8 *mix_l = state->frame_mix[0], *mix_r = state->frame_mix[1];
|
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_l, 0, FRAME_SAMPLES / sizeof (s8));
|
||||||
SDL_memset(mix_r, 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)
|
foreach_ptr(Sound_src, snd, state -> sounds)
|
||||||
|
@ -85,7 +109,7 @@ int audio_frame(Ampler_state *state) {
|
||||||
for int t = 0; t < CHANNELS; t += 1 do
|
for int t = 0; t < CHANNELS; t += 1 do
|
||||||
frame[i * CHANNELS + t] = ((s16) (mix[t][i])) * vol;
|
frame[i * CHANNELS + t] = ((s16) (mix[t][i])) * vol;
|
||||||
|
|
||||||
if SDL_QueueAudio(state -> playdev, frame, sizeof frame) do
|
if SDL_QueueAudio(state -> playdev, frame, sizeof (frame)) do
|
||||||
puts(SDL_GetError());
|
puts(SDL_GetError());
|
||||||
|
|
||||||
return 1; // audio was qued
|
return 1; // audio was qued
|
||||||
|
@ -107,7 +131,7 @@ void load_sample(Ampler_state *state, const char *file_name) {
|
||||||
s16 *buffer = NULL;
|
s16 *buffer = NULL;
|
||||||
u32 bytes = 0;
|
u32 bytes = 0;
|
||||||
|
|
||||||
SDL_LoadWAV(file_name, &spec, &buffer, &bytes);
|
SDL_LoadWAV(file_name, &spec, (u8 **) &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");
|
||||||
|
@ -115,7 +139,7 @@ void load_sample(Ampler_state *state, const char *file_name) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const int chans = spec.channels;
|
const int chans = spec.channels;
|
||||||
const int length = (bytes / sizeof s16) / chans;
|
const int length = (bytes / sizeof (s16)) / chans;
|
||||||
|
|
||||||
snd -> track_len = length;
|
snd -> track_len = length;
|
||||||
snd -> speed = 1.0f;
|
snd -> speed = 1.0f;
|
||||||
|
@ -124,7 +148,7 @@ void load_sample(Ampler_state *state, const char *file_name) {
|
||||||
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 ?
|
snd -> note_speed = 1.0f; // TODO: Look up a note ?
|
||||||
SDL_memset(snd->name, 0, sizeof snd->name);
|
SDL_memset(snd->name, 0, sizeof (snd->name));
|
||||||
for int i = 0; i < arraylen(snd->name) - 1; i += 1 do
|
for int i = 0; i < arraylen(snd->name) - 1; i += 1 do
|
||||||
if file_name[i] == '\0' or file_name[i] == '.' do break;
|
if file_name[i] == '\0' or file_name[i] == '.' do break;
|
||||||
else snd->name[i] = file_name[i];
|
else snd->name[i] = file_name[i];
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
#!/bin/bash
|
||||||
|
gcc ampler.c udp.c -o ampler.so -shared -lSDL2 -g --std c99 && echo > reload-trigger
|
|
@ -0,0 +1,2 @@
|
||||||
|
#!/bin/bash
|
||||||
|
gcc core.c -o core -lSDL2 -g
|
31
core.c
31
core.c
|
@ -6,11 +6,30 @@
|
||||||
#define SDL_MAIN_HANDLED
|
#define SDL_MAIN_HANDLED
|
||||||
#include <SDL2/SDL.h>
|
#include <SDL2/SDL.h>
|
||||||
|
|
||||||
|
#ifdef __WIN32__
|
||||||
# define SHARED_OBJECT "ampler.dll"
|
# define SHARED_OBJECT "ampler.dll"
|
||||||
|
# define SHARED_OBJECT_ACTIVE SHARED_OBJECT "-active.dll"
|
||||||
|
#else
|
||||||
|
# define SHARED_OBJECT "./ampler.so"
|
||||||
|
# define SHARED_OBJECT_ACTIVE SHARED_OBJECT
|
||||||
|
#endif
|
||||||
|
|
||||||
#define SHARED_MAIN "ampler_main"
|
#define SHARED_MAIN "ampler_main"
|
||||||
|
|
||||||
|
#ifdef __WIN32__
|
||||||
#define SHARED_OBJECT_ACTIVE SHARED_OBJECT "-active.dll"
|
int copy_shared_object() {
|
||||||
|
if (system("copy " SHARED_OBJECT " " SHARED_OBJECT_ACTIVE " /Y")) {
|
||||||
|
puts("failed copying to " SHARED_OBJECT_ACTIVE);
|
||||||
|
// puts(SDL_GetError());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
int copy_shared_object() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
puts("start.");
|
puts("start.");
|
||||||
|
@ -25,16 +44,10 @@ int main(int argc, char **argv) {
|
||||||
r = SDL_CreateRenderer(w, -1,
|
r = SDL_CreateRenderer(w, -1,
|
||||||
SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE);
|
SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE);
|
||||||
|
|
||||||
//SDL_CreateWindowAndRenderer(
|
|
||||||
// 1080, 480, SDL_WINDOW_RESIZABLE, &w, &r);
|
|
||||||
|
|
||||||
void *u_data = NULL;
|
void *u_data = NULL;
|
||||||
while (1) {
|
while (1) {
|
||||||
if (system("copy " SHARED_OBJECT " " SHARED_OBJECT_ACTIVE " /Y")) {
|
if (copy_shared_object())
|
||||||
puts("failed copying to " SHARED_OBJECT_ACTIVE);
|
|
||||||
// puts(SDL_GetError());
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
void *so = SDL_LoadObject(SHARED_OBJECT_ACTIVE);
|
void *so = SDL_LoadObject(SHARED_OBJECT_ACTIVE);
|
||||||
if (so == 0) {
|
if (so == 0) {
|
||||||
|
|
6
draw.c
6
draw.c
|
@ -13,7 +13,7 @@ void draw_frame(SDL_Window *w, SDL_Renderer *r, Ampler_state *state) {
|
||||||
// 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 int space = (44100 * 8) / 512;
|
||||||
const int t = 0; // TODO: DRAW L / R OVERLAPPED IN DIFF COLORS ?
|
const int t = 0; // TODO: DRAW L / R OVERLAPPED IN DIFF COLORS ?
|
||||||
const int wav_h = 128;
|
const int wav_h = 128;
|
||||||
if 0 do
|
if 0 do
|
||||||
|
@ -40,6 +40,10 @@ void draw_frame(SDL_Window *w, SDL_Renderer *r, Ampler_state *state) {
|
||||||
for int x = 0; x < FRAME_SAMPLES - 1; x += 1 do {
|
for int x = 0; x < FRAME_SAMPLES - 1; x += 1 do {
|
||||||
u8 cur = state->frame_mix[0][x] + 128;
|
u8 cur = state->frame_mix[0][x] + 128;
|
||||||
u8 next = state->frame_mix[0][x + 1] + 128;
|
u8 next = state->frame_mix[0][x + 1] + 128;
|
||||||
|
|
||||||
|
cur = state->frame_rec[0][x] + 128;
|
||||||
|
next = state->frame_rec[0][x + 1] + 128;
|
||||||
|
|
||||||
markov[cur][next] += 1;
|
markov[cur][next] += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
35
udp.c
35
udp.c
|
@ -8,7 +8,14 @@
|
||||||
* store from ip + port in message ?
|
* store from ip + port in message ?
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifdef __WIN32__
|
||||||
#include <winsock2.h>
|
#include <winsock2.h>
|
||||||
|
#else
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/select.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "ampler.h"
|
#include "ampler.h"
|
||||||
|
|
||||||
|
@ -19,8 +26,13 @@
|
||||||
#undef while
|
#undef while
|
||||||
|
|
||||||
// G l o b a L E v i L //
|
// G l o b a L E v i L //
|
||||||
|
#ifdef __WIN32__
|
||||||
static SOCKET udp_sock;
|
static SOCKET udp_sock;
|
||||||
|
#else
|
||||||
|
static int udp_sock;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __WIN32__
|
||||||
void udp_init(Ampler_state *state) {
|
void udp_init(Ampler_state *state) {
|
||||||
// https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-wsastartup
|
// https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-wsastartup
|
||||||
WSADATA wsa;
|
WSADATA wsa;
|
||||||
|
@ -53,12 +65,24 @@ void udp_init(Ampler_state *state) {
|
||||||
if (bind_result == SOCKET_ERROR)
|
if (bind_result == SOCKET_ERROR)
|
||||||
printf("error: bind returned SOCKET_ERROR, WSAGetLastError() = %i\n" , WSAGetLastError());
|
printf("error: bind returned SOCKET_ERROR, WSAGetLastError() = %i\n" , WSAGetLastError());
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
void udp_init(Ampler_state *state) {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __WIN32__
|
||||||
void udp_quit(Ampler_state *state) {
|
void udp_quit(Ampler_state *state) {
|
||||||
closesocket(udp_sock);
|
closesocket(udp_sock);
|
||||||
WSACleanup();
|
WSACleanup();
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
void udp_quit(Ampler_state *state) {
|
||||||
|
// close(udp_sock);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __WIN32__
|
||||||
void recv_packet(Ampler_state *state) {
|
void recv_packet(Ampler_state *state) {
|
||||||
char discard_buf[32] = { 0 }; // for dropped packets
|
char discard_buf[32] = { 0 }; // for dropped packets
|
||||||
char *buf = discard_buf;
|
char *buf = discard_buf;
|
||||||
|
@ -98,7 +122,13 @@ void recv_packet(Ampler_state *state) {
|
||||||
if (0) // FOR DEBUGGING
|
if (0) // FOR DEBUGGING
|
||||||
printf("%s:%d\t%s\n", from_ip_str, from_port, buf);
|
printf("%s:%d\t%s\n", from_ip_str, from_port, buf);
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
void recv_packet(Ampler_state *state) {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __WIN32__
|
||||||
void udp_frame(Ampler_state *state) {
|
void udp_frame(Ampler_state *state) {
|
||||||
// https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-select
|
// https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-select
|
||||||
fd_set recv_fd_set;
|
fd_set recv_fd_set;
|
||||||
|
@ -133,6 +163,11 @@ void udp_frame(Ampler_state *state) {
|
||||||
recv_packet(state);
|
recv_packet(state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
void udp_frame(Ampler_state *state) {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue