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

📄 taudiofilterheadphone.cpp

📁 从FFMPEG转换而来的H264解码程序,VC下编译..
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/*
 * Copyright (c) 2004-2006 Milan Cutka
 * based on VideoLAN headphone virtual spatialization channel mixer module by Boris Dor鑣
 * HRTF by ylai
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "stdafx.h"
#include "TaudioFilterHeadphone.h"
#include "TmixerSettings.h"
#include "firfilter.h"
#include "TfirSettings.h"

TaudioFilterHeadphone::TaudioFilterHeadphone(IffdshowBase *Ideci,Tfilters *Iparent):TaudioFilter(Ideci,Iparent)
{
 oldfmt.freq=0;olddim=-1;
 p_sys=NULL;
 inited=false;
}
void TaudioFilterHeadphone::done(void)
{
 if (p_sys)
  {
   if (p_sys->p_overflow_buffer) free(p_sys->p_overflow_buffer);
   if (p_sys->p_atomic_operations) free(p_sys->p_atomic_operations);
   free(p_sys);p_sys=NULL;
  }
}

/*****************************************************************************
 * Init: initialize internal data structures
 * and computes the needed atomic operations
 *****************************************************************************/
/* x and z represent the coordinates of the virtual speaker
 *  relatively to the center of the listener's head, measured in meters :
 *
 *  left              right
 *Z
 *-
 *a          head
 *x
 *i
 *s
 *  rear left    rear right
 *
 *          x-axis
 *  */
void TaudioFilterHeadphone::aout_filter_sys_t::ComputeChannelOperations (
        unsigned int i_rate , unsigned int i_next_atomic_operation
        , int i_source_channel_offset , double d_x , double d_z
        , double d_channel_amplitude_factor )
{
    double d_c = 340; /*sound celerity (unit: m/s)*/

    /* Left ear */
    p_atomic_operations[i_next_atomic_operation]
        .i_source_channel_offset = i_source_channel_offset;
    p_atomic_operations[i_next_atomic_operation]
        .i_dest_channel_offset = 0;/* left */
    p_atomic_operations[i_next_atomic_operation]
        .i_delay = (int)( sqrt( (-0.1-d_x)*(-0.1-d_x) + (0-d_z)*(0-d_z) )
                          / d_c * i_rate );
    if ( d_x < 0 )
    {
        p_atomic_operations[i_next_atomic_operation]
            .d_amplitude_factor = d_channel_amplitude_factor * 1.1 / 2;
    }
    else if ( d_x > 0 )
    {
        p_atomic_operations[i_next_atomic_operation]
            .d_amplitude_factor = d_channel_amplitude_factor * 0.9 / 2;
    }
    else
    {
        p_atomic_operations[i_next_atomic_operation]
            .d_amplitude_factor = d_channel_amplitude_factor / 2;
    }

    /* Right ear */
    p_atomic_operations[i_next_atomic_operation + 1]
        .i_source_channel_offset = i_source_channel_offset;
    p_atomic_operations[i_next_atomic_operation + 1]
        .i_dest_channel_offset = 1;/* right */
    p_atomic_operations[i_next_atomic_operation + 1]
        .i_delay = (int)( sqrt( (0.1-d_x)*(0.1-d_x) + (0-d_z)*(0-d_z) )
                          / d_c * i_rate );
    if ( d_x < 0 )
    {
        p_atomic_operations[i_next_atomic_operation + 1]
            .d_amplitude_factor = d_channel_amplitude_factor * 0.9 / 2;
    }
    else if ( d_x > 0 )
    {
        p_atomic_operations[i_next_atomic_operation + 1]
            .d_amplitude_factor = d_channel_amplitude_factor * 1.1 / 2;
    }
    else
    {
        p_atomic_operations[i_next_atomic_operation + 1]
            .d_amplitude_factor = d_channel_amplitude_factor / 2;
    }
}

int TaudioFilterHeadphone::aout_filter_sys_t::Init(const TsampleFormat &fmt,const TmixerSettings *cfg)
{
    double d_x = cfg->headphone_dim;//config_GetInt ( p_filter , "headphone-dim" );
    double d_z = d_x;
    double d_z_rear = -d_x/3;
    unsigned int i_next_atomic_operation;
    int i_source_channel_offset;

    /* Number of elementary operations */
    i_nb_atomic_operations = fmt.nchannels * 2;
    p_atomic_operations = (atomic_operation_t*)malloc ( sizeof(atomic_operation_t)
            * i_nb_atomic_operations );
    /* For each virtual speaker, computes elementary wave propagation time
     * to each ear */
    i_next_atomic_operation = 0;
    i_source_channel_offset = 0;
    for (unsigned int ch=0;ch<fmt.nchannels;ch++)
     if ( fmt.speakers[ch] == SPEAKER_FRONT_LEFT)
      {
          ComputeChannelOperations ( fmt.freq
                  , i_next_atomic_operation , i_source_channel_offset
                  , -d_x , d_z , 2.0 / fmt.nchannels );
          i_next_atomic_operation += 2;
          i_source_channel_offset++;
      }
     else if ( fmt.speakers[ch] ==  SPEAKER_FRONT_RIGHT )
      {
          ComputeChannelOperations ( fmt.freq
                  , i_next_atomic_operation , i_source_channel_offset
                  , d_x , d_z , 2.0 / fmt.nchannels );
          i_next_atomic_operation += 2;
          i_source_channel_offset++;
      }
     else if ( fmt.speakers[ch] == SPEAKER_BACK_LEFT )
      {
          ComputeChannelOperations ( fmt.freq
                  , i_next_atomic_operation , i_source_channel_offset
                  , -d_x , d_z_rear , 1.5 / fmt.nchannels );
          i_next_atomic_operation += 2;
          i_source_channel_offset++;
      }
     else if ( fmt.speakers[ch] == SPEAKER_BACK_RIGHT )
      {
          ComputeChannelOperations ( fmt.freq
                  , i_next_atomic_operation , i_source_channel_offset
                  , d_x , d_z_rear , 1.5 / fmt.nchannels );
          i_next_atomic_operation += 2;
          i_source_channel_offset++;
      }
     else if ( fmt.speakers[ch] ==  SPEAKER_BACK_CENTER )
      {
          ComputeChannelOperations ( fmt.freq
                  , i_next_atomic_operation , i_source_channel_offset
                  , 0 , -d_z , 1.5 / fmt.nchannels );
          i_next_atomic_operation += 2;
          i_source_channel_offset++;
      }
     else if ( fmt.speakers[ch] ==  SPEAKER_FRONT_CENTER )
      {
          ComputeChannelOperations ( fmt.freq
                  , i_next_atomic_operation , i_source_channel_offset
                  , 0 , d_z , 1.5 / fmt.nchannels );
          i_next_atomic_operation += 2;
          i_source_channel_offset++;
      }
     else if ( fmt.speakers[ch] == SPEAKER_LOW_FREQUENCY )
      {
          ComputeChannelOperations ( fmt.freq
                  , i_next_atomic_operation , i_source_channel_offset
                  , 0 , d_z_rear , 5.0 / fmt.nchannels );
          i_next_atomic_operation += 2;
          i_source_channel_offset++;
      }
     else if ( fmt.speakers[ch] ==  SPEAKER_SIDE_LEFT )
      {
          ComputeChannelOperations ( fmt.freq
                  , i_next_atomic_operation , i_source_channel_offset
                  , -d_x , 0 , 1.5 / fmt.nchannels );
          i_next_atomic_operation += 2;
          i_source_channel_offset++;
      }
     else if ( fmt.speakers[ch] == SPEAKER_SIDE_RIGHT )
      {
          ComputeChannelOperations ( fmt.freq
                  , i_next_atomic_operation , i_source_channel_offset
                  , d_x , 0 , 1.5 / fmt.nchannels );
          i_next_atomic_operation += 2;
          i_source_channel_offset++;
      }

    /* Initialize the overflow buffer
     * we need it because the process induce a delay in the samples */
    i_overflow_buffer_size = 0;
    for (unsigned int i= 0 ; i < i_nb_atomic_operations ; i++ )
    {
        if ( i_overflow_buffer_size
                < p_atomic_operations[i].i_delay * ((fmt.nchannels >= 2) ? fmt.nchannels : 2)
                * sizeof (float) )
        {
            i_overflow_buffer_size
                = p_atomic_operations[i].i_delay * ((fmt.nchannels >= 2) ? fmt.nchannels : 2)
                * sizeof (float);
        }
    }
    p_overflow_buffer = (byte_t*)malloc ( i_overflow_buffer_size );
    memset ( p_overflow_buffer , 0 , i_overflow_buffer_size );

    /* end */
    return 0;
}

bool TaudioFilterHeadphone::getOutputFmt(TsampleFormat &fmt,const TfilterSettingsAudio *cfg)
{
 if (super::getOutputFmt(fmt,cfg))
  {
   fmt.setChannels(2);
   return true;
  }
 else
  return false;
}

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);
        }
      }

⌨️ 快捷键说明

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