5 using System.Collections.Generic;
7 using System.Threading;
9 using SiliconStudio.Core;
10 using SiliconStudio.Core.IO;
11 using SiliconStudio.Paradox.Audio.Wave;
13 namespace SiliconStudio.
Paradox.Audio
48 internal WaveFormat WaveFormat {
get;
private set; }
50 private IntPtr nativeDataBuffer;
52 internal IntPtr WaveDataPtr {
get;
private set; }
54 internal int WaveDataSize {
get;
private set; }
71 throw new ArgumentNullException(
"engine");
74 throw new ArgumentNullException(
"stream");
77 throw new ObjectDisposedException(
"Audio Engine");
80 var newSdEff =
new SoundEffect(engine) { nativeDataBuffer = Utilities.AllocateMemory((int)stream.Length) };
83 stream.CopyTo(nativeStream);
84 nativeStream.Position = 0;
86 var waveStreamReader =
new SoundStream(nativeStream);
87 var waveFormat = waveStreamReader.Format;
89 if (waveFormat.Channels > 2)
90 throw new NotSupportedException(
"The wave file contains more than 2 data channels. Only mono and stereo formats are currently supported.");
92 if (waveFormat.Encoding != WaveFormatEncoding.Pcm || waveFormat.BitsPerSample != 16)
93 throw new NotSupportedException(
"The wave file audio format is not supported. Only 16bits PCM encoded formats are currently supported.");
95 newSdEff.WaveFormat = waveFormat;
96 newSdEff.WaveDataPtr = newSdEff.nativeDataBuffer + (int)nativeStream.Position;
97 newSdEff.WaveDataSize = (
int)waveStreamReader.Length;
98 newSdEff.Name =
"Sound Effect " + soundEffectCreationCount;
100 newSdEff.AdaptAudioDataImpl();
103 engine.RegisterSound(newSdEff);
105 Interlocked.Increment(ref soundEffectCreationCount);
113 private static int soundEffectCreationCount;
117 private int intancesCreationCount;
130 var newInstance =
new SoundEffectInstance(
this) { Name = Name +
" - Instance " + intancesCreationCount };
132 RegisterInstance(newInstance);
134 ++intancesCreationCount;
143 internal readonly List<SoundEffectInstance> Instances =
new List<SoundEffectInstance>();
151 Instances.Add(instance);
157 internal void StopAllInstances()
159 foreach (var instance
in Instances)
167 internal void StopConcurrentInstances(SoundEffectInstance mainInstance)
169 foreach (var instance
in Instances)
171 if(instance != mainInstance)
180 internal void UnregisterInstance(SoundEffectInstance instance)
182 if(!Instances.Remove(instance))
183 throw new AudioSystemInternalException(
"Tried to unregister soundEffectInstance while not contained in the instance list.");
187 private SoundEffectInstance DefaultInstance
189 get {
return defaultInstance ?? (defaultInstance = CreateInstance()); }
191 private SoundEffectInstance defaultInstance;
193 private SoundEffect(AudioEngine engine)
198 #region Interface Implementation using underlying SoundEffectInstance
202 get {
return DefaultInstance.Pan; }
203 set { DefaultInstance.Pan = value; }
208 get {
return DefaultInstance.Volume; }
209 set { DefaultInstance.Volume = value; }
214 DefaultInstance.Apply3D(listener, emitter);
219 get {
return DefaultInstance.PlayState; }
224 get {
return DefaultInstance.IsLooped; }
225 set { DefaultInstance.IsLooped = value; }
230 DefaultInstance.Play();
235 DefaultInstance.Pause();
240 DefaultInstance.Stop();
245 DefaultInstance.ExitLoop();
250 DefaultInstance.Reset3D();
261 foreach (var seInstance
in Instances.ToArray())
262 seInstance.Dispose();
267 if (nativeDataBuffer != IntPtr.Zero)
269 Utilities.FreeMemory(nativeDataBuffer);
270 nativeDataBuffer = IntPtr.Zero;
271 WaveDataPtr = IntPtr.Zero;
276 AudioEngine.UnregisterSound(
this);
279 private unsafe
void DuplicateTracks(IntPtr waveDataPtr, IntPtr newWaveDataPtr,
int newWaveDataSize)
281 var pInputCurrent = (
short*)waveDataPtr;
282 var pOutputCurrent = (
short*)newWaveDataPtr;
283 var numberOfIters = newWaveDataSize /
sizeof(short);
286 while (count < numberOfIters)
288 *pOutputCurrent++ = *pInputCurrent;
289 *pOutputCurrent++ = *pInputCurrent;
296 private unsafe
void UpSampleByTwo(IntPtr waveDataPtr, IntPtr newWaveDataPtr,
int newWaveDataSize,
int nbOfChannels,
bool convertToStereo)
298 var pInputCurrent = (
short*)waveDataPtr;
299 var pOutputCurrent = (
short*)newWaveDataPtr;
300 var numberOfIters = newWaveDataSize /
sizeof(short);
305 for (
int i = 0; i < nbOfChannels; i++)
307 if (count >= numberOfIters)
310 *pOutputCurrent = *pInputCurrent;
318 *pOutputCurrent = pOutputCurrent[-1];
322 for (
int i = 0; i < nbOfChannels; i++)
324 if (count >= numberOfIters)
327 *pOutputCurrent = (short)((pInputCurrent[0] + pInputCurrent[-nbOfChannels]) >> 1);
335 *pOutputCurrent = pOutputCurrent[-1];
340 pInputCurrent -= nbOfChannels;
344 private unsafe
void UpSample(IntPtr waveDataPtr, IntPtr newWaveDataPtr,
int newWaveDataSize,
float sampleRateRatio,
int nbOfChannels,
bool convertToStereo)
346 var pInputCurrent = (
short*)waveDataPtr;
347 var pOutputCurrent = (
short*)newWaveDataPtr;
348 var numberOfIters = newWaveDataSize /
sizeof(short);
351 var currentPosition = 0f;
354 for (
int i = 0; i < nbOfChannels; i++)
356 if (count >= numberOfIters)
359 *pOutputCurrent = (short)((1 - currentPosition) * pInputCurrent[i] + currentPosition * pInputCurrent[i + nbOfChannels]);
366 *pOutputCurrent = pOutputCurrent[-1];
371 currentPosition += sampleRateRatio;
373 if (currentPosition >= 1)
375 pInputCurrent += nbOfChannels;
376 currentPosition -= 1;
Represents a 3D audio listener in the audio scene. This object, used in combination with an AudioEmit...
void ExitLoop()
Stop looping. That is, do not start over at the end of the current loop, continue to play until the e...
This class provides a loaded sound resource which is localizable in the 3D scene. ...
SoundEffectInstance CreateInstance()
Create a new sound effect instance of the sound effect. The audio data are shared between the instanc...
void Apply3D(AudioListener listener, AudioEmitter emitter)
Applies 3D positioning to the sound. More precisely adjust the channel volumes and pitch of the sound...
SoundPlayState
Current state (playing, paused, or stopped) of a sound implementing the IPlayableSound interface...
void Play()
Start or resume playing the sound.
bool IsDisposed
Has the component been disposed or not yet.
Represents the audio engine. In current version, the audio engine necessarily creates its context on ...
void Reset3D()
Cancel the effect of possible previous calls to Apply3D.
static SoundEffect Load(AudioEngine engine, Stream stream)
Create and Load a sound effect from an input wav stream.
override void Destroy()
Disposes of object resources.
Base class for all the sounds and sound instances.
A MemoryStream over a native memory region.
Represents a 3D audio emitter in the audio scene. This object, used in combination with an AudioListe...
void Stop()
Stop playing the sound immediately and reset the sound to the beginning of the track.
Instance of a SoundEffect sound which can be independently localized and played.
Interface for 3D localizable sound. The interface currently supports only mono and stereo sounds (ref...
void Pause()
Pause the sounds.