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

    if (!p_sys || oldfmt!=fmt || olddim!=cfg->headphone_dim) {
        oldfmt=fmt;
        olddim=cfg->headphone_dim;
        done();
        /* Allocate the memory needed to store the module's structure */
        p_sys=(aout_filter_sys_t*)malloc(sizeof(aout_filter_sys_t));
        p_sys->i_overflow_buffer_size=0;
        p_sys->p_overflow_buffer=NULL;
        p_sys->i_nb_atomic_operations=0;
        p_sys->p_atomic_operations=NULL;
        inited=p_sys->Init(fmt,cfg)>=0;
    }

    if (inited) {
        float *p_in=(float*)init(cfg,fmt,samples0,numsamples);
        unsigned int i_input_nb=fmt.nchannels;
        fmt.setChannels(2);
        float *p_out=(float*)alloc_buffer(fmt,numsamples,buf);
        unsigned int i_output_nb=fmt.nchannels;

        /* Slide the overflow buffer */
        byte_t *p_overflow = p_sys->p_overflow_buffer;
        size_t i_overflow_size = p_sys->i_overflow_buffer_size;
        size_t i_out_size=numsamples*fmt.blockAlign();

        memset ( p_out , 0 , i_out_size );
        if ( i_out_size > i_overflow_size ) {
            memcpy ( p_out , p_overflow , i_overflow_size );
        } else {
            memcpy ( p_out , p_overflow , i_out_size );
        }

        byte_t *p_slide = p_sys->p_overflow_buffer;
        while ( p_slide < p_overflow + i_overflow_size ) {
            if ( p_slide + i_out_size < p_overflow + i_overflow_size ) {
                memset ( p_slide , 0 , i_out_size );
                if ( p_slide + 2 * i_out_size < p_overflow + i_overflow_size ) {
                    memcpy ( p_slide , p_slide + i_out_size , i_out_size );
                } else {
                    memcpy ( p_slide , p_slide + i_out_size , p_overflow + i_overflow_size - ( p_slide + i_out_size ) );
                }
            } else {
                memset ( p_slide , 0 , p_overflow + i_overflow_size - p_slide );
            }
            p_slide += i_out_size;
        }

        /* apply the atomic operations */
        for ( unsigned int i = 0 ; i < p_sys->i_nb_atomic_operations ; i++ ) {
            /* shorter variable names */
            int i_source_channel_offset = p_sys->p_atomic_operations[i].i_source_channel_offset;
            int i_dest_channel_offset = p_sys->p_atomic_operations[i].i_dest_channel_offset;
            unsigned int i_delay = p_sys->p_atomic_operations[i].i_delay;
            double d_amplitude_factor = p_sys->p_atomic_operations[i].d_amplitude_factor;

            if ( numsamples > i_delay ) {
                unsigned int j;
                /* current buffer coefficients */
                for ( j = 0 ; j < numsamples - i_delay ; j++ ) {
                    p_out[ (i_delay+j)*i_output_nb + i_dest_channel_offset ]
                    += float(p_in[ j * i_input_nb + i_source_channel_offset ]
                             * d_amplitude_factor);
                }

                /* overflow buffer coefficients */
                for ( j = 0 ; j < i_delay ; j++ ) {
                    ((float*)p_overflow)[ j*i_output_nb + i_dest_channel_offset ]
                    += float(p_in[ (numsamples - i_delay + j)
                                   * i_input_nb + i_source_channel_offset ]
                             * d_amplitude_factor);
                }
            } else {
                /* overflow buffer coefficients only */
                for ( unsigned int j = 0 ; j < numsamples ; j++ ) {
                    ((float*)p_overflow)[ (i_delay - numsamples + j)
                                          * i_output_nb + i_dest_channel_offset ]
                    += float(p_in[ j * i_input_nb + i_source_channel_offset ]
                             * d_amplitude_factor);
                }
            }
        }
        samples0=p_out;
    }
    return parent->deliverSamples(++it,fmt,samples0,numsamples);
}