using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Text;
using LameDLLWrap;
using NAudio.Lame;
using NAudio.Wave;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")]
[assembly: AssemblyCompany("Corey Murtagh")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCopyright("Copyright © 2013-2023 Corey Murtagh")]
[assembly: AssemblyDescription("Uses libmp3lame.dll from the Lame project to provide MP3 encoding support to NAudio. Both 64-bit and 32-bit versions of libmp3lame.dll are provided, with platform detection to determine which to use.")]
[assembly: AssemblyFileVersion("2.1.0.0")]
[assembly: AssemblyInformationalVersion("2.1.0+5b5bb009d8c63ef8ab95cb36ca9105c8acc1c5fc")]
[assembly: AssemblyProduct("NAudio.Lame")]
[assembly: AssemblyTitle("NAudio.Lame")]
[assembly: AssemblyVersion("2.1.0.0")]
internal class <Module>
{
static <Module>()
{
ModuleInitializer.Initialize();
}
}
namespace NAudio.Lame;
public static class ID3Decoder
{
private class ID3FrameData
{
private delegate string delGetString(byte[] buffer, ref int offset, bool requireTeminator);
public class APICData
{
public string MIMEType;
public byte ImageType;
public string Description;
public byte[] ImageBytes;
}
public readonly string FrameID;
public readonly int Size;
public readonly short Flags;
public readonly byte[] Data;
private ID3FrameData(string frameID, int size, short flags, byte[] data)
{
FrameID = frameID;
Size = size;
Flags = flags;
Data = data;
}
public static ID3FrameData ReadFrame(byte[] buffer, int offset, out int size)
{
size = -1;
if (buffer.Length - offset <= 10)
{
return null;
}
string @string = Encoding.ASCII.GetString(buffer, offset, 4);
int num = DecodeBEInt32(buffer, offset + 4);
short num2 = DecodeBEInt16(buffer, offset + 8);
byte[] array = new byte[num];
Array.Copy(buffer, offset + 10, array, 0, num);
if (((uint)num2 & 0x80u) != 0)
{
using MemoryStream memoryStream = new MemoryStream();
using DeflateStream deflateStream = new DeflateStream(new MemoryStream(array), CompressionMode.Decompress);
deflateStream.CopyTo(memoryStream);
array = memoryStream.ToArray();
}
size = 10 + num;
return new ID3FrameData(@string, num, num2, array);
}
private static string GetASCIIString(byte[] buffer, ref int offset, bool requireTerminator)
{
int num = offset;
int i;
for (i = offset; i < buffer.Length && buffer[i] != 0; i++)
{
}
if (requireTerminator && i >= buffer.Length)
{
return null;
}
int num2 = i - num;
offset = i + 1;
if (num2 >= 1)
{
return Encoding.ASCII.GetString(buffer, num, num2);
}
return string.Empty;
}
private static string GetUnicodeString(byte[] buffer, ref int offset, bool requireTerminator = true)
{
int num = offset;
int i;
for (i = offset; i < buffer.Length - 1 && (buffer[i] != 0 || buffer[i + 1] != 0); i += 2)
{
}
if (requireTerminator && i >= buffer.Length)
{
return null;
}
int num2 = i - num;
offset = i + 2;
return UCS2.GetString(buffer, num, num2);
}
private delGetString GetGetString()
{
byte b = Data[0];
return b switch
{
0 => GetASCIIString,
1 => GetUnicodeString,
_ => throw new InvalidDataException($"Invalid string encoding: {b}"),
};
}
public string ParseString()
{
int offset = 1;
return GetGetString()(Data, ref offset, requireTeminator: false);
}
public string ParseCommentText()
{
delGetString getString = GetGetString();
int num = 1;
Encoding.ASCII.GetString(Data, num, 3);
num += 3;
getString(Data, ref num, requireTeminator: true);
return getString(Data, ref num, requireTeminator: false);
}
public KeyValuePair<string, string> ParseUserDefinedText()
{
byte b = Data[0];
delGetString delGetString = b switch
{
0 => GetASCIIString,
1 => GetUnicodeString,
_ => throw new InvalidDataException($"Unknown string encoding: {b}"),
};
int offset = 1;
string key = delGetString(Data, ref offset, requireTeminator: true);
string value = delGetString(Data, ref offset, requireTeminator: false);
return new KeyValuePair<string, string>(key, value);
}
public APICData ParseAPIC()
{
if (FrameID != "APIC")
{
return null;
}
delGetString getString = GetGetString();
int offset = 1;
string mIMEType = getString(Data, ref offset, requireTeminator: true);
byte imageType = Data[offset++];
string description = getString(Data, ref offset, requireTeminator: true);
int num = Data.Length - offset;
byte[] array = new byte[num];
Array.Copy(Data, offset, array, 0, num);
return new APICData
{
MIMEType = mIMEType,
ImageType = imageType,
Description = description,
ImageBytes = array
};
}
}
public static ID3TagData Decode(Stream stream)
{
byte[] array = new byte[10];
if (stream.Read(array, 0, 10) != 10 || !ValidateTagHeader(array))
{
throw new InvalidDataException("Bad ID3 Tag Header");
}
int num = DecodeHeaderSize(array, 6);
if (num < 10 || num >= 268435456)
{
throw new InvalidDataException($"ID3 header size '{num:#,0}' out of range.");
}
byte[] array2 = new byte[10 + num];
stream.Read(array2, 0, array2.Length);
return InternalDecode(array2, 0, num, array[5]);
}
public static ID3TagData Decode(byte[] buffer)
{
if (!ValidateTagHeader(buffer))
{
throw new InvalidDataException("Bad ID3 Tag Header");
}
int num = DecodeHeaderSize(buffer, 6);
if (num < 10 || num > buffer.Length - 10)
{
throw new InvalidDataException($"ID3 header size '{num:#,0}' out of range.");
}
return InternalDecode(buffer, 10, num, buffer[5]);
}
private static ID3TagData InternalDecode(byte[] buffer, int offset, int size, byte flags)
{
byte[] array = new byte[size];
Array.Copy(buffer, offset, array, 0, size);
if ((flags & 0x80u) != 0)
{
array = UnsyncBytes(array);
}
ID3TagData iD3TagData = new ID3TagData();
int num = 0;
if ((flags & 0x40u) != 0)
{
int num2 = DecodeBEInt32(array, num);
num += num2 + 4;
}
int size2;
ID3FrameData iD3FrameData = ID3FrameData.ReadFrame(array, num, out size2);
while (size2 > 0 && iD3FrameData != null)
{
switch (iD3FrameData.FrameID)
{
case "TIT2":
iD3TagData.Title = iD3FrameData.ParseString();
break;
case "TPE1":
iD3TagData.Artist = iD3FrameData.ParseString();
break;
case "TALB":
iD3TagData.Album = iD3FrameData.ParseString();
break;
case "TYER":
iD3TagData.Year = iD3FrameData.ParseString();
break;
case "COMM":
iD3TagData.Comment = iD3FrameData.ParseCommentText();
break;
case "TCON":
iD3TagData.Genre = iD3FrameData.ParseString();
break;
case "TRCK":
iD3TagData.Track = iD3FrameData.ParseString();
break;
case "TIT3":
iD3TagData.Subtitle = iD3FrameData.ParseString();
break;
case "TPE2":
iD3TagData.AlbumArtist = iD3FrameData.ParseString();
break;
case "TXXX":
{
KeyValuePair<string, string> keyValuePair = iD3FrameData.ParseUserDefinedText();
iD3TagData.UserDefinedText[keyValuePair.Key] = keyValuePair.Value;
break;
}
case "APIC":
iD3TagData.AlbumArt = iD3FrameData.ParseAPIC()?.ImageBytes;
break;
}
num += size2;
iD3FrameData = ID3FrameData.ReadFrame(array, num, out size2);
}
return iD3TagData;
}
private static bool ValidateTagHeader(byte[] buffer)
{
if (buffer != null && buffer.Length >= 4 && buffer[0] == 73 && buffer[1] == 68 && buffer[2] == 51 && buffer[3] == 3)
{
return buffer[4] == 0;
}
return false;
}
private static int DecodeHeaderSize(byte[] buffer, int offset)
{
return (buffer[offset] << 21) | (buffer[offset + 1] << 14) | (buffer[offset + 2] << 7) | buffer[offset + 3];
}
private static short DecodeBEInt16(byte[] buffer, int offset)
{
return (short)((buffer[offset] << 8) | buffer[offset + 1]);
}
private static int DecodeBEInt32(byte[] buffer, int offset)
{
return (buffer[offset] << 24) | (buffer[offset + 1] << 16) | (buffer[offset + 2] << 8) | buffer[offset + 3];
}
private static byte[] UnsyncBytes(IEnumerable<byte> buffer)
{
return ProcessBuffer().ToArray();
IEnumerable<byte> ProcessBuffer()
{
byte b2 = 0;
foreach (byte b in buffer)
{
if (b != 0 || b2 != byte.MaxValue)
{
yield return b;
}
b2 = b;
}
}
}
}
public class ID3TagData
{
public string Title;
public string Artist;
public string Album;
public string Year;
public string Comment;
public string Genre;
public string Track;
public string Subtitle;
public string AlbumArtist;
public byte[] AlbumArt;
[Obsolete("Use the UserDefinedText property instead.", false)]
public string[] UserDefinedTags
{
get
{
return UserDefinedText.Select((KeyValuePair<string, string> kv) => kv.Key + "=" + kv.Value).ToArray();
}
set
{
SetUDT(value);
}
}
public bool V2Only { get; set; } = true;
public Dictionary<string, string> CustomFields { get; } = new Dictionary<string, string>();
public Dictionary<string, string> UserDefinedText { get; } = new Dictionary<string, string>();
public void SetUDT(IEnumerable<string> data)
{
UserDefinedText.Clear();
foreach (string datum in data)
{
string text = datum.Split(new char[1] { '=' }).First();
int num = text.Length + 1;
string value = ((num > datum.Length) ? string.Empty : datum.Substring(num));
UserDefinedText[text] = value;
}
}
}
public class LameConfig
{
private LAMEPreset? _preset;
private int? _bitrate;
private int? _vbrquality;
public LAMEPreset? Preset
{
get
{
return _preset;
}
set
{
_preset = value;
if (value.HasValue)
{
_bitrate = null;
}
}
}
public int? BitRate
{
get
{
return _bitrate;
}
set
{
_bitrate = value;
if (value.HasValue)
{
_preset = null;
}
}
}
public int? OutputSampleRate { get; set; }
public VBRMode? VBR { get; set; }
public int? ABRRateKbps { get; set; }
public int? VBRMinimumRateKbps { get; set; }
public int? VBRMaximumRateKbps { get; set; }
public bool? VBREnforceMinimum { get; set; }
public int? VBRQuality
{
get
{
return _vbrquality;
}
set
{
if (!value.HasValue)
{
_vbrquality = null;
}
else
{
_vbrquality = Math.Max(0, Math.Min(9, value.Value));
}
}
}
public float? Scale { get; set; }
public float? ScaleLeft { get; set; }
public float? ScaleRight { get; set; }
public int? LowPassFreq { get; set; }
public int? LowPassWidth { get; set; }
public int? HighPassFreq { get; set; }
public int? HighPassWidth { get; set; }
public bool? Analysis { get; set; }
public bool? WriteVBRTag { get; set; }
public MPEGMode? Mode { get; set; }
public bool? ForceMS { get; set; }
public bool? UseFreeFormat { get; set; }
public bool? Copyright { get; set; }
public bool? Original { get; set; }
public bool? ErrorProtection { get; set; }
public bool? StrictISO { get; set; }
public ID3TagData ID3 { get; set; }
public LibMp3Lame ConfigureDLL(WaveFormat format)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_001e: Expected O, but got Unknown
//IL_0087: Unknown result type (might be due to invalid IL or missing references)
LibMp3Lame val = new LibMp3Lame
{
InputSampleRate = format.SampleRate,
NumChannels = format.Channels
};
if (_bitrate.HasValue)
{
val.BitRate = _bitrate.Value;
}
else
{
if (_preset >= LAMEPreset.V9 && _preset <= LAMEPreset.V0 && (int)val.VBR == 0 && !VBR.HasValue)
{
val.VBR = (VBRMode)4;
}
val.SetPreset((int)_preset.GetValueOrDefault(LAMEPreset.STANDARD));
}
if (OutputSampleRate.HasValue)
{
val.OutputSampleRate = OutputSampleRate.Value;
}
if (VBR.HasValue)
{
val.VBR = (VBRMode)VBR.Value;
if (VBR == VBRMode.ABR && ABRRateKbps.HasValue)
{
val.VBRMeanBitrateKbps = ABRRateKbps.Value;
}
if (VBRMinimumRateKbps.HasValue)
{
val.VBRMinBitrateKbps = VBRMinimumRateKbps.Value;
}
if (VBRMaximumRateKbps.HasValue)
{
val.VBRMaxBitrateKbps = VBRMaximumRateKbps.Value;
}
if (VBREnforceMinimum.HasValue)
{
val.VBRHardMin = VBREnforceMinimum.Value;
}
if (VBRQuality.HasValue)
{
val.VBRQualityLevel = VBRQuality.Value;
}
}
if (Scale.HasValue)
{
val.Scale = Scale.Value;
}
if (ScaleLeft.HasValue)
{
val.ScaleLeft = ScaleLeft.Value;
}
if (ScaleRight.HasValue)
{
val.ScaleRight = ScaleRight.Value;
}
if (LowPassFreq.HasValue)
{
val.LowPassFreq = LowPassFreq.Value;
}
if (LowPassWidth.HasValue)
{
val.LowPassWidth = LowPassWidth.Value;
}
if (HighPassFreq.HasValue)
{
val.HighPassFreq = HighPassFreq.Value;
}
if (HighPassWidth.HasValue)
{
val.HighPassWidth = HighPassWidth.Value;
}
if (Analysis.HasValue)
{
val.Analysis = Analysis.Value;
}
if (WriteVBRTag.HasValue)
{
val.WriteVBRTag = WriteVBRTag.Value;
}
if (Mode.HasValue)
{
val.Mode = (MPEGMode)Mode.Value;
}
if (ForceMS.HasValue)
{
val.ForceMS = ForceMS.Value;
}
if (UseFreeFormat.HasValue)
{
val.UseFreeFormat = UseFreeFormat.Value;
}
if (Copyright.HasValue)
{
val.Copyright = Copyright.Value;
}
if (Original.HasValue)
{
val.Original = Original.Value;
}
if (ErrorProtection.HasValue)
{
val.ErrorProtection = ErrorProtection.Value;
}
if (StrictISO.HasValue)
{
val.StrictISO = StrictISO.Value;
}
return val;
}
}
public static class LameDLL
{
public static string LameVersion => LameDLLImpl.LameVersion;
public static string LameShortVersion => LameDLLImpl.LameShortVersion;
public static string LameVeryShortVersion => LameDLLImpl.LameVeryShortVersion;
public static string LamePsychoacousticVersion => LameDLLImpl.LamePsychoacousticVersion;
public static string LameURL => LameDLLImpl.LameURL;
public static string LameOSBitness => LameDLLImpl.LameOSBitness;
public static bool LoadNativeDLL(params string[] rootPaths)
{
return LameDLLImpl.Native.LoadNativeDLL(rootPaths);
}
public static LAMEVersion GetLameVersion()
{
return LameDLLImpl.GetLameVersion();
}
}
internal static class LameDLLImpl
{
internal static class Native
{
private static IntPtr _hLameDll = IntPtr.Zero;
[DllImport("kernel32", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern IntPtr LoadLibraryW([MarshalAs(UnmanagedType.LPWStr)] string lpFilename);
private static bool TryLoadLameDLL(FileInfo file)
{
if (file == null || !file.Exists)
{
return false;
}
IntPtr intPtr = LoadLibraryW(file.FullName);
if (intPtr == IntPtr.Zero)
{
return false;
}
_hLameDll = intPtr;
return true;
}
internal static bool LoadNativeDLL(params string[] rootPaths)
{
if (_hLameDll != IntPtr.Zero)
{
return true;
}
if (!IsWindowsOS)
{
return false;
}
string text = null;
try
{
text = Path.GetDirectoryName(typeof(LameDLL).Assembly.Location);
}
catch
{
}
string[] array = (from p in rootPaths.Concat(new string[2]
{
AppDomain.CurrentDomain.BaseDirectory,
text
})
where !string.IsNullOrEmpty(p)
select p).Distinct().ToArray();
string searchPattern = "libmp3lame." + (Environment.Is64BitProcess ? "64" : "32") + ".dll";
string[] array2 = array;
for (int i = 0; i < array2.Length; i++)
{
if (TryLoadLameDLL(new DirectoryInfo(array2[i]).GetFiles(searchPattern, SearchOption.AllDirectories).FirstOrDefault()))
{
return true;
}
}
return false;
}
}
internal static string LameVersion => LibMp3Lame.LameVersion;
internal static string LameShortVersion => LibMp3Lame.LameShortVersion;
internal static string LameVeryShortVersion => LibMp3Lame.LameVeryShortVersion;
internal static string LamePsychoacousticVersion => LibMp3Lame.LamePsychoacousticVersion;
internal static string LameURL => LibMp3Lame.LameURL;
internal static string LameOSBitness => LibMp3Lame.LameOSBitness;
internal static bool IsWindowsOS => Environment.OSVersion.Platform == PlatformID.Win32NT;
internal static LAMEVersion GetLameVersion()
{
return new LAMEVersion(LibMp3Lame.GetLameVersion());
}
}
public delegate void OutputHandler(string text);
public delegate void ProgressHandler(object writer, long inputBytes, long outputBytes, bool finished);
public class LameMP3FileWriter : Stream
{
private delegate int delEncode();
[StructLayout(LayoutKind.Explicit)]
private class ArrayUnion
{
[FieldOffset(0)]
public readonly int nBytes;
[FieldOffset(16)]
public readonly byte[] bytes;
[FieldOffset(16)]
public readonly short[] shorts;
[FieldOffset(16)]
public readonly int[] ints;
[FieldOffset(16)]
public readonly long[] longs;
[FieldOffset(16)]
public readonly float[] floats;
[FieldOffset(16)]
public readonly double[] doubles;
public int nShorts => nBytes / 2;
public int nInts => nBytes / 4;
public int nLongs => nBytes / 8;
public int nFloats => nBytes / 4;
public int nDoubles => doubles.Length;
public ArrayUnion(int reqBytes)
{
int num = (reqBytes + 7) / 8;
doubles = new double[num];
nBytes = num * 8;
}
private ArrayUnion()
{
throw new Exception("Default constructor cannot be called for ArrayUnion");
}
}
private LibMp3Lame _lame;
private readonly WaveFormat _inputFormat;
private Stream _outStream;
private readonly bool _disposeOutput;
private readonly ArrayUnion _inBuffer;
private int inPosition;
protected byte[] _outBuffer;
private long _inputByteCount;
private long _outputByteCount;
private readonly delEncode _encode;
private int _minProgressTime = 100;
private DateTime _lastProgress = DateTime.Now;
private static Dictionary<int, string> _genres;
public int LastLameResult => _lame.LastLameError;
public int MinProgressTime
{
get
{
return _minProgressTime;
}
set
{
_minProgressTime = Math.Max(0, value);
}
}
public override bool CanRead => false;
public override bool CanSeek => false;
public override bool CanWrite
{
get
{
if (_outStream != null)
{
return _lame != null;
}
return false;
}
}
public override long Position
{
get
{
return 0L;
}
set
{
throw new NotImplementedException();
}
}
public override long Length => 0L;
public static Dictionary<int, string> Genres
{
get
{
if (_genres == null)
{
_genres = LibMp3Lame.ID3GenreList();
}
return _genres;
}
}
public event ProgressHandler OnProgress;
public LameMP3FileWriter(string outFileName, WaveFormat format, LAMEPreset quality, ID3TagData id3 = null)
: this(File.Create(outFileName), format, quality, id3)
{
_disposeOutput = true;
}
public LameMP3FileWriter(Stream outStream, WaveFormat format, LAMEPreset quality, ID3TagData id3 = null)
: this(outStream, format, new LameConfig
{
Preset = quality,
ID3 = id3
})
{
}
public LameMP3FileWriter(string outFileName, WaveFormat format, int bitRate, ID3TagData id3 = null)
: this(File.Create(outFileName), format, bitRate, id3)
{
_disposeOutput = true;
}
public LameMP3FileWriter(Stream outStream, WaveFormat format, int bitRate, ID3TagData id3 = null)
: this(outStream, format, new LameConfig
{
BitRate = bitRate,
ID3 = id3
})
{
}
public LameMP3FileWriter(string outFileName, WaveFormat format, LameConfig config)
: this(File.Create(outFileName), format, config)
{
_disposeOutput = true;
}
public LameMP3FileWriter(Stream outStream, WaveFormat format, LameConfig config)
{
//IL_005a: Unknown result type (might be due to invalid IL or missing references)
//IL_0060: Invalid comparison between Unknown and I4
//IL_008c: Unknown result type (might be due to invalid IL or missing references)
//IL_0092: Invalid comparison between Unknown and I4
//IL_0063: Unknown result type (might be due to invalid IL or missing references)
//IL_0069: Invalid comparison between Unknown and I4
//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
//IL_00c5: Invalid comparison between Unknown and I4
//IL_0071: Unknown result type (might be due to invalid IL or missing references)
//IL_012c: Unknown result type (might be due to invalid IL or missing references)
//IL_0132: Invalid comparison between Unknown and I4
if (format == null)
{
throw new ArgumentNullException("format");
}
if (format.Channels != 1 && format.Channels != 2)
{
throw new ArgumentException($"Unsupported number of channels {format.Channels}", "format");
}
if ((int)format.Encoding != 1 && (int)format.Encoding != 3)
{
throw new ArgumentException($"Unsupported encoding format {format.Encoding}", "format");
}
if ((int)format.Encoding == 1 && format.BitsPerSample != 16)
{
throw new ArgumentException($"Unsupported PCM sample size {format.BitsPerSample}", "format");
}
if ((int)format.Encoding == 3 && format.BitsPerSample != 32)
{
throw new ArgumentException($"Unsupported Float sample size {format.BitsPerSample}", "format");
}
if (format.SampleRate < 8000 || format.SampleRate > 48000)
{
throw new ArgumentException($"Unsupported Sample Rate {format.SampleRate}", "format");
}
if ((int)format.Encoding == 1)
{
if (format.Channels == 1)
{
_encode = Encode_pcm_16_mono;
}
else
{
_encode = Encode_pcm_16_stereo;
}
}
else if (format.Channels == 1)
{
_encode = Encode_float_mono;
}
else
{
_encode = Encode_float_stereo;
}
_inputFormat = format;
_outStream = outStream ?? throw new ArgumentNullException("outStream");
_disposeOutput = false;
_inBuffer = new ArrayUnion(format.AverageBytesPerSecond);
_outBuffer = new byte[format.SampleRate * 5 / 4 + 7200];
_lame = config.ConfigureDLL(format);
if (config.ID3 != null)
{
ApplyID3Tag(config.ID3);
}
_lame.InitParams();
}
protected override void Dispose(bool disposing)
{
if (_lame != null && _outStream != null)
{
Flush();
}
LibMp3Lame lame = _lame;
if (lame != null)
{
lame.Dispose();
}
_lame = null;
if (_disposeOutput)
{
_outStream?.Dispose();
_outStream = null;
}
base.Dispose(disposing);
}
private int Encode_pcm_16_mono()
{
return _lame.Write(_inBuffer.shorts, inPosition / 2, _outBuffer, _outBuffer.Length, true);
}
private int Encode_pcm_16_stereo()
{
return _lame.Write(_inBuffer.shorts, inPosition / 2, _outBuffer, _outBuffer.Length, false);
}
private int Encode_float_mono()
{
return _lame.Write(_inBuffer.floats, inPosition / 4, _outBuffer, _outBuffer.Length, true);
}
private int Encode_float_stereo()
{
return _lame.Write(_inBuffer.floats, inPosition / 4, _outBuffer, _outBuffer.Length, false);
}
private void Encode()
{
if (_outStream == null || _lame == null)
{
throw new InvalidOperationException("Output stream closed.");
}
if (inPosition >= _inputFormat.Channels * 2)
{
int num = _encode();
if (num > 0)
{
_outStream.Write(_outBuffer, 0, num);
_outputByteCount += num;
}
_inputByteCount += inPosition;
inPosition = 0;
RaiseProgress(finished: false);
}
}
public override void Write(byte[] buffer, int offset, int count)
{
while (count > 0)
{
int num = Math.Min(_inBuffer.nBytes - inPosition, count);
Buffer.BlockCopy(buffer, offset, _inBuffer.bytes, inPosition, num);
inPosition += num;
count -= num;
offset += num;
if (inPosition >= _inBuffer.nBytes)
{
Encode();
}
}
}
public override void Flush()
{
if (inPosition > 0)
{
Encode();
}
int num = _lame.Flush(_outBuffer, _outBuffer.Length);
if (num > 0)
{
_outStream.Write(_outBuffer, 0, num);
_outputByteCount += num;
}
RaiseProgress(finished: true);
if (_lame.WriteVBRTag)
{
UpdateLameTagFrame();
}
if (_disposeOutput)
{
_outStream.Dispose();
}
_outStream = null;
}
private bool UpdateLameTagFrame()
{
if (_outStream == null || !_outStream.CanSeek || !_outStream.CanRead || !_outStream.CanWrite)
{
return false;
}
long position = _outStream.Position;
try
{
byte[] lAMETagFrame = _lame.GetLAMETagFrame();
if (lAMETagFrame == null || lAMETagFrame.Length < 4)
{
return false;
}
if (SkipId3v2(lAMETagFrame.Length) != 0)
{
return false;
}
_outStream.Write(lAMETagFrame, 0, lAMETagFrame.Length);
return true;
}
finally
{
_outStream.Position = position;
}
}
private int SkipId3v2(int framesize)
{
try
{
_outStream.Position = 0L;
}
catch
{
return -2;
}
byte[] array = new byte[10];
if (_outStream.Read(array, 0, 10) != 10)
{
return -3;
}
int num = 0;
if (array[0] == 73 || array[1] == 68 || array[2] == 51)
{
num = (((array[6] & 0x7F) << 21) | ((array[7] & 0x7F) << 14) | ((array[8] & 0x7F) << 7) | (array[9] & 0x7F)) + 10;
}
_outStream.Position = num;
if (_outStream.Read(array, 0, 4) != 4 || array[0] != byte.MaxValue || (array[1] & 0xE0) != 224)
{
return -1;
}
_outStream.Position = num + framesize;
if (_outStream.Read(array, 0, 4) != 4 || array[0] != byte.MaxValue || (array[1] & 0xE0) != 224)
{
return -1;
}
_outStream.Position = num;
return 0;
}
public override int Read(byte[] buffer, int offset, int count)
{
throw new NotImplementedException();
}
public override void SetLength(long value)
{
throw new NotImplementedException();
}
public override long Seek(long offset, SeekOrigin origin)
{
throw new NotImplementedException();
}
private void ApplyID3Tag(ID3TagData tag)
{
if (tag == null)
{
return;
}
_lame.ID3Init();
if (tag.V2Only)
{
_lame.ID3V2Only();
}
foreach (KeyValuePair<string, string> customField in tag.CustomFields)
{
_lame.ID3SetFieldValue(customField.Key + "=" + customField.Value);
}
if (!string.IsNullOrEmpty(tag.Title))
{
_lame.ID3SetTitle(tag.Title);
}
if (!string.IsNullOrEmpty(tag.Artist))
{
_lame.ID3SetArtist(tag.Artist);
}
if (!string.IsNullOrEmpty(tag.Album))
{
_lame.ID3SetAlbum(tag.Album);
}
if (!string.IsNullOrEmpty(tag.Year))
{
_lame.ID3SetYear(tag.Year);
}
if (!string.IsNullOrEmpty(tag.Comment))
{
_lame.ID3SetComment(tag.Comment);
}
if (!string.IsNullOrEmpty(tag.Genre))
{
_lame.ID3SetGenre(tag.Genre);
}
if (!string.IsNullOrEmpty(tag.Track))
{
_lame.ID3SetTrack(tag.Track);
}
if (!string.IsNullOrEmpty(tag.Subtitle))
{
_lame.ID3SetFieldValue("TIT3=" + tag.Subtitle);
}
if (!string.IsNullOrEmpty(tag.AlbumArtist))
{
_lame.ID3SetFieldValue("TPE2=" + tag.AlbumArtist);
}
foreach (KeyValuePair<string, string> item in tag.UserDefinedText)
{
_lame.ID3SetFieldValue("TXXX=" + item.Key + "=" + item.Value);
}
byte[] albumArt = tag.AlbumArt;
if (albumArt != null && albumArt.Length != 0)
{
_lame.ID3SetAlbumArt(tag.AlbumArt);
}
byte[] array = _lame.ID3GetID3v2Tag();
if (array != null && array.Length >= 32768)
{
_lame.ID3WriteTagAutomatic = false;
_outStream.Write(array, 0, array.Length);
}
}
public byte[] GetID3v1TagBytes()
{
return _lame.ID3GetID3v1Tag();
}
public byte[] GetID3v2TagBytes()
{
return _lame.ID3GetID3v2Tag();
}
public void SetErrorFunction(OutputHandler fn)
{
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_0024: Expected O, but got Unknown
_lame.SetErrorFunc((ReportFunction)delegate(string t)
{
fn(t);
});
}
public void SetDebugFunction(OutputHandler fn)
{
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_0024: Expected O, but got Unknown
_lame.SetMsgFunc((ReportFunction)delegate(string t)
{
fn(t);
});
}
public void SetMessageFunction(OutputHandler fn)
{
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_0024: Expected O, but got Unknown
_lame.SetMsgFunc((ReportFunction)delegate(string t)
{
fn(t);
});
}
public void PrintLAMEConfig()
{
_lame.PrintConfig();
}
public void PrintLAMEInternals()
{
_lame.PrintInternals();
}
protected void RaiseProgress(bool finished)
{
TimeSpan timeSpan = DateTime.Now - _lastProgress;
if (finished || timeSpan.TotalMilliseconds >= (double)_minProgressTime)
{
_lastProgress = DateTime.Now;
this.OnProgress?.Invoke(this, _inputByteCount, _outputByteCount, finished);
}
}
}
public enum LAMEPreset
{
ABR_8 = 8,
ABR_16 = 16,
ABR_32 = 32,
ABR_48 = 48,
ABR_64 = 64,
ABR_96 = 96,
ABR_128 = 128,
ABR_160 = 160,
ABR_256 = 256,
ABR_320 = 320,
V9 = 410,
VBR_10 = 410,
V8 = 420,
VBR_20 = 420,
V7 = 430,
VBR_30 = 430,
V6 = 440,
VBR_40 = 440,
V5 = 450,
VBR_50 = 450,
V4 = 460,
VBR_60 = 460,
V3 = 470,
VBR_70 = 470,
V2 = 480,
VBR_80 = 480,
V1 = 490,
VBR_90 = 490,
V0 = 500,
VBR_100 = 500,
R3MIX = 1000,
STANDARD = 1001,
EXTREME = 1002,
INSANE = 1003,
STANDARD_FAST = 1004,
EXTREME_FAST = 1005,
MEDIUM = 1006,
MEDIUM_FAST = 1007
}
public class LAMEVersion
{
public int Major { get; private set; }
public int Minor { get; private set; }
public bool Alpha { get; private set; }
public bool Beta { get; private set; }
public int PsychoAcoustic_Major { get; private set; }
public int PsychoAcoustic_Minor { get; private set; }
public bool PsychoAcoustic_Alpha { get; private set; }
public bool PsychoAcoustic_Beta { get; private set; }
public string Features { get; private set; }
internal LAMEVersion(LAMEVersion source)
{
Major = source.major;
Minor = source.minor;
Alpha = source.alpha;
Beta = source.beta;
PsychoAcoustic_Major = source.psy_major;
PsychoAcoustic_Minor = source.psy_minor;
PsychoAcoustic_Alpha = source.psy_alpha;
PsychoAcoustic_Beta = source.psy_beta;
Features = source.features;
}
private LAMEVersion()
{
}
}
public static class ModuleInitializer
{
public static void Initialize()
{
ResourceAssemblyLoader.Init();
}
}
public enum MPEGMode : uint
{
Stereo = 0u,
JointStereo = 1u,
Mono = 3u,
NotSet = 4u
}
internal static class ResourceAssemblyLoader
{
internal static bool Initialized;
internal static string LoadedName;
public static void Init()
{
lock (typeof(ResourceAssemblyLoader))
{
if (!Initialized)
{
AppDomain.CurrentDomain.AssemblyResolve += LoadLameWrapper;
Initialized = true;
}
}
}
private static Assembly LoadLameWrapper(object sender, ResolveEventArgs args)
{
string value = new AssemblyName(args.Name).Name + ".dll";
Assembly assembly = typeof(ResourceAssemblyLoader).Assembly;
byte[] array = null;
string[] manifestResourceNames = assembly.GetManifestResourceNames();
foreach (string text in manifestResourceNames)
{
int num = text.IndexOf(Environment.Is64BitProcess ? "x64" : "x86");
int num2 = text.IndexOf(value);
if (num >= 0 && num2 >= 0)
{
LoadedName = text;
using (Stream stream = assembly.GetManifestResourceStream(text))
{
array = new byte[stream.Length];
stream.Read(array, 0, (int)stream.Length);
}
break;
}
}
if (array == null)
{
return null;
}
LameDLL.LoadNativeDLL();
return Assembly.Load(array);
}
}
public enum VBRMode : uint
{
Off = 0u,
MT = 1u,
RH = 2u,
ABR = 3u,
MTRH = 4u,
Default = 4u
}
internal class NAudioLame_ProcessedByFody
{
internal const string FodyVersion = "6.3.0.0";
internal const string ModuleInit = "2.1.1.0";
}