// name: hey_sine.cpp
// desc: hey there, sine wave

// include headers
#include "RtAudio.h"
#include <math.h>
#include <iostream>
using namespace std; // for STL

// define some stuff
#define MUH_FLOAT  double
#define MUH_FORMAT RTAUDIO_FLOAT64
#define MUH_SRATE  44100
#define MUH_PIE    3.14159265358979323846

// define some global variables
MUH_FLOAT g_frequency = 440;
MUH_FLOAT g_gain = 1.0;
MUH_FLOAT g_t = 0;

// callback function
int callme( char * buffer, int buffer_size, void * user_data )
{
    // cast into right type
    MUH_FLOAT * buffy = (MUH_FLOAT *)buffer;
    
    // loop over
    for( int i = 0; i < buffer_size; i++ )
    {
        // compute next sample
        buffy[i] = g_gain * sin( 2 * MUH_PIE * g_frequency * g_t / MUH_SRATE );
        // increment our time counter
        g_t += 1.0;
    }

    return 0;
}

// get input
void getInput()
{
    string command;

    // keep going
    while( true )
    {
        // read from console
        cin >> command;

        // check
        switch( command[0] )
        {
        case 'q': // quit
            cout << "bye!" << endl;
            return;
        
        case 'f': // frequency
            cout << "enter new frequency (" << g_frequency << "): ";
            cin >> g_frequency;
            break;
        
        case 'g': // gain
            cout << "enter new gain (" << g_gain << "): ";
            cin >> g_gain;
            break;

        default:  // everything else
            cout << "huh?" << endl;
            break;
        }
    }
}

// entry point
int main( int argc, char ** argv )
{
    // variables to hold important values
    int device = 0;
    int chans = 1;
    int buffer_size = 512;

    // RtAudio pointer
    RtAudio * audio = NULL;

    // let's try to create instance of RtAudio
    try {
        audio = new RtAudio( 
            device,       // device number of output
            chans,        // number of output channels
            0,            // device number of input
            0,            // number of input channels
            MUH_FORMAT,   // data format
            MUH_SRATE,    // requested sample rate
            &buffer_size, // buffer size
            8             // number of buffers
        );
    } catch( RtError & error ) {
        // do stuff in case of error
        error.printMessage();
        exit( 1 );
    }
    
    // set the callback function and start audio
    try {
        audio->setStreamCallback( &callme, NULL );
        audio->startStream();
    } catch( RtError & error ) {
        // do stuff in case of error
        error.printMessage();
        goto cleanup;
    }
    
    // get input
    getInput();
    
    // if we get here, we are done
    try {
        audio->stopStream();
    } catch (RtError &error) {
        error.printMessage();
    }

    // clean up
cleanup:
    audio->closeStream();
    delete audio;
    
    return 0;
}
