#include "precompile.h" #ifdef _WIN32 /*this header is used by windows multi-media*/ #include #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