//----------------------------------------------------------------------------- // name: Sender.cpp //----------------------------------------------------------------------------- #include #include #include #include //#include #ifdef __APPLE__ #include #else #include #endif #include #include "sender.h" #include "RtAudio.h" #include "ticktimer.h" #include "textfile.h" #include "osc/OscOutboundPacketStream.h" #include "ip/UdpSocket.h" using namespace std; #define ADDRESS "fgeorg-kandinsky.stanford.edu" #define PORT 3767 #define OUTPUT_BUFFER_SIZE 2100 UdpTransmitSocket transmitSocket( IpEndpointName( ADDRESS, PORT ) ); char packet_buffer[OUTPUT_BUFFER_SIZE]; bool is_sending_osc_data = false; void start_sending_osc_data() { is_sending_osc_data = true; osc::OutboundPacketStream packet_stream( packet_buffer, OUTPUT_BUFFER_SIZE ); packet_stream << osc::BeginBundleImmediate; packet_stream << osc::BeginMessage( "/audio_begin" ) << osc::EndMessage; packet_stream << osc::EndBundle; transmitSocket.Send( packet_stream.Data(), packet_stream.Size() ); cout << "packet sent! size: " << packet_stream.Size() << endl; } void finish_sending_osc_data() { is_sending_osc_data = false; osc::OutboundPacketStream packet_stream( packet_buffer, OUTPUT_BUFFER_SIZE ); packet_stream << osc::BeginBundleImmediate; packet_stream << osc::BeginMessage( "/audio_end" ) << osc::EndMessage; packet_stream << osc::EndBundle; transmitSocket.Send( packet_stream.Data(), packet_stream.Size() ); cout << "packet sent! size: " << packet_stream.Size() << endl; } // some defines #define SAMPLE double #define PI 3.14159265358979 #define TARGET_FPS 90 #define SAMPLE_RATE 44100 #define FORMAT RTAUDIO_FLOAT64 #define BASE_RATE 0.005 #define CHANNELS 1 #define N_FOUNTAINS 256 // audio callback int Sender::audio_callback(void *outputBuffer, void *inputBuffer, unsigned int nBufferFrames, double streamTime, RtAudioStreamStatus status, void* user_data) { /* hack to get this instance from inside static callback */ Sender * self = (Sender *) user_data; SAMPLE * ibuffy = (SAMPLE *)inputBuffer; if (is_sending_osc_data) { { osc::OutboundPacketStream packet_stream( packet_buffer, OUTPUT_BUFFER_SIZE ); packet_stream << osc::BeginBundleImmediate; packet_stream << osc::BeginMessage( "/audio" ) << osc::Blob(ibuffy, nBufferFrames * sizeof(SAMPLE)/2) << osc::EndMessage; packet_stream << osc::EndBundle; transmitSocket.Send( packet_stream.Data(), packet_stream.Size() ); cout << "packet sent! size: " << packet_stream.Size() << endl; } { osc::OutboundPacketStream packet_stream( packet_buffer, OUTPUT_BUFFER_SIZE ); packet_stream << osc::BeginBundleImmediate; packet_stream << osc::BeginMessage( "/audio" ) << osc::Blob(ibuffy + nBufferFrames/2, nBufferFrames * sizeof(SAMPLE)/2) << osc::EndMessage; packet_stream << osc::EndBundle; transmitSocket.Send( packet_stream.Data(), packet_stream.Size() ); cout << "packet sent! size: " << packet_stream.Size() << endl; } } for( unsigned int i = 0; i < nBufferFrames; i++ ) { self->_audio_buffer[i] = ibuffy[i]; // zero out buffer ibuffy[i] = 0.0; } return 0; } // entry point Sender::Sender() { _window_width = 800; _window_height = 600; init_sdl(); init_gl(); _dac = new RtAudio; if ( _dac->getDeviceCount() < 1 ) { std::cout << "No audio devices found!\n"; exit( 1 ); } // Let RtAudio print messages to stderr. _dac->showWarnings( true ); unsigned int offset = 0; _buffer_size = 512; RtAudio::StreamParameters iParams; iParams.deviceId = _dac->getDefaultInputDevice(); iParams.nChannels = CHANNELS; iParams.firstChannel = offset; try { _dac->openStream( NULL, &iParams, FORMAT, SAMPLE_RATE, &_buffer_size, audio_callback, this, NULL ); _audio_buffer = new SAMPLE[_buffer_size]; _dac->startStream(); } catch ( RtError& e ) { e.printMessage(); return; } // let GLUT handle the current thread from here cout << "initialization SUCCESS! buffer size is " << _buffer_size << endl; } Sender::~Sender() { delete _dac; } void Sender::clean_up() { try { _dac->stopStream(); } catch ( RtError& e ) { e.printMessage(); } if ( _dac->isStreamOpen() ) _dac->closeStream(); } void Sender::init_gl() { glEnable(GL_BLEND); glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // glEnable(GL_TEXTURE_2D); } /* initialize sdl screen*/ int Sender::init_sdl() { SDL_Surface *screen; if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) < 0) { fprintf(stderr, "Unable to initialize SDL: %s\n", SDL_GetError()); return(-1); } SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16); SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8); if (!(screen = SDL_SetVideoMode(_window_width, _window_height, 0, SDL_SWSURFACE | SDL_RESIZABLE | SDL_OPENGL))) { fprintf(stderr, "Unable to set video mode: %s\n", SDL_GetError()); return(-1); } SDL_WM_SetCaption("Realtime Sender", NULL); do_gl_projection(); return(0); } void Sender::do_gl_projection() { double aspect = double(_window_width)/_window_height; // set up coordinate space glMatrixMode( GL_PROJECTION ); glLoadIdentity(); glOrtho(-aspect, aspect, -1, 1, -1, 1); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } //----------------------------------------------------------------------------- // Name: reshapeFunc( ) // Desc: called when window size changes //----------------------------------------------------------------------------- void Sender::reshapeFunc( const SDL_ResizeEvent & resize_e ) { int w = resize_e.w, h = resize_e.h; // save the new window size _window_width = w; _window_height = h; // map the view port to the client area glViewport( 0, 0, w, h ); SDL_SetVideoMode(_window_width, _window_height, 0, SDL_SWSURFACE | SDL_RESIZABLE | SDL_OPENGL); do_gl_projection(); } int Sender::keyboard_event(const SDL_KeyboardEvent & keyboard_e) { int key = keyboard_e.keysym.sym; if (key == SDLK_ESCAPE || key == SDLK_q) { return SDL_QUIT; } return 0; } //----------------------------------------------------------------------------- // Name: render( ) // Desc: callback function invoked to draw the client area //----------------------------------------------------------------------------- void Sender::render(double tick_time) { glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); draw_phase_loop(); SDL_GL_SwapBuffers( ); } void Sender::update(double tick_time) { /* empty for now */ } void Sender::draw_phase_loop() { glEnable(GL_POINT_SMOOTH); glHint(GL_POINT_SMOOTH_HINT, GL_NICEST); glPointSize(2); double size_mult = 2; if (is_sending_osc_data) glColor4f( 1,.3,.3, .6); else glColor4f( 1,1,1, .4); for (int j = 3; j > 0; j--) { glLineWidth( j ); glBegin( GL_POINTS ); for( unsigned int i = 0; i < _buffer_size/2; i++ ) { glVertex2f( size_mult * _audio_buffer[i], size_mult * _audio_buffer[i+ _buffer_size/2]); } for( unsigned int i = 0; i < _buffer_size/2; i++ ) { glVertex2f( size_mult * _audio_buffer[i + _buffer_size/2], size_mult * _audio_buffer[i]); } glEnd(); } if (is_sending_osc_data) glColor4f( 1,.3,.3, .13); else glColor4f( 1,1,1, .1); for (int j = 3; j > 0; j--) { glLineWidth( j ); glBegin( GL_LINE_STRIP ); for( unsigned int i = 0; i < _buffer_size/2; i++ ) { glVertex2f( size_mult * _audio_buffer[i], size_mult * _audio_buffer[i+ _buffer_size/2]); } for( unsigned int i = 0; i < _buffer_size/2; i++ ) { glVertex2f( size_mult * _audio_buffer[i + _buffer_size/2], size_mult * _audio_buffer[i]); } glEnd(); } } void Sender::mouse_down_event(const SDL_MouseButtonEvent & button_e) { if (button_e.button != 1) return; start_sending_osc_data(); } void Sender::mouse_up_event(const SDL_MouseButtonEvent & button_e) { if (button_e.button != 1) return; finish_sending_osc_data(); } int Sender::main_loop() { bool quit = false; SDL_Event event; TickTimer tick_timer; TickTimer fps_tt; while (!quit) { if (SDL_PollEvent(&event)) { switch (event.type) { case SDL_MOUSEBUTTONDOWN: mouse_down_event(event.button); break; case SDL_MOUSEBUTTONUP: mouse_up_event(event.button); break; // case SDL_MOUSEMOTION: // mouse_motion_event(event.motion); // break ; // if( event.type == SDL_VIDEORESIZE case SDL_VIDEORESIZE: reshapeFunc(event.resize); break; case SDL_KEYDOWN: //case SDL_KEYUP: if (keyboard_event(event.key) == SDL_QUIT) quit = true; break; case SDL_QUIT: quit = true; break; } } else { fps_tt.tick(); double time_elapsed = tick_timer.tick(); update(time_elapsed); render(time_elapsed); double sleep_time = 1.0/TARGET_FPS - fps_tt.tick(); if (sleep_time > 0) usleep(sleep_time * 1000000); } } clean_up(); return(0); }