sl@0: // Copyright (c) 2000-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // Polymorphic DLL implementation of GSM 6.10 full rate (FR) speech coder sl@0: // and decoder objects. sl@0: // This codec is based on ANSI C simulation codes. For this implementation sl@0: // (polymorphic DLL) the original ANSI C codes have been modified slightly: sl@0: // - The original .c files were renamed to .cpp files. sl@0: // - All global varibles (codec's state) are now encoder's or decoder's sl@0: // private member variables. sl@0: // - Because codec's state is in the codec object, an extra variable - sl@0: // a pointer codec object - have been added to some original routines. sl@0: // - Global tables are now const C++ tables in tables.h header file. sl@0: // - VAD and DTX modules have been removed from the original routines. sl@0: // - Due to error in GNU tool chain all array indexes of type [i-1] in sl@0: // rpeltp.cpp have been removed and changed to [j] type. sl@0: // - multr, L_add, L_mac from basicop.cpp inlined sl@0: // INCLUDES sl@0: // sl@0: // sl@0: sl@0: #include "gsm610fr.h" sl@0: #include "codec.h" sl@0: #include sl@0: sl@0: sl@0: // LOCAL FUNCTIONS sl@0: //=================================================================== sl@0: /* sl@0: ----------------------------------------------------------------------------- sl@0: sl@0: GSM610FR_Encoder sl@0: sl@0: ConstructL sl@0: sl@0: This function implements the second phase construction of GSM610FR_Encoder sl@0: class. Function binds the encoder to given input and output streams and sl@0: resets encoder. sl@0: sl@0: Parameters: RReadStream aInStrm Handle to input stream (16 bit sl@0: PCM speech data) sl@0: RWriteStream aOutStrm Handle to output stream (encoded sl@0: speech data) sl@0: sl@0: Return Values: none sl@0: sl@0: ----------------------------------------------------------------------------- sl@0: */ sl@0: EXPORT_C void CGSM610FR_Encoder::ConstructL() sl@0: { sl@0: ::reset_encoder(this); sl@0: iOddFrame = TRUE; sl@0: } sl@0: sl@0: sl@0: /* sl@0: ----------------------------------------------------------------------------- sl@0: sl@0: GSM610FR_Encoder sl@0: sl@0: ~GSM610FR_Encoder sl@0: sl@0: Empty encoder destructor. sl@0: sl@0: Parameters: none sl@0: sl@0: Return Values: none sl@0: sl@0: ----------------------------------------------------------------------------- sl@0: */ sl@0: EXPORT_C CGSM610FR_Encoder::~CGSM610FR_Encoder() sl@0: { sl@0: } sl@0: sl@0: sl@0: /* sl@0: ----------------------------------------------------------------------------- sl@0: sl@0: GSM610FR_Encoder sl@0: sl@0: StartL sl@0: sl@0: Start encoder object. Initialize codec status. sl@0: sl@0: Parameters: none sl@0: sl@0: Return Values: none sl@0: sl@0: ----------------------------------------------------------------------------- sl@0: */ sl@0: EXPORT_C void CGSM610FR_Encoder::StartL() sl@0: { sl@0: ::reset_encoder(this); sl@0: iOddFrame = TRUE; sl@0: } sl@0: sl@0: sl@0: /* sl@0: ----------------------------------------------------------------------------- sl@0: sl@0: GSM610FR_Encoder sl@0: sl@0: ExecuteL sl@0: sl@0: Execute encoder object. Read one speech frame from the input stream, sl@0: RPELTP encode it and write the encoded frame to output stream. sl@0: sl@0: Parameters: none sl@0: sl@0: Return Values: none sl@0: sl@0: Leave Handling: sl@0: sl@0: If the length of data available in the input stream is less than sl@0: FRAMESIZE then the function leaves with KErrEof. sl@0: sl@0: ----------------------------------------------------------------------------- sl@0: */ sl@0: EXPORT_C void CGSM610FR_Encoder::ExecuteL(TUint8* aInBuf, TUint8* aOutBuf) sl@0: { sl@0: TInt16* inBufPtr = (TInt16*) aInBuf; sl@0: sl@0: sl@0: for (TInt frame = 0; frame < 2; frame++) sl@0: { sl@0: ::RPELTP_encoder(this, inBufPtr, &iCodeBuf); sl@0: sl@0: if ( iOddFrame ) sl@0: { sl@0: PackFrame0 (&iCodeBuf, (TInt8*) aOutBuf); sl@0: } sl@0: else sl@0: { sl@0: PackFrame1 (&iCodeBuf, (TInt8*) aOutBuf); sl@0: } sl@0: sl@0: iOddFrame = !iOddFrame; sl@0: inBufPtr += FRAMESIZE; sl@0: } sl@0: sl@0: } sl@0: /* sl@0: ----------------------------------------------------------------------------- sl@0: sl@0: GSM610FR_Encoder sl@0: sl@0: StopL sl@0: sl@0: Stop encoder object. Flush out last frames, if necessary. sl@0: sl@0: Parameters: none sl@0: sl@0: Return Values: none sl@0: sl@0: ----------------------------------------------------------------------------- sl@0: */ sl@0: EXPORT_C void CGSM610FR_Encoder::StopL() sl@0: { sl@0: } sl@0: sl@0: sl@0: /* sl@0: ----------------------------------------------------------------------------- sl@0: sl@0: GSM610FR_Encoder sl@0: sl@0: PackFrame0 sl@0: sl@0: Pack the codewords of the even frame into pack buffer. sl@0: sl@0: Packing as in MS gsm610 encoder. sl@0: sl@0: Parameters: struct codes* aCodeBuf Code words for one speech frame. sl@0: sl@0: Return Values: none sl@0: sl@0: sl@0: ----------------------------------------------------------------------------- sl@0: */ sl@0: void CGSM610FR_Encoder::PackFrame0(struct codes* aCodeBuf, TInt8* pbuf) sl@0: { sl@0: TInt16* LAR = aCodeBuf->LARc; sl@0: sl@0: // pack the LARc[0..7] into the first 4.5 bytes sl@0: *pbuf++ = (TUint8)(((LAR[0] ) & 0x3F) | ((LAR[1] << 6) & 0xC0)); sl@0: *pbuf++ = (TUint8)(((LAR[1] >> 2) & 0x0F) | ((LAR[2] << 4) & 0xF0)); sl@0: *pbuf++ = (TUint8)(((LAR[2] >> 4) & 0x01) | ((LAR[3] << 1) & 0x3E) | ((LAR[4] << 6) & 0xC0)); sl@0: *pbuf++ = (TUint8)(((LAR[4] >> 2) & 0x03) | ((LAR[5] << 2) & 0x3C) | ((LAR[6] << 6) & 0xC0)); sl@0: *pbuf = (TUint8)(((LAR[6] >> 2) & 0x01) | ((LAR[7] << 1) & 0x0E)); sl@0: sl@0: // pack Nc, bc, Mc, xmaxc, and xMc for each of the 4 sub-frames sl@0: for(TInt i = 0; i < 4; i++) sl@0: { sl@0: struct sfcodes& c = aCodeBuf->sfc[i]; sl@0: *pbuf++ |= ((c.Nc << 4) & 0xF0); sl@0: *pbuf++ = (TUint8)(((c.Nc >> 4) & 0x07) | ((c.bc << 3) & 0x18) | ((c.Mc << 5) & 0x60) | ((c.xmaxc << 7) & 0x80)); sl@0: *pbuf++ = (TUint8)(((c.xmaxc >> 1) & 0x1F) | ((c.xMc[0] << 5) & 0xE0)); sl@0: *pbuf++ = (TUint8)((c.xMc[1] & 0x07) | ((c.xMc[2] << 3) & 0x38) | ((c.xMc[3] << 6) & 0xC0)); sl@0: *pbuf++ = (TUint8)(((c.xMc[3] >> 2) & 0x01) | ((c.xMc[4] << 1) & 0x0E) | ((c.xMc[5] << 4) & 0x70) | ((c.xMc[6] << 7) & 0x80)); sl@0: *pbuf++ = (TUint8)(((c.xMc[6] >> 1) & 0x03) | ((c.xMc[7] << 2) & 0x1C) | ((c.xMc[8] << 5) & 0xE0)); sl@0: *pbuf++ = (TUint8)((c.xMc[9] & 0x07) | ((c.xMc[10] << 3) & 0x38) | ((c.xMc[11] << 6) & 0xC0)); sl@0: *pbuf = (TUint8)(((c.xMc[11] >> 2) & 0x01) | ((c.xMc[12] << 1) & 0x0E)); sl@0: } sl@0: } sl@0: sl@0: sl@0: /* sl@0: ----------------------------------------------------------------------------- sl@0: sl@0: GSM610FR_Encoder sl@0: sl@0: PackFrame1 sl@0: sl@0: Pack the codewords of the odd frame into pack buffer. sl@0: sl@0: Packing as in MS gsm610 encoder. sl@0: sl@0: Parameters: struct codes* aCodeBuf Code words for one speech frame. sl@0: sl@0: Return Values: none sl@0: sl@0: sl@0: ----------------------------------------------------------------------------- sl@0: */ sl@0: void CGSM610FR_Encoder::PackFrame1(struct codes* aCodeBuf, TInt8* pbuf) sl@0: { sl@0: TInt16* LAR = aCodeBuf->LARc; sl@0: sl@0: pbuf += (PACKSIZE / 2); sl@0: TInt8 pbufZero = pbuf[0]; sl@0: sl@0: // pack the LARc[0..7] into the first 4.5 bytes, starting with the msb of the first byte sl@0: *pbuf++ = (TUint8) (pbufZero | ((LAR[0] << 4) & 0xF0)); sl@0: *pbuf++ = (TUint8)(((LAR[0] >> 4) & 0x03) | ((LAR[1] << 2) & 0xFC)); sl@0: *pbuf++ = (TUint8)(((LAR[2] ) & 0x1F) | ((LAR[3] << 5) & 0xE0)); sl@0: *pbuf++ = (TUint8)(((LAR[3] >> 3) & 0x03) | ((LAR[4] << 2) & 0x3C) | ((LAR[5] << 6) & 0xC0)); sl@0: *pbuf++ = (TUint8)(((LAR[5] >> 2) & 0x03) | ((LAR[6] << 2) & 0x1C) | ((LAR[7] << 5) & 0xE0)); sl@0: sl@0: // pack Nc, bc, Mc, xmaxc, and xMc for each of the 4 sub-frames sl@0: for(TInt i = 0; i < 4; i++) sl@0: { sl@0: struct sfcodes& c = aCodeBuf->sfc[i]; sl@0: *pbuf++ = (TUint8)((c.Nc & 0x7F) | ((c.bc << 7) & 0x80)); sl@0: *pbuf++ = (TUint8)(((c.bc >> 1) & 0x01) | ((c.Mc << 1) & 0x06) | ((c.xmaxc << 3) & 0xF8)); sl@0: *pbuf++ = (TUint8)(((c.xmaxc >> 5) & 0x01) | ((c.xMc[0] << 1) & 0x0E) | ((c.xMc[1] << 4) & 0x70) | ((c.xMc[2] << 7) & 0x80)); sl@0: *pbuf++ = (TUint8)(((c.xMc[2] >> 1) & 0x03) | ((c.xMc[3] << 2) & 0x1C) | ((c.xMc[4] << 5) & 0xE0)); sl@0: *pbuf++ = (TUint8)(((c.xMc[5]) & 0x07) | ((c.xMc[6] << 3) & 0x38) | ((c.xMc[7] << 6) & 0xC0)); sl@0: *pbuf++ = (TUint8)(((c.xMc[7] >> 2) & 0x01) | ((c.xMc[8] << 1) & 0x0E) | ((c.xMc[9] << 4) & 0x70) | ((c.xMc[10] << 7) & 0x80)); sl@0: *pbuf++ = (TUint8)(((c.xMc[10] >> 1) & 0x03) | ((c.xMc[11] << 2) & 0x1C) | ((c.xMc[12] << 5) & 0xE0)); sl@0: } sl@0: } sl@0: sl@0: /* sl@0: ----------------------------------------------------------------------------- sl@0: sl@0: GSM610FR_Decoder sl@0: sl@0: ConstructL sl@0: sl@0: This function implements the second phase construction of GSM610FR_Decoder sl@0: class. Function binds the decoder to given input and output streams and sl@0: resets decoder. sl@0: sl@0: Parameters: RReadStream aInStrm Handle to input stream (encoded sl@0: speech data) sl@0: sl@0: RWriteStream aOutStrm Handle to output stream (16 bit sl@0: PCM speech data) sl@0: sl@0: Return Values: none sl@0: sl@0: ----------------------------------------------------------------------------- sl@0: */ sl@0: EXPORT_C void CGSM610FR_Decoder::ConstructL() sl@0: { sl@0: ::reset_decoder(this); sl@0: iOddFrame = TRUE; sl@0: } sl@0: sl@0: sl@0: /* sl@0: ----------------------------------------------------------------------------- sl@0: sl@0: GSM610FR_Decoder sl@0: sl@0: ~GSM610FR_Decoder sl@0: sl@0: Empty decoder destructor. sl@0: sl@0: Parameters: none sl@0: sl@0: Return Values: none sl@0: sl@0: ----------------------------------------------------------------------------- sl@0: */ sl@0: EXPORT_C CGSM610FR_Decoder::~CGSM610FR_Decoder() sl@0: { sl@0: } sl@0: sl@0: sl@0: /* sl@0: ----------------------------------------------------------------------------- sl@0: sl@0: GSM610FR_Decoder sl@0: sl@0: StartL sl@0: sl@0: Start decoder object. Initialize codec status. sl@0: sl@0: Parameters: none sl@0: sl@0: Return Values: none sl@0: sl@0: ----------------------------------------------------------------------------- sl@0: */ sl@0: EXPORT_C void CGSM610FR_Decoder::StartL() sl@0: { sl@0: ::reset_decoder(this); sl@0: iOddFrame = TRUE; sl@0: } sl@0: sl@0: sl@0: /* sl@0: ----------------------------------------------------------------------------- sl@0: sl@0: GSM610FR_Decoder sl@0: sl@0: ExecuteL sl@0: sl@0: Execute decoder object. Read one encoded speech frame from the input sl@0: stream RPELTP decode it and write the decoded frame to output stream. sl@0: sl@0: Parameters: none sl@0: sl@0: Return Values: none sl@0: sl@0: Leave Handling: sl@0: sl@0: If the length of data available in the input stream is less than size sl@0: of one encoded speech frame then the function leaves with KErrEof. sl@0: sl@0: ----------------------------------------------------------------------------- sl@0: */ sl@0: EXPORT_C void CGSM610FR_Decoder::ExecuteL(TUint8* aInBuf, TUint8* aOutBuf) sl@0: { sl@0: sl@0: TInt16* outBufPtr = (TInt16*) aOutBuf; sl@0: sl@0: sl@0: // Process both odd and even frames sl@0: sl@0: for (TInt frame = 0; frame < 2; frame++) sl@0: { sl@0: if ( iOddFrame ) sl@0: { sl@0: UnpackFrame0(&iCodeBuf, (TInt8*) aInBuf); sl@0: } sl@0: else sl@0: { sl@0: UnpackFrame1(&iCodeBuf, (TInt8*) aInBuf); sl@0: } sl@0: sl@0: sl@0: ::RPELTP_decoder(this, &iCodeBuf, outBufPtr); sl@0: sl@0: iOddFrame = !iOddFrame; sl@0: outBufPtr += FRAMESIZE; sl@0: sl@0: } sl@0: sl@0: } sl@0: sl@0: /* sl@0: ----------------------------------------------------------------------------- sl@0: sl@0: GSM610FR_Decoder sl@0: sl@0: StopL sl@0: sl@0: Stop decoder object. Flush out last frames, if necessary. sl@0: sl@0: Parameters: none sl@0: sl@0: Return Values: none sl@0: sl@0: ----------------------------------------------------------------------------- sl@0: */ sl@0: EXPORT_C void CGSM610FR_Decoder::StopL() sl@0: { sl@0: } sl@0: sl@0: sl@0: /* sl@0: ----------------------------------------------------------------------------- sl@0: sl@0: GSM610FR_Decoder sl@0: sl@0: UnpackFrame0 sl@0: sl@0: Unpack the codewords of the even frame from pack buffer. sl@0: sl@0: Packing as in MS gsm610 encoder. sl@0: sl@0: Parameters: struct codes* aCodeBuf Code words for one speech frame sl@0: are unpacked into this structure. sl@0: sl@0: Return Values: none sl@0: sl@0: sl@0: ----------------------------------------------------------------------------- sl@0: */ sl@0: void CGSM610FR_Decoder::UnpackFrame0(struct codes* aCodeBuf, TInt8* pbuf) sl@0: { sl@0: TInt16* LAR = aCodeBuf->LARc; sl@0: sl@0: // unpack the LAR[0..7] from the first 4.5 bytes sl@0: LAR[0] = (TInt16)((pbuf[0] & 0x3F)); sl@0: LAR[1] = (TInt16)(((pbuf[0] & 0xC0) >> 6) | ((pbuf[1] & 0x0F) << 2)); sl@0: LAR[2] = (TInt16)(((pbuf[1] & 0xF0) >> 4) | ((pbuf[2] & 0x01) << 4)); sl@0: LAR[3] = (TInt16)(((pbuf[2] & 0x3E) >> 1)); sl@0: LAR[4] = (TInt16)(((pbuf[2] & 0xC0) >> 6) | ((pbuf[3] & 0x03) << 2)); sl@0: LAR[5] = (TInt16)(((pbuf[3] & 0x3C) >> 2)); sl@0: LAR[6] = (TInt16)(((pbuf[3] & 0xC0) >> 6) | ((pbuf[4] & 0x01) << 2)); sl@0: LAR[7] = (TInt16)(((pbuf[4] & 0x0E) >> 1)); sl@0: sl@0: // unpack Nc, bc, Mc, xmaxc, and xMc for each of the 4 sub-frames sl@0: for(TInt i = 0; i < 4; i++) sl@0: { sl@0: struct sfcodes& c = aCodeBuf->sfc[i]; sl@0: #define sfb(x) (pbuf[4+i*7+x]) sl@0: c.Nc = (TInt16)(((sfb(0) & 0xF0) >> 4) | ((sfb(1) & 0x07) << 4)); sl@0: c.bc = (TInt16)(((sfb(1) & 0x18) >> 3)); sl@0: c.Mc = (TInt16)(((sfb(1) & 0x60) >> 5)); sl@0: c.xmaxc = (TInt16)(((sfb(1) & 0x80) >> 7) | ((sfb(2) & 0x1F) << 1)); sl@0: c.xMc[0] = (TInt16)(((sfb(2) & 0xE0) >> 5)); sl@0: c.xMc[1] = (TInt16)((sfb(3) & 0x07)); sl@0: c.xMc[2] = (TInt16)(((sfb(3) & 0x3C) >> 3)); sl@0: c.xMc[3] = (TInt16)(((sfb(3) & 0xC0) >> 6) | ((sfb(4) & 0x01) << 2)); sl@0: c.xMc[4] = (TInt16)(((sfb(4) & 0x0E) >> 1)); sl@0: c.xMc[5] = (TInt16)(((sfb(4) & 0x70) >> 4)); sl@0: c.xMc[6] = (TInt16)(((sfb(4) & 0x80) >> 7) | ((sfb(5) & 0x03) << 1)); sl@0: c.xMc[7] = (TInt16)(((sfb(5) & 0x1C) >> 2)); sl@0: c.xMc[8] = (TInt16)(((sfb(5) & 0xE0) >> 5)); sl@0: c.xMc[9] = (TInt16)((sfb(6) & 0x07)); sl@0: c.xMc[10] = (TInt16)(((sfb(6) & 0x38) >> 3)); sl@0: c.xMc[11] = (TInt16)(((sfb(6) & 0xC0) >> 6) | ((sfb(7) & 0x01) << 2)); sl@0: c.xMc[12] = (TInt16)(((sfb(7) & 0x0E) >> 1)); sl@0: #undef sfb sl@0: } sl@0: } sl@0: sl@0: sl@0: /* sl@0: ----------------------------------------------------------------------------- sl@0: sl@0: GSM610FR_Decoder sl@0: sl@0: UnpackFrame1 sl@0: sl@0: Unpack the codewords of the odd frame from pack buffer. sl@0: sl@0: Packing as in MS gsm610 encoder. sl@0: sl@0: Parameters: struct codes* aCodeBuf Code words for one speech frame sl@0: are unpacked into this structure. sl@0: sl@0: Return Values: none sl@0: sl@0: sl@0: ----------------------------------------------------------------------------- sl@0: */ sl@0: void CGSM610FR_Decoder::UnpackFrame1(struct codes* aCodeBuf, TInt8* pbuf) sl@0: { sl@0: TInt16* LAR = aCodeBuf->LARc; sl@0: sl@0: // unpack the LAR[0..7] from the first 4.5 bytes sl@0: LAR[0] = (TInt16)(((pbuf[32] & 0xF0) >> 4) | ((pbuf[33] & 0x03) << 4)); sl@0: LAR[1] = (TInt16)(((pbuf[33] & 0xFC) >> 2)); sl@0: LAR[2] = (TInt16)(((pbuf[34] & 0x1F))); sl@0: LAR[3] = (TInt16)(((pbuf[34] & 0xE0) >> 5) | ((pbuf[35] & 0x03) << 3)); sl@0: LAR[4] = (TInt16)(((pbuf[35] & 0x3C) >> 2)); sl@0: LAR[5] = (TInt16)(((pbuf[35] & 0xC0) >> 6) | ((pbuf[36] & 0x03) << 2)); sl@0: LAR[6] = (TInt16)(((pbuf[36] & 0x1C) >> 2)); sl@0: LAR[7] = (TInt16)(((pbuf[36] & 0xE0) >> 5)); sl@0: sl@0: // unpack Nc, bc, Mc, xmaxc, and xMc for each of the 4 sub-frames sl@0: for(TInt i = 0; i < 4; i++) sl@0: { sl@0: struct sfcodes& c = aCodeBuf->sfc[i]; sl@0: #define sfb(x) (pbuf[37+i*7+x]) sl@0: c.Nc = (TInt16)(sfb(0) & 0x7F); sl@0: c.bc = (TInt16)(((sfb(0) & 0x80) >> 7) | ((sfb(1) & 0x01) << 1)); sl@0: c.Mc = (TInt16)(((sfb(1) & 0x06) >> 1)); sl@0: c.xmaxc = (TInt16)(((sfb(1) & 0xF8) >> 3) | ((sfb(2) & 0x01) << 5)); sl@0: c.xMc[0] = (TInt16)(((sfb(2) & 0x0E) >> 1)); sl@0: c.xMc[1] = (TInt16)(((sfb(2) & 0x70) >> 4)); sl@0: c.xMc[2] = (TInt16)(((sfb(2) & 0x80) >> 7) | ((sfb(3) & 0x03) << 1)); sl@0: c.xMc[3] = (TInt16)(((sfb(3) & 0x1C) >> 2)); sl@0: c.xMc[4] = (TInt16)(((sfb(3) & 0xE0) >> 5)); sl@0: c.xMc[5] = (TInt16)(((sfb(4) & 0x07))); sl@0: c.xMc[6] = (TInt16)(((sfb(4) & 0x38) >> 3)); sl@0: c.xMc[7] = (TInt16)(((sfb(4) & 0xC0) >> 6) | ((sfb(5) & 0x01) << 2)); sl@0: c.xMc[8] = (TInt16)(((sfb(5) & 0x0E) >> 1)); sl@0: c.xMc[9] = (TInt16)(((sfb(5) & 0x70) >> 4)); sl@0: c.xMc[10] = (TInt16)(((sfb(5) & 0x80) >> 7) | ((sfb(6) & 0x03) << 1)); sl@0: c.xMc[11] = (TInt16)(((sfb(6) & 0x1C) >> 2)); sl@0: c.xMc[12] = (TInt16)(((sfb(6) & 0xE0) >> 5)); sl@0: sl@0: #undef sfb sl@0: } sl@0: } sl@0: sl@0: sl@0: //----------------------------------------------------------------------------- sl@0: // End of File sl@0: //-----------------------------------------------------------------------------