<commit_before>//  
// Copyright (C) 2008 SIPfoundry Inc. 
// Licensed by SIPfoundry under the LGPL license. 
//  
// Copyright (C) 2008 SIPez LLC. 
// Licensed to SIPfoundry under a Contributor Agreement. 
//  
// $$ 
////////////////////////////////////////////////////////////////////////////// 

// Author: <NAME> <Alexander DOT <EMAIL>is AT SIPez DOT com>

// SYSTEM INCLUDES
// APPLICATION INCLUDES
#include "mp/MpBridgeAlgSimple.h"
#include "mp/MpMisc.h"

// EXTERNAL FUNCTIONS
// EXTERNAL VARIABLES
// CONSTANTS
// TYPEDEFS
// DEFINES
#define MAX_AMPLITUDE_ROUND  (1<<MP_AUDIO_SAMPLE_SIZE)

// MACROS
// STATIC VARIABLE INITIALIZATIONS

/* //////////////////////////////// PUBLIC //////////////////////////////// */

/* =============================== CREATORS =============================== */

MpBridgeAlgSimple::MpBridgeAlgSimple(int inputs, int outputs,
                                     UtlBoolean mixSilence,
                                     int samplesPerFrame)
: MpBridgeAlgBase(inputs, outputs, mixSilence)
, mpGainMatrix(NULL)
, mpMixAccumulator(NULL)
{
   // Allocate mix matrix.
   mpGainMatrix = new MpBridgeGain[maxInputs()*maxOutputs()];
   assert(mpGainMatrix != NULL);

   // Initially set matrix to inversed unity matrix, with zeros along
   // main diagonal.
   MpBridgeGain *pGain = mpGainMatrix;
   *pGain = MP_BRIDGE_GAIN_MUTED;
   pGain++;
   for (int row=0; row<maxOutputs()-1; row++)
   {
      for (int i=0; i<maxInputs(); i++)
      {
         *pGain = MP_BRIDGE_GAIN_PASSTHROUGH;
         pGain++;
      }
      *pGain = MP_BRIDGE_GAIN_MUTED;
      pGain++;
   }

   // Allocate temporary storage for mixing data.
   mpMixAccumulator = new MpBridgeAccum[samplesPerFrame];
   assert(mpMixAccumulator != NULL);
}

MpBridgeAlgSimple::~MpBridgeAlgSimple()
{
   delete[] mpGainMatrix;
   delete[] mpMixAccumulator;
}

/* ============================= MANIPULATORS ============================= */

UtlBoolean MpBridgeAlgSimple::doMix(MpBufPtr inBufs[], int inBufsSize,
                                    MpBufPtr outBufs[], int outBufsSize,
                                    int samplesPerFrame)
{
   // Initialize amplitudes if they haven't been initialized yet.
   if (mpPrevAmplitudes[0] < 0)
   {
      saveAmplitudes(inBufs, inBufsSize);
   }

   // Loop over all outputs and mix
   for (int outputNum=0; outputNum<outBufsSize; outputNum++)
   {
      MpBridgeGain *pInputGains = &mpGainMatrix[outputNum*maxInputs()];
      int32_t amplitude = 0;

      // Initialize accumulator
      for (int i=0; i<samplesPerFrame; i++)
      {
         mpMixAccumulator[i] = MPF_BRIDGE_FLOAT(0.0f);
      }

      // Get buffer for output data.
      MpAudioBufPtr pOutBuf = MpMisc.RawAudioPool->getBuffer();
      assert(pOutBuf.isValid());
      pOutBuf->setSamplesNumber(samplesPerFrame);
      pOutBuf->setSpeechType(MP_SPEECH_UNKNOWN);

      // Mix input data to accumulator
      for (int inputNum=0; inputNum<inBufsSize; inputNum++)
      {
         if (inBufs[inputNum].isValid() &&
             pInputGains[inputNum] != MP_BRIDGE_GAIN_MUTED)
         {
            MpAudioBufPtr pFrame = inBufs[inputNum];
            assert(pFrame->getSamplesNumber() == samplesPerFrame);
            MpBridgeGain prevAmplitude = mpPrevAmplitudes[inputNum];
            MpBridgeGain curAmplitude = pFrame->getAmplitude();

            if (  pInputGains[inputNum] == MP_BRIDGE_GAIN_PASSTHROUGH
               && prevAmplitude == MpSpeechParams::MAX_AMPLITUDE
               && curAmplitude == MpSpeechParams::MAX_AMPLITUDE)
            {
               MpDspUtils::add_IGain(pFrame->getSamplesPtr(), mpMixAccumulator,
                                     samplesPerFrame, MP_BRIDGE_FRAC_LENGTH);

               // Update output amplitude value.
               amplitude += MpSpeechParams::MAX_AMPLITUDE;
            }
            else if (curAmplitude == prevAmplitude)
            {
               // Calculate gain taking into account input amplitude.
               MpBridgeGain scaledGain = (MpBridgeGain)
                  (pInputGains[inputNum]*MAX_AMPLITUDE_ROUND)/curAmplitude;

               MpDspUtils::addMul_I(pFrame->getSamplesPtr(),
                                    scaledGain,
                                    mpMixAccumulator,
                                    samplesPerFrame);

               // Update output amplitude value.
               amplitude += (curAmplitude*scaledGain)>>MP_BRIDGE_FRAC_LENGTH;
            }
            else
            {
               // Calculate gain start and end taking into account previous
               // and current input amplitudes.
               MpBridgeGain scaledGainStart = (MpBridgeGain)
                  (pInputGains[inputNum]*MAX_AMPLITUDE_ROUND)/prevAmplitude;
               MpBridgeGain scaledGainEnd = (MpBridgeGain)
                  (pInputGains[inputNum]*MAX_AMPLITUDE_ROUND)/curAmplitude;

               MpDspUtils::addMulLinear_I(pFrame->getSamplesPtr(),
                                          scaledGainStart,
                                          scaledGainEnd,
                                          mpMixAccumulator,
                                          samplesPerFrame);

               // Update output amplitude value.
               MpBridgeGain scaledGainMax = MpDspUtils::maximum(scaledGainStart, scaledGainEnd);
               amplitude += (curAmplitude*scaledGainMax) >> MP_BRIDGE_FRAC_LENGTH;
            }
         }
      }

      // Set amplitude of the output frame.
      pOutBuf->setAmplitude(MPF_SATURATE16(amplitude));

      // Move data from accumulator to output.
      MpDspUtils::convert_Att(mpMixAccumulator, pOutBuf->getSamplesWritePtr(),
                              samplesPerFrame, MP_BRIDGE_FRAC_LENGTH);
      outBufs[outputNum].swap(pOutBuf);
   }
<commit_msg>Fix MpBridgeAlgSimple to correctly apply AGC and to set speech type on produced audio frames corectly.<commit_after>//  
// Copyright (C) 2008 SIPfoundry Inc. 
// Licensed by SIPfoundry under the LGPL license. 
//  
// Copyright (C) 2008 SIPez LLC. 
// Licensed to SIPfoundry under a Contributor Agreement. 
//  
// $$ 
////////////////////////////////////////////////////////////////////////////// 

// Author: <NAME> <Alexander DOT Chemeris AT SIPez DOT com>

// SYSTEM INCLUDES
// APPLICATION INCLUDES
#include "mp/MpBridgeAlgSimple.h"
#include "mp/MpMisc.h"

// EXTERNAL FUNCTIONS
// EXTERNAL VARIABLES
// CONSTANTS
// TYPEDEFS
// DEFINES
#define MAX_AMPLITUDE_ROUND  (1<<(MP_AUDIO_SAMPLE_SIZE-1))

// MACROS
// STATIC VARIABLE INITIALIZATIONS

/* //////////////////////////////// PUBLIC //////////////////////////////// */

/* =============================== CREATORS =============================== */

MpBridgeAlgSimple::MpBridgeAlgSimple(int inputs, int outputs,
                                     UtlBoolean mixSilence,
                                     int samplesPerFrame)
: MpBridgeAlgBase(inputs, outputs, mixSilence)
, mpGainMatrix(NULL)
, mpMixAccumulator(NULL)
{
   // Allocate mix matrix.
   mpGainMatrix = new MpBridgeGain[maxInputs()*maxOutputs()];
   assert(mpGainMatrix != NULL);

   // Initially set matrix to inversed unity matrix, with zeros along
   // main diagonal.
   MpBridgeGain *pGain = mpGainMatrix;
   *pGain = MP_BRIDGE_GAIN_MUTED;
   pGain++;
   for (int row=0; row<maxOutputs()-1; row++)
   {
      for (int i=0; i<maxInputs(); i++)
      {
         *pGain = MP_BRIDGE_GAIN_PASSTHROUGH;
         pGain++;
      }
      *pGain = MP_BRIDGE_GAIN_MUTED;
      pGain++;
   }

   // Allocate temporary storage for mixing data.
   mpMixAccumulator = new MpBridgeAccum[samplesPerFrame];
   assert(mpMixAccumulator != NULL);
}

MpBridgeAlgSimple::~MpBridgeAlgSimple()
{
   delete[] mpGainMatrix;
   delete[] mpMixAccumulator;
}

/* ============================= MANIPULATORS ============================= */

UtlBoolean MpBridgeAlgSimple::doMix(MpBufPtr inBufs[], int inBufsSize,
                                    MpBufPtr outBufs[], int outBufsSize,
                                    int samplesPerFrame)
{
   // Initialize amplitudes if they haven't been initialized yet.
   for (int i=0; i<inBufsSize; i++)
   {
      if (mpPrevAmplitudes[i] < 0 && inBufs[i].isValid())
      {
         MpAudioBufPtr pAudioBuf = inBufs[i];
         mpPrevAmplitudes[i] = pAudioBuf->getAmplitude();
      }
   }

//#define DEBUG_AGC
#ifdef DEBUG_AGC
   static int debugCounter = 0;
   debugCounter++;
   if (debugCounter % 50 == 0)
   {
      printf("\nInput:  ");
      for (int inputNum=0; inputNum<inBufsSize; inputNum++)
      {
         if (inBufs[inputNum].isValid())
         {
            MpAudioBufPtr pFrame = inBufs[inputNum];
            printf("%d ", pFrame->getAmplitude());
         }
         else
         {
            printf("- ");
         }
      }
      printf("\n");
      printf("Output: ");
   }
#endif

   // Loop over all outputs and mix
   for (int outputNum=0; outputNum<outBufsSize; outputNum++)
   {
      MpBridgeGain *pInputGains = &mpGainMatrix[outputNum*maxInputs()];
      int32_t amplitude = 0;

      // Initialize accumulator
      for (int i=0; i<samplesPerFrame; i++)
      {
         mpMixAccumulator[i] = MPF_BRIDGE_FLOAT(0.0f);
      }

      // Get buffer for output data.
      MpAudioBufPtr pOutBuf = MpMisc.RawAudioPool->getBuffer();
      assert(pOutBuf.isValid());
      pOutBuf->setSamplesNumber(samplesPerFrame);
      pOutBuf->setSpeechType(MP_SPEECH_SILENT);

      // Mix input data to accumulator
      for (int inputNum=0; inputNum<inBufsSize; inputNum++)
      {
         if (inBufs[inputNum].isValid() &&
             pInputGains[inputNum] != MP_BRIDGE_GAIN_MUTED)
         {
            MpAudioBufPtr pFrame = inBufs[inputNum];
            assert(pFrame->getSamplesNumber() == samplesPerFrame);

            // Do not mix muted audio.
            if (pFrame->getSpeechType() == MP_SPEECH_MUTED)
            {
               continue;
            }

            MpAudioSample prevAmplitude = mpPrevAmplitudes[inputNum];
            MpAudioSample curAmplitude = pFrame->getAmplitude();

            if (  pInputGains[inputNum] == MP_BRIDGE_GAIN_PASSTHROUGH
               && prevAmplitude == MpSpeechParams::MAX_AMPLITUDE
               && curAmplitude == MpSpeechParams::MAX_AMPLITUDE)
            {
               MpDspUtils::add_IGain(pFrame->getSamplesPtr(), mpMixAccumulator,
                                     samplesPerFrame, MP_BRIDGE_FRAC_LENGTH);

               // Update output amplitude value.
               amplitude += MpSpeechParams::MAX_AMPLITUDE;
#ifdef DEBUG_AGC
               if (  debugCounter % 50 == 0
                  && (outputNum==0 || outputNum==3) )
               {
                  printf("|P|");
               }
#endif
            }
            else if (curAmplitude == prevAmplitude)
            {
               // Calculate gain taking into account input amplitude.
               MpBridgeGain scaledGain = (MpBridgeGain)
                  ((pInputGains[inputNum]*MAX_AMPLITUDE_ROUND)/curAmplitude);

               MpDspUtils::addMul_I(pFrame->getSamplesPtr(),
                                    scaledGain,
                                    mpMixAccumulator,
                                    samplesPerFrame);

               // Update output amplitude value.
               amplitude += (curAmplitude*scaledGain)>>MP_BRIDGE_FRAC_LENGTH;
#ifdef DEBUG_AGC
               if (  debugCounter % 50 == 0
                  && (outputNum==0 || outputNum==3) )
               {
                  printf("|F:%d|", scaledGain);
               }
#endif
            }
            else
            {
               // Calculate gain start and end taking into account previous
               // and current input amplitudes.
               MpBridgeGain scaledGainStart = (MpBridgeGain)
                  ((pInputGains[inputNum]*MAX_AMPLITUDE_ROUND)/prevAmplitude);
               MpBridgeGain scaledGainEnd = (MpBridgeGain)
                  ((pInputGains[inputNum]*MAX_AMPLITUDE_ROUND)/curAmplitude);

               MpDspUtils::addMulLinear_I(pFrame->getSamplesPtr(),
                                          scaledGainStart,
                                          scaledGainEnd,
                                          mpMixAccumulator,
                                          samplesPerFrame);

               // Update output amplitude value.
               MpBridgeGain scaledGainMax = MpDspUtils::maximum(scaledGainStart, scaledGainEnd);
               amplitude += (curAmplitude*scaledGainMax) >> MP_BRIDGE_FRAC_LENGTH;
#ifdef DEBUG_AGC
               if (  debugCounter % 50 == 0
                  && (outputNum==0 || outputNum==3) )
               {
                  printf("|V:%d:%d|", scaledGainStart, scaledGainEnd);
               }
#endif
            }

            // Update output frame speech type.
            pOutBuf->setSpeechType(mixSpeechTypes(pOutBuf->getSpeechType(),
                                                  pFrame->getSpeechType()));
         }
      }

      // Set amplitude of the output frame.
      pOutBuf->setAmplitude(MPF_SATURATE16(amplitude));

#ifdef DEBUG_AGC
      if (  debugCounter % 50 == 0
         && (outputNum==0 || outputNum==3) )
      {
         printf("%d ", MPF_SATURATE16(amplitude));
      }
#endif

      // Move data from accumulator to output.
      MpDspUtils::convert_Att(mpMixAccumulator, pOutBuf->getSamplesWritePtr(),
                              samplesPerFrame, MP_BRIDGE_FRAC_LENGTH);
      outBufs[outputNum].swap(pOutBuf);
   }

#ifdef DEBUG_AGC
   if (debugCounter % 50 == 0)
   {
      printf("\n");
   }
#endif

{'fraction_non_alphanumeric': 0.13386115387434938, 'fraction_numerical': 0.00579136426948171, 'mean_word_length': 1.8492063492063493, 'pattern_counts': {'":': 0, '<': 26, '<?xml version=': 0, '>': 42, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 36, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7046935', 'n_tokens_mistral': 4286, 'n_tokens_neox': 4075, 'n_words': 751}