Refactoring codecs infrastructure:

AudioWriterSettings passed to IAdioDest constructors now
AudioWriterSettings now includes AudioPCMConfig
This commit is contained in:
Grigory Chudov
2013-04-07 20:41:58 -04:00
parent b44e482dee
commit 9670c6c891
43 changed files with 652 additions and 723 deletions

View File

@@ -78,8 +78,8 @@ namespace CUEPlayer
cfg.Phase = 50;
cfg.AllowAliasing = false;
cfg.Bandwidth = 0;
_resampler = new SOXResampler(parent.Mixer.PCM, _player.PCM, cfg);
resampled = new AudioBuffer(_player.PCM, parent.Mixer.BufferSize * 2 * parent.Mixer.PCM.SampleRate / _player.PCM.SampleRate);
_resampler = new SOXResampler(parent.Mixer.PCM, _player.Settings.PCM, cfg);
resampled = new AudioBuffer(_player.Settings.PCM, parent.Mixer.BufferSize * 2 * parent.Mixer.PCM.SampleRate / _player.Settings.PCM.SampleRate);
}
catch (Exception ex)
{

View File

@@ -176,17 +176,18 @@ namespace CUETools.ALACEnc
audioSource = new AudioPipe(audioSource, 0x10000);
if (output_file == null)
output_file = Path.ChangeExtension(input_file, "m4a");
settings.PCM = audioSource.PCM;
ALACWriter alac = new ALACWriter((output_file == "-" || output_file == "nul") ? "" : output_file,
output_file == "-" ? Console.OpenStandardOutput() :
output_file == "nul" ? new NullStream() : null,
audioSource.PCM);
settings);
alac.FinalSampleCount = audioSource.Length;
IAudioDest audioDest = alac;
AudioBuffer buff = new AudioBuffer(audioSource, 0x10000);
try
{
alac.Settings = settings;
settings.Validate();
if (stereo_method != null)
alac.StereoMethod = Alac.LookupStereoMethod(stereo_method);
if (order_method != null)

View File

@@ -935,18 +935,8 @@ namespace CUETools.AccurateRip
{
get
{
return new AudioEncoderSettings();
return new AudioEncoderSettings(AudioPCMConfig.RedBook);
}
set
{
if (value != null && value.GetType() != typeof(AudioEncoderSettings))
throw new Exception("Unsupported options " + value);
}
}
public AudioPCMConfig PCM
{
get { return AudioPCMConfig.RedBook; }
}
public CDImageLayout TOC

View File

@@ -417,18 +417,8 @@ namespace CUETools.AccurateRip
{
get
{
return new AudioEncoderSettings();
return new AudioEncoderSettings(AudioPCMConfig.RedBook);
}
set
{
if (value != null && value.GetType() != typeof(AudioEncoderSettings))
throw new Exception("Unsupported options " + value);
}
}
public AudioPCMConfig PCM
{
get { return AudioPCMConfig.RedBook; }
}
public string Path

View File

@@ -35,10 +35,9 @@ namespace CUETools.Codecs.ALAC
{
public class ALACWriterSettings: AudioEncoderSettings
{
public ALACWriterSettings()
public ALACWriterSettings()
: base("0 1 2 3 4 5 6 7 8 9 10", "3")
{
DoVerify = false;
{
}
public override bool IsValid()
@@ -103,15 +102,13 @@ namespace CUETools.Codecs.ALAC
List<int> chunk_pos;
AudioPCMConfig _pcm;
public ALACWriter(string path, Stream IO, AudioPCMConfig pcm)
public ALACWriter(string path, Stream IO, ALACWriterSettings settings)
{
_pcm = pcm;
m_settings = settings;
if (_pcm.BitsPerSample != 16)
if (Settings.PCM.BitsPerSample != 16)
throw new Exception("Bits per sample must be 16.");
if (_pcm.ChannelCount != 2)
if (Settings.PCM.ChannelCount != 2)
throw new Exception("ChannelCount must be 2.");
_path = path;
@@ -120,18 +117,18 @@ namespace CUETools.Codecs.ALAC
if (_IO != null && !_IO.CanSeek)
throw new NotSupportedException("stream doesn't support seeking");
samplesBuffer = new int[Alac.MAX_BLOCKSIZE * (_pcm.ChannelCount == 2 ? 5 : _pcm.ChannelCount)];
residualBuffer = new int[Alac.MAX_BLOCKSIZE * (_pcm.ChannelCount == 2 ? 6 : _pcm.ChannelCount + 1)];
samplesBuffer = new int[Alac.MAX_BLOCKSIZE * (Settings.PCM.ChannelCount == 2 ? 5 : Settings.PCM.ChannelCount)];
residualBuffer = new int[Alac.MAX_BLOCKSIZE * (Settings.PCM.ChannelCount == 2 ? 6 : Settings.PCM.ChannelCount + 1)];
windowBuffer = new float[Alac.MAX_BLOCKSIZE * 2 * Alac.MAX_LPC_WINDOWS];
eparams.set_defaults(5);
eparams.set_defaults(m_settings.EncoderModeIndex);
frame = new ALACFrame(_pcm.ChannelCount == 2 ? 5 : _pcm.ChannelCount);
frame = new ALACFrame(Settings.PCM.ChannelCount == 2 ? 5 : Settings.PCM.ChannelCount);
chunk_pos = new List<int>();
}
public ALACWriter(string path, AudioPCMConfig pcm)
: this(path, null, pcm)
public ALACWriter(string path, ALACWriterSettings settings)
: this(path, null, settings)
{
}
@@ -143,7 +140,7 @@ namespace CUETools.Codecs.ALAC
}
}
ALACWriterSettings m_settings = new ALACWriterSettings();
ALACWriterSettings m_settings;
public AudioEncoderSettings Settings
{
@@ -151,12 +148,6 @@ namespace CUETools.Codecs.ALAC
{
return m_settings;
}
set
{
m_settings = value.Clone<ALACWriterSettings>();
var _compressionLevel = m_settings.EncoderModeIndex;
eparams.set_defaults(_compressionLevel);
}
}
#if INTEROP
@@ -446,11 +437,6 @@ namespace CUETools.Codecs.ALAC
}
}
public AudioPCMConfig PCM
{
get { return _pcm; }
}
/// <summary>
/// Copy channel-interleaved input samples into separate subframes
/// </summary>
@@ -461,13 +447,13 @@ namespace CUETools.Codecs.ALAC
{
fixed (int* fsamples = samplesBuffer, src = &samples[pos, 0])
{
if (_pcm.ChannelCount == 2)
if (Settings.PCM.ChannelCount == 2)
AudioSamples.Deinterlace(fsamples + samplesInBuffer, fsamples + Alac.MAX_BLOCKSIZE + samplesInBuffer, src, block);
else
for (int ch = 0; ch < _pcm.ChannelCount; ch++)
for (int ch = 0; ch < Settings.PCM.ChannelCount; ch++)
{
int* psamples = fsamples + ch * Alac.MAX_BLOCKSIZE + samplesInBuffer;
int channels = _pcm.ChannelCount;
int channels = Settings.PCM.ChannelCount;
for (int i = 0; i < block; i++)
psamples[i] = src[i * channels + ch];
}
@@ -794,7 +780,7 @@ namespace CUETools.Codecs.ALAC
frame.current.order = order;
frame.current.window = iWindow;
int bps = _pcm.BitsPerSample + _pcm.ChannelCount - 1;
int bps = Settings.PCM.BitsPerSample + Settings.PCM.ChannelCount - 1;
int* coefs = stackalloc int[lpc.MAX_LPC_ORDER];
@@ -849,7 +835,7 @@ namespace CUETools.Codecs.ALAC
{
int* smp = frame.subframes[ch].samples;
int i, n = frame.blocksize;
int bps = _pcm.BitsPerSample + _pcm.ChannelCount - 1;
int bps = Settings.PCM.BitsPerSample + Settings.PCM.ChannelCount - 1;
// FIXED
//if (0 == (2 & frame.subframes[ch].done_fixed) && (pass != 1 || n < eparams.max_prediction_order))
@@ -896,7 +882,7 @@ namespace CUETools.Codecs.ALAC
unsafe void output_frame_header(ALACFrame frame, BitWriter bitwriter)
{
bitwriter.writebits(3, _pcm.ChannelCount - 1);
bitwriter.writebits(3, Settings.PCM.ChannelCount - 1);
bitwriter.writebits(16, 0);
bitwriter.writebits(1, frame.blocksize != m_blockSize ? 1 : 0); // sample count is in the header
bitwriter.writebits(2, 0); // wasted bytes
@@ -907,7 +893,7 @@ namespace CUETools.Codecs.ALAC
{
bitwriter.writebits(8, frame.interlacing_shift);
bitwriter.writebits(8, frame.interlacing_leftweight);
for (int ch = 0; ch < _pcm.ChannelCount; ch++)
for (int ch = 0; ch < Settings.PCM.ChannelCount; ch++)
{
bitwriter.writebits(4, 0); // prediction type
bitwriter.writebits(4, frame.subframes[ch].best.shift);
@@ -982,7 +968,7 @@ namespace CUETools.Codecs.ALAC
unsafe void estimate_frame(ALACFrame frame, bool do_midside)
{
int subframes = do_midside ? 5 : _pcm.ChannelCount;
int subframes = do_midside ? 5 : Settings.PCM.ChannelCount;
switch (eparams.stereo_method)
{
@@ -1041,7 +1027,7 @@ namespace CUETools.Codecs.ALAC
return total + bitsBest;
}
for (int ch = 0; ch < _pcm.ChannelCount; ch++)
for (int ch = 0; ch < Settings.PCM.ChannelCount; ch++)
total += frame.subframes[ch].best.size;
return total;
@@ -1052,14 +1038,14 @@ namespace CUETools.Codecs.ALAC
switch (eparams.stereo_method)
{
case StereoMethod.Estimate:
for (int ch = 0; ch < _pcm.ChannelCount; ch++)
for (int ch = 0; ch < Settings.PCM.ChannelCount; ch++)
{
frame.subframes[ch].best.size = AudioSamples.UINT32_MAX;
encode_residual_pass2(frame, ch);
}
break;
case StereoMethod.Evaluate:
for (int ch = 0; ch < _pcm.ChannelCount; ch++)
for (int ch = 0; ch < Settings.PCM.ChannelCount; ch++)
encode_residual_pass2(frame, ch);
break;
case StereoMethod.Search:
@@ -1107,15 +1093,15 @@ namespace CUETools.Codecs.ALAC
}
frame.window_buffer = window;
int bps = _pcm.BitsPerSample + _pcm.ChannelCount - 1;
if (_pcm.ChannelCount != 2 || frame.blocksize <= 32 || eparams.stereo_method == StereoMethod.Independent)
int bps = Settings.PCM.BitsPerSample + Settings.PCM.ChannelCount - 1;
if (Settings.PCM.ChannelCount != 2 || frame.blocksize <= 32 || eparams.stereo_method == StereoMethod.Independent)
{
frame.current.residual = r + _pcm.ChannelCount * Alac.MAX_BLOCKSIZE;
frame.current.residual = r + Settings.PCM.ChannelCount * Alac.MAX_BLOCKSIZE;
for (int ch = 0; ch < _pcm.ChannelCount; ch++)
for (int ch = 0; ch < Settings.PCM.ChannelCount; ch++)
frame.subframes[ch].Init(s + ch * Alac.MAX_BLOCKSIZE, r + ch * Alac.MAX_BLOCKSIZE);
for (int ch = 0; ch < _pcm.ChannelCount; ch++)
for (int ch = 0; ch < Settings.PCM.ChannelCount; ch++)
encode_residual_pass2(frame, ch);
}
else
@@ -1131,7 +1117,7 @@ namespace CUETools.Codecs.ALAC
encode_estimated_frame(frame);
}
for (int ch = 0; ch < _pcm.ChannelCount; ch++)
for (int ch = 0; ch < Settings.PCM.ChannelCount; ch++)
{
if (eparams.min_modifier == eparams.max_modifier)
frame.subframes[ch].best.ricemodifier = eparams.max_modifier;
@@ -1141,19 +1127,19 @@ namespace CUETools.Codecs.ALAC
}
uint fs = measure_frame_size(frame, false);
frame.type = ((int)fs > frame.blocksize * _pcm.ChannelCount * bps) ? FrameType.Verbatim : FrameType.Compressed;
frame.type = ((int)fs > frame.blocksize * Settings.PCM.ChannelCount * bps) ? FrameType.Verbatim : FrameType.Compressed;
BitWriter bitwriter = new BitWriter(frame_buffer, 0, max_frame_size);
output_frame_header(frame, bitwriter);
if (frame.type == FrameType.Verbatim)
{
int obps = _pcm.BitsPerSample;
int obps = Settings.PCM.BitsPerSample;
for (int i = 0; i < frame.blocksize; i++)
for (int ch = 0; ch < _pcm.ChannelCount; ch++)
for (int ch = 0; ch < Settings.PCM.ChannelCount; ch++)
bitwriter.writebits_signed(obps, frame.subframes[ch].samples[i]);
}
else if (frame.type == FrameType.Compressed)
{
for (int ch = 0; ch < _pcm.ChannelCount; ch++)
for (int ch = 0; ch < Settings.PCM.ChannelCount; ch++)
alac_entropy_coder(bitwriter, frame.subframes[ch].best.residual, frame.blocksize,
bps, frame.subframes[ch].best.ricemodifier);
}
@@ -1177,7 +1163,7 @@ namespace CUETools.Codecs.ALAC
if (verify != null)
{
fixed (int* s = verifyBuffer, r = samplesBuffer)
for (int ch = 0; ch < _pcm.ChannelCount; ch++)
for (int ch = 0; ch < Settings.PCM.ChannelCount; ch++)
AudioSamples.MemCpy(s + ch * Alac.MAX_BLOCKSIZE, r + ch * Alac.MAX_BLOCKSIZE, blocksize);
}
@@ -1196,13 +1182,13 @@ namespace CUETools.Codecs.ALAC
int decoded = verify.DecodeFrame(frame_buffer, 0, fs);
if (decoded != fs || verify.Remaining != bs)
throw new Exception("validation failed!");
int[,] deinterlaced = new int[bs, _pcm.ChannelCount];
int[,] deinterlaced = new int[bs, Settings.PCM.ChannelCount];
verify.deinterlace(deinterlaced, 0, bs);
fixed (int* s = verifyBuffer, r = deinterlaced)
{
int channels = _pcm.ChannelCount;
int channels = Settings.PCM.ChannelCount;
for (int i = 0; i < bs; i++)
for (int ch = 0; ch < _pcm.ChannelCount; ch++)
for (int ch = 0; ch < Settings.PCM.ChannelCount; ch++)
if (r[i * channels + ch] != s[ch * Alac.MAX_BLOCKSIZE + i])
throw new Exception("validation failed!");
}
@@ -1211,7 +1197,7 @@ namespace CUETools.Codecs.ALAC
if (bs < blocksize)
{
fixed (int* s = samplesBuffer)
for (int ch = 0; ch < _pcm.ChannelCount; ch++)
for (int ch = 0; ch < Settings.PCM.ChannelCount; ch++)
AudioSamples.MemCpy(s + ch * Alac.MAX_BLOCKSIZE, s + bs + ch * Alac.MAX_BLOCKSIZE, blocksize - bs);
}
@@ -1297,7 +1283,7 @@ namespace CUETools.Codecs.ALAC
bitwriter.writebits(32, 0);
bitwriter.writebits(_creationTime.Value);
bitwriter.writebits(_creationTime.Value);
bitwriter.writebits(32, _pcm.SampleRate);
bitwriter.writebits(32, Settings.PCM.SampleRate);
bitwriter.writebits(32, sample_count);
bitwriter.writebits(32, 0x00010000); // reserved (preferred rate) 1.0 = normal
bitwriter.writebits(16, 0x0100); // reserved (preferred volume) 1.0 = normal
@@ -1374,7 +1360,7 @@ namespace CUETools.Codecs.ALAC
bitwriter.writebits(16, 16); // reserved bps
bitwriter.writebits(16, 0); // reserved compression ID
bitwriter.writebits(16, 0); // packet size
bitwriter.writebits(16, _pcm.SampleRate); // time scale
bitwriter.writebits(16, Settings.PCM.SampleRate); // time scale
bitwriter.writebits(16, 0); // reserved
chunk_start(bitwriter);
{
@@ -1389,15 +1375,15 @@ namespace CUETools.Codecs.ALAC
bitwriter.writebits(32, 0); // reserved
bitwriter.writebits(32, m_blockSize); // max frame size
bitwriter.writebits(8, 0); // reserved
bitwriter.writebits(8, _pcm.BitsPerSample);
bitwriter.writebits(8, Settings.PCM.BitsPerSample);
bitwriter.writebits(8, history_mult);
bitwriter.writebits(8, initial_history);
bitwriter.writebits(8, k_modifier);
bitwriter.writebits(8, _pcm.ChannelCount); // channels
bitwriter.writebits(8, Settings.PCM.ChannelCount); // channels
bitwriter.writebits(16, 0); // reserved or 0x00 0xff????
bitwriter.writebits(32, max_fs);
bitwriter.writebits(32, (int)(8 * sum_fs * _pcm.SampleRate / sample_count)); // average bitrate
bitwriter.writebits(32, _pcm.SampleRate);
bitwriter.writebits(32, (int)(8 * sum_fs * Settings.PCM.SampleRate / sample_count)); // average bitrate
bitwriter.writebits(32, Settings.PCM.SampleRate);
}
chunk_end(bitwriter);
}
@@ -1487,7 +1473,7 @@ namespace CUETools.Codecs.ALAC
bitwriter.writebits(32, 0); // version & flags
bitwriter.writebits(_creationTime.Value);
bitwriter.writebits(_creationTime.Value);
bitwriter.writebits(32, _pcm.SampleRate);
bitwriter.writebits(32, Settings.PCM.SampleRate);
bitwriter.writebits(32, sample_count);
bitwriter.writebits(16, 0x55c4); // language
bitwriter.writebits(16, 0); // quality
@@ -1646,30 +1632,30 @@ namespace CUETools.Codecs.ALAC
void encode_init()
{
// FIXME: For now, only 44100 samplerate is supported
if (_pcm.SampleRate != 44100)
if (Settings.PCM.SampleRate != 44100)
throw new Exception("non-standard samplerate");
// FIXME: For now, only 16-bit encoding is supported
if (_pcm.BitsPerSample != 16)
if (Settings.PCM.BitsPerSample != 16)
throw new Exception("non-standard bps");
m_blockSize =
m_settings.BlockSize != 0 ? m_settings.BlockSize :
select_blocksize(_pcm.SampleRate, eparams.block_time_ms);
select_blocksize(Settings.PCM.SampleRate, eparams.block_time_ms);
// set maximum encoded frame size (if larger, re-encodes in verbatim mode)
if (_pcm.ChannelCount == 2)
max_frame_size = 16 + ((m_blockSize * (_pcm.BitsPerSample + _pcm.BitsPerSample + 1) + 7) >> 3);
if (Settings.PCM.ChannelCount == 2)
max_frame_size = 16 + ((m_blockSize * (Settings.PCM.BitsPerSample + Settings.PCM.BitsPerSample + 1) + 7) >> 3);
else
max_frame_size = 16 + ((m_blockSize * _pcm.ChannelCount * _pcm.BitsPerSample + 7) >> 3);
max_frame_size = 16 + ((m_blockSize * Settings.PCM.ChannelCount * Settings.PCM.BitsPerSample + 7) >> 3);
frame_buffer = new byte[max_frame_size];
_sample_byte_size = new uint[Math.Max(0x100, sample_count / m_blockSize + 1)];
if (m_settings.DoVerify)
{
verify = new ALACReader(_pcm, history_mult, initial_history, k_modifier, m_blockSize);
verifyBuffer = new int[Alac.MAX_BLOCKSIZE * _pcm.ChannelCount];
verify = new ALACReader(Settings.PCM, history_mult, initial_history, k_modifier, m_blockSize);
verifyBuffer = new int[Alac.MAX_BLOCKSIZE * Settings.PCM.ChannelCount];
}
if (sample_count < 0)

View File

@@ -265,14 +265,13 @@ namespace CUETools { namespace Codecs { namespace APE {
public ref class APEWriter : IAudioDest
{
public:
APEWriter(String^ path, AudioPCMConfig^ pcm)
APEWriter(String^ path, APEWriterSettings^ settings)
{
_settings = gcnew APEWriterSettings();
_pcm = pcm;
_settings = settings;
if (_pcm->ChannelCount != 1 && _pcm->ChannelCount != 2)
if (_settings->PCM->ChannelCount != 1 && _settings->PCM->ChannelCount != 2)
throw gcnew Exception("Only stereo and mono audio formats are allowed.");
if (_pcm->BitsPerSample != 16 && _pcm->BitsPerSample != 24)
if (_settings->PCM->BitsPerSample != 16 && _settings->PCM->BitsPerSample != 24)
throw gcnew Exception("Monkey's Audio doesn't support selected bits per sample value.");
_path = path;
@@ -342,14 +341,6 @@ namespace CUETools { namespace Codecs { namespace APE {
}
}
virtual property AudioPCMConfig^ PCM
{
AudioPCMConfig^ get()
{
return _pcm;
}
}
virtual void Write(AudioBuffer^ buff)
{
if (!_initialized)
@@ -374,18 +365,12 @@ namespace CUETools { namespace Codecs { namespace APE {
{
return _settings;
}
void set(AudioEncoderSettings^ value)
{
_settings = value->Clone<APEWriterSettings^>();
}
}
private:
IAPECompress * pAPECompress;
bool _initialized;
Int32 _finalSampleCount, _samplesWritten;
AudioPCMConfig^ _pcm;
APEWriterSettings^ _settings;
String^ _path;
Stream^ _IO;
@@ -403,13 +388,13 @@ namespace CUETools { namespace Codecs { namespace APE {
_winFileIO = new CWinFileIO(_gchIO, _gchBuffer);
WAVEFORMATEX waveFormat;
FillWaveFormatEx (&waveFormat, _pcm->SampleRate, _pcm->BitsPerSample, _pcm->ChannelCount);
FillWaveFormatEx (&waveFormat, _settings->PCM->SampleRate, _settings->PCM->BitsPerSample, _settings->PCM->ChannelCount);
Int32 _compressionLevel = (_settings->EncoderModeIndex + 1) * 1000;
int res = pAPECompress->StartEx (_winFileIO,
&waveFormat,
(_finalSampleCount == 0) ? MAX_AUDIO_BYTES_UNKNOWN : _finalSampleCount * _pcm->BlockAlign,
(_finalSampleCount == 0) ? MAX_AUDIO_BYTES_UNKNOWN : _finalSampleCount * _settings->PCM->BlockAlign,
_compressionLevel,
NULL,
CREATE_WAV_HEADER_ON_DECOMPRESSION);

View File

@@ -26,9 +26,9 @@ namespace CUETools.Codecs.CoreAudio
volatile PlaybackState playbackState;
Thread playThread;
private long _sampleOffset;
private AudioPCMConfig pcm;
private NAudio.Wave.WaveFormatExtensible outputFormat;
WaitHandle[] waitHandles;
AudioEncoderSettings m_settings;
/// <summary>
/// Playback Stopped
@@ -67,11 +67,11 @@ namespace CUETools.Codecs.CoreAudio
/// <param name="latency"></param>
public WasapiOut(MMDevice device, AudioClientShareMode shareMode, bool useEventSync, int latency, AudioPCMConfig pcm)
{
this.m_settings = new AudioEncoderSettings(pcm);
this.audioClient = device.AudioClient;
this.shareMode = shareMode;
this.isUsingEventSync = useEventSync;
this.latencyMilliseconds = latency;
this.pcm = pcm;
this.outputFormat = new NAudio.Wave.WaveFormatExtensible(pcm.SampleRate, pcm.BitsPerSample, pcm.ChannelCount);
NAudio.Wave.WaveFormatExtensible closestSampleRateFormat;
if (!audioClient.IsFormatSupported(shareMode, outputFormat, out closestSampleRateFormat))
@@ -199,7 +199,7 @@ namespace CUETools.Codecs.CoreAudio
break;
numFramesAvailable = Math.Min(numFramesAvailable, buff.Length - offs);
buffer = renderClient.GetBuffer(numFramesAvailable);
Marshal.Copy(buff.Bytes, offs * pcm.BlockAlign, buffer, numFramesAvailable * pcm.BlockAlign);
Marshal.Copy(buff.Bytes, offs * Settings.PCM.BlockAlign, buffer, numFramesAvailable * Settings.PCM.BlockAlign);
renderClient.ReleaseBuffer(numFramesAvailable, AudioClientBufferFlags.None);
offs += numFramesAvailable;
if (offs == buff.Length)
@@ -417,7 +417,7 @@ namespace CUETools.Codecs.CoreAudio
Stop();
return;
}
if (src.PCM.BitsPerSample != pcm.BitsPerSample || src.PCM.ChannelCount != pcm.ChannelCount)
if (src.PCM.BitsPerSample != Settings.PCM.BitsPerSample || src.PCM.ChannelCount != Settings.PCM.ChannelCount)
throw new NotSupportedException();
if (playThread != null)
{
@@ -429,7 +429,7 @@ namespace CUETools.Codecs.CoreAudio
if (active == null)
throw new Exception("done");
int toCopy = Math.Min(active.Size - active_offset, src.Length - src_offs);
Buffer.BlockCopy(src.Bytes, src_offs * pcm.BlockAlign, active.Bytes, active_offset * pcm.BlockAlign, toCopy * pcm.BlockAlign);
Buffer.BlockCopy(src.Bytes, src_offs * Settings.PCM.BlockAlign, active.Bytes, active_offset * Settings.PCM.BlockAlign, toCopy * Settings.PCM.BlockAlign);
src_offs += toCopy;
active_offset += toCopy;
if (active_offset == active.Size)
@@ -464,7 +464,7 @@ namespace CUETools.Codecs.CoreAudio
{
//Trace.WriteLine(string.Format("Write {0}", numFramesAvailable));
IntPtr buffer = renderClient.GetBuffer(numFramesAvailable);
Marshal.Copy(b, src_offs * pcm.BlockAlign, buffer, numFramesAvailable * pcm.BlockAlign);
Marshal.Copy(b, src_offs * Settings.PCM.BlockAlign, buffer, numFramesAvailable * Settings.PCM.BlockAlign);
renderClient.ReleaseBuffer(numFramesAvailable, AudioClientBufferFlags.None);
src_offs += numFramesAvailable;
}
@@ -493,18 +493,8 @@ namespace CUETools.Codecs.CoreAudio
{
get
{
return new AudioEncoderSettings();
return m_settings;
}
set
{
if (value != null && value.GetType() != typeof(AudioEncoderSettings))
throw new Exception("Unsupported options " + value);
}
}
public AudioPCMConfig PCM
{
get { return pcm; }
}
public string Path { get { return null; } }

View File

@@ -503,13 +503,11 @@ namespace CUETools { namespace Codecs { namespace FLAC {
public ref class FLACWriter : IAudioDest
{
public:
FLACWriter(String^ path, AudioPCMConfig^ pcm)
FLACWriter(String^ path, FLACWriterSettings^ settings)
{
_pcm = pcm;
_settings = settings;
_settings = gcnew FLACWriterSettings();
if (_pcm->BitsPerSample < 16 || _pcm->BitsPerSample > 24)
if (_settings->PCM->BitsPerSample < 16 || _settings->PCM->BitsPerSample > 24)
throw gcnew Exception("bits per sample must be 16..24");
_initialized = false;
@@ -519,9 +517,9 @@ namespace CUETools { namespace Codecs { namespace FLAC {
_encoder = FLAC__stream_encoder_new();
FLAC__stream_encoder_set_bits_per_sample(_encoder, _pcm->BitsPerSample);
FLAC__stream_encoder_set_channels(_encoder, _pcm->ChannelCount);
FLAC__stream_encoder_set_sample_rate(_encoder, _pcm->SampleRate);
FLAC__stream_encoder_set_bits_per_sample(_encoder, _settings->PCM->BitsPerSample);
FLAC__stream_encoder_set_channels(_encoder, _settings->PCM->ChannelCount);
FLAC__stream_encoder_set_sample_rate(_encoder, _settings->PCM->SampleRate);
}
virtual void Close() {
@@ -559,12 +557,6 @@ namespace CUETools { namespace Codecs { namespace FLAC {
}
}
virtual property AudioPCMConfig^ PCM {
AudioPCMConfig^ get() {
return _pcm;
}
}
virtual property String^ Path {
String^ get() {
return _path;
@@ -604,11 +596,6 @@ namespace CUETools { namespace Codecs { namespace FLAC {
{
return _settings;
}
void set(AudioEncoderSettings^ value)
{
_settings = value->Clone<FLACWriterSettings^>();
}
}
private:
@@ -617,7 +604,6 @@ namespace CUETools { namespace Codecs { namespace FLAC {
bool _initialized;
String^ _path;
Int64 _finalSampleCount, _samplesWritten;
AudioPCMConfig^ _pcm;
FLAC__StreamMetadata **_metadataList;
int _metadataCount;
@@ -632,7 +618,7 @@ namespace CUETools { namespace Codecs { namespace FLAC {
if (_finalSampleCount != 0) {
seektable = FLAC__metadata_object_new(FLAC__METADATA_TYPE_SEEKTABLE);
FLAC__metadata_object_seektable_template_append_spaced_points_by_samples(
seektable, _pcm->SampleRate * 10, _finalSampleCount);
seektable, _settings->PCM->SampleRate * 10, _finalSampleCount);
FLAC__metadata_object_seektable_template_sort(seektable, true);
_metadataList[_metadataCount++] = seektable;
}

View File

@@ -33,19 +33,10 @@ namespace CUETools.Codecs.FLACCL
{
public class FLACCLWriterSettings: AudioEncoderSettings
{
public FLACCLWriterSettings()
public FLACCLWriterSettings()
: base("", "8")
{
this.DoVerify = false;
this.GPUOnly = true;
this.DoRice = false;
this.MappedMemory = false;
this.DoMD5 = true;
this.GroupSize = 128;
this.TaskSize = 8;
this.DeviceType = OpenCLDeviceType.GPU;
this.AllowNonSubset = false;
}
{
}
public override string GetSupportedModes()
{
@@ -118,23 +109,6 @@ namespace CUETools.Codecs.FLACCL
}
}
int padding = 8192;
[DefaultValue(8192)]
[SRDescription(typeof(Properties.Resources), "DescriptionPadding")]
public int Padding
{
get
{
return padding;
}
set
{
if (value < 0 || value > 1024*1024)
throw new Exception("Padding must be between 0..1MB");
padding = value;
}
}
[DefaultValue(false)]
[DisplayName("Allow Non-subset")]
[SRDescription(typeof(Properties.Resources), "AllowNonSubsetDescription")]
@@ -240,36 +214,35 @@ namespace CUETools.Codecs.FLACCL
internal int framesPerTask;
AudioPCMConfig _pcm;
public const int MAX_BLOCKSIZE = 65536;
public FLACCLWriter(string path, Stream IO, AudioPCMConfig pcm)
public FLACCLWriter(string path, Stream IO, FLACCLWriterSettings settings)
{
_pcm = pcm;
m_settings = settings;
// FIXME: For now, only 16-bit encoding is supported
if (pcm.BitsPerSample != 16 && pcm.BitsPerSample != 24)
if (Settings.PCM.BitsPerSample != 16 && Settings.PCM.BitsPerSample != 24)
throw new Exception("Bits per sample must be 16.");
//if (pcm.ChannelCount != 2)
// throw new Exception("ChannelCount must be 2.");
channels = pcm.ChannelCount;
sample_rate = pcm.SampleRate;
bits_per_sample = (uint) pcm.BitsPerSample;
channels = Settings.PCM.ChannelCount;
sample_rate = Settings.PCM.SampleRate;
bits_per_sample = (uint)Settings.PCM.BitsPerSample;
// flake_validate_params
_path = path;
_IO = IO;
eparams.flake_set_defaults(7);
var _compressionLevel = Settings.EncoderModeIndex;
eparams.flake_set_defaults(_compressionLevel);
crc8 = new Crc8();
}
public FLACCLWriter(string path, AudioPCMConfig pcm)
: this(path, null, pcm)
public FLACCLWriter(string path, FLACCLWriterSettings settings)
: this(path, null, settings)
{
}
@@ -281,7 +254,7 @@ namespace CUETools.Codecs.FLACCL
}
}
internal FLACCLWriterSettings m_settings = new FLACCLWriterSettings();
internal FLACCLWriterSettings m_settings;
public AudioEncoderSettings Settings
{
@@ -289,12 +262,6 @@ namespace CUETools.Codecs.FLACCL
{
return m_settings;
}
set
{
m_settings = value.Clone<FLACCLWriterSettings>();
var _compressionLevel = m_settings.EncoderModeIndex;
eparams.flake_set_defaults(_compressionLevel);
}
}
//[DllImport("kernel32.dll")]
@@ -582,11 +549,6 @@ namespace CUETools.Codecs.FLACCL
get { return _userProcessorTime; }
}
public AudioPCMConfig PCM
{
get { return _pcm; }
}
unsafe void encode_residual_fixed(int* res, int* smp, int n, int order)
{
int i;
@@ -1126,7 +1088,7 @@ namespace CUETools.Codecs.FLACCL
task.ResidualTasks[task.nResidualTasks].samplesOffs = ch * task.channelSize + iFrame * blocksize;
task.ResidualTasks[task.nResidualTasks].residualOffs = task.ResidualTasks[task.nResidualTasks].samplesOffs;
task.ResidualTasks[task.nResidualTasks].wbits = 0;
task.ResidualTasks[task.nResidualTasks].coding_method = PCM.BitsPerSample > 16 ? 1 : 0;
task.ResidualTasks[task.nResidualTasks].coding_method = Settings.PCM.BitsPerSample > 16 ? 1 : 0;
task.ResidualTasks[task.nResidualTasks].size = task.ResidualTasks[task.nResidualTasks].obits * blocksize;
task.nResidualTasks++;
}
@@ -1142,7 +1104,7 @@ namespace CUETools.Codecs.FLACCL
task.ResidualTasks[task.nResidualTasks].samplesOffs = ch * task.channelSize + iFrame * blocksize;
task.ResidualTasks[task.nResidualTasks].residualOffs = task.ResidualTasks[task.nResidualTasks].samplesOffs;
task.ResidualTasks[task.nResidualTasks].wbits = 0;
task.ResidualTasks[task.nResidualTasks].coding_method = PCM.BitsPerSample > 16 ? 1 : 0;
task.ResidualTasks[task.nResidualTasks].coding_method = Settings.PCM.BitsPerSample > 16 ? 1 : 0;
task.ResidualTasks[task.nResidualTasks].size = task.ResidualTasks[task.nResidualTasks].obits * blocksize;
task.ResidualTasks[task.nResidualTasks].residualOrder = 1;
task.ResidualTasks[task.nResidualTasks].shift = 0;
@@ -1161,7 +1123,7 @@ namespace CUETools.Codecs.FLACCL
task.ResidualTasks[task.nResidualTasks].samplesOffs = ch * task.channelSize + iFrame * blocksize;
task.ResidualTasks[task.nResidualTasks].residualOffs = task.ResidualTasks[task.nResidualTasks].samplesOffs;
task.ResidualTasks[task.nResidualTasks].wbits = 0;
task.ResidualTasks[task.nResidualTasks].coding_method = PCM.BitsPerSample > 16 ? 1 : 0;
task.ResidualTasks[task.nResidualTasks].coding_method = Settings.PCM.BitsPerSample > 16 ? 1 : 0;
task.ResidualTasks[task.nResidualTasks].size = task.ResidualTasks[task.nResidualTasks].obits * blocksize;
task.ResidualTasks[task.nResidualTasks].shift = 0;
switch (order)
@@ -1310,7 +1272,7 @@ namespace CUETools.Codecs.FLACCL
int pmin = get_max_p_order(eparams.min_partition_order, task.frame.blocksize, task.frame.subframes[ch].best.order);
int pmax = get_max_p_order(eparams.max_partition_order, task.frame.blocksize, task.frame.subframes[ch].best.order);
calc_rice_params(task.frame.subframes[ch].best.rc, pmin, pmax, task.frame.subframes[ch].best.residual, (uint)task.frame.blocksize, (uint)task.frame.subframes[ch].best.order, PCM.BitsPerSample > 16 ? 1 : 0);
calc_rice_params(task.frame.subframes[ch].best.rc, pmin, pmax, task.frame.subframes[ch].best.residual, (uint)task.frame.blocksize, (uint)task.frame.subframes[ch].best.order, Settings.PCM.BitsPerSample > 16 ? 1 : 0);
}
break;
case SubframeType.LPC:
@@ -1318,7 +1280,7 @@ namespace CUETools.Codecs.FLACCL
{
fixed (int* coefs = task.frame.subframes[ch].best.coefs)
{
if (PCM.BitsPerSample > 16)
if (Settings.PCM.BitsPerSample > 16)
lpc.encode_residual_long(task.frame.subframes[ch].best.residual, task.frame.subframes[ch].samples, task.frame.blocksize, task.frame.subframes[ch].best.order, coefs, task.frame.subframes[ch].best.shift);
else
lpc.encode_residual(task.frame.subframes[ch].best.residual, task.frame.subframes[ch].samples, task.frame.blocksize, task.frame.subframes[ch].best.order, coefs, task.frame.subframes[ch].best.shift);
@@ -1326,7 +1288,7 @@ namespace CUETools.Codecs.FLACCL
int pmin = get_max_p_order(eparams.min_partition_order, task.frame.blocksize, task.frame.subframes[ch].best.order);
int pmax = get_max_p_order(eparams.max_partition_order, task.frame.blocksize, task.frame.subframes[ch].best.order);
calc_rice_params(task.frame.subframes[ch].best.rc, pmin, pmax, task.frame.subframes[ch].best.residual, (uint)task.frame.blocksize, (uint)task.frame.subframes[ch].best.order, PCM.BitsPerSample > 16 ? 1 : 0);
calc_rice_params(task.frame.subframes[ch].best.rc, pmin, pmax, task.frame.subframes[ch].best.residual, (uint)task.frame.blocksize, (uint)task.frame.subframes[ch].best.order, Settings.PCM.BitsPerSample > 16 ? 1 : 0);
}
break;
}
@@ -1446,10 +1408,11 @@ namespace CUETools.Codecs.FLACCL
int* s = task.frame.subframes[ch].samples;
int wbits = (int)task.frame.subframes[ch].wbits;
byte* src = &srcptr[ch * 3];
int ba = Settings.PCM.BlockAlign;
for (int i = 0; i < count; i++)
{
s[i] = (((int)src[0] << 8) + ((int)src[1] << 16) + ((int)src[2] << 24)) >> (8 + wbits);
src += PCM.BlockAlign;
src += ba;
}
}
break;
@@ -1524,10 +1487,10 @@ namespace CUETools.Codecs.FLACCL
unsafe void unpack_samples(FLACCLTask task, int count)
{
int iFrame = task.frame.frame_number;
byte* srcptr = ((byte*)task.clSamplesBytesPtr) + iFrame * task.frameSize * PCM.BlockAlign;
if (PCM.BitsPerSample == 16)
byte* srcptr = ((byte*)task.clSamplesBytesPtr) + iFrame * task.frameSize * Settings.PCM.BlockAlign;
if (Settings.PCM.BitsPerSample == 16)
unpack_samples_16(task, srcptr, count);
else if (PCM.BitsPerSample == 24)
else if (Settings.PCM.BitsPerSample == 24)
unpack_samples_24(task, srcptr, count);
else
throw new Exception("Invalid BPS");
@@ -1545,7 +1508,7 @@ namespace CUETools.Codecs.FLACCL
task.frame.subframes[ch].Init(
smp + ch * task.channelSize + iFrame * task.frameSize,
((int*)task.clResidualPtr) + ch * task.channelSize + iFrame * task.frameSize,
_pcm.BitsPerSample + (doMidside && ch == 3 ? 1 : 0), 0);
Settings.PCM.BitsPerSample + (doMidside && ch == 3 ? 1 : 0), 0);
encode_residual(task, channelCount, iFrame);
@@ -1576,7 +1539,7 @@ namespace CUETools.Codecs.FLACCL
frame_count += nFrames;
frame_pos += nFrames * blocksize;
if (!task.UseMappedMemory)
task.openCLCQ.EnqueueWriteBuffer(task.clSamplesBytes, false, 0, PCM.BlockAlign * blocksize * nFrames, task.clSamplesBytesPtr);
task.openCLCQ.EnqueueWriteBuffer(task.clSamplesBytes, false, 0, Settings.PCM.BlockAlign * blocksize * nFrames, task.clSamplesBytesPtr);
//task.openCLCQ.EnqueueUnmapMemObject(task.clSamplesBytes, task.clSamplesBytes.HostPtr);
//task.openCLCQ.EnqueueMapBuffer(task.clSamplesBytes, true, MapFlags.WRITE, 0, task.samplesBufferLen / 2);
}
@@ -1618,10 +1581,10 @@ namespace CUETools.Codecs.FLACCL
{
for (int ch = 0; ch < channels; ch++)
{
byte* res = ((byte*)task.clSamplesBytesPtr) + PCM.BlockAlign * iFrame * task.frameSize + ch * (PCM.BlockAlign / channels);
byte* res = ((byte*)task.clSamplesBytesPtr) + Settings.PCM.BlockAlign * iFrame * task.frameSize + ch * (Settings.PCM.BlockAlign / channels);
int* smp = r + ch * Flake.MAX_BLOCKSIZE;
int ba = PCM.BlockAlign;
if (PCM.BitsPerSample == 16)
int ba = Settings.PCM.BlockAlign;
if (Settings.PCM.BitsPerSample == 16)
{
for (int i = task.frameSize; i > 0; i--)
{
@@ -1632,7 +1595,7 @@ namespace CUETools.Codecs.FLACCL
res += ba;
}
}
else if (PCM.BitsPerSample == 24)
else if (Settings.PCM.BitsPerSample == 24)
{
for (int i = task.frameSize; i > 0; i--)
{
@@ -1765,9 +1728,9 @@ namespace CUETools.Codecs.FLACCL
"#define FLACCL_VERSION \"" + vendor_string + "\"\n" +
(UseGPUOnly ? "#define DO_PARTITIONS\n" : "") +
(UseGPURice ? "#define DO_RICE\n" : "") +
"#define BITS_PER_SAMPLE " + PCM.BitsPerSample + "\n" +
"#define BITS_PER_SAMPLE " + Settings.PCM.BitsPerSample + "\n" +
"#define MAX_BLOCKSIZE " + maxBS + "\n" +
"#define MAX_CHANNELS " + PCM.ChannelCount + "\n" +
"#define MAX_CHANNELS " + Settings.PCM.ChannelCount + "\n" +
#if DEBUG
"#define DEBUG\n" +
#endif
@@ -1829,13 +1792,13 @@ namespace CUETools.Codecs.FLACCL
if (_IO.CanSeek)
first_frame_offset = _IO.Position;
task1 = new FLACCLTask(openCLProgram, channelCount, channels, bits_per_sample, max_frame_size, this, groupSize, UseGPUOnly, UseGPURice);
task2 = new FLACCLTask(openCLProgram, channelCount, channels, bits_per_sample, max_frame_size, this, groupSize, UseGPUOnly, UseGPURice);
task1 = new FLACCLTask(openCLProgram, channelCount, max_frame_size, this, groupSize, UseGPUOnly, UseGPURice);
task2 = new FLACCLTask(openCLProgram, channelCount, max_frame_size, this, groupSize, UseGPUOnly, UseGPURice);
if (m_settings.CPUThreads > 0)
{
cpu_tasks = new FLACCLTask[m_settings.CPUThreads];
for (int i = 0; i < cpu_tasks.Length; i++)
cpu_tasks[i] = new FLACCLTask(openCLProgram, channelCount, channels, bits_per_sample, max_frame_size, this, groupSize, UseGPUOnly, UseGPURice);
cpu_tasks[i] = new FLACCLTask(openCLProgram, channelCount, max_frame_size, this, groupSize, UseGPUOnly, UseGPURice);
}
inited = true;
}
@@ -1851,7 +1814,7 @@ namespace CUETools.Codecs.FLACCL
int block = Math.Min(buff.Length - pos, m_blockSize * framesPerTask - samplesInBuffer);
fixed (byte* buf = buff.Bytes)
AudioSamples.MemCpy(((byte*)task1.clSamplesBytesPtr) + samplesInBuffer * _pcm.BlockAlign, buf + pos * _pcm.BlockAlign, block * _pcm.BlockAlign);
AudioSamples.MemCpy(((byte*)task1.clSamplesBytesPtr) + samplesInBuffer * Settings.PCM.BlockAlign, buf + pos * Settings.PCM.BlockAlign, block * Settings.PCM.BlockAlign);
samplesInBuffer += block;
pos += block;
@@ -1966,8 +1929,8 @@ namespace CUETools.Codecs.FLACCL
if (samplesInBuffer > 0)
AudioSamples.MemCpy(
((byte*)task2.clSamplesBytesPtr),
((byte*)task1.clSamplesBytesPtr) + bs * _pcm.BlockAlign,
samplesInBuffer * _pcm.BlockAlign);
((byte*)task1.clSamplesBytesPtr) + bs * Settings.PCM.BlockAlign,
samplesInBuffer * Settings.PCM.BlockAlign);
FLACCLTask tmp = task1;
task1 = task2;
task2 = tmp;
@@ -2524,13 +2487,13 @@ namespace CUETools.Codecs.FLACCL
public bool UseGPURice = false;
public bool UseMappedMemory = false;
unsafe public FLACCLTask(Program _openCLProgram, int channelsCount, int channels, uint bits_per_sample, int max_frame_size, FLACCLWriter writer, int groupSize, bool gpuOnly, bool gpuRice)
unsafe public FLACCLTask(Program _openCLProgram, int channelsCount, int max_frame_size, FLACCLWriter writer, int groupSize, bool gpuOnly, bool gpuRice)
{
this.UseGPUOnly = gpuOnly;
this.UseGPURice = gpuOnly && gpuRice;
this.UseMappedMemory = writer.m_settings.MappedMemory || writer.m_settings.DeviceType == OpenCLDeviceType.CPU;
this.groupSize = groupSize;
this.channels = channels;
this.channels = writer.Settings.PCM.ChannelCount;
this.channelsCount = channelsCount;
this.writer = writer;
openCLProgram = _openCLProgram;
@@ -2546,9 +2509,9 @@ namespace CUETools.Codecs.FLACCL
int MAX_CHANNELSIZE = MAX_FRAMES * ((writer.m_blockSize + 3) & ~3);
residualTasksLen = sizeof(FLACCLSubframeTask) * 32 * channelsCount * MAX_FRAMES;
bestResidualTasksLen = sizeof(FLACCLSubframeTask) * channels * MAX_FRAMES;
int samplesBufferLen = writer.PCM.BlockAlign * MAX_CHANNELSIZE * channelsCount;
int samplesBufferLen = writer.Settings.PCM.BlockAlign * MAX_CHANNELSIZE * channelsCount;
int residualBufferLen = sizeof(int) * MAX_CHANNELSIZE * channels; // need to adjust residualOffset?
int partitionsLen = sizeof(int) * ((writer.PCM.BitsPerSample > 16 ? 31 : 15) * 2 << 8) * channels * MAX_FRAMES;
int partitionsLen = sizeof(int) * ((writer.Settings.PCM.BitsPerSample > 16 ? 31 : 15) * 2 << 8) * channels * MAX_FRAMES;
int riceParamsLen = sizeof(int) * (4 << 8) * channels * MAX_FRAMES;
int autocorLen = sizeof(float) * (MAX_ORDER + 1) * lpc.MAX_LPC_WINDOWS * channelsCount * MAX_FRAMES;
int lpcDataLen = autocorLen * 32;
@@ -2663,7 +2626,7 @@ namespace CUETools.Codecs.FLACCL
frame.writer = new BitWriter(outputBuffer, 0, outputBuffer.Length);
if (writer.m_settings.DoVerify)
verify = new FlakeReader(new AudioPCMConfig((int)bits_per_sample, channels, 44100));
verify = new FlakeReader(writer.Settings.PCM);
}
public void Dispose()
@@ -2811,7 +2774,7 @@ namespace CUETools.Codecs.FLACCL
if (channels == 2)
{
Kernel clChannelDecorr = channelsCount == 4 ? clStereoDecorr : clChannelDecorr2;
int channelSize1 = writer.PCM.BitsPerSample == 16 ? channelSize / 4 : channelSize;
int channelSize1 = writer.Settings.PCM.BitsPerSample == 16 ? channelSize / 4 : channelSize;
clChannelDecorr.SetArgs(
clSamples,
clSamplesBytes,
@@ -3021,7 +2984,7 @@ namespace CUETools.Codecs.FLACCL
clPartitions,
max_porder);
int maxK = writer.PCM.BitsPerSample > 16 ? 30 : Flake.MAX_RICE_PARAM;
int maxK = writer.Settings.PCM.BitsPerSample > 16 ? 30 : Flake.MAX_RICE_PARAM;
if (openCLCQ.Device.DeviceType == DeviceType.CPU)
openCLCQ.EnqueueNDRangeKernel(
clSumPartition,
@@ -3090,7 +3053,7 @@ namespace CUETools.Codecs.FLACCL
if (!this.UseMappedMemory)
{
if (UseGPURice)
openCLCQ.EnqueueReadBuffer(clRiceOutput, false, 0, (channels * frameSize * (writer.PCM.BitsPerSample + 1) + 256) / 8 * frameCount, clRiceOutputPtr);
openCLCQ.EnqueueReadBuffer(clRiceOutput, false, 0, (channels * frameSize * (writer.Settings.PCM.BitsPerSample + 1) + 256) / 8 * frameCount, clRiceOutputPtr);
else
{
openCLCQ.EnqueueReadBuffer(clBestRiceParams, false, 0, sizeof(int) * (1 << max_porder) * channels * frameCount, clBestRiceParamsPtr);

View File

@@ -34,14 +34,11 @@ using CUETools.Codecs;
namespace CUETools.Codecs.FLAKE
{
public class FlakeWriterSettings: AudioEncoderSettings
{
public FlakeWriterSettings()
public class FlakeWriterSettings : AudioEncoderSettings
{
public FlakeWriterSettings()
: base("", "7")
{
DoVerify = false;
DoMD5 = true;
AllowNonSubset = false;
{
}
public override string GetSupportedModes()
@@ -51,20 +48,21 @@ namespace CUETools.Codecs.FLAKE
public override bool IsValid()
{
return EncoderModeIndex >= 0 && Padding >= 0 &&
return EncoderModeIndex >= 0 &&
(Padding >= 0 && Padding <= 1024 * 1024) &&
(BlockSize == 0 || (BlockSize >= 256 && BlockSize <= Flake.MAX_BLOCKSIZE)) &&
(AllowNonSubset || EncoderModeIndex <= 8);
}
[DefaultValue(false)]
[DisplayName("Verify")]
[SRDescription(typeof(Properties.Resources), "DoVerifyDescription")]
public bool DoVerify { get; set; }
[DefaultValue(false)]
[DisplayName("Verify")]
[SRDescription(typeof(Properties.Resources), "DoVerifyDescription")]
public bool DoVerify { get; set; }
[DefaultValue(true)]
[DisplayName("MD5")]
[SRDescription(typeof(Properties.Resources), "DoMD5Description")]
public bool DoMD5 { get; set; }
[DefaultValue(true)]
[DisplayName("MD5")]
[SRDescription(typeof(Properties.Resources), "DoMD5Description")]
public bool DoMD5 { get; set; }
[DefaultValue(false)]
[DisplayName("Allow Non-subset")]
@@ -141,18 +139,17 @@ namespace CUETools.Codecs.FLAKE
int seek_table_offset = -1;
bool inited = false;
AudioPCMConfig _pcm;
public FlakeWriter(string path, Stream IO, AudioPCMConfig pcm)
public FlakeWriter(string path, Stream IO, FlakeWriterSettings settings)
{
_pcm = pcm;
m_settings = settings;
//if (_pcm.BitsPerSample != 16)
//if (Settings.PCM.BitsPerSample != 16)
// throw new Exception("Bits per sample must be 16.");
//if (_pcm.ChannelCount != 2)
//if (Settings.PCM.ChannelCount != 2)
// throw new Exception("ChannelCount must be 2.");
channels = pcm.ChannelCount;
channels = Settings.PCM.ChannelCount;
// flake_validate_params
@@ -164,14 +161,15 @@ namespace CUETools.Codecs.FLAKE
windowBuffer = new float[Flake.MAX_BLOCKSIZE * 2 * lpc.MAX_LPC_WINDOWS];
windowScale = new double[lpc.MAX_LPC_WINDOWS];
eparams.flake_set_defaults(7);
var _compressionLevel = Settings.EncoderModeIndex;
eparams.flake_set_defaults(_compressionLevel);
crc8 = new Crc8();
frame = new FlacFrame(channels * 2);
}
public FlakeWriter(string path, AudioPCMConfig pcm)
: this(path, null, pcm)
public FlakeWriter(string path, FlakeWriterSettings settings)
: this(path, null, settings)
{
}
@@ -183,7 +181,7 @@ namespace CUETools.Codecs.FLAKE
}
}
FlakeWriterSettings m_settings = new FlakeWriterSettings();
FlakeWriterSettings m_settings;
public AudioEncoderSettings Settings
{
@@ -191,12 +189,6 @@ namespace CUETools.Codecs.FLAKE
{
return m_settings;
}
set
{
m_settings = value.Clone<FlakeWriterSettings>();
var _compressionLevel = m_settings.EncoderModeIndex;
eparams.flake_set_defaults(_compressionLevel);
}
}
#if INTEROP
@@ -494,11 +486,6 @@ namespace CUETools.Codecs.FLAKE
}
}
public AudioPCMConfig PCM
{
get { return _pcm; }
}
unsafe int get_wasted_bits(int* signal, int samples)
{
int i, shift;
@@ -979,7 +966,7 @@ new int[] { // 30
lpc.encode_residual(frame.current.residual, frame.subframes[ch].samples, frame.blocksize, frame.current.order, coefs, frame.current.shift);
}
var cur_size = calc_rice_params(frame.current.rc, pmin, pmax, frame.current.residual, (uint)frame.blocksize, (uint)frame.current.order, PCM.BitsPerSample);
var cur_size = calc_rice_params(frame.current.rc, pmin, pmax, frame.current.residual, (uint)frame.blocksize, (uint)frame.current.order, Settings.PCM.BitsPerSample);
frame.current.size = (uint)(frame.current.order * frame.subframes[ch].obits + 4 + 5 + frame.current.order * frame.current.cbits + 6 + (int)cur_size);
if (frame.current.size < best_size)
@@ -1099,7 +1086,7 @@ new int[] { // 30
}
int pmax = get_max_p_order(eparams.max_partition_order, frame.blocksize, frame.current.order);
int pmin = Math.Min(eparams.min_partition_order, pmax);
uint best_size = calc_rice_params(frame.current.rc, pmin, pmax, frame.current.residual, (uint)frame.blocksize, (uint)frame.current.order, PCM.BitsPerSample);
uint best_size = calc_rice_params(frame.current.rc, pmin, pmax, frame.current.residual, (uint)frame.blocksize, (uint)frame.current.order, Settings.PCM.BitsPerSample);
// not working
//for (int o = 1; o <= frame.current.order; o++)
//{
@@ -1142,7 +1129,7 @@ new int[] { // 30
int pmax = get_max_p_order(eparams.max_partition_order, frame.blocksize, frame.current.order);
int pmin = Math.Min(eparams.min_partition_order, pmax);
frame.current.size = (uint)(frame.current.order * frame.subframes[ch].obits) + 6
+ calc_rice_params(frame.current.rc, pmin, pmax, frame.current.residual, (uint)frame.blocksize, (uint)frame.current.order, PCM.BitsPerSample);
+ calc_rice_params(frame.current.rc, pmin, pmax, frame.current.residual, (uint)frame.blocksize, (uint)frame.current.order, Settings.PCM.BitsPerSample);
frame.subframes[ch].done_fixed |= (1U << order);
@@ -1638,7 +1625,7 @@ new int[] { // 30
frame.ch_mode = channels != 2 ? ChannelMode.NotStereo : ChannelMode.LeftRight;
for (int ch = 0; ch < channels; ch++)
frame.subframes[ch].Init(s + ch * Flake.MAX_BLOCKSIZE, r + ch * Flake.MAX_BLOCKSIZE,
_pcm.BitsPerSample, get_wasted_bits(s + ch * Flake.MAX_BLOCKSIZE, frame.blocksize));
Settings.PCM.BitsPerSample, get_wasted_bits(s + ch * Flake.MAX_BLOCKSIZE, frame.blocksize));
for (int ch = 0; ch < channels; ch++)
encode_residual_pass2(frame, ch);
@@ -1650,7 +1637,7 @@ new int[] { // 30
frame.current.residual = r + 4 * Flake.MAX_BLOCKSIZE;
for (int ch = 0; ch < 4; ch++)
frame.subframes[ch].Init(s + ch * Flake.MAX_BLOCKSIZE, r + ch * Flake.MAX_BLOCKSIZE,
_pcm.BitsPerSample + (ch == 3 ? 1 : 0), get_wasted_bits(s + ch * Flake.MAX_BLOCKSIZE, frame.blocksize));
Settings.PCM.BitsPerSample + (ch == 3 ? 1 : 0), get_wasted_bits(s + ch * Flake.MAX_BLOCKSIZE, frame.blocksize));
//for (int ch = 0; ch < 4; ch++)
// for (int iWindow = 0; iWindow < _windowcount; iWindow++)
@@ -1862,9 +1849,9 @@ new int[] { // 30
bitwriter.writebits(16, m_blockSize);
bitwriter.writebits(24, 0);
bitwriter.writebits(24, max_frame_size);
bitwriter.writebits(20, _pcm.SampleRate);
bitwriter.writebits(20, Settings.PCM.SampleRate);
bitwriter.writebits(3, channels - 1);
bitwriter.writebits(5, _pcm.BitsPerSample - 1);
bitwriter.writebits(5, Settings.PCM.BitsPerSample - 1);
// total samples
if (sample_count > 0)
@@ -1989,7 +1976,7 @@ new int[] { // 30
// find samplerate in table
for (i = 1; i < 12; i++)
{
if (_pcm.SampleRate == Flake.flac_samplerates[i])
if (Settings.PCM.SampleRate == Flake.flac_samplerates[i])
{
sr_code0 = i;
break;
@@ -2002,7 +1989,7 @@ new int[] { // 30
for (i = 1; i < 8; i++)
{
if (_pcm.BitsPerSample == Flake.flac_bitdepths[i])
if (Settings.PCM.BitsPerSample == Flake.flac_bitdepths[i])
{
bps_code = i;
break;
@@ -2012,17 +1999,17 @@ new int[] { // 30
throw new Exception("non-standard bps");
m_blockSize = m_settings.BlockSize != 0 ? m_settings.BlockSize :
select_blocksize(_pcm.SampleRate, eparams.block_time_ms);
select_blocksize(Settings.PCM.SampleRate, eparams.block_time_ms);
// set maximum encoded frame size (if larger, re-encodes in verbatim mode)
if (channels == 2)
max_frame_size = 16 + ((m_blockSize * (_pcm.BitsPerSample + _pcm.BitsPerSample + 1) + 7) >> 3);
max_frame_size = 16 + ((m_blockSize * (Settings.PCM.BitsPerSample + Settings.PCM.BitsPerSample + 1) + 7) >> 3);
else
max_frame_size = 16 + ((m_blockSize * channels * _pcm.BitsPerSample + 7) >> 3);
max_frame_size = 16 + ((m_blockSize * channels * Settings.PCM.BitsPerSample + 7) >> 3);
if (_IO.CanSeek && eparams.do_seektable && sample_count > 0)
{
int seek_points_distance = _pcm.SampleRate * 10;
int seek_points_distance = Settings.PCM.SampleRate * 10;
int num_seek_points = 1 + sample_count / seek_points_distance; // 1 seek point per 10 seconds
if (sample_count % seek_points_distance == 0)
num_seek_points--;
@@ -2045,7 +2032,7 @@ new int[] { // 30
if (m_settings.DoVerify)
{
verify = new FlakeReader(_pcm);
verify = new FlakeReader(Settings.PCM);
verifyBuffer = new int[Flake.MAX_BLOCKSIZE * channels];
}

View File

@@ -79,11 +79,6 @@ namespace HDCDDotNet
}
}
public AudioPCMConfig PCM
{
get { return AudioPCMConfig.RedBook; }
}
public long FinalSampleCount
{
set { throw new Exception("unsupported"); }

View File

@@ -11,7 +11,7 @@ namespace CUETools.Codecs.Icecast
public class IcecastWriter: IAudioDest
{
private long _sampleOffset = 0;
private AudioPCMConfig pcm = AudioPCMConfig.RedBook;
private AudioEncoderSettings m_settings;
private LAME.LAMEEncoderCBR encoder = null;
private HttpWebRequest req = null;
private HttpWebResponse resp = null;
@@ -28,7 +28,7 @@ namespace CUETools.Codecs.Icecast
public IcecastWriter(AudioPCMConfig pcm, IcecastSettingsData settings)
{
this.pcm = pcm;
this.m_settings = new AudioEncoderSettings(pcm);
this.settings = settings;
}
@@ -80,10 +80,12 @@ namespace CUETools.Codecs.Icecast
resp = req.GetResponse() as HttpWebResponse;
if (resp.StatusCode == HttpStatusCode.OK)
{
encoder = new CUETools.Codecs.LAME.LAMEEncoderCBR("", reqStream, AudioPCMConfig.RedBook);
(encoder.Settings as CUETools.Codecs.LAME.LAMEEncoderCBRSettings).StereoMode = settings.JointStereo ?
CUETools.Codecs.LAME.Interop.MpegMode.JOINT_STEREO : CUETools.Codecs.LAME.Interop.MpegMode.STEREO;
(encoder.Settings as CUETools.Codecs.LAME.LAMEEncoderCBRSettings).CustomBitrate = settings.Bitrate;
var encoderSettings = new CUETools.Codecs.LAME.LAMEEncoderCBRSettings() { PCM = AudioPCMConfig.RedBook };
encoderSettings.StereoMode = settings.JointStereo ?
CUETools.Codecs.LAME.Interop.MpegMode.JOINT_STEREO :
CUETools.Codecs.LAME.Interop.MpegMode.STEREO;
encoderSettings.CustomBitrate = settings.Bitrate;
encoder = new CUETools.Codecs.LAME.LAMEEncoderCBR("", reqStream, encoderSettings);
}
}
catch (WebException ex)
@@ -209,18 +211,8 @@ namespace CUETools.Codecs.Icecast
{
get
{
return new AudioEncoderSettings();
return m_settings;
}
set
{
if (value != null && value.GetType() != typeof(AudioEncoderSettings))
throw new Exception("Unsupported options " + value);
}
}
public AudioPCMConfig PCM
{
get { return pcm; }
}
public string Path { get { return null; } }

View File

@@ -15,7 +15,7 @@ namespace CUETools.Codecs.LAME
private byte[] m_InBuffer = null;
private int m_InBufferPos = 0;
private byte[] m_OutBuffer = null;
private AudioPCMConfig _pcm;
private AudioEncoderSettings m_settings;
private string _path;
private Stream _IO;
private long position = 0, sample_count = -1;
@@ -26,12 +26,7 @@ namespace CUETools.Codecs.LAME
{
get
{
return new AudioEncoderSettings();
}
set
{
if (value != null && value.GetType() != typeof(AudioEncoderSettings))
throw new Exception("Unsupported options " + value);
return m_settings;
}
}
@@ -45,11 +40,6 @@ namespace CUETools.Codecs.LAME
set { sample_count = (int)value; }
}
public AudioPCMConfig PCM
{
get { return _pcm; }
}
public string Path { get { return _path; } }
public long BytesWritten
@@ -57,17 +47,17 @@ namespace CUETools.Codecs.LAME
get { return bytesWritten; }
}
public LAMEEncoder(string path, Stream IO, AudioPCMConfig pcm)
public LAMEEncoder(string path, Stream IO, AudioEncoderSettings settings)
{
if (pcm.BitsPerSample != 16)// && pcm.BitsPerSample != 32)
if (settings.PCM.BitsPerSample != 16)// && pcm.BitsPerSample != 32)
throw new ArgumentOutOfRangeException("format", "Only 16 & 32 bits samples supported");
_pcm = pcm;
m_settings = settings;
_path = path;
_IO = IO;
}
public LAMEEncoder(string path, AudioPCMConfig pcm)
: this(path, null, pcm)
public LAMEEncoder(string path, AudioEncoderSettings settings)
: this(path, null, settings)
{
}
@@ -146,7 +136,7 @@ namespace CUETools.Codecs.LAME
protected virtual BE_CONFIG MakeConfig()
{
return new BE_CONFIG(_pcm);
return new BE_CONFIG(Settings.PCM);
}
private void Init()

View File

@@ -7,7 +7,7 @@ namespace CUETools.Codecs.LAME
//[AudioEncoderClass("lame CBR", "mp3", false, 2, typeof(LAMEEncoderCBRSettings))]
public class LAMEEncoderCBR : LAMEEncoder
{
private LAMEEncoderCBRSettings m_settings = new LAMEEncoderCBRSettings();
private LAMEEncoderCBRSettings m_settings;
public override AudioEncoderSettings Settings
{
@@ -15,25 +15,21 @@ namespace CUETools.Codecs.LAME
{
return m_settings;
}
set
{
m_settings = value.Clone<LAMEEncoderCBRSettings>();
}
}
public LAMEEncoderCBR(string path, Stream IO, AudioPCMConfig pcm)
: base(path, IO, pcm)
public LAMEEncoderCBR(string path, Stream IO, AudioEncoderSettings settings)
: base(path, IO, settings)
{
}
public LAMEEncoderCBR(string path, AudioPCMConfig pcm)
: base(path, null, pcm)
public LAMEEncoderCBR(string path, AudioEncoderSettings settings)
: base(path, null, settings)
{
}
protected override BE_CONFIG MakeConfig()
{
BE_CONFIG Mp3Config = new BE_CONFIG(PCM, m_settings.CustomBitrate > 0 ? (uint)m_settings.CustomBitrate : LAMEEncoderCBRSettings.bps_table[m_settings.EncoderModeIndex], 5);
BE_CONFIG Mp3Config = new BE_CONFIG(Settings.PCM, m_settings.CustomBitrate > 0 ? (uint)m_settings.CustomBitrate : LAMEEncoderCBRSettings.bps_table[m_settings.EncoderModeIndex], 5);
Mp3Config.format.lhv1.bWriteVBRHeader = 1;
Mp3Config.format.lhv1.nMode = m_settings.StereoMode;
//Mp3Config.format.lhv1.nVbrMethod = VBRMETHOD.VBR_METHOD_NONE; // --cbr

View File

@@ -7,7 +7,7 @@ namespace CUETools.Codecs.LAME
//[AudioEncoderClass("lame VBR", "mp3", false, 2, typeof(LAMEEncoderVBRSettings))]
public class LAMEEncoderVBR : LAMEEncoder
{
private LAMEEncoderVBRSettings m_settings = new LAMEEncoderVBRSettings();
private LAMEEncoderVBRSettings m_settings;
public override AudioEncoderSettings Settings
{
@@ -15,25 +15,21 @@ namespace CUETools.Codecs.LAME
{
return m_settings;
}
set
{
m_settings = value.Clone<LAMEEncoderVBRSettings>();
}
}
public LAMEEncoderVBR(string path, Stream IO, AudioPCMConfig pcm)
: base(path, IO, pcm)
public LAMEEncoderVBR(string path, Stream IO, AudioEncoderSettings settings)
: base(path, IO, settings)
{
}
public LAMEEncoderVBR(string path, AudioPCMConfig pcm)
: base(path, null, pcm)
public LAMEEncoderVBR(string path, AudioEncoderSettings settings)
: base(path, null, settings)
{
}
protected override BE_CONFIG MakeConfig()
{
BE_CONFIG Mp3Config = new BE_CONFIG(PCM, 0, (uint)m_settings.Quality);
BE_CONFIG Mp3Config = new BE_CONFIG(Settings.PCM, 0, (uint)m_settings.Quality);
Mp3Config.format.lhv1.bWriteVBRHeader = 1;
Mp3Config.format.lhv1.nMode = MpegMode.JOINT_STEREO;
Mp3Config.format.lhv1.bEnableVBR = 1;

View File

@@ -54,7 +54,6 @@ namespace CUETools.Codecs.LAME
private bool m_closed = false, m_initialized = false;
private IntPtr m_handle;
private AudioPCMConfig m_pcm;
private uint m_finalSampleCount;
private byte[] m_outputBuffer;
@@ -70,17 +69,12 @@ namespace CUETools.Codecs.LAME
}
}
public AudioPCMConfig PCM
{
get { return this.m_pcm; }
}
public string Path
{
get { return this.m_outputPath; }
}
private LameWriterSettings m_settings = new LameWriterCBRSettings();
private LameWriterSettings m_settings;
public virtual AudioEncoderSettings Settings
{
@@ -88,26 +82,19 @@ namespace CUETools.Codecs.LAME
{
return m_settings;
}
set
{
m_settings = value.Clone<LameWriterSettings>();
}
}
public LameWriter(string path, Stream output, AudioPCMConfig pcm)
public LameWriter(string path, Stream output, LameWriterSettings settings)
{
this.CheckPCMConfig(pcm);
this.m_pcm = pcm;
this.CheckPCMConfig(settings.PCM);
this.m_settings = settings;
this.m_outputPath = path;
this.m_outputStream = output != null ? output : File.Create(path);
}
public LameWriter(string path, AudioPCMConfig pcm)
public LameWriter(string path, LameWriterSettings settings)
: this(path, null, settings)
{
this.CheckPCMConfig(pcm);
this.m_pcm = pcm;
this.m_outputPath = path;
this.m_outputStream = File.Create(path);
}
private void CheckPCMConfig(AudioPCMConfig pcm)
@@ -219,8 +206,8 @@ namespace CUETools.Codecs.LAME
lame_set_bWriteVbrTag(m_handle, 1);
lame_set_write_id3tag_automatic(m_handle, 0);
lame_set_num_channels(m_handle, this.m_pcm.ChannelCount);
lame_set_in_samplerate(m_handle, this.m_pcm.SampleRate);
lame_set_num_channels(m_handle, this.Settings.PCM.ChannelCount);
lame_set_in_samplerate(m_handle, this.Settings.PCM.SampleRate);
if (this.m_finalSampleCount != 0)
{

View File

@@ -10,7 +10,7 @@ namespace CUETools.Codecs.LossyWAV
public const string version_string = "1.1.1#";
private IAudioDest _audioDest, _lwcdfDest;
private AudioPCMConfig _pcm;
private AudioEncoderSettings m_settings;
private AudioBuffer _audioBuffer;
private short[] fft_bit_length;
private float[] frequency_limits;
@@ -75,18 +75,8 @@ namespace CUETools.Codecs.LossyWAV
{
get
{
return new AudioEncoderSettings();
return m_settings;
}
set
{
if (value != null && value.GetType() != typeof(AudioEncoderSettings))
throw new Exception("Unsupported options " + value);
}
}
public AudioPCMConfig PCM
{
get { return _pcm; }
}
public int OverallBitsRemoved
@@ -164,15 +154,15 @@ namespace CUETools.Codecs.LossyWAV
#region Constructor
public LossyWAVWriter(IAudioDest audioDest, IAudioDest lwcdfDest, double quality, AudioPCMConfig pcm)
public LossyWAVWriter(IAudioDest audioDest, IAudioDest lwcdfDest, double quality, AudioEncoderSettings settings)
{
_audioDest = audioDest;
_lwcdfDest = lwcdfDest;
_pcm = pcm;
m_settings = settings;
if (_audioDest != null && _audioDest.PCM.BitsPerSample > _pcm.BitsPerSample)
if (_audioDest != null && _audioDest.Settings.PCM.BitsPerSample > Settings.PCM.BitsPerSample)
throw new Exception("audio parameters mismatch");
if (_lwcdfDest != null && _lwcdfDest.PCM.BitsPerSample != _pcm.BitsPerSample)
if (_lwcdfDest != null && _lwcdfDest.Settings.PCM.BitsPerSample != Settings.PCM.BitsPerSample)
throw new Exception("audio parameters mismatch");
int quality_integer = (int)Math.Floor(quality);
@@ -195,7 +185,7 @@ namespace CUETools.Codecs.LossyWAV
shaping_factor = Math.Min(1, quality / 10);
shaping_is_on = shaping_factor > 0;
_audioBuffer = new AudioBuffer(_pcm, 256);
_audioBuffer = new AudioBuffer(Settings.PCM, 256);
}
#endregion
@@ -208,7 +198,7 @@ namespace CUETools.Codecs.LossyWAV
{
shift_codec_blocks();
if (samplesInBuffer > 0)
Array.Copy(sampleBuffer, 0, rotating_blocks_ptr[3], 0, samplesInBuffer * _pcm.ChannelCount);
Array.Copy(sampleBuffer, 0, rotating_blocks_ptr[3], 0, samplesInBuffer * Settings.PCM.ChannelCount);
next_codec_block_size = samplesInBuffer;
process_this_codec_block();
if (next_codec_block_size > 0)
@@ -237,8 +227,8 @@ namespace CUETools.Codecs.LossyWAV
{
shift_codec_blocks(); // next_codec_block_size is now zero
if (samplesInBuffer > 0)
Array.Copy(sampleBuffer, 0, rotating_blocks_ptr[3], 0, samplesInBuffer * _pcm.ChannelCount);
Array.Copy(buff.Samples, pos * _pcm.ChannelCount, rotating_blocks_ptr[3], samplesInBuffer * _pcm.ChannelCount, (codec_block_size - samplesInBuffer) * _pcm.ChannelCount);
Array.Copy(sampleBuffer, 0, rotating_blocks_ptr[3], 0, samplesInBuffer * Settings.PCM.ChannelCount);
Array.Copy(buff.Samples, pos * Settings.PCM.ChannelCount, rotating_blocks_ptr[3], samplesInBuffer * Settings.PCM.ChannelCount, (codec_block_size - samplesInBuffer) * Settings.PCM.ChannelCount);
next_codec_block_size = codec_block_size;
pos += codec_block_size - samplesInBuffer;
sampleCount -= codec_block_size - samplesInBuffer;
@@ -249,7 +239,7 @@ namespace CUETools.Codecs.LossyWAV
}
if (sampleCount > 0)
{
Array.Copy(buff.Samples, pos * _pcm.ChannelCount, sampleBuffer, samplesInBuffer * _pcm.ChannelCount, sampleCount * _pcm.ChannelCount);
Array.Copy(buff.Samples, pos * Settings.PCM.ChannelCount, sampleBuffer, samplesInBuffer * Settings.PCM.ChannelCount, sampleCount * Settings.PCM.ChannelCount);
samplesInBuffer += sampleCount;
}
}
@@ -319,7 +309,7 @@ namespace CUETools.Codecs.LossyWAV
{ 4.876022F,5.668487F,6.605748F,7.589148F,8.584943F,9.583902F,10.583678F,11.583589F,12.583571F,13.583568F,14.583551F,15.583574F,16.583541F,17.583544F,18.583555F,19.583554F,20.583574F,21.583577F,22.583531F,23.583560F,24.583548F,25.583570F,26.583561F,27.583581F,28.583552F,29.583540F,30.583564F,31.583530F,32.583546F,33.583585F,34.583557F,35.583567F}
};
if (_pcm.SampleRate > 46050)
if (Settings.PCM.SampleRate > 46050)
{
shaping_a = /* order_4_48000_a */ new double[4] { +0.90300, +0.01160, -0.58530, -0.25710 };
shaping_b = /* order_4_48000_b */ new double[4] { -2.23740, +0.73390, +0.12510, +0.60330 };
@@ -336,8 +326,8 @@ namespace CUETools.Codecs.LossyWAV
short bits_in_block_size = (short)Math.Floor(fastlog2(codec_block_size));
for (int i = 0; i < precalc_analyses; i++)
fft_bit_length[i] += (short)(bits_in_block_size - 9);
if (frequency_limits[spread_freqs] > _pcm.SampleRate / 2)
frequency_limits[spread_freqs] = _pcm.SampleRate / 2;
if (frequency_limits[spread_freqs] > Settings.PCM.SampleRate / 2)
frequency_limits[spread_freqs] = Settings.PCM.SampleRate / 2;
fill_fft_lookup_block = new int[maxblocksize * 4];
fill_fft_lookup_offset = new int[maxblocksize * 4];
for (int i = 0; i < codec_block_size * 4; i++)
@@ -350,8 +340,8 @@ namespace CUETools.Codecs.LossyWAV
for (int j = 0; j < precalc_analyses; j++)
saved_fft_results[i, j].start = -1;
clipped_samples = 0;
this_max_sample = (1 << (_pcm.BitsPerSample - 1)) - 1;
this_min_sample = 0 - (1 << (_pcm.BitsPerSample - 1));
this_max_sample = (1 << (Settings.PCM.BitsPerSample - 1)) - 1;
this_min_sample = 0 - (1 << (Settings.PCM.BitsPerSample - 1));
for (int this_fft_bit_length = 1; this_fft_bit_length <= MaxFFTBitLength; this_fft_bit_length++)
{
int this_fft_length = 1 << this_fft_bit_length;
@@ -368,7 +358,7 @@ namespace CUETools.Codecs.LossyWAV
shaping_a[i] *= sf;
shaping_b[i] *= sf;
}
static_maximum_bits_to_remove = (short)(_pcm.BitsPerSample - static_minimum_bits_to_keep);
static_maximum_bits_to_remove = (short)(Settings.PCM.BitsPerSample - static_minimum_bits_to_keep);
double lfb = Math.Log10(frequency_limits[0]); // 20Hz lower limit for skewing;
double mfb = Math.Log10(frequency_limits[2]); // 3445.3125Hz upper limit for skewing;
double dfb = mfb - lfb; // skewing range;
@@ -394,8 +384,8 @@ namespace CUETools.Codecs.LossyWAV
fft_array = new double[1 << (MaxFFTBitLength + 1)];
fft_result = new double[1 << MaxFFTBitLength];
rotating_blocks_ptr = new int[4][,];
sampleBuffer = new int[codec_block_size, _pcm.ChannelCount];
channel_recs = new channel_rec[_pcm.ChannelCount];
sampleBuffer = new int[codec_block_size, Settings.PCM.ChannelCount];
channel_recs = new channel_rec[Settings.PCM.ChannelCount];
analysis_recs = new analysis_rec[precalc_analyses];
for (int analysis_number = 0; analysis_number < precalc_analyses; analysis_number++)
@@ -418,7 +408,7 @@ namespace CUETools.Codecs.LossyWAV
analysis_recs[analysis_number].fft_underlap_length = total_overlap_length * 1.0 / Math.Max(1, analysis_recs[analysis_number].analysis_blocks);
// Calculate actual analysis_time values for fft_lengths
analysis_recs[analysis_number].bin_width = _pcm.SampleRate * 1.0 / (1 << this_fft_bit_length);
analysis_recs[analysis_number].bin_width = Settings.PCM.SampleRate * 1.0 / (1 << this_fft_bit_length);
analysis_recs[analysis_number].bin_time = 1.0 / analysis_recs[analysis_number].bin_width;
// Calculate which FFT bin corresponds to the low frequency limit
@@ -464,9 +454,9 @@ namespace CUETools.Codecs.LossyWAV
analysis_recs[analysis_number].threshold_index[last_filled++] = 32; // ?? 31?
} // calculating for each analysis_number
for (int i = 0; i < 4; i++)
rotating_blocks_ptr[i] = new int[codec_block_size, _pcm.ChannelCount];
btrd_codec_block = new int[codec_block_size, _pcm.ChannelCount];
corr_codec_block = new int[codec_block_size, _pcm.ChannelCount];
rotating_blocks_ptr[i] = new int[codec_block_size, Settings.PCM.ChannelCount];
btrd_codec_block = new int[codec_block_size, Settings.PCM.ChannelCount];
corr_codec_block = new int[codec_block_size, Settings.PCM.ChannelCount];
blocks_processed = 0;
overall_bits_removed = 0;
overall_bits_lost = 0;
@@ -530,8 +520,8 @@ namespace CUETools.Codecs.LossyWAV
void remove_bits(int channel, short bits_to_remove_from_this_channel)
{
short min_bits_to_remove = 0;
if (_audioDest != null && _audioDest.PCM.BitsPerSample < _pcm.BitsPerSample)
min_bits_to_remove = (short)(_pcm.BitsPerSample - _audioDest.PCM.BitsPerSample);
if (_audioDest != null && _audioDest.Settings.PCM.BitsPerSample < Settings.PCM.BitsPerSample)
min_bits_to_remove = (short)(Settings.PCM.BitsPerSample - _audioDest.Settings.PCM.BitsPerSample);
if (bits_to_remove_from_this_channel < min_bits_to_remove)
bits_to_remove_from_this_channel = min_bits_to_remove;
@@ -610,18 +600,18 @@ namespace CUETools.Codecs.LossyWAV
void process_this_codec_block()
{
short codec_block_dependent_bits_to_remove = (short)_pcm.BitsPerSample;
short codec_block_dependent_bits_to_remove = (short)Settings.PCM.BitsPerSample;
double min_codec_block_channel_rms = channel_recs[0].this_codec_block_rms;
for (int channel = 0; channel < _pcm.ChannelCount; channel++)
for (int channel = 0; channel < Settings.PCM.ChannelCount; channel++)
min_codec_block_channel_rms = Math.Min(min_codec_block_channel_rms, channel_recs[channel].this_codec_block_rms);
for (int channel = 0; channel < _pcm.ChannelCount; channel++)
for (int channel = 0; channel < Settings.PCM.ChannelCount; channel++)
{
// if (linkchannels)...
channel_recs[channel].this_codec_block_bits = channel_recs[channel].this_codec_block_rms;
}
for (int channel = 0; channel < _pcm.ChannelCount; channel++)
for (int channel = 0; channel < Settings.PCM.ChannelCount; channel++)
{
fft_results_rec min_fft_result;
@@ -712,7 +702,7 @@ namespace CUETools.Codecs.LossyWAV
codec_block_dependent_bits_to_remove = Math.Min(codec_block_dependent_bits_to_remove, channel_recs[channel].bits_to_remove);
}
for (int channel = 0; channel < _pcm.ChannelCount; channel++)
for (int channel = 0; channel < Settings.PCM.ChannelCount; channel++)
{
// if (linkchannels)
overall_bits_removed += channel_recs[channel].bits_to_remove;
@@ -722,11 +712,11 @@ namespace CUETools.Codecs.LossyWAV
if (_audioDest != null)
{
if (_audioDest.PCM.BitsPerSample < _pcm.BitsPerSample)
if (_audioDest.Settings.PCM.BitsPerSample < Settings.PCM.BitsPerSample)
{
int sh = _pcm.BitsPerSample - _audioDest.PCM.BitsPerSample;
int sh = Settings.PCM.BitsPerSample - _audioDest.Settings.PCM.BitsPerSample;
for (int i = 0; i < this_codec_block_size; i++)
for (int c = 0; c < _pcm.ChannelCount; c++)
for (int c = 0; c < Settings.PCM.ChannelCount; c++)
btrd_codec_block[i, c] >>= sh;
}
_audioBuffer.Prepare(btrd_codec_block, this_codec_block_size);
@@ -755,7 +745,7 @@ namespace CUETools.Codecs.LossyWAV
if (this_codec_block_size > 0)
{
blocks_processed++;
for (int channel = 0; channel < _pcm.ChannelCount; channel++)
for (int channel = 0; channel < Settings.PCM.ChannelCount; channel++)
{
double x = 0;
for (int i = 0; i < this_codec_block_size; i++)

View File

@@ -205,16 +205,23 @@ namespace TTA {
}
};
[AudioEncoderClass("ttalib", "tta", true, 1, AudioEncoderSettings::typeid)]
public ref class TTAWriterSettings : public AudioEncoderSettings
{
public:
TTAWriterSettings() : AudioEncoderSettings()
{
}
};
[AudioEncoderClass("ttalib", "tta", true, 1, TTAWriterSettings::typeid)]
public ref class TTAWriter : public IAudioDest
{
public:
TTAWriter(String^ path, AudioPCMConfig^ pcm)
TTAWriter(String^ path, TTAWriterSettings^ settings)
{
_settings = gcnew AudioEncoderSettings();
_pcm = pcm;
_settings = settings;
if (_pcm->BitsPerSample < 16 || _pcm->BitsPerSample > 24)
if (_settings->PCM->BitsPerSample < 16 || _settings->PCM->BitsPerSample > 24)
throw gcnew Exception("Bits per sample must be 16..24.");
_initialized = false;
@@ -271,11 +278,6 @@ namespace TTA {
}
}
virtual property AudioPCMConfig^ PCM
{
AudioPCMConfig^ get() { return _pcm; }
}
virtual property String^ Path {
String^ get() {
return _path;
@@ -287,12 +289,12 @@ namespace TTA {
sampleBuffer->Prepare(this);
if ((_sampleBuffer == nullptr) || (_sampleBuffer->Length < sampleBuffer->Length * _pcm->ChannelCount))
_sampleBuffer = gcnew array<long> (sampleBuffer->Length * _pcm->ChannelCount);
if ((_sampleBuffer == nullptr) || (_sampleBuffer->Length < sampleBuffer->Length * _settings->PCM->ChannelCount))
_sampleBuffer = gcnew array<long> (sampleBuffer->Length * _settings->PCM->ChannelCount);
interior_ptr<Int32> pSampleBuffer = &sampleBuffer->Samples[0, 0];
interior_ptr<long> pTTABuffer = &_sampleBuffer[0];
for (int i = 0; i < sampleBuffer->Length * _pcm->ChannelCount; i++)
for (int i = 0; i < sampleBuffer->Length * _settings->PCM->ChannelCount; i++)
pTTABuffer[i] = pSampleBuffer[i];
pin_ptr<long> buffer = &_sampleBuffer[0];
@@ -313,11 +315,6 @@ namespace TTA {
{
return _settings;
}
void set(AudioEncoderSettings^ value)
{
_settings = value->Clone<AudioEncoderSettings^>();
}
}
private:
@@ -327,7 +324,6 @@ namespace TTA {
bool _initialized;
String^ _path;
Int64 _finalSampleCount, _samplesWritten;
AudioPCMConfig^ _pcm;
AudioEncoderSettings^ _settings;
void Initialize()
@@ -338,7 +334,7 @@ namespace TTA {
_IO = gcnew FileStream (_path, FileMode::Create, FileAccess::Write, FileShare::Read);
try
{
_ttaWriter = new TTALib::TTAWriter((HANDLE)_IO->Handle, 0, WAVE_FORMAT_PCM, _pcm->ChannelCount, _pcm->BitsPerSample, _pcm->SampleRate, _finalSampleCount);
_ttaWriter = new TTALib::TTAWriter((HANDLE)_IO->Handle, 0, WAVE_FORMAT_PCM, _settings->PCM->ChannelCount, _settings->PCM->BitsPerSample, _settings->PCM->SampleRate, _finalSampleCount);
} catch (TTALib::TTAException ex)
{
throw gcnew Exception(String::Format("TTA encoder: {0}", gcnew String(TTAErrorsStr[ex.GetErrNo()])));

View File

@@ -1,90 +1,115 @@
using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
using CUETools.Codecs;
using System.IO;
using System.Text;
using WindowsMediaLib;
using WindowsMediaLib.Defs;
using System.Collections.Generic;
namespace CUETools.Codecs.WMA
{
public class WMAWriterSettings : AudioEncoderSettings
public abstract class WMAWriterSettings : AudioEncoderSettings
{
public WMAWriterSettings() { }
}
[AudioEncoderClass("windows", "wma", true, 1, typeof(WMAWriterSettings))]
public class WMAWriter : IAudioDest
{
IWMProfileManager m_pProfileManager;
IWMWriter m_pWriter;
int m_iCodec, m_iFormat;
private string outputPath;
private bool closed = false;
private AudioPCMConfig pcm;
private long sampleCount, finalSampleCount;
public long FinalSampleCount
public WMAWriterSettings(Guid subType)
: base()
{
set
{
this.finalSampleCount = value;
}
this.m_subType = subType;
}
public AudioPCMConfig PCM
private readonly Guid m_subType;
protected bool m_vbr = true;
public IWMWriter GetWriter()
{
get { return this.pcm; }
}
public string Path
{
get { return this.outputPath; }
}
AudioEncoderSettings m_settings = new AudioEncoderSettings();
public virtual AudioEncoderSettings Settings
{
get
{
return m_settings;
}
set
{
m_settings = value.Clone<AudioEncoderSettings>();
}
}
public WMAWriter(string path, AudioPCMConfig pcm)
{
this.CheckPCMConfig(pcm);
this.pcm = pcm;
this.outputPath = path;
IWMProfileManager pProfileManager = null;
try
{
WMUtils.WMCreateProfileManager(out m_pProfileManager);
var pCodecInfo3 = m_pProfileManager as IWMCodecInfo3;
WMUtils.WMCreateProfileManager(out pProfileManager);
var pCodecInfo3 = pProfileManager as IWMCodecInfo3;
// We have to use the same pProfileManager for enumeration,
// because it calls SetCodecEnumerationSetting, so chosenFormat.format
// would not point to the same format for a pProfileManager
// with different (default) settings, and GetCodecFormat
// would return the wrong stream config.
var formats = GetFormats(pProfileManager);
if (this.EncoderMode != "")
formats.RemoveAll(fmt => fmt.modeName != this.EncoderMode);
if (formats.Count < 1)
throw new NotSupportedException("codec/format not found");
if (formats.Count > 1)
throw new NotSupportedException("codec/format ambiguous");
var chosenFormat = formats[0];
IWMStreamConfig pStreamConfig1;
pCodecInfo3.GetCodecFormat(MediaType.Audio, chosenFormat.codec, chosenFormat.format, out pStreamConfig1);
try
{
pStreamConfig1.SetStreamNumber(1);
IWMProfile pProfile;
pProfileManager.CreateEmptyProfile(WMVersion.V9_0, out pProfile);
try
{
pProfile.AddStream(pStreamConfig1);
IWMWriter pWriter;
WMUtils.WMCreateWriter(IntPtr.Zero, out pWriter);
try
{
pWriter.SetProfile(pProfile);
}
catch (Exception ex)
{
Marshal.ReleaseComObject(pWriter);
throw ex;
}
return pWriter;
}
finally
{
Marshal.ReleaseComObject(pProfile);
}
}
finally
{
Marshal.ReleaseComObject(pStreamConfig1);
}
}
finally
{
Marshal.ReleaseComObject(pProfileManager);
}
}
internal IEnumerable<WMAFormatInfo> EnumerateFormatInfo(IWMProfileManager pProfileManager2)
{
IWMProfileManager pProfileManager = null;
try
{
if (pProfileManager2 == null)
WMUtils.WMCreateProfileManager(out pProfileManager);
var pCodecInfo3 = (pProfileManager2 ?? pProfileManager) as IWMCodecInfo3;
int cCodecs;
pCodecInfo3.GetCodecInfoCount(MediaType.Audio, out cCodecs);
bool codecFound = false;
for (int iCodec = 0; iCodec < cCodecs; iCodec++)
{
int szCodecName = 0;
pCodecInfo3.GetCodecName(MediaType.Audio, iCodec, null, ref szCodecName);
var codecName = new StringBuilder(szCodecName);
pCodecInfo3.GetCodecName(MediaType.Audio, iCodec, codecName, ref szCodecName);
//if (codec != WMAvoice)
try
var attrDataType = new AttrDataType();
int dwAttrSize = 0;
byte[] pAttrValue = new byte[4];
pCodecInfo3.GetCodecProp(MediaType.Audio, iCodec, Constants.g_wszIsVBRSupported, out attrDataType, pAttrValue, ref dwAttrSize);
if (pAttrValue[0] != 1)
continue;
if (m_vbr)
{
pCodecInfo3.SetCodecEnumerationSetting(MediaType.Audio, iCodec, Constants.g_wszVBREnabled, AttrDataType.BOOL, new byte[] {1, 0, 0, 0}, 4);
//pCodecInfo3.SetCodecEnumerationSetting(MediaType.Audio, iCodec, Constants.g_wszNumPasses, AttrDataType.DWORD, new byte[] {1, 0, 0, 0}, 4);
}
catch (COMException)
pCodecInfo3.SetCodecEnumerationSetting(MediaType.Audio, iCodec, Constants.g_wszVBREnabled, AttrDataType.BOOL, new byte[] { 1, 0, 0, 0 }, 4);
pCodecInfo3.SetCodecEnumerationSetting(MediaType.Audio, iCodec, Constants.g_wszNumPasses, AttrDataType.DWORD, new byte[] { 1, 0, 0, 0 }, 4);
}
else
{
pCodecInfo3.SetCodecEnumerationSetting(MediaType.Audio, iCodec, Constants.g_wszVBREnabled, AttrDataType.BOOL, new byte[] { 0, 0, 0, 0 }, 4);
}
int cFormat;
@@ -92,7 +117,11 @@ namespace CUETools.Codecs.WMA
for (int iFormat = 0; iFormat < cFormat; iFormat++)
{
IWMStreamConfig pStreamConfig;
pCodecInfo3.GetCodecFormat(MediaType.Audio, iCodec, iFormat, out pStreamConfig);
int cchDesc = 1024;
StringBuilder szDesc = new StringBuilder(cchDesc);
pCodecInfo3.GetCodecFormatDesc(MediaType.Audio, iCodec, iFormat, out pStreamConfig, szDesc, ref cchDesc);
if (szDesc.ToString().Contains("(A/V)"))
continue;
try
{
var pProps = pStreamConfig as IWMMediaProps;
@@ -104,16 +133,21 @@ namespace CUETools.Codecs.WMA
pProps.GetMediaType(pMediaType, ref cbType);
try
{
if (pMediaType.majorType == MediaType.Audio && pMediaType.formatType == FormatType.WaveEx && pMediaType.subType == MediaSubType.WMAudio_Lossless)
if (pMediaType.majorType == MediaType.Audio && pMediaType.formatType == FormatType.WaveEx && pMediaType.subType == m_subType)
{
WaveFormatEx pWfx = new WaveFormatEx();
Marshal.PtrToStructure(pMediaType.formatPtr, pWfx);
if (pWfx.nChannels == pcm.ChannelCount && pWfx.wBitsPerSample == pcm.BitsPerSample && pWfx.nSamplesPerSec == pcm.SampleRate)
var info = new WMAFormatInfo()
{
m_iCodec = iCodec;
m_iFormat = iFormat;
codecFound = true;
}
codec = iCodec,
codecName = codecName.ToString(),
format = iFormat,
formatName = szDesc.ToString(),
subType = pMediaType.subType,
pcm = new AudioPCMConfig(pWfx.wBitsPerSample, pWfx.nChannels, pWfx.nSamplesPerSec)
};
if (PCM == null || (pWfx.nChannels == PCM.ChannelCount && pWfx.wBitsPerSample == PCM.BitsPerSample && pWfx.nSamplesPerSec == PCM.SampleRate))
yield return info;
}
}
finally
@@ -127,48 +161,131 @@ namespace CUETools.Codecs.WMA
}
}
}
if (!codecFound)
throw new NotSupportedException("codec not found");
IWMStreamConfig pStreamConfig1;
pCodecInfo3.GetCodecFormat(MediaType.Audio, m_iCodec, m_iFormat, out pStreamConfig1);
try
{
pStreamConfig1.SetStreamNumber(1);
IWMProfile pProfile;
m_pProfileManager.CreateEmptyProfile(WMVersion.V9_0, out pProfile);
try
{
pProfile.AddStream(pStreamConfig1);
WMUtils.WMCreateWriter(IntPtr.Zero, out m_pWriter);
m_pWriter.SetProfile(pProfile);
int cInputs;
m_pWriter.GetInputCount(out cInputs);
//for (int iInput = 0; iInput < cInputs; iInput++)
//{
//}
//IWMInputMediaProps pInput;
//pWriter.GetInputProps(0, out pInput);
//pInput.GetMediaType(pType, ref cbType);
// fill (WAVEFORMATEX*)pType->pbFormat
// WAVEFORMATEXTENSIBLE if needed (dwChannelMask, wValidBitsPerSample)
// if (chg)
//pInput.SetMediaType(pType);
//pWriter.SetInputProps(0, pInput);
}
finally
{
if (pProfileManager != null)
Marshal.ReleaseComObject(pProfileManager);
}
}
//{ DWORD dwFormatCount = 0; hr = pWriter->GetInputFormatCount(0, &dwFormatCount); TEST(hr); TESTB(dwFormatCount > 0); }
//// GetInputFormatCount failed previously for multichannel formats, before ...mask = guessChannelMask() added. Leave this check j.i.c.
m_pWriter.SetOutputFilename(outputPath);
m_pWriter.BeginWriting();
}
finally
{
Marshal.ReleaseComObject(pProfile);
}
}
finally
{
Marshal.ReleaseComObject(pStreamConfig1);
}
internal List<WMAFormatInfo> GetFormats(IWMProfileManager pProfileManager)
{
var formats = new List<WMAFormatInfo>(this.EnumerateFormatInfo(pProfileManager));
if (formats.Count < 2) return formats;
int prefixLen = 0, suffixLen = 0;
while (formats.TrueForAll(s => s.formatName.Length > prefixLen &&
s.formatName.Substring(0, prefixLen + 1) ==
formats[0].formatName.Substring(0, prefixLen + 1)))
prefixLen++;
while (formats.TrueForAll(s => s.formatName.Length > suffixLen &&
s.formatName.Substring(s.formatName.Length - suffixLen - 1) ==
formats[0].formatName.Substring(formats[0].formatName.Length - suffixLen - 1)))
suffixLen++;
formats.ForEach(s => s.modeName = s.formatName.Substring(prefixLen, s.formatName.Length - suffixLen - prefixLen).Trim().Replace(' ', '_'));
int ix, iy;
formats.Sort((Comparison<WMAFormatInfo>)((x, y) => int.TryParse(x.modeName, out ix) && int.TryParse(y.modeName, out iy) ? ix - iy : x.modeName.CompareTo(y.modeName)));
return formats;
}
public override string GetSupportedModes()
{
return string.Join(" ", GetFormats(null).ConvertAll(s => s.modeName).ToArray());
}
}
internal class WMAFormatInfo
{
public int codec;
public string codecName;
public int format;
public string formatName;
public string modeName;
public Guid subType;
public AudioPCMConfig pcm;
}
public class WMALWriterSettings : WMAWriterSettings
{
public WMALWriterSettings()
: base(MediaSubType.WMAudio_Lossless)
{
}
}
public class WMAVBRWriterSettings : WMAWriterSettings
{
public WMAVBRWriterSettings()
: base(MediaSubType.WMAudioV8)
{
}
[DefaultValue(true)]
public bool VBR
{
get { return m_vbr; }
set { m_vbr = value; }
}
}
[AudioEncoderClass("windows", "wma", true, 1, typeof(WMALWriterSettings))]
[AudioEncoderClass("windows", "wma", false, 1, typeof(WMAVBRWriterSettings))]
public class WMAWriter : IAudioDest
{
IWMWriter m_pWriter;
private string outputPath;
private bool closed = false;
private long sampleCount, finalSampleCount;
public long FinalSampleCount
{
set
{
this.finalSampleCount = value;
}
}
public string Path
{
get { return this.outputPath; }
}
WMAWriterSettings m_settings;
public virtual AudioEncoderSettings Settings
{
get
{
return m_settings;
}
}
public WMAWriter(string path, WMAWriterSettings settings)
{
this.m_settings = settings;
this.outputPath = path;
try
{
m_pWriter = settings.GetWriter();
int cInputs;
m_pWriter.GetInputCount(out cInputs);
//for (int iInput = 0; iInput < cInputs; iInput++)
//{
//}
//IWMInputMediaProps pInput;
//pWriter.GetInputProps(0, out pInput);
//pInput.GetMediaType(pType, ref cbType);
// fill (WAVEFORMATEX*)pType->pbFormat
// WAVEFORMATEXTENSIBLE if needed (dwChannelMask, wValidBitsPerSample)
// if (chg)
//pInput.SetMediaType(pType);
//pWriter.SetInputProps(0, pInput);
//{ DWORD dwFormatCount = 0; hr = pWriter->GetInputFormatCount(0, &dwFormatCount); TEST(hr); TESTB(dwFormatCount > 0); }
//// GetInputFormatCount failed previously for multichannel formats, before ...mask = guessChannelMask() added. Leave this check j.i.c.
m_pWriter.SetOutputFilename(outputPath);
m_pWriter.BeginWriting();
}
catch (Exception ex)
{
@@ -177,23 +294,10 @@ namespace CUETools.Codecs.WMA
Marshal.ReleaseComObject(m_pWriter);
m_pWriter = null;
}
if (m_pProfileManager != null)
{
Marshal.ReleaseComObject(m_pProfileManager);
m_pProfileManager = null;
}
throw ex;
}
}
private void CheckPCMConfig(AudioPCMConfig pcm)
{
if (pcm.BitsPerSample != 16)
{
throw new ArgumentException("LAME only supports 16 bits/sample.");
}
}
public void Close()
{
if (!this.closed)
@@ -209,11 +313,6 @@ namespace CUETools.Codecs.WMA
Marshal.ReleaseComObject(m_pWriter);
m_pWriter = null;
}
if (m_pProfileManager != null)
{
Marshal.ReleaseComObject(m_pProfileManager);
m_pProfileManager = null;
}
}
this.closed = true;
@@ -248,7 +347,7 @@ namespace CUETools.Codecs.WMA
pSample.GetBuffer(out pdwBuffer);
pSample.SetLength(buffer.ByteLength);
Marshal.Copy(buffer.Bytes, 0, pdwBuffer, buffer.ByteLength);
long cnsSampleTime = sampleCount * 10000000L / pcm.SampleRate;
long cnsSampleTime = sampleCount * 10000000L / Settings.PCM.SampleRate;
m_pWriter.WriteSample(0, cnsSampleTime, SampleFlag.CleanPoint, pSample);
Marshal.ReleaseComObject(pSample);
sampleCount += buffer.Length;

View File

@@ -338,15 +338,13 @@ namespace CUETools { namespace Codecs { namespace WavPack {
public ref class WavPackWriter : IAudioDest
{
public:
WavPackWriter(String^ path, AudioPCMConfig^ pcm)
WavPackWriter(String^ path, WavPackWriterSettings^ settings)
{
_settings = gcnew WavPackWriterSettings();
_settings = settings;
_pcm = pcm;
if (_pcm->ChannelCount != 1 && _pcm->ChannelCount != 2)
if (_settings->PCM->ChannelCount != 1 && _settings->PCM->ChannelCount != 2)
throw gcnew Exception("Only stereo and mono audio formats are allowed.");
if (_pcm->BitsPerSample < 16 || _pcm->BitsPerSample > 24)
if (_settings->PCM->BitsPerSample < 16 || _settings->PCM->BitsPerSample > 24)
throw gcnew Exception("Bits per sample must be 16..24.");
_path = path;
@@ -398,11 +396,6 @@ namespace CUETools { namespace Codecs { namespace WavPack {
}
}
virtual property AudioPCMConfig^ PCM
{
AudioPCMConfig^ get() { return _pcm; }
}
virtual void Write(AudioBuffer^ sampleBuffer)
{
if (!_initialized)
@@ -413,12 +406,12 @@ namespace CUETools { namespace Codecs { namespace WavPack {
if (_settings->MD5Sum)
UpdateHash(sampleBuffer->Bytes, sampleBuffer->ByteLength);
if ((_pcm->BitsPerSample & 7) != 0)
if ((_settings->PCM->BitsPerSample & 7) != 0)
{
if (_shiftedSampleBuffer == nullptr || _shiftedSampleBuffer.GetLength(0) < sampleBuffer->Length)
_shiftedSampleBuffer = gcnew array<int,2>(sampleBuffer->Length, _pcm->ChannelCount);
int shift = 8 - (_pcm->BitsPerSample & 7);
int ch = _pcm->ChannelCount;
_shiftedSampleBuffer = gcnew array<int,2>(sampleBuffer->Length, _settings->PCM->ChannelCount);
int shift = 8 - (_settings->PCM->BitsPerSample & 7);
int ch = _settings->PCM->ChannelCount;
for (int i = 0; i < sampleBuffer->Length; i++)
for (int c = 0; c < ch; c++)
_shiftedSampleBuffer[i,c] = sampleBuffer->Samples[i,c] << shift;
@@ -448,11 +441,6 @@ namespace CUETools { namespace Codecs { namespace WavPack {
{
return _settings;
}
void set(AudioEncoderSettings^ value)
{
_settings = value->Clone<WavPackWriterSettings^>();
}
}
void UpdateHash(array<unsigned char>^ buff, Int32 len)
@@ -472,7 +460,6 @@ namespace CUETools { namespace Codecs { namespace WavPack {
String^ _path;
MD5^ _md5hasher;
array<int,2>^ _shiftedSampleBuffer;
AudioPCMConfig^ _pcm;
WavPackWriterSettings^ _settings;
void Initialize() {
@@ -484,11 +471,11 @@ namespace CUETools { namespace Codecs { namespace WavPack {
}
memset(&config, 0, sizeof(WavpackConfig));
config.bits_per_sample = _pcm->BitsPerSample;
config.bytes_per_sample = (_pcm->BitsPerSample + 7) / 8;
config.num_channels = _pcm->ChannelCount;
config.channel_mask = 5 - _pcm->ChannelCount;
config.sample_rate = _pcm->SampleRate;
config.bits_per_sample = _settings->PCM->BitsPerSample;
config.bytes_per_sample = (_settings->PCM->BitsPerSample + 7) / 8;
config.num_channels = _settings->PCM->ChannelCount;
config.channel_mask = 5 - _settings->PCM->ChannelCount;
config.sample_rate = _settings->PCM->SampleRate;
Int32 _compressionMode = _settings->EncoderModeIndex;
if (_compressionMode == 0) config.flags |= CONFIG_FAST_FLAG;
if (_compressionMode == 2) config.flags |= CONFIG_HIGH_FLAG;

View File

@@ -327,7 +327,7 @@ namespace CUETools.Codecs
public void Prepare(IAudioDest dest)
{
if (dest.PCM.ChannelCount != pcm.ChannelCount || dest.PCM.BitsPerSample != pcm.BitsPerSample)
if (dest.Settings.PCM.ChannelCount != pcm.ChannelCount || dest.Settings.PCM.BitsPerSample != pcm.BitsPerSample)
throw new Exception("AudioBuffer format mismatch");
}

View File

@@ -9,12 +9,14 @@ namespace CUETools.Codecs
public class AudioEncoderSettings
{
public AudioEncoderSettings()
: this("", "")
{
// Iterate through each property and call ResetValue()
foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(this))
property.ResetValue(this);
this.m_supported_modes = "";
this.EncoderMode = "";
}
public AudioEncoderSettings(AudioPCMConfig pcm)
: this("", "")
{
this.PCM = pcm;
}
public AudioEncoderSettings(string supported_modes, string default_mode)
@@ -38,24 +40,36 @@ namespace CUETools.Codecs
return BlockSize == 0 && Padding >= 0;
}
public T Clone<T>() where T : AudioEncoderSettings
public void Validate()
{
if (this as T == null)
throw new Exception("Unsupported options " + this);
var result = this.MemberwiseClone() as T;
if (!result.IsValid())
if (!IsValid())
throw new Exception("unsupported encoder settings");
return result;
}
public AudioEncoderSettings Clone()
{
return this.MemberwiseClone() as AudioEncoderSettings;
}
[Browsable(false)]
[XmlIgnore]
public AudioPCMConfig PCM
{
get;
set;
}
[Browsable(false)]
[DefaultValue(0)]
public int BlockSize
{
get; set;
get;
set;
}
[Browsable(false)]
[XmlIgnore]
[DefaultValue(4096)]
public int Padding
{
@@ -64,6 +78,7 @@ namespace CUETools.Codecs
}
[Browsable(false)]
[DefaultValue("")]
public string EncoderMode
{
get;

View File

@@ -94,6 +94,7 @@
<Compile Include="UserDefinedWriter.cs" />
<Compile Include="WAVReader.cs" />
<Compile Include="WAVWriter.cs" />
<Compile Include="WAVWriterSettings.cs" />
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include="Microsoft.Net.Client.3.5">

View File

@@ -4,11 +4,11 @@ namespace CUETools.Codecs
{
public class DummyWriter : IAudioDest
{
AudioPCMConfig _pcm;
AudioEncoderSettings m_settings;
public DummyWriter(string path, AudioPCMConfig pcm)
public DummyWriter(string path, AudioEncoderSettings settings)
{
_pcm = pcm;
m_settings = settings;
}
public void Close()
@@ -28,18 +28,8 @@ namespace CUETools.Codecs
{
get
{
return new AudioEncoderSettings();
return m_settings;
}
set
{
if (value != null && value.GetType() != typeof(AudioEncoderSettings))
throw new Exception("Unsupported options " + value);
}
}
public AudioPCMConfig PCM
{
get { return _pcm; }
}
public void Write(AudioBuffer buff)

View File

@@ -2,11 +2,10 @@
{
public interface IAudioDest
{
AudioPCMConfig PCM { get; }
string Path { get; }
AudioEncoderSettings Settings { get; set; }
long FinalSampleCount { set; }
AudioEncoderSettings Settings { get; }
string Path { get; }
long FinalSampleCount { set; }
void Write(AudioBuffer buffer);
void Close();

View File

@@ -14,6 +14,7 @@ namespace CUETools.Codecs
string tempFile = null;
long _finalSampleCount = -1;
bool closed = false;
private AudioEncoderSettings m_settings;
public long Position
{
@@ -29,29 +30,19 @@ namespace CUETools.Codecs
}
// !!!! Must not start the process in constructor, so that we can set CompressionLevel via Settings!
private AudioEncoderSettings m_settings = new AudioEncoderSettings();
public AudioEncoderSettings Settings
{
get
{
return m_settings;
}
set
{
m_settings = value.Clone<AudioEncoderSettings>();
}
}
public AudioPCMConfig PCM
{
get { return wrt.PCM; }
}
public string Path { get { return _path; } }
public UserDefinedWriter(string path, Stream IO, AudioPCMConfig pcm, string encoder, string encoderParams, string encoderMode, int padding)
public UserDefinedWriter(string path, Stream IO, AudioEncoderSettings settings, string encoder, string encoderParams, string encoderMode, int padding)
{
m_settings = settings as AudioEncoderSettings;
_path = path;
_encoder = encoder;
_encoderParams = encoderParams;
@@ -70,7 +61,7 @@ namespace CUETools.Codecs
_encoderProcess.StartInfo.RedirectStandardOutput = true;
if (useTempFile)
{
wrt = new WAVWriter(tempFile, null, pcm);
wrt = new WAVWriter(tempFile, null, new WAVWriterSettings(settings.PCM));
return;
}
bool started = false;
@@ -93,7 +84,7 @@ namespace CUETools.Codecs
outputBuffer = new CyclicBuffer(2 * 1024 * 1024, _encoderProcess.StandardOutput.BaseStream, outputStream);
}
Stream inputStream = new CyclicBufferOutputStream(_encoderProcess.StandardInput.BaseStream, 128 * 1024);
wrt = new WAVWriter(path, inputStream, pcm);
wrt = new WAVWriter(path, inputStream, new WAVWriterSettings(settings.PCM));
}
public void Close()

View File

@@ -4,12 +4,11 @@ using System.IO;
namespace CUETools.Codecs
{
[AudioEncoderClass("cuetools", "wav", true, 10, typeof(AudioEncoderSettings))]
[AudioEncoderClass("cuetools", "wav", true, 10, typeof(WAVWriterSettings))]
public class WAVWriter : IAudioDest
{
private Stream _IO;
private BinaryWriter _bw;
private AudioPCMConfig _pcm;
private long _sampleLen;
private string _path;
private long hdrLen = 0;
@@ -17,6 +16,7 @@ namespace CUETools.Codecs
private long _finalSampleCount = -1;
private List<byte[]> _chunks = null;
private List<uint> _chunkFCCs = null;
private WAVWriterSettings m_settings;
public long Position
{
@@ -35,32 +35,22 @@ namespace CUETools.Codecs
{
get
{
return new AudioEncoderSettings();
return m_settings;
}
set
{
if (value != null && value.GetType() != typeof(AudioEncoderSettings))
throw new Exception("Unsupported options " + value);
}
}
public AudioPCMConfig PCM
{
get { return _pcm; }
}
public string Path { get { return _path; } }
public WAVWriter(string path, Stream IO, AudioPCMConfig pcm)
public WAVWriter(string path, Stream IO, WAVWriterSettings settings)
{
_pcm = pcm;
m_settings = settings;
_path = path;
_IO = IO != null ? IO : new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read);
_bw = new BinaryWriter(_IO);
}
public WAVWriter(string path, AudioPCMConfig pcm)
: this(path, null, pcm)
public WAVWriter(string path, WAVWriterSettings settings)
: this(path, null, settings)
{
}
@@ -85,11 +75,11 @@ namespace CUETools.Codecs
const uint fccFormat = 0x20746D66;
const uint fccData = 0x61746164;
bool wavex = _pcm.BitsPerSample != 16 && _pcm.BitsPerSample != 24;
bool wavex = Settings.PCM.BitsPerSample != 16 && Settings.PCM.BitsPerSample != 24;
hdrLen += 36 + (wavex ? 24 : 0) + 8;
uint dataLen = (uint)(_finalSampleCount * _pcm.BlockAlign);
uint dataLen = (uint)(_finalSampleCount * Settings.PCM.BlockAlign);
uint dataLenPadded = dataLen + (dataLen & 1);
_bw.Write(fccRIFF);
@@ -106,15 +96,15 @@ namespace CUETools.Codecs
_bw.Write((uint)16);
_bw.Write((ushort)1); // PCM
}
_bw.Write((ushort)_pcm.ChannelCount);
_bw.Write((uint)_pcm.SampleRate);
_bw.Write((uint)(_pcm.SampleRate * _pcm.BlockAlign));
_bw.Write((ushort)_pcm.BlockAlign);
_bw.Write((ushort)((_pcm.BitsPerSample + 7) / 8 * 8));
_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)_pcm.BitsPerSample);
_bw.Write((ushort)Settings.PCM.BitsPerSample);
_bw.Write((uint)3); // speaker positions (3 == stereo)
_bw.Write((ushort)1); // PCM
_bw.Write((ushort)0);
@@ -150,11 +140,11 @@ namespace CUETools.Codecs
if (_finalSampleCount <= 0)
{
const long maxFileSize = 0x7FFFFFFEL;
long dataLen = _sampleLen * _pcm.BlockAlign;
long dataLen = _sampleLen * Settings.PCM.BlockAlign;
if ((dataLen & 1) == 1)
_bw.Write((byte)0);
if (dataLen + hdrLen > maxFileSize)
dataLen = ((maxFileSize - hdrLen) / _pcm.BlockAlign) * _pcm.BlockAlign;
dataLen = ((maxFileSize - hdrLen) / Settings.PCM.BlockAlign) * Settings.PCM.BlockAlign;
long dataLenPadded = dataLen + (dataLen & 1);
_bw.Seek(4, SeekOrigin.Begin);

View File

@@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace CUETools.Codecs
{
public class WAVWriterSettings : AudioEncoderSettings
{
public WAVWriterSettings()
: this(null)
{
}
public WAVWriterSettings(AudioPCMConfig pcm)
: base(pcm)
{
}
}
}

View File

@@ -10,6 +10,7 @@ namespace CUETools.DSP.Mixer
private long samplePos;
private MixingBuffer mixbuff;
private float volume;
private AudioEncoderSettings m_settings;
public long Position
{
@@ -26,18 +27,8 @@ namespace CUETools.DSP.Mixer
{
get
{
return new AudioEncoderSettings();
return m_settings;
}
set
{
if (value != null && value.GetType() != typeof(AudioEncoderSettings))
throw new Exception("Unsupported options " + value);
}
}
public AudioPCMConfig PCM
{
get { return mixer.PCM; }
}
public float Volume
@@ -50,6 +41,7 @@ namespace CUETools.DSP.Mixer
public MixingWriter(MixingSource mixer, int iSource)
{
this.m_settings = new AudioEncoderSettings(mixer.PCM);
this.mixer = mixer;
this.iSource = iSource;
this.samplePos = 0;
@@ -76,7 +68,7 @@ namespace CUETools.DSP.Mixer
if (mixbuff != null)
{
if (mixbuff.source[iSource].Length < mixbuff.source[iSource].Size)
AudioSamples.MemSet(mixbuff.source[iSource].Bytes, 0, mixbuff.source[iSource].Length * PCM.BlockAlign, (mixbuff.source[iSource].Size - mixbuff.source[iSource].Length) * PCM.BlockAlign);
AudioSamples.MemSet(mixbuff.source[iSource].Bytes, 0, mixbuff.source[iSource].Length * Settings.PCM.BlockAlign, (mixbuff.source[iSource].Size - mixbuff.source[iSource].Length) * Settings.PCM.BlockAlign);
mixer.UnlockEmptyBuffer(mixbuff, iSource, volume);
mixbuff = null;
}
@@ -84,7 +76,7 @@ namespace CUETools.DSP.Mixer
public void Write(AudioBuffer buff)
{
int bs = PCM.BlockAlign;
int bs = Settings.PCM.BlockAlign;
int buff_offs = 0;
while (buff_offs < buff.Length)

View File

@@ -247,10 +247,11 @@ namespace CUETools.FLACCL.cmd
audioSource = new AudioPipe(audioSource, FLACCLWriter.MAX_BLOCKSIZE);
if (output_file == null)
output_file = Path.ChangeExtension(input_file, "flac");
settings.PCM = audioSource.PCM;
FLACCLWriter encoder = new FLACCLWriter((output_file == "-" || output_file == "nul") ? "" : output_file,
output_file == "-" ? Console.OpenStandardOutput() :
output_file == "nul" ? new NullStream() : null,
audioSource.PCM);
settings);
encoder.FinalSampleCount = audioSource.Length;
IAudioDest audioDest = encoder;
AudioBuffer buff = new AudioBuffer(audioSource, FLACCLWriter.MAX_BLOCKSIZE);
@@ -259,7 +260,7 @@ namespace CUETools.FLACCL.cmd
{
if (device_type != null)
settings.DeviceType = (OpenCLDeviceType)(Enum.Parse(typeof(OpenCLDeviceType), device_type, true));
encoder.Settings = settings;
settings.Validate();
if (stereo_method != null)
encoder.StereoMethod = Flake.LookupStereoMethod(stereo_method);
if (window_function != null)

View File

@@ -323,17 +323,18 @@ namespace CUETools.FlakeExe
audioSource = new AudioPipe(audioSource, 0x10000);
if (output_file == null)
output_file = Path.ChangeExtension(input_file, "flac");
settings.PCM = audioSource.PCM;
FlakeWriter flake = new FlakeWriter((output_file == "-" || output_file == "nul") ? "" : output_file,
output_file == "-" ? Console.OpenStandardOutput() :
output_file == "nul" ? new NullStream() : null,
audioSource.PCM);
settings);
flake.FinalSampleCount = audioSource.Length - skip_a - skip_b;
IAudioDest audioDest = flake;
AudioBuffer buff = new AudioBuffer(audioSource, 0x10000);
try
{
flake.Settings = settings;
settings.Validate();
if (prediction_type != null)
flake.PredictionType = Flake.LookupPredictionType(prediction_type);
if (stereo_method != null)

View File

@@ -93,9 +93,9 @@ namespace LossyWAVSharp
WAVReader audioSource = new WAVReader(sourceFile, (sourceFile == "-" ? Console.OpenStandardInput() : null));
if (sourceFile == "-" && stdinName != null) sourceFile = stdinName;
AudioPCMConfig pcm = outputBPS == 0 ? audioSource.PCM : new AudioPCMConfig(outputBPS, audioSource.PCM.ChannelCount, audioSource.PCM.SampleRate);
WAVWriter audioDest = new WAVWriter(Path.ChangeExtension(sourceFile, ".lossy.wav"), toStdout ? Console.OpenStandardOutput() : null, pcm);
WAVWriter lwcdfDest = createCorrection ? new WAVWriter(Path.ChangeExtension(sourceFile, ".lwcdf.wav"), null, audioSource.PCM) : null;
LossyWAVWriter lossyWAV = new LossyWAVWriter(audioDest, lwcdfDest, quality, audioSource.PCM);
WAVWriter audioDest = new WAVWriter(Path.ChangeExtension(sourceFile, ".lossy.wav"), toStdout ? Console.OpenStandardOutput() : null, new WAVWriterSettings(pcm));
WAVWriter lwcdfDest = createCorrection ? new WAVWriter(Path.ChangeExtension(sourceFile, ".lwcdf.wav"), null, new WAVWriterSettings(audioSource.PCM)) : null;
LossyWAVWriter lossyWAV = new LossyWAVWriter(audioDest, lwcdfDest, quality, new AudioEncoderSettings(audioSource.PCM));
AudioBuffer buff = new AudioBuffer(audioSource, 0x10000);
Console.WriteLine("Filename : {0}", sourceFile);

View File

@@ -74,7 +74,7 @@ namespace CUETools.Processor
IAudioDest dest;
if (audioEncoderType == AudioEncoderType.NoAudio || extension == ".dummy")
{
dest = new DummyWriter(path, pcm);
dest = new DummyWriter(path, new AudioEncoderSettings(pcm));
dest.FinalSampleCount = finalSampleCount;
return dest;
}
@@ -86,19 +86,21 @@ namespace CUETools.Processor
null;
if (encoder == null)
throw new Exception("Unsupported audio type: " + path);
if (encoder.path != null)
dest = new UserDefinedWriter(path, null, pcm, encoder.path, encoder.parameters, encoder.EncoderMode, padding);
var settings = encoder.settings.Clone();
settings.PCM = pcm;
settings.Padding = padding;
settings.Validate();
if (encoder.path != null)
dest = new UserDefinedWriter(path, null, settings, encoder.path, encoder.parameters, encoder.EncoderMode, padding);
else if (encoder.type != null)
{
object o = Activator.CreateInstance(encoder.type, path, pcm);
object o = Activator.CreateInstance(encoder.type, path, settings);
if (o == null || !(o is IAudioDest))
throw new Exception("Unsupported audio type: " + path + ": " + encoder.type.FullName);
dest = o as IAudioDest;
}
else
throw new Exception("Unsupported audio type: " + path);
dest.Settings = encoder.settings;
dest.Settings.Padding = padding;
dest.FinalSampleCount = finalSampleCount;
return dest;
}
@@ -114,7 +116,7 @@ namespace CUETools.Processor
AudioPCMConfig lossypcm = new AudioPCMConfig((config.detectHDCD && config.decodeHDCD && !config.decodeHDCDtoLW16) ? 24 : 16, pcm.ChannelCount, pcm.SampleRate);
IAudioDest lossyDest = GetAudioDest(AudioEncoderType.Lossless, path, lossypcm, finalSampleCount, padding, extension, config);
IAudioDest lwcdfDest = audioEncoderType == AudioEncoderType.Hybrid ? GetAudioDest(AudioEncoderType.Lossless, lwcdfPath, lossypcm, finalSampleCount, padding, extension, config) : null;
return new LossyWAVWriter(lossyDest, lwcdfDest, config.lossyWAVQuality, pcm);
return new LossyWAVWriter(lossyDest, lwcdfDest, config.lossyWAVQuality, new AudioEncoderSettings(pcm));
}
}
}

View File

@@ -154,7 +154,15 @@ namespace CUETools.Processor
encoders = new CUEToolsUDCList();
foreach (Type type in CUEProcessorPlugins.encs)
foreach (AudioEncoderClass enc in Attribute.GetCustomAttributes(type, typeof(AudioEncoderClass)))
encoders.Add(new CUEToolsUDC(enc, type));
{
try
{
encoders.Add(new CUEToolsUDC(enc, type));
}
catch (Exception)
{
}
}
decoders = new CUEToolsUDCList();
foreach (Type type in CUEProcessorPlugins.decs)
foreach (AudioDecoderClass dec in Attribute.GetCustomAttributes(type, typeof(AudioDecoderClass)))

View File

@@ -3877,7 +3877,7 @@ namespace CUETools.Processor
{
var pcm = new AudioPCMConfig(bps, 2, 44100);
if (noOutput)
return new DummyWriter(path, pcm);
return new DummyWriter(path, new AudioEncoderSettings(pcm));
return AudioReadWrite.GetAudioDest(_audioEncoderType, path, finalSampleCount, padding, pcm, _config);
}

View File

@@ -242,7 +242,7 @@ namespace CUETools.ConsoleRipper
cueFile.Close();
//IAudioDest audioDest = new FLACWriter(destFile, audioSource.BitsPerSample, audioSource.ChannelCount, audioSource.SampleRate);
IAudioDest audioDest = new WAVWriter(destFile, null, audioSource.PCM);
IAudioDest audioDest = new WAVWriter(destFile, null, new WAVWriterSettings(audioSource.PCM));
audioDest.FinalSampleCount = audioSource.Length;
while (audioSource.Read(buff, -1) != 0)
{

View File

@@ -79,7 +79,7 @@ namespace CUETools.TestCodecs
AudioBuffer buff = WAVReader.ReadAllSamples("test.wav", null);
ALACWriter target;
target = new ALACWriter("alacwriter1.m4a", null, buff.PCM);
target = new ALACWriter("alacwriter1.m4a", null, new ALACWriterSettings() { PCM = buff.PCM });
target.Settings.Padding = 1;
target.Vendor = "CUETools";
target.CreationTime = DateTime.Parse("15 Aug 1976");
@@ -88,7 +88,7 @@ namespace CUETools.TestCodecs
target.Close();
CollectionAssert.AreEqual(File.ReadAllBytes("alac.m4a"), File.ReadAllBytes("alacwriter1.m4a"), "alacwriter1.m4a doesn't match.");
target = new ALACWriter("alacwriter0.m4a", null, buff.PCM);
target = new ALACWriter("alacwriter0.m4a", null, new ALACWriterSettings() { PCM = buff.PCM });
target.Settings.Padding = 1;
target.Vendor = "CUETools";
target.CreationTime = DateTime.Parse("15 Aug 1976");

View File

@@ -336,13 +336,13 @@ namespace CUETools.TestCodecs
AudioBuffer buff = WAVReader.ReadAllSamples("test.wav", null);
WAVWriter target;
target = new WAVWriter("wavwriter0.wav", null, buff.PCM);
target = new WAVWriter("wavwriter0.wav", null, new WAVWriterSettings(buff.PCM));
//target.FinalSampleCount = buff.Length;
target.Write(buff);
target.Close();
CollectionAssert.AreEqual(File.ReadAllBytes("test.wav"), File.ReadAllBytes("wavwriter0.wav"), "wavwriter0.wav doesn't match.");
target = new WAVWriter("wavwriter1.wav", null, buff.PCM);
target = new WAVWriter("wavwriter1.wav", null, new WAVWriterSettings(buff.PCM));
target.FinalSampleCount = buff.Length;
target.Write(buff);
target.Close();

View File

@@ -38,7 +38,7 @@ namespace CUETools.TestCodecs
AudioBuffer buff = WAVReader.ReadAllSamples("test.wav", null);
FLACWriter target;
target = new FLACWriter("flacwriter2.flac", buff.PCM);
target = new FLACWriter("flacwriter2.flac", new FLACWriterSettings() { PCM = buff.PCM });
target.Settings.Padding = 1;
target.Settings.BlockSize = 32;
//target.Vendor = "CUETools";

View File

@@ -73,31 +73,31 @@ namespace CUETools.TestCodecs
/// <summary>
///A test for FlakeWriter (string, int, int, int, Stream)
///</summary>
[TestMethod()]
public void ConstructorTest()
{
AudioBuffer buff = WAVReader.ReadAllSamples("test.wav", null);
FlakeWriter target;
[TestMethod()]
public void ConstructorTest()
{
AudioBuffer buff = WAVReader.ReadAllSamples("test.wav", null);
FlakeWriter target;
target = new FlakeWriter("flakewriter0.flac", null, buff.PCM);
target.Settings.Padding = 1;
target.DoSeekTable = false;
//target.Vendor = "CUETools";
//target.CreationTime = DateTime.Parse("15 Aug 1976");
target.FinalSampleCount = buff.Length;
target.Write(buff);
target.Close();
CollectionAssert.AreEqual(File.ReadAllBytes("flake.flac"), File.ReadAllBytes("flakewriter0.flac"), "flakewriter0.flac doesn't match.");
target = new FlakeWriter("flakewriter0.flac", null, new FlakeWriterSettings() { PCM = buff.PCM });
target.Settings.Padding = 1;
target.DoSeekTable = false;
//target.Vendor = "CUETools";
//target.CreationTime = DateTime.Parse("15 Aug 1976");
target.FinalSampleCount = buff.Length;
target.Write(buff);
target.Close();
CollectionAssert.AreEqual(File.ReadAllBytes("flake.flac"), File.ReadAllBytes("flakewriter0.flac"), "flakewriter0.flac doesn't match.");
target = new FlakeWriter("flakewriter1.flac", null, buff.PCM);
target.Settings.Padding = 1;
target.DoSeekTable = false;
//target.Vendor = "CUETools";
//target.CreationTime = DateTime.Parse("15 Aug 1976");
target.Write(buff);
target.Close();
CollectionAssert.AreEqual(File.ReadAllBytes("flake.flac"), File.ReadAllBytes("flakewriter1.flac"), "flakewriter1.flac doesn't match.");
}
target = new FlakeWriter("flakewriter1.flac", null, new FlakeWriterSettings() { PCM = buff.PCM });
target.Settings.Padding = 1;
target.DoSeekTable = false;
//target.Vendor = "CUETools";
//target.CreationTime = DateTime.Parse("15 Aug 1976");
target.Write(buff);
target.Close();
CollectionAssert.AreEqual(File.ReadAllBytes("flake.flac"), File.ReadAllBytes("flakewriter1.flac"), "flakewriter1.flac doesn't match.");
}
public static unsafe void
compute_schur_reflection(/*const*/ double* autoc, uint max_order,

View File

@@ -172,7 +172,7 @@ namespace JDP {
//
// toolStripContainer1.LeftToolStripPanel
//
this.toolStripContainer1.LeftToolStripPanel.MaximumSize = new System.Drawing.Size(32, 0);
resources.ApplyResources(this.toolStripContainer1.LeftToolStripPanel, "toolStripContainer1.LeftToolStripPanel");
this.toolStripContainer1.LeftToolStripPanelVisible = false;
this.toolStripContainer1.Name = "toolStripContainer1";
this.toolStripContainer1.RightToolStripPanelVisible = false;
@@ -357,7 +357,6 @@ namespace JDP {
//
resources.ApplyResources(this.checkBoxUseAccurateRip, "checkBoxUseAccurateRip");
this.checkBoxUseAccurateRip.Image = global::JDP.Properties.Resources.AR;
this.checkBoxUseAccurateRip.MinimumSize = new System.Drawing.Size(0, 16);
this.checkBoxUseAccurateRip.Name = "checkBoxUseAccurateRip";
this.toolTip1.SetToolTip(this.checkBoxUseAccurateRip, resources.GetString("checkBoxUseAccurateRip.ToolTip"));
this.checkBoxUseAccurateRip.UseVisualStyleBackColor = true;
@@ -367,7 +366,6 @@ namespace JDP {
//
resources.ApplyResources(this.checkBoxUseFreeDb, "checkBoxUseFreeDb");
this.checkBoxUseFreeDb.Image = global::JDP.Properties.Resources.freedb16;
this.checkBoxUseFreeDb.MinimumSize = new System.Drawing.Size(0, 16);
this.checkBoxUseFreeDb.Name = "checkBoxUseFreeDb";
this.toolTip1.SetToolTip(this.checkBoxUseFreeDb, resources.GetString("checkBoxUseFreeDb.ToolTip"));
this.checkBoxUseFreeDb.UseVisualStyleBackColor = true;
@@ -405,7 +403,6 @@ namespace JDP {
//
resources.ApplyResources(this.checkBoxUseMusicBrainz, "checkBoxUseMusicBrainz");
this.checkBoxUseMusicBrainz.Image = global::JDP.Properties.Resources.musicbrainz;
this.checkBoxUseMusicBrainz.MinimumSize = new System.Drawing.Size(0, 16);
this.checkBoxUseMusicBrainz.Name = "checkBoxUseMusicBrainz";
this.toolTip1.SetToolTip(this.checkBoxUseMusicBrainz, resources.GetString("checkBoxUseMusicBrainz.ToolTip"));
this.checkBoxUseMusicBrainz.UseVisualStyleBackColor = true;
@@ -549,7 +546,6 @@ namespace JDP {
// labelFormat
//
resources.ApplyResources(this.labelFormat, "labelFormat");
this.labelFormat.MinimumSize = new System.Drawing.Size(16, 16);
this.labelFormat.Name = "labelFormat";
//
// comboBoxAudioFormat

View File

@@ -40,6 +40,7 @@ using CUETools.CTDB;
using CUETools.Compression;
using CUETools.Processor;
using CUETools.Processor.Settings;
using CUETools.Codecs;
namespace JDP
{
@@ -2452,6 +2453,8 @@ namespace JDP
SelectedOutputAudioFmt.encoderLossless = encoder;
else
SelectedOutputAudioFmt.encoderLossy = encoder;
// TODO: something cleverer than this hack...
if (encoder.settings != null) encoder.settings.PCM = AudioPCMConfig.RedBook;
string[] modes = encoder.SupportedModes;
if (modes == null || modes.Length < 2)
{

View File

@@ -126,7 +126,7 @@
</data>
<assembly alias="System.Drawing" name="System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="toolStripStatusLabel1.Size" type="System.Drawing.Size, System.Drawing">
<value>401, 24</value>
<value>503, 24</value>
</data>
<data name="toolStripStatusLabel1.TextAlign" type="System.Drawing.ContentAlignment, System.Drawing">
<value>MiddleLeft</value>
@@ -465,6 +465,9 @@
<data name="checkBoxUseAccurateRip.Margin" type="System.Windows.Forms.Padding, System.Windows.Forms">
<value>0, 0, 0, 0</value>
</data>
<data name="checkBoxUseAccurateRip.MinimumSize" type="System.Drawing.Size, System.Drawing">
<value>0, 16</value>
</data>
<data name="checkBoxUseAccurateRip.Size" type="System.Drawing.Size, System.Drawing">
<value>49, 26</value>
</data>
@@ -501,6 +504,9 @@
<data name="checkBoxUseFreeDb.Margin" type="System.Windows.Forms.Padding, System.Windows.Forms">
<value>0, 0, 0, 0</value>
</data>
<data name="checkBoxUseFreeDb.MinimumSize" type="System.Drawing.Size, System.Drawing">
<value>0, 16</value>
</data>
<data name="checkBoxUseFreeDb.Size" type="System.Drawing.Size, System.Drawing">
<value>48, 26</value>
</data>
@@ -654,6 +660,9 @@
<data name="checkBoxUseMusicBrainz.Margin" type="System.Windows.Forms.Padding, System.Windows.Forms">
<value>0, 0, 0, 0</value>
</data>
<data name="checkBoxUseMusicBrainz.MinimumSize" type="System.Drawing.Size, System.Drawing">
<value>0, 16</value>
</data>
<data name="checkBoxUseMusicBrainz.Size" type="System.Drawing.Size, System.Drawing">
<value>47, 26</value>
</data>
@@ -1128,6 +1137,9 @@
<data name="labelFormat.Location" type="System.Drawing.Point, System.Drawing">
<value>11, 90</value>
</data>
<data name="labelFormat.MinimumSize" type="System.Drawing.Size, System.Drawing">
<value>16, 16</value>
</data>
<data name="labelFormat.Size" type="System.Drawing.Size, System.Drawing">
<value>16, 16</value>
</data>
@@ -2253,6 +2265,9 @@
<data name="toolStripContainer1.Dock" type="System.Windows.Forms.DockStyle, System.Windows.Forms">
<value>Fill</value>
</data>
<data name="toolStripContainer1.LeftToolStripPanel.MaximumSize" type="System.Drawing.Size, System.Drawing">
<value>32, 0</value>
</data>
<data name="&gt;&gt;toolStripContainer1.LeftToolStripPanel.Name" xml:space="preserve">
<value>toolStripContainer1.LeftToolStripPanel</value>
</data>