mirror of
https://github.com/BlackLight/Voxifera.git
synced 2024-11-24 04:25:11 +01:00
Experimental implementation of FDCT.
This commit is contained in:
parent
8d23b07db0
commit
0058cbc913
7 changed files with 257 additions and 76 deletions
16
Makefile
16
Makefile
|
@ -1,9 +1,19 @@
|
||||||
|
CC = gcc
|
||||||
|
SRCDIR = src/
|
||||||
|
INCDIR = include/
|
||||||
|
CFLAGS = -I$(INCDIR) -O3 -funroll-loops -w -ffast-math -fno-stack-protector -ffunction-sections -funsafe-math-optimizations -fno-trapping-math
|
||||||
|
LFLAGS = -lm
|
||||||
|
|
||||||
all:
|
all:
|
||||||
gcc -Wall -pedantic -o vocal main.c dsp.c utils.c -lm -O3 -funroll-loops -w -ffast-math -fno-stack-protector -ffunction-sections -funsafe-math-optimizations -fno-trapping-math
|
$(CC) -c $(CFLAGS) $(SRCDIR)utils.c
|
||||||
|
$(CC) -c $(CFLAGS) $(SRCDIR)dsp.c
|
||||||
|
$(CC) -c $(CFLAGS) $(SRCDIR)fdct.c
|
||||||
|
|
||||||
|
$(CC) $(CFLAGS) $(LFLAGS) $(SRCDIR)main.c *.o -o voxifera
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm vocal
|
rm -f voxifera *.o
|
||||||
|
|
||||||
install:
|
install:
|
||||||
mkdir -p /usr/local/bin
|
mkdir -p /usr/local/bin
|
||||||
cp vocal /usr/local/bin
|
cp voxifera /usr/local/bin
|
||||||
|
|
53
include/fdct.h
Normal file
53
include/fdct.h
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
/***************************************************************************
|
||||||
|
* 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. *
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
// Very fast DCT (discrete cosine transform) implementation based on IEEE signal proc, 1992 #8 .
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#define FDCT_TOTSIZE 16384 /* !!! QUESTA È LA GRANDEZZA DEL BUFFER --DEVE-- ESSERE UNA POTENZA DI 2 !!! */
|
||||||
|
#define FDCT_POW 14 /* ln( FDCT_TOTSIZE ) */
|
||||||
|
#define FDCT_TSO2 8192 /* FDCT_TOTSIZE / 2 */
|
||||||
|
#define FDCT_TSO4 4096 /* FDCT_TOTSIZE / 4 */
|
||||||
|
#define FDCT_2OTS 0.00012207 /* 2 / FDCT_TOTSIZE */
|
||||||
|
#define FDCT_2OTS_SQ 0.011048543 /* sqrt( 2 / FDCT_TOTSIZE ) */
|
||||||
|
#define FDCT_FACTOR 0.7071067814
|
||||||
|
|
||||||
|
// fast DCT main structure
|
||||||
|
typedef struct {
|
||||||
|
double * transform;
|
||||||
|
double * ctable;
|
||||||
|
}
|
||||||
|
fdct_t;
|
||||||
|
|
||||||
|
// initialize the structure with data
|
||||||
|
void fdct_init( fdct_t *dct, unsigned char *data );
|
||||||
|
// reverse data 'til size-th byte
|
||||||
|
inline void fdct_bitrev( double *data, unsigned int size );
|
||||||
|
// complete data reversing
|
||||||
|
inline void fdct_scramble( double *data );
|
||||||
|
// compute cosine coefficents
|
||||||
|
inline void fdct_butterflies( fdct_t *dct );
|
||||||
|
// compute FDCT sums on data
|
||||||
|
inline void fdct_sums(double *data);
|
||||||
|
// compute FDCT
|
||||||
|
inline void fdct_compute( fdct_t *dct );
|
||||||
|
// compute FDCT vector sum, where k is the normalizing factor and neutral an optional mask to subtract
|
||||||
|
inline double fdct_sum( fdct_t *dct, double div, unsigned char *neutral, unsigned int neutral_size );
|
||||||
|
// release FDCT structure
|
||||||
|
void fdct_release( fdct_t *dct );
|
181
src/fdct.c
Normal file
181
src/fdct.c
Normal file
|
@ -0,0 +1,181 @@
|
||||||
|
/***************************************************************************
|
||||||
|
* 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);
|
||||||
|
}
|
|
@ -16,43 +16,10 @@
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#include "vocal.h"
|
#include "vocal.h"
|
||||||
|
#include "fdct.h"
|
||||||
|
|
||||||
typedef enum { capture, append } mode;
|
typedef enum { capture, append } mode;
|
||||||
|
|
||||||
/* tabella dei fattoriali di 1/n!, dove 0 <= n < 30 */
|
|
||||||
static double ftable[] = { 0.0, 1.0, 0.5, 0.166667, 0.0416667, 0.00833333, 0.00138889, 0.000198413,
|
|
||||||
2.48016e-05, 2.75573e-06, 2.75573e-07, 2.50521e-08, 2.08768e-09, 5.17584e-10,
|
|
||||||
7.81894e-10, 4.98925e-10, 4.98955e-10, -3.46594e-09, -1.11305e-09, 9.12062e-09,
|
|
||||||
-4.75707e-10, -8.3674e-10, -1.91309e-09, 1.15948e-09, -1.28875e-09, 4.81654e-10,
|
|
||||||
-5.39409e-10, 6.73499e-10, -7.26886e-10, -8.05468e-10 };
|
|
||||||
/* intervallo in cui posizionare x */
|
|
||||||
static double offset[] = { 0.0, M_PI };
|
|
||||||
/* sviluppo in serie di Taylor della funzione coseno
|
|
||||||
*
|
|
||||||
* x : valore per cui calcolare il coseno .
|
|
||||||
* terms : numero di termini da usare nello sviluppo dove 0 <= terms < 30 e terms è un numero pari .
|
|
||||||
*/
|
|
||||||
inline double taylor_cosine( double x, int terms ) {
|
|
||||||
|
|
||||||
int i = terms,
|
|
||||||
quadrant = x * TWO_O_M_PI; /* 0, 1, 2 o 3 */
|
|
||||||
double x2, r;
|
|
||||||
|
|
||||||
/* tariamo x in modo tale che −π < x < π */
|
|
||||||
x = x - quadrant * H_M_PI;
|
|
||||||
quadrant += 1;
|
|
||||||
x = offset[ (quadrant >> 1) & 1 ] - x;
|
|
||||||
x2 = -(x*x);
|
|
||||||
/* eseguo lo sviluppo in serie */
|
|
||||||
r = ftable[i] * x2;
|
|
||||||
for( i -= 2; i > 0; i -= 2 ){
|
|
||||||
r += ftable[i];
|
|
||||||
r *= x2;
|
|
||||||
}
|
|
||||||
|
|
||||||
return r + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void helpandusage() {
|
void helpandusage() {
|
||||||
fprintf (stderr,
|
fprintf (stderr,
|
||||||
"---=== BlackLight's & evilsocket's vocal recognition v.0.1b ===---\n"
|
"---=== BlackLight's & evilsocket's vocal recognition v.0.1b ===---\n"
|
||||||
|
@ -72,10 +39,9 @@ int main (int argc, char **argv) {
|
||||||
char *line, *tmp, *cmd = NULL, *fname = NULL, *device = NULL;
|
char *line, *tmp, *cmd = NULL, *fname = NULL, *device = NULL;
|
||||||
char **match = NULL;
|
char **match = NULL;
|
||||||
|
|
||||||
double deviance;
|
fdct_t dct;
|
||||||
double *neutral, *trans;
|
double sum, deviance, value;
|
||||||
double value, sum = 0.0;
|
double *neutral;
|
||||||
double t, v;
|
|
||||||
|
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
time_t t1, t2;
|
time_t t1, t2;
|
||||||
|
@ -98,8 +64,7 @@ int main (int argc, char **argv) {
|
||||||
|
|
||||||
buf = (u8*) malloc(TOTSIZE);
|
buf = (u8*) malloc(TOTSIZE);
|
||||||
neutral = (double*) malloc(TOTSIZE*sizeof(double));
|
neutral = (double*) malloc(TOTSIZE*sizeof(double));
|
||||||
trans = (double*) malloc(TOTSIZE*sizeof(double));
|
memset(buf, 0x80, TOTSIZE );
|
||||||
memset(buf, 0x80, TOTSIZE);
|
|
||||||
|
|
||||||
if (!fname) {
|
if (!fname) {
|
||||||
fname = (char*) malloc(0x100);
|
fname = (char*) malloc(0x100);
|
||||||
|
@ -131,43 +96,15 @@ int main (int argc, char **argv) {
|
||||||
t1 = time((unsigned) NULL);
|
t1 = time((unsigned) NULL);
|
||||||
|
|
||||||
|
|
||||||
/* porto fuori il loop per i = 0 così da evitare controlli su t (che dipende da i)
|
fdct_init( &dct, buf );
|
||||||
* e j nel secondo loop più consistente . */
|
|
||||||
v = 0;
|
|
||||||
for( j = 0; j < TOTSIZE; ++j ){
|
|
||||||
v += buf[j];
|
|
||||||
}
|
|
||||||
v *= M_COEFF;
|
|
||||||
v -= neutral[0];
|
|
||||||
v = (v >= 0) ? v : -v;
|
|
||||||
trans[0] = log(v);
|
|
||||||
|
|
||||||
double init = buf[0];
|
sum = fdct_sum( &dct, 36927.96, NULL/*neutral*/, TOTSIZE );
|
||||||
for( i = 1; i < TOTSIZE; ++i ) {
|
|
||||||
t = M_FACTOR * i;
|
|
||||||
v = init;
|
|
||||||
/* dato che ho inizializzato v a buf[0] e sono sicuro che t != 0,
|
|
||||||
* posso partire da j = 1 . */
|
|
||||||
for( j = 1; j < TOTSIZE; ++j ){
|
|
||||||
v += buf[j] * taylor_cosine( t * j, 10 );
|
|
||||||
}
|
|
||||||
v *= M_COEFF;
|
|
||||||
v -= neutral[i];
|
|
||||||
v = (v >= 0) ? v : -v;
|
|
||||||
trans[i] = log(v);
|
|
||||||
}
|
|
||||||
|
|
||||||
free(neutral);
|
fdct_release(&dct);
|
||||||
free(buf);
|
|
||||||
|
|
||||||
t2 = time((unsigned) NULL);
|
t2 = time((unsigned) NULL);
|
||||||
|
|
||||||
printf ("DCT computing: done in %u seconds\n", (unsigned int) (t2-t1));
|
printf ("DCT computing: done in %u seconds\n", (unsigned int) (t2-t1));
|
||||||
|
|
||||||
for (i=0; i<TOTSIZE; i++)
|
|
||||||
sum += trans[i];
|
|
||||||
sum = exp(sum/100000.0);
|
|
||||||
free(trans);
|
|
||||||
|
|
||||||
printf ("vocal sequence successfully acquired, Fourier sum = %g\n", sum);
|
printf ("vocal sequence successfully acquired, Fourier sum = %g\n", sum);
|
||||||
|
|
||||||
if (m == append) {
|
if (m == append) {
|
Loading…
Reference in a new issue