Skip to content

Commit

Permalink
Added LameConfig to give greater control over encoder setup. Changed …
Browse files Browse the repository at this point in the history
…constructors to use this, reducing duplication.
  • Loading branch information
Corey-M committed Apr 6, 2020
1 parent cdb7f16 commit 6172e16
Show file tree
Hide file tree
Showing 2 changed files with 145 additions and 64 deletions.
120 changes: 120 additions & 0 deletions NAudio.Lame/LameConfig.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
using LameDLLWrap;

namespace NAudio.Lame
{
/// <summary>
/// Holds configuration for the LAME engine, applied when the encoder instance is initialised.
/// </summary>
public class LameConfig
{
#region Quality
private LAMEPreset? _preset = null;
/// <summary>Compression preset, clears <see cref="BitRate"/> if set, defaults to STANDARD</summary>
public LAMEPreset? Preset
{
get => _preset;
set
{
_preset = value;
if (value != null)
_bitrate = null;
}
}

private int? _bitrate = null;
/// <summary>Compression bitrate, clears <see cref="Preset"/> if set.</summary>
public int? BitRate
{
get => _bitrate;
set
{
_bitrate = value;
if (value != null)
_preset = null;
}
}
#endregion

#region Input settings
/// <summary>Global amplification factor.</summary>
public float? Scale { get; set; }

/// <summary>Left channel amplification.</summary>
public float? ScaleLeft { get; set; }

/// <summary>Right channel amplification.</summary>
public float? ScaleRight { get; set; }
#endregion

#region General Control
/// <summary>Enable analysis.</summary>
public bool? Analysis { get; set; }

/// <summary>WRite VBR tag to MP3 file.</summary>
public bool? WriteVBRTag { get; set; }

/// <summary>Specify MPEG channel mode, use best guess if false/unset.</summary>
public MPEGMode? Mode { get; set; }

/// <summary>Force M/S mode.</summary>
public bool? ForceMS { get; set; }

/// <summary>Use free format.</summary>
public bool? UseFreeFormat { get; set; }
#endregion

#region Frame Parameters
/// <summary>Set output Copyright flag.</summary>
public bool? Copyright { get; set; }

/// <summary>Set output Original flag.</summary>
public bool? Original { get; set; }

/// <summary>Set error protection. Uses 2 bytes from each fram for CRC checksum.</summary>
public bool? ErrorProtection { get; set; }

/// <summary>Enforce strict ISO compliance.</summary>
public bool? StrictISO { get; set; }
#endregion

#region ID3
/// <summary>ID3 tag data, to be added after configuration.</summary>
public ID3TagData ID3 { get; set; }
#endregion

#region DLL initialisation
/// <summary>Create <see cref="LibMp3Lame"/> and configure it.</summary>
/// <returns></returns>
public LibMp3Lame ConfigureDLL()
{
var result = new LibMp3Lame();

// Input settings
if (Scale != null) result.Scale = Scale.Value;
if (ScaleLeft != null) result.ScaleLeft = ScaleLeft.Value;
if (ScaleRight != null) result.ScaleRight = ScaleRight.Value;

// General Control
if (Analysis != null) result.Analysis = Analysis.Value;
if (WriteVBRTag != null) result.WriteVBRTag = WriteVBRTag.Value;
if (Mode != null) result.Mode = Mode.Value;
if (ForceMS != null) result.ForceMS = ForceMS.Value;
if (UseFreeFormat != null) result.UseFreeFormat = UseFreeFormat.Value;

// Frame Parameters
if (Copyright != null) result.Copyright = Copyright.Value;
if (Original != null) result.Original = Original.Value;
if (ErrorProtection != null) result.ErrorProtection = ErrorProtection.Value;
if (StrictISO != null) result.StrictISO = StrictISO.Value;

// Set quality
if (_bitrate != null)
result.BitRate = _bitrate.Value;
else
result.SetPreset((int)(_preset ?? LAMEPreset.STANDARD));

return result;
}
#endregion
}
}
89 changes: 25 additions & 64 deletions NAudio.Lame/LameMP3FileWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ public int MinProgressTime
public event ProgressHandler OnProgress;

private DateTime _lastProgress = DateTime.Now;

// Pre-initialisation
#endregion

#region Lifecycle
Expand All @@ -92,62 +94,8 @@ public LameMP3FileWriter(string outFileName, WaveFormat format, LAMEPreset quali
/// <param name="quality">LAME quality preset</param>
/// <param name="id3">Optional ID3 data block</param>
public LameMP3FileWriter(Stream outStream, WaveFormat format, LAMEPreset quality, ID3TagData id3 = null)
: base()
{
if (format == null)
throw new ArgumentNullException("format");

// check for unsupported wave formats
if (format.Channels != 1 && format.Channels != 2)
throw new ArgumentException($"Unsupported number of channels {format.Channels}", "format");
if (format.Encoding != WaveFormatEncoding.Pcm && format.Encoding != WaveFormatEncoding.IeeeFloat)
throw new ArgumentException($"Unsupported encoding format {format.Encoding}", "format");
if (format.Encoding == WaveFormatEncoding.Pcm && format.BitsPerSample != 16)
throw new ArgumentException($"Unsupported PCM sample size {format.BitsPerSample}", "format");
if (format.Encoding == WaveFormatEncoding.IeeeFloat && format.BitsPerSample != 32)
throw new ArgumentException($"Unsupported Float sample size {format.BitsPerSample}", "format");
if (format.SampleRate < 8000 || format.SampleRate > 48000)
throw new ArgumentException($"Unsupported Sample Rate {format.SampleRate}", "format");

// select encoder function that matches data format
if (format.Encoding == WaveFormatEncoding.Pcm)
{
if (format.Channels == 1)
_encode = Encode_pcm_16_mono;
else
_encode = Encode_pcm_16_stereo;
}
else
{
if (format.Channels == 1)
_encode = Encode_float_mono;
else
_encode = Encode_float_stereo;
}

// Set base properties
_inputFormat = format;
_outStream = outStream ?? throw new ArgumentNullException("outStream");
_disposeOutput = false;

// Allocate buffers based on sample rate
_inBuffer = new ArrayUnion(format.AverageBytesPerSecond);
_outBuffer = new byte[format.SampleRate * 5 / 4 + 7200];

// Initialize lame library
_lame = new LibMp3Lame
{
InputSampleRate = format.SampleRate,
NumChannels = format.Channels
};

_lame.SetPreset((int)quality);

if (id3 != null)
ApplyID3Tag(id3);

_lame.InitParams();
}
: this(outStream, format, new LameConfig { Preset = quality, ID3 = id3 })
{ }

/// <summary>Create MP3FileWriter to write to a file on disk</summary>
/// <param name="outFileName">Name of file to create</param>
Expand All @@ -166,6 +114,24 @@ public LameMP3FileWriter(string outFileName, WaveFormat format, int bitRate, ID3
/// <param name="bitRate">Output bit rate in kbps</param>
/// <param name="id3">Optional ID3 data block</param>
public LameMP3FileWriter(Stream outStream, WaveFormat format, int bitRate, ID3TagData id3 = null)
: this(outStream, format, new LameConfig { BitRate = bitRate, ID3 = id3 })
{ }

/// <summary>Create MP3FileWriter to write to a file on disk</summary>
/// <param name="outFileName">Name of file to create</param>
/// <param name="format">Input WaveFormat</param>
/// <param name="config">LAME configuration</param>
public LameMP3FileWriter(string outFileName, WaveFormat format, LameConfig config)
: this(File.Create(outFileName), format, config)
{
_disposeOutput = true;
}

/// <summary>Create MP3FileWriter to write to supplied stream</summary>
/// <param name="outStream">Stream to write encoded data to</param>
/// <param name="format">Input WaveFormat</param>
/// <param name="config">LAME configuration</param>
public LameMP3FileWriter(Stream outStream, WaveFormat format, LameConfig config)
: base()
{
if (format == null)
Expand Down Expand Up @@ -209,15 +175,10 @@ public LameMP3FileWriter(Stream outStream, WaveFormat format, int bitRate, ID3Ta
_outBuffer = new byte[format.SampleRate * 5 / 4 + 7200];

// Initialize lame library
_lame = new LibMp3Lame
{
InputSampleRate = format.SampleRate,
NumChannels = format.Channels,
BitRate = bitRate
};
_lame = config.ConfigureDLL();

if (id3 != null)
ApplyID3Tag(id3);
if (config.ID3 != null)
ApplyID3Tag(config.ID3);

_lame.InitParams();
}
Expand Down

0 comments on commit 6172e16

Please sign in to comment.