Audaspace:

* Added a stopCallback function that is called when the end of a sound is reached.
* Fixed the scrubbing not working.
* Minor SoundActuator cleanup.
This commit is contained in:
Joerg Mueller 2010-08-02 18:22:34 +00:00
parent bce3a49e2e
commit 86fc34b924
16 changed files with 347 additions and 7 deletions

View File

@ -68,6 +68,12 @@ struct AUD_OpenALHandle : AUD_Handle
/// The loop count of the source.
int loopcount;
/// The stop callback.
stopCallback stop;
/// Stop callback data.
void* stop_data;
};
struct AUD_OpenALBufferedFactory
@ -131,13 +137,9 @@ void AUD_OpenALDevice::updateStreams()
{
// for all sounds
AUD_HandleIterator it = m_playingSounds->begin();
while(it != m_playingSounds->end())
for(AUD_HandleIterator it = m_playingSounds->begin(); it != m_playingSounds->end(); it++)
{
sound = *it;
// increment the iterator to make sure it's valid,
// in case the sound gets deleted after stopping
++it;
// is it a streamed sound?
if(!sound->isBuffered)
@ -227,12 +229,21 @@ void AUD_OpenALDevice::updateStreams()
// if it really stopped
if(sound->data_end)
{
if(sound->stop)
sound->stop(sound->stop_data);
// increment the iterator to the next value,
// because the sound gets deleted in the list here.
++it;
// pause or
if(sound->keep)
pause(sound);
// stop
else
stop(sound);
// decrement again, so that we get the next sound in the
// next loop run
--it;
}
// continue playing
else
@ -1012,6 +1023,20 @@ bool AUD_OpenALDevice::setLoopCount(AUD_Handle* handle, int count)
return result;
}
bool AUD_OpenALDevice::setStopCallback(AUD_Handle* handle, stopCallback callback, void* data)
{
lock();
bool result = isValid(handle);
if(result)
{
AUD_OpenALHandle* h = (AUD_OpenALHandle*)handle;
h->stop = callback;
h->stop_data = data;
}
unlock();
return result;
}
/* AUD_XXX Temorary disabled
bool AUD_OpenALDevice::bufferFactory(void *value)

View File

@ -160,6 +160,7 @@ public:
virtual bool setPitch(AUD_Handle* handle, float pitch);
virtual int getLoopCount(AUD_Handle* handle);
virtual bool setLoopCount(AUD_Handle* handle, int count);
virtual bool setStopCallback(AUD_Handle* handle, stopCallback callback = NULL, void* data = NULL);
virtual AUD_Vector3 getListenerLocation() const;
virtual void setListenerLocation(const AUD_Vector3& location);

View File

@ -60,6 +60,7 @@ bool g_pyinitialized = false;
#include "AUD_ReadDevice.h"
#include "AUD_IReader.h"
#include "AUD_SequencerFactory.h"
#include "AUD_SilenceFactory.h"
#ifdef WITH_SDL
#include "AUD_SDLDevice.h"
@ -845,6 +846,32 @@ float* AUD_readSoundBuffer(const char* filename, float low, float high,
return result;
}
static void pauseSound(AUD_Channel* handle)
{
assert(AUD_device);
AUD_device->pause(handle);
}
AUD_Channel* AUD_pauseAfter(AUD_Channel* handle, float seconds)
{
assert(AUD_device);
AUD_SilenceFactory silence;
AUD_LimiterFactory limiter(&silence, 0, seconds);
try
{
AUD_Channel* channel = AUD_device->play(&limiter);
AUD_device->setStopCallback(channel, (stopCallback)pauseSound, handle);
return channel;
}
catch(AUD_Exception&)
{
return NULL;
}
}
AUD_Sound* AUD_createSequencer(void* data, AUD_volumeFunction volume)
{
/* AUD_XXX should be this: but AUD_createSequencer is called before the device

View File

@ -463,6 +463,14 @@ extern float* AUD_readSoundBuffer(const char* filename, float low, float high,
float sthreshold, int samplerate,
int* length);
/**
* Pauses a playing sound after a specific amount of time.
* \param handle The handle to the sound.
* \param time The time in seconds.
* \return The silence handle.
*/
extern AUD_Channel* AUD_pauseAfter(AUD_Channel* handle, float seconds);
extern AUD_Sound* AUD_createSequencer(void* data, AUD_volumeFunction volume);
extern void AUD_destroySequencer(AUD_Sound* sequencer);

View File

@ -34,6 +34,8 @@ struct AUD_Handle
{
};
typedef void (*stopCallback)(void*);
/**
* This class represents an output device for sound sources.
* Output devices may be several backends such as plattform independand like
@ -225,6 +227,18 @@ public:
* - false if the handle is invalid.
*/
virtual bool setLoopCount(AUD_Handle* handle, int count)=0;
/**
* Sets the callback function that's called when the end of a playing sound
* is reached.
* \param handle The sound handle.
* \param callback The callback function.
* \param data The data that should be passed to the callback function.
* \return
* - true if the handle is valid.
* - false if the handle is invalid.
*/
virtual bool setStopCallback(AUD_Handle* handle, stopCallback callback = 0, void* data = 0)=0;
};
#endif //AUD_IDevice

View File

@ -133,3 +133,8 @@ bool AUD_NULLDevice::setLoopCount(AUD_Handle* handle, int count)
{
return false;
}
bool AUD_NULLDevice::setStopCallback(AUD_Handle* handle, stopCallback callback, void* data)
{
return false;
}

View File

@ -59,6 +59,7 @@ public:
virtual bool setPitch(AUD_Handle* handle, float pitch);
virtual int getLoopCount(AUD_Handle* handle);
virtual bool setLoopCount(AUD_Handle* handle, int count);
virtual bool setStopCallback(AUD_Handle* handle, stopCallback callback = 0, void* data = 0);
};
#endif //AUD_NULLDEVICE

View File

@ -0,0 +1,37 @@
/*
* $Id$
*
* ***** BEGIN LGPL LICENSE BLOCK *****
*
* Copyright 2009 Jörg Hermann Müller
*
* This file is part of AudaSpace.
*
* AudaSpace is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* AudaSpace 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
*
* ***** END LGPL LICENSE BLOCK *****
*/
#include "AUD_SilenceFactory.h"
#include "AUD_SilenceReader.h"
#include "AUD_Space.h"
AUD_SilenceFactory::AUD_SilenceFactory()
{
}
AUD_IReader* AUD_SilenceFactory::createReader() const
{
return new AUD_SilenceReader();
}

View File

@ -0,0 +1,50 @@
/*
* $Id$
*
* ***** BEGIN LGPL LICENSE BLOCK *****
*
* Copyright 2009 Jörg Hermann Müller
*
* This file is part of AudaSpace.
*
* AudaSpace is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* AudaSpace 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
*
* ***** END LGPL LICENSE BLOCK *****
*/
#ifndef AUD_SILENCEFACTORY
#define AUD_SILENCEFACTORY
#include "AUD_IFactory.h"
/**
* This factory creates a reader that plays a sine tone.
*/
class AUD_SilenceFactory : public AUD_IFactory
{
private:
// hide copy constructor and operator=
AUD_SilenceFactory(const AUD_SilenceFactory&);
AUD_SilenceFactory& operator=(const AUD_SilenceFactory&);
public:
/**
* Creates a new silence factory.
*/
AUD_SilenceFactory();
virtual AUD_IReader* createReader() const;
};
#endif //AUD_SILENCEFACTORY

View File

@ -0,0 +1,74 @@
/*
* $Id$
*
* ***** BEGIN LGPL LICENSE BLOCK *****
*
* Copyright 2009 Jörg Hermann Müller
*
* This file is part of AudaSpace.
*
* AudaSpace is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* AudaSpace 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
*
* ***** END LGPL LICENSE BLOCK *****
*/
#include "AUD_SilenceReader.h"
#include <cstring>
AUD_SilenceReader::AUD_SilenceReader() :
m_position(0)
{
}
bool AUD_SilenceReader::isSeekable() const
{
return true;
}
void AUD_SilenceReader::seek(int position)
{
m_position = position;
}
int AUD_SilenceReader::getLength() const
{
return -1;
}
int AUD_SilenceReader::getPosition() const
{
return m_position;
}
AUD_Specs AUD_SilenceReader::getSpecs() const
{
AUD_Specs specs;
specs.rate = AUD_RATE_44100;
specs.channels = AUD_CHANNELS_MONO;
return specs;
}
void AUD_SilenceReader::read(int & length, sample_t* & buffer)
{
// resize if necessary
if(m_buffer.getSize() < length * sizeof(sample_t))
{
m_buffer.resize(length * sizeof(sample_t));
memset(m_buffer.getBuffer(), 0, m_buffer.getSize());
}
buffer = m_buffer.getBuffer();
m_position += length;
}

View File

@ -0,0 +1,71 @@
/*
* $Id$
*
* ***** BEGIN LGPL LICENSE BLOCK *****
*
* Copyright 2009 Jörg Hermann Müller
*
* This file is part of AudaSpace.
*
* AudaSpace is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* AudaSpace 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
*
* ***** END LGPL LICENSE BLOCK *****
*/
#ifndef AUD_SILENCEREADER
#define AUD_SILENCEREADER
#include "AUD_IReader.h"
#include "AUD_Buffer.h"
/**
* This class is used for sine tone playback.
* The output format is in the 16 bit format and stereo, the sample rate can be
* specified.
* As the two channels both play the same the output could also be mono, but
* in most cases this will result in having to resample for output, so stereo
* sound is created directly.
*/
class AUD_SilenceReader : public AUD_IReader
{
private:
/**
* The current position in samples.
*/
int m_position;
/**
* The playback buffer.
*/
AUD_Buffer m_buffer;
// hide copy constructor and operator=
AUD_SilenceReader(const AUD_SilenceReader&);
AUD_SilenceReader& operator=(const AUD_SilenceReader&);
public:
/**
* Creates a new reader.
*/
AUD_SilenceReader();
virtual bool isSeekable() const;
virtual void seek(int position);
virtual int getLength() const;
virtual int getPosition() const;
virtual AUD_Specs getSpecs() const;
virtual void read(int & length, sample_t* & buffer);
};
#endif //AUD_SILENCEREADER

View File

@ -45,6 +45,12 @@ struct AUD_SoftwareHandle : AUD_Handle
/// The loop count of the source.
int loopcount;
/// The stop callback.
stopCallback stop;
/// Stop callback data.
void* stop_data;
};
typedef std::list<AUD_SoftwareHandle*>::iterator AUD_HandleIterator;
@ -151,6 +157,9 @@ void AUD_SoftwareDevice::mix(data_t* buffer, int length)
// in case the end of the sound is reached
if(pos < length)
{
if(sound->stop)
sound->stop(sound->stop_data);
if(sound->keep)
pause(sound);
else
@ -488,3 +497,17 @@ bool AUD_SoftwareDevice::setLoopCount(AUD_Handle* handle, int count)
unlock();
return result;
}
bool AUD_SoftwareDevice::setStopCallback(AUD_Handle* handle, stopCallback callback, void* data)
{
lock();
bool result = isValid(handle);
if(result)
{
AUD_SoftwareHandle* h = (AUD_SoftwareHandle*)handle;
h->stop = callback;
h->stop_data = data;
}
unlock();
return result;
}

View File

@ -132,6 +132,7 @@ public:
virtual bool setPitch(AUD_Handle* handle, float pitch);
virtual int getLoopCount(AUD_Handle* handle);
virtual bool setLoopCount(AUD_Handle* handle, int count);
virtual bool setStopCallback(AUD_Handle* handle, stopCallback callback = NULL, void* data = NULL);
};
#endif //AUD_SOFTWAREDEVICE

View File

@ -438,6 +438,10 @@ void sound_seek_scene(struct bContext *C)
else
AUD_seek(scene->sound_scene_handle, CFRA / FPS);
AUD_resume(scene->sound_scene_handle);
if(AUD_getStatus(scene->sound_scrub_handle) != AUD_STATUS_INVALID)
AUD_seek(scene->sound_scrub_handle, 0);
else
scene->sound_scrub_handle = AUD_pauseAfter(scene->sound_scene_handle, 1 / FPS);
}
else
{

View File

@ -797,6 +797,7 @@ typedef struct Scene {
void *sound_scene;
void *sound_scene_handle;
void *sound_scrub_handle;
void *fps_info; /* (runtime) info/cache used for presenting playback framerate info to the user */

View File

@ -107,14 +107,12 @@ public:
static int pyattr_set_audposition(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
static int pyattr_set_gain(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
static int pyattr_set_pitch(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
static int pyattr_set_rollOffFactor(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
static int pyattr_set_type(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
static PyObject* pyattr_get_3d_property(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
static PyObject* pyattr_get_audposition(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
static PyObject* pyattr_get_gain(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
static PyObject* pyattr_get_pitch(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
static PyObject* pyattr_get_rollOffFactor(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
static PyObject* pyattr_get_type(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
#endif // DISABLE_PYTHON