abx.c 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323
  1. /*
  2. * Usage: abx original_file test_file
  3. *
  4. * Ask you as long as the probability is below the given percentage that
  5. * you recognize differences
  6. *
  7. * Example: abx music.wav music.mp3
  8. * abx music.wav music.mp3 --help
  9. *
  10. * Note: several 'decoding' utilites must be on the 'right' place
  11. *
  12. * Bugs:
  13. * fix path of decoding utilities
  14. * only 16 bit support
  15. * only support of the same sample frequency
  16. * no exact WAV file header analysis
  17. * no mouse or joystick support
  18. * don't uses functionality of ath.c
  19. * only 2 files are comparable
  20. * worse user interface
  21. * quick & dirty hack
  22. * wastes memory
  23. * compile time warnings
  24. * buffer overruns possible
  25. * no dithering if recalcs are necessary
  26. * correlation only done with one channel (2 channels, sum, what is better?)
  27. * lowpass+highpass filtering (300 Hz+2*5 kHz) before delay+amplitude corr
  28. * cross fade at start/stop
  29. * non portable keyboard
  30. * fade out on quit, fade in on start
  31. * level/delay ajustment should be switchable
  32. * pause key missing
  33. * problems with digital silence files (division by 0)
  34. * Gr��e cross corr fenster 2^16...18
  35. * Stellensuche, ab 0*len oder 0.1*len oder 0.25*len, nach Effektiv oder Spitzenwert
  36. * Absturz bei LPAC feeding, warum?
  37. * Als 'B' beim Ratespiel sollte auch '0'...'9' verwendbar sein
  38. * Oder mit einem Filter 300 Hz...3 kHz vorher filtern?
  39. * Multiple encoded differenziertes Signal
  40. * Amplitudenanpassung schaltbar machen?
  41. * Direkt auf der Kommandozeile kodieren:
  42. * abx "test.wav" "!lame -b128 test.wav -"
  43. */
  44. // If the program should increase it priority while playing define USE_NICE.
  45. // Program must be installed SUID root. Decompressing phase is using NORMAL priority
  46. #define USE_NICE
  47. // Not only increase priority but change to relatime scheduling. Program must be installed SUID root
  48. #define USE_REALTIME
  49. // Path of the programs: mpg123, mppdec, faad, ac3dec, ogg123, lpac, shorten, MAC, flac
  50. //#define PATH_OF_EXTERNAL_TOOLS_FOR_UNCOMPRESSING "/usr/local/bin/"
  51. #define PATH_OF_EXTERNAL_TOOLS_FOR_UNCOMPRESSING ""
  52. #if defined HAVE_CONFIG_H
  53. # include <config.h>
  54. #endif
  55. #include <assert.h>
  56. #include <ctype.h>
  57. #include <fcntl.h>
  58. #include <limits.h>
  59. #include <math.h>
  60. #include <memory.h>
  61. #include <signal.h>
  62. #include <stdio.h>
  63. #include <stdlib.h>
  64. #include <string.h>
  65. #include <termios.h>
  66. #include <time.h>
  67. #include <unistd.h>
  68. #include <sys/ioctl.h>
  69. #include <sys/mman.h>
  70. #include <sys/stat.h>
  71. #include <sys/time.h>
  72. #include <sys/types.h>
  73. #define MAX (1<<17)
  74. #if defined HAVE_SYS_SOUNDCARD_H
  75. # include <sys/soundcard.h>
  76. #elif defined HAVE_LINUX_SOUNDCARD_H
  77. # include <linux/soundcard.h>
  78. #else
  79. # include <linux/soundcard.h> /* stand alone compilable for my tests */
  80. #endif
  81. #if defined USE_NICE
  82. # include <sys/resource.h>
  83. #endif
  84. #if defined USE_REALTIME
  85. # include <sched.h>
  86. #endif
  87. #define BF ((freq)/25)
  88. #define MAX_LEN (210 * 44100)
  89. #define DMA_SAMPLES 512 /* My Linux driver uses a DMA buffer of 65536*16 bit, which is 32768 samples in 16 bit stereo mode */
  90. void Set_Realtime ( void )
  91. {
  92. #if defined USE_REALTIME
  93. struct sched_param sp;
  94. int ret;
  95. memset ( &sp, 0, sizeof(sp) );
  96. seteuid ( 0 );
  97. sp.sched_priority = sched_get_priority_min ( SCHED_FIFO );
  98. ret = sched_setscheduler ( 0, SCHED_RR, &sp );
  99. seteuid ( getuid() );
  100. #endif
  101. #if defined USE_NICE
  102. seteuid ( 0 );
  103. setpriority ( PRIO_PROCESS, getpid(), -20 );
  104. seteuid ( getuid() );
  105. #endif
  106. }
  107. int verbose = 0;
  108. static struct termios stored_settings;
  109. void reset ( void )
  110. {
  111. tcsetattr ( 0, TCSANOW, &stored_settings );
  112. }
  113. void set ( void )
  114. {
  115. struct termios new_settings;
  116. tcgetattr ( 0, &stored_settings );
  117. new_settings = stored_settings;
  118. new_settings.c_lflag &= ~ECHO;
  119. /* Disable canonical mode, and set buffer size to 1 byte */
  120. new_settings.c_lflag &= ~ICANON;
  121. new_settings.c_cc[VTIME] = 0;
  122. new_settings.c_cc[VMIN] = 1;
  123. tcsetattr(0,TCSANOW,&new_settings);
  124. return;
  125. }
  126. int sel ( void )
  127. {
  128. struct timeval t;
  129. fd_set fd [1];
  130. int ret;
  131. unsigned char c;
  132. FD_SET (0, fd);
  133. t.tv_sec = 0;
  134. t.tv_usec = 0;
  135. ret = select ( 1, fd, NULL, NULL, &t );
  136. switch ( ret ) {
  137. case 0:
  138. return -1;
  139. case 1:
  140. ret = read (0, &c, 1);
  141. return ret == 1 ? c : -1;
  142. default:
  143. return -2;
  144. }
  145. }
  146. #define FFT_ERR_OK 0 // no error
  147. #define FFT_ERR_LD 1 // len is not a power of 2
  148. #define FFT_ERR_MAX 2 // len too large
  149. typedef float f_t;
  150. typedef f_t compl [2];
  151. compl root [MAX >> 1]; // Sinus-/Kosinustabelle
  152. size_t shuffle [MAX >> 1] [2]; // Shuffle-Tabelle
  153. size_t shuffle_len;
  154. // Bitinversion
  155. size_t swap ( size_t number, int bits )
  156. {
  157. size_t ret;
  158. for ( ret = 0; bits--; number >>= 1 ) {
  159. ret = ret + ret + (number & 1);
  160. }
  161. return ret;
  162. }
  163. // Bestimmen des Logarithmus dualis
  164. int ld ( size_t number )
  165. {
  166. size_t i;
  167. for ( i = 0; i < sizeof(size_t)*CHAR_BIT; i++ )
  168. if ( ((size_t)1 << i) == number )
  169. return i;
  170. return -1;
  171. }
  172. // Die eigentliche FFT
  173. int fft ( compl* fn, const size_t newlen )
  174. {
  175. static size_t len = 0;
  176. static int bits = 0;
  177. size_t i;
  178. size_t j;
  179. size_t k;
  180. size_t p;
  181. /* Tabellen initialisieren */
  182. if ( newlen != len ) {
  183. len = newlen;
  184. if ( (bits=ld(len)) == -1 )
  185. return FFT_ERR_LD;
  186. for ( i = 0; i < len; i++ ) {
  187. j = swap ( i, bits );
  188. if ( i < j ) {
  189. shuffle [shuffle_len] [0] = i;
  190. shuffle [shuffle_len] [1] = j;
  191. shuffle_len++;
  192. }
  193. }
  194. for ( i = 0; i < (len>>1); i++ ) {
  195. double x = (double) swap ( i+i, bits ) * 2*M_PI/len;
  196. root [i] [0] = cos (x);
  197. root [i] [1] = sin (x);
  198. }
  199. }
  200. /* Eigentliche Transformation */
  201. p = len >> 1;
  202. do {
  203. f_t* bp = (f_t*) root;
  204. f_t* si = (f_t*) fn;
  205. f_t* di = (f_t*) fn+p+p;
  206. do {
  207. k = p;
  208. do {
  209. f_t mulr = bp[0]*di[0] - bp[1]*di[1];
  210. f_t muli = bp[1]*di[0] + bp[0]*di[1];
  211. di[0] = si[0] - mulr;
  212. di[1] = si[1] - muli;
  213. si[0] += mulr;
  214. si[1] += muli;
  215. si += 2, di += 2;
  216. } while ( --k );
  217. si += p+p, di += p+p, bp += 2;
  218. } while ( si < &fn[len][0] );
  219. } while (p >>= 1);
  220. /* Bitinversion */
  221. for ( k = 0; k < shuffle_len; k++ ) {
  222. f_t tmp;
  223. i = shuffle [k] [0];
  224. j = shuffle [k] [1];
  225. tmp = fn [i][0]; fn [i][0] = fn [j][0]; fn [j][0] = tmp;
  226. tmp = fn [i][1]; fn [i][1] = fn [j][1]; fn [j][1] = tmp;
  227. }
  228. return FFT_ERR_OK;
  229. }
  230. void printnumber ( long double x )
  231. {
  232. unsigned exp = 0;
  233. if ( x < 9.999995 ) fprintf ( stderr, "%7.5f", (double)x );
  234. else if ( x < 99.99995 ) fprintf ( stderr, "%7.4f", (double)x );
  235. else if ( x < 999.9995 ) fprintf ( stderr, "%7.3f", (double)x );
  236. else if ( x < 9999.995 ) fprintf ( stderr, "%7.2f", (double)x );
  237. else if ( x < 99999.95 ) fprintf ( stderr, "%7.1f", (double)x );
  238. else if ( x < 999999.5 ) fprintf ( stderr, "%6.0f.", (double)x );
  239. else if ( x < 9999999.5 ) fprintf ( stderr, "%7.0f", (double)x );
  240. else if ( x < 9.9995e9 ) {
  241. while ( x >= 9.9995 ) exp++ , x /= 10;
  242. fprintf ( stderr, "%5.3fe%01u", (double)x, exp );
  243. } else if ( x < 9.995e99 ) {
  244. while ( x >= 9.5e6 ) exp+=6 , x /= 1.e6;
  245. while ( x >= 9.995 ) exp++ , x /= 10;
  246. fprintf ( stderr, "%4.2fe%02u", (double)x, exp );
  247. } else if ( x < 9.95e999L ) {
  248. while ( x >= 9.5e18 ) exp+=18, x /= 1.e18;
  249. while ( x >= 9.95 ) exp++ , x /= 10;
  250. fprintf ( stderr, "%3.1fe%03u", (double)x, exp );
  251. } else {
  252. while ( x >= 9.5e48 ) exp+=48, x /= 1.e48;
  253. while ( x >= 9.5 ) exp++ , x /= 10;
  254. fprintf ( stderr, "%1.0f.e%04u", (double)x, exp );
  255. }
  256. }
  257. double logdual ( long double x )
  258. {
  259. unsigned exp = 0;
  260. while ( x >= 18446744073709551616. )
  261. x /= 18446744073709551616., exp += 64;
  262. while ( x >= 256. )
  263. x /= 256., exp += 8;
  264. while ( x >= 2. )
  265. x /= 2., exp += 1;
  266. return exp + log (x)/log(2);
  267. }
  268. int random_number ( void )
  269. {
  270. struct timeval t;
  271. unsigned long val;
  272. gettimeofday ( &t, NULL );
  273. val = t.tv_sec ^ t.tv_usec ^ rand();
  274. val ^= val >> 16;
  275. val ^= val >> 8;
  276. val ^= val >> 4;
  277. val ^= val >> 2;
  278. val ^= val >> 1;
  279. return val & 1;
  280. }
  281. long double prob ( int last, int total )
  282. {
  283. long double sum = 0.;
  284. long double tmp = 1.;
  285. int i;
  286. int j = total;
  287. if ( 2*last == total )
  288. return 1.;
  289. if ( 2*last > total )
  290. last = total - last;
  291. for ( i = 0; i <= last; i++ ) {
  292. sum += tmp;
  293. tmp = tmp * (total-i) / (1+i);
  294. while ( j > 0 && tmp > 1 )
  295. j--, sum *= 0.5, tmp *= 0.5;
  296. }
  297. while ( j > 0 )
  298. j--, sum *= 0.5;
  299. return 2.*sum;
  300. }
  301. void eval ( int right )
  302. {
  303. static int count = 0;
  304. static int okay = 0;
  305. long double val;
  306. count ++;
  307. okay += right;
  308. val = 1.L / prob ( okay, count );
  309. fprintf (stderr, " %s %5u/%-5u ", right ? "OK" : "- " , okay, count );
  310. printnumber (val);
  311. if ( count > 1 )
  312. fprintf (stderr, " %4.2f bit", 0.01 * (int)(logdual(val) / (count-1) * 100.) );
  313. fprintf ( stderr, "\n" );
  314. }
  315. typedef signed short sample_t;
  316. typedef sample_t mono_t [1];
  317. typedef sample_t stereo_t [2];
  318. typedef struct {
  319. unsigned long n;
  320. long double x;
  321. long double x2;
  322. long double y;
  323. long double y2;
  324. long double xy;
  325. } korr_t;
  326. void analyze_stereo ( const stereo_t* p1, const stereo_t* p2, size_t len, korr_t* const k )
  327. {
  328. long double _x = 0, _x2 = 0, _y = 0, _y2 = 0, _xy = 0;
  329. double t1;
  330. double t2;
  331. k -> n += 2*len;
  332. for ( ; len--; p1++, p2++ ) {
  333. _x += (t1 = (*p1)[0]); _x2 += t1 * t1;
  334. _y += (t2 = (*p2)[0]); _y2 += t2 * t2;
  335. _xy += t1 * t2;
  336. _x += (t1 = (*p1)[1]); _x2 += t1 * t1;
  337. _y += (t2 = (*p2)[1]); _y2 += t2 * t2;
  338. _xy += t1 * t2;
  339. }
  340. k -> x += _x ;
  341. k -> x2 += _x2;
  342. k -> y += _y ;
  343. k -> y2 += _y2;
  344. k -> xy += _xy;
  345. }
  346. int sgn ( double x )
  347. {
  348. if ( x == 0 ) return 0;
  349. if ( x < 0 ) return -1;
  350. return +1;
  351. }
  352. long double report ( const korr_t* const k )
  353. {
  354. long double r;
  355. long double sx;
  356. long double sy;
  357. long double x;
  358. long double y;
  359. long double b;
  360. r = (k->x2*k->n - k->x*k->x) * (k->y2*k->n - k->y*k->y);
  361. r = r > 0.l ? (k->xy*k->n - k->x*k->y) / sqrt (r) : 1.l;
  362. sx = k->n > 1 ? sqrt ( (k->x2 - k->x*k->x/k->n) / (k->n - 1) ) : 0.l;
  363. sy = k->n > 1 ? sqrt ( (k->y2 - k->y*k->y/k->n) / (k->n - 1) ) : 0.l;
  364. x = k->n > 0 ? k->x/k->n : 0.l;
  365. y = k->n > 0 ? k->y/k->n : 0.l;
  366. b = sx != 0 ? sy/sx * sgn(r) : 0.l;
  367. if (verbose)
  368. fprintf ( stderr, "r=%Lf sx=%Lf sy=%Lf x=%Lf y=%Lf b=%Lf\n", r, sx, sy, x, y, b );
  369. return b;
  370. }
  371. /* Input: an unsigned short n.
  372. * Output: the swapped bytes of n if the arch is big-endian or n itself
  373. * if the arch is little-endian.
  374. * Comment: should be replaced latter with a better solution than this
  375. * home-brewed hack (rbrito). The name should be better also.
  376. */
  377. inline unsigned short be16_le(unsigned short n)
  378. {
  379. #ifdef _WORDS_BIGENDIAN
  380. return (n << 8) | (n >> 8);
  381. #else
  382. return n;
  383. #endif
  384. }
  385. int feed ( int fd, const stereo_t* p, int len )
  386. {
  387. int i;
  388. stereo_t tmp[30000]; /* An arbitrary size--to be changed latter */
  389. if (len > sizeof(tmp)/sizeof(*tmp))
  390. len = sizeof(tmp)/sizeof(*tmp);
  391. for (i = 0; i < len; i++) {
  392. tmp[i][0] = be16_le(p[i][0]);
  393. tmp[i][1] = be16_le(p[i][1]);
  394. }
  395. write ( fd, tmp, sizeof(stereo_t) * len );
  396. return len;
  397. }
  398. short round ( double f )
  399. {
  400. long x = (long) floor ( f + 0.5 );
  401. return x == (short)x ? (short)x : (short) ((x >> 31) ^ 0x7FFF);
  402. }
  403. int feed2 ( int fd, const stereo_t* p1, const stereo_t* p2, int len )
  404. {
  405. stereo_t tmp [30000]; /* An arbitrary size, hope that no overruns occure */
  406. int i;
  407. if (len > sizeof(tmp)/sizeof(*tmp))
  408. len = sizeof(tmp)/sizeof(*tmp);
  409. for ( i = 0; i < len; i++ ) {
  410. double f = cos ( M_PI/2*i/len );
  411. f *= f;
  412. tmp [i] [0] = be16_le(round ( p1 [i] [0] * f + p2 [i] [0] * (1. - f) ));
  413. tmp [i] [1] = be16_le(round ( p1 [i] [1] * f + p2 [i] [1] * (1. - f) ));
  414. }
  415. write ( fd, tmp, sizeof(stereo_t) * len );
  416. return len;
  417. }
  418. int feedfac ( int fd, const stereo_t* p1, const stereo_t* p2, int len, double fac1, double fac2 )
  419. {
  420. stereo_t tmp [30000]; /* An arbitrary size, hope that no overruns occure */
  421. int i;
  422. if (len > sizeof(tmp)/sizeof(*tmp))
  423. len = sizeof(tmp)/sizeof(*tmp);
  424. for ( i = 0; i < len; i++ ) {
  425. tmp [i] [0] = be16_le(round ( p1 [i] [0] * fac1 + p2 [i] [0] * fac2 ));
  426. tmp [i] [1] = be16_le(round ( p1 [i] [1] * fac1 + p2 [i] [1] * fac2 ));
  427. }
  428. write ( fd, tmp, sizeof(stereo_t) * len );
  429. return len;
  430. }
  431. void setup ( int fdd, int samples, long freq )
  432. {
  433. int status, org, arg;
  434. // Nach vorn verschoben
  435. if ( -1 == (status = ioctl (fdd, SOUND_PCM_SYNC, 0)) )
  436. perror ("SOUND_PCM_SYNC ioctl failed");
  437. org = arg = 2;
  438. if ( -1 == (status = ioctl (fdd, SOUND_PCM_WRITE_CHANNELS, &arg)) )
  439. perror ("SOUND_PCM_WRITE_CHANNELS ioctl failed");
  440. if (arg != org)
  441. perror ("unable to set number of channels");
  442. fprintf (stderr, "%1u*", arg);
  443. org = arg = AFMT_S16_LE;
  444. if ( -1 == ioctl (fdd, SNDCTL_DSP_SETFMT, &arg) )
  445. perror ("SNDCTL_DSP_SETFMT ioctl failed");
  446. if ((arg & org) == 0)
  447. perror ("unable to set data format");
  448. org = arg = freq;
  449. if ( -1 == (status = ioctl (fdd, SNDCTL_DSP_SPEED, &arg)) )
  450. perror ("SNDCTL_DSP_SPEED ioctl failed");
  451. fprintf (stderr, "%5u Hz*%.3f sec\n", arg, (double)samples/arg );
  452. }
  453. void Message ( const char* s, size_t index, long freq, size_t start, size_t stop )
  454. {
  455. unsigned long norm_index = 100lu * index / freq;
  456. unsigned long norm_start = 100lu * start / freq;
  457. unsigned long norm_stop = 100lu * stop / freq;
  458. fprintf ( stderr, "\rListening %s %2lu:%02lu.%02lu (%1lu:%02lu.%02lu...%1lu:%02lu.%02lu)%*.*s\rListening %s",
  459. s,
  460. norm_index / 6000, norm_index / 100 % 60, norm_index % 100,
  461. norm_start / 6000, norm_start / 100 % 60, norm_start % 100,
  462. norm_stop / 6000, norm_stop / 100 % 60, norm_stop % 100,
  463. 36 - (int)strlen(s), 36 - (int)strlen(s), "",
  464. s );
  465. fflush ( stderr );
  466. }
  467. size_t calc_true_index ( size_t index, size_t start, size_t stop )
  468. {
  469. if ( start >= stop )
  470. return start;
  471. while ( index - start < DMA_SAMPLES )
  472. index += stop - start;
  473. return index - DMA_SAMPLES;
  474. }
  475. void testing ( const stereo_t* A, const stereo_t* B, size_t len, long freq )
  476. {
  477. int c;
  478. int fd = open ( "/dev/dsp", O_WRONLY );
  479. int rnd = random_number (); /* Auswahl von X */
  480. int state = 0; /* derzeitiger F�ttungsmodus */
  481. float fac1 = 0.5;
  482. float fac2 = 0.5;
  483. size_t start = 0;
  484. size_t stop = len;
  485. size_t index = start; /* derzeitiger Offset auf den Audiostr�men */
  486. char message [80] = "A ";
  487. setup ( fd, len, freq );
  488. while ( 1 ) {
  489. c = sel ();
  490. if ( c == 27 )
  491. c = sel () + 0x100;
  492. switch ( c ) {
  493. case 'A' :
  494. case 'a' :
  495. strcpy ( message, "A " );
  496. if ( state != 0 )
  497. state = 2;
  498. break;
  499. case 0x100+'0' :
  500. case '0' :
  501. case 'B' :
  502. case 'b' :
  503. strcpy ( message, " B" );
  504. if ( state != 1 )
  505. state = 3;
  506. break;
  507. case 'X' :
  508. case 'x' :
  509. strcpy ( message, " X " );
  510. if ( state != rnd )
  511. state = rnd + 2;
  512. break;
  513. case 'm' :
  514. state = 8;
  515. break;
  516. case 'M' :
  517. state = (state & 1) + 4;
  518. break;
  519. case 'x'&0x1F:
  520. state = (state & 1) + 6;
  521. break;
  522. case ' ':
  523. start = 0;
  524. stop = len;
  525. break;
  526. case 'o' :
  527. start = calc_true_index ( index, start, stop);
  528. break;
  529. case 'p' :
  530. stop = calc_true_index ( index, start, stop);
  531. break;
  532. case 'h' :
  533. if ( start > freq/100 )
  534. start -= freq/100;
  535. else
  536. start = 0;
  537. index = start;
  538. continue;
  539. case 'j' :
  540. if ( start < stop-freq/100 )
  541. start += freq/100;
  542. else
  543. start = stop;
  544. index = start;
  545. continue;
  546. case 'k' :
  547. if ( stop > start+freq/100 )
  548. stop -= freq/100;
  549. else
  550. stop = start;
  551. continue;
  552. case 'l' :
  553. if ( stop < len-freq/100 )
  554. stop += freq/100;
  555. else
  556. stop = len;
  557. continue;
  558. case '\n':
  559. index = start;
  560. continue;
  561. case 'D'+0x100:
  562. strcpy ( message, "Difference (+40 dB)" );
  563. state = 9;
  564. fac1 = -100.;
  565. fac2 = +100.;
  566. break;
  567. case 'd'+0x100:
  568. strcpy ( message, "Difference (+30 dB)" );
  569. state = 9;
  570. fac1 = -32.;
  571. fac2 = +32.;
  572. break;
  573. case 'D' & 0x1F :
  574. strcpy ( message, "Difference (+20 dB)" );
  575. state = 9;
  576. fac1 = -10.;
  577. fac2 = +10.;
  578. break;
  579. case 'D' :
  580. strcpy ( message, "Difference (+10 dB)" );
  581. state = 9;
  582. fac1 = -3.;
  583. fac2 = +3.;
  584. break;
  585. case 'd' :
  586. strcpy ( message, "Difference ( 0 dB)" );
  587. state = 9;
  588. fac1 = -1.;
  589. fac2 = +1.;
  590. break;
  591. case 0x100+'1' :
  592. case 0x100+'2' :
  593. case 0x100+'3' :
  594. case 0x100+'4' :
  595. case 0x100+'5' :
  596. case 0x100+'6' :
  597. case 0x100+'7' :
  598. case 0x100+'8' :
  599. case 0x100+'9' :
  600. sprintf ( message, " B (Errors -%c dB)", (char)c );
  601. state = 9;
  602. fac2 = pow (10., -0.05*(c-0x100-'0') );
  603. fac1 = 1. - fac2;
  604. break;
  605. case '1' :
  606. case '2' :
  607. case '3' :
  608. case '4' :
  609. case '5' :
  610. case '6' :
  611. case '7' :
  612. case '8' :
  613. case '9' :
  614. sprintf ( message, " B (Errors +%c dB)", c );
  615. state = 9;
  616. fac2 = pow (10., 0.05*(c-'0') );
  617. fac1 = 1. - fac2;
  618. break;
  619. case 'A' & 0x1F:
  620. fprintf (stderr, " Vote for X:=A" );
  621. eval ( rnd == 0 );
  622. rnd = random_number ();
  623. if ( state == 6 && state == 7 )
  624. state = 6 + rnd;
  625. else if ( state != rnd )
  626. state = rnd + 2;
  627. strcpy ( message," X " );
  628. break;
  629. case 'B' & 0x1F:
  630. fprintf (stderr, " Vote for X:=B" );
  631. eval ( rnd == 1 );
  632. rnd = random_number ();
  633. if ( state == 6 && state == 7 )
  634. state = 6 + rnd;
  635. else if ( state != rnd )
  636. state = rnd + 2;
  637. strcpy ( message," X " );
  638. break;
  639. case -1:
  640. break;
  641. default:
  642. fprintf (stderr, "\a" );
  643. break;
  644. case 'Q':
  645. case 'q':
  646. fprintf ( stderr, "\n%-79.79s\r", "Quit program" );
  647. close (fd);
  648. fprintf ( stderr, "\n\n");
  649. return;
  650. }
  651. switch (state) {
  652. case 0: /* A */
  653. if ( index + BF >= stop )
  654. index += feed (fd, A+index, stop-index );
  655. else
  656. index += feed (fd, A+index, BF );
  657. break;
  658. case 1: /* B */
  659. if ( index + BF >= stop )
  660. index += feed (fd, B+index, stop-index );
  661. else
  662. index += feed (fd, B+index, BF );
  663. break;
  664. case 2: /* B => A */
  665. if ( index + BF >= stop )
  666. index += feed2 (fd, B+index, A+index, stop-index );
  667. else
  668. index += feed2 (fd, B+index, A+index, BF );
  669. state = 0;
  670. break;
  671. case 3: /* A => B */
  672. if ( index + BF >= stop )
  673. index += feed2 (fd, A+index, B+index, stop-index );
  674. else
  675. index += feed2 (fd, A+index, B+index, BF );
  676. state = 1;
  677. break;
  678. case 4: /* A */
  679. strcpy ( message, "A " );
  680. if ( index + BF >= stop )
  681. index += feed (fd, A+index, stop-index ),
  682. state++;
  683. else
  684. index += feed (fd, A+index, BF );
  685. break;
  686. case 5: /* B */
  687. strcpy ( message, " B" );
  688. if ( index + BF >= stop )
  689. index += feed (fd, B+index, stop-index ),
  690. state--;
  691. else
  692. index += feed (fd, B+index, BF );
  693. break;
  694. case 6: /* X */
  695. strcpy ( message, " X " );
  696. if ( index + BF >= stop )
  697. index += feed (fd, (rnd ? B : A)+index, stop-index ),
  698. state++;
  699. else
  700. index += feed (fd, (rnd ? B : A)+index, BF );
  701. break;
  702. case 7: /* !X */
  703. strcpy ( message, "!X " );
  704. if ( index + BF >= stop )
  705. index += feed (fd, (rnd ? A : B)+index, stop-index ),
  706. state--;
  707. else
  708. index += feed (fd, (rnd ? A : B)+index, BF );
  709. break;
  710. case 8:
  711. if ( index + BF/2 >= stop )
  712. index += feed2 (fd, A+index, B+index, stop-index );
  713. else
  714. index += feed2 (fd, A+index, B+index, BF/2 );
  715. Message ( " B", index, freq, start, stop );
  716. if ( index + BF >= stop )
  717. index += feed (fd, B+index, stop-index );
  718. else
  719. index += feed (fd, B+index, BF );
  720. if ( index + BF/2 >= stop )
  721. index += feed2 (fd, B+index, A+index, stop-index );
  722. else
  723. index += feed2 (fd, B+index, A+index, BF/2 );
  724. Message ( "A ", index, freq, start, stop );
  725. if ( index + BF >= stop )
  726. index += feed (fd, A+index, stop-index );
  727. else
  728. index += feed (fd, A+index, BF );
  729. break;
  730. case 9: /* Liko */
  731. if ( index + BF >= stop )
  732. index += feedfac (fd, A+index, B+index, stop-index, fac1, fac2 );
  733. else
  734. index += feedfac (fd, A+index, B+index, BF , fac1, fac2 );
  735. break;
  736. default:
  737. assert (0);
  738. }
  739. if (index >= stop)
  740. index = start;
  741. Message ( message, calc_true_index ( index, start, stop), freq, start, stop );
  742. }
  743. }
  744. int has_ext ( const char* name, const char* ext )
  745. {
  746. if ( strlen (name) < strlen (ext) )
  747. return 0;
  748. name += strlen (name) - strlen (ext);
  749. return strcasecmp (name, ext) ? 0 : 1;
  750. }
  751. typedef struct {
  752. const char* const extention;
  753. const char* const command;
  754. } decoder_t;
  755. #define REDIR " 2> /dev/null"
  756. #define STDOUT "/dev/fd/1"
  757. #define PATH PATH_OF_EXTERNAL_TOOLS_FOR_UNCOMPRESSING
  758. const decoder_t decoder [] = {
  759. { ".mp1" , PATH"mpg123 -w - %s" REDIR }, // MPEG Layer I : www.iis.fhg.de, www.mpeg.org
  760. { ".mp2" , PATH"mpg123 -w - %s" REDIR }, // MPEG Layer II : www.iis.fhg.de, www.uq.net.au/~zzmcheng, www.mpeg.org
  761. { ".mp3" , PATH"mpg123 -w - %s" REDIR }, // MPEG Layer III : www.iis.fhg.de, www.mp3dev.org, www.mpeg.org
  762. { ".mp3pro" , PATH"mpg123 -w - %s" REDIR }, // MPEG Layer III : www.iis.fhg.de, www.mp3dev.org, www.mpeg.org
  763. { ".mpt" , PATH"mpg123 -w - %s" REDIR }, // MPEG Layer III : www.iis.fhg.de, www.mp3dev.org, www.mpeg.org
  764. { ".mpp" , PATH"mppdec %s -" REDIR }, // MPEGplus : www.stud.uni-hannover.de/user/73884
  765. { ".mpc" , PATH"mppdec %s -" REDIR }, // MPEGplus : www.stud.uni-hannover.de/user/73884
  766. { ".mp+" , PATH"mppdec %s -" REDIR }, // MPEGplus : www.stud.uni-hannover.de/user/73884
  767. { ".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
  768. { "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
  769. { ".ac3" , PATH"ac3dec %s" REDIR }, // Dolby AC3 : www.att.com
  770. { "ac3.lqt" , PATH"ac3dec %s" REDIR }, // Dolby AC3 : www.att.com
  771. { ".ogg" , PATH"ogg123 -d wav -o file:"STDOUT" %s" REDIR }, // Ogg Vorbis : www.xiph.org/ogg/vorbis/index.html
  772. { ".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)
  773. { ".shn" , PATH"shorten -x < %s" REDIR }, // Shorten : shnutils.freeshell.org, www.softsound.com/Shorten.html (shnutils@freeshell.org, shorten@softsound.com)
  774. { ".wav.gz" , PATH"gzip -d < %s | sox -twav - -twav -sw -"REDIR }, // gziped WAV
  775. { ".wav.sz" , PATH"szip -d < %s | sox -twav - -twav -sw -"REDIR }, // sziped WAV
  776. { ".wav.sz2", PATH"szip2 -d < %s | sox -twav - -twav -sw -"REDIR }, // sziped WAV
  777. { ".raw" , PATH"sox -r44100 -sw -c2 -traw %s -twav -sw -"REDIR }, // raw files are treated as CD like audio
  778. { ".cdr" , PATH"sox -r44100 -sw -c2 -traw %s -twav -sw -"REDIR }, // CD-DA files are treated as CD like audio, no preemphasis info available
  779. { ".rm" , "echo %s '???'" REDIR }, // Real Audio : www.real.com
  780. { ".epc" , "echo %s '???'" REDIR }, // ePAC : www.audioveda.com, www.lucent.com/ldr
  781. { ".mov" , "echo %s '???'" REDIR }, // QDesign Music 2 : www.qdesign.com
  782. { ".vqf" , "echo %s '???'" REDIR }, // TwinVQ : www.yamaha-xg.com/english/xg/SoundVQ, www.vqf.com, sound.splab.ecl.ntt.co.jp/twinvq-e
  783. { ".wma" , "echo %s '???'" REDIR }, // Microsoft Media Audio: www.windowsmedia.com, www.microsoft.com/windows/windowsmedia
  784. { ".flac" , PATH"flac -c -d %s" REDIR }, // Free Lossless Audio Coder: flac.sourceforge.net/
  785. { ".fla" , PATH"flac -c -d %s" REDIR }, // Free Lossless Audio Coder: flac.sourceforge.net/
  786. { ".ape" , "( "PATH"MAC %s _._.wav -d > /dev/null; cat _._.wav; rm _._.wav )" REDIR }, // Monkey's Audio Codec : www.monkeysaudio.com (email@monkeysaudio.com)
  787. { ".rka" , "( "PATH"rkau %s _._.wav > /dev/null; cat _._.wav; rm _._.wav )" REDIR }, // RK Audio:
  788. { ".rkau" , "( "PATH"rkau %s _._.wav > /dev/null; cat _._.wav; rm _._.wav )" REDIR }, // RK Audio:
  789. { ".mod" , PATH"xmp -b16 -c -f44100 --stereo -o- %s | sox -r44100 -sw -c2 -traw - -twav -sw -"
  790. REDIR }, // Amiga's Music on Disk:
  791. { "" , PATH"sox %s -twav -sw -" REDIR }, // Rest, may be sox can handle it
  792. };
  793. #undef REDIR
  794. #undef STDOUT
  795. #undef PATH
  796. int readwave ( stereo_t* buff, size_t maxlen, const char* name, size_t* len )
  797. {
  798. char* command = malloc (2*strlen(name) + 512);
  799. char* name_q = malloc (2*strlen(name) + 128);
  800. unsigned short header [22];
  801. FILE* fp;
  802. size_t i;
  803. size_t j;
  804. // The *nice* shell quoting
  805. i = j = 0;
  806. if ( name[i] == '-' )
  807. name_q[j++] = '.',
  808. name_q[j++] = '/';
  809. while (name[i]) {
  810. if ( !isalnum (name[i]) && name[i]!='-' && name[i]!='_' && name[i]!='.' )
  811. name_q[j++] = '\\';
  812. name_q[j++] = name[i++];
  813. }
  814. name_q[j] = '\0';
  815. fprintf (stderr, "Reading %s", name );
  816. for ( i = 0; i < sizeof(decoder)/sizeof(*decoder); i++ )
  817. if ( has_ext (name, decoder[i].extention) ) {
  818. sprintf ( command, decoder[i].command, name_q );
  819. break;
  820. }
  821. free (name_q);
  822. if ( (fp = popen (command, "r")) == NULL ) {
  823. fprintf (stderr, "Can't exec:\n%s\n", command );
  824. exit (1);
  825. }
  826. free (command);
  827. fprintf (stderr, " ..." );
  828. fread ( header, sizeof(*header), sizeof(header)/sizeof(*header), fp );
  829. switch (be16_le(header[11])) {
  830. case 2:
  831. *len = fread ( buff, sizeof(stereo_t), maxlen, fp );
  832. for (i = 0; i < *len; i ++) {
  833. buff[i][0] = be16_le(buff[i][0]);
  834. buff[i][1] = be16_le(buff[i][1]);
  835. }
  836. break;
  837. case 1:
  838. *len = fread ( buff, sizeof(sample_t), maxlen, fp );
  839. for ( i = *len; i-- > 0; )
  840. buff[i][0] = buff[i][1] = ((sample_t*)buff) [i];
  841. break;
  842. case 0:
  843. fprintf (stderr, "\b\b\b\b, Standard Open Source Bug detected, try murksaround ..." );
  844. *len = fread ( buff, sizeof(stereo_t), maxlen, fp );
  845. header[11] = 2;
  846. header[12] = 65534; /* use that of the other channel */
  847. break;
  848. default:
  849. fprintf (stderr, "Only 1 or 2 channels are supported, not %u\n", header[11] );
  850. pclose (fp);
  851. return -1;
  852. }
  853. pclose ( fp );
  854. fprintf (stderr, "\n" );
  855. return be16_le(header[12]) ? be16_le(header[12]) : 65534;
  856. }
  857. double cross_analyze ( const stereo_t* p1, const stereo_t *p2, size_t len )
  858. {
  859. float P1 [MAX] [2];
  860. float P2 [MAX] [2];
  861. int i;
  862. int maxindex;
  863. double sum1;
  864. double sum2;
  865. double max;
  866. double y1;
  867. double y2;
  868. double y3;
  869. double yo;
  870. double xo;
  871. double tmp;
  872. double tmp1;
  873. double tmp2;
  874. int ret = 0;
  875. int cnt = 5;
  876. // Calculating effective voltage
  877. sum1 = sum2 = 0.;
  878. for ( i = 0; i < len; i++ ) {
  879. sum1 += (double)p1[i][0] * p1[i][0];
  880. sum2 += (double)p2[i][0] * p2[i][0];
  881. }
  882. sum1 = sqrt ( sum1/len );
  883. sum2 = sqrt ( sum2/len );
  884. // Searching beginning of signal (not stable for pathological signals)
  885. for ( i = 0; i < len; i++ )
  886. if ( abs (p1[i][0]) >= sum1 && abs (p2[i][0]) >= sum2 )
  887. break;
  888. p1 += i;
  889. p2 += i;
  890. len -= i;
  891. if ( len <= MAX )
  892. return 0;
  893. // Filling arrays for FFT
  894. do {
  895. sum1 = sum2 = 0.;
  896. for ( i = 0; i < MAX; i++ ) {
  897. #ifdef USEDIFF
  898. tmp1 = p1 [i][0] - p1 [i+1][0];
  899. tmp2 = p2 [i+ret][0] - p2 [i+ret+1][0];
  900. #else
  901. tmp1 = p1 [i][0];
  902. tmp2 = p2 [i+ret][0];
  903. #endif
  904. sum1 += tmp1*tmp1;
  905. sum2 += tmp2*tmp2;
  906. P1 [i][0] = tmp1;
  907. P2 [i][0] = tmp2;
  908. P1 [i][1] = 0.;
  909. P2 [i][1] = 0.;
  910. }
  911. fft (P1, MAX);
  912. fft (P2, MAX);
  913. for ( i = 0; i < MAX; i++ ) {
  914. double a0 = P1 [i][0];
  915. double a1 = P1 [i][1];
  916. double b0 = P2 [(MAX-i)&(MAX-1)][0];
  917. double b1 = P2 [(MAX-i)&(MAX-1)][1];
  918. P1 [i][0] = a0*b0 - a1*b1;
  919. P1 [i][1] = a0*b1 + a1*b0;
  920. }
  921. fft (P1, MAX);
  922. max = P1 [maxindex = 0][0];
  923. for ( i = 1; i < MAX; i++ )
  924. if ( P1[i][0] > max )
  925. max = P1 [maxindex = i][0];
  926. y2 = P1 [ maxindex ][0];
  927. y1 = P1 [(maxindex-1)&(MAX-1)][0] - y2;
  928. y3 = P1 [(maxindex+1)&(MAX-1)][0] - y2;
  929. xo = 0.5 * (y1-y3) / (y1+y3);
  930. yo = 0.5 * ( (y1+y3)*xo + (y3-y1) ) * xo;
  931. if (maxindex > MAX/2 )
  932. maxindex -= MAX;
  933. ret += maxindex;
  934. tmp = 100./MAX/sqrt(sum1*sum2);
  935. if (verbose)
  936. printf ( "[%5d]%8.4f [%5d]%8.4f [%5d]%8.4f [%10.4f]%8.4f\n",
  937. ret- 1, (y1+y2)*tmp,
  938. ret , y2 *tmp,
  939. ret+ 1, (y3+y2)*tmp,
  940. ret+xo, (yo+y2)*tmp );
  941. } while ( maxindex && cnt-- );
  942. return ret + xo;
  943. }
  944. short to_short ( int x )
  945. {
  946. return x == (short)x ? (short)x : (short) ((x >> 31) ^ 0x7FFF);
  947. }
  948. void DC_cancel ( stereo_t* p, size_t len )
  949. {
  950. double sum1 = 0;
  951. double sum2 = 0;
  952. size_t i;
  953. int diff1;
  954. int diff2;
  955. for (i = 0; i < len; i++ ) {
  956. sum1 += p[i][0];
  957. sum2 += p[i][1];
  958. }
  959. if ( fabs(sum1) < len && fabs(sum2) < len )
  960. return;
  961. diff1 = round ( sum1 / len );
  962. diff2 = round ( sum2 / len );
  963. if (verbose)
  964. fprintf (stderr, "Removing DC (left=%d, right=%d)\n", diff1, diff2 );
  965. for (i = 0; i < len; i++ ) {
  966. p[i][0] = to_short ( p[i][0] - diff1);
  967. p[i][1] = to_short ( p[i][1] - diff2);
  968. }
  969. }
  970. void multiply ( char c, stereo_t* p, size_t len, double fact )
  971. {
  972. size_t i;
  973. if ( fact == 1. )
  974. return;
  975. if (verbose)
  976. fprintf (stderr, "Multiplying %c by %7.5f\n", c, fact );
  977. for (i = 0; i < len; i++ ) {
  978. p[i][0] = to_short ( p[i][0] * fact );
  979. p[i][1] = to_short ( p[i][1] * fact );
  980. }
  981. }
  982. int maximum ( stereo_t* p, size_t len )
  983. {
  984. int max = 0;
  985. size_t i;
  986. for (i = 0; i < len; i++ ) {
  987. if (abs(p[i][0]) > max) max = abs(p[i][0]);
  988. if (abs(p[i][1]) > max) max = abs(p[i][1]);
  989. }
  990. return max;
  991. }
  992. void usage ( void )
  993. {
  994. fprintf ( stderr,
  995. "usage: abx [-v] File_A File_B\n"
  996. "\n"
  997. "File_A and File_B loaded and played. File_A should be the better/reference\n"
  998. "file, File_B the other. You can press the following keys:\n"
  999. "\n"
  1000. " a/A: Listen to File A\n"
  1001. " b/B: Listen to File B\n"
  1002. " x/X: Listen to the randomly selected File X, which is A or B\n"
  1003. " Ctrl-A: You vote for X=A\n"
  1004. " Ctrl-B: You vote for X=B\n"
  1005. " m: Alternating playing A and B. Fast switching\n"
  1006. " M: Alternating playing A and B. Slow switching\n"
  1007. " d/D/Ctrl-D/Alt-d/Alt-D:\n"
  1008. " Listen to the difference A-B (+0 dB...+40 dB)\n"
  1009. " o/p: Chunk select\n"
  1010. " hjkl: Chunk fine adjust (hj: start, kl: stop)\n"
  1011. " Space: Chunk deselect\n"
  1012. " 0...9: Listen to B, but difference A-B is amplified by 0-9 dB\n"
  1013. " Q: Quit the program\n"
  1014. "\n"
  1015. );
  1016. }
  1017. int main ( int argc, char** argv )
  1018. {
  1019. stereo_t* _A = calloc ( MAX_LEN, sizeof(stereo_t) );
  1020. stereo_t* _B = calloc ( MAX_LEN, sizeof(stereo_t) );
  1021. stereo_t* A = _A;
  1022. stereo_t* B = _B;
  1023. size_t len_A;
  1024. size_t len_B;
  1025. size_t len;
  1026. int max_A;
  1027. int max_B;
  1028. int max;
  1029. long freq1;
  1030. long freq2;
  1031. int shift;
  1032. double fshift;
  1033. double ampl;
  1034. int ampl_X;
  1035. korr_t k;
  1036. if (argc > 1 && 0 == strcmp (argv[1], "-v") ) {
  1037. verbose = 1;
  1038. argc--;
  1039. argv++;
  1040. }
  1041. switch ( argc ) {
  1042. case 0:
  1043. case 1:
  1044. case 2:
  1045. default:
  1046. usage ();
  1047. return 1;
  1048. case 3:
  1049. usage();
  1050. break;
  1051. }
  1052. freq1 = readwave ( A, MAX_LEN, argv[1], &len_A );
  1053. DC_cancel ( A, len_A );
  1054. freq2 = readwave ( B, MAX_LEN, argv[2], &len_B );
  1055. DC_cancel ( B, len_B );
  1056. if ( freq1 == 65534 && freq2 != 65534 )
  1057. freq1 = freq2;
  1058. else if ( freq2 == 65534 && freq1 != 65534 )
  1059. freq2 = freq1;
  1060. else if ( freq1 == 65534 && freq2 == 65534 )
  1061. freq1 = freq2 = 44100;
  1062. if ( freq1 != freq2 ) {
  1063. fprintf ( stderr, "Different sample frequencies currently not supported\n");
  1064. fprintf ( stderr, "A: %ld, B: %ld\n", freq1, freq2 );
  1065. return 2;
  1066. }
  1067. len = len_A < len_B ? len_A : len_B;
  1068. fshift = cross_analyze ( A, B, len );
  1069. shift = floor ( fshift + 0.5 );
  1070. if ( verbose ) {
  1071. fprintf ( stderr, "Delay Ch1 is %.4f samples\n", fshift );
  1072. fprintf ( stderr, "Delay Ch2 is %.4f samples\n",
  1073. cross_analyze ( (stereo_t*)(((sample_t*)A)+1), (stereo_t*)(((sample_t*)B)+1), len ) );
  1074. }
  1075. if (shift > 0) {
  1076. if (verbose)
  1077. fprintf ( stderr, "Delaying A by %d samples\n", +shift);
  1078. B += shift;
  1079. len_B -= shift;
  1080. }
  1081. if (shift < 0) {
  1082. if (verbose)
  1083. fprintf ( stderr, "Delaying B by %d samples\n", -shift);
  1084. A -= shift;
  1085. len_A += shift;
  1086. }
  1087. len = len_A < len_B ? len_A : len_B;
  1088. memset ( &k, 0, sizeof(k) );
  1089. analyze_stereo ( A, B, len, &k );
  1090. ampl = report (&k);
  1091. max_A = maximum ( A, len );
  1092. max_B = maximum ( B, len );
  1093. if ( ampl <= 0.98855 ) { /* < -0.05 dB */
  1094. max = max_A*ampl < max_B ? max_B : max_A*ampl;
  1095. ampl_X = (int)(29203 / max);
  1096. if ( ampl_X < 2 ) ampl_X = 1;
  1097. multiply ( 'A', A, len, ampl*ampl_X );
  1098. multiply ( 'B', B, len, ampl_X );
  1099. } else if ( ampl >= 1.01158 ) { /* > +0.05 dB */
  1100. max = max_A < max_B/ampl ? max_B/ampl : max_A;
  1101. ampl_X = (int)(29203 / max);
  1102. if ( ampl_X < 2 ) ampl_X = 1;
  1103. multiply ( 'A', A, len, ampl_X );
  1104. multiply ( 'B', B, len, 1./ampl*ampl_X );
  1105. } else {
  1106. max = max_A < max_B ? max_B : max_A;
  1107. ampl_X = (int)(29203 / max);
  1108. if ( ampl_X < 2 ) ampl_X = 1;
  1109. multiply ( 'A', A, len, ampl_X );
  1110. multiply ( 'B', B, len, ampl_X );
  1111. }
  1112. set ();
  1113. Set_Realtime ();
  1114. testing ( A, B, len, freq1 );
  1115. reset ();
  1116. free (_A);
  1117. free (_B);
  1118. return 0;
  1119. }
  1120. /* end of abx.c */