mirror of
https://github.com/claunia/cuetools.net.git
synced 2025-12-16 18:14:25 +00:00
Code cleanup; Reader classes renamed to Decoders, Writers to Encoders, every Decoder must have a corresponding Settings class now just like Encoders. UserDefinedEncoders renamed to CommandLineEncoders, etc.
This commit is contained in:
@@ -12,15 +12,15 @@ namespace CUETools.Codecs
|
||||
public class CUEToolsCodecsConfig
|
||||
{
|
||||
public Dictionary<string, CUEToolsFormat> formats;
|
||||
public CUEToolsUDCEncoderList encoders;
|
||||
public CUEToolsUDCDecoderList decoders;
|
||||
public EncoderListViewModel encoders;
|
||||
public DecoderListViewModel decoders;
|
||||
|
||||
public CUEToolsCodecsConfig(CUEToolsCodecsConfig src)
|
||||
{
|
||||
encoders = new CUEToolsUDCEncoderList();
|
||||
encoders = new EncoderListViewModel();
|
||||
foreach (var enc in src.encoders)
|
||||
encoders.Add(enc.Clone());
|
||||
decoders = new CUEToolsUDCDecoderList();
|
||||
decoders = new DecoderListViewModel();
|
||||
foreach (var dec in src.decoders)
|
||||
decoders.Add(dec.Clone());
|
||||
formats = new Dictionary<string, CUEToolsFormat>();
|
||||
@@ -30,7 +30,7 @@ namespace CUETools.Codecs
|
||||
|
||||
public CUEToolsCodecsConfig(List<Type> encs, List<Type> decs)
|
||||
{
|
||||
encoders = new CUEToolsUDCEncoderList();
|
||||
encoders = new EncoderListViewModel();
|
||||
foreach (Type type in encs)
|
||||
foreach (AudioEncoderClassAttribute enc in Attribute.GetCustomAttributes(type, typeof(AudioEncoderClassAttribute)))
|
||||
try
|
||||
@@ -42,7 +42,7 @@ namespace CUETools.Codecs
|
||||
System.Diagnostics.Trace.WriteLine(ex.Message);
|
||||
}
|
||||
|
||||
decoders = new CUEToolsUDCDecoderList();
|
||||
decoders = new DecoderListViewModel();
|
||||
foreach (Type type in decs)
|
||||
foreach (AudioDecoderClassAttribute dec in Attribute.GetCustomAttributes(type, typeof(AudioDecoderClassAttribute)))
|
||||
try
|
||||
@@ -66,8 +66,8 @@ namespace CUETools.Codecs
|
||||
encoders.Add(new AudioEncoderSettingsViewModel("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"));
|
||||
encoders.Add(new AudioEncoderSettingsViewModel("qaac tvbr", "m4a", false, "10 20 30 40 50 60 70 80 90 100 110 127", "80", "qaac.exe", "-s -V %M -q 2 - -o %O"));
|
||||
|
||||
decoders.Add(new AudioDecoderSettingsViewModel(new CommandLineDecoderSettings("takc", "tak", "takc.exe", "-d %I -")));
|
||||
decoders.Add(new AudioDecoderSettingsViewModel(new CommandLineDecoderSettings("ffmpeg alac", "m4a", "ffmpeg.exe", "-v 0 -i %I -f wav -")));
|
||||
decoders.Add(new AudioDecoderSettingsViewModel(new CommandLine.DecoderSettings("takc", "tak", "takc.exe", "-d %I -")));
|
||||
decoders.Add(new AudioDecoderSettingsViewModel(new CommandLine.DecoderSettings("ffmpeg alac", "m4a", "ffmpeg.exe", "-v 0 -i %I -f wav -")));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -1,271 +0,0 @@
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace CUETools.Codecs
|
||||
{
|
||||
[JsonObject(MemberSerialization.OptIn)]
|
||||
public class AudioEncoderSettingsViewModel : INotifyPropertyChanged
|
||||
{
|
||||
[JsonProperty]
|
||||
public AudioEncoderSettings settings = null;
|
||||
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
[JsonConstructor]
|
||||
private AudioEncoderSettingsViewModel()
|
||||
{
|
||||
}
|
||||
|
||||
public AudioEncoderSettingsViewModel(
|
||||
string _name,
|
||||
string _extension,
|
||||
bool _lossless,
|
||||
string _supported_modes,
|
||||
string _default_mode,
|
||||
string _path,
|
||||
string _parameters
|
||||
)
|
||||
{
|
||||
settings = new CommandLineEncoderSettings() { name = _name, extension = _extension, SupportedModes = _supported_modes, EncoderMode = _default_mode, Path = _path, Parameters = _parameters, lossless = _lossless };
|
||||
}
|
||||
|
||||
public AudioEncoderSettingsViewModel(AudioEncoderClassAttribute enc)
|
||||
{
|
||||
settings = Activator.CreateInstance(enc.Settings) as AudioEncoderSettings;
|
||||
if (settings == null)
|
||||
throw new InvalidOperationException("invalid codec");
|
||||
}
|
||||
|
||||
public AudioEncoderSettingsViewModel Clone()
|
||||
{
|
||||
var res = this.MemberwiseClone() as AudioEncoderSettingsViewModel;
|
||||
if (settings != null) res.settings = settings.Clone();
|
||||
return res;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Name;
|
||||
}
|
||||
|
||||
public string FullName => Name + " [" + Extension + "]";
|
||||
|
||||
public string Path
|
||||
{
|
||||
get
|
||||
{
|
||||
if (settings is CommandLineEncoderSettings)
|
||||
return (settings as CommandLineEncoderSettings).Path;
|
||||
return "";
|
||||
}
|
||||
set
|
||||
{
|
||||
var settings = this.settings as CommandLineEncoderSettings;
|
||||
if (settings == null) throw new InvalidOperationException();
|
||||
settings.Path = value;
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Path"));
|
||||
}
|
||||
}
|
||||
|
||||
public string Parameters
|
||||
{
|
||||
get
|
||||
{
|
||||
if (settings is CommandLineEncoderSettings)
|
||||
return (settings as CommandLineEncoderSettings).Parameters;
|
||||
return "";
|
||||
}
|
||||
set
|
||||
{
|
||||
var settings = this.settings as CommandLineEncoderSettings;
|
||||
if (settings == null) throw new InvalidOperationException();
|
||||
settings.Parameters = value;
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Parameters"));
|
||||
}
|
||||
}
|
||||
|
||||
public bool Lossless
|
||||
{
|
||||
get => settings.Lossless;
|
||||
set
|
||||
{
|
||||
var settings = this.settings as CommandLineEncoderSettings;
|
||||
if (settings == null) throw new InvalidOperationException();
|
||||
settings.lossless = value;
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Lossless"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public string Name
|
||||
{
|
||||
get => settings.Name;
|
||||
set
|
||||
{
|
||||
var settings = this.settings as CommandLineEncoderSettings;
|
||||
if (settings == null) throw new InvalidOperationException();
|
||||
settings.name = value;
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Name"));
|
||||
}
|
||||
}
|
||||
|
||||
public string Extension
|
||||
{
|
||||
get => settings.Extension;
|
||||
set
|
||||
{
|
||||
var settings = this.settings as CommandLineEncoderSettings;
|
||||
if (settings == null) throw new InvalidOperationException();
|
||||
settings.extension = value;
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Extension"));
|
||||
}
|
||||
}
|
||||
|
||||
public string DotExtension => "." + Extension;
|
||||
|
||||
public string SupportedModesStr
|
||||
{
|
||||
get
|
||||
{
|
||||
string defaultMode;
|
||||
return this.settings.GetSupportedModes(out defaultMode);
|
||||
}
|
||||
set
|
||||
{
|
||||
var settings = this.settings as CommandLineEncoderSettings;
|
||||
if (settings == null) throw new InvalidOperationException();
|
||||
settings.SupportedModes = value;
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("SupportedModesStr"));
|
||||
}
|
||||
}
|
||||
|
||||
public string[] SupportedModes => this.SupportedModesStr.Split(' ');
|
||||
|
||||
public int EncoderModeIndex
|
||||
{
|
||||
get
|
||||
{
|
||||
string[] modes = this.SupportedModes;
|
||||
if (modes == null || modes.Length < 2)
|
||||
return -1;
|
||||
for (int i = 0; i < modes.Length; i++)
|
||||
if (modes[i] == this.settings.EncoderMode)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
public bool CanBeDeleted => settings is CommandLineEncoderSettings;
|
||||
|
||||
public bool IsValid =>
|
||||
(settings != null)
|
||||
&& (settings is CommandLineEncoderSettings ? (settings as CommandLineEncoderSettings).Path != "" : true);
|
||||
}
|
||||
|
||||
[JsonObject(MemberSerialization.OptIn)]
|
||||
public class AudioDecoderSettingsViewModel : INotifyPropertyChanged
|
||||
{
|
||||
[JsonProperty]
|
||||
public AudioDecoderSettings decoderSettings = null;
|
||||
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
[JsonConstructor]
|
||||
private AudioDecoderSettingsViewModel()
|
||||
{
|
||||
}
|
||||
|
||||
public AudioDecoderSettingsViewModel(AudioDecoderSettings settings)
|
||||
{
|
||||
decoderSettings = settings;
|
||||
}
|
||||
|
||||
public AudioDecoderSettingsViewModel Clone()
|
||||
{
|
||||
var res = this.MemberwiseClone() as AudioDecoderSettingsViewModel;
|
||||
if (decoderSettings != null) res.decoderSettings = decoderSettings.Clone();
|
||||
return res;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Name;
|
||||
}
|
||||
|
||||
public string FullName => Name + " [" + Extension + "]";
|
||||
|
||||
public string Path
|
||||
{
|
||||
get
|
||||
{
|
||||
if (decoderSettings is CommandLineDecoderSettings)
|
||||
return (decoderSettings as CommandLineDecoderSettings).Path;
|
||||
return "";
|
||||
}
|
||||
set
|
||||
{
|
||||
if (decoderSettings is CommandLineDecoderSettings)
|
||||
(decoderSettings as CommandLineDecoderSettings).Path = value;
|
||||
else throw new InvalidOperationException();
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Path"));
|
||||
}
|
||||
}
|
||||
public string Parameters
|
||||
{
|
||||
get
|
||||
{
|
||||
if (decoderSettings is CommandLineDecoderSettings)
|
||||
return (decoderSettings as CommandLineDecoderSettings).Parameters;
|
||||
return "";
|
||||
}
|
||||
set
|
||||
{
|
||||
if (decoderSettings is CommandLineDecoderSettings)
|
||||
(decoderSettings as CommandLineDecoderSettings).Parameters = value;
|
||||
else throw new InvalidOperationException();
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Parameters"));
|
||||
}
|
||||
}
|
||||
|
||||
public bool Lossless
|
||||
{
|
||||
get => true;
|
||||
set {
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
public string Name
|
||||
{
|
||||
get => decoderSettings.Name;
|
||||
set
|
||||
{
|
||||
if (decoderSettings is CommandLineDecoderSettings)
|
||||
(decoderSettings as CommandLineDecoderSettings).name = value;
|
||||
else throw new InvalidOperationException();
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Name"));
|
||||
}
|
||||
}
|
||||
|
||||
public string Extension
|
||||
{
|
||||
get => decoderSettings.Extension;
|
||||
set
|
||||
{
|
||||
if (decoderSettings is CommandLineDecoderSettings)
|
||||
(decoderSettings as CommandLineDecoderSettings).extension = value;
|
||||
else throw new InvalidOperationException();
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Extension"));
|
||||
}
|
||||
}
|
||||
|
||||
public string DotExtension => "." + Extension;
|
||||
|
||||
public bool CanBeDeleted => decoderSettings is CommandLineDecoderSettings;
|
||||
|
||||
public bool IsValid =>
|
||||
(decoderSettings != null)
|
||||
&& (decoderSettings is CommandLineDecoderSettings ? (decoderSettings as CommandLineDecoderSettings).Path != "" : true);
|
||||
}
|
||||
}
|
||||
@@ -1,88 +0,0 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace CUETools.Codecs
|
||||
{
|
||||
public class CUEToolsUDCEncoderList : BindingList<AudioEncoderSettingsViewModel>
|
||||
{
|
||||
public CUEToolsUDCEncoderList()
|
||||
: base()
|
||||
{
|
||||
AddingNew += OnAddingNew;
|
||||
}
|
||||
|
||||
private void OnAddingNew(object sender, AddingNewEventArgs e)
|
||||
{
|
||||
e.NewObject = new AudioEncoderSettingsViewModel("new", "wav", true, "", "", "", "");
|
||||
}
|
||||
|
||||
public bool TryGetValue(string extension, bool lossless, string name, out AudioEncoderSettingsViewModel result)
|
||||
{
|
||||
//result = this.Where(udc => udc.settings.Extension == extension && udc.settings.Lossless == lossless && udc.settings.Name == name).First();
|
||||
foreach (AudioEncoderSettingsViewModel udc in this)
|
||||
{
|
||||
if (udc.settings.Extension == extension && udc.settings.Lossless == lossless && udc.settings.Name == name)
|
||||
{
|
||||
result = udc;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
result = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
public AudioEncoderSettingsViewModel GetDefault(string extension, bool lossless)
|
||||
{
|
||||
AudioEncoderSettingsViewModel result = null;
|
||||
foreach (AudioEncoderSettingsViewModel udc in this)
|
||||
{
|
||||
if (udc.settings.Extension == extension && udc.settings.Lossless == lossless && (result == null || result.settings.Priority < udc.settings.Priority))
|
||||
{
|
||||
result = udc;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public class CUEToolsUDCDecoderList : BindingList<AudioDecoderSettingsViewModel>
|
||||
{
|
||||
public CUEToolsUDCDecoderList()
|
||||
: base()
|
||||
{
|
||||
AddingNew += OnAddingNew;
|
||||
}
|
||||
|
||||
private void OnAddingNew(object sender, AddingNewEventArgs e)
|
||||
{
|
||||
e.NewObject = new AudioDecoderSettingsViewModel(new CommandLineDecoderSettings("new", "wav", "", ""));
|
||||
}
|
||||
|
||||
public bool TryGetValue(string extension, bool lossless, string name, out AudioDecoderSettingsViewModel result)
|
||||
{
|
||||
foreach (AudioDecoderSettingsViewModel udc in this)
|
||||
{
|
||||
if (udc.decoderSettings.Extension == extension && udc.decoderSettings.Lossless == lossless && udc.decoderSettings.Name == name)
|
||||
{
|
||||
result = udc;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
result = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
public AudioDecoderSettingsViewModel GetDefault(string extension, bool lossless)
|
||||
{
|
||||
AudioDecoderSettingsViewModel result = null;
|
||||
foreach (AudioDecoderSettingsViewModel udc in this)
|
||||
{
|
||||
if (udc.decoderSettings.Extension == extension && udc.decoderSettings.Lossless == lossless && (result == null || result.decoderSettings.Priority < udc.decoderSettings.Priority))
|
||||
{
|
||||
result = udc;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,112 +1,112 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
|
||||
namespace CUETools.Codecs
|
||||
{
|
||||
public class CommandLineDecoder : IAudioSource
|
||||
{
|
||||
string _path;
|
||||
Process _decoderProcess;
|
||||
WAV.AudioDecoder rdr;
|
||||
|
||||
private CommandLineDecoderSettings m_settings;
|
||||
public AudioDecoderSettings Settings => m_settings;
|
||||
|
||||
public long Position
|
||||
{
|
||||
get
|
||||
{
|
||||
Initialize();
|
||||
return rdr.Position;
|
||||
}
|
||||
set
|
||||
{
|
||||
Initialize();
|
||||
rdr.Position = value;
|
||||
}
|
||||
}
|
||||
|
||||
public long Length
|
||||
{
|
||||
get
|
||||
{
|
||||
Initialize();
|
||||
return rdr.Length;
|
||||
}
|
||||
}
|
||||
|
||||
public long Remaining
|
||||
{
|
||||
get
|
||||
{
|
||||
Initialize();
|
||||
return rdr.Remaining;
|
||||
}
|
||||
}
|
||||
|
||||
public AudioPCMConfig PCM
|
||||
{
|
||||
get
|
||||
{
|
||||
Initialize();
|
||||
return rdr.PCM;
|
||||
}
|
||||
}
|
||||
|
||||
public string Path { get { return _path; } }
|
||||
|
||||
public CommandLineDecoder(CommandLineDecoderSettings settings, string path, Stream IO)
|
||||
{
|
||||
m_settings = settings;
|
||||
_path = path;
|
||||
_decoderProcess = null;
|
||||
rdr = null;
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
if (_decoderProcess != null)
|
||||
return;
|
||||
_decoderProcess = new Process();
|
||||
_decoderProcess.StartInfo.FileName = m_settings.Path;
|
||||
_decoderProcess.StartInfo.Arguments = m_settings.Parameters.Replace("%I", "\"" + _path + "\"");
|
||||
_decoderProcess.StartInfo.CreateNoWindow = true;
|
||||
_decoderProcess.StartInfo.RedirectStandardOutput = true;
|
||||
_decoderProcess.StartInfo.UseShellExecute = false;
|
||||
bool started = false;
|
||||
Exception ex = null;
|
||||
try
|
||||
{
|
||||
started = _decoderProcess.Start();
|
||||
if (started)
|
||||
_decoderProcess.PriorityClass = Process.GetCurrentProcess().PriorityClass;
|
||||
}
|
||||
catch (Exception _ex)
|
||||
{
|
||||
ex = _ex;
|
||||
}
|
||||
if (!started)
|
||||
{
|
||||
_decoderProcess = null;
|
||||
throw new Exception(m_settings.Path + ": " + (ex == null ? "please check the path" : ex.Message));
|
||||
}
|
||||
rdr = new WAV.AudioDecoder(new WAV.DecoderSettings(), _path, _decoderProcess.StandardOutput.BaseStream);
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
if (rdr != null)
|
||||
rdr.Close();
|
||||
if (_decoderProcess != null && !_decoderProcess.HasExited)
|
||||
try { _decoderProcess.Kill(); _decoderProcess.WaitForExit(); }
|
||||
catch { }
|
||||
}
|
||||
|
||||
public int Read(AudioBuffer buff, int maxLength)
|
||||
{
|
||||
Initialize();
|
||||
return rdr.Read(buff, maxLength);
|
||||
}
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
|
||||
namespace CUETools.Codecs.CommandLine
|
||||
{
|
||||
public class AudioDecoder : IAudioSource
|
||||
{
|
||||
string _path;
|
||||
Process _decoderProcess;
|
||||
WAV.AudioDecoder rdr;
|
||||
|
||||
private DecoderSettings m_settings;
|
||||
public AudioDecoderSettings Settings => m_settings;
|
||||
|
||||
public long Position
|
||||
{
|
||||
get
|
||||
{
|
||||
Initialize();
|
||||
return rdr.Position;
|
||||
}
|
||||
set
|
||||
{
|
||||
Initialize();
|
||||
rdr.Position = value;
|
||||
}
|
||||
}
|
||||
|
||||
public long Length
|
||||
{
|
||||
get
|
||||
{
|
||||
Initialize();
|
||||
return rdr.Length;
|
||||
}
|
||||
}
|
||||
|
||||
public long Remaining
|
||||
{
|
||||
get
|
||||
{
|
||||
Initialize();
|
||||
return rdr.Remaining;
|
||||
}
|
||||
}
|
||||
|
||||
public AudioPCMConfig PCM
|
||||
{
|
||||
get
|
||||
{
|
||||
Initialize();
|
||||
return rdr.PCM;
|
||||
}
|
||||
}
|
||||
|
||||
public string Path { get { return _path; } }
|
||||
|
||||
public AudioDecoder(DecoderSettings settings, string path, Stream IO)
|
||||
{
|
||||
m_settings = settings;
|
||||
_path = path;
|
||||
_decoderProcess = null;
|
||||
rdr = null;
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
if (_decoderProcess != null)
|
||||
return;
|
||||
_decoderProcess = new Process();
|
||||
_decoderProcess.StartInfo.FileName = m_settings.Path;
|
||||
_decoderProcess.StartInfo.Arguments = m_settings.Parameters.Replace("%I", "\"" + _path + "\"");
|
||||
_decoderProcess.StartInfo.CreateNoWindow = true;
|
||||
_decoderProcess.StartInfo.RedirectStandardOutput = true;
|
||||
_decoderProcess.StartInfo.UseShellExecute = false;
|
||||
bool started = false;
|
||||
Exception ex = null;
|
||||
try
|
||||
{
|
||||
started = _decoderProcess.Start();
|
||||
if (started)
|
||||
_decoderProcess.PriorityClass = Process.GetCurrentProcess().PriorityClass;
|
||||
}
|
||||
catch (Exception _ex)
|
||||
{
|
||||
ex = _ex;
|
||||
}
|
||||
if (!started)
|
||||
{
|
||||
_decoderProcess = null;
|
||||
throw new Exception(m_settings.Path + ": " + (ex == null ? "please check the path" : ex.Message));
|
||||
}
|
||||
rdr = new WAV.AudioDecoder(new WAV.DecoderSettings(), _path, _decoderProcess.StandardOutput.BaseStream);
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
if (rdr != null)
|
||||
rdr.Close();
|
||||
if (_decoderProcess != null && !_decoderProcess.HasExited)
|
||||
try { _decoderProcess.Kill(); _decoderProcess.WaitForExit(); }
|
||||
catch { }
|
||||
}
|
||||
|
||||
public int Read(AudioBuffer buff, int maxLength)
|
||||
{
|
||||
Initialize();
|
||||
return rdr.Read(buff, maxLength);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,137 +1,137 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
|
||||
namespace CUETools.Codecs
|
||||
{
|
||||
public class CommandLineEncoder : IAudioDest
|
||||
{
|
||||
string _path;
|
||||
Process _encoderProcess;
|
||||
WAV.AudioEncoder wrt;
|
||||
CyclicBuffer outputBuffer = null;
|
||||
bool useTempFile = false;
|
||||
string tempFile = null;
|
||||
long _finalSampleCount = -1;
|
||||
bool closed = false;
|
||||
|
||||
public long Position
|
||||
{
|
||||
get
|
||||
{
|
||||
return wrt.Position;
|
||||
}
|
||||
}
|
||||
|
||||
public long FinalSampleCount
|
||||
{
|
||||
set { _finalSampleCount = wrt.FinalSampleCount = value; }
|
||||
}
|
||||
|
||||
// !!!! Must not start the process in constructor, so that we can set CompressionLevel via Settings!
|
||||
private CommandLineEncoderSettings m_settings;
|
||||
public AudioEncoderSettings Settings => m_settings;
|
||||
|
||||
public string Path { get { return _path; } }
|
||||
|
||||
public CommandLineEncoder(CommandLineEncoderSettings settings, string path, Stream IO = null)
|
||||
{
|
||||
m_settings = settings;
|
||||
_path = path;
|
||||
useTempFile = m_settings.Parameters.Contains("%I");
|
||||
tempFile = path + ".tmp.wav";
|
||||
|
||||
_encoderProcess = new Process();
|
||||
_encoderProcess.StartInfo.FileName = m_settings.Path;
|
||||
_encoderProcess.StartInfo.Arguments = m_settings.Parameters.Replace("%O", "\"" + path + "\"").Replace("%M", m_settings.EncoderMode).Replace("%P", m_settings.Padding.ToString()).Replace("%I", "\"" + tempFile + "\"");
|
||||
_encoderProcess.StartInfo.CreateNoWindow = true;
|
||||
if (!useTempFile)
|
||||
_encoderProcess.StartInfo.RedirectStandardInput = true;
|
||||
_encoderProcess.StartInfo.UseShellExecute = false;
|
||||
if (!m_settings.Parameters.Contains("%O"))
|
||||
_encoderProcess.StartInfo.RedirectStandardOutput = true;
|
||||
if (useTempFile)
|
||||
{
|
||||
wrt = new WAV.AudioEncoder(new WAV.EncoderSettings(settings.PCM), tempFile);
|
||||
return;
|
||||
}
|
||||
bool started = false;
|
||||
Exception ex = null;
|
||||
try
|
||||
{
|
||||
started = _encoderProcess.Start();
|
||||
if (started)
|
||||
_encoderProcess.PriorityClass = Process.GetCurrentProcess().PriorityClass;
|
||||
}
|
||||
catch (Exception _ex)
|
||||
{
|
||||
ex = _ex;
|
||||
}
|
||||
if (!started)
|
||||
throw new Exception(m_settings.Path + ": " + (ex == null ? "please check the path" : ex.Message));
|
||||
if (_encoderProcess.StartInfo.RedirectStandardOutput)
|
||||
{
|
||||
Stream outputStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read);
|
||||
outputBuffer = new CyclicBuffer(2 * 1024 * 1024, _encoderProcess.StandardOutput.BaseStream, outputStream);
|
||||
}
|
||||
Stream inputStream = new CyclicBufferOutputStream(_encoderProcess.StandardInput.BaseStream, 128 * 1024);
|
||||
wrt = new WAV.AudioEncoder(new WAV.EncoderSettings(settings.PCM), path, inputStream);
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
if (closed)
|
||||
return;
|
||||
closed = true;
|
||||
wrt.Close();
|
||||
if (useTempFile && (_finalSampleCount < 0 || wrt.Position == _finalSampleCount))
|
||||
{
|
||||
bool started = false;
|
||||
Exception ex = null;
|
||||
try
|
||||
{
|
||||
started = _encoderProcess.Start();
|
||||
if (started)
|
||||
_encoderProcess.PriorityClass = Process.GetCurrentProcess().PriorityClass;
|
||||
}
|
||||
catch (Exception _ex)
|
||||
{
|
||||
ex = _ex;
|
||||
}
|
||||
if (!started)
|
||||
throw new Exception(m_settings.Path + ": " + (ex == null ? "please check the path" : ex.Message));
|
||||
}
|
||||
wrt = null;
|
||||
if (!_encoderProcess.HasExited)
|
||||
_encoderProcess.WaitForExit();
|
||||
if (useTempFile)
|
||||
File.Delete(tempFile);
|
||||
if (outputBuffer != null)
|
||||
outputBuffer.Close();
|
||||
if (_encoderProcess.ExitCode != 0)
|
||||
throw new Exception(String.Format("{0} returned error code {1}", m_settings.Path, _encoderProcess.ExitCode));
|
||||
}
|
||||
|
||||
public void Delete()
|
||||
{
|
||||
Close();
|
||||
File.Delete(_path);
|
||||
}
|
||||
|
||||
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}", m_settings.Path, _encoderProcess.ExitCode), ex);
|
||||
else
|
||||
throw ex;
|
||||
}
|
||||
//_sampleLen += sampleCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
|
||||
namespace CUETools.Codecs.CommandLine
|
||||
{
|
||||
public class AudioEncoder : IAudioDest
|
||||
{
|
||||
string _path;
|
||||
Process _encoderProcess;
|
||||
WAV.AudioEncoder wrt;
|
||||
CyclicBuffer outputBuffer = null;
|
||||
bool useTempFile = false;
|
||||
string tempFile = null;
|
||||
long _finalSampleCount = -1;
|
||||
bool closed = false;
|
||||
|
||||
public long Position
|
||||
{
|
||||
get
|
||||
{
|
||||
return wrt.Position;
|
||||
}
|
||||
}
|
||||
|
||||
public long FinalSampleCount
|
||||
{
|
||||
set { _finalSampleCount = wrt.FinalSampleCount = value; }
|
||||
}
|
||||
|
||||
// !!!! Must not start the process in constructor, so that we can set CompressionLevel via Settings!
|
||||
private EncoderSettings m_settings;
|
||||
public AudioEncoderSettings Settings => m_settings;
|
||||
|
||||
public string Path { get { return _path; } }
|
||||
|
||||
public AudioEncoder(EncoderSettings settings, string path, Stream IO = null)
|
||||
{
|
||||
m_settings = settings;
|
||||
_path = path;
|
||||
useTempFile = m_settings.Parameters.Contains("%I");
|
||||
tempFile = path + ".tmp.wav";
|
||||
|
||||
_encoderProcess = new Process();
|
||||
_encoderProcess.StartInfo.FileName = m_settings.Path;
|
||||
_encoderProcess.StartInfo.Arguments = m_settings.Parameters.Replace("%O", "\"" + path + "\"").Replace("%M", m_settings.EncoderMode).Replace("%P", m_settings.Padding.ToString()).Replace("%I", "\"" + tempFile + "\"");
|
||||
_encoderProcess.StartInfo.CreateNoWindow = true;
|
||||
if (!useTempFile)
|
||||
_encoderProcess.StartInfo.RedirectStandardInput = true;
|
||||
_encoderProcess.StartInfo.UseShellExecute = false;
|
||||
if (!m_settings.Parameters.Contains("%O"))
|
||||
_encoderProcess.StartInfo.RedirectStandardOutput = true;
|
||||
if (useTempFile)
|
||||
{
|
||||
wrt = new WAV.AudioEncoder(new WAV.EncoderSettings(settings.PCM), tempFile);
|
||||
return;
|
||||
}
|
||||
bool started = false;
|
||||
Exception ex = null;
|
||||
try
|
||||
{
|
||||
started = _encoderProcess.Start();
|
||||
if (started)
|
||||
_encoderProcess.PriorityClass = Process.GetCurrentProcess().PriorityClass;
|
||||
}
|
||||
catch (Exception _ex)
|
||||
{
|
||||
ex = _ex;
|
||||
}
|
||||
if (!started)
|
||||
throw new Exception(m_settings.Path + ": " + (ex == null ? "please check the path" : ex.Message));
|
||||
if (_encoderProcess.StartInfo.RedirectStandardOutput)
|
||||
{
|
||||
Stream outputStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read);
|
||||
outputBuffer = new CyclicBuffer(2 * 1024 * 1024, _encoderProcess.StandardOutput.BaseStream, outputStream);
|
||||
}
|
||||
Stream inputStream = new CyclicBufferOutputStream(_encoderProcess.StandardInput.BaseStream, 128 * 1024);
|
||||
wrt = new WAV.AudioEncoder(new WAV.EncoderSettings(settings.PCM), path, inputStream);
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
if (closed)
|
||||
return;
|
||||
closed = true;
|
||||
wrt.Close();
|
||||
if (useTempFile && (_finalSampleCount < 0 || wrt.Position == _finalSampleCount))
|
||||
{
|
||||
bool started = false;
|
||||
Exception ex = null;
|
||||
try
|
||||
{
|
||||
started = _encoderProcess.Start();
|
||||
if (started)
|
||||
_encoderProcess.PriorityClass = Process.GetCurrentProcess().PriorityClass;
|
||||
}
|
||||
catch (Exception _ex)
|
||||
{
|
||||
ex = _ex;
|
||||
}
|
||||
if (!started)
|
||||
throw new Exception(m_settings.Path + ": " + (ex == null ? "please check the path" : ex.Message));
|
||||
}
|
||||
wrt = null;
|
||||
if (!_encoderProcess.HasExited)
|
||||
_encoderProcess.WaitForExit();
|
||||
if (useTempFile)
|
||||
File.Delete(tempFile);
|
||||
if (outputBuffer != null)
|
||||
outputBuffer.Close();
|
||||
if (_encoderProcess.ExitCode != 0)
|
||||
throw new Exception(String.Format("{0} returned error code {1}", m_settings.Path, _encoderProcess.ExitCode));
|
||||
}
|
||||
|
||||
public void Delete()
|
||||
{
|
||||
Close();
|
||||
File.Delete(_path);
|
||||
}
|
||||
|
||||
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}", m_settings.Path, _encoderProcess.ExitCode), ex);
|
||||
else
|
||||
throw ex;
|
||||
}
|
||||
//_sampleLen += sampleCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,21 +4,21 @@ using System.Text;
|
||||
using System.ComponentModel;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace CUETools.Codecs
|
||||
namespace CUETools.Codecs.CommandLine
|
||||
{
|
||||
[JsonObject(MemberSerialization.OptIn)]
|
||||
public class CommandLineDecoderSettings : AudioDecoderSettings
|
||||
public class DecoderSettings : AudioDecoderSettings
|
||||
{
|
||||
public override string Name => name;
|
||||
|
||||
public override string Extension => extension;
|
||||
|
||||
public CommandLineDecoderSettings()
|
||||
public DecoderSettings()
|
||||
: base()
|
||||
{
|
||||
}
|
||||
|
||||
public CommandLineDecoderSettings(
|
||||
public DecoderSettings(
|
||||
string _name,
|
||||
string _extension,
|
||||
string _path,
|
||||
@@ -1,63 +1,63 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.ComponentModel;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace CUETools.Codecs
|
||||
{
|
||||
[JsonObject(MemberSerialization.OptIn)]
|
||||
public class CommandLineEncoderSettings : AudioEncoderSettings
|
||||
{
|
||||
public override string Name => name;
|
||||
|
||||
public override string Extension => extension;
|
||||
|
||||
public override Type EncoderType => typeof(CommandLineEncoder);
|
||||
|
||||
public override bool Lossless => lossless;
|
||||
|
||||
public CommandLineEncoderSettings()
|
||||
: base()
|
||||
{
|
||||
}
|
||||
|
||||
[JsonProperty]
|
||||
public string name;
|
||||
|
||||
[JsonProperty]
|
||||
public string extension;
|
||||
|
||||
[JsonProperty]
|
||||
public bool lossless;
|
||||
|
||||
[DefaultValue(null)]
|
||||
[JsonProperty]
|
||||
public string Path
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[DefaultValue(null)]
|
||||
[JsonProperty]
|
||||
public string Parameters
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[JsonProperty]
|
||||
public string SupportedModes
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_supported_modes;
|
||||
}
|
||||
set
|
||||
{
|
||||
m_supported_modes = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.ComponentModel;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace CUETools.Codecs.CommandLine
|
||||
{
|
||||
[JsonObject(MemberSerialization.OptIn)]
|
||||
public class EncoderSettings : AudioEncoderSettings
|
||||
{
|
||||
public override string Name => name;
|
||||
|
||||
public override string Extension => extension;
|
||||
|
||||
public override Type EncoderType => typeof(AudioEncoder);
|
||||
|
||||
public override bool Lossless => lossless;
|
||||
|
||||
public EncoderSettings()
|
||||
: base()
|
||||
{
|
||||
}
|
||||
|
||||
[JsonProperty]
|
||||
public string name;
|
||||
|
||||
[JsonProperty]
|
||||
public string extension;
|
||||
|
||||
[JsonProperty]
|
||||
public bool lossless;
|
||||
|
||||
[DefaultValue(null)]
|
||||
[JsonProperty]
|
||||
public string Path
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[DefaultValue(null)]
|
||||
[JsonProperty]
|
||||
public string Parameters
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[JsonProperty]
|
||||
public string SupportedModes
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_supported_modes;
|
||||
}
|
||||
set
|
||||
{
|
||||
m_supported_modes = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace CUETools.Codecs
|
||||
{
|
||||
public class DummyWriter : IAudioDest
|
||||
{
|
||||
AudioEncoderSettings m_settings;
|
||||
|
||||
public DummyWriter(string path, AudioEncoderSettings settings)
|
||||
{
|
||||
m_settings = settings;
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
}
|
||||
|
||||
public void Delete()
|
||||
{
|
||||
}
|
||||
|
||||
public long FinalSampleCount
|
||||
{
|
||||
set { }
|
||||
}
|
||||
|
||||
public AudioEncoderSettings Settings
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_settings;
|
||||
}
|
||||
}
|
||||
|
||||
public void Write(AudioBuffer buff)
|
||||
{
|
||||
}
|
||||
|
||||
public string Path { get { return null; } }
|
||||
}
|
||||
}
|
||||
@@ -1,61 +1,61 @@
|
||||
namespace CUETools.Codecs
|
||||
{
|
||||
public class SilenceGenerator : IAudioSource
|
||||
{
|
||||
private long _sampleOffset, _sampleCount;
|
||||
private AudioPCMConfig pcm;
|
||||
private int _sampleVal;
|
||||
|
||||
public AudioDecoderSettings Settings { get { return null; } }
|
||||
|
||||
public long Length
|
||||
{
|
||||
get { return _sampleCount; }
|
||||
}
|
||||
|
||||
public long Remaining
|
||||
{
|
||||
get { return _sampleCount - _sampleOffset; }
|
||||
}
|
||||
|
||||
public long Position
|
||||
{
|
||||
get { return _sampleOffset; }
|
||||
set { _sampleOffset = value; }
|
||||
}
|
||||
|
||||
public AudioPCMConfig PCM { get { return pcm; } }
|
||||
|
||||
public string Path { get { return null; } }
|
||||
|
||||
public SilenceGenerator(AudioPCMConfig pcm, long sampleCount, int sampleVal)
|
||||
{
|
||||
this._sampleVal = sampleVal;
|
||||
this._sampleOffset = 0;
|
||||
this._sampleCount = sampleCount;
|
||||
this.pcm = pcm;
|
||||
}
|
||||
|
||||
public SilenceGenerator(long sampleCount)
|
||||
: this(AudioPCMConfig.RedBook, sampleCount, 0)
|
||||
{
|
||||
}
|
||||
|
||||
public int Read(AudioBuffer buff, int maxLength)
|
||||
{
|
||||
buff.Prepare(this, maxLength);
|
||||
|
||||
int[,] samples = buff.Samples;
|
||||
for (int i = 0; i < buff.Length; i++)
|
||||
for (int j = 0; j < PCM.ChannelCount; j++)
|
||||
samples[i, j] = _sampleVal;
|
||||
|
||||
_sampleOffset += buff.Length;
|
||||
return buff.Length;
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
namespace CUETools.Codecs.NULL
|
||||
{
|
||||
public class AudioDecoder : IAudioSource
|
||||
{
|
||||
private long _sampleOffset, _sampleCount;
|
||||
private AudioPCMConfig pcm;
|
||||
private int _sampleVal;
|
||||
|
||||
public AudioDecoderSettings Settings { get { return null; } }
|
||||
|
||||
public long Length
|
||||
{
|
||||
get { return _sampleCount; }
|
||||
}
|
||||
|
||||
public long Remaining
|
||||
{
|
||||
get { return _sampleCount - _sampleOffset; }
|
||||
}
|
||||
|
||||
public long Position
|
||||
{
|
||||
get { return _sampleOffset; }
|
||||
set { _sampleOffset = value; }
|
||||
}
|
||||
|
||||
public AudioPCMConfig PCM { get { return pcm; } }
|
||||
|
||||
public string Path { get { return null; } }
|
||||
|
||||
public AudioDecoder(AudioPCMConfig pcm, long sampleCount, int sampleVal)
|
||||
{
|
||||
this._sampleVal = sampleVal;
|
||||
this._sampleOffset = 0;
|
||||
this._sampleCount = sampleCount;
|
||||
this.pcm = pcm;
|
||||
}
|
||||
|
||||
public AudioDecoder(long sampleCount)
|
||||
: this(AudioPCMConfig.RedBook, sampleCount, 0)
|
||||
{
|
||||
}
|
||||
|
||||
public int Read(AudioBuffer buff, int maxLength)
|
||||
{
|
||||
buff.Prepare(this, maxLength);
|
||||
|
||||
int[,] samples = buff.Samples;
|
||||
for (int i = 0; i < buff.Length; i++)
|
||||
for (int j = 0; j < PCM.ChannelCount; j++)
|
||||
samples[i, j] = _sampleVal;
|
||||
|
||||
_sampleOffset += buff.Length;
|
||||
return buff.Length;
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
35
CUETools.Codecs/NULL/AudioEncoder.cs
Normal file
35
CUETools.Codecs/NULL/AudioEncoder.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
using System;
|
||||
|
||||
namespace CUETools.Codecs.NULL
|
||||
{
|
||||
public class AudioEncoder : IAudioDest
|
||||
{
|
||||
AudioEncoderSettings m_settings;
|
||||
|
||||
public AudioEncoder(string path, AudioEncoderSettings settings)
|
||||
{
|
||||
m_settings = settings;
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
}
|
||||
|
||||
public void Delete()
|
||||
{
|
||||
}
|
||||
|
||||
public long FinalSampleCount
|
||||
{
|
||||
set { }
|
||||
}
|
||||
|
||||
public AudioEncoderSettings Settings => m_settings;
|
||||
|
||||
public void Write(AudioBuffer buff)
|
||||
{
|
||||
}
|
||||
|
||||
public string Path => null;
|
||||
}
|
||||
}
|
||||
112
CUETools.Codecs/ViewModel/AudioDecoderSettingsViewModel.cs
Normal file
112
CUETools.Codecs/ViewModel/AudioDecoderSettingsViewModel.cs
Normal file
@@ -0,0 +1,112 @@
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace CUETools.Codecs
|
||||
{
|
||||
[JsonObject(MemberSerialization.OptIn)]
|
||||
public class AudioDecoderSettingsViewModel : INotifyPropertyChanged
|
||||
{
|
||||
[JsonProperty]
|
||||
public AudioDecoderSettings decoderSettings = null;
|
||||
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
[JsonConstructor]
|
||||
private AudioDecoderSettingsViewModel()
|
||||
{
|
||||
}
|
||||
|
||||
public AudioDecoderSettingsViewModel(AudioDecoderSettings settings)
|
||||
{
|
||||
decoderSettings = settings;
|
||||
}
|
||||
|
||||
public AudioDecoderSettingsViewModel Clone()
|
||||
{
|
||||
var res = this.MemberwiseClone() as AudioDecoderSettingsViewModel;
|
||||
if (decoderSettings != null) res.decoderSettings = decoderSettings.Clone();
|
||||
return res;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Name;
|
||||
}
|
||||
|
||||
public string FullName => Name + " [" + Extension + "]";
|
||||
|
||||
public string Path
|
||||
{
|
||||
get
|
||||
{
|
||||
if (decoderSettings is CommandLine.DecoderSettings)
|
||||
return (decoderSettings as CommandLine.DecoderSettings).Path;
|
||||
return "";
|
||||
}
|
||||
set
|
||||
{
|
||||
if (decoderSettings is CommandLine.DecoderSettings)
|
||||
(decoderSettings as CommandLine.DecoderSettings).Path = value;
|
||||
else throw new InvalidOperationException();
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Path"));
|
||||
}
|
||||
}
|
||||
public string Parameters
|
||||
{
|
||||
get
|
||||
{
|
||||
if (decoderSettings is CommandLine.DecoderSettings)
|
||||
return (decoderSettings as CommandLine.DecoderSettings).Parameters;
|
||||
return "";
|
||||
}
|
||||
set
|
||||
{
|
||||
if (decoderSettings is CommandLine.DecoderSettings)
|
||||
(decoderSettings as CommandLine.DecoderSettings).Parameters = value;
|
||||
else throw new InvalidOperationException();
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Parameters"));
|
||||
}
|
||||
}
|
||||
|
||||
public bool Lossless
|
||||
{
|
||||
get => true;
|
||||
set {
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
public string Name
|
||||
{
|
||||
get => decoderSettings.Name;
|
||||
set
|
||||
{
|
||||
if (decoderSettings is CommandLine.DecoderSettings)
|
||||
(decoderSettings as CommandLine.DecoderSettings).name = value;
|
||||
else throw new InvalidOperationException();
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Name"));
|
||||
}
|
||||
}
|
||||
|
||||
public string Extension
|
||||
{
|
||||
get => decoderSettings.Extension;
|
||||
set
|
||||
{
|
||||
if (decoderSettings is CommandLine.DecoderSettings)
|
||||
(decoderSettings as CommandLine.DecoderSettings).extension = value;
|
||||
else throw new InvalidOperationException();
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Extension"));
|
||||
}
|
||||
}
|
||||
|
||||
public string DotExtension => "." + Extension;
|
||||
|
||||
public bool CanBeDeleted => decoderSettings is CommandLine.DecoderSettings;
|
||||
|
||||
public bool IsValid =>
|
||||
(decoderSettings != null)
|
||||
&& (decoderSettings is CommandLine.DecoderSettings ? (decoderSettings as CommandLine.DecoderSettings).Path != "" : true);
|
||||
}
|
||||
}
|
||||
165
CUETools.Codecs/ViewModel/AudioEncoderSettingsViewModel.cs
Normal file
165
CUETools.Codecs/ViewModel/AudioEncoderSettingsViewModel.cs
Normal file
@@ -0,0 +1,165 @@
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace CUETools.Codecs
|
||||
{
|
||||
[JsonObject(MemberSerialization.OptIn)]
|
||||
public class AudioEncoderSettingsViewModel : INotifyPropertyChanged
|
||||
{
|
||||
[JsonProperty]
|
||||
public AudioEncoderSettings settings = null;
|
||||
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
[JsonConstructor]
|
||||
private AudioEncoderSettingsViewModel()
|
||||
{
|
||||
}
|
||||
|
||||
public AudioEncoderSettingsViewModel(
|
||||
string _name,
|
||||
string _extension,
|
||||
bool _lossless,
|
||||
string _supported_modes,
|
||||
string _default_mode,
|
||||
string _path,
|
||||
string _parameters
|
||||
)
|
||||
{
|
||||
settings = new CommandLine.EncoderSettings() { name = _name, extension = _extension, SupportedModes = _supported_modes, EncoderMode = _default_mode, Path = _path, Parameters = _parameters, lossless = _lossless };
|
||||
}
|
||||
|
||||
public AudioEncoderSettingsViewModel(AudioEncoderClassAttribute enc)
|
||||
{
|
||||
settings = Activator.CreateInstance(enc.Settings) as AudioEncoderSettings;
|
||||
if (settings == null)
|
||||
throw new InvalidOperationException("invalid codec");
|
||||
}
|
||||
|
||||
public AudioEncoderSettingsViewModel Clone()
|
||||
{
|
||||
var res = this.MemberwiseClone() as AudioEncoderSettingsViewModel;
|
||||
if (settings != null) res.settings = settings.Clone();
|
||||
return res;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Name;
|
||||
}
|
||||
|
||||
public string FullName => Name + " [" + Extension + "]";
|
||||
|
||||
public string Path
|
||||
{
|
||||
get
|
||||
{
|
||||
if (settings is CommandLine.EncoderSettings)
|
||||
return (settings as CommandLine.EncoderSettings).Path;
|
||||
return "";
|
||||
}
|
||||
set
|
||||
{
|
||||
var settings = this.settings as CommandLine.EncoderSettings;
|
||||
if (settings == null) throw new InvalidOperationException();
|
||||
settings.Path = value;
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Path"));
|
||||
}
|
||||
}
|
||||
|
||||
public string Parameters
|
||||
{
|
||||
get
|
||||
{
|
||||
if (settings is CommandLine.EncoderSettings)
|
||||
return (settings as CommandLine.EncoderSettings).Parameters;
|
||||
return "";
|
||||
}
|
||||
set
|
||||
{
|
||||
var settings = this.settings as CommandLine.EncoderSettings;
|
||||
if (settings == null) throw new InvalidOperationException();
|
||||
settings.Parameters = value;
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Parameters"));
|
||||
}
|
||||
}
|
||||
|
||||
public bool Lossless
|
||||
{
|
||||
get => settings.Lossless;
|
||||
set
|
||||
{
|
||||
var settings = this.settings as CommandLine.EncoderSettings;
|
||||
if (settings == null) throw new InvalidOperationException();
|
||||
settings.lossless = value;
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Lossless"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public string Name
|
||||
{
|
||||
get => settings.Name;
|
||||
set
|
||||
{
|
||||
var settings = this.settings as CommandLine.EncoderSettings;
|
||||
if (settings == null) throw new InvalidOperationException();
|
||||
settings.name = value;
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Name"));
|
||||
}
|
||||
}
|
||||
|
||||
public string Extension
|
||||
{
|
||||
get => settings.Extension;
|
||||
set
|
||||
{
|
||||
var settings = this.settings as CommandLine.EncoderSettings;
|
||||
if (settings == null) throw new InvalidOperationException();
|
||||
settings.extension = value;
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Extension"));
|
||||
}
|
||||
}
|
||||
|
||||
public string DotExtension => "." + Extension;
|
||||
|
||||
public string SupportedModesStr
|
||||
{
|
||||
get
|
||||
{
|
||||
string defaultMode;
|
||||
return this.settings.GetSupportedModes(out defaultMode);
|
||||
}
|
||||
set
|
||||
{
|
||||
var settings = this.settings as CommandLine.EncoderSettings;
|
||||
if (settings == null) throw new InvalidOperationException();
|
||||
settings.SupportedModes = value;
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("SupportedModesStr"));
|
||||
}
|
||||
}
|
||||
|
||||
public string[] SupportedModes => this.SupportedModesStr.Split(' ');
|
||||
|
||||
public int EncoderModeIndex
|
||||
{
|
||||
get
|
||||
{
|
||||
string[] modes = this.SupportedModes;
|
||||
if (modes == null || modes.Length < 2)
|
||||
return -1;
|
||||
for (int i = 0; i < modes.Length; i++)
|
||||
if (modes[i] == this.settings.EncoderMode)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
public bool CanBeDeleted => settings is CommandLine.EncoderSettings;
|
||||
|
||||
public bool IsValid =>
|
||||
(settings != null)
|
||||
&& (settings is CommandLine.EncoderSettings ? (settings as CommandLine.EncoderSettings).Path != "" : true);
|
||||
}
|
||||
}
|
||||
46
CUETools.Codecs/ViewModel/DecoderListViewModel.cs
Normal file
46
CUETools.Codecs/ViewModel/DecoderListViewModel.cs
Normal file
@@ -0,0 +1,46 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace CUETools.Codecs
|
||||
{
|
||||
public class DecoderListViewModel : BindingList<AudioDecoderSettingsViewModel>
|
||||
{
|
||||
public DecoderListViewModel()
|
||||
: base()
|
||||
{
|
||||
AddingNew += OnAddingNew;
|
||||
}
|
||||
|
||||
private void OnAddingNew(object sender, AddingNewEventArgs e)
|
||||
{
|
||||
e.NewObject = new AudioDecoderSettingsViewModel(new CommandLine.DecoderSettings("new", "wav", "", ""));
|
||||
}
|
||||
|
||||
public bool TryGetValue(string extension, bool lossless, string name, out AudioDecoderSettingsViewModel result)
|
||||
{
|
||||
foreach (AudioDecoderSettingsViewModel udc in this)
|
||||
{
|
||||
if (udc.decoderSettings.Extension == extension && udc.decoderSettings.Lossless == lossless && udc.decoderSettings.Name == name)
|
||||
{
|
||||
result = udc;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
result = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
public AudioDecoderSettingsViewModel GetDefault(string extension, bool lossless)
|
||||
{
|
||||
AudioDecoderSettingsViewModel result = null;
|
||||
foreach (AudioDecoderSettingsViewModel udc in this)
|
||||
{
|
||||
if (udc.decoderSettings.Extension == extension && udc.decoderSettings.Lossless == lossless && (result == null || result.decoderSettings.Priority < udc.decoderSettings.Priority))
|
||||
{
|
||||
result = udc;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
47
CUETools.Codecs/ViewModel/EncoderListViewModel.cs
Normal file
47
CUETools.Codecs/ViewModel/EncoderListViewModel.cs
Normal file
@@ -0,0 +1,47 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace CUETools.Codecs
|
||||
{
|
||||
public class EncoderListViewModel : BindingList<AudioEncoderSettingsViewModel>
|
||||
{
|
||||
public EncoderListViewModel()
|
||||
: base()
|
||||
{
|
||||
AddingNew += OnAddingNew;
|
||||
}
|
||||
|
||||
private void OnAddingNew(object sender, AddingNewEventArgs e)
|
||||
{
|
||||
e.NewObject = new AudioEncoderSettingsViewModel("new", "wav", true, "", "", "", "");
|
||||
}
|
||||
|
||||
public bool TryGetValue(string extension, bool lossless, string name, out AudioEncoderSettingsViewModel result)
|
||||
{
|
||||
//result = this.Where(udc => udc.settings.Extension == extension && udc.settings.Lossless == lossless && udc.settings.Name == name).First();
|
||||
foreach (AudioEncoderSettingsViewModel udc in this)
|
||||
{
|
||||
if (udc.settings.Extension == extension && udc.settings.Lossless == lossless && udc.settings.Name == name)
|
||||
{
|
||||
result = udc;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
result = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
public AudioEncoderSettingsViewModel GetDefault(string extension, bool lossless)
|
||||
{
|
||||
AudioEncoderSettingsViewModel result = null;
|
||||
foreach (AudioEncoderSettingsViewModel udc in this)
|
||||
{
|
||||
if (udc.settings.Extension == extension && udc.settings.Lossless == lossless && (result == null || result.settings.Priority < udc.settings.Priority))
|
||||
{
|
||||
result = udc;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,285 +1,270 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace CUETools.Codecs.WAV
|
||||
{
|
||||
public class DecoderSettings : AudioDecoderSettings
|
||||
{
|
||||
public override string Name => "cuetools";
|
||||
|
||||
public override string Extension => "wav";
|
||||
|
||||
public override Type DecoderType => typeof(AudioDecoder);
|
||||
|
||||
public override int Priority => 2;
|
||||
|
||||
public DecoderSettings() : base() {}
|
||||
|
||||
public bool IgnoreChunkSizes;
|
||||
}
|
||||
|
||||
[AudioDecoderClass(typeof(DecoderSettings))]
|
||||
public class AudioDecoder : IAudioSource
|
||||
{
|
||||
Stream _IO;
|
||||
BinaryReader _br;
|
||||
long _dataOffset, _samplePos, _sampleLen;
|
||||
private AudioPCMConfig pcm;
|
||||
long _dataLen;
|
||||
bool _largeFile;
|
||||
string _path;
|
||||
|
||||
private DecoderSettings m_settings;
|
||||
public AudioDecoderSettings Settings => m_settings;
|
||||
|
||||
public long Position
|
||||
{
|
||||
get
|
||||
{
|
||||
return _samplePos;
|
||||
}
|
||||
set
|
||||
{
|
||||
long seekPos;
|
||||
|
||||
if (_samplePos == value)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var oldSamplePos = _samplePos;
|
||||
if (_sampleLen >= 0 && value > _sampleLen)
|
||||
_samplePos = _sampleLen;
|
||||
else
|
||||
_samplePos = value;
|
||||
|
||||
if (_IO.CanSeek || _samplePos < oldSamplePos)
|
||||
{
|
||||
seekPos = _dataOffset + _samplePos * PCM.BlockAlign;
|
||||
_IO.Seek(seekPos, SeekOrigin.Begin);
|
||||
}
|
||||
else
|
||||
{
|
||||
int offs = (int)(_samplePos - oldSamplePos) * PCM.BlockAlign;
|
||||
while (offs > 0)
|
||||
{
|
||||
int chunk = Math.Min(offs, 16536);
|
||||
_br.ReadBytes(chunk);
|
||||
offs -= chunk;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public long Length
|
||||
{
|
||||
get
|
||||
{
|
||||
return _sampleLen;
|
||||
}
|
||||
}
|
||||
|
||||
public long Remaining
|
||||
{
|
||||
get
|
||||
{
|
||||
return _sampleLen - _samplePos;
|
||||
}
|
||||
}
|
||||
|
||||
public AudioPCMConfig PCM { get { return pcm; } }
|
||||
|
||||
public string Path { get { return _path; } }
|
||||
|
||||
public AudioDecoder(DecoderSettings settings, string path, Stream IO = null)
|
||||
{
|
||||
m_settings = settings;
|
||||
_path = path;
|
||||
_IO = IO ?? new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, 0x10000, FileOptions.SequentialScan);
|
||||
_br = new BinaryReader(_IO);
|
||||
|
||||
ParseHeaders();
|
||||
|
||||
if (_dataLen < 0 || m_settings.IgnoreChunkSizes)
|
||||
_sampleLen = -1;
|
||||
else
|
||||
_sampleLen = _dataLen / pcm.BlockAlign;
|
||||
}
|
||||
|
||||
public AudioDecoder(DecoderSettings settings, string path, Stream IO, AudioPCMConfig _pcm)
|
||||
{
|
||||
m_settings = settings;
|
||||
_path = path;
|
||||
_IO = IO != null ? IO : new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, 0x10000, FileOptions.SequentialScan);
|
||||
_br = new BinaryReader(_IO);
|
||||
|
||||
_largeFile = false;
|
||||
_dataOffset = 0;
|
||||
_samplePos = 0;
|
||||
pcm = _pcm;
|
||||
_dataLen = _IO.CanSeek ? _IO.Length : -1;
|
||||
if (_dataLen < 0)
|
||||
_sampleLen = -1;
|
||||
else
|
||||
{
|
||||
_sampleLen = _dataLen / pcm.BlockAlign;
|
||||
if ((_dataLen % pcm.BlockAlign) != 0)
|
||||
throw new Exception("odd file size");
|
||||
}
|
||||
}
|
||||
|
||||
public static AudioBuffer ReadAllSamples(DecoderSettings settings, string path, Stream IO = null)
|
||||
{
|
||||
AudioDecoder reader = new AudioDecoder(settings, 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()
|
||||
{
|
||||
if (_br != null)
|
||||
{
|
||||
_br.Close();
|
||||
_br = null;
|
||||
}
|
||||
_IO = null;
|
||||
}
|
||||
|
||||
private void ParseHeaders()
|
||||
{
|
||||
const long maxFileSize = 0x7FFFFFFEL;
|
||||
const uint fccRIFF = 0x46464952;
|
||||
const uint fccWAVE = 0x45564157;
|
||||
const uint fccFormat = 0x20746D66;
|
||||
const uint fccData = 0x61746164;
|
||||
|
||||
uint lenRIFF;
|
||||
bool foundFormat, foundData;
|
||||
|
||||
if (_br.ReadUInt32() != fccRIFF)
|
||||
{
|
||||
throw new Exception("Not a valid RIFF file.");
|
||||
}
|
||||
|
||||
lenRIFF = _br.ReadUInt32();
|
||||
|
||||
if (_br.ReadUInt32() != fccWAVE)
|
||||
{
|
||||
throw new Exception("Not a valid WAVE file.");
|
||||
}
|
||||
|
||||
_largeFile = false;
|
||||
foundFormat = false;
|
||||
foundData = false;
|
||||
long pos = 12;
|
||||
do
|
||||
{
|
||||
uint ckID, ckSize, ckSizePadded;
|
||||
long ckEnd;
|
||||
|
||||
ckID = _br.ReadUInt32();
|
||||
ckSize = _br.ReadUInt32();
|
||||
ckSizePadded = (ckSize + 1U) & ~1U;
|
||||
pos += 8;
|
||||
ckEnd = pos + (long)ckSizePadded;
|
||||
|
||||
if (ckID == fccFormat)
|
||||
{
|
||||
foundFormat = true;
|
||||
|
||||
uint fmtTag = _br.ReadUInt16();
|
||||
int _channelCount = _br.ReadInt16();
|
||||
int _sampleRate = _br.ReadInt32();
|
||||
_br.ReadInt32(); // bytes per second
|
||||
int _blockAlign = _br.ReadInt16();
|
||||
int _bitsPerSample = _br.ReadInt16();
|
||||
int _channelMask = 0;
|
||||
pos += 16;
|
||||
|
||||
if (fmtTag == 0xFFFEU && ckSize >= 34) // WAVE_FORMAT_EXTENSIBLE
|
||||
{
|
||||
_br.ReadInt16(); // CbSize
|
||||
_br.ReadInt16(); // ValidBitsPerSample
|
||||
_channelMask = _br.ReadInt32();
|
||||
fmtTag = _br.ReadUInt16();
|
||||
pos += 10;
|
||||
}
|
||||
|
||||
if (fmtTag != 1) // WAVE_FORMAT_PCM
|
||||
throw new Exception("WAVE format tag not WAVE_FORMAT_PCM.");
|
||||
|
||||
pcm = new AudioPCMConfig(_bitsPerSample, _channelCount, _sampleRate, (AudioPCMConfig.SpeakerConfig)_channelMask);
|
||||
if (pcm.BlockAlign != _blockAlign)
|
||||
throw new Exception("WAVE has strange BlockAlign");
|
||||
}
|
||||
else if (ckID == fccData)
|
||||
{
|
||||
foundData = true;
|
||||
|
||||
_dataOffset = pos;
|
||||
if (!_IO.CanSeek || _IO.Length <= maxFileSize)
|
||||
{
|
||||
if (ckSize == 0 || ckSize >= 0x7fffffff)
|
||||
_dataLen = -1;
|
||||
else
|
||||
_dataLen = (long)ckSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
_largeFile = true;
|
||||
_dataLen = _IO.Length - pos;
|
||||
}
|
||||
}
|
||||
|
||||
if ((foundFormat & foundData) || _largeFile)
|
||||
break;
|
||||
if (_IO.CanSeek)
|
||||
_IO.Seek(ckEnd, SeekOrigin.Begin);
|
||||
else
|
||||
_br.ReadBytes((int)(ckEnd - pos));
|
||||
pos = ckEnd;
|
||||
} while (true);
|
||||
|
||||
if ((foundFormat & foundData) == false || pcm == null)
|
||||
throw new Exception("Format or data chunk not found.");
|
||||
if (pcm.ChannelCount <= 0)
|
||||
throw new Exception("Channel count is invalid.");
|
||||
if (pcm.SampleRate <= 0)
|
||||
throw new Exception("Sample rate is invalid.");
|
||||
if ((pcm.BitsPerSample <= 0) || (pcm.BitsPerSample > 32))
|
||||
throw new Exception("Bits per sample is invalid.");
|
||||
if (pos != _dataOffset)
|
||||
Position = 0;
|
||||
}
|
||||
|
||||
public int Read(AudioBuffer buff, int maxLength)
|
||||
{
|
||||
buff.Prepare(this, maxLength);
|
||||
|
||||
byte[] bytes = buff.Bytes;
|
||||
int byteCount = (int)buff.ByteLength;
|
||||
int pos = 0;
|
||||
|
||||
while (pos < byteCount)
|
||||
{
|
||||
int len = _IO.Read(bytes, pos, byteCount - pos);
|
||||
if (len <= 0)
|
||||
{
|
||||
if ((pos % PCM.BlockAlign) != 0 || _sampleLen >= 0)
|
||||
throw new Exception("Incomplete file read.");
|
||||
buff.Length = pos / PCM.BlockAlign;
|
||||
_samplePos += buff.Length;
|
||||
_sampleLen = _samplePos;
|
||||
return buff.Length;
|
||||
}
|
||||
pos += len;
|
||||
}
|
||||
_samplePos += buff.Length;
|
||||
return buff.Length;
|
||||
}
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace CUETools.Codecs.WAV
|
||||
{
|
||||
[AudioDecoderClass(typeof(DecoderSettings))]
|
||||
public class AudioDecoder : IAudioSource
|
||||
{
|
||||
Stream _IO;
|
||||
BinaryReader _br;
|
||||
long _dataOffset, _samplePos, _sampleLen;
|
||||
private AudioPCMConfig pcm;
|
||||
long _dataLen;
|
||||
bool _largeFile;
|
||||
string _path;
|
||||
|
||||
private DecoderSettings m_settings;
|
||||
public AudioDecoderSettings Settings => m_settings;
|
||||
|
||||
public long Position
|
||||
{
|
||||
get
|
||||
{
|
||||
return _samplePos;
|
||||
}
|
||||
set
|
||||
{
|
||||
long seekPos;
|
||||
|
||||
if (_samplePos == value)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var oldSamplePos = _samplePos;
|
||||
if (_sampleLen >= 0 && value > _sampleLen)
|
||||
_samplePos = _sampleLen;
|
||||
else
|
||||
_samplePos = value;
|
||||
|
||||
if (_IO.CanSeek || _samplePos < oldSamplePos)
|
||||
{
|
||||
seekPos = _dataOffset + _samplePos * PCM.BlockAlign;
|
||||
_IO.Seek(seekPos, SeekOrigin.Begin);
|
||||
}
|
||||
else
|
||||
{
|
||||
int offs = (int)(_samplePos - oldSamplePos) * PCM.BlockAlign;
|
||||
while (offs > 0)
|
||||
{
|
||||
int chunk = Math.Min(offs, 16536);
|
||||
_br.ReadBytes(chunk);
|
||||
offs -= chunk;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public long Length
|
||||
{
|
||||
get
|
||||
{
|
||||
return _sampleLen;
|
||||
}
|
||||
}
|
||||
|
||||
public long Remaining
|
||||
{
|
||||
get
|
||||
{
|
||||
return _sampleLen - _samplePos;
|
||||
}
|
||||
}
|
||||
|
||||
public AudioPCMConfig PCM { get { return pcm; } }
|
||||
|
||||
public string Path { get { return _path; } }
|
||||
|
||||
public AudioDecoder(DecoderSettings settings, string path, Stream IO = null)
|
||||
{
|
||||
m_settings = settings;
|
||||
_path = path;
|
||||
_IO = IO ?? new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, 0x10000, FileOptions.SequentialScan);
|
||||
_br = new BinaryReader(_IO);
|
||||
|
||||
ParseHeaders();
|
||||
|
||||
if (_dataLen < 0 || m_settings.IgnoreChunkSizes)
|
||||
_sampleLen = -1;
|
||||
else
|
||||
_sampleLen = _dataLen / pcm.BlockAlign;
|
||||
}
|
||||
|
||||
public AudioDecoder(DecoderSettings settings, string path, Stream IO, AudioPCMConfig _pcm)
|
||||
{
|
||||
m_settings = settings;
|
||||
_path = path;
|
||||
_IO = IO != null ? IO : new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, 0x10000, FileOptions.SequentialScan);
|
||||
_br = new BinaryReader(_IO);
|
||||
|
||||
_largeFile = false;
|
||||
_dataOffset = 0;
|
||||
_samplePos = 0;
|
||||
pcm = _pcm;
|
||||
_dataLen = _IO.CanSeek ? _IO.Length : -1;
|
||||
if (_dataLen < 0)
|
||||
_sampleLen = -1;
|
||||
else
|
||||
{
|
||||
_sampleLen = _dataLen / pcm.BlockAlign;
|
||||
if ((_dataLen % pcm.BlockAlign) != 0)
|
||||
throw new Exception("odd file size");
|
||||
}
|
||||
}
|
||||
|
||||
public static AudioBuffer ReadAllSamples(DecoderSettings settings, string path, Stream IO = null)
|
||||
{
|
||||
AudioDecoder reader = new AudioDecoder(settings, 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()
|
||||
{
|
||||
if (_br != null)
|
||||
{
|
||||
_br.Close();
|
||||
_br = null;
|
||||
}
|
||||
_IO = null;
|
||||
}
|
||||
|
||||
private void ParseHeaders()
|
||||
{
|
||||
const long maxFileSize = 0x7FFFFFFEL;
|
||||
const uint fccRIFF = 0x46464952;
|
||||
const uint fccWAVE = 0x45564157;
|
||||
const uint fccFormat = 0x20746D66;
|
||||
const uint fccData = 0x61746164;
|
||||
|
||||
uint lenRIFF;
|
||||
bool foundFormat, foundData;
|
||||
|
||||
if (_br.ReadUInt32() != fccRIFF)
|
||||
{
|
||||
throw new Exception("Not a valid RIFF file.");
|
||||
}
|
||||
|
||||
lenRIFF = _br.ReadUInt32();
|
||||
|
||||
if (_br.ReadUInt32() != fccWAVE)
|
||||
{
|
||||
throw new Exception("Not a valid WAVE file.");
|
||||
}
|
||||
|
||||
_largeFile = false;
|
||||
foundFormat = false;
|
||||
foundData = false;
|
||||
long pos = 12;
|
||||
do
|
||||
{
|
||||
uint ckID, ckSize, ckSizePadded;
|
||||
long ckEnd;
|
||||
|
||||
ckID = _br.ReadUInt32();
|
||||
ckSize = _br.ReadUInt32();
|
||||
ckSizePadded = (ckSize + 1U) & ~1U;
|
||||
pos += 8;
|
||||
ckEnd = pos + (long)ckSizePadded;
|
||||
|
||||
if (ckID == fccFormat)
|
||||
{
|
||||
foundFormat = true;
|
||||
|
||||
uint fmtTag = _br.ReadUInt16();
|
||||
int _channelCount = _br.ReadInt16();
|
||||
int _sampleRate = _br.ReadInt32();
|
||||
_br.ReadInt32(); // bytes per second
|
||||
int _blockAlign = _br.ReadInt16();
|
||||
int _bitsPerSample = _br.ReadInt16();
|
||||
int _channelMask = 0;
|
||||
pos += 16;
|
||||
|
||||
if (fmtTag == 0xFFFEU && ckSize >= 34) // WAVE_FORMAT_EXTENSIBLE
|
||||
{
|
||||
_br.ReadInt16(); // CbSize
|
||||
_br.ReadInt16(); // ValidBitsPerSample
|
||||
_channelMask = _br.ReadInt32();
|
||||
fmtTag = _br.ReadUInt16();
|
||||
pos += 10;
|
||||
}
|
||||
|
||||
if (fmtTag != 1) // WAVE_FORMAT_PCM
|
||||
throw new Exception("WAVE format tag not WAVE_FORMAT_PCM.");
|
||||
|
||||
pcm = new AudioPCMConfig(_bitsPerSample, _channelCount, _sampleRate, (AudioPCMConfig.SpeakerConfig)_channelMask);
|
||||
if (pcm.BlockAlign != _blockAlign)
|
||||
throw new Exception("WAVE has strange BlockAlign");
|
||||
}
|
||||
else if (ckID == fccData)
|
||||
{
|
||||
foundData = true;
|
||||
|
||||
_dataOffset = pos;
|
||||
if (!_IO.CanSeek || _IO.Length <= maxFileSize)
|
||||
{
|
||||
if (ckSize == 0 || ckSize >= 0x7fffffff)
|
||||
_dataLen = -1;
|
||||
else
|
||||
_dataLen = (long)ckSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
_largeFile = true;
|
||||
_dataLen = _IO.Length - pos;
|
||||
}
|
||||
}
|
||||
|
||||
if ((foundFormat & foundData) || _largeFile)
|
||||
break;
|
||||
if (_IO.CanSeek)
|
||||
_IO.Seek(ckEnd, SeekOrigin.Begin);
|
||||
else
|
||||
_br.ReadBytes((int)(ckEnd - pos));
|
||||
pos = ckEnd;
|
||||
} while (true);
|
||||
|
||||
if ((foundFormat & foundData) == false || pcm == null)
|
||||
throw new Exception("Format or data chunk not found.");
|
||||
if (pcm.ChannelCount <= 0)
|
||||
throw new Exception("Channel count is invalid.");
|
||||
if (pcm.SampleRate <= 0)
|
||||
throw new Exception("Sample rate is invalid.");
|
||||
if ((pcm.BitsPerSample <= 0) || (pcm.BitsPerSample > 32))
|
||||
throw new Exception("Bits per sample is invalid.");
|
||||
if (pos != _dataOffset)
|
||||
Position = 0;
|
||||
}
|
||||
|
||||
public int Read(AudioBuffer buff, int maxLength)
|
||||
{
|
||||
buff.Prepare(this, maxLength);
|
||||
|
||||
byte[] bytes = buff.Bytes;
|
||||
int byteCount = (int)buff.ByteLength;
|
||||
int pos = 0;
|
||||
|
||||
while (pos < byteCount)
|
||||
{
|
||||
int len = _IO.Read(bytes, pos, byteCount - pos);
|
||||
if (len <= 0)
|
||||
{
|
||||
if ((pos % PCM.BlockAlign) != 0 || _sampleLen >= 0)
|
||||
throw new Exception("Incomplete file read.");
|
||||
buff.Length = pos / PCM.BlockAlign;
|
||||
_samplePos += buff.Length;
|
||||
_sampleLen = _samplePos;
|
||||
return buff.Length;
|
||||
}
|
||||
pos += len;
|
||||
}
|
||||
_samplePos += buff.Length;
|
||||
return buff.Length;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,181 +1,181 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace CUETools.Codecs.WAV
|
||||
{
|
||||
[AudioEncoderClass(typeof(EncoderSettings))]
|
||||
public class AudioEncoder : IAudioDest
|
||||
{
|
||||
private Stream _IO;
|
||||
private BinaryWriter _bw;
|
||||
private long _sampleLen;
|
||||
private string _path;
|
||||
private long hdrLen = 0;
|
||||
private bool _headersWritten = false;
|
||||
private long _finalSampleCount = -1;
|
||||
private List<byte[]> _chunks = null;
|
||||
private List<uint> _chunkFCCs = null;
|
||||
|
||||
public long Position
|
||||
{
|
||||
get
|
||||
{
|
||||
return _sampleLen;
|
||||
}
|
||||
}
|
||||
|
||||
public long FinalSampleCount
|
||||
{
|
||||
set { _finalSampleCount = value; }
|
||||
}
|
||||
|
||||
private EncoderSettings m_settings;
|
||||
public AudioEncoderSettings Settings => m_settings;
|
||||
|
||||
public string Path { get { return _path; } }
|
||||
|
||||
public AudioEncoder(EncoderSettings settings, string path, Stream IO = null)
|
||||
{
|
||||
m_settings = settings;
|
||||
_path = path;
|
||||
_IO = IO ?? new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read);
|
||||
_bw = new BinaryWriter(_IO);
|
||||
}
|
||||
|
||||
public void WriteChunk(uint fcc, byte[] data)
|
||||
{
|
||||
if (_sampleLen > 0)
|
||||
throw new Exception("data already written, no chunks allowed");
|
||||
if (_chunks == null)
|
||||
{
|
||||
_chunks = new List<byte[]>();
|
||||
_chunkFCCs = new List<uint>();
|
||||
}
|
||||
_chunkFCCs.Add(fcc);
|
||||
_chunks.Add(data);
|
||||
hdrLen += 8 + data.Length + (data.Length & 1);
|
||||
}
|
||||
|
||||
private void WriteHeaders()
|
||||
{
|
||||
const uint fccRIFF = 0x46464952;
|
||||
const uint fccWAVE = 0x45564157;
|
||||
const uint fccFormat = 0x20746D66;
|
||||
const uint fccData = 0x61746164;
|
||||
|
||||
bool wavex = (Settings.PCM.BitsPerSample != 16 && Settings.PCM.BitsPerSample != 24) || Settings.PCM.ChannelMask != AudioPCMConfig.GetDefaultChannelMask(Settings.PCM.ChannelCount);
|
||||
|
||||
hdrLen += 36 + (wavex ? 24 : 0) + 8;
|
||||
|
||||
uint dataLen = (uint)(_finalSampleCount * Settings.PCM.BlockAlign);
|
||||
uint dataLenPadded = dataLen + (dataLen & 1);
|
||||
|
||||
_bw.Write(fccRIFF);
|
||||
if (_finalSampleCount <= 0)
|
||||
_bw.Write((uint)0xffffffff);
|
||||
else
|
||||
_bw.Write((uint)(dataLenPadded + hdrLen - 8));
|
||||
_bw.Write(fccWAVE);
|
||||
_bw.Write(fccFormat);
|
||||
if (wavex)
|
||||
{
|
||||
_bw.Write((uint)40);
|
||||
_bw.Write((ushort)0xfffe); // WAVEX follows
|
||||
}
|
||||
else
|
||||
{
|
||||
_bw.Write((uint)16);
|
||||
_bw.Write((ushort)1); // PCM
|
||||
}
|
||||
_bw.Write((ushort)Settings.PCM.ChannelCount);
|
||||
_bw.Write((uint)Settings.PCM.SampleRate);
|
||||
_bw.Write((uint)(Settings.PCM.SampleRate * Settings.PCM.BlockAlign));
|
||||
_bw.Write((ushort)Settings.PCM.BlockAlign);
|
||||
_bw.Write((ushort)((Settings.PCM.BitsPerSample + 7) / 8 * 8));
|
||||
if (wavex)
|
||||
{
|
||||
_bw.Write((ushort)22); // length of WAVEX structure
|
||||
_bw.Write((ushort)Settings.PCM.BitsPerSample);
|
||||
_bw.Write((uint)Settings.PCM.ChannelMask);
|
||||
_bw.Write((ushort)1); // PCM Guid
|
||||
_bw.Write((ushort)0);
|
||||
_bw.Write((ushort)0);
|
||||
_bw.Write((ushort)0x10);
|
||||
_bw.Write((byte)0x80);
|
||||
_bw.Write((byte)0x00);
|
||||
_bw.Write((byte)0x00);
|
||||
_bw.Write((byte)0xaa);
|
||||
_bw.Write((byte)0x00);
|
||||
_bw.Write((byte)0x38);
|
||||
_bw.Write((byte)0x9b);
|
||||
_bw.Write((byte)0x71);
|
||||
}
|
||||
if (_chunks != null)
|
||||
for (int i = 0; i < _chunks.Count; i++)
|
||||
{
|
||||
_bw.Write(_chunkFCCs[i]);
|
||||
_bw.Write((uint)_chunks[i].Length);
|
||||
_bw.Write(_chunks[i]);
|
||||
if ((_chunks[i].Length & 1) != 0)
|
||||
_bw.Write((byte)0);
|
||||
}
|
||||
|
||||
_bw.Write(fccData);
|
||||
if (_finalSampleCount <= 0)
|
||||
_bw.Write((uint)0xffffffff);
|
||||
else
|
||||
_bw.Write(dataLen);
|
||||
|
||||
_headersWritten = true;
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
if (_finalSampleCount <= 0 && _IO.CanSeek)
|
||||
{
|
||||
long dataLen = _sampleLen * Settings.PCM.BlockAlign;
|
||||
long dataLenPadded = dataLen + (dataLen & 1);
|
||||
if (dataLenPadded + hdrLen - 8 < 0xffffffff)
|
||||
{
|
||||
if ((dataLen & 1) == 1)
|
||||
_bw.Write((byte)0);
|
||||
|
||||
_bw.Seek(4, SeekOrigin.Begin);
|
||||
_bw.Write((uint)(dataLenPadded + hdrLen - 8));
|
||||
|
||||
_bw.Seek((int)hdrLen - 4, SeekOrigin.Begin);
|
||||
_bw.Write((uint)dataLen);
|
||||
}
|
||||
}
|
||||
|
||||
_bw.Close();
|
||||
|
||||
_bw = null;
|
||||
_IO = null;
|
||||
|
||||
if (_finalSampleCount > 0 && _sampleLen != _finalSampleCount)
|
||||
throw new Exception("Samples written differs from the expected sample count.");
|
||||
}
|
||||
|
||||
public void Delete()
|
||||
{
|
||||
_bw.Close();
|
||||
_bw = null;
|
||||
_IO = null;
|
||||
if (_path != "")
|
||||
File.Delete(_path);
|
||||
}
|
||||
|
||||
public void Write(AudioBuffer buff)
|
||||
{
|
||||
if (buff.Length == 0)
|
||||
return;
|
||||
buff.Prepare(this);
|
||||
if (!_headersWritten)
|
||||
WriteHeaders();
|
||||
_IO.Write(buff.Bytes, 0, buff.ByteLength);
|
||||
_sampleLen += buff.Length;
|
||||
}
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace CUETools.Codecs.WAV
|
||||
{
|
||||
[AudioEncoderClass(typeof(EncoderSettings))]
|
||||
public class AudioEncoder : IAudioDest
|
||||
{
|
||||
private Stream _IO;
|
||||
private BinaryWriter _bw;
|
||||
private long _sampleLen;
|
||||
private string _path;
|
||||
private long hdrLen = 0;
|
||||
private bool _headersWritten = false;
|
||||
private long _finalSampleCount = -1;
|
||||
private List<byte[]> _chunks = null;
|
||||
private List<uint> _chunkFCCs = null;
|
||||
|
||||
public long Position
|
||||
{
|
||||
get
|
||||
{
|
||||
return _sampleLen;
|
||||
}
|
||||
}
|
||||
|
||||
public long FinalSampleCount
|
||||
{
|
||||
set { _finalSampleCount = value; }
|
||||
}
|
||||
|
||||
private EncoderSettings m_settings;
|
||||
public AudioEncoderSettings Settings => m_settings;
|
||||
|
||||
public string Path { get { return _path; } }
|
||||
|
||||
public AudioEncoder(EncoderSettings settings, string path, Stream IO = null)
|
||||
{
|
||||
m_settings = settings;
|
||||
_path = path;
|
||||
_IO = IO ?? new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read);
|
||||
_bw = new BinaryWriter(_IO);
|
||||
}
|
||||
|
||||
public void WriteChunk(uint fcc, byte[] data)
|
||||
{
|
||||
if (_sampleLen > 0)
|
||||
throw new Exception("data already written, no chunks allowed");
|
||||
if (_chunks == null)
|
||||
{
|
||||
_chunks = new List<byte[]>();
|
||||
_chunkFCCs = new List<uint>();
|
||||
}
|
||||
_chunkFCCs.Add(fcc);
|
||||
_chunks.Add(data);
|
||||
hdrLen += 8 + data.Length + (data.Length & 1);
|
||||
}
|
||||
|
||||
private void WriteHeaders()
|
||||
{
|
||||
const uint fccRIFF = 0x46464952;
|
||||
const uint fccWAVE = 0x45564157;
|
||||
const uint fccFormat = 0x20746D66;
|
||||
const uint fccData = 0x61746164;
|
||||
|
||||
bool wavex = (Settings.PCM.BitsPerSample != 16 && Settings.PCM.BitsPerSample != 24) || Settings.PCM.ChannelMask != AudioPCMConfig.GetDefaultChannelMask(Settings.PCM.ChannelCount);
|
||||
|
||||
hdrLen += 36 + (wavex ? 24 : 0) + 8;
|
||||
|
||||
uint dataLen = (uint)(_finalSampleCount * Settings.PCM.BlockAlign);
|
||||
uint dataLenPadded = dataLen + (dataLen & 1);
|
||||
|
||||
_bw.Write(fccRIFF);
|
||||
if (_finalSampleCount <= 0)
|
||||
_bw.Write((uint)0xffffffff);
|
||||
else
|
||||
_bw.Write((uint)(dataLenPadded + hdrLen - 8));
|
||||
_bw.Write(fccWAVE);
|
||||
_bw.Write(fccFormat);
|
||||
if (wavex)
|
||||
{
|
||||
_bw.Write((uint)40);
|
||||
_bw.Write((ushort)0xfffe); // WAVEX follows
|
||||
}
|
||||
else
|
||||
{
|
||||
_bw.Write((uint)16);
|
||||
_bw.Write((ushort)1); // PCM
|
||||
}
|
||||
_bw.Write((ushort)Settings.PCM.ChannelCount);
|
||||
_bw.Write((uint)Settings.PCM.SampleRate);
|
||||
_bw.Write((uint)(Settings.PCM.SampleRate * Settings.PCM.BlockAlign));
|
||||
_bw.Write((ushort)Settings.PCM.BlockAlign);
|
||||
_bw.Write((ushort)((Settings.PCM.BitsPerSample + 7) / 8 * 8));
|
||||
if (wavex)
|
||||
{
|
||||
_bw.Write((ushort)22); // length of WAVEX structure
|
||||
_bw.Write((ushort)Settings.PCM.BitsPerSample);
|
||||
_bw.Write((uint)Settings.PCM.ChannelMask);
|
||||
_bw.Write((ushort)1); // PCM Guid
|
||||
_bw.Write((ushort)0);
|
||||
_bw.Write((ushort)0);
|
||||
_bw.Write((ushort)0x10);
|
||||
_bw.Write((byte)0x80);
|
||||
_bw.Write((byte)0x00);
|
||||
_bw.Write((byte)0x00);
|
||||
_bw.Write((byte)0xaa);
|
||||
_bw.Write((byte)0x00);
|
||||
_bw.Write((byte)0x38);
|
||||
_bw.Write((byte)0x9b);
|
||||
_bw.Write((byte)0x71);
|
||||
}
|
||||
if (_chunks != null)
|
||||
for (int i = 0; i < _chunks.Count; i++)
|
||||
{
|
||||
_bw.Write(_chunkFCCs[i]);
|
||||
_bw.Write((uint)_chunks[i].Length);
|
||||
_bw.Write(_chunks[i]);
|
||||
if ((_chunks[i].Length & 1) != 0)
|
||||
_bw.Write((byte)0);
|
||||
}
|
||||
|
||||
_bw.Write(fccData);
|
||||
if (_finalSampleCount <= 0)
|
||||
_bw.Write((uint)0xffffffff);
|
||||
else
|
||||
_bw.Write(dataLen);
|
||||
|
||||
_headersWritten = true;
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
if (_finalSampleCount <= 0 && _IO.CanSeek)
|
||||
{
|
||||
long dataLen = _sampleLen * Settings.PCM.BlockAlign;
|
||||
long dataLenPadded = dataLen + (dataLen & 1);
|
||||
if (dataLenPadded + hdrLen - 8 < 0xffffffff)
|
||||
{
|
||||
if ((dataLen & 1) == 1)
|
||||
_bw.Write((byte)0);
|
||||
|
||||
_bw.Seek(4, SeekOrigin.Begin);
|
||||
_bw.Write((uint)(dataLenPadded + hdrLen - 8));
|
||||
|
||||
_bw.Seek((int)hdrLen - 4, SeekOrigin.Begin);
|
||||
_bw.Write((uint)dataLen);
|
||||
}
|
||||
}
|
||||
|
||||
_bw.Close();
|
||||
|
||||
_bw = null;
|
||||
_IO = null;
|
||||
|
||||
if (_finalSampleCount > 0 && _sampleLen != _finalSampleCount)
|
||||
throw new Exception("Samples written differs from the expected sample count.");
|
||||
}
|
||||
|
||||
public void Delete()
|
||||
{
|
||||
_bw.Close();
|
||||
_bw = null;
|
||||
_IO = null;
|
||||
if (_path != "")
|
||||
File.Delete(_path);
|
||||
}
|
||||
|
||||
public void Write(AudioBuffer buff)
|
||||
{
|
||||
if (buff.Length == 0)
|
||||
return;
|
||||
buff.Prepare(this);
|
||||
if (!_headersWritten)
|
||||
WriteHeaders();
|
||||
_IO.Write(buff.Bytes, 0, buff.ByteLength);
|
||||
_sampleLen += buff.Length;
|
||||
}
|
||||
}
|
||||
}
|
||||
19
CUETools.Codecs/WAV/DecoderSettings.cs
Normal file
19
CUETools.Codecs/WAV/DecoderSettings.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
using System;
|
||||
|
||||
namespace CUETools.Codecs.WAV
|
||||
{
|
||||
public class DecoderSettings : AudioDecoderSettings
|
||||
{
|
||||
public override string Name => "cuetools";
|
||||
|
||||
public override string Extension => "wav";
|
||||
|
||||
public override Type DecoderType => typeof(AudioDecoder);
|
||||
|
||||
public override int Priority => 2;
|
||||
|
||||
public DecoderSettings() : base() { }
|
||||
|
||||
public bool IgnoreChunkSizes;
|
||||
}
|
||||
}
|
||||
@@ -1,29 +1,29 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace CUETools.Codecs.WAV
|
||||
{
|
||||
public class EncoderSettings : AudioEncoderSettings
|
||||
{
|
||||
public override string Extension => "wav";
|
||||
|
||||
public override string Name => "cuetools";
|
||||
|
||||
public override Type EncoderType => typeof(WAV.AudioEncoder);
|
||||
|
||||
public override int Priority => 10;
|
||||
|
||||
public override bool Lossless => true;
|
||||
|
||||
public EncoderSettings()
|
||||
: this(null)
|
||||
{
|
||||
}
|
||||
|
||||
public EncoderSettings(AudioPCMConfig pcm)
|
||||
: base(pcm)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace CUETools.Codecs.WAV
|
||||
{
|
||||
public class EncoderSettings : AudioEncoderSettings
|
||||
{
|
||||
public override string Extension => "wav";
|
||||
|
||||
public override string Name => "cuetools";
|
||||
|
||||
public override Type EncoderType => typeof(WAV.AudioEncoder);
|
||||
|
||||
public override int Priority => 10;
|
||||
|
||||
public override bool Lossless => true;
|
||||
|
||||
public EncoderSettings()
|
||||
: this(null)
|
||||
{
|
||||
}
|
||||
|
||||
public EncoderSettings(AudioPCMConfig pcm)
|
||||
: base(pcm)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -244,7 +244,7 @@ namespace CUETools.FLACCL.cmd
|
||||
if (input_file == "-")
|
||||
audioSource = new Codecs.WAV.AudioDecoder(new Codecs.WAV.DecoderSettings() { IgnoreChunkSizes = true }, "", Console.OpenStandardInput());
|
||||
else if (input_file == "nul")
|
||||
audioSource = new SilenceGenerator(new AudioPCMConfig(input_bps, input_ch, input_rate), input_len, input_val);
|
||||
audioSource = new Codecs.NULL.AudioDecoder(new AudioPCMConfig(input_bps, input_ch, input_rate), input_len, input_val);
|
||||
else if (File.Exists(input_file) && Path.GetExtension(input_file) == ".wav")
|
||||
audioSource = new Codecs.WAV.AudioDecoder(new Codecs.WAV.DecoderSettings(), input_file);
|
||||
else if (File.Exists(input_file) && Path.GetExtension(input_file) == ".flac")
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace CUETools.Processor
|
||||
long len;
|
||||
if (!long.TryParse(slen, out len))
|
||||
len = CDImageLayout.TimeFromString(slen) * 588;
|
||||
return new SilenceGenerator(len);
|
||||
return new Codecs.NULL.AudioDecoder(len);
|
||||
}
|
||||
}
|
||||
if (extension == ".bin")
|
||||
@@ -51,7 +51,7 @@ namespace CUETools.Processor
|
||||
{
|
||||
IAudioDest dest;
|
||||
if (audioEncoderType == AudioEncoderType.NoAudio || extension == ".dummy")
|
||||
return new DummyWriter(path, new AudioEncoderSettings(pcm)) { FinalSampleCount = finalSampleCount };
|
||||
return new Codecs.NULL.AudioEncoder(path, new AudioEncoderSettings(pcm)) { FinalSampleCount = finalSampleCount };
|
||||
CUEToolsFormat fmt;
|
||||
if (!extension.StartsWith(".") || !config.formats.TryGetValue(extension.Substring(1), out fmt))
|
||||
throw new Exception("Unsupported audio type: " + path);
|
||||
|
||||
@@ -71,8 +71,8 @@ namespace CUETools.Processor
|
||||
public bool CopyAlbumArt { get; set; }
|
||||
public string ArLogFilenameFormat { get; set; }
|
||||
public string AlArtFilenameFormat { get; set; }
|
||||
public CUEToolsUDCEncoderList Encoders => encoders;
|
||||
public CUEToolsUDCDecoderList Decoders => decoders;
|
||||
public EncoderListViewModel Encoders => encoders;
|
||||
public DecoderListViewModel Decoders => decoders;
|
||||
|
||||
public CUEConfig()
|
||||
: base(CUEProcessorPlugins.encs, CUEProcessorPlugins.decs)
|
||||
@@ -312,9 +312,9 @@ namespace CUETools.Processor
|
||||
|
||||
int nDecoders = 0;
|
||||
foreach (var decoder in decoders)
|
||||
if (decoder.decoderSettings is CommandLineDecoderSettings)
|
||||
if (decoder.decoderSettings is Codecs.CommandLine.DecoderSettings)
|
||||
{
|
||||
var settings = decoder.decoderSettings as CommandLineDecoderSettings;
|
||||
var settings = decoder.decoderSettings as Codecs.CommandLine.DecoderSettings;
|
||||
sw.Save(string.Format("ExternalDecoder{0}Name", nDecoders), settings.Name);
|
||||
sw.Save(string.Format("ExternalDecoder{0}Extension", nDecoders), settings.Extension);
|
||||
sw.Save(string.Format("ExternalDecoder{0}Path", nDecoders), settings.Path);
|
||||
@@ -434,14 +434,14 @@ namespace CUETools.Processor
|
||||
try
|
||||
{
|
||||
var jsonObject = JsonConvert.DeserializeObject(sr.Load("Encoders"),
|
||||
typeof(CUEToolsUDCEncoderList),
|
||||
typeof(EncoderListViewModel),
|
||||
new JsonSerializerSettings {
|
||||
DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate,
|
||||
TypeNameHandling = TypeNameHandling.Auto
|
||||
});
|
||||
if (jsonObject as CUEToolsUDCEncoderList == null)
|
||||
if (jsonObject as EncoderListViewModel == null)
|
||||
throw new Exception();
|
||||
encoders = jsonObject as CUEToolsUDCEncoderList;
|
||||
encoders = jsonObject as EncoderListViewModel;
|
||||
encoders.Where(x => !x.IsValid).ToList().ForEach(x => encoders.Remove(x));
|
||||
AudioEncoderSettingsViewModel tmp;
|
||||
encodersBackup.Where(x => !encoders.TryGetValue(x.Extension, x.Lossless, x.Name, out tmp)).ToList().ForEach(x => encoders.Add(x));
|
||||
@@ -503,7 +503,7 @@ namespace CUETools.Processor
|
||||
string parameters = sr.Load(string.Format("ExternalDecoder{0}Parameters", nDecoders));
|
||||
AudioDecoderSettingsViewModel decoder;
|
||||
if (!decoders.TryGetValue(extension, true, name, out decoder))
|
||||
decoders.Add(new AudioDecoderSettingsViewModel(new CommandLineDecoderSettings(name, extension, path, parameters)));
|
||||
decoders.Add(new AudioDecoderSettingsViewModel(new Codecs.CommandLine.DecoderSettings(name, extension, path, parameters)));
|
||||
else
|
||||
{
|
||||
decoder.Extension = extension;
|
||||
|
||||
@@ -3972,7 +3972,7 @@ namespace CUETools.Processor
|
||||
|
||||
if (sourceInfo.Path == null)
|
||||
{
|
||||
audioSource = new SilenceGenerator(sourceInfo.Offset + sourceInfo.Length);
|
||||
audioSource = new Codecs.NULL.AudioDecoder(sourceInfo.Offset + sourceInfo.Length);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user