mirror of
https://github.com/claunia/cuetools.net.git
synced 2025-12-16 18:14:25 +00:00
Refactored the LAME interop.
This commit is contained in:
@@ -82,7 +82,7 @@ namespace CUETools.Codecs.Icecast
|
|||||||
{
|
{
|
||||||
encoder = new CUETools.Codecs.LAME.LAMEEncoderCBR("", reqStream, AudioPCMConfig.RedBook);
|
encoder = new CUETools.Codecs.LAME.LAMEEncoderCBR("", reqStream, AudioPCMConfig.RedBook);
|
||||||
(encoder.Settings as CUETools.Codecs.LAME.LAMEEncoderCBRSettings).StereoMode = settings.JointStereo ?
|
(encoder.Settings as CUETools.Codecs.LAME.LAMEEncoderCBRSettings).StereoMode = settings.JointStereo ?
|
||||||
CUETools.Codecs.LAME.MpegMode.JOINT_STEREO : CUETools.Codecs.LAME.MpegMode.STEREO;
|
CUETools.Codecs.LAME.Interop.MpegMode.JOINT_STEREO : CUETools.Codecs.LAME.Interop.MpegMode.STEREO;
|
||||||
(encoder.Settings as CUETools.Codecs.LAME.LAMEEncoderCBRSettings).CustomBitrate = settings.Bitrate;
|
(encoder.Settings as CUETools.Codecs.LAME.LAMEEncoderCBRSettings).CustomBitrate = settings.Bitrate;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,8 +59,22 @@
|
|||||||
<Reference Include="System.Xml" />
|
<Reference Include="System.Xml" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="Encoder.cs" />
|
<Compile Include="Interop\ACC.cs" />
|
||||||
<Compile Include="Lame.cs" />
|
<Compile Include="Interop\BE_CONFIG.cs" />
|
||||||
|
<Compile Include="Interop\BE_VERSION.cs" />
|
||||||
|
<Compile Include="Interop\Format.cs" />
|
||||||
|
<Compile Include="Interop\Lame_encDLL.cs" />
|
||||||
|
<Compile Include="Interop\LAME_QUALITY_PRESET.cs" />
|
||||||
|
<Compile Include="Interop\LHV1.cs" />
|
||||||
|
<Compile Include="Interop\MP3.cs" />
|
||||||
|
<Compile Include="Interop\MpegMode.cs" />
|
||||||
|
<Compile Include="Interop\VBRMETHOD.cs" />
|
||||||
|
<Compile Include="LAMEEncoder.cs" />
|
||||||
|
<Compile Include="LAMEEncoderCBR.cs" />
|
||||||
|
<Compile Include="LAMEEncoderCBRSettings.cs" />
|
||||||
|
<Compile Include="LAMEEncoderVBR.cs" />
|
||||||
|
<Compile Include="LAMEEncoderVBRProcessingQuality.cs" />
|
||||||
|
<Compile Include="LAMEEncoderVBRSettings.cs" />
|
||||||
<Compile Include="LameWriter.cs" />
|
<Compile Include="LameWriter.cs" />
|
||||||
<Compile Include="LameWriterSettings.cs" />
|
<Compile Include="LameWriterSettings.cs" />
|
||||||
<Compile Include="LameWriterVBR.cs" />
|
<Compile Include="LameWriterVBR.cs" />
|
||||||
@@ -90,6 +104,9 @@
|
|||||||
<Install>true</Install>
|
<Install>true</Install>
|
||||||
</BootstrapperPackage>
|
</BootstrapperPackage>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Content Include="Interop\License.txt" />
|
||||||
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||||
Other similar extension points exist, see Microsoft.Common.targets.
|
Other similar extension points exist, see Microsoft.Common.targets.
|
||||||
|
|||||||
@@ -1,438 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.ComponentModel;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Text;
|
|
||||||
using System.IO;
|
|
||||||
using CUETools.Codecs;
|
|
||||||
|
|
||||||
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 AudioPCMConfig _pcm;
|
|
||||||
private string _path;
|
|
||||||
private Stream _IO;
|
|
||||||
private long position = 0, sample_count = -1;
|
|
||||||
private long bytesWritten = 0;
|
|
||||||
|
|
||||||
public LAMEEncoder(string path, Stream IO, AudioPCMConfig pcm)
|
|
||||||
{
|
|
||||||
if (pcm.BitsPerSample != 16)// && pcm.BitsPerSample != 32)
|
|
||||||
throw new ArgumentOutOfRangeException("format", "Only 16 & 32 bits samples supported");
|
|
||||||
_pcm = pcm;
|
|
||||||
_path = path;
|
|
||||||
_IO = IO;
|
|
||||||
}
|
|
||||||
|
|
||||||
public LAMEEncoder(string path, AudioPCMConfig pcm)
|
|
||||||
: this(path, null, pcm)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
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(_pcm);
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool inited = false;
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual int CompressionLevel
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (value != 0)
|
|
||||||
throw new Exception("unsupported compression level");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual object Settings
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (value != null && value.GetType() != typeof(object))
|
|
||||||
throw new Exception("Unsupported options " + value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public long Padding
|
|
||||||
{
|
|
||||||
set { }
|
|
||||||
}
|
|
||||||
|
|
||||||
public long Position
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return position;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public long FinalSampleCount
|
|
||||||
{
|
|
||||||
set { sample_count = (int)value; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public long BlockSize
|
|
||||||
{
|
|
||||||
set { }
|
|
||||||
get { return 0; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public AudioPCMConfig PCM
|
|
||||||
{
|
|
||||||
get { return _pcm; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public string Path { get { return _path; } }
|
|
||||||
|
|
||||||
public long BytesWritten
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return bytesWritten;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum LAMEEncoderVBRProcessingQuality : uint
|
|
||||||
{
|
|
||||||
Best = 0,
|
|
||||||
Normal = 5,
|
|
||||||
}
|
|
||||||
|
|
||||||
public class LAMEEncoderVBRSettings
|
|
||||||
{
|
|
||||||
public LAMEEncoderVBRSettings()
|
|
||||||
{
|
|
||||||
// Iterate through each property and call ResetValue()
|
|
||||||
foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(this))
|
|
||||||
property.ResetValue(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
[DefaultValue(LAMEEncoderVBRProcessingQuality.Normal)]
|
|
||||||
public LAMEEncoderVBRProcessingQuality Quality { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
[AudioEncoderClass("lame VBR", "mp3", false, "V9 V8 V7 V6 V5 V4 V3 V2 V1 V0", "V2", 2, typeof(LAMEEncoderVBRSettings))]
|
|
||||||
public class LAMEEncoderVBR : LAMEEncoder
|
|
||||||
{
|
|
||||||
private int quality = 0;
|
|
||||||
|
|
||||||
public LAMEEncoderVBR(string path, Stream IO, AudioPCMConfig pcm)
|
|
||||||
: base(path, IO, pcm)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public LAMEEncoderVBR(string path, AudioPCMConfig pcm)
|
|
||||||
: base(path, null, pcm)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override BE_CONFIG MakeConfig()
|
|
||||||
{
|
|
||||||
BE_CONFIG Mp3Config = new BE_CONFIG(PCM, 0, (uint)_settings.Quality);
|
|
||||||
Mp3Config.format.lhv1.bWriteVBRHeader = 1;
|
|
||||||
Mp3Config.format.lhv1.nMode = MpegMode.JOINT_STEREO;
|
|
||||||
Mp3Config.format.lhv1.bEnableVBR = 1;
|
|
||||||
Mp3Config.format.lhv1.nVBRQuality = quality;
|
|
||||||
Mp3Config.format.lhv1.nVbrMethod = VBRMETHOD.VBR_METHOD_NEW; // --vbr-new
|
|
||||||
return Mp3Config;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override int CompressionLevel
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return 9 - quality;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (value < 0 || value > 9)
|
|
||||||
throw new Exception("unsupported compression level");
|
|
||||||
quality = 9 - value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LAMEEncoderVBRSettings _settings = new LAMEEncoderVBRSettings();
|
|
||||||
|
|
||||||
public override object Settings
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return _settings;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (value as LAMEEncoderVBRSettings == null)
|
|
||||||
throw new Exception("Unsupported options " + value);
|
|
||||||
_settings = value as LAMEEncoderVBRSettings;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class LAMEEncoderCBRSettings
|
|
||||||
{
|
|
||||||
public LAMEEncoderCBRSettings() {
|
|
||||||
// Iterate through each property and call ResetValue()
|
|
||||||
foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(this))
|
|
||||||
property.ResetValue(this);
|
|
||||||
}
|
|
||||||
[DefaultValue(0)]
|
|
||||||
public int CustomBitrate { get; set; }
|
|
||||||
[DefaultValue(MpegMode.STEREO)]
|
|
||||||
public MpegMode StereoMode { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
[AudioEncoderClass("lame CBR", "mp3", false, "96 128 192 256 320", "256", 2, typeof(LAMEEncoderCBRSettings))]
|
|
||||||
public class LAMEEncoderCBR : LAMEEncoder
|
|
||||||
{
|
|
||||||
private uint bps;
|
|
||||||
private static readonly uint[] bps_table = new uint[] {96, 128, 192, 256, 320};
|
|
||||||
|
|
||||||
public LAMEEncoderCBR(string path, Stream IO, AudioPCMConfig pcm)
|
|
||||||
: base(path, IO, pcm)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public LAMEEncoderCBR(string path, AudioPCMConfig pcm)
|
|
||||||
: base(path, null, pcm)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public override int CompressionLevel
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
for (int i = 0; i < bps_table.Length; i++)
|
|
||||||
if (bps == bps_table[i])
|
|
||||||
return i;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (value < 0 || value > bps_table.Length)
|
|
||||||
throw new Exception("unsupported compression level");
|
|
||||||
bps = bps_table[value];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LAMEEncoderCBRSettings _settings = new LAMEEncoderCBRSettings();
|
|
||||||
|
|
||||||
public override object Settings
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return _settings;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (value as LAMEEncoderCBRSettings == null)
|
|
||||||
throw new Exception("Unsupported options " + value);
|
|
||||||
_settings = value as LAMEEncoderCBRSettings;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override BE_CONFIG MakeConfig()
|
|
||||||
{
|
|
||||||
BE_CONFIG Mp3Config = new BE_CONFIG(PCM, _settings.CustomBitrate > 0 ? (uint)_settings.CustomBitrate : bps, 5);
|
|
||||||
Mp3Config.format.lhv1.bWriteVBRHeader = 1;
|
|
||||||
Mp3Config.format.lhv1.nMode = _settings.StereoMode;
|
|
||||||
//Mp3Config.format.lhv1.nVbrMethod = VBRMETHOD.VBR_METHOD_NONE; // --cbr
|
|
||||||
//Mp3Config.format.lhv1.nPreset = LAME_QUALITY_PRESET.LQP_NORMAL_QUALITY;
|
|
||||||
return Mp3Config;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
14
CUETools.Codecs.LAME/Interop/ACC.cs
Normal file
14
CUETools.Codecs.LAME/Interop/ACC.cs
Normal file
@@ -0,0 +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;
|
||||||
|
}
|
||||||
|
}
|
||||||
27
CUETools.Codecs.LAME/Interop/BE_CONFIG.cs
Normal file
27
CUETools.Codecs.LAME/Interop/BE_CONFIG.cs
Normal file
@@ -0,0 +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)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
34
CUETools.Codecs.LAME/Interop/BE_VERSION.cs
Normal file
34
CUETools.Codecs.LAME/Interop/BE_VERSION.cs
Normal file
@@ -0,0 +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];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
21
CUETools.Codecs.LAME/Interop/Format.cs
Normal file
21
CUETools.Codecs.LAME/Interop/Format.cs
Normal file
@@ -0,0 +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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
34
CUETools.Codecs.LAME/Interop/LAME_QUALITY_PRESET.cs
Normal file
34
CUETools.Codecs.LAME/Interop/LAME_QUALITY_PRESET.cs
Normal file
@@ -0,0 +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
|
||||||
|
}
|
||||||
|
}
|
||||||
130
CUETools.Codecs.LAME/Interop/LHV1.cs
Normal file
130
CUETools.Codecs.LAME/Interop/LHV1.cs
Normal file
@@ -0,0 +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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
161
CUETools.Codecs.LAME/Interop/Lame_encDLL.cs
Normal file
161
CUETools.Codecs.LAME/Interop/Lame_encDLL.cs
Normal file
@@ -0,0 +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);
|
||||||
|
}
|
||||||
|
}
|
||||||
25
CUETools.Codecs.LAME/Interop/License.txt
Normal file
25
CUETools.Codecs.LAME/Interop/License.txt
Normal file
@@ -0,0 +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.
|
||||||
|
For details, please visit http://www.mp3licensing.com.
|
||||||
17
CUETools.Codecs.LAME/Interop/MP3.cs
Normal file
17
CUETools.Codecs.LAME/Interop/MP3.cs
Normal file
@@ -0,0 +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;
|
||||||
|
}
|
||||||
|
}
|
||||||
13
CUETools.Codecs.LAME/Interop/MpegMode.cs
Normal file
13
CUETools.Codecs.LAME/Interop/MpegMode.cs
Normal file
@@ -0,0 +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. */
|
||||||
|
}
|
||||||
|
}
|
||||||
12
CUETools.Codecs.LAME/Interop/VBRMETHOD.cs
Normal file
12
CUETools.Codecs.LAME/Interop/VBRMETHOD.cs
Normal file
@@ -0,0 +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
|
||||||
|
}
|
||||||
|
}
|
||||||
281
CUETools.Codecs.LAME/LAMEEncoder.cs
Normal file
281
CUETools.Codecs.LAME/LAMEEncoder.cs
Normal file
@@ -0,0 +1,281 @@
|
|||||||
|
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 AudioPCMConfig _pcm;
|
||||||
|
private string _path;
|
||||||
|
private Stream _IO;
|
||||||
|
private long position = 0, sample_count = -1;
|
||||||
|
private long bytesWritten = 0;
|
||||||
|
private bool inited = false;
|
||||||
|
|
||||||
|
public virtual int CompressionLevel
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value != 0)
|
||||||
|
throw new Exception("unsupported compression level");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual object Settings
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value != null && value.GetType() != typeof(object))
|
||||||
|
throw new Exception("Unsupported options " + value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public long Padding
|
||||||
|
{
|
||||||
|
set { }
|
||||||
|
}
|
||||||
|
|
||||||
|
public long Position
|
||||||
|
{
|
||||||
|
get { return position; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public long FinalSampleCount
|
||||||
|
{
|
||||||
|
set { sample_count = (int)value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public long BlockSize
|
||||||
|
{
|
||||||
|
set { }
|
||||||
|
get { return 0; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public AudioPCMConfig PCM
|
||||||
|
{
|
||||||
|
get { return _pcm; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Path { get { return _path; } }
|
||||||
|
|
||||||
|
public long BytesWritten
|
||||||
|
{
|
||||||
|
get { return bytesWritten; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public LAMEEncoder(string path, Stream IO, AudioPCMConfig pcm)
|
||||||
|
{
|
||||||
|
if (pcm.BitsPerSample != 16)// && pcm.BitsPerSample != 32)
|
||||||
|
throw new ArgumentOutOfRangeException("format", "Only 16 & 32 bits samples supported");
|
||||||
|
_pcm = pcm;
|
||||||
|
_path = path;
|
||||||
|
_IO = IO;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LAMEEncoder(string path, AudioPCMConfig pcm)
|
||||||
|
: this(path, null, pcm)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
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(_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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
70
CUETools.Codecs.LAME/LAMEEncoderCBR.cs
Normal file
70
CUETools.Codecs.LAME/LAMEEncoderCBR.cs
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using CUETools.Codecs.LAME.Interop;
|
||||||
|
|
||||||
|
namespace CUETools.Codecs.LAME
|
||||||
|
{
|
||||||
|
[AudioEncoderClass("lame CBR", "mp3", false, "96 128 192 256 320", "256", 2, typeof(LAMEEncoderCBRSettings))]
|
||||||
|
public class LAMEEncoderCBR : LAMEEncoder
|
||||||
|
{
|
||||||
|
private static readonly uint[] bps_table = new uint[] { 96, 128, 192, 256, 320 };
|
||||||
|
|
||||||
|
private uint bps;
|
||||||
|
private LAMEEncoderCBRSettings _settings = new LAMEEncoderCBRSettings();
|
||||||
|
|
||||||
|
public override object Settings
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _settings;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value as LAMEEncoderCBRSettings == null)
|
||||||
|
throw new Exception("Unsupported options " + value);
|
||||||
|
_settings = value as LAMEEncoderCBRSettings;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int CompressionLevel
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
for (int i = 0; i < bps_table.Length; i++)
|
||||||
|
{
|
||||||
|
if (bps == bps_table[i])
|
||||||
|
{
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value < 0 || value > bps_table.Length)
|
||||||
|
throw new Exception("unsupported compression level");
|
||||||
|
bps = bps_table[value];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public LAMEEncoderCBR(string path, Stream IO, AudioPCMConfig pcm)
|
||||||
|
: base(path, IO, pcm)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public LAMEEncoderCBR(string path, AudioPCMConfig pcm)
|
||||||
|
: base(path, null, pcm)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override BE_CONFIG MakeConfig()
|
||||||
|
{
|
||||||
|
BE_CONFIG Mp3Config = new BE_CONFIG(PCM, _settings.CustomBitrate > 0 ? (uint)_settings.CustomBitrate : bps, 5);
|
||||||
|
Mp3Config.format.lhv1.bWriteVBRHeader = 1;
|
||||||
|
Mp3Config.format.lhv1.nMode = _settings.StereoMode;
|
||||||
|
//Mp3Config.format.lhv1.nVbrMethod = VBRMETHOD.VBR_METHOD_NONE; // --cbr
|
||||||
|
//Mp3Config.format.lhv1.nPreset = LAME_QUALITY_PRESET.LQP_NORMAL_QUALITY;
|
||||||
|
return Mp3Config;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
23
CUETools.Codecs.LAME/LAMEEncoderCBRSettings.cs
Normal file
23
CUETools.Codecs.LAME/LAMEEncoderCBRSettings.cs
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
using System.ComponentModel;
|
||||||
|
using CUETools.Codecs.LAME.Interop;
|
||||||
|
|
||||||
|
namespace CUETools.Codecs.LAME
|
||||||
|
{
|
||||||
|
public class LAMEEncoderCBRSettings
|
||||||
|
{
|
||||||
|
[DefaultValue(0)]
|
||||||
|
public int CustomBitrate { get; set; }
|
||||||
|
|
||||||
|
[DefaultValue(MpegMode.STEREO)]
|
||||||
|
public MpegMode StereoMode { get; set; }
|
||||||
|
|
||||||
|
public LAMEEncoderCBRSettings()
|
||||||
|
{
|
||||||
|
// Iterate through each property and call ResetValue()
|
||||||
|
foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(this))
|
||||||
|
{
|
||||||
|
property.ResetValue(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
62
CUETools.Codecs.LAME/LAMEEncoderVBR.cs
Normal file
62
CUETools.Codecs.LAME/LAMEEncoderVBR.cs
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using CUETools.Codecs.LAME.Interop;
|
||||||
|
|
||||||
|
namespace CUETools.Codecs.LAME
|
||||||
|
{
|
||||||
|
[AudioEncoderClass("lame VBR", "mp3", false, "V9 V8 V7 V6 V5 V4 V3 V2 V1 V0", "V2", 2, typeof(LAMEEncoderVBRSettings))]
|
||||||
|
public class LAMEEncoderVBR : LAMEEncoder
|
||||||
|
{
|
||||||
|
private int quality = 0;
|
||||||
|
private LAMEEncoderVBRSettings _settings = new LAMEEncoderVBRSettings();
|
||||||
|
|
||||||
|
public override int CompressionLevel
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return 9 - quality;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value < 0 || value > 9)
|
||||||
|
throw new Exception("unsupported compression level");
|
||||||
|
quality = 9 - value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override object Settings
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _settings;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value as LAMEEncoderVBRSettings == null)
|
||||||
|
throw new Exception("Unsupported options " + value);
|
||||||
|
_settings = value as LAMEEncoderVBRSettings;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public LAMEEncoderVBR(string path, Stream IO, AudioPCMConfig pcm)
|
||||||
|
: base(path, IO, pcm)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public LAMEEncoderVBR(string path, AudioPCMConfig pcm)
|
||||||
|
: base(path, null, pcm)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override BE_CONFIG MakeConfig()
|
||||||
|
{
|
||||||
|
BE_CONFIG Mp3Config = new BE_CONFIG(PCM, 0, (uint)_settings.Quality);
|
||||||
|
Mp3Config.format.lhv1.bWriteVBRHeader = 1;
|
||||||
|
Mp3Config.format.lhv1.nMode = MpegMode.JOINT_STEREO;
|
||||||
|
Mp3Config.format.lhv1.bEnableVBR = 1;
|
||||||
|
Mp3Config.format.lhv1.nVBRQuality = quality;
|
||||||
|
Mp3Config.format.lhv1.nVbrMethod = VBRMETHOD.VBR_METHOD_NEW; // --vbr-new
|
||||||
|
return Mp3Config;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
8
CUETools.Codecs.LAME/LAMEEncoderVBRProcessingQuality.cs
Normal file
8
CUETools.Codecs.LAME/LAMEEncoderVBRProcessingQuality.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
namespace CUETools.Codecs.LAME
|
||||||
|
{
|
||||||
|
public enum LAMEEncoderVBRProcessingQuality : uint
|
||||||
|
{
|
||||||
|
Best = 0,
|
||||||
|
Normal = 5,
|
||||||
|
}
|
||||||
|
}
|
||||||
18
CUETools.Codecs.LAME/LAMEEncoderVBRSettings.cs
Normal file
18
CUETools.Codecs.LAME/LAMEEncoderVBRSettings.cs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
using System.ComponentModel;
|
||||||
|
|
||||||
|
namespace CUETools.Codecs.LAME
|
||||||
|
{
|
||||||
|
public class LAMEEncoderVBRSettings
|
||||||
|
{
|
||||||
|
[DefaultValue(LAMEEncoderVBRProcessingQuality.Normal)]
|
||||||
|
public LAMEEncoderVBRProcessingQuality Quality { get; set; }
|
||||||
|
|
||||||
|
public LAMEEncoderVBRSettings()
|
||||||
|
{
|
||||||
|
// Iterate through each property and call ResetValue()
|
||||||
|
foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(this)) {
|
||||||
|
property.ResetValue(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,455 +0,0 @@
|
|||||||
//
|
|
||||||
//
|
|
||||||
// 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.
|
|
||||||
//
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using System.Runtime.Serialization;
|
|
||||||
using CUETools.Codecs;
|
|
||||||
|
|
||||||
namespace CUETools.Codecs.LAME
|
|
||||||
{
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 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. */
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
[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;
|
|
||||||
}
|
|
||||||
|
|
||||||
[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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential), Serializable]
|
|
||||||
public struct ACC
|
|
||||||
{
|
|
||||||
public uint dwSampleRate;
|
|
||||||
public byte byMode;
|
|
||||||
public ushort wBitrate;
|
|
||||||
public byte byEncodingMethod;
|
|
||||||
}
|
|
||||||
|
|
||||||
[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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[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)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[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];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,8 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text;
|
|
||||||
using CUETools.Codecs;
|
|
||||||
|
|
||||||
namespace CUETools.Codecs.LAME
|
namespace CUETools.Codecs.LAME
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user