|
|
|
// NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
|
|
|
|
// Copyright (C) 2010 Winch Gate Property Limited
|
|
|
|
//
|
|
|
|
// This program is free software: you can redistribute it and/or modify
|
|
|
|
// it under the terms of the GNU Affero General Public License as
|
|
|
|
// published by the Free Software Foundation, either version 3 of the
|
|
|
|
// License, or (at your option) any later version.
|
|
|
|
//
|
|
|
|
// This program is distributed in the hope that it will be useful,
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
// GNU Affero General Public License for more details.
|
|
|
|
//
|
|
|
|
// You should have received a copy of the GNU Affero General Public License
|
|
|
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This sample shows how to initialize the audio mixer (UAudioMixer),
|
|
|
|
* how to create a source (USource), and how to move the listener
|
|
|
|
* (UListener).
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
#include "nel/misc/debug.h"
|
|
|
|
#include "nel/misc/time_nl.h"
|
|
|
|
#include "nel/misc/path.h"
|
|
|
|
#include "nel/misc/vector.h"
|
|
|
|
using namespace NLMISC;
|
|
|
|
|
|
|
|
#include "nel/sound/u_audio_mixer.h"
|
|
|
|
#include "nel/sound/u_listener.h"
|
|
|
|
using namespace NLSOUND;
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
#ifndef NL_SOUND_DATA
|
|
|
|
#define NL_SOUND_DATA "."
|
|
|
|
#endif // NL_SOUND_DATA
|
|
|
|
|
|
|
|
// Pointer to the audio mixer object
|
|
|
|
UAudioMixer *AudioMixer = NULL;
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Initialization
|
|
|
|
*/
|
|
|
|
void Init()
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
|
|
|
|
CPath::addSearchPath(NL_SOUND_DATA"/data", true, false);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 1. Create the audio mixer object and init it.
|
|
|
|
* If the sound driver cannot be loaded, an exception is thrown.
|
|
|
|
*/
|
|
|
|
AudioMixer = UAudioMixer::createAudioMixer();
|
|
|
|
|
|
|
|
// Set the sample path before init, this allow the mixer to build the sample banks
|
|
|
|
AudioMixer->setSamplePath("data/samplebank");
|
|
|
|
// Packed sheet option, this mean we want packed sheet generated in 'data' folder
|
|
|
|
AudioMixer->setPackedSheetOption("data", true);
|
|
|
|
|
|
|
|
printf("Select NLSOUND Driver:\n");
|
|
|
|
printf(" [1] FMod\n");
|
|
|
|
printf(" [2] OpenAl\n");
|
|
|
|
printf(" [3] DSound\n");
|
|
|
|
printf(" [4] XAudio2\n");
|
|
|
|
printf("> ");
|
|
|
|
int selection = getchar();
|
|
|
|
printf("\n");
|
|
|
|
|
|
|
|
// init with 32 tracks, EAX enabled, no ADPCM, and activate automatic sample bank loading
|
|
|
|
AudioMixer->init(32, true, false, NULL, true, (UAudioMixer::TDriver)(selection - '0')/*UAudioMixer::DriverFMod*/);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 2. Initialize listener's position and orientation (in NeL coordinate system).
|
|
|
|
*/
|
|
|
|
CVector initpos ( 0.0f, 0.0f, 0.0f );
|
|
|
|
CVector frontvec( 0.0f, 1.0f, 0.0f );
|
|
|
|
CVector upvec( 0.0f, 0.0f, 1.0f );
|
|
|
|
AudioMixer->getListener()->setPos( initpos );
|
|
|
|
AudioMixer->getListener()->setOrientation( frontvec, upvec );
|
|
|
|
|
|
|
|
}
|
|
|
|
catch( Exception& e )
|
|
|
|
{
|
|
|
|
nlerror( "Error: %s", e.what() );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Adding a source
|
|
|
|
*/
|
|
|
|
USource *OnAddSource( const char *name, float x, float y, float z )
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Create a source with sound 'name', and set some of its initial properties, if successful
|
|
|
|
*/
|
|
|
|
USource *source = AudioMixer->createSource( CStringMapper::map(name) );
|
|
|
|
if ( source != NULL )
|
|
|
|
{
|
|
|
|
source->setPos( CVector(x,y,z) );
|
|
|
|
|
|
|
|
/* The initial gain, pitch and looping state are stored
|
|
|
|
* in the "source sounds file".
|
|
|
|
*/
|
|
|
|
source->setLooping(true);
|
|
|
|
source->play(); // start playing immediately
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
nlwarning( "Sound '%s' not found", name );
|
|
|
|
}
|
|
|
|
return source;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* When moving the listener, wait for a short delay
|
|
|
|
*/
|
|
|
|
void OnMove( const CVector& listenerpos )
|
|
|
|
{
|
|
|
|
// Move forward
|
|
|
|
AudioMixer->getListener()->setPos( listenerpos );
|
|
|
|
|
|
|
|
// Wait 20 ms
|
|
|
|
TTime time = CTime::getLocalTime();
|
|
|
|
while ( CTime::getLocalTime() < time+20 );
|
|
|
|
|
|
|
|
/* If we used spawned sources or "envsounds" or if we had
|
|
|
|
* a large number of sources, we should call:
|
|
|
|
* AudioMixer->update();
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* main
|
|
|
|
*
|
|
|
|
* Note: The NeL vector coordinate system is described as follows:
|
|
|
|
* \verbatim
|
|
|
|
* (top)
|
|
|
|
* z
|
|
|
|
* | y (front)
|
|
|
|
* | /
|
|
|
|
* -----x (right)
|
|
|
|
* \endverbatim
|
|
|
|
*/
|
|
|
|
int main()
|
|
|
|
{
|
|
|
|
CApplicationContext *appContext = new CApplicationContext(); // crash at end if on stack ...
|
|
|
|
|
|
|
|
// Initialization
|
|
|
|
Init();
|
|
|
|
|
|
|
|
// First step: we create two sources
|
|
|
|
printf( "Press ENTER to start playing the two sources\n" );
|
|
|
|
printf( "One is 20 meters ahead, on the right\n" );
|
|
|
|
printf( "The other is 5 meters ahead, on the left\n" );
|
|
|
|
getchar();
|
|
|
|
USource *src1 = OnAddSource( "beep", 1.0f, 20.0f, 0.0f ); // Beep on the right, 20 meters ahead
|
|
|
|
USource *src2 = OnAddSource( "tuut", -2.0f, 5.0f, 0.0f ); // Tuut on the left, 5 meters ahead
|
|
|
|
|
|
|
|
// Second step: we will move the listener ahead
|
|
|
|
printf( "Press ENTER again to start moving the listener\n" );
|
|
|
|
getchar();
|
|
|
|
|
|
|
|
// Listener orientation is constant in this example (see initialization)
|
|
|
|
|
|
|
|
// Move forward, then backward, twice
|
|
|
|
CVector listenervel;
|
|
|
|
CVector listenerpos ( 0.0f, 0.0f, 0.0f );
|
|
|
|
for ( uint i=0; i!=2; i++ )
|
|
|
|
{
|
|
|
|
printf( "%u of 2\n", i+1 );
|
|
|
|
|
|
|
|
// Forward velocity
|
|
|
|
listenervel.set( 0.0f, 0.5f, 0.0f );
|
|
|
|
AudioMixer->getListener()->setVelocity( listenervel );
|
|
|
|
|
|
|
|
// Move forward: set position every frame
|
|
|
|
printf( "Moving forward, going past the sources...\n" );
|
|
|
|
for ( listenerpos.y=0.0f; listenerpos.y<30.0f; listenerpos.y+=0.1f )
|
|
|
|
{
|
|
|
|
OnMove( listenerpos );
|
|
|
|
AudioMixer->update();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Backward velocity
|
|
|
|
listenervel.set( 0.0f, -0.5f, 0.0f );
|
|
|
|
AudioMixer->getListener()->setVelocity( listenervel );
|
|
|
|
|
|
|
|
// Move backward: set position every frame
|
|
|
|
printf( "Moving backward, going back to the start position...\n" );
|
|
|
|
for ( listenerpos.y=30.0f; listenerpos.y>0.0f; listenerpos.y-=0.1f )
|
|
|
|
{
|
|
|
|
OnMove( listenerpos );
|
|
|
|
AudioMixer->update();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Finalization
|
|
|
|
printf( "Press ENTER again to exit\n" );
|
|
|
|
getchar();
|
|
|
|
|
|
|
|
delete src1; delete src2;
|
|
|
|
delete AudioMixer;
|
|
|
|
|
|
|
|
delete appContext;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|