summaryrefslogtreecommitdiffstats
path: root/flow/gsl/gslwchunk.c
diff options
context:
space:
mode:
Diffstat (limited to 'flow/gsl/gslwchunk.c')
-rw-r--r--flow/gsl/gslwchunk.c279
1 files changed, 279 insertions, 0 deletions
diff --git a/flow/gsl/gslwchunk.c b/flow/gsl/gslwchunk.c
new file mode 100644
index 0000000..1fa4d74
--- /dev/null
+++ b/flow/gsl/gslwchunk.c
@@ -0,0 +1,279 @@
+/* GSL - Generic Sound Layer
+ * Copyright (C) 2001-2002 Tim Janik
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#include "gslwavechunk.h"
+#include "gsldatahandle.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <math.h>
+
+enum {
+ VERBOSITY_NONE,
+ VERBOSITY_SETUP,
+ VERBOSITY_BLOCKS,
+ VERBOSITY_DATA,
+ VERBOSITY_PADDING,
+ VERBOSITY_CHECKS,
+};
+static guint verbosity = VERBOSITY_SETUP;
+
+static gfloat my_data[] = {
+ 0.555555555,1,2,3,4,5,6,7,8,9,
+ 10,11,12,13,14,15,16,17,18,19,
+ 20,21,22,23,24,25,26,27,28,29,
+ 30,31,32,33,34,35,36,
+};
+static guint my_data_length = sizeof (my_data) / sizeof (my_data[0]);
+
+static void print_block (GslWaveChunk *wchunk,
+ GslWaveChunkBlock *block);
+
+#define DEBUG_SIZE (1024 * 256)
+#define MINI_DEBUG_SIZE (16)
+
+static void
+run_tests (GslWaveLoopType loop_type,
+ gint play_dir,
+ gint loop_first,
+ gint loop_last,
+ gint loop_count)
+{
+ gfloat tmpstorage[DEBUG_SIZE], *cmpblock = tmpstorage + DEBUG_SIZE / 2;
+ GslDataHandle *myhandle;
+ GslDataCache *dcache;
+ GslWaveChunkBlock block = { 0, 0 };
+ GslWaveChunk *wchunk;
+ GslErrorType error;
+
+ myhandle = gsl_data_handle_new_mem (1, 32, my_data_length, my_data, NULL);
+ dcache = gsl_data_cache_new (myhandle, 1);
+ gsl_data_handle_unref (myhandle);
+ wchunk = gsl_wave_chunk_new (dcache,
+ 44.0, 44100.0,
+ loop_type, loop_first, loop_last, loop_count);
+ error = gsl_wave_chunk_open (wchunk);
+ if (error)
+ g_error ("failed to open wave chunk: %s", gsl_strerror (error));
+ gsl_wave_chunk_unref (wchunk);
+ if (verbosity >= VERBOSITY_SETUP)
+ g_print ("SETUP: loop_type=%u loop_first=%ld loop_last=%ld loop_count=%d playdir=%+d\n",
+ wchunk->loop_type, wchunk->loop_first, wchunk->loop_last, wchunk->loop_count, play_dir);
+ gsl_wave_chunk_debug_block (wchunk, - DEBUG_SIZE / 2, DEBUG_SIZE, cmpblock - DEBUG_SIZE / 2);
+
+ block.play_dir = play_dir;
+
+ block.offset = block.play_dir < 0 ? wchunk->wave_length + MINI_DEBUG_SIZE/2 : -MINI_DEBUG_SIZE/2;
+ while (block.offset < wchunk->wave_length + MINI_DEBUG_SIZE &&
+ block.offset > -MINI_DEBUG_SIZE)
+ {
+ gint i, start, end, abort;
+
+ gsl_wave_chunk_use_block (wchunk, &block);
+
+ print_block (wchunk, &block);
+ if (block.play_dir > 0)
+ {
+ start = block.offset - wchunk->n_pad_values;
+ end = block.offset + block.length + wchunk->n_pad_values;
+ }
+ else
+ {
+ start = block.offset + wchunk->n_pad_values;
+ end = block.offset - block.length - wchunk->n_pad_values;
+ }
+ abort = FALSE;
+ for (i = start; i != end; i += block.play_dir)
+ {
+ gfloat v = (block.play_dir < 0) ^ (block.dirstride > 0) ? block.start[i - block.offset] : block.start[block.offset - i];
+
+ if (fabs (cmpblock[i] - v) > 1e-15)
+ {
+ abort = TRUE;
+ verbosity = 99;
+ }
+ if (verbosity >= VERBOSITY_CHECKS)
+ g_print ("%s: offset=%d (block.offset=%ld) value=%.16f found=%.16f\n",
+ fabs (cmpblock[i] - v) > 1e-15 ? "MISMATCH" : "match",
+ i, (i - block.offset), cmpblock[i], v);
+ }
+ if (abort)
+ {
+ g_error ("mismatches occoured, setup: loop_type=%u loop_first=%ld loop_last=%ld loop_count=%d (length=%ld)",
+ wchunk->loop_type, wchunk->loop_first, wchunk->loop_last, wchunk->loop_count,
+ gsl_data_handle_length (wchunk->dcache->dhandle));
+ }
+
+ gsl_wave_chunk_unuse_block (wchunk, &block);
+
+ block.offset = block.next_offset;
+ /* block.offset += block.play_dir; */
+ }
+ gsl_wave_chunk_close (wchunk);
+ gsl_data_cache_unref (dcache);
+}
+
+static void
+print_block (GslWaveChunk *wchunk,
+ GslWaveChunkBlock *block)
+{
+ gfloat *p = NULL;
+ guint i;
+
+ if (verbosity >= VERBOSITY_BLOCKS)
+ {
+ g_print ("BLOCK:");
+ g_print (" offset=%ld", block->offset);
+ g_print (" length=%ld", block->length);
+ g_print (" dirstride=%d", block->dirstride);
+ }
+
+ if (verbosity >= VERBOSITY_PADDING)
+ {
+ g_print (" {prepad:");
+ i = wchunk->n_pad_values;
+ p = block->start - (block->dirstride > 0 ? i : -i);
+ while (i--)
+ {
+ g_print (" %.1f", *p);
+ p += block->dirstride;
+ }
+ g_print ("}");
+ }
+
+ if (verbosity >= VERBOSITY_DATA)
+ {
+ g_print (" {data:");
+ p = block->start;
+ while (p != block->end)
+ {
+ g_print (" %.1f", *p);
+ p += block->dirstride;
+ }
+ g_print ("}");
+ }
+
+ if (verbosity >= VERBOSITY_PADDING)
+ {
+ i = wchunk->n_pad_values;
+ g_print (" {postpad:");
+ while (i--)
+ {
+ g_print (" %.1f", *p);
+ p += block->dirstride;
+ }
+ g_print ("}");
+ }
+
+ if (verbosity >= VERBOSITY_BLOCKS)
+ g_print ("\n");
+}
+
+int
+main (gint argc,
+ gchar *argv[])
+{
+ GslConfigValue gslconfig[] = {
+ { "wave_chunk_padding", 1, },
+ { "wave_chunk_big_pad", 2, },
+ { "dcache_block_size", 16, },
+ { NULL, },
+ };
+ gint i, j, k;
+
+ if (!g_thread_supported ())
+ g_thread_init (NULL);
+ gsl_init (gslconfig, NULL);
+
+ if (1)
+ {
+ GslDataHandle *myhandle;
+ GslDataHandle *rhandle1, *rhandle2;
+ GslLong o, l, i, e;
+ GslErrorType error;
+
+ g_print ("reversed datahandle test:...\n");
+
+ myhandle = gsl_data_handle_new_mem (1, 32, my_data_length, my_data, NULL);
+ rhandle1 = gsl_data_handle_new_reverse (myhandle);
+ gsl_data_handle_unref (myhandle);
+ rhandle2 = gsl_data_handle_new_reverse (rhandle1);
+ gsl_data_handle_unref (rhandle1);
+ error = gsl_data_handle_open (rhandle2);
+ if (error)
+ g_error ("failed to open rhandle2: %s", gsl_strerror (error));
+ gsl_data_handle_unref (rhandle2);
+
+ g_assert (gsl_data_handle_length (rhandle2) == gsl_data_handle_length (myhandle));
+
+ for (i = 1; i < 8; i++)
+ {
+ o = 0;
+ l = gsl_data_handle_length (rhandle2);
+ while (l)
+ {
+ gfloat d1[8], d2[8];
+
+ e = gsl_data_handle_read (myhandle, o, MIN (i, l), d1);
+ g_assert (e == MIN (i, l));
+ e = gsl_data_handle_read (rhandle2, o, MIN (i, l), d2);
+ g_assert (e == MIN (i, l));
+ g_assert (memcmp (d1, d2, sizeof (d1[0]) * e) == 0);
+ l -= e;
+ o += e;
+ }
+ }
+ gsl_data_handle_close (rhandle2);
+ g_print ("passed.\n");
+ }
+
+ if (1)
+ {
+ g_print ("primitive loop tests:...\n");
+
+ run_tests (GSL_WAVE_LOOP_NONE, -1, 0, 0, 0);
+
+ run_tests (GSL_WAVE_LOOP_NONE, 1, 0, 0, 0);
+ run_tests (GSL_WAVE_LOOP_NONE, -1, 0, 0, 0);
+ run_tests (GSL_WAVE_LOOP_JUMP, 1, 0, 0, 0);
+ run_tests (GSL_WAVE_LOOP_PINGPONG, 1, 0, 0, 0);
+ run_tests (GSL_WAVE_LOOP_JUMP, -1, 0, 0, 0);
+ run_tests (GSL_WAVE_LOOP_PINGPONG, -1, 0, 0, 0);
+ g_print ("passed.\n");
+ }
+
+ if (1)
+ {
+ g_print ("brute loop tests:...\n");
+ for (i = 1; i < 7; i++)
+ for (j = 0; j < my_data_length - 1; j++)
+ for (k = j + 1; k < my_data_length; k++)
+ {
+ run_tests (GSL_WAVE_LOOP_JUMP, 1, j, k, i);
+ run_tests (GSL_WAVE_LOOP_PINGPONG, 1, j, k, i);
+ run_tests (GSL_WAVE_LOOP_JUMP, -1, j, k, i);
+ run_tests (GSL_WAVE_LOOP_PINGPONG, -1, j, k, i);
+ }
+ g_print ("passed.\n");
+ }
+
+ return 0;
+}