diff --git a/CUETools.Codecs.TTA/AssemblyInfo.cpp b/CUETools.Codecs.TTA/AssemblyInfo.cpp new file mode 100644 index 0000000..a2bfbd7 --- /dev/null +++ b/CUETools.Codecs.TTA/AssemblyInfo.cpp @@ -0,0 +1,40 @@ +#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("CUEToolsCodecsTTA")]; +[assembly:AssemblyDescriptionAttribute("")]; +[assembly:AssemblyConfigurationAttribute("")]; +[assembly:AssemblyCompanyAttribute("Microsoft")]; +[assembly:AssemblyProductAttribute("CUEToolsCodecsTTA")]; +[assembly:AssemblyCopyrightAttribute("Copyright (c) Microsoft 2009")]; +[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("1.0.*")]; + +[assembly:ComVisible(false)]; + +[assembly:CLSCompliantAttribute(true)]; + +[assembly:SecurityPermission(SecurityAction::RequestMinimum, UnmanagedCode = true)]; diff --git a/CUETools.Codecs.TTA/CUETools.Codecs.TTA.cpp b/CUETools.Codecs.TTA/CUETools.Codecs.TTA.cpp new file mode 100644 index 0000000..8d8e10e --- /dev/null +++ b/CUETools.Codecs.TTA/CUETools.Codecs.TTA.cpp @@ -0,0 +1,232 @@ +// This is the main DLL file. + +#include "stdafx.h" + +#include "CUETools.Codecs.TTA.h" + +typedef void * HANDLE; + +#include "../TTALib-1.1/TTAReader.h" +#include "../TTALib-1.1/TTAError.h" + +namespace CUETools { +namespace Codecs { +namespace TTA { + + static const char *TTAErrorsStr[] = { + "no errors found", + "not compatible file format", + "file is corrupted", + "file(s) not found", + "problem creating directory", + "can't open file", + "can't write to output file", + "can't read from input file", + "insufficient memory available", + "operation canceled" + }; + + public ref class TTAReader : public IAudioSource + { + public: + TTAReader(String^ path, Stream^ IO) + { + _tags = gcnew NameValueCollection(); + _sampleOffset = 0; + _sampleBuffer = nullptr; + _path = path; + _bufferOffset = 0; + _bufferLength = 0; + + _IO = (IO != nullptr) ? IO : gcnew FileStream (path, FileMode::Open, FileAccess::Read, FileShare::Read); + + // skip ID3v2 + + + if (_IO->ReadByte() == 'I' && _IO->ReadByte() == 'D' && _IO->ReadByte() == '3') + { + _IO->ReadByte(); + _IO->ReadByte(); + int flags = _IO->ReadByte(); + int sz = _IO->ReadByte(); + if (sz & 0x80) + throw gcnew Exception("Invalid ID3 tag."); + int offset = sz; + offset = (offset << 7) | (_IO->ReadByte() & 0x7f); + offset = (offset << 7) | (_IO->ReadByte() & 0x7f); + offset = (offset << 7) | (_IO->ReadByte() & 0x7f); + if (flags & (1 << 4)) + offset += 10; + _IO->Position = 10 + offset; + } else + _IO->Position = 0; + + try + { + _ttaReader = new TTALib::TTAReader((HANDLE)((FileStream^) _IO)->Handle); + } catch (TTALib::TTAException ex) + { + throw gcnew Exception(String::Format("TTA decoder: {0}", gcnew String(TTAErrorsStr[ex.GetErrNo()]))); + } + if (WAVE_FORMAT_PCM != _ttaReader->ttahdr.AudioFormat) + throw gcnew Exception("floating point format not supported."); + _channelCount = _ttaReader->ttahdr.NumChannels; + _bitsPerSample = _ttaReader->ttahdr.BitsPerSample; + _sampleRate = _ttaReader->ttahdr.SampleRate; + _sampleCount = _ttaReader->ttahdr.DataLength; + } + + ~TTAReader () + { + Close (); + } + + virtual property Int32 BitsPerSample { + Int32 get() { + return _bitsPerSample; + } + } + + virtual property Int32 ChannelCount { + Int32 get() { + return _channelCount; + } + } + + virtual property Int32 SampleRate { + Int32 get() { + return _sampleRate; + } + } + + virtual property UInt64 Length { + UInt64 get() { + return _sampleCount; + } + } + + virtual property UInt64 Position { + UInt64 get() + { + return _sampleOffset - SamplesInBuffer; + } + void set(UInt64 offset) + { + _sampleOffset = offset; + _bufferOffset = 0; + _bufferLength = 0; + throw gcnew Exception("Unable to seek."); + } + } + + virtual property String^ Path { + String^ get() { + return _path; + } + } + + virtual property NameValueCollection^ Tags { + NameValueCollection^ get () { + return _tags; + } + void set (NameValueCollection ^tags) { + _tags = tags; + } + } + + virtual bool UpdateTags (bool preserveTime) + { + return false; + } + + virtual property UInt64 Remaining { + UInt64 get() { + return _sampleCount - _sampleOffset + SamplesInBuffer; + } + } + + virtual void Close() { + if (_ttaReader) + { + delete _ttaReader; + _ttaReader = nullptr; + } + if (_IO != nullptr) + { + _IO->Close (); + _IO = nullptr; + } + } + + virtual array^ Read(array^ buff) + { + return AudioSamples::Read(this, buff); + } + + void processBlock (long * buffer, int sampleCount) + { + if (_bufferLength > 0) + throw gcnew Exception("Received unrequested samples."); + + if ((_sampleBuffer == nullptr) || (_sampleBuffer->GetLength(0) < sampleCount)) + _sampleBuffer = gcnew array(sampleCount, _channelCount); + + interior_ptr pMyBuffer = &_sampleBuffer[0, 0]; + const long *pTTABuffer = buffer; + const long *pTTABufferEnd = pTTABuffer + sampleCount * _channelCount; + while (pTTABuffer < pTTABufferEnd) + *(pMyBuffer++) = *(pTTABuffer++); + _bufferLength = sampleCount; + } + + virtual UInt32 Read([Out] array^ buff, UInt32 sampleCount) + { + UInt32 buffOffset = 0; + UInt32 samplesNeeded = sampleCount; + + while (samplesNeeded != 0) + { + if (SamplesInBuffer == 0) + { + _bufferOffset = 0; + _bufferLength = 0; + do + { + long * buf; + int samplesInBuf = _ttaReader->GetBlock(&buf); + if (samplesInBuf == 0) + throw gcnew Exception("An error occurred while decoding."); + processBlock (buf, samplesInBuf); + } 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; + } + + private: + Int64 _sampleCount, _sampleOffset; + Int32 _bitsPerSample, _channelCount, _sampleRate; + array^ _sampleBuffer; + array^ _readBuffer; + NameValueCollection^ _tags; + String^ _path; + Stream^ _IO; + UInt32 _bufferOffset, _bufferLength; + TTALib::TTAReader * _ttaReader; + + property UInt32 SamplesInBuffer { + UInt32 get () + { + return (UInt32) (_bufferLength - _bufferOffset); + } + } + }; +} +} +} diff --git a/CUETools.Codecs.TTA/CUETools.Codecs.TTA.h b/CUETools.Codecs.TTA/CUETools.Codecs.TTA.h new file mode 100644 index 0000000..446a12a --- /dev/null +++ b/CUETools.Codecs.TTA/CUETools.Codecs.TTA.h @@ -0,0 +1,11 @@ +// CUETools.Codecs.TTA.h + +#pragma once + +using namespace System; +using namespace System::Text; +using namespace System::IO; +using namespace System::Collections::Generic; +using namespace System::Collections::Specialized; +using namespace System::Runtime::InteropServices; +using namespace CUETools::Codecs; diff --git a/CUETools.Codecs.TTA/CUETools.Codecs.TTA.vcproj b/CUETools.Codecs.TTA/CUETools.Codecs.TTA.vcproj new file mode 100644 index 0000000..1494f32 --- /dev/null +++ b/CUETools.Codecs.TTA/CUETools.Codecs.TTA.vcproj @@ -0,0 +1,426 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/CUETools.Codecs.TTA/ReadMe.txt b/CUETools.Codecs.TTA/ReadMe.txt new file mode 100644 index 0000000..5f3a035 --- /dev/null +++ b/CUETools.Codecs.TTA/ReadMe.txt @@ -0,0 +1,31 @@ +======================================================================== + DYNAMIC LINK LIBRARY : CUETools.Codecs.TTA Project Overview +======================================================================== + +AppWizard has created this CUETools.Codecs.TTA DLL for you. + +This file contains a summary of what you will find in each of the files that +make up your CUETools.Codecs.TTA application. + +CUETools.Codecs.TTA.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. + +CUETools.Codecs.TTA.cpp + This is the main DLL source file. + +CUETools.Codecs.TTA.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. + +///////////////////////////////////////////////////////////////////////////// diff --git a/CUETools.Codecs.TTA/Stdafx.cpp b/CUETools.Codecs.TTA/Stdafx.cpp new file mode 100644 index 0000000..44a182d --- /dev/null +++ b/CUETools.Codecs.TTA/Stdafx.cpp @@ -0,0 +1,5 @@ +// stdafx.cpp : source file that includes just the standard includes +// CUETools.Codecs.TTA.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" diff --git a/CUETools.Codecs.TTA/Stdafx.h b/CUETools.Codecs.TTA/Stdafx.h new file mode 100644 index 0000000..2e525d4 --- /dev/null +++ b/CUETools.Codecs.TTA/Stdafx.h @@ -0,0 +1,7 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, +// but are changed infrequently + +#pragma once + + diff --git a/CUETools.Codecs.TTA/app.ico b/CUETools.Codecs.TTA/app.ico new file mode 100644 index 0000000..3a5525f Binary files /dev/null and b/CUETools.Codecs.TTA/app.ico differ diff --git a/CUETools.Codecs.TTA/app.rc b/CUETools.Codecs.TTA/app.rc new file mode 100644 index 0000000..bb5fb6f --- /dev/null +++ b/CUETools.Codecs.TTA/app.rc @@ -0,0 +1,63 @@ +// 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 + diff --git a/CUETools.Codecs.TTA/resource.h b/CUETools.Codecs.TTA/resource.h new file mode 100644 index 0000000..1f2251c --- /dev/null +++ b/CUETools.Codecs.TTA/resource.h @@ -0,0 +1,3 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by app.rc