Refactoring

This commit is contained in:
Grigory Chudov
2013-04-02 19:56:58 -04:00
parent 9dd4897acc
commit 1c9e76c421
7 changed files with 101 additions and 212 deletions

View File

@@ -78,10 +78,8 @@
<Compile Include="LameException.cs" /> <Compile Include="LameException.cs" />
<Compile Include="LameWriterConstants.cs" /> <Compile Include="LameWriterConstants.cs" />
<Compile Include="LameWriter.cs" /> <Compile Include="LameWriter.cs" />
<Compile Include="LameWriterCBR.cs" />
<Compile Include="LameWriterCBRSettings.cs" /> <Compile Include="LameWriterCBRSettings.cs" />
<Compile Include="LameWriterSettings.cs" /> <Compile Include="LameWriterSettings.cs" />
<Compile Include="LameWriterVBR.cs" />
<Compile Include="LameWriterVBRSettings.cs" /> <Compile Include="LameWriterVBRSettings.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup> </ItemGroup>

View File

@@ -5,6 +5,8 @@ using System.IO;
namespace CUETools.Codecs.LAME namespace CUETools.Codecs.LAME
{ {
[AudioEncoderClass("CBR (libmp3lame)", "mp3", false, 1, typeof(LameWriterCBRSettings))]
[AudioEncoderClass("VBR (libmp3lame)", "mp3", false, 2, typeof(LameWriterVBRSettings))]
public class LameWriter : IAudioDest public class LameWriter : IAudioDest
{ {
#region Unmanaged Functions #region Unmanaged Functions
@@ -13,48 +15,48 @@ namespace CUETools.Codecs.LAME
private const CallingConvention LameCallingConvention = CallingConvention.Cdecl; private const CallingConvention LameCallingConvention = CallingConvention.Cdecl;
[DllImport(LameDll, CallingConvention = LameCallingConvention)] [DllImport(LameDll, CallingConvention = LameCallingConvention)]
private static extern IntPtr lame_init(); internal static extern IntPtr lame_init();
[DllImport(LameDll, CallingConvention = LameCallingConvention)] [DllImport(LameDll, CallingConvention = LameCallingConvention)]
private static extern int lame_close(IntPtr handle); internal static extern int lame_close(IntPtr handle);
[DllImport(LameDll, CallingConvention = LameCallingConvention)] [DllImport(LameDll, CallingConvention = LameCallingConvention)]
private static extern int lame_set_num_channels(IntPtr handle, int channels); internal static extern int lame_set_num_channels(IntPtr handle, int channels);
[DllImport(LameDll, CallingConvention = LameCallingConvention)] [DllImport(LameDll, CallingConvention = LameCallingConvention)]
private static extern int lame_set_in_samplerate(IntPtr handle, int sampleRate); internal static extern int lame_set_in_samplerate(IntPtr handle, int sampleRate);
[DllImport(LameDll, CallingConvention = LameCallingConvention)] [DllImport(LameDll, CallingConvention = LameCallingConvention)]
private static extern int lame_set_quality(IntPtr handle, int quality); internal static extern int lame_set_quality(IntPtr handle, int quality);
[DllImport(LameDll, CallingConvention = LameCallingConvention)] [DllImport(LameDll, CallingConvention = LameCallingConvention)]
private static extern int lame_set_VBR(IntPtr handle, int vbrMode); internal static extern int lame_set_VBR(IntPtr handle, int vbrMode);
[DllImport(LameDll, CallingConvention = LameCallingConvention)] [DllImport(LameDll, CallingConvention = LameCallingConvention)]
private static extern int lame_set_VBR_mean_bitrate_kbps(IntPtr handle, int meanBitrate); internal static extern int lame_set_VBR_mean_bitrate_kbps(IntPtr handle, int meanBitrate);
[DllImport(LameDll, CallingConvention = LameCallingConvention)] [DllImport(LameDll, CallingConvention = LameCallingConvention)]
private static extern int lame_init_params(IntPtr handle); internal static extern int lame_init_params(IntPtr handle);
[DllImport(LameDll, CallingConvention = LameCallingConvention)] [DllImport(LameDll, CallingConvention = LameCallingConvention)]
private static extern int lame_set_num_samples(IntPtr handle, uint numSamples); internal static extern int lame_set_num_samples(IntPtr handle, uint numSamples);
[DllImport(LameDll, CallingConvention = LameCallingConvention)] [DllImport(LameDll, CallingConvention = LameCallingConvention)]
private static extern int lame_encode_buffer_interleaved(IntPtr handle, IntPtr pcm, int num_samples, IntPtr mp3buf, int mp3buf_size); internal static extern int lame_encode_buffer_interleaved(IntPtr handle, IntPtr pcm, int num_samples, IntPtr mp3buf, int mp3buf_size);
[DllImport(LameDll, CallingConvention = LameCallingConvention)] [DllImport(LameDll, CallingConvention = LameCallingConvention)]
private static extern int lame_encode_flush(IntPtr handle, IntPtr mp3buf, int size); internal static extern int lame_encode_flush(IntPtr handle, IntPtr mp3buf, int size);
[DllImport(LameDll, CallingConvention = LameCallingConvention)] [DllImport(LameDll, CallingConvention = LameCallingConvention)]
private static extern uint lame_get_lametag_frame(IntPtr handle, IntPtr buffer, uint size); internal static extern uint lame_get_lametag_frame(IntPtr handle, IntPtr buffer, uint size);
[DllImport(LameDll, CallingConvention = LameCallingConvention)] [DllImport(LameDll, CallingConvention = LameCallingConvention)]
private static extern int lame_set_VBR_quality(IntPtr handle, float vbrQuality); internal static extern int lame_set_VBR_quality(IntPtr handle, float vbrQuality);
[DllImport(LameDll, CallingConvention = LameCallingConvention)] [DllImport(LameDll, CallingConvention = LameCallingConvention)]
private static extern int lame_set_brate(IntPtr handle, int bitrate); internal static extern int lame_set_brate(IntPtr handle, int bitrate);
[DllImport(LameDll, CallingConvention = LameCallingConvention)] [DllImport(LameDll, CallingConvention = LameCallingConvention)]
private static extern int lame_set_bWriteVbrTag(IntPtr handle, int writeVbrTag); internal static extern int lame_set_bWriteVbrTag(IntPtr handle, int writeVbrTag);
[DllImport(LameDll, CallingConvention = LameCallingConvention)] [DllImport(LameDll, CallingConvention = LameCallingConvention)]
private static extern int lame_set_write_id3tag_automatic(IntPtr handle, int automaticWriteId3Tag); internal static extern int lame_set_write_id3tag_automatic(IntPtr handle, int automaticWriteId3Tag);
#endregion #endregion
private string outputPath; private string m_outputPath;
private Stream outputStream; private Stream m_outputStream;
private bool closed = false, initialized = false; private bool m_closed = false, m_initialized = false;
private IntPtr handle; private IntPtr m_handle;
private AudioPCMConfig pcm; private AudioPCMConfig m_pcm;
private uint finalSampleCount; private uint m_finalSampleCount;
private byte[] outputBuffer; private byte[] m_outputBuffer;
public long BlockSize public long BlockSize
{ {
@@ -69,13 +71,13 @@ namespace CUETools.Codecs.LAME
{ {
throw new ArgumentException("Input file too big."); throw new ArgumentException("Input file too big.");
} }
this.finalSampleCount = (uint)value; this.m_finalSampleCount = (uint)value;
} }
} }
public AudioPCMConfig PCM public AudioPCMConfig PCM
{ {
get { return this.pcm; } get { return this.m_pcm; }
} }
public long Padding public long Padding
@@ -85,44 +87,39 @@ namespace CUETools.Codecs.LAME
public string Path public string Path
{ {
get { return this.outputPath; } get { return this.m_outputPath; }
} }
private LameWriterSettings m_settings = new LameWriterCBRSettings();
public virtual AudioEncoderSettings Settings public virtual AudioEncoderSettings Settings
{ {
get get
{ {
return new AudioEncoderSettings(); return m_settings;
} }
set set
{ {
throw new MethodAccessException(); if (value as LameWriterSettings == null)
throw new InvalidOperationException("Unsupported options " + value);
m_settings = value as LameWriterSettings;
} }
} }
protected virtual LameWriterConfig Config public LameWriter(string path, Stream output, AudioPCMConfig pcm)
{ {
get this.CheckPCMConfig(pcm);
{ this.m_pcm = pcm;
return LameWriterConfig.CreateCbr(320); this.m_outputPath = path;
} this.m_outputStream = output != null ? output : File.Create(path);
} }
public LameWriter(string path, AudioPCMConfig pcm) public LameWriter(string path, AudioPCMConfig pcm)
{ {
this.CheckPCMConfig(pcm); this.CheckPCMConfig(pcm);
this.m_pcm = pcm;
this.pcm = pcm; this.m_outputPath = path;
this.outputPath = path; this.m_outputStream = File.Create(path);
this.outputStream = File.Create(path);
}
public LameWriter(Stream output, AudioPCMConfig pcm)
{
this.CheckPCMConfig(pcm);
this.outputStream = output;
this.pcm = pcm;
} }
private void CheckPCMConfig(AudioPCMConfig pcm) private void CheckPCMConfig(AudioPCMConfig pcm)
@@ -140,9 +137,9 @@ namespace CUETools.Codecs.LAME
int flushResult; int flushResult;
unsafe unsafe
{ {
fixed (byte* outputBufferPtr = outputBuffer) fixed (byte* outputBufferPtr = m_outputBuffer)
{ {
flushResult = lame_encode_flush(handle, (IntPtr)outputBufferPtr, outputBuffer.Length); flushResult = lame_encode_flush(m_handle, (IntPtr)outputBufferPtr, m_outputBuffer.Length);
} }
} }
if (flushResult < 0) if (flushResult < 0)
@@ -151,19 +148,19 @@ namespace CUETools.Codecs.LAME
} }
if (flushResult > 0) if (flushResult > 0)
{ {
this.outputStream.Write(this.outputBuffer, 0, flushResult); this.m_outputStream.Write(this.m_outputBuffer, 0, flushResult);
} }
int lametagFrameSize = this.GetLametagFrame(); int lametagFrameSize = this.GetLametagFrame();
this.outputStream.Seek(0, SeekOrigin.Begin); this.m_outputStream.Seek(0, SeekOrigin.Begin);
this.outputStream.Write(this.outputBuffer, 0, lametagFrameSize); this.m_outputStream.Write(this.m_outputBuffer, 0, lametagFrameSize);
} }
public void Close() public void Close()
{ {
if (!this.closed) if (!this.m_closed)
{ {
if (this.initialized) if (this.m_initialized)
{ {
try try
{ {
@@ -173,20 +170,20 @@ namespace CUETools.Codecs.LAME
} }
finally finally
{ {
lame_close(handle); lame_close(m_handle);
} }
} }
finally finally
{ {
handle = IntPtr.Zero; m_handle = IntPtr.Zero;
if (this.outputPath != null) if (this.m_outputPath != null)
{ {
this.outputStream.Close(); this.m_outputStream.Close();
} }
} }
} }
this.closed = true; this.m_closed = true;
} }
} }
@@ -197,16 +194,16 @@ namespace CUETools.Codecs.LAME
uint lametagFrameResult; uint lametagFrameResult;
unsafe unsafe
{ {
fixed (byte* outputBufferPtr = outputBuffer) fixed (byte* outputBufferPtr = m_outputBuffer)
{ {
lametagFrameResult = lame_get_lametag_frame(this.handle, (IntPtr)outputBufferPtr, (uint)outputBuffer.Length); lametagFrameResult = lame_get_lametag_frame(this.m_handle, (IntPtr)outputBufferPtr, (uint)m_outputBuffer.Length);
} }
} }
if (lametagFrameResult < 0) if (lametagFrameResult < 0)
{ {
throw new LameException("Error getting lametag frame."); throw new LameException("Error getting lametag frame.");
} }
if (lametagFrameResult <= outputBuffer.Length) if (lametagFrameResult <= m_outputBuffer.Length)
{ {
return (int)lametagFrameResult; return (int)lametagFrameResult;
} }
@@ -220,83 +217,64 @@ namespace CUETools.Codecs.LAME
{ {
fixed (byte* outputBufferPtr = outputBuffer) fixed (byte* outputBufferPtr = outputBuffer)
{ {
return lame_get_lametag_frame(handle, (IntPtr)outputBufferPtr, (uint)outputBuffer.Length); return lame_get_lametag_frame(m_handle, (IntPtr)outputBufferPtr, (uint)outputBuffer.Length);
} }
} }
} }
private void EnsureInitialized() private void EnsureInitialized()
{ {
if (!this.initialized) if (!this.m_initialized)
{ {
var config = this.Config; m_handle = lame_init();
handle = lame_init(); lame_set_bWriteVbrTag(m_handle, 1);
lame_set_write_id3tag_automatic(m_handle, 0);
lame_set_bWriteVbrTag(handle, 1); lame_set_num_channels(m_handle, this.m_pcm.ChannelCount);
lame_set_write_id3tag_automatic(handle, 0); lame_set_in_samplerate(m_handle, this.m_pcm.SampleRate);
lame_set_num_channels(handle, this.pcm.ChannelCount); if (this.m_finalSampleCount != 0)
lame_set_in_samplerate(handle, this.pcm.SampleRate);
lame_set_quality(handle, (int)config.Quality);
if (this.finalSampleCount != 0)
{ {
lame_set_num_samples(handle, this.finalSampleCount); lame_set_num_samples(m_handle, this.m_finalSampleCount);
} }
lame_set_VBR(this.handle, (int)config.VbrMode); m_settings.Apply(m_handle);
switch (config.VbrMode) if (lame_init_params(m_handle) != 0)
{
case LameVbrMode.Abr:
lame_set_VBR_mean_bitrate_kbps(handle, config.Bitrate);
break;
case LameVbrMode.Default:
lame_set_VBR_quality(handle, config.VbrQuality);
break;
case LameVbrMode.Off:
lame_set_brate(handle, config.Bitrate);
break;
default:
throw new ArgumentException("Only ABR, Default and Off VBR modes are supported.");
}
if (lame_init_params(handle) != 0)
{ {
throw new LameException("lame_init_params failed"); throw new LameException("lame_init_params failed");
} }
this.initialized = true; this.m_initialized = true;
} }
} }
public void Delete() public void Delete()
{ {
if (this.outputPath == null) if (this.m_outputPath == null)
{ {
throw new InvalidOperationException("This writer was not created from file."); throw new InvalidOperationException("This writer was not created from file.");
} }
if (!closed) if (!m_closed)
{ {
this.Close(); this.Close();
File.Delete(this.outputPath); File.Delete(this.m_outputPath);
} }
} }
private void EnsureOutputBufferSize(int requiredSize) private void EnsureOutputBufferSize(int requiredSize)
{ {
if (this.outputBuffer == null || this.outputBuffer.Length < requiredSize) if (this.m_outputBuffer == null || this.m_outputBuffer.Length < requiredSize)
{ {
this.outputBuffer = new byte[requiredSize]; this.m_outputBuffer = new byte[requiredSize];
} }
} }
public void Write(AudioBuffer buffer) public void Write(AudioBuffer buffer)
{ {
if (this.closed) if (this.m_closed)
{ {
throw new InvalidOperationException("Writer already closed."); throw new InvalidOperationException("Writer already closed.");
} }
@@ -314,9 +292,9 @@ namespace CUETools.Codecs.LAME
{ {
fixed (byte* bytesPtr = bytes) fixed (byte* bytesPtr = bytes)
{ {
fixed (byte* outputBufferPtr = this.outputBuffer) fixed (byte* outputBufferPtr = this.m_outputBuffer)
{ {
result = lame_encode_buffer_interleaved(handle, (IntPtr)bytesPtr, buffer.Length, (IntPtr)outputBufferPtr, outputBuffer.Length); result = lame_encode_buffer_interleaved(m_handle, (IntPtr)bytesPtr, buffer.Length, (IntPtr)outputBufferPtr, m_outputBuffer.Length);
} }
} }
} }
@@ -340,7 +318,7 @@ namespace CUETools.Codecs.LAME
if (result > 0) if (result > 0)
{ {
this.outputStream.Write(this.outputBuffer, 0, result); this.m_outputStream.Write(this.m_outputBuffer, 0, result);
} }
} }
} }

View File

@@ -1,43 +0,0 @@
using System;
using System.IO;
namespace CUETools.Codecs.LAME
{
[AudioEncoderClass("CBR (libmp3lame)", "mp3", false, 1, typeof(LameWriterCBRSettings))]
public class LameWriterCBR : LameWriter
{
public LameWriterCBR(string path, Stream IO, AudioPCMConfig pcm)
: base(IO, pcm)
{
}
public LameWriterCBR(string path, AudioPCMConfig pcm)
: base(path, pcm)
{
}
LameWriterCBRSettings _settings = new LameWriterCBRSettings();
public override AudioEncoderSettings Settings
{
get
{
return _settings;
}
set
{
if (value as LameWriterCBRSettings == null)
throw new Exception("Unsupported options " + value);
_settings = value as LameWriterCBRSettings;
}
}
protected override LameWriterConfig Config
{
get
{
return LameWriterConfig.CreateCbr(LameWriterCBRSettings.bps_table[this._settings.EncoderModeIndex], this._settings.Quality);
}
}
}
}

View File

@@ -5,7 +5,7 @@ using System.Text;
namespace CUETools.Codecs.LAME namespace CUETools.Codecs.LAME
{ {
public class LameWriterCBRSettings : AudioEncoderSettings public class LameWriterCBRSettings : LameWriterSettings
{ {
public static readonly int[] bps_table = new int[] { 96, 128, 192, 256, 320 }; public static readonly int[] bps_table = new int[] { 96, 128, 192, 256, 320 };
@@ -16,5 +16,12 @@ namespace CUETools.Codecs.LAME
: base("96 128 192 256 320", "256") : base("96 128 192 256 320", "256")
{ {
} }
public override void Apply(IntPtr lame)
{
LameWriter.lame_set_VBR(lame, (int)LameVbrMode.Off);
LameWriter.lame_set_brate(lame, LameWriterCBRSettings.bps_table[this.EncoderModeIndex]);
LameWriter.lame_set_quality(lame, (int)this.Quality);
}
} }
} }

View File

@@ -1,34 +1,19 @@
using System; using System;
using System.Collections.Generic;
using System.Text;
namespace CUETools.Codecs.LAME namespace CUETools.Codecs.LAME
{ {
public class LameWriterConfig public class LameWriterSettings : AudioEncoderSettings
{ {
public LameQuality Quality { get; set; } public LameWriterSettings(string modes, string defaultMode)
public LameVbrMode VbrMode { get; set; } : base(modes, defaultMode)
public int VbrQuality { get; set; }
public int Bitrate { get; set; }
public LameWriterConfig()
{ {
Quality = LameQuality.High;
VbrMode = LameVbrMode.Default;
VbrQuality = 5;
} }
public static LameWriterConfig CreateCbr(int bitrate, LameQuality encodeQuality = LameQuality.High) public virtual void Apply(IntPtr lame)
{ {
return new LameWriterConfig() { VbrMode = LameVbrMode.Off, Bitrate = bitrate, Quality = encodeQuality }; throw new MethodAccessException();
}
public static LameWriterConfig CreateAbr(int bitrate, LameQuality encodeQuality = LameQuality.High)
{
return new LameWriterConfig() { VbrMode = LameVbrMode.Abr, Bitrate = bitrate, Quality = encodeQuality };
}
public static LameWriterConfig CreateVbr(int vbrQuality, LameQuality encodeQuality = LameQuality.High)
{
return new LameWriterConfig() { VbrMode = LameVbrMode.Default, VbrQuality = vbrQuality, Quality = encodeQuality };
} }
} }
} }

View File

@@ -1,43 +0,0 @@
using System;
using System.IO;
namespace CUETools.Codecs.LAME
{
[AudioEncoderClass("VBR (libmp3lame)", "mp3", false, 2, typeof(LameWriterVBRSettings))]
public class LameWriterVBR : LameWriter
{
public LameWriterVBR(string path, Stream IO, AudioPCMConfig pcm)
: base(IO, pcm)
{
}
public LameWriterVBR(string path, AudioPCMConfig pcm)
: base(path, pcm)
{
}
LameWriterVBRSettings _settings = new LameWriterVBRSettings();
public override AudioEncoderSettings Settings
{
get
{
return _settings;
}
set
{
if (value as LameWriterVBRSettings == null)
throw new Exception("Unsupported options " + value);
_settings = value as LameWriterVBRSettings;
}
}
protected override LameWriterConfig Config
{
get
{
return LameWriterConfig.CreateVbr(9 - this._settings.EncoderModeIndex, this._settings.Quality);
}
}
}
}

View File

@@ -5,7 +5,7 @@ using System.Text;
namespace CUETools.Codecs.LAME namespace CUETools.Codecs.LAME
{ {
public class LameWriterVBRSettings: AudioEncoderSettings public class LameWriterVBRSettings : LameWriterSettings
{ {
[DefaultValue(LameQuality.High)] [DefaultValue(LameQuality.High)]
public LameQuality Quality { get; set; } public LameQuality Quality { get; set; }
@@ -14,5 +14,12 @@ namespace CUETools.Codecs.LAME
: base("V9 V8 V7 V6 V5 V4 V3 V2 V1 V0", "V2") : base("V9 V8 V7 V6 V5 V4 V3 V2 V1 V0", "V2")
{ {
} }
public override void Apply(IntPtr lame)
{
LameWriter.lame_set_VBR(lame, (int)LameVbrMode.Default);
LameWriter.lame_set_VBR_quality(lame, 9 - this.EncoderModeIndex);
LameWriter.lame_set_quality(lame, (int)this.Quality);
}
} }
} }