# SoftBank Robotics documentation What's new in NAOqi 2.8?

# Sound playback

<< return to C++ examples

## Overview

This example module ALSoundPlayback sends sound to NAO’s loudspeakers.

This is a local module, it must be cross-compiled and sent to the robot.

## Downloads

### Whole module

`soundplayback.zip`

### Header: alsoundplayback.h

`alsoundplayback.h`

    /**
    * @author Vincent Meserette & Gwennael Gate
    * Copyright (c) Aldebaran Robotics 2010
    */

    #ifndef SOUNDPLAYBACK_H
    #define SOUNDPLAYBACK_H

    #include <boost/shared_ptr.hpp>
    #include <alcommon/almodule.h>

    namespace AL
    {
      class ALBroker;
    }

    class ALSoundPlayback : public AL::ALModule
    {
      struct wavheader
      {
        char chunkID[4];
        long chunkSize;
        char format[4];
        char subchunk1ID[4];
        long subchunk1Size;
        unsigned short audioFormat;
        unsigned short nbOfChannels;
        unsigned long sampleRate;
        unsigned long byteRate;
        unsigned short blockAlign;
        unsigned short bitsPerSample;
        char subchunk2ID[4];
        long subchunk2Size;
      };

    public:
      ALSoundPlayback(boost::shared_ptr<AL::ALBroker> pBroker, const std::string& pName);

      virtual ~ALSoundPlayback();

      void playWavFile(const std::string &pFileName);

    private:

      boost::shared_ptr <AL::ALProxy> audioDeviceProxy;
    };
    #endif

### Source: alsoundplayback.cpp

`alsoundplayback.cpp`

    /**
    * @author Vincent Meserette & Gwennael Gate
    * Copyright (c) Aldebaran Robotics 2010
    */

    #include "alsoundplayback.h"

    #include <iostream>
    #include <alcommon/alproxy.h>
    #include <boost/shared_ptr.hpp>
    #include <alcommon/albroker.h>
    #include <alcommon/almodule.h>

    using namespace AL;

    ALSoundPlayback::ALSoundPlayback(boost::shared_ptr<ALBroker> pBroker, const std::string& pName ): ALModule(pBroker, pName )
    {
      setModuleDescription("An example of how to send sound onto the nao's loudspeakers.");

      /// Define callable methods with there description
      functionName("playWavFile",
                   getName(),
                   "sends the content of a wav file of a remote desktop onto the nao's loudspeakers ");

      addParam("pFileName", "Name of twav file to play");
      BIND_METHOD(ALSoundPlayback::playWavFile);

      audioDeviceProxy = getParentBroker()->getProxy("ALAudioDevice");
    }

    ALSoundPlayback::~ALSoundPlayback()
    {

    }

    void ALSoundPlayback::playWavFile(const std::string &pFileName)
    {
      /// Maximum buffer size that ALAudioDevice can send
      const int outputBufferSize = 16384;
      /// Number of output channels on Nao
      const int numberOfOutputChannels = 2;
      FILE *fInputWavFile;

      /// Opening of the input file
      if((fInputWavFile = fopen(pFileName.c_str(), "rb" )) == NULL)
      {
        throw AL::ALError("ALSoundProcessing",
                          "playWavFile()",
                          "Failed to open input sound file.");
      }

      /// Reading of the wav header
      wavheader * wavHeader = new wavheader;
      fread(wavHeader,1,44,fInputWavFile);

      unsigned short nbOfChannels = wavHeader->nbOfChannels;
      unsigned long sampleRate = wavHeader->sampleRate;
      unsigned short bitsPerSample = wavHeader->bitsPerSample;

      try
      {
        /// Set output sample rate of audiodevice
        audioDeviceProxy->callVoid("setParameter",
                                   std::string("outputSampleRate"),
                                   (int)sampleRate);
      }
      catch(ALError &e)
      {
        throw AL::ALError("ALSoundProcessing",
                          "playWavFile()",
                          e.getDescription());
      }

      /// Go to the beginning of the audio data
      fseek(fInputWavFile, 44, SEEK_SET);

      /// Reading of the audio data
      /// Buffer to store the data contained in the wav file
      short * fInputAudioData = new short[outputBufferSize*nbOfChannels];
      /// Buffer to construct stereo audio data
      short * fStereoAudioData = new short[outputBufferSize*numberOfOutputChannels];

      /// ALValue where to store the stereo audio data to send
      ALValue pDataBin;
      while(!feof(fInputWavFile))
      {
        /// Read samples from file
        int fNbOfInputSamples = fread(fInputAudioData,
                                      bitsPerSample/8*nbOfChannels,
                                      outputBufferSize,
                                      fInputWavFile);

        if(nbOfChannels ==1)
        {
          /// Construction of stereo audio data in case the input file is mono
          int i=0;
          for(int j=0 ; j<fNbOfInputSamples ; j++)
          {
            fStereoAudioData[i] = fInputAudioData[j];
            fStereoAudioData[i+1] = fInputAudioData[j];
            i += numberOfOutputChannels;
          }

          /// Transform audio data to binary samples
          pDataBin.SetBinary(fStereoAudioData,
                             fNbOfInputSamples*sizeof(short)*numberOfOutputChannels);
        }
        else if(nbOfChannels == 2)
        {
          /// Transform audio data to binary samples
          pDataBin.SetBinary(fInputAudioData,
                             fNbOfInputSamples*sizeof(short)*numberOfOutputChannels);
        }
        else
        {
          throw AL::ALError("ALSoundProcessing",
                            "playWavFile()",
                            "The wav file should contain a mono or stereo signal.");
        }

        /// Send the stereo audio data to audiodevice module
        try
        {
          audioDeviceProxy->call<bool>("sendRemoteBufferToOutput",
                                       fNbOfInputSamples,
                                       pDataBin);
        }
        catch(AL::ALError &e)
        {
          throw AL::ALError("ALSoundProcessing","playWavFile()", e.getDescription());
        }
      }
      fclose(fInputWavFile);
    }

### Main: main.cpp

`main.cpp`

    /**
     * @author Vincent Meserette
     * Copyright (c) Aldebaran Robotics 2010 All Rights Reserved
    */

    #ifndef _WIN32
    #include <signal.h>
    #endif

    #include <boost/shared_ptr.hpp>
    #include <alcommon/albroker.h>
    #include <alcommon/almodule.h>
    #include <alcommon/albrokermanager.h>
    #include <alcommon/altoolsmain.h>
    #include "alsoundplayback.h"

    #ifdef SOUNDPLAYBACK_IS_REMOTE
    # define ALCALL
    #else
    # ifdef _WIN32
    #  define ALCALL __declspec(dllexport)
    # else
    #  define ALCALL
    # endif
    #endif

    extern "C"
    {

    ALCALL int _createModule(boost::shared_ptr<AL::ALBroker> pBroker)
    {
      // init broker with the main broker instance
      // from the parent executable
      AL::ALBrokerManager::setInstance(pBroker->fBrokerManager.lock());
      AL::ALBrokerManager::getInstance()->addBroker(pBroker);

      // create module instances
      AL::ALModule::createModule<ALSoundPlayback>(pBroker,"ALSoundPlayback");
      return 0;
    }

    ALCALL int _closeModule()
    {
      return 0;
    }

    } // extern "C"

    #ifdef SOUNDPLAYBACK_IS_REMOTE

    int main(int argc, char *argv[] )
    {
      // pointer on createModule
      TMainType sig;
      sig = &_createModule;

      // call main
      ALTools::mainFunction("alsoundplayback", argc, argv, sig);
    }

    #endif

### CMakeLists.txt

`CMakeLists.txt`

    # Copyright (C) 2010 Aldebaran Robotics

    cmake_minimum_required(VERSION 2.6.4 FATAL_ERROR)
    project(soundplayback)
    find_package(qibuild)

    option(SOUNDPLAYBACK_IS_REMOTE
      "module is compiled as a remote module (ON or OFF)"
      ON)

    set(_srcs
        main.cpp
        alsoundplayback.h
        alsoundplayback.cpp
    )

    if(SOUNDPLAYBACK_IS_REMOTE)
      add_definitions("-DSOUNDPLAYBACK_IS_REMOTE")
      qi_create_bin(soundplayback ${_srcs})
    else()
      qi_create_lib(soundplayback SHARED ${_srcs} SUBFOLDER naoqi)
    endif()

    qi_use_lib(soundplayback ALCOMMON ALPROXIES ALAUDIO)

Glossary Site map Index Support Contact Legal Notices