//----------------------------------------------------------------------------- // name: HelloSine.cpp // desc: hello sine wave, real-time // // author: Ge Wang (ge@ccrma.stanford.edu) // date: fall 2011 // uses: RtAudio by Gary Scavone //----------------------------------------------------------------------------- #include "RtAudio.h" #include #include #include using namespace std; #ifdef __MACOSX_CORE__ #include #include #include #else #include #include #include #endif //----------------------------------------------------------------------------- // function prototypes //----------------------------------------------------------------------------- void initGfx(); void idleFunc(); void displayFunc(); void reshapeFunc( GLsizei width, GLsizei height ); void keyboardFunc( unsigned char, int, int ); void mouseFunc( int button, int state, int x, int y ); // our datetype #define SAMPLE double // corresponding format for RtAudio #define MY_FORMAT RTAUDIO_FLOAT64 // sample rate #define MY_SRATE 44100 // number of channels #define MY_CHANNELS 1 // for convenience #define MY_PIE 3.14159265358979 // width and height long g_width = 1024; long g_height = 720; // global buffer SAMPLE * g_buffer = NULL; long g_bufferSize; //----------------------------------------------------------------------------- // name: callme() // desc: audio callback //----------------------------------------------------------------------------- int callme( void * outputBuffer, void * inputBuffer, unsigned int numFrames, double streamTime, RtAudioStreamStatus status, void * data ) { // cast! SAMPLE * input = (SAMPLE *)inputBuffer; SAMPLE * output = (SAMPLE *)outputBuffer; // fill for( int i = 0; i < numFrames; i++ ) { // assume mono g_buffer[i] = input[i]; // zero output output[i] = 0; } return 0; } //----------------------------------------------------------------------------- // name: main() // desc: entry point //----------------------------------------------------------------------------- int main( int argc, char ** argv ) { // instantiate RtAudio object RtAudio audio; // variables unsigned int bufferBytes = 0; // frame size unsigned int bufferFrames = 512; // check for audio devices if( audio.getDeviceCount() < 1 ) { // nopes cout << "no audio devices found!" << endl; exit( 1 ); } // initialize GLUT glutInit( &argc, argv ); // init gfx initGfx(); // let RtAudio print messages to stderr. audio.showWarnings( true ); // set input and output parameters RtAudio::StreamParameters iParams, oParams; iParams.deviceId = audio.getDefaultInputDevice(); iParams.nChannels = MY_CHANNELS; iParams.firstChannel = 0; oParams.deviceId = audio.getDefaultOutputDevice(); oParams.nChannels = MY_CHANNELS; oParams.firstChannel = 0; // create stream options RtAudio::StreamOptions options; // go for it try { // open a stream audio.openStream( &oParams, &iParams, MY_FORMAT, MY_SRATE, &bufferFrames, &callme, (void *)&bufferBytes, &options ); } catch( RtError& e ) { // error! cout << e.getMessage() << endl; exit( 1 ); } // compute bufferBytes = bufferFrames * MY_CHANNELS * sizeof(SAMPLE); // allocate global buffer g_bufferSize = bufferFrames; g_buffer = new SAMPLE[g_bufferSize]; memset( g_buffer, 0, sizeof(SAMPLE)*g_bufferSize ); // go for it try { // start stream audio.startStream(); // let GLUT handle the current thread from here glutMainLoop(); // stop the stream. audio.stopStream(); } catch( RtError& e ) { // print error message cout << e.getMessage() << endl; goto cleanup; } cleanup: // close if open if( audio.isStreamOpen() ) audio.closeStream(); // done return 0; } //----------------------------------------------------------------------------- // Name: reshapeFunc( ) // Desc: called when window size changes //----------------------------------------------------------------------------- void initGfx() { // double buffer, use rgb color, enable depth buffer glutInitDisplayMode( GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH ); // initialize the window size glutInitWindowSize( g_width, g_height ); // set the window postion glutInitWindowPosition( 100, 100 ); // create the window glutCreateWindow( "VisualSine" ); // set the idle function - called when idle glutIdleFunc( idleFunc ); // set the display function - called when redrawing glutDisplayFunc( displayFunc ); // set the reshape function - called when client area changes glutReshapeFunc( reshapeFunc ); // set the keyboard function - called on keyboard events glutKeyboardFunc( keyboardFunc ); // set the mouse function - called on mouse stuff glutMouseFunc( mouseFunc ); // set clear color glClearColor( 0, 0, 0, 1 ); // enable color material glEnable( GL_COLOR_MATERIAL ); // enable depth test glEnable( GL_DEPTH_TEST ); } //----------------------------------------------------------------------------- // Name: reshapeFunc( ) // Desc: called when window size changes //----------------------------------------------------------------------------- void reshapeFunc( GLsizei w, GLsizei h ) { // save the new window size g_width = w; g_height = h; // map the view port to the client area glViewport( 0, 0, w, h ); // set the matrix mode to project glMatrixMode( GL_PROJECTION ); // load the identity matrix glLoadIdentity( ); // create the viewing frustum gluPerspective( 45.0, (GLfloat) w / (GLfloat) h, 1.0, 300.0 ); // set the matrix mode to modelview glMatrixMode( GL_MODELVIEW ); // load the identity matrix glLoadIdentity( ); // position the view point gluLookAt( 0.0f, 0.0f, 10.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f ); } //----------------------------------------------------------------------------- // Name: keyboardFunc( ) // Desc: key event //----------------------------------------------------------------------------- void keyboardFunc( unsigned char key, int x, int y ) { switch( key ) { case 'Q': case 'q': exit(1); break; } glutPostRedisplay( ); } //----------------------------------------------------------------------------- // Name: mouseFunc( ) // Desc: handles mouse stuff //----------------------------------------------------------------------------- void mouseFunc( int button, int state, int x, int y ) { if( button == GLUT_LEFT_BUTTON ) { // when left mouse button is down if( state == GLUT_DOWN ) { } else { } } else if ( button == GLUT_RIGHT_BUTTON ) { // when right mouse button down if( state == GLUT_DOWN ) { } else { } } else { } glutPostRedisplay( ); } //----------------------------------------------------------------------------- // Name: idleFunc( ) // Desc: callback from GLUT //----------------------------------------------------------------------------- void idleFunc( ) { // render the scene glutPostRedisplay( ); } //----------------------------------------------------------------------------- // Name: displayFunc( ) // Desc: callback function invoked to draw the client area //----------------------------------------------------------------------------- void displayFunc( ) { static GLfloat c = 0; static GLfloat r = 0; // clear the color and depth buffers glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); glEnable( GL_LIGHT0 ); glEnable( GL_LIGHTING ); // line width glLineWidth( 1.0 ); // x coordinate GLfloat x = -5; // find the x increment GLfloat xinc = ::fabs( 2*x / (g_bufferSize-1) ); // make it change glColor3f( (sin(c)+1)/2, (sin(c*2)+1)/2, (sin(c+.5)+1)/2 ); // loop through global buffer for( int i = 0; i < g_bufferSize; i++ ) { // push glPushMatrix(); // translate glTranslatef( x, 5*g_buffer[i], 0 ); // rotate glRotatef( r, 0, 1, 0 ); // teapot glutWireTeapot( .1 + .5*(sin(c)+1) ); // pop glPopMatrix(); // increment x x += xinc; } c += .1f; r += 5; // flush! glFlush( ); // swap the double buffer glutSwapBuffers( ); }