ResidualVM logo ResidualVM website - Forums - Contact us BuildBot - Doxygen - Wiki curved edge

dct.cpp

Go to the documentation of this file.
00001 /* ScummVM - Graphic Adventure Engine
00002  *
00003  * ScummVM is the legal property of its developers, whose names
00004  * are too numerous to list here. Please refer to the COPYRIGHT
00005  * file distributed with this source distribution.
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License
00009  * as published by the Free Software Foundation; either version 2
00010  * of the License, or (at your option) any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00020  *
00021  */
00022 
00023 // Based on eos' (I)RDFT code which is in turn
00024 // Based upon the (I)DCT code in FFmpeg
00025 // Copyright (c) 2009 Peter Ross <pross@xvid.org>
00026 // Copyright (c) 2010 Alex Converse <alex.converse@gmail.com>
00027 // Copyright (c) 2010 Vitor Sessak
00028 
00029 #include "common/dct.h"
00030 
00031 namespace Common {
00032 
00033 DCT::DCT(int bits, TransformType trans) : _bits(bits), _cos(1 << (_bits + 2) ), _trans(trans), _rdft(nullptr) {
00034     int n = 1 << _bits;
00035 
00036     _tCos = _cos.getTable();
00037 
00038     _csc2 = new float[n / 2];
00039 
00040     _rdft = new RDFT(_bits, (_trans == DCT_III) ? RDFT::IDFT_C2R : RDFT::DFT_R2C);
00041 
00042     for (int i = 0; i < (n / 2); i++)
00043         _csc2[i] = 0.5 / sin((M_PI / (2 * n) * (2 * i + 1)));
00044 }
00045 
00046 DCT::~DCT() {
00047     delete _rdft;
00048     delete[] _csc2;
00049 }
00050 
00051 void DCT::calc(float *data) {
00052     switch (_trans) {
00053     case DCT_I:
00054         calcDCTI(data);
00055         break;
00056     case DCT_II:
00057         calcDCTII(data);
00058         break;
00059     case DCT_III:
00060         calcDCTIII(data);
00061         break;
00062     case DST_I:
00063         calcDSTI(data);
00064         break;
00065     }
00066 }
00067 
00068 /* sin((M_PI * x / (2*n)) */
00069 #define SIN(n,x) (_tCos[(n) - (x)])
00070 /* cos((M_PI * x / (2*n)) */
00071 #define COS(n,x) (_tCos[x])
00072 
00073 void DCT::calcDCTI(float *data) {
00074     int n = 1 << _bits;
00075 
00076     float next = -0.5f * (data[0] - data[n]);
00077 
00078     for (int i = 0; i < (n / 2); i++) {
00079         float tmp1 = data[i    ];
00080         float tmp2 = data[n - i];
00081 
00082         float s = SIN(n, 2 * i);
00083         float c = COS(n, 2 * i);
00084 
00085         c *= tmp1 - tmp2;
00086         s *= tmp1 - tmp2;
00087 
00088         next += c;
00089 
00090         tmp1 = (tmp1 + tmp2) * 0.5f;
00091 
00092         data[i    ] = tmp1 - s;
00093         data[n - i] = tmp1 + s;
00094     }
00095 
00096     _rdft->calc(data);
00097 
00098     data[n] = data[1];
00099     data[1] = next;
00100 
00101     for (int i = 3; i <= n; i += 2)
00102         data[i] = data[i - 2] - data[i];
00103 }
00104 
00105 void DCT::calcDCTII(float *data) {
00106     int n = 1 << _bits;
00107 
00108     for (int i = 0; i < (n / 2); i++) {
00109         float tmp1 = data[i        ];
00110         float tmp2 = data[n - i - 1];
00111 
00112         float s = SIN(n, 2 * i + 1);
00113 
00114         s *= tmp1 - tmp2;
00115 
00116         tmp1 = (tmp1 + tmp2) * 0.5f;
00117 
00118         data[i        ] = tmp1 + s;
00119         data[n - i - 1] = tmp1 - s;
00120     }
00121 
00122     _rdft->calc(data);
00123 
00124     float next = data[1] * 0.5f;
00125 
00126     data[1] *= -1;
00127 
00128     for (int i = n - 2; i >= 0; i -= 2) {
00129         float inr = data[i    ];
00130         float ini = data[i + 1];
00131 
00132         float c = COS(n, i);
00133         float s = SIN(n, i);
00134 
00135         data[i    ] = c * inr + s * ini;
00136         data[i + 1] = next;
00137 
00138         next += s * inr - c * ini;
00139     }
00140 }
00141 
00142 void DCT::calcDCTIII(float *data) {
00143     int n = 1 << _bits;
00144 
00145     float next  = data[n - 1];
00146     float inv_n = 1.0f / n;
00147 
00148     for (int i = n - 2; i >= 2; i -= 2) {
00149         float val1 = data[i    ];
00150         float val2 = data[i - 1] - data[i + 1];
00151 
00152         float c = COS(n, i);
00153         float s = SIN(n, i);
00154 
00155         data[i    ] = c * val1 + s * val2;
00156         data[i + 1] = s * val1 - c * val2;
00157     }
00158 
00159     data[1] = 2 * next;
00160 
00161     _rdft->calc(data);
00162 
00163     for (int i = 0; i < (n / 2); i++) {
00164         float tmp1 = data[i        ] * inv_n;
00165         float tmp2 = data[n - i - 1] * inv_n;
00166 
00167         float csc = _csc2[i] * (tmp1 - tmp2);
00168 
00169         tmp1 += tmp2;
00170 
00171         data[i        ] = tmp1 + csc;
00172         data[n - i - 1] = tmp1 - csc;
00173     }
00174 }
00175 
00176 void DCT::calcDSTI(float *data) {
00177     int n = 1 << _bits;
00178 
00179     data[0] = 0;
00180 
00181     for (int i = 1; i < (n / 2); i++) {
00182         float tmp1 = data[i    ];
00183         float tmp2 = data[n - i];
00184         float s = SIN(n, 2 * i);
00185 
00186         s   *=  tmp1 + tmp2;
00187         tmp1 = (tmp1 - tmp2) * 0.5f;
00188 
00189         data[i    ] = s + tmp1;
00190         data[n - i] = s - tmp1;
00191     }
00192 
00193     data[n / 2] *= 2;
00194 
00195     _rdft->calc(data);
00196 
00197     data[0] *= 0.5f;
00198 
00199     for (int i = 1; i < (n - 2); i += 2) {
00200         data[i + 1] +=  data[i - 1];
00201         data[i    ]  = -data[i + 2];
00202     }
00203 
00204     data[n - 1] = 0;
00205 }
00206 
00207 } // End of namespace Common


Generated on Sat Feb 16 2019 05:00:48 for ResidualVM by doxygen 1.7.1
curved edge   curved edge