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);} } //////////////////////////////////////////////////////////// /// /// Is the sound stream's position relative to the listener's position, /// or is it absolute? /// Default value is false (absolute) /// //////////////////////////////////////////////////////////// public bool RelativeToListener { get {return sfSoundStream_IsRelativeToListener(This);} set {sfSoundStream_SetRelativeToListener(This, value);} } //////////////////////////////////////////////////////////// /// /// 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 {sfSoundStream_SetPlayingOffset(This, value);} } //////////////////////////////////////////////////////////// /// /// Provide a string describing the object /// /// String description of the object //////////////////////////////////////////////////////////// public override string ToString() { return "[SoundStream]" + " SampleRate = " + SampleRate + " ChannelsCount = " + ChannelsCount + " Status = " + Status + " Loop = " + Loop + " Pitch = " + Pitch + " Volume = " + Volume + " Position = " + Position + " RelativeToListener = " + RelativeToListener + " MinDistance = " + MinDistance + " Attenuation = " + Attenuation + " PlayingOffset = " + PlayingOffset; } //////////////////////////////////////////////////////////// /// /// 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) { myGetDataCallback = new GetDataCallbackType(GetData); mySeekCallback = new SeekCallbackType(Seek); SetThis(sfSoundStream_Create(myGetDataCallback, mySeekCallback, channelsCount, sampleRate, IntPtr.Zero)); } //////////////////////////////////////////////////////////// /// /// 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); //////////////////////////////////////////////////////////// /// /// Virtual function called to seek into the stream /// /// New position, expressed in seconds //////////////////////////////////////////////////////////// protected abstract void OnSeek(float timeOffset); //////////////////////////////////////////////////////////// /// /// 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 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; } } //////////////////////////////////////////////////////////// /// /// Called to seek in the stream /// /// New position, expressed in seconds /// User data -- unused /// If false is returned, the playback is aborted //////////////////////////////////////////////////////////// private void Seek(float timeOffset, IntPtr userData) { OnSeek(timeOffset); } [UnmanagedFunctionPointer(CallingConvention.Cdecl)] private delegate bool GetDataCallbackType(ref Chunk dataChunk, IntPtr UserData); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] private delegate void SeekCallbackType(float timeOffset, IntPtr UserData); private GetDataCallbackType myGetDataCallback; private SeekCallbackType mySeekCallback; private short[] myTempBuffer; #region Imports [DllImport("csfml-audio"), SuppressUnmanagedCodeSecurity] static extern IntPtr sfSoundStream_Create(GetDataCallbackType OnGetData, SeekCallbackType OnSeek, uint ChannelsCount, uint SampleRate, IntPtr UserData); [DllImport("csfml-audio"), SuppressUnmanagedCodeSecurity] static extern void sfSoundStream_Destroy(IntPtr SoundStreamStream); [DllImport("csfml-audio"), SuppressUnmanagedCodeSecurity] static extern void sfSoundStream_Play(IntPtr SoundStream); [DllImport("csfml-audio"), SuppressUnmanagedCodeSecurity] static extern void sfSoundStream_Pause(IntPtr SoundStream); [DllImport("csfml-audio"), SuppressUnmanagedCodeSecurity] static extern void sfSoundStream_Stop(IntPtr SoundStream); [DllImport("csfml-audio"), SuppressUnmanagedCodeSecurity] static extern SoundStatus sfSoundStream_GetStatus(IntPtr SoundStream); [DllImport("csfml-audio"), SuppressUnmanagedCodeSecurity] static extern uint sfSoundStream_GetChannelsCount(IntPtr SoundStream); [DllImport("csfml-audio"), SuppressUnmanagedCodeSecurity] static extern uint sfSoundStream_GetSampleRate(IntPtr SoundStream); [DllImport("csfml-audio"), SuppressUnmanagedCodeSecurity] static extern void sfSoundStream_SetLoop(IntPtr SoundStream, bool Loop); [DllImport("csfml-audio"), SuppressUnmanagedCodeSecurity] static extern void sfSoundStream_SetPitch(IntPtr SoundStream, float Pitch); [DllImport("csfml-audio"), SuppressUnmanagedCodeSecurity] static extern void sfSoundStream_SetVolume(IntPtr SoundStream, float Volume); [DllImport("csfml-audio"), SuppressUnmanagedCodeSecurity] static extern void sfSoundStream_SetPosition(IntPtr SoundStream, float X, float Y, float Z); [DllImport("csfml-audio"), SuppressUnmanagedCodeSecurity] static extern void sfSoundStream_SetRelativeToListener(IntPtr SoundStream, bool Relative); [DllImport("csfml-audio"), SuppressUnmanagedCodeSecurity] static extern void sfSoundStream_SetMinDistance(IntPtr SoundStream, float MinDistance); [DllImport("csfml-audio"), SuppressUnmanagedCodeSecurity] static extern void sfSoundStream_SetAttenuation(IntPtr SoundStream, float Attenuation); [DllImport("csfml-audio"), SuppressUnmanagedCodeSecurity] static extern void sfSoundStream_SetPlayingOffset(IntPtr SoundStream, float TimeOffset); [DllImport("csfml-audio"), SuppressUnmanagedCodeSecurity] static extern bool sfSoundStream_GetLoop(IntPtr SoundStream); [DllImport("csfml-audio"), SuppressUnmanagedCodeSecurity] static extern float sfSoundStream_GetPitch(IntPtr SoundStream); [DllImport("csfml-audio"), SuppressUnmanagedCodeSecurity] static extern float sfSoundStream_GetVolume(IntPtr SoundStream); [DllImport("csfml-audio"), SuppressUnmanagedCodeSecurity] static extern void sfSoundStream_GetPosition(IntPtr SoundStream, out float X, out float Y, out float Z); [DllImport("csfml-audio"), SuppressUnmanagedCodeSecurity] static extern bool sfSoundStream_IsRelativeToListener(IntPtr SoundStream); [DllImport("csfml-audio"), SuppressUnmanagedCodeSecurity] static extern float sfSoundStream_GetMinDistance(IntPtr SoundStream); [DllImport("csfml-audio"), SuppressUnmanagedCodeSecurity] static extern float sfSoundStream_GetAttenuation(IntPtr SoundStream); [DllImport("csfml-audio"), SuppressUnmanagedCodeSecurity] static extern float sfSoundStream_GetPlayingOffset(IntPtr SoundStream); #endregion } } }