cleanup: float stuff

This commit is contained in:
bnnm 2024-08-27 02:12:41 +02:00
parent 045e1c9107
commit 1d86c2d03e
12 changed files with 146 additions and 76 deletions

View File

@ -1,4 +1,5 @@
#include "api_internal.h" #include "api_internal.h"
#include "mixing.h"
#if LIBVGMSTREAM_ENABLE #if LIBVGMSTREAM_ENABLE
#define INTERNAL_BUF_SAMPLES 1024 #define INTERNAL_BUF_SAMPLES 1024
@ -81,4 +82,27 @@ void libvgmstream_priv_reset(libvgmstream_priv_t* priv, bool reset_buf) {
priv->decode_done = false; priv->decode_done = false;
} }
libvgmstream_sample_t api_get_output_sample_type(libvgmstream_priv_t* priv) {
VGMSTREAM* v = priv->vgmstream;
sfmt_t format = mixing_get_output_sample_type(v);
switch(format) {
case SFMT_S16: return LIBVGMSTREAM_SAMPLE_PCM16;
case SFMT_FLT: return LIBVGMSTREAM_SAMPLE_FLOAT;
default:
return 0x00; //???
}
}
int api_get_sample_size(libvgmstream_sample_t sample_type) {
switch(sample_type) {
case LIBVGMSTREAM_SAMPLE_PCM24:
case LIBVGMSTREAM_SAMPLE_PCM32:
case LIBVGMSTREAM_SAMPLE_FLOAT:
return 0x04;
case LIBVGMSTREAM_SAMPLE_PCM16:
default:
return 0x02;
}
}
#endif #endif

View File

@ -1,4 +1,6 @@
#include "api_internal.h" #include "api_internal.h"
#include "sbuf.h"
#include "mixing.h"
#if LIBVGMSTREAM_ENABLE #if LIBVGMSTREAM_ENABLE
@ -47,6 +49,11 @@ static void prepare_mixing(libvgmstream_priv_t* priv, libvgmstream_options_t* op
vgmstream_mixing_stereo_only(priv->vgmstream, opt->stereo_track - 1); vgmstream_mixing_stereo_only(priv->vgmstream, opt->stereo_track - 1);
} }
if (priv->cfg.force_pcm16)
mixing_macro_output_sample_format(priv->vgmstream, SFMT_S16);
else if (priv->cfg.force_float)
mixing_macro_output_sample_format(priv->vgmstream, SFMT_FLT);
vgmstream_mixing_enable(priv->vgmstream, INTERNAL_BUF_SAMPLES, NULL /*&input_channels*/, NULL /*&output_channels*/); vgmstream_mixing_enable(priv->vgmstream, INTERNAL_BUF_SAMPLES, NULL /*&input_channels*/, NULL /*&output_channels*/);
} }
@ -59,27 +66,10 @@ static void update_position(libvgmstream_priv_t* priv) {
pos->current = 0; pos->current = 0;
} }
static int get_sample_size(libvgmstream_sample_t sample_type) {
switch(sample_type) {
case LIBVGMSTREAM_SAMPLE_PCM24:
case LIBVGMSTREAM_SAMPLE_PCM32:
case LIBVGMSTREAM_SAMPLE_FLOAT:
return 0x04;
case LIBVGMSTREAM_SAMPLE_PCM16:
default:
return 0x02;
}
}
static void update_format_info(libvgmstream_priv_t* priv) { static void update_format_info(libvgmstream_priv_t* priv) {
libvgmstream_format_t* fmt = &priv->fmt; libvgmstream_format_t* fmt = &priv->fmt;
VGMSTREAM* v = priv->vgmstream; VGMSTREAM* v = priv->vgmstream;
fmt->sample_type = LIBVGMSTREAM_SAMPLE_PCM16;
//fmt->sample_type = LIBVGMSTREAM_SAMPLE_FLOAT;
fmt->sample_size = get_sample_size(fmt->sample_type);
fmt->sample_rate = v->sample_rate;
fmt->subsong_index = v->stream_index; fmt->subsong_index = v->stream_index;
fmt->subsong_count = v->num_streams; fmt->subsong_count = v->num_streams;
@ -88,6 +78,11 @@ static void update_format_info(libvgmstream_priv_t* priv) {
vgmstream_mixing_enable(v, 0, &fmt->input_channels, &fmt->channels); vgmstream_mixing_enable(v, 0, &fmt->input_channels, &fmt->channels);
fmt->channel_layout = v->channel_layout; fmt->channel_layout = v->channel_layout;
fmt->sample_type = api_get_output_sample_type(priv);
fmt->sample_size = api_get_sample_size(fmt->sample_type);
fmt->sample_rate = v->sample_rate;
fmt->stream_samples = v->num_samples; fmt->stream_samples = v->num_samples;
fmt->loop_start = v->loop_start_sample; fmt->loop_start = v->loop_start_sample;
fmt->loop_end = v->loop_end_sample; fmt->loop_end = v->loop_end_sample;

View File

@ -1,4 +1,6 @@
#include "api_internal.h" #include "api_internal.h"
#include "mixing.h"
#if LIBVGMSTREAM_ENABLE #if LIBVGMSTREAM_ENABLE
@ -11,25 +13,28 @@ static bool reset_buf(libvgmstream_priv_t* priv) {
if (priv->buf.initialized) if (priv->buf.initialized)
return true; return true;
vgmstream_mixing_enable(priv->vgmstream, 0, &priv->buf.input_channels, &priv->buf.output_channels); //query // calc input/output values to reserve buf (should be as big as input or output)
int input_channels = 0, output_channels = 0;
vgmstream_mixing_enable(priv->vgmstream, 0, &input_channels, &output_channels); //query
// ??? int min_channels = input_channels;
if (priv->buf.input_channels <= 0) if (min_channels < output_channels)
priv->buf.input_channels = priv->vgmstream->channels; min_channels = output_channels;
if (priv->buf.output_channels <= 0)
priv->buf.output_channels = priv->vgmstream->channels;
// should be as big as output sfmt_t input_sfmt = mixing_get_input_sample_type(priv->vgmstream);
if (priv->buf.input_channels < priv->buf.output_channels) sfmt_t output_sfmt = mixing_get_output_sample_type(priv->vgmstream);
priv->buf.input_channels = priv->buf.output_channels; int input_sample_size = sfmt_get_sample_size(input_sfmt);
int output_sample_size = sfmt_get_sample_size(output_sfmt);
int min_sample_size = input_sample_size;
if (min_sample_size < output_sample_size)
min_sample_size = output_sample_size;
priv->buf.sample_size = sizeof(sample_t);
//priv->buf.sample_size = sizeof(float);
priv->buf.max_samples = INTERNAL_BUF_SAMPLES; priv->buf.max_samples = INTERNAL_BUF_SAMPLES;
priv->buf.sample_size = output_sample_size;
priv->buf.channels = output_channels;
int max_sample_size = sizeof(sample_t); int max_bytes = priv->buf.max_samples * min_sample_size * min_channels;
//int max_sample_size = sizeof(float);
int max_bytes = priv->buf.max_samples * max_sample_size * priv->buf.input_channels;
priv->buf.data = malloc(max_bytes); priv->buf.data = malloc(max_bytes);
if (!priv->buf.data) return false; if (!priv->buf.data) return false;
@ -39,7 +44,7 @@ static bool reset_buf(libvgmstream_priv_t* priv) {
static void update_buf(libvgmstream_priv_t* priv, int samples_done) { static void update_buf(libvgmstream_priv_t* priv, int samples_done) {
priv->buf.samples = samples_done; priv->buf.samples = samples_done;
priv->buf.bytes = samples_done * priv->buf.sample_size * priv->buf.output_channels; priv->buf.bytes = samples_done * priv->buf.sample_size * priv->buf.channels;
//priv->buf.consumed = 0; //external //priv->buf.consumed = 0; //external
if (!priv->pos.play_forever) { if (!priv->pos.play_forever) {
@ -99,8 +104,8 @@ LIBVGMSTREAM_API int libvgmstream_fill(libvgmstream_t* lib, void* buf, int buf_s
int copy_samples = priv->buf.samples; int copy_samples = priv->buf.samples;
if (copy_samples > buf_samples) if (copy_samples > buf_samples)
copy_samples = buf_samples; copy_samples = buf_samples;
int copy_bytes = priv->buf.sample_size * priv->buf.output_channels * copy_samples; int copy_bytes = priv->buf.sample_size * priv->buf.channels * copy_samples;
int skip_bytes = priv->buf.sample_size * priv->buf.output_channels * priv->buf.consumed; int skip_bytes = priv->buf.sample_size * priv->buf.channels * priv->buf.consumed;
memcpy(buf, ((uint8_t*)priv->buf.data) + skip_bytes, copy_bytes); memcpy(buf, ((uint8_t*)priv->buf.data) + skip_bytes, copy_bytes);
priv->buf.consumed += copy_samples; priv->buf.consumed += copy_samples;

View File

@ -22,10 +22,9 @@ typedef struct {
bool initialized; bool initialized;
void* data; void* data;
/* config */ /* config (output values channels/size after mixing, though buf may be as big as input size) */
int input_channels;
int output_channels;
int max_samples; int max_samples;
int channels; /* */
int sample_size; int sample_size;
/* state */ /* state */
@ -58,6 +57,8 @@ typedef struct {
void libvgmstream_priv_reset(libvgmstream_priv_t* priv, bool reset_buf); void libvgmstream_priv_reset(libvgmstream_priv_t* priv, bool reset_buf);
libvgmstream_sample_t api_get_output_sample_type(libvgmstream_priv_t* priv);
int api_get_sample_size(libvgmstream_sample_t sample_type);
STREAMFILE* open_api_streamfile(libstreamfile_t* libsf); STREAMFILE* open_api_streamfile(libstreamfile_t* libsf);

View File

@ -62,17 +62,23 @@ void mixer_update_channel(mixer_t* mixer) {
bool mixer_is_active(mixer_t* mixer) { bool mixer_is_active(mixer_t* mixer) {
/* no support or not need to apply */ /* no support or not need to apply */
if (!mixer || !mixer->active || mixer->chain_count == 0) if (!mixer || !mixer->active)
return false; return false;
if (mixer->chain_count > 0)
return true; return true;
if (mixer->force_type != SFMT_NONE)
return true;
return false;
} }
void mixer_process(mixer_t* mixer, sbuf_t* sbuf, int32_t current_pos) { void mixer_process(mixer_t* mixer, sbuf_t* sbuf, int32_t current_pos) {
/* no support or not need to apply */ /* external */
if (!mixer || !mixer->active || mixer->chain_count == 0) //if (!mixer_is_active(mixer))
return; // return;
/* try to skip if no fades apply (set but does nothing yet) + only has fades /* try to skip if no fades apply (set but does nothing yet) + only has fades
* (could be done in mix op but avoids upgrading bufs in some cases) */ * (could be done in mix op but avoids upgrading bufs in some cases) */
@ -112,8 +118,10 @@ void mixer_process(mixer_t* mixer, sbuf_t* sbuf, int32_t current_pos) {
} }
// setup + remix to output buf (buf is expected to be big enough to handle config) // setup + remix to output buf (buf is expected to be big enough to handle config)
sbuf->channels = mixer->output_channels; // new channels sbuf->channels = mixer->output_channels;
//if (force_float) sbuf->fmt = SFMT_FLT; // new format if (mixer->force_type) {
//if (force_pcm16) sbuf->fmt = SFMT_PCM16; // new format sbuf->fmt = mixer->force_type;
}
sbuf_copy_from_f32(sbuf, mixer->mixbuf); sbuf_copy_from_f32(sbuf, mixer->mixbuf);
} }

View File

@ -2,6 +2,7 @@
#define _MIXER_PRIV_H_ #define _MIXER_PRIV_H_
#include "../streamtypes.h" #include "../streamtypes.h"
#include "mixer.h" #include "mixer.h"
#include "sbuf.h"
#define VGMSTREAM_MAX_MIXING 512 #define VGMSTREAM_MAX_MIXING 512
@ -52,6 +53,7 @@ struct mixer_t {
int current_channels; /* state: channels may increase/decrease during ops */ int current_channels; /* state: channels may increase/decrease during ops */
int32_t current_subpos; /* state: current sample pos in the stream */ int32_t current_subpos; /* state: current sample pos in the stream */
sfmt_t force_type;
}; };
void mixer_op_swap(mixer_t* mixer, int32_t sample_count, mix_op_t* op); void mixer_op_swap(mixer_t* mixer, int32_t sample_count, mix_op_t* op);

View File

@ -58,11 +58,6 @@ void mix_vgmstream(sbuf_t* sbuf, VGMSTREAM* vgmstream) {
if (!mixer_is_active(vgmstream->mixer)) if (!mixer_is_active(vgmstream->mixer))
return; return;
//sbuf_t sbuf_tmp;
//sbuf_t* sbuf = &sbuf_tmp;
//sbuf_init_s16(sbuf, outbuf, sample_count, vgmstream->channels);
//sbuf->filled = sbuf->samples;
int32_t current_pos = get_current_pos(vgmstream, sbuf->filled); int32_t current_pos = get_current_pos(vgmstream, sbuf->filled);
mixer_process(vgmstream->mixer, sbuf, current_pos); mixer_process(vgmstream->mixer, sbuf, current_pos);
@ -153,8 +148,11 @@ void mixing_info(VGMSTREAM* vgmstream, int* p_input_channels, int* p_output_chan
mixer_t* mixer = vgmstream->mixer; mixer_t* mixer = vgmstream->mixer;
int input_channels, output_channels; int input_channels, output_channels;
if (!mixer) if (!mixer) {
goto fail; if (p_input_channels) *p_input_channels = vgmstream->channels;
if (p_output_channels) *p_output_channels = vgmstream->channels;
return;
}
output_channels = mixer->output_channels; output_channels = mixer->output_channels;
if (mixer->output_channels > vgmstream->channels) if (mixer->output_channels > vgmstream->channels)
@ -164,11 +162,22 @@ void mixing_info(VGMSTREAM* vgmstream, int* p_input_channels, int* p_output_chan
if (p_input_channels) *p_input_channels = input_channels; if (p_input_channels) *p_input_channels = input_channels;
if (p_output_channels) *p_output_channels = output_channels; if (p_output_channels) *p_output_channels = output_channels;
}
//;VGM_LOG("MIX: channels %i, in=%i, out=%i, mix=%i\n", vgmstream->channels, input_channels, output_channels, data->mixing_channels);
return; sfmt_t mixing_get_input_sample_type(VGMSTREAM* vgmstream) {
fail: // TODO: check vgmstream
if (p_input_channels) *p_input_channels = vgmstream->channels; return SFMT_S16;
if (p_output_channels) *p_output_channels = vgmstream->channels; }
return;
sfmt_t mixing_get_output_sample_type(VGMSTREAM* vgmstream) {
sfmt_t input_fmt = mixing_get_input_sample_type(vgmstream);
mixer_t* mixer = vgmstream->mixer;
if (!mixer)
return input_fmt;
if (mixer->force_type)
return mixer->force_type;
return input_fmt;
} }

View File

@ -2,7 +2,7 @@
#define _MIXING_H_ #define _MIXING_H_
#include "../vgmstream.h" #include "../vgmstream.h"
#include "../util/log.h" #include "../util/log.h" //TODO remove
#include "sbuf.h" #include "sbuf.h"
/* Applies mixing commands to the sample buffer. Mixing must be externally enabled and /* Applies mixing commands to the sample buffer. Mixing must be externally enabled and
@ -17,6 +17,9 @@ void mixing_setup(VGMSTREAM* vgmstream, int32_t max_sample_count);
/* gets current mixing info */ /* gets current mixing info */
void mixing_info(VGMSTREAM* vgmstream, int* input_channels, int* output_channels); void mixing_info(VGMSTREAM* vgmstream, int* input_channels, int* output_channels);
sfmt_t mixing_get_input_sample_type(VGMSTREAM* vgmstream);
sfmt_t mixing_get_output_sample_type(VGMSTREAM* vgmstream);
/* adds mixes filtering and optimizing if needed */ /* adds mixes filtering and optimizing if needed */
void mixing_push_swap(VGMSTREAM* vgmstream, int ch_dst, int ch_src); void mixing_push_swap(VGMSTREAM* vgmstream, int ch_dst, int ch_src);
void mixing_push_add(VGMSTREAM* vgmstream, int ch_dst, int ch_src, double volume); void mixing_push_add(VGMSTREAM* vgmstream, int ch_dst, int ch_src, double volume);
@ -33,6 +36,7 @@ void mixing_macro_layer(VGMSTREAM* vgmstream, int max, uint32_t mask, char mode)
void mixing_macro_crosstrack(VGMSTREAM* vgmstream, int max); void mixing_macro_crosstrack(VGMSTREAM* vgmstream, int max);
void mixing_macro_crosslayer(VGMSTREAM* vgmstream, int max, char mode); void mixing_macro_crosslayer(VGMSTREAM* vgmstream, int max, char mode);
void mixing_macro_downmix(VGMSTREAM* vgmstream, int max /*, mapping_t output_mapping*/); void mixing_macro_downmix(VGMSTREAM* vgmstream, int max /*, mapping_t output_mapping*/);
void mixing_macro_output_sample_format(VGMSTREAM* vgmstream, sfmt_t type);
#endif #endif

View File

@ -1,10 +1,10 @@
#include <math.h>
#include <limits.h>
#include "../vgmstream.h" #include "../vgmstream.h"
#include "../util/channel_mappings.h" #include "../util/channel_mappings.h"
#include "../layout/layout.h" #include "../layout/layout.h"
#include "mixing.h" #include "mixing.h"
#include "mixer_priv.h" #include "mixer_priv.h"
#include <math.h>
#include <limits.h>
#define MIX_MACRO_VOCALS 'v' #define MIX_MACRO_VOCALS 'v'
@ -471,7 +471,7 @@ typedef enum {
void mixing_macro_downmix(VGMSTREAM* vgmstream, int max /*, mapping_t output_mapping*/) { void mixing_macro_downmix(VGMSTREAM* vgmstream, int max /*, mapping_t output_mapping*/) {
mixer_t* mixer = vgmstream->mixer; mixer_t* mixer = vgmstream->mixer;
int ch, output_channels, mp_in, mp_out, ch_in, ch_out; int output_channels, mp_in, mp_out, ch_in, ch_out;
channel_mapping_t input_mapping, output_mapping; channel_mapping_t input_mapping, output_mapping;
const double vol_max = 1.0; const double vol_max = 1.0;
const double vol_sqrt = 1 / sqrt(2); const double vol_sqrt = 1 / sqrt(2);
@ -534,7 +534,7 @@ void mixing_macro_downmix(VGMSTREAM* vgmstream, int max /*, mapping_t output_map
/* save and make N fake channels at the beginning for easier calcs */ /* save and make N fake channels at the beginning for easier calcs */
output_channels = mixer->output_channels; output_channels = mixer->output_channels;
for (ch = 0; ch < max; ch++) { for (int ch = 0; ch < max; ch++) {
mixing_push_upmix(vgmstream, 0); mixing_push_upmix(vgmstream, 0);
} }
@ -565,3 +565,16 @@ void mixing_macro_downmix(VGMSTREAM* vgmstream, int max /*, mapping_t output_map
/* remove unneeded channels */ /* remove unneeded channels */
mixing_push_killmix(vgmstream, max); mixing_push_killmix(vgmstream, max);
} }
void mixing_macro_output_sample_format(VGMSTREAM* vgmstream, sfmt_t type) {
mixer_t* mixer = vgmstream->mixer;
if (!mixer)
return;
// optimization (may skip initializing mixer)
sfmt_t input_fmt = mixing_get_input_sample_type(vgmstream);
if (input_fmt == type)
return;
mixer->force_type = type;
}

View File

@ -22,7 +22,7 @@ void sbuf_init_f32(sbuf_t* sbuf, float* buf, int samples, int channels) {
} }
static int get_sample_size(sfmt_t fmt) { int sfmt_get_sample_size(sfmt_t fmt) {
switch(fmt) { switch(fmt) {
case SFMT_F32: case SFMT_F32:
case SFMT_FLT: case SFMT_FLT:
@ -34,16 +34,18 @@ static int get_sample_size(sfmt_t fmt) {
} }
} }
#if 0
void* sbuf_get_filled_buf(sbuf_t* sbuf) { void* sbuf_get_filled_buf(sbuf_t* sbuf) {
int sample_size = get_sample_size(sbuf->fmt); int sample_size = sfmt_get_sample_size(sbuf->fmt);
uint8_t* buf = sbuf->buf; uint8_t* buf = sbuf->buf;
buf += sbuf->filled * sbuf->channels * sample_size; buf += sbuf->filled * sbuf->channels * sample_size;
return buf; return buf;
} }
#endif
void sbuf_consume(sbuf_t* sbuf, int count) { void sbuf_consume(sbuf_t* sbuf, int count) {
int sample_size = get_sample_size(sbuf->fmt); int sample_size = sfmt_get_sample_size(sbuf->fmt);
if (sample_size <= 0) if (sample_size <= 0)
return; return;
if (count > sbuf->samples || count > sbuf->filled) //TODO? if (count > sbuf->samples || count > sbuf->filled) //TODO?
@ -87,10 +89,14 @@ static inline int double_to_int(double val) {
#elif defined(_MSC_VER) #elif defined(_MSC_VER)
return (int)val; return (int)val;
#else #else
return lrintf(val); return lrint(val);
#endif #endif
} }
static inline float double_to_float(double val) {
return (float)val;
}
//TODO decide if using float 1.0 style or 32767 style (fuzzy PCM when doing that) //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) //TODO: maybe use macro-style templating (but kinda ugly)
void sbuf_copy_to_f32(float* dst, sbuf_t* sbuf) { void sbuf_copy_to_f32(float* dst, sbuf_t* sbuf) {
@ -185,7 +191,7 @@ void sbuf_silence_s16(sample_t* dst, int samples, int channels, int filled) {
} }
void sbuf_silence_part(sbuf_t* sbuf, int from, int count) { void sbuf_silence_part(sbuf_t* sbuf, int from, int count) {
int sample_size = get_sample_size(sbuf->fmt); int sample_size = sfmt_get_sample_size(sbuf->fmt);
uint8_t* buf = sbuf->buf; uint8_t* buf = sbuf->buf;
buf += from * sbuf->channels * sample_size; buf += from * sbuf->channels * sample_size;
@ -235,7 +241,7 @@ void sbuf_fadeout(sbuf_t* sbuf, int start, int to_do, int fade_pos, int fade_dur
fade_pos++; fade_pos++;
for (int ch = 0; ch < sbuf->channels; ch++) { for (int ch = 0; ch < sbuf->channels; ch++) {
buf[s] = double_to_int(buf[s] * fadedness); buf[s] = double_to_float(buf[s] * fadedness);
s++; s++;
} }
} }

View File

@ -30,7 +30,9 @@ void sbuf_init_s16(sbuf_t* sbuf, int16_t* buf, int samples, int channels);
void sbuf_init_f32(sbuf_t* sbuf, float* buf, int samples, int channels); void sbuf_init_f32(sbuf_t* sbuf, float* buf, int samples, int channels);
void* sbuf_get_filled_buf(sbuf_t* sbuf); int sfmt_get_sample_size(sfmt_t fmt);
//void* sbuf_get_filled_buf(sbuf_t* sbuf);
//void sbuf_clamp(sbuf_t* sbuf, int samples); //void sbuf_clamp(sbuf_t* sbuf, int samples);

View File

@ -188,6 +188,7 @@ typedef struct {
// ** this type of downmixing is very simplistic and not recommended // ** this type of downmixing is very simplistic and not recommended
bool force_pcm16; // forces output buffer to be remixed into PCM16 bool force_pcm16; // forces output buffer to be remixed into PCM16
bool force_float; // forces output buffer to be remixed into float
} libvgmstream_config_t; } libvgmstream_config_t;