Beispiel #1
0
        public void SubmitBuffer_ParameterValidation_ComplexOverload()
        {
            using (var instance = new DynamicSoundEffectInstance(16000, AudioChannels.Stereo))
            {
                // Null or empty buffer - with different null behavior to the other overload
                Assert.Throws <ArgumentException>(() => { instance.SubmitBuffer(null, 0, 4); });
                Assert.Throws <ArgumentException>(() => { instance.SubmitBuffer(new byte[0], 0, 4); });

                var buffer = GenerateSineWave(440, 16000, 2, 0.5f);

                // Correct alignment
                instance.SubmitBuffer(buffer, 0, 4);       // One sample per channel
                instance.SubmitBuffer(buffer, 1000, 1000); // 250 samples

                // Invalid alignment
                Assert.Throws <ArgumentException>(() => { instance.SubmitBuffer(buffer, 0, 3); });
                Assert.Throws <ArgumentException>(() => { instance.SubmitBuffer(buffer, 1, 4); }); // Unaligned start position also throws

                // Invalid size
                Assert.Throws <ArgumentException>(() => { instance.SubmitBuffer(buffer, 0, 0); });
                Assert.Throws <ArgumentException>(() => { instance.SubmitBuffer(buffer, 0, -1); });
                Assert.Throws <ArgumentException>(() => { instance.SubmitBuffer(buffer, 0, buffer.Length + 1); });
                Assert.Throws <ArgumentException>(() => { instance.SubmitBuffer(buffer, buffer.Length - 4, 8); });
            }
        }
Beispiel #2
0
        private void StreamThread()
        {
            while (!sound.IsDisposed)
            {
                // sleep until we need a buffer
                while (!sound.IsDisposed && !threadRunHandle.WaitOne(0) && !needBufferHandle.WaitOne(0))
                {
                    Thread.Sleep(50);
                }

                // if the thread is waiting to exit, leave
                if (threadRunHandle.WaitOne(0))
                {
                    break;
                }

                lock (sound) {
                    // ensure the effect isn't disposed
                    if (sound.IsDisposed)
                    {
                        break;
                    }
                }

                // read the next chunk of data
                int samplesRead = reader.ReadSamples(nvBuffer, 0, nvBuffer.Length);

                // out of data and looping? reset the reader and read again
                if (samplesRead == 0 && IsLooped)
                {
                    reader.DecodedTime = TimeSpan.Zero;
                    samplesRead        = reader.ReadSamples(nvBuffer, 0, nvBuffer.Length);
                }

                if (samplesRead > 0)
                {
                    for (int i = 0; i < samplesRead; i++)
                    {
                        short sValue = (short)Math.Max(Math.Min(short.MaxValue * nvBuffer[i], short.MaxValue), short.MinValue);
                        buffer[i * 2]     = (byte)(sValue & 0xff);
                        buffer[i * 2 + 1] = (byte)((sValue >> 8) & 0xff);
                    }

                    // submit our buffers
                    lock (sound) {
                        // ensure the effect isn't disposed
                        if (sound.IsDisposed)
                        {
                            break;
                        }

                        sound.SubmitBuffer(buffer, 0, samplesRead);
                        sound.SubmitBuffer(buffer, samplesRead, samplesRead);
                    }
                }

                // reset our handle
                needBufferHandle.Reset();
            }
        }
Beispiel #3
0
        public virtual void Tick(long cycles = 0)
        {
            currentPeriod += (int)cycles;
            if (Restart && !ChannelThree)
            {
                //Stopping clears the buffer.
                Channel_Out.Stop();
                Channel_Out.Play();
            }

            //if looping and the buffer is empty, or starting a new sound.
            if (Play() && !ChannelThree)
            {
                Channel_Out.SubmitBuffer(CreateTone());
                Restart = false;
            }
            else if (Restart && ChannelThree && currentPeriod > period)
            {
                if (pendingSamples.Count >= 32)
                {
                    TriggerWavePlay();
                }
            }
            else if (Play() && ChannelThree)
            {
                //while(Channel_Out.PendingBufferCount < 50)
                //{
                //    Channel_Out.SubmitBuffer(bBuffer);
                //}
            }
        }
Beispiel #4
0
        public void SubmitBuffer(byte[] buf, int offset, int length)
        {
            System.Buffer.BlockCopy(buf, offset, mBuffer, 0, length);

            int halfLen = length / 2;

            mSoundEffectInstance.SubmitBuffer(mBuffer, 0, halfLen);
            mSoundEffectInstance.SubmitBuffer(mBuffer, halfLen, halfLen);
        }
Beispiel #5
0
        /// <summary>
        /// DynamicSoundEffectInstance.BufferNeeded イベントの発生で呼び出されます。
        /// 必要に応じて Wave データを読み込み、DynamicSoundEffectInstance に設定します。
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void OnDynamicSoundBufferNeeded(object sender, EventArgs e)
        {
            if (!Looped && totalDataCount == dataChunkHeader.Size)
            {
                // 再生を完全に終わらせるように処理します。
                if (dynamicSound.PendingBufferCount == 0)
                {
                    // 停止寸前であるため状態をリセットします。
                    // これにより、停止後に再生を開始した時に Wave データの先頭から再生できます。
                    Reset();

                    // 停止状態に設定します。
                    dynamicSound.Stop();
                }
                return;
            }

            if (asyncResult == null)
            {
                // 再生直後はここに入ります。
                // ここでは同期的に Wave データを読み込みます。
                ReadData();
            }
            else
            {
                // 非同期に Wave データを読み込んでいるので、その完了を待機します。
                asyncResult.AsyncWaitHandle.WaitOne();
            }

            if (dataCount == bufferSize)
            {
                // 最大サイズをフルに使用している場合は分割して設定します。
                var halfSize = bufferSize / 2;
                dynamicSound.SubmitBuffer(buffer, 0, halfSize);
                dynamicSound.SubmitBuffer(buffer, halfSize, halfSize);
            }
            else if (dataCount != 0)
            {
                // 最大サイズに足りていない場合はそのまま設定します。
                dynamicSound.SubmitBuffer(buffer, 0, dataCount);
            }

            dataCount = 0;

            if (!Looped && totalDataCount == dataChunkHeader.Size)
            {
                // ループ OFF で末尾に到達しているならば、ここで設定したバッファで再生を終えます。
                // なお、DynamicSoundEffectInstance は、Stop() および Stop(bool) メソッドを呼び出しても、
                // PendingBufferCount = 0 になるまで停止しない点に注意が必要です。
                return;
            }

            // 非同期に次の Wave データを読み込み、次の BufferNeeded イベント受信に備えます。
            asyncResult = readDataAsyncCaller.BeginInvoke(null, null);
        }
Beispiel #6
0
        bool SubmitSamples()
        {
            // read the next chunk of data
            int samplesRead = reader.ReadSamples(nvBuffer, 0, nvBuffer.Length);

            // out of data and looping? reset the reader and read again
            if (samplesRead == 0)
            {
                if (IsLooped)
                {
                    reader.DecodedTime = TimeSpan.Zero;
                    samplesRead        = reader.ReadSamples(nvBuffer, 0, nvBuffer.Length);
                }
                else
                {
                    // Song is over, stop thread
                    thread = null;
                    return(false);
                }
            }

            if (samplesRead > 0)
            {
                // Submit our buffers
#if !FNA
                for (int i = 0; i < samplesRead; i++)
                {
                    short sValue = (short)Math.Max(Math.Min(short.MaxValue * nvBuffer[i], short.MaxValue), short.MinValue);
                    buffer[i * 2]     = (byte)(sValue & 0xff);
                    buffer[i * 2 + 1] = (byte)((sValue >> 8) & 0xff);
                }
#endif
                lock ( effect )
                {
                    // Ensure the effect isn't disposed
                    if (effect.IsDisposed)
                    {
                        return(false);
                    }

                    // Ensure the number of samples read is block-aligned
                    samplesRead += samplesRead % (reader.Channels * 2);

#if !FNA
                    effect.SubmitBuffer(buffer, 0, samplesRead);
                    effect.SubmitBuffer(buffer, samplesRead, samplesRead);
#else
                    effect.SubmitFloatBufferEXT(nvBuffer);
#endif
                }
            }

            return(true);
        }
        void DynamicSound_BufferNeeded(object sender, EventArgs e)
        {
            dynamicSound.SubmitBuffer(byteArray, position, count / 2);
            dynamicSound.SubmitBuffer(byteArray, position + count / 2, count / 2);

            position += count;
            if (position + count > byteArray.Length)
            {
                position = 0;
            }
        }
Beispiel #8
0
        public MainPage()
        {
            InitializeComponent();
            mixer = new Mixer();

            emptyBuffer = new byte[1024];

            sound = new DynamicSoundEffectInstance(48000, AudioChannels.Stereo);
            sound.SubmitBuffer(emptyBuffer);
            sound.SubmitBuffer(emptyBuffer);
            sound.BufferNeeded += new EventHandler <EventArgs>(sound_BufferNeeded);
            sound.Play();
        }
Beispiel #9
0
        public void Stop_RemovesBuffers()
        {
            using (var instance = new DynamicSoundEffectInstance(12000, AudioChannels.Mono))
            {
                instance.SubmitBuffer(GenerateSineWave(440, 12000, 1, 0.1f));
                instance.SubmitBuffer(GenerateSineWave(440, 12000, 1, 0.1f));
                instance.SubmitBuffer(GenerateSineWave(440, 12000, 1, 0.1f));
                Assert.AreEqual(3, instance.PendingBufferCount);

                instance.Stop();
                SleepWhileDispatching(20);
                Assert.AreEqual(0, instance.PendingBufferCount);
            }
        }
Beispiel #10
0
 private void SubmitBuffer(object sender, EventArgs e)
 {
     byte[] buffer = new byte[524288];
     lock (this)
     {
         var read = Stream.Read(buffer, 0, buffer.Length);
         LastChunkSize = read;
         if (read == 0)
         {
             return;
         }
         Inst.SubmitBuffer(buffer, 0, read);
     }
 }
Beispiel #11
0
 void _dsei_BufferNeeded(object sender, EventArgs e)
 {
     if (Player != null)
     {
         for (int i = 0; i < 3; i++)
         {
             this.Player.GetBytes(buf, 8192);
             _dsei.SubmitBuffer(buf);
         }
     }
     else
     {
         _dsei.SubmitBuffer(buf);
     }
 }
Beispiel #12
0
        private void SubmitBuffer()
        {
            _bufferPos = 0;

            ConvertBuffer(_workingBuffer, _monoBuffer);
            _instance.SubmitBuffer(_monoBuffer);
        }
Beispiel #13
0
        void FillBuffer()
        {
            /*
             * int WriteBuffer =
             * WaitAtLeastBuffer(4);
             * for (int n = 0; n < 4; n++)
             * {
             *      var Segment = Buffer.Dequeue();
             *      //Debug.WriteLine("BUFFER: {0}, {1} : {2}:{3}", Buffer.Count, DynamicSoundEffect.PendingBufferCount, Segment.Offset, Segment.Count);
             *      //DynamicSoundEffect.SubmitBuffer(Segment.Array, Segment.Offset, Segment.Count);
             *      DynamicSoundEffect.SubmitBuffer(Segment);
             * }
             */
            int BufferCount = 2;

            do
            {
                WaitAtLeastBuffer(BufferCount);
                for (int n = 0; n < BufferCount; n++)
                {
                    var Segment = ReadBuffer();
                    if (Segment == null)
                    {
                        Ended = true;
                        return;
                    }
                    else
                    {
                        EmittedBytes += Segment.Length;
                        DynamicSoundEffect.SubmitBuffer(Segment);
                    }
                }
            } while (DynamicSoundEffect.PendingBufferCount < BufferCount * 2);
            //DynamicSoundEffect.pen
        }
Beispiel #14
0
        private void OnBufferNeeded(object sender, EventArgs e)
        {
            Array.Clear(_buffer, 0, _buffer.Length);
            var available = _audioSampleProvider != null?_audioSampleProvider.Read(_buffer, _buffer.Length) : 0;

            _dsei.SubmitBuffer(_buffer, available);
        }
Beispiel #15
0
        private void QueueBuffer(object source, EventArgs ea)
        {
            // The original method refers to Int64 Vorbisfile.ov_read(IntPtr, IntPtr, Int32, Int32, Int32, Int32, Int32 ByRef),
            // which has been changed in newer FNA releases. The last parameter is now out, not ref.

            int pos = 0;
            int read;

            do
            {
                int current_section;
                read = (int)Vorbisfile.ov_read(vorbisFile, bufferPtr + pos, 4096, 0, 2, 1, out current_section);
                pos += read;
            }while (read > 0 && pos < 187904);

            if (pos != 0)
            {
                soundEffect.SubmitBuffer(vorbisBuffer, 0, pos);
                return;
            }

            if (IsLooped)
            {
                Vorbisfile.ov_time_seek(vorbisFile, 0.0);
                QueueBuffer(source, ea);
                return;
            }

            hitEof = true;
            soundEffect.BufferNeeded -= OnBufferNeeded;
        }
Beispiel #16
0
        private void FillBuffers(int buffers = 3, int samples = 44100)
        {
            float[] sampleBuffer = null;

            while (mInstance.PendingBufferCount < buffers && mReader != null)
            {
                if (sampleBuffer == null)
                {
                    sampleBuffer = new float[samples];
                }

                var read = mReader.ReadSamples(sampleBuffer, 0, sampleBuffer.Length);
                if (read == 0)
                {
                    mReader.DecodedPosition = 0;
                    continue;
                }

                var dataBuffer = new byte[read << 1];
                for (var sampleIndex = 0; sampleIndex < read; ++sampleIndex)
                {
                    var sample     = (short)MathHelper.Clamp(sampleBuffer[sampleIndex] * 32767f, short.MinValue, short.MaxValue);
                    var sampleData = BitConverter.GetBytes(sample);
                    for (var sampleByteIndex = 0; sampleByteIndex < sampleData.Length; ++sampleByteIndex)
                    {
                        dataBuffer[(sampleIndex << 1) + sampleByteIndex] = sampleData[sampleByteIndex];
                    }
                }

                mInstance.SubmitBuffer(dataBuffer, 0, read << 1);
            }
        }
Beispiel #17
0
        private void SubmitBuffer()
        {
            _vorbis.SubmitBuffer();

            if (_vorbis.Decoded == 0)
            {
                // Restart
                _vorbis.Restart();
                _vorbis.SubmitBuffer();
            }

            var audioShort = _vorbis.SongBuffer;

            byte[] audioData = new byte[_vorbis.Decoded * _vorbis.Channels * 2];
            for (var i = 0; i < _vorbis.Decoded * _vorbis.Channels; ++i)
            {
                if (i * 2 >= audioData.Length)
                {
                    break;
                }

                var b1 = (byte)(audioShort[i] >> 8);
                var b2 = (byte)(audioShort[i] & 256);

                audioData[i * 2 + 0] = b2;
                audioData[i * 2 + 1] = b1;
            }

            _effect.SubmitBuffer(audioData);
        }
Beispiel #18
0
        /// <summary>
        /// Plays the effect.
        /// </summary>
        /// <param name="asEffect">Set to false for music, true for sound effects.</param>
        public void Play(bool asEffect = true)
        {
            double now = UltimaGame.TotalMS;

            CullExpiredEffects(now);

            m_ThisInstance = GetNewInstance(asEffect);
            if (m_ThisInstance == null)
            {
                this.Dispose();
                return;
            }

            BeforePlay();

            byte[] buffer = GetBuffer();
            if (buffer != null && buffer.Length > 0)
            {
                m_ThisInstance.BufferNeeded += new EventHandler <EventArgs>(OnBufferNeeded);
                m_ThisInstance.SubmitBuffer(buffer);
                m_ThisInstance.Play();

                List <Tuple <DynamicSoundEffectInstance, double> > list = (asEffect) ? m_EffectInstances : m_MusicInstances;
                list.Add(new Tuple <DynamicSoundEffectInstance, double>(m_ThisInstance, now + (m_ThisInstance.GetSampleDuration(buffer.Length).Milliseconds)));
            }
        }
Beispiel #19
0
        private static void PlaybackSpeech()
        {
            // trace the operation
            TraceHelper.AddMessage("About to playback speech");

            // create a sound effect instance
            DynamicSoundEffectInstance effect = new DynamicSoundEffectInstance(mic.SampleRate, AudioChannels.Mono);

            // submit all the buffers to the instance
            foreach (var buf in speechBufferList)
            {
                if (buf.Length > 0)
                {
                    effect.SubmitBuffer(buf);
                }
            }
            speechBufferList.Clear();

            // create an event handler to stop playback when all the buffers have been consumed
            effect.BufferNeeded += delegate
            {
                if (effect.PendingBufferCount == 0)
                {
                    effect.Stop();
                    TraceHelper.AddMessage("Finished playing back speech");
                }
            };

            // play the speech
            FrameworkDispatcher.Update();
            effect.Play();
        }
Beispiel #20
0
        internal void QueueBuffer(object sender, EventArgs args)
        {
            int bs;
            int cur   = 0;
            int total = 0;

            do
            {
                cur = (int)Vorbisfile.ov_read(
                    vorbisFile,
                    bufferPtr + total,
                    4096,
                    0,
                    2,
                    1,
                    out bs
                    );
                total += cur;
            } while (cur > 0 && total < (MAX_SAMPLES - 4096));

            // If we're at the end of the file, stop!
            if (total == 0)
            {
                eof = true;
                soundStream.BufferNeeded -= QueueBuffer;
                return;
            }

            // Send the filled buffer to the stream.
            soundStream.SubmitBuffer(
                vorbisBuffer,
                0,
                total
                );
        }
Beispiel #21
0
        public override void Update()
        {
            while (soundInstance.PendingBufferCount < 3)
            {
                var p8Buffer         = Emulator.Audio.RequestBuffer();
                var samplesPerBuffer = p8Buffer.Length;
                var audioBuffer      = new byte[samplesPerBuffer * 2];

                for (var i = 0; i < samplesPerBuffer; i += 1)
                {
                    var floatSample = p8Buffer[i];

                    var shortSample =
                        (short)(floatSample >= 0.0f ? floatSample * short.MaxValue : floatSample * short.MinValue * -1);

                    if (!BitConverter.IsLittleEndian)
                    {
                        audioBuffer[i * 2]     = (byte)(shortSample >> 8);
                        audioBuffer[i * 2 + 1] = (byte)shortSample;
                    }
                    else
                    {
                        audioBuffer[i * 2]     = (byte)shortSample;
                        audioBuffer[i * 2 + 1] = (byte)(shortSample >> 8);
                    }
                }

                soundInstance.SubmitBuffer(audioBuffer);
            }
        }
Beispiel #22
0
        private void HandleAudio()
        {
            //If enough has been gathered to submit, do so
            if (emu.APU.GetAudioBufferReady())
            {
                float[] buffer = emu.APU.GetAudioBuffer();

                for (int i = 0; i < APU.BufferSize; i++)
                {
                    float sample       = MathHelper.Clamp(buffer[i], 0, 1);
                    short signedSample = (short)(sample * (short.MaxValue - short.MinValue) + short.MinValue);

                    int index = i * 2;

                    if (!BitConverter.IsLittleEndian)
                    {
                        audioBuffer[index]     = (byte)(signedSample >> 8);
                        audioBuffer[index + 1] = (byte)signedSample;
                    }
                    else
                    {
                        audioBuffer[index]     = (byte)signedSample;
                        audioBuffer[index + 1] = (byte)(signedSample >> 8);
                    }
                }

                sound.SubmitBuffer(audioBuffer);
            }
        }
Beispiel #23
0
        // Private Methods

        private void SubmitBuffer()
        {
            ClearWorkingBuffer();
            FillWorkingBuffer();
            SoundHelper.ConvertBuffer(_workingBuffer, _xnaBuffer);
            _instance.SubmitBuffer(_xnaBuffer);
        }
        public void PlaySound(int samplingRate, byte[] pcmData)
        {
            DynamicSoundEffectInstance playback =
                new DynamicSoundEffectInstance(samplingRate, AudioChannels.Mono);

            playback.SubmitBuffer(pcmData);
            playback.Play();
        }
Beispiel #25
0
 void submitBuffer()
 {
     // clear the buffer before filling it
     Array.Clear(_workingBuffer, 0, channels * samplesPerBuffer);
     fillWorkingBuffer();
     SoundHelper.convertBuffer(_workingBuffer, _xnaBuffer);
     _instance.SubmitBuffer(_xnaBuffer);
 }
Beispiel #26
0
 private void UnlockBuffer(byte[] buffer)
 {
     lock (m_soundEffect)
     {
         m_soundEffect.SubmitBuffer(buffer);
         m_playQueue.Enqueue(buffer);
     }
 }
Beispiel #27
0
        public void TestPendingBufferCount()
        {
            mono8Bits = new DynamicSoundEffectInstance(defaultEngine, 44100, AudioChannels.Mono, AudioDataEncoding.PCM_8Bits);
            var dispInstance = new DynamicSoundEffectInstance(defaultEngine, 44100, AudioChannels.Stereo, AudioDataEncoding.PCM_16Bits);

            dispInstance.Dispose();

            var pendingCount = 0;

            ///////////////////////////////////////////////////////////////////////////
            // 1. Test that it throws ObjectDisposedException with disposed instance
            Assert.Throws <ObjectDisposedException>(() => pendingCount = dispInstance.PendingBufferCount, "PendingBufferCount did not throw ObjectDisposedException");

            //////////////////////////////////
            // 2. Test that it does not crash
            Assert.DoesNotThrow(() => pendingCount = mono8Bits.PendingBufferCount, "PendingBufferCount crashed with valid instance");

            ////////////////////////////
            // 3. Test the default value
            mono8Bits.Stop();
            Assert.AreEqual(0, mono8Bits.PendingBufferCount, "PendingBufferCount default value is not 0");

            //////////////////////////////////////////////////
            // 4. Check the value after adding some buffers
            mono8Bits.SubmitBuffer(generator.Generate(44100, new[] { 0f }, 1, 10000));
            mono8Bits.SubmitBuffer(generator.Generate(44100, new[] { 0f }, 1, 10000));
            mono8Bits.SubmitBuffer(generator.Generate(44100, new[] { 0f }, 1, 10000));
            Assert.AreEqual(3, mono8Bits.PendingBufferCount, "PendingBufferCount value is not 3 after adding buffers");

            //////////////////////////////////
            // 5. Check the value after stop
            mono8Bits.Stop();
            Assert.AreEqual(0, mono8Bits.PendingBufferCount, "PendingBufferCount default value is not 0");

            //////////////////////////////////
            // 6 Check the value after play
            mono8Bits.SubmitBuffer(generator.Generate(44100, new[] { 0f }, 1, 1000));
            mono8Bits.SubmitBuffer(generator.Generate(44100, new[] { 0f }, 1, 1000));
            mono8Bits.Play();
            Utilities.Sleep(1000);
            Assert.AreEqual(0, mono8Bits.PendingBufferCount, "PendingBufferCount value is not 0 after play");
            mono8Bits.Stop();

            mono8Bits.Dispose();
        }
Beispiel #28
0
 /// <summary>
 /// Gives samples to the DynamicSoundEffectInstance to play.
 /// Updates the position of the playback in the buffer.
 /// </summary>
 /// <param name="sender">DynamicSoundEffectInstance.</param>
 /// <param name="e">Event arguments.</param>
 private void GetSamples(object sender, EventArgs e)
 {
     // -44 for taking wav header into account
     while (playback.PendingBufferCount < 2 && position < byteArray.Length - 44)
     {
         playback.SubmitBuffer(byteArray, position, sampleSize);
         position += sampleSize;
     }
 }
Beispiel #29
0
        void sound_BufferNeeded(object sender, EventArgs e)
        {
            if (!isPlaying)
            {
                sound.SubmitBuffer(emptyBuffer);
            }
            else
            {
                short[] data   = mixer.MixToStream();
                byte[]  buffer = new byte[data.Length * sizeof(short)];
                for (int i = 0; i < data.Length; i++)
                {
                    BitConverter.GetBytes(data[i]).CopyTo(buffer, i * 2);
                }

                sound.SubmitBuffer(buffer);
            }
        }
Beispiel #30
0
 private void SubmitBuffer(int count = 1)
 {
     while (count > 0)
     {
         ReadFromStream();
         m_Instance.SubmitBuffer(m_WaveBuffer);
         count--;
     }
 }
Beispiel #31
0
        public void TestDispose()
        {
            var crossDisposedEngine = AudioEngineFactory.NewAudioEngine(); 
            var engine = AudioEngineFactory.NewAudioEngine();
            crossDisposedEngine.Dispose(); // Check there no Dispose problems with sereval cross-disposed instances. 

            // Create some SoundEffects
            SoundEffect soundEffect;
            using (var wavStream = AssetManager.FileProvider.OpenStream("EffectBip", VirtualFileMode.Open, VirtualFileAccess.Read))
            {
                soundEffect = SoundEffect.Load(engine, wavStream);
            }
            SoundEffect dispSoundEffect;
            using (var wavStream = AssetManager.FileProvider.OpenStream("EffectBip", VirtualFileMode.Open, VirtualFileAccess.Read))
            {
                dispSoundEffect = SoundEffect.Load(engine, wavStream);
            }
            dispSoundEffect.Dispose();

            var soundEffectInstance = soundEffect.CreateInstance();
            var dispInstance = soundEffect.CreateInstance();
            dispInstance.Dispose();

            // Create some SoundMusics.
            var soundMusic1 = SoundMusic.Load(engine, AssetManager.FileProvider.OpenStream("MusicBip", VirtualFileMode.Open, VirtualFileAccess.Read));
            var soundMusic2 = SoundMusic.Load(engine, AssetManager.FileProvider.OpenStream("MusicToneA", VirtualFileMode.Open, VirtualFileAccess.Read));
            soundMusic2.Dispose();

            // Create some dynamicSounds.
            var generator = new SoundGenerator();
            var dynSound1 = new DynamicSoundEffectInstance(engine, 44100, AudioChannels.Mono, AudioDataEncoding.PCM_8Bits);
            var dynSound2 = new DynamicSoundEffectInstance(engine, 20000, AudioChannels.Mono, AudioDataEncoding.PCM_8Bits);
            dynSound1.Play();
            dynSound1.SubmitBuffer(generator.Generate(44100, new[]{ 1000f }, 1, 120000));
            dynSound2.Dispose();

            // Start playing some
            soundEffectInstance.Play();
            soundMusic1.Play();

            for (int i = 0; i < 10; i++)
            {
                engine.Update();
                Utilities.Sleep(5);
            }

            Assert.DoesNotThrow(engine.Dispose, "AudioEngine crashed during disposal.");
            Assert.IsTrue(soundEffect.IsDisposed, "SoundEffect is not disposed.");
            Assert.Throws<InvalidOperationException>(engine.Dispose, "AudioEngine did not threw invalid operation exception.");
            Assert.AreEqual(SoundPlayState.Stopped, soundEffectInstance.PlayState, "SoundEffectInstance has not been stopped properly.");
            Assert.IsTrue(soundEffectInstance.IsDisposed, "SoundEffectInstance has not been disposed properly.");
            Assert.AreEqual(SoundPlayState.Stopped, soundMusic1.PlayState, "soundMusic1 has not been stopped properly.");
            Assert.IsTrue(soundMusic1.IsDisposed, "soundMusic1 has not been disposed properly.");
            //Assert.AreEqual(SoundPlayState.Stopped, dynSound1.PlayState, "The dynamic sound 1 has not been stopped correctly.");
            //Assert.IsTrue(dynSound1.IsDisposed, "The dynamic sound 1 has not been disposed correctly.");
        }
        public void TestBufferNeeded()
        {
            mono8Bits = new DynamicSoundEffectInstance(defaultEngine, 44100, AudioChannels.Mono, AudioDataEncoding.PCM_8Bits);

            mono8Bits.BufferNeeded += SetBufferNeededHasBeenCalledToTrue;

            var sizeOfOneSubBuffer = 44100 * 200 / 1000;

#if SILICONSTUDIO_PLATFORM_ANDROID
            sizeOfOneSubBuffer = mono8Bits.SubBufferSize;
#endif

            ////////////////////////////////////////////////////////////////////////////////////////////////////////
            // 1. Check that BufferNeeded is thrown when the user call plays with insufficient number of audio data
            mono8Bits.Play();
            Utilities.Sleep(50);
            Assert.IsTrue(bufferNeededHasBeenCalled, "Buffer Needed has not been called when the user played without any buffers");
            bufferNeededHasBeenCalled = false;
            mono8Bits.Stop();
            
            mono8Bits.SubmitBuffer(generator.Generate(44100, new[] { 0f }, 1, 1000));
            Utilities.Sleep(50);
            bufferNeededHasBeenCalled = false;
            mono8Bits.Play();
            Utilities.Sleep(50);
            Assert.IsTrue(bufferNeededHasBeenCalled, "Buffer Needed has not been called when the user played wit one buffers");
            bufferNeededHasBeenCalled = false;
            mono8Bits.Stop();
            
            ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
            // 2. Check that BufferNeeded is thrown when the user call SubmitBuffer with insufficient number of audio data
            mono8Bits.SubmitBuffer(generator.Generate(44100, new[] { 0f }, 1, sizeOfOneSubBuffer));
            Utilities.Sleep(50);
            Assert.IsTrue(bufferNeededHasBeenCalled, "Buffer Needed has not been called when the user submit the first buffer");
            bufferNeededHasBeenCalled = false;

            mono8Bits.SubmitBuffer(generator.Generate(44100, new[] { 0f }, 1, sizeOfOneSubBuffer));
            Utilities.Sleep(50);
            Assert.IsTrue(bufferNeededHasBeenCalled, "Buffer Needed has not been called when the user submit the second buffer");
            bufferNeededHasBeenCalled = false;
            mono8Bits.Stop();
            
            ////////////////////////////////////////////////////////////////////////////////////////////////////
            // 3. Check that BufferNeeded is thrown when the number of buffers falls from 3 to 2, 2 to 1, 1 to 0
            mono8Bits.SubmitBuffer(generator.Generate(44100, new[] { 0f }, 1, sizeOfOneSubBuffer));
            mono8Bits.SubmitBuffer(generator.Generate(44100, new[] { 0f }, 1, sizeOfOneSubBuffer));
            mono8Bits.SubmitBuffer(generator.Generate(44100, new[] { 0f }, 1, sizeOfOneSubBuffer));
            Utilities.Sleep(50);
            bufferNeededHasBeenCalled = false;
            mono8Bits.Play();
            var lastBufferCount = mono8Bits.PendingBufferCount;
            var loopCount = 0;
            while (true)
            {
                Utilities.Sleep(10);

                if (lastBufferCount != mono8Bits.PendingBufferCount)
                {
                    lastBufferCount = mono8Bits.PendingBufferCount;
                    Assert.IsTrue(bufferNeededHasBeenCalled, "Buffer Needed has not been called when number of buffer pass from "+(lastBufferCount+1)+" to "+lastBufferCount);
                    bufferNeededHasBeenCalled = false;
                }
                if (lastBufferCount == 0)
                    break;

                ++loopCount;

                if(loopCount>100)
                    Assert.Fail("The test process is block in the loop.");
            }
            mono8Bits.Stop();

            ///////////////////////////////////////////////////////////////////////////
            // 4. Check that invocation of BufferNeeded does not block audio playback
            mono8Bits.BufferNeeded -= SetBufferNeededHasBeenCalledToTrue;
            mono8Bits.BufferNeeded += GenerateNextDataAndBlockThead;

            mono8Bits.Play();
            Utilities.Sleep(2000);
            mono8Bits.Stop();

            mono8Bits.BufferNeeded -= GenerateNextDataAndBlockThead;
            mono8Bits.Dispose();
        }
        public void TestPendingBufferCount()
        {
            mono8Bits = new DynamicSoundEffectInstance(defaultEngine, 44100, AudioChannels.Mono, AudioDataEncoding.PCM_8Bits);
            var dispInstance = new DynamicSoundEffectInstance(defaultEngine, 44100, AudioChannels.Stereo, AudioDataEncoding.PCM_16Bits);
            dispInstance.Dispose();

            var pendingCount = 0;
            ///////////////////////////////////////////////////////////////////////////
            // 1. Test that it throws ObjectDisposedException with disposed instance
            Assert.Throws<ObjectDisposedException>(() => pendingCount = dispInstance.PendingBufferCount, "PendingBufferCount did not throw ObjectDisposedException");

            //////////////////////////////////
            // 2. Test that it does not crash
            Assert.DoesNotThrow(() => pendingCount = mono8Bits.PendingBufferCount, "PendingBufferCount crashed with valid instance");

            ////////////////////////////
            // 3. Test the default value
            mono8Bits.Stop();
            Assert.AreEqual(0, mono8Bits.PendingBufferCount, "PendingBufferCount default value is not 0");

            //////////////////////////////////////////////////
            // 4. Check the value after adding some buffers
            mono8Bits.SubmitBuffer(generator.Generate(44100, new[] { 0f }, 1, 10000));
            mono8Bits.SubmitBuffer(generator.Generate(44100, new[] { 0f }, 1, 10000));
            mono8Bits.SubmitBuffer(generator.Generate(44100, new[] { 0f }, 1, 10000));
            Assert.AreEqual(3, mono8Bits.PendingBufferCount, "PendingBufferCount value is not 3 after adding buffers");

            //////////////////////////////////
            // 5. Check the value after stop
            mono8Bits.Stop();
            Assert.AreEqual(0, mono8Bits.PendingBufferCount, "PendingBufferCount default value is not 0");

            //////////////////////////////////
            // 6 Check the value after play
            mono8Bits.SubmitBuffer(generator.Generate(44100, new[] { 0f }, 1, 1000));
            mono8Bits.SubmitBuffer(generator.Generate(44100, new[] { 0f }, 1, 1000));
            mono8Bits.Play();
            Utilities.Sleep(1000);
            Assert.AreEqual(0, mono8Bits.PendingBufferCount, "PendingBufferCount value is not 0 after play");
            mono8Bits.Stop();

            mono8Bits.Dispose();
        }
        public void TestSubmitBuffer()
        {
            mono8Bits = new DynamicSoundEffectInstance(defaultEngine, 44100, AudioChannels.Mono, AudioDataEncoding.PCM_8Bits);
            var mono16Bits = new DynamicSoundEffectInstance(defaultEngine, 44100, AudioChannels.Mono, AudioDataEncoding.PCM_16Bits);
            var stereo8Bits = new DynamicSoundEffectInstance(defaultEngine, 44100, AudioChannels.Stereo, AudioDataEncoding.PCM_8Bits);
            var stereo16Bits = new DynamicSoundEffectInstance(defaultEngine, 44100, AudioChannels.Stereo, AudioDataEncoding.PCM_16Bits);
            var dispInstance = new DynamicSoundEffectInstance(defaultEngine, 44100, AudioChannels.Stereo, AudioDataEncoding.PCM_16Bits);
            dispInstance.Dispose();

            ///////////////////////////////////////////////////////////////////////
            // 1. Test that it throws ObjectDisposedException with disposed instance
            Assert.Throws<ObjectDisposedException>(() => dispInstance.SubmitBuffer(new byte[16]), "SubmitBuffer did not throw ObjectDisposedException");

            ///////////////////////////////////////////////////////////
            // 2. Test that ArgumentNullException is correctly thrown
            Assert.Throws<ArgumentNullException>(() => mono8Bits.SubmitBuffer(null), "SubmitBuffer did not throw ArgumentNullException");

            /////////////////////////////////////////////////////////////////////////////
            // 3. Test that ArgumentException is correctly thrown when buffer length is 0
            Assert.Throws<ArgumentException>(() => mono8Bits.SubmitBuffer(new byte[0]), "SubmitBuffer did not throw ArgumentException with 0 length buffer");

            //////////////////////////////////////////////////////////////////////////////////////////////////////////////
            // 4. Test that ArgumentException is correctly thrown when buffer length do not respect alignment restrictions
            Assert.Throws<ArgumentException>(() => mono16Bits.SubmitBuffer(new byte[3]), "SubmitBuffer did not throw ArgumentException with 3 length buffer");

            ///////////////////////////////////////////////////////////////////////////
            // 5. Test that ArgumentOutOfRangeException is thrown with negative offset
            Assert.Throws<ArgumentOutOfRangeException>(() => mono8Bits.SubmitBuffer(new byte[16], -1, 3), "SubmitBuffer did not throw ArgumentOutOfRangeException with -1 offset");

            //////////////////////////////////////////////////////////////////////////////////////////////
            // 6. Test that ArgumentOutOfRangeException is thrown with offset greater than buffer length
            Assert.Throws<ArgumentOutOfRangeException>(() => mono8Bits.SubmitBuffer(new byte[16], 16, 3), "SubmitBuffer did not throw ArgumentOutOfRangeException with 16 offset");

            //////////////////////////////////////////////////////////////////////////////////
            // 7. Test that ArgumentOutOfRangeException is thrown with byteCount is negative
            Assert.Throws<ArgumentOutOfRangeException>(() => mono8Bits.SubmitBuffer(new byte[16], 16, -1), "SubmitBuffer did not throw ArgumentOutOfRangeException with -1 bytecount");

            ////////////////////////////////////////////////////////////////////////////////////////////
            // 8. Test that ArgumentOutOfRangeException is thrown with offset+byteCount is more buffer length
            Assert.Throws<ArgumentOutOfRangeException>(() => mono8Bits.SubmitBuffer(new byte[16], 10, 7), "SubmitBuffer did not throw ArgumentOutOfRangeException with offset+bytecount greater than buffer length.");

            /////////////////////////////////////////////////////////////////////////////////////////
            // 9. Check that submitting mono-8bits signals does not crash and has the good behaviour
            Assert.DoesNotThrow(()=>mono8Bits.SubmitBuffer(generator.Generate(44100, new[] { 40000f }, 1, 88200 )), "SubmitBuffer on mono8Bits crached.");
            mono8Bits.Play();
            Utilities.Sleep(2500);
            
            /////////////////////////////////////////////////////////////////////////////////////////
            // 10. Check that submitting mono-16bits signals does not crash and has the good behaviour
            Assert.DoesNotThrow(() => mono16Bits.SubmitBuffer(generator.Generate(44100, new[] { 40000f }, 2, 176400)), "SubmitBuffer on mono16Bits crached.");
            mono16Bits.Play();
            Utilities.Sleep(2500);
            
            ///////////////////////////////////////////////////////////////////////////////////////////
            // 11. Check that submitting stereo-8bits signals does not crash and has the good behaviour
            Assert.DoesNotThrow(() => stereo8Bits.SubmitBuffer(generator.Generate(44100, new[] { 40000f, 20000f }, 1, 176400)), "SubmitBuffer on stereo8Bits crached.");
            stereo8Bits.Play();
            Utilities.Sleep(2500);
            
            ///////////////////////////////////////////////////////////////////////////////////////////
            // 12 Check that submitting stereo-16bits signals does not crash and has the good behaviour
            Assert.DoesNotThrow(() => stereo16Bits.SubmitBuffer(generator.Generate(44100, new[] { 40000f, 10000f }, 2, 352800)), "SubmitBuffer on stereo16Bits crached.");
            stereo16Bits.Play();
            Utilities.Sleep(2500);

            /////////////////////////////////////////////////////////////////////
            // 13. Check that offset and byte count works in SubmitBuffer method
            var buffer1 = generator.Generate(44100, new[] { 10000f }, 1, 44100);
            var buffer2 = generator.Generate(44100, new[] { 40000f }, 1, 44100);
            var buffer3 = generator.Generate(44100, new[] { 80000f }, 1, 44100);
            var totalBuffer = new byte[132300];
            Array.Copy(buffer1, totalBuffer, 44100);
            Array.Copy(buffer2, 0, totalBuffer, 44100, 44100);
            Array.Copy(buffer3, 0, totalBuffer, 88200, 44100);

            Assert.DoesNotThrow(() => mono8Bits.SubmitBuffer(totalBuffer, 44100, 44100), "SubmitBuffer with offset and bytecount crached.");
            mono8Bits.Play();
            Utilities.Sleep(1500);

            mono8Bits.Dispose();
            mono16Bits.Dispose();
            stereo8Bits.Dispose();
            stereo16Bits.Dispose();
        }