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