summaryrefslogtreecommitdiff
path: root/plugins/dumb/dumb-kode54/examples
diff options
context:
space:
mode:
authorGravatar Alexey Yakovenko <wakeroid@gmail.com>2010-04-11 15:01:21 +0200
committerGravatar Alexey Yakovenko <wakeroid@gmail.com>2010-04-11 15:01:21 +0200
commite763dfa3ddf5c499875a6e1e9ec91d7fc154c076 (patch)
tree8fddc5ecbb1d867afa4690cfdde245929cafb21c /plugins/dumb/dumb-kode54/examples
parentdc0b9121ff16d57f92f4ab2b16bf78518d3a8b9b (diff)
moved DUMB to dynamic plugin
Diffstat (limited to 'plugins/dumb/dumb-kode54/examples')
-rw-r--r--plugins/dumb/dumb-kode54/examples/Makefile.am11
-rw-r--r--plugins/dumb/dumb-kode54/examples/dumb.ini44
-rw-r--r--plugins/dumb/dumb-kode54/examples/dumb2wav.c481
-rw-r--r--plugins/dumb/dumb-kode54/examples/dumbout.c404
-rw-r--r--plugins/dumb/dumb-kode54/examples/dumbplay.c238
-rw-r--r--plugins/dumb/dumb-kode54/examples/playduh.c169
6 files changed, 1347 insertions, 0 deletions
diff --git a/plugins/dumb/dumb-kode54/examples/Makefile.am b/plugins/dumb/dumb-kode54/examples/Makefile.am
new file mode 100644
index 00000000..2c1117fd
--- /dev/null
+++ b/plugins/dumb/dumb-kode54/examples/Makefile.am
@@ -0,0 +1,11 @@
+INCLUDES = \
+ -I $(top_srcdir)/include
+
+LIBS = $(top_builddir)/src/libdumb.la -lm
+
+bin_PROGRAMS = dumb2wav dumbout
+
+dumb2wav_SOURCES = dumb2wav.c
+dumbout_SOURCES = dumbout.c
+#dumbplay_SOURCES = dumbplay.c
+#playduh_SOURCES = playduh.c
diff --git a/plugins/dumb/dumb-kode54/examples/dumb.ini b/plugins/dumb/dumb-kode54/examples/dumb.ini
new file mode 100644
index 00000000..ee707ad2
--- /dev/null
+++ b/plugins/dumb/dumb-kode54/examples/dumb.ini
@@ -0,0 +1,44 @@
+# Please edit this file to control the playback quality for 'dumbplay'. Note
+# that this does not affect DUMB when you use it in your own programs; you
+# need to borrow some code from the example program in order to get that to
+# happen.
+
+# dumb_resampling_quality can be 0 for aliasing, 1 for linear interpolation
+# or 2 for cubic interpolation. See docs/dumb.txt for details on what these
+# terms mean.
+
+# dumb_it_max_to_mix is the maximum number of samples DUMB will render at a
+# time. See docs/dumb.txt for a more detailed description.
+
+# Increase buffer_size to combat stuttering.
+
+# The music module will be rendered at the sampling frequency specified by
+# sound_freq. This variable is also used by Allegro for initialising the
+# sound hardware.
+
+# buffer_size and sound_freq are passed directly to al_start_duh(). See this
+# function's description in docs/dumb.txt for information about how to use
+# these variables.
+
+# You can ignore the quality variable. Allegro uses it when relaying the
+# audio stream to the sound card. Only a masochist would set it lower than 2;
+# if your computer is powerful enough to run DUMB, it is powerful enough to
+# use this setting with Allegro.
+
+# For best results, choose a value for sound_freq that your sound card can do
+# exactly. See Allegro's docs, "Standard config variables", for details. If
+# you do not choose an exact value, Allegro will round it to the nearest
+# value it can do; then when DUMB plays the stream at a sampling frequency of
+# sound_freq, Allegro will have to resample it. Allegro's 'quality = 2'
+# setting is only comparable with DUMB's 'dumb_resampling_quality = 1'
+# setting. Therefore, in order to appreciate DUMB's cubic resampler fully,
+# you will need to make sure Allegro doesn't do any resampling, by choosing
+# an exact value for sound_freq.
+
+[sound]
+dumb_resampling_quality = 2
+dumb_it_max_to_mix = 256
+buffer_size = 4096
+sound_freq = 44100
+
+quality = 2
diff --git a/plugins/dumb/dumb-kode54/examples/dumb2wav.c b/plugins/dumb/dumb-kode54/examples/dumb2wav.c
new file mode 100644
index 00000000..9a4c5090
--- /dev/null
+++ b/plugins/dumb/dumb-kode54/examples/dumb2wav.c
@@ -0,0 +1,481 @@
+/* _______ ____ __ ___ ___
+ * \ _ \ \ / \ / \ \ / / ' ' '
+ * | | \ \ | | || | \/ | . .
+ * | | | | | | || ||\ /| |
+ * | | | | | | || || \/ | | ' ' '
+ * | | | | | | || || | | . .
+ * | |_/ / \ \__// || | |
+ * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
+ * / \
+ * / . \
+ * dumb2wav.c - Utility to convert DUH to WAV. / / \ \
+ * | < / \_
+ * By Chad Austin, based on dumbout.c by entheh. | \/ /\ /
+ * \_ / > /
+ * | \ / /
+ * | ' /
+ * \__/
+ */
+
+#include <time.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <math.h>
+#include <string.h>
+#include <dumb.h>
+
+#include <internal/it.h>
+
+union {
+ float s32[4096];
+ short s16[8192];
+ char s8[16384];
+} buffer;
+
+sample_t ** internal_buffer;
+
+int loop_count = 1;
+
+
+static int write32_le(FILE* outf, unsigned int value) {
+ int total = 0;
+ total += fputc(value & 0xFF, outf);
+ total += fputc((value >> 8) & 0xFF, outf);
+ total += fputc((value >> 16) & 0xFF, outf);
+ total += fputc((value >> 24) & 0xFF, outf);
+ return total;
+}
+
+static int write16_le(FILE* outf, unsigned int value) {
+ int total = 0;
+ total += fputc(value & 0xFF, outf);
+ total += fputc((value >> 8) & 0xFF, outf);
+ return total;
+}
+
+
+static int loop_callback(void* data) {
+ return (--loop_count <= 0 ? -1 : 0);
+}
+
+
+int main(int argc, const char *argv[])
+{
+ DUH *duh;
+ DUH_SIGRENDERER *sr;
+
+ const char *fn = NULL;
+ const char *fn_out = NULL;
+ FILE *outf;
+
+ int depth = 16;
+ int unsign = 0;
+ int freq = 44100;
+ int n_channels = 2;
+ int solo = -1;
+ float volume = 1.0f;
+ float delay = 0.0f;
+ float delta;
+ int bufsize;
+ clock_t start, end;
+ int data_written = 0; /* total bytes written to data chunk */
+
+ int i = 1;
+
+ LONG_LONG length;
+ LONG_LONG done;
+ int dots;
+
+ while (i < argc) {
+ const char *arg = argv[i++];
+ if (*arg != '-') {
+ if (fn) {
+ fprintf(stderr,
+ "Cannot specify multiple filenames!\n"
+ "Second filename found: \"%s\"\n", arg);
+ return 1;
+ }
+ fn = arg;
+ continue;
+ }
+ arg++;
+ while (*arg) {
+ char *endptr;
+ switch (*arg++) {
+ case 'o':
+ case 'O':
+ if (i >= argc) {
+ fprintf(stderr, "Out of arguments; output filename expected!\n");
+ return 1;
+ }
+ fn_out = argv[i++];
+ break;
+ case 'd':
+ case 'D':
+ if (i >= argc) {
+ fprintf(stderr, "Out of arguments; delay expected!\n");
+ return 1;
+ }
+ delay = (float)strtod(argv[i++], &endptr);
+ if (*endptr != 0 || delay < 0.0f || delay > 64.0f) {
+ fprintf(stderr, "Invalid delay!\n");
+ return 1;
+ }
+ break;
+ case 'v':
+ case 'V':
+ if (i >= argc) {
+ fprintf(stderr, "Out of arguments; volume expected!\n");
+ return 1;
+ }
+ volume = (float)strtod(argv[i++], &endptr);
+ if (*endptr != 0 || volume < -8.0f || volume > 8.0f) {
+ fprintf(stderr, "Invalid volume!\n");
+ return 1;
+ }
+ break;
+ case 's':
+ case 'S':
+ if (i >= argc) {
+ fprintf(stderr, "Out of arguments; sampling rate expected!\n");
+ return 1;
+ }
+ freq = strtol(argv[i++], &endptr, 10);
+ if (*endptr != 0 || freq < 1 || freq > 960000) {
+ fprintf(stderr, "Invalid sampling rate!\n");
+ return 1;
+ }
+ break;
+ case 'f':
+ depth = 32;
+ break;
+ case '8':
+ depth = 8;
+ break;
+ case 'l':
+ case 'L':
+ if (i >= argc) {
+ fprintf(stderr, "Out of arguments: loop count expected!\n");
+ return 1;
+ }
+ loop_count = strtol(argv[i++], &endptr, 10);
+ break;
+ case 'm':
+ case 'M':
+ n_channels = 1;
+ break;
+ case 'u':
+ case 'U':
+ unsign = 1;
+ break;
+ case 'r':
+ case 'R':
+ if (i >= argc) {
+ fprintf(stderr, "Out of arguments; resampling quality expected!\n");
+ return 1;
+ }
+ dumb_resampling_quality = strtol(argv[i++], &endptr, 10);
+ if (*endptr != 0 || dumb_resampling_quality < 0 || dumb_resampling_quality > 2) {
+ fprintf(stderr, "Invalid resampling quality!\n");
+ return 1;
+ }
+ break;
+ case 'c':
+ case 'C':
+ if (i >= argc) {
+ fprintf(stderr, "Out of arguments; channel number expected!\n");
+ return 1;
+ }
+ solo = strtol(argv[i++], &endptr, 10);
+ if (*endptr != 0 || solo < 0 || solo >= DUMB_IT_N_CHANNELS) {
+ fprintf(stderr, "Invalid channel number!\n");
+ return 1;
+ }
+ break;
+ default:
+ fprintf(stderr, "Invalid switch - '%c'!\n", isprint(arg[-1]) ? arg[-1] : '?');
+ return 1;
+ }
+ }
+ }
+
+ if (!fn) {
+ fprintf(stderr,
+ "Usage: dumb2wav [options] module [more-options]\n"
+ "\n"
+ "The module can be any IT, XM, S3M or MOD file. It will be rendered to a .wav\n"
+ "file of the same name, unless you specify otherwise with the -o option.\n"
+ "\n"
+ "The valid options are:\n"
+ "-o <file> specify the output filename (defaults to the input filename with\n"
+ " the extension replaced with .wav); use - to write to standard\n"
+ " output or . to write nowhere (useful for measuring DUMB's\n"
+ " performance, and DOS and Windows don't have /dev/null!)\n"
+ "-d <delay> set the initial delay, in seconds (default 0.0)\n"
+ "-v <volume> adjust the volume (default 1.0)\n"
+ "-s <freq> set the sampling rate in Hz (default 44100)\n"
+ "-8 generate 8-bit instead of 16-bit\n"
+ "-f generate floating point samples instead of 16-bit\n"
+ "-m generate mono output instead of stereo left/right pairs\n"
+ "-u generated unsigned output instead of signed\n"
+ "-r <value> specify the resampling quality to use\n"
+ "-l <value> specify the number of times to loop (default 1)\n"
+ "-c <value> specify a channel number to solo\n");
+ return 1;
+ }
+
+ atexit(&dumb_exit);
+ dumb_register_stdfiles();
+
+ dumb_it_max_to_mix = 256;
+
+ duh = load_duh(fn);
+ if (!duh) {
+ duh = dumb_load_it(fn);
+ if (!duh) {
+ duh = dumb_load_xm(fn);
+ if (!duh) {
+ duh = dumb_load_s3m(fn);
+ if (!duh) {
+ duh = dumb_load_mod(fn);
+ if (!duh) {
+ fprintf(stderr, "Unable to open %s!\n", fn);
+ return 1;
+ }
+ }
+ }
+ }
+ }
+
+ sr = duh_start_sigrenderer(duh, 0, n_channels, 0);
+ if (!sr) {
+ unload_duh(duh);
+ fprintf(stderr, "Unable to play file!\n");
+ return 1;
+ }
+
+ if (solo >= 0) {
+ DUMB_IT_SIGRENDERER * itsr = duh_get_it_sigrenderer(sr);
+ if (itsr) {
+ for (i = 0; i < DUMB_IT_N_CHANNELS; i++) {
+ if (i != solo) {
+ IT_CHANNEL * channel = &itsr->channel[i];
+ IT_PLAYING * playing = channel->playing;
+ channel->flags |= IT_CHANNEL_MUTED;
+ /* start_sigrenderer leaves me all of the channels the first tick triggered */
+ if (playing) {
+ playing->ramp_volume[0] = 0;
+ playing->ramp_volume[1] = 0;
+ playing->ramp_delta[0] = 0;
+ playing->ramp_delta[1] = 0;
+ }
+ }
+ }
+ }
+ }
+
+ if (fn_out) {
+ if (fn_out[0] == '-' && fn_out[1] == 0)
+ outf = stdout;
+ else if (fn_out[0] == '.' && fn_out[1] == 0)
+ outf = NULL;
+ else {
+ outf = fopen(fn_out, "wb");
+ if (!outf) {
+ fprintf(stderr, "Unable to open %s for writing!\n", fn_out);
+ duh_end_sigrenderer(sr);
+ unload_duh(duh);
+ return 1;
+ }
+ }
+ } else {
+ char *extptr = NULL, *p;
+ char *fn_out = malloc(strlen(fn)+5);
+ if (!fn_out) {
+ fprintf(stderr, "Out of memory!\n");
+ duh_end_sigrenderer(sr);
+ unload_duh(duh);
+ return 1;
+ }
+ strcpy(fn_out, fn);
+ for (p = fn_out; *p; p++)
+ if (*p == '.') extptr = p;
+ if (!extptr) extptr = p;
+ strcpy(extptr, ".wav");
+ outf = fopen(fn_out, "wb");
+ if (!outf) {
+ fprintf(stderr, "Unable to open %s for writing!\n", fn_out);
+ free(fn_out);
+ duh_end_sigrenderer(sr);
+ unload_duh(duh);
+ return 1;
+ }
+ free(fn_out);
+ }
+
+ {
+ DUMB_IT_SIGRENDERER *itsr = duh_get_it_sigrenderer(sr);
+ dumb_it_set_ramp_style(itsr, 2);
+ dumb_it_set_loop_callback(itsr, loop_callback, NULL);
+ dumb_it_set_xm_speed_zero_callback(itsr, &dumb_it_callback_terminate, NULL);
+ dumb_it_set_global_volume_zero_callback(itsr, &dumb_it_callback_terminate, NULL);
+ }
+
+
+ if (outf) {
+ /* write RIFF header: fill file length later */
+ fwrite("RIFF", 1, 4, outf);
+ fwrite(" ", 1, 4, outf);
+ fwrite("WAVE", 1, 4, outf);
+
+ /* write format chunk */
+ fwrite("fmt ", 1, 4, outf);
+
+ if (depth == 32)
+ {
+ write32_le(outf, 18);
+ write16_le(outf, 3);
+ }
+ else
+ {
+ write32_le(outf, 16); /* header length */
+ write16_le(outf, 1); /* WAVE_FORMAT_PCM */
+ }
+ write16_le(outf, n_channels); /* channel count */
+ write32_le(outf, freq); /* frequency */
+ write32_le(outf, freq * n_channels * depth / 8); /*bytes/sec*/
+ write16_le(outf, n_channels * depth / 8); /* block alignment */
+ write16_le(outf, depth); /* bits per sample */
+
+ if (depth == 32)
+ {
+ write16_le(outf, 0);
+ }
+
+ /* start data chunk */
+ fwrite("data", 1, 4, outf);
+ fwrite(" ", 1, 4, outf); /* fill in later */
+ }
+
+ length = (LONG_LONG)_dumb_it_build_checkpoints(duh_get_it_sigdata(duh), 0) * freq >> 16;
+ done = 0;
+ dots = 0;
+ delta = 65536.0f / freq;
+ bufsize = sizeof(buffer);
+ if (depth == 32) bufsize /= sizeof(*buffer.s32);
+ else if (depth == 16) bufsize /= sizeof(*buffer.s16);
+ bufsize /= n_channels;
+
+ if (depth == 32) {
+ internal_buffer = create_sample_buffer(n_channels, bufsize);
+ if (!internal_buffer) {
+ fprintf(stderr, "Out of memory!\n");
+ duh_end_sigrenderer(sr);
+ unload_duh(duh);
+ }
+ }
+
+ {
+ long l = (long)floor(delay * freq + 0.5f);
+ l *= n_channels * (depth >> 3);
+ if (l) {
+ if (unsign && depth != 32) {
+ if (depth == 16) {
+ for (i = 0; i < 8192; i++) {
+ buffer.s8[i*2] = 0x00;
+ buffer.s8[i*2+1] = 0x80;
+ }
+ } else
+ memset(buffer.s8, 0x80, 16384);
+ } else
+ memset(buffer.s8, 0, 16384);
+ while (l >= 16384) {
+ if (outf) fwrite(buffer.s8, 1, 16384, outf);
+ l -= 16384;
+ data_written += 16384;
+ }
+ if (l) {
+ if (outf) fwrite(buffer.s8, 1, l, outf);
+ data_written += 1;
+ }
+ }
+ }
+
+ start = clock();
+
+ fprintf(stderr, "................................................................\n");
+ for (;;) {
+ int write_size;
+ int l;
+
+ if (depth != 32) {
+ l = duh_render(sr, depth, unsign, volume, delta, bufsize, &buffer);
+ if (depth == 16) {
+ for (i = 0; i < l * n_channels; i++) {
+ short val = buffer.s16[i];
+ buffer.s8[i*2] = val;
+ buffer.s8[i*2+1] = val >> 8;
+ }
+ }
+ } else {
+ int j;
+ dumb_silence(internal_buffer[0], bufsize * n_channels);
+ l = duh_sigrenderer_get_samples(sr, volume, delta, bufsize, internal_buffer);
+ for (i = 0; i < n_channels; i++) {
+ for (j = 0; j < l; j++) {
+ buffer.s32[j * n_channels + i] = (float)((double)internal_buffer[i][j] * (1.0 / (double)(0x800000)));
+ }
+ }
+ }
+ write_size = l * n_channels * (depth >> 3);
+ if (outf) fwrite(buffer.s8, 1, write_size, outf);
+ data_written += write_size;
+ if (l < bufsize) break;
+ done += l;
+ l = done * 64 / length;
+ while (dots < 64 && l > dots) {
+ fprintf(stderr, "|");
+ dots++;
+ }
+ if (dots >= 64) {
+ putchar('\n');
+ dots = 0;
+ done = 0;
+ }
+ }
+
+ while (64 > dots) {
+ fprintf(stderr, "|");
+ dots++;
+ }
+ fprintf(stderr, "\n");
+
+ end = clock();
+
+ if (depth == 32) destroy_sample_buffer(internal_buffer);
+
+ /* fill in blanks we left in WAVE file */
+ if (outf) {
+ /* file size, not including RIFF header */
+ const int fmt_size = 8 + ((depth == 32) ? 18 : 16);
+ const int data_size = 8 + data_written;
+ const int file_size = fmt_size + data_size;
+
+ /* can we seek stdout? */
+ fseek(outf, 4, SEEK_SET);
+ write32_le(outf, file_size);
+
+ fseek(outf, 12 + fmt_size + 4, SEEK_SET);
+ write32_le(outf, data_written);
+ }
+
+
+ duh_end_sigrenderer(sr);
+ unload_duh(duh);
+ if (outf && outf != stdout) fclose(outf);
+
+ fprintf(stderr, "Elapsed time: %f seconds\n", (end - start) / (float)CLOCKS_PER_SEC);
+
+ return 0;
+}
diff --git a/plugins/dumb/dumb-kode54/examples/dumbout.c b/plugins/dumb/dumb-kode54/examples/dumbout.c
new file mode 100644
index 00000000..3082b3b4
--- /dev/null
+++ b/plugins/dumb/dumb-kode54/examples/dumbout.c
@@ -0,0 +1,404 @@
+/* _______ ____ __ ___ ___
+ * \ _ \ \ / \ / \ \ / / ' ' '
+ * | | \ \ | | || | \/ | . .
+ * | | | | | | || ||\ /| |
+ * | | | | | | || || \/ | | ' ' '
+ * | | | | | | || || | | . .
+ * | |_/ / \ \__// || | |
+ * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
+ * / \
+ * / . \
+ * dumbout.c - Utility to stream music to a file. / / \ \
+ * | < / \_
+ * By entheh. | \/ /\ /
+ * \_ / > /
+ * | \ / /
+ * | ' /
+ * \__/
+ */
+
+#include <time.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <math.h>
+#include <string.h>
+#include <dumb.h>
+
+#include <internal/it.h>
+
+union {
+ float s32[4096];
+ short s16[8192];
+ char s8[16384];
+} buffer;
+
+sample_t ** internal_buffer;
+
+int main(int argc, const char *const *argv) /* I'm const-crazy! */
+{
+ DUH *duh;
+ DUH_SIGRENDERER *sr;
+
+ const char *fn = NULL;
+ const char *fn_out = NULL;
+ FILE *outf;
+
+ int depth = 16;
+ int bigendian = 0;
+ int unsign = 0;
+ int freq = 44100;
+ int n_channels = 2;
+ int solo = -1;
+ float volume = 1.0f;
+ float delay = 0.0f;
+ float delta;
+ int bufsize;
+ clock_t start, end;
+
+ int i = 1;
+
+ LONG_LONG length;
+ LONG_LONG done;
+ int dots;
+
+ while (i < argc) {
+ const char *arg = argv[i++];
+ if (*arg != '-') {
+ if (fn) {
+ fprintf(stderr,
+ "Cannot specify multiple filenames!\n"
+ "Second filename found: \"%s\"\n", arg);
+ return 1;
+ }
+ fn = arg;
+ continue;
+ }
+ arg++;
+ while (*arg) {
+ char *endptr;
+ switch (*arg++) {
+ case 'o':
+ case 'O':
+ if (i >= argc) {
+ fprintf(stderr, "Out of arguments; output filename expected!\n");
+ return 1;
+ }
+ fn_out = argv[i++];
+ break;
+ case 'd':
+ case 'D':
+ if (i >= argc) {
+ fprintf(stderr, "Out of arguments; delay expected!\n");
+ return 1;
+ }
+ delay = (float)strtod(argv[i++], &endptr);
+ if (*endptr != 0 || delay < 0.0f || delay > 64.0f) {
+ fprintf(stderr, "Invalid delay!\n");
+ return 1;
+ }
+ break;
+ case 'v':
+ case 'V':
+ if (i >= argc) {
+ fprintf(stderr, "Out of arguments; volume expected!\n");
+ return 1;
+ }
+ volume = (float)strtod(argv[i++], &endptr);
+ if (*endptr != 0 || volume < -8.0f || volume > 8.0f) {
+ fprintf(stderr, "Invalid volume!\n");
+ return 1;
+ }
+ break;
+ case 's':
+ case 'S':
+ if (i >= argc) {
+ fprintf(stderr, "Out of arguments; sampling rate expected!\n");
+ return 1;
+ }
+ freq = strtol(argv[i++], &endptr, 10);
+ if (*endptr != 0 || freq < 1 || freq > 960000) {
+ fprintf(stderr, "Invalid sampling rate!\n");
+ return 1;
+ }
+ break;
+ case 'f':
+ depth = 32;
+ break;
+ case '8':
+ depth = 8;
+ break;
+ case 'b':
+ case 'B':
+ bigendian = 1;
+ break;
+ case 'm':
+ case 'M':
+ n_channels = 1;
+ break;
+ case 'u':
+ case 'U':
+ unsign = 1;
+ break;
+ case 'r':
+ case 'R':
+ if (i >= argc) {
+ fprintf(stderr, "Out of arguments; resampling quality expected!\n");
+ return 1;
+ }
+ dumb_resampling_quality = strtol(argv[i++], &endptr, 10);
+ if (*endptr != 0 || dumb_resampling_quality < 0 || dumb_resampling_quality > 2) {
+ fprintf(stderr, "Invalid resampling quality!\n");
+ return 1;
+ }
+ break;
+ case 'c':
+ case 'C':
+ if (i >= argc) {
+ fprintf(stderr, "Out of arguments; channel number expected!\n");
+ return 1;
+ }
+ solo = strtol(argv[i++], &endptr, 10);
+ if (*endptr != 0 || solo < 0 || solo >= DUMB_IT_N_CHANNELS) {
+ fprintf(stderr, "Invalid channel number!\n");
+ return 1;
+ }
+ break;
+ default:
+ fprintf(stderr, "Invalid switch - '%c'!\n", isprint(arg[-1]) ? arg[-1] : '?');
+ return 1;
+ }
+ }
+ }
+
+ if (!fn) {
+ fprintf(stderr,
+ "Usage: dumbout [options] module [more-options]\n"
+ "\n"
+ "The module can be any IT, XM, S3M or MOD file. It will be rendered to a .pcm\n"
+ "file of the same name, unless you specify otherwise with the -o option.\n"
+ "\n"
+ "The valid options are:\n"
+ "-o <file> specify the output filename (defaults to the input filename with\n"
+ " the extension replaced with .pcm); use - to write to standard\n"
+ " output or . to write nowhere (useful for measuring DUMB's\n"
+ " performance, and DOS and Windows don't have /dev/null!)\n"
+ "-d <delay> set the initial delay, in seconds (default 0.0)\n"
+ "-v <volume> adjust the volume (default 1.0)\n"
+ "-s <freq> set the sampling rate in Hz (default 44100)\n"
+ "-8 generate 8-bit instead of 16-bit\n"
+ "-f generate 32-bit floating point data instead of 16-bit\n"
+ "-b generate big-endian data instead of little-endian (meaningless when\n"
+ " using -8)\n"
+ "-m generate mono output instead of stereo left/right pairs\n"
+ "-u generated unsigned output instead of signed\n"
+ "-r <value> specify the resampling quality to use\n"
+ "-c <value> specify a channel number to solo\n");
+ return 1;
+ }
+
+ atexit(&dumb_exit);
+ dumb_register_stdfiles();
+
+ dumb_it_max_to_mix = 256;
+
+ duh = load_duh(fn);
+ if (!duh) {
+ duh = dumb_load_it(fn);
+ if (!duh) {
+ duh = dumb_load_xm(fn);
+ if (!duh) {
+ duh = dumb_load_s3m(fn);
+ if (!duh) {
+ duh = dumb_load_mod(fn);
+ if (!duh) {
+ fprintf(stderr, "Unable to open %s!\n", fn);
+ return 1;
+ }
+ }
+ }
+ }
+ }
+
+ sr = duh_start_sigrenderer(duh, 0, n_channels, 0);
+ if (!sr) {
+ unload_duh(duh);
+ fprintf(stderr, "Unable to play file!\n");
+ return 1;
+ }
+
+ if (solo >= 0) {
+ DUMB_IT_SIGRENDERER * itsr = duh_get_it_sigrenderer(sr);
+ if (itsr) {
+ for (i = 0; i < DUMB_IT_N_CHANNELS; i++) {
+ if (i != solo) {
+ IT_CHANNEL * channel = &itsr->channel[i];
+ IT_PLAYING * playing = channel->playing;
+ channel->flags |= IT_CHANNEL_MUTED;
+ /* start_sigrenderer leaves me all of the channels the first tick triggered */
+ if (playing) {
+ playing->ramp_volume[0] = 0;
+ playing->ramp_volume[1] = 0;
+ playing->ramp_delta[0] = 0;
+ playing->ramp_delta[1] = 0;
+ }
+ }
+ }
+ }
+ }
+
+ if (fn_out) {
+ if (fn_out[0] == '-' && fn_out[1] == 0)
+ outf = stdout;
+ else if (fn_out[0] == '.' && fn_out[1] == 0)
+ outf = NULL;
+ else {
+ outf = fopen(fn_out, "wb");
+ if (!outf) {
+ fprintf(stderr, "Unable to open %s for writing!\n", fn_out);
+ duh_end_sigrenderer(sr);
+ unload_duh(duh);
+ return 1;
+ }
+ }
+ } else {
+ char *extptr = NULL, *p;
+ char *fn_out = malloc(strlen(fn)+5);
+ if (!fn_out) {
+ fprintf(stderr, "Out of memory!\n");
+ duh_end_sigrenderer(sr);
+ unload_duh(duh);
+ return 1;
+ }
+ strcpy(fn_out, fn);
+ for (p = fn_out; *p; p++)
+ if (*p == '.') extptr = p;
+ if (!extptr) extptr = p;
+ strcpy(extptr, ".pcm");
+ outf = fopen(fn_out, "wb");
+ if (!outf) {
+ fprintf(stderr, "Unable to open %s for writing!\n", fn_out);
+ free(fn_out);
+ duh_end_sigrenderer(sr);
+ unload_duh(duh);
+ return 1;
+ }
+ free(fn_out);
+ }
+
+ {
+ DUMB_IT_SIGRENDERER *itsr = duh_get_it_sigrenderer(sr);
+ dumb_it_set_ramp_style(itsr, 2);
+ dumb_it_set_loop_callback(itsr, &dumb_it_callback_terminate, NULL);
+ dumb_it_set_xm_speed_zero_callback(itsr, &dumb_it_callback_terminate, NULL);
+ dumb_it_set_global_volume_zero_callback(itsr, &dumb_it_callback_terminate, NULL);
+ }
+
+ length = (LONG_LONG)_dumb_it_build_checkpoints(duh_get_it_sigdata(duh), 0) * freq >> 16;
+ done = 0;
+ dots = 0;
+ delta = 65536.0f / freq;
+ bufsize = sizeof(buffer);
+ if (depth == 32) bufsize /= sizeof(*buffer.s32);
+ else if (depth == 16) bufsize /= sizeof(*buffer.s16);
+ bufsize /= n_channels;
+
+ if (depth == 32) {
+ internal_buffer = create_sample_buffer(n_channels, bufsize);
+ if (!internal_buffer) {
+ fprintf(stderr, "Out of memory!\n");
+ duh_end_sigrenderer(sr);
+ unload_duh(duh);
+ }
+ }
+
+ {
+ long l = (long)floor(delay * freq + 0.5f);
+ l *= n_channels * (depth >> 3);
+ if (l) {
+ if (unsign && depth != 32) {
+ if (depth == 16) {
+ if (bigendian) {
+ for (i = 0; i < 8192; i++) {
+ buffer.s8[i*2] = 0x80;
+ buffer.s8[i*2+1] = 0x00;
+ }
+ } else {
+ for (i = 0; i < 8192; i++) {
+ buffer.s8[i*2] = 0x00;
+ buffer.s8[i*2+1] = 0x80;
+ }
+ }
+ } else
+ memset(buffer.s8, 0x80, 16384);
+ } else
+ memset(buffer.s8, 0, 16384);
+ while (l >= 16384) {
+ if (outf) fwrite(buffer.s8, 1, 16384, outf);
+ l -= 16384;
+ }
+ if (l && outf) fwrite(buffer.s8, 1, l, outf);
+ }
+ }
+
+ start = clock();
+
+ fprintf(stderr, "................................................................\n");
+ for (;;) {
+ int l;
+
+ if (depth != 32) {
+ l = duh_render(sr, depth, unsign, volume, delta, bufsize, &buffer);
+ if (depth == 16) {
+ if (bigendian) {
+ for (i = 0; i < l * n_channels; i++) {
+ short val = buffer.s16[i];
+ buffer.s8[i*2] = val >> 8;
+ buffer.s8[i*2+1] = val;
+ }
+ } else {
+ for (i = 0; i < l * n_channels; i++) {
+ short val = buffer.s16[i];
+ buffer.s8[i*2] = val;
+ buffer.s8[i*2+1] = val >> 8;
+ }
+ }
+ }
+ } else {
+ int j;
+ dumb_silence(internal_buffer[0], bufsize * n_channels);
+ l = duh_sigrenderer_get_samples(sr, volume, delta, bufsize, internal_buffer);
+ for (i = 0; i < n_channels; i++) {
+ for (j = i; j < l; j++) {
+ buffer.s32[j * n_channels] = (float)((double)internal_buffer[i][j] * (1.0 / (double)(0x800000)));
+ }
+ }
+ }
+ if (outf) fwrite(buffer.s8, 1, l * n_channels * (depth >> 3), outf);
+ if (l < bufsize) break;
+ done += l;
+ l = done * 64 / length;
+ while (dots < 64 && l > dots) {
+ fprintf(stderr, "|");
+ dots++;
+ }
+ }
+
+ while (64 > dots) {
+ fprintf(stderr, "|");
+ dots++;
+ }
+ fprintf(stderr, "\n");
+
+ end = clock();
+
+ if (depth == 32) destroy_sample_buffer(internal_buffer);
+
+ duh_end_sigrenderer(sr);
+ unload_duh(duh);
+ if (outf && outf != stdout) fclose(outf);
+
+ fprintf(stderr, "Elapsed time: %f seconds\n", (end - start) / (float)CLOCKS_PER_SEC);
+
+ return 0;
+}
diff --git a/plugins/dumb/dumb-kode54/examples/dumbplay.c b/plugins/dumb/dumb-kode54/examples/dumbplay.c
new file mode 100644
index 00000000..521113f6
--- /dev/null
+++ b/plugins/dumb/dumb-kode54/examples/dumbplay.c
@@ -0,0 +1,238 @@
+/* _______ ____ __ ___ ___
+ * \ _ \ \ / \ / \ \ / / ' ' '
+ * | | \ \ | | || | \/ | . .
+ * | | | | | | || ||\ /| |
+ * | | | | | | || || \/ | | ' ' '
+ * | | | | | | || || | | . .
+ * | |_/ / \ \__// || | |
+ * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
+ * / \
+ * / . \
+ * dumbplay.c - Not-so-simple program to play / / \ \
+ * music. It used to be simpler! | < / \_
+ * | \/ /\ /
+ * By entheh. \_ / > /
+ * | \ / /
+ * IMPORTANT NOTE: This file is not very friendly. | ' /
+ * I strongly recommend AGAINST using it as a \__/
+ * reference for writing your own code. If you would
+ * like to write a program that uses DUMB, or add DUMB to an existing
+ * project, please use docs/howto.txt. It will help you a lot more than this
+ * file can. (If you have difficulty reading documentation, you are lacking
+ * an important coding skill, and now is as good a time as any to learn.)
+ */
+
+#include <stdlib.h>
+#include <allegro.h>
+
+#ifndef ALLEGRO_DOS
+#include <string.h>
+#endif
+
+/* Note that your own programs should use <aldumb.h> not "aldumb.h". <> tells
+ * the compiler to look in the compiler's default header directory, which is
+ * where DUMB should be installed before you use it (make install does this).
+ * Use "" when it is your own header file. This example uses "" because DUMB
+ * might not have been installed yet when the makefile builds it.
+ */
+#include "aldumb.h"
+
+
+
+#ifndef ALLEGRO_DOS
+static volatile int closed = 0;
+static void closehook(void) { closed = 1; }
+#else
+#define closed 0
+#endif
+
+#ifdef ALLEGRO_WINDOWS
+#define GFX_DUMB_MODE GFX_GDI
+#include <winalleg.h>
+#define YIELD() Sleep(1)
+#else
+#define GFX_DUMB_MODE GFX_AUTODETECT_WINDOWED
+#ifdef ALLEGRO_UNIX
+#include <sys/time.h>
+static void YIELD(void)
+{
+ struct timeval tv;
+ tv.tv_sec = 0;
+ tv.tv_usec = 1;
+ select(0, NULL, NULL, NULL, &tv);
+}
+#else
+#define YIELD() yield_timeslice()
+#endif
+#endif
+
+
+
+#ifdef ALLEGRO_DOS
+static int loop_callback(void *data)
+{
+ (void)data;
+ printf("Music has looped.\n");
+ return 0;
+}
+
+static int xm_speed_zero_callback(void *data)
+{
+ (void)data;
+ printf("Music has stopped.\n");
+ return 0;
+}
+#else
+static int gfx_half_width;
+
+static int loop_callback(void *data)
+{
+ (void)data;
+ if (gfx_half_width) {
+ acquire_screen();
+ textout_centre(screen, font, "Music has looped.", gfx_half_width, 36, 10);
+ release_screen();
+ }
+ return 0;
+}
+
+static int xm_speed_zero_callback(void *data)
+{
+ (void)data;
+ if (gfx_half_width) {
+ text_mode(0); /* In case this is overwriting "Music has looped." */
+ acquire_screen();
+ textout_centre(screen, font, "Music has stopped.", gfx_half_width, 36, 10);
+ release_screen();
+ }
+ return 0;
+}
+#endif
+
+
+
+static void usage(const char *exename)
+{
+ allegro_message(
+#ifdef ALLEGRO_WINDOWS
+ "Usage:\n"
+ " At the command line: %s file\n"
+ " In Windows Explorer: drag a file on to this program's icon.\n"
+#else
+ "Usage: %s file\n"
+#endif
+ "This will play the music file specified.\n"
+ "File formats supported: IT XM S3M MOD.\n"
+ "You can control playback quality by editing dumb.ini.\n", exename);
+
+ exit(1);
+}
+
+
+
+int main(int argc, const char *const *argv) /* I'm const-crazy! */
+{
+ DUH *duh;
+ AL_DUH_PLAYER *dp;
+
+ if (allegro_init())
+ return 1;
+
+ if (argc != 2)
+ usage(argv[0]);
+
+ set_config_file("dumb.ini");
+
+ if (install_keyboard()) {
+ allegro_message("Failed to initialise keyboard driver!\n");
+ return 1;
+ }
+
+ set_volume_per_voice(0);
+
+ if (install_sound(DIGI_AUTODETECT, MIDI_NONE, NULL)) {
+ allegro_message("Failed to initialise sound driver!\n%s\n", allegro_error);
+ return 1;
+ }
+
+ atexit(&dumb_exit);
+
+ dumb_register_packfiles();
+
+ duh = dumb_load_it(argv[1]);
+ if (!duh) {
+ duh = dumb_load_xm(argv[1]);
+ if (!duh) {
+ duh = dumb_load_s3m(argv[1]);
+ if (!duh) {
+ duh = dumb_load_mod(argv[1]);
+ if (!duh) {
+ allegro_message("Failed to load %s!\n", argv[1]);
+ return 1;
+ }
+ }
+ }
+ }
+
+ dumb_resampling_quality = get_config_int("sound", "dumb_resampling_quality", 4);
+ dumb_it_max_to_mix = get_config_int("sound", "dumb_it_max_to_mix", 128);
+
+#ifndef ALLEGRO_DOS
+ {
+ const char *fn = get_filename(argv[1]);
+ gfx_half_width = strlen(fn);
+ if (gfx_half_width < 22) gfx_half_width = 22;
+ gfx_half_width = (gfx_half_width + 2) * 4;
+
+ /* set_window_title() is not const-correct (yet). */
+ set_window_title((char *)"DUMB Music Player");
+
+ if (set_gfx_mode(GFX_DUMB_MODE, gfx_half_width*2, 80, 0, 0) == 0) {
+ acquire_screen();
+ textout_centre(screen, font, fn, gfx_half_width, 20, 14);
+ textout_centre(screen, font, "Press any key to exit.", gfx_half_width, 52, 11);
+ release_screen();
+ } else
+ gfx_half_width = 0;
+ }
+
+#if ALLEGRO_VERSION*10000 + ALLEGRO_SUB_VERSION*100 + ALLEGRO_WIP_VERSION >= 40105
+ set_close_button_callback(&closehook);
+#else
+ set_window_close_hook(&closehook);
+#endif
+
+#endif
+
+ set_display_switch_mode(SWITCH_BACKGROUND);
+
+ dp = al_start_duh(duh, 2, 0, 1.0f,
+ get_config_int("sound", "buffer_size", 4096),
+ get_config_int("sound", "sound_freq", 44100));
+
+ {
+ DUH_SIGRENDERER *sr = al_duh_get_sigrenderer(dp);
+ DUMB_IT_SIGRENDERER *itsr = duh_get_it_sigrenderer(sr);
+ dumb_it_set_loop_callback(itsr, &loop_callback, NULL);
+ dumb_it_set_xm_speed_zero_callback(itsr, &xm_speed_zero_callback, NULL);
+ }
+
+ for (;;) {
+ if (keypressed()) {
+ readkey();
+ break;
+ }
+
+ if (al_poll_duh(dp) || closed)
+ break;
+
+ YIELD();
+ }
+
+ al_stop_duh(dp);
+
+ unload_duh(duh);
+
+ return 0;
+}
+END_OF_MAIN();
diff --git a/plugins/dumb/dumb-kode54/examples/playduh.c b/plugins/dumb/dumb-kode54/examples/playduh.c
new file mode 100644
index 00000000..31d7b619
--- /dev/null
+++ b/plugins/dumb/dumb-kode54/examples/playduh.c
@@ -0,0 +1,169 @@
+/* _______ ____ __ ___ ___
+ * \ _ \ \ / \ / \ \ / / ' ' '
+ * | | \ \ | | || | \/ | . .
+ * | | | | | | || ||\ /| |
+ * | | | | | | || || \/ | | ' ' '
+ * | | | | | | || || | | . .
+ * | |_/ / \ \__// || | |
+ * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
+ * / \
+ * / . \
+ * playduh.c - Simple program to play DUH files. / / \ \
+ * | < / \_
+ * By entheh. | \/ /\ /
+ * \_ / > /
+ * | \ / /
+ * | ' /
+ * \__/
+ */
+
+#include <stdlib.h>
+#include <allegro.h>
+
+#ifndef ALLEGRO_DOS
+#include <string.h>
+#endif
+
+/* Note that your own programs should use <aldumb.h> not "aldumb.h". <> tells
+ * the compiler to look in the compiler's default header directory, which is
+ * where DUMB should be installed before you use it (make install does this).
+ * Use "" when it is your own header file. This example uses "" because DUMB
+ * might not have been installed yet when the makefile builds it.
+ */
+#include "aldumb.h"
+
+
+
+#ifndef ALLEGRO_DOS
+static int closed = 0;
+static void closehook(void) { closed = 1; }
+#else
+#define closed 0
+#endif
+
+#ifdef ALLEGRO_WINDOWS
+#define GFX_DUMB_MODE GFX_GDI
+#include <winalleg.h>
+#define YIELD() Sleep(1)
+#else
+#define GFX_DUMB_MODE GFX_AUTODETECT_WINDOWED
+#ifdef ALLEGRO_UNIX
+#include <sys/time.h>
+static void YIELD(void)
+{
+ struct timeval tv;
+ tv.tv_sec = 0;
+ tv.tv_usec = 1;
+ select(0, NULL, NULL, NULL, &tv);
+}
+#else
+#define YIELD() yield_timeslice()
+#endif
+#endif
+
+
+
+static void usage(void)
+{
+ allegro_message(
+ "Usage: playduh file.duh\n"
+ "This will play the .duh file specified.\n"
+ "You can control playback quality by editing dumb.ini.\n"
+ );
+
+ exit(1);
+}
+
+
+
+int main(int argc, char *argv[])
+{
+ DUH *duh;
+ AL_DUH_PLAYER *dp;
+
+ if (allegro_init())
+ return 1;
+
+ if (argc != 2)
+ usage();
+
+ set_config_file("dumb.ini");
+
+ if (install_keyboard()) {
+ allegro_message("Failed to initialise keyboard driver!\n");
+ return 1;
+ }
+
+ set_volume_per_voice(0);
+
+ if (install_sound(DIGI_AUTODETECT, MIDI_NONE, NULL)) {
+ allegro_message("Failed to initialise sound driver!\n%s\n", allegro_error);
+ return 1;
+ }
+
+ atexit(&dumb_exit);
+
+ dumb_register_stdfiles();
+
+/*
+ dumb_register_sigtype_sample();
+ dumb_register_sigtype_combining();
+ dumb_register_sigtype_stereopan();
+ dumb_register_sigtype_sequence();
+*/
+
+ duh = load_duh(argv[1]);
+ if (!duh) {
+ allegro_message("Failed to load %s!\n", argv[1]);
+ return 1;
+ }
+
+ dumb_resampling_quality = get_config_int("sound", "dumb_resampling_quality", 4);
+ // Are we sure dumb_it_max_to_mix will be unused? Can decide when editor matures...
+
+#ifndef ALLEGRO_DOS
+ {
+ const char *fn = get_filename(argv[1]);
+ int w = strlen(fn);
+ if (w < 22) w = 22;
+ w = (w + 2) * 4;
+
+ set_window_title("DUMB - IT player");
+
+ if (set_gfx_mode(GFX_DUMB_MODE, w*2, 80, 0, 0) == 0) {
+ acquire_screen();
+ textout_centre(screen, font, fn, w, 28, 14);
+ textout_centre(screen, font, "Press any key to exit.", w, 44, 11);
+ release_screen();
+ }
+ }
+
+ //set_window_close_hook(&closehook);
+#endif
+
+ set_display_switch_mode(SWITCH_BACKGROUND);
+
+ dp = al_start_duh(duh, 2, 0, 1.0,
+ get_config_int("sound", "buffer_size", 4096),
+ get_config_int("sound", "sound_freq", 44100));
+
+ for (;;) {
+ if (keypressed()) {
+ readkey();
+ break;
+ }
+
+ if (al_poll_duh(dp) || closed)
+ break;
+
+ YIELD();
+ }
+
+ al_stop_duh(dp);
+
+ unload_duh(duh);
+
+ return 0;
+}
+END_OF_MAIN();
+