Sound playback¶
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¶
Header: 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¶
/**
* @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¶
/**
* @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¶
# 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)