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++; } } }
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++; } } } }
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(); } }
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); } }
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++; } } }