aboutsummaryrefslogtreecommitdiff
path: root/engines/sci/sfx/mixer/test.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/sci/sfx/mixer/test.cpp')
-rw-r--r--engines/sci/sfx/mixer/test.cpp351
1 files changed, 351 insertions, 0 deletions
diff --git a/engines/sci/sfx/mixer/test.cpp b/engines/sci/sfx/mixer/test.cpp
new file mode 100644
index 0000000000..20b3e952e1
--- /dev/null
+++ b/engines/sci/sfx/mixer/test.cpp
@@ -0,0 +1,351 @@
+/***************************************************************************
+ test.c Copyright (C) 2003 Christoph Reichenbach
+
+
+ This program may be modified and copied freely according to the terms of
+ the GNU general public license (GPL), as long as the above copyright
+ notice and the licensing information contained herein are preserved.
+
+ Please refer to www.gnu.org for licensing details.
+
+ This work is provided AS IS, without warranty of any kind, expressed or
+ implied, including but not limited to the warranties of merchantibility,
+ noninfringement, and fitness for a specific purpose. The author will not
+ be held liable for any damage caused by this work or derivatives of it.
+
+ By using this source code, you agree to the licensing terms as stated
+ above.
+
+
+ Please contact the maintainer for bug reports or inquiries.
+
+ Current Maintainer:
+
+ Christoph Reichenbach (CR) <jameson@linuxgames.com>
+
+***************************************************************************/
+/* Mixer inspection/test program */
+
+
+#include "../mixer.h"
+#include <time.h>
+
+#if 0
+sfx_pcm_mixer_t *mix;
+
+int dev_init(sfx_pcm_device_t *self);
+void dev_exit(sfx_pcm_device_t *self);
+int dev_option(sfx_pcm_device_t *self, char *name, char *value);
+int dev_output(sfx_pcm_device_t *self, byte *buf, int count);
+
+#define MIN_OUTPUT 128
+/* Min amount of output to compute */
+
+#define DEVICES_NR 10
+
+sfx_pcm_device_t devices[DEVICES_NR] = {
+ { "test-1", "0", dev_init, dev_exit, dev_option, dev_output,
+ { 200, SFX_PCM_MONO, SFX_PCM_FORMAT_U8 }, 1024, NULL },
+#if (DEVICES_NR > 1)
+ { "test-2", "0", dev_init, dev_exit, dev_option, dev_output,
+ { 200, SFX_PCM_STEREO_LR, SFX_PCM_FORMAT_U8 }, 1024, NULL },
+ { "test-3", "0", dev_init, dev_exit, dev_option, dev_output,
+ { 200, SFX_PCM_STEREO_RL, SFX_PCM_FORMAT_U8 }, 1024, NULL },
+ { "test-4", "0", dev_init, dev_exit, dev_option, dev_output,
+ { 200, SFX_PCM_MONO, SFX_PCM_FORMAT_S8 }, 1024, NULL },
+ { "test-5", "0", dev_init, dev_exit, dev_option, dev_output,
+ { 200, SFX_PCM_MONO, SFX_PCM_FORMAT_U16_LE }, 1024, NULL },
+ { "test-6", "0", dev_init, dev_exit, dev_option, dev_output,
+ { 200, SFX_PCM_MONO, SFX_PCM_FORMAT_U16_BE }, 1024, NULL },
+ { "test-7", "0", dev_init, dev_exit, dev_option, dev_output,
+ { 200, SFX_PCM_MONO, SFX_PCM_FORMAT_S16_LE }, 1024, NULL },
+ { "test-8", "0", dev_init, dev_exit, dev_option, dev_output,
+ { 200, SFX_PCM_MONO, SFX_PCM_FORMAT_S16_BE }, 1024, NULL },
+ { "test-9", "0", dev_init, dev_exit, dev_option, dev_output,
+ { 200, SFX_PCM_STEREO_RL, SFX_PCM_FORMAT_S16_LE }, 1024, NULL },
+ { "test-10", "0", dev_init, dev_exit, dev_option, dev_output,
+ { 200, SFX_PCM_STEREO_LR, SFX_PCM_FORMAT_U16_BE }, 1024, NULL }
+#endif
+};
+
+int output_count;
+
+int dev_init(sfx_pcm_device_t *self)
+{
+ output_count = 0;
+
+ fprintf(stderr, "[DEV] Initialised device %p as follows:\n"
+ "\trate = %d\n"
+ "\tstereo = %s\n"
+ "\tbias = %x\n"
+ "\tbytes/sample = %d\n"
+ "\tendianness = %s\n",
+ self,
+ self->conf.rate,
+ self->conf.stereo? ((self->conf.stereo == SFX_PCM_STEREO_LR)? "Left, Right" : "Right, Left") : "No",
+ self->conf.format & ~SFX_PCM_FORMAT_LMASK,
+ (self->conf.format & SFX_PCM_FORMAT_16)? 2 : 1,
+ ((self->conf.format & SFX_PCM_FORMAT_ENDIANNESS) == SFX_PCM_FORMAT_BE)? "big" : "little");
+ return 0;
+}
+
+void dev_exit(sfx_pcm_device_t *self)
+{
+ fprintf(stderr, "[DEV] Uninitialising device\n");
+}
+
+int dev_option(sfx_pcm_device_t *self, char *name, char *value)
+{
+ fprintf(stderr, "[DEV] Set option '%s' to '%s'\n", name, value);
+ return 0;
+}
+
+int dev_output_enabled = 0;
+
+int dev_output(sfx_pcm_device_t *self, byte *buf, int count)
+{
+ int mono_sample_size = ((self->conf.format & SFX_PCM_FORMAT_16)? 2 : 1);
+ int sample_size = (self->conf.stereo? 2 : 1) * mono_sample_size;
+ int bias = self->conf.format & ~SFX_PCM_FORMAT_LMASK;
+ int is_bigendian = (self->conf.format & SFX_PCM_FORMAT_ENDIANNESS) == SFX_PCM_FORMAT_BE;
+ byte *left_channel = buf;
+ byte *right_channel = buf;
+
+ if (!dev_output_enabled)
+ return 0;
+
+ if (self->conf.format & SFX_PCM_FORMAT_16)
+ bias <<= 8;
+
+ if (self->conf.stereo == SFX_PCM_STEREO_LR)
+ right_channel += mono_sample_size;
+ if (self->conf.stereo == SFX_PCM_STEREO_RL)
+ left_channel += mono_sample_size;
+
+ while (count--) {
+ int right = right_channel[0];
+ int left = left_channel[0];
+ int second_byte = ((self->conf.format & SFX_PCM_FORMAT_16)? 1 : 0);
+
+ if (second_byte) {
+
+ if (is_bigendian) {
+ left = left << 8 | left_channel[1];
+ right = right << 8 | right_channel[1];
+ } else {
+ left = left | left_channel[1] << 8;
+ right = right | right_channel[1] << 8;
+ }
+ }
+
+ left -= bias;
+ right -= bias;
+
+ if (!second_byte) {
+ left <<= 8;
+ right <<= 8;
+ }
+
+ fprintf(stderr, "[DEV] %p play %04x:\t%04x %04x\n", self, output_count++, left & 0xffff, right & 0xffff);
+
+ left_channel += sample_size;
+ right_channel += sample_size;
+ }
+ return 0;
+}
+
+/* Feeds for debugging */
+
+typedef struct {
+ int i;
+} int_struct;
+
+int feed_poll(sfx_pcm_feed_t *self, byte *dest, int size);
+void feed_destroy(sfx_pcm_feed_t *self);
+
+int_struct private_bits[10] = {
+ {0},
+ {0},
+ {0},
+ {0},
+ {0},
+ {0},
+ {0},
+ {0},
+ {0}
+};
+
+
+typedef struct {
+ int start;
+ int samples_nr;
+ byte *data;
+} sample_feed_t;
+
+#define FEEDS_NR 4
+
+sfx_pcm_feed_t feeds[FEEDS_NR] = {
+ { feed_poll, feed_destroy, &(private_bits[0]),
+ { 200, SFX_PCM_MONO, SFX_PCM_FORMAT_S8 }, "test-feed", 0, 0}
+#if FEEDS_NR > 1
+ ,{ feed_poll, feed_destroy, &(private_bits[1]),
+ { 400, SFX_PCM_MONO, SFX_PCM_FORMAT_U8 }, "test-feed", 1, 0}
+#endif
+#if FEEDS_NR > 2
+ ,{ feed_poll, feed_destroy, &(private_bits[2]),
+ { 20, SFX_PCM_MONO, SFX_PCM_FORMAT_S16_LE }, "test-feed", 2, 0}
+#endif
+#if FEEDS_NR > 3
+ ,{ feed_poll, feed_destroy, &(private_bits[3]),
+ { 150, SFX_PCM_STEREO_LR, SFX_PCM_FORMAT_S8 }, "test-feed", 3, 0}
+#endif
+ /*
+ ,{ feed_poll, feed_destroy, &(private_bits[4]),
+ {}, "test-feed", 4, 0}
+ ,{ feed_poll, feed_destroy, &(private_bits[5]),
+ {}, "test-feed", 5, 0}
+ */
+};
+
+byte feed_data_0[] = {0xfd, 0xfe, 0xff, 0, 1, 2, 3, 4, 5, 6};
+byte feed_data_1[] = {0x80, 0x90, 0xA0, 0xB0, 0xC0,
+ 0xD0, 0xD0, 0xC0, 0xB0, 0xA0, 0x90, 0x80};
+byte feed_data_2[] = {0x00, 0x00,
+ 0x00, 0x80,
+ 0xe8, 0x03};
+byte feed_data_3[] = {0x00, 0x10,
+ 0x01, 0x20,
+ 0x02, 0x30};
+
+sample_feed_t sample_feeds[FEEDS_NR] = {
+ { 1, 10, feed_data_0 }
+#if FEEDS_NR > 1
+ ,{ 21, 12, feed_data_1 }
+#endif
+#if FEEDS_NR > 2
+ ,{ 0, 3, feed_data_2 }
+#endif
+#if FEEDS_NR > 3
+ ,{ 40, 3, feed_data_3 }
+#endif
+};
+
+void
+feed_destroy(sfx_pcm_feed_t *self)
+{
+ int_struct *s = (int_struct *) self->internal;
+ s->i = 0; /* reset */
+}
+
+
+int
+feed_poll(sfx_pcm_feed_t *self, byte *dest, int size)
+{
+ int_struct *s = (int_struct *) self->internal;
+ int sample_size = self->sample_size;
+ sample_feed_t *data = &(sample_feeds[self->debug_nr]);
+ int bias = self->conf.format & ~SFX_PCM_FORMAT_LMASK;
+ byte neutral[4] = {0, 0, 0, 0};
+ int i;
+fprintf(stderr, "[feed] Asked for %d at %p, ss=%d\n", size, dest, sample_size);
+ if (bias) {
+ byte first = bias >> 8;
+ byte second = bias & 0xff;
+
+ if ((self->conf.format & SFX_PCM_FORMAT_ENDIANNESS) == SFX_PCM_FORMAT_LE) {
+ int t = first;
+ first = second;
+ second = t;
+ }
+
+ if (self->conf.format & SFX_PCM_FORMAT_16) {
+ neutral[0] = first;
+ neutral[1] = second;
+ neutral[2] = first;
+ neutral[3] = second;
+ } else {
+ neutral[0] = bias;
+ neutral[1] = bias;
+ }
+ }
+
+ for (i = 0; i < size; i++) {
+ int t = s->i - data->start;
+
+ if (t >= data->samples_nr)
+ return i;
+
+ if (t >= 0)
+ memcpy(dest, data->data + t * sample_size, sample_size);
+ else
+ memcpy(dest, neutral, sample_size);
+
+ dest += sample_size;
+ s->i++;
+ }
+ return size;
+}
+
+
+
+
+extern FILE *con_file;
+
+#define DELAY usleep((rand() / (RAND_MAX / 250L)))
+
+
+int
+main(int argc, char **argv)
+{
+ int dev_nr;
+
+ mix = sfx_pcm_find_mixer(NULL);
+
+ if (!mix) {
+ fprintf(stderr, "Error: Could not find a mixer!\n");
+ return 1;
+ } else {
+ fprintf(stderr, "Running %s, v%s\n",
+ mix->name, mix->version);
+ }
+ con_file = stderr;
+
+ srand(time(NULL));
+
+ for (dev_nr = 0; dev_nr < DEVICES_NR; dev_nr++) {
+ sfx_pcm_device_t *dev = &(devices[dev_nr++]);
+ int j;
+ dev->init(dev);
+ mix->init(mix, dev);
+
+ dev_output_enabled = 0;
+ /* Prime it to our timing */
+ for (j = 0; j < 250; j++) {
+ DELAY;
+ mix->process(mix);
+ }
+ dev_output_enabled = 1;
+
+ fprintf(stderr, "[test] Subscribing...\n");
+
+ for (j = 0; j < FEEDS_NR; j++)
+ mix->subscribe(mix, &(feeds[j]));
+
+ fprintf(stderr, "[test] Subscribed %d feeds.\n",
+ FEEDS_NR);
+
+ while (output_count < MIN_OUTPUT) {
+ DELAY;
+ mix->process(mix);
+ fprintf(stderr, "<tick>\n");
+ }
+
+ fprintf(stderr, "[test] Preparing finalisation\n");
+ mix->exit(mix);
+ fprintf(stderr, "[test] Mixer uninitialised\n");
+ }
+}
+
+#else
+int main() {}
+#endif