Search by Tags

How to play audio on TorizonCore using Alsa and C/C++

 

Article updated at 22 Mar 2021
Subscribe for this article updates

Select the version of your OS from the tabs below. If you don't know the version you are using, run the command cat /etc/os-release or cat /etc/issue on the board.



Remember that you can always refer to the Torizon Documentation, there you can find a lot of relevant articles that might help you in the application development.

Torizon 5.0.0

Introduction

In this article, we will show you how to play audio using Alsa (the Advanced Linux Sound Architecture) and C/C++ on TorizonCore.

Alsa is the Advanced Linux Sound Architecture, which is responsible to access input and output sound devices and it works based on client/server pattern, where the server-side is the Alsa driver inside Linux kernel space.

On Linux distributions for desktops (e.g. Ubuntu), we usually don't use Alsa directly because it can only support one client at a time, so we use PulseAudio, which can be seen as a layer between applications and Alsa and makes it possible to have more than one application using sound devices. Since an embedded system usually serves a single purpose, not using PulseAudio generally doesn't represent a limitation.

Prerequisites

Tip: In case you want to learn more about C/C++ Development on Torizon, It's also recommended reading the C/C++ Development and Debugging on TorizonCore Using Visual Studio Code article.

Instructions

Creating the project

Here, using the Visual Studio Code Extension for TorizonCore, we will create a headless project for C/C++ for our module, based on CMake. You must choose between arm32 or arm64, depending on your module's architecture.


  • CMake-based project

    CMake-based project

Let's call out project alsa-example.

After creating the alsa-example project, create the folder alsa-example/appconfig_0/audio, download and place the audio file example Ryan Andersen - Faster! Faster! Faster!.wav (original MP3 from here, converted to WAVE file) .

Configuring the project

Now, to configure our project, we need to tackle both the application runtime perspective and application development perspective.

Runtime perspective

From the application perspective, we will need to make sure that the application will:

  • have access to the sound devices;
  • have access to the audio file.
  • have the necessary packages for its runtime;
  • have the audio file as an input argument (this is needed since our application will play the audio file defined by its input argument)

Making a device available to the application

To make the sound devices available, we need to add /dev/snd to the devices entry of the Torizon Tab.


  • Screenshot of /dev/snd added to devices entry on Torizon Tab

    Screenshot of /dev/snd added to devices entry on Torizon Tab

Making a file available to the application

To make the audio file accessible, we need to add COPY audio /audio to the targetfiles entry of the Torizon Tab. With this, the audio file Ryan Andersen - Faster! Faster! Faster!.wav will be placed on the root of the filesystem of our application, but of course, you can place it where it best fits for your needs.


  • Screenshot of COPY audio /audio added to devices entry on Torizon Tab

    Screenshot of COPY audio /audio added to devices entry on Torizon Tab

Making a package available to the application

To make the packages available to the application's runtime, we need to add libasound2 alsa-utils to the extrapackages entry of the Torizon Tab. This will make the libasound2 (so we can use the Alsa API) and alsa-utils (so we can easily make audio configurations) to be installed on our application's Docker image.


  • Screenshot of libasound2 alsa-utils added to extrapackages entry on Torizon Tab

    Screenshot of libasound2 alsa-utils added to extrapackages entry on Torizon Tab

Setting input argument for the application

To set the input argument for the application, we need to add "/audio/Ryan\ Andersen\ -\ Faster\!\ Faster\!\ Faster\!.wav" to the arg entry of the Torizon Tab.


  • Screenshot of /audio/Ryan\ Andersen\ -\ Faster!\ Faster!\ Faster!.wav added to appargs entry on Torizon Tab

    Screenshot of /audio/Ryan\ Andersen\ -\ Faster!\ Faster!\ Faster!.wav added to appargs entry on Torizon Tab

Development perspective

And, from the development perspective, we will need to make sure that our SDK will:

  • have access to the compile-time necessary packages

Making a package available for compile-time

To make the package available to the application's compile-time, we need to add the development package of libasound2, so it will be added to our application's SDK Docker image. To perform this. We would need to pay attention to our module's architecture since our application will be cross-compiled, but the Visual Studio Code Extension for Torizon makes available the platform.debian-arch variable available, so we can add to devpackages libasound2-dev:#%platform.debian-arch%#.


  • Screenshot of libasound2-dev:#%platform.debian-arch%# added to devpackages entry on Torizon Tab

    Screenshot of libasound2-dev:#%platform.debian-arch%# added to devpackages entry on Torizon Tab

Setting up the example project files

Now you will need to get some source files for this example.

Source main code

Substitute your alsa-example.cpp with this alsa-example.cpp from the github repository (if you used another name than alsa-example for this project, you may have to rename this file accordingly)

CMakeLists file

Substitute your CMakeLists.txt with this CMakeLists.txt from the repository (if you used other name than alsa-example for this project, you may have to rename this file accordingly).

Debugging options (optional)

On your .vscode/launch.json, change your stopAtEntry option to false, so the debugger will not place a breakpoint on the first line code.


  • Screenshot of stopAtEntry defined as false on .vscode/launch.json

    Screenshot of stopAtEntry defined as false on .vscode/launch.json

Executing the application on the module

Now you can fit F5 to deploy your application-container to the module and, if you have your module/carrier board correctly connected to a sound system, you should listen to the Faster! Faster! Faster! from Ryan Andersen.

Remark: the original alsa-example.cpp is from here