xref: /haiku/src/add-ons/media/plugins/ape_reader/MAClib/MACLib.h (revision 053cc0d4fe060114342762e1e8dbbf86a9cad259)
1 /*****************************************************************************************
2 Monkey's Audio MACLib.h (include for using MACLib.lib in your projects)
3 Copyright (C) 2000-2003 by Matthew T. Ashland   All Rights Reserved.
4 
5 Overview:
6 
7 There are two main interfaces... create one (using CreateIAPExxx) and go to town:
8 
9     IAPECompress - for creating APE files
10     IAPEDecompress - for decompressing and analyzing APE files
11 
12 Note(s):
13 
14 Unless otherwise specified, functions return ERROR_SUCCESS (0) on success and an
15 error code on failure.
16 
17 The terminology "Sample" refers to a single sample value, and "Block" refers
18 to a collection    of "Channel" samples.  For simplicity, MAC typically uses blocks
19 everywhere so that channel mis-alignment cannot happen. (i.e. on a CD, a sample is
20 2 bytes and a block is 4 bytes ([2 bytes per sample] * [2 channels] = 4 bytes))
21 
22 Questions / Suggestions:
23 
24 Please direct questions or comments to the Monkey's Audio developers board:
25 http://www.monkeysaudio.com/cgi-bin/YaBB/YaBB.cgi -> Developers
26 or, if necessary, matt @ monkeysaudio.com
27 *****************************************************************************************/
28 
29 #ifndef APE_MACLIB_H
30 #define APE_MACLIB_H
31 
32 /*************************************************************************************************
33 APE File Format Overview: (pieces in order -- only valid for the latest version APE files)
34 
35     JUNK - any amount of "junk" before the APE_DESCRIPTOR (so people that put ID3v2 tags on the files aren't hosed)
36     APE_DESCRIPTOR - defines the sizes (and offsets) of all the pieces, as well as the MD5 checksum
37     APE_HEADER - describes all of the necessary information about the APE file
38     SEEK TABLE - the table that represents seek offsets [optional]
39     HEADER DATA - the pre-audio data from the original file [optional]
40     APE FRAMES - the actual compressed audio (broken into frames for seekability)
41     TERMINATING DATA - the post-audio data from the original file [optional]
42     TAG - describes all the properties of the file [optional]
43 
44 Notes:
45 
46     Junk:
47 
48     This block may not be supported in the future, so don't write any software that adds meta data
49     before the APE_DESCRIPTOR.  Please use the APE Tag for any meta data.
50 
51     Seek Table:
52 
53     A 32-bit unsigned integer array of offsets from the header to the frame data.  May become "delta"
54     values someday to better suit huge files.
55 
56     MD5 Hash:
57 
58     Since the header is the last part written to an APE file, you must calculate the MD5 checksum out of order.
59     So, you first calculate from the tail of the seek table to the end of the terminating data.
60     Then, go back and do from the end of the descriptor to the tail of the seek table.
61     You may wish to just cache the header data when starting and run it last, so you don't
62     need to seek back in the I/O.
63 *************************************************************************************************/
64 
65 #include "NoWindows.h"
66 #include "All.h"
67 
68 /*****************************************************************************************
69 Defines
70 *****************************************************************************************/
71 #define COMPRESSION_LEVEL_FAST          1000
72 #define COMPRESSION_LEVEL_NORMAL        2000
73 #define COMPRESSION_LEVEL_HIGH          3000
74 #define COMPRESSION_LEVEL_EXTRA_HIGH    4000
75 #define COMPRESSION_LEVEL_INSANE        5000
76 
77 #define MAC_FORMAT_FLAG_8_BIT                 1    // is 8-bit [OBSOLETE]
78 #define MAC_FORMAT_FLAG_CRC                   2    // uses the new CRC32 error detection [OBSOLETE]
79 #define MAC_FORMAT_FLAG_HAS_PEAK_LEVEL        4    // uint32 nPeakLevel after the header [OBSOLETE]
80 #define MAC_FORMAT_FLAG_24_BIT                8    // is 24-bit [OBSOLETE]
81 #define MAC_FORMAT_FLAG_HAS_SEEK_ELEMENTS    16    // has the number of seek elements after the peak level
82 #define MAC_FORMAT_FLAG_CREATE_WAV_HEADER    32    // create the wave header on decompression (not stored)
83 
84 #define CREATE_WAV_HEADER_ON_DECOMPRESSION    -1
85 #define MAX_AUDIO_BYTES_UNKNOWN -1
86 
87 typedef void (__stdcall * APE_PROGRESS_CALLBACK) (int);
88 
89 /*****************************************************************************************
90 WAV header structure
91 *****************************************************************************************/
92 struct WAVE_HEADER
93 {
94     // RIFF header
95     char cRIFFHeader[4];
96     unsigned int nRIFFBytes;
97 
98     // data type
99     char cDataTypeID[4];
100 
101     // wave format
102     char cFormatHeader[4];
103     unsigned int nFormatBytes;
104 
105     unsigned short nFormatTag;
106     unsigned short nChannels;
107     unsigned int nSamplesPerSec;
108     unsigned int nAvgBytesPerSec;
109     unsigned short nBlockAlign;
110     unsigned short nBitsPerSample;
111 
112     // data chunk header
113     char cDataHeader[4];
114     unsigned int nDataBytes;
115 };
116 
117 /*****************************************************************************************
118 APE_DESCRIPTOR structure (file header that describes lengths, offsets, etc.)
119 *****************************************************************************************/
120 struct APE_DESCRIPTOR
121 {
122     char    cID[4];                             // should equal 'MAC '
123     uint16  nVersion;                           // version number * 1000 (3.81 = 3810)
124 
125     uint32  nDescriptorBytes;                   // the number of descriptor bytes (allows later expansion of this header)
126     uint32  nHeaderBytes;                       // the number of header APE_HEADER bytes
127     uint32  nSeekTableBytes;                    // the number of bytes of the seek table
128     uint32  nHeaderDataBytes;                   // the number of header data bytes (from original file)
129     uint32  nAPEFrameDataBytes;                 // the number of bytes of APE frame data
130     uint32  nAPEFrameDataBytesHigh;             // the high order number of APE frame data bytes
131     uint32  nTerminatingDataBytes;              // the terminating data of the file (not including tag data)
132 
133     uint8   cFileMD5[16];                       // the MD5 hash of the file (see notes for usage... it's a littly tricky)
134 };
135 
136 /*****************************************************************************************
137 APE_HEADER structure (describes the format, duration, etc. of the APE file)
138 *****************************************************************************************/
139 struct APE_HEADER
140 {
141     uint16    nCompressionLevel;                 // the compression level (see defines I.E. COMPRESSION_LEVEL_FAST)
142     uint16    nFormatFlags;                      // any format flags (for future use)
143 
144     uint32    nBlocksPerFrame;                   // the number of audio blocks in one frame
145     uint32    nFinalFrameBlocks;                 // the number of audio blocks in the final frame
146     uint32    nTotalFrames;                      // the total number of frames
147 
148     uint16    nBitsPerSample;                    // the bits per sample (typically 16)
149     uint16    nChannels;                         // the number of channels (1 or 2)
150     uint32    nSampleRate;                       // the sample rate (typically 44100)
151 };
152 
153 /*************************************************************************************************
154 Classes (fully defined elsewhere)
155 *************************************************************************************************/
156 class CIO;
157 class CInputSource;
158 class CAPEInfo;
159 
160 /*************************************************************************************************
161 IAPEDecompress fields - used when querying for information
162 
163 Note(s):
164 -the distinction between APE_INFO_XXXX and APE_DECOMPRESS_XXXX is that the first is querying the APE
165 information engine, and the other is querying the decompressor, and since the decompressor can be
166 a range of an APE file (for APL), differences will arise.  Typically, use the APE_DECOMPRESS_XXXX
167 fields when querying for info about the length, etc. so APL will work properly.
168 (i.e. (APE_INFO_TOTAL_BLOCKS != APE_DECOMPRESS_TOTAL_BLOCKS) for APL files)
169 *************************************************************************************************/
170 enum APE_DECOMPRESS_FIELDS
171 {
172     APE_INFO_FILE_VERSION = 1000,               // version of the APE file * 1000 (3.93 = 3930) [ignored, ignored]
173     APE_INFO_COMPRESSION_LEVEL = 1001,          // compression level of the APE file [ignored, ignored]
174     APE_INFO_FORMAT_FLAGS = 1002,               // format flags of the APE file [ignored, ignored]
175     APE_INFO_SAMPLE_RATE = 1003,                // sample rate (Hz) [ignored, ignored]
176     APE_INFO_BITS_PER_SAMPLE = 1004,            // bits per sample [ignored, ignored]
177     APE_INFO_BYTES_PER_SAMPLE = 1005,           // number of bytes per sample [ignored, ignored]
178     APE_INFO_CHANNELS = 1006,                   // channels [ignored, ignored]
179     APE_INFO_BLOCK_ALIGN = 1007,                // block alignment [ignored, ignored]
180     APE_INFO_BLOCKS_PER_FRAME = 1008,           // number of blocks in a frame (frames are used internally)  [ignored, ignored]
181     APE_INFO_FINAL_FRAME_BLOCKS = 1009,         // blocks in the final frame (frames are used internally) [ignored, ignored]
182     APE_INFO_TOTAL_FRAMES = 1010,               // total number frames (frames are used internally) [ignored, ignored]
183     APE_INFO_WAV_HEADER_BYTES = 1011,           // header bytes of the decompressed WAV [ignored, ignored]
184     APE_INFO_WAV_TERMINATING_BYTES = 1012,      // terminating bytes of the decompressed WAV [ignored, ignored]
185     APE_INFO_WAV_DATA_BYTES = 1013,             // data bytes of the decompressed WAV [ignored, ignored]
186     APE_INFO_WAV_TOTAL_BYTES = 1014,            // total bytes of the decompressed WAV [ignored, ignored]
187     APE_INFO_APE_TOTAL_BYTES = 1015,            // total bytes of the APE file [ignored, ignored]
188     APE_INFO_TOTAL_BLOCKS = 1016,               // total blocks of audio data [ignored, ignored]
189     APE_INFO_LENGTH_MS = 1017,                  // length in ms (1 sec = 1000 ms) [ignored, ignored]
190     APE_INFO_AVERAGE_BITRATE = 1018,            // average bitrate of the APE [ignored, ignored]
191     APE_INFO_FRAME_BITRATE = 1019,              // bitrate of specified APE frame [frame index, ignored]
192     APE_INFO_DECOMPRESSED_BITRATE = 1020,       // bitrate of the decompressed WAV [ignored, ignored]
193     APE_INFO_PEAK_LEVEL = 1021,                 // peak audio level (obsolete) (-1 is unknown) [ignored, ignored]
194     APE_INFO_SEEK_BIT = 1022,                   // bit offset [frame index, ignored]
195     APE_INFO_SEEK_BYTE = 1023,                  // byte offset [frame index, ignored]
196     APE_INFO_WAV_HEADER_DATA = 1024,            // error code [buffer *, max bytes]
197     APE_INFO_WAV_TERMINATING_DATA = 1025,       // error code [buffer *, max bytes]
198     APE_INFO_WAVEFORMATEX = 1026,               // error code [waveformatex *, ignored]
199     APE_INFO_IO_SOURCE = 1027,                  // I/O source (CIO *) [ignored, ignored]
200     APE_INFO_FRAME_BYTES = 1028,                // bytes (compressed) of the frame [frame index, ignored]
201     APE_INFO_FRAME_BLOCKS = 1029,               // blocks in a given frame [frame index, ignored]
202     APE_INFO_TAG = 1030,                        // point to tag (CAPETag *) [ignored, ignored]
203 
204     APE_DECOMPRESS_CURRENT_BLOCK = 2000,        // current block location [ignored, ignored]
205     APE_DECOMPRESS_CURRENT_MS = 2001,           // current millisecond location [ignored, ignored]
206     APE_DECOMPRESS_TOTAL_BLOCKS = 2002,         // total blocks in the decompressors range [ignored, ignored]
207     APE_DECOMPRESS_LENGTH_MS = 2003,            // total blocks in the decompressors range [ignored, ignored]
208     APE_DECOMPRESS_CURRENT_BITRATE = 2004,      // current bitrate [ignored, ignored]
209     APE_DECOMPRESS_AVERAGE_BITRATE = 2005,      // average bitrate (works with ranges) [ignored, ignored]
210 
211     APE_INTERNAL_INFO = 3000,                   // for internal use -- don't use (returns APE_FILE_INFO *) [ignored, ignored]
212 };
213 
214 /*************************************************************************************************
215 IAPEDecompress - interface for working with existing APE files (decoding, seeking, analyzing, etc.)
216 *************************************************************************************************/
217 class IAPEDecompress
218 {
219 public:
220 
221     // destructor (needed so implementation's destructor will be called)
~IAPEDecompress()222     virtual ~IAPEDecompress() {}
223 
224     /*********************************************************************************************
225     * Decompress / Seek
226     *********************************************************************************************/
227 
228     //////////////////////////////////////////////////////////////////////////////////////////////
229     // GetData(...) - gets raw decompressed audio
230     //
231     // Parameters:
232     //    char * pBuffer
233     //        a pointer to a buffer to put the data into
234     //    int nBlocks
235     //        the number of audio blocks desired (see note at intro about blocks vs. samples)
236     //    int * pBlocksRetrieved
237     //        the number of blocks actually retrieved (could be less at end of file or on critical failure)
238     //////////////////////////////////////////////////////////////////////////////////////////////
239     virtual int GetData(char * pBuffer, int nBlocks, int * pBlocksRetrieved) = 0;
240 
241     //////////////////////////////////////////////////////////////////////////////////////////////
242     // Seek(...) - seeks
243     //
244     // Parameters:
245     //    int nBlockOffset
246     //        the block to seek to (see note at intro about blocks vs. samples)
247     //////////////////////////////////////////////////////////////////////////////////////////////
248     virtual int Seek(int nBlockOffset) = 0;
249 
250     /*********************************************************************************************
251     * Get Information
252     *********************************************************************************************/
253 
254     //////////////////////////////////////////////////////////////////////////////////////////////
255     // GetInfo(...) - get information about the APE file or the state of the decompressor
256     //
257     // Parameters:
258     //    APE_DECOMPRESS_FIELDS Field
259     //        the field we're querying (see APE_DECOMPRESS_FIELDS above for more info)
260     //    int nParam1
261     //        generic parameter... usage is listed in APE_DECOMPRESS_FIELDS
262     //    int nParam2
263     //        generic parameter... usage is listed in APE_DECOMPRESS_FIELDS
264     //////////////////////////////////////////////////////////////////////////////////////////////
265     virtual int GetInfo(APE_DECOMPRESS_FIELDS Field, int nParam1 = 0, int nParam2 = 0) = 0;
266 };
267 
268 /*************************************************************************************************
269 IAPECompress - interface for creating APE files
270 
271 Usage:
272 
273     To create an APE file, you Start(...), then add data (in a variety of ways), then Finish(...)
274 *************************************************************************************************/
275 class IAPECompress
276 {
277 public:
278 
279     // destructor (needed so implementation's destructor will be called)
~IAPECompress()280     virtual ~IAPECompress() {}
281 
282     /*********************************************************************************************
283     * Start
284     *********************************************************************************************/
285 
286     //////////////////////////////////////////////////////////////////////////////////////////////
287     // Start(...) / StartEx(...) - starts encoding
288     //
289     // Parameters:
290     //    CIO * pioOutput / const str_utf16 * pFilename
291     //        the output... either a filename or an I/O source
292     //    WAVEFORMATEX * pwfeInput
293     //        format of the audio to encode (use FillWaveFormatEx() if necessary)
294     //    int nMaxAudioBytes
295     //        the absolute maximum audio bytes that will be encoded... encoding fails with a
296     //        ERROR_APE_COMPRESS_TOO_MUCH_DATA if you attempt to encode more than specified here
297     //        (if unknown, use MAX_AUDIO_BYTES_UNKNOWN to allocate as much storage in the seek table as
298     //        possible... limit is then 2 GB of data (~4 hours of CD music)... this wastes around
299     //        30kb, so only do it if completely necessary)
300     //    int nCompressionLevel
301     //        the compression level for the APE file (fast - extra high)
302     //        (note: extra-high is much slower for little gain)
303     //    const void * pHeaderData
304     //        a pointer to a buffer containing the WAV header (data before the data block in the WAV)
305     //        (note: use NULL for on-the-fly encoding... see next parameter)
306     //    int nHeaderBytes
307     //        number of bytes in the header data buffer (use CREATE_WAV_HEADER_ON_DECOMPRESSION and
308     //        NULL for the pHeaderData and MAC will automatically create the appropriate WAV header
309     //        on decompression)
310     //////////////////////////////////////////////////////////////////////////////////////////////
311 
312     virtual int Start(const str_utf16 * pOutputFilename, const WAVEFORMATEX * pwfeInput,
313         int nMaxAudioBytes = MAX_AUDIO_BYTES_UNKNOWN, int nCompressionLevel = COMPRESSION_LEVEL_NORMAL,
314         const void * pHeaderData = NULL, int nHeaderBytes = CREATE_WAV_HEADER_ON_DECOMPRESSION) = 0;
315 
316     virtual int StartEx(CIO * pioOutput, const WAVEFORMATEX * pwfeInput,
317         int nMaxAudioBytes = MAX_AUDIO_BYTES_UNKNOWN, int nCompressionLevel = COMPRESSION_LEVEL_NORMAL,
318         const void * pHeaderData = NULL, int nHeaderBytes = CREATE_WAV_HEADER_ON_DECOMPRESSION) = 0;
319 
320     /*********************************************************************************************
321     * Add / Compress Data
322     *    - there are 3 ways to add data:
323     *        1) simple call AddData(...)
324     *        2) lock MAC's buffer, copy into it, and unlock (LockBuffer(...) / UnlockBuffer(...))
325     *        3) from an I/O source (AddDataFromInputSource(...))
326     *********************************************************************************************/
327 
328     //////////////////////////////////////////////////////////////////////////////////////////////
329     // AddData(...) - adds data to the encoder
330     //
331     // Parameters:
332     //    unsigned char * pData
333     //        a pointer to a buffer containing the raw audio data
334     //    int nBytes
335     //        the number of bytes in the buffer
336     //////////////////////////////////////////////////////////////////////////////////////////////
337     virtual int AddData(unsigned char * pData, int nBytes) = 0;
338 
339     //////////////////////////////////////////////////////////////////////////////////////////////
340     // GetBufferBytesAvailable(...) - returns the number of bytes available in the buffer
341     //    (helpful when locking)
342     //////////////////////////////////////////////////////////////////////////////////////////////
343     virtual int GetBufferBytesAvailable() = 0;
344 
345     //////////////////////////////////////////////////////////////////////////////////////////////
346     // LockBuffer(...) - locks MAC's buffer so we can copy into it
347     //
348     // Parameters:
349     //    int * pBytesAvailable
350     //        returns the number of bytes available in the buffer (DO NOT COPY MORE THAN THIS IN)
351     //
352     // Return:
353     //    pointer to the buffer (add at that location)
354     //////////////////////////////////////////////////////////////////////////////////////////////
355     virtual unsigned char * LockBuffer(int * pBytesAvailable) = 0;
356 
357     //////////////////////////////////////////////////////////////////////////////////////////////
358     // UnlockBuffer(...) - releases the buffer
359     //
360     // Parameters:
361     //    int nBytesAdded
362     //        the number of bytes copied into the buffer
363     //    BOOL bProcess
364     //        whether MAC should process as much as possible of the buffer
365     //////////////////////////////////////////////////////////////////////////////////////////////
366     virtual int UnlockBuffer(int nBytesAdded, BOOL bProcess = TRUE) = 0;
367 
368 
369     //////////////////////////////////////////////////////////////////////////////////////////////
370     // AddDataFromInputSource(...) - use a CInputSource (input source) to add data
371     //
372     // Parameters:
373     //    CInputSource * pInputSource
374     //        a pointer to the input source
375     //    int nMaxBytes
376     //        the maximum number of bytes to let MAC add (-1 if MAC can add any amount)
377     //    int * pBytesAdded
378     //        returns the number of bytes added from the I/O source
379     //////////////////////////////////////////////////////////////////////////////////////////////
380     virtual int AddDataFromInputSource(CInputSource * pInputSource, int nMaxBytes = -1, int * pBytesAdded = NULL) = 0;
381 
382     /*********************************************************************************************
383     * Finish / Kill
384     *********************************************************************************************/
385 
386     //////////////////////////////////////////////////////////////////////////////////////////////
387     // Finish(...) - ends encoding and finalizes the file
388     //
389     // Parameters:
390     //    unsigned char * pTerminatingData
391     //        a pointer to a buffer containing the information to place at the end of the APE file
392     //        (comprised of the WAV terminating data (data after the data block in the WAV) followed
393     //        by any tag information)
394     //    int nTerminatingBytes
395     //        number of bytes in the terminating data buffer
396     //    int nWAVTerminatingBytes
397     //        the number of bytes of the terminating data buffer that should be appended to a decoded
398     //        WAV file (it's basically nTerminatingBytes - the bytes that make up the tag)
399     //////////////////////////////////////////////////////////////////////////////////////////////
400     virtual int Finish(unsigned char * pTerminatingData, int nTerminatingBytes, int nWAVTerminatingBytes) = 0;
401 
402     //////////////////////////////////////////////////////////////////////////////////////////////
403     // Kill(...) - stops encoding and deletes the output file
404     // --- NOT CURRENTLY IMPLEMENTED ---
405     //////////////////////////////////////////////////////////////////////////////////////////////
406     virtual int Kill() = 0;
407 };
408 
409 /*************************************************************************************************
410 Functions to create the interfaces
411 
412 Usage:
413     Interface creation returns a NULL pointer on failure (and fills error code if it was passed in)
414 
415 Usage example:
416     int nErrorCode;
417     IAPEDecompress * pAPEDecompress = CreateIAPEDecompress("c:\\1.ape", &nErrorCode);
418     if (pAPEDecompress == NULL)
419     {
420         // failure... nErrorCode will have specific code
421     }
422 
423 *************************************************************************************************/
424 extern "C"
425 {
426     IAPEDecompress * __stdcall CreateIAPEDecompress(const str_utf16 * pFilename, int * pErrorCode = NULL);
427     IAPEDecompress * __stdcall CreateIAPEDecompressEx(CIO * pIO, int * pErrorCode = NULL);
428     IAPEDecompress * __stdcall CreateIAPEDecompressEx2(CAPEInfo * pAPEInfo, int nStartBlock = -1, int nFinishBlock = -1, int * pErrorCode = NULL);
429     IAPECompress * __stdcall CreateIAPECompress(int * pErrorCode = NULL);
430 }
431 
432 /*************************************************************************************************
433 Simple functions - see the SDK sample projects for usage examples
434 *************************************************************************************************/
435 extern "C"
436 {
437     // process whole files
438     DLLEXPORT int __stdcall CompressFile(const str_ansi * pInputFilename, const str_ansi * pOutputFilename, int nCompressionLevel = COMPRESSION_LEVEL_NORMAL, int * pPercentageDone = NULL, APE_PROGRESS_CALLBACK ProgressCallback = 0, int * pKillFlag = NULL);
439     DLLEXPORT int __stdcall DecompressFile(const str_ansi * pInputFilename, const str_ansi * pOutputFilename, int * pPercentageDone, APE_PROGRESS_CALLBACK ProgressCallback, int * pKillFlag);
440     DLLEXPORT int __stdcall ConvertFile(const str_ansi * pInputFilename, const str_ansi * pOutputFilename, int nCompressionLevel, int * pPercentageDone, APE_PROGRESS_CALLBACK ProgressCallback, int * pKillFlag);
441     DLLEXPORT int __stdcall VerifyFile(const str_ansi * pInputFilename, int * pPercentageDone, APE_PROGRESS_CALLBACK ProgressCallback, int * pKillFlag, BOOL bQuickVerifyIfPossible);
442 
443     DLLEXPORT int __stdcall CompressFileW(const str_utf16 * pInputFilename, const str_utf16 * pOutputFilename, int nCompressionLevel = COMPRESSION_LEVEL_NORMAL, int * pPercentageDone = NULL, APE_PROGRESS_CALLBACK ProgressCallback = 0, int * pKillFlag = NULL);
444     DLLEXPORT int __stdcall DecompressFileW(const str_utf16 * pInputFilename, const str_utf16 * pOutputFilename, int * pPercentageDone, APE_PROGRESS_CALLBACK ProgressCallback, int * pKillFlag);
445     DLLEXPORT int __stdcall ConvertFileW(const str_utf16 * pInputFilename, const str_utf16 * pOutputFilename, int nCompressionLevel, int * pPercentageDone, APE_PROGRESS_CALLBACK ProgressCallback, int * pKillFlag);
446     DLLEXPORT int __stdcall VerifyFileW(const str_utf16 * pInputFilename, int * pPercentageDone, APE_PROGRESS_CALLBACK ProgressCallback, int * pKillFlag, BOOL bQuickVerifyIfPossible = FALSE);
447 
448     // helper functions
449     DLLEXPORT int __stdcall FillWaveFormatEx(WAVEFORMATEX * pWaveFormatEx, int nSampleRate = 44100, int nBitsPerSample = 16, int nChannels = 2);
450     DLLEXPORT int __stdcall FillWaveHeader(WAVE_HEADER * pWAVHeader, int nAudioBytes, WAVEFORMATEX * pWaveFormatEx, int nTerminatingBytes = 0);
451 }
452 
453 #endif // #ifndef APE_MACLIB_H
454