mirror of
https://github.com/vgmstream/vgmstream.git
synced 2024-12-18 09:25:53 +01:00
cleanup: api misc
This commit is contained in:
parent
e79e0bad3f
commit
d98e1c854f
@ -1,4 +1,4 @@
|
|||||||
#include "../src/api.h"
|
#include "../src/libvgmstream.h"
|
||||||
#if LIBVGMSTREAM_ENABLE
|
#if LIBVGMSTREAM_ENABLE
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
55
src/api.h
55
src/api.h
@ -1,59 +1,4 @@
|
|||||||
#ifndef _API_H_
|
#ifndef _API_H_
|
||||||
#define _API_H_
|
#define _API_H_
|
||||||
#include "base/plugins.h" //TODO: to be removed
|
#include "base/plugins.h" //TODO: to be removed
|
||||||
|
|
||||||
//#define LIBVGMSTREAM_ENABLE 1
|
|
||||||
#if LIBVGMSTREAM_ENABLE
|
|
||||||
|
|
||||||
/* vgmstream's public API
|
|
||||||
*
|
|
||||||
* By default vgmstream behaves like a simple decoder (extract samples until stream end), but you can configure it
|
|
||||||
* to loop N times or even downmix. In other words, it also behaves a bit like a player.
|
|
||||||
*
|
|
||||||
* It exposes multiple options and convenience functions beyond simple decoding mainly for various plugins,
|
|
||||||
* since it was faster moving shared behavior to core rather than reimplementing every time.
|
|
||||||
*
|
|
||||||
* All this may make the API a bit twisted and coupled (sorry, tried my best), probably will improve later. Probably.
|
|
||||||
*
|
|
||||||
* Notes:
|
|
||||||
* - vgmstream may dynamically allocate stuff as needed (not too much beyond some setup buffers, but varies per format)
|
|
||||||
* - previously the only way to use vgmstream was accesing its internals. Now there is an API internals may change in the future
|
|
||||||
* - some details described in the API may not happen at the moment (they are defined for future internal changes)
|
|
||||||
* - main reason it uses the slighly long-winded libvgmstream_* names is that internals use the vgmstream_* 'namespace'
|
|
||||||
* - c-strings should be in UTF-8
|
|
||||||
* - the API is still WIP and may be slightly buggy overall due to lack of time, to be improved later
|
|
||||||
* - vgmstream's features are mostly stable, but this API may be tweaked from time to time (check API_VERSION)
|
|
||||||
*
|
|
||||||
* Basic usage (also see api_example.c):
|
|
||||||
* - libvgmstream_init(...) // base context
|
|
||||||
* - libvgmstream_setup(...) // config if needed
|
|
||||||
* - libvgmstream_open(...) // setup format
|
|
||||||
* - libvgmstream_play(...) // main decode
|
|
||||||
* - output samples + repeat libvgmstream_play until stream is done
|
|
||||||
* - libvgmstream_free(...) // cleanup
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
|
|
||||||
/* standard C param call and name mangling (to avoid __stdcall / .defs) */
|
|
||||||
//#define LIBVGMSTREAM_CALL __cdecl //needed?
|
|
||||||
//LIBVGMSTREAM_API (type) LIBVGMSTREAM_CALL libvgmstream_function(...);
|
|
||||||
|
|
||||||
/* define external function behavior (during compilation) */
|
|
||||||
#if defined(LIBVGMSTREAM_EXPORT)
|
|
||||||
#define LIBVGMSTREAM_API __declspec(dllexport) /* when exporting/creating vgmstream DLL */
|
|
||||||
#elif defined(LIBVGMSTREAM_IMPORT)
|
|
||||||
#define LIBVGMSTREAM_API __declspec(dllimport) /* when importing/linking vgmstream DLL */
|
|
||||||
#else
|
|
||||||
#define LIBVGMSTREAM_API /* nothing, internal/default */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "api_version.h"
|
|
||||||
#include "api_decode.h"
|
|
||||||
#include "api_helpers.h"
|
|
||||||
#include "api_streamfile.h"
|
|
||||||
#include "api_tags.h"
|
|
||||||
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
|
202
src/api_decode.h
202
src/api_decode.h
@ -1,202 +0,0 @@
|
|||||||
#ifndef _API_DECODE_H_
|
|
||||||
#define _API_DECODE_H_
|
|
||||||
#include "api.h"
|
|
||||||
#if LIBVGMSTREAM_ENABLE
|
|
||||||
#include "api_streamfile.h"
|
|
||||||
|
|
||||||
|
|
||||||
/* vgmstream's main (decode) API.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/* interleaved samples: buf[0]=ch0, buf[1]=ch1, buf[2]=ch0, buf[3]=ch0, ... */
|
|
||||||
typedef enum {
|
|
||||||
LIBVGMSTREAM_SAMPLE_PCM16 = 0x01,
|
|
||||||
LIBVGMSTREAM_SAMPLE_PCM24 = 0x02,
|
|
||||||
LIBVGMSTREAM_SAMPLE_PCM32 = 0x03,
|
|
||||||
LIBVGMSTREAM_SAMPLE_FLOAT = 0x04,
|
|
||||||
} libvgmstream_sample_t;
|
|
||||||
|
|
||||||
/* current song info, may be copied around (values are info-only) */
|
|
||||||
typedef struct {
|
|
||||||
/* main (always set) */
|
|
||||||
libvgmstream_sample_t sample_type; // output buffer's sample type
|
|
||||||
int channels; // output channels
|
|
||||||
int sample_rate; // output sample rate
|
|
||||||
|
|
||||||
int sample_size; // derived from sample_type (pcm16=2, float=4, etc)
|
|
||||||
|
|
||||||
/* extra info (may be 0 if not known or not relevant) */
|
|
||||||
uint32_t channel_layout; // standard WAVE bitflags
|
|
||||||
|
|
||||||
int subsong_index; // 0 = none, N = loaded subsong N
|
|
||||||
int subsong_count; // 0 = format has no concept of subsongs, N = has N subsongs (1 = format has subsongs, and only 1)
|
|
||||||
|
|
||||||
int input_channels; // original file's channels before downmixing (if any)
|
|
||||||
//int interleave; // when file is interleaved
|
|
||||||
//int interleave_first; // when file is interleaved
|
|
||||||
//int interleave_last; // when file is interleaved
|
|
||||||
//int frame_size; // when file has some configurable frame size
|
|
||||||
|
|
||||||
/* sample info (may not be used depending on config) */
|
|
||||||
int64_t sample_count; // file's max samples (not final play duration)
|
|
||||||
int64_t loop_start; // loop start sample
|
|
||||||
int64_t loop_end; // loop end sample
|
|
||||||
bool loop_flag; // if file loops; note that false + defined loops means looping was forcefully disabled
|
|
||||||
|
|
||||||
bool play_forever; // if file loops forever based on current config (meaning _play never stops)
|
|
||||||
int64_t play_samples; // totals after all calculations (after applying loop/fade/etc config)
|
|
||||||
// ** may not be 100% accurate in some cases (must check decoder's 'done' flag rather than this count)
|
|
||||||
// ** if play_forever is set this is still provided for reference based on non-forever config
|
|
||||||
|
|
||||||
int stream_bitrate; // average bitrate of the subsong (slightly bloated vs codec_bitrate; incorrect in rare cases)
|
|
||||||
//int codec_bitrate; // average bitrate of the codec data
|
|
||||||
// ** not possible / slow to calculate in most cases
|
|
||||||
|
|
||||||
/* descriptions */
|
|
||||||
char codec_name[128]; //
|
|
||||||
char layout_name[128]; //
|
|
||||||
char meta_name[128]; // (not internal "tag" metadata)
|
|
||||||
char stream_name[256]; // some internal name or representation, not always useful
|
|
||||||
// ** these are a bit big for a struct, but the typical use case of vgsmtream is opening a file > immediately
|
|
||||||
// query description and since libvgmstream returns its own copy it shouldn't be too much of a problem
|
|
||||||
// ** (may be separated later)
|
|
||||||
|
|
||||||
/* misc */
|
|
||||||
//bool rough_samples; // signal cases where loop points or sample count can't exactly reflect actual behavior (do not use to export)
|
|
||||||
|
|
||||||
int format_internal_id; // may be used when reopening subfiles or similar formats without checking other possible formats first
|
|
||||||
// ** this value WILL change without warning between vgmstream versions/commits
|
|
||||||
|
|
||||||
} libvgmstream_format_t;
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
void* buf; // current decoded buf (valid after _decode until next call; may change between calls)
|
|
||||||
int buf_samples; // current buffer samples (0 is possible in some cases, meaning current _decode can't generate samples)
|
|
||||||
int buf_bytes; // current buffer bytes (channels * sample_size * samples)
|
|
||||||
|
|
||||||
bool done; // flag when stream is done playing based on config; will still allow _play calls returning blank samples
|
|
||||||
// ** note that with play_forever this flag is never set
|
|
||||||
} libvgmstream_decoder_t;
|
|
||||||
|
|
||||||
|
|
||||||
/* vgmstream context/handle */
|
|
||||||
typedef struct {
|
|
||||||
void* priv; // internal data
|
|
||||||
|
|
||||||
/* pointers for easier ABI compatibility */
|
|
||||||
const libvgmstream_format_t* format; // current song info, updated on _open
|
|
||||||
libvgmstream_decoder_t* decoder; // updated on each _decode call
|
|
||||||
|
|
||||||
} libvgmstream_t;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* inits the vgmstream context
|
|
||||||
* - returns NULL on error
|
|
||||||
* - call libvgmstream_free when done.
|
|
||||||
*/
|
|
||||||
LIBVGMSTREAM_API libvgmstream_t* libvgmstream_init(void);
|
|
||||||
|
|
||||||
/* frees vgmstream context and any other internal stuff that may not be closed
|
|
||||||
*/
|
|
||||||
LIBVGMSTREAM_API void libvgmstream_free(libvgmstream_t* lib);
|
|
||||||
|
|
||||||
|
|
||||||
/* configures how vgmstream behaves internally when playing a file */
|
|
||||||
typedef struct {
|
|
||||||
bool disable_config_override; // ignore forced (TXTP) config
|
|
||||||
bool allow_play_forever; // must allow manually as some cases a TXTP may set loop forever but client may not handle it (ex. wave dumpers)
|
|
||||||
|
|
||||||
bool play_forever; // keeps looping forever (file must have loop_flag set)
|
|
||||||
bool ignore_loop; // ignores loops points
|
|
||||||
bool force_loop; // enables full loops (0..samples) if file doesn't have loop points
|
|
||||||
bool really_force_loop; // forces full loops (0..samples) even if file has loop points
|
|
||||||
bool ignore_fade; // don't fade after N loops and play remaning stream (for files with outros)
|
|
||||||
|
|
||||||
double loop_count; // target loops (values like 1.5 are ok)
|
|
||||||
double fade_time; // fade period after target loops
|
|
||||||
double fade_delay; // fade delay after target loops
|
|
||||||
|
|
||||||
int auto_downmix_channels; // downmixing if vgmstream's channels are higher than value
|
|
||||||
// ** for players that can only handle N channels, but this type of downmixing is very simplistic and not recommended
|
|
||||||
|
|
||||||
bool force_pcm16; // forces output buffer to be remixed into PCM16
|
|
||||||
|
|
||||||
} libvgmstream_config_t;
|
|
||||||
|
|
||||||
/* pass default config, that will be applied to song on open
|
|
||||||
* - invalid config or complex cases (ex. some TXTP) may ignore these settings.
|
|
||||||
* - called without a song loaded (before _open or after _close), otherwise ignored.
|
|
||||||
* - without config vgmstream will decode the current stream once
|
|
||||||
*/
|
|
||||||
LIBVGMSTREAM_API void libvgmstream_setup(libvgmstream_t* lib, libvgmstream_config_t* cfg);
|
|
||||||
|
|
||||||
|
|
||||||
/* configures how vgmstream opens the format */
|
|
||||||
typedef struct {
|
|
||||||
libvgmstream_streamfile_t* libsf; // custom IO streamfile that provides reader info for vgmstream
|
|
||||||
// ** not needed after _open and should be closed, as vgmstream re-opens its own SFs internally as needed
|
|
||||||
|
|
||||||
int subsong; // target subsong (1..N) or 0 = default/first
|
|
||||||
// ** to check if a file has subsongs, _open first + check format->total_subsongs (then _open 2nd, 3rd, etc)
|
|
||||||
|
|
||||||
int format_internal_id; // force a format (for example when loading new subsong of the same archive)
|
|
||||||
|
|
||||||
int stereo_track; // forces vgmstream to decode one 2ch+2ch+2ch... 'track' and discard other channels, where 0 = disabled, 1..N = Nth track
|
|
||||||
|
|
||||||
} libvgmstream_options_t;
|
|
||||||
|
|
||||||
/* opens file based on config and prepares it to play if supported.
|
|
||||||
* - returns < 0 on error (file not recognised, invalid subsong index, etc)
|
|
||||||
* - will close currently loaded song if needed
|
|
||||||
*/
|
|
||||||
LIBVGMSTREAM_API int libvgmstream_open(libvgmstream_t* lib, libvgmstream_options_t* open_options);
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
/* opens file based on config and returns its file info
|
|
||||||
* - returns < 0 on error (file not recognised, invalid subsong index, etc)
|
|
||||||
* - equivalent to _open, but doesn't update the current loaded song / format and copies to passed struct
|
|
||||||
* - may be used while current song is loaded/playing but you need to query next song with current config
|
|
||||||
* - to play a new song don't call _open_info to check the format first, just call _open + check format afterwards
|
|
||||||
* - in many cases the only way for vgmstream to get a file's format info is making it almost ready to play,
|
|
||||||
* so this isn't any faster than _open
|
|
||||||
*/
|
|
||||||
LIBVGMSTREAM_API int libvgmstream_open_info(libvgmstream_t* lib, libvgmstream_options_t* options, libvgmstream_format_t* format);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* closes current song; may still use libvgmstream to open other songs
|
|
||||||
*/
|
|
||||||
LIBVGMSTREAM_API void libvgmstream_close(libvgmstream_t* lib);
|
|
||||||
|
|
||||||
|
|
||||||
/* decodes next batch of samples
|
|
||||||
* - vgmstream supplies its own buffer, updated on lib->decoder->* values (may change between calls)
|
|
||||||
* - returns < 0 on error
|
|
||||||
*/
|
|
||||||
LIBVGMSTREAM_API int libvgmstream_play(libvgmstream_t* lib);
|
|
||||||
|
|
||||||
/* Same as _play, but fills some external buffer (also updates lib->decoder->* values)
|
|
||||||
* - returns < 0 on error, or N = number of filled samples.
|
|
||||||
* - buf must be at least as big as channels * sample_size * buf_samples
|
|
||||||
* - needs copying around from internal bufs so may be slightly slower; mainly for cases when you have buf constraints
|
|
||||||
*/
|
|
||||||
LIBVGMSTREAM_API int libvgmstream_fill(libvgmstream_t* lib, void* buf, int buf_samples);
|
|
||||||
|
|
||||||
/* Gets current position within the song.
|
|
||||||
* - return < 0 on error (file not ready)
|
|
||||||
*/
|
|
||||||
LIBVGMSTREAM_API int64_t libvgmstream_get_play_position(libvgmstream_t* lib);
|
|
||||||
|
|
||||||
/* Seeks to absolute position. Will clamp incorrect values such as seeking before/past playable length.
|
|
||||||
* - on play_forever may seek to any position
|
|
||||||
*/
|
|
||||||
LIBVGMSTREAM_API void libvgmstream_seek(libvgmstream_t* lib, int64_t sample);
|
|
||||||
|
|
||||||
/* Reset current song
|
|
||||||
*/
|
|
||||||
LIBVGMSTREAM_API void libvgmstream_reset(libvgmstream_t* lib);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
#endif
|
|
@ -1,81 +0,0 @@
|
|||||||
#ifndef _API_HELPERS_H_
|
|
||||||
#define _API_HELPERS_H_
|
|
||||||
#include "api.h"
|
|
||||||
#if LIBVGMSTREAM_ENABLE
|
|
||||||
|
|
||||||
|
|
||||||
/* vgmstream's helper stuff, for plugins.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
LIBVGMSTREAM_LOG_LEVEL_ALL = 0,
|
|
||||||
LIBVGMSTREAM_LOG_LEVEL_DEBUG = 20,
|
|
||||||
LIBVGMSTREAM_LOG_LEVEL_INFO = 30,
|
|
||||||
LIBVGMSTREAM_LOG_LEVEL_NONE = 100,
|
|
||||||
} libvgmstream_loglevel_t;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
libvgmstream_loglevel_t level; // log level
|
|
||||||
void (*callback)(int level, const char* str); // log callback
|
|
||||||
bool stdout_callback; // use default log callback rather than user supplied
|
|
||||||
} libvgmstream_log_t;
|
|
||||||
|
|
||||||
/* defines a global log callback, as vgmstream sometimes communicates format issues to the user.
|
|
||||||
* - note that log is currently set globally rather than per libvgmstream_t
|
|
||||||
*/
|
|
||||||
LIBVGMSTREAM_API void libvgmstream_set_log(libvgmstream_log_t* cfg);
|
|
||||||
|
|
||||||
|
|
||||||
/* Returns a list of supported extensions (WARNING: it's pretty big), such as "adx", "dsp", etc.
|
|
||||||
* Mainly for plugins that want to know which extensions are supported.
|
|
||||||
* - returns NULL if no size is provided
|
|
||||||
*/
|
|
||||||
LIBVGMSTREAM_API const char** libvgmstream_get_extensions(size_t* size);
|
|
||||||
|
|
||||||
|
|
||||||
/* Same as above, buf returns a list what vgmstream considers "common" formats (such as "wav", "ogg"),
|
|
||||||
* which usually one doesn't want to associate to vgmstream.
|
|
||||||
* - returns NULL if no size is provided
|
|
||||||
*/
|
|
||||||
LIBVGMSTREAM_API const char** libvgmstream_get_common_extensions(size_t* size);
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
bool is_extension; /* set if filename is just an extension */
|
|
||||||
bool skip_default; /* set if shouldn't check default formats */
|
|
||||||
bool reject_extensionless; /* set if player can't play extensionless files */
|
|
||||||
bool accept_unknown; /* set to allow any extension (for txth) */
|
|
||||||
bool accept_common; /* set to allow known-but-common extension (when player has plugin priority) */
|
|
||||||
} libvgmstream_valid_t;
|
|
||||||
|
|
||||||
/* returns if vgmstream can parse a filename by extension, to reject some files earlier
|
|
||||||
* - doesn't check file contents (that's only done on _open)
|
|
||||||
* - config may be NULL
|
|
||||||
* - mainly for plugins that fail early; libvgmstream doesn't use this
|
|
||||||
*/
|
|
||||||
LIBVGMSTREAM_API bool libvgmstream_is_valid(const char* filename, libvgmstream_valid_t* cfg);
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
bool force_title; // TODO: what was this for?
|
|
||||||
bool subsong_range; // print a range of possible subsongs after title 'filename#1~N'
|
|
||||||
bool remove_extension; // remove extension from passed filename
|
|
||||||
bool remove_archive; // remove '(archive)|(subfile)' format of some plugins
|
|
||||||
const char* filename; // base file's filename
|
|
||||||
// ** note that sometimes vgmstream doesn't have/know the original name, so it's needed again here
|
|
||||||
} libvgmstream_title_t;
|
|
||||||
|
|
||||||
/* get a simple title for plugins, derived from internal stream name if available
|
|
||||||
* - valid after _open
|
|
||||||
*/
|
|
||||||
LIBVGMSTREAM_API int libvgmstream_get_title(libvgmstream_t* lib, libvgmstream_title_t* cfg, char* buf, int buf_len);
|
|
||||||
|
|
||||||
|
|
||||||
/* Writes a description of the current song into dst. Will always be null-terminated.
|
|
||||||
* - returns < 0 if file was truncated, though will still succeed.
|
|
||||||
*/
|
|
||||||
LIBVGMSTREAM_API int libvgmstream_format_describe(libvgmstream_t* lib, char* dst, int dst_size);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
#endif
|
|
@ -1,45 +0,0 @@
|
|||||||
#ifndef _API_TAGS_H_
|
|
||||||
#define _API_TAGS_H_
|
|
||||||
#include "api.h"
|
|
||||||
#if LIBVGMSTREAM_ENABLE
|
|
||||||
|
|
||||||
/* vgmstream's !tags.m3u API.
|
|
||||||
* Doesn't need a main libvgmstream as tags aren't tied to loaded songs.
|
|
||||||
*
|
|
||||||
* Meant to be a simple implementation; feel free to ignore and roll your own
|
|
||||||
* (or use another external tags plugin).
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/* tag state */
|
|
||||||
typedef struct {
|
|
||||||
void* priv; // internal data
|
|
||||||
|
|
||||||
const char* key; // current key
|
|
||||||
const char* val; // current value
|
|
||||||
} libvgmstream_tags_t;
|
|
||||||
|
|
||||||
/* Initializes tags.
|
|
||||||
* - libsf should point to a !tags.m3u file
|
|
||||||
* - unlike libvgmstream_open, sf tagfile must be valid during the tag extraction process.
|
|
||||||
*/
|
|
||||||
LIBVGMSTREAM_API libvgmstream_tags_t* libvgmstream_tags_init(libvgmstream_streamfile_t* libsf);
|
|
||||||
|
|
||||||
|
|
||||||
/* Finds tags for a new filename. Must be called first before extracting tags.
|
|
||||||
*/
|
|
||||||
LIBVGMSTREAM_API void libvgmstream_tags_find(libvgmstream_tags_t* tags, const char* target_filename);
|
|
||||||
|
|
||||||
|
|
||||||
/* Extracts next valid tag in tagfile to key/val.
|
|
||||||
* - returns false if no more tags are found (meant to be called repeatedly until false)
|
|
||||||
* - key/values are trimmed of beginning/end whitespaces and values are in UTF-8
|
|
||||||
*/
|
|
||||||
LIBVGMSTREAM_API bool libvgmstream_tags_next_tag(libvgmstream_tags_t* tags);
|
|
||||||
|
|
||||||
|
|
||||||
/* Closes tags. */
|
|
||||||
LIBVGMSTREAM_API void libvgmstream_tags_free(libvgmstream_tags_t* tags);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
#endif
|
|
@ -1,25 +0,0 @@
|
|||||||
#ifndef _API_VERSION_H_
|
|
||||||
#define _API_VERSION_H_
|
|
||||||
#include "api.h"
|
|
||||||
#if LIBVGMSTREAM_ENABLE
|
|
||||||
|
|
||||||
/* Current API version.
|
|
||||||
* - only refers to the API itself, as changes related to formats/etc don't alter this (since they are usually additive)
|
|
||||||
* - vgmstream's features are mostly stable, but this API may be tweaked from time to time
|
|
||||||
*/
|
|
||||||
#define LIBVGMSTREAM_API_VERSION_MAJOR 1 // breaking API/ABI changes
|
|
||||||
#define LIBVGMSTREAM_API_VERSION_MINOR 0 // compatible API/ABI changes
|
|
||||||
#define LIBVGMSTREAM_API_VERSION_PATCH 0 // fixes
|
|
||||||
|
|
||||||
/* returns API version in hex format: 0xMMmmpppp = MM-major, mm-minor, pppp-patch
|
|
||||||
* - use when loading vgmstream as a dynamic library to ensure API/ABI compatibility
|
|
||||||
*/
|
|
||||||
LIBVGMSTREAM_API uint32_t libvgmstream_get_version(void);
|
|
||||||
|
|
||||||
/* CHANGELOG:
|
|
||||||
*
|
|
||||||
* - 1.0.0: initial version
|
|
||||||
*/
|
|
||||||
|
|
||||||
#endif
|
|
||||||
#endif
|
|
@ -1,6 +1,7 @@
|
|||||||
#ifndef _API_INTERNAL_H_
|
#ifndef _API_INTERNAL_H_
|
||||||
#define _API_INTERNAL_H_
|
#define _API_INTERNAL_H_
|
||||||
#include "../api.h"
|
#include "../libvgmstream.h"
|
||||||
|
#include "../util/log.h"
|
||||||
#include "../vgmstream.h"
|
#include "../vgmstream.h"
|
||||||
#include "plugins.h"
|
#include "plugins.h"
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#define _MIXING_H_
|
#define _MIXING_H_
|
||||||
|
|
||||||
#include "../vgmstream.h"
|
#include "../vgmstream.h"
|
||||||
|
#include "../util/log.h"
|
||||||
|
|
||||||
/* Applies mixing commands to the sample buffer. Mixing must be externally enabled and
|
/* Applies mixing commands to the sample buffer. Mixing must be externally enabled and
|
||||||
* outbuf must big enough to hold output_channels*samples_to_do */
|
* outbuf must big enough to hold output_channels*samples_to_do */
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include "../vgmstream.h"
|
#include "../vgmstream.h"
|
||||||
#include "../util/reader_sf.h"
|
#include "../util/reader_sf.h"
|
||||||
#include "../util/reader_get_nibbles.h"
|
#include "../util/reader_get_nibbles.h"
|
||||||
|
#include "../util/log.h"
|
||||||
//todo remove
|
//todo remove
|
||||||
#include "libs/clhca.h"
|
#include "libs/clhca.h"
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include "../streamtypes.h"
|
#include "../streamtypes.h"
|
||||||
#include "../vgmstream.h"
|
#include "../vgmstream.h"
|
||||||
#include "../util/reader_sf.h"
|
#include "../util/reader_sf.h"
|
||||||
|
#include "../util/log.h"
|
||||||
|
|
||||||
/* blocked layouts */
|
/* blocked layouts */
|
||||||
void render_vgmstream_blocked(sample_t* buffer, int32_t sample_count, VGMSTREAM* vgmstream);
|
void render_vgmstream_blocked(sample_t* buffer, int32_t sample_count, VGMSTREAM* vgmstream);
|
||||||
|
360
src/libvgmstream.h
Normal file
360
src/libvgmstream.h
Normal file
@ -0,0 +1,360 @@
|
|||||||
|
/* libvgmstream: vgmstream's public API */
|
||||||
|
|
||||||
|
#ifndef _LIBVGMSTREAM_H_
|
||||||
|
#define _LIBVGMSTREAM_H_
|
||||||
|
|
||||||
|
//#define LIBVGMSTREAM_ENABLE 1
|
||||||
|
#if LIBVGMSTREAM_ENABLE
|
||||||
|
|
||||||
|
/* By default vgmstream behaves like a decoder (decode samples until stream end), but you can configure
|
||||||
|
* it to loop N times or even downmix. In other words, it also behaves a bit like a player.
|
||||||
|
* It exposes multiple convenience stuff mainly for various plugins that mostly repeat the same features.
|
||||||
|
* All this may make the API still WIP and a bit twisted, probably will improve later. Probably.
|
||||||
|
*
|
||||||
|
* Notes:
|
||||||
|
* - now there is an API internals (vgmstream.h) may change in the future
|
||||||
|
* - may dynamically allocate stuff as needed (mainly some buffers, but varies per format)
|
||||||
|
* - some details described in the API may not happen at the moment (defined for future changes)
|
||||||
|
* - uses long-winded libvgmstream_* names since internals alredy use the vgmstream_* 'namespace', #define as needed
|
||||||
|
* - c-strings should be in UTF-8
|
||||||
|
*
|
||||||
|
* Basic usage (also see api_example.c):
|
||||||
|
* - libvgmstream_init(...) // base context
|
||||||
|
* - libvgmstream_setup(...) // config if needed
|
||||||
|
* - libvgmstream_open(...) // setup format
|
||||||
|
* - libvgmstream_play(...) // main decode
|
||||||
|
* - output samples + repeat libvgmstream_play until stream is done
|
||||||
|
* - libvgmstream_free(...) // cleanup
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* DEFINES */
|
||||||
|
|
||||||
|
///* standard C param call and name mangling (to avoid __stdcall / .defs) */
|
||||||
|
//#define LIBVGMSTREAM_CALL __cdecl //needed?
|
||||||
|
//LIBVGMSTREAM_API (type) LIBVGMSTREAM_CALL libvgmstream_function(...);
|
||||||
|
|
||||||
|
/* external function behavior (for compile time) */
|
||||||
|
#if defined(LIBVGMSTREAM_EXPORT)
|
||||||
|
#define LIBVGMSTREAM_API __declspec(dllexport) /* when exporting/creating vgmstream DLL */
|
||||||
|
#elif defined(LIBVGMSTREAM_IMPORT)
|
||||||
|
#define LIBVGMSTREAM_API __declspec(dllimport) /* when importing/linking vgmstream DLL */
|
||||||
|
#else
|
||||||
|
#define LIBVGMSTREAM_API /* nothing, internal/default */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include "libvgmstream_streamfile.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* VERSION */
|
||||||
|
|
||||||
|
/* Current API version, for static checks.
|
||||||
|
* - only refers to the API itself, changes related to formats/etc don't alter this
|
||||||
|
* - vgmstream's features are mostly stable, but this API may be tweaked from time to time
|
||||||
|
*/
|
||||||
|
#define LIBVGMSTREAM_API_VERSION_MAJOR 1 // breaking API/ABI changes
|
||||||
|
#define LIBVGMSTREAM_API_VERSION_MINOR 0 // compatible API/ABI changes
|
||||||
|
#define LIBVGMSTREAM_API_VERSION_PATCH 0 // fixes
|
||||||
|
|
||||||
|
/* Current API version, for dynamic checks. returns hex value: 0xMMmmpppp = MM-major, mm-minor, pppp-patch
|
||||||
|
* - use when loading vgmstream as a dynamic library to ensure API/ABI compatibility
|
||||||
|
*/
|
||||||
|
LIBVGMSTREAM_API uint32_t libvgmstream_get_version(void);
|
||||||
|
|
||||||
|
/* CHANGELOG:
|
||||||
|
* - 1.0.0: initial version
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* DECODE */
|
||||||
|
|
||||||
|
/* interleaved samples: buf[0]=ch0, buf[1]=ch1, buf[2]=ch0, buf[3]=ch0, ... */
|
||||||
|
typedef enum {
|
||||||
|
LIBVGMSTREAM_SAMPLE_PCM16 = 0x01,
|
||||||
|
LIBVGMSTREAM_SAMPLE_PCM24 = 0x02,
|
||||||
|
LIBVGMSTREAM_SAMPLE_PCM32 = 0x03,
|
||||||
|
LIBVGMSTREAM_SAMPLE_FLOAT = 0x04,
|
||||||
|
} libvgmstream_sample_t;
|
||||||
|
|
||||||
|
/* current song info, may be copied around (values are info-only) */
|
||||||
|
typedef struct {
|
||||||
|
/* main (always set) */
|
||||||
|
int channels; // output channels
|
||||||
|
int sample_rate; // output sample rate
|
||||||
|
|
||||||
|
libvgmstream_sample_t sample_type; // output buffer's sample type
|
||||||
|
int sample_size; // derived from sample_type (pcm16=0x02, float=0x04, etc)
|
||||||
|
|
||||||
|
/* extra info (may be 0 if not known or not relevant) */
|
||||||
|
uint32_t channel_layout; // standard WAVE bitflags
|
||||||
|
|
||||||
|
int subsong_index; // 0 = none, N = loaded subsong N (1=first)
|
||||||
|
int subsong_count; // 0 = format has no concept of subsongs, N = has N subsongs
|
||||||
|
// ** 1 = format has subsongs, and only 1 for current file
|
||||||
|
|
||||||
|
int input_channels; // original file's channels before downmixing (if any)
|
||||||
|
//int interleave; // when file is interleaved
|
||||||
|
//int interleave_first; // when file is interleaved
|
||||||
|
//int interleave_last; // when file is interleaved
|
||||||
|
//int frame_size; // when file has some configurable frame size
|
||||||
|
|
||||||
|
/* sample info (may not be used depending on config) */
|
||||||
|
int64_t sample_count; // file's max samples (not final play duration)
|
||||||
|
int64_t loop_start; // loop start sample
|
||||||
|
int64_t loop_end; // loop end sample
|
||||||
|
bool loop_flag; // if file loops (false + defined loops means looping was forcefully disabled)
|
||||||
|
|
||||||
|
bool play_forever; // if file loops forever based on current config (meaning _play never stops)
|
||||||
|
int64_t play_samples; // totals after all calculations (after applying loop/fade/etc config)
|
||||||
|
// ** may not be 100% accurate in some cases (check decoder's 'done' flag to stop)
|
||||||
|
// ** if play_forever is set this is still provided for reference based on non-forever config
|
||||||
|
|
||||||
|
int stream_bitrate; // average bitrate of the subsong (slightly bloated vs codec_bitrate; incorrect in rare cases)
|
||||||
|
//int codec_bitrate; // average bitrate of the codec data
|
||||||
|
// ** not possible / slow to calculate in most cases
|
||||||
|
|
||||||
|
/* descriptions */
|
||||||
|
char codec_name[128]; //
|
||||||
|
char layout_name[128]; //
|
||||||
|
char meta_name[128]; // (not internal "tag" metadata)
|
||||||
|
char stream_name[256]; // some internal name or representation, not always useful
|
||||||
|
// ** these are a bit big for a struct, but the typical use case of vgsmtream is opening a file > immediately
|
||||||
|
// query description and since libvgmstream returns its own copy it shouldn't be too much of a problem
|
||||||
|
// ** (may be separated later)
|
||||||
|
|
||||||
|
/* misc */
|
||||||
|
//bool rough_samples; // signal cases where loop points or sample count can't exactly reflect actual behavior
|
||||||
|
|
||||||
|
int format_internal_id; // when reopening subfiles or similar formats without checking other all possible formats
|
||||||
|
// ** this value WILL change without warning between vgmstream versions/commits
|
||||||
|
|
||||||
|
} libvgmstream_format_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
void* buf; // current decoded buf (valid after _decode until next call; may change between calls)
|
||||||
|
int buf_samples; // current buffer samples (0 is possible in some cases)
|
||||||
|
int buf_bytes; // current buffer bytes (channels * sample_size * samples)
|
||||||
|
|
||||||
|
bool done; // when stream is done based on config
|
||||||
|
// ** note that with play_forever this flag is never set
|
||||||
|
} libvgmstream_decoder_t;
|
||||||
|
|
||||||
|
/* vgmstream context/handle */
|
||||||
|
typedef struct {
|
||||||
|
void* priv; // internal data
|
||||||
|
|
||||||
|
/* pointers for easier ABI compatibility */
|
||||||
|
const libvgmstream_format_t* format; // current song info, updated on _open
|
||||||
|
libvgmstream_decoder_t* decoder; // updated on each _decode call
|
||||||
|
|
||||||
|
} libvgmstream_t;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Inits the vgmstream context
|
||||||
|
* - returns NULL on error
|
||||||
|
*/
|
||||||
|
LIBVGMSTREAM_API libvgmstream_t* libvgmstream_init(void);
|
||||||
|
|
||||||
|
/* Frees the vgmstream context and any other internal stuff.
|
||||||
|
*/
|
||||||
|
LIBVGMSTREAM_API void libvgmstream_free(libvgmstream_t* lib);
|
||||||
|
|
||||||
|
|
||||||
|
/* configures how vgmstream behaves internally when playing a file */
|
||||||
|
typedef struct {
|
||||||
|
bool disable_config_override; // ignore forced (TXTP) config
|
||||||
|
bool allow_play_forever; // must allow manually as some cases a TXTP may set loop forever but client may not handle it
|
||||||
|
|
||||||
|
bool play_forever; // keeps looping forever (file must have loop_flag set)
|
||||||
|
bool ignore_loop; // ignores loops points
|
||||||
|
bool force_loop; // enables full loops (0..samples) if file doesn't have loop points
|
||||||
|
bool really_force_loop; // forces full loops (0..samples) even if file has loop points
|
||||||
|
bool ignore_fade; // don't fade after N loops and play remaning stream (for files with outros)
|
||||||
|
|
||||||
|
double loop_count; // target loops (values like 1.5 are ok)
|
||||||
|
double fade_time; // fade period after target loops
|
||||||
|
double fade_delay; // fade delay after target loops
|
||||||
|
|
||||||
|
int auto_downmix_channels; // downmixing if vgmstream's channels are higher than value
|
||||||
|
// ** for players that can only handle N channels
|
||||||
|
// ** this type of downmixing is very simplistic and not recommended
|
||||||
|
|
||||||
|
bool force_pcm16; // forces output buffer to be remixed into PCM16
|
||||||
|
|
||||||
|
} libvgmstream_config_t;
|
||||||
|
|
||||||
|
/* pass default config, that will be applied to song on open
|
||||||
|
* - invalid config or complex cases (ex. some TXTP) may ignore these settings.
|
||||||
|
* - called without a song loaded (before _open or after _close), otherwise ignored.
|
||||||
|
* - without config vgmstream will decode the current stream once
|
||||||
|
*/
|
||||||
|
LIBVGMSTREAM_API void libvgmstream_setup(libvgmstream_t* lib, libvgmstream_config_t* cfg);
|
||||||
|
|
||||||
|
|
||||||
|
/* configures how vgmstream opens the format */
|
||||||
|
typedef struct {
|
||||||
|
libvgmstream_streamfile_t* libsf; // custom IO streamfile that provides reader info for vgmstream
|
||||||
|
// ** not needed after _open and should be closed, as vgmstream re-opens its own SFs internally as needed
|
||||||
|
|
||||||
|
int subsong; // target subsong (1..N) or 0 = default/first
|
||||||
|
// ** to check if a file has subsongs, _open first + check format->total_subsongs (then _open 2nd, 3rd, etc)
|
||||||
|
|
||||||
|
int format_internal_id; // force a format (for example when loading new subsong of the same archive)
|
||||||
|
|
||||||
|
int stereo_track; // forces vgmstream to decode one 2ch+2ch+2ch... 'track' and discard other channels, where 0 = disabled, 1..N = Nth track
|
||||||
|
|
||||||
|
} libvgmstream_options_t;
|
||||||
|
|
||||||
|
/* Opens file based on config and prepares it to play if supported.
|
||||||
|
* - returns < 0 on error (file not recognised, invalid subsong index, etc)
|
||||||
|
* - will close currently loaded song if needed
|
||||||
|
*/
|
||||||
|
LIBVGMSTREAM_API int libvgmstream_open(libvgmstream_t* lib, libvgmstream_options_t* open_options);
|
||||||
|
|
||||||
|
/* Closes current song; may still use libvgmstream to open other songs
|
||||||
|
*/
|
||||||
|
LIBVGMSTREAM_API void libvgmstream_close(libvgmstream_t* lib);
|
||||||
|
|
||||||
|
|
||||||
|
/* Decodes next batch of samples
|
||||||
|
* - vgmstream supplies its own buffer, updated on lib->decoder->* values (may change between calls)
|
||||||
|
* - returns < 0 on error
|
||||||
|
*/
|
||||||
|
LIBVGMSTREAM_API int libvgmstream_play(libvgmstream_t* lib);
|
||||||
|
|
||||||
|
/* Same as _play, but fills some external buffer (also updates lib->decoder->* values)
|
||||||
|
* - returns < 0 on error, or N = number of filled samples.
|
||||||
|
* - buf must be at least as big as channels * sample_size * buf_samples
|
||||||
|
* - needs copying around from internal bufs so may be slightly slower; mainly for cases when you have buf constraints
|
||||||
|
*/
|
||||||
|
LIBVGMSTREAM_API int libvgmstream_fill(libvgmstream_t* lib, void* buf, int buf_samples);
|
||||||
|
|
||||||
|
/* Gets current position within the song.
|
||||||
|
* - return < 0 on error
|
||||||
|
*/
|
||||||
|
LIBVGMSTREAM_API int64_t libvgmstream_get_play_position(libvgmstream_t* lib);
|
||||||
|
|
||||||
|
/* Seeks to absolute position. Will clamp incorrect values such as seeking before/past playable length.
|
||||||
|
*/
|
||||||
|
LIBVGMSTREAM_API void libvgmstream_seek(libvgmstream_t* lib, int64_t sample);
|
||||||
|
|
||||||
|
/* Reset current song
|
||||||
|
*/
|
||||||
|
LIBVGMSTREAM_API void libvgmstream_reset(libvgmstream_t* lib);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* HELPERS */
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
LIBVGMSTREAM_LOG_LEVEL_ALL = 0,
|
||||||
|
LIBVGMSTREAM_LOG_LEVEL_DEBUG = 20,
|
||||||
|
LIBVGMSTREAM_LOG_LEVEL_INFO = 30,
|
||||||
|
LIBVGMSTREAM_LOG_LEVEL_NONE = 100,
|
||||||
|
} libvgmstream_loglevel_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
libvgmstream_loglevel_t level; // log level
|
||||||
|
void (*callback)(int level, const char* str); // log callback
|
||||||
|
bool stdout_callback; // use default log callback rather than user supplied
|
||||||
|
} libvgmstream_log_t;
|
||||||
|
|
||||||
|
/* Defines a global log callback, as vgmstream sometimes communicates format issues to the user.
|
||||||
|
* - note that log is currently set globally rather than per libvgmstream_t
|
||||||
|
*/
|
||||||
|
LIBVGMSTREAM_API void libvgmstream_set_log(libvgmstream_log_t* cfg);
|
||||||
|
|
||||||
|
|
||||||
|
/* Returns a list of supported extensions (WARNING: it's pretty big), such as "adx", "dsp", etc.
|
||||||
|
* Mainly for plugins that want to know which extensions are supported.
|
||||||
|
* - returns NULL if no size is provided
|
||||||
|
*/
|
||||||
|
LIBVGMSTREAM_API const char** libvgmstream_get_extensions(size_t* size);
|
||||||
|
|
||||||
|
/* Same as above, buf returns a list what vgmstream considers "common" formats (such as "wav", "ogg"),
|
||||||
|
* which usually one doesn't want to associate to vgmstream.
|
||||||
|
* - returns NULL if no size is provided
|
||||||
|
*/
|
||||||
|
LIBVGMSTREAM_API const char** libvgmstream_get_common_extensions(size_t* size);
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
bool is_extension; /* set if filename is just an extension */
|
||||||
|
bool skip_default; /* set if shouldn't check default formats */
|
||||||
|
bool reject_extensionless; /* set if player can't play extensionless files */
|
||||||
|
bool accept_unknown; /* set to allow any extension (for txth) */
|
||||||
|
bool accept_common; /* set to allow known-but-common extension (when player has plugin priority) */
|
||||||
|
} libvgmstream_valid_t;
|
||||||
|
|
||||||
|
/* Returns if vgmstream can parse a filename by extension, to reject some files earlier
|
||||||
|
* - doesn't check file contents (that's only done on _open)
|
||||||
|
* - config may be NULL
|
||||||
|
* - mainly for plugins that fail early; libvgmstream doesn't use this
|
||||||
|
*/
|
||||||
|
LIBVGMSTREAM_API bool libvgmstream_is_valid(const char* filename, libvgmstream_valid_t* cfg);
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
bool force_title; // TODO: what was this for?
|
||||||
|
bool subsong_range; // print a range of possible subsongs after title 'filename#1~N'
|
||||||
|
bool remove_extension; // remove extension from passed filename
|
||||||
|
bool remove_archive; // remove '(archive)|(subfile)' format of some plugins
|
||||||
|
const char* filename; // base file's filename
|
||||||
|
// ** note that sometimes vgmstream doesn't have/know the original name, so it's needed again here
|
||||||
|
} libvgmstream_title_t;
|
||||||
|
|
||||||
|
/* Get a simple title for plugins, derived from internal stream name if available
|
||||||
|
* - valid after _open
|
||||||
|
*/
|
||||||
|
LIBVGMSTREAM_API int libvgmstream_get_title(libvgmstream_t* lib, libvgmstream_title_t* cfg, char* buf, int buf_len);
|
||||||
|
|
||||||
|
/* Writes a description of the current song into dst. Will always be null-terminated.
|
||||||
|
* - returns < 0 if file was truncated, though will still succeed.
|
||||||
|
*/
|
||||||
|
LIBVGMSTREAM_API int libvgmstream_format_describe(libvgmstream_t* lib, char* dst, int dst_size);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* TAGS */
|
||||||
|
|
||||||
|
/* Meant to be a simple implementation; feel free to ignore and roll your own (or use another tags plugin).
|
||||||
|
* Doesn't need a main libvgmstream as tags aren't tied to loaded songs. */
|
||||||
|
|
||||||
|
/* tag state */
|
||||||
|
typedef struct {
|
||||||
|
void* priv; // internal data
|
||||||
|
|
||||||
|
const char* key; // current key
|
||||||
|
const char* val; // current value
|
||||||
|
} libvgmstream_tags_t;
|
||||||
|
|
||||||
|
/* Initializes tags.
|
||||||
|
* - libsf should point to a !tags.m3u file
|
||||||
|
* - unlike libvgmstream_open, sf tagfile must be valid during the tag extraction process.
|
||||||
|
*/
|
||||||
|
LIBVGMSTREAM_API libvgmstream_tags_t* libvgmstream_tags_init(libvgmstream_streamfile_t* libsf);
|
||||||
|
|
||||||
|
/* Finds tags for a new filename. Must be called first before extracting tags.
|
||||||
|
*/
|
||||||
|
LIBVGMSTREAM_API void libvgmstream_tags_find(libvgmstream_tags_t* tags, const char* target_filename);
|
||||||
|
|
||||||
|
/* Extracts next valid tag in tagfile to key/val.
|
||||||
|
* - returns false if no more tags are found (meant to be called repeatedly until false)
|
||||||
|
* - key/values are trimmed of beginning/end whitespaces and values are in UTF-8
|
||||||
|
*/
|
||||||
|
LIBVGMSTREAM_API bool libvgmstream_tags_next_tag(libvgmstream_tags_t* tags);
|
||||||
|
|
||||||
|
/* Closes tags. */
|
||||||
|
LIBVGMSTREAM_API void libvgmstream_tags_free(libvgmstream_tags_t* tags);
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#endif
|
@ -81,11 +81,8 @@
|
|||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="api.h" />
|
<ClInclude Include="api.h" />
|
||||||
<ClInclude Include="api_decode.h" />
|
<ClInclude Include="libvgmstream.h" />
|
||||||
<ClInclude Include="api_helpers.h" />
|
<ClInclude Include="libvgmstream_streamfile.h" />
|
||||||
<ClInclude Include="api_streamfile.h" />
|
|
||||||
<ClInclude Include="api_tags.h" />
|
|
||||||
<ClInclude Include="api_version.h" />
|
|
||||||
<ClInclude Include="streamfile.h" />
|
<ClInclude Include="streamfile.h" />
|
||||||
<ClInclude Include="streamtypes.h" />
|
<ClInclude Include="streamtypes.h" />
|
||||||
<ClInclude Include="util.h" />
|
<ClInclude Include="util.h" />
|
||||||
|
@ -77,19 +77,10 @@
|
|||||||
<ClInclude Include="api.h">
|
<ClInclude Include="api.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="api_decode.h">
|
<ClInclude Include="libvgmstream.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="api_helpers.h">
|
<ClInclude Include="libvgmstream_streamfile.h">
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="api_streamfile.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="api_tags.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="api_version.h">
|
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="streamfile.h">
|
<ClInclude Include="streamfile.h">
|
||||||
|
@ -1,18 +1,13 @@
|
|||||||
#ifndef _API_STREAMFILE_H_
|
#ifndef _LIBVGMSTREAM_STREAMFILE_H_
|
||||||
#define _API_STREAMFILE_H_
|
#define _LIBVGMSTREAM_STREAMFILE_H_
|
||||||
#include "api.h"
|
#include "libvgmstream.h"
|
||||||
#if LIBVGMSTREAM_ENABLE
|
#if LIBVGMSTREAM_ENABLE
|
||||||
|
|
||||||
/* vgmstream's IO API, defined as a "streamfile" (SF).
|
/* vgmstream's IO API, defined as a "streamfile" (SF).
|
||||||
*
|
*
|
||||||
* Compared to typical IO, vgmstream has some extra needs that roughly assume there is an underlying filesystem (as usual in games):
|
* vgmstream roughly assumes there is an underlying filesystem (as usual in games): seeking + reading from arbitrary offsets,
|
||||||
* - seeking + reading from arbitrary offsets: header not in the beginning of a stream, rewinding back when looping, etc
|
* opening companion files, filename tests, etc. If your case is too different you may still create a partial streamfile: returning
|
||||||
* - opening other streamfiles: reopening a copy of the current SF, formats with split header + data, decryption files, etc
|
* a fake filename, only handling "open" that reopens itself (same filename), etc. Simpler formats will probably work just fine.
|
||||||
* - extracting the filename: opening similarly named companion files, basic extension sanity checks, heuristics for odd cases, etc
|
|
||||||
*
|
|
||||||
* If your IO can't fully satisfy those constraints, it may still be possible to create a streamfile that just simulates part of it.
|
|
||||||
* For example, returning a fake filename, and only handling "open" that reopens itself (same filename), while returning default/incorrect
|
|
||||||
* values for non-handled operations. Simpler formats will probably work just fine.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@ -28,26 +23,26 @@ typedef struct libvgmstream_streamfile_t {
|
|||||||
//uint32_t flags; // info flags for vgmstream
|
//uint32_t flags; // info flags for vgmstream
|
||||||
void* user_data; // any internal structure
|
void* user_data; // any internal structure
|
||||||
|
|
||||||
/* read 'length' data at internal offset to 'dst' (implicit seek if needed)
|
/* read 'length' data at internal offset to 'dst'
|
||||||
* - assumes 0 = failure/EOF
|
* - assumes 0 = failure/EOF
|
||||||
*/
|
*/
|
||||||
int (*read)(void* user_data, uint8_t* dst, int dst_size);
|
int (*read)(void* user_data, uint8_t* dst, int dst_size);
|
||||||
|
|
||||||
/* seek to offset
|
/* seek to offset
|
||||||
* - note that due to how vgmstream works this is a fairly common operation (to be optimized later)
|
* - note that vgmstream needs to seek + read fairly often (to be optimized later)
|
||||||
*/
|
*/
|
||||||
int64_t (*seek)(void* user_data, int64_t offset, int whence);
|
int64_t (*seek)(void* user_data, int64_t offset, int whence);
|
||||||
|
|
||||||
/* get max offset
|
/* get max offset (typically for checks or calculations)
|
||||||
*/
|
*/
|
||||||
int64_t (*get_size)(void* user_data);
|
int64_t (*get_size)(void* user_data);
|
||||||
|
|
||||||
/* get current filename
|
/* get current filename (used to open same or other streamfiles and heuristics; no need to be a real path)
|
||||||
*/
|
*/
|
||||||
const char* (*get_name)(void* user_data);
|
const char* (*get_name)(void* user_data);
|
||||||
|
|
||||||
/* open another streamfile from filename (may be some path/protocol, or same as current get_name = reopen)
|
/* open another streamfile from filename (may be some path/protocol, or same as current get_name = reopen)
|
||||||
* - vgmstream mainly opens stuff based on current get_name (relative), so there shouldn't be need to transform this path
|
* - vgmstream opens stuff based on current get_name (relative), so there shouldn't be need to transform this path
|
||||||
*/
|
*/
|
||||||
struct libvgmstream_streamfile_t* (*open)(void* user_data, const char* filename);
|
struct libvgmstream_streamfile_t* (*open)(void* user_data, const char* filename);
|
||||||
|
|
@ -5,6 +5,7 @@
|
|||||||
#include "../util/reader_sf.h"
|
#include "../util/reader_sf.h"
|
||||||
#include "../util/reader_text.h"
|
#include "../util/reader_text.h"
|
||||||
#include "../util/sf_utils.h"
|
#include "../util/sf_utils.h"
|
||||||
|
#include "../util/log.h"
|
||||||
|
|
||||||
typedef VGMSTREAM* (*init_vgmstream_t)(STREAMFILE* sf);
|
typedef VGMSTREAM* (*init_vgmstream_t)(STREAMFILE* sf);
|
||||||
|
|
||||||
|
@ -23,7 +23,6 @@
|
|||||||
|
|
||||||
#include "streamfile.h"
|
#include "streamfile.h"
|
||||||
#include "vgmstream_types.h"
|
#include "vgmstream_types.h"
|
||||||
#include "util/log.h"
|
|
||||||
|
|
||||||
#ifdef VGM_USE_MP4V2
|
#ifdef VGM_USE_MP4V2
|
||||||
#define MP4V2_NO_STDINT_DEFS
|
#define MP4V2_NO_STDINT_DEFS
|
||||||
@ -38,14 +37,14 @@
|
|||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int config_set; /* some of the mods below are set */
|
bool config_set; /* some of the mods below are set */
|
||||||
|
|
||||||
/* modifiers */
|
/* modifiers */
|
||||||
int play_forever;
|
bool play_forever;
|
||||||
int ignore_loop;
|
bool ignore_loop;
|
||||||
int force_loop;
|
bool force_loop;
|
||||||
int really_force_loop;
|
bool really_force_loop;
|
||||||
int ignore_fade;
|
bool ignore_fade;
|
||||||
|
|
||||||
/* processing */
|
/* processing */
|
||||||
double loop_count;
|
double loop_count;
|
||||||
@ -66,18 +65,18 @@ typedef struct {
|
|||||||
double pad_end_s;
|
double pad_end_s;
|
||||||
|
|
||||||
/* internal flags */
|
/* internal flags */
|
||||||
int pad_begin_set;
|
bool pad_begin_set;
|
||||||
int trim_begin_set;
|
bool trim_begin_set;
|
||||||
int body_time_set;
|
bool body_time_set;
|
||||||
int loop_count_set;
|
bool loop_count_set;
|
||||||
int trim_end_set;
|
bool trim_end_set;
|
||||||
int fade_delay_set;
|
bool fade_delay_set;
|
||||||
int fade_time_set;
|
bool fade_time_set;
|
||||||
int pad_end_set;
|
bool pad_end_set;
|
||||||
|
|
||||||
/* for lack of a better place... */
|
/* for lack of a better place... */
|
||||||
int is_txtp;
|
bool is_txtp;
|
||||||
int is_mini_txtp;
|
bool is_mini_txtp;
|
||||||
|
|
||||||
} play_config_t;
|
} play_config_t;
|
||||||
|
|
||||||
@ -165,7 +164,7 @@ typedef struct {
|
|||||||
meta_t meta_type; /* type of metadata */
|
meta_t meta_type; /* type of metadata */
|
||||||
|
|
||||||
/* loop config */
|
/* loop config */
|
||||||
int loop_flag; /* is this stream looped? */
|
bool loop_flag; /* is this stream looped? */
|
||||||
int32_t loop_start_sample; /* first sample of the loop (included in the loop) */
|
int32_t loop_start_sample; /* first sample of the loop (included in the loop) */
|
||||||
int32_t loop_end_sample; /* last sample of the loop (not included in the loop) */
|
int32_t loop_end_sample; /* last sample of the loop (not included in the loop) */
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user