Code cleanup; Reader classes renamed to Decoders, Writers to Encoders, every Decoder must have a corresponding Settings class now just like Encoders. UserDefinedEncoders renamed to CommandLineEncoders, etc.

This commit is contained in:
Grigory Chudov
2018-03-24 12:15:49 -04:00
parent ca8bb2fff6
commit e1f8906170
65 changed files with 1713 additions and 1798 deletions

View File

@@ -1000,8 +1000,8 @@ namespace CUERipper
private void resetEncoderModes(AudioEncoderSettingsViewModel encoder)
{
encoder.settings.PCM = AudioPCMConfig.RedBook;
buttonEncoderSettings.Enabled = encoder.settings.HasBrowsableAttributes();
encoder.Settings.PCM = AudioPCMConfig.RedBook;
buttonEncoderSettings.Enabled = encoder.Settings.HasBrowsableAttributes();
string[] modes = encoder.SupportedModes;
if (modes == null || modes.Length < 2)
{
@@ -1015,12 +1015,12 @@ namespace CUERipper
if (encoder.EncoderModeIndex == -1)
{
string defaultMode;
encoder.settings.GetSupportedModes(out defaultMode);
encoder.settings.EncoderMode = defaultMode;
encoder.Settings.GetSupportedModes(out defaultMode);
encoder.Settings.EncoderMode = defaultMode;
}
trackBarEncoderMode.Maximum = modes.Length - 1;
trackBarEncoderMode.Value = encoder.EncoderModeIndex == -1 ? modes.Length - 1 : encoder.EncoderModeIndex;
labelEncoderMode.Text = encoder.settings.EncoderMode;
labelEncoderMode.Text = encoder.Settings.EncoderMode;
labelEncoderMinMode.Text = modes[0];
labelEncoderMaxMode.Text = modes[modes.Length - 1];
trackBarEncoderMode.Visible = true;
@@ -1048,8 +1048,8 @@ namespace CUERipper
{
var encoder = bnComboBoxEncoder.SelectedItem as AudioEncoderSettingsViewModel;
string[] modes = encoder.SupportedModes;
encoder.settings.EncoderMode = modes[trackBarEncoderMode.Value];
labelEncoderMode.Text = encoder.settings.EncoderMode;
encoder.Settings.EncoderMode = modes[trackBarEncoderMode.Value];
labelEncoderMode.Text = encoder.Settings.EncoderMode;
}
private void trackBarSecureMode_Scroll(object sender, EventArgs e)
@@ -1129,7 +1129,7 @@ namespace CUERipper
data.Encoders.RaiseListChangedEvents = false;
foreach (var encoder in _config.encoders)
foreach (var encoder in _config.Encoders)
if (encoder.Extension == SelectedOutputAudioFmt.extension)
{
if (SelectedOutputAudioType == AudioEncoderType.Lossless && !encoder.Lossless)
@@ -1572,7 +1572,7 @@ namespace CUERipper
var encoder = bnComboBoxEncoder.SelectedItem as AudioEncoderSettingsViewModel;
if (encoder == null)
return;
var form = new Options(encoder.settings);
var form = new Options(encoder.Settings);
form.propertyGrid1.HelpVisible = true;
form.ShowDialog(this);
resetEncoderModes(encoder);

View File

@@ -40,7 +40,6 @@ namespace CUETools.Codecs.ALAC
public DecoderSettings() : base() { }
}
[AudioDecoderClass(typeof(DecoderSettings))]
public class AudioDecoder : IAudioSource
{
public AudioDecoder(DecoderSettings settings, string path, Stream IO = null)

View File

@@ -67,7 +67,6 @@ namespace CUETools.Codecs.ALAC
public bool DoVerify { get; set; }
}
[AudioEncoderClass(typeof(EncoderSettings))]
public class AudioEncoder : IAudioDest
{
Stream _IO = null;

View File

@@ -5,20 +5,6 @@ using System.IO;
namespace CUETools.Codecs.BDLPCM
{
public class DecoderSettings : AudioDecoderSettings
{
public override string Extension => "m2ts";
public override string Name => "cuetools";
public override Type DecoderType => typeof(AudioDecoder);
public override int Priority => 2;
public DecoderSettings() : base() { }
}
[AudioDecoderClass(typeof(DecoderSettings))]
public class AudioDecoder : IAudioSource
{
public unsafe AudioDecoder(string path, Stream IO, ushort pid)
@@ -37,7 +23,7 @@ namespace CUETools.Codecs.BDLPCM
_samplePos = 0;
_sampleLen = -1;
demux_ts_packets(null, 0);
settings = new BDLPCMDecoderSettings();
settings = new DecoderSettings();
}
public AudioDecoderSettings Settings { get { return settings; } }
@@ -749,6 +735,6 @@ namespace CUETools.Codecs.BDLPCM
int demuxer_channel;
TsStream chosenStream;
long _samplePos, _sampleLen;
BDLPCMDecoderSettings settings;
DecoderSettings settings;
}
}

View File

@@ -7,17 +7,25 @@ using Newtonsoft.Json;
namespace CUETools.Codecs.BDLPCM
{
[JsonObject(MemberSerialization.OptIn)]
public class BDLPCMDecoderSettings : AudioDecoderSettings
public class DecoderSettings : AudioDecoderSettings
{
public BDLPCMDecoderSettings()
{
IgnoreShortItems = true;
}
public override string Extension => "m2ts";
public override string Name => "cuetools";
public override Type DecoderType => typeof(AudioDecoder);
public override int Priority => 2;
public bool IgnoreShortItems { get; set; }
public int? Stream { get; set; }
public ushort? Pid { get; set; }
public DecoderSettings() : base()
{
IgnoreShortItems = true;
}
}
}

View File

@@ -6,20 +6,6 @@ using System.Globalization;
namespace CUETools.Codecs.BDLPCM
{
public class MPLSDecoderSettings : AudioDecoderSettings
{
public override string Extension => "mpls";
public override string Name => "cuetools";
public override Type DecoderType => typeof(MPLSDecoder);
public override int Priority => 2;
public MPLSDecoderSettings() : base() { }
}
[AudioDecoderClass(typeof(MPLSDecoderSettings))]
public class MPLSDecoder : IAudioSource
{
public unsafe MPLSDecoder(string path, Stream IO, ushort pid)
@@ -30,7 +16,7 @@ namespace CUETools.Codecs.BDLPCM
public unsafe MPLSDecoder(string path, Stream IO)
{
settings = new BDLPCMDecoderSettings();
settings = new DecoderSettings();
_path = path;
_IO = IO != null ? IO : new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, 0x10000);
int length = (int)_IO.Length;
@@ -453,7 +439,7 @@ namespace CUETools.Codecs.BDLPCM
List<AudioDecoder> readers;
AudioDecoder currentReader;
MPLSHeader hdr_m;
BDLPCMDecoderSettings settings;
DecoderSettings settings;
}
public struct MPLSPlaylistMark

View File

@@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using Newtonsoft.Json;
namespace CUETools.Codecs.MPLS
{
[JsonObject(MemberSerialization.OptIn)]
public class DecoderSettings : AudioDecoderSettings
{
public override string Extension => "mpls";
public override string Name => "cuetools";
public override Type DecoderType => typeof(BDLPCM.MPLSDecoder);
public override int Priority => 2;
public bool IgnoreShortItems { get; set; }
public int? Stream { get; set; }
public ushort? Pid { get; set; }
public DecoderSettings() : base()
{
IgnoreShortItems = true;
}
}
}

View File

@@ -279,7 +279,6 @@ namespace CUETools.Codecs.FLACCL
GPU = DeviceType.GPU
}
[AudioEncoderClass(typeof(EncoderSettings))]
public class AudioEncoder : IAudioDest
{
Stream _IO = null;

View File

@@ -39,7 +39,6 @@ namespace CUETools.Codecs.FLAKE
public DecoderSettings() : base() { }
}
[AudioDecoderClass(typeof(DecoderSettings))]
public class AudioDecoder: IAudioSource
{
int[] samplesBuffer;

View File

@@ -272,8 +272,6 @@ namespace CUETools.Codecs.FLAKE
public string[] Tags { get; set; }
}
[AudioEncoderClass(typeof(EncoderSettings))]
//[AudioEncoderClass("libFlake nonsub", "flac", true, "9 10 11", "9", 3, typeof(FlakeWriterSettings))]
public class AudioEncoder : IAudioDest
{
Stream _IO = null;

View File

@@ -12,7 +12,7 @@ namespace CUETools.Codecs.Icecast
{
private long _sampleOffset = 0;
private AudioEncoderSettings m_settings;
private LAME.LAMEEncoderCBR encoder = null;
private LAME.AudioEncoder encoder = null;
private HttpWebRequest req = null;
private HttpWebResponse resp = null;
private Stream reqStream;
@@ -80,12 +80,12 @@ namespace CUETools.Codecs.Icecast
resp = req.GetResponse() as HttpWebResponse;
if (resp.StatusCode == HttpStatusCode.OK)
{
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);
var encoderSettings = new CUETools.Codecs.LAME.CBREncoderSettings() { 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.AudioEncoder(encoderSettings, "", reqStream);
}
}
catch (WebException ex)

View File

@@ -40,7 +40,6 @@ namespace CUETools.Codecs.WMA
public DecoderSettings() : base() { }
}
[AudioDecoderClass(typeof(DecoderSettings))]
public class AudioDecoder : IAudioSource
{
IWMSyncReader m_syncReader;

View File

@@ -276,8 +276,6 @@ namespace CUETools.Codecs.WMA
}
}
[AudioEncoderClass(typeof(LosslessEncoderSettings))]
[AudioEncoderClass(typeof(LossyEncoderSettings))]
public class AudioEncoder : IAudioDest
{
IWMWriter m_pEncoder;

View File

@@ -1,29 +1,29 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net40;net20;netstandard2.0</TargetFrameworks>
<Version>2.1.7.0</Version>
<AssemblyName>CUETools.Codecs.LAME</AssemblyName>
<RootNamespace>CUETools.Codecs.LAME</RootNamespace>
<Product>CUETools</Product>
<Description>A library for encoding mp3 using LAME encoder.</Description>
<Copyright>Copyright (c) 2008-2018 Grigory Chudov</Copyright>
<Authors>Grigory Chudov</Authors>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<OutputPath>..\bin\$(Configuration)\plugins\win32</OutputPath>
<RepositoryUrl>https://github.com/gchudov/cuetools.net</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<Company />
</PropertyGroup>
<ItemDefinitionGroup>
<ProjectReference>
<Private>False</Private>
</ProjectReference>
</ItemDefinitionGroup>
<ItemGroup>
<ProjectReference Include="..\CUETools.Codecs\CUETools.Codecs.csproj" />
</ItemGroup>
</Project>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net40;net20;netstandard2.0</TargetFrameworks>
<Version>2.1.7.0</Version>
<AssemblyName>CUETools.Codecs.lame_enc</AssemblyName>
<RootNamespace>CUETools.Codecs.lame_enc</RootNamespace>
<Product>CUETools</Product>
<Description>A library for encoding mp3 using LAME encoder.</Description>
<Copyright>Copyright (c) 2008-2018 Grigory Chudov</Copyright>
<Authors>Grigory Chudov</Authors>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<OutputPath>..\bin\$(Configuration)\plugins\win32</OutputPath>
<RepositoryUrl>https://github.com/gchudov/cuetools.net</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<Company />
</PropertyGroup>
<ItemDefinitionGroup>
<ProjectReference>
<Private>False</Private>
</ProjectReference>
</ItemDefinitionGroup>
<ItemGroup>
<ProjectReference Include="..\CUETools.Codecs\CUETools.Codecs.csproj" />
</ItemGroup>
</Project>

View File

@@ -1,14 +1,14 @@
using System;
using System.Runtime.InteropServices;
namespace CUETools.Codecs.LAME.Interop
{
[StructLayout(LayoutKind.Sequential), Serializable]
public struct ACC
{
public uint dwSampleRate;
public byte byMode;
public ushort wBitrate;
public byte byEncodingMethod;
}
}
using System;
using System.Runtime.InteropServices;
namespace CUETools.Codecs.LAME.Interop
{
[StructLayout(LayoutKind.Sequential), Serializable]
public struct ACC
{
public uint dwSampleRate;
public byte byMode;
public ushort wBitrate;
public byte byEncodingMethod;
}
}

View File

@@ -1,27 +1,27 @@
using System;
using System.Runtime.InteropServices;
namespace CUETools.Codecs.LAME.Interop
{
[StructLayout(LayoutKind.Sequential), Serializable]
public class BE_CONFIG
{
// encoding formats
public const uint BE_CONFIG_MP3 = 0;
public const uint BE_CONFIG_LAME = 256;
public uint dwConfig;
public Format format;
public BE_CONFIG(AudioPCMConfig format, uint MpeBitRate, uint quality)
{
this.dwConfig = BE_CONFIG_LAME;
this.format = new Format(format, MpeBitRate, quality);
}
public BE_CONFIG(AudioPCMConfig format)
: this(format, 0, 5)
{
}
}
}
using System;
using System.Runtime.InteropServices;
namespace CUETools.Codecs.LAME.Interop
{
[StructLayout(LayoutKind.Sequential), Serializable]
public class BE_CONFIG
{
// encoding formats
public const uint BE_CONFIG_MP3 = 0;
public const uint BE_CONFIG_LAME = 256;
public uint dwConfig;
public Format format;
public BE_CONFIG(AudioPCMConfig format, uint MpeBitRate, uint quality)
{
this.dwConfig = BE_CONFIG_LAME;
this.format = new Format(format, MpeBitRate, quality);
}
public BE_CONFIG(AudioPCMConfig format)
: this(format, 0, 5)
{
}
}
}

View File

@@ -1,34 +1,34 @@
using System.Runtime.InteropServices;
namespace CUETools.Codecs.LAME.Interop
{
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public class BE_VERSION
{
public const uint BE_MAX_HOMEPAGE = 256;
public byte byDLLMajorVersion;
public byte byDLLMinorVersion;
public byte byMajorVersion;
public byte byMinorVersion;
// DLL Release date
public byte byDay;
public byte byMonth;
public ushort wYear;
//Homepage URL
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 257/*BE_MAX_HOMEPAGE+1*/)]
public string zHomepage;
public byte byAlphaLevel;
public byte byBetaLevel;
public byte byMMXEnabled;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 125)]
public byte[] btReserved;
public BE_VERSION()
{
btReserved = new byte[125];
}
}
}
using System.Runtime.InteropServices;
namespace CUETools.Codecs.LAME.Interop
{
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public class BE_VERSION
{
public const uint BE_MAX_HOMEPAGE = 256;
public byte byDLLMajorVersion;
public byte byDLLMinorVersion;
public byte byMajorVersion;
public byte byMinorVersion;
// DLL Release date
public byte byDay;
public byte byMonth;
public ushort wYear;
//Homepage URL
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 257/*BE_MAX_HOMEPAGE+1*/)]
public string zHomepage;
public byte byAlphaLevel;
public byte byBetaLevel;
public byte byMMXEnabled;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 125)]
public byte[] btReserved;
public BE_VERSION()
{
btReserved = new byte[125];
}
}
}

View File

@@ -1,21 +1,21 @@
using System;
using System.Runtime.InteropServices;
namespace CUETools.Codecs.LAME.Interop
{
[StructLayout(LayoutKind.Explicit), Serializable]
public class Format
{
[FieldOffset(0)]
public MP3 mp3;
[FieldOffset(0)]
public LHV1 lhv1;
[FieldOffset(0)]
public ACC acc;
public Format(AudioPCMConfig format, uint MpeBitRate, uint quality)
{
lhv1 = new LHV1(format, MpeBitRate, quality);
}
}
}
using System;
using System.Runtime.InteropServices;
namespace CUETools.Codecs.LAME.Interop
{
[StructLayout(LayoutKind.Explicit), Serializable]
public class Format
{
[FieldOffset(0)]
public MP3 mp3;
[FieldOffset(0)]
public LHV1 lhv1;
[FieldOffset(0)]
public ACC acc;
public Format(AudioPCMConfig format, uint MpeBitRate, uint quality)
{
lhv1 = new LHV1(format, MpeBitRate, quality);
}
}
}

View File

@@ -1,34 +1,34 @@
namespace CUETools.Codecs.LAME.Interop
{
public enum LAME_QUALITY_PRESET : int
{
LQP_NOPRESET = -1,
// QUALITY PRESETS
LQP_NORMAL_QUALITY = 0,
LQP_LOW_QUALITY = 1,
LQP_HIGH_QUALITY = 2,
LQP_VOICE_QUALITY = 3,
LQP_R3MIX = 4,
LQP_VERYHIGH_QUALITY = 5,
LQP_STANDARD = 6,
LQP_FAST_STANDARD = 7,
LQP_EXTREME = 8,
LQP_FAST_EXTREME = 9,
LQP_INSANE = 10,
LQP_ABR = 11,
LQP_CBR = 12,
LQP_MEDIUM = 13,
LQP_FAST_MEDIUM = 14,
// NEW PRESET VALUES
LQP_PHONE = 1000,
LQP_SW = 2000,
LQP_AM = 3000,
LQP_FM = 4000,
LQP_VOICE = 5000,
LQP_RADIO = 6000,
LQP_TAPE = 7000,
LQP_HIFI = 8000,
LQP_CD = 9000,
LQP_STUDIO = 10000
}
}
namespace CUETools.Codecs.LAME.Interop
{
public enum LAME_QUALITY_PRESET : int
{
LQP_NOPRESET = -1,
// QUALITY PRESETS
LQP_NORMAL_QUALITY = 0,
LQP_LOW_QUALITY = 1,
LQP_HIGH_QUALITY = 2,
LQP_VOICE_QUALITY = 3,
LQP_R3MIX = 4,
LQP_VERYHIGH_QUALITY = 5,
LQP_STANDARD = 6,
LQP_FAST_STANDARD = 7,
LQP_EXTREME = 8,
LQP_FAST_EXTREME = 9,
LQP_INSANE = 10,
LQP_ABR = 11,
LQP_CBR = 12,
LQP_MEDIUM = 13,
LQP_FAST_MEDIUM = 14,
// NEW PRESET VALUES
LQP_PHONE = 1000,
LQP_SW = 2000,
LQP_AM = 3000,
LQP_FM = 4000,
LQP_VOICE = 5000,
LQP_RADIO = 6000,
LQP_TAPE = 7000,
LQP_HIFI = 8000,
LQP_CD = 9000,
LQP_STUDIO = 10000
}
}

View File

@@ -1,130 +1,130 @@
using System;
using System.Runtime.InteropServices;
namespace CUETools.Codecs.LAME.Interop
{
[StructLayout(LayoutKind.Sequential, Size = 327), Serializable]
public struct LHV1 // BE_CONFIG_LAME LAME header version 1
{
public const uint MPEG1 = 1;
public const uint MPEG2 = 0;
// STRUCTURE INFORMATION
public uint dwStructVersion;
public uint dwStructSize;
// BASIC ENCODER SETTINGS
public uint dwSampleRate; // SAMPLERATE OF INPUT FILE
public uint dwReSampleRate; // DOWNSAMPLERATE, 0=ENCODER DECIDES
public MpegMode nMode; // STEREO, MONO
public uint dwBitrate; // CBR bitrate, VBR min bitrate
public uint dwMaxBitrate; // CBR ignored, VBR Max bitrate
public LAME_QUALITY_PRESET nPreset; // Quality preset
public uint dwMpegVersion; // MPEG-1 OR MPEG-2
public uint dwPsyModel; // FUTURE USE, SET TO 0
public uint dwEmphasis; // FUTURE USE, SET TO 0
// BIT STREAM SETTINGS
public int bPrivate; // Set Private Bit (TRUE/FALSE)
public int bCRC; // Insert CRC (TRUE/FALSE)
public int bCopyright; // Set Copyright Bit (TRUE/FALSE)
public int bOriginal; // Set Original Bit (TRUE/FALSE)
// VBR STUFF
public int bWriteVBRHeader; // WRITE XING VBR HEADER (TRUE/FALSE)
public int bEnableVBR; // USE VBR ENCODING (TRUE/FALSE)
public int nVBRQuality; // VBR QUALITY 0..9
public uint dwVbrAbr_bps; // Use ABR in stead of nVBRQuality
public VBRMETHOD nVbrMethod;
public int bNoRes; // Disable Bit resorvoir (TRUE/FALSE)
// MISC SETTINGS
public int bStrictIso; // Use strict ISO encoding rules (TRUE/FALSE)
public ushort nQuality; // Quality Setting, HIGH BYTE should be NOT LOW byte, otherwhise quality=5
// FUTURE USE, SET TO 0, align strucutre to 331 bytes
//[ MarshalAs( UnmanagedType.ByValArray, SizeConst=255-4*4-2 )]
//public byte[] btReserved;//[255-4*sizeof(DWORD) - sizeof( WORD )];
public LHV1(AudioPCMConfig format, uint MpeBitRate, uint quality)
{
dwStructVersion = 1;
dwStructSize = (uint)Marshal.SizeOf(typeof(BE_CONFIG));
switch (format.SampleRate)
{
case 16000:
case 22050:
case 24000:
dwMpegVersion = MPEG2;
break;
case 32000:
case 44100:
case 48000:
dwMpegVersion = MPEG1;
break;
default:
throw new ArgumentOutOfRangeException("format", "Unsupported sample rate");
}
dwSampleRate = (uint)format.SampleRate; // INPUT FREQUENCY
dwReSampleRate = 0; // DON'T RESAMPLE
switch (format.ChannelCount)
{
case 1:
nMode = MpegMode.MONO;
break;
case 2:
nMode = MpegMode.STEREO;
break;
default:
throw new ArgumentOutOfRangeException("format", "Invalid number of channels");
}
switch (MpeBitRate)
{
case 0:
case 32:
case 40:
case 48:
case 56:
case 64:
case 80:
case 96:
case 112:
case 128:
case 160: //Allowed bit rates in MPEG1 and MPEG2
break;
case 192:
case 224:
case 256:
case 320: //Allowed only in MPEG1
if (dwMpegVersion != MPEG1)
{
throw new ArgumentOutOfRangeException("MpsBitRate", "Bit rate not compatible with input format");
}
break;
case 8:
case 16:
case 24:
case 144: //Allowed only in MPEG2
if (dwMpegVersion != MPEG2)
{
throw new ArgumentOutOfRangeException("MpsBitRate", "Bit rate not compatible with input format");
}
break;
default:
throw new ArgumentOutOfRangeException("MpsBitRate", "Unsupported bit rate");
}
dwBitrate = MpeBitRate; // MINIMUM BIT RATE
nPreset = LAME_QUALITY_PRESET.LQP_NORMAL_QUALITY; // QUALITY PRESET SETTING
dwPsyModel = 0; // USE DEFAULT PSYCHOACOUSTIC MODEL
dwEmphasis = 0; // NO EMPHASIS TURNED ON
bOriginal = 1; // SET ORIGINAL FLAG
bWriteVBRHeader = 0;
bNoRes = 0; // No Bit resorvoir
bCopyright = 0;
bCRC = 0;
bEnableVBR = 0;
bPrivate = 0;
bStrictIso = 0;
dwMaxBitrate = 0;
dwVbrAbr_bps = 0;
nQuality = (ushort)(quality | ((~quality) << 8));
nVbrMethod = VBRMETHOD.VBR_METHOD_NONE;
nVBRQuality = 0;
}
}
}
using System;
using System.Runtime.InteropServices;
namespace CUETools.Codecs.LAME.Interop
{
[StructLayout(LayoutKind.Sequential, Size = 327), Serializable]
public struct LHV1 // BE_CONFIG_LAME LAME header version 1
{
public const uint MPEG1 = 1;
public const uint MPEG2 = 0;
// STRUCTURE INFORMATION
public uint dwStructVersion;
public uint dwStructSize;
// BASIC ENCODER SETTINGS
public uint dwSampleRate; // SAMPLERATE OF INPUT FILE
public uint dwReSampleRate; // DOWNSAMPLERATE, 0=ENCODER DECIDES
public MpegMode nMode; // STEREO, MONO
public uint dwBitrate; // CBR bitrate, VBR min bitrate
public uint dwMaxBitrate; // CBR ignored, VBR Max bitrate
public LAME_QUALITY_PRESET nPreset; // Quality preset
public uint dwMpegVersion; // MPEG-1 OR MPEG-2
public uint dwPsyModel; // FUTURE USE, SET TO 0
public uint dwEmphasis; // FUTURE USE, SET TO 0
// BIT STREAM SETTINGS
public int bPrivate; // Set Private Bit (TRUE/FALSE)
public int bCRC; // Insert CRC (TRUE/FALSE)
public int bCopyright; // Set Copyright Bit (TRUE/FALSE)
public int bOriginal; // Set Original Bit (TRUE/FALSE)
// VBR STUFF
public int bWriteVBRHeader; // WRITE XING VBR HEADER (TRUE/FALSE)
public int bEnableVBR; // USE VBR ENCODING (TRUE/FALSE)
public int nVBRQuality; // VBR QUALITY 0..9
public uint dwVbrAbr_bps; // Use ABR in stead of nVBRQuality
public VBRMETHOD nVbrMethod;
public int bNoRes; // Disable Bit resorvoir (TRUE/FALSE)
// MISC SETTINGS
public int bStrictIso; // Use strict ISO encoding rules (TRUE/FALSE)
public ushort nQuality; // Quality Setting, HIGH BYTE should be NOT LOW byte, otherwhise quality=5
// FUTURE USE, SET TO 0, align strucutre to 331 bytes
//[ MarshalAs( UnmanagedType.ByValArray, SizeConst=255-4*4-2 )]
//public byte[] btReserved;//[255-4*sizeof(DWORD) - sizeof( WORD )];
public LHV1(AudioPCMConfig format, uint MpeBitRate, uint quality)
{
dwStructVersion = 1;
dwStructSize = (uint)Marshal.SizeOf(typeof(BE_CONFIG));
switch (format.SampleRate)
{
case 16000:
case 22050:
case 24000:
dwMpegVersion = MPEG2;
break;
case 32000:
case 44100:
case 48000:
dwMpegVersion = MPEG1;
break;
default:
throw new ArgumentOutOfRangeException("format", "Unsupported sample rate");
}
dwSampleRate = (uint)format.SampleRate; // INPUT FREQUENCY
dwReSampleRate = 0; // DON'T RESAMPLE
switch (format.ChannelCount)
{
case 1:
nMode = MpegMode.MONO;
break;
case 2:
nMode = MpegMode.STEREO;
break;
default:
throw new ArgumentOutOfRangeException("format", "Invalid number of channels");
}
switch (MpeBitRate)
{
case 0:
case 32:
case 40:
case 48:
case 56:
case 64:
case 80:
case 96:
case 112:
case 128:
case 160: //Allowed bit rates in MPEG1 and MPEG2
break;
case 192:
case 224:
case 256:
case 320: //Allowed only in MPEG1
if (dwMpegVersion != MPEG1)
{
throw new ArgumentOutOfRangeException("MpsBitRate", "Bit rate not compatible with input format");
}
break;
case 8:
case 16:
case 24:
case 144: //Allowed only in MPEG2
if (dwMpegVersion != MPEG2)
{
throw new ArgumentOutOfRangeException("MpsBitRate", "Bit rate not compatible with input format");
}
break;
default:
throw new ArgumentOutOfRangeException("MpsBitRate", "Unsupported bit rate");
}
dwBitrate = MpeBitRate; // MINIMUM BIT RATE
nPreset = LAME_QUALITY_PRESET.LQP_NORMAL_QUALITY; // QUALITY PRESET SETTING
dwPsyModel = 0; // USE DEFAULT PSYCHOACOUSTIC MODEL
dwEmphasis = 0; // NO EMPHASIS TURNED ON
bOriginal = 1; // SET ORIGINAL FLAG
bWriteVBRHeader = 0;
bNoRes = 0; // No Bit resorvoir
bCopyright = 0;
bCRC = 0;
bEnableVBR = 0;
bPrivate = 0;
bStrictIso = 0;
dwMaxBitrate = 0;
dwVbrAbr_bps = 0;
nQuality = (ushort)(quality | ((~quality) << 8));
nVbrMethod = VBRMETHOD.VBR_METHOD_NONE;
nVBRQuality = 0;
}
}
}

View File

@@ -1,161 +1,161 @@
using System;
using System.Runtime.InteropServices;
namespace CUETools.Codecs.LAME.Interop
{
/// <summary>
/// Lame_enc DLL functions
/// </summary>
public class Lame_encDll
{
//Error codes
public const uint BE_ERR_SUCCESSFUL = 0;
public const uint BE_ERR_INVALID_FORMAT = 1;
public const uint BE_ERR_INVALID_FORMAT_PARAMETERS = 2;
public const uint BE_ERR_NO_MORE_HANDLES = 3;
public const uint BE_ERR_INVALID_HANDLE = 4;
/// <summary>
/// This function is the first to call before starting an encoding stream.
/// </summary>
/// <param name="pbeConfig">Encoder settings</param>
/// <param name="dwSamples">Receives the number of samples (not bytes, each sample is a SHORT) to send to each beEncodeChunk() on return.</param>
/// <param name="dwBufferSize">Receives the minimun number of bytes that must have the output(result) buffer</param>
/// <param name="phbeStream">Receives the stream handle on return</param>
/// <returns>On success: BE_ERR_SUCCESSFUL</returns>
[DllImport("Lame_enc.dll")]
public static extern uint beInitStream(BE_CONFIG pbeConfig, ref uint dwSamples, ref uint dwBufferSize, ref uint phbeStream);
/// <summary>
/// Encodes a chunk of samples. Please note that if you have set the output to
/// generate mono MP3 files you must feed beEncodeChunk() with mono samples
/// </summary>
/// <param name="hbeStream">Handle of the stream.</param>
/// <param name="nSamples">Number of samples to be encoded for this call.
/// This should be identical to what is returned by beInitStream(),
/// unless you are encoding the last chunk, which might be smaller.</param>
/// <param name="pInSamples">Array of 16-bit signed samples to be encoded.
/// These should be in stereo when encoding a stereo MP3
/// and mono when encoding a mono MP3</param>
/// <param name="pOutput">Buffer where to write the encoded data.
/// This buffer should be at least of the minimum size returned by beInitStream().</param>
/// <param name="pdwOutput">Returns the number of bytes of encoded data written.
/// The amount of data written might vary from chunk to chunk</param>
/// <returns>On success: BE_ERR_SUCCESSFUL</returns>
[DllImport("Lame_enc.dll")]
public static extern uint beEncodeChunk(uint hbeStream, uint nSamples, short[] pInSamples, [In, Out] byte[] pOutput, ref uint pdwOutput);
/// <summary>
/// Encodes a chunk of samples. Please note that if you have set the output to
/// generate mono MP3 files you must feed beEncodeChunk() with mono samples
/// </summary>
/// <param name="hbeStream">Handle of the stream.</param>
/// <param name="nSamples">Number of samples to be encoded for this call.
/// This should be identical to what is returned by beInitStream(),
/// unless you are encoding the last chunk, which might be smaller.</param>
/// <param name="pSamples">Pointer at the 16-bit signed samples to be encoded.
/// InPtr is used to pass any type of array without need of make memory copy,
/// then gaining in performance. Note that nSamples is not the number of bytes,
/// but samples (is sample is a SHORT)</param>
/// <param name="pOutput">Buffer where to write the encoded data.
/// This buffer should be at least of the minimum size returned by beInitStream().</param>
/// <param name="pdwOutput">Returns the number of bytes of encoded data written.
/// The amount of data written might vary from chunk to chunk</param>
/// <returns>On success: BE_ERR_SUCCESSFUL</returns>
[DllImport("Lame_enc.dll")]
protected static extern uint beEncodeChunk(uint hbeStream, uint nSamples, IntPtr pSamples, IntPtr pOutput, ref uint pdwOutput);
/// <summary>
/// Encodes a chunk of samples. Samples are contained in a byte array
/// </summary>
/// <param name="hbeStream">Handle of the stream.</param>
/// <param name="buffer">Bytes to encode</param>
/// <param name="index">Position of the first byte to encode</param>
/// <param name="nBytes">Number of bytes to encode (not samples, samples are two byte lenght)</param>
/// <param name="pOutput">Buffer where to write the encoded data.
/// This buffer should be at least of the minimum size returned by beInitStream().</param>
/// <param name="pdwOutput">Returns the number of bytes of encoded data written.
/// The amount of data written might vary from chunk to chunk</param>
/// <returns>On success: BE_ERR_SUCCESSFUL</returns>
public static unsafe uint EncodeChunk(uint hbeStream, byte* pSamples, uint nBytes, byte* pOutput, ref uint pdwOutput)
{
return beEncodeChunk(hbeStream, nBytes / 2/*Samples*/, (IntPtr)pSamples, (IntPtr)pOutput, ref pdwOutput);
}
/// <summary>
/// Encodes a chunk of samples. Samples are contained in a byte array
/// </summary>
/// <param name="hbeStream">Handle of the stream.</param>
/// <param name="buffer">Bytes to encode</param>
/// <param name="index">Position of the first byte to encode</param>
/// <param name="nBytes">Number of bytes to encode (not samples, samples are two byte lenght)</param>
/// <param name="pOutput">Buffer where to write the encoded data.
/// This buffer should be at least of the minimum size returned by beInitStream().</param>
/// <param name="pdwOutput">Returns the number of bytes of encoded data written.
/// The amount of data written might vary from chunk to chunk</param>
/// <returns>On success: BE_ERR_SUCCESSFUL</returns>
public static unsafe uint EncodeChunk(uint hbeStream, byte[] Samples, int index, uint nBytes, byte[] Output, ref uint pdwOutput)
{
fixed (byte* pSamples = &Samples[index], pOutput = Output)
return beEncodeChunk(hbeStream, nBytes / 2/*Samples*/, (IntPtr)pSamples, (IntPtr)pOutput, ref pdwOutput);
}
/// <summary>
/// Encodes a chunk of samples. Samples are contained in a byte array
/// </summary>
/// <param name="hbeStream">Handle of the stream.</param>
/// <param name="buffer">Bytes to encode</param>
/// <param name="pOutput">Buffer where to write the encoded data.
/// This buffer should be at least of the minimum size returned by beInitStream().</param>
/// <param name="pdwOutput">Returns the number of bytes of encoded data written.
/// The amount of data written might vary from chunk to chunk</param>
/// <returns>On success: BE_ERR_SUCCESSFUL</returns>
public static uint EncodeChunk(uint hbeStream, byte[] buffer, byte[] pOutput, ref uint pdwOutput)
{
return EncodeChunk(hbeStream, buffer, 0, (uint)buffer.Length, pOutput, ref pdwOutput);
}
/// <summary>
/// This function should be called after encoding the last chunk in order to flush
/// the encoder. It writes any encoded data that still might be left inside the
/// encoder to the output buffer. This function should NOT be called unless
/// you have encoded all of the chunks in your stream.
/// </summary>
/// <param name="hbeStream">Handle of the stream.</param>
/// <param name="pOutput">Where to write the encoded data. This buffer should be
/// at least of the minimum size returned by beInitStream().</param>
/// <param name="pdwOutput">Returns number of bytes of encoded data written.</param>
/// <returns>On success: BE_ERR_SUCCESSFUL</returns>
[DllImport("Lame_enc.dll")]
public static extern uint beDeinitStream(uint hbeStream, [In, Out] byte[] pOutput, ref uint pdwOutput);
/// <summary>
/// Last function to be called when finished encoding a stream.
/// Should unlike beDeinitStream() also be called if the encoding is canceled.
/// </summary>
/// <param name="hbeStream">Handle of the stream.</param>
/// <returns>On success: BE_ERR_SUCCESSFUL</returns>
[DllImport("Lame_enc.dll")]
public static extern uint beCloseStream(uint hbeStream);
/// <summary>
/// Returns information like version numbers (both of the DLL and encoding engine),
/// release date and URL for lame_enc's homepage.
/// All this information should be made available to the user of your product
/// through a dialog box or something similar.
/// </summary>
/// <param name="pbeVersion"Where version number, release date and URL for homepage
/// is returned.</param>
[DllImport("Lame_enc.dll")]
public static extern void beVersion([Out] BE_VERSION pbeVersion);
[DllImport("Lame_enc.dll", CharSet = CharSet.Ansi)]
public static extern void beWriteVBRHeader(string pszMP3FileName);
[DllImport("Lame_enc.dll")]
public static extern uint beEncodeChunkFloatS16NI(uint hbeStream, uint nSamples, [In]float[] buffer_l, [In]float[] buffer_r, [In, Out]byte[] pOutput, ref uint pdwOutput);
[DllImport("Lame_enc.dll")]
public static extern uint beFlushNoGap(uint hbeStream, [In, Out]byte[] pOutput, ref uint pdwOutput);
[DllImport("Lame_enc.dll", CharSet = CharSet.Ansi)]
public static extern uint beWriteInfoTag(uint hbeStream, string lpszFileName);
}
}
using System;
using System.Runtime.InteropServices;
namespace CUETools.Codecs.LAME.Interop
{
/// <summary>
/// Lame_enc DLL functions
/// </summary>
public class Lame_encDll
{
//Error codes
public const uint BE_ERR_SUCCESSFUL = 0;
public const uint BE_ERR_INVALID_FORMAT = 1;
public const uint BE_ERR_INVALID_FORMAT_PARAMETERS = 2;
public const uint BE_ERR_NO_MORE_HANDLES = 3;
public const uint BE_ERR_INVALID_HANDLE = 4;
/// <summary>
/// This function is the first to call before starting an encoding stream.
/// </summary>
/// <param name="pbeConfig">Encoder settings</param>
/// <param name="dwSamples">Receives the number of samples (not bytes, each sample is a SHORT) to send to each beEncodeChunk() on return.</param>
/// <param name="dwBufferSize">Receives the minimun number of bytes that must have the output(result) buffer</param>
/// <param name="phbeStream">Receives the stream handle on return</param>
/// <returns>On success: BE_ERR_SUCCESSFUL</returns>
[DllImport("Lame_enc.dll")]
public static extern uint beInitStream(BE_CONFIG pbeConfig, ref uint dwSamples, ref uint dwBufferSize, ref uint phbeStream);
/// <summary>
/// Encodes a chunk of samples. Please note that if you have set the output to
/// generate mono MP3 files you must feed beEncodeChunk() with mono samples
/// </summary>
/// <param name="hbeStream">Handle of the stream.</param>
/// <param name="nSamples">Number of samples to be encoded for this call.
/// This should be identical to what is returned by beInitStream(),
/// unless you are encoding the last chunk, which might be smaller.</param>
/// <param name="pInSamples">Array of 16-bit signed samples to be encoded.
/// These should be in stereo when encoding a stereo MP3
/// and mono when encoding a mono MP3</param>
/// <param name="pOutput">Buffer where to write the encoded data.
/// This buffer should be at least of the minimum size returned by beInitStream().</param>
/// <param name="pdwOutput">Returns the number of bytes of encoded data written.
/// The amount of data written might vary from chunk to chunk</param>
/// <returns>On success: BE_ERR_SUCCESSFUL</returns>
[DllImport("Lame_enc.dll")]
public static extern uint beEncodeChunk(uint hbeStream, uint nSamples, short[] pInSamples, [In, Out] byte[] pOutput, ref uint pdwOutput);
/// <summary>
/// Encodes a chunk of samples. Please note that if you have set the output to
/// generate mono MP3 files you must feed beEncodeChunk() with mono samples
/// </summary>
/// <param name="hbeStream">Handle of the stream.</param>
/// <param name="nSamples">Number of samples to be encoded for this call.
/// This should be identical to what is returned by beInitStream(),
/// unless you are encoding the last chunk, which might be smaller.</param>
/// <param name="pSamples">Pointer at the 16-bit signed samples to be encoded.
/// InPtr is used to pass any type of array without need of make memory copy,
/// then gaining in performance. Note that nSamples is not the number of bytes,
/// but samples (is sample is a SHORT)</param>
/// <param name="pOutput">Buffer where to write the encoded data.
/// This buffer should be at least of the minimum size returned by beInitStream().</param>
/// <param name="pdwOutput">Returns the number of bytes of encoded data written.
/// The amount of data written might vary from chunk to chunk</param>
/// <returns>On success: BE_ERR_SUCCESSFUL</returns>
[DllImport("Lame_enc.dll")]
protected static extern uint beEncodeChunk(uint hbeStream, uint nSamples, IntPtr pSamples, IntPtr pOutput, ref uint pdwOutput);
/// <summary>
/// Encodes a chunk of samples. Samples are contained in a byte array
/// </summary>
/// <param name="hbeStream">Handle of the stream.</param>
/// <param name="buffer">Bytes to encode</param>
/// <param name="index">Position of the first byte to encode</param>
/// <param name="nBytes">Number of bytes to encode (not samples, samples are two byte lenght)</param>
/// <param name="pOutput">Buffer where to write the encoded data.
/// This buffer should be at least of the minimum size returned by beInitStream().</param>
/// <param name="pdwOutput">Returns the number of bytes of encoded data written.
/// The amount of data written might vary from chunk to chunk</param>
/// <returns>On success: BE_ERR_SUCCESSFUL</returns>
public static unsafe uint EncodeChunk(uint hbeStream, byte* pSamples, uint nBytes, byte* pOutput, ref uint pdwOutput)
{
return beEncodeChunk(hbeStream, nBytes / 2/*Samples*/, (IntPtr)pSamples, (IntPtr)pOutput, ref pdwOutput);
}
/// <summary>
/// Encodes a chunk of samples. Samples are contained in a byte array
/// </summary>
/// <param name="hbeStream">Handle of the stream.</param>
/// <param name="buffer">Bytes to encode</param>
/// <param name="index">Position of the first byte to encode</param>
/// <param name="nBytes">Number of bytes to encode (not samples, samples are two byte lenght)</param>
/// <param name="pOutput">Buffer where to write the encoded data.
/// This buffer should be at least of the minimum size returned by beInitStream().</param>
/// <param name="pdwOutput">Returns the number of bytes of encoded data written.
/// The amount of data written might vary from chunk to chunk</param>
/// <returns>On success: BE_ERR_SUCCESSFUL</returns>
public static unsafe uint EncodeChunk(uint hbeStream, byte[] Samples, int index, uint nBytes, byte[] Output, ref uint pdwOutput)
{
fixed (byte* pSamples = &Samples[index], pOutput = Output)
return beEncodeChunk(hbeStream, nBytes / 2/*Samples*/, (IntPtr)pSamples, (IntPtr)pOutput, ref pdwOutput);
}
/// <summary>
/// Encodes a chunk of samples. Samples are contained in a byte array
/// </summary>
/// <param name="hbeStream">Handle of the stream.</param>
/// <param name="buffer">Bytes to encode</param>
/// <param name="pOutput">Buffer where to write the encoded data.
/// This buffer should be at least of the minimum size returned by beInitStream().</param>
/// <param name="pdwOutput">Returns the number of bytes of encoded data written.
/// The amount of data written might vary from chunk to chunk</param>
/// <returns>On success: BE_ERR_SUCCESSFUL</returns>
public static uint EncodeChunk(uint hbeStream, byte[] buffer, byte[] pOutput, ref uint pdwOutput)
{
return EncodeChunk(hbeStream, buffer, 0, (uint)buffer.Length, pOutput, ref pdwOutput);
}
/// <summary>
/// This function should be called after encoding the last chunk in order to flush
/// the encoder. It writes any encoded data that still might be left inside the
/// encoder to the output buffer. This function should NOT be called unless
/// you have encoded all of the chunks in your stream.
/// </summary>
/// <param name="hbeStream">Handle of the stream.</param>
/// <param name="pOutput">Where to write the encoded data. This buffer should be
/// at least of the minimum size returned by beInitStream().</param>
/// <param name="pdwOutput">Returns number of bytes of encoded data written.</param>
/// <returns>On success: BE_ERR_SUCCESSFUL</returns>
[DllImport("Lame_enc.dll")]
public static extern uint beDeinitStream(uint hbeStream, [In, Out] byte[] pOutput, ref uint pdwOutput);
/// <summary>
/// Last function to be called when finished encoding a stream.
/// Should unlike beDeinitStream() also be called if the encoding is canceled.
/// </summary>
/// <param name="hbeStream">Handle of the stream.</param>
/// <returns>On success: BE_ERR_SUCCESSFUL</returns>
[DllImport("Lame_enc.dll")]
public static extern uint beCloseStream(uint hbeStream);
/// <summary>
/// Returns information like version numbers (both of the DLL and encoding engine),
/// release date and URL for lame_enc's homepage.
/// All this information should be made available to the user of your product
/// through a dialog box or something similar.
/// </summary>
/// <param name="pbeVersion"Where version number, release date and URL for homepage
/// is returned.</param>
[DllImport("Lame_enc.dll")]
public static extern void beVersion([Out] BE_VERSION pbeVersion);
[DllImport("Lame_enc.dll", CharSet = CharSet.Ansi)]
public static extern void beWriteVBRHeader(string pszMP3FileName);
[DllImport("Lame_enc.dll")]
public static extern uint beEncodeChunkFloatS16NI(uint hbeStream, uint nSamples, [In]float[] buffer_l, [In]float[] buffer_r, [In, Out]byte[] pOutput, ref uint pdwOutput);
[DllImport("Lame_enc.dll")]
public static extern uint beFlushNoGap(uint hbeStream, [In, Out]byte[] pOutput, ref uint pdwOutput);
[DllImport("Lame_enc.dll", CharSet = CharSet.Ansi)]
public static extern uint beWriteInfoTag(uint hbeStream, string lpszFileName);
}
}

View File

@@ -1,25 +1,25 @@
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
PURPOSE. IT CAN BE DISTRIBUTED FREE OF CHARGE AS LONG AS THIS HEADER
REMAINS UNCHANGED.
Email: yetiicb@hotmail.com
Copyright (C) 2002-2003 Idael Cardoso.
LAME ( LAME Ain't an Mp3 Encoder )
You must call the fucntion "beVersion" to obtain information like version
numbers (both of the DLL and encoding engine), release date and URL for
lame_enc's homepage. All this information should be made available to the
user of your product through a dialog box or something similar.
You must see all information about LAME project and legal license infos at
http://www.mp3dev.org/ The official LAME site
About Thomson and/or Fraunhofer patents:
Any use of this product does not convey a license under the relevant
intellectual property of Thomson and/or Fraunhofer Gesellschaft nor imply
any right to use this product in any finished end user or ready-to-use final
product. An independent license for such use is required.
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
PURPOSE. IT CAN BE DISTRIBUTED FREE OF CHARGE AS LONG AS THIS HEADER
REMAINS UNCHANGED.
Email: yetiicb@hotmail.com
Copyright (C) 2002-2003 Idael Cardoso.
LAME ( LAME Ain't an Mp3 Encoder )
You must call the fucntion "beVersion" to obtain information like version
numbers (both of the DLL and encoding engine), release date and URL for
lame_enc's homepage. All this information should be made available to the
user of your product through a dialog box or something similar.
You must see all information about LAME project and legal license infos at
http://www.mp3dev.org/ The official LAME site
About Thomson and/or Fraunhofer patents:
Any use of this product does not convey a license under the relevant
intellectual property of Thomson and/or Fraunhofer Gesellschaft nor imply
any right to use this product in any finished end user or ready-to-use final
product. An independent license for such use is required.
For details, please visit http://www.mp3licensing.com.

View File

@@ -1,17 +1,17 @@
using System;
using System.Runtime.InteropServices;
namespace CUETools.Codecs.LAME.Interop
{
[StructLayout(LayoutKind.Sequential), Serializable]
public struct MP3 //BE_CONFIG_MP3
{
public uint dwSampleRate; // 48000, 44100 and 32000 allowed
public byte byMode; // BE_MP3_MODE_STEREO, BE_MP3_MODE_DUALCHANNEL, BE_MP3_MODE_MONO
public ushort wBitrate; // 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256 and 320 allowed
public int bPrivate;
public int bCRC;
public int bCopyright;
public int bOriginal;
}
}
using System;
using System.Runtime.InteropServices;
namespace CUETools.Codecs.LAME.Interop
{
[StructLayout(LayoutKind.Sequential), Serializable]
public struct MP3 //BE_CONFIG_MP3
{
public uint dwSampleRate; // 48000, 44100 and 32000 allowed
public byte byMode; // BE_MP3_MODE_STEREO, BE_MP3_MODE_DUALCHANNEL, BE_MP3_MODE_MONO
public ushort wBitrate; // 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256 and 320 allowed
public int bPrivate;
public int bCRC;
public int bCopyright;
public int bOriginal;
}
}

View File

@@ -1,13 +1,13 @@
namespace CUETools.Codecs.LAME.Interop
{
/* MPEG modes */
public enum MpegMode : uint
{
STEREO = 0,
JOINT_STEREO,
DUAL_CHANNEL, /* LAME doesn't supports this! */
MONO,
NOT_SET,
MAX_INDICATOR /* Don't use this! It's used for sanity checks. */
}
}
namespace CUETools.Codecs.LAME.Interop
{
/* MPEG modes */
public enum MpegMode : uint
{
STEREO = 0,
JOINT_STEREO,
DUAL_CHANNEL, /* LAME doesn't supports this! */
MONO,
NOT_SET,
MAX_INDICATOR /* Don't use this! It's used for sanity checks. */
}
}

View File

@@ -1,12 +1,12 @@
namespace CUETools.Codecs.LAME.Interop
{
public enum VBRMETHOD : int
{
VBR_METHOD_NONE = -1,
VBR_METHOD_DEFAULT = 0,
VBR_METHOD_OLD = 1,
VBR_METHOD_NEW = 2,
VBR_METHOD_MTRH = 3,
VBR_METHOD_ABR = 4
}
}
namespace CUETools.Codecs.LAME.Interop
{
public enum VBRMETHOD : int
{
VBR_METHOD_NONE = -1,
VBR_METHOD_DEFAULT = 0,
VBR_METHOD_OLD = 1,
VBR_METHOD_NEW = 2,
VBR_METHOD_MTRH = 3,
VBR_METHOD_ABR = 4
}
}

View File

@@ -1,247 +1,247 @@
using System;
using System.IO;
using System.Text;
using CUETools.Codecs.LAME.Interop;
namespace CUETools.Codecs.LAME
{
public class LAMEEncoder : IAudioDest
{
private bool closed = false;
private BE_CONFIG m_Mp3Config = null;
private uint m_hLameStream = 0;
private uint m_InputSamples = 0;
private uint m_OutBufferSize = 0;
private byte[] m_InBuffer = null;
private int m_InBufferPos = 0;
private byte[] m_OutBuffer = null;
private AudioEncoderSettings m_settings;
private string _path;
private Stream _IO;
private long position = 0, sample_count = -1;
private long bytesWritten = 0;
private bool inited = false;
public virtual AudioEncoderSettings Settings
{
get
{
return m_settings;
}
}
public long Position
{
get { return position; }
}
public long FinalSampleCount
{
set { sample_count = (int)value; }
}
public string Path { get { return _path; } }
public long BytesWritten
{
get { return bytesWritten; }
}
public LAMEEncoder(string path, Stream IO, AudioEncoderSettings settings)
{
if (settings.PCM.BitsPerSample != 16)// && pcm.BitsPerSample != 32)
throw new ArgumentOutOfRangeException("format", "Only 16 & 32 bits samples supported");
m_settings = settings;
_path = path;
_IO = IO;
}
public LAMEEncoder(string path, AudioEncoderSettings settings)
: this(path, null, settings)
{
}
public void DeInit(bool flush)
{
if (!inited || closed)
return;
try
{
if (flush)
{
uint EncodedSize = 0;
if (m_InBufferPos > 0)
{
if (Lame_encDll.EncodeChunk(m_hLameStream, m_InBuffer, 0, (uint)m_InBufferPos, m_OutBuffer, ref EncodedSize) == Lame_encDll.BE_ERR_SUCCESSFUL)
{
if (EncodedSize > 0)
{
_IO.Write(m_OutBuffer, 0, (int)EncodedSize);
bytesWritten += EncodedSize;
}
}
}
EncodedSize = 0;
if (Lame_encDll.beDeinitStream(m_hLameStream, m_OutBuffer, ref EncodedSize) == Lame_encDll.BE_ERR_SUCCESSFUL)
{
if (EncodedSize > 0)
{
_IO.Write(m_OutBuffer, 0, (int)EncodedSize);
bytesWritten += EncodedSize;
}
}
}
}
finally
{
Lame_encDll.beCloseStream(m_hLameStream);
_IO.Close();
closed = true;
}
}
public void Close()
{
bool needTag = !closed && _path != null && _path != "";
DeInit(true);
if (needTag)
{
bool utf8Required = Encoding.Default.GetString(Encoding.Default.GetBytes(_path)) != _path;
var tempDir = System.IO.Path.Combine(System.IO.Path.GetPathRoot(_path), "Temp");
var tempName = utf8Required ? System.IO.Path.Combine(tempDir, Guid.NewGuid().ToString()) : _path;
try
{
if (utf8Required && !Directory.Exists(tempDir)) Directory.CreateDirectory(tempDir);
if (utf8Required) File.Move(_path, tempName);
Lame_encDll.beWriteInfoTag(m_hLameStream, tempName);
if (utf8Required) File.Move(tempName, _path);
}
catch
{
if (utf8Required) File.Move(tempName, _path);
}
}
}
public void Delete()
{
if (!closed)
{
DeInit(false);
if (_path != "")
File.Delete(_path);
}
}
protected virtual BE_CONFIG MakeConfig()
{
return new BE_CONFIG(Settings.PCM);
}
private void Init()
{
if (inited)
return;
m_Mp3Config = MakeConfig();
uint LameResult = Lame_encDll.beInitStream(m_Mp3Config, ref m_InputSamples, ref m_OutBufferSize, ref m_hLameStream);
if (LameResult != Lame_encDll.BE_ERR_SUCCESSFUL)
throw new ApplicationException(string.Format("Lame_encDll.beInitStream failed with the error code {0}", LameResult));
m_InBuffer = new byte[m_InputSamples * 2]; //Input buffer is expected as short[]
m_OutBuffer = new byte[Math.Max(65536, m_OutBufferSize)];
if (_IO == null)
_IO = new FileStream(_path, FileMode.Create, FileAccess.Write, FileShare.Read);
inited = true;
}
public unsafe void Write(AudioBuffer buff)
{
buff.Prepare(this);
Init();
byte[] buffer = buff.Bytes;
int index = 0;
int count = buff.ByteLength;
int ToCopy = 0;
uint EncodedSize = 0;
uint LameResult;
uint outBufferIndex = 0;
fixed (byte* pBuffer = buffer, pOutBuffer = m_OutBuffer)
{
while (count > 0)
{
if (m_InBufferPos > 0)
{
ToCopy = Math.Min(count, m_InBuffer.Length - m_InBufferPos);
Buffer.BlockCopy(buffer, index, m_InBuffer, m_InBufferPos, ToCopy);
m_InBufferPos += ToCopy;
index += ToCopy;
count -= ToCopy;
if (m_InBufferPos >= m_InBuffer.Length)
{
m_InBufferPos = 0;
if (outBufferIndex > 0)
{
_IO.Write(m_OutBuffer, 0, (int)outBufferIndex);
bytesWritten += outBufferIndex;
outBufferIndex = 0;
}
if ((LameResult = Lame_encDll.EncodeChunk(m_hLameStream, m_InBuffer, m_OutBuffer, ref EncodedSize)) == Lame_encDll.BE_ERR_SUCCESSFUL)
{
outBufferIndex += EncodedSize;
}
else
{
throw new ApplicationException(string.Format("Lame_encDll.EncodeChunk failed with the error code {0}", LameResult));
}
}
}
else
{
if (count >= m_InBuffer.Length)
{
if (outBufferIndex + m_OutBufferSize > m_OutBuffer.Length)
{
_IO.Write(m_OutBuffer, 0, (int)outBufferIndex);
bytesWritten += outBufferIndex;
outBufferIndex = 0;
}
if ((LameResult = Lame_encDll.EncodeChunk(m_hLameStream, pBuffer + index, (uint)m_InBuffer.Length, pOutBuffer + outBufferIndex, ref EncodedSize)) == Lame_encDll.BE_ERR_SUCCESSFUL)
{
outBufferIndex += EncodedSize;
}
else
{
throw new ApplicationException(string.Format("Lame_encDll.EncodeChunk failed with the error code {0}", LameResult));
}
count -= m_InBuffer.Length;
index += m_InBuffer.Length;
}
else
{
Buffer.BlockCopy(buffer, index, m_InBuffer, 0, count);
m_InBufferPos = count;
index += count;
count = 0;
}
}
}
}
if (outBufferIndex > 0)
{
_IO.Write(m_OutBuffer, 0, (int)outBufferIndex);
bytesWritten += outBufferIndex;
}
}
}
}
using System;
using System.IO;
using System.Text;
using CUETools.Codecs.LAME.Interop;
namespace CUETools.Codecs.LAME
{
public class LAMEEncoder : IAudioDest
{
private bool closed = false;
private BE_CONFIG m_Mp3Config = null;
private uint m_hLameStream = 0;
private uint m_InputSamples = 0;
private uint m_OutBufferSize = 0;
private byte[] m_InBuffer = null;
private int m_InBufferPos = 0;
private byte[] m_OutBuffer = null;
private AudioEncoderSettings m_settings;
private string _path;
private Stream _IO;
private long position = 0, sample_count = -1;
private long bytesWritten = 0;
private bool inited = false;
public virtual AudioEncoderSettings Settings
{
get
{
return m_settings;
}
}
public long Position
{
get { return position; }
}
public long FinalSampleCount
{
set { sample_count = (int)value; }
}
public string Path { get { return _path; } }
public long BytesWritten
{
get { return bytesWritten; }
}
public LAMEEncoder(string path, Stream IO, AudioEncoderSettings settings)
{
if (settings.PCM.BitsPerSample != 16)// && pcm.BitsPerSample != 32)
throw new ArgumentOutOfRangeException("format", "Only 16 & 32 bits samples supported");
m_settings = settings;
_path = path;
_IO = IO;
}
public LAMEEncoder(string path, AudioEncoderSettings settings)
: this(path, null, settings)
{
}
public void DeInit(bool flush)
{
if (!inited || closed)
return;
try
{
if (flush)
{
uint EncodedSize = 0;
if (m_InBufferPos > 0)
{
if (Lame_encDll.EncodeChunk(m_hLameStream, m_InBuffer, 0, (uint)m_InBufferPos, m_OutBuffer, ref EncodedSize) == Lame_encDll.BE_ERR_SUCCESSFUL)
{
if (EncodedSize > 0)
{
_IO.Write(m_OutBuffer, 0, (int)EncodedSize);
bytesWritten += EncodedSize;
}
}
}
EncodedSize = 0;
if (Lame_encDll.beDeinitStream(m_hLameStream, m_OutBuffer, ref EncodedSize) == Lame_encDll.BE_ERR_SUCCESSFUL)
{
if (EncodedSize > 0)
{
_IO.Write(m_OutBuffer, 0, (int)EncodedSize);
bytesWritten += EncodedSize;
}
}
}
}
finally
{
Lame_encDll.beCloseStream(m_hLameStream);
_IO.Close();
closed = true;
}
}
public void Close()
{
bool needTag = !closed && _path != null && _path != "";
DeInit(true);
if (needTag)
{
bool utf8Required = Encoding.Default.GetString(Encoding.Default.GetBytes(_path)) != _path;
var tempDir = System.IO.Path.Combine(System.IO.Path.GetPathRoot(_path), "Temp");
var tempName = utf8Required ? System.IO.Path.Combine(tempDir, Guid.NewGuid().ToString()) : _path;
try
{
if (utf8Required && !Directory.Exists(tempDir)) Directory.CreateDirectory(tempDir);
if (utf8Required) File.Move(_path, tempName);
Lame_encDll.beWriteInfoTag(m_hLameStream, tempName);
if (utf8Required) File.Move(tempName, _path);
}
catch
{
if (utf8Required) File.Move(tempName, _path);
}
}
}
public void Delete()
{
if (!closed)
{
DeInit(false);
if (_path != "")
File.Delete(_path);
}
}
protected virtual BE_CONFIG MakeConfig()
{
return new BE_CONFIG(Settings.PCM);
}
private void Init()
{
if (inited)
return;
m_Mp3Config = MakeConfig();
uint LameResult = Lame_encDll.beInitStream(m_Mp3Config, ref m_InputSamples, ref m_OutBufferSize, ref m_hLameStream);
if (LameResult != Lame_encDll.BE_ERR_SUCCESSFUL)
throw new ApplicationException(string.Format("Lame_encDll.beInitStream failed with the error code {0}", LameResult));
m_InBuffer = new byte[m_InputSamples * 2]; //Input buffer is expected as short[]
m_OutBuffer = new byte[Math.Max(65536, m_OutBufferSize)];
if (_IO == null)
_IO = new FileStream(_path, FileMode.Create, FileAccess.Write, FileShare.Read);
inited = true;
}
public unsafe void Write(AudioBuffer buff)
{
buff.Prepare(this);
Init();
byte[] buffer = buff.Bytes;
int index = 0;
int count = buff.ByteLength;
int ToCopy = 0;
uint EncodedSize = 0;
uint LameResult;
uint outBufferIndex = 0;
fixed (byte* pBuffer = buffer, pOutBuffer = m_OutBuffer)
{
while (count > 0)
{
if (m_InBufferPos > 0)
{
ToCopy = Math.Min(count, m_InBuffer.Length - m_InBufferPos);
Buffer.BlockCopy(buffer, index, m_InBuffer, m_InBufferPos, ToCopy);
m_InBufferPos += ToCopy;
index += ToCopy;
count -= ToCopy;
if (m_InBufferPos >= m_InBuffer.Length)
{
m_InBufferPos = 0;
if (outBufferIndex > 0)
{
_IO.Write(m_OutBuffer, 0, (int)outBufferIndex);
bytesWritten += outBufferIndex;
outBufferIndex = 0;
}
if ((LameResult = Lame_encDll.EncodeChunk(m_hLameStream, m_InBuffer, m_OutBuffer, ref EncodedSize)) == Lame_encDll.BE_ERR_SUCCESSFUL)
{
outBufferIndex += EncodedSize;
}
else
{
throw new ApplicationException(string.Format("Lame_encDll.EncodeChunk failed with the error code {0}", LameResult));
}
}
}
else
{
if (count >= m_InBuffer.Length)
{
if (outBufferIndex + m_OutBufferSize > m_OutBuffer.Length)
{
_IO.Write(m_OutBuffer, 0, (int)outBufferIndex);
bytesWritten += outBufferIndex;
outBufferIndex = 0;
}
if ((LameResult = Lame_encDll.EncodeChunk(m_hLameStream, pBuffer + index, (uint)m_InBuffer.Length, pOutBuffer + outBufferIndex, ref EncodedSize)) == Lame_encDll.BE_ERR_SUCCESSFUL)
{
outBufferIndex += EncodedSize;
}
else
{
throw new ApplicationException(string.Format("Lame_encDll.EncodeChunk failed with the error code {0}", LameResult));
}
count -= m_InBuffer.Length;
index += m_InBuffer.Length;
}
else
{
Buffer.BlockCopy(buffer, index, m_InBuffer, 0, count);
m_InBufferPos = count;
index += count;
count = 0;
}
}
}
}
if (outBufferIndex > 0)
{
_IO.Write(m_OutBuffer, 0, (int)outBufferIndex);
bytesWritten += outBufferIndex;
}
}
}
}

View File

@@ -1,40 +1,40 @@
using System;
using System.IO;
using CUETools.Codecs.LAME.Interop;
namespace CUETools.Codecs.LAME
{
//[AudioEncoderClass("lame CBR", "mp3", false, 2, typeof(LAMEEncoderCBRSettings))]
public class LAMEEncoderCBR : LAMEEncoder
{
private LAMEEncoderCBRSettings m_settings;
public override AudioEncoderSettings Settings
{
get
{
return m_settings;
}
}
public LAMEEncoderCBR(string path, Stream IO, AudioEncoderSettings settings)
: base(path, IO, settings)
{
}
public LAMEEncoderCBR(string path, AudioEncoderSettings settings)
: base(path, null, settings)
{
}
protected override BE_CONFIG MakeConfig()
{
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
//Mp3Config.format.lhv1.nPreset = LAME_QUALITY_PRESET.LQP_NORMAL_QUALITY;
return Mp3Config;
}
}
}
using System;
using System.IO;
using CUETools.Codecs.LAME.Interop;
namespace CUETools.Codecs.LAME
{
//[AudioEncoderClass("lame CBR", "mp3", false, 2, typeof(LAMEEncoderCBRSettings))]
public class LAMEEncoderCBR : LAMEEncoder
{
private LAMEEncoderCBRSettings m_settings;
public override AudioEncoderSettings Settings
{
get
{
return m_settings;
}
}
public LAMEEncoderCBR(string path, Stream IO, AudioEncoderSettings settings)
: base(path, IO, settings)
{
}
public LAMEEncoderCBR(string path, AudioEncoderSettings settings)
: base(path, null, settings)
{
}
protected override BE_CONFIG MakeConfig()
{
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
//Mp3Config.format.lhv1.nPreset = LAME_QUALITY_PRESET.LQP_NORMAL_QUALITY;
return Mp3Config;
}
}
}

View File

@@ -1,24 +1,24 @@
using System;
using System.ComponentModel;
using CUETools.Codecs.LAME.Interop;
namespace CUETools.Codecs.LAME
{
public class LAMEEncoderCBRSettings : AudioEncoderSettings
{
public override Type EncoderType => typeof(LAMEEncoderCBR);
public static readonly uint[] bps_table = new uint[] { 96, 128, 192, 256, 320 };
[DefaultValue(0)]
public int CustomBitrate { get; set; }
[DefaultValue(MpegMode.STEREO)]
public MpegMode StereoMode { get; set; }
public LAMEEncoderCBRSettings()
: base("96 128 192 256 320", "256")
{
}
}
}
using System;
using System.ComponentModel;
using CUETools.Codecs.LAME.Interop;
namespace CUETools.Codecs.LAME
{
public class LAMEEncoderCBRSettings : AudioEncoderSettings
{
public override Type EncoderType => typeof(LAMEEncoderCBR);
public static readonly uint[] bps_table = new uint[] { 96, 128, 192, 256, 320 };
[DefaultValue(0)]
public int CustomBitrate { get; set; }
[DefaultValue(MpegMode.STEREO)]
public MpegMode StereoMode { get; set; }
public LAMEEncoderCBRSettings()
: base("96 128 192 256 320", "256")
{
}
}
}

View File

@@ -1,41 +1,41 @@
using System;
using System.IO;
using CUETools.Codecs.LAME.Interop;
namespace CUETools.Codecs.LAME
{
//[AudioEncoderClass("lame VBR", "mp3", false, 2, typeof(LAMEEncoderVBRSettings))]
public class LAMEEncoderVBR : LAMEEncoder
{
private LAMEEncoderVBRSettings m_settings;
public override AudioEncoderSettings Settings
{
get
{
return m_settings;
}
}
public LAMEEncoderVBR(string path, Stream IO, AudioEncoderSettings settings)
: base(path, IO, settings)
{
}
public LAMEEncoderVBR(string path, AudioEncoderSettings settings)
: base(path, null, settings)
{
}
protected override BE_CONFIG MakeConfig()
{
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;
Mp3Config.format.lhv1.nVBRQuality = 9 - m_settings.EncoderModeIndex;
Mp3Config.format.lhv1.nVbrMethod = VBRMETHOD.VBR_METHOD_NEW; // --vbr-new
return Mp3Config;
}
}
}
using System;
using System.IO;
using CUETools.Codecs.LAME.Interop;
namespace CUETools.Codecs.LAME
{
//[AudioEncoderClass("lame VBR", "mp3", false, 2, typeof(LAMEEncoderVBRSettings))]
public class LAMEEncoderVBR : LAMEEncoder
{
private LAMEEncoderVBRSettings m_settings;
public override AudioEncoderSettings Settings
{
get
{
return m_settings;
}
}
public LAMEEncoderVBR(string path, Stream IO, AudioEncoderSettings settings)
: base(path, IO, settings)
{
}
public LAMEEncoderVBR(string path, AudioEncoderSettings settings)
: base(path, null, settings)
{
}
protected override BE_CONFIG MakeConfig()
{
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;
Mp3Config.format.lhv1.nVBRQuality = 9 - m_settings.EncoderModeIndex;
Mp3Config.format.lhv1.nVbrMethod = VBRMETHOD.VBR_METHOD_NEW; // --vbr-new
return Mp3Config;
}
}
}

View File

@@ -1,8 +1,8 @@
namespace CUETools.Codecs.LAME
{
public enum LAMEEncoderVBRProcessingQuality : uint
{
Best = 0,
Normal = 5,
}
}
namespace CUETools.Codecs.LAME
{
public enum LAMEEncoderVBRProcessingQuality : uint
{
Best = 0,
Normal = 5,
}
}

View File

@@ -1,18 +1,18 @@
using System;
using System.ComponentModel;
namespace CUETools.Codecs.LAME
{
public class LAMEEncoderVBRSettings : AudioEncoderSettings
{
public override Type EncoderType => typeof(LAMEEncoderVBR);
[DefaultValue(LAMEEncoderVBRProcessingQuality.Normal)]
public LAMEEncoderVBRProcessingQuality Quality { get; set; }
public LAMEEncoderVBRSettings()
: base("V9 V8 V7 V6 V5 V4 V3 V2 V1 V0", "V2")
{
}
}
}
using System;
using System.ComponentModel;
namespace CUETools.Codecs.LAME
{
public class LAMEEncoderVBRSettings : AudioEncoderSettings
{
public override Type EncoderType => typeof(LAMEEncoderVBR);
[DefaultValue(LAMEEncoderVBRProcessingQuality.Normal)]
public LAMEEncoderVBRProcessingQuality Quality { get; set; }
public LAMEEncoderVBRSettings()
: base("V9 V8 V7 V6 V5 V4 V3 V2 V1 V0", "V2")
{
}
}
}

View File

@@ -21,7 +21,6 @@ namespace CUETools.Codecs.libFLAC
public Settings() : base() { }
}
[AudioDecoderClass(typeof(Settings))]
public unsafe class Reader : IAudioSource
{
public Reader(string path, Stream IO)

View File

@@ -44,7 +44,6 @@ namespace CUETools.Codecs.libFLAC
public string Version => FLACDLL.GetVersion;
};
[AudioEncoderClass(typeof(EncoderSettings))]
public unsafe class Encoder : IAudioDest
{
public Encoder(string path, Stream output, EncoderSettings settings)

View File

@@ -0,0 +1,29 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net40;net20;netstandard2.0</TargetFrameworks>
<Version>2.1.7.0</Version>
<AssemblyName>CUETools.Codecs.libmp3lame</AssemblyName>
<RootNamespace>CUETools.Codecs.libmp3lame</RootNamespace>
<Product>CUETools</Product>
<Description>A library for encoding mp3 using LAME encoder.</Description>
<Copyright>Copyright (c) 2008-2018 Grigory Chudov</Copyright>
<Authors>Grigory Chudov</Authors>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<OutputPath>..\bin\$(Configuration)\plugins</OutputPath>
<RepositoryUrl>https://github.com/gchudov/cuetools.net</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<Company />
</PropertyGroup>
<ItemDefinitionGroup>
<ProjectReference>
<Private>False</Private>
</ProjectReference>
</ItemDefinitionGroup>
<ItemGroup>
<ProjectReference Include="..\CUETools.Codecs\CUETools.Codecs.csproj" />
</ItemGroup>
</Project>

View File

@@ -1,14 +1,14 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace CUETools.Codecs.LAME
{
public class LameException : Exception
{
public LameException(string message)
: base(message)
{
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
namespace CUETools.Codecs.libmp3lame
{
public class LameException : Exception
{
public LameException(string message)
: base(message)
{
}
}
}

View File

@@ -1,300 +1,259 @@
using System;
using System.Runtime.InteropServices;
using CUETools.Codecs;
using System.IO;
namespace CUETools.Codecs.LAME
{
[AudioEncoderClass(typeof(CBREncoderSettings))]
[AudioEncoderClass(typeof(VBREncoderSettings))]
public class AudioEncoder : IAudioDest
{
#region Unmanaged Functions
private const string LameDll = "libmp3lame";
private const CallingConvention LameCallingConvention = CallingConvention.Cdecl;
[DllImport(LameDll, CallingConvention = LameCallingConvention)]
internal static extern IntPtr lame_init();
[DllImport(LameDll, CallingConvention = LameCallingConvention)]
internal static extern int lame_close(IntPtr handle);
[DllImport(LameDll, CallingConvention = LameCallingConvention)]
internal static extern int lame_set_num_channels(IntPtr handle, int channels);
[DllImport(LameDll, CallingConvention = LameCallingConvention)]
internal static extern int lame_set_in_samplerate(IntPtr handle, int sampleRate);
[DllImport(LameDll, CallingConvention = LameCallingConvention)]
internal static extern int lame_set_quality(IntPtr handle, int quality);
[DllImport(LameDll, CallingConvention = LameCallingConvention)]
internal static extern int lame_set_VBR(IntPtr handle, int vbrMode);
[DllImport(LameDll, CallingConvention = LameCallingConvention)]
internal static extern int lame_set_VBR_mean_bitrate_kbps(IntPtr handle, int meanBitrate);
[DllImport(LameDll, CallingConvention = LameCallingConvention)]
internal static extern int lame_init_params(IntPtr handle);
[DllImport(LameDll, CallingConvention = LameCallingConvention)]
internal static extern int lame_set_num_samples(IntPtr handle, uint numSamples);
[DllImport(LameDll, CallingConvention = LameCallingConvention)]
internal static extern int lame_encode_buffer_interleaved(IntPtr handle, IntPtr pcm, int num_samples, IntPtr mp3buf, int mp3buf_size);
[DllImport(LameDll, CallingConvention = LameCallingConvention)]
internal static extern int lame_encode_flush(IntPtr handle, IntPtr mp3buf, int size);
[DllImport(LameDll, CallingConvention = LameCallingConvention)]
internal static extern uint lame_get_lametag_frame(IntPtr handle, IntPtr buffer, uint size);
[DllImport(LameDll, CallingConvention = LameCallingConvention)]
internal static extern int lame_set_VBR_quality(IntPtr handle, float vbrQuality);
[DllImport(LameDll, CallingConvention = LameCallingConvention)]
internal static extern int lame_set_brate(IntPtr handle, int bitrate);
[DllImport(LameDll, CallingConvention = LameCallingConvention)]
internal static extern int lame_set_bWriteVbrTag(IntPtr handle, int writeVbrTag);
[DllImport(LameDll, CallingConvention = LameCallingConvention)]
internal static extern int lame_set_write_id3tag_automatic(IntPtr handle, int automaticWriteId3Tag);
#endregion
private string m_outputPath;
private Stream m_outputStream;
private bool m_closed = false, m_initialized = false;
private IntPtr m_handle;
private uint m_finalSampleCount;
private byte[] m_outputBuffer;
public long FinalSampleCount
{
set
{
if (value > uint.MaxValue)
{
throw new ArgumentException("Input file too big.");
}
this.m_finalSampleCount = (uint)value;
}
}
public string Path
{
get { return this.m_outputPath; }
}
private LameEncoderSettings m_settings;
public virtual AudioEncoderSettings Settings
{
get
{
return m_settings;
}
}
public AudioEncoder(string path, Stream output, LameEncoderSettings settings)
{
this.CheckPCMConfig(settings.PCM);
this.m_settings = settings;
this.m_outputPath = path;
this.m_outputStream = output != null ? output : File.Create(path);
}
public AudioEncoder(string path, LameEncoderSettings settings)
: this(path, null, settings)
{
}
private void CheckPCMConfig(AudioPCMConfig pcm)
{
if (pcm.BitsPerSample != 16)
{
throw new ArgumentException("LAME only supports 16 bits/sample.");
}
}
private void FinalizeEncoding()
{
this.EnsureOutputBufferSize(7200);
int flushResult;
unsafe
{
fixed (byte* outputBufferPtr = m_outputBuffer)
{
flushResult = lame_encode_flush(m_handle, (IntPtr)outputBufferPtr, m_outputBuffer.Length);
}
}
if (flushResult < 0)
{
throw new LameException("Unknown flush error");
}
if (flushResult > 0)
{
this.m_outputStream.Write(this.m_outputBuffer, 0, flushResult);
}
int lametagFrameSize = this.GetLametagFrame();
this.m_outputStream.Seek(0, SeekOrigin.Begin);
this.m_outputStream.Write(this.m_outputBuffer, 0, lametagFrameSize);
}
public void Close()
{
if (!this.m_closed)
{
if (this.m_initialized)
{
try
{
try
{
this.FinalizeEncoding();
}
finally
{
lame_close(m_handle);
}
}
finally
{
m_handle = IntPtr.Zero;
if (this.m_outputPath != null)
{
this.m_outputStream.Close();
}
}
}
this.m_closed = true;
}
}
private int GetLametagFrame()
{
while (true)
{
uint lametagFrameResult;
unsafe
{
fixed (byte* outputBufferPtr = m_outputBuffer)
{
lametagFrameResult = lame_get_lametag_frame(this.m_handle, (IntPtr)outputBufferPtr, (uint)m_outputBuffer.Length);
}
}
if (lametagFrameResult < 0)
{
throw new LameException("Error getting lametag frame.");
}
if (lametagFrameResult <= m_outputBuffer.Length)
{
return (int)lametagFrameResult;
}
this.EnsureOutputBufferSize((int)lametagFrameResult);
}
}
public uint GetLametagFrame(byte[] outputBuffer)
{
unsafe
{
fixed (byte* outputBufferPtr = outputBuffer)
{
return lame_get_lametag_frame(m_handle, (IntPtr)outputBufferPtr, (uint)outputBuffer.Length);
}
}
}
private void EnsureInitialized()
{
if (!this.m_initialized)
{
m_handle = lame_init();
lame_set_bWriteVbrTag(m_handle, 1);
lame_set_write_id3tag_automatic(m_handle, 0);
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)
{
lame_set_num_samples(m_handle, this.m_finalSampleCount);
}
m_settings.Apply(m_handle);
if (lame_init_params(m_handle) != 0)
{
throw new LameException("lame_init_params failed");
}
this.m_initialized = true;
}
}
public void Delete()
{
if (this.m_outputPath == null)
{
throw new InvalidOperationException("This writer was not created from file.");
}
if (!m_closed)
{
this.Close();
File.Delete(this.m_outputPath);
}
}
private void EnsureOutputBufferSize(int requiredSize)
{
if (this.m_outputBuffer == null || this.m_outputBuffer.Length < requiredSize)
{
this.m_outputBuffer = new byte[requiredSize];
}
}
public void Write(AudioBuffer buffer)
{
if (this.m_closed)
{
throw new InvalidOperationException("Writer already closed.");
}
buffer.Prepare(this);
this.EnsureInitialized();
this.EnsureOutputBufferSize(buffer.Length * 5 / 4 + 7200);
byte[] bytes = buffer.Bytes;
int result;
unsafe
{
fixed (byte* bytesPtr = bytes)
{
fixed (byte* outputBufferPtr = this.m_outputBuffer)
{
result = lame_encode_buffer_interleaved(m_handle, (IntPtr)bytesPtr, buffer.Length, (IntPtr)outputBufferPtr, m_outputBuffer.Length);
}
}
}
if (result < 0)
{
switch (result)
{
case -1:
throw new LameException("Output buffer is too small");
case -2:
throw new LameException("malloc problem");
case -3:
throw new LameException("lame_init_params was not called");
case -4:
throw new LameException("Psycho acoustic problems");
default:
throw new LameException("Unknown error");
}
}
if (result > 0)
{
this.m_outputStream.Write(this.m_outputBuffer, 0, result);
}
}
}
}
using System;
using System.Runtime.InteropServices;
using CUETools.Codecs;
using System.IO;
namespace CUETools.Codecs.libmp3lame
{
public class AudioEncoder : IAudioDest
{
private string m_outputPath;
private Stream m_outputStream;
private bool m_closed = false, m_initialized = false;
private IntPtr m_handle;
private uint m_finalSampleCount;
private byte[] m_outputBuffer;
private long m_bytesWritten;
public long FinalSampleCount
{
set
{
if (value > uint.MaxValue)
{
throw new ArgumentException("Input file too big.");
}
this.m_finalSampleCount = (uint)value;
}
}
public string Path
{
get { return this.m_outputPath; }
}
private LameEncoderSettings m_settings;
public virtual AudioEncoderSettings Settings
{
get
{
return m_settings;
}
}
public long BytesWritten => m_bytesWritten;
public AudioEncoder(LameEncoderSettings settings, string path, Stream output = null)
{
this.CheckPCMConfig(settings.PCM);
this.m_settings = settings;
this.m_outputPath = path;
this.m_outputStream = output != null ? output : File.Create(path);
this.m_bytesWritten = 0;
}
private void CheckPCMConfig(AudioPCMConfig pcm)
{
if (pcm.BitsPerSample != 16)
{
throw new ArgumentException("LAME only supports 16 bits/sample.");
}
}
private void FinalizeEncoding()
{
this.EnsureOutputBufferSize(7200);
int flushResult;
unsafe
{
fixed (byte* outputBufferPtr = m_outputBuffer)
{
flushResult = libmp3lamedll.lame_encode_flush(m_handle, (IntPtr)outputBufferPtr, m_outputBuffer.Length);
}
}
if (flushResult < 0)
{
throw new LameException("Unknown flush error");
}
if (flushResult > 0)
{
this.m_outputStream.Write(this.m_outputBuffer, 0, flushResult);
m_bytesWritten += flushResult;
}
int lametagFrameSize = this.GetLametagFrame();
this.m_outputStream.Seek(0, SeekOrigin.Begin);
this.m_outputStream.Write(this.m_outputBuffer, 0, lametagFrameSize);
}
public void Close()
{
if (!this.m_closed)
{
if (this.m_initialized)
{
try
{
try
{
this.FinalizeEncoding();
}
finally
{
libmp3lamedll.lame_close(m_handle);
}
}
finally
{
m_handle = IntPtr.Zero;
if (this.m_outputPath != null)
{
this.m_outputStream.Close();
}
}
}
this.m_closed = true;
}
}
private int GetLametagFrame()
{
while (true)
{
uint lametagFrameResult;
unsafe
{
fixed (byte* outputBufferPtr = m_outputBuffer)
{
lametagFrameResult = libmp3lamedll.lame_get_lametag_frame(this.m_handle, (IntPtr)outputBufferPtr, (uint)m_outputBuffer.Length);
}
}
if (lametagFrameResult < 0)
{
throw new LameException("Error getting lametag frame.");
}
if (lametagFrameResult <= m_outputBuffer.Length)
{
return (int)lametagFrameResult;
}
this.EnsureOutputBufferSize((int)lametagFrameResult);
}
}
public uint GetLametagFrame(byte[] outputBuffer)
{
unsafe
{
fixed (byte* outputBufferPtr = outputBuffer)
{
return libmp3lamedll.lame_get_lametag_frame(m_handle, (IntPtr)outputBufferPtr, (uint)outputBuffer.Length);
}
}
}
private void EnsureInitialized()
{
if (!this.m_initialized)
{
m_handle = libmp3lamedll.lame_init();
libmp3lamedll.lame_set_bWriteVbrTag(m_handle, 1);
libmp3lamedll.lame_set_write_id3tag_automatic(m_handle, 0);
libmp3lamedll.lame_set_num_channels(m_handle, this.Settings.PCM.ChannelCount);
libmp3lamedll.lame_set_in_samplerate(m_handle, this.Settings.PCM.SampleRate);
if (this.m_finalSampleCount != 0)
{
libmp3lamedll.lame_set_num_samples(m_handle, this.m_finalSampleCount);
}
m_settings.Apply(m_handle);
if (libmp3lamedll.lame_init_params(m_handle) != 0)
{
throw new LameException("lame_init_params failed");
}
this.m_initialized = true;
}
}
public void Delete()
{
if (this.m_outputPath == null)
{
throw new InvalidOperationException("This writer was not created from file.");
}
if (!m_closed)
{
this.Close();
File.Delete(this.m_outputPath);
}
}
private void EnsureOutputBufferSize(int requiredSize)
{
if (this.m_outputBuffer == null || this.m_outputBuffer.Length < requiredSize)
{
this.m_outputBuffer = new byte[requiredSize];
}
}
public void Write(AudioBuffer buffer)
{
if (this.m_closed)
{
throw new InvalidOperationException("Writer already closed.");
}
buffer.Prepare(this);
this.EnsureInitialized();
this.EnsureOutputBufferSize(buffer.Length * 5 / 4 + 7200);
byte[] bytes = buffer.Bytes;
int result;
unsafe
{
fixed (byte* bytesPtr = bytes)
{
fixed (byte* outputBufferPtr = this.m_outputBuffer)
{
result = libmp3lamedll.lame_encode_buffer_interleaved(m_handle, (IntPtr)bytesPtr, buffer.Length, (IntPtr)outputBufferPtr, m_outputBuffer.Length);
}
}
}
if (result < 0)
{
switch (result)
{
case -1:
throw new LameException("Output buffer is too small");
case -2:
throw new LameException("malloc problem");
case -3:
throw new LameException("lame_init_params was not called");
case -4:
throw new LameException("Psycho acoustic problems");
default:
throw new LameException("Unknown error");
}
}
if (result > 0)
{
this.m_outputStream.Write(this.m_outputBuffer, 0, result);
m_bytesWritten += result;
}
}
}
}

View File

@@ -1,36 +1,36 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using Newtonsoft.Json;
namespace CUETools.Codecs.LAME
{
[JsonObject(MemberSerialization.OptIn)]
public class CBREncoderSettings : LameEncoderSettings
{
public override string Extension => "mp3";
public override string Name => "libmp3lame-CBR";
public override int Priority => 1;
public static readonly int[] bps_table = new int[] { 96, 128, 192, 256, 320 };
[JsonProperty]
[DefaultValue(LameQuality.High)]
public LameQuality Quality { get; set; }
public CBREncoderSettings()
: base("96 128 192 256 320", "256")
{
}
public override void Apply(IntPtr lame)
{
AudioEncoder.lame_set_VBR(lame, (int)LameVbrMode.Off);
AudioEncoder.lame_set_brate(lame, CBREncoderSettings.bps_table[this.EncoderModeIndex]);
AudioEncoder.lame_set_quality(lame, (int)this.Quality);
}
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using Newtonsoft.Json;
namespace CUETools.Codecs.libmp3lame
{
[JsonObject(MemberSerialization.OptIn)]
public class CBREncoderSettings : LameEncoderSettings
{
public override string Extension => "mp3";
public override string Name => "libmp3lame-CBR";
public override int Priority => 1;
public static readonly int[] bps_table = new int[] { 96, 128, 192, 256, 320 };
[JsonProperty]
[DefaultValue(LameQuality.High)]
public LameQuality Quality { get; set; }
public CBREncoderSettings()
: base("96 128 192 256 320", "256")
{
}
public override void Apply(IntPtr lame)
{
libmp3lamedll.lame_set_VBR(lame, (int)LameVbrMode.Off);
libmp3lamedll.lame_set_brate(lame, CBREncoderSettings.bps_table[this.EncoderModeIndex]);
libmp3lamedll.lame_set_quality(lame, (int)this.Quality);
}
}
}

View File

@@ -1,22 +1,22 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace CUETools.Codecs.LAME
{
public enum LameQuality
{
High = 2,
Normal = 5,
Fast = 7,
}
public enum LameVbrMode
{
Off = 0,
Mt = 1,
Rh = 2,
Abr = 3,
Default = 4,
}
}
using System;
using System.Collections.Generic;
using System.Text;
namespace CUETools.Codecs.libmp3lame
{
public enum LameQuality
{
High = 2,
Normal = 5,
Fast = 7,
}
public enum LameVbrMode
{
Off = 0,
Mt = 1,
Rh = 2,
Abr = 3,
Default = 4,
}
}

View File

@@ -1,21 +1,21 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace CUETools.Codecs.LAME
{
public class LameEncoderSettings : AudioEncoderSettings
{
public override Type EncoderType => typeof(AudioEncoder);
public LameEncoderSettings(string modes, string defaultMode)
: base(modes, defaultMode)
{
}
public virtual void Apply(IntPtr lame)
{
throw new MethodAccessException();
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
namespace CUETools.Codecs.libmp3lame
{
public class LameEncoderSettings : AudioEncoderSettings
{
public override Type EncoderType => typeof(AudioEncoder);
public LameEncoderSettings(string modes, string defaultMode)
: base(modes, defaultMode)
{
}
public virtual void Apply(IntPtr lame)
{
throw new MethodAccessException();
}
}
}

View File

@@ -1,34 +1,34 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using Newtonsoft.Json;
namespace CUETools.Codecs.LAME
{
[JsonObject(MemberSerialization.OptIn)]
public class VBREncoderSettings : LameEncoderSettings
{
public override string Extension => "mp3";
public override string Name => "libmp3lame-VBR";
public override int Priority => 2;
[JsonProperty]
[DefaultValue(LameQuality.High)]
public LameQuality Quality { get; set; }
public VBREncoderSettings()
: base("V9 V8 V7 V6 V5 V4 V3 V2 V1 V0", "V2")
{
}
public override void Apply(IntPtr lame)
{
AudioEncoder.lame_set_VBR(lame, (int)LameVbrMode.Default);
AudioEncoder.lame_set_VBR_quality(lame, 9 - this.EncoderModeIndex);
AudioEncoder.lame_set_quality(lame, (int)this.Quality);
}
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using Newtonsoft.Json;
namespace CUETools.Codecs.libmp3lame
{
[JsonObject(MemberSerialization.OptIn)]
public class VBREncoderSettings : LameEncoderSettings
{
public override string Extension => "mp3";
public override string Name => "libmp3lame-VBR";
public override int Priority => 2;
[JsonProperty]
[DefaultValue(LameQuality.High)]
public LameQuality Quality { get; set; }
public VBREncoderSettings()
: base("V9 V8 V7 V6 V5 V4 V3 V2 V1 V0", "V2")
{
}
public override void Apply(IntPtr lame)
{
libmp3lamedll.lame_set_VBR(lame, (int)LameVbrMode.Default);
libmp3lamedll.lame_set_VBR_quality(lame, 9 - this.EncoderModeIndex);
libmp3lamedll.lame_set_quality(lame, (int)this.Quality);
}
}
}

View File

@@ -0,0 +1,66 @@
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
namespace CUETools.Codecs.libmp3lame
{
class libmp3lamedll
{
private const string DllName = "libmp3lame";
private const CallingConvention LameCallingConvention = CallingConvention.Cdecl;
[DllImport("kernel32.dll")]
private static extern IntPtr LoadLibrary(string dllToLoad);
[DllImport(DllName, CallingConvention = LameCallingConvention)]
internal static extern IntPtr lame_init();
[DllImport(DllName, CallingConvention = LameCallingConvention)]
internal static extern int lame_close(IntPtr handle);
[DllImport(DllName, CallingConvention = LameCallingConvention)]
internal static extern int lame_set_num_channels(IntPtr handle, int channels);
[DllImport(DllName, CallingConvention = LameCallingConvention)]
internal static extern int lame_set_in_samplerate(IntPtr handle, int sampleRate);
[DllImport(DllName, CallingConvention = LameCallingConvention)]
internal static extern int lame_set_quality(IntPtr handle, int quality);
[DllImport(DllName, CallingConvention = LameCallingConvention)]
internal static extern int lame_set_VBR(IntPtr handle, int vbrMode);
[DllImport(DllName, CallingConvention = LameCallingConvention)]
internal static extern int lame_set_VBR_mean_bitrate_kbps(IntPtr handle, int meanBitrate);
[DllImport(DllName, CallingConvention = LameCallingConvention)]
internal static extern int lame_init_params(IntPtr handle);
[DllImport(DllName, CallingConvention = LameCallingConvention)]
internal static extern int lame_set_num_samples(IntPtr handle, uint numSamples);
[DllImport(DllName, CallingConvention = LameCallingConvention)]
internal static extern int lame_encode_buffer_interleaved(IntPtr handle, IntPtr pcm, int num_samples, IntPtr mp3buf, int mp3buf_size);
[DllImport(DllName, CallingConvention = LameCallingConvention)]
internal static extern int lame_encode_flush(IntPtr handle, IntPtr mp3buf, int size);
[DllImport(DllName, CallingConvention = LameCallingConvention)]
internal static extern uint lame_get_lametag_frame(IntPtr handle, IntPtr buffer, uint size);
[DllImport(DllName, CallingConvention = LameCallingConvention)]
internal static extern int lame_set_VBR_quality(IntPtr handle, float vbrQuality);
[DllImport(DllName, CallingConvention = LameCallingConvention)]
internal static extern int lame_set_brate(IntPtr handle, int bitrate);
[DllImport(DllName, CallingConvention = LameCallingConvention)]
internal static extern int lame_set_bWriteVbrTag(IntPtr handle, int writeVbrTag);
[DllImport(DllName, CallingConvention = LameCallingConvention)]
internal static extern int lame_set_write_id3tag_automatic(IntPtr handle, int automaticWriteId3Tag);
static libmp3lamedll()
{
var myPath = new Uri(typeof(libmp3lamedll).Assembly.CodeBase).LocalPath;
var myFolder = System.IO.Path.GetDirectoryName(myPath);
var is64 = IntPtr.Size == 8;
var subfolder = is64 ? "x64" : "win32";
#if NET40
IntPtr Dll = LoadLibrary(System.IO.Path.Combine(myFolder, subfolder, DllName + ".dll"));
#else
IntPtr Dll = LoadLibrary(System.IO.Path.Combine(System.IO.Path.Combine(myFolder, subfolder), DllName + ".dll"));
#endif
if (Dll == IntPtr.Zero)
Dll = LoadLibrary(DllName + ".dll");
if (Dll == IntPtr.Zero)
throw new DllNotFoundException();
}
}
}

View File

@@ -21,7 +21,6 @@ namespace CUETools.Codecs.libwavpack
public DecoderSettings() : base() { }
}
[AudioDecoderClass(typeof(DecoderSettings))]
public unsafe class AudioDecoder : IAudioSource
{
private readonly void* IO_ID_WV = ((IntPtr)1).ToPointer();

View File

@@ -54,7 +54,6 @@ namespace CUETools.Codecs.libwavpack
private int m_extraMode;
};
[AudioEncoderClass(typeof(EncoderSettings))]
public unsafe class AudioEncoder : IAudioDest
{
public AudioEncoder(EncoderSettings settings, string path, Stream output = null)

View File

@@ -1,35 +0,0 @@
using System;
namespace CUETools.Codecs
{
/// <summary>
/// This class provides an attribute for marking
/// classes that provide <see cref="IAudioSource" />.
/// </summary>
/// <remarks>
/// When plugins with classes that provide <see cref="IAudioSource" /> are
/// registered, their <see cref="AudioDecoderClass" /> attributes are read.
/// </remarks>
/// <example>
/// <code lang="C#">using CUETools.Codecs;
///
///[AudioDecoderClass(typeof(MyDecoderSettings))]
///public class MyDecoder : IAudioSource {
/// ...
///}</code>
/// </example>
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public sealed class AudioDecoderClassAttribute : Attribute
{
public Type Settings
{
get;
private set;
}
public AudioDecoderClassAttribute(Type settings)
{
Settings = settings;
}
}
}

View File

@@ -1,35 +0,0 @@
using System;
namespace CUETools.Codecs
{
/// <summary>
/// This class provides an attribute for marking
/// classes that provide <see cref="IAudioDest" />.
/// </summary>
/// <remarks>
/// When plugins with classes that provide <see cref="IAudioDest" /> are
/// registered, their <see cref="AudioEncoderClassAttribute" /> attributes are read.
/// </remarks>
/// <example>
/// <code lang="C#">using CUETools.Codecs;
///
///[AudioEncoderClass(typeof(MyEncoderSettings))]
///public class MyEncoder : IAudioDest {
/// ...
///}</code>
/// </example>
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
public sealed class AudioEncoderClassAttribute : Attribute
{
public Type Settings
{
get;
private set;
}
public AudioEncoderClassAttribute(Type settings)
{
Settings = settings;
}
}
}

View File

@@ -20,7 +20,7 @@ namespace CUETools.Codecs
}
[JsonObject(MemberSerialization.OptIn)]
public class AudioEncoderSettings
public class AudioEncoderSettings : IAudioEncoderSettings
{
[Browsable(false)]
public virtual string Name => null;

View File

@@ -1,4 +1,5 @@
using System;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
@@ -11,83 +12,81 @@ namespace CUETools.Codecs
{
public class CUEToolsCodecsConfig
{
[JsonIgnore]
public Dictionary<string, CUEToolsFormat> formats;
public EncoderListViewModel encoders;
public DecoderListViewModel decoders;
public List<AudioEncoderSettings> encoders;
public List<AudioDecoderSettings> decoders;
[JsonIgnore]
public EncoderListViewModel encodersViewModel;
[JsonIgnore]
public DecoderListViewModel decodersViewModel;
public CUEToolsCodecsConfig()
{
encoders = new List<AudioEncoderSettings>();
decoders = new List<AudioDecoderSettings>();
encodersViewModel = new EncoderListViewModel(encoders);
decodersViewModel = new DecoderListViewModel(decoders);
formats = new Dictionary<string, CUEToolsFormat>();
}
public CUEToolsCodecsConfig(CUEToolsCodecsConfig src)
{
encoders = new EncoderListViewModel();
foreach (var enc in src.encoders)
encoders.Add(enc.Clone());
decoders = new DecoderListViewModel();
foreach (var dec in src.decoders)
decoders.Add(dec.Clone());
encoders = new List<AudioEncoderSettings>();
decoders = new List<AudioDecoderSettings>();
src.encoders.ForEach(item => encoders.Add(item.Clone()));
src.decoders.ForEach(item => decoders.Add(item.Clone()));
encodersViewModel = new EncoderListViewModel(encoders);
decodersViewModel = new DecoderListViewModel(decoders);
formats = new Dictionary<string, CUEToolsFormat>();
foreach (var fmt in src.formats)
formats.Add(fmt.Key, fmt.Value.Clone(this));
}
public CUEToolsCodecsConfig(List<Type> encs, List<Type> decs)
public void Init(List<AudioEncoderSettings> src_encoders, List<AudioDecoderSettings> src_decoders)
{
encoders = new EncoderListViewModel();
foreach (Type type in encs)
foreach (AudioEncoderClassAttribute enc in Attribute.GetCustomAttributes(type, typeof(AudioEncoderClassAttribute)))
try
{
encoders.Add(new AudioEncoderSettingsViewModel(enc));
}
catch (Exception ex)
{
System.Diagnostics.Trace.WriteLine(ex.Message);
}
decoders = new DecoderListViewModel();
foreach (Type type in decs)
foreach (AudioDecoderClassAttribute dec in Attribute.GetCustomAttributes(type, typeof(AudioDecoderClassAttribute)))
try
{
decoders.Add(new AudioDecoderSettingsViewModel(Activator.CreateInstance(dec.Settings) as AudioDecoderSettings));
}
catch (Exception ex)
{
System.Diagnostics.Trace.WriteLine(ex.Message);
}
encoders = new List<AudioEncoderSettings>();
decoders = new List<AudioDecoderSettings>();
src_encoders.ForEach(item => encoders.Add(item.Clone()));
src_decoders.ForEach(item => decoders.Add(item.Clone()));
if (Type.GetType("Mono.Runtime", false) == null)
{
encoders.Add(new AudioEncoderSettingsViewModel("flake", "flac", true, "0 1 2 3 4 5 6 7 8 9 10 11 12", "8", "flake.exe", "-%M - -o %O -p %P"));
encoders.Add(new AudioEncoderSettingsViewModel("takc", "tak", true, "0 1 2 2e 2m 3 3e 3m 4 4e 4m", "2", "takc.exe", "-e -p%M -overwrite - %O"));
encoders.Add(new AudioEncoderSettingsViewModel("ffmpeg alac", "m4a", true, "", "", "ffmpeg.exe", "-i - -f ipod -acodec alac -y %O"));
encoders.Add(new AudioEncoderSettingsViewModel("VBR (lame.exe)", "mp3", false, "V9 V8 V7 V6 V5 V4 V3 V2 V1 V0", "V2", "lame.exe", "--vbr-new -%M - %O"));
encoders.Add(new AudioEncoderSettingsViewModel("CBR (lame.exe)", "mp3", false, "96 128 192 256 320", "256", "lame.exe", "-m s -q 0 -b %M --noreplaygain - %O"));
encoders.Add(new AudioEncoderSettingsViewModel("oggenc", "ogg", false, "-1 -0.5 0 0.5 1 1.5 2 2.5 3 3.5 4 4.5 5 5.5 6 6.5 7 7.5 8", "3", "oggenc.exe", "-q %M - -o %O"));
encoders.Add(new AudioEncoderSettingsViewModel("opusenc", "opus", false, "6 16 32 48 64 96 128 192 256", "128", "opusenc.exe", "--bitrate %M - %O"));
encoders.Add(new AudioEncoderSettingsViewModel("nero aac", "m4a", false, "0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9", "0.4", "neroAacEnc.exe", "-q %M -if - -of %O"));
encoders.Add(new AudioEncoderSettingsViewModel("qaac tvbr", "m4a", false, "10 20 30 40 50 60 70 80 90 100 110 127", "80", "qaac.exe", "-s -V %M -q 2 - -o %O"));
encoders.Add(new CommandLine.EncoderSettings("flake", "flac", true, "0 1 2 3 4 5 6 7 8 9 10 11 12", "8", "flake.exe", "-%M - -o %O -p %P"));
encoders.Add(new CommandLine.EncoderSettings("takc", "tak", true, "0 1 2 2e 2m 3 3e 3m 4 4e 4m", "2", "takc.exe", "-e -p%M -overwrite - %O"));
encoders.Add(new CommandLine.EncoderSettings("ffmpeg alac", "m4a", true, "", "", "ffmpeg.exe", "-i - -f ipod -acodec alac -y %O"));
encoders.Add(new CommandLine.EncoderSettings("VBR (lame.exe)", "mp3", false, "V9 V8 V7 V6 V5 V4 V3 V2 V1 V0", "V2", "lame.exe", "--vbr-new -%M - %O"));
encoders.Add(new CommandLine.EncoderSettings("CBR (lame.exe)", "mp3", false, "96 128 192 256 320", "256", "lame.exe", "-m s -q 0 -b %M --noreplaygain - %O"));
encoders.Add(new CommandLine.EncoderSettings("oggenc", "ogg", false, "-1 -0.5 0 0.5 1 1.5 2 2.5 3 3.5 4 4.5 5 5.5 6 6.5 7 7.5 8", "3", "oggenc.exe", "-q %M - -o %O"));
encoders.Add(new CommandLine.EncoderSettings("opusenc", "opus", false, "6 16 32 48 64 96 128 192 256", "128", "opusenc.exe", "--bitrate %M - %O"));
encoders.Add(new CommandLine.EncoderSettings("nero aac", "m4a", false, "0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9", "0.4", "neroAacEnc.exe", "-q %M -if - -of %O"));
encoders.Add(new CommandLine.EncoderSettings("qaac tvbr", "m4a", false, "10 20 30 40 50 60 70 80 90 100 110 127", "80", "qaac.exe", "-s -V %M -q 2 - -o %O"));
decoders.Add(new AudioDecoderSettingsViewModel(new CommandLine.DecoderSettings("takc", "tak", "takc.exe", "-d %I -")));
decoders.Add(new AudioDecoderSettingsViewModel(new CommandLine.DecoderSettings("ffmpeg alac", "m4a", "ffmpeg.exe", "-v 0 -i %I -f wav -")));
decoders.Add(new CommandLine.DecoderSettings("takc", "tak", "takc.exe", "-d %I -"));
decoders.Add(new CommandLine.DecoderSettings("ffmpeg alac", "m4a", "ffmpeg.exe", "-v 0 -i %I -f wav -"));
}
else
{
// !!!
}
encodersViewModel = new EncoderListViewModel(encoders);
decodersViewModel = new DecoderListViewModel(decoders);
formats = new Dictionary<string, CUEToolsFormat>();
formats.Add("flac", new CUEToolsFormat("flac", CUEToolsTagger.TagLibSharp, true, false, true, true, encoders.GetDefault("flac", true), null, decoders.GetDefault("flac", true)));
formats.Add("wv", new CUEToolsFormat("wv", CUEToolsTagger.TagLibSharp, true, false, true, true, encoders.GetDefault("wv", true), null, decoders.GetDefault("wv", true)));
formats.Add("ape", new CUEToolsFormat("ape", CUEToolsTagger.TagLibSharp, true, false, true, true, encoders.GetDefault("ape", true), null, decoders.GetDefault("ape", true)));
formats.Add("tta", new CUEToolsFormat("tta", CUEToolsTagger.APEv2, true, false, false, true, encoders.GetDefault("tta", true), null, decoders.GetDefault("tta", true)));
formats.Add("m2ts", new CUEToolsFormat("m2ts", CUEToolsTagger.APEv2, true, false, false, true, null, null, decoders.GetDefault("m2ts", true)));
formats.Add("mpls", new CUEToolsFormat("mpls", CUEToolsTagger.APEv2, true, false, false, true, null, null, decoders.GetDefault("mpls", true)));
formats.Add("wav", new CUEToolsFormat("wav", CUEToolsTagger.TagLibSharp, true, false, false, true, encoders.GetDefault("wav", true), null, decoders.GetDefault("wav", true)));
formats.Add("m4a", new CUEToolsFormat("m4a", CUEToolsTagger.TagLibSharp, true, true, false, true, encoders.GetDefault("m4a", true), encoders.GetDefault("m4a", false), decoders.GetDefault("m4a", true)));
formats.Add("tak", new CUEToolsFormat("tak", CUEToolsTagger.APEv2, true, false, true, true, encoders.GetDefault("tak", true), null, decoders.GetDefault("tak", true)));
formats.Add("wma", new CUEToolsFormat("wma", CUEToolsTagger.TagLibSharp, true, true, false, true, encoders.GetDefault("wma", true), encoders.GetDefault("wma", false), decoders.GetDefault("wma", true)));
formats.Add("mp3", new CUEToolsFormat("mp3", CUEToolsTagger.TagLibSharp, false, true, false, true, null, encoders.GetDefault("mp3", false), null));
formats.Add("ogg", new CUEToolsFormat("ogg", CUEToolsTagger.TagLibSharp, false, true, false, true, null, encoders.GetDefault("ogg", false), null));
formats.Add("opus", new CUEToolsFormat("opus", CUEToolsTagger.TagLibSharp, false, true, false, true, null, encoders.GetDefault("opus", false), null));
formats.Add("flac", new CUEToolsFormat("flac", CUEToolsTagger.TagLibSharp, true, false, true, true, encodersViewModel.GetDefault("flac", true), null, decodersViewModel.GetDefault("flac", true)));
formats.Add("wv", new CUEToolsFormat("wv", CUEToolsTagger.TagLibSharp, true, false, true, true, encodersViewModel.GetDefault("wv", true), null, decodersViewModel.GetDefault("wv", true)));
formats.Add("ape", new CUEToolsFormat("ape", CUEToolsTagger.TagLibSharp, true, false, true, true, encodersViewModel.GetDefault("ape", true), null, decodersViewModel.GetDefault("ape", true)));
formats.Add("tta", new CUEToolsFormat("tta", CUEToolsTagger.APEv2, true, false, false, true, encodersViewModel.GetDefault("tta", true), null, decodersViewModel.GetDefault("tta", true)));
formats.Add("m2ts", new CUEToolsFormat("m2ts", CUEToolsTagger.APEv2, true, false, false, true, null, null, decodersViewModel.GetDefault("m2ts", true)));
formats.Add("mpls", new CUEToolsFormat("mpls", CUEToolsTagger.APEv2, true, false, false, true, null, null, decodersViewModel.GetDefault("mpls", true)));
formats.Add("wav", new CUEToolsFormat("wav", CUEToolsTagger.TagLibSharp, true, false, false, true, encodersViewModel.GetDefault("wav", true), null, decodersViewModel.GetDefault("wav", true)));
formats.Add("m4a", new CUEToolsFormat("m4a", CUEToolsTagger.TagLibSharp, true, true, false, true, encodersViewModel.GetDefault("m4a", true), encodersViewModel.GetDefault("m4a", false), decodersViewModel.GetDefault("m4a", true)));
formats.Add("tak", new CUEToolsFormat("tak", CUEToolsTagger.APEv2, true, false, true, true, encodersViewModel.GetDefault("tak", true), null, decodersViewModel.GetDefault("tak", true)));
formats.Add("wma", new CUEToolsFormat("wma", CUEToolsTagger.TagLibSharp, true, true, false, true, encodersViewModel.GetDefault("wma", true), encodersViewModel.GetDefault("wma", false), decodersViewModel.GetDefault("wma", true)));
formats.Add("mp3", new CUEToolsFormat("mp3", CUEToolsTagger.TagLibSharp, false, true, false, true, null, encodersViewModel.GetDefault("mp3", false), null));
formats.Add("ogg", new CUEToolsFormat("ogg", CUEToolsTagger.TagLibSharp, false, true, false, true, null, encodersViewModel.GetDefault("ogg", false), null));
formats.Add("opus", new CUEToolsFormat("opus", CUEToolsTagger.TagLibSharp, false, true, false, true, null, encodersViewModel.GetDefault("opus", false), null));
}
}
}

View File

@@ -34,9 +34,9 @@
public CUEToolsFormat Clone(CUEToolsCodecsConfig cfg)
{
var res = this.MemberwiseClone() as CUEToolsFormat;
if (decoder != null) cfg.decoders.TryGetValue(decoder.decoderSettings.Extension, decoder.Lossless, decoder.decoderSettings.Name, out res.decoder);
if (encoderLossy != null) cfg.encoders.TryGetValue(encoderLossy.settings.Extension, encoderLossy.Lossless, encoderLossy.settings.Name, out res.encoderLossy);
if (encoderLossless != null) cfg.encoders.TryGetValue(encoderLossless.settings.Extension, encoderLossless.Lossless, encoderLossless.settings.Name, out res.encoderLossless);
if (decoder != null) cfg.decodersViewModel.TryGetValue(decoder.Settings.Extension, decoder.Lossless, decoder.Settings.Name, out res.decoder);
if (encoderLossy != null) cfg.encodersViewModel.TryGetValue(encoderLossy.Settings.Extension, encoderLossy.Lossless, encoderLossy.Settings.Name, out res.encoderLossy);
if (encoderLossless != null) cfg.encodersViewModel.TryGetValue(encoderLossless.Settings.Extension, encoderLossless.Lossless, encoderLossless.Settings.Name, out res.encoderLossless);
return res;
}

View File

@@ -22,6 +22,25 @@ namespace CUETools.Codecs.CommandLine
{
}
public EncoderSettings(
string _name,
string _extension,
bool _lossless,
string _supported_modes,
string _default_mode,
string _path,
string _parameters
)
{
name = _name;
extension = _extension;
lossless = _lossless;
SupportedModes = _supported_modes;
EncoderMode = _default_mode;
Path = _path;
Parameters = _parameters;
}
[JsonProperty]
public string name;

View File

@@ -8,7 +8,7 @@ namespace CUETools.Codecs
public class AudioDecoderSettingsViewModel : INotifyPropertyChanged
{
[JsonProperty]
public AudioDecoderSettings decoderSettings = null;
public AudioDecoderSettings Settings = null;
public event PropertyChangedEventHandler PropertyChanged;
@@ -19,14 +19,7 @@ namespace CUETools.Codecs
public AudioDecoderSettingsViewModel(AudioDecoderSettings settings)
{
decoderSettings = settings;
}
public AudioDecoderSettingsViewModel Clone()
{
var res = this.MemberwiseClone() as AudioDecoderSettingsViewModel;
if (decoderSettings != null) res.decoderSettings = decoderSettings.Clone();
return res;
this.Settings = settings;
}
public override string ToString()
@@ -40,14 +33,14 @@ namespace CUETools.Codecs
{
get
{
if (decoderSettings is CommandLine.DecoderSettings)
return (decoderSettings as CommandLine.DecoderSettings).Path;
if (Settings is CommandLine.DecoderSettings)
return (Settings as CommandLine.DecoderSettings).Path;
return "";
}
set
{
if (decoderSettings is CommandLine.DecoderSettings)
(decoderSettings as CommandLine.DecoderSettings).Path = value;
if (Settings is CommandLine.DecoderSettings)
(Settings as CommandLine.DecoderSettings).Path = value;
else throw new InvalidOperationException();
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Path"));
}
@@ -56,14 +49,14 @@ namespace CUETools.Codecs
{
get
{
if (decoderSettings is CommandLine.DecoderSettings)
return (decoderSettings as CommandLine.DecoderSettings).Parameters;
if (Settings is CommandLine.DecoderSettings)
return (Settings as CommandLine.DecoderSettings).Parameters;
return "";
}
set
{
if (decoderSettings is CommandLine.DecoderSettings)
(decoderSettings as CommandLine.DecoderSettings).Parameters = value;
if (Settings is CommandLine.DecoderSettings)
(Settings as CommandLine.DecoderSettings).Parameters = value;
else throw new InvalidOperationException();
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Parameters"));
}
@@ -79,11 +72,11 @@ namespace CUETools.Codecs
public string Name
{
get => decoderSettings.Name;
get => Settings.Name;
set
{
if (decoderSettings is CommandLine.DecoderSettings)
(decoderSettings as CommandLine.DecoderSettings).name = value;
if (Settings is CommandLine.DecoderSettings)
(Settings as CommandLine.DecoderSettings).name = value;
else throw new InvalidOperationException();
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Name"));
}
@@ -91,11 +84,11 @@ namespace CUETools.Codecs
public string Extension
{
get => decoderSettings.Extension;
get => Settings.Extension;
set
{
if (decoderSettings is CommandLine.DecoderSettings)
(decoderSettings as CommandLine.DecoderSettings).extension = value;
if (Settings is CommandLine.DecoderSettings)
(Settings as CommandLine.DecoderSettings).extension = value;
else throw new InvalidOperationException();
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Extension"));
}
@@ -103,10 +96,10 @@ namespace CUETools.Codecs
public string DotExtension => "." + Extension;
public bool CanBeDeleted => decoderSettings is CommandLine.DecoderSettings;
public bool CanBeDeleted => Settings is CommandLine.DecoderSettings;
public bool IsValid =>
(decoderSettings != null)
&& (decoderSettings is CommandLine.DecoderSettings ? (decoderSettings as CommandLine.DecoderSettings).Path != "" : true);
(Settings != null)
&& (Settings is CommandLine.DecoderSettings ? (Settings as CommandLine.DecoderSettings).Path != "" : true);
}
}

View File

@@ -8,7 +8,7 @@ namespace CUETools.Codecs
public class AudioEncoderSettingsViewModel : INotifyPropertyChanged
{
[JsonProperty]
public AudioEncoderSettings settings = null;
public AudioEncoderSettings Settings = null;
public event PropertyChangedEventHandler PropertyChanged;
@@ -17,31 +17,9 @@ namespace CUETools.Codecs
{
}
public AudioEncoderSettingsViewModel(
string _name,
string _extension,
bool _lossless,
string _supported_modes,
string _default_mode,
string _path,
string _parameters
)
public AudioEncoderSettingsViewModel(AudioEncoderSettings settings)
{
settings = new CommandLine.EncoderSettings() { name = _name, extension = _extension, SupportedModes = _supported_modes, EncoderMode = _default_mode, Path = _path, Parameters = _parameters, lossless = _lossless };
}
public AudioEncoderSettingsViewModel(AudioEncoderClassAttribute enc)
{
settings = Activator.CreateInstance(enc.Settings) as AudioEncoderSettings;
if (settings == null)
throw new InvalidOperationException("invalid codec");
}
public AudioEncoderSettingsViewModel Clone()
{
var res = this.MemberwiseClone() as AudioEncoderSettingsViewModel;
if (settings != null) res.settings = settings.Clone();
return res;
this.Settings = settings;
}
public override string ToString()
@@ -55,13 +33,13 @@ namespace CUETools.Codecs
{
get
{
if (settings is CommandLine.EncoderSettings)
return (settings as CommandLine.EncoderSettings).Path;
if (Settings is CommandLine.EncoderSettings)
return (Settings as CommandLine.EncoderSettings).Path;
return "";
}
set
{
var settings = this.settings as CommandLine.EncoderSettings;
var settings = this.Settings as CommandLine.EncoderSettings;
if (settings == null) throw new InvalidOperationException();
settings.Path = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Path"));
@@ -72,13 +50,13 @@ namespace CUETools.Codecs
{
get
{
if (settings is CommandLine.EncoderSettings)
return (settings as CommandLine.EncoderSettings).Parameters;
if (Settings is CommandLine.EncoderSettings)
return (Settings as CommandLine.EncoderSettings).Parameters;
return "";
}
set
{
var settings = this.settings as CommandLine.EncoderSettings;
var settings = this.Settings as CommandLine.EncoderSettings;
if (settings == null) throw new InvalidOperationException();
settings.Parameters = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Parameters"));
@@ -87,10 +65,10 @@ namespace CUETools.Codecs
public bool Lossless
{
get => settings.Lossless;
get => Settings.Lossless;
set
{
var settings = this.settings as CommandLine.EncoderSettings;
var settings = this.Settings as CommandLine.EncoderSettings;
if (settings == null) throw new InvalidOperationException();
settings.lossless = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Lossless"));
@@ -100,10 +78,10 @@ namespace CUETools.Codecs
public string Name
{
get => settings.Name;
get => Settings.Name;
set
{
var settings = this.settings as CommandLine.EncoderSettings;
var settings = this.Settings as CommandLine.EncoderSettings;
if (settings == null) throw new InvalidOperationException();
settings.name = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Name"));
@@ -112,10 +90,10 @@ namespace CUETools.Codecs
public string Extension
{
get => settings.Extension;
get => Settings.Extension;
set
{
var settings = this.settings as CommandLine.EncoderSettings;
var settings = this.Settings as CommandLine.EncoderSettings;
if (settings == null) throw new InvalidOperationException();
settings.extension = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Extension"));
@@ -129,11 +107,11 @@ namespace CUETools.Codecs
get
{
string defaultMode;
return this.settings.GetSupportedModes(out defaultMode);
return this.Settings.GetSupportedModes(out defaultMode);
}
set
{
var settings = this.settings as CommandLine.EncoderSettings;
var settings = this.Settings as CommandLine.EncoderSettings;
if (settings == null) throw new InvalidOperationException();
settings.SupportedModes = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("SupportedModesStr"));
@@ -150,16 +128,16 @@ namespace CUETools.Codecs
if (modes == null || modes.Length < 2)
return -1;
for (int i = 0; i < modes.Length; i++)
if (modes[i] == this.settings.EncoderMode)
if (modes[i] == this.Settings.EncoderMode)
return i;
return -1;
}
}
public bool CanBeDeleted => settings is CommandLine.EncoderSettings;
public bool CanBeDeleted => Settings is CommandLine.EncoderSettings;
public bool IsValid =>
(settings != null)
&& (settings is CommandLine.EncoderSettings ? (settings as CommandLine.EncoderSettings).Path != "" : true);
(Settings != null)
&& (Settings is CommandLine.EncoderSettings ? (Settings as CommandLine.EncoderSettings).Path != "" : true);
}
}

View File

@@ -1,26 +1,33 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
namespace CUETools.Codecs
{
public class DecoderListViewModel : BindingList<AudioDecoderSettingsViewModel>
{
public DecoderListViewModel()
private List<AudioDecoderSettings> model;
public DecoderListViewModel(List<AudioDecoderSettings> model)
: base()
{
this.model = model;
model.ForEach(item => Add(new AudioDecoderSettingsViewModel(item)));
AddingNew += OnAddingNew;
}
private void OnAddingNew(object sender, AddingNewEventArgs e)
{
e.NewObject = new AudioDecoderSettingsViewModel(new CommandLine.DecoderSettings("new", "wav", "", ""));
var item = new CommandLine.DecoderSettings("new", "wav", "", "");
model.Add(item);
e.NewObject = new AudioDecoderSettingsViewModel(item);
}
public bool TryGetValue(string extension, bool lossless, string name, out AudioDecoderSettingsViewModel result)
{
foreach (AudioDecoderSettingsViewModel udc in this)
{
if (udc.decoderSettings.Extension == extension && udc.decoderSettings.Lossless == lossless && udc.decoderSettings.Name == name)
if (udc.Settings.Extension == extension && udc.Settings.Lossless == lossless && udc.Settings.Name == name)
{
result = udc;
return true;
@@ -35,7 +42,7 @@ namespace CUETools.Codecs
AudioDecoderSettingsViewModel result = null;
foreach (AudioDecoderSettingsViewModel udc in this)
{
if (udc.decoderSettings.Extension == extension && udc.decoderSettings.Lossless == lossless && (result == null || result.decoderSettings.Priority < udc.decoderSettings.Priority))
if (udc.Settings.Extension == extension && udc.Settings.Lossless == lossless && (result == null || result.Settings.Priority < udc.Settings.Priority))
{
result = udc;
}

View File

@@ -1,19 +1,26 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
namespace CUETools.Codecs
{
public class EncoderListViewModel : BindingList<AudioEncoderSettingsViewModel>
{
public EncoderListViewModel()
private List<AudioEncoderSettings> model;
public EncoderListViewModel(List<AudioEncoderSettings> model)
: base()
{
this.model = model;
model.ForEach(item => Add(new AudioEncoderSettingsViewModel(item)));
AddingNew += OnAddingNew;
}
private void OnAddingNew(object sender, AddingNewEventArgs e)
{
e.NewObject = new AudioEncoderSettingsViewModel("new", "wav", true, "", "", "", "");
var item = new CommandLine.EncoderSettings("new", "wav", true, "", "", "", "");
model.Add(item);
e.NewObject = new AudioEncoderSettingsViewModel(item);
}
public bool TryGetValue(string extension, bool lossless, string name, out AudioEncoderSettingsViewModel result)
@@ -21,7 +28,7 @@ namespace CUETools.Codecs
//result = this.Where(udc => udc.settings.Extension == extension && udc.settings.Lossless == lossless && udc.settings.Name == name).First();
foreach (AudioEncoderSettingsViewModel udc in this)
{
if (udc.settings.Extension == extension && udc.settings.Lossless == lossless && udc.settings.Name == name)
if (udc.Settings.Extension == extension && udc.Settings.Lossless == lossless && udc.Settings.Name == name)
{
result = udc;
return true;
@@ -36,7 +43,7 @@ namespace CUETools.Codecs
AudioEncoderSettingsViewModel result = null;
foreach (AudioEncoderSettingsViewModel udc in this)
{
if (udc.settings.Extension == extension && udc.settings.Lossless == lossless && (result == null || result.settings.Priority < udc.settings.Priority))
if (udc.Settings.Extension == extension && udc.Settings.Lossless == lossless && (result == null || result.Settings.Priority < udc.Settings.Priority))
{
result = udc;
}

View File

@@ -3,7 +3,6 @@ using System.IO;
namespace CUETools.Codecs.WAV
{
[AudioDecoderClass(typeof(DecoderSettings))]
public class AudioDecoder : IAudioSource
{
Stream _IO;

View File

@@ -4,7 +4,6 @@ using System.IO;
namespace CUETools.Codecs.WAV
{
[AudioEncoderClass(typeof(EncoderSettings))]
public class AudioEncoder : IAudioDest
{
private Stream _IO;

View File

@@ -30,7 +30,7 @@ namespace CUETools.Converter
{
AudioEncoderSettingsViewModel tmpEncoder;
return chosenEncoder != null ?
(config.encoders.TryGetValue(fmt.extension, lossless, chosenEncoder, out tmpEncoder) ? tmpEncoder : null) :
(config.encodersViewModel.TryGetValue(fmt.extension, lossless, chosenEncoder, out tmpEncoder) ? tmpEncoder : null) :
(lossless ? fmt.encoderLossless : fmt.encoderLossy);
}
@@ -47,16 +47,16 @@ namespace CUETools.Converter
throw new Exception("Unsupported audio type: " + path);
var decoder = fmt.decoder;
if (chosenDecoder != null && !config.decoders.TryGetValue(fmt.extension, true, chosenDecoder, out decoder))
if (chosenDecoder != null && !config.decodersViewModel.TryGetValue(fmt.extension, true, chosenDecoder, out decoder))
throw new Exception("Unknown audio decoder " + chosenDecoder + " or unsupported audio type " + fmt.extension);
if (decoder == null)
throw new Exception("Unsupported audio type: " + path);
var settings = fmt.decoder.decoderSettings.Clone();
var settings = fmt.decoder.Settings.Clone();
try
{
object src = Activator.CreateInstance(decoder.decoderSettings.DecoderType, settings, path, IO);
object src = Activator.CreateInstance(decoder.Settings.DecoderType, settings, path, IO);
if (src == null || !(src is IAudioSource))
throw new Exception("Unsupported audio type: " + path + ": " + decoder.decoderSettings.DecoderType.FullName);
throw new Exception("Unsupported audio type: " + path + ": " + decoder.Settings.DecoderType.FullName);
return src as IAudioSource;
}
catch (System.Reflection.TargetInvocationException ex)
@@ -133,7 +133,8 @@ namespace CUETools.Converter
DateTime start = DateTime.Now;
TimeSpan lastPrint = TimeSpan.FromMilliseconds(0);
CUEToolsCodecsConfig config = new CUEConfig();
var config = new CUEConfigAdvanced();
config.Init();
#if !DEBUG
try
@@ -186,12 +187,12 @@ namespace CUETools.Converter
Program.GetEncoder(config, fmt, true, encoderName) ?? Program.GetEncoder(config, fmt, false, encoderName);
if (encoder == null)
{
var lst = new List<AudioEncoderSettingsViewModel>(config.encoders).FindAll(
var lst = new List<AudioEncoderSettingsViewModel>(config.encodersViewModel).FindAll(
e => e.Extension == fmt.extension && (audioEncoderType == AudioEncoderType.NoAudio || audioEncoderType == (e.Lossless ? AudioEncoderType.Lossless : AudioEncoderType.Lossy))).
ConvertAll(e => e.Name + (e.Lossless ? " (lossless)" : " (lossy)"));
throw new Exception("Encoders available for format " + fmt.extension + ": " + (lst.Count == 0 ? "none" : string.Join(", ", lst.ToArray())));
}
var settings = encoder.settings.Clone();
var settings = encoder.Settings.Clone();
settings.PCM = audioSource.PCM;
settings.Padding = padding;
settings.EncoderMode = encoderMode ?? settings.EncoderMode;

View File

@@ -25,12 +25,12 @@ namespace CUETools.Processor
throw new Exception("Unsupported audio type: " + path);
if (fmt.decoder == null)
throw new Exception("Unsupported audio type: " + path);
var settings = fmt.decoder.decoderSettings.Clone();
var settings = fmt.decoder.Settings.Clone();
try
{
object src = Activator.CreateInstance(fmt.decoder.decoderSettings.DecoderType, settings, path, IO);
object src = Activator.CreateInstance(fmt.decoder.Settings.DecoderType, settings, path, IO);
if (src == null || !(src is IAudioSource))
throw new Exception("Unsupported audio type: " + path + ": " + fmt.decoder.decoderSettings.DecoderType.FullName);
throw new Exception("Unsupported audio type: " + path + ": " + fmt.decoder.Settings.DecoderType.FullName);
return src as IAudioSource;
}
catch (System.Reflection.TargetInvocationException ex)
@@ -60,7 +60,7 @@ namespace CUETools.Processor
null;
if (encoder == null)
throw new Exception("Unsupported audio type: " + path);
var settings = encoder.settings.Clone();
var settings = encoder.Settings.Clone();
settings.PCM = pcm;
settings.Padding = padding;
object o;

View File

@@ -12,7 +12,7 @@ using System.Linq;
namespace CUETools.Processor
{
public class CUEConfig : CUEToolsCodecsConfig
public class CUEConfig
{
public uint fixOffsetMinimumConfidence;
public uint fixOffsetMinimumTracksPercent;
@@ -71,11 +71,12 @@ namespace CUETools.Processor
public bool CopyAlbumArt { get; set; }
public string ArLogFilenameFormat { get; set; }
public string AlArtFilenameFormat { get; set; }
public EncoderListViewModel Encoders => encoders;
public DecoderListViewModel Decoders => decoders;
public EncoderListViewModel Encoders => advanced.encodersViewModel;
public DecoderListViewModel Decoders => advanced.decodersViewModel;
public Dictionary<string, CUEToolsFormat> formats => advanced.formats;
public CUEConfig()
: base(CUEProcessorPlugins.encs, CUEProcessorPlugins.decs)
: base()
{
fixOffsetMinimumConfidence = 2;
fixOffsetMinimumTracksPercent = 51;
@@ -136,6 +137,7 @@ namespace CUETools.Processor
gapsHandling = CUEStyle.GapsAppended;
advanced = new CUEConfigAdvanced();
advanced.Init();
language = Thread.CurrentThread.CurrentUICulture.Name;
@@ -155,7 +157,6 @@ namespace CUETools.Processor
}
public CUEConfig(CUEConfig src)
: base(src)
{
fixOffsetMinimumConfidence = src.fixOffsetMinimumConfidence;
fixOffsetMinimumTracksPercent = src.fixOffsetMinimumTracksPercent;
@@ -296,33 +297,13 @@ namespace CUETools.Processor
sw.Save("AlArtFilenameFormat", AlArtFilenameFormat);
sw.SaveText("Advanced", JsonConvert.SerializeObject(advanced,
Newtonsoft.Json.Formatting.Indented,
new JsonSerializerSettings
{
DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate
}));
sw.SaveText("Encoders", JsonConvert.SerializeObject(encoders,
Newtonsoft.Json.Formatting.Indented,
new JsonSerializerSettings
{
DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate,
TypeNameHandling = TypeNameHandling.Auto
TypeNameHandling = TypeNameHandling.Auto,
}));
int nDecoders = 0;
foreach (var decoder in decoders)
if (decoder.decoderSettings is Codecs.CommandLine.DecoderSettings)
{
var settings = decoder.decoderSettings as Codecs.CommandLine.DecoderSettings;
sw.Save(string.Format("ExternalDecoder{0}Name", nDecoders), settings.Name);
sw.Save(string.Format("ExternalDecoder{0}Extension", nDecoders), settings.Extension);
sw.Save(string.Format("ExternalDecoder{0}Path", nDecoders), settings.Path);
sw.Save(string.Format("ExternalDecoder{0}Parameters", nDecoders), settings.Parameters);
nDecoders++;
}
sw.Save("ExternalDecoders", nDecoders);
int nFormats = 0;
foreach (KeyValuePair<string, CUEToolsFormat> format in formats)
{
@@ -415,100 +396,56 @@ namespace CUETools.Processor
separateDecodingThread = sr.LoadBoolean("SeparateDecodingThread") ?? separateDecodingThread;
try
var jsonConfig = sr.Load("Advanced");
if (jsonConfig != null)
{
var jsonObject = JsonConvert.DeserializeObject(sr.Load("Advanced"),
typeof(CUEConfigAdvanced),
new JsonSerializerSettings { DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate
});
if (jsonObject as CUEConfigAdvanced == null)
throw new Exception();
advanced = jsonObject as CUEConfigAdvanced;
}
catch (Exception ex)
{
System.Diagnostics.Trace.WriteLine(ex.Message);
}
var encodersBackup = encoders;
try
{
var jsonObject = JsonConvert.DeserializeObject(sr.Load("Encoders"),
typeof(EncoderListViewModel),
new JsonSerializerSettings {
DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate,
TypeNameHandling = TypeNameHandling.Auto
});
if (jsonObject as EncoderListViewModel == null)
throw new Exception();
encoders = jsonObject as EncoderListViewModel;
encoders.Where(x => !x.IsValid).ToList().ForEach(x => encoders.Remove(x));
AudioEncoderSettingsViewModel tmp;
encodersBackup.Where(x => !encoders.TryGetValue(x.Extension, x.Lossless, x.Name, out tmp)).ToList().ForEach(x => encoders.Add(x));
}
catch (Exception ex)
{
System.Diagnostics.Trace.WriteLine(ex.Message);
}
//int totalEncoders = sr.LoadInt32("ExternalEncoders", 0, null) ?? 0;
//for (int nEncoders = 0; nEncoders < totalEncoders; nEncoders++)
//{
// string name = sr.Load(string.Format("ExternalEncoder{0}Name", nEncoders));
// string extension = sr.Load(string.Format("ExternalEncoder{0}Extension", nEncoders));
// string settings = sr.Load(string.Format("ExternalEncoder{0}Settings", nEncoders));
// bool lossless = sr.LoadBoolean(string.Format("ExternalEncoder{0}Lossless", nEncoders)) ?? true;
// CUEToolsUDC encoder;
// if (name == null || extension == null) continue;
// if (!encoders.TryGetValue(extension, lossless, name, out encoder))
// {
// encoder = new CUEToolsUDC(name, extension, lossless, "", "", "", "");
// encoders.Add(encoder);
// }
// try
// {
// if (settings != null)
// {
// var encoderSettings = JsonConvert.DeserializeObject(settings,
// encoder.settings.GetType(),
// new JsonSerializerSettings { DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate });
// if (encoderSettings as AudioEncoderSettings == null)
// throw new Exception();
// encoder.settings = encoderSettings as AudioEncoderSettings;
// if (encoder.settings is UserDefinedEncoderSettings && (encoder.settings as UserDefinedEncoderSettings).Path == "")
// throw new Exception();
// }
// }
// catch (Exception ex)
// {
// System.Diagnostics.Trace.WriteLine(ex.Message);
// if (version == 203 && encoder.settings is UserDefinedEncoderSettings)
// {
// (encoder.settings as UserDefinedEncoderSettings).SupportedModes = sr.Load(string.Format("ExternalEncoder{0}Modes", nEncoders));
// (encoder.settings as UserDefinedEncoderSettings).EncoderMode = sr.Load(string.Format("ExternalEncoder{0}Mode", nEncoders));
// (encoder.settings as UserDefinedEncoderSettings).Path = sr.Load(string.Format("ExternalEncoder{0}Path", nEncoders));
// (encoder.settings as UserDefinedEncoderSettings).Parameters = sr.Load(string.Format("ExternalEncoder{0}Parameters", nEncoders));
// }
// else
// encoders.Remove(encoder);
// }
//}
int totalDecoders = sr.LoadInt32("ExternalDecoders", 0, null) ?? 0;
for (int nDecoders = 0; nDecoders < totalDecoders; nDecoders++)
{
string name = sr.Load(string.Format("ExternalDecoder{0}Name", nDecoders));
string extension = sr.Load(string.Format("ExternalDecoder{0}Extension", nDecoders));
string path = sr.Load(string.Format("ExternalDecoder{0}Path", nDecoders));
string parameters = sr.Load(string.Format("ExternalDecoder{0}Parameters", nDecoders));
AudioDecoderSettingsViewModel decoder;
if (!decoders.TryGetValue(extension, true, name, out decoder))
decoders.Add(new AudioDecoderSettingsViewModel(new Codecs.CommandLine.DecoderSettings(name, extension, path, parameters)));
else
var backup = advanced;
try
{
decoder.Extension = extension;
decoder.Path = path;
decoder.Parameters = parameters;
var jsonObject = JsonConvert.DeserializeObject(jsonConfig,
typeof(CUEConfigAdvanced),
new JsonSerializerSettings
{
DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate,
TypeNameHandling = TypeNameHandling.Auto,
});
if (jsonObject as CUEConfigAdvanced == null)
throw new Exception();
advanced = jsonObject as CUEConfigAdvanced;
// Add missing codecs
backup.encoders.Where(x => advanced.encoders
.FindAll(y => y.Extension == x.Extension && y.Lossless == x.Lossless && y.Name == x.Name).Count == 0)
.ToList().ForEach(x => advanced.encoders.Add(x));
backup.decoders.Where(x => advanced.decoders
.FindAll(y => y.Extension == x.Extension && y.Lossless == x.Lossless && y.Name == x.Name).Count == 0)
.ToList().ForEach(x => advanced.decoders.Add(x));
// Reset the ViewModel
advanced.encodersViewModel = new EncoderListViewModel(advanced.encoders);
advanced.decodersViewModel = new DecoderListViewModel(advanced.decoders);
// Reset the links in formats
foreach (var extension in formats.Keys)
{
var format = formats[extension];
AudioEncoderSettingsViewModel encoderLossless, encoderLossy;
AudioDecoderSettingsViewModel decoder;
if (format.encoderLossless == null || !Encoders.TryGetValue(extension, true, format.encoderLossless.Name, out encoderLossless))
encoderLossless = Encoders.GetDefault(extension, true);
if (format.encoderLossy == null || !Encoders.TryGetValue(extension, false, format.encoderLossy.Name, out encoderLossy))
encoderLossy = Encoders.GetDefault(extension, false);
if (format.decoder == null || !Decoders.TryGetValue(extension, true, format.decoder.Name, out decoder))
decoder = Decoders.GetDefault(extension, true);
format.encoderLossless = encoderLossless;
format.encoderLossy = encoderLossy;
format.decoder = decoder;
}
}
catch (Exception ex)
{
System.Diagnostics.Trace.WriteLine(ex.Message);
advanced = backup;
}
}
@@ -526,12 +463,12 @@ namespace CUETools.Processor
CUEToolsFormat format;
AudioEncoderSettingsViewModel udcLossless, udcLossy;
AudioDecoderSettingsViewModel udcDecoder;
if (encoderLossless == "" || !encoders.TryGetValue(extension, true, encoderLossless, out udcLossless))
udcLossless = encoders.GetDefault(extension, true);
if (encoderLossy == "" || !encoders.TryGetValue(extension, false, encoderLossy, out udcLossy))
udcLossy = encoders.GetDefault(extension, false);
if (decoder == "" || !decoders.TryGetValue(extension, true, decoder, out udcDecoder))
udcDecoder = decoders.GetDefault(extension, true);
if (encoderLossless == "" || !Encoders.TryGetValue(extension, true, encoderLossless, out udcLossless))
udcLossless = Encoders.GetDefault(extension, true);
if (encoderLossy == "" || !Encoders.TryGetValue(extension, false, encoderLossy, out udcLossy))
udcLossy = Encoders.GetDefault(extension, false);
if (decoder == "" || !Decoders.TryGetValue(extension, true, decoder, out udcDecoder))
udcDecoder = Decoders.GetDefault(extension, true);
if (!formats.TryGetValue(extension, out format))
formats.Add(extension, new CUEToolsFormat(extension, tagger, allowLossless, allowLossy, allowEmbed, false, udcLossless, udcLossy, udcDecoder));
else

View File

@@ -1,10 +1,11 @@
using System;
using CUETools.Codecs;
using System;
using System.ComponentModel;
namespace CUETools.Processor
{
[Serializable]
public class CUEConfigAdvanced
public class CUEConfigAdvanced : CUEToolsCodecsConfig
{
public enum ProxyMode
{
@@ -38,6 +39,11 @@ namespace CUETools.Processor
}
}
public void Init()
{
Init(CUEProcessorPlugins.encs, CUEProcessorPlugins.decs);
}
[DefaultValue("i"), Category("Freedb"), DisplayName("Email user")]
public string FreedbUser { get; set; }

View File

@@ -11,8 +11,8 @@ namespace CUETools.Processor
{
public static class CUEProcessorPlugins
{
public static List<Type> encs;
public static List<Type> decs;
public static List<AudioEncoderSettings> encs;
public static List<AudioDecoderSettings> decs;
public static List<Type> arcp;
public static List<string> arcp_fmt;
public static Type hdcd;
@@ -20,13 +20,13 @@ namespace CUETools.Processor
static CUEProcessorPlugins()
{
encs = new List<Type>();
decs = new List<Type>();
encs = new List<AudioEncoderSettings>();
decs = new List<AudioDecoderSettings>();
arcp = new List<Type>();
arcp_fmt = new List<string>();
encs.Add(typeof(CUETools.Codecs.WAV.AudioEncoder));
decs.Add(typeof(CUETools.Codecs.WAV.AudioDecoder));
encs.Add(new Codecs.WAV.EncoderSettings());
decs.Add(new Codecs.WAV.DecoderSettings());
//ApplicationSecurityInfo asi = new ApplicationSecurityInfo(AppDomain.CurrentDomain.ActivationContext);
//string arch = asi.ApplicationId.ProcessorArchitecture;
@@ -67,14 +67,14 @@ namespace CUETools.Processor
{
try
{
if (Attribute.GetCustomAttribute(type, typeof(AudioDecoderClassAttribute)) != null)
if (!type.IsClass || type.IsAbstract) continue;
if (type.GetInterface(typeof(IAudioDecoderSettings).Name) != null && type != typeof(AudioDecoderSettings))
{
decs.Add(type);
decs.Add(Activator.CreateInstance(type) as AudioDecoderSettings);
}
//if (type.IsClass && !type.IsAbstract && typeof(IAudioDest).IsAssignableFrom(type))
if (Attribute.GetCustomAttributes(type, typeof(AudioEncoderClassAttribute)).Length > 0)
if (type.GetInterface(typeof(IAudioEncoderSettings).Name) != null && type != typeof(AudioEncoderSettings))
{
encs.Add(type);
encs.Add(Activator.CreateInstance(type) as AudioEncoderSettings);
}
CompressionProviderClass archclass = Attribute.GetCustomAttribute(type, typeof(CompressionProviderClass)) as CompressionProviderClass;
if (archclass != null)
@@ -87,7 +87,7 @@ namespace CUETools.Processor
{
hdcd = type;
}
if (type.IsClass && !type.IsAbstract && typeof(ICDRipper).IsAssignableFrom(type))
if (type.GetInterface(typeof(ICDRipper).Name) != null)
{
ripper = type;
}

View File

@@ -788,7 +788,7 @@ namespace CUETools.Processor
else
{
TagLib.File fileInfo;
TagLib.UserDefined.AdditionalFileTypes.Config = _config;
TagLib.UserDefined.AdditionalFileTypes.Config = _config.advanced;
TagLib.File.IFileAbstraction file = new TagLib.File.LocalFileAbstraction(path);
fileInfo = TagLib.File.Create(file);
NameValueCollection tags = Tagging.Analyze(fileInfo);
@@ -2195,7 +2195,7 @@ namespace CUETools.Processor
}
else
{
TagLib.UserDefined.AdditionalFileTypes.Config = _config;
TagLib.UserDefined.AdditionalFileTypes.Config = _config.advanced;
TagLib.File.IFileAbstraction file = _isArchive
? (TagLib.File.IFileAbstraction)new ArchiveFileAbstraction(this, path)
: (TagLib.File.IFileAbstraction)new TagLib.File.LocalFileAbstraction(path);
@@ -2668,9 +2668,9 @@ namespace CUETools.Processor
if (_audioEncoderType != AudioEncoderType.NoAudio)
{
NameValueCollection tags = GenerateAlbumTags(bestOffset, OutputStyle == CUEStyle.SingleFileWithCUE, _ripperLog ?? _eacLog);
TagLib.UserDefined.AdditionalFileTypes.Config = _config;
TagLib.UserDefined.AdditionalFileTypes.Config = _config.advanced;
TagLib.File fileInfo = TagLib.File.Create(new TagLib.File.LocalFileAbstraction(_destPaths[0]));
if (Tagging.UpdateTags(fileInfo, tags, _config, _config.advanced.UseId3v24))
if (Tagging.UpdateTags(fileInfo, tags, _config.advanced, _config.advanced.UseId3v24))
{
TagLib.File sourceFileInfo = _tracks[0]._fileInfo ?? _fileInfo;
@@ -2754,9 +2754,9 @@ namespace CUETools.Processor
{
string path = _destPaths[iTrack + (htoaToFile ? 1 : 0)];
NameValueCollection tags = GenerateTrackTags(iTrack, bestOffset);
TagLib.UserDefined.AdditionalFileTypes.Config = _config;
TagLib.UserDefined.AdditionalFileTypes.Config = _config.advanced;
TagLib.File fileInfo = TagLib.File.Create(new TagLib.File.LocalFileAbstraction(path));
if (Tagging.UpdateTags(fileInfo, tags, _config, _config.advanced.UseId3v24))
if (Tagging.UpdateTags(fileInfo, tags, _config.advanced, _config.advanced.UseId3v24))
{
TagLib.File sourceFileInfo = _tracks[iTrack]._fileInfo ?? _fileInfo;
@@ -3033,7 +3033,7 @@ namespace CUETools.Processor
NameValueCollection tags = Tagging.Analyze(_fileInfo);
CleanupTags(tags, "ACCURATERIP");
GenerateAccurateRipTags(tags, bestOffset, -1);
if (Tagging.UpdateTags(_fileInfo, tags, _config, _config.advanced.UseId3v24))
if (Tagging.UpdateTags(_fileInfo, tags, _config.advanced, _config.advanced.UseId3v24))
_fileInfo.Save();
}
else if (_hasTrackFilenames)
@@ -3043,7 +3043,7 @@ namespace CUETools.Processor
NameValueCollection tags = Tagging.Analyze(_tracks[iTrack]._fileInfo);
CleanupTags(tags, "ACCURATERIP");
GenerateAccurateRipTags(tags, bestOffset, iTrack);
if (Tagging.UpdateTags(_tracks[iTrack]._fileInfo, tags, _config, _config.advanced.UseId3v24))
if (Tagging.UpdateTags(_tracks[iTrack]._fileInfo, tags, _config.advanced, _config.advanced.UseId3v24))
_tracks[iTrack]._fileInfo.Save();
}
}
@@ -3059,7 +3059,7 @@ namespace CUETools.Processor
CleanupTags(tags, "CTDBDISCCONFIDENCE");
CleanupTags(tags, "CTDBTRACKCONFIDENCE");
GenerateCTDBTags(tags, -1);
if (Tagging.UpdateTags(_fileInfo, tags, _config, _config.advanced.UseId3v24))
if (Tagging.UpdateTags(_fileInfo, tags, _config.advanced, _config.advanced.UseId3v24))
_fileInfo.Save();
}
else if (_hasTrackFilenames)
@@ -3070,7 +3070,7 @@ namespace CUETools.Processor
CleanupTags(tags, "CTDBDISCCONFIDENCE");
CleanupTags(tags, "CTDBTRACKCONFIDENCE");
GenerateCTDBTags(tags, iTrack);
if (Tagging.UpdateTags(_tracks[iTrack]._fileInfo, tags, _config, _config.advanced.UseId3v24))
if (Tagging.UpdateTags(_tracks[iTrack]._fileInfo, tags, _config.advanced, _config.advanced.UseId3v24))
_tracks[iTrack]._fileInfo.Save();
}
}
@@ -3687,7 +3687,7 @@ namespace CUETools.Processor
{
if (fileGroup.type == FileGroupInfoType.FileWithCUE)
{
TagLib.UserDefined.AdditionalFileTypes.Config = _config;
TagLib.UserDefined.AdditionalFileTypes.Config = _config.advanced;
TagLib.File.IFileAbstraction fileAbsraction = new TagLib.File.LocalFileAbstraction(fileGroup.main.FullName);
TagLib.File fileInfo = TagLib.File.Create(fileAbsraction);
return Tagging.Analyze(fileInfo).Get("CUESHEET");
@@ -4199,7 +4199,7 @@ namespace CUETools.Processor
string cueFound = null;
CDImageLayout tocFound = null;
TimeSpan dur = TimeSpan.Zero;
TagLib.UserDefined.AdditionalFileTypes.Config = _config;
TagLib.UserDefined.AdditionalFileTypes.Config = _config.advanced;
TagLib.File.IFileAbstraction fileAbsraction = new TagLib.File.LocalFileAbstraction(file.FullName);
try
{

View File

@@ -36,7 +36,7 @@ namespace CUETools.eac3to
{
AudioEncoderSettingsViewModel tmpEncoder;
return chosenEncoder != null ?
(config.encoders.TryGetValue(fmt.extension, lossless, chosenEncoder, out tmpEncoder) ? tmpEncoder : null) :
(config.encodersViewModel.TryGetValue(fmt.extension, lossless, chosenEncoder, out tmpEncoder) ? tmpEncoder : null) :
(lossless ? fmt.encoderLossless : fmt.encoderLossy);
}
@@ -115,7 +115,8 @@ namespace CUETools.eac3to
DateTime start = DateTime.Now;
TimeSpan lastPrint = TimeSpan.FromMilliseconds(0);
CUEToolsCodecsConfig config = new CUEConfig();
var config = new CUEConfigAdvanced();
config.Init();
#if !DEBUG
try
@@ -314,7 +315,7 @@ namespace CUETools.eac3to
if (stream - chapterStreams - videos.Count > audios.Count)
throw new Exception(string.Format("The source file doesn't contain a track with the number {0}.", stream));
ushort pid = audios[stream - chapterStreams - videos.Count - 1].pid;
(audioSource.Settings as BDLPCMDecoderSettings).Pid = pid;
(audioSource.Settings as Codecs.MPLS.DecoderSettings).Pid = pid;
}
}
@@ -353,13 +354,13 @@ namespace CUETools.eac3to
Program.GetEncoder(config, fmt, true, encoderName) ?? Program.GetEncoder(config, fmt, false, encoderName);
if (encoder == null)
{
var lst = new List<AudioEncoderSettingsViewModel>(config.encoders).FindAll(
var lst = new List<AudioEncoderSettingsViewModel>(config.encodersViewModel).FindAll(
e => e.Extension == fmt.extension && (audioEncoderType == AudioEncoderType.NoAudio || audioEncoderType == (e.Lossless ? AudioEncoderType.Lossless : AudioEncoderType.Lossy))).
ConvertAll(e => e.Name + (e.Lossless ? " (lossless)" : " (lossy)"));
throw new Exception("Encoders available for format " + fmt.extension + ": " + (lst.Count == 0 ? "none" : string.Join(", ", lst.ToArray())));
}
Console.Error.WriteLine("Output {0} : {1}", stream, destFile);
var settings = encoder.settings.Clone();
var settings = encoder.Settings.Clone();
settings.PCM = audioSource.PCM;
settings.Padding = padding;
settings.EncoderMode = encoderMode ?? settings.EncoderMode;

View File

@@ -133,7 +133,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CUEPlayer", "..\CUEPlayer\C
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CUETools.Codecs.CoreAudio", "..\CUETools.Codecs.CoreAudio\CUETools.Codecs.CoreAudio.csproj", "{FAD09EE2-D6B2-4A8E-9F1C-2A9FB293661A}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CUETools.Codecs.LAME", "..\CUETools.Codecs.LAME\CUETools.Codecs.LAME.csproj", "{1AF02E2C-2CB2-44B5-B417-37653071FEC6}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CUETools.Codecs.libmp3lame", "..\CUETools.Codecs.libmp3lame\CUETools.Codecs.libmp3lame.csproj", "{1AF02E2C-2CB2-44B5-B417-37653071FEC6}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CUETools.Codecs.DirectSound", "..\CUETools.Codecs.DirectSound\CUETools.Codecs.DirectSound.csproj", "{5A9FB016-6388-475D-AB33-6F86AD49FDAD}"
EndProject
@@ -193,8 +193,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libwavpack", "..\ThirdParty
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wavpackdll", "..\ThirdParty\WavPack\wavpackdll\wavpackdll.vcxproj", "{1A87F412-BA74-4DBB-9F77-FD55C042FB63}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ttadll", "..\ThirdParty\libtta\ttaddl.vcxproj", "{083CE608-B3E8-4E3E-871E-1144F8F751FD}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -737,16 +735,6 @@ Global
{1A87F412-BA74-4DBB-9F77-FD55C042FB63}.Release|Win32.Build.0 = Release|Win32
{1A87F412-BA74-4DBB-9F77-FD55C042FB63}.Release|x64.ActiveCfg = Release|x64
{1A87F412-BA74-4DBB-9F77-FD55C042FB63}.Release|x64.Build.0 = Release|x64
{083CE608-B3E8-4E3E-871E-1144F8F751FD}.Debug|Any CPU.ActiveCfg = Debug|Win32
{083CE608-B3E8-4E3E-871E-1144F8F751FD}.Debug|Win32.ActiveCfg = Debug|Win32
{083CE608-B3E8-4E3E-871E-1144F8F751FD}.Debug|Win32.Build.0 = Debug|Win32
{083CE608-B3E8-4E3E-871E-1144F8F751FD}.Debug|x64.ActiveCfg = Debug|x64
{083CE608-B3E8-4E3E-871E-1144F8F751FD}.Debug|x64.Build.0 = Debug|x64
{083CE608-B3E8-4E3E-871E-1144F8F751FD}.Release|Any CPU.ActiveCfg = Release|Win32
{083CE608-B3E8-4E3E-871E-1144F8F751FD}.Release|Win32.ActiveCfg = Release|Win32
{083CE608-B3E8-4E3E-871E-1144F8F751FD}.Release|Win32.Build.0 = Release|Win32
{083CE608-B3E8-4E3E-871E-1144F8F751FD}.Release|x64.ActiveCfg = Release|x64
{083CE608-B3E8-4E3E-871E-1144F8F751FD}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -806,7 +794,6 @@ Global
{4D1B3411-F4F7-4E62-B7CB-A3AC3D530443} = {93B7AE1D-DEF6-4A04-A222-5CDE09DF262D}
{5CCCB9CF-0384-458F-BA08-72B73866840F} = {8B179853-B7D6-479C-B8B2-6CBCE835D040}
{1A87F412-BA74-4DBB-9F77-FD55C042FB63} = {8B179853-B7D6-479C-B8B2-6CBCE835D040}
{083CE608-B3E8-4E3E-871E-1144F8F751FD} = {8B179853-B7D6-479C-B8B2-6CBCE835D040}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {C634D169-5814-4203-94B6-6A11371DDA95}

View File

@@ -2348,7 +2348,7 @@ namespace JDP
}
case AudioEncoderType.Lossless:
{
foreach (AudioEncoderSettingsViewModel encoder in _profile._config.encoders)
foreach (AudioEncoderSettingsViewModel encoder in _profile._config.Encoders)
if (encoder.Extension == SelectedOutputAudioFmt.extension)
if (encoder.Lossless)
comboBoxEncoder.Items.Add(encoder);
@@ -2359,7 +2359,7 @@ namespace JDP
}
case AudioEncoderType.Lossy:
{
foreach (AudioEncoderSettingsViewModel encoder in _profile._config.encoders)
foreach (AudioEncoderSettingsViewModel encoder in _profile._config.Encoders)
if (encoder.Extension == SelectedOutputAudioFmt.extension)
if (!encoder.Lossless)
comboBoxEncoder.Items.Add(encoder);
@@ -2409,8 +2409,8 @@ namespace JDP
private void resetEncoderModes(AudioEncoderSettingsViewModel encoder)
{
// TODO: something cleverer than this hack...
encoder.settings.PCM = AudioPCMConfig.RedBook;
buttonEncoderSettings.Visible = encoder.settings.HasBrowsableAttributes();
encoder.Settings.PCM = AudioPCMConfig.RedBook;
buttonEncoderSettings.Visible = encoder.Settings.HasBrowsableAttributes();
string[] modes = encoder.SupportedModes;
if (modes == null || modes.Length < 2)
{
@@ -2424,12 +2424,12 @@ namespace JDP
if (encoder.EncoderModeIndex == -1)
{
string defaultMode;
encoder.settings.GetSupportedModes(out defaultMode);
encoder.settings.EncoderMode = defaultMode;
encoder.Settings.GetSupportedModes(out defaultMode);
encoder.Settings.EncoderMode = defaultMode;
}
trackBarEncoderMode.Maximum = modes.Length - 1;
trackBarEncoderMode.Value = encoder.EncoderModeIndex == -1 ? modes.Length - 1 : encoder.EncoderModeIndex;
labelEncoderMode.Text = encoder.settings.EncoderMode;
labelEncoderMode.Text = encoder.Settings.EncoderMode;
labelEncoderMinMode.Text = modes[0];
labelEncoderMaxMode.Text = modes[modes.Length - 1];
trackBarEncoderMode.Visible = true;
@@ -2461,8 +2461,8 @@ namespace JDP
{
var encoder = comboBoxEncoder.SelectedItem as AudioEncoderSettingsViewModel;
string[] modes = encoder.SupportedModes;
encoder.settings.EncoderMode = modes[trackBarEncoderMode.Value];
labelEncoderMode.Text = encoder.settings.EncoderMode;
encoder.Settings.EncoderMode = modes[trackBarEncoderMode.Value];
labelEncoderMode.Text = encoder.Settings.EncoderMode;
}
//private void toolStripButton1_Click(object sender, EventArgs e)

View File

@@ -316,11 +316,11 @@ namespace JDP
return;
}
foreach (var encoder in _config.encoders)
foreach (var encoder in _config.Encoders)
if (encoder.Extension == format.extension)
encoder.Extension = e.Label;
foreach (var decoder in _config.decoders)
foreach (var decoder in _config.Decoders)
if (decoder.Extension == format.extension)
decoder.Extension = e.Label;
@@ -361,17 +361,17 @@ namespace JDP
if (format.builtin)
return;
var decodersToRemove = new List<AudioDecoderSettingsViewModel>();
foreach (var decoder in _config.decoders)
foreach (var decoder in _config.Decoders)
if (decoder.Extension == format.extension)
decodersToRemove.Add(decoder);
foreach (var decoder in decodersToRemove)
_config.decoders.Remove(decoder);
_config.Decoders.Remove(decoder);
var encodersToRemove = new List<AudioEncoderSettingsViewModel>();
foreach (var encoder in _config.encoders)
foreach (var encoder in _config.Encoders)
if (encoder.Extension == format.extension)
encodersToRemove.Add(encoder);
foreach (var encoder in encodersToRemove)
_config.encoders.Remove(encoder);
_config.Encoders.Remove(encoder);
comboBoxEncoderExtension.Items.Remove(format.extension);
comboBoxDecoderExtension.Items.Remove(format.extension);
_config.formats.Remove(format.extension);
@@ -390,21 +390,21 @@ namespace JDP
return;
comboFormatLosslessEncoder.Items.Clear();
foreach (var encoder in _config.encoders)
foreach (var encoder in _config.Encoders)
if (encoder.Extension == format.extension && encoder.Lossless)
comboFormatLosslessEncoder.Items.Add(encoder);
comboFormatLosslessEncoder.SelectedItem = format.encoderLossless;
comboFormatLosslessEncoder.Enabled = format.allowLossless;
comboFormatLossyEncoder.Items.Clear();
foreach (var encoder in _config.encoders)
foreach (var encoder in _config.Encoders)
if (encoder.Extension == format.extension && !encoder.Lossless)
comboFormatLossyEncoder.Items.Add(encoder);
comboFormatLossyEncoder.SelectedItem = format.encoderLossy;
comboFormatLossyEncoder.Enabled = format.allowLossy;
comboFormatDecoder.Items.Clear();
foreach (var decoder in _config.decoders)
foreach (var decoder in _config.Decoders)
if (decoder.Extension == format.extension)
comboFormatDecoder.Items.Add(decoder);
comboFormatDecoder.SelectedItem = format.decoder;
@@ -466,8 +466,8 @@ namespace JDP
comboBoxEncoderExtension.Enabled = encoder.CanBeDeleted;
groupBoxExternalEncoder.Visible = encoder.CanBeDeleted;
checkBoxEncoderLossless.Enabled = format != null && format.allowLossless && format.allowLossy;
propertyGridEncoderSettings.Visible = !encoder.CanBeDeleted && encoder.settings.HasBrowsableAttributes();
propertyGridEncoderSettings.SelectedObject = encoder.CanBeDeleted ? null : encoder.settings;
propertyGridEncoderSettings.Visible = !encoder.CanBeDeleted && encoder.Settings.HasBrowsableAttributes();
propertyGridEncoderSettings.SelectedObject = encoder.CanBeDeleted ? null : encoder.Settings;
if (!checkBoxEncoderLossless.Enabled && format != null && encoder.Lossless != format.allowLossless)
encoder.Lossless = format.allowLossless;
foreach (KeyValuePair<string, CUEToolsFormat> fmtEntry in _config.formats)