summaryrefslogtreecommitdiff
path: root/plugins/vtx
diff options
context:
space:
mode:
authorGravatar Alexey Yakovenko <wakeroid@gmail.com>2009-12-19 12:35:17 +0100
committerGravatar Alexey Yakovenko <wakeroid@gmail.com>2009-12-19 13:05:38 +0100
commit21b1594b496d29131dd124ffb9e597fbc2ccfaa6 (patch)
tree47f0a783ca2fdfa00d7d2f3fcd9b864ce4b5de1d /plugins/vtx
parent9bfb851af15b94be6387b505fa74ea99546e8ede (diff)
vtx playback with seeking
Diffstat (limited to 'plugins/vtx')
-rw-r--r--plugins/vtx/ay8912.c4
-rw-r--r--plugins/vtx/vtx.c158
2 files changed, 155 insertions, 7 deletions
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);