Update mixing code

This commit is contained in:
bnnm 2019-02-25 00:38:35 +01:00
parent 05119fdceb
commit c99034cff8
3 changed files with 69 additions and 16 deletions

View File

@ -340,7 +340,7 @@ int main(int argc, char ** argv) {
char outfilename_temp[PATH_LIMIT];
sample_t * buf = NULL;
int channels;
int channels, input_channels;
int32_t len_samples;
int32_t fade_samples;
int i, j;
@ -458,8 +458,19 @@ int main(int argc, char ** argv) {
/* last init */
channels = vgmstream->channels;
input_channels = vgmstream->channels;
buf = malloc(BUFFER_SAMPLES * sizeof(sample_t) * channels);
#ifdef VGMSTREAM_MIXING
/* enable after all config but before outbuf */
{
vgmstream_enable_mixing(vgmstream, BUFFER_SAMPLES);
channels = vgmstream->output_channels;
input_channels = vgmstream->input_channels;
}
#endif
buf = malloc(BUFFER_SAMPLES * sizeof(sample_t) * input_channels);
if (!buf) {
fprintf(stderr,"failed allocating output buffer\n");
goto fail;

View File

@ -569,6 +569,16 @@ static VGMSTREAM * init_vgmstream_internal(STREAMFILE *streamFile) {
}
void setup_vgmstream(VGMSTREAM * vgmstream) {
#ifdef VGMSTREAM_MIXING
/* fill default config to simplify external code (mixing off will always happen
* initially, and if they contain values it means mixing must be enabled) */
if (!vgmstream->mixing_on || vgmstream->input_channels <= 0)
vgmstream->input_channels = vgmstream->channels;
if (!vgmstream->mixing_on || vgmstream->output_channels <= 0)
vgmstream->output_channels = vgmstream->channels;
#endif
/* save start things so we can restart when seeking */
memcpy(vgmstream->start_ch, vgmstream->ch, sizeof(VGMSTREAMCHANNEL)*vgmstream->channels);
memcpy(vgmstream->start_vgmstream, vgmstream, sizeof(VGMSTREAM));
@ -747,9 +757,9 @@ VGMSTREAM * allocate_vgmstream(int channel_count, int loop_flag) {
#ifdef VGMSTREAM_MIXING
/* fixed arrays, for now */
vgmstream->mixing_size = 64;
vgmstream->stream_name_size = STREAM_NAME_SIZE;
vgmstream->mixing_size = VGMSTREAM_MAX_MIXING;
#endif
//vgmstream->stream_name_size = STREAM_NAME_SIZE;
return vgmstream;
fail:
if (vgmstream) {
@ -980,6 +990,9 @@ void vgmstream_set_loop_target(VGMSTREAM* vgmstream, int loop_target) {
vgmstream_set_loop_target(data->layers[i], loop_target);
}
}
/* notify of new initial state */
setup_vgmstream(vgmstream);
}
@ -1042,7 +1055,7 @@ void render_vgmstream(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstre
break;
}
#ifndef VGMSTREAM_MIXING
/* swap channels if set, to create custom channel mappings */
if (vgmstream->channel_mappings_on) {
int ch_from,ch_to,s;
@ -1075,6 +1088,11 @@ void render_vgmstream(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstre
}
}
}
#endif
#ifdef VGMSTREAM_MIXING
mix_vgmstream(buffer, sample_count, vgmstream);
#endif
}
/* Get the number of samples of a single frame (smallest self-contained sample group, 1/N channels) */
@ -2529,7 +2547,7 @@ static void try_dual_file_stereo(VGMSTREAM * opened_vgmstream, STREAMFILE *strea
}
/* check these even if there is no loop, because they should then be zero in both
* Homura PS2 right channel doesn't have loop points so it's ignored */
* (Homura PS2 right channel doesn't have loop points so this check is ignored) */
if (new_vgmstream->meta_type != meta_PS2_SMPL &&
!(new_vgmstream->loop_flag == opened_vgmstream->loop_flag &&
new_vgmstream->loop_start_sample== opened_vgmstream->loop_start_sample &&

View File

@ -9,6 +9,9 @@
enum { PATH_LIMIT = 32768 };
enum { STREAM_NAME_SIZE = 255 };
enum { VGMSTREAM_MAX_CHANNELS = 64 };
#ifdef VGMSTREAM_MIXING
enum { VGMSTREAM_MAX_MIXING = 64 };
#endif
#include "streamfile.h"
@ -731,20 +734,28 @@ typedef enum {
MIX_ADD,
MIX_ADD_VOLUME,
MIX_VOLUME,
MIX_CROSSFADE,
MIX_LIMIT,
MIX_DOWNMIX,
MIX_DOWNMIX_REST,
MIX_UPMIX
MIX_UPMIX,
MIX_FADE
} mix_command_t;
typedef struct {
mix_command_t command;
int ch_a;
int ch_b;
float vol_a;
float vol_b;
float pos_a;
float pos_b;
/* common */
int ch_dst;
int ch_src;
float vol;
/* fade envelope */
float vol_start; /* volume from pre to start */
float vol_end; /* volume from end to post */
char shape; /* curve type */
float time_pre; /* position before curve where vol_str applies (-1 = beginning) */
float time_start; /* curve start position where vol changes from src to dst */
float time_end; /* curve end position where vol changes from src to dst */
float time_post; /* position after curve where vol_dst applies (-1 = end) */
} mix_config_data;
#endif
@ -823,15 +834,19 @@ typedef struct {
/* other config */
int allow_dual_stereo; /* search for dual stereo (file_L.ext + file_R.ext = single stereo file) */
#ifndef VGMSTREAM_MIXING
uint32_t channel_mask; /* to silence crossfading subsongs/layers */
int channel_mappings_on; /* channel mappings are active */
int channel_mappings[32]; /* swap channel "i" with "[i]" */
#endif
#ifdef VGMSTREAM_MIXING
int output_channels; /* resulting channels after mixing (may be ignored if plugin doesn't support it) */
/* may be ignored if plugin doesn't support it, but fields will be always set to simplify plugin's code */
int input_channels; /* starting channels before mixing (outbuf must be this big) */
int output_channels; /* resulting channels after mixing */
int mixing_on; /* mixing allowed */
int mixing_count; /* mixing number */
mix_config_data mixing[64]; /* applies transformation to output samples (could be alloc'ed but to simplify...) */
size_t mixing_size; /* mixing max */
mix_config_data mixing_chain[VGMSTREAM_MAX_MIXING]; /* effects to apply (could be alloc'ed but to simplify...) */
#endif
/* config requests, players must read and honor these values */
/* (ideally internally would work as a player, but for now player must do it manually) */
@ -1317,6 +1332,15 @@ VGMSTREAM * allocate_vgmstream(int channel_count, int looped);
/* Prepare the VGMSTREAM's initial state once parsed and ready, but before playing. */
void setup_vgmstream(VGMSTREAM * vgmstream);
#ifdef VGMSTREAM_MIXING
/* Applies mixing commands to the vgmstream to the sample buffer.
* Mixing must be enabled and outbuf must be big enough for output_channels*samples_to_do big. */
void mix_vgmstream(sample_t *outbuf, int32_t sample_count, VGMSTREAM* vgmstream);
/* Add a new internal mix. Always use this as it validates mixes. */
void vgmstream_add_mixing(VGMSTREAM* vgmstream, mix_config_data mix);
#endif
/* Get the number of samples of a single frame (smallest self-contained sample group, 1/N channels) */
int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream);
/* Get the number of bytes of a single frame (smallest self-contained byte group, 1/N channels) */