view dev/s2u-regen.c @ 227:a5200ad12d58

dev/s2u-regen.c: new approach
author Mychaela Falconia <falcon@freecalypso.org>
date Sun, 23 Apr 2023 16:53:32 +0000
parents 84d22eb72196
children
line wrap: on
line source

/*
 * This program generates a G.711 mu-law encoding table of the same form
 * as the s2u[] table in the toast_ulaw.c module in libgsm/toast, i.e.,
 * an encoding table that takes only the upper 13 bits of the linear PCM
 * sample to be encoded, even though canonical mu-law encoding requires
 * 14-bit input.  The 13-bit table constructed by this program is computed
 * as if the lsb of the "proper" 14-bit input is always zero, like it is
 * expected to be when the linear PCM samples came from the output of a
 * GSM speech decoder.
 *
 * The "engine" function that does the computation is based on ulaw_compress()
 * from ITU-T G.191 STL.
 */

#include <stdio.h>
#include <stdlib.h>

static unsigned
ulaw_compress(input)
    unsigned input;
{
    short i;                    /* aux.var. */
    short absno;                /* absolute value of linear (input) sample */
    short segno;                /* segment (Table 2/G711, column 1) */
    short low_nibble;           /* low nibble of log companded sample */
    short high_nibble;          /* high nibble of log companded sample */
    unsigned output;

    /* -------------------------------------------------------------------- */
    /* Input is 14-bit right-justified in this version */
    /* Compute absolute value; adjust for easy processing */
    /* -------------------------------------------------------------------- */
    absno = input >= 0x2000     /* compute 1's complement in case of */
      ? (~input & 0x1FFF) + 33          /* negative samples */
      : input + 33;                     /* NB: 33 is the difference value */
    /* between the thresholds for */
    /* A-law and u-law. */
    if (absno > (0x1FFF))       /* limitation to "absno" < 8192 */
      absno = (0x1FFF);

    /* Determination of sample's segment */
    i = absno >> 6;
    segno = 1;
    while (i != 0) {
      segno++;
      i >>= 1;
    }

    /* Mounting the high-nibble of the log-PCM sample */
    high_nibble = (0x0008) - segno;

    /* Mounting the low-nibble of the log PCM sample */
    low_nibble = (absno >> segno)       /* right shift of mantissa and */
      &(0x000F);                /* masking away leading '1' */
    low_nibble = (0x000F) - low_nibble;

    /* Joining the high-nibble and the low-nibble of the log PCM sample */
    output = (high_nibble << 4) | low_nibble;

    /* Add sign bit */
    if (input < 0x2000)
      output = output | (0x0080);

    return output;
}

main(argc, argv)
	char **argv;
{
	unsigned input, output;

	for (input = 0; input < 8192; input++) {
		output = ulaw_compress(input << 1);
		printf("%04o,", output);
		if ((input % 15) == 14 || input == 8191)
			putchar('\n');
	}
	exit(0);
}