182 lines
5.0 KiB
C
182 lines
5.0 KiB
C
|
/***************************************************************************
|
||
|
* This program is free software; you can redistribute it and/or modify *
|
||
|
* it under the terms of the GNU General Public License as published by *
|
||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||
|
* (at your option) any later version. *
|
||
|
* *
|
||
|
* This program is distributed in the hope that it will be useful, *
|
||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||
|
* GNU General Public License for more details. *
|
||
|
* *
|
||
|
* You should have received a copy of the GNU General Public License *
|
||
|
* along with this program; if not, write to the *
|
||
|
* Free Software Foundation, Inc., *
|
||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||
|
***************************************************************************/
|
||
|
#include "fdct.h"
|
||
|
|
||
|
void fdct_init( fdct_t *dct, unsigned char *data ){
|
||
|
int i, group, base, item, nitems;
|
||
|
double factor;
|
||
|
|
||
|
/* alloc transform vector and fill with data */
|
||
|
dct->transform = (double *)calloc( FDCT_TOTSIZE, sizeof(double) );
|
||
|
for( i = 0; i < FDCT_TOTSIZE; i++ ){
|
||
|
dct->transform[i] = (double)data[i];
|
||
|
}
|
||
|
|
||
|
/* alloc and fill cosines table */
|
||
|
dct->ctable = (double *)calloc( FDCT_TOTSIZE, sizeof(double) );
|
||
|
for( i = 0; i <= FDCT_TSO2 - 1; i++ ){
|
||
|
dct->ctable[FDCT_TSO2 + i] = 4 * i + 1;
|
||
|
}
|
||
|
|
||
|
for( group = 1; group <= FDCT_POW - 1; group++ ){
|
||
|
nitems = base = 1 << (group - 1);
|
||
|
factor = 1.0 * (1 << (FDCT_POW - group));
|
||
|
for( item = 1; item <= nitems; item++ ){
|
||
|
dct->ctable[base + item - 1] = factor * dct->ctable[FDCT_TSO2 + item - 1];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
for( i = 1; i <= FDCT_TOTSIZE - 1; i++ ){
|
||
|
dct->ctable[i] = 1.0 / (2.0 * cos( dct->ctable[i] * M_PI / (2.0 * FDCT_TOTSIZE) ));
|
||
|
}
|
||
|
|
||
|
return dct;
|
||
|
}
|
||
|
|
||
|
inline void fdct_bitrev( double *data, unsigned int size ){
|
||
|
int i, m,
|
||
|
j = 1,
|
||
|
hsize = size >> 1;
|
||
|
double tmp;
|
||
|
|
||
|
if( size <= 2 ){ return; }
|
||
|
|
||
|
for( i = 1; i <= size; i++ ){
|
||
|
if(i < j){
|
||
|
tmp = data[j - 1];
|
||
|
data[j - 1] = data[i - 1];
|
||
|
data[i - 1] = tmp;
|
||
|
}
|
||
|
m = hsize;
|
||
|
while(j > m){
|
||
|
j = j - m;
|
||
|
m = (m + 1) >> 1;
|
||
|
}
|
||
|
j = j + m;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
inline void fdct_scramble( double *data ){
|
||
|
double tmp;
|
||
|
int i, ii1, ii2;
|
||
|
|
||
|
fdct_bitrev( data, FDCT_TOTSIZE );
|
||
|
fdct_bitrev( &data[0], FDCT_TSO2 );
|
||
|
fdct_bitrev( &data[FDCT_TSO2], FDCT_TSO2);
|
||
|
|
||
|
ii1 = FDCT_TOTSIZE - 1;
|
||
|
ii2 = FDCT_TSO2;
|
||
|
for( i = 0; i <= FDCT_TSO4 - 1; i++, ii1--, ii2++ ){
|
||
|
tmp = data[ii1];
|
||
|
data[ii1] = data[ii2];
|
||
|
data[ii2] = tmp;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
inline void fdct_butterflies( fdct_t *dct ){
|
||
|
int stage, ii1, ii2,
|
||
|
butterfly,
|
||
|
ngroups,
|
||
|
group,
|
||
|
wingspan,
|
||
|
inc,
|
||
|
ptr;
|
||
|
double cosine, value;
|
||
|
|
||
|
for( stage = FDCT_POW; stage >= 1; stage-- ){
|
||
|
ngroups = 1 << (FDCT_POW - stage);
|
||
|
wingspan = 1 << (stage - 1);
|
||
|
inc = wingspan << 1;
|
||
|
|
||
|
for( butterfly = 1; butterfly <= wingspan; butterfly++ ){
|
||
|
cosine = dct->ctable[ wingspan + butterfly - 1 ];
|
||
|
ptr = 0;
|
||
|
|
||
|
for( group = 1; group <= ngroups; group++ ){
|
||
|
ii1 = ptr + butterfly - 1;
|
||
|
ii2 = ii1 + wingspan;
|
||
|
value = dct->transform[ii2];
|
||
|
dct->transform[ii2] = cosine *(dct->transform[ii1] - value);
|
||
|
dct->transform[ii1] = dct->transform[ii1] + value;
|
||
|
ptr += inc;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
inline void fdct_sums(double *data){
|
||
|
int stepsize,
|
||
|
stage, i,
|
||
|
nthreads,
|
||
|
thread,
|
||
|
step,
|
||
|
nsteps;
|
||
|
|
||
|
for( stage = FDCT_POW - 1; stage >= 1; stage-- ){
|
||
|
nthreads = 1 << (stage - 1);
|
||
|
stepsize = nthreads << 1;
|
||
|
nsteps = (1 << (FDCT_POW - stage)) - 1;
|
||
|
|
||
|
for( thread = 1; thread <= nthreads; thread++ ){
|
||
|
i = nthreads + thread - 1;
|
||
|
for( step = 1; step <= nsteps; step++ ){
|
||
|
data[i] += data[i + stepsize];
|
||
|
i += stepsize;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
inline void fdct_compute( fdct_t *dct ){
|
||
|
int i;
|
||
|
|
||
|
fdct_scramble( dct->transform );
|
||
|
fdct_butterflies( dct );
|
||
|
fdct_bitrev( dct->transform, FDCT_TOTSIZE );
|
||
|
fdct_sums(dct->transform);
|
||
|
|
||
|
dct->transform[0] *= FDCT_FACTOR;
|
||
|
for( i = 0; i <= FDCT_TOTSIZE - 1; i++ ){
|
||
|
dct->transform[i] *= FDCT_2OTS_SQ;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
inline double fdct_sum( fdct_t *dct, double div, unsigned char *neutral, unsigned int neutral_size ){
|
||
|
int i;
|
||
|
double sum = 0.0;
|
||
|
|
||
|
fdct_compute( dct );
|
||
|
|
||
|
if( neutral ){
|
||
|
for( i = 0; i < FDCT_TOTSIZE; i++ ){
|
||
|
sum += dct->transform[i] - neutral[i % neutral_size];
|
||
|
}
|
||
|
}
|
||
|
else{
|
||
|
for( i = 0; i < FDCT_TOTSIZE; i++ ){
|
||
|
sum += dct->transform[i];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return fabs(sum / div);
|
||
|
}
|
||
|
|
||
|
void fdct_release( fdct_t *dct ){
|
||
|
free(dct->ctable);
|
||
|
free(dct->transform);
|
||
|
}
|