mirror of
https://github.com/love2d/love.git
synced 2026-08-15 15:51:12 +02:00
Merged love.audio changes.
This commit is contained in:
@@ -1,48 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2006-2009 LOVE Development Team
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
**/
|
||||
|
||||
#ifndef LOVE_AUDIO_AUDIBLE_H
|
||||
#define LOVE_AUDIO_AUDIBLE_H
|
||||
|
||||
// LOVE
|
||||
#include <common/Object.h>
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace audio
|
||||
{
|
||||
class Source;
|
||||
|
||||
class Audible : public Object
|
||||
{
|
||||
public:
|
||||
|
||||
virtual ~Audible(){};
|
||||
virtual void play(Source * source) = 0;
|
||||
virtual void update(Source * source) = 0;
|
||||
virtual void stop(Source * source) = 0;
|
||||
virtual void rewind(Source * source) = 0;
|
||||
|
||||
}; // Audible
|
||||
|
||||
} // audio
|
||||
} // love
|
||||
|
||||
#endif // LOVE_AUDIO_AUDIBLE_H
|
||||
@@ -23,11 +23,14 @@
|
||||
|
||||
#include <common/Module.h>
|
||||
#include "Source.h"
|
||||
#include "Sound.h"
|
||||
#include "Music.h"
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace sound
|
||||
{
|
||||
class Decoder;
|
||||
class SoundData;
|
||||
}
|
||||
namespace audio
|
||||
{
|
||||
/**
|
||||
@@ -42,26 +45,9 @@ namespace audio
|
||||
**/
|
||||
virtual ~Audio(){};
|
||||
|
||||
/**
|
||||
* Creates a new Sound with the specified SoundData.
|
||||
* @param data The SoundData from which to create the sound.
|
||||
* @return A new Sound if successful, zero otherwise.
|
||||
**/
|
||||
virtual Sound * newSound(love::sound::SoundData * data) = 0;
|
||||
|
||||
/**
|
||||
* Creates a new Music (stream) using the specified SoundData.
|
||||
* @param decoder The object to use to decode the sound stream.
|
||||
**/
|
||||
virtual Music * newMusic(love::sound::Decoder * decoder) = 0;
|
||||
|
||||
/**
|
||||
* Creates a new Source.
|
||||
* @returns A new Source.
|
||||
**/
|
||||
virtual Source * newSource(Sound * sound) = 0;
|
||||
virtual Source * newSource(Music * music) = 0;
|
||||
|
||||
virtual Source * newSource(love::sound::Decoder * decoder) = 0;
|
||||
virtual Source * newSource(love::sound::SoundData * soundData) = 0;
|
||||
|
||||
/**
|
||||
* Gets the current number of simulatenous playing sources.
|
||||
* @return The current number of simulatenous playing sources.
|
||||
@@ -80,26 +66,6 @@ namespace audio
|
||||
**/
|
||||
virtual void play(Source * source) = 0;
|
||||
|
||||
/**
|
||||
* Plays one Sound on the specified Source. We need separate
|
||||
* Sound and Music play functions because Music must be cloned,
|
||||
* whereas Sound needs not be.
|
||||
*
|
||||
* @param sound The Sound to play.
|
||||
* @param source The Source on which to play the Sound.
|
||||
**/
|
||||
virtual void play(Sound * sound) = 0;
|
||||
|
||||
/**
|
||||
* Plays one Music on the specified Source. We need separate
|
||||
* Sound and Music play functions because Music must be cloned,
|
||||
* whereas Sound needs not be.
|
||||
*
|
||||
* @param music The Music to play.
|
||||
* @param source The Source on which to play the Music.
|
||||
**/
|
||||
virtual void play(Music * music) = 0;
|
||||
|
||||
/**
|
||||
* Stops playback on the specified source.
|
||||
* @param source The source on which to stop the playback.
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2006-2009 LOVE Development Team
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
**/
|
||||
|
||||
#ifndef LOVE_AUDIO_MUSIC_H
|
||||
#define LOVE_AUDIO_MUSIC_H
|
||||
|
||||
// LOVE
|
||||
#include "Audible.h"
|
||||
#include <sound/Decoder.h>
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace audio
|
||||
{
|
||||
/**
|
||||
* A Music object represents a stream of sound samples which are gradually
|
||||
* acquired somehow. Compare with Sounds, which have all the needed sound
|
||||
* samples pre-decoded.
|
||||
*
|
||||
* Typically, you would want to use love::sound::Decoder to decode samples
|
||||
* from some encoded format, like OGG or MP3, however, Music can come from
|
||||
* other sources as well.
|
||||
**/
|
||||
class Music : public Audible
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
**/
|
||||
virtual ~Music(){};
|
||||
|
||||
/**
|
||||
* Creates a clone of the music stream. Music objects are gradually
|
||||
* decoded, so if the client wants to play the same Music object, we can't
|
||||
* use the same object. We must clone the entire stream.
|
||||
* @return A clone of this object, but rewound to the start.
|
||||
**/
|
||||
virtual Music * clone() = 0;
|
||||
|
||||
}; // Music
|
||||
|
||||
} // audio
|
||||
} // love
|
||||
|
||||
#endif // LOVE_AUDIO_MUSIC_H
|
||||
@@ -1,42 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2006-2009 LOVE Development Team
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
**/
|
||||
|
||||
#ifndef LOVE_AUDIO_SOUND_H
|
||||
#define LOVE_AUDIO_SOUND_H
|
||||
|
||||
// LOVE
|
||||
#include <sound/SoundData.h>
|
||||
#include "Audible.h"
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace audio
|
||||
{
|
||||
class Sound : public Audible
|
||||
{
|
||||
private:
|
||||
public:
|
||||
virtual ~Sound(){};
|
||||
}; // Sound
|
||||
|
||||
} // audio
|
||||
} // love
|
||||
|
||||
#endif // LOVE_AUDIO_SOUND_H
|
||||
@@ -24,47 +24,32 @@ namespace love
|
||||
{
|
||||
namespace audio
|
||||
{
|
||||
Source::Source()
|
||||
: audible(0), looping(false)
|
||||
Source::Source(Type type)
|
||||
: type(type)
|
||||
{
|
||||
}
|
||||
|
||||
Source::~Source()
|
||||
{
|
||||
if(audible != 0)
|
||||
{
|
||||
audible->stop(this);
|
||||
audible->release();
|
||||
}
|
||||
}
|
||||
|
||||
void Source::setAudible(Audible * audible)
|
||||
{
|
||||
// If this source already has an audible, remove it.
|
||||
if(this->audible != 0)
|
||||
{
|
||||
this->audible->stop(this);
|
||||
this->audible->release();
|
||||
}
|
||||
|
||||
this->audible = audible;
|
||||
audible->retain();
|
||||
}
|
||||
|
||||
Audible * Source::getAudible() const
|
||||
{
|
||||
return audible;
|
||||
}
|
||||
|
||||
void Source::setLooping(bool looping)
|
||||
bool Source::getConstant(const char * in, Type & out)
|
||||
{
|
||||
this->looping = looping;
|
||||
return types.find(in, out);
|
||||
}
|
||||
|
||||
bool Source::isLooping() const
|
||||
{
|
||||
return looping;
|
||||
bool Source::getConstant(Type in, const char *& out)
|
||||
{
|
||||
return types.find(in, out);
|
||||
}
|
||||
|
||||
StringMap<Source::Type, Source::TYPE_MAX_ENUM>::Entry Source::typeEntries[] =
|
||||
{
|
||||
{"static", Source::TYPE_STATIC},
|
||||
{"stream", Source::TYPE_STREAM},
|
||||
};
|
||||
|
||||
StringMap<Source::Type, Source::TYPE_MAX_ENUM> Source::types(Source::typeEntries, sizeof(Source::typeEntries));
|
||||
|
||||
} // audio
|
||||
} // love
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
// LOVE
|
||||
#include <common/Object.h>
|
||||
#include "Audible.h"
|
||||
#include <common/StringMap.h>
|
||||
|
||||
namespace love
|
||||
{
|
||||
@@ -31,14 +31,23 @@ namespace audio
|
||||
{
|
||||
class Source : public Object
|
||||
{
|
||||
protected:
|
||||
Audible * audible;
|
||||
bool looping;
|
||||
public:
|
||||
Source();
|
||||
|
||||
enum Type
|
||||
{
|
||||
TYPE_STATIC = 1,
|
||||
TYPE_STREAM,
|
||||
TYPE_MAX_ENUM
|
||||
}; // Type
|
||||
|
||||
protected:
|
||||
Type type;
|
||||
public:
|
||||
|
||||
Source(Type type);
|
||||
virtual ~Source();
|
||||
void setAudible(Audible * audible);
|
||||
Audible * getAudible() const;
|
||||
|
||||
virtual Source * copy() = 0;
|
||||
|
||||
virtual void play() = 0;
|
||||
virtual void stop() = 0;
|
||||
@@ -46,6 +55,7 @@ namespace audio
|
||||
virtual void resume() = 0;
|
||||
virtual void rewind() = 0;
|
||||
virtual bool isStopped() const = 0;
|
||||
virtual bool isFinished() const = 0;
|
||||
virtual void update() = 0;
|
||||
|
||||
virtual void setPitch(float pitch) = 0;
|
||||
@@ -62,8 +72,16 @@ namespace audio
|
||||
virtual void setDirection(float * v) = 0;
|
||||
virtual void getDirection(float * v) const = 0;
|
||||
|
||||
void setLooping(bool looping);
|
||||
bool isLooping() const;
|
||||
virtual void setLooping(bool looping) = 0;
|
||||
virtual bool isLooping() const = 0;
|
||||
|
||||
static bool getConstant(const char * in, Type & out);
|
||||
static bool getConstant(Type in, const char *& out);
|
||||
|
||||
private:
|
||||
|
||||
static StringMap<Type, TYPE_MAX_ENUM>::Entry typeEntries[];
|
||||
static StringMap<Type, TYPE_MAX_ENUM> types;
|
||||
|
||||
}; // Source
|
||||
|
||||
|
||||
@@ -39,22 +39,12 @@ namespace null
|
||||
return "love.audio.null";
|
||||
}
|
||||
|
||||
love::audio::Sound * Audio::newSound(love::sound::SoundData * data)
|
||||
{
|
||||
return new Sound(data);
|
||||
}
|
||||
|
||||
love::audio::Music * Audio::newMusic(love::sound::Decoder * decoder)
|
||||
{
|
||||
return new Music(decoder);
|
||||
}
|
||||
|
||||
love::audio::Source * Audio::newSource(love::audio::Sound * sound)
|
||||
love::audio::Source * Audio::newSource(love::sound::Decoder * decoder)
|
||||
{
|
||||
return new Source();
|
||||
}
|
||||
|
||||
love::audio::Source * Audio::newSource(love::audio::Music * music)
|
||||
love::audio::Source * Audio::newSource(love::sound::SoundData * soundData)
|
||||
{
|
||||
return new Source();
|
||||
}
|
||||
@@ -73,14 +63,6 @@ namespace null
|
||||
{
|
||||
}
|
||||
|
||||
void Audio::play(love::audio::Sound * sound)
|
||||
{
|
||||
}
|
||||
|
||||
void Audio::play(love::audio::Music * music)
|
||||
{
|
||||
}
|
||||
|
||||
void Audio::play()
|
||||
{
|
||||
}
|
||||
|
||||
@@ -24,8 +24,6 @@
|
||||
// LOVE
|
||||
#include <audio/Audio.h>
|
||||
|
||||
#include "Sound.h"
|
||||
#include "Music.h"
|
||||
#include "Source.h"
|
||||
|
||||
namespace love
|
||||
@@ -41,21 +39,17 @@ namespace null
|
||||
public:
|
||||
|
||||
Audio();
|
||||
~Audio();
|
||||
virtual ~Audio();
|
||||
|
||||
// Implements Module.
|
||||
const char * getName() const;
|
||||
|
||||
// Implements Audio.
|
||||
love::audio::Sound * newSound(love::sound::SoundData * data);
|
||||
love::audio::Music * newMusic(love::sound::Decoder * decoder);
|
||||
love::audio::Source * newSource(love::audio::Sound * sound);
|
||||
love::audio::Source * newSource(love::audio::Music * music);
|
||||
love::audio::Source * newSource(love::sound::Decoder * decoder);
|
||||
love::audio::Source * newSource(love::sound::SoundData * soundData);
|
||||
int getNumSources() const;
|
||||
int getMaxSources() const;
|
||||
void play(love::audio::Source * source);
|
||||
void play(love::audio::Sound * sound);
|
||||
void play(love::audio::Music * music);
|
||||
void play();
|
||||
void stop(love::audio::Source * source);
|
||||
void stop();
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2006-2009 LOVE Development Team
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
**/
|
||||
|
||||
#include "Music.h"
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace audio
|
||||
{
|
||||
namespace null
|
||||
{
|
||||
Music::Music(love::sound::Decoder * decoder)
|
||||
: decoder(decoder)
|
||||
{
|
||||
decoder->retain();
|
||||
}
|
||||
|
||||
Music::~Music()
|
||||
{
|
||||
decoder->release();
|
||||
}
|
||||
|
||||
love::audio::Music * Music::clone()
|
||||
{
|
||||
return new Music(decoder->clone());
|
||||
}
|
||||
|
||||
void Music::play(love::audio::Source * s)
|
||||
{
|
||||
}
|
||||
|
||||
void Music::update(love::audio::Source * s)
|
||||
{
|
||||
}
|
||||
|
||||
void Music::stop(love::audio::Source * s)
|
||||
{
|
||||
}
|
||||
|
||||
void Music::rewind(love::audio::Source * s)
|
||||
{
|
||||
}
|
||||
|
||||
} // null
|
||||
} // audio
|
||||
} // love
|
||||
@@ -1,57 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2006-2009 LOVE Development Team
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
**/
|
||||
|
||||
#ifndef LOVE_AUDIO_NULL_MUSIC_H
|
||||
#define LOVE_AUDIO_NULL_MUSIC_H
|
||||
|
||||
// LOVE
|
||||
#include <audio/Music.h>
|
||||
#include <sound/Decoder.h>
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace audio
|
||||
{
|
||||
namespace null
|
||||
{
|
||||
class Music : public love::audio::Music
|
||||
{
|
||||
private:
|
||||
love::sound::Decoder * decoder;
|
||||
public:
|
||||
Music(love::sound::Decoder * decoder);
|
||||
virtual ~Music();
|
||||
|
||||
// Implements Audible.
|
||||
void play(love::audio::Source * source);
|
||||
void update(love::audio::Source * source);
|
||||
void stop(love::audio::Source * source);
|
||||
void rewind(love::audio::Source * source);
|
||||
|
||||
// Implements Music.
|
||||
love::audio::Music * clone();
|
||||
|
||||
}; // Music
|
||||
|
||||
} // null
|
||||
} // audio
|
||||
} // love
|
||||
|
||||
#endif // LOVE_AUDIO_NULL_MUSIC_H
|
||||
@@ -1,55 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2006-2009 LOVE Development Team
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
**/
|
||||
|
||||
#include "Sound.h"
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace audio
|
||||
{
|
||||
namespace null
|
||||
{
|
||||
Sound::Sound(love::sound::SoundData * data)
|
||||
{
|
||||
}
|
||||
|
||||
Sound::~Sound()
|
||||
{
|
||||
}
|
||||
|
||||
void Sound::play(love::audio::Source * s)
|
||||
{
|
||||
}
|
||||
|
||||
void Sound::update(love::audio::Source * s)
|
||||
{
|
||||
}
|
||||
|
||||
void Sound::stop(love::audio::Source * s)
|
||||
{
|
||||
}
|
||||
|
||||
void Sound::rewind(love::audio::Source * s)
|
||||
{
|
||||
}
|
||||
|
||||
} // null
|
||||
} // audio
|
||||
} // love
|
||||
@@ -1,54 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2006-2009 LOVE Development Team
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
**/
|
||||
|
||||
#ifndef LOVE_AUDIO_NULL_SOUND_H
|
||||
#define LOVE_AUDIO_NULL_SOUND_H
|
||||
|
||||
// LOVE
|
||||
#include <sound/SoundData.h>
|
||||
#include <audio/Sound.h>
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace audio
|
||||
{
|
||||
namespace null
|
||||
{
|
||||
class Sound : public love::audio::Sound
|
||||
{
|
||||
private:
|
||||
|
||||
public:
|
||||
Sound(love::sound::SoundData * data);
|
||||
virtual ~Sound();
|
||||
|
||||
// Implements Audible.
|
||||
void play(love::audio::Source * s);
|
||||
void update(love::audio::Source * s);
|
||||
void stop(love::audio::Source * s);
|
||||
void rewind(love::audio::Source * s);
|
||||
|
||||
}; // Sound
|
||||
|
||||
} // null
|
||||
} // audio
|
||||
} // love
|
||||
|
||||
#endif // LOVE_AUDIO_NULL_SOUND_H
|
||||
@@ -28,18 +28,20 @@ namespace null
|
||||
{
|
||||
|
||||
Source::Source()
|
||||
: love::audio::Source(Source::TYPE_STATIC)
|
||||
{
|
||||
}
|
||||
|
||||
Source::Source(Audible * audible)
|
||||
{
|
||||
setAudible(audible);
|
||||
}
|
||||
|
||||
Source::~Source()
|
||||
{
|
||||
}
|
||||
|
||||
love::audio::Source * Source::copy()
|
||||
{
|
||||
this->retain();
|
||||
return this;
|
||||
}
|
||||
|
||||
void Source::play()
|
||||
{
|
||||
}
|
||||
@@ -65,6 +67,11 @@ namespace null
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Source::isFinished() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void Source::update()
|
||||
{
|
||||
}
|
||||
@@ -113,6 +120,16 @@ namespace null
|
||||
{
|
||||
}
|
||||
|
||||
void Source::setLooping(bool looping)
|
||||
{
|
||||
this->looping = looping;
|
||||
}
|
||||
|
||||
bool Source::isLooping() const
|
||||
{
|
||||
return looping;
|
||||
}
|
||||
|
||||
} // null
|
||||
} // audio
|
||||
} // love
|
||||
|
||||
@@ -36,33 +36,34 @@ namespace null
|
||||
private:
|
||||
|
||||
float pitch;
|
||||
float volume;
|
||||
float volume;
|
||||
bool looping;
|
||||
|
||||
public:
|
||||
Source();
|
||||
Source(Audible * audible);
|
||||
virtual ~Source();
|
||||
|
||||
void play();
|
||||
void stop();
|
||||
void pause();
|
||||
void resume();
|
||||
void rewind();
|
||||
bool isStopped() const;
|
||||
void update();
|
||||
|
||||
void setPitch(float pitch);
|
||||
float getPitch() const;
|
||||
|
||||
void setVolume(float volume);
|
||||
float getVolume() const;
|
||||
|
||||
void setPosition(float * v);
|
||||
void getPosition(float * v) const;
|
||||
void setVelocity(float * v);
|
||||
void getVelocity(float * v) const;
|
||||
void setDirection(float * v);
|
||||
void getDirection(float * v) const;
|
||||
virtual love::audio::Source * copy();
|
||||
virtual void play();
|
||||
virtual void stop();
|
||||
virtual void pause();
|
||||
virtual void resume();
|
||||
virtual void rewind();
|
||||
virtual bool isStopped() const;
|
||||
virtual bool isFinished() const;
|
||||
virtual void update();
|
||||
virtual void setPitch(float pitch);
|
||||
virtual float getPitch() const;
|
||||
virtual void setVolume(float volume);
|
||||
virtual float getVolume() const;
|
||||
virtual void setPosition(float * v);
|
||||
virtual void getPosition(float * v) const;
|
||||
virtual void setVelocity(float * v);
|
||||
virtual void getVelocity(float * v) const;
|
||||
virtual void setDirection(float * v);
|
||||
virtual void getDirection(float * v) const;
|
||||
void setLooping(bool looping);
|
||||
bool isLooping() const;
|
||||
|
||||
}; // Source
|
||||
|
||||
|
||||
@@ -82,24 +82,14 @@ namespace openal
|
||||
return "love.audio.openal";
|
||||
}
|
||||
|
||||
love::audio::Sound * Audio::newSound(love::sound::SoundData * data)
|
||||
love::audio::Source * Audio::newSource(love::sound::Decoder * decoder)
|
||||
{
|
||||
return new Sound(pool, data);
|
||||
return new Source(pool, decoder);
|
||||
}
|
||||
|
||||
love::audio::Music * Audio::newMusic(love::sound::Decoder * decoder)
|
||||
love::audio::Source * Audio::newSource(love::sound::SoundData * soundData)
|
||||
{
|
||||
return new Music(pool, decoder);
|
||||
}
|
||||
|
||||
love::audio::Source * Audio::newSource(love::audio::Sound * sound)
|
||||
{
|
||||
return new Source(pool, sound);
|
||||
}
|
||||
|
||||
love::audio::Source * Audio::newSource(love::audio::Music * music)
|
||||
{
|
||||
return new Source(pool, music->clone());
|
||||
return new Source(pool, soundData);
|
||||
}
|
||||
|
||||
int Audio::getNumSources() const
|
||||
@@ -117,22 +107,6 @@ namespace openal
|
||||
source->play();
|
||||
}
|
||||
|
||||
void Audio::play(love::audio::Sound * sound)
|
||||
{
|
||||
Source * source = new Source(pool, sound);
|
||||
play(source);
|
||||
source->release();
|
||||
}
|
||||
|
||||
void Audio::play(love::audio::Music * music)
|
||||
{
|
||||
love::audio::Music *cloned = music->clone();
|
||||
Source * source = new Source(pool, cloned);
|
||||
play(source);
|
||||
cloned->release();
|
||||
source->release();
|
||||
}
|
||||
|
||||
void Audio::stop(love::audio::Source * source)
|
||||
{
|
||||
source->stop();
|
||||
|
||||
@@ -35,8 +35,6 @@
|
||||
#include <common/config.h>
|
||||
#include <sound/SoundData.h>
|
||||
|
||||
#include "Sound.h"
|
||||
#include "Music.h"
|
||||
#include "Source.h"
|
||||
#include "Pool.h"
|
||||
|
||||
@@ -86,15 +84,11 @@ namespace openal
|
||||
const char * getName() const;
|
||||
|
||||
// Implements Audio.
|
||||
love::audio::Sound * newSound(love::sound::SoundData * data);
|
||||
love::audio::Music * newMusic(love::sound::Decoder * decoder);
|
||||
love::audio::Source * newSource(love::audio::Sound * sound);
|
||||
love::audio::Source * newSource(love::audio::Music * music);
|
||||
love::audio::Source * newSource(love::sound::Decoder * decoder);
|
||||
love::audio::Source * newSource(love::sound::SoundData * soundData);
|
||||
int getNumSources() const;
|
||||
int getMaxSources() const;
|
||||
void play(love::audio::Source * source);
|
||||
void play(love::audio::Sound * sound);
|
||||
void play(love::audio::Music * music);
|
||||
void play();
|
||||
void stop(love::audio::Source * source);
|
||||
void stop();
|
||||
|
||||
@@ -1,134 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2006-2009 LOVE Development Team
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
**/
|
||||
|
||||
#include "Music.h"
|
||||
|
||||
// STD
|
||||
#include <iostream>
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace audio
|
||||
{
|
||||
namespace openal
|
||||
{
|
||||
Music::Music(Pool * pool, love::sound::Decoder * decoder)
|
||||
: pool(pool), decoder(decoder), source(0)
|
||||
{
|
||||
decoder->retain();
|
||||
alGenBuffers(NUM_BUFFERS, buffers);
|
||||
}
|
||||
|
||||
Music::~Music()
|
||||
{
|
||||
decoder->release();
|
||||
alDeleteBuffers(NUM_BUFFERS, buffers);
|
||||
}
|
||||
|
||||
love::audio::Music * Music::clone()
|
||||
{
|
||||
return new Music(pool, decoder->clone());
|
||||
}
|
||||
|
||||
void Music::play(love::audio::Source * s)
|
||||
{
|
||||
source = pool->find(s);
|
||||
|
||||
if(source)
|
||||
{
|
||||
for(int i = 0; i < NUM_BUFFERS; i++)
|
||||
{
|
||||
if(!stream(s, buffers[i]))
|
||||
{
|
||||
std::cout << "Could not stream music." << std::endl;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
alSourceQueueBuffers(source, NUM_BUFFERS, buffers);
|
||||
}
|
||||
}
|
||||
|
||||
void Music::update(love::audio::Source * s)
|
||||
{
|
||||
if(source)
|
||||
{
|
||||
// Number of processed buffers.
|
||||
ALint processed;
|
||||
|
||||
alGetSourcei(source, AL_BUFFERS_PROCESSED, &processed);
|
||||
|
||||
while(processed--)
|
||||
{
|
||||
ALuint buffer;
|
||||
|
||||
// Get a free buffer.
|
||||
alSourceUnqueueBuffers(source, 1, &buffer);
|
||||
|
||||
if(stream(s, buffer))
|
||||
alSourceQueueBuffers(source, 1, &buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Music::stop(love::audio::Source * s)
|
||||
{
|
||||
if(source)
|
||||
{
|
||||
ALuint bufs[NUM_BUFFERS];
|
||||
alSourceStop(source);
|
||||
alSourceUnqueueBuffers(source, NUM_BUFFERS, bufs);
|
||||
source = 0;
|
||||
rewind(s);
|
||||
}
|
||||
}
|
||||
|
||||
void Music::rewind(love::audio::Source * s)
|
||||
{
|
||||
decoder->rewind();
|
||||
}
|
||||
|
||||
bool Music::stream(love::audio::Source * source, ALuint buffer)
|
||||
{
|
||||
if(source->isLooping() && decoder->isFinished())
|
||||
decoder->rewind();
|
||||
|
||||
// Get more sound data.
|
||||
int decoded = decoder->decode();
|
||||
|
||||
int fmt = pool->getFormat(decoder->getChannels(), decoder->getBits());
|
||||
|
||||
if(fmt == 0)
|
||||
return false;
|
||||
|
||||
if(decoded > 0)
|
||||
{
|
||||
alBufferData(buffer, fmt, decoder->getBuffer(),
|
||||
decoder->getSize(), decoder->getSampleRate());
|
||||
return true;
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
} // openal
|
||||
} // audio
|
||||
} // love
|
||||
@@ -1,79 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2006-2009 LOVE Development Team
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
**/
|
||||
|
||||
#ifndef LOVE_AUDIO_OPENAL_MUSIC_H
|
||||
#define LOVE_AUDIO_OPENAL_MUSIC_H
|
||||
|
||||
// LOVE
|
||||
#include <audio/Music.h>
|
||||
#include <common/config.h>
|
||||
#include <sound/Decoder.h>
|
||||
#include "Pool.h"
|
||||
|
||||
// OpenAL
|
||||
#ifdef LOVE_MACOSX
|
||||
#include <OpenAL/alc.h>
|
||||
#include <OpenAL/al.h>
|
||||
#else
|
||||
#include <AL/alc.h>
|
||||
#include <AL/al.h>
|
||||
#endif
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace audio
|
||||
{
|
||||
namespace openal
|
||||
{
|
||||
|
||||
// Forward declarations.
|
||||
class Audio;
|
||||
|
||||
class Music : public love::audio::Music
|
||||
{
|
||||
private:
|
||||
static const unsigned int NUM_BUFFERS = 32;
|
||||
ALuint buffers[NUM_BUFFERS];
|
||||
Pool * pool;
|
||||
love::sound::Decoder * decoder;
|
||||
ALuint source;
|
||||
|
||||
public:
|
||||
Music(Pool * pool, love::sound::Decoder * decoder);
|
||||
virtual ~Music();
|
||||
|
||||
// Implements Audible.
|
||||
void play(love::audio::Source * source);
|
||||
void update(love::audio::Source * source);
|
||||
void stop(love::audio::Source * source);
|
||||
void rewind(love::audio::Source * source);
|
||||
|
||||
// Implements Music.
|
||||
love::audio::Music * clone();
|
||||
|
||||
private:
|
||||
bool stream(love::audio::Source * source, ALuint buffer);
|
||||
}; // Sound
|
||||
|
||||
} // openal
|
||||
} // audio
|
||||
} // love
|
||||
|
||||
#endif // LOVE_AUDIO_OPENAL_MUSIC_H
|
||||
@@ -20,6 +20,8 @@
|
||||
|
||||
#include "Pool.h"
|
||||
|
||||
#include "Source.h"
|
||||
|
||||
#define MUTEX_ASSERT(fn, sval) \
|
||||
if(fn != sval) \
|
||||
{ \
|
||||
@@ -62,20 +64,6 @@ namespace openal
|
||||
alDeleteSources(NUM_SOURCES, sources);
|
||||
}
|
||||
|
||||
ALenum Pool::getFormat(int channels, int bits) const
|
||||
{
|
||||
if(channels == 1 && bits == 8)
|
||||
return AL_FORMAT_MONO8;
|
||||
else if(channels == 1 && bits == 16)
|
||||
return AL_FORMAT_MONO16;
|
||||
else if(channels == 2 && bits == 8)
|
||||
return AL_FORMAT_STEREO8;
|
||||
else if(channels == 2 && bits == 16)
|
||||
return AL_FORMAT_STEREO16;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool Pool::isAvailable() const
|
||||
{
|
||||
bool has = false;
|
||||
@@ -85,42 +73,11 @@ namespace openal
|
||||
return has;
|
||||
}
|
||||
|
||||
ALuint Pool::claim(love::audio::Source * source)
|
||||
{
|
||||
ALuint s = 0;
|
||||
LOCK(mutex);
|
||||
if(!available.empty())
|
||||
{
|
||||
// Get the first available source.
|
||||
s = available.front();
|
||||
|
||||
// Remove it.
|
||||
available.pop();
|
||||
|
||||
// Insert into map of playing sources.
|
||||
playing.insert(std::pair<love::audio::Source *, ALuint>(source, s));
|
||||
|
||||
source->retain();
|
||||
}
|
||||
UNLOCK(mutex);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
ALuint Pool::find(const love::audio::Source * source) const
|
||||
{
|
||||
ALuint r = 0;
|
||||
LOCK(mutex);
|
||||
r = findi(source);
|
||||
UNLOCK(mutex);
|
||||
return r;
|
||||
}
|
||||
|
||||
bool Pool::isPlaying(love::audio::Source * s)
|
||||
bool Pool::isPlaying(Source * s)
|
||||
{
|
||||
bool p = false;
|
||||
LOCK(mutex);
|
||||
for(std::map<love::audio::Source *, ALuint>::iterator i = playing.begin(); i != playing.end(); i++)
|
||||
for(std::map<Source *, ALuint>::iterator i = playing.begin(); i != playing.end(); i++)
|
||||
{
|
||||
if(i->first == s)
|
||||
p = true;
|
||||
@@ -133,13 +90,13 @@ namespace openal
|
||||
{
|
||||
LOCK(mutex);
|
||||
|
||||
std::map<love::audio::Source *, ALuint>::iterator i = playing.begin();
|
||||
std::map<Source *, ALuint>::iterator i = playing.begin();
|
||||
|
||||
while(i != playing.end())
|
||||
{
|
||||
if(i->first->isStopped())
|
||||
{
|
||||
i->first->stop();
|
||||
i->first->stopAtomic();
|
||||
i->first->release();
|
||||
available.push(i->second);
|
||||
playing.erase(i++);
|
||||
@@ -164,12 +121,56 @@ namespace openal
|
||||
return NUM_SOURCES;
|
||||
}
|
||||
|
||||
bool Pool::play(Source * source, ALuint & out)
|
||||
{
|
||||
bool ok;
|
||||
out = 0;
|
||||
|
||||
LOCK(mutex);
|
||||
|
||||
bool alreadyPlaying = findSource(source, out);
|
||||
|
||||
if(!alreadyPlaying)
|
||||
{
|
||||
// Try to play.
|
||||
if(!available.empty())
|
||||
{
|
||||
// Get the first available source.
|
||||
out = available.front();
|
||||
|
||||
// Remove it.
|
||||
available.pop();
|
||||
|
||||
// Insert into map of playing sources.
|
||||
playing.insert(std::pair<Source *, ALuint>(source, out));
|
||||
|
||||
source->retain();
|
||||
|
||||
source->playAtomic();
|
||||
|
||||
ok = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
ok = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ok = true;
|
||||
}
|
||||
|
||||
UNLOCK(mutex);
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
void Pool::stop()
|
||||
{
|
||||
LOCK(mutex);
|
||||
for(std::map<love::audio::Source *, ALuint>::iterator i = playing.begin(); i != playing.end(); i++)
|
||||
for(std::map<Source *, ALuint>::iterator i = playing.begin(); i != playing.end(); i++)
|
||||
{
|
||||
i->first->stop();
|
||||
i->first->stopAtomic();
|
||||
available.push(i->second);
|
||||
}
|
||||
|
||||
@@ -178,31 +179,65 @@ namespace openal
|
||||
UNLOCK(mutex);
|
||||
}
|
||||
|
||||
void Pool::stop(Source * source)
|
||||
{
|
||||
LOCK(mutex);
|
||||
removeSource(source);
|
||||
UNLOCK(mutex);
|
||||
}
|
||||
|
||||
void Pool::pause()
|
||||
{
|
||||
LOCK(mutex);
|
||||
for(std::map<love::audio::Source *, ALuint>::iterator i = playing.begin(); i != playing.end(); i++)
|
||||
i->first->pause();
|
||||
for(std::map<Source *, ALuint>::iterator i = playing.begin(); i != playing.end(); i++)
|
||||
i->first->pauseAtomic();
|
||||
UNLOCK(mutex);
|
||||
}
|
||||
|
||||
void Pool::pause(Source * source)
|
||||
{
|
||||
LOCK(mutex);
|
||||
ALuint out;
|
||||
if(findSource(source, out))
|
||||
source->pauseAtomic();
|
||||
UNLOCK(mutex);
|
||||
}
|
||||
|
||||
void Pool::resume()
|
||||
{
|
||||
LOCK(mutex);
|
||||
for(std::map<love::audio::Source *, ALuint>::iterator i = playing.begin(); i != playing.end(); i++)
|
||||
i->first->resume();
|
||||
for(std::map<Source *, ALuint>::iterator i = playing.begin(); i != playing.end(); i++)
|
||||
i->first->resumeAtomic();
|
||||
UNLOCK(mutex);
|
||||
}
|
||||
|
||||
void Pool::resume(Source * source)
|
||||
{
|
||||
LOCK(mutex);
|
||||
ALuint out;
|
||||
if(findSource(source, out))
|
||||
source->resumeAtomic();
|
||||
UNLOCK(mutex);
|
||||
}
|
||||
|
||||
void Pool::rewind()
|
||||
{
|
||||
LOCK(mutex);
|
||||
for(std::map<love::audio::Source *, ALuint>::iterator i = playing.begin(); i != playing.end(); i++)
|
||||
i->first->rewind();
|
||||
for(std::map<Source *, ALuint>::iterator i = playing.begin(); i != playing.end(); i++)
|
||||
i->first->rewindAtomic();
|
||||
UNLOCK(mutex);
|
||||
}
|
||||
|
||||
void Pool::release(love::audio::Source * source)
|
||||
void Pool::rewind(Source * source)
|
||||
{
|
||||
LOCK(mutex);
|
||||
ALuint out;
|
||||
if(findSource(source, out))
|
||||
source->rewindAtomic();
|
||||
UNLOCK(mutex);
|
||||
}
|
||||
|
||||
void Pool::release(Source * source)
|
||||
{
|
||||
ALuint s = findi(source);
|
||||
|
||||
@@ -213,9 +248,9 @@ namespace openal
|
||||
}
|
||||
}
|
||||
|
||||
ALuint Pool::findi(const love::audio::Source * source) const
|
||||
ALuint Pool::findi(const Source * source) const
|
||||
{
|
||||
std::map<love::audio::Source *, ALuint>::const_iterator i = playing.find((love::audio::Source *)source);
|
||||
std::map<Source *, ALuint>::const_iterator i = playing.find((Source *)source);
|
||||
|
||||
if(i != playing.end())
|
||||
return i->second;
|
||||
@@ -223,6 +258,34 @@ namespace openal
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool Pool::findSource(Source * source, ALuint & out)
|
||||
{
|
||||
std::map<Source *, ALuint>::const_iterator i = playing.find((Source *)source);
|
||||
|
||||
bool found = i != playing.end();
|
||||
|
||||
if(found)
|
||||
out = i->second;
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
bool Pool::removeSource(Source * source)
|
||||
{
|
||||
std::map<Source *, ALuint>::const_iterator i = playing.find((Source *)source);
|
||||
|
||||
if(i != playing.end())
|
||||
{
|
||||
source->stopAtomic();
|
||||
source->release();
|
||||
available.push(i->second);
|
||||
playing.erase(i++);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // openal
|
||||
} // audio
|
||||
} // love
|
||||
|
||||
@@ -31,7 +31,6 @@
|
||||
#include <SDL.h>
|
||||
|
||||
// LOVE
|
||||
#include <audio/Source.h>
|
||||
#include <common/config.h>
|
||||
#include <common/Exception.h>
|
||||
|
||||
@@ -50,6 +49,9 @@ namespace audio
|
||||
{
|
||||
namespace openal
|
||||
{
|
||||
|
||||
class Source;
|
||||
|
||||
class Pool
|
||||
{
|
||||
private:
|
||||
@@ -64,7 +66,7 @@ namespace openal
|
||||
std::queue<ALuint> available;
|
||||
|
||||
// A map of playing sources.
|
||||
std::map<love::audio::Source *, ALuint> playing;
|
||||
std::map<Source *, ALuint> playing;
|
||||
|
||||
// Only one thread can access this object at the same time. This mutex will
|
||||
// make sure of that.
|
||||
@@ -75,15 +77,6 @@ namespace openal
|
||||
Pool();
|
||||
~Pool();
|
||||
|
||||
/**
|
||||
* Gets the OpenAL format identifier based on number of
|
||||
* channels and bits.
|
||||
* @param channels Either 1 (mono) or 2 (stereo).
|
||||
* @param bits Either 8-bit samples, or 16-bit samples.
|
||||
* @return One of AL_FORMAT_*, or 0 if unsupported format.
|
||||
**/
|
||||
ALenum getFormat(int channels, int bits) const;
|
||||
|
||||
/**
|
||||
* Checks whether an OpenAL source is available.
|
||||
* @return True if at least one is available, false otherwise.
|
||||
@@ -93,26 +86,22 @@ namespace openal
|
||||
/**
|
||||
* Checks whether a Source is currently in the playing list.
|
||||
**/
|
||||
bool isPlaying(love::audio::Source * s);
|
||||
|
||||
/**
|
||||
* Returns an available OpenAL source identifier, or 0 if
|
||||
* none is available.
|
||||
* @return An OpenAL source ID, or 0 if unavailable.
|
||||
**/
|
||||
ALuint claim(love::audio::Source * source);
|
||||
|
||||
ALuint find(const love::audio::Source * source) const;
|
||||
bool isPlaying(Source * s);
|
||||
|
||||
void update();
|
||||
|
||||
int getNumSources() const;
|
||||
int getMaxSources() const;
|
||||
|
||||
bool play(Source * source, ALuint & out);
|
||||
void stop();
|
||||
void stop(Source * source);
|
||||
void pause();
|
||||
void pause(Source * source);
|
||||
void resume();
|
||||
void resume(Source * source);
|
||||
void rewind();
|
||||
void rewind(Source * source);
|
||||
|
||||
private:
|
||||
|
||||
@@ -120,9 +109,12 @@ namespace openal
|
||||
* Makes the specified OpenAL source available for use.
|
||||
* @param source The OpenAL source.
|
||||
**/
|
||||
void release(love::audio::Source * source);
|
||||
void release(Source * source);
|
||||
|
||||
ALuint findi(const love::audio::Source * source) const;
|
||||
ALuint findi(const Source * source) const;
|
||||
|
||||
bool findSource(Source * source, ALuint & out);
|
||||
bool removeSource(Source * source);
|
||||
}; // Pool
|
||||
|
||||
} // openal
|
||||
|
||||
@@ -1,87 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2006-2009 LOVE Development Team
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
**/
|
||||
|
||||
#include "Sound.h"
|
||||
|
||||
#include <common/Exception.h>
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace audio
|
||||
{
|
||||
namespace openal
|
||||
{
|
||||
Sound::Sound(Pool * pool, love::sound::SoundData * data)
|
||||
: pool(pool), buffer(0), source(source)
|
||||
{
|
||||
|
||||
// Generate the buffer.
|
||||
alGenBuffers(1, &buffer);
|
||||
|
||||
int fmt = pool->getFormat(data->getChannels(), data->getBits());
|
||||
|
||||
if(fmt == 0)
|
||||
throw love::Exception("Unsupported audio format.");
|
||||
|
||||
alBufferData(buffer, fmt, data->getData(), data->getSize(), data->getSampleRate());
|
||||
|
||||
// Note: we're done with the sound data
|
||||
// at this point. No need to retain.
|
||||
}
|
||||
|
||||
Sound::~Sound()
|
||||
{
|
||||
if(buffer)
|
||||
alDeleteBuffers(1, &buffer);
|
||||
}
|
||||
|
||||
void Sound::play(love::audio::Source * s)
|
||||
{
|
||||
// Set the buffer for the sound.
|
||||
source = pool->find(s);
|
||||
|
||||
if(source)
|
||||
{
|
||||
alSourcei(source, AL_BUFFER, buffer);
|
||||
alSourcei(source, AL_LOOPING, s->isLooping() ? AL_TRUE : AL_FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
void Sound::update(love::audio::Source * s)
|
||||
{
|
||||
// Looping mode could have changed.
|
||||
alSourcei(source, AL_LOOPING, s->isLooping() ? AL_TRUE : AL_FALSE);
|
||||
}
|
||||
|
||||
void Sound::stop(love::audio::Source * s)
|
||||
{
|
||||
if(source)
|
||||
alSourceStop(source);
|
||||
}
|
||||
|
||||
void Sound::rewind(love::audio::Source * s)
|
||||
{
|
||||
if(source)
|
||||
alSourceRewind(source);
|
||||
}
|
||||
|
||||
} // openal
|
||||
} // audio
|
||||
} // love
|
||||
@@ -1,77 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2006-2009 LOVE Development Team
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
**/
|
||||
|
||||
#ifndef LOVE_AUDIO_OPENAL_SOUND_H
|
||||
#define LOVE_AUDIO_OPENAL_SOUND_H
|
||||
|
||||
// LOVE
|
||||
#include <sound/SoundData.h>
|
||||
#include <audio/Sound.h>
|
||||
#include <common/config.h>
|
||||
#include "Pool.h"
|
||||
|
||||
|
||||
|
||||
// OpenAL
|
||||
#ifdef LOVE_MACOSX
|
||||
#include <OpenAL/alc.h>
|
||||
#include <OpenAL/al.h>
|
||||
#else
|
||||
#include <AL/alc.h>
|
||||
#include <AL/al.h>
|
||||
#endif
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace audio
|
||||
{
|
||||
namespace openal
|
||||
{
|
||||
// Forward declarations.
|
||||
class Audio;
|
||||
|
||||
class Sound : public love::audio::Sound
|
||||
{
|
||||
private:
|
||||
|
||||
Pool * pool;
|
||||
|
||||
// Sounds only need one buffer.
|
||||
ALuint buffer;
|
||||
|
||||
ALuint source;
|
||||
|
||||
public:
|
||||
Sound(Pool * pool, love::sound::SoundData * data);
|
||||
virtual ~Sound();
|
||||
|
||||
// Implements Audible.
|
||||
void play(love::audio::Source * s);
|
||||
void update(love::audio::Source * s);
|
||||
void stop(love::audio::Source * s);
|
||||
void rewind(love::audio::Source * s);
|
||||
|
||||
}; // Sound
|
||||
|
||||
} // openal
|
||||
} // audio
|
||||
} // love
|
||||
|
||||
#endif // LOVE_AUDIO_OPENAL_SOUND_H
|
||||
@@ -20,6 +20,8 @@
|
||||
|
||||
#include "Source.h"
|
||||
|
||||
#include "Pool.h"
|
||||
|
||||
// STD
|
||||
#include <iostream>
|
||||
|
||||
@@ -30,107 +32,116 @@ namespace audio
|
||||
namespace openal
|
||||
{
|
||||
|
||||
Source::Source(Pool * pool)
|
||||
: pool(pool), source(0), pitch(1.0f), volume(1.0f)
|
||||
static int acc = 0;
|
||||
|
||||
Source::Source(Pool * pool, love::sound::SoundData * soundData)
|
||||
: love::audio::Source(Source::TYPE_STATIC), pool(pool), pitch(1.0f),
|
||||
volume(1.0f), looping(false), decoder(0), valid(false)
|
||||
{
|
||||
alGenBuffers(1, buffers);
|
||||
ALenum fmt = getFormat(soundData->getChannels(), soundData->getBits());
|
||||
alBufferData(buffers[0], fmt, soundData->getData(), soundData->getSize(), soundData->getSampleRate());
|
||||
}
|
||||
|
||||
Source::Source(Pool * pool, Audible * audible)
|
||||
: pool(pool), source(0), pitch(1.0f), volume(1.0f)
|
||||
Source::Source(Pool * pool, love::sound::Decoder * decoder)
|
||||
: love::audio::Source(Source::TYPE_STREAM), pool(pool), pitch(1.0f),
|
||||
volume(1.0f), looping(false), decoder(decoder), valid(false)
|
||||
{
|
||||
setAudible(audible);
|
||||
decoder->retain();
|
||||
alGenBuffers(MAX_BUFFERS, buffers);
|
||||
}
|
||||
|
||||
Source::~Source()
|
||||
{
|
||||
stop();
|
||||
alDeleteBuffers((type == TYPE_STATIC) ? 1 : MAX_BUFFERS, buffers);
|
||||
}
|
||||
|
||||
love::audio::Source * Source::copy()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Source::play()
|
||||
{
|
||||
if(source != 0)
|
||||
return; // Already playing.
|
||||
|
||||
if(pool->isAvailable())
|
||||
source = pool->claim(this);
|
||||
|
||||
if(source != 0)
|
||||
{
|
||||
audible->play(this);
|
||||
|
||||
// Set these properties. These may have changed while we've
|
||||
// been without an AL source.
|
||||
alSourcef(source, AL_PITCH, pitch);
|
||||
alSourcef(source, AL_GAIN, volume);
|
||||
|
||||
alSourcePlay(source);
|
||||
}
|
||||
|
||||
valid = pool->play(this, source);
|
||||
}
|
||||
|
||||
|
||||
void Source::stop()
|
||||
{
|
||||
if(source)
|
||||
{
|
||||
alSourceStop(source);
|
||||
audible->stop(this);
|
||||
source = 0;
|
||||
}
|
||||
pool->stop(this);
|
||||
}
|
||||
|
||||
void Source::pause()
|
||||
{
|
||||
if(source)
|
||||
{
|
||||
alSourcePause(source);
|
||||
}
|
||||
pool->pause();
|
||||
}
|
||||
|
||||
void Source::resume()
|
||||
{
|
||||
if(source)
|
||||
{
|
||||
alSourcePlay(source);
|
||||
}
|
||||
pool->resume();
|
||||
}
|
||||
|
||||
void Source::rewind()
|
||||
{
|
||||
if(audible != 0)
|
||||
audible->rewind(this);
|
||||
pool->rewind();
|
||||
}
|
||||
|
||||
bool Source::isStopped() const
|
||||
{
|
||||
if(source)
|
||||
if(valid)
|
||||
{
|
||||
ALenum state;
|
||||
alGetSourcei(source, AL_SOURCE_STATE, &state);
|
||||
return (state == AL_STOPPED);
|
||||
}
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Source::isFinished() const
|
||||
{
|
||||
return type == TYPE_STATIC ? isStopped() : isStopped() && !isLooping() && decoder->isFinished();
|
||||
}
|
||||
|
||||
void Source::update()
|
||||
{
|
||||
if(audible != 0)
|
||||
audible->update(this);
|
||||
if(valid && type == TYPE_STATIC)
|
||||
{
|
||||
// Looping mode could have changed.
|
||||
alSourcei(source, AL_LOOPING, isLooping() ? AL_TRUE : AL_FALSE);
|
||||
}
|
||||
else if(valid && type == TYPE_STREAM)
|
||||
{
|
||||
// Number of processed buffers.
|
||||
ALint processed;
|
||||
|
||||
alGetSourcei(source, AL_BUFFERS_PROCESSED, &processed);
|
||||
|
||||
while(processed--)
|
||||
{
|
||||
ALuint buffer;
|
||||
|
||||
// Get a free buffer.
|
||||
alSourceUnqueueBuffers(source, 1, &buffer);
|
||||
|
||||
if(streamAtomic(buffer, decoder) > 0)
|
||||
alSourceQueueBuffers(source, 1, &buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Source::setPitch(float pitch)
|
||||
{
|
||||
if(source)
|
||||
{
|
||||
if(valid)
|
||||
alSourcef(source, AL_PITCH, pitch);
|
||||
}
|
||||
|
||||
this->pitch = pitch;
|
||||
}
|
||||
|
||||
float Source::getPitch() const
|
||||
{
|
||||
if(source)
|
||||
if(valid)
|
||||
{
|
||||
ALfloat f;
|
||||
alGetSourcef(source, AL_PITCH, &f);
|
||||
@@ -143,7 +154,7 @@ namespace openal
|
||||
|
||||
void Source::setVolume(float volume)
|
||||
{
|
||||
if(source)
|
||||
if(valid)
|
||||
{
|
||||
alSourcef(source, AL_GAIN, volume);
|
||||
}
|
||||
@@ -153,7 +164,7 @@ namespace openal
|
||||
|
||||
float Source::getVolume() const
|
||||
{
|
||||
if(source)
|
||||
if(valid)
|
||||
{
|
||||
ALfloat f;
|
||||
alGetSourcef(source, AL_GAIN, &f);
|
||||
@@ -166,40 +177,185 @@ namespace openal
|
||||
|
||||
void Source::setPosition(float * v)
|
||||
{
|
||||
if(source)
|
||||
if(valid)
|
||||
alSourcefv(source, AL_POSITION, v);
|
||||
}
|
||||
|
||||
void Source::getPosition(float * v) const
|
||||
{
|
||||
if(source)
|
||||
if(valid)
|
||||
alGetSourcefv(source, AL_POSITION, v);
|
||||
}
|
||||
|
||||
void Source::setVelocity(float * v)
|
||||
{
|
||||
if(source)
|
||||
if(valid)
|
||||
alSourcefv(source, AL_VELOCITY, v);
|
||||
}
|
||||
|
||||
void Source::getVelocity(float * v) const
|
||||
{
|
||||
if(source)
|
||||
if(valid)
|
||||
alGetSourcefv(source, AL_VELOCITY, v);
|
||||
}
|
||||
|
||||
void Source::setDirection(float * v)
|
||||
{
|
||||
if(source)
|
||||
if(valid)
|
||||
alSourcefv(source, AL_DIRECTION, v);
|
||||
}
|
||||
|
||||
void Source::getDirection(float * v) const
|
||||
{
|
||||
if(source)
|
||||
if(valid)
|
||||
alGetSourcefv(source, AL_DIRECTION, v);
|
||||
}
|
||||
|
||||
void Source::setLooping(bool looping)
|
||||
{
|
||||
this->looping = looping;
|
||||
}
|
||||
|
||||
bool Source::isLooping() const
|
||||
{
|
||||
return looping;
|
||||
}
|
||||
|
||||
void Source::playAtomic()
|
||||
{
|
||||
if(type == TYPE_STATIC)
|
||||
{
|
||||
alSourcei(source, AL_BUFFER, buffers[0]);
|
||||
alSourcei(source, AL_LOOPING, isLooping() ? AL_TRUE : AL_FALSE);
|
||||
}
|
||||
else if(type == TYPE_STREAM)
|
||||
{
|
||||
int usedBuffers = 0;
|
||||
|
||||
for(int i = 0; i < MAX_BUFFERS; i++)
|
||||
{
|
||||
int decoded = streamAtomic(buffers[i], decoder);
|
||||
++usedBuffers;
|
||||
if(decoded < decoder->getSize())
|
||||
break;
|
||||
}
|
||||
|
||||
if(usedBuffers > 0)
|
||||
alSourceQueueBuffers(source, usedBuffers, buffers);
|
||||
}
|
||||
|
||||
// Set these properties. These may have changed while we've
|
||||
// been without an AL source.
|
||||
alSourcef(source, AL_PITCH, pitch);
|
||||
alSourcef(source, AL_GAIN, volume);
|
||||
|
||||
alSourcePlay(source);
|
||||
}
|
||||
|
||||
void Source::stopAtomic()
|
||||
{
|
||||
if(valid)
|
||||
{
|
||||
if(type == TYPE_STATIC)
|
||||
{
|
||||
alSourceStop(source);
|
||||
}
|
||||
else if(type == TYPE_STREAM)
|
||||
{
|
||||
alSourceStop(source);
|
||||
|
||||
int queued = 0;
|
||||
alGetSourcei(source, AL_BUFFERS_QUEUED, &queued);
|
||||
|
||||
while(queued--)
|
||||
{
|
||||
ALuint buffer;
|
||||
alSourceUnqueueBuffers(source, 1, &buffer);
|
||||
}
|
||||
}
|
||||
|
||||
reset(source);
|
||||
}
|
||||
rewindAtomic();
|
||||
valid = false;
|
||||
}
|
||||
|
||||
void Source::pauseAtomic()
|
||||
{
|
||||
if(valid)
|
||||
{
|
||||
alSourcePause(source);
|
||||
}
|
||||
}
|
||||
|
||||
void Source::resumeAtomic()
|
||||
{
|
||||
if(valid)
|
||||
{
|
||||
alSourcePlay(source);
|
||||
}
|
||||
}
|
||||
|
||||
void Source::rewindAtomic()
|
||||
{
|
||||
if(valid && type == TYPE_STATIC)
|
||||
{
|
||||
alSourceRewind(source);
|
||||
}
|
||||
else if(valid && type == TYPE_STREAM)
|
||||
{
|
||||
decoder->rewind();
|
||||
}
|
||||
}
|
||||
|
||||
void Source::reset(ALenum source)
|
||||
{
|
||||
alSourcei(source, AL_BUFFER, AL_NONE);
|
||||
}
|
||||
|
||||
ALenum Source::getFormat(int channels, int bits) const
|
||||
{
|
||||
if(channels == 1 && bits == 8)
|
||||
return AL_FORMAT_MONO8;
|
||||
else if(channels == 1 && bits == 16)
|
||||
return AL_FORMAT_MONO16;
|
||||
else if(channels == 2 && bits == 8)
|
||||
return AL_FORMAT_STEREO8;
|
||||
else if(channels == 2 && bits == 16)
|
||||
return AL_FORMAT_STEREO16;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Source::streamAtomic(ALuint buffer, love::sound::Decoder * d)
|
||||
{
|
||||
//if(isLooping() && d->isFinished())
|
||||
// d->rewind();
|
||||
|
||||
// Get more sound data.
|
||||
int decoded = d->decode();
|
||||
|
||||
int fmt = getFormat(d->getChannels(), d->getBits());
|
||||
|
||||
//printf("Decoded %i ( %i )", decoded, d->getSize());
|
||||
|
||||
if(decoded > 0 && fmt != 0)
|
||||
{
|
||||
alBufferData(buffer, fmt, d->getBuffer(), decoded, d->getSampleRate());
|
||||
acc++;
|
||||
//printf(" [%i] ", acc);
|
||||
}
|
||||
|
||||
if(decoded < d->getSize() && isLooping())
|
||||
{
|
||||
printf(" Rewinding at %i.\n", acc);
|
||||
d->rewind();
|
||||
acc = 0;
|
||||
}
|
||||
|
||||
return decoded;
|
||||
}
|
||||
|
||||
} // openal
|
||||
} // audio
|
||||
} // love
|
||||
|
||||
@@ -25,7 +25,8 @@
|
||||
#include <common/config.h>
|
||||
#include <common/Object.h>
|
||||
#include <audio/Source.h>
|
||||
#include "Pool.h"
|
||||
#include <sound/SoundData.h>
|
||||
#include <sound/Decoder.h>
|
||||
|
||||
// OpenAL
|
||||
#ifdef LOVE_MACOSX
|
||||
@@ -43,6 +44,7 @@ namespace audio
|
||||
namespace openal
|
||||
{
|
||||
class Audio;
|
||||
class Pool;
|
||||
|
||||
class Source : public love::audio::Source
|
||||
{
|
||||
@@ -50,35 +52,63 @@ namespace openal
|
||||
|
||||
Pool * pool;
|
||||
ALuint source;
|
||||
bool valid;
|
||||
static const unsigned int MAX_BUFFERS = 32;
|
||||
ALuint buffers[MAX_BUFFERS];
|
||||
|
||||
float pitch;
|
||||
float volume;
|
||||
float volume;
|
||||
bool looping;
|
||||
|
||||
love::sound::Decoder * decoder;
|
||||
|
||||
public:
|
||||
Source(Pool * pool);
|
||||
Source(Pool * pool, Audible * audible);
|
||||
Source(Pool * pool, love::sound::SoundData * soundData);
|
||||
Source(Pool * pool, love::sound::Decoder * decoder);
|
||||
virtual ~Source();
|
||||
|
||||
void play();
|
||||
void stop();
|
||||
void pause();
|
||||
void resume();
|
||||
void rewind();
|
||||
bool isStopped() const;
|
||||
void update();
|
||||
virtual love::audio::Source * copy();
|
||||
virtual void play();
|
||||
virtual void stop();
|
||||
virtual void pause();
|
||||
virtual void resume();
|
||||
virtual void rewind();
|
||||
virtual bool isStopped() const;
|
||||
virtual bool isFinished() const;
|
||||
virtual void update();
|
||||
virtual void setPitch(float pitch);
|
||||
virtual float getPitch() const;
|
||||
virtual void setVolume(float volume);
|
||||
virtual float getVolume() const;
|
||||
virtual void setPosition(float * v);
|
||||
virtual void getPosition(float * v) const;
|
||||
virtual void setVelocity(float * v);
|
||||
virtual void getVelocity(float * v) const;
|
||||
virtual void setDirection(float * v);
|
||||
virtual void getDirection(float * v) const;
|
||||
void setLooping(bool looping);
|
||||
bool isLooping() const;
|
||||
|
||||
void setPitch(float pitch);
|
||||
float getPitch() const;
|
||||
void playAtomic();
|
||||
void stopAtomic();
|
||||
void pauseAtomic();
|
||||
void resumeAtomic();
|
||||
void rewindAtomic();
|
||||
|
||||
void setVolume(float volume);
|
||||
float getVolume() const;
|
||||
private:
|
||||
|
||||
void setPosition(float * v);
|
||||
void getPosition(float * v) const;
|
||||
void setVelocity(float * v);
|
||||
void getVelocity(float * v) const;
|
||||
void setDirection(float * v);
|
||||
void getDirection(float * v) const;
|
||||
void reset(ALenum source);
|
||||
|
||||
/**
|
||||
* Gets the OpenAL format identifier based on number of
|
||||
* channels and bits.
|
||||
* @param channels Either 1 (mono) or 2 (stereo).
|
||||
* @param bits Either 8-bit samples, or 16-bit samples.
|
||||
* @return One of AL_FORMAT_*, or 0 if unsupported format.
|
||||
**/
|
||||
ALenum getFormat(int channels, int bits) const;
|
||||
|
||||
int streamAtomic(ALuint buffer, love::sound::Decoder * d);
|
||||
|
||||
}; // Source
|
||||
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
#include "openal/Audio.h"
|
||||
#include "null/Audio.h"
|
||||
|
||||
#include <scripts/audio.lua.h>
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace audio
|
||||
@@ -36,81 +38,31 @@ namespace audio
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_newSound(lua_State * L)
|
||||
{
|
||||
// Convert to File, if necessary.
|
||||
if(lua_isstring(L, 1))
|
||||
luax_convobj(L, 1, "filesystem", "newFile");
|
||||
|
||||
// Convert to SoundData, if necessary.
|
||||
if(luax_istype(L, 1, FILESYSTEM_FILE_T))
|
||||
luax_convobj(L, 1, "sound", "newSoundData");
|
||||
|
||||
love::sound::SoundData * data = luax_checktype<love::sound::SoundData>(L, 1, "SoundData", SOUND_SOUND_DATA_T);
|
||||
Sound * t = instance->newSound(data);
|
||||
luax_newtype(L, "Sound", AUDIO_SOUND_T, (void*)t);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int w_newMusic(lua_State * L)
|
||||
{
|
||||
// Convert to Decoder, if necessary.
|
||||
if(!luax_istype(L, 1, SOUND_DECODER_T))
|
||||
luax_convobj(L, 1, "sound", "newDecoder");
|
||||
|
||||
love::sound::Decoder * decoder = luax_checktype<love::sound::Decoder>(L, 1, "Decoder", SOUND_DECODER_T);
|
||||
Music * t = instance->newMusic(decoder);
|
||||
luax_newtype(L, "Music", AUDIO_MUSIC_T, (void*)t);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_newSource(lua_State * L)
|
||||
int w_newSource1(lua_State * L)
|
||||
{
|
||||
Source * t = 0;
|
||||
|
||||
if(luax_istype(L, 1, AUDIO_SOUND_T))
|
||||
if(luax_istype(L, 1, SOUND_SOUND_DATA_T))
|
||||
t = instance->newSource(luax_totype<love::sound::SoundData>(L, 1, "SoundData", SOUND_SOUND_DATA_T));
|
||||
else if(luax_istype(L, 1, SOUND_DECODER_T))
|
||||
t = instance->newSource(luax_totype<love::sound::Decoder>(L, 1, "Decoder", SOUND_DECODER_T));
|
||||
|
||||
if(t)
|
||||
{
|
||||
Sound * s = luax_checksound(L, 1);
|
||||
t = instance->newSource(s);
|
||||
}
|
||||
else if(luax_istype(L, 1, AUDIO_MUSIC_T))
|
||||
{
|
||||
Music * m = luax_checkmusic(L, 1);
|
||||
t = instance->newSource(m);
|
||||
luax_newtype(L, "Source", AUDIO_SOURCE_T, (void*)t);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(!t)
|
||||
else
|
||||
return luaL_error(L, "No matching overload");
|
||||
|
||||
luax_newtype(L, "Source", AUDIO_SOURCE_T, (void*)t);
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int w_play(lua_State * L)
|
||||
{
|
||||
int argn = lua_gettop(L);
|
||||
|
||||
if(luax_istype(L, 1, AUDIO_SOUND_T))
|
||||
{
|
||||
Sound * s = luax_checksound(L, 1);
|
||||
instance->play(s);
|
||||
return 0;
|
||||
}
|
||||
else if(luax_istype(L, 1, AUDIO_MUSIC_T))
|
||||
{
|
||||
Music * m = luax_checkmusic(L, 1);
|
||||
instance->play(m);
|
||||
return 0;
|
||||
}
|
||||
else if(luax_istype(L, 1, AUDIO_SOURCE_T))
|
||||
{
|
||||
Source * s = luax_checksource(L, 1);
|
||||
instance->play(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return luaL_error(L, "No matching overload");
|
||||
Source * s = luax_checksource(L, 1);
|
||||
instance->play(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int w_stop(lua_State * L)
|
||||
@@ -252,9 +204,7 @@ namespace audio
|
||||
// List of functions to wrap.
|
||||
static const luaL_Reg functions[] = {
|
||||
{ "getNumSources", w_getNumSources },
|
||||
{ "newSound", w_newSound },
|
||||
{ "newMusic", w_newMusic },
|
||||
{ "newSource", w_newSource },
|
||||
{ "newSource1", w_newSource1 },
|
||||
{ "play", w_play },
|
||||
{ "stop", w_stop },
|
||||
{ "pause", w_pause },
|
||||
@@ -273,8 +223,6 @@ namespace audio
|
||||
|
||||
static const lua_CFunction types[] = {
|
||||
luaopen_source,
|
||||
luaopen_music,
|
||||
luaopen_sound,
|
||||
0
|
||||
};
|
||||
|
||||
@@ -316,7 +264,12 @@ namespace audio
|
||||
w.functions = functions;
|
||||
w.types = types;
|
||||
|
||||
return luax_register_module(L, w);
|
||||
luax_register_module(L, w);
|
||||
|
||||
if (luaL_loadbuffer(L, (const char *)audio_lua, sizeof(audio_lua), "audio.lua") == 0)
|
||||
lua_call(L, 0, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // audio
|
||||
|
||||
@@ -22,9 +22,9 @@
|
||||
#define LOVE_AUDIO_WRAP_AUDIO_H
|
||||
|
||||
// LOVE
|
||||
#include <common/config.h>
|
||||
#include <common/runtime.h>
|
||||
#include "Audio.h"
|
||||
#include "wrap_Sound.h"
|
||||
#include "wrap_Music.h"
|
||||
#include "wrap_Source.h"
|
||||
|
||||
namespace love
|
||||
@@ -32,9 +32,7 @@ namespace love
|
||||
namespace audio
|
||||
{
|
||||
int w_getNumSources(lua_State * L);
|
||||
int w_newSound(lua_State * L);
|
||||
int w_newMusic(lua_State * L);
|
||||
int w_newSource(lua_State * L);
|
||||
int w_newSource1(lua_State * L);
|
||||
int w_play(lua_State * L);
|
||||
int w_stop(lua_State * L);
|
||||
int w_pause(lua_State * L);
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2006-2009 LOVE Development Team
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
**/
|
||||
|
||||
#include "wrap_Music.h"
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace audio
|
||||
{
|
||||
Music * luax_checkmusic(lua_State * L, int idx)
|
||||
{
|
||||
return luax_checktype<Music>(L, idx, "Music", AUDIO_MUSIC_T);
|
||||
}
|
||||
|
||||
static const luaL_Reg functions[] = {
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
int luaopen_music(lua_State * L)
|
||||
{
|
||||
return luax_register_type(L, "Music", functions);
|
||||
}
|
||||
|
||||
} // audio
|
||||
} // love
|
||||
@@ -1,37 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2006-2009 LOVE Development Team
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
**/
|
||||
|
||||
#ifndef LOVE_AUDIO_WRAP_MUSIC_H
|
||||
#define LOVE_AUDIO_WRAP_MUSIC_H
|
||||
|
||||
#include <common/runtime.h>
|
||||
#include "Music.h"
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace audio
|
||||
{
|
||||
Music * luax_checkmusic(lua_State * L, int idx);
|
||||
int luaopen_music(lua_State * L);
|
||||
|
||||
} // audio
|
||||
} // love
|
||||
|
||||
#endif // LOVE_AUDIO_WRAP_MUSIC_H
|
||||
@@ -1,42 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2006-2009 LOVE Development Team
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
**/
|
||||
|
||||
#include "wrap_Sound.h"
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace audio
|
||||
{
|
||||
Sound * luax_checksound(lua_State * L, int idx)
|
||||
{
|
||||
return luax_checktype<Sound>(L, idx, "Sound", AUDIO_SOUND_T);
|
||||
}
|
||||
|
||||
static const luaL_Reg functions[] = {
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
int luaopen_sound(lua_State * L)
|
||||
{
|
||||
return luax_register_type(L, "Sound", functions);
|
||||
}
|
||||
|
||||
} // audio
|
||||
} // love
|
||||
@@ -1,37 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2006-2009 LOVE Development Team
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
**/
|
||||
|
||||
#ifndef LOVE_AUDIO_WRAP_SOUND_H
|
||||
#define LOVE_AUDIO_WRAP_SOUND_H
|
||||
|
||||
#include <common/runtime.h>
|
||||
#include "Sound.h"
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace audio
|
||||
{
|
||||
Sound * luax_checksound(lua_State * L, int idx);
|
||||
int luaopen_sound(lua_State * L);
|
||||
|
||||
} // audio
|
||||
} // love
|
||||
|
||||
#endif // LOVE_AUDIO_WRAP_SOUND_H
|
||||
@@ -139,6 +139,13 @@ namespace audio
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_Source_isStopped(lua_State * L)
|
||||
{
|
||||
Source * t = luax_checksource(L, 1);
|
||||
luax_pushboolean(L, t->isStopped());
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const luaL_Reg functions[] = {
|
||||
{ "setPitch", w_Source_setPitch },
|
||||
{ "getPitch", w_Source_getPitch },
|
||||
@@ -146,6 +153,7 @@ namespace audio
|
||||
{ "getVolume", w_Source_getVolume },
|
||||
{ "setLooping", w_Source_setLooping },
|
||||
{ "isLooping", w_Source_isLooping },
|
||||
{ "isStopped", w_Source_isStopped },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@ namespace audio
|
||||
int w_Source_getDirection(lua_State * L);
|
||||
int w_Source_setLooping(lua_State * L);
|
||||
int w_Source_isLooping(lua_State * L);
|
||||
int w_Source_isStopped(lua_State * L);
|
||||
int luaopen_source(lua_State * L);
|
||||
|
||||
} // audio
|
||||
|
||||
@@ -40,7 +40,7 @@ namespace sound
|
||||
* Indicates how many bytes of raw data should be generated at each
|
||||
* call to Decode.
|
||||
**/
|
||||
static const int DEFAULT_BUFFER_SIZE = 1024;
|
||||
static const int DEFAULT_BUFFER_SIZE = 2048;
|
||||
|
||||
/**
|
||||
* Indicates the quality of the sound.
|
||||
@@ -55,7 +55,7 @@ namespace sound
|
||||
/**
|
||||
* 16 bit audio is the default.
|
||||
**/
|
||||
static const int DEFAULT_T = 16;
|
||||
static const int DEFAULT_BITS = 16;
|
||||
|
||||
/**
|
||||
* Creates a deep of itself. The sound stream can (and should) be
|
||||
|
||||
@@ -60,7 +60,11 @@ namespace lullaby
|
||||
bool ModPlugDecoder::accepts(const std::string & ext)
|
||||
{
|
||||
static const std::string supported[] = {
|
||||
"it", "xm", "mod", "wav", ""
|
||||
"699", "abc", "amf", "ams", "dbm", "dmf",
|
||||
"dsm", "far", "it", "j2b", "mdl", "med",
|
||||
"mid", "mod", "mt2", "mtm", "okt", "pat",
|
||||
"psm", "s3m", "stm", "ult", "umx", "wav",
|
||||
"xm", ""
|
||||
};
|
||||
|
||||
for(int i = 0; !(supported[i].empty()); i++)
|
||||
|
||||
@@ -44,7 +44,7 @@ namespace lullaby
|
||||
public:
|
||||
|
||||
ModPlugDecoder(Data * data, const std::string & ext, int bufferSize, int sampleRate);
|
||||
~ModPlugDecoder();
|
||||
virtual ~ModPlugDecoder();
|
||||
|
||||
static bool accepts(const std::string & ext);
|
||||
|
||||
|
||||
@@ -34,9 +34,12 @@ namespace lullaby
|
||||
bool Mpg123Decoder::inited = false;
|
||||
|
||||
Mpg123Decoder::Mpg123Decoder(Data * data, const std::string & ext, int bufferSize, int sampleRate)
|
||||
: Decoder(data, ext, bufferSize, sampleRate), handle(0), islooping(false)
|
||||
: Decoder(data, ext, bufferSize, sampleRate), handle(0)
|
||||
{
|
||||
|
||||
data_size = data->getSize();
|
||||
data_offset = 0;
|
||||
|
||||
int ret;
|
||||
|
||||
if(!inited)
|
||||
@@ -57,21 +60,11 @@ namespace lullaby
|
||||
ret = mpg123_format(handle, sampleRate, MPG123_STEREO, MPG123_ENC_SIGNED_16);
|
||||
if (ret != MPG123_OK)
|
||||
throw love::Exception("Could not set output format.");
|
||||
size_t numbytes = 0;
|
||||
ret = mpg123_decode(handle, (unsigned char*)data->getData(), data->getSize(), NULL, 0, &numbytes);
|
||||
|
||||
if(ret == MPG123_NEW_FORMAT)
|
||||
{
|
||||
long rate;
|
||||
int channels;
|
||||
int encoding;
|
||||
mpg123_getformat(handle, &rate, &channels, &encoding);
|
||||
}
|
||||
else if(ret != 0)
|
||||
{
|
||||
throw love::Exception(mpg123_strerror(handle));
|
||||
}
|
||||
|
||||
ret = feed(16384);
|
||||
|
||||
if (ret != MPG123_OK && ret != MPG123_DONE)
|
||||
throw love::Exception("Could not feed!");
|
||||
}
|
||||
|
||||
Mpg123Decoder::~Mpg123Decoder()
|
||||
@@ -108,26 +101,51 @@ namespace lullaby
|
||||
|
||||
int Mpg123Decoder::decode()
|
||||
{
|
||||
size_t numbytes;
|
||||
int r = mpg123_read(handle, (unsigned char*) buffer, bufferSize, &numbytes);
|
||||
|
||||
if (r == MPG123_DONE || r != MPG123_OK)
|
||||
int size = 0;
|
||||
bool done = false;
|
||||
|
||||
while(size < bufferSize && !done && !eof)
|
||||
{
|
||||
if ( r == MPG123_NEED_MORE && islooping )
|
||||
{
|
||||
islooping = false;
|
||||
size_t numbytes = 0;
|
||||
mpg123_decode(handle, (unsigned char*) data->getData(), data->getSize(), (unsigned char*) buffer, bufferSize, &numbytes);
|
||||
}
|
||||
else
|
||||
size_t numbytes = 0;
|
||||
|
||||
int r = mpg123_read(handle, (unsigned char*) buffer + size, bufferSize - size, &numbytes);
|
||||
|
||||
switch(r)
|
||||
{
|
||||
case MPG123_NEW_FORMAT:
|
||||
continue;
|
||||
case MPG123_NEED_MORE:
|
||||
{
|
||||
int v = feed(8192);
|
||||
|
||||
switch(v)
|
||||
{
|
||||
case MPG123_OK:
|
||||
continue;
|
||||
case MPG123_DONE:
|
||||
if(numbytes == 0)
|
||||
eof = true;
|
||||
break;
|
||||
default:
|
||||
done = true;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
case MPG123_OK:
|
||||
size += numbytes;
|
||||
continue;
|
||||
case MPG123_DONE:
|
||||
// Apparently, mpg123_read does not return MPG123_DONE, but
|
||||
// let's keep it here anyway.
|
||||
eof = true;
|
||||
numbytes = 0;
|
||||
default:
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return numbytes;
|
||||
return size;
|
||||
}
|
||||
|
||||
bool Mpg123Decoder::seek(float s)
|
||||
@@ -139,11 +157,16 @@ namespace lullaby
|
||||
|
||||
bool Mpg123Decoder::rewind()
|
||||
{
|
||||
if(mpg123_seek(handle, 0, SEEK_SET) >= 0)
|
||||
return false;
|
||||
islooping = true;
|
||||
eof = false;
|
||||
return true;
|
||||
off_t offset;
|
||||
|
||||
if(mpg123_feedseek(handle, 0, SEEK_SET, &offset) >= 0)
|
||||
{
|
||||
data_offset = offset;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Mpg123Decoder::isSeekable()
|
||||
@@ -160,7 +183,23 @@ namespace lullaby
|
||||
{
|
||||
return 16;
|
||||
}
|
||||
|
||||
int Mpg123Decoder::feed(int bytes)
|
||||
{
|
||||
int remaining = data_size - data_offset;
|
||||
|
||||
if(remaining <= 0)
|
||||
return MPG123_DONE;
|
||||
|
||||
int feed_bytes = remaining < bytes ? remaining : bytes;
|
||||
|
||||
int r = mpg123_feed(handle, (unsigned char*)data->getData() + data_offset, feed_bytes);
|
||||
|
||||
if(r == MPG123_OK || r == MPG123_DONE)
|
||||
data_offset += feed_bytes;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
} // lullaby
|
||||
} // sound
|
||||
|
||||
@@ -43,13 +43,15 @@ namespace lullaby
|
||||
private:
|
||||
|
||||
mpg123_handle * handle;
|
||||
bool islooping;
|
||||
static bool inited;
|
||||
|
||||
int data_offset;
|
||||
int data_size;
|
||||
|
||||
public:
|
||||
|
||||
Mpg123Decoder(Data * data, const std::string & ext, int bufferSize, int sampleRate);
|
||||
~Mpg123Decoder();
|
||||
virtual ~Mpg123Decoder();
|
||||
|
||||
static bool accepts(const std::string & ext);
|
||||
static void quit();
|
||||
@@ -62,6 +64,10 @@ namespace lullaby
|
||||
int getChannels() const;
|
||||
int getBits() const;
|
||||
|
||||
private:
|
||||
|
||||
int feed(int bytes);
|
||||
|
||||
}; // Decoder
|
||||
|
||||
} // lullaby
|
||||
|
||||
@@ -55,9 +55,9 @@ namespace lullaby
|
||||
// Find a suitable decoder here, and return it.
|
||||
if(ModPlugDecoder::accepts(ext))
|
||||
decoder = new ModPlugDecoder(data, ext, bufferSize, sampleRate);
|
||||
else if (Mpg123Decoder::accepts(ext))
|
||||
else if(Mpg123Decoder::accepts(ext))
|
||||
decoder = new Mpg123Decoder(data, ext, bufferSize, sampleRate);
|
||||
else if (VorbisDecoder::accepts(ext))
|
||||
else if(VorbisDecoder::accepts(ext))
|
||||
decoder = new VorbisDecoder(data, ext, bufferSize, sampleRate);
|
||||
/*else if (FLACDecoder::accepts(ext))
|
||||
decoder = new FLACDecoder(data, ext, bufferSize, sampleRate);*/
|
||||
|
||||
@@ -182,42 +182,20 @@ namespace lullaby
|
||||
|
||||
int VorbisDecoder::decode()
|
||||
{
|
||||
int bits = this->getBits();
|
||||
int size = 0;
|
||||
int section;
|
||||
int result;
|
||||
|
||||
if(bits == 16)
|
||||
bits = 2;
|
||||
else
|
||||
bits = 1;
|
||||
|
||||
while(size < bufferSize)
|
||||
{
|
||||
result = ov_read(&handle, (char*) buffer + size, bufferSize - size, endian, bits, 1, §ion);
|
||||
int result = ov_read(&handle, (char*) buffer + size, bufferSize - size, endian, (getBits() == 16 ? 2 : 1), 1, 0);
|
||||
|
||||
if(result > 0)
|
||||
size += result;
|
||||
else if(result < 0)
|
||||
{
|
||||
switch(result)
|
||||
{
|
||||
case OV_EREAD:
|
||||
throw love::Exception("Vorbis read: Read from media");
|
||||
case OV_ENOTVORBIS:
|
||||
throw love::Exception("Vorbis read: Not Vorbis data");
|
||||
case OV_EVERSION:
|
||||
throw love::Exception("Vorbis read: Vorbis version mismatch");
|
||||
case OV_EBADHEADER:
|
||||
throw love::Exception("Vorbis read: Invalid Vorbis header");
|
||||
case OV_EFAULT:
|
||||
throw love::Exception("Vorbis read: Internal logic fault (bug or heap/stack corruption)");
|
||||
default:
|
||||
throw love::Exception("Vorbis read: Unknown error");
|
||||
}
|
||||
}
|
||||
else
|
||||
if(result == OV_HOLE)
|
||||
continue;
|
||||
else if(result <= OV_EREAD)
|
||||
return -1;
|
||||
else if(result == 0)
|
||||
break;
|
||||
else if(result > 0)
|
||||
size += result;
|
||||
}
|
||||
|
||||
if(oggFile.dataSize - oggFile.dataRead == 0)
|
||||
@@ -256,7 +234,8 @@ namespace lullaby
|
||||
bool VorbisDecoder::rewind()
|
||||
{
|
||||
eof = false;
|
||||
return this->seek(0);
|
||||
ov_pcm_seek(&handle, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VorbisDecoder::isSeekable()
|
||||
|
||||
@@ -56,7 +56,7 @@ namespace lullaby
|
||||
public:
|
||||
|
||||
VorbisDecoder(Data * data, const std::string & ext, int bufferSize, int sampleRate);
|
||||
~VorbisDecoder();
|
||||
virtual ~VorbisDecoder();
|
||||
|
||||
static bool accepts(const std::string & ext);
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace sound
|
||||
{
|
||||
int samples = luaL_checkint(L, 1);
|
||||
int sampleRate = luaL_optint(L, 2, Decoder::DEFAULT_SAMPLE_RATE);
|
||||
int bits = luaL_optint(L, 3, Decoder::DEFAULT_T);
|
||||
int bits = luaL_optint(L, 3, Decoder::DEFAULT_BITS);
|
||||
int channels = luaL_optint(L, 4, Decoder::DEFAULT_CHANNELS);
|
||||
|
||||
try
|
||||
|
||||
Reference in New Issue
Block a user