|
|
|
/* 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., 51 Franklin Street, Fifth Floor,
|
|
|
|
* Boston, MA 02110-1301, 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;
|
|
|
|
}
|