mirror of
https://github.com/vgmstream/vgmstream.git
synced 2025-02-25 22:38:11 +01:00
Update mixing code
This commit is contained in:
parent
05119fdceb
commit
c99034cff8
@ -340,7 +340,7 @@ int main(int argc, char ** argv) {
|
|||||||
char outfilename_temp[PATH_LIMIT];
|
char outfilename_temp[PATH_LIMIT];
|
||||||
|
|
||||||
sample_t * buf = NULL;
|
sample_t * buf = NULL;
|
||||||
int channels;
|
int channels, input_channels;
|
||||||
int32_t len_samples;
|
int32_t len_samples;
|
||||||
int32_t fade_samples;
|
int32_t fade_samples;
|
||||||
int i, j;
|
int i, j;
|
||||||
@ -458,8 +458,19 @@ int main(int argc, char ** argv) {
|
|||||||
|
|
||||||
/* last init */
|
/* last init */
|
||||||
channels = vgmstream->channels;
|
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) {
|
if (!buf) {
|
||||||
fprintf(stderr,"failed allocating output buffer\n");
|
fprintf(stderr,"failed allocating output buffer\n");
|
||||||
goto fail;
|
goto fail;
|
||||||
|
@ -569,6 +569,16 @@ static VGMSTREAM * init_vgmstream_internal(STREAMFILE *streamFile) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void setup_vgmstream(VGMSTREAM * vgmstream) {
|
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 */
|
/* save start things so we can restart when seeking */
|
||||||
memcpy(vgmstream->start_ch, vgmstream->ch, sizeof(VGMSTREAMCHANNEL)*vgmstream->channels);
|
memcpy(vgmstream->start_ch, vgmstream->ch, sizeof(VGMSTREAMCHANNEL)*vgmstream->channels);
|
||||||
memcpy(vgmstream->start_vgmstream, vgmstream, sizeof(VGMSTREAM));
|
memcpy(vgmstream->start_vgmstream, vgmstream, sizeof(VGMSTREAM));
|
||||||
@ -747,9 +757,9 @@ VGMSTREAM * allocate_vgmstream(int channel_count, int loop_flag) {
|
|||||||
|
|
||||||
#ifdef VGMSTREAM_MIXING
|
#ifdef VGMSTREAM_MIXING
|
||||||
/* fixed arrays, for now */
|
/* fixed arrays, for now */
|
||||||
vgmstream->mixing_size = 64;
|
vgmstream->mixing_size = VGMSTREAM_MAX_MIXING;
|
||||||
vgmstream->stream_name_size = STREAM_NAME_SIZE;
|
|
||||||
#endif
|
#endif
|
||||||
|
//vgmstream->stream_name_size = STREAM_NAME_SIZE;
|
||||||
return vgmstream;
|
return vgmstream;
|
||||||
fail:
|
fail:
|
||||||
if (vgmstream) {
|
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);
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef VGMSTREAM_MIXING
|
||||||
/* swap channels if set, to create custom channel mappings */
|
/* swap channels if set, to create custom channel mappings */
|
||||||
if (vgmstream->channel_mappings_on) {
|
if (vgmstream->channel_mappings_on) {
|
||||||
int ch_from,ch_to,s;
|
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) */
|
/* 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
|
/* 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 &&
|
if (new_vgmstream->meta_type != meta_PS2_SMPL &&
|
||||||
!(new_vgmstream->loop_flag == opened_vgmstream->loop_flag &&
|
!(new_vgmstream->loop_flag == opened_vgmstream->loop_flag &&
|
||||||
new_vgmstream->loop_start_sample== opened_vgmstream->loop_start_sample &&
|
new_vgmstream->loop_start_sample== opened_vgmstream->loop_start_sample &&
|
||||||
|
@ -9,6 +9,9 @@
|
|||||||
enum { PATH_LIMIT = 32768 };
|
enum { PATH_LIMIT = 32768 };
|
||||||
enum { STREAM_NAME_SIZE = 255 };
|
enum { STREAM_NAME_SIZE = 255 };
|
||||||
enum { VGMSTREAM_MAX_CHANNELS = 64 };
|
enum { VGMSTREAM_MAX_CHANNELS = 64 };
|
||||||
|
#ifdef VGMSTREAM_MIXING
|
||||||
|
enum { VGMSTREAM_MAX_MIXING = 64 };
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "streamfile.h"
|
#include "streamfile.h"
|
||||||
|
|
||||||
@ -731,20 +734,28 @@ typedef enum {
|
|||||||
MIX_ADD,
|
MIX_ADD,
|
||||||
MIX_ADD_VOLUME,
|
MIX_ADD_VOLUME,
|
||||||
MIX_VOLUME,
|
MIX_VOLUME,
|
||||||
MIX_CROSSFADE,
|
MIX_LIMIT,
|
||||||
MIX_DOWNMIX,
|
MIX_DOWNMIX,
|
||||||
MIX_DOWNMIX_REST,
|
MIX_DOWNMIX_REST,
|
||||||
MIX_UPMIX
|
MIX_UPMIX,
|
||||||
|
MIX_FADE
|
||||||
} mix_command_t;
|
} mix_command_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
mix_command_t command;
|
mix_command_t command;
|
||||||
int ch_a;
|
/* common */
|
||||||
int ch_b;
|
int ch_dst;
|
||||||
float vol_a;
|
int ch_src;
|
||||||
float vol_b;
|
float vol;
|
||||||
float pos_a;
|
|
||||||
float pos_b;
|
/* 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;
|
} mix_config_data;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -823,15 +834,19 @@ typedef struct {
|
|||||||
|
|
||||||
/* other config */
|
/* other config */
|
||||||
int allow_dual_stereo; /* search for dual stereo (file_L.ext + file_R.ext = single stereo file) */
|
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 */
|
uint32_t channel_mask; /* to silence crossfading subsongs/layers */
|
||||||
int channel_mappings_on; /* channel mappings are active */
|
int channel_mappings_on; /* channel mappings are active */
|
||||||
int channel_mappings[32]; /* swap channel "i" with "[i]" */
|
int channel_mappings[32]; /* swap channel "i" with "[i]" */
|
||||||
|
#endif
|
||||||
#ifdef VGMSTREAM_MIXING
|
#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_on; /* mixing allowed */
|
||||||
int mixing_count; /* mixing number */
|
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 */
|
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
|
#endif
|
||||||
/* config requests, players must read and honor these values */
|
/* config requests, players must read and honor these values */
|
||||||
/* (ideally internally would work as a player, but for now player must do it manually) */
|
/* (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. */
|
/* Prepare the VGMSTREAM's initial state once parsed and ready, but before playing. */
|
||||||
void setup_vgmstream(VGMSTREAM * vgmstream);
|
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) */
|
/* 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);
|
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) */
|
/* Get the number of bytes of a single frame (smallest self-contained byte group, 1/N channels) */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user