mirror of
https://github.com/vgmstream/vgmstream.git
synced 2024-11-28 00:20:47 +01:00
cleanup: float stuff
This commit is contained in:
parent
045e1c9107
commit
1d86c2d03e
@ -1,4 +1,5 @@
|
||||
#include "api_internal.h"
|
||||
#include "mixing.h"
|
||||
#if LIBVGMSTREAM_ENABLE
|
||||
|
||||
#define INTERNAL_BUF_SAMPLES 1024
|
||||
@ -81,4 +82,27 @@ void libvgmstream_priv_reset(libvgmstream_priv_t* priv, bool reset_buf) {
|
||||
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
|
||||
|
@ -1,4 +1,6 @@
|
||||
#include "api_internal.h"
|
||||
#include "sbuf.h"
|
||||
#include "mixing.h"
|
||||
#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);
|
||||
}
|
||||
|
||||
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*/);
|
||||
}
|
||||
|
||||
@ -59,27 +66,10 @@ static void update_position(libvgmstream_priv_t* priv) {
|
||||
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) {
|
||||
libvgmstream_format_t* fmt = &priv->fmt;
|
||||
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_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);
|
||||
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->loop_start = v->loop_start_sample;
|
||||
fmt->loop_end = v->loop_end_sample;
|
||||
|
@ -1,4 +1,6 @@
|
||||
#include "api_internal.h"
|
||||
#include "mixing.h"
|
||||
|
||||
#if LIBVGMSTREAM_ENABLE
|
||||
|
||||
|
||||
@ -11,25 +13,28 @@ static bool reset_buf(libvgmstream_priv_t* priv) {
|
||||
if (priv->buf.initialized)
|
||||
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
|
||||
|
||||
// ???
|
||||
if (priv->buf.input_channels <= 0)
|
||||
priv->buf.input_channels = priv->vgmstream->channels;
|
||||
if (priv->buf.output_channels <= 0)
|
||||
priv->buf.output_channels = priv->vgmstream->channels;
|
||||
int min_channels = input_channels;
|
||||
if (min_channels < output_channels)
|
||||
min_channels = output_channels;
|
||||
|
||||
// should be as big as output
|
||||
if (priv->buf.input_channels < priv->buf.output_channels)
|
||||
priv->buf.input_channels = priv->buf.output_channels;
|
||||
sfmt_t input_sfmt = mixing_get_input_sample_type(priv->vgmstream);
|
||||
sfmt_t output_sfmt = mixing_get_output_sample_type(priv->vgmstream);
|
||||
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.sample_size = output_sample_size;
|
||||
priv->buf.channels = output_channels;
|
||||
|
||||
int max_sample_size = sizeof(sample_t);
|
||||
//int max_sample_size = sizeof(float);
|
||||
int max_bytes = priv->buf.max_samples * max_sample_size * priv->buf.input_channels;
|
||||
int max_bytes = priv->buf.max_samples * min_sample_size * min_channels;
|
||||
priv->buf.data = malloc(max_bytes);
|
||||
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) {
|
||||
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
|
||||
|
||||
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;
|
||||
if (copy_samples > buf_samples)
|
||||
copy_samples = buf_samples;
|
||||
int copy_bytes = priv->buf.sample_size * priv->buf.output_channels * copy_samples;
|
||||
int skip_bytes = priv->buf.sample_size * priv->buf.output_channels * priv->buf.consumed;
|
||||
int copy_bytes = priv->buf.sample_size * priv->buf.channels * copy_samples;
|
||||
int skip_bytes = priv->buf.sample_size * priv->buf.channels * priv->buf.consumed;
|
||||
|
||||
memcpy(buf, ((uint8_t*)priv->buf.data) + skip_bytes, copy_bytes);
|
||||
priv->buf.consumed += copy_samples;
|
||||
|
@ -22,10 +22,9 @@ typedef struct {
|
||||
bool initialized;
|
||||
void* data;
|
||||
|
||||
/* config */
|
||||
int input_channels;
|
||||
int output_channels;
|
||||
/* config (output values channels/size after mixing, though buf may be as big as input size) */
|
||||
int max_samples;
|
||||
int channels; /* */
|
||||
int sample_size;
|
||||
|
||||
/* state */
|
||||
@ -58,6 +57,8 @@ typedef struct {
|
||||
|
||||
|
||||
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);
|
||||
|
||||
|
@ -62,17 +62,23 @@ void mixer_update_channel(mixer_t* mixer) {
|
||||
|
||||
bool mixer_is_active(mixer_t* mixer) {
|
||||
/* no support or not need to apply */
|
||||
if (!mixer || !mixer->active || mixer->chain_count == 0)
|
||||
if (!mixer || !mixer->active)
|
||||
return false;
|
||||
|
||||
if (mixer->chain_count > 0)
|
||||
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) {
|
||||
|
||||
/* no support or not need to apply */
|
||||
if (!mixer || !mixer->active || mixer->chain_count == 0)
|
||||
return;
|
||||
/* external */
|
||||
//if (!mixer_is_active(mixer))
|
||||
// return;
|
||||
|
||||
/* 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) */
|
||||
@ -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)
|
||||
sbuf->channels = mixer->output_channels; // new channels
|
||||
//if (force_float) sbuf->fmt = SFMT_FLT; // new format
|
||||
//if (force_pcm16) sbuf->fmt = SFMT_PCM16; // new format
|
||||
sbuf->channels = mixer->output_channels;
|
||||
if (mixer->force_type) {
|
||||
sbuf->fmt = mixer->force_type;
|
||||
}
|
||||
|
||||
sbuf_copy_from_f32(sbuf, mixer->mixbuf);
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
#define _MIXER_PRIV_H_
|
||||
#include "../streamtypes.h"
|
||||
#include "mixer.h"
|
||||
#include "sbuf.h"
|
||||
|
||||
#define VGMSTREAM_MAX_MIXING 512
|
||||
|
||||
@ -52,6 +53,7 @@ struct mixer_t {
|
||||
int current_channels; /* state: channels may increase/decrease during ops */
|
||||
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);
|
||||
|
@ -58,11 +58,6 @@ void mix_vgmstream(sbuf_t* sbuf, VGMSTREAM* vgmstream) {
|
||||
if (!mixer_is_active(vgmstream->mixer))
|
||||
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);
|
||||
|
||||
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;
|
||||
int input_channels, output_channels;
|
||||
|
||||
if (!mixer)
|
||||
goto fail;
|
||||
if (!mixer) {
|
||||
if (p_input_channels) *p_input_channels = vgmstream->channels;
|
||||
if (p_output_channels) *p_output_channels = vgmstream->channels;
|
||||
return;
|
||||
}
|
||||
|
||||
output_channels = mixer->output_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_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;
|
||||
fail:
|
||||
if (p_input_channels) *p_input_channels = vgmstream->channels;
|
||||
if (p_output_channels) *p_output_channels = vgmstream->channels;
|
||||
return;
|
||||
}
|
||||
|
||||
sfmt_t mixing_get_input_sample_type(VGMSTREAM* vgmstream) {
|
||||
// TODO: check vgmstream
|
||||
return SFMT_S16;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
#define _MIXING_H_
|
||||
|
||||
#include "../vgmstream.h"
|
||||
#include "../util/log.h"
|
||||
#include "../util/log.h" //TODO remove
|
||||
#include "sbuf.h"
|
||||
|
||||
/* Applies mixing commands to the sample buffer. Mixing must be externally enabled and
|
||||
@ -15,7 +15,10 @@ void mix_vgmstream(sbuf_t* sbuf, VGMSTREAM* vgmstream);
|
||||
void mixing_setup(VGMSTREAM* vgmstream, int32_t max_sample_count);
|
||||
|
||||
/* 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 */
|
||||
void mixing_push_swap(VGMSTREAM* vgmstream, int ch_dst, int ch_src);
|
||||
@ -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_crosslayer(VGMSTREAM* vgmstream, int max, char mode);
|
||||
void mixing_macro_downmix(VGMSTREAM* vgmstream, int max /*, mapping_t output_mapping*/);
|
||||
void mixing_macro_output_sample_format(VGMSTREAM* vgmstream, sfmt_t type);
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -1,10 +1,10 @@
|
||||
#include <math.h>
|
||||
#include <limits.h>
|
||||
#include "../vgmstream.h"
|
||||
#include "../util/channel_mappings.h"
|
||||
#include "../layout/layout.h"
|
||||
#include "mixing.h"
|
||||
#include "mixer_priv.h"
|
||||
#include <math.h>
|
||||
#include <limits.h>
|
||||
|
||||
|
||||
#define MIX_MACRO_VOCALS 'v'
|
||||
@ -471,7 +471,7 @@ typedef enum {
|
||||
|
||||
void mixing_macro_downmix(VGMSTREAM* vgmstream, int max /*, mapping_t output_mapping*/) {
|
||||
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;
|
||||
const double vol_max = 1.0;
|
||||
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 */
|
||||
output_channels = mixer->output_channels;
|
||||
for (ch = 0; ch < max; ch++) {
|
||||
for (int ch = 0; ch < max; ch++) {
|
||||
mixing_push_upmix(vgmstream, 0);
|
||||
}
|
||||
|
||||
@ -542,13 +542,13 @@ void mixing_macro_downmix(VGMSTREAM* vgmstream, int max /*, mapping_t output_map
|
||||
ch_in = 0;
|
||||
for (mp_in = 0; mp_in < 16; mp_in++) {
|
||||
/* read input mapping (ex. 5.1) and find channel */
|
||||
if (!(input_mapping & (1<<mp_in)))
|
||||
if (!(input_mapping & (1 << mp_in)))
|
||||
continue;
|
||||
|
||||
ch_out = 0;
|
||||
for (mp_out = 0; mp_out < 16; mp_out++) {
|
||||
/* read output mapping (ex. 2.0) and find channel */
|
||||
if (!(output_mapping & (1<<mp_out)))
|
||||
if (!(output_mapping & (1 << mp_out)))
|
||||
continue;
|
||||
mixing_push_add(vgmstream, ch_out, max + ch_in, matrix[mp_in][mp_out]);
|
||||
|
||||
@ -565,3 +565,16 @@ void mixing_macro_downmix(VGMSTREAM* vgmstream, int max /*, mapping_t output_map
|
||||
/* remove unneeded channels */
|
||||
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;
|
||||
}
|
||||
|
@ -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) {
|
||||
case SFMT_F32:
|
||||
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) {
|
||||
int sample_size = get_sample_size(sbuf->fmt);
|
||||
int sample_size = sfmt_get_sample_size(sbuf->fmt);
|
||||
|
||||
uint8_t* buf = sbuf->buf;
|
||||
buf += sbuf->filled * sbuf->channels * sample_size;
|
||||
return buf;
|
||||
}
|
||||
#endif
|
||||
|
||||
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)
|
||||
return;
|
||||
if (count > sbuf->samples || count > sbuf->filled) //TODO?
|
||||
@ -87,10 +89,14 @@ static inline int double_to_int(double val) {
|
||||
#elif defined(_MSC_VER)
|
||||
return (int)val;
|
||||
#else
|
||||
return lrintf(val);
|
||||
return lrint(val);
|
||||
#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: maybe use macro-style templating (but kinda ugly)
|
||||
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) {
|
||||
int sample_size = get_sample_size(sbuf->fmt);
|
||||
int sample_size = sfmt_get_sample_size(sbuf->fmt);
|
||||
|
||||
uint8_t* buf = sbuf->buf;
|
||||
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++;
|
||||
|
||||
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++;
|
||||
}
|
||||
}
|
||||
|
@ -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_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);
|
||||
|
||||
|
@ -188,6 +188,7 @@ typedef struct {
|
||||
// ** this type of downmixing is very simplistic and not recommended
|
||||
|
||||
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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user