Subsections

Realtime Audio and MIDI Input/Output

Blocking Functionality

Below is an example realtime audio ouput program that uses the RtWvOut class in a blocking context.
#include "SineWave.h"
#include "RtWvOut.h"
#include "Envelope.h"
#include "ADSR.h"
#include "FileWvOut.h"

using namespace stk;

int main()
{
  // Set the global sample rate before creating class instances.
  Stk::setSampleRate( 44100.0 );
  Stk::showWarnings( true );
  int nFrames = 100000;
  int releaseCount = (int) (0.9 * nFrames);
  float rampTime = (nFrames - releaseCount) / Stk::sampleRate();

  try {

    SineWave sine;
    RtWvOut dac( 1 );  // Define and open the default realtime output device for one-channel playback

    /* If you wanted to also create an output soundfile (also uncomment output.tick() below)
       FileWvOut output;
       output.openFile( "rttest", 1, FileWrite::FILE_WAV, Stk::STK_SINT16 );
    */

    /* Use ADSR */
    ADSR env;
    env.keyOn();
    env.setAllTimes( rampTime, rampTime, 0.7, rampTime ); // Attack time, decay time, sustain level, release time


    /* Or use a linear line segment envelope (and comment-out the ADSR lines above)
       Envelope env;
       env.keyOn();
       env.setTime( rampTime ); // Attack and release time
    */

    sine.setFrequency( 440.0 );

    // Single-sample computations
    StkFloat temp;
    for ( int i=0; i<nFrames; i++ ) {
      temp = env.tick() * sine.tick();
      dac.tick( temp );
      //output.tick( temp );
      if ( i == releaseCount ) env.keyOff();
    }
  }
  catch ( StkError & ) {
    exit( 1 );
  }

  return 0;
}

This example can be compiled on a Macintosh OS-X system with the following syntax, assuming the file rtsine.cpp is in the working directory as described above:

g++ -Istk/include/ -Lstk/src/ -D__MACOSX_CORE__ rtsine.cpp -lstk -lpthread -framework CoreAudio -framework CoreMIDI -framework CoreFoundation

This example can be compiled on a Windows system (using MinGW and MSYS) with the following syntax, assuming the file rtsine.cpp is in the working directory as described above:

g++ -o rtsine -Istk/include/ -Lstk/src/ -D__WINDOWS_DS__ rtsine.cpp -lstk -lpthread -ldsound -lole32 -lwinmm

Callback Functionality

Below are two examples of realtime audio ouput using the RtAudio class in a callback context.
// rtex1.cpp
//
// Realtime audio output example using callback functionality.

#include "RtAudio.h"
#include <iostream>
#include <cmath>

const double PI     = 3.14159265359;
const double TWO_PI = 2 * PI;
const double frequency = 440.0;
const int sampleRate = 44100;
const double samplePeriod = 1.0 / sampleRate;
const double phaseIncrement = TWO_PI * frequency * samplePeriod;
double phase = 0;

int sin( void *outputBuffer, void *, unsigned int nBufferFrames,
         double, RtAudioStreamStatus, void * )
{
  // Cast the buffer to the correct data type.
  double *my_data = (double *) outputBuffer;

  // We know we only have 1 sample per frame here.
  for ( int i=0; i<nBufferFrames; i++ ) {
    my_data[i] = std::sin( phase );
    phase += phaseIncrement;
    if ( phase > TWO_PI ) phase -= TWO_PI;
  }

  return 0;
}

int main()
{
  unsigned int nBufferFrames = 256;  // 256 sample frames
  unsigned int sampleRate = 44100;
  unsigned int nChannels = 1;
  RtAudio dac;

  // Open the default realtime output device.
  RtAudio::StreamParameters parameters;
  parameters.deviceId = dac.getDefaultOutputDevice();
  parameters.nChannels = nChannels;
  try {
    dac.openStream( &parameters, NULL, RTAUDIO_FLOAT64, sampleRate, &nBufferFrames, &sin );
  }
  catch ( RtAudioError &error ) {
    error.printMessage();
    exit( EXIT_FAILURE );
  }

  try {
    dac.startStream();
  }
  catch ( RtAudioError &error ) {
    error.printMessage();
    exit( EXIT_FAILURE );
  }

  char input;
  std::cin.get( input ); // block until user hits return

  // Stop the stream.
  try {
    dac.stopStream();
  }
  catch ( RtAudioError &error ) {
    error.printMessage();
  }

  return 0;
}

This example can be compiled on a Macintosh OS-X system with the following syntax:

g++ -Istk/include/ -Lstk/src/ -D__MACOSX_CORE__ rtex1.cpp -lstk -lpthread -framework CoreAudio -framework CoreMIDI -framework CoreFoundation

The previous example can be easily modified to take realtime input from a soundcard, pass it through a comb filter, and send it back out to the soundcard as follows:

// rtex2.cpp
//
// Realtime audio input/output example with comb filter using callback functionality.
#include "RtAudio.h"
#include <iostream>
#include "Delay.h"
using namespace stk;

Delay delay;

int comb( void *outputBuffer, void *inputBuffer, unsigned int nBufferFrames,
          double, RtAudioStreamStatus, void * )
{
  // Cast the buffers to the correct data type.
  double *idata = (double *) inputBuffer;
  double *odata = (double *) outputBuffer;

  // We know we only have 1 sample per frame here.
  for ( int i=0; i<nBufferFrames; i++ ) {
    odata[i] = idata[i] + 0.98 * delay.lastOut(); // feedback comb
//    odata[i] = idata[i] + delay.tick( idata[i] ); // feedforward comb
    odata[i] *= 0.45;
    delay.tick( odata[i] );  // feedback comb
  }

  return 0;
}

int main()
{
  unsigned int nBufferFrames = 256;  // 256 sample frames
  unsigned int sampleRate = 44100;
  unsigned int nChannels = 1;
  RtAudio adac;

  delay.setDelay( 1000 );

  // Open the default realtime output device.
  RtAudio::StreamParameters oParameters, iParameters;
  oParameters.deviceId = adac.getDefaultOutputDevice();
  iParameters.deviceId = adac.getDefaultInputDevice();
  oParameters.nChannels = nChannels;
  iParameters.nChannels = nChannels;
  try {
    adac.openStream( &oParameters, &iParameters, RTAUDIO_FLOAT64, sampleRate, &nBufferFrames, &comb );
  }
  catch ( RtAudioError &error ) {
    error.printMessage();
    exit( EXIT_FAILURE );
  }

  try {
    adac.startStream();
  }
  catch ( RtAudioError &error ) {
    error.printMessage();
    exit( EXIT_FAILURE );
  }

  char input;
  std::cin.get( input ); // block until user hits return

  // Stop the stream.
  try {
    adac.stopStream();
  }
  catch ( RtAudioError &error ) {
    error.printMessage();
  }

  return 0;
}



McGill ©2004-2020 McGill University. All Rights Reserved.
Maintained by Gary P. Scavone.