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     default:
00066         break;
00067     }
00068 }
00069 
00070 /* sin((M_PI * x / (2*n)) */
00071 #define SIN(n,x) (_tCos[(n) - (x)])
00072 /* cos((M_PI * x / (2*n)) */
00073 #define COS(n,x) (_tCos[x])
00074 
00075 void DCT::calcDCTI(float *data) {
00076     int n = 1 << _bits;
00077 
00078     float next = -0.5f * (data[0] - data[n]);
00079 
00080     for (int i = 0; i < (n / 2); i++) {
00081         float tmp1 = data[i    ];
00082         float tmp2 = data[n - i];
00083 
00084         float s = SIN(n, 2 * i);
00085         float c = COS(n, 2 * i);
00086 
00087         c *= tmp1 - tmp2;
00088         s *= tmp1 - tmp2;
00089 
00090         next += c;
00091 
00092         tmp1 = (tmp1 + tmp2) * 0.5f;
00093 
00094         data[i    ] = tmp1 - s;
00095         data[n - i] = tmp1 + s;
00096     }
00097 
00098     _rdft->calc(data);
00099 
00100     data[n] = data[1];
00101     data[1] = next;
00102 
00103     for (int i = 3; i <= n; i += 2)
00104         data[i] = data[i - 2] - data[i];
00105 }
00106 
00107 void DCT::calcDCTII(float *data) {
00108     int n = 1 << _bits;
00109 
00110     for (int i = 0; i < (n / 2); i++) {
00111         float tmp1 = data[i        ];
00112         float tmp2 = data[n - i - 1];
00113 
00114         float s = SIN(n, 2 * i + 1);
00115 
00116         s *= tmp1 - tmp2;
00117 
00118         tmp1 = (tmp1 + tmp2) * 0.5f;
00119 
00120         data[i        ] = tmp1 + s;
00121         data[n - i - 1] = tmp1 - s;
00122     }
00123 
00124     _rdft->calc(data);
00125 
00126     float next = data[1] * 0.5f;
00127 
00128     data[1] *= -1;
00129 
00130     for (int i = n - 2; i >= 0; i -= 2) {
00131         float inr = data[i    ];
00132         float ini = data[i + 1];
00133 
00134         float c = COS(n, i);
00135         float s = SIN(n, i);
00136 
00137         data[i    ] = c * inr + s * ini;
00138         data[i + 1] = next;
00139 
00140         next += s * inr - c * ini;
00141     }
00142 }
00143 
00144 void DCT::calcDCTIII(float *data) {
00145     int n = 1 << _bits;
00146 
00147     float next  = data[n - 1];
00148     float inv_n = 1.0f / n;
00149 
00150     for (int i = n - 2; i >= 2; i -= 2) {
00151         float val1 = data[i    ];
00152         float val2 = data[i - 1] - data[i + 1];
00153 
00154         float c = COS(n, i);
00155         float s = SIN(n, i);
00156 
00157         data[i    ] = c * val1 + s * val2;
00158         data[i + 1] = s * val1 - c * val2;
00159     }
00160 
00161     data[1] = 2 * next;
00162 
00163     _rdft->calc(data);
00164 
00165     for (int i = 0; i < (n / 2); i++) {
00166         float tmp1 = data[i        ] * inv_n;
00167         float tmp2 = data[n - i - 1] * inv_n;
00168 
00169         float csc = _csc2[i] * (tmp1 - tmp2);
00170 
00171         tmp1 += tmp2;
00172 
00173         data[i        ] = tmp1 + csc;
00174         data[n - i - 1] = tmp1 - csc;
00175     }
00176 }
00177 
00178 void DCT::calcDSTI(float *data) {
00179     int n = 1 << _bits;
00180 
00181     data[0] = 0;
00182 
00183     for (int i = 1; i < (n / 2); i++) {
00184         float tmp1 = data[i    ];
00185         float tmp2 = data[n - i];
00186         float s = SIN(n, 2 * i);
00187 
00188         s   *=  tmp1 + tmp2;
00189         tmp1 = (tmp1 - tmp2) * 0.5f;
00190 
00191         data[i    ] = s + tmp1;
00192         data[n - i] = s - tmp1;
00193     }
00194 
00195     data[n / 2] *= 2;
00196 
00197     _rdft->calc(data);
00198 
00199     data[0] *= 0.5f;
00200 
00201     for (int i = 1; i < (n - 2); i += 2) {
00202         data[i + 1] +=  data[i - 1];
00203         data[i    ]  = -data[i + 2];
00204     }
00205 
00206     data[n - 1] = 0;
00207 }
00208 
00209 } // End of namespace Common


Generated on Sat May 30 2020 05:00:37 for ResidualVM by doxygen 1.7.1
curved edge   curved edge