world leader in high performance signal processing
Trace: » audio

ADSP-BF548 EZ-KIT Quick Start: Peripheral Demos: audio

www.analog.com_static_imported-files_images_product_descriptions_680755565image1a.jpg

What is audio

A simple application that uses SDL_mixer to play an mp3 file (fur ellise) through the audio output.

Note that the kernel option 'Device Drivers > Sound card Support > Alsa for SoC audio support > SoC AC97 Audio for the ADI BF5xx chip' must be enabled for this to work. The suboptions of that should have 'BOARD has COLD Reset GPIO' enabled with port 19 set for gpio cold reset and also have suboption 'SoC AD1980/1 Audio support for BF5xx (Obsolete)' enabled.

Device Drivers ->
  Sound card Support ->
    Advanced Linux Sound Architecture ->
      Alsa for SoC audio support ->
        SoC AC97 Audio for the ADI BF5xx chip ->
          [X] Enable MMAP Support
          [X] BOARD has COLD Reset GPIO
            (19) Set a GPIO for cold reset
          [X] SoC AD1980/1 Audio support for BF5xx (Obsolete)

Download audio

The demo comes with the customised Ubuntu ISO and can be found in the folder /home/Blackfin/demos. Alternatively it is already installed on the demo uClinux image (demo-uclinux.img) that you can get on ADSP-BF548 EZ-KIT Quick Start: Booting uClinux.

If you just want to download the demos on their own and get their source code you can download the compressed archive (demos-R1.tar.gz) here bf548-quick-start .

How to run the audio program

  • Change directory to /demos/audio

    root:/> cd /demos/audio
  • Make sure headphones or speakers are plugged into the correct port

  • Make sure SDL knows that there is no mouse available otherwise it won't run

    root:/> export SDL_NOMOUSE=1

    Note: You only need to do this once per uClinux boot. If you want your program to make use of the touch screen, do not run this environment variable and instead run the commands found in the touchscreen demos.

  • Run audio

    root:/> ./audio
    Playing. Interrupt to exit
  • Listen to music from your headphones / speakers
  • Exit (Ctrl + C)

How the audio demo works

Required header files

#include <stdio.h>

// Necessary for this demo
#include <SDL.h>

// Necessary Audio Libraries
#include <SDL_mixer.h>

These libraries as you can see are for SDL_mixer to load and and handle audio.

SDL Initialisation

// Initializes the audio & video subsystem
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0)
{
  fprintf(stderr, "Error: Unable to init SDL: %s\n", SDL_GetError());
  exit(1);
}
atexit(SDL_Quit);
SDL_ShowCursor (SDL_DISABLE);

screen = SDL_SetVideoMode(screen_width, screen_height, screen_bitdepth, SDL_HWSURFACE | SDL_DOUBLEBUF);
if (screen == NULL)
{
  fprintf(stderr, "Error: Unable to grab screen\n");
  SDL_Quit();
  exit(1);
}

if(Mix_OpenAudio(audio_rate, audio_format, audio_channels, audio_buffers))
{
  fprintf(stderr, "Unable to open audio!\n");
  exit(1);
}

This section of code will initiate SDL with expectations to grab video and audio. It also hides the cursor. This is a good example of merging two SDL functions together, in this case video and audio. You can learn more about SDL and initiation at its official documentation.

After SDL is initiated, it will then grab the video device (in this case the LCD) and set up a surface to work with that should be full screen.

It also initiates the SDL_mixer library by opening up the audio device with some preconfigured settings (variables defined to set it for CD quality playback).

Playing Music

// Draw a white screen just to show we're running
SDL_Rect rect0 = {0, 0, screen_width, screen_height};
SDL_FillRect(screen, &rect0, 0xFFFFFF);
SDL_Flip(screen);

// Begin playing music
music = Mix_LoadMUS("FurElise.mp3");
Mix_PlayMusic(music, 0);
Mix_HookMusicFinished(musicDone);

This section of code will first draw a blank white rectangle that fills the screen and displays it with the SDL_Flip.

The next part involves loading the mp3 file using Mix_LoadMUS and playing it with Mix_PlayMusic and setting a function to run when the mp3 finishes playing. That function is musicDone.

Mix_Chunk *phaser = NULL;
Mix_Music *music = NULL;

int phaserChannel = -1;

void musicDone() 
{
  Mix_HaltMusic();
  Mix_FreeMusic(music);
  music = NULL;
}

musicDone just cleans up after the program when the mp3 has finished playing.

SDL input loop

// Wait for user to interrupt program to end it
printf("Waiting for input. Interrupt to exit\n"); 
memset(&input_event, 0, sizeof(input_event));
while (running == 0)
{
  if (SDL_PollEvent(&input_event))
  {
    if (input_event.type == SDL_QUIT)
    {
      running = 1;
    }
  }
}

This section of code will continuously check for input events. If the event is an SDL_Quit call it will exit the program.

Exiting

musicDone();
Mix_CloseAudio();
SDL_Quit();
return 0;

This section just does some basic clean up and exits the program.

Compiling audio

First make sure that your kernel has the libraries libSDL, SDL_mixer, SDL_gfx and Alsa enabled.

Secondly, make sure your vendor staging install is complete (ADSP-BF548 EZ-KIT Quick Start: Compiling uClinux).

root:/> make vendor_staging_install

Run the following compile command in the same directory as the source code:

root:/> bfin-linux-uclibc-gcc -O2 \
$(~/Blackfin/blackfin-linux-dist/staging/usr/bin/sdl-config --cflags) \
$(~/Blackfin/blackfin-linux-dist/staging/usr/bin/sdl-config --libs) \ 
-lSDL_mixer -lSDL_gfx -lasound \ 
audio.c -o audio

What this compile command is doing is it is calling the uclibc cross compiler that is set up from the Blackfin toolchains to compile our application.

The calls to sdl-config are a special case for SDL because SDL places its header & library files in non-root locations so this will load them properly.

The parameters prefixed with -l are to indicate we need to load that library, so in this case the libraries SDL_mixer, SDL_gfx, and alsa are loaded. Without these, our program would not have access to the required functions (audio and graphics).

The final parameters match up to standard gcc compiling, “audio.c” is the source file while ”-o audio” indicates the output file is “audio”.

A standard make file is accompanies this demo and you can run that by simply calling

root:/> make audio

Further Reading

SDL_mixer is documented on the main SDL site http://www.libsdl.org/projects/SDL_mixer/docs/index.html and you can read more up on it there.

Alsa Utils is expected to be installed for the aplay command to work. You can actually record and play audio using aplay and arecord from alsa utils if you want to have a simpler time. To enable alsa utils when compiling uClinux enable Blackfin app programs > ALSA utils.

You can read up on the alsa library at its official documentation http://www.alsa-project.org

If you cannot find your audio device on the BF548 with a fresh copy of the uClinux2011R1-RC3 release that is because in that release the audio drivers had a slight error. You can fix this by downloading the latest kernel updates from the Blackfin uClinux git repository or getting the upgrade.patch file from the custom Ubuntu ISO in the “Blackfin/blackfin-linux-dist/linux-2.6.x” folder and applying it to your distribution to run the updates automatically (patch -p1 < upgrade.patch).

To check that the alsa audio driver is running, check the dev directory for /dev/dsp. If it exists, the driver should be ready to go. If not, you'll need to determine whether the audio drivers are enabled or not.

root:/> ls /dev/dsp