Ejemplo n.º 1
0
        /// <summary>
        /// Tries to retrieve the next available ALAC frame
        /// </summary>
        /// <param name="frame">Will be set to the retrieved frame if successful</param>
        /// <returns>True if successful, False if waiting for next frame and null if the audio buffer has been stopped</returns>
        public bool?GetNextFrame(out byte[] frame, out uint timeStamp)
        {
            frame     = null;
            timeStamp = 0;

            if (bufferStopped)
            {
                return(null);
            }

            lock (syncRoot)
            {
                if (bufferStopped)
                {
                    return(null);
                }

                if (!bufferInit || actualBufferSize < 1 || !synced)
                {
                    if (synced && actualBufferSize < 1)
                    {
                        //Buffer underrun
                        Logger.Warn("Audio Buffer: Underrun");
                    }
                    // Signal we're waiting and wait for next packet
                    Logger.Debug("Audio Buffer: Waiting for new packet");
                    decoderStopped = true;
                    Monitor.Wait(syncRoot);
                    if (bufferStopped)
                    {
                        return(null);
                    }
                    Logger.Debug("Audio Buffer: New packet received");
                    decoderStopped = false;
                    OnBufferRestart();
                }

                // Overrunning. Restart at a sane distance
                if (actualBufferSize >= maxBufferFrames)
                {
                    Logger.Debug("Buffer overrun");
                    readIndex = (ushort)(writeIndex - startFill);
                }

                for (int i = 16; i < (startFill / 2); i = i * 2)
                {
                    int next = readIndex + i;
                    if (!audioBuffer[next % maxBufferFrames].Ready)
                    {
                        OnMissingPackets(new MissingPacketEventArgs(next, next + 1));
                    }
                }

                AudioData buffer = audioBuffer[readIndex % maxBufferFrames];
                bool      ready  = buffer.Ready;
                if (ready)
                {
                    timeStamp    = buffer.TimeStamp;
                    frame        = ProcessNextPacket(buffer.Data);
                    buffer.Ready = false;
                }
                else
                {
                    //Logger.Warn("Audio Buffer: Missing packet {0}", readIndex);
                }

                readIndex++;
                actualBufferSize = (ushort)(writeIndex - readIndex);
                OnPacketTaken();

                return(ready);
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Decrypts and adds the audio data to the buffer
        /// </summary>
        /// <param name="seqno">The sequence number of the packet</param>
        /// <param name="timestamp">The timestamp of the packet</param>
        /// <param name="data">The encrypted audio packet</param>
        public void PutPacketInBuffer(ushort seqno, uint timestamp, byte[] data)
        {
            if (bufferStopped)
            {
                return;
            }

            bool fireStarted = false;
            bool fireReady   = false;

            lock (syncRoot)
            {
                if (bufferStopped)
                {
                    return;
                }

                if (!synced)
                {
                    writeIndex = seqno;
                    readIndex  = seqno;
                    synced     = true;
                }

                AudioData buffer = audioBuffer[seqno % maxBufferFrames];
                if (seqno == writeIndex)
                {
                    //Packet we expected
                    buffer.Data      = data;
                    buffer.TimeStamp = timestamp;
                    buffer.Ready     = true;
                    writeIndex++;
                }
                else if (isSequence(writeIndex, seqno))
                {
                    //Too early, missed packets between writeIndex and seqno
                    //Logger.Debug("Audio Buffer: Received packet early. Expected: {0}, Received: {1}", writeIndex, seqno);
                    //OnMissingPackets(new MissingPacketEventArgs(writeIndex, seqno)); //ask to resend
                    buffer.Data      = data;
                    buffer.TimeStamp = timestamp;
                    buffer.Ready     = true;
                    //jump to new seq no.
                    writeIndex = (ushort)(seqno + 1);
                }
                else if (isSequence(readIndex, seqno))
                {
                    //Less than write index but greater than read so not yet played, insert
                    //Logger.Debug("Audio Buffer: Received packet late but still in time to play. Expected: {0}, Received: {1}", writeIndex, seqno);
                    buffer.Data      = data;
                    buffer.TimeStamp = timestamp;
                    buffer.Ready     = true;
                    return;
                }
                else
                {
                    //Already played
                    Logger.Warn("Audio Buffer: Received packet late. Expected: {0}, Received: {1}", writeIndex, seqno);
                    return;
                }

                // The number of packets in buffer
                actualBufferSize = (ushort)(writeIndex - readIndex);

                if (!bufferStarted && actualBufferSize > 0)
                {
                    bufferStarted = true;
                    fireStarted   = true;
                }

                if (actualBufferSize > startFill)
                {
                    if (!bufferInit)
                    {
                        bufferInit = true;
                        fireReady  = true;
                        Monitor.PulseAll(syncRoot);
                    }
                    else if (decoderStopped)
                    {
                        Monitor.PulseAll(syncRoot);
                    }
                }
            }

            if (fireStarted)
            {
                OnBufferStarted();
            }
            if (fireReady)
            {
                OnBufferReady();
            }
        }