cleanup: sample stuff

This commit is contained in:
bnnm 2024-08-24 23:58:37 +02:00
parent 8917fde7ac
commit aec9e9a723
12 changed files with 119 additions and 75 deletions

View File

@ -837,7 +837,7 @@ void decode_vgmstream(VGMSTREAM* vgmstream, int samples_filled, int samples_to_d
switch (vgmstream->coding_type) {
case coding_SILENCE:
sbuf_silence(buffer, samples_to_do, vgmstream->channels, 0);
sbuf_silence_s16(buffer, samples_to_do, vgmstream->channels, 0);
break;
case coding_CRI_ADX:

View File

@ -68,8 +68,7 @@ bool mixer_is_active(mixer_t* mixer) {
return true;
}
void mixer_process(mixer_t* mixer, sample_t* outbuf, int32_t sample_count, int32_t current_pos) {
void mixer_process(mixer_t* mixer, sbuf_t* sbuf, int32_t current_pos) {
/* no support or not need to apply */
if (!mixer || !mixer->active || mixer->chain_count == 0)
@ -80,7 +79,7 @@ void mixer_process(mixer_t* mixer, sample_t* outbuf, int32_t sample_count, int32
mixer->current_subpos = 0;
if (mixer->has_fade) {
//;VGM_LOG("MIX: fade test %i, %i\n", data->has_non_fade, mixer_op_fade_is_active(data, current_pos, current_pos + sample_count));
if (!mixer->has_non_fade && !mixer_op_fade_is_active(mixer, current_pos, current_pos + sample_count))
if (!mixer->has_non_fade && !mixer_op_fade_is_active(mixer, current_pos, current_pos + sbuf->filled))
return;
//;VGM_LOG("MIX: fade pos=%i\n", current_pos);
@ -88,31 +87,33 @@ void mixer_process(mixer_t* mixer, sample_t* outbuf, int32_t sample_count, int32
}
// upgrade buf for mixing (somehow using float buf rather than int32 is faster?)
sbuf_copy_s16_to_f32(mixer->mixbuf, outbuf, sample_count, mixer->input_channels);
sbuf_copy_to_f32(mixer->mixbuf, sbuf);
//sbuf_copy_s16_to_f32(mixer->mixbuf, outbuf, sample_count, mixer->input_channels);
/* apply mixing ops in order. Some ops change total channels they may change around:
* - 2ch w/ "1+2,1u" = ch1+ch2, ch1(add and push rest) = 3ch: ch1' ch1+ch2 ch2
* - 2ch w/ "1u" = downmix to 1ch (current_channels decreases once)
*/
// apply mixing ops in order. current_channels may increase or decrease per op
// - 2ch w/ "1+2,1u" = ch1+ch2, ch1(add and push rest) = 3ch: ch1' ch1+ch2 ch2
// - 2ch w/ "1u" = downmix to 1ch (current_channels decreases once)
mixer->current_channels = mixer->input_channels;
for (int m = 0; m < mixer->chain_count; m++) {
mix_op_t* mix = &mixer->chain[m];
//TODO: set callback
//TO-DO: set callback
switch(mix->type) {
case MIX_SWAP: mixer_op_swap(mixer, sample_count, mix); break;
case MIX_ADD: mixer_op_add(mixer, sample_count, mix); break;
case MIX_VOLUME: mixer_op_volume(mixer, sample_count, mix); break;
case MIX_LIMIT: mixer_op_limit(mixer, sample_count, mix); break;
case MIX_UPMIX: mixer_op_upmix(mixer, sample_count, mix); break;
case MIX_DOWNMIX: mixer_op_downmix(mixer, sample_count, mix); break;
case MIX_KILLMIX: mixer_op_killmix(mixer, sample_count, mix); break;
case MIX_FADE: mixer_op_fade(mixer, sample_count, mix);
case MIX_SWAP: mixer_op_swap(mixer, sbuf->filled, mix); break;
case MIX_ADD: mixer_op_add(mixer, sbuf->filled, mix); break;
case MIX_VOLUME: mixer_op_volume(mixer, sbuf->filled, mix); break;
case MIX_LIMIT: mixer_op_limit(mixer, sbuf->filled, mix); break;
case MIX_UPMIX: mixer_op_upmix(mixer, sbuf->filled, mix); break;
case MIX_DOWNMIX: mixer_op_downmix(mixer, sbuf->filled, mix); break;
case MIX_KILLMIX: mixer_op_killmix(mixer, sbuf->filled, mix); break;
case MIX_FADE: mixer_op_fade(mixer, sbuf->filled, mix);
default:
break;
}
}
/* downgrade mix to original output */
sbuf_copy_f32_to_s16(outbuf, mixer->mixbuf, sample_count, mixer->output_channels);
// downgrade mix to original output (with new channels)
sbuf->channels = mixer->output_channels;
sbuf_copy_from_f32(sbuf, mixer->mixbuf);
//sbuf_copy_f32_to_s16(outbuf, mixer->mixbuf, sbuf->filled, mixer->output_channels);
}

View File

@ -2,6 +2,7 @@
#define _MIXER_H_
#include "../streamtypes.h"
#include "sbuf.h"
typedef struct mixer_t mixer_t;
@ -10,7 +11,7 @@ typedef struct mixer_t mixer_t;
mixer_t* mixer_init(int channels);
void mixer_free(mixer_t* mixer);
void mixer_update_channel(mixer_t* mixer);
void mixer_process(mixer_t* mixer, sample_t *outbuf, int32_t sample_count, int32_t current_pos);
void mixer_process(mixer_t* mixer, sbuf_t* sbuf, int32_t current_pos);
bool mixer_is_active(mixer_t* mixer);
#endif

View File

@ -1,12 +1,12 @@
#include <math.h>
#include <limits.h>
#include "../vgmstream.h"
#include "../util/channel_mappings.h"
#include "../layout/layout.h"
#include "mixing.h"
#include "mixer.h"
#include "mixer_priv.h"
#include "sbuf.h"
#include "../layout/layout.h"
#include <math.h>
#include <limits.h>
//TODO simplify
/**
@ -58,9 +58,14 @@ void mix_vgmstream(sample_t *outbuf, int32_t sample_count, VGMSTREAM* vgmstream)
if (!mixer_is_active(vgmstream->mixer))
return;
int32_t current_pos = get_current_pos(vgmstream, sample_count);
sbuf_t sbuf_tmp;
sbuf_t* sbuf = &sbuf_tmp;
sbuf_init_s16(sbuf, outbuf, sample_count, vgmstream->channels);
sbuf->filled = sbuf->samples;
mixer_process(vgmstream->mixer, outbuf, sample_count, current_pos);
int32_t current_pos = get_current_pos(vgmstream, sbuf->filled);
mixer_process(vgmstream->mixer, sbuf, current_pos);
}
/* ******************************************************************* */

View File

@ -84,7 +84,7 @@ int render_layout(sample_t* buf, int32_t sample_count, VGMSTREAM* vgmstream) {
if (vgmstream->current_sample > vgmstream->num_samples) {
int channels = vgmstream->channels;
memset(buf, 0, sample_count * sizeof(sample_t) * channels);
sbuf_silence_s16(buf, sample_count, channels, 0);
return sample_count;
}
@ -156,7 +156,8 @@ int render_layout(sample_t* buf, int32_t sample_count, VGMSTREAM* vgmstream) {
excess = sample_count;
decoded = sample_count - excess;
memset(buf + decoded * channels, 0, excess * sizeof(sample_t) * channels);
sbuf_silence_s16(buf, sample_count, channels, decoded);
return sample_count;
}
@ -214,7 +215,8 @@ static void play_op_pad_begin(VGMSTREAM* vgmstream, render_helper_t* renderer) {
if (to_do > buf_samples)
to_do = buf_samples;
memset(renderer->tmpbuf, 0, to_do * sizeof(sample_t) * channels);
sbuf_silence_s16(renderer->tmpbuf, to_do, channels, 0);
ps->pad_begin_left -= to_do;
renderer->samples_done += to_do;
@ -258,8 +260,8 @@ static void play_op_fade(VGMSTREAM* vgmstream, sample_t* buf, int samples_done)
ps->fade_left -= to_do;
/* next samples after fade end would be pad end/silence, so we can just memset */
memset(buf + (start + to_do) * channels, 0, (samples_done - to_do - start) * sizeof(sample_t) * channels);
/* next samples after fade end would be pad end/silence */
sbuf_silence_s16(buf, samples_done, channels, (start + to_do));
}
// adds null samples after decode
@ -292,7 +294,7 @@ static int play_op_pad_end(VGMSTREAM* vgmstream, sample_t* buf, int samples_done
if (to_do > samples_done - skip)
to_do = samples_done - skip;
memset(buf + (skip * channels), 0, to_do * sizeof(sample_t) * channels);
sbuf_silence_s16(buf, to_do + skip, channels, skip);
return skip + to_do;
}
@ -354,6 +356,7 @@ int render_vgmstream(sample_t* buf, int32_t sample_count, VGMSTREAM* vgmstream)
/* main decode */
int done = render_layout(renderer.tmpbuf, renderer.samples_to_do, vgmstream);
mix_vgmstream(renderer.tmpbuf, done, vgmstream);

View File

@ -3,37 +3,74 @@
#include "../util.h"
#include "sbuf.h"
#if 0
/* skips N samples from current sbuf */
void sbuf_init16(sbuf_t* sbuf, int16_t* buf, int samples, int channels) {
void sbuf_init_s16(sbuf_t* sbuf, int16_t* buf, int samples, int channels) {
memset(sbuf, 0, sizeof(sbuf_t));
sbuf->buf = buf;
sbuf->samples = samples;
sbuf->channels = channels;
sbuf->fmt = SFMT_S16;
}
#endif
void sbuf_init_f32(sbuf_t* sbuf, float* buf, int samples, int channels) {
memset(sbuf, 0, sizeof(sbuf_t));
sbuf->buf = buf;
sbuf->samples = samples;
sbuf->channels = channels;
sbuf->fmt = SFMT_F32;
}
// TODO decide if using float 1.0 style or 32767 style (fuzzy PCM changes when doing that)
void sbuf_copy_s16_to_f32(float* buf_f32, int16_t* buf_s16, int samples, int channels) {
for (int s = 0; s < samples * channels; s++) {
buf_f32[s] = (float)buf_s16[s]; // / 32767.0f
//TODO decide if using float 1.0 style or 32767 style (fuzzy PCM when doing that)
//TODO: maybe use macro-style templating (but kinda ugly)
void sbuf_copy_to_f32(float* dst, sbuf_t* sbuf) {
switch(sbuf->fmt) {
case SFMT_S16: {
int16_t* buf = sbuf->buf;
for (int s = 0; s < sbuf->filled * sbuf->channels; s++) {
dst[s] = (float)buf[s]; // / 32767.0f
}
break;
}
case SFMT_F32: {
float* buf = sbuf->buf;
for (int s = 0; s < sbuf->filled * sbuf->channels; s++) {
dst[s] = buf[s];
}
break;
}
default:
break;
}
}
void sbuf_copy_f32_to_s16(int16_t* buf_s16, float* buf_f32, int samples, int channels) {
/* when casting float to int, value is simply truncated:
* - (int)1.7 = 1, (int)-1.7 = -1
* alts for more accurate rounding could be:
* - (int)floor(f)
* - (int)(f < 0 ? f - 0.5f : f + 0.5f)
* - (((int) (f1 + 32768.5)) - 32768)
* - etc
* but since +-1 isn't really audible we'll just cast, as it's the fastest
*/
for (int s = 0; s < samples * channels; s++) {
buf_s16[s] = clamp16( buf_f32[s]); // * 32767.0f
/* when casting float to int, value is simply truncated:
* - (int)1.7 = 1, (int)-1.7 = -1
* alts for more accurate rounding could be:
* - (int)floor(f)
* - (int)(f < 0 ? f - 0.5f : f + 0.5f)
* - (((int) (f1 + 32768.5)) - 32768)
* - etc
* but since +-1 isn't really audible we'll just cast, as it's the fastest
*/
void sbuf_copy_from_f32(sbuf_t* sbuf, float* src) {
switch(sbuf->fmt) {
case SFMT_S16: {
int16_t* buf = sbuf->buf;
for (int s = 0; s < sbuf->filled * sbuf->channels; s++) {
buf[s] = clamp16( src[s]); // * 32767.0f
}
break;
}
case SFMT_F32: {
float* buf = sbuf->buf;
for (int s = 0; s < sbuf->filled * sbuf->channels; s++) {
buf[s] = src[s];
}
break;
}
default:
break;
}
}
@ -72,7 +109,7 @@ void sbuf_copy_layers(sample_t* dst, int dst_channels, sample_t* src, int src_ch
}
}
void sbuf_silence(sample_t* dst, int samples, int channels, int filled) {
void sbuf_silence_s16(sample_t* dst, int samples, int channels, int filled) {
memset(dst + filled * channels, 0, (samples - filled) * channels * sizeof(sample_t));
}

View File

@ -3,49 +3,46 @@
#include "../streamtypes.h"
#if 0
/* interleaved: buffer for all channels = [ch*s] = (ch1 ch2 ch1 ch2 ch1 ch2 ch1 ch2 ...) */
/* planar: buffer per channel = [ch][s] = (c1 c1 c1 c1 ...) (c2 c2 c2 c2 ...) */
typedef enum {
SFMT_NONE,
SFMT_S16,
SFMT_F32,
//SFMT_S24,
//SFMT_S32,
//SFMT_S16P,
//SFMT_F32P,
SFMT_F32,
} sfmt_t;
typedef struct {
void* buf; /* current sample buffer */
int samples; /* max samples */
int channels; /* interleaved step or planar buffers */
sfmt_t fmt; /* buffer type */
//int filled; /* samples in buffer */
int channels; /* interleaved step or planar buffers */
int samples; /* max samples */
int filled; /* samples in buffer */
//int planar;
} sbuf_t;
void sbuf_init16(sbuf_t* sbuf, int16_t* buf, int samples, int channels);
void sbuf_init_s16(sbuf_t* sbuf, int16_t* buf, int samples, int channels);
void sbuf_clamp(sbuf_t* sbuf, int samples);
void sbuf_init_f32(sbuf_t* sbuf, float* buf, int samples, int channels);
/* skips N samples from current sbuf */
void sbuf_consume(sbuf_t* sbuf, int samples);
#endif
//void sbuf_clamp(sbuf_t* sbuf, int samples);
//void sbuf_consume(sbuf_t* sbuf, int samples);
/* it's probably slightly faster to make those inline'd, but aren't called that often to matter (given big enough total samples) */
// TODO decide if using float 1.0 style or 32767 style (fuzzy PCM changes when doing that)
void sbuf_copy_s16_to_f32(float* buf_f32, int16_t* buf_s16, int samples, int channels);
void sbuf_copy_to_f32(float* dst, sbuf_t* sbuf);
void sbuf_copy_f32_to_s16(int16_t* buf_s16, float* buf_f32, int samples, int channels);
void sbuf_copy_from_f32(sbuf_t* sbuf, float* src);
void sbuf_copy_samples(sample_t* dst, int dst_channels, sample_t* src, int src_channels, int samples_to_do, int samples_filled);
void sbuf_copy_layers(sample_t* dst, int dst_channels, sample_t* src, int src_channels, int samples_to_do, int samples_filled, int dst_ch_start);
void sbuf_silence(sample_t* dst, int samples, int channels, int filled);
void sbuf_silence_s16(sample_t* dst, int samples, int channels, int filled);
bool sbuf_realloc(sample_t** dst, int samples, int channels);

View File

@ -92,7 +92,7 @@ void render_vgmstream_blocked(sample_t* outbuf, int32_t sample_count, VGMSTREAM*
return;
decode_fail:
sbuf_silence(outbuf, sample_count, vgmstream->channels, samples_filled);
sbuf_silence_s16(outbuf, sample_count, vgmstream->channels, samples_filled);
}
/* helper functions to parse new block */

View File

@ -38,5 +38,5 @@ void render_vgmstream_flat(sample_t* outbuf, int32_t sample_count, VGMSTREAM* vg
return;
decode_fail:
sbuf_silence(outbuf, sample_count, vgmstream->channels, samples_filled);
sbuf_silence_s16(outbuf, sample_count, vgmstream->channels, samples_filled);
}

View File

@ -147,7 +147,7 @@ void render_vgmstream_interleave(sample_t* outbuf, int32_t sample_count, VGMSTRE
layout_config_t layout = {0};
if (!setup_helper(&layout, vgmstream)) {
VGM_LOG_ONCE("INTERLEAVE: wrong config found\n");
sbuf_silence(outbuf, sample_count, vgmstream->channels, 0);
sbuf_silence_s16(outbuf, sample_count, vgmstream->channels, 0);
return;
}
@ -193,5 +193,5 @@ void render_vgmstream_interleave(sample_t* outbuf, int32_t sample_count, VGMSTRE
return;
decode_fail:
sbuf_silence(outbuf, sample_count, vgmstream->channels, samples_filled);
sbuf_silence_s16(outbuf, sample_count, vgmstream->channels, samples_filled);
}

View File

@ -58,7 +58,7 @@ void render_vgmstream_layered(sample_t* outbuf, int32_t sample_count, VGMSTREAM*
return;
decode_fail:
sbuf_silence(outbuf, sample_count, data->output_channels, samples_filled);
sbuf_silence_s16(outbuf, sample_count, data->output_channels, samples_filled);
}

View File

@ -23,7 +23,7 @@ void render_vgmstream_segmented(sample_t* outbuf, int32_t sample_count, VGMSTREA
if (data->current_segment >= data->segment_count) {
VGM_LOG_ONCE("SEGMENT: wrong current segment\n");
sbuf_silence(outbuf, sample_count, data->output_channels, 0);
sbuf_silence_s16(outbuf, sample_count, data->output_channels, 0);
return;
}
@ -87,7 +87,7 @@ void render_vgmstream_segmented(sample_t* outbuf, int32_t sample_count, VGMSTREA
return;
decode_fail:
sbuf_silence(outbuf, sample_count, data->output_channels, samples_filled);
sbuf_silence_s16(outbuf, sample_count, data->output_channels, samples_filled);
}