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 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203
|
/*
* sample_test.c - Sample audio conversion tests
*
* Tests every combination of audio format conversions (484 combinations).
* This is done by creating a double audio format triangle waveform and then
* for each transformation format pair, converting this waveform to the
* first format, then the second, then back to double again and comparing
* against the original.
*
* libInstPatch
* Copyright (C) 1999-2010 Joshua "Element" Green <jgreen@users.sourceforge.net>
*
* 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; version 2.1
* of the License only.
*
* 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 General Public License for more details.
*
* You should have received a copy of the GNU 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 or point your web browser to http://www.gnu.org.
*/
#include <libinstpatch/libinstpatch.h>
#define DEFAULT_AUDIO_SIZE (32 * 1024) /* default test waveform size in samples */
#define WAVEFORM_PERIOD 1684 /* something to exercise LSB bytes too */
#define MAX_DIFF_ALLOWED 0.016 /* maximum difference allowed */
#define WAVEFORM_QUARTER (WAVEFORM_PERIOD / 4)
/* all available sample format combinations */
int testformats[] = {
IPATCH_SAMPLE_8BIT,
IPATCH_SAMPLE_16BIT,
IPATCH_SAMPLE_24BIT,
IPATCH_SAMPLE_32BIT,
IPATCH_SAMPLE_FLOAT,
IPATCH_SAMPLE_DOUBLE,
IPATCH_SAMPLE_REAL24BIT,
IPATCH_SAMPLE_8BIT | IPATCH_SAMPLE_UNSIGNED,
IPATCH_SAMPLE_16BIT | IPATCH_SAMPLE_UNSIGNED,
IPATCH_SAMPLE_24BIT | IPATCH_SAMPLE_UNSIGNED,
IPATCH_SAMPLE_32BIT | IPATCH_SAMPLE_UNSIGNED,
IPATCH_SAMPLE_REAL24BIT | IPATCH_SAMPLE_UNSIGNED,
IPATCH_SAMPLE_16BIT | IPATCH_SAMPLE_BENDIAN,
IPATCH_SAMPLE_24BIT | IPATCH_SAMPLE_BENDIAN,
IPATCH_SAMPLE_32BIT | IPATCH_SAMPLE_BENDIAN,
IPATCH_SAMPLE_FLOAT | IPATCH_SAMPLE_BENDIAN,
IPATCH_SAMPLE_DOUBLE | IPATCH_SAMPLE_BENDIAN,
IPATCH_SAMPLE_REAL24BIT | IPATCH_SAMPLE_BENDIAN,
IPATCH_SAMPLE_16BIT | IPATCH_SAMPLE_UNSIGNED | IPATCH_SAMPLE_BENDIAN,
IPATCH_SAMPLE_24BIT | IPATCH_SAMPLE_UNSIGNED | IPATCH_SAMPLE_BENDIAN,
IPATCH_SAMPLE_32BIT | IPATCH_SAMPLE_UNSIGNED | IPATCH_SAMPLE_BENDIAN,
IPATCH_SAMPLE_REAL24BIT | IPATCH_SAMPLE_UNSIGNED | IPATCH_SAMPLE_BENDIAN
};
#define SAMPLE_FORMAT_COUNT G_N_ELEMENTS (testformats)
static int test_size = DEFAULT_AUDIO_SIZE;
static gboolean verbose = FALSE;
static GOptionEntry entries[] =
{
{ "size", 's', 0, G_OPTION_ARG_INT, &test_size, "Size of test waveform in samples (default=32768)", NULL },
{ "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, "Be verbose", NULL },
{ NULL }
};
int main (int argc, char *argv[])
{
IpatchSampleTransform *trans;
gpointer srctrans, desttrans;
double *dwave, *fintrans;
guint periodpos;
int srcform, destform;
int isrc, idest;
double d, maxdiff;
int i, maxindex, failcount = 0;
GError *error = NULL;
GOptionContext *context;
context = g_option_context_new ("- test libInstPatch sample format conversions");
g_option_context_add_main_entries (context, entries, "sample_test");
if (!g_option_context_parse (context, &argc, &argv, &error))
{
printf ("Failed to parse command line arguments: %s\n",
ipatch_gerror_message (error));
return 1;
}
g_option_context_free (context);
ipatch_init ();
dwave = g_new (double, test_size); /* allocate audio buffer (double format) */
srctrans = g_malloc (8 * test_size); /* source format transform buf */
desttrans = g_malloc (8 * test_size); /* destination format transform buf */
fintrans = g_malloc (8 * test_size); /* final transform buf */
/* create sample transform object and allocate its buffer */
trans = ipatch_sample_transform_new (0, 0, 0);
ipatch_sample_transform_alloc_size (trans, 32 * 1024);
/* generate triangle waveform */
for (i = 0; i < test_size; i++)
{
periodpos = i % WAVEFORM_PERIOD;
if (periodpos <= WAVEFORM_QUARTER)
dwave[i] = periodpos / (double)WAVEFORM_QUARTER;
else if (periodpos <= WAVEFORM_QUARTER * 3)
dwave[i] = -((periodpos - WAVEFORM_QUARTER) / (double)WAVEFORM_QUARTER - 1.0);
else dwave[i] = (periodpos - WAVEFORM_QUARTER * 3) / (double)WAVEFORM_QUARTER - 1.0;
}
/* Convert between all possible format pairs using the following steps:
* - Convert double to first format of format pair
* - Convert from first format to second format
* - Convert second format back to double
* - Calculate maximum sample difference between new double audio and original
*/
for (isrc = 0; isrc < SAMPLE_FORMAT_COUNT; isrc++)
{
srcform = testformats[isrc];
for (idest = 0; idest < SAMPLE_FORMAT_COUNT; idest++)
{
destform = testformats[idest];
/* convert double waveform to source format */
ipatch_sample_transform_set_formats (trans, IPATCH_SAMPLE_DOUBLE
| IPATCH_SAMPLE_ENDIAN_HOST, srcform,
IPATCH_SAMPLE_UNITY_CHANNEL_MAP);
ipatch_sample_transform_convert (trans, dwave, srctrans, test_size);
/* convert source format to destination format */
ipatch_sample_transform_set_formats (trans, srcform, destform,
IPATCH_SAMPLE_UNITY_CHANNEL_MAP);
ipatch_sample_transform_convert (trans, srctrans, desttrans, test_size);
/* convert destination format to final double output */
ipatch_sample_transform_set_formats (trans, destform, IPATCH_SAMPLE_DOUBLE
| IPATCH_SAMPLE_ENDIAN_HOST,
IPATCH_SAMPLE_UNITY_CHANNEL_MAP);
ipatch_sample_transform_convert (trans, desttrans, fintrans, test_size);
/* compare final waveform against original */
for (i = 0, maxdiff = 0.0, maxindex = 0; i < test_size; i++)
{
d = dwave[i] - fintrans[i];
if (d < 0.0) d = -d;
if (d > maxdiff)
{
maxdiff = d;
maxindex = i;
}
}
if (verbose)
printf ("Convert format %03x to %03x%s: maxdiff=%0.6f, sample=%d\n",
srcform, destform, maxdiff > MAX_DIFF_ALLOWED ? " FAILED" : "",
maxdiff, maxindex);
if (maxdiff > MAX_DIFF_ALLOWED)
{
if (!verbose)
printf ("Convert format %03x to %03x FAILED: maxdiff=%0.6f, sample=%d\n",
srcform, destform, maxdiff, maxindex);
failcount++;
}
}
}
ipatch_sample_transform_free (trans);
g_free (dwave);
g_free (srctrans);
g_free (desttrans);
g_free (fintrans);
if (failcount > 0)
{
printf ("%d of %d format conversions FAILED\n", failcount,
SAMPLE_FORMAT_COUNT * SAMPLE_FORMAT_COUNT);
return 1;
}
printf ("All %d sample format conversions PASSED\n",
SAMPLE_FORMAT_COUNT * SAMPLE_FORMAT_COUNT);
return 0;
}
|