2008-01-31 07:04:26 +01:00
|
|
|
#include "vgmstream.h"
|
|
|
|
#include "fmt/adx.h"
|
2008-02-04 16:20:20 +01:00
|
|
|
#include "fmt/brstm.h"
|
2008-01-31 07:04:26 +01:00
|
|
|
#include "fmt/interleave.h"
|
2008-02-05 01:03:39 +01:00
|
|
|
#include "fmt/nolayout.h"
|
2008-01-31 07:04:26 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* List of functions that will recognize files. These should correspond pretty
|
|
|
|
* directly to the metadata types
|
|
|
|
*/
|
2008-02-04 16:20:20 +01:00
|
|
|
#define INIT_VGMSTREAM_FCNS 2
|
2008-01-31 07:04:26 +01:00
|
|
|
VGMSTREAM * (*init_vgmstream_fcns[INIT_VGMSTREAM_FCNS])(const char * const) = {
|
|
|
|
init_vgmstream_adx,
|
2008-02-04 16:20:20 +01:00
|
|
|
init_vgmstream_brstm,
|
2008-01-31 07:04:26 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
/* format detection and VGMSTREAM setup */
|
|
|
|
VGMSTREAM * init_vgmstream(const char * const filename) {
|
|
|
|
int i;
|
|
|
|
|
|
|
|
/* try a series of formats, see which works */
|
|
|
|
for (i=0;i<INIT_VGMSTREAM_FCNS;i++) {
|
|
|
|
VGMSTREAM * vgmstream = (init_vgmstream_fcns[i])(filename);
|
|
|
|
if (vgmstream) {
|
|
|
|
/* everything should have a reasonable sample rate */
|
|
|
|
if (!check_sample_rate(vgmstream->sample_rate)) {
|
|
|
|
close_vgmstream(vgmstream);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
/* save start things so we can restart for seeking */
|
|
|
|
memcpy(vgmstream->start_ch,vgmstream->ch,sizeof(VGMSTREAMCHANNEL)*vgmstream->channels);
|
|
|
|
vgmstream->start_block_offset = vgmstream->current_block_offset;
|
|
|
|
return vgmstream;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* simply allocate memory for the VGMSTREAM and its channels */
|
|
|
|
VGMSTREAM * allocate_vgmstream(int channel_count, int looped) {
|
|
|
|
VGMSTREAM * vgmstream;
|
|
|
|
VGMSTREAMCHANNEL * channels;
|
|
|
|
VGMSTREAMCHANNEL * start_channels;
|
|
|
|
VGMSTREAMCHANNEL * loop_channels;
|
|
|
|
|
|
|
|
vgmstream = calloc(1,sizeof(VGMSTREAM));
|
|
|
|
if (!vgmstream) return NULL;
|
|
|
|
|
|
|
|
channels = calloc(channel_count,sizeof(VGMSTREAMCHANNEL));
|
|
|
|
if (!channels) {
|
|
|
|
free(vgmstream);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
vgmstream->ch = channels;
|
|
|
|
vgmstream->channels = channel_count;
|
|
|
|
|
|
|
|
start_channels = calloc(channel_count,sizeof(VGMSTREAMCHANNEL));
|
|
|
|
if (!start_channels) {
|
|
|
|
free(vgmstream);
|
|
|
|
free(channels);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
vgmstream->start_ch = start_channels;
|
|
|
|
|
|
|
|
if (looped) {
|
|
|
|
loop_channels = calloc(channel_count,sizeof(VGMSTREAMCHANNEL));
|
|
|
|
if (!loop_channels) {
|
|
|
|
free(vgmstream);
|
|
|
|
free(channels);
|
|
|
|
free(start_channels);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
vgmstream->loop_ch = loop_channels;
|
|
|
|
}
|
|
|
|
|
|
|
|
vgmstream->loop_flag = looped;
|
|
|
|
|
|
|
|
return vgmstream;
|
|
|
|
}
|
|
|
|
|
|
|
|
void close_vgmstream(VGMSTREAM * vgmstream) {
|
|
|
|
int i;
|
|
|
|
if (!vgmstream) return;
|
|
|
|
|
|
|
|
for (i=0;i<vgmstream->channels;i++)
|
|
|
|
if (vgmstream->ch[i].streamfile)
|
|
|
|
close_streamfile(vgmstream->ch[i].streamfile);
|
|
|
|
|
|
|
|
if (vgmstream->loop_ch) free(vgmstream->loop_ch);
|
|
|
|
if (vgmstream->start_ch) free(vgmstream->start_ch);
|
|
|
|
if (vgmstream->ch) free(vgmstream->ch);
|
|
|
|
|
|
|
|
free(vgmstream);
|
|
|
|
}
|
|
|
|
|
|
|
|
int32_t get_vgmstream_play_samples(double looptimes, double fadetime, VGMSTREAM * vgmstream) {
|
|
|
|
if (vgmstream->loop_flag) {
|
|
|
|
return vgmstream->loop_start_sample+(vgmstream->loop_end_sample-vgmstream->loop_start_sample)*looptimes+fadetime*vgmstream->sample_rate;
|
|
|
|
} else return vgmstream->num_samples;
|
|
|
|
}
|
|
|
|
|
|
|
|
void render_vgmstream(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream) {
|
|
|
|
switch (vgmstream->layout_type) {
|
|
|
|
case layout_interleave:
|
2008-02-04 16:20:20 +01:00
|
|
|
case layout_interleave_shortblock:
|
2008-01-31 07:04:26 +01:00
|
|
|
render_vgmstream_interleave(buffer,sample_count,vgmstream);
|
|
|
|
break;
|
2008-02-05 01:03:39 +01:00
|
|
|
case layout_none:
|
|
|
|
render_vgmstream_nolayout(buffer,sample_count,vgmstream);
|
|
|
|
break;
|
2008-01-31 07:04:26 +01:00
|
|
|
}
|
|
|
|
}
|