Skip to main content
Version: Torizon OS 7.x.y

How to play audio on Torizon OS using ALSA and C/C++

Introduction

This article shows how to play audio using ALSA and C/C++ on Torizon OS.

What is ALSA

ALSA stands for Advanced Linux Sound Architecture and is responsible for accessing input and output sound devices. It works based on a client/server pattern, where the server side is the ALSA driver inside the Linux kernel space. For more information, see the ALSA documentation.

On desktop Linux distributions (e.g. Ubuntu), ALSA is rarely used directly because it can only support one client at a time. Instead, we use PulseAudio - a layer between applications and ALSA - that 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 and introduces additional complexity without providing substantial benefits.

Prerequisites

  • A SoM with Torizon OS installed.
  • An audio speaker or headphones.

Project Structure

For a hands-on example of using ALSA with Toradex modules, we are going to build and run a C code example. In summary, This application will:

  1. Read a WAV file and get audio data.
  2. Set up ALSA based on the file format and audio output.
  3. Play the audio.

This application requires the following project structure:

├── alsa-example
│ ├── main.c
│ ├── wav-file.wav
│ ├── Dockerfile
  • main.c: The source code of the application.
  • WAV file: The audio that will be played on the SoM.
  • Dockerfile: The file that contains the commands to build the container.

Build the Application

  1. Download the source code of the application alsa-alsa_example.cpp from GitHub.

  2. Download a WAV file. You can download the following one as an example: Ryan Andersen - Faster! Faster! Faster!.wav.

  3. Get the name of your module's audio codec with the following command:

    # cat /proc/asound/cards

    Output example for the imx8mpnau8822 audio codec:

     1 [imx8mpnau8822  ]: simple-card - imx8mp-nau8822
    imx8mp-nau8822

    For more information about ALSA utilities and audio processing on different SoMs, see Audio (Linux).

  4. Create a Dockerfile with the content below. Remember to replace imx8mpnau8822 with your module's audio codec name.

    Dockerfile
    ### Build Stage ###
    FROM --platform=linux/arm64 torizon/debian:3-bookworm AS build

    ENV DEBIAN_FRONTEND=noninteractive

    # Install dependencies
    RUN apt-get update \
    && apt-get install -y build-essential libasound2-dev

    # Set the directory for subsequent Dokerfile instructions
    WORKDIR /home/torizon

    # Copy the source code from the local system to the build stage
    COPY alsa-example.cpp .

    # Compile the application, linking the libasound library
    RUN g++ alsa-example.cpp -O2 -lasound -o alsa_example

    ### Deploy stage ###
    FROM --platform=linux/arm64 torizon/debian:3-bookworm AS deploy

    ENV DEBIAN_FRONTEND=noninteractive

    # Install dependencies in the container image
    RUN apt-get update \
    && apt-get install -y alsa-utils \
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/*

    WORKDIR /home/torizon

    # TODO: Replace "imx8mpnau8822" with your sound codec
    ENV ALSA_CARD=imx8mpnau8822

    # Copy the compiled program to the container image
    COPY --from=build /home/torizon/alsa_example .

    # Copy the .wav file to the container image
    COPY ["Ryan Andersen - Faster! Faster! Faster!.wav", "."]

    # Set alsa-example as the entry point of the container
    # Once up, the container will automatically run this application
    ENTRYPOINT [ "./alsa_example" ]

    # Pass the WAV file as an argument to alsa-example
    CMD ["Ryan Andersen - Faster! Faster! Faster!.wav"]
    info

    This Dockerfile uses a multi-stage build to reduce container image size.

  1. Enable ARM emulation. This is necessary for building the container for the ARM architecture.

  2. Open a terminal in your project directory and build the container image. Make sure your project structure is correct.

    $ docker build -t <your-container-registry>/alsa-example .

    For more information about container registries, see Store and Share Container Images.

  3. Push the image to a container registry:

    $ docker push <your-container-registry>/alsa-example

Run the Application

  1. Connect a speaker or headphones to the audio jack on your carrier board.

  2. Run the container on your target device:

    # docker run -it --rm --device /dev/snd/ <your-container-registry>/alsa-example

    The --device /dev/snd/ flag allows the container to access the available sound cards. For more information, see Peripheral Access Overview.

  3. If the application successfully plays the audio, it will display the following message:

    Simple mixer control 'Headphone',0
    Capabilities: volume pswitch
    Playback channels: Front Left - Front Right
    Capture channels: Front Left - Front Right
    Limits: 0 - 63
    Front Left: 32 [51%] [-25.00dB] Playback [on]
    Front Right: 32 [51%] [-25.00dB] Playback [on]

Debugging

To debug the application while it runs on your target device, we recommend using the Torizon IDE extension. It provides tasks that automatically set up the development environment and remote debugging session.



Send Feedback!