예제 #1
0
        protected override void PrepareInternal()
        {
            base.PrepareInternal();

            begin = true;
            if (byteBuffer != null)
            {
                return;
            }

            compressedSoundStream.Position = 0;
            currentPacketIndex             = 0;
            startPktSampleIndex            = 0;
            endPktSampleIndex = 0;
            endPacketIndex    = numberOfPackets;

            PlayRange range;

            lock (rangeLock)
            {
                range = playRange;
            }

            // Reset decoder state
            decoder.ResetDecoder();

            // Ignore invalid data at beginning (due to encoder delay) & end of stream (due to packet size)
            var samplesToSkip = decoder.GetDecoderSampleDelay();

            var frameSize = SamplesPerFrame * channels;
            //ok we need to handle this case properly, this means that the user wants to use a different then full audio stream range...
            var sampleStart = (channels * samplesToSkip) + (int)Math.Floor(sampleRate * (double)channels * range.Start.TotalSeconds);

            startPktSampleIndex = sampleStart % (frameSize);

            var sampleStop = (channels * samplesToSkip)
                             + (range.Length != TimeSpan.Zero
                    ? (int)Math.Floor(sampleRate * (double)channels * range.End.TotalSeconds)
                    : (channels * samples));

            endPktSampleIndex = frameSize - sampleStop % frameSize;

            var skipCounter = startingPacketIndex = sampleStart / frameSize;

            endPacketIndex = sampleStop / frameSize;

            // skip to the starting packet
            if (startingPacketIndex < numberOfPackets && endPacketIndex < numberOfPackets && startingPacketIndex < endPacketIndex)
            {
                //valid offsets.. process it
                while (skipCounter-- > 0)
                {
                    //skip data to reach starting packet
                    var len = reader.ReadInt16();
                    compressedSoundStream.Position = compressedSoundStream.Position + len;
                    currentPacketIndex++;
                }
            }
        }
예제 #2
0
        protected override void PrepareInternal()
        {
            base.PrepareInternal();

            begin = true;
            if (ByteBuffer != null)
            {
                return;
            }

            compressedSoundStream.Position = 0;
            currentPacketIndex             = 0;
            startPktSampleIndex            = 0;
            endPktSampleIndex = 0;
            endPacketIndex    = numberOfPackets;

            PlayRange range;

            lock (rangeLock)
            {
                range = playRange;
            }

            if (range.Start != TimeSpan.Zero || range.Length != TimeSpan.Zero)
            {
                var frameSize = SamplesPerFrame * channels;
                //ok we need to handle this case properly, this means that the user wants to use a different then full audio stream range...
                var sampleStart = sampleRate * (double)channels * range.Start.TotalSeconds;
                startPktSampleIndex = (int)Math.Floor(sampleStart) % (frameSize);

                var sampleStop = sampleRate * (double)channels * range.End.TotalSeconds;
                endPktSampleIndex = frameSize - (int)Math.Floor(sampleStart) % frameSize;

                var skipCounter = startingPacketIndex = (int)Math.Floor(sampleStart / frameSize);
                endPacketIndex = (int)Math.Floor(sampleStop / frameSize);

                // skip to the starting packet
                if (startingPacketIndex < numberOfPackets && endPacketIndex < numberOfPackets && startingPacketIndex < endPacketIndex)
                {
                    //valid offsets.. process it
                    while (skipCounter-- > 0)
                    {
                        //skip data to reach starting packet
                        var len = reader.ReadInt16();
                        compressedSoundStream.Position = compressedSoundStream.Position + len;
                        currentPacketIndex++;
                    }
                }
            }
        }
예제 #3
0
        internal void LoadSoundInMemory()
        {
            if (PreloadedBuffer.Ptr != IntPtr.Zero)
            {
                return;
            }

            using (var soundStream = ContentManager.FileProvider.OpenStream(CompressedDataUrl, VirtualFileMode.Open, VirtualFileAccess.Read, VirtualFileShare.Read, StreamFlags.Seekable))
                using (var decoder = new Celt(SampleRate, CompressedSoundSource.SamplesPerFrame, Channels, true))
                {
                    var reader           = new BinarySerializationReader(soundStream);
                    var samplesPerPacket = CompressedSoundSource.SamplesPerFrame * Channels;

                    PreloadedBuffer = AudioLayer.BufferCreate(samplesPerPacket * NumberOfPackets * sizeof(short));

                    var memory = new UnmanagedArray <short>(samplesPerPacket * NumberOfPackets);

                    var offset       = 0;
                    var outputBuffer = new short[samplesPerPacket];
                    for (var i = 0; i < NumberOfPackets; i++)
                    {
                        var len = reader.ReadInt16();
                        var compressedBuffer = reader.ReadBytes(len);
                        var samplesDecoded   = decoder.Decode(compressedBuffer, len, outputBuffer);
                        memory.Write(outputBuffer, offset, 0, samplesDecoded * Channels);
                        offset += samplesDecoded * Channels * sizeof(short);
                    }

                    AudioLayer.BufferFill(PreloadedBuffer, memory.Pointer, memory.Length * sizeof(short), SampleRate, Channels == 1);
                    memory.Dispose();
                }
        }
예제 #4
0
        public override void Serialize(ref Sound obj, ArchiveMode mode, SerializationStream stream)
        {
            if (mode == ArchiveMode.Deserialize)
            {
                var services    = stream.Context.Tags.Get(ServiceRegistry.ServiceRegistryKey);
                var audioEngine = services.GetServiceAs <IAudioEngineProvider>()?.AudioEngine;

                obj.CompressedDataUrl = stream.ReadString();
                obj.SampleRate        = stream.ReadInt32();
                obj.Channels          = stream.ReadByte();
                obj.StreamFromDisk    = stream.ReadBoolean();
                obj.Spatialized       = stream.ReadBoolean();
                obj.NumberOfPackets   = stream.ReadInt16();
                obj.MaxPacketLength   = stream.ReadInt16();

                if (!obj.StreamFromDisk && audioEngine != null && audioEngine.State != AudioEngineState.Invalidated && audioEngine.State != AudioEngineState.Disposed) //immediatelly preload all the data and decode
                {
                    using (var soundStream = ContentManager.FileProvider.OpenStream(obj.CompressedDataUrl, VirtualFileMode.Open, VirtualFileAccess.Read, VirtualFileShare.Read, StreamFlags.Seekable))
                        using (var decoder = new Celt(obj.SampleRate, CompressedSoundSource.SamplesPerFrame, obj.Channels, true))
                        {
                            var reader           = new BinarySerializationReader(soundStream);
                            var samplesPerPacket = CompressedSoundSource.SamplesPerFrame * obj.Channels;

                            obj.PreloadedBuffer = AudioLayer.BufferCreate(samplesPerPacket * obj.NumberOfPackets * sizeof(short));

                            var memory = new UnmanagedArray <short>(samplesPerPacket * obj.NumberOfPackets);

                            var offset       = 0;
                            var outputBuffer = new short[samplesPerPacket];
                            for (var i = 0; i < obj.NumberOfPackets; i++)
                            {
                                var len = reader.ReadInt16();
                                var compressedBuffer = reader.ReadBytes(len);
                                var samplesDecoded   = decoder.Decode(compressedBuffer, len, outputBuffer);
                                memory.Write(outputBuffer, offset, 0, samplesDecoded * obj.Channels);
                                offset += samplesDecoded * obj.Channels * sizeof(short);
                            }

                            AudioLayer.BufferFill(obj.PreloadedBuffer, memory.Pointer, memory.Length * sizeof(short), obj.SampleRate, obj.Channels == 1);
                            memory.Dispose();
                        }
                }

                if (audioEngine != null)
                {
                    obj.Attach(audioEngine);
                }
            }
            else
            {
                stream.Write(obj.CompressedDataUrl);
                stream.Write(obj.SampleRate);
                stream.Write((byte)obj.Channels);
                stream.Write(obj.StreamFromDisk);
                stream.Write(obj.Spatialized);
                stream.Write((short)obj.NumberOfPackets);
                stream.Write((short)obj.MaxPacketLength);
            }
        }
예제 #5
0
        protected override void PrepareInternal()
        {
            base.PrepareInternal();

            begin = true;
            if (byteBuffer != null)
            {
                return;
            }

            compressedSoundStream.Position = 0;
            currentPacketIndex             = 0;
            startPktSampleIndex            = 0;
            endPktSampleIndex = 0;
            endPacketIndex    = numberOfPackets;

            PlayRange range;

            lock (rangeLock)
            {
                range = playRange;
            }

            // Reset decoder state
            decoder.ResetDecoder();

            // Ignore invalid data at beginning (due to encoder delay) & end of stream (due to packet size)
            var samplesToSkip = decoder.GetDecoderSampleDelay();

            // Compute boundaries
            var sampleBegin = (channels * samplesToSkip);
            var sampleEnd   = sampleBegin + (channels * samples);

            var frameSize = SamplesPerFrame * channels;
            //ok we need to handle this case properly, this means that the user wants to use a different then full audio stream range...
            var sampleStart = sampleBegin + (int)Math.Floor(sampleRate * (double)channels * range.Start.TotalSeconds);

            // Make sure start is at least one sample before the end to avoid edge cases where startingPacketIndex == numberOfPackets
            sampleStart = Math.Min(Math.Max(sampleStart, sampleBegin), sampleEnd - 1 * channels);

            var sampleStop = sampleBegin
                             + (range.Length != TimeSpan.Zero
                    ? (int)Math.Floor(sampleRate * (double)channels * range.End.TotalSeconds)
                    : (channels * samples));

            // Make sure stop is at least one sample after start
            sampleStop = Math.Min(Math.Max(sampleStop, sampleStart + 1 * channels), sampleEnd);

            // Compute start/end packet
            startingPacketIndex = sampleStart / frameSize;
            endPacketIndex      = (sampleStop - 1) / frameSize; // -1 to make sure we stay in last packet if using all of it

            // How much data to use in start/end packet
            startPktSampleIndex = sampleStart % (frameSize);
            endPktSampleIndex   = frameSize - sampleStop % frameSize;

            // skip to the starting packet
            if (startingPacketIndex < numberOfPackets && endPacketIndex < numberOfPackets && startingPacketIndex <= endPacketIndex) // this shouldn't happen anymore with the min/max clamps
            {
                //valid offsets.. process it
                var skipCounter = startingPacketIndex;
                while (skipCounter-- > 0)
                {
                    //skip data to reach starting packet
                    var len = reader.ReadInt16();
                    compressedSoundStream.Position = compressedSoundStream.Position + len;
                    currentPacketIndex++;
                }
            }
        }