From 9670c6c8913bce9014c05cc8e08088c94715cb69 Mon Sep 17 00:00:00 2001 From: Grigory Chudov Date: Sun, 7 Apr 2013 20:41:58 -0400 Subject: [PATCH] Refactoring codecs infrastructure: AudioWriterSettings passed to IAdioDest constructors now AudioWriterSettings now includes AudioPCMConfig --- CUEPlayer/Output.cs | 4 +- CUETools.ALACEnc/Program.cs | 5 +- CUETools.AccurateRip/AccurateRip.cs | 12 +- CUETools.AccurateRip/CDRepair.cs | 12 +- CUETools.Codecs.ALAC/ALACWriter.cs | 122 +++--- CUETools.Codecs.APE/CUETools.Codecs.APE.cpp | 27 +- CUETools.Codecs.CoreAudio/WasapiOut.cs | 24 +- CUETools.Codecs.FLAC/CUETools.Codecs.FLAC.cpp | 28 +- CUETools.Codecs.FLACCL/FLACCLWriter.cs | 131 +++---- CUETools.Codecs.FLAKE/FlakeWriter.cs | 89 ++--- CUETools.Codecs.HDCD/HDCDDotNet.cs | 5 - CUETools.Codecs.Icecast/IcecastWriter.cs | 26 +- CUETools.Codecs.LAME/LAMEEncoder.cs | 26 +- CUETools.Codecs.LAME/LAMEEncoderCBR.cs | 16 +- CUETools.Codecs.LAME/LAMEEncoderVBR.cs | 16 +- CUETools.Codecs.LAME/LameWriter.cs | 29 +- CUETools.Codecs.LossyWAV/LossyWAVWriter.cs | 78 ++-- CUETools.Codecs.TTA/CUETools.Codecs.TTA.cpp | 36 +- CUETools.Codecs.WMA/WMAWriter.cs | 353 +++++++++++------- .../CUETools.Codecs.WavPack.cpp | 39 +- CUETools.Codecs/AudioBuffer.cs | 2 +- CUETools.Codecs/AudioEncoderSettings.cs | 39 +- CUETools.Codecs/CUETools.Codecs.csproj | 1 + CUETools.Codecs/DummyWriter.cs | 18 +- CUETools.Codecs/IAudioDest.cs | 9 +- CUETools.Codecs/UserDefinedWriter.cs | 19 +- CUETools.Codecs/WAVWriter.cs | 44 +-- CUETools.Codecs/WAVWriterSettings.cs | 19 + CUETools.DSP.Mixer/MixingWriter.cs | 18 +- CUETools.FLACCL.cmd/Program.cs | 5 +- CUETools.Flake/Program.cs | 5 +- CUETools.LossyWAV/Program.cs | 6 +- CUETools.Processor/AudioReadWrite.cs | 16 +- CUETools.Processor/CUEConfig.cs | 10 +- CUETools.Processor/CUESheet.cs | 2 +- CUETools.Ripper.Console/Program.cs | 2 +- .../CUETools.TestCodecs/ALACWriterTest.cs | 4 +- CUETools/CUETools.TestCodecs/CodecsTest.cs | 4 +- .../CUETools.TestCodecs/FlacWriterTest.cs | 2 +- .../CUETools.TestCodecs/FlakeWriterTest.cs | 46 +-- CUETools/frmCUETools.Designer.cs | 6 +- CUETools/frmCUETools.cs | 3 + CUETools/frmCUETools.resx | 17 +- 43 files changed, 652 insertions(+), 723 deletions(-) create mode 100644 CUETools.Codecs/WAVWriterSettings.cs diff --git a/CUEPlayer/Output.cs b/CUEPlayer/Output.cs index 6c87bda..1143556 100644 --- a/CUEPlayer/Output.cs +++ b/CUEPlayer/Output.cs @@ -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) { diff --git a/CUETools.ALACEnc/Program.cs b/CUETools.ALACEnc/Program.cs index 2f4498c..f676d07 100644 --- a/CUETools.ALACEnc/Program.cs +++ b/CUETools.ALACEnc/Program.cs @@ -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) diff --git a/CUETools.AccurateRip/AccurateRip.cs b/CUETools.AccurateRip/AccurateRip.cs index 9658a19..ef9a8fc 100644 --- a/CUETools.AccurateRip/AccurateRip.cs +++ b/CUETools.AccurateRip/AccurateRip.cs @@ -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 diff --git a/CUETools.AccurateRip/CDRepair.cs b/CUETools.AccurateRip/CDRepair.cs index 2c0efbc..463c234 100644 --- a/CUETools.AccurateRip/CDRepair.cs +++ b/CUETools.AccurateRip/CDRepair.cs @@ -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 diff --git a/CUETools.Codecs.ALAC/ALACWriter.cs b/CUETools.Codecs.ALAC/ALACWriter.cs index 042810f..999abf2 100644 --- a/CUETools.Codecs.ALAC/ALACWriter.cs +++ b/CUETools.Codecs.ALAC/ALACWriter.cs @@ -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 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(); } - 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(); - 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; } - } - /// /// Copy channel-interleaved input samples into separate subframes /// @@ -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) diff --git a/CUETools.Codecs.APE/CUETools.Codecs.APE.cpp b/CUETools.Codecs.APE/CUETools.Codecs.APE.cpp index e572a10..62b739d 100644 --- a/CUETools.Codecs.APE/CUETools.Codecs.APE.cpp +++ b/CUETools.Codecs.APE/CUETools.Codecs.APE.cpp @@ -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(); - } } 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); diff --git a/CUETools.Codecs.CoreAudio/WasapiOut.cs b/CUETools.Codecs.CoreAudio/WasapiOut.cs index 887052b..045cbfd 100644 --- a/CUETools.Codecs.CoreAudio/WasapiOut.cs +++ b/CUETools.Codecs.CoreAudio/WasapiOut.cs @@ -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; /// /// Playback Stopped @@ -67,11 +67,11 @@ namespace CUETools.Codecs.CoreAudio /// 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; } } diff --git a/CUETools.Codecs.FLAC/CUETools.Codecs.FLAC.cpp b/CUETools.Codecs.FLAC/CUETools.Codecs.FLAC.cpp index 64ed654..b3144ab 100644 --- a/CUETools.Codecs.FLAC/CUETools.Codecs.FLAC.cpp +++ b/CUETools.Codecs.FLAC/CUETools.Codecs.FLAC.cpp @@ -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(); - } } 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; } diff --git a/CUETools.Codecs.FLACCL/FLACCLWriter.cs b/CUETools.Codecs.FLACCL/FLACCLWriter.cs index 953ec9e..3482be9 100644 --- a/CUETools.Codecs.FLACCL/FLACCLWriter.cs +++ b/CUETools.Codecs.FLACCL/FLACCLWriter.cs @@ -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(); - 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); diff --git a/CUETools.Codecs.FLAKE/FlakeWriter.cs b/CUETools.Codecs.FLAKE/FlakeWriter.cs index 0aee750..0b7feec 100644 --- a/CUETools.Codecs.FLAKE/FlakeWriter.cs +++ b/CUETools.Codecs.FLAKE/FlakeWriter.cs @@ -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(); - 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]; } diff --git a/CUETools.Codecs.HDCD/HDCDDotNet.cs b/CUETools.Codecs.HDCD/HDCDDotNet.cs index aa266fc..31c22ef 100644 --- a/CUETools.Codecs.HDCD/HDCDDotNet.cs +++ b/CUETools.Codecs.HDCD/HDCDDotNet.cs @@ -79,11 +79,6 @@ namespace HDCDDotNet } } - public AudioPCMConfig PCM - { - get { return AudioPCMConfig.RedBook; } - } - public long FinalSampleCount { set { throw new Exception("unsupported"); } diff --git a/CUETools.Codecs.Icecast/IcecastWriter.cs b/CUETools.Codecs.Icecast/IcecastWriter.cs index 4423a20..96a5156 100644 --- a/CUETools.Codecs.Icecast/IcecastWriter.cs +++ b/CUETools.Codecs.Icecast/IcecastWriter.cs @@ -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; } } diff --git a/CUETools.Codecs.LAME/LAMEEncoder.cs b/CUETools.Codecs.LAME/LAMEEncoder.cs index 680f856..6f09a57 100644 --- a/CUETools.Codecs.LAME/LAMEEncoder.cs +++ b/CUETools.Codecs.LAME/LAMEEncoder.cs @@ -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() diff --git a/CUETools.Codecs.LAME/LAMEEncoderCBR.cs b/CUETools.Codecs.LAME/LAMEEncoderCBR.cs index 2303403..a4c97eb 100644 --- a/CUETools.Codecs.LAME/LAMEEncoderCBR.cs +++ b/CUETools.Codecs.LAME/LAMEEncoderCBR.cs @@ -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(); - } } - 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 diff --git a/CUETools.Codecs.LAME/LAMEEncoderVBR.cs b/CUETools.Codecs.LAME/LAMEEncoderVBR.cs index 726879a..108fdfe 100644 --- a/CUETools.Codecs.LAME/LAMEEncoderVBR.cs +++ b/CUETools.Codecs.LAME/LAMEEncoderVBR.cs @@ -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(); - } } - 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; diff --git a/CUETools.Codecs.LAME/LameWriter.cs b/CUETools.Codecs.LAME/LameWriter.cs index 31f8995..b0e4591 100644 --- a/CUETools.Codecs.LAME/LameWriter.cs +++ b/CUETools.Codecs.LAME/LameWriter.cs @@ -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(); - } } - 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) { diff --git a/CUETools.Codecs.LossyWAV/LossyWAVWriter.cs b/CUETools.Codecs.LossyWAV/LossyWAVWriter.cs index 4fa91ca..c0900f8 100644 --- a/CUETools.Codecs.LossyWAV/LossyWAVWriter.cs +++ b/CUETools.Codecs.LossyWAV/LossyWAVWriter.cs @@ -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++) diff --git a/CUETools.Codecs.TTA/CUETools.Codecs.TTA.cpp b/CUETools.Codecs.TTA/CUETools.Codecs.TTA.cpp index 5159e59..328889c 100644 --- a/CUETools.Codecs.TTA/CUETools.Codecs.TTA.cpp +++ b/CUETools.Codecs.TTA/CUETools.Codecs.TTA.cpp @@ -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 (sampleBuffer->Length * _pcm->ChannelCount); + if ((_sampleBuffer == nullptr) || (_sampleBuffer->Length < sampleBuffer->Length * _settings->PCM->ChannelCount)) + _sampleBuffer = gcnew array (sampleBuffer->Length * _settings->PCM->ChannelCount); interior_ptr pSampleBuffer = &sampleBuffer->Samples[0, 0]; interior_ptr 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 buffer = &_sampleBuffer[0]; @@ -313,11 +315,6 @@ namespace TTA { { return _settings; } - - void set(AudioEncoderSettings^ value) - { - _settings = value->Clone(); - } } 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()]))); diff --git a/CUETools.Codecs.WMA/WMAWriter.cs b/CUETools.Codecs.WMA/WMAWriter.cs index 2fbcb03..104b020 100644 --- a/CUETools.Codecs.WMA/WMAWriter.cs +++ b/CUETools.Codecs.WMA/WMAWriter.cs @@ -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(); - } - } - - 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 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 GetFormats(IWMProfileManager pProfileManager) + { + var formats = new List(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)((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; diff --git a/CUETools.Codecs.WavPack/CUETools.Codecs.WavPack.cpp b/CUETools.Codecs.WavPack/CUETools.Codecs.WavPack.cpp index fd454cf..8ba469b 100644 --- a/CUETools.Codecs.WavPack/CUETools.Codecs.WavPack.cpp +++ b/CUETools.Codecs.WavPack/CUETools.Codecs.WavPack.cpp @@ -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(sampleBuffer->Length, _pcm->ChannelCount); - int shift = 8 - (_pcm->BitsPerSample & 7); - int ch = _pcm->ChannelCount; + _shiftedSampleBuffer = gcnew array(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(); - } } void UpdateHash(array^ buff, Int32 len) @@ -472,7 +460,6 @@ namespace CUETools { namespace Codecs { namespace WavPack { String^ _path; MD5^ _md5hasher; array^ _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; diff --git a/CUETools.Codecs/AudioBuffer.cs b/CUETools.Codecs/AudioBuffer.cs index 016ecbb..34e2e8b 100644 --- a/CUETools.Codecs/AudioBuffer.cs +++ b/CUETools.Codecs/AudioBuffer.cs @@ -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"); } diff --git a/CUETools.Codecs/AudioEncoderSettings.cs b/CUETools.Codecs/AudioEncoderSettings.cs index 3ac6589..205cb48 100644 --- a/CUETools.Codecs/AudioEncoderSettings.cs +++ b/CUETools.Codecs/AudioEncoderSettings.cs @@ -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() 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; diff --git a/CUETools.Codecs/CUETools.Codecs.csproj b/CUETools.Codecs/CUETools.Codecs.csproj index 22f4aab..943e822 100644 --- a/CUETools.Codecs/CUETools.Codecs.csproj +++ b/CUETools.Codecs/CUETools.Codecs.csproj @@ -94,6 +94,7 @@ + diff --git a/CUETools.Codecs/DummyWriter.cs b/CUETools.Codecs/DummyWriter.cs index b024368..5bb91e6 100644 --- a/CUETools.Codecs/DummyWriter.cs +++ b/CUETools.Codecs/DummyWriter.cs @@ -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) diff --git a/CUETools.Codecs/IAudioDest.cs b/CUETools.Codecs/IAudioDest.cs index 130e609..c0394a5 100644 --- a/CUETools.Codecs/IAudioDest.cs +++ b/CUETools.Codecs/IAudioDest.cs @@ -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(); diff --git a/CUETools.Codecs/UserDefinedWriter.cs b/CUETools.Codecs/UserDefinedWriter.cs index d84f01b..b014c76 100644 --- a/CUETools.Codecs/UserDefinedWriter.cs +++ b/CUETools.Codecs/UserDefinedWriter.cs @@ -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(); - } - } - - 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() diff --git a/CUETools.Codecs/WAVWriter.cs b/CUETools.Codecs/WAVWriter.cs index 9524ca7..e4a756f 100644 --- a/CUETools.Codecs/WAVWriter.cs +++ b/CUETools.Codecs/WAVWriter.cs @@ -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 _chunks = null; private List _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); diff --git a/CUETools.Codecs/WAVWriterSettings.cs b/CUETools.Codecs/WAVWriterSettings.cs new file mode 100644 index 0000000..cd7345b --- /dev/null +++ b/CUETools.Codecs/WAVWriterSettings.cs @@ -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) + { + } + } +} diff --git a/CUETools.DSP.Mixer/MixingWriter.cs b/CUETools.DSP.Mixer/MixingWriter.cs index 5cd5c45..b4d3e26 100644 --- a/CUETools.DSP.Mixer/MixingWriter.cs +++ b/CUETools.DSP.Mixer/MixingWriter.cs @@ -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) diff --git a/CUETools.FLACCL.cmd/Program.cs b/CUETools.FLACCL.cmd/Program.cs index f3d6dc9..f755216 100644 --- a/CUETools.FLACCL.cmd/Program.cs +++ b/CUETools.FLACCL.cmd/Program.cs @@ -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) diff --git a/CUETools.Flake/Program.cs b/CUETools.Flake/Program.cs index 2eeb645..42d1485 100644 --- a/CUETools.Flake/Program.cs +++ b/CUETools.Flake/Program.cs @@ -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) diff --git a/CUETools.LossyWAV/Program.cs b/CUETools.LossyWAV/Program.cs index 3074193..1f203b6 100644 --- a/CUETools.LossyWAV/Program.cs +++ b/CUETools.LossyWAV/Program.cs @@ -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); diff --git a/CUETools.Processor/AudioReadWrite.cs b/CUETools.Processor/AudioReadWrite.cs index 26ea0ad..2889e51 100644 --- a/CUETools.Processor/AudioReadWrite.cs +++ b/CUETools.Processor/AudioReadWrite.cs @@ -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)); } } } \ No newline at end of file diff --git a/CUETools.Processor/CUEConfig.cs b/CUETools.Processor/CUEConfig.cs index 18c6543..34ad846 100644 --- a/CUETools.Processor/CUEConfig.cs +++ b/CUETools.Processor/CUEConfig.cs @@ -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))) diff --git a/CUETools.Processor/CUESheet.cs b/CUETools.Processor/CUESheet.cs index 15139a5..6abdebe 100644 --- a/CUETools.Processor/CUESheet.cs +++ b/CUETools.Processor/CUESheet.cs @@ -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); } diff --git a/CUETools.Ripper.Console/Program.cs b/CUETools.Ripper.Console/Program.cs index b701f44..8c4b821 100644 --- a/CUETools.Ripper.Console/Program.cs +++ b/CUETools.Ripper.Console/Program.cs @@ -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) { diff --git a/CUETools/CUETools.TestCodecs/ALACWriterTest.cs b/CUETools/CUETools.TestCodecs/ALACWriterTest.cs index ccd4f2c..c094ff6 100644 --- a/CUETools/CUETools.TestCodecs/ALACWriterTest.cs +++ b/CUETools/CUETools.TestCodecs/ALACWriterTest.cs @@ -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"); diff --git a/CUETools/CUETools.TestCodecs/CodecsTest.cs b/CUETools/CUETools.TestCodecs/CodecsTest.cs index 203cef3..a1dbf32 100644 --- a/CUETools/CUETools.TestCodecs/CodecsTest.cs +++ b/CUETools/CUETools.TestCodecs/CodecsTest.cs @@ -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(); diff --git a/CUETools/CUETools.TestCodecs/FlacWriterTest.cs b/CUETools/CUETools.TestCodecs/FlacWriterTest.cs index 6bf00bf..a0305c1 100644 --- a/CUETools/CUETools.TestCodecs/FlacWriterTest.cs +++ b/CUETools/CUETools.TestCodecs/FlacWriterTest.cs @@ -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"; diff --git a/CUETools/CUETools.TestCodecs/FlakeWriterTest.cs b/CUETools/CUETools.TestCodecs/FlakeWriterTest.cs index 7774c9a..ee3aab6 100644 --- a/CUETools/CUETools.TestCodecs/FlakeWriterTest.cs +++ b/CUETools/CUETools.TestCodecs/FlakeWriterTest.cs @@ -73,31 +73,31 @@ namespace CUETools.TestCodecs /// ///A test for FlakeWriter (string, int, int, int, Stream) /// - [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, diff --git a/CUETools/frmCUETools.Designer.cs b/CUETools/frmCUETools.Designer.cs index 7db1830..7bb66f0 100644 --- a/CUETools/frmCUETools.Designer.cs +++ b/CUETools/frmCUETools.Designer.cs @@ -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 diff --git a/CUETools/frmCUETools.cs b/CUETools/frmCUETools.cs index 18537c9..319f160 100644 --- a/CUETools/frmCUETools.cs +++ b/CUETools/frmCUETools.cs @@ -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) { diff --git a/CUETools/frmCUETools.resx b/CUETools/frmCUETools.resx index 91e533c..8384f2b 100644 --- a/CUETools/frmCUETools.resx +++ b/CUETools/frmCUETools.resx @@ -126,7 +126,7 @@ - 401, 24 + 503, 24 MiddleLeft @@ -465,6 +465,9 @@ 0, 0, 0, 0 + + 0, 16 + 49, 26 @@ -501,6 +504,9 @@ 0, 0, 0, 0 + + 0, 16 + 48, 26 @@ -654,6 +660,9 @@ 0, 0, 0, 0 + + 0, 16 + 47, 26 @@ -1128,6 +1137,9 @@ 11, 90 + + 16, 16 + 16, 16 @@ -2253,6 +2265,9 @@ Fill + + 32, 0 + toolStripContainer1.LeftToolStripPanel