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:
Grigory Chudov
2018-03-23 20:26:28 -04:00
parent 16fccfe5c9
commit ca8bb2fff6
22 changed files with 1301 additions and 1292 deletions

View File

@@ -0,0 +1,112 @@
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);
}
}
}

View File

@@ -0,0 +1,137 @@
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;
}
}
}

View File

@@ -0,0 +1,56 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
using Newtonsoft.Json;
namespace CUETools.Codecs.CommandLine
{
[JsonObject(MemberSerialization.OptIn)]
public class DecoderSettings : AudioDecoderSettings
{
public override string Name => name;
public override string Extension => extension;
public DecoderSettings()
: base()
{
}
public DecoderSettings(
string _name,
string _extension,
string _path,
string _parameters)
: base()
{
name = _name;
extension = _extension;
Path = _path;
Parameters = _parameters;
}
[JsonProperty]
public string name;
[JsonProperty]
public string extension;
[DefaultValue(null)]
[JsonProperty]
public string Path
{
get;
set;
}
[DefaultValue(null)]
[JsonProperty]
public string Parameters
{
get;
set;
}
}
}

View File

@@ -0,0 +1,63 @@
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;
}
}
}
}