Bitcrusher

This commit is contained in:
John Alanbrook 2022-07-12 20:43:02 +00:00
parent 37d6b64bb9
commit 4896bc5e52
9 changed files with 6184 additions and 37 deletions

View file

@ -120,12 +120,12 @@ linkinclude = $(BIN)include
LINK = $(LIBPATH) $(LINKER_FLAGS) $(LELIBS) -o $@ LINK = $(LIBPATH) $(LINKER_FLAGS) $(LELIBS) -o $@
engine: $(yuginec:.%.c=$(objprefix)%.o) $(ENGINE) engine: tags $(yuginec:.%.c=$(objprefix)%.o) $(ENGINE)
@echo Linking engine @echo Linking engine
@$(CC) $@ $(LINK) @$(CC) $@ $(LINK)
@echo Finished build @echo Finished build
editor: $(yuginec:.%.c=$(objprefix)%.o) $(EDITOR) $(ENGINE) editor: tags $(yuginec:.%.c=$(objprefix)%.o) $(EDITOR) $(ENGINE)
@echo Linking editor @echo Linking editor
@$(CC) $^ $(LINK) @$(CC) $^ $(LINK)
@echo Finished build @echo Finished build
@ -145,7 +145,7 @@ xbrainstorm: $(bsobjects) $(ENGINE) $(EDITOR)
$(CC) $^ $(LINK) $(CC) $^ $(LINK)
@mv xbrainstorm brainstorm/brainstorm$(EXT) @mv xbrainstorm brainstorm/brainstorm$(EXT)
pinball: $(ENGINE) $(pinobjects) pinball: tags $(ENGINE) $(pinobjects)
@echo Making pinball @echo Making pinball
@$(CC) $(pinobjects) $(LINK) -o $@ @$(CC) $(pinobjects) $(LINK) -o $@
@mv pinball paladin/pinball @mv pinball paladin/pinball

View file

@ -494,14 +494,14 @@ void editor_project_gui()
NK_WINDOW_NO_SCROLLBAR)) NK_WINDOW_NO_SCROLLBAR))
{ {
nk_layout_row_dynamic(ctx, 25, 2); nk_layout_row_dynamic(ctx, 25, 2);
static struct sound *ss; static struct wav ss;
if (nk_button_label(ctx, "Load sound")) { if (nk_button_label(ctx, "Load sound")) {
ss = make_sound("alert.wav"); ss = make_sound("alert.wav");
} }
if (nk_button_label(ctx, "Play sound")) { if (nk_button_label(ctx, "Play sound")) {
play_sound(ss); play_sound(&ss);
} }
nk_layout_row_dynamic(ctx, 30, 2); nk_layout_row_dynamic(ctx, 30, 2);

View file

@ -130,6 +130,8 @@ struct wav gen_triangle(float amp, float freq, int sr, int ch)
data[i+j] = val; data[i+j] = val;
} }
} }
return new;
} }
struct wav gen_saw(float amp, float freq, int sr, int ch) struct wav gen_saw(float amp, float freq, int sr, int ch)
@ -149,11 +151,16 @@ struct wav gen_saw(float amp, float freq, int sr, int ch)
data[i+j] = val; data[i+j] = val;
} }
} }
return new;
} }
void make_dsp_filter() struct dsp_filter dsp_filter(void *data, void (*filter)(void *data, short *out, int samples))
{ {
struct dsp_filter new;
new.data = data;
data.filter = filter;
return new;
} }
void dsp_filter(short *in, short *out, int samples, struct dsp_delay *d) void dsp_filter(short *in, short *out, int samples, struct dsp_delay *d)
@ -600,10 +607,7 @@ void dsp_pan(float *deg, short *out, int n)
short L = out[i*CHANNELS]; short L = out[i*CHANNELS];
short R = out[i*CHANNELS +1]; short R = out[i*CHANNELS +1];
if (*deg > 0) { if (*deg > 0) {
out[i*CHANNELS] = short_gain(L, db1); out[i*CHANNELS] = short_gain(L, db1);
out[i*CHANNELS+1] = (R + short_gain(L, db2)) / 2; out[i*CHANNELS+1] = (R + short_gain(L, db2)) / 2;
@ -612,13 +616,7 @@ void dsp_pan(float *deg, short *out, int n)
out[i*CHANNELS+1] = short_gain(R, db1); out[i*CHANNELS+1] = short_gain(R, db1);
out[i*CHANNELS] = short_gain(L, db1) + short_gain(R, db2); out[i*CHANNELS] = short_gain(L, db1) + short_gain(R, db2);
} }
} }
void dsp_mono(void *p, short *out, int n) void dsp_mono(void *p, short *out, int n)
@ -630,3 +628,11 @@ void dsp_mono(void *p, short *out, int n)
out[i*CHANNELS+j] = val; out[i*CHANNELS+j] = val;
} }
} }
void dsp_bitcrush(void *p, short *out, int n)
{
for (int i = 0; i < n; i++) {
for (int j = 0; j < CHANNELS; j++)
out[i*CHANNELS+j] = (out[i*CHANNELS+j] | 0xFF); /* Mask out the lower 8 bits */
}
}

View file

@ -22,6 +22,8 @@ struct dsp_filter {
int dirty; int dirty;
}; };
struct dsp_filter dsp_filter(void *data, void (*filter)(void *data, short *out, int samples));
struct dsp_fir { struct dsp_fir {
float freq; float freq;
int n; int n;
@ -147,4 +149,6 @@ void dsp_pan(float *deg, short *out, int n);
void dsp_mono(void *p, short *out, int n); void dsp_mono(void *p, short *out, int n);
void dsp_bitcrush(void *p, short *out, int n);
#endif #endif

View file

@ -10,6 +10,7 @@ struct bus {
int on; int on;
struct dsp_filter in; struct dsp_filter in;
short buf[BUF_FRAMES*CHANNELS]; short buf[BUF_FRAMES*CHANNELS];
float gain;
}; };
struct listener { struct listener {
@ -22,6 +23,7 @@ extern short mastermix[BUF_FRAMES*CHANNELS];
struct bus *first_free_bus(struct dsp_filter in); struct bus *first_free_bus(struct dsp_filter in);
void bus_fill_buffers(short *master, int n); void bus_fill_buffers(short *master, int n);
void bus_free(struct bus *bus);
#endif #endif

View file

@ -31,8 +31,22 @@
const char *audioDriver; const char *audioDriver;
void new_samplerate(short *in, short *out, int n, int ch, int sr_in, int sr_out)
{
SDL_AudioStream *stream = SDL_NewAudioStream(AUDIO_S16, ch, sr_in, AUDIO_S16, ch, sr_out);
SDL_AudioStreamPut(stream, in, n * ch * sizeof(short));
SDL_AudioStreamGet(stream, out, n * ch * sizeof(short));
SDL_FreeAudioStream(stream);
}
struct wav change_samplerate(struct wav w, int rate) struct wav change_samplerate(struct wav w, int rate)
{ {
int samples = sizeof(short) * w.ch * w.frames;
short *new = malloc(samples);
new_samplerate(w.data, new,
SDL_AudioStream *stream = SDL_NewAudioStream(AUDIO_S16, w.ch, w.samplerate, AUDIO_S16, w.ch, rate); SDL_AudioStream *stream = SDL_NewAudioStream(AUDIO_S16, w.ch, w.samplerate, AUDIO_S16, w.ch, rate);
SDL_AudioStreamPut(stream, w.data, w.frames*w.ch*sizeof(short)); SDL_AudioStreamPut(stream, w.data, w.frames*w.ch*sizeof(short));
@ -70,7 +84,7 @@ void check_pa_err(PaError e)
static PaStream *stream_def; static PaStream *stream_def;
void normalize_gain(struct wav *w, double lv) void wav_norm_gain(struct wav *w, double lv)
{ {
short tarmax = db2short(lv); short tarmax = db2short(lv);
short max = 0; short max = 0;
@ -81,7 +95,13 @@ void normalize_gain(struct wav *w, double lv)
} }
} }
w->gain = log10((float)tarmax/max) * 20; float mult = (float)max / tarmax;
for (int i = 0; i < w->frames; i++) {
for (int j = 0; j < w->ch; j++) {
s[i*w->ch + j] *= mult;
}
}
} }
struct osc sin600; struct osc sin600;
@ -143,40 +163,70 @@ struct wav make_sound(const char *wav)
mwav = change_samplerate(mwav, 48000); mwav = change_samplerate(mwav, 48000);
} }
mwav.gain = 0; mwav.gain = 1.f;
normalize_gain(&mwav, -3);
return mwav; return mwav;
} }
struct sound play_sound(struct wav *wav) struct sound *play_sound(struct wav *wav)
{ {
struct sound new; struct sound *new = calloc(1, sizeof(*new));
new.loop = 0;
new.frame = 0;
new.gain = 0;
new.data = wav; new.data = wav;
// TODO: Make filter to send to mixer new->bus = first_free_bus(dsp_filter(new, sound_fillbuf));
new->playing = 1;
return new; return new;
} }
int sound_playing(const struct sound *s)
{
return s.playing;
}
int sound_paused(const struct sound *s)
{
return (!s.playing && s.frame < s.data->frames);
}
void sound_pause(struct sound *s)
{
s->playing = 0;
bus_free(s->bus);
}
void sound_resume(struct sound *s)
{
s->playing = 1;
s->bus = first_free_bus(dsp_filter(s, sound_fillbuf));
}
void sound_stop(struct sound *s)
{
s->playing = 0;
s->frame = 0;
bus_free(s->bus);
}
int sound_finished(struct sound *s)
{
return !s->playing && s->frame == s->data->frames;
}
int sound_stopped(struct sound *s)
{
return !s->playing && s->frame = 0;
}
struct music make_music(const char *mp3) struct music make_music(const char *mp3)
{ {
drmp3 new; drmp3 new;
if (!drmp3_init_file(&new, mp3, NULL)) { if (!drmp3_init_file(&new, mp3, NULL)) {
YughError("Could not open mp3 file %s.", mp3); YughError("Could not open mp3 file %s.", mp3);
} }
//printf("CIrcus mp3 channels: %ui, samplerate: %ui\n", mp3.channels, mp3.sampleRate);
} }
void audio_init() void audio_init()
{ {
//audioDriver = SDL_GetAudioDeviceName(0,0); //audioDriver = SDL_GetAudioDeviceName(0,0);
@ -208,21 +258,32 @@ int open_device(const char *adriver)
void sound_fillbuf(struct sound *s, short *buf, int n) void sound_fillbuf(struct sound *s, short *buf, int n)
{ {
float gainmult = pct2mult(s->data->gain);
short *in = s->data->data; short *in = s->data->data;
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
for (int j = 0; j < 2; j++) { for (int j = 0; j < 2; j++) {
buf[i*2+j] = in[s->frame+j]; buf[i*2+j] = in[s->frame+j] * gainmult;
} }
s->frame++; s->frame++;
if (s->frame == s->data->frames) { if (s->frame == s->data->frames) {
s->frame = 0;
if (s->loop > 0) { if (s->loop > 0) {
s->loop--; s->loop--;
s->frame = 0;
} else {
bus_free(s->bus);
} }
} }
} }
} }
void mp3_fillbuf(struct sound *s, short *buf, int n)
{
}
struct soundstream soundstream_make() struct soundstream soundstream_make()
{ {
struct soundstream new; struct soundstream new;
@ -260,3 +321,10 @@ float pct2db(float pct)
return 10*log2(pct); return 10*log2(pct);
} }
float pct2mult(float pct)
{
if (pct <= 0) return 0.f;
return pow(10, 0.5*log2(pct));
}

View file

@ -26,20 +26,28 @@ struct soundstream soundstream_make();
struct sound { struct sound {
int loop; int loop;
int frame; int frame;
int playing;
float gain; float gain;
struct wav *data; struct wav *data;
struct bus *bus;
}; };
struct wav { struct wav {
unsigned int ch; unsigned int ch;
unsigned int samplerate; unsigned int samplerate;
unsigned int frames; unsigned int frames;
float gain; float gain; /* In dB */
void *data; void *data;
}; };
struct soundstream {
SDL_AudioStream *srconv;
void *data;
};
struct music { struct music {
}; };
@ -53,9 +61,22 @@ void audio_close();
void sound_fillbuf(struct sound *s, short *buf, int n); void sound_fillbuf(struct sound *s, short *buf, int n);
struct wav make_sound(const char *wav); struct wav make_sound(const char *wav);
struct sound *make_music(const char *ogg); void wav_norm_gain(struct wav *w, double lv);
struct sound play_sound(struct wav *wav);
int sound_playing(struct sound *s);
int sound_paused(struct sound *s);
int sound_stopped(struct sound *s);
int sound_finished(struct sound *s);
void sound_pause(struct sound *s);
void sound_resume(struct sound *s);
void sound_stop(struct sound *s);
struct music make_music(const char *ogg);
void play_sound(struct wav wav);
const char *get_audio_driver(); const char *get_audio_driver();
@ -67,9 +88,11 @@ int open_device(const char *adriver);
float short2db(short val); float short2db(short val);
short db2short(float db); short db2short(float db);
float pct2db(float pct);
short short_gain(short val, float db); short short_gain(short val, float db);
float pct2db(float pct);
float pct2mult(float pct);
void audio_init(); void audio_init();

3158
source/engine/tinyspline.c Normal file

File diff suppressed because it is too large Load diff

2886
source/engine/tinyspline.h Normal file

File diff suppressed because it is too large Load diff