From 21b1594b496d29131dd124ffb9e597fbc2ccfaa6 Mon Sep 17 00:00:00 2001 From: Alexey Yakovenko Date: Sat, 19 Dec 2009 12:35:17 +0100 Subject: vtx playback with seeking --- plugins/vtx/ay8912.c | 4 ++ plugins/vtx/vtx.c | 158 ++++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 155 insertions(+), 7 deletions(-) (limited to 'plugins/vtx') diff --git a/plugins/vtx/ay8912.c b/plugins/vtx/ay8912.c index bf79f95c..9ac72245 100644 --- a/plugins/vtx/ay8912.c +++ b/plugins/vtx/ay8912.c @@ -303,9 +303,13 @@ int ayemu_set_stereo(ayemu_ay_t *ay, ayemu_stereo_t stereo_type, int *custom_eq) } +#if 0 #define WARN_IF_REGISTER_GREAT_THAN(r,m) \ if (*(regs + r) > m) \ fprintf(stderr, "ayemu_set_regs: warning: possible bad register data- R%d > %d\n", r, m) +#else +#define WARN_IF_REGISTER_GREAT_THAN(r,m) +#endif /** Assign values for AY registers. diff --git a/plugins/vtx/vtx.c b/plugins/vtx/vtx.c index 42951795..836ded0b 100644 --- a/plugins/vtx/vtx.c +++ b/plugins/vtx/vtx.c @@ -24,8 +24,8 @@ #define min(x,y) ((x)<(y)?(x):(y)) #define max(x,y) ((x)>(y)?(x):(y)) -#define trace(...) { fprintf (stderr, __VA_ARGS__); } -//#define trace(fmt,...) +//#define trace(...) { fprintf (stderr, __VA_ARGS__); } +#define trace(fmt,...) static DB_decoder_t plugin; static DB_functions_t *deadbeef; @@ -33,16 +33,108 @@ static DB_functions_t *deadbeef; static const char * exts[] = { "vtx", NULL }; static const char *filetypes[] = { "VTX", NULL }; +static ayemu_vtx_t *decoder; +static ayemu_ay_t ay; + +#define AY_FRAME_SIZE 14 + +static char regs[AY_FRAME_SIZE]; +static int vtx_pos; +static int left; +static int rate; +static int currentsample; +static int16_t soundbuffer[]; + static int vtx_init (DB_playItem_t *it) { // prepare to decode the track // return -1 on failure + + size_t sz = 0; + char *buf = NULL; + + DB_FILE *fp = deadbeef->fopen (it->fname); + if (!fp) { + trace ("vtx: failed to open file %s\n", it->fname); + return -1; + } + + sz = deadbeef->fgetlength (fp); + if (sz <= 0) { + trace ("vtx: bad file size\n"); + return -1; + } + + buf = malloc (sz); + if (!buf) { + trace ("vtx: out of memory\n"); + return -1; + } + if (deadbeef->fread (buf, 1, sz, fp) != sz) { + trace ("vtx: read failed\n"); + free (buf); + return -1; + } + + decoder = ayemu_vtx_load (buf, sz); + if (!decoder) { + trace ("vtx: ayemu_vtx_load failed\n"); + free (buf); + return -1; + } + trace ("vtx: data=%p, size=%d\n", decoder->regdata, decoder->regdata_size); + + free (buf); + + ayemu_init (&ay); + ayemu_set_chip_type (&ay, decoder->chiptype, NULL); + ayemu_set_chip_freq(&ay, decoder->chipFreq); + ayemu_set_stereo (&ay, decoder->stereo, NULL); + + int samplerate = deadbeef->get_output ()->samplerate (); + + ayemu_set_sound_format (&ay, samplerate, deadbeef->get_output ()->channels (), deadbeef->get_output ()->bitspersample ()); + + left = 0; + rate = deadbeef->get_output ()->channels () * deadbeef->get_output ()->bitspersample () / 8; + vtx_pos = 0; + memset (regs, 0, sizeof (regs)); + plugin.info.bps = deadbeef->get_output ()->bitspersample (); + plugin.info.channels = deadbeef->get_output ()->channels (); + plugin.info.samplerate = samplerate; + plugin.info.readpos = 0; return 0; } static void vtx_free (void) { // free everything allocated in _init + if (decoder) { + ayemu_vtx_free (decoder); + decoder = NULL; + } + ayemu_reset (&ay); +} + +/** Get next 14-bytes frame of AY register data. + * + * Return value: 1 on success, 0 on eof + */ +static int +ayemu_vtx_get_next_frame (ayemu_vtx_t *vtx, char *regs) +{ + int numframes = vtx->regdata_size / AY_FRAME_SIZE; + if (vtx_pos++ >= numframes) { + return 0; + } + else { + int n; + char *p = vtx->regdata + vtx_pos; + for(n = 0 ; n < AY_FRAME_SIZE ; n++, p += numframes) { + regs[n] = *p; + } + return 1; + } } static int @@ -50,7 +142,33 @@ vtx_read_int16 (char *bytes, int size) { // try decode `size' bytes // return number of decoded bytes // return 0 on EOF - return 0; + int initsize = size; + int donow = 0; + + while (size > 0) { + if (left > 0) { + donow = (size > left) ? left : size; + left -= donow; + bytes = ayemu_gen_sound (&ay, (char *)bytes, donow); + size -= donow; + } + else { + if ((ayemu_vtx_get_next_frame (decoder, regs) == 0)) { + break; // eof + } + else { + // number of samples it current frame + left = plugin.info.samplerate / decoder->playerFreq; + // mul by rate to get number of bytes; + left *= rate; + ayemu_set_regs (&ay, regs); + donow = 0; + } + } + } + currentsample += (initsize - size) / 4; + plugin.info.readpos = (float)currentsample / plugin.info.samplerate; + return initsize - size; } static int @@ -58,6 +176,30 @@ vtx_seek_sample (int sample) { // seek to specified sample (frame) // return 0 on success // return -1 on failure + + // get frame + int num_frames = decoder->regdata_size / AY_FRAME_SIZE; + int samples_per_frame = plugin.info.samplerate / decoder->playerFreq; + + // start of frame + vtx_pos = sample / samples_per_frame; + if (vtx_pos >= num_frames) { + return -1; // eof + } + // copy register data + int n; + char *p = decoder->regdata + vtx_pos; + for(n = 0 ; n < AY_FRAME_SIZE ; n++, p += num_frames) { + regs[n] = *p; + } + // set number of bytes left in frame + left = plugin.info.samplerate / decoder->playerFreq - (sample % samples_per_frame); + // mul by rate to get number of bytes + left *= rate; + currentsample = sample; + plugin.info.readpos = (float)currentsample / plugin.info.samplerate; + + return 0; } static int @@ -65,8 +207,7 @@ vtx_seek (float time) { // seek to specified time in seconds // return 0 on success // return -1 on failure - // e.g. return vtx_seek_sample (time * samplerate); - return 0; + return vtx_seek_sample (time * plugin.info.samplerate); } static DB_playItem_t * @@ -97,6 +238,7 @@ vtx_insert (DB_playItem_t *after, const char *fname) { trace ("vtx: failed to read header\n"); return NULL; } + trace ("vtx: datasize: %d\n", hdr->regdata_size); DB_playItem_t *it = deadbeef->pl_item_alloc (); @@ -104,8 +246,10 @@ vtx_insert (DB_playItem_t *after, const char *fname) { it->fname = strdup (fname); it->filetype = filetypes[0]; - int totalsamples = 44100*60*5; - deadbeef->pl_set_item_duration (it, (float)totalsamples/hdr->playerFreq); + int numframes = hdr->regdata_size / AY_FRAME_SIZE; +// int totalsamples = numframes * hdr->playerFreq; + trace ("vtx: numframes=%d, playerFreq=%d\n", numframes, hdr->playerFreq); + deadbeef->pl_set_item_duration (it, (float)numframes / hdr->playerFreq); // add metadata deadbeef->pl_add_meta (it, "title", hdr->title); -- cgit v1.2.3