udp packets are now rightly placed in message buf, that is cleared at end of frame
parent
3fa2487596
commit
2680732685
4
ampler.c
4
ampler.c
|
@ -67,6 +67,10 @@ int ampler_main(SDL_Window *w, SDL_Renderer *r, Ampler_state **u_data) {
|
||||||
state -> played_audio_last_frame = audio_frame(state);
|
state -> played_audio_last_frame = audio_frame(state);
|
||||||
draw_frame(w, r, state);
|
draw_frame(w, r, state);
|
||||||
|
|
||||||
|
// CLEAR UDP MESSAGES
|
||||||
|
foreach_ptr(Udp_msg, msg, state -> messages)
|
||||||
|
msg -> state = MSG_FREE;
|
||||||
|
|
||||||
SDL_Delay(1);
|
SDL_Delay(1);
|
||||||
|
|
||||||
if !remove("reload-trigger") do {
|
if !remove("reload-trigger") do {
|
||||||
|
|
14
ampler.h
14
ampler.h
|
@ -28,6 +28,11 @@ typedef double f64;
|
||||||
|
|
||||||
#define arraylen(a) (sizeof (a) / sizeof ((a)[0]))
|
#define arraylen(a) (sizeof (a) / sizeof ((a)[0]))
|
||||||
|
|
||||||
|
#define foreach_ptr(TYPE, N, ARRAY) \
|
||||||
|
for int N##_i = 0; N##_i == 0; N##_i = 1 do \
|
||||||
|
for TYPE *N = &((ARRAY)[N##_i]); N != NULL; N = NULL do \
|
||||||
|
for ; N##_i < arraylen(ARRAY); N##_i += 1, N = &((ARRAY)[N##_i]) do
|
||||||
|
|
||||||
#define SAMPLE_RATE (44100)
|
#define SAMPLE_RATE (44100)
|
||||||
#define CHANNELS (2)
|
#define CHANNELS (2)
|
||||||
#define FRAME_SAMPLES (SAMPLE_RATE / 60)
|
#define FRAME_SAMPLES (SAMPLE_RATE / 60)
|
||||||
|
@ -38,7 +43,13 @@ struct Sound_src {
|
||||||
s32 len; // in samples
|
s32 len; // in samples
|
||||||
f32 pos; // position in samples
|
f32 pos; // position in samples
|
||||||
f32 speed; // in samples, per sample, can be negative
|
f32 speed; // in samples, per sample, can be negative
|
||||||
enum { FREE = 0, STOPPED, PLAYING, LOOPING } state;
|
enum { SND_FREE = 0, SND_STOPPED, SND_PLAYING, SND_LOOPING, } state;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct Udp_msg Udp_msg;
|
||||||
|
struct Udp_msg {
|
||||||
|
s8 text[32]; // includes null terminator
|
||||||
|
enum { MSG_FREE = 0, MSG_TRIGGER, } state;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct Ampler_state Ampler_state;
|
typedef struct Ampler_state Ampler_state;
|
||||||
|
@ -47,6 +58,7 @@ struct Ampler_state {
|
||||||
SDL_AudioDeviceID playdev;
|
SDL_AudioDeviceID playdev;
|
||||||
Sound_src sounds[64];
|
Sound_src sounds[64];
|
||||||
s32 played_audio_last_frame;
|
s32 played_audio_last_frame;
|
||||||
|
Udp_msg messages[64];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
27
audio.c
27
audio.c
|
@ -1,7 +1,10 @@
|
||||||
// audio.c
|
// audio.c
|
||||||
|
|
||||||
|
// TODO: add something to make sure, we KNOW if we've dropped audio
|
||||||
|
// eg. buffer has gone unfilled for a frame or more
|
||||||
|
|
||||||
void sound_src_frame(Sound_src *s, s8 *mix[]) {
|
void sound_src_frame(Sound_src *s, s8 *mix[]) {
|
||||||
if s -> state == LOOPING do
|
if s -> state == SND_LOOPING do
|
||||||
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];
|
||||||
|
@ -27,8 +30,8 @@ int audio_frame(Ampler_state *state) {
|
||||||
SDL_memset(mix_r, 0, sizeof mix_r);
|
SDL_memset(mix_r, 0, sizeof mix_r);
|
||||||
|
|
||||||
s8 *mix[] = { mix_l, mix_r };
|
s8 *mix[] = { mix_l, mix_r };
|
||||||
for int s = 0; s < arraylen(state -> sounds); s += 1 do
|
foreach_ptr(Sound_src, snd, state -> sounds) //for int s = 0; s < arraylen(state -> sounds); s += 1 do
|
||||||
sound_src_frame(&(state -> sounds[s]), mix);
|
sound_src_frame(snd, mix); //sound_src_frame(&(state -> sounds[s]), mix);
|
||||||
|
|
||||||
const int vol = 100;
|
const int vol = 100;
|
||||||
static s16 frame[FRAME_SAMPLES * CHANNELS] = { 0 };
|
static s16 frame[FRAME_SAMPLES * CHANNELS] = { 0 };
|
||||||
|
@ -43,6 +46,17 @@ int audio_frame(Ampler_state *state) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void load_track(Ampler_state *state) {
|
void load_track(Ampler_state *state) {
|
||||||
|
Sound_src *snd = NULL;
|
||||||
|
foreach_ptr(Sound_src, s, state -> sounds)
|
||||||
|
if s -> state == SND_FREE do {
|
||||||
|
snd = s;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if snd == NULL do {
|
||||||
|
puts("error: all sound sources in use");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
SDL_AudioSpec spec;
|
SDL_AudioSpec spec;
|
||||||
s16 *buffer = NULL;
|
s16 *buffer = NULL;
|
||||||
u32 bytes = 0;
|
u32 bytes = 0;
|
||||||
|
@ -57,18 +71,17 @@ void load_track(Ampler_state *state) {
|
||||||
const int chans = spec.channels;
|
const int chans = spec.channels;
|
||||||
const int length = (bytes / sizeof s16) / chans;
|
const int length = (bytes / sizeof s16) / chans;
|
||||||
|
|
||||||
// TODO: Actually find free sound_src
|
|
||||||
Sound_src *snd = &(state -> sounds[0]);
|
|
||||||
snd -> len = length;
|
snd -> len = length;
|
||||||
snd -> speed = 1.0f;
|
snd -> speed = 1.0f;
|
||||||
snd -> pos = 0.0f;
|
snd -> pos = 0.0f;
|
||||||
snd -> state = LOOPING; // TOOD: Should be STOPPED
|
// snd -> state = SND_LOOPING;
|
||||||
|
snd -> state = SND_STOPPED;
|
||||||
|
|
||||||
for int i = 0; i < CHANNELS; i += 1 do
|
for int i = 0; i < CHANNELS; i += 1 do
|
||||||
snd -> tracks[i] = malloc(snd -> len);
|
snd -> tracks[i] = malloc(snd -> len);
|
||||||
|
|
||||||
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");
|
||||||
|
|
||||||
for int i = 0; i < snd -> len; i += 1 do
|
for int i = 0; i < snd -> len; i += 1 do
|
||||||
|
|
21
draw.c
21
draw.c
|
@ -5,20 +5,23 @@ void draw_frame(SDL_Window *w, SDL_Renderer *r, Ampler_state *state) {
|
||||||
//SDL_SetRenderDrawColor(r, 10, 10, 10, 100);
|
//SDL_SetRenderDrawColor(r, 10, 10, 10, 100);
|
||||||
SDL_RenderClear(r);
|
SDL_RenderClear(r);
|
||||||
|
|
||||||
// TODO: ACTUALLY DRAW ALL SOUNDS, BUT 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;
|
const int t = 0;
|
||||||
for int x = 0; x < 512; x += 1 do {
|
foreach_ptr(Sound_src, snd, state -> sounds)
|
||||||
const int y = 128 + 256 * t;
|
if snd -> state != SND_FREE do
|
||||||
const int val = state -> sounds[0].tracks[t][x * space];
|
for int x = 0; x < 512; x += 1 do {
|
||||||
SDL_RenderDrawLine(r, x, y + val / 8, x, y + val);
|
const int y = 128 + 256 * snd_i;
|
||||||
//SDL_RenderDrawPoint(r, x, y + val);
|
const int val = snd -> tracks[t][x * space];
|
||||||
}
|
SDL_RenderDrawLine(r, x, y + val / 8, x, y + val);
|
||||||
|
//SDL_RenderDrawPoint(r, x, y + val);
|
||||||
|
}
|
||||||
|
|
||||||
if state -> played_audio_last_frame do
|
if state -> played_audio_last_frame do
|
||||||
for int i = 0; i < arraylen(state -> sounds); i += 1 do {
|
foreach_ptr(Sound_src, snd, state -> sounds) {
|
||||||
const int x = state -> sounds[i].pos / space;
|
const int x = snd -> pos / space;
|
||||||
SDL_RenderDrawLine(r, x, 0, x, 512);
|
SDL_RenderDrawLine(r, x, 0, x, 512);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
79
udp.c
79
udp.c
|
@ -1,5 +1,13 @@
|
||||||
// udp.c
|
// udp.c
|
||||||
|
|
||||||
|
/* TODO:
|
||||||
|
* convert error codes to strings and print them, we could just make a table
|
||||||
|
* option to change port, handle when we cant get gur port
|
||||||
|
* be able to send packets when sounds / recording starts / ends ?
|
||||||
|
|
||||||
|
* store from ip + port in message ?
|
||||||
|
*/
|
||||||
|
|
||||||
#include <winsock2.h>
|
#include <winsock2.h>
|
||||||
|
|
||||||
#include "ampler.h"
|
#include "ampler.h"
|
||||||
|
@ -46,6 +54,51 @@ void udp_init(Ampler_state *state) {
|
||||||
printf("error: bind returned SOCKET_ERROR, WSAGetLastError() = %i\n" , WSAGetLastError());
|
printf("error: bind returned SOCKET_ERROR, WSAGetLastError() = %i\n" , WSAGetLastError());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void udp_quit(Ampler_state *state) {
|
||||||
|
closesocket(udp_sock);
|
||||||
|
WSACleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
void recv_packet(Ampler_state *state) {
|
||||||
|
char discard_buf[32] = { 0 }; // for dropped packets
|
||||||
|
char *buf = discard_buf;
|
||||||
|
int buf_len = sizeof discard_buf;
|
||||||
|
|
||||||
|
for (int i = 0; i < arraylen(state -> messages); i += 1) {
|
||||||
|
Udp_msg *msg = &(state -> messages[i]);
|
||||||
|
if (msg -> state == MSG_FREE) {
|
||||||
|
msg -> state = MSG_TRIGGER;
|
||||||
|
buf = msg -> text;
|
||||||
|
buf_len = sizeof msg -> text;
|
||||||
|
SDL_memset(buf, 0, buf_len);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (buf == discard_buf)
|
||||||
|
puts("dropped udp packet.");
|
||||||
|
|
||||||
|
struct sockaddr_in from_addr;
|
||||||
|
int from_addr_size = sizeof from_addr;
|
||||||
|
// https://docs.microsoft.com/en-us/windows/win32/api/winsock/nf-winsock-recvfrom
|
||||||
|
int recv_len = recvfrom(
|
||||||
|
udp_sock, // socket to recive on
|
||||||
|
buf, // buffer for recv'd data
|
||||||
|
buf_len - 1, // size of buffer in bytes, '- 1' preserves null terminator
|
||||||
|
0, // flags
|
||||||
|
&from_addr, // address struct to recieve source of packet
|
||||||
|
&from_addr_size // POINTER to size of address struct
|
||||||
|
);
|
||||||
|
if (recv_len == SOCKET_ERROR)
|
||||||
|
if (WSAGetLastError() != WSAEMSGSIZE) // packet was truncated to fit buffer
|
||||||
|
printf("error: recvfrom returned SOCKET_ERROR, WSAGetLastError() = %i\n" , WSAGetLastError());
|
||||||
|
|
||||||
|
// convert to ipv4 address string, stored in static buffer, next call overwrites
|
||||||
|
const char *from_ip_str = inet_ntoa(from_addr.sin_addr);
|
||||||
|
int from_port = ntohs(from_addr.sin_port); // convert network to host byte order for short
|
||||||
|
if (0) // FOR DEBUGGING
|
||||||
|
printf("%s:%d\t%s\n", from_ip_str, from_port, buf);
|
||||||
|
}
|
||||||
|
|
||||||
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;
|
||||||
|
@ -77,34 +130,10 @@ void udp_frame(Ampler_state *state) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
char buf[16] = { 0 };
|
recv_packet(state);
|
||||||
struct sockaddr_in from_addr;
|
|
||||||
int from_addr_size = sizeof from_addr;
|
|
||||||
// https://docs.microsoft.com/en-us/windows/win32/api/winsock/nf-winsock-recvfrom
|
|
||||||
int recv_len = recvfrom(
|
|
||||||
udp_sock, // socket to recive on
|
|
||||||
buf, // buffer for recv'd data
|
|
||||||
sizeof buf - 1, // size of buffer in bytes, '- 1' preserves null terminator
|
|
||||||
0, // flags
|
|
||||||
&from_addr, // address struct to recieve source of packet
|
|
||||||
&from_addr_size // POINTER to size of address struct
|
|
||||||
);
|
|
||||||
if (recv_len == SOCKET_ERROR)
|
|
||||||
if (WSAGetLastError() != WSAEMSGSIZE) // packet was truncated to fit buffer
|
|
||||||
printf("error: recvfrom returned SOCKET_ERROR, WSAGetLastError() = %i\n" , WSAGetLastError());
|
|
||||||
|
|
||||||
// convert to ipv4 address string, stored in static buffer, next call overwrites
|
|
||||||
const char *from_ip_str = inet_ntoa(from_addr.sin_addr);
|
|
||||||
int from_port = ntohs(from_addr.sin_port); // convert network to host byte order for short
|
|
||||||
printf("%s\t\t%s:%d\n", buf, from_ip_str, from_port);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void udp_quit(Ampler_state *state) {
|
|
||||||
closesocket(udp_sock);
|
|
||||||
WSACleanup();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue