Skip to content

Multithreading

Samuel H edited this page Jul 22, 2021 · 2 revisions

In the previous tutorial, you have seen the basics of multithreading in TSAL. In this tutorial, we will see a more complex "Hello world!" example utilizing the multithreading capability of TSAL.

Linux/Mac/Cygwin users: Start off by creating a folder and name it "Tutorial4". Create a file inside of Tutorial4 and name it "threadedHello.cpp". Then, navigate to the cloned TSAL folder and into the genericMakefile folder. Copy the Makefile into Tutorial2 and change the "TARGET" line so that "program" is now "threadedHello". Follow the steps in the Building Programs page on how to compile and run the program (this is a single-file program).

Each synth will get its own thread and play a pitch based on that thread id.

#include "tsal.hpp"
#include <omp.h>

using namespace tsal;

int main() {
  int numThreads = 2;
      
  // Create the mixer and array of synths
  Mixer mixer;
  std::vector<Synth> synths(numThreads, Synth(&mixer));

  // Setup omp with a number of threads
  omp_set_num_threads(numThreads);
}

Let's add each synth based on the id using an omp parallel block:

#include "tsal.hpp"
#include <omp.h>

using namespace tsal;

int main() {
  int numThreads = 2;
      
  // Create the mixer and array of synths
  Mixer mixer;
  std::vector<Synth> synths(numThreads, Synth(&mixer));

  // Setup omp with a number of threads
  omp_set_num_threads(numThreads);

  // Run the parallel block
  #pragma omp parallel
  {
    int id = omp_get_thread_num();

    // Add the synth to the mixer
    mixer.add(synths[id]);
    synths[id].setVolume(.5);
    
    // Start playing a pitch based on thread number
    synths[id].play(C4 + 5 * id);

    // Wait for a second
    Util::thread_sleep(1000);

    // Stop playing 
    synths[id].stop();
  }

  return 0;
}

After compiling and running, you should hear a sound playing for a second. You can change the numThreads variable to the number of threads you want. To add more flexibility, let's provide the user with an option of inputting the desired number of threads as an argument.

#include "tsal.hpp"
#include <omp.h>

using namespace tsal;

int main(int argc, char* argv[]) {
  int numThreads = (argc == 2) ? atoi(argv[1]) : 2;
  if (numThreads == 0) {
    std::cout << "\nhello_tsal_threads <num_threads>\n"
              << "\tnum_threads = the number of threads\n"
              << std::endl;
    return 0;
  }
      
  // Create the mixer and array of synths
  Mixer mixer;
  std::vector<Synth> synths(numThreads, Synth(&mixer));

  // Setup omp with a number of threads
  omp_set_num_threads(numThreads);

  // Run the parallel block
  #pragma omp parallel
  {
    int id = omp_get_thread_num();

    // Add the synth to the mixer
    mixer.add(synths[id]);
    synths[id].setVolume(.5);
    
    // Start playing a pitch based on thread number
    synths[id].play(C4 + 5 * id);

    // Wait for a second
    Util::thread_sleep(1000);

    // Stop playing 
    synths[id].stop();
  }

  return 0;
}

The above code will take the number of threads as an argument if provided. If not provided it will default to 2 threads. Then uses the thread id to play the corresponding synth through the mixer.

That concludes the tutorials we have for you. Now you can create your own sonifications using TSAL.

Clone this wiki locally