#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <stdint.h>
#include <ao/ao.h>

#define TWO_PI          6.2831853071795862
#define SAMPLE_MAX_FLT  32768.0
#define SAMPLE_RATE     44100

/* calc number of sound samples for ms milliseconds */
#define NUM_SAMPLES(ms) ((ms) * 44100 / 1000)

void gen_sine(int16_t *buf, long msec, float freq, float ampl);

int main(void) {
    ao_device *dev;
    ao_sample_format fmt;
    int16_t *buf;
    size_t bsz;

    /* initialize libao */
    ao_initialize();

    fmt.bits = 16;
    fmt.channels = 2;
    fmt.rate = SAMPLE_RATE;
    fmt.byte_format = AO_FMT_LITTLE;

    /* open output device with the format specified by fmt */
    if(!(dev = ao_open_live(ao_default_driver_id(), &fmt, 0))) {
        fputs("Failed to open audio device\n", stderr);
        return EXIT_FAILURE;
    }

    /* create a 4sec sound buffer */
    bsz = NUM_SAMPLES(4000) * 2 * sizeof *buf;
    if(!(buf = malloc(bsz))) {
        perror("failed to allocate sound buffer");
        return EXIT_FAILURE;
    }

    /* generate a 4sec 440 Hz tone */
    gen_sine(buf, 4000, 440.0, 1.0);

    ao_play(dev, (void*)buf, bsz);

    free(buf);

    /* close the device and shut down libao */
    ao_close(dev);
    ao_shutdown();

    return 0;
}

void gen_sine(int16_t *buf, long msec, float freq, float ampl) {
    int i, samples = NUM_SAMPLES(msec);

    for(i=0; i<samples; i++) {
        float t = (float)i / (float)SAMPLE_RATE;
        int16_t s = (int16_t)(ampl * sin(TWO_PI * t * freq) * SAMPLE_MAX_FLT);
        buf[i] = buf[i + 1] = s;
    }
}