Reacting to an audio event: loud noise¶
Principle¶
If you want to have a sound-based reaction, you need to retrieve the sound received by NAO’s microphones. To do so, you have to implement a particular kind of module: it must inherit from ALSoundExtractor.
ALSoundExtractor implements some key methods to help you process sound:
- process. This method has to be redefined by the user. It is automatically called each time a sound buffer is sent, and its arguments correspond to the buffer information. You do not have to worry about any optimization, since it will automatically be called in local mode if possible.
- startDetection. Once this method has been called, sound buffers will be sent regularly with the desired preferences to the process method.
- stopDetection. This method stops the sound buffer sending.
The preferences for the kind of buffer to be sent are set through a proxy to ALAudioDevice.
Warning
Make sure that your sound processing function has an execution time either much smaller than the time between two sound buffers, or is thread-safe.
Example: ALSoundBasedReaction module¶
This section implements an example module. It will make NAO say “Hello there” each time a sufficiently loud noise is detected.
The whole example is available here:
soundbasedreaction.zip
Header:¶
/**
* @author Gwennael Gate
* Copyright (c) Aldebaran Robotics 2010
*/
#ifndef SOUNDBASEDREACTION_H
#define SOUNDBASEDREACTION_H
#ifdef SOUNDBASEDREACTION_IS_REMOTE
#include <qi/application.hpp>
#include <boost/function.hpp>
#include <boost/bind.hpp>
#endif
#include <boost/shared_ptr.hpp>
#include <alcommon/almodule.h>
#include <string>
#include <alproxies/altexttospeechproxy.h>
#include "alaudio/alsoundextractor.h"
using namespace AL;
class ALSoundBasedReaction : public ALSoundExtractor
{
public:
ALSoundBasedReaction(boost::shared_ptr<ALBroker> broker,
const std::string & name);
virtual ~ALSoundBasedReaction();
void init();
void process(const int & nbOfChannels,
const int & nbrOfSamplesByChannel,
const AL_SOUND_FORMAT * buffer,
const ALValue & timeStamp);
private:
ALTextToSpeechProxy fProxyToTextToSpeech;
};
#endif // SOUNDBASEDREACTION_H
Source file:¶
/**
* @author Gwennael Gate
* Copyright (c) Aldebaran Robotics 2010
*/
#include "alsoundbasedreaction.h"
#include <alvalue/alvalue.h>
#include <alcommon/alproxy.h>
#include <alcommon/albroker.h>
#include <iostream>
#include <fstream>
ALSoundBasedReaction::ALSoundBasedReaction(boost::shared_ptr<ALBroker> broker,
const std::string& name) :
ALSoundExtractor(broker, name)
{
/// This line will display a description of this module on the web page of the robot
setModuleDescription("This module launch a texttospeech command when a "
"sudden and significative noise is heard.");
}
void ALSoundBasedReaction::init()
{
/// Setting up the appropriate language
fProxyToTextToSpeech.setLanguage("English");
audioDevice->callVoid("setClientPreferences",
getName(), //Name of this module
16000, //16000 Hz requested
(int)FRONTCHANNEL, //Front Channels requested
0 //Deinterleaving is not needed here
);
#ifdef SOUNDBASEDREACTION_IS_REMOTE
qi::Application::atStop(boost::bind(&ALSoundBasedReaction::stopDetection, this));
#endif
startDetection();
}
ALSoundBasedReaction::~ALSoundBasedReaction()
{
stopDetection();
}
/// This function will be automatically called by the module ALAudioDevice
/// every 170ms with the appropriate audio buffer (front channel at 16000Hz)
void ALSoundBasedReaction::process(const int & nbOfChannels,
const int & nbrOfSamplesByChannel,
const AL_SOUND_FORMAT * buffer,
const ALValue & timeStamp)
{
/// Compute the maximum value of the front microphone signal.
int maxValueFront = 0;
for(int i = 0 ; i < nbrOfSamplesByChannel ; i++)
{
if(buffer[i] > maxValueFront)
{
maxValueFront = buffer[i];
}
}
/// Print it in the console
/// (Naoqi needs to be launched in console mode to see the log)
std::cout << "maxvalue : " << maxValueFront << std::endl;
/// Launch a texttospeech command when it is appropriate
if(maxValueFront > 10000)
{
fProxyToTextToSpeech.say("Hello there!");
}
}
Main:¶
/**
* @author Gwennael Gate
* Copyright (c) Aldebaran Robotics 2010
*/
#include <signal.h>
#include <boost/shared_ptr.hpp>
#include <alcommon/albroker.h>
#include <alcommon/almodule.h>
#include <alcommon/albrokermanager.h>
#include <alcommon/altoolsmain.h>
#include "alsoundbasedreaction.h"
#ifdef SOUNDBASEDREACTION_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);
AL::ALModule::createModule<ALSoundBasedReaction>(pBroker, "ALSoundBasedReaction");
return 0;
}
ALCALL int _closeModule()
{
return 0;
}
}
#ifdef SOUNDBASEDREACTION_IS_REMOTE
int main(int argc, char *argv[])
{
// pointer to createModule
TMainType sig;
sig = &_createModule;
// call main
ALTools::mainFunction("alsoundbasedreaction",argc, argv,sig);
}
#endif
CMakeLists.txt:¶
# Copyright (C) 2010 Aldebaran Robotics
cmake_minimum_required(VERSION 2.6.4 FATAL_ERROR)
project(soundbasedreaction)
find_package(qibuild)
option(SOUNDBASEDREACTION_IS_REMOTE
"module is compiled as a remote module (ON or OFF)"
ON)
set(_srcs
main.cpp
alsoundbasedreaction.h
alsoundbasedreaction.cpp
)
if(SOUNDBASEDREACTION_IS_REMOTE)
add_definitions(" -DSOUNDBASEDREACTION_IS_REMOTE ")
qi_create_bin(soundbasedreaction ${_srcs})
else()
qi_create_lib(soundbasedreaction SHARED ${_srcs} SUBFOLDER naoqi)
endif()
qi_use_lib(soundbasedreaction ALCOMMON ALPROXIES ALAUDIO)