void AudioVisualizerApp::setup() { // initialize signals signalChannelEnd = false; // make a list of valid audio file extensions and initialize audio variables const char* extensions[] = { "mp3", "wav", "ogg" }; mAudioExtensions = vector<string>( extensions, extensions + 2 ); mAudioPath = getAssetPath( "" ); mIsAudioPlaying = false; // setup camera mCamera.setPerspective( 50.0f, 1.0f, 1.0f, 10000.0f ); mCamera.lookAt( vec3( -kWidth / 4, kHeight / 2, -kWidth / 8 ), vec3( kWidth / 4, -kHeight / 8, kWidth / 4 ) ); mCameraUi.setCamera( &mCamera ); // create channels from which we can construct our textures mChannelLeft = Channel32f( kBands, kHistory ); mChannelRight = Channel32f( kBands, kHistory ); memset( mChannelLeft.getData(), 0, mChannelLeft.getRowBytes() * kHistory ); memset( mChannelRight.getData(), 0, mChannelRight.getRowBytes() * kHistory ); // create texture format (wrap the y-axis, clamp the x-axis) mTextureFormat.setWrapS( GL_CLAMP_TO_BORDER ); mTextureFormat.setWrapT( GL_REPEAT ); mTextureFormat.setMinFilter( GL_LINEAR ); mTextureFormat.setMagFilter( GL_LINEAR ); mTextureFormat.loadTopDown( true ); // compile shader try { mShader = gl::GlslProg::create( loadAsset( "shaders/spectrum.vert" ), loadAsset( "shaders/spectrum.frag" ) ); } catch( const std::exception& e ) { console() << e.what() << std::endl; quit(); return; } // create static mesh (all animation is done in the vertex shader) std::vector<vec3> positions; std::vector<Colorf> colors; std::vector<vec2> coords; std::vector<uint32_t> indices; for( size_t h = 0; h < kHeight; ++h ) { for( size_t w = 0; w < kWidth; ++w ) { // add polygon indices if( h < kHeight - 1 && w < kWidth - 1 ) { size_t offset = positions.size(); indices.emplace_back( offset ); indices.emplace_back( offset + kWidth ); indices.emplace_back( offset + kWidth + 1 ); indices.emplace_back( offset ); indices.emplace_back( offset + kWidth + 1 ); indices.emplace_back( offset + 1 ); } // add vertex positions.emplace_back( vec3( float( w ), 0, float( h ) ) ); // add texture coordinates // note: we only want to draw the lower part of the frequency bands, // so we scale the coordinates a bit const float part = 0.5f; float s = w / float( kWidth - 1 ); float t = h / float( kHeight - 1 ); coords.emplace_back( vec2( part - part * s, t ) ); // add vertex colors colors.emplace_back( Color( CM_HSV, s, 0.5f, 0.75f ) ); } } gl::VboMesh::Layout layout; layout.usage( GL_STATIC_DRAW ); layout.attrib( geom::Attrib::POSITION, 3 ); layout.attrib( geom::Attrib::COLOR, 3 ); layout.attrib( geom::Attrib::TEX_COORD_0, 2 ); mMesh = gl::VboMesh::create( positions.size(), GL_TRIANGLES, { layout }, indices.size(), GL_UNSIGNED_INT ); mMesh->bufferAttrib( geom::POSITION, positions.size() * sizeof( vec3 ), positions.data() ); mMesh->bufferAttrib( geom::COLOR, colors.size() * sizeof( vec3 ), colors.data() ); mMesh->bufferAttrib( geom::TEX_COORD_0, coords.size() * sizeof( vec2 ), coords.data() ); mMesh->bufferIndices( indices.size() * sizeof( uint32_t ), indices.data() ); // play audio using the Cinder FMOD block FMOD::System_Create( &mFMODSystem ); mFMODSystem->init( 32, FMOD_INIT_NORMAL | FMOD_INIT_ENABLE_PROFILE, NULL ); mFMODSound = nullptr; mFMODChannel = nullptr; playAudio( findAudio( mAudioPath ) ); mIsMouseDown = false; mMouseUpDelay = 30.0; mMouseUpTime = getElapsedSeconds() - mMouseUpDelay; // the texture offset has two purposes: // 1) it tells us where to upload the next spectrum data // 2) we use it to offset the texture coordinates in the shader for the scrolling effect mOffset = 0; }
void FiretrailApp::setup() { mCamera.lookAt(vec3(.0f, .0f, -1.0f), vec3(.0f)); mParams = params::InterfaceGl::create( getWindow(), "App parameters", toPixels( ivec2( 200, 300 ) ) ); mParams->addParam("FPS", &mFps); mParams->addParam("Max D Slice", &mMaxDSlice); mParams->addParam("Time Factor", &mTimeFactor); mParams->addParam("Gain", &mGain ).updateFn( [this] { mGlsl->uniform("gain", mGain);} ); mParams->addParam("Lacunarity", &mLacunarity).updateFn( [this] { mGlsl->uniform("lacunarity", mLacunarity);} ); mParams->addParam("Magnitude", &mMagnitude ).updateFn( [this] { mGlsl->uniform("magnitude", mMagnitude);} ); mParams->addParam("Frag Mul", &mFragMul ).updateFn( [this] { mGlsl->uniform("fragMul", mFragMul);} ); mParams->addParam("Noise Scale", &mNoiseScale).updateFn( [this] { mGlsl->uniform("noiseScale", mNoiseScale);} ); mParams->addParam("Layer Offset", &mLayerOffset).updateFn( [this] { mGlsl->uniform("layerOffset", mLayerOffset);} ); mParams->addButton("Start Recording", [this] { if (!mRecordingMovie) startMovieRecording(); }); mParams->addButton("End Recording", [this] { if (mRecordingMovie) endMovieRecording(); }); gl::Texture::Format mTexFormat; mTexFormat.magFilter( GL_LINEAR ).minFilter( GL_LINEAR ).internalFormat( GL_RGBA );//.wrap(GL_REPEAT); mFireTex = gl::Texture::create( loadImage( loadAsset( "flame6.png" ) ), mTexFormat ); mTexFormat.wrap(GL_REPEAT); mNoiseTex = gl::Texture::create( loadImage( loadAsset( "nzw.png" ) ), mTexFormat ); mGlsl = gl::GlslProg::create(gl::GlslProg::Format() .vertex( loadAsset( "fire.vert" ) ) .fragment( loadAsset( "fire.frag" ) ) .geometry( loadAsset( "fire.geom" )).attrib( geom::CUSTOM_0, "vSize" ) ); mGlsl->uniform("fireTex", 0); mGlsl->uniform("noiseTex", 1); mGlsl->uniform("fragMul", mFragMul); mGlsl->uniform("gain", mGain); mGlsl->uniform("magnitude", mMagnitude); mGlsl->uniform("lacunarity", mLacunarity); mGlsl->uniform("noiseScale", mNoiseScale); mGlsl->uniform("layerOffset", mLayerOffset); // compute texture coordinates vector<float> amp( NUM_SPLINE_NODES ); amp.resize(NUM_SPLINE_NODES); for (size_t i = 0; i < NUM_SPLINE_NODES; ++i) { const auto t = (float)i / (float)(NUM_SPLINE_NODES - 1); amp[i] = 1.0f - easeInOutSine(t); } mVboMesh = gl::VboMesh::create( NUM_SPLINE_NODES, GL_POINTS, { gl::VboMesh::Layout().usage( GL_DYNAMIC_DRAW ).attrib( geom::POSITION, 3 ), gl::VboMesh::Layout().usage( GL_STATIC_DRAW ).attrib( geom::Attrib::CUSTOM_0, 1 ), }); mVboMesh->bufferAttrib(geom::Attrib::CUSTOM_0, amp); mBatch = gl::Batch::create(mVboMesh, mGlsl); resize(); }