1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/mm/mmlibs/mmfw/Codecs/Src/MMFCodecCommon/MMFAudioPcm16ToImaAdpcmCodec.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,165 @@
1.4 +// Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +//
1.18 +
1.19 +#include "MMFAudioPcm16ToImaAdpcmCodec.h"
1.20 +
1.21 +
1.22 +EXPORT_C void TMMFAudioPcm16ToImaAdpcmCodec::SetState(const TMMFImaAdpcmCodecState& aState)
1.23 + {
1.24 + iState = aState ;
1.25 + }
1.26 +
1.27 +EXPORT_C const TMMFImaAdpcmCodecState& TMMFAudioPcm16ToImaAdpcmCodec::GetState()
1.28 + {
1.29 + return iState;
1.30 + }
1.31 +
1.32 +/**
1.33 +*
1.34 +* Convert
1.35 +* @param aSrc
1.36 +* @param aDst
1.37 +* @param aSamples
1.38 +*
1.39 +*/
1.40 +EXPORT_C void TMMFAudioPcm16ToImaAdpcmCodec::Convert(TUint8* aSrc, TUint8* aDst, TInt aSamples)
1.41 + {
1.42 + TInt val; // Current input sample value
1.43 + TInt sign; // Current adpcm sign bit
1.44 + TInt delta; // Current adpcm output value
1.45 + TInt diff; // Difference between val and valprev
1.46 + TInt step; // Stepsize
1.47 + TInt valpred; // Predicted value
1.48 + TInt vpdiff; // Current change to valpred
1.49 + TInt index; // Current step change index
1.50 +
1.51 + TInt16* srcPtr=REINTERPRET_CAST(TInt16*, aSrc);
1.52 + TInt16* src=srcPtr;
1.53 +
1.54 + iState.iPredicted = *aSrc++;
1.55 + iState.iPredicted |= STATIC_CAST(TInt16, ((*aSrc++) << 8));
1.56 +
1.57 + valpred = iState.iPredicted;
1.58 + index = iState.iIndex;
1.59 + ASSERT(index >= 0);
1.60 + step = KStepSizeTable[index];
1.61 +
1.62 + //Write block header
1.63 + *aDst++ = STATIC_CAST( TUint8, valpred);
1.64 + *aDst++ = STATIC_CAST( TUint8, valpred >> 8);
1.65 + *aDst++ = STATIC_CAST( TUint8, index);
1.66 + *aDst++ = 0; //reserved byte
1.67 + src++;
1.68 + aSamples --;
1.69 +
1.70 + for (; aSamples > 0; aSamples--)
1.71 + {
1.72 + val = *src;
1.73 + src++;
1.74 +
1.75 + step = KStepSizeTable[index];
1.76 +
1.77 + // Step 1 - compute difference with previous value
1.78 + diff = val - valpred;
1.79 + sign = (diff < 0) ? 8 : 0;
1.80 + if ( sign ) diff = (-diff);
1.81 +
1.82 + // Step 2 - Divide and clamp
1.83 + // Note:
1.84 + // This code *approximately* computes:
1.85 + // delta = diff*4/step;
1.86 + // vpdiff = (delta+0.5)*step/4;
1.87 + // but in shift step bits are dropped. The net result of this is
1.88 + // that even if you have fast mul/div hardware you cannot put it to
1.89 + // good use since the fixup would be too expensive.
1.90 + //
1.91 + delta = 0;
1.92 + vpdiff = (step >> 3);
1.93 +
1.94 + if ( diff >= step )
1.95 + {
1.96 + delta = 4;
1.97 + diff -= step;
1.98 + vpdiff += step;
1.99 + }
1.100 + step >>= 1;
1.101 + if ( diff >= step )
1.102 + {
1.103 + delta |= 2;
1.104 + diff -= step;
1.105 + vpdiff += step;
1.106 + }
1.107 + step >>= 1;
1.108 + if ( diff >= step )
1.109 + {
1.110 + delta |= 1;
1.111 + vpdiff += step;
1.112 + }
1.113 +
1.114 + // Step 3 - Update previous value
1.115 + if ( sign )
1.116 + valpred -= vpdiff;
1.117 + else
1.118 + valpred += vpdiff;
1.119 +
1.120 + // Step 4 - Clamp previous value to 16 bits
1.121 + if ( valpred > KClamp - 1 )
1.122 + valpred = KClamp - 1;
1.123 + else if ( valpred < - KClamp )
1.124 + valpred = - KClamp;
1.125 +
1.126 + // Step 5 - Assemble value, update index and step values
1.127 + delta |= sign;
1.128 +
1.129 + index += KIndexTable[delta];
1.130 + if ( index < 0 ) index = 0;
1.131 + if ( index > 88 ) index = 88;
1.132 +
1.133 + // Step 6 - Output value
1.134 + if (iBufferStep)
1.135 + iBuffer = delta & 0x0f;
1.136 + else
1.137 + *aDst++ = STATIC_CAST( TInt8, ((delta << 4) & 0xf0) | iBuffer);
1.138 +
1.139 + iBufferStep = !iBufferStep;
1.140 + }
1.141 +
1.142 + iState.iPredicted = STATIC_CAST(TInt16, valpred);
1.143 + iState.iIndex = STATIC_CAST(TUint8, index);
1.144 + }
1.145 +
1.146 +// IMA-ADPCM step variation table
1.147 +const TInt TMMFAudioPcm16ToImaAdpcmCodec::KIndexTable[] =
1.148 + {
1.149 + -1, -1, -1, -1, 2, 4, 6, 8,
1.150 + -1, -1, -1, -1, 2, 4, 6, 8
1.151 + };
1.152 +
1.153 +const TInt TMMFAudioPcm16ToImaAdpcmCodec::KStepSizeTable[] =
1.154 + {
1.155 + 7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
1.156 + 19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
1.157 + 50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
1.158 + 130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
1.159 + 337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
1.160 + 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
1.161 + 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
1.162 + 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
1.163 + 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
1.164 + };
1.165 +
1.166 +
1.167 +
1.168 +