using System; using System.Runtime.InteropServices; using System.Security; namespace SFML { namespace Audio { //////////////////////////////////////////////////////////// /// /// 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 (see Music), /// or for streaming sound from the network /// //////////////////////////////////////////////////////////// public abstract class SoundStream : ObjectBase { //////////////////////////////////////////////////////////// /// /// Default constructor /// //////////////////////////////////////////////////////////// public SoundStream() : base(IntPtr.Zero) { } //////////////////////////////////////////////////////////// /// /// Play the sound stream /// //////////////////////////////////////////////////////////// public void Play() { sfSoundStream_Play(This); } //////////////////////////////////////////////////////////// /// /// Pause the sound stream /// //////////////////////////////////////////////////////////// public void Pause() { sfSoundStream_Pause(This); } //////////////////////////////////////////////////////////// /// /// Stop the sound stream /// //////////////////////////////////////////////////////////// public void Stop() { sfSoundStream_Stop(This); } //////////////////////////////////////////////////////////// /// /// Samples rate, in samples per second /// //////////////////////////////////////////////////////////// public uint SampleRate { get {return sfSoundStream_GetSampleRate(This);} } //////////////////////////////////////////////////////////// /// /// Number of channels (1 = mono, 2 = stereo) /// //////////////////////////////////////////////////////////// public uint ChannelsCount { get {return sfSoundStream_GetChannelsCount(This);} } //////////////////////////////////////////////////////////// /// /// Current status of the sound stream (see SoundStatus enum) /// //////////////////////////////////////////////////////////// public SoundStatus Status { get {return sfSoundStream_GetStatus(This);} } //////////////////////////////////////////////////////////// /// /// Loop state of the sound stream. Default value is false /// //////////////////////////////////////////////////////////// public bool Loop { get {return sfSoundStream_GetLoop(This);} set {sfSoundStream_SetLoop(This, value);} } //////////////////////////////////////////////////////////// /// /// Pitch of the sound stream. Default value is 1 /// //////////////////////////////////////////////////////////// public float Pitch { get {return sfSoundStream_GetPitch(This);} set {sfSoundStream_SetPitch(This, value);} } //////////////////////////////////////////////////////////// /// /// Volume of the sound stream, in range [0, 100]. Default value is 100 /// //////////////////////////////////////////////////////////// public float Volume { get {return sfSoundStream_GetVolume(This);} set {sfSoundStream_SetVolume(This, value);} } //////////////////////////////////////////////////////////// /// /// 3D position of the sound stream. Default value is (0, 0, 0) /// //////////////////////////////////////////////////////////// public Vector3 Position { get {Vector3 v; sfSoundStream_GetPosition(This, out v.X, out v.Y, out v.Z); return v;} set {sfSoundStream_SetPosition(This, value.X, value.Y, value.Z);} } //////////////////////////////////////////////////////////// /// /// Minimum distance of the sound stream. Closer than this distance, /// the listener will hear the sound at its maximum volume. /// The default value is 1 /// //////////////////////////////////////////////////////////// public float MinDistance { get {return sfSoundStream_GetMinDistance(This);} set {sfSoundStream_SetMinDistance(This, value);} } //////////////////////////////////////////////////////////// /// /// Attenuation factor. The higher the attenuation, the /// more the sound will be attenuated with distance from listener. /// The default value is 1 /// //////////////////////////////////////////////////////////// public float Attenuation { get {return sfSoundStream_GetAttenuation(This);} set {sfSoundStream_SetAttenuation(This, value);} } //////////////////////////////////////////////////////////// /// /// Current playing position, in seconds /// //////////////////////////////////////////////////////////// public float PlayingOffset { get {return sfSoundStream_GetPlayingOffset(This);} } //////////////////////////////////////////////////////////// /// /// Set the audio stream parameters, you must call it before Play() /// /// Number of channels /// Sample rate, in samples per second //////////////////////////////////////////////////////////// protected void Initialize(uint channelsCount, uint sampleRate) { myStartCallback = new StartCallbackType(Start); myGetDataCallback = new GetDataCallbackType(GetData); SetThis(sfSoundStream_Create(myStartCallback, myGetDataCallback, channelsCount, sampleRate, IntPtr.Zero)); } //////////////////////////////////////////////////////////// /// /// Virtual function called when the stream restarts /// /// If false is returned, the playback is aborted //////////////////////////////////////////////////////////// protected virtual bool OnStart() { // Does nothing by default return true; } //////////////////////////////////////////////////////////// /// /// Virtual function called each time new audio data is needed to feed the stream /// /// Array of samples to fill for the stream /// True to continue playback, false to stop //////////////////////////////////////////////////////////// protected abstract bool OnGetData(out short[] samples); //////////////////////////////////////////////////////////// /// /// Handle the destruction of the object /// /// Is the GC disposing the object, or is it an explicit call ? //////////////////////////////////////////////////////////// protected override void Destroy(bool disposing) { sfSoundStream_Destroy(This); } //////////////////////////////////////////////////////////// /// /// Structure mapping the C library arguments passed to the data callback /// //////////////////////////////////////////////////////////// [StructLayout(LayoutKind.Sequential)] private struct Chunk { unsafe public short* samplesPtr; public uint samplesCount; } //////////////////////////////////////////////////////////// /// /// Called when the stream restarts /// /// User data -- unused /// If false is returned, the playback is aborted //////////////////////////////////////////////////////////// private bool Start(IntPtr userData) { return OnStart(); } //////////////////////////////////////////////////////////// /// /// Called each time new audio data is needed to feed the stream /// /// Data chunk to fill with new audio samples /// User data -- unused /// True to continue playback, false to stop //////////////////////////////////////////////////////////// private bool GetData(ref Chunk dataChunk, IntPtr userData) { if (OnGetData(out myTempBuffer)) { unsafe { fixed (short* samplesPtr = myTempBuffer) { dataChunk.samplesPtr = samplesPtr; dataChunk.samplesCount = (uint)myTempBuffer.Length; } } return true; } else { return false; } } [UnmanagedFunctionPointer(CallingConvention.Cdecl)] private delegate bool StartCallbackType(IntPtr UserData); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] private delegate bool GetDataCallbackType(ref Chunk dataChunk, IntPtr UserData); private StartCallbackType myStartCallback; private GetDataCallbackType myGetDataCallback; private short[] myTempBuffer; #region Imports [DllImport("csfml-audio")] static extern IntPtr sfSoundStream_Create(StartCallbackType OnStart, GetDataCallbackType OnGetData, uint ChannelsCount, uint SampleRate, IntPtr UserData); [DllImport("csfml-audio")] static extern void sfSoundStream_Destroy(IntPtr SoundStreamStream); [DllImport("csfml-audio")] static extern void sfSoundStream_Play(IntPtr SoundStream); [DllImport("csfml-audio")] static extern void sfSoundStream_Pause(IntPtr SoundStream); [DllImport("csfml-audio")] static extern void sfSoundStream_Stop(IntPtr SoundStream); [DllImport("csfml-audio")] static extern SoundStatus sfSoundStream_GetStatus(IntPtr SoundStream); [DllImport("csfml-audio")] static extern uint sfSoundStream_GetChannelsCount(IntPtr SoundStream); [DllImport("csfml-audio")] static extern uint sfSoundStream_GetSampleRate(IntPtr SoundStream); [DllImport("csfml-audio")] static extern void sfSoundStream_SetLoop(IntPtr SoundStream, bool Loop); [DllImport("csfml-audio")] static extern void sfSoundStream_SetPitch(IntPtr SoundStream, float Pitch); [DllImport("csfml-audio")] static extern void sfSoundStream_SetVolume(IntPtr SoundStream, float Volume); [DllImport("csfml-audio")] static extern void sfSoundStream_SetPosition(IntPtr SoundStream, float X, float Y, float Z); [DllImport("csfml-audio")] static extern void sfSoundStream_SetMinDistance(IntPtr SoundStream, float MinDistance); [DllImport("csfml-audio")] static extern void sfSoundStream_SetAttenuation(IntPtr SoundStream, float Attenuation); [DllImport("csfml-audio")] static extern bool sfSoundStream_GetLoop(IntPtr SoundStream); [DllImport("csfml-audio")] static extern float sfSoundStream_GetPitch(IntPtr SoundStream); [DllImport("csfml-audio")] static extern float sfSoundStream_GetVolume(IntPtr SoundStream); [DllImport("csfml-audio")] static extern void sfSoundStream_GetPosition(IntPtr SoundStream, out float X, out float Y, out float Z); [DllImport("csfml-audio")] static extern float sfSoundStream_GetMinDistance(IntPtr SoundStream); [DllImport("csfml-audio")] static extern float sfSoundStream_GetAttenuation(IntPtr SoundStream); [DllImport("csfml-audio"), SuppressUnmanagedCodeSecurity] static extern float sfSoundStream_GetPlayingOffset(IntPtr SoundStream); #endregion } } }