|
1 // Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // |
|
15 |
|
16 #include "mmfpcm16ToImaAdpcm.h" |
|
17 |
|
18 /** |
|
19 * |
|
20 * NewL |
|
21 * |
|
22 */ |
|
23 CMMFPcm16ToImaAdpcmHwDevice* CMMFPcm16ToImaAdpcmHwDevice::NewL() |
|
24 { |
|
25 CMMFPcm16ToImaAdpcmHwDevice* self=new(ELeave) CMMFPcm16ToImaAdpcmHwDevice(); |
|
26 CleanupStack::PushL(self); |
|
27 self->ConstructL(); |
|
28 CleanupStack::Pop(self); |
|
29 return self; |
|
30 } |
|
31 |
|
32 /** |
|
33 * |
|
34 * ~CMMFPcm16ToAlawHwDevice |
|
35 * |
|
36 */ |
|
37 CMMFPcm16ToImaAdpcmHwDevice::~CMMFPcm16ToImaAdpcmHwDevice() |
|
38 { |
|
39 } |
|
40 |
|
41 /** |
|
42 * |
|
43 * ConstructL |
|
44 * |
|
45 */ |
|
46 void CMMFPcm16ToImaAdpcmHwDevice::ConstructL() |
|
47 { |
|
48 iCodec = new (ELeave) CMMFPcm16ToImaAdpcmCodec(); |
|
49 } |
|
50 |
|
51 /** |
|
52 * |
|
53 * Codec |
|
54 * |
|
55 */ |
|
56 CMMFSwCodec &CMMFPcm16ToImaAdpcmHwDevice::Codec() |
|
57 { |
|
58 return *iCodec; |
|
59 } |
|
60 |
|
61 /** |
|
62 * |
|
63 * ResetL |
|
64 * |
|
65 */ |
|
66 void CMMFPcm16ToImaAdpcmCodec::ResetL() |
|
67 { |
|
68 //Reset the actual codec |
|
69 TMMFImaAdpcmCodecState state; |
|
70 state.iIndex = 0; |
|
71 state.iPredicted = 0; |
|
72 iPcm16ToImaAdpcm.SetState(state); |
|
73 } |
|
74 |
|
75 /** |
|
76 * |
|
77 * ProcessL |
|
78 * @param aSrc src buffer |
|
79 * @param aDst destination buffer |
|
80 * @return CMMFSwCodec::TCodecProcessResult |
|
81 * This function converts PCM samples to IMA ADPCM samples in |
|
82 * blocks of KImaAdpcmBlockAlign (256) bytes. 1010 source |
|
83 * bytes are required to fill a 256 byte block. |
|
84 * @pre if last buffer and src contains < 1010 bytes discard input |
|
85 * This function throws away the last buffer if it contains < 1010 bytes |
|
86 * (ie we must have sufficient data to process an entire frame ) |
|
87 * All other src buffers must contain |
|
88 * All destination buffer must contain |
|
89 * |
|
90 **/ |
|
91 CMMFSwCodec::TCodecProcessResult CMMFPcm16ToImaAdpcmCodec::ProcessL(const CMMFBuffer& aSrc, CMMFBuffer& aDst) |
|
92 { |
|
93 CMMFSwCodec::TCodecProcessResult result; |
|
94 result.iCodecProcessStatus = TCodecProcessResult::EProcessComplete; |
|
95 |
|
96 //convert from generic CMMFBuffer to CMMFDataBuffer |
|
97 const CMMFDataBuffer* source = STATIC_CAST(const CMMFDataBuffer*, &aSrc); |
|
98 CMMFDataBuffer* destination = STATIC_CAST(CMMFDataBuffer*, &aDst); |
|
99 |
|
100 //[ source and destination must not be null ] |
|
101 if( !source || !destination ) |
|
102 User::Leave( KErrArgument ); |
|
103 |
|
104 //[ check preconditions ] |
|
105 if( !BuffersStatus( source, destination )) |
|
106 { |
|
107 User::Leave( KErrArgument ); |
|
108 } |
|
109 |
|
110 //[ code the buffers ] |
|
111 ProcessBuffers( *source, *destination, result ); |
|
112 |
|
113 return result; |
|
114 } |
|
115 |
|
116 /** |
|
117 * |
|
118 * ProcessBuffers |
|
119 * @param aSource |
|
120 * @param aDestination |
|
121 * @param aResult |
|
122 * all we have to do is find out how many source frames there |
|
123 * are to process and process them |
|
124 * finally returning process complete and fillin the status of the result |
|
125 * |
|
126 **/ |
|
127 void CMMFPcm16ToImaAdpcmCodec::ProcessBuffers(const CMMFDataBuffer& aSource, CMMFDataBuffer& aDestination, CMMFSwCodec::TCodecProcessResult& aResult ) |
|
128 { |
|
129 //[ calculate how many full buffers are to be processed ] |
|
130 const TUint srcLen = aSource.Data().Length(); |
|
131 TInt numFullSrcFrames = srcLen/KSourceFrameSize; |
|
132 |
|
133 TUint8* pSrc = const_cast<TUint8*>(aSource.Data().Ptr()); |
|
134 TUint8* pDst = const_cast<TUint8*>(aDestination.Data().Ptr()); |
|
135 TInt dstBytesAdded = 0; |
|
136 // calculate number of pcm samples per source frame |
|
137 const TInt KSamplesPerFrame = KSourceFrameSize/(sizeof(TInt16)); |
|
138 |
|
139 //[ convert all the buffers ] |
|
140 for( TInt count = 0; count < numFullSrcFrames; count++ ) |
|
141 { |
|
142 i16PcmToImaAdpcm.Convert(pSrc, pDst, KSamplesPerFrame ); |
|
143 pSrc += KSourceFrameSize; |
|
144 pDst += KCodedFrameSize; |
|
145 dstBytesAdded += KCodedFrameSize; |
|
146 } |
|
147 aResult.iSrcBytesProcessed = numFullSrcFrames*KSourceFrameSize; |
|
148 aResult.iDstBytesAdded = dstBytesAdded; |
|
149 aDestination.Data().SetLength( aResult.iDstBytesAdded); |
|
150 } |
|
151 |
|
152 /** |
|
153 * |
|
154 * BuffersStatus |
|
155 * @param source buffer containing the data to be coded |
|
156 * @param destination buffer containing the coded data |
|
157 * @return TBool EFalse indicates bad buffers |
|
158 * |
|
159 **/ |
|
160 TBool CMMFPcm16ToImaAdpcmCodec::BuffersStatus( const CMMFDataBuffer* source, const CMMFDataBuffer* destination ) |
|
161 { |
|
162 TBool status = EFalse; |
|
163 |
|
164 //[ demand source and destination positions are zero ] |
|
165 CMMFDataBuffer* pDst = const_cast<CMMFDataBuffer*>( destination ); |
|
166 if( source->Position() || destination->Position() ) |
|
167 { |
|
168 return status; |
|
169 } |
|
170 |
|
171 //[ Have we got full buffers ] |
|
172 TInt sourceBuffers = source->Data().Length()/KSourceFrameSize; |
|
173 TInt destBuffers = (pDst->Data().MaxLength())/KCodedFrameSize; |
|
174 |
|
175 if( sourceBuffers <= destBuffers ) // the sink can process the source |
|
176 { |
|
177 return ETrue; // note this precondition has been weakened in line with other codecs |
|
178 } // such that it can process partially full buffers |
|
179 // ie you can if you wish use larger buffers than needed and only partially |
|
180 // fill them. We do however expect all the input to be processed. |
|
181 return status; |
|
182 } |