1 /* Copyright (c) 2007-2008 CSIRO 2 Copyright (c) 2007-2008 Xiph.Org Foundation 3 Written by Jean-Marc Valin */ 4 /* 5 Redistribution and use in source and binary forms, with or without 6 modification, are permitted provided that the following conditions 7 are met: 8 9 - Redistributions of source code must retain the above copyright 10 notice, this list of conditions and the following disclaimer. 11 12 - Redistributions in binary form must reproduce the above copyright 13 notice, this list of conditions and the following disclaimer in the 14 documentation and/or other materials provided with the distribution. 15 16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 20 OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 23 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 24 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 25 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 26 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 /* This is a simple MDCT implementation that uses a N/4 complex FFT 30 to do most of the work. It should be relatively straightforward to 31 plug in pretty much and FFT here. 32 33 This replaces the Vorbis FFT (and uses the exact same API), which 34 was a bit too messy and that was ending up duplicating code 35 (might as well use the same FFT everywhere). 36 37 The algorithm is similar to (and inspired from) Fabrice Bellard's 38 MDCT implementation in FFMPEG, but has differences in signs, ordering 39 and scaling in many places. 40 */ 41 #ifndef __MDCT_MIPSR1_H__ 42 #define __MDCT_MIPSR1_H__ 43 44 #ifndef SKIP_CONFIG_H 45 #ifdef HAVE_CONFIG_H 46 #include "config.h" 47 #endif 48 #endif 49 50 #include "mdct.h" 51 #include "kiss_fft.h" 52 #include "_kiss_fft_guts.h" 53 #include <math.h> 54 #include "os_support.h" 55 #include "mathops.h" 56 #include "stack_alloc.h" 57 58 /* Forward MDCT trashes the input array */ 59 #define OVERRIDE_clt_mdct_forward 60 void clt_mdct_forward(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scalar * OPUS_RESTRICT out, 61 const opus_val16 *window, int overlap, int shift, int stride, int arch) 62 { 63 int i; 64 int N, N2, N4; 65 VARDECL(kiss_fft_scalar, f); 66 VARDECL(kiss_fft_cpx, f2); 67 const kiss_fft_state *st = l->kfft[shift]; 68 const kiss_twiddle_scalar *trig; 69 opus_val16 scale; 70 #ifdef FIXED_POINT 71 /* Allows us to scale with MULT16_32_Q16(), which is faster than 72 MULT16_32_Q15() on ARM. */ 73 int scale_shift = st->scale_shift-1; 74 #endif 75 76 (void)arch; 77 78 SAVE_STACK; 79 scale = st->scale; 80 81 N = l->n; 82 trig = l->trig; 83 for (i=0;i<shift;i++) 84 { 85 N >>= 1; 86 trig += N; 87 } 88 N2 = N>>1; 89 N4 = N>>2; 90 91 ALLOC(f, N2, kiss_fft_scalar); 92 ALLOC(f2, N4, kiss_fft_cpx); 93 94 /* Consider the input to be composed of four blocks: [a, b, c, d] */ 95 /* Window, shuffle, fold */ 96 { 97 /* Temp pointers to make it really clear to the compiler what we're doing */ 98 const kiss_fft_scalar * OPUS_RESTRICT xp1 = in+(overlap>>1); 99 const kiss_fft_scalar * OPUS_RESTRICT xp2 = in+N2-1+(overlap>>1); 100 kiss_fft_scalar * OPUS_RESTRICT yp = f; 101 const opus_val16 * OPUS_RESTRICT wp1 = window+(overlap>>1); 102 const opus_val16 * OPUS_RESTRICT wp2 = window+(overlap>>1)-1; 103 for(i=0;i<((overlap+3)>>2);i++) 104 { 105 /* Real part arranged as -d-cR, Imag part arranged as -b+aR*/ 106 *yp++ = S_MUL_ADD(*wp2, xp1[N2],*wp1,*xp2); 107 *yp++ = S_MUL_SUB(*wp1, *xp1,*wp2, xp2[-N2]); 108 xp1+=2; 109 xp2-=2; 110 wp1+=2; 111 wp2-=2; 112 } 113 wp1 = window; 114 wp2 = window+overlap-1; 115 for(;i<N4-((overlap+3)>>2);i++) 116 { 117 /* Real part arranged as a-bR, Imag part arranged as -c-dR */ 118 *yp++ = *xp2; 119 *yp++ = *xp1; 120 xp1+=2; 121 xp2-=2; 122 } 123 for(;i<N4;i++) 124 { 125 /* Real part arranged as a-bR, Imag part arranged as -c-dR */ 126 *yp++ = S_MUL_SUB(*wp2, *xp2, *wp1, xp1[-N2]); 127 *yp++ = S_MUL_ADD(*wp2, *xp1, *wp1, xp2[N2]); 128 xp1+=2; 129 xp2-=2; 130 wp1+=2; 131 wp2-=2; 132 } 133 } 134 /* Pre-rotation */ 135 { 136 kiss_fft_scalar * OPUS_RESTRICT yp = f; 137 const kiss_twiddle_scalar *t = &trig[0]; 138 for(i=0;i<N4;i++) 139 { 140 kiss_fft_cpx yc; 141 kiss_twiddle_scalar t0, t1; 142 kiss_fft_scalar re, im, yr, yi; 143 t0 = t[i]; 144 t1 = t[N4+i]; 145 re = *yp++; 146 im = *yp++; 147 148 yr = S_MUL_SUB(re,t0,im,t1); 149 yi = S_MUL_ADD(im,t0,re,t1); 150 151 yc.r = yr; 152 yc.i = yi; 153 yc.r = PSHR32(MULT16_32_Q16(scale, yc.r), scale_shift); 154 yc.i = PSHR32(MULT16_32_Q16(scale, yc.i), scale_shift); 155 f2[st->bitrev[i]] = yc; 156 } 157 } 158 159 /* N/4 complex FFT, does not downscale anymore */ 160 opus_fft_impl(st, f2); 161 162 /* Post-rotate */ 163 { 164 /* Temp pointers to make it really clear to the compiler what we're doing */ 165 const kiss_fft_cpx * OPUS_RESTRICT fp = f2; 166 kiss_fft_scalar * OPUS_RESTRICT yp1 = out; 167 kiss_fft_scalar * OPUS_RESTRICT yp2 = out+stride*(N2-1); 168 const kiss_twiddle_scalar *t = &trig[0]; 169 /* Temp pointers to make it really clear to the compiler what we're doing */ 170 for(i=0;i<N4;i++) 171 { 172 kiss_fft_scalar yr, yi; 173 yr = S_MUL_SUB(fp->i,t[N4+i] , fp->r,t[i]); 174 yi = S_MUL_ADD(fp->r,t[N4+i] ,fp->i,t[i]); 175 *yp1 = yr; 176 *yp2 = yi; 177 fp++; 178 yp1 += 2*stride; 179 yp2 -= 2*stride; 180 } 181 } 182 RESTORE_STACK; 183 } 184 185 #define OVERRIDE_clt_mdct_backward 186 void clt_mdct_backward(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scalar * OPUS_RESTRICT out, 187 const opus_val16 * OPUS_RESTRICT window, int overlap, int shift, int stride, int arch) 188 { 189 int i; 190 int N, N2, N4; 191 const kiss_twiddle_scalar *trig; 192 193 (void)arch; 194 195 N = l->n; 196 trig = l->trig; 197 for (i=0;i<shift;i++) 198 { 199 N >>= 1; 200 trig += N; 201 } 202 N2 = N>>1; 203 N4 = N>>2; 204 205 /* Pre-rotate */ 206 { 207 /* Temp pointers to make it really clear to the compiler what we're doing */ 208 const kiss_fft_scalar * OPUS_RESTRICT xp1 = in; 209 const kiss_fft_scalar * OPUS_RESTRICT xp2 = in+stride*(N2-1); 210 kiss_fft_scalar * OPUS_RESTRICT yp = out+(overlap>>1); 211 const kiss_twiddle_scalar * OPUS_RESTRICT t = &trig[0]; 212 const opus_int16 * OPUS_RESTRICT bitrev = l->kfft[shift]->bitrev; 213 for(i=0;i<N4;i++) 214 { 215 int rev; 216 kiss_fft_scalar yr, yi; 217 rev = *bitrev++; 218 yr = S_MUL_ADD(*xp2, t[i] , *xp1, t[N4+i]); 219 yi = S_MUL_SUB(*xp1, t[i] , *xp2, t[N4+i]); 220 /* We swap real and imag because we use an FFT instead of an IFFT. */ 221 yp[2*rev+1] = yr; 222 yp[2*rev] = yi; 223 /* Storing the pre-rotation directly in the bitrev order. */ 224 xp1+=2*stride; 225 xp2-=2*stride; 226 } 227 } 228 229 opus_fft_impl(l->kfft[shift], (kiss_fft_cpx*)(out+(overlap>>1))); 230 231 /* Post-rotate and de-shuffle from both ends of the buffer at once to make 232 it in-place. */ 233 { 234 kiss_fft_scalar * OPUS_RESTRICT yp0 = out+(overlap>>1); 235 kiss_fft_scalar * OPUS_RESTRICT yp1 = out+(overlap>>1)+N2-2; 236 const kiss_twiddle_scalar *t = &trig[0]; 237 /* Loop to (N4+1)>>1 to handle odd N4. When N4 is odd, the 238 middle pair will be computed twice. */ 239 for(i=0;i<(N4+1)>>1;i++) 240 { 241 kiss_fft_scalar re, im, yr, yi; 242 kiss_twiddle_scalar t0, t1; 243 /* We swap real and imag because we're using an FFT instead of an IFFT. */ 244 re = yp0[1]; 245 im = yp0[0]; 246 t0 = t[i]; 247 t1 = t[N4+i]; 248 /* We'd scale up by 2 here, but instead it's done when mixing the windows */ 249 yr = S_MUL_ADD(re,t0 , im,t1); 250 yi = S_MUL_SUB(re,t1 , im,t0); 251 /* We swap real and imag because we're using an FFT instead of an IFFT. */ 252 re = yp1[1]; 253 im = yp1[0]; 254 yp0[0] = yr; 255 yp1[1] = yi; 256 257 t0 = t[(N4-i-1)]; 258 t1 = t[(N2-i-1)]; 259 /* We'd scale up by 2 here, but instead it's done when mixing the windows */ 260 yr = S_MUL_ADD(re,t0,im,t1); 261 yi = S_MUL_SUB(re,t1,im,t0); 262 yp1[0] = yr; 263 yp0[1] = yi; 264 yp0 += 2; 265 yp1 -= 2; 266 } 267 } 268 269 /* Mirror on both sides for TDAC */ 270 { 271 kiss_fft_scalar * OPUS_RESTRICT xp1 = out+overlap-1; 272 kiss_fft_scalar * OPUS_RESTRICT yp1 = out; 273 const opus_val16 * OPUS_RESTRICT wp1 = window; 274 const opus_val16 * OPUS_RESTRICT wp2 = window+overlap-1; 275 276 for(i = 0; i < overlap/2; i++) 277 { 278 kiss_fft_scalar x1, x2; 279 x1 = *xp1; 280 x2 = *yp1; 281 *yp1++ = MULT16_32_Q15(*wp2, x2) - MULT16_32_Q15(*wp1, x1); 282 *xp1-- = MULT16_32_Q15(*wp1, x2) + MULT16_32_Q15(*wp2, x1); 283 wp1++; 284 wp2--; 285 } 286 } 287 } 288 #endif /* __MDCT_MIPSR1_H__ */ 289