

//  Input samples assumed to be in the range -32768 to 32767.
//
//  Outputs are 0/1 (intended for a 1-bit DAC).
//
//  The output gain determines how the 0/1 are treated.  An output
//  of 0 treated as the value "-out_gain", and an output of 1 is
//  treated as the value "+out_gain".  By default, pass in 32767.
//  Smaller values may be useful if your input isn't "full scale"
//  input.
//
void sdm
(
    const short   *i_samp,      // input sample array
    unsigned char *o_samp,      // output sample array
    int           num_samp,     // number of inputs to process
    int           oversamp,     // oversampling ratio
    int           out_gain      // output gain
)
{
    int error = 0;
    int i, j, samp;

    for (i = 0; i < num_samp; i++)
    {
        samp = *i_samp++;

        for (j = 0; j < oversamp; j++)
        {
            if (samp > error)
            {
                *o_samp++ = 1;
                error    +=  out_gain - samp;
            } else
            {
                *o_samp++ = 0;
                error    += -out_gain - samp;
            }
        }
    }
}


#ifdef TEST

#include <stdio.h>
#include <math.h>

// Test code:  Generate 10 samples of a sinewave and plot an 8x 
//             oversampled version alongside it.

int main(void)
{
    short         i_samp[10];
    unsigned char o_samp[80];
    int   i, j;
    double a;

    // Initialize the sine wave.
    for (a = 0., i = 0; i < 10; i++, a += 0.2 * M_PI)
        i_samp[i] = (short)( 32767. * sin(a) );

    // Perform sigma delta modulation.
    sdm(i_samp, o_samp, 10, 8, 32767);

    // Crude ASCII plot of the sine wave, 33 rows tall
    for (i = 16; i >= -16; i--)
    {
        int hi = 2048*i, lo = hi - 2048;

        for (j = 0; j < 79; j++)
        {
            int samp = i_samp[j / 8];
            int outc = i == 0 && j % 8 == 0     ? '|'
                     : hi >= samp && samp >  lo ? '*' 
                     : i == 0 && j % 8 != 0     ? '-'
                     :                            ' ';

            putchar(outc);
        }
        putchar('\n');
    }

    putchar('\n');
    putchar('\n');

    // Crude ASCII plot of the sigma-delta modulated wave, 6 rows tall
    for (j = 0; j < 79; j++) 
        putchar(o_samp[j] == 1 ? '-' : ' ');

    putchar('\n');

    for (i = 0; i < 4; i++)
    {
        for (j = 0; j < 79; j++)
            putchar(o_samp[j] != o_samp[j+1] ? '|' : ' ');
        putchar('\n');
    }

    for (j = 0; j < 79; j++) 
        putchar(o_samp[j] == 0 ? '-' : ' ');

    putchar('\n');

    return 0;
}

#endif
