Added the trunk/branches/tags directories at repository root, and moved previous root into trunk/
git-svn-id: https://sfml.svn.sourceforge.net/svnroot/sfml/trunk@1002 4e206d99-4929-0410-ac5d-dfc041789085
This commit is contained in:
commit
2f524481c1
974 changed files with 295448 additions and 0 deletions
550
DSFML/import/dsfml/audio/soundstream.d
Normal file
550
DSFML/import/dsfml/audio/soundstream.d
Normal file
|
@ -0,0 +1,550 @@
|
|||
/*
|
||||
* DSFML - SFML Library binding in D language.
|
||||
* Copyright (C) 2008 Julien Dagorn (sirjulio13@gmail.com)
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
module dsfml.audio.soundstream;
|
||||
|
||||
import dsfml.system.alloc;
|
||||
import dsfml.system.common;
|
||||
import dsfml.system.vector3;
|
||||
import dsfml.system.linkedlist;
|
||||
import dsfml.system.lock;
|
||||
import dsfml.system.mutex;
|
||||
import dsfml.system.sleep;
|
||||
import dsfml.system.thread;
|
||||
|
||||
import dsfml.audio.sound;
|
||||
import dsfml.audio.soundstatus;
|
||||
|
||||
/**
|
||||
* SoundStream is a streamed sound, ie samples are acquired
|
||||
* while the sound is playing. Use it for big sounds that would
|
||||
* require hundreds of MB in memory, or for streaming sound from the network.
|
||||
*
|
||||
* SoundStream is a base class and cannot be instanciated directly.
|
||||
*
|
||||
* $(B onGetData override will be called by a different thread, take care of synchronization issues.) onStart is called by the thread which called .play().
|
||||
*
|
||||
* ------------------------
|
||||
* class MySoundStream : SoundStream
|
||||
* {
|
||||
* this()
|
||||
* {
|
||||
* super(2, 44100); // you need to initialize the base class before any operation.
|
||||
* }
|
||||
* protected bool onGetData(out short[] data)
|
||||
* {
|
||||
* //You need to fill data array with some samples
|
||||
*
|
||||
* return true; //or false if you want to stop playback
|
||||
* }
|
||||
*
|
||||
* protected bool onStart()
|
||||
* {
|
||||
* return true;
|
||||
* }
|
||||
* }
|
||||
* ------------------------
|
||||
*/
|
||||
abstract class SoundStream : DSFMLObject
|
||||
{
|
||||
override void dispose()
|
||||
{
|
||||
stop();
|
||||
sfSoundStream_Destroy(m_ptr);
|
||||
s_instances.remove(m_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Start playing the stream
|
||||
*/
|
||||
void play()
|
||||
{
|
||||
m_flag = true;
|
||||
sfSoundStream_Play(m_ptr);
|
||||
|
||||
if (getStatus() != SoundStatus.PAUSED)
|
||||
{
|
||||
m_t = new Thread(&threadPoll);
|
||||
m_t.launch();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Pause the stream
|
||||
*/
|
||||
void pause()
|
||||
{
|
||||
sfSoundStream_Pause(m_ptr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop the stream
|
||||
*/
|
||||
void stop()
|
||||
{
|
||||
m_flag = false;
|
||||
sfSoundStream_Stop(m_ptr);
|
||||
m_t.wait();
|
||||
if (m_dummy !is null)
|
||||
delete m_dummy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get number of channels of the stream
|
||||
*
|
||||
* Returns:
|
||||
* number of channels
|
||||
*/
|
||||
uint getChannelsCount()
|
||||
{
|
||||
return m_channelsCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the sample rate of the stream
|
||||
*
|
||||
* Returns:
|
||||
* sample rate
|
||||
*/
|
||||
uint getSampleRate()
|
||||
{
|
||||
return m_sampleRate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current status of the stream
|
||||
*
|
||||
* Returns:
|
||||
* Current stream status
|
||||
*/
|
||||
SoundStatus getStatus()
|
||||
{
|
||||
return sfSoundStream_GetStatus(m_ptr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the sound pitch.
|
||||
* The default pitch is 1
|
||||
*
|
||||
* Params:
|
||||
* pitch = New pitch
|
||||
*/
|
||||
void setPitch(float pitch)
|
||||
{
|
||||
sfSoundStream_SetPitch(m_ptr, pitch);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the sound volume.
|
||||
* The default volume is 100
|
||||
*
|
||||
* Params:
|
||||
* volume = Volume (in range [0, 100])
|
||||
*/
|
||||
void setVolume(float volume)
|
||||
in
|
||||
{
|
||||
assert(volume >= 0.f && volume <= 100.f);
|
||||
}
|
||||
body
|
||||
{
|
||||
sfSoundStream_SetVolume(m_ptr, volume);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the sound position (take 3 values).
|
||||
* The default position is (0, 0, 0)
|
||||
*
|
||||
* Params:
|
||||
* x, y, z = Position of the sound in the world
|
||||
*/
|
||||
|
||||
void setPosition(float x, float y, float z)
|
||||
{
|
||||
sfSoundStream_SetPosition(m_ptr, x, y, z);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the sound position (take 3 values).
|
||||
* The default position is (0, 0, 0)
|
||||
*
|
||||
* Params:
|
||||
* vec = Position of the sound in the world
|
||||
*
|
||||
*/
|
||||
|
||||
void setPosition(Vector3f vec)
|
||||
{
|
||||
sfSoundStream_SetPosition(m_ptr, vec.x, vec.y, vec.z);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the minimum distance - closer than this distance,
|
||||
* the listener will hear the sound at its maximum volume.
|
||||
* The default minimum distance is 1.0
|
||||
*
|
||||
* Params:
|
||||
* minDistance = New minimum distance for the sound
|
||||
*/
|
||||
void setMinDistance(float minDistance)
|
||||
{
|
||||
sfSoundStream_SetMinDistance(m_ptr, minDistance);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the attenuation factor - the higher the attenuation, the
|
||||
* more the sound will be attenuated with distance from listener.
|
||||
* The default attenuation factor 1.0
|
||||
*
|
||||
* Params:
|
||||
* attenuation = New attenuation factor for the sound
|
||||
*
|
||||
*/
|
||||
void setAttenuation(float attenuation)
|
||||
{
|
||||
sfSoundStream_SetAttenuation(m_ptr, attenuation);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the pitch
|
||||
*
|
||||
* Returns:
|
||||
* Pitch value
|
||||
*/
|
||||
|
||||
float getPitch()
|
||||
{
|
||||
return sfSoundStream_GetPitch(m_ptr);
|
||||
}
|
||||
/**
|
||||
* Get the volume
|
||||
*
|
||||
* Returns:
|
||||
* Volume value (in range [1, 100])
|
||||
*
|
||||
*/
|
||||
|
||||
float getVolume()
|
||||
{
|
||||
return sfSoundStream_GetVolume(m_ptr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the sound position
|
||||
*
|
||||
* Returns:
|
||||
* Sound position
|
||||
*/
|
||||
Vector3f getPosition()
|
||||
{
|
||||
Vector3f vec;
|
||||
sfSoundStream_GetPosition(m_ptr, &vec.x, &vec.y, &vec.z);
|
||||
return vec;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the minimum distance
|
||||
*
|
||||
* Returns:
|
||||
* Get the minimum distance of the sound
|
||||
*/
|
||||
float getMinDistance()
|
||||
{
|
||||
return sfSoundStream_GetMinDistance(m_ptr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the attenuation
|
||||
*
|
||||
* Returns:
|
||||
* Get the attenuation of the sound
|
||||
*/
|
||||
float getAttenuation()
|
||||
{
|
||||
return sfSoundStream_GetAttenuation(m_ptr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current playing offset of the stream
|
||||
*
|
||||
* Returns:
|
||||
* current playing offset, in seconds.
|
||||
*/
|
||||
float getPlayingOffset()
|
||||
{
|
||||
return sfSoundStream_GetPlayingOffset(m_ptr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tell whether or not the stream is looping
|
||||
*
|
||||
* Returns:
|
||||
* True if the music is looping, false otherwise
|
||||
*/
|
||||
bool getLoop()
|
||||
{
|
||||
if (m_ptr !is null)
|
||||
return cast(bool)sfSoundStream_GetLoop(m_ptr);
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the stream loop state.
|
||||
*
|
||||
* Disabled by default.
|
||||
*
|
||||
* Params:
|
||||
* loop = true to play in loop, false to play once
|
||||
*/
|
||||
void setLoop(bool loop)
|
||||
{
|
||||
if (m_ptr !is null)
|
||||
sfSoundStream_SetLoop(m_ptr, loop);
|
||||
}
|
||||
protected:
|
||||
/**
|
||||
* Protected constructor
|
||||
*
|
||||
* Params:
|
||||
* channelsCount = number of channel
|
||||
* sampleRate = sample rate of the stream
|
||||
*
|
||||
*/
|
||||
this(uint channelsCount, uint sampleRate)
|
||||
{
|
||||
m_channelsCount = channelsCount;
|
||||
m_sampleRate = sampleRate;
|
||||
super(sfSoundStream_Create(&externalOnStart, &externalOnGetData, channelsCount, sampleRate, &m_id));
|
||||
|
||||
m_mutex = new Mutex();
|
||||
|
||||
m_samples = new LinkedList!(Data);
|
||||
|
||||
m_t = new Thread(&this.threadPoll);
|
||||
|
||||
m_id = ++s_seed;
|
||||
s_instances[m_id] = this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called each time the stream restart
|
||||
*
|
||||
* Returns:
|
||||
* false to abort the playback
|
||||
*/
|
||||
abstract bool onStart();
|
||||
|
||||
/**
|
||||
* Called each time the stream needs new data.
|
||||
* This method will be call by an other thread, take care of possible synchronisation issues.
|
||||
*
|
||||
* Params:
|
||||
* data = array of samples to stream
|
||||
*
|
||||
* Returns:
|
||||
* true to continue streaming, false to stop
|
||||
*/
|
||||
abstract bool onGetData(out short[] data);
|
||||
private:
|
||||
|
||||
// Called sync when user calling play()
|
||||
extern(C) static int externalOnStart(void* user)
|
||||
{
|
||||
int id;
|
||||
if ((id = *cast(int*) user) in s_instances)
|
||||
{
|
||||
SoundStream temp = s_instances[id];
|
||||
return (temp.m_flag = temp.onStart());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// C Thread callback (no allocation can be done)
|
||||
extern (C) static int externalOnGetData(sfSoundStreamChunk* data, void* user)
|
||||
{
|
||||
int id, flag = false;
|
||||
// Get calling soundStream
|
||||
if ((id = *cast(int*) user) in s_instances)
|
||||
{
|
||||
SoundStream temp = s_instances[id];
|
||||
//if no samples are available but streaming is not stopped, we sleep the thread
|
||||
while (temp.m_samples.empty && temp.m_flag)
|
||||
sleep(0.01f);
|
||||
|
||||
scope Lock l = new Lock(temp.m_mutex);
|
||||
if (!temp.m_samples.empty)
|
||||
{
|
||||
if (temp.m_dummy !is null)
|
||||
delete temp.m_dummy;
|
||||
|
||||
temp.m_dummy = temp.m_samples.dequeue;
|
||||
|
||||
if ((flag = temp.m_dummy.Flag) == true)
|
||||
{
|
||||
data.Samples = temp.m_dummy.Samples.ptr;
|
||||
data.NbSamples = temp.m_dummy.Samples.length;
|
||||
}
|
||||
else
|
||||
{
|
||||
data.Samples = null;
|
||||
data.NbSamples = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
|
||||
// Managed thread loop
|
||||
void threadPoll(void* dummy)
|
||||
{
|
||||
short[] data;
|
||||
bool ret = true;
|
||||
// while streaming is active ...
|
||||
while (ret && m_flag)
|
||||
{
|
||||
{
|
||||
scope Lock l = new Lock(m_mutex);
|
||||
// see how many samples are available (keep always 2 samples ready)
|
||||
if (m_samples.getCount < 2)
|
||||
{
|
||||
// if we need new samples, lock and call derived class
|
||||
ret = onGetData(data);
|
||||
m_samples.enqueue(new Data(data, ret));
|
||||
}
|
||||
}
|
||||
sleep(0.1f);
|
||||
}
|
||||
}
|
||||
|
||||
private class Data
|
||||
{
|
||||
short[] Samples;
|
||||
bool Flag;
|
||||
|
||||
mixin Alloc;
|
||||
|
||||
this (short[] samples, bool flag)
|
||||
{
|
||||
this.Samples = samples;
|
||||
this.Flag = flag;
|
||||
}
|
||||
}
|
||||
|
||||
Thread m_t;
|
||||
Mutex m_mutex;
|
||||
LinkedList!(Data) m_samples;
|
||||
Data m_dummy;
|
||||
|
||||
bool m_flag;
|
||||
|
||||
uint m_channelsCount;
|
||||
uint m_sampleRate;
|
||||
|
||||
int m_id;
|
||||
static SoundStream[int] s_instances;
|
||||
static int s_seed = 0;
|
||||
|
||||
// External ====================================================================
|
||||
|
||||
extern (C)
|
||||
{
|
||||
struct sfSoundStreamChunk{ short* Samples; uint NbSamples; }
|
||||
|
||||
alias int function(void*) sfSoundStreamStartCallback;
|
||||
alias int function (sfSoundStreamChunk*, void*) sfSoundStreamGetDataCallback;
|
||||
|
||||
typedef void* function(sfSoundStreamStartCallback, sfSoundStreamGetDataCallback, uint, uint, void*) pf_sfSoundStream_Create;
|
||||
typedef void function(void*) pf_sfSoundStream_Destroy;
|
||||
typedef void function(void*) pf_sfSoundStream_Play;
|
||||
typedef void function(void*) pf_sfSoundStream_Pause;
|
||||
typedef void function(void*) pf_sfSoundStream_Stop;
|
||||
typedef SoundStatus function(void*) pf_sfSoundStream_GetStatus;
|
||||
typedef uint function(void*) pf_sfSoundStream_GetChannelsCount;
|
||||
typedef uint function(void*) pf_sfSoundStream_GetSampleRate;
|
||||
typedef void function(void*, float) pf_sfSoundStream_SetPitch;
|
||||
typedef void function(void*, float) pf_sfSoundStream_SetVolume;
|
||||
typedef void function(void*, float, float, float) pf_sfSoundStream_SetPosition;
|
||||
typedef void function(void*, float) pf_sfSoundStream_SetMinDistance;
|
||||
typedef void function(void*, float) pf_sfSoundStream_SetAttenuation;
|
||||
typedef float function(void*) pf_sfSoundStream_GetPitch;
|
||||
typedef float function(void*) pf_sfSoundStream_GetVolume;
|
||||
typedef void function(void*, float*, float*, float*) pf_sfSoundStream_GetPosition;
|
||||
typedef float function(void*) pf_sfSoundStream_GetMinDistance;
|
||||
typedef float function(void*) pf_sfSoundStream_GetAttenuation;
|
||||
typedef float function(void*) pf_sfSoundStream_GetPlayingOffset;
|
||||
typedef int function(void*) pf_sfSoundStream_GetLoop;
|
||||
typedef void function(void*, int) pf_sfSoundStream_SetLoop;
|
||||
|
||||
|
||||
static pf_sfSoundStream_Create sfSoundStream_Create;
|
||||
static pf_sfSoundStream_Destroy sfSoundStream_Destroy;
|
||||
static pf_sfSoundStream_Play sfSoundStream_Play;
|
||||
static pf_sfSoundStream_Pause sfSoundStream_Pause;
|
||||
static pf_sfSoundStream_Stop sfSoundStream_Stop;
|
||||
static pf_sfSoundStream_GetStatus sfSoundStream_GetStatus;
|
||||
static pf_sfSoundStream_GetChannelsCount sfSoundStream_GetChannelsCount;
|
||||
static pf_sfSoundStream_GetSampleRate sfSoundStream_GetSampleRate;
|
||||
static pf_sfSoundStream_SetPitch sfSoundStream_SetPitch;
|
||||
static pf_sfSoundStream_SetVolume sfSoundStream_SetVolume;
|
||||
static pf_sfSoundStream_SetPosition sfSoundStream_SetPosition;
|
||||
static pf_sfSoundStream_SetMinDistance sfSoundStream_SetMinDistance;
|
||||
static pf_sfSoundStream_SetAttenuation sfSoundStream_SetAttenuation;
|
||||
static pf_sfSoundStream_GetPitch sfSoundStream_GetPitch;
|
||||
static pf_sfSoundStream_GetVolume sfSoundStream_GetVolume;
|
||||
static pf_sfSoundStream_GetPosition sfSoundStream_GetPosition;
|
||||
static pf_sfSoundStream_GetMinDistance sfSoundStream_GetMinDistance;
|
||||
static pf_sfSoundStream_GetAttenuation sfSoundStream_GetAttenuation;
|
||||
static pf_sfSoundStream_GetPlayingOffset sfSoundStream_GetPlayingOffset;
|
||||
static pf_sfSoundStream_GetLoop sfSoundStream_GetLoop;
|
||||
static pf_sfSoundStream_SetLoop sfSoundStream_SetLoop;
|
||||
}
|
||||
|
||||
static this()
|
||||
{
|
||||
DllLoader dll = DllLoader.load("csfml-audio");
|
||||
|
||||
sfSoundStream_Create = cast(pf_sfSoundStream_Create)dll.getSymbol("sfSoundStream_Create");
|
||||
sfSoundStream_Destroy = cast(pf_sfSoundStream_Destroy)dll.getSymbol("sfSoundStream_Destroy");
|
||||
sfSoundStream_Play = cast(pf_sfSoundStream_Play)dll.getSymbol("sfSoundStream_Play");
|
||||
sfSoundStream_Pause = cast(pf_sfSoundStream_Pause)dll.getSymbol("sfSoundStream_Pause");
|
||||
sfSoundStream_Stop = cast(pf_sfSoundStream_Stop)dll.getSymbol("sfSoundStream_Stop");
|
||||
sfSoundStream_GetStatus = cast(pf_sfSoundStream_GetStatus)dll.getSymbol("sfSoundStream_GetStatus");
|
||||
sfSoundStream_GetChannelsCount = cast(pf_sfSoundStream_GetChannelsCount)dll.getSymbol("sfSoundStream_GetChannelsCount");
|
||||
sfSoundStream_GetSampleRate = cast(pf_sfSoundStream_GetSampleRate)dll.getSymbol("sfSoundStream_GetSampleRate");
|
||||
sfSoundStream_SetPitch = cast(pf_sfSoundStream_SetPitch)dll.getSymbol("sfSoundStream_SetPitch");
|
||||
sfSoundStream_SetVolume = cast(pf_sfSoundStream_SetVolume)dll.getSymbol("sfSoundStream_SetVolume");
|
||||
sfSoundStream_SetPosition = cast(pf_sfSoundStream_SetPosition)dll.getSymbol("sfSoundStream_SetPosition");
|
||||
sfSoundStream_SetMinDistance = cast(pf_sfSoundStream_SetMinDistance)dll.getSymbol("sfSoundStream_SetMinDistance");
|
||||
sfSoundStream_SetAttenuation = cast(pf_sfSoundStream_SetAttenuation)dll.getSymbol("sfSoundStream_SetAttenuation");
|
||||
sfSoundStream_GetPitch = cast(pf_sfSoundStream_GetPitch)dll.getSymbol("sfSoundStream_GetPitch");
|
||||
sfSoundStream_GetVolume = cast(pf_sfSoundStream_GetVolume)dll.getSymbol("sfSoundStream_GetVolume");
|
||||
sfSoundStream_GetPosition = cast(pf_sfSoundStream_GetPosition)dll.getSymbol("sfSoundStream_GetPosition");
|
||||
sfSoundStream_GetMinDistance = cast(pf_sfSoundStream_GetMinDistance)dll.getSymbol("sfSoundStream_GetMinDistance");
|
||||
sfSoundStream_GetAttenuation = cast(pf_sfSoundStream_GetAttenuation)dll.getSymbol("sfSoundStream_GetAttenuation");
|
||||
sfSoundStream_GetPlayingOffset = cast(pf_sfSoundStream_GetPlayingOffset)dll.getSymbol("sfSoundStream_GetPlayingOffset");
|
||||
sfSoundStream_GetLoop = cast(pf_sfSoundStream_GetLoop)dll.getSymbol("sfSoundStream_GetLoop");
|
||||
sfSoundStream_SetLoop = cast(pf_sfSoundStream_SetLoop)dll.getSymbol("sfSoundStream_SetLoop");
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue