1 /*
2 * sample_list_test.c - Tests sample edit lists and virtual sample store
3 *
4 * - Creates double stereo format test waveform with triangle wave in left
5 * channel and sine wave in right channel
6 * - Re-constructs both channels using 2 sample lists using various list
7 * operations
8 * - Creates virtual sample store using double stereo format with left
9 * and right sample lists
10 * - Duplicates virtual sample store to a double stereo format store
11 * - Compares final duplicated store to original waveform and makes sure its
12 * the same
13 *
14 * libInstPatch
15 * Copyright (C) 1999-2014 Element Green <element@elementsofsound.org>
16 *
17 * This program is free software; you can redistribute it and/or
18 * modify it under the terms of the GNU Lesser General Public License
19 * as published by the Free Software Foundation; version 2.1
20 * of the License only.
21 *
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU Lesser General Public License for more details.
26 *
27 * You should have received a copy of the GNU Lesser General Public License
28 * along with this program; if not, write to the Free Software
29 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
30 * 02110-1301, USA or on the web at http://www.gnu.org.
31 */
32 #include <libinstpatch/libinstpatch.h>
33 #include <math.h>
34
35 #define DEFAULT_AUDIO_SIZE (32 * 1024) /* default test waveform size in samples */
36 #define WAVEFORM_PERIOD 1684 /* something to exercise LSB bytes too */
37 #define MAX_DIFF_ALLOWED 0.0 /* maximum difference allowed */
38
39 #define WAVEFORM_QUARTER (WAVEFORM_PERIOD / 4)
40
41
42 static int test_size = DEFAULT_AUDIO_SIZE;
43 static gboolean verbose = FALSE;
44
45 static GOptionEntry entries[] =
46 {
47 { "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, "Be verbose", NULL },
48 { NULL }
49 };
50
main(int argc,char * argv[])51 int main(int argc, char *argv[])
52 {
53 IpatchSampleStore *store, *vstore, *finstore;
54 IpatchSampleList *rlist, *llist;
55 IpatchSampleData *data, *vdata;
56 double *dwave, *findata;
57 guint periodpos;
58 double d, maxdiff;
59 int i, maxindex;
60 GError *error = NULL;
61 GOptionContext *context;
62 int test_size_q;
63
64 context = g_option_context_new("- test libInstPatch sample edit list functions");
65 g_option_context_add_main_entries(context, entries, "sample_list_test");
66
67 if(!g_option_context_parse(context, &argc, &argv, &error))
68 {
69 printf("Failed to parse command line arguments: %s\n",
70 ipatch_gerror_message(error));
71 return 1;
72 }
73
74 g_option_context_free(context);
75
76 test_size_q = test_size / 4; /* test size quarter */
77
78 ipatch_init();
79
80 /* allocate audio buffer (double format stereo) */
81 dwave = g_new(double, test_size * 2); /* ++ alloc */
82
83 /* generate triangle waveform for left channel and sine wave for right */
84 for(i = 0; i < test_size * 2; i += 2)
85 {
86 periodpos = i % WAVEFORM_PERIOD;
87
88 if(periodpos <= WAVEFORM_QUARTER)
89 {
90 dwave[i] = periodpos / (double)WAVEFORM_QUARTER;
91 }
92 else if(periodpos <= WAVEFORM_QUARTER * 3)
93 {
94 dwave[i] = -((periodpos - WAVEFORM_QUARTER) / (double)WAVEFORM_QUARTER - 1.0);
95 }
96 else
97 {
98 dwave[i] = (periodpos - WAVEFORM_QUARTER * 3) / (double)WAVEFORM_QUARTER - 1.0;
99 }
100
101 dwave[i + 1] = sin((periodpos / (double)WAVEFORM_PERIOD) * G_PI * 2.0);
102 }
103
104 data = ipatch_sample_data_new(test_size); /* ++ ref */
105
106 /* ++ ref - create sample store object for original waveform */
107 store = ipatch_sample_store_new(IPATCH_TYPE_SAMPLE_STORE_RAM, data,
108 "format", IPATCH_SAMPLE_DOUBLE
109 | IPATCH_SAMPLE_STEREO
110 | IPATCH_SAMPLE_ENDIAN_HOST,
111 "location", dwave,
112 "active", TRUE,
113 NULL);
114
115 rlist = ipatch_sample_list_new();
116
117 /* re-construct right channel in a very inefficient way ;) */
118 ipatch_sample_list_prepend(rlist, store, test_size_q * 2, test_size_q,
119 IPATCH_SAMPLE_LIST_CHAN_RIGHT);
120 ipatch_sample_list_prepend(rlist, store, 0, test_size_q,
121 IPATCH_SAMPLE_LIST_CHAN_RIGHT);
122 ipatch_sample_list_insert_index(rlist, 1, store, test_size_q, test_size_q,
123 IPATCH_SAMPLE_LIST_CHAN_RIGHT);
124 ipatch_sample_list_append(rlist, store, test_size_q * 3, test_size_q,
125 IPATCH_SAMPLE_LIST_CHAN_RIGHT);
126 /* cut a segment out which overlaps segments and then re-insert the cut seg */
127 ipatch_sample_list_cut(rlist, test_size_q + test_size_q / 2, test_size_q);
128 ipatch_sample_list_insert(rlist, test_size_q + test_size_q / 2,
129 store, test_size_q + test_size_q / 2,
130 test_size_q, IPATCH_SAMPLE_LIST_CHAN_RIGHT);
131
132 llist = ipatch_sample_list_new();
133
134 /* have fun with left channel too */
135 ipatch_sample_list_append(llist, store, 0, test_size,
136 IPATCH_SAMPLE_LIST_CHAN_LEFT);
137 ipatch_sample_list_cut(llist, test_size_q, test_size_q);
138 ipatch_sample_list_insert(llist, test_size_q, store, test_size_q,
139 test_size_q, IPATCH_SAMPLE_LIST_CHAN_LEFT);
140
141 vdata = ipatch_sample_data_new(test_size); /* ++ ref */
142
143 /* ++ ref - create virtual store from left and right sample lists */
144 vstore = ipatch_sample_store_new(IPATCH_TYPE_SAMPLE_STORE_VIRTUAL, vdata,
145 "format", IPATCH_SAMPLE_DOUBLE
146 | IPATCH_SAMPLE_STEREO
147 | IPATCH_SAMPLE_ENDIAN_HOST,
148 NULL);
149 ipatch_sample_store_virtual_set_list(vstore, 0, llist);
150 ipatch_sample_store_virtual_set_list(vstore, 1, rlist);
151 ipatch_sample_store_activate(vstore);
152
153 /* ++ ref - Duplicate store to render final waveform */
154 finstore = ipatch_sample_store_duplicate(vstore, IPATCH_TYPE_SAMPLE_STORE_RAM,
155 IPATCH_SAMPLE_DOUBLE
156 | IPATCH_SAMPLE_STEREO
157 | IPATCH_SAMPLE_ENDIAN_HOST, &error);
158
159 if(!finstore)
160 {
161 printf("Failed to create new duplicate sample store: %s",
162 ipatch_gerror_message(error));
163 return 1;
164 }
165
166 findata = ipatch_sample_store_RAM_get_location(finstore);
167
168 /* compare final waveform against original */
169 for(i = 0, maxdiff = 0.0, maxindex = 0; i < test_size * 2; i++)
170 {
171 d = dwave[i] - findata[i];
172
173 if(d < 0.0)
174 {
175 d = -d;
176 }
177
178 if(d > maxdiff)
179 {
180 maxdiff = d;
181 maxindex = i;
182 }
183 }
184
185 /* free up objects and data (for memcheck) */
186 g_object_unref(data);
187 g_object_unref(vdata);
188 g_object_unref(store);
189 g_object_unref(vstore);
190 g_object_unref(finstore);
191 g_free(dwave);
192
193 if(maxdiff > MAX_DIFF_ALLOWED)
194 {
195 printf("Sample list test failed: maxdiff=%0.16f index=%d\n",
196 maxdiff, maxindex);
197 return 1;
198 }
199
200 if(verbose)
201 printf("Sample list test passed: maxdiff=%0.16f index=%d\n",
202 maxdiff, maxindex);
203 else
204 {
205 printf("Sample list and virtual sample store test passed\n");
206 }
207
208 return 0;
209 }
210