~ubuntu-branches/ubuntu/wily/bluez/wily

« back to all changes in this revision

Viewing changes to sbc/sbctester.c

  • Committer: Bazaar Package Importer
  • Author(s): Mario Limonciello
  • Date: 2008-10-07 12:10:29 UTC
  • Revision ID: james.westby@ubuntu.com-20081007121029-4gup4fmmh2vfo5nh
Tags: upstream-4.12
ImportĀ upstreamĀ versionĀ 4.12

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *
 
3
 *  Bluetooth low-complexity, subband codec (SBC) library
 
4
 *
 
5
 *  Copyright (C) 2007-2008  Marcel Holtmann <marcel@holtmann.org>
 
6
 *  Copyright (C) 2007-2008  Frederic Dalleau <fdalleau@free.fr>
 
7
 *
 
8
 *
 
9
 *  This program is free software; you can redistribute it and/or modify
 
10
 *  it under the terms of the GNU General Public License as published by
 
11
 *  the Free Software Foundation; either version 2 of the License, or
 
12
 *  (at your option) any later version.
 
13
 *
 
14
 *  This program is distributed in the hope that it will be useful,
 
15
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
16
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
17
 *  GNU General Public License for more details.
 
18
 *
 
19
 *  You should have received a copy of the GNU General Public License
 
20
 *  along with this program; if not, write to the Free Software
 
21
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
22
 *
 
23
 */
 
24
 
 
25
#ifdef HAVE_CONFIG_H
 
26
#include <config.h>
 
27
#endif
 
28
 
 
29
#include <stdio.h>
 
30
#include <stdlib.h>
 
31
#include <sndfile.h>
 
32
#include <math.h>
 
33
#include <string.h>
 
34
 
 
35
#define MAXCHANNELS 2
 
36
#define DEFACCURACY 7
 
37
 
 
38
static double sampletobits(short sample16, int verbose)
 
39
{
 
40
        double bits = 0;
 
41
        unsigned short bit;
 
42
        int i;
 
43
 
 
44
        if (verbose)
 
45
                printf("===> sampletobits(%hd, %04hX)\n", sample16, sample16);
 
46
 
 
47
        /* Bit 0 is MSB */
 
48
        if (sample16 < 0)
 
49
                bits = -1;
 
50
 
 
51
        if (verbose)
 
52
                printf("%d", (sample16 < 0) ? 1 : 0);
 
53
 
 
54
        /* Bit 15 is LSB */
 
55
        for (i = 1; i < 16; i++) {
 
56
                bit = (unsigned short) sample16;
 
57
                bit >>= 15 - i;
 
58
                bit %= 2;
 
59
 
 
60
                if (verbose)
 
61
                        printf("%d", bit);
 
62
 
 
63
                if (bit)
 
64
                        bits += (1.0 / pow(2.0, i));
 
65
        }
 
66
 
 
67
        if (verbose)
 
68
                printf("\n");
 
69
 
 
70
        return bits;
 
71
}
 
72
 
 
73
static int calculate_rms_level(SNDFILE * sndref, SF_INFO * infosref,
 
74
                                SNDFILE * sndtst, SF_INFO * infostst,
 
75
                                                int accuracy, char *csvname)
 
76
{
 
77
        short refsample[MAXCHANNELS], tstsample[MAXCHANNELS];
 
78
        double refbits, tstbits;
 
79
        double rms_accu[MAXCHANNELS];
 
80
        double rms_level[MAXCHANNELS];
 
81
        double rms_limit = 1.0 / (pow(2.0, accuracy - 1) * pow(12.0, 0.5));
 
82
        FILE *csv = NULL;
 
83
        int i, j, r1, r2, verdict;
 
84
 
 
85
        if (csvname)
 
86
                csv = fopen(csvname, "wt");
 
87
 
 
88
        if (csv) {
 
89
                fprintf(csv, "num;");
 
90
                for (j = 0; j < infostst->channels; j++)
 
91
                        fprintf(csv, "ref channel %d;tst channel %d;", j, j);
 
92
                fprintf(csv, "\r\n");
 
93
        }
 
94
 
 
95
        sf_seek(sndref, 0, SEEK_SET);
 
96
        sf_seek(sndtst, 0, SEEK_SET);
 
97
 
 
98
        memset(rms_accu, 0, sizeof(rms_accu));
 
99
        memset(rms_level, 0, sizeof(rms_level));
 
100
 
 
101
        for (i = 0; i < infostst->frames; i++) {
 
102
                if (csv)
 
103
                        fprintf(csv, "%d;", i);
 
104
 
 
105
                r1 = sf_read_short(sndref, refsample, infostst->channels);
 
106
                if (r1 != infostst->channels) {
 
107
                        printf("Failed to read reference data: %s "
 
108
                                        "(r1=%d, channels=%d)",
 
109
                                        sf_strerror(sndref), r1,
 
110
                                        infostst->channels);
 
111
                        if (csv)
 
112
                                fclose(csv);
 
113
                        return -1;
 
114
                }
 
115
 
 
116
                r2 = sf_read_short(sndtst, tstsample, infostst->channels);
 
117
                if (r2 != infostst->channels) {
 
118
                        printf("Failed to read test data: %s "
 
119
                                        "(r2=%d, channels=%d)\n",
 
120
                                        sf_strerror(sndtst), r2,
 
121
                                        infostst->channels);
 
122
                        if (csv)
 
123
                                fclose(csv);
 
124
                        return -1;
 
125
                }
 
126
 
 
127
                for (j = 0; j < infostst->channels; j++) {
 
128
                        if (csv)
 
129
                                fprintf(csv, "%d;%d;", refsample[j],
 
130
                                                tstsample[j]);
 
131
 
 
132
                        refbits = sampletobits(refsample[j], 0);
 
133
                        tstbits = sampletobits(tstsample[j], 0);
 
134
 
 
135
                        rms_accu[j] += pow(tstbits - refbits, 2.0);
 
136
                }
 
137
 
 
138
                if (csv)
 
139
                        fprintf(csv, "\r\n");
 
140
        }
 
141
 
 
142
        printf("Limit: %f\n", rms_limit);
 
143
 
 
144
        for (j = 0; j < infostst->channels; j++) {
 
145
                printf("Channel %d\n", j);
 
146
                printf("Accumulated %f\n", rms_accu[j]);
 
147
                rms_accu[j] /= (double) infostst->frames;
 
148
                printf("Accumulated / %f = %f\n", (double) infostst->frames,
 
149
                                rms_accu[j]);
 
150
                rms_level[j] = sqrt(rms_accu[j]);
 
151
                printf("Level = %f (%f x %f = %f)\n",
 
152
                                rms_level[j], rms_level[j], rms_level[j],
 
153
                                                rms_level[j] * rms_level[j]);
 
154
        }
 
155
 
 
156
        verdict = 1;
 
157
 
 
158
        for (j = 0; j < infostst->channels; j++) {
 
159
                printf("Channel %d: %f\n", j, rms_level[j]);
 
160
 
 
161
                if (rms_level[j] > rms_limit)
 
162
                        verdict = 0;
 
163
        }
 
164
 
 
165
        printf("%s return %d\n", __FUNCTION__, verdict);
 
166
 
 
167
        return verdict;
 
168
}
 
169
 
 
170
static int check_absolute_diff(SNDFILE * sndref, SF_INFO * infosref,
 
171
                                SNDFILE * sndtst, SF_INFO * infostst,
 
172
                                int accuracy)
 
173
{
 
174
        short refsample[MAXCHANNELS], tstsample[MAXCHANNELS];
 
175
        short refmax[MAXCHANNELS], tstmax[MAXCHANNELS];
 
176
        double refbits, tstbits;
 
177
        double rms_absolute = 1.0 / (pow(2, accuracy - 2));
 
178
        double calc_max[MAXCHANNELS];
 
179
        int calc_count = 0;
 
180
        short r1, r2;
 
181
        double cur_diff;
 
182
        int i, j, verdict;
 
183
 
 
184
        memset(&refmax, 0, sizeof(refmax));
 
185
        memset(&tstmax, 0, sizeof(tstmax));
 
186
        memset(&calc_max, 0, sizeof(calc_max));
 
187
        memset(&refsample, 0, sizeof(refsample));
 
188
        memset(&tstsample, 0, sizeof(tstsample));
 
189
 
 
190
        sf_seek(sndref, 0, SEEK_SET);
 
191
        sf_seek(sndtst, 0, SEEK_SET);
 
192
 
 
193
        verdict = 1;
 
194
 
 
195
        printf("Absolute max: %f\n", rms_absolute);
 
196
        for (i = 0; i < infostst->frames; i++) {
 
197
                r1 = sf_read_short(sndref, refsample, infostst->channels);
 
198
 
 
199
                if (r1 != infostst->channels) {
 
200
                        printf("Failed to read reference data: %s "
 
201
                                        "(r1=%d, channels=%d)",
 
202
                                        sf_strerror(sndref), r1,
 
203
                                        infostst->channels);
 
204
                        return -1;
 
205
                }
 
206
 
 
207
                r2 = sf_read_short(sndtst, tstsample, infostst->channels);
 
208
                if (r2 != infostst->channels) {
 
209
                        printf("Failed to read test data: %s "
 
210
                                        "(r2=%d, channels=%d)\n",
 
211
                                        sf_strerror(sndtst), r2,
 
212
                                        infostst->channels);
 
213
                        return -1;
 
214
                }
 
215
 
 
216
                for (j = 0; j < infostst->channels; j++) {
 
217
                        refbits = sampletobits(refsample[j], 0);
 
218
                        tstbits = sampletobits(tstsample[j], 0);
 
219
 
 
220
                        cur_diff = fabs(tstbits - refbits);
 
221
 
 
222
                        if (cur_diff > rms_absolute) {
 
223
                                calc_count++;
 
224
                                /* printf("Channel %d exceeded : fabs(%f - %f) = %f > %f\n", j, tstbits, refbits, cur_diff, rms_absolute); */
 
225
                                verdict = 0;
 
226
                        }
 
227
 
 
228
                        if (cur_diff > calc_max[j]) {
 
229
                                calc_max[j] = cur_diff;
 
230
                                refmax[j] = refsample[j];
 
231
                                tstmax[j] = tstsample[j];
 
232
                        }
 
233
                }
 
234
        }
 
235
 
 
236
        for (j = 0; j < infostst->channels; j++) {
 
237
                printf("Calculated max: %f (%hd-%hd=%hd)\n",
 
238
                        calc_max[j], tstmax[j], refmax[j],
 
239
                        tstmax[j] - refmax[j]);
 
240
        }
 
241
 
 
242
        printf("%s return %d\n", __FUNCTION__, verdict);
 
243
 
 
244
        return verdict;
 
245
}
 
246
 
 
247
static void usage()
 
248
{
 
249
        printf("SBC conformance test ver %s\n", VERSION);
 
250
        printf("Copyright (c) 2007-2008 Marcel Holtmann\n");
 
251
        printf("Copyright (c) 2007-2008 Frederic Dalleau\n\n");
 
252
 
 
253
        printf("Usage:\n"
 
254
                "\tsbctester reference.wav checkfile.wav\n"
 
255
                "\tsbctester integer\n"
 
256
                "\n");
 
257
 
 
258
        printf("To test the encoder:\n");
 
259
        printf("\tUse a reference codec to encode original.wav to reference.sbc\n");
 
260
        printf("\tUse sbcenc to encode original.wav to checkfile.sbc\n");
 
261
        printf("\tDecode both file using the reference decoder\n");
 
262
        printf("\tRun sbctester with these two wav files to get the result\n\n");
 
263
 
 
264
        printf("\tA file called out.csv is generated to use the data in a\n");
 
265
        printf("\tspreadsheet application or database.\n\n");
 
266
}
 
267
 
 
268
int main(int argc, char *argv[])
 
269
{
 
270
        SNDFILE *sndref = NULL;
 
271
        SNDFILE *sndtst = NULL;
 
272
        SF_INFO infosref;
 
273
        SF_INFO infostst;
 
274
        char *ref;
 
275
        char *tst;
 
276
        int pass_rms, pass_absolute, pass, accuracy;
 
277
 
 
278
        if (argc == 2) {
 
279
                double db;
 
280
 
 
281
                printf("Test sampletobits\n");
 
282
                db = sampletobits((short) atoi(argv[1]), 1);
 
283
                printf("db = %f\n", db);
 
284
                exit(0);
 
285
        }
 
286
 
 
287
        if (argc < 3) {
 
288
                usage();
 
289
                exit(1);
 
290
        }
 
291
 
 
292
        ref = argv[1];
 
293
        tst = argv[2];
 
294
 
 
295
        printf("opening reference %s\n", ref);
 
296
 
 
297
        sndref = sf_open(ref, SFM_READ, &infosref);
 
298
        if (!sndref) {
 
299
                printf("Failed to open reference file\n");
 
300
                exit(1);
 
301
        }
 
302
 
 
303
        printf("opening testfile %s\n", tst);
 
304
        sndtst = sf_open(tst, SFM_READ, &infostst);
 
305
        if (!sndtst) {
 
306
                printf("Failed to open test file\n");
 
307
                sf_close(sndref);
 
308
                exit(1);
 
309
        }
 
310
 
 
311
        printf("reference:\n\t%d frames,\n\t%d hz,\n\t%d channels\n",
 
312
                (int) infosref.frames, (int) infosref.samplerate,
 
313
                (int) infosref.channels);
 
314
        printf("testfile:\n\t%d frames,\n\t%d hz,\n\t%d channels\n",
 
315
                (int) infostst.frames, (int) infostst.samplerate,
 
316
                (int) infostst.channels);
 
317
 
 
318
        /* check number of channels */
 
319
        if (infosref.channels > 2 || infostst.channels > 2) {
 
320
                printf("Too many channels\n");
 
321
                goto error;
 
322
        }
 
323
 
 
324
        /* compare number of samples */
 
325
        if (infosref.samplerate != infostst.samplerate ||
 
326
                                infosref.channels != infostst.channels) {
 
327
                printf("Cannot compare files with different charasteristics\n");
 
328
                goto error;
 
329
        }
 
330
 
 
331
        accuracy = DEFACCURACY;
 
332
        printf("Accuracy: %d\n", accuracy);
 
333
 
 
334
        /* Condition 1 rms level */
 
335
        pass_rms = calculate_rms_level(sndref, &infosref, sndtst, &infostst,
 
336
                                        accuracy, "out.csv");
 
337
        if (pass_rms < 0)
 
338
                goto error;
 
339
 
 
340
        /* Condition 2 absolute difference */
 
341
        pass_absolute = check_absolute_diff(sndref, &infosref, sndtst,
 
342
                                                &infostst, accuracy);
 
343
        if (pass_absolute < 0)
 
344
                goto error;
 
345
 
 
346
        /* Verdict */
 
347
        pass = pass_rms && pass_absolute;
 
348
        printf("Verdict: %s\n", pass ? "pass" : "fail");
 
349
 
 
350
        return 0;
 
351
 
 
352
error:
 
353
        sf_close(sndref);
 
354
        sf_close(sndtst);
 
355
 
 
356
        exit(1);
 
357
}