/*-------------- Telecommunications & Signal Processing Lab --------------- McGill University Routine: void AFwriteAlaw (AFILE *AFp, const float Fbuff[], int Nval) Purpose: Write 8-bit A-law data to an audio file (float input values) Description: This routine writes a specified number of 8-bit A-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 A-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.6 $ $Date: 1996/08/14 18:15:59 $ -------------------------------------------------------------------------*/ static char rcsid [] = "$Id: AFwriteAlaw.c 1.6 1996/08/14 AFsp-V2R1 $"; #include #include #include #include #define LW FDL_ALAW8 #define MINV(a, b) (((a) < (b)) ? (a) : (b)) #define NBBUF 8192 #define NLEV 256 #define AMAX 32768 /* ITU-T Recommendation G.711 Conversion to A-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. A-law data is stored in sign-magnitude bit-complemented format. The sign bit is 1 for positive data. The uncomplemented byte is in sign-segment- mantissa format. bin no. signal value bit pattern complement 0-15 1, ... , 31 1 000 xxxx 1 101 xyxy 16-31 33, ... , 63 1 001 xxxx 1 100 xyxy 32-47 66, ... , 126 1 010 xxxx 1 111 xyxy 48-63 132, ... , 252 1 011 xxxx 1 110 xyxy 64-79 264, ... , 504 1 100 xxxx 1 001 xyxy 80-95 528, ... , 1008 1 101 xxxx 1 000 xyxy 96-111 1056, ... , 2016 1 110 xxxx 1 011 xyxy 112-127 2112, ... , 4032 1 111 xxxx 1 010 xyxy 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) A-law representation. The decision levels are scaled by 8, corresponding to quantized values from -32256 to +32256 (for AFp->ScaleF = 1). */ static const float Xq[NLEV/2-1] = { 16, 32, 48, 64, 80, 96, 112, 128, 144, 160, 176, 192, 208, 224, 240, 256, 272, 288, 304, 320, 336, 352, 368, 384, 400, 416, 432, 448, 464, 480, 496, 512, 544, 576, 608, 640, 672, 704, 736, 768, 800, 832, 864, 896, 928, 960, 992, 1024, 1088, 1152, 1216, 1280, 1344, 1408, 1472, 1536, 1600, 1664, 1728, 1792, 1856, 1920, 1984, 2048, 2176, 2304, 2432, 2560, 2688, 2816, 2944, 3072, 3200, 3328, 3456, 3584, 3712, 3840, 3968, 4096, 4352, 4608, 4864, 5120, 5376, 5632, 5888, 6144, 6400, 6656, 6912, 7168, 7424, 7680, 7936, 8192, 8704, 9216, 9728, 10240, 10752, 11264, 11776, 12288, 12800, 13312, 13824, 14336, 14848, 15360, 15872, 16384, 17408, 18432, 19456, 20480, 21504, 22528, 23552, 24576, 25600, 26624, 27648, 28672, 29696, 30720, 31744 }; void AFwriteAlaw (AFp, Fbuff, Nval) AFILE *AFp; const float Fbuff[]; int Nval; { int is, N, i; long int Novld, 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 ^ 0xD5; /* Set the sign bit, flip alternate bits */ } else { if (-Fv > AMAX) ++Novld; ibin = SPquant (-Fv, Xq, NLEV/2); Buf[i] = ibin ^ 0x55; /* Flip alternate bits */ } } 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 ("AFwriteAlaw - Output data clipped"); AFp->Novld = Novld; return; }