|
1 // Copyright (c) 1997-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 "MMFCodecBaseDefinitions.h" |
|
17 #include "MMFAudioCodecBase.h" |
|
18 #include <mmf/common/mmfpaniccodes.h> |
|
19 |
|
20 // Base of Audio codecs |
|
21 // These T Classes are "wrapped" by derived MMFCodecs, not exposed directly. |
|
22 |
|
23 |
|
24 void Panic(TInt aPanicCode) |
|
25 { |
|
26 _LIT(KMMFCodecBaseDefinitionsPanicCategory, "MMFCodecBaseDefinitions"); |
|
27 User::Panic(KMMFCodecBaseDefinitionsPanicCategory, aPanicCode); |
|
28 } |
|
29 |
|
30 |
|
31 void TMMFImaAdpcmBaseCodecOld::ResetBuffer() |
|
32 { |
|
33 iBufferStep = ETrue; |
|
34 iBuffer = 0; |
|
35 } |
|
36 |
|
37 TBool TMMFImaAdpcmBaseCodecOld::OutputStep() |
|
38 { |
|
39 return !iBufferStep; |
|
40 } |
|
41 |
|
42 void TMMFImaAdpcmTo16PcmCodecOld::Convert(TUint8* aSrc, TUint8* aDst, TInt aSamples) |
|
43 { |
|
44 TInt delta; // Current adpcm output value |
|
45 TInt step; // Stepsize |
|
46 TInt valpred; // Predicted value |
|
47 TInt vpdiff; // Current change to valpred |
|
48 TInt index; // Current step change index |
|
49 |
|
50 TInt channelCount=16;//for stereo only |
|
51 |
|
52 aSamples*=iChannels; |
|
53 |
|
54 //Read first sample and index from block header |
|
55 iState[0].iPredicted = *aSrc++; |
|
56 iState[0].iPredicted |= STATIC_CAST(TInt16, ((*aSrc++) << 8)); |
|
57 iState[0].iIndex = *aSrc++; |
|
58 |
|
59 aSrc++; //skip reserved header byte |
|
60 |
|
61 valpred = iState[0].iPredicted; |
|
62 index = iState[0].iIndex; |
|
63 TUint8* dst=aDst; |
|
64 |
|
65 //Write first sample to dest |
|
66 *aDst++ = STATIC_CAST( TUint8, valpred); |
|
67 *aDst++ = STATIC_CAST( TUint8, valpred >> 8); |
|
68 dst += 2; |
|
69 aSamples --; |
|
70 |
|
71 if (iChannels==2) |
|
72 { |
|
73 iState[1].iPredicted = *aSrc++; |
|
74 iState[1].iPredicted |= STATIC_CAST(TInt16, ((*aSrc++) << 8)); |
|
75 iState[1].iIndex = *aSrc++; |
|
76 aSrc++; |
|
77 |
|
78 *aDst++ = STATIC_CAST( TUint8, iState[1].iPredicted); |
|
79 *aDst++ = STATIC_CAST( TUint8, iState[1].iPredicted >> 8); |
|
80 dst += 2; |
|
81 aSamples --; |
|
82 } |
|
83 |
|
84 for ( ; aSamples > 0 ; aSamples-- ) |
|
85 { |
|
86 // Step 1 - get the delta value |
|
87 if (iBufferStep) |
|
88 { |
|
89 iBuffer = *aSrc++; |
|
90 delta = iBuffer & 0xf; |
|
91 } |
|
92 else |
|
93 { |
|
94 delta = (iBuffer >> 4) & 0xf; |
|
95 } |
|
96 |
|
97 iBufferStep = !iBufferStep; |
|
98 |
|
99 ASSERT(index >= 0); |
|
100 step = iStepSizeTable[index]; |
|
101 |
|
102 vpdiff = step>>3; |
|
103 if ( delta & 4 ) |
|
104 vpdiff += step; |
|
105 if ( delta & 2 ) |
|
106 vpdiff += step>>1; |
|
107 if ( delta & 1 ) |
|
108 vpdiff += step>>2; |
|
109 |
|
110 if ( delta & 8 ) |
|
111 valpred -= vpdiff; |
|
112 else |
|
113 valpred += vpdiff; |
|
114 |
|
115 if ( valpred > (KClamp - 1) ) |
|
116 valpred = (KClamp - 1); |
|
117 else if ( valpred < -KClamp ) |
|
118 valpred = -KClamp; |
|
119 |
|
120 index += iIndexTable[delta]; |
|
121 if ( index < 0 ) |
|
122 index = 0; |
|
123 if ( index > KMaxImaAdpcmTableEntries ) |
|
124 index = KMaxImaAdpcmTableEntries; |
|
125 |
|
126 *dst++ = STATIC_CAST( TUint8, valpred&KAndMask8bit); |
|
127 *dst++ = STATIC_CAST( TUint8, (valpred>>8)&KAndMask8bit); |
|
128 |
|
129 if (iChannels==2) |
|
130 { |
|
131 dst+=2; |
|
132 if (--channelCount == 8) |
|
133 { |
|
134 dst=aDst+2; //right channel |
|
135 iState[0].iPredicted=STATIC_CAST(TInt16, valpred); |
|
136 iState[0].iIndex=STATIC_CAST(TUint8,index); |
|
137 valpred = iState[1].iPredicted; |
|
138 index = iState[1].iIndex; |
|
139 } |
|
140 else |
|
141 { |
|
142 if (!channelCount) |
|
143 { |
|
144 aDst+=32; |
|
145 dst=aDst; |
|
146 channelCount=16; |
|
147 iState[1].iPredicted=STATIC_CAST(TInt16, valpred); |
|
148 iState[1].iIndex=STATIC_CAST(TUint8, index); |
|
149 valpred = iState[0].iPredicted; |
|
150 index = iState[0].iIndex; |
|
151 } |
|
152 } |
|
153 } |
|
154 } |
|
155 if (iChannels==1) |
|
156 { |
|
157 iState[0].iPredicted=STATIC_CAST(TInt16,valpred); |
|
158 iState[0].iIndex=STATIC_CAST(TUint8,index); |
|
159 } |
|
160 } |
|
161 |
|
162 void TMMF16PcmToImaAdpcmCodecOld::Convert(TUint8* aSrc, TUint8* aDst, TInt aSamples) |
|
163 { |
|
164 TInt val; // Current input sample value |
|
165 TInt sign; // Current adpcm sign bit |
|
166 TInt delta; // Current adpcm output value |
|
167 TInt diff; // Difference between val and valprev |
|
168 TInt step; // Stepsize |
|
169 TInt valpred; // Predicted value |
|
170 TInt vpdiff; // Current change to valpred |
|
171 TInt index; // Current step change index |
|
172 |
|
173 TInt16* srcPtr=REINTERPRET_CAST(TInt16*, aSrc); |
|
174 TInt16* src=srcPtr; |
|
175 |
|
176 TInt bufferCount=16;//for stereo only |
|
177 |
|
178 if (iChannels==2) |
|
179 { |
|
180 aSamples*=2; |
|
181 iBufferStep=ETrue; |
|
182 } |
|
183 |
|
184 iState[0].iPredicted = *aSrc++; |
|
185 iState[0].iPredicted |= STATIC_CAST(TInt16, ((*aSrc++) << 8)); |
|
186 |
|
187 valpred = iState[0].iPredicted; |
|
188 index = iState[0].iIndex; |
|
189 ASSERT(index >= 0); |
|
190 step = iStepSizeTable[index]; |
|
191 |
|
192 //Write block header |
|
193 *aDst++ = STATIC_CAST( TUint8, valpred); |
|
194 *aDst++ = STATIC_CAST( TUint8, valpred >> 8); |
|
195 *aDst++ = STATIC_CAST( TUint8, index); |
|
196 *aDst++ = 0; //reserved byte |
|
197 src++; |
|
198 aSamples --; |
|
199 |
|
200 if (iChannels==2) |
|
201 { |
|
202 iState[1].iPredicted = *aSrc++; |
|
203 iState[1].iPredicted |= STATIC_CAST(TInt16, ((*aSrc++) << 8)); |
|
204 |
|
205 //Write header for second channel |
|
206 *aDst++ = STATIC_CAST( TUint8, iState[1].iPredicted); |
|
207 *aDst++ = STATIC_CAST( TUint8, iState[1].iPredicted >> 8); |
|
208 *aDst++ = STATIC_CAST( TUint8, iState[1].iIndex); |
|
209 *aDst++ = 0; |
|
210 src ++; |
|
211 aSamples --; |
|
212 } |
|
213 |
|
214 for (; aSamples > 0; aSamples--) |
|
215 { |
|
216 val = *src; |
|
217 src += iChannels; |
|
218 |
|
219 ASSERT(index >= 0); |
|
220 step = iStepSizeTable[index]; |
|
221 |
|
222 // Step 1 - compute difference with previous value |
|
223 diff = val - valpred; |
|
224 sign = (diff < 0) ? 8 : 0; |
|
225 if ( sign ) diff = (-diff); |
|
226 |
|
227 // Step 2 - Divide and clamp |
|
228 // Note: |
|
229 // This code *approximately* computes: |
|
230 // delta = diff*4/step; |
|
231 // vpdiff = (delta+0.5)*step/4; |
|
232 // but in shift step bits are dropped. The net result of this is |
|
233 // that even if you have fast mul/div hardware you cannot put it to |
|
234 // good use since the fixup would be too expensive. |
|
235 // |
|
236 delta = 0; |
|
237 vpdiff = (step >> 3); |
|
238 |
|
239 if ( diff >= step ) |
|
240 { |
|
241 delta = 4; |
|
242 diff -= step; |
|
243 vpdiff += step; |
|
244 } |
|
245 step >>= 1; |
|
246 if ( diff >= step ) |
|
247 { |
|
248 delta |= 2; |
|
249 diff -= step; |
|
250 vpdiff += step; |
|
251 } |
|
252 step >>= 1; |
|
253 if ( diff >= step ) |
|
254 { |
|
255 delta |= 1; |
|
256 vpdiff += step; |
|
257 } |
|
258 |
|
259 // Step 3 - Update previous value |
|
260 if ( sign ) |
|
261 valpred -= vpdiff; |
|
262 else |
|
263 valpred += vpdiff; |
|
264 |
|
265 // Step 4 - Clamp previous value to 16 bits |
|
266 if ( valpred > KClamp - 1 ) |
|
267 valpred = KClamp - 1; |
|
268 else if ( valpred < - KClamp ) |
|
269 valpred = - KClamp; |
|
270 |
|
271 // Step 5 - Assemble value, update index and step values |
|
272 delta |= sign; |
|
273 |
|
274 index += iIndexTable[delta]; |
|
275 if ( index < 0 ) index = 0; |
|
276 if ( index > 88 ) index = 88; |
|
277 |
|
278 // Step 6 - Output value |
|
279 if (iBufferStep) |
|
280 iBuffer = delta & 0x0f; |
|
281 else |
|
282 *aDst++ = STATIC_CAST( TInt8, ((delta << 4) & 0xf0) | iBuffer); |
|
283 |
|
284 iBufferStep = !iBufferStep; |
|
285 |
|
286 if (iChannels==2) |
|
287 { |
|
288 if (--bufferCount==8) |
|
289 { |
|
290 src=srcPtr+1; //right channel |
|
291 iState[0].iPredicted = STATIC_CAST(TInt16, valpred); |
|
292 iState[0].iIndex = STATIC_CAST(TUint8, index); |
|
293 valpred = iState[1].iPredicted; |
|
294 index = iState[1].iIndex; |
|
295 } |
|
296 else |
|
297 { |
|
298 if (!bufferCount) |
|
299 { |
|
300 iState[1].iPredicted = STATIC_CAST(TInt16, valpred); |
|
301 iState[1].iIndex = STATIC_CAST(TUint8, index); |
|
302 valpred = iState[0].iPredicted; |
|
303 index = iState[0].iIndex; |
|
304 bufferCount=16; |
|
305 srcPtr+=16;//32bytes |
|
306 src=srcPtr; |
|
307 } |
|
308 } |
|
309 } |
|
310 } |
|
311 |
|
312 if (iChannels==1) |
|
313 { |
|
314 iState[0].iPredicted = STATIC_CAST(TInt16, valpred); |
|
315 iState[0].iIndex = STATIC_CAST(TUint8, index); |
|
316 } |
|
317 } |
|
318 |
|
319 // IMA-ADPCM step variation table |
|
320 const TInt TMMFImaAdpcmBaseCodecOld::iIndexTable[16] = |
|
321 { |
|
322 -1, -1, -1, -1, 2, 4, 6, 8, |
|
323 -1, -1, -1, -1, 2, 4, 6, 8 |
|
324 }; |
|
325 |
|
326 const TInt TMMFImaAdpcmBaseCodecOld::iStepSizeTable[89] = |
|
327 { |
|
328 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, |
|
329 19, 21, 23, 25, 28, 31, 34, 37, 41, 45, |
|
330 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, |
|
331 130, 143, 157, 173, 190, 209, 230, 253, 279, 307, |
|
332 337, 371, 408, 449, 494, 544, 598, 658, 724, 796, |
|
333 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066, |
|
334 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358, |
|
335 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899, |
|
336 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767 |
|
337 }; |
|
338 |
|
339 |