videoeditorengine/audioeditorengine/src/RateConverter.cpp
changeset 9 d87d32eab1a9
parent 0 951a5db380a0
equal deleted inserted replaced
0:951a5db380a0 9:d87d32eab1a9
     1 /*
       
     2 * Copyright (c) 2010 Ixonos Plc.
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of the "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - Initial contribution
       
    11 *
       
    12 * Contributors:
       
    13 * Ixonos Plc
       
    14 *
       
    15 * Description:  
       
    16 *
       
    17 */
       
    18 
       
    19 
       
    20 
       
    21 #include "RateConverter.h"
       
    22 
       
    23 
       
    24 // CONSTANTS
       
    25 
       
    26 
       
    27 
       
    28 // MACROS
       
    29 
       
    30 // Debug print macro
       
    31 #if defined _DEBUG 
       
    32 #include <e32svr.h>
       
    33 #define PRINT(x) RDebug::Print x;
       
    34 #else
       
    35 #define PRINT(x)
       
    36 #endif
       
    37 
       
    38 // -----------------------------------------------------------------------------
       
    39 // CRateConverter::NewL
       
    40 // Two-phased constructor.
       
    41 // -----------------------------------------------------------------------------
       
    42 //
       
    43 CRateConverter* CRateConverter::NewL(TInt aFromSampleRate, TInt aToSampleRate, TInt aFromChannels, TInt aToChannels)                          
       
    44     {
       
    45     CRateConverter* self = NewLC(aFromSampleRate, aToSampleRate, aFromChannels, aToChannels);
       
    46     CleanupStack::Pop(self);
       
    47     return self;
       
    48     }
       
    49 
       
    50 // -----------------------------------------------------------------------------
       
    51 // CRateConverter::NewLC
       
    52 // Two-phased constructor.
       
    53 // -----------------------------------------------------------------------------
       
    54 //
       
    55 CRateConverter* CRateConverter::NewLC(TInt aFromSampleRate, TInt aToSampleRate, TInt aFromChannels, TInt aToChannels)                             
       
    56     {
       
    57     CRateConverter* self = new (ELeave) CRateConverter(aFromSampleRate, aToSampleRate, aFromChannels, aToChannels);
       
    58     CleanupStack::PushL(self);
       
    59     self->ConstructL();
       
    60     return self;
       
    61     }
       
    62 
       
    63 // -----------------------------------------------------------------------------
       
    64 // CRateConverter::ConstructL
       
    65 // Symbian 2nd phase constructor can leave.
       
    66 // -----------------------------------------------------------------------------
       
    67 //    
       
    68 void CRateConverter::ConstructL()
       
    69     {
       
    70     }
       
    71 
       
    72 // -----------------------------------------------------------------------------
       
    73 // CRateConverter::CRateConverter
       
    74 // C++ default constructor can NOT contain any code, that
       
    75 // might leave.
       
    76 // -----------------------------------------------------------------------------
       
    77 //
       
    78 CRateConverter::CRateConverter(TInt aFromSampleRate, TInt aToSampleRate, TInt aFromChannels, TInt aToChannels)
       
    79  : iFromSampleRate(aFromSampleRate), iToSampleRate(aToSampleRate),
       
    80    iFromChannels(aFromChannels), iToChannels(aToChannels)
       
    81     {
       
    82     // Select the smaller of the two
       
    83     iChannels = (iFromChannels < iToChannels) ? iFromChannels : iToChannels;
       
    84     }
       
    85 
       
    86 // ---------------------------------------------------------
       
    87 // CRateConverter::~CRateConverter
       
    88 // Destructor
       
    89 // ---------------------------------------------------------
       
    90 //
       
    91 CRateConverter::~CRateConverter()
       
    92     {
       
    93     if (iChild)
       
    94         {
       
    95         delete iChild;
       
    96         iChild = NULL;
       
    97         }
       
    98     
       
    99     if (iConverter)
       
   100         {
       
   101     	delete iConverter;
       
   102     	iConverter = NULL;
       
   103         }
       
   104         
       
   105     if (iInBuffer)
       
   106         {
       
   107         for (TInt i = 0; (i < iChannels) && iInBuffer[i]; i++)
       
   108             {
       
   109     		User::Free(iInBuffer[i]);
       
   110     		iInBuffer[i] = NULL;
       
   111             }
       
   112     	User::Free(iInBuffer);
       
   113     	iInBuffer = NULL;
       
   114         }
       
   115     
       
   116     if (iOutBuffer)
       
   117         {
       
   118         for (TInt i = 0; (i < iChannels) && iOutBuffer[i]; i++)
       
   119             {
       
   120     		User::Free(iOutBuffer[i]);
       
   121     		iOutBuffer[i] = NULL;
       
   122             }
       
   123     	User::Free(iOutBuffer);
       
   124     	iOutBuffer = NULL;
       
   125         }
       
   126         
       
   127     if (iScratchBuffer)
       
   128         {
       
   129         User::Free(iScratchBuffer);
       
   130         iScratchBuffer = NULL;
       
   131         }
       
   132     }
       
   133 
       
   134 // -----------------------------------------------------------------------------
       
   135 // CRateConverter::InitL
       
   136 // Initialize the rate converter
       
   137 // -----------------------------------------------------------------------------
       
   138 //  
       
   139 TBool CRateConverter::InitL(TInt aInputBufferSize)
       
   140     {
       
   141     PRINT((_L("CRateConverter::InitL() In")));
       
   142     
       
   143     if (iConverter)
       
   144         {
       
   145         PRINT((_L("CRateConverter::InitL() Already initialized")));
       
   146         return EFalse;
       
   147         }
       
   148     
       
   149     // Check that the input and output are either mono or stereo    
       
   150     if ( ((iFromChannels != 1) && (iFromChannels != 2)) ||
       
   151          ((iToChannels != 1) && (iToChannels != 2)) )
       
   152         {
       
   153         PRINT((_L("CRateConverter::InitL() Only mono and stereo are supported for input/output")));
       
   154         return EFalse;
       
   155         }
       
   156         
       
   157     if (iFromSampleRate == iToSampleRate)
       
   158         {
       
   159         // No sample rate conversion needed so do only channel conversion
       
   160         iInputBlockSize = iOuputBlockSize = aInputBufferSize;
       
   161         
       
   162         PRINT((_L("CRateConverter::InitL() Out")));
       
   163         return ETrue;
       
   164         }
       
   165         
       
   166     if (!DoInitL(aInputBufferSize))
       
   167         {
       
   168         return EFalse;
       
   169         }
       
   170     
       
   171     // Allocate internal input buffer
       
   172     iInBuffer = (TInt16**) User::AllocL(iChannels * sizeof(TInt16*));
       
   173     
       
   174     for (TInt i = 0; i < iChannels; i++)
       
   175         {
       
   176         iInBuffer[i] = (TInt16*) User::AllocL(iInputBlockSize * sizeof(TInt16));
       
   177         }
       
   178         
       
   179     PRINT((_L("CRateConverter::InitL() Out")));     
       
   180     return ETrue;
       
   181     }
       
   182 
       
   183 // -----------------------------------------------------------------------------
       
   184 // CRateConverter::DoInitL
       
   185 // Does internal initialization
       
   186 // -----------------------------------------------------------------------------
       
   187 //    
       
   188 TBool CRateConverter::DoInitL(TInt aInputBufferSize)
       
   189     {
       
   190     iInputBlockSize = aInputBufferSize;
       
   191     
       
   192     // Supported direct conversions:
       
   193     //
       
   194     // 16000 ->  8000: /2
       
   195     // 24000 ->  8000: /3
       
   196     //
       
   197     // 8000  -> 16000: *2
       
   198     // 32000 -> 16000: /2
       
   199     // 48000 -> 16000: /3
       
   200     //
       
   201     // 16000 -> 48000: *3
       
   202     // 24000 -> 48000: *2
       
   203     // 32000 -> 48000: *3/2
       
   204     // 44100 -> 48000: *i
       
   205     
       
   206     // Try to use direct conversion
       
   207     iConverter = RESAMPLER_RateConversionInputDrivenInt16::New(iFromSampleRate, iToSampleRate, iChannels);
       
   208     
       
   209     if (!iConverter)
       
   210         {
       
   211         // Direct conversion is not possible so multi phase conversion is needed
       
   212 
       
   213         // Conversions are done in the following order:
       
   214         // (*i means 160/147 conversion)
       
   215         //
       
   216         // 11025 ->  8000: *i *2 /3    (three phase)
       
   217         // 22050 ->  8000: *i /3       (two phase)
       
   218         // 32000 ->  8000: /2 /2       (two phase)
       
   219         // 44100 ->  8000: *i /3 /2    (three phase)
       
   220         // 48000 ->  8000: /3 /2       (two phase)
       
   221         // 
       
   222         // 11025 -> 16000: *2 *2 *i /3 (four phase)
       
   223         // 22050 -> 16000: *2 *i /3    (three phase)
       
   224         // 24000 -> 16000: *2 /3       (two phase)
       
   225         // 44100 -> 16000: *i /3       (two phase)
       
   226         // 
       
   227         // 8000  -> 48000: *3 *2       (two phase)
       
   228         // 11025 -> 48000: *2 *2 *i    (three phase)
       
   229         // 22050 -> 48000: *2 *i       (two phase)
       
   230         
       
   231         // Check the last phase in the chain and make the decision where the child should convert
       
   232         if( ((iToSampleRate == 8000) && ((iFromSampleRate == 11025) || (iFromSampleRate == 22050))) ||
       
   233             (iToSampleRate == 16000) )
       
   234             {
       
   235             // Last phase is /3 so the child converter needs to do
       
   236             // conversion from iFromSampleRate to iToSampleRate*3
       
   237             
       
   238             // Create the child converter
       
   239             iChild = CRateConverter::NewL(iFromSampleRate, iToSampleRate * 3, iChannels, iChannels);
       
   240             if (!iChild->DoInitL(aInputBufferSize))
       
   241                 {
       
   242                 return EFalse;
       
   243                 }
       
   244             
       
   245             // Update sample rates and buffer sizes
       
   246             iFromSampleRate = iToSampleRate * 3;
       
   247             aInputBufferSize = iChild->GetOutputBufferSize();
       
   248         
       
   249             // Try to create our converter  
       
   250             iConverter = RESAMPLER_RateConversionInputDrivenInt16::New(iFromSampleRate, iToSampleRate, iChannels);
       
   251             if (!iConverter)
       
   252                 {
       
   253                 return EFalse;
       
   254                 }
       
   255             }
       
   256         else if( (iToSampleRate == 8000) )
       
   257             {
       
   258             // Last phase is /2 so the child converter needs to do
       
   259             // conversion from iFromSampleRate to iToSampleRate*2
       
   260             
       
   261             // Create the child converter
       
   262             iChild = CRateConverter::NewL(iFromSampleRate, iToSampleRate * 2, iChannels, iChannels);
       
   263             if (!iChild->DoInitL(aInputBufferSize))
       
   264                 {
       
   265                 return EFalse;
       
   266                 }
       
   267             
       
   268             // Update sample rates and buffer sizes
       
   269             iFromSampleRate = iToSampleRate * 2;
       
   270             aInputBufferSize = iChild->GetOutputBufferSize();
       
   271             
       
   272             // Try to create our converter  
       
   273             iConverter = RESAMPLER_RateConversionInputDrivenInt16::New(iFromSampleRate, iToSampleRate, iChannels);
       
   274             if (!iConverter)
       
   275                 {
       
   276                 return EFalse;
       
   277                 }
       
   278             }
       
   279         else if( ((iToSampleRate == 48000) && ((iFromSampleRate == 11025) || (iFromSampleRate == 22050))) )
       
   280             {
       
   281             // Last phase is *i so the child converter needs to do
       
   282             // conversion from iFromSampleRate to 44100
       
   283             
       
   284             // Create the child converter
       
   285             iChild = CRateConverter::NewL(iFromSampleRate, 44100, iChannels, iChannels);
       
   286             if (!iChild->DoInitL(aInputBufferSize))
       
   287                 {
       
   288                 return EFalse;
       
   289                 }
       
   290             
       
   291             // Update sample rates and buffer sizes
       
   292             iFromSampleRate = 44100;
       
   293             aInputBufferSize = iChild->GetOutputBufferSize();
       
   294             
       
   295             // Try to create our converter  
       
   296             iConverter = RESAMPLER_RateConversionInputDrivenInt16::New(iFromSampleRate, iToSampleRate, iChannels);
       
   297             if (!iConverter)
       
   298                 {
       
   299                 return EFalse;
       
   300                 }
       
   301             }
       
   302         else if( ((iFromSampleRate == 11025) && ((iToSampleRate == 24000) || (iToSampleRate == 44100))) ||
       
   303                  ((iFromSampleRate == 8000) && (iToSampleRate == 48000)) )
       
   304             {
       
   305             // Last phase is *2 so the child converter needs to do
       
   306             // conversion from iFromSampleRate to iToSampleRate/2
       
   307             
       
   308             // Create the child converter
       
   309             iChild = CRateConverter::NewL(iFromSampleRate, iToSampleRate / 2, iChannels, iChannels);
       
   310             if (!iChild->DoInitL(aInputBufferSize))
       
   311                 {
       
   312                 return EFalse;
       
   313                 }
       
   314                 
       
   315             // Update sample rates and buffer sizes
       
   316             iFromSampleRate = iToSampleRate / 2;
       
   317             aInputBufferSize = iChild->GetOutputBufferSize();
       
   318             
       
   319             // Try to create our converter  
       
   320             iConverter = RESAMPLER_RateConversionInputDrivenInt16::New(iFromSampleRate, iToSampleRate, iChannels);
       
   321             if (!iConverter)
       
   322                 {
       
   323                 return EFalse;
       
   324                 }
       
   325             }
       
   326         else
       
   327             {
       
   328             // We don't know how to convert, probably this is an unsupported conversion
       
   329             PRINT((_L("CRateConverter::DoInitL() Can not convert from %d to %d"), iFromSampleRate, iToSampleRate));
       
   330             return EFalse;
       
   331             }
       
   332         }
       
   333         
       
   334     if (!iConverter->InitInputDriven())
       
   335         {
       
   336         PRINT((_L("CRateConverter::InitL() Failed to initialize converter")));
       
   337         return EFalse;
       
   338         }
       
   339     
       
   340     // Set scratch memory buffer for converter    
       
   341     size_t scratchBufferSize = iConverter->ScratchMemoryNeedInputDriven(aInputBufferSize);
       
   342     
       
   343     if (scratchBufferSize == 0)
       
   344         {
       
   345         PRINT((_L("CRateConverter::InitL() Scratch buffer size is too big")));
       
   346         return EFalse;
       
   347         }
       
   348         
       
   349     iScratchBuffer = (TInt8*) User::AllocL(scratchBufferSize);
       
   350     iConverter->SetScratchBufferInputDriven((char *)iScratchBuffer);
       
   351         
       
   352     iOuputBlockSize = iConverter->MaxOutputSampleCount(aInputBufferSize);
       
   353     
       
   354     // Allocate internal output buffer
       
   355     iOutBuffer = (TInt16**) User::AllocL(iChannels * sizeof(TInt16*));
       
   356     
       
   357     for (TInt i = 0; i < iChannels; i++)
       
   358         {
       
   359         iOutBuffer[i] = (TInt16*) User::AllocL(iOuputBlockSize * sizeof(TInt16));
       
   360         }
       
   361         
       
   362     iConverter->SetQualityInputDriven(RESAMPLER_RATE_CONVERSION_QUALITY_STANDARD);
       
   363     
       
   364     PRINT((_L("CRateConverter::DoInitL() Convert %d -> %d Hz, %d -> %d channels"), iFromSampleRate, iToSampleRate, iFromChannels, iToChannels));
       
   365     
       
   366     PRINT((_L("CRateConverter::DoInitL() Input buffer %d, Output buffer %d"), iInputBlockSize, iOuputBlockSize));
       
   367     
       
   368     return ETrue;
       
   369     }
       
   370 
       
   371 // -----------------------------------------------------------------------------
       
   372 // CRateConverter::ConvertBufferL
       
   373 // Does rate and channel conversion for given buffer
       
   374 // -----------------------------------------------------------------------------
       
   375 //    
       
   376 TInt CRateConverter::ConvertBufferL(TInt16* aInput, TInt16* aOutput, TInt aInputSampleCount)
       
   377     {
       
   378     if (iFromSampleRate == iToSampleRate)
       
   379         {
       
   380         // No sample rate conversion needed
       
   381         if (iFromChannels == iToChannels)
       
   382             {
       
   383             // No channel conversion needed either so copy input directly to output
       
   384             Mem::Copy(aOutput, aInput, aInputSampleCount * 2 * iFromChannels);
       
   385             }    
       
   386         else if (iFromChannels == 2)
       
   387             {
       
   388             // Convert stereo to mono
       
   389             for (TInt i = 0; i < aInputSampleCount; ++i)
       
   390                 {
       
   391                 // Average left and right samples
       
   392                 aOutput[i] = (aInput[2*i + 0] + aInput[2*i + 1]) >> 1;
       
   393                 }
       
   394             }
       
   395         else if (iToChannels == 2)
       
   396             {
       
   397             // Convert mono to stereo
       
   398             for (TInt i = 0; i < aInputSampleCount; ++i)
       
   399                 {
       
   400                 // Duplicate left channel to right channel
       
   401                 aOutput[2*i + 0] = aInput[i];
       
   402                 aOutput[2*i + 1] = aInput[i];
       
   403                 }
       
   404             }
       
   405         
       
   406         return aInputSampleCount;
       
   407         }
       
   408     
       
   409     if (!iConverter)
       
   410         {
       
   411         PRINT((_L("CRateConverter::ConvertBufferL() Not initialized")));
       
   412         User::Leave(KErrNotReady);
       
   413         }
       
   414     
       
   415     if (aInputSampleCount > iInputBlockSize)
       
   416         {
       
   417         PRINT((_L("CRateConverter::ConvertBufferL() Too many input samples")));
       
   418         User::Leave(KErrArgument);
       
   419         }
       
   420     
       
   421     // Copy to input buffers and do channel conversion if needed    
       
   422     if (iChannels == 2)
       
   423         {
       
   424         // Both channels are stereo so copy both channels to own buffers
       
   425         for (TInt i = 0; i < aInputSampleCount; ++i)
       
   426             {
       
   427             iInBuffer[0][i] = aInput[2*i + 0];
       
   428             iInBuffer[1][i] = aInput[2*i + 1];
       
   429             }
       
   430         }
       
   431     else if (iFromChannels == 2)
       
   432         {
       
   433         // Source is stereo so convert stereo to mono
       
   434         for (TInt i = 0; i < aInputSampleCount; ++i)
       
   435             {
       
   436             // Average left and right samples
       
   437             iInBuffer[0][i] = (aInput[2*i + 0] + aInput[2*i + 1]) >> 1;
       
   438             }
       
   439         }
       
   440     else
       
   441         {
       
   442         // Source is mono so copy it directly
       
   443         Mem::Copy(iInBuffer[0], aInput, aInputSampleCount * 2);
       
   444         }
       
   445         
       
   446     TInt outputSampleCount = DoConvertL(iInBuffer, aInputSampleCount);
       
   447     
       
   448     // Copy to output buffers and do channel conversion if needed    
       
   449     if (iChannels == 2)
       
   450         {
       
   451         // Both channels are stereo so copy both channels to own buffers
       
   452         for (TInt i = 0; i < outputSampleCount; ++i)
       
   453             {
       
   454             aOutput[2*i + 0] = iOutBuffer[0][i];
       
   455             aOutput[2*i + 1] = iOutBuffer[1][i];
       
   456             }
       
   457         }
       
   458     else if (iToChannels == 2)
       
   459         {
       
   460         // Ouput is stereo so convert mono to stereo
       
   461         for (TInt i = 0; i < outputSampleCount; ++i)
       
   462             {
       
   463             // Duplicate left channel to right channel
       
   464             aOutput[2*i + 0] = iOutBuffer[0][i];
       
   465             aOutput[2*i + 1] = iOutBuffer[0][i];
       
   466             }
       
   467         }
       
   468     else
       
   469         {
       
   470         // Output is mono so copy it directly
       
   471         Mem::Copy(aOutput, iOutBuffer[0], outputSampleCount * 2);
       
   472         }
       
   473         
       
   474     PRINT((_L("CRateConverter::ConvertBufferL() Output %d samples"), outputSampleCount));
       
   475          
       
   476     return outputSampleCount;
       
   477     }
       
   478 
       
   479 // -----------------------------------------------------------------------------
       
   480 // CRateConverter::DoConvertL
       
   481 // Does the actual conversion
       
   482 // -----------------------------------------------------------------------------
       
   483 //     
       
   484 TInt CRateConverter::DoConvertL(TInt16** aInput, TInt aInputSampleCount)
       
   485     {
       
   486     if (iChild)
       
   487         {
       
   488         // If we have a child then we need to do a multi phase conversion
       
   489         TInt tempSampleCount = iChild->DoConvertL(aInput, aInputSampleCount);
       
   490         
       
   491         // Get pointer to child's output and use it as an input
       
   492         TInt16** tempBuf = iChild->GetOutputBuffer();
       
   493         
       
   494         return iConverter->ProcessFromInput(iOutBuffer, tempBuf, tempSampleCount);
       
   495         }
       
   496     else
       
   497         {
       
   498         // Otherwise process directly from input to output
       
   499         return iConverter->ProcessFromInput(iOutBuffer, aInput, aInputSampleCount);
       
   500         }
       
   501     }
       
   502     
       
   503