mirror of
https://github.com/vgmstream/vgmstream.git
synced 2024-11-12 01:30:49 +01:00
cleanup: sample stuff
This commit is contained in:
parent
8917fde7ac
commit
aec9e9a723
@ -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:
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/* ******************************************************************* */
|
||||
|
@ -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);
|
||||
|
||||
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user