diff options
Diffstat (limited to 'flow/gsl/gslwchunk.c')
-rw-r--r-- | flow/gsl/gslwchunk.c | 279 |
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; +} |