HRESULT TaudioFilterHeadphone2::process(TfilterQueue::iterator it,TsampleFormat &fmt,void *samples,size_t numsamples,const TfilterSettingsAudio *cfg0)
{
    const TmixerSettings *cfg=(const TmixerSettings*)cfg0;

    if (!s || oldfmt!=fmt) {
        oldfmt=fmt;
        done();
        /* MPlayer's 5 channel layout (notation for the variable):
         *
         * 0: L (LF), 1: R (RF), 2: Ls (LR), 3: Rs (RR), 4: C (CF), matrix
         * encoded: Cs (CR)
         *
         * or: L = left, C = center, R = right, F = front, R = rear*/
        indexes[0]=fmt.findSpeaker(SPEAKER_FRONT_LEFT);
        indexes[1]=fmt.findSpeaker(SPEAKER_FRONT_RIGHT);
        indexes[2]=fmt.findSpeaker(SPEAKER_BACK_LEFT);
        indexes[3]=fmt.findSpeaker(SPEAKER_BACK_RIGHT);
        indexes[4]=fmt.findSpeaker(SPEAKER_FRONT_CENTER);
        indexes[5]=fmt.findSpeaker(SPEAKER_LOW_FREQUENCY);
        //indexes[6]=fmt.findSpeaker(SPEAKER_BACK_CENTER);
        //indexes[7]=fmt.findSpeaker(SPEAKER_SIDE_LEFT);
        //indexes[8]=fmt.findSpeaker(SPEAKER_SIDE_RIGHT);
        s=new af_hrtf_s(fmt);
    }

    float *inbuf=(float*)init(cfg,fmt,samples,numsamples); // Input audio data
    float *end=inbuf+numsamples*fmt.nchannels; // Loop end
    fmt.setChannels(2);
    float *out=(float*)(samples=alloc_buffer(fmt,numsamples,buf));

    const int dblen = s->dlbuflen, hlen = s->hrflen, blen = s->basslen;
    while(inbuf < end) {
        const int k = s->cyc_pos;
        for (int i=0 ; i<6 /* 9 */ ; i++) {
            in[i]=indexes[i]!=-1 ? inbuf[indexes[i]] : 0.0f;
        }

        s->update_ch(in, k);

        /* Simulate a 7.5 ms -20 dB echo of the center channel in the
           front channels (like reflection from a room wall) - a kind of
           psycho-acoustically "cheating" to focus the center front
           channel, which is normally hard to be perceived as front */
        static const float CFECHOAMPL=M17_0DB;    /* Center front echo amplitude */
        s->lf[k] += CFECHOAMPL * s->cf[(k + CFECHODELAY) % s->dlbuflen];
        s->rf[k] += CFECHOAMPL * s->cf[(k + CFECHODELAY) % s->dlbuflen];

        float common,left,right;

        common = conv(dblen, hlen, &s->cf[0], &s->cf_ir[0], k + s->cf_o);

        left    =
            ( conv(dblen, hlen, &s->lf[0], s->af_ir, k + s->af_o) +
              conv(dblen, hlen, &s->rf[0], s->of_ir, k + s->of_o) +
              conv(dblen, hlen, &s->lr[0], s->ar_ir, k + s->ar_o) +
              conv(dblen, hlen, &s->rr[0], s->or_ir, k + s->or_o) +
              common);
        right   =
            ( conv(dblen, hlen, &s->rf[0], s->af_ir, k + s->af_o) +
              conv(dblen, hlen, &s->lf[0], s->of_ir, k + s->of_o) +
              conv(dblen, hlen, &s->rr[0], s->ar_ir, k + s->ar_o) +
              conv(dblen, hlen, &s->lr[0], s->or_ir, k + s->or_o) +
              common);

        /* Bass compensation for the lower frequency cut of the HRTF.  A
           cross talk of the left and right channel is introduced to
           match the directional characteristics of higher frequencies.
           The bass will not have any real 3D perception, but that is
           OK (note at 180 Hz, the wavelength is about 2 m, and any
           spatial perception is impossible). */
        float left_b  = conv(dblen, blen, &s->ba_l[0], s->ba_ir, k);
        float right_b = conv(dblen, blen, &s->ba_r[0], s->ba_ir, k);
        left  += (1 - BASSCROSS) * left_b  + BASSCROSS * right_b;
        right += (1 - BASSCROSS) * right_b + BASSCROSS * left_b;
        /* Also mix the LFE channel (if available) */
        if(indexes[5]!=-1) {
            left  += in[5] * M3_01DB;
            right += in[5] * M3_01DB;
        }

        /* Amplitude renormalization. */
        static const float AMPLNORM=M6_99DB;    /* Overall amplitude renormalization */
        left  *= AMPLNORM;
        right *= AMPLNORM;

        /* "Cheating": linear stereo expansion to amplify the 3D
           perception.  Note: Too much will destroy the acoustic space
           and may even result in headaches. */
        float diff = STEXPAND2 * (left - right);
        out[0] = left  + diff;
        out[1] = right - diff;
        /* Next sample... */
        inbuf += oldfmt.nchannels;
        out += fmt.nchannels;
        s->cyc_pos--;
        if(s->cyc_pos < 0) {
            s->cyc_pos += dblen;
        }
    }
    return parent->deliverSamples(++it,fmt,samples,numsamples);
}