khanat-opennel-code/code/nel/samples/sound_sources/main.cpp

215 lines
5.8 KiB
C++

// 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;
}