/*-------------- Telecommunications & Signal Processing Lab --------------- McGill University Routine: void AFwriteMulaw (AFILE *AFp, const float Fbuff[], int Nval) Purpose: Write 8-bit mu-law data to an audio file (float input values) Description: This routine writes a specified number of 8-bit mu-law samples to an audio file. The input to this routine is a buffer of float values. The file must have been opened using subroutine AFopenWrite. A warning message is printed if the input values exceed the dynamic range of the mu-law representation. Parameters: -> AFILE *AFp Audio file pointer for an audio file opened by AFopenWrite -> const float Fbuff[] Array of floats with the samples to be written -> int Nval Number of samples to be written Author / revision: P. Kabal Copyright (C) 1996 $Revision: 1.22 $ $Date: 1996/08/14 18:16:51 $ -------------------------------------------------------------------------*/ static char rcsid [] = "$Id: AFwriteMulaw.c 1.22 1996/08/14 AFsp-V2R1 $"; #include #include #include #include #define LW FDL_MULAW8 #define MINV(a, b) (((a) < (b)) ? (a) : (b)) #define NBBUF 8192 #define NLEV 256 #define AMAX 32636 /* ITU-T Recommendation G.711 Conversion to mu-law is carried out using a quantization operation. Given an array of (ordered) decision levels, the interval containing the input value is determined. However, there is an ambiguity at the quantizer decision levels themselves. G.711 allows the output value corresponding to the decision levels to either go up or down. For the quantization routine SPquant, the intervals are defined as Xq[i-1] < x <= Xq[i], and so that input values which lie at the decision level move downward. In this routine SPquant is used to quantize the magnitude, with the sign being handled separately. Mu-law data is stored in sign-magnitude bit-complemented format. The sign bit is 0 for positive data. The uncomplemented byte is in sign-segment- mantissa format. bin no. signal value bit pattern complement 0-15 0, ... , 30 0 000 xxxx 1 111 yyyy 16-31 33, ... , 93 0 001 xxxx 1 110 yyyy 32-47 99, ... , 217 0 010 xxxx 1 101 yyyy 48-63 231, ... , 471 0 011 xxxx 1 100 yyyy 64-79 495, ... , 975 0 100 xxxx 1 011 yyyy 80-95 1023, ... , 1983 0 101 xxxx 1 010 yyyy 96-111 2079, ... , 3999 0 110 xxxx 1 001 yyyy 112-127 4191, ... , 8031 0 111 xxxx 1 000 yyyy SPquant is used to find a bin number for the absolute value of the samples. The bin number with sign directly corresponds to the (uncomplemented) mu-law representation. G.711 allows for the optional suppression of the all zero code. In this implementation, the zero code is NOT suppressed. The decision levels are scaled by 4, corresponding to quantized values from -32124 to +32124 (for AFp->ScaleF = 1). */ static const float Xq[NLEV/2-1] = { 4, 12, 20, 28, 36, 44, 52, 60, 68, 76, 84, 92, 100, 108, 116, 124, 140, 156, 172, 188, 204, 220, 236, 252, 268, 284, 300, 316, 332, 348, 364, 380, 412, 444, 476, 508, 540, 572, 604, 636, 668, 700, 732, 764, 796, 828, 860, 892, 956, 1020, 1084, 1148, 1212, 1276, 1340, 1404, 1468, 1532, 1596, 1660, 1724, 1788, 1852, 1916, 2044, 2172, 2300, 2428, 2556, 2684, 2812, 2940, 3068, 3196, 3324, 3452, 3580, 3708, 3836, 3964, 4220, 4476, 4732, 4988, 5244, 5500, 5756, 6012, 6268, 6524, 6780, 7036, 7292, 7548, 7804, 8060, 8572, 9084, 9596, 10108, 10620, 11132, 11644, 12156, 12668, 13180, 13692, 14204, 14716, 15228, 15740, 16252, 17276, 18300, 19324, 20348, 21372, 22396, 23420, 24444, 25468, 26492, 27516, 28540, 29564, 30588, 31612 }; void AFwriteMulaw (AFp, Fbuff, Nval) AFILE *AFp; const float Fbuff[]; int Nval; { int is, N, i; long int Novld; long int offs; uint1_t Buf[NBBUF/LW]; double Fv; uint1_t ibin; /* Write data to the audio file */ offs = AFp->End; is = 0; Novld = AFp->Novld; while (is < Nval) { N = MINV (NBBUF / LW, Nval - is); for (i = 0; i < N; ++i) { Fv = AFp->ScaleF * Fbuff[i+is]; if (Fv >= 0.0) { if (Fv > AMAX) ++Novld; ibin = SPquant (Fv, Xq, NLEV/2); Buf[i] = ~ibin; } else { if (-Fv > AMAX) ++Novld; ibin = SPquant (-Fv, Xq, NLEV/2); Buf[i] = ~(ibin | 0x80); } } FLwriteFile (AFp->fp, offs, (void *) Buf, (size_t) LW, (size_t) N); is = is + N; offs = offs + LW * N; } /* Update the file position and number of overloads*/ AFp->End = offs; if (Novld > 0L && AFp->Novld == 0L) UTwarn ("AFwriteMulaw - Output data clipped"); AFp->Novld = Novld; return; }