|
Packit |
47f805 |
/*
|
|
Packit |
47f805 |
* Usage: abx original_file test_file
|
|
Packit |
47f805 |
*
|
|
Packit |
47f805 |
* Ask you as long as the probability is below the given percentage that
|
|
Packit |
47f805 |
* you recognize differences
|
|
Packit |
47f805 |
*
|
|
Packit |
47f805 |
* Example: abx music.wav music.mp3
|
|
Packit |
47f805 |
* abx music.wav music.mp3 --help
|
|
Packit |
47f805 |
*
|
|
Packit |
47f805 |
* Note: several 'decoding' utilites must be on the 'right' place
|
|
Packit |
47f805 |
*
|
|
Packit |
47f805 |
* Bugs:
|
|
Packit |
47f805 |
* fix path of decoding utilities
|
|
Packit |
47f805 |
* only 16 bit support
|
|
Packit |
47f805 |
* only support of the same sample frequency
|
|
Packit |
47f805 |
* no exact WAV file header analysis
|
|
Packit |
47f805 |
* no mouse or joystick support
|
|
Packit |
47f805 |
* don't uses functionality of ath.c
|
|
Packit |
47f805 |
* only 2 files are comparable
|
|
Packit |
47f805 |
* worse user interface
|
|
Packit |
47f805 |
* quick & dirty hack
|
|
Packit |
47f805 |
* wastes memory
|
|
Packit |
47f805 |
* compile time warnings
|
|
Packit |
47f805 |
* buffer overruns possible
|
|
Packit |
47f805 |
* no dithering if recalcs are necessary
|
|
Packit |
47f805 |
* correlation only done with one channel (2 channels, sum, what is better?)
|
|
Packit |
47f805 |
* lowpass+highpass filtering (300 Hz+2*5 kHz) before delay+amplitude corr
|
|
Packit |
47f805 |
* cross fade at start/stop
|
|
Packit |
47f805 |
* non portable keyboard
|
|
Packit |
47f805 |
* fade out on quit, fade in on start
|
|
Packit |
47f805 |
* level/delay ajustment should be switchable
|
|
Packit |
47f805 |
* pause key missing
|
|
Packit |
47f805 |
* problems with digital silence files (division by 0)
|
|
Packit |
47f805 |
* Gr��e cross corr fenster 2^16...18
|
|
Packit |
47f805 |
* Stellensuche, ab 0*len oder 0.1*len oder 0.25*len, nach Effektiv oder Spitzenwert
|
|
Packit |
47f805 |
* Absturz bei LPAC feeding, warum?
|
|
Packit |
47f805 |
* Als 'B' beim Ratespiel sollte auch '0'...'9' verwendbar sein
|
|
Packit |
47f805 |
* Oder mit einem Filter 300 Hz...3 kHz vorher filtern?
|
|
Packit |
47f805 |
* Multiple encoded differenziertes Signal
|
|
Packit |
47f805 |
* Amplitudenanpassung schaltbar machen?
|
|
Packit |
47f805 |
* Direkt auf der Kommandozeile kodieren:
|
|
Packit |
47f805 |
* abx "test.wav" "!lame -b128 test.wav -"
|
|
Packit |
47f805 |
*/
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
// If the program should increase it priority while playing define USE_NICE.
|
|
Packit |
47f805 |
// Program must be installed SUID root. Decompressing phase is using NORMAL priority
|
|
Packit |
47f805 |
#define USE_NICE
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
// Not only increase priority but change to relatime scheduling. Program must be installed SUID root
|
|
Packit |
47f805 |
#define USE_REALTIME
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
// Path of the programs: mpg123, mppdec, faad, ac3dec, ogg123, lpac, shorten, MAC, flac
|
|
Packit |
47f805 |
//#define PATH_OF_EXTERNAL_TOOLS_FOR_UNCOMPRESSING "/usr/local/bin/"
|
|
Packit |
47f805 |
#define PATH_OF_EXTERNAL_TOOLS_FOR_UNCOMPRESSING ""
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
#if defined HAVE_CONFIG_H
|
|
Packit |
47f805 |
# include <config.h>
|
|
Packit |
47f805 |
#endif
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
#include <assert.h>
|
|
Packit |
47f805 |
#include <ctype.h>
|
|
Packit |
47f805 |
#include <fcntl.h>
|
|
Packit |
47f805 |
#include <limits.h>
|
|
Packit |
47f805 |
#include <math.h>
|
|
Packit |
47f805 |
#include <memory.h>
|
|
Packit |
47f805 |
#include <signal.h>
|
|
Packit |
47f805 |
#include <stdio.h>
|
|
Packit |
47f805 |
#include <stdlib.h>
|
|
Packit |
47f805 |
#include <string.h>
|
|
Packit |
47f805 |
#include <termios.h>
|
|
Packit |
47f805 |
#include <time.h>
|
|
Packit |
47f805 |
#include <unistd.h>
|
|
Packit |
47f805 |
#include <sys/ioctl.h>
|
|
Packit |
47f805 |
#include <sys/mman.h>
|
|
Packit |
47f805 |
#include <sys/stat.h>
|
|
Packit |
47f805 |
#include <sys/time.h>
|
|
Packit |
47f805 |
#include <sys/types.h>
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
#define MAX (1<<17)
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
#if defined HAVE_SYS_SOUNDCARD_H
|
|
Packit |
47f805 |
# include <sys/soundcard.h>
|
|
Packit |
47f805 |
#elif defined HAVE_LINUX_SOUNDCARD_H
|
|
Packit |
47f805 |
# include <linux/soundcard.h>
|
|
Packit |
47f805 |
#else
|
|
Packit |
47f805 |
# include <linux/soundcard.h> /* stand alone compilable for my tests */
|
|
Packit |
47f805 |
#endif
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
#if defined USE_NICE
|
|
Packit |
47f805 |
# include <sys/resource.h>
|
|
Packit |
47f805 |
#endif
|
|
Packit |
47f805 |
#if defined USE_REALTIME
|
|
Packit |
47f805 |
# include <sched.h>
|
|
Packit |
47f805 |
#endif
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
#define BF ((freq)/25)
|
|
Packit |
47f805 |
#define MAX_LEN (210 * 44100)
|
|
Packit |
47f805 |
#define DMA_SAMPLES 512 /* My Linux driver uses a DMA buffer of 65536*16 bit, which is 32768 samples in 16 bit stereo mode */
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
void Set_Realtime ( void )
|
|
Packit |
47f805 |
{
|
|
Packit |
47f805 |
#if defined USE_REALTIME
|
|
Packit |
47f805 |
struct sched_param sp;
|
|
Packit |
47f805 |
int ret;
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
memset ( &sp, 0, sizeof(sp) );
|
|
Packit |
47f805 |
seteuid ( 0 );
|
|
Packit |
47f805 |
sp.sched_priority = sched_get_priority_min ( SCHED_FIFO );
|
|
Packit |
47f805 |
ret = sched_setscheduler ( 0, SCHED_RR, &sp );
|
|
Packit |
47f805 |
seteuid ( getuid() );
|
|
Packit |
47f805 |
#endif
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
#if defined USE_NICE
|
|
Packit |
47f805 |
seteuid ( 0 );
|
|
Packit |
47f805 |
setpriority ( PRIO_PROCESS, getpid(), -20 );
|
|
Packit |
47f805 |
seteuid ( getuid() );
|
|
Packit |
47f805 |
#endif
|
|
Packit |
47f805 |
}
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
int verbose = 0;
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
static struct termios stored_settings;
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
void reset ( void )
|
|
Packit |
47f805 |
{
|
|
Packit |
47f805 |
tcsetattr ( 0, TCSANOW, &stored_settings );
|
|
Packit |
47f805 |
}
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
void set ( void )
|
|
Packit |
47f805 |
{
|
|
Packit |
47f805 |
struct termios new_settings;
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
tcgetattr ( 0, &stored_settings );
|
|
Packit |
47f805 |
new_settings = stored_settings;
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
new_settings.c_lflag &= ~ECHO;
|
|
Packit |
47f805 |
/* Disable canonical mode, and set buffer size to 1 byte */
|
|
Packit |
47f805 |
new_settings.c_lflag &= ~ICANON;
|
|
Packit |
47f805 |
new_settings.c_cc[VTIME] = 0;
|
|
Packit |
47f805 |
new_settings.c_cc[VMIN] = 1;
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
tcsetattr(0,TCSANOW,&new_settings);
|
|
Packit |
47f805 |
return;
|
|
Packit |
47f805 |
}
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
int sel ( void )
|
|
Packit |
47f805 |
{
|
|
Packit |
47f805 |
struct timeval t;
|
|
Packit |
47f805 |
fd_set fd [1];
|
|
Packit |
47f805 |
int ret;
|
|
Packit |
47f805 |
unsigned char c;
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
FD_SET (0, fd);
|
|
Packit |
47f805 |
t.tv_sec = 0;
|
|
Packit |
47f805 |
t.tv_usec = 0;
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
ret = select ( 1, fd, NULL, NULL, &t );
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
switch ( ret ) {
|
|
Packit |
47f805 |
case 0:
|
|
Packit |
47f805 |
return -1;
|
|
Packit |
47f805 |
case 1:
|
|
Packit |
47f805 |
ret = read (0, &c, 1);
|
|
Packit |
47f805 |
return ret == 1 ? c : -1;
|
|
Packit |
47f805 |
default:
|
|
Packit |
47f805 |
return -2;
|
|
Packit |
47f805 |
}
|
|
Packit |
47f805 |
}
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
#define FFT_ERR_OK 0 // no error
|
|
Packit |
47f805 |
#define FFT_ERR_LD 1 // len is not a power of 2
|
|
Packit |
47f805 |
#define FFT_ERR_MAX 2 // len too large
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
typedef float f_t;
|
|
Packit |
47f805 |
typedef f_t compl [2];
|
|
Packit |
47f805 |
compl root [MAX >> 1]; // Sinus-/Kosinustabelle
|
|
Packit |
47f805 |
size_t shuffle [MAX >> 1] [2]; // Shuffle-Tabelle
|
|
Packit |
47f805 |
size_t shuffle_len;
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
// Bitinversion
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
size_t swap ( size_t number, int bits )
|
|
Packit |
47f805 |
{
|
|
Packit |
47f805 |
size_t ret;
|
|
Packit |
47f805 |
for ( ret = 0; bits--; number >>= 1 ) {
|
|
Packit |
47f805 |
ret = ret + ret + (number & 1);
|
|
Packit |
47f805 |
}
|
|
Packit |
47f805 |
return ret;
|
|
Packit |
47f805 |
}
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
// Bestimmen des Logarithmus dualis
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
int ld ( size_t number )
|
|
Packit |
47f805 |
{
|
|
Packit |
47f805 |
size_t i;
|
|
Packit |
47f805 |
for ( i = 0; i < sizeof(size_t)*CHAR_BIT; i++ )
|
|
Packit |
47f805 |
if ( ((size_t)1 << i) == number )
|
|
Packit |
47f805 |
return i;
|
|
Packit |
47f805 |
return -1;
|
|
Packit |
47f805 |
}
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
// Die eigentliche FFT
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
int fft ( compl* fn, const size_t newlen )
|
|
Packit |
47f805 |
{
|
|
Packit |
47f805 |
static size_t len = 0;
|
|
Packit |
47f805 |
static int bits = 0;
|
|
Packit |
47f805 |
size_t i;
|
|
Packit |
47f805 |
size_t j;
|
|
Packit |
47f805 |
size_t k;
|
|
Packit |
47f805 |
size_t p;
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
/* Tabellen initialisieren */
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
if ( newlen != len ) {
|
|
Packit |
47f805 |
len = newlen;
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
if ( (bits=ld(len)) == -1 )
|
|
Packit |
47f805 |
return FFT_ERR_LD;
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
for ( i = 0; i < len; i++ ) {
|
|
Packit |
47f805 |
j = swap ( i, bits );
|
|
Packit |
47f805 |
if ( i < j ) {
|
|
Packit |
47f805 |
shuffle [shuffle_len] [0] = i;
|
|
Packit |
47f805 |
shuffle [shuffle_len] [1] = j;
|
|
Packit |
47f805 |
shuffle_len++;
|
|
Packit |
47f805 |
}
|
|
Packit |
47f805 |
}
|
|
Packit |
47f805 |
for ( i = 0; i < (len>>1); i++ ) {
|
|
Packit |
47f805 |
double x = (double) swap ( i+i, bits ) * 2*M_PI/len;
|
|
Packit |
47f805 |
root [i] [0] = cos (x);
|
|
Packit |
47f805 |
root [i] [1] = sin (x);
|
|
Packit |
47f805 |
}
|
|
Packit |
47f805 |
}
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
/* Eigentliche Transformation */
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
p = len >> 1;
|
|
Packit |
47f805 |
do {
|
|
Packit |
47f805 |
f_t* bp = (f_t*) root;
|
|
Packit |
47f805 |
f_t* si = (f_t*) fn;
|
|
Packit |
47f805 |
f_t* di = (f_t*) fn+p+p;
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
do {
|
|
Packit |
47f805 |
k = p;
|
|
Packit |
47f805 |
do {
|
|
Packit |
47f805 |
f_t mulr = bp[0]*di[0] - bp[1]*di[1];
|
|
Packit |
47f805 |
f_t muli = bp[1]*di[0] + bp[0]*di[1];
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
di[0] = si[0] - mulr;
|
|
Packit |
47f805 |
di[1] = si[1] - muli;
|
|
Packit |
47f805 |
si[0] += mulr;
|
|
Packit |
47f805 |
si[1] += muli;
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
si += 2, di += 2;
|
|
Packit |
47f805 |
} while ( --k );
|
|
Packit |
47f805 |
si += p+p, di += p+p, bp += 2;
|
|
Packit |
47f805 |
} while ( si < &fn[len][0] );
|
|
Packit |
47f805 |
} while (p >>= 1);
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
/* Bitinversion */
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
for ( k = 0; k < shuffle_len; k++ ) {
|
|
Packit |
47f805 |
f_t tmp;
|
|
Packit |
47f805 |
i = shuffle [k] [0];
|
|
Packit |
47f805 |
j = shuffle [k] [1];
|
|
Packit |
47f805 |
tmp = fn [i][0]; fn [i][0] = fn [j][0]; fn [j][0] = tmp;
|
|
Packit |
47f805 |
tmp = fn [i][1]; fn [i][1] = fn [j][1]; fn [j][1] = tmp;
|
|
Packit |
47f805 |
}
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
return FFT_ERR_OK;
|
|
Packit |
47f805 |
}
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
void printnumber ( long double x )
|
|
Packit |
47f805 |
{
|
|
Packit |
47f805 |
unsigned exp = 0;
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
if ( x < 9.999995 ) fprintf ( stderr, "%7.5f", (double)x );
|
|
Packit |
47f805 |
else if ( x < 99.99995 ) fprintf ( stderr, "%7.4f", (double)x );
|
|
Packit |
47f805 |
else if ( x < 999.9995 ) fprintf ( stderr, "%7.3f", (double)x );
|
|
Packit |
47f805 |
else if ( x < 9999.995 ) fprintf ( stderr, "%7.2f", (double)x );
|
|
Packit |
47f805 |
else if ( x < 99999.95 ) fprintf ( stderr, "%7.1f", (double)x );
|
|
Packit |
47f805 |
else if ( x < 999999.5 ) fprintf ( stderr, "%6.0f.", (double)x );
|
|
Packit |
47f805 |
else if ( x < 9999999.5 ) fprintf ( stderr, "%7.0f", (double)x );
|
|
Packit |
47f805 |
else if ( x < 9.9995e9 ) {
|
|
Packit |
47f805 |
while ( x >= 9.9995 ) exp++ , x /= 10;
|
|
Packit |
47f805 |
fprintf ( stderr, "%5.3fe%01u", (double)x, exp );
|
|
Packit |
47f805 |
} else if ( x < 9.995e99 ) {
|
|
Packit |
47f805 |
while ( x >= 9.5e6 ) exp+=6 , x /= 1.e6;
|
|
Packit |
47f805 |
while ( x >= 9.995 ) exp++ , x /= 10;
|
|
Packit |
47f805 |
fprintf ( stderr, "%4.2fe%02u", (double)x, exp );
|
|
Packit |
47f805 |
} else if ( x < 9.95e999L ) {
|
|
Packit |
47f805 |
while ( x >= 9.5e18 ) exp+=18, x /= 1.e18;
|
|
Packit |
47f805 |
while ( x >= 9.95 ) exp++ , x /= 10;
|
|
Packit |
47f805 |
fprintf ( stderr, "%3.1fe%03u", (double)x, exp );
|
|
Packit |
47f805 |
} else {
|
|
Packit |
47f805 |
while ( x >= 9.5e48 ) exp+=48, x /= 1.e48;
|
|
Packit |
47f805 |
while ( x >= 9.5 ) exp++ , x /= 10;
|
|
Packit |
47f805 |
fprintf ( stderr, "%1.0f.e%04u", (double)x, exp );
|
|
Packit |
47f805 |
}
|
|
Packit |
47f805 |
}
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
double logdual ( long double x )
|
|
Packit |
47f805 |
{
|
|
Packit |
47f805 |
unsigned exp = 0;
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
while ( x >= 18446744073709551616. )
|
|
Packit |
47f805 |
x /= 18446744073709551616., exp += 64;
|
|
Packit |
47f805 |
while ( x >= 256. )
|
|
Packit |
47f805 |
x /= 256., exp += 8;
|
|
Packit |
47f805 |
while ( x >= 2. )
|
|
Packit |
47f805 |
x /= 2., exp += 1;
|
|
Packit |
47f805 |
return exp + log (x)/log(2);
|
|
Packit |
47f805 |
}
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
int random_number ( void )
|
|
Packit |
47f805 |
{
|
|
Packit |
47f805 |
struct timeval t;
|
|
Packit |
47f805 |
unsigned long val;
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
gettimeofday ( &t, NULL );
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
val = t.tv_sec ^ t.tv_usec ^ rand();
|
|
Packit |
47f805 |
val ^= val >> 16;
|
|
Packit |
47f805 |
val ^= val >> 8;
|
|
Packit |
47f805 |
val ^= val >> 4;
|
|
Packit |
47f805 |
val ^= val >> 2;
|
|
Packit |
47f805 |
val ^= val >> 1;
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
return val & 1;
|
|
Packit |
47f805 |
}
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
long double prob ( int last, int total )
|
|
Packit |
47f805 |
{
|
|
Packit |
47f805 |
long double sum = 0.;
|
|
Packit |
47f805 |
long double tmp = 1.;
|
|
Packit |
47f805 |
int i;
|
|
Packit |
47f805 |
int j = total;
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
if ( 2*last == total )
|
|
Packit |
47f805 |
return 1.;
|
|
Packit |
47f805 |
if ( 2*last > total )
|
|
Packit |
47f805 |
last = total - last;
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
for ( i = 0; i <= last; i++ ) {
|
|
Packit |
47f805 |
sum += tmp;
|
|
Packit |
47f805 |
tmp = tmp * (total-i) / (1+i);
|
|
Packit |
47f805 |
while ( j > 0 && tmp > 1 )
|
|
Packit |
47f805 |
j--, sum *= 0.5, tmp *= 0.5;
|
|
Packit |
47f805 |
}
|
|
Packit |
47f805 |
while ( j > 0 )
|
|
Packit |
47f805 |
j--, sum *= 0.5;
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
return 2.*sum;
|
|
Packit |
47f805 |
}
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
void eval ( int right )
|
|
Packit |
47f805 |
{
|
|
Packit |
47f805 |
static int count = 0;
|
|
Packit |
47f805 |
static int okay = 0;
|
|
Packit |
47f805 |
long double val;
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
count ++;
|
|
Packit |
47f805 |
okay += right;
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
val = 1.L / prob ( okay, count );
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
fprintf (stderr, " %s %5u/%-5u ", right ? "OK" : "- " , okay, count );
|
|
Packit |
47f805 |
printnumber (val);
|
|
Packit |
47f805 |
if ( count > 1 )
|
|
Packit |
47f805 |
fprintf (stderr, " %4.2f bit", 0.01 * (int)(logdual(val) / (count-1) * 100.) );
|
|
Packit |
47f805 |
fprintf ( stderr, "\n" );
|
|
Packit |
47f805 |
}
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
typedef signed short sample_t;
|
|
Packit |
47f805 |
typedef sample_t mono_t [1];
|
|
Packit |
47f805 |
typedef sample_t stereo_t [2];
|
|
Packit |
47f805 |
typedef struct {
|
|
Packit |
47f805 |
unsigned long n;
|
|
Packit |
47f805 |
long double x;
|
|
Packit |
47f805 |
long double x2;
|
|
Packit |
47f805 |
long double y;
|
|
Packit |
47f805 |
long double y2;
|
|
Packit |
47f805 |
long double xy;
|
|
Packit |
47f805 |
} korr_t;
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
void analyze_stereo ( const stereo_t* p1, const stereo_t* p2, size_t len, korr_t* const k )
|
|
Packit |
47f805 |
{
|
|
Packit |
47f805 |
long double _x = 0, _x2 = 0, _y = 0, _y2 = 0, _xy = 0;
|
|
Packit |
47f805 |
double t1;
|
|
Packit |
47f805 |
double t2;
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
k -> n += 2*len;
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
for ( ; len--; p1++, p2++ ) {
|
|
Packit |
47f805 |
_x += (t1 = (*p1)[0]); _x2 += t1 * t1;
|
|
Packit |
47f805 |
_y += (t2 = (*p2)[0]); _y2 += t2 * t2;
|
|
Packit |
47f805 |
_xy += t1 * t2;
|
|
Packit |
47f805 |
_x += (t1 = (*p1)[1]); _x2 += t1 * t1;
|
|
Packit |
47f805 |
_y += (t2 = (*p2)[1]); _y2 += t2 * t2;
|
|
Packit |
47f805 |
_xy += t1 * t2;
|
|
Packit |
47f805 |
}
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
k -> x += _x ;
|
|
Packit |
47f805 |
k -> x2 += _x2;
|
|
Packit |
47f805 |
k -> y += _y ;
|
|
Packit |
47f805 |
k -> y2 += _y2;
|
|
Packit |
47f805 |
k -> xy += _xy;
|
|
Packit |
47f805 |
}
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
int sgn ( double x )
|
|
Packit |
47f805 |
{
|
|
Packit |
47f805 |
if ( x == 0 ) return 0;
|
|
Packit |
47f805 |
if ( x < 0 ) return -1;
|
|
Packit |
47f805 |
return +1;
|
|
Packit |
47f805 |
}
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
long double report ( const korr_t* const k )
|
|
Packit |
47f805 |
{
|
|
Packit |
47f805 |
long double r;
|
|
Packit |
47f805 |
long double sx;
|
|
Packit |
47f805 |
long double sy;
|
|
Packit |
47f805 |
long double x;
|
|
Packit |
47f805 |
long double y;
|
|
Packit |
47f805 |
long double b;
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
r = (k->x2*k->n - k->x*k->x) * (k->y2*k->n - k->y*k->y);
|
|
Packit |
47f805 |
r = r > 0.l ? (k->xy*k->n - k->x*k->y) / sqrt (r) : 1.l;
|
|
Packit |
47f805 |
sx = k->n > 1 ? sqrt ( (k->x2 - k->x*k->x/k->n) / (k->n - 1) ) : 0.l;
|
|
Packit |
47f805 |
sy = k->n > 1 ? sqrt ( (k->y2 - k->y*k->y/k->n) / (k->n - 1) ) : 0.l;
|
|
Packit |
47f805 |
x = k->n > 0 ? k->x/k->n : 0.l;
|
|
Packit |
47f805 |
y = k->n > 0 ? k->y/k->n : 0.l;
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
b = sx != 0 ? sy/sx * sgn(r) : 0.l;
|
|
Packit |
47f805 |
if (verbose)
|
|
Packit |
47f805 |
fprintf ( stderr, "r=%Lf sx=%Lf sy=%Lf x=%Lf y=%Lf b=%Lf\n", r, sx, sy, x, y, b );
|
|
Packit |
47f805 |
return b;
|
|
Packit |
47f805 |
}
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
/* Input: an unsigned short n.
|
|
Packit |
47f805 |
* Output: the swapped bytes of n if the arch is big-endian or n itself
|
|
Packit |
47f805 |
* if the arch is little-endian.
|
|
Packit |
47f805 |
* Comment: should be replaced latter with a better solution than this
|
|
Packit |
47f805 |
* home-brewed hack (rbrito). The name should be better also.
|
|
Packit |
47f805 |
*/
|
|
Packit |
47f805 |
inline unsigned short be16_le(unsigned short n)
|
|
Packit |
47f805 |
{
|
|
Packit |
47f805 |
#ifdef _WORDS_BIGENDIAN
|
|
Packit |
47f805 |
return (n << 8) | (n >> 8);
|
|
Packit |
47f805 |
#else
|
|
Packit |
47f805 |
return n;
|
|
Packit |
47f805 |
#endif
|
|
Packit |
47f805 |
}
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
int feed ( int fd, const stereo_t* p, int len )
|
|
Packit |
47f805 |
{
|
|
Packit |
47f805 |
int i;
|
|
Packit |
47f805 |
stereo_t tmp[30000]; /* An arbitrary size--to be changed latter */
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
if (len > sizeof(tmp)/sizeof(*tmp))
|
|
Packit |
47f805 |
len = sizeof(tmp)/sizeof(*tmp);
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
for (i = 0; i < len; i++) {
|
|
Packit |
47f805 |
tmp[i][0] = be16_le(p[i][0]);
|
|
Packit |
47f805 |
tmp[i][1] = be16_le(p[i][1]);
|
|
Packit |
47f805 |
}
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
write ( fd, tmp, sizeof(stereo_t) * len );
|
|
Packit |
47f805 |
return len;
|
|
Packit |
47f805 |
}
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
short round ( double f )
|
|
Packit |
47f805 |
{
|
|
Packit |
47f805 |
long x = (long) floor ( f + 0.5 );
|
|
Packit |
47f805 |
return x == (short)x ? (short)x : (short) ((x >> 31) ^ 0x7FFF);
|
|
Packit |
47f805 |
}
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
int feed2 ( int fd, const stereo_t* p1, const stereo_t* p2, int len )
|
|
Packit |
47f805 |
{
|
|
Packit |
47f805 |
stereo_t tmp [30000]; /* An arbitrary size, hope that no overruns occure */
|
|
Packit |
47f805 |
int i;
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
if (len > sizeof(tmp)/sizeof(*tmp))
|
|
Packit |
47f805 |
len = sizeof(tmp)/sizeof(*tmp);
|
|
Packit |
47f805 |
for ( i = 0; i < len; i++ ) {
|
|
Packit |
47f805 |
double f = cos ( M_PI/2*i/len );
|
|
Packit |
47f805 |
f *= f;
|
|
Packit |
47f805 |
tmp [i] [0] = be16_le(round ( p1 [i] [0] * f + p2 [i] [0] * (1. - f) ));
|
|
Packit |
47f805 |
tmp [i] [1] = be16_le(round ( p1 [i] [1] * f + p2 [i] [1] * (1. - f) ));
|
|
Packit |
47f805 |
}
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
write ( fd, tmp, sizeof(stereo_t) * len );
|
|
Packit |
47f805 |
return len;
|
|
Packit |
47f805 |
}
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
int feedfac ( int fd, const stereo_t* p1, const stereo_t* p2, int len, double fac1, double fac2 )
|
|
Packit |
47f805 |
{
|
|
Packit |
47f805 |
stereo_t tmp [30000]; /* An arbitrary size, hope that no overruns occure */
|
|
Packit |
47f805 |
int i;
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
if (len > sizeof(tmp)/sizeof(*tmp))
|
|
Packit |
47f805 |
len = sizeof(tmp)/sizeof(*tmp);
|
|
Packit |
47f805 |
for ( i = 0; i < len; i++ ) {
|
|
Packit |
47f805 |
tmp [i] [0] = be16_le(round ( p1 [i] [0] * fac1 + p2 [i] [0] * fac2 ));
|
|
Packit |
47f805 |
tmp [i] [1] = be16_le(round ( p1 [i] [1] * fac1 + p2 [i] [1] * fac2 ));
|
|
Packit |
47f805 |
}
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
write ( fd, tmp, sizeof(stereo_t) * len );
|
|
Packit |
47f805 |
return len;
|
|
Packit |
47f805 |
}
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
void setup ( int fdd, int samples, long freq )
|
|
Packit |
47f805 |
{
|
|
Packit |
47f805 |
int status, org, arg;
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
// Nach vorn verschoben
|
|
Packit |
47f805 |
if ( -1 == (status = ioctl (fdd, SOUND_PCM_SYNC, 0)) )
|
|
Packit |
47f805 |
perror ("SOUND_PCM_SYNC ioctl failed");
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
org = arg = 2;
|
|
Packit |
47f805 |
if ( -1 == (status = ioctl (fdd, SOUND_PCM_WRITE_CHANNELS, &arg)) )
|
|
Packit |
47f805 |
perror ("SOUND_PCM_WRITE_CHANNELS ioctl failed");
|
|
Packit |
47f805 |
if (arg != org)
|
|
Packit |
47f805 |
perror ("unable to set number of channels");
|
|
Packit |
47f805 |
fprintf (stderr, "%1u*", arg);
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
org = arg = AFMT_S16_LE;
|
|
Packit |
47f805 |
if ( -1 == ioctl (fdd, SNDCTL_DSP_SETFMT, &arg) )
|
|
Packit |
47f805 |
perror ("SNDCTL_DSP_SETFMT ioctl failed");
|
|
Packit |
47f805 |
if ((arg & org) == 0)
|
|
Packit |
47f805 |
perror ("unable to set data format");
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
org = arg = freq;
|
|
Packit |
47f805 |
if ( -1 == (status = ioctl (fdd, SNDCTL_DSP_SPEED, &arg)) )
|
|
Packit |
47f805 |
perror ("SNDCTL_DSP_SPEED ioctl failed");
|
|
Packit |
47f805 |
fprintf (stderr, "%5u Hz*%.3f sec\n", arg, (double)samples/arg );
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
}
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
void Message ( const char* s, size_t index, long freq, size_t start, size_t stop )
|
|
Packit |
47f805 |
{
|
|
Packit |
47f805 |
unsigned long norm_index = 100lu * index / freq;
|
|
Packit |
47f805 |
unsigned long norm_start = 100lu * start / freq;
|
|
Packit |
47f805 |
unsigned long norm_stop = 100lu * stop / freq;
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
fprintf ( stderr, "\rListening %s %2lu:%02lu.%02lu (%1lu:%02lu.%02lu...%1lu:%02lu.%02lu)%*.*s\rListening %s",
|
|
Packit |
47f805 |
s,
|
|
Packit |
47f805 |
norm_index / 6000, norm_index / 100 % 60, norm_index % 100,
|
|
Packit |
47f805 |
norm_start / 6000, norm_start / 100 % 60, norm_start % 100,
|
|
Packit |
47f805 |
norm_stop / 6000, norm_stop / 100 % 60, norm_stop % 100,
|
|
Packit |
47f805 |
36 - (int)strlen(s), 36 - (int)strlen(s), "",
|
|
Packit |
47f805 |
s );
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
fflush ( stderr );
|
|
Packit |
47f805 |
}
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
size_t calc_true_index ( size_t index, size_t start, size_t stop )
|
|
Packit |
47f805 |
{
|
|
Packit |
47f805 |
if ( start >= stop )
|
|
Packit |
47f805 |
return start;
|
|
Packit |
47f805 |
while ( index - start < DMA_SAMPLES )
|
|
Packit |
47f805 |
index += stop - start;
|
|
Packit |
47f805 |
return index - DMA_SAMPLES;
|
|
Packit |
47f805 |
}
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
void testing ( const stereo_t* A, const stereo_t* B, size_t len, long freq )
|
|
Packit |
47f805 |
{
|
|
Packit |
47f805 |
int c;
|
|
Packit |
47f805 |
int fd = open ( "/dev/dsp", O_WRONLY );
|
|
Packit |
47f805 |
int rnd = random_number (); /* Auswahl von X */
|
|
Packit |
47f805 |
int state = 0; /* derzeitiger F�ttungsmodus */
|
|
Packit |
47f805 |
float fac1 = 0.5;
|
|
Packit |
47f805 |
float fac2 = 0.5;
|
|
Packit |
47f805 |
size_t start = 0;
|
|
Packit |
47f805 |
size_t stop = len;
|
|
Packit |
47f805 |
size_t index = start; /* derzeitiger Offset auf den Audiostr�men */
|
|
Packit |
47f805 |
char message [80] = "A ";
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
setup ( fd, len, freq );
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
while ( 1 ) {
|
|
Packit |
47f805 |
c = sel ();
|
|
Packit |
47f805 |
if ( c == 27 )
|
|
Packit |
47f805 |
c = sel () + 0x100;
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
switch ( c ) {
|
|
Packit |
47f805 |
case 'A' :
|
|
Packit |
47f805 |
case 'a' :
|
|
Packit |
47f805 |
strcpy ( message, "A " );
|
|
Packit |
47f805 |
if ( state != 0 )
|
|
Packit |
47f805 |
state = 2;
|
|
Packit |
47f805 |
break;
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
case 0x100+'0' :
|
|
Packit |
47f805 |
case '0' :
|
|
Packit |
47f805 |
case 'B' :
|
|
Packit |
47f805 |
case 'b' :
|
|
Packit |
47f805 |
strcpy ( message, " B" );
|
|
Packit |
47f805 |
if ( state != 1 )
|
|
Packit |
47f805 |
state = 3;
|
|
Packit |
47f805 |
break;
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
case 'X' :
|
|
Packit |
47f805 |
case 'x' :
|
|
Packit |
47f805 |
strcpy ( message, " X " );
|
|
Packit |
47f805 |
if ( state != rnd )
|
|
Packit |
47f805 |
state = rnd + 2;
|
|
Packit |
47f805 |
break;
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
case 'm' :
|
|
Packit |
47f805 |
state = 8;
|
|
Packit |
47f805 |
break;
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
case 'M' :
|
|
Packit |
47f805 |
state = (state & 1) + 4;
|
|
Packit |
47f805 |
break;
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
case 'x'&0x1F:
|
|
Packit |
47f805 |
state = (state & 1) + 6;
|
|
Packit |
47f805 |
break;
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
case ' ':
|
|
Packit |
47f805 |
start = 0;
|
|
Packit |
47f805 |
stop = len;
|
|
Packit |
47f805 |
break;
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
case 'o' :
|
|
Packit |
47f805 |
start = calc_true_index ( index, start, stop);
|
|
Packit |
47f805 |
break;
|
|
Packit |
47f805 |
case 'p' :
|
|
Packit |
47f805 |
stop = calc_true_index ( index, start, stop);
|
|
Packit |
47f805 |
break;
|
|
Packit |
47f805 |
case 'h' :
|
|
Packit |
47f805 |
if ( start > freq/100 )
|
|
Packit |
47f805 |
start -= freq/100;
|
|
Packit |
47f805 |
else
|
|
Packit |
47f805 |
start = 0;
|
|
Packit |
47f805 |
index = start;
|
|
Packit |
47f805 |
continue;
|
|
Packit |
47f805 |
case 'j' :
|
|
Packit |
47f805 |
if ( start < stop-freq/100 )
|
|
Packit |
47f805 |
start += freq/100;
|
|
Packit |
47f805 |
else
|
|
Packit |
47f805 |
start = stop;
|
|
Packit |
47f805 |
index = start;
|
|
Packit |
47f805 |
continue;
|
|
Packit |
47f805 |
case 'k' :
|
|
Packit |
47f805 |
if ( stop > start+freq/100 )
|
|
Packit |
47f805 |
stop -= freq/100;
|
|
Packit |
47f805 |
else
|
|
Packit |
47f805 |
stop = start;
|
|
Packit |
47f805 |
continue;
|
|
Packit |
47f805 |
case 'l' :
|
|
Packit |
47f805 |
if ( stop < len-freq/100 )
|
|
Packit |
47f805 |
stop += freq/100;
|
|
Packit |
47f805 |
else
|
|
Packit |
47f805 |
stop = len;
|
|
Packit |
47f805 |
continue;
|
|
Packit |
47f805 |
case '\n':
|
|
Packit |
47f805 |
index = start;
|
|
Packit |
47f805 |
continue;
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
case 'D'+0x100:
|
|
Packit |
47f805 |
strcpy ( message, "Difference (+40 dB)" );
|
|
Packit |
47f805 |
state = 9;
|
|
Packit |
47f805 |
fac1 = -100.;
|
|
Packit |
47f805 |
fac2 = +100.;
|
|
Packit |
47f805 |
break;
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
case 'd'+0x100:
|
|
Packit |
47f805 |
strcpy ( message, "Difference (+30 dB)" );
|
|
Packit |
47f805 |
state = 9;
|
|
Packit |
47f805 |
fac1 = -32.;
|
|
Packit |
47f805 |
fac2 = +32.;
|
|
Packit |
47f805 |
break;
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
case 'D' & 0x1F :
|
|
Packit |
47f805 |
strcpy ( message, "Difference (+20 dB)" );
|
|
Packit |
47f805 |
state = 9;
|
|
Packit |
47f805 |
fac1 = -10.;
|
|
Packit |
47f805 |
fac2 = +10.;
|
|
Packit |
47f805 |
break;
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
case 'D' :
|
|
Packit |
47f805 |
strcpy ( message, "Difference (+10 dB)" );
|
|
Packit |
47f805 |
state = 9;
|
|
Packit |
47f805 |
fac1 = -3.;
|
|
Packit |
47f805 |
fac2 = +3.;
|
|
Packit |
47f805 |
break;
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
case 'd' :
|
|
Packit |
47f805 |
strcpy ( message, "Difference ( 0 dB)" );
|
|
Packit |
47f805 |
state = 9;
|
|
Packit |
47f805 |
fac1 = -1.;
|
|
Packit |
47f805 |
fac2 = +1.;
|
|
Packit |
47f805 |
break;
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
case 0x100+'1' :
|
|
Packit |
47f805 |
case 0x100+'2' :
|
|
Packit |
47f805 |
case 0x100+'3' :
|
|
Packit |
47f805 |
case 0x100+'4' :
|
|
Packit |
47f805 |
case 0x100+'5' :
|
|
Packit |
47f805 |
case 0x100+'6' :
|
|
Packit |
47f805 |
case 0x100+'7' :
|
|
Packit |
47f805 |
case 0x100+'8' :
|
|
Packit |
47f805 |
case 0x100+'9' :
|
|
Packit |
47f805 |
sprintf ( message, " B (Errors -%c dB)", (char)c );
|
|
Packit |
47f805 |
state = 9;
|
|
Packit |
47f805 |
fac2 = pow (10., -0.05*(c-0x100-'0') );
|
|
Packit |
47f805 |
fac1 = 1. - fac2;
|
|
Packit |
47f805 |
break;
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
case '1' :
|
|
Packit |
47f805 |
case '2' :
|
|
Packit |
47f805 |
case '3' :
|
|
Packit |
47f805 |
case '4' :
|
|
Packit |
47f805 |
case '5' :
|
|
Packit |
47f805 |
case '6' :
|
|
Packit |
47f805 |
case '7' :
|
|
Packit |
47f805 |
case '8' :
|
|
Packit |
47f805 |
case '9' :
|
|
Packit |
47f805 |
sprintf ( message, " B (Errors +%c dB)", c );
|
|
Packit |
47f805 |
state = 9;
|
|
Packit |
47f805 |
fac2 = pow (10., 0.05*(c-'0') );
|
|
Packit |
47f805 |
fac1 = 1. - fac2;
|
|
Packit |
47f805 |
break;
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
case 'A' & 0x1F:
|
|
Packit |
47f805 |
fprintf (stderr, " Vote for X:=A" );
|
|
Packit |
47f805 |
eval ( rnd == 0 );
|
|
Packit |
47f805 |
rnd = random_number ();
|
|
Packit |
47f805 |
if ( state == 6 && state == 7 )
|
|
Packit |
47f805 |
state = 6 + rnd;
|
|
Packit |
47f805 |
else if ( state != rnd )
|
|
Packit |
47f805 |
state = rnd + 2;
|
|
Packit |
47f805 |
strcpy ( message," X " );
|
|
Packit |
47f805 |
break;
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
case 'B' & 0x1F:
|
|
Packit |
47f805 |
fprintf (stderr, " Vote for X:=B" );
|
|
Packit |
47f805 |
eval ( rnd == 1 );
|
|
Packit |
47f805 |
rnd = random_number ();
|
|
Packit |
47f805 |
if ( state == 6 && state == 7 )
|
|
Packit |
47f805 |
state = 6 + rnd;
|
|
Packit |
47f805 |
else if ( state != rnd )
|
|
Packit |
47f805 |
state = rnd + 2;
|
|
Packit |
47f805 |
strcpy ( message," X " );
|
|
Packit |
47f805 |
break;
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
case -1:
|
|
Packit |
47f805 |
break;
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
default:
|
|
Packit |
47f805 |
fprintf (stderr, "\a" );
|
|
Packit |
47f805 |
break;
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
case 'Q':
|
|
Packit |
47f805 |
case 'q':
|
|
Packit |
47f805 |
fprintf ( stderr, "\n%-79.79s\r", "Quit program" );
|
|
Packit |
47f805 |
close (fd);
|
|
Packit |
47f805 |
fprintf ( stderr, "\n\n");
|
|
Packit |
47f805 |
return;
|
|
Packit |
47f805 |
}
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
switch (state) {
|
|
Packit |
47f805 |
case 0: /* A */
|
|
Packit |
47f805 |
if ( index + BF >= stop )
|
|
Packit |
47f805 |
index += feed (fd, A+index, stop-index );
|
|
Packit |
47f805 |
else
|
|
Packit |
47f805 |
index += feed (fd, A+index, BF );
|
|
Packit |
47f805 |
break;
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
case 1: /* B */
|
|
Packit |
47f805 |
if ( index + BF >= stop )
|
|
Packit |
47f805 |
index += feed (fd, B+index, stop-index );
|
|
Packit |
47f805 |
else
|
|
Packit |
47f805 |
index += feed (fd, B+index, BF );
|
|
Packit |
47f805 |
break;
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
case 2: /* B => A */
|
|
Packit |
47f805 |
if ( index + BF >= stop )
|
|
Packit |
47f805 |
index += feed2 (fd, B+index, A+index, stop-index );
|
|
Packit |
47f805 |
else
|
|
Packit |
47f805 |
index += feed2 (fd, B+index, A+index, BF );
|
|
Packit |
47f805 |
state = 0;
|
|
Packit |
47f805 |
break;
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
case 3: /* A => B */
|
|
Packit |
47f805 |
if ( index + BF >= stop )
|
|
Packit |
47f805 |
index += feed2 (fd, A+index, B+index, stop-index );
|
|
Packit |
47f805 |
else
|
|
Packit |
47f805 |
index += feed2 (fd, A+index, B+index, BF );
|
|
Packit |
47f805 |
state = 1;
|
|
Packit |
47f805 |
break;
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
case 4: /* A */
|
|
Packit |
47f805 |
strcpy ( message, "A " );
|
|
Packit |
47f805 |
if ( index + BF >= stop )
|
|
Packit |
47f805 |
index += feed (fd, A+index, stop-index ),
|
|
Packit |
47f805 |
state++;
|
|
Packit |
47f805 |
else
|
|
Packit |
47f805 |
index += feed (fd, A+index, BF );
|
|
Packit |
47f805 |
break;
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
case 5: /* B */
|
|
Packit |
47f805 |
strcpy ( message, " B" );
|
|
Packit |
47f805 |
if ( index + BF >= stop )
|
|
Packit |
47f805 |
index += feed (fd, B+index, stop-index ),
|
|
Packit |
47f805 |
state--;
|
|
Packit |
47f805 |
else
|
|
Packit |
47f805 |
index += feed (fd, B+index, BF );
|
|
Packit |
47f805 |
break;
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
case 6: /* X */
|
|
Packit |
47f805 |
strcpy ( message, " X " );
|
|
Packit |
47f805 |
if ( index + BF >= stop )
|
|
Packit |
47f805 |
index += feed (fd, (rnd ? B : A)+index, stop-index ),
|
|
Packit |
47f805 |
state++;
|
|
Packit |
47f805 |
else
|
|
Packit |
47f805 |
index += feed (fd, (rnd ? B : A)+index, BF );
|
|
Packit |
47f805 |
break;
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
case 7: /* !X */
|
|
Packit |
47f805 |
strcpy ( message, "!X " );
|
|
Packit |
47f805 |
if ( index + BF >= stop )
|
|
Packit |
47f805 |
index += feed (fd, (rnd ? A : B)+index, stop-index ),
|
|
Packit |
47f805 |
state--;
|
|
Packit |
47f805 |
else
|
|
Packit |
47f805 |
index += feed (fd, (rnd ? A : B)+index, BF );
|
|
Packit |
47f805 |
break;
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
case 8:
|
|
Packit |
47f805 |
if ( index + BF/2 >= stop )
|
|
Packit |
47f805 |
index += feed2 (fd, A+index, B+index, stop-index );
|
|
Packit |
47f805 |
else
|
|
Packit |
47f805 |
index += feed2 (fd, A+index, B+index, BF/2 );
|
|
Packit |
47f805 |
Message ( " B", index, freq, start, stop );
|
|
Packit |
47f805 |
if ( index + BF >= stop )
|
|
Packit |
47f805 |
index += feed (fd, B+index, stop-index );
|
|
Packit |
47f805 |
else
|
|
Packit |
47f805 |
index += feed (fd, B+index, BF );
|
|
Packit |
47f805 |
if ( index + BF/2 >= stop )
|
|
Packit |
47f805 |
index += feed2 (fd, B+index, A+index, stop-index );
|
|
Packit |
47f805 |
else
|
|
Packit |
47f805 |
index += feed2 (fd, B+index, A+index, BF/2 );
|
|
Packit |
47f805 |
Message ( "A ", index, freq, start, stop );
|
|
Packit |
47f805 |
if ( index + BF >= stop )
|
|
Packit |
47f805 |
index += feed (fd, A+index, stop-index );
|
|
Packit |
47f805 |
else
|
|
Packit |
47f805 |
index += feed (fd, A+index, BF );
|
|
Packit |
47f805 |
break;
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
case 9: /* Liko */
|
|
Packit |
47f805 |
if ( index + BF >= stop )
|
|
Packit |
47f805 |
index += feedfac (fd, A+index, B+index, stop-index, fac1, fac2 );
|
|
Packit |
47f805 |
else
|
|
Packit |
47f805 |
index += feedfac (fd, A+index, B+index, BF , fac1, fac2 );
|
|
Packit |
47f805 |
break;
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
default:
|
|
Packit |
47f805 |
assert (0);
|
|
Packit |
47f805 |
}
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
if (index >= stop)
|
|
Packit |
47f805 |
index = start;
|
|
Packit |
47f805 |
Message ( message, calc_true_index ( index, start, stop), freq, start, stop );
|
|
Packit |
47f805 |
}
|
|
Packit |
47f805 |
}
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
int has_ext ( const char* name, const char* ext )
|
|
Packit |
47f805 |
{
|
|
Packit |
47f805 |
if ( strlen (name) < strlen (ext) )
|
|
Packit |
47f805 |
return 0;
|
|
Packit |
47f805 |
name += strlen (name) - strlen (ext);
|
|
Packit |
47f805 |
return strcasecmp (name, ext) ? 0 : 1;
|
|
Packit |
47f805 |
}
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
typedef struct {
|
|
Packit |
47f805 |
const char* const extention;
|
|
Packit |
47f805 |
const char* const command;
|
|
Packit |
47f805 |
} decoder_t;
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
#define REDIR " 2> /dev/null"
|
|
Packit |
47f805 |
#define STDOUT "/dev/fd/1"
|
|
Packit |
47f805 |
#define PATH PATH_OF_EXTERNAL_TOOLS_FOR_UNCOMPRESSING
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
const decoder_t decoder [] = {
|
|
Packit |
47f805 |
{ ".mp1" , PATH"mpg123 -w - %s" REDIR }, // MPEG Layer I : www.iis.fhg.de, www.mpeg.org
|
|
Packit |
47f805 |
{ ".mp2" , PATH"mpg123 -w - %s" REDIR }, // MPEG Layer II : www.iis.fhg.de, www.uq.net.au/~zzmcheng, www.mpeg.org
|
|
Packit |
47f805 |
{ ".mp3" , PATH"mpg123 -w - %s" REDIR }, // MPEG Layer III : www.iis.fhg.de, www.mp3dev.org, www.mpeg.org
|
|
Packit |
47f805 |
{ ".mp3pro" , PATH"mpg123 -w - %s" REDIR }, // MPEG Layer III : www.iis.fhg.de, www.mp3dev.org, www.mpeg.org
|
|
Packit |
47f805 |
{ ".mpt" , PATH"mpg123 -w - %s" REDIR }, // MPEG Layer III : www.iis.fhg.de, www.mp3dev.org, www.mpeg.org
|
|
Packit |
47f805 |
{ ".mpp" , PATH"mppdec %s -" REDIR }, // MPEGplus : www.stud.uni-hannover.de/user/73884
|
|
Packit |
47f805 |
{ ".mpc" , PATH"mppdec %s -" REDIR }, // MPEGplus : www.stud.uni-hannover.de/user/73884
|
|
Packit |
47f805 |
{ ".mp+" , PATH"mppdec %s -" REDIR }, // MPEGplus : www.stud.uni-hannover.de/user/73884
|
|
Packit |
47f805 |
{ ".aac" , PATH"faad -t.wav -w %s" REDIR }, // Advanced Audio Coding: psytel.hypermart.net, www.aac-tech.com, sourceforge.net/projects/faac, www.aac-audio.com, www.mpeg.org
|
|
Packit |
47f805 |
{ "aac.lqt" , PATH"faad -t.wav -w %s" REDIR }, // Advanced Audio Coding: psytel.hypermart.net, www.aac-tech.com, sourceforge.net/projects/faac, www.aac-audio.com, www.mpeg.org
|
|
Packit |
47f805 |
{ ".ac3" , PATH"ac3dec %s" REDIR }, // Dolby AC3 : www.att.com
|
|
Packit |
47f805 |
{ "ac3.lqt" , PATH"ac3dec %s" REDIR }, // Dolby AC3 : www.att.com
|
|
Packit |
47f805 |
{ ".ogg" , PATH"ogg123 -d wav -o file:"STDOUT" %s" REDIR }, // Ogg Vorbis : www.xiph.org/ogg/vorbis/index.html
|
|
Packit |
47f805 |
{ ".pac" , PATH"lpac -x %s "STDOUT REDIR }, // Lossless predictive Audio Compression: www-ft.ee.tu-berlin.de/~liebchen/lpac.html (liebchen@ft.ee.tu-berlin.de)
|
|
Packit |
47f805 |
{ ".shn" , PATH"shorten -x < %s" REDIR }, // Shorten : shnutils.freeshell.org, www.softsound.com/Shorten.html (shnutils@freeshell.org, shorten@softsound.com)
|
|
Packit |
47f805 |
{ ".wav.gz" , PATH"gzip -d < %s | sox -twav - -twav -sw -"REDIR }, // gziped WAV
|
|
Packit |
47f805 |
{ ".wav.sz" , PATH"szip -d < %s | sox -twav - -twav -sw -"REDIR }, // sziped WAV
|
|
Packit |
47f805 |
{ ".wav.sz2", PATH"szip2 -d < %s | sox -twav - -twav -sw -"REDIR }, // sziped WAV
|
|
Packit |
47f805 |
{ ".raw" , PATH"sox -r44100 -sw -c2 -traw %s -twav -sw -"REDIR }, // raw files are treated as CD like audio
|
|
Packit |
47f805 |
{ ".cdr" , PATH"sox -r44100 -sw -c2 -traw %s -twav -sw -"REDIR }, // CD-DA files are treated as CD like audio, no preemphasis info available
|
|
Packit |
47f805 |
{ ".rm" , "echo %s '???'" REDIR }, // Real Audio : www.real.com
|
|
Packit |
47f805 |
{ ".epc" , "echo %s '???'" REDIR }, // ePAC : www.audioveda.com, www.lucent.com/ldr
|
|
Packit |
47f805 |
{ ".mov" , "echo %s '???'" REDIR }, // QDesign Music 2 : www.qdesign.com
|
|
Packit |
47f805 |
{ ".vqf" , "echo %s '???'" REDIR }, // TwinVQ : www.yamaha-xg.com/english/xg/SoundVQ, www.vqf.com, sound.splab.ecl.ntt.co.jp/twinvq-e
|
|
Packit |
47f805 |
{ ".wma" , "echo %s '???'" REDIR }, // Microsoft Media Audio: www.windowsmedia.com, www.microsoft.com/windows/windowsmedia
|
|
Packit |
47f805 |
{ ".flac" , PATH"flac -c -d %s" REDIR }, // Free Lossless Audio Coder: flac.sourceforge.net/
|
|
Packit |
47f805 |
{ ".fla" , PATH"flac -c -d %s" REDIR }, // Free Lossless Audio Coder: flac.sourceforge.net/
|
|
Packit |
47f805 |
{ ".ape" , "( "PATH"MAC %s _._.wav -d > /dev/null; cat _._.wav; rm _._.wav )" REDIR }, // Monkey's Audio Codec : www.monkeysaudio.com (email@monkeysaudio.com)
|
|
Packit |
47f805 |
{ ".rka" , "( "PATH"rkau %s _._.wav > /dev/null; cat _._.wav; rm _._.wav )" REDIR }, // RK Audio:
|
|
Packit |
47f805 |
{ ".rkau" , "( "PATH"rkau %s _._.wav > /dev/null; cat _._.wav; rm _._.wav )" REDIR }, // RK Audio:
|
|
Packit |
47f805 |
{ ".mod" , PATH"xmp -b16 -c -f44100 --stereo -o- %s | sox -r44100 -sw -c2 -traw - -twav -sw -"
|
|
Packit |
47f805 |
REDIR }, // Amiga's Music on Disk:
|
|
Packit |
47f805 |
{ "" , PATH"sox %s -twav -sw -" REDIR }, // Rest, may be sox can handle it
|
|
Packit |
47f805 |
};
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
#undef REDIR
|
|
Packit |
47f805 |
#undef STDOUT
|
|
Packit |
47f805 |
#undef PATH
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
int readwave ( stereo_t* buff, size_t maxlen, const char* name, size_t* len )
|
|
Packit |
47f805 |
{
|
|
Packit |
47f805 |
char* command = malloc (2*strlen(name) + 512);
|
|
Packit |
47f805 |
char* name_q = malloc (2*strlen(name) + 128);
|
|
Packit |
47f805 |
unsigned short header [22];
|
|
Packit |
47f805 |
FILE* fp;
|
|
Packit |
47f805 |
size_t i;
|
|
Packit |
47f805 |
size_t j;
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
// The *nice* shell quoting
|
|
Packit |
47f805 |
i = j = 0;
|
|
Packit |
47f805 |
if ( name[i] == '-' )
|
|
Packit |
47f805 |
name_q[j++] = '.',
|
|
Packit |
47f805 |
name_q[j++] = '/';
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
while (name[i]) {
|
|
Packit |
47f805 |
if ( !isalnum (name[i]) && name[i]!='-' && name[i]!='_' && name[i]!='.' )
|
|
Packit |
47f805 |
name_q[j++] = '\\';
|
|
Packit |
47f805 |
name_q[j++] = name[i++];
|
|
Packit |
47f805 |
}
|
|
Packit |
47f805 |
name_q[j] = '\0';
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
fprintf (stderr, "Reading %s", name );
|
|
Packit |
47f805 |
for ( i = 0; i < sizeof(decoder)/sizeof(*decoder); i++ )
|
|
Packit |
47f805 |
if ( has_ext (name, decoder[i].extention) ) {
|
|
Packit |
47f805 |
sprintf ( command, decoder[i].command, name_q );
|
|
Packit |
47f805 |
break;
|
|
Packit |
47f805 |
}
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
free (name_q);
|
|
Packit |
47f805 |
if ( (fp = popen (command, "r")) == NULL ) {
|
|
Packit |
47f805 |
fprintf (stderr, "Can't exec:\n%s\n", command );
|
|
Packit |
47f805 |
exit (1);
|
|
Packit |
47f805 |
}
|
|
Packit |
47f805 |
free (command);
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
fprintf (stderr, " ..." );
|
|
Packit |
47f805 |
fread ( header, sizeof(*header), sizeof(header)/sizeof(*header), fp );
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
switch (be16_le(header[11])) {
|
|
Packit |
47f805 |
case 2:
|
|
Packit |
47f805 |
*len = fread ( buff, sizeof(stereo_t), maxlen, fp );
|
|
Packit |
47f805 |
for (i = 0; i < *len; i ++) {
|
|
Packit |
47f805 |
buff[i][0] = be16_le(buff[i][0]);
|
|
Packit |
47f805 |
buff[i][1] = be16_le(buff[i][1]);
|
|
Packit |
47f805 |
}
|
|
Packit |
47f805 |
break;
|
|
Packit |
47f805 |
case 1:
|
|
Packit |
47f805 |
*len = fread ( buff, sizeof(sample_t), maxlen, fp );
|
|
Packit |
47f805 |
for ( i = *len; i-- > 0; )
|
|
Packit |
47f805 |
buff[i][0] = buff[i][1] = ((sample_t*)buff) [i];
|
|
Packit |
47f805 |
break;
|
|
Packit |
47f805 |
case 0:
|
|
Packit |
47f805 |
fprintf (stderr, "\b\b\b\b, Standard Open Source Bug detected, try murksaround ..." );
|
|
Packit |
47f805 |
*len = fread ( buff, sizeof(stereo_t), maxlen, fp );
|
|
Packit |
47f805 |
header[11] = 2;
|
|
Packit |
47f805 |
header[12] = 65534; /* use that of the other channel */
|
|
Packit |
47f805 |
break;
|
|
Packit |
47f805 |
default:
|
|
Packit |
47f805 |
fprintf (stderr, "Only 1 or 2 channels are supported, not %u\n", header[11] );
|
|
Packit |
47f805 |
pclose (fp);
|
|
Packit |
47f805 |
return -1;
|
|
Packit |
47f805 |
}
|
|
Packit |
47f805 |
pclose ( fp );
|
|
Packit |
47f805 |
fprintf (stderr, "\n" );
|
|
Packit |
47f805 |
return be16_le(header[12]) ? be16_le(header[12]) : 65534;
|
|
Packit |
47f805 |
}
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
double cross_analyze ( const stereo_t* p1, const stereo_t *p2, size_t len )
|
|
Packit |
47f805 |
{
|
|
Packit |
47f805 |
float P1 [MAX] [2];
|
|
Packit |
47f805 |
float P2 [MAX] [2];
|
|
Packit |
47f805 |
int i;
|
|
Packit |
47f805 |
int maxindex;
|
|
Packit |
47f805 |
double sum1;
|
|
Packit |
47f805 |
double sum2;
|
|
Packit |
47f805 |
double max;
|
|
Packit |
47f805 |
double y1;
|
|
Packit |
47f805 |
double y2;
|
|
Packit |
47f805 |
double y3;
|
|
Packit |
47f805 |
double yo;
|
|
Packit |
47f805 |
double xo;
|
|
Packit |
47f805 |
double tmp;
|
|
Packit |
47f805 |
double tmp1;
|
|
Packit |
47f805 |
double tmp2;
|
|
Packit |
47f805 |
int ret = 0;
|
|
Packit |
47f805 |
int cnt = 5;
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
// Calculating effective voltage
|
|
Packit |
47f805 |
sum1 = sum2 = 0.;
|
|
Packit |
47f805 |
for ( i = 0; i < len; i++ ) {
|
|
Packit |
47f805 |
sum1 += (double)p1[i][0] * p1[i][0];
|
|
Packit |
47f805 |
sum2 += (double)p2[i][0] * p2[i][0];
|
|
Packit |
47f805 |
}
|
|
Packit |
47f805 |
sum1 = sqrt ( sum1/len );
|
|
Packit |
47f805 |
sum2 = sqrt ( sum2/len );
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
// Searching beginning of signal (not stable for pathological signals)
|
|
Packit |
47f805 |
for ( i = 0; i < len; i++ )
|
|
Packit |
47f805 |
if ( abs (p1[i][0]) >= sum1 && abs (p2[i][0]) >= sum2 )
|
|
Packit |
47f805 |
break;
|
|
Packit |
47f805 |
p1 += i;
|
|
Packit |
47f805 |
p2 += i;
|
|
Packit |
47f805 |
len -= i;
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
if ( len <= MAX )
|
|
Packit |
47f805 |
return 0;
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
// Filling arrays for FFT
|
|
Packit |
47f805 |
do {
|
|
Packit |
47f805 |
sum1 = sum2 = 0.;
|
|
Packit |
47f805 |
for ( i = 0; i < MAX; i++ ) {
|
|
Packit |
47f805 |
#ifdef USEDIFF
|
|
Packit |
47f805 |
tmp1 = p1 [i][0] - p1 [i+1][0];
|
|
Packit |
47f805 |
tmp2 = p2 [i+ret][0] - p2 [i+ret+1][0];
|
|
Packit |
47f805 |
#else
|
|
Packit |
47f805 |
tmp1 = p1 [i][0];
|
|
Packit |
47f805 |
tmp2 = p2 [i+ret][0];
|
|
Packit |
47f805 |
#endif
|
|
Packit |
47f805 |
sum1 += tmp1*tmp1;
|
|
Packit |
47f805 |
sum2 += tmp2*tmp2;
|
|
Packit |
47f805 |
P1 [i][0] = tmp1;
|
|
Packit |
47f805 |
P2 [i][0] = tmp2;
|
|
Packit |
47f805 |
P1 [i][1] = 0.;
|
|
Packit |
47f805 |
P2 [i][1] = 0.;
|
|
Packit |
47f805 |
}
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
fft (P1, MAX);
|
|
Packit |
47f805 |
fft (P2, MAX);
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
for ( i = 0; i < MAX; i++ ) {
|
|
Packit |
47f805 |
double a0 = P1 [i][0];
|
|
Packit |
47f805 |
double a1 = P1 [i][1];
|
|
Packit |
47f805 |
double b0 = P2 [(MAX-i)&(MAX-1)][0];
|
|
Packit |
47f805 |
double b1 = P2 [(MAX-i)&(MAX-1)][1];
|
|
Packit |
47f805 |
P1 [i][0] = a0*b0 - a1*b1;
|
|
Packit |
47f805 |
P1 [i][1] = a0*b1 + a1*b0;
|
|
Packit |
47f805 |
}
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
fft (P1, MAX);
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
max = P1 [maxindex = 0][0];
|
|
Packit |
47f805 |
for ( i = 1; i < MAX; i++ )
|
|
Packit |
47f805 |
if ( P1[i][0] > max )
|
|
Packit |
47f805 |
max = P1 [maxindex = i][0];
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
y2 = P1 [ maxindex ][0];
|
|
Packit |
47f805 |
y1 = P1 [(maxindex-1)&(MAX-1)][0] - y2;
|
|
Packit |
47f805 |
y3 = P1 [(maxindex+1)&(MAX-1)][0] - y2;
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
xo = 0.5 * (y1-y3) / (y1+y3);
|
|
Packit |
47f805 |
yo = 0.5 * ( (y1+y3)*xo + (y3-y1) ) * xo;
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
if (maxindex > MAX/2 )
|
|
Packit |
47f805 |
maxindex -= MAX;
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
ret += maxindex;
|
|
Packit |
47f805 |
tmp = 100./MAX/sqrt(sum1*sum2);
|
|
Packit |
47f805 |
if (verbose)
|
|
Packit |
47f805 |
printf ( "[%5d]%8.4f [%5d]%8.4f [%5d]%8.4f [%10.4f]%8.4f\n",
|
|
Packit |
47f805 |
ret- 1, (y1+y2)*tmp,
|
|
Packit |
47f805 |
ret , y2 *tmp,
|
|
Packit |
47f805 |
ret+ 1, (y3+y2)*tmp,
|
|
Packit |
47f805 |
ret+xo, (yo+y2)*tmp );
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
} while ( maxindex && cnt-- );
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
return ret + xo;
|
|
Packit |
47f805 |
}
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
short to_short ( int x )
|
|
Packit |
47f805 |
{
|
|
Packit |
47f805 |
return x == (short)x ? (short)x : (short) ((x >> 31) ^ 0x7FFF);
|
|
Packit |
47f805 |
}
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
void DC_cancel ( stereo_t* p, size_t len )
|
|
Packit |
47f805 |
{
|
|
Packit |
47f805 |
double sum1 = 0;
|
|
Packit |
47f805 |
double sum2 = 0;
|
|
Packit |
47f805 |
size_t i;
|
|
Packit |
47f805 |
int diff1;
|
|
Packit |
47f805 |
int diff2;
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
for (i = 0; i < len; i++ ) {
|
|
Packit |
47f805 |
sum1 += p[i][0];
|
|
Packit |
47f805 |
sum2 += p[i][1];
|
|
Packit |
47f805 |
}
|
|
Packit |
47f805 |
if ( fabs(sum1) < len && fabs(sum2) < len )
|
|
Packit |
47f805 |
return;
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
diff1 = round ( sum1 / len );
|
|
Packit |
47f805 |
diff2 = round ( sum2 / len );
|
|
Packit |
47f805 |
if (verbose)
|
|
Packit |
47f805 |
fprintf (stderr, "Removing DC (left=%d, right=%d)\n", diff1, diff2 );
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
for (i = 0; i < len; i++ ) {
|
|
Packit |
47f805 |
p[i][0] = to_short ( p[i][0] - diff1);
|
|
Packit |
47f805 |
p[i][1] = to_short ( p[i][1] - diff2);
|
|
Packit |
47f805 |
}
|
|
Packit |
47f805 |
}
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
void multiply ( char c, stereo_t* p, size_t len, double fact )
|
|
Packit |
47f805 |
{
|
|
Packit |
47f805 |
size_t i;
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
if ( fact == 1. )
|
|
Packit |
47f805 |
return;
|
|
Packit |
47f805 |
if (verbose)
|
|
Packit |
47f805 |
fprintf (stderr, "Multiplying %c by %7.5f\n", c, fact );
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
for (i = 0; i < len; i++ ) {
|
|
Packit |
47f805 |
p[i][0] = to_short ( p[i][0] * fact );
|
|
Packit |
47f805 |
p[i][1] = to_short ( p[i][1] * fact );
|
|
Packit |
47f805 |
}
|
|
Packit |
47f805 |
}
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
int maximum ( stereo_t* p, size_t len )
|
|
Packit |
47f805 |
{
|
|
Packit |
47f805 |
int max = 0;
|
|
Packit |
47f805 |
size_t i;
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
for (i = 0; i < len; i++ ) {
|
|
Packit |
47f805 |
if (abs(p[i][0]) > max) max = abs(p[i][0]);
|
|
Packit |
47f805 |
if (abs(p[i][1]) > max) max = abs(p[i][1]);
|
|
Packit |
47f805 |
}
|
|
Packit |
47f805 |
return max;
|
|
Packit |
47f805 |
}
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
void usage ( void )
|
|
Packit |
47f805 |
{
|
|
Packit |
47f805 |
fprintf ( stderr,
|
|
Packit |
47f805 |
"usage: abx [-v] File_A File_B\n"
|
|
Packit |
47f805 |
"\n"
|
|
Packit |
47f805 |
"File_A and File_B loaded and played. File_A should be the better/reference\n"
|
|
Packit |
47f805 |
"file, File_B the other. You can press the following keys:\n"
|
|
Packit |
47f805 |
"\n"
|
|
Packit |
47f805 |
" a/A: Listen to File A\n"
|
|
Packit |
47f805 |
" b/B: Listen to File B\n"
|
|
Packit |
47f805 |
" x/X: Listen to the randomly selected File X, which is A or B\n"
|
|
Packit |
47f805 |
" Ctrl-A: You vote for X=A\n"
|
|
Packit |
47f805 |
" Ctrl-B: You vote for X=B\n"
|
|
Packit |
47f805 |
" m: Alternating playing A and B. Fast switching\n"
|
|
Packit |
47f805 |
" M: Alternating playing A and B. Slow switching\n"
|
|
Packit |
47f805 |
" d/D/Ctrl-D/Alt-d/Alt-D:\n"
|
|
Packit |
47f805 |
" Listen to the difference A-B (+0 dB...+40 dB)\n"
|
|
Packit |
47f805 |
" o/p: Chunk select\n"
|
|
Packit |
47f805 |
" hjkl: Chunk fine adjust (hj: start, kl: stop)\n"
|
|
Packit |
47f805 |
" Space: Chunk deselect\n"
|
|
Packit |
47f805 |
" 0...9: Listen to B, but difference A-B is amplified by 0-9 dB\n"
|
|
Packit |
47f805 |
" Q: Quit the program\n"
|
|
Packit |
47f805 |
"\n"
|
|
Packit |
47f805 |
);
|
|
Packit |
47f805 |
}
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
int main ( int argc, char** argv )
|
|
Packit |
47f805 |
{
|
|
Packit |
47f805 |
stereo_t* _A = calloc ( MAX_LEN, sizeof(stereo_t) );
|
|
Packit |
47f805 |
stereo_t* _B = calloc ( MAX_LEN, sizeof(stereo_t) );
|
|
Packit |
47f805 |
stereo_t* A = _A;
|
|
Packit |
47f805 |
stereo_t* B = _B;
|
|
Packit |
47f805 |
size_t len_A;
|
|
Packit |
47f805 |
size_t len_B;
|
|
Packit |
47f805 |
size_t len;
|
|
Packit |
47f805 |
int max_A;
|
|
Packit |
47f805 |
int max_B;
|
|
Packit |
47f805 |
int max;
|
|
Packit |
47f805 |
long freq1;
|
|
Packit |
47f805 |
long freq2;
|
|
Packit |
47f805 |
int shift;
|
|
Packit |
47f805 |
double fshift;
|
|
Packit |
47f805 |
double ampl;
|
|
Packit |
47f805 |
int ampl_X;
|
|
Packit |
47f805 |
korr_t k;
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
if (argc > 1 && 0 == strcmp (argv[1], "-v") ) {
|
|
Packit |
47f805 |
verbose = 1;
|
|
Packit |
47f805 |
argc--;
|
|
Packit |
47f805 |
argv++;
|
|
Packit |
47f805 |
}
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
switch ( argc ) {
|
|
Packit |
47f805 |
case 0:
|
|
Packit |
47f805 |
case 1:
|
|
Packit |
47f805 |
case 2:
|
|
Packit |
47f805 |
default:
|
|
Packit |
47f805 |
usage ();
|
|
Packit |
47f805 |
return 1;
|
|
Packit |
47f805 |
case 3:
|
|
Packit |
47f805 |
usage();
|
|
Packit |
47f805 |
break;
|
|
Packit |
47f805 |
}
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
freq1 = readwave ( A, MAX_LEN, argv[1], &len_A );
|
|
Packit |
47f805 |
DC_cancel ( A, len_A );
|
|
Packit |
47f805 |
freq2 = readwave ( B, MAX_LEN, argv[2], &len_B );
|
|
Packit |
47f805 |
DC_cancel ( B, len_B );
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
if ( freq1 == 65534 && freq2 != 65534 )
|
|
Packit |
47f805 |
freq1 = freq2;
|
|
Packit |
47f805 |
else if ( freq2 == 65534 && freq1 != 65534 )
|
|
Packit |
47f805 |
freq2 = freq1;
|
|
Packit |
47f805 |
else if ( freq1 == 65534 && freq2 == 65534 )
|
|
Packit |
47f805 |
freq1 = freq2 = 44100;
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
if ( freq1 != freq2 ) {
|
|
Packit |
47f805 |
fprintf ( stderr, "Different sample frequencies currently not supported\n");
|
|
Packit |
47f805 |
fprintf ( stderr, "A: %ld, B: %ld\n", freq1, freq2 );
|
|
Packit |
47f805 |
return 2;
|
|
Packit |
47f805 |
}
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
len = len_A < len_B ? len_A : len_B;
|
|
Packit |
47f805 |
fshift = cross_analyze ( A, B, len );
|
|
Packit |
47f805 |
shift = floor ( fshift + 0.5 );
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
if ( verbose ) {
|
|
Packit |
47f805 |
fprintf ( stderr, "Delay Ch1 is %.4f samples\n", fshift );
|
|
Packit |
47f805 |
fprintf ( stderr, "Delay Ch2 is %.4f samples\n",
|
|
Packit |
47f805 |
cross_analyze ( (stereo_t*)(((sample_t*)A)+1), (stereo_t*)(((sample_t*)B)+1), len ) );
|
|
Packit |
47f805 |
}
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
if (shift > 0) {
|
|
Packit |
47f805 |
if (verbose)
|
|
Packit |
47f805 |
fprintf ( stderr, "Delaying A by %d samples\n", +shift);
|
|
Packit |
47f805 |
B += shift;
|
|
Packit |
47f805 |
len_B -= shift;
|
|
Packit |
47f805 |
}
|
|
Packit |
47f805 |
if (shift < 0) {
|
|
Packit |
47f805 |
if (verbose)
|
|
Packit |
47f805 |
fprintf ( stderr, "Delaying B by %d samples\n", -shift);
|
|
Packit |
47f805 |
A -= shift;
|
|
Packit |
47f805 |
len_A += shift;
|
|
Packit |
47f805 |
}
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
len = len_A < len_B ? len_A : len_B;
|
|
Packit |
47f805 |
memset ( &k, 0, sizeof(k) );
|
|
Packit |
47f805 |
analyze_stereo ( A, B, len, &k );
|
|
Packit |
47f805 |
ampl = report (&k);
|
|
Packit |
47f805 |
max_A = maximum ( A, len );
|
|
Packit |
47f805 |
max_B = maximum ( B, len );
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
if ( ampl <= 0.98855 ) { /* < -0.05 dB */
|
|
Packit |
47f805 |
max = max_A*ampl < max_B ? max_B : max_A*ampl;
|
|
Packit |
47f805 |
ampl_X = (int)(29203 / max);
|
|
Packit |
47f805 |
if ( ampl_X < 2 ) ampl_X = 1;
|
|
Packit |
47f805 |
multiply ( 'A', A, len, ampl*ampl_X );
|
|
Packit |
47f805 |
multiply ( 'B', B, len, ampl_X );
|
|
Packit |
47f805 |
} else if ( ampl >= 1.01158 ) { /* > +0.05 dB */
|
|
Packit |
47f805 |
max = max_A < max_B/ampl ? max_B/ampl : max_A;
|
|
Packit |
47f805 |
ampl_X = (int)(29203 / max);
|
|
Packit |
47f805 |
if ( ampl_X < 2 ) ampl_X = 1;
|
|
Packit |
47f805 |
multiply ( 'A', A, len, ampl_X );
|
|
Packit |
47f805 |
multiply ( 'B', B, len, 1./ampl*ampl_X );
|
|
Packit |
47f805 |
} else {
|
|
Packit |
47f805 |
max = max_A < max_B ? max_B : max_A;
|
|
Packit |
47f805 |
ampl_X = (int)(29203 / max);
|
|
Packit |
47f805 |
if ( ampl_X < 2 ) ampl_X = 1;
|
|
Packit |
47f805 |
multiply ( 'A', A, len, ampl_X );
|
|
Packit |
47f805 |
multiply ( 'B', B, len, ampl_X );
|
|
Packit |
47f805 |
}
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
set ();
|
|
Packit |
47f805 |
Set_Realtime ();
|
|
Packit |
47f805 |
testing ( A, B, len, freq1 );
|
|
Packit |
47f805 |
reset ();
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
free (_A);
|
|
Packit |
47f805 |
free (_B);
|
|
Packit |
47f805 |
return 0;
|
|
Packit |
47f805 |
}
|
|
Packit |
47f805 |
|
|
Packit |
47f805 |
/* end of abx.c */
|