From 1f844b44e191247b1e37590509abd158c137e5cd Mon Sep 17 00:00:00 2001 From: chudov Date: Sat, 6 Feb 2010 23:17:07 +0000 Subject: [PATCH] reorganizing a bit --- ArCueDotNet/ArCueDotNet.csproj | 2 +- Bwg.Hardware/Bwg.Hardware.csproj | 2 +- Bwg.Logging/Bwg.Logging.csproj | 4 +- Bwg.Scsi/Bwg.Scsi.csproj | 4 +- CUEControls/CUEControls.csproj | 2 +- CUERipper/CUERipper.csproj | 2 +- CUETools.ALACEnc/CUETools.ALACEnc.csproj | 57 + CUETools.ALACEnc/Program.cs | 291 ++ CUETools.ALACEnc/Properties/AssemblyInfo.cs | 33 + CUETools.AccurateRip/AccurateRip.cs | 118 +- .../CUETools.AccurateRip.csproj | 2 +- CUETools.CDImage/CDImage.cs | 2 +- CUETools.CDImage/CUETools.CDImage.csproj | 2 +- CUETools.Codecs.ALAC/ALACDotNet.cs | 173 +- CUETools.Codecs.ALAC/ALACWriter.cs | 206 +- .../CUETools.Codecs.ALAC.csproj | 2 +- CUETools.Codecs.APE/CUETools.Codecs.APE.cpp | 135 +- .../CUETools.Codecs.APE.vcproj | 9 +- CUETools.Codecs.FLAC/CUETools.Codecs.FLAC.cpp | 151 +- .../CUETools.Codecs.FLAC.vcproj | 11 +- .../CUETools.Codecs.FLAKE.csproj | 2 +- CUETools.Codecs.FLAKE/Flake.cs | 12 +- CUETools.Codecs.FLAKE/FlakeReader.cs | 134 +- CUETools.Codecs.FLAKE/FlakeWriter.cs | 154 +- .../CUETools.Codecs.LossyWAV.csproj | 3 +- CUETools.Codecs.LossyWAV/LossyWAV.cs | 160 +- CUETools.Codecs.TTA/CUETools.Codecs.TTA.cpp | 137 +- .../CUETools.Codecs.TTA.vcproj | 21 +- .../CUETools.Codecs.WavPack.cpp | 164 +- .../CUETools.Codecs.WavPack.vcproj | 9 +- CUETools.Codecs/CRCs/CRC32.cs | 38 +- CUETools.Codecs/CUETools.Codecs.csproj | 2 +- CUETools.Codecs/Codecs.cs | 1167 ++++---- CUETools.Converter/CUETools.Converter.csproj | 2 +- CUETools.Converter/Program.cs | 18 +- .../CUETools.Codecs.FlaCuda.csproj | 4 +- CUETools.FlaCuda/FlaCudaWriter.cs | 254 +- CUETools.FlaCuda/flacuda.cu | 14 + CUETools.FlaCuda/flacuda.cubin | 2526 ++++++++--------- CUETools.FlaCudaExe/CUETools.FlaCuda.csproj | 2 +- CUETools.FlaCudaExe/Program.cs | 84 +- CUETools.Flake/CUETools.Flake.csproj | 2 +- CUETools.Flake/Program.cs | 32 +- CUETools.Processor/AudioReadWrite.cs | 135 +- CUETools.Processor/CUETools.Processor.csproj | 18 +- CUETools.Processor/Processor.cs | 289 +- .../CUETools.ConsoleRipper.csproj | 2 +- CUETools.Ripper.Console/Program.cs | 21 +- .../CUETools.Ripper.SCSI.csproj | 2 +- CUETools.Ripper.SCSI/SCSIDrive.cs | 116 +- .../CUETools.TestCodecs/ALACWriterTest.cs | 103 + .../CUETools.TestCodecs/AccurateRipTest.cs | 96 + .../CUETools.TestCodecs.csproj | 67 + CUETools/CUETools.TestCodecs/CodecsTest.cs | 345 +++ .../CUETools.TestCodecs/FlakeWriterTest.cs | 105 + .../Properties/AssemblyInfo.cs | 35 + CUETools/CUETools.TestCodecs/alac.m4a | Bin 0 -> 774 bytes CUETools/CUETools.TestCodecs/flake.flac | Bin 0 -> 125 bytes CUETools/CUETools.TestCodecs/pipe.wav | Bin 0 -> 256 bytes CUETools/CUETools.TestCodecs/test.wav | Bin 0 -> 256 bytes CUETools/CUETools.csproj | 2 +- CUETools/CUETools.sln | 549 ++-- CUETools/app.config | 5 + CUETools/cue2.ico | Bin 0 -> 23558 bytes CUETools/frmChoice.Designer.cs | 94 +- CUETools/frmChoice.cs | 298 +- CUETools/frmChoice.resx | 399 +-- CUETools/frmSettings.Designer.cs | 66 +- CUETools/frmSettings.cs | 12 +- CUETools/frmSettings.resx | 220 +- CUETools/hdcd.dll | Bin 0 -> 106496 bytes CUETools/unrar.dll | Bin 0 -> 168448 bytes CUETools/user_profiles_enabled | 0 Freedb/Freedb.csproj | 5 +- HDCDDotNet/HDCDDotNet.cs | 14 +- HDCDDotNet/HDCDDotNet.csproj | 3 +- LossyWAVSharp/LossyWAVSharp.csproj | 2 +- LossyWAVSharp/Program.cs | 29 +- MAC_SDK/Source/MACLib/Assembly/Assembly.obj | Bin 836 -> 836 bytes MAC_SDK/Source/MACLib/Assembly/Assembly64.obj | Bin 1259 -> 1259 bytes MusicBrainz/MusicBrainz.csproj | 2 +- UnRarDotNet/UnRarDotNet.csproj | 2 +- 82 files changed, 5239 insertions(+), 3946 deletions(-) create mode 100644 CUETools.ALACEnc/CUETools.ALACEnc.csproj create mode 100644 CUETools.ALACEnc/Program.cs create mode 100644 CUETools.ALACEnc/Properties/AssemblyInfo.cs create mode 100644 CUETools/CUETools.TestCodecs/ALACWriterTest.cs create mode 100644 CUETools/CUETools.TestCodecs/AccurateRipTest.cs create mode 100644 CUETools/CUETools.TestCodecs/CUETools.TestCodecs.csproj create mode 100644 CUETools/CUETools.TestCodecs/CodecsTest.cs create mode 100644 CUETools/CUETools.TestCodecs/FlakeWriterTest.cs create mode 100644 CUETools/CUETools.TestCodecs/Properties/AssemblyInfo.cs create mode 100644 CUETools/CUETools.TestCodecs/alac.m4a create mode 100644 CUETools/CUETools.TestCodecs/flake.flac create mode 100644 CUETools/CUETools.TestCodecs/pipe.wav create mode 100644 CUETools/CUETools.TestCodecs/test.wav create mode 100644 CUETools/cue2.ico create mode 100644 CUETools/hdcd.dll create mode 100644 CUETools/unrar.dll create mode 100644 CUETools/user_profiles_enabled diff --git a/ArCueDotNet/ArCueDotNet.csproj b/ArCueDotNet/ArCueDotNet.csproj index cc009e0..4c2df87 100644 --- a/ArCueDotNet/ArCueDotNet.csproj +++ b/ArCueDotNet/ArCueDotNet.csproj @@ -22,7 +22,7 @@ pdbonly true - bin\Release\ + ..\bin\any\Release\ TRACE prompt 4 diff --git a/Bwg.Hardware/Bwg.Hardware.csproj b/Bwg.Hardware/Bwg.Hardware.csproj index fe3a896..281a43f 100644 --- a/Bwg.Hardware/Bwg.Hardware.csproj +++ b/Bwg.Hardware/Bwg.Hardware.csproj @@ -38,7 +38,7 @@ pdbonly true - bin\Release\ + ..\bin\any\Release\ TRACE prompt 4 diff --git a/Bwg.Logging/Bwg.Logging.csproj b/Bwg.Logging/Bwg.Logging.csproj index 13882ad..db344b4 100644 --- a/Bwg.Logging/Bwg.Logging.csproj +++ b/Bwg.Logging/Bwg.Logging.csproj @@ -38,11 +38,11 @@ pdbonly true - bin\Release\ + ..\bin\any\Release\ TRACE prompt 4 - bin\Release\Bwg.Logging.XML + ..\bin\any\Release\\Bwg.Logging.XML true diff --git a/Bwg.Scsi/Bwg.Scsi.csproj b/Bwg.Scsi/Bwg.Scsi.csproj index 789a3d1..19f690e 100644 --- a/Bwg.Scsi/Bwg.Scsi.csproj +++ b/Bwg.Scsi/Bwg.Scsi.csproj @@ -39,12 +39,12 @@ pdbonly true - bin\Release\ + ..\bin\any\Release\ TRACE prompt 4 true - bin\Release\Bwg.Scsi.XML + ..\bin\any\Release\Bwg.Scsi.XML true diff --git a/CUEControls/CUEControls.csproj b/CUEControls/CUEControls.csproj index 36919b6..f7c4f18 100644 --- a/CUEControls/CUEControls.csproj +++ b/CUEControls/CUEControls.csproj @@ -23,7 +23,7 @@ pdbonly true - bin\Release\ + ..\bin\any\Release\ TRACE prompt 4 diff --git a/CUERipper/CUERipper.csproj b/CUERipper/CUERipper.csproj index 48edf8c..d6988f0 100644 --- a/CUERipper/CUERipper.csproj +++ b/CUERipper/CUERipper.csproj @@ -22,7 +22,7 @@ pdbonly true - bin\Release\ + ..\bin\any\Release\ TRACE prompt 4 diff --git a/CUETools.ALACEnc/CUETools.ALACEnc.csproj b/CUETools.ALACEnc/CUETools.ALACEnc.csproj new file mode 100644 index 0000000..860ea83 --- /dev/null +++ b/CUETools.ALACEnc/CUETools.ALACEnc.csproj @@ -0,0 +1,57 @@ + + + Debug + AnyCPU + 8.0.50727 + 2.0 + {8E6E1763-39AE-491D-A10F-44C8844ABA5B} + Exe + Properties + CUETools.ALACEnc + CUETools.ALACEnc + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + ..\bin\any\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + {F2EC7193-D5E5-4252-9803-5CEB407E910F} + CUETools.Codecs.ALAC + + + {6458A13A-30EF-45A9-9D58-E5031B17BEE2} + CUETools.Codecs + + + + + \ No newline at end of file diff --git a/CUETools.ALACEnc/Program.cs b/CUETools.ALACEnc/Program.cs new file mode 100644 index 0000000..d30913d --- /dev/null +++ b/CUETools.ALACEnc/Program.cs @@ -0,0 +1,291 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.IO; +using CUETools.Codecs; +using CUETools.Codecs.ALAC; + +namespace CUETools.ALACEnc +{ + class Program + { + static void Usage() + { + Console.WriteLine("Usage : CUETools.ALACEnc.exe [options] "); + Console.WriteLine(); + Console.WriteLine("Options:"); + Console.WriteLine(); + Console.WriteLine(" -0 .. -10 Compression level, default 5."); + Console.WriteLine(" -o Output filename, or \"-\" for stdout, or nul."); + //Console.WriteLine(" -p # Padding bytes."); + Console.WriteLine(" -q --quiet Quiet mode."); + Console.WriteLine(" --verify Verify during encoding."); + //Console.WriteLine(" --no-seektable Don't generate a seektable."); + Console.WriteLine(); + Console.WriteLine("Advanced Options:"); + Console.WriteLine(); + Console.WriteLine(" -b # Block size."); + Console.WriteLine(" -s Stereo decorrelation (independent,estimate,evaluate,search)."); + Console.WriteLine(" --history-modifier # Rice history modifier {max} or {min},{max}, default 4,4."); + Console.WriteLine(); + Console.WriteLine("LPC options:"); + Console.WriteLine(); + Console.WriteLine(" -m Prediction order search (estimate,estsearch,logfast,search)."); + Console.WriteLine(" -e # Estimation depth (1..30)."); + Console.WriteLine(" -w [,] One or more window functions (welch,hann,flattop,tukey)."); + Console.WriteLine(" --window-method Window selection method (estimate,evaluate,search)."); + Console.WriteLine(" -l #[,#] Prediction order {max} or {min},{max} (1..30)."); + Console.WriteLine(); + } + + static int Main(string[] args) + { + TextWriter stdout = Console.Out; + Console.SetOut(Console.Error); + + DateTime start = DateTime.Now; + TimeSpan lastPrint = TimeSpan.FromMilliseconds(0); + bool debug = false, quiet = false; + string stereo_method = null; + string window_method = null; + string order_method = null; + string window_function = null; + string input_file = null; + string output_file = null; + int min_lpc_order = -1, max_lpc_order = -1, + blocksize = -1, estimation_depth = -1, + min_modifier = -1, max_modifier = -1; + int level = -1, padding = -1; + int initial_history = -1, history_mult = -1; + int adaptive_passes = -1; + bool do_seektable = true, do_verify = false; + bool buffered = false; + + for (int arg = 0; arg < args.Length; arg++) + { + bool ok = true; + if (args[arg].Length == 0) + ok = false; + else if (args[arg] == "--debug") + debug = true; + else if ((args[arg] == "-q" || args[arg] == "--quiet")) + quiet = true; + else if (args[arg] == "--verify") + do_verify = true; + else if (args[arg] == "--no-seektable") + do_seektable = false; + else if (args[arg] == "--buffered") + buffered = true; + else if ((args[arg] == "-o" || args[arg] == "--output") && ++arg < args.Length) + output_file = args[arg]; + else if ((args[arg] == "-s" || args[arg] == "--stereo") && ++arg < args.Length) + stereo_method = args[arg]; + else if ((args[arg] == "-m" || args[arg] == "--order-method") && ++arg < args.Length) + order_method = args[arg]; + else if ((args[arg] == "-w" || args[arg] == "--window") && ++arg < args.Length) + window_function = args[arg]; + else if (args[arg] == "--window-method" && ++arg < args.Length) + window_method = args[arg]; + else if ((args[arg] == "-l" || args[arg] == "--lpc-order") && ++arg < args.Length) + { + ok = (args[arg].Split(',').Length == 2 && + int.TryParse(args[arg].Split(',')[0], out min_lpc_order) && + int.TryParse(args[arg].Split(',')[1], out max_lpc_order)) || + int.TryParse(args[arg], out max_lpc_order); + } + else if ((args[arg] == "--history-modifier") && ++arg < args.Length) + { + ok = (args[arg].Split(',').Length == 2 && + int.TryParse(args[arg].Split(',')[0], out min_modifier) && + int.TryParse(args[arg].Split(',')[1], out max_modifier)) || + int.TryParse(args[arg], out max_modifier); + } + else if ((args[arg] == "--initial-history") && ++arg < args.Length) + ok = int.TryParse(args[arg], out initial_history); + else if ((args[arg] == "--adaptive-passes") && ++arg < args.Length) + ok = int.TryParse(args[arg], out adaptive_passes); + else if ((args[arg] == "--history-mult") && ++arg < args.Length) + ok = int.TryParse(args[arg], out history_mult); + else if ((args[arg] == "-e" || args[arg] == "--estimation-depth") && ++arg < args.Length) + ok = int.TryParse(args[arg], out estimation_depth); + else if ((args[arg] == "-b" || args[arg] == "--blocksize") && ++arg < args.Length) + ok = int.TryParse(args[arg], out blocksize); + else if ((args[arg] == "-p" || args[arg] == "--padding") && ++arg < args.Length) + ok = int.TryParse(args[arg], out padding); + else if (args[arg] != "-" && args[arg][0] == '-' && int.TryParse(args[arg].Substring(1), out level)) + ok = level >= 0 && level <= 11; + else if ((args[arg][0] != '-' || args[arg] == "-") && input_file == null) + input_file = args[arg]; + else + ok = false; + if (!ok) + { + Usage(); + return 1; + } + } + if (input_file == null || ((input_file == "-" || Path.GetExtension(input_file) == ".m4a") && output_file == null)) + { + Usage(); + return 2; + } + + if (!quiet) + { + Console.WriteLine("CUETools.ALACEnc, Copyright (C) 2009 Gregory S. Chudov."); + Console.WriteLine("Based on ffdshow ALAC audio encoder"); + Console.WriteLine("Copyright (c) 2008 Jaikrishnan Menon, "); + Console.WriteLine("This is free software under the GNU GPLv3+ license; There is NO WARRANTY, to"); + Console.WriteLine("the extent permitted by law. for details."); + } + + //byte [] b = new byte[0x10000]; + //int len = 0; + //Stream si = Console.OpenStandardInput(); + //Stream so = new FileStream(output_file, FileMode.Create); + //do + //{ + // len = si.Read(b, 0, 0x10000); + // so.Write(b, 0, len); + //} while (len > 0); + //return 0; + IAudioSource audioSource; + if (input_file == "-") + audioSource = new WAVReader("", Console.OpenStandardInput()); + else if (File.Exists(input_file) && Path.GetExtension(input_file) == ".wav") + audioSource = new WAVReader(input_file, null); + else if (File.Exists(input_file) && Path.GetExtension(input_file) == ".m4a") + audioSource = new ALACReader(input_file, null); + else + { + Usage(); + return 2; + } + if (buffered) + audioSource = new AudioPipe(audioSource, 0x10000); + if (output_file == null) + output_file = Path.ChangeExtension(input_file, "m4a"); + ALACWriter alac = new ALACWriter((output_file == "-" || output_file == "nul") ? "" : output_file, + output_file == "-" ? Console.OpenStandardOutput() : + output_file == "nul" ? new NullStream() : null, + audioSource.PCM); + alac.FinalSampleCount = (long)audioSource.Length; + IAudioDest audioDest = alac; + AudioBuffer buff = new AudioBuffer(audioSource, 0x10000); + + try + { + if (level >= 0) + alac.CompressionLevel = level; + if (stereo_method != null) + alac.StereoMethod = Alac.LookupStereoMethod(stereo_method); + if (order_method != null) + alac.OrderMethod = Alac.LookupOrderMethod(order_method); + if (window_function != null) + alac.WindowFunction = Alac.LookupWindowFunction(window_function); + if (window_method != null) + alac.WindowMethod = Alac.LookupWindowMethod(window_method); + if (max_lpc_order >= 0) + alac.MaxLPCOrder = max_lpc_order; + if (min_lpc_order >= 0) + alac.MinLPCOrder = min_lpc_order; + if (max_modifier >= 0) + alac.MaxHistoryModifier = max_modifier; + if (min_modifier >= 0) + alac.MinHistoryModifier = min_modifier; + if (history_mult >= 0) + alac.HistoryMult = history_mult; + if (initial_history >= 0) + alac.InitialHistory = initial_history; + if (blocksize >= 0) + alac.BlockSize = blocksize; + if (estimation_depth >= 0) + alac.EstimationDepth = estimation_depth; + if (padding >= 0) + alac.PaddingLength = padding; + if (adaptive_passes >= 0) + alac.AdaptivePasses = adaptive_passes; + alac.DoSeekTable = do_seektable; + alac.DoVerify = do_verify; + } + catch (Exception ex) + { + Usage(); + Console.WriteLine(""); + Console.WriteLine("Error: {0}.", ex.Message); + return 3; + } + + if (!quiet) + { + Console.WriteLine("Filename : {0}", input_file); + Console.WriteLine("File Info : {0}kHz; {1} channel; {2} bit; {3}", audioSource.PCM.SampleRate, audioSource.PCM.ChannelCount, audioSource.PCM.BitsPerSample, TimeSpan.FromSeconds(audioSource.Length * 1.0 / audioSource.PCM.SampleRate)); + } + +#if !DEBUG + try +#endif + { + while (audioSource.Read(buff, -1) != 0) + { + audioDest.Write(buff); + TimeSpan elapsed = DateTime.Now - start; + if (!quiet) + { + if ((elapsed - lastPrint).TotalMilliseconds > 60) + { + Console.Error.Write("\rProgress : {0:00}%; {1:0.00}x; {2}/{3}", + 100.0 * audioSource.Position / audioSource.Length, + audioSource.Position / elapsed.TotalSeconds / audioSource.PCM.SampleRate, + elapsed, + TimeSpan.FromMilliseconds(elapsed.TotalMilliseconds / audioSource.Position * audioSource.Length) + ); + lastPrint = elapsed; + } + } + } + audioDest.Close(); + } +#if !DEBUG + catch (Exception ex) + { + Console.Error.Write("\r \r"); + Console.WriteLine("Error : {0}", ex.Message); + audioDest.Delete(); + audioSource.Close(); + return 4; + } +#endif + + if (!quiet) + { + TimeSpan totalElapsed = DateTime.Now - start; + Console.Error.Write("\r \r"); + Console.WriteLine("Results : {0:0.00}x; {1}", + audioSource.Position / totalElapsed.TotalSeconds / audioSource.PCM.SampleRate, + totalElapsed + ); + } + audioSource.Close(); + + if (debug) + { + Console.SetOut(stdout); + Console.Out.WriteLine("{0}\t{1}\t{2}\t{3}\t{4}\t{5}..{6}\t{7}..{8}\t{9}", + alac.TotalSize, + alac.UserProcessorTime.TotalSeconds, + alac.StereoMethod.ToString().PadRight(15), + (alac.OrderMethod.ToString() + (alac.OrderMethod == OrderMethod.Estimate ? "(" + alac.EstimationDepth.ToString() + ")" : "")).PadRight(15), + alac.WindowFunction.ToString() + "(" + alac.AdaptivePasses.ToString() + ")", + alac.MinLPCOrder, + alac.MaxLPCOrder, + alac.MinHistoryModifier, + alac.MaxHistoryModifier, + alac.BlockSize + ); + } + //File.SetAttributes(output_file, FileAttributes.ReadOnly); + return 0; + } + } +} diff --git a/CUETools.ALACEnc/Properties/AssemblyInfo.cs b/CUETools.ALACEnc/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..5b7c58a --- /dev/null +++ b/CUETools.ALACEnc/Properties/AssemblyInfo.cs @@ -0,0 +1,33 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("CUETools.ALACEnc")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Microsoft")] +[assembly: AssemblyProduct("CUETools.ALACEnc")] +[assembly: AssemblyCopyright("Copyright © Microsoft 2009")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("24fa1fb9-e01a-48cf-b478-f560496d1ed3")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/CUETools.AccurateRip/AccurateRip.cs b/CUETools.AccurateRip/AccurateRip.cs index 4d687e7..07b9e17 100644 --- a/CUETools.AccurateRip/AccurateRip.cs +++ b/CUETools.AccurateRip/AccurateRip.cs @@ -41,7 +41,7 @@ For each range i calculate baseSum, which is an AR CRC of the current sample, us All the other CRC's in this offset range are calculated by consequently adding sampleValue to the previous sum. */ - unsafe private void CalculateAccurateRipCRCsSemifast(int* samples, uint count, int iTrack, uint currentOffset, uint previousOffset, uint trackLength) + unsafe private void CalculateAccurateRipCRCsSemifast(int* samples, int count, int iTrack, int currentOffset, int previousOffset, int trackLength) { fixed (uint* CRCsA = &_offsetedCRC[Math.Max(0, iTrack - 1), 0], CRCsB = &_offsetedCRC[iTrack, 0], @@ -51,7 +51,7 @@ All the other CRC's in this offset range are calculated by consequently adding s //CRC32C = &_offsetedCRC32[Math.Min(_toc.AudioTracks - 1, iTrack + 1), 0] ) { - for (uint si = 0; si < count; si++) + for (int si = 0; si < count; si++) { uint sampleValue = (uint)((samples[2 * si] & 0xffff) + (samples[2 * si + 1] << 16)); int i; @@ -84,7 +84,7 @@ All the other CRC's in this offset range are calculated by consequently adding s } } - unsafe private void CalculateAccurateRipCRCs(int* samples, uint count, int iTrack, uint currentOffset, uint previousOffset, uint trackLength) + unsafe private void CalculateAccurateRipCRCs(int* samples, int count, int iTrack, int currentOffset, int previousOffset, int trackLength) { for (int si = 0; si < count; si++) { @@ -123,10 +123,10 @@ All the other CRC's in this offset range are calculated by consequently adding s } } - unsafe private void CalculateAccurateRipCRCsFast(int* samples, uint count, int iTrack, uint currentOffset) + unsafe private void CalculateAccurateRipCRCsFast(int* samples, int count, int iTrack, int currentOffset) { - int s1 = (int)Math.Min(count, Math.Max(0, 450 * 588 - _arOffsetRange - (int)currentOffset)); - int s2 = (int)Math.Min(count, Math.Max(0, 451 * 588 + _arOffsetRange - (int)currentOffset)); + int s1 = Math.Min(count, Math.Max(0, 450 * 588 - _arOffsetRange - currentOffset)); + int s2 = Math.Min(count, Math.Max(0, 451 * 588 + _arOffsetRange - currentOffset)); if (s1 < s2) fixed (uint* FrameCRCs = &_offsetedFrame450CRC[iTrack, 0]) for (int sj = s1; sj < s2; sj++) @@ -141,15 +141,14 @@ All the other CRC's in this offset range are calculated by consequently adding s fixed (uint* CRCs = &_offsetedCRC[iTrack, 0]) { uint baseSum = 0, stepSum = 0; - int* s = samples, fin = samples + 2 * count; - uint mult = 0; - while (s < fin) + int* s = samples; + for (uint mult = 0; mult < count; mult++) { uint sampleValue = (uint)((*(s++) & 0xffff) + (*(s++) << 16)); stepSum += sampleValue; - baseSum += sampleValue * (mult++); + baseSum += sampleValue * mult; } - currentOffset += (uint)_arOffsetRange + 1; + currentOffset += _arOffsetRange + 1; baseSum += stepSum * (uint)currentOffset; for (int i = 2 * _arOffsetRange; i >= 0; i--) { @@ -274,39 +273,78 @@ All the other CRC's in this offset range are calculated by consequently adding s return _offsetedFrame450CRC[iTrack, _arOffsetRange - oi]; } - public void Write(int[,] sampleBuffer, int offset, int count) + public unsafe void CalculateCRCs(AudioBuffer buff, int pos, int count) { - uint sampleCount = (uint)count; - for (uint pos = (uint)offset; pos < sampleCount; ) + uint crc0 = _CRC32[0]; + uint crc1 = _CRC32[_currentTrack]; + uint crc2 = _CRCWONULL[0]; + uint crc3 = _CRCWONULL[_currentTrack]; + + fixed (int* pSampleBuff = &buff.Samples[pos, 0]) + fixed (uint* t = _crc32.table) { - uint copyCount = Math.Min(sampleCount - pos, (uint)_samplesRemTrack); + for (int i = 0; i < 2 * count; i++) + { + int s = pSampleBuff[i]; + byte s0 = (byte)s; + byte s1 = (byte)(s >> 8); + if (s != 0) + { + crc2 = (crc2 >> 8) ^ t[((byte)crc2) ^ s0]; + crc2 = (crc2 >> 8) ^ t[((byte)crc2) ^ s1]; + crc3 = (crc3 >> 8) ^ t[((byte)crc3) ^ s0]; + crc3 = (crc3 >> 8) ^ t[((byte)crc3) ^ s1]; + } + crc0 = (crc0 >> 8) ^ t[((byte)crc0) ^ s0]; + crc0 = (crc0 >> 8) ^ t[((byte)crc0) ^ s1]; + crc1 = (crc1 >> 8) ^ t[((byte)crc1) ^ s0]; + crc1 = (crc1 >> 8) ^ t[((byte)crc1) ^ s1]; + } + } + + _CRC32[0] = crc0; + _CRCWONULL[0] = crc2; + if (_currentTrack > 0) + { + _CRC32[_currentTrack] = crc1; + _CRCWONULL[_currentTrack] = crc3; + } + } + + public void Write(AudioBuffer sampleBuffer) + { + sampleBuffer.Prepare(this); + + int pos = 0; + while (pos < sampleBuffer.Length) + { + int copyCount = (int)Math.Min((long)sampleBuffer.Length - pos, _samplesRemTrack); + + CalculateCRCs(sampleBuffer, pos, copyCount); + unsafe { - fixed (int* pSampleBuff = &sampleBuffer[pos, 0]) + fixed (int* pSampleBuff = &sampleBuffer.Samples[pos, 0]) + //fixed (byte* pByteBuff = &sampleBuffer.Bytes[pos * sampleBuffer.BlockAlign]) { if (_currentTrack > 0) { - uint trackLength = _toc[_currentTrack + _toc.FirstAudio - 1].Length * 588; - uint currentOffset = (uint)_sampleCount - _toc[_currentTrack + _toc.FirstAudio - 1].Start * 588; - uint previousOffset = _currentTrack > 1 ? _toc[_currentTrack + _toc.FirstAudio - 2].Length * 588 : _toc[_toc.FirstAudio].Pregap * 588; - uint si1 = (uint)Math.Min(copyCount, Math.Max(0, 588 * (_currentTrack == 1 ? 10 : 5) - (int)currentOffset)); - uint si2 = (uint)Math.Min(copyCount, Math.Max(si1, trackLength - (int)currentOffset - 588 * (_currentTrack == _toc.AudioTracks ? 10 : 5))); + int trackLength = (int)_toc[_currentTrack + _toc.FirstAudio - 1].Length * 588; + int currentOffset = (int)_sampleCount - (int)_toc[_currentTrack + _toc.FirstAudio - 1].Start * 588; + int previousOffset = _currentTrack > 1 ? (int)_toc[_currentTrack + _toc.FirstAudio - 2].Length * 588 : (int)_toc[_toc.FirstAudio].Pregap * 588; + int si1 = Math.Min(copyCount, Math.Max(0, 588 * (_currentTrack == 1 ? 10 : 5) - currentOffset)); + int si2 = Math.Min(copyCount, Math.Max(si1, trackLength - currentOffset - 588 * (_currentTrack == _toc.AudioTracks ? 10 : 5))); if (_currentTrack == 1) CalculateAccurateRipCRCs(pSampleBuff, si1, _currentTrack - 1, currentOffset, previousOffset, trackLength); else CalculateAccurateRipCRCsSemifast(pSampleBuff, si1, _currentTrack - 1, currentOffset, previousOffset, trackLength); if (si2 > si1) - CalculateAccurateRipCRCsFast(pSampleBuff + si1 * 2, (uint)(si2 - si1), _currentTrack - 1, currentOffset + si1); + CalculateAccurateRipCRCsFast(pSampleBuff + si1 * 2, si2 - si1, _currentTrack - 1, currentOffset + si1); if (_currentTrack == _toc.AudioTracks) CalculateAccurateRipCRCs(pSampleBuff + si2 * 2, copyCount - si2, _currentTrack - 1, currentOffset + si2, previousOffset, trackLength); else CalculateAccurateRipCRCsSemifast(pSampleBuff + si2 * 2, copyCount - si2, _currentTrack - 1, currentOffset + si2, previousOffset, trackLength); - - _CRC32[_currentTrack] = _crc32.ComputeChecksum(_CRC32[_currentTrack], pSampleBuff, copyCount); - _CRCWONULL[_currentTrack] = _crc32.ComputeChecksumWONULL(_CRCWONULL[_currentTrack], pSampleBuff, copyCount); } - _CRC32[0] = _crc32.ComputeChecksum(_CRC32[0], pSampleBuff, copyCount); - _CRCWONULL[0] = _crc32.ComputeChecksumWONULL(_CRCWONULL[0], pSampleBuff, copyCount); } } pos += copyCount; @@ -455,14 +493,34 @@ All the other CRC's in this offset range are calculated by consequently adding s throw new Exception("unsupported"); } - public int BitsPerSample + public int CompressionLevel { - get { return 16; } + get { return 0; } + set { } + } + + public string Options + { + set + { + if (value == null || value == "") return; + throw new Exception("Unsupported options " + value); + } + } + + public AudioPCMConfig PCM + { + get { return AudioPCMConfig.RedBook; } } public long FinalSampleCount { - set { _finalSampleCount = value; } + set + { + if (value < 0) // != _toc.Length? + throw new Exception("invalid FinalSampleCount"); + _finalSampleCount = value; + } } public long BlockSize diff --git a/CUETools.AccurateRip/CUETools.AccurateRip.csproj b/CUETools.AccurateRip/CUETools.AccurateRip.csproj index 3299464..7deb6ce 100644 --- a/CUETools.AccurateRip/CUETools.AccurateRip.csproj +++ b/CUETools.AccurateRip/CUETools.AccurateRip.csproj @@ -23,7 +23,7 @@ pdbonly true - bin\Release\ + ..\bin\any\Release\ TRACE prompt 4 diff --git a/CUETools.CDImage/CDImage.cs b/CUETools.CDImage/CDImage.cs index 83c0e16..141e31d 100644 --- a/CUETools.CDImage/CDImage.cs +++ b/CUETools.CDImage/CDImage.cs @@ -355,7 +355,7 @@ namespace CUETools.CDImage { if (iIndex < _tracks[iTrack - 1].LastIndex) return _tracks[iTrack - 1][iIndex + 1].Start - _tracks[iTrack - 1][iIndex].Start; - if (iTrack < AudioTracks) + if (iTrack < TrackCount && _tracks[iTrack].IsAudio) return _tracks[iTrack][0].Start - _tracks[iTrack - 1][iIndex].Start; return _tracks[iTrack - 1].End + 1 - _tracks[iTrack - 1][iIndex].Start; } diff --git a/CUETools.CDImage/CUETools.CDImage.csproj b/CUETools.CDImage/CUETools.CDImage.csproj index dbdad51..422eb03 100644 --- a/CUETools.CDImage/CUETools.CDImage.csproj +++ b/CUETools.CDImage/CUETools.CDImage.csproj @@ -22,7 +22,7 @@ pdbonly true - bin\Release\ + ..\bin\any\Release\ TRACE prompt 4 diff --git a/CUETools.Codecs.ALAC/ALACDotNet.cs b/CUETools.Codecs.ALAC/ALACDotNet.cs index 8e84a3c..a17190d 100644 --- a/CUETools.Codecs.ALAC/ALACDotNet.cs +++ b/CUETools.Codecs.ALAC/ALACDotNet.cs @@ -27,6 +27,7 @@ using CUETools.Codecs; namespace CUETools.Codecs.ALAC { + [AudioDecoderClass("builtin alac", "m4a")] public class ALACReader : IAudioSource { public ALACReader(string path, Stream IO) @@ -36,19 +37,17 @@ namespace CUETools.Codecs.ALAC _buff = new byte[512]; _tags = new NameValueCollection(); qtmovie_read(); - if (!_formatRead || _bitsPerSample != 16 || _channelCount != 2 || _sampleRate != 44100) + if (!_formatRead || pcm.BitsPerSample != 16 || pcm.ChannelCount != 2 || pcm.SampleRate != 44100) throw new Exception("Invalid ALAC file."); _saved_mdat_pos = _IO.Position; calculate_length(); } - public ALACReader(int channels, int bps, int rice_historymult, int rice_initialhistory, int rice_kmodifier, int blocksize) + public ALACReader(AudioPCMConfig _pcm, int rice_historymult, int rice_initialhistory, int rice_kmodifier, int blocksize) { - _channelCount = channels; - _bitsPerSample = bps; - _sampleRate = 44100; + pcm = _pcm; - setinfo_max_samples_per_frame = (uint)blocksize; + setinfo_max_samples_per_frame = blocksize; setinfo_rice_historymult = (byte)rice_historymult; setinfo_rice_initialhistory = (byte)rice_initialhistory; setinfo_rice_kmodifier = (byte)rice_kmodifier; @@ -60,17 +59,12 @@ namespace CUETools.Codecs.ALAC _framesBuffer = new byte[65536]; } - public int[,] Read(int[,] buff) - { - return AudioSamples.Read(this, buff); - } - private void InitTables() { if (_predicterror_buffer_a != null) return; - setinfo_max_samples_per_frame = read_uint32(_codecData, 24); + setinfo_max_samples_per_frame = (int)read_uint32(_codecData, 24); byte setinfo_7a = read_uint8(_codecData, 28); byte setinfo_sample_size = read_uint8(_codecData, 29); setinfo_rice_historymult = read_uint8(_codecData, 30); @@ -91,29 +85,32 @@ namespace CUETools.Codecs.ALAC _framesBuffer = new byte[65536]; } - public uint Read(int[,] buff, uint sampleCount) + public int Read(AudioBuffer buff, int maxLength) { InitTables(); - uint offset = 0; + buff.Prepare(this, maxLength); + + int offset = 0; + int sampleCount = buff.Length; while (_samplesInBuffer < sampleCount) { if (_samplesInBuffer > 0) { - deinterlace(buff, offset, _samplesInBuffer); - sampleCount -= (uint) _samplesInBuffer; + deinterlace(buff.Samples, offset, _samplesInBuffer); + sampleCount -= _samplesInBuffer; offset += _samplesInBuffer; _samplesInBuffer = 0; _samplesBufferOffset = 0; } - uint sampleDuration; - uint sampleSize; - if ((int) _iSample >= _sample_byte_size.Length) - return (uint)offset; + int sampleDuration; + int sampleSize; + if (_iSample >= _sample_byte_size.Length) + return offset; get_sample_info(_iSample, out sampleDuration, out sampleSize); - _IO.Read(_framesBuffer, 0, (int) sampleSize); + _IO.Read(_framesBuffer, 0, sampleSize); decodeFrame(sampleSize); if (sampleDuration != _samplesInBuffer) throw new Exception("sample count mismatch"); @@ -122,12 +119,12 @@ namespace CUETools.Codecs.ALAC _iSample++; } - deinterlace(buff, offset, sampleCount); + deinterlace(buff.Samples, offset, sampleCount); _samplesInBuffer -= sampleCount; _samplesBufferOffset += sampleCount; if (_samplesInBuffer == 0) _samplesBufferOffset = 0; - return (uint) offset + sampleCount; + return offset + sampleCount; } public void Close() @@ -135,7 +132,7 @@ namespace CUETools.Codecs.ALAC _IO.Close(); } - public ulong Length + public long Length { get { @@ -143,7 +140,7 @@ namespace CUETools.Codecs.ALAC } } - public ulong Remaining + public long Remaining { get { @@ -151,7 +148,7 @@ namespace CUETools.Codecs.ALAC } } - public ulong Position + public long Position { get { @@ -164,10 +161,10 @@ namespace CUETools.Codecs.ALAC _samplesBufferOffset = 0; _iSample = 0; - ulong durOffs = 0; - uint sampleDuration; + long durOffs = 0; + int sampleDuration; long fileOffs = 0; - uint sampleSize; + int sampleSize; do { if (durOffs == value) @@ -183,51 +180,12 @@ namespace CUETools.Codecs.ALAC _iSample++; } while (durOffs <= value); _IO.Position = _saved_mdat_pos + fileOffs - sampleSize; - _samplesBufferOffset = (uint) (value + sampleDuration - durOffs); + _samplesBufferOffset = (int) (value + sampleDuration - durOffs); _iSample--; } } - public int BitsPerSample - { - get - { - return _bitsPerSample; - } - } - - public int ChannelCount - { - get - { - return _channelCount; - } - } - - public int SampleRate - { - get - { - return _sampleRate; - } - } - - public NameValueCollection Tags - { - get - { - return _tags; - } - set - { - _tags = value; - } - } - - public bool UpdateTags(bool preserveTime) - { - return false; - } + public AudioPCMConfig PCM { get { return pcm; } } public string Path { @@ -237,11 +195,11 @@ namespace CUETools.Codecs.ALAC } } - private void get_sample_info(ulong iSample, out uint sampleDuration, out uint sampleSize) + private void get_sample_info(long iSample, out int sampleDuration, out int sampleSize) { // if (iSample >= _sample_byte_size.Length) - uint duration_index_accum = 0; - uint duration_cur_index = 0; + int duration_index_accum = 0; + int duration_cur_index = 0; while (_time_to_sample_count[duration_cur_index] + duration_index_accum <= iSample) { duration_index_accum += _time_to_sample_count[duration_cur_index]; @@ -262,11 +220,11 @@ namespace CUETools.Codecs.ALAC // try a work around for ffdshow-generated buggy files if (_time_to_sample_count.Length == 1 && _IO.CanSeek) { - uint sample_count_0 = _time_to_sample_count[0] - 1; - uint sample_duration_0 = _time_to_sample_duration[0]; + int sample_count_0 = _time_to_sample_count[0] - 1; + int sample_duration_0 = _time_to_sample_duration[0]; Position = sample_count_0 * sample_duration_0; - uint sampleDuration; - uint sampleSize; + int sampleDuration; + int sampleSize; if ((int)_iSample < _sample_byte_size.Length) { get_sample_info(_iSample, out sampleDuration, out sampleSize); @@ -275,8 +233,8 @@ namespace CUETools.Codecs.ALAC decodeFrame(sampleSize); if (_samplesInBuffer < sampleDuration) { - _time_to_sample_duration = new uint[2] { sample_duration_0, _samplesInBuffer }; - _time_to_sample_count = new uint[2] { sample_count_0, 1 }; + _time_to_sample_duration = new int[2] { sample_duration_0, _samplesInBuffer }; + _time_to_sample_count = new int[2] { sample_count_0, 1 }; _sampleCount -= sampleDuration - _samplesInBuffer; } } @@ -485,7 +443,7 @@ namespace CUETools.Codecs.ALAC return x; } - private unsafe void basterdised_rice_decompress(uint output_size, ref int pos, ref predictor_t predictor_info, ref int[] predicterror_buffer, int readsamplesize) + private unsafe void basterdised_rice_decompress(int output_size, ref int pos, ref predictor_t predictor_info, ref int[] predicterror_buffer, int readsamplesize) { fixed (predictor_t* pr = &predictor_info) fixed (int* output_buffer = &predicterror_buffer[0]) @@ -540,7 +498,7 @@ namespace CUETools.Codecs.ALAC return (short)(1 - ((v >> 30) & 2)); } - private unsafe void predictor_decompress_fir_adapt(uint output_size, ref predictor_t predictor_info, ref int[] error_buffer, ref int[] buffer_out, int readsamplesize) + private unsafe void predictor_decompress_fir_adapt(int output_size, ref predictor_t predictor_info, ref int[] error_buffer, ref int[] buffer_out, int readsamplesize) { int i; @@ -623,7 +581,7 @@ namespace CUETools.Codecs.ALAC } } - internal unsafe void deinterlace(int[,] samplesBuffer, uint offset, uint sampleCount) + internal unsafe void deinterlace(int[,] samplesBuffer, int offset, int sampleCount) { if (sampleCount <= 0 || sampleCount > _samplesInBuffer) return; @@ -656,18 +614,18 @@ namespace CUETools.Codecs.ALAC } /* otherwise basic interlacing took place */ - AudioSamples.Interlace(buf_s, buf_a, buf_b, (int)sampleCount); + AudioSamples.Interlace(buf_s, buf_a, buf_b, sampleCount); } } internal int DecodeFrame(byte[] buffer, int pos, int len) { Array.Copy(buffer, pos, _framesBuffer, 0, len); - decodeFrame((uint)len); + decodeFrame(len); return len; // pos } - private void decodeFrame(uint sampleSize) + private void decodeFrame(int sampleSize) { _bitaccumulator = 0; int pos = 0; @@ -681,9 +639,9 @@ namespace CUETools.Codecs.ALAC bool hassize = 0 != readbits(_framesBuffer, ref pos, 1); /* the output sample size is stored soon */ int wasted_bytes = (int) readbits(_framesBuffer, ref pos, 2); /* unknown ? */ bool isnotcompressed = 0 != readbits(_framesBuffer, ref pos, 1); /* whether the frame is compressed */ - uint outputSamples = hassize ? readbits(_framesBuffer, ref pos, 32) : setinfo_max_samples_per_frame; + int outputSamples = hassize ? (int)readbits(_framesBuffer, ref pos, 32) : setinfo_max_samples_per_frame; - int readsamplesize = _bitsPerSample - (wasted_bytes * 8) + channels; + int readsamplesize = pcm.BitsPerSample - (wasted_bytes * 8) + pcm.ChannelCount; if (!isnotcompressed) { /* compressed */ @@ -710,10 +668,11 @@ namespace CUETools.Codecs.ALAC else { /* not compressed, easy case */ + int bps = pcm.BitsPerSample; for (int i = 0; i < outputSamples; i++) { - _outputsamples_buffer_a[i] = extend_sign32((int)readbits(_framesBuffer, ref pos, _bitsPerSample), _bitsPerSample); - _outputsamples_buffer_b[i] = extend_sign32((int)readbits(_framesBuffer, ref pos, _bitsPerSample), _bitsPerSample); + _outputsamples_buffer_a[i] = extend_sign32((int)readbits(_framesBuffer, ref pos, bps), bps); + _outputsamples_buffer_b[i] = extend_sign32((int)readbits(_framesBuffer, ref pos, bps), bps); } /* wasted_bytes = 0; */ _interlacing_shift = 0; @@ -828,9 +787,9 @@ namespace CUETools.Codecs.ALAC stream_read_uint16(); entry_remaining -= 2; - _channelCount = (int)stream_read_uint16(); + int _channelCount = (int)stream_read_uint16(); - _bitsPerSample = stream_read_uint16(); + int _bitsPerSample = stream_read_uint16(); entry_remaining -= 4; /* compression id */ @@ -840,13 +799,15 @@ namespace CUETools.Codecs.ALAC entry_remaining -= 4; /* sample rate - 32bit fixed point = 16bit?? */ - _sampleRate = stream_read_uint16(); + int _sampleRate = stream_read_uint16(); entry_remaining -= 2; /* skip 2 */ stream_skip(2); entry_remaining -= 2; + pcm = new AudioPCMConfig(_bitsPerSample, _channelCount, _sampleRate); + /* remaining is codec data */ //#if 0 @@ -904,13 +865,13 @@ namespace CUETools.Codecs.ALAC numentries = stream_read_uint32(); size_remaining -= 4; - _time_to_sample_count = new UInt32[numentries]; - _time_to_sample_duration = new UInt32[numentries]; + _time_to_sample_count = new int[numentries]; + _time_to_sample_duration = new int[numentries]; for (i = 0; i < numentries; i++) { - _time_to_sample_count[i] = stream_read_uint32(); - _time_to_sample_duration[i] = stream_read_uint32(); + _time_to_sample_count[i] = (int)stream_read_uint32(); + _time_to_sample_duration[i] = (int)stream_read_uint32(); size_remaining -= 8; } @@ -949,11 +910,11 @@ namespace CUETools.Codecs.ALAC numentries = stream_read_uint32(); size_remaining -= 4; - _sample_byte_size = new uint[numentries]; + _sample_byte_size = new int[numentries]; for (i = 0; i < numentries; i++) { - _sample_byte_size[i] = stream_read_uint32(); + _sample_byte_size[i] = (int)stream_read_uint32(); size_remaining -= 4; } @@ -1259,11 +1220,11 @@ namespace CUETools.Codecs.ALAC Stream _IO; byte[] _codecData; - uint[] _time_to_sample_count, _time_to_sample_duration, _sample_byte_size; + int[] _time_to_sample_count, _time_to_sample_duration, _sample_byte_size; long _saved_mdat_pos; bool _formatRead; int _bitaccumulator; - uint setinfo_max_samples_per_frame; + int setinfo_max_samples_per_frame; byte setinfo_rice_initialhistory; byte setinfo_rice_kmodifier; byte setinfo_rice_historymult; @@ -1276,17 +1237,15 @@ namespace CUETools.Codecs.ALAC predictor_t predictor_info_b; NameValueCollection _tags; - uint _samplesInBuffer, _samplesBufferOffset; + int _samplesInBuffer, _samplesBufferOffset; byte[] _framesBuffer; byte[] _buff; byte _interlacing_shift; byte _interlacing_leftweight; - int _sampleRate; - int _channelCount; - int _bitsPerSample; - ulong _sampleCount; - ulong _sampleOffset; - ulong _iSample; + AudioPCMConfig pcm; + long _sampleCount; + long _sampleOffset; + long _iSample; Dictionary _qtmovie_parsers; Dictionary _qtmovie_parser_params; diff --git a/CUETools.Codecs.ALAC/ALACWriter.cs b/CUETools.Codecs.ALAC/ALACWriter.cs index d036251..4b41fa2 100644 --- a/CUETools.Codecs.ALAC/ALACWriter.cs +++ b/CUETools.Codecs.ALAC/ALACWriter.cs @@ -32,26 +32,16 @@ using CUETools.Codecs; namespace CUETools.Codecs.ALAC { + [AudioEncoderClass("libALAC", "m4a", true, "0 1 2 3 4 5 6 7 8 9 10", "3", 1)] public class ALACWriter : IAudioDest { Stream _IO = null; string _path; long _position; - // number of audio channels - // valid values are 1 to 8 - int channels, ch_code; - - // audio sample rate in Hz - int sample_rate; - - // sample size in bits - // only 16-bit is currently supported - uint bits_per_sample; - // total stream samples - // if 0, stream length is unknown - int sample_count; + // if < 0, stream length is unknown + int sample_count = -1; ALACEncodeParams eparams; @@ -97,22 +87,22 @@ namespace CUETools.Codecs.ALAC List chunk_pos; - public ALACWriter(string path, int bitsPerSample, int channelCount, int sampleRate, Stream IO) - { - if (bitsPerSample != 16) - throw new Exception("Bits per sample must be 16."); - if (channelCount != 2) - throw new Exception("ChannelCount must be 2."); + AudioPCMConfig _pcm; - channels = channelCount; - sample_rate = sampleRate; - bits_per_sample = (uint) bitsPerSample; + public ALACWriter(string path, Stream IO, AudioPCMConfig pcm) + { + _pcm = pcm; + + if (_pcm.BitsPerSample != 16) + throw new Exception("Bits per sample must be 16."); + if (_pcm.ChannelCount != 2) + throw new Exception("ChannelCount must be 2."); _path = path; _IO = IO; - samplesBuffer = new int[Alac.MAX_BLOCKSIZE * (channels == 2 ? 5 : channels)]; - residualBuffer = new int[Alac.MAX_BLOCKSIZE * (channels == 2 ? 6 : channels + 1)]; + samplesBuffer = new int[Alac.MAX_BLOCKSIZE * (_pcm.ChannelCount == 2 ? 5 : _pcm.ChannelCount)]; + residualBuffer = new int[Alac.MAX_BLOCKSIZE * (_pcm.ChannelCount == 2 ? 6 : _pcm.ChannelCount + 1)]; windowBuffer = new float[Alac.MAX_BLOCKSIZE * 2 * Alac.MAX_LPC_WINDOWS]; eparams.set_defaults(_compressionLevel); @@ -120,10 +110,15 @@ namespace CUETools.Codecs.ALAC crc8 = new Crc8(); crc16 = new Crc16(); - frame = new ALACFrame(channels == 2 ? 5 : channels); + frame = new ALACFrame(_pcm.ChannelCount == 2 ? 5 : _pcm.ChannelCount); chunk_pos = new List(); } + public ALACWriter(string path, AudioPCMConfig pcm) + : this(path, null, pcm) + { + } + public int TotalSize { get @@ -159,6 +154,15 @@ namespace CUETools.Codecs.ALAC } } + public string Options + { + set + { + if (value == null || value == "") return; + throw new Exception("Unsupported options " + value); + } + } + #if INTEROP [DllImport("kernel32.dll")] static extern bool GetThreadTimes(IntPtr hThread, out long lpCreationTime, out long lpExitTime, out long lpKernelTime, out long lpUserTime); @@ -200,6 +204,9 @@ namespace CUETools.Codecs.ALAC bitwriter.flush(); _IO.Write(header, 0, 4); + if (sample_count <= 0 && _position != 0) + sample_count = (int)_position; + _IO.Position = _IO.Length; int trailer_len = write_trailers(); _IO.Write(header, 0, trailer_len); @@ -218,7 +225,7 @@ namespace CUETools.Codecs.ALAC public void Close() { DoClose(); - if (sample_count != 0 && _position != sample_count) + if (sample_count > 0 && _position != sample_count) throw new Exception("Samples written differs from the expected sample count."); } @@ -421,9 +428,9 @@ namespace CUETools.Codecs.ALAC } } - public int BitsPerSample + public AudioPCMConfig PCM { - get { return 16; } + get { return _pcm; } } /// @@ -436,12 +443,13 @@ namespace CUETools.Codecs.ALAC { fixed (int* fsamples = samplesBuffer, src = &samples[pos, 0]) { - if (channels == 2) + if (_pcm.ChannelCount == 2) AudioSamples.Deinterlace(fsamples + samplesInBuffer, fsamples + Alac.MAX_BLOCKSIZE + samplesInBuffer, src, block); else - for (int ch = 0; ch < channels; ch++) + for (int ch = 0; ch < _pcm.ChannelCount; ch++) { int* psamples = fsamples + ch * Alac.MAX_BLOCKSIZE + samplesInBuffer; + int channels = _pcm.ChannelCount; for (int i = 0; i < block; i++) psamples[i] = src[i * channels + ch]; } @@ -691,7 +699,7 @@ namespace CUETools.Codecs.ALAC frame.current.order = order; frame.current.window = iWindow; - int bps = (int)bits_per_sample + channels - 1; + int bps = _pcm.BitsPerSample + _pcm.ChannelCount - 1; int* coefs = stackalloc int[lpc.MAX_LPC_ORDER]; @@ -746,7 +754,7 @@ namespace CUETools.Codecs.ALAC { int* smp = frame.subframes[ch].samples; int i, n = frame.blocksize; - int bps = (int)bits_per_sample + channels - 1; + int bps = _pcm.BitsPerSample + _pcm.ChannelCount - 1; // FIXED //if (0 == (2 & frame.subframes[ch].done_fixed) && (pass != 1 || n < eparams.max_prediction_order)) @@ -793,7 +801,7 @@ namespace CUETools.Codecs.ALAC unsafe void output_frame_header(ALACFrame frame, BitWriter bitwriter) { - bitwriter.writebits(3, channels - 1); + bitwriter.writebits(3, _pcm.ChannelCount - 1); bitwriter.writebits(16, 0); bitwriter.writebits(1, frame.blocksize != eparams.block_size ? 1 : 0); // sample count is in the header bitwriter.writebits(2, 0); // wasted bytes @@ -804,7 +812,7 @@ namespace CUETools.Codecs.ALAC { bitwriter.writebits(8, frame.interlacing_shift); bitwriter.writebits(8, frame.interlacing_leftweight); - for (int ch = 0; ch < channels; ch++) + for (int ch = 0; ch < _pcm.ChannelCount; ch++) { bitwriter.writebits(4, 0); // prediction type bitwriter.writebits(4, frame.subframes[ch].best.shift); @@ -879,7 +887,7 @@ namespace CUETools.Codecs.ALAC unsafe void estimate_frame(ALACFrame frame, bool do_midside) { - int subframes = do_midside ? 5 : channels; + int subframes = do_midside ? 5 : _pcm.ChannelCount; switch (eparams.stereo_method) { @@ -938,7 +946,7 @@ namespace CUETools.Codecs.ALAC return total + bitsBest; } - for (int ch = 0; ch < channels; ch++) + for (int ch = 0; ch < _pcm.ChannelCount; ch++) total += frame.subframes[ch].best.size; return total; @@ -949,14 +957,14 @@ namespace CUETools.Codecs.ALAC switch (eparams.stereo_method) { case StereoMethod.Estimate: - for (int ch = 0; ch < channels; ch++) + for (int ch = 0; ch < _pcm.ChannelCount; ch++) { frame.subframes[ch].best.size = AudioSamples.UINT32_MAX; encode_residual_pass2(frame, ch); } break; case StereoMethod.Evaluate: - for (int ch = 0; ch < channels; ch++) + for (int ch = 0; ch < _pcm.ChannelCount; ch++) encode_residual_pass2(frame, ch); break; case StereoMethod.Search: @@ -1004,15 +1012,15 @@ namespace CUETools.Codecs.ALAC } frame.window_buffer = window; - int bps = (int)bits_per_sample + channels - 1; - if (channels != 2 || frame.blocksize <= 32 || eparams.stereo_method == StereoMethod.Independent) + int bps = _pcm.BitsPerSample + _pcm.ChannelCount - 1; + if (_pcm.ChannelCount != 2 || frame.blocksize <= 32 || eparams.stereo_method == StereoMethod.Independent) { - frame.current.residual = r + channels * Alac.MAX_BLOCKSIZE; + frame.current.residual = r + _pcm.ChannelCount * Alac.MAX_BLOCKSIZE; - for (int ch = 0; ch < channels; ch++) + for (int ch = 0; ch < _pcm.ChannelCount; ch++) frame.subframes[ch].Init(s + ch * Alac.MAX_BLOCKSIZE, r + ch * Alac.MAX_BLOCKSIZE); - for (int ch = 0; ch < channels; ch++) + for (int ch = 0; ch < _pcm.ChannelCount; ch++) encode_residual_pass2(frame, ch); } else @@ -1028,7 +1036,7 @@ namespace CUETools.Codecs.ALAC encode_estimated_frame(frame); } - for (int ch = 0; ch < channels; ch++) + for (int ch = 0; ch < _pcm.ChannelCount; ch++) { if (eparams.min_modifier == eparams.max_modifier) frame.subframes[ch].best.ricemodifier = eparams.max_modifier; @@ -1038,23 +1046,30 @@ namespace CUETools.Codecs.ALAC } uint fs = measure_frame_size(frame, false); - frame.type = ((int)fs > frame.blocksize * channels * bps) ? FrameType.Verbatim : FrameType.Compressed; + frame.type = ((int)fs > frame.blocksize * _pcm.ChannelCount * bps) ? FrameType.Verbatim : FrameType.Compressed; BitWriter bitwriter = new BitWriter(frame_buffer, 0, max_frame_size); output_frame_header(frame, bitwriter); if (frame.type == FrameType.Verbatim) { + int obps = _pcm.BitsPerSample; for (int i = 0; i < frame.blocksize; i++) - for (int ch = 0; ch < channels; ch++) - bitwriter.writebits_signed((int)bits_per_sample, frame.subframes[ch].samples[i]); + for (int ch = 0; ch < _pcm.ChannelCount; ch++) + bitwriter.writebits_signed(obps, frame.subframes[ch].samples[i]); } else if (frame.type == FrameType.Compressed) { - for (int ch = 0; ch < channels; ch++) + for (int ch = 0; ch < _pcm.ChannelCount; ch++) alac_entropy_coder(bitwriter, frame.subframes[ch].best.residual, frame.blocksize, bps, frame.subframes[ch].best.ricemodifier); } output_frame_footer(bitwriter); + if (_sample_byte_size.Length <= frame_count) + { + uint[] tmp = new uint[frame_count * 2]; + Array.Copy(_sample_byte_size, tmp, _sample_byte_size.Length); + _sample_byte_size = tmp; + } _sample_byte_size[frame_count++] = (uint)bitwriter.Length; size = frame.blocksize; @@ -1067,7 +1082,7 @@ namespace CUETools.Codecs.ALAC if (verify != null) { fixed (int* s = verifyBuffer, r = samplesBuffer) - for (int ch = 0; ch < channels; ch++) + for (int ch = 0; ch < _pcm.ChannelCount; ch++) AudioSamples.MemCpy(s + ch * Alac.MAX_BLOCKSIZE, r + ch * Alac.MAX_BLOCKSIZE, eparams.block_size); } @@ -1084,14 +1099,15 @@ namespace CUETools.Codecs.ALAC if (verify != null) { int decoded = verify.DecodeFrame(frame_buffer, 0, fs); - if (decoded != fs || verify.Remaining != (ulong)bs) + if (decoded != fs || verify.Remaining != bs) throw new Exception("validation failed!"); - int [,] deinterlaced = new int[bs,channels]; - verify.deinterlace(deinterlaced, 0, (uint)bs); + int[,] deinterlaced = new int[bs, _pcm.ChannelCount]; + verify.deinterlace(deinterlaced, 0, bs); fixed (int* s = verifyBuffer, r = deinterlaced) { + int channels = _pcm.ChannelCount; for (int i = 0; i < bs; i++) - for (int ch = 0; ch < channels; ch++) + for (int ch = 0; ch < _pcm.ChannelCount; ch++) if (r[i * channels + ch] != s[ch * Alac.MAX_BLOCKSIZE + i]) throw new Exception("validation failed!"); } @@ -1100,7 +1116,7 @@ namespace CUETools.Codecs.ALAC if (bs < blocksize) { fixed (int* s = samplesBuffer) - for (int ch = 0; ch < channels; ch++) + for (int ch = 0; ch < _pcm.ChannelCount; ch++) AudioSamples.MemCpy(s + ch * Alac.MAX_BLOCKSIZE, s + bs + ch * Alac.MAX_BLOCKSIZE, eparams.block_size - bs); } @@ -1109,7 +1125,7 @@ namespace CUETools.Codecs.ALAC return bs; } - public void Write(int[,] buff, int pos, int sampleCount) + public void Write(AudioBuffer buff) { if (!inited) { @@ -1122,12 +1138,15 @@ namespace CUETools.Codecs.ALAC inited = true; } - int len = sampleCount; + buff.Prepare(this); + + int pos = 0; + int len = buff.Length; while (len > 0) { int block = Math.Min(len, eparams.block_size - samplesInBuffer); - copy_samples(buff, pos, block); + copy_samples(buff.Samples, pos, block); len -= block; pos += block; @@ -1139,6 +1158,28 @@ namespace CUETools.Codecs.ALAC public string Path { get { return _path; } } + private DateTime? _creationTime = null; + + public DateTime CreationTime + { + set + { + _creationTime = value; + } + } + + public string Vendor + { + get + { + return vendor_string; + } + set + { + vendor_string = value; + } + } + string vendor_string = "CUETools.2.05"; int select_blocksize(int samplerate, int time_ms) @@ -1235,7 +1276,7 @@ namespace CUETools.Codecs.ALAC bitwriter.writebits(16, 16); // reserved bps bitwriter.writebits(16, 0); // reserved compression ID bitwriter.writebits(16, 0); // packet size - bitwriter.writebits(16, sample_rate); // time scale + bitwriter.writebits(16, _pcm.SampleRate); // time scale bitwriter.writebits(16, 0); // reserved chunk_start(bitwriter); { @@ -1243,15 +1284,15 @@ namespace CUETools.Codecs.ALAC bitwriter.writebits(32, 0); // reserved bitwriter.writebits(32, eparams.block_size); // max frame size bitwriter.writebits(8, 0); // reserved - bitwriter.writebits(8, bits_per_sample); + bitwriter.writebits(8, _pcm.BitsPerSample); bitwriter.writebits(8, history_mult); bitwriter.writebits(8, initial_history); bitwriter.writebits(8, k_modifier); - bitwriter.writebits(8, channels); // channels + bitwriter.writebits(8, _pcm.ChannelCount); // channels bitwriter.writebits(16, 0); // reserved bitwriter.writebits(32, max_frame_size); - bitwriter.writebits(32, sample_rate * channels * (int)bits_per_sample); // average bitrate - bitwriter.writebits(32, sample_rate); + bitwriter.writebits(32, _pcm.SampleRate * _pcm.ChannelCount * _pcm.BitsPerSample); // average bitrate + bitwriter.writebits(32, _pcm.SampleRate); } chunk_end(bitwriter); } @@ -1328,7 +1369,7 @@ namespace CUETools.Codecs.ALAC bitwriter.writebits(32, 0); // version & flags bitwriter.writebits(32, (int)UnixTime.TotalSeconds); bitwriter.writebits(32, (int)UnixTime.TotalSeconds); - bitwriter.writebits(32, sample_rate); + bitwriter.writebits(32, _pcm.SampleRate); bitwriter.writebits(32, sample_count); bitwriter.writebits(16, 0x55c4); // language bitwriter.writebits(16, 0); // quality @@ -1365,7 +1406,7 @@ namespace CUETools.Codecs.ALAC bitwriter.writebits(32, (int)UnixTime.TotalSeconds); bitwriter.writebits(32, 1); // track ID bitwriter.writebits(32, 0); // reserved - bitwriter.writebits(32, sample_count / sample_rate); + bitwriter.writebits(32, sample_count / _pcm.SampleRate); bitwriter.writebits(32, 0); // reserved bitwriter.writebits(32, 0); // reserved bitwriter.writebits(32, 0); // reserved (layer & alternate group) @@ -1436,8 +1477,8 @@ namespace CUETools.Codecs.ALAC int write_trailers() { - TimeSpan UnixTime = DateTime.Now - new DateTime(1970, 1, 1, 0, 0, 0, 0).ToLocalTime(); - header = new byte[0x1000 + frame_count * 8]; // FIXME!!! Possible buffer overrun + TimeSpan UnixTime = (_creationTime ?? DateTime.Now) - new DateTime(1970, 1, 1, 0, 0, 0, 0).ToLocalTime(); + header = new byte[0x1000 + frame_count * 8 + eparams.padding_size]; // FIXME!!! Possible buffer overrun BitWriter bitwriter = new BitWriter(header, 0, header.Length); chunk_start(bitwriter); { @@ -1447,6 +1488,12 @@ namespace CUETools.Codecs.ALAC write_chunk_udta(bitwriter); } chunk_end(bitwriter); + chunk_start(bitwriter); // padding + { + bitwriter.write('f', 'r', 'e', 'e'); + bitwriter.writebytes(eparams.padding_size, 0); + } + chunk_end(bitwriter); return bitwriter.Length; } @@ -1464,6 +1511,13 @@ namespace CUETools.Codecs.ALAC bitwriter.writebits(32, 0); chunk_end(bitwriter); + chunk_start(bitwriter); // padding + { + bitwriter.write('f', 'r', 'e', 'e'); + bitwriter.writebytes(eparams.padding_size, 0); + } + chunk_end(bitwriter); + chunk_start(bitwriter); // padding in case we need extended mdat len bitwriter.write('f', 'r', 'e', 'e'); chunk_end(bitwriter); @@ -1483,30 +1537,28 @@ namespace CUETools.Codecs.ALAC //if(flake_validate_params(s) < 0) - ch_code = channels - 1; - // FIXME: For now, only 44100 samplerate is supported - if (sample_rate != 44100) + if (_pcm.SampleRate != 44100) throw new Exception("non-standard samplerate"); // FIXME: For now, only 16-bit encoding is supported - if (bits_per_sample != 16) + if (_pcm.BitsPerSample != 16) throw new Exception("non-standard bps"); if (_blocksize == 0) { if (eparams.block_size == 0) - eparams.block_size = select_blocksize(sample_rate, eparams.block_time_ms); + eparams.block_size = select_blocksize(_pcm.SampleRate, eparams.block_time_ms); _blocksize = eparams.block_size; } else eparams.block_size = _blocksize; // set maximum encoded frame size (if larger, re-encodes in verbatim mode) - if (channels == 2) - max_frame_size = 16 + ((eparams.block_size * (int)(bits_per_sample + bits_per_sample + 1) + 7) >> 3); + if (_pcm.ChannelCount == 2) + max_frame_size = 16 + ((eparams.block_size * (_pcm.BitsPerSample + _pcm.BitsPerSample + 1) + 7) >> 3); else - max_frame_size = 16 + ((eparams.block_size * channels * (int)bits_per_sample + 7) >> 3); + max_frame_size = 16 + ((eparams.block_size * _pcm.ChannelCount * _pcm.BitsPerSample + 7) >> 3); //if (_IO.CanSeek && eparams.do_seektable) //{ @@ -1517,12 +1569,12 @@ namespace CUETools.Codecs.ALAC header_len = write_headers(); frame_buffer = new byte[max_frame_size]; - _sample_byte_size = new uint[sample_count / eparams.block_size + 1]; + _sample_byte_size = new uint[Math.Max(0x100, sample_count / eparams.block_size + 1)]; if (eparams.do_verify) { - verify = new ALACReader(channels, (int)bits_per_sample, history_mult, initial_history, k_modifier, eparams.block_size); - verifyBuffer = new int[Alac.MAX_BLOCKSIZE * channels]; + verify = new ALACReader(_pcm, history_mult, initial_history, k_modifier, eparams.block_size); + verifyBuffer = new int[Alac.MAX_BLOCKSIZE * _pcm.ChannelCount]; } return header_len; diff --git a/CUETools.Codecs.ALAC/CUETools.Codecs.ALAC.csproj b/CUETools.Codecs.ALAC/CUETools.Codecs.ALAC.csproj index 4c3d264..3e1fdc4 100644 --- a/CUETools.Codecs.ALAC/CUETools.Codecs.ALAC.csproj +++ b/CUETools.Codecs.ALAC/CUETools.Codecs.ALAC.csproj @@ -23,7 +23,7 @@ pdbonly true - ..\bin\x64\Release\ + ..\bin\any\Release\ TRACE prompt 4 diff --git a/CUETools.Codecs.APE/CUETools.Codecs.APE.cpp b/CUETools.Codecs.APE/CUETools.Codecs.APE.cpp index 17f2381..9d5606f 100644 --- a/CUETools.Codecs.APE/CUETools.Codecs.APE.cpp +++ b/CUETools.Codecs.APE/CUETools.Codecs.APE.cpp @@ -101,6 +101,7 @@ namespace CUETools { namespace Codecs { namespace APE { GCHandle _gchBuffer; }; + [AudioDecoderClass("MAC_SDK", "ape")] public ref class APEReader : public IAudioSource { public: @@ -124,9 +125,10 @@ namespace CUETools { namespace Codecs { namespace APE { throw gcnew Exception("Unable to open file."); } - _sampleRate = pAPEDecompress->GetInfo (APE_INFO_SAMPLE_RATE, 0, 0); - _bitsPerSample = pAPEDecompress->GetInfo (APE_INFO_BITS_PER_SAMPLE, 0, 0); - _channelCount = pAPEDecompress->GetInfo (APE_INFO_CHANNELS, 0, 0); + pcm = gcnew AudioPCMConfig( + pAPEDecompress->GetInfo (APE_INFO_BITS_PER_SAMPLE, 0, 0), + pAPEDecompress->GetInfo (APE_INFO_CHANNELS, 0, 0), + pAPEDecompress->GetInfo (APE_INFO_SAMPLE_RATE, 0, 0)); // make a buffer to hold 16384 blocks of audio data nBlockAlign = pAPEDecompress->GetInfo (APE_INFO_BLOCK_ALIGN, 0, 0); @@ -146,36 +148,24 @@ namespace CUETools { namespace Codecs { namespace APE { _gchReadBuffer.Free(); } - virtual property Int32 BitsPerSample { - Int32 get() { - return _bitsPerSample; + virtual property AudioPCMConfig^ PCM { + AudioPCMConfig^ get() { + return pcm; } } - virtual property Int32 ChannelCount { - Int32 get() { - return _channelCount; - } - } - - virtual property Int32 SampleRate { - Int32 get() { - return _sampleRate; - } - } - - virtual property UInt64 Length { - UInt64 get() { + virtual property Int64 Length { + Int64 get() { return _sampleCount; } } - virtual property UInt64 Position + virtual property Int64 Position { - UInt64 get() { + Int64 get() { return _sampleOffset - SamplesInBuffer; } - void set(UInt64 offset) { + void set(Int64 offset) { _sampleOffset = offset; _bufferOffset = 0; _bufferLength = 0; @@ -184,8 +174,8 @@ namespace CUETools { namespace Codecs { namespace APE { } } - virtual property UInt64 Remaining { - UInt64 get() { + virtual property Int64 Remaining { + Int64 get() { return _sampleCount - _sampleOffset + SamplesInBuffer; } } @@ -210,15 +200,13 @@ namespace CUETools { namespace Codecs { namespace APE { } } - virtual array^ Read(array^ buff) + virtual int Read(AudioBuffer^ buff, int maxLength) { - return AudioSamples::Read(this, buff); - } + buff->Prepare(this, maxLength); - virtual UInt32 Read([Out] array^ buff, UInt32 sampleCount) - { - UInt32 buffOffset = 0; - UInt32 samplesNeeded = sampleCount; + Int32 buffOffset = 0; + Int32 samplesNeeded = buff->Length; + Int32 _channelCount = pcm->ChannelCount; while (samplesNeeded != 0) { @@ -232,21 +220,21 @@ namespace CUETools { namespace Codecs { namespace APE { _bufferLength = nBlocksRetrieved; _sampleOffset += nBlocksRetrieved; } - UInt32 copyCount = Math::Min(samplesNeeded, SamplesInBuffer); - AudioSamples::BytesToFLACSamples_16(_samplesBuffer, _bufferOffset*nBlockAlign, buff, buffOffset, copyCount, _channelCount); + Int32 copyCount = Math::Min(samplesNeeded, SamplesInBuffer); + AudioBuffer::BytesToFLACSamples_16(_samplesBuffer, _bufferOffset*nBlockAlign, buff->Samples, buffOffset, copyCount, _channelCount); samplesNeeded -= copyCount; buffOffset += copyCount; _bufferOffset += copyCount; } - return sampleCount; + return buff->Length; } private: IAPEDecompress * pAPEDecompress; Int64 _sampleCount, _sampleOffset; - Int32 _bitsPerSample, _channelCount, _sampleRate; - UInt32 _bufferOffset, _bufferLength; + AudioPCMConfig^ pcm; + Int32 _bufferOffset, _bufferLength; int nBlockAlign; array^ _samplesBuffer; String^ _path; @@ -255,39 +243,37 @@ namespace CUETools { namespace Codecs { namespace APE { CWinFileIO* _winFileIO; GCHandle _gchIO, _gchReadBuffer; - property UInt32 SamplesInBuffer + property Int32 SamplesInBuffer { - UInt32 get () + Int32 get () { - return (UInt32) (_bufferLength - _bufferOffset); + return _bufferLength - _bufferOffset; } } }; + [AudioEncoderClass("MAC_SDK", "ape", true, "fast normal high extra insane", "high", 1)] public ref class APEWriter : IAudioDest { public: - APEWriter(String^ path, Int32 bitsPerSample, Int32 channelCount, Int32 sampleRate) + APEWriter(String^ path, AudioPCMConfig^ pcm) { - if (channelCount != 1 && channelCount != 2) + _pcm = pcm; + + if (_pcm->ChannelCount != 1 && _pcm->ChannelCount != 2) throw gcnew Exception("Only stereo and mono audio formats are allowed."); - if (bitsPerSample != 16 && bitsPerSample != 24) + if (_pcm->BitsPerSample != 16 && _pcm->BitsPerSample != 24) throw gcnew Exception("Monkey's Audio doesn't support selected bits per sample value."); - _path = path; - _winFileIO = NULL; + _path = path; + _winFileIO = NULL; - _compressionLevel = COMPRESSION_LEVEL_NORMAL; + _compressionLevel = COMPRESSION_LEVEL_NORMAL; - _bitsPerSample = bitsPerSample; - _channelCount = channelCount; - _sampleRate = sampleRate; - _blockAlign = _channelCount * ((_bitsPerSample + 7) / 8); - - int nRetVal; - pAPECompress = CreateIAPECompress (&nRetVal); - if (!pAPECompress) - throw gcnew Exception("Unable to open APE compressor."); + int nRetVal; + pAPECompress = CreateIAPECompress (&nRetVal); + if (!pAPECompress) + throw gcnew Exception("Unable to open APE compressor."); } ~APEWriter() @@ -349,21 +335,23 @@ namespace CUETools { namespace Codecs { namespace APE { } } - virtual property int BitsPerSample + virtual property AudioPCMConfig^ PCM { - int get() { return _bitsPerSample; } + AudioPCMConfig^ get() + { + return _pcm; + } } - virtual void Write(array^ buff, int offset, int sampleCount) + virtual void Write(AudioBuffer^ buff) { - if (_sampleBuffer == nullptr || _sampleBuffer.Length < sampleCount * _blockAlign) - _sampleBuffer = gcnew array(sampleCount * _blockAlign); - AudioSamples::FLACSamplesToBytes(buff, offset, _sampleBuffer, 0, sampleCount, _channelCount, _bitsPerSample); - if (!_initialized) Initialize(); - pin_ptr pSampleBuffer = &_sampleBuffer[0]; - if (pAPECompress->AddData (pSampleBuffer, sampleCount * _blockAlign)) + if (!_initialized) + Initialize(); + buff->Prepare(this); + pin_ptr pSampleBuffer = &buff->Bytes[0]; + if (pAPECompress->AddData (pSampleBuffer, buff->ByteLength)) throw gcnew Exception("An error occurred while encoding."); - _samplesWritten += sampleCount; + _samplesWritten += buff->Length; } virtual property String^ Path @@ -373,7 +361,7 @@ namespace CUETools { namespace Codecs { namespace APE { } } - property Int32 CompressionLevel { + virtual property Int32 CompressionLevel { Int32 get() { return _compressionLevel / 1000 - 1; } @@ -385,11 +373,20 @@ namespace CUETools { namespace Codecs { namespace APE { } } + virtual property String^ Options + { + void set(String^ value) + { + if (value == nullptr || value == "") return; + throw gcnew Exception(String::Format("Unsupported options: {0}", value)); + } + } + private: IAPECompress * pAPECompress; bool _initialized; Int32 _finalSampleCount, _samplesWritten; - Int32 _bitsPerSample, _channelCount, _sampleRate, _blockAlign; + AudioPCMConfig^ _pcm; Int32 _compressionLevel; String^ _path; Stream^ _IO; @@ -407,11 +404,11 @@ namespace CUETools { namespace Codecs { namespace APE { _winFileIO = new CWinFileIO(_gchIO, _gchBuffer); WAVEFORMATEX waveFormat; - FillWaveFormatEx (&waveFormat, _sampleRate, _bitsPerSample, _channelCount); + FillWaveFormatEx (&waveFormat, _pcm->SampleRate, _pcm->BitsPerSample, _pcm->ChannelCount); int res = pAPECompress->StartEx (_winFileIO, &waveFormat, - (_finalSampleCount == 0) ? MAX_AUDIO_BYTES_UNKNOWN : _finalSampleCount * _blockAlign, + (_finalSampleCount == 0) ? MAX_AUDIO_BYTES_UNKNOWN : _finalSampleCount * _pcm->BlockAlign, _compressionLevel, NULL, CREATE_WAV_HEADER_ON_DECOMPRESSION); diff --git a/CUETools.Codecs.APE/CUETools.Codecs.APE.vcproj b/CUETools.Codecs.APE/CUETools.Codecs.APE.vcproj index 8d657c2..799a4c2 100644 --- a/CUETools.Codecs.APE/CUETools.Codecs.APE.vcproj +++ b/CUETools.Codecs.APE/CUETools.Codecs.APE.vcproj @@ -20,7 +20,7 @@ diff --git a/CUETools.Codecs.FLAC/CUETools.Codecs.FLAC.cpp b/CUETools.Codecs.FLAC/CUETools.Codecs.FLAC.cpp index ee14b87..1dc7c83 100644 --- a/CUETools.Codecs.FLAC/CUETools.Codecs.FLAC.cpp +++ b/CUETools.Codecs.FLAC/CUETools.Codecs.FLAC.cpp @@ -67,10 +67,11 @@ namespace CUETools { namespace Codecs { namespace FLAC { [UnmanagedFunctionPointer(CallingConvention::Cdecl)] public delegate FLAC__bool DecoderEofDelegate (const FLAC__StreamDecoder *decoder, void *client_data); + [AudioDecoderClass("libFLAC", "flac")] public ref class FLACReader : public IAudioSource { public: - FLACReader(String^ path, Stream^ IO, bool disableAsm) + FLACReader(String^ path, Stream^ IO) { _writeDel = gcnew DecoderWriteDelegate(this, &FLACReader::WriteCallback); _metadataDel = gcnew DecoderMetadataDelegate(this, &FLACReader::MetadataCallback); @@ -96,8 +97,8 @@ namespace CUETools { namespace Codecs { namespace FLAC { if (!FLAC__stream_decoder_set_metadata_respond (_decoder, FLAC__METADATA_TYPE_VORBIS_COMMENT)) throw gcnew Exception("Unable to setup the decoder."); - if (!FLAC__stream_decoder_set_disable_asm(_decoder, disableAsm)) - throw gcnew Exception("Unable to setup the decoder."); + //if (!FLAC__stream_decoder_set_disable_asm(_decoder, disableAsm)) + // throw gcnew Exception("Unable to setup the decoder."); if (FLAC__stream_decoder_init_stream(_decoder, (FLAC__StreamDecoderReadCallback)Marshal::GetFunctionPointerForDelegate(_readDel).ToPointer(), @@ -126,36 +127,24 @@ namespace CUETools { namespace Codecs { namespace FLAC { Close (); } - virtual property Int32 BitsPerSample { - Int32 get() { - return _bitsPerSample; + virtual property AudioPCMConfig^ PCM { + AudioPCMConfig^ get() { + return pcm; } } - virtual property Int32 ChannelCount { - Int32 get() { - return _channelCount; - } - } - - virtual property Int32 SampleRate { - Int32 get() { - return _sampleRate; - } - } - - virtual property UInt64 Length { - UInt64 get() { + virtual property Int64 Length { + Int64 get() { return _sampleCount; } } - virtual property UInt64 Position { - UInt64 get() + virtual property Int64 Position { + Int64 get() { return _sampleOffset - SamplesInBuffer; } - void set(UInt64 offset) + void set(Int64 offset) { _sampleOffset = offset; _bufferOffset = 0; @@ -236,8 +225,8 @@ namespace CUETools { namespace Codecs { namespace FLAC { // return 0 != res; //} - virtual property UInt64 Remaining { - UInt64 get() { + virtual property Int64 Remaining { + Int64 get() { return _sampleCount - _sampleOffset + SamplesInBuffer; } } @@ -256,15 +245,12 @@ namespace CUETools { namespace Codecs { namespace FLAC { } } - virtual array^ Read(array^ buff) + virtual int Read(AudioBuffer^ buff, int maxLength) { - return AudioSamples::Read(this, buff); - } + buff->Prepare(this, maxLength); - virtual UInt32 Read([Out] array^ buff, UInt32 sampleCount) - { - UInt32 buffOffset = 0; - UInt32 samplesNeeded = sampleCount; + Int32 buffOffset = 0; + Int32 samplesNeeded = buff->Length; while (samplesNeeded != 0) { @@ -275,19 +261,19 @@ namespace CUETools { namespace Codecs { namespace FLAC { do { if (FLAC__stream_decoder_get_state(_decoder) == FLAC__STREAM_DECODER_END_OF_STREAM) - return sampleCount - samplesNeeded; + return buff->Length - samplesNeeded; if (!FLAC__stream_decoder_process_single(_decoder)) throw gcnew Exception("An error occurred while decoding."); } while (_bufferLength == 0); _sampleOffset += _bufferLength; } - UInt32 copyCount = Math::Min(samplesNeeded, SamplesInBuffer); - Array::Copy(_sampleBuffer, _bufferOffset * _channelCount, buff, buffOffset * _channelCount, copyCount * _channelCount); + Int32 copyCount = Math::Min(samplesNeeded, SamplesInBuffer); + Array::Copy(_sampleBuffer, _bufferOffset * pcm->ChannelCount, buff->Samples, buffOffset * pcm->ChannelCount, copyCount * pcm->ChannelCount); samplesNeeded -= copyCount; buffOffset += copyCount; _bufferOffset += copyCount; } - return sampleCount; + return buff->Length; } private: @@ -301,18 +287,18 @@ namespace CUETools { namespace Codecs { namespace FLAC { DecoderEofDelegate^ _eofDel; FLAC__StreamDecoder *_decoder; Int64 _sampleCount, _sampleOffset; - Int32 _bitsPerSample, _channelCount, _sampleRate; + AudioPCMConfig^ pcm; array^ _sampleBuffer; array^ _readBuffer; String^ _path; bool _decoderActive; Stream^ _IO; - UInt32 _bufferOffset, _bufferLength; + Int32 _bufferOffset, _bufferLength; - property UInt32 SamplesInBuffer { - UInt32 get () + property Int32 SamplesInBuffer { + Int32 get () { - return (UInt32) (_bufferLength - _bufferOffset); + return _bufferLength - _bufferOffset; } } @@ -325,17 +311,18 @@ namespace CUETools { namespace Codecs { namespace FLAC { throw gcnew Exception("Received unrequested samples."); } - if ((frame->header.bits_per_sample != _bitsPerSample) || - (frame->header.channels != _channelCount) || - (frame->header.sample_rate != _sampleRate)) + if ((frame->header.bits_per_sample != pcm->BitsPerSample) || + (frame->header.channels != pcm->ChannelCount) || + (frame->header.sample_rate != pcm->SampleRate)) { throw gcnew Exception("Format changes within a file are not allowed."); } if ((_sampleBuffer == nullptr) || (_sampleBuffer->GetLength(0) < sampleCount)) { - _sampleBuffer = gcnew array(sampleCount, _channelCount); + _sampleBuffer = gcnew array(sampleCount, pcm->ChannelCount); } + int _channelCount = pcm->ChannelCount; for (Int32 iChan = 0; iChan < _channelCount; iChan++) { interior_ptr pMyBuffer = &_sampleBuffer[0, iChan]; const FLAC__int32 *pFLACBuffer = buffer[iChan]; @@ -357,9 +344,10 @@ namespace CUETools { namespace Codecs { namespace FLAC { { if (metadata->type == FLAC__METADATA_TYPE_STREAMINFO) { - _bitsPerSample = metadata->data.stream_info.bits_per_sample; - _channelCount = metadata->data.stream_info.channels; - _sampleRate = metadata->data.stream_info.sample_rate; + pcm = gcnew AudioPCMConfig( + metadata->data.stream_info.bits_per_sample, + metadata->data.stream_info.channels, + metadata->data.stream_info.sample_rate); _sampleCount = metadata->data.stream_info.total_samples; } //if (metadata->type == FLAC__METADATA_TYPE_VORBIS_COMMENT) @@ -447,12 +435,15 @@ namespace CUETools { namespace Codecs { namespace FLAC { } }; + [AudioEncoderClass("libFLAC", "flac", true, "0 1 2 3 4 5 6 7 8", "5", 1)] public ref class FLACWriter : IAudioDest { public: - FLACWriter(String^ path, Int32 bitsPerSample, Int32 channelCount, Int32 sampleRate) + FLACWriter(String^ path, AudioPCMConfig^ pcm) { - if (bitsPerSample < 16 || bitsPerSample > 24) + _pcm = pcm; + + if (_pcm->BitsPerSample < 16 || _pcm->BitsPerSample > 24) throw gcnew Exception("Bits per sample must be 16..24."); _initialized = false; @@ -460,9 +451,6 @@ namespace CUETools { namespace Codecs { namespace FLAC { _path = path; _finalSampleCount = 0; _samplesWritten = 0; - _bitsPerSample = bitsPerSample; - _channelCount = channelCount; - _sampleRate = sampleRate; _compressionLevel = 5; _paddingLength = 8192; _verify = false; @@ -470,9 +458,9 @@ namespace CUETools { namespace Codecs { namespace FLAC { _encoder = FLAC__stream_encoder_new(); - FLAC__stream_encoder_set_bits_per_sample(_encoder, bitsPerSample); - FLAC__stream_encoder_set_channels(_encoder, channelCount); - FLAC__stream_encoder_set_sample_rate(_encoder, sampleRate); + FLAC__stream_encoder_set_bits_per_sample(_encoder, _pcm->BitsPerSample); + FLAC__stream_encoder_set_channels(_encoder, _pcm->ChannelCount); + FLAC__stream_encoder_set_sample_rate(_encoder, _pcm->SampleRate); } virtual void Close() { @@ -520,9 +508,10 @@ namespace CUETools { namespace Codecs { namespace FLAC { } } - virtual property int BitsPerSample - { - int get() { return _bitsPerSample; } + virtual property AudioPCMConfig^ PCM { + AudioPCMConfig^ get() { + return _pcm; + } } virtual property String^ Path { @@ -531,13 +520,15 @@ namespace CUETools { namespace Codecs { namespace FLAC { } } - virtual void Write(array^ sampleBuffer, int offset, int sampleCount) { + virtual void Write(AudioBuffer^ sampleBuffer) { if (!_initialized) Initialize(); - pin_ptr pSampleBuffer = &sampleBuffer[offset, 0]; + sampleBuffer->Prepare(this); + + pin_ptr pSampleBuffer = &sampleBuffer->Samples[0, 0]; if (!FLAC__stream_encoder_process_interleaved(_encoder, - (const FLAC__int32*)pSampleBuffer, sampleCount)) + (const FLAC__int32*)pSampleBuffer, sampleBuffer->Length)) { String^ state = gcnew String(FLAC__StreamEncoderStateString[FLAC__stream_encoder_get_state(_encoder)]); if (FLAC__stream_encoder_get_state(_encoder) == FLAC__STREAM_ENCODER_VERIFY_MISMATCH_IN_AUDIO_DATA) @@ -553,10 +544,10 @@ namespace CUETools { namespace Codecs { namespace FLAC { throw gcnew Exception("An error occurred while encoding: " + state); } - _samplesWritten += sampleCount; + _samplesWritten += sampleBuffer->Length; } - property Int32 CompressionLevel { + virtual property Int32 CompressionLevel { Int32 get() { return _compressionLevel; } @@ -568,6 +559,34 @@ namespace CUETools { namespace Codecs { namespace FLAC { } } + virtual property String^ Options + { + void set(String^ value) + { + if (value == nullptr || value == "") return; + cli::array^ args = value->Split(); + for (int i = 0; i < args->Length; i++) + { + if (args[i] == "--padding-length" && (++i) < args->Length) + { + PaddingLength = Int32::Parse(args[i]); + continue; + } + if (args[i] == "--disable-asm") + { + DisableAsm = true; + continue; + } + if (args[i] == "--verify") + { + Verify = true; + continue; + } + throw gcnew Exception(String::Format("Unsupported options: {0}", value)); + } + } + } + property Boolean Verify { Boolean get() { return _verify; @@ -603,7 +622,7 @@ namespace CUETools { namespace Codecs { namespace FLAC { bool _initialized; String^ _path; Int64 _finalSampleCount, _samplesWritten, _blockSize; - Int32 _bitsPerSample, _channelCount, _sampleRate; + AudioPCMConfig^ _pcm; Int32 _compressionLevel; Int32 _paddingLength; Boolean _verify; @@ -622,7 +641,7 @@ namespace CUETools { namespace Codecs { namespace FLAC { if (_finalSampleCount != 0) { seektable = FLAC__metadata_object_new(FLAC__METADATA_TYPE_SEEKTABLE); FLAC__metadata_object_seektable_template_append_spaced_points_by_samples( - seektable, _sampleRate * 10, _finalSampleCount); + seektable, _pcm->SampleRate * 10, _finalSampleCount); FLAC__metadata_object_seektable_template_sort(seektable, true); _metadataList[_metadataCount++] = seektable; } diff --git a/CUETools.Codecs.FLAC/CUETools.Codecs.FLAC.vcproj b/CUETools.Codecs.FLAC/CUETools.Codecs.FLAC.vcproj index 4bafacb..0447aff 100644 --- a/CUETools.Codecs.FLAC/CUETools.Codecs.FLAC.vcproj +++ b/CUETools.Codecs.FLAC/CUETools.Codecs.FLAC.vcproj @@ -20,7 +20,7 @@ diff --git a/CUETools.Codecs.FLAKE/CUETools.Codecs.FLAKE.csproj b/CUETools.Codecs.FLAKE/CUETools.Codecs.FLAKE.csproj index cdb17e7..3a049e9 100644 --- a/CUETools.Codecs.FLAKE/CUETools.Codecs.FLAKE.csproj +++ b/CUETools.Codecs.FLAKE/CUETools.Codecs.FLAKE.csproj @@ -23,7 +23,7 @@ pdbonly true - bin\Release\ + ..\bin\any\Release\ TRACE prompt 4 diff --git a/CUETools.Codecs.FLAKE/Flake.cs b/CUETools.Codecs.FLAKE/Flake.cs index 38db01c..ab474f9 100644 --- a/CUETools.Codecs.FLAKE/Flake.cs +++ b/CUETools.Codecs.FLAKE/Flake.cs @@ -123,7 +123,7 @@ namespace CUETools.Codecs.FLAKE lpc_ctx[i] = new LpcContext(); } - public void Init(int* s, int* r, uint bps, uint w) + public void Init(int* s, int* r, int bps, int w) { if (w > bps) throw new Exception("internal error"); @@ -139,8 +139,8 @@ namespace CUETools.Codecs.FLAKE } public FlacSubframe best; - public uint obits; - public uint wbits; + public int obits; + public int wbits; public int* samples; public uint done_fixed; public LpcContext[] lpc_ctx; @@ -314,9 +314,9 @@ namespace CUETools.Codecs.FLAKE public struct SeekPoint { - public ulong number; - public ulong offset; - public uint framesize; + public long number; + public long offset; + public int framesize; } public enum MetadataType diff --git a/CUETools.Codecs.FLAKE/FlakeReader.cs b/CUETools.Codecs.FLAKE/FlakeReader.cs index ee61090..da7fef0 100644 --- a/CUETools.Codecs.FLAKE/FlakeReader.cs +++ b/CUETools.Codecs.FLAKE/FlakeReader.cs @@ -26,6 +26,7 @@ using System.IO; namespace CUETools.Codecs.FLAKE { + [AudioDecoderClass("libFlake", "flac")] public class FlakeReader: IAudioSource { int[] samplesBuffer; @@ -41,18 +42,15 @@ namespace CUETools.Codecs.FLAKE Crc16 crc16; FlacFrame frame; BitReader framereader; - int channels; - uint bits_per_sample; - int sample_rate = 44100; + AudioPCMConfig pcm; uint min_block_size = 0; uint max_block_size = 0; uint min_frame_size = 0; uint max_frame_size = 0; - uint _samplesInBuffer, _samplesBufferOffset; - ulong _sampleCount = 0; - ulong _sampleOffset = 0; + int _samplesInBuffer, _samplesBufferOffset; + long _sampleCount = 0, _sampleOffset = 0; bool do_crc = true; @@ -90,37 +88,36 @@ namespace CUETools.Codecs.FLAKE _framesBuffer = new byte[0x20000]; decode_metadata(); - frame = new FlacFrame(channels); + frame = new FlacFrame(PCM.ChannelCount); framereader = new BitReader(); - //max_frame_size = 16 + ((Flake.MAX_BLOCKSIZE * (int)(bits_per_sample * channels + 1) + 7) >> 3); - if (((int)max_frame_size * (int)bits_per_sample * channels * 2 >> 3) > _framesBuffer.Length) + //max_frame_size = 16 + ((Flake.MAX_BLOCKSIZE * PCM.BitsPerSample * PCM.ChannelCount + 1) + 7) >> 3); + if (((int)max_frame_size * PCM.BitsPerSample * PCM.ChannelCount * 2 >> 3) > _framesBuffer.Length) { byte[] temp = _framesBuffer; - _framesBuffer = new byte[((int)max_frame_size * (int)bits_per_sample * channels * 2 >> 3)]; + _framesBuffer = new byte[((int)max_frame_size * PCM.BitsPerSample * PCM.ChannelCount * 2 >> 3)]; if (_framesBufferLength > 0) Array.Copy(temp, _framesBufferOffset, _framesBuffer, 0, _framesBufferLength); _framesBufferOffset = 0; } _samplesInBuffer = 0; - if (bits_per_sample != 16 || channels != 2 || sample_rate != 44100) + if (PCM.BitsPerSample != 16 || PCM.ChannelCount != 2 || PCM.SampleRate != 44100) throw new Exception("invalid flac file"); - samplesBuffer = new int[Flake.MAX_BLOCKSIZE * channels]; - residualBuffer = new int[Flake.MAX_BLOCKSIZE * channels]; + samplesBuffer = new int[Flake.MAX_BLOCKSIZE * PCM.ChannelCount]; + residualBuffer = new int[Flake.MAX_BLOCKSIZE * PCM.ChannelCount]; } - public FlakeReader(int _channels, uint _bits_per_sample) + public FlakeReader(AudioPCMConfig _pcm) { + pcm = _pcm; crc8 = new Crc8(); crc16 = new Crc16(); - channels = _channels; - bits_per_sample = _bits_per_sample; - samplesBuffer = new int[Flake.MAX_BLOCKSIZE * channels]; - residualBuffer = new int[Flake.MAX_BLOCKSIZE * channels]; - frame = new FlacFrame(channels); + samplesBuffer = new int[Flake.MAX_BLOCKSIZE * PCM.ChannelCount]; + residualBuffer = new int[Flake.MAX_BLOCKSIZE * PCM.ChannelCount]; + frame = new FlacFrame(PCM.ChannelCount); framereader = new BitReader(); } @@ -129,12 +126,7 @@ namespace CUETools.Codecs.FLAKE _IO.Close(); } - public int[,] Read(int[,] buff) - { - return AudioSamples.Read(this, buff); - } - - public ulong Length + public long Length { get { @@ -142,7 +134,7 @@ namespace CUETools.Codecs.FLAKE } } - public ulong Remaining + public long Remaining { get { @@ -150,7 +142,7 @@ namespace CUETools.Codecs.FLAKE } } - public ulong Position + public long Position { get { @@ -197,33 +189,17 @@ namespace CUETools.Codecs.FLAKE _sampleOffset += _samplesInBuffer; }; - uint diff = _samplesInBuffer - (uint)(_sampleOffset - value); + int diff = _samplesInBuffer - (int)(_sampleOffset - value); _samplesInBuffer -= diff; _samplesBufferOffset += diff; } } - public int BitsPerSample + public AudioPCMConfig PCM { get { - return (int)bits_per_sample; - } - } - - public int ChannelCount - { - get - { - return channels; - } - } - - public int SampleRate - { - get - { - return sample_rate; + return pcm; } } @@ -237,14 +213,14 @@ namespace CUETools.Codecs.FLAKE unsafe void interlace(int [,] buff, int offset, int count) { - if (channels == 2) + if (PCM.ChannelCount == 2) { fixed (int* res = &buff[offset, 0], src = &samplesBuffer[_samplesBufferOffset]) AudioSamples.Interlace(res, src, src + Flake.MAX_BLOCKSIZE, count); } else { - for (int ch = 0; ch < channels; ch++) + for (int ch = 0; ch < PCM.ChannelCount; ch++) fixed (int* res = &buff[offset, ch], src = &samplesBuffer[_samplesBufferOffset + ch * Flake.MAX_BLOCKSIZE]) { int* psrc = src; @@ -254,16 +230,19 @@ namespace CUETools.Codecs.FLAKE } } - public uint Read(int[,] buff, uint sampleCount) + public int Read(AudioBuffer buff, int maxLength) { - uint offset = 0; + buff.Prepare(this, maxLength); + + int offset = 0; + int sampleCount = buff.Length; while (_samplesInBuffer < sampleCount) { if (_samplesInBuffer > 0) { - interlace(buff, (int)offset, (int)_samplesInBuffer); - sampleCount -= (uint)_samplesInBuffer; + interlace(buff.Samples, offset, _samplesInBuffer); + sampleCount -= _samplesInBuffer; offset += _samplesInBuffer; _samplesInBuffer = 0; _samplesBufferOffset = 0; @@ -282,12 +261,12 @@ namespace CUETools.Codecs.FLAKE _sampleOffset += _samplesInBuffer; } - interlace(buff, (int)offset, (int)sampleCount); + interlace(buff.Samples, offset, sampleCount); _samplesInBuffer -= sampleCount; _samplesBufferOffset += sampleCount; if (_samplesInBuffer == 0) _samplesBufferOffset = 0; - return (uint)offset + sampleCount; + return offset + sampleCount; } unsafe void fill_frames_buffer() @@ -320,7 +299,7 @@ namespace CUETools.Codecs.FLAKE uint sr_code0 = bitreader.readbits(4); frame.ch_mode = (ChannelMode)bitreader.readbits(4); uint bps_code = bitreader.readbits(3); - if (Flake.flac_bitdepths[bps_code] != bits_per_sample) + if (Flake.flac_bitdepths[bps_code] != PCM.BitsPerSample) throw new Exception("unsupported bps coding"); uint t1 = bitreader.readbit(); // == 0????? if (t1 != 0) @@ -357,7 +336,7 @@ namespace CUETools.Codecs.FLAKE frame_channels = 2; else frame.ch_mode = ChannelMode.NotStereo; - if (frame_channels != channels) + if (frame_channels != PCM.ChannelCount) throw new Exception("invalid channel mode"); // CRC-8 of frame header @@ -369,13 +348,13 @@ namespace CUETools.Codecs.FLAKE unsafe void decode_subframe_constant(BitReader bitreader, FlacFrame frame, int ch) { - int obits = (int)frame.subframes[ch].obits; + int obits = frame.subframes[ch].obits; frame.subframes[ch].best.residual[0] = bitreader.readbits_signed(obits); } unsafe void decode_subframe_verbatim(BitReader bitreader, FlacFrame frame, int ch) { - int obits = (int)frame.subframes[ch].obits; + int obits = frame.subframes[ch].obits; for (int i = 0; i < frame.blocksize; i++) frame.subframes[ch].best.residual[i] = bitreader.readbits_signed(obits); } @@ -421,7 +400,7 @@ namespace CUETools.Codecs.FLAKE unsafe void decode_subframe_fixed(BitReader bitreader, FlacFrame frame, int ch) { // warm-up samples - int obits = (int)frame.subframes[ch].obits; + int obits = frame.subframes[ch].obits; for (int i = 0; i < frame.subframes[ch].best.order; i++) frame.subframes[ch].best.residual[i] = bitreader.readbits_signed(obits); @@ -432,7 +411,7 @@ namespace CUETools.Codecs.FLAKE unsafe void decode_subframe_lpc(BitReader bitreader, FlacFrame frame, int ch) { // warm-up samples - int obits = (int)frame.subframes[ch].obits; + int obits = frame.subframes[ch].obits; for (int i = 0; i < frame.subframes[ch].best.order; i++) frame.subframes[ch].best.residual[i] = bitreader.readbits_signed(obits); @@ -451,23 +430,23 @@ namespace CUETools.Codecs.FLAKE unsafe void decode_subframes(BitReader bitreader, FlacFrame frame) { fixed (int *r = residualBuffer, s = samplesBuffer) - for (int ch = 0; ch < channels; ch++) + for (int ch = 0; ch < PCM.ChannelCount; ch++) { // subframe header uint t1 = bitreader.readbit(); // ?????? == 0 if (t1 != 0) throw new Exception("unsupported subframe coding"); int type_code = (int)bitreader.readbits(6); - frame.subframes[ch].wbits = bitreader.readbit(); + frame.subframes[ch].wbits = (int)bitreader.readbit(); if (frame.subframes[ch].wbits != 0) - frame.subframes[ch].wbits += bitreader.read_unary(); + frame.subframes[ch].wbits += (int)bitreader.read_unary(); - frame.subframes[ch].obits = bits_per_sample - frame.subframes[ch].wbits; + frame.subframes[ch].obits = PCM.BitsPerSample - frame.subframes[ch].wbits; switch (frame.ch_mode) { - case ChannelMode.MidSide: frame.subframes[ch].obits += (uint)ch; break; - case ChannelMode.LeftSide: frame.subframes[ch].obits += (uint)ch; break; - case ChannelMode.RightSide: frame.subframes[ch].obits += 1 - (uint)ch; break; + case ChannelMode.MidSide: frame.subframes[ch].obits += ch; break; + case ChannelMode.LeftSide: frame.subframes[ch].obits += ch; break; + case ChannelMode.RightSide: frame.subframes[ch].obits += 1 - ch; break; } frame.subframes[ch].best.type = (SubframeType)type_code; @@ -562,7 +541,7 @@ namespace CUETools.Codecs.FLAKE { for (int i = sub.best.order; i > 0; i--) csum += (ulong)Math.Abs(coefs[i - 1]); - if ((csum << (int)sub.obits) >= 1UL << 32) + if ((csum << sub.obits) >= 1UL << 32) lpc.decode_residual_long(sub.best.residual, sub.samples, frame.blocksize, sub.best.order, coefs, sub.best.shift); else lpc.decode_residual(sub.best.residual, sub.samples, frame.blocksize, sub.best.order, coefs, sub.best.shift); @@ -571,7 +550,7 @@ namespace CUETools.Codecs.FLAKE unsafe void restore_samples(FlacFrame frame) { - for (int ch = 0; ch < channels; ch++) + for (int ch = 0; ch < PCM.ChannelCount; ch++) { switch (frame.subframes[ch].best.type) { @@ -643,7 +622,7 @@ namespace CUETools.Codecs.FLAKE if (do_crc && crc_1 != crc_2) throw new Exception("frame crc mismatch"); restore_samples(frame); - _samplesInBuffer = (uint)frame.blocksize; + _samplesInBuffer = frame.blocksize; return framereader.Position - pos; } } @@ -743,10 +722,11 @@ namespace CUETools.Codecs.FLAKE max_block_size = bitreader.readbits(FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN); min_frame_size = bitreader.readbits(FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN); max_frame_size = bitreader.readbits(FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN); - sample_rate = (int)bitreader.readbits(FLAC__STREAM_METADATA_STREAMINFO_SAMPLE_RATE_LEN); - channels = 1 + (int)bitreader.readbits(FLAC__STREAM_METADATA_STREAMINFO_CHANNELS_LEN); - bits_per_sample = 1 + bitreader.readbits(FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN); - _sampleCount = bitreader.readbits64(FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN); + int sample_rate = (int)bitreader.readbits(FLAC__STREAM_METADATA_STREAMINFO_SAMPLE_RATE_LEN); + int channels = 1 + (int)bitreader.readbits(FLAC__STREAM_METADATA_STREAMINFO_CHANNELS_LEN); + int bits_per_sample = 1 + (int)bitreader.readbits(FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN); + pcm = new AudioPCMConfig(bits_per_sample, channels, sample_rate); + _sampleCount = (long)bitreader.readbits64(FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN); bitreader.skipbits(FLAC__STREAM_METADATA_STREAMINFO_MD5SUM_LEN); } else if (type == MetadataType.Seektable) @@ -755,9 +735,9 @@ namespace CUETools.Codecs.FLAKE seek_table = new SeekPoint[num_entries]; for (int e = 0; e < num_entries; e++) { - seek_table[e].number = bitreader.readbits64(Flake.FLAC__STREAM_METADATA_SEEKPOINT_SAMPLE_NUMBER_LEN); - seek_table[e].offset = bitreader.readbits64(Flake.FLAC__STREAM_METADATA_SEEKPOINT_STREAM_OFFSET_LEN); - seek_table[e].framesize = bitreader.readbits24(Flake.FLAC__STREAM_METADATA_SEEKPOINT_FRAME_SAMPLES_LEN); + seek_table[e].number = (long)bitreader.readbits64(Flake.FLAC__STREAM_METADATA_SEEKPOINT_SAMPLE_NUMBER_LEN); + seek_table[e].offset = (long)bitreader.readbits64(Flake.FLAC__STREAM_METADATA_SEEKPOINT_STREAM_OFFSET_LEN); + seek_table[e].framesize = (int)bitreader.readbits24(Flake.FLAC__STREAM_METADATA_SEEKPOINT_FRAME_SAMPLES_LEN); } } if (_framesBufferLength < 4 + len) diff --git a/CUETools.Codecs.FLAKE/FlakeWriter.cs b/CUETools.Codecs.FLAKE/FlakeWriter.cs index c497e0a..6e025ff 100644 --- a/CUETools.Codecs.FLAKE/FlakeWriter.cs +++ b/CUETools.Codecs.FLAKE/FlakeWriter.cs @@ -25,7 +25,6 @@ using System; using System.Text; using System.IO; using System.Collections.Generic; -using System.Collections.Specialized; using System.Security.Cryptography; #if INTEROP using System.Runtime.InteropServices; @@ -34,6 +33,7 @@ using CUETools.Codecs; namespace CUETools.Codecs.FLAKE { + [AudioEncoderClass("libFlake", "flac", true, "0 1 2 3 4 5 6 7 8 9 10 11", "7", 2)] public class FlakeWriter : IAudioDest { Stream _IO = null; @@ -47,18 +47,17 @@ namespace CUETools.Codecs.FLAKE // audio sample rate in Hz // set by user prior to calling flake_encode_init - int sample_rate, sr_code0, sr_code1; + int sr_code0, sr_code1; // sample size in bits // set by user prior to calling flake_encode_init // only 16-bit is currently supported - uint bits_per_sample; int bps_code; // total stream samples // set by user prior to calling flake_encode_init // if 0, stream length is unknown - int sample_count; + int sample_count = -1; FlakeEncodeParams eparams; @@ -104,17 +103,18 @@ namespace CUETools.Codecs.FLAKE int seek_table_offset = -1; bool inited = false; + AudioPCMConfig _pcm; - public FlakeWriter(string path, int bitsPerSample, int channelCount, int sampleRate, Stream IO) + public FlakeWriter(string path, Stream IO, AudioPCMConfig pcm) { - if (bitsPerSample != 16) + _pcm = pcm; + + if (_pcm.BitsPerSample != 16) throw new Exception("Bits per sample must be 16."); - if (channelCount != 2) + if (_pcm.ChannelCount != 2) throw new Exception("ChannelCount must be 2."); - channels = channelCount; - sample_rate = sampleRate; - bits_per_sample = (uint) bitsPerSample; + channels = pcm.ChannelCount; // flake_validate_params @@ -134,6 +134,11 @@ namespace CUETools.Codecs.FLAKE frame = new FlacFrame(channels * 2); } + public FlakeWriter(string path, AudioPCMConfig pcm) + : this(path, null, pcm) + { + } + public int TotalSize { get @@ -169,6 +174,15 @@ namespace CUETools.Codecs.FLAKE } } + public string Options + { + set + { + if (value == null || value == "") return; + throw new Exception("Unsupported options " + value); + } + } + #if INTEROP [DllImport("kernel32.dll")] static extern bool GetThreadTimes(IntPtr hThread, out long lpCreationTime, out long lpExitTime, out long lpKernelTime, out long lpUserTime); @@ -188,6 +202,15 @@ namespace CUETools.Codecs.FLAKE if (_IO.CanSeek) { + if (sample_count <= 0 && _position != 0) + { + BitWriter bitwriter = new BitWriter(header, 0, 4); + bitwriter.writebits(32, (int)_position); + bitwriter.flush(); + _IO.Position = 22; + _IO.Write(header, 0, 4); + } + if (md5 != null) { md5.TransformFinalBlock(frame_buffer, 0, 0); @@ -216,7 +239,7 @@ namespace CUETools.Codecs.FLAKE public void Close() { DoClose(); - if (sample_count != 0 && _position != sample_count) + if (sample_count > 0 && _position != sample_count) throw new Exception("Samples written differs from the expected sample count."); } @@ -463,12 +486,12 @@ namespace CUETools.Codecs.FLAKE } } - public int BitsPerSample + public AudioPCMConfig PCM { - get { return 16; } + get { return _pcm; } } - unsafe uint get_wasted_bits(int* signal, int samples) + unsafe int get_wasted_bits(int* signal, int samples) { int i, shift; int x = 0; @@ -492,7 +515,7 @@ namespace CUETools.Codecs.FLAKE signal[i] >>= shift; } - return (uint)shift; + return shift; } /// @@ -506,7 +529,26 @@ namespace CUETools.Codecs.FLAKE fixed (int* fsamples = samplesBuffer, src = &samples[pos, 0]) { if (channels == 2) - AudioSamples.Deinterlace(fsamples + samplesInBuffer, fsamples + Flake.MAX_BLOCKSIZE + samplesInBuffer, src, block); + { + if (eparams.stereo_method == StereoMethod.Independent) + AudioSamples.Deinterlace(fsamples + samplesInBuffer, fsamples + Flake.MAX_BLOCKSIZE + samplesInBuffer, src, block); + else + { + int* left = fsamples + samplesInBuffer; + int* right = left + Flake.MAX_BLOCKSIZE; + int* leftM = right + Flake.MAX_BLOCKSIZE; + int* rightM = leftM + Flake.MAX_BLOCKSIZE; + for (int i = 0; i < block; i++) + { + int l = src[2 * i]; + int r = src[2 * i + 1]; + left[i] = l; + right[i] = r; + leftM[i] = (l + r) >> 1; + rightM[i] = l - r; + } + } + } else for (int ch = 0; ch < channels; ch++) { @@ -780,7 +822,7 @@ namespace CUETools.Codecs.FLAKE for (int i = frame.current.order; i > 0; i--) csum += (ulong)Math.Abs(coefs[i - 1]); - if ((csum << (int)frame.subframes[ch].obits) >= 1UL << 32) + if ((csum << frame.subframes[ch].obits) >= 1UL << 32) lpc.encode_residual_long(frame.current.residual, frame.subframes[ch].samples, frame.blocksize, frame.current.order, coefs, frame.current.shift); else lpc.encode_residual(frame.current.residual, frame.subframes[ch].samples, frame.blocksize, frame.current.order, coefs, frame.current.shift); @@ -806,7 +848,7 @@ namespace CUETools.Codecs.FLAKE // } // } //} - frame.current.size = (uint)frame.current.order * frame.subframes[ch].obits + 4 + 5 + (uint)frame.current.order * cbits + 6 + best_size; + frame.current.size = (uint)(frame.current.order * frame.subframes[ch].obits + 4 + 5 + frame.current.order * (int)cbits + 6 + (int)best_size); frame.ChooseBestSubframe(ch); } } @@ -823,7 +865,7 @@ namespace CUETools.Codecs.FLAKE int pmax = get_max_p_order(eparams.max_partition_order, frame.blocksize, frame.current.order); int pmin = Math.Min(eparams.min_partition_order, pmax); - frame.current.size = (uint)frame.current.order * frame.subframes[ch].obits + 6 + frame.current.size = (uint)(frame.current.order * frame.subframes[ch].obits) + 6 + calc_rice_params(frame.current.rc, pmin, pmax, frame.current.residual, (uint)frame.blocksize, (uint)frame.current.order); frame.subframes[ch].done_fixed |= (1U << order); @@ -846,13 +888,13 @@ namespace CUETools.Codecs.FLAKE { frame.subframes[ch].best.type = SubframeType.Constant; frame.subframes[ch].best.residual[0] = smp[0]; - frame.subframes[ch].best.size = frame.subframes[ch].obits; + frame.subframes[ch].best.size = (uint)frame.subframes[ch].obits; return; } // VERBATIM frame.current.type = SubframeType.Verbatim; - frame.current.size = frame.subframes[ch].obits * (uint)frame.blocksize; + frame.current.size = (uint)(frame.subframes[ch].obits * frame.blocksize); frame.ChooseBestSubframe(ch); if (n < 5 || predict == PredictionType.None) @@ -1313,19 +1355,19 @@ namespace CUETools.Codecs.FLAKE frame.ch_mode = channels != 2 ? ChannelMode.NotStereo : ChannelMode.LeftRight; for (int ch = 0; ch < channels; ch++) frame.subframes[ch].Init(s + ch * Flake.MAX_BLOCKSIZE, r + ch * Flake.MAX_BLOCKSIZE, - bits_per_sample, get_wasted_bits(s + ch * Flake.MAX_BLOCKSIZE, frame.blocksize)); + _pcm.BitsPerSample, get_wasted_bits(s + ch * Flake.MAX_BLOCKSIZE, frame.blocksize)); for (int ch = 0; ch < channels; ch++) encode_residual_pass2(frame, ch); } else { - channel_decorrelation(s, s + Flake.MAX_BLOCKSIZE, s + 2 * Flake.MAX_BLOCKSIZE, s + 3 * Flake.MAX_BLOCKSIZE, frame.blocksize); + //channel_decorrelation(s, s + Flake.MAX_BLOCKSIZE, s + 2 * Flake.MAX_BLOCKSIZE, s + 3 * Flake.MAX_BLOCKSIZE, frame.blocksize); frame.window_buffer = window; frame.current.residual = r + 4 * Flake.MAX_BLOCKSIZE; for (int ch = 0; ch < 4; ch++) - frame.subframes[ch].Init(s + ch * Flake.MAX_BLOCKSIZE, r + ch * Flake.MAX_BLOCKSIZE, - bits_per_sample + (ch == 3 ? 1U : 0U), get_wasted_bits(s + ch * Flake.MAX_BLOCKSIZE, frame.blocksize)); + frame.subframes[ch].Init(s + ch * Flake.MAX_BLOCKSIZE, r + ch * Flake.MAX_BLOCKSIZE, + _pcm.BitsPerSample + (ch == 3 ? 1 : 0), get_wasted_bits(s + ch * Flake.MAX_BLOCKSIZE, frame.blocksize)); //for (int ch = 0; ch < 4; ch++) // for (int iWindow = 0; iWindow < _windowcount; iWindow++) @@ -1416,13 +1458,13 @@ namespace CUETools.Codecs.FLAKE { if (seek_table[sp].framesize != 0) continue; - if (seek_table[sp].number > (ulong)_position + (ulong)bs) + if (seek_table[sp].number > _position + bs) break; - if (seek_table[sp].number >= (ulong)_position) + if (seek_table[sp].number >= _position) { - seek_table[sp].number = (ulong)_position; - seek_table[sp].offset = (ulong)(_IO.Position - first_frame_offset); - seek_table[sp].framesize = (uint)bs; + seek_table[sp].number = _position; + seek_table[sp].offset = _IO.Position - first_frame_offset; + seek_table[sp].framesize = bs; } } } @@ -1434,7 +1476,7 @@ namespace CUETools.Codecs.FLAKE if (verify != null) { int decoded = verify.DecodeFrame(frame_buffer, 0, fs); - if (decoded != fs || verify.Remaining != (ulong)bs) + if (decoded != fs || verify.Remaining != bs) throw new Exception("validation failed!"); fixed (int* s = verifyBuffer, r = verify.Samples) { @@ -1456,7 +1498,7 @@ namespace CUETools.Codecs.FLAKE return bs; } - public void Write(int[,] buff, int pos, int sampleCount) + public void Write(AudioBuffer buff) { if (!inited) { @@ -1469,25 +1511,23 @@ namespace CUETools.Codecs.FLAKE inited = true; } - int len = sampleCount; - while (len > 0) + buff.Prepare(this); + + int pos = 0; + while (pos < buff.Length) { - int block = Math.Min(len, eparams.block_size - samplesInBuffer); + int block = Math.Min(buff.Length - pos, eparams.block_size - samplesInBuffer); - copy_samples(buff, pos, block); + copy_samples(buff.Samples, pos, block); - if (md5 != null) - { - AudioSamples.FLACSamplesToBytes(buff, pos, frame_buffer, 0, block, channels, (int)bits_per_sample); - md5.TransformBlock(frame_buffer, 0, block * channels * ((int)bits_per_sample >> 3), null, 0); - } - - len -= block; pos += block; while (samplesInBuffer >= eparams.block_size) output_frame(); } + + if (md5 != null) + md5.TransformBlock(buff.Bytes, 0, buff.ByteLength, null, 0); } public string Path { get { return _path; } } @@ -1532,9 +1572,9 @@ namespace CUETools.Codecs.FLAKE bitwriter.writebits(16, eparams.block_size); bitwriter.writebits(24, 0); bitwriter.writebits(24, max_frame_size); - bitwriter.writebits(20, sample_rate); + bitwriter.writebits(20, _pcm.SampleRate); bitwriter.writebits(3, channels - 1); - bitwriter.writebits(5, bits_per_sample - 1); + bitwriter.writebits(5, _pcm.BitsPerSample - 1); // total samples if (sample_count > 0) @@ -1589,8 +1629,8 @@ namespace CUETools.Codecs.FLAKE bitwriter.writebits(24, 18 * seek_table.Length); for (int i = 0; i < seek_table.Length; i++) { - bitwriter.writebits64(Flake.FLAC__STREAM_METADATA_SEEKPOINT_SAMPLE_NUMBER_LEN, seek_table[i].number); - bitwriter.writebits64(Flake.FLAC__STREAM_METADATA_SEEKPOINT_STREAM_OFFSET_LEN, seek_table[i].offset); + bitwriter.writebits64(Flake.FLAC__STREAM_METADATA_SEEKPOINT_SAMPLE_NUMBER_LEN, (ulong)seek_table[i].number); + bitwriter.writebits64(Flake.FLAC__STREAM_METADATA_SEEKPOINT_STREAM_OFFSET_LEN, (ulong)seek_table[i].offset); bitwriter.writebits(Flake.FLAC__STREAM_METADATA_SEEKPOINT_FRAME_SAMPLES_LEN, seek_table[i].framesize); } bitwriter.flush(); @@ -1658,7 +1698,7 @@ namespace CUETools.Codecs.FLAKE // find samplerate in table for (i = 4; i < 12; i++) { - if (sample_rate == Flake.flac_samplerates[i]) + if (_pcm.SampleRate == Flake.flac_samplerates[i]) { sr_code0 = i; break; @@ -1671,7 +1711,7 @@ namespace CUETools.Codecs.FLAKE for (i = 1; i < 8; i++) { - if (bits_per_sample == Flake.flac_bitdepths[i]) + if (_pcm.BitsPerSample == Flake.flac_bitdepths[i]) { bps_code = i; break; @@ -1680,13 +1720,13 @@ namespace CUETools.Codecs.FLAKE if (i == 8) throw new Exception("non-standard bps"); // FIXME: For now, only 16-bit encoding is supported - if (bits_per_sample != 16) + if (_pcm.BitsPerSample != 16) throw new Exception("non-standard bps"); if (_blocksize == 0) { if (eparams.block_size == 0) - eparams.block_size = select_blocksize(sample_rate, eparams.block_time_ms); + eparams.block_size = select_blocksize(_pcm.SampleRate, eparams.block_time_ms); _blocksize = eparams.block_size; } else @@ -1694,13 +1734,13 @@ namespace CUETools.Codecs.FLAKE // set maximum encoded frame size (if larger, re-encodes in verbatim mode) if (channels == 2) - max_frame_size = 16 + ((eparams.block_size * (int)(bits_per_sample + bits_per_sample + 1) + 7) >> 3); + max_frame_size = 16 + ((eparams.block_size * (_pcm.BitsPerSample + _pcm.BitsPerSample + 1) + 7) >> 3); else - max_frame_size = 16 + ((eparams.block_size * channels * (int)bits_per_sample + 7) >> 3); + max_frame_size = 16 + ((eparams.block_size * channels * _pcm.BitsPerSample + 7) >> 3); - if (_IO.CanSeek && eparams.do_seektable) + if (_IO.CanSeek && eparams.do_seektable && sample_count > 0) { - int seek_points_distance = sample_rate * 10; + int seek_points_distance = _pcm.SampleRate * 10; int num_seek_points = 1 + sample_count / seek_points_distance; // 1 seek point per 10 seconds if (sample_count % seek_points_distance == 0) num_seek_points--; @@ -1709,7 +1749,7 @@ namespace CUETools.Codecs.FLAKE { seek_table[sp].framesize = 0; seek_table[sp].offset = 0; - seek_table[sp].number = (ulong)(sp * seek_points_distance); + seek_table[sp].number = sp * seek_points_distance; } } @@ -1723,7 +1763,7 @@ namespace CUETools.Codecs.FLAKE if (eparams.do_verify) { - verify = new FlakeReader(channels, bits_per_sample); + verify = new FlakeReader(_pcm); verifyBuffer = new int[Flake.MAX_BLOCKSIZE * channels]; } diff --git a/CUETools.Codecs.LossyWAV/CUETools.Codecs.LossyWAV.csproj b/CUETools.Codecs.LossyWAV/CUETools.Codecs.LossyWAV.csproj index e273d25..fab3417 100644 --- a/CUETools.Codecs.LossyWAV/CUETools.Codecs.LossyWAV.csproj +++ b/CUETools.Codecs.LossyWAV/CUETools.Codecs.LossyWAV.csproj @@ -18,11 +18,12 @@ DEBUG;TRACE prompt 4 + true pdbonly true - ..\bin\Win32\Release\ + ..\bin\any\Release\ TRACE prompt 4 diff --git a/CUETools.Codecs.LossyWAV/LossyWAV.cs b/CUETools.Codecs.LossyWAV/LossyWAV.cs index 24b50aa..a443a6a 100644 --- a/CUETools.Codecs.LossyWAV/LossyWAV.cs +++ b/CUETools.Codecs.LossyWAV/LossyWAV.cs @@ -34,17 +34,15 @@ namespace CUETools.Codecs.LossyWAV public const string version_string = "1.1.1#"; - public LossyWAVWriter(IAudioDest audioDest, IAudioDest lwcdfDest, int bitsPerSample, int channelCount, int sampleRate, double quality) + public LossyWAVWriter(IAudioDest audioDest, IAudioDest lwcdfDest, double quality, AudioPCMConfig pcm) { _audioDest = audioDest; _lwcdfDest = lwcdfDest; - channels = channelCount; - samplerate = sampleRate; - bitspersample = bitsPerSample; + _pcm = pcm; - if (_audioDest != null && _audioDest.BitsPerSample > bitsPerSample) + if (_audioDest != null && _audioDest.PCM.BitsPerSample > _pcm.BitsPerSample) throw new Exception("audio parameters mismatch"); - if (_lwcdfDest != null && _lwcdfDest.BitsPerSample != bitsPerSample) + if (_lwcdfDest != null && _lwcdfDest.PCM.BitsPerSample != _pcm.BitsPerSample) throw new Exception("audio parameters mismatch"); int quality_integer = (int)Math.Floor(quality); @@ -66,6 +64,8 @@ namespace CUETools.Codecs.LossyWAV scaling_factor = 1.0; shaping_factor = Math.Min(1, quality / 10); shaping_is_on = shaping_factor > 0; + + _audioBuffer = new AudioBuffer(_pcm, 256); } public void Close() @@ -74,7 +74,7 @@ namespace CUETools.Codecs.LossyWAV { shift_codec_blocks(); if (samplesInBuffer > 0) - Array.Copy(sampleBuffer, 0, rotating_blocks_ptr[3], 0, samplesInBuffer * channels); + Array.Copy(sampleBuffer, 0, rotating_blocks_ptr[3], 0, samplesInBuffer * _pcm.ChannelCount); next_codec_block_size = samplesInBuffer; process_this_codec_block(); if (next_codec_block_size > 0) @@ -90,17 +90,21 @@ namespace CUETools.Codecs.LossyWAV if (_audioDest != null) _audioDest.Close(); } - public void Write(int[,] buff, int pos, int sampleCount) + public void Write(AudioBuffer buff) { if (!initialized) Initialize(); + buff.Prepare(this); + + int pos = 0; + int sampleCount = buff.Length; while (sampleCount + samplesInBuffer > codec_block_size) { shift_codec_blocks(); // next_codec_block_size is now zero if (samplesInBuffer > 0) - Array.Copy(sampleBuffer, 0, rotating_blocks_ptr[3], 0, samplesInBuffer * channels); - Array.Copy(buff, pos * channels, rotating_blocks_ptr[3], samplesInBuffer * channels, (codec_block_size - samplesInBuffer) * channels); + Array.Copy(sampleBuffer, 0, rotating_blocks_ptr[3], 0, samplesInBuffer * _pcm.ChannelCount); + Array.Copy(buff.Samples, pos * _pcm.ChannelCount, rotating_blocks_ptr[3], samplesInBuffer * _pcm.ChannelCount, (codec_block_size - samplesInBuffer) * _pcm.ChannelCount); next_codec_block_size = codec_block_size; pos += codec_block_size - samplesInBuffer; sampleCount -= codec_block_size - samplesInBuffer; @@ -111,8 +115,8 @@ namespace CUETools.Codecs.LossyWAV } if (sampleCount > 0) { - Array.Copy(buff, pos * channels, sampleBuffer, samplesInBuffer * channels, sampleCount * channels); - samplesInBuffer += (int) sampleCount; + Array.Copy(buff.Samples, pos * _pcm.ChannelCount, sampleBuffer, samplesInBuffer * _pcm.ChannelCount, sampleCount * _pcm.ChannelCount); + samplesInBuffer += sampleCount; } } @@ -138,9 +142,24 @@ namespace CUETools.Codecs.LossyWAV set { } } - public int BitsPerSample + public int CompressionLevel { - get { return bitspersample; } + get { return 0; } + set { } + } + + public string Options + { + set + { + if (value == null || value == "") return; + throw new Exception("Unsupported options " + value); + } + } + + public AudioPCMConfig PCM + { + get { return _pcm; } } public int OverallBitsRemoved @@ -272,7 +291,7 @@ namespace CUETools.Codecs.LossyWAV { 4.876022F,5.668487F,6.605748F,7.589148F,8.584943F,9.583902F,10.583678F,11.583589F,12.583571F,13.583568F,14.583551F,15.583574F,16.583541F,17.583544F,18.583555F,19.583554F,20.583574F,21.583577F,22.583531F,23.583560F,24.583548F,25.583570F,26.583561F,27.583581F,28.583552F,29.583540F,30.583564F,31.583530F,32.583546F,33.583585F,34.583557F,35.583567F} }; - if (samplerate > 46050) + if (_pcm.SampleRate > 46050) { shaping_a = /* order_4_48000_a */ new double[4] { +0.90300, +0.01160, -0.58530, -0.25710 }; shaping_b = /* order_4_48000_b */ new double[4] { -2.23740, +0.73390, +0.12510, +0.60330 }; @@ -289,8 +308,8 @@ namespace CUETools.Codecs.LossyWAV short bits_in_block_size = (short)Math.Floor(fastlog2(codec_block_size)); for (int i = 0; i < precalc_analyses; i++) fft_bit_length[i] += (short)(bits_in_block_size - 9); - if (frequency_limits[spread_freqs] > samplerate / 2) - frequency_limits[spread_freqs] = samplerate / 2; + if (frequency_limits[spread_freqs] > _pcm.SampleRate / 2) + frequency_limits[spread_freqs] = _pcm.SampleRate / 2; fill_fft_lookup_block = new int[maxblocksize * 4]; fill_fft_lookup_offset = new int[maxblocksize * 4]; for (int i = 0; i < codec_block_size * 4; i++) @@ -303,8 +322,8 @@ namespace CUETools.Codecs.LossyWAV for (int j = 0; j < precalc_analyses; j++) saved_fft_results[i, j].start = -1; clipped_samples = 0; - this_max_sample = (1 << (bitspersample - 1)) - 1; - this_min_sample = 0 - (1 << (bitspersample - 1)); + this_max_sample = (1 << (_pcm.BitsPerSample - 1)) - 1; + this_min_sample = 0 - (1 << (_pcm.BitsPerSample - 1)); for (int this_fft_bit_length = 1; this_fft_bit_length <= MaxFFTBitLength; this_fft_bit_length++) { int this_fft_length = 1 << this_fft_bit_length; @@ -321,7 +340,7 @@ namespace CUETools.Codecs.LossyWAV shaping_a[i] *= sf; shaping_b[i] *= sf; } - static_maximum_bits_to_remove = (short)(bitspersample - static_minimum_bits_to_keep); + static_maximum_bits_to_remove = (short)(_pcm.BitsPerSample - static_minimum_bits_to_keep); double lfb = Math.Log10(frequency_limits[0]); // 20Hz lower limit for skewing; double mfb = Math.Log10(frequency_limits[2]); // 3445.3125Hz upper limit for skewing; double dfb = mfb - lfb; // skewing range; @@ -347,8 +366,8 @@ namespace CUETools.Codecs.LossyWAV fft_array = new double[1 << (MaxFFTBitLength + 1)]; fft_result = new double[1 << MaxFFTBitLength]; rotating_blocks_ptr = new int[4][,]; - sampleBuffer = new int[codec_block_size, channels]; - channel_recs = new channel_rec[channels]; + sampleBuffer = new int[codec_block_size, _pcm.ChannelCount]; + channel_recs = new channel_rec[_pcm.ChannelCount]; analysis_recs = new analyzis_rec[precalc_analyses]; for (int analysis_number = 0; analysis_number < precalc_analyses; analysis_number++) @@ -371,7 +390,7 @@ namespace CUETools.Codecs.LossyWAV analysis_recs[analysis_number].fft_underlap_length = total_overlap_length * 1.0 / Math.Max(1, analysis_recs[analysis_number].analysis_blocks); // Calculate actual analysis_time values for fft_lengths - analysis_recs[analysis_number].bin_width = samplerate * 1.0 / (1 << this_fft_bit_length); + analysis_recs[analysis_number].bin_width = _pcm.SampleRate * 1.0 / (1 << this_fft_bit_length); analysis_recs[analysis_number].bin_time = 1.0 / analysis_recs[analysis_number].bin_width; // Calculate which FFT bin corresponds to the low frequency limit @@ -417,9 +436,9 @@ namespace CUETools.Codecs.LossyWAV analysis_recs[analysis_number].threshold_index[last_filled++] = 32; // ?? 31? } // calculating for each analysis_number for (int i = 0; i < 4; i++) - rotating_blocks_ptr[i] = new int[codec_block_size, channels]; - btrd_codec_block = new int[codec_block_size, channels]; - corr_codec_block = new int[codec_block_size, channels]; + rotating_blocks_ptr[i] = new int[codec_block_size, _pcm.ChannelCount]; + btrd_codec_block = new int[codec_block_size, _pcm.ChannelCount]; + corr_codec_block = new int[codec_block_size, _pcm.ChannelCount]; blocks_processed = 0; overall_bits_removed = 0; overall_bits_lost = 0; @@ -483,8 +502,8 @@ namespace CUETools.Codecs.LossyWAV void remove_bits(int channel, short bits_to_remove_from_this_channel) { short min_bits_to_remove = 0; - if (_audioDest != null && _audioDest.BitsPerSample < bitspersample) - min_bits_to_remove = (short) (bitspersample - _audioDest.BitsPerSample); + if (_audioDest != null && _audioDest.PCM.BitsPerSample < _pcm.BitsPerSample) + min_bits_to_remove = (short) (_pcm.BitsPerSample - _audioDest.PCM.BitsPerSample); if (bits_to_remove_from_this_channel < min_bits_to_remove) bits_to_remove_from_this_channel = min_bits_to_remove; @@ -563,18 +582,18 @@ namespace CUETools.Codecs.LossyWAV void process_this_codec_block() { - short codec_block_dependent_bits_to_remove = (short)bitspersample; + short codec_block_dependent_bits_to_remove = (short)_pcm.BitsPerSample; double min_codec_block_channel_rms = channel_recs[0].this_codec_block_rms; - for (int channel = 0; channel < channels; channel++) + for (int channel = 0; channel < _pcm.ChannelCount; channel++) min_codec_block_channel_rms = Math.Min(min_codec_block_channel_rms, channel_recs[channel].this_codec_block_rms); - for (int channel = 0; channel < channels; channel++) + for (int channel = 0; channel < _pcm.ChannelCount; channel++) { // if (linkchannels)... channel_recs[channel].this_codec_block_bits = channel_recs[channel].this_codec_block_rms; } - for (int channel = 0; channel < channels; channel++) + for (int channel = 0; channel < _pcm.ChannelCount; channel++) { fft_results_rec min_fft_result; @@ -665,7 +684,7 @@ namespace CUETools.Codecs.LossyWAV codec_block_dependent_bits_to_remove = Math.Min(codec_block_dependent_bits_to_remove, channel_recs[channel].bits_to_remove); } - for (int channel = 0; channel < channels; channel++) + for (int channel = 0; channel < _pcm.ChannelCount; channel++) { // if (linkchannels) overall_bits_removed += channel_recs[channel].bits_to_remove; @@ -675,16 +694,21 @@ namespace CUETools.Codecs.LossyWAV if (_audioDest != null) { - if (_audioDest.BitsPerSample < bitspersample) + if (_audioDest.PCM.BitsPerSample < _pcm.BitsPerSample) { - int sh = bitspersample - _audioDest.BitsPerSample; + int sh = _pcm.BitsPerSample - _audioDest.PCM.BitsPerSample; for (int i = 0; i < this_codec_block_size; i++) - for (int c = 0; c < channels; c++) + for (int c = 0; c < _pcm.ChannelCount; c++) btrd_codec_block[i, c] >>= sh; } - _audioDest.Write(btrd_codec_block, 0, this_codec_block_size); + _audioBuffer.Prepare(btrd_codec_block, this_codec_block_size); + _audioDest.Write(_audioBuffer); + } + if (_lwcdfDest != null) + { + _audioBuffer.Prepare(corr_codec_block, this_codec_block_size); + _lwcdfDest.Write(_audioBuffer); } - if (_lwcdfDest != null) _lwcdfDest.Write(corr_codec_block, 0, this_codec_block_size); } void shift_codec_blocks() @@ -703,7 +727,7 @@ namespace CUETools.Codecs.LossyWAV if (this_codec_block_size > 0) { blocks_processed++; - for (int channel = 0; channel < channels; channel++) + for (int channel = 0; channel < _pcm.ChannelCount; channel++) { double x = 0; for (int i = 0; i < this_codec_block_size; i++) @@ -798,7 +822,8 @@ namespace CUETools.Codecs.LossyWAV #region Private fields IAudioDest _audioDest, _lwcdfDest; - int channels, samplerate, bitspersample; + AudioPCMConfig _pcm; + private AudioBuffer _audioBuffer; short[] fft_bit_length; float[] frequency_limits; int[] fill_fft_lookup_block; @@ -884,33 +909,28 @@ namespace CUETools.Codecs.LossyWAV if (_audioSource.Length != _lwcdfSource.Length) throw new Exception("Data not same length"); - if (_audioSource.BitsPerSample != _lwcdfSource.BitsPerSample - || _audioSource.ChannelCount != _lwcdfSource.ChannelCount - || _audioSource.SampleRate != _lwcdfSource.SampleRate) + if (_audioSource.PCM.BitsPerSample != _lwcdfSource.PCM.BitsPerSample + || _audioSource.PCM.ChannelCount != _lwcdfSource.PCM.ChannelCount + || _audioSource.PCM.SampleRate != _lwcdfSource.PCM.SampleRate) throw new Exception("FMT Data mismatch"); scaling_factor = 1.0; // !!!! Need to read 'fact' chunks or tags here } - public int[,] Read(int[,] buff) + public int Read(AudioBuffer buff, int maxLength) { - return AudioSamples.Read(this, buff); - } - - public uint Read(int[,] buff, uint sampleCount) - { - if (sampleBuffer == null || sampleBuffer.Length < sampleCount) - sampleBuffer = new int[sampleCount, _audioSource.ChannelCount]; - sampleCount = _audioSource.Read(buff, sampleCount); - if (sampleCount != _lwcdfSource.Read(sampleBuffer, sampleCount)) - throw new Exception("size mismatch"); + if (lwcdfBuffer == null || lwcdfBuffer.Size < buff.Size) + lwcdfBuffer = new AudioBuffer(_lwcdfSource, buff.Size); + int sampleCount = _audioSource.Read(buff, maxLength); + if (sampleCount != _lwcdfSource.Read(lwcdfBuffer, maxLength)) + throw new Exception("size mismatch"); // Very likely to happen (depending on lwcdfSource implementation) for (uint i = 0; i < sampleCount; i++) - for (int c = 0; c < _audioSource.ChannelCount; c++) - buff[i,c] = (int)Math.Round(buff[i, c] / scaling_factor + sampleBuffer[i, c]); + for (int c = 0; c < buff.PCM.ChannelCount; c++) + buff.Samples[i, c] = (int)Math.Round(buff.Samples[i, c] / scaling_factor + lwcdfBuffer.Samples[i, c]); return sampleCount; } - public ulong Length + public long Length { get { @@ -918,7 +938,7 @@ namespace CUETools.Codecs.LossyWAV } } - public ulong Position + public long Position { get { @@ -931,7 +951,7 @@ namespace CUETools.Codecs.LossyWAV } } - public ulong Remaining + public long Remaining { get { @@ -939,27 +959,11 @@ namespace CUETools.Codecs.LossyWAV } } - public int BitsPerSample + public AudioPCMConfig PCM { get { - return _audioSource.BitsPerSample; - } - } - - public int ChannelCount - { - get - { - return _audioSource.ChannelCount; - } - } - - public int SampleRate - { - get - { - return _audioSource.SampleRate; + return _audioSource.PCM; } } @@ -979,8 +983,8 @@ namespace CUETools.Codecs.LossyWAV } IAudioSource _audioSource, _lwcdfSource; + AudioBuffer lwcdfBuffer; double scaling_factor; - int[,] sampleBuffer; } #endregion diff --git a/CUETools.Codecs.TTA/CUETools.Codecs.TTA.cpp b/CUETools.Codecs.TTA/CUETools.Codecs.TTA.cpp index 6f8c430..d7c970f 100644 --- a/CUETools.Codecs.TTA/CUETools.Codecs.TTA.cpp +++ b/CUETools.Codecs.TTA/CUETools.Codecs.TTA.cpp @@ -27,6 +27,7 @@ namespace TTA { "operation canceled" }; + [AudioDecoderClass("ttalib", "tta")] public ref class TTAReader : public IAudioSource { public: @@ -70,9 +71,8 @@ namespace TTA { } if (WAVE_FORMAT_PCM != _ttaReader->ttahdr.AudioFormat) throw gcnew Exception("floating point format not supported."); - _channelCount = _ttaReader->ttahdr.NumChannels; - _bitsPerSample = _ttaReader->ttahdr.BitsPerSample; - _sampleRate = _ttaReader->ttahdr.SampleRate; + + pcm = gcnew AudioPCMConfig((int)_ttaReader->ttahdr.BitsPerSample, (int)_ttaReader->ttahdr.NumChannels, (int)_ttaReader->ttahdr.SampleRate); _sampleCount = _ttaReader->ttahdr.DataLength; } @@ -81,36 +81,24 @@ namespace TTA { Close (); } - virtual property Int32 BitsPerSample { - Int32 get() { - return _bitsPerSample; + virtual property AudioPCMConfig^ PCM { + AudioPCMConfig^ get() { + return pcm; } } - virtual property Int32 ChannelCount { - Int32 get() { - return _channelCount; - } - } - - virtual property Int32 SampleRate { - Int32 get() { - return _sampleRate; - } - } - - virtual property UInt64 Length { - UInt64 get() { + virtual property Int64 Length { + Int64 get() { return _sampleCount; } } - virtual property UInt64 Position { - UInt64 get() + virtual property Int64 Position { + Int64 get() { return _sampleOffset - SamplesInBuffer; } - void set(UInt64 offset) + void set(Int64 offset) { _sampleOffset = offset; _bufferOffset = 0; @@ -125,8 +113,8 @@ namespace TTA { } } - virtual property UInt64 Remaining { - UInt64 get() { + virtual property Int64 Remaining { + Int64 get() { return _sampleCount - _sampleOffset + SamplesInBuffer; } } @@ -144,31 +132,28 @@ namespace TTA { } } - virtual array^ Read(array^ buff) - { - return AudioSamples::Read(this, buff); - } - void processBlock (long * buffer, int sampleCount) { if (_bufferLength > 0) throw gcnew Exception("Received unrequested samples."); if ((_sampleBuffer == nullptr) || (_sampleBuffer->GetLength(0) < sampleCount)) - _sampleBuffer = gcnew array(sampleCount, _channelCount); + _sampleBuffer = gcnew array(sampleCount, pcm->ChannelCount); interior_ptr pMyBuffer = &_sampleBuffer[0, 0]; const long *pTTABuffer = buffer; - const long *pTTABufferEnd = pTTABuffer + sampleCount * _channelCount; + const long *pTTABufferEnd = pTTABuffer + sampleCount * pcm->ChannelCount; while (pTTABuffer < pTTABufferEnd) *(pMyBuffer++) = *(pTTABuffer++); _bufferLength = sampleCount; } - virtual UInt32 Read([Out] array^ buff, UInt32 sampleCount) + virtual int Read(AudioBuffer^ buff, int maxLength) { - UInt32 buffOffset = 0; - UInt32 samplesNeeded = sampleCount; + buff->Prepare(this, maxLength); + + Int32 buffOffset = 0; + Int32 samplesNeeded = buff->Length; while (samplesNeeded != 0) { @@ -193,51 +178,51 @@ namespace TTA { } while (_bufferLength == 0); _sampleOffset += _bufferLength; } - UInt32 copyCount = Math::Min(samplesNeeded, SamplesInBuffer); - Array::Copy(_sampleBuffer, _bufferOffset * _channelCount, buff, buffOffset * _channelCount, copyCount * _channelCount); + Int32 copyCount = Math::Min(samplesNeeded, SamplesInBuffer); + Array::Copy(_sampleBuffer, _bufferOffset * pcm->ChannelCount, buff->Samples, buffOffset * pcm->ChannelCount, copyCount * pcm->ChannelCount); samplesNeeded -= copyCount; buffOffset += copyCount; _bufferOffset += copyCount; } - return sampleCount; + return buff->Length; } private: Int64 _sampleCount, _sampleOffset; - Int32 _bitsPerSample, _channelCount, _sampleRate; + AudioPCMConfig^ pcm; array^ _sampleBuffer; array^ _readBuffer; String^ _path; Stream^ _IO; - UInt32 _bufferOffset, _bufferLength; + Int32 _bufferOffset, _bufferLength; TTALib::TTAReader * _ttaReader; - property UInt32 SamplesInBuffer { - UInt32 get () + property Int32 SamplesInBuffer { + Int32 get () { - return (UInt32) (_bufferLength - _bufferOffset); + return _bufferLength - _bufferOffset; } } }; - public ref class TTAWriter : IAudioDest + [AudioEncoderClass("ttalib", "tta", true, "", "", 1)] + public ref class TTAWriter : public IAudioDest { public: - TTAWriter(String^ path, Int32 bitsPerSample, Int32 channelCount, Int32 sampleRate) + TTAWriter(String^ path, AudioPCMConfig^ pcm) { - if (bitsPerSample < 16 || bitsPerSample > 24) - throw gcnew Exception("Bits per sample must be 16..24."); + _pcm = pcm; - _initialized = false; - _sampleBuffer = nullptr; - _path = path; - _finalSampleCount = 0; - _samplesWritten = 0; - _bitsPerSample = bitsPerSample; - _channelCount = channelCount; - _sampleRate = sampleRate; - _compressionLevel = 5; - _blockSize = 0; + if (_pcm->BitsPerSample < 16 || _pcm->BitsPerSample > 24) + throw gcnew Exception("Bits per sample must be 16..24."); + + _initialized = false; + _sampleBuffer = nullptr; + _path = path; + _finalSampleCount = 0; + _samplesWritten = 0; + _compressionLevel = 5; + _blockSize = 0; } virtual void Close() { @@ -295,9 +280,9 @@ namespace TTA { } } - virtual property int BitsPerSample + virtual property AudioPCMConfig^ PCM { - int get() { return _bitsPerSample; } + AudioPCMConfig^ get() { return _pcm; } } virtual property String^ Path { @@ -306,41 +291,51 @@ namespace TTA { } } - virtual void Write(array^ sampleBuffer, int offset, int sampleCount) { + virtual void Write(AudioBuffer^ sampleBuffer) { if (!_initialized) Initialize(); - if ((_sampleBuffer == nullptr) || (_sampleBuffer->Length < sampleCount * _channelCount)) - _sampleBuffer = gcnew array (sampleCount * _channelCount); + sampleBuffer->Prepare(this); - interior_ptr pSampleBuffer = &sampleBuffer[offset, 0]; + if ((_sampleBuffer == nullptr) || (_sampleBuffer->Length < sampleBuffer->Length * _pcm->ChannelCount)) + _sampleBuffer = gcnew array (sampleBuffer->Length * _pcm->ChannelCount); + + interior_ptr pSampleBuffer = &sampleBuffer->Samples[0, 0]; interior_ptr pTTABuffer = &_sampleBuffer[0]; - for (int i = 0; i < sampleCount * _channelCount; i++) + for (int i = 0; i < sampleBuffer->Length * _pcm->ChannelCount; i++) pTTABuffer[i] = pSampleBuffer[i]; pin_ptr buffer = &_sampleBuffer[0]; try { - _ttaWriter->CompressBlock(buffer, sampleCount); + _ttaWriter->CompressBlock(buffer, sampleBuffer->Length); } catch (TTALib::TTAException ex) { throw gcnew Exception(String::Format("TTA encoder: {0}", gcnew String(TTAErrorsStr[ex.GetErrNo()]))); } - _samplesWritten += sampleCount; + _samplesWritten += sampleBuffer->Length; } - property Int32 CompressionLevel { + virtual property Int32 CompressionLevel { Int32 get() { return _compressionLevel; } void set(Int32 value) { - if ((value < 0) || (value > 8)) { + if (value > 0) throw gcnew Exception("Invalid compression level."); - } _compressionLevel = value; } } + virtual property String^ Options + { + void set(String^ value) + { + if (value == nullptr || value == "") return; + throw gcnew Exception(String::Format("Unsupported options: {0}", value)); + } + } + private: TTALib::TTAWriter* _ttaWriter; FileStream^ _IO; @@ -348,7 +343,7 @@ namespace TTA { bool _initialized; String^ _path; Int64 _finalSampleCount, _samplesWritten, _blockSize; - Int32 _bitsPerSample, _channelCount, _sampleRate; + AudioPCMConfig^ _pcm; Int32 _compressionLevel; void Initialize() @@ -433,7 +428,7 @@ namespace TTA { _IO = gcnew FileStream (_path, FileMode::Create, FileAccess::Write, FileShare::Read); try { - _ttaWriter = new TTALib::TTAWriter((HANDLE)_IO->Handle, 0, WAVE_FORMAT_PCM, _channelCount, _bitsPerSample, _sampleRate, _finalSampleCount); + _ttaWriter = new TTALib::TTAWriter((HANDLE)_IO->Handle, 0, WAVE_FORMAT_PCM, _pcm->ChannelCount, _pcm->BitsPerSample, _pcm->SampleRate, _finalSampleCount); } catch (TTALib::TTAException ex) { throw gcnew Exception(String::Format("TTA encoder: {0}", gcnew String(TTAErrorsStr[ex.GetErrNo()]))); diff --git a/CUETools.Codecs.TTA/CUETools.Codecs.TTA.vcproj b/CUETools.Codecs.TTA/CUETools.Codecs.TTA.vcproj index 3078298..7fd6863 100644 --- a/CUETools.Codecs.TTA/CUETools.Codecs.TTA.vcproj +++ b/CUETools.Codecs.TTA/CUETools.Codecs.TTA.vcproj @@ -20,8 +20,8 @@ @@ -416,10 +417,6 @@ > - - diff --git a/CUETools.Codecs.WavPack/CUETools.Codecs.WavPack.cpp b/CUETools.Codecs.WavPack/CUETools.Codecs.WavPack.cpp index 71a59fa..5943e99 100644 --- a/CUETools.Codecs.WavPack/CUETools.Codecs.WavPack.cpp +++ b/CUETools.Codecs.WavPack/CUETools.Codecs.WavPack.cpp @@ -58,10 +58,21 @@ namespace CUETools { namespace Codecs { namespace WavPack { [UnmanagedFunctionPointer(CallingConvention::Cdecl)] public delegate int DecoderCanSeekDelegate(void *id); + [AudioDecoderClass("libwavpack", "wv")] public ref class WavPackReader : public IAudioSource { public: WavPackReader(String^ path, Stream^ IO, Stream^ IO_WVC) + { + Initialize (path, IO, IO_WVC); + } + + WavPackReader(String^ path, Stream^ IO) + { + Initialize (path, IO, nullptr); + } + + void Initialize(String^ path, Stream^ IO, Stream^ IO_WVC) { char errorMessage[256]; @@ -95,9 +106,10 @@ namespace CUETools { namespace Codecs { namespace WavPack { throw gcnew Exception("Unable to initialize the decoder."); } - _bitsPerSample = WavpackGetBitsPerSample(_wpc); - _channelCount = WavpackGetNumChannels(_wpc); - _sampleRate = WavpackGetSampleRate(_wpc); + pcm = gcnew AudioPCMConfig( + WavpackGetBitsPerSample(_wpc), + WavpackGetNumChannels(_wpc), + (int)WavpackGetSampleRate(_wpc)); _sampleCount = WavpackGetNumSamples(_wpc); _sampleOffset = 0; } @@ -107,35 +119,23 @@ namespace CUETools { namespace Codecs { namespace WavPack { delete ioReader; } - virtual property Int32 BitsPerSample { - Int32 get() { - return _bitsPerSample; + virtual property AudioPCMConfig^ PCM { + AudioPCMConfig^ get() { + return pcm; } } - virtual property Int32 ChannelCount { - Int32 get() { - return _channelCount; - } - } - - virtual property Int32 SampleRate { - Int32 get() { - return _sampleRate; - } - } - - virtual property UInt64 Length { - UInt64 get() { + virtual property Int64 Length { + Int64 get() { return _sampleCount; } } - virtual property UInt64 Position { - UInt64 get() { + virtual property Int64 Position { + Int64 get() { return _sampleOffset; } - void set(UInt64 offset) { + void set(Int64 offset) { _sampleOffset = offset; if (!WavpackSeekSample(_wpc, offset)) { throw gcnew Exception("Unable to seek."); @@ -143,8 +143,8 @@ namespace CUETools { namespace Codecs { namespace WavPack { } } - virtual property UInt64 Remaining { - UInt64 get() { + virtual property Int64 Remaining { + Int64 get() { return _sampleCount - _sampleOffset; } } @@ -171,25 +171,22 @@ namespace CUETools { namespace Codecs { namespace WavPack { } } - virtual array^ Read(array^ buff) + virtual int Read(AudioBuffer^ sampleBuffer, int maxLength) { - return AudioSamples::Read(this, buff); - } + sampleBuffer->Prepare(this, maxLength); - virtual UInt32 Read(array^ sampleBuffer, UInt32 sampleCount) - { - pin_ptr pSampleBuffer = &sampleBuffer[0, 0]; - int samplesRead = WavpackUnpackSamples(_wpc, pSampleBuffer, sampleCount); + pin_ptr pSampleBuffer = &sampleBuffer->Samples[0, 0]; + int samplesRead = WavpackUnpackSamples(_wpc, pSampleBuffer, sampleBuffer->Length); _sampleOffset += samplesRead; - if (samplesRead != sampleCount) + if (samplesRead != sampleBuffer->Length) throw gcnew Exception("Decoder returned a different number of samples than requested."); - return sampleCount; + return sampleBuffer->Length; } private: WavpackContext *_wpc; Int32 _sampleCount, _sampleOffset; - Int32 _bitsPerSample, _channelCount, _sampleRate; + AudioPCMConfig^ pcm; String^ _path; Stream^ _IO; Stream^ _IO_WVC; @@ -293,16 +290,17 @@ namespace CUETools { namespace Codecs { namespace WavPack { } }; + [AudioEncoderClass("libwavpack", "wv", true, "fast normal high high+", "normal", 1)] public ref class WavPackWriter : IAudioDest { public: - WavPackWriter(String^ path, Int32 bitsPerSample, Int32 channelCount, Int32 sampleRate) + WavPackWriter(String^ path, AudioPCMConfig^ pcm) { - IntPtr pathChars; + _pcm = pcm; - if (channelCount != 1 && channelCount != 2) + if (_pcm->ChannelCount != 1 && _pcm->ChannelCount != 2) throw gcnew Exception("Only stereo and mono audio formats are allowed."); - if (bitsPerSample < 16 || bitsPerSample > 24) + if (_pcm->BitsPerSample < 16 || _pcm->BitsPerSample > 24) throw gcnew Exception("Bits per sample must be 16..24."); _path = path; @@ -311,12 +309,7 @@ namespace CUETools { namespace Codecs { namespace WavPack { _extraMode = 0; _blockSize = 0; - _bitsPerSample = bitsPerSample; - _channelCount = channelCount; - _sampleRate = sampleRate; - _blockAlign = _channelCount * ((_bitsPerSample + 7) / 8); - - pathChars = Marshal::StringToHGlobalUni(path); + IntPtr pathChars = Marshal::StringToHGlobalUni(path); _hFile = _wfopen((const wchar_t*)pathChars.ToPointer(), L"w+b"); Marshal::FreeHGlobal(pathChars); if (!_hFile) { @@ -371,42 +364,41 @@ namespace CUETools { namespace Codecs { namespace WavPack { } } - virtual property int BitsPerSample + virtual property AudioPCMConfig^ PCM { - int get() { return _bitsPerSample; } + AudioPCMConfig^ get() { return _pcm; } } - virtual void Write(array^ sampleBuffer, int offset, int sampleCount) + virtual void Write(AudioBuffer^ sampleBuffer) { if (!_initialized) Initialize(); - if (MD5Sum) - { - if (_sampleBuffer == nullptr || _sampleBuffer.Length < sampleCount * _blockAlign) - _sampleBuffer = gcnew array(sampleCount * _blockAlign); - AudioSamples::FLACSamplesToBytes(sampleBuffer, offset, _sampleBuffer, 0, sampleCount, _channelCount, _bitsPerSample); - UpdateHash(_sampleBuffer, sampleCount * _blockAlign); - } + sampleBuffer->Prepare(this); - if ((_bitsPerSample & 7) != 0) + if (MD5Sum) + UpdateHash(sampleBuffer->Bytes, sampleBuffer->ByteLength); + + if ((_pcm->BitsPerSample & 7) != 0) { - if (_shiftedSampleBuffer == nullptr || _shiftedSampleBuffer.GetLength(0) < sampleCount) - _shiftedSampleBuffer = gcnew array(sampleCount, _channelCount); - for (int i = 0; i < sampleCount; i++) - for (int c = 0; c < _channelCount; c++) - _shiftedSampleBuffer[i,c] = sampleBuffer[i+offset,c] << 8 - (_bitsPerSample & 7); + if (_shiftedSampleBuffer == nullptr || _shiftedSampleBuffer.GetLength(0) < sampleBuffer->Length) + _shiftedSampleBuffer = gcnew array(sampleBuffer->Length, _pcm->ChannelCount); + int shift = 8 - (_pcm->BitsPerSample & 7); + int ch = _pcm->ChannelCount; + for (int i = 0; i < sampleBuffer->Length; i++) + for (int c = 0; c < ch; c++) + _shiftedSampleBuffer[i,c] = sampleBuffer->Samples[i,c] << shift; pin_ptr pSampleBuffer = &_shiftedSampleBuffer[0, 0]; - if (!WavpackPackSamples(_wpc, (int32_t*)pSampleBuffer, sampleCount)) + if (!WavpackPackSamples(_wpc, (int32_t*)pSampleBuffer, sampleBuffer->Length)) throw gcnew Exception("An error occurred while encoding."); } else { - pin_ptr pSampleBuffer = &sampleBuffer[offset, 0]; - if (!WavpackPackSamples(_wpc, (int32_t*)pSampleBuffer, sampleCount)) + pin_ptr pSampleBuffer = &sampleBuffer->Samples[0, 0]; + if (!WavpackPackSamples(_wpc, (int32_t*)pSampleBuffer, sampleBuffer->Length)) throw gcnew Exception("An error occurred while encoding."); } - _samplesWritten += sampleCount; + _samplesWritten += sampleBuffer->Length; } virtual property String^ Path @@ -416,11 +408,11 @@ namespace CUETools { namespace Codecs { namespace WavPack { } } - property Int32 CompressionMode { - Int32 get() { + virtual property int CompressionLevel { + int get() { return _compressionMode; } - void set(Int32 value) { + void set(int value) { if ((value < 0) || (value > 3)) { throw gcnew Exception("Invalid compression mode."); } @@ -428,6 +420,29 @@ namespace CUETools { namespace Codecs { namespace WavPack { } } + virtual property String^ Options + { + void set(String^ value) + { + if (value == nullptr || value == "") return; + cli::array^ args = value->Split(); + for (int i = 0; i < args->Length; i++) + { + if (args[i] == "--extra-mode" && (++i) < args->Length) + { + ExtraMode = Int32::Parse(args[i]); + continue; + } + if (args[i] == "--md5") + { + MD5Sum = true; + continue; + } + throw gcnew Exception(String::Format("Unsupported options: {0}", value)); + } + } + } + property Int32 ExtraMode { Int32 get() { return _extraMode; @@ -463,13 +478,12 @@ namespace CUETools { namespace Codecs { namespace WavPack { bool _initialized; WavpackContext *_wpc; Int32 _finalSampleCount, _samplesWritten; - Int32 _bitsPerSample, _channelCount, _sampleRate, _blockAlign; Int32 _compressionMode, _extraMode, _blockSize; String^ _path; bool _md5Sum; MD5^ _md5hasher; - array^ _sampleBuffer; array^ _shiftedSampleBuffer; + AudioPCMConfig^ _pcm; void Initialize() { WavpackConfig config; @@ -480,11 +494,11 @@ namespace CUETools { namespace Codecs { namespace WavPack { } memset(&config, 0, sizeof(WavpackConfig)); - config.bits_per_sample = _bitsPerSample; - config.bytes_per_sample = (_bitsPerSample + 7) / 8; - config.num_channels = _channelCount; - config.channel_mask = 5 - _channelCount; - config.sample_rate = _sampleRate; + config.bits_per_sample = _pcm->BitsPerSample; + config.bytes_per_sample = (_pcm->BitsPerSample + 7) / 8; + config.num_channels = _pcm->ChannelCount; + config.channel_mask = 5 - _pcm->ChannelCount; + config.sample_rate = _pcm->SampleRate; if (_compressionMode == 0) config.flags |= CONFIG_FAST_FLAG; if (_compressionMode == 2) config.flags |= CONFIG_HIGH_FLAG; if (_compressionMode == 3) config.flags |= CONFIG_HIGH_FLAG | CONFIG_VERY_HIGH_FLAG; diff --git a/CUETools.Codecs.WavPack/CUETools.Codecs.WavPack.vcproj b/CUETools.Codecs.WavPack/CUETools.Codecs.WavPack.vcproj index f1a9950..907f7b1 100644 --- a/CUETools.Codecs.WavPack/CUETools.Codecs.WavPack.vcproj +++ b/CUETools.Codecs.WavPack/CUETools.Codecs.WavPack.vcproj @@ -20,7 +20,7 @@ diff --git a/CUETools.Codecs/CRCs/CRC32.cs b/CUETools.Codecs/CRCs/CRC32.cs index 99161f8..7e68443 100644 --- a/CUETools.Codecs/CRCs/CRC32.cs +++ b/CUETools.Codecs/CRCs/CRC32.cs @@ -6,29 +6,36 @@ namespace CUETools.Codecs { public class Crc32 { - uint[] table = new uint[256]; + public uint[] table = new uint[256]; public uint ComputeChecksum(uint crc, byte val) { return (crc >> 8) ^ table[(crc & 0xff) ^ val]; } - public uint ComputeChecksum(uint crc, byte[] bytes, int pos, int count) + public unsafe uint ComputeChecksum(uint crc, byte* bytes, int count) { - for (int i = pos; i < pos + count; i++) - crc = ComputeChecksum(crc, bytes[i]); + fixed (uint *t = table) + for (int i = 0; i < count; i++) + crc = (crc >> 8) ^ t[(crc ^ bytes[i]) & 0xff]; return crc; } + public unsafe uint ComputeChecksum(uint crc, byte[] bytes, int pos, int count) + { + fixed (byte* pbytes = &bytes[pos]) + return ComputeChecksum(crc, pbytes, count); + } + public uint ComputeChecksum(uint crc, uint s) { return ComputeChecksum(ComputeChecksum(ComputeChecksum(ComputeChecksum( crc, (byte)s), (byte)(s >> 8)), (byte)(s >> 16)), (byte)(s >> 24)); } - public unsafe uint ComputeChecksum(uint crc, int * samples, uint count) + public unsafe uint ComputeChecksum(uint crc, int * samples, int count) { - for (uint i = 0; i < count; i++) + for (int i = 0; i < count; i++) { int s1 = samples[2 * i], s2 = samples[2 * i + 1]; crc = ComputeChecksum(ComputeChecksum(ComputeChecksum(ComputeChecksum( @@ -37,9 +44,24 @@ namespace CUETools.Codecs return crc; } - public unsafe uint ComputeChecksumWONULL(uint crc, int* samples, uint count) + public unsafe uint ComputeChecksumWONULL(uint crc, short* samples, int count) { - for (uint i = 0; i < count; i++) + fixed (uint* t = table) + for (int i = 0; i < count; i++) + { + short s1 = samples[i]; + if (s1 != 0) + { + crc = (crc >> 8) ^ t[(crc ^ s1) & 0xff]; + crc = (crc >> 8) ^ t[(crc ^ (s1 >> 8)) & 0xff]; + } + } + return crc; + } + + public unsafe uint ComputeChecksumWONULL(uint crc, int* samples, int count) + { + for (int i = 0; i < count; i++) { int s1 = samples[2 * i], s2 = samples[2 * i + 1]; if (s1 != 0) diff --git a/CUETools.Codecs/CUETools.Codecs.csproj b/CUETools.Codecs/CUETools.Codecs.csproj index be64207..8610bc6 100644 --- a/CUETools.Codecs/CUETools.Codecs.csproj +++ b/CUETools.Codecs/CUETools.Codecs.csproj @@ -23,7 +23,7 @@ pdbonly true - bin\Release\ + ..\bin\any\Release\ TRACE prompt 4 diff --git a/CUETools.Codecs/Codecs.cs b/CUETools.Codecs/Codecs.cs index b3bfd15..68768b3 100644 --- a/CUETools.Codecs/Codecs.cs +++ b/CUETools.Codecs/Codecs.cs @@ -28,31 +28,339 @@ namespace CUETools.Codecs { public interface IAudioSource { - uint Read(int[,] buff, uint sampleCount); - int[,] Read(int[,] buff); - ulong Length { get; } - ulong Position { get; set; } - ulong Remaining { get; } + int Read(AudioBuffer buffer, int maxLength); void Close(); - int BitsPerSample { get; } - int ChannelCount { get; } - int SampleRate { get; } + + AudioPCMConfig PCM { get; } string Path { get; } + + long Length { get; } + long Position { get; set; } + long Remaining { get; } } public interface IAudioDest { - void Write(int[,] buff, int pos, int sampleCount); + void Write(AudioBuffer buffer); void Close(); void Delete(); - int BitsPerSample { get; } + + AudioPCMConfig PCM { get; } + string Path { get; } + + int CompressionLevel { get; set; } + string Options { set; } long FinalSampleCount { set; } long BlockSize { set; } - string Path { get; } } - public class AudioSamples + /// + /// This class provides an attribute for marking + /// classes that provide . + /// + /// + /// When plugins with classes that provide are + /// registered, their attributes are read. + /// + /// + /// using CUETools.Codecs; + /// + ///[AudioEncoderClass("libFLAC", "flac", true, "0 1 2 3 4 5 6 7 8", "5", 1)] + ///public class MyEncoder : IAudioDest { + /// ... + ///} + /// + [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] + public sealed class AudioEncoderClass : Attribute { + private string _encoderName, _extension, _supportedModes, _defaultMode; + bool _lossless; + int _priority; + + public AudioEncoderClass(string encoderName, string extension, bool lossless, string supportedModes, string defaultMode, int priority) + { + _encoderName = encoderName; + _extension = extension; + _supportedModes = supportedModes; + _defaultMode = defaultMode; + _lossless = lossless; + _priority = priority; + } + + public string EncoderName + { + get { return _encoderName; } + } + + public string Extension + { + get { return _extension; } + } + + public string SupportedModes + { + get { return _supportedModes; } + } + + public string DefaultMode + { + get { return _defaultMode; } + } + + public bool Lossless + { + get { return _lossless; } + } + + public int Priority + { + get { return _priority; } + } + } + + /// + /// This class provides an attribute for marking + /// classes that provide . + /// + /// + /// When plugins with classes that provide are + /// registered, their attributes are read. + /// + /// + /// using CUETools.Codecs; + /// + ///[AudioDecoderClass("libFLAC", "flac")] + ///public class MyDecoder : IAudioSource { + /// ... + ///} + /// + [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] + public sealed class AudioDecoderClass : Attribute + { + private string _decoderName, _extension; + + public AudioDecoderClass(string decoderName, string extension) + { + _decoderName = decoderName; + _extension = extension; + } + + public string DecoderName + { + get { return _decoderName; } + } + + public string Extension + { + get { return _extension; } + } + } + + public class AudioPCMConfig + { + private int _bitsPerSample; + private int _channelCount; + private int _sampleRate; + + public AudioPCMConfig(int bitsPerSample, int channelCount, int sampleRate) + { + _bitsPerSample = bitsPerSample; + _channelCount = channelCount; + _sampleRate = sampleRate; + } + + public static readonly AudioPCMConfig RedBook = new AudioPCMConfig(16, 2, 44100); + + public int BitsPerSample { get { return _bitsPerSample; } } + public int ChannelCount { get { return _channelCount; } } + public int SampleRate { get { return _sampleRate; } } + public int BlockAlign { get { return _channelCount * ((_bitsPerSample + 7) / 8); } } + public bool IsRedBook { get { return _bitsPerSample == 16 && _channelCount == 2 && _sampleRate == 44100; } } + } + + public class AudioBuffer + { + private int[,] samples; + private byte[] bytes; + private int length; + private int size; + private AudioPCMConfig pcm; + private bool dataInSamples = false; + private bool dataInBytes = false; + + public int Length + { + get + { + return length; + } + set + { + length = value; + } + } + + public int Size + { + get + { + return size; + } + } + + public AudioPCMConfig PCM { get { return pcm; } } + + public int ByteLength + { + get + { + return length * pcm.BlockAlign; + } + } + + public int[,] Samples + { + get + { + if (samples == null || samples.GetLength(0) < length) + samples = new int[size, pcm.ChannelCount]; + if (!dataInSamples && dataInBytes && length != 0) + BytesToFLACSamples(bytes, 0, samples, 0, length, pcm.ChannelCount, pcm.BitsPerSample); + dataInSamples = true; + return samples; + } + } + + public byte[] Bytes + { + get + { + if (bytes == null || bytes.Length < length * pcm.BlockAlign) + bytes = new byte[size * pcm.BlockAlign]; + if (!dataInBytes && dataInSamples && length != 0) + FLACSamplesToBytes(samples, 0, bytes, 0, length, pcm.ChannelCount, pcm.BitsPerSample); + dataInBytes = true; + return bytes; + } + } + + public AudioBuffer(AudioPCMConfig _pcm, int _size) + { + pcm = _pcm; + size = _size; + } + + public AudioBuffer(AudioPCMConfig _pcm, int[,] _samples, int _length) + { + pcm = _pcm; + // assert _samples.GetLength(1) == pcm.ChannelCount + Prepare(_samples, _length); + } + + public AudioBuffer(AudioPCMConfig _pcm, byte[] _bytes, int _length) + { + pcm = _pcm; + Prepare(_bytes, _length); + } + + public AudioBuffer(IAudioSource source, int _size) + { + pcm = source.PCM; + size = _size; + } + + public void Prepare(IAudioDest dest) + { + if (dest.PCM.ChannelCount != pcm.ChannelCount || dest.PCM.BitsPerSample != pcm.BitsPerSample) + throw new Exception("AudioBuffer format mismatch"); + } + + public void Prepare(IAudioSource source, int maxLength) + { + if (source.PCM.ChannelCount != pcm.ChannelCount || source.PCM.BitsPerSample != pcm.BitsPerSample) + throw new Exception("AudioBuffer format mismatch"); + length = size; + if (maxLength >= 0) + length = Math.Min(length, maxLength); + if (source.Remaining >= 0) + length = (int)Math.Min((long)length, source.Remaining); + dataInBytes = false; + dataInSamples = false; + } + + public void Prepare(int[,] _samples, int _length) + { + length = _length; + size = _samples.GetLength(0); + samples = _samples; + dataInSamples = true; + dataInBytes = false; + } + + public void Prepare(byte[] _bytes, int _length) + { + length = _length; + size = _bytes.Length / PCM.BlockAlign; + bytes = _bytes; + dataInSamples = false; + dataInBytes = true; + } + + public unsafe void Prepare(AudioBuffer _src, int _offset, int _length) + { + length = Math.Min(size, _src.Length - _offset); + if (_length >= 0) + length = Math.Min(length, _length); + dataInBytes = false; + dataInSamples = true; + fixed (int* dest = Samples, src = &_src.Samples[_offset, 0]) + AudioSamples.MemCpy(dest, src, Length * pcm.ChannelCount); + } + + public void Swap(AudioBuffer buffer) + { + if (pcm.BitsPerSample != buffer.PCM.BitsPerSample || pcm.ChannelCount != buffer.PCM.ChannelCount) + throw new Exception("AudioBuffer format mismatch"); + + int[,] samplesTmp = samples; + byte[] bytesTmp = bytes; + + samples = buffer.samples; + bytes = buffer.bytes; + length = buffer.length; + size = buffer.size; + dataInSamples = buffer.dataInSamples; + dataInBytes = buffer.dataInBytes; + + buffer.samples = samplesTmp; + buffer.bytes = bytesTmp; + buffer.length = 0; + buffer.dataInSamples = false; + buffer.dataInBytes = false; + } + + //public void Clear() + //{ + // length = 0; + //} + + public static unsafe void FLACSamplesToBytes_16(int[,] inSamples, int inSampleOffset, + byte* outSamples, int sampleCount, int channelCount) + { + int loopCount = sampleCount * channelCount; + + if (inSamples.GetLength(0) - inSampleOffset < sampleCount) + throw new IndexOutOfRangeException(); + + fixed (int* pInSamplesFixed = &inSamples[inSampleOffset, 0]) + { + int* pInSamples = pInSamplesFixed; + short* pOutSamples = (short*)outSamples; + for (int i = 0; i < loopCount; i++) + pOutSamples[i] = (short)pInSamples[i]; + } + } + public static unsafe void FLACSamplesToBytes_16(int[,] inSamples, int inSampleOffset, byte[] outSamples, int outByteOffset, int sampleCount, int channelCount) { @@ -78,7 +386,7 @@ namespace CUETools.Codecs } } } - + public static unsafe void FLACSamplesToBytes_24(int[,] inSamples, int inSampleOffset, byte[] outSamples, int outByteOffset, int sampleCount, int channelCount, int wastedBits) { @@ -114,17 +422,26 @@ namespace CUETools.Codecs byte[] outSamples, int outByteOffset, int sampleCount, int channelCount, int bitsPerSample) { if (bitsPerSample == 16) - AudioSamples.FLACSamplesToBytes_16(inSamples, inSampleOffset, outSamples, outByteOffset, sampleCount, channelCount); + FLACSamplesToBytes_16(inSamples, inSampleOffset, outSamples, outByteOffset, sampleCount, channelCount); else if (bitsPerSample > 16 && bitsPerSample <= 24) - AudioSamples.FLACSamplesToBytes_24(inSamples, inSampleOffset, outSamples, outByteOffset, sampleCount, channelCount, 24 - bitsPerSample); + FLACSamplesToBytes_24(inSamples, inSampleOffset, outSamples, outByteOffset, sampleCount, channelCount, 24 - bitsPerSample); + else + throw new Exception("Unsupported bitsPerSample value"); + } + + public static unsafe void FLACSamplesToBytes(int[,] inSamples, int inSampleOffset, + byte* outSamples, int sampleCount, int channelCount, int bitsPerSample) + { + if (bitsPerSample == 16) + FLACSamplesToBytes_16(inSamples, inSampleOffset, outSamples, sampleCount, channelCount); else throw new Exception("Unsupported bitsPerSample value"); } public static unsafe void BytesToFLACSamples_16(byte[] inSamples, int inByteOffset, - int[,] outSamples, int outSampleOffset, uint sampleCount, int channelCount) + int[,] outSamples, int outSampleOffset, int sampleCount, int channelCount) { - uint loopCount = sampleCount * (uint)channelCount; + int loopCount = sampleCount * channelCount; if ((inSamples.Length - inByteOffset < loopCount * 2) || (outSamples.GetLength(0) - outSampleOffset < sampleCount)) @@ -148,9 +465,9 @@ namespace CUETools.Codecs } public static unsafe void BytesToFLACSamples_24(byte[] inSamples, int inByteOffset, - int[,] outSamples, int outSampleOffset, uint sampleCount, int channelCount, int wastedBits) + int[,] outSamples, int outSampleOffset, int sampleCount, int channelCount, int wastedBits) { - uint loopCount = sampleCount * (uint)channelCount; + int loopCount = sampleCount * channelCount; if ((inSamples.Length - inByteOffset < loopCount * 3) || (outSamples.GetLength(0) - outSampleOffset < sampleCount)) @@ -174,29 +491,19 @@ namespace CUETools.Codecs } public static unsafe void BytesToFLACSamples(byte[] inSamples, int inByteOffset, - int[,] outSamples, int outSampleOffset, uint sampleCount, int channelCount, int bitsPerSample) + int[,] outSamples, int outSampleOffset, int sampleCount, int channelCount, int bitsPerSample) { if (bitsPerSample == 16) - AudioSamples.BytesToFLACSamples_16(inSamples, inByteOffset, outSamples, outSampleOffset, sampleCount, channelCount); + BytesToFLACSamples_16(inSamples, inByteOffset, outSamples, outSampleOffset, sampleCount, channelCount); else if (bitsPerSample > 16 && bitsPerSample <= 24) - AudioSamples.BytesToFLACSamples_24(inSamples, inByteOffset, outSamples, outSampleOffset, sampleCount, channelCount, 24 - bitsPerSample); + BytesToFLACSamples_24(inSamples, inByteOffset, outSamples, outSampleOffset, sampleCount, channelCount, 24 - bitsPerSample); else throw new Exception("Unsupported bitsPerSample value"); } + } - public static int[,] Read(IAudioSource source, int[,] buff) - { - if (source.Remaining == 0) return null; - uint toRead = Math.Min(65536U, (uint)source.Remaining); - if (buff == null || (ulong)buff.GetLength(0) > source.Remaining) - buff = new int[toRead, source.ChannelCount]; - else - toRead = (uint)buff.GetLength(0); - uint samplesRead = source.Read(buff, toRead); - if (samplesRead != toRead) throw new Exception("samples read != requested"); - return buff; - } - + public class AudioSamples + { unsafe public static void Interlace(int* res, int* src1, int* src2, int n) { for (int i = n; i > 0; i--) @@ -243,6 +550,14 @@ namespace CUETools.Codecs unsafe public static void MemCpy(byte* res, byte* smp, int n) { + if ((((IntPtr)smp).ToInt64() & 4) == 0 && (((IntPtr)res).ToInt64() & 4) == 0 && n > 4) + { + MemCpy((int*)res, (int*)smp, n >> 2); + int n4 = (n >> 2) << 2; + n -= n4; + smp += n4; + res += n4; + } for (int i = n; i > 0; i--) *(res++) = *(smp++); } @@ -258,9 +573,11 @@ namespace CUETools.Codecs public class DummyWriter : IAudioDest { - public DummyWriter(string path, int bitsPerSample, int channelCount, int sampleRate) + AudioPCMConfig _pcm; + + public DummyWriter(string path, AudioPCMConfig pcm) { - _bitsPerSample = bitsPerSample; + _pcm = pcm; } public void Close() @@ -276,36 +593,51 @@ namespace CUETools.Codecs set { } } + public int CompressionLevel + { + get { return 0; } + set { } + } + + public string Options + { + set + { + if (value == null || value == "") return; + throw new Exception("Unsupported options " + value); + } + } + public long BlockSize { set { } } - public int BitsPerSample + public AudioPCMConfig PCM { - get { return _bitsPerSample; } + get { return _pcm; } } - public void Write(int[,] buff, int pos, int sampleCount) + public void Write(AudioBuffer buff) { } public string Path { get { return null; } } - - int _bitsPerSample; } public class SilenceGenerator : IAudioSource { - private ulong _sampleOffset, _sampleCount; + private long _sampleOffset, _sampleCount; + private AudioPCMConfig pcm; - public SilenceGenerator(uint sampleCount) + public SilenceGenerator(long sampleCount) { _sampleOffset = 0; _sampleCount = sampleCount; + pcm = AudioPCMConfig.RedBook; } - public ulong Length + public long Length { get { @@ -313,7 +645,7 @@ namespace CUETools.Codecs } } - public ulong Remaining + public long Remaining { get { @@ -321,7 +653,7 @@ namespace CUETools.Codecs } } - public ulong Position + public long Position { get { @@ -333,55 +665,19 @@ namespace CUETools.Codecs } } - public int BitsPerSample + public AudioPCMConfig PCM { get { return pcm; } } + + public int Read(AudioBuffer buff, int maxLength) { - get - { - return 16; - } - } + buff.Prepare(this, maxLength); - public int ChannelCount - { - get - { - return 2; - } - } + int[,] samples = buff.Samples; + for (int i = 0; i < buff.Length; i++) + for (int j = 0; j < PCM.ChannelCount; j++) + samples[i, j] = 0; - public int SampleRate - { - get - { - return 44100; - } - } - - public uint Read(int [,] buff, uint sampleCount) - { - uint samplesRemaining = (uint)(_sampleCount - _sampleOffset); - if (sampleCount > samplesRemaining) - sampleCount = samplesRemaining; - - for (uint i = 0; i < sampleCount; i++) - for (int j = 0; j < buff.GetLength(1); j++) - buff[i,j] = 0; - - _sampleOffset += sampleCount; - return sampleCount; - } - - public int[,] Read(int[,] buff) - { - if (buff != null && buff.GetLength(0) <= (int)Remaining) - { - _sampleOffset += (ulong) buff.GetLength(0); - Array.Clear(buff, 0, buff.Length); - return buff; - } - ulong samples = Math.Min(Remaining, (ulong)4096); - _sampleCount += samples; - return new int[samples, ChannelCount]; + _sampleOffset += buff.Length; + return buff.Length; } public void Close() @@ -391,16 +687,16 @@ namespace CUETools.Codecs public string Path { get { return null; } } } + [AudioDecoderClass("builtin wav", "wav")] public class WAVReader : IAudioSource { Stream _IO; BinaryReader _br; - ulong _dataOffset, _samplePos, _sampleLen; + long _dataOffset, _samplePos, _sampleLen; + private AudioPCMConfig pcm; long _dataLen; - int _bitsPerSample, _channelCount, _sampleRate, _blockAlign; bool _largeFile; string _path; - private byte[] _sampleBuffer; public WAVReader(string path, Stream IO) { @@ -411,22 +707,41 @@ namespace CUETools.Codecs ParseHeaders(); if (_dataLen < 0) - //_sampleLen = 0; - throw new Exception("WAVE stream length unknown"); + _sampleLen = -1; else - _sampleLen = (ulong)(_dataLen / _blockAlign); + _sampleLen = _dataLen / pcm.BlockAlign; } - public WAVReader(Stream IO) + public WAVReader(string path, Stream IO, AudioPCMConfig _pcm) { - _path = ""; - _IO = IO; + _path = path; + _IO = IO != null ? IO : new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, 0x10000, FileOptions.SequentialScan); _br = new BinaryReader(_IO); - ParseHeaders(); + + _largeFile = false; + _dataOffset = 0; + _samplePos = 0; + pcm = _pcm; + _dataLen = _IO.CanSeek ? _IO.Length : -1; if (_dataLen < 0) - _sampleLen = 0; + _sampleLen = -1; else - _sampleLen = (ulong)(_dataLen / _blockAlign); + { + _sampleLen = _dataLen / pcm.BlockAlign; + if ((_dataLen % pcm.BlockAlign) != 0) + throw new Exception("odd file size"); + } + } + + public static AudioBuffer ReadAllSamples(string path, Stream IO) + { + WAVReader reader = new WAVReader(path, IO); + AudioBuffer buff = new AudioBuffer(reader, (int)reader.Length); + reader.Read(buff, -1); + if (reader.Remaining != 0) + throw new Exception("couldn't read the whole file"); + reader.Close(); + return buff; } public void Close() @@ -487,18 +802,21 @@ namespace CUETools.Codecs { throw new Exception("WAVE must be PCM format."); } - _channelCount = _br.ReadInt16(); - _sampleRate = _br.ReadInt32(); + int _channelCount = _br.ReadInt16(); + int _sampleRate = _br.ReadInt32(); _br.ReadInt32(); - _blockAlign = _br.ReadInt16(); - _bitsPerSample = _br.ReadInt16(); + int _blockAlign = _br.ReadInt16(); + int _bitsPerSample = _br.ReadInt16(); + pcm = new AudioPCMConfig(_bitsPerSample, _channelCount, _sampleRate); + if (pcm.BlockAlign != _blockAlign) + throw new Exception("WAVE has strange BlockAlign"); pos += 16; } else if (ckID == fccData) { foundData = true; - _dataOffset = (ulong)pos; + _dataOffset = pos; if (!_IO.CanSeek || _IO.Length <= maxFileSize) { if (ckSize >= 0x7fffffff) @@ -522,21 +840,19 @@ namespace CUETools.Codecs pos = ckEnd; } while (true); - if ((foundFormat & foundData) == false) + if ((foundFormat & foundData) == false || pcm == null) throw new Exception("Format or data chunk not found."); - if (_channelCount <= 0) + if (pcm.ChannelCount <= 0) throw new Exception("Channel count is invalid."); - if (_sampleRate <= 0) + if (pcm.SampleRate <= 0) throw new Exception("Sample rate is invalid."); - if (_blockAlign != (_channelCount * ((_bitsPerSample + 7) / 8))) - throw new Exception("Block align is invalid."); - if ((_bitsPerSample <= 0) || (_bitsPerSample > 32)) + if ((pcm.BitsPerSample <= 0) || (pcm.BitsPerSample > 32)) throw new Exception("Bits per sample is invalid."); - if (pos != (long)_dataOffset) + if (pos != _dataOffset) Position = 0; } - public ulong Position + public long Position { get { @@ -544,19 +860,19 @@ namespace CUETools.Codecs } set { - ulong seekPos; + long seekPos; - if (_sampleLen != 0 && value > _sampleLen) + if (_sampleLen >= 0 && value > _sampleLen) _samplePos = _sampleLen; else _samplePos = value; - seekPos = _dataOffset + (_samplePos * (uint)_blockAlign); - _IO.Seek((long)seekPos, SeekOrigin.Begin); + seekPos = _dataOffset + _samplePos * PCM.BlockAlign; + _IO.Seek(seekPos, SeekOrigin.Begin); } } - public ulong Length + public long Length { get { @@ -564,7 +880,7 @@ namespace CUETools.Codecs } } - public ulong Remaining + public long Remaining { get { @@ -572,102 +888,64 @@ namespace CUETools.Codecs } } - public int ChannelCount - { - get - { - return _channelCount; - } - } + public AudioPCMConfig PCM { get { return pcm; } } - public int SampleRate + public int Read(AudioBuffer buff, int maxLength) { - get - { - return _sampleRate; - } - } + buff.Prepare(this, maxLength); - public int BitsPerSample - { - get - { - return _bitsPerSample; - } - } - - public int BlockAlign - { - get - { - return _blockAlign; - } - } - - public uint Read(int[,] buff, uint sampleCount) - { - if (_sampleLen > 0 && sampleCount > Remaining) - sampleCount = (uint)Remaining; - - if (sampleCount == 0) - return 0; - int byteCount = (int) sampleCount * _blockAlign; - if (_sampleBuffer == null || _sampleBuffer.Length < byteCount) - _sampleBuffer = new byte[byteCount]; + byte[] bytes = buff.Bytes; + int byteCount = (int)buff.ByteLength; int pos = 0; - do + + while (pos < byteCount) { - int len = _IO.Read(_sampleBuffer, pos, (int)byteCount - pos); + int len = _IO.Read(bytes, pos, byteCount - pos); if (len <= 0) { - if ((pos % BlockAlign) != 0 || _sampleLen > 0) + if ((pos % PCM.BlockAlign) != 0 || _sampleLen >= 0) throw new Exception("Incomplete file read."); - sampleCount = (uint)(pos / BlockAlign); - _sampleLen = _samplePos + sampleCount; - break; + buff.Length = pos / PCM.BlockAlign; + _samplePos += buff.Length; + _sampleLen = _samplePos; + return buff.Length; } pos += len; - } while (pos < byteCount); - AudioSamples.BytesToFLACSamples(_sampleBuffer, 0, buff, 0, - sampleCount, _channelCount, _bitsPerSample); - _samplePos += sampleCount; - return sampleCount; - } - - public int[,] Read(int[,] buff) - { - return AudioSamples.Read(this, buff); + } + _samplePos += buff.Length; + return buff.Length; } public string Path { get { return _path; } } } + [AudioEncoderClass("builtin wav", "wav", true, "", "", 10)] public class WAVWriter : IAudioDest { Stream _IO; BinaryWriter _bw; - int _bitsPerSample, _channelCount, _sampleRate, _blockAlign; + AudioPCMConfig _pcm; long _sampleLen; string _path; - private byte[] _sampleBuffer; long hdrLen = 0; bool _headersWritten = false; - long _finalSampleCount; + long _finalSampleCount = -1; List _chunks = null; List _chunkFCCs = null; - public WAVWriter(string path, int bitsPerSample, int channelCount, int sampleRate, Stream IO) + public WAVWriter(string path, Stream IO, AudioPCMConfig pcm) { + _pcm = pcm; _path = path; - _bitsPerSample = bitsPerSample; - _channelCount = channelCount; - _sampleRate = sampleRate; - _blockAlign = _channelCount * ((_bitsPerSample + 7) / 8); - _IO = IO != null ? IO : new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read); _bw = new BinaryWriter(_IO); } + public WAVWriter(string path, AudioPCMConfig pcm) + : this(path, null, pcm) + { + } + public void WriteChunk(uint fcc, byte[] data) { if (_sampleLen > 0) @@ -689,11 +967,11 @@ namespace CUETools.Codecs const uint fccFormat = 0x20746D66; const uint fccData = 0x61746164; - bool wavex = _bitsPerSample != 16 && _bitsPerSample != 24; + bool wavex = _pcm.BitsPerSample != 16 && _pcm.BitsPerSample != 24; hdrLen += 36 + (wavex ? 24 : 0) + 8; - uint dataLen = (uint) (_finalSampleCount * _blockAlign); + uint dataLen = (uint)(_finalSampleCount * _pcm.BlockAlign); uint dataLenPadded = dataLen + (dataLen & 1); _bw.Write(fccRIFF); @@ -710,15 +988,15 @@ namespace CUETools.Codecs _bw.Write((uint)16); _bw.Write((ushort)1); // PCM } - _bw.Write((ushort)_channelCount); - _bw.Write((uint)_sampleRate); - _bw.Write((uint)(_sampleRate * _blockAlign)); - _bw.Write((ushort)_blockAlign); - _bw.Write((ushort)((_bitsPerSample+7)/8*8)); + _bw.Write((ushort)_pcm.ChannelCount); + _bw.Write((uint)_pcm.SampleRate); + _bw.Write((uint)(_pcm.SampleRate * _pcm.BlockAlign)); + _bw.Write((ushort)_pcm.BlockAlign); + _bw.Write((ushort)((_pcm.BitsPerSample+7)/8*8)); if (wavex) { _bw.Write((ushort)22); // length of WAVEX structure - _bw.Write((ushort)_bitsPerSample); + _bw.Write((ushort)_pcm.BitsPerSample); _bw.Write((uint)3); // speaker positions (3 == stereo) _bw.Write((ushort)1); // PCM _bw.Write((ushort)0); @@ -751,14 +1029,14 @@ namespace CUETools.Codecs public void Close() { - if (_finalSampleCount == 0) + if (_finalSampleCount <= 0) { const long maxFileSize = 0x7FFFFFFEL; - long dataLen = _sampleLen * _blockAlign; + long dataLen = _sampleLen * _pcm.BlockAlign; if ((dataLen & 1) == 1) _bw.Write((byte)0); if (dataLen + hdrLen > maxFileSize) - dataLen = ((maxFileSize - hdrLen) / _blockAlign) * _blockAlign; + dataLen = ((maxFileSize - hdrLen) / _pcm.BlockAlign) * _pcm.BlockAlign; long dataLenPadded = dataLen + (dataLen & 1); _bw.Seek(4, SeekOrigin.Begin); @@ -773,7 +1051,7 @@ namespace CUETools.Codecs _bw = null; _IO = null; - if (_finalSampleCount != 0 && _sampleLen != _finalSampleCount) + if (_finalSampleCount > 0 && _sampleLen != _finalSampleCount) throw new Exception("Samples written differs from the expected sample count."); } @@ -803,23 +1081,35 @@ namespace CUETools.Codecs set { } } - public int BitsPerSample + public int CompressionLevel { - get { return _bitsPerSample; } + get { return 0; } + set { } } - public void Write(int[,] buff, int pos, int sampleCount) + public string Options { - if (sampleCount == 0) + set + { + if (value == null || value == "") return; + throw new Exception("Unsupported options " + value); + } + } + + public AudioPCMConfig PCM + { + get { return _pcm; } + } + + public void Write(AudioBuffer buff) + { + if (buff.Length == 0) return; + buff.Prepare(this); if (!_headersWritten) WriteHeaders(); - if (_sampleBuffer == null || _sampleBuffer.Length < sampleCount * _blockAlign) - _sampleBuffer = new byte[sampleCount * _blockAlign]; - AudioSamples.FLACSamplesToBytes(buff, pos, _sampleBuffer, 0, - sampleCount, _channelCount, _bitsPerSample); - _IO.Write(_sampleBuffer, 0, (int)sampleCount * _blockAlign); - _sampleLen += sampleCount; + _IO.Write(buff.Bytes, 0, buff.ByteLength); + _sampleLen += buff.Length; } public string Path { get { return _path; } } @@ -836,6 +1126,7 @@ namespace CUETools.Codecs private int _end = 0; // moved only by Read private bool _eof = false; private Thread _readThread = null, _writeThread = null; + private Exception _ex = null; public event FlushOutput flushOutput; public event CloseOutput closeOutput; @@ -941,8 +1232,10 @@ namespace CUETools.Codecs int pos, chunk; lock (this) { - while (FreeSpace == 0) + while (FreeSpace == 0 && _ex == null) Monitor.Wait(this); + if (_ex != null) + throw _ex; pos = _end % _size; chunk = Math.Min(FreeSpace, _size - pos); } @@ -964,8 +1257,10 @@ namespace CUETools.Codecs { lock (this) { - while (FreeSpace == 0) + while (FreeSpace == 0 && _ex == null) Monitor.Wait(this); + if (_ex != null) + throw _ex; pos = _end % _size; chunk = Math.Min(FreeSpace, _size - pos); chunk = Math.Min(chunk, count); @@ -996,7 +1291,19 @@ namespace CUETools.Codecs chunk = Math.Min(DataAvailable, _size - pos); } if (flushOutput != null) - flushOutput(_buffer, pos, chunk, to); + try + { + flushOutput(_buffer, pos, chunk, to); + } + catch (Exception ex) + { + lock (this) + { + _ex = ex; + Monitor.Pulse(this); + return; + } + } lock (this) { _start += chunk; @@ -1090,7 +1397,7 @@ namespace CUETools.Codecs WAVWriter wrt; CyclicBuffer outputBuffer = null; - public UserDefinedWriter(string path, int bitsPerSample, int channelCount, int sampleRate, Stream IO, string encoder, string encoderParams, string encoderMode, int padding) + public UserDefinedWriter(string path, Stream IO, AudioPCMConfig pcm, string encoder, string encoderParams, string encoderMode, int padding) { _path = path; _encoder = encoder; @@ -1125,7 +1432,7 @@ namespace CUETools.Codecs outputBuffer = new CyclicBuffer(2 * 1024 * 1024, _encoderProcess.StandardOutput.BaseStream, outputStream); } Stream inputStream = new CycilcBufferOutputStream(_encoderProcess.StandardInput.BaseStream, 128 * 1024); - wrt = new WAVWriter(path, bitsPerSample, channelCount, sampleRate, inputStream); + wrt = new WAVWriter(path, inputStream, pcm); } public void Close() @@ -1163,14 +1470,39 @@ namespace CUETools.Codecs set { } } - public int BitsPerSample + public int CompressionLevel { - get { return wrt.BitsPerSample; } + get { return 0; } + set { } // !!!! Must not start the process in constructor, so that we can set CompressionLevel! } - public void Write(int[,] buff, int pos, int sampleCount) + public string Options { - wrt.Write(buff, pos, sampleCount); + set + { + if (value == null || value == "") return; + throw new Exception("Unsupported options " + value); + } + } + + public AudioPCMConfig PCM + { + get { return wrt.PCM; } + } + + public void Write(AudioBuffer buff) + { + try + { + wrt.Write(buff); + } + catch (IOException ex) + { + if (_encoderProcess.HasExited) + throw new IOException(string.Format("{0} has exited prematurely with code {1}", _encoder, _encoderProcess.ExitCode), ex); + else + throw ex; + } //_sampleLen += sampleCount; } @@ -1180,6 +1512,7 @@ namespace CUETools.Codecs public class UserDefinedReader : IAudioSource { string _path, _decoder, _decoderParams; + private AudioPCMConfig pcm; Process _decoderProcess; WAVReader rdr; @@ -1228,7 +1561,7 @@ namespace CUETools.Codecs catch { } } - public ulong Position + public long Position { get { @@ -1242,7 +1575,7 @@ namespace CUETools.Codecs } } - public ulong Length + public long Length { get { @@ -1251,7 +1584,7 @@ namespace CUETools.Codecs } } - public ulong Remaining + public long Remaining { get { @@ -1260,51 +1593,19 @@ namespace CUETools.Codecs } } - public int ChannelCount + public AudioPCMConfig PCM { get { Initialize(); - return rdr.ChannelCount; + return pcm; } } - public int SampleRate - { - get - { - Initialize(); - return rdr.SampleRate; - } - } - - public int BitsPerSample - { - get - { - Initialize(); - return rdr.BitsPerSample; - } - } - - public int BlockAlign - { - get - { - Initialize(); - return rdr.BlockAlign; - } - } - - public uint Read(int[,] buff, uint sampleCount) + public int Read(AudioBuffer buff, int maxLength) { Initialize(); - return rdr.Read(buff, sampleCount); - } - - public int[,] Read(int[,] buff) - { - return AudioSamples.Read(this, buff); + return rdr.Read(buff, maxLength); } public string Path { get { return _path; } } @@ -1312,52 +1613,54 @@ namespace CUETools.Codecs public class AudioPipe : IAudioSource//, IDisposable { - private readonly Queue _buffer = new Queue(); - int _bitsPerSample, _channelCount, _sampleRate, _bufferPos; - ulong _sampleLen, _samplePos; + private AudioBuffer _readBuffer, _writeBuffer; + long _sampleLen, _samplePos; private int _maxLength; private Thread _workThread; IAudioSource _source; bool _close = false; + bool _haveData = false; + int _bufferPos = 0; Exception _ex = null; - public AudioPipe(IAudioSource source, int maxLength) + public AudioPipe(IAudioSource source, int size) { _source = source; - _maxLength = maxLength; - _bitsPerSample = _source.BitsPerSample; - _channelCount = _source.ChannelCount; - _sampleRate = _source.SampleRate; + _readBuffer = new AudioBuffer(source, size); + _writeBuffer = new AudioBuffer(source, size); + _maxLength = size; _sampleLen = _source.Length; - _samplePos = 0; - _bufferPos = 0; + _samplePos = _source.Position; } private void Decompress(object o) { - // catch try { + bool done = false; do { - //int[,] buff = new int[65536, 2]; - //uint toRead = Math.Min((uint)buff.GetLength(0), (uint)_source.Remaining); - //uint samplesRead = _source.Read(buff, toRead); - int[,] buff = _source.Read(null); - if (buff == null) break; - //uint samplesRead = buff.GetLength(0); - //if (samplesRead == 0) break; - //if (samplesRead != toRead) - // throw new Exception("samples read != samples requested"); - Write(buff); - } while (true); + done = _source.Read(_writeBuffer, -1) == 0; + lock (this) + { + while (_haveData && !_close) + Monitor.Wait(this); + if (_close) + throw new Exception("Decompression aborted"); + AudioBuffer temp = _writeBuffer; + _writeBuffer = _readBuffer; + _readBuffer = temp; + _haveData = true; + Monitor.Pulse(this); + } + } while (!done); } catch (Exception ex) { - lock (_buffer) + lock (this) { _ex = ex; - Monitor.Pulse(_buffer); + Monitor.Pulse(this); } } } @@ -1378,20 +1681,29 @@ namespace CUETools.Codecs public void Close() { - lock (_buffer) + lock (this) { _close = true; - Monitor.Pulse(_buffer); + Monitor.Pulse(this); } if (_workThread != null) { _workThread.Join(); _workThread = null; } - _buffer.Clear(); + if (_readBuffer != null) + { + //_readBuffer.Clear(); + _readBuffer = null; + } + if (_writeBuffer != null) + { + //_writeBuffer.Clear(); + _writeBuffer = null; + } } - public ulong Position + public long Position { get { @@ -1403,7 +1715,7 @@ namespace CUETools.Codecs } } - public ulong Length + public long Length { get { @@ -1411,7 +1723,7 @@ namespace CUETools.Codecs } } - public ulong Remaining + public long Remaining { get { @@ -1419,275 +1731,58 @@ namespace CUETools.Codecs } } - public int ChannelCount + public AudioPCMConfig PCM { get { - return _channelCount; + return _source.PCM; } } - public int SampleRate - { - get - { - return _sampleRate; - } - } - - public int BitsPerSample - { - get - { - return _bitsPerSample; - } - } - - - public int[,] Read(int[,] buff) + public int Read(AudioBuffer buff, int maxLength) { Go(); - if (Remaining == 0) - return null; + + bool needToCopy = false; if (_bufferPos != 0) - throw new Exception("Mixed Read usage not yet suppoted"); - lock (_buffer) - { - while (_buffer.Count == 0 && _ex == null) - Monitor.Wait(_buffer); - if (_ex != null) - throw _ex; - buff = _buffer.Dequeue(); - Monitor.Pulse(_buffer); - } - return buff; - } - - public uint Read(int[,] buff, uint sampleCount) - { - Go(); - if (sampleCount > Remaining) - sampleCount = (uint)Remaining; - int pos = 0; - while (sampleCount > 0) - { - lock (_buffer) + needToCopy = true; + else + lock (this) { - while (_buffer.Count == 0 && _ex == null) - Monitor.Wait(_buffer); + while (!_haveData && _ex == null) + Monitor.Wait(this); if (_ex != null) throw _ex; - int[,] chunk = _buffer.Peek(); - int copyCount = Math.Min((int)sampleCount, chunk.GetLength(0) - _bufferPos); - Array.Copy(chunk, _bufferPos * _channelCount, buff, pos * _channelCount, copyCount * _channelCount); - pos += copyCount; - sampleCount -= (uint) copyCount; - _samplePos += (ulong) copyCount; - _bufferPos += copyCount; - if (_bufferPos == chunk.GetLength(0)) + if (_bufferPos == 0 && (maxLength < 0 || _readBuffer.Length <= maxLength)) { - _buffer.Dequeue(); // .Finalize? - _bufferPos = 0; - Monitor.Pulse(_buffer); + buff.Swap(_readBuffer); + _haveData = false; + Monitor.Pulse(this); + } + else + needToCopy = true; + } + if (needToCopy) + { + buff.Prepare(_readBuffer, _bufferPos, maxLength); + _bufferPos += buff.Length; + if (_bufferPos == _readBuffer.Length) + { + _bufferPos = 0; + lock (this) + { + _haveData = false; + Monitor.Pulse(this); } } } - return (uint) pos; - } - - public void Write(int[,] buff) - { - lock (_buffer) - { - while (_buffer.Count >= _maxLength && !_close) - Monitor.Wait(_buffer); - if (_close) - throw new Exception("Decompression aborted"); - //_flushed = false; - _buffer.Enqueue(buff); - Monitor.Pulse(_buffer); - } + _samplePos += buff.Length; + return buff.Length; } public string Path { get { return _source.Path; } } } - public class BufferedWriter: IAudioDest - { - IAudioDest _writer; - Thread _flushThread = null; - private int[,] _buffer; - private int _size; - private int _channels = 2; - private int _start = 0; // moved only by Write - private int _end = 0; // moved only by Read - private bool _eof = false, _delete = false; - Exception exceptionOnFlush = null; - - public long FinalSampleCount - { - //get { return _writer.FinalSampleCount; } - set { _writer.FinalSampleCount = value; } - } - - public long BlockSize - { - set { _writer.BlockSize = value; } - } - - public int BitsPerSample - { - get { return _writer.BitsPerSample; } - } - - public int Channels - { - get { return _channels; } // !!!! writer.Channels - } - - // public bool ReadSource(IAudioSource input) - - public unsafe void Write(int[,] samples, int offset, int count) - { - int pos, chunk; - while (count > 0) - { - lock (this) - { - while (FreeSpace == 0 && exceptionOnFlush == null) - Monitor.Wait(this); - if (exceptionOnFlush != null) - { - Exception ex = exceptionOnFlush; - exceptionOnFlush = null; - throw ex; - } - pos = _end % _size; - chunk = Math.Min(FreeSpace, _size - pos); - chunk = Math.Min(chunk, count); - } - fixed (int* src = &samples[offset, 0], dst = &_buffer[pos, 0]) - AudioSamples.MemCpy(dst, src, chunk * Channels); - //Array.Copy(samples, offset * Channels, _buffer, pos * Channels, chunk * Channels); - lock (this) - { - _end += chunk; - Monitor.Pulse(this); - } - count -= chunk; - offset += chunk; - } - } - - public string Path { get { return _writer.Path; } } - - public BufferedWriter(IAudioDest writer, int size) - { - _writer = writer; - _size = size; - _buffer = new int[_size, Channels]; - _flushThread = new Thread(Flush); - //_writeThread.Priority = ThreadPriority.Normal; - _flushThread.IsBackground = true; - _flushThread.Start(_writer); - } - - int DataAvailable - { - get - { - return _end - _start; - } - } - - int FreeSpace - { - get - { - return _size - DataAvailable; - } - } - - public void Delete() - { - SetEOF(true); - if (_flushThread != null) - { - _flushThread.Join(); - _flushThread = null; - } - } - - public void Close() - { - SetEOF(false); - if (_flushThread != null) - { - _flushThread.Join(); - _flushThread = null; - } - if (exceptionOnFlush != null) - { - Exception ex = exceptionOnFlush; - exceptionOnFlush = null; - throw ex; - } - } - - public void SetEOF(bool delete) - { - lock (this) - { - _eof = true; - _delete = delete; - Monitor.Pulse(this); - } - } - - public void Flush(object o) - { - IAudioDest dest = (IAudioDest)o; - try - { - do - { - int pos, chunk; - lock (this) - { - while (DataAvailable == 0 && !_eof) - Monitor.Wait(this); - if (DataAvailable == 0) - { - if (_delete) - dest.Delete(); - else - dest.Close(); - return; - } - pos = _start % _size; - chunk = Math.Min(DataAvailable, _size - pos); - } - dest.Write(_buffer, pos, chunk); - lock (this) - { - _start += chunk; - Monitor.Pulse(this); - } - } - while (true); - } - catch (Exception ex) - { - lock (this) - { - exceptionOnFlush = ex; - Monitor.Pulse(this); - dest.Delete(); - } - } - } - } - public class NullStream : Stream { public NullStream() diff --git a/CUETools.Converter/CUETools.Converter.csproj b/CUETools.Converter/CUETools.Converter.csproj index ffe0a1e..d784726 100644 --- a/CUETools.Converter/CUETools.Converter.csproj +++ b/CUETools.Converter/CUETools.Converter.csproj @@ -22,7 +22,7 @@ pdbonly true - ..\bin\win32\Release\ + ..\bin\any\Release\ TRACE prompt 4 diff --git a/CUETools.Converter/Program.cs b/CUETools.Converter/Program.cs index e688de6..b36dc49 100644 --- a/CUETools.Converter/Program.cs +++ b/CUETools.Converter/Program.cs @@ -45,34 +45,32 @@ namespace CUETools.Converter #endif { IAudioSource audioSource = AudioReadWrite.GetAudioSource(sourceFile, null, config); - IAudioDest audioDest = AudioReadWrite.GetAudioDest(AudioEncoderType.Lossless, destFile, (long)audioSource.Length, audioSource.BitsPerSample, audioSource.SampleRate, 8192, config); - int[,] buff = new int[0x4000, audioSource.ChannelCount]; + IAudioDest audioDest = AudioReadWrite.GetAudioDest(AudioEncoderType.Lossless, destFile, (long)audioSource.Length, audioSource.PCM.BitsPerSample, audioSource.PCM.SampleRate, 8192, config); + AudioBuffer buff = new AudioBuffer(audioSource, 0x10000); Console.WriteLine("Filename : {0}", sourceFile); - Console.WriteLine("File Info : {0}kHz; {1} channel; {2} bit; {3}", audioSource.SampleRate, audioSource.ChannelCount, audioSource.BitsPerSample, TimeSpan.FromSeconds(audioSource.Length * 1.0 / audioSource.SampleRate)); + Console.WriteLine("File Info : {0}kHz; {1} channel; {2} bit; {3}", audioSource.PCM.SampleRate, audioSource.PCM.ChannelCount, audioSource.PCM.BitsPerSample, TimeSpan.FromSeconds(audioSource.Length * 1.0 / audioSource.PCM.SampleRate)); - do + while (audioSource.Read(buff, -1) != 0) { - uint samplesRead = audioSource.Read(buff, Math.Min((uint)buff.GetLength(0), (uint)audioSource.Remaining)); - if (samplesRead == 0) break; - audioDest.Write(buff, 0, (int)samplesRead); + audioDest.Write(buff); TimeSpan elapsed = DateTime.Now - start; if ((elapsed - lastPrint).TotalMilliseconds > 60) { Console.Error.Write("\rProgress : {0:00}%; {1:0.00}x; {2}/{3}", 100.0 * audioSource.Position / audioSource.Length, - audioSource.Position / elapsed.TotalSeconds / audioSource.SampleRate, + audioSource.Position / elapsed.TotalSeconds / audioSource.PCM.SampleRate, elapsed, TimeSpan.FromMilliseconds(elapsed.TotalMilliseconds / audioSource.Position * audioSource.Length) ); lastPrint = elapsed; } - } while (true); + } TimeSpan totalElapsed = DateTime.Now - start; Console.Error.Write("\r \r"); Console.WriteLine("Results : {0:0.00}x; {1}", - audioSource.Position / totalElapsed.TotalSeconds / audioSource.SampleRate, + audioSource.Position / totalElapsed.TotalSeconds / audioSource.PCM.SampleRate, totalElapsed ); audioSource.Close(); diff --git a/CUETools.FlaCuda/CUETools.Codecs.FlaCuda.csproj b/CUETools.FlaCuda/CUETools.Codecs.FlaCuda.csproj index c5ddfde..1dbe623 100644 --- a/CUETools.FlaCuda/CUETools.Codecs.FlaCuda.csproj +++ b/CUETools.FlaCuda/CUETools.Codecs.FlaCuda.csproj @@ -23,7 +23,7 @@ pdbonly true - bin\Release\ + ..\bin\any\Release\ TRACE prompt 4 @@ -69,6 +69,6 @@ - nvcc $(ProjectDir)flacuda.cu -o $(ProjectDir)\flacuda.cubin --machine 32 --cubin --compiler-bindir "C:\Program Files (x86)\Microsoft Visual Studio 8\VC\bin" --system-include "C:\Program Files (x86)\Microsoft Visual Studio 8\VC\include" + C:\work\cuda\bin\nvcc $(ProjectDir)flacuda.cu -o $(ProjectDir)\flacuda.cubin --machine 32 --cubin --compiler-bindir "C:\Program Files (x86)\Microsoft Visual Studio 8\VC\bin" --system-include "C:\Program Files (x86)\Microsoft Visual Studio 8\VC\include" \ No newline at end of file diff --git a/CUETools.FlaCuda/FlaCudaWriter.cs b/CUETools.FlaCuda/FlaCudaWriter.cs index e1e934e..a45975a 100644 --- a/CUETools.FlaCuda/FlaCudaWriter.cs +++ b/CUETools.FlaCuda/FlaCudaWriter.cs @@ -30,6 +30,7 @@ using GASS.CUDA.Types; namespace CUETools.Codecs.FlaCuda { + [AudioEncoderClass("FlaCuda", "flac", true, "0 1 2 3 4 5 6 7 8 9 10 11", "8", 1)] public class FlaCudaWriter : IAudioDest { Stream _IO = null; @@ -50,7 +51,7 @@ namespace CUETools.Codecs.FlaCuda // total stream samples // if 0, stream length is unknown - int sample_count; + int sample_count = -1; FlakeEncodeParams eparams; @@ -70,11 +71,10 @@ namespace CUETools.Codecs.FlaCuda byte[] header; float[] windowBuffer; - byte[] md5_buffer; int samplesInBuffer = 0; int max_frames = 0; - int _compressionLevel = 5; + int _compressionLevel = 7; int _blocksize = 0; int _totalSize = 0; int _windowsize = 0, _windowcount = 0; @@ -102,21 +102,25 @@ namespace CUETools.Codecs.FlaCuda bool do_lattice = false; + AudioPCMConfig _pcm; + public const int MAX_BLOCKSIZE = 4096 * 16; internal const int maxFrames = 128; internal const int maxResidualParts = 64; // not (MAX_BLOCKSIZE + 255) / 256!! 64 is hardcoded in cudaEstimateResidual. It's per block. internal const int maxAutocorParts = (MAX_BLOCKSIZE + 255) / 256; - public FlaCudaWriter(string path, int bitsPerSample, int channelCount, int sampleRate, Stream IO) + public FlaCudaWriter(string path, Stream IO, AudioPCMConfig pcm) { - if (bitsPerSample != 16) + _pcm = pcm; + + if (pcm.BitsPerSample != 16) throw new Exception("Bits per sample must be 16."); - if (channelCount != 2) + if (pcm.ChannelCount != 2) throw new Exception("ChannelCount must be 2."); - channels = channelCount; - sample_rate = sampleRate; - bits_per_sample = (uint) bitsPerSample; + channels = pcm.ChannelCount; + sample_rate = pcm.SampleRate; + bits_per_sample = (uint) pcm.BitsPerSample; // flake_validate_params @@ -124,7 +128,6 @@ namespace CUETools.Codecs.FlaCuda _IO = IO; windowBuffer = new float[FlaCudaWriter.MAX_BLOCKSIZE * lpc.MAX_LPC_WINDOWS]; - md5_buffer = new byte[FlaCudaWriter.MAX_BLOCKSIZE * channels * bits_per_sample / 8]; eparams.flake_set_defaults(_compressionLevel, encode_on_cpu); eparams.padding_size = 8192; @@ -133,6 +136,11 @@ namespace CUETools.Codecs.FlaCuda crc16 = new Crc16(); } + public FlaCudaWriter(string path, AudioPCMConfig pcm) + : this(path, null, pcm) + { + } + public int TotalSize { get @@ -168,6 +176,15 @@ namespace CUETools.Codecs.FlaCuda } } + public string Options + { + set + { + if (value == null || value == "") return; + throw new Exception("Unsupported options " + value); + } + } + public int CPUThreads { get @@ -248,7 +265,7 @@ namespace CUETools.Codecs.FlaCuda if (_IO.CanSeek) { - if (sample_count == 0 && _position != 0) + if (sample_count <= 0 && _position != 0) { BitWriter bitwriter = new BitWriter(header, 0, 4); bitwriter.writebits(32, (int)_position); @@ -289,7 +306,7 @@ namespace CUETools.Codecs.FlaCuda public void Close() { DoClose(); - if (sample_count != 0 && _position != sample_count) + if (sample_count > 0 && _position != sample_count) throw new Exception(string.Format("Samples written differs from the expected sample count. Expected {0}, got {1}.", sample_count, _position)); } @@ -492,22 +509,9 @@ namespace CUETools.Codecs.FlaCuda get { return _userProcessorTime; } } - public int BitsPerSample + public AudioPCMConfig PCM { - get { return 16; } - } - - /// - /// Copy input samples into task buffer - /// - /// - /// - /// - unsafe void copy_samples(int[,] samples, int pos, int block, FlaCudaTask task) - { - AudioSamples.FLACSamplesToBytes(samples, pos, ((byte*)task.samplesBytesPtr) + samplesInBuffer * channels * 2, - block, channels, (int)bits_per_sample); - samplesInBuffer += block; + get { return _pcm; } } unsafe void encode_residual_fixed(int* res, int* smp, int n, int order) @@ -1021,7 +1025,7 @@ namespace CUETools.Codecs.FlaCuda int pmin = get_max_p_order(eparams.min_partition_order, task.frame.blocksize, task.frame.subframes[ch].best.order); int pmax = get_max_p_order(eparams.max_partition_order, task.frame.blocksize, task.frame.subframes[ch].best.order); - uint bits = (uint)task.frame.subframes[ch].best.order * task.frame.subframes[ch].obits + 6; + uint bits = (uint)(task.frame.subframes[ch].best.order * task.frame.subframes[ch].obits) + 6; task.frame.subframes[ch].best.size = bits + calc_rice_params(task.frame.subframes[ch].best.rc, pmin, pmax, task.frame.subframes[ch].best.residual, (uint)task.frame.blocksize, (uint)task.frame.subframes[ch].best.order); } break; @@ -1031,54 +1035,32 @@ namespace CUETools.Codecs.FlaCuda ulong csum = 0; for (int i = task.frame.subframes[ch].best.order; i > 0; i--) csum += (ulong)Math.Abs(coefs[i - 1]); - if ((csum << (int)task.frame.subframes[ch].obits) >= 1UL << 32 || encode_on_cpu) + if ((csum << task.frame.subframes[ch].obits) >= 1UL << 32 || encode_on_cpu) { if (!unpacked) unpack_samples(task, task.frameSize); unpacked = true; - if ((csum << (int)task.frame.subframes[ch].obits) >= 1UL << 32) + if ((csum << task.frame.subframes[ch].obits) >= 1UL << 32) lpc.encode_residual_long(task.frame.subframes[ch].best.residual, task.frame.subframes[ch].samples, task.frame.blocksize, task.frame.subframes[ch].best.order, coefs, task.frame.subframes[ch].best.shift); else lpc.encode_residual(task.frame.subframes[ch].best.residual, task.frame.subframes[ch].samples, task.frame.blocksize, task.frame.subframes[ch].best.order, coefs, task.frame.subframes[ch].best.shift); int pmin = get_max_p_order(eparams.min_partition_order, task.frame.blocksize, task.frame.subframes[ch].best.order); int pmax = get_max_p_order(eparams.max_partition_order, task.frame.blocksize, task.frame.subframes[ch].best.order); - uint bits = (uint)task.frame.subframes[ch].best.order * task.frame.subframes[ch].obits + 4 + 5 + (uint)task.frame.subframes[ch].best.order * (uint)task.frame.subframes[ch].best.cbits + 6; + uint bits = (uint)(task.frame.subframes[ch].best.order * task.frame.subframes[ch].obits) + 4 + 5 + (uint)task.frame.subframes[ch].best.order * (uint)task.frame.subframes[ch].best.cbits + 6; //uint oldsize = task.frame.subframes[ch].best.size; task.frame.subframes[ch].best.size = bits + calc_rice_params(task.frame.subframes[ch].best.rc, pmin, pmax, task.frame.subframes[ch].best.residual, (uint)task.frame.blocksize, (uint)task.frame.subframes[ch].best.order); //if (task.frame.subframes[ch].best.size > task.frame.subframes[ch].obits * (uint)task.frame.blocksize && // oldsize <= task.frame.subframes[ch].obits * (uint)task.frame.blocksize) // throw new Exception("oops"); } -#if DEBUG - else - { - // residual - int len = task.frame.subframes[ch].best.order * (int)task.frame.subframes[ch].obits + 6 + - 4 + 5 + task.frame.subframes[ch].best.order * task.frame.subframes[ch].best.cbits + - (4 << task.frame.subframes[ch].best.rc.porder); - int j = task.frame.subframes[ch].best.order; - int psize = task.frame.blocksize >> task.frame.subframes[ch].best.rc.porder; - for (int p = 0; p < (1 << task.frame.subframes[ch].best.rc.porder); p++) - { - int k = task.frame.subframes[ch].best.rc.rparams[p]; - int cnt = p == 0 ? psize - task.frame.subframes[ch].best.order : psize; - len += (k + 1) * cnt; - for (int i = j; i < j + cnt; i++) - len += (((task.frame.subframes[ch].best.residual[i] << 1) ^ (task.frame.subframes[ch].best.residual[i] >> 31)) >> k); - j += cnt; - } - if (len != task.frame.subframes[ch].best.size) - throw new Exception(string.Format("length mismatch: {0} vs {1}", len, task.frame.subframes[ch].best.size)); - } -#endif } break; } - if (task.frame.subframes[ch].best.size > task.frame.subframes[ch].obits * (uint)task.frame.blocksize) + if (task.frame.subframes[ch].best.size > task.frame.subframes[ch].obits * task.frame.blocksize) { #if DEBUG throw new Exception("larger than verbatim"); #endif task.frame.subframes[ch].best.type = SubframeType.Verbatim; - task.frame.subframes[ch].best.size = task.frame.subframes[ch].obits * (uint)task.frame.blocksize; + task.frame.subframes[ch].best.size = (uint)(task.frame.subframes[ch].obits * task.frame.blocksize); if (!unpacked) unpack_samples(task, task.frameSize); unpacked = true; } } @@ -1109,7 +1091,7 @@ namespace CUETools.Codecs.FlaCuda int index = ch + iFrame * channels; frame.subframes[ch].best.residual = ((int*)task.residualBufferPtr) + task.BestResidualTasks[index].residualOffs; frame.subframes[ch].best.type = SubframeType.Verbatim; - frame.subframes[ch].best.size = frame.subframes[ch].obits * (uint)frame.blocksize; + frame.subframes[ch].best.size = (uint)(frame.subframes[ch].obits * frame.blocksize); frame.subframes[ch].wbits = 0; if (task.BestResidualTasks[index].size < 0) @@ -1121,12 +1103,9 @@ namespace CUETools.Codecs.FlaCuda frame.subframes[ch].best.order = task.BestResidualTasks[index].residualOrder; frame.subframes[ch].best.cbits = task.BestResidualTasks[index].cbits; frame.subframes[ch].best.shift = task.BestResidualTasks[index].shift; - frame.subframes[ch].obits -= (uint)task.BestResidualTasks[index].wbits; - frame.subframes[ch].wbits = (uint)task.BestResidualTasks[index].wbits; + frame.subframes[ch].obits -= task.BestResidualTasks[index].wbits; + frame.subframes[ch].wbits = task.BestResidualTasks[index].wbits; frame.subframes[ch].best.rc.porder = task.BestResidualTasks[index].porder; - if (frame.subframes[ch].wbits != 0) - for (int i = 0; i < frame.blocksize; i++) - frame.subframes[ch].samples[i] >>= (int)frame.subframes[ch].wbits; for (int i = 0; i < task.BestResidualTasks[index].residualOrder; i++) frame.subframes[ch].best.coefs[i] = task.BestResidualTasks[index].coefs[task.BestResidualTasks[index].residualOrder - 1 - i]; if (!encode_on_cpu && (frame.subframes[ch].best.type == SubframeType.Fixed || frame.subframes[ch].best.type == SubframeType.LPC)) @@ -1354,20 +1333,23 @@ namespace CUETools.Codecs.FlaCuda for (int ch = 0; ch < channels; ch++) { int* s = task.frame.subframes[ch].samples; + int wbits = (int)task.frame.subframes[ch].wbits; for (int i = 0; i < count; i++) - s[i] = src[i * channels + ch]; + s[i] = src[i * channels + ch] >>= wbits; } break; case ChannelMode.LeftRight: { int* left = task.frame.subframes[0].samples; int* right = task.frame.subframes[1].samples; + int lwbits = (int)task.frame.subframes[0].wbits; + int rwbits = (int)task.frame.subframes[1].wbits; for (int i = 0; i < count; i++) { int l = *(src++); int r = *(src++); - left[i] = l; - right[i] = r; + left[i] = l >> lwbits; + right[i] = r >> rwbits; } break; } @@ -1375,12 +1357,14 @@ namespace CUETools.Codecs.FlaCuda { int* left = task.frame.subframes[0].samples; int* right = task.frame.subframes[1].samples; + int lwbits = (int)task.frame.subframes[0].wbits; + int rwbits = (int)task.frame.subframes[1].wbits; for (int i = 0; i < count; i++) { int l = *(src++); int r = *(src++); - left[i] = l; - right[i] = l - r; + left[i] = l >> lwbits; + right[i] = (l - r) >> rwbits; } break; } @@ -1388,12 +1372,14 @@ namespace CUETools.Codecs.FlaCuda { int* left = task.frame.subframes[0].samples; int* right = task.frame.subframes[1].samples; + int lwbits = (int)task.frame.subframes[0].wbits; + int rwbits = (int)task.frame.subframes[1].wbits; for (int i = 0; i < count; i++) { int l = *(src++); int r = *(src++); - left[i] = l - r; - right[i] = r; + left[i] = (l - r) >> lwbits; + right[i] = r >> rwbits; } break; } @@ -1401,12 +1387,14 @@ namespace CUETools.Codecs.FlaCuda { int* left = task.frame.subframes[0].samples; int* right = task.frame.subframes[1].samples; + int lwbits = (int)task.frame.subframes[0].wbits; + int rwbits = (int)task.frame.subframes[1].wbits; for (int i = 0; i < count; i++) { int l = *(src++); int r = *(src++); - left[i] = (l + r) >> 1; - right[i] = l - r; + left[i] = (l + r) >> (1 + lwbits); + right[i] = (l - r) >> rwbits; } break; } @@ -1425,7 +1413,7 @@ namespace CUETools.Codecs.FlaCuda task.frame.subframes[ch].Init( smp + ch * FlaCudaWriter.MAX_BLOCKSIZE + iFrame * task.frameSize, ((int*)task.residualBufferPtr) + ch * FlaCudaWriter.MAX_BLOCKSIZE + iFrame * task.frameSize, - bits_per_sample + (doMidside && ch == 3 ? 1U : 0U), 0); + _pcm.BitsPerSample + (doMidside && ch == 3 ? 1 : 0), 0); select_best_methods(task.frame, channelCount, iFrame, task); //unpack_samples(task); @@ -1490,8 +1478,8 @@ namespace CUETools.Codecs.FlaCuda bool doMidside = channels == 2 && eparams.do_midside; int channelCount = doMidside ? 2 * channels : channels; - int iSample = 0; - int iByte = 0; + long iSample = 0; + long iByte = 0; task.frame.writer.Reset(); task.frame.writer_offset = 0; for (int iFrame = 0; iFrame < task.frameCount; iFrame++) @@ -1499,13 +1487,13 @@ namespace CUETools.Codecs.FlaCuda //if (0 != eparams.variable_block_size && 0 == (task.blocksize & 7) && task.blocksize >= 128) // fs = encode_frame_vbs(); //else - int fn = task.frameNumber + (eparams.variable_block_size > 0 ? iSample : iFrame); + int fn = task.frameNumber + (eparams.variable_block_size > 0 ? (int)iSample : iFrame); int fs = encode_frame(doMidside, channelCount, iFrame, task, fn); if (task.verify != null) { int decoded = task.verify.DecodeFrame(task.frame.writer.Buffer, task.frame.writer_offset, fs); - if (decoded != fs || task.verify.Remaining != (ulong)task.frameSize) + if (decoded != fs || task.verify.Remaining != task.frameSize) throw new Exception("validation failed! frame size mismatch"); fixed (int* r = task.verify.Samples) { @@ -1530,13 +1518,13 @@ namespace CUETools.Codecs.FlaCuda { if (seek_table[sp].framesize != 0) continue; - if (seek_table[sp].number >= (ulong)(task.framePos + iSample + task.frameSize)) + if (seek_table[sp].number >= task.framePos + iSample + task.frameSize) break; - if (seek_table[sp].number >= (ulong)(task.framePos + iSample)) + if (seek_table[sp].number >= task.framePos + iSample) { - seek_table[sp].number = (ulong)(task.framePos + iSample); - seek_table[sp].offset = (ulong)iByte; - seek_table[sp].framesize = (uint)task.frameSize; + seek_table[sp].number = task.framePos + iSample; + seek_table[sp].offset = iByte; + seek_table[sp].framesize = task.frameSize; } } } @@ -1546,7 +1534,7 @@ namespace CUETools.Codecs.FlaCuda iSample += task.frameSize; iByte += fs; } - task.outputSize = iByte; + task.outputSize = (int)iByte; if (iByte != task.frame.writer.Length) throw new Exception("invalid length"); } @@ -1558,17 +1546,17 @@ namespace CUETools.Codecs.FlaCuda if (seek_table != null && _IO.CanSeek) for (int sp = 0; sp < seek_table.Length; sp++) { - if (seek_table[sp].number >= (ulong)(task.framePos + iSample)) + if (seek_table[sp].number >= task.framePos + iSample) break; - if (seek_table[sp].number >= (ulong)(task.framePos)) - seek_table[sp].offset += (ulong)(_IO.Position - first_frame_offset); + if (seek_table[sp].number >= task.framePos) + seek_table[sp].offset += _IO.Position - first_frame_offset; } _IO.Write(task.outputBuffer, 0, task.outputSize); _position += iSample; _totalSize += task.outputSize; } - public unsafe void Write(int[,] buff, int pos, int sampleCount) + public unsafe void InitTasks() { bool doMidside = channels == 2 && eparams.do_midside; int channelCount = doMidside ? 2 * channels : channels; @@ -1597,29 +1585,32 @@ namespace CUETools.Codecs.FlaCuda cpu_tasks[i] = new FlaCudaTask(cuda, channelCount, channels, bits_per_sample, max_frame_size, eparams.do_verify); } cudaWindow = cuda.Allocate((uint)sizeof(float) * FlaCudaWriter.MAX_BLOCKSIZE * 2 * lpc.MAX_LPC_WINDOWS); - + inited = true; } - int len = sampleCount; - while (len > 0) + } + + public unsafe void Write(AudioBuffer buff) + { + InitTasks(); + buff.Prepare(this); + int pos = 0; + while (pos < buff.Length) { - int block = Math.Min(len, eparams.block_size * max_frames - samplesInBuffer); + int block = Math.Min(buff.Length - pos, eparams.block_size * max_frames - samplesInBuffer); - copy_samples(buff, pos, block, task1); - - if (md5 != null) - { - AudioSamples.FLACSamplesToBytes(buff, pos, md5_buffer, 0, block, channels, (int)bits_per_sample); - md5.TransformBlock(md5_buffer, 0, block * channels * ((int)bits_per_sample >> 3), null, 0); - } - - len -= block; + fixed (byte* buf = buff.Bytes) + AudioSamples.MemCpy(((byte*)task1.samplesBytesPtr) + samplesInBuffer * _pcm.BlockAlign, buf + pos * _pcm.BlockAlign, block * _pcm.BlockAlign); + + samplesInBuffer += block; pos += block; int nFrames = samplesInBuffer / eparams.block_size; if (nFrames >= max_frames) do_output_frames(nFrames); } + if (md5 != null) + md5.TransformBlock(buff.Bytes, 0, buff.ByteLength, null, 0); } public void wait_for_cpu_task() @@ -1629,25 +1620,40 @@ namespace CUETools.Codecs.FlaCuda return; lock (task) { - while (!task.done) + while (!task.done && task.exception == null) Monitor.Wait(task); + if (task.exception != null) + throw task.exception; } } public void cpu_task_thread(object param) { FlaCudaTask task = param as FlaCudaTask; - while (true) + try + { + while (true) + { + lock (task) + { + while (task.done && !task.exit) + Monitor.Wait(task); + if (task.exit) + return; + } + process_result(task); + lock (task) + { + task.done = true; + Monitor.Pulse(task); + } + } + } + catch (Exception ex) { lock (task) { - while (task.done) - Monitor.Wait(task); - } - process_result(task); - lock (task) - { - task.done = true; + task.exception = ex; Monitor.Pulse(task); } } @@ -1659,6 +1665,7 @@ namespace CUETools.Codecs.FlaCuda if (task.workThread == null) { task.done = false; + task.exit = false; task.workThread = new Thread(cpu_task_thread); task.workThread.IsBackground = true; //task.workThread.Priority = ThreadPriority.BelowNormal; @@ -1676,9 +1683,6 @@ namespace CUETools.Codecs.FlaCuda public unsafe void do_output_frames(int nFrames) { - bool doMidside = channels == 2 && eparams.do_midside; - int channelCount = doMidside ? 2 * channels : channels; - send_to_GPU(task1, nFrames, eparams.block_size); if (task2.frameCount > 0) cuda.SynchronizeStream(task2.stream); @@ -1707,9 +1711,9 @@ namespace CUETools.Codecs.FlaCuda } } int bs = eparams.block_size * nFrames; - if (bs < samplesInBuffer) - AudioSamples.MemCpy(((short*)task2.samplesBytesPtr), ((short*)task1.samplesBytesPtr) + bs * channels, (samplesInBuffer - bs) * channels); samplesInBuffer -= bs; + if (samplesInBuffer > 0) + AudioSamples.MemCpy(((byte*)task2.samplesBytesPtr), ((byte*)task1.samplesBytesPtr) + bs * _pcm.BlockAlign, samplesInBuffer * _pcm.BlockAlign); FlaCudaTask tmp = task1; task1 = task2; task2 = tmp; @@ -1718,7 +1722,7 @@ namespace CUETools.Codecs.FlaCuda public string Path { get { return _path; } } - string vendor_string = "FlaCuda#0.7"; + public static readonly string vendor_string = "FlaCuda#.91"; int select_blocksize(int samplerate, int time_ms) { @@ -1815,8 +1819,8 @@ namespace CUETools.Codecs.FlaCuda bitwriter.writebits(24, 18 * seek_table.Length); for (int i = 0; i < seek_table.Length; i++) { - bitwriter.writebits64(Flake.FLAC__STREAM_METADATA_SEEKPOINT_SAMPLE_NUMBER_LEN, seek_table[i].number); - bitwriter.writebits64(Flake.FLAC__STREAM_METADATA_SEEKPOINT_STREAM_OFFSET_LEN, seek_table[i].offset); + bitwriter.writebits64(Flake.FLAC__STREAM_METADATA_SEEKPOINT_SAMPLE_NUMBER_LEN, (ulong)seek_table[i].number); + bitwriter.writebits64(Flake.FLAC__STREAM_METADATA_SEEKPOINT_STREAM_OFFSET_LEN, (ulong)seek_table[i].offset); bitwriter.writebits(Flake.FLAC__STREAM_METADATA_SEEKPOINT_FRAME_SAMPLES_LEN, seek_table[i].framesize); } bitwriter.flush(); @@ -1926,7 +1930,7 @@ namespace CUETools.Codecs.FlaCuda else max_frame_size = 16 + ((eparams.block_size * channels * (int)bits_per_sample + 7) >> 3); - if (_IO.CanSeek && eparams.do_seektable && sample_count != 0) + if (_IO.CanSeek && eparams.do_seektable && sample_count > 0) { int seek_points_distance = sample_rate * 10; int num_seek_points = 1 + sample_count / seek_points_distance; // 1 seek point per 10 seconds @@ -1937,7 +1941,7 @@ namespace CUETools.Codecs.FlaCuda { seek_table[sp].framesize = 0; seek_table[sp].offset = 0; - seek_table[sp].number = (ulong)(sp * seek_points_distance); + seek_table[sp].number = sp * seek_points_distance; } } @@ -1946,7 +1950,7 @@ namespace CUETools.Codecs.FlaCuda header_len = write_headers(); // initialize CRC & MD5 - if (_IO.CanSeek && eparams.do_md5) + if (eparams.do_md5) md5 = new MD5CryptoServiceProvider(); return header_len; @@ -2252,7 +2256,9 @@ namespace CUETools.Codecs.FlaCuda public FlakeReader verify; public Thread workThread = null; + public Exception exception = null; public bool done = false; + public bool exit = false; unsafe public FlaCudaTask(CUDA _cuda, int channelCount, int channels, uint bits_per_sample, int max_frame_size, bool do_verify) { @@ -2328,13 +2334,23 @@ namespace CUETools.Codecs.FlaCuda if (do_verify) { - verify = new FlakeReader(channels, bits_per_sample); + verify = new FlakeReader(new AudioPCMConfig((int)bits_per_sample, channels, 44100)); verify.DoCRC = false; } } public void Dispose() { + if (workThread != null) + { + lock (this) + { + exit = true; + Monitor.Pulse(this); + } + workThread.Join(); + workThread = null; + } cuda.Free(cudaSamples); cuda.Free(cudaSamplesBytes); cuda.Free(cudaLPCData); diff --git a/CUETools.FlaCuda/flacuda.cu b/CUETools.FlaCuda/flacuda.cu index a40d99f..34c76bf 100644 --- a/CUETools.FlaCuda/flacuda.cu +++ b/CUETools.FlaCuda/flacuda.cu @@ -1324,3 +1324,17 @@ extern "C" __global__ void cudaFindPartitionOrder( } #endif + +#if 0 + if (threadIdx.x < order) + { + for (int i = 0; i < order; i++) + if (threadIdx.x >= i) + sum[threadIdx.x - i] += coefs[threadIdx.x] * sample[order - i - 1]; + fot (int i = order; i < blocksize; i++) + { + if (!threadIdx.x) sample[order + i] = s = residual[order + i] + (sum[order + i] >> shift); + sum[threadIdx.x + i + 1] += coefs[threadIdx.x] * s; + } + } +#endif \ No newline at end of file diff --git a/CUETools.FlaCuda/flacuda.cubin b/CUETools.FlaCuda/flacuda.cubin index f6251ea..29b566d 100644 --- a/CUETools.FlaCuda/flacuda.cubin +++ b/CUETools.FlaCuda/flacuda.cubin @@ -23,21 +23,21 @@ code { 0xa0000009 0x040007c0 0xa008a003 0x00000000 0x1008a003 0x00000280 0xa0000415 0x04000780 0x30810bfd 0x644107c8 0xa0015003 0x00000000 - 0x30020a11 0xc4100780 0x10015003 0x00000280 - 0x1000ca01 0x0423c780 0x40014e0d 0x00200780 - 0x3010060d 0xc4100780 0x60004e01 0x0020c780 - 0x3007000d 0xc4100780 0x30060001 0xc4100780 - 0x20008600 0x2100e800 0x20000801 0x04000780 - 0xd00e0001 0x80c00780 0x00000805 0xc0000780 + 0x10015003 0x00000280 0x1000ca01 0x0423c780 + 0x40014e0d 0x00200780 0x3010060d 0xc4100780 + 0x60004e01 0x0020c780 0x3005000d 0xc4100780 + 0x30040001 0xc4100780 0x20008600 0x20008a00 + 0x30020001 0xc4100780 0x2000c801 0x04200780 + 0xd00e0001 0x80c00780 0x00020a05 0xc0000780 0x04001601 0xe4200780 0x307c0bfd 0x640147ca 0xa0022003 0x00000000 0x10022003 0x00000280 0xa0004c0d 0x04200780 0x10004e01 0x0023c780 0x6000480d 0x0020c780 0x2101f001 0x00000003 - 0x40070019 0x00000780 0x60060219 0x00018780 - 0x30100c19 0xc4100780 0x60060001 0x00018780 + 0x40070011 0x00000780 0x60060211 0x00010780 + 0x30100811 0xc4100780 0x60060001 0x00010780 0x30050001 0xc4100780 0x00023601 0xe4200780 - 0x00000805 0xc0000782 0x213ff001 0x0fffffff - 0x30050001 0xa4000780 0x04013601 0xe4200780 + 0x00020a05 0xc0000782 0x213ff001 0x0fffffff + 0x30000a01 0xa4000780 0x04013601 0xe4200780 0x3006e40d 0xc4300780 0x20000a0d 0x0400c780 0xa000060d 0x44004780 0x0401b601 0xe420c780 0x04017601 0xe4200780 0x3006e401 0xc4300780 @@ -46,13 +46,13 @@ code { 0xa0044003 0x00000000 0x10044003 0x00000280 0xd008d805 0x20000780 0x3005d001 0xc4300780 0x2400c00d 0x04200780 0xa000e401 0x44214780 - 0x20000a0d 0x0400c780 0xa0000a1d 0x44004780 - 0x90000021 0x60000780 0x30020619 0xc4100780 - 0xc00a0e0d 0x040a3d73 0xc018101d 0x03f31723 - 0x2000ce19 0x04218780 0xd00e0c19 0x80c00780 - 0x00000805 0xc0000780 0xc007060d 0x00000780 - 0x90000c11 0x60000780 0xc0180811 0x03f31723 - 0xe0040001 0x0000c780 0x0401b601 0xe4200780 + 0x20000a0d 0x0400c780 0xa0000a11 0x44004780 + 0x90000019 0x60000780 0x3002060d 0xc4100780 + 0xc00a0811 0x040a3d73 0xc0180c19 0x03f31723 + 0x2000ce0d 0x0420c780 0xd00e060d 0x80c00780 + 0xc0060811 0x00000780 0x9000060d 0x60000780 + 0xc018060d 0x03f31723 0xe0030001 0x00010780 + 0x00020a05 0xc0000780 0x0401b601 0xe4200780 0x30010a19 0xc4100782 0x1002801d 0x00000003 0x301f0e01 0xec100780 0xd0820001 0x04400780 0x20000001 0x0401c780 0x30010001 0xec100780 @@ -173,9 +173,9 @@ code { 0x41052c0c 0x41032e18 0x3010060d 0xc4100780 0x30100c19 0xc4100780 0x60044c09 0x0020c780 0x60024e05 0x00218780 0x20018404 0x20018004 - 0x30070209 0xc4100780 0x30060205 0xc4100780 - 0x20000405 0x04004780 0x30020809 0xc4100780 - 0x2101e804 0x20018404 0x20008205 0x00000007 + 0x30050209 0xc4100780 0x30040205 0xc4100780 + 0x20018404 0x20018804 0x30020205 0xc4100780 + 0x2000c805 0x04204780 0x20008205 0x00000007 0xd00e0215 0xa0c00780 0xf0000001 0xe0000002 0x20048001 0x00000003 0x3000cdfd 0x6c2107d8 0x10096003 0x00001280 0xf0000001 0xe0000001 @@ -185,208 +185,206 @@ code { name = cudaComputeLPCLattice lmem = 0 smem = 3436 - reg = 18 + reg = 17 bar = 1 const { segname = const segnum = 1 offset = 0 - bytes = 36 + bytes = 32 mem { 0x0000000f 0xffffffff 0x0000007f 0x0000003f - 0x0000001f 0x7e800000 0x38000000 0x00000001 - 0x3e800000 + 0x0000001f 0x7e800000 0x38000000 0x3e800000 } } bincode { - 0xa000001d 0x04000780 0x30800ffd 0x644107c8 - 0xa0010003 0x00000000 0x30020e21 0xc4100780 - 0x10010003 0x00000280 0x1000ca01 0x0423c780 - 0x40014e05 0x00200780 0x30100205 0xc4100780 - 0x60004e01 0x00204780 0x30070005 0xc4100780 - 0x30060001 0xc4100780 0x20008200 0x2100e800 - 0x20001001 0x04000780 0xd00e0001 0x80c00780 - 0x00001005 0xc0000780 0x04001401 0xe4200780 - 0x307c0e01 0x640087c2 0xa00001fd 0x0c0147f8 - 0x00000025 0x20003780 0xa001c003 0x00000000 + 0xa000003d 0x04000780 0x30801ffd 0x644107c8 + 0xa0010003 0x00000000 0x10010003 0x00000280 + 0x1000ca01 0x0423c780 0x40014e05 0x00200780 + 0x30100205 0xc4100780 0x60004e01 0x00204780 + 0x30050005 0xc4100780 0x30040001 0xc4100780 + 0x20008200 0x20009e00 0x30020001 0xc4100780 + 0x2000c801 0x04200780 0xd00e0001 0x80c00780 + 0x00021e05 0xc0000780 0x04001401 0xe4200780 + 0x307c1e01 0x640087c2 0xa00001fd 0x0c0147f8 + 0x00000041 0x20003780 0xa001c003 0x00000000 0x1001c003 0x00000100 0xa0004e01 0x04200780 0x20018001 0x00000003 0x2101f005 0x00000003 0x6100ce01 0x80604780 0x40010001 0x00018780 0x30050001 0xc4100780 0x0006b401 0xe4200780 0xf0000001 0xe0000002 0x861ffe03 0x00000000 - 0x3007e3fd 0x6420c7c8 0x1000e201 0x0423c780 - 0x2000d605 0x0421c500 0x30020205 0xc4100500 + 0x300fe3fd 0x6420c7c8 0x1000e201 0x0423c780 + 0x2000d605 0x0423c500 0x30020205 0xc4100500 0x2000cc05 0x04204500 0xd00e0205 0x80c00500 - 0xa0000205 0x44014500 0xc0860209 0x00400500 - 0x1000f809 0x0403c280 0xa0035003 0x00000000 - 0x20008e05 0x00000013 0x300101fd 0x6400c7c8 - 0x10000405 0x0403c780 0x10034003 0x00000280 - 0x2000d601 0x0421c780 0x30020001 0xc4100780 + 0xa0000205 0x44014500 0xc086020d 0x00400500 + 0x1000f80d 0x0403c280 0xa0035003 0x00000000 + 0x20009e05 0x00000013 0x300101fd 0x6400c7c8 + 0x10000609 0x0403c780 0x10034003 0x00000280 + 0x2000d601 0x0423c780 0x30020001 0xc4100780 0x2000cc01 0x04200780 0x20008001 0x00000043 0xd00e0001 0x80c00780 0xa0000001 0x44014780 - 0xc000000d 0x03800003 0x10035003 0x00000780 - 0x1000f80d 0x0403c780 0x00001005 0xc0000782 - 0x04003401 0xe4208780 0x10000601 0x0403c780 - 0x04023401 0xe420c780 0x861ffe03 0x00000000 - 0xc003060d 0x00000780 0xe0020409 0x0000c780 - 0x00001005 0xc0000780 0x04047401 0xe4208780 - 0x861ffe03 0x00000000 0x30820e09 0x6440c7d0 - 0xa00005fd 0x0c0147c8 0x00001005 0xc0001680 + 0xc0000001 0x03800003 0x10035003 0x00000780 + 0x1000f801 0x0403c780 0x00021e05 0xc0000782 + 0x04003401 0xe420c780 0x10000005 0x0403c780 + 0x04023401 0xe4200780 0x861ffe03 0x00000000 + 0xc0000001 0x00000780 0xe0030601 0x00000780 + 0x00021e05 0xc0000780 0x04047401 0xe4200780 + 0x861ffe03 0x00000000 0x30821e01 0x6440c7d0 + 0xa00001fd 0x0c0147c8 0x00021e05 0xc0001680 0xd415d00d 0x20001680 0xd411d009 0x20001680 - 0x1c00c009 0x0423d680 0xb800c009 0x00209680 - 0x04047401 0xe4209680 0x861ffe03 0x00000000 - 0x30830e09 0x6440c7e0 0xa00005fd 0x0c0147d8 - 0x00001005 0xc0002680 0xd413d00d 0x20002680 - 0xd411d009 0x20002680 0x1c00c009 0x0423e680 - 0xb800c009 0x0020a680 0x04047401 0xe420a680 - 0x861ffe03 0x00000000 0x30840e09 0x6440c7f0 - 0xa00005fd 0x0c0147e8 0x00001005 0xc0003680 + 0x1c00c001 0x0423d680 0xb800c001 0x00201680 + 0x04047401 0xe4201680 0x861ffe03 0x00000000 + 0x30831e01 0x6440c7e0 0xa00001fd 0x0c0147d8 + 0x00021e05 0xc0002680 0xd413d00d 0x20002680 + 0xd411d009 0x20002680 0x1c00c001 0x0423e680 + 0xb800c001 0x00202680 0x04047401 0xe4202680 + 0x861ffe03 0x00000000 0x30841e01 0x6440c7f0 + 0xa00001fd 0x0c0147e8 0x00021e05 0xc0003680 0xd412d00d 0x20003680 0xd411d009 0x20003680 - 0x1c00c009 0x0423f680 0xb800c009 0x0020b680 - 0x04047401 0xe420b680 0x861ffe03 0x00000000 + 0x1c00c001 0x0423f680 0xb800c001 0x00203680 + 0x04047401 0xe4203680 0x861ffe03 0x00000000 0xa0069003 0x00000000 0x10069003 0x00002100 - 0x00001005 0xc0000780 0xd411d009 0x20000780 - 0x1800e009 0x0423c780 0xb800c009 0x00208780 - 0x04047401 0xe4208780 0x1900f008 0xb9026008 - 0x04047401 0xe4208780 0x1900e808 0xb9026008 - 0x04047401 0xe4208780 0x1900e408 0xb9026008 - 0x04047401 0xe4208780 0x1900e208 0xb9026008 - 0x04047401 0xe4208780 0xf0000001 0xe0000002 + 0x00021e05 0xc0000780 0xd411d009 0x20000780 + 0x1800e001 0x0423c780 0xb800c001 0x00200780 + 0x04047401 0xe4200780 0x1900f000 0xb9006000 + 0x04047401 0xe4200780 0x1900e800 0xb9006000 + 0x04047401 0xe4200780 0x1900e400 0xb9006000 + 0x04047401 0xe4200780 0x1900e200 0xb9006000 + 0x04047401 0xe4200780 0xf0000001 0xe0000002 0x861ffe03 0x00000000 0xd011d005 0x20000780 - 0x1400c009 0x0423c780 0x861ffe03 0x00000000 - 0x307cd1fd 0x6c20c7f8 0x1015f003 0x00003280 - 0x20018e29 0x00000003 0x20018e2d 0x00000013 - 0x20028e31 0x00000003 0x20028e35 0x00000013 - 0x1000f839 0x0403c780 0x20001441 0x04038780 - 0x3010e3fd 0x6c20c7f8 0x20001c0d 0x0401f500 - 0x2100060d 0x0441f500 0x00020605 0xc0003500 - 0xc401f40d 0x00203500 0x1000f80d 0x0403f280 - 0x00001005 0xc0000780 0x04047401 0xe420c780 - 0x2000163d 0x04038780 0xa008d003 0x00000000 - 0x300fe3fd 0x6c20c7f8 0x1008a003 0x00003280 - 0x20001c0d 0x0401c780 0x00001005 0xc0000780 - 0x2001860d 0x00000013 0xd411d009 0x20000780 - 0x00020605 0xc0000780 0x1800c00d 0x0423c780 - 0xe400f40d 0x0020c780 0x1008d003 0x00000780 - 0x00001005 0xc0000780 0xd411d005 0x20000780 - 0x1400c00d 0x0423c780 0x00001005 0xc0000782 - 0x04047401 0xe420c780 0x861ffe03 0x00000000 - 0x00001005 0xc0000680 0xd415d00d 0x20000680 - 0xd411d009 0x20000680 0x1c00c00d 0x0423c680 - 0xb800c00d 0x0020c680 0x04047401 0xe420c680 - 0x861ffe03 0x00000000 0x00001005 0xc0001680 - 0xd413d00d 0x20001680 0xd411d009 0x20001680 - 0x1c00c00d 0x0423d680 0xb800c00d 0x0020d680 - 0x04047401 0xe420d680 0x861ffe03 0x00000000 - 0x00001005 0xc0002680 0xd412d00d 0x20002680 - 0xd411d009 0x20002680 0x1c00c00d 0x0423e680 - 0xb800c00d 0x0020e680 0x04047401 0xe420e680 - 0x861ffe03 0x00000000 0xa00b4003 0x00000000 - 0x100b4003 0x00002100 0x00001005 0xc0000780 - 0xd411d009 0x20000780 0x1800e00d 0x0423c780 - 0xb800c00d 0x0020c780 0x04047401 0xe420c780 - 0x1900f00c 0xb903600c 0x04047401 0xe420c780 - 0x1900e80c 0xb903600c 0x04047401 0xe420c780 - 0x1900e40c 0xb903600c 0x04047401 0xe420c780 - 0x1900e20c 0xb903600c 0x04047401 0xe420c780 - 0xf0000001 0xe0000002 0x861ffe03 0x00000000 - 0xd011d005 0x20000780 0x1400c00d 0x0423c780 - 0x861ffe03 0x00000000 0xa00c3003 0x00000000 - 0x00001201 0xa00007f0 0x100c3003 0x00003100 - 0x10008610 0x10008414 0xb08505fd 0x605107f8 - 0xc0880811 0x00403680 0xc0880a15 0x00403680 - 0x90000a14 0xc0050810 0x00021c05 0xc0000780 - 0x04043401 0xe4210780 0xf0000001 0xe0000002 - 0xa00d5003 0x00000000 0x30071dfd 0x6400c7f8 - 0x100d5003 0x00003280 0x20401c11 0x0401c780 - 0x00001005 0xc0000780 0x00020809 0xc0000780 - 0xd410d005 0x20000780 0xd810c809 0x20000780 - 0x10008618 0x10008444 0x1500e014 0x1900e010 - 0xb08505fd 0x605107f8 0xc0880619 0x00403680 - 0xc0880445 0x00403680 0x90002244 0xc0110c18 - 0xe0060811 0x04014780 0x00001005 0xc0000780 - 0x04043401 0xe4210780 0xf0000001 0xe0000002 - 0xa00e2003 0x00000000 0x30071dfd 0x640047f8 - 0x100e2003 0x00003280 0x30000e11 0x04038780 - 0x00020809 0xc0000780 0xd01ad005 0x20000780 - 0x30051c11 0xc4100780 0x2504e010 0x20048e10 - 0xd810d005 0x20000780 0x30020815 0xc4100780 - 0x1500e010 0x2105f214 0xd00e0a11 0xa0c00780 - 0xf0000001 0xe0000002 0xa00f5003 0x00000000 - 0x1000e211 0x0423c780 0x3010e3fd 0x6c20c7f8 - 0x100f5003 0x00003280 0x20001c11 0x0401c780 - 0x20018811 0x00000003 0x00020805 0xc0000780 - 0x10008614 0x10008418 0x1400f411 0x0423c780 - 0xb08505fd 0x605107f8 0xc0880615 0x00403680 - 0xc0880419 0x00403680 0x90000c18 0xc0060a18 - 0x1400f415 0x0423c780 0xe0060215 0x04014780 - 0x04003401 0xe4214780 0xe0040c05 0x04004780 - 0x1000e211 0x0423c780 0xf0000001 0xe0000002 - 0xa0107003 0x00000000 0x30041ffd 0x6c0187f8 - 0x10107003 0x00003280 0x20001c11 0x0401c780 - 0x20018811 0x00000013 0x00020805 0xc0000780 - 0x10008614 0x10008418 0x1400f411 0x0423c780 - 0xb08505fd 0x605107f8 0xc0880615 0x00403680 - 0xc0880419 0x00403680 0x90000c08 0xc0020a0c - 0x1400f409 0x0423c780 0xe0030009 0x04008780 - 0x04003401 0xe4208780 0xe0040601 0x04000780 - 0x1000e211 0x0423c780 0x20001809 0x04038782 - 0x300209fd 0x6c00c7f8 0x20001c09 0x0401f500 - 0x21000409 0x0441f500 0x00020405 0xc0003500 - 0xc001020d 0x00003500 0x1400f409 0x0423f500 - 0xe402f409 0x0020f500 0x1000f809 0x0403f280 - 0x00001005 0xc0000780 0x04047401 0xe4208780 - 0x20001a09 0x04038780 0xa0123003 0x00000000 - 0x3002e3fd 0x6c20c7f8 0x10120003 0x00003280 - 0x20001c09 0x0401c780 0x20018409 0x00000013 - 0x00020405 0xc0000780 0xc000000d 0x00000780 - 0x1400f409 0x0423c780 0x00001009 0xc0000780 - 0xe402f409 0x0020c780 0xd811d005 0x20000780 - 0xb400c009 0x00208780 0x10123003 0x00000780 - 0x00001005 0xc0000780 0xd411d005 0x20000780 - 0x1400c009 0x0423c780 0x00001005 0xc0000782 - 0x04047401 0xe4208780 0x861ffe03 0x00000000 - 0x00001005 0xc0000680 0xd415d00d 0x20000680 - 0xd411d009 0x20000680 0x1c00c009 0x0423c680 - 0xb800c009 0x00208680 0x04047401 0xe4208680 - 0x861ffe03 0x00000000 0x00001005 0xc0001680 - 0xd413d00d 0x20001680 0xd411d009 0x20001680 - 0x1c00c009 0x0423d680 0xb800c009 0x00209680 - 0x04047401 0xe4209680 0x861ffe03 0x00000000 - 0x00001005 0xc0002680 0xd412d00d 0x20002680 - 0xd411d009 0x20002680 0x1c00c009 0x0423e680 - 0xb800c009 0x0020a680 0x04047401 0xe420a680 - 0x861ffe03 0x00000000 0xa014a003 0x00000000 - 0x1014a003 0x00002100 0x00001005 0xc0000780 - 0xd411d009 0x20000780 0x1800e009 0x0423c780 - 0xb800c009 0x00208780 0x04047401 0xe4208780 - 0x1900f008 0xb9026008 0x04047401 0xe4208780 - 0x1900e808 0xb9026008 0x04047401 0xe4208780 - 0x1900e408 0xb9026008 0x04047401 0xe4208780 - 0x1900e208 0xb9026008 0x04047401 0xe4208780 - 0xf0000001 0xe0000002 0x861ffe03 0x00000000 - 0xd011d005 0x20000780 0xa015a003 0x00000000 - 0xc5006009 0x03f00003 0x00001201 0xa00007f0 - 0x1015a003 0x00003100 0x2040e20d 0x04238780 - 0xa0000611 0x44014780 0x1000040d 0x0403c780 - 0xb08509fd 0x605107f8 0xc088060d 0x00403680 - 0xc0880811 0x00403680 0x90000810 0xc004060c - 0x00021c05 0xc0000780 0x04067401 0xe420c780 - 0xf0000001 0xe0000002 0x861ffe03 0x00000000 - 0x20019c39 0x00000003 0x300ed1fd 0x6c2147f8 - 0x10075003 0x00003280 0x3007d1fd 0x6420c7c8 - 0x30000003 0x00000280 0xd01ad005 0x20000780 - 0x3005d001 0xc4300780 0x2400c001 0x04200780 - 0x00001005 0xc0000780 0x20000e01 0x04000780 - 0xd419d005 0x20000780 0x30020005 0xc4100780 - 0x1500e000 0x2101f204 0xd00e0201 0xa0c00781 + 0x1400c001 0x0423c780 0x861ffe03 0x00000000 + 0x307cd1fd 0x6c20c7f8 0x1015c003 0x00003280 + 0x20019e39 0x00000003 0x20019e35 0x00000013 + 0x20029e31 0x00000003 0x20029e2d 0x00000013 + 0x1000f821 0x0403c780 0x20001c29 0x04020780 + 0x300ae3fd 0x6c20c7f8 0x2000100d 0x0403f500 + 0x00020605 0xc0003500 0xc402f60d 0x00203500 + 0x1000f80d 0x0403f280 0x00021e05 0xc0000780 + 0x04047401 0xe420c780 0x20001a25 0x04020780 + 0xa008c003 0x00000000 0x3009e3fd 0x6c20c7f8 + 0x10089003 0x00003280 0x2000100d 0x0403c780 + 0x00021e09 0xc0000780 0x00020605 0xc0000780 + 0xd811d009 0x20000780 0xd408d805 0x20000780 + 0x1800c00d 0x0423c780 0xe401c00d 0x0020c780 + 0x1008c003 0x00000780 0x00021e05 0xc0000780 + 0xd411d005 0x20000780 0x1400c00d 0x0423c780 + 0x00021e05 0xc0000782 0x04047401 0xe420c780 + 0x861ffe03 0x00000000 0x00021e05 0xc0000680 + 0xd415d00d 0x20000680 0xd411d009 0x20000680 + 0x1c00c00d 0x0423c680 0xb800c00d 0x0020c680 + 0x04047401 0xe420c680 0x861ffe03 0x00000000 + 0x00021e05 0xc0001680 0xd413d00d 0x20001680 + 0xd411d009 0x20001680 0x1c00c00d 0x0423d680 + 0xb800c00d 0x0020d680 0x04047401 0xe420d680 + 0x861ffe03 0x00000000 0x00021e05 0xc0002680 + 0xd412d00d 0x20002680 0xd411d009 0x20002680 + 0x1c00c00d 0x0423e680 0xb800c00d 0x0020e680 + 0x04047401 0xe420e680 0x861ffe03 0x00000000 + 0xa00b3003 0x00000000 0x100b3003 0x00002100 + 0x00021e05 0xc0000780 0xd411d009 0x20000780 + 0x1800e00d 0x0423c780 0xb800c00d 0x0020c780 + 0x04047401 0xe420c780 0x1900f00c 0xb903600c + 0x04047401 0xe420c780 0x1900e80c 0xb903600c + 0x04047401 0xe420c780 0x1900e40c 0xb903600c + 0x04047401 0xe420c780 0x1900e20c 0xb903600c + 0x04047401 0xe420c780 0xf0000001 0xe0000002 + 0x861ffe03 0x00000000 0xd011d005 0x20000780 + 0x1400c01d 0x0423c780 0x861ffe03 0x00000000 + 0xa00c2003 0x00000000 0x00002001 0xa00007f0 + 0x100c2003 0x00003100 0x10008e0c 0x10008010 + 0xb08501fd 0x605107f8 0xc087060d 0x00403680 + 0xc0870811 0x00403680 0x90000810 0xc004060c + 0x00021005 0xc0000780 0x04043401 0xe420c780 + 0xf0000001 0xe0000002 0xa00d4003 0x00000000 + 0x300f11fd 0x6400c7f8 0x100d4003 0x00003280 + 0x30001e0d 0x04020780 0x00021e05 0xc0000780 + 0x00020609 0xc0000780 0xd410d005 0x20000780 + 0xd810c809 0x20000780 0x10008e10 0x1000800c + 0x1500e018 0x1900e014 0xb08501fd 0x605107f8 + 0xc0870e11 0x00403680 0xc087000d 0x00403680 + 0x9000060c 0xc003080c 0xe0030a0d 0x04018780 + 0x00021e05 0xc0000780 0x04043401 0xe420c780 + 0xf0000001 0xe0000002 0xa00e1003 0x00000000 + 0x300f11fd 0x640047f8 0x100e1003 0x00003280 + 0x30001e0d 0x04020780 0x00020605 0xc0000780 + 0xd01ad009 0x20000780 0x3005100d 0xc4100780 + 0x2903e00c 0x20039e0c 0xd410d005 0x20000780 + 0x30020611 0xc4100780 0x1500e00c 0x2104f210 + 0xd00e080d 0xa0c00780 0xf0000001 0xe0000002 + 0xa00f3003 0x00000000 0x1000e20d 0x0423c780 + 0x300ae3fd 0x6c20c7f8 0x100f3003 0x00003280 + 0x2000100d 0x0403c780 0x00020605 0xc0000780 + 0x10008e10 0x10008014 0x1400f60d 0x0423c780 + 0xb08501fd 0x605107f8 0xc0870e11 0x00403680 + 0xc0870015 0x00403680 0x90000a14 0xc0050814 + 0x1400f611 0x0423c780 0xe0050411 0x04010780 + 0x04003601 0xe4210780 0xe0030a09 0x04008780 + 0x1000e20d 0x0423c780 0xf0000001 0xe0000002 + 0xa0106003 0x00000000 0x300313fd 0x6c0187f8 + 0x10106003 0x00003280 0x2000100d 0x0403c780 + 0x00020605 0xc0000780 0xd408d809 0x20000780 + 0x10008e10 0x10008014 0x1800c00d 0x0423c780 + 0xb08501fd 0x605107f8 0xc0870e11 0x00403680 + 0xc0870015 0x00403680 0x90000a01 0x00000780 + 0xd408d809 0x20000780 0xc0000810 0x1900e000 + 0xe0040201 0x04000780 0x04023601 0xe4200780 + 0xe0030805 0x04004780 0x1000e20d 0x0423c780 + 0x20001801 0x04020782 0x300007fd 0x6c00c7f8 + 0x20001001 0x0403f500 0x00020005 0xc0003500 + 0xc002040d 0x00003500 0x1400f601 0x0423f500 + 0xe400f601 0x0020f500 0x1000f801 0x0403f280 + 0x00021e05 0xc0000780 0x04047401 0xe4200780 + 0x20001601 0x04020780 0xa0120003 0x00000000 + 0x3000e3fd 0x6c20c7f8 0x1011d003 0x00003280 + 0x20001e01 0x04020780 0x00020005 0xc0000780 + 0xd408d809 0x20000780 0xc001020c 0x1900e000 + 0x00021e05 0xc0000780 0xe800c001 0x0020c780 + 0xd411d005 0x20000780 0xb400c001 0x00200780 + 0x10120003 0x00000780 0x00021e05 0xc0000780 + 0xd411d005 0x20000780 0x1400c001 0x0423c780 + 0x00021e05 0xc0000782 0x04047401 0xe4200780 + 0x861ffe03 0x00000000 0x00021e05 0xc0000680 + 0xd415d00d 0x20000680 0xd411d009 0x20000680 + 0x1c00c001 0x0423c680 0xb800c001 0x00200680 + 0x04047401 0xe4200680 0x861ffe03 0x00000000 + 0x00021e05 0xc0001680 0xd413d00d 0x20001680 + 0xd411d009 0x20001680 0x1c00c001 0x0423d680 + 0xb800c001 0x00201680 0x04047401 0xe4201680 + 0x861ffe03 0x00000000 0x00021e05 0xc0002680 + 0xd412d00d 0x20002680 0xd411d009 0x20002680 + 0x1c00c001 0x0423e680 0xb800c001 0x00202680 + 0x04047401 0xe4202680 0x861ffe03 0x00000000 + 0xa0147003 0x00000000 0x10147003 0x00002100 + 0x00021e05 0xc0000780 0xd411d009 0x20000780 + 0x1800e001 0x0423c780 0xb800c001 0x00200780 + 0x04047401 0xe4200780 0x1900f000 0xb9006000 + 0x04047401 0xe4200780 0x1900e800 0xb9006000 + 0x04047401 0xe4200780 0x1900e400 0xb9006000 + 0x04047401 0xe4200780 0x1900e200 0xb9006000 + 0x04047401 0xe4200780 0xf0000001 0xe0000002 + 0x861ffe03 0x00000000 0xd011d005 0x20000780 + 0xa0157003 0x00000000 0xc5006001 0x03f00003 + 0x00002001 0xa00007f0 0x10157003 0x00003100 + 0x2040e20d 0x04220780 0xa0000611 0x44014780 + 0x1000000d 0x0403c780 0xb08509fd 0x605107f8 + 0xc087060d 0x00403680 0xc0870811 0x00403680 + 0x90000810 0xc004060c 0x00021005 0xc0000780 + 0x04067401 0xe420c780 0xf0000001 0xe0000002 + 0x861ffe03 0x00000000 0x20019021 0x00000003 + 0x3008d1fd 0x6c2147f8 0x10075003 0x00003280 + 0x300fd1fd 0x6420c7c8 0x30000003 0x00000280 + 0xd01ad005 0x20000780 0x3005d001 0xc4300780 + 0x2400c001 0x04200780 0x00021e05 0xc0000780 + 0x20001e01 0x04000780 0xd419d005 0x20000780 + 0x30020005 0xc4100780 0x1500e000 0x2101f204 + 0xd00e0201 0xa0c00781 } } code { name = cudaComputeAutocor lmem = 0 smem = 3328 - reg = 7 + reg = 6 bar = 1 const { segname = const @@ -399,85 +397,84 @@ code { } bincode { 0x10000005 0x0403c780 0xd0800601 0x00400780 - 0xa0000001 0x04000780 0xa0000415 0x04000780 - 0x30050005 0xc4100780 0x20000a0d 0x04004780 + 0xa0000001 0x04000780 0xa0000411 0x04000780 + 0x30050005 0xc4100780 0x2000080d 0x04004780 0x308107fd 0x644107c8 0xa0015003 0x00000000 - 0x30020611 0xc4100780 0x10015003 0x00000280 - 0xa0004e09 0x04200780 0x1000d205 0x0423c780 - 0x30010405 0xe4000780 0x4001d405 0x00218780 - 0x30070209 0xc4100780 0x30060205 0xc4100780 - 0x20018404 0x2101ee04 0x20000805 0x04004780 - 0xd00e0205 0x80c00780 0x00000805 0xc0000780 + 0x10015003 0x00000280 0xa0004e09 0x04200780 + 0x1000d205 0x0423c780 0x30010405 0xe4000780 + 0x4001d405 0x00218780 0x30050209 0xc4100780 + 0x30040205 0xc4100780 0x20018404 0x20018604 + 0x30020205 0xc4100780 0x2000ce05 0x04204780 + 0xd00e0205 0x80c00780 0x00020605 0xc0000780 0x04061601 0xe4204780 0x307c07fd 0x6c0147ca 0xa002d003 0x00000000 0x1002d003 0x00000280 - 0x10018019 0x00000003 0x1000d205 0x0423c780 - 0xa0004c09 0x04200780 0x30010c19 0xc4000780 + 0x10018015 0x00000003 0x1000d205 0x0423c780 + 0xa0004c09 0x04200780 0x30010a15 0xc4000780 0x40608405 0x0000001f 0xa0004e09 0x04200780 - 0x203f8c19 0x0fffffff 0x00067801 0xe4204780 - 0xd019e009 0x20000780 0xd0060409 0x04000780 + 0x203f8a15 0x0fffffff 0x00067801 0xe4204780 + 0xd019e009 0x20000780 0xd0050409 0x04000780 0xd0186005 0x20000780 0x1800c005 0x0423c780 0x6402cc05 0x80204780 0x1400cc09 0x0423c780 0x00067c01 0xe4204780 0x1900e004 0x2501e004 - 0x00067e01 0xe4204780 0x2120f019 0x0000001f - 0x3800c005 0x04208780 0x30060205 0xac000780 + 0x00067e01 0xe4204780 0x2120f015 0x0000001f + 0x3800c005 0x04208780 0x30050205 0xac000780 0x00067a01 0xe4204780 0xf0000001 0xe0000002 0x861ffe03 0x00000000 0xd019e805 0x20000780 0x3403c1fd 0x6c20c7c8 0xa003f003 0x00000000 0x1003e003 0x00000280 0xd019f005 0x20000780 0x2503e204 0x2503e008 0x30020205 0xc4100780 - 0x30020419 0xc4100780 0x2000ca05 0x04204780 - 0xd00e0209 0x80c00780 0x2000cc05 0x04218780 + 0x30020415 0xc4100780 0x2000ca05 0x04204780 + 0xd00e0209 0x80c00780 0x2000cc05 0x04214780 0xd00e0205 0x80c00780 0xa0000409 0x44014780 0xc0010405 0x00000780 0x1003f003 0x00000780 - 0x1000f805 0x0403c780 0x00000805 0xc0000782 + 0x1000f805 0x0403c780 0x00020605 0xc0000782 0x04001601 0xe4204780 0xd019e805 0x20000780 0x20008605 0x00000013 0x3401c1fd 0x6c20c7c8 - 0x00020205 0xc0000780 0xa0055003 0x00000000 - 0x10054003 0x00000280 0xd019f009 0x20000780 - 0x2903e204 0x2903e008 0x20008205 0x00000013 - 0x20008409 0x00000013 0x30020205 0xc4100780 - 0x30020419 0xc4100780 0x2000ca05 0x04204780 - 0xd00e0209 0x80c00780 0x2000cc05 0x04218780 + 0xa0053003 0x00000000 0x10052003 0x00000280 + 0xd019f005 0x20000780 0x2503e204 0x2503e008 + 0x30020205 0xc4100780 0x30020409 0xc4100780 + 0x2101ea04 0x2102ec14 0x20008205 0x00000043 + 0xd00e0209 0x80c00780 0x20008a05 0x00000043 0xd00e0205 0x80c00780 0xa0000409 0x44014780 - 0xc0010405 0x00000780 0x10055003 0x00000780 - 0x1000f805 0x0403c780 0x04001601 0xe4204782 - 0x861ffe03 0x00000000 0x3000d1fd 0x6c2047c8 - 0xa008f003 0x00000000 0x1008f003 0x00000280 - 0x307c0bfd 0x640087c8 0x404f8a09 0x00000003 - 0x20000405 0x04000780 0x00020209 0xc0000780 - 0x00020405 0xc0000780 0x1900f814 0x1900f604 - 0xc405d815 0x00200780 0xe401d615 0x00214780 - 0x1800da05 0x0423c780 0xe401da15 0x00214780 - 0x1800dc05 0x0423c780 0xe401dc15 0x00214780 - 0x1800de05 0x0423c780 0xe401de15 0x00214780 - 0x1800e005 0x0423c780 0xe401e015 0x00214780 - 0x1800e205 0x0423c780 0xe401e215 0x00214780 - 0x1800e405 0x0423c780 0xe401e415 0x00214780 - 0x1800e605 0x0423c780 0xe401e615 0x00214780 - 0x1800e805 0x0423c780 0xe401e815 0x00214780 - 0x1800ea05 0x0423c780 0xe401ea15 0x00214780 - 0x1800ec05 0x0423c780 0xe401ec15 0x00214780 - 0x1800ee05 0x0423c780 0xe401ee15 0x00214780 - 0x1800f005 0x0423c780 0xe401f015 0x00214780 - 0x1800f205 0x0423c780 0xe401f205 0x00214780 - 0x00000805 0xc0000780 0x04041601 0xe4204780 - 0xd4105809 0x20000780 0x1900f004 0xb9016004 - 0xb800e005 0x00204780 0xb800f005 0x00204780 - 0x04041601 0xe4204780 0x1900e404 0xb9016004 - 0xb9016804 0xb9016c04 0x04041601 0xe4204780 - 0x00000805 0xc0000680 0xd4105809 0x20000680 - 0x1800c205 0x0423c680 0x00020005 0xc0000680 - 0xb800c005 0x00204680 0x04063601 0xe4204680 - 0x20088001 0x00000003 0x3000d1fd 0x6c2187d8 - 0x1005c003 0x00001280 0xf0000001 0xe0000002 - 0x861ffe03 0x00000000 0x3003d1fd 0x6c2047c8 - 0x30000003 0x00000280 0xa0004e01 0x04200780 - 0xa0004805 0x04200780 0x40010005 0x00018780 - 0xa0004c01 0x04200780 0x20000001 0x04004780 - 0x2101f005 0x00000003 0x00000805 0xc0000780 - 0x60010001 0x8000c780 0xd418d805 0x20000780 - 0x30020005 0xc4100780 0x1500e000 0x2101e804 - 0xd00e0201 0xa0c00781 + 0xc0010405 0x00000780 0x10053003 0x00000780 + 0x1000f805 0x0403c780 0x00020605 0xc0000782 + 0x04021601 0xe4204780 0x861ffe03 0x00000000 + 0x3000d1fd 0x6c2047c8 0xa008e003 0x00000000 + 0x1008e003 0x00000280 0x307c09fd 0x640087c8 + 0x404f8809 0x00000003 0x20000405 0x04000780 + 0x00020209 0xc0000780 0x00020405 0xc0000780 + 0x1900f810 0x1900f604 0xc404d811 0x00200780 + 0xe401d611 0x00210780 0x1800da05 0x0423c780 + 0xe401da11 0x00210780 0x1800dc05 0x0423c780 + 0xe401dc11 0x00210780 0x1800de05 0x0423c780 + 0xe401de11 0x00210780 0x1800e005 0x0423c780 + 0xe401e011 0x00210780 0x1800e205 0x0423c780 + 0xe401e211 0x00210780 0x1800e405 0x0423c780 + 0xe401e411 0x00210780 0x1800e605 0x0423c780 + 0xe401e611 0x00210780 0x1800e805 0x0423c780 + 0xe401e811 0x00210780 0x1800ea05 0x0423c780 + 0xe401ea11 0x00210780 0x1800ec05 0x0423c780 + 0xe401ec11 0x00210780 0x1800ee05 0x0423c780 + 0xe401ee11 0x00210780 0x1800f005 0x0423c780 + 0xe401f011 0x00210780 0x1800f205 0x0423c780 + 0xe401f205 0x00210780 0x00020605 0xc0000780 + 0x04041601 0xe4204780 0xd4105809 0x20000780 + 0x1900f004 0xb9016004 0xb800e005 0x00204780 + 0xb800f005 0x00204780 0x04041601 0xe4204780 + 0x1900e404 0xb9016004 0xb9016804 0xb9016c04 + 0x04041601 0xe4204780 0x00020605 0xc0000680 + 0xd4105809 0x20000680 0x1800c205 0x0423c680 + 0x00020005 0xc0000680 0xb800c005 0x00204680 + 0x04063601 0xe4204680 0x20088001 0x00000003 + 0x3000d1fd 0x6c2187d8 0x1005b003 0x00001280 + 0xf0000001 0xe0000002 0x861ffe03 0x00000000 + 0x3003d1fd 0x6c2047c8 0x30000003 0x00000280 + 0xa0004e01 0x04200780 0xa0004805 0x04200780 + 0x40010005 0x00018780 0xa0004c01 0x04200780 + 0x20000001 0x04004780 0x2101f005 0x00000003 + 0x00020605 0xc0000780 0x60010001 0x8000c780 + 0xd418d805 0x20000780 0x30020005 0xc4100780 + 0x1500e000 0x2101e804 0xd00e0201 0xa0c00781 } } code { @@ -499,11 +496,11 @@ code { 0x1000ca05 0x0423c780 0xa0000009 0x04000780 0x30010401 0xe40007d0 0x307c01fd 0x640087c8 0xa0014003 0x00000000 0x10013003 0x00001680 - 0x2101ea05 0x00000003 0x100f8001 0x00000003 - 0x30010001 0xc4000780 0x40014e11 0x00200780 + 0x2101ea01 0x00000003 0x100f8005 0x00000003 + 0x30000205 0xc4000780 0x40034e11 0x00200780 0xa0004c0d 0x04200780 0x30100811 0xc4100780 - 0x30010605 0xc4000780 0x60004e01 0x00210780 - 0x20018000 0x20008400 0x30020001 0xc4100780 + 0x30000601 0xc4000780 0x60024e05 0x00210780 + 0x20008200 0x20008400 0x30020001 0xc4100780 0x2000c801 0x04200780 0xd00e000d 0x80c00780 0x10014003 0x00000780 0x1000f80d 0x0403c780 0xa0004205 0x04200782 0x1100ea00 0x20018410 @@ -552,9 +549,9 @@ code { 0x30040001 0xc4000780 0x40014e19 0x00200780 0xa0004c15 0x04200780 0x30100c19 0xc4100780 0x30040a11 0xc4000780 0x60004e01 0x00218780 - 0x20048000 0x20008600 0x2003820c 0x20008200 - 0x20038404 0x20008400 0x00020205 0xc0000780 - 0x30020005 0xc4100780 0x1500ec00 0x2101e804 + 0x20048000 0x20008610 0x20038200 0x20048204 + 0x20008400 0x20018404 0x00020005 0xc0000780 + 0x30020205 0xc4100780 0x1500ec00 0x2101e804 0xd00e0201 0xa0c00781 } } @@ -574,87 +571,90 @@ code { } } bincode { - 0xd0800205 0x00400780 0xa0000019 0x04000780 - 0xa0000215 0x04000780 0x30810dfd 0x644107c8 - 0xa0013003 0x00000000 0x30060a01 0xc4100780 - 0x10013003 0x00000280 0xa0004e05 0x04200780 - 0xa0004409 0x04200780 0x40428204 0x20018a04 - 0x30070209 0xc4100780 0x30060205 0xc4100780 - 0x20000409 0x04004780 0x30020c05 0xc4100780 - 0x2102ec0c 0x20018008 0x20000205 0x0400c780 - 0xd00e0205 0x80c00780 0x00000405 0xc0000780 - 0x04045201 0xe4204780 0x00000005 0xc0000782 - 0xd4114809 0x20000780 0x3806c1fd 0x6420c7c8 - 0xa0025003 0x00000000 0x1800c001 0x0423c780 - 0x10024003 0x00000280 0xa0004e05 0x04200780 - 0xa0004409 0x04200780 0x40428204 0x20018a04 - 0x30070209 0xc4100780 0x30060205 0xc4100780 - 0x20000405 0x04004780 0x30020c09 0xc4100780 - 0x2101ec04 0x20018404 0x20008205 0x00000007 - 0xd00e0205 0x80c00780 0x10025003 0x00000780 - 0x1000f805 0x0403c780 0x30050a09 0xc4100782 - 0x2000041d 0x040187c0 0x00020e09 0xc0000780 - 0x08055201 0xe4204780 0xa0036003 0x00000000 - 0x10036003 0x00000280 0xa0004c05 0x04200780 - 0x4001d005 0x00218780 0x00075201 0xe4204780 - 0xd01d480d 0x20000780 0xd0115009 0x20000780 - 0x1100f004 0x1d00e008 0x2101ee0c 0x2942ec04 - 0x30030205 0xac000780 0x00075401 0xe4204780 - 0x1d00e004 0x2901e004 0x00075601 0xe4204780 - 0xf0000001 0xe0000002 0x861ffe03 0x00000000 - 0xd01d5009 0x20000780 0x3807c1fd 0x6c20c7c8 - 0xa0046003 0x00000000 0x10046003 0x00000280 - 0xd01d5809 0x20000780 0x2800c005 0x0421c780 - 0x30020205 0xc4100780 0xd011a009 0x20000780 - 0x2000ca05 0x04204780 0xd00e0209 0x80c00780 - 0x1800c005 0x0423c780 0x30010405 0xec000780 - 0x00020e09 0xc0000780 0x08001201 0xe4204780 - 0xd01d5009 0x20000782 0x2000d005 0x0421c780 - 0x3801c1fd 0x6c20c7c8 0x00020209 0xc0000780 - 0xa0055003 0x00000000 0x10055003 0x00000280 - 0xd01d580d 0x20000780 0x2d07e004 0x2101f004 - 0x30020205 0xc4100780 0xd011a00d 0x20000780 - 0x2000ca05 0x04204780 0xd00e0209 0x80c00780 - 0x1c00c005 0x0423c780 0x30010405 0xec000780 - 0x08001201 0xe4204780 0xf0000001 0xe0000002 + 0xa0000011 0x04000780 0xd0800201 0x00400780 + 0x308109fd 0x644107c8 0xa0012003 0x00000000 + 0xa0000015 0x04000780 0x10012003 0x00000280 + 0xa0004e01 0x04200780 0xa0004405 0x04200780 + 0x40418000 0x20008a00 0x30050005 0xc4100780 + 0x30040001 0xc4100780 0x20008200 0x20008800 + 0x30040a05 0xc4100780 0x30020001 0xc4100780 + 0x20018804 0x2100ec00 0xd00e0001 0x80c00780 + 0x00020205 0xc0000780 0x04045201 0xe4200780 + 0x00060a05 0xc0000782 0xd4114809 0x20000780 + 0x3804c1fd 0x6420c7c8 0xa0024003 0x00000000 + 0x1800c001 0x0423c780 0x10023003 0x00000280 + 0xa0004e05 0x04200780 0xa0004409 0x04200780 + 0x40428204 0x20018a04 0x30050209 0xc4100780 + 0x30040205 0xc4100780 0x20018404 0x20018804 + 0x30020205 0xc4100780 0x2000cc05 0x04204780 + 0x20008205 0x00000007 0xd00e0205 0x80c00780 + 0x10024003 0x00000780 0x1000f805 0x0403c780 + 0x30050a09 0xc4100782 0x20000419 0x040107c0 + 0x00020c09 0xc0000780 0x08055201 0xe4204780 + 0xa0035003 0x00000000 0x10035003 0x00000280 + 0xa0004c05 0x04200780 0x4001d005 0x00218780 + 0x00075201 0xe4204780 0xd01d480d 0x20000780 + 0xd0115009 0x20000780 0x1100f004 0x1d00e008 + 0x2101ee0c 0x2942ec04 0x30030205 0xac000780 + 0x00075401 0xe4204780 0x1d00e004 0x2901e004 + 0x00075601 0xe4204780 0xf0000001 0xe0000002 0x861ffe03 0x00000000 0xd01d5009 0x20000780 - 0x2840c005 0x04200780 0x3001d005 0xac200780 - 0x307c0205 0x8c000780 0x300603fd 0x6c00c7c8 - 0xa0088003 0x00000000 0x1000f821 0x0403c780 - 0x10088003 0x00000280 0x20000025 0x04018780 - 0x20098c09 0x00000003 0x2009920d 0x00000003 - 0x20000029 0x04004780 0x0002040d 0xc0000780 - 0x00020611 0xc0000780 0x00070a09 0xc0000780 - 0xd8154809 0x20000780 0x1900e204 0x1900e60c - 0x1900e000 0x1900e408 0x4d41e204 0x4d43e60c - 0x6c00c001 0x80204780 0x6c02c405 0x8020c780 - 0x20018004 0x1900e800 0x6c00c805 0x80204780 - 0x1800ca01 0x0423c780 0x6c00ca31 0x80204780 - 0x1900ee2c 0x1900ec10 0x1900f004 0x1900f200 - 0x1900f60c 0x1900f408 0x4c0bce2d 0x00218780 - 0xd4115809 0x20000780 0x6c04cc2d 0x8022c780 - 0x1900e010 0x200b982c 0x6c01d005 0x8022c780 - 0x4c03d60d 0x00218780 0x6c00d201 0x80204780 - 0x6c02d405 0x8020c780 0x20000001 0x04004780 - 0x30040001 0xec000780 0x2040c001 0x04200784 + 0x3806c1fd 0x6c20c7c8 0xa0045003 0x00000000 + 0x10045003 0x00000280 0xd01d5809 0x20000780 + 0x2800c005 0x04218780 0x30020205 0xc4100780 + 0xd011a009 0x20000780 0x2000ca05 0x04204780 + 0xd00e0209 0x80c00780 0x1800c005 0x0423c780 + 0x30010405 0xec000780 0x00020c09 0xc0000780 + 0x08001201 0xe4204780 0xd01d5009 0x20000782 + 0x2000d005 0x04218780 0x3801c1fd 0x6c20c7c8 + 0x00020209 0xc0000780 0xa0054003 0x00000000 + 0x10054003 0x00000280 0xd01d580d 0x20000780 + 0x2d06e004 0x2101f004 0x30020205 0xc4100780 + 0xd011a00d 0x20000780 0x2000ca05 0x04204780 + 0xd00e0209 0x80c00780 0x1c00c005 0x0423c780 + 0x30010405 0xec000780 0x08001201 0xe4204780 + 0xf0000001 0xe0000002 0x861ffe03 0x00000000 + 0xd01d5009 0x20000780 0x2840c005 0x04200780 + 0x3001d005 0xac200780 0x307c0205 0x8c000780 + 0x300403fd 0x6c00c7c8 0xa008f003 0x00000000 + 0x1000f81d 0x0403c780 0x1008f003 0x00000280 + 0x30020009 0xc4100780 0x30020801 0xc4100780 + 0x20000009 0x04008780 0x20248409 0x00000003 + 0x30020205 0xc4100780 0x0000040d 0xc0000780 + 0x20248225 0x00000003 0x20248021 0x00000003 + 0x00070a09 0xc0000780 0xd8154811 0x20000780 + 0x00001009 0xc0000780 0x1000c205 0x0423c784 + 0x1000c60d 0x0423c784 0x1000c001 0x0423c784 + 0x1000c409 0x0423c784 0x4941e204 0x4943e60c + 0x6800c001 0x80204780 0x6802c405 0x8020c780 + 0x20000005 0x04004780 0x1000c801 0x0423c784 + 0x6800c805 0x80204780 0x1000ca01 0x0423c784 + 0x6800ca31 0x80204780 0x1000ce2d 0x0423c784 + 0x1000cc29 0x0423c784 0x1000d005 0x0423c784 + 0x1000d201 0x0423c784 0x1000d60d 0x0423c784 + 0x1000d409 0x0423c784 0x480bce2d 0x00218780 + 0x680acc29 0x8022c780 0x20001829 0x04028780 + 0x6801d005 0x80228780 0x4803d60d 0x00218780 + 0x6800d201 0x80204780 0x6802d405 0x8020c780 + 0xd4115809 0x20000780 0x20018004 0x1900e000 + 0x30000201 0xec000780 0x2c40c001 0x04200780 0x301f0005 0xec100780 0x30010001 0xc4100780 - 0xd0000201 0x04008780 0x20209225 0x00000003 - 0x30820001 0xac400780 0x300a13fd 0x6c0047c8 - 0x20001021 0x04000780 0xdc01000d 0x20000780 - 0xd0010011 0x20000784 0x10065003 0x00000280 - 0x00020e05 0xc0000782 0x04025201 0xe4220780 - 0xd4094809 0x20000780 0x1800d001 0x0423c780 - 0x1800f005 0x0423c780 0x2800c001 0x04200780 - 0x2800e005 0x04204780 0x20000001 0x04004780 - 0x04025201 0xe4200780 0x1900e400 0x1900ec04 - 0x2900e000 0x2901e804 0x20000001 0x04004780 - 0x307c0dfd 0x640147c8 0x04025201 0xe4200780 - 0x30000003 0x00000280 0x10004401 0x0023c780 - 0x60004e05 0x00214780 0x00020e05 0xc0000780 - 0xa0004c01 0x04200780 0x30060205 0xc4100780 - 0xd4094805 0x20000780 0x20018004 0x1500e200 - 0x30020205 0xc4100780 0x2500e008 0x2101e800 - 0xd00e0009 0xa0c00781 + 0xd0000201 0x04008780 0x20009021 0x0000000b + 0x30820001 0xac400780 0x300911fd 0x640047c8 + 0x20000e1d 0x04000780 0xdc01000d 0x20000780 + 0x10066003 0x00000280 0x00020c05 0xc0000782 + 0x04025201 0xe421c780 0xd4094809 0x20000780 + 0x1800d001 0x0423c780 0x1800f005 0x0423c780 + 0x2800c001 0x04200780 0x2800e005 0x04204780 + 0x20000001 0x04004780 0x04025201 0xe4200780 + 0x1900e400 0x1900ec04 0x2900e000 0x2901e804 + 0x20000001 0x04004780 0x307c09fd 0x640147c8 + 0x04025201 0xe4200780 0x30000003 0x00000280 + 0x10004401 0x0023c780 0x60004e05 0x00214780 + 0x00020c05 0xc0000780 0xa0004c01 0x04200780 + 0x30060205 0xc4100780 0xd4094805 0x20000780 + 0x20018004 0x1500e200 0x30020205 0xc4100780 + 0x2500e008 0x2101e800 0xd00e0009 0xa0c00781 } } code { @@ -667,143 +667,132 @@ code { segname = const segnum = 1 offset = 0 - bytes = 36 + bytes = 48 mem { - 0x0000002f 0x0000001f 0x0000007f 0x0000003f - 0xffffffff 0x00000008 0x00000020 0x00000002 - 0x0fffffff + 0x0000002f 0x00000030 0x0000001f 0x0000007f + 0x0000003f 0xffffffff 0x000000c0 0x00000008 + 0x00000020 0x00000002 0x0fffffff 0x00000034 } } bincode { - 0xa000000d 0x04000780 0x308007fd 0x644107c8 - 0xa000d003 0x00000000 0x30020609 0xc4100780 - 0x1000d003 0x00000280 0xa0004e01 0x04200780 - 0x30070005 0xc4100780 0x30060001 0xc4100780 - 0x20008200 0x2100ea00 0x20000401 0x04000780 - 0xd00e0001 0x80c00780 0x00000405 0xc0000780 - 0x04069001 0xe4200780 0x1000ce01 0x0423c782 - 0x10028005 0x00000003 0x30000211 0xc4000780 - 0x300309fd 0x6400c7c8 0xa001c003 0x00000000 - 0x1001b003 0x00000280 0xa0004e01 0x04200780 - 0x2102ee05 0x00000003 0x30010001 0xc4000780 - 0x20008800 0x20008600 0x30020001 0xc4100780 + 0xa0000005 0x04000780 0x308003fd 0x644107c8 + 0x3002020d 0xc4100780 0x60824e01 0x00604500 + 0x30020001 0xc4100500 0x2000ca01 0x04200500 + 0xd00e0001 0x80c00500 0x00000605 0xc0000500 + 0x04069001 0xe4200500 0x1000ce01 0x0423c780 + 0x10028009 0x00000003 0x30000411 0xc4000780 + 0x300109fd 0x6400c7c8 0xa0018003 0x00000000 + 0x10017003 0x00000280 0xa0004e01 0x04200780 + 0x2102ee09 0x00000003 0x30020001 0xc4000780 + 0x20008800 0x20008200 0x30020001 0xc4100780 0x2000cc01 0x04200780 0xd00e0001 0x80c00780 - 0x1001c003 0x00000780 0x1000f801 0x0403c780 - 0x00000405 0xc0000782 0x20008605 0x00000013 - 0x300109fd 0x6400c7c8 0x04001001 0xe4200780 - 0xa002c003 0x00000000 0x1002b003 0x00000280 - 0xa0004e01 0x04200780 0x2102ee05 0x00000003 - 0x30010001 0xc4000780 0x20008800 0x20008600 + 0x10018003 0x00000780 0x1000f801 0x0403c780 + 0x00000605 0xc0000782 0x20008209 0x00000013 + 0x300209fd 0x6400c7c8 0x04001001 0xe4200780 + 0xa0028003 0x00000000 0x10027003 0x00000280 + 0xa0004e01 0x04200780 0x2102ee09 0x00000003 + 0x30020001 0xc4000780 0x20008800 0x20008200 0x30020001 0xc4100780 0x2000cc01 0x04200780 0x20008001 0x00000043 0xd00e0001 0x80c00780 - 0x1002c003 0x00000780 0x1000f801 0x0403c780 - 0x00000405 0xc0000782 0x04021001 0xe4200780 + 0x10028003 0x00000780 0x1000f801 0x0403c780 + 0x00000605 0xc0000782 0x04021001 0xe4200780 0x861ffe03 0x00000000 0x307ccffd 0x6c2047c8 - 0x1000ce01 0x0423c780 0x10076003 0x00000280 - 0x308207fd 0x6440c7e8 0x308307fd 0x6440c7f8 - 0x308107fd 0x6440c7c8 0x307c07fd 0x640087d8 - 0x00000015 0x20001780 0x300007fd 0xe40007d8 - 0x10000e05 0x2440d500 0x30000205 0xc4001500 - 0x20400805 0x04005500 0x20000605 0x04005500 - 0x00020205 0xc0001500 0x1400d005 0x0423d500 - 0x1000f805 0x0403d280 0x00000405 0xc0000780 - 0x04041001 0xe4204780 0x861ffe03 0x00000000 - 0x00000405 0xc0002680 0xd414400d 0x20002680 - 0xd4104009 0x20002680 0x1c00c005 0x0423e680 - 0x2800c005 0x04206680 0x04041001 0xe4206680 - 0x861ffe03 0x00000000 0x00000405 0xc0003680 + 0x1000ce01 0x0423c780 0x10072003 0x00000280 + 0x308303fd 0x6440c7e8 0x308403fd 0x6440c7f8 + 0x308203fd 0x6440c7c8 0x307c03fd 0x640087d8 + 0x00000015 0x20001780 0x300003fd 0xe40007d8 + 0x10001209 0x2440d500 0x30000409 0xc4001500 + 0x20400809 0x04009500 0x20000209 0x04009500 + 0x00020405 0xc0001500 0x1400d009 0x0423d500 + 0x1000f809 0x0403d280 0x00000605 0xc0000780 + 0x04041001 0xe4208780 0x861ffe03 0x00000000 + 0x00000605 0xc0002680 0xd414400d 0x20002680 + 0xd4104009 0x20002680 0x1c00c009 0x0423e680 + 0x2800c009 0x0420a680 0x04041001 0xe420a680 + 0x861ffe03 0x00000000 0x00000605 0xc0003680 0xd412400d 0x20003680 0xd4104009 0x20003680 - 0x1c00c005 0x0423f680 0x2800c005 0x04207680 - 0x04041001 0xe4207680 0x861ffe03 0x00000000 - 0x00000405 0xc0000680 0xd411400d 0x20000680 - 0xd4104009 0x20000680 0x1c00c005 0x0423c680 - 0x2800c005 0x04204680 0x04041001 0xe4204680 - 0x861ffe03 0x00000000 0xa0066003 0x00000000 - 0x10066003 0x00000100 0x00000405 0xc0000780 - 0xd4104009 0x20000780 0x1800e005 0x0423c780 - 0x2800c005 0x04204780 0x04041001 0xe4204780 - 0x1900f004 0x2901e004 0x04041001 0xe4204780 - 0x1900e804 0x2901e004 0x04041001 0xe4204780 - 0x1900e404 0x2901e004 0x04041001 0xe4204780 - 0x1900e204 0x2901e004 0x04041001 0xe4204780 - 0xf0000001 0xe0000002 0xa0070003 0x00000000 - 0x00000a01 0xa00007d0 0x10070003 0x00001100 - 0x10048005 0x00000003 0xd0104005 0x20000780 - 0x30000205 0xc4000780 0x00020009 0xc0000780 - 0x2400c005 0x04204780 0x08061001 0xe4204780 + 0x1c00c009 0x0423f680 0x2800c009 0x0420b680 + 0x04041001 0xe420b680 0x861ffe03 0x00000000 + 0x00000605 0xc0000680 0xd411400d 0x20000680 + 0xd4104009 0x20000680 0x1c00c009 0x0423c680 + 0x2800c009 0x04208680 0x04041001 0xe4208680 + 0x861ffe03 0x00000000 0xa0062003 0x00000000 + 0x10062003 0x00000100 0x00000605 0xc0000780 + 0xd4104009 0x20000780 0x1800e009 0x0423c780 + 0x2800c009 0x04208780 0x04041001 0xe4208780 + 0x1900f008 0x2902e008 0x04041001 0xe4208780 + 0x1900e808 0x2902e008 0x04041001 0xe4208780 + 0x1900e408 0x2902e008 0x04041001 0xe4208780 + 0x1900e208 0x2902e008 0x04041001 0xe4208780 + 0xf0000001 0xe0000002 0xa006c003 0x00000000 + 0x00000a01 0xa00007d0 0x1006c003 0x00001100 + 0x10048009 0x00000003 0xd0104005 0x20000780 + 0x30000409 0xc4000780 0x00020009 0xc0000780 + 0x2400c009 0x04208780 0x08061001 0xe4208780 0xf0000001 0xe0000002 0x861ffe03 0x00000000 - 0x203f8001 0x0fffffff 0x308401fd 0x6c4147d8 - 0x10037003 0x00001280 0x10077003 0x00000780 - 0x308107fd 0x6440c7c8 0xa00eb003 0x00000000 - 0x100eb003 0x00000100 0x00000405 0xc0000780 - 0x3003cffd 0x642187c8 0x04065001 0xe420c780 - 0x00000405 0xc0000500 0x10001001 0x2440c500 - 0x04061001 0xe4200500 0x10001001 0x2440c500 - 0x00000405 0xc0000280 0xd4184005 0x20000280 - 0x1400c001 0x0423c280 0x00000405 0xc0000780 - 0x20108605 0x00000033 0x00020209 0xc0000780 - 0x20088605 0x00000003 0x3800c1fd 0x6c2047c8 - 0x10000605 0x0403c500 0x0002020d 0xc0000780 - 0xdc19400d 0x20000780 0x3800c005 0xac200780 - 0x1c00c001 0x0423c780 0x200c8609 0x00000033 - 0x04065001 0xe4200780 0x00020409 0xc0000780 - 0x04061001 0xe4204780 0x20048601 0x00000003 - 0x3801c1fd 0x6c2047c8 0x10000601 0x0403c500 - 0x0002000d 0xc0000780 0xdc19400d 0x20000780 - 0x3801c005 0xac200780 0x1c00c001 0x0423c780 - 0x200a8609 0x00000033 0x04065001 0xe4200780 - 0x00020409 0xc0000780 0x04061001 0xe4204780 - 0x20028601 0x00000003 0x3801c1fd 0x6c2047c8 - 0x10000601 0x0403c500 0x0002000d 0xc0000780 - 0xdc19400d 0x20000780 0x3801c005 0xac200780 - 0x1c00c001 0x0423c780 0x20098609 0x00000033 - 0x04065001 0xe4200780 0x00020409 0xc0000780 - 0x04061001 0xe4204780 0x20018601 0x00000003 - 0x3801c1fd 0x6c2047c8 0x10000601 0x0403c500 - 0x0002000d 0xc0000780 0xdc19400d 0x20000780 - 0x3801c015 0xac200780 0x1c00c001 0x0423c780 - 0x307c0605 0x640087d0 0x04065001 0xe4200780 - 0xa00003fd 0x0c0147c8 0xa00bc003 0x00000000 - 0x04061001 0xe4214780 0x100bc003 0x00001100 - 0xa0004e01 0x04200780 0x30070005 0xc4100780 - 0x30060001 0xc4100780 0x20000201 0x04000780 - 0xd0194005 0x20000780 0x2100ea04 0x1500e000 - 0x20348205 0x00000003 0xd00e0201 0xa0c00780 - 0xf0000001 0xe0000002 0x100eb003 0x00000100 - 0xd01a6805 0x20000780 0x1400cc01 0x0423c780 - 0x3485c1fd 0x6c6147c8 0x2440c201 0x04200780 - 0x100cc003 0x00000280 0xd01a4005 0x20000780 - 0x1400c005 0x0423c780 0x40030009 0x00000780 - 0x60020209 0x00008780 0x30100409 0xc4100780 - 0x60020001 0x00008780 0x20000001 0x04014780 - 0x20068001 0x00000003 0x100e5003 0x00000780 - 0xd01a6805 0x20000780 0x3486c1fd 0x6c6147c8 - 0x100dc003 0x00000280 0xd01a4005 0x20000780 - 0x1400c009 0x0423c780 0x1400c605 0x0423c780 - 0x4005001c 0x40040618 0x6004021d 0x0001c780 - 0x60050419 0x00018780 0x30100e1d 0xc4100780 - 0x30100c19 0xc4100780 0x6004001d 0x0001c780 - 0x60040401 0x00018780 0x20058e04 0x20018000 - 0x200f8009 0x00000003 0x100e4003 0x00000780 - 0xd01a6805 0x20000780 0x1400c405 0x0423c780 - 0x40030009 0x00000780 0x60020215 0x00008780 - 0x10000009 0x0403c780 0x347cc1fd 0x6c2147c8 - 0x30100a15 0xc4100780 0x60020009 0x00014280 - 0x10000401 0x0403c780 0xa0004e05 0x04200780 - 0x30070209 0xc4100780 0x30060205 0xc4100780 - 0x20018404 0x2101ea04 0x20108205 0x00000003 - 0xd00e0201 0xa0c00780 0xf0000001 0xe0000002 - 0x861ffe03 0x00000000 0xd0194005 0x20000780 - 0x1400c001 0x0423c780 0x300007fd 0xe40007c8 - 0x30000003 0x00000280 0xa0004e05 0x04200780 - 0x2102ee01 0x00000003 0xd0194005 0x20000780 - 0x10028015 0x00000003 0x30000209 0xc4000780 - 0x1500e000 0x20028808 0x30000a11 0xc4000780 - 0x1100ee00 0x20448408 0x30000201 0xc4000780 - 0x20028604 0x20008600 0x30020205 0xc4100780 - 0x30020009 0xc4100780 0x2000cc01 0x04204780 - 0xd00e0001 0x80c00780 0x2000c805 0x04208780 - 0xd00e0201 0xa0c00781 + 0x203f8001 0x0fffffff 0x308501fd 0x6c4147d8 + 0x10033003 0x00001280 0x10073003 0x00000780 + 0x308203fd 0x6440c7c8 0xa00d6003 0x00000000 + 0x100d6003 0x00000100 0x00000605 0xc0000780 + 0x3001cffd 0x642187c8 0x04065001 0xe4204780 + 0x00000605 0xc0000500 0x10001401 0x2440c500 + 0x04061001 0xe4200500 0x10001401 0x2440c500 + 0x00000605 0xc0000280 0xd4184005 0x20000280 + 0x1400c001 0x0423c280 0x00000605 0xc0000780 + 0xd4184809 0x20000780 0x20208615 0x000000cb + 0x20008609 0x000000cf 0x3800cffd 0x6c2047c8 + 0x10000a09 0x0403c500 0x0000040d 0xc0000780 + 0x3800ce09 0xac200780 0x1c00c001 0x0423c780 + 0x04065001 0xe4200780 0x04061001 0xe4208780 + 0x20308601 0x000000cb 0x3802c7fd 0x6c2047c8 + 0x10000a01 0x0403c500 0x0000000d 0xc0000780 + 0x3802c609 0xac200780 0x1c00c001 0x0423c780 + 0x04065001 0xe4200780 0x04061001 0xe4208780 + 0x20288601 0x000000cb 0x3802c3fd 0x6c2047c8 + 0x10000a01 0x0403c500 0x0000000d 0xc0000780 + 0x3802c209 0xac200780 0x1c00c001 0x0423c780 + 0x04065001 0xe4200780 0x04061001 0xe4208780 + 0x20248601 0x000000cb 0x3802c1fd 0x6c2047c8 + 0x10000a01 0x0403c500 0x0000000d 0xc0000780 + 0x3802c015 0xac200780 0x1c00c001 0x0423c780 + 0x307c0209 0x640087d0 0x04065001 0xe4200780 + 0xa00005fd 0x0c0147c8 0x04061001 0xe4214780 + 0x1000ca01 0x0423d680 0xd0194005 0x20000780 + 0x608c4e01 0x00601680 0x1400c009 0x0423d680 + 0x21000001 0x0442d680 0xd00e0009 0xa0c01680 + 0x100d6003 0x00000100 0xd01a6805 0x20000780 + 0x1400cc01 0x0423c780 0x3487c1fd 0x6c6147c8 + 0x2440c201 0x04200780 0x100b9003 0x00000280 + 0xd01a4005 0x20000780 0x1400c009 0x0423c780 + 0x4005000d 0x00000780 0x6004020d 0x0000c780 + 0x3010060d 0xc4100780 0x60040001 0x0000c780 + 0x20000001 0x04014780 0x20068001 0x00000003 + 0x100d2003 0x00000780 0xd01a6805 0x20000780 + 0x3488c1fd 0x6c6147c8 0x100c9003 0x00000280 + 0xd01a4005 0x20000780 0x1400c00d 0x0423c780 + 0x1400c609 0x0423c780 0x4007001c 0x40060a18 + 0x6006021d 0x0001c780 0x60070819 0x00018780 + 0x30100e1d 0xc4100780 0x30100c19 0xc4100780 + 0x6006001d 0x0001c780 0x60060801 0x00018780 + 0x20058e08 0x20028000 0x200f800d 0x00000003 + 0x100d1003 0x00000780 0xd01a6805 0x20000780 + 0x1400c409 0x0423c780 0x4005000d 0x00000780 + 0x60040215 0x0000c780 0x1000000d 0x0403c780 + 0x347cc1fd 0x6c2147c8 0x30100a15 0xc4100780 + 0x6004000d 0x00014280 0x10000601 0x0403c780 + 0x1000ca09 0x0423c780 0x61002e09 0x0000000f + 0x20108409 0x00000003 0xd00e0401 0xa0c00780 + 0xf0000001 0xe0000002 0x861ffe03 0x00000000 + 0xd0194005 0x20000780 0x1400c001 0x0423c780 + 0x300003fd 0xe40007c8 0x30000003 0x00000280 + 0xa0004e09 0x04200780 0x2102ee01 0x00000003 + 0xd0194005 0x20000780 0x10028015 0x00000003 + 0x3000040d 0xc4000780 0x1500e000 0x2003880c + 0x30000a11 0xc4000780 0x1100ee00 0x2044860c + 0x30000409 0xc4000780 0x20038200 0x20028204 + 0x30020001 0xc4100780 0x30020205 0xc4100780 + 0x2000cc01 0x04200780 0xd00e0001 0x80c00780 + 0x2000c805 0x04204780 0xd00e0201 0xa0c00781 } } code { @@ -822,91 +811,93 @@ code { } } bincode { - 0xd0800205 0x00400780 0xa0000019 0x04000780 - 0xa0000215 0x04000780 0x30810dfd 0x644107c8 - 0xa0013003 0x00000000 0x30060a01 0xc4100780 - 0x10013003 0x00000280 0xa0004e05 0x04200780 - 0xa0004409 0x04200780 0x40428204 0x20018a04 - 0x30070209 0xc4100780 0x30060205 0xc4100780 - 0x20000409 0x04004780 0x30020c05 0xc4100780 - 0x2102ec0c 0x20018008 0x20000205 0x0400c780 - 0xd00e0205 0x80c00780 0x00000405 0xc0000780 - 0x04045201 0xe4204780 0x00000005 0xc0000782 - 0xd4114809 0x20000780 0x3806c1fd 0x6420c7c8 - 0xa0025003 0x00000000 0x1800c001 0x0423c780 - 0x10024003 0x00000280 0xa0004e05 0x04200780 - 0xa0004409 0x04200780 0x40428204 0x20018a04 - 0x30070209 0xc4100780 0x30060205 0xc4100780 - 0x20000405 0x04004780 0x30020c09 0xc4100780 - 0x2101ec04 0x20018404 0x20008205 0x00000007 - 0xd00e0205 0x80c00780 0x10025003 0x00000780 - 0x1000f805 0x0403c780 0x30050a09 0xc4100782 - 0x2000041d 0x040187c0 0x00020e09 0xc0000780 - 0x08055201 0xe4204780 0xa0036003 0x00000000 - 0x10036003 0x00000280 0xa0004c05 0x04200780 - 0x4001d005 0x00218780 0x00075201 0xe4204780 - 0xd01d480d 0x20000780 0xd0115009 0x20000780 - 0x1100f004 0x1d00e008 0x2101ee0c 0x2942ec04 - 0x30030205 0xac000780 0x00075401 0xe4204780 - 0x1d00e004 0x2901e004 0x00075601 0xe4204780 - 0xf0000001 0xe0000002 0x861ffe03 0x00000000 - 0xd01d5009 0x20000780 0x3807c1fd 0x6c20c7c8 - 0xa0046003 0x00000000 0x10046003 0x00000280 - 0xd01d5809 0x20000780 0x2800c005 0x0421c780 - 0x30020205 0xc4100780 0xd011a009 0x20000780 - 0x2000ca05 0x04204780 0xd00e0209 0x80c00780 - 0x1800c005 0x0423c780 0x30010405 0xec000780 - 0x00020e09 0xc0000780 0x08001201 0xe4204780 - 0xd01d5009 0x20000782 0x2000d005 0x0421c780 - 0x3801c1fd 0x6c20c7c8 0x00020209 0xc0000780 - 0xa0055003 0x00000000 0x10055003 0x00000280 - 0xd01d580d 0x20000780 0x2d07e004 0x2101f004 - 0x30020205 0xc4100780 0xd011a00d 0x20000780 - 0x2000ca05 0x04204780 0xd00e0209 0x80c00780 - 0x1c00c005 0x0423c780 0x30010405 0xec000780 - 0x08001201 0xe4204780 0xf0000001 0xe0000002 + 0xa0000011 0x04000780 0xd0800201 0x00400780 + 0x308109fd 0x644107c8 0xa0012003 0x00000000 + 0xa0000015 0x04000780 0x10012003 0x00000280 + 0xa0004e01 0x04200780 0xa0004405 0x04200780 + 0x40418000 0x20008a00 0x30050005 0xc4100780 + 0x30040001 0xc4100780 0x20008200 0x20008800 + 0x30040a05 0xc4100780 0x30020001 0xc4100780 + 0x20018804 0x2100ec00 0xd00e0001 0x80c00780 + 0x00020205 0xc0000780 0x04045201 0xe4200780 + 0x00060a05 0xc0000782 0xd4114809 0x20000780 + 0x3804c1fd 0x6420c7c8 0xa0024003 0x00000000 + 0x1800c001 0x0423c780 0x10023003 0x00000280 + 0xa0004e05 0x04200780 0xa0004409 0x04200780 + 0x40428204 0x20018a04 0x30050209 0xc4100780 + 0x30040205 0xc4100780 0x20018404 0x20018804 + 0x30020205 0xc4100780 0x2000cc05 0x04204780 + 0x20008205 0x00000007 0xd00e0205 0x80c00780 + 0x10024003 0x00000780 0x1000f805 0x0403c780 + 0x30050a09 0xc4100782 0x20000419 0x040107c0 + 0x00020c09 0xc0000780 0x08055201 0xe4204780 + 0xa0035003 0x00000000 0x10035003 0x00000280 + 0xa0004c05 0x04200780 0x4001d005 0x00218780 + 0x00075201 0xe4204780 0xd01d480d 0x20000780 + 0xd0115009 0x20000780 0x1100f004 0x1d00e008 + 0x2101ee0c 0x2942ec04 0x30030205 0xac000780 + 0x00075401 0xe4204780 0x1d00e004 0x2901e004 + 0x00075601 0xe4204780 0xf0000001 0xe0000002 0x861ffe03 0x00000000 0xd01d5009 0x20000780 - 0x2840c005 0x04200780 0x3001d005 0xac200780 - 0x307c0205 0x8c000780 0x300603fd 0x6c00c7c8 - 0xa0082003 0x00000000 0x1000f821 0x0403c780 - 0x10082003 0x00000280 0x20000025 0x04018780 - 0x20098c09 0x00000003 0x2009920d 0x00000003 - 0x20000029 0x04004780 0x0002040d 0xc0000780 - 0x00020611 0xc0000780 0x00070a09 0xc0000780 - 0xd8154809 0x20000780 0x1900e204 0x1900e000 - 0x4c01c205 0x00218780 0x6c00c031 0x80204780 - 0x1900e62c 0x1900e410 0x1900e804 0x1900ea00 - 0x1900ee0c 0x1900ec08 0x4c0bc62d 0x00218780 - 0xd4115809 0x20000780 0x6c04c42d 0x8022c780 - 0x1900e010 0x200b982c 0x6c01c805 0x8022c780 - 0x4c03ce0d 0x00218780 0x6c00ca01 0x80204780 - 0x6c02cc05 0x8020c780 0x20000001 0x04004780 - 0x30040001 0xec000780 0x2040c001 0x04200784 + 0x3806c1fd 0x6c20c7c8 0xa0045003 0x00000000 + 0x10045003 0x00000280 0xd01d5809 0x20000780 + 0x2800c005 0x04218780 0x30020205 0xc4100780 + 0xd011a009 0x20000780 0x2000ca05 0x04204780 + 0xd00e0209 0x80c00780 0x1800c005 0x0423c780 + 0x30010405 0xec000780 0x00020c09 0xc0000780 + 0x08001201 0xe4204780 0xd01d5009 0x20000782 + 0x2000d005 0x04218780 0x3801c1fd 0x6c20c7c8 + 0x00020209 0xc0000780 0xa0054003 0x00000000 + 0x10054003 0x00000280 0xd01d580d 0x20000780 + 0x2d06e004 0x2101f004 0x30020205 0xc4100780 + 0xd011a00d 0x20000780 0x2000ca05 0x04204780 + 0xd00e0209 0x80c00780 0x1c00c005 0x0423c780 + 0x30010405 0xec000780 0x08001201 0xe4204780 + 0xf0000001 0xe0000002 0x861ffe03 0x00000000 + 0xd01d5009 0x20000780 0x2840c005 0x04200780 + 0x3001d005 0xac200780 0x307c0205 0x8c000780 + 0x300403fd 0x6c00c7c8 0xa0087003 0x00000000 + 0x1000f825 0x0403c780 0x10087003 0x00000280 + 0x30020009 0xc4100780 0x30020801 0xc4100780 + 0x20000009 0x04008780 0x20248409 0x00000003 + 0x30020205 0xc4100780 0x0000040d 0xc0000780 + 0x2024822d 0x00000003 0x20248029 0x00000003 + 0x00070a09 0xc0000780 0xd8154811 0x20000780 + 0x00001409 0xc0000780 0x1000c205 0x0423c784 + 0x1000c001 0x0423c784 0x4801c205 0x00218780 + 0x6800c031 0x80204780 0x1000c621 0x0423c784 + 0x1000c41d 0x0423c784 0x1000c805 0x0423c784 + 0x1000ca01 0x0423c784 0x1000ce0d 0x0423c784 + 0x1000cc09 0x0423c784 0x4808c621 0x00218780 + 0x6807c41d 0x80220780 0x2000181d 0x0401c780 + 0x6801c805 0x8021c780 0x4803ce0d 0x00218780 + 0x6800ca01 0x80204780 0x6802cc05 0x8020c780 + 0xd4115809 0x20000780 0x20018004 0x1900e000 + 0x30000201 0xec000780 0x2c40c001 0x04200780 0x301f0005 0xec100780 0x30010001 0xc4100780 - 0xd0000201 0x04008780 0x20209225 0x00000003 - 0x30820001 0xac400780 0x300a13fd 0x6c0047c8 - 0x20001021 0x04000780 0xdc01000d 0x20000780 - 0xd0010011 0x20000784 0x10065003 0x00000280 - 0x00020e05 0xc0000782 0x04025201 0xe4220780 - 0xd4094809 0x20000780 0x1800d001 0x0423c780 - 0x1800f005 0x0423c780 0x2800c001 0x04200780 - 0x2800e005 0x04204780 0x20000001 0x04004780 - 0x04025201 0xe4200780 0x1900e400 0x1900ec04 - 0x2900e000 0x2901e804 0x20000001 0x04004780 - 0x307c0dfd 0x640147c8 0x04025201 0xe4200780 - 0x30000003 0x00000280 0x10004401 0x0023c780 - 0x60004e05 0x00214780 0x00020e05 0xc0000780 - 0xa0004c01 0x04200780 0x30060205 0xc4100780 - 0xd4094805 0x20000780 0x20018004 0x1500e200 - 0x30020205 0xc4100780 0x2500e008 0x2101e800 - 0xd00e0009 0xa0c00781 + 0xd0000201 0x04008780 0x20009429 0x0000000b + 0x30820001 0xac400780 0x300b15fd 0x640047c8 + 0x20001225 0x04000780 0xdc01000d 0x20000780 + 0x10066003 0x00000280 0x00020c05 0xc0000782 + 0x04025201 0xe4224780 0xd4094809 0x20000780 + 0x1800d001 0x0423c780 0x1800f005 0x0423c780 + 0x2800c001 0x04200780 0x2800e005 0x04204780 + 0x20000001 0x04004780 0x04025201 0xe4200780 + 0x1900e400 0x1900ec04 0x2900e000 0x2901e804 + 0x20000001 0x04004780 0x307c09fd 0x640147c8 + 0x04025201 0xe4200780 0x30000003 0x00000280 + 0x10004401 0x0023c780 0x60004e05 0x00214780 + 0x00020c05 0xc0000780 0xa0004c01 0x04200780 + 0x30060205 0xc4100780 0xd4094805 0x20000780 + 0x20018004 0x1500e200 0x30020205 0xc4100780 + 0x2500e008 0x2101e800 0xd00e0009 0xa0c00781 } } code { name = cudaEstimateResidual lmem = 0 smem = 3748 - reg = 12 + reg = 11 bar = 1 const { segname = const @@ -919,83 +910,84 @@ code { } } bincode { - 0xd0800205 0x00400780 0xa0000019 0x04000780 - 0xa0000211 0x04000780 0x30810dfd 0x644107c8 - 0xa0015003 0x00000000 0xa0004405 0x04200780 - 0x30060815 0xc4100780 0x10015003 0x00000280 - 0x40034e01 0x00200780 0x30100001 0xc4100780 - 0x60024e01 0x00200780 0x20000001 0x04010780 - 0x30070009 0xc4100780 0x30060001 0xc4100780 - 0x20000409 0x04000780 0x30020c01 0xc4100780 - 0x2102ec0c 0x20008a08 0x20000001 0x0400c780 - 0xd00e0001 0x80c00780 0x00000405 0xc0000780 - 0x04045201 0xe4200780 0xf0000001 0xe0000002 - 0x861ffe03 0x00000000 0xa0004c09 0x04200780 - 0x1000d001 0x0423c780 0x4004020d 0x00000780 - 0x3010060d 0xc4100780 0x6004000d 0x0000c780 - 0x1000d001 0x0423c780 0xd0118005 0x20000780 - 0x2100ee00 0x2543e01c 0x30050821 0xc4100780 - 0x3007001d 0xac000780 0x20001021 0x04018780 - 0x30080ffd 0x6c00c7c8 0xa002e003 0x00000000 - 0x1002d003 0x00000280 0xd0115005 0x20000780 - 0x2503e000 0x20009000 0x30020001 0xc4100780 - 0x2000ca01 0x04200780 0xd00e0025 0x80c00780 - 0x1400d401 0x0423c780 0x30001201 0xec000780 - 0x1002e003 0x00000780 0x1000f801 0x0403c780 - 0x00021005 0xc0000782 0x308211fd 0x6c4107c8 - 0x04001201 0xe4200780 0xa0043003 0x00000000 - 0x10043003 0x00000280 0x2000d001 0x04220780 - 0x300701fd 0x6c0187c8 0x00020009 0xc0000780 - 0xa0042003 0x00000000 0x10041003 0x00000280 - 0xd011500d 0x20000780 0x2108f020 0x2d03e000 - 0x20000001 0x04020780 0x30020001 0xc4100780 - 0x2000ca01 0x04200780 0xd00e000d 0x80c00780 - 0x1c00d401 0x0423c780 0x30000601 0xec000780 - 0x10042003 0x00000780 0x1000f801 0x0403c780 - 0x08001201 0xe4200782 0xf0000001 0xe0000002 - 0x861ffe03 0x00000000 0x04025201 0xe43f0780 - 0x00000a09 0xc0000780 0xd8114809 0x20000780 - 0x3806c1fd 0x6420c7c8 0xa0058003 0x00000000 - 0x10057003 0x00000280 0x40034e01 0x00200780 + 0xa0000011 0x04000780 0xd0800201 0x00400780 + 0x308109fd 0x644107c8 0xa0014003 0x00000000 + 0xa0004405 0x04200780 0xa000000d 0x04000780 + 0x10014003 0x00000280 0x40034e01 0x00200780 0x30100001 0xc4100780 0x60024e01 0x00200780 - 0x20000001 0x04010780 0x3007000d 0xc4100780 - 0x30060001 0xc4100780 0x2000060d 0x04000780 - 0x30020c01 0xc4100780 0x2103ec0c 0x20038000 - 0x20008001 0x00000007 0xd00e0001 0x80c00780 - 0x10058003 0x00000780 0x1000f801 0x0403c780 - 0x04055201 0xe4200782 0x00000a09 0xc0000780 - 0xd8117009 0x20000780 0x3883c001 0x6c608780 - 0xd0000221 0x04000780 0x300111fd 0x640187c8 - 0xa0089003 0x00000000 0x10089003 0x00000280 - 0x00000a09 0xc0000780 0xd8114809 0x20000780 - 0x30051001 0xc4100780 0x3900e00d 0x00000003 - 0x20000c01 0x04000780 0x307c07fd 0x6c0187c8 - 0xa0076003 0x00000000 0x1000f829 0x0403c780 - 0x2800c025 0x04200780 0x10076003 0x00000280 - 0x3007082d 0xc4100780 0x2009800d 0x00000003 - 0x2024962d 0x00000003 0x00020609 0xc0000780 - 0x0000160d 0xc0000780 0xdc150011 0x20000780 - 0x1000c00d 0x0423c784 0x20018001 0x00000003 - 0x6a03c229 0x80228780 0x300901fd 0x6c0147c8 - 0xdc00080d 0x20000780 0x1006f003 0x00000280 - 0x00000a09 0xc0000782 0xd8115809 0x20000780 - 0x1800c001 0x0423c780 0x30001401 0xec000780 - 0x00021209 0xc0000780 0x2840d20d 0x04200780 - 0x301f0601 0xec100780 0x30010629 0xc4100780 - 0x30090e0d 0x6c010780 0xd4094809 0x20000780 - 0xd00a0025 0x04008780 0xa000060d 0x2c014780 - 0x1800c001 0x0423c780 0x30841225 0xac400780 - 0x20019021 0x00000003 0x60090601 0x80000780 - 0x300111fd 0x640147c8 0x04025201 0xe4200780 - 0x10060003 0x00000280 0xd4094809 0x20000782 - 0x1800d001 0x0423c780 0x1800f00d 0x0423c780 - 0x2800c001 0x04200780 0x2800e00d 0x0420c780 - 0x20000001 0x0400c780 0x04025201 0xe4200780 - 0x1900e400 0x1900ec0c 0x2900e000 0x2903e80c - 0x20000001 0x0400c780 0x307c0dfd 0x640147c8 + 0x20000601 0x04000780 0x30050009 0xc4100780 + 0x30040001 0xc4100780 0x20008400 0x20008808 + 0x30040601 0xc4100780 0x30020415 0xc4100780 + 0x20008808 0x2105ec00 0xd00e0001 0x80c00780 + 0x00020405 0xc0000780 0x04045201 0xe4200780 + 0xf0000001 0xe0000002 0x861ffe03 0x00000000 + 0xa0004c09 0x04200780 0x1000d001 0x0423c780 + 0x40040215 0x00000780 0x30100a15 0xc4100780 + 0x60040019 0x00014780 0x1000d001 0x0423c780 + 0xd0118005 0x20000780 0x2100ee00 0x2546e014 + 0x3005061d 0xc4100780 0x30050015 0xac000780 + 0x20000e1d 0x04010780 0x30070bfd 0x6c00c7c8 + 0xa002d003 0x00000000 0x1002c003 0x00000280 + 0xd0115005 0x20000780 0x2506e000 0x20008e00 + 0x30020001 0xc4100780 0x2000ca01 0x04200780 + 0xd00e0021 0x80c00780 0x1400d401 0x0423c780 + 0x30001001 0xec000780 0x1002d003 0x00000780 + 0x1000f801 0x0403c780 0x00020e05 0xc0000782 + 0x30820ffd 0x6c4107c8 0x04001201 0xe4200780 + 0xa0042003 0x00000000 0x10042003 0x00000280 + 0x2000d001 0x0421c780 0x300501fd 0x6c0187c8 + 0x00020009 0xc0000780 0xa0041003 0x00000000 + 0x10040003 0x00000280 0xd011500d 0x20000780 + 0x2107f01c 0x2d06e000 0x20000001 0x0401c780 + 0x30020001 0xc4100780 0x2000ca01 0x04200780 + 0xd00e0019 0x80c00780 0x1c00d401 0x0423c780 + 0x30000c01 0xec000780 0x10041003 0x00000780 + 0x1000f801 0x0403c780 0x08001201 0xe4200782 + 0xf0000001 0xe0000002 0x861ffe03 0x00000000 + 0x00060609 0xc0000780 0x04025201 0xe43f0780 + 0xd811480d 0x20000780 0x3c04c1fd 0x6420c7c8 + 0xa0057003 0x00000000 0x10056003 0x00000280 + 0x40034e01 0x00200780 0x30100001 0xc4100780 + 0x60024e01 0x00200780 0x20000001 0x0400c780 + 0x30050019 0xc4100780 0x30040001 0xc4100780 + 0x20008c00 0x20008800 0x30020001 0xc4100780 + 0x2000cc01 0x04200780 0x20008001 0x00000007 + 0xd00e0001 0x80c00780 0x10057003 0x00000780 + 0x1000f801 0x0403c780 0x04055201 0xe4200782 + 0xd811700d 0x20000780 0x3c83c001 0x6c608780 + 0xd0000219 0x04000780 0x30010dfd 0x640187c8 + 0xa008b003 0x00000000 0x1008b003 0x00000280 + 0xd811480d 0x20000780 0x30050c01 0xc4100780 + 0x3d00e01d 0x00000003 0x20000801 0x04000780 + 0x307c0ffd 0x6c0187c8 0xa0079003 0x00000000 + 0x1000f81d 0x0403c780 0x2c00c021 0x04200780 + 0x10077003 0x00000280 0x30070625 0xc4100780 + 0x20249225 0x00000003 0x30020029 0xc4100780 + 0x30021001 0xc4100780 0x0000120d 0xc0000780 + 0x20249429 0x00000003 0x20248025 0x00000003 + 0xdc150011 0x20000780 0x1000c001 0x0423c784 + 0x00001411 0xc0000780 0x20049429 0x00000003 + 0x300915fd 0x640147c8 0x6000c01d 0x8021c784 + 0xdc00080d 0x20000780 0x1006e003 0x00000280 + 0x10079003 0x00000780 0x30021001 0xc4100780 + 0x20248025 0x00000003 0xd811580d 0x20000782 + 0x1c00c001 0x0423c780 0x0000120d 0xc0000780 + 0x30000e01 0xec000780 0x2c40c001 0x04200780 + 0x301f001d 0xec100780 0x30010025 0xc4100780 + 0x30080a01 0x6c010780 0xd409480d 0x20000780 + 0xd0090e21 0x04008780 0xa000001d 0x2c014780 + 0x1c00c001 0x0423c780 0x30841021 0xac400780 + 0x20018c19 0x00000003 0x60080e01 0x80000780 + 0x30010dfd 0x640147c8 0x04025201 0xe4200780 + 0x1005e003 0x00000280 0xd4094809 0x20000782 + 0x1800d001 0x0423c780 0x1800f015 0x0423c780 + 0x2800c001 0x04200780 0x2800e015 0x04214780 + 0x20000001 0x04014780 0x04025201 0xe4200780 + 0x1900e400 0x1900ec14 0x2900e000 0x2905e814 + 0x20000001 0x04014780 0x307c09fd 0x640147c8 0x04025201 0xe4200780 0x30000003 0x00000280 0x40034e01 0x00200780 0x30100001 0xc4100780 - 0x60024e01 0x00200780 0x20000001 0x04010780 + 0x60024e01 0x00200780 0x20000001 0x0400c780 0x30060001 0xc4100780 0xd4094805 0x20000780 0x20008404 0x1500e200 0x30020205 0xc4100780 0x2500e008 0x2101e800 0xd00e0009 0xa0c00781 @@ -1005,96 +997,93 @@ code { name = cudaCalcPartition16 lmem = 0 smem = 1388 - reg = 9 + reg = 10 bar = 1 const { segname = const segnum = 1 offset = 0 - bytes = 24 + bytes = 28 mem { - 0x000003ff 0x0000002f 0x0000001f 0x000fffff - 0x0000000e 0x0000000f + 0x000003ff 0x0000002f 0x00000030 0x0000001f + 0x000fffff 0x0000000e 0x0000000f } } bincode { 0x10000005 0x0403c780 0xd0800601 0x00400780 - 0xa0000001 0x04000780 0xa0000409 0x04000780 - 0x30040005 0xc4100780 0x2000040d 0x04004780 - 0x308107fd 0x644107c8 0xa0012003 0x00000000 - 0x30020619 0xc4100780 0x10012003 0x00000280 - 0xa0004e05 0x04200780 0x30070211 0xc4100780 - 0x30060205 0xc4100780 0x20018804 0x2101ee04 - 0x20000c05 0x04004780 0xd00e0205 0x80c00780 - 0x00000c05 0xc0000780 0x04025601 0xe4204780 + 0xa0000001 0x04000780 0xa0000411 0x04000780 + 0x30040005 0xc4100780 0x20000805 0x04004780 + 0x308103fd 0x644107c8 0x60844e09 0x00604500 + 0x30020409 0xc4100500 0x2000ce09 0x04208500 + 0xd00e0409 0x80c00500 0x00020205 0xc0000500 + 0x04025601 0xe4208500 0x861ffe03 0x00000000 + 0xa0004c15 0x04200780 0x30080a19 0xc4100780 + 0x308303fd 0x6c4107c8 0xa0026003 0x00000000 + 0x20000c0d 0x04004780 0x10026003 0x00000280 + 0xd0095805 0x20000780 0x2400c009 0x04204780 + 0x30020609 0xac000780 0x308305fd 0x6c40c7c8 + 0xa0024003 0x00000000 0x10023003 0x00000280 + 0xd0096005 0x20000780 0x2400c009 0x0420c780 + 0x30020409 0xc4100780 0x2000cc09 0x04208780 + 0x20008409 0x0ffffffb 0xd00e041d 0x80c00780 + 0x1400d409 0x0423c780 0x30020e09 0xec000780 + 0x10024003 0x00000780 0x1000f809 0x0403c780 + 0x00020205 0xc0000782 0x04001601 0xe4208780 + 0xd0096005 0x20000782 0x2400c009 0x0420c780 + 0x30020409 0xc4100780 0x2000cc09 0x04208780 + 0xd00e040d 0x80c00780 0x1400d409 0x0423c780 + 0x30020609 0xec000780 0x00020205 0xc0000780 + 0x04005601 0xe4208780 0x861ffe03 0x00000000 + 0xd0095805 0x20000780 0x3500e00d 0x00000003 + 0x307c07fd 0x6c0187c8 0x1000f81d 0x0403c780 + 0x1400c009 0x0423c780 0x10047003 0x00000280 + 0x20000609 0x04004780 0xd0095809 0x20000780 + 0x200b8409 0x00000003 0x3802c00d 0xc4300780 + 0x00020405 0xc0000780 0x102c8021 0x00000003 + 0x1800c009 0x0423c780 0x202c8625 0x00000003 + 0x00001009 0xc0000780 0xd809800d 0x20000780 + 0x20049021 0x00000003 0xd4010009 0x20000780 + 0x1c00c00d 0x0423c780 0x300911fd 0x640147c8 + 0x6803c01d 0x8021c780 0xd4000805 0x20000780 + 0x1003e003 0x00000280 0xd0096805 0x20000780 + 0x1400c00d 0x0423c780 0x00020205 0xc0000780 + 0x300105fd 0x6c00c7c8 0x30030e09 0xec000780 + 0xd4015805 0x20000780 0x307c0bfd 0x64014148 + 0xa0058003 0x00000000 0x2440c009 0x04208780 + 0x10057003 0x00000100 0xd009a805 0x20000780 + 0x2506e00c 0x2003820c 0x3002060d 0xc4100780 + 0x2000ca0d 0x0420c780 0xd00e0609 0xa0c00780 + 0x10058003 0x00000780 0x1000f809 0x0403c780 0xf0000001 0xe0000002 0x861ffe03 0x00000000 - 0xa0004c11 0x04200780 0x30080815 0xc4100780 - 0x308207fd 0x6c4107c8 0xa002c003 0x00000000 - 0x20000a1d 0x0400c780 0x1002c003 0x00000280 - 0xd0095805 0x20000780 0x2400c005 0x0420c780 - 0x30010e05 0xac000780 0x308203fd 0x6c40c7c8 - 0xa002a003 0x00000000 0x10029003 0x00000280 - 0xd0096005 0x20000780 0x2400c005 0x0421c780 - 0x30020205 0xc4100780 0x2000cc05 0x04204780 - 0x20008205 0x0ffffffb 0xd00e0221 0x80c00780 - 0x1400d405 0x0423c780 0x30011005 0xec000780 - 0x1002a003 0x00000780 0x1000f805 0x0403c780 - 0x00000c05 0xc0000782 0x04001601 0xe4204780 - 0xd0096005 0x20000782 0x2400c005 0x0421c780 - 0x30020205 0xc4100780 0x2000cc05 0x04204780 - 0xd00e021d 0x80c00780 0x1400d405 0x0423c780 - 0x30010e05 0xec000780 0x00000c05 0xc0000780 - 0x04005601 0xe4204780 0x861ffe03 0x00000000 - 0xd0095805 0x20000780 0x3500e01d 0x00000003 - 0x307c0ffd 0x6c0187c8 0x1000f821 0x0403c780 - 0x1400c005 0x0423c780 0x1004d003 0x00000280 - 0x20000e05 0x0400c780 0x200b821d 0x00000003 - 0x102c8005 0x00000003 0x00020e09 0xc0000780 - 0x00000205 0xc0000780 0x1000f81d 0x0403c780 - 0xd4098011 0x20000780 0xd801000d 0x20000780 - 0x20018e1d 0x00000003 0x1000c005 0x0423c784 - 0xd0095811 0x20000780 0x6c01c021 0x80220780 - 0x3007c1fd 0x6c2147cc 0xd8000809 0x20000780 - 0xd4000805 0x20000780 0x1000c005 0x0423c784 - 0x10042003 0x00000280 0xd0096805 0x20000780 - 0x1400c01d 0x0423c780 0x00000c05 0xc0000780 - 0x300303fd 0x6c00c7c8 0x30071005 0xec000780 - 0xd4015805 0x20000780 0x307c09fd 0x64014148 - 0xa005e003 0x00000000 0x2440c005 0x04204780 - 0x1005d003 0x00000100 0xd009a805 0x20000780 - 0x2505e014 0x20058614 0x30020a15 0xc4100780 - 0x2000ca15 0x04214780 0xd00e0a05 0xa0c00780 - 0x1005e003 0x00000780 0x1000f805 0x0403c780 - 0xf0000001 0xe0000002 0x861ffe03 0x00000000 - 0x301f0215 0xec100780 0x30010219 0xc4100780 - 0x20000605 0x04000780 0xd0060a0d 0x04008780 - 0x00020205 0xc0000780 0x30830605 0xac400780 + 0x301f040d 0xec100780 0x30010409 0xc4100780 + 0x20000219 0x04000780 0xd0020605 0x04008780 + 0x00020c05 0xc0000780 0x30840205 0xac400780 0x04001601 0xe4204780 0x861ffe03 0x00000000 - 0x40518405 0x00000003 0x00020205 0xc0000780 - 0x3400d605 0xec200780 0x3400d80d 0xec200780 - 0x3400da15 0xec200780 0x3400dc19 0xec200780 - 0x20038204 0x20068a0c 0x3400de15 0xec200780 - 0x3400e019 0xec200780 0x20038204 0x20068a0c - 0x3400e215 0xec200780 0x3400e419 0xec200780 - 0x20038204 0x20068a0c 0x3400e615 0xec200780 - 0x3400e819 0xec200780 0x20038204 0x20068a0c - 0x3400ea15 0xec200780 0x3400ec19 0xec200780 - 0x20038204 0x20068a0c 0x3400ee15 0xec200780 - 0x3400f019 0xec200780 0x20038204 0x20068a0c - 0x3400f215 0xec200780 0x3400f419 0xec200780 - 0x20038204 0x20068a0c 0x308401fd 0x644107c8 - 0x20000215 0x0400c780 0x30000003 0x00000280 - 0x200009fd 0x040087c8 0xa0093003 0x00000000 - 0x10090003 0x00000280 0xd0095805 0x20000780 - 0x20018005 0x00000003 0x3510e00d 0x00000003 - 0x40070419 0x00000780 0x60060619 0x00018780 - 0x30100c19 0xc4100780 0x60060405 0x00018780 - 0x20000205 0x04014780 0x10093003 0x00000780 - 0x30040005 0xc4100780 0x20000a05 0x04004780 + 0x40518805 0x00000003 0x00020205 0xc0000780 + 0x3400d605 0xec200780 0x3400d809 0xec200780 + 0x3400da0d 0xec200780 0x3400dc19 0xec200780 + 0x20028204 0x20068608 0x3400de0d 0xec200780 + 0x3400e019 0xec200780 0x20028204 0x20068608 + 0x3400e20d 0xec200780 0x3400e419 0xec200780 + 0x20028204 0x20068608 0x3400e60d 0xec200780 + 0x3400e819 0xec200780 0x20028204 0x20068608 + 0x3400ea0d 0xec200780 0x3400ec19 0xec200780 + 0x20028204 0x20068608 0x3400ee0d 0xec200780 + 0x3400f019 0xec200780 0x20028204 0x20068608 + 0x3400f20d 0xec200780 0x3400f419 0xec200780 + 0x20028204 0x20068608 0x308501fd 0x644107c8 + 0x2000020d 0x04008780 0x30000003 0x00000280 + 0x20000bfd 0x040107c8 0xa008d003 0x00000000 + 0x1008a003 0x00000280 0xd0095805 0x20000780 + 0x20018005 0x00000003 0x3510e009 0x00000003 + 0x40050419 0x00000780 0x60040619 0x00018780 + 0x30100c19 0xc4100780 0x60040405 0x00018780 + 0x20000205 0x0400c780 0x1008d003 0x00000780 + 0x30040005 0xc4100780 0x20000605 0x04004780 0x20108205 0x00000003 0xf0000001 0xe0000002 - 0x610f2e01 0x00000003 0x2101f00d 0x00000003 - 0x3003000d 0xc4000780 0x30040801 0xc4100780 - 0x20038000 0x20008400 0x30020001 0xc4100780 + 0x610f2e01 0x00000003 0x2101f009 0x00000003 + 0x30020009 0xc4000780 0x30040a01 0xc4100780 + 0x20028000 0x20008800 0x30020001 0xc4100780 0x2000c801 0x04200780 0xd00e0005 0xa0c00781 } } @@ -1102,170 +1091,167 @@ code { name = cudaChooseBestMethod lmem = 0 smem = 4132 - reg = 14 + reg = 15 bar = 1 const { segname = const segnum = 1 offset = 0 - bytes = 48 + bytes = 56 mem { - 0x000003ff 0x7e800000 0x3f000000 0x0000000e - 0x00000008 0x00000001 0x00000020 0x0000007f - 0x0000003f 0x0000001f 0x00000024 0x3e800000 + 0x000003ff 0x00000030 0x000000c0 0x7e800000 + 0x3f000000 0x0000000e 0x00000008 0x00000001 + 0x00000020 0x0000007f 0x0000003f 0x0000001f + 0x00000024 0x3e800000 } } bincode { 0xd0800205 0x00400780 0xa000020d 0x04000780 0xa0000005 0x04000780 0x30050601 0xc4100780 - 0x20000211 0x04000780 0x103f8001 0x07ffffff - 0x00020805 0xc0000780 0x307cd1fd 0x6c20c7c8 - 0x04011201 0xe4200780 0x00070609 0xc0000780 - 0x100b3003 0x00000280 0xa0004415 0x04200780 - 0x1000f819 0x0403c780 0x20000c1d 0x0400c780 - 0x3007d1fd 0x6420c7c8 0xa00b0003 0x00000000 - 0x100b0003 0x00000280 0x1000d001 0x0423c780 - 0x40014e09 0x00200780 0x30100409 0xc4100780 - 0x60004e09 0x00208780 0x30070601 0xc4100780 - 0x30070c2d 0xc4100780 0x30060c31 0xc4100780 - 0x30060629 0xc4100780 0x30070425 0xc4100780 - 0x30060421 0xc4100780 0x200c962c 0x200a8000 - 0x20089224 0x210be828 0x30020221 0xc4100780 - 0x200a802c 0x20099028 0x20088024 0x200b9420 - 0xd00e1021 0x80c00780 0x00000005 0xc0000780 - 0x0000120d 0xc0000780 0x0c051201 0xe4220780 - 0x3001cffd 0x6c20c7c8 0xa0055003 0x00000000 - 0x10000201 0x0403c780 0x1000f821 0x0403c780 - 0x10055003 0x00000280 0x30060c25 0xc4100780 - 0x30060629 0xc4100780 0x20001225 0x04028780 - 0x30060409 0xc4100780 0x20000425 0x04024780 - 0xa0004229 0x04200780 0xd414480d 0x20000780 - 0x1c00ce09 0x0423c780 0x6000cc09 0x88208780 - 0x3c7ccbfd 0x6c2147c8 0x3d02e02c 0x20009208 - 0x30020409 0xc4100780 0x2000ca09 0x04208780 - 0xd00e0409 0x80c00780 0xa003e003 0x00000000 - 0x1003b003 0x00000280 0x307c05fd 0x6c0087c8 - 0x1003d003 0x00000280 0x10018031 0x00000003 - 0x1003e003 0x00000780 0x1000f831 0x0403c780 - 0x300bcc2d 0xac200782 0x307c162d 0x8c000780 - 0x400c162d 0x00018780 0xa0001631 0x44014780 - 0xb03d1831 0x0358637b 0xa0000435 0x44014780 - 0xb08119fd 0x605107c8 0xb03d1a35 0x0358637b - 0xc08b1a35 0x00400680 0xc08b1831 0x00400680 - 0x90001831 0x00000780 0xe10c1a31 0x00408780 - 0x90001831 0x60000780 0xa0001831 0x8c064780 - 0x30831831 0xac400780 0x307c1831 0x8c000780 - 0x300c0409 0xec000780 0x20019831 0x00000003 - 0x20000001 0x04028780 0x600c1609 0x80008780 - 0x3000cffd 0x6c2107c8 0x20001021 0x04008780 - 0x1002f003 0x00000280 0x0002080d 0xc0000782 - 0x0c031201 0xe4220780 0xdc0c4811 0x20000780 - 0x1000e001 0x0423c784 0x2000c001 0x04200784 - 0x0c031201 0xe4200780 0x1000d001 0x0423c784 - 0x2000c001 0x04200784 0x0c031201 0xe4200780 - 0x1000c801 0x0423c784 0x2000c001 0x04200784 - 0x0c031201 0xe4200780 0x1000c401 0x0423c784 - 0x2000c001 0x04200784 0x0c031201 0xe4200780 - 0x1000c201 0x0423c784 0x2000c001 0x04200784 - 0x307c03fd 0x640147c8 0x0c031201 0xe4200780 - 0x100b0003 0x00000280 0xd414700d 0x20000780 - 0x1d00ec08 0x1d00e400 0x2c40c209 0x04208780 - 0x40050021 0x00000780 0x60040221 0x00020780 - 0x30101021 0xc4100780 0x3c84c1fd 0x6c6147c8 - 0x60040021 0x00020780 0xa00ad003 0x00000000 - 0x10083003 0x00000280 0xd4144805 0x20000780 - 0x1400c001 0x0423c780 0x3002ce25 0xc4300780 - 0x4005002d 0x00000780 0x301f1229 0xec100780 - 0x6004022d 0x0002c780 0xd0851429 0x04400780 - 0x3010162d 0xc4100780 0x20001425 0x04024780 - 0x60040009 0x0002c780 0x30011201 0xec100780 - 0x20000401 0x04000780 0xd80c4805 0x20000780 - 0x2400c001 0x04200780 0x20068001 0x00000003 - 0x100ad003 0x00000780 0xd414700d 0x20000780 - 0x3c86c1fd 0x6c6147c8 0xa00ac003 0x00000000 - 0x10097003 0x00000280 0xd4144805 0x20000780 - 0x2502e608 0x1500e000 0x3002ce25 0xc4300780 - 0x40050029 0x00000780 0x301f122d 0xec100780 - 0x60040229 0x00028780 0xd085162d 0x04400780 - 0x30101429 0xc4100780 0x20001625 0x04024780 - 0x60040001 0x00028780 0x30011209 0xec100780 - 0x20000001 0x04008780 0xd80c4805 0x20000780 - 0x2400c001 0x04200780 0x200f8001 0x00000003 - 0x100ac003 0x00000780 0xd414700d 0x20000780 - 0x3c7cc1fd 0x6c2147c8 0xa00ab003 0x00000000 - 0x100a5003 0x00000280 0xd80c480d 0x20000780 - 0xd4148005 0x20000780 0x3c7cc1fd 0x6c2087c8 - 0x2501e001 0x00000003 0x10000a01 0x2440c280 + 0x20000211 0x04000780 0x103f8009 0x07ffffff + 0x00020805 0xc0000780 0x30020801 0xc4100780 + 0x307cd1fd 0x6c20c7c8 0x04011201 0xe4208780 + 0x20248015 0x00000003 0x100b4003 0x00000280 + 0xa0004419 0x04200780 0x1000f81d 0x0403c780 + 0x20000e21 0x0400c780 0x3008d1fd 0x6420c7c8 + 0xa00b1003 0x00000000 0x100b1003 0x00000280 + 0x1000d001 0x0423c780 0x40014e09 0x00200780 + 0x30100409 0xc4100780 0x60004e29 0x00208780 + 0x20001401 0x04020780 0x30050009 0xc4100780 + 0x30040001 0xc4100780 0x20008400 0x20008200 + 0x30020009 0xc4100780 0x60810601 0x60404780 + 0x2000c809 0x04208780 0xd00e0409 0x80c00780 + 0x00020005 0xc0000780 0x04051201 0xe4208780 + 0x3001cffd 0x6c20c7c8 0xa0054003 0x00000000 + 0x10000201 0x0403c780 0x1000f825 0x0403c780 + 0x10054003 0x00000280 0x30060e2d 0xc4100780 + 0x30060631 0xc4100780 0x10248009 0x00000003 + 0x2000162d 0x04030780 0x60820609 0x60408780 + 0x30061429 0xc4100780 0x00000405 0xc0000780 + 0x20001429 0x0402c780 0xa000422d 0x04200780 + 0xd4140009 0x20000780 0x20009430 0x1900ee08 + 0x30021831 0xc4100780 0x6000cc35 0x88208780 + 0x2000ca09 0x04230780 0xd00e0409 0x80c00780 + 0xa003d003 0x00000000 0x387ccbfd 0x6c2147c8 + 0x3800c031 0x04234780 0x1003a003 0x00000280 + 0x307c05fd 0x6c0087c8 0x1003c003 0x00000280 + 0x10018035 0x00000003 0x1003d003 0x00000780 + 0x1000f835 0x0403c780 0x300ccc31 0xac200782 + 0x307c1831 0x8c000780 0x400d1831 0x00018780 + 0xa0001835 0x44014780 0xb03d1a39 0x0358637b + 0xa0000435 0x44014780 0xb0831dfd 0x605107c8 + 0xb03d1a35 0x0358637b 0xc08d1a35 0x00400680 + 0xc08d1c39 0x00400680 0x90001c39 0x00000780 + 0xe10e1a35 0x00410780 0x90001a35 0x60000780 + 0xa0001a35 0x8c064780 0x30851a35 0xac400780 + 0x307c1a35 0x8c000780 0x300d0409 0xec000780 + 0x20019a35 0x00000003 0x600d1809 0x80008780 + 0x20000001 0x0402c780 0x3000cffd 0x6c2107c8 + 0x20001225 0x04008780 0x1002e003 0x00000280 + 0x00000a05 0xc0000782 0x04030001 0xe4224780 + 0xd40c0009 0x20000780 0x1800e001 0x0423c780 + 0x2800c001 0x04200780 0x04030001 0xe4200780 + 0x1900f000 0x2900e000 0x04030001 0xe4200780 + 0x1900e800 0x2900e000 0x04030001 0xe4200780 + 0x1900e400 0x2900e000 0x04030001 0xe4200780 + 0x1900e200 0x2900e000 0x307c03fd 0x640147c8 + 0x04030001 0xe4200780 0x100b1003 0x00000280 + 0x10248001 0x00000003 0x60820601 0x60400780 + 0x00000005 0xc0000780 0xd4142809 0x20000780 + 0x1900ec08 0x1900e400 0x2840c209 0x04208780 0x40050025 0x00000780 0x60040225 0x00024780 - 0x30101225 0xc4100780 0x60040001 0x00024780 - 0x100ab003 0x00000780 0xd4148005 0x20000780 - 0x1400c001 0x0423c780 0x40050025 0x00000780 - 0x60040225 0x00024780 0x30101225 0xc4100780 - 0x60040001 0x00024780 0xf0000001 0xe0000002 - 0xf0000001 0xe0000002 0x30080001 0xac000782 - 0x00020e05 0xc0000780 0x04011201 0xe4200780 - 0x20000c19 0x04014782 0x3006d1fd 0x6c2107c8 - 0x1000d003 0x00000280 0x861ffe03 0x00000000 - 0x3004d1fd 0x6c20c7c8 0xa00c4003 0x00000000 - 0x100c4003 0x00000280 0x1000d001 0x0423c780 - 0x40014e05 0x00200780 0x30100205 0xc4100780 - 0x60004e01 0x00204780 0x20000001 0x04010780 - 0x30070005 0xc4100780 0x30060001 0xc4100780 - 0x00020805 0xc0000780 0x20000201 0x04000780 - 0xd4044805 0x20000780 0x2100e804 0x1500e000 - 0x20108205 0x00000003 0xd00e0201 0xa0c00780 + 0x30101225 0xc4100780 0x3886c1fd 0x6c6147c8 + 0x60040025 0x00024780 0xa00ae003 0x00000000 + 0x10082003 0x00000280 0xd4140005 0x20000780 + 0x1400c001 0x0423c780 0x3002ce29 0xc4300780 + 0x40050031 0x00000780 0x301f142d 0xec100780 + 0x60040231 0x00030780 0xd087162d 0x04400780 + 0x30101831 0xc4100780 0x20001629 0x04028780 + 0x60040009 0x00030780 0x30011401 0xec100780 + 0x00070605 0xc0000780 0x20000401 0x04000780 + 0xd40c4805 0x20000780 0x2400c001 0x04200780 + 0x20068001 0x00000003 0x100ae003 0x00000780 + 0xd4142809 0x20000780 0x3888c1fd 0x6c6147c8 + 0xa00ad003 0x00000000 0x10097003 0x00000280 + 0xd4140005 0x20000780 0x2502e608 0x1500e000 + 0x3002ce2d 0xc4300780 0x40050029 0x00000780 + 0x301f1631 0xec100780 0x60040229 0x00028780 + 0xd0871831 0x04400780 0x30101429 0xc4100780 + 0x2000182d 0x0402c780 0x60040001 0x00028780 + 0x30011609 0xec100780 0x00070605 0xc0000780 + 0x20000001 0x04008780 0xd40c4805 0x20000780 + 0x2400c001 0x04200780 0x200f8001 0x00000003 + 0x100ad003 0x00000780 0xd4142809 0x20000780 + 0x387cc1fd 0x6c2147c8 0xa00ac003 0x00000000 + 0x100a6003 0x00000280 0x00070609 0xc0000780 + 0xd4143805 0x20000780 0xd80c4809 0x20000780 + 0x2501e001 0x00000003 0x387cc1fd 0x6c2087c8 + 0x10000e01 0x2440c280 0x40050029 0x00000780 + 0x60040229 0x00028780 0x30101429 0xc4100780 + 0x60040001 0x00028780 0x100ac003 0x00000780 + 0xd4143805 0x20000780 0x1400c001 0x0423c780 + 0x40050029 0x00000780 0x60040229 0x00028780 + 0x30101429 0xc4100780 0x60040001 0x00028780 + 0xf0000001 0xe0000002 0xf0000001 0xe0000002 + 0x30090001 0xac000782 0x00021005 0xc0000780 + 0x04011201 0xe4200780 0x20000e1d 0x04018782 + 0x3007d1fd 0x6c2107c8 0x1000e003 0x00000280 + 0x861ffe03 0x00000000 0x3004d1fd 0x6c20c7c8 + 0xa00c5003 0x00000000 0x100c5003 0x00000280 + 0x1000d001 0x0423c780 0x40014e05 0x00200780 + 0x30100205 0xc4100780 0x60004e01 0x00204780 + 0x20000001 0x04010780 0x30070005 0xc4100780 + 0x30060001 0xc4100780 0x00000a05 0xc0000780 + 0x20000201 0x04000780 0xd4040005 0x20000780 + 0x2100e804 0x1500e000 0x20108205 0x00000003 + 0xd00e0201 0xa0c00780 0xf0000001 0xe0000002 + 0x861ffe03 0x00000000 0x00000a05 0xc0000780 + 0xd4040005 0x20000780 0x308909fd 0x6c4107c8 + 0xa00d8003 0x00000000 0x1400c001 0x0423c780 + 0x100d8003 0x00000280 0x00000a05 0xc0000780 + 0xd408000d 0x20000780 0xd4040009 0x20000780 + 0x1c00c001 0x0423c780 0x3800c1fd 0x6c2107c8 + 0x1c00c001 0x0423c780 0x20008805 0x0000000b + 0x3800c001 0xac200780 0x10000805 0x0403c500 + 0x04000001 0xe4204780 0x04010001 0xe4200780 0xf0000001 0xe0000002 0x861ffe03 0x00000000 - 0x00020805 0xc0000780 0xd4044805 0x20000780 - 0x308709fd 0x6c4107c8 0xa00d7003 0x00000000 - 0x1400c001 0x0423c780 0x100d7003 0x00000280 - 0x00020805 0xc0000780 0xd408480d 0x20000780 - 0xd4044809 0x20000780 0x1c00c001 0x0423c780 - 0x3800c1fd 0x6c2107c8 0x1c00c001 0x0423c780 - 0x20008805 0x0000000b 0x3800c001 0xac200780 - 0x10000805 0x0403c500 0x04001201 0xe4204780 - 0x04011201 0xe4200780 0xf0000001 0xe0000002 - 0x861ffe03 0x00000000 0x308809fd 0x6c4107c8 - 0xa00e6003 0x00000000 0x100e6003 0x00000280 - 0x00020805 0xc0000780 0xd4064809 0x20000780 - 0x20008805 0x00000007 0x3800c1fd 0x6c2047c8 - 0x10000805 0x0403c500 0x0002020d 0xc0000780 - 0x3800c001 0xac200780 0x1c00d205 0x0423c780 - 0x04001201 0xe4204780 0x04011201 0xe4200780 - 0xf0000001 0xe0000002 0x861ffe03 0x00000000 - 0x308909fd 0x6c4107c8 0x30000003 0x00000280 - 0x20298805 0x0000000b 0x00020209 0xc0000780 - 0x20208805 0x00000003 0x3800c1fd 0x6c2047c8 - 0x10000805 0x0403c500 0x0002020d 0xc0000780 - 0x00020805 0xc0000780 0x3800c005 0xac200780 - 0x1c00d201 0x0423c780 0x20198809 0x0000000b - 0x04001201 0xe4200780 0x00020409 0xc0000780 - 0x04011201 0xe4204780 0x20108801 0x00000003 - 0x3801c1fd 0x6c2047c8 0x10000801 0x0403c500 - 0x0002000d 0xc0000780 0x3801c005 0xac200780 - 0x1c00d201 0x0423c780 0x20118809 0x0000000b - 0x04001201 0xe4200780 0x00020409 0xc0000780 - 0x04011201 0xe4204780 0x20088801 0x00000003 - 0x3801c1fd 0x6c2047c8 0x10000801 0x0403c500 - 0x0002000d 0xc0000780 0x3801c005 0xac200780 - 0x1c00d201 0x0423c780 0x200d8809 0x0000000b - 0x04001201 0xe4200780 0x00020409 0xc0000780 - 0x04011201 0xe4204780 0x20048801 0x00000003 - 0x3801c1fd 0x6c2047c8 0x10000801 0x0403c500 - 0x0002000d 0xc0000780 0x3801c005 0xac200780 - 0x1c00d201 0x0423c780 0x200b8809 0x0000000b - 0x04001201 0xe4200780 0x00020409 0xc0000780 - 0x04011201 0xe4204780 0x20028801 0x00000003 - 0x3801c1fd 0x6c2047c8 0x10000801 0x0403c500 - 0x0002000d 0xc0000780 0x3801c005 0xac200780 - 0x1c00d201 0x0423c780 0x04001201 0xe4200780 - 0x307c09fd 0x6c0147c8 0x04011201 0xe4204780 + 0x308a09fd 0x6c4107c8 0xa00e7003 0x00000000 + 0x100e7003 0x00000280 0x00000a05 0xc0000780 + 0xd4060009 0x20000780 0x20008a05 0x00000013 + 0x3800c1fd 0x6c2047c8 0x10000a05 0x0403c500 + 0x0000020d 0xc0000780 0x3800c001 0xac200780 + 0x1c00c005 0x0423c780 0x04000001 0xe4204780 + 0x04010001 0xe4200780 0xf0000001 0xe0000002 + 0x861ffe03 0x00000000 0x308b09fd 0x6c4107c8 + 0x30000003 0x00000280 0x00000a05 0xc0000780 + 0xd4041009 0x20000780 0x20008a05 0x0000000b + 0x3800fdfd 0x6c2047c8 0x10000a05 0x0403c500 + 0x0000020d 0xc0000780 0x3800fc05 0xac200780 + 0x1c00c001 0x0423c780 0x04000001 0xe4200780 + 0x04010001 0xe4204780 0x20008a01 0x00000007 + 0x3801ddfd 0x6c2047c8 0x10000a01 0x0403c500 + 0x0000000d 0xc0000780 0x3801dc05 0xac200780 + 0x1c00c001 0x0423c780 0x04000001 0xe4200780 + 0x04010001 0xe4204780 0x20208a01 0x00000003 + 0x3801cdfd 0x6c2047c8 0x10000a01 0x0403c500 + 0x0000000d 0xc0000780 0x3801cc05 0xac200780 + 0x1c00c001 0x0423c780 0x04000001 0xe4200780 + 0x04010001 0xe4204780 0x20108a01 0x00000003 + 0x3801c5fd 0x6c2047c8 0x10000a01 0x0403c500 + 0x0000000d 0xc0000780 0x3801c405 0xac200780 + 0x1c00c001 0x0423c780 0x04000001 0xe4200780 + 0x04010001 0xe4204780 0x20088a01 0x00000003 + 0x3801c1fd 0x6c2047c8 0x10000a01 0x0403c500 + 0x0000000d 0xc0000780 0x3801c005 0xac200780 + 0x1c00c001 0x0423c780 0x04000001 0xe4200780 + 0x307c09fd 0x6c0147c8 0x04010001 0xe4204780 0x30000003 0x00000280 0x1000d001 0x0423c780 0x40014e05 0x00200780 0xd0044805 0x20000780 0x30100209 0xc4100780 0x1400c205 0x0423c780 0x60004e09 0x00208780 0x3401c1fd 0x6c2107c8 0x10048011 0x00000003 0x10248001 0x00000003 0x30070405 0xc4100780 0x3006040d 0xc4100780 - 0x21000801 0x04428280 0x20000205 0x0400c780 + 0x21000801 0x04430280 0x20000205 0x0400c780 0x00000005 0xc0000780 0x2101e800 0x2502e004 0x20208001 0x00000003 0xd00e0005 0xa0c00781 } @@ -1274,70 +1260,69 @@ code { name = cudaEncodeResidual lmem = 0 smem = 1372 - reg = 6 + reg = 8 bar = 1 const { segname = const segnum = 1 offset = 0 - bytes = 8 + bytes = 12 mem { - 0x0000002f 0x0000001f + 0x0000002f 0x00000030 0x0000001f } } bincode { - 0xa0000009 0x04000780 0x308005fd 0x644107c8 - 0xa000d003 0x00000000 0x1000d003 0x00000280 - 0xa0004e01 0x04200780 0x30070005 0xc4100780 - 0x30060001 0xc4100780 0x20000201 0x04000780 - 0x30020405 0xc4100780 0x2100ec00 0x20008200 - 0xd00e0001 0x80c00780 0x00020405 0xc0000780 - 0x04024e01 0xe4200780 0xf0000001 0xe0000002 - 0x861ffe03 0x00000000 0xa0004205 0x04200780 - 0x40034c01 0x00200780 0x30100001 0xc4100780 - 0xd0093805 0x20000780 0x60024c0d 0x00200780 - 0x2501e000 0x2543ee10 0x30040011 0xac000780 - 0x300209fd 0x6c00c7c8 0xa0022003 0x00000000 - 0x10021003 0x00000280 0xd0094005 0x20000780 - 0x2503e000 0x20008400 0x30020001 0xc4100780 - 0x2000ca01 0x04200780 0xd00e0015 0x80c00780 - 0x1400d401 0x0423c780 0x30000a01 0xec000780 - 0x10022003 0x00000780 0x1000f801 0x0403c780 - 0x00020405 0xc0000782 0x308105fd 0x6c4107c8 - 0x04000e01 0xe4200780 0xa0037003 0x00000000 - 0x10037003 0x00000280 0x20000201 0x04008780 - 0x300401fd 0x6c0187c8 0x00020009 0xc0000780 - 0xa0036003 0x00000000 0x10035003 0x00000280 - 0xd009400d 0x20000780 0x20028200 0x2d03e010 - 0x20000001 0x04010780 0x30020001 0xc4100780 - 0x2000ca01 0x04200780 0xd00e0011 0x80c00780 - 0x1c00d401 0x0423c780 0x30000801 0xec000780 - 0x10036003 0x00000780 0x1000f801 0x0403c780 - 0x08000e01 0xe4200782 0xd0093809 0x20000782 - 0x2943ee00 0x3900e000 0x30000201 0xac000780 - 0x307c0005 0x8c000780 0x861ffe03 0x00000000 - 0xd0093809 0x20000780 0x387cc1fd 0x6c20c7c8 - 0x1000f811 0x0403c780 0x1004d003 0x00000280 - 0x101c8001 0x00000003 0x0000000d 0xc0000780 - 0x1000f815 0x0403c780 0x20000a01 0x04008780 - 0xd0093811 0x20000780 0x20018a15 0x00000003 - 0xdc098009 0x20000780 0x3005c1fd 0x6c2147cc - 0x00020011 0xc0000780 0x1800c001 0x0423c780 - 0x6000ce11 0x80210784 0xdc00080d 0x20000780 - 0x10043003 0x00000280 0x861ffe03 0x00000000 - 0xd0093809 0x20000780 0x2902e014 0x1900e400 - 0x00020a09 0xc0000780 0x30000801 0xec000780 - 0x2840ce01 0x04200780 0x08000e01 0xe4200780 - 0x861ffe03 0x00000000 0xd0093809 0x20000780 - 0x2800c001 0x04204780 0x300201fd 0x6c0107c8 - 0x3802c1fd 0x6c20c2c8 0xa0061003 0x00000000 - 0x10061003 0x00000100 0xd0093809 0x20000780 - 0x2903f400 0x20008400 0x30020011 0xc4100780 - 0x1500ee00 0x2104e810 0xd00e0801 0xa0c00780 - 0x2800c001 0x04204780 0xf0000001 0xe0000002 - 0x20008405 0x00000013 0x300101fd 0x6c00c7c8 - 0x30000003 0x00000280 0xd0098809 0x20000780 - 0x2903e000 0x20008400 0x30020001 0xc4100780 + 0xa0000001 0x04000780 0x308001fd 0x644107c8 + 0x60824e05 0x00600500 0x30020205 0xc4100500 + 0x2000cc05 0x04204500 0xd00e0205 0x80c00500 + 0x00020005 0xc0000500 0x04024e01 0xe4204500 + 0x861ffe03 0x00000000 0xa0004209 0x04200780 + 0x40054c05 0x00200780 0x30100205 0xc4100780 + 0xd0093805 0x20000780 0x60044c0d 0x00204780 + 0x2502e004 0x2543ee10 0x30040211 0xac000780 + 0x300009fd 0x6c00c7c8 0xa001c003 0x00000000 + 0x1001b003 0x00000280 0xd0094005 0x20000780 + 0x2503e004 0x20018004 0x30020205 0xc4100780 + 0x2000ca05 0x04204780 0xd00e0215 0x80c00780 + 0x1400d405 0x0423c780 0x30010a05 0xec000780 + 0x1001c003 0x00000780 0x1000f805 0x0403c780 + 0x00020005 0xc0000782 0x308201fd 0x6c4107c8 + 0x04000e01 0xe4204780 0xa0031003 0x00000000 + 0x10031003 0x00000280 0x20000405 0x04000780 + 0x300403fd 0x6c0187c8 0x00020205 0xc0000780 + 0xa0030003 0x00000000 0x1002f003 0x00000280 + 0xd0094009 0x20000780 0x20008404 0x2903e010 + 0x20000205 0x04010780 0x30020205 0xc4100780 + 0x2000ca05 0x04204780 0xd00e0211 0x80c00780 + 0x1800d405 0x0423c780 0x30010805 0xec000780 + 0x10030003 0x00000780 0x1000f805 0x0403c780 + 0x04000e01 0xe4204782 0xd0093805 0x20000782 + 0x2543ee04 0x3501e004 0x30010405 0xac000780 + 0x307c0209 0x8c000780 0x861ffe03 0x00000000 + 0xd0093805 0x20000780 0x347cc1fd 0x6c20c7c8 + 0x1000f811 0x0403c780 0x10049003 0x00000280 + 0xd0093805 0x20000780 0x3402c005 0xc4300780 + 0x101c8015 0x00000003 0x1000f81d 0x0403c780 + 0x201c8219 0x00000003 0x00000a05 0xc0000780 + 0x20000e05 0x04000780 0xd4098009 0x20000780 + 0x20048a15 0x00000003 0x00020205 0xc0000780 + 0x1800c005 0x0423c780 0x30060bfd 0x640147c8 + 0x6401ce11 0x80210780 0x20018e1d 0x00000003 + 0x1003f003 0x00000280 0x861ffe03 0x00000000 + 0xd0093805 0x20000780 0x2500e014 0x1500e404 + 0x00020a05 0xc0000780 0x30010805 0xec000780 + 0x2440ce05 0x04204780 0x04000e01 0xe4204780 + 0x861ffe03 0x00000000 0xd0093805 0x20000780 + 0x2400c005 0x04208780 0x300003fd 0x6c0107c8 + 0x3400c1fd 0x6c20c2c8 0xa005e003 0x00000000 + 0x1005e003 0x00000100 0xd0093805 0x20000780 + 0x2503f404 0x20018004 0x00020009 0xc0000780 + 0x30020211 0xc4100780 0x1900ee04 0x2104e810 + 0xd00e0805 0xa0c00780 0x2400c005 0x04208780 + 0xf0000001 0xe0000002 0x20008009 0x00000013 + 0x300203fd 0x6c00c7c8 0x30000003 0x00000280 + 0xd0098805 0x20000780 0x2503e004 0x20018004 + 0x00020005 0xc0000780 0x30020201 0xc4100780 0xd4083805 0x20000780 0x2100e804 0x1500e000 0x20008205 0x00000043 0xd00e0201 0xa0c00781 } @@ -1346,32 +1331,31 @@ code { name = cudaCopyBestMethod lmem = 0 smem = 32 - reg = 5 + reg = 3 bar = 1 const { segname = const segnum = 1 offset = 0 - bytes = 4 + bytes = 8 mem { - 0x0000002f + 0x0000002f 0x00000030 } } bincode { - 0xa0000005 0x040007c0 0xa000d003 0x00000000 - 0x1000d003 0x00000280 0x1000cc01 0x0423c780 - 0x40014e09 0x00200780 0x30100409 0xc4100780 - 0x60004e01 0x00208780 0x30070009 0xc4100780 - 0x30060001 0xc4100780 0x20008400 0x2100ea00 - 0x20208001 0x00000003 0xd00e0001 0x80c00780 - 0x00000e01 0xe4200780 0xf0000001 0xe0000002 - 0x861ffe03 0x00000000 0x308003fd 0x644107c8 - 0x30000003 0x00000280 0xa0004e01 0x04200780 - 0x3007ce0d 0xc4300780 0x3006ce11 0xc4300780 - 0x30070009 0xc4100780 0x30060001 0xc4100780 - 0x2004860c 0x20008408 0x30020201 0xc4100780 - 0x2103ea0c 0x2102e804 0x20038008 0x20018004 - 0xd00e0401 0x80c00780 0xd00e0201 0xa0c00781 + 0xa0000001 0x040007c0 0xa000d003 0x00000000 + 0x1000d003 0x00000280 0x1000cc05 0x0423c780 + 0x40034e09 0x00200780 0x30100409 0xc4100780 + 0x60024e05 0x00208780 0x30070209 0xc4100780 + 0x30060205 0xc4100780 0x20018404 0x2101ea04 + 0x20208205 0x00000003 0xd00e0205 0x80c00780 + 0x00000e01 0xe4204780 0xf0000001 0xe0000002 + 0x861ffe03 0x00000000 0x308001fd 0x644107c8 + 0x30000003 0x00000280 0x3005ce05 0xc4300780 + 0x3004ce09 0xc4300780 0x20028204 0x20018004 + 0x61302e01 0x00000003 0x30020205 0xc4100780 + 0x30020009 0xc4100780 0x2101ea00 0x2102e804 + 0xd00e0001 0x80c00780 0xd00e0201 0xa0c00781 } } code { @@ -1384,80 +1368,78 @@ code { segname = const segnum = 1 offset = 0 - bytes = 24 + bytes = 36 mem { 0x00000020 0x000003ff 0x00000001 0x0000000e - 0x00000080 0x00000040 + 0x00000080 0x0000061c 0x00000040 0x0000051c + 0x0000049c } } bincode { 0x10028009 0x00000003 0x1000cc05 0x0423c780 - 0x30010409 0xc4000780 0x10000005 0x0403c780 - 0x30800409 0xac400780 0xa0000401 0x04000780 - 0x3000040d 0x640107d0 0xd0820609 0x00400780 - 0xa00007fd 0x0c0147c8 0xa001b003 0x00000000 - 0xa0000405 0x04000780 0x1001a003 0x00001100 - 0x2101ec11 0x00000003 0x100f800d 0x00000003 - 0x3004060d 0xc4000780 0x40074e15 0x00200780 - 0x30100a15 0xc4100780 0x60064e15 0x00214780 - 0x3004020d 0xc4000780 0x20000a11 0x0400c780 - 0x60804c0d 0x00600780 0x2000060d 0x04010780 - 0x3002060d 0xc4100780 0x2000ca0d 0x0420c780 - 0xd00e0611 0x80c00780 0x1001b003 0x00000780 - 0x103f8011 0x000fffff 0x1000f80d 0x0403c782 - 0x20088215 0x00000003 0x30830a19 0x6440c780 - 0x1000040d 0x2440c280 0xa0000c19 0x2c014780 - 0xd00607fd 0x040007c8 0xa0035003 0x00000000 - 0x10034003 0x00000100 0x2101ec19 0x00000003 - 0x100f800d 0x00000003 0x3006060d 0xc4000780 - 0x40074e1d 0x00200780 0x30100e1d 0xc4100780 - 0x60064e21 0x0021c780 0x3006021d 0xc4000780 - 0x1008800d 0x00000003 0x2000101d 0x0401c780 - 0x3006060d 0xc4000780 0x2000060d 0x0401c780 - 0x61202c0d 0x00000003 0x2000000d 0x0400c780 - 0x3002060d 0xc4100780 0x2000ca0d 0x0420c780 - 0xd00e0619 0x80c00780 0x10035003 0x00000780 - 0x103f8019 0x000fffff 0x3005020d 0xc4100782 - 0x20000601 0x04000780 0x300609fd 0x6c0107c8 - 0x1000020d 0x0403c780 0x10000a0d 0x0403c280 - 0x00020005 0xc0000780 0x30060805 0xac000780 - 0x04020e01 0xe420c780 0x04000e01 0xe4204780 - 0x861ffe03 0x00000000 0x308401fd 0x6c4187c8 - 0xa004e003 0x00000000 0x1004e003 0x00000280 - 0x20008011 0x0000000b 0x00020809 0xc0000780 - 0x1000000d 0x0403c780 0x3801cffd 0x6c2047c8 - 0x1000080d 0x0403c280 0x00020605 0xc0000780 - 0xd408380d 0x20000780 0x00020005 0xc0000780 - 0x3801ce05 0xac200780 0x1c00c00d 0x0423c780 - 0x04020e01 0xe420c780 0x04000e01 0xe4204780 + 0x30010405 0xc4000780 0x30800209 0xac400780 + 0xa0000005 0x04000780 0x3001040d 0x640107d0 + 0xd0820201 0x00400780 0xa00007fd 0x0c0147c8 + 0xa001a003 0x00000000 0xa0000001 0x04000780 + 0x10019003 0x00001100 0x2101ec11 0x00000003 + 0x100f800d 0x00000003 0x3004060d 0xc4000780 + 0x40074e15 0x00200780 0x30100a15 0xc4100780 + 0x60064e15 0x00214780 0x3004000d 0xc4000780 + 0x20000a11 0x0400c780 0x60804c0d 0x00604780 + 0x2000060d 0x04010780 0x3002060d 0xc4100780 + 0x2000ca0d 0x0420c780 0xd00e0611 0x80c00780 + 0x1001a003 0x00000780 0x103f8011 0x000fffff + 0x1000f80d 0x0403c782 0x20088015 0x00000003 + 0x30830a19 0x6440c780 0x1000040d 0x2440c280 + 0xa0000c19 0x2c014780 0xd00607fd 0x040007c8 + 0xa0034003 0x00000000 0x10033003 0x00000100 + 0x2101ec19 0x00000003 0x100f800d 0x00000003 + 0x3006060d 0xc4000780 0x40074e1d 0x00200780 + 0x30100e1d 0xc4100780 0x60064e21 0x0021c780 + 0x3006001d 0xc4000780 0x1008800d 0x00000003 + 0x2000101d 0x0401c780 0x3006060d 0xc4000780 + 0x2000060d 0x0401c780 0x61202c0d 0x00000003 + 0x2000020d 0x0400c780 0x3002060d 0xc4100780 + 0x2000ca0d 0x0420c780 0xd00e0619 0x80c00780 + 0x10034003 0x00000780 0x103f8019 0x000fffff + 0x3005000d 0xc4100782 0x2000060d 0x04004780 + 0x300609fd 0x6c0107c8 0x10000005 0x0403c780 + 0x10000a05 0x0403c280 0x00020605 0xc0000780 + 0x30060801 0xac000780 0x04020e01 0xe4204780 + 0x30020611 0xc4100780 0x04000e01 0xe4200780 + 0x861ffe03 0x00000000 0x308407fd 0x6c4187c8 + 0xa004c003 0x00000000 0x1004c003 0x00000280 + 0x00000805 0xc0000780 0xd4043809 0x20000780 + 0x201c8805 0x00000043 0x3800c1fd 0x6c2047c8 + 0x21000805 0x04414280 0x0000020d 0xc0000780 + 0x3800c001 0xac200780 0x1c00c005 0x0423c780 + 0x04020e01 0xe4204780 0x04000e01 0xe4200780 0xf0000001 0xe0000002 0x861ffe03 0x00000000 - 0x308501fd 0x6c4187c8 0xa005f003 0x00000000 - 0x1005f003 0x00000280 0x20008011 0x00000007 - 0x00020809 0xc0000780 0x1000000d 0x0403c780 - 0x3801cffd 0x6c2047c8 0x1000080d 0x0403c280 - 0x00020605 0xc0000780 0xd408380d 0x20000780 - 0x00020005 0xc0000780 0x3801ce05 0xac200780 - 0x1c00c00d 0x0423c780 0x04020e01 0xe420c780 - 0x04000e01 0xe4204780 0xf0000001 0xe0000002 - 0x861ffe03 0x00000000 0x308001fd 0x6c4187c8 - 0xa0070003 0x00000000 0x10070003 0x00000280 - 0x20208011 0x00000003 0x00020809 0xc0000780 - 0x1000000d 0x0403c780 0x3801cffd 0x6c2047c8 - 0x1000080d 0x0403c280 0x00020605 0xc0000780 - 0xd408380d 0x20000780 0x00020005 0xc0000780 - 0x3801ce0d 0xac200780 0x1c00c005 0x0423c780 - 0x04020e01 0xe4204780 0x04000e01 0xe420c780 + 0x308607fd 0x6c4187c8 0xa005b003 0x00000000 + 0x1005b003 0x00000280 0x00000805 0xc0000780 + 0xd4023809 0x20000780 0x201c8805 0x00000043 + 0x3800c1fd 0x6c2047c8 0x21000805 0x0441c280 + 0x0000020d 0xc0000780 0x3800c001 0xac200780 + 0x1c00c005 0x0423c780 0x04020e01 0xe4204780 + 0x04000e01 0xe4200780 0xf0000001 0xe0000002 + 0x861ffe03 0x00000000 0x308007fd 0x6c4187c8 + 0xa006a003 0x00000000 0x1006a003 0x00000280 + 0x00000805 0xc0000780 0xd4013809 0x20000780 + 0x201c8805 0x00000043 0x3800c1fd 0x6c2047c8 + 0x21000805 0x04420280 0x0000020d 0xc0000780 + 0x3800c005 0xac200780 0x1c00c001 0x0423c780 + 0x04020e01 0xe4200780 0x04000e01 0xe4204780 0xf0000001 0xe0000002 0x861ffe03 0x00000000 - 0x300005fd 0x6c00c7c8 0x30000003 0x00000280 - 0xa0004c0d 0x04200780 0x40060a05 0x00000780 - 0x2102ec19 0x00000003 0xa0004e15 0x04200780 - 0x30100211 0xc4100780 0x30060a05 0xc4000780 - 0x60060809 0x00010780 0x2101ec15 0x00000003 - 0x10018011 0x00000003 0x2000040d 0x04004780 - 0x30050811 0xc4000780 0x00020005 0xc0000780 - 0x2003800c 0x20028000 0x20000209 0x04010780 - 0xd4083809 0x20000780 0x30020605 0xc4100780 - 0x20028008 0x1900e000 0x2000c805 0x04204780 + 0x300305fd 0x6c00c7c8 0x30000003 0x00000280 + 0xa0004c01 0x04200780 0x40000a19 0x00000780 + 0x2102ec05 0x00000003 0xa0004e15 0x04200780 + 0x30100c19 0xc4100780 0x30010a05 0xc4000780 + 0x60000801 0x00018780 0x2101ec15 0x00000003 + 0x10018019 0x00000003 0x20000009 0x04004780 + 0x30050c15 0xc4000780 0x00000805 0xc0000780 + 0x20028608 0x2000860c 0x20000201 0x04014780 + 0xd4083809 0x20000780 0x30020405 0xc4100780 + 0x20008608 0x1900e000 0x2000c805 0x04204780 0x30020409 0xc4100780 0xd00e0201 0xa0c00780 0x1500ee00 0x2102e804 0xd00e0201 0xa0c00781 } @@ -1466,7 +1448,7 @@ code { name = cudaFindWastedBits lmem = 0 smem = 2140 - reg = 7 + reg = 6 bar = 1 const { segname = const @@ -1480,43 +1462,43 @@ code { } bincode { 0xa0000005 0x04000780 0x308003fd 0x644107c8 - 0xa0010003 0x00000000 0x30020209 0xc4100780 - 0x10010003 0x00000280 0x1000cc01 0x0423c780 - 0x40014c0d 0x00200780 0x3010060d 0xc4100780 - 0x60004c01 0x0020c780 0x3007000d 0xc4100780 - 0x30060001 0xc4100780 0x20008600 0x2100e800 - 0x20000401 0x04000780 0xd00e0001 0x80c00780 - 0x00000405 0xc0000780 0x04040e01 0xe4200780 - 0x00000405 0xc0000782 0x04000e01 0xe43f0780 + 0xa0010003 0x00000000 0x10010003 0x00000280 + 0x1000cc01 0x0423c780 0x40014c09 0x00200780 + 0x30100409 0xc4100780 0x60004c01 0x00208780 + 0x30050009 0xc4100780 0x30040001 0xc4100780 + 0x20008400 0x20008200 0x30020001 0xc4100780 + 0x2000c801 0x04200780 0xd00e0001 0x80c00780 + 0x00020205 0xc0000780 0x04040e01 0xe4200780 + 0x00020205 0xc0000782 0x04000e01 0xe43f0780 0x04020e01 0xe43f0780 0x861ffe03 0x00000000 0xd0107005 0x20000780 0x347cc1fd 0x6c20c7c8 0x1400c001 0x0423c780 0x10030003 0x00000280 - 0xa000420d 0x04200780 0x1000f811 0x0403c780 - 0x20000815 0x04004780 0x300501fd 0x6400c7c8 - 0xd0104005 0x20000780 0x2400c001 0x04210500 + 0xa0004209 0x04200780 0x1000f80d 0x0403c780 + 0x20000611 0x04004780 0x300401fd 0x6400c7c8 + 0xd0104005 0x20000780 0x2400c001 0x0420c500 0x20000201 0x04000500 0x30020001 0xc4100500 0x2000ca01 0x04200500 0xd00e0001 0x80c00500 - 0x1000f801 0x0403c280 0x00000405 0xc0000780 - 0xd400ce15 0x04204780 0x301f0019 0xec100780 - 0x04000e01 0xe4214780 0xd0060001 0x04008780 + 0x1000f801 0x0403c280 0x00020205 0xc0000780 + 0xd400ce11 0x04204780 0x301f0015 0xec100780 + 0x04000e01 0xe4210780 0xd0050001 0x04008780 0xd4083809 0x20000780 0xd800c001 0x04204780 - 0x04020e01 0xe4200780 0x20000811 0x0400c780 - 0xd0107005 0x20000780 0x3404c1fd 0x6c2107c8 + 0x04020e01 0xe4200780 0x2000060d 0x04008780 + 0xd0107005 0x20000780 0x3403c1fd 0x6c2107c8 0x1400c001 0x0423c780 0x1001a003 0x00000280 0x861ffe03 0x00000000 0x30810201 0x6440c7d0 - 0xa00001fd 0x0c0147c8 0x00000405 0xc0001680 + 0xa00001fd 0x0c0147c8 0x00020205 0xc0001680 0xd4043809 0x20001680 0x1800c001 0x0423d680 0xd400ce01 0x04205680 0x04000e01 0xe4201680 0x861ffe03 0x00000000 0x30820201 0x6440c7e0 - 0xa00001fd 0x0c0147d8 0x00000405 0xc0002680 + 0xa00001fd 0x0c0147d8 0x00020205 0xc0002680 0xd4023809 0x20002680 0x1800c001 0x0423e680 0xd400ce01 0x04206680 0x04000e01 0xe4202680 0x861ffe03 0x00000000 0x30830201 0x6440c7f0 - 0xa00001fd 0x0c0147e8 0x00000405 0xc0003680 + 0xa00001fd 0x0c0147e8 0x00020205 0xc0003680 0xd4013809 0x20003680 0x1800c001 0x0423f680 0xd400ce01 0x04207680 0x04000e01 0xe4203680 0x861ffe03 0x00000000 0xa005b003 0x00000000 - 0x1005b003 0x00002100 0x00000405 0xc0000780 + 0x1005b003 0x00002100 0x00020205 0xc0000780 0x1400ee01 0x0423c780 0xd400ce01 0x04204780 0x04000e01 0xe4200780 0x1400de01 0x0423c780 0xd400ce01 0x04204780 0x04000e01 0xe4200780 @@ -1525,18 +1507,18 @@ code { 0xd400ce01 0x04204780 0x04000e01 0xe4200780 0x1400d001 0x0423c780 0xd400ce01 0x04204780 0x04000e01 0xe4200780 0xf0000001 0xe0000002 - 0x00000405 0xc0000680 0xd40c380d 0x20000680 + 0x00020205 0xc0000680 0xd40c380d 0x20000680 0xd4083809 0x20000680 0x1c00c001 0x0423c680 0xd800c001 0x04204680 0x04020e01 0xe4200680 - 0x861ffe03 0x00000000 0x00000405 0xc0001680 + 0x861ffe03 0x00000000 0x00020205 0xc0001680 0xd40a380d 0x20001680 0xd4083809 0x20001680 0x1c00c001 0x0423d680 0xd800c001 0x04205680 0x04020e01 0xe4201680 0x861ffe03 0x00000000 - 0x00000405 0xc0002680 0xd409380d 0x20002680 + 0x00020205 0xc0002680 0xd409380d 0x20002680 0xd4083809 0x20002680 0x1c00c001 0x0423e680 0xd800c001 0x04206680 0x04020e01 0xe4202680 0x861ffe03 0x00000000 0xa0084003 0x00000000 - 0x10084003 0x00002100 0x00000405 0xc0000780 + 0x10084003 0x00002100 0x00020205 0xc0000780 0xd4083809 0x20000780 0x1800e001 0x0423c780 0xd800c001 0x04204780 0x04020e01 0xe4200780 0x1800d001 0x0423c780 0xd800c001 0x04204780 @@ -1581,7 +1563,7 @@ code { name = cudaComputeLPC lmem = 0 smem = 760 - reg = 8 + reg = 11 bar = 0 const { segname = const @@ -1598,9 +1580,9 @@ code { 0x10013003 0x00000280 0xa0004e0d 0x04200780 0x1000ca09 0x0423c780 0x40050c11 0x00000780 0x60040e11 0x00010780 0x30100811 0xc4100780 - 0x60040c09 0x00010780 0x3007040d 0xc4100780 - 0x30060409 0xc4100780 0x2000060d 0x04008780 - 0x30020009 0xc4100780 0x2103e80c 0x20038408 + 0x60040c09 0x00010780 0x3005040d 0xc4100780 + 0x30040409 0xc4100780 0x20028608 0x20028008 + 0x30020409 0xc4100780 0x2000c809 0x04208780 0xd00e0409 0x80c00780 0x00020005 0xc0000780 0x04001601 0xe4208780 0x307c01fd 0x6c0147ca 0xa0022003 0x00000000 0x10022003 0x00000280 @@ -1637,34 +1619,38 @@ code { 0x00020005 0xc0000780 0xd404e009 0x20000780 0x1900e008 0x1900e004 0x0400b601 0xe4208780 0xd004d809 0x20000780 0x04007601 0xe43f0780 - 0x307ccffd 0x6c20c7c8 0x1800c009 0x0423c780 - 0x1008b003 0x00000280 0x307c01fd 0x640087c8 - 0x213fee11 0x0fffffff 0x1000f815 0x0403c780 - 0xd002d809 0x20000780 0xb08205fd 0x605107d8 - 0x1000040d 0x0403c780 0xa800c019 0xe4204780 - 0xc0830c19 0x00401680 0xc083060d 0x00401680 - 0x9000060c 0x2045881c 0xc0030c19 0x00000780 - 0xd002d809 0x20000780 0x300701fd 0x640187d8 - 0xe806c009 0x00208780 0xd402e009 0x20001500 - 0x1800c00d 0x0423d500 0xe0010c0d 0x0000d500 - 0xe806c005 0x00205500 0x0400b601 0xe420d500 - 0x00020a09 0xc0000680 0x0800f601 0xe4208680 - 0x20400a0d 0x04000780 0x00020609 0xc0000780 - 0xd801d00d 0x20000780 0x30000bfd 0x6400c7d8 - 0xcc06c01d 0x00200780 0x1000f81d 0x0403d280 - 0x30000bfd 0x640147d8 0xb0000e0d 0x00018780 - 0x10000e0d 0x0403d280 0xd401d80d 0x20000780 - 0xbc00c00d 0x0020c780 0x30000bfd 0x640047d8 - 0x04007601 0xe420c780 0xa0087003 0x00000000 - 0x10087003 0x00001280 0xd005e00d 0x20000780 - 0x30050a0d 0xc4100780 0x2d03e00c 0x2003800c - 0xd801d809 0x20000780 0x30020619 0xc4100780 - 0xa800c00d 0xe4204780 0x2000d019 0x04218780 - 0xd00e0c0d 0xa0c00780 0xf0000001 0xe0000002 - 0x20018a15 0x00000003 0x3005cffd 0x6c2147d8 - 0x1005e003 0x00001280 0x3000cffd 0x6420c7c8 - 0x30000003 0x00000280 0xd005e009 0x20000780 - 0x3005ce05 0xc4300780 0x2901e004 0x20018000 + 0x307ccffd 0x6c20c7c8 0x30020011 0xc4100780 + 0x1800c009 0x0423c780 0x10091003 0x00000280 + 0x307c01fd 0x640087c8 0x213fee15 0x0fffffff + 0x1000f819 0x0403c780 0x3002ce1d 0xc4300780 + 0x1000f821 0x0403c780 0xd002d805 0x20000780 + 0xb08205fd 0x605107d8 0x1000040d 0x0403c780 + 0xa400c025 0xe4204780 0xc0831225 0x00401680 + 0xc083060d 0x00401680 0x90000628 0x20488a0c + 0xc00a1225 0x00000780 0xd002d805 0x20000780 + 0x300301fd 0x640187d8 0xe409c009 0x00208780 + 0x00000805 0xc0001500 0xd402e009 0x20001500 + 0x1800c00d 0x0423d500 0xe001120d 0x0000d500 + 0xe809c005 0x00205500 0x0400b601 0xe420d500 + 0x00000c05 0xc0000680 0x0400f601 0xe4208680 + 0x20400c0d 0x04010780 0x00000605 0xc0000780 + 0xd401d009 0x20000780 0x30040dfd 0x6400c7d8 + 0xc809c029 0x00200780 0x1000f829 0x0403d280 + 0x30040dfd 0x640147d8 0xb000140d 0x00024780 + 0x00000809 0xc0000780 0x1000140d 0x0403d280 + 0xd801d80d 0x20000780 0xbc00c00d 0x0020c780 + 0x30040dfd 0x640047d8 0x08007601 0xe420c780 + 0xa008c003 0x00000000 0x1008c003 0x00001280 + 0xd005e009 0x20000780 0x3005100d 0xc4100780 + 0x2903e00c 0x2003800c 0xd401d805 0x20000780 + 0x30020625 0xc4100780 0xa400c00d 0xe4204780 + 0x2000d025 0x04224780 0xd00e120d 0xa0c00780 + 0xf0000001 0xe0000002 0x20048c19 0x00000003 + 0x30070dfd 0x6c0147d8 0x20019021 0x00000003 + 0x10061003 0x00001280 0x3000cffd 0x6420c7c8 + 0x30000003 0x00000280 0xd005e005 0x20000780 + 0x3005ce05 0xc4300780 0x2400c005 0x04204780 + 0x00000805 0xc0000780 0x20000001 0x04004780 0xd403d805 0x20000780 0x30020005 0xc4100780 0x1500e000 0x2101f004 0xd00e0201 0xa0c00781 } @@ -1679,101 +1665,99 @@ code { segname = const segnum = 1 offset = 0 - bytes = 24 + bytes = 28 mem { - 0x000003ff 0x0000002f 0x0000001f 0x00000001 - 0x000fffff 0x0000000e + 0x000003ff 0x0000002f 0x00000030 0x0000001f + 0x00000001 0x000fffff 0x0000000e } } bincode { 0xd0800205 0x00400780 0xa0000215 0x04000780 0xa0000019 0x04000780 0x30040a01 0xc4100780 0x20000c05 0x04000780 0x308103fd 0x644107c8 - 0xa0011003 0x00000000 0x3002021d 0xc4100780 - 0x10011003 0x00000280 0xa0004e01 0x04200780 - 0x30070009 0xc4100780 0x30060001 0xc4100780 - 0x20008400 0x2100ee00 0x20000e01 0x04000780 - 0xd00e0001 0x80c00780 0x00000e05 0xc0000780 - 0x04025601 0xe4200780 0xf0000001 0xe0000002 - 0x861ffe03 0x00000000 0xa0004c09 0x04200780 - 0x1000d201 0x0423c780 0x4004020d 0x00000780 - 0x3010060d 0xc4100780 0x6004000d 0x0000c780 - 0x1000d401 0x0423c780 0x40010c11 0x00000780 - 0x60000e11 0x00010780 0x30100811 0xc4100780 - 0x60000c01 0x00010780 0x308203fd 0x6c4107c8 - 0xa0033003 0x00000000 0x20000025 0x04004780 - 0x10033003 0x00000280 0xd0095805 0x20000780 - 0x2400c001 0x04204780 0x30001201 0xac000780 - 0x308201fd 0x6c40c7c8 0xa0031003 0x00000000 - 0x10030003 0x00000280 0xd0096005 0x20000780 - 0x2400c001 0x04224780 0x30020001 0xc4100780 + 0x60844e01 0x00604500 0x30020001 0xc4100500 + 0x2000ce01 0x04200500 0xd00e0001 0x80c00500 + 0x00020205 0xc0000500 0x04025601 0xe4200500 + 0x861ffe03 0x00000000 0xa0004c0d 0x04200780 + 0x1000d201 0x0423c780 0x40060209 0x00000780 + 0x30100409 0xc4100780 0x60060009 0x00008780 + 0x1000d401 0x0423c780 0x40010811 0x00000780 + 0x60000a11 0x00010780 0x30100811 0xc4100780 + 0x60000801 0x00010780 0x308303fd 0x6c4107c8 + 0xa002d003 0x00000000 0x20000021 0x04004780 + 0x1002d003 0x00000280 0xd0095805 0x20000780 + 0x2400c001 0x04204780 0x30001001 0xac000780 + 0x308301fd 0x6c40c7c8 0xa002b003 0x00000000 + 0x1002a003 0x00000280 0xd0096005 0x20000780 + 0x2400c001 0x04220780 0x30020001 0xc4100780 0x2000cc01 0x04200780 0x20008001 0x0ffffffb - 0xd00e000d 0x80c00780 0x1400d401 0x0423c780 - 0x30000601 0xec000780 0x10031003 0x00000780 - 0x1000f801 0x0403c780 0x00000e05 0xc0000782 + 0xd00e0009 0x80c00780 0x1400d401 0x0423c780 + 0x30000401 0xec000780 0x1002b003 0x00000780 + 0x1000f801 0x0403c780 0x00020205 0xc0000782 0x04001601 0xe4200780 0x1000d401 0x0423c782 - 0x4005000d 0x00000780 0x60040211 0x0000c780 - 0x10018021 0x00000003 0x1000d00d 0x0423c780 - 0x30100811 0xc4100780 0x3003100d 0xc4000780 - 0x60040021 0x00010780 0x3003900c 0x1100f200 - 0x3003d411 0xa4200780 0x4001100d 0x00000780 - 0x6000120d 0x0000c780 0x3010060d 0xc4100780 - 0x60001001 0x0000c780 0x30010001 0x6c0107d0 - 0xa00001fd 0x0c0147c8 0xa004e003 0x00000000 - 0x1004d003 0x00001100 0xd0096005 0x20000780 - 0x2400c001 0x04224780 0x30020001 0xc4100780 - 0x2000cc01 0x04200780 0xd00e000d 0x80c00780 - 0x1400d401 0x0423c780 0x30000601 0xec000780 - 0x1004e003 0x00000780 0x1000f801 0x0403c780 - 0x00000e05 0xc0000782 0x04005601 0xe4200780 + 0x40070009 0x00000780 0x60060211 0x00008780 + 0x1001801d 0x00000003 0x1000d009 0x0423c780 + 0x30100811 0xc4100780 0x30020e09 0xc4000780 + 0x6006001d 0x00010780 0x30028e08 0x1100f200 + 0x3002d411 0xa4200780 0x40011009 0x00000780 + 0x60001209 0x00008780 0x30100409 0xc4100780 + 0x60001001 0x00008780 0x30010001 0x6c0107d0 + 0xa00001fd 0x0c0147c8 0xa0048003 0x00000000 + 0x10047003 0x00001100 0xd0096005 0x20000780 + 0x2400c001 0x04220780 0x30020001 0xc4100780 + 0x2000cc01 0x04200780 0xd00e0009 0x80c00780 + 0x1400d401 0x0423c780 0x30000401 0xec000780 + 0x10048003 0x00000780 0x1000f801 0x0403c780 + 0x00020205 0xc0000782 0x04005601 0xe4200780 0x861ffe03 0x00000000 0xd0095805 0x20000780 - 0x3500e029 0x00000003 0x307c15fd 0x6c0187d8 - 0x1000f80d 0x0403c780 0x1400c001 0x0423c780 - 0x10068003 0x00001280 0x20001401 0x04004780 - 0x200b8029 0x00000003 0x102c8001 0x00000003 - 0x00021409 0xc0000780 0x00000005 0xc0000780 - 0x1000f829 0x0403c780 0xd4098011 0x20000780 - 0xd801000d 0x20000780 0x20019429 0x00000003 - 0x1000c001 0x0423c784 0xd0095811 0x20000780 - 0x6c00c00d 0x8020c780 0x300ac1fd 0x6c2147dc - 0xd8000809 0x20000780 0xd4000805 0x20000780 - 0x1000c001 0x0423c784 0x1005d003 0x00001280 - 0xd0096809 0x20000780 0x3009002d 0x6c00c780 - 0x1000f829 0x0403c780 0x00000e05 0xc0000780 - 0x1800c001 0x0423c780 0xa000161d 0x2c014780 - 0x10000629 0x2440c280 0x30000601 0xec000780 - 0xd4015805 0x20000780 0xd00715fd 0x040007c8 + 0x3500e009 0x00000003 0x307c05fd 0x6c0187d8 + 0x1000f825 0x0403c780 0x1400c001 0x0423c780 + 0x10062003 0x00001280 0x20000401 0x04004780 + 0xd0095809 0x20000780 0x200b8001 0x00000003 + 0x3802c009 0xc4300780 0x00020005 0xc0000780 + 0x102c8029 0x00000003 0x1800c001 0x0423c780 + 0x202c842d 0x00000003 0x00001409 0xc0000780 + 0xd809800d 0x20000780 0x20049429 0x00000003 + 0xd4010009 0x20000780 0x1c00c009 0x0423c780 + 0x300b15fd 0x640147d8 0x6802c025 0x80224780 + 0xd4000805 0x20000780 0x10059003 0x00001280 + 0xd0096809 0x20000780 0x30080029 0x6c00c780 + 0x1000f809 0x0403c780 0x00020205 0xc0000780 + 0x1800c001 0x0423c780 0xa0001429 0x2c014780 + 0x10000809 0x2440c280 0x30001201 0xec000780 + 0xd4015805 0x20000780 0xd00a05fd 0x040007c8 0x2440c001 0x04200780 0xd009a805 0x20000780 - 0x2400c00d 0x04224680 0x3002060d 0xc4100680 - 0x2000ca0d 0x0420c680 0xd00e0601 0xa0c00680 + 0x2400c009 0x04220680 0x30020409 0xc4100680 + 0x2000ca09 0x04208680 0xd00e0401 0xa0c00680 0x1000f801 0x0403c100 0x861ffe03 0x00000000 - 0x301f001d 0xec100780 0x30010025 0xc4100780 - 0x1100f20c 0x10008200 0xd0090e1d 0x04008780 - 0x200af003 0x00000780 0x20000201 0x04000780 - 0x00020005 0xc0000780 0x30840e01 0xac400780 + 0x301f0021 0xec100780 0x30010025 0xc4100780 + 0x1100f208 0x10008200 0xd0091021 0x04008780 + 0x200ab003 0x00000780 0x20000201 0x04000780 + 0x00020005 0xc0000780 0x30851001 0xac400780 0x04001601 0xe4200780 0x861ffe03 0x00000000 - 0xd0095805 0x20000780 0x1000d20d 0x0423c780 + 0xd0095805 0x20000780 0x1000d209 0x0423c780 0x20018a05 0x00000003 0x1000d201 0x0423c780 - 0x3503e00c 0x4001041c 0x60000625 0x0001c780 - 0x4007041d 0x00000780 0x30101225 0xc4100780 - 0x6006061d 0x0001c780 0x200005fd 0x040187c8 - 0x60000401 0x00024780 0x30100e09 0xc4100780 - 0x307cd3fd 0x6c20c7d8 0x60060401 0x00008100 - 0x1009f003 0x00001280 0x2101f205 0x00000003 - 0x40010c05 0x00018780 0x200b8209 0x00000003 - 0x00020405 0xc0000780 0xa009e003 0x00000000 - 0x2000d209 0x04204780 0x20018205 0x00000003 - 0x3605c20d 0xec200780 0x300203fd 0x6c0147c8 - 0x20000001 0x0400c780 0x10099003 0x00000280 + 0x3502e008 0x40010420 0x60000625 0x00020780 + 0x40050421 0x00000780 0x30101225 0xc4100780 + 0x60040621 0x00020780 0x200007fd 0x040187c8 + 0x60000401 0x00024780 0x3010100d 0xc4100780 + 0x307cd3fd 0x6c20c7d8 0x60040401 0x0000c100 + 0x1009b003 0x00001280 0x2101f205 0x00000003 + 0x40418c04 0x2101f208 0x30020205 0xc4100780 + 0x30020409 0xc4100780 0xa009a003 0x00000000 + 0x202c8205 0x00000003 0x202c8409 0x00000003 + 0x00000205 0xc0000780 0x20048205 0x00000003 + 0x3405c00d 0xec200780 0x300203fd 0x640147c8 + 0x20000001 0x0400c780 0x10094003 0x00000280 0xf0000001 0xe0000002 0x300609fd 0x640107c8 - 0x30850bfd 0x6440c2c8 0x30000003 0x00000100 - 0x2101f009 0x00000003 0x100f8005 0x00000003 - 0x30020205 0xc4000780 0x40034e0d 0x00200780 - 0x3010060d 0xc4100780 0x30020a09 0xc4000780 - 0x60024e0d 0x0020c780 0x20069004 0x20028608 + 0x30860bfd 0x6440c2c8 0x30000003 0x00000100 + 0x2101f005 0x00000003 0x100f8009 0x00000003 + 0x30010409 0xc4000780 0x40054e0d 0x00200780 + 0x30100611 0xc4100780 0x30010a0d 0xc4000780 + 0x60044e09 0x00210780 0x20068e04 0x20038408 0x20000205 0x04008780 0x30020205 0xc4100780 0x2000c805 0x04204780 0xd00e0201 0xa0c00780 - 0x30000003 0x00000780 0xa0000625 0x04114780 + 0x30000003 0x00000780 0xa0000425 0x04114780 0xa0001229 0x44004780 0xa000002d 0x04114780 0x90001431 0x00000780 0xa0001629 0x44064780 0x203e9831 0x0fffffff 0xc00c1429 0x0000c7c0 @@ -1785,10 +1769,10 @@ code { 0x40122a31 0x00000780 0x60132831 0x00030780 0x30101831 0xc4100780 0x60122831 0x00030780 0x3000182d 0x0402c780 0x300b1225 0x6400c780 - 0xd0000601 0x04008780 0x301f0001 0xe4100780 + 0xd0000401 0x04008780 0x301f0001 0xe4100780 0x30001229 0x04028780 0xa0000025 0x2c014780 - 0xd00a1225 0x04008780 0x307c07fd 0x6c0147c8 - 0x20000001 0x04024780 0xd0030001 0x0402c500 + 0xd00a1225 0x04008780 0x307c05fd 0x6c0147c8 + 0x20000001 0x04024780 0xd0020001 0x0402c500 0x30000003 0x00000780 0xf0000001 0xe0000001 } } @@ -1796,94 +1780,90 @@ code { name = cudaEstimateResidual1 lmem = 0 smem = 2412 - reg = 7 + reg = 6 bar = 1 const { segname = const segnum = 1 offset = 0 - bytes = 32 + bytes = 36 mem { - 0x000003ff 0x00000020 0x0000002f 0x0000001f - 0x007fffff 0x0000007f 0x0000003f 0x00000040 + 0x000003ff 0x00000020 0x0000002f 0x00000030 + 0x0000001f 0x007fffff 0x0000007f 0x0000003f + 0x00000040 } } bincode { 0xd0800209 0x00400780 0xa0000001 0x04000780 - 0x60200401 0x00000003 0x308201fd 0x644107c8 - 0xa000f003 0x00000000 0x3002000d 0xc4100780 - 0x1000f003 0x00000280 0xa0004e05 0x04200780 - 0x30070209 0xc4100780 0x30060205 0xc4100780 - 0x20018404 0x2101ec04 0x20000605 0x04004780 - 0xd00e0205 0x80c00780 0x00000605 0xc0000780 - 0x04045201 0xe4204780 0x307c0005 0x6c0087d2 - 0xa00003fd 0x0c0147c8 0xa001e003 0x00000000 - 0x1001e003 0x00001100 0x1000d005 0x0423c780 + 0x60200401 0x00000003 0x20098005 0x00000003 + 0x308201fd 0x644107c8 0x00020205 0xc0000780 + 0x60864e05 0x00600500 0x30020205 0xc4100500 + 0x2000cc05 0x04204500 0xd00e0205 0x80c00500 + 0x04044001 0xe4204500 0x307c0005 0x6c0087d0 + 0xa00003fd 0x0c0147c8 0xa001a003 0x00000000 + 0x1001a003 0x00001100 0x1000d005 0x0423c780 0x40034c09 0x00200780 0x30100409 0xc4100780 0x60024c05 0x00208780 0x0004b201 0xe4204780 - 0xd012c809 0x20000780 0xd0114805 0x20000780 - 0x1100f004 0x1900e008 0x2501e010 0x2542ee04 - 0x30040205 0xac000780 0x0004b401 0xe4204780 + 0xd012c80d 0x20000780 0xd0114809 0x20000780 + 0x1100f004 0x1d00e008 0x2901e00c 0x2942ee04 + 0x30030205 0xac000780 0x0004b401 0xe4204780 0xf0000001 0xe0000002 0x861ffe03 0x00000000 - 0xd012d005 0x20000780 0x3400c1fd 0x6c20c7d8 - 0xa002f003 0x00000000 0x1002e003 0x00001280 - 0xd012c809 0x20000780 0xd0115005 0x20000780 - 0x1900e004 0x2501e004 0x20000005 0x04004780 + 0xd012d009 0x20000780 0x3800c1fd 0x6c20c7d8 + 0xa002b003 0x00000000 0x1002a003 0x00001280 + 0xd012c80d 0x20000780 0xd0115009 0x20000780 + 0x1d00e004 0x2901e004 0x20000005 0x04004780 0x30020205 0xc4100780 0x2000ca05 0x04204780 - 0xd00e0209 0x80c00780 0x1400d405 0x0423c780 - 0x30010405 0xec000780 0x1002f003 0x00000780 - 0x1000f805 0x0403c780 0x00000605 0xc0000782 - 0x30830009 0x6c40c7e0 0x04001201 0xe4204780 - 0xa00005fd 0x0c0147d8 0xa0047003 0x00000000 - 0x10047003 0x00002100 0xd012d005 0x20000780 - 0x2000d005 0x04200780 0x3401c1fd 0x6c20c7e8 - 0x00020205 0xc0000780 0xa0046003 0x00000000 - 0x10045003 0x00002280 0xd012c80d 0x20000780 - 0xd0115009 0x20000780 0x1d00e004 0x2100f008 - 0x2901e004 0x20018404 0x30020205 0xc4100780 + 0xd00e0209 0x80c00780 0x1800d405 0x0423c780 + 0x30010405 0xec000780 0x1002b003 0x00000780 + 0x1000f805 0x0403c780 0x30840009 0x6c40c7e2 + 0x04000001 0xe4204780 0xa00005fd 0x0c0147d8 + 0xa0043003 0x00000000 0x10043003 0x00002100 + 0xd012d009 0x20000780 0x2000d005 0x04200780 + 0x3801c1fd 0x6c20c7e8 0x00020209 0xc0000780 + 0xa0042003 0x00000000 0x10041003 0x00002280 + 0xd012c811 0x20000780 0xd011500d 0x20000780 + 0x1000c005 0x0423c784 0x2100f008 0x2d01e004 + 0x20000405 0x04004780 0x30020205 0xc4100780 0x2000ca05 0x04204780 0xd00e0209 0x80c00780 - 0x1800d405 0x0423c780 0x30010405 0xec000780 - 0x10046003 0x00000780 0x1000f805 0x0403c780 - 0x04001201 0xe4204782 0xf0000001 0xe0000002 - 0x861ffe03 0x00000000 0xd0114805 0x20000780 - 0x3500e005 0x00000003 0x307c03fd 0x6c0187e8 - 0x1000f811 0x0403c780 0x1005d003 0x00002280 - 0xd0114809 0x20000780 0x20098009 0x00000003 - 0x3802c005 0xc4300780 0x00020405 0xc0000780 - 0x10248015 0x00000003 0x2800c009 0x04200780 - 0x20248219 0x00000003 0x00000a09 0xc0000780 - 0xd8118009 0x20000780 0x1800c005 0x0423c780 - 0x20048a15 0x00000003 0x6601c211 0x80210780 - 0x30060bfd 0x640147e8 0x10055003 0x00002280 - 0x1005f003 0x00000780 0xd0114805 0x20000780 - 0x2400c009 0x04200780 0xd0115805 0x20000780 - 0x1400c005 0x0423c780 0x30010805 0xec000780 - 0x00020405 0xc0000780 0x2440d205 0x04204780 - 0xd012d005 0x20000780 0x301f0211 0xec100780 - 0x30010215 0xc4100780 0x3402c005 0x6c210780 - 0xd0050809 0x04008780 0xa0000205 0x2c014780 - 0x30840409 0xac400780 0x40020205 0x00018780 - 0x00000605 0xc0000780 0x04025201 0xe4204780 - 0x861ffe03 0x00000000 0x308501fd 0x6c4107e8 - 0x00000605 0xc0002500 0xd40d480d 0x20002500 - 0xd4094809 0x20002500 0x1c00c005 0x0423e500 - 0x2800c005 0x04206500 0x04025201 0xe4206500 + 0x1c00d405 0x0423c780 0x30010405 0xec000780 + 0x10042003 0x00000780 0x1000f805 0x0403c780 + 0x08001201 0xe4204782 0xf0000001 0xe0000002 + 0x861ffe03 0x00000000 0xd0114809 0x20000780 + 0x3900e005 0x00000003 0x307c03fd 0x6c0187e8 + 0x1000f80d 0x0403c780 0x10058003 0x00002280 + 0xd0114809 0x20000780 0x3802c005 0xc4300780 + 0x10248011 0x00000003 0x2800c009 0x04200780 + 0x20248215 0x00000003 0xd4000009 0x20000780 + 0x0000080d 0xc0000780 0xdc11800d 0x20000780 + 0x1c00c005 0x0423c780 0x20048811 0x00000003 + 0x6a01c20d 0x8020c780 0x300509fd 0x640147e8 + 0x10050003 0x00002280 0x1005a003 0x00000780 + 0xd0114809 0x20000780 0x2800c009 0x04200780 + 0xd0115809 0x20000780 0x1800c005 0x0423c780 + 0x30010605 0xec000780 0x00020409 0xc0000780 + 0x2840d205 0x04204780 0xd012d009 0x20000780 + 0x301f020d 0xec100780 0x30010211 0xc4100780 + 0x3802c005 0x6c210780 0xd0040609 0x04008780 + 0xa0000205 0x2c014780 0x30850409 0xac400780 + 0x40020205 0x00018780 0x04024001 0xe4204780 0x861ffe03 0x00000000 0x308601fd 0x6c4107e8 - 0x00000605 0xc0002500 0xd40b480d 0x20002500 - 0xd4094809 0x20002500 0x1c00c001 0x0423e500 - 0x2800c001 0x04202500 0x04025201 0xe4202500 - 0x861ffe03 0x00000000 0x00000605 0xc0001680 - 0xd40a480d 0x20001680 0xd4094809 0x20001680 - 0x1c00c001 0x0423d680 0x2800c001 0x04201680 - 0x04025201 0xe4201680 0x861ffe03 0x00000000 - 0xa0095003 0x00000000 0x10095003 0x00001100 - 0x00000605 0xc0000780 0xd4094809 0x20000780 + 0xd40d000d 0x20002500 0xd4090009 0x20002500 + 0x1c00c005 0x0423e500 0x2800c005 0x04206500 + 0x04024001 0xe4206500 0x861ffe03 0x00000000 + 0x308701fd 0x6c4107e8 0xd40b000d 0x20002500 + 0xd4090009 0x20002500 0x1c00c001 0x0423e500 + 0x2800c001 0x04202500 0x04024001 0xe4202500 + 0x861ffe03 0x00000000 0xd40a000d 0x20001680 + 0xd4090009 0x20001680 0x1c00c001 0x0423d680 + 0x2800c001 0x04201680 0x04024001 0xe4201680 + 0x861ffe03 0x00000000 0xa008b003 0x00000000 + 0x1008b003 0x00001100 0xd4090009 0x20000780 0x1800e001 0x0423c780 0x2800c001 0x04200780 - 0x04025201 0xe4200780 0x1900f000 0x2900e000 - 0x04025201 0xe4200780 0x1900e800 0x2900e000 - 0x04025201 0xe4200780 0x1900e400 0x2900e000 - 0x04025201 0xe4200780 0x1900e200 0x2900e000 - 0x04025201 0xe4200780 0xf0000001 0xe0000002 + 0x04024001 0xe4200780 0x1900f000 0x2900e000 + 0x04024001 0xe4200780 0x1900e800 0x2900e000 + 0x04024001 0xe4200780 0x1900e400 0x2900e000 + 0x04024001 0xe4200780 0x1900e200 0x2900e000 + 0x04024001 0xe4200780 0xf0000001 0xe0000002 0x30000003 0x00000100 0xa0004c01 0x04200780 0x61002e01 0x00000007 0xd0094805 0x20000780 0x30020005 0xc4100780 0x1500e000 0x2101e804 @@ -1916,75 +1896,72 @@ code { name = cudaCalcLargePartition lmem = 0 smem = 2284 - reg = 10 + reg = 11 bar = 1 const { segname = const segnum = 1 offset = 0 - bytes = 20 + bytes = 24 mem { - 0x000003ff 0x0000002f 0x00000100 0x000fffff - 0x0000000e + 0x000003ff 0x0000002f 0x00000030 0x00000100 + 0x000fffff 0x0000000e } } bincode { 0xd0800205 0x00400780 0xa000020d 0x04000780 - 0xa0000001 0x04000780 0x30040605 0xc4100780 - 0x20000009 0x04004780 0x308105fd 0x644107c8 - 0xa0011003 0x00000000 0x30020411 0xc4100780 - 0x10011003 0x00000280 0xa0004e05 0x04200780 - 0x30070215 0xc4100780 0x30060205 0xc4100780 - 0x20018a04 0x2101ee04 0x20000805 0x04004780 - 0xd00e0205 0x80c00780 0x00000805 0xc0000780 - 0x04041601 0xe4204780 0xf0000001 0xe0000002 + 0xa0000009 0x04000780 0x30040601 0xc4100780 + 0x20000401 0x04000780 0x308101fd 0x644107c8 + 0x60844e05 0x00600500 0x30020205 0xc4100500 + 0x2000ce05 0x04204500 0xd00e0205 0x80c00500 + 0x00020005 0xc0000500 0x04041601 0xe4204500 0x861ffe03 0x00000000 0x307cd3fd 0x6c20c7c8 - 0x1000f819 0x0403c780 0x10046003 0x00000280 + 0x1000f811 0x0403c780 0x10040003 0x00000280 0xa0004c15 0x04200780 0x1000d205 0x0423c780 - 0x400a061d 0x00000780 0x30100e1d 0xc4100780 - 0x600a0405 0x0001c780 0x3082d215 0xac600780 - 0x2000d221 0x04204780 0xa0045003 0x00000000 - 0x30000bfd 0x6c0107c8 0x2001841c 0x20088420 - 0x10000405 0x0403c780 0xd0105805 0x20000780 - 0x3407c1fd 0x6c20c7d8 0x3001d3fd 0x6c2112d8 - 0xa002d003 0x00000000 0x1002c003 0x00001100 - 0xd010a805 0x20000780 0x2400c009 0x0421c780 - 0x30020409 0xc4100780 0x2000ca09 0x04208780 - 0xd00e0425 0x80c00780 0x1002d003 0x00000780 - 0x1000f825 0x0403c780 0x301f1209 0xec100782 - 0x30011225 0xc4100780 0xd0090409 0x04008780 - 0x00000805 0xc0000780 0x30830409 0xac400780 - 0x04001601 0xe4208780 0x861ffe03 0x00000000 - 0xa003f003 0x00000000 0x10000009 0x0403c780 - 0x1003f003 0x00000100 0x200b8025 0x00000003 - 0x00021205 0xc0000780 0x20108409 0x00000003 - 0x3403c025 0xec200780 0x30020bfd 0x6c0107d8 - 0x20000c19 0x04024780 0xd4008005 0x20000780 - 0x10039003 0x00001280 0xf0000001 0xe0000002 - 0x861ffe03 0x00000000 0x20008e1d 0x00000013 - 0x30080ffd 0x6c0047d8 0x20008205 0x00000013 - 0x10021003 0x00001280 0xf0000001 0xe0000002 - 0x30830c05 0xac400780 0x00000805 0xc0000780 + 0x400a0619 0x00000780 0x30100c19 0xc4100780 + 0x600a0419 0x00018780 0x3083d215 0xac600780 + 0xa003f003 0x00000000 0x2106f21c 0x10008004 + 0x30020bfd 0x6c0107c8 0x20068018 0x2007801c + 0xd0105805 0x20000780 0x3406c1fd 0x6c20c7d8 + 0x3001d3fd 0x6c2112d8 0xa0026003 0x00000000 + 0x10025003 0x00001100 0xd010a805 0x20000780 + 0x2400c021 0x04218780 0x30021021 0xc4100780 + 0x2000ca21 0x04220780 0xd00e1021 0x80c00780 + 0x10026003 0x00000780 0x1000f821 0x0403c780 + 0x301f1025 0xec100782 0x30011021 0xc4100780 + 0xd0081221 0x04008780 0x00020005 0xc0000780 + 0x30841021 0xac400780 0x04001601 0xe4220780 + 0x861ffe03 0x00000000 0xa0039003 0x00000000 + 0x10039003 0x00000100 0x30020421 0xc4100780 + 0x30020a25 0xc4100780 0x202c9021 0x00000003 + 0x202c9225 0x00000003 0x00001005 0xc0000780 + 0x20009021 0x00000007 0x3403c029 0xec200780 + 0x300911fd 0x640047d8 0x20000811 0x04028780 + 0x10033003 0x00001280 0xf0000001 0xe0000002 + 0x861ffe03 0x00000000 0x20008c19 0x00000013 + 0x30070dfd 0x6c0047d8 0x20008205 0x00000013 + 0x1001a003 0x00001280 0xf0000001 0xe0000002 + 0x30840805 0xac400780 0x00020005 0xc0000780 0x04021601 0xe4204780 0xd4085809 0x20000780 0x1900f004 0x2901e004 0x04021601 0xe4204780 0x1900e804 0x2901e004 0x04021601 0xe4204780 0x1900e404 0x2901e004 0x04021601 0xe4204780 - 0x1800c205 0x0423c780 0x307c01fd 0x640087c8 - 0x2800c001 0x04204780 0x308407fd 0x6440c2c8 - 0x04021601 0xe4200780 0x30000003 0x00000100 + 0x1800c205 0x0423c780 0x307c05fd 0x640087c8 + 0x2800c005 0x04204780 0x308507fd 0x6440c2c8 + 0x04021601 0xe4204780 0x30000003 0x00000100 0xd0105805 0x20000780 0x2101f019 0x00000003 - 0x100f8005 0x00000003 0x20018609 0x00000003 - 0x1000d201 0x0423c780 0x30060205 0xc4000780 - 0x1100f214 0x41032e1c 0x40000a24 0x3505e014 - 0x30100e21 0xc4100780 0x6001081d 0x00024780 - 0x3006060d 0xc4000780 0x400b0819 0x00000780 - 0x60024e05 0x00220780 0x00000805 0xc0000780 - 0x30100e1d 0xc4100780 0x600a0a11 0x00018780 - 0x2000020d 0x0400c780 0xa0004c05 0x042007c0 - 0x60000801 0x0001c780 0x30100811 0xc4100780 - 0xd4085805 0x20000780 0x20000205 0x0400c780 - 0x600a0801 0x00010100 0x3483c009 0xac600780 - 0x30020205 0xc4100780 0x20028000 0x2101e804 + 0x100f8009 0x00000003 0x20018611 0x00000003 + 0x1000d205 0x0423c780 0x30060415 0xc4000780 + 0x1100f208 0x410b2e20 0x4002121c 0x3502e008 + 0x30101021 0xc4100780 0x6003101d 0x0001c780 + 0x30060619 0xc4000780 0x4005100d 0x00000780 + 0x600a4e21 0x00220780 0x00020005 0xc0000780 + 0x30100e01 0xc4100780 0x60041215 0x0000c780 + 0x20001019 0x04018780 0xa0004c0d 0x042007c0 + 0x60021001 0x00000780 0x30100a05 0xc4100780 + 0xd4085805 0x20000780 0x2000060d 0x04018780 + 0x60041001 0x00004100 0x3484c005 0xac600780 + 0x30020609 0xc4100780 0x20018000 0x2102e804 0xd00e0201 0xa0c00781 } } @@ -1992,15 +1969,16 @@ code { name = cudaCopyBestMethodStereo lmem = 0 smem = 68 - reg = 6 + reg = 4 bar = 1 const { segname = const segnum = 1 offset = 0 - bytes = 16 + bytes = 24 mem { 0x00000003 0x00000004 0x7fffffff 0x0000002f + 0x00000060 0x00000180 } } bincode { @@ -2037,35 +2015,31 @@ code { 0x00001e01 0xe4205500 0x1000d005 0x0423d500 0x00002001 0xe4205500 0xf0000001 0xe0000002 0x861ffe03 0x00000000 0x30830005 0x6440c7e0 - 0xa00003fd 0x0c0147d8 0xa0051003 0x00000000 - 0x10051003 0x00002100 0x41022e05 0x00000003 - 0x3007de0d 0xc4300780 0x3006de11 0xc4300780 - 0x30070209 0xc4100780 0x30060205 0xc4100780 - 0x2004860c 0x20018404 0x30020009 0xc4100780 - 0x2103ea10 0x2101e80c 0x20000405 0x04010780 - 0xd00e0205 0x80c00780 0x20000409 0x0400c780 + 0xa00003fd 0x0c0147d8 0xa004f003 0x00000000 + 0x1004f003 0x00002100 0x3005de05 0xc4300780 + 0x3004de09 0xc4300780 0x20028204 0x20018008 + 0x60884e05 0x00600780 0x30020409 0xc4100780 + 0x3002020d 0xc4100780 0x2000ca05 0x04208780 + 0xd00e0205 0x80c00780 0x2000c809 0x0420c780 0xd00e0405 0xa0c00780 0xf0000001 0xe0000002 - 0xa005f003 0x00000000 0x1005f003 0x00000100 - 0x41022e05 0x00000003 0x3007ce09 0xc4300780 - 0x3006ce0d 0xc4300780 0x30070211 0xc4100780 - 0x30060215 0xc4100780 0x20038404 0x20058808 - 0x2101ea04 0x2102e808 0x20288205 0x00000003 - 0xd00e0205 0x80c00780 0x20288409 0x00000003 - 0xd00e0405 0xa0c00780 0xf0000001 0xe0000002 - 0xa006e003 0x00000000 0x1006e003 0x00001100 - 0x41022e05 0x00000003 0x3007e00d 0xc4300780 - 0x30070209 0xc4100780 0x30060205 0xc4100780 - 0x3006e011 0xc4300780 0x20018404 0x20048608 - 0x30020001 0xc4100780 0x2101e804 0x2102ea08 - 0x20018004 0x20028000 0xd00e0001 0x80c00780 - 0x20008205 0x0000000f 0xd00e0201 0xa0c00780 - 0xf0000001 0xe0000002 0x30000003 0x00000100 - 0x41022e01 0x00000003 0x3007d005 0xc4300780 - 0x3006d009 0xc4300780 0x3007000d 0xc4100780 - 0x30060011 0xc4100780 0x20028200 0x20048604 - 0x2100ea00 0x2101e804 0x20288001 0x00000003 - 0xd00e0001 0x80c00780 0x20288205 0x0000000f - 0xd00e0201 0xa0c00781 + 0xa005b003 0x00000000 0x1005b003 0x00000100 + 0x3007ce05 0xc4300780 0x3006ce09 0xc4300780 + 0x20028208 0x1100e804 0x2000ca09 0x04208780 + 0x61002e05 0x0000001b 0x20288409 0x00000003 + 0xd00e0409 0x80c00780 0x20288205 0x00000003 + 0xd00e0209 0xa0c00780 0xf0000001 0xe0000002 + 0xa0069003 0x00000000 0x10069003 0x00001100 + 0x3005e005 0xc4300780 0x3004e009 0xc4300780 + 0x20028208 0x1100e804 0x20000009 0x04008780 + 0x3002000d 0xc4100780 0x61002e05 0x0000001b + 0x30020401 0xc4100780 0x20038204 0x2100ea00 + 0xd00e0001 0x80c00780 0x20008205 0x0000000f + 0xd00e0201 0xa0c00780 0xf0000001 0xe0000002 + 0x30000003 0x00000100 0x3007d001 0xc4300780 + 0x3006d005 0xc4300780 0x20018004 0x1100e800 + 0x2000ca05 0x04204780 0x61002e01 0x0000001b + 0x20288205 0x00000003 0xd00e0205 0x80c00780 + 0x20288001 0x0000000f 0xd00e0005 0xa0c00781 } } code { @@ -2076,12 +2050,12 @@ code { bar = 0 bincode { 0x10004205 0x0023c780 0xa0000005 0x04000780 - 0x60014c05 0x00204780 0x3001cdfd 0x6c20c7c8 - 0x30000003 0x00000280 0xa0004e09 0x04200780 - 0x1000cc01 0x0423c780 0x41032a0c 0x40040210 + 0x60014c09 0x00204780 0x3002cdfd 0x6c20c7c8 + 0x30000003 0x00000280 0xa0004e05 0x04200780 + 0x1000cc01 0x0423c780 0x41052a0c 0x40020210 0x3010060d 0xc4100780 0x30100811 0xc4100780 - 0x60024a0d 0x0020c780 0x60040011 0x00010780 - 0x20038400 0x20018804 0x30010001 0xc4100780 + 0x60044a0d 0x0020c780 0x60020011 0x00010780 + 0x20038200 0x20028804 0x30010001 0xc4100780 0x30020205 0xc4100780 0x2100ea00 0x2101e804 0xd00e0001 0x80600780 0xd00e0201 0xa0c00781 } diff --git a/CUETools.FlaCudaExe/CUETools.FlaCuda.csproj b/CUETools.FlaCudaExe/CUETools.FlaCuda.csproj index c46e7cf..f093ddd 100644 --- a/CUETools.FlaCudaExe/CUETools.FlaCuda.csproj +++ b/CUETools.FlaCudaExe/CUETools.FlaCuda.csproj @@ -22,7 +22,7 @@ pdbonly true - ..\bin\x64\Release\ + ..\bin\any\Release\ TRACE prompt 4 diff --git a/CUETools.FlaCudaExe/Program.cs b/CUETools.FlaCudaExe/Program.cs index ba32d97..c147f27 100644 --- a/CUETools.FlaCudaExe/Program.cs +++ b/CUETools.FlaCudaExe/Program.cs @@ -35,32 +35,32 @@ namespace CUETools.FlaCudaExe Console.WriteLine(); Console.WriteLine("Options:"); Console.WriteLine(); - Console.WriteLine(" -0 .. -11 Compression level, default 5."); - Console.WriteLine(" -o Output filename, or \"-\" for stdout, or nul."); - Console.WriteLine(" -p # Padding bytes."); - Console.WriteLine(" -q --quiet Quiet mode."); - Console.WriteLine(" --verify Verify during encoding."); - Console.WriteLine(" --no-md5 Don't compute MD5 hash."); - Console.WriteLine(" --no-seektable Don't generate a seektable."); - Console.WriteLine(" --gpu-only Do everything on GPU."); - Console.WriteLine(" --cpu-threads Use additional CPU threads."); + Console.WriteLine(" -0 .. -11 Compression level, default 7; 9..11 are non-subset"); + Console.WriteLine(" -o Output filename, or \"-\" for stdout, or nul"); + Console.WriteLine(" -p # Padding bytes"); + Console.WriteLine(" -q --quiet Quiet mode"); + Console.WriteLine(" --verify Verify during encoding"); + Console.WriteLine(" --no-md5 Don't compute MD5 hash"); + Console.WriteLine(" --no-seektable Don't generate a seektable"); + Console.WriteLine(" --slow-gpu Some encoding stages are done on CPU"); + Console.WriteLine(" --cpu-threads Use additional CPU threads"); Console.WriteLine(); Console.WriteLine("Advanced Options:"); Console.WriteLine(); - Console.WriteLine(" -b # Block size."); - Console.WriteLine(" -v # Variable block size mode (0,4)."); - Console.WriteLine(" -s Stereo decorrelation (independent,search)."); - Console.WriteLine(" -r #[,#] Rice partition order {max} or {min},{max} (0..8)."); + Console.WriteLine(" -b # Block size"); + Console.WriteLine(" -v # Variable block size mode (0,4)"); + Console.WriteLine(" -s Stereo decorrelation (independent,search)"); + Console.WriteLine(" -r #[,#] Rice partition order {max} or {min},{max} (0..8)"); Console.WriteLine(); Console.WriteLine("LPC options:"); Console.WriteLine(); - Console.WriteLine(" -w [,] One or more window functions (bartlett,welch,hann,flattop,tukey)."); - Console.WriteLine(" -l #[,#] Prediction order {max} or {min},{max} (1..32)."); - Console.WriteLine(" --max-precision Coefficients precision search (0..1)."); + Console.WriteLine(" -w [,] Window functions (bartlett,welch,hann,flattop,tukey)"); + Console.WriteLine(" -l #[,#] Prediction order {max} or {min},{max} (1..32)"); + Console.WriteLine(" --max-precision Coefficients precision search (0..1)"); Console.WriteLine(); } - static void Main(string[] args) + static int Main(string[] args) { TextWriter stdout = Console.Out; Console.SetOut(Console.Error); @@ -79,7 +79,8 @@ namespace CUETools.FlaCudaExe orders_per_window = -1, blocksize = -1; int level = -1, padding = -1, vbr_mode = -1; - bool do_md5 = true, do_seektable = true, do_verify = false, gpu_only = false, use_lattice = false; + bool do_md5 = true, do_seektable = true, do_verify = false, gpu_only = true, use_lattice = false; + bool buffered = false; int cpu_threads = 0; bool ok = true; @@ -95,12 +96,14 @@ namespace CUETools.FlaCudaExe do_verify = true; else if (args[arg] == "--no-seektable") do_seektable = false; - else if (args[arg] == "--gpu-only") - gpu_only = true; + else if (args[arg] == "--slow-gpu") + gpu_only = false; else if (args[arg] == "--use-lattice") use_lattice = true; else if (args[arg] == "--no-md5") do_md5 = false; + else if (args[arg] == "--buffered") + buffered = true; else if (args[arg] == "--cpu-threads") ok = (++arg < args.Length) && int.TryParse(args[arg], out cpu_threads); else if ((args[arg] == "-o" || args[arg] == "--output") && ++arg < args.Length) @@ -156,14 +159,14 @@ namespace CUETools.FlaCudaExe } if (!quiet) { - Console.WriteLine("CUETools.FlaCuda, Copyright (C) 2009 Gregory S. Chudov."); + Console.WriteLine("{0}, Copyright (C) 2009 Gregory S. Chudov.", FlaCudaWriter.vendor_string); Console.WriteLine("This is free software under the GNU GPLv3+ license; There is NO WARRANTY, to"); Console.WriteLine("the extent permitted by law. for details."); } if (!ok || input_file == null) { Usage(); - return; + return 1; } if (((input_file == "-" || Path.GetExtension(input_file) == ".flac") && output_file == null)) @@ -172,12 +175,12 @@ namespace CUETools.FlaCudaExe Console.WriteLine("Output file not specified."); Console.WriteLine(); Usage(); - return; + return 2; } IAudioSource audioSource; if (input_file == "-") - audioSource = new WAVReader(Console.OpenStandardInput()); + audioSource = new WAVReader("", Console.OpenStandardInput()); else if (File.Exists(input_file) && Path.GetExtension(input_file) == ".wav") audioSource = new WAVReader(input_file, null); else if (File.Exists(input_file) && Path.GetExtension(input_file) == ".flac") @@ -185,18 +188,19 @@ namespace CUETools.FlaCudaExe else { Usage(); - return; + return 2; } + if (buffered) + audioSource = new AudioPipe(audioSource, FlaCudaWriter.MAX_BLOCKSIZE); if (output_file == null) output_file = Path.ChangeExtension(input_file, "flac"); FlaCudaWriter encoder = new FlaCudaWriter((output_file == "-" || output_file == "nul") ? "" : output_file, - audioSource.BitsPerSample, audioSource.ChannelCount, audioSource.SampleRate, output_file == "-" ? Console.OpenStandardOutput() : - output_file == "nul" ? new NullStream() : null); - if (audioSource.Length != 0) - encoder.FinalSampleCount = (long)audioSource.Length; + output_file == "nul" ? new NullStream() : null, + audioSource.PCM); + encoder.FinalSampleCount = audioSource.Length; IAudioDest audioDest = encoder; - int[,] buff = new int[FlaCudaWriter.MAX_BLOCKSIZE, audioSource.ChannelCount]; + AudioBuffer buff = new AudioBuffer(audioSource, FlaCudaWriter.MAX_BLOCKSIZE); try { @@ -242,25 +246,22 @@ namespace CUETools.FlaCudaExe Usage(); Console.WriteLine(""); Console.WriteLine("Error: {0}.", ex.Message); - return; + return 3; } if (!quiet) { Console.WriteLine("Filename : {0}", input_file); - Console.WriteLine("File Info : {0}kHz; {1} channel; {2} bit; {3}", audioSource.SampleRate, audioSource.ChannelCount, audioSource.BitsPerSample, TimeSpan.FromSeconds(audioSource.Length * 1.0 / audioSource.SampleRate)); + Console.WriteLine("File Info : {0}kHz; {1} channel; {2} bit; {3}", audioSource.PCM.SampleRate, audioSource.PCM.ChannelCount, audioSource.PCM.BitsPerSample, TimeSpan.FromSeconds(audioSource.Length * 1.0 / audioSource.PCM.SampleRate)); } #if !DEBUG try #endif { - do + while (audioSource.Read(buff, -1) != 0) { - uint toRead = audioSource.Length == 0 ? (uint)buff.GetLength(0) : Math.Min((uint)buff.GetLength(0), (uint)audioSource.Remaining); - uint samplesRead = audioSource.Read(buff, toRead); - if (samplesRead == 0) break; - audioDest.Write(buff, 0, (int)samplesRead); + audioDest.Write(buff); TimeSpan elapsed = DateTime.Now - start; if (!quiet) { @@ -268,14 +269,14 @@ namespace CUETools.FlaCudaExe { Console.Error.Write("\rProgress : {0:00}%; {1:0.00}x; {2}/{3}", 100.0 * audioSource.Position / audioSource.Length, - audioSource.Position / elapsed.TotalSeconds / audioSource.SampleRate, + audioSource.Position / elapsed.TotalSeconds / audioSource.PCM.SampleRate, elapsed, TimeSpan.FromMilliseconds(elapsed.TotalMilliseconds / audioSource.Position * audioSource.Length) ); lastPrint = elapsed; } } - } while (true); + } audioDest.Close(); } #if !DEBUG @@ -285,7 +286,7 @@ namespace CUETools.FlaCudaExe Console.WriteLine("Error : {0}", ex.Message); audioDest.Delete(); audioSource.Close(); - return; + return 4; } #endif @@ -294,7 +295,7 @@ namespace CUETools.FlaCudaExe { Console.Error.Write("\r \r"); Console.WriteLine("Results : {0:0.00}x; {2} bytes in {1} seconds;", - audioSource.Position / totalElapsed.TotalSeconds / audioSource.SampleRate, + audioSource.Position / totalElapsed.TotalSeconds / audioSource.PCM.SampleRate, totalElapsed, encoder.TotalSize ); @@ -319,6 +320,7 @@ namespace CUETools.FlaCudaExe encoder.VBRMode ); } + return 0; } } } diff --git a/CUETools.Flake/CUETools.Flake.csproj b/CUETools.Flake/CUETools.Flake.csproj index b30211d..faa4c1a 100644 --- a/CUETools.Flake/CUETools.Flake.csproj +++ b/CUETools.Flake/CUETools.Flake.csproj @@ -22,7 +22,7 @@ pdbonly true - ..\bin\x64\Release\ + ..\bin\any\Release\ TRACE prompt 4 diff --git a/CUETools.Flake/Program.cs b/CUETools.Flake/Program.cs index 94ca046..fba04f2 100644 --- a/CUETools.Flake/Program.cs +++ b/CUETools.Flake/Program.cs @@ -162,7 +162,7 @@ namespace CUETools.FlakeExe IAudioSource audioSource; if (input_file == "-") - audioSource = new WAVReader(Console.OpenStandardInput()); + audioSource = new WAVReader("", Console.OpenStandardInput()); else if (File.Exists(input_file) && Path.GetExtension(input_file) == ".wav") audioSource = new WAVReader(input_file, null); else if (File.Exists(input_file) && Path.GetExtension(input_file) == ".flac") @@ -172,15 +172,17 @@ namespace CUETools.FlakeExe Usage(); return; } + if (buffered) + audioSource = new AudioPipe(audioSource, 0x10000); if (output_file == null) output_file = Path.ChangeExtension(input_file, "flac"); - FlakeWriter flake = new FlakeWriter((output_file == "-" || output_file == "nul") ? "" : output_file, - audioSource.BitsPerSample, audioSource.ChannelCount, audioSource.SampleRate, + FlakeWriter flake = new FlakeWriter((output_file == "-" || output_file == "nul") ? "" : output_file, output_file == "-" ? Console.OpenStandardOutput() : - output_file == "nul" ? new NullStream() : null); - flake.FinalSampleCount = (long)audioSource.Length; - IAudioDest audioDest = buffered ? (IAudioDest)new BufferedWriter(flake, 512 * 1024) : (IAudioDest)flake; - int[,] buff = new int[0x10000, audioSource.ChannelCount]; + output_file == "nul" ? new NullStream() : null, + audioSource.PCM); + flake.FinalSampleCount = audioSource.Length; + IAudioDest audioDest = flake; + AudioBuffer buff = new AudioBuffer(audioSource, 0x10000); try { @@ -235,14 +237,12 @@ namespace CUETools.FlakeExe if (!quiet) { Console.WriteLine("Filename : {0}", input_file); - Console.WriteLine("File Info : {0}kHz; {1} channel; {2} bit; {3}", audioSource.SampleRate, audioSource.ChannelCount, audioSource.BitsPerSample, TimeSpan.FromSeconds(audioSource.Length * 1.0 / audioSource.SampleRate)); + Console.WriteLine("File Info : {0}kHz; {1} channel; {2} bit; {3}", audioSource.PCM.SampleRate, audioSource.PCM.ChannelCount, audioSource.PCM.BitsPerSample, TimeSpan.FromSeconds(audioSource.Length * 1.0 / audioSource.PCM.SampleRate)); } - do + while (audioSource.Read(buff, -1) != 0) { - uint samplesRead = audioSource.Read(buff, Math.Min((uint)buff.GetLength(0), (uint)audioSource.Remaining)); - if (samplesRead == 0) break; - audioDest.Write(buff, 0, (int)samplesRead); + audioDest.Write(buff); TimeSpan elapsed = DateTime.Now - start; if (!quiet) { @@ -250,22 +250,22 @@ namespace CUETools.FlakeExe { Console.Error.Write("\rProgress : {0:00}%; {1:0.00}x; {2}/{3}", 100.0 * audioSource.Position / audioSource.Length, - audioSource.Position / elapsed.TotalSeconds / audioSource.SampleRate, + audioSource.Position / elapsed.TotalSeconds / audioSource.PCM.SampleRate, elapsed, TimeSpan.FromMilliseconds(elapsed.TotalMilliseconds / audioSource.Position * audioSource.Length) ); lastPrint = elapsed; } } - } while (true); - + } audioDest.Close(); + TimeSpan totalElapsed = DateTime.Now - start; if (!quiet) { Console.Error.Write("\r \r"); Console.WriteLine("Results : {0:0.00}x; {1}", - audioSource.Position / totalElapsed.TotalSeconds / audioSource.SampleRate, + audioSource.Position / totalElapsed.TotalSeconds / audioSource.PCM.SampleRate, totalElapsed ); } diff --git a/CUETools.Processor/AudioReadWrite.cs b/CUETools.Processor/AudioReadWrite.cs index 183189d..7143620 100644 --- a/CUETools.Processor/AudioReadWrite.cs +++ b/CUETools.Processor/AudioReadWrite.cs @@ -1,15 +1,10 @@ using System; using System.IO; +using CUETools.CDImage; using CUETools.Codecs; using CUETools.Codecs.ALAC; using CUETools.Codecs.FLAKE; using CUETools.Codecs.FlaCuda; -#if !MONO -using CUETools.Codecs.FLAC; -using CUETools.Codecs.WavPack; -using CUETools.Codecs.APE; -using CUETools.Codecs.TTA; -#endif using CUETools.Codecs.LossyWAV; using System.Collections.Generic; using System.Collections.Specialized; @@ -19,35 +14,33 @@ namespace CUETools.Processor public static class AudioReadWrite { public static IAudioSource GetAudioSource(string path, Stream IO, string extension, CUEConfig config) { + if (extension == ".dummy") + { + using (StreamReader sr = (IO == null ? new StreamReader(path) : new StreamReader(IO))) { + string slen = sr.ReadLine(); + long len; + if (!long.TryParse(slen, out len)) + len = CDImageLayout.TimeFromString(slen) * 588; + return new SilenceGenerator(len); + } + } + if (extension == ".bin") + return new WAVReader(path, IO, AudioPCMConfig.RedBook); CUEToolsFormat fmt; if (!extension.StartsWith(".") || !config.formats.TryGetValue(extension.Substring(1), out fmt)) throw new Exception("Unsupported audio type: " + path); CUEToolsUDC decoder; if (fmt.decoder == null || !config.decoders.TryGetValue(fmt.decoder, out decoder)) throw new Exception("Unsupported audio type: " + path); - switch (decoder.className) - { - case "WAVReader": - return new WAVReader(path, IO); - case "ALACReader": - return new ALACReader(path, IO); - case "FlakeReader": - return new FlakeReader(path, IO); -#if !MONO - case "FLACReader": - return new FLACReader(path, IO, config.disableAsm); - case "WavPackReader": - return new WavPackReader(path, IO, null); - case "APEReader": - return new APEReader(path, IO); - case "TTAReader": - return new TTAReader(path, IO); -#endif - default: - if (decoder.path == null) - throw new Exception("Unsupported audio type: " + path); - return new UserDefinedReader(path, IO, decoder.path, decoder.parameters); - } + if (decoder.path != null) + return new UserDefinedReader(path, IO, decoder.path, decoder.parameters); + if (decoder.type == null) + throw new Exception("Unsupported audio type: " + path); + + object src = Activator.CreateInstance(decoder.type, path, IO); + if (src == null || !(src is IAudioSource)) + throw new Exception("Unsupported audio type: " + path + ": " + decoder.type.FullName); + return src as IAudioSource; } public static IAudioSource GetAudioSource(string path, Stream IO, CUEConfig config) @@ -73,12 +66,12 @@ namespace CUETools.Processor return new LossyWAVReader(lossySource, lwcdfSource); } - public static IAudioDest GetAudioDest(AudioEncoderType audioEncoderType, string path, int bitsPerSample, int channelCount, int sampleRate, long finalSampleCount, int padding, string extension, CUEConfig config) + public static IAudioDest GetAudioDest(AudioEncoderType audioEncoderType, string path, AudioPCMConfig pcm, long finalSampleCount, int padding, string extension, CUEConfig config) { IAudioDest dest; if (audioEncoderType == AudioEncoderType.NoAudio || extension == ".dummy") { - dest = new DummyWriter(path, bitsPerSample, channelCount, sampleRate); + dest = new DummyWriter(path, pcm); dest.FinalSampleCount = finalSampleCount; return dest; } @@ -90,59 +83,44 @@ namespace CUETools.Processor null; if (encoder == null) throw new Exception("Unsupported audio type: " + path); - switch (encoder.className) + if (encoder.path != null) + dest = new UserDefinedWriter(path, null, pcm, encoder.path, encoder.parameters, encoder.default_mode, padding); + else if (encoder.type != null) { - case "WAVWriter": - dest = new WAVWriter(path, bitsPerSample, channelCount, sampleRate, null); - break; - case "FlakeWriter": - dest = new FlakeWriter(path, bitsPerSample, channelCount, sampleRate, null); + object o = Activator.CreateInstance(encoder.type, path, pcm); + if (o == null || !(o is IAudioDest)) + throw new Exception("Unsupported audio type: " + path + ": " + encoder.type.FullName); + dest = o as IAudioDest; + } else + throw new Exception("Unsupported audio type: " + path); + dest.CompressionLevel = encoder.DefaultModeIndex; + dest.FinalSampleCount = finalSampleCount; + switch (encoder.type.FullName) + { + case "CUETools.Codecs.FLAKE.FlakeWriter": ((FlakeWriter)dest).PaddingLength = padding; - ((FlakeWriter)dest).CompressionLevel = encoder.DefaultModeIndex; - //dest = new BufferedWriter(dest, 128 * 1024); break; - case "FlaCudaWriter": - dest = new FlaCudaWriter(path, bitsPerSample, channelCount, sampleRate, null); + case "CUETools.Codecs.FlaCuda.FlaCudaWriter": ((FlaCudaWriter)dest).PaddingLength = padding; - ((FlaCudaWriter)dest).CompressionLevel = encoder.DefaultModeIndex; ((FlaCudaWriter)dest).DoVerify = config.flaCudaVerify; ((FlaCudaWriter)dest).GPUOnly = config.flaCudaGPUOnly; - break; - case "ALACWriter": - dest = new ALACWriter(path, bitsPerSample, channelCount, sampleRate, null); + ((FlaCudaWriter)dest).CPUThreads = config.FlaCudaThreads ? 1 : 0; + break; + case "CUETools.Codecs.ALAC.ALACWriter": ((ALACWriter)dest).PaddingLength = padding; - ((ALACWriter)dest).CompressionLevel = encoder.DefaultModeIndex; - //dest = new BufferedWriter(dest, 128 * 1024); break; -#if !MONO - case "FLACWriter": - dest = new FLACWriter(path, bitsPerSample, channelCount, sampleRate); - ((FLACWriter)dest).PaddingLength = padding; - ((FLACWriter)dest).CompressionLevel = encoder.DefaultModeIndex; - ((FLACWriter)dest).Verify = config.flacVerify; - ((FLACWriter)dest).DisableAsm = config.disableAsm; + case "CUETools.Codecs.FLAC.FLACWriter": + dest.Options = string.Format("{0}{1}--padding-length {2}", + config.disableAsm ? "--disable-asm " : "", + config.flacVerify ? "--verify " : "", + padding); break; - case "WavPackWriter": - dest = new WavPackWriter(path, bitsPerSample, channelCount, sampleRate); - ((WavPackWriter)dest).CompressionMode = encoder.DefaultModeIndex; - ((WavPackWriter)dest).ExtraMode = config.wvExtraMode; - ((WavPackWriter)dest).MD5Sum = config.wvStoreMD5; - break; - case "APEWriter": - dest = new APEWriter(path, bitsPerSample, channelCount, sampleRate); - ((APEWriter)dest).CompressionLevel = encoder.DefaultModeIndex; - break; - case "TTAWriter": - dest = new TTAWriter(path, bitsPerSample, channelCount, sampleRate); - break; -#endif - default: - if (encoder.path == null) - throw new Exception("Unsupported audio type: " + path); - dest = new UserDefinedWriter(path, bitsPerSample, channelCount, sampleRate, null, encoder.path, encoder.parameters, encoder.default_mode, padding); + case "CUETools.Codecs.WavPack.WavPackWriter": + dest.Options = string.Format("{0}--extra-mode {1}", + config.wvStoreMD5 ? "--md5 " : "", + config.wvExtraMode); break; } - dest.FinalSampleCount = finalSampleCount; return dest; } @@ -150,14 +128,15 @@ namespace CUETools.Processor { string extension = Path.GetExtension(path).ToLower(); string filename = Path.GetFileNameWithoutExtension(path); + AudioPCMConfig pcm = new AudioPCMConfig(bitsPerSample, 2, sampleRate); if (audioEncoderType == AudioEncoderType.NoAudio || audioEncoderType == AudioEncoderType.Lossless || Path.GetExtension(filename).ToLower() != ".lossy") - return GetAudioDest(audioEncoderType, path, bitsPerSample, 2, sampleRate, finalSampleCount, padding, extension, config); + return GetAudioDest(audioEncoderType, path, pcm, finalSampleCount, padding, extension, config); string lwcdfPath = Path.Combine(Path.GetDirectoryName(path), Path.GetFileNameWithoutExtension(filename) + ".lwcdf" + extension); - int lossyBitsPerSample = (config.detectHDCD && config.decodeHDCD && !config.decodeHDCDtoLW16) ? 24 : 16; - IAudioDest lossyDest = GetAudioDest(AudioEncoderType.Lossless, path, lossyBitsPerSample, 2, sampleRate, finalSampleCount, padding, extension, config); - IAudioDest lwcdfDest = audioEncoderType == AudioEncoderType.Hybrid ? GetAudioDest(AudioEncoderType.Lossless, lwcdfPath, bitsPerSample, 2, sampleRate, finalSampleCount, padding, extension, config) : null; - return new LossyWAVWriter(lossyDest, lwcdfDest, bitsPerSample, 2, sampleRate, config.lossyWAVQuality); + AudioPCMConfig lossypcm = new AudioPCMConfig((config.detectHDCD && config.decodeHDCD && !config.decodeHDCDtoLW16) ? 24 : 16, 2, sampleRate); + IAudioDest lossyDest = GetAudioDest(AudioEncoderType.Lossless, path, lossypcm, finalSampleCount, padding, extension, config); + IAudioDest lwcdfDest = audioEncoderType == AudioEncoderType.Hybrid ? GetAudioDest(AudioEncoderType.Lossless, lwcdfPath, lossypcm, finalSampleCount, padding, extension, config) : null; + return new LossyWAVWriter(lossyDest, lwcdfDest, config.lossyWAVQuality, pcm); } } } \ No newline at end of file diff --git a/CUETools.Processor/CUETools.Processor.csproj b/CUETools.Processor/CUETools.Processor.csproj index 1649375..2c6b66c 100644 --- a/CUETools.Processor/CUETools.Processor.csproj +++ b/CUETools.Processor/CUETools.Processor.csproj @@ -23,7 +23,7 @@ pdbonly true - bin\Release\ + ..\bin\any\Release\ TRACE prompt 4 @@ -116,18 +116,10 @@ {F2EC7193-D5E5-4252-9803-5CEB407E910F} CUETools.Codecs.ALAC - - {9AE965C4-301E-4C01-B90F-297AF341ACC6} - CUETools.Codecs.APE - {082D6B9E-326E-4D15-9798-EDAE9EDE70A6} CUETools.Codecs.FLAKE - - {1D1E99BC-6D22-41C0-BD94-FF4DD5EC725B} - CUETools.Codecs.TTA - {6458A13A-30EF-45A9-9D58-E5031B17BEE2} CUETools.Codecs @@ -148,10 +140,6 @@ {8CF07381-BEA2-4AFC-B3DD-9B2F21C65A3A} CUETools.Ripper.SCSI - - {E70FA90A-7012-4A52-86B5-362B699D1540} - CUETools.Codecs.FLAC - {5ADCFD6D-BFEA-4B10-BB45-9083BBB56AF4} Freedb @@ -168,10 +156,6 @@ {74C2036B-2C9B-4FC8-B7BD-AE81A8DCE533} MusicBrainz - - {CC2E74B6-534A-43D8-9F16-AC03FE955000} - CUETools.Codecs.WavPack - {8427CAA5-80B8-4952-9A68-5F3DFCFBDF40} UnRarDotNet diff --git a/CUETools.Processor/Processor.cs b/CUETools.Processor/Processor.cs index 1c3b42a..1d56098 100644 --- a/CUETools.Processor/Processor.cs +++ b/CUETools.Processor/Processor.cs @@ -28,12 +28,15 @@ using System.Text; using System.Globalization; using System.IO; using System.Net; +using System.Security.Policy; using System.Security.Cryptography; using System.Threading; using System.Xml; using System.Drawing; using System.Drawing.Drawing2D; using System.Drawing.Imaging; +using System.Reflection; +using System.Runtime.InteropServices; using HDCDDotNet; using CUETools.Codecs; using CUETools.Codecs.LossyWAV; @@ -44,7 +47,6 @@ using MusicBrainz; using Freedb; #if !MONO using UnRarDotNet; -using CUETools.Codecs.FLAC; #endif using ICSharpCode.SharpZipLib.Zip; using CSScriptLibrary; @@ -616,24 +618,30 @@ namespace CUETools.Processor default_mode = _default_mode; path = _path; parameters = _parameters; - className = null; + type = null; } - public CUEToolsUDC( - string _name, - string _extension, - bool _lossless, - string _supported_modes, - string _default_mode, - string _className) + public CUEToolsUDC(AudioEncoderClass enc, Type enctype) { - name = _name; - extension = _extension; - lossless = _lossless; - supported_modes = _supported_modes; - default_mode = _default_mode; + name = enc.EncoderName; + extension = enc.Extension; + lossless = enc.Lossless; + supported_modes = enc.SupportedModes; + default_mode = enc.DefaultMode; + priority = enc.Priority; path = null; parameters = null; - className = _className; + type = enctype; + } + public CUEToolsUDC(AudioDecoderClass enc, Type dectype) + { + name = enc.DecoderName; + extension = enc.Extension; + lossless = true; + supported_modes = ""; + default_mode = ""; + path = null; + parameters = null; + type = dectype; } public override string ToString() { @@ -643,10 +651,11 @@ namespace CUETools.Processor public string extension = "wav"; public string path = ""; public string parameters = ""; - public string className = ""; + public Type type = null; public string supported_modes = ""; public string default_mode = ""; public bool lossless = false; + public int priority = 0; public string Name { @@ -760,6 +769,15 @@ namespace CUETools.Processor return false; } + public CUEToolsUDC GetDefault(string extension, bool lossless) + { + CUEToolsUDC result = null; + foreach (CUEToolsUDC udc in this) + if (udc.extension == extension && udc.lossless == lossless && (result == null || result.priority < udc.priority)) + result = udc; + return result; + } + public CUEToolsUDC this[string name] { get @@ -788,6 +806,7 @@ namespace CUETools.Processor public bool flacVerify; public bool flaCudaVerify; public bool flaCudaGPUOnly; + public bool flaCudaThreads; public bool preserveHTOA; public int wvExtraMode; public bool wvStoreMD5; @@ -838,6 +857,9 @@ namespace CUETools.Processor public CUEStyle gapsHandling; public bool CopyAlbumArt { get { return copyAlbumArt; } set { copyAlbumArt = value; } } + public bool FlaCudaThreads { get { return flaCudaThreads; } set { flaCudaThreads = value; } } + public bool FlaCudaGPUOnly { get { return flaCudaGPUOnly; } set { flaCudaGPUOnly = value; } } + public bool FlaCudaVerify { get { return flaCudaVerify; } set { flaCudaVerify = value; } } public string ArLogFilenameFormat { get { return arLogFilenameFormat; } set { arLogFilenameFormat = value; } } public string AlArtFilenameFormat { get { return alArtFilenameFormat; } set { alArtFilenameFormat = value; } } public CUEToolsUDCList Encoders @@ -863,6 +885,7 @@ namespace CUETools.Processor flacVerify = false; flaCudaVerify = false; flaCudaGPUOnly = false; + flaCudaThreads = true; preserveHTOA = true; wvExtraMode = 0; wvStoreMD5 = false; @@ -912,17 +935,53 @@ namespace CUETools.Processor language = Thread.CurrentThread.CurrentUICulture.Name; + List encs = new List(); + List decs = new List(); + + encs.Add(typeof(CUETools.Codecs.WAVWriter)); + encs.Add(typeof(CUETools.Codecs.FLAKE.FlakeWriter)); + encs.Add(typeof(CUETools.Codecs.FlaCuda.FlaCudaWriter)); + encs.Add(typeof(CUETools.Codecs.ALAC.ALACWriter)); + + decs.Add(typeof(CUETools.Codecs.WAVReader)); + decs.Add(typeof(CUETools.Codecs.FLAKE.FlakeReader)); + decs.Add(typeof(CUETools.Codecs.ALAC.ALACReader)); + + //ApplicationSecurityInfo asi = new ApplicationSecurityInfo(AppDomain.CurrentDomain.ActivationContext); + //string arch = asi.ApplicationId.ProcessorArchitecture; + //ActivationContext is null most of the time :( + + string arch = Marshal.SizeOf(typeof(IntPtr)) == 8 ? "x64" : "x86"; + string plugins_path = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "plugins (" + arch + ")"); + if (Directory.Exists(plugins_path)) + foreach (string plugin_path in Directory.GetFiles(plugins_path, "*.dll", SearchOption.TopDirectoryOnly)) + { + AssemblyName name = AssemblyName.GetAssemblyName(plugin_path); + Assembly assembly = Assembly.Load(name); + foreach (Type type in assembly.GetExportedTypes()) + { + try + { + if (Attribute.GetCustomAttribute(type, typeof(AudioDecoderClass)) != null) + decs.Add(type); + //if (type.IsClass && !type.IsAbstract && typeof(IAudioDest).IsAssignableFrom(type)) + if (Attribute.GetCustomAttribute(type, typeof(AudioEncoderClass)) != null) + encs.Add(type); + } + catch (Exception ex) + { + System.Diagnostics.Debug.WriteLine(ex.Message); + } + } + } + encoders = new CUEToolsUDCList(); -#if !MONO - encoders.Add(new CUEToolsUDC("libFLAC", "flac", true, "0 1 2 3 4 5 6 7 8", "5", "FLACWriter")); - encoders.Add(new CUEToolsUDC("libwavpack", "wv", true, "fast normal high high+", "normal", "WavPackWriter")); - encoders.Add(new CUEToolsUDC("MAC_SDK", "ape", true, "fast normal high extra insane", "high", "APEWriter")); - encoders.Add(new CUEToolsUDC("ttalib", "tta", true, "", "", "TTAWriter")); -#endif - encoders.Add(new CUEToolsUDC("libFlake", "flac", true, "0 1 2 3 4 5 6 7 8 9 10 11", "7", "FlakeWriter")); - encoders.Add(new CUEToolsUDC("FlaCuda", "flac", true, "0 1 2 3 4 5 6 7 8 9 10 11", "8", "FlaCudaWriter")); - encoders.Add(new CUEToolsUDC("libALAC", "m4a", true, "0 1 2 3 4 5 6 7 8 9 10", "3", "ALACWriter")); - encoders.Add(new CUEToolsUDC("builtin wav", "wav", true, "", "", "WAVWriter")); + foreach (Type type in encs) + { + AudioEncoderClass enc = Attribute.GetCustomAttribute(type, typeof(AudioEncoderClass)) as AudioEncoderClass; + //if (!encoders.TryGetValue(enc.EncoderName)) + encoders.Add(new CUEToolsUDC(enc, type)); + } encoders.Add(new CUEToolsUDC("flake", "flac", true, "0 1 2 3 4 5 6 7 8 9 10 11", "10", "flake.exe", "-%M - -o %O -p %P")); encoders.Add(new CUEToolsUDC("takc", "tak", true, "0 1 2 2e 2m 3 3e 3m 4 4e 4m", "2", "takc.exe", "-e -p%M -overwrite - %O")); encoders.Add(new CUEToolsUDC("ffmpeg alac", "m4a", true, "", "", "ffmpeg.exe", "-i - -f ipod -acodec alac -y %O")); @@ -932,28 +991,24 @@ namespace CUETools.Processor encoders.Add(new CUEToolsUDC("nero aac", "m4a", false, "0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9", "0.4", "neroAacEnc.exe", "-q %M -if - -of %O")); decoders = new Dictionary(); -#if !MONO - decoders.Add("libFLAC", new CUEToolsUDC("libFLAC", "flac", true, "", "", "FLACReader")); - decoders.Add("libwavpack", new CUEToolsUDC("libwavpack", "wv", true, "", "", "WavPackReader")); - decoders.Add("MAC_SDK", new CUEToolsUDC("MAC_SDK", "ape", true, "", "", "APEReader")); - decoders.Add("ttalib", new CUEToolsUDC("ttalib", "tta", true, "", "", "TTAReader")); -#endif - decoders.Add("libFlake", new CUEToolsUDC("libFlake", "flac", true, "", "", "FlakeReader")); - decoders.Add("builtin wav", new CUEToolsUDC("builtin wav", "wav", true, "", "", "WAVReader")); - decoders.Add("builtin alac", new CUEToolsUDC("builtin alac", "m4a", true, "", "", "ALACReader")); + foreach (Type type in decs) + { + AudioDecoderClass dec = Attribute.GetCustomAttribute(type, typeof(AudioDecoderClass)) as AudioDecoderClass; + decoders.Add(dec.DecoderName, new CUEToolsUDC(dec, type)); + } decoders.Add("takc", new CUEToolsUDC("takc", "tak", true, "", "", "takc.exe", "-d %I -")); decoders.Add("ffmpeg alac", new CUEToolsUDC("ffmpeg alac", "m4a", true, "", "", "ffmpeg.exe", "%I -f wav -")); formats = new Dictionary(); - formats.Add("flac", new CUEToolsFormat("flac", CUEToolsTagger.TagLibSharp, true, false, true, true, true, encoders["libFLAC"], null, "libFLAC")); - formats.Add("wv", new CUEToolsFormat("wv", CUEToolsTagger.TagLibSharp, true, false, true, true, true, encoders["libwavpack"], null, "libwavpack")); - formats.Add("ape", new CUEToolsFormat("ape", CUEToolsTagger.TagLibSharp, true, false, false, true, true, encoders["MAC_SDK"], null, "MAC_SDK")); - formats.Add("tta", new CUEToolsFormat("tta", CUEToolsTagger.APEv2, true, false, false, false, true, encoders["ttalib"], null, "ttalib")); - formats.Add("wav", new CUEToolsFormat("wav", CUEToolsTagger.TagLibSharp, true, false, true, false, true, encoders["builtin wav"], null, "builtin wav")); - formats.Add("tak", new CUEToolsFormat("tak", CUEToolsTagger.APEv2, true, false, true, true, true, encoders["takc"], null, "takc")); - formats.Add("m4a", new CUEToolsFormat("m4a", CUEToolsTagger.TagLibSharp, true, true, false, false, true, encoders["ffmpeg alac"], encoders["nero aac"], "builtin alac")); - formats.Add("mp3", new CUEToolsFormat("mp3", CUEToolsTagger.TagLibSharp, false, true, false, false, true, null, encoders["lame vbr"], null)); - formats.Add("ogg", new CUEToolsFormat("ogg", CUEToolsTagger.TagLibSharp, false, true, false, false, true, null, encoders["oggenc"], null)); + formats.Add("flac", new CUEToolsFormat("flac", CUEToolsTagger.TagLibSharp, true, false, true, true, true, encoders.GetDefault("flac", true), null, "libFLAC")); + formats.Add("wv", new CUEToolsFormat("wv", CUEToolsTagger.TagLibSharp, true, false, true, true, true, encoders.GetDefault("wv", true), null, "libwavpack")); + formats.Add("ape", new CUEToolsFormat("ape", CUEToolsTagger.TagLibSharp, true, false, false, true, true, encoders.GetDefault("ape", true), null, "MAC_SDK")); + formats.Add("tta", new CUEToolsFormat("tta", CUEToolsTagger.APEv2, true, false, false, false, true, encoders.GetDefault("tta", true), null, "ttalib")); + formats.Add("wav", new CUEToolsFormat("wav", CUEToolsTagger.TagLibSharp, true, false, true, false, true, encoders.GetDefault("wav", true), null, "builtin wav")); + formats.Add("tak", new CUEToolsFormat("tak", CUEToolsTagger.APEv2, true, false, true, true, true, encoders.GetDefault("tak", true), null, "takc")); + formats.Add("m4a", new CUEToolsFormat("m4a", CUEToolsTagger.TagLibSharp, true, true, false, false, true, encoders.GetDefault("m4a", true), encoders.GetDefault("m4a", false), "builtin alac")); + formats.Add("mp3", new CUEToolsFormat("mp3", CUEToolsTagger.TagLibSharp, false, true, false, false, true, null, encoders.GetDefault("mp3", false), null)); + formats.Add("ogg", new CUEToolsFormat("ogg", CUEToolsTagger.TagLibSharp, false, true, false, false, true, null, encoders.GetDefault("ogg", false), null)); scripts = new Dictionary(); scripts.Add("default", new CUEToolsScript("default", true, @@ -1019,6 +1074,7 @@ return processor.Go(); sw.Save("FLACVerify", flacVerify); sw.Save("FlaCudaVerify", flaCudaVerify); sw.Save("FlaCudaGPUOnly", flaCudaGPUOnly); + sw.Save("FlaCudaThreads", flaCudaThreads); sw.Save("WVExtraMode", wvExtraMode); sw.Save("WVStoreMD5", wvStoreMD5); sw.Save("KeepOriginalFilenames", keepOriginalFilenames); @@ -1148,6 +1204,7 @@ return processor.Go(); flacVerify = sr.LoadBoolean("FLACVerify") ?? false; flaCudaVerify = sr.LoadBoolean("FlaCudaVerify") ?? false; flaCudaGPUOnly = sr.LoadBoolean("FlaCudaGPUOnly") ?? false; + flaCudaThreads = sr.LoadBoolean("FlaCudaThreads") ?? true; wvExtraMode = sr.LoadInt32("WVExtraMode", 0, 6) ?? 0; wvStoreMD5 = sr.LoadBoolean("WVStoreMD5") ?? false; keepOriginalFilenames = sr.LoadBoolean("KeepOriginalFilenames") ?? false; @@ -1566,11 +1623,27 @@ return processor.Go(); } } + public void CopyMetadata(CUESheet metadata) + { + TotalDiscs = metadata.TotalDiscs; + DiscNumber = metadata.DiscNumber; + Year = metadata.Year; + Genre = metadata.Genre; + Artist = metadata.Artist; + Title = metadata.Title; + for (int i = 0; i < Tracks.Count; i++) + { + Tracks[i].Title = metadata.Tracks[i].Title; + Tracks[i].Artist = metadata.Tracks[i].Artist; + } + } + public void FillFromMusicBrainz(MusicBrainz.Release release) { Year = release.GetEvents().Count > 0 ? release.GetEvents()[0].Date.Substring(0, 4) : ""; Artist = release.GetArtist(); Title = release.GetTitle(); + // How to get Genre: http://mm.musicbrainz.org/ws/1/release/6fe1e218-2aee-49ac-94f0-7910ba2151df.html?type=xml&inc=tags //Catalog = release.GetEvents().Count > 0 ? release.GetEvents()[0].Barcode : ""; for (int i = 1; i <= _toc.AudioTracks; i++) { @@ -2025,21 +2098,35 @@ return processor.Go(); if (command == "FILE") { fileType = line.Params[2].ToUpper(); - if ((fileType == "BINARY") || (fileType == "MOTOROLA")) - fileIsBinary = true; - else + fileIsBinary = (fileType == "BINARY") || (fileType == "MOTOROLA"); + if (fileIsBinary) + { + if (!_hasEmbeddedCUESheet && _sourcePaths.Count == 0) + { + try + { + if (_isArchive) + pathAudio = LocateFile(_archiveCUEpath, line.Params[1], _archiveContents); + else + pathAudio = LocateFile(_inputDir, line.Params[1], null); + fileIsBinary = (pathAudio == null); + } + catch { } + } + } + if (!fileIsBinary) { - fileIsBinary = false; if (!_hasEmbeddedCUESheet) { if (_isArchive) pathAudio = LocateFile(_archiveCUEpath, line.Params[1], _archiveContents); - else + else pathAudio = LocateFile(_inputDir, line.Params[1], null); - } else + } + else { pathAudio = _inputPath; - if (_sourcePaths.Count > 0 ) + if (_sourcePaths.Count > 0) throw new Exception("Extra file in embedded CUE sheet: \"" + line.Params[1] + "\"."); } _sourcePaths.Add(pathAudio); @@ -2116,11 +2203,14 @@ return processor.Go(); { if (fileIsBinary) { + // THIS CODE NEVER EXECUTES!!! + fileTimeLengthFrames = timeRelativeToFileStart + 150; sourceInfo.Path = null; sourceInfo.Offset = 0; sourceInfo.Length = 150 * 588; _sources.Add(sourceInfo); + throw new Exception("unexpected BINARY directive"); } else { @@ -2688,7 +2778,7 @@ return processor.Go(); public string GetCommonTag(GetStringTagProvider provider) { if (_hasEmbeddedCUESheet || _hasSingleFilename) - return General.EmptyStringToNull(provider(_fileInfo)); + return _fileInfo == null ? null : General.EmptyStringToNull(provider(_fileInfo)); if (_hasTrackFilenames) { string tagValue = null; @@ -2713,7 +2803,8 @@ return processor.Go(); return GetCommonTag(delegate(TagLib.File file) { return Tagging.TagListToSingleValue(Tagging.GetMiscTag(file, tagName)); }); } - private static string LocateFile(string dir, string file, List contents) { + private static string LocateFile(string dir, string file, List contents) + { List dirList, fileList; string altDir; @@ -2951,19 +3042,23 @@ return processor.Go(); private int GetSampleLength(string path, out TagLib.File fileInfo) { ShowProgress("Analyzing input file...", 0.0, 0.0, path, null); - - TagLib.UserDefined.AdditionalFileTypes.Config = _config; - TagLib.File.IFileAbstraction file = _isArchive - ? (TagLib.File.IFileAbstraction) new ArchiveFileAbstraction(this, path) - : (TagLib.File.IFileAbstraction) new TagLib.File.LocalFileAbstraction(path); - fileInfo = TagLib.File.Create(file); + + if (Path.GetExtension(path) == ".dummy" || Path.GetExtension(path) == ".bin") + { + fileInfo = null; + } else + { + TagLib.UserDefined.AdditionalFileTypes.Config = _config; + TagLib.File.IFileAbstraction file = _isArchive + ? (TagLib.File.IFileAbstraction)new ArchiveFileAbstraction(this, path) + : (TagLib.File.IFileAbstraction)new TagLib.File.LocalFileAbstraction(path); + fileInfo = TagLib.File.Create(file); + } IAudioSource audioSource = AudioReadWrite.GetAudioSource(path, _isArchive ? OpenArchive(path, true) : null, _config); - if ((audioSource.BitsPerSample != 16) || - (audioSource.ChannelCount != 2) || - (audioSource.SampleRate != 44100) || - (audioSource.Length == 0) || - (audioSource.Length >= Int32.MaxValue)) + if (!audioSource.PCM.IsRedBook || + audioSource.Length <= 0 || + audioSource.Length >= Int32.MaxValue) { audioSource.Close(); throw new Exception("Audio format is invalid."); @@ -3979,26 +4074,25 @@ return processor.Go(); public void WriteAudioFilesPass(string dir, CUEStyle style, int[] destLengths, bool htoaToFile, bool noOutput) { - const int buffLen = 0x8000; int iTrack, iIndex; - int[,] sampleBuffer = new int[buffLen, 2]; + AudioBuffer sampleBuffer = new AudioBuffer(AudioPCMConfig.RedBook, 0x10000); TrackInfo track; IAudioSource audioSource = null; IAudioDest audioDest = null; bool discardOutput; int iSource = -1; int iDest = -1; - uint samplesRemSource = 0; + int samplesRemSource = 0; //CDImageLayout updatedTOC = null; if (_writeOffset != 0) { - uint absOffset = (uint)Math.Abs(_writeOffset); + int absOffset = Math.Abs(_writeOffset); SourceInfo sourceInfo; sourceInfo.Path = null; sourceInfo.Offset = 0; - sourceInfo.Length = absOffset; + sourceInfo.Length = (uint)absOffset; if (_writeOffset < 0) { @@ -4007,11 +4101,11 @@ return processor.Go(); int last = _sources.Count - 1; while (absOffset >= _sources[last].Length) { - absOffset -= _sources[last].Length; + absOffset -= (int)_sources[last].Length; _sources.RemoveAt(last--); } sourceInfo = _sources[last]; - sourceInfo.Length -= absOffset; + sourceInfo.Length -= (uint)absOffset; _sources[last] = sourceInfo; } else @@ -4020,12 +4114,12 @@ return processor.Go(); while (absOffset >= _sources[0].Length) { - absOffset -= _sources[0].Length; + absOffset -= (int)_sources[0].Length; _sources.RemoveAt(0); } sourceInfo = _sources[0]; - sourceInfo.Offset += absOffset; - sourceInfo.Length -= absOffset; + sourceInfo.Offset += (uint)absOffset; + sourceInfo.Length -= (uint)absOffset; _sources[0] = sourceInfo; } @@ -4045,10 +4139,10 @@ return processor.Go(); audioDest = GetAudioDest(_destPaths[iDest], destLengths[iDest], hdcdDecoder != null && hdcdDecoder.Decoding ? hdcdDecoder.BitsPerSample : 16, _padding, noOutput); } - uint currentOffset = 0, previousOffset = 0; - uint trackLength = _toc.Pregap * 588; - uint diskLength = 588 * _toc.AudioLength; - uint diskOffset = 0; + int currentOffset = 0, previousOffset = 0; + int trackLength = (int)_toc.Pregap * 588; + int diskLength = 588 * (int)_toc.AudioLength; + int diskOffset = 0; if (_useAccurateRip) _arVerify.Init(); @@ -4075,13 +4169,13 @@ return processor.Go(); for (iIndex = 0; iIndex <= _toc[_toc.FirstAudio + iTrack].LastIndex; iIndex++) { - uint samplesRemIndex = _toc.IndexLength(_toc.FirstAudio + iTrack, iIndex) * 588; + int samplesRemIndex = (int)_toc.IndexLength(_toc.FirstAudio + iTrack, iIndex) * 588; if (iIndex == 1) { previousOffset = currentOffset; currentOffset = 0; - trackLength = _toc[_toc.FirstAudio + iTrack].Length * 588; + trackLength = (int)_toc[_toc.FirstAudio + iTrack].Length * 588; } if ((style == CUEStyle.GapsAppended) && (iIndex == 1)) @@ -4122,10 +4216,10 @@ return processor.Go(); //#endif if (audioSource != null && !_isCD) audioSource.Close(); audioSource = GetAudioSource(++iSource); - samplesRemSource = (uint)_sources[iSource].Length; + samplesRemSource = (int)_sources[iSource].Length; } - uint copyCount = (uint)Math.Min(Math.Min(samplesRemIndex, samplesRemSource), buffLen); + int copyCount = Math.Min(samplesRemIndex, samplesRemSource); if (trackLength > 0 && !_isCD) { @@ -4135,12 +4229,11 @@ return processor.Go(); _isCD ? string.Format("{0}: {1:00} - {2}", audioSource.Path, iTrack + 1, _tracks[iTrack].Title) : audioSource.Path, discardOutput ? null : audioDest.Path); } - if (audioSource.Read(sampleBuffer, copyCount) != copyCount) - throw new Exception("samples read != samples expected"); + copyCount = audioSource.Read(sampleBuffer, copyCount); if (!discardOutput) { if (!_config.detectHDCD || !_config.decodeHDCD) - audioDest.Write(sampleBuffer, 0, (int)copyCount); + audioDest.Write(sampleBuffer); if (_config.detectHDCD && hdcdDecoder != null) { if (_config.wait750FramesForHDCD && diskOffset > 750 * 588 && !hdcdDecoder.Detected) @@ -4158,15 +4251,15 @@ return processor.Go(); { if (_config.decodeHDCD) hdcdDecoder.AudioDest = (discardOutput || noOutput) ? null : audioDest; - hdcdDecoder.Process(sampleBuffer, copyCount); + hdcdDecoder.Process(sampleBuffer.Samples, copyCount); } } } if (_useAccurateRip) { - _arVerify.Write(sampleBuffer, 0, (int)copyCount); + _arVerify.Write(sampleBuffer); if (iTrack > 0 || iIndex > 0) - Tracks[iTrack + (iIndex == 0 ? -1 : 0)].MeasurePeakLevel(sampleBuffer, copyCount); + Tracks[iTrack + (iIndex == 0 ? -1 : 0)].MeasurePeakLevel(sampleBuffer.Samples, copyCount); } currentOffset += copyCount; @@ -4466,12 +4559,24 @@ return processor.Go(); { return _toc; } + set + { + _toc = new CDImageLayout(value); + if (Tracks.Count == 0) + { + for (int iTrack = 0; iTrack < _toc.AudioTracks; iTrack++) + { + //_trackFilenames.Add(string.Format("{0:00}.wav", iTrack + 1)); + _tracks.Add(new TrackInfo()); + } + } + } } private IAudioDest GetAudioDest(string path, int finalSampleCount, int bps, int padding, bool noOutput) { if (noOutput) - return new DummyWriter(path, bps, 2, 44100); + return new DummyWriter(path, new AudioPCMConfig(bps, 2, 44100)); return AudioReadWrite.GetAudioDest(_audioEncoderType, path, finalSampleCount, bps, 44100, padding, _config); } @@ -4488,7 +4593,7 @@ return processor.Go(); { _ripper.Position = 0; //audioSource = _ripper; - audioSource = new AudioPipe(_ripper, 3); + audioSource = new AudioPipe(_ripper, 0x100000); } else #endif if (_isArchive) @@ -4500,6 +4605,8 @@ return processor.Go(); if (sourceInfo.Offset != 0) audioSource.Position = sourceInfo.Offset; + //audioSource = new AudioPipe(audioSource, 0x10000); + return audioSource; } @@ -5224,7 +5331,7 @@ return processor.Go(); _peakLevel = 0; } - public unsafe void MeasurePeakLevel(int[,] samplesBuffer, uint sampleCount) + public unsafe void MeasurePeakLevel(int[,] samplesBuffer, int sampleCount) { fixed (int* s = samplesBuffer) { diff --git a/CUETools.Ripper.Console/CUETools.ConsoleRipper.csproj b/CUETools.Ripper.Console/CUETools.ConsoleRipper.csproj index 0a2b8fe..c21f3bc 100644 --- a/CUETools.Ripper.Console/CUETools.ConsoleRipper.csproj +++ b/CUETools.Ripper.Console/CUETools.ConsoleRipper.csproj @@ -22,7 +22,7 @@ pdbonly true - bin\Release\ + ..\bin\any\Release\ TRACE prompt 4 diff --git a/CUETools.Ripper.Console/Program.cs b/CUETools.Ripper.Console/Program.cs index 40220b7..0ae0cb5 100644 --- a/CUETools.Ripper.Console/Program.cs +++ b/CUETools.Ripper.Console/Program.cs @@ -175,7 +175,7 @@ namespace CUETools.ConsoleRipper } AccurateRipVerify arVerify = new AccurateRipVerify(audioSource.TOC); - int[,] buff = new int[audioSource.BestBlockSize, audioSource.ChannelCount]; + AudioBuffer buff = new AudioBuffer(audioSource, 0x10000); string CDDBId = AccurateRipVerify.CalculateCDDBId(audioSource.TOC); string ArId = AccurateRipVerify.CalculateAccurateRipId(audioSource.TOC); Release release; @@ -207,27 +207,22 @@ namespace CUETools.ConsoleRipper Console.WriteLine("MusicBrainz : {0}", release == null ? "not found" : release.GetArtist() + " - " + release.GetTitle()); //IAudioDest audioDest = new FLACWriter(destFile, audioSource.BitsPerSample, audioSource.ChannelCount, audioSource.SampleRate); - IAudioDest audioDest = new WAVWriter(destFile, audioSource.BitsPerSample, audioSource.ChannelCount, audioSource.SampleRate, null); - audioDest.FinalSampleCount = (long)audioSource.Length; + IAudioDest audioDest = new WAVWriter(destFile, null, audioSource.PCM); + audioDest.FinalSampleCount = audioSource.Length; ProgressMeter meter = new ProgressMeter(); audioSource.ReadProgress += new EventHandler(meter.ReadProgress); - do + while (audioSource.Read(buff, -1) != 0) { - uint toRead = Math.Min((uint)buff.GetLength(0), (uint)audioSource.Remaining); - uint samplesRead = audioSource.Read(buff, toRead); - if (samplesRead == 0) break; - if (samplesRead != toRead) - throw new Exception("samples read != samples requested"); - arVerify.Write(buff, 0, (int)samplesRead); - audioDest.Write(buff, 0, (int)samplesRead); - } while (true); + arVerify.Write(buff); + audioDest.Write(buff); + } TimeSpan totalElapsed = DateTime.Now - meter.realStart; Console.Write("\r \r"); Console.WriteLine("Results : {0:0.00}x; {1:d5} errors; {2:d2}:{3:d2}:{4:d2}", - audioSource.Length / totalElapsed.TotalSeconds / audioSource.SampleRate, + audioSource.Length / totalElapsed.TotalSeconds / audioSource.PCM.SampleRate, audioSource.ErrorsCount, totalElapsed.Hours, totalElapsed.Minutes, totalElapsed.Seconds ); diff --git a/CUETools.Ripper.SCSI/CUETools.Ripper.SCSI.csproj b/CUETools.Ripper.SCSI/CUETools.Ripper.SCSI.csproj index 438e24b..253ba3f 100644 --- a/CUETools.Ripper.SCSI/CUETools.Ripper.SCSI.csproj +++ b/CUETools.Ripper.SCSI/CUETools.Ripper.SCSI.csproj @@ -22,7 +22,7 @@ pdbonly true - bin\Release\ + ..\bin\any\Release\ TRACE prompt 4 diff --git a/CUETools.Ripper.SCSI/SCSIDrive.cs b/CUETools.Ripper.SCSI/SCSIDrive.cs index d43ec20..3dc9228 100644 --- a/CUETools.Ripper.SCSI/SCSIDrive.cs +++ b/CUETools.Ripper.SCSI/SCSIDrive.cs @@ -960,114 +960,50 @@ namespace CUETools.Ripper.SCSI } } - public int[,] Read(int[,] buff) + public unsafe int Read(AudioBuffer buff, int maxLength) { if (_toc == null) throw new Exception("Read: invalid TOC"); - if (_sampleOffset - _driveOffset >= (uint)Length) - return null; - if (_sampleOffset >= (int)Length) - return new int[_driveOffset - (_sampleOffset - (int)Length), ChannelCount]; - if (_sampleOffset < 0) - return new int[-_sampleOffset, ChannelCount]; - PrefetchSector((int)_sampleOffset / 588); - int samplesRead = Math.Min(_currentEnd * 588, (int)Length + _driveOffset) - _sampleOffset; - buff = new int[samplesRead, ChannelCount]; - AudioSamples.BytesToFLACSamples_16(_currentData, (_sampleOffset - _currentStart * 588) * 4, buff, 0, (uint) samplesRead, 2); - _sampleOffset = _currentEnd * 588; - return buff; - } - - public uint Read(int[,] buff, uint sampleCount) - { - if (_toc == null) - throw new Exception("Read: invalid TOC"); - if (_sampleOffset - _driveOffset >= (uint)Length) - return 0; - if (_sampleOffset >= (uint)Length) + buff.Prepare(this, maxLength); + if (Position >= Length) + return 0; + if (_sampleOffset >= Length) { - int samplesRead = _driveOffset - (_sampleOffset - (int)Length); - for (int i = 0; i < samplesRead; i++) - for (int c = 0; c < ChannelCount; c++) - buff[i, c] = 0; - _sampleOffset += samplesRead; - return (uint) samplesRead; + for (int i = 0; i < buff.ByteLength; i++) + buff.Bytes[i] = 0; + return buff.Length; // == Remaining } - if ((uint)(_sampleOffset - _driveOffset + sampleCount) > Length) - sampleCount = (uint)((int)Length + _driveOffset - _sampleOffset); - int silenceCount = 0; - if ((uint)(_sampleOffset + sampleCount) > Length) - { - silenceCount = _sampleOffset + (int)sampleCount - (int)Length; - sampleCount -= (uint) silenceCount; - } - uint pos = 0; if (_sampleOffset < 0) { - uint nullSamplesRead = Math.Min((uint)-_sampleOffset, sampleCount); - for (int i = 0; i < nullSamplesRead; i++) - for (int c = 0; c < ChannelCount; c++) - buff[i, c] = 0; - pos += nullSamplesRead; - sampleCount -= nullSamplesRead; - _sampleOffset += (int)nullSamplesRead; - if (sampleCount == 0) - return pos; + buff.Length = Math.Min(buff.Length, -_sampleOffset); + for (int i = 0; i < buff.ByteLength; i++) + buff.Bytes[i] = 0; + return buff.Length; } - int firstSector = (int)_sampleOffset / 588; - int lastSector = Math.Min((int)(_sampleOffset + sampleCount + 587)/588, (int)_toc.AudioLength); - for (int sector = firstSector; sector < lastSector; sector ++) - { - PrefetchSector(sector); - uint samplesRead = (uint) (Math.Min((int)sampleCount, 588 - (_sampleOffset % 588))); - AudioSamples.BytesToFLACSamples_16(_currentData, (sector - _currentStart) * 4 * 588 + ((int)_sampleOffset % 588) * 4, buff, (int)pos, samplesRead, 2); - pos += samplesRead; - sampleCount -= samplesRead; - _sampleOffset += (int) samplesRead; - } - if (silenceCount > 0) - { - uint nullSamplesRead = (uint)silenceCount; - for (int i = 0; i < nullSamplesRead; i++) - for (int c = 0; c < ChannelCount; c++) - buff[pos + i, c] = 0; - pos += nullSamplesRead; - _sampleOffset += (int)nullSamplesRead; - } - return pos; + PrefetchSector(_sampleOffset / 588); + buff.Length = Math.Min(buff.Length, (int)Length - _sampleOffset); + buff.Length = Math.Min(buff.Length, _currentEnd * 588 - _sampleOffset); + fixed (byte* dest = buff.Bytes, src = &_currentData[(_sampleOffset - _currentStart * 588) * 4]) + AudioSamples.MemCpy(dest, src, buff.ByteLength); + _sampleOffset += buff.Length; + return buff.Length; } - public ulong Length + public long Length { get { if (_toc == null) throw new Exception("invalid TOC"); - return (ulong)588 * _toc.AudioLength; + return 588 * (int)_toc.AudioLength; } } - public int BitsPerSample + public AudioPCMConfig PCM { get { - return 16; - } - } - - public int ChannelCount - { - get - { - return 2; - } - } - - public int SampleRate - { - get - { - return 44100; + return AudioPCMConfig.RedBook; } } @@ -1099,11 +1035,11 @@ namespace CUETools.Ripper.SCSI } } - public ulong Position + public long Position { get { - return (ulong)(_sampleOffset - _driveOffset); + return _sampleOffset - _driveOffset; } set { @@ -1118,7 +1054,7 @@ namespace CUETools.Ripper.SCSI } } - public ulong Remaining + public long Remaining { get { diff --git a/CUETools/CUETools.TestCodecs/ALACWriterTest.cs b/CUETools/CUETools.TestCodecs/ALACWriterTest.cs new file mode 100644 index 0000000..1c9cfb7 --- /dev/null +++ b/CUETools/CUETools.TestCodecs/ALACWriterTest.cs @@ -0,0 +1,103 @@ +// The following code was generated by Microsoft Visual Studio 2005. +// The test owner should check each test for validity. +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.Text; +using System.Collections.Generic; +using System.IO; +using CUETools.Codecs; +using CUETools.Codecs.ALAC; +namespace CUETools.TestCodecs +{ + /// + ///This is a test class for CUETools.Codecs.ALAC.ALACWriter and is intended + ///to contain all CUETools.Codecs.ALAC.ALACWriter Unit Tests + /// + [TestClass()] + public class ALACWriterTest + { + + + private TestContext testContextInstance; + + /// + ///Gets or sets the test context which provides + ///information about and functionality for the current test run. + /// + public TestContext TestContext + { + get + { + return testContextInstance; + } + set + { + testContextInstance = value; + } + } + #region Additional test attributes + // + //You can use the following additional attributes as you write your tests: + // + //Use ClassInitialize to run code before running the first test in the class + // + //[ClassInitialize()] + //public static void MyClassInitialize(TestContext testContext) + //{ + //} + // + //Use ClassCleanup to run code after all tests in a class have run + // + //[ClassCleanup()] + //public static void MyClassCleanup() + //{ + //} + // + //Use TestInitialize to run code before running each test + // + //[TestInitialize()] + //public void MyTestInitialize() + //{ + //} + // + //Use TestCleanup to run code after each test has run + // + //[TestCleanup()] + //public void MyTestCleanup() + //{ + //} + // + #endregion + + + /// + ///A test for ALACWriter (string, int, int, int, Stream) + /// + [TestMethod()] + public void ConstructorTest() + { + AudioBuffer buff = WAVReader.ReadAllSamples("test.wav", null); + ALACWriter target; + + target = new ALACWriter("alacwriter0.m4a", null, buff.PCM); + target.PaddingLength = 1; + target.Vendor = "CUETools"; + target.CreationTime = DateTime.Parse("15 Aug 1976"); + target.Write(buff); + target.Close(); + CollectionAssert.AreEqual(File.ReadAllBytes("alac.m4a"), File.ReadAllBytes("alacwriter0.m4a"), "alacwriter0.m4a doesn't match."); + + target = new ALACWriter("alacwriter1.m4a", null, buff.PCM); + target.PaddingLength = 1; + target.Vendor = "CUETools"; + target.CreationTime = DateTime.Parse("15 Aug 1976"); + target.FinalSampleCount = buff.Length; + target.Write(buff); + target.Close(); + CollectionAssert.AreEqual(File.ReadAllBytes("alac.m4a"), File.ReadAllBytes("alacwriter1.m4a"), "alacwriter1.m4a doesn't match."); + } + + } + + +} diff --git a/CUETools/CUETools.TestCodecs/AccurateRipTest.cs b/CUETools/CUETools.TestCodecs/AccurateRipTest.cs new file mode 100644 index 0000000..acf92e8 --- /dev/null +++ b/CUETools/CUETools.TestCodecs/AccurateRipTest.cs @@ -0,0 +1,96 @@ +// The following code was generated by Microsoft Visual Studio 2005. +// The test owner should check each test for validity. +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.Text; +using System.Collections.Generic; +using CUETools.CDImage; +using CUETools.AccurateRip; +using CUETools.Codecs; +namespace CUETools.TestCodecs +{ + /// + ///This is a test class for CUETools.AccurateRip.AccurateRipVerify and is intended + ///to contain all CUETools.AccurateRip.AccurateRipVerify Unit Tests + /// + [TestClass()] + public class AccurateRipVerifyTest + { + + + private TestContext testContextInstance; + + private int[,] testSamples = new int[,] { { 0, 0 }, { -2, -3 }, { 32767, 32766 }, { -32765, -32764 } }; + + /// + ///Gets or sets the test context which provides + ///information about and functionality for the current test run. + /// + public TestContext TestContext + { + get + { + return testContextInstance; + } + set + { + testContextInstance = value; + } + } + #region Additional test attributes + // + //You can use the following additional attributes as you write your tests: + // + //Use ClassInitialize to run code before running the first test in the class + // + //[ClassInitialize()] + //public static void MyClassInitialize(TestContext testContext) + //{ + //} + // + //Use ClassCleanup to run code after all tests in a class have run + // + //[ClassCleanup()] + //public static void MyClassCleanup() + //{ + //} + // + //Use TestInitialize to run code before running each test + // + //[TestInitialize()] + //public void MyTestInitialize() + //{ + //} + // + //Use TestCleanup to run code after each test has run + // + //[TestCleanup()] + //public void MyTestCleanup() + //{ + //} + // + #endregion + + + /// + ///A test for CalculateCRCs (AudioBuffer, int, int) + /// + [TestMethod()] + public void CalculateCRCsTest() + { + CDImageLayout toc = new CDImageLayout(); + toc.AddTrack(new CDTrack(1, 0, 10, true, false)); + AccurateRipVerify target = new AccurateRipVerify(toc); + AudioBuffer buff = new AudioBuffer(AudioPCMConfig.RedBook, testSamples, testSamples.GetLength(0)); + target.CalculateCRCs(buff, 0, testSamples.GetLength(0)); + Crc32 crc32 = new Crc32(); + uint crc1 = crc32.ComputeChecksum(0xffffffff, buff.Bytes, 0, buff.ByteLength) ^ 0xffffffff; + Assert.AreEqual(3856971150, crc1, "CRC32 was not set correctly."); + Assert.AreEqual(3856971150, target.CRC32(0), "CRC32 was not set correctly."); + Assert.AreEqual(1921661108, target.CRCWONULL(0), "CRC32WONULL was not set correctly."); + } + + } + + +} diff --git a/CUETools/CUETools.TestCodecs/CUETools.TestCodecs.csproj b/CUETools/CUETools.TestCodecs/CUETools.TestCodecs.csproj new file mode 100644 index 0000000..ddf6fb5 --- /dev/null +++ b/CUETools/CUETools.TestCodecs/CUETools.TestCodecs.csproj @@ -0,0 +1,67 @@ + + + + Debug + AnyCPU + 8.0.50727 + 2.0 + {04945FB2-8410-4F14-8262-2ED18DCDACD6} + Library + CUETools.TestCodecs + CUETools.TestCodecs + 4 + {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + + + true + full + false + .\bin\Debug\ + DEBUG;TRACE + + + false + true + .\bin\Release\ + TRACE + + + + False + ..\..\..\..\Windows\assembly\GAC_MSIL\Microsoft.VisualStudio.QualityTools.UnitTestFramework\8.0.0.0__b03f5f7f11d50a3a\Microsoft.VisualStudio.QualityTools.UnitTestFramework.dll + + + + + + + + + + + + + + + {5802C7E9-157E-4124-946D-70B5AE48A5A1} + CUETools.AccurateRip + + + {1DD41038-D885-46C5-8DDE-E0B82F066584} + CUETools.CDImage + + + {F2EC7193-D5E5-4252-9803-5CEB407E910F} + CUETools.Codecs.ALAC + + + {082D6B9E-326E-4D15-9798-EDAE9EDE70A6} + CUETools.Codecs.FLAKE + + + {6458A13A-30EF-45A9-9D58-E5031B17BEE2} + CUETools.Codecs + + + + \ No newline at end of file diff --git a/CUETools/CUETools.TestCodecs/CodecsTest.cs b/CUETools/CUETools.TestCodecs/CodecsTest.cs new file mode 100644 index 0000000..5b12dc2 --- /dev/null +++ b/CUETools/CUETools.TestCodecs/CodecsTest.cs @@ -0,0 +1,345 @@ +// The following code was generated by Microsoft Visual Studio 2005. +// The test owner should check each test for validity. +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.Text; +using System.Collections.Generic; +using CUETools.Codecs; +using System.IO; + +namespace CUETools.TestCodecs +{ + /// + ///This is a test class for CUETools.Codecs.AudioBuffer and is intended + ///to contain all CUETools.Codecs.AudioBuffer Unit Tests + /// + [TestClass()] + public class AudioBufferTest + { + + + private TestContext testContextInstance; + + private int[,] testSamples = new int[,] { { 0, 1 }, { -2, -3 }, { 32767, 32766 }, { -32765, -32764 } }; + private byte[] testBytes = new byte[] { 0, 0, 1, 0, 254, 255, 253, 255, 255, 127, 254, 127, 3, 128, 4, 128 }; + + private int[,] testSamples2 = new int[,] { { 0, 1 }, { -2, -3 }, { 32767, 32766 }, { -32765, -32764 }, { 42, 42 } }; + private byte[] testBytes2 = new byte[] { 0, 0, 1, 0, 254, 255, 253, 255, 255, 127, 254, 127, 3, 128, 4, 128, 42, 0, 42, 0 }; + + /// + ///Gets or sets the test context which provides + ///information about and functionality for the current test run. + /// + public TestContext TestContext + { + get + { + return testContextInstance; + } + set + { + testContextInstance = value; + } + } + #region Additional test attributes + // + //You can use the following additional attributes as you write your tests: + // + //Use ClassInitialize to run code before running the first test in the class + // + //[ClassInitialize()] + //public static void MyClassInitialize(TestContext testContext) + //{ + //} + // + //Use ClassCleanup to run code after all tests in a class have run + // + //[ClassCleanup()] + //public static void MyClassCleanup() + //{ + //} + // + //Use TestInitialize to run code before running each test + // + //[TestInitialize()] + //public void MyTestInitialize() + //{ + //} + // + //Use TestCleanup to run code after each test has run + // + //[TestCleanup()] + //public void MyTestCleanup() + //{ + //} + // + #endregion + + + /// + ///A test for Bytes + /// + [TestMethod()] + public void BytesTest() + { + AudioBuffer target = new AudioBuffer(AudioPCMConfig.RedBook, 1); + target.Prepare(testSamples, testSamples.GetLength(0)); + CollectionAssert.AreEqual(testBytes, target.Bytes, "CUETools.Codecs.AudioBuffer.Bytes was not set correctly."); + target.Prepare(testSamples2, testSamples2.GetLength(0)); + CollectionAssert.AreEqual(testBytes2, target.Bytes, "CUETools.Codecs.AudioBuffer.Bytes was not set correctly."); + } + + /// + ///A test for Samples + /// + [TestMethod()] + public void SamplesTest() + { + AudioBuffer target = new AudioBuffer(AudioPCMConfig.RedBook, 1); + target.Prepare(testBytes, testSamples.GetLength(0)); + CollectionAssert.AreEqual(testSamples, target.Samples, "CUETools.Codecs.AudioBuffer.Samples was not set correctly."); + target.Prepare(testBytes2, testSamples2.GetLength(0)); + CollectionAssert.AreEqual(testSamples2, target.Samples, "CUETools.Codecs.AudioBuffer.Samples was not set correctly."); + } + + } + + + /// + ///This is a test class for CUETools.Codecs.WAVReader and is intended + ///to contain all CUETools.Codecs.WAVReader Unit Tests + /// + [TestClass()] + public class WAVReaderTest + { + + + private TestContext testContextInstance; + private WAVReader pipe = null; + private WAVReader wave = null; + + public readonly static int[,] pipeSamples = new int[,] { { -1, 1 }, { 0, -1 }, { -1, 0 }, { 0, -1 }, { -1, -1 }, { -1, -1 }, { 1, 0 }, { -3, -2 }, { 3, 1 }, { -4, -3 }, { 3, 2 }, { -4, -3 }, { 3, 1 }, { -3, -1 }, { 1, -1 }, { -1, 1 }, { -1, -3 }, { 0, 3 }, { -2, -4 }, { 0, 3 }, { -1, -4 }, { -1, 3 }, { 0, -3 }, { -2, 1 }, { 1, -1 }, { -2, -1 }, { 0, 1 }, { -1, -2 }, { -1, 1 }, { 1, -2 }, { -3, 1 }, { 3, -2 }, { -4, 0 }, { 3, -1 }, { -4, -1 }, { 3, -1 }, { -3, 0 }, { 1, -1 }, { -1, 1 }, { -1, -2 }, { 0, 2 }, { -1, -3 }, { 0, 2 }, { 0, -3 }, { -1, 1 }, { 1, -1 }, { -2, -1 }, { 2, 1 }, { -2, -3 }, { 1, 3 }, { -1, -4 }, { -1, 3 }, { 1, -4 }, { 0, 0 } }; + public readonly static int[,] testSamples = new int[,] { { -1, 1 }, { 0, -1 }, { -1, 0 }, { 0, -1 }, { -1, -1 }, { -1, -1 }, { 1, 0 }, { -3, -2 }, { 3, 1 }, { -4, -3 }, { 3, 2 }, { -4, -3 }, { 3, 1 }, { -3, -1 }, { 1, -1 }, { -1, 1 }, { -1, -3 }, { 0, 3 }, { -2, -4 }, { 0, 3 }, { -1, -4 }, { -1, 3 }, { 0, -3 }, { -2, 1 }, { 1, -1 }, { -2, -1 }, { 0, 1 }, { -1, -2 }, { -1, 1 }, { 1, -2 }, { -3, 1 }, { 3, -2 }, { -4, 0 }, { 3, -1 }, { -4, -1 }, { 3, -1 }, { -3, 0 }, { 1, -1 }, { -1, 1 }, { -1, -2 }, { 0, 2 }, { -1, -3 }, { 0, 2 }, { 0, -3 }, { -1, 1 }, { 1, -1 }, { -2, -1 }, { 2, 1 }, { -2, -3 }, { 1, 3 }, { -1, -4 }, { -1, 3 }, { 1, -4 }}; + + /// + ///Gets or sets the test context which provides + ///information about and functionality for the current test run. + /// + public TestContext TestContext + { + get + { + return testContextInstance; + } + set + { + testContextInstance = value; + } + } + #region Additional test attributes + // + //You can use the following additional attributes as you write your tests: + // + //Use ClassInitialize to run code before running the first test in the class + // + [ClassInitialize()] + public static void MyClassInitialize(TestContext testContext) + { + } + + // + //Use ClassCleanup to run code after all tests in a class have run + // + [ClassCleanup()] + public static void MyClassCleanup() + { + } + // + //Use TestInitialize to run code before running each test + // + [TestInitialize()] + public void MyTestInitialize() + { + pipe = new WAVReader("pipe.wav", null); + wave = new WAVReader("test.wav", null); + } + // + //Use TestCleanup to run code after each test has run + // + [TestCleanup()] + public void MyTestCleanup() + { + pipe.Close(); + pipe = null; + wave.Close(); + wave = null; + } + // + #endregion + + private void DumpSamples(int[,] samples) + { + StringWriter sw = new StringWriter(); + for (int i = 0; i < samples.GetLength(0); i++) + sw.Write(" {0}{1}, {2}{3},", "{", samples[i, 0], samples[i, 1], "}"); + TestContext.WriteLine("{0}", sw.ToString()); + } + + /// + ///A test for Read (AudioBuffer, int) + /// + [TestMethod()] + public void ReadTest() + { + Assert.AreEqual(-1L, pipe.Length, "CUETools.Codecs.WAVReader.Length did not return the expected value."); + AudioBuffer buff = new AudioBuffer(pipe, 54); + int actual = pipe.Read(buff, -1); + Assert.AreEqual(53, actual, "CUETools.Codecs.WAVReader.Read did not return the expected value."); + Assert.AreEqual(actual, buff.Length, "CUETools.Codecs.WAVReader.Read did not return the expected value."); + CollectionAssert.AreEqual(pipeSamples, buff.Samples, "AudioBuffer.Samples was not set correctly."); + actual = pipe.Read(buff, -1); + Assert.AreEqual(0, actual, "CUETools.Codecs.WAVReader.Read did not return the expected value."); + } + + + /// + ///A test for BitsPerSample + /// + [TestMethod()] + public void BitsPerSampleTest() + { + Assert.AreEqual(16, pipe.PCM.BitsPerSample, "CUETools.Codecs.WAVReader.BitsPerSample was not set correctly."); + } + + /// + ///A test for BlockAlign + /// + [TestMethod()] + public void BlockAlignTest() + { + Assert.AreEqual(4, pipe.PCM.BlockAlign, "CUETools.Codecs.WAVReader.BlockAlign was not set correctly."); + } + + /// + ///A test for ChannelCount + /// + [TestMethod()] + public void ChannelCountTest() + { + Assert.AreEqual(2, pipe.PCM.ChannelCount, "CUETools.Codecs.WAVReader.ChannelCount was not set correctly."); + } + + /// + ///A test for Length + /// + [TestMethod()] + public void LengthTest() + { + Assert.AreEqual(-1L, pipe.Length, "CUETools.Codecs.WAVReader.Length was not set correctly."); + Assert.AreEqual(53L, wave.Length, "CUETools.Codecs.WAVReader.Length was not set correctly."); + } + + /// + ///A test for SampleRate + /// + [TestMethod()] + public void SampleRateTest() + { + Assert.AreEqual(44100, pipe.PCM.SampleRate, "CUETools.Codecs.WAVReader.SampleRate was not set correctly."); + } + + /// + ///A test for ReadAllSamples (string, Stream) + /// + [TestMethod()] + public void ReadAllSamplesTest() + { + AudioBuffer buff = WAVReader.ReadAllSamples("test.wav", null); + CollectionAssert.AreEqual(testSamples, buff.Samples, "AudioBuffer.Samples was not set correctly."); + } + } + /// + ///This is a test class for CUETools.Codecs.WAVWriter and is intended + ///to contain all CUETools.Codecs.WAVWriter Unit Tests + /// + [TestClass()] + public class WAVWriterTest + { + + + private TestContext testContextInstance; + + /// + ///Gets or sets the test context which provides + ///information about and functionality for the current test run. + /// + public TestContext TestContext + { + get + { + return testContextInstance; + } + set + { + testContextInstance = value; + } + } + #region Additional test attributes + // + //You can use the following additional attributes as you write your tests: + // + //Use ClassInitialize to run code before running the first test in the class + // + //[ClassInitialize()] + //public static void MyClassInitialize(TestContext testContext) + //{ + //} + // + //Use ClassCleanup to run code after all tests in a class have run + // + //[ClassCleanup()] + //public static void MyClassCleanup() + //{ + //} + // + //Use TestInitialize to run code before running each test + // + //[TestInitialize()] + //public void MyTestInitialize() + //{ + //} + // + //Use TestCleanup to run code after each test has run + // + //[TestCleanup()] + //public void MyTestCleanup() + //{ + //} + // + #endregion + + + /// + ///A test for WAVWriter (string, int, int, int, Stream) + /// + [TestMethod()] + public void ConstructorTest() + { + AudioBuffer buff = WAVReader.ReadAllSamples("test.wav", null); + WAVWriter target; + + target = new WAVWriter("wavwriter0.wav", null, buff.PCM); + //target.FinalSampleCount = buff.Length; + target.Write(buff); + target.Close(); + CollectionAssert.AreEqual(File.ReadAllBytes("test.wav"), File.ReadAllBytes("wavwriter0.wav"), "wavwriter0.wav doesn't match."); + + target = new WAVWriter("wavwriter1.wav", null, buff.PCM); + target.FinalSampleCount = buff.Length; + target.Write(buff); + target.Close(); + CollectionAssert.AreEqual(File.ReadAllBytes("test.wav"), File.ReadAllBytes("wavwriter1.wav"), "wavwriter1.wav doesn't match."); + } + + } +} diff --git a/CUETools/CUETools.TestCodecs/FlakeWriterTest.cs b/CUETools/CUETools.TestCodecs/FlakeWriterTest.cs new file mode 100644 index 0000000..e026692 --- /dev/null +++ b/CUETools/CUETools.TestCodecs/FlakeWriterTest.cs @@ -0,0 +1,105 @@ +// The following code was generated by Microsoft Visual Studio 2005. +// The test owner should check each test for validity. +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.Text; +using System.Collections.Generic; +using System.IO; +using CUETools.Codecs; +using CUETools.Codecs.FLAKE; +namespace CUETools.TestCodecs +{ + /// + ///This is a test class for CUETools.Codecs.FLAKE.FlakeWriter and is intended + ///to contain all CUETools.Codecs.FLAKE.FlakeWriter Unit Tests + /// + [TestClass()] + public class FlakeWriterTest + { + + + private TestContext testContextInstance; + + /// + ///Gets or sets the test context which provides + ///information about and functionality for the current test run. + /// + public TestContext TestContext + { + get + { + return testContextInstance; + } + set + { + testContextInstance = value; + } + } + #region Additional test attributes + // + //You can use the following additional attributes as you write your tests: + // + //Use ClassInitialize to run code before running the first test in the class + // + //[ClassInitialize()] + //public static void MyClassInitialize(TestContext testContext) + //{ + //} + // + //Use ClassCleanup to run code after all tests in a class have run + // + //[ClassCleanup()] + //public static void MyClassCleanup() + //{ + //} + // + //Use TestInitialize to run code before running each test + // + //[TestInitialize()] + //public void MyTestInitialize() + //{ + //} + // + //Use TestCleanup to run code after each test has run + // + //[TestCleanup()] + //public void MyTestCleanup() + //{ + //} + // + #endregion + + + /// + ///A test for FlakeWriter (string, int, int, int, Stream) + /// + [TestMethod()] + public void ConstructorTest() + { + AudioBuffer buff = WAVReader.ReadAllSamples("test.wav", null); + FlakeWriter target; + + target = new FlakeWriter("flakewriter0.flac", null, buff.PCM); + target.PaddingLength = 1; + target.DoSeekTable = false; + //target.Vendor = "CUETools"; + //target.CreationTime = DateTime.Parse("15 Aug 1976"); + target.FinalSampleCount = buff.Length; + target.Write(buff); + target.Close(); + CollectionAssert.AreEqual(File.ReadAllBytes("flake.flac"), File.ReadAllBytes("flakewriter0.flac"), "flakewriter0.flac doesn't match."); + + target = new FlakeWriter("flakewriter1.flac", null, buff.PCM); + target.PaddingLength = 1; + target.DoSeekTable = false; + //target.Vendor = "CUETools"; + //target.CreationTime = DateTime.Parse("15 Aug 1976"); + target.Write(buff); + target.Close(); + CollectionAssert.AreEqual(File.ReadAllBytes("flake.flac"), File.ReadAllBytes("flakewriter1.flac"), "flakewriter1.flac doesn't match."); + } + + } + + +} diff --git a/CUETools/CUETools.TestCodecs/Properties/AssemblyInfo.cs b/CUETools/CUETools.TestCodecs/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..0794533 --- /dev/null +++ b/CUETools/CUETools.TestCodecs/Properties/AssemblyInfo.cs @@ -0,0 +1,35 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("CUETools.TestCodecs")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Microsoft")] +[assembly: AssemblyProduct("CUETools.TestCodecs")] +[assembly: AssemblyCopyright("Copyright © Microsoft 2010")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM componenets. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("62e9c766-721e-4dba-8187-f9d87449920e")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Revision and Build Numbers +// by using the '*' as shown below: +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/CUETools/CUETools.TestCodecs/alac.m4a b/CUETools/CUETools.TestCodecs/alac.m4a new file mode 100644 index 0000000000000000000000000000000000000000..2ca355d27f2d5732801f9562beb7f4e74b1a994c GIT binary patch literal 774 zcmZQzU{FXasVwj{aa3SnU}6B#xdkRhnZ^0J3=qJXR+O3wVsbzkwz(;ZB?=4z3=9le z3=FdDQ@7-7$?ub8pY|=AE%!c$kkBfg)_|f_JYFl5jtMZVVp$N%9@)_)Fommtfq|(% zH$T6Ofq@|>w=5$CWGYYbf(szbz`*>1fq}u4fsp}(KvEFQ2%+F48s7mfftA6;z`(e- zq$n|)fq@~WBpYleKgd21WFaZ<6REcUYV`OehW+Eswb5p=}Fo4VlVFrdZ zE+Bt}9s!%Bn~{=J1ZFWXFcjyP=E2w?nkP8FG%v*?F)t-2wTOX%ktH`XFO7kLL7+Gn zVkk%v0|SFf3PfBcr6?674-y7Bm#4HSM*-^86U8M-ISdR85yd6N;DCmTdnD#0CWACU z`4A=(I65ItWnfT2s1aab5YXV_V*)925?~PRXn=Z1p}3@^7$nL7N;hBzC`Ewd&Xj?H zL8iE*7}*|>`(Rk2xTLrWtOY`V#6fyQic6C7AwpntEEyOW;!0CWKmi+;n+m2u(n`pI yn46MWlvq#z@+(LVf;BR8ic3Jzv9cr|WTHe$B3L)bCI;tF*O2`D9FXfFi5mb^A8`o) literal 0 HcmV?d00001 diff --git a/CUETools/CUETools.TestCodecs/flake.flac b/CUETools/CUETools.TestCodecs/flake.flac new file mode 100644 index 0000000000000000000000000000000000000000..0eb2875f997e21d548cd5c80162b51ae01c22dec GIT binary patch literal 125 zcmYfENpxmlU{Dfb5MlrUuK=ziP9GQ;7))>Pv~rnM!qMl&XR*GNvEv^L1A`zZ0|SFw zPGWYdvVooaz10%!#ADJr{Om4a`F#P}j|9|m?E#?d|%O}h~IeD`2q@v=J7wrF^ ct60FSmZ&B literal 0 HcmV?d00001 diff --git a/CUETools/CUETools.TestCodecs/pipe.wav b/CUETools/CUETools.TestCodecs/pipe.wav new file mode 100644 index 0000000000000000000000000000000000000000..aceb4a3ecbf5d6ea6650bc26a1ffaf87df792557 GIT binary patch literal 256 zcmWIYbaVUi|NsAR$1vBl+!6%=1_lO31||lVH4F>_8<`kb7z7wn5=#;<{09L>1_lNY z%>boA?En8kqJRJY`_Ih4$nfX?-~Y@EOi-GU;qQNtJV+fQ!~g$(|1&T!GyMDi2TcF} z|L6bz|I7>w3?SW%3?LQ%{{R0Ea>4)qAQnjM-~Ye=8L{YsmSt(zyFyTn4mNx!{7fPT_9zQ4FCWC{m;O_%<%93A29v@ z|DXT=|1&c%Fo1M3GJsV4`wuc5#sZ1``~UYpBNkl{(?BXAHvId~z`z8xg9&UVNE{>& QGLwmckpX5B%wCXd0ni(MkN^Mx literal 0 HcmV?d00001 diff --git a/CUETools/CUETools.csproj b/CUETools/CUETools.csproj index 46ea11a..b0270ef 100644 --- a/CUETools/CUETools.csproj +++ b/CUETools/CUETools.csproj @@ -49,7 +49,7 @@ pdbonly true - ..\bin\mono\Release\ + ..\bin\any\Release\ TRACE prompt 4 diff --git a/CUETools/CUETools.sln b/CUETools/CUETools.sln index 09e6817..9fc135f 100644 --- a/CUETools/CUETools.sln +++ b/CUETools/CUETools.sln @@ -31,11 +31,6 @@ EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ArCueDotNet", "..\ArCueDotNet\ArCueDotNet.csproj", "{A5A8D8FA-9E32-4010-8AAF-AE580C5AF728}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CUETools.Processor", "..\CUETools.Processor\CUETools.Processor.csproj", "{4911BD82-49EF-4858-8B51-5394F86739A4}" - ProjectSection(ProjectDependencies) = postProject - {E70FA90A-7012-4A52-86B5-362B699D1540} = {E70FA90A-7012-4A52-86B5-362B699D1540} - {CC2E74B6-534A-43D8-9F16-AC03FE955000} = {CC2E74B6-534A-43D8-9F16-AC03FE955000} - {9AE965C4-301E-4C01-B90F-297AF341ACC6} = {9AE965C4-301E-4C01-B90F-297AF341ACC6} - EndProjectSection EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HDCDDotNet", "..\HDCDDotNet\HDCDDotNet.csproj", "{32338A04-5B6B-4C63-8EE7-C6400F73B5D7}" EndProject @@ -77,8 +72,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TTALib", "..\ttalib-1.1\TTA EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CUETools.Codecs.TTA", "..\CUETools.Codecs.TTA\CUETools.Codecs.TTA.vcproj", "{1D1E99BC-6D22-41C0-BD94-FF4DD5EC725B}" ProjectSection(ProjectDependencies) = postProject - {6458A13A-30EF-45A9-9D58-E5031B17BEE2} = {6458A13A-30EF-45A9-9D58-E5031B17BEE2} {B3DF599C-1C8F-451D-91E4-DD766210DA1F} = {B3DF599C-1C8F-451D-91E4-DD766210DA1F} + {6458A13A-30EF-45A9-9D58-E5031B17BEE2} = {6458A13A-30EF-45A9-9D58-E5031B17BEE2} EndProjectSection EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CUETools.Converter", "..\CUETools.Converter\CUETools.Converter.csproj", "{115CC5B0-0385-41CD-8A23-6A7EA4C51926}" @@ -95,636 +90,402 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CUETools.Flake", "..\CUEToo EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CUETools.ALACEnc", "..\CUETools.ALACEnc\CUETools.ALACEnc.csproj", "{8E6E1763-39AE-491D-A10F-44C8844ABA5B}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CUETools.Codecs.FlaCuda", "..\CUETools.FlaCuda\CUETools.Codecs.FlaCuda.csproj", "{DFE50673-906C-4B8F-993B-A24CAD1CA17D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CUETools.FlaCuda", "..\CUETools.FlaCudaExe\CUETools.FlaCuda.csproj", "{1FCA8834-34E6-47CF-B53F-D8DF49F0819E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CUETools.Codecs.CLAC", "..\CUETools.Codecs.CLAC\CUETools.Codecs.CLAC.csproj", "{DDE1EA77-637C-4D5F-96F3-1328BC45CE80}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CUETools.CLACEncoder", "..\CUETools.CLACEncoder\CUETools.CLACEncoder.csproj", "{FC4BCF9B-F4C7-41AD-8A16-2A90A082954A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CUETools.TestCodecs", "CUETools.TestCodecs\CUETools.TestCodecs.csproj", "{04945FB2-8410-4F14-8262-2ED18DCDACD6}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{366B7C6D-3A2C-4767-9121-4FBB550B5DE2}" + ProjectSection(SolutionItems) = preProject + CUETools1.vsmdi = CUETools1.vsmdi + localtestrun.testrunconfig = localtestrun.testrunconfig + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CUETools.TestProcessor", "CUETools.TestProcessor\CUETools.TestProcessor.csproj", "{A430AD28-B76A-4ED0-AF7D-D13B8969297F}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Plugins", "Plugins", "{39A17A65-E893-44B8-A312-DDCDD990D9D1}" +EndProject Global + GlobalSection(TestCaseManagementSettings) = postSolution + CategoryFile = CUETools1.vsmdi + EndGlobalSection GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU - Debug|Mixed Platforms = Debug|Mixed Platforms Debug|Win32 = Debug|Win32 Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 Release|Any CPU = Release|Any CPU - Release|Mixed Platforms = Release|Mixed Platforms Release|Win32 = Release|Win32 Release|x64 = Release|x64 - Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {EF351583-A9CD-4530-92C3-20AC02136BC2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {EF351583-A9CD-4530-92C3-20AC02136BC2}.Debug|Any CPU.Build.0 = Debug|Any CPU - {EF351583-A9CD-4530-92C3-20AC02136BC2}.Debug|Mixed Platforms.ActiveCfg = Debug|x64 - {EF351583-A9CD-4530-92C3-20AC02136BC2}.Debug|Mixed Platforms.Build.0 = Debug|x64 - {EF351583-A9CD-4530-92C3-20AC02136BC2}.Debug|Win32.ActiveCfg = Debug|x64 - {EF351583-A9CD-4530-92C3-20AC02136BC2}.Debug|x64.ActiveCfg = Debug|x64 - {EF351583-A9CD-4530-92C3-20AC02136BC2}.Debug|x64.Build.0 = Debug|x64 - {EF351583-A9CD-4530-92C3-20AC02136BC2}.Debug|x86.ActiveCfg = Debug|x86 - {EF351583-A9CD-4530-92C3-20AC02136BC2}.Debug|x86.Build.0 = Debug|x86 + {EF351583-A9CD-4530-92C3-20AC02136BC2}.Debug|Win32.ActiveCfg = Debug|Any CPU + {EF351583-A9CD-4530-92C3-20AC02136BC2}.Debug|x64.ActiveCfg = Debug|Any CPU {EF351583-A9CD-4530-92C3-20AC02136BC2}.Release|Any CPU.ActiveCfg = Release|Any CPU {EF351583-A9CD-4530-92C3-20AC02136BC2}.Release|Any CPU.Build.0 = Release|Any CPU - {EF351583-A9CD-4530-92C3-20AC02136BC2}.Release|Mixed Platforms.ActiveCfg = Release|x64 - {EF351583-A9CD-4530-92C3-20AC02136BC2}.Release|Mixed Platforms.Build.0 = Release|x64 - {EF351583-A9CD-4530-92C3-20AC02136BC2}.Release|Win32.ActiveCfg = Release|x64 - {EF351583-A9CD-4530-92C3-20AC02136BC2}.Release|x64.ActiveCfg = Release|x64 - {EF351583-A9CD-4530-92C3-20AC02136BC2}.Release|x64.Build.0 = Release|x64 - {EF351583-A9CD-4530-92C3-20AC02136BC2}.Release|x86.ActiveCfg = Release|x86 - {EF351583-A9CD-4530-92C3-20AC02136BC2}.Release|x86.Build.0 = Release|x86 + {EF351583-A9CD-4530-92C3-20AC02136BC2}.Release|Win32.ActiveCfg = Release|Any CPU + {EF351583-A9CD-4530-92C3-20AC02136BC2}.Release|x64.ActiveCfg = Release|Any CPU {E70FA90A-7012-4A52-86B5-362B699D1540}.Debug|Any CPU.ActiveCfg = Debug|x64 - {E70FA90A-7012-4A52-86B5-362B699D1540}.Debug|Mixed Platforms.ActiveCfg = Debug|x64 - {E70FA90A-7012-4A52-86B5-362B699D1540}.Debug|Mixed Platforms.Build.0 = Debug|x64 {E70FA90A-7012-4A52-86B5-362B699D1540}.Debug|Win32.ActiveCfg = Debug|Win32 {E70FA90A-7012-4A52-86B5-362B699D1540}.Debug|Win32.Build.0 = Debug|Win32 {E70FA90A-7012-4A52-86B5-362B699D1540}.Debug|x64.ActiveCfg = Debug|x64 {E70FA90A-7012-4A52-86B5-362B699D1540}.Debug|x64.Build.0 = Debug|x64 - {E70FA90A-7012-4A52-86B5-362B699D1540}.Debug|x86.ActiveCfg = Debug|Win32 - {E70FA90A-7012-4A52-86B5-362B699D1540}.Debug|x86.Build.0 = Debug|Win32 {E70FA90A-7012-4A52-86B5-362B699D1540}.Release|Any CPU.ActiveCfg = Release|x64 - {E70FA90A-7012-4A52-86B5-362B699D1540}.Release|Mixed Platforms.ActiveCfg = Release|x64 - {E70FA90A-7012-4A52-86B5-362B699D1540}.Release|Mixed Platforms.Build.0 = Release|x64 {E70FA90A-7012-4A52-86B5-362B699D1540}.Release|Win32.ActiveCfg = Release|Win32 {E70FA90A-7012-4A52-86B5-362B699D1540}.Release|Win32.Build.0 = Release|Win32 {E70FA90A-7012-4A52-86B5-362B699D1540}.Release|x64.ActiveCfg = Release|x64 {E70FA90A-7012-4A52-86B5-362B699D1540}.Release|x64.Build.0 = Release|x64 - {E70FA90A-7012-4A52-86B5-362B699D1540}.Release|x86.ActiveCfg = Release|Win32 - {E70FA90A-7012-4A52-86B5-362B699D1540}.Release|x86.Build.0 = Release|Win32 {9AE965C4-301E-4C01-B90F-297AF341ACC6}.Debug|Any CPU.ActiveCfg = Debug|x64 - {9AE965C4-301E-4C01-B90F-297AF341ACC6}.Debug|Mixed Platforms.ActiveCfg = Debug|x64 - {9AE965C4-301E-4C01-B90F-297AF341ACC6}.Debug|Mixed Platforms.Build.0 = Debug|x64 {9AE965C4-301E-4C01-B90F-297AF341ACC6}.Debug|Win32.ActiveCfg = Debug|Win32 {9AE965C4-301E-4C01-B90F-297AF341ACC6}.Debug|Win32.Build.0 = Debug|Win32 {9AE965C4-301E-4C01-B90F-297AF341ACC6}.Debug|x64.ActiveCfg = Debug|x64 {9AE965C4-301E-4C01-B90F-297AF341ACC6}.Debug|x64.Build.0 = Debug|x64 - {9AE965C4-301E-4C01-B90F-297AF341ACC6}.Debug|x86.ActiveCfg = Debug|Win32 - {9AE965C4-301E-4C01-B90F-297AF341ACC6}.Debug|x86.Build.0 = Debug|Win32 {9AE965C4-301E-4C01-B90F-297AF341ACC6}.Release|Any CPU.ActiveCfg = Release|x64 - {9AE965C4-301E-4C01-B90F-297AF341ACC6}.Release|Mixed Platforms.ActiveCfg = Release|x64 - {9AE965C4-301E-4C01-B90F-297AF341ACC6}.Release|Mixed Platforms.Build.0 = Release|x64 {9AE965C4-301E-4C01-B90F-297AF341ACC6}.Release|Win32.ActiveCfg = Release|Win32 {9AE965C4-301E-4C01-B90F-297AF341ACC6}.Release|Win32.Build.0 = Release|Win32 {9AE965C4-301E-4C01-B90F-297AF341ACC6}.Release|x64.ActiveCfg = Release|x64 {9AE965C4-301E-4C01-B90F-297AF341ACC6}.Release|x64.Build.0 = Release|x64 - {9AE965C4-301E-4C01-B90F-297AF341ACC6}.Release|x86.ActiveCfg = Release|Win32 - {9AE965C4-301E-4C01-B90F-297AF341ACC6}.Release|x86.Build.0 = Release|Win32 {CC2E74B6-534A-43D8-9F16-AC03FE955000}.Debug|Any CPU.ActiveCfg = Debug|x64 - {CC2E74B6-534A-43D8-9F16-AC03FE955000}.Debug|Mixed Platforms.ActiveCfg = Debug|x64 - {CC2E74B6-534A-43D8-9F16-AC03FE955000}.Debug|Mixed Platforms.Build.0 = Debug|x64 {CC2E74B6-534A-43D8-9F16-AC03FE955000}.Debug|Win32.ActiveCfg = Debug|Win32 {CC2E74B6-534A-43D8-9F16-AC03FE955000}.Debug|Win32.Build.0 = Debug|Win32 {CC2E74B6-534A-43D8-9F16-AC03FE955000}.Debug|x64.ActiveCfg = Debug|x64 {CC2E74B6-534A-43D8-9F16-AC03FE955000}.Debug|x64.Build.0 = Debug|x64 - {CC2E74B6-534A-43D8-9F16-AC03FE955000}.Debug|x86.ActiveCfg = Debug|Win32 - {CC2E74B6-534A-43D8-9F16-AC03FE955000}.Debug|x86.Build.0 = Debug|Win32 {CC2E74B6-534A-43D8-9F16-AC03FE955000}.Release|Any CPU.ActiveCfg = Release|Win32 - {CC2E74B6-534A-43D8-9F16-AC03FE955000}.Release|Mixed Platforms.ActiveCfg = Release|x64 - {CC2E74B6-534A-43D8-9F16-AC03FE955000}.Release|Mixed Platforms.Build.0 = Release|x64 {CC2E74B6-534A-43D8-9F16-AC03FE955000}.Release|Win32.ActiveCfg = Release|Win32 {CC2E74B6-534A-43D8-9F16-AC03FE955000}.Release|Win32.Build.0 = Release|Win32 {CC2E74B6-534A-43D8-9F16-AC03FE955000}.Release|x64.ActiveCfg = Release|x64 {CC2E74B6-534A-43D8-9F16-AC03FE955000}.Release|x64.Build.0 = Release|x64 - {CC2E74B6-534A-43D8-9F16-AC03FE955000}.Release|x86.ActiveCfg = Release|Win32 - {CC2E74B6-534A-43D8-9F16-AC03FE955000}.Release|x86.Build.0 = Release|Win32 {0B9C97D4-61B8-4294-A1DF-BA90752A1779}.Debug|Any CPU.ActiveCfg = Debug|x64 - {0B9C97D4-61B8-4294-A1DF-BA90752A1779}.Debug|Mixed Platforms.ActiveCfg = Debug|x64 - {0B9C97D4-61B8-4294-A1DF-BA90752A1779}.Debug|Mixed Platforms.Build.0 = Debug|x64 {0B9C97D4-61B8-4294-A1DF-BA90752A1779}.Debug|Win32.ActiveCfg = Debug|Win32 {0B9C97D4-61B8-4294-A1DF-BA90752A1779}.Debug|Win32.Build.0 = Debug|Win32 {0B9C97D4-61B8-4294-A1DF-BA90752A1779}.Debug|x64.ActiveCfg = Debug|x64 {0B9C97D4-61B8-4294-A1DF-BA90752A1779}.Debug|x64.Build.0 = Debug|x64 - {0B9C97D4-61B8-4294-A1DF-BA90752A1779}.Debug|x86.ActiveCfg = Debug|Win32 - {0B9C97D4-61B8-4294-A1DF-BA90752A1779}.Debug|x86.Build.0 = Debug|Win32 {0B9C97D4-61B8-4294-A1DF-BA90752A1779}.Release|Any CPU.ActiveCfg = Release|x64 - {0B9C97D4-61B8-4294-A1DF-BA90752A1779}.Release|Mixed Platforms.ActiveCfg = Release|x64 - {0B9C97D4-61B8-4294-A1DF-BA90752A1779}.Release|Mixed Platforms.Build.0 = Release|x64 {0B9C97D4-61B8-4294-A1DF-BA90752A1779}.Release|Win32.ActiveCfg = Release|Win32 {0B9C97D4-61B8-4294-A1DF-BA90752A1779}.Release|Win32.Build.0 = Release|Win32 {0B9C97D4-61B8-4294-A1DF-BA90752A1779}.Release|x64.ActiveCfg = Release|x64 {0B9C97D4-61B8-4294-A1DF-BA90752A1779}.Release|x64.Build.0 = Release|x64 - {0B9C97D4-61B8-4294-A1DF-BA90752A1779}.Release|x86.ActiveCfg = Release|Win32 - {0B9C97D4-61B8-4294-A1DF-BA90752A1779}.Release|x86.Build.0 = Release|Win32 {4CEFBC84-C215-11DB-8314-0800200C9A66}.Debug|Any CPU.ActiveCfg = Debug|x64 - {4CEFBC84-C215-11DB-8314-0800200C9A66}.Debug|Mixed Platforms.ActiveCfg = Debug|x64 - {4CEFBC84-C215-11DB-8314-0800200C9A66}.Debug|Mixed Platforms.Build.0 = Debug|x64 {4CEFBC84-C215-11DB-8314-0800200C9A66}.Debug|Win32.ActiveCfg = Debug|Win32 {4CEFBC84-C215-11DB-8314-0800200C9A66}.Debug|Win32.Build.0 = Debug|Win32 {4CEFBC84-C215-11DB-8314-0800200C9A66}.Debug|x64.ActiveCfg = Debug|x64 {4CEFBC84-C215-11DB-8314-0800200C9A66}.Debug|x64.Build.0 = Debug|x64 - {4CEFBC84-C215-11DB-8314-0800200C9A66}.Debug|x86.ActiveCfg = Debug|Win32 - {4CEFBC84-C215-11DB-8314-0800200C9A66}.Debug|x86.Build.0 = Debug|Win32 {4CEFBC84-C215-11DB-8314-0800200C9A66}.Release|Any CPU.ActiveCfg = Release|x64 - {4CEFBC84-C215-11DB-8314-0800200C9A66}.Release|Mixed Platforms.ActiveCfg = Release|x64 - {4CEFBC84-C215-11DB-8314-0800200C9A66}.Release|Mixed Platforms.Build.0 = Release|x64 {4CEFBC84-C215-11DB-8314-0800200C9A66}.Release|Win32.ActiveCfg = Release|Win32 {4CEFBC84-C215-11DB-8314-0800200C9A66}.Release|Win32.Build.0 = Release|Win32 {4CEFBC84-C215-11DB-8314-0800200C9A66}.Release|x64.ActiveCfg = Release|x64 {4CEFBC84-C215-11DB-8314-0800200C9A66}.Release|x64.Build.0 = Release|x64 - {4CEFBC84-C215-11DB-8314-0800200C9A66}.Release|x86.ActiveCfg = Release|Win32 - {4CEFBC84-C215-11DB-8314-0800200C9A66}.Release|x86.Build.0 = Release|Win32 {5CCCB9CF-0384-458F-BA08-72B73866840F}.Debug|Any CPU.ActiveCfg = Debug|x64 - {5CCCB9CF-0384-458F-BA08-72B73866840F}.Debug|Mixed Platforms.ActiveCfg = Debug|x64 - {5CCCB9CF-0384-458F-BA08-72B73866840F}.Debug|Mixed Platforms.Build.0 = Debug|x64 {5CCCB9CF-0384-458F-BA08-72B73866840F}.Debug|Win32.ActiveCfg = Debug|Win32 {5CCCB9CF-0384-458F-BA08-72B73866840F}.Debug|Win32.Build.0 = Debug|Win32 {5CCCB9CF-0384-458F-BA08-72B73866840F}.Debug|x64.ActiveCfg = Debug|x64 {5CCCB9CF-0384-458F-BA08-72B73866840F}.Debug|x64.Build.0 = Debug|x64 - {5CCCB9CF-0384-458F-BA08-72B73866840F}.Debug|x86.ActiveCfg = Debug|Win32 - {5CCCB9CF-0384-458F-BA08-72B73866840F}.Debug|x86.Build.0 = Debug|Win32 {5CCCB9CF-0384-458F-BA08-72B73866840F}.Release|Any CPU.ActiveCfg = Release|x64 - {5CCCB9CF-0384-458F-BA08-72B73866840F}.Release|Mixed Platforms.ActiveCfg = Release|x64 - {5CCCB9CF-0384-458F-BA08-72B73866840F}.Release|Mixed Platforms.Build.0 = Release|x64 {5CCCB9CF-0384-458F-BA08-72B73866840F}.Release|Win32.ActiveCfg = Release|Win32 {5CCCB9CF-0384-458F-BA08-72B73866840F}.Release|Win32.Build.0 = Release|Win32 {5CCCB9CF-0384-458F-BA08-72B73866840F}.Release|x64.ActiveCfg = Release|x64 {5CCCB9CF-0384-458F-BA08-72B73866840F}.Release|x64.Build.0 = Release|x64 - {5CCCB9CF-0384-458F-BA08-72B73866840F}.Release|x86.ActiveCfg = Release|Win32 - {5CCCB9CF-0384-458F-BA08-72B73866840F}.Release|x86.Build.0 = Release|Win32 {A5A8D8FA-9E32-4010-8AAF-AE580C5AF728}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {A5A8D8FA-9E32-4010-8AAF-AE580C5AF728}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A5A8D8FA-9E32-4010-8AAF-AE580C5AF728}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 - {A5A8D8FA-9E32-4010-8AAF-AE580C5AF728}.Debug|Mixed Platforms.Build.0 = Debug|x86 - {A5A8D8FA-9E32-4010-8AAF-AE580C5AF728}.Debug|Win32.ActiveCfg = Debug|x86 - {A5A8D8FA-9E32-4010-8AAF-AE580C5AF728}.Debug|x64.ActiveCfg = Debug|x64 - {A5A8D8FA-9E32-4010-8AAF-AE580C5AF728}.Debug|x64.Build.0 = Debug|x64 - {A5A8D8FA-9E32-4010-8AAF-AE580C5AF728}.Debug|x86.ActiveCfg = Debug|x86 - {A5A8D8FA-9E32-4010-8AAF-AE580C5AF728}.Debug|x86.Build.0 = Debug|x86 + {A5A8D8FA-9E32-4010-8AAF-AE580C5AF728}.Debug|Win32.ActiveCfg = Debug|Any CPU + {A5A8D8FA-9E32-4010-8AAF-AE580C5AF728}.Debug|x64.ActiveCfg = Debug|Any CPU {A5A8D8FA-9E32-4010-8AAF-AE580C5AF728}.Release|Any CPU.ActiveCfg = Release|Any CPU {A5A8D8FA-9E32-4010-8AAF-AE580C5AF728}.Release|Any CPU.Build.0 = Release|Any CPU - {A5A8D8FA-9E32-4010-8AAF-AE580C5AF728}.Release|Mixed Platforms.ActiveCfg = Release|x86 - {A5A8D8FA-9E32-4010-8AAF-AE580C5AF728}.Release|Mixed Platforms.Build.0 = Release|x86 - {A5A8D8FA-9E32-4010-8AAF-AE580C5AF728}.Release|Win32.ActiveCfg = Release|x86 - {A5A8D8FA-9E32-4010-8AAF-AE580C5AF728}.Release|x64.ActiveCfg = Release|x64 - {A5A8D8FA-9E32-4010-8AAF-AE580C5AF728}.Release|x64.Build.0 = Release|x64 - {A5A8D8FA-9E32-4010-8AAF-AE580C5AF728}.Release|x86.ActiveCfg = Release|x86 - {A5A8D8FA-9E32-4010-8AAF-AE580C5AF728}.Release|x86.Build.0 = Release|x86 + {A5A8D8FA-9E32-4010-8AAF-AE580C5AF728}.Release|Win32.ActiveCfg = Release|Any CPU + {A5A8D8FA-9E32-4010-8AAF-AE580C5AF728}.Release|x64.ActiveCfg = Release|Any CPU {4911BD82-49EF-4858-8B51-5394F86739A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {4911BD82-49EF-4858-8B51-5394F86739A4}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4911BD82-49EF-4858-8B51-5394F86739A4}.Debug|Mixed Platforms.ActiveCfg = Debug|x64 - {4911BD82-49EF-4858-8B51-5394F86739A4}.Debug|Mixed Platforms.Build.0 = Debug|x64 - {4911BD82-49EF-4858-8B51-5394F86739A4}.Debug|Win32.ActiveCfg = Debug|x64 - {4911BD82-49EF-4858-8B51-5394F86739A4}.Debug|x64.ActiveCfg = Debug|x64 - {4911BD82-49EF-4858-8B51-5394F86739A4}.Debug|x64.Build.0 = Debug|x64 - {4911BD82-49EF-4858-8B51-5394F86739A4}.Debug|x86.ActiveCfg = Debug|x86 - {4911BD82-49EF-4858-8B51-5394F86739A4}.Debug|x86.Build.0 = Debug|x86 + {4911BD82-49EF-4858-8B51-5394F86739A4}.Debug|Win32.ActiveCfg = Debug|Any CPU + {4911BD82-49EF-4858-8B51-5394F86739A4}.Debug|x64.ActiveCfg = Debug|Any CPU + {4911BD82-49EF-4858-8B51-5394F86739A4}.Debug|x64.Build.0 = Debug|Any CPU {4911BD82-49EF-4858-8B51-5394F86739A4}.Release|Any CPU.ActiveCfg = Release|Any CPU {4911BD82-49EF-4858-8B51-5394F86739A4}.Release|Any CPU.Build.0 = Release|Any CPU - {4911BD82-49EF-4858-8B51-5394F86739A4}.Release|Mixed Platforms.ActiveCfg = Release|x64 - {4911BD82-49EF-4858-8B51-5394F86739A4}.Release|Mixed Platforms.Build.0 = Release|x64 - {4911BD82-49EF-4858-8B51-5394F86739A4}.Release|Win32.ActiveCfg = Release|x64 + {4911BD82-49EF-4858-8B51-5394F86739A4}.Release|Win32.ActiveCfg = Release|Any CPU {4911BD82-49EF-4858-8B51-5394F86739A4}.Release|x64.ActiveCfg = Release|Any CPU - {4911BD82-49EF-4858-8B51-5394F86739A4}.Release|x64.Build.0 = Release|Any CPU - {4911BD82-49EF-4858-8B51-5394F86739A4}.Release|x86.ActiveCfg = Release|x86 - {4911BD82-49EF-4858-8B51-5394F86739A4}.Release|x86.Build.0 = Release|x86 {32338A04-5B6B-4C63-8EE7-C6400F73B5D7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {32338A04-5B6B-4C63-8EE7-C6400F73B5D7}.Debug|Any CPU.Build.0 = Debug|Any CPU - {32338A04-5B6B-4C63-8EE7-C6400F73B5D7}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 - {32338A04-5B6B-4C63-8EE7-C6400F73B5D7}.Debug|Mixed Platforms.Build.0 = Debug|x86 - {32338A04-5B6B-4C63-8EE7-C6400F73B5D7}.Debug|Win32.ActiveCfg = Debug|x86 + {32338A04-5B6B-4C63-8EE7-C6400F73B5D7}.Debug|Win32.ActiveCfg = Debug|Any CPU {32338A04-5B6B-4C63-8EE7-C6400F73B5D7}.Debug|x64.ActiveCfg = Debug|x64 {32338A04-5B6B-4C63-8EE7-C6400F73B5D7}.Debug|x64.Build.0 = Debug|x64 - {32338A04-5B6B-4C63-8EE7-C6400F73B5D7}.Debug|x86.ActiveCfg = Debug|x86 - {32338A04-5B6B-4C63-8EE7-C6400F73B5D7}.Debug|x86.Build.0 = Debug|x86 - {32338A04-5B6B-4C63-8EE7-C6400F73B5D7}.Release|Any CPU.ActiveCfg = Release|x64 - {32338A04-5B6B-4C63-8EE7-C6400F73B5D7}.Release|Mixed Platforms.ActiveCfg = Release|x86 - {32338A04-5B6B-4C63-8EE7-C6400F73B5D7}.Release|Mixed Platforms.Build.0 = Release|x86 - {32338A04-5B6B-4C63-8EE7-C6400F73B5D7}.Release|Win32.ActiveCfg = Release|x86 - {32338A04-5B6B-4C63-8EE7-C6400F73B5D7}.Release|x64.ActiveCfg = Release|x64 - {32338A04-5B6B-4C63-8EE7-C6400F73B5D7}.Release|x64.Build.0 = Release|x64 - {32338A04-5B6B-4C63-8EE7-C6400F73B5D7}.Release|x86.ActiveCfg = Release|x86 - {32338A04-5B6B-4C63-8EE7-C6400F73B5D7}.Release|x86.Build.0 = Release|x86 + {32338A04-5B6B-4C63-8EE7-C6400F73B5D7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {32338A04-5B6B-4C63-8EE7-C6400F73B5D7}.Release|Any CPU.Build.0 = Release|Any CPU + {32338A04-5B6B-4C63-8EE7-C6400F73B5D7}.Release|Win32.ActiveCfg = Release|Any CPU + {32338A04-5B6B-4C63-8EE7-C6400F73B5D7}.Release|x64.ActiveCfg = Release|Any CPU {6458A13A-30EF-45A9-9D58-E5031B17BEE2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {6458A13A-30EF-45A9-9D58-E5031B17BEE2}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6458A13A-30EF-45A9-9D58-E5031B17BEE2}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 - {6458A13A-30EF-45A9-9D58-E5031B17BEE2}.Debug|Mixed Platforms.Build.0 = Debug|x86 - {6458A13A-30EF-45A9-9D58-E5031B17BEE2}.Debug|Win32.ActiveCfg = Debug|x86 + {6458A13A-30EF-45A9-9D58-E5031B17BEE2}.Debug|Win32.ActiveCfg = Debug|Any CPU {6458A13A-30EF-45A9-9D58-E5031B17BEE2}.Debug|x64.ActiveCfg = Debug|Any CPU {6458A13A-30EF-45A9-9D58-E5031B17BEE2}.Debug|x64.Build.0 = Debug|Any CPU - {6458A13A-30EF-45A9-9D58-E5031B17BEE2}.Debug|x86.ActiveCfg = Debug|x86 - {6458A13A-30EF-45A9-9D58-E5031B17BEE2}.Debug|x86.Build.0 = Debug|x86 {6458A13A-30EF-45A9-9D58-E5031B17BEE2}.Release|Any CPU.ActiveCfg = Release|Any CPU {6458A13A-30EF-45A9-9D58-E5031B17BEE2}.Release|Any CPU.Build.0 = Release|Any CPU - {6458A13A-30EF-45A9-9D58-E5031B17BEE2}.Release|Mixed Platforms.ActiveCfg = Release|x86 - {6458A13A-30EF-45A9-9D58-E5031B17BEE2}.Release|Mixed Platforms.Build.0 = Release|x86 - {6458A13A-30EF-45A9-9D58-E5031B17BEE2}.Release|Win32.ActiveCfg = Release|x86 + {6458A13A-30EF-45A9-9D58-E5031B17BEE2}.Release|Win32.ActiveCfg = Release|Any CPU {6458A13A-30EF-45A9-9D58-E5031B17BEE2}.Release|x64.ActiveCfg = Release|Any CPU - {6458A13A-30EF-45A9-9D58-E5031B17BEE2}.Release|x64.Build.0 = Release|Any CPU - {6458A13A-30EF-45A9-9D58-E5031B17BEE2}.Release|x86.ActiveCfg = Release|x86 - {6458A13A-30EF-45A9-9D58-E5031B17BEE2}.Release|x86.Build.0 = Release|x86 {F2EC7193-D5E5-4252-9803-5CEB407E910F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {F2EC7193-D5E5-4252-9803-5CEB407E910F}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F2EC7193-D5E5-4252-9803-5CEB407E910F}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 - {F2EC7193-D5E5-4252-9803-5CEB407E910F}.Debug|Mixed Platforms.Build.0 = Debug|x86 - {F2EC7193-D5E5-4252-9803-5CEB407E910F}.Debug|Win32.ActiveCfg = Debug|x86 + {F2EC7193-D5E5-4252-9803-5CEB407E910F}.Debug|Win32.ActiveCfg = Debug|Any CPU {F2EC7193-D5E5-4252-9803-5CEB407E910F}.Debug|x64.ActiveCfg = Debug|Any CPU {F2EC7193-D5E5-4252-9803-5CEB407E910F}.Debug|x64.Build.0 = Debug|Any CPU - {F2EC7193-D5E5-4252-9803-5CEB407E910F}.Debug|x86.ActiveCfg = Debug|x86 - {F2EC7193-D5E5-4252-9803-5CEB407E910F}.Debug|x86.Build.0 = Debug|x86 {F2EC7193-D5E5-4252-9803-5CEB407E910F}.Release|Any CPU.ActiveCfg = Release|Any CPU {F2EC7193-D5E5-4252-9803-5CEB407E910F}.Release|Any CPU.Build.0 = Release|Any CPU - {F2EC7193-D5E5-4252-9803-5CEB407E910F}.Release|Mixed Platforms.ActiveCfg = Release|x86 - {F2EC7193-D5E5-4252-9803-5CEB407E910F}.Release|Mixed Platforms.Build.0 = Release|x86 - {F2EC7193-D5E5-4252-9803-5CEB407E910F}.Release|Win32.ActiveCfg = Release|x86 - {F2EC7193-D5E5-4252-9803-5CEB407E910F}.Release|x64.ActiveCfg = Release|x64 - {F2EC7193-D5E5-4252-9803-5CEB407E910F}.Release|x64.Build.0 = Release|x64 - {F2EC7193-D5E5-4252-9803-5CEB407E910F}.Release|x86.ActiveCfg = Release|x86 - {F2EC7193-D5E5-4252-9803-5CEB407E910F}.Release|x86.Build.0 = Release|x86 + {F2EC7193-D5E5-4252-9803-5CEB407E910F}.Release|Win32.ActiveCfg = Release|Any CPU + {F2EC7193-D5E5-4252-9803-5CEB407E910F}.Release|x64.ActiveCfg = Release|Any CPU {8427CAA5-80B8-4952-9A68-5F3DFCFBDF40}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8427CAA5-80B8-4952-9A68-5F3DFCFBDF40}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 - {8427CAA5-80B8-4952-9A68-5F3DFCFBDF40}.Debug|Mixed Platforms.Build.0 = Debug|x86 - {8427CAA5-80B8-4952-9A68-5F3DFCFBDF40}.Debug|Win32.ActiveCfg = Debug|x86 + {8427CAA5-80B8-4952-9A68-5F3DFCFBDF40}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8427CAA5-80B8-4952-9A68-5F3DFCFBDF40}.Debug|Win32.ActiveCfg = Debug|Any CPU {8427CAA5-80B8-4952-9A68-5F3DFCFBDF40}.Debug|x64.ActiveCfg = Debug|x64 {8427CAA5-80B8-4952-9A68-5F3DFCFBDF40}.Debug|x64.Build.0 = Debug|x64 - {8427CAA5-80B8-4952-9A68-5F3DFCFBDF40}.Debug|x86.ActiveCfg = Debug|x86 - {8427CAA5-80B8-4952-9A68-5F3DFCFBDF40}.Debug|x86.Build.0 = Debug|x86 - {8427CAA5-80B8-4952-9A68-5F3DFCFBDF40}.Release|Any CPU.ActiveCfg = Release|x64 - {8427CAA5-80B8-4952-9A68-5F3DFCFBDF40}.Release|Mixed Platforms.ActiveCfg = Release|x86 - {8427CAA5-80B8-4952-9A68-5F3DFCFBDF40}.Release|Mixed Platforms.Build.0 = Release|x86 - {8427CAA5-80B8-4952-9A68-5F3DFCFBDF40}.Release|Win32.ActiveCfg = Release|x86 - {8427CAA5-80B8-4952-9A68-5F3DFCFBDF40}.Release|x64.ActiveCfg = Release|x64 - {8427CAA5-80B8-4952-9A68-5F3DFCFBDF40}.Release|x64.Build.0 = Release|x64 - {8427CAA5-80B8-4952-9A68-5F3DFCFBDF40}.Release|x86.ActiveCfg = Release|x86 - {8427CAA5-80B8-4952-9A68-5F3DFCFBDF40}.Release|x86.Build.0 = Release|x86 + {8427CAA5-80B8-4952-9A68-5F3DFCFBDF40}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8427CAA5-80B8-4952-9A68-5F3DFCFBDF40}.Release|Any CPU.Build.0 = Release|Any CPU + {8427CAA5-80B8-4952-9A68-5F3DFCFBDF40}.Release|Win32.ActiveCfg = Release|Any CPU + {8427CAA5-80B8-4952-9A68-5F3DFCFBDF40}.Release|x64.ActiveCfg = Release|Any CPU {8A0426FA-0BC2-4C49-A6E5-1F9A68156F19}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {8A0426FA-0BC2-4C49-A6E5-1F9A68156F19}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8A0426FA-0BC2-4C49-A6E5-1F9A68156F19}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 - {8A0426FA-0BC2-4C49-A6E5-1F9A68156F19}.Debug|Mixed Platforms.Build.0 = Debug|x86 - {8A0426FA-0BC2-4C49-A6E5-1F9A68156F19}.Debug|Win32.ActiveCfg = Debug|x86 - {8A0426FA-0BC2-4C49-A6E5-1F9A68156F19}.Debug|x64.ActiveCfg = Debug|x64 - {8A0426FA-0BC2-4C49-A6E5-1F9A68156F19}.Debug|x64.Build.0 = Debug|x64 - {8A0426FA-0BC2-4C49-A6E5-1F9A68156F19}.Debug|x86.ActiveCfg = Debug|x86 - {8A0426FA-0BC2-4C49-A6E5-1F9A68156F19}.Debug|x86.Build.0 = Debug|x86 + {8A0426FA-0BC2-4C49-A6E5-1F9A68156F19}.Debug|Win32.ActiveCfg = Debug|Any CPU + {8A0426FA-0BC2-4C49-A6E5-1F9A68156F19}.Debug|x64.ActiveCfg = Debug|Any CPU + {8A0426FA-0BC2-4C49-A6E5-1F9A68156F19}.Debug|x64.Build.0 = Debug|Any CPU {8A0426FA-0BC2-4C49-A6E5-1F9A68156F19}.Release|Any CPU.ActiveCfg = Release|Any CPU {8A0426FA-0BC2-4C49-A6E5-1F9A68156F19}.Release|Any CPU.Build.0 = Release|Any CPU - {8A0426FA-0BC2-4C49-A6E5-1F9A68156F19}.Release|Mixed Platforms.ActiveCfg = Release|x86 - {8A0426FA-0BC2-4C49-A6E5-1F9A68156F19}.Release|Mixed Platforms.Build.0 = Release|x86 - {8A0426FA-0BC2-4C49-A6E5-1F9A68156F19}.Release|Win32.ActiveCfg = Release|x86 - {8A0426FA-0BC2-4C49-A6E5-1F9A68156F19}.Release|x64.ActiveCfg = Release|x64 - {8A0426FA-0BC2-4C49-A6E5-1F9A68156F19}.Release|x64.Build.0 = Release|x64 - {8A0426FA-0BC2-4C49-A6E5-1F9A68156F19}.Release|x86.ActiveCfg = Release|x86 - {8A0426FA-0BC2-4C49-A6E5-1F9A68156F19}.Release|x86.Build.0 = Release|x86 + {8A0426FA-0BC2-4C49-A6E5-1F9A68156F19}.Release|Win32.ActiveCfg = Release|Any CPU + {8A0426FA-0BC2-4C49-A6E5-1F9A68156F19}.Release|x64.ActiveCfg = Release|Any CPU {A574F3B1-E38B-4EE4-9394-49D6E2DF52EA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {A574F3B1-E38B-4EE4-9394-49D6E2DF52EA}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A574F3B1-E38B-4EE4-9394-49D6E2DF52EA}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 - {A574F3B1-E38B-4EE4-9394-49D6E2DF52EA}.Debug|Mixed Platforms.Build.0 = Debug|x86 - {A574F3B1-E38B-4EE4-9394-49D6E2DF52EA}.Debug|Win32.ActiveCfg = Debug|x86 + {A574F3B1-E38B-4EE4-9394-49D6E2DF52EA}.Debug|Win32.ActiveCfg = Debug|Any CPU {A574F3B1-E38B-4EE4-9394-49D6E2DF52EA}.Debug|x64.ActiveCfg = Debug|x64 {A574F3B1-E38B-4EE4-9394-49D6E2DF52EA}.Debug|x64.Build.0 = Debug|x64 - {A574F3B1-E38B-4EE4-9394-49D6E2DF52EA}.Debug|x86.ActiveCfg = Debug|x86 - {A574F3B1-E38B-4EE4-9394-49D6E2DF52EA}.Debug|x86.Build.0 = Debug|x86 {A574F3B1-E38B-4EE4-9394-49D6E2DF52EA}.Release|Any CPU.ActiveCfg = Release|Any CPU {A574F3B1-E38B-4EE4-9394-49D6E2DF52EA}.Release|Any CPU.Build.0 = Release|Any CPU - {A574F3B1-E38B-4EE4-9394-49D6E2DF52EA}.Release|Mixed Platforms.ActiveCfg = Release|x86 - {A574F3B1-E38B-4EE4-9394-49D6E2DF52EA}.Release|Mixed Platforms.Build.0 = Release|x86 - {A574F3B1-E38B-4EE4-9394-49D6E2DF52EA}.Release|Win32.ActiveCfg = Release|x86 - {A574F3B1-E38B-4EE4-9394-49D6E2DF52EA}.Release|x64.ActiveCfg = Release|x64 - {A574F3B1-E38B-4EE4-9394-49D6E2DF52EA}.Release|x64.Build.0 = Release|x64 - {A574F3B1-E38B-4EE4-9394-49D6E2DF52EA}.Release|x86.ActiveCfg = Release|x86 - {A574F3B1-E38B-4EE4-9394-49D6E2DF52EA}.Release|x86.Build.0 = Release|x86 + {A574F3B1-E38B-4EE4-9394-49D6E2DF52EA}.Release|Win32.ActiveCfg = Release|Any CPU + {A574F3B1-E38B-4EE4-9394-49D6E2DF52EA}.Release|x64.ActiveCfg = Release|Any CPU {B75FA7AD-968E-4990-B342-1B4B17C850DF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {B75FA7AD-968E-4990-B342-1B4B17C850DF}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B75FA7AD-968E-4990-B342-1B4B17C850DF}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 - {B75FA7AD-968E-4990-B342-1B4B17C850DF}.Debug|Mixed Platforms.Build.0 = Debug|x86 - {B75FA7AD-968E-4990-B342-1B4B17C850DF}.Debug|Win32.ActiveCfg = Debug|x86 - {B75FA7AD-968E-4990-B342-1B4B17C850DF}.Debug|x64.ActiveCfg = Debug|x64 - {B75FA7AD-968E-4990-B342-1B4B17C850DF}.Debug|x64.Build.0 = Debug|x64 - {B75FA7AD-968E-4990-B342-1B4B17C850DF}.Debug|x86.ActiveCfg = Debug|x86 - {B75FA7AD-968E-4990-B342-1B4B17C850DF}.Debug|x86.Build.0 = Debug|x86 + {B75FA7AD-968E-4990-B342-1B4B17C850DF}.Debug|Win32.ActiveCfg = Debug|Any CPU + {B75FA7AD-968E-4990-B342-1B4B17C850DF}.Debug|x64.ActiveCfg = Debug|Any CPU {B75FA7AD-968E-4990-B342-1B4B17C850DF}.Release|Any CPU.ActiveCfg = Release|Any CPU {B75FA7AD-968E-4990-B342-1B4B17C850DF}.Release|Any CPU.Build.0 = Release|Any CPU - {B75FA7AD-968E-4990-B342-1B4B17C850DF}.Release|Mixed Platforms.ActiveCfg = Release|x86 - {B75FA7AD-968E-4990-B342-1B4B17C850DF}.Release|Mixed Platforms.Build.0 = Release|x86 - {B75FA7AD-968E-4990-B342-1B4B17C850DF}.Release|Win32.ActiveCfg = Release|x86 - {B75FA7AD-968E-4990-B342-1B4B17C850DF}.Release|x64.ActiveCfg = Release|x64 - {B75FA7AD-968E-4990-B342-1B4B17C850DF}.Release|x64.Build.0 = Release|x64 - {B75FA7AD-968E-4990-B342-1B4B17C850DF}.Release|x86.ActiveCfg = Release|x86 - {B75FA7AD-968E-4990-B342-1B4B17C850DF}.Release|x86.Build.0 = Release|x86 + {B75FA7AD-968E-4990-B342-1B4B17C850DF}.Release|Win32.ActiveCfg = Release|Any CPU + {B75FA7AD-968E-4990-B342-1B4B17C850DF}.Release|x64.ActiveCfg = Release|Any CPU {F2DFEB00-BB35-4665-85EA-CB8C7729A6B7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {F2DFEB00-BB35-4665-85EA-CB8C7729A6B7}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F2DFEB00-BB35-4665-85EA-CB8C7729A6B7}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 - {F2DFEB00-BB35-4665-85EA-CB8C7729A6B7}.Debug|Mixed Platforms.Build.0 = Debug|x86 - {F2DFEB00-BB35-4665-85EA-CB8C7729A6B7}.Debug|Win32.ActiveCfg = Debug|x86 - {F2DFEB00-BB35-4665-85EA-CB8C7729A6B7}.Debug|x64.ActiveCfg = Debug|x64 - {F2DFEB00-BB35-4665-85EA-CB8C7729A6B7}.Debug|x64.Build.0 = Debug|x64 - {F2DFEB00-BB35-4665-85EA-CB8C7729A6B7}.Debug|x86.ActiveCfg = Debug|x86 - {F2DFEB00-BB35-4665-85EA-CB8C7729A6B7}.Debug|x86.Build.0 = Debug|x86 + {F2DFEB00-BB35-4665-85EA-CB8C7729A6B7}.Debug|Win32.ActiveCfg = Debug|Any CPU + {F2DFEB00-BB35-4665-85EA-CB8C7729A6B7}.Debug|x64.ActiveCfg = Debug|Any CPU {F2DFEB00-BB35-4665-85EA-CB8C7729A6B7}.Release|Any CPU.ActiveCfg = Release|Any CPU {F2DFEB00-BB35-4665-85EA-CB8C7729A6B7}.Release|Any CPU.Build.0 = Release|Any CPU - {F2DFEB00-BB35-4665-85EA-CB8C7729A6B7}.Release|Mixed Platforms.ActiveCfg = Release|x86 - {F2DFEB00-BB35-4665-85EA-CB8C7729A6B7}.Release|Mixed Platforms.Build.0 = Release|x86 - {F2DFEB00-BB35-4665-85EA-CB8C7729A6B7}.Release|Win32.ActiveCfg = Release|x86 - {F2DFEB00-BB35-4665-85EA-CB8C7729A6B7}.Release|x64.ActiveCfg = Release|x64 - {F2DFEB00-BB35-4665-85EA-CB8C7729A6B7}.Release|x64.Build.0 = Release|x64 - {F2DFEB00-BB35-4665-85EA-CB8C7729A6B7}.Release|x86.ActiveCfg = Release|x86 - {F2DFEB00-BB35-4665-85EA-CB8C7729A6B7}.Release|x86.Build.0 = Release|x86 + {F2DFEB00-BB35-4665-85EA-CB8C7729A6B7}.Release|Win32.ActiveCfg = Release|Any CPU + {F2DFEB00-BB35-4665-85EA-CB8C7729A6B7}.Release|x64.ActiveCfg = Release|Any CPU {A05B6AA6-0EC3-495D-BCC4-ECE1210071A8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {A05B6AA6-0EC3-495D-BCC4-ECE1210071A8}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A05B6AA6-0EC3-495D-BCC4-ECE1210071A8}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 - {A05B6AA6-0EC3-495D-BCC4-ECE1210071A8}.Debug|Mixed Platforms.Build.0 = Debug|x86 - {A05B6AA6-0EC3-495D-BCC4-ECE1210071A8}.Debug|Win32.ActiveCfg = Debug|x86 - {A05B6AA6-0EC3-495D-BCC4-ECE1210071A8}.Debug|x64.ActiveCfg = Debug|x64 - {A05B6AA6-0EC3-495D-BCC4-ECE1210071A8}.Debug|x64.Build.0 = Debug|x64 - {A05B6AA6-0EC3-495D-BCC4-ECE1210071A8}.Debug|x86.ActiveCfg = Debug|x86 - {A05B6AA6-0EC3-495D-BCC4-ECE1210071A8}.Debug|x86.Build.0 = Debug|x86 + {A05B6AA6-0EC3-495D-BCC4-ECE1210071A8}.Debug|Win32.ActiveCfg = Debug|Any CPU + {A05B6AA6-0EC3-495D-BCC4-ECE1210071A8}.Debug|x64.ActiveCfg = Debug|Any CPU {A05B6AA6-0EC3-495D-BCC4-ECE1210071A8}.Release|Any CPU.ActiveCfg = Release|Any CPU {A05B6AA6-0EC3-495D-BCC4-ECE1210071A8}.Release|Any CPU.Build.0 = Release|Any CPU - {A05B6AA6-0EC3-495D-BCC4-ECE1210071A8}.Release|Mixed Platforms.ActiveCfg = Release|x86 - {A05B6AA6-0EC3-495D-BCC4-ECE1210071A8}.Release|Mixed Platforms.Build.0 = Release|x86 - {A05B6AA6-0EC3-495D-BCC4-ECE1210071A8}.Release|Win32.ActiveCfg = Release|x86 - {A05B6AA6-0EC3-495D-BCC4-ECE1210071A8}.Release|x64.ActiveCfg = Release|x64 - {A05B6AA6-0EC3-495D-BCC4-ECE1210071A8}.Release|x64.Build.0 = Release|x64 - {A05B6AA6-0EC3-495D-BCC4-ECE1210071A8}.Release|x86.ActiveCfg = Release|x86 - {A05B6AA6-0EC3-495D-BCC4-ECE1210071A8}.Release|x86.Build.0 = Release|x86 + {A05B6AA6-0EC3-495D-BCC4-ECE1210071A8}.Release|Win32.ActiveCfg = Release|Any CPU + {A05B6AA6-0EC3-495D-BCC4-ECE1210071A8}.Release|x64.ActiveCfg = Release|Any CPU {8CF07381-BEA2-4AFC-B3DD-9B2F21C65A3A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {8CF07381-BEA2-4AFC-B3DD-9B2F21C65A3A}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8CF07381-BEA2-4AFC-B3DD-9B2F21C65A3A}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 - {8CF07381-BEA2-4AFC-B3DD-9B2F21C65A3A}.Debug|Mixed Platforms.Build.0 = Debug|x86 - {8CF07381-BEA2-4AFC-B3DD-9B2F21C65A3A}.Debug|Win32.ActiveCfg = Debug|x86 + {8CF07381-BEA2-4AFC-B3DD-9B2F21C65A3A}.Debug|Win32.ActiveCfg = Debug|Any CPU {8CF07381-BEA2-4AFC-B3DD-9B2F21C65A3A}.Debug|x64.ActiveCfg = Debug|x64 {8CF07381-BEA2-4AFC-B3DD-9B2F21C65A3A}.Debug|x64.Build.0 = Debug|x64 - {8CF07381-BEA2-4AFC-B3DD-9B2F21C65A3A}.Debug|x86.ActiveCfg = Debug|x86 - {8CF07381-BEA2-4AFC-B3DD-9B2F21C65A3A}.Debug|x86.Build.0 = Debug|x86 {8CF07381-BEA2-4AFC-B3DD-9B2F21C65A3A}.Release|Any CPU.ActiveCfg = Release|Any CPU {8CF07381-BEA2-4AFC-B3DD-9B2F21C65A3A}.Release|Any CPU.Build.0 = Release|Any CPU - {8CF07381-BEA2-4AFC-B3DD-9B2F21C65A3A}.Release|Mixed Platforms.ActiveCfg = Release|x86 - {8CF07381-BEA2-4AFC-B3DD-9B2F21C65A3A}.Release|Mixed Platforms.Build.0 = Release|x86 - {8CF07381-BEA2-4AFC-B3DD-9B2F21C65A3A}.Release|Win32.ActiveCfg = Release|x86 - {8CF07381-BEA2-4AFC-B3DD-9B2F21C65A3A}.Release|x64.ActiveCfg = Release|x64 - {8CF07381-BEA2-4AFC-B3DD-9B2F21C65A3A}.Release|x64.Build.0 = Release|x64 - {8CF07381-BEA2-4AFC-B3DD-9B2F21C65A3A}.Release|x86.ActiveCfg = Release|x86 - {8CF07381-BEA2-4AFC-B3DD-9B2F21C65A3A}.Release|x86.Build.0 = Release|x86 + {8CF07381-BEA2-4AFC-B3DD-9B2F21C65A3A}.Release|Win32.ActiveCfg = Release|Any CPU + {8CF07381-BEA2-4AFC-B3DD-9B2F21C65A3A}.Release|x64.ActiveCfg = Release|Any CPU {9253A314-1821-42BF-B02F-2BF986B1765D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {9253A314-1821-42BF-B02F-2BF986B1765D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {9253A314-1821-42BF-B02F-2BF986B1765D}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 - {9253A314-1821-42BF-B02F-2BF986B1765D}.Debug|Mixed Platforms.Build.0 = Debug|x86 - {9253A314-1821-42BF-B02F-2BF986B1765D}.Debug|Win32.ActiveCfg = Debug|x86 + {9253A314-1821-42BF-B02F-2BF986B1765D}.Debug|Win32.ActiveCfg = Debug|Any CPU {9253A314-1821-42BF-B02F-2BF986B1765D}.Debug|x64.ActiveCfg = Debug|x64 {9253A314-1821-42BF-B02F-2BF986B1765D}.Debug|x64.Build.0 = Debug|x64 - {9253A314-1821-42BF-B02F-2BF986B1765D}.Debug|x86.ActiveCfg = Debug|x86 - {9253A314-1821-42BF-B02F-2BF986B1765D}.Debug|x86.Build.0 = Debug|x86 {9253A314-1821-42BF-B02F-2BF986B1765D}.Release|Any CPU.ActiveCfg = Release|Any CPU {9253A314-1821-42BF-B02F-2BF986B1765D}.Release|Any CPU.Build.0 = Release|Any CPU - {9253A314-1821-42BF-B02F-2BF986B1765D}.Release|Mixed Platforms.ActiveCfg = Release|x86 - {9253A314-1821-42BF-B02F-2BF986B1765D}.Release|Mixed Platforms.Build.0 = Release|x86 - {9253A314-1821-42BF-B02F-2BF986B1765D}.Release|Win32.ActiveCfg = Release|x86 - {9253A314-1821-42BF-B02F-2BF986B1765D}.Release|x64.ActiveCfg = Release|x64 - {9253A314-1821-42BF-B02F-2BF986B1765D}.Release|x64.Build.0 = Release|x64 - {9253A314-1821-42BF-B02F-2BF986B1765D}.Release|x86.ActiveCfg = Release|x86 - {9253A314-1821-42BF-B02F-2BF986B1765D}.Release|x86.Build.0 = Release|x86 + {9253A314-1821-42BF-B02F-2BF986B1765D}.Release|Win32.ActiveCfg = Release|Any CPU + {9253A314-1821-42BF-B02F-2BF986B1765D}.Release|x64.ActiveCfg = Release|Any CPU {1DD41038-D885-46C5-8DDE-E0B82F066584}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {1DD41038-D885-46C5-8DDE-E0B82F066584}.Debug|Any CPU.Build.0 = Debug|Any CPU - {1DD41038-D885-46C5-8DDE-E0B82F066584}.Debug|Mixed Platforms.ActiveCfg = Debug|x64 - {1DD41038-D885-46C5-8DDE-E0B82F066584}.Debug|Mixed Platforms.Build.0 = Debug|x64 - {1DD41038-D885-46C5-8DDE-E0B82F066584}.Debug|Win32.ActiveCfg = Debug|x64 - {1DD41038-D885-46C5-8DDE-E0B82F066584}.Debug|x64.ActiveCfg = Debug|x64 - {1DD41038-D885-46C5-8DDE-E0B82F066584}.Debug|x64.Build.0 = Debug|x64 - {1DD41038-D885-46C5-8DDE-E0B82F066584}.Debug|x86.ActiveCfg = Debug|x86 - {1DD41038-D885-46C5-8DDE-E0B82F066584}.Debug|x86.Build.0 = Debug|x86 + {1DD41038-D885-46C5-8DDE-E0B82F066584}.Debug|Win32.ActiveCfg = Debug|Any CPU + {1DD41038-D885-46C5-8DDE-E0B82F066584}.Debug|x64.ActiveCfg = Debug|Any CPU {1DD41038-D885-46C5-8DDE-E0B82F066584}.Release|Any CPU.ActiveCfg = Release|Any CPU {1DD41038-D885-46C5-8DDE-E0B82F066584}.Release|Any CPU.Build.0 = Release|Any CPU - {1DD41038-D885-46C5-8DDE-E0B82F066584}.Release|Mixed Platforms.ActiveCfg = Release|x64 - {1DD41038-D885-46C5-8DDE-E0B82F066584}.Release|Mixed Platforms.Build.0 = Release|x64 - {1DD41038-D885-46C5-8DDE-E0B82F066584}.Release|Win32.ActiveCfg = Release|x64 - {1DD41038-D885-46C5-8DDE-E0B82F066584}.Release|x64.ActiveCfg = Release|x64 - {1DD41038-D885-46C5-8DDE-E0B82F066584}.Release|x64.Build.0 = Release|x64 - {1DD41038-D885-46C5-8DDE-E0B82F066584}.Release|x86.ActiveCfg = Release|x86 - {1DD41038-D885-46C5-8DDE-E0B82F066584}.Release|x86.Build.0 = Release|x86 + {1DD41038-D885-46C5-8DDE-E0B82F066584}.Release|Win32.ActiveCfg = Release|Any CPU + {1DD41038-D885-46C5-8DDE-E0B82F066584}.Release|x64.ActiveCfg = Release|Any CPU {5802C7E9-157E-4124-946D-70B5AE48A5A1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {5802C7E9-157E-4124-946D-70B5AE48A5A1}.Debug|Any CPU.Build.0 = Debug|Any CPU - {5802C7E9-157E-4124-946D-70B5AE48A5A1}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 - {5802C7E9-157E-4124-946D-70B5AE48A5A1}.Debug|Mixed Platforms.Build.0 = Debug|x86 - {5802C7E9-157E-4124-946D-70B5AE48A5A1}.Debug|Win32.ActiveCfg = Debug|x86 - {5802C7E9-157E-4124-946D-70B5AE48A5A1}.Debug|x64.ActiveCfg = Debug|x64 - {5802C7E9-157E-4124-946D-70B5AE48A5A1}.Debug|x64.Build.0 = Debug|x64 - {5802C7E9-157E-4124-946D-70B5AE48A5A1}.Debug|x86.ActiveCfg = Debug|x86 - {5802C7E9-157E-4124-946D-70B5AE48A5A1}.Debug|x86.Build.0 = Debug|x86 + {5802C7E9-157E-4124-946D-70B5AE48A5A1}.Debug|Win32.ActiveCfg = Debug|Any CPU + {5802C7E9-157E-4124-946D-70B5AE48A5A1}.Debug|x64.ActiveCfg = Debug|Any CPU {5802C7E9-157E-4124-946D-70B5AE48A5A1}.Release|Any CPU.ActiveCfg = Release|Any CPU {5802C7E9-157E-4124-946D-70B5AE48A5A1}.Release|Any CPU.Build.0 = Release|Any CPU - {5802C7E9-157E-4124-946D-70B5AE48A5A1}.Release|Mixed Platforms.ActiveCfg = Release|x86 - {5802C7E9-157E-4124-946D-70B5AE48A5A1}.Release|Mixed Platforms.Build.0 = Release|x86 - {5802C7E9-157E-4124-946D-70B5AE48A5A1}.Release|Win32.ActiveCfg = Release|x86 - {5802C7E9-157E-4124-946D-70B5AE48A5A1}.Release|x64.ActiveCfg = Release|x64 - {5802C7E9-157E-4124-946D-70B5AE48A5A1}.Release|x64.Build.0 = Release|x64 - {5802C7E9-157E-4124-946D-70B5AE48A5A1}.Release|x86.ActiveCfg = Release|x86 - {5802C7E9-157E-4124-946D-70B5AE48A5A1}.Release|x86.Build.0 = Release|x86 + {5802C7E9-157E-4124-946D-70B5AE48A5A1}.Release|Win32.ActiveCfg = Release|Any CPU + {5802C7E9-157E-4124-946D-70B5AE48A5A1}.Release|x64.ActiveCfg = Release|Any CPU {74C2036B-2C9B-4FC8-B7BD-AE81A8DCE533}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {74C2036B-2C9B-4FC8-B7BD-AE81A8DCE533}.Debug|Any CPU.Build.0 = Debug|Any CPU - {74C2036B-2C9B-4FC8-B7BD-AE81A8DCE533}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {74C2036B-2C9B-4FC8-B7BD-AE81A8DCE533}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU {74C2036B-2C9B-4FC8-B7BD-AE81A8DCE533}.Debug|Win32.ActiveCfg = Debug|Any CPU {74C2036B-2C9B-4FC8-B7BD-AE81A8DCE533}.Debug|x64.ActiveCfg = Debug|Any CPU {74C2036B-2C9B-4FC8-B7BD-AE81A8DCE533}.Debug|x64.Build.0 = Debug|Any CPU - {74C2036B-2C9B-4FC8-B7BD-AE81A8DCE533}.Debug|x86.ActiveCfg = Debug|Any CPU - {74C2036B-2C9B-4FC8-B7BD-AE81A8DCE533}.Debug|x86.Build.0 = Debug|Any CPU {74C2036B-2C9B-4FC8-B7BD-AE81A8DCE533}.Release|Any CPU.ActiveCfg = Release|Any CPU {74C2036B-2C9B-4FC8-B7BD-AE81A8DCE533}.Release|Any CPU.Build.0 = Release|Any CPU - {74C2036B-2C9B-4FC8-B7BD-AE81A8DCE533}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {74C2036B-2C9B-4FC8-B7BD-AE81A8DCE533}.Release|Mixed Platforms.Build.0 = Release|Any CPU {74C2036B-2C9B-4FC8-B7BD-AE81A8DCE533}.Release|Win32.ActiveCfg = Release|Any CPU {74C2036B-2C9B-4FC8-B7BD-AE81A8DCE533}.Release|x64.ActiveCfg = Release|Any CPU - {74C2036B-2C9B-4FC8-B7BD-AE81A8DCE533}.Release|x64.Build.0 = Release|Any CPU - {74C2036B-2C9B-4FC8-B7BD-AE81A8DCE533}.Release|x86.ActiveCfg = Release|Any CPU - {74C2036B-2C9B-4FC8-B7BD-AE81A8DCE533}.Release|x86.Build.0 = Release|Any CPU {39B43BBB-BAFC-4D85-9BEA-3BCB7EFED89C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {39B43BBB-BAFC-4D85-9BEA-3BCB7EFED89C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {39B43BBB-BAFC-4D85-9BEA-3BCB7EFED89C}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 - {39B43BBB-BAFC-4D85-9BEA-3BCB7EFED89C}.Debug|Mixed Platforms.Build.0 = Debug|x86 - {39B43BBB-BAFC-4D85-9BEA-3BCB7EFED89C}.Debug|Win32.ActiveCfg = Debug|x86 - {39B43BBB-BAFC-4D85-9BEA-3BCB7EFED89C}.Debug|x64.ActiveCfg = Debug|x64 - {39B43BBB-BAFC-4D85-9BEA-3BCB7EFED89C}.Debug|x64.Build.0 = Debug|x64 - {39B43BBB-BAFC-4D85-9BEA-3BCB7EFED89C}.Debug|x86.ActiveCfg = Debug|x86 - {39B43BBB-BAFC-4D85-9BEA-3BCB7EFED89C}.Debug|x86.Build.0 = Debug|x86 + {39B43BBB-BAFC-4D85-9BEA-3BCB7EFED89C}.Debug|Win32.ActiveCfg = Debug|Any CPU + {39B43BBB-BAFC-4D85-9BEA-3BCB7EFED89C}.Debug|x64.ActiveCfg = Debug|Any CPU {39B43BBB-BAFC-4D85-9BEA-3BCB7EFED89C}.Release|Any CPU.ActiveCfg = Release|Any CPU {39B43BBB-BAFC-4D85-9BEA-3BCB7EFED89C}.Release|Any CPU.Build.0 = Release|Any CPU - {39B43BBB-BAFC-4D85-9BEA-3BCB7EFED89C}.Release|Mixed Platforms.ActiveCfg = Release|x86 - {39B43BBB-BAFC-4D85-9BEA-3BCB7EFED89C}.Release|Mixed Platforms.Build.0 = Release|x86 - {39B43BBB-BAFC-4D85-9BEA-3BCB7EFED89C}.Release|Win32.ActiveCfg = Release|x86 - {39B43BBB-BAFC-4D85-9BEA-3BCB7EFED89C}.Release|x64.ActiveCfg = Release|x64 - {39B43BBB-BAFC-4D85-9BEA-3BCB7EFED89C}.Release|x64.Build.0 = Release|x64 - {39B43BBB-BAFC-4D85-9BEA-3BCB7EFED89C}.Release|x86.ActiveCfg = Release|x86 - {39B43BBB-BAFC-4D85-9BEA-3BCB7EFED89C}.Release|x86.Build.0 = Release|x86 + {39B43BBB-BAFC-4D85-9BEA-3BCB7EFED89C}.Release|Win32.ActiveCfg = Release|Any CPU + {39B43BBB-BAFC-4D85-9BEA-3BCB7EFED89C}.Release|x64.ActiveCfg = Release|Any CPU {5ADCFD6D-BFEA-4B10-BB45-9083BBB56AF4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {5ADCFD6D-BFEA-4B10-BB45-9083BBB56AF4}.Debug|Any CPU.Build.0 = Debug|Any CPU - {5ADCFD6D-BFEA-4B10-BB45-9083BBB56AF4}.Debug|Mixed Platforms.ActiveCfg = Debug|x64 - {5ADCFD6D-BFEA-4B10-BB45-9083BBB56AF4}.Debug|Mixed Platforms.Build.0 = Debug|x64 - {5ADCFD6D-BFEA-4B10-BB45-9083BBB56AF4}.Debug|Win32.ActiveCfg = Debug|x64 - {5ADCFD6D-BFEA-4B10-BB45-9083BBB56AF4}.Debug|x64.ActiveCfg = Debug|x64 - {5ADCFD6D-BFEA-4B10-BB45-9083BBB56AF4}.Debug|x64.Build.0 = Debug|x64 - {5ADCFD6D-BFEA-4B10-BB45-9083BBB56AF4}.Debug|x86.ActiveCfg = Debug|Any CPU - {5ADCFD6D-BFEA-4B10-BB45-9083BBB56AF4}.Debug|x86.Build.0 = Debug|Any CPU + {5ADCFD6D-BFEA-4B10-BB45-9083BBB56AF4}.Debug|Win32.ActiveCfg = Debug|Any CPU + {5ADCFD6D-BFEA-4B10-BB45-9083BBB56AF4}.Debug|x64.ActiveCfg = Debug|Any CPU + {5ADCFD6D-BFEA-4B10-BB45-9083BBB56AF4}.Debug|x64.Build.0 = Debug|Any CPU {5ADCFD6D-BFEA-4B10-BB45-9083BBB56AF4}.Release|Any CPU.ActiveCfg = Release|Any CPU {5ADCFD6D-BFEA-4B10-BB45-9083BBB56AF4}.Release|Any CPU.Build.0 = Release|Any CPU - {5ADCFD6D-BFEA-4B10-BB45-9083BBB56AF4}.Release|Mixed Platforms.ActiveCfg = Release|x64 - {5ADCFD6D-BFEA-4B10-BB45-9083BBB56AF4}.Release|Mixed Platforms.Build.0 = Release|x64 - {5ADCFD6D-BFEA-4B10-BB45-9083BBB56AF4}.Release|Win32.ActiveCfg = Release|x64 - {5ADCFD6D-BFEA-4B10-BB45-9083BBB56AF4}.Release|x64.ActiveCfg = Release|x64 - {5ADCFD6D-BFEA-4B10-BB45-9083BBB56AF4}.Release|x64.Build.0 = Release|x64 - {5ADCFD6D-BFEA-4B10-BB45-9083BBB56AF4}.Release|x86.ActiveCfg = Release|Any CPU - {5ADCFD6D-BFEA-4B10-BB45-9083BBB56AF4}.Release|x86.Build.0 = Release|Any CPU + {5ADCFD6D-BFEA-4B10-BB45-9083BBB56AF4}.Release|Win32.ActiveCfg = Release|Any CPU + {5ADCFD6D-BFEA-4B10-BB45-9083BBB56AF4}.Release|x64.ActiveCfg = Release|Any CPU {B3DF599C-1C8F-451D-91E4-DD766210DA1F}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {B3DF599C-1C8F-451D-91E4-DD766210DA1F}.Debug|Mixed Platforms.ActiveCfg = Debug|x64 - {B3DF599C-1C8F-451D-91E4-DD766210DA1F}.Debug|Mixed Platforms.Build.0 = Debug|x64 {B3DF599C-1C8F-451D-91E4-DD766210DA1F}.Debug|Win32.ActiveCfg = Debug|Win32 {B3DF599C-1C8F-451D-91E4-DD766210DA1F}.Debug|Win32.Build.0 = Debug|Win32 {B3DF599C-1C8F-451D-91E4-DD766210DA1F}.Debug|x64.ActiveCfg = Debug|x64 {B3DF599C-1C8F-451D-91E4-DD766210DA1F}.Debug|x64.Build.0 = Debug|x64 - {B3DF599C-1C8F-451D-91E4-DD766210DA1F}.Debug|x86.ActiveCfg = Debug|Win32 - {B3DF599C-1C8F-451D-91E4-DD766210DA1F}.Debug|x86.Build.0 = Debug|Win32 {B3DF599C-1C8F-451D-91E4-DD766210DA1F}.Release|Any CPU.ActiveCfg = Release|Win32 - {B3DF599C-1C8F-451D-91E4-DD766210DA1F}.Release|Mixed Platforms.ActiveCfg = Release|x64 - {B3DF599C-1C8F-451D-91E4-DD766210DA1F}.Release|Mixed Platforms.Build.0 = Release|x64 {B3DF599C-1C8F-451D-91E4-DD766210DA1F}.Release|Win32.ActiveCfg = Release|Win32 {B3DF599C-1C8F-451D-91E4-DD766210DA1F}.Release|Win32.Build.0 = Release|Win32 {B3DF599C-1C8F-451D-91E4-DD766210DA1F}.Release|x64.ActiveCfg = Release|x64 {B3DF599C-1C8F-451D-91E4-DD766210DA1F}.Release|x64.Build.0 = Release|x64 - {B3DF599C-1C8F-451D-91E4-DD766210DA1F}.Release|x86.ActiveCfg = Release|Win32 - {B3DF599C-1C8F-451D-91E4-DD766210DA1F}.Release|x86.Build.0 = Release|Win32 {1D1E99BC-6D22-41C0-BD94-FF4DD5EC725B}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {1D1E99BC-6D22-41C0-BD94-FF4DD5EC725B}.Debug|Mixed Platforms.ActiveCfg = Debug|x64 - {1D1E99BC-6D22-41C0-BD94-FF4DD5EC725B}.Debug|Mixed Platforms.Build.0 = Debug|x64 {1D1E99BC-6D22-41C0-BD94-FF4DD5EC725B}.Debug|Win32.ActiveCfg = Debug|Win32 {1D1E99BC-6D22-41C0-BD94-FF4DD5EC725B}.Debug|Win32.Build.0 = Debug|Win32 {1D1E99BC-6D22-41C0-BD94-FF4DD5EC725B}.Debug|x64.ActiveCfg = Debug|x64 {1D1E99BC-6D22-41C0-BD94-FF4DD5EC725B}.Debug|x64.Build.0 = Debug|x64 - {1D1E99BC-6D22-41C0-BD94-FF4DD5EC725B}.Debug|x86.ActiveCfg = Debug|Win32 - {1D1E99BC-6D22-41C0-BD94-FF4DD5EC725B}.Debug|x86.Build.0 = Debug|Win32 {1D1E99BC-6D22-41C0-BD94-FF4DD5EC725B}.Release|Any CPU.ActiveCfg = Release|Win32 - {1D1E99BC-6D22-41C0-BD94-FF4DD5EC725B}.Release|Mixed Platforms.ActiveCfg = Release|x64 - {1D1E99BC-6D22-41C0-BD94-FF4DD5EC725B}.Release|Mixed Platforms.Build.0 = Release|x64 {1D1E99BC-6D22-41C0-BD94-FF4DD5EC725B}.Release|Win32.ActiveCfg = Release|Win32 {1D1E99BC-6D22-41C0-BD94-FF4DD5EC725B}.Release|Win32.Build.0 = Release|Win32 {1D1E99BC-6D22-41C0-BD94-FF4DD5EC725B}.Release|x64.ActiveCfg = Release|x64 {1D1E99BC-6D22-41C0-BD94-FF4DD5EC725B}.Release|x64.Build.0 = Release|x64 - {1D1E99BC-6D22-41C0-BD94-FF4DD5EC725B}.Release|x86.ActiveCfg = Release|Win32 - {1D1E99BC-6D22-41C0-BD94-FF4DD5EC725B}.Release|x86.Build.0 = Release|Win32 {115CC5B0-0385-41CD-8A23-6A7EA4C51926}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {115CC5B0-0385-41CD-8A23-6A7EA4C51926}.Debug|Any CPU.Build.0 = Debug|Any CPU - {115CC5B0-0385-41CD-8A23-6A7EA4C51926}.Debug|Mixed Platforms.ActiveCfg = Debug|x64 - {115CC5B0-0385-41CD-8A23-6A7EA4C51926}.Debug|Mixed Platforms.Build.0 = Debug|x64 - {115CC5B0-0385-41CD-8A23-6A7EA4C51926}.Debug|Win32.ActiveCfg = Debug|x64 + {115CC5B0-0385-41CD-8A23-6A7EA4C51926}.Debug|Win32.ActiveCfg = Debug|Any CPU {115CC5B0-0385-41CD-8A23-6A7EA4C51926}.Debug|x64.ActiveCfg = Debug|x64 {115CC5B0-0385-41CD-8A23-6A7EA4C51926}.Debug|x64.Build.0 = Debug|x64 - {115CC5B0-0385-41CD-8A23-6A7EA4C51926}.Debug|x86.ActiveCfg = Debug|x86 - {115CC5B0-0385-41CD-8A23-6A7EA4C51926}.Debug|x86.Build.0 = Debug|x86 {115CC5B0-0385-41CD-8A23-6A7EA4C51926}.Release|Any CPU.ActiveCfg = Release|Any CPU {115CC5B0-0385-41CD-8A23-6A7EA4C51926}.Release|Any CPU.Build.0 = Release|Any CPU - {115CC5B0-0385-41CD-8A23-6A7EA4C51926}.Release|Mixed Platforms.ActiveCfg = Release|x64 - {115CC5B0-0385-41CD-8A23-6A7EA4C51926}.Release|Mixed Platforms.Build.0 = Release|x64 - {115CC5B0-0385-41CD-8A23-6A7EA4C51926}.Release|Win32.ActiveCfg = Release|x64 - {115CC5B0-0385-41CD-8A23-6A7EA4C51926}.Release|x64.ActiveCfg = Release|x64 - {115CC5B0-0385-41CD-8A23-6A7EA4C51926}.Release|x64.Build.0 = Release|x64 - {115CC5B0-0385-41CD-8A23-6A7EA4C51926}.Release|x86.ActiveCfg = Release|x86 - {115CC5B0-0385-41CD-8A23-6A7EA4C51926}.Release|x86.Build.0 = Release|x86 + {115CC5B0-0385-41CD-8A23-6A7EA4C51926}.Release|Win32.ActiveCfg = Release|Any CPU + {115CC5B0-0385-41CD-8A23-6A7EA4C51926}.Release|x64.ActiveCfg = Release|Any CPU {4CC18776-125E-4318-9D24-D60110AD9697}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {4CC18776-125E-4318-9D24-D60110AD9697}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4CC18776-125E-4318-9D24-D60110AD9697}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {4CC18776-125E-4318-9D24-D60110AD9697}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU {4CC18776-125E-4318-9D24-D60110AD9697}.Debug|Win32.ActiveCfg = Debug|Any CPU {4CC18776-125E-4318-9D24-D60110AD9697}.Debug|x64.ActiveCfg = Debug|Any CPU {4CC18776-125E-4318-9D24-D60110AD9697}.Debug|x64.Build.0 = Debug|Any CPU - {4CC18776-125E-4318-9D24-D60110AD9697}.Debug|x86.ActiveCfg = Debug|Any CPU - {4CC18776-125E-4318-9D24-D60110AD9697}.Debug|x86.Build.0 = Debug|Any CPU {4CC18776-125E-4318-9D24-D60110AD9697}.Release|Any CPU.ActiveCfg = Release|Any CPU {4CC18776-125E-4318-9D24-D60110AD9697}.Release|Any CPU.Build.0 = Release|Any CPU - {4CC18776-125E-4318-9D24-D60110AD9697}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {4CC18776-125E-4318-9D24-D60110AD9697}.Release|Mixed Platforms.Build.0 = Release|Any CPU {4CC18776-125E-4318-9D24-D60110AD9697}.Release|Win32.ActiveCfg = Release|Any CPU {4CC18776-125E-4318-9D24-D60110AD9697}.Release|x64.ActiveCfg = Release|Any CPU - {4CC18776-125E-4318-9D24-D60110AD9697}.Release|x64.Build.0 = Release|Any CPU - {4CC18776-125E-4318-9D24-D60110AD9697}.Release|x86.ActiveCfg = Release|Any CPU - {4CC18776-125E-4318-9D24-D60110AD9697}.Release|x86.Build.0 = Release|Any CPU {CA4D64E6-6544-4A29-8BA5-7DB08D50D072}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {CA4D64E6-6544-4A29-8BA5-7DB08D50D072}.Debug|Any CPU.Build.0 = Debug|Any CPU - {CA4D64E6-6544-4A29-8BA5-7DB08D50D072}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {CA4D64E6-6544-4A29-8BA5-7DB08D50D072}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU {CA4D64E6-6544-4A29-8BA5-7DB08D50D072}.Debug|Win32.ActiveCfg = Debug|Any CPU {CA4D64E6-6544-4A29-8BA5-7DB08D50D072}.Debug|x64.ActiveCfg = Debug|Any CPU - {CA4D64E6-6544-4A29-8BA5-7DB08D50D072}.Debug|x64.Build.0 = Debug|Any CPU - {CA4D64E6-6544-4A29-8BA5-7DB08D50D072}.Debug|x86.ActiveCfg = Debug|Any CPU - {CA4D64E6-6544-4A29-8BA5-7DB08D50D072}.Debug|x86.Build.0 = Debug|Any CPU {CA4D64E6-6544-4A29-8BA5-7DB08D50D072}.Release|Any CPU.ActiveCfg = Release|Any CPU {CA4D64E6-6544-4A29-8BA5-7DB08D50D072}.Release|Any CPU.Build.0 = Release|Any CPU - {CA4D64E6-6544-4A29-8BA5-7DB08D50D072}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {CA4D64E6-6544-4A29-8BA5-7DB08D50D072}.Release|Mixed Platforms.Build.0 = Release|Any CPU {CA4D64E6-6544-4A29-8BA5-7DB08D50D072}.Release|Win32.ActiveCfg = Release|Any CPU {CA4D64E6-6544-4A29-8BA5-7DB08D50D072}.Release|x64.ActiveCfg = Release|Any CPU - {CA4D64E6-6544-4A29-8BA5-7DB08D50D072}.Release|x64.Build.0 = Release|Any CPU - {CA4D64E6-6544-4A29-8BA5-7DB08D50D072}.Release|x86.ActiveCfg = Release|Any CPU - {CA4D64E6-6544-4A29-8BA5-7DB08D50D072}.Release|x86.Build.0 = Release|Any CPU {082D6B9E-326E-4D15-9798-EDAE9EDE70A6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {082D6B9E-326E-4D15-9798-EDAE9EDE70A6}.Debug|Any CPU.Build.0 = Debug|Any CPU - {082D6B9E-326E-4D15-9798-EDAE9EDE70A6}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {082D6B9E-326E-4D15-9798-EDAE9EDE70A6}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU {082D6B9E-326E-4D15-9798-EDAE9EDE70A6}.Debug|Win32.ActiveCfg = Debug|Any CPU {082D6B9E-326E-4D15-9798-EDAE9EDE70A6}.Debug|x64.ActiveCfg = Debug|Any CPU {082D6B9E-326E-4D15-9798-EDAE9EDE70A6}.Debug|x64.Build.0 = Debug|Any CPU - {082D6B9E-326E-4D15-9798-EDAE9EDE70A6}.Debug|x86.ActiveCfg = Debug|Any CPU - {082D6B9E-326E-4D15-9798-EDAE9EDE70A6}.Debug|x86.Build.0 = Debug|Any CPU {082D6B9E-326E-4D15-9798-EDAE9EDE70A6}.Release|Any CPU.ActiveCfg = Release|Any CPU {082D6B9E-326E-4D15-9798-EDAE9EDE70A6}.Release|Any CPU.Build.0 = Release|Any CPU - {082D6B9E-326E-4D15-9798-EDAE9EDE70A6}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {082D6B9E-326E-4D15-9798-EDAE9EDE70A6}.Release|Mixed Platforms.Build.0 = Release|Any CPU {082D6B9E-326E-4D15-9798-EDAE9EDE70A6}.Release|Win32.ActiveCfg = Release|Any CPU {082D6B9E-326E-4D15-9798-EDAE9EDE70A6}.Release|x64.ActiveCfg = Release|Any CPU - {082D6B9E-326E-4D15-9798-EDAE9EDE70A6}.Release|x64.Build.0 = Release|Any CPU - {082D6B9E-326E-4D15-9798-EDAE9EDE70A6}.Release|x86.ActiveCfg = Release|Any CPU - {082D6B9E-326E-4D15-9798-EDAE9EDE70A6}.Release|x86.Build.0 = Release|Any CPU {F53335A2-C013-4354-98CC-83E612EAEB60}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {F53335A2-C013-4354-98CC-83E612EAEB60}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {F53335A2-C013-4354-98CC-83E612EAEB60}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {F53335A2-C013-4354-98CC-83E612EAEB60}.Debug|Win32.ActiveCfg = Debug|Win32 - {F53335A2-C013-4354-98CC-83E612EAEB60}.Debug|Win32.Build.0 = Debug|Win32 {F53335A2-C013-4354-98CC-83E612EAEB60}.Debug|x64.ActiveCfg = Debug|x64 - {F53335A2-C013-4354-98CC-83E612EAEB60}.Debug|x86.ActiveCfg = Debug|x64 {F53335A2-C013-4354-98CC-83E612EAEB60}.Release|Any CPU.ActiveCfg = Release|Win32 - {F53335A2-C013-4354-98CC-83E612EAEB60}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {F53335A2-C013-4354-98CC-83E612EAEB60}.Release|Mixed Platforms.Build.0 = Release|Win32 {F53335A2-C013-4354-98CC-83E612EAEB60}.Release|Win32.ActiveCfg = Release|Win32 - {F53335A2-C013-4354-98CC-83E612EAEB60}.Release|Win32.Build.0 = Release|Win32 {F53335A2-C013-4354-98CC-83E612EAEB60}.Release|x64.ActiveCfg = Release|x64 - {F53335A2-C013-4354-98CC-83E612EAEB60}.Release|x64.Build.0 = Release|x64 - {F53335A2-C013-4354-98CC-83E612EAEB60}.Release|x86.ActiveCfg = Release|Win32 {2379BAAF-A406-4477-BF53-2D6A326C24C8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {2379BAAF-A406-4477-BF53-2D6A326C24C8}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2379BAAF-A406-4477-BF53-2D6A326C24C8}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {2379BAAF-A406-4477-BF53-2D6A326C24C8}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU {2379BAAF-A406-4477-BF53-2D6A326C24C8}.Debug|Win32.ActiveCfg = Debug|Any CPU {2379BAAF-A406-4477-BF53-2D6A326C24C8}.Debug|x64.ActiveCfg = Debug|Any CPU {2379BAAF-A406-4477-BF53-2D6A326C24C8}.Debug|x64.Build.0 = Debug|Any CPU - {2379BAAF-A406-4477-BF53-2D6A326C24C8}.Debug|x86.ActiveCfg = Debug|x86 - {2379BAAF-A406-4477-BF53-2D6A326C24C8}.Debug|x86.Build.0 = Debug|x86 {2379BAAF-A406-4477-BF53-2D6A326C24C8}.Release|Any CPU.ActiveCfg = Release|Any CPU {2379BAAF-A406-4477-BF53-2D6A326C24C8}.Release|Any CPU.Build.0 = Release|Any CPU - {2379BAAF-A406-4477-BF53-2D6A326C24C8}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {2379BAAF-A406-4477-BF53-2D6A326C24C8}.Release|Mixed Platforms.Build.0 = Release|Any CPU {2379BAAF-A406-4477-BF53-2D6A326C24C8}.Release|Win32.ActiveCfg = Release|Any CPU {2379BAAF-A406-4477-BF53-2D6A326C24C8}.Release|x64.ActiveCfg = Release|Any CPU - {2379BAAF-A406-4477-BF53-2D6A326C24C8}.Release|x64.Build.0 = Release|Any CPU - {2379BAAF-A406-4477-BF53-2D6A326C24C8}.Release|x86.ActiveCfg = Release|x86 - {2379BAAF-A406-4477-BF53-2D6A326C24C8}.Release|x86.Build.0 = Release|x86 {8E6E1763-39AE-491D-A10F-44C8844ABA5B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {8E6E1763-39AE-491D-A10F-44C8844ABA5B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8E6E1763-39AE-491D-A10F-44C8844ABA5B}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {8E6E1763-39AE-491D-A10F-44C8844ABA5B}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU {8E6E1763-39AE-491D-A10F-44C8844ABA5B}.Debug|Win32.ActiveCfg = Debug|Any CPU {8E6E1763-39AE-491D-A10F-44C8844ABA5B}.Debug|x64.ActiveCfg = Debug|Any CPU - {8E6E1763-39AE-491D-A10F-44C8844ABA5B}.Debug|x64.Build.0 = Debug|Any CPU - {8E6E1763-39AE-491D-A10F-44C8844ABA5B}.Debug|x86.ActiveCfg = Debug|Any CPU {8E6E1763-39AE-491D-A10F-44C8844ABA5B}.Release|Any CPU.ActiveCfg = Release|Any CPU {8E6E1763-39AE-491D-A10F-44C8844ABA5B}.Release|Any CPU.Build.0 = Release|Any CPU - {8E6E1763-39AE-491D-A10F-44C8844ABA5B}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {8E6E1763-39AE-491D-A10F-44C8844ABA5B}.Release|Mixed Platforms.Build.0 = Release|Any CPU {8E6E1763-39AE-491D-A10F-44C8844ABA5B}.Release|Win32.ActiveCfg = Release|Any CPU {8E6E1763-39AE-491D-A10F-44C8844ABA5B}.Release|x64.ActiveCfg = Release|Any CPU - {8E6E1763-39AE-491D-A10F-44C8844ABA5B}.Release|x64.Build.0 = Release|Any CPU - {8E6E1763-39AE-491D-A10F-44C8844ABA5B}.Release|x86.ActiveCfg = Release|Any CPU + {DFE50673-906C-4B8F-993B-A24CAD1CA17D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DFE50673-906C-4B8F-993B-A24CAD1CA17D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DFE50673-906C-4B8F-993B-A24CAD1CA17D}.Debug|Win32.ActiveCfg = Debug|Any CPU + {DFE50673-906C-4B8F-993B-A24CAD1CA17D}.Debug|x64.ActiveCfg = Debug|Any CPU + {DFE50673-906C-4B8F-993B-A24CAD1CA17D}.Debug|x64.Build.0 = Debug|Any CPU + {DFE50673-906C-4B8F-993B-A24CAD1CA17D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DFE50673-906C-4B8F-993B-A24CAD1CA17D}.Release|Any CPU.Build.0 = Release|Any CPU + {DFE50673-906C-4B8F-993B-A24CAD1CA17D}.Release|Win32.ActiveCfg = Release|Any CPU + {DFE50673-906C-4B8F-993B-A24CAD1CA17D}.Release|x64.ActiveCfg = Release|Any CPU + {1FCA8834-34E6-47CF-B53F-D8DF49F0819E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1FCA8834-34E6-47CF-B53F-D8DF49F0819E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1FCA8834-34E6-47CF-B53F-D8DF49F0819E}.Debug|Win32.ActiveCfg = Debug|Any CPU + {1FCA8834-34E6-47CF-B53F-D8DF49F0819E}.Debug|x64.ActiveCfg = Debug|Any CPU + {1FCA8834-34E6-47CF-B53F-D8DF49F0819E}.Debug|x64.Build.0 = Debug|Any CPU + {1FCA8834-34E6-47CF-B53F-D8DF49F0819E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1FCA8834-34E6-47CF-B53F-D8DF49F0819E}.Release|Any CPU.Build.0 = Release|Any CPU + {1FCA8834-34E6-47CF-B53F-D8DF49F0819E}.Release|Win32.ActiveCfg = Release|Any CPU + {1FCA8834-34E6-47CF-B53F-D8DF49F0819E}.Release|x64.ActiveCfg = Release|Any CPU + {DDE1EA77-637C-4D5F-96F3-1328BC45CE80}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DDE1EA77-637C-4D5F-96F3-1328BC45CE80}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DDE1EA77-637C-4D5F-96F3-1328BC45CE80}.Debug|Win32.ActiveCfg = Debug|Any CPU + {DDE1EA77-637C-4D5F-96F3-1328BC45CE80}.Debug|x64.ActiveCfg = Debug|Any CPU + {DDE1EA77-637C-4D5F-96F3-1328BC45CE80}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DDE1EA77-637C-4D5F-96F3-1328BC45CE80}.Release|Any CPU.Build.0 = Release|Any CPU + {DDE1EA77-637C-4D5F-96F3-1328BC45CE80}.Release|Win32.ActiveCfg = Release|Any CPU + {DDE1EA77-637C-4D5F-96F3-1328BC45CE80}.Release|x64.ActiveCfg = Release|Any CPU + {FC4BCF9B-F4C7-41AD-8A16-2A90A082954A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FC4BCF9B-F4C7-41AD-8A16-2A90A082954A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FC4BCF9B-F4C7-41AD-8A16-2A90A082954A}.Debug|Win32.ActiveCfg = Debug|Any CPU + {FC4BCF9B-F4C7-41AD-8A16-2A90A082954A}.Debug|x64.ActiveCfg = Debug|Any CPU + {FC4BCF9B-F4C7-41AD-8A16-2A90A082954A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FC4BCF9B-F4C7-41AD-8A16-2A90A082954A}.Release|Any CPU.Build.0 = Release|Any CPU + {FC4BCF9B-F4C7-41AD-8A16-2A90A082954A}.Release|Win32.ActiveCfg = Release|Any CPU + {FC4BCF9B-F4C7-41AD-8A16-2A90A082954A}.Release|x64.ActiveCfg = Release|Any CPU + {04945FB2-8410-4F14-8262-2ED18DCDACD6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {04945FB2-8410-4F14-8262-2ED18DCDACD6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {04945FB2-8410-4F14-8262-2ED18DCDACD6}.Debug|Win32.ActiveCfg = Debug|Any CPU + {04945FB2-8410-4F14-8262-2ED18DCDACD6}.Debug|x64.ActiveCfg = Debug|Any CPU + {04945FB2-8410-4F14-8262-2ED18DCDACD6}.Debug|x64.Build.0 = Debug|Any CPU + {04945FB2-8410-4F14-8262-2ED18DCDACD6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {04945FB2-8410-4F14-8262-2ED18DCDACD6}.Release|Any CPU.Build.0 = Release|Any CPU + {04945FB2-8410-4F14-8262-2ED18DCDACD6}.Release|Win32.ActiveCfg = Release|Any CPU + {04945FB2-8410-4F14-8262-2ED18DCDACD6}.Release|x64.ActiveCfg = Release|Any CPU + {A430AD28-B76A-4ED0-AF7D-D13B8969297F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A430AD28-B76A-4ED0-AF7D-D13B8969297F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A430AD28-B76A-4ED0-AF7D-D13B8969297F}.Debug|Win32.ActiveCfg = Debug|Any CPU + {A430AD28-B76A-4ED0-AF7D-D13B8969297F}.Debug|x64.ActiveCfg = Debug|Any CPU + {A430AD28-B76A-4ED0-AF7D-D13B8969297F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A430AD28-B76A-4ED0-AF7D-D13B8969297F}.Release|Any CPU.Build.0 = Release|Any CPU + {A430AD28-B76A-4ED0-AF7D-D13B8969297F}.Release|Win32.ActiveCfg = Release|Any CPU + {A430AD28-B76A-4ED0-AF7D-D13B8969297F}.Release|x64.ActiveCfg = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution - {9AE965C4-301E-4C01-B90F-297AF341ACC6} = {85F88959-C9E9-4989-ACB1-67BA9D1BEFE7} - {CC2E74B6-534A-43D8-9F16-AC03FE955000} = {85F88959-C9E9-4989-ACB1-67BA9D1BEFE7} - {E70FA90A-7012-4A52-86B5-362B699D1540} = {85F88959-C9E9-4989-ACB1-67BA9D1BEFE7} {F2EC7193-D5E5-4252-9803-5CEB407E910F} = {85F88959-C9E9-4989-ACB1-67BA9D1BEFE7} {8A0426FA-0BC2-4C49-A6E5-1F9A68156F19} = {85F88959-C9E9-4989-ACB1-67BA9D1BEFE7} - {1D1E99BC-6D22-41C0-BD94-FF4DD5EC725B} = {85F88959-C9E9-4989-ACB1-67BA9D1BEFE7} {082D6B9E-326E-4D15-9798-EDAE9EDE70A6} = {85F88959-C9E9-4989-ACB1-67BA9D1BEFE7} + {DFE50673-906C-4B8F-993B-A24CAD1CA17D} = {85F88959-C9E9-4989-ACB1-67BA9D1BEFE7} + {DDE1EA77-637C-4D5F-96F3-1328BC45CE80} = {85F88959-C9E9-4989-ACB1-67BA9D1BEFE7} + {39A17A65-E893-44B8-A312-DDCDD990D9D1} = {85F88959-C9E9-4989-ACB1-67BA9D1BEFE7} {0B9C97D4-61B8-4294-A1DF-BA90752A1779} = {8B179853-B7D6-479C-B8B2-6CBCE835D040} {4CEFBC84-C215-11DB-8314-0800200C9A66} = {8B179853-B7D6-479C-B8B2-6CBCE835D040} {5CCCB9CF-0384-458F-BA08-72B73866840F} = {8B179853-B7D6-479C-B8B2-6CBCE835D040} @@ -735,8 +496,14 @@ Global {115CC5B0-0385-41CD-8A23-6A7EA4C51926} = {4B59E09C-A51F-4B80-91BE-987904DCEF7D} {2379BAAF-A406-4477-BF53-2D6A326C24C8} = {4B59E09C-A51F-4B80-91BE-987904DCEF7D} {8E6E1763-39AE-491D-A10F-44C8844ABA5B} = {4B59E09C-A51F-4B80-91BE-987904DCEF7D} + {1FCA8834-34E6-47CF-B53F-D8DF49F0819E} = {4B59E09C-A51F-4B80-91BE-987904DCEF7D} + {FC4BCF9B-F4C7-41AD-8A16-2A90A082954A} = {4B59E09C-A51F-4B80-91BE-987904DCEF7D} {B75FA7AD-968E-4990-B342-1B4B17C850DF} = {B36BE134-D85A-437E-AB61-2DA1CCDE06C1} {F2DFEB00-BB35-4665-85EA-CB8C7729A6B7} = {B36BE134-D85A-437E-AB61-2DA1CCDE06C1} {A05B6AA6-0EC3-495D-BCC4-ECE1210071A8} = {B36BE134-D85A-437E-AB61-2DA1CCDE06C1} + {9AE965C4-301E-4C01-B90F-297AF341ACC6} = {39A17A65-E893-44B8-A312-DDCDD990D9D1} + {E70FA90A-7012-4A52-86B5-362B699D1540} = {39A17A65-E893-44B8-A312-DDCDD990D9D1} + {1D1E99BC-6D22-41C0-BD94-FF4DD5EC725B} = {39A17A65-E893-44B8-A312-DDCDD990D9D1} + {CC2E74B6-534A-43D8-9F16-AC03FE955000} = {39A17A65-E893-44B8-A312-DDCDD990D9D1} EndGlobalSection EndGlobal diff --git a/CUETools/app.config b/CUETools/app.config index 3201f86..c8d467d 100644 --- a/CUETools/app.config +++ b/CUETools/app.config @@ -1,3 +1,8 @@ + + + + + \ No newline at end of file diff --git a/CUETools/cue2.ico b/CUETools/cue2.ico new file mode 100644 index 0000000000000000000000000000000000000000..5212447b33693b6dff89d912ee0dbb3cc3260a61 GIT binary patch literal 23558 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 Choices { set { - foreach(object i in value) - { - ListViewItem item = ToItem(i); - listChoices.Items.Add(item); - } + if (CUE != null) + AddItem(CUE); + foreach (object i in value) + AddItem(i); if (CUE != null) { - string text = String.Format("{0}: {1} - {2}", - CUE.Year == "" ? "YYYY" : CUE.Year, - CUE.Artist == "" ? "Unknown Artist" : CUE.Artist, - CUE.Title == "" ? "Unknown Title" : CUE.Title); - ListViewItem item = new ListViewItem(text, 3); - item.Tag = CUE; - listChoices.Items.Insert(0, item); textBox1.Hide(); listTracks.Show(); - btnEdit.Show(); + listMetadata.Show(); + tableLayoutPanel1.SetRowSpan(listChoices, 2); + tableLayoutPanel1.PerformLayout(); + } + else + { + listTracks.Hide(); + tableLayoutPanel1.SetRowSpan(textBox1, 3); + //tableLayoutPanel1.RowStyles[2].Height = 0; + //tableLayoutPanel1.RowStyles[3].Height = 0; + tableLayoutPanel1.PerformLayout(); } if (listChoices.Items.Count > 0) listChoices.Items[0].Selected = true; @@ -99,12 +121,29 @@ namespace JDP } } + private ReleaseInfo ChosenRelease + { + get + { + object o = ChosenObject; + return o != null && o is ReleaseInfo ? o as ReleaseInfo : null; + } + } + + private ListViewItem ChosenItem + { + get + { + return listChoices.SelectedItems.Count > 0 ? listChoices.SelectedItems[0] : null; + } + } + private void frmChoice_FormClosing(object sender, FormClosingEventArgs e) { - object item = ChosenObject; - if (e.CloseReason != CloseReason.None || DialogResult != DialogResult.OK || item == null || !(item is ReleaseInfo)) + ReleaseInfo ri = ChosenRelease; + if (e.CloseReason != CloseReason.None || DialogResult != DialogResult.OK || ri == null || CUE == null) return; - (item as ReleaseInfo).FillCUE(); + CUE.CopyMetadata(ri.metadata); } private void AutoResizeTracks() @@ -123,84 +162,37 @@ namespace JDP if (item != null && item is CUEToolsSourceFile) { textBox1.Text = (item as CUEToolsSourceFile).contents.Replace("\r\n", "\n").Replace("\r", "\n").Replace("\n", "\r\n"); - chkFixEncoding.Visible = false; } else if (item != null && item is ReleaseInfo) { ReleaseInfo r = (item as ReleaseInfo); listTracks.Items.Clear(); - if (r.musicbrainz != null) - foreach (MusicBrainz.Track track in r.musicbrainz.GetTracks()) - { - listTracks.Items.Add(new ListViewItem(new string[] { - track.GetTitle(), - (listTracks.Items.Count + 1).ToString(), - CUE == null ? "" : CUE.TOC[listTracks.Items.Count + CUE.TOC.FirstAudio].StartMSF, - CUE == null ? "" : CUE.TOC[listTracks.Items.Count + CUE.TOC.FirstAudio].LengthMSF - })); - } - if (r.freedb != null) - for (int i = 0; i < r.freedb.Tracks.Count; i++) - { - listTracks.Items.Add(new ListViewItem(new string[] { - r.freedb.Tracks[i].Title, - (i + 1).ToString(), - CDImageLayout.TimeToString((uint)r.freedb.Tracks[i].FrameOffset - 150), - CDImageLayout.TimeToString((i + 1 < r.freedb.Tracks.Count) ? (uint) (r.freedb.Tracks[i + 1].FrameOffset - r.freedb.Tracks[i].FrameOffset) : - (CUE == null || i >= CUE.TOC.TrackCount) ? 0 : CUE.TOC[i + CUE.TOC.FirstAudio].Length) - })); - } - AutoResizeTracks(); - chkFixEncoding.Visible = r.freedb != null; - chkFixEncoding.Checked = r.freedb_latin1 != null; - } - else if (item != null && item is CUESheet) - { - CUESheet cueSheet = item as CUESheet; - listTracks.Items.Clear(); - foreach (TrackInfo track in cueSheet.Tracks) + foreach (TrackInfo track in r.metadata.Tracks) { listTracks.Items.Add(new ListViewItem(new string[] { - track.Title, + track.Title, (listTracks.Items.Count + 1).ToString(), - CUE == null ? "" : CUE.TOC[listTracks.Items.Count + 1].StartMSF, - CUE == null ? "" : CUE.TOC[listTracks.Items.Count + 1].LengthMSF + r.metadata.TOC[listTracks.Items.Count + r.metadata.TOC.FirstAudio].StartMSF, + r.metadata.TOC[listTracks.Items.Count + r.metadata.TOC.FirstAudio].LengthMSF })); } AutoResizeTracks(); - chkFixEncoding.Visible = false; + listMetadata.Items.Clear(); + listMetadata.Items.Add(new ListViewItem(new string[] { r.metadata.Artist, "Artist" })); + listMetadata.Items.Add(new ListViewItem(new string[] { r.metadata.Title, "Album" })); + listMetadata.Items.Add(new ListViewItem(new string[] { r.metadata.Year, "Date" })); + listMetadata.Items.Add(new ListViewItem(new string[] { r.metadata.Genre, "Genre" })); + listMetadata.Items.Add(new ListViewItem(new string[] { r.metadata.DiscNumber, "Disc Number" })); + listMetadata.Items.Add(new ListViewItem(new string[] { r.metadata.TotalDiscs, "Total Discs" })); } else { + listMetadata.Items.Clear(); listTracks.Items.Clear(); - chkFixEncoding.Visible = false; textBox1.Text = ""; } } - private void btnEdit_Click(object sender, EventArgs e) - { - object item = ChosenObject; - if (item == null || CUE == null) - return; - if (item is ReleaseInfo) - (item as ReleaseInfo).FillCUE(); - else if (!(item is CUESheet)) - return; - listChoices.Items[0].Selected = true; - listChoices.Items[0].Text = String.Format("{0}: {1} - {2}", - CUE.Year == "" ? "YYYY" : CUE.Year, - CUE.Artist == "" ? "Unknown Artist" : CUE.Artist, - CUE.Title == "" ? "Unknown Title" : CUE.Title); - frmProperties frm = new frmProperties(); - frm.CUE = CUE; - if (frm.ShowDialog(this) == DialogResult.OK) - listChoices.Items[0].Text = String.Format("{0}: {1} - {2}", - CUE.Year == "" ? "YYYY" : CUE.Year, - CUE.Artist == "" ? "Unknown Artist" : CUE.Artist, - CUE.Title == "" ? "Unknown Title" : CUE.Title); - } - private void listTracks_DoubleClick(object sender, EventArgs e) { listTracks.FocusedItem.BeginEdit(); @@ -214,8 +206,7 @@ namespace JDP private void listTracks_BeforeLabelEdit(object sender, LabelEditEventArgs e) { - object item = ChosenObject; - if (item == null || !(item is CUESheet)) + if (ChosenRelease == null) { e.CancelEdit = true; return; @@ -224,10 +215,9 @@ namespace JDP private void listTracks_AfterLabelEdit(object sender, LabelEditEventArgs e) { - if (e.Label != null) - { - CUE.Tracks[e.Item].Title = e.Label; - } + ReleaseInfo ri = ChosenRelease; + if (ri != null && e.Label != null) + ri.metadata.Tracks[e.Item].Title = e.Label; } private void listTracks_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e) @@ -244,51 +234,70 @@ namespace JDP } } - private void chkFixEncoding_CheckedChanged(object sender, EventArgs e) + private void listMetadata_DoubleClick(object sender, EventArgs e) { - if (listChoices.SelectedItems.Count > 0) + listMetadata.FocusedItem.BeginEdit(); + } + + private void listMetadata_KeyDown(object sender, KeyEventArgs e) + { + if (e.KeyCode == Keys.F2) + listMetadata.FocusedItem.BeginEdit(); + } + + private void listMetadata_AfterLabelEdit(object sender, LabelEditEventArgs e) + { + ListViewItem item = ChosenItem; + ReleaseInfo r = ChosenRelease; + if (e.Label != null && item != null && r != null) { - ListViewItem item = listChoices.Items[listChoices.SelectedItems[0].Index]; - if (item.Tag is ReleaseInfo) + switch (e.Item) { - ReleaseInfo r = item.Tag as ReleaseInfo; - if ((r.freedb_latin1 == null) == chkFixEncoding.Checked) - { - r.FixEncoding(); - item.Text = r.Text; - for (int i = 0; i < r.freedb.Tracks.Count; i++) - listTracks.Items[i].Text = r.freedb.Tracks[i].Title; - } + case 0: + foreach (TrackInfo track in r.metadata.Tracks) + if (track.Artist == r.metadata.Artist) + track.Artist = e.Label; + r.metadata.Artist = e.Label; + break; + case 1: r.metadata.Title = e.Label; break; + case 2: r.metadata.Year = e.Label; break; + case 3: r.metadata.Genre = e.Label; break; + case 4: r.metadata.DiscNumber = e.Label; break; + case 5: r.metadata.TotalDiscs = e.Label; break; } + item.Text = r.Text; } } } sealed class ReleaseInfo { - public Freedb.CDEntry freedb_latin1; - public Freedb.CDEntry freedb; - public MusicBrainz.Release musicbrainz; - public CUESheet CUE; - private Encoding iso; + public CUESheet metadata; + + public ReleaseInfo(CUESheet cue) + { + metadata = new CUESheet(cue.Config); + metadata.TOC = cue.TOC; + metadata.CopyMetadata(cue); + } public ReleaseInfo(CUESheet cue, Freedb.CDEntry release) { - CUE = cue; - iso = Encoding.GetEncoding("iso-8859-1"); - freedb_latin1 = null; - freedb = release; + metadata = new CUESheet(cue.Config); + metadata.TOC = cue.TocFromCDEntry(release); + metadata.FillFromFreedb(release); } public ReleaseInfo(CUESheet cue, MusicBrainz.Release release) { - CUE = cue; - iso = Encoding.GetEncoding("iso-8859-1"); - musicbrainz = release; + metadata = new CUESheet(cue.Config); + metadata.TOC = cue.TOC; + metadata.FillFromMusicBrainz(release); } private string FixEncoding(string src) { + Encoding iso = Encoding.GetEncoding("iso-8859-1"); return Encoding.Default.GetString(iso.GetBytes(src)); } @@ -296,44 +305,31 @@ namespace JDP { get { - if (musicbrainz != null) - return string.Format("{0}: {1} - {2}", - musicbrainz.GetEvents().Count > 0 ? musicbrainz.GetEvents()[0].Date.Substring(0, 4) : "YYYY", - musicbrainz.GetArtist(), - musicbrainz.GetTitle()); - if (freedb != null) - return string.Format("{0}: {1} - {2}", - freedb.Year, - freedb.Artist, - freedb.Title); - return null; + return string.Format("{0}: {1} - {2}", + metadata.Year == "" ? "YYYY" : metadata.Year, + metadata.Artist == "" ? "Unknown Artist" : metadata.Artist, + metadata.Title == "" ? "Unknown Title" : metadata.Title); } } public void FixEncoding() { - if (freedb == null) - return; - if (freedb_latin1 != null) + metadata.Artist = FixEncoding(metadata.Artist); + metadata.Title = FixEncoding(metadata.Title); + foreach (TrackInfo track in metadata.Tracks) { - freedb = freedb_latin1; - freedb_latin1 = null; - return; + track.Title = FixEncoding(track.Title); + track.Artist = FixEncoding(track.Artist); } - freedb_latin1 = freedb; - freedb = new Freedb.CDEntry(freedb_latin1); - freedb.Artist = FixEncoding(freedb.Artist); - freedb.Title = FixEncoding(freedb.Title); - foreach (Freedb.Track tr in freedb.Tracks) - tr.Title = FixEncoding(tr.Title); } - public void FillCUE() + public bool Equals(ReleaseInfo r) { - if (musicbrainz != null) - CUE.FillFromMusicBrainz(musicbrainz); - else if (freedb != null) - CUE.FillFromFreedb(freedb); + bool equal = metadata.Title == r.metadata.Title && metadata.Artist == r.metadata.Artist; + for (int t = 0; t < metadata.TrackCount; t++) + if (r.metadata.Tracks[t].Title != metadata.Tracks[t].Title || r.metadata.Tracks[t].Artist != metadata.Tracks[t].Artist) + equal = false; + return equal; } } } \ No newline at end of file diff --git a/CUETools/frmChoice.resx b/CUETools/frmChoice.resx index 1e4af5c..67b05c3 100644 --- a/CUETools/frmChoice.resx +++ b/CUETools/frmChoice.resx @@ -117,40 +117,47 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 488, 293 + + + Fill - - 75, 23 + + + 437, 3 + + + 105, 23 - - 23 + + 0 - + Ok - - button1 + + buttonOk - + System.Windows.Forms.Button, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - $this + + tableLayoutPanel2 - - 5 + + 0 520 + + Fill + - 12, 12 + 3, 3 - 551, 72 + 545, 77 17, 17 @@ -159,88 +166,87 @@ AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj0yLjAuMC4w LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0 - ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAADY + ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAACg EQAAAk1TRnQBSQFMAgEBBAEAAQwBAAEEAQABEAEAARABAAT/ASEBAAj/AUIBTQE2BwABNgMAASgDAAFA - AwABIAMAAQEBAAEgBgABIP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8ALgADAgEDAxQBHAMs - AUwDNAF5AzIBmgMwAaQDMgGaAzQBeQMsAUwDFAEcAwMBBAgAA5YB/wEyAgAB/wEyAgAB/wEyAgAB/wEy - AgAB/wEyAgAB/wEyAgAB/wEyAgAB/wEyAgAB/wEyAgAB/wEyAgAB/wEyAgAB/wEyAgAB/wEyAgAB/wEy - AgAB/wEyAgAB/wQAAWUBzAL/ATICmQH/ATICmQH/AWUBzAL/AWUBzAL/AWUBzAL/AWUBzAL/AWUBzAL/ - AWUBzAL/AWUBzAL/AWUBzAL/AWUBzAL/AWUBzAL/AWUBzAL/EAADAgEDAxQBHAMsAUwDNAF5AzIBmgMw - AaQDMgGaAzQBeQMsAUwDFAEcAwMBBBAAAwQBBgMjATYDRwGwAWMCXwHlAZECiQH7AbMCqQH/AZECjAH7 - AWECYAHrAzwB0wMuAawDNAGCAyUBPAMHAQkEAAHMApkB/wGAAgAB/wGAAgAB/wGAAgAB/wGAAgAB/wPq - Af8D6gH/A+oB/wGAAgAB/wPqAf8D6gH/A+oB/wGAAgAB/wGAAgAB/wFlAgAB/wEyAgAB/wEyApkB/wMA - Af8DKAH/A0wB/wMAAf8DGwH/AWUBzAL/AWUBzAL/AWUBzAL/AWUBzAL/AWUBzAL/AWUBzAL/AWUBzAL/ - AWUBzAL/AWUBzAL/AWUBzAL/CAADBAEGAyMBNgNHAbABYwJfAeUBkQKJAfsBswKpAf8BkQKMAfsBYQJg - AesDPAHTAy4BrAM0AYIDJQE8AwcBCQgAAwIBAwMxAU8BbQJnAeoBzwK0Av8C3QL/AuIC/wLoAv8C7gL/ - AvMB/wPPAf8DcgHzAzMBxgMzAZIDJQE8AwMBBAHMApkB/wGAAgAB/wGAAgAB/wGAAgAB/wPxAf8BgAIA - Af8BgAIAAf8D8QH/AYACAAH/A/EB/wGAAgAB/wGAAgAB/wPxAf8BgAIAAf8BgAIAAf8BMgIAAf8DAAH/ - A8wN/wNMAf8DGwH/AWUBzAL/AWUBzAL/AWUBzAL/AWUBzAL/AWUBzAL/AWUBzAL/AWUBzAL/AWUBzAL/ - AWUBzAL/BAADAgEDAzEBTwFtAmcB6gHPArQC/wLdAv8C4gL/AugC/wLuAv8C8wH/A88B/wNyAfMDMwHG - AzMBkgMlATwDAwEEBAADJwE4AYACdQH3AfUCxwL/AtIC/wLYAv8C3QL/AuIC/wLoAv8C9AX/A/UB/wOZ - AfsDMwHGAzQBggMUARwBzAKZAf8BmQEAATIB/wGAAgAB/wGAAgAF/wGAAgAB/wGAAgAF/wGAAgAF/wGA - AgAB/wGAAgAF/wGAAgAB/wGAAgAB/wEyAgAB/wMAAf8DzBH/AwAB/wFlAcwC/wFlAcwC/wFlAcwC/wFl - AcwC/wFlAcwC/wFlAcwC/wFlAcwC/wFlAcwC/wFlAcwC/wQAAycBOAGAAnUB9wH1AscC/wLSAv8C2AL/ - At0C/wLiAv8C6AL/AvQF/wP1Af8DmQH7AzMBxgM0AYIDFAEcAwcBCQFxAmsB3QH1As0C/wLPAv8CzQL/ - AtIC/wLYAv8C3QL/AuIC/wL6Cf8D9QH/A3IB8wMuAawDLAFMAcwCmQH/AZkBAAEyAf8BgAIAAf8BgAIA - Af8BgAIADf8BgAIADf8BgAIAAf8BgAIAAf8BgAIAAf8BMgIAAf8BMgKZAf8DGwH/A3YB/wPAAf8DwAH/ - A8wB/wMAAf8DKAH/AwAB/wMAAf8DAAH/AwAB/wMoAf8BZQHMAv8BZQHMAv8BZQHMAv8DBwEJAXECawHd - AfUCzQL/As8C/wLNAv8C0gL/AtgC/wLdAv8C4gL/AvoJ/wP1Af8DcgHzAy4BrAMsAUwDQwFqAcYCsQL/ - AtkC/wLUAv8CzwL/As0C/wHUAdsC/wHXAeIC/wHkAeoR/wHSAswB/wM8AdMDNAF3AcwCmQH/AZkBAAEy - Af8BgAIAAf8BgAIAAf8BgAIAAf8BgAIAAf8BgAIABf8BgAIABf8BgAIAAf8BgAIAAf8BgAIAAf8BgAIA - Af8BgAIAAf8BMgIAAf8BZQHMAv8BMgKZAf8DGwH/AwAB/wMABf8DAAH/AxsB/wGkAqAJ/wOZAf8DKAH/ - AygB/wFlAcwC/wFlAcwC/wNDAWoBxgKxAv8C2QL/AtQC/wLPAv8CzQL/AdQB2wL/AdcB4gL/AeQB6hH/ - AdICzAH/AzwB0wM0AXcDYwG2Af8C4wH/AQABLQEuAf8BAAEtAS4B/wEAAS0BLgL/Ad4B5wH/AQABLQEu - Av8B0QHzAf8BAAEtAS4C/wH4Av8BbQJzAf8BAAEtAS4B/wFtAnMB/wHMApkB/wFcAlUB6gMzAZQBzAKZ - Af8BmQEAATIB/wGAAgAB/wGAAgAB/wGAAgAB/wGAAgAB/wGAAgAF/wGAAgAF/wGAAgAB/wGAAgAB/wGA - AgAB/wGAAgAB/wGAAgAB/wEyAgAB/wFlAcwC/wFlAcwC/wFlAcwC/wFlAcwC/wMABf8DAAH/AygR/wPM - Af8DAAH/AWUBzAL/AWUBzAL/A2MBtgH/AuMB/wFtAnMB/wEAAS0BLgH/AW0CcwL/Ad4B5wH/AW0CcwH/ - AQABLQEuAf8BbQJzAv8B+AL/AQABLQEuAf8BAAEtAS4B/wEAAS0BLgH/AcwCmQH/AVwCVQHqAzMBlAGH - AoEB4gH/AucB/wEAAS0BLgL/At4C/wLgAv8B7wH8Af8BAAEtAS4C/wHiAfwB/wEAAS0BLgH/AfwB8AH5 - Af8BAAEtAS4B/wHMApkB/wEAAS0BLgH/AcwCmQH/AXoCbAH3AzEBoQHMApkB/wGZAQABMgH/AYACAAH/ - AYACAAH/AYACAAH/AYACAAH/AYACAAH/AYACAAH/AYACAAH/AYACAAH/AYACAAH/AYACAAH/AYACAAH/ - AYACAAH/AYACAAH/ATICAAH/AZkCZQH/AZkCZQH/AZkCZQH/AZkCZQH/AwAF/wMAAf8DAAH/A0wB/wPM - Df8DAAH/AZkCZQH/AZkCZQH/AYcCgQHiAf8C5wH/AQABLQEuAv8C3gH/AQABLQEuAv8B7wH8Af8BAAEt - AS4C/wHiAfwB/wEAAS0BLgH/AfwB8AH5Af8BAAEtAS4B/wHMApkB/wHMApkB/wHMApkB/wF6AmwB9wMx - AaEBngKMAf8B6QK+Af8BAAEtAS4B/wEAAS0BLgH/AfkC1gL/AekB8wH/AQABLQEuAf8BAAEtAS4B/wEA - AS0BLgH/AfkB6AHsAf8BAAEtAS4B/wHmAroB/wHmAr0B/wHmAsAB/wGmApQB/wMzAZQ0/wPxAf8D6gH/ - A4AB/wGZAmUB/wGZAmUB/wGZAmUB/wGZAmUB/wMABf8DAAH/A1QB/wMbAf8DAAH/AwAB/wMABf8DAAH/ - AZkCZQH/AZkCZQH/AZ4CjAH/AekCvgH/AQABLQEuAf8B8wLFAf8B+QLWAv8B6QHzAf8BAAEtAS4C/wHp - AfMB/wEAAS0BLgH/AfkB6AHsAf8BAAEtAS4B/wEAAS0BLgH/AeYCvQH/AeYCwAH/AaYClAH/AzMBlAF6 - Am8B0gHbAqgB/wEAAS0BLgH/AeoCtwH/AfMCzQL/Ae4B/AH/AQABLQEuAv8B0gH1Af8BAAEtAS4C/wH0 - AfwB/wEAAS0BLgL/AtgB/wEAAS0BLgL/AuIB/wGBAnwB9gM0AXcE/wGZAQABMgn/AYACAA3/AYACAAH/ - AYACAA3/AYACAAH/AYACAAH/A4AB/wGZAmUB/wGZAmUB/wGZAmUB/wGZAmUB/wMABf8DGwH/AwAB/wMo - Af8DVAH/A1QB/wMABf8DAAH/AZkCZQH/AZkCZQH/AXoCbwHSAdsCqAH/AQABLQEuAf8B6gK3Af8BAAEt - AS4C/wHuAfwB/wEAAS0BLgL/AdIB9QH/AQABLQEuAv8B9AH8Af8BAAEtAS4C/wLYAv8C3QL/AuIB/wGB - AnwB9gM0AXcBYgJgAbEB1QKiAf8BAAEtAS4B/wEAAS0BLgH/AQABLQEuAv8B9gL/AW0CcwH/AQABLQEu - Af8BbQJzAv8B4AHnAf8BbQJzAf8BAAEtAS4B/wFtAnMC/wLdAf8BWgJZAeQDLAFMBP8BmQEAATIJ/wGA - AgAJ/wGAAgAR/wGAAgAB/wPxAf8D6gH/A4AB/wGZAmUB/wGZAmUB/wGZAmUB/wGZAmUB/wMACf8DmQH/ - AygB/wMAAf8DGwH/AwAF/wMAAf8BmQJlAf8BmQJlAf8BYgJgAbEB1QKiAf8BbQJzAf8BAAEtAS4B/wFt - AnMC/wH2Av8BAAEtAS4C/wHSAfUB/wEAAS0BLgL/AeAB5wH/AQABLQEuAf8BAAEtAS4B/wEAAS0BLgL/ - At0B/wFaAlkB5AMsAUwDNwFQAcMCvxL/AewB8QL/AdsB5wL/AdkB3gL/AtQC/wLPAv8CzQL/AtIB/wHG - Aq0B/wNHAawDFAEbBP8BmQEAATIJ/wGAAgAJ/wGAAgAB/wGAAgAB/wGAAgAB/wGAAgAF/wGAAgAB/wGA - AgAB/wGAAgAB/wEyAgAB/wGZAmUB/wGZAmUB/wGZAmUB/wGZAmUB/wMAAf8DwA3/A8wB/wNeAf8DAAX/ - AwAB/wGZAmUB/wGZAmUB/wM3AVABwwK/Ev8B7AHxAv8B2wHnAv8B2QHeAv8C1AL/As8C/wLNAv8C0gH/ - AcYCrQH/A0cBrAMUARsEAANpAcAD9Qr/Av4C/wLnAv8C4wL/At4C/wLZAv8C1AL/As8B/wH1AscB/wFp - AmQB4wMiATQDAgEDBP8BmQEAATIB/wGAAgAF/wGAAgAJ/wGAAgAJ/wGAAgAF/wGAAgAB/wPxAf8D6gH/ - ATICAAH/AZkCZQH/AZkCZQH/AZkCZQH/AZkCZQH/AygB/wNMAf8DwBn/AwAB/wGZAmUB/wGZAmUB/wQA - A2kBwAP1Cv8C/gL/AucC/wLjAv8C3gL/AtkC/wLUAv8CzwH/AfUCxwH/AWkCZAHjAyIBNAMCAQMEAAMY - ASADgQHvA/UG/wL4Av8C7AL/AucC/wLjAv8C3gL/AtkB/wH1As0B/wGAAnUB9wMwAU0DBAEGBAAE/wGZ - AjIJ/wGAAgAB/wGAAgAJ/wGAAgAB/wGAAgAN/wGAAgAB/wGAAgAB/wOGAf8BmQJlAf8BmQJlAf8BmQJl - Af8BmQJlAf8BmQJlAf8DKAH/AwAB/wMoAf8DmRH/AwAB/wGZAmUB/wGZAmUB/wQAAxgBIAOBAe8D9Qb/ - AvgC/wLsAv8C5wL/AuMC/wLeAv8C2QH/AfUCzQH/AYACdQH3AzABTQMEAQYMAAMYASADaQHAA8YC/wL3 - Av8C8gL/AuwC/wLnAv8C4wH/AcYCsQH/AW0CagHQAyUBNgMCAQMIAAT/AZkCMi3/A/EB/wPqAf8DhgH/ - AZkCZQH/AZkCZQH/AZkCZQH/AZkCZQH/AZkCZQH/AZkCZQH/AZkCZQH/AygB/wMAAf8DGwH/A3YB/wPM - Bf8DAAH/AZkCZQH/AZkCZQH/CAADGAEgA2kBwAPGAv8C9wL/AvIC/wLsAv8C5wL/AuMB/wHGArEB/wFt - AmoB0AMlATYDAgEDGAADNwFQA18BogGCAoAB0gGMAokB/wGCAn4B1ANfAaYDOwFaAwUBBxAACP8BzAKZ - Lf8D8QH/A8AB/wQAAZkCZQH/AZkCZQH/AZkCZQH/AZkCZQH/AZkCZQH/AZkCZQH/AZkCZQH/AZkCZQH/ - AZkCZQH/AxsB/wMAAf8DTAH/AygB/wGZAmUB/xQAAzcBUANfAaIBggKAAdIBjAKJAf8BggJ+AdQDXwGm - AzsBWgMFAQcQAAFCAU0BPgcAAT4DAAEoAwABQAMAASADAAEBAQABAQYAAQEWAAP/gQAB4AEDAgABgAEB - AeABAwHAAQEEAAHAAQEBgAUAAYABAAGABQABgEEAAYAFAAGAAQABgAEBBAABgAEBAcABAwQAAcABAwHw - AQ8CAAGAAQEB8AEPCw== + AwABIAMAAQEBAAEgBgABIP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8ALgADAgEDAxQBHAMw + AUwDRAF5A1ABmgNQAaQDUAGaA0QBeQMwAUwDFAEcAwMBBAgAA5YB/wEkAgAB/wEkAgAB/wEkAgAB/wEk + AgAB/wEkAgAB/wEkAgAB/wEkAgAB/wEkAgAB/wEkAgAB/wEkAgAB/wEkAgAB/wEkAgAB/wEkAgAB/wEk + AgAB/wEkAgAB/wQAAVcBzAL/ASQCmQH/ASQCmQH/AVcBzAL/AVcBzAL/AVcBzAL/AVcBzAL/AVcBzAL/ + AVcBzAL/AVcBzAL/AVcBzAL/AVcBzAL/AVcBzAL/AVcBzAL/EAADAgEDAxQBHAMwAUwDRAF5A1ABmgNQ + AaQDUAGaA0QBeQMwAUwDFAEcAwMBBBAAAwQBBgMkATYDUwGwAWMCXgHlAYMCcwH7AbMCqQH/AYMCfAH7 + A2AB6wNaAdMDUwGsA0cBggMoATwDBwEJBAABzAKZAf8BgAIAAf8BgAIAAf8BgAIAAf8BgAIAAf8D6gH/ + A+oB/wPqAf8BgAIAAf8D6gH/A+oB/wPqAf8BgAIAAf8BgAIAAf8BVwIAAf8BJAIAAf8BJAKZAf8DAAH/ + AxoB/wM+Af8DAAH/Aw0B/wFXAcwC/wFXAcwC/wFXAcwC/wFXAcwC/wFXAcwC/wFXAcwC/wFXAcwC/wFX + AcwC/wFXAcwC/wFXAcwC/wgAAwQBBgMkATYDUwGwAWMCXgHlAYMCcwH7AbMCqQH/AYMCfAH7A2AB6wNa + AdMDUwGsA0cBggMoATwDBwEJCAADAgEDAzEBTwNcAeoBzwK0Av8C3QL/AuIC/wLoAv8C7gL/AvMB/wPP + Af8DXwHzA1gBxgNMAZIDKAE8AwMBBAHMApkB/wGAAgAB/wGAAgAB/wGAAgAB/wPxAf8BgAIAAf8BgAIA + Af8D8QH/AYACAAH/A/EB/wGAAgAB/wGAAgAB/wPxAf8BgAIAAf8BgAIAAf8BJAIAAf8DAAH/A8wN/wM+ + Af8DDQH/AVcBzAL/AVcBzAL/AVcBzAL/AVcBzAL/AVcBzAL/AVcBzAL/AVcBzAL/AVcBzAL/AVcBzAL/ + BAADAgEDAzEBTwNcAeoBzwK0Av8C3QL/AuIC/wLoAv8C7gL/AvMB/wPPAf8DXwHzA1gBxgNMAZIDKAE8 + AwMBBAQAAyYBOANtAfcB9QLHAv8C0gL/AtgC/wLdAv8C4gL/AugC/wL0Bf8D9QH/A4oB+wNYAcYDRwGC + AxQBHAHMApkB/wGZAQABJAH/AYACAAH/AYACAAX/AYACAAH/AYACAAX/AYACAAX/AYACAAH/AYACAAX/ + AYACAAH/AYACAAH/ASQCAAH/AwAB/wPMEf8DAAH/AVcBzAL/AVcBzAL/AVcBzAL/AVcBzAL/AVcBzAL/ + AVcBzAL/AVcBzAL/AVcBzAL/AVcBzAL/BAADJgE4A20B9wH1AscC/wLSAv8C2AL/At0C/wLiAv8C6AL/ + AvQF/wP1Af8DigH7A1gBxgNHAYIDFAEcAwcBCQNeAd0B9QLNAv8CzwL/As0C/wLSAv8C2AL/At0C/wLi + Av8C+gn/A/UB/wNfAfMDUwGsAzABTAHMApkB/wGZAQABJAH/AYACAAH/AYACAAH/AYACAA3/AYACAA3/ + AYACAAH/AYACAAH/AYACAAH/ASQCAAH/ASQCmQH/Aw0B/wNoAf8DwAH/A8AB/wPMAf8DAAH/AxoB/wMA + Af8DAAH/AwAB/wMAAf8DGgH/AVcBzAL/AVcBzAL/AVcBzAL/AwcBCQNeAd0B9QLNAv8CzwL/As0C/wLS + Av8C2AL/At0C/wLiAv8C+gn/A/UB/wNfAfMDUwGsAzABTAM+AWoBxgKxAv8C2QL/AtQC/wLPAv8CzQL/ + AdQB2wL/AdcB4gL/AeQB6hH/AdICzAH/A1oB0wNDAXcBzAKZAf8BmQEAASQB/wGAAgAB/wGAAgAB/wGA + AgAB/wGAAgAB/wGAAgAF/wGAAgAF/wGAAgAB/wGAAgAB/wGAAgAB/wGAAgAB/wGAAgAB/wEkAgAB/wFX + AcwC/wEkApkB/wMNAf8DAAH/AwAF/wMAAf8DDQH/AaQCoAn/A5kB/wMaAf8DGgH/AVcBzAL/AVcBzAL/ + Az4BagHGArEC/wLZAv8C1AL/As8C/wLNAv8B1AHbAv8B1wHiAv8B5AHqEf8B0gLMAf8DWgHTA0MBdwNW + AbYB/wLjAf8BAAEfASAB/wEAAR8BIAH/AQABHwEgAv8B3gHnAf8BAAEfASAC/wHRAfMB/wEAAR8BIAL/ + AfgC/wFfAmUB/wEAAR8BIAH/AV8CZQH/AcwCmQH/AVwCVQHqA04BlAHMApkB/wGZAQABJAH/AYACAAH/ + AYACAAH/AYACAAH/AYACAAH/AYACAAX/AYACAAX/AYACAAH/AYACAAH/AYACAAH/AYACAAH/AYACAAH/ + ASQCAAH/AVcBzAL/AVcBzAL/AVcBzAL/AVcBzAL/AwAF/wMAAf8DGhH/A8wB/wMAAf8BVwHMAv8BVwHM + Av8DVgG2Af8C4wH/AV8CZQH/AQABHwEgAf8BXwJlAv8B3gHnAf8BXwJlAf8BAAEfASAB/wFfAmUC/wH4 + Av8BAAEfASAB/wEAAR8BIAH/AQABHwEgAf8BzAKZAf8BXAJVAeoDTgGUA2EB4gH/AucB/wEAAR8BIAL/ + At4C/wLgAv8B7wH8Af8BAAEfASAC/wHiAfwB/wEAAR8BIAH/AfwB8AH5Af8BAAEfASAB/wHMApkB/wEA + AR8BIAH/AcwCmQH/AW0CbAH3A1EBoQHMApkB/wGZAQABJAH/AYACAAH/AYACAAH/AYACAAH/AYACAAH/ + AYACAAH/AYACAAH/AYACAAH/AYACAAH/AYACAAH/AYACAAH/AYACAAH/AYACAAH/AYACAAH/ASQCAAH/ + AZkCVwH/AZkCVwH/AZkCVwH/AZkCVwH/AwAF/wMAAf8DAAH/Az4B/wPMDf8DAAH/AZkCVwH/AZkCVwH/ + A2EB4gH/AucB/wEAAR8BIAL/At4B/wEAAR8BIAL/Ae8B/AH/AQABHwEgAv8B4gH8Af8BAAEfASAB/wH8 + AfAB+QH/AQABHwEgAf8BzAKZAf8BzAKZAf8BzAKZAf8BbQJsAfcDUQGhAZ4CjAH/AekCvgH/AQABHwEg + Af8BAAEfASAB/wH5AtYC/wHpAfMB/wEAAR8BIAH/AQABHwEgAf8BAAEfASAB/wH5AegB7AH/AQABHwEg + Af8B5gK6Af8B5gK9Af8B5gLAAf8BpgKUAf8DTgGUNP8D8QH/A+oB/wOAAf8BmQJXAf8BmQJXAf8BmQJX + Af8BmQJXAf8DAAX/AwAB/wNGAf8DDQH/AwAB/wMAAf8DAAX/AwAB/wGZAlcB/wGZAlcB/wGeAowB/wHp + Ar4B/wEAAR8BIAH/AfMCxQH/AfkC1gL/AekB8wH/AQABHwEgAv8B6QHzAf8BAAEfASAB/wH5AegB7AH/ + AQABHwEgAf8BAAEfASAB/wHmAr0B/wHmAsAB/wGmApQB/wNOAZQDXQHSAdsCqAH/AQABHwEgAf8B6gK3 + Af8B8wLNAv8B7gH8Af8BAAEfASAC/wHSAfUB/wEAAR8BIAL/AfQB/AH/AQABHwEgAv8C2AH/AQABHwEg + Av8C4gH/A2IB9gNDAXcE/wGZAQABJAn/AYACAA3/AYACAAH/AYACAA3/AYACAAH/AYACAAH/A4AB/wGZ + AlcB/wGZAlcB/wGZAlcB/wGZAlcB/wMABf8DDQH/AwAB/wMaAf8DRgH/A0YB/wMABf8DAAH/AZkCVwH/ + AZkCVwH/A10B0gHbAqgB/wEAAR8BIAH/AeoCtwH/AQABHwEgAv8B7gH8Af8BAAEfASAC/wHSAfUB/wEA + AR8BIAL/AfQB/AH/AQABHwEgAv8C2AL/At0C/wLiAf8DYgH2A0MBdwNWAbEB1QKiAf8BAAEfASAB/wEA + AR8BIAH/AQABHwEgAv8B9gL/AV8CZQH/AQABHwEgAf8BXwJlAv8B4AHnAf8BXwJlAf8BAAEfASAB/wFf + AmUC/wLdAf8DWgHkAzABTAT/AZkBAAEkCf8BgAIACf8BgAIAEf8BgAIAAf8D8QH/A+oB/wOAAf8BmQJX + Af8BmQJXAf8BmQJXAf8BmQJXAf8DAAn/A5kB/wMaAf8DAAH/Aw0B/wMABf8DAAH/AZkCVwH/AZkCVwH/ + A1YBsQHVAqIB/wFfAmUB/wEAAR8BIAH/AV8CZQL/AfYC/wEAAR8BIAL/AdIB9QH/AQABHwEgAv8B4AHn + Af8BAAEfASAB/wEAAR8BIAH/AQABHwEgAv8C3QH/A1oB5AMwAUwDMgFQAcMCvxL/AewB8QL/AdsB5wL/ + AdkB3gL/AtQC/wLPAv8CzQL/AtIB/wHGAq0B/wNTAawDFAEbBP8BmQEAASQJ/wGAAgAJ/wGAAgAB/wGA + AgAB/wGAAgAB/wGAAgAF/wGAAgAB/wGAAgAB/wGAAgAB/wEkAgAB/wGZAlcB/wGZAlcB/wGZAlcB/wGZ + AlcB/wMAAf8DwA3/A8wB/wNQAf8DAAX/AwAB/wGZAlcB/wGZAlcB/wMyAVABwwK/Ev8B7AHxAv8B2wHn + Av8B2QHeAv8C1AL/As8C/wLNAv8C0gH/AcYCrQH/A1MBrAMUARsEAANaAcAD9Qr/Av4C/wLnAv8C4wL/ + At4C/wLZAv8C1AL/As8B/wH1AscB/wNfAeMDIwE0AwIBAwT/AZkBAAEkAf8BgAIABf8BgAIACf8BgAIA + Cf8BgAIABf8BgAIAAf8D8QH/A+oB/wEkAgAB/wGZAlcB/wGZAlcB/wGZAlcB/wGZAlcB/wMaAf8DPgH/ + A8AZ/wMAAf8BmQJXAf8BmQJXAf8EAANaAcAD9Qr/Av4C/wLnAv8C4wL/At4C/wLZAv8C1AL/As8B/wH1 + AscB/wNfAeMDIwE0AwIBAwQAAxcBIANiAe8D9Qb/AvgC/wLsAv8C5wL/AuMC/wLeAv8C2QH/AfUCzQH/ + A20B9wMwAU0DBAEGBAAE/wGZAiQJ/wGAAgAB/wGAAgAJ/wGAAgAB/wGAAgAN/wGAAgAB/wGAAgAB/wOG + Af8BmQJXAf8BmQJXAf8BmQJXAf8BmQJXAf8BmQJXAf8DGgH/AwAB/wMaAf8DmRH/AwAB/wGZAlcB/wGZ + AlcB/wQAAxcBIANiAe8D9Qb/AvgC/wLsAv8C5wL/AuMC/wLeAv8C2QH/AfUCzQH/A20B9wMwAU0DBAEG + DAADFwEgA1oBwAPGAv8C9wL/AvIC/wLsAv8C5wL/AuMB/wHGArEB/wNeAdADJAE2AwIBAwgABP8BmQIk + Lf8D8QH/A+oB/wOGAf8BmQJXAf8BmQJXAf8BmQJXAf8BmQJXAf8BmQJXAf8BmQJXAf8BmQJXAf8DGgH/ + AwAB/wMNAf8DaAH/A8wF/wMAAf8BmQJXAf8BmQJXAf8IAAMXASADWgHAA8YC/wL3Av8C8gL/AuwC/wLn + Av8C4wH/AcYCsQH/A14B0AMkATYDAgEDGAADMgFQA1EBogNdAdIBjAKJAf8DYAHUA1QBpgM3AVoDBQEH + EAAI/wHMApkt/wPxAf8DwAH/BAABmQJXAf8BmQJXAf8BmQJXAf8BmQJXAf8BmQJXAf8BmQJXAf8BmQJX + Af8BmQJXAf8BmQJXAf8DDQH/AwAB/wM+Af8DGgH/AZkCVwH/FAADMgFQA1EBogNdAdIBjAKJAf8DYAHU + A1QBpgM3AVoDBQEHEAABQgFNAT4HAAE+AwABKAMAAUADAAEgAwABAQEAAQEGAAEBFgAD/4EAAeABAwIA + AYABAQHgAQMBwAEBBAABwAEBAYAFAAGAAQABgAUAAYBBAAGABQABgAEAAYABAQQAAYABAQHAAQMEAAHA + AQMB8AEPAgABgAEBAfABDws= - 24 + 0 listChoices @@ -249,29 +255,31 @@ System.Windows.Forms.ListView, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - $this + tableLayoutPanel1 4 + + Fill + Courier New, 8pt - 12, 90 + 3, 86 True - Vertical - 551, 197 + 545, 35 - 25 + 1 textBox1 @@ -280,36 +288,9 @@ System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - $this + tableLayoutPanel1 - 3 - - - Top, Left, Right - - - 12, 90 - - - 551, 197 - - - 26 - - - False - - - listTracks - - - System.Windows.Forms.ListView, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - 2 @@ -342,68 +323,152 @@ Right - - 407, 293 + + Fill - - 75, 23 + + 3, 243 - - 27 + + 545, 137 - - Edit + + 3 - + False - - btnEdit + + listTracks - - System.Windows.Forms.Button, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + System.Windows.Forms.ListView, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - $this + + tableLayoutPanel1 - + + 3 + + 1 - - True + + 1 - - 315, 297 + + Value - - 86, 17 + + 400 - - 28 + + 0 - - Fix encoding + + Name - - chkFixEncoding + + 120 - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + Fill - + + 3, 127 + + + 545, 110 + + + 2 + + + False + + + listMetadata + + + System.Windows.Forms.ListView, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tableLayoutPanel1 + + + 0 + + + 4 + + + Fill + + + 3, 386 + + + 1 + + + 545, 29 + + + 30 + + + tableLayoutPanel2 + + + System.Windows.Forms.TableLayoutPanel, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tableLayoutPanel1 + + + 1 + + + <?xml version="1.0" encoding="utf-16"?><TableLayoutSettings><Controls><Control Name="buttonOk" Row="0" RowSpan="1" Column="3" ColumnSpan="1" /></Controls><Columns Styles="Percent,37,59399,Percent,22,93233,Percent,19,17293,Percent,20,11278" /><Rows Styles="Percent,100" /></TableLayoutSettings> + + + 12, 12 + + + 5 + + + 551, 418 + + + 29 + + + tableLayoutPanel1 + + + System.Windows.Forms.TableLayoutPanel, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + $this - + 0 + + <?xml version="1.0" encoding="utf-16"?><TableLayoutSettings><Controls><Control Name="listMetadata" Row="2" RowSpan="1" Column="0" ColumnSpan="1" /><Control Name="tableLayoutPanel2" Row="4" RowSpan="1" Column="0" ColumnSpan="1" /><Control Name="textBox1" Row="1" RowSpan="1" Column="0" ColumnSpan="1" /><Control Name="listTracks" Row="3" RowSpan="1" Column="0" ColumnSpan="1" /><Control Name="listChoices" Row="0" RowSpan="1" Column="0" ColumnSpan="1" /></Controls><Columns Styles="Percent,100" /><Rows Styles="Percent,19,79167,Percent,9,895833,Percent,27,86458,Percent,34,11458,Percent,8,000021,Absolute,20" /></TableLayoutSettings> + True + + 51 + 6, 13 - 575, 328 + 575, 442 CenterParent @@ -447,6 +512,18 @@ System.Windows.Forms.ColumnHeader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + columnHeader2 + + + System.Windows.Forms.ColumnHeader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + columnHeader3 + + + System.Windows.Forms.ColumnHeader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + frmChoice diff --git a/CUETools/frmSettings.Designer.cs b/CUETools/frmSettings.Designer.cs index 05b95dd..5459460 100644 --- a/CUETools/frmSettings.Designer.cs +++ b/CUETools/frmSettings.Designer.cs @@ -126,14 +126,14 @@ namespace JDP { this.listViewFormats = new System.Windows.Forms.ListView(); this.columnHeader1 = new System.Windows.Forms.ColumnHeader(); this.tabPage10 = new System.Windows.Forms.TabPage(); + this.groupBoxFlaCudaOptions = new System.Windows.Forms.GroupBox(); + this.checkBoxFlaCudaGPUOnly = new System.Windows.Forms.CheckBox(); + this.checkBoxFlaCudaVerify = new System.Windows.Forms.CheckBox(); this.groupBoxExternalEncoder = new System.Windows.Forms.GroupBox(); this.labelEncoderName = new System.Windows.Forms.Label(); this.labelEncoderModes = new System.Windows.Forms.Label(); this.labelEncoderPath = new System.Windows.Forms.Label(); this.labelEncoderParameters = new System.Windows.Forms.Label(); - this.groupBoxFlaCudaOptions = new System.Windows.Forms.GroupBox(); - this.checkBoxFlaCudaGPUOnly = new System.Windows.Forms.CheckBox(); - this.checkBoxFlaCudaVerify = new System.Windows.Forms.CheckBox(); this.buttonEncoderDelete = new System.Windows.Forms.Button(); this.buttonEncoderAdd = new System.Windows.Forms.Button(); this.listBoxEncoders = new System.Windows.Forms.ListBox(); @@ -174,6 +174,7 @@ namespace JDP { this.labelFormatEncoder = new System.Windows.Forms.Label(); this.columnHeader2 = new System.Windows.Forms.ColumnHeader(); this.checkBox1 = new System.Windows.Forms.CheckBox(); + this.checkBoxFlaCudaMultithread = new System.Windows.Forms.CheckBox(); btnCancel = new System.Windows.Forms.Button(); this.grpGeneral.SuspendLayout(); this.groupBox1.SuspendLayout(); @@ -202,8 +203,8 @@ namespace JDP { this.tabPage3.SuspendLayout(); this.groupBoxFormat.SuspendLayout(); this.tabPage10.SuspendLayout(); - this.groupBoxExternalEncoder.SuspendLayout(); this.groupBoxFlaCudaOptions.SuspendLayout(); + this.groupBoxExternalEncoder.SuspendLayout(); this.groupBoxLibWavpack.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.numWVExtraMode)).BeginInit(); this.groupBoxLibFLAC.SuspendLayout(); @@ -1056,6 +1057,7 @@ namespace JDP { // resources.ApplyResources(this.tabPage10, "tabPage10"); this.tabPage10.BackColor = System.Drawing.SystemColors.Control; + this.tabPage10.Controls.Add(this.groupBoxFlaCudaOptions); this.tabPage10.Controls.Add(this.groupBoxExternalEncoder); this.tabPage10.Controls.Add(this.buttonEncoderDelete); this.tabPage10.Controls.Add(this.buttonEncoderAdd); @@ -1065,9 +1067,31 @@ namespace JDP { this.tabPage10.Controls.Add(this.groupBoxLibWavpack); this.tabPage10.Controls.Add(this.labelEncoderExtension); this.tabPage10.Controls.Add(this.groupBoxLibFLAC); - this.tabPage10.Controls.Add(this.groupBoxFlaCudaOptions); this.tabPage10.Name = "tabPage10"; // + // groupBoxFlaCudaOptions + // + this.groupBoxFlaCudaOptions.Controls.Add(this.checkBoxFlaCudaMultithread); + this.groupBoxFlaCudaOptions.Controls.Add(this.checkBoxFlaCudaGPUOnly); + this.groupBoxFlaCudaOptions.Controls.Add(this.checkBoxFlaCudaVerify); + resources.ApplyResources(this.groupBoxFlaCudaOptions, "groupBoxFlaCudaOptions"); + this.groupBoxFlaCudaOptions.Name = "groupBoxFlaCudaOptions"; + this.groupBoxFlaCudaOptions.TabStop = false; + // + // checkBoxFlaCudaGPUOnly + // + resources.ApplyResources(this.checkBoxFlaCudaGPUOnly, "checkBoxFlaCudaGPUOnly"); + this.checkBoxFlaCudaGPUOnly.DataBindings.Add(new System.Windows.Forms.Binding("Checked", this.cUEConfigBindingSource, "FlaCudaGPUOnly", true)); + this.checkBoxFlaCudaGPUOnly.Name = "checkBoxFlaCudaGPUOnly"; + this.checkBoxFlaCudaGPUOnly.UseVisualStyleBackColor = true; + // + // checkBoxFlaCudaVerify + // + resources.ApplyResources(this.checkBoxFlaCudaVerify, "checkBoxFlaCudaVerify"); + this.checkBoxFlaCudaVerify.DataBindings.Add(new System.Windows.Forms.Binding("Checked", this.cUEConfigBindingSource, "FlaCudaVerify", true)); + this.checkBoxFlaCudaVerify.Name = "checkBoxFlaCudaVerify"; + this.checkBoxFlaCudaVerify.UseVisualStyleBackColor = true; + // // groupBoxExternalEncoder // resources.ApplyResources(this.groupBoxExternalEncoder, "groupBoxExternalEncoder"); @@ -1103,26 +1127,6 @@ namespace JDP { resources.ApplyResources(this.labelEncoderParameters, "labelEncoderParameters"); this.labelEncoderParameters.Name = "labelEncoderParameters"; // - // groupBoxFlaCudaOptions - // - this.groupBoxFlaCudaOptions.Controls.Add(this.checkBoxFlaCudaGPUOnly); - this.groupBoxFlaCudaOptions.Controls.Add(this.checkBoxFlaCudaVerify); - resources.ApplyResources(this.groupBoxFlaCudaOptions, "groupBoxFlaCudaOptions"); - this.groupBoxFlaCudaOptions.Name = "groupBoxFlaCudaOptions"; - this.groupBoxFlaCudaOptions.TabStop = false; - // - // checkBoxFlaCudaGPUOnly - // - resources.ApplyResources(this.checkBoxFlaCudaGPUOnly, "checkBoxFlaCudaGPUOnly"); - this.checkBoxFlaCudaGPUOnly.Name = "checkBoxFlaCudaGPUOnly"; - this.checkBoxFlaCudaGPUOnly.UseVisualStyleBackColor = true; - // - // checkBoxFlaCudaVerify - // - resources.ApplyResources(this.checkBoxFlaCudaVerify, "checkBoxFlaCudaVerify"); - this.checkBoxFlaCudaVerify.Name = "checkBoxFlaCudaVerify"; - this.checkBoxFlaCudaVerify.UseVisualStyleBackColor = true; - // // buttonEncoderDelete // this.buttonEncoderDelete.DataBindings.Add(new System.Windows.Forms.Binding("Enabled", this.encodersBindingSource, "CanBeDeleted", true)); @@ -1451,6 +1455,13 @@ namespace JDP { this.checkBox1.Name = "checkBox1"; this.checkBox1.UseVisualStyleBackColor = true; // + // checkBoxFlaCudaMultithread + // + resources.ApplyResources(this.checkBoxFlaCudaMultithread, "checkBoxFlaCudaMultithread"); + this.checkBoxFlaCudaMultithread.DataBindings.Add(new System.Windows.Forms.Binding("Checked", this.cUEConfigBindingSource, "FlaCudaThreads", true)); + this.checkBoxFlaCudaMultithread.Name = "checkBoxFlaCudaMultithread"; + this.checkBoxFlaCudaMultithread.UseVisualStyleBackColor = true; + // // frmSettings // this.AcceptButton = this.btnOK; @@ -1507,10 +1518,10 @@ namespace JDP { this.groupBoxFormat.PerformLayout(); this.tabPage10.ResumeLayout(false); this.tabPage10.PerformLayout(); - this.groupBoxExternalEncoder.ResumeLayout(false); - this.groupBoxExternalEncoder.PerformLayout(); this.groupBoxFlaCudaOptions.ResumeLayout(false); this.groupBoxFlaCudaOptions.PerformLayout(); + this.groupBoxExternalEncoder.ResumeLayout(false); + this.groupBoxExternalEncoder.PerformLayout(); this.groupBoxLibWavpack.ResumeLayout(false); this.groupBoxLibWavpack.PerformLayout(); ((System.ComponentModel.ISupportInitialize)(this.numWVExtraMode)).EndInit(); @@ -1683,6 +1694,7 @@ namespace JDP { private System.Windows.Forms.CheckBox checkBoxFlaCudaGPUOnly; private System.Windows.Forms.CheckBox checkBoxFlaCudaVerify; private System.Windows.Forms.CheckBox checkBox1; + private System.Windows.Forms.CheckBox checkBoxFlaCudaMultithread; } } \ No newline at end of file diff --git a/CUETools/frmSettings.cs b/CUETools/frmSettings.cs index 3b57721..bcca793 100644 --- a/CUETools/frmSettings.cs +++ b/CUETools/frmSettings.cs @@ -45,8 +45,6 @@ namespace JDP { numEncodeWhenPercent.Value = _config.encodeWhenPercent; chkEncodeWhenZeroOffset.Checked = _config.encodeWhenZeroOffset; chkFLACVerify.Checked = _config.flacVerify; - checkBoxFlaCudaVerify.Checked = _config.flaCudaVerify; - checkBoxFlaCudaGPUOnly.Checked = _config.flaCudaGPUOnly; chkWriteArTagsOnConvert.Checked = _config.writeArTagsOnEncode; chkWriteARTagsOnVerify.Checked = _config.writeArTagsOnVerify; chkWVExtraMode.Checked = (_config.wvExtraMode != 0); @@ -209,8 +207,6 @@ namespace JDP { _config.encodeWhenConfidence = (uint)numEncodeWhenConfidence.Value; _config.encodeWhenZeroOffset = chkEncodeWhenZeroOffset.Checked; _config.flacVerify = chkFLACVerify.Checked; - _config.flaCudaVerify = checkBoxFlaCudaVerify.Checked; - _config.flaCudaGPUOnly = checkBoxFlaCudaGPUOnly.Checked; _config.writeArTagsOnEncode = chkWriteArTagsOnConvert.Checked; _config.writeArTagsOnVerify = chkWriteARTagsOnVerify.Checked; if (!chkWVExtraMode.Checked) _config.wvExtraMode = 0; @@ -493,10 +489,10 @@ namespace JDP { comboBoxEncoderExtension.Visible = encoder != null; comboBoxEncoderExtension.Enabled = encoder != null && encoder.path != null; groupBoxExternalEncoder.Visible = encoder != null && encoder.path != null; - groupBoxFlaCudaOptions.Visible = encoder != null && encoder.path == null && encoder.className == "FlaCudaWriter"; - groupBoxLibFLAC.Visible = encoder != null && encoder.path == null && encoder.className == "FLACWriter"; - groupBoxLibWavpack.Visible = encoder != null && encoder.path == null && encoder.className == "WavPackWriter"; - groupBoxLibMAC_SDK.Visible = encoder != null && encoder.path == null && encoder.className == "APEWriter"; + groupBoxFlaCudaOptions.Visible = encoder != null && encoder.path == null && encoder.type.Name == "FlaCudaWriter"; + groupBoxLibFLAC.Visible = encoder != null && encoder.path == null && encoder.type.Name == "FLACWriter"; + groupBoxLibWavpack.Visible = encoder != null && encoder.path == null && encoder.type.Name == "WavPackWriter"; + groupBoxLibMAC_SDK.Visible = encoder != null && encoder.path == null && encoder.type.Name == "APEWriter"; checkBoxEncoderLossless.Enabled = encoder != null && format != null && format.allowLossless && format.allowLossy; if (!checkBoxEncoderLossless.Enabled && encoder != null && format != null && encoder.Lossless != format.allowLossless) encoder.Lossless = format.allowLossless; diff --git a/CUETools/frmSettings.resx b/CUETools/frmSettings.resx index ded84c8..1437aa0 100644 --- a/CUETools/frmSettings.resx +++ b/CUETools/frmSettings.resx @@ -2928,6 +2928,123 @@ True + + True + + + NoControl + + + 9, 68 + + + 80, 17 + + + 22 + + + Multithread + + + checkBoxFlaCudaMultithread + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBoxFlaCudaOptions + + + 0 + + + True + + + NoControl + + + 10, 26 + + + 69, 17 + + + 21 + + + GPU only + + + checkBoxFlaCudaGPUOnly + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBoxFlaCudaOptions + + + 1 + + + True + + + NoControl + + + 9, 46 + + + 54, 17 + + + 20 + + + Verify + + + checkBoxFlaCudaVerify + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBoxFlaCudaOptions + + + 2 + + + 136, 39 + + + 390, 100 + + + 30 + + + FlaCuda options + + + False + + + groupBoxFlaCudaOptions + + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabPage10 + + + 0 + None @@ -3073,7 +3190,7 @@ tabPage10 - 0 + 1 @@ -3114,7 +3231,7 @@ tabPage10 - 1 + 2 @@ -3152,7 +3269,7 @@ tabPage10 - 2 + 3 6, 7 @@ -3173,7 +3290,7 @@ tabPage10 - 3 + 4 459, 12 @@ -3197,7 +3314,7 @@ tabPage10 - 4 + 5 136, 39 @@ -3224,7 +3341,7 @@ tabPage10 - 5 + 6 True @@ -3335,7 +3452,7 @@ tabPage10 - 6 + 7 True @@ -3371,7 +3488,7 @@ tabPage10 - 7 + 8 True @@ -3428,93 +3545,6 @@ tabPage10 - 8 - - - True - - - NoControl - - - 10, 26 - - - 69, 17 - - - 21 - - - GPU only - - - checkBoxFlaCudaGPUOnly - - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - groupBoxFlaCudaOptions - - - 0 - - - True - - - NoControl - - - 9, 46 - - - 54, 17 - - - 20 - - - Verify - - - checkBoxFlaCudaVerify - - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - groupBoxFlaCudaOptions - - - 1 - - - 136, 39 - - - 390, 74 - - - 30 - - - FlaCuda options - - - False - - - groupBoxFlaCudaOptions - - - System.Windows.Forms.GroupBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabPage10 - - 9 diff --git a/CUETools/hdcd.dll b/CUETools/hdcd.dll new file mode 100644 index 0000000000000000000000000000000000000000..ae565f6c976918fce5c33cc45936f20eaa717ec1 GIT binary patch literal 106496 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

j?r(fzvnX!q-x+BPc2hqMndI%;TV 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

?;L;rO9^6+nu6avj}ShxP? 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

1#kGmaM0$yD3 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 N8Rk?OGZ{vP000#Wprompt - ..\bin\win32\Release\ + ..\bin\any\Release\ false 285212672 false - TRACE + + false diff --git a/HDCDDotNet/HDCDDotNet.cs b/HDCDDotNet/HDCDDotNet.cs index fccb9ed..0293d1e 100644 --- a/HDCDDotNet/HDCDDotNet.cs +++ b/HDCDDotNet/HDCDDotNet.cs @@ -32,6 +32,8 @@ namespace HDCDDotNet { _decoder = IntPtr.Zero; #if !MONO + if (decode) + _audioBuffer = new AudioBuffer(new AudioPCMConfig(output_bps, channels, 44100), 256); _decoder = hdcd_decoder_new(); _channelCount = channels; _bitsPerSample = output_bps; @@ -121,19 +123,19 @@ namespace HDCDDotNet stats = (hdcd_decoder_statistics) Marshal.PtrToStructure(_statsPtr, typeof(hdcd_decoder_statistics)); } - public void Process(int[,] sampleBuffer, uint sampleCount) + public void Process(int[,] sampleBuffer, int sampleCount) { #if !MONO - if (!hdcd_decoder_process_buffer_interleaved(_decoder, sampleBuffer, (int) sampleCount)) + if (!hdcd_decoder_process_buffer_interleaved(_decoder, sampleBuffer, sampleCount)) throw new Exception("HDCD processing error."); #endif } - public void Process(byte[] buff, uint sampleCount) + public void Process(byte[] buff, int sampleCount) { if (_inSampleBuffer == null || _inSampleBuffer.GetLength(0) < sampleCount) _inSampleBuffer = new int[sampleCount, _channelCount]; - AudioSamples.BytesToFLACSamples_16(buff, 0, _inSampleBuffer, 0, sampleCount, _channelCount); + AudioBuffer.BytesToFLACSamples_16(buff, 0, _inSampleBuffer, 0, sampleCount, _channelCount); Process(_inSampleBuffer, sampleCount); } @@ -198,6 +200,7 @@ namespace HDCDDotNet /**< Processing failed due to a memory allocation error. */ }; + private AudioBuffer _audioBuffer; private IntPtr _decoder; private int[,] _inSampleBuffer; private int[,] _outSampleBuffer; @@ -234,7 +237,8 @@ namespace HDCDDotNet for (int i = 0; i < loopCount; i++) *(pOutSamples++) = *(pInSamples++); } - AudioDest.Write(_outSampleBuffer, 0, samples); + _audioBuffer.Prepare(_outSampleBuffer, samples); + AudioDest.Write(_audioBuffer); return true; } diff --git a/HDCDDotNet/HDCDDotNet.csproj b/HDCDDotNet/HDCDDotNet.csproj index f017e79..1da8f19 100644 --- a/HDCDDotNet/HDCDDotNet.csproj +++ b/HDCDDotNet/HDCDDotNet.csproj @@ -22,10 +22,11 @@ pdbonly true - bin\Release\ + ..\bin\any\Release\ TRACE prompt 4 + true true diff --git a/LossyWAVSharp/LossyWAVSharp.csproj b/LossyWAVSharp/LossyWAVSharp.csproj index d514f50..55f5bbe 100644 --- a/LossyWAVSharp/LossyWAVSharp.csproj +++ b/LossyWAVSharp/LossyWAVSharp.csproj @@ -22,7 +22,7 @@ pdbonly true - bin\Release\ + ..\bin\any\Release\ TRACE prompt 4 diff --git a/LossyWAVSharp/Program.cs b/LossyWAVSharp/Program.cs index 456d0b8..20f9f31 100644 --- a/LossyWAVSharp/Program.cs +++ b/LossyWAVSharp/Program.cs @@ -92,39 +92,38 @@ namespace LossyWAVSharp { WAVReader audioSource = new WAVReader(sourceFile, (sourceFile == "-" ? Console.OpenStandardInput() : null)); if (sourceFile == "-" && stdinName != null) sourceFile = stdinName; - WAVWriter audioDest = new WAVWriter(Path.ChangeExtension(sourceFile, ".lossy.wav"), outputBPS == 0 ? audioSource.BitsPerSample : outputBPS, audioSource.ChannelCount, audioSource.SampleRate, toStdout ? Console.OpenStandardOutput() : null); - WAVWriter lwcdfDest = createCorrection ? new WAVWriter(Path.ChangeExtension(sourceFile, ".lwcdf.wav"), audioSource.BitsPerSample, audioSource.ChannelCount, audioSource.SampleRate, null) : null; - LossyWAVWriter lossyWAV = new LossyWAVWriter(audioDest, lwcdfDest, audioSource.BitsPerSample, audioSource.ChannelCount, audioSource.SampleRate, quality); - int[,] buff = new int[0x1000, audioSource.ChannelCount]; + AudioPCMConfig pcm = outputBPS == 0 ? audioSource.PCM : new AudioPCMConfig(outputBPS, audioSource.PCM.ChannelCount, audioSource.PCM.SampleRate); + WAVWriter audioDest = new WAVWriter(Path.ChangeExtension(sourceFile, ".lossy.wav"), toStdout ? Console.OpenStandardOutput() : null, pcm); + WAVWriter lwcdfDest = createCorrection ? new WAVWriter(Path.ChangeExtension(sourceFile, ".lwcdf.wav"), null, audioSource.PCM) : null; + LossyWAVWriter lossyWAV = new LossyWAVWriter(audioDest, lwcdfDest, quality, audioSource.PCM); + AudioBuffer buff = new AudioBuffer(audioSource, 0x10000); Console.WriteLine("Filename : {0}", sourceFile); - Console.WriteLine("File Info : {0}kHz; {1} channel; {2} bit; {3}", audioSource.SampleRate, audioSource.ChannelCount, audioSource.BitsPerSample, TimeSpan.FromSeconds(audioSource.Length * 1.0 / audioSource.SampleRate)); - lossyWAV.FinalSampleCount = (long) audioSource.Length; + Console.WriteLine("File Info : {0}kHz; {1} channel; {2} bit; {3}", audioSource.PCM.SampleRate, audioSource.PCM.ChannelCount, audioSource.PCM.BitsPerSample, TimeSpan.FromSeconds(audioSource.Length * 1.0 / audioSource.PCM.SampleRate)); + lossyWAV.FinalSampleCount = audioSource.Length; - do + while (audioSource.Read(buff, -1) != 0) { - uint samplesRead = audioSource.Read(buff, Math.Min((uint)buff.GetLength(0), (uint)audioSource.Remaining)); - if (samplesRead == 0) break; - lossyWAV.Write(buff, 0, (int)samplesRead); + lossyWAV.Write(buff); TimeSpan elapsed = DateTime.Now - start; if ((elapsed - lastPrint).TotalMilliseconds > 60) { Console.Error.Write("\rProgress : {0:00}%; {1:0.0000} bits; {2:0.00}x; {3}/{4}", 100.0 * audioSource.Position / audioSource.Length, - 1.0 * lossyWAV.OverallBitsRemoved / audioSource.ChannelCount / lossyWAV.BlocksProcessed, - lossyWAV.SamplesProcessed / elapsed.TotalSeconds / audioSource.SampleRate, + 1.0 * lossyWAV.OverallBitsRemoved / audioSource.PCM.ChannelCount / lossyWAV.BlocksProcessed, + lossyWAV.SamplesProcessed / elapsed.TotalSeconds / audioSource.PCM.SampleRate, elapsed, TimeSpan.FromMilliseconds(elapsed.TotalMilliseconds / lossyWAV.SamplesProcessed * audioSource.Length) ); lastPrint = elapsed; } - } while (true); + } TimeSpan totalElapsed = DateTime.Now - start; Console.Error.Write("\r \r"); Console.WriteLine("Results : {0:0.0000} bits; {1:0.00}x; {2}", - (1.0 * lossyWAV.OverallBitsRemoved) / audioSource.ChannelCount / lossyWAV.BlocksProcessed, - lossyWAV.SamplesProcessed / totalElapsed.TotalSeconds / audioSource.SampleRate, + (1.0 * lossyWAV.OverallBitsRemoved) / audioSource.PCM.ChannelCount / lossyWAV.BlocksProcessed, + lossyWAV.SamplesProcessed / totalElapsed.TotalSeconds / audioSource.PCM.SampleRate, totalElapsed ); audioSource.Close(); diff --git a/MAC_SDK/Source/MACLib/Assembly/Assembly.obj b/MAC_SDK/Source/MACLib/Assembly/Assembly.obj index 123adbe02bd1fc3f43ad689293c81ca4c70c1bdd..2917adcd18b56dc38c02992a48b8dc02e9f9f92a 100644 GIT binary patch delta 17 YcmX@Yc7%rHzrHTFu#eBgbPF05$Xls{jB1 delta 17 YcmaFO`I?g>rHzq6$H~)cBgbPF05o3(eE none true - . + ..\bin\any\Release\ prompt 4 . diff --git a/UnRarDotNet/UnRarDotNet.csproj b/UnRarDotNet/UnRarDotNet.csproj index a15809d..48bdfdd 100644 --- a/UnRarDotNet/UnRarDotNet.csproj +++ b/UnRarDotNet/UnRarDotNet.csproj @@ -22,7 +22,7 @@ pdbonly true - bin\Release\ + ..\bin\any\Release\ TRACE prompt 4