1 /*
2  * This file is part of libdcadec.
3  *
4  * This library is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU Lesser General Public License as published by the
6  * Free Software Foundation; either version 2.1 of the License, or (at your
7  * option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
12  * for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public License
15  * along with this library; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18 
19 #include <stdlib.h>
20 #include <stdio.h>
21 #include <stdint.h>
22 #include <string.h>
23 #include <math.h>
24 
25 #define BUF 3000
26 #define HDR 44
27 
main(int argc,char ** argv)28 int main(int argc, char **argv)
29 {
30     uint8_t buf1[BUF], buf2[BUF], *p1, *p2;
31     int64_t acc = 0, cnt = 0;
32     size_t r1, r2, i;
33     double ref = 0.0;
34 
35     if (argc != 4)
36         goto fail;
37 
38     if (strcmp(argv[3], "?")) {
39         char *p;
40         ref = strtod(argv[3], &p);
41         if (*p || p == argv[3])
42             goto fail;
43     }
44 
45     FILE *fp1 = fopen(argv[1], "rb");
46     FILE *fp2 = fopen(argv[2], "rb");
47     if (!fp1 || !fp2)
48         goto fail;
49 
50     if (fread(buf1, HDR, 1, fp1) != 1 || fread(buf2, HDR, 1, fp2) != 1)
51         goto fail;
52 
53     if (memcmp(buf1, buf2, HDR) || memcmp(buf1, "RIFF", 4))
54         goto fail;
55 
56     int bps;
57     switch (buf1[34] | (buf1[35] << 8)) {
58     case 16:
59         bps = 2;
60         break;
61     case 24:
62         bps = 3;
63         break;
64     default:
65         goto fail;
66     }
67 
68     do {
69         r1 = fread(buf1, 1, BUF, fp1);
70         r2 = fread(buf2, 1, BUF, fp2);
71         if (r1 != r2 || r1 % bps)
72             goto fail;
73 
74         for (i = 0, p1 = buf1, p2 = buf2; i < r1 / bps; i++, p1 += bps, p2 += bps) {
75             int64_t d;
76 
77             if (bps == 3) {
78                 uint32_t u1 = (p1[0] << 8) | (p1[1] << 16) | ((uint32_t)p1[2] << 24);
79                 uint32_t u2 = (p2[0] << 8) | (p2[1] << 16) | ((uint32_t)p2[2] << 24);
80                 int32_t v1 = (int32_t)u1 >> 8;
81                 int32_t v2 = (int32_t)u2 >> 8;
82                 d = v1 - v2;
83             } else {
84                 int16_t v1 = p1[0] | (p1[1] << 8);
85                 int16_t v2 = p2[0] | (p2[1] << 8);
86                 d = v1 - v2;
87             }
88 
89             acc += d * d;
90         }
91 
92         cnt += i;
93     } while (r1 == BUF);
94 
95     if (!cnt)
96         goto fail;
97 
98     double var = (double)acc / cnt;
99     double dev = sqrt(var);
100     if (strcmp(argv[3], "?")) {
101         if (fabs(dev - ref) > 0.1)
102             goto fail;
103         printf("%s: OK\n", argv[1]);
104     } else {
105         printf("%s: %f\n", argv[1], dev);
106     }
107 
108     return 0;
109 
110 fail:
111     printf("%s: FAILED\n", argc > 1 ? argv[1] : "???");
112     return 1;
113 }
114