import from git: added extra usage explanation, added -s command-line option to set multisample level, added a fallback to AV::start() to try multisample level of 1 if attempting samples>1 fails, fixed audio bug for combining multiple streams getting staticky, added documentation for joint and sound Lua member methods

git-svn-id: svn://anubis/anaglym/trunk@300 99a6e188-d820-4881-8870-2d33a10e2619
This commit is contained in:
Josh Holtrop 2010-08-06 01:56:27 +00:00
parent 82254ff82c
commit 8dbcc0b043
4 changed files with 210 additions and 9 deletions

47
AV.cc
View File

@ -17,6 +17,15 @@ using namespace std;
#define CALLBACK_SAMPLES 4096 #define CALLBACK_SAMPLES 4096
#define CHANNELS 2 #define CHANNELS 2
#define BYTES_PER_SAMPLE 2 #define BYTES_PER_SAMPLE 2
#if AV_SOUND_FORMAT == AUDIO_S16SYS
# define SAMPLE_MIN SHRT_MIN
# define SAMPLE_MAX SHRT_MAX
#elif AV_SOUND_FORMAT == AUDIO_U16SYS
# define SAMPLE_MIN 0
# define SAMPLE_MAX USHRT_MAX
#else
# error Unknown AV_SOUND_FORMAT
#endif
void AV_sound_callback(void * userdata, Uint8 * stream, int len) void AV_sound_callback(void * userdata, Uint8 * stream, int len)
{ {
@ -56,12 +65,13 @@ AV::AV()
desired.samples = CALLBACK_SAMPLES; desired.samples = CALLBACK_SAMPLES;
desired.callback = AV_sound_callback; desired.callback = AV_sound_callback;
desired.userdata = this; desired.userdata = this;
desired.silence = 0;
if (SDL_OpenAudio(&desired, NULL) < 0) if (SDL_OpenAudio(&desired, NULL) < 0)
{ {
cerr << "SDL_OpenAudio() error." << endl; cerr << "SDL_OpenAudio() error." << endl;
exit(3); exit(3);
} }
m_sound_buffer = new int16_t[CALLBACK_SAMPLES * CHANNELS]; m_sound_buffer = new sample_t[CALLBACK_SAMPLES * CHANNELS];
m_active_sounds_mutex = SDL_CreateMutex(); m_active_sounds_mutex = SDL_CreateMutex();
} }
@ -76,7 +86,7 @@ AV::~AV()
delete[] m_sound_buffer; delete[] m_sound_buffer;
} }
void AV::start(int width, int height, bool fullscreen, bool grab_input, bool AV::start(int width, int height, bool fullscreen, bool grab_input,
int samples) int samples)
{ {
if (m_surface == NULL) if (m_surface == NULL)
@ -96,6 +106,31 @@ void AV::start(int width, int height, bool fullscreen, bool grab_input,
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, samples); SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, samples);
} }
m_surface = SDL_SetVideoMode(width, height, 32, flags); m_surface = SDL_SetVideoMode(width, height, 32, flags);
if (m_surface == NULL)
{
if (samples > 1)
{
cerr << "Error setting video mode, trying again without multisampling" << endl;
/* failed to set SDL video mode with multisampling, try without */
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 0);
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 0);
m_surface = SDL_SetVideoMode(width, height, 32, flags);
if (m_surface != NULL)
{
cerr << "Successfully set video mode without multisampling" << endl;
}
}
}
if (m_surface == NULL)
{
cerr << "Error setting SDL video mode." << endl;
cerr << "Parameters:" << endl;
cerr << " width = " << width << endl;
cerr << " height = " << height << endl;
cerr << " fullscreen = " << fullscreen << endl;
cerr << " input grab = " << grab_input << endl;
return false;
}
if (grab_input) if (grab_input)
{ {
SDL_ShowCursor(SDL_DISABLE); SDL_ShowCursor(SDL_DISABLE);
@ -119,6 +154,7 @@ void AV::start(int width, int height, bool fullscreen, bool grab_input,
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
} }
return true;
} }
void AV::stop() void AV::stop()
@ -161,7 +197,7 @@ void AV::stopSound(AV::Sound * s)
void AV::playCallback(Uint8 * stream, int len) void AV::playCallback(Uint8 * stream, int len)
{ {
uint16_t * stream16 = (uint16_t *) stream; sample_t * stream16 = (sample_t *) stream;
memset(stream, 0, len); memset(stream, 0, len);
SDL_mutexP(m_active_sounds_mutex); SDL_mutexP(m_active_sounds_mutex);
#ifdef DEBUG #ifdef DEBUG
@ -188,7 +224,7 @@ void AV::playCallback(Uint8 * stream, int len)
i++) i++)
{ {
int sample_val = stream16[i] + (int)(volume * m_sound_buffer[i]); int sample_val = stream16[i] + (int)(volume * m_sound_buffer[i]);
stream16[i] = min(SHRT_MAX, max(SHRT_MIN, sample_val)); stream16[i] = min(SAMPLE_MAX, max(SAMPLE_MIN, sample_val));
} }
} }
int sz = m_active_sounds.size(); int sz = m_active_sounds.size();
@ -237,10 +273,9 @@ bool AV::Sound::load(FileLoader & fileLoader, const FileLoader::Path & path)
} }
else else
{ {
SDL_FreeRW(m_rwops);
m_rwops = NULL;
cerr << "Error loading sound " << path.toString() << ": " cerr << "Error loading sound " << path.toString() << ": "
<< Sound_GetError() << endl; << Sound_GetError() << endl;
m_rwops = NULL;
} }
} }
return false; return false;

13
AV.h
View File

@ -11,9 +11,18 @@
#include "FileLoader/FileLoader.h" #include "FileLoader/FileLoader.h"
#include "refptr/refptr.h" #include "refptr/refptr.h"
#define AV_SOUND_FORMAT AUDIO_S16SYS
class AV class AV
{ {
public: public:
#if AV_SOUND_FORMAT == AUDIO_S16SYS
typedef int16_t sample_t;
#elif AV_SOUND_FORMAT == AUDIO_U16SYS
typedef uint16_t sample_t;
#else
# error Unknown AV_SOUND_FORMAT
#endif
class Sound class Sound
{ {
public: public:
@ -41,7 +50,7 @@ class AV
AV(); AV();
~AV(); ~AV();
void start(int width = 0, int height = 0, bool start(int width = 0, int height = 0,
bool fullscreen = true, bool grab_input = true, bool fullscreen = true, bool grab_input = true,
int samples = 4); int samples = 4);
void stop(); void stop();
@ -87,7 +96,7 @@ class AV
#endif #endif
std::set< Sound * > m_active_sounds; std::set< Sound * > m_active_sounds;
SDL_mutex * m_active_sounds_mutex; SDL_mutex * m_active_sounds_mutex;
int16_t * m_sound_buffer; sample_t * m_sound_buffer;
}; };
#endif #endif

View File

@ -13,6 +13,12 @@ static void usage();
static void usage() static void usage()
{ {
cerr << "Usage: anaglym [options] program.lua[c]" << endl; cerr << "Usage: anaglym [options] program.lua[c]" << endl;
cerr << "Options:" << endl;
cerr << " -w<width> : set window width" << endl;
cerr << " -h<height> : set window height" << endl;
cerr << " -f : do not fullscreen" << endl;
cerr << " -g : do not grab mouse input" << endl;
cerr << " -s<samples>: set multisample level (default 4)" << endl;
exit(42); exit(42);
} }
@ -22,6 +28,7 @@ int main(int argc, char * argv[])
bool grab_input = true; bool grab_input = true;
int width = 0; int width = 0;
int height = 0; int height = 0;
int samples = 4;
const char * program = NULL; const char * program = NULL;
for (int i = 1; i < argc; i++) for (int i = 1; i < argc; i++)
{ {
@ -55,6 +62,10 @@ int main(int argc, char * argv[])
{ {
height = atoi((strlen(argv[i]) == 2) ? argv[++i] : argv[i] + 2); height = atoi((strlen(argv[i]) == 2) ? argv[++i] : argv[i] + 2);
} }
else if (!strncmp(argv[i], "-s", 2))
{
samples = atoi((strlen(argv[i]) == 2) ? argv[++i] : argv[i] + 2);
}
else else
{ {
cerr << "Warning: Unrecognized option '" << argv[i]+1 cerr << "Warning: Unrecognized option '" << argv[i]+1
@ -72,7 +83,11 @@ int main(int argc, char * argv[])
srand(time(NULL)); srand(time(NULL));
AV av; AV av;
av.start(width, height, fullscreen, grab_input); if (!av.start(width, height, fullscreen, grab_input, samples))
{
cerr << "anaglym: exiting." << endl;
return -1;
}
dInitODE(); dInitODE();
g_engine = new Engine(argv[0], av); g_engine = new Engine(argv[0], av);

View File

@ -34,6 +34,8 @@ The library functions are documented below.
<ul> <ul>
<li><a href="#object_creation">object creation functions</a></li> <li><a href="#object_creation">object creation functions</a></li>
<li><a href="#object">object member methods</a></li> <li><a href="#object">object member methods</a></li>
<li><a href="#joint">joint member methods</a></li>
<li><a href="#sound">sound member methods</a></li>
</ul> </ul>
</li> </li>
<li><a href="#std"><tt>std</tt> library</a></li> <li><a href="#std"><tt>std</tt> library</a></li>
@ -58,6 +60,7 @@ The library functions are documented below.
<li><tt>-h height</tt> - specify the height in pixels of the window</li> <li><tt>-h height</tt> - specify the height in pixels of the window</li>
<li><tt>-f</tt> - do not fullscreen window</li> <li><tt>-f</tt> - do not fullscreen window</li>
<li><tt>-g</tt> - do not grab mouse input</li> <li><tt>-g</tt> - do not grab mouse input</li>
<li><tt>-s samples</tt> - set multisample level (default 4)</li>
</ul> </ul>
</p> </p>
@ -476,6 +479,16 @@ You can instantiate a reference object into a normal object by calling
the <a href="#object_clone">clone()</a> method on the object. the <a href="#object_clone">clone()</a> method on the object.
</p> </p>
<a name="ag_loadSound" />
<h3>loadSound</h3>
<p><tt>sound = ag.loadSound(sound_name)</tt></p>
<p>
This routine loads a <a href="#sound">sound</a> object from file
<tt>sound_name</tt> and returns a Lua reference to the loaded sound.
The <tt>sound_name</tt> should contain the file extension,
since multiple formats are supported (.wav, .mp3, etc...).
</p>
<a name="ag_loadTexture" /> <a name="ag_loadTexture" />
<h3>loadTexture</h3> <h3>loadTexture</h3>
<p><tt>texture = ag.loadTexture(texture_name)</tt></p> <p><tt>texture = ag.loadTexture(texture_name)</tt></p>
@ -925,6 +938,135 @@ Newly created objects are visible by default.
<hr /> <hr />
<a name="joint" />
<h2>Joint member methods</h2>
<a name="joint_setAMotorAxis" />
<h3>setAMotorAxis</h3>
<p><tt>joint:setAMotorAxis(anum, rel, x, y, z)</tt></p>
<p>
Set axis parameters of the AMotor joint.
See <a href="#ag_createAMotor">ag.createAMotor()</a> for more information.
</p>
<a name="joint_setNumAxes" />
<h3>setAMotorNumAxes</h3>
<p><tt>joint:setAMotorNumAxes(num)</tt></p>
<p>
Set the number of axes of the AMotor joint.
See <a href="#ag_createAMotor">ag.createAMotor()</a> for more information.
</p>
<a name="joint_setAMotorAngle" />
<h3>setAMotorAngle</h3>
<p><tt>joint:setAMotorAngle(anum, angle)</tt></p>
<p>
Set the angle of the specified of axis of the AMotor joint.
See <a href="#ag_createAMotor">ag.createAMotor()</a> for more information.
</p>
<a name="joint_setAMotorLoStop" />
<h3>setAMotorLoStop</h3>
<p><tt>joint:setAMotorLoStop(anum, lostop)</tt></p>
<p>
Set the low stop angle of the specified axis of the AMotor joint.
See <a href="#ag_createAMotor">ag.createAMotor()</a> for more information.
</p>
<a name="joint_setAMotorHiStop" />
<h3>setAMotorHiStop</h3>
<p><tt>joint:setAMotorHiStop(anum, histop)</tt></p>
<p>
Set the high stop angle of the specified axis of the AMotor joint.
See <a href="#ag_createAMotor">ag.createAMotor()</a> for more information.
</p>
<a name="joint_setAMotorVel" />
<h3>setAMotorVel</h3>
<p><tt>joint:setAMotorVel(vel)</tt></p>
<p>
Set the velocity of the AMotor joint.
See <a href="#ag_createAMotor">ag.createAMotor()</a> for more information.
</p>
<a name="joint_setAMotorFMax" />
<h3>setAMotorFMax</h3>
<p><tt>joint:setAMotorFMax(vel)</tt></p>
<p>
Set the maximum force that the AMotor joint will apply to
maintain its constraints.
See <a href="#ag_createAMotor">ag.createAMotor()</a> for more information.
</p>
<a name="joint_setAMotorBounce" />
<h3>setAMotorBounce</h3>
<p><tt>joint:setAMotorBounce(bounce)</tt></p>
<p>
Set the bounciness of the AMotor joint.
See <a href="#ag_createAMotor">ag.createAMotor()</a> for more information.
</p>
<hr />
<a name="sound" />
<h2>Sound member methods</h2>
<a name="sound_play" />
<h3>play</h3>
<p><tt>snd:play()</tt></p>
<p>
Begins playing the <tt>snd</tt> sound at the beginning.
</p>
<a name="sound_resume" />
<h3>resume</h3>
<p><tt>snd:resume()</tt></p>
<p>
Begins playing the <tt>snd</tt> sound where it stopped after calling
<a href="#sound_stop">stop()</a>.
</p>
<a name="sound_stop" />
<h3>stop</h3>
<p><tt>snd:stop()</tt></p>
<p>
Stops playing the <tt>snd</tt> sound at its current position.
</p>
<a name="sound_loop" />
<h3>loop</h3>
<p><tt>snd:loop(count)</tt></p>
<p>
Begins playing the <tt>snd</tt> sound at the beginning and sets the loop
count to <tt>count</tt>. <tt>snd:loop(1)</tt> is equivalent to
<tt>snd:play()</tt>.
</p>
<a name="sound_loopForever" />
<h3>loopForever</h3>
<p><tt>snd:loopForever()</tt></p>
<p>
Begins playing the <tt>snd</tt> sound at the beginning and sets the loop
count to infinity. This routine is good for background music.
</p>
<a name="sound_getVolume" />
<h3>getVolume</h3>
<p><tt>snd:getVolume()</tt></p>
<p>
Get the volume for the <tt>snd</tt> sound.
</p>
<a name="sound_setVolume" />
<h3>setVolume</h3>
<p><tt>snd:setVolume(vol)</tt></p>
<p>
Set the volume for the <tt>snd</tt> sound to <tt>snd</tt>.
<tt>snd</tt> should be between <tt>0.0</tt> and <tt>1.0</tt>.
</p>
<hr />
<a name="std" /> <a name="std" />
<h2><tt>std</tt> library</h2> <h2><tt>std</tt> library</h2>