Mixer and a few filters

This commit is contained in:
John Alanbrook 2022-07-06 22:17:06 +00:00
parent 1c556a70bc
commit eb49f0fcc5
11 changed files with 350 additions and 104 deletions

View file

@ -79,7 +79,7 @@ COMPINCLUDE = $(edirs) $(eddirs) $(pindirs) $(bsdirs)
WARNING_FLAGS = -Wall -Wwrite-strings -Wunsupported #-Wall -Wextra -Wwrite-strings -Wno-unused-parameter -Wno-unused-function -Wno-missing-braces -Wno-incompatible-function-pointer-types -Wno-gnu-statement-expression -Wno-complex-component-init -pedantic
WARNING_FLAGS = -Wall -Wwrite-strings -Wunsupported -Wall -Wextra -Wwrite-strings -Wno-unused-parameter -Wno-unused-function -Wno-missing-braces -Wno-incompatible-function-pointer-types -Wno-gnu-statement-expression -Wno-complex-component-init -pedantic

View file

@ -22,16 +22,16 @@ struct fileasset {
};
struct editorVars {
bool showStats :1 ;
bool showHierarchy :1 ;
bool showLighting :1 ;
bool showGameSettings :1 ;
bool showViewmode :1 ;
bool showDebugMenu :1 ;
bool showAssetMenu :1 ;
bool showREPL :1 ;
bool showExport :1 ;
bool showLevel :1 ;
bool showStats;
bool showHierarchy;
bool showLighting;
bool showGameSettings;
bool showViewmode;
bool showDebugMenu;
bool showAssetMenu;
bool showREPL;
bool showExport;
bool showLevel;
};
struct gameproject {

View file

@ -7,7 +7,6 @@ struct circbuf circbuf_init(size_t size, unsigned int len)
{
struct circbuf new;
new.len = powof2(len);
new.len = len;
new.data = calloc(sizeof(short), new.len);
new.read = new.write = 0;
@ -23,7 +22,7 @@ int cbuf_empty(struct circbuf *buf) {
}
int cbuf_full(struct circbuf *buf) {
return cbuf_size(buf) == buf->len;
return cbuf_size(buf) >= buf->len;
}
uint32_t cbuf_mask(struct circbuf *buf, uint32_t n) {
@ -31,13 +30,13 @@ uint32_t cbuf_mask(struct circbuf *buf, uint32_t n) {
}
void cbuf_push(struct circbuf *buf, short data) {
assert(!cbuf_full(buf));
//assert(!cbuf_full(buf));
buf->data[cbuf_mask(buf,buf->write++)] = data;
}
short cbuf_shift(struct circbuf *buf) {
assert(!cbuf_empty(buf));
//assert(!cbuf_empty(buf));
return buf->data[cbuf_mask(buf, buf->read++)];
}

View file

@ -9,6 +9,8 @@
#include "log.h"
#include "texture.h"
#include <stdlib.h>
#include "mix.h"
#include "limits.h"
struct mShader *vid_shader;
@ -31,7 +33,12 @@ static void render_frame(plm_t * mpeg, plm_frame_t * frame, void *user)
static void render_audio(plm_t * mpeg, plm_samples_t * samples, void *user)
{
struct datastream *ds = user;
play_raw(ds->audio_device, samples->interleaved, samples->count * 2);
short t;
for (int i = 0; i < samples->count * CHANNELS; i++) {
t = (short)(samples->interleaved[i] * SHRT_MAX);
cbuf_push(&ds->astream.buf, t*5);
}
}
struct Texture *ds_maketexture(struct datastream *ds)
@ -62,6 +69,14 @@ void ds_openvideo(struct datastream *ds, const char *video, const char *adriver)
plm_get_duration(ds->plm)
);
ds->astream = soundstream_make();
struct dsp_filter astream_filter;
astream_filter.data = &ds->astream;
astream_filter.filter = soundstream_fillbuf;
first_free_bus(astream_filter);
printf("Circbuf size is %u.\n", ds->astream.buf.len);
plm_set_video_decode_callback(ds->plm, render_frame, ds);
plm_set_audio_decode_callback(ds->plm, render_audio, ds);
plm_set_loop(ds->plm, false);
@ -118,7 +133,7 @@ void ds_advance(struct datastream *ds, double s)
void ds_seek(struct datastream *ds, double time)
{
clear_raw(ds->audio_device);
//clear_raw(ds->audio_device);
plm_seek(ds->plm, time, false);
}

View file

@ -3,6 +3,7 @@
#include <stdint.h>
#include <pl_mpeg.h>
#include "sound.h"
struct datastream {
plm_t *plm;
@ -13,6 +14,7 @@ struct datastream {
uint32_t texture_y;
uint32_t texture_cb;
uint32_t texture_cr;
struct soundstream astream;
};
struct Texture;

View file

@ -3,13 +3,28 @@
#include "sound.h"
#include "limits.h"
#include "math.h"
#include "stdlib.h"
#define PI 3.14159265
void am_mod(short *a, short *b, short *c, int n)
struct dsp_filter make_dsp(void *data, void (*in)(void *data, short *out, int n)) {
struct dsp_filter new;
new.data = data;
new.filter = in;
}
void dsp_run(struct dsp_filter filter, short *out, int n) {
filter.filter(filter.data, out, n);
}
void am_mod(struct dsp_ammod *mod, short *c, int n)
{
for (int i = 0; i < n; i++) {
c[i] = (a[i]*b[i])>>15;
dsp_run(mod->ina, mod->abuf, n);
dsp_run(mod->inb, mod->bbuf, n);
for (int i = 0; i < n*2; i++) {
c[i] = (mod->abuf[i]*mod->bbuf[i])>>15;
//c[i] = mod->abuf[i];
}
}
@ -38,10 +53,11 @@ struct wav gen_sine(float amp, float freq, int sr, int ch)
for (int j = 0; j < new.ch; j++) {
data[i*new.ch+j] = val;
printf("Element %i gets val %i.\n", i*new.frames+j, val);
}
}
printf("Made sine with %i frames.\n", new.frames);
return new;
}
@ -112,4 +128,106 @@ void make_dsp_filter()
void dsp_filter(short *in, short *out, int samples, struct dsp_delay *d)
{
}
void dsp_rectify(short *in, short *out, int n)
{
for (int i = 0; i < n; i++) {
out[i] = abs(in[i]);
}
}
struct phasor phasor_make(unsigned int sr, float freq)
{
struct phasor new;
new.sr = sr;
new.cur = 0.f;
new.freq = freq;
new.cstep = 0;
new.clen = new.sr / new.freq;
new.cache = malloc(new.clen * sizeof(float));
for (int i = 0; i < new.clen; i++) {
new.cache[i] = (float)i / new.clen;
}
return new;
}
float phasor_step(struct phasor *p)
{
p->cur += p->freq/p->sr;
if (p->cur >= 1.f) p->cur = 0.f;
return p->cur;
/*
float ret = p->cache[p->cstep++];
if (p->cstep ==p->clen) p->cstep = 0;
return ret;
*/
}
float sin_phasor(float p)
{
return sin(2*PI*p);
}
float square_phasor(float p)
{
return lround(p);
}
float saw_phasor(float p)
{
return 2*p-1;
}
float tri_phasor(float p)
{
return 4*(p * 0.5f ? p : (1-p)) - 1;
}
void osc_fillbuf(struct osc *osc, short *buf, int n)
{
for (int i = 0; i < n; i++) {
short val = SHRT_MAX * osc->f(phasor_step(&osc->p));
buf[i*2] = buf[i*2+1] = val;
}
}
void gen_whitenoise(void *data, short *buf, int n)
{
for (int i = 0; i < n; i++) {
for (int j = 0; j < 2; j++) {
buf[i*2+j] = (rand()>>15) - USHRT_MAX;
}
}
}
struct dsp_delay dsp_delay_make(unsigned int ms_delay)
{
struct dsp_delay new;
new.ms_delay = ms_delay;
/* Circular buffer size is enough to have the delay */
unsigned int datasize = ms_delay * CHANNELS * (SAMPLERATE / 1000);
new.buf = circbuf_init(sizeof(short), datasize);
new.buf.write = datasize;
printf("Buffer size is %u.\n", new.buf.len);
return new;
}
void dsp_delay_filbuf(struct dsp_delay *delay, short *buf, int n)
{
static short cache[BUF_FRAMES*2];
dsp_run(delay->in, cache, n);
for (int i = 0; i < n*2; i++) {
cbuf_push(&delay->buf, cache[i] / 2);
buf[i] = cache[i] + cbuf_shift(&delay->buf);
}
}

View file

@ -1,18 +1,70 @@
#ifndef DSP_H
#define DSP_H
#define SAMPLERATE 48000
#define BUF_FRAMES 4096
#define CHANNELS 2
#define MUSIZE 2
#include "circbuf.h"
void am_mod(short *a, short *b, short *c, int n);
void dsp_rectify(short *in, short *out, int n);
struct dsp_filter {
void (*filter)(short *in, short *out, int samples, void *data);
void (*filter)(void *data, short *out, int samples);
void *data;
};
struct dsp_delay {
unsigned int ms_delay;
struct circbuf buf;
struct dsp_filter in;
};
struct dsp_delay dsp_delay_make(unsigned int ms_delay);
void dsp_delay_filbuf(struct dsp_delay *delay, short *buf, int n);
struct dsp_ammod {
struct dsp_filter ina;
struct dsp_filter inb;
short abuf[BUF_FRAMES*2];
short bbuf[BUF_FRAMES*2];
};
struct dsp_compressor {
};
struct dsp_limiter {
};
struct dsp_hpf {
};
struct dsp_lpf {
};
struct phasor {
unsigned int sr;
float cur;
float freq;
unsigned int clen;
unsigned int cstep;
float *cache;
};
struct phasor phasor_make(unsigned int sr, float freq);
struct osc {
float (*f)(float p);
struct phasor p;
unsigned int frames;
unsigned int frame;
short *cache;
};
struct wav;
@ -22,4 +74,14 @@ struct wav gen_square(float amp, float freq, int sr, int ch);
struct wav gen_triangle(float amp, float freq, int sr, int ch);
struct wav gen_saw(float amp, float freq, int sr, int ch);
float sin_phasor(float p);
float square_phasor(float p);
float saw_phasor(float p);
float tri_phasor(float p);
void osc_fillbuf(struct osc *osc, short *buf, int n);
void am_mod(struct dsp_ammod *mod, short *c, int n);
#endif

View file

@ -1,42 +1,41 @@
#include "mix.h"
#include "stddef.h"
#include "time.h"
#include "sound.h"
static struct bus bus[256];
short mastermix[BUF_FRAMES*CHANNELS];
struct bus *first_free_bus() {
struct bus *first_free_bus(struct dsp_filter in) {
for (int i = 0; i < 256; i++) {
if (!bus[i].on) return &bus[i];
if (!bus[i].on) {
bus[i].on = 1;
bus[i].in = in;
return &bus[i];
}
}
return NULL;
}
void bus_fill_buffers() {
void bus_fill_buffers(short *master, int n) {
//clock_t sa = clock();
for (int i = 0; i < 256; i++) {
if (!bus[i].on) continue;
short *s = (short*)bus[i].sound->data->data;
for (int k = 0; k < BUF_FRAMES; k++) {
for (int j = 0; j < CHANNELS; j++) {
bus[i].buf[k*CHANNELS + j] = s[bus[i].sound->frame++];
if (bus[i].sound->frame == bus[i].sound->data->frames) {
bus[i].sound->frame = 0;
if (!bus[i].sound->loop) bus[i].on = 0;
}
}
}
if (bus[i].on != 1) continue;
dsp_run(bus[i].in, bus[i].buf, BUF_FRAMES);
}
//printf("DSP run took %f.\n", (double)(clock() - sa)/CLOCKS_PER_SEC);
for (int i = 0; i < BUF_FRAMES*CHANNELS; i++) {
mastermix[i] = 0;
//sa = clock();
memset(master, 0, BUF_FRAMES*CHANNELS*sizeof(short));
for (int j = 0; j < 256; j++) {
if (!bus[j].on) continue;
mastermix[i] += bus[j].buf[i];
for (int i = 0; i < BUF_FRAMES*CHANNELS; i++) {
master[i] += bus[j].buf[i];
}
}
}
//printf("Mix took %f.\n", (double)(clock() - sa)/CLOCKS_PER_SEC);
}

View file

@ -1,23 +1,21 @@
#ifndef MIX_H
#define MIX_H
#define BUF_FRAMES 4096
#define CHANNELS 2
#define MUSIZE 2
#include "dsp.h"
struct sound;
struct bus {
int on;
struct sound *sound;
struct dsp_filter in;
short buf[BUF_FRAMES*CHANNELS];
};
extern short mastermix[BUF_FRAMES*CHANNELS];
struct bus *first_free_bus();
void bus_fill_buffers();
struct bus *first_free_bus(struct dsp_filter in);
void bus_fill_buffers(short *master, int n);
#endif

View file

@ -11,7 +11,6 @@
#include "SDL2/SDL.h"
#include "mix.h"
#include "dsp.h"
#define TSF_IMPLEMENTATION
@ -75,21 +74,7 @@ static int patestCallback(const void *inputBuffer, void *outputBuffer, unsigned
/* Cast data passed through stream to our structure. */
short *out = (short*)outputBuffer;
bus_fill_buffers();
for (int i = 0; i < framesPerBuffer * 2; i++) {
out[i] = mastermix[i];
}
if (!vidplaying) return 0;
for (int i = 0; i < framesPerBuffer; i++) {
out[i*2] += cbuf_shift(&vidbuf) * 5;
out[i*2+1] += cbuf_shift(&vidbuf) * 5;
}
bus_fill_buffers(outputBuffer, framesPerBuffer);
return 0;
}
@ -118,6 +103,13 @@ void normalize_gain(struct wav *w, double lv)
w->gain = log10((float)tarmax/max) * 20;
}
struct osc sin600;
struct osc sin20;
struct dsp_ammod dspammod;
struct dsp_delay dspdel;
struct wav s600wav;
struct sound s600wavsound;
void sound_init()
{
vidbuf = circbuf_init(sizeof(short), 262144);
@ -139,13 +131,54 @@ void sound_init()
//play_sound(&wavsound);
sin440 = gen_sine(0.4f, 30, 48000, 2);
sin440 = gen_sine(0.4f, 30, SAMPLERATE, 2);
a440.data = &sin440;
a440.loop = 1;
play_sound(&a440);
//play_sound(&a440);
printf("Playing wav with %i frames.\n", wavsound.data->frames);
sin600.f = tri_phasor;
sin600.p = phasor_make(SAMPLERATE, 200);
sin20.f = square_phasor;
sin20.p.sr = SAMPLERATE;
sin20.p.freq = 4;
s600wav = gen_sine(0.6f, 600, SAMPLERATE, CHANNELS);
s600wavsound.loop = -1;
s600wavsound.data = &s600wav;
struct dsp_filter s600;
s600.data = &s600wavsound;
s600.filter = sound_fillbuf;
struct dsp_filter s20;
s20.data = &sin20;
s20.filter = osc_fillbuf;
struct dsp_filter am_filter;
dspammod.ina = s600;
dspammod.inb = s20;
am_filter.filter = am_mod;
am_filter.data = &dspammod;
dspdel = dsp_delay_make(150);
dspdel.in = am_filter;
struct dsp_filter del_filter;
del_filter.filter = dsp_delay_filbuf;
del_filter.data = &dspdel;
//first_free_bus(s600);
first_free_bus(del_filter);
/*
if (!drmp3_init_file(&mp3, "sounds/circus.mp3", NULL)) {
YughError("Could not open mp3.",0);
@ -154,7 +187,7 @@ void sound_init()
printf("CIrcus mp3 channels: %ui, samplerate: %ui\n", mp3.channels, mp3.sampleRate);
*/
PaError err = Pa_Initialize();
PaError err = Pa_Initialize();
check_pa_err(err);
int numDevices = Pa_GetDeviceCount();
@ -178,7 +211,7 @@ void sound_init()
*/
//err = Pa_OpenStream(&stream_def, NULL, &outparams, 48000, 4096, paNoFlag, patestCallback, &data);
err = Pa_OpenDefaultStream(&stream_def, 0, 2, paInt16, 48000, 4096, patestCallback, NULL);
err = Pa_OpenDefaultStream(&stream_def, 0, 2, paInt16, SAMPLERATE, BUF_FRAMES, patestCallback, NULL);
check_pa_err(err);
err = Pa_StartStream(stream_def);
@ -221,13 +254,6 @@ struct sound *make_music(const char *ogg)
}
void play_sound(struct sound *sound)
{
struct bus *b = first_free_bus();
b->sound = sound;
b->on = 1;
sound->frame = 0;
}
void play_music(struct sound *music)
{
@ -282,45 +308,22 @@ void audio_init()
//audioDriver = SDL_GetAudioDeviceName(0,0);
}
void play_raw(int device, void *data, int size)
{
float *d = data;
short t;
for (int i = 0; i < size; i++) {
t = (short)(d[i]*32767);
cbuf_push(&vidbuf, t);
}
vidplaying = 1;
/*
for (int i = 0; i < size; i++) {
short temp = (short)(d[i] * 32767);
cbuf_append(&vidbuf, &temp, 1);
}
*/
}
void close_audio_device(int device)
{
//SDL_CloseAudioDevice(device);
}
void clear_raw(int device)
{
//SDL_ClearQueuedAudio(device);
}
int open_device(const char *adriver)
{
/*
SDL_AudioSpec audio_spec;
SDL_memset(&audio_spec, 0, sizeof(audio_spec));
audio_spec.freq = 48000;
audio_spec.freq = SAMPLERATE;
audio_spec.format = AUDIO_F32;
audio_spec.channels = 2;
audio_spec.samples = 4096;
audio_spec.samples = BUF_FRAMES;
int dev = (int) SDL_OpenAudioDevice(adriver, 0, &audio_spec, NULL, 0);
SDL_PauseAudioDevice(dev, 0);
@ -328,3 +331,43 @@ int open_device(const char *adriver)
*/
return 0;
}
void play_sound(struct sound *sound)
{
sound->frame = 0;
//struct bus *b = first_free_bus(sound, sound_fillbuf);
}
void sound_fillbuf(struct sound *s, short *buf, int n)
{
short *in = s->data->data;
for (int i = 0; i < n; i++) {
for (int j = 0; j < 2; j++) {
buf[i*2+j] = in[s->frame+j];
}
s->frame++;
if (s->frame == s->data->frames) {
s->frame = 0;
if (s->loop > 0) {
s->loop--;
}
}
}
}
struct soundstream soundstream_make()
{
struct soundstream new;
new.buf = circbuf_init(sizeof(short), BUF_FRAMES*CHANNELS*2);
return new;
}
void soundstream_fillbuf(struct soundstream *s, short *buf, int n)
{
int max = s->buf.write - s->buf.read;
for (int i = 0; i < n*CHANNELS; i++) {
buf[i] = (i < max) ? cbuf_shift(&s->buf) : 0;
}
}

View file

@ -1,6 +1,8 @@
#ifndef SOUND_H
#define SOUND_H
#include "circbuf.h"
struct Mix_Chunk {
int i;
};
@ -15,6 +17,12 @@ enum MUS {
MUS_PAUSE
};
struct soundstream {
struct circbuf buf;
};
struct soundstream soundstream_make();
struct sound {
int loop;
int frame;
@ -36,6 +44,8 @@ void sound_init();
void audio_open(const char *device);
void audio_close();
void sound_fillbuf(struct sound *s, short *buf, int n);
struct sound *make_sound(const char *wav);
struct sound *make_music(const char *ogg);
@ -52,9 +62,9 @@ void music_resume();
void music_pause();
void music_stop();
void soundstream_fillbuf(struct soundstream *stream, short *buf, int n);
void close_audio_device(int device);
void clear_raw(int device);
void play_raw(int device, void *data, int size);
int open_device(const char *adriver);
void audio_init();