internal void LoadSoundInMemory() { if (PreloadedBuffer.Ptr != IntPtr.Zero) { return; } using (var soundStream = 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); } // Ignore invalid data at beginning (due to encoder delay) & end of stream (due to packet size) var samplesToSkip = decoder.GetDecoderSampleDelay(); AudioLayer.BufferFill(PreloadedBuffer, memory.Pointer + samplesToSkip * Channels * sizeof(short), Samples * Channels * sizeof(short), SampleRate, Channels == 1); memory.Dispose(); } }
protected override unsafe void ExtractAndFillData() { if (byteBuffer != null) { int maxSize = 100 * 1000; int bufferLen = byteBuffer.Length; int remainingLen = bufferLen - byteBufferCurrentPosition; int countByteTransfered = remainingLen > maxSize ? maxSize : remainingLen; short[] sdata = new short[(int)Math.Ceiling((decimal)(countByteTransfered / 2))]; Buffer.BlockCopy(byteBuffer, byteBufferCurrentPosition, sdata, 0, countByteTransfered); byteBufferCurrentPosition += countByteTransfered; bool endingPacket = byteBufferCurrentPosition == bufferLen; var bufferType = AudioLayer.BufferType.None; if (endingPacket) { bufferType = looped ? AudioLayer.BufferType.EndOfLoop : AudioLayer.BufferType.EndOfStream; } else if (begin) { bufferType = AudioLayer.BufferType.BeginOfStream; begin = false; } FillBuffer(sdata, countByteTransfered, bufferType); } else { const int passes = SamplesPerBuffer / SamplesPerFrame; var offset = 0; var bufferPtr = (short *)utilityBuffer.Pointer; var startingPacket = startingPacketIndex == currentPacketIndex; var endingPacket = false; for (var i = 0; i < passes; i++) { endingPacket = endPacketIndex == currentPacketIndex; //read one packet, size first, then data var len = reader.ReadInt16(); compressedSoundStream.Read(compressedBuffer, 0, len); currentPacketIndex++; var writePtr = bufferPtr + offset; if (decoder.Decode(compressedBuffer, len, writePtr) != SamplesPerFrame) { throw new Exception("Celt decoder returned a wrong decoding buffer size."); } offset += SamplesPerFrame * channels; if (endingPacket || compressedSoundStream.Position == compressedSoundStream.Length) { break; } } // Send buffer to hardware var finalPtr = new IntPtr(bufferPtr + (startingPacket ? startPktSampleIndex : 0)); var finalSize = (offset - (startingPacket ? startPktSampleIndex : 0) - (endingPacket ? endPktSampleIndex : 0)) * sizeof(short); var bufferType = AudioLayer.BufferType.None; if (endingPacket) { bufferType = looped ? AudioLayer.BufferType.EndOfLoop : AudioLayer.BufferType.EndOfStream; } else if (begin) { bufferType = AudioLayer.BufferType.BeginOfStream; begin = false; } FillBuffer(finalPtr, finalSize, bufferType); // Go back to beginning if necessary if (endingPacket || compressedSoundStream.Position == compressedSoundStream.Length) { if (looped) //prepare again to play from begin { PrepareInternal(); } else // stops the sound { StopInternal(false); } } } }