1 #include "All.h"
2 #include "APECompress.h"
3 #include IO_HEADER_FILE
4 #include "APECompressCreate.h"
5 #include "WAVInputSource.h"
6
CAPECompress()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
~CAPECompress()21 CAPECompress::~CAPECompress()
22 {
23 SAFE_ARRAY_DELETE(m_pBuffer)
24
25 if (m_bOwnsOutputIO)
26 {
27 SAFE_DELETE(m_pioOutput)
28 }
29 }
30
Start(const char * pOutputFilename,const WAVEFORMATEX * pwfeInput,int nMaxAudioBytes,int nCompressionLevel,const void * pHeaderData,int nHeaderBytes)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
StartEx(CIO * pioOutput,const WAVEFORMATEX * pwfeInput,int nMaxAudioBytes,int nCompressionLevel,const void * pHeaderData,int nHeaderBytes)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
GetBufferBytesAvailable()68 int CAPECompress::GetBufferBytesAvailable()
69 {
70 return m_nBufferSize - m_nBufferTail;
71 }
72
UnlockBuffer(int nBytesAdded,BOOL bProcess)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
LockBuffer(int * pBytesAvailable)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
AddData(unsigned char * pData,int nBytes)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
Finish(unsigned char * pTerminatingData,int nTerminatingBytes,int nWAVTerminatingBytes)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
Kill()141 int CAPECompress::Kill()
142 {
143 return ERROR_SUCCESS;
144 }
145
ProcessBuffer(BOOL bFinalize)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
AddDataFromInputSource(CInputSource * pInputSource,int nMaxBytes,int * pBytesAdded)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