You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
arts/flow/gsl/gslwchunk.c

280 lines
7.7 KiB

/* 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;
}