cleanup: move defs around

This commit is contained in:
bnnm 2024-08-07 22:35:38 +02:00
parent 8160794db5
commit 637273bcd9
9 changed files with 189 additions and 160 deletions

View File

@ -1,6 +1,7 @@
#include <ctype.h>
#include "../vgmstream.h"
#include "../coding/coding.h"
#include "../layout/layout.h"
#include "mixing.h"
#include "../util/channel_mappings.h"
#include "../util/sf_utils.h"

View File

@ -4,6 +4,7 @@
#include "mixer.h"
#include "mixer_priv.h"
#include "sbuf.h"
#include "../layout/layout.h"
#include <math.h>
#include <limits.h>

View File

@ -1,5 +1,6 @@
#include "../vgmstream.h"
#include "../util/channel_mappings.h"
#include "../layout/layout.h"
#include "mixing.h"
#include "mixer_priv.h"
#include <math.h>

View File

@ -8,6 +8,14 @@
#include "../vgmstream.h"
/* List supported formats and return elements in the list, for plugins that need to know.
* The list disables some common formats that may conflict (.wav, .ogg, etc). */
const char** vgmstream_get_formats(size_t* size);
/* same, but for common-but-disabled formats in the above list. */
const char** vgmstream_get_common_formats(size_t* size);
/* ****************************************** */
/* CONTEXT: simplifies plugin code */
/* ****************************************** */

View File

@ -3,135 +3,148 @@
#include "../util.h"
/* Westwood Studios ADPCM */
/* Based on Valery V. Anisimovsky's WS-AUD.txt */
static char WSTable2bit[4] = { -2,-1,0,1 };
static char WSTable4bit[16] = { -9,-8,-6,-5,-4,-3,-2,-1, 0, 1, 2, 3, 4, 5 ,6, 8 };
static char WSTable2bit[4] = { -2, -1, 0, 1 };
static char WSTable4bit[16] = { -9, -8, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 8 };
/* We pass in the VGMSTREAM here, unlike in other codings, because
the decoder has to know about the block structure. */
void decode_ws(VGMSTREAM * vgmstream, int channel, sample * outbuf, int channelspacing, int32_t first_sample,
int32_t samples_to_do) {
VGMSTREAMCHANNEL * stream = &(vgmstream->ch[channel]);
/* We pass in the VGMSTREAM here, unlike in other codings, because the decoder has to know about the block structure. */
void decode_ws(VGMSTREAM* vgmstream, int channel, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
VGMSTREAMCHANNEL* stream = &(vgmstream->ch[channel]);
STREAMFILE* sf = stream->streamfile;
int16_t hist = stream->adpcm_history1_16;
off_t offset = stream->offset;
int samples_left_in_frame = stream->samples_left_in_frame;
off_t header_off = stream->frame_header_offset;
int samples_left_in_frame = stream->ws_samples_left_in_frame;
off_t header_offset = stream->ws_frame_header_offset;
int i;
int32_t sample_count;
//int i;
int32_t sample_count = 0;
if (vgmstream->ws_output_size == vgmstream->current_block_size) {
/* uncompressed, we just need to convert to 16-bit */
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing,offset++) {
outbuf[sample_count]=((uint8_t)read_8bit(offset,stream->streamfile)-0x80)*0x100;
/* uncompressed pcm8 to pcm16 */
for (int i = first_sample; i < first_sample + samples_to_do; i++) {
outbuf[sample_count] = (read_u8(offset,sf) - 0x80) * 0x100;
sample_count += channelspacing;
offset++;
}
} else {
}
else {
if (first_sample == 0) {
hist = 0x80;
samples_left_in_frame = 0;
}
/* actually decompress */
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; ) {
uint8_t header;
uint8_t count;
/* decompress */
for (int i = first_sample; i < first_sample + samples_to_do; /* manually incremented */) {
if (samples_left_in_frame == 0) {
header_off = offset;
header_offset = offset;
offset++;
}
header = read_8bit(header_off,stream->streamfile);
count = header & 0x3f;
switch (header>>6) { /* code */
uint8_t header = read_u8(header_offset, sf);
uint8_t count = header & 0x3f;
uint8_t code = header >> 6;
switch (code) { /* code */
case 0: /* 2-bit ADPCM */
if (samples_left_in_frame == 0) {
samples_left_in_frame = (count + 1)*4;
}
for (;samples_left_in_frame>0 && /* read this frame */
i<first_sample+samples_to_do; /* up to samples_to_do */
i++,sample_count+=channelspacing, /* done with writing a sample */
samples_left_in_frame--) { /* done with reading a sample */
int twobit = ((count + 1)*4-samples_left_in_frame)%4;
uint8_t sample;
sample = read_8bit(offset,stream->streamfile);
sample = (sample >> (twobit*2)) & 0x3;
if (samples_left_in_frame == 0)
samples_left_in_frame = (count + 1) * 4;
/* read this frame up to samples_to_do */
for ( ; samples_left_in_frame>0 && i < first_sample + samples_to_do; i++) {
int twobit = ((count + 1) * 4 - samples_left_in_frame) % 4;
uint8_t sample = read_u8(offset,sf);
sample = (sample >> (twobit * 2)) & 0x3;
hist += WSTable2bit[sample];
if (hist < 0) hist = 0;
if (hist > 0xff) hist = 0xff;
outbuf[sample_count]=(hist-0x80)*0x100;
else if (hist > 0xff) hist = 0xff;
outbuf[sample_count] = (hist - 0x80) * 0x100;
sample_count += channelspacing;
samples_left_in_frame--;
if (twobit == 3)
offset++; /* done with that byte */
}
break;
case 1: /* 4-bit ADPCM */
if (samples_left_in_frame == 0) {
samples_left_in_frame = (count + 1)*2;
}
for (;samples_left_in_frame>0 && /* read this frame */
i<first_sample+samples_to_do; /* up to samples_to_do */
i++,sample_count+=channelspacing, /* done with writing a sample */
samples_left_in_frame--) { /* done with reading a sample */
int nibble = ((count + 1)*4-samples_left_in_frame)%2;
uint8_t sample;
sample = read_8bit(offset,stream->streamfile);
if (samples_left_in_frame == 0)
samples_left_in_frame = (count + 1) * 2;
/* read this frame up to samples_to_do */
for ( ; samples_left_in_frame>0 && i < first_sample + samples_to_do; i++) {
int nibble = ((count + 1) * 4 - samples_left_in_frame) % 2;
uint8_t sample = read_u8(offset, sf);
if (nibble == 0)
sample &= 0xf;
else
sample >>= 4;
hist += WSTable4bit[sample];
if (hist < 0) hist = 0;
if (hist > 0xff) hist = 0xff;
outbuf[sample_count]=(hist-0x80)*0x100;
else if (hist > 0xff) hist = 0xff;
outbuf[sample_count] = (hist - 0x80) * 0x100;
sample_count += channelspacing;
samples_left_in_frame--;
if (nibble == 1)
offset++; /* done with that byte */
}
break;
case 2: /* no compression */
if (count & 0x20) { /* delta */
/* Note no checks against samples_to_do here,
at the top of the for loop we can always do at
least one sample */
if (count & 0x20) { /* new delta */
/* Note no checks against samples_to_do here, at the top of the for loop
* we can always do at least one sample */
/* low 5 bits are a signed delta */
if (count & 0x10) {
hist -= ((count & 0xf)^0xf) + 1;
hist -= ((count & 0x0f) ^ 0x0f) + 1;
} else {
hist += count & 0xf;
hist += count & 0x0f;
}
/* Valery doesn't specify this, but I will assume */
/* Valery doesn't specify this, but clamp just in case */
if (hist < 0) hist = 0;
if (hist > 0xff) hist = 0xff;
else if (hist > 0xff) hist = 0xff;
outbuf[sample_count]=(hist-0x80)*0x100;
sample_count+=channelspacing;
i++;
/* just one, and we got it */
samples_left_in_frame = 0;
} else { /* copy bytes verbatim */
outbuf[sample_count] = (hist - 0x80) * 0x100;
sample_count += channelspacing;
samples_left_in_frame = 0; /* just one */
}
else {
/* copy bytes verbatim */
if (samples_left_in_frame == 0)
samples_left_in_frame=count+1;
for (;samples_left_in_frame>0 && /* read this frame */
i<first_sample+samples_to_do; /* up to samples_to_do */
offset++, /* done with a byte */
i++,sample_count+=channelspacing, /* done with writing a sample */
samples_left_in_frame--) { /* done with reading a sample */
outbuf[sample_count]=((hist=(uint8_t)read_8bit(offset,stream->streamfile))-0x80)*0x100;
samples_left_in_frame = (count + 1);
/* read this frame up to samples_to_do */
for ( ; samples_left_in_frame > 0 && i < first_sample + samples_to_do; i++) {
hist = read_u8(offset,sf);
offset++;
outbuf[sample_count] = (hist - 0x80) * 0x100;
sample_count += channelspacing;
samples_left_in_frame--;
}
}
break;
case 3: /* RLE */
if (samples_left_in_frame == 0)
samples_left_in_frame=count+1;
for (;samples_left_in_frame>0 && /* read this frame */
i<first_sample+samples_to_do; /* up to samples_to_do */
i++,sample_count+=channelspacing, /* done with writing a sample */
samples_left_in_frame--) { /* done with reading a sample */
outbuf[sample_count]=(hist-0x80)*0x100;
samples_left_in_frame = (count + 1);
/* read this frame up to samples_to_do */
for ( ; samples_left_in_frame > 0 && i < first_sample + samples_to_do; i++) {
outbuf[sample_count] = (hist - 0x80) * 0x100;
sample_count += channelspacing;
samples_left_in_frame--;
}
default:
break;
@ -141,6 +154,6 @@ void decode_ws(VGMSTREAM * vgmstream, int channel, sample * outbuf, int channels
stream->offset = offset;
stream->adpcm_history1_16 = hist;
stream->samples_left_in_frame = samples_left_in_frame;
stream->frame_header_offset = header_off;
stream->ws_samples_left_in_frame = samples_left_in_frame;
stream->ws_frame_header_offset = header_offset;
}

View File

@ -1,5 +1,6 @@
#include "vgmstream.h"
#include "coding/coding.h"
#include "layout/layout.h"
/* Defines the list of accepted extensions. vgmstream doesn't use it internally so it's here
@ -1237,7 +1238,7 @@ static const meta_info meta_info_list[] = {
{meta_EB_SF0, "assumed Excitebots .sf0 by extension"},
{meta_MTAF, "Konami MTAF header"},
{meta_ALP, "High Voltage ALP header"},
{meta_WPD, "WPD 'DPW' header"},
{meta_WPD, "Navel WPD header"},
{meta_MN_STR, "Mini Ninjas 'STR' header"},
{meta_MSS, "Guerilla MCSS header"},
{meta_PS2_HSF, "Lowrider 'HSF' header"},

View File

@ -6,6 +6,53 @@
#include "../util/reader_sf.h"
#include "../util/log.h"
/* basic layouts */
void render_vgmstream_flat(sample_t* buffer, int32_t sample_count, VGMSTREAM* vgmstream);
void render_vgmstream_interleave(sample_t* buffer, int32_t sample_count, VGMSTREAM* vgmstream);
/* segmented layout */
/* for files made of "continuous" segments, one per section of a song (using a complete sub-VGMSTREAM) */
typedef struct {
int segment_count;
VGMSTREAM** segments;
int current_segment;
sample_t* buffer;
int input_channels; /* internal buffer channels */
int output_channels; /* resulting channels (after mixing, if applied) */
int mixed_channels; /* segments have different number of channels */
} segmented_layout_data;
void render_vgmstream_segmented(sample_t* buffer, int32_t sample_count, VGMSTREAM* vgmstream);
segmented_layout_data* init_layout_segmented(int segment_count);
int setup_layout_segmented(segmented_layout_data* data);
void free_layout_segmented(segmented_layout_data* data);
void reset_layout_segmented(segmented_layout_data* data);
void seek_layout_segmented(VGMSTREAM* vgmstream, int32_t seek_sample);
void loop_layout_segmented(VGMSTREAM* vgmstream, int32_t loop_sample);
VGMSTREAM* allocate_segmented_vgmstream(segmented_layout_data* data, int loop_flag, int loop_start_segment, int loop_end_segment);
/* layered layout */
/* for files made of "parallel" layers, one per group of channels (using a complete sub-VGMSTREAM) */
typedef struct {
int layer_count;
VGMSTREAM** layers;
sample_t* buffer;
int input_channels; /* internal buffer channels */
int output_channels; /* resulting channels (after mixing, if applied) */
int external_looping; /* don't loop using per-layer loops, but layout's own looping */
int curr_layer; /* helper */
} layered_layout_data;
void render_vgmstream_layered(sample_t* buffer, int32_t sample_count, VGMSTREAM* vgmstream);
layered_layout_data* init_layout_layered(int layer_count);
int setup_layout_layered(layered_layout_data* data);
void free_layout_layered(layered_layout_data* data);
void reset_layout_layered(layered_layout_data* data);
void seek_layout_layered(VGMSTREAM* vgmstream, int32_t seek_sample);
void loop_layout_layered(VGMSTREAM* vgmstream, int32_t loop_sample);
VGMSTREAM* allocate_layered_vgmstream(layered_layout_data* data);
/* blocked layouts */
void render_vgmstream_blocked(sample_t* buffer, int32_t sample_count, VGMSTREAM* vgmstream);
void block_update(off_t block_offset, VGMSTREAM* vgmstream);
@ -51,27 +98,4 @@ void block_update_ubi_sce(off_t block_offset, VGMSTREAM* vgmstream);
void block_update_tt_ad(off_t block_offset, VGMSTREAM* vgmstream);
void block_update_vas(off_t block_offset, VGMSTREAM* vgmstream);
/* other layouts */
void render_vgmstream_interleave(sample_t* buffer, int32_t sample_count, VGMSTREAM* vgmstream);
void render_vgmstream_flat(sample_t* buffer, int32_t sample_count, VGMSTREAM* vgmstream);
void render_vgmstream_segmented(sample_t* buffer, int32_t sample_count, VGMSTREAM* vgmstream);
segmented_layout_data* init_layout_segmented(int segment_count);
int setup_layout_segmented(segmented_layout_data* data);
void free_layout_segmented(segmented_layout_data* data);
void reset_layout_segmented(segmented_layout_data* data);
void seek_layout_segmented(VGMSTREAM* vgmstream, int32_t seek_sample);
void loop_layout_segmented(VGMSTREAM* vgmstream, int32_t loop_sample);
VGMSTREAM *allocate_segmented_vgmstream(segmented_layout_data* data, int loop_flag, int loop_start_segment, int loop_end_segment);
void render_vgmstream_layered(sample_t* buffer, int32_t sample_count, VGMSTREAM* vgmstream);
layered_layout_data* init_layout_layered(int layer_count);
int setup_layout_layered(layered_layout_data* data);
void free_layout_layered(layered_layout_data* data);
void reset_layout_layered(layered_layout_data* data);
void seek_layout_layered(VGMSTREAM* vgmstream, int32_t seek_sample);
void loop_layout_layered(VGMSTREAM* vgmstream, int32_t loop_sample);
VGMSTREAM *allocate_layered_vgmstream(layered_layout_data* data);
#endif

View File

@ -94,27 +94,28 @@ typedef struct {
} play_state_t;
/* info for a single vgmstream channel */
/* info for a single vgmstream 'channel' (or rather, mono stream) */
typedef struct {
STREAMFILE* streamfile; /* file used by this channel */
off_t channel_start_offset; /* where data for this channel begins */
off_t offset; /* current location in the file */
off_t frame_header_offset; /* offset of the current frame header (for WS) */
int samples_left_in_frame; /* for WS */
/* format and channel specific */
/* format specific */
/* adpcm */
int16_t adpcm_coef[16]; /* formats with decode coefficients built in (DSP, some ADX) */
int32_t adpcm_coef_3by32[0x60]; /* Level-5 0x555 */
int16_t vadpcm_coefs[8*2*8]; /* VADPCM: max 8 groups * max 2 order * fixed 8 subframe coefs */
/* ADPCM with built or variable decode coefficients */
union {
int16_t adpcm_history1_16; /* previous sample */
int16_t adpcm_coef[16]; /* DSP, some ADX (in rare cases may change per block) */
int16_t vadpcm_coefs[8*2*8]; /* VADPCM: max 8 groups * max 2 order * fixed 8 subframe = 128 coefs */
int32_t adpcm_coef_3by32[96]; /* Level-5 0x555 */
};
/* previous ADPCM samples */
union {
int16_t adpcm_history1_16;
int32_t adpcm_history1_32;
};
union {
int16_t adpcm_history2_16; /* previous previous sample */
int16_t adpcm_history2_16;
int32_t adpcm_history2_32;
};
union {
@ -129,14 +130,20 @@ typedef struct {
//double adpcm_history1_double;
//double adpcm_history2_double;
int adpcm_step_index; /* for IMA */
int adpcm_scale; /* for MS ADPCM */
/* for ADPCM decoders that store steps (IMA) or scales (MSADPCM) */
union {
int adpcm_step_index;
int adpcm_scale;
};
/* Westwood Studios decoder */
off_t ws_frame_header_offset; /* offset of the current frame header */
int ws_samples_left_in_frame; /* last decoded info */
/* state for G.721 decoder, sort of big but we might as well keep it around */
struct g72x_state g72x_state;
/* ADX encryption */
int adx_channels;
uint16_t adx_xor;
uint16_t adx_mult;
uint16_t adx_add;
@ -147,9 +154,9 @@ typedef struct {
/* main vgmstream info */
typedef struct {
/* basic config */
int32_t num_samples; /* the actual max number of samples */
int channels; /* number of channels for the current stream */
int32_t sample_rate; /* sample rate in Hz */
int channels; /* number of channels */
int32_t num_samples; /* the actual max number of samples */
coding_t coding_type; /* type of encoding */
layout_t layout_type; /* type of layout */
meta_t meta_type; /* type of metadata */
@ -180,13 +187,13 @@ typedef struct {
int format_id; /* internal format ID */
/* layout/block state */
size_t full_block_size; /* actual data size of an entire block (ie. may be fixed, include padding/headers, etc) */
int32_t current_sample; /* sample point within the file (for loop detection) */
int32_t samples_into_block; /* number of samples into the current block/interleave/segment/etc */
off_t current_block_offset; /* start of this block (offset of block header) */
size_t current_block_size; /* size in usable bytes of the block we're in now (used to calculate num_samples per block) */
int32_t current_block_samples; /* size in samples of the block we're in now (used over current_block_size if possible) */
off_t next_block_offset; /* offset of header of the next block */
size_t full_block_size; /* actual data size of an entire block (ie. may be fixed, include padding/headers, etc) */
/* loop state (saved when loop is hit to restore later) */
int32_t loop_current_sample; /* saved from current_sample (same as loop_start_sample, but more state-like) */
@ -228,35 +235,13 @@ typedef struct {
play_state_t pstate; /* player state (applied over decoding) */
int loop_count; /* counter of complete loops (1=looped once) */
int loop_target; /* max loops before continuing with the stream end (loops forever if not set) */
sample_t* tmpbuf; /* garbage buffer used for seeking/trimming */
size_t tmpbuf_size; /* for all channels (samples = tmpbuf_size / channels) */
} VGMSTREAM;
/* for files made of "continuous" segments, one per section of a song (using a complete sub-VGMSTREAM) */
typedef struct {
int segment_count;
VGMSTREAM** segments;
int current_segment;
sample_t* buffer;
int input_channels; /* internal buffer channels */
int output_channels; /* resulting channels (after mixing, if applied) */
int mixed_channels; /* segments have different number of channels */
} segmented_layout_data;
/* for files made of "parallel" layers, one per group of channels (using a complete sub-VGMSTREAM) */
typedef struct {
int layer_count;
VGMSTREAM** layers;
sample_t* buffer;
int input_channels; /* internal buffer channels */
int output_channels; /* resulting channels (after mixing, if applied) */
int external_looping; /* don't loop using per-layer loops, but layout's own looping */
int curr_layer; /* helper */
} layered_layout_data;
// VGMStream description in structure format
typedef struct {
int sample_rate;
@ -304,9 +289,6 @@ void reset_vgmstream(VGMSTREAM* vgmstream);
/* close an open vgmstream */
void close_vgmstream(VGMSTREAM* vgmstream);
/* calculate the number of samples to be played based on looping parameters */
int32_t get_vgmstream_play_samples(double looptimes, double fadeseconds, double fadedelayseconds, VGMSTREAM* vgmstream);
/* Decode data into sample buffer. Returns < sample_count on stream end */
int render_vgmstream(sample_t* buffer, int32_t sample_count, VGMSTREAM* vgmstream);
@ -321,20 +303,6 @@ void describe_vgmstream_info(VGMSTREAM* vgmstream, vgmstream_info* desc);
/* Return the average bitrate in bps of all unique files contained within this stream. */
int get_vgmstream_average_bitrate(VGMSTREAM* vgmstream);
/* List supported formats and return elements in the list, for plugins that need to know.
* The list disables some common formats that may conflict (.wav, .ogg, etc). */
const char** vgmstream_get_formats(size_t* size);
/* same, but for common-but-disabled formats in the above list. */
const char** vgmstream_get_common_formats(size_t* size);
/* Force enable/disable internal looping. Should be done before playing anything (or after reset),
* and not all codecs support arbitrary loop values ATM. */
void vgmstream_force_loop(VGMSTREAM* vgmstream, int loop_flag, int loop_start_sample, int loop_end_sample);
/* Set number of max loops to do, then play up to stream end (for songs with proper endings) */
void vgmstream_set_loop_target(VGMSTREAM* vgmstream, int loop_target);
/* Return 1 if vgmstream detects from the filename that said file can be used even if doesn't physically exist */
int vgmstream_is_virtual_filename(const char* filename);
@ -358,5 +326,16 @@ void get_vgmstream_coding_description(VGMSTREAM* vgmstream, char* out, size_t ou
void get_vgmstream_layout_description(VGMSTREAM* vgmstream, char* out, size_t out_size);
void get_vgmstream_meta_description(VGMSTREAM* vgmstream, char* out, size_t out_size);
/* calculate the number of samples to be played based on looping parameters */
int32_t get_vgmstream_play_samples(double looptimes, double fadeseconds, double fadedelayseconds, VGMSTREAM* vgmstream);
void setup_state_vgmstream(VGMSTREAM* vgmstream);
/* Force enable/disable internal looping. Should be done before playing anything (or after reset),
* and not all codecs support arbitrary loop values ATM. */
void vgmstream_force_loop(VGMSTREAM* vgmstream, int loop_flag, int loop_start_sample, int loop_end_sample);
/* Set number of max loops to do, then play up to stream end (for songs with proper endings) */
void vgmstream_set_loop_target(VGMSTREAM* vgmstream, int loop_target);
#endif

View File

@ -237,8 +237,9 @@ void WINAPI xmplay_GetInfoText(char* format, char* length) {
rate = vgmstream->sample_rate;
samples = vgmstream->num_samples;
bps = get_vgmstream_average_bitrate(vgmstream) / 1000;
get_vgmstream_coding_description(vgmstream, fmt, sizeof(fmt));
if (strcmp(fmt, "FFmpeg") == 0)
//get_vgmstream_coding_description(vgmstream, fmt, sizeof(fmt));
//if (strcmp(fmt, "FFmpeg") == 0)
{
char buffer[1024];
buffer[0] = '\0';