1 /* Copyright (c) 2008-2011 Xiph.Org Foundation
2 Written by Jean-Marc Valin */
3 /*
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions
6 are met:
7
8 - Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10
11 - Redistributions in binary form must reproduce the above copyright
12 notice, this list of conditions and the following disclaimer in the
13 documentation and/or other materials provided with the distribution.
14
15 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
19 OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
23 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28 #ifdef HAVE_CONFIG_H
29 #include "config.h"
30 #endif
31
32 #define SKIP_CONFIG_H
33
34 #ifndef CUSTOM_MODES
35 #define CUSTOM_MODES
36 #endif
37
38 #include <stdio.h>
39
40 #define CELT_C
41 #include "mdct.h"
42 #include "stack_alloc.h"
43
44 #include "kiss_fft.c"
45 #include "mdct.c"
46 #include "mathops.c"
47 #include "entcode.c"
48
49 #if defined(OPUS_X86_MAY_HAVE_SSE2) || defined(OPUS_X86_MAY_HAVE_SSE4_1)
50 # include "x86/x86cpu.c"
51 #elif defined(OPUS_ARM_ASM) || defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
52 # include "arm/armcpu.c"
53 # include "pitch.c"
54 # include "celt_lpc.c"
55 # if defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
56 # include "arm/celt_neon_intr.c"
57 # if defined(HAVE_ARM_NE10)
58 # include "arm/celt_ne10_fft.c"
59 # include "arm/celt_ne10_mdct.c"
60 # endif
61 # endif
62 # include "arm/arm_celt_map.c"
63 #endif
64
65 #ifndef M_PI
66 #define M_PI 3.141592653
67 #endif
68
69 int ret = 0;
check(kiss_fft_scalar * in,kiss_fft_scalar * out,int nfft,int isinverse)70 void check(kiss_fft_scalar * in,kiss_fft_scalar * out,int nfft,int isinverse)
71 {
72 int bin,k;
73 double errpow=0,sigpow=0;
74 double snr;
75 for (bin=0;bin<nfft/2;++bin) {
76 double ansr = 0;
77 double difr;
78
79 for (k=0;k<nfft;++k) {
80 double phase = 2*M_PI*(k+.5+.25*nfft)*(bin+.5)/nfft;
81 double re = cos(phase);
82
83 re /= nfft/4;
84
85 ansr += in[k] * re;
86 }
87 /*printf ("%f %f\n", ansr, out[bin]);*/
88 difr = ansr - out[bin];
89 errpow += difr*difr;
90 sigpow += ansr*ansr;
91 }
92 snr = 10*log10(sigpow/errpow);
93 printf("nfft=%d inverse=%d,snr = %f\n",nfft,isinverse,snr );
94 if (snr<60) {
95 printf( "** poor snr: %f **\n", snr);
96 ret = 1;
97 }
98 }
99
check_inv(kiss_fft_scalar * in,kiss_fft_scalar * out,int nfft,int isinverse)100 void check_inv(kiss_fft_scalar * in,kiss_fft_scalar * out,int nfft,int isinverse)
101 {
102 int bin,k;
103 double errpow=0,sigpow=0;
104 double snr;
105 for (bin=0;bin<nfft;++bin) {
106 double ansr = 0;
107 double difr;
108
109 for (k=0;k<nfft/2;++k) {
110 double phase = 2*M_PI*(bin+.5+.25*nfft)*(k+.5)/nfft;
111 double re = cos(phase);
112
113 /*re *= 2;*/
114
115 ansr += in[k] * re;
116 }
117 /*printf ("%f %f\n", ansr, out[bin]);*/
118 difr = ansr - out[bin];
119 errpow += difr*difr;
120 sigpow += ansr*ansr;
121 }
122 snr = 10*log10(sigpow/errpow);
123 printf("nfft=%d inverse=%d,snr = %f\n",nfft,isinverse,snr );
124 if (snr<60) {
125 printf( "** poor snr: %f **\n", snr);
126 ret = 1;
127 }
128 }
129
130
test1d(int nfft,int isinverse,int arch)131 void test1d(int nfft,int isinverse,int arch)
132 {
133 mdct_lookup cfg;
134 size_t buflen = sizeof(kiss_fft_scalar)*nfft;
135
136 kiss_fft_scalar * in = (kiss_fft_scalar*)malloc(buflen);
137 kiss_fft_scalar * in_copy = (kiss_fft_scalar*)malloc(buflen);
138 kiss_fft_scalar * out= (kiss_fft_scalar*)malloc(buflen);
139 opus_val16 * window= (opus_val16*)malloc(sizeof(opus_val16)*nfft/2);
140 int k;
141
142 clt_mdct_init(&cfg, nfft, 0, arch);
143 for (k=0;k<nfft;++k) {
144 in[k] = (rand() % 32768) - 16384;
145 }
146
147 for (k=0;k<nfft/2;++k) {
148 window[k] = Q15ONE;
149 }
150 for (k=0;k<nfft;++k) {
151 in[k] *= 32768;
152 }
153
154 if (isinverse)
155 {
156 for (k=0;k<nfft;++k) {
157 in[k] /= nfft;
158 }
159 }
160
161 for (k=0;k<nfft;++k)
162 in_copy[k] = in[k];
163 /*for (k=0;k<nfft;++k) printf("%d %d ", in[k].r, in[k].i);printf("\n");*/
164
165 if (isinverse)
166 {
167 for (k=0;k<nfft;++k)
168 out[k] = 0;
169 clt_mdct_backward(&cfg,in,out, window, nfft/2, 0, 1, arch);
170 /* apply TDAC because clt_mdct_backward() no longer does that */
171 for (k=0;k<nfft/4;++k)
172 out[nfft-k-1] = out[nfft/2+k];
173 check_inv(in,out,nfft,isinverse);
174 } else {
175 clt_mdct_forward(&cfg,in,out,window, nfft/2, 0, 1, arch);
176 check(in_copy,out,nfft,isinverse);
177 }
178 /*for (k=0;k<nfft;++k) printf("%d %d ", out[k].r, out[k].i);printf("\n");*/
179
180
181 free(in);
182 free(in_copy);
183 free(out);
184 free(window);
185 clt_mdct_clear(&cfg, arch);
186 }
187
main(int argc,char ** argv)188 int main(int argc,char ** argv)
189 {
190 ALLOC_STACK;
191 int arch = opus_select_arch();
192
193 if (argc>1) {
194 int k;
195 for (k=1;k<argc;++k) {
196 test1d(atoi(argv[k]),0,arch);
197 test1d(atoi(argv[k]),1,arch);
198 }
199 }else{
200 test1d(32,0,arch);
201 test1d(32,1,arch);
202 test1d(256,0,arch);
203 test1d(256,1,arch);
204 test1d(512,0,arch);
205 test1d(512,1,arch);
206 test1d(1024,0,arch);
207 test1d(1024,1,arch);
208 test1d(2048,0,arch);
209 test1d(2048,1,arch);
210 #ifndef RADIX_TWO_ONLY
211 test1d(36,0,arch);
212 test1d(36,1,arch);
213 test1d(40,0,arch);
214 test1d(40,1,arch);
215 test1d(60,0,arch);
216 test1d(60,1,arch);
217 test1d(120,0,arch);
218 test1d(120,1,arch);
219 test1d(240,0,arch);
220 test1d(240,1,arch);
221 test1d(480,0,arch);
222 test1d(480,1,arch);
223 test1d(960,0,arch);
224 test1d(960,1,arch);
225 test1d(1920,0,arch);
226 test1d(1920,1,arch);
227 #endif
228 }
229 return ret;
230 }
231