mirror of
https://github.com/claunia/cuetools.net.git
synced 2025-12-16 18:14:25 +00:00
Replaced C++/CLR version of Monkey's Audio plugin with a .dll and a PInvoke plugin
This commit is contained in:
158
CUETools.Codecs.MACLib/AudioEncoder.cs
Normal file
158
CUETools.Codecs.MACLib/AudioEncoder.cs
Normal file
@@ -0,0 +1,158 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace CUETools.Codecs.MACLib
|
||||
{
|
||||
public unsafe class AudioEncoder : IAudioDest, IDisposable
|
||||
{
|
||||
public AudioEncoder(EncoderSettings settings, string path, Stream output = null)
|
||||
{
|
||||
m_settings = settings;
|
||||
|
||||
m_path = path;
|
||||
m_stream = output;
|
||||
m_settings = settings;
|
||||
m_streamGiven = output != null;
|
||||
m_initialized = false;
|
||||
m_finalSampleCount = 0;
|
||||
m_samplesWritten = 0;
|
||||
|
||||
if (m_settings.PCM.ChannelCount != 1 && m_settings.PCM.ChannelCount != 2)
|
||||
throw new Exception("Only stereo and mono audio formats are allowed.");
|
||||
if (m_settings.PCM.BitsPerSample != 16 && m_settings.PCM.BitsPerSample != 24)
|
||||
throw new Exception("bits per sample must be 16 or 24");
|
||||
|
||||
int nRetVal;
|
||||
pAPECompress = MACLibDll.c_APECompress_Create(out nRetVal);
|
||||
if (pAPECompress == null)
|
||||
throw new Exception("Unable to open APE compressor.");
|
||||
}
|
||||
|
||||
public IAudioEncoderSettings Settings => m_settings;
|
||||
|
||||
public string Path { get => m_path; }
|
||||
|
||||
public long FinalSampleCount
|
||||
{
|
||||
get => m_finalSampleCount;
|
||||
set
|
||||
{
|
||||
if (value < 0)
|
||||
throw new Exception("invalid final sample count");
|
||||
if (m_initialized)
|
||||
throw new Exception("final sample count cannot be changed after encoding begins");
|
||||
m_finalSampleCount = value;
|
||||
}
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (pAPECompress != null)
|
||||
MACLibDll.c_APECompress_Finish(pAPECompress, null, 0, 0);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
Dispose();
|
||||
if ((m_finalSampleCount != 0) && (m_samplesWritten != m_finalSampleCount))
|
||||
throw new Exception("samples written differs from the expected sample count");
|
||||
}
|
||||
|
||||
public void Delete()
|
||||
{
|
||||
var path = m_path;
|
||||
Dispose(true);
|
||||
m_initialized = false;
|
||||
if (path != "")
|
||||
File.Delete(path);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
if (m_StreamIO != null)
|
||||
{
|
||||
m_StreamIO.Dispose();
|
||||
m_StreamIO = null;
|
||||
}
|
||||
if (m_stream != null)
|
||||
{
|
||||
m_stream.Dispose();
|
||||
m_stream = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (pAPECompress != null) MACLibDll.c_APECompress_Destroy(pAPECompress);
|
||||
pAPECompress = IntPtr.Zero;
|
||||
}
|
||||
|
||||
~AudioEncoder()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
|
||||
public void Write(AudioBuffer sampleBuffer)
|
||||
{
|
||||
if (!m_initialized) Initialize();
|
||||
|
||||
sampleBuffer.Prepare(this);
|
||||
|
||||
fixed (byte* pSampleBuffer = &sampleBuffer.Bytes[0])
|
||||
if (0 != MACLibDll.c_APECompress_AddData(pAPECompress, pSampleBuffer, sampleBuffer.ByteLength))
|
||||
throw new Exception("An error occurred while encoding");
|
||||
|
||||
m_samplesWritten += sampleBuffer.Length;
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
if (m_stream == null)
|
||||
m_stream = new FileStream(m_path, FileMode.Create, FileAccess.ReadWrite, FileShare.Read, 0x10000);
|
||||
m_StreamIO = new StreamIO(m_stream);
|
||||
|
||||
WAVEFORMATEX* pWaveFormatEx = stackalloc WAVEFORMATEX[1];
|
||||
pWaveFormatEx->extraSize = 0;
|
||||
pWaveFormatEx->sampleRate = m_settings.PCM.SampleRate;
|
||||
pWaveFormatEx->bitsPerSample = (short)m_settings.PCM.BitsPerSample;
|
||||
pWaveFormatEx->channels = (short)m_settings.PCM.ChannelCount;
|
||||
pWaveFormatEx->waveFormatTag = 1;
|
||||
pWaveFormatEx->blockAlign = (short)m_settings.PCM.BlockAlign;
|
||||
pWaveFormatEx->averageBytesPerSecond = m_settings.PCM.BlockAlign * m_settings.PCM.SampleRate;
|
||||
|
||||
int compressionLevel = (m_settings.GetEncoderModeIndex() + 1) * 1000;
|
||||
|
||||
int res = MACLibDll.c_APECompress_StartEx(
|
||||
pAPECompress,
|
||||
m_StreamIO.Callbacks,
|
||||
pWaveFormatEx,
|
||||
(m_finalSampleCount == 0) ? -1 : (int) (m_finalSampleCount * m_settings.PCM.BlockAlign),
|
||||
compressionLevel,
|
||||
null,
|
||||
/*CREATE_WAV_HEADER_ON_DECOMPRESSION*/-1);
|
||||
if (res != 0)
|
||||
throw new Exception("Unable to create the encoder.");
|
||||
|
||||
m_initialized = true;
|
||||
}
|
||||
|
||||
|
||||
IntPtr pAPECompress;
|
||||
EncoderSettings m_settings;
|
||||
Stream m_stream;
|
||||
bool m_streamGiven;
|
||||
bool m_initialized;
|
||||
string m_path;
|
||||
long m_finalSampleCount, m_samplesWritten;
|
||||
StreamIO m_StreamIO;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user