mirror of
https://github.com/claunia/cuetools.net.git
synced 2025-12-16 10:04:24 +00:00
Replaced C++/CLR version of Monkey's Audio plugin with a .dll and a PInvoke plugin
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -15,5 +15,7 @@ launchSettings.json
|
||||
/CUETools/TestResults
|
||||
/ThirdParty/*/libFLAC_dynamic.*
|
||||
/ThirdParty/*/MACLib.*
|
||||
/ThirdParty/*/MACLibDll.*
|
||||
/ThirdParty/*/wavpackdll.*
|
||||
/ThirdParty/*/libwavpack.*
|
||||
/ThirdPartyDebug/
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
#include "stdafx.h"
|
||||
|
||||
using namespace System;
|
||||
using namespace System::Reflection;
|
||||
using namespace System::Runtime::CompilerServices;
|
||||
using namespace System::Runtime::InteropServices;
|
||||
using namespace System::Security::Permissions;
|
||||
|
||||
//
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
//
|
||||
[assembly:AssemblyTitleAttribute("APEDotNet")];
|
||||
[assembly:AssemblyDescriptionAttribute("")];
|
||||
[assembly:AssemblyConfigurationAttribute("")];
|
||||
[assembly:AssemblyCompanyAttribute("")];
|
||||
[assembly:AssemblyProductAttribute("APEDotNet")];
|
||||
[assembly:AssemblyCopyrightAttribute("Copyright (c) Greg Chudov 2008")];
|
||||
[assembly:AssemblyTrademarkAttribute("")];
|
||||
[assembly:AssemblyCultureAttribute("")];
|
||||
|
||||
//
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the value or you can default the Revision and Build Numbers
|
||||
// by using the '*' as shown below:
|
||||
|
||||
[assembly:AssemblyVersionAttribute("2.1.7.0")];
|
||||
|
||||
[assembly:ComVisible(false)];
|
||||
|
||||
[assembly:CLSCompliantAttribute(true)];
|
||||
|
||||
[assembly:SecurityPermission(SecurityAction::RequestMinimum, UnmanagedCode = true)];
|
||||
@@ -1,627 +0,0 @@
|
||||
// This is the main DLL file.
|
||||
|
||||
using namespace System;
|
||||
using namespace System::Text;
|
||||
using namespace System::Collections::Generic;
|
||||
using namespace System::Runtime::InteropServices;
|
||||
using namespace System::IO;
|
||||
using namespace CUETools::Codecs;
|
||||
|
||||
#define PLATFORM_WINDOWS
|
||||
#define PLATFORM_WINDOWS_NO_HEADER
|
||||
#define EXCLUDE_CIO
|
||||
#include "All.h"
|
||||
#include "MACLib.h"
|
||||
#include "IO.h"
|
||||
|
||||
using namespace ::APE;
|
||||
|
||||
namespace CUETools { namespace Codecs { namespace APE {
|
||||
|
||||
class CWinFileIO : public ::APE::CIO
|
||||
{
|
||||
public:
|
||||
|
||||
// construction / destruction
|
||||
CWinFileIO(GCHandle gchIO, GCHandle gchBuffer)
|
||||
{
|
||||
_gchIO = gchIO;
|
||||
_gchBuffer = gchBuffer;
|
||||
}
|
||||
~CWinFileIO()
|
||||
{
|
||||
}
|
||||
|
||||
// open / close
|
||||
int Open(const wchar_t * pName, bool bOpenReadOnly = false)
|
||||
{
|
||||
throw gcnew Exception("CIO::Open Unsupported.");
|
||||
}
|
||||
int Close()
|
||||
{
|
||||
throw gcnew Exception("CIO::Close Unsupported.");
|
||||
}
|
||||
|
||||
// read / write
|
||||
int Read(void * pBuffer, unsigned int nBytesToRead, unsigned int * pBytesRead);
|
||||
int Write(const void * pBuffer, unsigned int nBytesToWrite, unsigned int * pBytesWritten);
|
||||
|
||||
// seek
|
||||
int Seek(int nDistance, unsigned int nMoveMode);
|
||||
|
||||
// other functions
|
||||
int SetEOF()
|
||||
{
|
||||
throw gcnew Exception("CIO::SetEOF unsupported.");
|
||||
}
|
||||
|
||||
// creation / destruction
|
||||
int Create(const wchar_t * pName)
|
||||
{
|
||||
throw gcnew Exception("CIO::Create unsupported.");
|
||||
}
|
||||
|
||||
int Delete()
|
||||
{
|
||||
throw gcnew Exception("CIO::Delete unsupported.");
|
||||
}
|
||||
|
||||
// attributes
|
||||
int GetPosition();
|
||||
unsigned int GetSize();
|
||||
|
||||
int GetName(wchar_t * pBuffer)
|
||||
{
|
||||
throw gcnew Exception("CIO::GetName unsupported.");
|
||||
}
|
||||
|
||||
private:
|
||||
GCHandle _gchIO;
|
||||
GCHandle _gchBuffer;
|
||||
};
|
||||
|
||||
ref class AudioDecoder;
|
||||
|
||||
[Newtonsoft::Json::JsonObject(Newtonsoft::Json::MemberSerialization::OptIn)]
|
||||
public ref class DecoderSettings : public IAudioDecoderSettings
|
||||
{
|
||||
public:
|
||||
DecoderSettings()
|
||||
{
|
||||
}
|
||||
|
||||
[System::ComponentModel::Browsable(false)]
|
||||
virtual property String^ Name
|
||||
{
|
||||
String^ get() { return "MAC_SDK"; }
|
||||
}
|
||||
|
||||
[System::ComponentModel::Browsable(false)]
|
||||
virtual property String^ Extension
|
||||
{
|
||||
String^ get() { return "ape"; }
|
||||
}
|
||||
|
||||
[System::ComponentModel::Browsable(false)]
|
||||
virtual property Type^ DecoderType
|
||||
{
|
||||
Type^ get() { return AudioDecoder::typeid; }
|
||||
}
|
||||
|
||||
[System::ComponentModel::Browsable(false)]
|
||||
virtual property int Priority
|
||||
{
|
||||
int get() { return 1; }
|
||||
}
|
||||
|
||||
virtual IAudioDecoderSettings^ Clone()
|
||||
{
|
||||
return (IAudioDecoderSettings^)MemberwiseClone();
|
||||
}
|
||||
|
||||
property String^ Version
|
||||
{
|
||||
String^ get()
|
||||
{
|
||||
return MAC_VERSION_STRING;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public ref class AudioDecoder : public IAudioSource
|
||||
{
|
||||
public:
|
||||
AudioDecoder(DecoderSettings^ settings, String^ path, Stream^ IO)
|
||||
{
|
||||
m_settings = settings;
|
||||
pAPEDecompress = NULL;
|
||||
_sampleOffset = 0;
|
||||
_bufferOffset = 0;
|
||||
_bufferLength = 0;
|
||||
_path = path;
|
||||
|
||||
int nRetVal = 0;
|
||||
|
||||
_IO = (IO != nullptr) ? IO : gcnew FileStream (path, FileMode::Open, FileAccess::Read, FileShare::Read);
|
||||
_readBuffer = gcnew array<unsigned char>(0x4000);
|
||||
_gchIO = GCHandle::Alloc(_IO);
|
||||
_gchReadBuffer = GCHandle::Alloc(_readBuffer);
|
||||
_winFileIO = new CWinFileIO(_gchIO, _gchReadBuffer);
|
||||
pAPEDecompress = CreateIAPEDecompressEx (_winFileIO, &nRetVal);
|
||||
if (!pAPEDecompress) {
|
||||
throw gcnew Exception("Unable to open file.");
|
||||
}
|
||||
|
||||
pcm = gcnew AudioPCMConfig(
|
||||
pAPEDecompress->GetInfo (APE_INFO_BITS_PER_SAMPLE, 0, 0),
|
||||
pAPEDecompress->GetInfo (APE_INFO_CHANNELS, 0, 0),
|
||||
pAPEDecompress->GetInfo (APE_INFO_SAMPLE_RATE, 0, 0),
|
||||
(AudioPCMConfig::SpeakerConfig)0);
|
||||
|
||||
// make a buffer to hold 16384 blocks of audio data
|
||||
nBlockAlign = pAPEDecompress->GetInfo (APE_INFO_BLOCK_ALIGN, 0, 0);
|
||||
_samplesBuffer = gcnew array<unsigned char> (16384 * nBlockAlign);
|
||||
|
||||
// loop through the whole file
|
||||
_sampleCount = pAPEDecompress->GetInfo (APE_DECOMPRESS_TOTAL_BLOCKS, 0, 0); // * ?
|
||||
}
|
||||
|
||||
~AudioDecoder ()
|
||||
{
|
||||
if (_winFileIO)
|
||||
delete _winFileIO;
|
||||
if (_gchIO.IsAllocated)
|
||||
_gchIO.Free();
|
||||
if (_gchReadBuffer.IsAllocated)
|
||||
_gchReadBuffer.Free();
|
||||
}
|
||||
|
||||
virtual property AudioPCMConfig^ PCM {
|
||||
AudioPCMConfig^ get() {
|
||||
return pcm;
|
||||
}
|
||||
}
|
||||
|
||||
virtual property Int64 Length {
|
||||
Int64 get() {
|
||||
return _sampleCount;
|
||||
}
|
||||
}
|
||||
|
||||
virtual property Int64 Position
|
||||
{
|
||||
Int64 get() {
|
||||
return _sampleOffset - SamplesInBuffer;
|
||||
}
|
||||
void set(Int64 offset) {
|
||||
_sampleOffset = offset;
|
||||
_bufferOffset = 0;
|
||||
_bufferLength = 0;
|
||||
if (pAPEDecompress->Seek ((int) offset /*? */))
|
||||
throw gcnew Exception("Unable to seek.");
|
||||
}
|
||||
}
|
||||
|
||||
virtual property Int64 Remaining {
|
||||
Int64 get() {
|
||||
return _sampleCount - _sampleOffset + SamplesInBuffer;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void Close()
|
||||
{
|
||||
if (pAPEDecompress)
|
||||
{
|
||||
delete pAPEDecompress;
|
||||
pAPEDecompress = NULL;
|
||||
}
|
||||
if (_IO != nullptr)
|
||||
{
|
||||
_IO->Close ();
|
||||
_IO = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
virtual property String^ Path {
|
||||
String^ get() {
|
||||
return _path;
|
||||
}
|
||||
}
|
||||
|
||||
virtual int Read(AudioBuffer^ buff, int maxLength)
|
||||
{
|
||||
buff->Prepare(this, maxLength);
|
||||
|
||||
Int32 buffOffset = 0;
|
||||
Int32 samplesNeeded = buff->Length;
|
||||
Int32 _channelCount = pcm->ChannelCount;
|
||||
|
||||
while (samplesNeeded != 0)
|
||||
{
|
||||
if (SamplesInBuffer == 0)
|
||||
{
|
||||
int nBlocksRetrieved;
|
||||
pin_ptr<unsigned char> pSampleBuffer = &_samplesBuffer[0];
|
||||
if (pAPEDecompress->GetData ((char *) pSampleBuffer, 16384, &nBlocksRetrieved))
|
||||
throw gcnew Exception("An error occurred while decoding.");
|
||||
_bufferOffset = 0;
|
||||
_bufferLength = nBlocksRetrieved;
|
||||
_sampleOffset += nBlocksRetrieved;
|
||||
}
|
||||
Int32 copyCount = Math::Min(samplesNeeded, SamplesInBuffer);
|
||||
AudioBuffer::BytesToFLACSamples_16(_samplesBuffer, _bufferOffset*nBlockAlign, buff->Samples, buffOffset, copyCount, _channelCount);
|
||||
samplesNeeded -= copyCount;
|
||||
buffOffset += copyCount;
|
||||
_bufferOffset += copyCount;
|
||||
}
|
||||
return buff->Length;
|
||||
}
|
||||
|
||||
virtual property IAudioDecoderSettings^ Settings {
|
||||
IAudioDecoderSettings^ get(void) {
|
||||
return m_settings;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
::APE::IAPEDecompress * pAPEDecompress;
|
||||
|
||||
Int64 _sampleCount, _sampleOffset;
|
||||
AudioPCMConfig^ pcm;
|
||||
Int32 _bufferOffset, _bufferLength;
|
||||
int nBlockAlign;
|
||||
array<unsigned char>^ _samplesBuffer;
|
||||
String^ _path;
|
||||
Stream^ _IO;
|
||||
array<unsigned char>^ _readBuffer;
|
||||
CWinFileIO* _winFileIO;
|
||||
GCHandle _gchIO, _gchReadBuffer;
|
||||
DecoderSettings^ m_settings;
|
||||
|
||||
property Int32 SamplesInBuffer
|
||||
{
|
||||
Int32 get ()
|
||||
{
|
||||
return _bufferLength - _bufferOffset;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ref class AudioEncoder;
|
||||
|
||||
[Newtonsoft::Json::JsonObject(Newtonsoft::Json::MemberSerialization::OptIn)]
|
||||
public ref class EncoderSettings : public IAudioEncoderSettings
|
||||
{
|
||||
public:
|
||||
[System::ComponentModel::Browsable(false)]
|
||||
virtual property String^ Name
|
||||
{
|
||||
String^ get() { return "MAC_SDK"; }
|
||||
}
|
||||
|
||||
[System::ComponentModel::Browsable(false)]
|
||||
virtual property String^ Extension
|
||||
{
|
||||
String^ get() { return "ape"; }
|
||||
}
|
||||
|
||||
[System::ComponentModel::Browsable(false)]
|
||||
virtual property Type^ EncoderType
|
||||
{
|
||||
Type^ get() { return AudioEncoder::typeid; }
|
||||
}
|
||||
|
||||
[System::ComponentModel::Browsable(false)]
|
||||
virtual property bool Lossless
|
||||
{
|
||||
bool get() { return true; }
|
||||
}
|
||||
|
||||
[System::ComponentModel::Browsable(false)]
|
||||
virtual property int Priority
|
||||
{
|
||||
int get() { return 1; }
|
||||
}
|
||||
|
||||
[System::ComponentModel::Browsable(false)]
|
||||
virtual property String^ SupportedModes
|
||||
{
|
||||
String^ get() { return "fast normal high extra insane"; }
|
||||
}
|
||||
|
||||
[System::ComponentModel::Browsable(false)]
|
||||
virtual property String^ DefaultMode
|
||||
{
|
||||
String^ get() { return "high"; }
|
||||
}
|
||||
|
||||
[System::ComponentModel::Browsable(false)]
|
||||
[Newtonsoft::Json::JsonProperty]
|
||||
virtual property String^ EncoderMode
|
||||
{
|
||||
String^ get() { return encoderMode; }
|
||||
void set(String^ value) { encoderMode = value; }
|
||||
}
|
||||
|
||||
[System::ComponentModel::Browsable(false)]
|
||||
virtual property AudioPCMConfig^ PCM
|
||||
{
|
||||
AudioPCMConfig^ get() { return pcm; }
|
||||
void set(AudioPCMConfig^ value) { pcm = value; }
|
||||
}
|
||||
|
||||
[System::ComponentModel::Browsable(false)]
|
||||
virtual property int BlockSize
|
||||
{
|
||||
int get() { return blockSize; }
|
||||
void set(int value) { blockSize = value; }
|
||||
}
|
||||
|
||||
[System::ComponentModel::Browsable(false)]
|
||||
virtual property int Padding
|
||||
{
|
||||
int get() { return padding; }
|
||||
void set(int value) { padding = value; }
|
||||
}
|
||||
|
||||
virtual IAudioEncoderSettings^ Clone()
|
||||
{
|
||||
return (IAudioEncoderSettings^)MemberwiseClone();
|
||||
}
|
||||
|
||||
EncoderSettings()
|
||||
{
|
||||
IAudioEncoderSettingsExtensions::Init(this, nullptr);
|
||||
}
|
||||
|
||||
property String^ Version
|
||||
{
|
||||
String^ get()
|
||||
{
|
||||
return MAC_VERSION_STRING;
|
||||
}
|
||||
}
|
||||
private:
|
||||
String ^ encoderMode;
|
||||
AudioPCMConfig^ pcm;
|
||||
int blockSize;
|
||||
int padding;
|
||||
};
|
||||
|
||||
public ref class AudioEncoder : IAudioDest
|
||||
{
|
||||
public:
|
||||
AudioEncoder(EncoderSettings^ settings, String^ path, Stream^ IO)
|
||||
{
|
||||
_settings = settings;
|
||||
_IO = IO;
|
||||
|
||||
if (_settings->PCM->ChannelCount != 1 && _settings->PCM->ChannelCount != 2)
|
||||
throw gcnew Exception("Only stereo and mono audio formats are allowed.");
|
||||
if (_settings->PCM->BitsPerSample != 16 && _settings->PCM->BitsPerSample != 24)
|
||||
throw gcnew Exception("Monkey's Audio doesn't support selected bits per sample value.");
|
||||
|
||||
_path = path;
|
||||
_winFileIO = NULL;
|
||||
|
||||
int nRetVal;
|
||||
pAPECompress = CreateIAPECompress (&nRetVal);
|
||||
if (!pAPECompress)
|
||||
throw gcnew Exception("Unable to open APE compressor.");
|
||||
}
|
||||
|
||||
~AudioEncoder()
|
||||
{
|
||||
if (_winFileIO)
|
||||
delete _winFileIO;
|
||||
if (_gchIO.IsAllocated)
|
||||
_gchIO.Free();
|
||||
if (_gchBuffer.IsAllocated)
|
||||
_gchBuffer.Free();
|
||||
}
|
||||
|
||||
void DoClose()
|
||||
{
|
||||
if (pAPECompress)
|
||||
{
|
||||
pAPECompress->Finish (NULL, 0, 0);
|
||||
delete pAPECompress;
|
||||
pAPECompress = NULL;
|
||||
}
|
||||
|
||||
if (_IO != nullptr)
|
||||
{
|
||||
_IO->Close ();
|
||||
_IO = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void Close()
|
||||
{
|
||||
DoClose();
|
||||
|
||||
if ((_finalSampleCount != 0) && (_samplesWritten != _finalSampleCount)) {
|
||||
throw gcnew Exception("Samples written differs from the expected sample count.");
|
||||
}
|
||||
}
|
||||
|
||||
virtual void Delete()
|
||||
{
|
||||
DoClose ();
|
||||
|
||||
File::Delete(_path);
|
||||
}
|
||||
|
||||
virtual property Int64 FinalSampleCount
|
||||
{
|
||||
Int64 get()
|
||||
{
|
||||
return _finalSampleCount;
|
||||
}
|
||||
void set(Int64 value)
|
||||
{
|
||||
if (value < 0)
|
||||
throw gcnew Exception("Invalid final sample count.");
|
||||
if (_initialized)
|
||||
throw gcnew Exception("Final sample count cannot be changed after encoding begins.");
|
||||
_finalSampleCount = value;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void Write(AudioBuffer^ buff)
|
||||
{
|
||||
if (!_initialized)
|
||||
Initialize();
|
||||
buff->Prepare(this);
|
||||
pin_ptr<unsigned char> pSampleBuffer = &buff->Bytes[0];
|
||||
if (pAPECompress->AddData (pSampleBuffer, buff->ByteLength))
|
||||
throw gcnew Exception("An error occurred while encoding.");
|
||||
_samplesWritten += buff->Length;
|
||||
}
|
||||
|
||||
virtual property String^ Path
|
||||
{
|
||||
String^ get() {
|
||||
return _path;
|
||||
}
|
||||
}
|
||||
|
||||
virtual property IAudioEncoderSettings^ Settings
|
||||
{
|
||||
IAudioEncoderSettings^ get()
|
||||
{
|
||||
return _settings;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
IAPECompress * pAPECompress;
|
||||
bool _initialized;
|
||||
Int64 _finalSampleCount, _samplesWritten;
|
||||
EncoderSettings^ _settings;
|
||||
String^ _path;
|
||||
Stream^ _IO;
|
||||
GCHandle _gchIO, _gchBuffer;
|
||||
CWinFileIO* _winFileIO;
|
||||
array<unsigned char>^ _writeBuffer;
|
||||
array<unsigned char>^ _sampleBuffer;
|
||||
|
||||
void Initialize() {
|
||||
if (_IO == nullptr)
|
||||
_IO = gcnew FileStream (_path, FileMode::Create, FileAccess::ReadWrite, FileShare::Read);
|
||||
_writeBuffer = gcnew array<unsigned char>(0x4000);
|
||||
|
||||
_gchIO = GCHandle::Alloc(_IO);
|
||||
_gchBuffer = GCHandle::Alloc(_writeBuffer);
|
||||
_winFileIO = new CWinFileIO(_gchIO, _gchBuffer);
|
||||
|
||||
WAVEFORMATEX waveFormat;
|
||||
FillWaveFormatEx (&waveFormat, _settings->PCM->SampleRate, _settings->PCM->BitsPerSample, _settings->PCM->ChannelCount);
|
||||
|
||||
Int32 _compressionLevel = (IAudioEncoderSettingsExtensions::GetEncoderModeIndex(_settings) + 1) * 1000;
|
||||
|
||||
int res = pAPECompress->StartEx (_winFileIO,
|
||||
&waveFormat,
|
||||
(_finalSampleCount == 0) ? MAX_AUDIO_BYTES_UNKNOWN : _finalSampleCount * _settings->PCM->BlockAlign,
|
||||
_compressionLevel,
|
||||
NULL,
|
||||
CREATE_WAV_HEADER_ON_DECOMPRESSION);
|
||||
if (res)
|
||||
throw gcnew Exception("Unable to create the encoder.");
|
||||
|
||||
_initialized = true;
|
||||
}
|
||||
};
|
||||
|
||||
int CWinFileIO::Read(void * pBuffer, unsigned int nBytesToRead, unsigned int * pBytesRead)
|
||||
{
|
||||
array<unsigned char>^ buff = (array<unsigned char>^) _gchBuffer.Target;
|
||||
if (buff->Length < nBytesToRead)
|
||||
{
|
||||
Array::Resize (buff, nBytesToRead);
|
||||
_gchBuffer.Target = buff;
|
||||
}
|
||||
int len = ((Stream^)_gchIO.Target)->Read (buff, 0, nBytesToRead);
|
||||
if (len) Marshal::Copy (buff, 0, (IntPtr)pBuffer, len);
|
||||
*pBytesRead = len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CWinFileIO::Write(const void * pBuffer, unsigned int nBytesToWrite, unsigned int * pBytesWritten)
|
||||
{
|
||||
array<unsigned char>^ buff = (array<unsigned char>^) _gchBuffer.Target;
|
||||
if (buff->Length < nBytesToWrite)
|
||||
{
|
||||
Array::Resize (buff, nBytesToWrite);
|
||||
_gchBuffer.Target = buff;
|
||||
}
|
||||
Marshal::Copy ((IntPtr)(void*)pBuffer, buff, 0, nBytesToWrite);
|
||||
((Stream^)_gchIO.Target)->Write (buff, 0, nBytesToWrite);
|
||||
*pBytesWritten = nBytesToWrite;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CWinFileIO::GetPosition()
|
||||
{
|
||||
return ((Stream^)_gchIO.Target)->Position;
|
||||
}
|
||||
|
||||
unsigned int CWinFileIO::GetSize()
|
||||
{
|
||||
return ((Stream^)_gchIO.Target)->Length;
|
||||
}
|
||||
|
||||
int CWinFileIO::Seek(int delta, unsigned int mode)
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
case FILE_BEGIN:
|
||||
((Stream^)_gchIO.Target)->Seek (delta, System::IO::SeekOrigin::Begin);
|
||||
break;
|
||||
case FILE_END:
|
||||
((Stream^)_gchIO.Target)->Seek (delta, System::IO::SeekOrigin::End);
|
||||
break;
|
||||
case FILE_CURRENT:
|
||||
((Stream^)_gchIO.Target)->Seek (delta, System::IO::SeekOrigin::Current);
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
extern "C"
|
||||
{
|
||||
BOOL GetMMXAvailable();
|
||||
int CalculateDotProduct8(const short* pA, const short* pB, int nOrder);
|
||||
};
|
||||
|
||||
public ref class SSE2Functions
|
||||
{
|
||||
public:
|
||||
SSE2Functions ()
|
||||
{
|
||||
_haveSSE2 = GetMMXAvailable();
|
||||
}
|
||||
int SumInts (short*a, short*b, int count)
|
||||
{
|
||||
if (_haveSSE2 && count == 8)
|
||||
return CalculateDotProduct8(a, b, count);
|
||||
int sum = 0;
|
||||
for (int j = 0; j < count; j++)
|
||||
sum += a[j] * b[j];
|
||||
return sum;
|
||||
}
|
||||
int SumInts (int*a, short*b, int count)
|
||||
{
|
||||
int sum = 0;
|
||||
for (int j = 0; j < count; j++)
|
||||
sum += a[j] * b[j];
|
||||
return sum;
|
||||
}
|
||||
private:
|
||||
bool _haveSSE2;
|
||||
};
|
||||
#endif
|
||||
}}}
|
||||
@@ -1,243 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{9AE965C4-301E-4C01-B90F-297AF341ACC6}</ProjectGuid>
|
||||
<RootNamespace>CUETools.Codecs.APE</RootNamespace>
|
||||
<Keyword>ManagedCProj</Keyword>
|
||||
<WindowsTargetPlatformVersion>10.0.16299.0</WindowsTargetPlatformVersion>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<CLRSupport>true</CLRSupport>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<CLRSupport>true</CLRSupport>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<CLRSupport>true</CLRSupport>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<CLRSupport>true</CLRSupport>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup>
|
||||
<_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>
|
||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\bin\$(Configuration)\plugins\$(Platform)\net40\</OutDir>
|
||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)..\obj\$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
|
||||
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
|
||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\bin\$(Configuration)\plugins\$(Platform)\net40\</OutDir>
|
||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\obj\$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
|
||||
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</LinkIncremental>
|
||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\bin\$(Configuration)\plugins\$(Platform)\net40\</OutDir>
|
||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)..\obj\$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
|
||||
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
|
||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\bin\$(Configuration)\plugins\$(Platform)\net40\</OutDir>
|
||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)..\obj\$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
|
||||
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkIncremental>
|
||||
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
|
||||
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
|
||||
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
|
||||
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
|
||||
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
|
||||
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
|
||||
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
|
||||
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>..\ThirdParty\MAC_SDK\Source\Shared;..\ThirdParty\MAC_SDK\Source\MACLib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AssemblyDebug>true</AssemblyDebug>
|
||||
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||
<DataExecutionPrevention>
|
||||
</DataExecutionPrevention>
|
||||
<TargetMachine>MachineX86</TargetMachine>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Midl>
|
||||
<TargetEnvironment>X64</TargetEnvironment>
|
||||
</Midl>
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>..\ThirdParty\MAC_SDK\Source\Shared;..\ThirdParty\MAC_SDK\Source\MACLib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AssemblyDebug>true</AssemblyDebug>
|
||||
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||
<DataExecutionPrevention>
|
||||
</DataExecutionPrevention>
|
||||
<TargetMachine>MachineX64</TargetMachine>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>..\ThirdParty\MAC_SDK\Source\Shared;..\ThirdParty\MAC_SDK\Source\MACLib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||
<DataExecutionPrevention>
|
||||
</DataExecutionPrevention>
|
||||
<TargetMachine>MachineX86</TargetMachine>
|
||||
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Midl>
|
||||
<TargetEnvironment>X64</TargetEnvironment>
|
||||
</Midl>
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>..\ThirdParty\MAC_SDK\Source\Shared;..\ThirdParty\MAC_SDK\Source\MACLib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||
<DataExecutionPrevention>
|
||||
</DataExecutionPrevention>
|
||||
<TargetMachine>MachineX64</TargetMachine>
|
||||
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Newtonsoft.Json">
|
||||
<HintPath>..\bin\Release\net40\Newtonsoft.Json.dll</HintPath>
|
||||
<Private>false</Private>
|
||||
<CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
|
||||
<ReferenceOutputAssembly>true</ReferenceOutputAssembly>
|
||||
</Reference>
|
||||
<Reference Include="System">
|
||||
<CopyLocalSatelliteAssemblies>true</CopyLocalSatelliteAssemblies>
|
||||
<ReferenceOutputAssembly>true</ReferenceOutputAssembly>
|
||||
</Reference>
|
||||
<Reference Include="System.Data">
|
||||
<CopyLocalSatelliteAssemblies>true</CopyLocalSatelliteAssemblies>
|
||||
<ReferenceOutputAssembly>true</ReferenceOutputAssembly>
|
||||
</Reference>
|
||||
<Reference Include="System.Xml">
|
||||
<CopyLocalSatelliteAssemblies>true</CopyLocalSatelliteAssemblies>
|
||||
<ReferenceOutputAssembly>true</ReferenceOutputAssembly>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="AssemblyInfo.cpp" />
|
||||
<ClCompile Include="CUETools.Codecs.APE.cpp" />
|
||||
<ClCompile Include="Stdafx.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="CUETools.Codecs.APE.h" />
|
||||
<ClInclude Include="resource.h" />
|
||||
<ClInclude Include="Stdafx.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="app.ico" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="app.rc" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\CUETools.Codecs\CUETools.Codecs.csproj">
|
||||
<Project>{6458a13a-30ef-45a9-9d58-e5031b17bee2}</Project>
|
||||
<Private>false</Private>
|
||||
<ReferenceOutputAssembly>true</ReferenceOutputAssembly>
|
||||
<CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
|
||||
<LinkLibraryDependencies>true</LinkLibraryDependencies>
|
||||
<UseLibraryDependencyInputs>false</UseLibraryDependencyInputs>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\ThirdParty\MAC_SDK\Source\Projects\VS2017\MACLib\MACLib.vcxproj">
|
||||
<Project>{21bf980f-c022-4dcc-9250-7c73528e422b}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
@@ -1,31 +0,0 @@
|
||||
========================================================================
|
||||
DYNAMIC LINK LIBRARY : APEDotNet Project Overview
|
||||
========================================================================
|
||||
|
||||
AppWizard has created this APEDotNet DLL for you.
|
||||
|
||||
This file contains a summary of what you will find in each of the files that
|
||||
make up your APEDotNet application.
|
||||
|
||||
APEDotNet.vcproj
|
||||
This is the main project file for VC++ projects generated using an Application Wizard.
|
||||
It contains information about the version of Visual C++ that generated the file, and
|
||||
information about the platforms, configurations, and project features selected with the
|
||||
Application Wizard.
|
||||
|
||||
APEDotNet.cpp
|
||||
This is the main DLL source file.
|
||||
|
||||
APEDotNet.h
|
||||
This file contains a class declaration.
|
||||
|
||||
AssemblyInfo.cpp
|
||||
Contains custom attributes for modifying assembly metadata.
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
Other notes:
|
||||
|
||||
AppWizard uses "TODO:" to indicate parts of the source code you
|
||||
should add to or customize.
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
@@ -1,5 +0,0 @@
|
||||
// stdafx.cpp : source file that includes just the standard includes
|
||||
// APEDotNet.pch will be the pre-compiled header
|
||||
// stdafx.obj will contain the pre-compiled type information
|
||||
|
||||
#include "stdafx.h"
|
||||
@@ -1,7 +0,0 @@
|
||||
// stdafx.h : include file for standard system include files,
|
||||
// or project specific include files that are used frequently,
|
||||
// but are changed infrequently
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 1.1 KiB |
@@ -1,63 +0,0 @@
|
||||
// Microsoft Visual C++ generated resource script.
|
||||
//
|
||||
#include "resource.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// English (U.S.) resources
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Icon
|
||||
//
|
||||
|
||||
// Icon placed first or with lowest ID value becomes application icon
|
||||
|
||||
LANGUAGE 25, 1
|
||||
#pragma code_page(1251)
|
||||
1 ICON "app.ico"
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE
|
||||
BEGIN
|
||||
"resource.h\0"
|
||||
"\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE
|
||||
BEGIN
|
||||
"#include ""afxres.h""\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE
|
||||
BEGIN
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Visual C++ generated include file.
|
||||
// Used by app.rc
|
||||
147
CUETools.Codecs.MACLib/AudioDecoder.cs
Normal file
147
CUETools.Codecs.MACLib/AudioDecoder.cs
Normal file
@@ -0,0 +1,147 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace CUETools.Codecs.MACLib
|
||||
{
|
||||
public unsafe class AudioDecoder : IAudioSource, IDisposable
|
||||
{
|
||||
public AudioDecoder(DecoderSettings settings, string path, Stream IO)
|
||||
{
|
||||
m_settings = settings;
|
||||
|
||||
_path = path;
|
||||
|
||||
m_stream = (IO != null) ? IO : new FileStream (path, FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||
m_StreamIO = new StreamIO(m_stream);
|
||||
|
||||
int errorCode = 0;
|
||||
pAPEDecompress = MACLibDll.c_APEDecompress_CreateEx(m_StreamIO.Callbacks, out errorCode);
|
||||
if (pAPEDecompress == null) {
|
||||
throw new Exception("Unable to initialize the decoder: " + errorCode);
|
||||
}
|
||||
|
||||
pcm = new AudioPCMConfig(
|
||||
MACLibDll.c_APEDecompress_GetInfo(pAPEDecompress, APE_DECOMPRESS_FIELDS.APE_INFO_BITS_PER_SAMPLE, 0, 0),
|
||||
MACLibDll.c_APEDecompress_GetInfo(pAPEDecompress, APE_DECOMPRESS_FIELDS.APE_INFO_CHANNELS, 0, 0),
|
||||
MACLibDll.c_APEDecompress_GetInfo(pAPEDecompress, APE_DECOMPRESS_FIELDS.APE_INFO_SAMPLE_RATE, 0, 0),
|
||||
(AudioPCMConfig.SpeakerConfig)0);
|
||||
_samplesBuffer = new byte[16384 * pcm.BlockAlign];
|
||||
_sampleCount = MACLibDll.c_APEDecompress_GetInfo(pAPEDecompress, APE_DECOMPRESS_FIELDS.APE_DECOMPRESS_TOTAL_BLOCKS, 0, 0);
|
||||
_sampleOffset = 0;
|
||||
}
|
||||
|
||||
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 (_samplesBuffer != null)
|
||||
{
|
||||
_samplesBuffer = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (pAPEDecompress != null) MACLibDll.c_APEDecompress_Destroy(pAPEDecompress);
|
||||
pAPEDecompress = IntPtr.Zero;
|
||||
}
|
||||
|
||||
~AudioDecoder()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
|
||||
// TODO: intn should always be 64 bit? Or should we use different interface in 32-bit mode?
|
||||
|
||||
private DecoderSettings m_settings;
|
||||
|
||||
public IAudioDecoderSettings Settings => m_settings;
|
||||
|
||||
public AudioPCMConfig PCM => pcm;
|
||||
|
||||
public string Path => _path;
|
||||
|
||||
public long Length => _sampleCount;
|
||||
|
||||
internal long SamplesInBuffer => _bufferLength - _bufferOffset;
|
||||
|
||||
public long Position
|
||||
{
|
||||
get => _sampleOffset - SamplesInBuffer;
|
||||
|
||||
set
|
||||
{
|
||||
_bufferOffset = 0;
|
||||
_bufferLength = 0;
|
||||
_sampleOffset = value;
|
||||
int res = MACLibDll.c_APEDecompress_Seek(pAPEDecompress, (int)value);
|
||||
if (0 != res)
|
||||
throw new Exception("unable to seek:" + res.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
public long Remaining => _sampleCount - _sampleOffset + SamplesInBuffer;
|
||||
|
||||
public void Close()
|
||||
{
|
||||
Dispose(true);
|
||||
}
|
||||
|
||||
public int Read(AudioBuffer buff, int maxLength)
|
||||
{
|
||||
buff.Prepare(this, maxLength);
|
||||
|
||||
long buffOffset = 0;
|
||||
long samplesNeeded = buff.Length;
|
||||
long _channelCount = pcm.ChannelCount;
|
||||
|
||||
while (samplesNeeded != 0)
|
||||
{
|
||||
if (SamplesInBuffer == 0)
|
||||
{
|
||||
long nBlocksRetrieved;
|
||||
fixed (byte* pSampleBuffer = &_samplesBuffer[0])
|
||||
{
|
||||
int res = MACLibDll.c_APEDecompress_GetData(pAPEDecompress, (char*)pSampleBuffer, (IntPtr)16384, out nBlocksRetrieved);
|
||||
if (res != 0)
|
||||
throw new Exception("An error occurred while decoding: " + res.ToString());
|
||||
}
|
||||
_bufferOffset = 0;
|
||||
_bufferLength = nBlocksRetrieved;
|
||||
_sampleOffset += nBlocksRetrieved;
|
||||
}
|
||||
long copyCount = Math.Min(samplesNeeded, SamplesInBuffer);
|
||||
AudioBuffer.BytesToFLACSamples_16(_samplesBuffer, (int)(_bufferOffset * pcm.BlockAlign), buff.Samples, (int)buffOffset, (int)copyCount, (int)_channelCount);
|
||||
samplesNeeded -= copyCount;
|
||||
buffOffset += copyCount;
|
||||
_bufferOffset += copyCount;
|
||||
}
|
||||
|
||||
return buff.Length;
|
||||
}
|
||||
|
||||
IntPtr pAPEDecompress;
|
||||
long _sampleCount, _sampleOffset;
|
||||
AudioPCMConfig pcm;
|
||||
string _path;
|
||||
Stream m_stream;
|
||||
long _bufferOffset, _bufferLength;
|
||||
byte[] _samplesBuffer;
|
||||
StreamIO m_StreamIO;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
29
CUETools.Codecs.MACLib/CUETools.Codecs.MACLib.csproj
Normal file
29
CUETools.Codecs.MACLib/CUETools.Codecs.MACLib.csproj
Normal file
@@ -0,0 +1,29 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net40;net20;netstandard2.0</TargetFrameworks>
|
||||
<Version>2.1.7.0</Version>
|
||||
<AssemblyName>CUETools.Codecs.MACLib</AssemblyName>
|
||||
<RootNamespace>CUETools.Codecs.MACLib</RootNamespace>
|
||||
<Product>CUETools</Product>
|
||||
<Description>A library for encoding APE files using official encoder.</Description>
|
||||
<Copyright>Copyright (c) 2008-2018 Grigory Chudov</Copyright>
|
||||
<Authors>Grigory Chudov</Authors>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<OutputPath>..\bin\$(Configuration)\plugins</OutputPath>
|
||||
<RepositoryUrl>https://github.com/gchudov/cuetools.net</RepositoryUrl>
|
||||
<RepositoryType>git</RepositoryType>
|
||||
<Company />
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemDefinitionGroup>
|
||||
<ProjectReference>
|
||||
<Private>False</Private>
|
||||
</ProjectReference>
|
||||
</ItemDefinitionGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\CUETools.Codecs\CUETools.Codecs.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
39
CUETools.Codecs.MACLib/DecoderSettings.cs
Normal file
39
CUETools.Codecs.MACLib/DecoderSettings.cs
Normal file
@@ -0,0 +1,39 @@
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace CUETools.Codecs.MACLib
|
||||
{
|
||||
[JsonObject(MemberSerialization.OptIn)]
|
||||
public class DecoderSettings : IAudioDecoderSettings
|
||||
{
|
||||
#region IAudioDecoderSettings implementation
|
||||
[Browsable(false)]
|
||||
public string Extension => "ape";
|
||||
|
||||
[Browsable(false)]
|
||||
public string Name => "MACLib";
|
||||
|
||||
[Browsable(false)]
|
||||
public Type DecoderType => typeof(AudioDecoder);
|
||||
|
||||
[Browsable(false)]
|
||||
public int Priority => 1;
|
||||
|
||||
public IAudioDecoderSettings Clone()
|
||||
{
|
||||
return MemberwiseClone() as IAudioDecoderSettings;
|
||||
}
|
||||
#endregion
|
||||
|
||||
public DecoderSettings()
|
||||
{
|
||||
this.Init();
|
||||
}
|
||||
|
||||
[DisplayName("Version")]
|
||||
[Description("Library version")]
|
||||
public string Version => Marshal.PtrToStringAnsi(MACLibDll.GetVersionString());
|
||||
}
|
||||
}
|
||||
68
CUETools.Codecs.MACLib/EncoderSettings.cs
Normal file
68
CUETools.Codecs.MACLib/EncoderSettings.cs
Normal file
@@ -0,0 +1,68 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using CUETools.Codecs;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace CUETools.Codecs.MACLib
|
||||
{
|
||||
[JsonObject(MemberSerialization.OptIn)]
|
||||
public class EncoderSettings : IAudioEncoderSettings
|
||||
{
|
||||
#region IAudioEncoderSettings implementation
|
||||
[Browsable(false)]
|
||||
public string Extension => "ape";
|
||||
|
||||
[Browsable(false)]
|
||||
public string Name => "MACLib";
|
||||
|
||||
[Browsable(false)]
|
||||
public Type EncoderType => typeof(AudioEncoder);
|
||||
|
||||
[Browsable(false)]
|
||||
public bool Lossless => true;
|
||||
|
||||
[Browsable(false)]
|
||||
public int Priority => 1;
|
||||
|
||||
[Browsable(false)]
|
||||
public string SupportedModes => "fast normal high extra insane";
|
||||
|
||||
[Browsable(false)]
|
||||
public string DefaultMode => "high";
|
||||
|
||||
[Browsable(false)]
|
||||
[DefaultValue("")]
|
||||
[JsonProperty]
|
||||
public string EncoderMode { get; set; }
|
||||
|
||||
[Browsable(false)]
|
||||
public AudioPCMConfig PCM { get; set; }
|
||||
|
||||
[Browsable(false)]
|
||||
public int BlockSize { get; set; }
|
||||
|
||||
[Browsable(false)]
|
||||
[DefaultValue(4096)]
|
||||
public int Padding { get; set; }
|
||||
|
||||
public IAudioEncoderSettings Clone()
|
||||
{
|
||||
return MemberwiseClone() as IAudioEncoderSettings;
|
||||
}
|
||||
#endregion
|
||||
|
||||
public EncoderSettings()
|
||||
{
|
||||
this.Init();
|
||||
}
|
||||
|
||||
[DisplayName("Version")]
|
||||
[Description("Library version")]
|
||||
public string Version => Marshal.PtrToStringAnsi(MACLibDll.GetVersionString());
|
||||
};
|
||||
}
|
||||
90
CUETools.Codecs.MACLib/MACLib.cs
Normal file
90
CUETools.Codecs.MACLib/MACLib.cs
Normal file
@@ -0,0 +1,90 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace CUETools.Codecs.MACLib
|
||||
{
|
||||
internal enum APE_DECOMPRESS_FIELDS : int
|
||||
{
|
||||
APE_INFO_FILE_VERSION = 1000, // version of the APE file * 1000 (3.93 = 3930) [ignored, ignored]
|
||||
APE_INFO_COMPRESSION_LEVEL = 1001, // compression level of the APE file [ignored, ignored]
|
||||
APE_INFO_FORMAT_FLAGS = 1002, // format flags of the APE file [ignored, ignored]
|
||||
APE_INFO_SAMPLE_RATE = 1003, // sample rate (Hz) [ignored, ignored]
|
||||
APE_INFO_BITS_PER_SAMPLE = 1004, // bits per sample [ignored, ignored]
|
||||
APE_INFO_BYTES_PER_SAMPLE = 1005, // number of bytes per sample [ignored, ignored]
|
||||
APE_INFO_CHANNELS = 1006, // channels [ignored, ignored]
|
||||
APE_INFO_BLOCK_ALIGN = 1007, // block alignment [ignored, ignored]
|
||||
APE_INFO_BLOCKS_PER_FRAME = 1008, // number of blocks in a frame (frames are used internally) [ignored, ignored]
|
||||
APE_INFO_FINAL_FRAME_BLOCKS = 1009, // blocks in the final frame (frames are used internally) [ignored, ignored]
|
||||
APE_INFO_TOTAL_FRAMES = 1010, // total number frames (frames are used internally) [ignored, ignored]
|
||||
APE_INFO_WAV_HEADER_BYTES = 1011, // header bytes of the decompressed WAV [ignored, ignored]
|
||||
APE_INFO_WAV_TERMINATING_BYTES = 1012, // terminating bytes of the decompressed WAV [ignored, ignored]
|
||||
APE_INFO_WAV_DATA_BYTES = 1013, // data bytes of the decompressed WAV [ignored, ignored]
|
||||
APE_INFO_WAV_TOTAL_BYTES = 1014, // total bytes of the decompressed WAV [ignored, ignored]
|
||||
APE_INFO_APE_TOTAL_BYTES = 1015, // total bytes of the APE file [ignored, ignored]
|
||||
APE_INFO_TOTAL_BLOCKS = 1016, // total blocks of audio data [ignored, ignored]
|
||||
APE_INFO_LENGTH_MS = 1017, // length in ms (1 sec = 1000 ms) [ignored, ignored]
|
||||
APE_INFO_AVERAGE_BITRATE = 1018, // average bitrate of the APE [ignored, ignored]
|
||||
APE_INFO_FRAME_BITRATE = 1019, // bitrate of specified APE frame [frame index, ignored]
|
||||
APE_INFO_DECOMPRESSED_BITRATE = 1020, // bitrate of the decompressed WAV [ignored, ignored]
|
||||
APE_INFO_PEAK_LEVEL = 1021, // peak audio level (obsolete) (-1 is unknown) [ignored, ignored]
|
||||
APE_INFO_SEEK_BIT = 1022, // bit offset [frame index, ignored]
|
||||
APE_INFO_SEEK_BYTE = 1023, // byte offset [frame index, ignored]
|
||||
APE_INFO_WAV_HEADER_DATA = 1024, // error code [buffer *, max bytes]
|
||||
APE_INFO_WAV_TERMINATING_DATA = 1025, // error code [buffer *, max bytes]
|
||||
APE_INFO_WAVEFORMATEX = 1026, // error code [waveformatex *, ignored]
|
||||
APE_INFO_IO_SOURCE = 1027, // I/O source (CIO *) [ignored, ignored]
|
||||
APE_INFO_FRAME_BYTES = 1028, // bytes (compressed) of the frame [frame index, ignored]
|
||||
APE_INFO_FRAME_BLOCKS = 1029, // blocks in a given frame [frame index, ignored]
|
||||
APE_INFO_TAG = 1030, // point to tag (CAPETag *) [ignored, ignored]
|
||||
|
||||
APE_DECOMPRESS_CURRENT_BLOCK = 2000, // current block location [ignored, ignored]
|
||||
APE_DECOMPRESS_CURRENT_MS = 2001, // current millisecond location [ignored, ignored]
|
||||
APE_DECOMPRESS_TOTAL_BLOCKS = 2002, // total blocks in the decompressors range [ignored, ignored]
|
||||
APE_DECOMPRESS_LENGTH_MS = 2003, // length of the decompressors range in milliseconds [ignored, ignored]
|
||||
APE_DECOMPRESS_CURRENT_BITRATE = 2004, // current bitrate [ignored, ignored]
|
||||
APE_DECOMPRESS_AVERAGE_BITRATE = 2005, // average bitrate (works with ranges) [ignored, ignored]
|
||||
APE_DECOMPRESS_CURRENT_FRAME = 2006, // current frame
|
||||
|
||||
APE_INTERNAL_INFO = 3000, // for internal use -- don't use (returns APE_FILE_INFO *) [ignored, ignored]
|
||||
};
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
|
||||
internal unsafe delegate int CIO_ReadDelegate(APE_CIO_Callbacks* pCIO, void* pBuffer, int nBytesToRead, out int pBytesRead);
|
||||
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
|
||||
internal unsafe delegate int CIO_WriteDelegate(APE_CIO_Callbacks* pCIO, void* pBuffer, int nBytesToWrite, out int pBytesWritten);
|
||||
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
|
||||
internal unsafe delegate int CIO_GetPositionDelegate(APE_CIO_Callbacks* pCIO);
|
||||
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
|
||||
internal unsafe delegate uint CIO_GetSizeDelegate(APE_CIO_Callbacks* pCIO);
|
||||
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
|
||||
internal unsafe delegate int CIO_SeekDelegate(APE_CIO_Callbacks* pCIO, IntPtr delta, int mode);
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 2)]
|
||||
public unsafe struct WAVEFORMATEX
|
||||
{
|
||||
/// <summary>format type</summary>
|
||||
internal ushort waveFormatTag;
|
||||
/// <summary>number of channels</summary>
|
||||
internal short channels;
|
||||
/// <summary>sample rate</summary>
|
||||
internal int sampleRate;
|
||||
/// <summary>for buffer estimation</summary>
|
||||
internal int averageBytesPerSecond;
|
||||
/// <summary>block size of data</summary>
|
||||
internal short blockAlign;
|
||||
/// <summary>number of bits per sample of mono data</summary>
|
||||
internal short bitsPerSample;
|
||||
/// <summary>number of following bytes</summary>
|
||||
internal short extraSize;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential), Serializable]
|
||||
internal unsafe struct APE_CIO_Callbacks
|
||||
{
|
||||
internal IntPtr read_bytes;
|
||||
internal IntPtr write_bytes;
|
||||
internal IntPtr seek;
|
||||
internal IntPtr get_pos;
|
||||
internal IntPtr get_size;
|
||||
};
|
||||
}
|
||||
74
CUETools.Codecs.MACLib/MACLibDll.cs
Normal file
74
CUETools.Codecs.MACLib/MACLibDll.cs
Normal file
@@ -0,0 +1,74 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace CUETools.Codecs.MACLib
|
||||
{
|
||||
internal unsafe static class MACLibDll
|
||||
{
|
||||
internal const string DllName = "MACLibDll";
|
||||
internal const CallingConvention DllCallingConvention = CallingConvention.StdCall;
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
private static extern IntPtr LoadLibrary(string dllToLoad);
|
||||
|
||||
[DllImport(DllName, CallingConvention = DllCallingConvention)]
|
||||
internal static extern int GetVersionNumber();
|
||||
|
||||
[DllImport(DllName, CallingConvention = DllCallingConvention)]
|
||||
internal static extern IntPtr GetVersionString();
|
||||
|
||||
[DllImport(DllName, CallingConvention = DllCallingConvention)]
|
||||
internal static extern IntPtr c_APECompress_Create(out int error);
|
||||
|
||||
[DllImport(DllName, CallingConvention = DllCallingConvention)]
|
||||
internal static extern void c_APECompress_Destroy(IntPtr hAPECompress);
|
||||
|
||||
[DllImport(DllName, CallingConvention = DllCallingConvention)]
|
||||
internal static extern int c_APECompress_Finish(IntPtr hAPECompress, char* pTerminatingData, int nTerminatingBytes, int nWAVTerminatingBytes);
|
||||
|
||||
[DllImport(DllName, CallingConvention = DllCallingConvention)]
|
||||
internal static extern int c_APECompress_AddData(IntPtr hAPECompress, byte* pData, int nBytes);
|
||||
|
||||
[DllImport(DllName, CallingConvention = DllCallingConvention)]
|
||||
internal static extern int c_APECompress_StartEx(
|
||||
IntPtr hAPECompress,
|
||||
APE_CIO_Callbacks* pCIO,
|
||||
WAVEFORMATEX* pwfeInput,
|
||||
int nMaxAudioBytes,
|
||||
int nCompressionLevel,
|
||||
void* pHeaderData,
|
||||
int nHeaderBytes);
|
||||
|
||||
[DllImport(DllName, CallingConvention = DllCallingConvention)]
|
||||
internal static extern IntPtr c_APEDecompress_CreateEx(APE_CIO_Callbacks* pCIO, out int pErrorCode);
|
||||
|
||||
[DllImport(DllName, CallingConvention = DllCallingConvention)]
|
||||
internal static extern int c_APEDecompress_GetInfo(IntPtr hAPEDecompress, APE_DECOMPRESS_FIELDS Field, int nParam1 = 0, int nParam2 = 0);
|
||||
|
||||
[DllImport(DllName, CallingConvention = DllCallingConvention)]
|
||||
internal static extern int c_APEDecompress_Seek(IntPtr hAPEDecompress, int nBlockOffset);
|
||||
|
||||
[DllImport(DllName, CallingConvention = DllCallingConvention)]
|
||||
internal static extern int c_APEDecompress_GetData(IntPtr hAPEDecompress, char* pBuffer, IntPtr nBlocks, out long pBlocksRetrieved);
|
||||
|
||||
[DllImport(DllName, CallingConvention = DllCallingConvention)]
|
||||
internal static extern void c_APEDecompress_Destroy(IntPtr hAPEDecompress);
|
||||
|
||||
static MACLibDll()
|
||||
{
|
||||
var myPath = new Uri(typeof(MACLibDll).Assembly.CodeBase).LocalPath;
|
||||
var myFolder = System.IO.Path.GetDirectoryName(myPath);
|
||||
var is64 = IntPtr.Size == 8;
|
||||
var subfolder = is64 ? "x64" : "win32";
|
||||
#if NET40
|
||||
IntPtr Dll = LoadLibrary(System.IO.Path.Combine(myFolder, subfolder, DllName + ".dll"));
|
||||
#else
|
||||
IntPtr Dll = LoadLibrary(System.IO.Path.Combine(System.IO.Path.Combine(myFolder, subfolder), DllName + ".dll"));
|
||||
#endif
|
||||
if (Dll == IntPtr.Zero)
|
||||
Dll = LoadLibrary(DllName + ".dll");
|
||||
if (Dll == IntPtr.Zero)
|
||||
throw new DllNotFoundException();
|
||||
}
|
||||
};
|
||||
}
|
||||
99
CUETools.Codecs.MACLib/StreamIO.cs
Normal file
99
CUETools.Codecs.MACLib/StreamIO.cs
Normal file
@@ -0,0 +1,99 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace CUETools.Codecs.MACLib
|
||||
{
|
||||
internal unsafe class StreamIO : IDisposable
|
||||
{
|
||||
public StreamIO(Stream stream)
|
||||
{
|
||||
m_stream = stream;
|
||||
|
||||
m_read_bytes = ReadCallback;
|
||||
m_write_bytes = WriteCallback;
|
||||
m_get_pos = TellCallback;
|
||||
m_get_size = GetSizeCallback;
|
||||
m_seek = SeekRelativeCallback;
|
||||
|
||||
m_callbacks = (APE_CIO_Callbacks*)Marshal.AllocHGlobal(sizeof(APE_CIO_Callbacks)).ToPointer();
|
||||
m_callbacks->read_bytes = Marshal.GetFunctionPointerForDelegate(m_read_bytes);
|
||||
m_callbacks->write_bytes = Marshal.GetFunctionPointerForDelegate(m_write_bytes);
|
||||
m_callbacks->get_pos = Marshal.GetFunctionPointerForDelegate(m_get_pos);
|
||||
m_callbacks->get_size = Marshal.GetFunctionPointerForDelegate(m_get_size);
|
||||
m_callbacks->seek = Marshal.GetFunctionPointerForDelegate(m_seek);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
m_stream = null;
|
||||
_readBuffer = null;
|
||||
}
|
||||
|
||||
if (m_callbacks != null) Marshal.FreeHGlobal((IntPtr)m_callbacks);
|
||||
m_callbacks = null;
|
||||
}
|
||||
|
||||
~StreamIO()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
|
||||
private int ReadCallback(APE_CIO_Callbacks* id, void* data, int bcount, out int pBytesRead)
|
||||
{
|
||||
if (_readBuffer == null || _readBuffer.Length < bcount)
|
||||
_readBuffer = new byte[Math.Max(bcount, 0x4000)];
|
||||
int len = m_stream.Read(_readBuffer, 0, bcount);
|
||||
if (len > 0) Marshal.Copy(_readBuffer, 0, (IntPtr)data, len);
|
||||
pBytesRead = len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
private int WriteCallback(APE_CIO_Callbacks* id, void* data, int bcount, out int pBytesWritten)
|
||||
{
|
||||
if (_readBuffer == null || _readBuffer.Length < bcount)
|
||||
_readBuffer = new byte[Math.Max(bcount, 0x4000)];
|
||||
Marshal.Copy((IntPtr)data, _readBuffer, 0, bcount);
|
||||
m_stream.Write(_readBuffer, 0, bcount);
|
||||
pBytesWritten = bcount;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int TellCallback(APE_CIO_Callbacks* id)
|
||||
{
|
||||
return (int)m_stream.Position;
|
||||
}
|
||||
|
||||
uint GetSizeCallback(APE_CIO_Callbacks* id)
|
||||
{
|
||||
return (uint)m_stream.Length;
|
||||
}
|
||||
|
||||
int SeekRelativeCallback(APE_CIO_Callbacks* id, IntPtr delta, int mode)
|
||||
{
|
||||
m_stream.Seek((long)delta, (SeekOrigin)(mode));
|
||||
return 0;
|
||||
}
|
||||
|
||||
internal APE_CIO_Callbacks* Callbacks => m_callbacks;
|
||||
|
||||
APE_CIO_Callbacks* m_callbacks;
|
||||
Stream m_stream;
|
||||
byte[] _readBuffer;
|
||||
CIO_ReadDelegate m_read_bytes;
|
||||
CIO_WriteDelegate m_write_bytes;
|
||||
CIO_GetPositionDelegate m_get_pos;
|
||||
CIO_GetSizeDelegate m_get_size;
|
||||
CIO_SeekDelegate m_seek;
|
||||
}
|
||||
}
|
||||
@@ -51,7 +51,7 @@ namespace CUETools.Converter
|
||||
throw new Exception("Unknown audio decoder " + chosenDecoder + " or unsupported audio type " + fmt.extension);
|
||||
if (decoder == null)
|
||||
throw new Exception("Unsupported audio type: " + path);
|
||||
var settings = fmt.decoder.Settings.Clone();
|
||||
var settings = decoder.Settings.Clone();
|
||||
try
|
||||
{
|
||||
object src = Activator.CreateInstance(decoder.Settings.DecoderType, settings, path, IO);
|
||||
|
||||
@@ -55,8 +55,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Interop", "Interop", "{86BB
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CUETools", "CUETools.csproj", "{EF351583-A9CD-4530-92C3-20AC02136BC2}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CUETools.Codecs.APE", "..\CUETools.Codecs.APE\CUETools.Codecs.APE.vcxproj", "{9AE965C4-301E-4C01-B90F-297AF341ACC6}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CUETools.ARCUE", "..\CUETools.ARCUE\CUETools.ARCUE.csproj", "{A5A8D8FA-9E32-4010-8AAF-AE580C5AF728}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{6458A13A-30EF-45A9-9D58-E5031B17BEE2} = {6458A13A-30EF-45A9-9D58-E5031B17BEE2}
|
||||
@@ -193,6 +191,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libwavpack", "..\ThirdParty
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wavpackdll", "..\ThirdParty\WavPack\wavpackdll\wavpackdll.vcxproj", "{1A87F412-BA74-4DBB-9F77-FD55C042FB63}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MACLibDll", "..\ThirdParty\MAC_SDK\Source\Projects\VS2017\MACLibDll\MACLibDll.vcxproj", "{CEE4A179-49FC-4D51-B045-F717D3A6C13A}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CUETools.Codecs.MACLib", "..\CUETools.Codecs.MACLib\CUETools.Codecs.MACLib.csproj", "{8FE405A0-E837-4088-88AD-B63652E34790}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -211,16 +213,6 @@ Global
|
||||
{EF351583-A9CD-4530-92C3-20AC02136BC2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{EF351583-A9CD-4530-92C3-20AC02136BC2}.Release|Win32.ActiveCfg = Release|Any CPU
|
||||
{EF351583-A9CD-4530-92C3-20AC02136BC2}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{9AE965C4-301E-4C01-B90F-297AF341ACC6}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||
{9AE965C4-301E-4C01-B90F-297AF341ACC6}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{9AE965C4-301E-4C01-B90F-297AF341ACC6}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{9AE965C4-301E-4C01-B90F-297AF341ACC6}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{9AE965C4-301E-4C01-B90F-297AF341ACC6}.Debug|x64.Build.0 = Debug|x64
|
||||
{9AE965C4-301E-4C01-B90F-297AF341ACC6}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{9AE965C4-301E-4C01-B90F-297AF341ACC6}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{9AE965C4-301E-4C01-B90F-297AF341ACC6}.Release|Win32.Build.0 = Release|Win32
|
||||
{9AE965C4-301E-4C01-B90F-297AF341ACC6}.Release|x64.ActiveCfg = Release|x64
|
||||
{9AE965C4-301E-4C01-B90F-297AF341ACC6}.Release|x64.Build.0 = Release|x64
|
||||
{A5A8D8FA-9E32-4010-8AAF-AE580C5AF728}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{A5A8D8FA-9E32-4010-8AAF-AE580C5AF728}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A5A8D8FA-9E32-4010-8AAF-AE580C5AF728}.Debug|Win32.ActiveCfg = Debug|Any CPU
|
||||
@@ -735,6 +727,24 @@ Global
|
||||
{1A87F412-BA74-4DBB-9F77-FD55C042FB63}.Release|Win32.Build.0 = Release|Win32
|
||||
{1A87F412-BA74-4DBB-9F77-FD55C042FB63}.Release|x64.ActiveCfg = Release|x64
|
||||
{1A87F412-BA74-4DBB-9F77-FD55C042FB63}.Release|x64.Build.0 = Release|x64
|
||||
{CEE4A179-49FC-4D51-B045-F717D3A6C13A}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{CEE4A179-49FC-4D51-B045-F717D3A6C13A}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{CEE4A179-49FC-4D51-B045-F717D3A6C13A}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{CEE4A179-49FC-4D51-B045-F717D3A6C13A}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{CEE4A179-49FC-4D51-B045-F717D3A6C13A}.Debug|x64.Build.0 = Debug|x64
|
||||
{CEE4A179-49FC-4D51-B045-F717D3A6C13A}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{CEE4A179-49FC-4D51-B045-F717D3A6C13A}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{CEE4A179-49FC-4D51-B045-F717D3A6C13A}.Release|Win32.Build.0 = Release|Win32
|
||||
{CEE4A179-49FC-4D51-B045-F717D3A6C13A}.Release|x64.ActiveCfg = Release|x64
|
||||
{CEE4A179-49FC-4D51-B045-F717D3A6C13A}.Release|x64.Build.0 = Release|x64
|
||||
{8FE405A0-E837-4088-88AD-B63652E34790}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{8FE405A0-E837-4088-88AD-B63652E34790}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{8FE405A0-E837-4088-88AD-B63652E34790}.Debug|Win32.ActiveCfg = Debug|Any CPU
|
||||
{8FE405A0-E837-4088-88AD-B63652E34790}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{8FE405A0-E837-4088-88AD-B63652E34790}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{8FE405A0-E837-4088-88AD-B63652E34790}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{8FE405A0-E837-4088-88AD-B63652E34790}.Release|Win32.ActiveCfg = Release|Any CPU
|
||||
{8FE405A0-E837-4088-88AD-B63652E34790}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
@@ -747,7 +757,6 @@ Global
|
||||
{FD1DD69E-EC51-443D-B6A7-908B8E0EF9E2} = {FD0D49DB-8F02-4A64-A9A3-A5AF54481770}
|
||||
{9A0D1EB8-269E-4165-971C-541C96AA506F} = {5D823ABE-D280-4800-824C-2633CBAB2EA9}
|
||||
{0E404B8B-FF82-427F-ADE4-77B54A29219F} = {5D823ABE-D280-4800-824C-2633CBAB2EA9}
|
||||
{9AE965C4-301E-4C01-B90F-297AF341ACC6} = {39A17A65-E893-44B8-A312-DDCDD990D9D1}
|
||||
{A5A8D8FA-9E32-4010-8AAF-AE580C5AF728} = {4B59E09C-A51F-4B80-91BE-987904DCEF7D}
|
||||
{32338A04-5B6B-4C63-8EE7-C6400F73B5D7} = {FD0D49DB-8F02-4A64-A9A3-A5AF54481770}
|
||||
{F2EC7193-D5E5-4252-9803-5CEB407E910F} = {93B7AE1D-DEF6-4A04-A222-5CDE09DF262D}
|
||||
@@ -794,6 +803,8 @@ Global
|
||||
{4D1B3411-F4F7-4E62-B7CB-A3AC3D530443} = {93B7AE1D-DEF6-4A04-A222-5CDE09DF262D}
|
||||
{5CCCB9CF-0384-458F-BA08-72B73866840F} = {8B179853-B7D6-479C-B8B2-6CBCE835D040}
|
||||
{1A87F412-BA74-4DBB-9F77-FD55C042FB63} = {8B179853-B7D6-479C-B8B2-6CBCE835D040}
|
||||
{CEE4A179-49FC-4D51-B045-F717D3A6C13A} = {8B179853-B7D6-479C-B8B2-6CBCE835D040}
|
||||
{8FE405A0-E837-4088-88AD-B63652E34790} = {93B7AE1D-DEF6-4A04-A222-5CDE09DF262D}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {C634D169-5814-4203-94B6-6A11371DDA95}
|
||||
|
||||
2
ThirdParty/MAC_SDK
vendored
2
ThirdParty/MAC_SDK
vendored
Submodule ThirdParty/MAC_SDK updated: ec5e7e8ee7...fe94269a91
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user