diff --git a/CUETools.Codecs.ALAC/ALACDotNet.cs b/CUETools.Codecs.ALAC/ALACDotNet.cs index e695f27..ef026c7 100644 --- a/CUETools.Codecs.ALAC/ALACDotNet.cs +++ b/CUETools.Codecs.ALAC/ALACDotNet.cs @@ -59,6 +59,8 @@ namespace CUETools.Codecs.ALAC _framesBuffer = new byte[65536]; } + public AudioDecoderSettings Settings { get { return null; } } + private void InitTables() { if (_predicterror_buffer_a != null) diff --git a/CUETools.Codecs.APE/CUETools.Codecs.APE.cpp b/CUETools.Codecs.APE/CUETools.Codecs.APE.cpp index 63df7b1..0a2e422 100644 --- a/CUETools.Codecs.APE/CUETools.Codecs.APE.cpp +++ b/CUETools.Codecs.APE/CUETools.Codecs.APE.cpp @@ -230,6 +230,12 @@ namespace CUETools { namespace Codecs { namespace APE { return buff->Length; } + virtual property AudioDecoderSettings^ Settings { + AudioDecoderSettings^ get(void) { + return nullptr; + } + } + private: IAPEDecompress * pAPEDecompress; diff --git a/CUETools.Codecs.BDLPCM/BDLPCMReader.cs b/CUETools.Codecs.BDLPCM/BDLPCMReader.cs index 23e5e2f..20cab6e 100644 --- a/CUETools.Codecs.BDLPCM/BDLPCMReader.cs +++ b/CUETools.Codecs.BDLPCM/BDLPCMReader.cs @@ -14,13 +14,15 @@ namespace CUETools.Codecs.BDLPCM _IO = IO != null ? IO : new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, 0x10000); streams = new Dictionary(); frameBuffer = new byte[192]; - streamId = 0; demuxer_channel = 0; _samplePos = 0; _sampleLen = -1; demux_ts_packets(null, 0); + settings = new BDLPCMReaderSettings(); } + public AudioDecoderSettings Settings { get { return settings; } } + public void Close() { //if (_br != null) @@ -47,31 +49,6 @@ namespace CUETools.Codecs.BDLPCM } } - public unsafe int StreamId - { - get - { - return streamId; - } - set - { - streamId = value; - chosenStream = null; - foreach (var s in streams) - { - if (s.Value.is_opened && s.Value.streamId == streamId) - { - chosenStream = s.Value; - if (chosenStream.pcm == null) - { - demux_ts_packets(null, 0); - } - break; - } - } - } - } - public unsafe int StreamIds { get @@ -101,13 +78,37 @@ namespace CUETools.Codecs.BDLPCM } } - public AudioPCMConfig PCM { get { return chosenStream.pcm; } } + public unsafe AudioPCMConfig PCM + { + get { + if (chosenStream == null) + { + if (settings.Stream != null) + { + foreach (var s in streams) + { + if (s.Value.is_opened && s.Value.streamId.ToString() == settings.Stream) + { + chosenStream = s.Value; + if (chosenStream.pcm == null) + { + demux_ts_packets(null, 0); + } + return chosenStream.pcm; + } + } + } + + throw new Exception("multiple streams present, please specify"); + } + return chosenStream.pcm; + } + } public string Path { get { return _path; } } public unsafe int Read(AudioBuffer buff, int maxLength) { - if (chosenStream == null) throw new InvalidOperationException("chosenStream == null"); buff.Prepare(this, maxLength); int sampleCount; fixed (byte* dest = &buff.Bytes[0]) @@ -164,7 +165,7 @@ namespace CUETools.Codecs.BDLPCM TsStream s; demux_ts_packet(fr, out s); int dataLen = (int) fr.Length; - if (dataLen > 0 && s != null) + if (dataLen > 0 && s != null && (chosenStream == null || s == chosenStream)) { int dataOffset = (int)(fr.Ptr - ptr); if (s.savedBufferSize > 0) @@ -687,7 +688,7 @@ namespace CUETools.Codecs.BDLPCM // } //} - if (s.is_opened && streamId == s.streamId) + if (s.is_opened) { if (s.at_packet_header) { @@ -706,8 +707,8 @@ namespace CUETools.Codecs.BDLPCM byte[] frameBuffer; int demuxer_channel; - int streamId; TsStream chosenStream; long _samplePos, _sampleLen; + BDLPCMReaderSettings settings; } } diff --git a/CUETools.Codecs.BDLPCM/BDLPCMReaderSettings.cs b/CUETools.Codecs.BDLPCM/BDLPCMReaderSettings.cs new file mode 100644 index 0000000..69ce9b5 --- /dev/null +++ b/CUETools.Codecs.BDLPCM/BDLPCMReaderSettings.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Text; + +namespace CUETools.Codecs.BDLPCM +{ + public class BDLPCMReaderSettings : AudioDecoderSettings + { + public BDLPCMReaderSettings() + { + } + + [Browsable(false)] + public string Stream { get; set; } + } +} diff --git a/CUETools.Codecs.BDLPCM/CUETools.Codecs.BDLPCM.csproj b/CUETools.Codecs.BDLPCM/CUETools.Codecs.BDLPCM.csproj index 8e9e8fb..4ce9da8 100644 --- a/CUETools.Codecs.BDLPCM/CUETools.Codecs.BDLPCM.csproj +++ b/CUETools.Codecs.BDLPCM/CUETools.Codecs.BDLPCM.csproj @@ -60,6 +60,7 @@ + diff --git a/CUETools.Codecs.FLAC/CUETools.Codecs.FLAC.cpp b/CUETools.Codecs.FLAC/CUETools.Codecs.FLAC.cpp index d4d9467..4a712d9 100644 --- a/CUETools.Codecs.FLAC/CUETools.Codecs.FLAC.cpp +++ b/CUETools.Codecs.FLAC/CUETools.Codecs.FLAC.cpp @@ -284,6 +284,12 @@ namespace CUETools { namespace Codecs { namespace FLAC { return buff->Length; } + virtual property AudioDecoderSettings^ Settings { + AudioDecoderSettings^ get(void) { + return nullptr; + } + } + private: DecoderWriteDelegate^ _writeDel; DecoderMetadataDelegate^ _metadataDel; diff --git a/CUETools.Codecs.FLAKE/FlakeReader.cs b/CUETools.Codecs.FLAKE/FlakeReader.cs index 256d64e..2c0c1e2 100644 --- a/CUETools.Codecs.FLAKE/FlakeReader.cs +++ b/CUETools.Codecs.FLAKE/FlakeReader.cs @@ -118,7 +118,9 @@ namespace CUETools.Codecs.FLAKE framereader = new BitReader(); } - public void Close() + public AudioDecoderSettings Settings { get { return null; } } + + public void Close() { _IO.Close(); } diff --git a/CUETools.Codecs.LossyWAV/LossyWAVReader.cs b/CUETools.Codecs.LossyWAV/LossyWAVReader.cs index 9e32f79..d628a39 100644 --- a/CUETools.Codecs.LossyWAV/LossyWAVReader.cs +++ b/CUETools.Codecs.LossyWAV/LossyWAVReader.cs @@ -10,6 +10,8 @@ namespace CUETools.Codecs.LossyWAV private AudioBuffer lwcdfBuffer; private double scaling_factor; + public AudioDecoderSettings Settings { get { return null; } } + public long Length { get diff --git a/CUETools.Codecs.TTA/CUETools.Codecs.TTA.cpp b/CUETools.Codecs.TTA/CUETools.Codecs.TTA.cpp index f9a7e75..7de2282 100644 --- a/CUETools.Codecs.TTA/CUETools.Codecs.TTA.cpp +++ b/CUETools.Codecs.TTA/CUETools.Codecs.TTA.cpp @@ -187,6 +187,12 @@ namespace TTA { return buff->Length; } + virtual property AudioDecoderSettings^ Settings { + AudioDecoderSettings^ get(void) { + return nullptr; + } + } + private: Int64 _sampleCount, _sampleOffset; AudioPCMConfig^ pcm; diff --git a/CUETools.Codecs.WMA/WMAReader.cs b/CUETools.Codecs.WMA/WMAReader.cs index fc953d5..fde3332 100644 --- a/CUETools.Codecs.WMA/WMAReader.cs +++ b/CUETools.Codecs.WMA/WMAReader.cs @@ -221,6 +221,8 @@ namespace CUETools.Codecs.WMA //m_syncReader.GetMaxOutputSampleSize(m_dwAudioOutputNum, out cbMax); } + public AudioDecoderSettings Settings { get { return null; } } + public void isValid(string filename) { int pdwDataSize = 0; diff --git a/CUETools.Codecs.WavPack/CUETools.Codecs.WavPack.cpp b/CUETools.Codecs.WavPack/CUETools.Codecs.WavPack.cpp index 197baa1..d9ee625 100644 --- a/CUETools.Codecs.WavPack/CUETools.Codecs.WavPack.cpp +++ b/CUETools.Codecs.WavPack/CUETools.Codecs.WavPack.cpp @@ -185,6 +185,12 @@ namespace CUETools { namespace Codecs { namespace WavPack { return sampleBuffer->Length; } + virtual property AudioDecoderSettings^ Settings { + AudioDecoderSettings^ get(void) { + return nullptr; + } + } + private: WavpackContext *_wpc; Int32 _sampleCount, _sampleOffset; diff --git a/CUETools.Codecs/AudioDecoderSettings.cs b/CUETools.Codecs/AudioDecoderSettings.cs new file mode 100644 index 0000000..9481f1b --- /dev/null +++ b/CUETools.Codecs/AudioDecoderSettings.cs @@ -0,0 +1,39 @@ +using System; +using System.ComponentModel; +using System.Collections.Generic; +using System.Xml.Serialization; +using System.Text; + +namespace CUETools.Codecs +{ + public class AudioDecoderSettings + { + public AudioDecoderSettings() + { + // Iterate through each property and call ResetValue() + foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(this)) + property.ResetValue(this); + } + + public AudioDecoderSettings Clone() + { + return this.MemberwiseClone() as AudioDecoderSettings; + } + + public bool HasBrowsableAttributes() + { + bool hasBrowsable = false; + foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(this)) + { + bool isBrowsable = true; + foreach (var attribute in property.Attributes) + { + var browsable = attribute as BrowsableAttribute; + isBrowsable &= browsable == null || browsable.Browsable; + } + hasBrowsable |= isBrowsable; + } + return hasBrowsable; + } + } +} diff --git a/CUETools.Codecs/AudioPipe.cs b/CUETools.Codecs/AudioPipe.cs index d98d454..ed871e6 100644 --- a/CUETools.Codecs/AudioPipe.cs +++ b/CUETools.Codecs/AudioPipe.cs @@ -18,6 +18,8 @@ namespace CUETools.Codecs private bool own; private ThreadPriority priority; + public AudioDecoderSettings Settings { get { return null; } } + public long Position { get diff --git a/CUETools.Codecs/CUETools.Codecs.csproj b/CUETools.Codecs/CUETools.Codecs.csproj index 21650f4..f625548 100644 --- a/CUETools.Codecs/CUETools.Codecs.csproj +++ b/CUETools.Codecs/CUETools.Codecs.csproj @@ -64,6 +64,7 @@ + diff --git a/CUETools.Codecs/CUEToolsCodecsConfig.cs b/CUETools.Codecs/CUEToolsCodecsConfig.cs index 0f78431..4450f51 100644 --- a/CUETools.Codecs/CUEToolsCodecsConfig.cs +++ b/CUETools.Codecs/CUEToolsCodecsConfig.cs @@ -72,6 +72,7 @@ namespace CUETools.Codecs formats.Add("wv", new CUEToolsFormat("wv", CUEToolsTagger.TagLibSharp, true, false, true, true, encoders.GetDefault("wv", true), null, decoders.GetDefault("wv", true))); formats.Add("ape", new CUEToolsFormat("ape", CUEToolsTagger.TagLibSharp, true, false, true, true, encoders.GetDefault("ape", true), null, decoders.GetDefault("ape", true))); formats.Add("tta", new CUEToolsFormat("tta", CUEToolsTagger.APEv2, true, false, false, true, encoders.GetDefault("tta", true), null, decoders.GetDefault("tta", true))); + formats.Add("m2ts", new CUEToolsFormat("m2ts", CUEToolsTagger.APEv2, true, false, false, true, null, null, decoders.GetDefault("m2ts", true))); formats.Add("wav", new CUEToolsFormat("wav", CUEToolsTagger.TagLibSharp, true, false, false, true, encoders.GetDefault("wav", true), null, decoders.GetDefault("wav", true))); formats.Add("m4a", new CUEToolsFormat("m4a", CUEToolsTagger.TagLibSharp, true, true, false, true, encoders.GetDefault("m4a", true), encoders.GetDefault("m4a", false), decoders.GetDefault("m4a", true))); formats.Add("tak", new CUEToolsFormat("tak", CUEToolsTagger.APEv2, true, false, true, true, encoders.GetDefault("tak", true), null, decoders.GetDefault("tak", true))); diff --git a/CUETools.Codecs/IAudioSource.cs b/CUETools.Codecs/IAudioSource.cs index 2d9c3b1..3d7d337 100644 --- a/CUETools.Codecs/IAudioSource.cs +++ b/CUETools.Codecs/IAudioSource.cs @@ -2,6 +2,8 @@ { public interface IAudioSource { + AudioDecoderSettings Settings { get; } + AudioPCMConfig PCM { get; } string Path { get; } diff --git a/CUETools.Codecs/SilenceGenerator.cs b/CUETools.Codecs/SilenceGenerator.cs index 0c8d74e..53999b3 100644 --- a/CUETools.Codecs/SilenceGenerator.cs +++ b/CUETools.Codecs/SilenceGenerator.cs @@ -6,6 +6,8 @@ private AudioPCMConfig pcm; private int _sampleVal; + public AudioDecoderSettings Settings { get { return null; } } + public long Length { get { return _sampleCount; } diff --git a/CUETools.Codecs/UserDefinedReader.cs b/CUETools.Codecs/UserDefinedReader.cs index 8f4ef8c..d0021fb 100644 --- a/CUETools.Codecs/UserDefinedReader.cs +++ b/CUETools.Codecs/UserDefinedReader.cs @@ -10,6 +10,8 @@ namespace CUETools.Codecs Process _decoderProcess; WAVReader rdr; + public AudioDecoderSettings Settings { get { return null; } } + public long Position { get diff --git a/CUETools.Codecs/WAVReader.cs b/CUETools.Codecs/WAVReader.cs index fce796b..b8636b2 100644 --- a/CUETools.Codecs/WAVReader.cs +++ b/CUETools.Codecs/WAVReader.cs @@ -14,6 +14,8 @@ namespace CUETools.Codecs bool _largeFile; string _path; + public AudioDecoderSettings Settings { get { return null; } } + public long Position { get diff --git a/CUETools.Converter/Program.cs b/CUETools.Converter/Program.cs index ea5d188..f9837fe 100644 --- a/CUETools.Converter/Program.cs +++ b/CUETools.Converter/Program.cs @@ -1,4 +1,5 @@ using System; +using System.ComponentModel; using System.Collections.Generic; using System.IO; using CUETools.Codecs; @@ -81,6 +82,7 @@ namespace CUETools.Converter string encoderFormat = null; bool ignore_chunk_sizes = false; AudioEncoderType audioEncoderType = AudioEncoderType.NoAudio; + var decoderOptions = new Dictionary(); for (int arg = 0; arg < args.Length; arg++) { @@ -90,6 +92,12 @@ namespace CUETools.Converter ignore_chunk_sizes = true; else if (args[arg] == "--decoder" && ++arg < args.Length) decoderName = args[arg]; + else if (args[arg] == "--decoder-option" && arg + 2 < args.Length) + { + var optionName = args[++arg]; + var optionValue = args[++arg]; + decoderOptions.Add(optionName, optionValue); + } else if (args[arg] == "--encoder" && ++arg < args.Length) encoderName = args[arg]; else if (args[arg] == "--encoder-format" && ++arg < args.Length) @@ -143,6 +151,17 @@ namespace CUETools.Converter try { audioSource = Program.GetAudioSource(config, sourceFile, decoderName, ignore_chunk_sizes); + foreach (var decOpt in decoderOptions) + { + var decoderSettings = audioSource.Settings; + if (decoderSettings == null) + throw new Exception(String.Format("{0} doesn't have any properties.", audioSource.GetType().Name)); + var property = TypeDescriptor.GetProperties(decoderSettings).Find(decOpt.Key, true); + if (property == null) + throw new Exception(String.Format("{0} doesn't have a property named {1}.", audioSource.GetType().Name, decOpt.Key)); + property.SetValue(decoderSettings, decOpt.Value); + } + AudioBuffer buff = new AudioBuffer(audioSource, 0x10000); Console.Error.WriteLine("Filename : {0}", sourceFile); Console.Error.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)); diff --git a/CUETools.DSP.Mixer/MixingSource.cs b/CUETools.DSP.Mixer/MixingSource.cs index 5812758..01da099 100644 --- a/CUETools.DSP.Mixer/MixingSource.cs +++ b/CUETools.DSP.Mixer/MixingSource.cs @@ -17,6 +17,8 @@ namespace CUETools.DSP.Mixer private int mixoffs = 0; private int current = 0; + public AudioDecoderSettings Settings { get { return null; } } + public void Close() { } diff --git a/CUETools.Processor/CUESheetAudio.cs b/CUETools.Processor/CUESheetAudio.cs index 34590d1..4d3edd0 100644 --- a/CUETools.Processor/CUESheetAudio.cs +++ b/CUETools.Processor/CUESheetAudio.cs @@ -11,6 +11,8 @@ namespace CUETools.Processor private long nextPos; private long _samplePos, _sampleLen; + public AudioDecoderSettings Settings { get { return null; } } + public long Length { get { return _sampleLen; } diff --git a/CUETools.Ripper.SCSI/SCSIDrive.cs b/CUETools.Ripper.SCSI/SCSIDrive.cs index 3452b80..42f2525 100644 --- a/CUETools.Ripper.SCSI/SCSIDrive.cs +++ b/CUETools.Ripper.SCSI/SCSIDrive.cs @@ -77,7 +77,9 @@ namespace CUETools.Ripper.SCSI private ReadProgressArgs progressArgs = new ReadProgressArgs(); public event EventHandler ReadProgress; - public CDImageLayout TOC + public AudioDecoderSettings Settings { get { return null; } } + + public CDImageLayout TOC { get { diff --git a/CUETools.TestHelpers/NoiseAndErrorsGenerator.cs b/CUETools.TestHelpers/NoiseAndErrorsGenerator.cs index 31e67cc..23d31fe 100644 --- a/CUETools.TestHelpers/NoiseAndErrorsGenerator.cs +++ b/CUETools.TestHelpers/NoiseAndErrorsGenerator.cs @@ -49,6 +49,8 @@ namespace CUETools.TestHelpers this.nextError = 0; } + public AudioDecoderSettings Settings { get { return null; } } + public NoiseAndErrorsGenerator(long sampleCount) : this(AudioPCMConfig.RedBook, sampleCount, 0, 0, 0) { diff --git a/CUETools/CUETools.sln b/CUETools/CUETools.sln index c9c3534..aef8a66 100644 --- a/CUETools/CUETools.sln +++ b/CUETools/CUETools.sln @@ -180,6 +180,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WindowsMediaLib", "..\Windo EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CUETools.Codecs.WMA", "..\CUETools.Codecs.WMA\CUETools.Codecs.WMA.csproj", "{082D6B9E-326E-4D15-9798-DE70A6EDAE9E}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CUETools.Codecs.BDLPCM", "..\CUETools.Codecs.BDLPCM\CUETools.Codecs.BDLPCM.csproj", "{E75F7CCD-4266-42E1-A039-DC7EB5EDD8F6}" +EndProject Global GlobalSection(TestCaseManagementSettings) = postSolution CategoryFile = CUETools1.vsmdi @@ -1075,6 +1077,20 @@ Global {082D6B9E-326E-4D15-9798-DE70A6EDAE9E}.Release|Win32.ActiveCfg = Release|Any CPU {082D6B9E-326E-4D15-9798-DE70A6EDAE9E}.Release|x64.ActiveCfg = Release|Any CPU {082D6B9E-326E-4D15-9798-DE70A6EDAE9E}.Release|x86.ActiveCfg = Release|Any CPU + {E75F7CCD-4266-42E1-A039-DC7EB5EDD8F6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E75F7CCD-4266-42E1-A039-DC7EB5EDD8F6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E75F7CCD-4266-42E1-A039-DC7EB5EDD8F6}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {E75F7CCD-4266-42E1-A039-DC7EB5EDD8F6}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {E75F7CCD-4266-42E1-A039-DC7EB5EDD8F6}.Debug|Win32.ActiveCfg = Debug|Any CPU + {E75F7CCD-4266-42E1-A039-DC7EB5EDD8F6}.Debug|x64.ActiveCfg = Debug|Any CPU + {E75F7CCD-4266-42E1-A039-DC7EB5EDD8F6}.Debug|x86.ActiveCfg = Debug|Any CPU + {E75F7CCD-4266-42E1-A039-DC7EB5EDD8F6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E75F7CCD-4266-42E1-A039-DC7EB5EDD8F6}.Release|Any CPU.Build.0 = Release|Any CPU + {E75F7CCD-4266-42E1-A039-DC7EB5EDD8F6}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {E75F7CCD-4266-42E1-A039-DC7EB5EDD8F6}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {E75F7CCD-4266-42E1-A039-DC7EB5EDD8F6}.Release|Win32.ActiveCfg = Release|Any CPU + {E75F7CCD-4266-42E1-A039-DC7EB5EDD8F6}.Release|x64.ActiveCfg = Release|Any CPU + {E75F7CCD-4266-42E1-A039-DC7EB5EDD8F6}.Release|x86.ActiveCfg = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1111,6 +1127,7 @@ Global {1AF02E2C-2CB2-44B5-B417-37653071FEC6} = {93B7AE1D-DEF6-4A04-A222-5CDE09DF262D} {DFE55765-564C-4B8F-993B-A94C4D1C212E} = {93B7AE1D-DEF6-4A04-A222-5CDE09DF262D} {082D6B9E-326E-4D15-9798-DE70A6EDAE9E} = {93B7AE1D-DEF6-4A04-A222-5CDE09DF262D} + {E75F7CCD-4266-42E1-A039-DC7EB5EDD8F6} = {93B7AE1D-DEF6-4A04-A222-5CDE09DF262D} {04945FB2-8410-4F14-8262-2ED18DCDACD6} = {D9D97BB6-002F-4858-8EF2-49B4C4C4DDB4} {A430AD28-B76A-4ED0-AF7D-D13B8969297F} = {D9D97BB6-002F-4858-8EF2-49B4C4C4DDB4} {5C8B61C0-BC3D-4316-B8A7-419D55BB5796} = {D9D97BB6-002F-4858-8EF2-49B4C4C4DDB4}