udp packets are now rightly placed in message buf, that is cleared at end of frame

master
bxwtf 2021-12-22 23:20:51 +00:00
parent 3fa2487596
commit 2680732685
5 changed files with 103 additions and 42 deletions

View File

@ -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);
draw_frame(w, r, state);
// CLEAR UDP MESSAGES
foreach_ptr(Udp_msg, msg, state -> messages)
msg -> state = MSG_FREE;
SDL_Delay(1);
if !remove("reload-trigger") do {

View File

@ -28,6 +28,11 @@ typedef double f64;
#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 CHANNELS (2)
#define FRAME_SAMPLES (SAMPLE_RATE / 60)
@ -38,7 +43,13 @@ struct Sound_src {
s32 len; // in samples
f32 pos; // position in samples
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;
@ -47,6 +58,7 @@ struct Ampler_state {
SDL_AudioDeviceID playdev;
Sound_src sounds[64];
s32 played_audio_last_frame;
Udp_msg messages[64];
};

27
audio.c
View File

@ -1,7 +1,10 @@
// 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[]) {
if s -> state == LOOPING do
if s -> state == SND_LOOPING do
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];
@ -27,8 +30,8 @@ int audio_frame(Ampler_state *state) {
SDL_memset(mix_r, 0, sizeof mix_r);
s8 *mix[] = { mix_l, mix_r };
for int s = 0; s < arraylen(state -> sounds); s += 1 do
sound_src_frame(&(state -> sounds[s]), mix);
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);
const int vol = 100;
static s16 frame[FRAME_SAMPLES * CHANNELS] = { 0 };
@ -43,6 +46,17 @@ int audio_frame(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;
s16 *buffer = NULL;
u32 bytes = 0;
@ -57,18 +71,17 @@ void load_track(Ampler_state *state) {
const int chans = spec.channels;
const int length = (bytes / sizeof s16) / chans;
// TODO: Actually find free sound_src
Sound_src *snd = &(state -> sounds[0]);
snd -> len = length;
snd -> speed = 1.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
snd -> tracks[i] = malloc(snd -> len);
for int i = 0; i < CHANNELS; i += 1 do
if !snd -> tracks[i] do
if !(snd -> tracks[i]) do
puts("fffuuuck");
for int i = 0; i < snd -> len; i += 1 do

21
draw.c
View File

@ -5,20 +5,23 @@ void draw_frame(SDL_Window *w, SDL_Renderer *r, Ampler_state *state) {
//SDL_SetRenderDrawColor(r, 10, 10, 10, 100);
SDL_RenderClear(r);
// TODO: ACTUALLY DRAW ALL SOUNDS, BUT SMOLER
// 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;
for int x = 0; x < 512; x += 1 do {
const int y = 128 + 256 * t;
const int val = state -> sounds[0].tracks[t][x * space];
SDL_RenderDrawLine(r, x, y + val / 8, x, y + val);
//SDL_RenderDrawPoint(r, x, y + val);
}
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;
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
for int i = 0; i < arraylen(state -> sounds); i += 1 do {
const int x = state -> sounds[i].pos / space;
foreach_ptr(Sound_src, snd, state -> sounds) {
const int x = snd -> pos / space;
SDL_RenderDrawLine(r, x, 0, x, 512);
}

79
udp.c
View File

@ -1,5 +1,13 @@
// 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 "ampler.h"
@ -46,6 +54,51 @@ void udp_init(Ampler_state *state) {
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) {
// https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-select
fd_set recv_fd_set;
@ -77,34 +130,10 @@ void udp_frame(Ampler_state *state) {
return;
}
char buf[16] = { 0 };
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);
recv_packet(state);
}
}
void udp_quit(Ampler_state *state) {
closesocket(udp_sock);
WSACleanup();
}