avfft.c (6577B)
1 /* 2 * This file is part of FFmpeg. 3 * 4 * FFmpeg is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation; either 7 * version 2.1 of the License, or (at your option) any later version. 8 * 9 * FFmpeg is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Lesser General Public License for more details. 13 * 14 * You should have received a copy of the GNU Lesser General Public 15 * License along with FFmpeg; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 */ 18 19 #include <stddef.h> 20 #include <string.h> 21 22 #include "libavutil/attributes.h" 23 #include "libavutil/macros.h" 24 #include "libavutil/mem.h" 25 #include "libavutil/tx.h" 26 #include "avfft.h" 27 28 typedef struct AVTXWrapper { 29 AVTXContext *ctx; 30 av_tx_fn fn; 31 32 AVTXContext *ctx2; 33 av_tx_fn fn2; 34 35 ptrdiff_t stride; 36 int len; 37 int inv; 38 39 float *tmp; 40 int out_of_place; 41 } AVTXWrapper; 42 43 /* FFT */ 44 45 FFTContext *av_fft_init(int nbits, int inverse) 46 { 47 int ret; 48 float scale = 1.0f; 49 AVTXWrapper *s = av_mallocz(sizeof(*s)); 50 if (!s) 51 return NULL; 52 53 ret = av_tx_init(&s->ctx, &s->fn, AV_TX_FLOAT_FFT, inverse, 1 << nbits, 54 &scale, AV_TX_INPLACE); 55 if (ret < 0) { 56 av_free(s); 57 return NULL; 58 } 59 60 return (FFTContext *)s; 61 } 62 63 void av_fft_permute(FFTContext *s, FFTComplex *z) 64 { 65 /* Empty */ 66 } 67 68 void av_fft_calc(FFTContext *s, FFTComplex *z) 69 { 70 AVTXWrapper *w = (AVTXWrapper *)s; 71 w->fn(w->ctx, z, (void *)z, sizeof(AVComplexFloat)); 72 } 73 74 av_cold void av_fft_end(FFTContext *s) 75 { 76 if (s) { 77 AVTXWrapper *w = (AVTXWrapper *)s; 78 av_tx_uninit(&w->ctx); 79 av_tx_uninit(&w->ctx2); 80 av_free(w); 81 } 82 } 83 84 FFTContext *av_mdct_init(int nbits, int inverse, double scale) 85 { 86 int ret; 87 float scale_f = scale; 88 AVTXWrapper *s = av_mallocz(sizeof(*s)); 89 if (!s) 90 return NULL; 91 92 ret = av_tx_init(&s->ctx, &s->fn, AV_TX_FLOAT_MDCT, inverse, 1 << (nbits - 1), &scale_f, 0); 93 if (ret < 0) { 94 av_free(s); 95 return NULL; 96 } 97 98 if (inverse) { 99 ret = av_tx_init(&s->ctx2, &s->fn2, AV_TX_FLOAT_MDCT, inverse, 1 << (nbits - 1), 100 &scale_f, AV_TX_FULL_IMDCT); 101 if (ret < 0) { 102 av_tx_uninit(&s->ctx); 103 av_free(s); 104 return NULL; 105 } 106 } 107 108 return (FFTContext *)s; 109 } 110 111 void av_imdct_calc(FFTContext *s, FFTSample *output, const FFTSample *input) 112 { 113 AVTXWrapper *w = (AVTXWrapper *)s; 114 w->fn2(w->ctx2, output, (void *)input, sizeof(float)); 115 } 116 117 void av_imdct_half(FFTContext *s, FFTSample *output, const FFTSample *input) 118 { 119 AVTXWrapper *w = (AVTXWrapper *)s; 120 w->fn(w->ctx, output, (void *)input, sizeof(float)); 121 } 122 123 void av_mdct_calc(FFTContext *s, FFTSample *output, const FFTSample *input) 124 { 125 AVTXWrapper *w = (AVTXWrapper *)s; 126 w->fn(w->ctx, output, (void *)input, sizeof(float)); 127 } 128 129 av_cold void av_mdct_end(FFTContext *s) 130 { 131 if (s) { 132 AVTXWrapper *w = (AVTXWrapper *)s; 133 av_tx_uninit(&w->ctx2); 134 av_tx_uninit(&w->ctx); 135 av_free(w); 136 } 137 } 138 139 RDFTContext *av_rdft_init(int nbits, enum RDFTransformType trans) 140 { 141 int ret; 142 float scale = trans == IDFT_C2R ? 0.5f : 1.0f; 143 AVTXWrapper *s; 144 145 /* The other 2 modes are unconventional, do not form an orthogonal 146 * transform, have never been useful, and so they're not implemented. */ 147 if (trans != IDFT_C2R && trans != DFT_R2C) 148 return NULL; 149 150 s = av_mallocz(sizeof(*s)); 151 if (!s) 152 return NULL; 153 154 ret = av_tx_init(&s->ctx, &s->fn, AV_TX_FLOAT_RDFT, trans == IDFT_C2R, 155 1 << nbits, &scale, 0x0); 156 if (ret < 0) { 157 av_free(s); 158 return NULL; 159 } 160 161 s->stride = (trans == DFT_C2R) ? sizeof(AVComplexFloat) : sizeof(float); 162 s->len = 1 << nbits; 163 s->inv = trans == IDFT_C2R; 164 165 s->tmp = av_malloc((s->len + 2)*sizeof(float)); 166 if (!s->tmp) { 167 av_tx_uninit(&s->ctx); 168 av_free(s); 169 return NULL; 170 } 171 172 return (RDFTContext *)s; 173 } 174 175 void av_rdft_calc(RDFTContext *s, FFTSample *data) 176 { 177 AVTXWrapper *w = (AVTXWrapper *)s; 178 float *src = w->inv ? w->tmp : (float *)data; 179 float *dst = w->inv ? (float *)data : w->tmp; 180 181 if (w->inv) { 182 memcpy(src, data, w->len*sizeof(float)); 183 184 src[w->len] = src[1]; 185 src[1] = 0.0f; 186 } 187 188 w->fn(w->ctx, dst, (void *)src, w->stride); 189 190 if (!w->inv) { 191 dst[1] = dst[w->len]; 192 memcpy(data, dst, w->len*sizeof(float)); 193 } 194 } 195 196 av_cold void av_rdft_end(RDFTContext *s) 197 { 198 if (s) { 199 AVTXWrapper *w = (AVTXWrapper *)s; 200 av_tx_uninit(&w->ctx); 201 av_free(w->tmp); 202 av_free(w); 203 } 204 } 205 206 DCTContext *av_dct_init(int nbits, enum DCTTransformType inverse) 207 { 208 int ret; 209 const float scale_map[] = { 210 [DCT_II] = 0.5f, 211 [DCT_III] = 1.0f / (1 << nbits), 212 [DCT_I] = 0.5f, 213 [DST_I] = 2.0f, 214 }; 215 static const enum AVTXType type_map[] = { 216 [DCT_II] = AV_TX_FLOAT_DCT, 217 [DCT_III] = AV_TX_FLOAT_DCT, 218 [DCT_I] = AV_TX_FLOAT_DCT_I, 219 [DST_I] = AV_TX_FLOAT_DST_I, 220 }; 221 222 AVTXWrapper *s = av_mallocz(sizeof(*s)); 223 if (!s) 224 return NULL; 225 226 s->len = (1 << nbits); 227 s->out_of_place = (inverse == DCT_I) || (inverse == DST_I); 228 229 ret = av_tx_init(&s->ctx, &s->fn, type_map[inverse], 230 (inverse == DCT_III), 1 << (nbits - (inverse == DCT_III)), 231 &scale_map[inverse], s->out_of_place ? 0 : AV_TX_INPLACE); 232 if (ret < 0) { 233 av_free(s); 234 return NULL; 235 } 236 237 if (s->out_of_place) { 238 s->tmp = av_malloc((1 << (nbits + 1))*sizeof(float)); 239 if (!s->tmp) { 240 av_tx_uninit(&s->ctx); 241 av_free(s); 242 return NULL; 243 } 244 } 245 246 return (DCTContext *)s; 247 } 248 249 void av_dct_calc(DCTContext *s, FFTSample *data) 250 { 251 AVTXWrapper *w = (AVTXWrapper *)s; 252 if (w->out_of_place) { 253 memcpy(w->tmp, data, w->len*sizeof(float)); 254 w->fn(w->ctx, (void *)data, w->tmp, sizeof(float)); 255 } else { 256 w->fn(w->ctx, data, (void *)data, sizeof(float)); 257 } 258 } 259 260 av_cold void av_dct_end(DCTContext *s) 261 { 262 if (s) { 263 AVTXWrapper *w = (AVTXWrapper *)s; 264 av_tx_uninit(&w->ctx); 265 av_free(w->tmp); 266 av_free(w); 267 } 268 }