cannam@154
|
1 /* Copyright (c) 2008 Xiph.Org Foundation
|
cannam@154
|
2 Written by Jean-Marc Valin */
|
cannam@154
|
3 /*
|
cannam@154
|
4 Redistribution and use in source and binary forms, with or without
|
cannam@154
|
5 modification, are permitted provided that the following conditions
|
cannam@154
|
6 are met:
|
cannam@154
|
7
|
cannam@154
|
8 - Redistributions of source code must retain the above copyright
|
cannam@154
|
9 notice, this list of conditions and the following disclaimer.
|
cannam@154
|
10
|
cannam@154
|
11 - Redistributions in binary form must reproduce the above copyright
|
cannam@154
|
12 notice, this list of conditions and the following disclaimer in the
|
cannam@154
|
13 documentation and/or other materials provided with the distribution.
|
cannam@154
|
14
|
cannam@154
|
15 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
cannam@154
|
16 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
cannam@154
|
17 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
cannam@154
|
18 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
cannam@154
|
19 OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
cannam@154
|
20 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
cannam@154
|
21 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
cannam@154
|
22 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
cannam@154
|
23 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
cannam@154
|
24 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
cannam@154
|
25 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
cannam@154
|
26 */
|
cannam@154
|
27
|
cannam@154
|
28 #ifdef HAVE_CONFIG_H
|
cannam@154
|
29 #include "config.h"
|
cannam@154
|
30 #endif
|
cannam@154
|
31
|
cannam@154
|
32 #include <stdio.h>
|
cannam@154
|
33
|
cannam@154
|
34 #include "stack_alloc.h"
|
cannam@154
|
35 #include "kiss_fft.h"
|
cannam@154
|
36 #include "mathops.h"
|
cannam@154
|
37 #include "modes.h"
|
cannam@154
|
38
|
cannam@154
|
39 #ifndef M_PI
|
cannam@154
|
40 #define M_PI 3.141592653
|
cannam@154
|
41 #endif
|
cannam@154
|
42
|
cannam@154
|
43 int ret = 0;
|
cannam@154
|
44
|
cannam@154
|
45 void check(kiss_fft_cpx * in,kiss_fft_cpx * out,int nfft,int isinverse)
|
cannam@154
|
46 {
|
cannam@154
|
47 int bin,k;
|
cannam@154
|
48 double errpow=0,sigpow=0, snr;
|
cannam@154
|
49
|
cannam@154
|
50 for (bin=0;bin<nfft;++bin) {
|
cannam@154
|
51 double ansr = 0;
|
cannam@154
|
52 double ansi = 0;
|
cannam@154
|
53 double difr;
|
cannam@154
|
54 double difi;
|
cannam@154
|
55
|
cannam@154
|
56 for (k=0;k<nfft;++k) {
|
cannam@154
|
57 double phase = -2*M_PI*bin*k/nfft;
|
cannam@154
|
58 double re = cos(phase);
|
cannam@154
|
59 double im = sin(phase);
|
cannam@154
|
60 if (isinverse)
|
cannam@154
|
61 im = -im;
|
cannam@154
|
62
|
cannam@154
|
63 if (!isinverse)
|
cannam@154
|
64 {
|
cannam@154
|
65 re /= nfft;
|
cannam@154
|
66 im /= nfft;
|
cannam@154
|
67 }
|
cannam@154
|
68
|
cannam@154
|
69 ansr += in[k].r * re - in[k].i * im;
|
cannam@154
|
70 ansi += in[k].r * im + in[k].i * re;
|
cannam@154
|
71 }
|
cannam@154
|
72 /*printf ("%d %d ", (int)ansr, (int)ansi);*/
|
cannam@154
|
73 difr = ansr - out[bin].r;
|
cannam@154
|
74 difi = ansi - out[bin].i;
|
cannam@154
|
75 errpow += difr*difr + difi*difi;
|
cannam@154
|
76 sigpow += ansr*ansr+ansi*ansi;
|
cannam@154
|
77 }
|
cannam@154
|
78 snr = 10*log10(sigpow/errpow);
|
cannam@154
|
79 printf("nfft=%d inverse=%d,snr = %f\n",nfft,isinverse,snr );
|
cannam@154
|
80 if (snr<60) {
|
cannam@154
|
81 printf( "** poor snr: %f ** \n", snr);
|
cannam@154
|
82 ret = 1;
|
cannam@154
|
83 }
|
cannam@154
|
84 }
|
cannam@154
|
85
|
cannam@154
|
86 void test1d(int nfft,int isinverse,int arch)
|
cannam@154
|
87 {
|
cannam@154
|
88 size_t buflen = sizeof(kiss_fft_cpx)*nfft;
|
cannam@154
|
89 kiss_fft_cpx *in;
|
cannam@154
|
90 kiss_fft_cpx *out;
|
cannam@154
|
91 int k;
|
cannam@154
|
92 #ifdef CUSTOM_MODES
|
cannam@154
|
93 kiss_fft_state *cfg = opus_fft_alloc(nfft,0,0,arch);
|
cannam@154
|
94 #else
|
cannam@154
|
95 int id;
|
cannam@154
|
96 const kiss_fft_state *cfg;
|
cannam@154
|
97 CELTMode *mode = opus_custom_mode_create(48000, 960, NULL);
|
cannam@154
|
98 if (nfft == 480) id = 0;
|
cannam@154
|
99 else if (nfft == 240) id = 1;
|
cannam@154
|
100 else if (nfft == 120) id = 2;
|
cannam@154
|
101 else if (nfft == 60) id = 3;
|
cannam@154
|
102 else return;
|
cannam@154
|
103 cfg = mode->mdct.kfft[id];
|
cannam@154
|
104 #endif
|
cannam@154
|
105
|
cannam@154
|
106 in = (kiss_fft_cpx*)malloc(buflen);
|
cannam@154
|
107 out = (kiss_fft_cpx*)malloc(buflen);
|
cannam@154
|
108
|
cannam@154
|
109 for (k=0;k<nfft;++k) {
|
cannam@154
|
110 in[k].r = (rand() % 32767) - 16384;
|
cannam@154
|
111 in[k].i = (rand() % 32767) - 16384;
|
cannam@154
|
112 }
|
cannam@154
|
113
|
cannam@154
|
114 for (k=0;k<nfft;++k) {
|
cannam@154
|
115 in[k].r *= 32768;
|
cannam@154
|
116 in[k].i *= 32768;
|
cannam@154
|
117 }
|
cannam@154
|
118
|
cannam@154
|
119 if (isinverse)
|
cannam@154
|
120 {
|
cannam@154
|
121 for (k=0;k<nfft;++k) {
|
cannam@154
|
122 in[k].r /= nfft;
|
cannam@154
|
123 in[k].i /= nfft;
|
cannam@154
|
124 }
|
cannam@154
|
125 }
|
cannam@154
|
126
|
cannam@154
|
127 /*for (k=0;k<nfft;++k) printf("%d %d ", in[k].r, in[k].i);printf("\n");*/
|
cannam@154
|
128
|
cannam@154
|
129 if (isinverse)
|
cannam@154
|
130 opus_ifft(cfg,in,out, arch);
|
cannam@154
|
131 else
|
cannam@154
|
132 opus_fft(cfg,in,out, arch);
|
cannam@154
|
133
|
cannam@154
|
134 /*for (k=0;k<nfft;++k) printf("%d %d ", out[k].r, out[k].i);printf("\n");*/
|
cannam@154
|
135
|
cannam@154
|
136 check(in,out,nfft,isinverse);
|
cannam@154
|
137
|
cannam@154
|
138 free(in);
|
cannam@154
|
139 free(out);
|
cannam@154
|
140 #ifdef CUSTOM_MODES
|
cannam@154
|
141 opus_fft_free(cfg, arch);
|
cannam@154
|
142 #endif
|
cannam@154
|
143 }
|
cannam@154
|
144
|
cannam@154
|
145 int main(int argc,char ** argv)
|
cannam@154
|
146 {
|
cannam@154
|
147 ALLOC_STACK;
|
cannam@154
|
148 int arch = opus_select_arch();
|
cannam@154
|
149
|
cannam@154
|
150 if (argc>1) {
|
cannam@154
|
151 int k;
|
cannam@154
|
152 for (k=1;k<argc;++k) {
|
cannam@154
|
153 test1d(atoi(argv[k]),0,arch);
|
cannam@154
|
154 test1d(atoi(argv[k]),1,arch);
|
cannam@154
|
155 }
|
cannam@154
|
156 }else{
|
cannam@154
|
157 test1d(32,0,arch);
|
cannam@154
|
158 test1d(32,1,arch);
|
cannam@154
|
159 test1d(128,0,arch);
|
cannam@154
|
160 test1d(128,1,arch);
|
cannam@154
|
161 test1d(256,0,arch);
|
cannam@154
|
162 test1d(256,1,arch);
|
cannam@154
|
163 #ifndef RADIX_TWO_ONLY
|
cannam@154
|
164 test1d(36,0,arch);
|
cannam@154
|
165 test1d(36,1,arch);
|
cannam@154
|
166 test1d(50,0,arch);
|
cannam@154
|
167 test1d(50,1,arch);
|
cannam@154
|
168 test1d(60,0,arch);
|
cannam@154
|
169 test1d(60,1,arch);
|
cannam@154
|
170 test1d(120,0,arch);
|
cannam@154
|
171 test1d(120,1,arch);
|
cannam@154
|
172 test1d(240,0,arch);
|
cannam@154
|
173 test1d(240,1,arch);
|
cannam@154
|
174 test1d(480,0,arch);
|
cannam@154
|
175 test1d(480,1,arch);
|
cannam@154
|
176 #endif
|
cannam@154
|
177 }
|
cannam@154
|
178 return ret;
|
cannam@154
|
179 }
|