⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 abx.c

📁 音频编码
💻 C
📖 第 1 页 / 共 3 页
字号:
{    if ( strlen (name) < strlen (ext) )        return 0;    name += strlen (name) - strlen (ext);    return strcasecmp (name, ext)  ?  0  :  1;}typedef struct {    const char* const  extention;    const char* const  command;} decoder_t;#define REDIR     " 2> /dev/null"#define STDOUT    "/dev/fd/1"#define PATH      PATH_OF_EXTERNAL_TOOLS_FOR_UNCOMPRESSINGconst decoder_t  decoder [] = {    { ".mp1"    , PATH"mpg123 -w - %s"                         REDIR },  // MPEG Layer I         : www.iis.fhg.de, www.mpeg.org    { ".mp2"    , PATH"mpg123 -w - %s"                         REDIR },  // MPEG Layer II        : www.iis.fhg.de, www.uq.net.au/~zzmcheng, www.mpeg.org    { ".mp3"    , PATH"mpg123 -w - %s"                         REDIR },  // MPEG Layer III       : www.iis.fhg.de, www.mp3dev.org/mp3, www.mpeg.org    { ".mp3pro" , PATH"mpg123 -w - %s"                         REDIR },  // MPEG Layer III       : www.iis.fhg.de, www.mp3dev.org/mp3, www.mpeg.org    { ".mpt"    , PATH"mpg123 -w - %s"                         REDIR },  // MPEG Layer III       : www.iis.fhg.de, www.mp3dev.org/mp3, www.mpeg.org    { ".mpp"    , PATH"mppdec %s -"                            REDIR },  // MPEGplus             : www.stud.uni-hannover.de/user/73884    { ".mpc"    , PATH"mppdec %s -"                            REDIR },  // MPEGplus             : www.stud.uni-hannover.de/user/73884    { ".mp+"    , PATH"mppdec %s -"                            REDIR },  // MPEGplus             : www.stud.uni-hannover.de/user/73884    { ".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    { "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    { ".ac3"    , PATH"ac3dec %s"                              REDIR },  // Dolby AC3            : www.att.com    { "ac3.lqt" , PATH"ac3dec %s"                              REDIR },  // Dolby AC3            : www.att.com    { ".ogg"    , PATH"ogg123 -d wav -o file:"STDOUT" %s"      REDIR },  // Ogg Vorbis           : www.xiph.org/ogg/vorbis/index.html    { ".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)    { ".shn"    , PATH"shorten -x < %s"                        REDIR },  // Shorten              : shnutils.freeshell.org, www.softsound.com/Shorten.html (shnutils@freeshell.org, shorten@softsound.com)    { ".wav.gz" , "gzip  -d < %s | sox -twav - -twav -sw -"    REDIR },  // gziped WAV    { ".wav.sz" , PATH"szip  -d < %s | sox -twav - -twav -sw -"REDIR },  // sziped WAV    { ".wav.sz2", PATH"szip2 -d < %s | sox -twav - -twav -sw -"REDIR },  // sziped WAV    { ".raw"    , "sox -r44100 -sw -c2 -traw %s -twav -sw -"   REDIR },  // raw files are treated as CD like audio    { ".cdr"    , "sox -r44100 -sw -c2 -traw %s -twav -sw -"   REDIR },  // CD-DA files are treated as CD like audio, no preemphasis info available    { ".rm"     , "echo %s '???'"                              REDIR },  // Real Audio           : www.real.com    { ".epc"    , "echo %s '???'"                              REDIR },  // ePAC                 : www.audioveda.com, www.lucent.com/ldr    { ".mov"    , "echo %s '???'"                              REDIR },  // QDesign Music 2      : www.qdesign.com    { ".vqf"    , "echo %s '???'"                              REDIR },  // TwinVQ               : www.yamaha-xg.com/english/xg/SoundVQ, www.vqf.com, sound.splab.ecl.ntt.co.jp/twinvq-e    { ".wma"    , "echo %s '???'"                              REDIR },  // Microsoft Media Audio: www.windowsmedia.com, www.microsoft.com/windows/windowsmedia    { ".flac"   , PATH"flac -c -d %s"                          REDIR },  // Free Lossless Audio Coder: flac.sourceforge.net/    { ".fla"    , PATH"flac -c -d %s"                          REDIR },  // Free Lossless Audio Coder: flac.sourceforge.net/    { ".ape"    , "( "PATH"MAC %s _._.wav -d > /dev/null; cat _._.wav; rm _._.wav )"  REDIR },  // Monkey's Audio Codec : www.monkeysaudio.com (email@monkeysaudio.com)    { ".rka"    , "( "PATH"rkau %s _._.wav   > /dev/null; cat _._.wav; rm _._.wav )"  REDIR },  // RK Audio:                  { ".rkau"   , "( "PATH"rkau %s _._.wav   > /dev/null; cat _._.wav; rm _._.wav )"  REDIR },  // RK Audio:                  { ".mod"    , "xmp -b16 -c -f44100 --stereo -o- %s | sox -r44100 -sw -c2 -traw - -twav -sw -"                                                               REDIR },  // Amiga's Music on Disk:    { ""        , "sox %s -twav -sw -"                         REDIR },  // Rest, may be sox can handle it};#undef REDIR#undef STDOUT#undef PATHint  readwave ( stereo_t* buff, size_t maxlen, const char* name, size_t* len ){    char*           command = malloc (2*strlen(name) + 512);    char*           name_q  = malloc (2*strlen(name) + 128);    unsigned short  header [22];    FILE*           fp;    size_t          i;    size_t          j;    // The *nice* shell quoting    i = j = 0;    if ( name[i] == '-' )        name_q[j++] = '.',        name_q[j++] = '/';            while (name[i]) {        if ( !isalnum (name[i]) && name[i]!='-' && name[i]!='_' && name[i]!='.' )            name_q[j++] = '\\';        name_q[j++] = name[i++];    }    name_q[j] = '\0';    fprintf (stderr, "Reading %s", name );    for ( i = 0; i < sizeof(decoder)/sizeof(*decoder); i++ )        if ( has_ext (name, decoder[i].extention) ) {            sprintf ( command, decoder[i].command, name_q );            break;        }    free (name_q);    if ( (fp = popen (command, "r")) == NULL ) {        fprintf (stderr, "Can't exec:\n%s\n", command );        exit (1);    }    free (command);        fprintf (stderr, " ..." );    fread ( header, sizeof(*header), sizeof(header)/sizeof(*header), fp );    switch ( header[11] ) {        case 2:            *len = fread ( buff, sizeof(stereo_t), maxlen, fp );            break;        case 1:            *len = fread ( buff, sizeof(sample_t), maxlen, fp );            for ( i = *len; i-- > 0; )                buff[i][0] = buff[i][1] = ((sample_t*)buff) [i];            break;        case 0:            fprintf (stderr, "\b\b\b\b, Standard Open Source Bug detected, try murksaround ..." );            *len = fread ( buff, sizeof(stereo_t), maxlen, fp );            header[11] =     2;            header[12] = 65534;  /* use that of the other channel */            break;        default:            fprintf (stderr, "Only 1 or 2 channels are supported, not %u\n", header[11] );            pclose (fp);            return -1;    }    pclose ( fp );     fprintf (stderr, "\n" );    return header[12] ? header[12] : 65534;}double  cross_analyze ( const stereo_t* p1, const stereo_t *p2, size_t len ){    float   P1 [MAX] [2];    float   P2 [MAX] [2];    int     i;    int     maxindex;    double  sum1;    double  sum2;    double  max;    double  y1;    double  y2;    double  y3;    double  yo;    double  xo;    double  tmp;    double  tmp1;    double  tmp2;    int     ret = 0;    int     cnt = 5;    // Calculating effective voltage    sum1 = sum2 = 0.;    for ( i = 0; i < len; i++ ) {        sum1 += (double)p1[i][0] * p1[i][0];        sum2 += (double)p2[i][0] * p2[i][0];    }    sum1 = sqrt ( sum1/len );    sum2 = sqrt ( sum2/len );    // Searching beginning of signal (not stable for pathological signals)    for ( i = 0; i < len; i++ )        if ( abs (p1[i][0]) >= sum1  &&  abs (p2[i][0]) >= sum2 )            break;    p1  += i;    p2  += i;    len -= i;    if ( len <= MAX )        return 0;    // Filling arrays for FFT    do {        sum1 = sum2 = 0.;        for ( i = 0; i < MAX; i++ ) {#ifdef USEDIFF            tmp1  = p1 [i][0] - p1 [i+1][0];            tmp2  = p2 [i+ret][0] - p2 [i+ret+1][0];#else            tmp1  = p1 [i][0];            tmp2  = p2 [i+ret][0];#endif            sum1 += tmp1*tmp1;            sum2 += tmp2*tmp2;            P1 [i][0] = tmp1;            P2 [i][0] = tmp2;            P1 [i][1] = 0.;            P2 [i][1] = 0.;        }        fft (P1, MAX);        fft (P2, MAX);        for ( i = 0; i < MAX; i++ ) {            double  a0 = P1 [i][0];            double  a1 = P1 [i][1];            double  b0 = P2 [(MAX-i)&(MAX-1)][0];            double  b1 = P2 [(MAX-i)&(MAX-1)][1];            P1 [i][0] = a0*b0 - a1*b1;            P1 [i][1] = a0*b1 + a1*b0;        }        fft (P1, MAX);        max = P1 [maxindex = 0][0];        for ( i = 1; i < MAX; i++ )            if ( P1[i][0] > max )                max = P1 [maxindex = i][0];        y2 = P1 [ maxindex           ][0];        y1 = P1 [(maxindex-1)&(MAX-1)][0] - y2;        y3 = P1 [(maxindex+1)&(MAX-1)][0] - y2;        xo = 0.5 * (y1-y3) / (y1+y3);        yo = 0.5 * ( (y1+y3)*xo + (y3-y1) ) * xo;        if (maxindex > MAX/2 )            maxindex -= MAX;        ret += maxindex;        tmp = 100./MAX/sqrt(sum1*sum2);        if (verbose)            printf ( "[%5d]%8.4f  [%5d]%8.4f  [%5d]%8.4f  [%10.4f]%8.4f\n",                     ret- 1, (y1+y2)*tmp,                     ret   ,     y2 *tmp,                     ret+ 1, (y3+y2)*tmp,                     ret+xo, (yo+y2)*tmp );    } while ( maxindex  &&  cnt-- );    return ret + xo;}short  to_short ( int x ){    return x == (short)x  ?  (short)x  :  (short) ((x >> 31) ^ 0x7FFF);}void  DC_cancel ( stereo_t* p, size_t len ){    double  sum1 = 0;    double  sum2 = 0;    size_t  i;    int     diff1;    int     diff2;        for (i = 0; i < len; i++ ) {        sum1 += p[i][0];        sum2 += p[i][1];    }    if ( fabs(sum1) < len  &&  fabs(sum2) < len )        return;            diff1 = round ( sum1 / len );    diff2 = round ( sum2 / len );    if (verbose)        fprintf (stderr, "Removing DC (left=%d, right=%d)\n", diff1, diff2 );        for (i = 0; i < len; i++ ) {        p[i][0] = to_short ( p[i][0] - diff1);        p[i][1] = to_short ( p[i][1] - diff2);    }}void  multiply ( char c, stereo_t* p, size_t len, double fact ){    size_t  i;        if ( fact == 1. )        return;    if (verbose)        fprintf (stderr, "Multiplying %c by %7.5f\n", c, fact );        for (i = 0; i < len; i++ ) {        p[i][0] = to_short ( p[i][0] * fact );        p[i][1] = to_short ( p[i][1] * fact );    }}int  maximum ( stereo_t* p, size_t len ){    int     max = 0;    size_t  i;        for (i = 0; i < len; i++ ) {        if (abs(p[i][0]) > max) max = abs(p[i][0]);        if (abs(p[i][1]) > max) max = abs(p[i][1]);    }    return max;}void  usage ( void ){    fprintf ( stderr,         "usage:  abx [-v] File_A File_B\n"        "\n"        "File_A and File_B loaded and played. File_A should be the better/reference\n"        "file, File_B the other. You can press the following keys:\n"        "\n"        "  a/A:    Listen to File A\n"        "  b/B:    Listen to File B\n"        "  x/X:    Listen to the randomly selected File X, which is A or B\n"        "  Ctrl-A: You vote for X=A\n"        "  Ctrl-B: You vote for X=B\n"        "  m:      Alternating playing A and B. Fast switching\n"        "  M:      Alternating playing A and B. Slow switching\n"        "  d/D/Ctrl-D/Alt-d/Alt-D:\n"        "          Listen to the difference A-B (+0 dB...+40 dB)\n"        "  o/p:    Chunk select\n"        "  hjkl:   Chunk fine adjust (hj: start, kl: stop)\n"        "  Space:  Chunk deselect\n"        "  0...9:  Listen to B, but difference A-B is amplified by 0-9 dB\n"        "  Q:      Quit the program\n"        "\n"    );}int  main ( int argc, char** argv ){    stereo_t*  _A = calloc ( sizeof(stereo_t), MAX_LEN );    stereo_t*  _B = calloc ( sizeof(stereo_t), MAX_LEN );    stereo_t*  A  = _A;    stereo_t*  B  = _B;    size_t     len_A;    size_t     len_B;    size_t     len;    int        max_A;    int        max_B;    int        max;    long       freq1;    long       freq2;    int        shift;    double     fshift;    double     ampl;    int        ampl_X;    korr_t     k;        if (argc > 1  &&  0 == strcmp (argv[1], "-v") ) {        verbose = 1;        argc--;        argv++;    }    switch ( argc ) {    case 0:    case 1:    case 2:    default:        usage ();        return 1;    case 3:        usage();        break;    }    freq1 = readwave ( A, MAX_LEN, argv[1], &len_A );    DC_cancel ( A, len_A );    freq2 = readwave ( B, MAX_LEN, argv[2], &len_B );    DC_cancel ( B, len_B );        if      ( freq1 == 65534  &&  freq2 != 65534 )        freq1 = freq2;    else if ( freq2 == 65534  &&  freq1 != 65534 )        freq2 = freq1;    else if ( freq1 == 65534  &&  freq2 == 65534 )        freq1 = freq2 = 44100;    if ( freq1 != freq2 ) {        fprintf ( stderr, "Different sample frequencies currently not supported\n");        fprintf ( stderr, "A: %ld, B: %ld\n", freq1, freq2 );        return 2;    }    len    = len_A < len_B  ?  len_A  :  len_B;    fshift = cross_analyze ( A, B, len );    shift  = floor ( fshift + 0.5 );    if ( verbose ) {        fprintf ( stderr, "Delay Ch1 is %.4f samples\n", fshift );	fprintf ( stderr, "Delay Ch2 is %.4f samples\n", 	          cross_analyze ( (stereo_t*)(((sample_t*)A)+1), (stereo_t*)(((sample_t*)B)+1), len ) );    }    if (shift > 0) {        if (verbose)             fprintf ( stderr, "Delaying A by %d samples\n", +shift);        B     += shift;        len_B -= shift;    }    if (shift < 0) {        if (verbose)            fprintf ( stderr, "Delaying B by %d samples\n", -shift);        A     -= shift;        len_A += shift;    }    len    = len_A < len_B  ?  len_A  :  len_B;    memset ( &k, 0, sizeof(k) );        analyze_stereo ( A, B, len, &k );    ampl  = report (&k);    max_A = maximum ( A, len );     max_B = maximum ( B, len );         if ( ampl <= 0.98855 ) { /* < -0.05 dB */        max    = max_A*ampl < max_B  ?  max_B  :  max_A*ampl;        ampl_X = (int)(29203 / max);        if ( ampl_X < 2 ) ampl_X = 1;        multiply ( 'A', A, len, ampl*ampl_X );        multiply ( 'B', B, len,      ampl_X );    } else if ( ampl >= 1.01158 ) { /* > +0.05 dB */        max    = max_A < max_B/ampl  ?  max_B/ampl  :  max_A;        ampl_X = (int)(29203 / max);        if ( ampl_X < 2 ) ampl_X = 1;        multiply ( 'A', A, len,         ampl_X );        multiply ( 'B', B, len, 1./ampl*ampl_X );    } else {        max    = max_A < max_B ? max_B : max_A;        ampl_X = (int)(29203 / max);        if ( ampl_X < 2 ) ampl_X = 1;        multiply ( 'A', A, len, ampl_X );        multiply ( 'B', B, len, ampl_X );    }    set ();    Set_Realtime ();    testing ( A, B, len, freq1 );    reset ();    free (_A);    free (_B);    return 0;}/* end of abx.c */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -