Initial commit — M3U playlist tool with MP3/AAC encoding

This commit is contained in:
2026-05-10 03:02:53 +00:00
commit b14531362b
114 changed files with 14184 additions and 0 deletions
+437
View File
@@ -0,0 +1,437 @@
using System.Text;
namespace m3uTool
{
/// <summary>
/// LAME 32bits version 3.97 (beta 1, Oct 16 2005) (http://www.mp3dev.org/)
///
/// usage: lame [options] <infile> [outfile]
///
/// <infile> and/or <outfile> can be "-", which means stdin/stdout.
///
/// RECOMMENDED:
/// lame -V2 input.wav output.mp3
///
/// OPTIONS:
/// Input options:
/// -r input is raw pcm
/// -x force byte-swapping of input
/// -s sfreq sampling frequency of input file (kHz) - default 44.1 kHz
/// --bitwidth w input bit width is w (default 16)
/// --scale <arg> scale input (multiply PCM data) by <arg>
/// --scale-l <arg> scale channel 0 (left) input (multiply PCM data) by <arg>
/// --scale-r <arg> scale channel 1 (right) input (multiply PCM data) by <arg>
/// --mp1input input file is a MPEG Layer I file
/// --mp2input input file is a MPEG Layer II file
/// --mp3input input file is a MPEG Layer III file
/// --nogap <file1> <file2> <...>
/// gapless encoding for a set of contiguous files
/// --nogapout <dir>
/// output dir for gapless encoding (must precede --nogap)
/// --nogaptags allow the use of VBR tags in gapless encoding
///
/// Operational options:
/// -a downmix from stereo to mono file for mono encoding
/// -m <mode> (j)oint, (s)imple, (f)orce, (d)dual-mono, (m)ono
/// default is (j) or (s) depending on bitrate
/// joint = joins the best possible of MS and LR stereo
/// simple = force LR stereo on all frames
/// force = force MS stereo on all frames.
/// --preset type type must be "medium", "standard", "extreme", "insane",
/// or a value for an average desired bitrate and depending
/// on the value specified, appropriate quality settings will
/// be used.
/// "--preset help" gives more info on these
/// --comp <arg> choose bitrate to achive a compression ratio of <arg>
/// --replaygain-fast compute RG fast but slightly inaccurately (default)
/// --replaygain-accurate compute RG more accurately and find the peak sample
/// --noreplaygain disable ReplayGain analysis
/// --clipdetect enable --replaygain-accurate and print a message whether
/// clipping occurs and how far the waveform is from full scale
/// --freeformat produce a free format bitstream
/// --decode input=mp3 file, output=wav
/// -t disable writing wav header when using --decode
///
///
/// Verbosity:
/// --disptime <arg>print progress report every arg seconds
/// -S don't print progress report, VBR histograms
/// --nohist disable VBR histogram display
/// --silent don't print anything on screen
/// --quiet don't print anything on screen
/// --brief print more useful information
/// --verbose print a lot of useful information
///
/// Noise shaping & psycho acoustic algorithms:
/// -q <arg> <arg> = 0...9. Default -q 5
/// -q 0: Highest quality, very slow
/// -q 9: Poor quality, but fast
/// -h Same as -q 2. Recommended.
/// -f Same as -q 7. Fast, ok quality
///
///
/// CBR (constant bitrate, the default) options:
/// -b <bitrate> set the bitrate in kbps, default 128 kbps
/// --cbr enforce use of constant bitrate
///
/// ABR options:
/// --abr <bitrate> specify average bitrate desired (instead of quality)
///
/// VBR options:
/// -v use variable bitrate (VBR) (--vbr-old)
/// --vbr-old use old variable bitrate (VBR) routine
/// --vbr-new use new variable bitrate (VBR) routine
/// -V n quality setting for VBR. default n=4
/// 0=high quality,bigger files. 9=smaller files
/// -b <bitrate> specify minimum allowed bitrate, default 32 kbps
/// -B <bitrate> specify maximum allowed bitrate, default 320 kbps
/// -F strictly enforce the -b option, for use with players that
/// do not support low bitrate mp3
/// -t disable writing LAME Tag
/// -T enable and force writing LAME Tag
///
///
/// PSY related:
/// --short use short blocks when appropriate
/// --noshort do not use short blocks
/// --allshort use only short blocks
/// --notemp disable temporal masking effect
/// --nssafejoint M/S switching criterion
/// --nsmsfix <arg> M/S switching tuning [effective 0-3.5]
/// --interch x adjust inter-channel masking ratio
/// --ns-bass x adjust masking for sfbs 0 - 6 (long) 0 - 5 (short)
/// --ns-alto x adjust masking for sfbs 7 - 13 (long) 6 - 10 (short)
/// --ns-treble x adjust masking for sfbs 14 - 21 (long) 11 - 12 (short)
/// --ns-sfb21 x change ns-treble by x dB for sfb21
///
///
/// experimental switches:
/// -X n[,m] selects between different noise measurements
/// n for long block, m for short. if m is omitted, m = n
/// -Y lets LAME ignore noise in sfb21, like in CBR
/// -Z [n] currently no effects
///
///
/// MP3 header/stream options:
/// -e <emp> de-emphasis n/5/c (obsolete)
/// -c mark as copyright
/// -o mark as non-original
/// -p error protection. adds 16 bit checksum to every frame
/// (the checksum is computed correctly)
/// --nores disable the bit reservoir
/// --strictly-enforce-ISO comply as much as possible to ISO MPEG spec
///
/// Filter options:
/// -k keep ALL frequencies (disables all filters),
/// Can cause ringing and twinkling
/// --lowpass <freq> frequency(kHz), lowpass filter cutoff above freq
/// --lowpass-width <freq> frequency(kHz) - default 15% of lowpass freq
/// --highpass <freq> frequency(kHz), highpass filter cutoff below freq
/// --highpass-width <freq> frequency(kHz) - default 15% of highpass freq
/// --resample <sfreq> sampling frequency of output file(kHz)- default=automatic
///
///
/// ID3 tag options:
/// --tt <title> audio/song title (max 30 chars for version 1 tag)
/// --ta <artist> audio/song artist (max 30 chars for version 1 tag)
/// --tl <album> audio/song album (max 30 chars for version 1 tag)
/// --ty <year> audio/song year of issue (1 to 9999)
/// --tc <comment> user-defined text (max 30 chars for v1 tag, 28 for v1.1)
/// --tn <track> audio/song track number (1 to 255, creates v1.1 tag)
/// --tg <genre> audio/song genre (name or number in list)
/// --add-id3v2 force addition of version 2 tag
/// --id3v1-only add only a version 1 tag
/// --id3v2-only add only a version 2 tag
/// --space-id3v1 pad version 1 tag with spaces instead of nulls
/// --pad-id3v2 pad version 2 tag with extra 128 bytes
/// --genre-list print alphabetically sorted ID3 genre list and exit
/// --ignore-tag-errors ignore errors in values passed for tags
///
/// Note: A version 2 tag will NOT be added unless one of the input fields
/// won't fit in a version 1 tag (e.g. the title string is longer than 30
/// characters), or the '--add-id3v2' or '--id3v2-only' options are used,
/// or output is redirected to stdout.
///
///
/// MS-Windows-specific options:
/// --priority <type> sets the process priority:
/// 0,1 = Low priority (IDLE_PRIORITY_CLASS)
/// 2 = normal priority (NORMAL_PRIORITY_CLASS, defau
/// lt)
/// 3,4 = High priority (HIGH_PRIORITY_CLASS))
/// Note: Calling '--priority' without a parameter will select priority 0.
///
///
/// Platform specific:
/// --noasm <instructions> disable assembly optimizations for mmx/3dnow/sse
///
///
///
/// MPEG-1 layer III sample frequencies (kHz): 32 48 44.1
/// bitrates (kbps): 32 40 48 56 64 80 96 112 128 160 192 224 256 320
///
/// MPEG-2 layer III sample frequencies (kHz): 16 24 22.05
/// bitrates (kbps): 8 16 24 32 40 48 56 64 80 96 112 128 144 160
///
/// MPEG-2.5 layer III sample frequencies (kHz): 8 12 11.025
/// bitrates (kbps): 8 16 24 32 40 48 56 64 80 96 112 128 144 160
///</summary>
public class Mp3EncodingOptions : ProcessArguments
{
#region Private variables
/// <summary>
/// Set the bitrate in kbps, default 128 kbps -b <bitrate>
/// </summary>
private BitRate mBitRate = BitRate.KBPS_0;
/// <summary>
/// (j)oint, (s)imple, (f)orce, (d)dual-mono, (m)ono (-m)
/// </summary>
private ChannelMode mChannelMode = ChannelMode.JointStereo;
/// <summary>
/// input=mp3 file, output=wav (--decode)
/// </summary>
private bool mDecodeWav;
/// <summary>
/// disable writing wav header when using --decode (-t)
/// </summary>
private bool mDisableWavHeader;
/// <summary>
/// force byte-swapping of input (-x)
/// </summary>
private bool mForceByteSwappingOfInput;
/// <summary>
/// produce a free format bitstream (--freeformat)
/// </summary>
private bool mFreeFormat;
/// <summary>
/// Input filename. Can be "-", which means stdin.
/// </summary>
private string mInfile;
/// <summary>
/// downmix from stereo to mono file for mono encoding (-a)
/// </summary>
private bool mMonoDownmixing;
/// <summary>
/// input file is a MPEG Layer III file (--mp3input)
/// </summary>
private bool mMp3Input;
/// <summary>
/// Output filename. Can be "-", which means stdout.
/// </summary>
private string mOutfile;
/// <summary>
/// input is raw pcm (-r)
/// </summary>
private bool mRawPCMInputMode;
/// <summary>
/// input bit width is w (default 16) (--bitwidth w)
/// </summary>
private int mRawPCMInputSampleRate = 16;
/// <summary>
/// sampling frequency of input file (kHz) - default 44.1 kHz (-s sfreq)
/// </summary>
private SampleRateFrequency mRawPCMInputSampleSize = SampleRateFrequency.Hz_44100;
#endregion
#region Public properties
/// <summary>
/// Input filename. Can be "-", which means stdin.
/// </summary>
public string Infile
{
get { return mInfile; }
set { mInfile = value; }
}
/// <summary>
/// Output filename. Can be "-", which means stdout.
/// </summary>
public string Outfile
{
get { return mOutfile; }
set { mOutfile = value; }
}
/// <summary>
/// input is raw pcm (-r)
/// </summary>
public bool RawPCMInputMode
{
get { return mRawPCMInputMode; }
set { mRawPCMInputMode = value; }
}
/// <summary>
/// force byte-swapping of input (-x)
/// </summary>
public bool ForceByteSwappingOfInput
{
get { return mForceByteSwappingOfInput; }
set
{
mForceByteSwappingOfInput = value;
mRawPCMInputMode = true;
}
}
/// <summary>
/// sampling frequency of input file (kHz) - default 44.1 kHz (-s sfreq)
/// </summary>
public SampleRateFrequency RawPCMInputSampleSize
{
get { return mRawPCMInputSampleSize; }
set
{
mRawPCMInputSampleSize = value;
mRawPCMInputMode = true;
}
}
/// <summary>
/// input bit width is w (default 16) (--bitwidth w)
/// </summary>
public int RawPCMInputSampleRate
{
get { return mRawPCMInputSampleRate; }
set
{
mRawPCMInputSampleRate = value;
mRawPCMInputMode = true;
}
}
/// <summary>
/// input file is a MPEG Layer III file (--mp3input)
/// </summary>
public bool Mp3Input
{
get { return mMp3Input; }
set
{
mMp3Input = value;
if (mMp3Input)
mRawPCMInputMode = false;
}
}
/// <summary>
/// downmix from stereo to mono file for mono encoding (-a)
/// </summary>
public bool MonoDownmixing
{
get { return mMonoDownmixing; }
set { mMonoDownmixing = value; }
}
/// <summary>
/// (j)oint, (s)imple, (f)orce, (d)dual-mono, (m)ono (-m)
/// </summary>
public ChannelMode ChannelMode
{
get { return mChannelMode; }
set { mChannelMode = value; }
}
/// <summary>
/// produce a free format bitstream (--freeformat)
/// </summary>
public bool Freeformat
{
get { return mFreeFormat; }
set { mFreeFormat = value; }
}
/// <summary>
/// input=mp3 file, output=wav (--decode)
/// </summary>
public bool DecodeWav
{
get { return mDecodeWav; }
set { mDecodeWav = value; }
}
/// <summary>
/// disable writing wav header when using --decode (-t)
/// </summary>
public bool DisableWavHeader
{
get { return mDisableWavHeader; }
set
{
mDisableWavHeader = value;
if (mDisableWavHeader)
DecodeWav = true;
}
}
public BitRate BitRate
{
get { return mBitRate; }
set { mBitRate = value; }
}
#endregion
/// <summary>
/// Gets a string representing the command line arguments specified by the properties in the object.
/// </summary>
/// <returns></returns>
public override string GetCommandLineArguments()
{
var stringBuilder = new StringBuilder();
if (mRawPCMInputMode)
{
stringBuilder.Append(" -r");
if (mForceByteSwappingOfInput)
stringBuilder.Append(" -x");
if (mRawPCMInputSampleSize != SampleRateFrequency.Hz_44100)
stringBuilder.Append(" -s " +
SampleRateFrequencyUtility.GetSampleRateFrequencyInt(mRawPCMInputSampleSize));
if (mRawPCMInputSampleRate != 16)
stringBuilder.Append(" --bandwidth " + mRawPCMInputSampleRate);
}
if (mMp3Input)
stringBuilder.Append(" --mp3input");
if (mMonoDownmixing)
stringBuilder.Append(" -a");
if (mChannelMode != ChannelMode.JointStereo)
stringBuilder.Append(" -m " + ChannelModeUtility.GetChannelModeChar(mChannelMode));
if (mFreeFormat)
{
stringBuilder.Append(" --freeformat");
stringBuilder.Append(" -b " + BitRateFrequencyUtility.GetBitRateInt(BitRate));
}
if (mDecodeWav)
{
stringBuilder.Append(" --decode");
if (mDisableWavHeader)
stringBuilder.Append(" -t");
}
if (!string.IsNullOrEmpty(mInfile))
stringBuilder.Append(" " + GetQuotedCommandLineArgument(mInfile));
if (!string.IsNullOrEmpty(mOutfile))
stringBuilder.Append(" " + (mOutfile));
return stringBuilder.ToString();
}
}
}