videoeditorengine/audioeditorengine/resampler/src/resampler_sinc_conv_44_to_48_int16.cpp
author Mikael Laine <mikael.laine@ixonos.com>
Fri, 29 Jan 2010 14:08:33 +0200
changeset 0 951a5db380a0
permissions -rw-r--r--
Committing the Video Editor package under the Eclipse Public License

/*
* Copyright (c) 2010 Ixonos Plc.
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of the "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - Initial contribution
*
* Contributors:
* Ixonos Plc
*
* Description:
*
*/


#include "resampler_sinc_conv_44_to_48_int16.h"
#include "resampler_clip.h"
#include "resampler_sinc_conv_44_to_48_tables_economy.h"
#include "resampler_sinc_conv_44_to_48_tables_standard.h"
#include "resampler_sinc_conv_44_to_48_tables_premium.h"

#include <string.h>

#include "resampler_sinc_conv_filter_int16.h"

/*
 * The amount of zero crossings in positive or negative
 * side of the sinc function. Because of filter symmetry
 * the amount of filter taps used in convolution is
 * zero crossings * 2.
 */
static const int LC_MAX_ZERO_CROSSINGS = RESAMPLER_44_TO_48_ZERO_CROSSINGS_PREMIUM;

static const int LC_BUFFER_ACCESS_OUTPUT = LC_MAX_ZERO_CROSSINGS;

/*
 * The number of filters needed in 44.1 to 48 kHz sinc interpolation
 * sampling rate conversion. Filter symmetry is utilized.
 */
static const int LC_FILTER_COUNT = 160;

/*
 * Calculated as 160-147.
 * 147/160 is the smallest ratio of 44100/48000.
 * Used as a hop increment in the filter table defined below.
 */
static const int LC_MATRIX_HOP_SIZE = 13;       

/*
 * This constant is calculated as ceil(2^23/160).
 * and used in InSamplesNeeded() method to 
 * avoid the division by 160. The result of the multiplication
 * has to be shifted afterwards by 23 bits right.
 */
static const int LC_SAMPLE_COUNT_MULT = 52429;   

/** Do not remove! LC_MAX_BLOCK_SIZE used in assert!
 */
#if 0
/* 
 * M_INPUT_COUNT_MULT * (6289*13+160) = 4294826393 (0xfffdd999).
 * 6289 is the largest number that fits 32 bits in the
 * input sample count multiplication method.
 */
static const int LC_MAX_BLOCK_SIZE = 6289;      
#endif // 0


RESAMPLER_SincConv44To48Int16::RESAMPLER_SincConv44To48Int16(int channelCount) :
m_memBuffers(0),
m_scratchBuffer(0),
m_channelCount(channelCount),
m_blockSize(0),
m_channelEnabled(0),
m_inputSamples(0),
m_index1(LC_FILTER_COUNT),
m_index2(0),
m_zeroCrossings(RESAMPLER_44_TO_48_ZERO_CROSSINGS_STANDARD),
m_filterMatrix(RESAMPLER_44_TO_48_FILTERS_STANDARD)
{
}


RESAMPLER_SincConv44To48Int16::~RESAMPLER_SincConv44To48Int16()
{
    DeInit();
}

bool RESAMPLER_SincConv44To48Int16::InitInputDriven()
{
    return Init();
}


bool RESAMPLER_SincConv44To48Int16::InitOutputDriven()
{
    return Init();
}

bool RESAMPLER_SincConv44To48Int16::Init()
{
    int i(0);

    m_memBuffers = new int16 *[m_channelCount];
    if (!m_memBuffers)
    {
        return false;
    }

    for (i = 0; i < m_channelCount; i++) 
    {
        m_memBuffers[i] = 0;
    }

    m_channelEnabled = new bool[m_channelCount];
    if (!m_channelEnabled)
    {
        DeInit();
        return false;
    }
    for (i = 0; i < m_channelCount; i++) 
    {
        m_channelEnabled[i] = true;
    }

    for (i = 0; i < m_channelCount; i++) 
    {
        m_memBuffers[i] = new int16[LC_MAX_ZERO_CROSSINGS * 2];
        if (!m_memBuffers[i])
        {
            DeInit();
            return false;
        }
        memset(m_memBuffers[i], 0, sizeof(int16) * (LC_MAX_ZERO_CROSSINGS * 2));
    }

    return true;
}

void 
RESAMPLER_SincConv44To48Int16::DeInit()
{
    if (m_channelCount)
    {
        for (int i = 0; i < m_channelCount; i++)
        {
            delete [] m_memBuffers[i];
        }
        delete [] m_memBuffers;
        delete [] m_channelEnabled;
    }
}

bool 
RESAMPLER_SincConv44To48Int16::SetQualityInputDriven(int mode)
{
    return SetQualityOutputDriven(mode);
}

bool 
RESAMPLER_SincConv44To48Int16::SetQualityOutputDriven(int mode)
{
    switch (mode)
    {
    case RESAMPLER_RATE_CONVERSION_QUALITY_ECONOMY:
        m_zeroCrossings = RESAMPLER_44_TO_48_ZERO_CROSSINGS_ECONOMY;
        m_filterMatrix  = RESAMPLER_44_TO_48_FILTERS_ECONOMY;
        break;
    case RESAMPLER_RATE_CONVERSION_QUALITY_STANDARD:
        m_zeroCrossings = RESAMPLER_44_TO_48_ZERO_CROSSINGS_STANDARD;
        m_filterMatrix  = RESAMPLER_44_TO_48_FILTERS_STANDARD;
        break;
    case RESAMPLER_RATE_CONVERSION_QUALITY_PREMIUM:
        m_zeroCrossings = RESAMPLER_44_TO_48_ZERO_CROSSINGS_PREMIUM;
        m_filterMatrix  = RESAMPLER_44_TO_48_FILTERS_PREMIUM;
        break;
    default:
        return false;
    }
    return true;
}

void 
RESAMPLER_SincConv44To48Int16::EnableChannelInputDriven(int channel)
{
    EnableChannelOutputDriven(channel);
}


void 
RESAMPLER_SincConv44To48Int16::DisableChannelInputDriven(int channel)
{
    DisableChannelOutputDriven(channel);
}


void 
RESAMPLER_SincConv44To48Int16::EnableChannelOutputDriven(int channel)
{
    m_channelEnabled[channel] = true;
}


void 
RESAMPLER_SincConv44To48Int16::DisableChannelOutputDriven(int channel)
{
    m_channelEnabled[channel] = false;
}

size_t 
RESAMPLER_SincConv44To48Int16::ScratchMemoryNeedInputDriven(int maxInputBlockSize) const
{
    /** 6289 == LC_MAX_BLOCK_SIZE
     */
    if (maxInputBlockSize > 6289 * 44100.0/48000.0)
        {
        return 0;
        }

    return sizeof(int16) * (LC_MAX_ZERO_CROSSINGS * 2 + maxInputBlockSize);
}

void 
RESAMPLER_SincConv44To48Int16::SetScratchBufferInputDriven(char *buffer)
{
    m_scratchBuffer = (int16 *)buffer;
}

size_t 
RESAMPLER_SincConv44To48Int16::ScratchMemoryNeedOutputDriven(int maxOutputBlockSize) const
{
    int blockSize =  (int)((maxOutputBlockSize * 44100.0/48000.0) + 1); 
    
    return ScratchMemoryNeedInputDriven(blockSize);
}

void 
RESAMPLER_SincConv44To48Int16::SetScratchBufferOutputDriven(char *buffer)
{
    m_scratchBuffer = (int16 *)buffer;
}



int 
RESAMPLER_SincConv44To48Int16::MaxInputSampleCount(int outSamples) const
{ 
    return (int)((outSamples * (44100.0 / 48000.0)) + 1); 
}


int 
RESAMPLER_SincConv44To48Int16::InSamplesNeeded(int outSamples)
{
    m_inputSamples = outSamples - ((LC_SAMPLE_COUNT_MULT * (outSamples*13+m_index2)) >> 23);
 
    return m_inputSamples;
}

int 
RESAMPLER_SincConv44To48Int16::MaxOutputSampleCount(int inSamples) const
{ 
    return (int)(inSamples * 160.0 / 147.0 + 1.0); 
}


int RESAMPLER_SincConv44To48Int16::ProcessFromInput(int16 *outputBuffers[], 
                                              int16 *inputBuffers[], 
                                              int inSamples)
{
    int outSamples = (int)((inSamples * 160.0 + m_index2) / 147.0);
    m_inputSamples = inSamples;
    return ProcessToOutput(outputBuffers, inputBuffers, outSamples);
}

int 
RESAMPLER_SincConv44To48Int16::ProcessToOutput(int16 *outputBuffers[], 
                                         int16 *inputBuffers[], 
                                         int outSamples)
{
    static const int FILTER_LENGTH = 2 * LC_MAX_ZERO_CROSSINGS;
	int i, j;
    int index1 = m_index1;
    int index2 = m_index2;

    for (i = 0; i < m_channelCount; i++) 
    {
        if (!m_channelEnabled[i])
        {
            break;
        }

        int16 *tempBuf = m_scratchBuffer;
        int16 *outBuf  = outputBuffers[i];
        index1 = m_index1; /* 160 SRC filter number */
        index2 = m_index2; /* 0 */
        
        int state = 0;

        memcpy(m_scratchBuffer, 
               m_memBuffers[i], 
               FILTER_LENGTH * sizeof(int16));

        // Read samples into memory
        memcpy(tempBuf + FILTER_LENGTH, 
               inputBuffers[i], 
               m_inputSamples * sizeof(int16));

        // Do band limited interpolation and set the result into 
        // every index in the output buffer. 
        for (j = 0; j < outSamples; j++) 
        {
            index1 -= LC_MATRIX_HOP_SIZE; /* -13 */ 
            index2 += LC_MATRIX_HOP_SIZE;  /* +13 */ 

            if (index1 <= 0)
            {
                index1 += LC_FILTER_COUNT; /* +160 */
                index2 -= LC_FILTER_COUNT;  /* -160 */
                state++;
            }

            /*lint -e{662} */
            const int16 *filterPtr1 = m_filterMatrix + index1 * m_zeroCrossings;
            const int16 *filterPtr2 = m_filterMatrix + index2 * m_zeroCrossings;
              
            int32 newSample = 
                RESAMPLER_SincConvFilterInt16(tempBuf + LC_BUFFER_ACCESS_OUTPUT - state + j,
                                        filterPtr1,
                                        filterPtr2,
                                        m_zeroCrossings);
             
            // round and shift down
            outBuf[j] = (int16)RESAMPLER_Clip16((newSample + 16384) >> 15);
        }
        
        // Copy the newest samples to the beginning of the buffer
        memcpy(m_memBuffers[i], 
               m_scratchBuffer + m_inputSamples, 
               FILTER_LENGTH * sizeof(int16));       
    }

    m_index1 = index1;
    m_index2 = index2;

	return outSamples;
}