/*
Generate pure tone on output.
Compile with: cc -o jack-dev-3 jack-dev-3.c `pkg-config --cflags --libs jack` -lm

Notice additional flag -lm for math library
*/
#include <stdio.h>
#include <unistd.h> // for sleep()
#include <math.h>
#include <jack/jack.h>

jack_port_t *out;
float sample_rate;
float sample_number = 0;
const float sine_frequency = 256; // Hz

int process(jack_nframes_t nframes, void *arg)
{
    float *output_buffer = (float*)jack_port_get_buffer(out, nframes);

    for(int i=0; i<nframes; ++i)
    {
        float time = sample_number / sample_rate;
        output_buffer[i] = sinf(2.0*M_PI * sine_frequency * time);

        ++sample_number;
    }

    /*
    32bit float has only 24 bits to store digits of number (significand), which will overflow in less than
    6 minutes when using 48kHz sample rate to track sample number (2^24/48000/60).
    To prevent this make sample_number cyclic, as sine(2pi*f*t) function does not care if time = 2.3 or 0.3.
    */
    if(sample_number > sample_rate)
    {
        sample_number -= sample_rate;
    }

    return 0;
}

int main(void)
{
    jack_client_t *client = jack_client_open("jack-dev-3", JackNoStartServer, NULL);
    if(client == NULL)
    {
        fprintf(stderr, "Connecting to jack failed\n");
        return 1;
    }

    // get sample rate for use in process()
    sample_rate = (float) jack_get_sample_rate(client);

    out = jack_port_register(client, "out", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
    if(out == NULL)
    {
        fprintf(stderr, "Creating output port failed\n");
        jack_client_close(client);
        return 1;
    }

    jack_set_process_callback(client, process, NULL);
    jack_activate(client);

    sleep(-1);
    return 0;
}
