示例#1
0
        private static void osd_update_audio_stream(byte[] buffer, int samples_this_frame)
        {
            int play_position, write_position;
            int stream_in;

            byte[] buffer1, buffer2;
            int    length1, length2;

            buf2.GetCurrentPosition(out play_position, out write_position);
            if (write_position < play_position)
            {
                write_position += 0x9400;
            }
            stream_in = stream_buffer_in;
            if (stream_in < write_position)
            {
                stream_in += 0x9400;
            }
            while (stream_in < write_position)
            {
                //buffer_underflows++;
                stream_in += 0xf00;
            }
            if (stream_in + 0xf00 > play_position + 0x9400)
            {
                //buffer_overflows++;
                return;
            }
            stream_buffer_in = stream_in % 0x9400;
            if (stream_buffer_in + 0xf00 < 0x9400)
            {
                length1 = 0xf00;
                length2 = 0;
                buffer1 = new byte[length1];
                Array.Copy(buffer, buffer1, length1);
                buf2.Write(stream_buffer_in, buffer1, LockFlag.None);
                stream_buffer_in = stream_buffer_in + 0xf00;
            }
            else if (stream_buffer_in + 0xf00 == 0x9400)
            {
                length1 = 0xf00;
                length2 = 0;
                buffer1 = new byte[length1];
                Array.Copy(buffer, buffer1, length1);
                buf2.Write(stream_buffer_in, buffer1, LockFlag.None);
                stream_buffer_in = 0;
            }
            else if (stream_buffer_in + 0xf00 > 0x9400)
            {
                length1 = 0x9400 - stream_buffer_in;
                length2 = 0xf00 - length1;
                buffer1 = new byte[length1];
                buffer2 = new byte[length2];
                Array.Copy(buffer, buffer1, length1);
                Array.Copy(buffer, length1, buffer2, 0, length2);
                buf2.Write(stream_buffer_in, buffer1, LockFlag.None);
                buf2.Write(0, buffer2, LockFlag.None);
                stream_buffer_in = length2;
            }
        }
示例#2
0
 public void Pause()
 {
     if (buffer != null)
     {
         try
         {
             if (buffer.Status.Playing)
             {
                 buffer.Stop();
             }
         }
         catch (AccessViolationException) { }
         int trash;
         buffer.GetCurrentPosition(out m_lastPlayingPosition, out trash);
     }
 }
示例#3
0
        void Play()
        {
            int playPos;
            int writePos;
            int lockSize;

            try
            {
                m_Buffer.GetCurrentPosition(out playPos, out writePos);
                lockSize = writePos - nextWriteOffset;
                if (lockSize < 0)
                {
                    lockSize += m_BufferBytes;
                }

                // Block align lock size so that we are always write on a boundary
                lockSize -= (lockSize % notifySize);

                if (0 == lockSize)
                {
                    return;
                }
                if (lockSize == m_BufferBytes)
                {
                }

                byte[] writeBytes = new byte[lockSize];

                if (circularBuffer.Read(writeBytes) > 0)
                {
                    m_Buffer.Write(nextWriteOffset, writeBytes, LockFlag.None);

                    // Move the capture offset along
                    nextWriteOffset += lockSize;
                    nextWriteOffset %= m_BufferBytes; // Circular buffer
                }
            }
            catch (Exception)
            {
            }
            finally
            {
            }
        }
示例#4
0
        /// <summary>
        /// The stream control thread raises events every half the stream.
        /// When the BufferNotificationEventArgs contains a SoundFinished property set to true, the
        /// current buffer segment is padded with silence.  At the next notification, the next
        /// buffer segment is filled with silence, and no event is raised.
        /// At the next notification, which will come when the padded segment
        /// (not the completely silent segment) is finished, the SecondaryBuffer is stopped and
        /// the thread terminated.
        /// </summary>
        private void StreamControlThread()
        {
            int nextPlaceForBytes     = 0;
            int wholeBufferSize       = SB.Caps.BufferBytes;
            int byteWindowSize        = wholeBufferSize / 2;
            NextNotificationTask task = NextNotificationTask.FillSectionWithNewSound;

            //BufferNotificationEventArgs ssea = new BufferNotificationEventArgs(SB.Caps.BufferBytes);
            BufferNotificationEventArgs firstNotificationEventArgs = new BufferNotificationEventArgs(wholeBufferSize);

            GetBytesByRaisingEvent(0, wholeBufferSize, firstNotificationEventArgs);
            task = HandleNewBytesInControlThread(nextPlaceForBytes, wholeBufferSize, firstNotificationEventArgs);


            bool terminate = false;

            while (!terminate)
            {
                NotificationEvent.Reset();
                NotificationEvent.WaitOne();

                if (SB.Disposed || (!Playing))
                {
                    break;
                }

                /// Very strange behavior from DirectSound!!
                /// SB.PlayPosition returns a value slightly less than the actual position.  Either that or the event is raised
                /// So you can use that to determine which section to fill.  Fill the half that you're currently "playing"
                /// according to the PlayPosition.
                /// If anyone knows how to do this properly, please e-mail me, [email protected].
                int playPosition = SB.PlayPosition;
                int distToBegin  = Math.Abs(playPosition - 0);
                int distToEnd    = Math.Abs(playPosition - wholeBufferSize);
                int distToMid    = Math.Abs(playPosition - byteWindowSize);

                if (distToMid < distToEnd && distToMid < distToBegin)
                {
                    nextPlaceForBytes = 0;
                }
                else
                {
                    nextPlaceForBytes = byteWindowSize;
                }
                //Console.WriteLine(DateTime.Now + ": Received request for bytes at " + nextPlaceForBytes + " and I'm now at " + SB.PlayPosition);
                switch (task)
                {
                case NextNotificationTask.FillSectionWithNewSound:
                    BufferNotificationEventArgs nextNotificationEventArgs = new BufferNotificationEventArgs(byteWindowSize);
                    GetBytesByRaisingEvent(nextPlaceForBytes, byteWindowSize, nextNotificationEventArgs);
                    task = HandleNewBytesInControlThread(nextPlaceForBytes, byteWindowSize, nextNotificationEventArgs);
                    break;

                case NextNotificationTask.FillSectionWithSilence:
                    task = NextNotificationTask.StopSecondaryBufferAndThread;
                    //Console.WriteLine("Filling section with silence at " + nextPlaceForBytes);
                    int currentPosition = 0; int writePos = 0;
                    SB.GetCurrentPosition(out currentPosition, out writePos);
                    //Console.WriteLine("Current pos " + currentPosition + " and writing " + byteWindowSize + " at " + nextPlaceForBytes);
                    SB.Write(nextPlaceForBytes, new byte[byteWindowSize], LockFlag.None);
                    break;

                default:                         // NextNotificationTask.StopSecondaryBufferAndThread
                    SB.Stop();
                    //Console.WriteLine("stream control thread dies.");
                    return;
                }
                //nextPlaceForBytes += byteWindowSize; if (nextPlaceForBytes >= SB.Caps.BufferBytes) nextPlaceForBytes = 0;
            }
            //Console.WriteLine("stream control thread dies.");
        }
示例#5
0
        public void Write(AudioBuffer src)
        {
            //wavoutput.Write(src);

            pcmStream.SetLength(0);
            pcmStream.Write(src.Bytes, 0, src.ByteLength);
            pcmStream.Position = 0;
            //pcmStream.Position = 0;

            //while (true)
            //{
            //    if (SecBufInitialLoad)
            //    {
            //        int count = Math.Min(src.ByteLength, SecBufByteSize - SecBufNextWritePosition);
            //        if (count > 0)
            //        {
            //            secondaryBuffer.Write(SecBufNextWritePosition, pcmStream, count, LockFlag.None);
            //            SecBufNextWritePosition += count;
            //            pcmStream.Position += count;
            //        }

            //        if (SecBufByteSize == SecBufNextWritePosition)
            //        {
            //            // Finished filling the buffer
            //            SecBufInitialLoad = false;
            //            SecBufNextWritePosition = 0;

            //            // So start the playback in its own thread
            //            secondaryBuffer.Play(0, BufferPlayFlags.Looping);

            //            // Yield rest of timeslice so playback can
            //            // start right away.
            //            Thread.Sleep(0);
            //        }
            //        else
            //        {
            //            continue;  // Get more PCM data
            //        }
            //    }

            // Exhaust the current PCM data by writing the data into secondaryBuffer
            while (pcmStream.Position < pcmStream.Length)
            {
                int PlayPosition, WritePosition;

                secondaryBuffer.GetCurrentPosition(out PlayPosition, out WritePosition);

                int WriteCount = (int)Math.Min(
                    (SecBufByteSize + PlayPosition - WritePosition) % SecBufByteSize,
                    pcmStream.Length - pcmStream.Position);

                if (WriteCount > 0)
                {
                    secondaryBuffer.Write(
                        WritePosition,
                        pcmStream,
                        WriteCount,
                        LockFlag.None);
                    pcmStream.Position += WriteCount;
                    if (!playing)
                    {
                        secondaryBuffer.Play(0, 0);
                        playing = true;
                    }
                }
                else
                {
                    WaitHandle.WaitAny(SecBufWaitHandles, new TimeSpan(0, 0, 5), true);
                }
            }
        }
示例#6
0
 /// <summary>
 /// 将新收到的音频数据存入辅助播放缓冲区,准备播放
 /// </summary>
 /// <param name="secBuf">辅助播放缓冲区</param>
 void m_objVP_ReadyForNewData(SecondaryBuffer secBuf)
 {
     try
     {
         int curPlayPos, curWritePos;
         secBuf.GetCurrentPosition(out curPlayPos, out curWritePos);
         //                Write( "curWritePos[" + curWritePos.ToString() + "]"
         //                     + "curPlay[" 	  + curPlayPos.ToString()  + "]");
         // 写到下一个写入通知之前
         int lockSize;// = m_nNextWritePos - curWritePos;
         #region 测试代码
         //curWritePos = (curWritePos / m_objVP.nNotifySize) * m_objVP.nNotifySize;
         lockSize = m_objVP.nNotifySize;
         #endregion
         if (lockSize < 0) lockSize += m_objVP.nBufSize;
         if (0 != lockSize)
         {
             byte[] data = new byte[lockSize];
             if (m_objBuf.Read(data) > 0)
             {
                 secBuf.Write(curWritePos, data, LockFlag.FromWriteCursor);
                 m_nNextWritePos = (m_nNextWritePos + m_objVP.nNotifySize) % m_objVP.nBufSize;
                 // Write( "curWritePos[" + curWritePos.ToString() + "]"
                 //      + "dataLength["  + data.Length.ToString() + "]");
             } // end of if
         } // end of if
     }
     catch
     {
     }
 }