123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696 |
- #include "precompile.h"
- #ifdef _WIN32
- /*this header is used by windows multi-media*/
- #include <mmreg.h>
- #endif
- #include "wavfile.h"
- #include "memutil.h"
- static const unsigned char pcm8toalaw[] = {
- 42,
- 42,42,42,43,43,43,43,40,40,40,40,41,41,41,41,46,
- 46,46,46,47,47,47,47,44,44,44,44,45,45,45,45,34,
- 34,34,34,35,35,35,35,32,32,32,32,33,33,33,33,38,
- 38,38,38,39,39,39,39,36,36,36,36,37,37,37,37,58,
- 58,59,59,56,56,57,57,62,62,63,63,60,60,61,61,50,
- 50,51,51,48,48,49,49,54,54,55,55,52,52,53,53,10,
- 11,8,9,14,15,12,13,2,3,0,1,6,7,4,5,26,
- 24,30,28,18,16,22,20,106,110,98,102,122,114,74,90,213,
- 197,245,253,229,225,237,233,149,151,145,147,157,159,153,155,133,
- 132,135,134,129,128,131,130,141,140,143,142,137,136,139,138,181,
- 181,180,180,183,183,182,182,177,177,176,176,179,179,178,178,189,
- 189,188,188,191,191,190,190,185,185,184,184,187,187,186,186,165,
- 165,165,165,164,164,164,164,167,167,167,167,166,166,166,166,161,
- 161,161,161,160,160,160,160,163,163,163,163,162,162,162,162,173,
- 173,173,173,172,172,172,172,175,175,175,175,174,174,174,174,169,
- 169,169,169,168,168,168,168,171,171,171,171,170,170,170,170,};
- static const unsigned char pcm8tomulaw[] = {
- 0,
- 0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,
- 4,4,4,4,5,5,5,5,6,6,6,6,7,7,7,7,
- 8,8,8,8,9,9,9,9,10,10,10,10,11,11,11,11,
- 12,12,12,12,13,13,13,13,14,14,14,14,15,15,15,15,
- 16,16,17,17,18,18,19,19,20,20,21,21,22,22,23,23,
- 24,24,25,25,26,26,27,27,28,28,29,29,30,30,31,31,
- 32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,
- 48,50,52,54,56,58,60,62,65,69,73,77,83,91,103,255,
- 231,219,211,205,201,197,193,190,188,186,184,182,180,178,176,175,
- 174,173,172,171,170,169,168,167,166,165,164,163,162,161,160,159,
- 159,158,158,157,157,156,156,155,155,154,154,153,153,152,152,151,
- 151,150,150,149,149,148,148,147,147,146,146,145,145,144,144,143,
- 143,143,143,142,142,142,142,141,141,141,141,140,140,140,140,139,
- 139,139,139,138,138,138,138,137,137,137,137,136,136,136,136,135,
- 135,135,135,134,134,134,134,133,133,133,133,132,132,132,132,131,
- 131,131,131,130,130,130,130,129,129,129,129,128,128,128,128,};
- static const unsigned char alawtopcm8[] = {
- 106,
- 107,104,105,110,111,108,109,98,99,96,97,102,103,100,101,117,
- 117,116,116,119,119,118,118,113,113,112,112,115,115,114,114,42,
- 46,34,38,58,62,50,54,10,14,2,6,26,30,18,22,85,
- 87,81,83,93,95,89,91,69,71,65,67,77,79,73,75,126,
- 126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,127,
- 127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,122,
- 122,122,122,123,123,123,123,120,120,120,120,121,121,121,121,125,
- 125,125,125,125,125,125,125,124,124,124,124,124,124,124,124,149,
- 148,151,150,145,144,147,146,157,156,159,158,153,152,155,154,138,
- 138,139,139,136,136,137,137,142,142,143,143,140,140,141,141,214,
- 210,222,218,198,194,206,202,246,242,254,250,230,226,238,234,171,
- 169,175,173,163,161,167,165,187,185,191,189,179,177,183,181,129,
- 129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,128,
- 128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,133,
- 133,133,133,132,132,132,132,135,135,135,135,134,134,134,134,130,
- 130,130,130,130,130,130,130,131,131,131,131,131,131,131,131,};
- static const unsigned char ulawtopcm8[] = {
- 2,6,10,14,18,22,26,30,34,38,42,46,50,
- 54,58,62,65,67,69,71,73,75,77,79,81,
- 83,85,87,89,91,93,95,97,98,99,100,101,
- 102,103,104,105,106,107,108,109,110,111,112,112,
- 113,113,114,114,115,115,116,116,117,117,118,118,
- 119,119,120,120,120,121,121,121,121,122,122,122,
- 122,123,123,123,123,124,124,124,124,124,124,125,
- 125,125,125,125,125,125,125,126,126,126,126,126,
- 126,126,126,126,126,126,126,127,127,127,127,127,
- 127,127,127,127,127,127,127,127,127,127,127,127,
- 127,127,127,127,127,127,128,253,249,245,241,237,
- 233,229,225,221,217,213,209,205,201,197,193,190,
- 188,186,184,182,180,178,176,174,172,170,168,166,
- 164,162,160,158,157,156,155,154,153,152,151,150,
- 149,148,147,146,145,144,143,143,142,142,141,141,
- 140,140,139,139,138,138,137,137,136,136,135,135,
- 135,134,134,134,134,133,133,133,133,132,132,132,
- 132,131,131,131,131,131,131,130,130,130,130,130,
- 130,130,130,129,129,129,129,129,129,129,129,129,
- 129,129,129,128,128,128,128,128,128,128,128,128,
- 128,128,128,128,128,128,128,128,128,128,128,128,
- 128,128,128,};
- /* Copied from the CCITT G.711 specification */
- static const uint8_t ulaw_to_alaw_table[256] =
- {
- 42, 43, 40, 41, 46, 47, 44, 45, 34, 35, 32, 33, 38, 39, 36, 37,
- 58, 59, 56, 57, 62, 63, 60, 61, 50, 51, 48, 49, 54, 55, 52, 53,
- 10, 11, 8, 9, 14, 15, 12, 13, 2, 3, 0, 1, 6, 7, 4, 26,
- 27, 24, 25, 30, 31, 28, 29, 18, 19, 16, 17, 22, 23, 20, 21, 106,
- 104, 105, 110, 111, 108, 109, 98, 99, 96, 97, 102, 103, 100, 101, 122, 120,
- 126, 127, 124, 125, 114, 115, 112, 113, 118, 119, 116, 117, 75, 73, 79, 77,
- 66, 67, 64, 65, 70, 71, 68, 69, 90, 91, 88, 89, 94, 95, 92, 93,
- 82, 82, 83, 83, 80, 80, 81, 81, 86, 86, 87, 87, 84, 84, 85, 85,
- 170, 171, 168, 169, 174, 175, 172, 173, 162, 163, 160, 161, 166, 167, 164, 165,
- 186, 187, 184, 185, 190, 191, 188, 189, 178, 179, 176, 177, 182, 183, 180, 181,
- 138, 139, 136, 137, 142, 143, 140, 141, 130, 131, 128, 129, 134, 135, 132, 154,
- 155, 152, 153, 158, 159, 156, 157, 146, 147, 144, 145, 150, 151, 148, 149, 234,
- 232, 233, 238, 239, 236, 237, 226, 227, 224, 225, 230, 231, 228, 229, 250, 248,
- 254, 255, 252, 253, 242, 243, 240, 241, 246, 247, 244, 245, 203, 201, 207, 205,
- 194, 195, 192, 193, 198, 199, 196, 197, 218, 219, 216, 217, 222, 223, 220, 221,
- 210, 210, 211, 211, 208, 208, 209, 209, 214, 214, 215, 215, 212, 212, 213, 213
- };
- /* These transcoding tables are copied from the CCITT G.711 specification. To achieve
- optimal results, do not change them. */
- static const uint8_t alaw_to_ulaw_table[256] =
- {
- 42, 43, 40, 41, 46, 47, 44, 45, 34, 35, 32, 33, 38, 39, 36, 37,
- 57, 58, 55, 56, 61, 62, 59, 60, 49, 50, 47, 48, 53, 54, 51, 52,
- 10, 11, 8, 9, 14, 15, 12, 13, 2, 3, 0, 1, 6, 7, 4, 5,
- 26, 27, 24, 25, 30, 31, 28, 29, 18, 19, 16, 17, 22, 23, 20, 21,
- 98, 99, 96, 97, 102, 103, 100, 101, 93, 93, 92, 92, 95, 95, 94, 94,
- 116, 118, 112, 114, 124, 126, 120, 122, 106, 107, 104, 105, 110, 111, 108, 109,
- 72, 73, 70, 71, 76, 77, 74, 75, 64, 65, 63, 63, 68, 69, 66, 67,
- 86, 87, 84, 85, 90, 91, 88, 89, 79, 79, 78, 78, 82, 83, 80, 81,
- 170, 171, 168, 169, 174, 175, 172, 173, 162, 163, 160, 161, 166, 167, 164, 165,
- 185, 186, 183, 184, 189, 190, 187, 188, 177, 178, 175, 176, 181, 182, 179, 180,
- 138, 139, 136, 137, 142, 143, 140, 141, 130, 131, 128, 129, 134, 135, 132, 133,
- 154, 155, 152, 153, 158, 159, 156, 157, 146, 147, 144, 145, 150, 151, 148, 149,
- 226, 227, 224, 225, 230, 231, 228, 229, 221, 221, 220, 220, 223, 223, 222, 222,
- 244, 246, 240, 242, 252, 254, 248, 250, 234, 235, 232, 233, 238, 239, 236, 237,
- 200, 201, 198, 199, 204, 205, 202, 203, 192, 193, 191, 191, 196, 197, 194, 195,
- 214, 215, 212, 213, 218, 219, 216, 217, 207, 207, 206, 206, 210, 211, 208, 209
- };
- static __inline uint8_t alaw_to_ulaw(uint8_t alaw)
- {
- return alaw_to_ulaw_table[alaw];
- }
- /*- End of function --------------------------------------------------------*/
- static __inline uint8_t ulaw_to_alaw(uint8_t ulaw)
- {
- return ulaw_to_alaw_table[ulaw];
- }
- /*- End of function --------------------------------------------------------*/
- static __inline int top_bit(unsigned int bits)
- {
- #if defined(SPANDSP_USE_86_ASM)
- int res;
- __asm__ (" xorl %[res],%[res];\n"
- " decl %[res];\n"
- " bsrl %[bits],%[res]\n"
- : [res] "=&r" (res)
- : [bits] "rm" (bits));
- return res;
- #elif defined(__ppc__) || defined(__powerpc__)
- int res;
- __asm__ ("cntlzw %[res],%[bits];\n"
- : [res] "=&r" (res)
- : [bits] "r" (bits));
- return 31 - res;
- #elif defined(_M_IX86)
- /* Visual Studio i386 */
- __asm
- {
- xor eax, eax
- dec eax
- bsr eax, bits
- }
- #elif defined(_M_X64)
- /* Visual Studio x86_64 */
- /* TODO: Need the appropriate x86_64 code */
- int res;
- if (bits == 0)
- return -1;
- res = 0;
- if (bits & 0xFFFF0000)
- {
- bits &= 0xFFFF0000;
- res += 16;
- }
- if (bits & 0xFF00FF00)
- {
- bits &= 0xFF00FF00;
- res += 8;
- }
- if (bits & 0xF0F0F0F0)
- {
- bits &= 0xF0F0F0F0;
- res += 4;
- }
- if (bits & 0xCCCCCCCC)
- {
- bits &= 0xCCCCCCCC;
- res += 2;
- }
- if (bits & 0xAAAAAAAA)
- {
- bits &= 0xAAAAAAAA;
- res += 1;
- }
- return res;
- #else
- int res;
- if (bits == 0)
- return -1;
- res = 0;
- if (bits & 0xFFFF0000)
- {
- bits &= 0xFFFF0000;
- res += 16;
- }
- if (bits & 0xFF00FF00)
- {
- bits &= 0xFF00FF00;
- res += 8;
- }
- if (bits & 0xF0F0F0F0)
- {
- bits &= 0xF0F0F0F0;
- res += 4;
- }
- if (bits & 0xCCCCCCCC)
- {
- bits &= 0xCCCCCCCC;
- res += 2;
- }
- if (bits & 0xAAAAAAAA)
- {
- bits &= 0xAAAAAAAA;
- res += 1;
- }
- return res;
- #endif
- }
- /*- End of function --------------------------------------------------------*/
- /*! \brief Find the bit position of the lowest set bit in a word
- \param bits The word to be searched
- \return The bit number of the lowest set bit, or -1 if the word is zero. */
- static __inline int bottom_bit(unsigned int bits)
- {
- int res;
-
- #if defined(SPANDSP_USE_86_ASM)
- __asm__ (" xorl %[res],%[res];\n"
- " decl %[res];\n"
- " bsfl %[bits],%[res]\n"
- : [res] "=&r" (res)
- : [bits] "rm" (bits));
- return res;
- #else
- if (bits == 0)
- return -1;
- res = 31;
- if (bits & 0x0000FFFF)
- {
- bits &= 0x0000FFFF;
- res -= 16;
- }
- if (bits & 0x00FF00FF)
- {
- bits &= 0x00FF00FF;
- res -= 8;
- }
- if (bits & 0x0F0F0F0F)
- {
- bits &= 0x0F0F0F0F;
- res -= 4;
- }
- if (bits & 0x33333333)
- {
- bits &= 0x33333333;
- res -= 2;
- }
- if (bits & 0x55555555)
- {
- bits &= 0x55555555;
- res -= 1;
- }
- return res;
- #endif
- }
- #define ULAW_BIAS 0x84
- /*! \brief Encode a linear sample to u-law
- \param linear The sample to encode.
- \return The u-law value.
- */
- static __inline uint8_t linear_to_ulaw(int linear)
- {
- uint8_t u_val;
- int mask;
- int seg;
- /* Get the sign and the magnitude of the value. */
- if (linear >= 0)
- {
- linear = ULAW_BIAS + linear;
- mask = 0xFF;
- }
- else
- {
- linear = ULAW_BIAS - linear;
- mask = 0x7F;
- }
- seg = top_bit(linear | 0xFF) - 7;
- /*
- * Combine the sign, segment, quantization bits,
- * and complement the code word.
- */
- if (seg >= 8)
- u_val = (uint8_t) (0x7F ^ mask);
- else
- u_val = (uint8_t) (((seg << 4) | ((linear >> (seg + 3)) & 0xF)) ^ mask);
- #ifdef ULAW_ZEROTRAP
- /* Optional ITU trap */
- if (u_val == 0)
- u_val = 0x02;
- #endif
- return u_val;
- }
- /*! The A-law alternate mark inversion mask */
- #define ALAW_AMI_MASK 0x55
- /*! \brief Encode a linear sample to A-law
- \param linear The sample to encode.
- \return The A-law value.
- */
- static __inline uint8_t linear_to_alaw(int linear)
- {
- int mask;
- int seg;
-
- if (linear >= 0)
- {
- /* Sign (bit 7) bit = 1 */
- mask = ALAW_AMI_MASK | 0x80;
- }
- else
- {
- /* Sign (bit 7) bit = 0 */
- mask = ALAW_AMI_MASK;
- linear = -linear - 1;
- }
- /* Convert the scaled magnitude to segment number. */
- seg = top_bit(linear | 0xFF) - 7;
- if (seg >= 8)
- {
- if (linear >= 0)
- {
- /* Out of range. Return maximum value. */
- return (uint8_t) (0x7F ^ mask);
- }
- /* We must be just a tiny step below zero */
- return (uint8_t) (0x00 ^ mask);
- }
- /* Combine the sign, segment, and quantization bits. */
- return (uint8_t) (((seg << 4) | ((linear >> ((seg) ? (seg + 3) : 4)) & 0x0F)) ^ mask);
- }
- /*- End of function --------------------------------------------------------*/
- struct wavfile_t
- {
- HANDLE hFile;
- int isread;
- int clock; // 8k or 16k
- int samplebit; // 8 or 16
- int format_tag;
- int file_format_tag;
- int file_samplebit;
- int file_clock;
- };
- static int read_wav_header(HANDLE hFile, int *clock, int *samplebit, int *format_tag)
- {
- DWORD dw;
- DWORD dwByteRead;
- DWORD dwFileLen;
- DWORD dwFormatLen;
- WAVEFORMATEX fmt;
- SetFilePointer(hFile, 0, NULL, FILE_END);
- dwFileLen = SetFilePointer(hFile, 0, NULL, FILE_CURRENT);
- SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
- ReadFile(hFile, &dw, sizeof(dw), &dwByteRead, NULL);
- if (dw != 'FFIR')
- return -1;
- ReadFile(hFile, &dw, sizeof(dw), &dwByteRead, NULL);
- if (dw != dwFileLen-8)
- return -1;
- ReadFile(hFile, &dw, sizeof(dw), &dwByteRead, NULL);
- if (dw != 'EVAW')
- return -1;
- ReadFile(hFile, &dw, sizeof(dw), &dwByteRead, NULL);
- if (dw != ' tmf')
- return -1;
- ReadFile(hFile, &dwFormatLen, sizeof(dwFormatLen), &dwByteRead, NULL);
- if (dwFormatLen < 16)
- return -1;
- ReadFile(hFile, &fmt, dwFormatLen, &dwByteRead, NULL);
- *format_tag = (int)fmt.wFormatTag;
- if (fmt.nChannels != 1)
- return -1;
- if (fmt.nSamplesPerSec == 8000)
- *clock = 8000;
- else if (fmt.nSamplesPerSec == 16000)
- *clock = 16000;
- else
- return -1; // not supported
- *samplebit = (int)fmt.wBitsPerSample;
- ReadFile(hFile, &dw, sizeof(dw), &dwByteRead, NULL);
- while (dw != 'atad') { // is not data chunk
- DWORD tmp;
- ReadFile(hFile, &tmp, sizeof(tmp), &dwByteRead, NULL);
- SetFilePointer(hFile, tmp, NULL, FILE_CURRENT);
- ReadFile(hFile, &dw, sizeof(dw), &dwByteRead, NULL);
- }
- ReadFile(hFile, &dw, sizeof(dw), &dwByteRead, NULL);
- return 0;
- }
- static int write_wav_header(HANDLE hFile, int clock, int samplebit, int format_tag)
- {
- WORD wFormat;
- WORD wBitsPerSample;
- DWORD dw;
- DWORD dwByteWritten;
- WAVEFORMATEX fmt;
- DWORD dwFmtSize = sizeof(fmt);
- wFormat = (WORD)format_tag;
- wBitsPerSample = (WORD)samplebit;
- if (wFormat == WAVE_FORMAT_PCM) {
- dwFmtSize -= 2;
- }
- dw = 'FFIR'; // riff chunk
- WriteFile(hFile, &dw, sizeof(dw), &dwByteWritten, NULL);
- dw = 0x7fffffff; // riff chunk size
- WriteFile(hFile, &dw, sizeof(dw), &dwByteWritten, NULL);
- dw = 'EVAW'; // format
- WriteFile(hFile, &dw, sizeof(dw), &dwByteWritten, NULL);
- dw = ' tmf'; // fmt subchunk
- WriteFile(hFile, &dw, sizeof(dw), &dwByteWritten, NULL);
- dw = dwFmtSize;
- WriteFile(hFile, &dw, sizeof(dw), &dwByteWritten, NULL);
- fmt.wFormatTag = wFormat;
- fmt.nChannels = 1;
- fmt.nSamplesPerSec = (DWORD)clock;
- fmt.nBlockAlign = 2;
- fmt.wBitsPerSample = wBitsPerSample;
- fmt.cbSize = 0;
- fmt.nAvgBytesPerSec = fmt.nSamplesPerSec * wBitsPerSample / 8;
- WriteFile(hFile, &fmt, dwFmtSize, &dwByteWritten, NULL);
- dw = 'atad'; // data chunk
- WriteFile(hFile, &dw, sizeof(dw), &dwByteWritten, NULL);
- dw = 0x7fffffff; // data chunk size
- WriteFile(hFile, &dw, sizeof(dw), &dwByteWritten, NULL);
- return 0;
- }
- static int write_wav_header_end(HANDLE hFile, int ispcm16)
- {
- DWORD dwByteWritten;
- DWORD dw;
- DWORD dwFileLen;
- DWORD dwDataChunkOffset;
- if (hFile == INVALID_HANDLE_VALUE)
- return -1;
- dwDataChunkOffset = (ispcm16 ? 44 : 46);
- SetFilePointer(hFile, 0, NULL, FILE_END);
- dwFileLen = SetFilePointer(hFile, 0, NULL, FILE_CURRENT);
- dw = dwFileLen - 8; // riff chunk size
- SetFilePointer(hFile, 4, NULL, FILE_BEGIN);
- WriteFile(hFile, &dw, sizeof(dw), &dwByteWritten, NULL);
- dw = dwFileLen - dwDataChunkOffset; // data chunk size
- SetFilePointer(hFile, dwDataChunkOffset-4, NULL, FILE_BEGIN);
- WriteFile(hFile, &dw, sizeof(dw), &dwByteWritten, NULL);
- SetFilePointer(hFile, 0, NULL, FILE_END);
- return 0;
- }
- static int read_wav_frame(HANDLE hFile, DWORD dwFrameSize, unsigned char *buf)
- {
- DWORD dwByteRead;
- BOOL bRet;
- bRet = ReadFile(hFile, buf, dwFrameSize, &dwByteRead, NULL);
- if (!bRet || dwByteRead == 0) {
- return -1;
- }
- if (dwByteRead < dwFrameSize) {
- memset(buf+dwByteRead, 0, dwFrameSize-dwByteRead);
- }
- return 0;
- }
- static int write_wav_frame(HANDLE hFile, const char *buf, DWORD size)
- {
- DWORD dwByteWritten;
- BOOL bRet = WriteFile(hFile, buf, size, &dwByteWritten, NULL);
- return bRet ? 0 : -1;
- }
- TOOLKIT_API int wavfile_probe_format(const char *file, int *p_clock, int *p_samplebit, int *format_tag)
- {
- HANDLE hFile;
- int clock;
- int tag;
- int samplebit;
- if (!file)
- return -1;
- hFile = CreateFileA(file,
- GENERIC_READ,
- FILE_SHARE_READ,
- NULL,
- OPEN_EXISTING,
- FILE_ATTRIBUTE_NORMAL,
- NULL);
- if (hFile == INVALID_HANDLE_VALUE)
- return -1;
- if (read_wav_header(hFile, &clock, &samplebit, &tag) != 0) {
- CloseHandle(hFile);
- return -1;
- }
- CloseHandle(hFile);
- if (p_clock)
- *p_clock = clock;
- if (format_tag)
- *format_tag = tag;
- if (p_samplebit)
- *p_samplebit = samplebit;
- return 0;
- }
- TOOLKIT_API int wavfile_open(const char *file,
- int isread,
- int clock,
- int samplebit,
- int format_tag,
- wavfile_t **p_wavfile)
- {
- wavfile_t *wavfile;
- wavfile = ZALLOC_T(wavfile_t);
- wavfile->clock = clock;
- wavfile->format_tag = format_tag;
- wavfile->samplebit = samplebit;
- wavfile->isread = !!isread;
- wavfile->hFile = CreateFileA(file,
- isread ? GENERIC_READ : GENERIC_WRITE, FILE_SHARE_READ,
- NULL,
- isread ? OPEN_EXISTING : OPEN_ALWAYS,
- FILE_ATTRIBUTE_NORMAL,
- NULL);
- if (wavfile->hFile == INVALID_HANDLE_VALUE)
- return -1;
- if (isread) {
- int read_clock;
- int read_format_tag;
- int read_samplebit;
- if (read_wav_header(wavfile->hFile, &read_clock, &read_samplebit, &read_format_tag) != 0) {
- CloseHandle(wavfile->hFile);
- return -1;
- }
- wavfile->file_clock = read_clock;
- wavfile->file_format_tag = read_format_tag;
- wavfile->file_samplebit = read_samplebit;
- } else {
- if (write_wav_header(wavfile->hFile, clock, samplebit, format_tag) != 0) {
- CloseHandle(wavfile->hFile);
- return -1;
- }
- }
- *p_wavfile = wavfile;
- return 0;
- }
- TOOLKIT_API int wavfile_close(wavfile_t *wavfile)
- {
- if (!wavfile->isread)
- write_wav_header_end(wavfile->hFile, wavfile->samplebit == 16);
- CloseHandle(wavfile->hFile);
- wavfile->hFile = INVALID_HANDLE_VALUE;
- free(wavfile);
- return 0;
- }
- TOOLKIT_API int wavfile_get_native_handle(wavfile_t *wavfile, HANDLE *p_handle)
- {
- *p_handle = wavfile->hFile;
- return 0;
- }
- TOOLKIT_API int wavfile_write(wavfile_t *wavfile, const void *buf, int size)
- {
- if (write_wav_frame(wavfile->hFile, buf, size) != 0)
- return -1;
- return 0;
- }
- TOOLKIT_API int wavfile_read(wavfile_t *wavfile, void *buf, int size)
- {
- int i;
- if (wavfile->file_format_tag == wavfile->format_tag) {
- if (wavfile->file_samplebit == wavfile->samplebit) {
- if (read_wav_frame(wavfile->hFile, size, buf) != 0)
- return -1;
- } else if (wavfile->file_samplebit == 16) {
- short tmp[256];
- if (read_wav_frame(wavfile->hFile, 2*size, (unsigned char*)&tmp[0]) != 0)
- return -1;
- if (wavfile->format_tag == WAVE_FORMAT_PCM) {
- for (i = 0; i < size; ++i)
- *((unsigned char*)buf + i) = (tmp[i] >> 8) + 128;
- } else if (wavfile->format_tag == WAVE_FORMAT_ALAW) {
- for (i = 0; i < size; ++i)
- *((unsigned char*)buf + i) = linear_to_alaw(tmp[i]);
- } else if (wavfile->format_tag == WAVE_FORMAT_MULAW) {
- for (i = 0; i < size; ++i)
- *((unsigned char*)buf + i) = linear_to_alaw(tmp[i]);
- } else {
- return -1;
- }
- } else {
- return -1;
- }
- } else if (wavfile->file_samplebit == wavfile->samplebit && wavfile->samplebit == 8) {
- if (read_wav_frame(wavfile->hFile, size, buf) != 0)
- return -1;
- if (wavfile->file_format_tag == WAVE_FORMAT_PCM) {
- if (wavfile->format_tag == WAVE_FORMAT_ALAW) {
- for (i = 0; i < size; ++i)
- *((unsigned char*)buf + i) = pcm8toalaw[*((unsigned char*)buf+i)];
- } else if (wavfile->format_tag == WAVE_FORMAT_MULAW) {
- for (i = 0; i < size; ++i)
- *((unsigned char*)buf + i) = pcm8tomulaw[*((unsigned char*)buf+i)];
- } else {
- return -1;
- }
- } else if (wavfile->file_format_tag == WAVE_FORMAT_ALAW) {
- if (wavfile->format_tag == WAVE_FORMAT_MULAW) {
- for (i = 0; i < size; ++i)
- *((unsigned char*)buf + i) = alaw_to_ulaw(*((unsigned char*)buf+i));
- } else if (wavfile->format_tag == WAVE_FORMAT_PCM) {
- for (i = 0; i < size; ++i)
- *((unsigned char*)buf + i) = alawtopcm8[*((unsigned char*)buf+i)];
- } else {
- return -1;
- }
- } else if (wavfile->file_format_tag == WAVE_FORMAT_MULAW) {
- if (wavfile->format_tag == WAVE_FORMAT_ALAW) {
- for (i = 0; i < size; ++i)
- *((unsigned char*)buf + i) = ulaw_to_alaw(*((unsigned char*)buf+i));
- } else if (wavfile->format_tag == WAVE_FORMAT_PCM) {
- for (i = 0; i < size; ++i)
- *((unsigned char*)buf + i) = ulawtopcm8[*((unsigned char*)buf+i)];
- } else {
- return -1;
- }
- } else {
- return -1;
- }
- } else {
- return -1;
- }
- return 0;
- }
- // PCM16, PCMA, PCMU, PCM8
|