[xmp] Add option for vblank-based timing

Use the --vblank command-line option to force vblank-based timing instead
of CIA tempo setting. Needed by some modules such as Klisje paa klisje.
Needs new timing API.

Signed-off-by: Claudio Matsuoka <cmatsuoka@gmail.com>
master
Claudio Matsuoka 13 years ago
parent 47b8e2d93f
commit cf788f338f
  1. 3
      src/common.h
  2. 111
      src/main.c
  3. 10
      src/options.c
  4. 3
      src/xmp.1

@ -15,7 +15,8 @@ struct options {
int loop; /* loop module */ int loop; /* loop module */
int random; /* play in random order */ int random; /* play in random order */
int reverse; /* reverse stereo channels */ int reverse; /* reverse stereo channels */
int verbose; int vblank; /* use vblank timing */
int verbose; /* verbosity level */
int silent; /* silent output */ int silent; /* silent output */
int info; /* display information and exit */ int info; /* display information and exit */
int probeonly; /* probe sound driver and exit */ int probeonly; /* probe sound driver and exit */

@ -147,7 +147,7 @@ int main(int argc, char **argv)
xmp_context handle; xmp_context handle;
struct xmp_module_info mi; struct xmp_module_info mi;
struct xmp_frame_info fi; struct xmp_frame_info fi;
struct options options; struct options opt;
struct control control; struct control control;
int i; int i;
int first; int first;
@ -166,46 +166,46 @@ int main(int argc, char **argv)
init_sound_drivers(); init_sound_drivers();
memset(&options, 0, sizeof (struct options)); memset(&opt, 0, sizeof (struct options));
memset(&control, 0, sizeof (struct control)); memset(&control, 0, sizeof (struct control));
/* set defaults */ /* set defaults */
options.verbose = 1; opt.verbose = 1;
options.rate = 44100; opt.rate = 44100;
options.mix = -1; opt.mix = -1;
options.driver_id = NULL; opt.driver_id = NULL;
options.interp = XMP_INTERP_SPLINE; opt.interp = XMP_INTERP_SPLINE;
options.dsp = XMP_DSP_LOWPASS; opt.dsp = XMP_DSP_LOWPASS;
/* read configuration file */ /* read configuration file */
read_config(&options); read_config(&opt);
get_options(argc, argv, &options); get_options(argc, argv, &opt);
if (!options.probeonly && optind >= argc) { if (!opt.probeonly && optind >= argc) {
fprintf(stderr, "%s: no modules to play\n" fprintf(stderr, "%s: no modules to play\n"
"Use `%s --help' for more information.\n", "Use `%s --help' for more information.\n",
argv[0], argv[0]); argv[0], argv[0]);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (options.interp < 0) { if (opt.interp < 0) {
fprintf(stderr, "%s: unknown interpolation type\n" fprintf(stderr, "%s: unknown interpolation type\n"
"Use `%s --help' for more information.\n", "Use `%s --help' for more information.\n",
argv[0], argv[0]); argv[0], argv[0]);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (options.silent) { if (opt.silent) {
options.driver_id = "null"; opt.driver_id = "null";
} }
sound = select_sound_driver(&options); sound = select_sound_driver(&opt);
if (sound == NULL) { if (sound == NULL) {
fprintf(stderr, "%s: can't initialize sound", argv[0]); fprintf(stderr, "%s: can't initialize sound", argv[0]);
if (options.driver_id != NULL) { if (opt.driver_id != NULL) {
fprintf(stderr, " (driver = %s)", options.driver_id); fprintf(stderr, " (driver = %s)", opt.driver_id);
} }
fprintf(stderr, "\n"); fprintf(stderr, "\n");
@ -215,25 +215,25 @@ int main(int argc, char **argv)
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (options.verbose > 0) { if (opt.verbose > 0) {
report("Extended Module Player " VERSION "\n" report("Extended Module Player " VERSION "\n"
"Copyright (C) 1996-2012 Claudio Matsuoka and Hipolito Carraro Jr\n"); "Copyright (C) 1996-2012 Claudio Matsuoka and Hipolito Carraro Jr\n");
report("Using %s\n", sound->description); report("Using %s\n", sound->description);
report("Mixer set to %d Hz, %dbit, %s%s%s\n", options.rate, report("Mixer set to %d Hz, %dbit, %s%s%s\n", opt.rate,
options.format & XMP_FORMAT_8BIT ? 8 : 16, opt.format & XMP_FORMAT_8BIT ? 8 : 16,
options.interp == XMP_INTERP_LINEAR ? "linear interpolated " : opt.interp == XMP_INTERP_LINEAR ? "linear interpolated " :
options.interp == XMP_INTERP_SPLINE ? "cubic spline interpolated " : "", opt.interp == XMP_INTERP_SPLINE ? "cubic spline interpolated " : "",
options.format & XMP_FORMAT_MONO ? "mono" : "stereo", opt.format & XMP_FORMAT_MONO ? "mono" : "stereo",
options.dsp & XMP_DSP_LOWPASS ? "" : " (no filter)"); opt.dsp & XMP_DSP_LOWPASS ? "" : " (no filter)");
} }
if (options.probeonly) { if (opt.probeonly) {
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
} }
if (options.random) { if (opt.random) {
shuffle(argc - optind + 1, &argv[optind - 1]); shuffle(argc - optind + 1, &argv[optind - 1]);
} }
@ -263,13 +263,13 @@ int main(int argc, char **argv)
skipprev = 0; skipprev = 0;
if (options.ins_path) { if (opt.ins_path) {
setenv("XMP_INSTRUMENT_PATH", options.ins_path, 1); setenv("XMP_INSTRUMENT_PATH", opt.ins_path, 1);
} }
lf_flag = 0; lf_flag = 0;
for (first = optind; optind < argc; optind++) { for (first = optind; optind < argc; optind++) {
if (options.verbose > 0) { if (opt.verbose > 0) {
if (lf_flag) if (lf_flag)
report("\n"); report("\n");
lf_flag = 1; lf_flag = 1;
@ -278,6 +278,7 @@ int main(int argc, char **argv)
} }
val = xmp_load_module(handle, argv[optind]); val = xmp_load_module(handle, argv[optind]);
if (val < 0) { if (val < 0) {
char *msg; char *msg;
@ -311,37 +312,47 @@ int main(int argc, char **argv)
} }
skipprev = 0; skipprev = 0;
control.time = 0.0; control.time = 0.0;
control.loop = options.loop; control.loop = opt.loop;
if (xmp_start_player(handle, options.rate, options.format) == 0) { if (xmp_start_player(handle, opt.rate, opt.format) == 0) {
xmp_set_mixer(handle, XMP_MIXER_INTERP, options.interp); xmp_set_player(handle, XMP_PLAYER_INTERP, opt.interp);
xmp_set_mixer(handle, XMP_MIXER_DSP, options.dsp); xmp_set_player(handle, XMP_PLAYER_DSP, opt.dsp);
if (options.mix >= 0) { if (opt.mix >= 0) {
xmp_set_mixer(handle, XMP_MIXER_MIX, options.mix); xmp_set_player(handle, XMP_PLAYER_MIX, opt.mix);
} }
if (options.reverse) { if (opt.reverse) {
int mix = xmp_get_mixer(handle, XMP_MIXER_MIX); int mix;
xmp_set_mixer(handle, XMP_MIXER_MIX, -mix); mix = xmp_get_player(handle, XMP_PLAYER_MIX);
xmp_set_player(handle, XMP_PLAYER_MIX, -mix);
} }
xmp_set_position(handle, options.start); xmp_set_position(handle, opt.start);
/* Mute channels */ /* Mute channels */
for (i = 0; i < XMP_MAX_CHANNELS; i++) { for (i = 0; i < XMP_MAX_CHANNELS; i++) {
xmp_channel_mute(handle, i, options.mute[i]); xmp_channel_mute(handle, i, opt.mute[i]);
}
/* Change timing if vblank specified */
if (opt.vblank) {
xmp_set_player(handle, XMP_PLAYER_TIMING,
XMP_TIMING_VBLANK);
xmp_scan_module(handle);
} }
/* Show module data */ /* Show module data */
xmp_get_module_info(handle, &mi); xmp_get_module_info(handle, &mi);
if (options.verbose > 0) { if (opt.verbose > 0) {
info_mod(&mi); info_mod(&mi);
} }
if (options.verbose > 1) {
if (opt.verbose > 1) {
info_instruments(&mi); info_instruments(&mi);
} }
@ -351,14 +362,14 @@ int main(int argc, char **argv)
info_frame_init(); info_frame_init();
fi.loop_count = 0; fi.loop_count = 0;
while (!options.info && xmp_play_frame(handle) == 0) { while (!opt.info && xmp_play_frame(handle) == 0) {
int old_loop = fi.loop_count; int old_loop = fi.loop_count;
xmp_get_frame_info(handle, &fi); xmp_get_frame_info(handle, &fi);
if (!control.loop && old_loop != fi.loop_count) if (!control.loop && old_loop != fi.loop_count)
break; break;
if (!background && options.verbose > 0) { if (!background && opt.verbose > 0) {
info_frame(&mi, &fi, &control, refresh_status); info_frame(&mi, &fi, &control, refresh_status);
refresh_status = 0; refresh_status = 0;
} }
@ -367,7 +378,7 @@ int main(int argc, char **argv)
sound->play(fi.buffer, fi.buffer_size); sound->play(fi.buffer, fi.buffer_size);
if (!background && !options.nocmd) { if (!background && !opt.nocmd) {
read_command(handle, &control); read_command(handle, &control);
if (control.display) { if (control.display) {
@ -377,15 +388,15 @@ int main(int argc, char **argv)
} }
} }
if (options.max_time > 0 && if (opt.max_time > 0 &&
control.time > options.max_time) { control.time > opt.max_time) {
break; break;
} }
check_pause(handle, &control, &mi, &fi, check_pause(handle, &control, &mi, &fi,
options.verbose); opt.verbose);
options.start = 0; opt.start = 0;
} }
xmp_end_player(handle); xmp_end_player(handle);
@ -393,7 +404,7 @@ int main(int argc, char **argv)
xmp_release_module(handle); xmp_release_module(handle);
if (!options.info) { if (!opt.info) {
report("\n"); report("\n");
} }

@ -31,11 +31,8 @@ enum {
OPT_FX9BUG = 0x105, OPT_FX9BUG = 0x105,
OPT_PROBEONLY, OPT_PROBEONLY,
OPT_LOADONLY, OPT_LOADONLY,
OPT_STDOUT,
OPT_STEREO,
OPT_NOCMD, OPT_NOCMD,
OPT_FIXLOOP, OPT_VBLANK
OPT_SHOWTIME,
}; };
static void usage(char *s) static void usage(char *s)
@ -71,6 +68,7 @@ static void usage(char *s)
" -S --solo ch-list Set channels to solo mode\n" " -S --solo ch-list Set channels to solo mode\n"
" -s --start num Start from the specified order\n" " -s --start num Start from the specified order\n"
" -t --time num Maximum playing time in seconds\n" " -t --time num Maximum playing time in seconds\n"
" --vblank Force vblank timing in Amiga modules\n"
"\nMixer options:\n" "\nMixer options:\n"
" -a --amplify {0|1|2|3} Amplification factor: 0=Normal, 1=x2, 2=x4, 3=x8\n" " -a --amplify {0|1|2|3} Amplification factor: 0=Normal, 1=x2, 2=x4, 3=x8\n"
" -b --bits {8|16} Software mixer resolution (8 or 16 bits)\n" " -b --bits {8|16} Software mixer resolution (8 or 16 bits)\n"
@ -125,6 +123,7 @@ static struct option lopt[] = {
{ "tempo", 1, 0, 'T' }, { "tempo", 1, 0, 'T' },
{ "time", 1, 0, 't' }, { "time", 1, 0, 't' },
{ "unsigned", 0, 0, 'u' }, { "unsigned", 0, 0, 'u' },
{ "vblank", 0, 0, OPT_VBLANK },
{ "version", 0, 0, 'V' }, { "version", 0, 0, 'V' },
{ "verbose", 0, 0, 'v' }, { "verbose", 0, 0, 'v' },
{ NULL, 0, 0, 0 } { NULL, 0, 0, 0 }
@ -266,6 +265,9 @@ void get_options(int argc, char **argv, struct options *options)
case 'u': case 'u':
options->format |= XMP_FORMAT_UNSIGNED; options->format |= XMP_FORMAT_UNSIGNED;
break; break;
case OPT_VBLANK:
options->vblank = 1;
break;
case 'V': case 'V':
puts("Extended Module Player " VERSION); puts("Extended Module Player " VERSION);
exit(0); exit(0);

@ -31,6 +31,7 @@ xmp - Extended Module Player
[\fB-s, --start\fP \fIpos\fP] [\fB-s, --start\fP \fIpos\fP]
[\fB-t, --time\fP \fItime\fP] [\fB-t, --time\fP \fItime\fP]
[\fB-u, --unsigned\fP] [\fB-u, --unsigned\fP]
[\fB--vblank\fP]
[\fB-V, --version\fP] [\fB-V, --version\fP]
[\fB-v, --verbose\fP] [\fB-v, --verbose\fP]
\fImodules\fP \fImodules\fP
@ -106,6 +107,8 @@ Specifies the maximum playing time to \fItime\fP seconds\&.
.IP "\fB-u, --unsigned\fP" .IP "\fB-u, --unsigned\fP"
Tell the software mixer to use unsigned samples when mixing to Tell the software mixer to use unsigned samples when mixing to
a file (default is signed)\&. a file (default is signed)\&.
.IP "\fB--vblank\fP"
Force Amiga vblank-based timing (no CIA tempo setting)\&.
.IP "\fB-V, --version\fP" .IP "\fB-V, --version\fP"
Print version information\&. Print version information\&.
.IP "\fB-v, --verbose\fP" .IP "\fB-v, --verbose\fP"

Loading…
Cancel
Save