//public Stream GetStream() //{ // MemoryStream mem = new MemoryStream(); // using (Stream raw = GetRawStream()) // using (IDecompressor decompressor = CompressorFactory.GetDecompressor(Compression)) // decompressor.Decompress(raw).CopyTo(mem); // mem.Position = 0; // return mem; // // return decompressor.Decompress(); //} public void CopyToMemory(Memory <byte> memory) { if (memory.Length < (int)UncompressedLength) { throw new ArgumentException("Memory buffer must be at least the uncompressed size of the chunk"); } using var rawStream = GetRawStream(); if (Compression == ArchiveChunkCompression.Zstandard) { using var zstdDecompressor = new ZstdDecompressor(); using var buffer = MemoryPool <byte> .Shared.Rent((int) CompressedLength); var compressedMemory = buffer.Memory.Slice(0, (int)CompressedLength); rawStream.Read(compressedMemory.Span); zstdDecompressor.DecompressData(compressedMemory.Span, memory.Span, out _); } else { rawStream.Read(memory.Span); } }
/// <summary> /// Handler for any pipe requests. /// </summary> /// <param name="request">The command to execute.</param> /// <param name="argument">Any additional arguments.</param> /// <param name="handler">The streamhandler to use.</param> private static void Server_OnRequest(string request, string argument, StreamHandler handler) { if (request == "ready") { //Notify the AA2 instance that we are ready if (IsLoaded) { Console.WriteLine("Connected to pipe"); } handler.WriteString(IsLoaded.ToString()); } else if (request == "matchfiles") { //Send a list of all loaded .pp files if (LogFiles) { Console.WriteLine("!!LOADED FILELIST!!"); } var loadedPP = Cache.LoadedFileReferences.Keys.Select(x => x.Archive).Distinct(); foreach (string pp in loadedPP) { handler.WriteString(pp + ".pp"); if (LogFiles) { Console.WriteLine(pp); } } handler.WriteString(""); } else if (request == "load") { //Transfer the file lock (Cache.LoadLock) { string[] splitNames = argument.Replace("data/", "").Split('/'); FileEntry entry = new FileEntry(splitNames[0], splitNames[1]); Logger.LogFile(argument); //Ensure we have the file if (!Cache.ReferenceMd5Sums.ContainsKey(entry)) { //We don't have the file handler.WriteString("NotAvailable"); if (LogFiles) { Console.WriteLine("!" + argument); } return; } if (LogFiles) { Console.WriteLine(argument); } //Write the data to the pipe var fileMd5 = Cache.ReferenceMd5Sums[entry]; if (!Cache.LoadedFiles.TryGetValue(fileMd5, out var cachedFile)) { //Console.WriteLine("Cache miss"); var chunk = Cache.LoadedFileReferences[entry]; chunk.Allocate(); // wait for the file to be available while (true) { if (Cache.LoadedFiles.TryGetValue(fileMd5, out cachedFile) && cachedFile.Ready) { break; } Thread.Sleep(50); } } while (!cachedFile.Ready) { Thread.Sleep(50); } using var compressedDataRef = cachedFile.GetMemory(); using var buffer = MemoryPool <byte> .Shared.Rent((int) cachedFile.UncompressedSize * 2); ZstdDecompressor.DecompressData(compressedDataRef.Memory.Span, buffer.Memory.Span, out int uncompressedSize); //Console.WriteLine($"Expected: {Utility.GetBytesReadable(cachedFile.UncompressedSize)} Actual: {Utility.GetBytesReadable(uncompressedSize)}"); if (entry.File.EndsWith("wav")) { using (var inputStream = new ReadOnlyMemoryStream(buffer.Memory.Slice(0, (int)uncompressedSize))) //using (var rentedSpan = MemoryPool<byte>.Shared.Rent(48_000_000)) using (var outputStream = new MemoryStream()) { OpusEncoder.Decode(inputStream, outputStream, false); outputStream.Position = 0; //Console.WriteLine($"Decompressed wav size: {Utility.GetBytesReadable(outputStream.Length)}"); handler.WriteString(outputStream.Length.ToString()); outputStream.CopyTo(handler.BaseStream); } } else { handler.WriteString(uncompressedSize.ToString()); handler.BaseStream.Write(buffer.Memory.Slice(0, (int)uncompressedSize).Span); } } } else { //Unknown command //Ignore instead of throwing exception Console.WriteLine("Unknown request: " + request + " [:] " + argument); } }