1 #include <algorithm> 2 3 #include "All.h" 4 #include "APEDecompress.h" 5 #include "APEInfo.h" 6 #include "Prepare.h" 7 #include "UnBitArray.h" 8 #include "NewPredictor.h" 9 10 #define DECODE_BLOCK_SIZE 4096 11 12 CAPEDecompress::CAPEDecompress(int * pErrorCode, CAPEInfo * pAPEInfo, int nStartBlock, int nFinishBlock) 13 { 14 *pErrorCode = ERROR_SUCCESS; 15 16 // open / analyze the file 17 m_spAPEInfo.Assign(pAPEInfo); 18 19 // version check (this implementation only works with 3.93 and later files) 20 if (GetInfo(APE_INFO_FILE_VERSION) < 3930) 21 { 22 *pErrorCode = ERROR_UNDEFINED; 23 return; 24 } 25 26 // get format information 27 GetInfo(APE_INFO_WAVEFORMATEX, (int) &m_wfeInput); 28 m_nBlockAlign = GetInfo(APE_INFO_BLOCK_ALIGN); 29 30 // initialize other stuff 31 m_bDecompressorInitialized = FALSE; 32 m_nCurrentFrame = 0; 33 m_nCurrentBlock = 0; 34 m_nCurrentFrameBufferBlock = 0; 35 m_nFrameBufferFinishedBlocks = 0; 36 m_bErrorDecodingCurrentFrame = FALSE; 37 38 // set the "real" start and finish blocks 39 m_nStartBlock = (nStartBlock < 0) 40 ? 0 : min(nStartBlock, GetInfo(APE_INFO_TOTAL_BLOCKS)); 41 m_nFinishBlock = (nFinishBlock < 0) 42 ? GetInfo(APE_INFO_TOTAL_BLOCKS) 43 : min(nFinishBlock, GetInfo(APE_INFO_TOTAL_BLOCKS)); 44 m_bIsRanged = (m_nStartBlock != 0) || (m_nFinishBlock != GetInfo(APE_INFO_TOTAL_BLOCKS)); 45 } 46 47 CAPEDecompress::~CAPEDecompress() 48 { 49 50 } 51 52 int CAPEDecompress::InitializeDecompressor() 53 { 54 // check if we have anything to do 55 if (m_bDecompressorInitialized) 56 return ERROR_SUCCESS; 57 58 // update the initialized flag 59 m_bDecompressorInitialized = TRUE; 60 61 // create a frame buffer 62 m_cbFrameBuffer.CreateBuffer((GetInfo(APE_INFO_BLOCKS_PER_FRAME) + DECODE_BLOCK_SIZE) * m_nBlockAlign, m_nBlockAlign * 64); 63 64 // create decoding components 65 m_spUnBitArray.Assign((CUnBitArrayBase *) CreateUnBitArray(this, GetInfo(APE_INFO_FILE_VERSION))); 66 67 if (GetInfo(APE_INFO_FILE_VERSION) >= 3950) 68 { 69 m_spNewPredictorX.Assign(new CPredictorDecompress3950toCurrent(GetInfo(APE_INFO_COMPRESSION_LEVEL), GetInfo(APE_INFO_FILE_VERSION))); 70 m_spNewPredictorY.Assign(new CPredictorDecompress3950toCurrent(GetInfo(APE_INFO_COMPRESSION_LEVEL), GetInfo(APE_INFO_FILE_VERSION))); 71 } 72 else 73 { 74 m_spNewPredictorX.Assign(new CPredictorDecompressNormal3930to3950(GetInfo(APE_INFO_COMPRESSION_LEVEL), GetInfo(APE_INFO_FILE_VERSION))); 75 m_spNewPredictorY.Assign(new CPredictorDecompressNormal3930to3950(GetInfo(APE_INFO_COMPRESSION_LEVEL), GetInfo(APE_INFO_FILE_VERSION))); 76 } 77 78 // seek to the beginning 79 return Seek(0); 80 } 81 82 int CAPEDecompress::GetData(char * pBuffer, int nBlocks, int * pBlocksRetrieved) 83 { 84 int nRetVal = ERROR_SUCCESS; 85 if (pBlocksRetrieved) *pBlocksRetrieved = 0; 86 87 // make sure we're initialized 88 RETURN_ON_ERROR(InitializeDecompressor()) 89 90 // cap 91 int nBlocksUntilFinish = m_nFinishBlock - m_nCurrentBlock; 92 const int nBlocksToRetrieve = min(nBlocks, nBlocksUntilFinish); 93 94 // get the data 95 unsigned char * pOutputBuffer = (unsigned char *) pBuffer; 96 int nBlocksLeft = nBlocksToRetrieve; int nBlocksThisPass = 1; 97 while ((nBlocksLeft > 0) && (nBlocksThisPass > 0)) 98 { 99 // fill up the frame buffer 100 int nDecodeRetVal = FillFrameBuffer(); 101 if (nDecodeRetVal != ERROR_SUCCESS) 102 nRetVal = nDecodeRetVal; 103 104 // analyze how much to remove from the buffer 105 const int nFrameBufferBlocks = m_nFrameBufferFinishedBlocks; 106 nBlocksThisPass = min(nBlocksLeft, nFrameBufferBlocks); 107 108 // remove as much as possible 109 if (nBlocksThisPass > 0) 110 { 111 m_cbFrameBuffer.Get(pOutputBuffer, nBlocksThisPass * m_nBlockAlign); 112 pOutputBuffer += nBlocksThisPass * m_nBlockAlign; 113 nBlocksLeft -= nBlocksThisPass; 114 m_nFrameBufferFinishedBlocks -= nBlocksThisPass; 115 } 116 } 117 118 // calculate the blocks retrieved 119 int nBlocksRetrieved = nBlocksToRetrieve - nBlocksLeft; 120 121 // update position 122 m_nCurrentBlock += nBlocksRetrieved; 123 if (pBlocksRetrieved) *pBlocksRetrieved = nBlocksRetrieved; 124 125 return nRetVal; 126 } 127 128 int CAPEDecompress::Seek(int nBlockOffset) 129 { 130 RETURN_ON_ERROR(InitializeDecompressor()) 131 132 // use the offset 133 nBlockOffset += m_nStartBlock; 134 135 // cap (to prevent seeking too far) 136 if (nBlockOffset >= m_nFinishBlock) 137 nBlockOffset = m_nFinishBlock - 1; 138 if (nBlockOffset < m_nStartBlock) 139 nBlockOffset = m_nStartBlock; 140 141 // seek to the perfect location 142 int nBaseFrame = nBlockOffset / GetInfo(APE_INFO_BLOCKS_PER_FRAME); 143 int nBlocksToSkip = nBlockOffset % GetInfo(APE_INFO_BLOCKS_PER_FRAME); 144 int nBytesToSkip = nBlocksToSkip * m_nBlockAlign; 145 146 m_nCurrentBlock = nBaseFrame * GetInfo(APE_INFO_BLOCKS_PER_FRAME); 147 m_nCurrentFrameBufferBlock = nBaseFrame * GetInfo(APE_INFO_BLOCKS_PER_FRAME); 148 m_nCurrentFrame = nBaseFrame; 149 m_nFrameBufferFinishedBlocks = 0; 150 m_cbFrameBuffer.Empty(); 151 RETURN_ON_ERROR(SeekToFrame(m_nCurrentFrame)); 152 153 // skip necessary blocks 154 CSmartPtr<char> spTempBuffer(new char [nBytesToSkip], TRUE); 155 if (spTempBuffer == NULL) return ERROR_INSUFFICIENT_MEMORY; 156 157 int nBlocksRetrieved = 0; 158 GetData(spTempBuffer, nBlocksToSkip, &nBlocksRetrieved); 159 if (nBlocksRetrieved != nBlocksToSkip) 160 return ERROR_UNDEFINED; 161 162 return ERROR_SUCCESS; 163 } 164 165 /***************************************************************************************** 166 Decodes blocks of data 167 *****************************************************************************************/ 168 int CAPEDecompress::FillFrameBuffer() 169 { 170 int nRetVal = ERROR_SUCCESS; 171 172 // determine the maximum blocks we can decode 173 // note that we won't do end capping because we can't use data 174 // until EndFrame(...) successfully handles the frame 175 // that means we may decode a little extra in end capping cases 176 // but this allows robust error handling of bad frames 177 int nMaxBlocks = m_cbFrameBuffer.MaxAdd() / m_nBlockAlign; 178 179 // loop and decode data 180 int nBlocksLeft = nMaxBlocks; 181 while (nBlocksLeft > 0) 182 { 183 int nFrameBlocks = GetInfo(APE_INFO_FRAME_BLOCKS, m_nCurrentFrame); 184 if (nFrameBlocks < 0) 185 break; 186 187 int nFrameOffsetBlocks = m_nCurrentFrameBufferBlock % GetInfo(APE_INFO_BLOCKS_PER_FRAME); 188 int nFrameBlocksLeft = nFrameBlocks - nFrameOffsetBlocks; 189 int nBlocksThisPass = min(nFrameBlocksLeft, nBlocksLeft); 190 191 // start the frame if we need to 192 if (nFrameOffsetBlocks == 0) 193 StartFrame(); 194 195 // store the frame buffer bytes before we start 196 int nFrameBufferBytes = m_cbFrameBuffer.MaxGet(); 197 198 // decode data 199 DecodeBlocksToFrameBuffer(nBlocksThisPass); 200 201 // end the frame if we need to 202 if ((nFrameOffsetBlocks + nBlocksThisPass) >= nFrameBlocks) 203 { 204 EndFrame(); 205 if (m_bErrorDecodingCurrentFrame) 206 { 207 // remove any decoded data from the buffer 208 m_cbFrameBuffer.RemoveTail(m_cbFrameBuffer.MaxGet() - nFrameBufferBytes); 209 210 // add silence 211 unsigned char cSilence = (GetInfo(APE_INFO_BITS_PER_SAMPLE) == 8) ? 127 : 0; 212 for (int z = 0; z < nFrameBlocks * m_nBlockAlign; z++) 213 { 214 *m_cbFrameBuffer.GetDirectWritePointer() = cSilence; 215 m_cbFrameBuffer.UpdateAfterDirectWrite(1); 216 } 217 218 // seek to try to synchronize after an error 219 SeekToFrame(m_nCurrentFrame); 220 221 // save the return value 222 nRetVal = ERROR_INVALID_CHECKSUM; 223 } 224 } 225 226 nBlocksLeft -= nBlocksThisPass; 227 } 228 229 return nRetVal; 230 } 231 232 void CAPEDecompress::DecodeBlocksToFrameBuffer(int nBlocks) 233 { 234 // decode the samples 235 int nBlocksProcessed = 0; 236 237 try 238 { 239 if (m_wfeInput.nChannels == 2) 240 { 241 if ((m_nSpecialCodes & SPECIAL_FRAME_LEFT_SILENCE) && 242 (m_nSpecialCodes & SPECIAL_FRAME_RIGHT_SILENCE)) 243 { 244 for (nBlocksProcessed = 0; nBlocksProcessed < nBlocks; nBlocksProcessed++) 245 { 246 m_Prepare.Unprepare(0, 0, &m_wfeInput, m_cbFrameBuffer.GetDirectWritePointer(), &m_nCRC); 247 m_cbFrameBuffer.UpdateAfterDirectWrite(m_nBlockAlign); 248 } 249 } 250 else if (m_nSpecialCodes & SPECIAL_FRAME_PSEUDO_STEREO) 251 { 252 for (nBlocksProcessed = 0; nBlocksProcessed < nBlocks; nBlocksProcessed++) 253 { 254 int X = m_spNewPredictorX->DecompressValue(m_spUnBitArray->DecodeValueRange(m_BitArrayStateX)); 255 m_Prepare.Unprepare(X, 0, &m_wfeInput, m_cbFrameBuffer.GetDirectWritePointer(), &m_nCRC); 256 m_cbFrameBuffer.UpdateAfterDirectWrite(m_nBlockAlign); 257 } 258 } 259 else 260 { 261 if (m_spAPEInfo->GetInfo(APE_INFO_FILE_VERSION) >= 3950) 262 { 263 for (nBlocksProcessed = 0; nBlocksProcessed < nBlocks; nBlocksProcessed++) 264 { 265 int nY = m_spUnBitArray->DecodeValueRange(m_BitArrayStateY); 266 int nX = m_spUnBitArray->DecodeValueRange(m_BitArrayStateX); 267 int Y = m_spNewPredictorY->DecompressValue(nY, m_nLastX); 268 int X = m_spNewPredictorX->DecompressValue(nX, Y); 269 m_nLastX = X; 270 271 m_Prepare.Unprepare(X, Y, &m_wfeInput, m_cbFrameBuffer.GetDirectWritePointer(), &m_nCRC); 272 m_cbFrameBuffer.UpdateAfterDirectWrite(m_nBlockAlign); 273 } 274 } 275 else 276 { 277 for (nBlocksProcessed = 0; nBlocksProcessed < nBlocks; nBlocksProcessed++) 278 { 279 int X = m_spNewPredictorX->DecompressValue(m_spUnBitArray->DecodeValueRange(m_BitArrayStateX)); 280 int Y = m_spNewPredictorY->DecompressValue(m_spUnBitArray->DecodeValueRange(m_BitArrayStateY)); 281 282 m_Prepare.Unprepare(X, Y, &m_wfeInput, m_cbFrameBuffer.GetDirectWritePointer(), &m_nCRC); 283 m_cbFrameBuffer.UpdateAfterDirectWrite(m_nBlockAlign); 284 } 285 } 286 } 287 } 288 else 289 { 290 if (m_nSpecialCodes & SPECIAL_FRAME_MONO_SILENCE) 291 { 292 for (nBlocksProcessed = 0; nBlocksProcessed < nBlocks; nBlocksProcessed++) 293 { 294 m_Prepare.Unprepare(0, 0, &m_wfeInput, m_cbFrameBuffer.GetDirectWritePointer(), &m_nCRC); 295 m_cbFrameBuffer.UpdateAfterDirectWrite(m_nBlockAlign); 296 } 297 } 298 else 299 { 300 for (nBlocksProcessed = 0; nBlocksProcessed < nBlocks; nBlocksProcessed++) 301 { 302 int X = m_spNewPredictorX->DecompressValue(m_spUnBitArray->DecodeValueRange(m_BitArrayStateX)); 303 m_Prepare.Unprepare(X, 0, &m_wfeInput, m_cbFrameBuffer.GetDirectWritePointer(), &m_nCRC); 304 m_cbFrameBuffer.UpdateAfterDirectWrite(m_nBlockAlign); 305 } 306 } 307 } 308 } 309 catch(...) 310 { 311 m_bErrorDecodingCurrentFrame = TRUE; 312 } 313 314 m_nCurrentFrameBufferBlock += nBlocks; 315 } 316 317 void CAPEDecompress::StartFrame() 318 { 319 m_nCRC = 0xFFFFFFFF; 320 321 // get the frame header 322 m_nStoredCRC = m_spUnBitArray->DecodeValue(DECODE_VALUE_METHOD_UNSIGNED_INT); 323 m_bErrorDecodingCurrentFrame = FALSE; 324 325 // get any 'special' codes if the file uses them (for silence, FALSE stereo, etc.) 326 m_nSpecialCodes = 0; 327 if (GET_USES_SPECIAL_FRAMES(m_spAPEInfo)) 328 { 329 if (m_nStoredCRC & 0x80000000) 330 { 331 m_nSpecialCodes = m_spUnBitArray->DecodeValue(DECODE_VALUE_METHOD_UNSIGNED_INT); 332 } 333 m_nStoredCRC &= 0x7FFFFFFF; 334 } 335 336 m_spNewPredictorX->Flush(); 337 m_spNewPredictorY->Flush(); 338 339 m_spUnBitArray->FlushState(m_BitArrayStateX); 340 m_spUnBitArray->FlushState(m_BitArrayStateY); 341 342 m_spUnBitArray->FlushBitArray(); 343 344 m_nLastX = 0; 345 } 346 347 void CAPEDecompress::EndFrame() 348 { 349 m_nFrameBufferFinishedBlocks += GetInfo(APE_INFO_FRAME_BLOCKS, m_nCurrentFrame); 350 m_nCurrentFrame++; 351 352 // finalize 353 m_spUnBitArray->Finalize(); 354 355 // check the CRC 356 m_nCRC = m_nCRC ^ 0xFFFFFFFF; 357 m_nCRC >>= 1; 358 if (m_nCRC != m_nStoredCRC) 359 m_bErrorDecodingCurrentFrame = TRUE; 360 } 361 362 /***************************************************************************************** 363 Seek to the proper frame (if necessary) and do any alignment of the bit array 364 *****************************************************************************************/ 365 int CAPEDecompress::SeekToFrame(int nFrameIndex) 366 { 367 int nSeekRemainder = (GetInfo(APE_INFO_SEEK_BYTE, nFrameIndex) - GetInfo(APE_INFO_SEEK_BYTE, 0)) % 4; 368 return m_spUnBitArray->FillAndResetBitArray(GetInfo(APE_INFO_SEEK_BYTE, nFrameIndex) - nSeekRemainder, nSeekRemainder * 8); 369 } 370 371 /***************************************************************************************** 372 Get information from the decompressor 373 *****************************************************************************************/ 374 int CAPEDecompress::GetInfo(APE_DECOMPRESS_FIELDS Field, int nParam1, int nParam2) 375 { 376 int nRetVal = 0; 377 BOOL bHandled = TRUE; 378 379 switch (Field) 380 { 381 case APE_DECOMPRESS_CURRENT_BLOCK: 382 nRetVal = m_nCurrentBlock - m_nStartBlock; 383 break; 384 case APE_DECOMPRESS_CURRENT_MS: 385 { 386 int nSampleRate = m_spAPEInfo->GetInfo(APE_INFO_SAMPLE_RATE, 0, 0); 387 if (nSampleRate > 0) 388 nRetVal = int((double(m_nCurrentBlock) * double(1000)) / double(nSampleRate)); 389 break; 390 } 391 case APE_DECOMPRESS_TOTAL_BLOCKS: 392 nRetVal = m_nFinishBlock - m_nStartBlock; 393 break; 394 case APE_DECOMPRESS_LENGTH_MS: 395 { 396 int nSampleRate = m_spAPEInfo->GetInfo(APE_INFO_SAMPLE_RATE, 0, 0); 397 if (nSampleRate > 0) 398 nRetVal = int((double(m_nFinishBlock - m_nStartBlock) * double(1000)) / double(nSampleRate)); 399 break; 400 } 401 case APE_DECOMPRESS_CURRENT_BITRATE: 402 nRetVal = GetInfo(APE_INFO_FRAME_BITRATE, m_nCurrentFrame); 403 break; 404 case APE_DECOMPRESS_AVERAGE_BITRATE: 405 { 406 if (m_bIsRanged) 407 { 408 // figure the frame range 409 const int nBlocksPerFrame = GetInfo(APE_INFO_BLOCKS_PER_FRAME); 410 int nStartFrame = m_nStartBlock / nBlocksPerFrame; 411 int nFinishFrame = (m_nFinishBlock + nBlocksPerFrame - 1) / nBlocksPerFrame; 412 413 // get the number of bytes in the first and last frame 414 int nTotalBytes = (GetInfo(APE_INFO_FRAME_BYTES, nStartFrame) * (m_nStartBlock % nBlocksPerFrame)) / nBlocksPerFrame; 415 if (nFinishFrame != nStartFrame) 416 nTotalBytes += (GetInfo(APE_INFO_FRAME_BYTES, nFinishFrame) * (m_nFinishBlock % nBlocksPerFrame)) / nBlocksPerFrame; 417 418 // get the number of bytes in between 419 const int nTotalFrames = GetInfo(APE_INFO_TOTAL_FRAMES); 420 for (int nFrame = nStartFrame + 1; (nFrame < nFinishFrame) && (nFrame < nTotalFrames); nFrame++) 421 nTotalBytes += GetInfo(APE_INFO_FRAME_BYTES, nFrame); 422 423 // figure the bitrate 424 int nTotalMS = int((double(m_nFinishBlock - m_nStartBlock) * double(1000)) / double(GetInfo(APE_INFO_SAMPLE_RATE))); 425 if (nTotalMS != 0) 426 nRetVal = (nTotalBytes * 8) / nTotalMS; 427 } 428 else 429 { 430 nRetVal = GetInfo(APE_INFO_AVERAGE_BITRATE); 431 } 432 433 break; 434 } 435 default: 436 bHandled = FALSE; 437 } 438 439 if (!bHandled && m_bIsRanged) 440 { 441 bHandled = TRUE; 442 443 switch (Field) 444 { 445 case APE_INFO_WAV_HEADER_BYTES: 446 nRetVal = sizeof(WAVE_HEADER); 447 break; 448 case APE_INFO_WAV_HEADER_DATA: 449 { 450 char * pBuffer = (char *) nParam1; 451 int nMaxBytes = nParam2; 452 453 if (sizeof(WAVE_HEADER) > static_cast<uint32>(nMaxBytes)) 454 { 455 nRetVal = -1; 456 } 457 else 458 { 459 WAVEFORMATEX wfeFormat; GetInfo(APE_INFO_WAVEFORMATEX, (int) &wfeFormat, 0); 460 WAVE_HEADER WAVHeader; FillWaveHeader(&WAVHeader, 461 (m_nFinishBlock - m_nStartBlock) * GetInfo(APE_INFO_BLOCK_ALIGN), 462 &wfeFormat, 0); 463 memcpy(pBuffer, &WAVHeader, sizeof(WAVE_HEADER)); 464 nRetVal = 0; 465 } 466 break; 467 } 468 case APE_INFO_WAV_TERMINATING_BYTES: 469 nRetVal = 0; 470 break; 471 case APE_INFO_WAV_TERMINATING_DATA: 472 nRetVal = 0; 473 break; 474 default: 475 bHandled = FALSE; 476 } 477 } 478 479 if (bHandled == FALSE) 480 nRetVal = m_spAPEInfo->GetInfo(Field, nParam1, nParam2); 481 482 return nRetVal; 483 } 484