diff options
Diffstat (limited to 'plugins/dumb/dumb-kode54/examples')
-rw-r--r-- | plugins/dumb/dumb-kode54/examples/dumb2wav.c | 962 | ||||
-rw-r--r-- | plugins/dumb/dumb-kode54/examples/dumbout.c | 187 | ||||
-rw-r--r-- | plugins/dumb/dumb-kode54/examples/dumbplay.c | 577 | ||||
-rw-r--r-- | plugins/dumb/dumb-kode54/examples/playduh.c | 338 |
4 files changed, 1066 insertions, 998 deletions
diff --git a/plugins/dumb/dumb-kode54/examples/dumb2wav.c b/plugins/dumb/dumb-kode54/examples/dumb2wav.c index 9a4c5090..fae7fab6 100644 --- a/plugins/dumb/dumb-kode54/examples/dumb2wav.c +++ b/plugins/dumb/dumb-kode54/examples/dumb2wav.c @@ -1,481 +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;
-}
+/* _______ ____ __ ___ ___ + * \ _ \ \ / \ / \ \ / / ' ' ' + * | | \ \ | | || | \/ | . . + * | | | | | | || ||\ /| | + * | | | | | | || || \/ | | ' ' ' + * | | | | | | || || | | . . + * | |_/ / \ \__// || | | + * /_______/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 index 3082b3b4..1ca85adf 100644 --- a/plugins/dumb/dumb-kode54/examples/dumbout.c +++ b/plugins/dumb/dumb-kode54/examples/dumbout.c @@ -12,8 +12,8 @@ * | < / \_
* By entheh. | \/ /\ /
* \_ / > /
- * | \ / /
- * | ' /
+ * This example demonstrates how to use DUMB without | \ / /
+ * using Allegro. | ' /
* \__/
*/
@@ -25,15 +25,12 @@ #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! */
{
@@ -49,7 +46,6 @@ int main(int argc, const char *const *argv) /* I'm const-crazy! */ int unsign = 0;
int freq = 44100;
int n_channels = 2;
- int solo = -1;
float volume = 1.0f;
float delay = 0.0f;
float delta;
@@ -69,7 +65,7 @@ int main(int argc, const char *const *argv) /* I'm const-crazy! */ fprintf(stderr,
"Cannot specify multiple filenames!\n"
"Second filename found: \"%s\"\n", arg);
- return 1;
+ return EXIT_FAILURE;
}
fn = arg;
continue;
@@ -82,7 +78,7 @@ int main(int argc, const char *const *argv) /* I'm const-crazy! */ case 'O':
if (i >= argc) {
fprintf(stderr, "Out of arguments; output filename expected!\n");
- return 1;
+ return EXIT_FAILURE;
}
fn_out = argv[i++];
break;
@@ -90,41 +86,38 @@ int main(int argc, const char *const *argv) /* I'm const-crazy! */ case 'D':
if (i >= argc) {
fprintf(stderr, "Out of arguments; delay expected!\n");
- return 1;
+ return EXIT_FAILURE;
}
delay = (float)strtod(argv[i++], &endptr);
if (*endptr != 0 || delay < 0.0f || delay > 64.0f) {
fprintf(stderr, "Invalid delay!\n");
- return 1;
+ return EXIT_FAILURE;
}
break;
case 'v':
case 'V':
if (i >= argc) {
fprintf(stderr, "Out of arguments; volume expected!\n");
- return 1;
+ return EXIT_FAILURE;
}
volume = (float)strtod(argv[i++], &endptr);
if (*endptr != 0 || volume < -8.0f || volume > 8.0f) {
fprintf(stderr, "Invalid volume!\n");
- return 1;
+ return EXIT_FAILURE;
}
break;
case 's':
case 'S':
if (i >= argc) {
fprintf(stderr, "Out of arguments; sampling rate expected!\n");
- return 1;
+ return EXIT_FAILURE;
}
freq = strtol(argv[i++], &endptr, 10);
if (*endptr != 0 || freq < 1 || freq > 960000) {
fprintf(stderr, "Invalid sampling rate!\n");
- return 1;
+ return EXIT_FAILURE;
}
break;
- case 'f':
- depth = 32;
- break;
case '8':
depth = 8;
break;
@@ -144,29 +137,17 @@ int main(int argc, const char *const *argv) /* I'm const-crazy! */ case 'R':
if (i >= argc) {
fprintf(stderr, "Out of arguments; resampling quality expected!\n");
- return 1;
+ return EXIT_FAILURE;
}
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;
+ return EXIT_FAILURE;
}
break;
default:
fprintf(stderr, "Invalid switch - '%c'!\n", isprint(arg[-1]) ? arg[-1] : '?');
- return 1;
+ return EXIT_FAILURE;
}
}
}
@@ -187,21 +168,28 @@ int main(int argc, const char *const *argv) /* I'm const-crazy! */ "-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;
+ "-r <value> specify the resampling quality to use\n");
+ return EXIT_FAILURE;
}
+ /* Initialisation, as in dumbplay.c, except this time we have to
+ * register stdio files since we're not using Allegro.
+ */
atexit(&dumb_exit);
dumb_register_stdfiles();
+ /* Mix as many voices as possible. DUMB only maintains state for 256
+ * of them.
+ */
dumb_it_max_to_mix = 256;
+ /* We may as well try and load a .duh file too, even though that file
+ * format will probably never materialise. :)
+ */
duh = load_duh(fn);
if (!duh) {
duh = dumb_load_it(fn);
@@ -213,38 +201,22 @@ int main(int argc, const char *const *argv) /* I'm const-crazy! */ duh = dumb_load_mod(fn);
if (!duh) {
fprintf(stderr, "Unable to open %s!\n", fn);
- return 1;
+ return EXIT_FAILURE;
}
}
}
}
}
+ /* This is equivalent to al_start_duh(), except the object returned
+ * contains playback state alone and no Allegro audio stream. We can
+ * get samples from it on demand.
+ */
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;
- }
- }
- }
- }
+ return EXIT_FAILURE;
}
if (fn_out) {
@@ -258,7 +230,7 @@ int main(int argc, const char *const *argv) /* I'm const-crazy! */ fprintf(stderr, "Unable to open %s for writing!\n", fn_out);
duh_end_sigrenderer(sr);
unload_duh(duh);
- return 1;
+ return EXIT_FAILURE;
}
}
} else {
@@ -268,7 +240,7 @@ int main(int argc, const char *const *argv) /* I'm const-crazy! */ fprintf(stderr, "Out of memory!\n");
duh_end_sigrenderer(sr);
unload_duh(duh);
- return 1;
+ return EXIT_FAILURE;
}
strcpy(fn_out, fn);
for (p = fn_out; *p; p++)
@@ -281,52 +253,48 @@ int main(int argc, const char *const *argv) /* I'm const-crazy! */ free(fn_out);
duh_end_sigrenderer(sr);
unload_duh(duh);
- return 1;
+ return EXIT_FAILURE;
}
free(fn_out);
}
+ /* Install dumb_it_callback_terminate() as the loop and XM speed zero
+ * callbacks. That means DUMB will stop generating samples
+ * immediately upon either of these events occurring.
+ * The callback function itself is provided by DUMB.
+ */
{
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;
+ /* This length value is not accurate. It is only used for the
+ * progress bar.
+ */
+ length = (LONG_LONG)duh_get_length(duh) * 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 = depth == 16 ? 8192 : 16384;
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);
- }
- }
-
+ /* Write the initial delay to the file if one was requested. */
{
long l = (long)floor(delay * freq + 0.5f);
l *= n_channels * (depth >> 3);
if (l) {
- if (unsign && depth != 32) {
+ if (unsign) {
if (depth == 16) {
if (bigendian) {
for (i = 0; i < 8192; i++) {
- buffer.s8[i*2] = 0x80;
- buffer.s8[i*2+1] = 0x00;
+ buffer.s8[i*2] = (char)0x80;
+ buffer.s8[i*2+1] = (char)0x00;
}
} else {
for (i = 0; i < 8192; i++) {
- buffer.s8[i*2] = 0x00;
- buffer.s8[i*2+1] = 0x80;
+ buffer.s8[i*2] = (char)0x00;
+ buffer.s8[i*2+1] = (char)0x80;
}
}
} else
@@ -341,43 +309,43 @@ int main(int argc, const char *const *argv) /* I'm const-crazy! */ }
}
+ /* On Linux, clock() is a measure of how much processing time was
+ * used by the program.
+ */
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;
- }
+ /* This is the function that generates samples. It is all
+ * explained in docs/dumb.txt. The return value is the number
+ * of samples generated. If it's less than the buffer size,
+ * we known that it's finished.
+ */
+ int l = duh_render(sr, depth, unsign, volume, delta, bufsize, &buffer);
+ if (depth == 16) {
+ /* If you are only targeting platforms of a specific
+ * endianness or you can find out what endianness the
+ * target platform is, you should be able to
+ * eliminate one case here.
+ */
+ if (bigendian) {
+ for (i = 0; i < l * n_channels; i++) {
+ short val = buffer.s16[i];
+ buffer.s8[i*2] = (char)(val >> 8);
+ buffer.s8[i*2+1] = (char)val;
}
- }
- } 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)));
+ } else {
+ for (i = 0; i < l * n_channels; i++) {
+ short val = buffer.s16[i];
+ buffer.s8[i*2] = (char)val;
+ buffer.s8[i*2+1] = (char)(val >> 8);
}
}
}
if (outf) fwrite(buffer.s8, 1, l * n_channels * (depth >> 3), outf);
if (l < bufsize) break;
done += l;
- l = done * 64 / length;
+ l = (int)(done * 64 / length);
while (dots < 64 && l > dots) {
fprintf(stderr, "|");
dots++;
@@ -392,13 +360,12 @@ int main(int argc, const char *const *argv) /* I'm const-crazy! */ end = clock();
- if (depth == 32) destroy_sample_buffer(internal_buffer);
-
+ /* Deallocate stuff and close the output file. */
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;
+ return EXIT_SUCCESS;
}
diff --git a/plugins/dumb/dumb-kode54/examples/dumbplay.c b/plugins/dumb/dumb-kode54/examples/dumbplay.c index 521113f6..c097ea80 100644 --- a/plugins/dumb/dumb-kode54/examples/dumbplay.c +++ b/plugins/dumb/dumb-kode54/examples/dumbplay.c @@ -1,238 +1,339 @@ -/* _______ ____ __ ___ ___
- * \ _ \ \ / \ / \ \ / / ' ' '
- * | | \ \ | | || | \/ | . .
- * | | | | | | || ||\ /| |
- * | | | | | | || || \/ | | ' ' '
- * | | | | | | || || | | . .
- * | |_/ / \ \__// || | |
- * /_______/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();
+/* _______ ____ __ ___ ___ + * \ _ \ \ / \ / \ \ / / ' ' ' + * | | \ \ | | || | \/ | . . + * | | | | | | || ||\ /| | + * | | | | | | || || \/ | | ' ' ' + * | | | | | | || || | | . . + * | |_/ / \ \__// || | | + * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque + * / \ + * / . \ + * dumbplay.c - Not-so-simple program to play / / \ \ + * music. It used to be simpler! | < / \_ + * | \/ /\ / + * By entheh. \_ / > / + * | \ / / + * If this example does not explain everything you | ' / + * need to know, or you write your own code and it \__/ + * doesn't work, please refer to docs/howto.txt for + * step-by-step instructions or docs/dumb.txt for a detailed description of + * each of DUMB's functions. + */ + +#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" + + + +/* Hook function to be called when the close button is clicked. If the + * variable is set, the program will exit. Not needed in DOS. + */ +#ifndef ALLEGRO_DOS + static volatile int closed = 0; + static void closehook(void) { closed = 1; } +#else +# define closed 0 +#endif + + +/* Platform-specific code. We use GDI in Windows since there's no point in + * using an accelerated graphics driver. If we can, we define our own YIELD() + * function that allows the system to sleep when it has nothing to do. This + * may now be part of Allegro, but I haven't kept up with it. You can ignore + * this stuff. + */ +#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 + + + +/* Playback flow callback functions. In DOS we don't set a graphics mode, so + * we can print a message to the console when a callback is invoked. On other + * platforms, we add a message to the window the program has created. + */ +#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; /* Encapsulates the music file. */ + AL_DUH_PLAYER *dp; /* Holds the current playback state. */ + + /* Initialise Allegro */ + if (allegro_init()) + return EXIT_FAILURE; + + /* Check that we have one argument (plus the executable name). */ + if (argc != 2) + usage(argv[0]); + + /* Tell Allegro where to find configuration data. This means you can + * put any settings for Allegro in dumb.ini. See Allegro's + * documentation for more information. + */ + set_config_file("dumb.ini"); + + /* Initialise Allegro's keyboard input. */ + if (install_keyboard()) { + allegro_message("Failed to initialise keyboard driver!\n"); + return EXIT_FAILURE; + } + + /* This function call is appropriate for a program that will play one + * sample or one audio stream at a time. If you have sound effects + * too, you may want to increase the parameter. See Allegro's + * documentation for details on what the parameter means. Note that + * newer versions of Allegro act as if set_volume_per_voice() was + * called with parameter 1 initially, while older versions behave as + * if -1 was passed, so you should call the function if you want + * consistent behaviour. + */ + set_volume_per_voice(0); + + /* Initialise Allegro's sound output system. */ + if (install_sound(DIGI_AUTODETECT, MIDI_NONE, NULL)) { + allegro_message("Failed to initialise sound driver!\n%s\n", allegro_error); + return EXIT_FAILURE; + } + + /* dumb_exit() is a function defined by DUMB. This operation arranges + * for dumb_exit() to be called last thing before the program exits. + * dumb_exit() does a bit of cleaning up for you. atexit() is + * declared in stdlib.h. + */ + atexit(&dumb_exit); + + /* DUMB defines its own wrappers for file input. There is a struct + * called DUMBFILE that holds function pointers for the various file + * operations needed by DUMB. You can decide whether to use stdio + * FILE objects, Allegro's PACKFILEs or something else entirely. No + * wrapper is installed initially, so you must call this or + * dumb_register_stdfiles() or set up your own before trying to load + * modules by file name. (If you are using another method, such as + * loading an Allegro datafile with modules embedded in it, then DUMB + * never opens a file by file name so this doesn't apply.) + */ + dumb_register_packfiles(); + + /* Load the module file into a DUH object. Quick and dirty: try the + * loader for each format until one succeeds. Note that 15-sample + * mods have no identifying features, so dumb_load_mod() may succeed + * on files that aren't mods at all. We therefore try that one last. + */ + 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 EXIT_FAILURE; + } + } + } + } + + /* Read the quality values from the config file we told Allegro to + * use. You may want to hardcode these or provide a more elaborate + * interface via which the user can control them. + */ + 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); + + /* If we're not in DOS, show a window and register our close hook + * function. + */ +# 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; + } + + /* Silly check to get around the fact that someone stupidly removed + * an old function from Allegro instead of deprecating it. The old + * function was put back a version later, but we may as well use the + * new one if it's there! + */ +# 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 + + /* We want to continue running if the user switches to another + * application. + */ + set_display_switch_mode(SWITCH_BACKGROUND); + + /* We have the music loaded, but it isn't playing yet. This starts it + * playing. We construct a second object, the AL_DUH_PLAYER, to + * represent the playing music. This means you can play the music + * twice at the same time should you want to! + * + * Specify the number of channels (2 for stereo), which 'signal' to + * play (always 0 for modules), the volume (1.0f for default), the + * buffer size (4096 generally works well) and the sampling frequency + * (ideally match the final output frequency Allegro is using). An + * Allegro audio stream will be started. + */ + dp = al_start_duh(duh, 2, 0, 1.0f, + get_config_int("sound", "buffer_size", 4096), + get_config_int("sound", "sound_freq", 44100)); + + /* Register our callback functions so that they are called when the + * music loops or stops. See docs/howto.txt for more information. + * There is no threading issue: DUMB will only process playback + * in al_poll_duh(), which we call below. + */ + { + 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); + } + + /* Main loop. */ + for (;;) { + /* Check for keys in the buffer. If we get one, discard it + * and exit the main loop. + */ + if (keypressed()) { + readkey(); + break; + } + + /* Poll the music. We exit the loop if al_poll_duh() has + * returned nonzero (music finished) or the window has been + * closed. al_poll_duh() might return nonzero if you have set + * up a callback that tells the music to stop. + */ + if (al_poll_duh(dp) || closed) + break; + + /* Give other threads a look-in, or allow the processor to + * sleep for a bit. YIELD() is defined further up in this + * file. + */ + YIELD(); + } + + /* Remove the audio stream and deallocate the memory being used for + * the playback state. We set dp to NULL to emphasise that the object + * has gone. + */ + al_stop_duh(dp); + dp = NULL; + + /* Free the DUH object containing the actual music data. */ + unload_duh(duh); + duh = NULL; + + /* All done! */ + return EXIT_SUCCESS; +} +END_OF_MAIN(); diff --git a/plugins/dumb/dumb-kode54/examples/playduh.c b/plugins/dumb/dumb-kode54/examples/playduh.c index 31d7b619..0fb33607 100644 --- a/plugins/dumb/dumb-kode54/examples/playduh.c +++ b/plugins/dumb/dumb-kode54/examples/playduh.c @@ -1,169 +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();
-
+/* _______ ____ __ ___ ___ + * \ _ \ \ / \ / \ \ / / ' ' ' + * | | \ \ | | || | \/ | . . + * | | | | | | || ||\ /| | + * | | | | | | || || \/ | | ' ' ' + * | | | | | | || || | | . . + * | |_/ / \ \__// || | | + * /_______/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(); + |