Chapter 12. Using Audio Input and Output

In this chapter, we will learn how to generate sounds using examples of ways to generate sounds driven by physics simulation. We will also present examples of visualizing sound with audio reactive animations.

The following recipes will cover:

  • Generating a sine oscillator
  • Generating sound with frequency modulation
  • Adding a delay effect
  • Generating sound upon the collision of objects
  • Visualizing FFT
  • Making sound-reactive particles

Generating a sine oscillator

In this recipe, we will learn how to generatively create a sine wave oscillator by manipulating the sound card's PCM (Pulse-code Modulation ) audio buffer. The frequency of the sine wave will be defined by the mouse's y coordinate.

We will also draw the sine wave for a visual representation.

Getting ready

Include the following files:

#include "cinder/audio/Output.h"
#include "cinder/audio/Callback.h"
#include "cinder/Rand.h"
#include "cinder/CinderMath.h"

And add the following useful using statements:

using namespace ci;
using namespace ci::app;
using namespace std;

How to do it…

We will create a sine wave oscillator using the following steps:

  1. Declare the following member variables and the callback method:
    void audioCallback( uint64_t inSampleOffset, uint32_t ioSampleCount, audio::Buffer32f *buffer );
    float mFrequency;
    float mPhase, mPhaseAdd;
    vector<float> mOutput;
  2. In the setup module we will initialize the variables and create the audio callback using the following code:
    mFrequency = 0.0f;
    mPhase = 0.0f;
    mPhaseAdd = 0.0f;
    audio::Output::play( audio::createCallback( this, &SineApp::audioCallback ) );
  3. In the update module we will update mFrequency based on the mouse's y position. The mouse's position will be mapped and clamped to a frequency value between 0 and 5000:
    float maxFrequency = 5000.0f;
    float targetFrequency = ( getMousePos().y / (float)getWindowHeight() ) * maxFrequency;
    mFrequency = math<float>::clamp( targetFrequency, 0.0f, maxFrequency );

    Let's implement the audio callback. We'll begin by resizing mOutput if necessary. Then we will calculate and interpolate mPhaseAdd, and then loop through all the values in the audio buffer and calculate their values based on the sine of mPhase and add mPhaseAdd to mPhase:

    if( mOutput.size() != ioSampleCount ){
     mOutput.resize( ioSampleCount );
    }
    int numChannels = buffer->mNumberChannels;
    mPhaseAdd += ( ( mFrequency / 44100.0f ) - mPhaseAdd ) * 0.1f;
    for( int i=0; i<ioSampleCount; i++ ){
     mPhase += mPhaseAdd;
     float output = math<float>::sin( mPhase * 2.0f * M_PI );
     for( int j=0; j<numChannels; j++ ){
      buffer->mData[ i*numChannels + j ] = output;
     }
     mOutput[i] = output;
    }
  4. Finally, we need to draw the sine wave. In the draw method, we will clear the background with black and draw a scaled up sine wave with a line strip using the values stored in mOutput:
    gl::clear( Color( 0, 0, 0 ) );
    if( mOutput.size() > 0 ){
     Vec2f scale;
     scale.x = (float)getWindowWidth() / (float)mOutput.size();
     scale.y = 100.0f;
     float centerY= getWindowHeight() / 2.0f;
     gl::begin( GL_LINE_STRIP );
     for( int i=0; i<mOutput.size(); i++ ){
      float x = (float)i * scale.x;
      float y = mOutput[i] * scale.y + centerY;
      gl::vertex( x,  y );
     } 
     gl::end();
    }
  5. Build and run the application. Move the mouse vertically to change the frequency. A line representing the generated sine wave is shown in the following screenshot:
    How to do it…

How it works…

We are manipulating the PCM buffer. PCM is a method to represent audio through values' samples at regular intervals. By accessing the PCM buffer, we can directly manipulate the audio signal that will be output by the sound card.

Every time the audioCallback method is called, we receive a sample of the PCM buffer, where we calculate the values to generate a continuous sine wave.

In the update module, we calculate the frequency by mapping the mouse's y position.

In the following line in the audioCallback implementation, we calculate how much mPhase has to increase based on a sample rate of 44100 to generate a wave with a frequency of mFrequency:

mPhaseAdd += ( ( mFrequency / 44100.0f ) - mPhaseAdd ) * 0.1f;
..................Content has been hidden....................

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