#pragma once #include "Types.h" #include "Utils.h" //------------------------------------------------------------------------------------------------------------------------------- // Данный массив содержит все возможные состояние (см. Annex C Table C-2) static MQCoderState aoMQCoderStates[47 * 2] = { { 0x5601, 0, &aoMQCoderStates[2], &aoMQCoderStates[3] }, { 0x5601, 1, &aoMQCoderStates[3], &aoMQCoderStates[2] }, { 0x3401, 0, &aoMQCoderStates[4], &aoMQCoderStates[12] }, { 0x3401, 1, &aoMQCoderStates[5], &aoMQCoderStates[13] }, { 0x1801, 0, &aoMQCoderStates[6], &aoMQCoderStates[18] }, { 0x1801, 1, &aoMQCoderStates[7], &aoMQCoderStates[19] }, { 0x0ac1, 0, &aoMQCoderStates[8], &aoMQCoderStates[24] }, { 0x0ac1, 1, &aoMQCoderStates[9], &aoMQCoderStates[25] }, { 0x0521, 0, &aoMQCoderStates[10], &aoMQCoderStates[58] }, { 0x0521, 1, &aoMQCoderStates[11], &aoMQCoderStates[59] }, { 0x0221, 0, &aoMQCoderStates[76], &aoMQCoderStates[66] }, { 0x0221, 1, &aoMQCoderStates[77], &aoMQCoderStates[67] }, { 0x5601, 0, &aoMQCoderStates[14], &aoMQCoderStates[13] }, { 0x5601, 1, &aoMQCoderStates[15], &aoMQCoderStates[12] }, { 0x5401, 0, &aoMQCoderStates[16], &aoMQCoderStates[28] }, { 0x5401, 1, &aoMQCoderStates[17], &aoMQCoderStates[29] }, { 0x4801, 0, &aoMQCoderStates[18], &aoMQCoderStates[28] }, { 0x4801, 1, &aoMQCoderStates[19], &aoMQCoderStates[29] }, { 0x3801, 0, &aoMQCoderStates[20], &aoMQCoderStates[28] }, { 0x3801, 1, &aoMQCoderStates[21], &aoMQCoderStates[29] }, { 0x3001, 0, &aoMQCoderStates[22], &aoMQCoderStates[34] }, { 0x3001, 1, &aoMQCoderStates[23], &aoMQCoderStates[35] }, { 0x2401, 0, &aoMQCoderStates[24], &aoMQCoderStates[36] }, { 0x2401, 1, &aoMQCoderStates[25], &aoMQCoderStates[37] }, { 0x1c01, 0, &aoMQCoderStates[26], &aoMQCoderStates[40] }, { 0x1c01, 1, &aoMQCoderStates[27], &aoMQCoderStates[41] }, { 0x1601, 0, &aoMQCoderStates[58], &aoMQCoderStates[42] }, { 0x1601, 1, &aoMQCoderStates[59], &aoMQCoderStates[43] }, { 0x5601, 0, &aoMQCoderStates[30], &aoMQCoderStates[29] }, { 0x5601, 1, &aoMQCoderStates[31], &aoMQCoderStates[28] }, { 0x5401, 0, &aoMQCoderStates[32], &aoMQCoderStates[28] }, { 0x5401, 1, &aoMQCoderStates[33], &aoMQCoderStates[29] }, { 0x5101, 0, &aoMQCoderStates[34], &aoMQCoderStates[30] }, { 0x5101, 1, &aoMQCoderStates[35], &aoMQCoderStates[31] }, { 0x4801, 0, &aoMQCoderStates[36], &aoMQCoderStates[32] }, { 0x4801, 1, &aoMQCoderStates[37], &aoMQCoderStates[33] }, { 0x3801, 0, &aoMQCoderStates[38], &aoMQCoderStates[34] }, { 0x3801, 1, &aoMQCoderStates[39], &aoMQCoderStates[35] }, { 0x3401, 0, &aoMQCoderStates[40], &aoMQCoderStates[36] }, { 0x3401, 1, &aoMQCoderStates[41], &aoMQCoderStates[37] }, { 0x3001, 0, &aoMQCoderStates[42], &aoMQCoderStates[38] }, { 0x3001, 1, &aoMQCoderStates[43], &aoMQCoderStates[39] }, { 0x2801, 0, &aoMQCoderStates[44], &aoMQCoderStates[38] }, { 0x2801, 1, &aoMQCoderStates[45], &aoMQCoderStates[39] }, { 0x2401, 0, &aoMQCoderStates[46], &aoMQCoderStates[40] }, { 0x2401, 1, &aoMQCoderStates[47], &aoMQCoderStates[41] }, { 0x2201, 0, &aoMQCoderStates[48], &aoMQCoderStates[42] }, { 0x2201, 1, &aoMQCoderStates[49], &aoMQCoderStates[43] }, { 0x1c01, 0, &aoMQCoderStates[50], &aoMQCoderStates[44] }, { 0x1c01, 1, &aoMQCoderStates[51], &aoMQCoderStates[45] }, { 0x1801, 0, &aoMQCoderStates[52], &aoMQCoderStates[46] }, { 0x1801, 1, &aoMQCoderStates[53], &aoMQCoderStates[47] }, { 0x1601, 0, &aoMQCoderStates[54], &aoMQCoderStates[48] }, { 0x1601, 1, &aoMQCoderStates[55], &aoMQCoderStates[49] }, { 0x1401, 0, &aoMQCoderStates[56], &aoMQCoderStates[50] }, { 0x1401, 1, &aoMQCoderStates[57], &aoMQCoderStates[51] }, { 0x1201, 0, &aoMQCoderStates[58], &aoMQCoderStates[52] }, { 0x1201, 1, &aoMQCoderStates[59], &aoMQCoderStates[53] }, { 0x1101, 0, &aoMQCoderStates[60], &aoMQCoderStates[54] }, { 0x1101, 1, &aoMQCoderStates[61], &aoMQCoderStates[55] }, { 0x0ac1, 0, &aoMQCoderStates[62], &aoMQCoderStates[56] }, { 0x0ac1, 1, &aoMQCoderStates[63], &aoMQCoderStates[57] }, { 0x09c1, 0, &aoMQCoderStates[64], &aoMQCoderStates[58] }, { 0x09c1, 1, &aoMQCoderStates[65], &aoMQCoderStates[59] }, { 0x08a1, 0, &aoMQCoderStates[66], &aoMQCoderStates[60] }, { 0x08a1, 1, &aoMQCoderStates[67], &aoMQCoderStates[61] }, { 0x0521, 0, &aoMQCoderStates[68], &aoMQCoderStates[62] }, { 0x0521, 1, &aoMQCoderStates[69], &aoMQCoderStates[63] }, { 0x0441, 0, &aoMQCoderStates[70], &aoMQCoderStates[64] }, { 0x0441, 1, &aoMQCoderStates[71], &aoMQCoderStates[65] }, { 0x02a1, 0, &aoMQCoderStates[72], &aoMQCoderStates[66] }, { 0x02a1, 1, &aoMQCoderStates[73], &aoMQCoderStates[67] }, { 0x0221, 0, &aoMQCoderStates[74], &aoMQCoderStates[68] }, { 0x0221, 1, &aoMQCoderStates[75], &aoMQCoderStates[69] }, { 0x0141, 0, &aoMQCoderStates[76], &aoMQCoderStates[70] }, { 0x0141, 1, &aoMQCoderStates[77], &aoMQCoderStates[71] }, { 0x0111, 0, &aoMQCoderStates[78], &aoMQCoderStates[72] }, { 0x0111, 1, &aoMQCoderStates[79], &aoMQCoderStates[73] }, { 0x0085, 0, &aoMQCoderStates[80], &aoMQCoderStates[74] }, { 0x0085, 1, &aoMQCoderStates[81], &aoMQCoderStates[75] }, { 0x0049, 0, &aoMQCoderStates[82], &aoMQCoderStates[76] }, { 0x0049, 1, &aoMQCoderStates[83], &aoMQCoderStates[77] }, { 0x0025, 0, &aoMQCoderStates[84], &aoMQCoderStates[78] }, { 0x0025, 1, &aoMQCoderStates[85], &aoMQCoderStates[79] }, { 0x0015, 0, &aoMQCoderStates[86], &aoMQCoderStates[80] }, { 0x0015, 1, &aoMQCoderStates[87], &aoMQCoderStates[81] }, { 0x0009, 0, &aoMQCoderStates[88], &aoMQCoderStates[82] }, { 0x0009, 1, &aoMQCoderStates[89], &aoMQCoderStates[83] }, { 0x0005, 0, &aoMQCoderStates[90], &aoMQCoderStates[84] }, { 0x0005, 1, &aoMQCoderStates[91], &aoMQCoderStates[85] }, { 0x0001, 0, &aoMQCoderStates[90], &aoMQCoderStates[86] }, { 0x0001, 1, &aoMQCoderStates[91], &aoMQCoderStates[87] }, { 0x5601, 0, &aoMQCoderStates[92], &aoMQCoderStates[92] }, { 0x5601, 1, &aoMQCoderStates[93], &aoMQCoderStates[93] }, }; //------------------------------------------------------------------------------------------------------------------------------- // Вспомогательные функции //------------------------------------------------------------------------------------------------------------------------------- static void MQC_ByteOut(MQCoder *pMQCoder) { if ( *pMQCoder->pBufferPointer == 0xff ) { pMQCoder->pBufferPointer++; *pMQCoder->pBufferPointer = pMQCoder->nCregister >> 20; pMQCoder->nCregister &= 0xfffff; pMQCoder->nCt = 7; } else { if ( ( pMQCoder->nCregister & 0x8000000 ) == 0 ) // CHANGE { pMQCoder->pBufferPointer++; *pMQCoder->pBufferPointer = pMQCoder->nCregister >> 19; pMQCoder->nCregister &= 0x7ffff; pMQCoder->nCt = 8; } else { (*pMQCoder->pBufferPointer)++; if ( *pMQCoder->pBufferPointer == 0xff ) { pMQCoder->nCregister &= 0x7ffffff; pMQCoder->pBufferPointer++; *pMQCoder->pBufferPointer = pMQCoder->nCregister >> 20; pMQCoder->nCregister &= 0xfffff; pMQCoder->nCt = 7; } else { pMQCoder->pBufferPointer++; *pMQCoder->pBufferPointer = pMQCoder->nCregister >> 19; pMQCoder->nCregister &= 0x7ffff; pMQCoder->nCt = 8; } } } } static void MQC_RenormE(MQCoder *pMQCoder) { do { pMQCoder->nAregister <<= 1; pMQCoder->nCregister <<= 1; pMQCoder->nCt--; if ( 0 == pMQCoder->nCt ) { MQC_ByteOut( pMQCoder ); } } while ( (pMQCoder->nAregister & 0x8000) == 0 ); } static void MQC_CodeMPS(MQCoder *pMQCoder) { pMQCoder->nAregister -= (*pMQCoder->ppCurContext)->nLPSValue; if ( (pMQCoder->nAregister & 0x8000) == 0 ) { if ( pMQCoder->nAregister < (*pMQCoder->ppCurContext)->nLPSValue ) { pMQCoder->nAregister = (*pMQCoder->ppCurContext)->nLPSValue; } else { pMQCoder->nCregister += (*pMQCoder->ppCurContext)->nLPSValue; } *pMQCoder->ppCurContext = (*pMQCoder->ppCurContext)->pNextMPS; MQC_RenormE( pMQCoder ); } else { pMQCoder->nCregister += (*pMQCoder->ppCurContext)->nLPSValue; } } static void MQC_CodeLPS(MQCoder *pMQCoder) { pMQCoder->nAregister -= (*pMQCoder->ppCurContext)->nLPSValue; if ( pMQCoder->nAregister < (*pMQCoder->ppCurContext)->nLPSValue ) { pMQCoder->nCregister += (*pMQCoder->ppCurContext)->nLPSValue; } else { pMQCoder->nAregister = (*pMQCoder->ppCurContext)->nLPSValue; } *pMQCoder->ppCurContext = (*pMQCoder->ppCurContext)->pNextLPS; MQC_RenormE( pMQCoder ); } static void MQC_SetBits(MQCoder *pMQCoder) { unsigned int nTempCode = pMQCoder->nCregister + pMQCoder->nAregister; pMQCoder->nCregister |= 0xffff; if ( pMQCoder->nCregister >= nTempCode ) { pMQCoder->nCregister -= 0x8000; } } static int MQC_MPSExchange(MQCoder *pMQCoder) { int nResult = 0; if ( pMQCoder->nAregister < (*pMQCoder->ppCurContext)->nLPSValue ) { nResult = 1 - (*pMQCoder->ppCurContext)->nMPS; *pMQCoder->ppCurContext = (*pMQCoder->ppCurContext)->pNextLPS; } else { nResult = (*pMQCoder->ppCurContext)->nMPS; *pMQCoder->ppCurContext = (*pMQCoder->ppCurContext)->pNextMPS; } return nResult; } static int MQC_LPSExchange(MQCoder *pMQCoder) { int nResult = 0; if ( pMQCoder->nAregister < (*pMQCoder->ppCurContext)->nLPSValue ) { pMQCoder->nAregister = (*pMQCoder->ppCurContext)->nLPSValue; nResult = (*pMQCoder->ppCurContext)->nMPS; *pMQCoder->ppCurContext = (*pMQCoder->ppCurContext)->pNextMPS; } else { pMQCoder->nAregister = (*pMQCoder->ppCurContext)->nLPSValue; nResult = 1 - (*pMQCoder->ppCurContext)->nMPS; *pMQCoder->ppCurContext = (*pMQCoder->ppCurContext)->pNextLPS; } return nResult; } static void MQC_ByteIn(MQCoder *pMQCoder) { if ( pMQCoder->pBufferPointer != pMQCoder->pEnd ) { unsigned int nCode = 0; if ( pMQCoder->pBufferPointer + 1 != pMQCoder->pEnd ) { nCode = *(pMQCoder->pBufferPointer + 1); } else { nCode = 0xff; } if ( *pMQCoder->pBufferPointer == 0xff ) { if ( nCode > 0x8f ) { pMQCoder->nCregister += 0xff00; pMQCoder->nCt = 8; } else { pMQCoder->pBufferPointer++; pMQCoder->nCregister += nCode << 9; pMQCoder->nCt = 7; } } else { pMQCoder->pBufferPointer++; pMQCoder->nCregister += nCode << 8; pMQCoder->nCt = 8; } } else { pMQCoder->nCregister += 0xff00; pMQCoder->nCt = 8; } } static void MQC_RenormD(MQCoder *pMQCoder) { do { if ( pMQCoder->nCt == 0 ) { MQC_ByteIn( pMQCoder ); } pMQCoder->nAregister <<= 1; pMQCoder->nCregister <<= 1; pMQCoder->nCt--; } while ( pMQCoder->nAregister < 0x8000 ); } //------------------------------------------------------------------------------------------------------------------------------- // Основные функции //------------------------------------------------------------------------------------------------------------------------------- MQCoder* MQC_Create() { MQCoder *pCoder = (MQCoder*)Malloc(HEAP_ZERO_MEMORY, sizeof(MQCoder)); return pCoder; } void MQC_Destroy(MQCoder *pMQCoder) { RELEASEHEAP( pMQCoder ); } int MQC_BytesCount(MQCoder *pMQCoder) { return pMQCoder->pBufferPointer - pMQCoder->pStart; } void MQC_ResetStates(MQCoder *pMQCoder) { for ( int nIndex = 0; nIndex < MQC_NUMCTXS; nIndex++ ) { pMQCoder->pContexts[nIndex] = aoMQCoderStates; } } void MQC_SetState(MQCoder *pMQCoder, int nContextIndex, int nMSB, int nProb) { pMQCoder->pContexts[nContextIndex] = &aoMQCoderStates[nMSB + (nProb << 1)]; } void MQC_SetCurContext(MQCoder *pMQCoder, int nContextIndex) { pMQCoder->ppCurContext = &pMQCoder->pContexts[nContextIndex]; } void MQC_InitEncoder(MQCoder *pMQCoder, unsigned char *pBufferPointer) { MQC_SetCurContext( pMQCoder, 0 ); pMQCoder->nAregister = 0x8000; pMQCoder->nCregister = 0; pMQCoder->pBufferPointer = pBufferPointer - 1; pMQCoder->nCt = 12; if ( *pMQCoder->pBufferPointer == 0xff ) { pMQCoder->nCt = 13; } pMQCoder->pStart = pBufferPointer; } void MQC_Encode(MQCoder *pMQCoder, int nValue) { if ( (*pMQCoder->ppCurContext)->nMPS == nValue ) { MQC_CodeMPS( pMQCoder ); } else { MQC_CodeLPS( pMQCoder ); } } void MQC_Flush(MQCoder *pMQCoder) { MQC_SetBits( pMQCoder ); pMQCoder->nCregister <<= pMQCoder->nCt; MQC_ByteOut( pMQCoder ); pMQCoder->nCregister <<= pMQCoder->nCt; MQC_ByteOut( pMQCoder ); if ( *pMQCoder->pBufferPointer != 0xff ) { pMQCoder->pBufferPointer++; } } void MQC_BypassInitEncoder(MQCoder *pMQCoder) { // TO DO: Данная функция непольностью протестирована pMQCoder->nCregister = 0; pMQCoder->nCt = 8; /* if ( *pMQCoder->bp == 0xff ) { pMQCoder->ct = 7; } */ } void MQC_BypassEncoder(MQCoder *pMQCoder, int nValue) { // TO DO: Данная функция непольностью протестирована pMQCoder->nCt--; pMQCoder->nCregister = pMQCoder->nCregister + (nValue << pMQCoder->nCt); if ( pMQCoder->nCt == 0 ) { pMQCoder->pBufferPointer++; *pMQCoder->pBufferPointer = pMQCoder->nCregister; pMQCoder->nCt = 8; if ( *pMQCoder->pBufferPointer == 0xff ) { pMQCoder->nCt = 7; } pMQCoder->nCregister = 0; } } int MQC_BypassFlushEncoder(MQCoder *pMQCoder) { // TO DO: Данная функция непольностью протестирована unsigned char nBitPadding = 0; if ( pMQCoder->nCt != 0 ) { while ( pMQCoder->nCt > 0 ) { pMQCoder->nCt--; pMQCoder->nCregister += nBitPadding << pMQCoder->nCt; nBitPadding = (nBitPadding + 1) & 0x01; } pMQCoder->pBufferPointer++; *pMQCoder->pBufferPointer = pMQCoder->nCregister; pMQCoder->nCt = 8; pMQCoder->nCregister = 0; } return 1; } void MQC_ResetEncoder(MQCoder *pMQCoder) { MQC_ResetStates( pMQCoder ); MQC_SetState( pMQCoder, 18, 0, 46 ); MQC_SetState( pMQCoder, 0, 0, 3 ); MQC_SetState( pMQCoder, 1, 0, 4 ); } int MQC_RestartEncoder(MQCoder *pMQCoder) { int nCorrection = 1; int nLen = 27 - 15 - pMQCoder->nCt; pMQCoder->nCregister <<= pMQCoder->nCt; while ( nLen > 0 ) { MQC_ByteOut( pMQCoder ); nLen -= pMQCoder->nCt; pMQCoder->nCregister <<= pMQCoder->nCt; } MQC_ByteOut( pMQCoder ); return nCorrection; } void MQC_RestartInitEncoder(MQCoder *pMQCoder) { MQC_SetCurContext( pMQCoder, 0 ); pMQCoder->nAregister = 0x8000; pMQCoder->nCregister = 0; pMQCoder->nCt = 12; pMQCoder->pBufferPointer--; if ( *pMQCoder->pBufferPointer == 0xff ) { pMQCoder->nCt = 13; } } void MQC_ErtermEncoder(MQCoder *pMQCoder) { int nK = 11 - pMQCoder->nCt + 1; while ( nK > 0 ) { pMQCoder->nCregister <<= pMQCoder->nCt; pMQCoder->nCt = 0; MQC_ByteOut( pMQCoder ); nK -= pMQCoder->nCt; } if ( *pMQCoder->pBufferPointer != 0xff ) { MQC_ByteOut( pMQCoder ); } } void MQC_SegMarkEncoder(MQCoder *pMQCoder) { MQC_SetCurContext( pMQCoder, 18 ); for ( int nIndex = 1; nIndex < 5; nIndex++ ) { MQC_Encode( pMQCoder, nIndex % 2 ); } } void MQC_InitDecoder(MQCoder *pMQCoder, unsigned char *nBufferPointer, int nLen) { MQC_SetCurContext( pMQCoder, 0 ); pMQCoder->pStart = nBufferPointer; pMQCoder->pEnd = nBufferPointer + nLen; pMQCoder->pBufferPointer = nBufferPointer; if ( 0 == nLen ) pMQCoder->nCregister = 0xff << 16; else pMQCoder->nCregister = *pMQCoder->pBufferPointer << 16; MQC_ByteIn( pMQCoder ); pMQCoder->nCregister <<= 7; pMQCoder->nCt -= 7; pMQCoder->nAregister = 0x8000; } int MQC_Decode(MQCoder *pMQCoder) { int nResult = 0; pMQCoder->nAregister -= (*pMQCoder->ppCurContext)->nLPSValue; if ( (pMQCoder->nCregister >> 16) < (*pMQCoder->ppCurContext)->nLPSValue ) { nResult = MQC_LPSExchange( pMQCoder ); MQC_RenormD( pMQCoder ); } else { pMQCoder->nCregister -= (*pMQCoder->ppCurContext)->nLPSValue << 16; if ( (pMQCoder->nAregister & 0x8000) == 0 ) { nResult = MQC_MPSExchange( pMQCoder ); MQC_RenormD( pMQCoder ); } else { nResult = (*pMQCoder->ppCurContext)->nMPS; } } return nResult; }