1 #include "All.h" 2 #include "APECompress.h" 3 #include IO_HEADER_FILE 4 #include "APECompressCreate.h" 5 #include "WAVInputSource.h" 6 7 CAPECompress::CAPECompress() 8 { 9 m_nBufferHead = 0; 10 m_nBufferTail = 0; 11 m_nBufferSize = 0; 12 m_bBufferLocked = FALSE; 13 m_bOwnsOutputIO = FALSE; 14 m_pioOutput = NULL; 15 16 m_spAPECompressCreate.Assign(new CAPECompressCreate()); 17 18 m_pBuffer = NULL; 19 } 20 21 CAPECompress::~CAPECompress() 22 { 23 SAFE_ARRAY_DELETE(m_pBuffer) 24 25 if (m_bOwnsOutputIO) 26 { 27 SAFE_DELETE(m_pioOutput) 28 } 29 } 30 31 int CAPECompress::Start(const char* pOutputFilename, const WAVEFORMATEX * pwfeInput, int nMaxAudioBytes, int nCompressionLevel, const void * pHeaderData, int nHeaderBytes) 32 { 33 m_pioOutput = new IO_CLASS_NAME; 34 m_bOwnsOutputIO = TRUE; 35 36 if (m_pioOutput->Create(pOutputFilename) != 0) 37 { 38 return ERROR_INVALID_OUTPUT_FILE; 39 } 40 41 m_spAPECompressCreate->Start(m_pioOutput, pwfeInput, nMaxAudioBytes, nCompressionLevel, 42 pHeaderData, nHeaderBytes); 43 44 SAFE_ARRAY_DELETE(m_pBuffer) 45 m_nBufferSize = m_spAPECompressCreate->GetFullFrameBytes(); 46 m_pBuffer = new unsigned char [m_nBufferSize]; 47 memcpy(&m_wfeInput, pwfeInput, sizeof(WAVEFORMATEX)); 48 49 return ERROR_SUCCESS; 50 } 51 52 int CAPECompress::StartEx(CIO * pioOutput, const WAVEFORMATEX * pwfeInput, int nMaxAudioBytes, int nCompressionLevel, const void * pHeaderData, int nHeaderBytes) 53 { 54 m_pioOutput = pioOutput; 55 m_bOwnsOutputIO = FALSE; 56 57 m_spAPECompressCreate->Start(m_pioOutput, pwfeInput, nMaxAudioBytes, nCompressionLevel, 58 pHeaderData, nHeaderBytes); 59 60 SAFE_ARRAY_DELETE(m_pBuffer) 61 m_nBufferSize = m_spAPECompressCreate->GetFullFrameBytes(); 62 m_pBuffer = new unsigned char [m_nBufferSize]; 63 memcpy(&m_wfeInput, pwfeInput, sizeof(WAVEFORMATEX)); 64 65 return ERROR_SUCCESS; 66 } 67 68 int CAPECompress::GetBufferBytesAvailable() 69 { 70 return m_nBufferSize - m_nBufferTail; 71 } 72 73 int CAPECompress::UnlockBuffer(int nBytesAdded, BOOL bProcess) 74 { 75 if (m_bBufferLocked == FALSE) 76 return ERROR_UNDEFINED; 77 78 m_nBufferTail += nBytesAdded; 79 m_bBufferLocked = FALSE; 80 81 if (bProcess) 82 { 83 int nRetVal = ProcessBuffer(); 84 if (nRetVal != 0) { return nRetVal; } 85 } 86 87 return ERROR_SUCCESS; 88 } 89 90 unsigned char * CAPECompress::LockBuffer(int * pBytesAvailable) 91 { 92 if (m_pBuffer == NULL) { return NULL; } 93 94 if (m_bBufferLocked) 95 return NULL; 96 97 m_bBufferLocked = TRUE; 98 99 if (pBytesAvailable) 100 *pBytesAvailable = GetBufferBytesAvailable(); 101 102 return &m_pBuffer[m_nBufferTail]; 103 } 104 105 int CAPECompress::AddData(unsigned char * pData, int nBytes) 106 { 107 if (m_pBuffer == NULL) return ERROR_INSUFFICIENT_MEMORY; 108 109 int nBytesDone = 0; 110 111 while (nBytesDone < nBytes) 112 { 113 // lock the buffer 114 int nBytesAvailable = 0; 115 unsigned char * pBuffer = LockBuffer(&nBytesAvailable); 116 if (pBuffer == NULL || nBytesAvailable <= 0) 117 return ERROR_UNDEFINED; 118 119 // calculate how many bytes to copy and add that much to the buffer 120 int nBytesToProcess = min(nBytesAvailable, nBytes - nBytesDone); 121 memcpy(pBuffer, &pData[nBytesDone], nBytesToProcess); 122 123 // unlock the buffer (fail if not successful) 124 int nRetVal = UnlockBuffer(nBytesToProcess); 125 if (nRetVal != ERROR_SUCCESS) 126 return nRetVal; 127 128 // update our progress 129 nBytesDone += nBytesToProcess; 130 } 131 132 return ERROR_SUCCESS; 133 } 134 135 int CAPECompress::Finish(unsigned char * pTerminatingData, int nTerminatingBytes, int nWAVTerminatingBytes) 136 { 137 RETURN_ON_ERROR(ProcessBuffer(TRUE)) 138 return m_spAPECompressCreate->Finish(pTerminatingData, nTerminatingBytes, nWAVTerminatingBytes); 139 } 140 141 int CAPECompress::Kill() 142 { 143 return ERROR_SUCCESS; 144 } 145 146 int CAPECompress::ProcessBuffer(BOOL bFinalize) 147 { 148 if (m_pBuffer == NULL) { return ERROR_UNDEFINED; } 149 150 try 151 { 152 // process as much as possible 153 int nThreshold = (bFinalize) ? 0 : m_spAPECompressCreate->GetFullFrameBytes(); 154 155 while ((m_nBufferTail - m_nBufferHead) >= nThreshold) 156 { 157 int nFrameBytes = min(m_spAPECompressCreate->GetFullFrameBytes(), m_nBufferTail - m_nBufferHead); 158 159 if (nFrameBytes == 0) 160 break; 161 162 int nRetVal = m_spAPECompressCreate->EncodeFrame(&m_pBuffer[m_nBufferHead], nFrameBytes); 163 if (nRetVal != 0) { return nRetVal; } 164 165 m_nBufferHead += nFrameBytes; 166 } 167 168 // shift the buffer 169 if (m_nBufferHead != 0) 170 { 171 int nBytesLeft = m_nBufferTail - m_nBufferHead; 172 173 if (nBytesLeft != 0) 174 memmove(m_pBuffer, &m_pBuffer[m_nBufferHead], nBytesLeft); 175 176 m_nBufferTail -= m_nBufferHead; 177 m_nBufferHead = 0; 178 } 179 } 180 catch(...) 181 { 182 return ERROR_UNDEFINED; 183 } 184 185 return ERROR_SUCCESS; 186 } 187 188 int CAPECompress::AddDataFromInputSource(CInputSource * pInputSource, int nMaxBytes, int * pBytesAdded) 189 { 190 // error check the parameters 191 if (pInputSource == NULL) return ERROR_BAD_PARAMETER; 192 193 // initialize 194 if (pBytesAdded) *pBytesAdded = 0; 195 196 // lock the buffer 197 int nBytesAvailable = 0; 198 unsigned char * pBuffer = LockBuffer(&nBytesAvailable); 199 if ((pBuffer == NULL) || (nBytesAvailable == 0)) 200 return ERROR_INSUFFICIENT_MEMORY; 201 202 // calculate the 'ideal' number of bytes 203 unsigned int nBytesRead = 0; 204 205 int nIdealBytes = m_spAPECompressCreate->GetFullFrameBytes() - (m_nBufferTail - m_nBufferHead); 206 if (nIdealBytes > 0) 207 { 208 // get the data 209 int nBytesToAdd = nBytesAvailable; 210 211 if (nMaxBytes > 0) 212 { 213 if (nBytesToAdd > nMaxBytes) nBytesToAdd = nMaxBytes; 214 } 215 216 if (nBytesToAdd > nIdealBytes) nBytesToAdd = nIdealBytes; 217 218 // always make requests along block boundaries 219 while ((nBytesToAdd % m_wfeInput.nBlockAlign) != 0) 220 nBytesToAdd--; 221 222 int nBlocksToAdd = nBytesToAdd / m_wfeInput.nBlockAlign; 223 224 // get data 225 int nBlocksAdded = 0; 226 int nRetVal = pInputSource->GetData(pBuffer, nBlocksToAdd, &nBlocksAdded); 227 if (nRetVal != 0) 228 return ERROR_IO_READ; 229 else 230 nBytesRead = (nBlocksAdded * m_wfeInput.nBlockAlign); 231 232 // store the bytes read 233 if (pBytesAdded) 234 *pBytesAdded = nBytesRead; 235 } 236 237 // unlock the data and process 238 int nRetVal = UnlockBuffer(nBytesRead, TRUE); 239 if (nRetVal != 0) 240 { 241 return nRetVal; 242 } 243 244 return ERROR_SUCCESS; 245 } 246 247