static int vtx_init (DB_fileinfo_t *_info, DB_playItem_t *it) { // prepare to decode the track // return -1 on failure vtx_info_t *info = (vtx_info_t *)_info; size_t sz = 0; char *buf = NULL; deadbeef->pl_lock (); DB_FILE *fp = deadbeef->fopen (deadbeef->pl_find_meta (it, ":URI")); deadbeef->pl_unlock (); if (!fp) { trace ("vtx: failed to open file %s\n", deadbeef->pl_find_meta (it, ":URI")); 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; } info->decoder = ayemu_vtx_load (buf, sz); if (!info->decoder) { trace ("vtx: ayemu_vtx_load failed\n"); free (buf); return -1; } trace ("vtx: data=%p, size=%d\n", info->decoder->regdata, info->decoder->regdata_size); free (buf); ayemu_init (&info->ay); ayemu_set_chip_type (&info->ay, info->decoder->chiptype, NULL); ayemu_set_chip_freq (&info->ay, info->decoder->chipFreq); ayemu_set_stereo (&info->ay, info->decoder->stereo, NULL); int samplerate = deadbeef->conf_get_int ("synth.samplerate", 44100); info->left = 0; info->vtx_pos = 0; _info->plugin = &plugin; _info->fmt.bps = deadbeef->conf_get_int ("vtx.bps", 16);; if (_info->fmt.bps != 16 && _info->fmt.bps != 8) { _info->fmt.bps = 16; } _info->fmt.channels = 2; _info->fmt.samplerate = samplerate; _info->fmt.channelmask = _info->fmt.channels == 1 ? DDB_SPEAKER_FRONT_LEFT : (DDB_SPEAKER_FRONT_LEFT | DDB_SPEAKER_FRONT_RIGHT); _info->readpos = 0; ayemu_set_sound_format (&info->ay, samplerate, _info->fmt.channels, _info->fmt.bps); info->rate = _info->fmt.channels * _info->fmt.bps / 8; return 0; }
static gboolean vtx_play(const gchar * filename, VFSFile * file) { gboolean eof = FALSE; void *stream; /* pointer to current position in sound buffer */ guchar regs[14]; gint need; gint left; /* how many sound frames can play with current AY register frame */ gint donow; gint rate; left = 0; rate = chans * (bits / 8); memset(&ay, 0, sizeof(ay)); if (!ayemu_vtx_open(&vtx, filename)) { g_print("libvtx: Error read vtx header from %s\n", filename); return FALSE; } else if (!ayemu_vtx_load_data(&vtx)) { g_print("libvtx: Error read vtx data from %s\n", filename); return FALSE; } ayemu_init(&ay); ayemu_set_chip_type(&ay, vtx.hdr.chiptype, NULL); ayemu_set_chip_freq(&ay, vtx.hdr.chipFreq); ayemu_set_stereo(&ay, vtx.hdr.stereo, NULL); if (aud_input_open_audio(FMT_S16_NE, freq, chans) == 0) { g_print("libvtx: output audio error!\n"); return FALSE; } aud_input_set_bitrate(14 * 50 * 8); while (!aud_input_check_stop() && !eof) { /* (time in sec) * 50 = offset in AY register data frames */ int seek_value = aud_input_check_seek(); if (seek_value >= 0) vtx.pos = seek_value / 20; /* fill sound buffer */ stream = sndbuf; for (need = SNDBUFSIZE / rate; need > 0; need -= donow) { if (left > 0) { /* use current AY register frame */ donow = (need > left) ? left : need; left -= donow; stream = ayemu_gen_sound(&ay, (char *)stream, donow * rate); } else { /* get next AY register frame */ if (ayemu_vtx_get_next_frame(&vtx, (char *)regs) == 0) { donow = need; memset(stream, 0, donow * rate); eof = TRUE; } else { left = freq / vtx.hdr.playerFreq; ayemu_set_regs(&ay, regs); donow = 0; } } } aud_input_write_audio(sndbuf, SNDBUFSIZE); } ayemu_vtx_free(&vtx); return TRUE; }
static gboolean vtx_play(InputPlayback * playback, const gchar * filename, VFSFile * file, gint start_time, gint stop_time, gboolean pause) { gboolean error = FALSE; gboolean eof = FALSE; void *stream; /* pointer to current position in sound buffer */ guchar regs[14]; gint need; gint left; /* how many sound frames can play with current AY register frame */ gint donow; gint rate; left = 0; rate = chans * (bits / 8); memset(&ay, 0, sizeof(ay)); if (!ayemu_vtx_open(&vtx, filename)) { g_print("libvtx: Error read vtx header from %s\n", filename); error = TRUE; goto ERR_NO_CLOSE; } else if (!ayemu_vtx_load_data(&vtx)) { g_print("libvtx: Error read vtx data from %s\n", filename); error = TRUE; goto ERR_NO_CLOSE; } ayemu_init(&ay); ayemu_set_chip_type(&ay, vtx.hdr.chiptype, NULL); ayemu_set_chip_freq(&ay, vtx.hdr.chipFreq); ayemu_set_stereo(&ay, vtx.hdr.stereo, NULL); if (playback->output->open_audio(FMT_S16_NE, freq, chans) == 0) { g_print("libvtx: output audio error!\n"); error = TRUE; goto ERR_NO_CLOSE; } if (pause) playback->output->pause (TRUE); stop_flag = FALSE; playback->set_params(playback, 14 * 50 * 8, freq, bits / 8); playback->set_pb_ready(playback); while (!stop_flag) { g_mutex_lock(seek_mutex); if (seek_value >= 0) { vtx.pos = seek_value * 50 / 1000; /* (time in sec) * 50 = offset in AY register data frames */ playback->output->flush(seek_value); seek_value = -1; g_cond_signal(seek_cond); } g_mutex_unlock(seek_mutex); /* fill sound buffer */ stream = sndbuf; for (need = SNDBUFSIZE / rate; need > 0; need -= donow) if (left > 0) { /* use current AY register frame */ donow = (need > left) ? left : need; left -= donow; stream = ayemu_gen_sound(&ay, (char *)stream, donow * rate); } else { /* get next AY register frame */ if (ayemu_vtx_get_next_frame(&vtx, (char *)regs) == 0) { donow = need; memset(stream, 0, donow * rate); eof = TRUE; } else { left = freq / vtx.hdr.playerFreq; ayemu_set_regs(&ay, regs); donow = 0; } } if (!stop_flag) playback->output->write_audio(sndbuf, SNDBUFSIZE); if (eof) { AUDDBG("EOF.\n"); while (!stop_flag && playback->output->buffer_playing()) g_usleep(10000); goto CLEANUP; } } CLEANUP: ayemu_vtx_free(&vtx); g_mutex_lock(seek_mutex); stop_flag = TRUE; g_cond_signal(seek_cond); /* wake up any waiting request */ g_mutex_unlock(seek_mutex); playback->output->close_audio(); ERR_NO_CLOSE: return !error; }
int main (int argc, char **argv) { int index; int c; int option_index = 0; opterr = 0; while ((c = getopt_long (argc, argv, short_opts, options, &option_index)) != -1) switch (c) { case 'q': qflag = 1; break; case 'Z': Zflag = 1; break; case 's': sflag = 1; break; case 'v': vflag = 1; break; case 'V': printf ("playvtx %s\n", VERSION); exit (0); case 'h': case 'u': usage (); exit (0); case '?': if (isprint (optopt)) fprintf (stderr, "Unknown option `-%c'.\n", optopt); else fprintf (stderr, "Unknown option character `\\x%x'.\n", optopt); usage (); return 1; case -1: break; default: abort (); } if (DEBUG) printf ("qflag = %d, Zflag = %d, sflag = %d, vflag = %d\n", qflag, Zflag, sflag, vflag); if (Zflag) printf ("The -Z flag is not implemented yet, sorry\n"); if (optind == argc) { fprintf (stderr, "No files to play specified, see %s --usage.\n", argv[0]); exit (1); } init_oss(); if (DEBUG) printf ("OSS sound system initialization success: bits=%d, chans=%d, freq=%d\n", bits, chans, freq); ayemu_init(&ay); ayemu_set_sound_format(&ay, freq, chans, bits); for (index = optind; index < argc; index++) { printf ("\nPlaying file %s\n", argv[index]); play (argv[index]); } return 0; }