Codecs cleanup

This commit is contained in:
chudov
2008-11-10 23:54:03 +00:00
parent 58d3af09c7
commit bb1648393e
16 changed files with 385 additions and 783 deletions

View File

@@ -337,6 +337,10 @@
ReferencedProjectIdentifier="{CA200BCB-DFC6-4153-9BD4-785BC768B26B}" ReferencedProjectIdentifier="{CA200BCB-DFC6-4153-9BD4-785BC768B26B}"
RelativePathToProject="..\APETagDotNet\APETagDotNet.csproj" RelativePathToProject="..\APETagDotNet\APETagDotNet.csproj"
/> />
<ProjectReference
ReferencedProjectIdentifier="{6458A13A-30EF-45A9-9D58-E5031B17BEE2}"
RelativePathToProject="..\AudioCodecsDotNet\AudioCodecsDotNet.csproj"
/>
</References> </References>
<Files> <Files>
<Filter <Filter

View File

@@ -7,6 +7,7 @@ using namespace System::Collections::Specialized;
using namespace System::Runtime::InteropServices; using namespace System::Runtime::InteropServices;
using namespace System::IO; using namespace System::IO;
using namespace APETagsDotNet; using namespace APETagsDotNet;
using namespace AudioCodecsDotNet;
#ifndef _WAVEFORMATEX_ #ifndef _WAVEFORMATEX_
#define _WAVEFORMATEX_ #define _WAVEFORMATEX_
@@ -102,14 +103,16 @@ namespace APEDotNet {
GCHandle _gchBuffer; GCHandle _gchBuffer;
}; };
public ref class APEReader { public ref class APEReader : public IAudioSource
{
public: public:
APEReader(String^ path, Stream^ IO) { APEReader(String^ path, Stream^ IO)
{
pAPEDecompress = NULL; pAPEDecompress = NULL;
_sampleOffset = 0; _sampleOffset = 0;
_bufferOffset = 0;
_bufferLength = 0;
_path = path; _path = path;
pBuffer = NULL;
int nRetVal = 0; int nRetVal = 0;
@@ -129,7 +132,7 @@ namespace APEDotNet {
// make a buffer to hold 16384 blocks of audio data // make a buffer to hold 16384 blocks of audio data
nBlockAlign = pAPEDecompress->GetInfo (APE_INFO_BLOCK_ALIGN, 0, 0); nBlockAlign = pAPEDecompress->GetInfo (APE_INFO_BLOCK_ALIGN, 0, 0);
pBuffer = new unsigned char [16384 * nBlockAlign]; _samplesBuffer = gcnew array<unsigned char> (16384 * nBlockAlign);
// loop through the whole file // loop through the whole file
_sampleCount = pAPEDecompress->GetInfo (APE_DECOMPRESS_TOTAL_BLOCKS, 0, 0); // * ? _sampleCount = pAPEDecompress->GetInfo (APE_DECOMPRESS_TOTAL_BLOCKS, 0, 0); // * ?
@@ -137,7 +140,6 @@ namespace APEDotNet {
~APEReader () ~APEReader ()
{ {
if (pBuffer) delete [] pBuffer;
if (_winFileIO) if (_winFileIO)
delete _winFileIO; delete _winFileIO;
if (_gchIO.IsAllocated) if (_gchIO.IsAllocated)
@@ -146,50 +148,57 @@ namespace APEDotNet {
_gchReadBuffer.Free(); _gchReadBuffer.Free();
} }
property Int32 BitsPerSample { virtual property Int32 BitsPerSample {
Int32 get() { Int32 get() {
return _bitsPerSample; return _bitsPerSample;
} }
} }
property Int32 ChannelCount { virtual property Int32 ChannelCount {
Int32 get() { Int32 get() {
return _channelCount; return _channelCount;
} }
} }
property Int32 SampleRate { virtual property Int32 SampleRate {
Int32 get() { Int32 get() {
return _sampleRate; return _sampleRate;
} }
} }
property Int64 Length { virtual property UInt64 Length {
Int64 get() { UInt64 get() {
return _sampleCount; return _sampleCount;
} }
} }
property Int64 Position { virtual property UInt64 Position
Int64 get() { {
return _sampleOffset; UInt64 get() {
return _sampleOffset - SamplesInBuffer;
} }
void set(Int64 offset) { void set(UInt64 offset) {
_sampleOffset = offset; _sampleOffset = offset;
_bufferOffset = 0;
_bufferLength = 0;
if (pAPEDecompress->Seek ((int) offset /*? */)) if (pAPEDecompress->Seek ((int) offset /*? */))
throw gcnew Exception("Unable to seek."); throw gcnew Exception("Unable to seek.");
} }
} }
property Int64 Remaining { virtual property UInt64 Remaining {
Int64 get() { UInt64 get() {
return _sampleCount - _sampleOffset; return _sampleCount - _sampleOffset + SamplesInBuffer;
} }
} }
void Close() { virtual void Close()
if (pAPEDecompress) delete pAPEDecompress; {
if (pAPEDecompress)
{
delete pAPEDecompress;
pAPEDecompress = NULL; pAPEDecompress = NULL;
}
if (_IO != nullptr) if (_IO != nullptr)
{ {
_IO->Close (); _IO->Close ();
@@ -197,14 +206,15 @@ namespace APEDotNet {
} }
} }
property String^ Path { virtual property String^ Path {
String^ get() { String^ get() {
return _path; return _path;
} }
} }
property NameValueCollection^ Tags { virtual property NameValueCollection^ Tags {
NameValueCollection^ get () { NameValueCollection^ get ()
{
if (!_tags) if (!_tags)
{ {
APETagDotNet^ apeTag = gcnew APETagDotNet (_IO, true); APETagDotNet^ apeTag = gcnew APETagDotNet (_IO, true);
@@ -213,33 +223,35 @@ namespace APEDotNet {
} }
return _tags; return _tags;
} }
void set (NameValueCollection ^tags) { void set (NameValueCollection ^tags)
{
_tags = tags; _tags = tags;
} }
} }
Int32 Read([Out] array<Int32, 2>^% sampleBuffer) { virtual UInt32 Read([Out] array<Int32, 2>^ buff, UInt32 sampleCount)
int sampleCount; {
UInt32 buffOffset = 0;
UInt32 samplesNeeded = sampleCount;
while (samplesNeeded != 0)
{
if (SamplesInBuffer == 0)
{
int nBlocksRetrieved; int nBlocksRetrieved;
if (pAPEDecompress->GetData ((char *) pBuffer, 16384, &nBlocksRetrieved)) pin_ptr<unsigned char> pSampleBuffer = &_samplesBuffer[0];
if (pAPEDecompress->GetData ((char *) pSampleBuffer, 16384, &nBlocksRetrieved))
throw gcnew Exception("An error occurred while decoding."); throw gcnew Exception("An error occurred while decoding.");
_bufferOffset = 0;
sampleCount = nBlocksRetrieved; _bufferLength = nBlocksRetrieved;
array<Int32,2>^ _sampleBuffer = gcnew array<Int32,2> (nBlocksRetrieved, 2);
interior_ptr<Int32> pMyBuffer = &_sampleBuffer[0, 0];
short * pAPEBuffer = (short *) pBuffer;
short * pAPEBufferEnd = (short *) pBuffer + 2 * nBlocksRetrieved;
while (pAPEBuffer < pAPEBufferEnd) {
*(pMyBuffer++) = *(pAPEBuffer++);
*(pMyBuffer++) = *(pAPEBuffer++);
}
sampleBuffer = _sampleBuffer;
_sampleOffset += nBlocksRetrieved; _sampleOffset += nBlocksRetrieved;
}
UInt32 copyCount = Math::Min(samplesNeeded, SamplesInBuffer);
AudioSamples::BytesToFLACSamples_16(_samplesBuffer, _bufferOffset*nBlockAlign, buff, buffOffset, copyCount, _channelCount);
samplesNeeded -= copyCount;
buffOffset += copyCount;
_bufferOffset += copyCount;
}
return sampleCount; return sampleCount;
} }
@@ -249,22 +261,33 @@ namespace APEDotNet {
NameValueCollection^ _tags; NameValueCollection^ _tags;
Int64 _sampleCount, _sampleOffset; Int64 _sampleCount, _sampleOffset;
Int32 _bitsPerSample, _channelCount, _sampleRate; Int32 _bitsPerSample, _channelCount, _sampleRate;
UInt32 _bufferOffset, _bufferLength;
int nBlockAlign; int nBlockAlign;
unsigned char * pBuffer; array<unsigned char>^ _samplesBuffer;
String^ _path; String^ _path;
Stream^ _IO; Stream^ _IO;
array<unsigned char>^ _readBuffer; array<unsigned char>^ _readBuffer;
CWinFileIO* _winFileIO; CWinFileIO* _winFileIO;
GCHandle _gchIO, _gchReadBuffer; GCHandle _gchIO, _gchReadBuffer;
property UInt32 SamplesInBuffer
{
UInt32 get ()
{
return (UInt32) (_bufferLength - _bufferOffset);
}
}
}; };
public ref class APEWriter { public ref class APEWriter : IAudioDest
{
public: public:
APEWriter(String^ path, Int32 bitsPerSample, Int32 channelCount, Int32 sampleRate) { APEWriter(String^ path, Int32 bitsPerSample, Int32 channelCount, Int32 sampleRate)
{
if ((channelCount != 1) && (channelCount != 2)) { if (bitsPerSample != 16 && bitsPerSample != 24)
throw gcnew Exception("Bits per sample must be 16 or 24.");
if (channelCount != 1 && channelCount != 2)
throw gcnew Exception("Only stereo and mono audio formats are allowed."); throw gcnew Exception("Only stereo and mono audio formats are allowed.");
}
_path = path; _path = path;
_tags = gcnew NameValueCollection(); _tags = gcnew NameValueCollection();
@@ -279,9 +302,8 @@ namespace APEDotNet {
int nRetVal; int nRetVal;
pAPECompress = CreateIAPECompress (&nRetVal); pAPECompress = CreateIAPECompress (&nRetVal);
if (!pAPECompress) { if (!pAPECompress)
throw gcnew Exception("Unable to open file."); throw gcnew Exception("Unable to open APE compressor.");
}
} }
~APEWriter() ~APEWriter()
@@ -294,7 +316,8 @@ namespace APEDotNet {
_gchBuffer.Free(); _gchBuffer.Free();
} }
void Close() { virtual void Close()
{
if (pAPECompress) if (pAPECompress)
{ {
pAPECompress->Finish (NULL, 0, 0); pAPECompress->Finish (NULL, 0, 0);
@@ -322,21 +345,47 @@ namespace APEDotNet {
} }
} }
property Int32 FinalSampleCount { virtual property Int64 FinalSampleCount
Int32 get() { {
Int64 get()
{
return _finalSampleCount; return _finalSampleCount;
} }
void set(Int32 value) { void set(Int64 value)
if (value < 0) { {
if (value < 0)
throw gcnew Exception("Invalid final sample count."); throw gcnew Exception("Invalid final sample count.");
} if (_initialized)
if (_initialized) {
throw gcnew Exception("Final sample count cannot be changed after encoding begins."); throw gcnew Exception("Final sample count cannot be changed after encoding begins.");
}
_finalSampleCount = value; _finalSampleCount = value;
} }
} }
virtual void Write(array<Int32,2>^ buff, UInt32 sampleCount)
{
if (_sampleBuffer == nullptr || _sampleBuffer.Length < sampleCount * _blockAlign)
_sampleBuffer = gcnew array<unsigned char>(sampleCount * _blockAlign);
AudioSamples::FLACSamplesToBytes(buff, 0, _sampleBuffer, 0, sampleCount, _channelCount, _bitsPerSample);
if (!_initialized) Initialize();
pin_ptr<unsigned char> pSampleBuffer = &_sampleBuffer[0];
if (pAPECompress->AddData (pSampleBuffer, sampleCount * _blockAlign))
throw gcnew Exception("An error occurred while encoding.");
_samplesWritten += sampleCount;
}
virtual property String^ Path
{
String^ get() {
return _path;
}
}
virtual bool SetTags (NameValueCollection^ tags)
{
_tags = tags;
return true;
}
property Int32 CompressionLevel { property Int32 CompressionLevel {
Int32 get() { Int32 get() {
return _compressionLevel; return _compressionLevel;
@@ -349,24 +398,6 @@ namespace APEDotNet {
} }
} }
void Write(array<unsigned char>^ sampleBuffer, UInt32 sampleCount) {
if (!_initialized) Initialize();
pin_ptr<unsigned char> pSampleBuffer = &sampleBuffer[0];
if (pAPECompress->AddData (pSampleBuffer, sampleCount * _blockAlign))
throw gcnew Exception("An error occurred while encoding.");
_samplesWritten += sampleCount;
}
property String^ Path {
String^ get() {
return _path;
}
}
void SetTags (NameValueCollection^ tags) {
_tags = tags;
}
private: private:
IAPECompress * pAPECompress; IAPECompress * pAPECompress;
bool _initialized; bool _initialized;
@@ -379,6 +410,7 @@ namespace APEDotNet {
GCHandle _gchIO, _gchBuffer; GCHandle _gchIO, _gchBuffer;
CWinFileIO* _winFileIO; CWinFileIO* _winFileIO;
array<unsigned char>^ _writeBuffer; array<unsigned char>^ _writeBuffer;
array<unsigned char>^ _sampleBuffer;
void Initialize() { void Initialize() {
_IO = gcnew FileStream (_path, FileMode::Create, FileAccess::ReadWrite, FileShare::Read); _IO = gcnew FileStream (_path, FileMode::Create, FileAccess::ReadWrite, FileShare::Read);
@@ -408,7 +440,10 @@ namespace APEDotNet {
{ {
array<unsigned char>^ buff = (array<unsigned char>^) _gchBuffer.Target; array<unsigned char>^ buff = (array<unsigned char>^) _gchBuffer.Target;
if (buff->Length < nBytesToRead) if (buff->Length < nBytesToRead)
{
Array::Resize (buff, nBytesToRead); Array::Resize (buff, nBytesToRead);
_gchBuffer.Target = buff;
}
int len = ((Stream^)_gchIO.Target)->Read (buff, 0, nBytesToRead); int len = ((Stream^)_gchIO.Target)->Read (buff, 0, nBytesToRead);
if (len) Marshal::Copy (buff, 0, (IntPtr)pBuffer, len); if (len) Marshal::Copy (buff, 0, (IntPtr)pBuffer, len);
*pBytesRead = len; *pBytesRead = len;
@@ -419,7 +454,10 @@ namespace APEDotNet {
{ {
array<unsigned char>^ buff = (array<unsigned char>^) _gchBuffer.Target; array<unsigned char>^ buff = (array<unsigned char>^) _gchBuffer.Target;
if (buff->Length < nBytesToWrite) if (buff->Length < nBytesToWrite)
{
Array::Resize (buff, nBytesToWrite); Array::Resize (buff, nBytesToWrite);
_gchBuffer.Target = buff;
}
Marshal::Copy ((IntPtr)(void*)pBuffer, buff, 0, nBytesToWrite); Marshal::Copy ((IntPtr)(void*)pBuffer, buff, 0, nBytesToWrite);
((Stream^)_gchIO.Target)->Write (buff, 0, nBytesToWrite); ((Stream^)_gchIO.Target)->Write (buff, 0, nBytesToWrite);
*pBytesWritten = nBytesToWrite; *pBytesWritten = nBytesToWrite;

View File

@@ -29,7 +29,7 @@ namespace AudioCodecsDotNet
string Path { get; } string Path { get; }
} }
public class AudioCodecsDotNet public class AudioSamples
{ {
public static unsafe void FLACSamplesToBytes_16(int[,] inSamples, uint inSampleOffset, public static unsafe void FLACSamplesToBytes_16(int[,] inSamples, uint inSampleOffset,
byte[] outSamples, uint outByteOffset, uint sampleCount, int channelCount) byte[] outSamples, uint outByteOffset, uint sampleCount, int channelCount)
@@ -92,9 +92,9 @@ namespace AudioCodecsDotNet
byte[] outSamples, uint outByteOffset, uint sampleCount, int channelCount, int bitsPerSample) byte[] outSamples, uint outByteOffset, uint sampleCount, int channelCount, int bitsPerSample)
{ {
if (bitsPerSample == 16) if (bitsPerSample == 16)
AudioCodecsDotNet.FLACSamplesToBytes_16(inSamples, inSampleOffset, outSamples, outByteOffset, sampleCount, channelCount); AudioSamples.FLACSamplesToBytes_16(inSamples, inSampleOffset, outSamples, outByteOffset, sampleCount, channelCount);
else if (bitsPerSample == 24) else if (bitsPerSample == 24)
AudioCodecsDotNet.FLACSamplesToBytes_24(inSamples, inSampleOffset, outSamples, outByteOffset, sampleCount, channelCount); AudioSamples.FLACSamplesToBytes_24(inSamples, inSampleOffset, outSamples, outByteOffset, sampleCount, channelCount);
else else
throw new Exception("Unsupported bitsPerSample value"); throw new Exception("Unsupported bitsPerSample value");
} }
@@ -483,7 +483,7 @@ namespace AudioCodecsDotNet
_sampleBuffer = new byte[byteCount]; _sampleBuffer = new byte[byteCount];
if (_IO.Read(_sampleBuffer, 0, (int)byteCount) != byteCount) if (_IO.Read(_sampleBuffer, 0, (int)byteCount) != byteCount)
throw new Exception("Incomplete file read."); throw new Exception("Incomplete file read.");
AudioCodecsDotNet.BytesToFLACSamples_16 (_sampleBuffer, 0, buff, 0, AudioSamples.BytesToFLACSamples_16(_sampleBuffer, 0, buff, 0,
sampleCount, _channelCount); sampleCount, _channelCount);
_samplePos += sampleCount; _samplePos += sampleCount;
return sampleCount; return sampleCount;
@@ -596,7 +596,7 @@ namespace AudioCodecsDotNet
return; return;
if (_sampleBuffer == null || _sampleBuffer.Length < sampleCount * _blockAlign) if (_sampleBuffer == null || _sampleBuffer.Length < sampleCount * _blockAlign)
_sampleBuffer = new byte[sampleCount * _blockAlign]; _sampleBuffer = new byte[sampleCount * _blockAlign];
AudioCodecsDotNet.FLACSamplesToBytes(buff, 0, _sampleBuffer, 0, AudioSamples.FLACSamplesToBytes(buff, 0, _sampleBuffer, 0,
sampleCount, _channelCount, _bitsPerSample); sampleCount, _channelCount, _bitsPerSample);
_IO.Write(_sampleBuffer, 0, (int)sampleCount * _blockAlign); _IO.Write(_sampleBuffer, 0, (int)sampleCount * _blockAlign);
_sampleLen += sampleCount; _sampleLen += sampleCount;

View File

@@ -53,500 +53,4 @@ namespace CUEToolsLib {
return dest; return dest;
} }
} }
#if !MONO
class FLACReader : IAudioSource {
FLACDotNet.FLACReader _flacReader;
int[,] _sampleBuffer;
uint _bufferOffset, _bufferLength;
public FLACReader(string path, Stream IO)
{
_flacReader = new FLACDotNet.FLACReader(path, IO);
_bufferOffset = 0;
_bufferLength = 0;
}
public void Close() {
_flacReader.Close();
}
public NameValueCollection Tags
{
get { return _flacReader.Tags; }
set { _flacReader.Tags = value; }
}
public bool UpdateTags(bool preserveTime)
{
return _flacReader.UpdateTags(preserveTime);
}
public ulong Length {
get {
return (ulong) _flacReader.Length;
}
}
public ulong Remaining {
get {
return (ulong) _flacReader.Remaining + SamplesInBuffer;
}
}
public ulong Position {
get {
return (ulong) _flacReader.Position - SamplesInBuffer;
}
set {
_flacReader.Position = (long) value;
_bufferOffset = 0;
_bufferLength = 0;
}
}
private uint SamplesInBuffer {
get {
return (uint) (_bufferLength - _bufferOffset);
}
}
public int BitsPerSample {
get {
return _flacReader.BitsPerSample;
}
}
public int ChannelCount {
get {
return _flacReader.ChannelCount;
}
}
public int SampleRate {
get {
return _flacReader.SampleRate;
}
}
public uint Read(int [,] buff, uint sampleCount) {
if (_flacReader.BitsPerSample != 16) {
throw new Exception("Reading is only supported for 16 bit sample depth.");
}
int chanCount = _flacReader.ChannelCount;
uint copyCount;
uint buffOffset = 0;
uint samplesNeeded = sampleCount;
while (samplesNeeded != 0) {
if (SamplesInBuffer == 0) {
_bufferOffset = 0;
_bufferLength = (uint) _flacReader.Read(out _sampleBuffer);
}
copyCount = Math.Min(samplesNeeded, SamplesInBuffer);
Array.Copy(_sampleBuffer, _bufferOffset * chanCount, buff, buffOffset * chanCount, copyCount * chanCount);
samplesNeeded -= copyCount;
buffOffset += copyCount;
_bufferOffset += copyCount;
}
return sampleCount;
}
public string Path { get { return _flacReader.Path; } }
}
class FLACWriter : IAudioDest {
FLACDotNet.FLACWriter _flacWriter;
int _bitsPerSample;
int _channelCount;
int _sampleRate;
public FLACWriter(string path, int bitsPerSample, int channelCount, int sampleRate) {
if (bitsPerSample != 16 && bitsPerSample != 24) {
throw new Exception("Bits per sample must be 16 or 24.");
}
_bitsPerSample = bitsPerSample;
_channelCount = channelCount;
_sampleRate = sampleRate;
_flacWriter = new FLACDotNet.FLACWriter(path, bitsPerSample, channelCount, sampleRate);
}
public long FinalSampleCount {
get {
return _flacWriter.FinalSampleCount;
}
set {
_flacWriter.FinalSampleCount = value;
}
}
public int CompressionLevel {
get {
return _flacWriter.CompressionLevel;
}
set {
_flacWriter.CompressionLevel = value;
}
}
public bool Verify {
get {
return _flacWriter.Verify;
}
set {
_flacWriter.Verify = value;
}
}
public bool SetTags(NameValueCollection tags)
{
_flacWriter.SetTags (tags);
return true;
}
public void Close() {
_flacWriter.Close();
}
public void Write(int[,] buff, uint sampleCount)
{
_flacWriter.Write(buff, (int) sampleCount);
}
public string Path { get { return _flacWriter.Path; } }
}
#endif
#if !MONO
class APEReader : IAudioSource {
APEDotNet.APEReader _apeReader;
int[,] _sampleBuffer;
uint _bufferOffset, _bufferLength;
public APEReader(string path, Stream IO) {
_apeReader = new APEDotNet.APEReader(path, IO);
_bufferOffset = 0;
_bufferLength = 0;
}
public void Close() {
_apeReader.Close();
}
public ulong Length {
get {
return (ulong) _apeReader.Length;
}
}
public ulong Remaining {
get {
return (ulong) _apeReader.Remaining + SamplesInBuffer;
}
}
public ulong Position {
get {
return (ulong) _apeReader.Position - SamplesInBuffer;
}
set {
_apeReader.Position = (long) value;
_bufferOffset = 0;
_bufferLength = 0;
}
}
private uint SamplesInBuffer {
get {
return (uint) (_bufferLength - _bufferOffset);
}
}
public int BitsPerSample {
get {
return _apeReader.BitsPerSample;
}
}
public int ChannelCount {
get {
return _apeReader.ChannelCount;
}
}
public int SampleRate {
get {
return _apeReader.SampleRate;
}
}
public NameValueCollection Tags
{
get { return _apeReader.Tags; }
set { _apeReader.Tags = value; }
}
private unsafe void APESamplesToFLACSamples(int[,] inSamples, uint inSampleOffset,
int[,] outSamples, uint outSampleOffset, uint sampleCount, int channelCount)
{
uint loopCount = sampleCount * (uint) channelCount;
if ((inSamples.GetLength(0) - inSampleOffset < sampleCount) ||
(outSamples.GetLength(0) - outSampleOffset < sampleCount))
{
throw new IndexOutOfRangeException();
}
fixed (int* pInSamplesFixed = &inSamples[inSampleOffset, 0]) {
fixed (int * pOutSamplesFixed = &outSamples[outSampleOffset, 0]) {
int* pInSamples = pInSamplesFixed;
int* pOutSamples = pOutSamplesFixed;
for (int i = 0; i < loopCount; i++) {
*(pOutSamples++) = *(pInSamples++);
}
}
}
}
public uint Read(int[,] buff, uint sampleCount) {
if (_apeReader.BitsPerSample != 16) {
throw new Exception("Reading is only supported for 16 bit sample depth.");
}
int chanCount = _apeReader.ChannelCount;
uint samplesNeeded, copyCount, buffOffset;
buffOffset = 0;
samplesNeeded = sampleCount;
while (samplesNeeded != 0) {
if (SamplesInBuffer == 0) {
_bufferOffset = 0;
_bufferLength = (uint) _apeReader.Read(out _sampleBuffer);
}
copyCount = Math.Min(samplesNeeded, SamplesInBuffer);
Array.Copy(_sampleBuffer, _bufferOffset * chanCount, buff, buffOffset * chanCount, copyCount * chanCount);
//APESamplesToFLACSamples(_sampleBuffer, _bufferOffset, buff, buffOffset,
// copyCount, chanCount);
samplesNeeded -= copyCount;
buffOffset += copyCount;
_bufferOffset += copyCount;
}
return sampleCount;
}
public string Path { get { return _apeReader.Path; } }
}
class APEWriter : IAudioDest
{
APEDotNet.APEWriter _apeWriter;
byte[] _sampleBuffer;
int _bitsPerSample;
int _channelCount;
int _sampleRate;
int _blockAlign;
public APEWriter(string path, int bitsPerSample, int channelCount, int sampleRate)
{
if (bitsPerSample != 16 && bitsPerSample != 24)
{
throw new Exception("Bits per sample must be 16 or 24.");
}
_bitsPerSample = bitsPerSample;
_channelCount = channelCount;
_sampleRate = sampleRate;
_blockAlign = _channelCount * ((_bitsPerSample + 7) / 8);
_apeWriter = new APEDotNet.APEWriter(path, bitsPerSample, channelCount, sampleRate);
}
public long FinalSampleCount
{
get { return _apeWriter.FinalSampleCount; }
set { _apeWriter.FinalSampleCount = (int) value; }
}
public int CompressionLevel
{
get { return _apeWriter.CompressionLevel; }
set { _apeWriter.CompressionLevel = value; }
}
public bool SetTags(NameValueCollection tags)
{
_apeWriter.SetTags(tags);
return true;
}
public void Close()
{
_apeWriter.Close();
}
public void Write(int [,] buff, uint sampleCount)
{
if (_sampleBuffer == null || _sampleBuffer.Length < sampleCount * _blockAlign)
_sampleBuffer = new byte[sampleCount * _blockAlign];
AudioCodecsDotNet.AudioCodecsDotNet.FLACSamplesToBytes (buff, 0, _sampleBuffer, 0, sampleCount, _channelCount, _bitsPerSample);
_apeWriter.Write(_sampleBuffer, sampleCount);
}
public string Path { get { return _apeWriter.Path; } }
}
#endif
#if !MONO
class WavPackReader : IAudioSource {
WavPackDotNet.WavPackReader _wavPackReader;
public WavPackReader(string path, Stream IO, Stream IO_WVC) {
_wavPackReader = new WavPackDotNet.WavPackReader(path, IO, IO_WVC);
}
public void Close() {
_wavPackReader.Close();
}
public ulong Length {
get {
return (ulong) _wavPackReader.Length;
}
}
public ulong Remaining {
get {
return (ulong) _wavPackReader.Remaining;
}
}
public ulong Position {
get {
return (ulong) _wavPackReader.Position;
}
set {
_wavPackReader.Position = (int) value;
}
}
public int BitsPerSample {
get {
return _wavPackReader.BitsPerSample;
}
}
public int ChannelCount {
get {
return _wavPackReader.ChannelCount;
}
}
public int SampleRate {
get {
return _wavPackReader.SampleRate;
}
}
public NameValueCollection Tags
{
get { return _wavPackReader.Tags; }
set { _wavPackReader.Tags = value; }
}
public uint Read(int[,] buff, uint sampleCount) {
if (_wavPackReader.BitsPerSample != 16) {
throw new Exception("Reading is only supported for 16 bit sample depth.");
}
_wavPackReader.Read(buff, (int) sampleCount);
return sampleCount;
}
public string Path { get { return _wavPackReader.Path; } }
}
class WavPackWriter : IAudioDest {
WavPackDotNet.WavPackWriter _wavPackWriter;
int _bitsPerSample;
int _channelCount;
int _sampleRate;
int _blockAlign;
byte[] _sampleBuffer;
public WavPackWriter(string path, int bitsPerSample, int channelCount, int sampleRate) {
if (bitsPerSample != 16 && bitsPerSample != 24)
{
throw new Exception("Bits per sample must be 16 or 24.");
}
_bitsPerSample = bitsPerSample;
_channelCount = channelCount;
_sampleRate = sampleRate;
_blockAlign = _channelCount * ((_bitsPerSample + 7) / 8);
_wavPackWriter = new WavPackDotNet.WavPackWriter(path, bitsPerSample, channelCount, sampleRate);
}
public bool SetTags(NameValueCollection tags)
{
_wavPackWriter.SetTags(tags);
return true;
}
public long FinalSampleCount {
get {
return _wavPackWriter.FinalSampleCount;
}
set {
_wavPackWriter.FinalSampleCount = (int)value;
}
}
public int CompressionMode {
get {
return _wavPackWriter.CompressionMode;
}
set {
_wavPackWriter.CompressionMode = value;
}
}
public int ExtraMode {
get {
return _wavPackWriter.ExtraMode;
}
set {
_wavPackWriter.ExtraMode = value;
}
}
public bool MD5Sum
{
get
{
return _wavPackWriter.MD5Sum;
}
set
{
_wavPackWriter.MD5Sum = value;
}
}
public void Close() {
_wavPackWriter.Close();
}
public void Write(int[,] sampleBuffer, uint sampleCount) {
if (MD5Sum)
{
if (_sampleBuffer == null || _sampleBuffer.Length < sampleCount * _blockAlign)
_sampleBuffer = new byte[sampleCount * _blockAlign];
AudioCodecsDotNet.AudioCodecsDotNet.FLACSamplesToBytes(sampleBuffer, 0, _sampleBuffer, 0, sampleCount, _channelCount, _bitsPerSample);
_wavPackWriter.UpdateHash(_sampleBuffer, (int) sampleCount * _blockAlign);
}
_wavPackWriter.Write(sampleBuffer, (int) sampleCount);
}
public string Path { get { return _wavPackWriter.Path; } }
}
#endif
} }

View File

@@ -31,6 +31,9 @@ using AudioCodecsDotNet;
using HDCDDotNet; using HDCDDotNet;
#if !MONO #if !MONO
using UnRarDotNet; using UnRarDotNet;
using FLACDotNet;
using APEDotNet;
using WavPackDotNet;
#endif #endif
namespace CUEToolsLib namespace CUEToolsLib

View File

@@ -328,6 +328,10 @@
RelativePath="System.XML.dll" RelativePath="System.XML.dll"
AssemblyName="System.Xml, Version=2.0.0.0, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL" AssemblyName="System.Xml, Version=2.0.0.0, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL"
/> />
<ProjectReference
ReferencedProjectIdentifier="{6458A13A-30EF-45A9-9D58-E5031B17BEE2}"
RelativePathToProject="..\AudioCodecsDotNet\AudioCodecsDotNet.csproj"
/>
</References> </References>
<Files> <Files>
<Filter <Filter

View File

@@ -35,6 +35,7 @@ using namespace System::IO;
using namespace System::Collections::Generic; using namespace System::Collections::Generic;
using namespace System::Collections::Specialized; using namespace System::Collections::Specialized;
using namespace System::Runtime::InteropServices; using namespace System::Runtime::InteropServices;
using namespace AudioCodecsDotNet;
#include "FLAC\all.h" #include "FLAC\all.h"
#include <string> #include <string>
@@ -67,9 +68,11 @@ namespace FLACDotNet {
[UnmanagedFunctionPointer(CallingConvention::Cdecl)] [UnmanagedFunctionPointer(CallingConvention::Cdecl)]
public delegate FLAC__bool DecoderEofDelegate (const FLAC__StreamDecoder *decoder, void *client_data); public delegate FLAC__bool DecoderEofDelegate (const FLAC__StreamDecoder *decoder, void *client_data);
public ref class FLACReader { public ref class FLACReader : public IAudioSource
{
public: public:
FLACReader(String^ path, Stream^ IO) { FLACReader(String^ path, Stream^ IO)
{
_tags = gcnew NameValueCollection(); _tags = gcnew NameValueCollection();
_writeDel = gcnew DecoderWriteDelegate(this, &FLACReader::WriteCallback); _writeDel = gcnew DecoderWriteDelegate(this, &FLACReader::WriteCallback);
@@ -84,9 +87,10 @@ namespace FLACDotNet {
_decoderActive = false; _decoderActive = false;
_sampleOffset = 0; _sampleOffset = 0;
_samplesWaiting = 0;
_sampleBuffer = nullptr; _sampleBuffer = nullptr;
_path = path; _path = path;
_bufferOffset = 0;
_bufferLength = 0;
_IO = (IO != nullptr) ? IO : gcnew FileStream (path, FileMode::Open, FileAccess::Read, FileShare::Read); _IO = (IO != nullptr) ? IO : gcnew FileStream (path, FileMode::Open, FileAccess::Read, FileShare::Read);
@@ -122,50 +126,53 @@ namespace FLACDotNet {
Close (); Close ();
} }
property Int32 BitsPerSample { virtual property Int32 BitsPerSample {
Int32 get() { Int32 get() {
return _bitsPerSample; return _bitsPerSample;
} }
} }
property Int32 ChannelCount { virtual property Int32 ChannelCount {
Int32 get() { Int32 get() {
return _channelCount; return _channelCount;
} }
} }
property Int32 SampleRate { virtual property Int32 SampleRate {
Int32 get() { Int32 get() {
return _sampleRate; return _sampleRate;
} }
} }
property Int64 Length { virtual property UInt64 Length {
Int64 get() { UInt64 get() {
return _sampleCount; return _sampleCount;
} }
} }
property Int64 Position { virtual property UInt64 Position {
Int64 get() { UInt64 get()
return _sampleOffset; {
return _sampleOffset - SamplesInBuffer;
} }
void set(Int64 offset) { void set(UInt64 offset)
{
_sampleOffset = offset; _sampleOffset = offset;
_samplesWaiting = 0; _bufferOffset = 0;
_bufferLength = 0;
if (!FLAC__stream_decoder_seek_absolute(_decoder, offset)) { if (!FLAC__stream_decoder_seek_absolute(_decoder, offset)) {
throw gcnew Exception("Unable to seek."); throw gcnew Exception("Unable to seek.");
} }
} }
} }
property String^ Path { virtual property String^ Path {
String^ get() { String^ get() {
return _path; return _path;
} }
} }
property NameValueCollection^ Tags { virtual property NameValueCollection^ Tags {
NameValueCollection^ get () { NameValueCollection^ get () {
return _tags; return _tags;
} }
@@ -238,13 +245,13 @@ namespace FLACDotNet {
return 0 != res; return 0 != res;
} }
property Int64 Remaining { virtual property UInt64 Remaining {
Int64 get() { UInt64 get() {
return _sampleCount - _sampleOffset; return _sampleCount - _sampleOffset + SamplesInBuffer;
} }
} }
void Close() { virtual void Close() {
if (_decoderActive) if (_decoderActive)
{ {
FLAC__stream_decoder_finish(_decoder); FLAC__stream_decoder_finish(_decoder);
@@ -258,18 +265,30 @@ namespace FLACDotNet {
} }
} }
Int32 Read([Out] array<Int32, 2>^% sampleBuffer) virtual UInt32 Read([Out] array<Int32, 2>^ buff, UInt32 sampleCount)
{ {
while (_samplesWaiting == 0) { UInt32 buffOffset = 0;
if (!FLAC__stream_decoder_process_single(_decoder)) { UInt32 samplesNeeded = sampleCount;
throw gcnew Exception("An error occurred while decoding.");
}
}
int sampleCount = _samplesWaiting; while (samplesNeeded != 0)
sampleBuffer = _sampleBuffer; {
_sampleOffset += sampleCount; if (SamplesInBuffer == 0)
_samplesWaiting = 0; {
_bufferOffset = 0;
_bufferLength = 0;
do
{
if (!FLAC__stream_decoder_process_single(_decoder))
throw gcnew Exception("An error occurred while decoding.");
} while (_bufferLength == 0);
_sampleOffset += _bufferLength;
}
UInt32 copyCount = Math::Min(samplesNeeded, SamplesInBuffer);
Array::Copy(_sampleBuffer, _bufferOffset * _channelCount, buff, buffOffset * _channelCount, copyCount * _channelCount);
samplesNeeded -= copyCount;
buffOffset += copyCount;
_bufferOffset += copyCount;
}
return sampleCount; return sampleCount;
} }
@@ -287,18 +306,25 @@ namespace FLACDotNet {
Int32 _bitsPerSample, _channelCount, _sampleRate; Int32 _bitsPerSample, _channelCount, _sampleRate;
array<Int32, 2>^ _sampleBuffer; array<Int32, 2>^ _sampleBuffer;
array<unsigned char>^ _readBuffer; array<unsigned char>^ _readBuffer;
int _samplesWaiting;
NameValueCollection^ _tags; NameValueCollection^ _tags;
String^ _path; String^ _path;
bool _decoderActive; bool _decoderActive;
Stream^ _IO; Stream^ _IO;
UInt32 _bufferOffset, _bufferLength;
property UInt32 SamplesInBuffer {
UInt32 get ()
{
return (UInt32) (_bufferLength - _bufferOffset);
}
}
FLAC__StreamDecoderWriteStatus WriteCallback(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderWriteStatus WriteCallback(const FLAC__StreamDecoder *decoder,
const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data) const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
{ {
Int32 sampleCount = frame->header.blocksize; Int32 sampleCount = frame->header.blocksize;
if (_samplesWaiting > 0) { if (_bufferLength > 0) {
throw gcnew Exception("Received unrequested samples."); throw gcnew Exception("Received unrequested samples.");
} }
@@ -325,8 +351,7 @@ namespace FLACDotNet {
} }
} }
_samplesWaiting = sampleCount; _bufferLength = sampleCount;
return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
} }
@@ -425,9 +450,14 @@ namespace FLACDotNet {
} }
}; };
public ref class FLACWriter { public ref class FLACWriter : IAudioDest
{
public: public:
FLACWriter(String^ path, Int32 bitsPerSample, Int32 channelCount, Int32 sampleRate) { FLACWriter(String^ path, Int32 bitsPerSample, Int32 channelCount, Int32 sampleRate)
{
if (bitsPerSample != 16 && bitsPerSample != 24)
throw gcnew Exception("Bits per sample must be 16 or 24.");
_initialized = false; _initialized = false;
_path = path; _path = path;
_finalSampleCount = 0; _finalSampleCount = 0;
@@ -447,7 +477,7 @@ namespace FLACDotNet {
FLAC__stream_encoder_set_sample_rate(_encoder, sampleRate); FLAC__stream_encoder_set_sample_rate(_encoder, sampleRate);
} }
void Close() { virtual void Close() {
FLAC__stream_encoder_finish(_encoder); FLAC__stream_encoder_finish(_encoder);
for (int i = 0; i < _metadataCount; i++) { for (int i = 0; i < _metadataCount; i++) {
@@ -466,7 +496,7 @@ namespace FLACDotNet {
_tags->Clear (); _tags->Clear ();
} }
property Int64 FinalSampleCount { virtual property Int64 FinalSampleCount {
Int64 get() { Int64 get() {
return _finalSampleCount; return _finalSampleCount;
} }
@@ -481,6 +511,32 @@ namespace FLACDotNet {
} }
} }
virtual bool SetTags (NameValueCollection^ tags)
{
_tags = tags;
return true;
}
virtual property String^ Path {
String^ get() {
return _path;
}
}
virtual void Write(array<Int32, 2>^ sampleBuffer, UInt32 sampleCount) {
if (!_initialized) Initialize();
pin_ptr<Int32> pSampleBuffer = &sampleBuffer[0, 0];
if (!FLAC__stream_encoder_process_interleaved(_encoder,
(const FLAC__int32*)pSampleBuffer, sampleCount))
{
throw gcnew Exception("An error occurred while encoding.");
}
_samplesWritten += sampleCount;
}
property Int32 CompressionLevel { property Int32 CompressionLevel {
Int32 get() { Int32 get() {
return _compressionLevel; return _compressionLevel;
@@ -514,30 +570,6 @@ namespace FLACDotNet {
} }
} }
void SetTags (NameValueCollection^ tags) {
_tags = tags;
}
property String^ Path {
String^ get() {
return _path;
}
}
void Write(array<Int32, 2>^ sampleBuffer, Int32 sampleCount) {
if (!_initialized) Initialize();
pin_ptr<Int32> pSampleBuffer = &sampleBuffer[0, 0];
if (!FLAC__stream_encoder_process_interleaved(_encoder,
(const FLAC__int32*)pSampleBuffer, sampleCount))
{
throw gcnew Exception("An error occurred while encoding.");
}
_samplesWritten += sampleCount;
}
private: private:
FLAC__StreamEncoder *_encoder; FLAC__StreamEncoder *_encoder;
bool _initialized; bool _initialized;

View File

@@ -116,7 +116,7 @@ namespace HDCDDotNet
{ {
if (_inSampleBuffer == null || _inSampleBuffer.GetLength(0) < sampleCount) if (_inSampleBuffer == null || _inSampleBuffer.GetLength(0) < sampleCount)
_inSampleBuffer = new int[sampleCount, _channelCount]; _inSampleBuffer = new int[sampleCount, _channelCount];
AudioCodecsDotNet.AudioCodecsDotNet.BytesToFLACSamples_16(buff, 0, _inSampleBuffer, 0, sampleCount, _channelCount); AudioSamples.BytesToFLACSamples_16(buff, 0, _inSampleBuffer, 0, sampleCount, _channelCount);
Process(_inSampleBuffer, sampleCount); Process(_inSampleBuffer, sampleCount);
} }

View File

@@ -35,6 +35,7 @@ using namespace System::Collections::Specialized;
using namespace System::Security::Cryptography; using namespace System::Security::Cryptography;
using namespace System::IO; using namespace System::IO;
using namespace APETagsDotNet; using namespace APETagsDotNet;
using namespace AudioCodecsDotNet;
#include <stdio.h> #include <stdio.h>
#include <memory.h> #include <memory.h>
@@ -59,9 +60,11 @@ namespace WavPackDotNet {
[UnmanagedFunctionPointer(CallingConvention::Cdecl)] [UnmanagedFunctionPointer(CallingConvention::Cdecl)]
public delegate int DecoderCanSeekDelegate(void *id); public delegate int DecoderCanSeekDelegate(void *id);
public ref class WavPackReader { public ref class WavPackReader : public IAudioSource
{
public: public:
WavPackReader(String^ path, Stream^ IO, Stream^ IO_WVC) { WavPackReader(String^ path, Stream^ IO, Stream^ IO_WVC)
{
char errorMessage[256]; char errorMessage[256];
_readDel = gcnew DecoderReadDelegate (this, &WavPackReader::ReadCallback); _readDel = gcnew DecoderReadDelegate (this, &WavPackReader::ReadCallback);
@@ -89,14 +92,6 @@ namespace WavPackDotNet {
_IO = (IO != nullptr) ? IO : gcnew FileStream (path, FileMode::Open, FileAccess::Read, FileShare::Read); _IO = (IO != nullptr) ? IO : gcnew FileStream (path, FileMode::Open, FileAccess::Read, FileShare::Read);
_IO_WVC = (IO != nullptr) ? IO_WVC : System::IO::File::Exists (path+"c") ? gcnew FileStream (path+"c", FileMode::Open, FileAccess::Read, FileShare::Read) : nullptr; _IO_WVC = (IO != nullptr) ? IO_WVC : System::IO::File::Exists (path+"c") ? gcnew FileStream (path+"c", FileMode::Open, FileAccess::Read, FileShare::Read) : nullptr;
//IntPtr pathChars;
//pathChars = Marshal::StringToHGlobalUni(path);
//size_t pathLen = wcslen ((const wchar_t*)pathChars.ToPointer())+1;
//wchar_t * pPath = new wchar_t[pathLen];
//memcpy ((void*) pPath, (const wchar_t*)pathChars.ToPointer(), pathLen*sizeof(wchar_t));
//Marshal::FreeHGlobal(pathChars);
//_wpc = WavpackOpenFileInput (pPath, errorMessage, OPEN_WVC, 0);
_wpc = WavpackOpenFileInputEx (ioReader, "v", _IO_WVC != nullptr ? "c" : NULL, errorMessage, OPEN_WVC, 0); _wpc = WavpackOpenFileInputEx (ioReader, "v", _IO_WVC != nullptr ? "c" : NULL, errorMessage, OPEN_WVC, 0);
if (_wpc == NULL) { if (_wpc == NULL) {
throw gcnew Exception("Unable to initialize the decoder."); throw gcnew Exception("Unable to initialize the decoder.");
@@ -114,35 +109,35 @@ namespace WavPackDotNet {
delete ioReader; delete ioReader;
} }
property Int32 BitsPerSample { virtual property Int32 BitsPerSample {
Int32 get() { Int32 get() {
return _bitsPerSample; return _bitsPerSample;
} }
} }
property Int32 ChannelCount { virtual property Int32 ChannelCount {
Int32 get() { Int32 get() {
return _channelCount; return _channelCount;
} }
} }
property Int32 SampleRate { virtual property Int32 SampleRate {
Int32 get() { Int32 get() {
return _sampleRate; return _sampleRate;
} }
} }
property Int32 Length { virtual property UInt64 Length {
Int32 get() { UInt64 get() {
return _sampleCount; return _sampleCount;
} }
} }
property Int32 Position { virtual property UInt64 Position {
Int32 get() { UInt64 get() {
return _sampleOffset; return _sampleOffset;
} }
void set(Int32 offset) { void set(UInt64 offset) {
_sampleOffset = offset; _sampleOffset = offset;
if (!WavpackSeekSample(_wpc, offset)) { if (!WavpackSeekSample(_wpc, offset)) {
throw gcnew Exception("Unable to seek."); throw gcnew Exception("Unable to seek.");
@@ -150,19 +145,19 @@ namespace WavPackDotNet {
} }
} }
property Int32 Remaining { virtual property UInt64 Remaining {
Int32 get() { UInt64 get() {
return _sampleCount - _sampleOffset; return _sampleCount - _sampleOffset;
} }
} }
property String^ Path { virtual property String^ Path {
String^ get() { String^ get() {
return _path; return _path;
} }
} }
property NameValueCollection^ Tags { virtual property NameValueCollection^ Tags {
NameValueCollection^ get () { NameValueCollection^ get () {
if (!_tags) if (!_tags)
{ {
@@ -177,7 +172,7 @@ namespace WavPackDotNet {
} }
} }
void Close() virtual void Close()
{ {
_wpc = WavpackCloseFile(_wpc); _wpc = WavpackCloseFile(_wpc);
if (_IO != nullptr) if (_IO != nullptr)
@@ -192,16 +187,14 @@ namespace WavPackDotNet {
} }
} }
void Read(array<Int32, 2>^ sampleBuffer, Int32 sampleCount) { virtual UInt32 Read(array<Int32, 2>^ sampleBuffer, UInt32 sampleCount)
{
pin_ptr<Int32> pSampleBuffer = &sampleBuffer[0, 0]; pin_ptr<Int32> pSampleBuffer = &sampleBuffer[0, 0];
int samplesRead; int samplesRead = WavpackUnpackSamples(_wpc, pSampleBuffer, sampleCount);
samplesRead = WavpackUnpackSamples(_wpc, pSampleBuffer, sampleCount);
_sampleOffset += samplesRead; _sampleOffset += samplesRead;
if (samplesRead != sampleCount)
if (samplesRead != sampleCount) {
throw gcnew Exception("Decoder returned a different number of samples than requested."); throw gcnew Exception("Decoder returned a different number of samples than requested.");
} return sampleCount;
} }
private: private:
@@ -312,14 +305,17 @@ namespace WavPackDotNet {
} }
}; };
public ref class WavPackWriter { public ref class WavPackWriter : IAudioDest
{
public: public:
WavPackWriter(String^ path, Int32 bitsPerSample, Int32 channelCount, Int32 sampleRate) { WavPackWriter(String^ path, Int32 bitsPerSample, Int32 channelCount, Int32 sampleRate)
{
IntPtr pathChars; IntPtr pathChars;
if ((channelCount != 1) && (channelCount != 2)) { if (channelCount != 1 && channelCount != 2)
throw gcnew Exception("Only stereo and mono audio formats are allowed."); throw gcnew Exception("Only stereo and mono audio formats are allowed.");
} if (bitsPerSample != 16 && bitsPerSample != 24)
throw gcnew Exception("Bits per sample must be 16 or 24.");
_path = path; _path = path;
_tags = gcnew NameValueCollection(); _tags = gcnew NameValueCollection();
@@ -330,6 +326,7 @@ namespace WavPackDotNet {
_bitsPerSample = bitsPerSample; _bitsPerSample = bitsPerSample;
_channelCount = channelCount; _channelCount = channelCount;
_sampleRate = sampleRate; _sampleRate = sampleRate;
_blockAlign = _channelCount * ((_bitsPerSample + 7) / 8);
pathChars = Marshal::StringToHGlobalUni(path); pathChars = Marshal::StringToHGlobalUni(path);
_hFile = _wfopen((const wchar_t*)pathChars.ToPointer(), L"w+b"); _hFile = _wfopen((const wchar_t*)pathChars.ToPointer(), L"w+b");
@@ -339,7 +336,8 @@ namespace WavPackDotNet {
} }
} }
void Close() { virtual void Close()
{
if (_md5Sum) if (_md5Sum)
{ {
_md5hasher->TransformFinalBlock (gcnew array<unsigned char>(1), 0, 0); _md5hasher->TransformFinalBlock (gcnew array<unsigned char>(1), 0, 0);
@@ -365,21 +363,56 @@ namespace WavPackDotNet {
} }
} }
property Int32 FinalSampleCount { virtual property Int64 FinalSampleCount
Int32 get() { {
Int64 get()
{
return _finalSampleCount; return _finalSampleCount;
} }
void set(Int32 value) { void set(Int64 value)
if (value < 0) { {
if (value < 0)
throw gcnew Exception("Invalid final sample count."); throw gcnew Exception("Invalid final sample count.");
} if (_initialized)
if (_initialized) {
throw gcnew Exception("Final sample count cannot be changed after encoding begins."); throw gcnew Exception("Final sample count cannot be changed after encoding begins.");
}
_finalSampleCount = value; _finalSampleCount = value;
} }
} }
virtual void Write(array<Int32, 2>^ sampleBuffer, UInt32 sampleCount)
{
if (!_initialized)
Initialize();
if (MD5Sum)
{
if (_sampleBuffer == nullptr || _sampleBuffer.Length < sampleCount * _blockAlign)
_sampleBuffer = gcnew array<unsigned char>(sampleCount * _blockAlign);
AudioSamples::FLACSamplesToBytes(sampleBuffer, 0, _sampleBuffer, 0, sampleCount, _channelCount, _bitsPerSample);
UpdateHash(_sampleBuffer, (int) sampleCount * _blockAlign);
}
pin_ptr<Int32> pSampleBuffer = &sampleBuffer[0, 0];
if (!WavpackPackSamples(_wpc, (int32_t*)pSampleBuffer, sampleCount)) {
throw gcnew Exception("An error occurred while encoding.");
}
_samplesWritten += sampleCount;
}
virtual property String^ Path
{
String^ get() {
return _path;
}
}
virtual bool SetTags (NameValueCollection^ tags)
{
_tags = tags;
return true;
}
property Int32 CompressionMode { property Int32 CompressionMode {
Int32 get() { Int32 get() {
return _compressionMode; return _compressionMode;
@@ -422,38 +455,18 @@ namespace WavPackDotNet {
_md5hasher->TransformBlock (buff, 0, len, buff, 0); _md5hasher->TransformBlock (buff, 0, len, buff, 0);
} }
void Write(array<Int32, 2>^ sampleBuffer, Int32 sampleCount) {
if (!_initialized) Initialize();
pin_ptr<Int32> pSampleBuffer = &sampleBuffer[0, 0];
if (!WavpackPackSamples(_wpc, (int32_t*)pSampleBuffer, sampleCount)) {
throw gcnew Exception("An error occurred while encoding.");
}
_samplesWritten += sampleCount;
}
property String^ Path {
String^ get() {
return _path;
}
}
void SetTags (NameValueCollection^ tags) {
_tags = tags;
}
private: private:
FILE *_hFile; FILE *_hFile;
bool _initialized; bool _initialized;
WavpackContext *_wpc; WavpackContext *_wpc;
Int32 _finalSampleCount, _samplesWritten; Int32 _finalSampleCount, _samplesWritten;
Int32 _bitsPerSample, _channelCount, _sampleRate; Int32 _bitsPerSample, _channelCount, _sampleRate, _blockAlign;
Int32 _compressionMode, _extraMode; Int32 _compressionMode, _extraMode;
NameValueCollection^ _tags; NameValueCollection^ _tags;
String^ _path; String^ _path;
bool _md5Sum; bool _md5Sum;
MD5^ _md5hasher; MD5^ _md5hasher;
array<unsigned char>^ _sampleBuffer;
void Initialize() { void Initialize() {
WavpackConfig config; WavpackConfig config;

View File

@@ -92,81 +92,6 @@
Name="VCPostBuildEventTool" Name="VCPostBuildEventTool"
/> />
</Configuration> </Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)..\bin\$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(SolutionDir)..\obj\$(ProjectName)\$(PlatformName)\$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="1"
ManagedExtensions="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="../wavpack-4.5.0/include"
AdditionalUsingDirectories=""
PreprocessorDefinitions="WIN32;NDEBUG;_CRT_SECURE_NO_WARNINGS"
RuntimeLibrary="2"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="1"
AdditionalLibraryDirectories=""
GenerateDebugInformation="true"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration <Configuration
Name="Debug|x64" Name="Debug|x64"
OutputDirectory="$(SolutionDir)..\bin\$(PlatformName)\$(ConfigurationName)" OutputDirectory="$(SolutionDir)..\bin\$(PlatformName)\$(ConfigurationName)"
@@ -242,6 +167,81 @@
Name="VCPostBuildEventTool" Name="VCPostBuildEventTool"
/> />
</Configuration> </Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)..\bin\$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(SolutionDir)..\obj\$(ProjectName)\$(PlatformName)\$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="1"
ManagedExtensions="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="../wavpack-4.5.0/include"
AdditionalUsingDirectories=""
PreprocessorDefinitions="WIN32;NDEBUG;_CRT_SECURE_NO_WARNINGS"
RuntimeLibrary="2"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="1"
AdditionalLibraryDirectories=""
GenerateDebugInformation="true"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration <Configuration
Name="Release|x64" Name="Release|x64"
OutputDirectory="$(SolutionDir)..\bin\$(PlatformName)\$(ConfigurationName)" OutputDirectory="$(SolutionDir)..\bin\$(PlatformName)\$(ConfigurationName)"
@@ -336,6 +336,10 @@
ReferencedProjectIdentifier="{CA200BCB-DFC6-4153-9BD4-785BC768B26B}" ReferencedProjectIdentifier="{CA200BCB-DFC6-4153-9BD4-785BC768B26B}"
RelativePathToProject="..\APETagDotNet\APETagDotNet.csproj" RelativePathToProject="..\APETagDotNet\APETagDotNet.csproj"
/> />
<ProjectReference
ReferencedProjectIdentifier="{6458A13A-30EF-45A9-9D58-E5031B17BEE2}"
RelativePathToProject="..\AudioCodecsDotNet\AudioCodecsDotNet.csproj"
/>
</References> </References>
<Files> <Files>
<Filter <Filter

Binary file not shown.

Binary file not shown.

Binary file not shown.