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