Generating sound upon the collision of objects

In this recipe, we will learn how to apply simple physics to object particles and generate sound upon the collision of two objects.

Getting ready

In this example, we are using code described in the recipe Generating a sine oscillator in this chapter, so please refer to that recipe.

How to do it…

We will create a Cinder application to illustrate the mechanism:

  1. Include the following necessary header files:
    #include "cinder/audio/Output.h"
    #include "cinder/audio/Callback.h"
    #include "cinder/Rand.h"
    #include "cinder/CinderMath.h"
    #include "ParticleSystem.h"
  2. Add members to the application's main class for particle simulation:
    ParticleSystem mParticleSystem;
    Vec2fattrPosition;
    float attrFactor;
    float attrRadius;
  3. Add members to the application's main class to make the particles interactive:
    bool    dragging;
    Particle *dragParticle;
  4. Add members for the generation of sound:
    void audioCallback( uint64_t inSampleOffset, uint32_t ioSampleCount,audio::Buffer32f *buffer );
    float mSndFrequency;
    float mPhase, mPhaseAdd;
    vector<float> mOutput;
  5. Initialize the particle system inside the setup method:
    mRunning= true;
    dragging = false;
    attrPosition = getWindowCenter();
    attrRadius = 75.f;
    attrFactor = 0.02f;
    int numParticle= 10;
    for( int i=0; i<numParticle; i++ ){
     float x = Rand::randFloat( 0.0f, getWindowWidth() );
     float y = Rand::randFloat( 0.0f, getWindowHeight() );
     float radius = Rand::randFloat(2.f, 40.f);
     Rand::randomize();
     float mass = radius;
     float drag = 0.95f;
     Particle *particle = new Particle( Vec2f( x, y ), radius,
      mass, drag );
     mParticleSystem.addParticle( particle );
    }
  6. Initialize the members to generate sound and register an audio callback inside the setup method:
    mSndFrequency = 0.0f;
    mPhase = 0.0f;
    mPhaseAdd = 0.0f;
    audio::Output::play( audio::createCallback( this, &MainApp::audioCallback ) );
  7. Implement the resize method to update the attractor position whenever an application window will be resized:
    void MainApp::resize(ResizeEvent event)
    {
      attrPosition = getWindowCenter();
    }
  8. Implement the mouse events handlers for mouse interaction with particles:
    void MainApp::mouseDown(MouseEvent event)
    {
     dragging = false;
     std::vector<Particle*>::iterator it;
     for( it = mParticleSystem.particles.begin(); 
       it != mParticleSystem.particles.end(); ++it ) {
      if( (*it)->position.distance(event.getPos()) 
        < (*it)->radius ) {
       dragging = true;
       dragParticle = (*it);
      }
     }
    }
    
    void MainApp::mouseUp(MouseEvent event) {
     dragging = false;
    }
  9. Inside the update method, add the following code for sound frequency calculation:
    float maxFrequency = 15000.0f;
    float targetFrequency = ( getMousePos().y / (float)getWindowHeight() ) * maxFrequency;
    targetFrequency = mSndFrequency - 10000.f;
    mSndFrequency = math<float>::clamp( targetFrequency, 0.0f, maxFrequency );
  10. Inside the update method, add the following code for particle movement calculation. At this point, we are detecting collisions and calculating the sound frequency:
    std::vector<Particle*>::iterator it;
    for( it = mParticleSystem.particles.begin(); 
      it != mParticleSystem.particles.end(); ++it ) {
     std::vector<Particle*>::iterator it2;
     for( it2 = mParticleSystem.particles.begin(); 
       it2 != mParticleSystem.particles.end(); ++it2 ) {
      float d = (*it)->position.distance( (*it2)->position );
      float d2 = (*it)->radius + (*it2)->radius;
      if(d >0.f&& d <= d2 ) {
       (*it)->forces += -1.1f * ( (*it2)->position 
         - (*it)->position );
       (*it2)->forces += -1.1f * ( (*it)->position 
         - (*it2)->position );
       mSndFrequency = 2000.f;
       mSndFrequency+= 10000.f
         * (1.f - ((*it)->radius / 40.f));
       mSndFrequency+= 10000.f 
         * (1.f - ((*it2)->radius / 40.f));
      }
     }
     Vec2f attrForce = attrPosition - (*it)->position;
     attrForce *= attrFactor;
     (*it)->forces += attrForce;
    }
    mSndFrequency = math<float>::clamp( mSndFrequency, 
     0.0f, maxFrequency );maxFrequency );
  11. Update position of dragging particle, if any, and update particle system:
    if(dragging) {
      dragParticle->forces = Vec2f::zero();
      dragParticle->position = getMousePos();
    }
    
    mParticleSystem.update();
  12. Draw particles by implementing the draw method as follows:
    gl::clear( Color::white() );
    gl::setViewport(getWindowBounds());
    gl::setMatricesWindow( getWindowWidth(), getWindowHeight() );
    gl::color( Color::black() );
    mParticleSystem.draw();
  13. Implement audio callback handler as covered in the recipe Generating a sine oscillator.

How it works…

We are generating random particles with applied physics and collision detection. While collision is detected, a frequency of a sine wave is calculated based on the particles' radii.

How it works…

Inside the update method, we are iterating through the particles and checking the distance between each of them to detect collision, if it occurs. A generated frequency is calculated from the radii of the colliding particles—the bigger the radius, the lower the frequency of the sound.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.144.40.189