diff --git a/.gitignore b/.gitignore index 8152104..055c62c 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ bin/ lib/ Release/ Debug/ +*.vcxproj.filters *.vcxproj.user *.csproj.user *.sdf @@ -14,3 +15,5 @@ launchSettings.json /CUETools/TestResults /ThirdParty/*/libFLAC_dynamic.* /ThirdParty/*/MACLib.* +/ThirdParty/*/wavpackdll.* +/ThirdParty/*/libwavpack.* diff --git a/CUETools.Codecs.WavPack/AssemblyInfo.cpp b/CUETools.Codecs.WavPack/AssemblyInfo.cpp deleted file mode 100644 index 0fac783..0000000 --- a/CUETools.Codecs.WavPack/AssemblyInfo.cpp +++ /dev/null @@ -1,39 +0,0 @@ - -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("WavPackDotNet")]; -[assembly:AssemblyDescriptionAttribute("")]; -[assembly:AssemblyConfigurationAttribute("")]; -[assembly:AssemblyCompanyAttribute("")]; -[assembly:AssemblyProductAttribute("")]; -[assembly:AssemblyCopyrightAttribute("Copyright 2006-2007 Moitah")]; -[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)]; diff --git a/CUETools.Codecs.WavPack/CUETools.Codecs.WavPack.cpp b/CUETools.Codecs.WavPack/CUETools.Codecs.WavPack.cpp deleted file mode 100644 index d9ee625..0000000 --- a/CUETools.Codecs.WavPack/CUETools.Codecs.WavPack.cpp +++ /dev/null @@ -1,518 +0,0 @@ -// **************************************************************************** -// -// Copyright (c) 2006-2007 Moitah (moitah@yahoo.com) -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// * Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of the author nor the names of its contributors may be -// used to endorse or promote products derived from this software without -// specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// -// **************************************************************************** - -using namespace System; -using namespace System::ComponentModel; -using namespace System::Runtime::InteropServices; -using namespace System::Security::Cryptography; -using namespace System::IO; -using namespace CUETools::Codecs; - -#include -#include -#include "wavpack.h" -#include - -namespace CUETools { namespace Codecs { namespace WavPack { - int write_block(void *id, void *data, int32_t length); - - [UnmanagedFunctionPointer(CallingConvention::Cdecl)] - public delegate int32_t DecoderReadDelegate(void *id, void *data, int32_t bcount); - [UnmanagedFunctionPointer(CallingConvention::Cdecl)] - public delegate uint32_t DecoderTellDelegate(void *id); - [UnmanagedFunctionPointer(CallingConvention::Cdecl)] - public delegate int DecoderSeekDelegate(void *id, uint32_t pos); - [UnmanagedFunctionPointer(CallingConvention::Cdecl)] - public delegate int DecoderSeekRelativeDelegate(void *id, int32_t delta, int mode); - [UnmanagedFunctionPointer(CallingConvention::Cdecl)] - public delegate int DecoderPushBackDelegate(void *id, int c); - [UnmanagedFunctionPointer(CallingConvention::Cdecl)] - public delegate uint32_t DecoderLengthDelegate(void *id); - [UnmanagedFunctionPointer(CallingConvention::Cdecl)] - public delegate int DecoderCanSeekDelegate(void *id); - - [AudioDecoderClass("libwavpack", "wv", 1)] - public ref class WavPackReader : public IAudioSource - { - public: - WavPackReader(String^ path, Stream^ IO, Stream^ IO_WVC) - { - Initialize (path, IO, IO_WVC); - } - - WavPackReader(String^ path, Stream^ IO) - { - Initialize (path, IO, nullptr); - } - - void Initialize(String^ path, Stream^ IO, Stream^ IO_WVC) - { - char errorMessage[256]; - - _readDel = gcnew DecoderReadDelegate (this, &WavPackReader::ReadCallback); - _tellDel = gcnew DecoderTellDelegate (this, &WavPackReader::TellCallback); - _seekDel = gcnew DecoderSeekDelegate (this, &WavPackReader::SeekCallback); - _seekRelDel = gcnew DecoderSeekRelativeDelegate (this, &WavPackReader::SeekRelCallback); - _pushBackDel = gcnew DecoderPushBackDelegate (this, &WavPackReader::PushBackCallback); - _lengthDel = gcnew DecoderLengthDelegate (this, &WavPackReader::LengthCallback); - _canSeekDel = gcnew DecoderCanSeekDelegate (this, &WavPackReader::CanSeekCallback); - - ioReader = new WavpackStreamReader; - ioReader->read_bytes = (int32_t (*)(void *, void *, int32_t)) Marshal::GetFunctionPointerForDelegate(_readDel).ToPointer(); - ioReader->get_pos = (uint32_t (*)(void *)) Marshal::GetFunctionPointerForDelegate(_tellDel).ToPointer(); - ioReader->set_pos_abs = (int (*)(void *, uint32_t)) Marshal::GetFunctionPointerForDelegate(_seekDel).ToPointer(); - ioReader->set_pos_rel = (int (*)(void *, int32_t, int)) Marshal::GetFunctionPointerForDelegate(_seekRelDel).ToPointer(); - ioReader->push_back_byte = (int (*)(void *, int)) Marshal::GetFunctionPointerForDelegate(_pushBackDel).ToPointer(); - ioReader->get_length = (uint32_t (*)(void *)) Marshal::GetFunctionPointerForDelegate(_lengthDel).ToPointer(); - ioReader->can_seek = (int (*)(void *)) Marshal::GetFunctionPointerForDelegate(_canSeekDel).ToPointer(); - ioReader->write_bytes = NULL; - - _IO_ungetc = _IO_WVC_ungetc = -1; - - _path = path; - - _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; - - _wpc = WavpackOpenFileInputEx (ioReader, "v", _IO_WVC != nullptr ? "c" : NULL, errorMessage, OPEN_WVC, 0); - if (_wpc == NULL) { - throw gcnew Exception("Unable to initialize the decoder."); - } - - pcm = gcnew AudioPCMConfig( - WavpackGetBitsPerSample(_wpc), - WavpackGetNumChannels(_wpc), - (int)WavpackGetSampleRate(_wpc), - (AudioPCMConfig::SpeakerConfig)WavpackGetChannelMask(_wpc)); - _sampleCount = WavpackGetNumSamples(_wpc); - _sampleOffset = 0; - } - - ~WavPackReader() - { - delete ioReader; - } - - virtual property AudioPCMConfig^ PCM { - AudioPCMConfig^ get() { - return pcm; - } - } - - virtual property Int64 Length { - Int64 get() { - return _sampleCount; - } - } - - virtual property Int64 Position { - Int64 get() { - return _sampleOffset; - } - void set(Int64 offset) { - _sampleOffset = offset; - if (!WavpackSeekSample(_wpc, offset)) { - throw gcnew Exception("Unable to seek."); - } - } - } - - virtual property Int64 Remaining { - Int64 get() { - return _sampleCount - _sampleOffset; - } - } - - virtual property String^ Path { - String^ get() { - return _path; - } - } - - virtual void Close() - { - if (_wpc != NULL) - _wpc = WavpackCloseFile(_wpc); - if (_IO != nullptr) - { - _IO->Close (); - _IO = nullptr; - } - if (_IO_WVC != nullptr) - { - _IO_WVC->Close (); - _IO_WVC = nullptr; - } - } - - virtual int Read(AudioBuffer^ sampleBuffer, int maxLength) - { - sampleBuffer->Prepare(this, maxLength); - - pin_ptr pSampleBuffer = &sampleBuffer->Samples[0, 0]; - int samplesRead = WavpackUnpackSamples(_wpc, pSampleBuffer, sampleBuffer->Length); - _sampleOffset += samplesRead; - if (samplesRead != sampleBuffer->Length) - throw gcnew Exception("Decoder returned a different number of samples than requested."); - return sampleBuffer->Length; - } - - virtual property AudioDecoderSettings^ Settings { - AudioDecoderSettings^ get(void) { - return nullptr; - } - } - - private: - WavpackContext *_wpc; - Int32 _sampleCount, _sampleOffset; - AudioPCMConfig^ pcm; - String^ _path; - Stream^ _IO; - Stream^ _IO_WVC; - DecoderReadDelegate^ _readDel; - DecoderTellDelegate^ _tellDel; - DecoderSeekDelegate^ _seekDel; - DecoderSeekRelativeDelegate^ _seekRelDel; - DecoderPushBackDelegate^ _pushBackDel; - DecoderLengthDelegate^ _lengthDel; - DecoderCanSeekDelegate^ _canSeekDel; - array^ _readBuffer; - int _IO_ungetc, _IO_WVC_ungetc; - WavpackStreamReader* ioReader; - - int32_t ReadCallback (void *id, void *data, int32_t bcount) - { - Stream^ IO = (*(char*)id=='c') ? _IO_WVC : _IO; - int IO_ungetc = (*(char*)id=='c') ? _IO_WVC_ungetc : _IO_ungetc; - int unget_len = 0; - - if (IO_ungetc != -1) - { - *(unsigned char*)data = (unsigned char) IO_ungetc; - if (IO == _IO) - _IO_ungetc = -1; - else - _IO_WVC_ungetc = -1; - bcount --; - if (!bcount) - return 1; - data = 1 + (unsigned char*)data; - unget_len = 1; - } - - if (_readBuffer == nullptr || _readBuffer->Length < bcount) - _readBuffer = gcnew array(bcount < 0x4000 ? 0x4000 : bcount); - int len = IO->Read (_readBuffer, 0, bcount); - if (len) Marshal::Copy (_readBuffer, 0, (IntPtr)data, len); - return len + unget_len; - } - - uint32_t TellCallback(void *id) - { - Stream^ IO = (*(char*)id=='c') ? _IO_WVC : _IO; - return IO->Position; - } - - int SeekCallback (void *id, uint32_t pos) - { - Stream^ IO = (*(char*)id=='c') ? _IO_WVC : _IO; - IO->Position = pos; - return 0; - } - - int SeekRelCallback (void *id, int32_t delta, int mode) - { - Stream^ IO = (*(char*)id=='c') ? _IO_WVC : _IO; - switch (mode) - { - case SEEK_SET: - IO->Seek (delta, System::IO::SeekOrigin::Begin); - break; - case SEEK_END: - IO->Seek (delta, System::IO::SeekOrigin::End); - break; - case SEEK_CUR: - IO->Seek (delta, System::IO::SeekOrigin::Current); - break; - default: - return -1; - } - return 0; - } - - int PushBackCallback (void *id, int c) - { - Stream^ IO = (*(char*)id=='c') ? _IO_WVC : _IO; - if (IO == _IO) - { - if (_IO_ungetc != -1) - throw gcnew Exception("Double PushBackCallback unsupported."); - _IO_ungetc = c; - } else - { - if (_IO_WVC_ungetc != -1) - throw gcnew Exception("Double PushBackCallback unsupported."); - _IO_WVC_ungetc = c; - } - - return 0; - } - - uint32_t LengthCallback (void *id) - { - Stream^ IO = (*(char*)id=='c') ? _IO_WVC : _IO; - return IO->Length; - } - - int CanSeekCallback(void *id) - { - Stream^ IO = (*(char*)id=='c') ? _IO_WVC : _IO; - return IO->CanSeek; - } - }; - - public ref class WavPackWriterSettings : AudioEncoderSettings - { - public: - WavPackWriterSettings() - : AudioEncoderSettings("fast normal high high+", "normal") - { - _md5Sum = true; - _extraMode = 0; - } - - [DefaultValue(0)] - [DisplayName("ExtraMode")] - property Int32 ExtraMode { - Int32 get() { - return _extraMode; - } - void set(Int32 value) { - if ((value < 0) || (value > 6)) { - throw gcnew Exception("Invalid extra mode."); - } - _extraMode = value; - } - } - - [DefaultValue(true)] - [DisplayName("MD5")] - [Description("Calculate MD5 hash for audio stream")] - property bool MD5Sum { - bool get() { - return _md5Sum; - } - void set(bool value) { - _md5Sum = value; - } - } - - private: - bool _md5Sum; - Int32 _extraMode; - }; - - [AudioEncoderClass("libwavpack", "wv", true, 1, WavPackWriterSettings::typeid)] - public ref class WavPackWriter : IAudioDest - { - public: - WavPackWriter(String^ path, WavPackWriterSettings^ settings) - { - _settings = settings; - - if (_settings->PCM->BitsPerSample < 16 || _settings->PCM->BitsPerSample > 24) - throw gcnew Exception("Bits per sample must be 16..24."); - - _path = path; - - IntPtr pathChars = Marshal::StringToHGlobalUni(path); - _hFile = _wfopen((const wchar_t*)pathChars.ToPointer(), L"w+b"); - Marshal::FreeHGlobal(pathChars); - if (!_hFile) { - throw gcnew Exception("Unable to open file."); - } - } - - virtual void Close() - { - if (_settings->MD5Sum) - { - _md5hasher->TransformFinalBlock (gcnew array(1), 0, 0); - pin_ptr md5_digest = &_md5hasher->Hash[0]; - WavpackStoreMD5Sum (_wpc, md5_digest); - } - - WavpackFlushSamples(_wpc); - _wpc = WavpackCloseFile(_wpc); - fclose(_hFile); - - if ((_finalSampleCount != 0) && (_samplesWritten != _finalSampleCount)) - throw gcnew Exception("Samples written differs from the expected sample count."); - } - - virtual void Delete() - { - try { Close (); } catch (Exception^) {} - 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^ sampleBuffer) - { - if (!_initialized) - Initialize(); - - sampleBuffer->Prepare(this); - - if (_settings->MD5Sum) - UpdateHash(sampleBuffer->Bytes, sampleBuffer->ByteLength); - - if ((_settings->PCM->BitsPerSample & 7) != 0) - { - if (_shiftedSampleBuffer == nullptr || _shiftedSampleBuffer.GetLength(0) < sampleBuffer->Length) - _shiftedSampleBuffer = gcnew array(sampleBuffer->Length, _settings->PCM->ChannelCount); - int shift = 8 - (_settings->PCM->BitsPerSample & 7); - int ch = _settings->PCM->ChannelCount; - for (int i = 0; i < sampleBuffer->Length; i++) - for (int c = 0; c < ch; c++) - _shiftedSampleBuffer[i,c] = sampleBuffer->Samples[i,c] << shift; - pin_ptr pSampleBuffer = &_shiftedSampleBuffer[0, 0]; - if (!WavpackPackSamples(_wpc, (int32_t*)pSampleBuffer, sampleBuffer->Length)) - throw gcnew Exception("An error occurred while encoding."); - } else - { - pin_ptr pSampleBuffer = &sampleBuffer->Samples[0, 0]; - if (!WavpackPackSamples(_wpc, (int32_t*)pSampleBuffer, sampleBuffer->Length)) - throw gcnew Exception("An error occurred while encoding."); - } - - _samplesWritten += sampleBuffer->Length; - } - - virtual property String^ Path - { - String^ get() { - return _path; - } - } - - virtual property AudioEncoderSettings^ Settings - { - AudioEncoderSettings^ get() - { - return _settings; - } - } - - void UpdateHash(array^ buff, Int32 len) - { - if (!_initialized) Initialize(); - - if (!_settings->MD5Sum || !_md5hasher) - throw gcnew Exception("MD5 not enabled."); - _md5hasher->TransformBlock (buff, 0, len, buff, 0); - } - - private: - FILE *_hFile; - bool _initialized; - WavpackContext *_wpc; - Int32 _finalSampleCount, _samplesWritten; - String^ _path; - MD5^ _md5hasher; - array^ _shiftedSampleBuffer; - WavPackWriterSettings^ _settings; - - void Initialize() { - WavpackConfig config; - - _wpc = WavpackOpenFileOutput(write_block, _hFile, NULL); - if (!_wpc) { - throw gcnew Exception("Unable to create the encoder."); - } - - memset(&config, 0, sizeof(WavpackConfig)); - config.bits_per_sample = _settings->PCM->BitsPerSample; - config.bytes_per_sample = (_settings->PCM->BitsPerSample + 7) / 8; - config.num_channels = _settings->PCM->ChannelCount; - config.channel_mask = (int32_t)_settings->PCM->ChannelMask; - config.sample_rate = _settings->PCM->SampleRate; - Int32 _compressionMode = _settings->EncoderModeIndex; - if (_compressionMode == 0) config.flags |= CONFIG_FAST_FLAG; - if (_compressionMode == 2) config.flags |= CONFIG_HIGH_FLAG; - if (_compressionMode == 3) config.flags |= CONFIG_HIGH_FLAG | CONFIG_VERY_HIGH_FLAG; - if (_settings->ExtraMode != 0) - { - config.flags |= CONFIG_EXTRA_MODE; - config.xmode = _settings->ExtraMode; - } - if (_settings->MD5Sum) - { - _md5hasher = gcnew MD5CryptoServiceProvider (); - config.flags |= CONFIG_MD5_CHECKSUM; - } - config.block_samples = (int)_settings->BlockSize; - if (_settings->BlockSize > 0 && _settings->BlockSize < 2048) - config.flags |= CONFIG_MERGE_BLOCKS; - - if (!WavpackSetConfiguration(_wpc, &config, (_finalSampleCount == 0) ? -1 : _finalSampleCount)) { - throw gcnew Exception("Invalid configuration setting."); - } - - if (!WavpackPackInit(_wpc)) { - throw gcnew Exception("Unable to initialize the encoder."); - } - - _initialized = true; - } - }; - -#pragma unmanaged - int write_block(void *id, void *data, int32_t length) { - return (fwrite(data, 1, length, (FILE*)id) == length); - } -}}} diff --git a/CUETools.Codecs.WavPack/CUETools.Codecs.WavPack.vcxproj b/CUETools.Codecs.WavPack/CUETools.Codecs.WavPack.vcxproj deleted file mode 100644 index c4a50a0..0000000 --- a/CUETools.Codecs.WavPack/CUETools.Codecs.WavPack.vcxproj +++ /dev/null @@ -1,229 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {CC2E74B6-534A-43D8-9F16-AC03FE955000} - CUETools.Codecs.WavPack - ManagedCProj - 10.0.16299.0 - v4.0 - - - - DynamicLibrary - Unicode - true - true - v141 - - - DynamicLibrary - Unicode - true - v141 - - - DynamicLibrary - Unicode - true - true - v141 - - - DynamicLibrary - Unicode - true - v141 - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.40219.1 - $(SolutionDir)..\bin\$(Configuration)\plugins\$(Platform)\net40\ - $(SolutionDir)..\obj\$(ProjectName)\$(Platform)\$(Configuration)\ - true - $(SolutionDir)..\bin\$(Configuration)\plugins\$(Platform)\net40\ - $(SolutionDir)..\obj\$(ProjectName)\$(Platform)\$(Configuration)\ - true - $(SolutionDir)..\bin\$(Configuration)\plugins\$(Platform)\net40\ - $(SolutionDir)..\obj\$(ProjectName)\$(Platform)\$(Configuration)\ - false - $(SolutionDir)..\bin\$(Configuration)\plugins\$(Platform)\net40\ - $(SolutionDir)..\obj\$(ProjectName)\$(Platform)\$(Configuration)\ - false - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - - - - Disabled - ../wavpack-4.5.0/include;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreadedDebugDLL - - - Level3 - ProgramDatabase - - - true - true - false - - - MachineX86 - - - - - X64 - - - Disabled - ../wavpack-4.5.0/include;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreadedDebugDLL - - - Level3 - ProgramDatabase - - - true - true - false - - - MachineX64 - - - - - ../wavpack-4.5.0/include;%(AdditionalIncludeDirectories) - %(AdditionalUsingDirectories) - WIN32;NDEBUG;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreadedDLL - - - Level3 - ProgramDatabase - - - %(AdditionalLibraryDirectories) - true - false - - - MachineX86 - - - - - X64 - - - ../wavpack-4.5.0/include;%(AdditionalIncludeDirectories) - %(AdditionalUsingDirectories) - WIN32;NDEBUG;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreadedDLL - - - Level3 - ProgramDatabase - - - %(AdditionalLibraryDirectories) - true - false - - - MachineX64 - - - - - true - true - - - true - true - - - true - true - - - - - - - - - - - - - - - - - - - {6458a13a-30ef-45a9-9d58-e5031b17bee2} - false - true - false - true - false - - - {5cccb9cf-0384-458f-ba08-72b73866840f} - false - - - - - - \ No newline at end of file diff --git a/CUETools.Codecs.WavPack/app.ico b/CUETools.Codecs.WavPack/app.ico deleted file mode 100644 index 3a5525f..0000000 Binary files a/CUETools.Codecs.WavPack/app.ico and /dev/null differ diff --git a/CUETools.Codecs.WavPack/app.rc b/CUETools.Codecs.WavPack/app.rc deleted file mode 100644 index 8c1d640..0000000 --- a/CUETools.Codecs.WavPack/app.rc +++ /dev/null @@ -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 9, 1 -#pragma code_page(1252) -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.WavPack/resource.h b/CUETools.Codecs.WavPack/resource.h deleted file mode 100644 index 1f2251c..0000000 --- a/CUETools.Codecs.WavPack/resource.h +++ /dev/null @@ -1,3 +0,0 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Visual C++ generated include file. -// Used by app.rc diff --git a/CUETools.Codecs.libwavpack/CUETools.Codecs.libwavpack.csproj b/CUETools.Codecs.libwavpack/CUETools.Codecs.libwavpack.csproj new file mode 100644 index 0000000..3924c45 --- /dev/null +++ b/CUETools.Codecs.libwavpack/CUETools.Codecs.libwavpack.csproj @@ -0,0 +1,29 @@ + + + + net40;net20;netstandard2.0 + 2.1.7.0 + CUETools.Codecs.libwavpack + CUETools.Codecs.libwavpack + CUETools + A library for encoding wavpack using official encoder. + Copyright (c) 2008-2018 Grigory Chudov + Grigory Chudov + true + ..\bin\$(Configuration)\plugins + https://github.com/gchudov/cuetools.net + git + + + + + + False + + + + + + + + diff --git a/CUETools.Codecs.libwavpack/Reader.cs b/CUETools.Codecs.libwavpack/Reader.cs new file mode 100644 index 0000000..982daf0 --- /dev/null +++ b/CUETools.Codecs.libwavpack/Reader.cs @@ -0,0 +1,213 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.IO; +using System.Runtime.InteropServices; +using System.Text; +using CUETools.Codecs; + +namespace CUETools.Codecs.libwavpack +{ + [AudioDecoderClass("libwavpack", "wv", 1)] + public unsafe class Reader : IAudioSource + { + private readonly void* IO_ID_WV = ((IntPtr)1).ToPointer(); + private readonly void* IO_ID_WVC = ((IntPtr)2).ToPointer(); + public Reader(string path, Stream IO, Stream IO_WVC) + { + m_read_bytes = ReadCallback; + m_get_pos = TellCallback; + m_set_pos_abs = SeekCallback; + m_set_pos_rel = SeekRelativeCallback; + m_push_back_byte = PushBackCallback; + m_get_length = LengthCallback; + m_can_seek = CanSeekCallback; + + m_ioReader = (WavpackStreamReader64*)Marshal.AllocHGlobal(sizeof(WavpackStreamReader64)).ToPointer(); + m_ioReader->read_bytes = Marshal.GetFunctionPointerForDelegate(m_read_bytes); + m_ioReader->write_bytes = IntPtr.Zero; + m_ioReader->get_pos = Marshal.GetFunctionPointerForDelegate(m_get_pos); + m_ioReader->set_pos_abs = Marshal.GetFunctionPointerForDelegate(m_set_pos_abs); + m_ioReader->set_pos_rel = Marshal.GetFunctionPointerForDelegate(m_set_pos_rel); + m_ioReader->push_back_byte = Marshal.GetFunctionPointerForDelegate(m_push_back_byte); + m_ioReader->get_length = Marshal.GetFunctionPointerForDelegate(m_get_length); + m_ioReader->can_seek = Marshal.GetFunctionPointerForDelegate(m_can_seek); + m_ioReader->truncate_here = IntPtr.Zero; + m_ioReader->close = IntPtr.Zero; + + _IO_ungetc = _IO_WVC_ungetc = -1; + + _path = path; + + _IO = (IO != null) ? IO : new FileStream (path, FileMode.Open, FileAccess.Read, FileShare.Read); + _IO_WVC = (IO != null) ? IO_WVC : File.Exists (path+"c") ? new FileStream (path+"c", FileMode.Open, FileAccess.Read, FileShare.Read) : null; + + string errorMessage; + + _wpc = wavpackdll.WavpackOpenFileInputEx64(m_ioReader, IO_ID_WV, IO_ID_WVC, out errorMessage, OpenFlags.OPEN_WVC, 0); + if (_wpc == null) { + throw new Exception("Unable to initialize the decoder: " + errorMessage); + } + + pcm = new AudioPCMConfig( + wavpackdll.WavpackGetBitsPerSample(_wpc), + wavpackdll.WavpackGetNumChannels(_wpc), + (int)wavpackdll.WavpackGetSampleRate(_wpc), + (AudioPCMConfig.SpeakerConfig)wavpackdll.WavpackGetChannelMask(_wpc)); + _sampleCount = wavpackdll.WavpackGetNumSamples64(_wpc); + _sampleOffset = 0; + } + + public Reader(string path, Stream IO) + : this(path, IO, null) + {} + + public AudioDecoderSettings Settings => null; + + public AudioPCMConfig PCM => pcm; + + public string Path => _path; + + public long Length => _sampleCount; + + public long Position + { + get => _sampleOffset; + + set + { + _sampleOffset = value; + if (0 == wavpackdll.WavpackSeekSample64(_wpc, value)) + throw new Exception("unable to seek: " + wavpackdll.WavpackGetErrorMessage(_wpc)); + } + } + + public long Remaining => _sampleCount - _sampleOffset; + + public void Close() + { + if (_wpc != null) + _wpc = wavpackdll.WavpackCloseFile(_wpc); + if (_IO != null) + { + _IO.Close (); + _IO = null; + } + if (_IO_WVC != null) + { + _IO_WVC.Close (); + _IO_WVC = null; + } + Marshal.FreeHGlobal((IntPtr)m_ioReader); + m_ioReader = null; + } + + public int Read(AudioBuffer buff, int maxLength) + { + buff.Prepare(this, maxLength); + fixed (int*pSampleBuffer = &buff.Samples[0,0]) + { + uint samplesRead = wavpackdll.WavpackUnpackSamples(_wpc, pSampleBuffer, (uint)buff.Length); + _sampleOffset += samplesRead; + if (samplesRead != buff.Length) + throw new Exception("Decoder returned a different number of samples than requested."); + } + return buff.Length; + } + + private int ReadCallback(void* id, void* data, int bcount) + { + Stream IO = (id == IO_ID_WVC) ? _IO_WVC : _IO; + int IO_ungetc = (id == IO_ID_WVC) ? _IO_WVC_ungetc : _IO_ungetc; + int unget_len = 0; + + if (IO_ungetc != -1) + { + *(byte*)data = (byte) IO_ungetc; + if (IO == _IO) + _IO_ungetc = -1; + else + _IO_WVC_ungetc = -1; + bcount--; + if (bcount <= 0) + return 1; + data = 1 + (byte*)data; + unget_len = 1; + } + + if (_readBuffer == null || _readBuffer.Length < bcount) + _readBuffer = new byte[Math.Max(bcount, 0x4000)]; + int len = IO.Read(_readBuffer, 0, bcount); + if (len > 0) Marshal.Copy(_readBuffer, 0, (IntPtr)data, len); + return len + unget_len; + } + + long TellCallback(void* id) + { + Stream IO = (id == IO_ID_WVC) ? _IO_WVC : _IO; + return IO.Position; + } + + int SeekCallback(void* id, long pos) + { + Stream IO = (id == IO_ID_WVC) ? _IO_WVC : _IO; + IO.Position = pos; + return 0; + } + + int SeekRelativeCallback(void* id, long delta, int mode) + { + Stream IO = (id == IO_ID_WVC) ? _IO_WVC : _IO; + IO.Seek(delta, (SeekOrigin)(mode)); + return 0; + } + + int PushBackCallback(void* id, int c) + { + Stream IO = (id == IO_ID_WVC) ? _IO_WVC : _IO; + if (IO == _IO) + { + if (_IO_ungetc != -1) + throw new Exception("Double PushBackCallback unsupported."); + _IO_ungetc = c; + } + else + { + if (_IO_WVC_ungetc != -1) + throw new Exception("Double PushBackCallback unsupported."); + _IO_WVC_ungetc = c; + } + + return 0; + } + + long LengthCallback(void* id) + { + Stream IO = (id == IO_ID_WVC) ? _IO_WVC : _IO; + return IO.Length; + } + + int CanSeekCallback(void* id) + { + Stream IO = (id == IO_ID_WVC) ? _IO_WVC : _IO; + return IO.CanSeek ? 1 : 0; + } + + WavpackContext* _wpc; + long _sampleCount, _sampleOffset; + Stream _IO; + Stream _IO_WVC; + string _path; + int _IO_ungetc, _IO_WVC_ungetc; + AudioPCMConfig pcm; + WavpackStreamReader64* m_ioReader; + DecoderReadDelegate m_read_bytes; + DecoderTellDelegate64 m_get_pos; + DecoderSeekDelegate64 m_set_pos_abs; + DecoderSeekRelativeDelegate64 m_set_pos_rel; + DecoderPushBackDelegate m_push_back_byte; + DecoderLengthDelegate64 m_get_length; + DecoderCanSeekDelegate m_can_seek; + byte[] _readBuffer; + } +} diff --git a/CUETools.Codecs.libwavpack/Writer.cs b/CUETools.Codecs.libwavpack/Writer.cs new file mode 100644 index 0000000..6749844 --- /dev/null +++ b/CUETools.Codecs.libwavpack/Writer.cs @@ -0,0 +1,221 @@ +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; + +namespace CUETools.Codecs.libwavpack +{ + public class WriterSettings : AudioEncoderSettings + { + public WriterSettings() + : base("fast normal high high+", "normal") + { + } + + [DefaultValue(0)] + [DisplayName("ExtraMode")] + public int ExtraMode { + get => m_extraMode; + set { + if ((value < 0) || (value > 6)) { + throw new Exception("Invalid extra mode."); + } + m_extraMode = value; + } + } + + [DefaultValue(true)] + [DisplayName("MD5")] + [Description("Calculate MD5 hash for audio stream")] + public bool MD5Sum { get; set; } + + [DisplayName("Version")] + [Description("Library version")] + public string Version => Marshal.PtrToStringAnsi(wavpackdll.WavpackGetLibraryVersionString()); + + private int m_extraMode; + }; + + [AudioEncoderClass("libwavpack", "wv", true, 1, typeof(WriterSettings))] + public unsafe class Writer : IAudioDest + { + public Writer(string path, Stream output, WriterSettings settings) + { + m_path = path; + m_stream = output; + m_settings = settings; + m_streamGiven = output != null; + m_initialized = false; + m_finalSampleCount = 0; + m_samplesWritten = 0; + m_blockOutput = BlockOutputCallback; + if (m_settings.PCM.BitsPerSample < 16 || m_settings.PCM.BitsPerSample > 24) + throw new Exception("bits per sample must be 16..24"); + } + + public Writer(string path, WriterSettings settings) + : this(path, null, settings) + { + } + + public AudioEncoderSettings 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() + { + if (m_initialized) + { + if (m_settings.MD5Sum) + { + _md5hasher.TransformFinalBlock (new byte[1], 0, 0); + fixed (byte* md5_digest = &_md5hasher.Hash[0]) + wavpackdll.WavpackStoreMD5Sum (_wpc, md5_digest); + } + wavpackdll.WavpackFlushSamples(_wpc); + _wpc = wavpackdll.WavpackCloseFile(_wpc); + m_initialized = false; + } + if (m_stream != null) + { + m_stream.Close(); + m_stream = null; + } + if ((m_finalSampleCount != 0) && (m_samplesWritten != m_finalSampleCount)) + throw new Exception("samples written differs from the expected sample count"); + } + + public void Delete() + { + try + { + if (m_initialized) + { + _wpc = wavpackdll.WavpackCloseFile(_wpc); + m_initialized = false; + } + if (m_stream != null) + { + m_stream.Close(); + m_stream = null; + } + } + catch (Exception) + { + } + if (m_path != "") + File.Delete(m_path); + } + + private void UpdateHash(byte[] buff, int len) + { + if (!m_settings.MD5Sum) throw new Exception("MD5 not enabled."); + if (!m_initialized) Initialize(); + _md5hasher.TransformBlock (buff, 0, len, buff, 0); + } + + public void Write(AudioBuffer sampleBuffer) + { + if (!m_initialized) Initialize(); + + sampleBuffer.Prepare(this); + + if (m_settings.MD5Sum) + UpdateHash(sampleBuffer.Bytes, sampleBuffer.ByteLength); + + int[,] samples = sampleBuffer.Samples; + if ((m_settings.PCM.BitsPerSample & 7) != 0) + { + if (_shiftedSampleBuffer == null || _shiftedSampleBuffer.GetLength(0) < sampleBuffer.Length) + _shiftedSampleBuffer = new int[sampleBuffer.Length, m_settings.PCM.ChannelCount]; + int shift = 8 - (m_settings.PCM.BitsPerSample & 7); + int ch = m_settings.PCM.ChannelCount; + for (int i = 0; i < sampleBuffer.Length; i++) + for (int c = 0; c < ch; c++) + _shiftedSampleBuffer[i, c] = sampleBuffer.Samples[i, c] << shift; + samples = _shiftedSampleBuffer; + } + + fixed (int* pSampleBuffer = &samples[0, 0]) + if (0 == wavpackdll.WavpackPackSamples(_wpc, pSampleBuffer, (uint)sampleBuffer.Length)) + throw new Exception("An error occurred while encoding: " + wavpackdll.WavpackGetErrorMessage(_wpc)); + + m_samplesWritten += sampleBuffer.Length; + } + + private int BlockOutputCallback(void* id, byte[] data, int bcount) + { + m_stream.Write(data, 0, bcount); + return 1; + } + + void Initialize() + { + if (m_stream == null) + m_stream = new FileStream(m_path, FileMode.Create, FileAccess.Write, FileShare.Read, 0x10000); + + WavpackConfig config = new WavpackConfig(); + config.bits_per_sample = m_settings.PCM.BitsPerSample; + config.bytes_per_sample = (m_settings.PCM.BitsPerSample + 7) / 8; + config.num_channels = m_settings.PCM.ChannelCount; + config.channel_mask = (int)m_settings.PCM.ChannelMask; + config.sample_rate = m_settings.PCM.SampleRate; + config.flags = ConfigFlags.CONFIG_COMPATIBLE_WRITE; + Int32 _compressionMode = m_settings.EncoderModeIndex; + if (_compressionMode == 0) config.flags |= ConfigFlags.CONFIG_FAST_FLAG; + if (_compressionMode == 2) config.flags |= ConfigFlags.CONFIG_HIGH_FLAG; + if (_compressionMode == 3) config.flags |= ConfigFlags.CONFIG_HIGH_FLAG | ConfigFlags.CONFIG_VERY_HIGH_FLAG; + if (m_settings.ExtraMode != 0) + { + config.flags |= ConfigFlags.CONFIG_EXTRA_MODE; + config.xmode = m_settings.ExtraMode; + } + if (m_settings.MD5Sum) + { + _md5hasher = new MD5CryptoServiceProvider (); + config.flags |= ConfigFlags.CONFIG_MD5_CHECKSUM; + } + config.block_samples = (int)m_settings.BlockSize; + if (m_settings.BlockSize > 0 && m_settings.BlockSize < 2048) + config.flags |= ConfigFlags.CONFIG_MERGE_BLOCKS; + + _wpc = wavpackdll.WavpackOpenFileOutput(m_blockOutput, null, null); + if (_wpc == null) + throw new Exception("Unable to create the encoder."); + if (0 == wavpackdll.WavpackSetConfiguration64(_wpc, &config, (m_finalSampleCount == 0) ? -1 : m_finalSampleCount, null)) + throw new Exception("Invalid configuration setting:" + wavpackdll.WavpackGetErrorMessage(_wpc)); + if (0 == wavpackdll.WavpackPackInit(_wpc)) + throw new Exception("Unable to initialize the encoder: " + wavpackdll.WavpackGetErrorMessage(_wpc)); + + m_initialized = true; + } + + int[,] _shiftedSampleBuffer; + WavpackContext* _wpc; + WriterSettings m_settings; + Stream m_stream; + MD5 _md5hasher; + bool m_streamGiven; + bool m_initialized; + string m_path; + Int64 m_finalSampleCount, m_samplesWritten; + EncoderBlockOutput m_blockOutput; + } +} diff --git a/CUETools.Codecs.libwavpack/libwavpack.cs b/CUETools.Codecs.libwavpack/libwavpack.cs new file mode 100644 index 0000000..cd24b75 --- /dev/null +++ b/CUETools.Codecs.libwavpack/libwavpack.cs @@ -0,0 +1,124 @@ +using System; +using System.Runtime.InteropServices; + +namespace CUETools.Codecs.libwavpack +{ + internal enum OpenFlags : int + { + OPEN_WVC = 0x1, // open/read "correction" file + OPEN_TAGS = 0x2, // read ID3v1 / APEv2 tags (seekable file) + OPEN_WRAPPER = 0x4, // make audio wrapper available (i.e. RIFF) + OPEN_2CH_MAX = 0x8, // open multichannel as stereo (no downmix) + OPEN_NORMALIZE = 0x10, // normalize floating point data to +/- 1.0 + OPEN_STREAMING = 0x20, // "streaming" mode blindly unpacks blocks + // w/o regard to header file position info + OPEN_EDIT_TAGS = 0x40, // allow editing of tags + OPEN_FILE_UTF8 = 0x80, // assume filenames are UTF-8 encoded, not ANSI (Windows only) + // new for version 5 + OPEN_DSD_NATIVE = 0x100, // open DSD files as bitstreams + // (returned as 8-bit "samples" stored in 32-bit words) + OPEN_DSD_AS_PCM = 0x200, // open DSD files as 24-bit PCM (decimated 8x) + OPEN_ALT_TYPES = 0x400, // application is aware of alternate file types & qmode + // (just affects retrieving wrappers & MD5 checksums) + OPEN_NO_CHECKSUM = 0x800, // don't verify block checksums before decoding + }; + + internal enum ConfigFlags : uint + { + CONFIG_BYTES_STORED = 3, // 1-4 bytes/sample + CONFIG_MONO_FLAG = 4, // not stereo + CONFIG_HYBRID_FLAG = 8, // hybrid mode + CONFIG_JOINT_STEREO = 0x10, // joint stereo + CONFIG_CROSS_DECORR = 0x20, // no-delay cross decorrelation + CONFIG_HYBRID_SHAPE = 0x40, // noise shape (hybrid mode only) + CONFIG_FLOAT_DATA = 0x80, // ieee 32-bit floating point data + + CONFIG_FAST_FLAG = 0x200, // fast mode + CONFIG_HIGH_FLAG = 0x800, // high quality mode + CONFIG_VERY_HIGH_FLAG = 0x1000, // very high + CONFIG_BITRATE_KBPS = 0x2000, // bitrate is kbps, not bits / sample + CONFIG_AUTO_SHAPING = 0x4000, // automatic noise shaping + CONFIG_SHAPE_OVERRIDE = 0x8000, // shaping mode specified + CONFIG_JOINT_OVERRIDE = 0x10000, // joint-stereo mode specified + CONFIG_DYNAMIC_SHAPING = 0x20000, // dynamic noise shaping + CONFIG_CREATE_EXE = 0x40000, // create executable + CONFIG_CREATE_WVC = 0x80000, // create correction file + CONFIG_OPTIMIZE_WVC = 0x100000, // maximize bybrid compression + CONFIG_COMPATIBLE_WRITE = 0x400000, // write files for decoders < 4.3 + CONFIG_CALC_NOISE = 0x800000, // calc noise in hybrid mode + CONFIG_LOSSY_MODE = 0x1000000, // obsolete (for information) + CONFIG_EXTRA_MODE = 0x2000000, // extra processing mode + CONFIG_SKIP_WVX = 0x4000000, // no wvx stream w/ floats & big ints + CONFIG_MD5_CHECKSUM = 0x8000000, // compute & store MD5 signature + CONFIG_MERGE_BLOCKS = 0x10000000, // merge blocks of equal redundancy (for lossyWAV) + CONFIG_PAIR_UNDEF_CHANS = 0x20000000, // encode undefined channels in stereo pairs + CONFIG_OPTIMIZE_MONO = 0x80000000, // optimize for mono streams posing as stereo + }; + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal unsafe delegate int DecoderReadDelegate(void* id, void* data, int bcount); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal unsafe delegate UInt32 DecoderTellDelegate(void* id); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal unsafe delegate int DecoderSeekDelegate(void* id, uint pos); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal unsafe delegate int DecoderSeekRelativeDelegate(void* id, int delta, int mode); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal unsafe delegate int DecoderPushBackDelegate(void* id, int c); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal unsafe delegate UInt32 DecoderLengthDelegate(void* id); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal unsafe delegate int DecoderCanSeekDelegate(void* id); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal unsafe delegate int WriteBytesDelegate(void* id, void* data, int bcount); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal unsafe delegate long DecoderTellDelegate64(void* id); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal unsafe delegate int DecoderSeekDelegate64(void* id, long pos); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal unsafe delegate int DecoderSeekRelativeDelegate64(void* id, long delta, int mode); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal unsafe delegate long DecoderLengthDelegate64(void* id); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal unsafe delegate long DecoderTruncateDelegate(void* id); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal unsafe delegate long DecoderCloseDelegate(void* id); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal unsafe delegate int EncoderBlockOutput(void* id, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2), In] byte[] data, int bcount); + + [StructLayout(LayoutKind.Sequential), Serializable] + internal unsafe struct WavpackStreamReader64 + { + internal IntPtr read_bytes; + internal IntPtr write_bytes; + internal IntPtr get_pos; + internal IntPtr set_pos_abs; + internal IntPtr set_pos_rel; + internal IntPtr push_back_byte; + internal IntPtr get_length; + internal IntPtr can_seek; + internal IntPtr truncate_here; + internal IntPtr close; + }; + + [StructLayout(LayoutKind.Sequential), Serializable] + internal unsafe struct WavpackConfig + { + internal float bitrate, shaping_weight; + internal int bits_per_sample, bytes_per_sample; + internal int qmode; + internal ConfigFlags flags; + internal int xmode, num_channels, float_norm_exp; + internal int block_samples, extra_flags, sample_rate, channel_mask; + internal fixed byte md5_checksum[16]; + internal byte md5_read; + internal int num_tag_strings; + internal char** tag_strings; + }; + + internal struct WavpackContext + { + } +} diff --git a/CUETools.Codecs.libwavpack/wavpackdll.cs b/CUETools.Codecs.libwavpack/wavpackdll.cs new file mode 100644 index 0000000..7479461 --- /dev/null +++ b/CUETools.Codecs.libwavpack/wavpackdll.cs @@ -0,0 +1,85 @@ +using System; +using System.Runtime.InteropServices; + +namespace CUETools.Codecs.libwavpack +{ + internal unsafe static class wavpackdll + { + internal const string DllName = "wavpackdll"; + internal const CallingConvention DllCallingConvention = CallingConvention.Cdecl; + + [DllImport("kernel32.dll")] + private static extern IntPtr LoadLibrary(string dllToLoad); + + [DllImport(DllName, CallingConvention = DllCallingConvention)] + internal static extern WavpackContext* WavpackOpenFileInputEx64 (WavpackStreamReader64 *reader, void *wv_id, void *wvc_id, + [param: MarshalAs(UnmanagedType.LPTStr), Out()] out string error, + OpenFlags flags, int norm_offset); + + [DllImport(DllName, CallingConvention = DllCallingConvention)] + internal static extern long WavpackGetNumSamples64 (WavpackContext *wpc); + + [DllImport(DllName, CallingConvention = DllCallingConvention)] + internal static extern int WavpackSeekSample64 (WavpackContext *wpc, long sample); + + [DllImport(DllName, CallingConvention = DllCallingConvention)] + internal static extern WavpackContext* WavpackCloseFile (WavpackContext *wpc); + + [DllImport(DllName, CallingConvention = DllCallingConvention)] + internal static extern uint WavpackUnpackSamples (WavpackContext *wpc, int *buffer, uint samples); + + [DllImport(DllName, CallingConvention = DllCallingConvention)] + internal static extern int WavpackGetBitsPerSample(WavpackContext* wpc); + + [DllImport(DllName, CallingConvention = DllCallingConvention)] + internal static extern int WavpackGetNumChannels(WavpackContext* wpc); + + [DllImport(DllName, CallingConvention = DllCallingConvention)] + internal static extern uint WavpackGetSampleRate(WavpackContext* wpc); + + [DllImport(DllName, CallingConvention = DllCallingConvention)] + internal static extern int WavpackGetChannelMask(WavpackContext* wpc); + + [DllImport(DllName, CallingConvention = DllCallingConvention)] + internal static extern IntPtr WavpackGetLibraryVersionString(); + + [DllImport(DllName, CallingConvention = DllCallingConvention)] + internal static extern int WavpackStoreMD5Sum(WavpackContext* wpc, byte* data); + + [DllImport(DllName, CallingConvention = DllCallingConvention)] + internal static extern int WavpackFlushSamples(WavpackContext* wpc); + + [DllImport(DllName, CallingConvention = DllCallingConvention)] + internal static extern int WavpackPackSamples(WavpackContext* wpc, int* sample_buffer, uint sample_count); + + [DllImport(DllName, CallingConvention = DllCallingConvention)] + internal static extern string WavpackGetErrorMessage(WavpackContext* wpc); + + [DllImport(DllName, CallingConvention = DllCallingConvention)] + internal static extern WavpackContext* WavpackOpenFileOutput(EncoderBlockOutput blockout, void* wv_id, void* wvc_id); + + [DllImport(DllName, CallingConvention = DllCallingConvention)] + internal static extern int WavpackSetConfiguration64(WavpackContext* wpc, WavpackConfig* config, long total_samples, byte* chan_ids); + + [DllImport(DllName, CallingConvention = DllCallingConvention)] + internal static extern int WavpackPackInit(WavpackContext* wpc); + + + static wavpackdll() + { + var myPath = new Uri(typeof(wavpackdll).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(); + } + }; +} diff --git a/CUETools/CUETools.sln b/CUETools/CUETools.sln index cdb5955..3391e84 100644 --- a/CUETools/CUETools.sln +++ b/CUETools/CUETools.sln @@ -57,10 +57,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CUETools", "CUETools.csproj EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CUETools.Codecs.APE", "..\CUETools.Codecs.APE\CUETools.Codecs.APE.vcxproj", "{9AE965C4-301E-4C01-B90F-297AF341ACC6}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CUETools.Codecs.WavPack", "..\CUETools.Codecs.WavPack\CUETools.Codecs.WavPack.vcxproj", "{CC2E74B6-534A-43D8-9F16-AC03FE955000}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libwavpack", "..\wavpack-4.5.0\src\libwavpack.vcxproj", "{5CCCB9CF-0384-458F-BA08-72B73866840F}" -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} @@ -191,6 +187,12 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MACLib", "..\ThirdParty\MAC EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenCLNet", "..\ThirdParty\openclnet\source\OpenCLNet.csproj", "{8373E3B2-16F0-4FD3-A13B-0B0248FFC228}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CUETools.Codecs.libwavpack", "..\CUETools.Codecs.libwavpack\CUETools.Codecs.libwavpack.csproj", "{4D1B3411-F4F7-4E62-B7CB-A3AC3D530443}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libwavpack", "..\ThirdParty\WavPack\src\libwavpack.vcxproj", "{5CCCB9CF-0384-458F-BA08-72B73866840F}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wavpackdll", "..\ThirdParty\WavPack\wavpackdll\wavpackdll.vcxproj", "{1A87F412-BA74-4DBB-9F77-FD55C042FB63}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -235,38 +237,6 @@ Global {9AE965C4-301E-4C01-B90F-297AF341ACC6}.Release|x64.ActiveCfg = Release|x64 {9AE965C4-301E-4C01-B90F-297AF341ACC6}.Release|x64.Build.0 = Release|x64 {9AE965C4-301E-4C01-B90F-297AF341ACC6}.Release|x86.ActiveCfg = Release|x64 - {CC2E74B6-534A-43D8-9F16-AC03FE955000}.Debug|Any CPU.ActiveCfg = Debug|x64 - {CC2E74B6-534A-43D8-9F16-AC03FE955000}.Debug|Mixed Platforms.ActiveCfg = Debug|x64 - {CC2E74B6-534A-43D8-9F16-AC03FE955000}.Debug|Mixed Platforms.Build.0 = Debug|x64 - {CC2E74B6-534A-43D8-9F16-AC03FE955000}.Debug|Win32.ActiveCfg = Debug|Win32 - {CC2E74B6-534A-43D8-9F16-AC03FE955000}.Debug|Win32.Build.0 = Debug|Win32 - {CC2E74B6-534A-43D8-9F16-AC03FE955000}.Debug|x64.ActiveCfg = Debug|x64 - {CC2E74B6-534A-43D8-9F16-AC03FE955000}.Debug|x64.Build.0 = Debug|x64 - {CC2E74B6-534A-43D8-9F16-AC03FE955000}.Debug|x86.ActiveCfg = Debug|x64 - {CC2E74B6-534A-43D8-9F16-AC03FE955000}.Release|Any CPU.ActiveCfg = Release|Win32 - {CC2E74B6-534A-43D8-9F16-AC03FE955000}.Release|Mixed Platforms.ActiveCfg = Release|x64 - {CC2E74B6-534A-43D8-9F16-AC03FE955000}.Release|Mixed Platforms.Build.0 = Release|x64 - {CC2E74B6-534A-43D8-9F16-AC03FE955000}.Release|Win32.ActiveCfg = Release|Win32 - {CC2E74B6-534A-43D8-9F16-AC03FE955000}.Release|Win32.Build.0 = Release|Win32 - {CC2E74B6-534A-43D8-9F16-AC03FE955000}.Release|x64.ActiveCfg = Release|x64 - {CC2E74B6-534A-43D8-9F16-AC03FE955000}.Release|x64.Build.0 = Release|x64 - {CC2E74B6-534A-43D8-9F16-AC03FE955000}.Release|x86.ActiveCfg = Release|x64 - {5CCCB9CF-0384-458F-BA08-72B73866840F}.Debug|Any CPU.ActiveCfg = Debug|x64 - {5CCCB9CF-0384-458F-BA08-72B73866840F}.Debug|Mixed Platforms.ActiveCfg = Debug|x64 - {5CCCB9CF-0384-458F-BA08-72B73866840F}.Debug|Mixed Platforms.Build.0 = Debug|x64 - {5CCCB9CF-0384-458F-BA08-72B73866840F}.Debug|Win32.ActiveCfg = Debug|Win32 - {5CCCB9CF-0384-458F-BA08-72B73866840F}.Debug|Win32.Build.0 = Debug|Win32 - {5CCCB9CF-0384-458F-BA08-72B73866840F}.Debug|x64.ActiveCfg = Debug|x64 - {5CCCB9CF-0384-458F-BA08-72B73866840F}.Debug|x64.Build.0 = Debug|x64 - {5CCCB9CF-0384-458F-BA08-72B73866840F}.Debug|x86.ActiveCfg = Debug|x64 - {5CCCB9CF-0384-458F-BA08-72B73866840F}.Release|Any CPU.ActiveCfg = Release|x64 - {5CCCB9CF-0384-458F-BA08-72B73866840F}.Release|Mixed Platforms.ActiveCfg = Release|x64 - {5CCCB9CF-0384-458F-BA08-72B73866840F}.Release|Mixed Platforms.Build.0 = Release|x64 - {5CCCB9CF-0384-458F-BA08-72B73866840F}.Release|Win32.ActiveCfg = Release|Win32 - {5CCCB9CF-0384-458F-BA08-72B73866840F}.Release|Win32.Build.0 = Release|Win32 - {5CCCB9CF-0384-458F-BA08-72B73866840F}.Release|x64.ActiveCfg = Release|x64 - {5CCCB9CF-0384-458F-BA08-72B73866840F}.Release|x64.Build.0 = Release|x64 - {5CCCB9CF-0384-458F-BA08-72B73866840F}.Release|x86.ActiveCfg = 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|Mixed Platforms.ActiveCfg = Debug|Any CPU @@ -1135,6 +1105,62 @@ Global {8373E3B2-16F0-4FD3-A13B-0B0248FFC228}.Release|x64.ActiveCfg = Release|Any CPU {8373E3B2-16F0-4FD3-A13B-0B0248FFC228}.Release|x86.ActiveCfg = Release|Any CPU {8373E3B2-16F0-4FD3-A13B-0B0248FFC228}.Release|x86.Build.0 = Release|Any CPU + {4D1B3411-F4F7-4E62-B7CB-A3AC3D530443}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4D1B3411-F4F7-4E62-B7CB-A3AC3D530443}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4D1B3411-F4F7-4E62-B7CB-A3AC3D530443}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {4D1B3411-F4F7-4E62-B7CB-A3AC3D530443}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {4D1B3411-F4F7-4E62-B7CB-A3AC3D530443}.Debug|Win32.ActiveCfg = Debug|Any CPU + {4D1B3411-F4F7-4E62-B7CB-A3AC3D530443}.Debug|Win32.Build.0 = Debug|Any CPU + {4D1B3411-F4F7-4E62-B7CB-A3AC3D530443}.Debug|x64.ActiveCfg = Debug|Any CPU + {4D1B3411-F4F7-4E62-B7CB-A3AC3D530443}.Debug|x64.Build.0 = Debug|Any CPU + {4D1B3411-F4F7-4E62-B7CB-A3AC3D530443}.Debug|x86.ActiveCfg = Debug|Any CPU + {4D1B3411-F4F7-4E62-B7CB-A3AC3D530443}.Debug|x86.Build.0 = Debug|Any CPU + {4D1B3411-F4F7-4E62-B7CB-A3AC3D530443}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4D1B3411-F4F7-4E62-B7CB-A3AC3D530443}.Release|Any CPU.Build.0 = Release|Any CPU + {4D1B3411-F4F7-4E62-B7CB-A3AC3D530443}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {4D1B3411-F4F7-4E62-B7CB-A3AC3D530443}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {4D1B3411-F4F7-4E62-B7CB-A3AC3D530443}.Release|Win32.ActiveCfg = Release|Any CPU + {4D1B3411-F4F7-4E62-B7CB-A3AC3D530443}.Release|Win32.Build.0 = Release|Any CPU + {4D1B3411-F4F7-4E62-B7CB-A3AC3D530443}.Release|x64.ActiveCfg = Release|Any CPU + {4D1B3411-F4F7-4E62-B7CB-A3AC3D530443}.Release|x64.Build.0 = Release|Any CPU + {4D1B3411-F4F7-4E62-B7CB-A3AC3D530443}.Release|x86.ActiveCfg = Release|Any CPU + {4D1B3411-F4F7-4E62-B7CB-A3AC3D530443}.Release|x86.Build.0 = Release|Any CPU + {5CCCB9CF-0384-458F-BA08-72B73866840F}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {5CCCB9CF-0384-458F-BA08-72B73866840F}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {5CCCB9CF-0384-458F-BA08-72B73866840F}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {5CCCB9CF-0384-458F-BA08-72B73866840F}.Debug|Win32.ActiveCfg = Debug|Win32 + {5CCCB9CF-0384-458F-BA08-72B73866840F}.Debug|Win32.Build.0 = Debug|Win32 + {5CCCB9CF-0384-458F-BA08-72B73866840F}.Debug|x64.ActiveCfg = Debug|x64 + {5CCCB9CF-0384-458F-BA08-72B73866840F}.Debug|x64.Build.0 = Debug|x64 + {5CCCB9CF-0384-458F-BA08-72B73866840F}.Debug|x86.ActiveCfg = Debug|Win32 + {5CCCB9CF-0384-458F-BA08-72B73866840F}.Debug|x86.Build.0 = Debug|Win32 + {5CCCB9CF-0384-458F-BA08-72B73866840F}.Release|Any CPU.ActiveCfg = Release|Win32 + {5CCCB9CF-0384-458F-BA08-72B73866840F}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {5CCCB9CF-0384-458F-BA08-72B73866840F}.Release|Mixed Platforms.Build.0 = Release|Win32 + {5CCCB9CF-0384-458F-BA08-72B73866840F}.Release|Win32.ActiveCfg = Release|Win32 + {5CCCB9CF-0384-458F-BA08-72B73866840F}.Release|Win32.Build.0 = Release|Win32 + {5CCCB9CF-0384-458F-BA08-72B73866840F}.Release|x64.ActiveCfg = Release|x64 + {5CCCB9CF-0384-458F-BA08-72B73866840F}.Release|x64.Build.0 = Release|x64 + {5CCCB9CF-0384-458F-BA08-72B73866840F}.Release|x86.ActiveCfg = Release|Win32 + {5CCCB9CF-0384-458F-BA08-72B73866840F}.Release|x86.Build.0 = Release|Win32 + {1A87F412-BA74-4DBB-9F77-FD55C042FB63}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {1A87F412-BA74-4DBB-9F77-FD55C042FB63}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {1A87F412-BA74-4DBB-9F77-FD55C042FB63}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {1A87F412-BA74-4DBB-9F77-FD55C042FB63}.Debug|Win32.ActiveCfg = Debug|Win32 + {1A87F412-BA74-4DBB-9F77-FD55C042FB63}.Debug|Win32.Build.0 = Debug|Win32 + {1A87F412-BA74-4DBB-9F77-FD55C042FB63}.Debug|x64.ActiveCfg = Debug|x64 + {1A87F412-BA74-4DBB-9F77-FD55C042FB63}.Debug|x64.Build.0 = Debug|x64 + {1A87F412-BA74-4DBB-9F77-FD55C042FB63}.Debug|x86.ActiveCfg = Debug|Win32 + {1A87F412-BA74-4DBB-9F77-FD55C042FB63}.Debug|x86.Build.0 = Debug|Win32 + {1A87F412-BA74-4DBB-9F77-FD55C042FB63}.Release|Any CPU.ActiveCfg = Release|Win32 + {1A87F412-BA74-4DBB-9F77-FD55C042FB63}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {1A87F412-BA74-4DBB-9F77-FD55C042FB63}.Release|Mixed Platforms.Build.0 = Release|Win32 + {1A87F412-BA74-4DBB-9F77-FD55C042FB63}.Release|Win32.ActiveCfg = Release|Win32 + {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 + {1A87F412-BA74-4DBB-9F77-FD55C042FB63}.Release|x86.ActiveCfg = Release|Win32 + {1A87F412-BA74-4DBB-9F77-FD55C042FB63}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1148,8 +1174,6 @@ Global {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} - {CC2E74B6-534A-43D8-9F16-AC03FE955000} = {39A17A65-E893-44B8-A312-DDCDD990D9D1} - {5CCCB9CF-0384-458F-BA08-72B73866840F} = {8B179853-B7D6-479C-B8B2-6CBCE835D040} {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} @@ -1193,6 +1217,9 @@ Global {4CEFBC83-C215-11DB-8314-0800200C9A66} = {8B179853-B7D6-479C-B8B2-6CBCE835D040} {21BF980F-C022-4DCC-9250-7C73528E422B} = {8B179853-B7D6-479C-B8B2-6CBCE835D040} {8373E3B2-16F0-4FD3-A13B-0B0248FFC228} = {7E402406-7E51-4F0D-8209-60824C1CD6E8} + {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} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {C634D169-5814-4203-94B6-6A11371DDA95} diff --git a/ThirdParty/MAC_SDK b/ThirdParty/MAC_SDK index bb37bfa..ec5e7e8 160000 --- a/ThirdParty/MAC_SDK +++ b/ThirdParty/MAC_SDK @@ -1 +1 @@ -Subproject commit bb37bfafa4d23f2df6d7767ca937c540bc422ad0 +Subproject commit ec5e7e8ee770037d54ab261d742fc1fe3d644153 diff --git a/ThirdParty/WavPack b/ThirdParty/WavPack index 8e3fe45..c2d60b1 160000 --- a/ThirdParty/WavPack +++ b/ThirdParty/WavPack @@ -1 +1 @@ -Subproject commit 8e3fe45a7bac31d9a3b558ae0079e2d92a04799e +Subproject commit c2d60b18d7247dc6739e7e2d55947dbb836d3172 diff --git a/ThirdParty/flac b/ThirdParty/flac index 36fce5b..6735ddd 160000 --- a/ThirdParty/flac +++ b/ThirdParty/flac @@ -1 +1 @@ -Subproject commit 36fce5b6502a6fc170ef85be9f61718ae8bbbbc0 +Subproject commit 6735ddd4602e6a4588ade4d363e750ae8fa1ab7d diff --git a/wavpack-4.5.0/ChangeLog b/wavpack-4.5.0/ChangeLog deleted file mode 100644 index 3beabfd..0000000 --- a/wavpack-4.5.0/ChangeLog +++ /dev/null @@ -1,379 +0,0 @@ - ---------------------------- - Release 4.50 - June 13, 2008 - ---------------------------- - - WavPack Library Source Code - 4.50 - ---------------------------------- - added: dynamic noise shaping for improved hybrid quality - added: option to merge blocks of similar redundancy - added: ability to store and retrieve extra mode level - fixed: alignment fault on some big-endian machines - fixed: compiling with enable-mmx on gcc 4.3.x (thanks Joachim) - improved: allow bitrate to be calculated for files down to 1/10 second - improved: decoding of corrupt files (prevents heap overrun crashes) - - wavpack.exe (command-line encoder) - 4.50 - ----------------------------------------- - added: dynamic noise shaping for improved hybrid quality - added: --channel-order option to reorder nonconforming multichannel files - added: --merge-blocks option to optimize storage of LossyWAV output files - added: ignore -o on Windows for compatibility with Linux version - fixed: alignment fault on some big-endian machines - improved: reformatted and expanded --help display - - wvunpack.exe (command-line decoder) - 4.50 - ------------------------------------------ - fixed: don't ignore fractions of seconds in --skip option - added: show extra level and dns status for newer files (-s command) - added: ignore -o on Windows for compatibility with Linux version - improved: decoding of corrupt files (prevents heap overrun crashes) - improved: display bitrate for files down to 1/10 second - - in_wv.dll (winamp plugin) - 2.5 - ------------------------------- - added: transcoding API (allows CD burning, format conversion, ReplayGain calc, etc.) - added: metadata writing API (for Auto-Tag, etc.) - added: full Unicode support for info box (older Winamps) and media library - added: standard Winamp metadata display & edit for newer Winamps - added: option to pass multichannel audio - added: option to pass all audio as 16-bit (for better compatibility) - added: option to output 24-bit audio when ReplayGain is active - added: genre display to info box (older Winamps) - fixed: seek bar sometimes vacillates when moved - fixed: crash when winamp is opened with files in playlist moved or deleted - improved: hi-res audio now output as 24-bit (not 32-bit) for better compatibility (EQ, etc.) - improved: performance of adding tracks to library, especially from network drives - improved: decoding of corrupt files (prevents heap overrun crashes) - - cool_wv4.flt (CoolEdit / Audition filter) - 2.9 - ----------------------------------------------- - added: about box - added: dynamic noise shaping for improved hybrid quality - improved: display bitrate for files as short as 1/10 second - improved: decoding of corrupt files (prevents heap overrun crashes) - improved: replace "extra processing" switch with a slider (0-6) - - - -------------------------- - Release 4.41 - May 6, 2007 - -------------------------- - - WavPack Library Source Code - 4.41 - ---------------------------------- - added: create wavpackdll.dll for Windows (not used yet) - fixed: corrupt floating-point audio on big-endian machines - fixed: put MSVC projects in their own subdir (fixed build problems) - fixed: limit RIFF data buffering to 16 MB to prevent out-of-memory crash - improved: attempt to mute errors when decoding corrupt legacy WavPack files - improved: overall performance enhancements of 10% to 30% (depending on mode) - added: MMX intrinsics for 24-bit (and higher) stereo encoding (thanks to - Joachim Henke) - - wavpack.exe (command-line encoder) - 4.41 - ----------------------------------------- - fixed: corrupt floating-point audio on big-endian machines - improved: refuse to encode WAV files over 4 GB or with over 16 MB RIFF data - improved: overall performance enhancements of 10% to 30% (depending on mode) - added: MMX intrinsics for 24-bit (and higher) stereo encoding (thanks to - Joachim Henke) - - wvunpack.exe (command-line decoder) - 4.41 - ------------------------------------------ - fixed: corrupt floating-point audio on big-endian machines - fixed: restore files mistakenly encoded with huge RIFF chunks - improved: attempt to mute errors when decoding corrupt legacy WavPack files - improved: overall performance enhancements of 10% to 30% (depending on mode) - added: --skip and --until commands to unpack specified range of audio data - added: MMX intrinsics for 24-bit (and higher) stereo encoding (thanks to - Joachim Henke) - - wvgain.exe (command-line ReplayGain scanner) - 4.41 - --------------------------------------------------- - improved: overall performance enhancements of 10% to 30% (depending on mode) - added: MMX intrinsics for 24-bit (and higher) stereo encoding (thanks to - Joachim Henke) - - cool_wv4.flt (CoolEdit / Audition filter) - 2.8 - ----------------------------------------------- - fixed: read all RIFF metadata from files created in other applications - improved: attempt to mute errors when decoding corrupt legacy WavPack files - improved: overall performance enhancements of 10% to 30% (depending on mode) - added: MMX intrinsics for 24-bit (and higher) stereo encoding (thanks to - Joachim Henke) - - - ------------------------------- - Release 4.40 - December 3, 2006 - ------------------------------- - - WavPack Library Source Code - 4.40 - ---------------------------------- - added: new hardware-friendly "high" mode that compresses almost as well as - old "high" mode but decodes significantly faster; old "high" mode - now available as "very high" - added: option added to improve compression of mono material in stereo files - (requires at least version 4.3 decoder) - added: function to obtain channel mapping information on decoding - added: function to get trailing wrapper info (RIFF) without decoding file - improved: "extra" mode levels 1-3 completely revamped, fast enough for use - improved: reorganized to create a standard library that should more easily - integrate into other applications; eliminated namespace issues - improved: more robust handling of corrupt files - - wavpack.exe (command-line encoder) - 4.40 - ----------------------------------------- - added: accepts long option names including --help for full usage info - added: new hardware-friendly "high" mode that compresses almost as well as - old "high" mode but decodes significantly faster; old "high" mode - now available as "very high" (-hh) - added: --optimize-mono option added to improve compression of mono material - in stereo files (requires at least version 4.3 decoder) - improved: "extra" mode levels 1-3 completely revamped, fast enough for use - improved: switched to Microsoft Visual Studio 2005 (win32 only) - removed: support for Windows 95 - - wvunpack.exe (command-line decoder) - 4.40 - ------------------------------------------ - added: cuesheet extraction (to .cue file or stdout) - added: wav header generation on decode for files with missing RIFF - information, or forced with -w option - added: more summary info (wrapper info + channel assignments) - improved: more robust handling of corrupt files - improved: separate options for raw (-r) and blind stream decoding (-b) - improved: switched to Microsoft Visual Studio 2005 (win32 only) - removed: support for Windows 95 - - wvgain.exe (command-line ReplayGain scanner) - 4.40 - --------------------------------------------------- - improved: switched to Microsoft Visual Studio 2005 (win32 only) - removed: support for Windows 95 - - wvselfx.exe (self-extraction stub) - 4.40 - ------------------------------------------ - added: automatic cuesheet extraction (if present in APEv2 tag) - - in_wv.dll (winamp plugin) - 2.4 - ------------------------------- - fixed: quietly skips deleted files in playlist - improved: more robust handling of corrupt files - improved: APEv2 tags are read even if followed by ID3v1 tag - - cool_wv4.flt (CoolEdit / Audition filter) - 2.7 - ----------------------------------------------- - added: new hardware-friendly "high" mode that compresses almost as well as - old "high" mode but decodes significantly faster; old "high" mode - now available as "v. high" - improved: more robust handling of corrupt files - - - ---------------------- - Update - April 5, 2006 - ---------------------- - - WavPack Library Source Code - 4.32 - wavpack.exe (command-line encoder) - 4.32 - ----------------------------------------- - fixed: generating RIFF headers on big-endian machines caused crash - - - -------------------------- - Update - December 10, 2005 - -------------------------- - - wavpack.exe (command-line encoder) - 4.31 - wvunpack.exe (command-line decoder) - 4.31 - ------------------------------------------ - fixed: detect debug mode in all cases (win32 only) - improved: use latest service pack and SDK for building (win32 only) - improved: better directory choice for logging file (win32 only) - improved: allow shell to expand wildcards (*nix only) - added: option (-o) to specify output directory or path (*nix only) - added: option (-t) to copy timestamp (*nix only) - - wvgain.exe (command-line ReplayGain scanner) - 4.31 - --------------------------------------------------- - new - - WavPack Library Source Code - 4.31 - ---------------------------------- - fixed: failing seek with some files that had been played to the end - fixed: small memory leak when opening hybrid lossless files - improved: signed characters no longer must be default - improved: APEv2 tags are read even if followed by ID3v1 tag - improved: limited APEv2 tag editing capability - - - ------------------------------ - Release 4.3 - November 1, 2005 - ------------------------------ - - wavpack.exe (command-line encoder) - 4.3 - ---------------------------------------- - fixed: bug causing termination error with very wide screen widths - added: command-line option (-l) to use low priority for batch operation - added: command-line option (-r) to generate a fresh RIFF header - added: debug mode (rename to wavpack_debug.exe) - added: automatically detect lower resolution data even without -x1 - added: src and dst dirs are searched also for tag source files (handy for EAC) - added: wildcard accepted for tag source files (handy for EAC) - added: handle non-standard sampling rates - improved: returns error status for any error - improved: use longer blocks in multichannel files (better "high" compression) - - wvunpack.exe (command-line decoder) - 4.3 - ----------------------------------------- - fixed: very rare decoding bug causing overflow with hi-res files - fixed: bug causing termination error with very wide screen widths - fixed: formatting error in duration display - added: command-line option (-ss) to include tags in summary dump - added: command-line option (-l) to use low priority for batch operation - added: debug mode (rename to wvunpack_debug.exe) - improved: returns error status for any error - improved: more robust decoding of damaged (or invalid) files - - in_wv.dll (winamp plugin) - 2.3 - nxWavPack.dll (Nero plugin) - 1.2 - WavPack_Apollo.dll (Apollo plugin) - 1.3 - cool_wv4.flt (CoolEdit / Audition filter) - 2.6 - ----------------------------------------------- - fixed: very rare decoding bug causing overflow with hi-res files - improved: handle ID3v1.1 tags (now includes track number) - improved: more robust decoding of damaged (or invalid) files - added: handle non-standard sampling rates - - foo_wavpack.dll (foobar plugin) - 2.3 - ----------------------------------------------- - fixed: any error during WavPack file open caused crash if wvc file present - fixed: very rare decoding bug causing overflow with hi-res files - improved: more robust decoding of damaged (or invalid) files - added: handle non-standard sampling rates - - WavPack Library Source Code - 4.3 - --------------------------------- - fixed: very rare decoding bug causing overflow with hi-res files - added: automatic generation of RIFF wav header during encoding - added: new functions to access tags by index (instead of item name) - added: automatically detect lower resolution data during encoding - added: handle non-standard sampling rates - improved: more robust decoding of damaged (or invalid) files - improved: use longer blocks in multichannel files (better "high" compression) - improved: two structures renamed to avoid namespace conflict - removed: legacy code for Borland compiler - - - -------------------------- - Update - September 1, 2005 - -------------------------- - - wavpack.exe (command-line encoder) - 4.22 - cool_wv4.flt (CoolEdit / Audition filter) - 2.5 - ----------------------------------------------- - fixed: possible corrupt files written (24 or 32-bit + "extra" mode) - - - --------------------------- - Release 4.2 - April 2, 2005 - --------------------------- - - wavpack.exe (command-line encoder) - 4.2 - ---------------------------------------- - fixed: handling of wav files larger than 2 gig - improved: stereo lossless encoding speed (including "extra" mode) - added: -i option to ignore length specified in wav header - added: -w option to write APEv2 tags directly from command line - - wvunpack.exe (command-line decoder) - 4.2 - ----------------------------------------- - improved: decoding speed - - in_wv.dll (winamp plugin) - 2.2 - ------------------------------- - added: winamp media library support - improved: decoding speed - - foo_wavpack.dll (foobar plugin) - 2.2 - ------------------------------------- - improved: decoding speed - - nxWavPack.dll (Nero plugin) - 1.1 - Cool_wv4.flt (CoolEdit / Audition filter) - 2.4 - ----------------------------------------------- - fixed: handling of wav files larger than 2 gig - improved: encoding and decoding speed - - WavPack Library Source Code - 4.2 - --------------------------------- - improved: encoding and decoding speed - fixed: works correctly with 64-bit compilers - added: mode bit to open files in "streaming" mode - - - -------------------------- - Update - December 12, 2004 - -------------------------- - - WavPack_Apollo.dll (Apollo plugin) - 1.2 - ---------------------------------------- - fixed: crash when Apollo opened and WavPack plugin can't find config file - - - -------------------------------- - Release 4.1 - September 14, 2004 - -------------------------------- - - wavpack.exe (command-line encoder) - 4.1 - ---------------------------------------- - fixed: hybrid mode + "extra" mode + very low bitrates making corrupt files - fixed: mono or multichannel files causing crash (no corruption possible) - added: third name specification for "correction" file (EAC specific) - added: -t option to preserve timestamps - added: error summary for batch mode - - wvunpack.exe (command-line decoder) - 4.1 - ----------------------------------------- - fixed: hybrid mode decoding bugs (very obscure situations) - added: -s option to dump file summary to stdout - added: -t option to preserve timestamps - added: error summary for batch mode - - wvselfx.exe (self-extraction stub) - 4.1 - ---------------------------------------- - fixed: hybrid mode decoding bugs (very obscure situations) - - in_wv.dll (winamp plugin) - 2.1 - ------------------------------- - fixed: international characters in tags display properly (UTF-8 to Ansi) - added: maximum tag data field width changed from 64 chars to 128 chars - added: new infobox items including encoder version & modes, track #, md5 - - foo_wavpack.dll (foobar plugin) - 2.1 - ------------------------------------- - added: new database items including encoder version & modes and md5 - - WavPack_Apollo.dll (Apollo plugin) - 1.1 - ---------------------------------------- - fixed: international characters in tags display properly (UTF-8 to Ansi) - - Cool_wv4.flt (CoolEdit / Audition filter) - 2.2 - ----------------------------------------------- - fixed: hybrid mode + "extra" mode + very low bitrates making corrupt files - fixed: saving mono file causing crash (no corruption possible) - fixed: hybrid mode decoding bugs (very obscure situations) - fixed: partial saves (with "Cancel") have incorrect RIFF header if unpacked - - nxWavPack.dll (Nero plugin) - 1.0 - --------------------------------- - new - - WavPack Library Source Code - 4.1 - --------------------------------- - fixed: hybrid mode + "extra" mode + very low bitrates making corrupt files - fixed: mono or multichannel files causing crash (no corruption possible) - fixed: hybrid mode decoding bugs (very obscure situations) - added: mode bits for determining additional encode info (extra, sfx) - added: function to return total compressed file length (including wvc) - added: function to return encoder version (1, 2, 3, or 4) - added: ability to obtain MD5 sum before decoding file (requires seek to end) - added: mode bit for determining tag type (for proper character translation) - added: ability to encode WavPack files without knowing length in advance - added: option for small "information only" version of library diff --git a/wavpack-4.5.0/README b/wavpack-4.5.0/README deleted file mode 100644 index fd8fe6f..0000000 --- a/wavpack-4.5.0/README +++ /dev/null @@ -1,103 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// **** WAVPACK **** // -// Hybrid Lossless Wavefile Compressor // -// Copyright (c) 1998 - 2006 Conifer Software. // -// All Rights Reserved. // -// Distributed under the BSD Software License (see license.txt) // -//////////////////////////////////////////////////////////////////////////// - -This package contains all the source code required to build the WavPack -command-line programs and the WavPack library and it has been tested on many -platforms. - -On Windows there are solution and project files for Visual Studio 2005 and -additional sourcecode to build the CoolEdit/Audition plugin and the winamp -plugin. The CoolEdit/Audition plugin provides a good example for using the -library to both read and write WavPack files. - -To build everything on Linux, type: - -1. ./configure [--enable-mmx] -2. make -3. make install (optionally, to install into /usr/local/bin) - -If you are using the code directly from SVN (rather than a distribution) -then you will need to do a ./autogen.sh before the configure step. For -processors that support MMX, use the --enable-mmx switch to utilize MMX -intrinsics to speed up encoding of stereo 24-bit (and higher) audio. - -Notes: - -1. There are two documentation files contained in the distribution: - - doc/library_use.txt contains a detailed description of the API provided - by WavPack library appropriate for read and writing - WavPack files - - doc/file_format.txt contains a description of the WavPack file format, - including details needed for parsing WavPack blocks - and interpreting the block header and flags - - There is also a description of the WavPack algorithms in the forth edition - of David Salomon's book "Data Compression: The Complete Reference". The - section on WavPack can be found here: - - www.wavpack.com/WavPack.pdf - -2. This code is designed to be easy to port to other platforms. File I/O is - done with streams and all file functions (except "fopen") are handled in - a wrapper in the "utils.c" module. The code is endian-independent. - - To maintain compatibility on various platforms, the following conventions - are used: A "short" must be 16-bits and an "int" must be 32-bits. - The "long" type is not used. The "char" type must be 8-bits, signed or - unsigned. - -3. For WavPack file decoding, a library interface in "wputils.c" provides all - the functionality required for both the winamp plugin and the "wvunpack" - command-line program (including the transparent decoding of "correction" - files). There is also an alternate entry point that uses reader callbacks - for all input, although in this case it is the caller's responsibility to - to open the "correction" file. The header file "include/wavpack.h" - includes everything needed while hiding all the WavPack internals from the - application. - -4. For WavPack file creation, the library interface in "wputils.c" provides - all the functionality for both the Audition filter and the "wavpack" - command-line program. No file I/O is performed by the library when creating - WavPack files. Instead, the user supplies a "write_block" function that - accepts completed WavPack blocks. It is also possible to append APEv2 tags - to WavPack files during creation and edit APEv2 tags on existing files - (although there is no support currently for "binary" fields in the tags). - -5. The following #define's can be optionally used to eliminate some functionality - to create smaller binaries. It is important that they must be specified - the same for the compilation of ALL files: - - NO_UNPACK no unpacking of audio samples from WavPack files - (also don't include unpack.c) - NO_PACK no creating WavPack files from raw audio data - (also don't include pack.c, extra1.c and extra2.c) - INFO_ONLY to obtain information from WavPack files, but not audio - (also don't include pack.c, extra1.c and extra2.c) - NO_SEEKING to not allow seeking to a specific sample index (unpack only) - NO_USE_FSTREAMS to not open WavPack files by name using fstreams - NO_TAGS to not read specified fields from ID3v1 and APEv2 tags and - create APEv2 tags - VER4_ONLY to only handle WavPack files from versions 4.0 onward - WIN32 required for Win32 platform - -6. There are alternate versions of this library available specifically designed - for "resource limited" CPUs or hardware encoding and decoding. There is the - "tiny decoder" library which works with less than 32k of code and less than - 4k of data and has assembly language optimizations for the ARM and Freescale - ColdFire CPUs. The "tiny encoder" is also designed for embedded use and - handles the pure lossless, lossy, and hybrid lossless modes. Neither of the - "tiny" versions use any memory allocation functions nor do they require - floating-point arithmetic support. - - For applications requiring very low latency, there is a special version of - the library that supports a variation on the regular WavPack block format - to facilitate this. - -7. Questions or comments should be directed to david@wavpack.com diff --git a/wavpack-4.5.0/include/wavpack.h b/wavpack-4.5.0/include/wavpack.h deleted file mode 100644 index ad29eb0..0000000 --- a/wavpack-4.5.0/include/wavpack.h +++ /dev/null @@ -1,304 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// **** WAVPACK **** // -// Hybrid Lossless Wavefile Compressor // -// Copyright (c) 1998 - 2006 Conifer Software. // -// All Rights Reserved. // -// Distributed under the BSD Software License (see license.txt) // -//////////////////////////////////////////////////////////////////////////// - -// wavpack.h - -#ifndef WAVPACK_H -#define WAVPACK_H - -// This header file contains all the definitions required to use the -// functions in "wputils.c" to read and write WavPack files and streams. - -#include - -#if defined(_WIN32) && !defined(__MINGW32__) -#include -typedef unsigned __int64 uint64_t; -typedef unsigned __int32 uint32_t; -typedef unsigned __int16 uint16_t; -typedef unsigned __int8 uint8_t; -typedef __int64 int64_t; -typedef __int32 int32_t; -typedef __int16 int16_t; -typedef __int8 int8_t; -typedef float float32_t; -#else -#include -#endif - -typedef unsigned char uchar; - -#if !defined(__GNUC__) || defined(WIN32) -typedef unsigned short ushort; -typedef unsigned int uint; -#endif - -// RIFF / wav header formats (these occur at the beginning of both wav files -// and pre-4.0 WavPack files that are not in the "raw" mode). Generally, an -// application using the library to read or write WavPack files will not be -// concerned with any of these. - -typedef struct { - char ckID [4]; - uint32_t ckSize; - char formType [4]; -} RiffChunkHeader; - -typedef struct { - char ckID [4]; - uint32_t ckSize; -} ChunkHeader; - -#define ChunkHeaderFormat "4L" - -typedef struct { - ushort FormatTag, NumChannels; - uint32_t SampleRate, BytesPerSecond; - ushort BlockAlign, BitsPerSample; - ushort cbSize, ValidBitsPerSample; - int32_t ChannelMask; - ushort SubFormat; - char GUID [14]; -} WaveHeader; - -#define WaveHeaderFormat "SSLLSSSSLS" - -// This is the ONLY structure that occurs in WavPack files (as of version -// 4.0), and is the preamble to every block in both the .wv and .wvc -// files (in little-endian format). Normally, this structure has no use -// to an application using the library to read or write WavPack files, -// but if an application needs to manually parse WavPack files then this -// would be used (with appropriate endian correction). - -typedef struct { - char ckID [4]; - uint32_t ckSize; - short version; - uchar track_no, index_no; - uint32_t total_samples, block_index, block_samples, flags, crc; -} WavpackHeader; - -#define WavpackHeaderFormat "4LS2LLLLL" - -// or-values for WavpackHeader.flags -#define BYTES_STORED 3 // 1-4 bytes/sample -#define MONO_FLAG 4 // not stereo -#define HYBRID_FLAG 8 // hybrid mode -#define JOINT_STEREO 0x10 // joint stereo -#define CROSS_DECORR 0x20 // no-delay cross decorrelation -#define HYBRID_SHAPE 0x40 // noise shape (hybrid mode only) -#define FLOAT_DATA 0x80 // ieee 32-bit floating point data - -#define INT32_DATA 0x100 // special extended int handling -#define HYBRID_BITRATE 0x200 // bitrate noise (hybrid mode only) -#define HYBRID_BALANCE 0x400 // balance noise (hybrid stereo mode only) - -#define INITIAL_BLOCK 0x800 // initial block of multichannel segment -#define FINAL_BLOCK 0x1000 // final block of multichannel segment - -#define SHIFT_LSB 13 -#define SHIFT_MASK (0x1fL << SHIFT_LSB) - -#define MAG_LSB 18 -#define MAG_MASK (0x1fL << MAG_LSB) - -#define SRATE_LSB 23 -#define SRATE_MASK (0xfL << SRATE_LSB) - -#define FALSE_STEREO 0x40000000 // block is stereo, but data is mono - -#define IGNORED_FLAGS 0x18000000 // reserved, but ignore if encountered -#define NEW_SHAPING 0x20000000 // use IIR filter for negative shaping -#define UNKNOWN_FLAGS 0x80000000 // also reserved, but refuse decode if - // encountered - -#define MONO_DATA (MONO_FLAG | FALSE_STEREO) - -#define MIN_STREAM_VERS 0x402 // lowest stream version we'll decode -#define MAX_STREAM_VERS 0x410 // highest stream version we'll decode or encode -#define CUR_STREAM_VERS 0x407 // stream version we are writing now - -// These are the mask bit definitions for the metadata chunk id byte (see format.txt) - -#define ID_UNIQUE 0x3f -#define ID_OPTIONAL_DATA 0x20 -#define ID_ODD_SIZE 0x40 -#define ID_LARGE 0x80 - -#define ID_DUMMY 0x0 -#define ID_ENCODER_INFO 0x1 -#define ID_DECORR_TERMS 0x2 -#define ID_DECORR_WEIGHTS 0x3 -#define ID_DECORR_SAMPLES 0x4 -#define ID_ENTROPY_VARS 0x5 -#define ID_HYBRID_PROFILE 0x6 -#define ID_SHAPING_WEIGHTS 0x7 -#define ID_FLOAT_INFO 0x8 -#define ID_INT32_INFO 0x9 -#define ID_WV_BITSTREAM 0xa -#define ID_WVC_BITSTREAM 0xb -#define ID_WVX_BITSTREAM 0xc -#define ID_CHANNEL_INFO 0xd - -#define ID_RIFF_HEADER (ID_OPTIONAL_DATA | 0x1) -#define ID_RIFF_TRAILER (ID_OPTIONAL_DATA | 0x2) -#define ID_REPLAY_GAIN (ID_OPTIONAL_DATA | 0x3) // never used (APEv2) -#define ID_CUESHEET (ID_OPTIONAL_DATA | 0x4) // never used (APEv2) -#define ID_CONFIG_BLOCK (ID_OPTIONAL_DATA | 0x5) -#define ID_MD5_CHECKSUM (ID_OPTIONAL_DATA | 0x6) -#define ID_SAMPLE_RATE (ID_OPTIONAL_DATA | 0x7) - -///////////////////////// WavPack Configuration /////////////////////////////// - -// This external structure is used during encode to provide configuration to -// the encoding engine and during decoding to provide fle information back to -// the higher level functions. Not all fields are used in both modes. - -typedef struct { - float bitrate, shaping_weight; - int bits_per_sample, bytes_per_sample; - int qmode, flags, xmode, num_channels, float_norm_exp; - int32_t block_samples, extra_flags, sample_rate, channel_mask; - uchar md5_checksum [16], md5_read; - int num_tag_strings; - char **tag_strings; -} WavpackConfig; - -#define CONFIG_HYBRID_FLAG 8 // hybrid mode -#define CONFIG_JOINT_STEREO 0x10 // joint stereo -#define CONFIG_HYBRID_SHAPE 0x40 // noise shape (hybrid mode only) -#define CONFIG_FAST_FLAG 0x200 // fast mode -#define CONFIG_HIGH_FLAG 0x800 // high quality mode -#define CONFIG_VERY_HIGH_FLAG 0x1000 // very high -#define CONFIG_BITRATE_KBPS 0x2000 // bitrate is kbps, not bits / sample -#define CONFIG_SHAPE_OVERRIDE 0x8000 // shaping mode specified -#define CONFIG_JOINT_OVERRIDE 0x10000 // joint-stereo mode specified -#define CONFIG_DYNAMIC_SHAPING 0x20000 // dynamic noise shaping -#define CONFIG_CREATE_EXE 0x40000 // create executable -#define CONFIG_CREATE_WVC 0x80000 // create correction file -#define CONFIG_OPTIMIZE_WVC 0x100000 // maximize bybrid compression -#define CONFIG_CALC_NOISE 0x800000 // calc noise in hybrid mode -#define CONFIG_EXTRA_MODE 0x2000000 // extra processing mode -#define CONFIG_SKIP_WVX 0x4000000 // no wvx stream w/ floats & big ints -#define CONFIG_MD5_CHECKSUM 0x8000000 // store MD5 signature -#define CONFIG_MERGE_BLOCKS 0x10000000 // merge blocks of equal redundancy (for lossyWAV) -#define CONFIG_OPTIMIZE_MONO 0x80000000 // optimize for mono streams posing as stereo - -////////////// Callbacks used for reading & writing WavPack streams ////////// - -typedef struct { - int32_t (*read_bytes)(void *id, void *data, int32_t bcount); - uint32_t (*get_pos)(void *id); - int (*set_pos_abs)(void *id, uint32_t pos); - int (*set_pos_rel)(void *id, int32_t delta, int mode); - int (*push_back_byte)(void *id, int c); - uint32_t (*get_length)(void *id); - int (*can_seek)(void *id); - - // this callback is for writing edited tags only - int32_t (*write_bytes)(void *id, void *data, int32_t bcount); -} WavpackStreamReader; - -typedef int (*WavpackBlockOutput)(void *id, void *data, int32_t bcount); - -//////////////////////////// function prototypes ///////////////////////////// - -// Note: See wputils.c sourcecode for descriptions for using these functions. - -typedef void WavpackContext; - -#ifdef __cplusplus -extern "C" { -#endif - -WavpackContext *WavpackOpenFileInputEx (WavpackStreamReader *reader, void *wv_id, void *wvc_id, char *error, int flags, int norm_offset); -WavpackContext *WavpackOpenFileInput (const wchar_t *infilename, char *error, int flags, int norm_offset); - -#define OPEN_WVC 0x1 // open/read "correction" file -#define OPEN_TAGS 0x2 // read ID3v1 / APEv2 tags (seekable file) -#define OPEN_WRAPPER 0x4 // make audio wrapper available (i.e. RIFF) -#define OPEN_2CH_MAX 0x8 // open multichannel as stereo (no downmix) -#define OPEN_NORMALIZE 0x10 // normalize floating point data to +/- 1.0 -#define OPEN_STREAMING 0x20 // "streaming" mode blindly unpacks blocks - // w/o regard to header file position info -#define OPEN_EDIT_TAGS 0x40 // allow editing of tags - -int WavpackGetMode (WavpackContext *wpc); - -#define MODE_WVC 0x1 -#define MODE_LOSSLESS 0x2 -#define MODE_HYBRID 0x4 -#define MODE_FLOAT 0x8 -#define MODE_VALID_TAG 0x10 -#define MODE_HIGH 0x20 -#define MODE_FAST 0x40 -#define MODE_EXTRA 0x80 // extra mode used, see MODE_XMODE for possible level -#define MODE_APETAG 0x100 -#define MODE_SFX 0x200 -#define MODE_VERY_HIGH 0x400 -#define MODE_MD5 0x800 -#define MODE_XMODE 0x7000 // mask for extra level (1-6, 0=unknown) -#define MODE_DNS 0x8000 - -char *WavpackGetErrorMessage (WavpackContext *wpc); -int WavpackGetVersion (WavpackContext *wpc); -uint32_t WavpackUnpackSamples (WavpackContext *wpc, int32_t *buffer, uint32_t samples); -uint32_t WavpackGetNumSamples (WavpackContext *wpc); -uint32_t WavpackGetSampleIndex (WavpackContext *wpc); -int WavpackGetNumErrors (WavpackContext *wpc); -int WavpackLossyBlocks (WavpackContext *wpc); -int WavpackSeekSample (WavpackContext *wpc, uint32_t sample); -WavpackContext *WavpackCloseFile (WavpackContext *wpc); -uint32_t WavpackGetSampleRate (WavpackContext *wpc); -int WavpackGetBitsPerSample (WavpackContext *wpc); -int WavpackGetBytesPerSample (WavpackContext *wpc); -int WavpackGetNumChannels (WavpackContext *wpc); -int WavpackGetChannelMask (WavpackContext *wpc); -int WavpackGetReducedChannels (WavpackContext *wpc); -int WavpackGetFloatNormExp (WavpackContext *wpc); -int WavpackGetMD5Sum (WavpackContext *wpc, uchar data [16]); -uint32_t WavpackGetWrapperBytes (WavpackContext *wpc); -uchar *WavpackGetWrapperData (WavpackContext *wpc); -void WavpackFreeWrapper (WavpackContext *wpc); -void WavpackSeekTrailingWrapper (WavpackContext *wpc); -double WavpackGetProgress (WavpackContext *wpc); -uint32_t WavpackGetFileSize (WavpackContext *wpc); -double WavpackGetRatio (WavpackContext *wpc); -double WavpackGetAverageBitrate (WavpackContext *wpc, int count_wvc); -double WavpackGetInstantBitrate (WavpackContext *wpc); -int WavpackGetNumTagItems (WavpackContext *wpc); -int WavpackGetTagItem (WavpackContext *wpc, const char *item, char *value, int size); -int WavpackGetTagItemIndexed (WavpackContext *wpc, int index, char *item, int size); -int WavpackAppendTagItem (WavpackContext *wpc, const char *item, const char *value, int vsize); -int WavpackDeleteTagItem (WavpackContext *wpc, const char *item); -int WavpackWriteTag (WavpackContext *wpc); - -WavpackContext *WavpackOpenFileOutput (WavpackBlockOutput blockout, void *wv_id, void *wvc_id); -int WavpackSetConfiguration (WavpackContext *wpc, WavpackConfig *config, uint32_t total_samples); -int WavpackAddWrapper (WavpackContext *wpc, void *data, uint32_t bcount); -int WavpackStoreMD5Sum (WavpackContext *wpc, uchar data [16]); -int WavpackPackInit (WavpackContext *wpc); -int WavpackPackSamples (WavpackContext *wpc, int32_t *sample_buffer, uint32_t sample_count); -int WavpackFlushSamples (WavpackContext *wpc); -void WavpackUpdateNumSamples (WavpackContext *wpc, void *first_block); -void *WavpackGetWrapperLocation (void *first_block, uint32_t *size); -double WavpackGetEncodedNoise (WavpackContext *wpc, double *peak); - -void WavpackFloatNormalize (int32_t *values, int32_t num_values, int delta_exp); - -void WavpackLittleEndianToNative (void *data, char *format); -void WavpackNativeToLittleEndian (void *data, char *format); - -uint32_t WavpackGetLibraryVersion (void); -const char *WavpackGetLibraryVersionString (void); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/wavpack-4.5.0/license.txt b/wavpack-4.5.0/license.txt deleted file mode 100644 index a20b215..0000000 --- a/wavpack-4.5.0/license.txt +++ /dev/null @@ -1,25 +0,0 @@ - Copyright (c) 1998 - 2008 Conifer Software - All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of Conifer Software nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/wavpack-4.5.0/src/bits.c b/wavpack-4.5.0/src/bits.c deleted file mode 100644 index 097c60f..0000000 --- a/wavpack-4.5.0/src/bits.c +++ /dev/null @@ -1,271 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// **** WAVPACK **** // -// Hybrid Lossless Wavefile Compressor // -// Copyright (c) 1998 - 2006 Conifer Software. // -// All Rights Reserved. // -// Distributed under the BSD Software License (see license.txt) // -//////////////////////////////////////////////////////////////////////////// - -// bits.c - -// This module provides utilities to support the BitStream structure which is -// used to read and write all WavPack audio data streams. It also contains a -// wrapper for the stream I/O functions and a set of functions dealing with -// endian-ness, both for enhancing portability. Finally, a debug wrapper for -// the malloc() system is provided. - -#include "wavpack_local.h" - -#include -#include -#include -#include - -#if defined(WIN32) -#include -#else -#include -#endif - -////////////////////////// Bitstream functions //////////////////////////////// - -#if !defined(NO_UNPACK) || defined(INFO_ONLY) - -// Open the specified BitStream and associate with the specified buffer. - -static void bs_read (Bitstream *bs); - -void bs_open_read (Bitstream *bs, void *buffer_start, void *buffer_end) -{ - bs->error = bs->sr = bs->bc = 0; - bs->ptr = (bs->buf = buffer_start) - 1; - bs->end = buffer_end; - bs->wrap = bs_read; -} - -// This function is only called from the getbit() and getbits() macros when -// the BitStream has been exhausted and more data is required. Sinve these -// bistreams no longer access files, this function simple sets an error and -// resets the buffer. - -static void bs_read (Bitstream *bs) -{ - bs->ptr = bs->buf - 1; - bs->error = 1; -} - -// This function is called to close the bitstream. It returns the number of -// full bytes actually read as bits. - -uint32_t bs_close_read (Bitstream *bs) -{ - uint32_t bytes_read; - - if (bs->bc < sizeof (*(bs->ptr)) * 8) - bs->ptr++; - - bytes_read = (uint32_t)(bs->ptr - bs->buf) * sizeof (*(bs->ptr)); - - if (!(bytes_read & 1)) - ++bytes_read; - - CLEAR (*bs); - return bytes_read; -} - -#endif - -#ifndef NO_PACK - -// Open the specified BitStream using the specified buffer pointers. It is -// assumed that enough buffer space has been allocated for all data that will -// be written, otherwise an error will be generated. - -static void bs_write (Bitstream *bs); - -void bs_open_write (Bitstream *bs, void *buffer_start, void *buffer_end) -{ - bs->error = bs->sr = bs->bc = 0; - bs->ptr = bs->buf = buffer_start; - bs->end = buffer_end; - bs->wrap = bs_write; -} - -// This function is only called from the putbit() and putbits() macros when -// the buffer is full, which is now flagged as an error. - -static void bs_write (Bitstream *bs) -{ - bs->ptr = bs->buf; - bs->error = 1; -} - -// This function forces a flushing write of the specified BitStream, and -// returns the total number of bytes written into the buffer. - -uint32_t bs_close_write (Bitstream *bs) -{ - uint32_t bytes_written; - - if (bs->error) - return (uint32_t) -1; - - while (1) { - while (bs->bc) - putbit_1 (bs); - - bytes_written = (uint32_t)(bs->ptr - bs->buf) * sizeof (*(bs->ptr)); - - if (bytes_written & 1) { - putbit_1 (bs); - } - else - break; - }; - - CLEAR (*bs); - return bytes_written; -} - -#endif - -/////////////////////// Endian Correction Routines //////////////////////////// - -void little_endian_to_native (void *data, char *format) -{ - uchar *cp = (uchar *) data; - int32_t temp; - - while (*format) { - switch (*format) { - case 'L': - temp = cp [0] + ((int32_t) cp [1] << 8) + ((int32_t) cp [2] << 16) + ((int32_t) cp [3] << 24); - * (int32_t *) cp = temp; - cp += 4; - break; - - case 'S': - temp = cp [0] + (cp [1] << 8); - * (short *) cp = (short) temp; - cp += 2; - break; - - default: - if (isdigit (*format)) - cp += *format - '0'; - - break; - } - - format++; - } -} - -void native_to_little_endian (void *data, char *format) -{ - uchar *cp = (uchar *) data; - int32_t temp; - - while (*format) { - switch (*format) { - case 'L': - temp = * (int32_t *) cp; - *cp++ = (uchar) temp; - *cp++ = (uchar) (temp >> 8); - *cp++ = (uchar) (temp >> 16); - *cp++ = (uchar) (temp >> 24); - break; - - case 'S': - temp = * (short *) cp; - *cp++ = (uchar) temp; - *cp++ = (uchar) (temp >> 8); - break; - - default: - if (isdigit (*format)) - cp += *format - '0'; - - break; - } - - format++; - } -} - -////////////////////////// Debug Wrapper for Malloc /////////////////////////// - -#ifdef DEBUG_ALLOC - -void *vptrs [512]; - -static void *add_ptr (void *ptr) -{ - int i; - - for (i = 0; i < 512; ++i) - if (!vptrs [i]) { - vptrs [i] = ptr; - break; - } - - if (i == 512) - error_line ("too many mallocs!"); - - return ptr; -} - -static void *del_ptr (void *ptr) -{ - int i; - - for (i = 0; i < 512; ++i) - if (vptrs [i] == ptr) { - vptrs [i] = NULL; - break; - } - - if (i == 512) - error_line ("free invalid ptr!"); - - return ptr; -} - -void *malloc_db (uint32_t size) -{ - if (size) - return add_ptr (malloc (size)); - else - return NULL; -} - -void free_db (void *ptr) -{ - if (ptr) - free (del_ptr (ptr)); -} - -void *realloc_db (void *ptr, uint32_t size) -{ - if (ptr && size) - return add_ptr (realloc (del_ptr (ptr), size)); - else if (size) - return malloc_db (size); - else - free_db (ptr); - - return NULL; -} - -int32_t dump_alloc (void) -{ - int i, j; - - for (j = i = 0; i < 512; ++i) - if (vptrs [i]) - j++; - - return j; -} - -#endif diff --git a/wavpack-4.5.0/src/extra1.c b/wavpack-4.5.0/src/extra1.c deleted file mode 100644 index 4936fb6..0000000 --- a/wavpack-4.5.0/src/extra1.c +++ /dev/null @@ -1,671 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// **** WAVPACK **** // -// Hybrid Lossless Wavefile Compressor // -// Copyright (c) 1998 - 2006 Conifer Software. // -// All Rights Reserved. // -// Distributed under the BSD Software License (see license.txt) // -//////////////////////////////////////////////////////////////////////////// - -// extra1.c - -// This module handles the "extra" mode for mono files. - -#include "wavpack_local.h" - -#include -#include -#include -#include - -//#define USE_OVERHEAD -#define LOG_LIMIT 6912 -//#define EXTRA_DUMP - -#ifdef DEBUG_ALLOC -#define malloc malloc_db -#define realloc realloc_db -#define free free_db -void *malloc_db (uint32_t size); -void *realloc_db (void *ptr, uint32_t size); -void free_db (void *ptr); -int32_t dump_alloc (void); -#endif - -//////////////////////////////// local tables /////////////////////////////// - -typedef struct { - int32_t *sampleptrs [MAX_NTERMS+2]; - struct decorr_pass dps [MAX_NTERMS]; - int nterms, log_limit; - uint32_t best_bits; -} WavpackExtraInfo; - -static void decorr_mono_pass (int32_t *in_samples, int32_t *out_samples, uint32_t num_samples, struct decorr_pass *dpp, int dir) -{ - int m = 0, i; - - dpp->sum_A = 0; - - if (dir < 0) { - out_samples += (num_samples - 1); - in_samples += (num_samples - 1); - dir = -1; - } - else - dir = 1; - - dpp->weight_A = restore_weight (store_weight (dpp->weight_A)); - - for (i = 0; i < 8; ++i) - dpp->samples_A [i] = exp2s (log2s (dpp->samples_A [i])); - - if (dpp->term > MAX_TERM) { - while (num_samples--) { - int32_t left, sam_A; - - if (dpp->term & 1) - sam_A = 2 * dpp->samples_A [0] - dpp->samples_A [1]; - else - sam_A = (3 * dpp->samples_A [0] - dpp->samples_A [1]) >> 1; - - dpp->samples_A [1] = dpp->samples_A [0]; - dpp->samples_A [0] = left = in_samples [0]; - - left -= apply_weight (dpp->weight_A, sam_A); - update_weight (dpp->weight_A, dpp->delta, sam_A, left); - dpp->sum_A += dpp->weight_A; - out_samples [0] = left; - in_samples += dir; - out_samples += dir; - } - } - else if (dpp->term > 0) { - while (num_samples--) { - int k = (m + dpp->term) & (MAX_TERM - 1); - int32_t left, sam_A; - - sam_A = dpp->samples_A [m]; - dpp->samples_A [k] = left = in_samples [0]; - m = (m + 1) & (MAX_TERM - 1); - - left -= apply_weight (dpp->weight_A, sam_A); - update_weight (dpp->weight_A, dpp->delta, sam_A, left); - dpp->sum_A += dpp->weight_A; - out_samples [0] = left; - in_samples += dir; - out_samples += dir; - } - } - - if (m && dpp->term > 0 && dpp->term <= MAX_TERM) { - int32_t temp_A [MAX_TERM]; - int k; - - memcpy (temp_A, dpp->samples_A, sizeof (dpp->samples_A)); - - for (k = 0; k < MAX_TERM; k++) { - dpp->samples_A [k] = temp_A [m]; - m = (m + 1) & (MAX_TERM - 1); - } - } -} - -static void reverse_mono_decorr (struct decorr_pass *dpp) -{ - if (dpp->term > MAX_TERM) { - int32_t sam_A; - - if (dpp->term & 1) - sam_A = 2 * dpp->samples_A [0] - dpp->samples_A [1]; - else - sam_A = (3 * dpp->samples_A [0] - dpp->samples_A [1]) >> 1; - - dpp->samples_A [1] = dpp->samples_A [0]; - dpp->samples_A [0] = sam_A; - - if (dpp->term & 1) - sam_A = 2 * dpp->samples_A [0] - dpp->samples_A [1]; - else - sam_A = (3 * dpp->samples_A [0] - dpp->samples_A [1]) >> 1; - - dpp->samples_A [1] = sam_A; - } - else if (dpp->term > 1) { - int i = 0, j = dpp->term - 1, cnt = dpp->term / 2; - - while (cnt--) { - i &= (MAX_TERM - 1); - j &= (MAX_TERM - 1); - dpp->samples_A [i] ^= dpp->samples_A [j]; - dpp->samples_A [j] ^= dpp->samples_A [i]; - dpp->samples_A [i++] ^= dpp->samples_A [j--]; - } - -// CLEAR (dpp->samples_A); - } -} - -static void decorr_mono_buffer (int32_t *samples, int32_t *outsamples, uint32_t num_samples, struct decorr_pass *dpp, int tindex) -{ - struct decorr_pass dp, *dppi = dpp + tindex; - int delta = dppi->delta, pre_delta, term = dppi->term; - - if (delta == 7) - pre_delta = 7; - else if (delta < 2) - pre_delta = 3; - else - pre_delta = delta + 1; - - CLEAR (dp); - dp.term = term; - dp.delta = pre_delta; - decorr_mono_pass (samples, outsamples, num_samples > 2048 ? 2048 : num_samples, &dp, -1); - dp.delta = delta; - - if (tindex == 0) - reverse_mono_decorr (&dp); - else - CLEAR (dp.samples_A); - - memcpy (dppi->samples_A, dp.samples_A, sizeof (dp.samples_A)); - dppi->weight_A = dp.weight_A; - - if (delta == 0) { - dp.delta = 1; - decorr_mono_pass (samples, outsamples, num_samples, &dp, 1); - dp.delta = 0; - memcpy (dp.samples_A, dppi->samples_A, sizeof (dp.samples_A)); - dppi->weight_A = dp.weight_A = dp.sum_A / num_samples; - } - -// if (memcmp (dppi, &dp, sizeof (dp))) -// error_line ("decorr_passes don't match, delta = %d", delta); - - decorr_mono_pass (samples, outsamples, num_samples, &dp, 1); -} - -static int log2overhead (int first_term, int num_terms) -{ -#ifdef USE_OVERHEAD - if (first_term > MAX_TERM) - return (4 + num_terms * 2) << 11; - else - return (2 + num_terms * 2) << 11; -#else - return 0; -#endif -} - -static void recurse_mono (WavpackContext *wpc, WavpackExtraInfo *info, int depth, int delta, uint32_t input_bits) -{ - WavpackStream *wps = wpc->streams [wpc->current_stream]; - int term, branches = ((wpc->config.extra_flags & EXTRA_BRANCHES) >> 6) - depth; - int32_t *samples, *outsamples; - uint32_t term_bits [22], bits; - - if (branches < 1 || depth + 1 == info->nterms) - branches = 1; - - CLEAR (term_bits); - samples = info->sampleptrs [depth]; - outsamples = info->sampleptrs [depth + 1]; - - for (term = 1; term <= 18; ++term) { - if (term == 17 && branches == 1 && depth + 1 < info->nterms) - continue; - - if (term > 8 && term < 17) - continue; - - if ((wpc->config.flags & CONFIG_FAST_FLAG) && (term > 4 && term < 17)) - continue; - - info->dps [depth].term = term; - info->dps [depth].delta = delta; - decorr_mono_buffer (samples, outsamples, wps->wphdr.block_samples, info->dps, depth); - bits = log2buffer (outsamples, wps->wphdr.block_samples, info->log_limit); - - if (bits != (uint32_t) -1) - bits += log2overhead (info->dps [0].term, depth + 1); - - if (bits < info->best_bits) { - info->best_bits = bits; - CLEAR (wps->decorr_passes); - memcpy (wps->decorr_passes, info->dps, sizeof (info->dps [0]) * (depth + 1)); - memcpy (info->sampleptrs [info->nterms + 1], info->sampleptrs [depth + 1], wps->wphdr.block_samples * 4); - } - - term_bits [term + 3] = bits; - } - - while (depth + 1 < info->nterms && branches--) { - uint32_t local_best_bits = input_bits; - int best_term = 0, i; - - for (i = 0; i < 22; ++i) - if (term_bits [i] && term_bits [i] < local_best_bits) { - local_best_bits = term_bits [i]; -// term_bits [i] = 0; - best_term = i - 3; - } - - if (!best_term) - break; - - term_bits [best_term + 3] = 0; - - info->dps [depth].term = best_term; - info->dps [depth].delta = delta; - decorr_mono_buffer (samples, outsamples, wps->wphdr.block_samples, info->dps, depth); - -// if (log2buffer (outsamples, wps->wphdr.block_samples * 2, 0) != local_best_bits) -// error_line ("data doesn't match!"); - - recurse_mono (wpc, info, depth + 1, delta, local_best_bits); - } -} - -static void delta_mono (WavpackContext *wpc, WavpackExtraInfo *info) -{ - WavpackStream *wps = wpc->streams [wpc->current_stream]; - int lower = FALSE, delta, d; - uint32_t bits; - - if (wps->decorr_passes [0].term) - delta = wps->decorr_passes [0].delta; - else - return; - - for (d = delta - 1; d >= 0; --d) { - int i; - - if (!d && (wps->wphdr.flags & HYBRID_FLAG)) - break; - - for (i = 0; i < info->nterms && wps->decorr_passes [i].term; ++i) { - info->dps [i].term = wps->decorr_passes [i].term; - info->dps [i].delta = d; - decorr_mono_buffer (info->sampleptrs [i], info->sampleptrs [i+1], wps->wphdr.block_samples, info->dps, i); - } - - bits = log2buffer (info->sampleptrs [i], wps->wphdr.block_samples, info->log_limit); - - if (bits != (uint32_t) -1) - bits += log2overhead (wps->decorr_passes [0].term, i); - - if (bits < info->best_bits) { - lower = TRUE; - info->best_bits = bits; - CLEAR (wps->decorr_passes); - memcpy (wps->decorr_passes, info->dps, sizeof (info->dps [0]) * i); - memcpy (info->sampleptrs [info->nterms + 1], info->sampleptrs [i], wps->wphdr.block_samples * 4); - } - else - break; - } - - for (d = delta + 1; !lower && d <= 7; ++d) { - int i; - - for (i = 0; i < info->nterms && wps->decorr_passes [i].term; ++i) { - info->dps [i].term = wps->decorr_passes [i].term; - info->dps [i].delta = d; - decorr_mono_buffer (info->sampleptrs [i], info->sampleptrs [i+1], wps->wphdr.block_samples, info->dps, i); - } - - bits = log2buffer (info->sampleptrs [i], wps->wphdr.block_samples, info->log_limit); - - if (bits != (uint32_t) -1) - bits += log2overhead (wps->decorr_passes [0].term, i); - - if (bits < info->best_bits) { - info->best_bits = bits; - CLEAR (wps->decorr_passes); - memcpy (wps->decorr_passes, info->dps, sizeof (info->dps [0]) * i); - memcpy (info->sampleptrs [info->nterms + 1], info->sampleptrs [i], wps->wphdr.block_samples * 4); - } - else - break; - } -} - -static void sort_mono (WavpackContext *wpc, WavpackExtraInfo *info) -{ - WavpackStream *wps = wpc->streams [wpc->current_stream]; - int reversed = TRUE; - uint32_t bits; - - while (reversed) { - int ri, i; - - memcpy (info->dps, wps->decorr_passes, sizeof (wps->decorr_passes)); - reversed = FALSE; - - for (ri = 0; ri < info->nterms && wps->decorr_passes [ri].term; ++ri) { - - if (ri + 1 >= info->nterms || !wps->decorr_passes [ri+1].term) - break; - - if (wps->decorr_passes [ri].term == wps->decorr_passes [ri+1].term) { - decorr_mono_buffer (info->sampleptrs [ri], info->sampleptrs [ri+1], wps->wphdr.block_samples, info->dps, ri); - continue; - } - - info->dps [ri] = wps->decorr_passes [ri+1]; - info->dps [ri+1] = wps->decorr_passes [ri]; - - for (i = ri; i < info->nterms && wps->decorr_passes [i].term; ++i) - decorr_mono_buffer (info->sampleptrs [i], info->sampleptrs [i+1], wps->wphdr.block_samples, info->dps, i); - - bits = log2buffer (info->sampleptrs [i], wps->wphdr.block_samples, info->log_limit); - - if (bits != (uint32_t) -1) - bits += log2overhead (wps->decorr_passes [0].term, i); - - if (bits < info->best_bits) { - reversed = TRUE; - info->best_bits = bits; - CLEAR (wps->decorr_passes); - memcpy (wps->decorr_passes, info->dps, sizeof (info->dps [0]) * i); - memcpy (info->sampleptrs [info->nterms + 1], info->sampleptrs [i], wps->wphdr.block_samples * 4); - } - else { - info->dps [ri] = wps->decorr_passes [ri]; - info->dps [ri+1] = wps->decorr_passes [ri+1]; - decorr_mono_buffer (info->sampleptrs [ri], info->sampleptrs [ri+1], wps->wphdr.block_samples, info->dps, ri); - } - } - } -} - -static const uint32_t xtable [] = { 91, 123, 187, 251 }; - -static void analyze_mono (WavpackContext *wpc, int32_t *samples, int do_samples) -{ - WavpackStream *wps = wpc->streams [wpc->current_stream]; - WavpackExtraInfo info; - int i; - -#ifdef LOG_LIMIT - info.log_limit = (((wps->wphdr.flags & MAG_MASK) >> MAG_LSB) + 4) * 256; - - if (info.log_limit > LOG_LIMIT) - info.log_limit = LOG_LIMIT; -#else - info.log_limit = 0; -#endif - - if (wpc->config.flags & (CONFIG_HIGH_FLAG | CONFIG_VERY_HIGH_FLAG)) - wpc->config.extra_flags = xtable [wpc->config.xmode - 4]; - else - wpc->config.extra_flags = xtable [wpc->config.xmode - 3]; - - info.nterms = wps->num_terms; - - for (i = 0; i < info.nterms + 2; ++i) - info.sampleptrs [i] = malloc (wps->wphdr.block_samples * 4); - - memcpy (info.dps, wps->decorr_passes, sizeof (info.dps)); - memcpy (info.sampleptrs [0], samples, wps->wphdr.block_samples * 4); - - for (i = 0; i < info.nterms && info.dps [i].term; ++i) - decorr_mono_pass (info.sampleptrs [i], info.sampleptrs [i + 1], wps->wphdr.block_samples, info.dps + i, 1); - - info.best_bits = log2buffer (info.sampleptrs [info.nterms], wps->wphdr.block_samples, 0) * 1; - info.best_bits += log2overhead (info.dps [0].term, i); - memcpy (info.sampleptrs [info.nterms + 1], info.sampleptrs [i], wps->wphdr.block_samples * 4); - - if (wpc->config.extra_flags & EXTRA_BRANCHES) - recurse_mono (wpc, &info, 0, (int) floor (wps->delta_decay + 0.5), - log2buffer (info.sampleptrs [0], wps->wphdr.block_samples, 0)); - - if (wpc->config.extra_flags & EXTRA_SORT_FIRST) - sort_mono (wpc, &info); - - if (wpc->config.extra_flags & EXTRA_TRY_DELTAS) { - delta_mono (wpc, &info); - - if ((wpc->config.extra_flags & EXTRA_ADJUST_DELTAS) && wps->decorr_passes [0].term) - wps->delta_decay = (float)((wps->delta_decay * 2.0 + wps->decorr_passes [0].delta) / 3.0); - else - wps->delta_decay = 2.0; - } - - if (wpc->config.extra_flags & EXTRA_SORT_LAST) - sort_mono (wpc, &info); - - if (do_samples) - memcpy (samples, info.sampleptrs [info.nterms + 1], wps->wphdr.block_samples * 4); - - for (i = 0; i < info.nterms; ++i) - if (!wps->decorr_passes [i].term) - break; - - wps->num_terms = i; - - for (i = 0; i < info.nterms + 2; ++i) - free (info.sampleptrs [i]); -} - -static void mono_add_noise (WavpackStream *wps, int32_t *lptr, int32_t *rptr) -{ - int shaping_weight, new = wps->wphdr.flags & NEW_SHAPING; - short *shaping_array = wps->dc.shaping_array; - int32_t error = 0, temp, cnt; - - scan_word (wps, rptr, wps->wphdr.block_samples, -1); - cnt = wps->wphdr.block_samples; - - if (wps->wphdr.flags & HYBRID_SHAPE) { - while (cnt--) { - if (shaping_array) - shaping_weight = *shaping_array++; - else - shaping_weight = (wps->dc.shaping_acc [0] += wps->dc.shaping_delta [0]) >> 16; - - temp = -apply_weight (shaping_weight, error); - - if (new && shaping_weight < 0 && temp) { - if (temp == error) - temp = (temp < 0) ? temp + 1 : temp - 1; - - lptr [0] += (error = nosend_word (wps, rptr [0], 0) - rptr [0] + temp); - } - else - lptr [0] += (error = nosend_word (wps, rptr [0], 0) - rptr [0]) + temp; - - lptr++; - rptr++; - } - - if (!shaping_array) - wps->dc.shaping_acc [0] -= wps->dc.shaping_delta [0] * wps->wphdr.block_samples; - } - else - while (cnt--) { - lptr [0] += nosend_word (wps, rptr [0], 0) - rptr [0]; - lptr++; - rptr++; - } -} - -void execute_mono (WavpackContext *wpc, int32_t *samples, int no_history, int do_samples) -{ - int32_t *temp_buffer [2], *best_buffer, *noisy_buffer = NULL; - struct decorr_pass temp_decorr_pass, save_decorr_passes [MAX_NTERMS]; - WavpackStream *wps = wpc->streams [wpc->current_stream]; - int32_t num_samples = wps->wphdr.block_samples; - int32_t buf_size = sizeof (int32_t) * num_samples; - uint32_t best_size = (uint32_t) -1, size; - int log_limit, pi, i; - - for (i = 0; i < num_samples; ++i) - if (samples [i]) - break; - - if (i == num_samples) { - CLEAR (wps->decorr_passes); - wps->num_terms = 0; - init_words (wps); - return; - } - -#ifdef LOG_LIMIT - log_limit = (((wps->wphdr.flags & MAG_MASK) >> MAG_LSB) + 4) * 256; - - if (log_limit > LOG_LIMIT) - log_limit = LOG_LIMIT; -#else - log_limit = 0; -#endif - - CLEAR (save_decorr_passes); - temp_buffer [0] = malloc (buf_size); - temp_buffer [1] = malloc (buf_size); - best_buffer = malloc (buf_size); - - if (wps->num_passes > 1 && (wps->wphdr.flags & HYBRID_FLAG)) { - CLEAR (temp_decorr_pass); - temp_decorr_pass.delta = 2; - temp_decorr_pass.term = 18; - - decorr_mono_pass (samples, temp_buffer [0], - num_samples > 2048 ? 2048 : num_samples, &temp_decorr_pass, -1); - - reverse_mono_decorr (&temp_decorr_pass); - decorr_mono_pass (samples, temp_buffer [0], num_samples, &temp_decorr_pass, 1); - CLEAR (temp_decorr_pass); - temp_decorr_pass.delta = 2; - temp_decorr_pass.term = 17; - - decorr_mono_pass (temp_buffer [0], temp_buffer [1], - num_samples > 2048 ? 2048 : num_samples, &temp_decorr_pass, -1); - - decorr_mono_pass (temp_buffer [0], temp_buffer [1], num_samples, &temp_decorr_pass, 1); - noisy_buffer = malloc (buf_size); - memcpy (noisy_buffer, samples, buf_size); - mono_add_noise (wps, noisy_buffer, temp_buffer [1]); - no_history = 1; - } - - if (no_history || wps->num_passes >= 7) - wps->best_decorr = wps->mask_decorr = 0; - - for (pi = 0; pi < wps->num_passes;) { - const WavpackDecorrSpec *wpds; - int nterms, c, j; - - if (!pi) - c = wps->best_decorr; - else { - if (wps->mask_decorr == 0) - c = 0; - else - c = (wps->best_decorr & (wps->mask_decorr - 1)) | wps->mask_decorr; - - if (c == wps->best_decorr) { - wps->mask_decorr = wps->mask_decorr ? ((wps->mask_decorr << 1) & (wps->num_decorrs - 1)) : 1; - continue; - } - } - - wpds = &wps->decorr_specs [c]; - nterms = (int) strlen (wpds->terms); - - while (1) { - memcpy (temp_buffer [0], noisy_buffer ? noisy_buffer : samples, buf_size); - CLEAR (save_decorr_passes); - - for (j = 0; j < nterms; ++j) { - CLEAR (temp_decorr_pass); - temp_decorr_pass.delta = wpds->delta; - temp_decorr_pass.term = wpds->terms [j]; - - if (temp_decorr_pass.term < 0) - temp_decorr_pass.term = 1; - - decorr_mono_pass (temp_buffer [j&1], temp_buffer [~j&1], - num_samples > 2048 ? 2048 : num_samples, &temp_decorr_pass, -1); - - if (j) { - CLEAR (temp_decorr_pass.samples_A); - } - else - reverse_mono_decorr (&temp_decorr_pass); - - memcpy (save_decorr_passes + j, &temp_decorr_pass, sizeof (struct decorr_pass)); - decorr_mono_pass (temp_buffer [j&1], temp_buffer [~j&1], num_samples, &temp_decorr_pass, 1); - } - - size = log2buffer (temp_buffer [j&1], num_samples, log_limit); - - if (size == (uint32_t) -1 && nterms) - nterms >>= 1; - else - break; - } - - size += log2overhead (wpds->terms [0], nterms); - - if (size < best_size) { - memcpy (best_buffer, temp_buffer [j&1], buf_size); - memcpy (wps->decorr_passes, save_decorr_passes, sizeof (struct decorr_pass) * MAX_NTERMS); - wps->num_terms = nterms; - wps->best_decorr = c; - best_size = size; - } - - if (pi++) - wps->mask_decorr = wps->mask_decorr ? ((wps->mask_decorr << 1) & (wps->num_decorrs - 1)) : 1; - } - - if (wpc->config.xmode > 3) { - if (noisy_buffer) { - analyze_mono (wpc, noisy_buffer, do_samples); - - if (do_samples) - memcpy (samples, noisy_buffer, buf_size); - } - else - analyze_mono (wpc, samples, do_samples); - } - else if (do_samples) - memcpy (samples, best_buffer, buf_size); - - if (no_history || wpc->config.xmode > 3) - scan_word (wps, best_buffer, num_samples, -1); - - if (noisy_buffer) - free (noisy_buffer); - - free (temp_buffer [1]); - free (temp_buffer [0]); - free (best_buffer); - -#ifdef EXTRA_DUMP - if (1) { - char string [256], substring [20]; - int i; - - sprintf (string, "M: terms ="); - - for (i = 0; i < wps->num_terms; ++i) { - if (wps->decorr_passes [i].term) { - if (i && wps->decorr_passes [i-1].delta == wps->decorr_passes [i].delta) - sprintf (substring, " %d", wps->decorr_passes [i].term); - else - sprintf (substring, " %d->%d", wps->decorr_passes [i].term, - wps->decorr_passes [i].delta); - } - else - sprintf (substring, " *"); - - strcat (string, substring); - } - - error_line (string); - } -#endif -} - diff --git a/wavpack-4.5.0/src/extra2.c b/wavpack-4.5.0/src/extra2.c deleted file mode 100644 index 17fcf01..0000000 --- a/wavpack-4.5.0/src/extra2.c +++ /dev/null @@ -1,1355 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// **** WAVPACK **** // -// Hybrid Lossless Wavefile Compressor // -// Copyright (c) 1998 - 2006 Conifer Software. // -// MMX optimizations (c) 2006 Joachim Henke // -// All Rights Reserved. // -// Distributed under the BSD Software License (see license.txt) // -//////////////////////////////////////////////////////////////////////////// - -// extra2.c - -// This module handles the "extra" mode for stereo files. - -#include "wavpack_local.h" - -#include -#include -#include -#include - -//#define USE_OVERHEAD -#define LOG_LIMIT 6912 -//#define EXTRA_DUMP - -#ifdef DEBUG_ALLOC -#define malloc malloc_db -#define realloc realloc_db -#define free free_db -void *malloc_db (uint32_t size); -void *realloc_db (void *ptr, uint32_t size); -void free_db (void *ptr); -int32_t dump_alloc (void); -#endif - -//////////////////////////////// local tables /////////////////////////////// - -typedef struct { - int32_t *sampleptrs [MAX_NTERMS+2]; - struct decorr_pass dps [MAX_NTERMS]; - int nterms, log_limit, gt16bit; - uint32_t best_bits; -} WavpackExtraInfo; - -#ifdef OPT_MMX - -static void decorr_stereo_pass (int32_t *in_samples, int32_t *out_samples, int32_t num_samples, struct decorr_pass *dpp, int dir) -{ - const __m64 - delta = _mm_set1_pi32 (dpp->delta), - fill = _mm_set1_pi32 (0x7bff), - mask = _mm_set1_pi32 (0x7fff), - round = _mm_set1_pi32 (512), - zero = _mm_set1_pi32 (0); - __m64 - sum_AB = zero, - weight_AB = _mm_set_pi32 (restore_weight (store_weight (dpp->weight_B)), restore_weight (store_weight (dpp->weight_A))), - left_right, sam_AB, tmp0, tmp1, samples_AB [MAX_TERM]; - int k, m = 0; - - if (dir < 0) { - out_samples += (num_samples - 1) * 2; - in_samples += (num_samples - 1) * 2; - dir = -2; - } - else - dir = 2; - - for (k = 0; k < MAX_TERM; ++k) { - ((int32_t *) samples_AB) [k * 2] = exp2s (log2s (dpp->samples_A [k])); - ((int32_t *) samples_AB) [k * 2 + 1] = exp2s (log2s (dpp->samples_B [k])); - } - - if (dpp->term > 0) { - if (dpp->term == 17) { - while (num_samples--) { - left_right = *(__m64 *) in_samples; - tmp0 = samples_AB [0]; - sam_AB = _m_paddd (tmp0, tmp0); - sam_AB = _m_psubd (sam_AB, samples_AB [1]); - samples_AB [0] = left_right; - samples_AB [1] = tmp0; - - tmp0 = _m_paddd (sam_AB, sam_AB); - tmp1 = _m_pand (sam_AB, mask); - tmp0 = _m_psrldi (tmp0, 16); - tmp1 = _m_pmaddwd (tmp1, weight_AB); - tmp0 = _m_pmaddwd (tmp0, weight_AB); - tmp1 = _m_paddd (tmp1, round); - tmp0 = _m_pslldi (tmp0, 5); - tmp1 = _m_psradi (tmp1, 10); - left_right = _m_psubd (left_right, tmp0); - left_right = _m_psubd (left_right, tmp1); - - *(__m64 *) out_samples = left_right; - - tmp0 = _m_pxor (sam_AB, left_right); - tmp0 = _m_psradi (tmp0, 31); - tmp1 = _m_pxor (delta, tmp0); - tmp1 = _m_psubd (tmp1, tmp0); - sam_AB = _m_pcmpeqd (sam_AB, zero); - tmp0 = _m_pcmpeqd (left_right, zero); - tmp0 = _m_por (tmp0, sam_AB); - tmp0 = _m_pandn (tmp0, tmp1); - weight_AB = _m_paddd (weight_AB, tmp0); - - sum_AB = _m_paddd (sum_AB, weight_AB); - - in_samples += dir; - out_samples += dir; - } - } - else if (dpp->term == 18) { - while (num_samples--) { - left_right = *(__m64 *) in_samples; - tmp0 = samples_AB [0]; - sam_AB = _m_psubd (tmp0, samples_AB [1]); - sam_AB = _m_psradi (sam_AB, 1); - sam_AB = _m_paddd (sam_AB, tmp0); - samples_AB [0] = left_right; - samples_AB [1] = tmp0; - - tmp0 = _m_paddd (sam_AB, sam_AB); - tmp1 = _m_pand (sam_AB, mask); - tmp0 = _m_psrldi (tmp0, 16); - tmp1 = _m_pmaddwd (tmp1, weight_AB); - tmp0 = _m_pmaddwd (tmp0, weight_AB); - tmp1 = _m_paddd (tmp1, round); - tmp0 = _m_pslldi (tmp0, 5); - tmp1 = _m_psradi (tmp1, 10); - left_right = _m_psubd (left_right, tmp0); - left_right = _m_psubd (left_right, tmp1); - - *(__m64 *) out_samples = left_right; - - tmp0 = _m_pxor (sam_AB, left_right); - tmp0 = _m_psradi (tmp0, 31); - tmp1 = _m_pxor (delta, tmp0); - tmp1 = _m_psubd (tmp1, tmp0); - sam_AB = _m_pcmpeqd (sam_AB, zero); - tmp0 = _m_pcmpeqd (left_right, zero); - tmp0 = _m_por (tmp0, sam_AB); - tmp0 = _m_pandn (tmp0, tmp1); - weight_AB = _m_paddd (weight_AB, tmp0); - - sum_AB = _m_paddd (sum_AB, weight_AB); - - in_samples += dir; - out_samples += dir; - } - } - else { - k = dpp->term & (MAX_TERM - 1); - while (num_samples--) { - left_right = *(__m64 *) in_samples; - sam_AB = samples_AB [m]; - samples_AB [k] = left_right; - - tmp0 = _m_paddd (sam_AB, sam_AB); - tmp1 = _m_pand (sam_AB, mask); - tmp0 = _m_psrldi (tmp0, 16); - tmp1 = _m_pmaddwd (tmp1, weight_AB); - tmp0 = _m_pmaddwd (tmp0, weight_AB); - tmp1 = _m_paddd (tmp1, round); - tmp0 = _m_pslldi (tmp0, 5); - tmp1 = _m_psradi (tmp1, 10); - left_right = _m_psubd (left_right, tmp0); - left_right = _m_psubd (left_right, tmp1); - - *(__m64 *) out_samples = left_right; - - tmp0 = _m_pxor (sam_AB, left_right); - tmp0 = _m_psradi (tmp0, 31); - tmp1 = _m_pxor (delta, tmp0); - tmp1 = _m_psubd (tmp1, tmp0); - sam_AB = _m_pcmpeqd (sam_AB, zero); - tmp0 = _m_pcmpeqd (left_right, zero); - tmp0 = _m_por (tmp0, sam_AB); - tmp0 = _m_pandn (tmp0, tmp1); - weight_AB = _m_paddd (weight_AB, tmp0); - - sum_AB = _m_paddd (sum_AB, weight_AB); - - in_samples += dir; - out_samples += dir; - k = (k + 1) & (MAX_TERM - 1); - m = (m + 1) & (MAX_TERM - 1); - } - } - } - else { - if (dpp->term == -1) { - while (num_samples--) { - left_right = *(__m64 *) in_samples; - sam_AB = samples_AB [0]; - samples_AB [0] = _m_punpckhdq (left_right, sam_AB); - sam_AB = _m_punpckldq (sam_AB, left_right); - - tmp0 = _m_paddd (sam_AB, sam_AB); - tmp1 = _m_pand (sam_AB, mask); - tmp0 = _m_psrldi (tmp0, 16); - tmp1 = _m_pmaddwd (tmp1, weight_AB); - tmp0 = _m_pmaddwd (tmp0, weight_AB); - tmp1 = _m_paddd (tmp1, round); - tmp0 = _m_pslldi (tmp0, 5); - tmp1 = _m_psradi (tmp1, 10); - left_right = _m_psubd (left_right, tmp0); - left_right = _m_psubd (left_right, tmp1); - - *(__m64 *) out_samples = left_right; - - tmp0 = _m_pcmpeqd (sam_AB, zero); - tmp1 = _m_pcmpeqd (left_right, zero); - tmp0 = _m_por (tmp0, tmp1); - tmp0 = _m_pandn (tmp0, delta); - sam_AB = _m_pxor (sam_AB, left_right); - sam_AB = _m_psradi (sam_AB, 31); - tmp1 = _m_psubd (fill, sam_AB); - weight_AB = _m_pxor (weight_AB, sam_AB); - weight_AB = _m_paddd (weight_AB, tmp1); - weight_AB = _m_paddsw (weight_AB, tmp0); - weight_AB = _m_psubd (weight_AB, tmp1); - weight_AB = _m_pxor (weight_AB, sam_AB); - - sum_AB = _m_paddd (sum_AB, weight_AB); - - in_samples += dir; - out_samples += dir; - } - } - else if (dpp->term == -2) { - while (num_samples--) { - left_right = *(__m64 *) in_samples; - sam_AB = samples_AB [0]; - samples_AB [0] = _m_punpckldq (sam_AB, left_right); - sam_AB = _m_punpckhdq (left_right, sam_AB); - - tmp0 = _m_paddd (sam_AB, sam_AB); - tmp1 = _m_pand (sam_AB, mask); - tmp0 = _m_psrldi (tmp0, 16); - tmp1 = _m_pmaddwd (tmp1, weight_AB); - tmp0 = _m_pmaddwd (tmp0, weight_AB); - tmp1 = _m_paddd (tmp1, round); - tmp0 = _m_pslldi (tmp0, 5); - tmp1 = _m_psradi (tmp1, 10); - left_right = _m_psubd (left_right, tmp0); - left_right = _m_psubd (left_right, tmp1); - - *(__m64 *) out_samples = left_right; - - tmp0 = _m_pcmpeqd (sam_AB, zero); - tmp1 = _m_pcmpeqd (left_right, zero); - tmp0 = _m_por (tmp0, tmp1); - tmp0 = _m_pandn (tmp0, delta); - sam_AB = _m_pxor (sam_AB, left_right); - sam_AB = _m_psradi (sam_AB, 31); - tmp1 = _m_psubd (fill, sam_AB); - weight_AB = _m_pxor (weight_AB, sam_AB); - weight_AB = _m_paddd (weight_AB, tmp1); - weight_AB = _m_paddsw (weight_AB, tmp0); - weight_AB = _m_psubd (weight_AB, tmp1); - weight_AB = _m_pxor (weight_AB, sam_AB); - - sum_AB = _m_paddd (sum_AB, weight_AB); - - in_samples += dir; - out_samples += dir; - } - } - else if (dpp->term == -3) { - while (num_samples--) { - left_right = *(__m64 *) in_samples; - sam_AB = samples_AB [0]; - tmp0 = _m_punpckhdq (left_right, left_right); - samples_AB [0] = _m_punpckldq (tmp0, left_right); - - tmp0 = _m_paddd (sam_AB, sam_AB); - tmp1 = _m_pand (sam_AB, mask); - tmp0 = _m_psrldi (tmp0, 16); - tmp1 = _m_pmaddwd (tmp1, weight_AB); - tmp0 = _m_pmaddwd (tmp0, weight_AB); - tmp1 = _m_paddd (tmp1, round); - tmp0 = _m_pslldi (tmp0, 5); - tmp1 = _m_psradi (tmp1, 10); - left_right = _m_psubd (left_right, tmp0); - left_right = _m_psubd (left_right, tmp1); - - *(__m64 *) out_samples = left_right; - - tmp0 = _m_pcmpeqd (sam_AB, zero); - tmp1 = _m_pcmpeqd (left_right, zero); - tmp0 = _m_por (tmp0, tmp1); - tmp0 = _m_pandn (tmp0, delta); - sam_AB = _m_pxor (sam_AB, left_right); - sam_AB = _m_psradi (sam_AB, 31); - tmp1 = _m_psubd (fill, sam_AB); - weight_AB = _m_pxor (weight_AB, sam_AB); - weight_AB = _m_paddd (weight_AB, tmp1); - weight_AB = _m_paddsw (weight_AB, tmp0); - weight_AB = _m_psubd (weight_AB, tmp1); - weight_AB = _m_pxor (weight_AB, sam_AB); - - sum_AB = _m_paddd (sum_AB, weight_AB); - - in_samples += dir; - out_samples += dir; - } - } - } - dpp->sum_A = ((int32_t *) &sum_AB) [0]; - dpp->sum_B = ((int32_t *) &sum_AB) [1]; - dpp->weight_A = ((int32_t *) &weight_AB) [0]; - dpp->weight_B = ((int32_t *) &weight_AB) [1]; - - for (k = 0; k < MAX_TERM; ++k) { - dpp->samples_A [k] = ((int32_t *) samples_AB) [m * 2]; - dpp->samples_B [k] = ((int32_t *) samples_AB) [m * 2 + 1]; - m = (m + 1) & (MAX_TERM - 1); - } - _mm_empty (); -} - -#else - -static void decorr_stereo_pass (int32_t *in_samples, int32_t *out_samples, int32_t num_samples, struct decorr_pass *dpp, int dir) -{ - int m = 0, i; - - dpp->sum_A = dpp->sum_B = 0; - - if (dir < 0) { - out_samples += (num_samples - 1) * 2; - in_samples += (num_samples - 1) * 2; - dir = -2; - } - else - dir = 2; - - dpp->weight_A = restore_weight (store_weight (dpp->weight_A)); - dpp->weight_B = restore_weight (store_weight (dpp->weight_B)); - - for (i = 0; i < 8; ++i) { - dpp->samples_A [i] = exp2s (log2s (dpp->samples_A [i])); - dpp->samples_B [i] = exp2s (log2s (dpp->samples_B [i])); - } - - switch (dpp->term) { - - case 2: - while (num_samples--) { - int32_t sam, tmp; - - sam = dpp->samples_A [0]; - dpp->samples_A [0] = dpp->samples_A [1]; - out_samples [0] = tmp = (dpp->samples_A [1] = in_samples [0]) - apply_weight (dpp->weight_A, sam); - update_weight (dpp->weight_A, dpp->delta, sam, tmp); - dpp->sum_A += dpp->weight_A; - - sam = dpp->samples_B [0]; - dpp->samples_B [0] = dpp->samples_B [1]; - out_samples [1] = tmp = (dpp->samples_B [1] = in_samples [1]) - apply_weight (dpp->weight_B, sam); - update_weight (dpp->weight_B, dpp->delta, sam, tmp); - dpp->sum_B += dpp->weight_B; - - in_samples += dir; - out_samples += dir; - } - - break; - - case 17: - while (num_samples--) { - int32_t sam, tmp; - - sam = 2 * dpp->samples_A [0] - dpp->samples_A [1]; - dpp->samples_A [1] = dpp->samples_A [0]; - out_samples [0] = tmp = (dpp->samples_A [0] = in_samples [0]) - apply_weight (dpp->weight_A, sam); - update_weight (dpp->weight_A, dpp->delta, sam, tmp); - dpp->sum_A += dpp->weight_A; - - sam = 2 * dpp->samples_B [0] - dpp->samples_B [1]; - dpp->samples_B [1] = dpp->samples_B [0]; - out_samples [1] = tmp = (dpp->samples_B [0] = in_samples [1]) - apply_weight (dpp->weight_B, sam); - update_weight (dpp->weight_B, dpp->delta, sam, tmp); - dpp->sum_B += dpp->weight_B; - - in_samples += dir; - out_samples += dir; - } - - break; - - case 18: - while (num_samples--) { - int32_t sam, tmp; - - sam = dpp->samples_A [0] + ((dpp->samples_A [0] - dpp->samples_A [1]) >> 1); - dpp->samples_A [1] = dpp->samples_A [0]; - out_samples [0] = tmp = (dpp->samples_A [0] = in_samples [0]) - apply_weight (dpp->weight_A, sam); - update_weight (dpp->weight_A, dpp->delta, sam, tmp); - dpp->sum_A += dpp->weight_A; - - sam = dpp->samples_B [0] + ((dpp->samples_B [0] - dpp->samples_B [1]) >> 1); - dpp->samples_B [1] = dpp->samples_B [0]; - out_samples [1] = tmp = (dpp->samples_B [0] = in_samples [1]) - apply_weight (dpp->weight_B, sam); - update_weight (dpp->weight_B, dpp->delta, sam, tmp); - dpp->sum_B += dpp->weight_B; - - in_samples += dir; - out_samples += dir; - } - - break; - - default: { - int k = dpp->term & (MAX_TERM - 1); - - while (num_samples--) { - int32_t sam, tmp; - - sam = dpp->samples_A [m]; - out_samples [0] = tmp = (dpp->samples_A [k] = in_samples [0]) - apply_weight (dpp->weight_A, sam); - update_weight (dpp->weight_A, dpp->delta, sam, tmp); - dpp->sum_A += dpp->weight_A; - - sam = dpp->samples_B [m]; - out_samples [1] = tmp = (dpp->samples_B [k] = in_samples [1]) - apply_weight (dpp->weight_B, sam); - update_weight (dpp->weight_B, dpp->delta, sam, tmp); - dpp->sum_B += dpp->weight_B; - - in_samples += dir; - out_samples += dir; - m = (m + 1) & (MAX_TERM - 1); - k = (k + 1) & (MAX_TERM - 1); - } - - if (m) { - int32_t temp_A [MAX_TERM], temp_B [MAX_TERM]; - int k; - - memcpy (temp_A, dpp->samples_A, sizeof (dpp->samples_A)); - memcpy (temp_B, dpp->samples_B, sizeof (dpp->samples_B)); - - for (k = 0; k < MAX_TERM; k++) { - dpp->samples_A [k] = temp_A [m]; - dpp->samples_B [k] = temp_B [m]; - m = (m + 1) & (MAX_TERM - 1); - } - } - - break; - } - - case -1: - while (num_samples--) { - int32_t sam_A, sam_B, tmp; - - sam_A = dpp->samples_A [0]; - out_samples [0] = tmp = (sam_B = in_samples [0]) - apply_weight (dpp->weight_A, sam_A); - update_weight_clip (dpp->weight_A, dpp->delta, sam_A, tmp); - dpp->sum_A += dpp->weight_A; - - out_samples [1] = tmp = (dpp->samples_A [0] = in_samples [1]) - apply_weight (dpp->weight_B, sam_B); - update_weight_clip (dpp->weight_B, dpp->delta, sam_B, tmp); - dpp->sum_B += dpp->weight_B; - - in_samples += dir; - out_samples += dir; - } - - break; - - case -2: - while (num_samples--) { - int32_t sam_A, sam_B, tmp; - - sam_B = dpp->samples_B [0]; - out_samples [1] = tmp = (sam_A = in_samples [1]) - apply_weight (dpp->weight_B, sam_B); - update_weight_clip (dpp->weight_B, dpp->delta, sam_B, tmp); - dpp->sum_B += dpp->weight_B; - - out_samples [0] = tmp = (dpp->samples_B [0] = in_samples [0]) - apply_weight (dpp->weight_A, sam_A); - update_weight_clip (dpp->weight_A, dpp->delta, sam_A, tmp); - dpp->sum_A += dpp->weight_A; - - in_samples += dir; - out_samples += dir; - } - - break; - - case -3: - while (num_samples--) { - int32_t sam_A, sam_B, tmp; - - sam_A = dpp->samples_A [0]; - sam_B = dpp->samples_B [0]; - - dpp->samples_A [0] = tmp = in_samples [1]; - out_samples [1] = tmp -= apply_weight (dpp->weight_B, sam_B); - update_weight_clip (dpp->weight_B, dpp->delta, sam_B, tmp); - dpp->sum_B += dpp->weight_B; - - dpp->samples_B [0] = tmp = in_samples [0]; - out_samples [0] = tmp -= apply_weight (dpp->weight_A, sam_A); - update_weight_clip (dpp->weight_A, dpp->delta, sam_A, tmp); - dpp->sum_A += dpp->weight_A; - - in_samples += dir; - out_samples += dir; - } - - break; - } -} - -#endif - -static void decorr_stereo_pass_quick (int32_t *in_samples, int32_t *out_samples, int32_t num_samples, struct decorr_pass *dpp, int dir) -{ - int m = 0, i; - - if (dir < 0) { - out_samples += (num_samples - 1) * 2; - in_samples += (num_samples - 1) * 2; - dir = -2; - } - else - dir = 2; - - dpp->weight_A = restore_weight (store_weight (dpp->weight_A)); - dpp->weight_B = restore_weight (store_weight (dpp->weight_B)); - - for (i = 0; i < 8; ++i) { - dpp->samples_A [i] = exp2s (log2s (dpp->samples_A [i])); - dpp->samples_B [i] = exp2s (log2s (dpp->samples_B [i])); - } - - switch (dpp->term) { - - case 2: - while (num_samples--) { - int32_t sam, tmp; - - sam = dpp->samples_A [0]; - dpp->samples_A [0] = dpp->samples_A [1]; - out_samples [0] = tmp = (dpp->samples_A [1] = in_samples [0]) - apply_weight_i (dpp->weight_A, sam); - update_weight (dpp->weight_A, dpp->delta, sam, tmp); - - sam = dpp->samples_B [0]; - dpp->samples_B [0] = dpp->samples_B [1]; - out_samples [1] = tmp = (dpp->samples_B [1] = in_samples [1]) - apply_weight_i (dpp->weight_B, sam); - update_weight (dpp->weight_B, dpp->delta, sam, tmp); - - in_samples += dir; - out_samples += dir; - } - - break; - - case 17: - while (num_samples--) { - int32_t sam, tmp; - - sam = 2 * dpp->samples_A [0] - dpp->samples_A [1]; - dpp->samples_A [1] = dpp->samples_A [0]; - out_samples [0] = tmp = (dpp->samples_A [0] = in_samples [0]) - apply_weight_i (dpp->weight_A, sam); - update_weight (dpp->weight_A, dpp->delta, sam, tmp); - - sam = 2 * dpp->samples_B [0] - dpp->samples_B [1]; - dpp->samples_B [1] = dpp->samples_B [0]; - out_samples [1] = tmp = (dpp->samples_B [0] = in_samples [1]) - apply_weight_i (dpp->weight_B, sam); - update_weight (dpp->weight_B, dpp->delta, sam, tmp); - - in_samples += dir; - out_samples += dir; - } - - break; - - case 18: - while (num_samples--) { - int32_t sam, tmp; - - sam = dpp->samples_A [0] + ((dpp->samples_A [0] - dpp->samples_A [1]) >> 1); - dpp->samples_A [1] = dpp->samples_A [0]; - out_samples [0] = tmp = (dpp->samples_A [0] = in_samples [0]) - apply_weight_i (dpp->weight_A, sam); - update_weight (dpp->weight_A, dpp->delta, sam, tmp); - - sam = dpp->samples_B [0] + ((dpp->samples_B [0] - dpp->samples_B [1]) >> 1); - dpp->samples_B [1] = dpp->samples_B [0]; - out_samples [1] = tmp = (dpp->samples_B [0] = in_samples [1]) - apply_weight_i (dpp->weight_B, sam); - update_weight (dpp->weight_B, dpp->delta, sam, tmp); - - in_samples += dir; - out_samples += dir; - } - - break; - - default: { - int k = dpp->term & (MAX_TERM - 1); - - while (num_samples--) { - int32_t sam, tmp; - - sam = dpp->samples_A [m]; - out_samples [0] = tmp = (dpp->samples_A [k] = in_samples [0]) - apply_weight_i (dpp->weight_A, sam); - update_weight (dpp->weight_A, dpp->delta, sam, tmp); - - sam = dpp->samples_B [m]; - out_samples [1] = tmp = (dpp->samples_B [k] = in_samples [1]) - apply_weight_i (dpp->weight_B, sam); - update_weight (dpp->weight_B, dpp->delta, sam, tmp); - - in_samples += dir; - out_samples += dir; - m = (m + 1) & (MAX_TERM - 1); - k = (k + 1) & (MAX_TERM - 1); - } - - if (m) { - int32_t temp_A [MAX_TERM], temp_B [MAX_TERM]; - int k; - - memcpy (temp_A, dpp->samples_A, sizeof (dpp->samples_A)); - memcpy (temp_B, dpp->samples_B, sizeof (dpp->samples_B)); - - for (k = 0; k < MAX_TERM; k++) { - dpp->samples_A [k] = temp_A [m]; - dpp->samples_B [k] = temp_B [m]; - m = (m + 1) & (MAX_TERM - 1); - } - } - - break; - } - - case -1: - while (num_samples--) { - int32_t sam_A, sam_B, tmp; - - sam_A = dpp->samples_A [0]; - out_samples [0] = tmp = (sam_B = in_samples [0]) - apply_weight_i (dpp->weight_A, sam_A); - update_weight_clip (dpp->weight_A, dpp->delta, sam_A, tmp); - - out_samples [1] = tmp = (dpp->samples_A [0] = in_samples [1]) - apply_weight_i (dpp->weight_B, sam_B); - update_weight_clip (dpp->weight_B, dpp->delta, sam_B, tmp); - - in_samples += dir; - out_samples += dir; - } - - break; - - case -2: - while (num_samples--) { - int32_t sam_A, sam_B, tmp; - - sam_B = dpp->samples_B [0]; - out_samples [1] = tmp = (sam_A = in_samples [1]) - apply_weight_i (dpp->weight_B, sam_B); - update_weight_clip (dpp->weight_B, dpp->delta, sam_B, tmp); - - out_samples [0] = tmp = (dpp->samples_B [0] = in_samples [0]) - apply_weight_i (dpp->weight_A, sam_A); - update_weight_clip (dpp->weight_A, dpp->delta, sam_A, tmp); - - in_samples += dir; - out_samples += dir; - } - - break; - - case -3: - while (num_samples--) { - int32_t sam_A, sam_B, tmp; - - sam_A = dpp->samples_A [0]; - sam_B = dpp->samples_B [0]; - - dpp->samples_A [0] = tmp = in_samples [1]; - out_samples [1] = tmp -= apply_weight_i (dpp->weight_B, sam_B); - update_weight_clip (dpp->weight_B, dpp->delta, sam_B, tmp); - - dpp->samples_B [0] = tmp = in_samples [0]; - out_samples [0] = tmp -= apply_weight_i (dpp->weight_A, sam_A); - update_weight_clip (dpp->weight_A, dpp->delta, sam_A, tmp); - - in_samples += dir; - out_samples += dir; - } - - break; - } -} - -static void reverse_decorr (struct decorr_pass *dpp) -{ - if (dpp->term > MAX_TERM) { - int32_t sam_A, sam_B; - - if (dpp->term & 1) { - sam_A = 2 * dpp->samples_A [0] - dpp->samples_A [1]; - sam_B = 2 * dpp->samples_B [0] - dpp->samples_B [1]; - } - else { - sam_A = (3 * dpp->samples_A [0] - dpp->samples_A [1]) >> 1; - sam_B = (3 * dpp->samples_B [0] - dpp->samples_B [1]) >> 1; - } - - dpp->samples_A [1] = dpp->samples_A [0]; - dpp->samples_B [1] = dpp->samples_B [0]; - dpp->samples_A [0] = sam_A; - dpp->samples_B [0] = sam_B; - - if (dpp->term & 1) { - sam_A = 2 * dpp->samples_A [0] - dpp->samples_A [1]; - sam_B = 2 * dpp->samples_B [0] - dpp->samples_B [1]; - } - else { - sam_A = (3 * dpp->samples_A [0] - dpp->samples_A [1]) >> 1; - sam_B = (3 * dpp->samples_B [0] - dpp->samples_B [1]) >> 1; - } - - dpp->samples_A [1] = sam_A; - dpp->samples_B [1] = sam_B; - } - else if (dpp->term > 1) { - int i = 0, j = dpp->term - 1, cnt = dpp->term / 2; - - while (cnt--) { - i &= (MAX_TERM - 1); - j &= (MAX_TERM - 1); - dpp->samples_A [i] ^= dpp->samples_A [j]; - dpp->samples_A [j] ^= dpp->samples_A [i]; - dpp->samples_A [i] ^= dpp->samples_A [j]; - dpp->samples_B [i] ^= dpp->samples_B [j]; - dpp->samples_B [j] ^= dpp->samples_B [i]; - dpp->samples_B [i++] ^= dpp->samples_B [j--]; - } - } - else if (dpp->term == -1) { - } - else if (dpp->term == -2) { - } - else if (dpp->term == -3) { - } -} - -static void decorr_stereo_buffer (WavpackExtraInfo *info, int32_t *samples, int32_t *outsamples, int32_t num_samples, int tindex) -{ - struct decorr_pass dp, *dppi = info->dps + tindex; - int delta = dppi->delta, pre_delta; - int term = dppi->term; - - if (delta == 7) - pre_delta = 7; - else if (delta < 2) - pre_delta = 3; - else - pre_delta = delta + 1; - - CLEAR (dp); - dp.term = term; - dp.delta = pre_delta; - decorr_stereo_pass (samples, outsamples, num_samples > 2048 ? 2048 : num_samples, &dp, -1); - dp.delta = delta; - - if (tindex == 0) - reverse_decorr (&dp); - else { - CLEAR (dp.samples_A); - CLEAR (dp.samples_B); - } - - memcpy (dppi->samples_A, dp.samples_A, sizeof (dp.samples_A)); - memcpy (dppi->samples_B, dp.samples_B, sizeof (dp.samples_B)); - dppi->weight_A = dp.weight_A; - dppi->weight_B = dp.weight_B; - - if (delta == 0) { - dp.delta = 1; - decorr_stereo_pass (samples, outsamples, num_samples, &dp, 1); - dp.delta = 0; - memcpy (dp.samples_A, dppi->samples_A, sizeof (dp.samples_A)); - memcpy (dp.samples_B, dppi->samples_B, sizeof (dp.samples_B)); - dppi->weight_A = dp.weight_A = dp.sum_A / num_samples; - dppi->weight_B = dp.weight_B = dp.sum_B / num_samples; - } - -// if (memcmp (dppi, &dp, sizeof (dp))) -// error_line ("decorr_passes don't match, delta = %d", delta); - - if (info->gt16bit) - decorr_stereo_pass (samples, outsamples, num_samples, &dp, 1); - else - decorr_stereo_pass_quick (samples, outsamples, num_samples, &dp, 1); -} - -static int log2overhead (int first_term, int num_terms) -{ -#ifdef USE_OVERHEAD - if (first_term > MAX_TERM) - return (8 + num_terms * 3) << 11; - else - return (4 + num_terms * 3) << 11; -#else - return 0; -#endif -} - -static void recurse_stereo (WavpackContext *wpc, WavpackExtraInfo *info, int depth, int delta, uint32_t input_bits) -{ - WavpackStream *wps = wpc->streams [wpc->current_stream]; - int term, branches = ((wpc->config.extra_flags & EXTRA_BRANCHES) >> 6) - depth; - int32_t *samples, *outsamples; - uint32_t term_bits [22], bits; - - if (branches < 1 || depth + 1 == info->nterms) - branches = 1; - - CLEAR (term_bits); - samples = info->sampleptrs [depth]; - outsamples = info->sampleptrs [depth + 1]; - - for (term = -3; term <= 18; ++term) { - if (!term || (term > 8 && term < 17)) - continue; - - if (term == 17 && branches == 1 && depth + 1 < info->nterms) - continue; - - if (term == -1 || term == -2) - if (!(wps->wphdr.flags & CROSS_DECORR)) - continue; - - if ((wpc->config.flags & CONFIG_FAST_FLAG) && (term > 4 && term < 17)) - continue; - - info->dps [depth].term = term; - info->dps [depth].delta = delta; - decorr_stereo_buffer (info, samples, outsamples, wps->wphdr.block_samples, depth); - bits = log2buffer (outsamples, wps->wphdr.block_samples * 2, info->log_limit); - - if (bits != (uint32_t) -1) - bits += log2overhead (info->dps [0].term, depth + 1); - - if (bits < info->best_bits) { - info->best_bits = bits; - CLEAR (wps->decorr_passes); - memcpy (wps->decorr_passes, info->dps, sizeof (info->dps [0]) * (depth + 1)); - memcpy (info->sampleptrs [info->nterms + 1], info->sampleptrs [depth + 1], wps->wphdr.block_samples * 8); - } - - term_bits [term + 3] = bits; - } - - while (depth + 1 < info->nterms && branches--) { - uint32_t local_best_bits = input_bits; - int best_term = 0, i; - - for (i = 0; i < 22; ++i) - if (term_bits [i] && term_bits [i] < local_best_bits) { - local_best_bits = term_bits [i]; -// term_bits [i] = 0; - best_term = i - 3; - } - - if (!best_term) - break; - - term_bits [best_term + 3] = 0; - - info->dps [depth].term = best_term; - info->dps [depth].delta = delta; - decorr_stereo_buffer (info, samples, outsamples, wps->wphdr.block_samples, depth); - -// if (log2buffer (outsamples, wps->wphdr.block_samples * 2, 0) != local_best_bits) -// error_line ("data doesn't match!"); - - recurse_stereo (wpc, info, depth + 1, delta, local_best_bits); - } -} - -static void delta_stereo (WavpackContext *wpc, WavpackExtraInfo *info) -{ - WavpackStream *wps = wpc->streams [wpc->current_stream]; - int lower = FALSE; - int delta, d; - uint32_t bits; - - if (wps->decorr_passes [0].term) - delta = wps->decorr_passes [0].delta; - else - return; - - for (d = delta - 1; d >= 0; --d) { - int i; - - if (!d && (wps->wphdr.flags & HYBRID_FLAG)) - break; - - for (i = 0; i < info->nterms && wps->decorr_passes [i].term; ++i) { - info->dps [i].term = wps->decorr_passes [i].term; - info->dps [i].delta = d; - decorr_stereo_buffer (info, info->sampleptrs [i], info->sampleptrs [i+1], wps->wphdr.block_samples, i); - } - - bits = log2buffer (info->sampleptrs [i], wps->wphdr.block_samples * 2, info->log_limit); - - if (bits != (uint32_t) -1) - bits += log2overhead (wps->decorr_passes [0].term, i); - - if (bits < info->best_bits) { - lower = TRUE; - info->best_bits = bits; - CLEAR (wps->decorr_passes); - memcpy (wps->decorr_passes, info->dps, sizeof (info->dps [0]) * i); - memcpy (info->sampleptrs [info->nterms + 1], info->sampleptrs [i], wps->wphdr.block_samples * 8); - } - else - break; - } - - for (d = delta + 1; !lower && d <= 7; ++d) { - int i; - - for (i = 0; i < info->nterms && wps->decorr_passes [i].term; ++i) { - info->dps [i].term = wps->decorr_passes [i].term; - info->dps [i].delta = d; - decorr_stereo_buffer (info, info->sampleptrs [i], info->sampleptrs [i+1], wps->wphdr.block_samples, i); - } - - bits = log2buffer (info->sampleptrs [i], wps->wphdr.block_samples * 2, info->log_limit); - - if (bits != (uint32_t) -1) - bits += log2overhead (wps->decorr_passes [0].term, i); - - if (bits < info->best_bits) { - info->best_bits = bits; - CLEAR (wps->decorr_passes); - memcpy (wps->decorr_passes, info->dps, sizeof (info->dps [0]) * i); - memcpy (info->sampleptrs [info->nterms + 1], info->sampleptrs [i], wps->wphdr.block_samples * 8); - } - else - break; - } -} - -static void sort_stereo (WavpackContext *wpc, WavpackExtraInfo *info) -{ - WavpackStream *wps = wpc->streams [wpc->current_stream]; - int reversed = TRUE; - uint32_t bits; - - while (reversed) { - int ri, i; - - memcpy (info->dps, wps->decorr_passes, sizeof (wps->decorr_passes)); - reversed = FALSE; - - for (ri = 0; ri < info->nterms && wps->decorr_passes [ri].term; ++ri) { - - if (ri + 1 >= info->nterms || !wps->decorr_passes [ri+1].term) - break; - - if (wps->decorr_passes [ri].term == wps->decorr_passes [ri+1].term) { - decorr_stereo_buffer (info, info->sampleptrs [ri], info->sampleptrs [ri+1], wps->wphdr.block_samples, ri); - continue; - } - - info->dps [ri] = wps->decorr_passes [ri+1]; - info->dps [ri+1] = wps->decorr_passes [ri]; - - for (i = ri; i < info->nterms && wps->decorr_passes [i].term; ++i) - decorr_stereo_buffer (info, info->sampleptrs [i], info->sampleptrs [i+1], wps->wphdr.block_samples, i); - - bits = log2buffer (info->sampleptrs [i], wps->wphdr.block_samples * 2, info->log_limit); - - if (bits != (uint32_t) -1) - bits += log2overhead (wps->decorr_passes [0].term, i); - - if (bits < info->best_bits) { - reversed = TRUE; - info->best_bits = bits; - CLEAR (wps->decorr_passes); - memcpy (wps->decorr_passes, info->dps, sizeof (info->dps [0]) * i); - memcpy (info->sampleptrs [info->nterms + 1], info->sampleptrs [i], wps->wphdr.block_samples * 8); - } - else { - info->dps [ri] = wps->decorr_passes [ri]; - info->dps [ri+1] = wps->decorr_passes [ri+1]; - decorr_stereo_buffer (info, info->sampleptrs [ri], info->sampleptrs [ri+1], wps->wphdr.block_samples, ri); - } - } - } -} - -static const uint32_t xtable [] = { 91, 123, 187, 251 }; - -static void analyze_stereo (WavpackContext *wpc, int32_t *samples, int do_samples) -{ - WavpackStream *wps = wpc->streams [wpc->current_stream]; - WavpackExtraInfo info; - int i; - - info.gt16bit = ((wps->wphdr.flags & MAG_MASK) >> MAG_LSB) >= 16; - -#ifdef LOG_LIMIT - info.log_limit = (((wps->wphdr.flags & MAG_MASK) >> MAG_LSB) + 4) * 256; - - if (info.log_limit > LOG_LIMIT) - info.log_limit = LOG_LIMIT; -#else - info.log_limit = 0; -#endif - - if (wpc->config.flags & (CONFIG_HIGH_FLAG | CONFIG_VERY_HIGH_FLAG)) - wpc->config.extra_flags = xtable [wpc->config.xmode - 4]; - else - wpc->config.extra_flags = xtable [wpc->config.xmode - 3]; - - info.nterms = wps->num_terms; - - for (i = 0; i < info.nterms + 2; ++i) - info.sampleptrs [i] = malloc (wps->wphdr.block_samples * 8); - - memcpy (info.dps, wps->decorr_passes, sizeof (info.dps)); - memcpy (info.sampleptrs [0], samples, wps->wphdr.block_samples * 8); - - for (i = 0; i < info.nterms && info.dps [i].term; ++i) - if (info.gt16bit) - decorr_stereo_pass (info.sampleptrs [i], info.sampleptrs [i + 1], wps->wphdr.block_samples, info.dps + i, 1); - else - decorr_stereo_pass_quick (info.sampleptrs [i], info.sampleptrs [i + 1], wps->wphdr.block_samples, info.dps + i, 1); - - info.best_bits = log2buffer (info.sampleptrs [info.nterms], wps->wphdr.block_samples * 2, 0) * 1; - info.best_bits += log2overhead (info.dps [0].term, i); - memcpy (info.sampleptrs [info.nterms + 1], info.sampleptrs [i], wps->wphdr.block_samples * 8); - - if (wpc->config.extra_flags & EXTRA_BRANCHES) - recurse_stereo (wpc, &info, 0, (int) floor (wps->delta_decay + 0.5), - log2buffer (info.sampleptrs [0], wps->wphdr.block_samples * 2, 0)); - - if (wpc->config.extra_flags & EXTRA_SORT_FIRST) - sort_stereo (wpc, &info); - - if (wpc->config.extra_flags & EXTRA_TRY_DELTAS) { - delta_stereo (wpc, &info); - - if ((wpc->config.extra_flags & EXTRA_ADJUST_DELTAS) && wps->decorr_passes [0].term) - wps->delta_decay = (float)((wps->delta_decay * 2.0 + wps->decorr_passes [0].delta) / 3.0); - else - wps->delta_decay = 2.0; - } - - if (wpc->config.extra_flags & EXTRA_SORT_LAST) - sort_stereo (wpc, &info); - - if (do_samples) - memcpy (samples, info.sampleptrs [info.nterms + 1], wps->wphdr.block_samples * 8); - - for (i = 0; i < info.nterms; ++i) - if (!wps->decorr_passes [i].term) - break; - - wps->num_terms = i; - - for (i = 0; i < info.nterms + 2; ++i) - free (info.sampleptrs [i]); -} - -static void stereo_add_noise (WavpackStream *wps, int32_t *lptr, int32_t *rptr) -{ - int shaping_weight, new = wps->wphdr.flags & NEW_SHAPING; - short *shaping_array = wps->dc.shaping_array; - int32_t error [2], temp, cnt; - - scan_word (wps, rptr, wps->wphdr.block_samples, -1); - cnt = wps->wphdr.block_samples; - CLEAR (error); - - if (wps->wphdr.flags & HYBRID_SHAPE) { - while (cnt--) { - if (shaping_array) - shaping_weight = *shaping_array++; - else - shaping_weight = (wps->dc.shaping_acc [0] += wps->dc.shaping_delta [0]) >> 16; - - temp = -apply_weight (shaping_weight, error [0]); - - if (new && shaping_weight < 0 && temp) { - if (temp == error [0]) - temp = (temp < 0) ? temp + 1 : temp - 1; - - lptr [0] += (error [0] = nosend_word (wps, rptr [0], 0) - rptr [0] + temp); - } - else - lptr [0] += (error [0] = nosend_word (wps, rptr [0], 0) - rptr [0]) + temp; - - if (!shaping_array) - shaping_weight = (wps->dc.shaping_acc [1] += wps->dc.shaping_delta [1]) >> 16; - - temp = -apply_weight (shaping_weight, error [1]); - - if (new && shaping_weight < 0 && temp) { - if (temp == error [1]) - temp = (temp < 0) ? temp + 1 : temp - 1; - - lptr [1] += (error [1] = nosend_word (wps, rptr [1], 1) - rptr [1] + temp); - } - else - lptr [1] += (error [1] = nosend_word (wps, rptr [1], 1) - rptr [1]) + temp; - - lptr += 2; - rptr += 2; - } - - if (!shaping_array) { - wps->dc.shaping_acc [0] -= wps->dc.shaping_delta [0] * wps->wphdr.block_samples; - wps->dc.shaping_acc [1] -= wps->dc.shaping_delta [1] * wps->wphdr.block_samples; - } - } - else - while (cnt--) { - lptr [0] += nosend_word (wps, rptr [0], 0) - rptr [0]; - lptr [1] += nosend_word (wps, rptr [1], 1) - rptr [1]; - lptr += 2; - rptr += 2; - } -} - -void execute_stereo (WavpackContext *wpc, int32_t *samples, int no_history, int do_samples) -{ - int32_t *temp_buffer [2], *best_buffer, *noisy_buffer = NULL, *js_buffer = NULL; - struct decorr_pass temp_decorr_pass, save_decorr_passes [MAX_NTERMS]; - WavpackStream *wps = wpc->streams [wpc->current_stream]; - int32_t num_samples = wps->wphdr.block_samples; - int32_t buf_size = sizeof (int32_t) * num_samples * 2; - uint32_t best_size = (uint32_t) -1, size; - int log_limit, force_js = 0, force_ts = 0, pi, i; - - for (i = 0; i < num_samples * 2; ++i) - if (samples [i]) - break; - - if (i == num_samples * 2) { - wps->wphdr.flags &= ~((uint32_t) JOINT_STEREO); - CLEAR (wps->decorr_passes); - wps->num_terms = 0; - init_words (wps); - return; - } - -#ifdef LOG_LIMIT - log_limit = (((wps->wphdr.flags & MAG_MASK) >> MAG_LSB) + 4) * 256; - - if (log_limit > LOG_LIMIT) - log_limit = LOG_LIMIT; -#else - log_limit = 0; -#endif - - if (wpc->config.flags & CONFIG_JOINT_OVERRIDE) { - if (wps->wphdr.flags & JOINT_STEREO) - force_js = 1; - else - force_ts = 1; - } - - CLEAR (save_decorr_passes); - temp_buffer [0] = malloc (buf_size); - temp_buffer [1] = malloc (buf_size); - best_buffer = malloc (buf_size); - - if (wps->num_passes > 1 && (wps->wphdr.flags & HYBRID_FLAG)) { - CLEAR (temp_decorr_pass); - temp_decorr_pass.delta = 2; - temp_decorr_pass.term = 18; - - decorr_stereo_pass (samples, temp_buffer [0], - num_samples > 2048 ? 2048 : num_samples, &temp_decorr_pass, -1); - - reverse_decorr (&temp_decorr_pass); - decorr_stereo_pass (samples, temp_buffer [0], num_samples, &temp_decorr_pass, 1); - CLEAR (temp_decorr_pass); - temp_decorr_pass.delta = 2; - temp_decorr_pass.term = 17; - - decorr_stereo_pass (temp_buffer [0], temp_buffer [1], - num_samples > 2048 ? 2048 : num_samples, &temp_decorr_pass, -1); - - decorr_stereo_pass (temp_buffer [0], temp_buffer [1], num_samples, &temp_decorr_pass, 1); - noisy_buffer = malloc (buf_size); - memcpy (noisy_buffer, samples, buf_size); - stereo_add_noise (wps, noisy_buffer, temp_buffer [1]); - no_history = 1; - } - - if (no_history || wps->num_passes >= 7) - wps->best_decorr = wps->mask_decorr = 0; - - for (pi = 0; pi < wps->num_passes;) { - const WavpackDecorrSpec *wpds; - int nterms, c, j; - - if (!pi) - c = wps->best_decorr; - else { - if (wps->mask_decorr == 0) - c = 0; - else - c = (wps->best_decorr & (wps->mask_decorr - 1)) | wps->mask_decorr; - - if (c == wps->best_decorr) { - wps->mask_decorr = wps->mask_decorr ? ((wps->mask_decorr << 1) & (wps->num_decorrs - 1)) : 1; - continue; - } - } - - wpds = &wps->decorr_specs [c]; - nterms = (int) strlen (wpds->terms); - - while (1) { - if (force_js || (wpds->joint_stereo && !force_ts)) { - if (!js_buffer) { - int32_t *lptr, cnt = num_samples; - - lptr = js_buffer = malloc (buf_size); - memcpy (js_buffer, noisy_buffer ? noisy_buffer : samples, buf_size); - - while (cnt--) { - lptr [1] += ((lptr [0] -= lptr [1]) >> 1); - lptr += 2; - } - } - - memcpy (temp_buffer [0], js_buffer, buf_size); - } - else - memcpy (temp_buffer [0], noisy_buffer ? noisy_buffer : samples, buf_size); - - CLEAR (save_decorr_passes); - - for (j = 0; j < nterms; ++j) { - CLEAR (temp_decorr_pass); - temp_decorr_pass.delta = wpds->delta; - temp_decorr_pass.term = wpds->terms [j]; - - if (temp_decorr_pass.term < 0 && !(wps->wphdr.flags & CROSS_DECORR)) - temp_decorr_pass.term = -3; - - decorr_stereo_pass (temp_buffer [j&1], temp_buffer [~j&1], - num_samples > 2048 ? 2048 : num_samples, &temp_decorr_pass, -1); - - if (j) { - CLEAR (temp_decorr_pass.samples_A); - CLEAR (temp_decorr_pass.samples_B); - } - else - reverse_decorr (&temp_decorr_pass); - - memcpy (save_decorr_passes + j, &temp_decorr_pass, sizeof (struct decorr_pass)); - - if (((wps->wphdr.flags & MAG_MASK) >> MAG_LSB) >= 16) - decorr_stereo_pass (temp_buffer [j&1], temp_buffer [~j&1], num_samples, &temp_decorr_pass, 1); - else - decorr_stereo_pass_quick (temp_buffer [j&1], temp_buffer [~j&1], num_samples, &temp_decorr_pass, 1); - } - - size = log2buffer (temp_buffer [j&1], num_samples * 2, log_limit); - - if (size == (uint32_t) -1 && nterms) - nterms >>= 1; - else - break; - } - - size += log2overhead (wpds->terms [0], nterms); - - if (size < best_size) { - memcpy (best_buffer, temp_buffer [j&1], buf_size); - memcpy (wps->decorr_passes, save_decorr_passes, sizeof (struct decorr_pass) * MAX_NTERMS); - wps->num_terms = nterms; - wps->best_decorr = c; - best_size = size; - } - - if (pi++) - wps->mask_decorr = wps->mask_decorr ? ((wps->mask_decorr << 1) & (wps->num_decorrs - 1)) : 1; - } - - if (force_js || (wps->decorr_specs [wps->best_decorr].joint_stereo && !force_ts)) - wps->wphdr.flags |= JOINT_STEREO; - else - wps->wphdr.flags &= ~((uint32_t) JOINT_STEREO); - - if (wpc->config.xmode > 3) { - if (wps->wphdr.flags & JOINT_STEREO) { - analyze_stereo (wpc, js_buffer, do_samples); - - if (do_samples) - memcpy (samples, js_buffer, buf_size); - } - else if (noisy_buffer) { - analyze_stereo (wpc, noisy_buffer, do_samples); - - if (do_samples) - memcpy (samples, noisy_buffer, buf_size); - } - else - analyze_stereo (wpc, samples, do_samples); - } - else if (do_samples) - memcpy (samples, best_buffer, buf_size); - - if (wpc->config.xmode > 3 || no_history || wps->joint_stereo != wps->decorr_specs [wps->best_decorr].joint_stereo) { - wps->joint_stereo = wps->decorr_specs [wps->best_decorr].joint_stereo; - scan_word (wps, best_buffer, num_samples, -1); - } - - if (noisy_buffer) - free (noisy_buffer); - - if (js_buffer) - free (js_buffer); - - free (temp_buffer [1]); - free (temp_buffer [0]); - free (best_buffer); - -#ifdef EXTRA_DUMP - if (1) { - char string [256], substring [20]; - int i; - - sprintf (string, "%s: terms =", - (wps->wphdr.flags & JOINT_STEREO) ? "JS" : "TS"); - - for (i = 0; i < wps->num_terms; ++i) { - if (wps->decorr_passes [i].term) { - if (i && wps->decorr_passes [i-1].delta == wps->decorr_passes [i].delta) - sprintf (substring, " %d", wps->decorr_passes [i].term); - else - sprintf (substring, " %d->%d", wps->decorr_passes [i].term, - wps->decorr_passes [i].delta); - } - else - sprintf (substring, " *"); - - strcat (string, substring); - } - - error_line (string); - } -#endif -} - diff --git a/wavpack-4.5.0/src/float.c b/wavpack-4.5.0/src/float.c deleted file mode 100644 index a01cfb3..0000000 --- a/wavpack-4.5.0/src/float.c +++ /dev/null @@ -1,371 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// **** WAVPACK **** // -// Hybrid Lossless Wavefile Compressor // -// Copyright (c) 1998 - 2006 Conifer Software. // -// All Rights Reserved. // -// Distributed under the BSD Software License (see license.txt) // -//////////////////////////////////////////////////////////////////////////// - -// float.c - -#include "wavpack_local.h" - -#include - -#ifdef DEBUG_ALLOC -#define malloc malloc_db -#define realloc realloc_db -#define free free_db -void *malloc_db (uint32_t size); -void *realloc_db (void *ptr, uint32_t size); -void free_db (void *ptr); -int32_t dump_alloc (void); -#endif - -#ifndef NO_PACK - -void write_float_info (WavpackStream *wps, WavpackMetadata *wpmd) -{ - char *byteptr; - - byteptr = wpmd->data = malloc (4); - wpmd->id = ID_FLOAT_INFO; - *byteptr++ = wps->float_flags; - *byteptr++ = wps->float_shift; - *byteptr++ = wps->float_max_exp; - *byteptr++ = wps->float_norm_exp; - wpmd->byte_length = (int32_t)(byteptr - (char *) wpmd->data); -} - -int scan_float_data (WavpackStream *wps, f32 *values, int32_t num_values) -{ - int32_t shifted_ones = 0, shifted_zeros = 0, shifted_both = 0; - int32_t false_zeros = 0, neg_zeros = 0; - uint32_t ordata = 0, crc = 0xffffffff; - int32_t count, value, shift_count; - int max_exp = 0; - f32 *dp; - - wps->float_shift = wps->float_flags = 0; - - for (dp = values, count = num_values; count--; dp++) { - crc = crc * 27 + get_mantissa (*dp) * 9 + get_exponent (*dp) * 3 + get_sign (*dp); - - if (get_exponent (*dp) > max_exp && get_exponent (*dp) < 255) - max_exp = get_exponent (*dp); - } - - wps->crc_x = crc; - - for (dp = values, count = num_values; count--; dp++) { - if (get_exponent (*dp) == 255) { - wps->float_flags |= FLOAT_EXCEPTIONS; - value = 0x1000000; - shift_count = 0; - } - else if (get_exponent (*dp)) { - shift_count = max_exp - get_exponent (*dp); - value = 0x800000 + get_mantissa (*dp); - } - else { - shift_count = max_exp ? max_exp - 1 : 0; - value = get_mantissa (*dp); - -// if (get_mantissa (*dp)) -// denormals++; - } - - if (shift_count < 25) - value >>= shift_count; - else - value = 0; - - if (!value) { - if (get_exponent (*dp) || get_mantissa (*dp)) - ++false_zeros; - else if (get_sign (*dp)) - ++neg_zeros; - } - else if (shift_count) { - int32_t mask = (1 << shift_count) - 1; - - if (!(get_mantissa (*dp) & mask)) - shifted_zeros++; - else if ((get_mantissa (*dp) & mask) == mask) - shifted_ones++; - else - shifted_both++; - } - - ordata |= value; - * (int32_t *) dp = (get_sign (*dp)) ? -value : value; - } - - wps->float_max_exp = max_exp; - - if (shifted_both) - wps->float_flags |= FLOAT_SHIFT_SENT; - else if (shifted_ones && !shifted_zeros) - wps->float_flags |= FLOAT_SHIFT_ONES; - else if (shifted_ones && shifted_zeros) - wps->float_flags |= FLOAT_SHIFT_SAME; - else if (ordata && !(ordata & 1)) { - while (!(ordata & 1)) { - wps->float_shift++; - ordata >>= 1; - } - - for (dp = values, count = num_values; count--; dp++) - * (int32_t *) dp >>= wps->float_shift; - } - - wps->wphdr.flags &= ~MAG_MASK; - - while (ordata) { - wps->wphdr.flags += 1 << MAG_LSB; - ordata >>= 1; - } - - if (false_zeros || neg_zeros) - wps->float_flags |= FLOAT_ZEROS_SENT; - - if (neg_zeros) - wps->float_flags |= FLOAT_NEG_ZEROS; - -// error_line ("samples = %d, max exp = %d, pre-shift = %d, denormals = %d", -// num_values, max_exp, wps->float_shift, denormals); -// if (wps->float_flags & FLOAT_EXCEPTIONS) -// error_line ("exceptions!"); -// error_line ("shifted ones/zeros/both = %d/%d/%d, true/neg/false zeros = %d/%d/%d", -// shifted_ones, shifted_zeros, shifted_both, true_zeros, neg_zeros, false_zeros); - - return wps->float_flags & (FLOAT_EXCEPTIONS | FLOAT_ZEROS_SENT | FLOAT_SHIFT_SENT | FLOAT_SHIFT_SAME); -} - -void send_float_data (WavpackStream *wps, f32 *values, int32_t num_values) -{ - int max_exp = wps->float_max_exp; - int32_t count, value, shift_count; - f32 *dp; - - for (dp = values, count = num_values; count--; dp++) { - if (get_exponent (*dp) == 255) { - if (get_mantissa (*dp)) { - putbit_1 (&wps->wvxbits); - putbits (get_mantissa (*dp), 23, &wps->wvxbits); - } - else { - putbit_0 (&wps->wvxbits); - } - - value = 0x1000000; - shift_count = 0; - } - else if (get_exponent (*dp)) { - shift_count = max_exp - get_exponent (*dp); - value = 0x800000 + get_mantissa (*dp); - } - else { - shift_count = max_exp ? max_exp - 1 : 0; - value = get_mantissa (*dp); - } - - if (shift_count < 25) - value >>= shift_count; - else - value = 0; - - if (!value) { - if (wps->float_flags & FLOAT_ZEROS_SENT) { - if (get_exponent (*dp) || get_mantissa (*dp)) { - putbit_1 (&wps->wvxbits); - putbits (get_mantissa (*dp), 23, &wps->wvxbits); - - if (max_exp >= 25) { - putbits (get_exponent (*dp), 8, &wps->wvxbits); - } - - putbit (get_sign (*dp), &wps->wvxbits); - } - else { - putbit_0 (&wps->wvxbits); - - if (wps->float_flags & FLOAT_NEG_ZEROS) - putbit (get_sign (*dp), &wps->wvxbits); - } - } - } - else if (shift_count) { - if (wps->float_flags & FLOAT_SHIFT_SENT) { - int32_t data = get_mantissa (*dp) & ((1 << shift_count) - 1); - putbits (data, shift_count, &wps->wvxbits); - } - else if (wps->float_flags & FLOAT_SHIFT_SAME) { - putbit (get_mantissa (*dp) & 1, &wps->wvxbits); - } - } - } -} - -#endif - -#if !defined(NO_UNPACK) || defined(INFO_ONLY) - -int read_float_info (WavpackStream *wps, WavpackMetadata *wpmd) -{ - int bytecnt = wpmd->byte_length; - char *byteptr = wpmd->data; - - if (bytecnt != 4) - return FALSE; - - wps->float_flags = *byteptr++; - wps->float_shift = *byteptr++; - wps->float_max_exp = *byteptr++; - wps->float_norm_exp = *byteptr; - return TRUE; -} - -#endif - -#ifndef NO_UNPACK - -static void float_values_nowvx (WavpackStream *wps, int32_t *values, int32_t num_values); - -void float_values (WavpackStream *wps, int32_t *values, int32_t num_values) -{ - uint32_t crc = wps->crc_x; - - if (!bs_is_open (&wps->wvxbits)) { - float_values_nowvx (wps, values, num_values); - return; - } - - while (num_values--) { - int shift_count = 0, exp = wps->float_max_exp; - f32 outval = 0; - uint32_t temp; - - if (*values == 0) { - if (wps->float_flags & FLOAT_ZEROS_SENT) { - if (getbit (&wps->wvxbits)) { - getbits (&temp, 23, &wps->wvxbits); - set_mantissa (outval, temp); - - if (exp >= 25) { - getbits (&temp, 8, &wps->wvxbits); - set_exponent (outval, temp); - } - - set_sign (outval, getbit (&wps->wvxbits)); - } - else if (wps->float_flags & FLOAT_NEG_ZEROS) - set_sign (outval, getbit (&wps->wvxbits)); - } - } - else { - *values <<= wps->float_shift; - - if (*values < 0) { - *values = -*values; - set_sign (outval, 1); - } - - if (*values == 0x1000000) { - if (getbit (&wps->wvxbits)) { - getbits (&temp, 23, &wps->wvxbits); - set_mantissa (outval, temp); - } - - set_exponent (outval, 255); - } - else { - if (exp) - while (!(*values & 0x800000) && --exp) { - shift_count++; - *values <<= 1; - } - - if (shift_count) { - if ((wps->float_flags & FLOAT_SHIFT_ONES) || - ((wps->float_flags & FLOAT_SHIFT_SAME) && getbit (&wps->wvxbits))) - *values |= ((1 << shift_count) - 1); - else if (wps->float_flags & FLOAT_SHIFT_SENT) { - getbits (&temp, shift_count, &wps->wvxbits); - *values |= temp & ((1 << shift_count) - 1); - } - } - - set_mantissa (outval, *values); - set_exponent (outval, exp); - } - } - - crc = crc * 27 + get_mantissa (outval) * 9 + get_exponent (outval) * 3 + get_sign (outval); - * (f32 *) values++ = outval; - } - - wps->crc_x = crc; -} - -static void float_values_nowvx (WavpackStream *wps, int32_t *values, int32_t num_values) -{ - while (num_values--) { - int shift_count = 0, exp = wps->float_max_exp; - f32 outval = 0; - - if (*values) { - *values <<= wps->float_shift; - - if (*values < 0) { - *values = -*values; - set_sign (outval, 1); - } - - if (*values >= 0x1000000) { - while (*values & 0xf000000) { - *values >>= 1; - ++exp; - } - } - else if (exp) { - while (!(*values & 0x800000) && --exp) { - shift_count++; - *values <<= 1; - } - - if (shift_count && (wps->float_flags & FLOAT_SHIFT_ONES)) - *values |= ((1 << shift_count) - 1); - } - - set_mantissa (outval, *values); - set_exponent (outval, exp); - } - - * (f32 *) values++ = outval; - } -} - -#endif - -void WavpackFloatNormalize (int32_t *values, int32_t num_values, int delta_exp) -{ - f32 *fvalues = (f32 *) values; - int exp; - - if (!delta_exp) - return; - - while (num_values--) { - if ((exp = get_exponent (*fvalues)) == 0 || exp + delta_exp <= 0) - *fvalues = 0; - else if (exp == 255 || (exp += delta_exp) >= 255) { - set_exponent (*fvalues, 255); - set_mantissa (*fvalues, 0); - } - else - set_exponent (*fvalues, exp); - - fvalues++; - } -} diff --git a/wavpack-4.5.0/src/libwavpack.sln b/wavpack-4.5.0/src/libwavpack.sln deleted file mode 100644 index 5bfa1f1..0000000 --- a/wavpack-4.5.0/src/libwavpack.sln +++ /dev/null @@ -1,26 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 9.00 -# Visual Studio 2005 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libwavpack", "libwavpack.vcproj", "{5CCCB9CF-0384-458F-BA08-72B73866840F}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Debug|x64 = Debug|x64 - Release|Win32 = Release|Win32 - Release|x64 = Release|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {5CCCB9CF-0384-458F-BA08-72B73866840F}.Debug|Win32.ActiveCfg = Debug|Win32 - {5CCCB9CF-0384-458F-BA08-72B73866840F}.Debug|Win32.Build.0 = Debug|Win32 - {5CCCB9CF-0384-458F-BA08-72B73866840F}.Debug|x64.ActiveCfg = Debug|x64 - {5CCCB9CF-0384-458F-BA08-72B73866840F}.Debug|x64.Build.0 = Debug|x64 - {5CCCB9CF-0384-458F-BA08-72B73866840F}.Release|Win32.ActiveCfg = Release|Win32 - {5CCCB9CF-0384-458F-BA08-72B73866840F}.Release|Win32.Build.0 = Release|Win32 - {5CCCB9CF-0384-458F-BA08-72B73866840F}.Release|x64.ActiveCfg = Release|x64 - {5CCCB9CF-0384-458F-BA08-72B73866840F}.Release|x64.Build.0 = Release|x64 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/wavpack-4.5.0/src/libwavpack.vcproj b/wavpack-4.5.0/src/libwavpack.vcproj deleted file mode 100644 index ff70ec3..0000000 --- a/wavpack-4.5.0/src/libwavpack.vcproj +++ /dev/null @@ -1,364 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/wavpack-4.5.0/src/libwavpack.vcxproj b/wavpack-4.5.0/src/libwavpack.vcxproj deleted file mode 100644 index bb9e2a2..0000000 --- a/wavpack-4.5.0/src/libwavpack.vcxproj +++ /dev/null @@ -1,192 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {5CCCB9CF-0384-458F-BA08-72B73866840F} - v2.0 - libwavpack - Win32Proj - 10.0.16299.0 - - - - StaticLibrary - v141 - - - StaticLibrary - v141 - - - StaticLibrary - v141 - - - StaticLibrary - v141 - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.40219.1 - $(SolutionDir)..\bin\$(Platform)\$(Configuration)\ - $(SolutionDir)..\obj\$(ProjectName)\$(Platform)\$(Configuration)\ - $(SolutionDir)..\bin\$(Platform)\$(Configuration)\ - $(SolutionDir)..\obj\$(ProjectName)\$(Platform)\$(Configuration)\ - $(SolutionDir)..\bin\$(Platform)\$(Configuration)\ - $(SolutionDir)..\obj\$(ProjectName)\$(Platform)\$(Configuration)\ - $(SolutionDir)..\bin\$(Platform)\$(Configuration)\ - $(SolutionDir)..\obj\$(ProjectName)\$(Platform)\$(Configuration)\ - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - - - - Disabled - WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;OPT_MMX;NO_USE_FSTREAMS;NO_TAGS;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebugDLL - - - Level3 - EditAndContinue - - - - - X64 - - - Disabled - WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;OPT_SSE2;NO_USE_FSTREAMS;NO_TAGS;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebugDLL - - - Level3 - ProgramDatabase - - - - - AnySuitable - true - Speed - true - WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;OPT_MMX;NO_USE_FSTREAMS;NO_TAGS;%(PreprocessorDefinitions) - true - - - MultiThreadedDLL - false - true - false - false - - - Level3 - - - Default - true - - - true - - - - - X64 - - - Full - AnySuitable - true - Speed - true - true - WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;OPT_SSE2;NO_USE_FSTREAMS;NO_TAGS;%(PreprocessorDefinitions) - true - - - MultiThreadedDLL - false - StreamingSIMDExtensions - Fast - false - false - - - Level3 - - - Default - true - - - true - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/wavpack-4.5.0/src/metadata.c b/wavpack-4.5.0/src/metadata.c deleted file mode 100644 index c6d641e..0000000 --- a/wavpack-4.5.0/src/metadata.c +++ /dev/null @@ -1,313 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// **** WAVPACK **** // -// Hybrid Lossless Wavefile Compressor // -// Copyright (c) 1998 - 2006 Conifer Software. // -// All Rights Reserved. // -// Distributed under the BSD Software License (see license.txt) // -//////////////////////////////////////////////////////////////////////////// - -// metadata.c - -// This module handles the metadata structure introduced in WavPack 4.0 - -#include "wavpack_local.h" - -#include -#include - -#ifdef DEBUG_ALLOC -#define malloc malloc_db -#define realloc realloc_db -#define free free_db -void *malloc_db (uint32_t size); -void *realloc_db (void *ptr, uint32_t size); -void free_db (void *ptr); -int32_t dump_alloc (void); -#endif - -#if !defined(NO_UNPACK) || defined(INFO_ONLY) - -int read_metadata_buff (WavpackMetadata *wpmd, uchar *blockbuff, uchar **buffptr) -{ - WavpackHeader *wphdr = (WavpackHeader *) blockbuff; - uchar *buffend = blockbuff + wphdr->ckSize + 8; - - if (buffend - *buffptr < 2) - return FALSE; - - wpmd->id = *(*buffptr)++; - wpmd->byte_length = *(*buffptr)++ << 1; - - if (wpmd->id & ID_LARGE) { - wpmd->id &= ~ID_LARGE; - - if (buffend - *buffptr < 2) - return FALSE; - - wpmd->byte_length += *(*buffptr)++ << 9; - wpmd->byte_length += *(*buffptr)++ << 17; - } - - if (wpmd->id & ID_ODD_SIZE) { - wpmd->id &= ~ID_ODD_SIZE; - wpmd->byte_length--; - } - - if (wpmd->byte_length) { - if (buffend - *buffptr < wpmd->byte_length + (wpmd->byte_length & 1)) { - wpmd->data = NULL; - return FALSE; - } - - wpmd->data = *buffptr; - (*buffptr) += wpmd->byte_length + (wpmd->byte_length & 1); - } - else - wpmd->data = NULL; - - return TRUE; -} - -int process_metadata (WavpackContext *wpc, WavpackMetadata *wpmd) -{ - WavpackStream *wps = wpc->streams [wpc->current_stream]; - - switch (wpmd->id) { - case ID_DUMMY: - return TRUE; - - case ID_DECORR_TERMS: - return read_decorr_terms (wps, wpmd); - - case ID_DECORR_WEIGHTS: - return read_decorr_weights (wps, wpmd); - - case ID_DECORR_SAMPLES: - return read_decorr_samples (wps, wpmd); - - case ID_ENTROPY_VARS: - return read_entropy_vars (wps, wpmd); - - case ID_HYBRID_PROFILE: - return read_hybrid_profile (wps, wpmd); - - case ID_SHAPING_WEIGHTS: - return read_shaping_info (wps, wpmd); - - case ID_FLOAT_INFO: - return read_float_info (wps, wpmd); - - case ID_INT32_INFO: - return read_int32_info (wps, wpmd); - - case ID_CHANNEL_INFO: - return read_channel_info (wpc, wpmd); - - case ID_CONFIG_BLOCK: - return read_config_info (wpc, wpmd); - - case ID_SAMPLE_RATE: - return read_sample_rate (wpc, wpmd); - - case ID_WV_BITSTREAM: - return init_wv_bitstream (wps, wpmd); - - case ID_WVC_BITSTREAM: - return init_wvc_bitstream (wps, wpmd); - - case ID_WVX_BITSTREAM: - return init_wvx_bitstream (wps, wpmd); - - case ID_RIFF_HEADER: case ID_RIFF_TRAILER: - return read_wrapper_data (wpc, wpmd); - - case ID_MD5_CHECKSUM: - if (wpmd->byte_length == 16) { - memcpy (wpc->config.md5_checksum, wpmd->data, 16); - wpc->config.flags |= CONFIG_MD5_CHECKSUM; - wpc->config.md5_read = 1; - } - - return TRUE; - - default: - return (wpmd->id & ID_OPTIONAL_DATA) ? TRUE : FALSE; - } -} - -#endif - -#ifndef NO_PACK - -int copy_metadata (WavpackMetadata *wpmd, uchar *buffer_start, uchar *buffer_end) -{ - uint32_t mdsize = wpmd->byte_length + (wpmd->byte_length & 1); - WavpackHeader *wphdr = (WavpackHeader *) buffer_start; - - if (wpmd->byte_length & 1) - ((char *) wpmd->data) [wpmd->byte_length] = 0; - - mdsize += (wpmd->byte_length > 510) ? 4 : 2; - buffer_start += wphdr->ckSize + 8; - - if (buffer_start + mdsize >= buffer_end) - return FALSE; - - buffer_start [0] = wpmd->id | (wpmd->byte_length & 1 ? ID_ODD_SIZE : 0); - buffer_start [1] = (wpmd->byte_length + 1) >> 1; - - if (wpmd->byte_length > 510) { - buffer_start [0] |= ID_LARGE; - buffer_start [2] = (wpmd->byte_length + 1) >> 9; - buffer_start [3] = (wpmd->byte_length + 1) >> 17; - } - - if (wpmd->data && wpmd->byte_length) { - if (wpmd->byte_length > 510) { - buffer_start [0] |= ID_LARGE; - buffer_start [2] = (wpmd->byte_length + 1) >> 9; - buffer_start [3] = (wpmd->byte_length + 1) >> 17; - memcpy (buffer_start + 4, wpmd->data, mdsize - 4); - } - else - memcpy (buffer_start + 2, wpmd->data, mdsize - 2); - } - - wphdr->ckSize += mdsize; - return TRUE; -} - -int add_to_metadata (WavpackContext *wpc, void *data, uint32_t bcount, uchar id) -{ - WavpackMetadata *mdp; - uchar *src = data; - - while (bcount) { - if (wpc->metacount) { - uint32_t bc = bcount; - - mdp = wpc->metadata + wpc->metacount - 1; - - if (mdp->id == id) { - if (wpc->metabytes + bcount > 1000000) - bc = 1000000 - wpc->metabytes; - - mdp->data = realloc (mdp->data, mdp->byte_length + bc); - memcpy ((char *) mdp->data + mdp->byte_length, src, bc); - mdp->byte_length += bc; - wpc->metabytes += bc; - bcount -= bc; - src += bc; - - if (wpc->metabytes >= 1000000 && !write_metadata_block (wpc)) - return FALSE; - } - } - - if (bcount) { - wpc->metadata = realloc (wpc->metadata, (wpc->metacount + 1) * sizeof (WavpackMetadata)); - mdp = wpc->metadata + wpc->metacount++; - mdp->byte_length = 0; - mdp->data = NULL; - mdp->id = id; - } - } - - return TRUE; -} - -static char *write_metadata (WavpackMetadata *wpmd, char *outdata) -{ - uchar id = wpmd->id, wordlen [3]; - - wordlen [0] = (wpmd->byte_length + 1) >> 1; - wordlen [1] = (wpmd->byte_length + 1) >> 9; - wordlen [2] = (wpmd->byte_length + 1) >> 17; - - if (wpmd->byte_length & 1) { -// ((char *) wpmd->data) [wpmd->byte_length] = 0; - id |= ID_ODD_SIZE; - } - - if (wordlen [1] || wordlen [2]) - id |= ID_LARGE; - - *outdata++ = id; - *outdata++ = wordlen [0]; - - if (id & ID_LARGE) { - *outdata++ = wordlen [1]; - *outdata++ = wordlen [2]; - } - - if (wpmd->data && wpmd->byte_length) { - memcpy (outdata, wpmd->data, wpmd->byte_length); - outdata += wpmd->byte_length; - - if (wpmd->byte_length & 1) - *outdata++ = 0; - } - - return outdata; -} - -int write_metadata_block (WavpackContext *wpc) -{ - char *block_buff, *block_ptr; - WavpackHeader *wphdr; - - if (wpc->metacount) { - int metacount = wpc->metacount, block_size = sizeof (WavpackHeader); - WavpackMetadata *wpmdp = wpc->metadata; - - while (metacount--) { - block_size += wpmdp->byte_length + (wpmdp->byte_length & 1); - block_size += (wpmdp->byte_length > 510) ? 4 : 2; - wpmdp++; - } - - wphdr = (WavpackHeader *) (block_buff = malloc (block_size)); - - CLEAR (*wphdr); - memcpy (wphdr->ckID, "wvpk", 4); - wphdr->total_samples = wpc->total_samples; - wphdr->version = wpc->stream_version; - wphdr->ckSize = block_size - 8; - wphdr->block_samples = 0; - - block_ptr = (char *)(wphdr + 1); - - wpmdp = wpc->metadata; - - while (wpc->metacount) { - block_ptr = write_metadata (wpmdp, block_ptr); - wpc->metabytes -= wpmdp->byte_length; - free_metadata (wpmdp++); - wpc->metacount--; - } - - free (wpc->metadata); - wpc->metadata = NULL; - native_to_little_endian ((WavpackHeader *) block_buff, WavpackHeaderFormat); - - if (!wpc->blockout (wpc->wv_out, block_buff, block_size)) { - free (block_buff); - strcpy (wpc->error_message, "can't write WavPack data, disk probably full!"); - return FALSE; - } - - free (block_buff); - } - - return TRUE; -} - -#endif - -void free_metadata (WavpackMetadata *wpmd) -{ - if (wpmd->data) { - free (wpmd->data); - wpmd->data = NULL; - } -} diff --git a/wavpack-4.5.0/src/pack.c b/wavpack-4.5.0/src/pack.c deleted file mode 100644 index 837b597..0000000 --- a/wavpack-4.5.0/src/pack.c +++ /dev/null @@ -1,2992 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// **** WAVPACK **** // -// Hybrid Lossless Wavefile Compressor // -// Copyright (c) 1998 - 2006 Conifer Software. // -// MMX optimizations (c) 2006 Joachim Henke // -// All Rights Reserved. // -// Distributed under the BSD Software License (see license.txt) // -//////////////////////////////////////////////////////////////////////////// - -// pack.c - -// This module actually handles the compression of the audio data, except for -// the entropy coding which is handled by the words? modules. For efficiency, -// the conversion is isolated to tight loops that handle an entire buffer. - -#include "wavpack_local.h" - -#include -#include -#include -#include - -#ifdef DEBUG_ALLOC -#define malloc malloc_db -#define realloc realloc_db -#define free free_db -void *malloc_db (uint32_t size); -void *realloc_db (void *ptr, uint32_t size); -void free_db (void *ptr); -int32_t dump_alloc (void); -#endif - -//////////////////////////////// local tables /////////////////////////////// - -// These two tables specify the characteristics of the decorrelation filters. -// Each term represents one layer of the sequential filter, where positive -// values indicate the relative sample involved from the same channel (1=prev), -// 17 & 18 are special functions using the previous 2 samples, and negative -// values indicate cross channel decorrelation (in stereo only). - -static const WavpackDecorrSpec fast_specs [] = { - { 1, 2,18,17 }, // 0 - { 1, 1,17,17 }, // 1 - { 0, 2,18,17 }, // 2 - { 0, 1,17,17 }, // 3 - { 1, 3, 1,18 }, // 4 - { 1, 1,17, 1 }, // 5 - { 0, 1, 1,17 }, // 6 - { 0, 1,-2,17 }, // 7 - { 0, 2,-1,17 }, // 8 - { 1, 1,17, 2 }, // 9 - { 0, 3,18,18 }, // 10 - { 0, 1,17, 1 }, // 11 - { 1, 6, 1, 2 }, // 12 - { 1, 1,17, 3 }, // 13 - { 0, 1,-2, 3 }, // 14 - { 0, 1, 2,17 }, // 15 - { 0, 1,18,-2 }, // 16 - { 0, 1,-1,17 }, // 17 - { 0, 1,18,17 }, // 18 - { 0, 1,17, 2 }, // 19 - { 1, 2,18,-2 }, // 20 - { 1, 1, 1,17 }, // 21 - { 0, 3,18, 2 }, // 22 - { 0, 1,17,-2 }, // 23 - { 0, 1,18,-2 }, // 24 - { 1, 2,17,-3 }, // 25 - { 0, 1,18, 3 }, // 26 - { 0, 1,18,18 }, // 27 - { 1, 1, 1, 3 }, // 28 - { 1, 1,18, 3 }, // 29 - { 1, 1, 1, 3 }, // 30 - { 0, 2,18,17 }, // 31 - { 1, 1, 1,17 }, // 32 - { 1, 1,17, 3 }, // 33 - { 0, 3,18,17 }, // 34 - { 0, 1,18,18 }, // 35 - { 1, 1, 1, 3 }, // 36 - { 1, 1, 1,18 }, // 37 - { 0, 1,18,-2 }, // 38 - { 0, 2,18,17 }, // 39 - { 0, 1,-1,18 }, // 40 - { 1, 1,17, 3 }, // 41 - { 0, 1,17, 2 }, // 42 - { 0, 1,17, 3 }, // 43 - { 1, 1,18, 2 }, // 44 - { 1, 1,17,-2 }, // 45 - { 0, 1, 1,-2 }, // 46 - { 0, 2,18,17 }, // 47 - { 0, 1,17,-2 }, // 48 - { 1, 1,17,-2 }, // 49 - { 0, 1,18, 3 }, // 50 - { 0, 1, 2,17 }, // 51 - { 1, 2,18,-3 }, // 52 - { 1, 2, 1,18 }, // 53 - { 1, 2,18, 2 }, // 54 - { 0, 1,17,-1 }, // 55 - { 0, 1,17,-2 }, // 56 - { 1, 1,17,-2 }, // 57 - { 1, 1, 1, 3 }, // 58 - { 0, 1, 1,17 }, // 59 - { 1, 2,18,-2 }, // 60 - { 1, 2,17,-3 }, // 61 - { 0, 2,18,17 }, // 62 - { 0, 2,18,17 }, // 63 - { 1, 1,17, 2 }, // 64 - { 1, 2,18,18 }, // 65 - { 0, 1,17, 2 }, // 66 - { 0, 1,18,17 }, // 67 - { 1, 1, 1,17 }, // 68 - { 1, 1,17, 2 }, // 69 - { 0, 2,18,18 }, // 70 - { 0, 2,18,17 }, // 71 - { 1, 2,17,-3 }, // 72 - { 1, 6, 1, 2 }, // 73 - { 0, 3,17,17 }, // 74 - { 0, 1, 1,18 }, // 75 - { 0, 1, 1,-2 }, // 76 - { 1, 1,17, 2 }, // 77 - { 0, 2,18,17 }, // 78 - { 0, 2,18,17 }, // 79 - { 1, 1,18, 3 }, // 80 - { 1, 2,17,-3 }, // 81 - { 0, 1,17, 2 }, // 82 - { 0, 1,17, 3 }, // 83 - { 0, 1,18,-2 }, // 84 - { 1, 1,18,18 }, // 85 - { 1, 6, 1, 2 }, // 86 - { 0, 2,18,17 }, // 87 - { 0, 2,18,17 }, // 88 - { 0, 1,-1,17 }, // 89 - { 1, 1,18, 3 }, // 90 - { 0, 1,17,18 }, // 91 - { 1, 1,17, 3 }, // 92 - { 0, 1,18, 3 }, // 93 - { 0, 2,18,17 }, // 94 - { 0, 2,18,17 }, // 95 - { 1, 2,18, 2 }, // 96 - { 0, 1,-2, 3 }, // 97 - { 0, 4,18,-1 }, // 98 - { 0, 2,18,18 }, // 99 - { 0, 1,-2, 3 }, // 100 - { 1, 1,17,-2 }, // 101 - { 0, 1,17, 3 }, // 102 - { 0, 2,18,17 }, // 103 - { 0, 2,-1,18 }, // 104 - { 1, 1, 2,17 }, // 105 - { 0, 2,17,-2 }, // 106 - { 0, 1,17, 2 }, // 107 - { 1, 2,18,-3 }, // 108 - { 0, 1,17,-2 }, // 109 - { 0, 2,18,17 }, // 110 - { 0, 2,18,17 }, // 111 - { 1, 1,17,-2 }, // 112 - { 1, 2,17,-3 }, // 113 - { 1, 1, 1, 3 }, // 114 - { 1, 1, 2,17 }, // 115 - { 1, 2,18, 2 }, // 116 - { 1, 1, 2,17 }, // 117 - { 1, 1,18, 2 }, // 118 - { 0, 2,18,17 }, // 119 - { 0, 2,18,17 }, // 120 - { 0, 1,17,-2 }, // 121 - { 0, 2,18,17 }, // 122 - { 0, 2,17,-1 }, // 123 - { 0, 2,18,-2 }, // 124 - { 0, 2,18,17 }, // 125 - { 0, 2,18,17 }, // 126 - { 0, 2,18,17 }, // 127 - { 1, 1, 1, 3 }, // 128 - { 0, 2,-2,17 }, // 129 - { 0, 2,18,-2 }, // 130 - { 0, 2,17,-2 }, // 131 - { 1, 1, 2,17 }, // 132 - { 1, 1, 1, 3 }, // 133 - { 0, 1, 2,17 }, // 134 - { 0, 2,18,17 }, // 135 - { 0, 3,-1,17 }, // 136 - { 1, 1, 2,17 }, // 137 - { 0, 2,18,18 }, // 138 - { 0, 1,17, 2 }, // 139 - { 1, 4,18,-3 }, // 140 - { 1, 1,18, 1 }, // 141 - { 0, 2,18,17 }, // 142 - { 0, 2,18,17 }, // 143 - { 1, 2,18,-1 }, // 144 - { 0, 1,-1,18 }, // 145 - { 1, 6, 1, 2 }, // 146 - { 1, 1,17, 2 }, // 147 - { 1, 4,18, 3 }, // 148 - { 0, 1, 1,17 }, // 149 - { 0, 1,18, 2 }, // 150 - { 0, 2,18,17 }, // 151 - { 0, 2,18,17 }, // 152 - { 1, 2,17, 2 }, // 153 - { 0, 2,18,-2 }, // 154 - { 0, 1, 1,18 }, // 155 - { 1, 2,18,-3 }, // 156 - { 0, 2,18,17 }, // 157 - { 0, 2,18,17 }, // 158 - { 0, 2,18,17 }, // 159 - { 1, 2,18,18 }, // 160 - { 1, 3,17,17 }, // 161 - { 0, 1,-2,17 }, // 162 - { 0, 1,17,18 }, // 163 - { 0, 1,-1, 3 }, // 164 - { 1, 1, 2,17 }, // 165 - { 0, 2,18,-1 }, // 166 - { 0, 2,18,17 }, // 167 - { 0, 2,18,17 }, // 168 - { 1, 1,17,-2 }, // 169 - { 1, 2,17, 2 }, // 170 - { 1, 1,18, 3 }, // 171 - { 0, 1,18, 2 }, // 172 - { 1, 2,17,-3 }, // 173 - { 0, 2,18,17 }, // 174 - { 0, 2,18,17 }, // 175 - { 0, 1,-2,17 }, // 176 - { 0, 1,17,-1 }, // 177 - { 0, 1,18,-1 }, // 178 - { 0, 2,18,17 }, // 179 - { 1, 2,17,-3 }, // 180 - { 1, 1, 1,18 }, // 181 - { 1, 3,18, 2 }, // 182 - { 0, 2,18,17 }, // 183 - { 0, 2,18,17 }, // 184 - { 0, 2,18,17 }, // 185 - { 0, 2,18,17 }, // 186 - { 0, 3,18,18 }, // 187 - { 0, 1, 1,-2 }, // 188 - { 0, 2,18,17 }, // 189 - { 0, 2,18,17 }, // 190 - { 0, 2,18,17 }, // 191 - { 1, 2,17,-3 }, // 192 - { 1, 1,18,18 }, // 193 - { 0, 2,18, 2 }, // 194 - { 0, 1,17,18 }, // 195 - { 1, 2,18, 2 }, // 196 - { 1, 1,17,-2 }, // 197 - { 0, 2,17,-1 }, // 198 - { 0, 2,18,17 }, // 199 - { 0, 2,18,17 }, // 200 - { 0, 2,18,17 }, // 201 - { 0, 1, 1,-2 }, // 202 - { 0, 1,18, 1 }, // 203 - { 1, 2,18,-2 }, // 204 - { 0, 1,17, 2 }, // 205 - { 0, 2,18,17 }, // 206 - { 0, 2,18,17 }, // 207 - { 1, 1,17, 3 }, // 208 - { 0, 1,17,-1 }, // 209 - { 0, 1,18, 2 }, // 210 - { 1, 1,17, 3 }, // 211 - { 1, 1,17,-2 }, // 212 - { 0, 1,18,18 }, // 213 - { 0, 2,18,17 }, // 214 - { 0, 2,18,17 }, // 215 - { 0, 2,18,17 }, // 216 - { 0, 2,18,17 }, // 217 - { 0, 2,18,17 }, // 218 - { 1, 1,17,18 }, // 219 - { 0, 1,-2, 3 }, // 220 - { 0, 2,18,17 }, // 221 - { 0, 2,18,17 }, // 222 - { 0, 2,18,17 }, // 223 - { 1, 2,18,-3 }, // 224 - { 0, 2,18,17 }, // 225 - { 0, 3,18, 2 }, // 226 - { 0, 1, 1,18 }, // 227 - { 0, 2,18,17 }, // 228 - { 0, 1,17,-1 }, // 229 - { 0, 2,18,17 }, // 230 - { 0, 2,18,17 }, // 231 - { 0, 2,18,17 }, // 232 - { 0, 1,-2, 3 }, // 233 - { 0, 3,17,17 }, // 234 - { 0, 2,18,17 }, // 235 - { 0, 2,18,17 }, // 236 - { 1, 1,17, 2 }, // 237 - { 0, 2,18,17 }, // 238 - { 0, 2,18,17 }, // 239 - { 1, 1,17, 2 }, // 240 - { 0, 2,18,17 }, // 241 - { 0, 2,18,17 }, // 242 - { 0, 2,18,17 }, // 243 - { 0, 2,18, 2 }, // 244 - { 0, 2,18,17 }, // 245 - { 0, 2,18,17 }, // 246 - { 0, 2,18,17 }, // 247 - { 0, 2,18,17 }, // 248 - { 0, 2,18,17 }, // 249 - { 0, 2,18,17 }, // 250 - { 0, 2,18,17 }, // 251 - { 0, 2,18,17 }, // 252 - { 0, 2,18,17 }, // 253 - { 0, 2,18,17 }, // 254 - { 0, 2,18,17 }, // 255 -}; - -static const WavpackDecorrSpec default_specs [] = { - { 1, 2,18,18, 2,17, 3 }, // 0 - { 0, 2,18,17,-1, 3, 2 }, // 1 - { 1, 1,17,18,18,-2, 2 }, // 2 - { 0, 2,18,17, 3,-2,17 }, // 3 - { 1, 2,18,17, 2,17, 3 }, // 4 - { 0, 1,18,18,-1, 2,17 }, // 5 - { 0, 1,17,17,-2, 2, 3 }, // 6 - { 0, 1,18,-2,18, 2,17 }, // 7 - { 1, 2,18,18,-1, 2, 3 }, // 8 - { 0, 2,18,17, 3, 2, 5 }, // 9 - { 1, 1,18,17,18, 2, 5 }, // 10 - { 0, 1,17,17,-2, 2, 3 }, // 11 - { 0, 1,18,-2,18, 2, 5 }, // 12 - { 0, 1,17,-2,17, 2,-3 }, // 13 - { 1, 1,17,-2,17, 1, 2 }, // 14 - { 0, 1,17,17,-2, 2, 3 }, // 15 - { 1, 1,18, 3, 1, 5, 4 }, // 16 - { 1, 4,18,18, 2, 3,-2 }, // 17 - { 0, 1, 1,-1,-1, 2,17 }, // 18 - { 0, 2,18,17, 3, 2, 5 }, // 19 - { 0, 1,18,18,18, 2,17 }, // 20 - { 0, 1,18,17,-1, 2,18 }, // 21 - { 1, 1,17, 3, 2, 1, 7 }, // 22 - { 0, 2,18,-2,18, 2, 3 }, // 23 - { 1, 3,18,-3,18, 2, 3 }, // 24 - { 0, 3,18,17, 2, 3,17 }, // 25 - { 1, 1,17,17, 2, 1, 4 }, // 26 - { 0, 1,17,18,-2, 2,17 }, // 27 - { 1, 1,18,18, 3, 5, 2 }, // 28 - { 0, 1,17,17, 2,18, 4 }, // 29 - { 0, 1,18,17, 1, 4, 6 }, // 30 - { 1, 1, 3,17,18, 2,17 }, // 31 - { 1, 1,17, 3, 2, 1, 7 }, // 32 - { 0, 1,18,17,-1, 2, 3 }, // 33 - { 1, 1,17,17, 2, 1, 4 }, // 34 - { 1, 2,18,17,-1,17, 3 }, // 35 - { 1, 2,18,17, 2, 3,-1 }, // 36 - { 0, 2,18,18,-2, 2,17 }, // 37 - { 0, 1,17,17, 2,18, 4 }, // 38 - { 0, 5,-2,18,18,18, 2 }, // 39 - { 1, 1,18,18,-1, 6, 3 }, // 40 - { 0, 1,17,17,-2, 2, 3 }, // 41 - { 1, 1,18,17,18, 2,17 }, // 42 - { 0, 1,18,17, 4, 3, 1 }, // 43 - { 0, 1,-2,18, 2, 2,18 }, // 44 - { 1, 2,18,18,-2, 2,-1 }, // 45 - { 1, 1,17,17, 2, 1, 4 }, // 46 - { 0, 1,17,18,-2, 2,17 }, // 47 - { 1, 1,17, 3, 2, 1, 7 }, // 48 - { 1, 3,18,-3,18, 2, 3 }, // 49 - { 1, 2,18,18,-2, 2,-1 }, // 50 - { 1, 1,18,18, 3, 5, 2 }, // 51 - { 0, 2,18,18,-1, 2,17 }, // 52 - { 0, 1,18,-1,17,18, 2 }, // 53 - { 0, 1,17,-1, 2, 3, 6 }, // 54 - { 0, 1,18,-2,18, 2, 5 }, // 55 - { 1, 2,18,18,-2, 2,-1 }, // 56 - { 0, 3,18,18, 2, 3,17 }, // 57 - { 0, 1,17,17, 2,18, 4 }, // 58 - { 1, 1,17,-2,17, 1, 2 }, // 59 - { 0, 1,-1, 3, 5, 4, 7 }, // 60 - { 0, 3,18,18, 3, 2, 5 }, // 61 - { 0, 1,17,17, 2,18, 4 }, // 62 - { 0, 1,18,17,-2,18, 3 }, // 63 - { 0, 2,18,18,-2, 2,17 }, // 64 - { 0, 3,18,17,-2, 2, 3 }, // 65 - { 1, 1,18,18,-2, 2,17 }, // 66 - { 0, 1,18,17, 4, 3, 1 }, // 67 - { 1, 2, 3,18,17, 2,17 }, // 68 - { 1, 2,18,18, 2,-2,18 }, // 69 - { 1, 2,18,18,-1,18, 2 }, // 70 - { 0, 2,18,18,-2, 2,17 }, // 71 - { 1, 3,18,18, 2, 3,-2 }, // 72 - { 0, 3,18,18, 3, 2, 5 }, // 73 - { 0, 1,18,-2,18, 2, 5 }, // 74 - { 1, 1,17, 3, 2, 1, 7 }, // 75 - { 1, 3,18,18,-2, 2,18 }, // 76 - { 1, 1,17,18,18,-2, 2 }, // 77 - { 0, 1,18,-2,18, 2, 5 }, // 78 - { 0, 2,18,-2,18, 2, 3 }, // 79 - { 0, 1,-1, 3, 4, 5, 7 }, // 80 - { 1, 1,17,17, 2,-1, 7 }, // 81 - { 0, 1,18,-1,-1, 2,-2 }, // 82 - { 0, 2,18,17, 2, 3,17 }, // 83 - { 0, 1,18,17, 2,18, 2 }, // 84 - { 0, 2,18,17,-1, 2,17 }, // 85 - { 0, 1, 1,18, 3, 2, 5 }, // 86 - { 0, 2,18,-2, 4,18, 2 }, // 87 - { 1, 1,18, 3, 1, 5, 4 }, // 88 - { 0, 1,18,17,18, 2, 5 }, // 89 - { 1, 1,18, 3, 1, 5, 4 }, // 90 - { 0, 4,18,18,-2, 2,18 }, // 91 - { 1, 1,18,18, 3, 2, 5 }, // 92 - { 1, 1,17,17, 2, 1, 4 }, // 93 - { 0, 2,18,18,-2,18, 2 }, // 94 - { 0, 2,18,18,-2,18, 2 }, // 95 - { 1, 1,18,18, 2, 1, 3 }, // 96 - { 1, 1,17,17, 2, 1, 4 }, // 97 - { 1, 2,17,17, 2,18, 3 }, // 98 - { 0, 1,18,17, 1, 4, 6 }, // 99 - { 1, 2,18,18,-2, 2,-1 }, // 100 - { 0, 1,18,-2,18, 2, 5 }, // 101 - { 1, 1,17, 2,18, 2,17 }, // 102 - { 0, 2,18,18,-2,18, 2 }, // 103 - { 0, 1,18,18, 3, 6,-1 }, // 104 - { 0, 1,18,17, 2,18, 3 }, // 105 - { 0, 1,18,17,-2, 2,17 }, // 106 - { 1, 1, 3,17,18, 2,17 }, // 107 - { 1, 3,18,-3,18, 2, 3 }, // 108 - { 1, 3,18,18,-3,18, 2 }, // 109 - { 1, 1,18, 3, 1, 5, 4 }, // 110 - { 0, 1,17,-2,17, 2,-3 }, // 111 - { 1, 1,18,18, 3, 5, 2 }, // 112 - { 1, 2,18,18,-2, 2,-1 }, // 113 - { 0, 1,18,-1,-1, 2,-2 }, // 114 - { 1, 1,18, 3, 1, 5, 4 }, // 115 - { 0, 3,18,17,-1, 2,17 }, // 116 - { 1, 3,18,17, 2,18,-2 }, // 117 - { 0, 2,18,18,-2,18, 2 }, // 118 - { 1, 2,18,18,-2, 2,-1 }, // 119 - { 1, 1,18, 3, 1, 5, 4 }, // 120 - { 0, 4, 3,18,18, 2,17 }, // 121 - { 0, 2,18,18,-2,18, 2 }, // 122 - { 1, 1,18,17,-1,18, 2 }, // 123 - { 0, 2,18,18,-2,18, 2 }, // 124 - { 0, 2,18,18,-2,18, 2 }, // 125 - { 0, 2,18,18,-2,18, 2 }, // 126 - { 0, 2,18,18,-2,18, 2 }, // 127 - { 1, 1,18,18,18, 3, 2 }, // 128 - { 0, 1,17,-1, 2, 3, 6 }, // 129 - { 0, 1,17,-1, 2, 3, 6 }, // 130 - { 0, 2,18,17,-2, 3, 2 }, // 131 - { 1, 3,18,17, 2,-2,18 }, // 132 - { 0, 2,18,18, 2,17, 3 }, // 133 - { 0, 1,18,18, 2,18,-2 }, // 134 - { 0, 2,18,-2, 4,18, 2 }, // 135 - { 0, 1,-2,18, 2, 2,18 }, // 136 - { 0, 2,18,17, 3, 6, 2 }, // 137 - { 0, 1,18,17,18, 2, 5 }, // 138 - { 0, 3,18,18,-2, 3, 2 }, // 139 - { 1, 1,18,18, 2,18, 5 }, // 140 - { 0, 1,17,-1, 2, 3, 6 }, // 141 - { 1, 4,18,18, 2, 3,-2 }, // 142 - { 0, 2,18,17,18, 2,-2 }, // 143 - { 0, 1, 1,18, 3, 2, 5 }, // 144 - { 1, 4,18,-2,18, 2, 3 }, // 145 - { 1, 2,18, 2,18, 3,-2 }, // 146 - { 0, 2,18,18,18, 2, 4 }, // 147 - { 0, 2, 3,17,18, 2,17 }, // 148 - { 1, 1,18,-1,18, 2,17 }, // 149 - { 1, 2,17,17, 2,18, 3 }, // 150 - { 0, 2,18,17,-2, 3, 2 }, // 151 - { 0, 1, 1,-1,-1, 2,17 }, // 152 - { 0, 3, 3,18,18, 2,17 }, // 153 - { 0, 1,18,-1,17,18, 2 }, // 154 - { 0, 1,18,17, 2,18, 3 }, // 155 - { 0, 2,18,18,-2,18, 2 }, // 156 - { 0, 1,18,17, 2,18, 2 }, // 157 - { 0, 2,18,18,-2,18, 2 }, // 158 - { 0, 2,18,18,-2,18, 2 }, // 159 - { 1, 2,17,17, 2,18, 3 }, // 160 - { 0, 1,18,17,-2, 2, 3 }, // 161 - { 0, 1,18,-2,18, 2, 5 }, // 162 - { 1, 4,18,-2,18, 2, 3 }, // 163 - { 1, 3,18,17, 2, 3, 6 }, // 164 - { 0, 2,18,18, 2,17, 3 }, // 165 - { 0, 2,18,17, 2,18, 2 }, // 166 - { 0, 2,18,18,-2,18, 2 }, // 167 - { 1, 1,18,18, 3, 5, 2 }, // 168 - { 0, 2,18,18,-2, 2, 3 }, // 169 - { 1, 2,18,17, 2,17, 3 }, // 170 - { 0, 1,18,17, 2, 3,18 }, // 171 - { 0, 2,18,18,-2,18, 2 }, // 172 - { 1, 4,18,18, 2, 3,-2 }, // 173 - { 0, 1,17,-2,17, 2,-3 }, // 174 - { 0, 1,17,17, 2,18, 4 }, // 175 - { 1, 1,18,18,18, 2, 4 }, // 176 - { 1, 2,18, 2,18, 3,-2 }, // 177 - { 1, 1,18,18,-2, 2,17 }, // 178 - { 0, 2,18,18,-2,18, 2 }, // 179 - { 0, 2,18,18, 2,17, 3 }, // 180 - { 0, 2,18,18,18, 2, 4 }, // 181 - { 0, 2,18,18,-2,18, 2 }, // 182 - { 0, 2,18,17,-2, 3, 2 }, // 183 - { 0, 1, 1,-1,-1, 2,17 }, // 184 - { 1, 4,18,18, 2, 3,-2 }, // 185 - { 0, 2,18,18,-2,18, 2 }, // 186 - { 0, 1,18,-2,18, 3, 2 }, // 187 - { 0, 2,18,18,-2,18, 2 }, // 188 - { 0, 2,18,18,-2,18, 2 }, // 189 - { 0, 2,18,18,-2,18, 2 }, // 190 - { 0, 2,18,18,-2,18, 2 }, // 191 - { 0, 1,18,18,-2, 2,17 }, // 192 - { 0, 3,18,17, 2, 3,17 }, // 193 - { 1, 2,18,18, 2,-2,18 }, // 194 - { 0, 1,-1, 3, 5, 4, 7 }, // 195 - { 1, 1,18, 3, 1, 5, 4 }, // 196 - { 1, 1,18,18,-2,18, 3 }, // 197 - { 0, 2,18,17,18, 2,-2 }, // 198 - { 0, 2,18,18, 2,17, 3 }, // 199 - { 1, 2,18, 2,18, 3,-2 }, // 200 - { 1, 4,18,18, 2, 3,-2 }, // 201 - { 1, 3,18,17, 2, 3, 6 }, // 202 - { 0, 2,18,18,-2,18, 2 }, // 203 - { 1, 2,18,17,-2,-1,17 }, // 204 - { 0, 1,17,-1, 2, 3, 6 }, // 205 - { 0, 2,18,18,-2,18, 2 }, // 206 - { 0, 2,18,18,-2, 2, 3 }, // 207 - { 1, 1,18,18,18, 2, 5 }, // 208 - { 0, 1,17,17,-2, 2, 3 }, // 209 - { 0, 2,18,18,-2,18, 2 }, // 210 - { 0, 2,18,17, 3, 6, 2 }, // 211 - { 0, 2,18,17,18, 2, 3 }, // 212 - { 0, 3,18,17,-3,18, 2 }, // 213 - { 0, 1,18,18,18, 2, 3 }, // 214 - { 0, 1,18,-2,-3, 2, 6 }, // 215 - { 0, 2,18,18,-2,18, 2 }, // 216 - { 1, 1,18,17,18, 2, 5 }, // 217 - { 0, 2,18,18,-2,18, 2 }, // 218 - { 0, 2,18,18,-2,18, 2 }, // 219 - { 1, 1,18,17,18, 2, 5 }, // 220 - { 0, 2,18,18,-2,18, 2 }, // 221 - { 0, 2,18,18,-2,18, 2 }, // 222 - { 0, 2,18,18,-2,18, 2 }, // 223 - { 0, 1,18,18,18, 2, 3 }, // 224 - { 1, 1,17,-2,17, 1, 2 }, // 225 - { 1, 1,17,17, 2,-1, 7 }, // 226 - { 0, 1,18,17, 4, 3, 1 }, // 227 - { 1, 3,18,-3,18, 2, 3 }, // 228 - { 0, 1, 1,18, 3, 2, 5 }, // 229 - { 0, 2,18,18,-2,18, 2 }, // 230 - { 0, 2,18,18,-2,18, 2 }, // 231 - { 0, 1,18,18, 3, 6, 2 }, // 232 - { 0, 1,17,17, 2,18, 4 }, // 233 - { 0, 1,17,17, 2,18, 4 }, // 234 - { 0, 2,18,18,-2,18, 2 }, // 235 - { 0, 2,18,18,-2,18, 2 }, // 236 - { 0, 2,18,18,-2,18, 2 }, // 237 - { 1, 2,18,-2,18, 3, 2 }, // 238 - { 1, 1,17,-2,17, 1, 2 }, // 239 - { 1, 1,18,18, 3, 2, 5 }, // 240 - { 0, 1,18,18,-1, 2, 3 }, // 241 - { 0, 2,18,18,-2,18, 2 }, // 242 - { 0, 2,18,18,-2,18, 2 }, // 243 - { 0, 1,18,17,18, 2, 5 }, // 244 - { 0, 2,18,18,-2,18, 2 }, // 245 - { 0, 2,18,18,-2,18, 2 }, // 246 - { 0, 2,18,18,-2,18, 2 }, // 247 - { 0, 2,18,18,-2,18, 2 }, // 248 - { 0, 1, 3,18,18, 2,17 }, // 249 - { 0, 2,18,18,-2,18, 2 }, // 250 - { 0, 2,18,18,-2,18, 2 }, // 251 - { 0, 2,18,18,-2,18, 2 }, // 252 - { 0, 2,18,18,-2,18, 2 }, // 253 - { 0, 2,18,18,-2,18, 2 }, // 254 - { 0, 2,18,18,-2,18, 2 }, // 255 -}; - -static const WavpackDecorrSpec high_specs [] = { - { 1, 2,18,18,18,-2, 2, 3, 5,-1,17, 4 }, // 0 - { 0, 1,18,17,-2, 2,18, 3, 7, 2, 5, 4 }, // 1 - { 1, 2, 1,18, 3, 6,-2,18, 2, 3, 4, 5 }, // 2 - { 0, 2,18,18,-2, 2,18, 3, 6, 2,17, 4 }, // 3 - { 1, 2,18,18, 2,18, 3, 2,-1, 4,18, 5 }, // 4 - { 1, 1, 7, 6, 5, 3, 4, 2, 5, 4, 3, 7 }, // 5 - { 1, 1,17, 3,18, 7, 2, 6, 1, 4, 3, 5 }, // 6 - { 1, 1,-2,18,18,18, 3,-2, 6, 5, 2, 1 }, // 7 - { 1, 2,18,18,-1,18, 2, 3, 6,-2,17, 5 }, // 8 - { 0, 1,17,17,18, 3, 6, 4, 5, 2,18,-2 }, // 9 - { 1, 2, 1,18,-2, 3, 5, 2, 4,-1, 6, 1 }, // 10 - { 0, 2,18,18, 3, 6,18, 2, 4, 8, 5, 3 }, // 11 - { 0, 1,-2, 1,18, 2,-2, 7,18, 2,-1, 5 }, // 12 - { 1, 1, 4, 3, 8, 1, 5, 2, 5, 6, 2, 8 }, // 13 - { 1, 1,17,18, 2, 6, 3, 4,-1, 1, 8, 6 }, // 14 - { 0, 1,18,18, 3, 6, 3,-2, 2, 5,-1, 1 }, // 15 - { 0, 1,18,18,17,-1, 2,-2,18, 3, 4, 5 }, // 16 - { 1, 2,18,17, 2,-2,18, 3, 5, 7, 2, 4 }, // 17 - { 1, 2,18,18, 3, 6,-2,18, 2, 5, 8, 3 }, // 18 - { 0, 1,18,17, 2,18,18, 2, 6, 5,17, 7 }, // 19 - { 1, 2,18,17, 2,18, 3, 2, 6,18,-1, 4 }, // 20 - { 1, 1, 5, 3, 6, 5, 3, 4, 1, 2, 4, 7 }, // 21 - { 1, 1, 5, 3, 6, 5, 3, 4, 1, 2, 4, 7 }, // 22 - { 0, 1,-2,18,18,18,-2, 3, 2, 4, 6, 5 }, // 23 - { 1, 2,18,17,-3, 3,-1,18, 2, 3, 6, 5 }, // 24 - { 0, 1,17,18, 7, 3,-2, 7, 1, 2, 4, 5 }, // 25 - { 1, 1, 2,18,18,-2, 2, 4,-1,18, 3, 6 }, // 26 - { 0, 3, 1,18, 4, 3, 5, 2, 4,18, 2, 3 }, // 27 - { 0, 1,-2,18, 2,18, 3, 7,18, 2, 6,-2 }, // 28 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 }, // 29 - { 1, 1,18,18, 5, 4, 6, 4, 5, 1, 4, 3 }, // 30 - { 1, 1,18, 3, 6, 5, 7, 8, 2, 3, 1,-1 }, // 31 - { 1, 1,18,18,18, 2,-2, 3, 5,18, 2, 8 }, // 32 - { 0, 2,18,17,-2, 2, 3,18,-3, 5, 2, 7 }, // 33 - { 1, 1, 1, 1,-1, 8,17, 3,-2, 2, 6,17 }, // 34 - { 0, 2,18,18,17, 2,-2, 3, 2, 4,18, 5 }, // 35 - { 1, 1,17,18, 2,-1, 5, 7,18, 3, 4, 6 }, // 36 - { 1, 1, 5, 4, 5,17, 3, 6, 3, 4, 7, 2 }, // 37 - { 0, 1,17, 3, 1, 7, 4, 2, 5,-2,18, 6 }, // 38 - { 0, 1,17,18, 2,18, 4, 3, 5, 7,-3, 6 }, // 39 - { 1, 2,17,17,-3,-2, 2, 8,18,-1, 3, 5 }, // 40 - { 0, 1,17,17,18, 2, 3, 6,-2, 8, 1, 7 }, // 41 - { 1, 1, 1, 2, 6,-2,18, 2, 5,-3, 7,-2 }, // 42 - { 0, 1,18,18, 3,18, 6, 8,-2, 2, 3, 5 }, // 43 - { 0, 1,18,17, 2,18,-2, 3, 7, 6, 2, 4 }, // 44 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 }, // 45 - { 1, 1,18,18, 2,-1, 3, 6, 1, 3, 4, 8 }, // 46 - { 0, 1,18,18, 3, 6, 5, 3,-2, 2,18,-1 }, // 47 - { 0, 1,18,17,-3,18, 2, 4,-2, 3, 6,17 }, // 48 - { 1, 3, 1, 2,17, 3,18, 7,-1, 5, 2, 4 }, // 49 - { 1, 1,18, 3,18, 6, 8,18,-2, 5, 7, 2 }, // 50 - { 0, 1,17, 2,18, 6, 3, 2, 5, 4, 8, 1 }, // 51 - { 0, 1,18,17,-1, 2, 3,18,18, 2, 3,17 }, // 52 - { 1, 1,18, 7, 6, 5, 5, 3, 1, 4, 2, 4 }, // 53 - { 1, 1, 6,17, 3, 8, 1, 5, 7,-1, 2, 1 }, // 54 - { 1, 1,18,-2,18, 3,-2, 2, 7, 4, 6,18 }, // 55 - { 1, 3,18,-3,18, 2, 3,18,-1, 7, 2, 5 }, // 56 - { 0, 2,18,-2, 7, 1, 3, 2, 4, 6,-3, 7 }, // 57 - { 1, 1,18,-2, 2,-3,18,-2,17,-1, 4, 2 }, // 58 - { 0, 3,17,17, 2, 5, 3, 7,18, 6, 4, 2 }, // 59 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 }, // 60 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 }, // 61 - { 1, 1,18,17, 4, 6, 6, 4, 5, 3, 4, 1 }, // 62 - { 0, 1,18, 5, 3, 6, 2, 3, 8, 1, 3, 7 }, // 63 - { 1, 2,18,17,-2, 2,18, 3, 5, 7,-1, 2 }, // 64 - { 0, 1, 1,18,18, 3, 6,-1, 4, 8, 5, 2 }, // 65 - { 1, 1, 1, 5, 3, 4, 1, 1, 3, 5, 7, 3 }, // 66 - { 0, 1, 3,18,18, 2,18,18,-1, 2, 3,18 }, // 67 - { 1, 2,18,18,-1,18, 2, 3, 4, 6,18, 5 }, // 68 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 }, // 69 - { 1, 1,18, 3, 1, 4, 5, 2, 7, 1, 3, 6 }, // 70 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 }, // 71 - { 1, 2,18,18,-1,18, 2, 3, 5,-2, 6, 8 }, // 72 - { 1, 1,17,18, 4, 8, 3, 2, 5, 2, 7, 6 }, // 73 - { 1, 4, 1, 2, 5,18,-2, 2, 3, 7,-1, 4 }, // 74 - { 0, 2,18,17,-1, 3, 6,18, 2, 3, 7, 5 }, // 75 - { 0, 1,-2,18, 2,-3, 6,18, 4, 3,-2, 5 }, // 76 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 }, // 77 - { 0, 1,17,17, 6, 2, 4, 8, 3, 5,-1,17 }, // 78 - { 1, 1,18, 3,18, 6, 8,18,-2, 5, 7, 2 }, // 79 - { 1, 2,17,17,-3, 2,18,-2, 8, 3, 6,-1 }, // 80 - { 1, 1,18,-2,17,18, 2, 3,-2, 6, 5, 4 }, // 81 - { 1, 2,18,17,-1, 3,18, 2, 5, 3, 6,-3 }, // 82 - { 0, 1,18,17, 2,18, 7,18, 2, 4, 3,17 }, // 83 - { 1, 3,18,18, 5, 6, 4, 3, 4,18, 6, 5 }, // 84 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 }, // 85 - { 1, 1, 7, 6, 5, 3, 4, 2, 5, 4, 3, 7 }, // 86 - { 0, 1,-2,18,18,18, 3, 6, 4, 2, 5, 2 }, // 87 - { 0, 3,18,17,-3,18, 3, 2, 5,-1,17, 3 }, // 88 - { 1, 1,17,18, 7, 3, 1, 7, 4, 2, 6, 5 }, // 89 - { 1, 1,18, 2,-2,-1,18, 5, 3,-2, 1, 2 }, // 90 - { 0, 3,18,18,-1, 3, 2, 7, 5,18, 4, 3 }, // 91 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 }, // 92 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 }, // 93 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 }, // 94 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 }, // 95 - { 1, 1,17,18, 2,-2, 4, 8,18, 3, 6, 5 }, // 96 - { 0, 2,18,17, 3, 5,-2, 7, 2,18, 3,-1 }, // 97 - { 1, 1,18, 2,-2,-1,18, 5, 3,-2, 1, 2 }, // 98 - { 0, 2, 3,17,18,18, 2, 5, 7, 6,18, 3 }, // 99 - { 1, 1,17,18,18, 4, 3, 2,18, 7, 8,-1 }, // 100 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 }, // 101 - { 0, 1,17, 1, 2, 3, 5, 6, 1, 4, 8,17 }, // 102 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 }, // 103 - { 0, 2,18,17,-1,18,-3, 2, 8, 3, 6,17 }, // 104 - { 1, 1,17,17, 1, 2, 4, 5,-1, 2, 1, 6 }, // 105 - { 1, 1, 1, 2, 6,-2,18, 2,-3, 3,-2, 5 }, // 106 - { 0, 1,18, 3,18, 6,18, 5, 2, 4,-1, 8 }, // 107 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 }, // 108 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 }, // 109 - { 1, 1,18,18,-1, 2,18, 3, 6, 4,-2, 7 }, // 110 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 }, // 111 - { 0, 2,-1,18,18,18, 2,-2, 4, 7, 2, 3 }, // 112 - { 0, 3, 3,17,-2, 5, 2, 7,18, 6, 4, 5 }, // 113 - { 0, 1,17, 6,18, 3, 8, 4, 5, 3, 8,18 }, // 114 - { 0, 2,18, 2, 6, 2,18, 3, 2, 4, 5, 8 }, // 115 - { 0, 1, 3,18,18, 2,18,-1, 2,18, 2,17 }, // 116 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 }, // 117 - { 0, 1, 3, 6,17,-2, 5, 1, 2, 7, 4, 8 }, // 118 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 }, // 119 - { 1, 3, 3,18,17, 5, 6, 2, 7,-2, 8,18 }, // 120 - { 1, 1,18,-1, 3, 1, 7, 2,-1, 4, 6,17 }, // 121 - { 1, 1,18, 2,-2,-1,18, 5, 3,-2, 1, 2 }, // 122 - { 0, 2,18, 1, 2,18, 3, 6, 5, 2, 4, 8 }, // 123 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 }, // 124 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 }, // 125 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 }, // 126 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 }, // 127 - { 1, 1,17,-2, 2,18,18, 8, 5, 3, 2, 6 }, // 128 - { 0, 1,18,17, 2,18, 3, 2, 7,-2,18, 4 }, // 129 - { 1, 2, 1,18, 2, 3,-1, 5, 6, 4, 7,17 }, // 130 - { 0, 2,18,17, 3, 6,-2, 2, 3, 8, 5,17 }, // 131 - { 0, 2,18,18, 3, 2,18,-1, 2, 4, 3,17 }, // 132 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 }, // 133 - { 1, 2,17,-1,18, 2, 3,-2, 5,18, 2, 7 }, // 134 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 }, // 135 - { 1, 2,18,-3,18, 2, 3,-2,18, 5, 6,-3 }, // 136 - { 0, 2,18,17, 3, 5,-2, 7, 2,18, 3,-1 }, // 137 - { 1, 1, 1,18,-1, 2, 3, 1,-2, 8, 2, 5 }, // 138 - { 0, 1,18,18, 3, 6,18, 2, 3, 4, 8, 5 }, // 139 - { 0, 1,-2, 1,18, 2,-2, 5, 7,18, 2,-1 }, // 140 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 }, // 141 - { 1, 1,17,18,-1, 2, 8, 3, 4, 5, 1, 7 }, // 142 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 }, // 143 - { 0, 2,18,18,-1, 2,18, 3,-2, 5, 4, 2 }, // 144 - { 1, 1,18,17, 2,18, 3, 8, 5, 2, 7,17 }, // 145 - { 0, 1,18,18, 3,18, 6, 8,-2, 2, 3, 5 }, // 146 - { 0, 1,18,18, 2,18, 2, 6,18, 2,17, 7 }, // 147 - { 1, 3,18,17,18, 2, 8,18, 5,-1, 3, 6 }, // 148 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 }, // 149 - { 1, 1,18, 7, 6, 5, 5, 3, 1, 4, 2, 4 }, // 150 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 }, // 151 - { 1, 2,18,17,-1, 3, 6,18, 2, 5, 8, 3 }, // 152 - { 0, 1,17,18,18, 4, 7, 2, 3,-2,18, 5 }, // 153 - { 1, 2,18, 1, 2, 6, 2, 5,18, 2, 4, 8 }, // 154 - { 0, 4,18, 4, 1, 2, 3, 5, 4, 1, 2, 6 }, // 155 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 }, // 156 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 }, // 157 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 }, // 158 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 }, // 159 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 }, // 160 - { 0, 2,18,17, 2,-1,18, 3,-3, 5, 2, 4 }, // 161 - { 0, 1,17,17, 3, 6, 3, 5,-2, 2,18,-1 }, // 162 - { 0, 2,18,18, 3,-2,18, 2,-3, 5, 3, 6 }, // 163 - { 1, 1,17,17, 2, 4, 1, 3, 5, 2, 6,-3 }, // 164 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 }, // 165 - { 0, 1,17, 1, 3, 2, 7, 1, 6, 3, 4, 8 }, // 166 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 }, // 167 - { 0, 1,17,-1,18, 2, 1, 5, 3, 8,-1,-2 }, // 168 - { 1, 1,17,18,-1, 8, 2, 5, 3, 4, 1, 6 }, // 169 - { 1, 2, 1,18, 3,-1, 5, 1, 2, 4, 7, 6 }, // 170 - { 0, 1,18,18, 3, 6, 5, 3,-2, 2,18,-1 }, // 171 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 }, // 172 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 }, // 173 - { 0, 1, 1,18,-1, 3, 8, 5, 6, 1, 2, 3 }, // 174 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 }, // 175 - { 0, 2,18,18, 2, 3, 6,18,-1, 4, 2, 3 }, // 176 - { 1, 1, 1, 3, 5,18, 2, 6, 7, 2, 3, 1 }, // 177 - { 1, 1, 1, 3, 8,18, 5, 2, 7, 1, 3,-2 }, // 178 - { 0, 2,17, 2,18, 3, 6, 2, 4, 5, 8, 3 }, // 179 - { 0, 1,18,17, 2,18, 3, 2, 7,-2,18, 4 }, // 180 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 }, // 181 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 }, // 182 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 }, // 183 - { 1, 2,18,-3,18,-1, 3,-2, 5, 7, 1, 2 }, // 184 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 }, // 185 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 }, // 186 - { 0, 3,18,18, 2, 6,18, 5,18, 2, 3,17 }, // 187 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 }, // 188 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 }, // 189 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 }, // 190 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 }, // 191 - { 1, 3, 1,-1, 1, 3,-2, 2, 5, 7,-3,18 }, // 192 - { 1, 2,18, 7, 3,-3, 2, 8, 2, 5, 4,17 }, // 193 - { 1, 1, 1, 4, 5, 1, 3, 4, 6, 7, 8, 3 }, // 194 - { 0, 1,18,17, 2,18,-1, 2, 3,18, 2, 4 }, // 195 - { 0, 2,18,18,-2,18, 2, 3, 4, 7, 5,17 }, // 196 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 }, // 197 - { 1, 1,17,18, 2, 1, 3, 2, 5, 1, 2, 3 }, // 198 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 }, // 199 - { 0, 2,18,18,-1, 2, 3, 5, 8, 6, 1,-2 }, // 200 - { 0, 1,17,18, 8, 3, 4, 6, 5, 2, 8, 7 }, // 201 - { 1, 2, 1, 3,-2,18, 2, 5, 1, 7,-1,-2 }, // 202 - { 0, 3,18,17,-1, 3,18, 2, 3, 6, 4,17 }, // 203 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 }, // 204 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 }, // 205 - { 1, 2,18,18, 4,18, 6, 7, 8, 3,18, 2 }, // 206 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 }, // 207 - { 0, 2,17,-3,17, 2,-2, 8, 3,18, 4,-3 }, // 208 - { 1, 1,18,17, 3, 5, 6, 2, 8, 1, 3, 7 }, // 209 - { 0, 1,18,18, 3, 6, 5, 3,-2, 2,18,-1 }, // 210 - { 0, 3,18,18, 2, 6,18, 5,18, 2, 3,17 }, // 211 - { 1, 1,18,18, 5, 4, 6, 4, 5, 1, 4, 3 }, // 212 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 }, // 213 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 }, // 214 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 }, // 215 - { 0, 2, 3,17,18,-3, 2, 5,18, 6,-1, 7 }, // 216 - { 1, 1,17,18, 3, 2, 5,-1, 6, 8, 4, 7 }, // 217 - { 1, 1,18, 1,-2, 3, 2, 1, 7, 6, 3, 4 }, // 218 - { 0, 3, 1, 2,17, 3,18, 2, 7, 5, 4,-1 }, // 219 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 }, // 220 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 }, // 221 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 }, // 222 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 }, // 223 - { 1, 1,17,-2, 2,18,18, 8, 5, 3, 2, 6 }, // 224 - { 0, 2,18, 5,18, 2, 3, 7,-2, 1, 6, 8 }, // 225 - { 0, 1, 2,-1,18,-1, 2, 4,-3, 5,18, 3 }, // 226 - { 0, 1, 3,17,18, 5, 2,18, 7, 3, 6, 5 }, // 227 - { 1, 4, 1, 2, 5,18,-2, 2, 3, 7,-1, 4 }, // 228 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 }, // 229 - { 0, 1, 1,18, 2, 1, 3, 4, 1, 5, 2, 7 }, // 230 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 }, // 231 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 }, // 232 - { 0, 1,17,17,18, 2, 4, 5,18,-2, 6, 3 }, // 233 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 }, // 234 - { 0, 2,18,18,-1, 3, 5, 6, 8,18, 2, 3 }, // 235 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 }, // 236 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 }, // 237 - { 0, 1,18,18, 4, 6, 8,18, 7, 3, 2, 5 }, // 238 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 }, // 239 - { 0, 2,-1,18,18,18, 2, 4,-2, 2, 3, 6 }, // 240 - { 0, 2,18,-2, 7, 1, 3, 2, 4, 6,-3, 7 }, // 241 - { 1, 1,17,18, 8, 3, 4, 6,-2, 5, 3, 8 }, // 242 - { 0, 2,18, 1, 2, 6, 2, 8, 3,18, 5, 4 }, // 243 - { 1, 1, 3,18,18, 2,18, 2,18, 3, 2,18 }, // 244 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 }, // 245 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 }, // 246 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 }, // 247 - { 1, 1, 3,17,18, 5, 2, 6, 7, 1, 4, 8 }, // 248 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 }, // 249 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 }, // 250 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 }, // 251 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 }, // 252 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 }, // 253 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 }, // 254 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2, 8 }, // 255 -}; - -static const WavpackDecorrSpec very_high_specs [] = { - { 1, 2,18,18, 2, 3,-2,18, 2, 4, 7, 5, 3, 6, 8,-1,18, 2 }, // 0 - { 0, 1,18,18,-1,18, 2, 3, 4, 6, 5, 7,18,-3, 8, 2,-1, 3 }, // 1 - { 1, 2, 1,18,-2, 4,18, 2, 3, 6,-1, 7, 5,-2,18, 8, 2, 4 }, // 2 - { 0, 1,17,17, 2, 3, 4,18,-1, 5, 6, 7,18, 2, 8,17, 3,-2 }, // 3 - { 1, 1,18,18, 2,18, 3, 2,18, 4,-1, 3,18, 2, 6, 8,17, 5 }, // 4 - { 0, 2,18,17, 2, 3,-2, 5,18,-3, 2, 4, 7, 3, 6, 8, 5,17 }, // 5 - { 1, 1,18,-2, 2,-3,18, 5,-2,18, 2, 3, 6, 2,17, 4, 7,-1 }, // 6 - { 1, 1,17, 8,18, 3,-2, 2, 5, 4,18, 6, 3, 8, 7, 2, 5, 4 }, // 7 - { 0, 2,18,17,-2, 2,18, 3, 2, 5,-3, 4, 7,18, 3, 8, 6, 2 }, // 8 - { 1, 1, 3, 6, 5, 5, 1, 3, 7, 4, 2, 6, 4,18, 3, 7, 5, 6 }, // 9 - { 1, 2, 1,18, 3, 2,-2, 1, 5, 4, 6, 2, 7, 1, 8, 3,-1, 1 }, // 10 - { 0, 1,18,18, 2, 3, 6, 3, 5,-2, 2, 4,18, 3,-2,-1, 6, 7 }, // 11 - { 0, 1,-2,18, 2,18, 7, 2, 6,-2, 3, 4,18,18, 2,-3, 8, 5 }, // 12 - { 0, 2,18,18,18, 2, 4, 3,18, 5, 3, 6,-2, 2, 4,18, 8, 7 }, // 13 - { 0, 1,-2, 1,18, 2,-2,18,-1, 5, 7, 2, 3, 4,18, 2, 6, 2 }, // 14 - { 1, 1,17,18, 3, 2, 1, 7,-1, 2, 4, 3, 5, 6,-2,18, 7, 8 }, // 15 - { 1, 1,18,18, 2,18, 3, 4, 6,-2,18, 5, 8, 2, 3, 7, 4,-1 }, // 16 - { 0, 1,18,18,18,-1, 2, 3, 4, 6, 8,18, 3, 5, 2, 6, 7, 4 }, // 17 - { 1, 1,17,-2,18,18, 2, 5, 3, 8, 2,-1, 6, 1, 3, 4, 7, 5 }, // 18 - { 0, 1,17,17,18, 2, 3, 6,-2, 8, 1, 7, 5, 2, 3, 1, 4, 8 }, // 19 - { 1, 1,17,17, 3, 2, 7, 1, 4, 3, 6, 2, 5,-2, 8, 7,18, 6 }, // 20 - { 0, 1,18,17,-2, 2,18, 3,-3, 7, 6, 5, 2, 4,-1, 8, 3,17 }, // 21 - { 1, 1, 2,18,18,-2, 2, 4,-1, 5,18, 3, 8, 6, 2, 7,17, 4 }, // 22 - { 0, 1,17, 3, 6, 8, 5, 4, 3, 8, 1,18, 7, 2, 4, 5, 6, 3 }, // 23 - { 1, 2,17,18, 4, 8, 3, 2, 5, 7, 6, 8, 2, 7,-2,18, 3, 4 }, // 24 - { 1, 1, 6, 5, 5, 3, 4, 7, 3, 2, 4, 6, 3, 7, 1, 5, 2, 4 }, // 25 - { 1, 1, 1,18,-1, 2, 1, 3, 8,-2, 2, 5, 6, 3, 8, 7,18, 4 }, // 26 - { 0, 1, 1,17,-1,18, 3, 2, 5, 4, 6, 7, 8, 3, 4, 2, 1,-2 }, // 27 - { 0, 1,18, 2,18,18, 2,18, 6,-2,18, 7, 5, 4, 3, 2,18,-2 }, // 28 - { 0, 3, 1, 4,18, 3, 2, 4, 1, 5, 2, 3, 6,18, 8, 7, 2, 4 }, // 29 - { 0, 1,17,-2, 1,-3, 2,18, 3,-2, 4,18, 3, 6, 7,-3, 2, 8 }, // 30 - { 1, 1,17,18,18, 4, 2, 3, 7, 6,18, 8, 5,-1, 4, 2, 3,17 }, // 31 - { 1, 2,18,-1,17,18, 2, 3,-2,18, 5, 8, 2, 4, 3, 7, 6,-1 }, // 32 - { 1, 1,18,18,18,-2, 4, 2, 3,18, 5, 8, 2, 4, 6, 7,-2, 3 }, // 33 - { 1, 2,18,18,-2,18,-1, 3, 2, 5,18,-2, 7, 2, 3, 4, 6, 8 }, // 34 - { 0, 1,17,18,-1, 2, 4,18, 8, 3, 6, 5, 7,-3, 2, 4, 3,17 }, // 35 - { 1, 1,18,18,17, 2,-1,18, 3, 2,18, 6, 5, 4,18, 7, 2,-1 }, // 36 - { 0, 2, 1,18,-1,18, 3, 2, 4, 6,-3, 7,-1, 5, 1, 2, 3, 8 }, // 37 - { 1, 1, 1,17,-2, 2,-3, 6, 3, 5, 1, 2, 7, 6, 8,-2, 4, 1 }, // 38 - { 0, 1,17,-1, 5, 1, 4, 3, 6, 2,-2,18, 3, 2, 4, 5, 8,-1 }, // 39 - { 0, 2,18,18,17, 2, 3,-2, 5,18, 2, 4, 7, 8, 6,17, 3, 5 }, // 40 - { 1, 1, 1, 5, 1, 3, 4, 3, 7, 5, 1, 3, 6, 1, 2, 4, 3, 8 }, // 41 - { 1, 2, 1,-1, 3, 2,18, 7,-2, 5, 2, 6, 4, 3,-1,18, 8, 7 }, // 42 - { 0, 2,18,17, 3,18, 2, 5, 4, 3, 6, 2, 7, 8,18, 3, 4, 5 }, // 43 - { 1, 1, 3, 6,17, 8, 7, 5,18,-1, 1, 2, 3, 4, 2, 6, 8, 1 }, // 44 - { 0, 2,18,18, 3,-3,18, 2, 6, 5, 3, 7,18, 4,-2, 8, 2, 3 }, // 45 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 }, // 46 - { 1, 1,17, 1, 7, 2, 3,18,-2, 3, 6, 4, 2, 7, 8, 5, 3,17 }, // 47 - { 1, 1, 3, 6, 5, 5, 1, 3, 7, 4, 2, 6, 4,18, 3, 7, 5, 6 }, // 48 - { 0, 1,18,18,18, 2, 4,-1,18, 8,-1, 2, 3, 4, 6,-2, 1, 7 }, // 49 - { 1, 1,18,-2,17,18, 2, 6, 3,-2, 5, 4, 7, 1,-3, 8, 2, 6 }, // 50 - { 0, 1,17,18,18, 4, 2, 7, 3, 6,-2,18, 8, 4, 5, 2, 7,17 }, // 51 - { 1, 1,18,18, 5, 4, 6, 4, 1, 5, 4, 3, 2, 5, 6, 1, 4, 5 }, // 52 - { 0, 1,18,18,-2,18, 2,-3, 3, 8, 5,18, 6, 4, 3,-1, 7, 2 }, // 53 - { 1, 1,18, 2,-2,-3,18, 5, 2, 3,-2, 4, 6, 1,-3, 2, 7, 8 }, // 54 - { 0, 1,18, 3, 5, 8, 2, 6, 7, 3, 1, 5, 2,-1, 8, 6, 7, 4 }, // 55 - { 1, 1, 4, 3, 8, 1, 5, 6, 2, 5, 8,-2, 2, 7, 3,18, 5, 4 }, // 56 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 }, // 57 - { 1, 1,17, 3,18,18, 7, 2, 4,18, 6, 2, 3,-1, 8, 5,18,-3 }, // 58 - { 0, 1, 3,17,18, 2,18, 6, 7,-3,18, 2, 5, 6, 3, 8, 7,-1 }, // 59 - { 1, 1,18,18, 2,18,18, 2,-1, 7, 3,18, 5, 2, 6, 4,-1,18 }, // 60 - { 0, 3,18, 3, 4, 1, 5, 2,18, 4, 2, 3,18, 7, 6, 1, 2, 4 }, // 61 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 }, // 62 - { 1, 1,17, 1,18, 2, 3, 6, 4, 5, 7,18, 3, 8, 2, 4,-2,17 }, // 63 - { 1, 2,18,17, 2, 3, 5,18, 6,-2, 7, 3, 2, 4,18, 8,-1, 5 }, // 64 - { 0, 2, 1,18,-1,18, 3, 2, 4, 6,-3, 7,-1, 5, 1, 2, 3, 8 }, // 65 - { 1, 1, 1,18,-1, 8, 2, 6, 3,-2, 1, 2, 5, 4,-3, 8, 6, 3 }, // 66 - { 0, 1,18,18, 2,18, 2,18, 7, 6,18, 2,-2, 3, 5, 4,18, 8 }, // 67 - { 1, 2,18,17, 2, 3,18,-1, 2, 3, 6,18, 5, 4, 3, 7, 2, 8 }, // 68 - { 1, 2,18,18, 3,-2, 4,18, 5, 7, 6, 2, 4,-3, 8, 5,18, 3 }, // 69 - { 1, 1,17,-2,18,18, 2, 5, 3, 8, 2,-1, 6, 1, 3, 4, 7, 5 }, // 70 - { 1, 1, 3,17,18, 5, 7, 2, 4, 6, 1, 8,-1, 3, 7, 4, 1, 2 }, // 71 - { 0, 2, 1,-2, 2,18, 3, 5, 2, 4, 7,-1, 2, 3, 5,18,-2, 4 }, // 72 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 }, // 73 - { 1, 1, 1, 2,-2, 6,18,-3, 2, 7, 3,-2, 5, 6, 1, 8, 2, 4 }, // 74 - { 0, 1,18,18,18, 3,-2, 6,18, 2, 4, 3, 5, 8, 7, 6, 2,-2 }, // 75 - { 1, 1, 1, 5, 1, 3, 4, 3, 7, 5, 1, 3, 6, 1, 2, 4, 3, 8 }, // 76 - { 0, 1, 3,17,18, 2, 5,18, 6, 7, 5,-2, 2, 4,18, 3, 6, 8 }, // 77 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 }, // 78 - { 0, 2,17,-1,18, 2, 4,-1, 8, 3,18, 7,-3, 4, 5, 1, 2,-2 }, // 79 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 8, 6, 4, 5, 7,-1 }, // 80 - { 1, 1,18,18, 3, 6, 4, 8,-2, 2, 5, 3, 7,18, 6, 8, 4, 2 }, // 81 - { 1, 1,17,18,18,-2, 5, 2, 3, 1, 4,-1, 8, 6, 5, 3, 2,18 }, // 82 - { 1, 1,17,17, 1, 2, 4, 5, 2, 6,-1, 3, 1, 1,-2, 4, 2, 7 }, // 83 - { 1, 1,17, 1, 7, 2, 3,18,-2, 3, 6, 4, 2, 7, 8, 5, 3,17 }, // 84 - { 0, 1,18,17,-2,-3, 1, 2, 3, 2, 5, 4, 7,-3, 6,-2, 2, 1 }, // 85 - { 1, 1, 1, 3, 5,18, 1, 2, 7, 3, 6, 2, 5, 8,-1, 1, 4, 7 }, // 86 - { 1, 1,17, 3, 6, 8, 1, 4, 5, 3,-2, 7, 2, 8, 5, 6,18, 3 }, // 87 - { 1, 1,17,18, 2, 4, 8,-2, 3, 1, 5, 6, 7, 1, 2, 3, 4, 7 }, // 88 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 }, // 89 - { 1, 1, 3, 1, 8,18, 5, 2, 3,18, 6, 7,-2, 4, 3, 2, 8,18 }, // 90 - { 0, 1,18,17, 2,18, 3, 4,-1,18, 7, 6, 2, 8, 4,18,18, 5 }, // 91 - { 0, 1,18,18, 2,18,18, 2, 7,-2, 6, 5, 4, 3,18, 3, 2,17 }, // 92 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 }, // 93 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 }, // 94 - { 1, 1,17, 8,18, 3, 2, 1, 5, 4, 6,-1, 3,-3, 8,18, 7, 2 }, // 95 - { 1, 2,18,17,18, 2, 3, 5,-2,18, 6,-1, 2, 3, 7, 4, 8,17 }, // 96 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 8, 6, 4, 5, 7,-1 }, // 97 - { 1, 2,18,18,-2,17, 2,18, 3, 4,18, 8, 7,-1, 2, 4, 5,17 }, // 98 - { 0, 2,17,-3,17, 3, 2,-2,18, 8, 4,-3, 2,18, 5, 3,-2, 6 }, // 99 - { 0, 1,18,18, 2,18,18, 2, 7,-2, 6, 5, 4, 3,18, 3, 2,17 }, // 100 - { 0, 2, 1,18,-1, 3, 5, 2,-3,18, 7, 3,-1, 6, 4, 2,17, 5 }, // 101 - { 1, 1,17,-2,17, 2,-3, 1, 5,-1, 4, 6, 3, 2, 8, 7,-2, 5 }, // 102 - { 1, 1, 1,18, 1, 3, 5, 8, 6, 2, 3,-1, 7, 1, 4, 8, 5,-3 }, // 103 - { 0, 2, 3,18,18, 2,18,-2, 6, 5, 7, 2, 4,18, 3, 6,-3, 5 }, // 104 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 }, // 105 - { 1, 1, 3, 6,17, 8, 7, 5,18,-1, 1, 2, 3, 4, 2, 6, 8, 1 }, // 106 - { 0, 4,18, 2,17, 3,18,-2, 2, 6,18, 2, 7, 3, 5, 4, 8,18 }, // 107 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 }, // 108 - { 0, 1,18,18, 2, 3, 6, 3, 5,-2, 2, 4,18, 3,-2,-1, 6, 7 }, // 109 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 }, // 110 - { 1, 1,17, 1, 2, 5, 3,-2, 1, 4, 3, 7, 6,-3, 2, 1, 1, 2 }, // 111 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 }, // 112 - { 1, 1,18,18,-2,18,-2, 2, 3, 6,18, 4,-1, 2, 3, 8, 1, 4 }, // 113 - { 1, 1,17,-2,17, 2,-3, 1, 5,-1, 4, 6, 3, 2, 8, 7,-2, 5 }, // 114 - { 0, 1,17,17,18, 3, 2,18,18, 6, 8, 2,-2, 3, 5, 4,17,18 }, // 115 - { 1, 1, 1, 5, 1, 3, 4, 3, 7, 5, 1, 3, 6, 1, 2, 4, 3, 8 }, // 116 - { 1, 1, 1, 3,-3,18,18, 6, 5,18, 2,-1, 3, 8, 7,-3, 4,17 }, // 117 - { 1, 1,18, 1, 2, 1, 3, 8, 7, 4, 1, 5, 2,-1,-3,18, 6, 2 }, // 118 - { 0, 1,18, 3, 5, 2, 6, 8,18, 5, 7, 2, 3,-1, 6, 7, 8, 5 }, // 119 - { 0, 2,18, 3,-2, 7, 8, 2, 5, 4,-3, 8, 3, 2,18, 5, 4, 6 }, // 120 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 }, // 121 - { 1, 3, 1, 1, 2, 5, 2, 7, 4, 3,-1,18,-2, 8, 2, 1, 6, 7 }, // 122 - { 0, 1, 3,17,18, 5, 2, 6, 7,18, 4, 5, 3, 6,18, 2, 7, 8 }, // 123 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 }, // 124 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 }, // 125 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 }, // 126 - { 0, 1, 1,18, 1, 2, 3, 5, 1, 2, 6, 7, 4, 3, 8, 1,17, 5 }, // 127 - { 1, 2,17,-1,18,-2, 2, 3, 5,18, 2, 4, 6, 7, 3,-1, 5, 8 }, // 128 - { 1, 1,18,18,-3,18,-2, 2, 3,-2,18, 6, 4, 5, 8, 3,17,-3 }, // 129 - { 1, 1,18, 7, 6, 5, 5, 3, 1, 4, 2, 7, 3, 4,-3, 6,18, 8 }, // 130 - { 0, 2,18,18, 2, 3, 5,18, 2, 4, 3, 6,18, 7, 8,-1, 5, 2 }, // 131 - { 0, 1,18,17,-1, 2,18, 3, 2,18, 4, 3,18, 2, 6, 5, 8,17 }, // 132 - { 0, 2,18,17, 2, 3,18, 5,-1, 6, 7, 8, 2, 3, 4, 5,18, 6 }, // 133 - { 1, 2,18,-3,18, 2, 3,-2,-3, 5,18, 7, 6, 2, 4, 3, 8,-2 }, // 134 - { 1, 1,17,18,18,-2, 2, 3, 5, 4, 8,18,-1, 5, 3, 6,-2, 7 }, // 135 - { 1, 2,18,17, 2,-2,18, 3,-1, 4,18, 2, 7, 5, 3, 8, 6, 4 }, // 136 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 }, // 137 - { 1, 1, 1, 5, 1, 3, 4, 3, 7, 5, 1, 3, 6, 1, 2, 4, 3, 8 }, // 138 - { 0, 2,18,18, 3, 3,-2, 2, 5,18, 6, 3,-1, 4, 7,-1, 1, 2 }, // 139 - { 0, 1,-2, 1,18, 2,-2, 5, 7,18, 3, 2, 6, 2,-1, 4,-2,17 }, // 140 - { 0, 2,18,18,18, 2, 3,-2,18, 5, 4, 2, 6, 8, 3,-2, 4,18 }, // 141 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 }, // 142 - { 1, 1,17,18,-1, 3, 2, 5, 1, 3, 2, 8, 4, 7, 6, 2,-1, 5 }, // 143 - { 1, 1,17,18,18, 4, 2, 3, 7, 6,18, 8, 5,-1, 4, 2, 3,17 }, // 144 - { 0, 1,18,18,-2,18, 2, 3, 4, 5, 6,18, 8, 2, 3, 7,-2, 4 }, // 145 - { 0, 1,18,-2,18,18,-3,-2, 2, 3, 5, 8, 1, 2, 6, 4, 7,-1 }, // 146 - { 0, 1,18,17, 2,18, 3,-2, 2, 7, 6, 4,18, 3, 8, 7, 4, 2 }, // 147 - { 1, 1,17,18,18, 4, 2, 3, 7, 6,18, 8, 5,-1, 4, 2, 3,17 }, // 148 - { 1, 1,18,17,18, 2, 5, 3,-2,18, 6, 2, 3, 4, 8, 7, 5,-1 }, // 149 - { 0, 1, 2,-1,18,-1, 2, 4,-3,18, 5, 3, 6,18, 2, 4, 7, 8 }, // 150 - { 1, 1,17,18, 8, 3, 6, 4,-1, 5, 2, 7, 3, 8, 6, 5,18, 4 }, // 151 - { 0, 2,18, 3,-2, 7, 8, 2, 5, 4,-3, 8, 3, 2,18, 5, 4, 6 }, // 152 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 }, // 153 - { 1, 1, 1,18,-1, 8, 2, 6, 3,-2, 1, 2, 5, 4,-3, 8, 6, 3 }, // 154 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 }, // 155 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 }, // 156 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 }, // 157 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 }, // 158 - { 0, 1,17,18,18, 4, 2, 7, 3, 6,-2,18, 8, 4, 5, 2, 7,17 }, // 159 - { 1, 2,18,-1,18, 3,-2,18, 2, 5, 3, 6, 7, 2,-1,18, 8, 4 }, // 160 - { 1, 2, 1,18,-2, 4,18, 2, 3, 6,-1, 7, 5,-2,18, 8, 2, 4 }, // 161 - { 1, 2, 1,18,-3, 2, 3,18,-1, 5, 6, 2, 8, 3, 4, 1,-2, 7 }, // 162 - { 0, 1, 1,17,-1,18, 3, 2, 5, 4, 6, 7, 8, 3, 4, 2, 1,-2 }, // 163 - { 1, 1,18,17,18, 4, 3, 5, 1, 2, 6, 3, 4, 7, 1, 8, 5, 2 }, // 164 - { 0, 1,18,-2, 7, 1, 3, 2,-3, 4, 6,-2, 7, 8, 1, 5, 4, 3 }, // 165 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 }, // 166 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 }, // 167 - { 0, 2,18,18,18,-2, 2, 5, 3, 7,18, 2, 4,-3, 5, 6, 3, 8 }, // 168 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 }, // 169 - { 0, 3, 3,18,-1, 5, 2, 7,18, 6, 5, 2, 4, 3,-1, 7,18, 6 }, // 170 - { 0, 2,18,18,18, 4, 3, 2, 6, 4, 8,18, 5, 3, 2, 7,-2, 6 }, // 171 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 }, // 172 - { 0, 2,18,18,18, 2, 3,-2,18, 5, 4, 2, 6, 8, 3,-2, 4,18 }, // 173 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 }, // 174 - { 1, 1,17, 8,18, 3, 2, 1, 5, 4, 6,-1, 3,-3, 8,18, 7, 2 }, // 175 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 }, // 176 - { 0, 1,-1,18,18,18, 2, 4, 6,-2, 2, 8, 3, 4,18, 7,-1, 6 }, // 177 - { 0, 1,18, 1,-2, 2, 4, 1, 3,-1, 2, 5, 7, 1, 6, 8,-2,17 }, // 178 - { 0, 1,17,17,18, 2, 5, 4,18, 3, 8, 7, 4, 6, 8, 1, 5, 2 }, // 179 - { 1, 2,18,18, 5, 4, 6, 3, 4,18, 8, 4,-1, 7, 5, 3, 6, 2 }, // 180 - { 0, 1,18,18,-3,18, 3, 6, 2, 5, 7,18, 3, 8,-1, 4, 5, 2 }, // 181 - { 1, 1,18, 2,-2,-3,18, 5, 2,-2, 4, 3, 6,18, 8,-1, 2, 7 }, // 182 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 }, // 183 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 }, // 184 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 }, // 185 - { 1, 1,17, 1, 7, 2, 3,18,-2, 3, 6, 4, 2, 7, 8, 5, 3,17 }, // 186 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 }, // 187 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 }, // 188 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 }, // 189 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 }, // 190 - { 0, 1,17,18, 3,18, 2, 5, 4, 7,-3, 6, 3, 2,18, 4, 7, 3 }, // 191 - { 1, 1, 1, 7, 4, 5, 3, 4, 5, 1, 3, 6, 3, 2, 4, 8,-2, 7 }, // 192 - { 0, 1, 1,18,-1,-2,18, 3, 2,-1, 6, 7, 4, 5, 3,18, 2,-3 }, // 193 - { 1, 1,18,18,-1, 3, 6,18, 5, 4, 8, 2, 3, 6,18, 7, 4,-2 }, // 194 - { 0, 2,18,18, 2, 6,18, 2,18, 5, 3,18, 2, 4, 7, 8, 3,18 }, // 195 - { 1, 1, 3,18,18, 5,18, 6, 2, 4, 7,-2,18, 5, 8, 6, 3, 2 }, // 196 - { 0, 1,18,-2, 7, 1, 3, 2,-3, 4, 6,-2, 7, 8, 1, 5, 4, 3 }, // 197 - { 1, 1,18,-2,18, 2, 5,18, 3,-2, 4, 7, 2,-1, 8, 6, 5, 1 }, // 198 - { 1, 1,17,17, 5,18, 4, 1, 2, 8, 6, 4,-2, 3, 5,-1, 1, 8 }, // 199 - { 0, 2, 1, 2,17, 3, 7,18, 2,-1, 4, 5,18, 2, 7, 3, 6, 8 }, // 200 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 }, // 201 - { 1, 1, 3, 6,17, 8, 7, 5,18,-1, 1, 2, 3, 4, 2, 6, 8, 1 }, // 202 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 }, // 203 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 }, // 204 - { 0, 2,18,18,18, 2,-2, 3, 6, 4, 8,18, 2, 5, 7, 4, 3, 6 }, // 205 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 }, // 206 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 }, // 207 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 }, // 208 - { 1, 1,18, 1, 8, 3, 5, 6, 4,-1, 8, 3, 7,18, 2, 5, 8, 4 }, // 209 - { 1, 1,17,18, 5, 2, 4, 3, 1, 6,-2, 1, 3, 2, 4, 5,-1,17 }, // 210 - { 1, 1,18,17, 2,18, 3,-3, 7, 2, 6, 4, 3, 5,18, 8, 2,-2 }, // 211 - { 1, 1,18,17,18, 4, 3, 5,-1,18, 2, 7, 8, 4, 6, 3,18, 5 }, // 212 - { 0, 1,18,17,18,-2, 2,-3, 3, 4, 8, 5, 2,18, 6, 3, 7,-2 }, // 213 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 }, // 214 - { 1, 1,17,18, 8, 3, 4, 6,18, 5,-2, 3, 8, 5, 2, 4, 7, 6 }, // 215 - { 0, 1,18,-2, 3, 5, 1, 7, 3, 2, 6,-3, 4, 1, 5, 8, 3,-2 }, // 216 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 }, // 217 - { 1, 1, 3,17,18, 5,-1,18, 2, 6, 7,18, 5, 3,-3,-1, 6, 2 }, // 218 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 }, // 219 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 }, // 220 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 }, // 221 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 }, // 222 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 }, // 223 - { 1, 3,18,17,-2, 3,-1,18, 2, 5, 3, 7, 6, 2, 4, 8,18, 5 }, // 224 - { 0, 1,18,-1,18, 2,18, 3, 5,18, 2, 8,18, 5, 4,-1, 6, 2 }, // 225 - { 1, 2,18,-2,18,18, 2, 3, 4,-3, 2, 5,18, 7, 4, 3, 8, 6 }, // 226 - { 0, 2,17,-1,18, 2,-1, 1, 7, 3, 8, 5,-2, 4, 1, 2,-3, 6 }, // 227 - { 0, 1,18,17, 2,18, 2,18, 6, 7, 4, 3,18, 5, 2,-2,17, 8 }, // 228 - { 0, 3,18,17, 2, 3,-3,-1,18, 2, 4, 5,18, 7, 3, 2,-3, 6 }, // 229 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 }, // 230 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 }, // 231 - { 0, 2, 3,18,18,18, 2, 6, 5,18, 7, 2, 4, 6,18, 5, 3, 8 }, // 232 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 }, // 233 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 }, // 234 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 }, // 235 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 }, // 236 - { 0, 1,18,18, 3, 6, 3,-2, 2,18, 5,-1, 7, 3, 4,-2, 2, 6 }, // 237 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 }, // 238 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 }, // 239 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 }, // 240 - { 1, 1,18,17,18,18,-2, 2, 3,-3,18, 6, 4, 2,-2, 8, 3, 7 }, // 241 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 }, // 242 - { 0, 1,18,18,18, 4, 2, 7, 8,18, 3, 2,-2, 4, 7, 6,17, 5 }, // 243 - { 1, 1,18,18,-1,-2, 8, 3,18, 6, 3, 5, 8, 2, 4, 7, 1, 6 }, // 244 - { 1, 1, 1,-3, 3,18,18, 2,-1, 3, 6, 5,18, 4, 7,-2, 8, 3 }, // 245 - { 1, 1, 1,18, 4, 2, 5,18, 1, 3,-1, 6, 1, 4, 8, 2, 5, 1 }, // 246 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 }, // 247 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 }, // 248 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 }, // 249 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 }, // 250 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 }, // 251 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 }, // 252 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 }, // 253 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 }, // 254 - { 0, 1,-1,18,18, 2,18, 3, 5,18, 2,18, 6, 8, 4, 5, 7,-1 }, // 255 -}; - -#define NUM_FAST_SPECS (sizeof (fast_specs) / sizeof (fast_specs [0])) -#define NUM_DEFAULT_SPECS (sizeof (default_specs) / sizeof (default_specs [0])) -#define NUM_HIGH_SPECS (sizeof (high_specs) / sizeof (high_specs [0])) -#define NUM_VERY_HIGH_SPECS (sizeof (very_high_specs) / sizeof (very_high_specs [0])) - -///////////////////////////// executable code //////////////////////////////// - -// This function initializes everything required to pack WavPack bitstreams -// and must be called BEFORE any other function in this module. - -void pack_init (WavpackContext *wpc) -{ - WavpackStream *wps = wpc->streams [wpc->current_stream]; - - wps->sample_index = 0; - wps->delta_decay = 2.0; - CLEAR (wps->decorr_passes); - CLEAR (wps->dc); - - /* although we set the term and delta values here for clarity, they're - * actually hardcoded in the analysis function for speed - */ - - CLEAR (wps->analysis_pass); - wps->analysis_pass.term = 18; - wps->analysis_pass.delta = 2; - - if (wpc->config.flags & CONFIG_AUTO_SHAPING) { - if (wpc->config.flags & CONFIG_OPTIMIZE_WVC) - wps->dc.shaping_acc [0] = wps->dc.shaping_acc [1] = -512L << 16; - else if (wpc->config.sample_rate >= 64000) - wps->dc.shaping_acc [0] = wps->dc.shaping_acc [1] = 1024L << 16; - else - wpc->config.flags |= CONFIG_DYNAMIC_SHAPING; - } - else { - int32_t weight = (int32_t) floor (wpc->config.shaping_weight * 1024.0 + 0.5); - - if (weight <= -1000) - weight = -1000; - - wps->dc.shaping_acc [0] = wps->dc.shaping_acc [1] = weight << 16; - } - - if (wpc->config.flags & CONFIG_DYNAMIC_SHAPING) - wps->dc.shaping_data = malloc (wpc->max_samples * sizeof (*wps->dc.shaping_data)); - - if (!wpc->config.xmode) - wps->num_passes = 0; - else if (wpc->config.xmode == 1) - wps->num_passes = 2; - else if (wpc->config.xmode == 2) - wps->num_passes = 4; - else - wps->num_passes = 9; - - if (wpc->config.flags & CONFIG_VERY_HIGH_FLAG) { - wps->num_decorrs = NUM_VERY_HIGH_SPECS; - wps->decorr_specs = very_high_specs; - } - else if (wpc->config.flags & CONFIG_HIGH_FLAG) { - wps->num_decorrs = NUM_HIGH_SPECS; - wps->decorr_specs = high_specs; - } - else if (wpc->config.flags & CONFIG_FAST_FLAG) { - wps->num_decorrs = NUM_FAST_SPECS; - wps->decorr_specs = fast_specs; - } - else { - wps->num_decorrs = NUM_DEFAULT_SPECS; - wps->decorr_specs = default_specs; - } - - init_words (wps); -} - -// Allocate room for and copy the decorrelation terms from the decorr_passes -// array into the specified metadata structure. Both the actual term id and -// the delta are packed into single characters. - -void write_decorr_terms (WavpackStream *wps, WavpackMetadata *wpmd) -{ - int tcount = wps->num_terms; - struct decorr_pass *dpp; - char *byteptr; - - byteptr = wpmd->data = malloc (tcount + 1); - wpmd->id = ID_DECORR_TERMS; - - for (dpp = wps->decorr_passes; tcount--; ++dpp) - *byteptr++ = ((dpp->term + 5) & 0x1f) | ((dpp->delta << 5) & 0xe0); - - wpmd->byte_length = (int32_t)(byteptr - (char *) wpmd->data); -} - -// Allocate room for and copy the decorrelation term weights from the -// decorr_passes array into the specified metadata structure. The weights -// range +/-1024, but are rounded and truncated to fit in signed chars for -// metadata storage. Weights are separate for the two channels - -void write_decorr_weights (WavpackStream *wps, WavpackMetadata *wpmd) -{ - struct decorr_pass *dpp = wps->decorr_passes; - int tcount = wps->num_terms, i; - char *byteptr; - - byteptr = wpmd->data = malloc ((tcount * 2) + 1); - wpmd->id = ID_DECORR_WEIGHTS; - - for (i = wps->num_terms - 1; i >= 0; --i) - if (store_weight (dpp [i].weight_A) || - (!(wps->wphdr.flags & MONO_DATA) && store_weight (dpp [i].weight_B))) - break; - - tcount = i + 1; - - for (i = 0; i < wps->num_terms; ++i) { - if (i < tcount) { - dpp [i].weight_A = restore_weight (*byteptr++ = store_weight (dpp [i].weight_A)); - - if (!(wps->wphdr.flags & MONO_DATA)) - dpp [i].weight_B = restore_weight (*byteptr++ = store_weight (dpp [i].weight_B)); - } - else - dpp [i].weight_A = dpp [i].weight_B = 0; - } - - wpmd->byte_length = (int32_t)(byteptr - (char *) wpmd->data); -} - -// Allocate room for and copy the decorrelation samples from the decorr_passes -// array into the specified metadata structure. The samples are signed 32-bit -// values, but are converted to signed log2 values for storage in metadata. -// Values are stored for both channels and are specified from the first term -// with unspecified samples set to zero. The number of samples stored varies -// with the actual term value, so those must obviously be specified before -// these in the metadata list. Any number of terms can have their samples -// specified from no terms to all the terms, however I have found that -// sending more than the first term's samples is a waste. The "wcount" -// variable can be set to the number of terms to have their samples stored. - -void write_decorr_samples (WavpackStream *wps, WavpackMetadata *wpmd) -{ - int tcount = wps->num_terms, wcount = 1, temp; - struct decorr_pass *dpp; - uchar *byteptr; - - byteptr = wpmd->data = malloc (256); - wpmd->id = ID_DECORR_SAMPLES; - - for (dpp = wps->decorr_passes; tcount--; ++dpp) - if (wcount) { - if (dpp->term > MAX_TERM) { - dpp->samples_A [0] = exp2s (temp = log2s (dpp->samples_A [0])); - *byteptr++ = temp; - *byteptr++ = temp >> 8; - dpp->samples_A [1] = exp2s (temp = log2s (dpp->samples_A [1])); - *byteptr++ = temp; - *byteptr++ = temp >> 8; - - if (!(wps->wphdr.flags & MONO_DATA)) { - dpp->samples_B [0] = exp2s (temp = log2s (dpp->samples_B [0])); - *byteptr++ = temp; - *byteptr++ = temp >> 8; - dpp->samples_B [1] = exp2s (temp = log2s (dpp->samples_B [1])); - *byteptr++ = temp; - *byteptr++ = temp >> 8; - } - } - else if (dpp->term < 0) { - dpp->samples_A [0] = exp2s (temp = log2s (dpp->samples_A [0])); - *byteptr++ = temp; - *byteptr++ = temp >> 8; - dpp->samples_B [0] = exp2s (temp = log2s (dpp->samples_B [0])); - *byteptr++ = temp; - *byteptr++ = temp >> 8; - } - else { - int m = 0, cnt = dpp->term; - - while (cnt--) { - dpp->samples_A [m] = exp2s (temp = log2s (dpp->samples_A [m])); - *byteptr++ = temp; - *byteptr++ = temp >> 8; - - if (!(wps->wphdr.flags & MONO_DATA)) { - dpp->samples_B [m] = exp2s (temp = log2s (dpp->samples_B [m])); - *byteptr++ = temp; - *byteptr++ = temp >> 8; - } - - m++; - } - } - - wcount--; - } - else { - CLEAR (dpp->samples_A); - CLEAR (dpp->samples_B); - } - - wpmd->byte_length = (int32_t)(byteptr - (uchar *) wpmd->data); -} - -// Allocate room for and copy the noise shaping info into the specified -// metadata structure. These would normally be written to the -// "correction" file and are used for lossless reconstruction of -// hybrid data. The "delta" parameter is not yet used in encoding as it -// will be part of the "quality" mode. - -void write_shaping_info (WavpackStream *wps, WavpackMetadata *wpmd) -{ - char *byteptr; - int temp; - - byteptr = wpmd->data = malloc (12); - wpmd->id = ID_SHAPING_WEIGHTS; - - wps->dc.error [0] = exp2s (temp = log2s (wps->dc.error [0])); - *byteptr++ = temp; - *byteptr++ = temp >> 8; - wps->dc.shaping_acc [0] = exp2s (temp = log2s (wps->dc.shaping_acc [0])); - *byteptr++ = temp; - *byteptr++ = temp >> 8; - - if (!(wps->wphdr.flags & MONO_DATA)) { - wps->dc.error [1] = exp2s (temp = log2s (wps->dc.error [1])); - *byteptr++ = temp; - *byteptr++ = temp >> 8; - wps->dc.shaping_acc [1] = exp2s (temp = log2s (wps->dc.shaping_acc [1])); - *byteptr++ = temp; - *byteptr++ = temp >> 8; - } - - if (wps->dc.shaping_delta [0] | wps->dc.shaping_delta [1]) { - wps->dc.shaping_delta [0] = exp2s (temp = log2s (wps->dc.shaping_delta [0])); - *byteptr++ = temp; - *byteptr++ = temp >> 8; - - if (!(wps->wphdr.flags & MONO_DATA)) { - wps->dc.shaping_delta [1] = exp2s (temp = log2s (wps->dc.shaping_delta [1])); - *byteptr++ = temp; - *byteptr++ = temp >> 8; - } - } - - wpmd->byte_length = (int32_t)(byteptr - (char *) wpmd->data); -} - -// Allocate room for and copy the int32 data values into the specified -// metadata structure. This data is used for integer data that has more -// than 24 bits of magnitude or, in some cases, it's used to eliminate -// redundant bits from any audio stream. - -void write_int32_info (WavpackStream *wps, WavpackMetadata *wpmd) -{ - char *byteptr; - - byteptr = wpmd->data = malloc (4); - wpmd->id = ID_INT32_INFO; - *byteptr++ = wps->int32_sent_bits; - *byteptr++ = wps->int32_zeros; - *byteptr++ = wps->int32_ones; - *byteptr++ = wps->int32_dups; - wpmd->byte_length = (int32_t)(byteptr - (char *) wpmd->data); -} - -// Allocate room for and copy the multichannel information into the specified -// metadata structure. The first byte is the total number of channels and the -// following bytes represent the channel_mask as described for Microsoft -// WAVEFORMATEX. - -void write_channel_info (WavpackContext *wpc, WavpackMetadata *wpmd) -{ - uint32_t mask = wpc->config.channel_mask; - char *byteptr; - - byteptr = wpmd->data = malloc (4); - wpmd->id = ID_CHANNEL_INFO; - *byteptr++ = wpc->config.num_channels; - - while (mask) { - *byteptr++ = mask; - mask >>= 8; - } - - wpmd->byte_length = (int32_t)(byteptr - (char *) wpmd->data); -} - -// Allocate room for and copy the configuration information into the specified -// metadata structure. Currently, we just store the upper 3 bytes of -// config.flags and only in the first block of audio data. Note that this is -// for informational purposes not required for playback or decoding (like -// whether high or fast mode was specified). - -void write_config_info (WavpackContext *wpc, WavpackMetadata *wpmd) -{ - char *byteptr; - - byteptr = wpmd->data = malloc (4); - wpmd->id = ID_CONFIG_BLOCK; - *byteptr++ = (char) (wpc->config.flags >> 8); - *byteptr++ = (char) (wpc->config.flags >> 16); - *byteptr++ = (char) (wpc->config.flags >> 24); - - if (wpc->config.flags & CONFIG_EXTRA_MODE) - *byteptr++ = (char) wpc->config.xmode; - - wpmd->byte_length = (int32_t)(byteptr - (char *) wpmd->data); -} - -// Allocate room for and copy the non-standard sampling rateinto the specified -// metadata structure. We just store the lower 3 bytes of the sampling rate. -// Note that this would only be used when the sampling rate was not included -// in the table of 15 "standard" values. - -void write_sample_rate (WavpackContext *wpc, WavpackMetadata *wpmd) - -{ - char *byteptr; - - byteptr = wpmd->data = malloc (4); - wpmd->id = ID_SAMPLE_RATE; - *byteptr++ = (char) (wpc->config.sample_rate); - *byteptr++ = (char) (wpc->config.sample_rate >> 8); - *byteptr++ = (char) (wpc->config.sample_rate >> 16); - wpmd->byte_length = (int32_t)(byteptr - (char *) wpmd->data); -} - -// Pack an entire block of samples (either mono or stereo) into a completed -// WavPack block. This function is actually a shell for pack_samples() and -// performs tasks like handling any shift required by the format, preprocessing -// of floating point data or integer data over 24 bits wide, and implementing -// the "extra" mode (via the extra?.c modules). It is assumed that there is -// sufficient space for the completed block at "wps->blockbuff" and that -// "wps->blockend" points to the end of the available space. A return value of -// FALSE indicates an error. - -static void best_floating_line (short *values, int num_values, double *initial_y, double *final_y, short *max_error); -static void dynamic_noise_shaping (WavpackContext *wpc, int32_t *buffer, int shortening_allowed); -static int scan_int32_data (WavpackStream *wps, int32_t *values, int32_t num_values); -static void scan_int32_quick (WavpackStream *wps, int32_t *values, int32_t num_values); -static void send_int32_data (WavpackStream *wps, int32_t *values, int32_t num_values); -static int scan_redundancy (int32_t *values, int32_t num_values); -static int pack_samples (WavpackContext *wpc, int32_t *buffer); - -int pack_block (WavpackContext *wpc, int32_t *buffer) -{ - WavpackStream *wps = wpc->streams [wpc->current_stream]; - uint32_t flags = wps->wphdr.flags, sflags = wps->wphdr.flags; - int32_t sample_count = wps->wphdr.block_samples, *orig_data = NULL; - int dynamic_shaping_done = FALSE; - - if (!wpc->current_stream && !(flags & FLOAT_DATA) && (flags & MAG_MASK) >> MAG_LSB < 24) { - if ((wpc->config.flags & CONFIG_DYNAMIC_SHAPING) && !wpc->config.block_samples) { - dynamic_noise_shaping (wpc, buffer, TRUE); - sample_count = wps->wphdr.block_samples; - dynamic_shaping_done = TRUE; - } - else if (wpc->block_boundary && sample_count >= (int32_t) wpc->block_boundary * 2) { - int bc = sample_count / wpc->block_boundary, chans = (flags & MONO_DATA) ? 1 : 2; - int res = scan_redundancy (buffer, wpc->block_boundary * chans), i; - - for (i = 1; i < bc; ++i) - if (res != scan_redundancy (buffer + (i * wpc->block_boundary * chans), - wpc->block_boundary * chans)) { - sample_count = wps->wphdr.block_samples = wpc->block_boundary * i; - break; - } - } - } - - if (!(flags & MONO_FLAG) && wpc->stream_version >= 0x410) { - int32_t lor = 0, diff = 0; - int32_t *sptr, *dptr, i; - - for (sptr = buffer, i = 0; i < (int32_t) sample_count; sptr += 2, i++) { - lor |= sptr [0] | sptr [1]; - diff |= sptr [0] - sptr [1]; - - if (lor && diff) - break; - } - - if (i == sample_count && lor && !diff) { - flags &= ~(JOINT_STEREO | CROSS_DECORR | HYBRID_BALANCE); - wps->wphdr.flags = flags |= FALSE_STEREO; - dptr = buffer; - sptr = buffer; - - for (i = sample_count; i--; sptr++) - *dptr++ = *sptr++; - - if (!wps->false_stereo) { - wps->false_stereo = 1; - wps->num_terms = 0; - init_words (wps); - } - } - else if (wps->false_stereo) { - wps->false_stereo = 0; - wps->num_terms = 0; - init_words (wps); - } - } - - if (flags & SHIFT_MASK) { - int shift = (flags & SHIFT_MASK) >> SHIFT_LSB; - int mag = (flags & MAG_MASK) >> MAG_LSB; - uint32_t cnt = sample_count; - int32_t *ptr = buffer; - - if (flags & MONO_DATA) - while (cnt--) - *ptr++ >>= shift; - else - while (cnt--) { - *ptr++ >>= shift; - *ptr++ >>= shift; - } - - if ((mag -= shift) < 0) - flags &= ~MAG_MASK; - else - flags -= (1 << MAG_LSB) * shift; - - wps->wphdr.flags = flags; - } - - if ((flags & FLOAT_DATA) || (flags & MAG_MASK) >> MAG_LSB >= 24) { - if ((!(flags & HYBRID_FLAG) || wpc->wvc_flag) && !(wpc->config.flags & CONFIG_SKIP_WVX)) { - orig_data = malloc (sizeof (f32) * ((flags & MONO_DATA) ? sample_count : sample_count * 2)); - memcpy (orig_data, buffer, sizeof (f32) * ((flags & MONO_DATA) ? sample_count : sample_count * 2)); - - if (flags & FLOAT_DATA) { - wps->float_norm_exp = wpc->config.float_norm_exp; - - if (!scan_float_data (wps, (f32 *) buffer, (flags & MONO_DATA) ? sample_count : sample_count * 2)) { - free (orig_data); - orig_data = NULL; - } - } - else { - if (!scan_int32_data (wps, buffer, (flags & MONO_DATA) ? sample_count : sample_count * 2)) { - free (orig_data); - orig_data = NULL; - } - } - } - else { - if (flags & FLOAT_DATA) { - wps->float_norm_exp = wpc->config.float_norm_exp; - - if (scan_float_data (wps, (f32 *) buffer, (flags & MONO_DATA) ? sample_count : sample_count * 2)) - wpc->lossy_blocks = TRUE; - } - else if (scan_int32_data (wps, buffer, (flags & MONO_DATA) ? sample_count : sample_count * 2)) - wpc->lossy_blocks = TRUE; - } - - wps->num_terms = 0; - } - else { - scan_int32_quick (wps, buffer, (flags & MONO_DATA) ? sample_count : sample_count * 2); - - if (wps->shift != wps->int32_zeros + wps->int32_ones + wps->int32_dups) { - wps->shift = wps->int32_zeros + wps->int32_ones + wps->int32_dups; - wps->num_terms = 0; - } - } - - if ((wpc->config.flags & CONFIG_DYNAMIC_SHAPING) && !dynamic_shaping_done) - dynamic_noise_shaping (wpc, buffer, FALSE); - - if (!wps->num_passes && !wps->num_terms) { - wps->num_passes = 1; - - if (flags & MONO_DATA) - execute_mono (wpc, buffer, 1, 0); - else - execute_stereo (wpc, buffer, 1, 0); - - wps->num_passes = 0; - } - - if (!pack_samples (wpc, buffer)) { - wps->wphdr.flags = sflags; - - if (orig_data) - free (orig_data); - - return FALSE; - } - else - wps->wphdr.flags = sflags; - - if (wps->dc.shaping_data) { - if (wps->dc.shaping_samples != sample_count) - memcpy (wps->dc.shaping_data, wps->dc.shaping_data + sample_count, - (wps->dc.shaping_samples - sample_count) * sizeof (*wps->dc.shaping_data)); - - wps->dc.shaping_samples -= sample_count; - } - - if (orig_data) { - uint32_t data_count; - uchar *cptr; - - if (wpc->wvc_flag) - cptr = wps->block2buff + ((WavpackHeader *) wps->block2buff)->ckSize + 8; - else - cptr = wps->blockbuff + ((WavpackHeader *) wps->blockbuff)->ckSize + 8; - - bs_open_write (&wps->wvxbits, cptr + 8, wpc->wvc_flag ? wps->block2end : wps->blockend); - - if (flags & FLOAT_DATA) - send_float_data (wps, (f32*) orig_data, (flags & MONO_DATA) ? sample_count : sample_count * 2); - else - send_int32_data (wps, orig_data, (flags & MONO_DATA) ? sample_count : sample_count * 2); - - data_count = bs_close_write (&wps->wvxbits); - free (orig_data); - - if (data_count) { - if (data_count != (uint32_t) -1) { - *cptr++ = ID_WVX_BITSTREAM | ID_LARGE; - *cptr++ = (data_count += 4) >> 1; - *cptr++ = data_count >> 9; - *cptr++ = data_count >> 17; - *cptr++ = wps->crc_x; - *cptr++ = wps->crc_x >> 8; - *cptr++ = wps->crc_x >> 16; - *cptr = wps->crc_x >> 24; - - if (wpc->wvc_flag) - ((WavpackHeader *) wps->block2buff)->ckSize += data_count + 4; - else - ((WavpackHeader *) wps->blockbuff)->ckSize += data_count + 4; - } - else - return FALSE; - } - } - - return TRUE; -} - -static void dynamic_noise_shaping (WavpackContext *wpc, int32_t *buffer, int shortening_allowed) -{ - WavpackStream *wps = wpc->streams [wpc->current_stream]; - int32_t sample_count = wps->wphdr.block_samples; - struct decorr_pass *ap = &wps->analysis_pass; - uint32_t flags = wps->wphdr.flags; - int32_t *bptr, temp, sam; - short *swptr; - int sc; - - if (!wps->num_terms && sample_count > 8) { - if (flags & MONO_DATA) - for (bptr = buffer + sample_count - 3, sc = sample_count - 2; sc--;) { - sam = (3 * bptr [1] - bptr [2]) >> 1; - temp = *bptr-- - apply_weight (ap->weight_A, sam); - update_weight (ap->weight_A, 2, sam, temp); - } - else - for (bptr = buffer + (sample_count - 3) * 2 + 1, sc = sample_count - 2; sc--;) { - sam = (3 * bptr [2] - bptr [4]) >> 1; - temp = *bptr-- - apply_weight (ap->weight_B, sam); - update_weight (ap->weight_B, 2, sam, temp); - sam = (3 * bptr [2] - bptr [4]) >> 1; - temp = *bptr-- - apply_weight (ap->weight_A, sam); - update_weight (ap->weight_A, 2, sam, temp); - } - } - - if (sample_count > wps->dc.shaping_samples) { - sc = sample_count - wps->dc.shaping_samples; - swptr = wps->dc.shaping_data + wps->dc.shaping_samples; - bptr = buffer + wps->dc.shaping_samples * ((flags & MONO_DATA) ? 1 : 2); - - if (flags & MONO_DATA) - while (sc--) { - sam = (3 * ap->samples_A [0] - ap->samples_A [1]) >> 1; - temp = *bptr - apply_weight (ap->weight_A, sam); - update_weight (ap->weight_A, 2, sam, temp); - ap->samples_A [1] = ap->samples_A [0]; - ap->samples_A [0] = *bptr++; - *swptr++ = (ap->weight_A < 256) ? 1024 : 1536 - ap->weight_A * 2; - } - else - while (sc--) { - sam = (3 * ap->samples_A [0] - ap->samples_A [1]) >> 1; - temp = *bptr - apply_weight (ap->weight_A, sam); - update_weight (ap->weight_A, 2, sam, temp); - ap->samples_A [1] = ap->samples_A [0]; - ap->samples_A [0] = *bptr++; - - sam = (3 * ap->samples_B [0] - ap->samples_B [1]) >> 1; - temp = *bptr - apply_weight (ap->weight_B, sam); - update_weight (ap->weight_B, 2, sam, temp); - ap->samples_B [1] = ap->samples_B [0]; - ap->samples_B [0] = *bptr++; - - *swptr++ = (ap->weight_A + ap->weight_B < 512) ? 1024 : 1536 - ap->weight_A - ap->weight_B; - } - - wps->dc.shaping_samples = sample_count; - } - - if (wpc->wvc_flag) { - int max_allowed_error = 1000000 / wpc->ave_block_samples; - short max_error, trial_max_error; - double initial_y, final_y; - - if (max_allowed_error < 128) - max_allowed_error = 128; - - best_floating_line (wps->dc.shaping_data, sample_count, &initial_y, &final_y, &max_error); - - if (shortening_allowed && max_error > max_allowed_error) { - int min_samples = 0, max_samples = sample_count, trial_count; - double trial_initial_y, trial_final_y; - - while (1) { - trial_count = (min_samples + max_samples) / 2; - - best_floating_line (wps->dc.shaping_data, trial_count, &trial_initial_y, - &trial_final_y, &trial_max_error); - - if (trial_max_error < max_allowed_error) { - max_error = trial_max_error; - min_samples = trial_count; - initial_y = trial_initial_y; - final_y = trial_final_y; - } - else - max_samples = trial_count; - - if (min_samples > 10000 || max_samples - min_samples < 2) - break; - } - - sample_count = min_samples; - } - - if (initial_y < -512) initial_y = -512; - else if (initial_y > 1024) initial_y = 1024; - - if (final_y < -512) final_y = -512; - else if (final_y > 1024) final_y = 1024; -#if 0 - error_line ("%.2f sec, sample count = %5d, max error = %3d, range = %5d, %5d, actual = %5d, %5d", - (double) wps->sample_index / wpc->config.sample_rate, sample_count, max_error, - (int) floor (initial_y), (int) floor (final_y), - wps->dc.shaping_data [0], wps->dc.shaping_data [sample_count-1]); -#endif - if (sample_count != wps->wphdr.block_samples) - wps->wphdr.block_samples = sample_count; - - if (wpc->wvc_flag) { - wps->dc.shaping_acc [0] = wps->dc.shaping_acc [1] = (int32_t) floor (initial_y * 65536.0 + 0.5); - - wps->dc.shaping_delta [0] = wps->dc.shaping_delta [1] = - (int32_t) floor ((final_y - initial_y) / (sample_count - 1) * 65536.0 + 0.5); - - wps->dc.shaping_array = NULL; - } - else - wps->dc.shaping_array = wps->dc.shaping_data; - } - else - wps->dc.shaping_array = wps->dc.shaping_data; -} - -// Quickly scan a buffer of long integer data and determine whether any -// redundancy in the LSBs can be used to reduce the data's magnitude. If yes, -// then the INT32_DATA flag is set and the int32 parameters are set. This -// version is designed to terminate as soon as it figures out that no -// redundancy is available so that it can be used for all files. - -static void scan_int32_quick (WavpackStream *wps, int32_t *values, int32_t num_values) -{ - uint32_t magdata = 0, ordata = 0, xordata = 0, anddata = ~0; - int total_shift = 0; - int32_t *dp, count; - - wps->int32_sent_bits = wps->int32_zeros = wps->int32_ones = wps->int32_dups = 0; - - for (dp = values, count = num_values; count--; dp++) { - magdata |= (*dp < 0) ? ~*dp : *dp; - xordata |= *dp ^ -(*dp & 1); - anddata &= *dp; - ordata |= *dp; - - if ((ordata & 1) && !(anddata & 1) && (xordata & 2)) - return; - } - - wps->wphdr.flags &= ~MAG_MASK; - - while (magdata) { - wps->wphdr.flags += 1 << MAG_LSB; - magdata >>= 1; - } - - if (!(wps->wphdr.flags & MAG_MASK)) - return; - - if (!(ordata & 1)) - while (!(ordata & 1)) { - wps->wphdr.flags -= 1 << MAG_LSB; - wps->int32_zeros++; - total_shift++; - ordata >>= 1; - } - else if (anddata & 1) - while (anddata & 1) { - wps->wphdr.flags -= 1 << MAG_LSB; - wps->int32_ones++; - total_shift++; - anddata >>= 1; - } - else if (!(xordata & 2)) - while (!(xordata & 2)) { - wps->wphdr.flags -= 1 << MAG_LSB; - wps->int32_dups++; - total_shift++; - xordata >>= 1; - } - - if (total_shift) { - wps->wphdr.flags |= INT32_DATA; - - for (dp = values, count = num_values; count--; dp++) - *dp >>= total_shift; - } -} - -static int scan_redundancy (int32_t *values, int32_t num_values) -{ - uint32_t ordata = 0, xordata = 0, anddata = ~0; - int redundant_bits = 0; - int32_t *dp, count; - - for (dp = values, count = num_values; count--; dp++) { - xordata |= *dp ^ -(*dp & 1); - anddata &= *dp; - ordata |= *dp; - - if ((ordata & 1) && !(anddata & 1) && (xordata & 2)) - return 0; - } - - if (!ordata || anddata == ~0 || !xordata) - return 0; - - if (!(ordata & 1)) - while (!(ordata & 1)) { - redundant_bits++; - ordata >>= 1; - } - else if (anddata & 1) - while (anddata & 1) { - redundant_bits = (redundant_bits + 1) | 0x40; - anddata >>= 1; - } - else if (!(xordata & 2)) - while (!(xordata & 2)) { - redundant_bits = (redundant_bits + 1) | 0x80; - redundant_bits++; - xordata >>= 1; - } - - return redundant_bits; -} - -// Scan a buffer of long integer data and determine whether any redundancy in -// the LSBs can be used to reduce the data's magnitude. If yes, then the -// INT32_DATA flag is set and the int32 parameters are set. If bits must still -// be transmitted literally to get down to 24 bits (which is all the integer -// compression code can handle) then we return TRUE to indicate that a wvx -// stream must be created in either lossless mode. - -static int scan_int32_data (WavpackStream *wps, int32_t *values, int32_t num_values) -{ - uint32_t magdata = 0, ordata = 0, xordata = 0, anddata = ~0; - uint32_t crc = 0xffffffff; - int total_shift = 0; - int32_t *dp, count; - - wps->int32_sent_bits = wps->int32_zeros = wps->int32_ones = wps->int32_dups = 0; - - for (dp = values, count = num_values; count--; dp++) { - crc = crc * 9 + (*dp & 0xffff) * 3 + ((*dp >> 16) & 0xffff); - magdata |= (*dp < 0) ? ~*dp : *dp; - xordata |= *dp ^ -(*dp & 1); - anddata &= *dp; - ordata |= *dp; - } - - wps->crc_x = crc; - wps->wphdr.flags &= ~MAG_MASK; - - while (magdata) { - wps->wphdr.flags += 1 << MAG_LSB; - magdata >>= 1; - } - - if (!((wps->wphdr.flags & MAG_MASK) >> MAG_LSB)) { - wps->wphdr.flags &= ~INT32_DATA; - return FALSE; - } - - if (!(ordata & 1)) - while (!(ordata & 1)) { - wps->wphdr.flags -= 1 << MAG_LSB; - wps->int32_zeros++; - total_shift++; - ordata >>= 1; - } - else if (anddata & 1) - while (anddata & 1) { - wps->wphdr.flags -= 1 << MAG_LSB; - wps->int32_ones++; - total_shift++; - anddata >>= 1; - } - else if (!(xordata & 2)) - while (!(xordata & 2)) { - wps->wphdr.flags -= 1 << MAG_LSB; - wps->int32_dups++; - total_shift++; - xordata >>= 1; - } - - if (((wps->wphdr.flags & MAG_MASK) >> MAG_LSB) > 23) { - wps->int32_sent_bits = (uchar)(((wps->wphdr.flags & MAG_MASK) >> MAG_LSB) - 23); - total_shift += wps->int32_sent_bits; - wps->wphdr.flags &= ~MAG_MASK; - wps->wphdr.flags += 23 << MAG_LSB; - } - - if (total_shift) { - wps->wphdr.flags |= INT32_DATA; - - for (dp = values, count = num_values; count--; dp++) - *dp >>= total_shift; - } - - return wps->int32_sent_bits; -} - -// For the specified buffer values and the int32 parameters stored in "wps", -// send the literal bits required to the "wvxbits" bitstream. - -static void send_int32_data (WavpackStream *wps, int32_t *values, int32_t num_values) -{ - int sent_bits = wps->int32_sent_bits, pre_shift; - int32_t mask = (1 << sent_bits) - 1; - int32_t count, value, *dp; - - pre_shift = wps->int32_zeros + wps->int32_ones + wps->int32_dups; - - if (sent_bits) - for (dp = values, count = num_values; count--; dp++) { - value = (*dp >> pre_shift) & mask; - putbits (value, sent_bits, &wps->wvxbits); - } -} - -// Pack an entire block of samples (either mono or stereo) into a completed -// WavPack block. It is assumed that there is sufficient space for the -// completed block at "wps->blockbuff" and that "wps->blockend" points to the -// end of the available space. A return value of FALSE indicates an error. -// Any unsent metadata is transmitted first, then required metadata for this -// block is sent, and finally the compressed integer data is sent. If a "wpx" -// stream is required for floating point data or large integer data, then this -// must be handled outside this function. To find out how much data was written -// the caller must look at the ckSize field of the written WavpackHeader, NOT -// the one in the WavpackStream. - -static void decorr_stereo_pass (struct decorr_pass *dpp, int32_t *buffer, int32_t sample_count); -static void decorr_stereo_pass_id2 (struct decorr_pass *dpp, int32_t *buffer, int32_t sample_count); - -static int pack_samples (WavpackContext *wpc, int32_t *buffer) -{ - WavpackStream *wps = wpc->streams [wpc->current_stream]; - uint32_t flags = wps->wphdr.flags, data_count, crc, crc2, i; - uint32_t sample_count = wps->wphdr.block_samples; - short *shaping_array = wps->dc.shaping_array; - int tcount, lossy = FALSE, m = 0; - double noise_acc = 0.0, noise; - struct decorr_pass *dpp; - WavpackMetadata wpmd; - int32_t *bptr; - - crc = crc2 = 0xffffffff; - - if (!(flags & HYBRID_FLAG) && (flags & MONO_DATA)) { - int32_t *eptr = buffer + sample_count; - - for (bptr = buffer; bptr < eptr;) - crc += (crc << 1) + *bptr++; - - if (wps->num_passes) - execute_mono (wpc, buffer, !wps->num_terms, 1); - } - else if (!(flags & HYBRID_FLAG) && !(flags & MONO_DATA)) { - int32_t *eptr = buffer + (sample_count * 2); - - for (bptr = buffer; bptr < eptr; bptr += 2) - crc += (crc << 3) + (bptr [0] << 1) + bptr [0] + bptr [1]; - - if (wps->num_passes) { - execute_stereo (wpc, buffer, !wps->num_terms, 1); - flags = wps->wphdr.flags; - } - } - else if ((flags & HYBRID_FLAG) && (flags & MONO_DATA)) { - if (wps->num_passes) - execute_mono (wpc, buffer, !wps->num_terms, 0); - } - else if ((flags & HYBRID_FLAG) && !(flags & MONO_DATA)) { - if (wps->num_passes) { - execute_stereo (wpc, buffer, !wps->num_terms, 0); - flags = wps->wphdr.flags; - } - } - - wps->wphdr.ckSize = sizeof (WavpackHeader) - 8; - memcpy (wps->blockbuff, &wps->wphdr, sizeof (WavpackHeader)); - - if (wpc->metacount) { - WavpackMetadata *wpmdp = wpc->metadata; - - while (wpc->metacount) { - copy_metadata (wpmdp, wps->blockbuff, wps->blockend); - wpc->metabytes -= wpmdp->byte_length; - free_metadata (wpmdp++); - wpc->metacount--; - } - - free (wpc->metadata); - wpc->metadata = NULL; - } - - if (!sample_count) - return TRUE; - - write_decorr_terms (wps, &wpmd); - copy_metadata (&wpmd, wps->blockbuff, wps->blockend); - free_metadata (&wpmd); - - write_decorr_weights (wps, &wpmd); - copy_metadata (&wpmd, wps->blockbuff, wps->blockend); - free_metadata (&wpmd); - - write_decorr_samples (wps, &wpmd); - copy_metadata (&wpmd, wps->blockbuff, wps->blockend); - free_metadata (&wpmd); - - write_entropy_vars (wps, &wpmd); - copy_metadata (&wpmd, wps->blockbuff, wps->blockend); - free_metadata (&wpmd); - - if ((flags & SRATE_MASK) == SRATE_MASK && wpc->config.sample_rate != 44100) { - write_sample_rate (wpc, &wpmd); - copy_metadata (&wpmd, wps->blockbuff, wps->blockend); - free_metadata (&wpmd); - } - - if (flags & HYBRID_FLAG) { - write_hybrid_profile (wps, &wpmd); - copy_metadata (&wpmd, wps->blockbuff, wps->blockend); - free_metadata (&wpmd); - } - - if (flags & FLOAT_DATA) { - write_float_info (wps, &wpmd); - copy_metadata (&wpmd, wps->blockbuff, wps->blockend); - free_metadata (&wpmd); - } - - if (flags & INT32_DATA) { - write_int32_info (wps, &wpmd); - copy_metadata (&wpmd, wps->blockbuff, wps->blockend); - free_metadata (&wpmd); - } - - if ((flags & INITIAL_BLOCK) && - (wpc->config.num_channels > 2 || - wpc->config.channel_mask != 0x5 - wpc->config.num_channels)) { - write_channel_info (wpc, &wpmd); - copy_metadata (&wpmd, wps->blockbuff, wps->blockend); - free_metadata (&wpmd); - } - - if ((flags & INITIAL_BLOCK) && !wps->sample_index) { - write_config_info (wpc, &wpmd); - copy_metadata (&wpmd, wps->blockbuff, wps->blockend); - free_metadata (&wpmd); - } - - bs_open_write (&wps->wvbits, wps->blockbuff + ((WavpackHeader *) wps->blockbuff)->ckSize + 12, wps->blockend); - - if (wpc->wvc_flag) { - wps->wphdr.ckSize = sizeof (WavpackHeader) - 8; - memcpy (wps->block2buff, &wps->wphdr, sizeof (WavpackHeader)); - - if (flags & HYBRID_SHAPE) { - write_shaping_info (wps, &wpmd); - copy_metadata (&wpmd, wps->block2buff, wps->block2end); - free_metadata (&wpmd); - } - - bs_open_write (&wps->wvcbits, wps->block2buff + ((WavpackHeader *) wps->block2buff)->ckSize + 12, wps->block2end); - } - - /////////////////////// handle lossless mono mode ///////////////////////// - - if (!(flags & HYBRID_FLAG) && (flags & MONO_DATA)) { - if (!wps->num_passes) - for (bptr = buffer, i = 0; i < sample_count; ++i) { - int32_t code = *bptr; - - for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount--; dpp++) { - int32_t sam; - - if (dpp->term > MAX_TERM) { - if (dpp->term & 1) - sam = 2 * dpp->samples_A [0] - dpp->samples_A [1]; - else - sam = (3 * dpp->samples_A [0] - dpp->samples_A [1]) >> 1; - - dpp->samples_A [1] = dpp->samples_A [0]; - dpp->samples_A [0] = code; - } - else { - sam = dpp->samples_A [m]; - dpp->samples_A [(m + dpp->term) & (MAX_TERM - 1)] = code; - } - - code -= apply_weight (dpp->weight_A, sam); - update_weight (dpp->weight_A, dpp->delta, sam, code); - } - - m = (m + 1) & (MAX_TERM - 1); - *bptr++ = code; - } - - send_words_lossless (wps, buffer, sample_count); - } - - //////////////////// handle the lossless stereo mode ////////////////////// - - else if (!(flags & HYBRID_FLAG) && !(flags & MONO_DATA)) { - int32_t *eptr = buffer + (sample_count * 2); - - if (!wps->num_passes) { - if (flags & JOINT_STEREO) - for (bptr = buffer; bptr < eptr; bptr += 2) - bptr [1] += ((bptr [0] -= bptr [1]) >> 1); - - for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount-- ; dpp++) - if (((flags & MAG_MASK) >> MAG_LSB) >= 16 || dpp->delta != 2) - decorr_stereo_pass (dpp, buffer, sample_count); - else - decorr_stereo_pass_id2 (dpp, buffer, sample_count); - } - - send_words_lossless (wps, buffer, sample_count); - } - - /////////////////// handle the lossy/hybrid mono mode ///////////////////// - - else if ((flags & HYBRID_FLAG) && (flags & MONO_DATA)) - for (bptr = buffer, i = 0; i < sample_count; ++i) { - int32_t code, temp; - int shaping_weight; - - crc2 += (crc2 << 1) + (code = *bptr++); - - if (flags & HYBRID_SHAPE) { - if (shaping_array) - shaping_weight = *shaping_array++; - else - shaping_weight = (wps->dc.shaping_acc [0] += wps->dc.shaping_delta [0]) >> 16; - - temp = -apply_weight (shaping_weight, wps->dc.error [0]); - - if ((flags & NEW_SHAPING) && shaping_weight < 0 && temp) { - if (temp == wps->dc.error [0]) - temp = (temp < 0) ? temp + 1 : temp - 1; - - wps->dc.error [0] = -code; - code += temp; - } - else - wps->dc.error [0] = -(code += temp); - } - - for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount-- ; dpp++) - if (dpp->term > MAX_TERM) { - if (dpp->term & 1) - dpp->samples_A [2] = 2 * dpp->samples_A [0] - dpp->samples_A [1]; - else - dpp->samples_A [2] = (3 * dpp->samples_A [0] - dpp->samples_A [1]) >> 1; - - code -= (dpp->aweight_A = apply_weight (dpp->weight_A, dpp->samples_A [2])); - } - else - code -= (dpp->aweight_A = apply_weight (dpp->weight_A, dpp->samples_A [m])); - - code = send_word (wps, code, 0); - - while (--dpp >= wps->decorr_passes) { - if (dpp->term > MAX_TERM) { - update_weight (dpp->weight_A, dpp->delta, dpp->samples_A [2], code); - dpp->samples_A [1] = dpp->samples_A [0]; - dpp->samples_A [0] = (code += dpp->aweight_A); - } - else { - int32_t sam = dpp->samples_A [m]; - - update_weight (dpp->weight_A, dpp->delta, sam, code); - dpp->samples_A [(m + dpp->term) & (MAX_TERM - 1)] = (code += dpp->aweight_A); - } - } - - wps->dc.error [0] += code; - m = (m + 1) & (MAX_TERM - 1); - - if ((crc += (crc << 1) + code) != crc2) - lossy = TRUE; - - if (wpc->config.flags & CONFIG_CALC_NOISE) { - noise = code - bptr [-1]; - - noise_acc += noise *= noise; - wps->dc.noise_ave = (wps->dc.noise_ave * 0.99) + (noise * 0.01); - - if (wps->dc.noise_ave > wps->dc.noise_max) - wps->dc.noise_max = wps->dc.noise_ave; - } - } - - /////////////////// handle the lossy/hybrid stereo mode /////////////////// - - else if ((flags & HYBRID_FLAG) && !(flags & MONO_DATA)) - for (bptr = buffer, i = 0; i < sample_count; ++i) { - int32_t left, right, temp; - int shaping_weight; - - left = *bptr++; - crc2 += (crc2 << 3) + (left << 1) + left + (right = *bptr++); - - if (flags & HYBRID_SHAPE) { - if (shaping_array) - shaping_weight = *shaping_array++; - else - shaping_weight = (wps->dc.shaping_acc [0] += wps->dc.shaping_delta [0]) >> 16; - - temp = -apply_weight (shaping_weight, wps->dc.error [0]); - - if ((flags & NEW_SHAPING) && shaping_weight < 0 && temp) { - if (temp == wps->dc.error [0]) - temp = (temp < 0) ? temp + 1 : temp - 1; - - wps->dc.error [0] = -left; - left += temp; - } - else - wps->dc.error [0] = -(left += temp); - - if (!shaping_array) - shaping_weight = (wps->dc.shaping_acc [1] += wps->dc.shaping_delta [1]) >> 16; - - temp = -apply_weight (shaping_weight, wps->dc.error [1]); - - if ((flags & NEW_SHAPING) && shaping_weight < 0 && temp) { - if (temp == wps->dc.error [1]) - temp = (temp < 0) ? temp + 1 : temp - 1; - - wps->dc.error [1] = -right; - right += temp; - } - else - wps->dc.error [1] = -(right += temp); - } - - if (flags & JOINT_STEREO) - right += ((left -= right) >> 1); - - for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount-- ; dpp++) - if (dpp->term > MAX_TERM) { - if (dpp->term & 1) { - dpp->samples_A [2] = 2 * dpp->samples_A [0] - dpp->samples_A [1]; - dpp->samples_B [2] = 2 * dpp->samples_B [0] - dpp->samples_B [1]; - } - else { - dpp->samples_A [2] = (3 * dpp->samples_A [0] - dpp->samples_A [1]) >> 1; - dpp->samples_B [2] = (3 * dpp->samples_B [0] - dpp->samples_B [1]) >> 1; - } - - left -= (dpp->aweight_A = apply_weight (dpp->weight_A, dpp->samples_A [2])); - right -= (dpp->aweight_B = apply_weight (dpp->weight_B, dpp->samples_B [2])); - } - else if (dpp->term > 0) { - left -= (dpp->aweight_A = apply_weight (dpp->weight_A, dpp->samples_A [m])); - right -= (dpp->aweight_B = apply_weight (dpp->weight_B, dpp->samples_B [m])); - } - else { - if (dpp->term == -1) - dpp->samples_B [0] = left; - else if (dpp->term == -2) - dpp->samples_A [0] = right; - - left -= (dpp->aweight_A = apply_weight (dpp->weight_A, dpp->samples_A [0])); - right -= (dpp->aweight_B = apply_weight (dpp->weight_B, dpp->samples_B [0])); - } - - left = send_word (wps, left, 0); - right = send_word (wps, right, 1); - - while (--dpp >= wps->decorr_passes) - if (dpp->term > MAX_TERM) { - update_weight (dpp->weight_A, dpp->delta, dpp->samples_A [2], left); - update_weight (dpp->weight_B, dpp->delta, dpp->samples_B [2], right); - - dpp->samples_A [1] = dpp->samples_A [0]; - dpp->samples_B [1] = dpp->samples_B [0]; - - dpp->samples_A [0] = (left += dpp->aweight_A); - dpp->samples_B [0] = (right += dpp->aweight_B); - } - else if (dpp->term > 0) { - int k = (m + dpp->term) & (MAX_TERM - 1); - - update_weight (dpp->weight_A, dpp->delta, dpp->samples_A [m], left); - dpp->samples_A [k] = (left += dpp->aweight_A); - - update_weight (dpp->weight_B, dpp->delta, dpp->samples_B [m], right); - dpp->samples_B [k] = (right += dpp->aweight_B); - } - else { - if (dpp->term == -1) { - dpp->samples_B [0] = left + dpp->aweight_A; - dpp->aweight_B = apply_weight (dpp->weight_B, dpp->samples_B [0]); - } - else if (dpp->term == -2) { - dpp->samples_A [0] = right + dpp->aweight_B; - dpp->aweight_A = apply_weight (dpp->weight_A, dpp->samples_A [0]); - } - - update_weight_clip (dpp->weight_A, dpp->delta, dpp->samples_A [0], left); - update_weight_clip (dpp->weight_B, dpp->delta, dpp->samples_B [0], right); - dpp->samples_B [0] = (left += dpp->aweight_A); - dpp->samples_A [0] = (right += dpp->aweight_B); - } - - if (flags & JOINT_STEREO) - left += (right -= (left >> 1)); - - wps->dc.error [0] += left; - wps->dc.error [1] += right; - m = (m + 1) & (MAX_TERM - 1); - - if ((crc += (crc << 3) + (left << 1) + left + right) != crc2) - lossy = TRUE; - - if (wpc->config.flags & CONFIG_CALC_NOISE) { - noise = (double)(left - bptr [-2]) * (left - bptr [-2]); - noise += (double)(right - bptr [-1]) * (right - bptr [-1]); - - noise_acc += noise /= 2.0; - wps->dc.noise_ave = (wps->dc.noise_ave * 0.99) + (noise * 0.01); - - if (wps->dc.noise_ave > wps->dc.noise_max) - wps->dc.noise_max = wps->dc.noise_ave; - } - } - - if (m) - for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount--; dpp++) - if (dpp->term > 0 && dpp->term <= MAX_TERM) { - int32_t temp_A [MAX_TERM], temp_B [MAX_TERM]; - int k; - - memcpy (temp_A, dpp->samples_A, sizeof (dpp->samples_A)); - memcpy (temp_B, dpp->samples_B, sizeof (dpp->samples_B)); - - for (k = 0; k < MAX_TERM; k++) { - dpp->samples_A [k] = temp_A [m]; - dpp->samples_B [k] = temp_B [m]; - m = (m + 1) & (MAX_TERM - 1); - } - } - - if (wpc->config.flags & CONFIG_CALC_NOISE) - wps->dc.noise_sum += noise_acc; - - flush_word (wps); - data_count = bs_close_write (&wps->wvbits); - - if (data_count) { - if (data_count != (uint32_t) -1) { - uchar *cptr = wps->blockbuff + ((WavpackHeader *) wps->blockbuff)->ckSize + 8; - - *cptr++ = ID_WV_BITSTREAM | ID_LARGE; - *cptr++ = data_count >> 1; - *cptr++ = data_count >> 9; - *cptr++ = data_count >> 17; - ((WavpackHeader *) wps->blockbuff)->ckSize += data_count + 4; - } - else - return FALSE; - } - - ((WavpackHeader *) wps->blockbuff)->crc = crc; - - if (wpc->wvc_flag) { - data_count = bs_close_write (&wps->wvcbits); - - if (data_count && lossy) { - if (data_count != (uint32_t) -1) { - uchar *cptr = wps->block2buff + ((WavpackHeader *) wps->block2buff)->ckSize + 8; - - *cptr++ = ID_WVC_BITSTREAM | ID_LARGE; - *cptr++ = data_count >> 1; - *cptr++ = data_count >> 9; - *cptr++ = data_count >> 17; - ((WavpackHeader *) wps->block2buff)->ckSize += data_count + 4; - } - else - return FALSE; - } - - ((WavpackHeader *) wps->block2buff)->crc = crc2; - } - else if (lossy) - wpc->lossy_blocks = TRUE; - - wps->sample_index += sample_count; - return TRUE; -} - -// Perform a pass of the stereo decorrelation as specified by the referenced -// dpp structure. This version is optimized for samples that can use the -// simple apply_weight macro (i.e. <= 16-bit audio) and for when the weight -// delta is 2 (which is the case with all the default, non -x modes). For -// cases that do not fit this model, the more general decorr_stereo_pass() -// is provided. Note that this function returns the dpp->samples_X[] values -// in the "normalized" positions for terms 1-8. - -static void decorr_stereo_pass_id2 (struct decorr_pass *dpp, int32_t *buffer, int32_t sample_count) -{ - int32_t *bptr, *eptr = buffer + (sample_count * 2); - int m, k; - - switch (dpp->term) { - case 17: - for (bptr = buffer; bptr < eptr; bptr += 2) { - int32_t sam, tmp; - - sam = 2 * dpp->samples_A [0] - dpp->samples_A [1]; - dpp->samples_A [1] = dpp->samples_A [0]; - bptr [0] = tmp = (dpp->samples_A [0] = bptr [0]) - apply_weight_i (dpp->weight_A, sam); - update_weight_d2 (dpp->weight_A, dpp->delta, sam, tmp); - - sam = 2 * dpp->samples_B [0] - dpp->samples_B [1]; - dpp->samples_B [1] = dpp->samples_B [0]; - bptr [1] = tmp = (dpp->samples_B [0] = bptr [1]) - apply_weight_i (dpp->weight_B, sam); - update_weight_d2 (dpp->weight_B, dpp->delta, sam, tmp); - } - - break; - - case 18: - for (bptr = buffer; bptr < eptr; bptr += 2) { - int32_t sam, tmp; - - sam = dpp->samples_A [0] + ((dpp->samples_A [0] - dpp->samples_A [1]) >> 1); - dpp->samples_A [1] = dpp->samples_A [0]; - bptr [0] = tmp = (dpp->samples_A [0] = bptr [0]) - apply_weight_i (dpp->weight_A, sam); - update_weight_d2 (dpp->weight_A, dpp->delta, sam, tmp); - - sam = dpp->samples_B [0] + ((dpp->samples_B [0] - dpp->samples_B [1]) >> 1); - dpp->samples_B [1] = dpp->samples_B [0]; - bptr [1] = tmp = (dpp->samples_B [0] = bptr [1]) - apply_weight_i (dpp->weight_B, sam); - update_weight_d2 (dpp->weight_B, dpp->delta, sam, tmp); - } - - break; - - default: - for (m = 0, k = dpp->term & (MAX_TERM - 1), bptr = buffer; bptr < eptr; bptr += 2) { - int32_t sam, tmp; - - sam = dpp->samples_A [m]; - bptr [0] = tmp = (dpp->samples_A [k] = bptr [0]) - apply_weight_i (dpp->weight_A, sam); - update_weight_d2 (dpp->weight_A, dpp->delta, sam, tmp); - - sam = dpp->samples_B [m]; - bptr [1] = tmp = (dpp->samples_B [k] = bptr [1]) - apply_weight_i (dpp->weight_B, sam); - update_weight_d2 (dpp->weight_B, dpp->delta, sam, tmp); - - m = (m + 1) & (MAX_TERM - 1); - k = (k + 1) & (MAX_TERM - 1); - } - - if (m) { - int32_t temp_A [MAX_TERM], temp_B [MAX_TERM]; - - memcpy (temp_A, dpp->samples_A, sizeof (dpp->samples_A)); - memcpy (temp_B, dpp->samples_B, sizeof (dpp->samples_B)); - - for (k = 0; k < MAX_TERM; k++) { - dpp->samples_A [k] = temp_A [m]; - dpp->samples_B [k] = temp_B [m]; - m = (m + 1) & (MAX_TERM - 1); - } - } - - break; - - case -1: - for (bptr = buffer; bptr < eptr; bptr += 2) { - int32_t sam_A, sam_B, tmp; - - sam_A = dpp->samples_A [0]; - bptr [0] = tmp = (sam_B = bptr [0]) - apply_weight_i (dpp->weight_A, sam_A); - update_weight_clip_d2 (dpp->weight_A, dpp->delta, sam_A, tmp); - - bptr [1] = tmp = (dpp->samples_A [0] = bptr [1]) - apply_weight_i (dpp->weight_B, sam_B); - update_weight_clip_d2 (dpp->weight_B, dpp->delta, sam_B, tmp); - } - - break; - - case -2: - for (bptr = buffer; bptr < eptr; bptr += 2) { - int32_t sam_A, sam_B, tmp; - - sam_B = dpp->samples_B [0]; - bptr [1] = tmp = (sam_A = bptr [1]) - apply_weight_i (dpp->weight_B, sam_B); - update_weight_clip_d2 (dpp->weight_B, dpp->delta, sam_B, tmp); - - bptr [0] = tmp = (dpp->samples_B [0] = bptr [0]) - apply_weight_i (dpp->weight_A, sam_A); - update_weight_clip_d2 (dpp->weight_A, dpp->delta, sam_A, tmp); - } - - break; - - case -3: - for (bptr = buffer; bptr < eptr; bptr += 2) { - int32_t sam_A, sam_B, tmp; - - sam_A = dpp->samples_A [0]; - sam_B = dpp->samples_B [0]; - - dpp->samples_A [0] = tmp = bptr [1]; - bptr [1] = tmp -= apply_weight_i (dpp->weight_B, sam_B); - update_weight_clip_d2 (dpp->weight_B, dpp->delta, sam_B, tmp); - - dpp->samples_B [0] = tmp = bptr [0]; - bptr [0] = tmp -= apply_weight_i (dpp->weight_A, sam_A); - update_weight_clip_d2 (dpp->weight_A, dpp->delta, sam_A, tmp); - } - - break; - } -} - -// Perform a pass of the stereo decorrelation as specified by the referenced -// dpp structure. This function is provided in both a regular C version and -// an MMX version (using intrinsics) written by Joachim Henke. The MMX version -// is significantly faster when the sample data requires the full-resolution -// apply_weight macro. However, when the data is lower resolution (<= 16-bit) -// then the difference is slight (or the MMX is even slower), so for these -// cases the simpler decorr_stereo_pass_id2() is used. Note that this function -// returns the dpp->samples_X[] values in the "normalized" positions for -// terms 1-8. - -#ifdef OPT_MMX - -static void decorr_stereo_pass (struct decorr_pass *dpp, int32_t *buffer, int32_t sample_count) -{ - const __m64 - delta = _mm_set1_pi32 (dpp->delta), - fill = _mm_set1_pi32 (0x7bff), - mask = _mm_set1_pi32 (0x7fff), - round = _mm_set1_pi32 (512), - zero = _mm_set1_pi32 (0); - __m64 - weight_AB = _mm_set_pi32 (restore_weight (store_weight (dpp->weight_B)), restore_weight (store_weight (dpp->weight_A))), - left_right, sam_AB, tmp0, tmp1, samples_AB [MAX_TERM]; - int k, m = 0; - - for (k = 0; k < MAX_TERM; ++k) { - ((int32_t *) samples_AB) [k * 2] = exp2s (log2s (dpp->samples_A [k])); - ((int32_t *) samples_AB) [k * 2 + 1] = exp2s (log2s (dpp->samples_B [k])); - } - - if (dpp->term > 0) { - if (dpp->term == 17) { - while (sample_count--) { - left_right = *(__m64 *) buffer; - tmp0 = samples_AB [0]; - sam_AB = _m_paddd (tmp0, tmp0); - sam_AB = _m_psubd (sam_AB, samples_AB [1]); - samples_AB [0] = left_right; - samples_AB [1] = tmp0; - - tmp0 = _m_paddd (sam_AB, sam_AB); - tmp1 = _m_pand (sam_AB, mask); - tmp0 = _m_psrldi (tmp0, 16); - tmp1 = _m_pmaddwd (tmp1, weight_AB); - tmp0 = _m_pmaddwd (tmp0, weight_AB); - tmp1 = _m_paddd (tmp1, round); - tmp0 = _m_pslldi (tmp0, 5); - tmp1 = _m_psradi (tmp1, 10); - left_right = _m_psubd (left_right, tmp0); - left_right = _m_psubd (left_right, tmp1); - - *(__m64 *) buffer = left_right; - - tmp0 = _m_pxor (sam_AB, left_right); - tmp0 = _m_psradi (tmp0, 31); - tmp1 = _m_pxor (delta, tmp0); - tmp1 = _m_psubd (tmp1, tmp0); - sam_AB = _m_pcmpeqd (sam_AB, zero); - tmp0 = _m_pcmpeqd (left_right, zero); - tmp0 = _m_por (tmp0, sam_AB); - tmp0 = _m_pandn (tmp0, tmp1); - weight_AB = _m_paddd (weight_AB, tmp0); - - buffer += 2; - } - } - else if (dpp->term == 18) { - while (sample_count--) { - left_right = *(__m64 *) buffer; - tmp0 = samples_AB [0]; - sam_AB = _m_psubd (tmp0, samples_AB [1]); - sam_AB = _m_psradi (sam_AB, 1); - sam_AB = _m_paddd (sam_AB, tmp0); - samples_AB [0] = left_right; - samples_AB [1] = tmp0; - - tmp0 = _m_paddd (sam_AB, sam_AB); - tmp1 = _m_pand (sam_AB, mask); - tmp0 = _m_psrldi (tmp0, 16); - tmp1 = _m_pmaddwd (tmp1, weight_AB); - tmp0 = _m_pmaddwd (tmp0, weight_AB); - tmp1 = _m_paddd (tmp1, round); - tmp0 = _m_pslldi (tmp0, 5); - tmp1 = _m_psradi (tmp1, 10); - left_right = _m_psubd (left_right, tmp0); - left_right = _m_psubd (left_right, tmp1); - - *(__m64 *) buffer = left_right; - - tmp0 = _m_pxor (sam_AB, left_right); - tmp0 = _m_psradi (tmp0, 31); - tmp1 = _m_pxor (delta, tmp0); - tmp1 = _m_psubd (tmp1, tmp0); - sam_AB = _m_pcmpeqd (sam_AB, zero); - tmp0 = _m_pcmpeqd (left_right, zero); - tmp0 = _m_por (tmp0, sam_AB); - tmp0 = _m_pandn (tmp0, tmp1); - weight_AB = _m_paddd (weight_AB, tmp0); - - buffer += 2; - } - } - else { - k = dpp->term & (MAX_TERM - 1); - while (sample_count--) { - left_right = *(__m64 *) buffer; - sam_AB = samples_AB [m]; - samples_AB [k] = left_right; - - tmp0 = _m_paddd (sam_AB, sam_AB); - tmp1 = _m_pand (sam_AB, mask); - tmp0 = _m_psrldi (tmp0, 16); - tmp1 = _m_pmaddwd (tmp1, weight_AB); - tmp0 = _m_pmaddwd (tmp0, weight_AB); - tmp1 = _m_paddd (tmp1, round); - tmp0 = _m_pslldi (tmp0, 5); - tmp1 = _m_psradi (tmp1, 10); - left_right = _m_psubd (left_right, tmp0); - left_right = _m_psubd (left_right, tmp1); - - *(__m64 *) buffer = left_right; - - tmp0 = _m_pxor (sam_AB, left_right); - tmp0 = _m_psradi (tmp0, 31); - tmp1 = _m_pxor (delta, tmp0); - tmp1 = _m_psubd (tmp1, tmp0); - sam_AB = _m_pcmpeqd (sam_AB, zero); - tmp0 = _m_pcmpeqd (left_right, zero); - tmp0 = _m_por (tmp0, sam_AB); - tmp0 = _m_pandn (tmp0, tmp1); - weight_AB = _m_paddd (weight_AB, tmp0); - - buffer += 2; - k = (k + 1) & (MAX_TERM - 1); - m = (m + 1) & (MAX_TERM - 1); - } - } - } - else { - if (dpp->term == -1) { - while (sample_count--) { - left_right = *(__m64 *) buffer; - sam_AB = samples_AB [0]; - samples_AB [0] = _m_punpckhdq (left_right, sam_AB); - sam_AB = _m_punpckldq (sam_AB, left_right); - - tmp0 = _m_paddd (sam_AB, sam_AB); - tmp1 = _m_pand (sam_AB, mask); - tmp0 = _m_psrldi (tmp0, 16); - tmp1 = _m_pmaddwd (tmp1, weight_AB); - tmp0 = _m_pmaddwd (tmp0, weight_AB); - tmp1 = _m_paddd (tmp1, round); - tmp0 = _m_pslldi (tmp0, 5); - tmp1 = _m_psradi (tmp1, 10); - left_right = _m_psubd (left_right, tmp0); - left_right = _m_psubd (left_right, tmp1); - - *(__m64 *) buffer = left_right; - - tmp0 = _m_pcmpeqd (sam_AB, zero); - tmp1 = _m_pcmpeqd (left_right, zero); - tmp0 = _m_por (tmp0, tmp1); - tmp0 = _m_pandn (tmp0, delta); - sam_AB = _m_pxor (sam_AB, left_right); - sam_AB = _m_psradi (sam_AB, 31); - tmp1 = _m_psubd (fill, sam_AB); - weight_AB = _m_pxor (weight_AB, sam_AB); - weight_AB = _m_paddd (weight_AB, tmp1); - weight_AB = _m_paddsw (weight_AB, tmp0); - weight_AB = _m_psubd (weight_AB, tmp1); - weight_AB = _m_pxor (weight_AB, sam_AB); - - buffer += 2; - } - } - else if (dpp->term == -2) { - while (sample_count--) { - left_right = *(__m64 *) buffer; - sam_AB = samples_AB [0]; - samples_AB [0] = _m_punpckldq (sam_AB, left_right); - sam_AB = _m_punpckhdq (left_right, sam_AB); - - tmp0 = _m_paddd (sam_AB, sam_AB); - tmp1 = _m_pand (sam_AB, mask); - tmp0 = _m_psrldi (tmp0, 16); - tmp1 = _m_pmaddwd (tmp1, weight_AB); - tmp0 = _m_pmaddwd (tmp0, weight_AB); - tmp1 = _m_paddd (tmp1, round); - tmp0 = _m_pslldi (tmp0, 5); - tmp1 = _m_psradi (tmp1, 10); - left_right = _m_psubd (left_right, tmp0); - left_right = _m_psubd (left_right, tmp1); - - *(__m64 *) buffer = left_right; - - tmp0 = _m_pcmpeqd (sam_AB, zero); - tmp1 = _m_pcmpeqd (left_right, zero); - tmp0 = _m_por (tmp0, tmp1); - tmp0 = _m_pandn (tmp0, delta); - sam_AB = _m_pxor (sam_AB, left_right); - sam_AB = _m_psradi (sam_AB, 31); - tmp1 = _m_psubd (fill, sam_AB); - weight_AB = _m_pxor (weight_AB, sam_AB); - weight_AB = _m_paddd (weight_AB, tmp1); - weight_AB = _m_paddsw (weight_AB, tmp0); - weight_AB = _m_psubd (weight_AB, tmp1); - weight_AB = _m_pxor (weight_AB, sam_AB); - - buffer += 2; - } - } - else if (dpp->term == -3) { - while (sample_count--) { - left_right = *(__m64 *) buffer; - sam_AB = samples_AB [0]; - tmp0 = _m_punpckhdq (left_right, left_right); - samples_AB [0] = _m_punpckldq (tmp0, left_right); - - tmp0 = _m_paddd (sam_AB, sam_AB); - tmp1 = _m_pand (sam_AB, mask); - tmp0 = _m_psrldi (tmp0, 16); - tmp1 = _m_pmaddwd (tmp1, weight_AB); - tmp0 = _m_pmaddwd (tmp0, weight_AB); - tmp1 = _m_paddd (tmp1, round); - tmp0 = _m_pslldi (tmp0, 5); - tmp1 = _m_psradi (tmp1, 10); - left_right = _m_psubd (left_right, tmp0); - left_right = _m_psubd (left_right, tmp1); - - *(__m64 *) buffer = left_right; - - tmp0 = _m_pcmpeqd (sam_AB, zero); - tmp1 = _m_pcmpeqd (left_right, zero); - tmp0 = _m_por (tmp0, tmp1); - tmp0 = _m_pandn (tmp0, delta); - sam_AB = _m_pxor (sam_AB, left_right); - sam_AB = _m_psradi (sam_AB, 31); - tmp1 = _m_psubd (fill, sam_AB); - weight_AB = _m_pxor (weight_AB, sam_AB); - weight_AB = _m_paddd (weight_AB, tmp1); - weight_AB = _m_paddsw (weight_AB, tmp0); - weight_AB = _m_psubd (weight_AB, tmp1); - weight_AB = _m_pxor (weight_AB, sam_AB); - - buffer += 2; - } - } - } - - dpp->weight_A = ((int32_t *) &weight_AB) [0]; - dpp->weight_B = ((int32_t *) &weight_AB) [1]; - - for (k = 0; k < MAX_TERM; ++k) { - dpp->samples_A [k] = ((int32_t *) samples_AB) [m * 2]; - dpp->samples_B [k] = ((int32_t *) samples_AB) [m * 2 + 1]; - m = (m + 1) & (MAX_TERM - 1); - } - - _mm_empty (); -} - -#else - -static void decorr_stereo_pass (struct decorr_pass *dpp, int32_t *buffer, int32_t sample_count) -{ - int32_t *bptr, *eptr = buffer + (sample_count * 2); - int m, k; - - switch (dpp->term) { - case 17: - for (bptr = buffer; bptr < eptr; bptr += 2) { - int32_t sam, tmp; - - sam = 2 * dpp->samples_A [0] - dpp->samples_A [1]; - dpp->samples_A [1] = dpp->samples_A [0]; - bptr [0] = tmp = (dpp->samples_A [0] = bptr [0]) - apply_weight (dpp->weight_A, sam); - update_weight (dpp->weight_A, dpp->delta, sam, tmp); - - sam = 2 * dpp->samples_B [0] - dpp->samples_B [1]; - dpp->samples_B [1] = dpp->samples_B [0]; - bptr [1] = tmp = (dpp->samples_B [0] = bptr [1]) - apply_weight (dpp->weight_B, sam); - update_weight (dpp->weight_B, dpp->delta, sam, tmp); - } - - break; - - case 18: - for (bptr = buffer; bptr < eptr; bptr += 2) { - int32_t sam, tmp; - - sam = dpp->samples_A [0] + ((dpp->samples_A [0] - dpp->samples_A [1]) >> 1); - dpp->samples_A [1] = dpp->samples_A [0]; - bptr [0] = tmp = (dpp->samples_A [0] = bptr [0]) - apply_weight (dpp->weight_A, sam); - update_weight (dpp->weight_A, dpp->delta, sam, tmp); - - sam = dpp->samples_B [0] + ((dpp->samples_B [0] - dpp->samples_B [1]) >> 1); - dpp->samples_B [1] = dpp->samples_B [0]; - bptr [1] = tmp = (dpp->samples_B [0] = bptr [1]) - apply_weight (dpp->weight_B, sam); - update_weight (dpp->weight_B, dpp->delta, sam, tmp); - } - - break; - - default: - for (m = 0, k = dpp->term & (MAX_TERM - 1), bptr = buffer; bptr < eptr; bptr += 2) { - int32_t sam, tmp; - - sam = dpp->samples_A [m]; - bptr [0] = tmp = (dpp->samples_A [k] = bptr [0]) - apply_weight (dpp->weight_A, sam); - update_weight (dpp->weight_A, dpp->delta, sam, tmp); - - sam = dpp->samples_B [m]; - bptr [1] = tmp = (dpp->samples_B [k] = bptr [1]) - apply_weight (dpp->weight_B, sam); - update_weight (dpp->weight_B, dpp->delta, sam, tmp); - - m = (m + 1) & (MAX_TERM - 1); - k = (k + 1) & (MAX_TERM - 1); - } - - if (m) { - int32_t temp_A [MAX_TERM], temp_B [MAX_TERM]; - - memcpy (temp_A, dpp->samples_A, sizeof (dpp->samples_A)); - memcpy (temp_B, dpp->samples_B, sizeof (dpp->samples_B)); - - for (k = 0; k < MAX_TERM; k++) { - dpp->samples_A [k] = temp_A [m]; - dpp->samples_B [k] = temp_B [m]; - m = (m + 1) & (MAX_TERM - 1); - } - } - - break; - - case -1: - for (bptr = buffer; bptr < eptr; bptr += 2) { - int32_t sam_A, sam_B, tmp; - - sam_A = dpp->samples_A [0]; - bptr [0] = tmp = (sam_B = bptr [0]) - apply_weight (dpp->weight_A, sam_A); - update_weight_clip (dpp->weight_A, dpp->delta, sam_A, tmp); - - bptr [1] = tmp = (dpp->samples_A [0] = bptr [1]) - apply_weight (dpp->weight_B, sam_B); - update_weight_clip (dpp->weight_B, dpp->delta, sam_B, tmp); - } - - break; - - case -2: - for (bptr = buffer; bptr < eptr; bptr += 2) { - int32_t sam_A, sam_B, tmp; - - sam_B = dpp->samples_B [0]; - bptr [1] = tmp = (sam_A = bptr [1]) - apply_weight (dpp->weight_B, sam_B); - update_weight_clip (dpp->weight_B, dpp->delta, sam_B, tmp); - - bptr [0] = tmp = (dpp->samples_B [0] = bptr [0]) - apply_weight (dpp->weight_A, sam_A); - update_weight_clip (dpp->weight_A, dpp->delta, sam_A, tmp); - } - - break; - - case -3: - for (bptr = buffer; bptr < eptr; bptr += 2) { - int32_t sam_A, sam_B, tmp; - - sam_A = dpp->samples_A [0]; - sam_B = dpp->samples_B [0]; - - dpp->samples_A [0] = tmp = bptr [1]; - bptr [1] = tmp -= apply_weight (dpp->weight_B, sam_B); - update_weight_clip (dpp->weight_B, dpp->delta, sam_B, tmp); - - dpp->samples_B [0] = tmp = bptr [0]; - bptr [0] = tmp -= apply_weight (dpp->weight_A, sam_A); - update_weight_clip (dpp->weight_A, dpp->delta, sam_A, tmp); - } - - break; - } -} - -#endif - -////////////////////////////////////////////////////////////////////////////// -// This function returns the accumulated RMS noise as a double if the // -// CALC_NOISE bit was set in the WavPack header. The peak noise can also be // -// returned if desired. See wavpack.c for the calculations required to // -// convert this into decibels of noise below full scale. // -////////////////////////////////////////////////////////////////////////////// - -double WavpackGetEncodedNoise (WavpackContext *wpc, double *peak) -{ - WavpackStream *wps = wpc->streams [wpc->current_stream]; - - if (peak) - *peak = wps->dc.noise_max; - - return wps->dc.noise_sum; -} - -// Given an array of integer data (in shorts), find the linear function that most closely -// represents it (based on minimum sum of absolute errors). This is returned as the double -// precision initial & final Y values of the best-fit line. The function can also optionally -// compute and return a maximum error value (as a short). Note that the ends of the resulting -// line may fall way outside the range of input values, so some sort of clipping may be -// needed. - -void best_floating_line (short *values, int num_values, double *initial_y, double *final_y, short *max_error) -{ - double left_sum = 0.0, right_sum = 0.0, center_x = (num_values - 1) / 2.0, center_y, m; - int i; - - for (i = 0; i < num_values >> 1; ++i) { - right_sum += values [num_values - i - 1]; - left_sum += values [i]; - } - - if (num_values & 1) { - right_sum += values [num_values >> 1] * 0.5; - left_sum += values [num_values >> 1] * 0.5; - } - - center_y = (right_sum + left_sum) / num_values; - m = (right_sum - left_sum) / ((double) num_values * num_values) * 4.0; - - if (initial_y) - *initial_y = center_y - m * center_x; - - if (final_y) - *final_y = center_y + m * center_x; - - if (max_error) { - double max = 0.0; - - for (i = 0; i < num_values; ++i) - if (fabs (values [i] - (center_y + (i - center_x) * m)) > max) - max = fabs (values [i] - (center_y + (i - center_x) * m)); - - *max_error = (short) floor (max + 0.5); - } -} diff --git a/wavpack-4.5.0/src/unpack.c b/wavpack-4.5.0/src/unpack.c deleted file mode 100644 index 80942c5..0000000 --- a/wavpack-4.5.0/src/unpack.c +++ /dev/null @@ -1,1399 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// **** WAVPACK **** // -// Hybrid Lossless Wavefile Compressor // -// Copyright (c) 1998 - 2006 Conifer Software. // -// All Rights Reserved. // -// Distributed under the BSD Software License (see license.txt) // -//////////////////////////////////////////////////////////////////////////// - -// unpack.c - -// This module actually handles the decompression of the audio data, except -// for the entropy decoding which is handled by the words? modules. For -// maximum efficiency, the conversion is isolated to tight loops that handle -// an entire buffer. - -#include "wavpack_local.h" - -#include -#include -#include -#include - -// This flag provides faster decoding speed at the expense of more code. The -// improvement applies to 16-bit stereo lossless only. - -#define FAST_DECODE - -#define LOSSY_MUTE - -#ifdef DEBUG_ALLOC -#define malloc malloc_db -#define realloc realloc_db -#define free free_db -void *malloc_db (uint32_t size); -void *realloc_db (void *ptr, uint32_t size); -void free_db (void *ptr); -int32_t dump_alloc (void); -#endif - -///////////////////////////// executable code //////////////////////////////// - -// This function initializes everything required to unpack a WavPack block -// and must be called before unpack_samples() is called to obtain audio data. -// It is assumed that the WavpackHeader has been read into the wps->wphdr -// (in the current WavpackStream) and that the entire block has been read at -// wps->blockbuff. If a correction file is available (wpc->wvc_flag = TRUE) -// then the corresponding correction block must be read into wps->block2buff -// and its WavpackHeader has overwritten the header at wps->wphdr. This is -// where all the metadata blocks are scanned including those that contain -// bitstream data. - -int unpack_init (WavpackContext *wpc) -{ - WavpackStream *wps = wpc->streams [wpc->current_stream]; - uchar *blockptr, *block2ptr; - WavpackMetadata wpmd; - - wps->mute_error = FALSE; - wps->crc = wps->crc_x = 0xffffffff; - CLEAR (wps->wvbits); - CLEAR (wps->wvcbits); - CLEAR (wps->wvxbits); - CLEAR (wps->decorr_passes); - CLEAR (wps->dc); - CLEAR (wps->w); - - if (!(wps->wphdr.flags & MONO_FLAG) && wpc->config.num_channels && wps->wphdr.block_samples && - (wpc->reduced_channels == 1 || wpc->config.num_channels == 1)) { - wps->mute_error = TRUE; - return FALSE; - } - - if ((wps->wphdr.flags & UNKNOWN_FLAGS) || (wps->wphdr.flags & MONO_DATA) == MONO_DATA) { - wps->mute_error = TRUE; - return FALSE; - } - - blockptr = wps->blockbuff + sizeof (WavpackHeader); - - while (read_metadata_buff (&wpmd, wps->blockbuff, &blockptr)) - if (!process_metadata (wpc, &wpmd)) { - wps->mute_error = TRUE; - return FALSE; - } - - if (wps->wphdr.block_samples && wpc->wvc_flag && wps->block2buff) { - block2ptr = wps->block2buff + sizeof (WavpackHeader); - - while (read_metadata_buff (&wpmd, wps->block2buff, &block2ptr)) - if (!process_metadata (wpc, &wpmd)) { - wps->mute_error = TRUE; - return FALSE; - } - } - - if (wps->wphdr.block_samples && !bs_is_open (&wps->wvbits)) { - if (bs_is_open (&wps->wvcbits)) - strcpy (wpc->error_message, "can't unpack correction files alone!"); - - wps->mute_error = TRUE; - return FALSE; - } - - if (wps->wphdr.block_samples && !bs_is_open (&wps->wvxbits)) { - if ((wps->wphdr.flags & INT32_DATA) && wps->int32_sent_bits) - wpc->lossy_blocks = TRUE; - - if ((wps->wphdr.flags & FLOAT_DATA) && - wps->float_flags & (FLOAT_EXCEPTIONS | FLOAT_ZEROS_SENT | FLOAT_SHIFT_SENT | FLOAT_SHIFT_SAME)) - wpc->lossy_blocks = TRUE; - } - - if (wps->wphdr.block_samples) - wps->sample_index = wps->wphdr.block_index; - - return TRUE; -} - -// This function initialzes the main bitstream for audio samples, which must -// be in the "wv" file. - -int init_wv_bitstream (WavpackStream *wps, WavpackMetadata *wpmd) -{ - if (!wpmd->byte_length) - return FALSE; - - bs_open_read (&wps->wvbits, wpmd->data, (uchar *) wpmd->data + wpmd->byte_length); - return TRUE; -} - -// This function initialzes the "correction" bitstream for audio samples, -// which currently must be in the "wvc" file. - -int init_wvc_bitstream (WavpackStream *wps, WavpackMetadata *wpmd) -{ - if (!wpmd->byte_length) - return FALSE; - - bs_open_read (&wps->wvcbits, wpmd->data, (uchar *) wpmd->data + wpmd->byte_length); - return TRUE; -} - -// This function initialzes the "extra" bitstream for audio samples which -// contains the information required to losslessly decompress 32-bit float data -// or integer data that exceeds 24 bits. This bitstream is in the "wv" file -// for pure lossless data or the "wvc" file for hybrid lossless. This data -// would not be used for hybrid lossy mode. There is also a 32-bit CRC stored -// in the first 4 bytes of these blocks. - -int init_wvx_bitstream (WavpackStream *wps, WavpackMetadata *wpmd) -{ - uchar *cp = wpmd->data; - - if (wpmd->byte_length <= 4) - return FALSE; - - wps->crc_wvx = *cp++; - wps->crc_wvx |= (int32_t) *cp++ << 8; - wps->crc_wvx |= (int32_t) *cp++ << 16; - wps->crc_wvx |= (int32_t) *cp++ << 24; - - bs_open_read (&wps->wvxbits, cp, (uchar *) wpmd->data + wpmd->byte_length); - return TRUE; -} - -// Read decorrelation terms from specified metadata block into the -// decorr_passes array. The terms range from -3 to 8, plus 17 & 18; -// other values are reserved and generate errors for now. The delta -// ranges from 0 to 7 with all values valid. Note that the terms are -// stored in the opposite order in the decorr_passes array compared -// to packing. - -int read_decorr_terms (WavpackStream *wps, WavpackMetadata *wpmd) -{ - int termcnt = wpmd->byte_length; - uchar *byteptr = wpmd->data; - struct decorr_pass *dpp; - - if (termcnt > MAX_NTERMS) - return FALSE; - - wps->num_terms = termcnt; - - for (dpp = wps->decorr_passes + termcnt - 1; termcnt--; dpp--) { - dpp->term = (int)(*byteptr & 0x1f) - 5; - dpp->delta = (*byteptr++ >> 5) & 0x7; - - if (!dpp->term || dpp->term < -3 || (dpp->term > MAX_TERM && dpp->term < 17) || dpp->term > 18) - return FALSE; - } - - return TRUE; -} - -// Read decorrelation weights from specified metadata block into the -// decorr_passes array. The weights range +/-1024, but are rounded and -// truncated to fit in signed chars for metadata storage. Weights are -// separate for the two channels and are specified from the "last" term -// (first during encode). Unspecified weights are set to zero. - -int read_decorr_weights (WavpackStream *wps, WavpackMetadata *wpmd) -{ - int termcnt = wpmd->byte_length, tcount; - char *byteptr = wpmd->data; - struct decorr_pass *dpp; - - if (!(wps->wphdr.flags & MONO_DATA)) - termcnt /= 2; - - if (termcnt > wps->num_terms) - return FALSE; - - for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount--; dpp++) - dpp->weight_A = dpp->weight_B = 0; - - while (--dpp >= wps->decorr_passes && termcnt--) { - dpp->weight_A = restore_weight (*byteptr++); - - if (!(wps->wphdr.flags & MONO_DATA)) - dpp->weight_B = restore_weight (*byteptr++); - } - - return TRUE; -} - -// Read decorrelation samples from specified metadata block into the -// decorr_passes array. The samples are signed 32-bit values, but are -// converted to signed log2 values for storage in metadata. Values are -// stored for both channels and are specified from the "last" term -// (first during encode) with unspecified samples set to zero. The -// number of samples stored varies with the actual term value, so -// those must obviously come first in the metadata. - -int read_decorr_samples (WavpackStream *wps, WavpackMetadata *wpmd) -{ - uchar *byteptr = wpmd->data; - uchar *endptr = byteptr + wpmd->byte_length; - struct decorr_pass *dpp; - int tcount; - - for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount--; dpp++) { - CLEAR (dpp->samples_A); - CLEAR (dpp->samples_B); - } - - if (wps->wphdr.version == 0x402 && (wps->wphdr.flags & HYBRID_FLAG)) { - if (byteptr + (wps->wphdr.flags & MONO_DATA ? 2 : 4) > endptr) - return FALSE; - - wps->dc.error [0] = exp2s ((short)(byteptr [0] + (byteptr [1] << 8))); - byteptr += 2; - - if (!(wps->wphdr.flags & MONO_DATA)) { - wps->dc.error [1] = exp2s ((short)(byteptr [0] + (byteptr [1] << 8))); - byteptr += 2; - } - } - - while (dpp-- > wps->decorr_passes && byteptr < endptr) - if (dpp->term > MAX_TERM) { - if (byteptr + (wps->wphdr.flags & MONO_DATA ? 4 : 8) > endptr) - return FALSE; - - dpp->samples_A [0] = exp2s ((short)(byteptr [0] + (byteptr [1] << 8))); - dpp->samples_A [1] = exp2s ((short)(byteptr [2] + (byteptr [3] << 8))); - byteptr += 4; - - if (!(wps->wphdr.flags & MONO_DATA)) { - dpp->samples_B [0] = exp2s ((short)(byteptr [0] + (byteptr [1] << 8))); - dpp->samples_B [1] = exp2s ((short)(byteptr [2] + (byteptr [3] << 8))); - byteptr += 4; - } - } - else if (dpp->term < 0) { - if (byteptr + 4 > endptr) - return FALSE; - - dpp->samples_A [0] = exp2s ((short)(byteptr [0] + (byteptr [1] << 8))); - dpp->samples_B [0] = exp2s ((short)(byteptr [2] + (byteptr [3] << 8))); - byteptr += 4; - } - else { - int m = 0, cnt = dpp->term; - - while (cnt--) { - if (byteptr + (wps->wphdr.flags & MONO_DATA ? 2 : 4) > endptr) - return FALSE; - - dpp->samples_A [m] = exp2s ((short)(byteptr [0] + (byteptr [1] << 8))); - byteptr += 2; - - if (!(wps->wphdr.flags & MONO_DATA)) { - dpp->samples_B [m] = exp2s ((short)(byteptr [0] + (byteptr [1] << 8))); - byteptr += 2; - } - - m++; - } - } - - return byteptr == endptr; -} - -// Read the shaping weights from specified metadata block into the -// WavpackStream structure. Note that there must be two values (even -// for mono streams) and that the values are stored in the same -// manner as decorrelation weights. These would normally be read from -// the "correction" file and are used for lossless reconstruction of -// hybrid data. - -int read_shaping_info (WavpackStream *wps, WavpackMetadata *wpmd) -{ - if (wpmd->byte_length == 2) { - char *byteptr = wpmd->data; - - wps->dc.shaping_acc [0] = (int32_t) restore_weight (*byteptr++) << 16; - wps->dc.shaping_acc [1] = (int32_t) restore_weight (*byteptr++) << 16; - return TRUE; - } - else if (wpmd->byte_length >= (wps->wphdr.flags & MONO_DATA ? 4 : 8)) { - uchar *byteptr = wpmd->data; - - wps->dc.error [0] = exp2s ((short)(byteptr [0] + (byteptr [1] << 8))); - wps->dc.shaping_acc [0] = exp2s ((short)(byteptr [2] + (byteptr [3] << 8))); - byteptr += 4; - - if (!(wps->wphdr.flags & MONO_DATA)) { - wps->dc.error [1] = exp2s ((short)(byteptr [0] + (byteptr [1] << 8))); - wps->dc.shaping_acc [1] = exp2s ((short)(byteptr [2] + (byteptr [3] << 8))); - byteptr += 4; - } - - if (wpmd->byte_length == (wps->wphdr.flags & MONO_DATA ? 6 : 12)) { - wps->dc.shaping_delta [0] = exp2s ((short)(byteptr [0] + (byteptr [1] << 8))); - - if (!(wps->wphdr.flags & MONO_DATA)) - wps->dc.shaping_delta [1] = exp2s ((short)(byteptr [2] + (byteptr [3] << 8))); - } - - return TRUE; - } - - return FALSE; -} - -// Read the int32 data from the specified metadata into the specified stream. -// This data is used for integer data that has more than 24 bits of magnitude -// or, in some cases, used to eliminate redundant bits from any audio stream. - -int read_int32_info (WavpackStream *wps, WavpackMetadata *wpmd) -{ - int bytecnt = wpmd->byte_length; - char *byteptr = wpmd->data; - - if (bytecnt != 4) - return FALSE; - - wps->int32_sent_bits = *byteptr++; - wps->int32_zeros = *byteptr++; - wps->int32_ones = *byteptr++; - wps->int32_dups = *byteptr; - - return TRUE; -} - -// Read multichannel information from metadata. The first byte is the total -// number of channels and the following bytes represent the channel_mask -// as described for Microsoft WAVEFORMATEX. - -int read_channel_info (WavpackContext *wpc, WavpackMetadata *wpmd) -{ - int bytecnt = wpmd->byte_length, shift = 0; - uchar *byteptr = wpmd->data; - uint32_t mask = 0; - - if (!bytecnt || bytecnt > 5) - return FALSE; - - if (!wpc->config.num_channels) { - wpc->config.num_channels = *byteptr++; - - while (--bytecnt) { - mask |= (uint32_t) *byteptr++ << shift; - shift += 8; - } - - wpc->config.channel_mask = mask; - } - - return TRUE; -} - -// Read configuration information from metadata. - -int read_config_info (WavpackContext *wpc, WavpackMetadata *wpmd) -{ - int bytecnt = wpmd->byte_length; - uchar *byteptr = wpmd->data; - - if (bytecnt >= 3) { - wpc->config.flags &= 0xff; - wpc->config.flags |= (int32_t) *byteptr++ << 8; - wpc->config.flags |= (int32_t) *byteptr++ << 16; - wpc->config.flags |= (int32_t) *byteptr++ << 24; - - if (bytecnt >= 4 && (wpc->config.flags & CONFIG_EXTRA_MODE)) - wpc->config.xmode = *byteptr; - } - - return TRUE; -} - -// Read non-standard sampling rate from metadata. - -int read_sample_rate (WavpackContext *wpc, WavpackMetadata *wpmd) -{ - int bytecnt = wpmd->byte_length; - uchar *byteptr = wpmd->data; - - if (bytecnt == 3) { - wpc->config.sample_rate = (int32_t) *byteptr++; - wpc->config.sample_rate |= (int32_t) *byteptr++ << 8; - wpc->config.sample_rate |= (int32_t) *byteptr++ << 16; - } - - return TRUE; -} - -// Read wrapper data from metadata. Currently, this consists of the RIFF -// header and trailer that wav files contain around the audio data but could -// be used for other formats as well. Because WavPack files contain all the -// information required for decoding and playback, this data can probably -// be ignored except when an exact wavefile restoration is needed. - -int read_wrapper_data (WavpackContext *wpc, WavpackMetadata *wpmd) -{ - if ((wpc->open_flags & OPEN_WRAPPER) && wpc->wrapper_bytes < MAX_WRAPPER_BYTES) { - wpc->wrapper_data = realloc (wpc->wrapper_data, wpc->wrapper_bytes + wpmd->byte_length); - memcpy (wpc->wrapper_data + wpc->wrapper_bytes, wpmd->data, wpmd->byte_length); - wpc->wrapper_bytes += wpmd->byte_length; - } - - return TRUE; -} - -#ifndef NO_UNPACK - -// This monster actually unpacks the WavPack bitstream(s) into the specified -// buffer as 32-bit integers or floats (depending on orignal data). Lossy -// samples will be clipped to their original limits (i.e. 8-bit samples are -// clipped to -128/+127) but are still returned in longs. It is up to the -// caller to potentially reformat this for the final output including any -// multichannel distribution, block alignment or endian compensation. The -// function unpack_init() must have been called and the entire WavPack block -// must still be visible (although wps->blockbuff will not be accessed again). -// For maximum clarity, the function is broken up into segments that handle -// various modes. This makes for a few extra infrequent flag checks, but -// makes the code easier to follow because the nesting does not become so -// deep. For maximum efficiency, the conversion is isolated to tight loops -// that handle an entire buffer. The function returns the total number of -// samples unpacked, which can be less than the number requested if an error -// occurs or the end of the block is reached. - -static void decorr_stereo_pass (struct decorr_pass *dpp, int32_t *buffer, int32_t sample_count); -static void decorr_stereo_pass_i (struct decorr_pass *dpp, int32_t *buffer, int32_t sample_count); -static void decorr_stereo_pass_1717 (struct decorr_pass *dpp, int32_t *buffer, int32_t sample_count); -static void decorr_stereo_pass_1718 (struct decorr_pass *dpp, int32_t *buffer, int32_t sample_count); -static void decorr_stereo_pass_1818 (struct decorr_pass *dpp, int32_t *buffer, int32_t sample_count); -static void decorr_stereo_pass_nn (struct decorr_pass *dpp, int32_t *buffer, int32_t sample_count); -static void fixup_samples (WavpackContext *wpc, int32_t *buffer, uint32_t sample_count); - -int32_t unpack_samples (WavpackContext *wpc, int32_t *buffer, uint32_t sample_count) -{ - WavpackStream *wps = wpc->streams [wpc->current_stream]; - uint32_t flags = wps->wphdr.flags, crc = wps->crc, i; - int32_t mute_limit = (1L << ((flags & MAG_MASK) >> MAG_LSB)) + 2; - int32_t correction [2], read_word, *bptr; - struct decorr_pass *dpp; - int tcount, m = 0; - - if (wps->sample_index + sample_count > wps->wphdr.block_index + wps->wphdr.block_samples) - sample_count = wps->wphdr.block_index + wps->wphdr.block_samples - wps->sample_index; - - if (wps->mute_error) { - if (wpc->reduced_channels == 1 || wpc->config.num_channels == 1 || (flags & MONO_FLAG)) - memset (buffer, 0, sample_count * 4); - else - memset (buffer, 0, sample_count * 8); - - wps->sample_index += sample_count; - return sample_count; - } - - if ((flags & HYBRID_FLAG) && !wps->block2buff) - mute_limit *= 2; - - //////////////// handle lossless or hybrid lossy mono data ///////////////// - - if (!wps->block2buff && (flags & MONO_DATA)) { - int32_t *eptr = buffer + sample_count; - - if (flags & HYBRID_FLAG) { - i = sample_count; - - for (bptr = buffer; bptr < eptr;) - if ((*bptr++ = get_word (wps, 0, NULL)) == WORD_EOF) { - i = (uint32_t)(bptr - buffer); - break; - } - } - else - i = get_words_lossless (wps, buffer, sample_count); - - for (bptr = buffer; bptr < eptr;) { - read_word = *bptr; - - for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount--; dpp++) { - int32_t sam, temp; - int k; - - if (dpp->term > MAX_TERM) { - if (dpp->term & 1) - sam = 2 * dpp->samples_A [0] - dpp->samples_A [1]; - else - sam = dpp->samples_A [0] + ((dpp->samples_A [0] - dpp->samples_A [1]) >> 1); - - dpp->samples_A [1] = dpp->samples_A [0]; - k = 0; - } - else { - sam = dpp->samples_A [m]; - k = (m + dpp->term) & (MAX_TERM - 1); - } - - temp = apply_weight (dpp->weight_A, sam) + read_word; - update_weight (dpp->weight_A, dpp->delta, sam, read_word); - dpp->samples_A [k] = read_word = temp; - } - - if (labs (read_word) > mute_limit) { - i = (uint32_t)(bptr - buffer); - break; - } - - m = (m + 1) & (MAX_TERM - 1); - crc += (crc << 1) + (*bptr++ = read_word); - } - } - - /////////////// handle lossless or hybrid lossy stereo data /////////////// - - else if (!wps->block2buff && !(flags & MONO_DATA)) { - int32_t *eptr = buffer + (sample_count * 2); - - if (flags & HYBRID_FLAG) { - i = sample_count; - - for (bptr = buffer; bptr < eptr; bptr += 2) - if ((bptr [0] = get_word (wps, 0, NULL)) == WORD_EOF || - (bptr [1] = get_word (wps, 1, NULL)) == WORD_EOF) { - i = (uint32_t)(bptr - buffer) / 2; - break; - } - } - else - i = get_words_lossless (wps, buffer, sample_count); - -#ifdef FAST_DECODE - for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount--; dpp++) - if (((flags & MAG_MASK) >> MAG_LSB) >= 16) - decorr_stereo_pass (dpp, buffer, sample_count); - else if (tcount && dpp [0].term == 17 && dpp [1].term == 17) { - decorr_stereo_pass_1717 (dpp, buffer, sample_count); - tcount--; - dpp++; - } - else if (tcount && dpp [0].term == 17 && dpp [1].term == 18) { - decorr_stereo_pass_1718 (dpp, buffer, sample_count); - tcount--; - dpp++; - } - else if (tcount && dpp [0].term == 18 && dpp [1].term == 18) { - decorr_stereo_pass_1818 (dpp, buffer, sample_count); - tcount--; - dpp++; - } - else if (tcount && dpp [0].term >= 1 && dpp [0].term <= 7 && - dpp [1].term >= 1 && dpp [1].term <= 7) { - decorr_stereo_pass_nn (dpp, buffer, sample_count); - tcount--; - dpp++; - } - else - decorr_stereo_pass_i (dpp, buffer, sample_count); -#else - for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount--; dpp++) - decorr_stereo_pass (dpp, buffer, sample_count); -#endif - - if (flags & JOINT_STEREO) - for (bptr = buffer; bptr < eptr; bptr += 2) { - bptr [0] += (bptr [1] -= (bptr [0] >> 1)); - crc += (crc << 3) + (bptr [0] << 1) + bptr [0] + bptr [1]; - } - else - for (bptr = buffer; bptr < eptr; bptr += 2) - crc += (crc << 3) + (bptr [0] << 1) + bptr [0] + bptr [1]; - - for (bptr = buffer; bptr < eptr; bptr += 16) - if (labs (bptr [0]) > mute_limit || labs (bptr [1]) > mute_limit) { - i = (uint32_t)(bptr - buffer) / 2; - break; - } - - m = sample_count & (MAX_TERM - 1); - } - - /////////////////// handle hybrid lossless mono data //////////////////// - - else if ((flags & HYBRID_FLAG) && (flags & MONO_DATA)) - for (bptr = buffer, i = 0; i < sample_count; ++i) { - - if ((read_word = get_word (wps, 0, correction)) == WORD_EOF) - break; - - for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount--; dpp++) { - int32_t sam, temp; - int k; - - if (dpp->term > MAX_TERM) { - if (dpp->term & 1) - sam = 2 * dpp->samples_A [0] - dpp->samples_A [1]; - else - sam = (3 * dpp->samples_A [0] - dpp->samples_A [1]) >> 1; - - dpp->samples_A [1] = dpp->samples_A [0]; - k = 0; - } - else { - sam = dpp->samples_A [m]; - k = (m + dpp->term) & (MAX_TERM - 1); - } - - temp = apply_weight (dpp->weight_A, sam) + read_word; - update_weight (dpp->weight_A, dpp->delta, sam, read_word); - dpp->samples_A [k] = read_word = temp; - } - - m = (m + 1) & (MAX_TERM - 1); - - if (flags & HYBRID_SHAPE) { - int shaping_weight = (wps->dc.shaping_acc [0] += wps->dc.shaping_delta [0]) >> 16; - int32_t temp = -apply_weight (shaping_weight, wps->dc.error [0]); - - if ((flags & NEW_SHAPING) && shaping_weight < 0 && temp) { - if (temp == wps->dc.error [0]) - temp = (temp < 0) ? temp + 1 : temp - 1; - - wps->dc.error [0] = temp - correction [0]; - } - else - wps->dc.error [0] = -correction [0]; - - read_word += correction [0] - temp; - } - else - read_word += correction [0]; - - crc += (crc << 1) + read_word; - -#ifdef LOSSY_MUTE - if (labs (read_word) > mute_limit) - break; -#endif - *bptr++ = read_word; - } - - //////////////////// handle hybrid lossless stereo data /////////////////// - - else if (wps->block2buff && !(flags & MONO_DATA)) - for (bptr = buffer, i = 0; i < sample_count; ++i) { - int32_t left, right, left2, right2; - int32_t left_c = 0, right_c = 0; - - if ((left = get_word (wps, 0, correction)) == WORD_EOF || - (right = get_word (wps, 1, correction + 1)) == WORD_EOF) - break; - - if (flags & CROSS_DECORR) { - left_c = left + correction [0]; - right_c = right + correction [1]; - - for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount--; dpp++) { - int32_t sam_A, sam_B; - - if (dpp->term > 0) { - if (dpp->term > MAX_TERM) { - if (dpp->term & 1) { - sam_A = 2 * dpp->samples_A [0] - dpp->samples_A [1]; - sam_B = 2 * dpp->samples_B [0] - dpp->samples_B [1]; - } - else { - sam_A = (3 * dpp->samples_A [0] - dpp->samples_A [1]) >> 1; - sam_B = (3 * dpp->samples_B [0] - dpp->samples_B [1]) >> 1; - } - } - else { - sam_A = dpp->samples_A [m]; - sam_B = dpp->samples_B [m]; - } - - left_c += apply_weight (dpp->weight_A, sam_A); - right_c += apply_weight (dpp->weight_B, sam_B); - } - else if (dpp->term == -1) { - left_c += apply_weight (dpp->weight_A, dpp->samples_A [0]); - right_c += apply_weight (dpp->weight_B, left_c); - } - else { - right_c += apply_weight (dpp->weight_B, dpp->samples_B [0]); - - if (dpp->term == -3) - left_c += apply_weight (dpp->weight_A, dpp->samples_A [0]); - else - left_c += apply_weight (dpp->weight_A, right_c); - } - } - - if (flags & JOINT_STEREO) - left_c += (right_c -= (left_c >> 1)); - } - - for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount--; dpp++) { - int32_t sam_A, sam_B; - - if (dpp->term > 0) { - int k; - - if (dpp->term > MAX_TERM) { - if (dpp->term & 1) { - sam_A = 2 * dpp->samples_A [0] - dpp->samples_A [1]; - sam_B = 2 * dpp->samples_B [0] - dpp->samples_B [1]; - } - else { - sam_A = (3 * dpp->samples_A [0] - dpp->samples_A [1]) >> 1; - sam_B = (3 * dpp->samples_B [0] - dpp->samples_B [1]) >> 1; - } - - dpp->samples_A [1] = dpp->samples_A [0]; - dpp->samples_B [1] = dpp->samples_B [0]; - k = 0; - } - else { - sam_A = dpp->samples_A [m]; - sam_B = dpp->samples_B [m]; - k = (m + dpp->term) & (MAX_TERM - 1); - } - - left2 = apply_weight (dpp->weight_A, sam_A) + left; - right2 = apply_weight (dpp->weight_B, sam_B) + right; - - update_weight (dpp->weight_A, dpp->delta, sam_A, left); - update_weight (dpp->weight_B, dpp->delta, sam_B, right); - - dpp->samples_A [k] = left = left2; - dpp->samples_B [k] = right = right2; - } - else if (dpp->term == -1) { - left2 = left + apply_weight (dpp->weight_A, dpp->samples_A [0]); - update_weight_clip (dpp->weight_A, dpp->delta, dpp->samples_A [0], left); - left = left2; - right2 = right + apply_weight (dpp->weight_B, left2); - update_weight_clip (dpp->weight_B, dpp->delta, left2, right); - dpp->samples_A [0] = right = right2; - } - else { - right2 = right + apply_weight (dpp->weight_B, dpp->samples_B [0]); - update_weight_clip (dpp->weight_B, dpp->delta, dpp->samples_B [0], right); - right = right2; - - if (dpp->term == -3) { - right2 = dpp->samples_A [0]; - dpp->samples_A [0] = right; - } - - left2 = left + apply_weight (dpp->weight_A, right2); - update_weight_clip (dpp->weight_A, dpp->delta, right2, left); - dpp->samples_B [0] = left = left2; - } - } - - m = (m + 1) & (MAX_TERM - 1); - - if (!(flags & CROSS_DECORR)) { - left_c = left + correction [0]; - right_c = right + correction [1]; - - if (flags & JOINT_STEREO) - left_c += (right_c -= (left_c >> 1)); - } - - if (flags & JOINT_STEREO) - left += (right -= (left >> 1)); - - if (flags & HYBRID_SHAPE) { - int shaping_weight; - int32_t temp; - - correction [0] = left_c - left; - shaping_weight = (wps->dc.shaping_acc [0] += wps->dc.shaping_delta [0]) >> 16; - temp = -apply_weight (shaping_weight, wps->dc.error [0]); - - if ((flags & NEW_SHAPING) && shaping_weight < 0 && temp) { - if (temp == wps->dc.error [0]) - temp = (temp < 0) ? temp + 1 : temp - 1; - - wps->dc.error [0] = temp - correction [0]; - } - else - wps->dc.error [0] = -correction [0]; - - left = left_c - temp; - correction [1] = right_c - right; - shaping_weight = (wps->dc.shaping_acc [1] += wps->dc.shaping_delta [1]) >> 16; - temp = -apply_weight (shaping_weight, wps->dc.error [1]); - - if ((flags & NEW_SHAPING) && shaping_weight < 0 && temp) { - if (temp == wps->dc.error [1]) - temp = (temp < 0) ? temp + 1 : temp - 1; - - wps->dc.error [1] = temp - correction [1]; - } - else - wps->dc.error [1] = -correction [1]; - - right = right_c - temp; - } - else { - left = left_c; - right = right_c; - } - -#ifdef LOSSY_MUTE - if (labs (left) > mute_limit || labs (right) > mute_limit) - break; -#endif - crc += (crc << 3) + (left << 1) + left + right; - *bptr++ = left; - *bptr++ = right; - } - else - i = 0; /* this line can't execute, but suppresses compiler warning */ - - if (i != sample_count) { - memset (buffer, 0, sample_count * (flags & MONO_FLAG ? 4 : 8)); - wps->mute_error = TRUE; - i = sample_count; - - if (bs_is_open (&wps->wvxbits)) - bs_close_read (&wps->wvxbits); - } - - if (m) - for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount--; dpp++) - if (dpp->term > 0 && dpp->term <= MAX_TERM) { - int32_t temp_A [MAX_TERM], temp_B [MAX_TERM]; - int k; - - memcpy (temp_A, dpp->samples_A, sizeof (dpp->samples_A)); - memcpy (temp_B, dpp->samples_B, sizeof (dpp->samples_B)); - - for (k = 0; k < MAX_TERM; k++) { - dpp->samples_A [k] = temp_A [m]; - dpp->samples_B [k] = temp_B [m]; - m = (m + 1) & (MAX_TERM - 1); - } - } - - fixup_samples (wpc, buffer, i); - - if ((flags & FLOAT_DATA) && (wpc->open_flags & OPEN_NORMALIZE)) - WavpackFloatNormalize (buffer, (flags & MONO_DATA) ? i : i * 2, - 127 - wps->float_norm_exp + wpc->norm_offset); - - if (flags & FALSE_STEREO) { - int32_t *dptr = buffer + i * 2; - int32_t *sptr = buffer + i; - int32_t c = i; - - while (c--) { - *--dptr = *--sptr; - *--dptr = *sptr; - } - } - - wps->sample_index += i; - wps->crc = crc; - - return i; -} - -// General function to perform stereo decorrelation pass on specified buffer -// (although since this is the reverse function it might technically be called -// "correlation" instead). This version handles all sample resolutions and -// weight deltas. The dpp->samples_X[] data is *not* returned normalized for -// term values 1-8, so it should be normalized if it is going to be used to -// call this function again. - -static void decorr_stereo_pass (struct decorr_pass *dpp, int32_t *buffer, int32_t sample_count) -{ - int32_t *bptr, *eptr = buffer + (sample_count * 2); - int m, k; - - switch (dpp->term) { - case 17: - for (bptr = buffer; bptr < eptr; bptr += 2) { - int32_t sam, tmp; - - sam = 2 * dpp->samples_A [0] - dpp->samples_A [1]; - dpp->samples_A [1] = dpp->samples_A [0]; - bptr [0] = dpp->samples_A [0] = apply_weight (dpp->weight_A, sam) + (tmp = bptr [0]); - update_weight (dpp->weight_A, dpp->delta, sam, tmp); - - sam = 2 * dpp->samples_B [0] - dpp->samples_B [1]; - dpp->samples_B [1] = dpp->samples_B [0]; - bptr [1] = dpp->samples_B [0] = apply_weight (dpp->weight_B, sam) + (tmp = bptr [1]); - update_weight (dpp->weight_B, dpp->delta, sam, tmp); - } - - break; - - case 18: - for (bptr = buffer; bptr < eptr; bptr += 2) { - int32_t sam, tmp; - - sam = dpp->samples_A [0] + ((dpp->samples_A [0] - dpp->samples_A [1]) >> 1); - dpp->samples_A [1] = dpp->samples_A [0]; - bptr [0] = dpp->samples_A [0] = apply_weight (dpp->weight_A, sam) + (tmp = bptr [0]); - update_weight (dpp->weight_A, dpp->delta, sam, tmp); - - sam = dpp->samples_B [0] + ((dpp->samples_B [0] - dpp->samples_B [1]) >> 1); - dpp->samples_B [1] = dpp->samples_B [0]; - bptr [1] = dpp->samples_B [0] = apply_weight (dpp->weight_B, sam) + (tmp = bptr [1]); - update_weight (dpp->weight_B, dpp->delta, sam, tmp); - } - - break; - - default: - for (m = 0, k = dpp->term & (MAX_TERM - 1), bptr = buffer; bptr < eptr; bptr += 2) { - int32_t sam; - - sam = dpp->samples_A [m]; - dpp->samples_A [k] = apply_weight (dpp->weight_A, sam) + bptr [0]; - update_weight (dpp->weight_A, dpp->delta, sam, bptr [0]); - bptr [0] = dpp->samples_A [k]; - - sam = dpp->samples_B [m]; - dpp->samples_B [k] = apply_weight (dpp->weight_B, sam) + bptr [1]; - update_weight (dpp->weight_B, dpp->delta, sam, bptr [1]); - bptr [1] = dpp->samples_B [k]; - - m = (m + 1) & (MAX_TERM - 1); - k = (k + 1) & (MAX_TERM - 1); - } - - break; - - case -1: - for (bptr = buffer; bptr < eptr; bptr += 2) { - int32_t sam; - - sam = bptr [0] + apply_weight (dpp->weight_A, dpp->samples_A [0]); - update_weight_clip (dpp->weight_A, dpp->delta, dpp->samples_A [0], bptr [0]); - bptr [0] = sam; - dpp->samples_A [0] = bptr [1] + apply_weight (dpp->weight_B, sam); - update_weight_clip (dpp->weight_B, dpp->delta, sam, bptr [1]); - bptr [1] = dpp->samples_A [0]; - } - - break; - - case -2: - for (bptr = buffer; bptr < eptr; bptr += 2) { - int32_t sam; - - sam = bptr [1] + apply_weight (dpp->weight_B, dpp->samples_B [0]); - update_weight_clip (dpp->weight_B, dpp->delta, dpp->samples_B [0], bptr [1]); - bptr [1] = sam; - dpp->samples_B [0] = bptr [0] + apply_weight (dpp->weight_A, sam); - update_weight_clip (dpp->weight_A, dpp->delta, sam, bptr [0]); - bptr [0] = dpp->samples_B [0]; - } - - break; - - case -3: - for (bptr = buffer; bptr < eptr; bptr += 2) { - int32_t sam_A, sam_B; - - sam_A = bptr [0] + apply_weight (dpp->weight_A, dpp->samples_A [0]); - update_weight_clip (dpp->weight_A, dpp->delta, dpp->samples_A [0], bptr [0]); - sam_B = bptr [1] + apply_weight (dpp->weight_B, dpp->samples_B [0]); - update_weight_clip (dpp->weight_B, dpp->delta, dpp->samples_B [0], bptr [1]); - bptr [0] = dpp->samples_B [0] = sam_A; - bptr [1] = dpp->samples_A [0] = sam_B; - } - - break; - } -} - -#ifdef FAST_DECODE - -// This function is a specialized version of decorr_stereo_pass() that works -// only with lower resolution data (<= 16-bit), but is otherwise identical. - -static void decorr_stereo_pass_i (struct decorr_pass *dpp, int32_t *buffer, int32_t sample_count) -{ - int32_t *bptr, *eptr = buffer + (sample_count * 2); - int m, k; - - switch (dpp->term) { - case 17: - for (bptr = buffer; bptr < eptr; bptr += 2) { - int32_t sam, tmp; - - sam = 2 * dpp->samples_A [0] - dpp->samples_A [1]; - dpp->samples_A [1] = dpp->samples_A [0]; - bptr [0] = dpp->samples_A [0] = apply_weight_i (dpp->weight_A, sam) + (tmp = bptr [0]); - update_weight (dpp->weight_A, dpp->delta, sam, tmp); - - sam = 2 * dpp->samples_B [0] - dpp->samples_B [1]; - dpp->samples_B [1] = dpp->samples_B [0]; - bptr [1] = dpp->samples_B [0] = apply_weight_i (dpp->weight_B, sam) + (tmp = bptr [1]); - update_weight (dpp->weight_B, dpp->delta, sam, tmp); - } - - break; - - case 18: - for (bptr = buffer; bptr < eptr; bptr += 2) { - int32_t sam, tmp; - - sam = dpp->samples_A [0] + ((dpp->samples_A [0] - dpp->samples_A [1]) >> 1); - dpp->samples_A [1] = dpp->samples_A [0]; - bptr [0] = dpp->samples_A [0] = apply_weight_i (dpp->weight_A, sam) + (tmp = bptr [0]); - update_weight (dpp->weight_A, dpp->delta, sam, tmp); - - sam = dpp->samples_B [0] + ((dpp->samples_B [0] - dpp->samples_B [1]) >> 1); - dpp->samples_B [1] = dpp->samples_B [0]; - bptr [1] = dpp->samples_B [0] = apply_weight_i (dpp->weight_B, sam) + (tmp = bptr [1]); - update_weight (dpp->weight_B, dpp->delta, sam, tmp); - } - - break; - - default: - for (m = 0, k = dpp->term & (MAX_TERM - 1), bptr = buffer; bptr < eptr; bptr += 2) { - int32_t sam; - - sam = dpp->samples_A [m]; - dpp->samples_A [k] = apply_weight_i (dpp->weight_A, sam) + bptr [0]; - update_weight (dpp->weight_A, dpp->delta, sam, bptr [0]); - bptr [0] = dpp->samples_A [k]; - - sam = dpp->samples_B [m]; - dpp->samples_B [k] = apply_weight_i (dpp->weight_B, sam) + bptr [1]; - update_weight (dpp->weight_B, dpp->delta, sam, bptr [1]); - bptr [1] = dpp->samples_B [k]; - - m = (m + 1) & (MAX_TERM - 1); - k = (k + 1) & (MAX_TERM - 1); - } - - break; - - case -1: - for (bptr = buffer; bptr < eptr; bptr += 2) { - int32_t sam; - - sam = bptr [0] + apply_weight_i (dpp->weight_A, dpp->samples_A [0]); - update_weight_clip (dpp->weight_A, dpp->delta, dpp->samples_A [0], bptr [0]); - bptr [0] = sam; - dpp->samples_A [0] = bptr [1] + apply_weight_i (dpp->weight_B, sam); - update_weight_clip (dpp->weight_B, dpp->delta, sam, bptr [1]); - bptr [1] = dpp->samples_A [0]; - } - - break; - - case -2: - for (bptr = buffer; bptr < eptr; bptr += 2) { - int32_t sam; - - sam = bptr [1] + apply_weight_i (dpp->weight_B, dpp->samples_B [0]); - update_weight_clip (dpp->weight_B, dpp->delta, dpp->samples_B [0], bptr [1]); - bptr [1] = sam; - dpp->samples_B [0] = bptr [0] + apply_weight_i (dpp->weight_A, sam); - update_weight_clip (dpp->weight_A, dpp->delta, sam, bptr [0]); - bptr [0] = dpp->samples_B [0]; - } - - break; - - case -3: - for (bptr = buffer; bptr < eptr; bptr += 2) { - int32_t sam_A, sam_B; - - sam_A = bptr [0] + apply_weight_i (dpp->weight_A, dpp->samples_A [0]); - update_weight_clip (dpp->weight_A, dpp->delta, dpp->samples_A [0], bptr [0]); - sam_B = bptr [1] + apply_weight_i (dpp->weight_B, dpp->samples_B [0]); - update_weight_clip (dpp->weight_B, dpp->delta, dpp->samples_B [0], bptr [1]); - bptr [0] = dpp->samples_B [0] = sam_A; - bptr [1] = dpp->samples_A [0] = sam_B; - } - - break; - } -} - -// These functions are specialized versions of decorr_stereo_pass() that work -// only with lower resolution data (<= 16-bit) and handle the equivalent of -// *two* decorrelation passes. By combining two passes we save a read and write -// of the sample data and some overhead dealing with buffer pointers and looping. -// -// The cases handled are: -// 17,17 -- standard "fast" mode before version 4.40 -// 17,18 -- standard "fast" mode starting with 4.40 -// 18,18 -- used in the default and higher modes -// [1-7],[1-7] -- common in "high" and "very high" modes - -static void decorr_stereo_pass_1718 (struct decorr_pass *dpp, int32_t *buffer, int32_t sample_count) -{ - int32_t *bptr, *eptr = buffer + (sample_count * 2); - - for (bptr = buffer; bptr < eptr; bptr += 2) { - int32_t sam; - - sam = 2 * dpp->samples_A [0] - dpp->samples_A [1]; - dpp->samples_A [1] = dpp->samples_A [0]; - dpp->samples_A [0] = apply_weight_i (dpp->weight_A, sam) + bptr [0]; - update_weight (dpp->weight_A, dpp->delta, sam, bptr [0]); - - sam = (dpp+1)->samples_A [0] + (((dpp+1)->samples_A [0] - (dpp+1)->samples_A [1]) >> 1); - (dpp+1)->samples_A [1] = (dpp+1)->samples_A [0]; - bptr [0] = (dpp+1)->samples_A [0] = apply_weight_i ((dpp+1)->weight_A, sam) + dpp->samples_A [0]; - update_weight ((dpp+1)->weight_A, (dpp+1)->delta, sam, dpp->samples_A [0]); - - sam = 2 * dpp->samples_B [0] - dpp->samples_B [1]; - dpp->samples_B [1] = dpp->samples_B [0]; - dpp->samples_B [0] = apply_weight_i (dpp->weight_B, sam) + bptr [1]; - update_weight (dpp->weight_B, dpp->delta, sam, bptr [1]); - - sam = (dpp+1)->samples_B [0] + (((dpp+1)->samples_B [0] - (dpp+1)->samples_B [1]) >> 1); - (dpp+1)->samples_B [1] = (dpp+1)->samples_B [0]; - bptr [1] = (dpp+1)->samples_B [0] = apply_weight_i ((dpp+1)->weight_B, sam) + dpp->samples_B [0]; - update_weight ((dpp+1)->weight_B, (dpp+1)->delta, sam, dpp->samples_B [0]); - } -} - -static void decorr_stereo_pass_1717 (struct decorr_pass *dpp, int32_t *buffer, int32_t sample_count) -{ - int32_t *bptr, *eptr = buffer + (sample_count * 2); - - for (bptr = buffer; bptr < eptr; bptr += 2) { - int32_t sam; - - sam = 2 * dpp->samples_A [0] - dpp->samples_A [1]; - dpp->samples_A [1] = dpp->samples_A [0]; - dpp->samples_A [0] = apply_weight_i (dpp->weight_A, sam) + bptr [0]; - update_weight (dpp->weight_A, dpp->delta, sam, bptr [0]); - - sam = 2 * (dpp+1)->samples_A [0] - (dpp+1)->samples_A [1]; - (dpp+1)->samples_A [1] = (dpp+1)->samples_A [0]; - bptr [0] = (dpp+1)->samples_A [0] = apply_weight_i ((dpp+1)->weight_A, sam) + dpp->samples_A [0]; - update_weight ((dpp+1)->weight_A, (dpp+1)->delta, sam, dpp->samples_A [0]); - - sam = 2 * dpp->samples_B [0] - dpp->samples_B [1]; - dpp->samples_B [1] = dpp->samples_B [0]; - dpp->samples_B [0] = apply_weight_i (dpp->weight_B, sam) + bptr [1]; - update_weight (dpp->weight_B, dpp->delta, sam, bptr [1]); - - sam = 2 * (dpp+1)->samples_B [0] - (dpp+1)->samples_B [1]; - (dpp+1)->samples_B [1] = (dpp+1)->samples_B [0]; - bptr [1] = (dpp+1)->samples_B [0] = apply_weight_i ((dpp+1)->weight_B, sam) + dpp->samples_B [0]; - update_weight ((dpp+1)->weight_B, (dpp+1)->delta, sam, dpp->samples_B [0]); - } -} - -static void decorr_stereo_pass_1818 (struct decorr_pass *dpp, int32_t *buffer, int32_t sample_count) -{ - int32_t *bptr, *eptr = buffer + (sample_count * 2); - - for (bptr = buffer; bptr < eptr; bptr += 2) { - int32_t sam; - - sam = dpp->samples_A [0] + ((dpp->samples_A [0] - dpp->samples_A [1]) >> 1); - dpp->samples_A [1] = dpp->samples_A [0]; - dpp->samples_A [0] = apply_weight_i (dpp->weight_A, sam) + bptr [0]; - update_weight (dpp->weight_A, dpp->delta, sam, bptr [0]); - - sam = (dpp+1)->samples_A [0] + (((dpp+1)->samples_A [0] - (dpp+1)->samples_A [1]) >> 1); - (dpp+1)->samples_A [1] = (dpp+1)->samples_A [0]; - bptr [0] = (dpp+1)->samples_A [0] = apply_weight_i ((dpp+1)->weight_A, sam) + dpp->samples_A [0]; - update_weight ((dpp+1)->weight_A, (dpp+1)->delta, sam, dpp->samples_A [0]); - - sam = dpp->samples_B [0] + ((dpp->samples_B [0] - dpp->samples_B [1]) >> 1); - dpp->samples_B [1] = dpp->samples_B [0]; - dpp->samples_B [0] = apply_weight_i (dpp->weight_B, sam) + bptr [1]; - update_weight (dpp->weight_B, dpp->delta, sam, bptr [1]); - - sam = (dpp+1)->samples_B [0] + (((dpp+1)->samples_B [0] - (dpp+1)->samples_B [1]) >> 1); - (dpp+1)->samples_B [1] = (dpp+1)->samples_B [0]; - bptr [1] = (dpp+1)->samples_B [0] = apply_weight_i ((dpp+1)->weight_B, sam) + dpp->samples_B [0]; - update_weight ((dpp+1)->weight_B, (dpp+1)->delta, sam, dpp->samples_B [0]); - } -} - -static void decorr_stereo_pass_nn (struct decorr_pass *dpp, int32_t *buffer, int32_t sample_count) -{ - int32_t *bptr, *eptr = buffer + (sample_count * 2); - int m, k, j; - - m = 0; - k = dpp->term & (MAX_TERM - 1); - j = (dpp+1)->term & (MAX_TERM - 1); - - for (bptr = buffer; bptr < eptr; bptr += 2) { - int32_t tmp; - - dpp->samples_A [k] = apply_weight_i (dpp->weight_A, dpp->samples_A [m]) + (tmp = bptr [0]); - update_weight (dpp->weight_A, dpp->delta, dpp->samples_A [m], tmp); - - bptr [0] = (dpp+1)->samples_A [j] = apply_weight_i ((dpp+1)->weight_A, (dpp+1)->samples_A [m]) + (tmp = dpp->samples_A [k]); - update_weight ((dpp+1)->weight_A, (dpp+1)->delta, (dpp+1)->samples_A [m], tmp); - - dpp->samples_B [k] = apply_weight_i (dpp->weight_B, dpp->samples_B [m]) + (tmp = bptr [1]); - update_weight (dpp->weight_B, dpp->delta, dpp->samples_B [m], tmp); - - bptr [1] = (dpp+1)->samples_B [j] = apply_weight_i ((dpp+1)->weight_B, (dpp+1)->samples_B [m]) + (tmp = dpp->samples_B [k]); - update_weight ((dpp+1)->weight_B, (dpp+1)->delta, (dpp+1)->samples_B [m], tmp); - - m = (m + 1) & (MAX_TERM - 1); - k = (k + 1) & (MAX_TERM - 1); - j = (j + 1) & (MAX_TERM - 1); - } -} - -#endif - -// This is a helper function for unpack_samples() that applies several final -// operations. First, if the data is 32-bit float data, then that conversion -// is done in the float.c module (whether lossy or lossless) and we return. -// Otherwise, if the extended integer data applies, then that operation is -// executed first. If the unpacked data is lossy (and not corrected) then -// it is clipped and shifted in a single operation. Otherwise, if it's -// lossless then the last step is to apply the final shift (if any). - -static void fixup_samples (WavpackContext *wpc, int32_t *buffer, uint32_t sample_count) -{ - WavpackStream *wps = wpc->streams [wpc->current_stream]; - uint32_t flags = wps->wphdr.flags; - int lossy_flag = (flags & HYBRID_FLAG) && !wps->block2buff; - int shift = (flags & SHIFT_MASK) >> SHIFT_LSB; - - if (flags & FLOAT_DATA) { - float_values (wps, buffer, (flags & MONO_DATA) ? sample_count : sample_count * 2); - return; - } - - if (flags & INT32_DATA) { - uint32_t count = (flags & MONO_DATA) ? sample_count : sample_count * 2; - int sent_bits = wps->int32_sent_bits, zeros = wps->int32_zeros; - int ones = wps->int32_ones, dups = wps->int32_dups; - uint32_t data, mask = (1 << sent_bits) - 1; - int32_t *dptr = buffer; - - if (bs_is_open (&wps->wvxbits)) { - uint32_t crc = wps->crc_x; - - while (count--) { -// if (sent_bits) { - getbits (&data, sent_bits, &wps->wvxbits); - *dptr = (*dptr << sent_bits) | (data & mask); -// } - - if (zeros) - *dptr <<= zeros; - else if (ones) - *dptr = ((*dptr + 1) << ones) - 1; - else if (dups) - *dptr = ((*dptr + (*dptr & 1)) << dups) - (*dptr & 1); - - crc = crc * 9 + (*dptr & 0xffff) * 3 + ((*dptr >> 16) & 0xffff); - dptr++; - } - - wps->crc_x = crc; - } - else if (!sent_bits && (zeros + ones + dups)) { - while (lossy_flag && (flags & BYTES_STORED) == 3 && shift < 8) { - if (zeros) - zeros--; - else if (ones) - ones--; - else if (dups) - dups--; - else - break; - - shift++; - } - - while (count--) { - if (zeros) - *dptr <<= zeros; - else if (ones) - *dptr = ((*dptr + 1) << ones) - 1; - else if (dups) - *dptr = ((*dptr + (*dptr & 1)) << dups) - (*dptr & 1); - - dptr++; - } - } - else - shift += zeros + sent_bits + ones + dups; - } - - if (lossy_flag) { - int32_t min_value, max_value, min_shifted, max_shifted; - - switch (flags & BYTES_STORED) { - case 0: - min_shifted = (min_value = -128 >> shift) << shift; - max_shifted = (max_value = 127 >> shift) << shift; - break; - - case 1: - min_shifted = (min_value = -32768 >> shift) << shift; - max_shifted = (max_value = 32767 >> shift) << shift; - break; - - case 2: - min_shifted = (min_value = -8388608 >> shift) << shift; - max_shifted = (max_value = 8388607 >> shift) << shift; - break; - - case 3: default: /* "default" suppresses compiler warning */ - min_shifted = (min_value = (int32_t) 0x80000000 >> shift) << shift; - max_shifted = (max_value = (int32_t) 0x7fffffff >> shift) << shift; - break; - } - - if (!(flags & MONO_DATA)) - sample_count *= 2; - - while (sample_count--) { - if (*buffer < min_value) - *buffer++ = min_shifted; - else if (*buffer > max_value) - *buffer++ = max_shifted; - else - *buffer++ <<= shift; - } - } - else if (shift) { - if (!(flags & MONO_DATA)) - sample_count *= 2; - - while (sample_count--) - *buffer++ <<= shift; - } -} - -// This function checks the crc value(s) for an unpacked block, returning the -// number of actual crc errors detected for the block. The block must be -// completely unpacked before this test is valid. For losslessly unpacked -// blocks of float or extended integer data the extended crc is also checked. -// Note that WavPack's crc is not a CCITT approved polynomial algorithm, but -// is a much simpler method that is virtually as robust for real world data. - -int check_crc_error (WavpackContext *wpc) -{ - int result = 0, stream; - - for (stream = 0; stream < wpc->num_streams; stream++) { - WavpackStream *wps = wpc->streams [stream]; - - if (wps->crc != wps->wphdr.crc) - ++result; - else if (bs_is_open (&wps->wvxbits) && wps->crc_x != wps->crc_wvx) - ++result; - } - - return result; -} - -#endif diff --git a/wavpack-4.5.0/src/unpack3.c b/wavpack-4.5.0/src/unpack3.c deleted file mode 100644 index 8308e9b..0000000 --- a/wavpack-4.5.0/src/unpack3.c +++ /dev/null @@ -1,2195 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// **** WAVPACK **** // -// Hybrid Lossless Wavefile Compressor // -// Copyright (c) 1998 - 2006 Conifer Software. // -// All Rights Reserved. // -// Distributed under the BSD Software License (see license.txt) // -//////////////////////////////////////////////////////////////////////////// - -// unpack3.c - -// This module provides unpacking for WavPack files prior to version 4.0, -// not including "raw" files. As these modes are all obsolete and are no -// longer written, this code will not be fully documented other than the -// global functions. However, full documenation is provided in the version -// 3.97 source code. - -#include -#include -#include -#include - -#include "wavpack_local.h" -#include "unpack3.h" - -#define ATTEMPT_ERROR_MUTING - -#ifdef DEBUG_ALLOC -#define malloc malloc_db -#define realloc realloc_db -#define free free_db -void *malloc_db (uint32_t size); -void *realloc_db (void *ptr, uint32_t size); -void free_db (void *ptr); -int32_t dump_alloc (void); -#endif - -static void unpack_init3 (WavpackStream3 *wps); -static int bs_open_read3 (Bitstream3 *bs, WavpackStreamReader *reader, void *id); -static void bs_close_read3 (Bitstream3 *bs); -#ifndef NO_SEEKING -static void bs_restore3 (Bitstream3 *bs); -#endif - -// This provides an extension to the WavpackOpenFileRead () function contained -// in the wputils.c module. It is assumed that an 'R' had been read as the -// first character of the file/stream (indicating a non-raw pre version 4.0 -// WavPack file) and had been pushed back onto the stream (or simply seeked -// back to). - -WavpackContext *open_file3 (WavpackContext *wpc, char *error) -{ - RiffChunkHeader RiffChunkHeader; - ChunkHeader ChunkHeader; - WavpackHeader3 wphdr; - WavpackStream3 *wps; - WaveHeader3 wavhdr; - - CLEAR (wavhdr); - wpc->stream3 = wps = (WavpackStream3 *) malloc (sizeof (WavpackStream3)); - CLEAR (*wps); - - if (wpc->reader->read_bytes (wpc->wv_in, &RiffChunkHeader, sizeof (RiffChunkHeader)) != - sizeof (RiffChunkHeader)) { - strcpy (error, "not a valid WavPack file!"); - return WavpackCloseFile (wpc); - } - - if (!strncmp (RiffChunkHeader.ckID, "RIFF", 4) && !strncmp (RiffChunkHeader.formType, "WAVE", 4)) { - - if (wpc->open_flags & OPEN_WRAPPER) { - wpc->wrapper_data = malloc (wpc->wrapper_bytes = sizeof (RiffChunkHeader)); - memcpy (wpc->wrapper_data, &RiffChunkHeader, sizeof (RiffChunkHeader)); - } - - // If the first chunk is a wave RIFF header, then read the various chunks - // until we get to the "data" chunk (and WavPack header should follow). If - // the first chunk is not a RIFF, then we assume a "raw" WavPack file and - // the WavPack header must be first. - - while (1) { - - if (wpc->reader->read_bytes (wpc->wv_in, &ChunkHeader, sizeof (ChunkHeader)) != - sizeof (ChunkHeader)) { - strcpy (error, "not a valid WavPack file!"); - return WavpackCloseFile (wpc); - } - else { - if (wpc->open_flags & OPEN_WRAPPER) { - wpc->wrapper_data = realloc (wpc->wrapper_data, wpc->wrapper_bytes + sizeof (ChunkHeader)); - memcpy (wpc->wrapper_data + wpc->wrapper_bytes, &ChunkHeader, sizeof (ChunkHeader)); - wpc->wrapper_bytes += sizeof (ChunkHeader); - } - - little_endian_to_native (&ChunkHeader, ChunkHeaderFormat); - - if (!strncmp (ChunkHeader.ckID, "fmt ", 4)) { - - if (ChunkHeader.ckSize < sizeof (wavhdr) || - wpc->reader->read_bytes (wpc->wv_in, &wavhdr, sizeof (wavhdr)) != sizeof (wavhdr)) { - strcpy (error, "not a valid WavPack file!"); - return WavpackCloseFile (wpc); - } - else if (wpc->open_flags & OPEN_WRAPPER) { - wpc->wrapper_data = realloc (wpc->wrapper_data, wpc->wrapper_bytes + sizeof (wavhdr)); - memcpy (wpc->wrapper_data + wpc->wrapper_bytes, &wavhdr, sizeof (wavhdr)); - wpc->wrapper_bytes += sizeof (wavhdr); - } - - little_endian_to_native (&wavhdr, WaveHeader3Format); - - if (ChunkHeader.ckSize > sizeof (wavhdr)) { - uint32_t bytes_to_skip = (ChunkHeader.ckSize + 1 - sizeof (wavhdr)) & ~1L; - - if (bytes_to_skip > 1024 * 1024) { - strcpy (error, "not a valid WavPack file!"); - return WavpackCloseFile (wpc); - } - - if (wpc->open_flags & OPEN_WRAPPER) { - wpc->wrapper_data = realloc (wpc->wrapper_data, wpc->wrapper_bytes + bytes_to_skip); - wpc->reader->read_bytes (wpc->wv_in, wpc->wrapper_data + wpc->wrapper_bytes, bytes_to_skip); - wpc->wrapper_bytes += bytes_to_skip; - } - else { - uchar *temp = malloc (bytes_to_skip); - wpc->reader->read_bytes (wpc->wv_in, temp, bytes_to_skip); - free (temp); - } - } - } - else if (!strncmp (ChunkHeader.ckID, "data", 4)) - break; - else if ((ChunkHeader.ckSize + 1) & ~1L) { - uint32_t bytes_to_skip = (ChunkHeader.ckSize + 1) & ~1L; - - if (bytes_to_skip > 1024 * 1024) { - strcpy (error, "not a valid WavPack file!"); - return WavpackCloseFile (wpc); - } - - if (wpc->open_flags & OPEN_WRAPPER) { - wpc->wrapper_data = realloc (wpc->wrapper_data, wpc->wrapper_bytes + bytes_to_skip); - wpc->reader->read_bytes (wpc->wv_in, wpc->wrapper_data + wpc->wrapper_bytes, bytes_to_skip); - wpc->wrapper_bytes += bytes_to_skip; - } - else { - uchar *temp = malloc (bytes_to_skip); - wpc->reader->read_bytes (wpc->wv_in, temp, bytes_to_skip); - free (temp); - } - } - } - } - } - else { - strcpy (error, "not a valid WavPack file!"); - return WavpackCloseFile (wpc); - } - - if (wavhdr.FormatTag != 1 || !wavhdr.NumChannels || wavhdr.NumChannels > 2 || - !wavhdr.SampleRate || wavhdr.BitsPerSample < 16 || wavhdr.BitsPerSample > 24 || - wavhdr.BlockAlign / wavhdr.NumChannels > 3 || wavhdr.BlockAlign % wavhdr.NumChannels || - wavhdr.BlockAlign / wavhdr.NumChannels < (wavhdr.BitsPerSample + 7) / 8) { - strcpy (error, "not a valid WavPack file!"); - return WavpackCloseFile (wpc); - } - - wpc->total_samples = ChunkHeader.ckSize / wavhdr.NumChannels / - ((wavhdr.BitsPerSample > 16) ? 3 : 2); - - if (wpc->reader->read_bytes (wpc->wv_in, &wphdr, 10) != 10) { - strcpy (error, "not a valid WavPack file!"); - return WavpackCloseFile (wpc); - } - - if (((char *) &wphdr) [8] == 2 && (wpc->reader->read_bytes (wpc->wv_in, ((char *) &wphdr) + 10, 2) != 2)) { - strcpy (error, "not a valid WavPack file!"); - return WavpackCloseFile (wpc); - } - else if (((char *) &wphdr) [8] == 3 && (wpc->reader->read_bytes (wpc->wv_in, ((char *) &wphdr) + 10, - sizeof (wphdr) - 10) != sizeof (wphdr) - 10)) { - strcpy (error, "not a valid WavPack file!"); - return WavpackCloseFile (wpc); - } - - little_endian_to_native (&wphdr, WavpackHeader3Format); - - // make sure this is a version we know about - - if (strncmp (wphdr.ckID, "wvpk", 4) || wphdr.version < 1 || wphdr.version > 3) { - strcpy (error, "not a valid WavPack file!"); - return WavpackCloseFile (wpc); - } - - // Because I ran out of flag bits in the WavPack header, an amazingly ugly - // kludge was forced upon me! This code takes care of preparing the flags - // field for internal use and checking for unknown formats we can't decode - - if (wphdr.version == 3) { - - if (wphdr.flags & EXTREME_DECORR) { - - if ((wphdr.flags & NOT_STORED_FLAGS) || - ((wphdr.bits) && - (((wphdr.flags & NEW_HIGH_FLAG) && - (wphdr.flags & (FAST_FLAG | HIGH_FLAG))) || - (wphdr.flags & CROSS_DECORR)))) { - strcpy (error, "not a valid WavPack file!"); - return WavpackCloseFile (wpc); - } - - if (wphdr.flags & CANCEL_EXTREME) - wphdr.flags &= ~(EXTREME_DECORR | CANCEL_EXTREME); - } - else - wphdr.flags &= ~CROSS_DECORR; - } - - // check to see if we should look for a "correction" file, and if so try - // to open it for reading, then set WVC_FLAG accordingly - - if (wpc->wvc_in && wphdr.version == 3 && wphdr.bits && (wphdr.flags & NEW_HIGH_FLAG)) { - wpc->file2len = wpc->reader->get_length (wpc->wvc_in); - wphdr.flags |= WVC_FLAG; - wpc->wvc_flag = TRUE; - } - else - wphdr.flags &= ~WVC_FLAG; - - // check WavPack version to handle special requirements of versions - // before 3.0 that had smaller headers - - if (wphdr.version < 3) { - wphdr.total_samples = wpc->total_samples; - wphdr.flags = wavhdr.NumChannels == 1 ? MONO_FLAG : 0; - wphdr.shift = 16 - wavhdr.BitsPerSample; - - if (wphdr.version == 1) - wphdr.bits = 0; - } - - wpc->config.sample_rate = wavhdr.SampleRate; - wpc->config.num_channels = wavhdr.NumChannels; - wpc->config.channel_mask = 5 - wavhdr.NumChannels; - - if (wphdr.flags & MONO_FLAG) - wpc->config.flags |= CONFIG_MONO_FLAG; - - if (wphdr.flags & EXTREME_DECORR) - wpc->config.flags |= CONFIG_HIGH_FLAG; - - if (wphdr.bits) { - if (wphdr.flags & NEW_HIGH_FLAG) - wpc->config.flags |= CONFIG_HYBRID_FLAG; - else - wpc->config.flags |= CONFIG_LOSSY_MODE; - } - else if (!(wphdr.flags & HIGH_FLAG)) - wpc->config.flags |= CONFIG_FAST_FLAG; - - wpc->config.bytes_per_sample = (wphdr.flags & BYTES_3) ? 3 : 2; - wpc->config.bits_per_sample = wavhdr.BitsPerSample; - - memcpy (&wps->wphdr, &wphdr, sizeof (wphdr)); - wps->wvbits.bufsiz = wps->wvcbits.bufsiz = 1024 * 1024; - return wpc; -} - -// return currently decoded sample index - -uint32_t get_sample_index3 (WavpackContext *wpc) -{ - WavpackStream3 *wps = (WavpackStream3 *) wpc->stream3; - - return (wps) ? wps->sample_index : (uint32_t) -1; -} - -int get_version3 (WavpackContext *wpc) -{ - WavpackStream3 *wps = (WavpackStream3 *) wpc->stream3; - - return (wps) ? wps->wphdr.version : 0; -} - -void free_stream3 (WavpackContext *wpc) -{ - WavpackStream3 *wps = (WavpackStream3 *) wpc->stream3; - - if (wps) { -#ifndef NO_SEEKING - if (wps->unpack_data) - free (wps->unpack_data); -#endif - if (wps->wphdr.flags & WVC_FLAG) - bs_close_read3 (&wps->wvcbits); - - bs_close_read3 (&wps->wvbits); - - free (wps); - } -} - -static void bs_read3 (Bitstream3 *bs) -{ - uint32_t bytes_read; - - bytes_read = bs->reader->read_bytes (bs->id, bs->buf, bs->bufsiz); - bs->end = bs->buf + bytes_read; - bs->fpos += bytes_read; - - if (bs->end == bs->buf) { - memset (bs->buf, -1, bs->bufsiz); - bs->end += bs->bufsiz; - } - - bs->ptr = bs->buf; -} - -// Open the specified BitStream and associate with the specified file. The -// "bufsiz" field of the structure must be preset with the desired buffer -// size and the file's read pointer must be set to where the desired bit -// data is located. A return value of TRUE indicates an error in -// allocating buffer space. - -static int bs_open_read3 (Bitstream3 *bs, WavpackStreamReader *reader, void *id) -{ - bs->fpos = (bs->reader = reader)->get_pos (bs->id = id); - - if (!bs->buf) - bs->buf = (uchar *) malloc (bs->bufsiz); - - bs->end = bs->buf + bs->bufsiz; - bs->ptr = bs->end - 1; - bs->sr = bs->bc = 0; - bs->error = bs->buf ? 0 : 1; - bs->wrap = bs_read3; - return bs->error; -} - -#ifndef NO_SEEKING - -// This function is called after a call to unpack_restore() has restored -// the BitStream structure to a previous state and causes any required data -// to be read from the file. This function is NOT supported for overlapped -// operation. - -static void bs_restore3 (Bitstream3 *bs) -{ - uint32_t bytes_to_read = (uint32_t)(bs->end - bs->ptr - 1), bytes_read; - - bs->reader->set_pos_abs (bs->id, bs->fpos - bytes_to_read); - - if (bytes_to_read > 0) { - - bytes_read = bs->reader->read_bytes (bs->id, bs->ptr + 1, bytes_to_read); - - if (bytes_to_read != bytes_read) - bs->end = bs->ptr + 1 + bytes_read; - } -} - -#endif - -// This function is called to release any resources used by the BitStream -// and position the file pointer to the first byte past the read bits. - -static void bs_close_read3 (Bitstream3 *bs) -{ - if (bs->buf) { - free (bs->buf); - CLEAR (*bs); - } -} - -static uint32_t bs_unused_bytes (Bitstream3 *bs) -{ - if (bs->bc < 8) { - bs->bc += 8; - bs->ptr++; - } - - return (uint32_t)(bs->end - bs->ptr); -} - -static uchar *bs_unused_data (Bitstream3 *bs) -{ - if (bs->bc < 8) { - bs->bc += 8; - bs->ptr++; - } - - return bs->ptr; -} - -#ifndef NO_UNPACK - -//////////////////////////////// local macros ///////////////////////////////// - -#define apply_weight_n(bits, weight, sample) ((weight * sample + (1 << (bits - 1))) >> bits) - -#define update_weight_n(bits, weight, source, result) \ - if (source && result) { \ - if ((source ^ result) >= 0) { if (weight++ == (1 << bits)) weight--; } \ - else if (weight-- == min_weight) weight++; \ - } - -#define apply_weight24(weight, sample) (((((sample & 0xffff) * weight) >> 7) + \ - (((sample & ~0xffff) >> 7) * weight) + 1) >> 1) - -#define update_weight2(weight, source, result) \ - if (source && result) { \ - if ((source ^ result) >= 0) { if (weight++ == 256) weight--; } \ - else if (weight-- == min_weight) weight++; \ - } - -//////////////////////////////// local tables /////////////////////////////// - -// These three tables specify the characteristics of the decorrelation filters. -// Each term represents one layer of the sequential filter, where positive -// values indicate the relative sample involved from the same channel (1=prev) -// while -1 and -2 indicate cross channel decorrelation (in stereo only). The -// "simple_terms" table is no longer used for writing, but is kept for older -// file decoding. - -static const signed char extreme_terms [] = { 1,1,1,2,4,-1,1,2,3,6,-2,8,5,7,4,1,2,3 }; -static const signed char default_terms [] = { 1,1,1,-1,2,1,-2 }; -static const signed char simple_terms [] = { 1,1,1,1 }; - -// This function initializes everything required to unpack WavPack -// bitstreams and must be called before any unpacking is performed. Note -// that the (WavpackHeader3 *) in the WavpackStream3 struct must be valid. - -static void init_words3 (WavpackStream3 *wps); - -static void unpack_init3 (WavpackStream3 *wps) -{ - int flags = wps->wphdr.flags; - struct decorr_pass *dpp; - int ti; - - CLEAR (wps->decorr_passes); - CLEAR (wps->dc); - - if (flags & EXTREME_DECORR) { - for (dpp = wps->decorr_passes, ti = 0; ti < sizeof (extreme_terms); ti++) - if (extreme_terms [sizeof (extreme_terms) - ti - 1] > 0 || (flags & CROSS_DECORR)) - dpp++->term = extreme_terms [sizeof (extreme_terms) - ti - 1]; - } - else if (flags & NEW_DECORR_FLAG) { - for (dpp = wps->decorr_passes, ti = 0; ti < sizeof (default_terms); ti++) - if (default_terms [sizeof (default_terms) - ti - 1] > 0 || (flags & CROSS_DECORR)) - dpp++->term = default_terms [sizeof (default_terms) - ti - 1]; - } - else - for (dpp = wps->decorr_passes, ti = 0; ti < sizeof (simple_terms); ti++) - dpp++->term = simple_terms [sizeof (simple_terms) - ti - 1]; - - wps->num_terms = (int)(dpp - wps->decorr_passes); - init_words3 (wps); -} - -#ifndef NO_SEEKING - -#define SAVE(destin, item) { memcpy (destin, &item, sizeof (item)); destin = (char *) destin + sizeof (item); } -#define RESTORE(item, source) { memcpy (&item, source, sizeof (item)); source = (char *) source + sizeof (item); } - -// This function returns the size (in bytes) required to save the unpacking -// context. Note that the (WavpackHeader3 *) in the WavpackStream3 struct -// must be valid. - -static int unpack_size (WavpackStream3 *wps) -{ - int flags = wps->wphdr.flags, byte_sum = 0, tcount; - struct decorr_pass *dpp; - - byte_sum += sizeof (wps->wvbits); - - if (flags & WVC_FLAG) - byte_sum += sizeof (wps->wvcbits); - - if (wps->wphdr.version == 3) { - if (wps->wphdr.bits) - byte_sum += sizeof (wps->w4); - else - byte_sum += sizeof (wps->w1); - - byte_sum += sizeof (wps->w3) + sizeof (wps->dc.crc); - } - else - byte_sum += sizeof (wps->w2); - - if (wps->wphdr.bits) - byte_sum += sizeof (wps->dc.error); - else - byte_sum += sizeof (wps->dc.sum_level) + sizeof (wps->dc.left_level) + - sizeof (wps->dc.right_level) + sizeof (wps->dc.diff_level); - - if (flags & OVER_20) - byte_sum += sizeof (wps->dc.last_extra_bits) + sizeof (wps->dc.extra_bits_count); - - if (!(flags & EXTREME_DECORR)) { - byte_sum += sizeof (wps->dc.sample); - byte_sum += sizeof (wps->dc.weight); - } - - if (flags & (HIGH_FLAG | NEW_HIGH_FLAG)) - for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount--; dpp++) - if (dpp->term > 0) { - byte_sum += sizeof (dpp->samples_A [0]) * dpp->term; - byte_sum += sizeof (dpp->weight_A); - - if (!(flags & MONO_FLAG)) { - byte_sum += sizeof (dpp->samples_B [0]) * dpp->term; - byte_sum += sizeof (dpp->weight_B); - } - } - else { - byte_sum += sizeof (dpp->samples_A [0]) + sizeof (dpp->samples_B [0]); - byte_sum += sizeof (dpp->weight_A) + sizeof (dpp->weight_B); - } - - return byte_sum; -} - -// This function saves the unpacking context at the specified pointer and -// returns the updated pointer. The actual amount of data required can be -// determined beforehand by calling unpack_size() but must be allocated by -// the caller. - -static void *unpack_save (WavpackStream3 *wps, void *destin) -{ - int flags = wps->wphdr.flags, tcount; - struct decorr_pass *dpp; - - SAVE (destin, wps->wvbits); - - if (flags & WVC_FLAG) - SAVE (destin, wps->wvcbits); - - if (wps->wphdr.version == 3) { - if (wps->wphdr.bits) { - SAVE (destin, wps->w4); - } - else { - SAVE (destin, wps->w1); - } - - SAVE (destin, wps->w3); - SAVE (destin, wps->dc.crc); - } - else - SAVE (destin, wps->w2); - - if (wps->wphdr.bits) { - SAVE (destin, wps->dc.error); - } - else { - SAVE (destin, wps->dc.sum_level); - SAVE (destin, wps->dc.left_level); - SAVE (destin, wps->dc.right_level); - SAVE (destin, wps->dc.diff_level); - } - - if (flags & OVER_20) { - SAVE (destin, wps->dc.last_extra_bits); - SAVE (destin, wps->dc.extra_bits_count); - } - - if (!(flags & EXTREME_DECORR)) { - SAVE (destin, wps->dc.sample); - SAVE (destin, wps->dc.weight); - } - - if (flags & (HIGH_FLAG | NEW_HIGH_FLAG)) - for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount--; dpp++) - if (dpp->term > 0) { - int count = dpp->term; - int index = wps->dc.m; - - SAVE (destin, dpp->weight_A); - - while (count--) { - SAVE (destin, dpp->samples_A [index]); - index = (index + 1) & (MAX_TERM - 1); - } - - if (!(flags & MONO_FLAG)) { - count = dpp->term; - index = wps->dc.m; - - SAVE (destin, dpp->weight_B); - - while (count--) { - SAVE (destin, dpp->samples_B [index]); - index = (index + 1) & (MAX_TERM - 1); - } - } - } - else { - SAVE (destin, dpp->weight_A); - SAVE (destin, dpp->weight_B); - SAVE (destin, dpp->samples_A [0]); - SAVE (destin, dpp->samples_B [0]); - } - - return destin; -} - -// This function restores the unpacking context from the specified pointer -// and returns the updated pointer. After this call, unpack_samples() will -// continue where it left off immediately before unpack_save() was called. -// If the WavPack files and bitstreams might have been closed and reopened, -// then the "keep_resources" flag should be set to avoid using the "old" -// resources that were originally saved (and are probably now invalid). - -static void *unpack_restore (WavpackStream3 *wps, void *source, int keep_resources) -{ - int flags = wps->wphdr.flags, tcount; - struct decorr_pass *dpp; - FILE *temp_file; - uchar *temp_buf; - - unpack_init3 (wps); - temp_file = wps->wvbits.id; - temp_buf = wps->wvbits.buf; - RESTORE (wps->wvbits, source); - - if (keep_resources) { - wps->wvbits.id = temp_file; - wps->wvbits.ptr += temp_buf - wps->wvbits.buf; - wps->wvbits.end += temp_buf - wps->wvbits.buf; - wps->wvbits.buf = temp_buf; - } - - bs_restore3 (&wps->wvbits); - - if (flags & WVC_FLAG) { - temp_file = wps->wvcbits.id; - temp_buf = wps->wvcbits.buf; - RESTORE (wps->wvcbits, source); - - if (keep_resources) { - wps->wvcbits.id = temp_file; - wps->wvcbits.ptr += temp_buf - wps->wvcbits.buf; - wps->wvcbits.end += temp_buf - wps->wvcbits.buf; - wps->wvcbits.buf = temp_buf; - } - - bs_restore3 (&wps->wvcbits); - } - - if (wps->wphdr.version == 3) { - if (wps->wphdr.bits) { - RESTORE (wps->w4, source); - } - else { - RESTORE (wps->w1, source); - } - - RESTORE (wps->w3, source); - RESTORE (wps->dc.crc, source); - } - else - RESTORE (wps->w2, source); - - if (wps->wphdr.bits) { - RESTORE (wps->dc.error, source); - } - else { - RESTORE (wps->dc.sum_level, source); - RESTORE (wps->dc.left_level, source); - RESTORE (wps->dc.right_level, source); - RESTORE (wps->dc.diff_level, source); - } - - if (flags & OVER_20) { - RESTORE (wps->dc.last_extra_bits, source); - RESTORE (wps->dc.extra_bits_count, source); - } - - if (!(flags & EXTREME_DECORR)) { - RESTORE (wps->dc.sample, source); - RESTORE (wps->dc.weight, source); - } - - if (flags & (HIGH_FLAG | NEW_HIGH_FLAG)) - for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount--; dpp++) - if (dpp->term > 0) { - int count = dpp->term; - int index = wps->dc.m; - - RESTORE (dpp->weight_A, source); - - while (count--) { - RESTORE (dpp->samples_A [index], source); - index = (index + 1) & (MAX_TERM - 1); - } - - if (!(flags & MONO_FLAG)) { - count = dpp->term; - index = wps->dc.m; - - RESTORE (dpp->weight_B, source); - - while (count--) { - RESTORE (dpp->samples_B [index], source); - index = (index + 1) & (MAX_TERM - 1); - } - } - } - else { - RESTORE (dpp->weight_A, source); - RESTORE (dpp->weight_B, source); - RESTORE (dpp->samples_A [0], source); - RESTORE (dpp->samples_B [0], source); - } - - return source; -} - -// This is an extension for WavpackSeekSample (). Note that because WavPack -// files created prior to version 4.0 are not inherently seekable, this -// function could take a long time if a forward seek is requested to an -// area that has not been played (or seeked through) yet. - - -int seek_sample3 (WavpackContext *wpc, uint32_t desired_index) -{ - int points_index = desired_index / ((wpc->total_samples >> 8) + 1); - WavpackStream3 *wps = (WavpackStream3 *) wpc->stream3; - - if (desired_index >= wpc->total_samples) - return FALSE; - - while (points_index) - if (wps->index_points [points_index].saved && - wps->index_points [points_index].sample_index <= desired_index) - break; - else - points_index--; - - if (wps->index_points [points_index].saved) - if (wps->index_points [points_index].sample_index > wps->sample_index || - wps->sample_index > desired_index) { - wps->sample_index = wps->index_points [points_index].sample_index; - unpack_restore (wps, wps->unpack_data + points_index * wps->unpack_size, TRUE); - } - - if (desired_index > wps->sample_index) { - int32_t *buffer = (int32_t *) malloc (1024 * (wps->wphdr.flags & MONO_FLAG ? 4 : 8)); - uint32_t samples_to_skip = desired_index - wps->sample_index; - - while (1) { - if (samples_to_skip > 1024) { - if (unpack_samples3 (wpc, buffer, 1024) == 1024) - samples_to_skip -= 1024; - else - break; - } - else { - samples_to_skip -= unpack_samples3 (wpc, buffer, samples_to_skip); - break; - } - } - - free (buffer); - - if (samples_to_skip) - return FALSE; - } - - return TRUE; -} - - -#endif - -// This monster actually unpacks the WavPack bitstream(s) into the specified -// buffer as longs, and serves as an extension to WavpackUnpackSamples(). -// Note that WavPack files created prior to version 4.0 could only contain 16 -// or 24 bit values, and these values are right-justified in the 32-bit values. -// So, if the original file contained 16-bit values, then the range of the -// returned longs would be +/- 32K. For maximum clarity, the function is -// broken up into segments that handle various modes. This makes for a few -// extra infrequent flag checks, but makes the code easier to follow because -// the nesting does not become so deep. For maximum efficiency, the conversion -// is isolated to tight loops that handle an entire buffer. - -static int32_t FASTCALL get_word1 (WavpackStream3 *wps, int chan); -static int32_t FASTCALL get_old_word1 (WavpackStream3 *wps, int chan); -static int32_t FASTCALL get_word2 (WavpackStream3 *wps, int chan); -static int32_t FASTCALL get_word3 (WavpackStream3 *wps, int chan); -static int32_t FASTCALL get_word4 (WavpackStream3 *wps, int chan, int32_t *correction); - -int32_t unpack_samples3 (WavpackContext *wpc, int32_t *buffer, uint32_t sample_count) -{ - WavpackStream3 *wps = (WavpackStream3 *) wpc->stream3; - int shift = wps->wphdr.shift, flags = wps->wphdr.flags, min_weight = 0, m = wps->dc.m, tcount; -#ifndef NO_SEEKING - int points_index = wps->sample_index / ((wpc->total_samples >> 8) + 1); -#endif - int32_t min_value, max_value, min_shifted, max_shifted; - int32_t correction [2], crc = wps->dc.crc; - struct decorr_pass *dpp; - int32_t read_word, *bptr; - int32_t sample [2] [2]; - int weight [2] [1]; - uint i; - -#ifdef ATTEMPT_ERROR_MUTING - int32_t mute_limit = (flags & BYTES_3) ? 8388608 : 32768; - int mute_block = 0; - - if (wps->wphdr.bits && !(flags & WVC_FLAG)) { - if (wps->wphdr.version < 3) - mute_limit *= 4; - else - mute_limit *= 2; - } -#endif - - if (wps->sample_index + sample_count > wpc->total_samples) - sample_count = wpc->total_samples - wps->sample_index; - - if (!sample_count) - return 0; - - if (!wps->sample_index) { - unpack_init3 (wps); - - bs_open_read3 (&wps->wvbits, wpc->reader, wpc->wv_in); - - if (wpc->wvc_flag) - bs_open_read3 (&wps->wvcbits, wpc->reader, wpc->wvc_in); - } - -#ifndef NO_SEEKING - if (!wps->index_points [points_index].saved) { - - if (!wps->unpack_data) - wps->unpack_data = (uchar *) malloc (256 * (wps->unpack_size = unpack_size (wps))); - - wps->index_points [points_index].sample_index = wps->sample_index; - unpack_save (wps, wps->unpack_data + points_index * wps->unpack_size); - wps->index_points [points_index].saved = TRUE; - } -#endif - - memcpy (sample, wps->dc.sample, sizeof (sample)); - memcpy (weight, wps->dc.weight, sizeof (weight)); - - if (wps->wphdr.bits) { - if (flags & (NEW_DECORR_FLAG | EXTREME_DECORR)) - min_weight = -256; - } - else - if (flags & NEW_DECORR_FLAG) - min_weight = (flags & EXTREME_DECORR) ? -512 : -256; - - if (flags & BYTES_3) { - min_shifted = (min_value = -8388608 >> shift) << shift; - max_shifted = (max_value = 8388607 >> shift) << shift; - } - else { - min_shifted = (min_value = -32768 >> shift) << shift; - max_shifted = (max_value = 32767 >> shift) << shift; - } - - ///////////////// handle version 3 lossless mono data ///////////////////// - - if (wps->wphdr.version == 3 && !wps->wphdr.bits && (flags & MONO_FLAG)) { - if (flags & FAST_FLAG) { - if (flags & OVER_20) - for (bptr = buffer, i = 0; i < sample_count; ++i) { - int32_t temp; - - if ((read_word = get_word3 (wps, 0)) == WORD_EOF) - break; - - sample [0] [0] += sample [0] [1] += read_word; - getbits (&temp, 4, &wps->wvbits); - crc = crc * 3 + (temp = (temp & 0xf) + (sample [0] [0] << 4)); - *bptr++ = temp; - } - else - for (bptr = buffer, i = 0; i < sample_count; ++i) { - if ((read_word = get_word3 (wps, 0)) == WORD_EOF) - break; - - crc = crc * 3 + (sample [0] [0] += sample [0] [1] += read_word); - *bptr++ = sample [0] [0] << shift; - } - } - else if (flags & HIGH_FLAG) - for (bptr = buffer, i = 0; i < sample_count; ++i) { - int32_t temp; - - if (flags & NEW_HIGH_FLAG) { - if ((read_word = get_word1 (wps, 0)) == WORD_EOF) - break; - } - else { - if ((read_word = get_old_word1 (wps, 0)) == WORD_EOF) - break; - } - - if (flags & EXTREME_DECORR) - for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount--; dpp++) { - int32_t sam = dpp->samples_A [m]; - - temp = apply_weight_n (9, dpp->weight_A, sam) + read_word; - update_weight_n (9, dpp->weight_A, sam, read_word); - dpp->samples_A [(m + dpp->term) & (MAX_TERM - 1)] = read_word = temp; - } - else - for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount--; dpp++) { - int32_t sam = dpp->samples_A [m]; - - temp = apply_weight_n (8, dpp->weight_A, sam) + read_word; - update_weight_n (8, dpp->weight_A, sam, read_word); - dpp->samples_A [(m + dpp->term) & (MAX_TERM - 1)] = read_word = temp; - } - - m = (m + 1) & (MAX_TERM - 1); - - if (flags & OVER_20) { - if (wps->dc.extra_bits_count < 8 || !getbit (&wps->wvbits)) { - getbits (&temp, 4, &wps->wvbits); - - if ((temp &= 0xf) != wps->dc.last_extra_bits) { - wps->dc.last_extra_bits = temp; - wps->dc.extra_bits_count = 0; - } - else - ++wps->dc.extra_bits_count; - } - - crc = crc * 3 + (temp = wps->dc.last_extra_bits + (read_word << 4)); - *bptr++ = temp; - } - else { - crc = crc * 3 + read_word; - *bptr++ = read_word << shift; - } - } - else - for (bptr = buffer, i = 0; i < sample_count; ++i) { - - int32_t temp; - - if ((read_word = get_word3 (wps, 0)) == WORD_EOF) - break; - - temp = sample [0] [0] + ((sample [0] [1] * weight [0] [0] + 128) >> 8) + read_word; - - if ((sample [0] [1] >= 0) == (read_word > 0)) { - if (weight [0] [0]++ == 256) - weight [0] [0]--; - } - else if (weight [0] [0]-- == 0) - weight [0] [0]++; - - sample [0] [0] += (sample [0] [1] = temp - sample [0] [0]); - - if (flags & OVER_20) { - if (wps->dc.extra_bits_count < 8 || !getbit (&wps->wvbits)) { - getbits (&temp, 4, &wps->wvbits); - - if ((temp &= 0xf) != wps->dc.last_extra_bits) { - wps->dc.last_extra_bits = temp; - wps->dc.extra_bits_count = 0; - } - else - ++wps->dc.extra_bits_count; - } - - crc = crc * 3 + (*bptr++ = temp = wps->dc.last_extra_bits + (sample [0] [0] << 4)); - } - else { - crc = crc * 3 + sample [0] [0]; - *bptr++ = sample [0] [0] << shift; - } - } - } - - //////////////// handle version 3 lossless stereo data //////////////////// - - else if (wps->wphdr.version == 3 && !wps->wphdr.bits && !(flags & MONO_FLAG)) { - int32_t left_level = wps->dc.left_level, right_level = wps->dc.right_level; - int32_t sum_level = wps->dc.sum_level, diff_level = wps->dc.diff_level; - - if (flags & FAST_FLAG) { - if (flags & OVER_20) - for (bptr = buffer, i = 0; i < sample_count; ++i) { - int32_t sum, diff, temp; - - read_word = get_word3 (wps, 0); - - if (read_word == WORD_EOF) - break; - - sum = (read_word << 1) | ((diff = get_word3 (wps, 1)) & 1); - sample [0] [0] += sample [0] [1] += ((sum + diff) >> 1); - sample [1] [0] += sample [1] [1] += ((sum - diff) >> 1); - getbits (&temp, 8, &wps->wvbits); - crc = crc * 3 + (*bptr++ = (sample [0] [0] << 4) + ((temp >> 4) & 0xf)); - crc = crc * 3 + (*bptr++ = (sample [1] [0] << 4) + (temp & 0xf)); - } - else - for (bptr = buffer, i = 0; i < sample_count; ++i) { - int32_t sum, diff; - - read_word = get_word3 (wps, 0); - - if (read_word == WORD_EOF) - break; - - sum = (read_word << 1) | ((diff = get_word3 (wps, 1)) & 1); - sample [0] [1] += ((sum + diff) >> 1); - sample [1] [1] += ((sum - diff) >> 1); - crc = crc * 3 + (sample [0] [0] += sample [0] [1]); - crc = crc * 3 + (sample [1] [0] += sample [1] [1]); - *bptr++ = sample [0] [0] << shift; - *bptr++ = sample [1] [0] << shift; - } - } - else if (flags & HIGH_FLAG) { - for (bptr = buffer, i = 0; i < sample_count; ++i) { - int32_t sum, left, right, diff, left2, right2, extra_bits, next_word; - - if (flags & CROSS_DECORR) { - left = get_word1 (wps, 0); - - if (left == WORD_EOF) - break; - - right = get_word1 (wps, 1); - } - else { - if (flags & NEW_HIGH_FLAG) { - read_word = get_word1 (wps, 0); - - if (read_word == WORD_EOF) - break; - - next_word = get_word1 (wps, 1); - - if (right_level > left_level) { - if (left_level + right_level < sum_level + diff_level && right_level < diff_level) { - sum = (right = read_word) + (left = next_word); - diff = left - right; - } - else { - diff = read_word; - - if (sum_level < left_level) { - sum = (next_word << 1) | (diff & 1); - left = (sum + diff) >> 1; - right = (sum - diff) >> 1; - } - else - sum = next_word + (right = (left = next_word) - diff); - } - } - else { - if (left_level + right_level < sum_level + diff_level && left_level < diff_level) { - sum = (left = read_word) + (right = next_word); - diff = left - right; - } - else { - diff = read_word; - - if (sum_level < right_level) { - sum = (next_word << 1) | (diff & 1); - left = (sum + diff) >> 1; - right = (sum - diff) >> 1; - } - else - sum = (left = diff + (right = next_word)) + next_word; - } - } - } - else { - read_word = get_old_word1 (wps, 0); - - if (read_word == WORD_EOF) - break; - - next_word = get_old_word1 (wps, 1); - - if (sum_level <= right_level && sum_level <= left_level) { - sum = (next_word << 1) | (read_word & 1); - left = (sum + read_word) >> 1; - right = (sum - read_word) >> 1; - } - else if (left_level <= right_level) - sum = next_word + (right = (left = next_word) - read_word); - else - sum = next_word + (left = read_word + (right = next_word)); - - diff = left - right; - } - - sum_level = sum_level - (sum_level >> 8) + labs (sum >> 1); - left_level = left_level - (left_level >> 8) + labs (left); - right_level = right_level - (right_level >> 8) + labs (right); - diff_level = diff_level - (diff_level >> 8) + labs (diff); - - if (flags & JOINT_STEREO) { - left = diff; - right = sum >> 1; - } - } - - if (flags & EXTREME_DECORR) { - for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount--; dpp++) - if (dpp->term > 0) { - int32_t sam_A = dpp->samples_A [m], sam_B = dpp->samples_B [m]; - int k = (m + dpp->term) & (MAX_TERM - 1); - - left2 = apply_weight_n (9, dpp->weight_A, sam_A) + left; - right2 = apply_weight_n (9, dpp->weight_B, sam_B) + right; - - update_weight_n (9, dpp->weight_A, sam_A, left); - update_weight_n (9, dpp->weight_B, sam_B, right); - - dpp->samples_A [k] = left = left2; - dpp->samples_B [k] = right = right2; - } - else if (dpp->term == -1) { - left2 = left + apply_weight_n (9, dpp->weight_A, dpp->samples_A [0]); - update_weight_n (9, dpp->weight_A, dpp->samples_A [0], left); - left = left2; - right2 = right + apply_weight_n (9, dpp->weight_B, left); - update_weight_n (9, dpp->weight_B, left, right); - dpp->samples_A [0] = right = right2; - } - else { - right2 = right + apply_weight_n (9, dpp->weight_A, dpp->samples_A [0]); - update_weight_n (9, dpp->weight_A, dpp->samples_A [0], right); - right = right2; - left2 = left + apply_weight_n (9, dpp->weight_B, right); - update_weight_n (9, dpp->weight_B, right, left); - dpp->samples_A [0] = left = left2; - } - } - else { - for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount--; dpp++) - if (dpp->term > 0) { - int32_t sam_A = dpp->samples_A [m], sam_B = dpp->samples_B [m]; - int k = (m + dpp->term) & (MAX_TERM - 1); - - left2 = apply_weight_n (8, dpp->weight_A, sam_A) + left; - right2 = apply_weight_n (8, dpp->weight_B, sam_B) + right; - - update_weight_n (8, dpp->weight_A, sam_A, left); - update_weight_n (8, dpp->weight_B, sam_B, right); - - dpp->samples_A [k] = left = left2; - dpp->samples_B [k] = right = right2; - } - else if (dpp->term == -1) { - left2 = left + apply_weight_n (8, dpp->weight_A, dpp->samples_A [0]); - update_weight_n (8, dpp->weight_A, dpp->samples_A [0], left); - left = left2; - right2 = right + apply_weight_n (8, dpp->weight_B, left); - update_weight_n (8, dpp->weight_B, left, right); - dpp->samples_A [0] = right = right2; - } - else { - right2 = right + apply_weight_n (8, dpp->weight_A, dpp->samples_A [0]); - update_weight_n (8, dpp->weight_A, dpp->samples_A [0], right); - right = right2; - left2 = left + apply_weight_n (8, dpp->weight_B, right); - update_weight_n (8, dpp->weight_B, right, left); - dpp->samples_A [0] = left = left2; - } - } - - m = (m + 1) & (MAX_TERM - 1); - - if (flags & JOINT_STEREO) { - sum = (right << 1) | ((diff = left) & 1); - right = (sum - diff) >> 1; - left = (sum + diff) >> 1; - } - - if (flags & OVER_20) { - if (wps->dc.extra_bits_count < 8 || !getbit (&wps->wvbits)) { - getbits (&extra_bits, 8, &wps->wvbits); - - if ((extra_bits &= 0xff) != wps->dc.last_extra_bits) { - wps->dc.last_extra_bits = extra_bits; - wps->dc.extra_bits_count = 0; - } - else - ++wps->dc.extra_bits_count; - } - - crc = crc * 3 + (*bptr++ = left = (left << 4) + (wps->dc.last_extra_bits >> 4)); - crc = crc * 3 + (*bptr++ = right = (right << 4) + (wps->dc.last_extra_bits & 0xf)); - } - else { - crc = crc * 9 + left * 3 + right; - *bptr++ = left << shift; - *bptr++ = right << shift; - } - } - } - else - for (bptr = buffer, i = 0; i < sample_count; ++i) { - int32_t sum, left, right, left2, right2, extra_bits; - - read_word = get_word3 (wps, 0); - - if (read_word == WORD_EOF) - break; - - if (sum_level <= right_level && sum_level <= left_level) { - sum = (get_word3 (wps, 1) << 1) | (read_word & 1); - left = (sum + read_word) >> 1; - right = (sum - read_word) >> 1; - } - else if (left_level <= right_level) { - right = (left = get_word3 (wps, 1)) - read_word; - sum = left + right; - } - else { - left = read_word + (right = get_word3 (wps, 1)); - sum = right + left; - } - - sum_level = sum_level - (sum_level >> 8) + labs (sum >> 1); - left_level = left_level - (left_level >> 8) + labs (left); - right_level = right_level - (right_level >> 8) + labs (right); - - left2 = sample [0] [0] + ((sample [0] [1] * weight [0] [0] + 128) >> 8) + left; - right2 = sample [1] [0] + ((sample [1] [1] * weight [1] [0] + 128) >> 8) + right; - - if ((sample [0] [1] >= 0) == (left > 0)) { - if (weight [0] [0]++ == 256) - weight [0] [0]--; - } - else if (weight [0] [0]-- == 0) - weight [0] [0]++; - - if ((sample [1] [1] >= 0) == (right > 0)) { - if (weight [1] [0]++ == 256) - weight [1] [0]--; - } - else if (weight [1] [0]-- == 0) - weight [1] [0]++; - - sample [0] [0] += (sample [0] [1] = left2 - sample [0] [0]); - sample [1] [0] += (sample [1] [1] = right2 - sample [1] [0]); - - if (flags & OVER_20) { - if (wps->dc.extra_bits_count < 8 || !getbit (&wps->wvbits)) { - getbits (&extra_bits, 8, &wps->wvbits); - - if ((extra_bits &= 0xff) != wps->dc.last_extra_bits) { - wps->dc.last_extra_bits = extra_bits; - wps->dc.extra_bits_count = 0; - } - else - ++wps->dc.extra_bits_count; - } - - crc = crc * 3 + (*bptr++ = left2 = (sample [0] [0] << 4) + (wps->dc.last_extra_bits >> 4)); - crc = crc * 3 + (*bptr++ = right2 = (sample [1] [0] << 4) + (wps->dc.last_extra_bits & 0xf)); - } - else { - crc = crc * 9 + sample [0] [0] * 3 + sample [1] [0]; - *bptr++ = sample [0] [0] << shift; - *bptr++ = sample [1] [0] << shift; - } - } - - wps->dc.left_level = left_level; - wps->dc.right_level = right_level; - wps->dc.sum_level = sum_level; - wps->dc.diff_level = diff_level; - } - - //////////////// handle version 3 lossy/hybrid mono data ////////////////// - - else if (wps->wphdr.version == 3 && wps->wphdr.bits && (flags & MONO_FLAG)) { - if (flags & FAST_FLAG) - for (bptr = buffer, i = 0; i < sample_count; ++i) { - - if ((read_word = get_word3 (wps, 0)) == WORD_EOF) - break; - - crc = crc * 3 + (sample [0] [0] += sample [0] [1] += read_word); - - if (sample [0] [0] < min_value) { -#ifdef ATTEMPT_ERROR_MUTING - if (sample [0] [0] < -mute_limit) - mute_block = 1; -#endif - *bptr++ = min_shifted; - } - else if (sample [0] [0] > max_value) { -#ifdef ATTEMPT_ERROR_MUTING - if (sample [0] [0] > mute_limit) - mute_block = 1; -#endif - *bptr++ = max_shifted; - } - else - *bptr++ = sample [0] [0] << shift; - } - else if (flags & (HIGH_FLAG | NEW_HIGH_FLAG)) - for (bptr = buffer, i = 0; i < sample_count; ++i) { - int32_t temp; - - read_word = (flags & NEW_HIGH_FLAG) ? - get_word4 (wps, 0, correction) : get_word3 (wps, 0); - - if (read_word == WORD_EOF) - break; - - for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount--; dpp++) { - int32_t sam = dpp->samples_A [m]; - - temp = apply_weight24 (dpp->weight_A, sam) + read_word; - update_weight2 (dpp->weight_A, sam, read_word); - dpp->samples_A [(m + dpp->term) & (MAX_TERM - 1)] = read_word = temp; - } - - m = (m + 1) & (MAX_TERM - 1); - - if (flags & WVC_FLAG) { - if (flags & LOSSY_SHAPE) { - crc = crc * 3 + (read_word += correction [0] + wps->dc.error [0]); - wps->dc.error [0] = -correction [0]; - } - else - crc = crc * 3 + (read_word += correction [0]); - - *bptr++ = read_word << shift; - } - else { - crc = crc * 3 + read_word; - - if (read_word < min_value) { -#ifdef ATTEMPT_ERROR_MUTING - if (read_word < -mute_limit) - mute_block = 1; -#endif - *bptr++ = min_shifted; - } - else if (read_word > max_value) { -#ifdef ATTEMPT_ERROR_MUTING - if (read_word > mute_limit) - mute_block = 1; -#endif - *bptr++ = max_shifted; - } - else - *bptr++ = read_word << shift; - } - } - else - for (bptr = buffer, i = 0; i < sample_count; ++i) { - int32_t new_sample; - - if ((read_word = get_word3 (wps, 0)) == WORD_EOF) - break; - - new_sample = sample [0] [0] + ((sample [0] [1] * weight [0] [0] + 128) >> 8) + read_word; - - if ((sample [0] [1] >= 0) == (read_word > 0)) { - if (weight [0] [0]++ == 256) - weight [0] [0]--; - } - else if (weight [0] [0]-- == 0) - weight [0] [0]++; - - sample [0] [1] = new_sample - sample [0] [0]; - crc = crc * 3 + (sample [0] [0] = new_sample); - - if (sample [0] [0] < min_value) { -#ifdef ATTEMPT_ERROR_MUTING - if (sample [0] [0] < -mute_limit) - mute_block = 1; -#endif - *bptr++ = min_shifted; - } - else if (sample [0] [0] > max_value) { -#ifdef ATTEMPT_ERROR_MUTING - if (sample [0] [0] > mute_limit) - mute_block = 1; -#endif - *bptr++ = max_shifted; - } - else - *bptr++ = sample [0] [0] << shift; - } - } - - //////////////// handle version 3 lossy/hybrid stereo data //////////////// - - else if (wps->wphdr.version == 3 && wps->wphdr.bits && !(flags & MONO_FLAG)) { - if (flags & FAST_FLAG) - for (bptr = buffer, i = 0; i < sample_count; ++i) { - - if ((read_word = get_word3 (wps, 0)) == WORD_EOF) - break; - - crc = crc * 3 + (sample [0] [0] += sample [0] [1] += read_word); - - if (sample [0] [0] < min_value) { -#ifdef ATTEMPT_ERROR_MUTING - if (sample [0] [0] < -mute_limit) - mute_block = 1; -#endif - *bptr++ = min_shifted; - } - else if (sample [0] [0] > max_value) { -#ifdef ATTEMPT_ERROR_MUTING - if (sample [0] [0] > mute_limit) - mute_block = 1; -#endif - *bptr++ = max_shifted; - } - else - *bptr++ = sample [0] [0] << shift; - - crc = crc * 3 + (sample [1] [0] += sample [1] [1] += get_word3 (wps, 1)); - - if (sample [1] [0] < min_value) { -#ifdef ATTEMPT_ERROR_MUTING - if (sample [1] [0] < -mute_limit) - mute_block = 1; -#endif - *bptr++ = min_shifted; - } - else if (sample [1] [0] > max_value) { -#ifdef ATTEMPT_ERROR_MUTING - if (sample [1] [0] > mute_limit) - mute_block = 1; -#endif - *bptr++ = max_shifted; - } - else - *bptr++ = sample [1] [0] << shift; - } - else if (flags & (HIGH_FLAG | NEW_HIGH_FLAG)) - for (bptr = buffer, i = 0; i < sample_count; ++i) { - int32_t left, right, left2, right2, sum, diff; - - if (flags & NEW_HIGH_FLAG) { - left = get_word4 (wps, 0, correction); - right = get_word4 (wps, 1, correction + 1); - } - else { - left = get_word3 (wps, 0); - right = get_word3 (wps, 1); - } - - if (left == WORD_EOF) - break; - - for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount--; dpp++) { - int32_t sam_A = dpp->samples_A [m], sam_B = dpp->samples_B [m]; - int k = (m + dpp->term) & (MAX_TERM - 1); - - left2 = apply_weight24 (dpp->weight_A, sam_A) + left; - update_weight2 (dpp->weight_A, sam_A, left); - dpp->samples_A [k] = left = left2; - - right2 = apply_weight24 (dpp->weight_B, sam_B) + right; - update_weight2 (dpp->weight_B, sam_B, right); - dpp->samples_B [k] = right = right2; - } - - m = (m + 1) & (MAX_TERM - 1); - - if (flags & WVC_FLAG) { - if (flags & LOSSY_SHAPE) { - left += correction [0] + wps->dc.error [0]; - right += correction [1] + wps->dc.error [1]; - wps->dc.error [0] = -correction [0]; - wps->dc.error [1] = -correction [1]; - } - else { - left += correction [0]; - right += correction [1]; - } - } - - if (flags & JOINT_STEREO) { - right = ((sum = (right << 1) | (left & 1)) - (diff = left)) >> 1; - left = (sum + diff) >> 1; - } - - crc = crc * 9 + left * 3 + right; - - if (flags & WVC_FLAG) { - *bptr++ = left << shift; - *bptr++ = right << shift; - } - else { - if (left < min_value) { -#ifdef ATTEMPT_ERROR_MUTING - if (left < -mute_limit) - mute_block = 1; -#endif - *bptr++ = min_shifted; - } - else if (left > max_value) { -#ifdef ATTEMPT_ERROR_MUTING - if (left > mute_limit) - mute_block = 1; -#endif - *bptr++ = max_shifted; - } - else - *bptr++ = left << shift; - - if (right < min_value) { -#ifdef ATTEMPT_ERROR_MUTING - if (right < -mute_limit) - mute_block = 1; -#endif - *bptr++ = min_shifted; - } - else if (right > max_value) { -#ifdef ATTEMPT_ERROR_MUTING - if (right > mute_limit) - mute_block = 1; -#endif - *bptr++ = max_shifted; - } - else - *bptr++ = right << shift; - } - } - else - for (bptr = buffer, i = 0; i < sample_count; ++i) { - int32_t new_sample; - - if ((read_word = get_word3 (wps, 0)) == WORD_EOF) - break; - - new_sample = sample [0] [0] + ((sample [0] [1] * weight [0] [0] + 128) >> 8) + read_word; - - if ((sample [0] [1] >= 0) == (read_word > 0)) { - if (weight [0] [0]++ == 256) - weight [0] [0]--; - } - else if (weight [0] [0]-- == 0) - weight [0] [0]++; - - sample [0] [1] = new_sample - sample [0] [0]; - crc = crc * 3 + (sample [0] [0] = new_sample); - - read_word = get_word3 (wps, 1); - new_sample = sample [1] [0] + ((sample [1] [1] * weight [1] [0] + 128) >> 8) + read_word; - - if ((sample [1] [1] >= 0) == (read_word > 0)) { - if (weight [1] [0]++ == 256) - weight [1] [0]--; - } - else if (weight [1] [0]-- == 0) - weight [1] [0]++; - - sample [1] [1] = new_sample - sample [1] [0]; - crc = crc * 3 + (sample [1] [0] = new_sample); - - if (sample [0] [0] < min_value) { -#ifdef ATTEMPT_ERROR_MUTING - if (sample [0] [0] < -mute_limit) - mute_block = 1; -#endif - *bptr++ = min_shifted; - } - else if (sample [0] [0] > max_value) { -#ifdef ATTEMPT_ERROR_MUTING - if (sample [0] [0] > mute_limit) - mute_block = 1; -#endif - *bptr++ = max_shifted; - } - else - *bptr++ = sample [0] [0] << shift; - - if (sample [1] [0] < min_value) { -#ifdef ATTEMPT_ERROR_MUTING - if (sample [1] [0] < -mute_limit) - mute_block = 1; -#endif - *bptr++ = min_shifted; - } - else if (sample [1] [0] > max_value) { -#ifdef ATTEMPT_ERROR_MUTING - if (sample [1] [0] > mute_limit) - mute_block = 1; -#endif - *bptr++ = max_shifted; - } - else - *bptr++ = sample [1] [0] << shift; - } - } - - //////////////////// finally, handle version 2 data /////////////////////// - - else if (wps->wphdr.version == 2 && (flags & MONO_FLAG)) - for (bptr = buffer, i = 0; i < sample_count; ++i) { - if ((read_word = get_word2 (wps, 0)) == WORD_EOF) - break; - - sample [0] [0] += sample [0] [1] += read_word; - - if (wps->wphdr.bits) { - if (sample [0] [0] < min_value) { -#ifdef ATTEMPT_ERROR_MUTING - if (sample [0] [0] < -mute_limit) - mute_block = 1; -#endif - sample [0] [0] = min_value; - } - else if (sample [0] [0] > max_value) { -#ifdef ATTEMPT_ERROR_MUTING - if (sample [0] [0] > mute_limit) - mute_block = 1; -#endif - sample [0] [0] = max_value; - } - } - - *bptr++ = sample [0] [0] << shift; - } - else if (wps->wphdr.version < 3 && !(flags & MONO_FLAG)) - for (bptr = buffer, i = 0; i < sample_count; ++i) { - int32_t sum, diff; - - read_word = get_word2 (wps, 0); - - if (read_word == WORD_EOF) - break; - - sum = (read_word << 1) | ((diff = get_word2 (wps, 1)) & 1); - sample [0] [0] += sample [0] [1] += ((sum + diff) >> 1); - sample [1] [0] += sample [1] [1] += ((sum - diff) >> 1); - - if (wps->wphdr.bits) { - if (sample [0] [0] < min_value) { -#ifdef ATTEMPT_ERROR_MUTING - if (sample [0] [0] < -mute_limit) - mute_block = 1; -#endif - sample [0] [0] = min_value; - } - else if (sample [0] [0] > max_value) { -#ifdef ATTEMPT_ERROR_MUTING - if (sample [0] [0] > mute_limit) - mute_block = 1; -#endif - sample [0] [0] = max_value; - } - - if (sample [1] [0] < min_value) { -#ifdef ATTEMPT_ERROR_MUTING - if (sample [1] [0] < -mute_limit) - mute_block = 1; -#endif - sample [1] [0] = min_value; - } - else if (sample [1] [0] > max_value) { -#ifdef ATTEMPT_ERROR_MUTING - if (sample [1] [0] > mute_limit) - mute_block = 1; -#endif - sample [1] [0] = max_value; - } - } - - *bptr++ = sample [0] [0] << shift; - *bptr++ = sample [1] [0] << shift; - } - else - i = 0; /* can't get here, but suppresses warning */ - -#ifdef ATTEMPT_ERROR_MUTING - if (!wps->wphdr.bits || (flags & WVC_FLAG)) { - int32_t *eptr = buffer + sample_count * ((flags & MONO_FLAG) ? 1 : 2); - - for (bptr = buffer; bptr < eptr; bptr += 3) - if (*bptr > mute_limit || *bptr < -mute_limit) { - mute_block = 1; - break; - } - } - - if (mute_block) - memset (buffer, 0, sizeof (*buffer) * sample_count * ((flags & MONO_FLAG) ? 1 : 2)); -#endif - - if (i && (wps->sample_index += i) == wpc->total_samples) { - - if (wps->wphdr.version == 3 && crc != (wpc->wvc_flag ? wps->wphdr.crc2 : wps->wphdr.crc)) - wpc->crc_errors++; - - if (wpc->open_flags & OPEN_WRAPPER) { - uchar *temp = malloc (1024); - uint32_t bcount; - - if (bs_unused_bytes (&wps->wvbits)) { - wpc->wrapper_data = realloc (wpc->wrapper_data, wpc->wrapper_bytes + bs_unused_bytes (&wps->wvbits)); - memcpy (wpc->wrapper_data + wpc->wrapper_bytes, bs_unused_data (&wps->wvbits), bs_unused_bytes (&wps->wvbits)); - wpc->wrapper_bytes += bs_unused_bytes (&wps->wvbits); - } - - while (1) { - bcount = wpc->reader->read_bytes (wpc->wv_in, temp, sizeof (temp)); - - if (!bcount) - break; - - wpc->wrapper_data = realloc (wpc->wrapper_data, wpc->wrapper_bytes + bcount); - memcpy (wpc->wrapper_data + wpc->wrapper_bytes, temp, bcount); - wpc->wrapper_bytes += bcount; - } - - free (temp); - - if (wpc->wrapper_bytes > 16) { - int c; - - for (c = 0; c < 16 && wpc->wrapper_data [c] == 0xff; ++c); - - if (c == 16) { - memcpy (wpc->wrapper_data, wpc->wrapper_data + 16, wpc->wrapper_bytes - 16); - wpc->wrapper_bytes -= 16; - } - else { - free (wpc->wrapper_data); - wpc->wrapper_data = NULL; - wpc->wrapper_bytes = 0; - } - } - } - } - - memcpy (wps->dc.sample, sample, sizeof (sample)); - memcpy (wps->dc.weight, weight, sizeof (weight)); - wps->dc.crc = crc; - wps->dc.m = m; - - return i; -} - -///////////////////////////// local table storage //////////////////////////// - -extern const uint32_t bitset []; -extern const uint32_t bitmask []; -extern const char nbits_table []; - -// This function initializes everything required to receive words with this -// module and must be called BEFORE any other function in this module. - -static void init_words3 (WavpackStream3 *wps) -{ - CLEAR (wps->w1); - CLEAR (wps->w2); - CLEAR (wps->w3); - CLEAR (wps->w4); - - if (wps->wphdr.flags & MONO_FLAG) - wps->w4.bitrate = wps->wphdr.bits - 768; - else - wps->w4.bitrate = (wps->wphdr.bits / 2) - 768; -} - -// This macro counts the number of bits that are required to specify the -// unsigned 32-bit value, counting from the LSB to the most significant bit -// that is set. Return range is 0 - 32. - -#define count_bits(av) ( \ - (av) < (1 << 8) ? nbits_table [av] : \ - ( \ - (av) < (1L << 16) ? nbits_table [(av) >> 8] + 8 : \ - ((av) < (1L << 24) ? nbits_table [(av) >> 16] + 16 : nbits_table [(av) >> 24] + 24) \ - ) \ -) - -static int32_t FASTCALL get_word1 (WavpackStream3 *wps, int chan) -{ - uint32_t tmp1, tmp2, avalue; - uint ones_count; - int k; - - if ((wps->wphdr.flags & EXTREME_DECORR) && !(wps->wphdr.flags & OVER_20)) { - if (wps->w1.zeros_acc) { - if (--wps->w1.zeros_acc) - return 0; - } - else if (wps->w1.ave_level [0] [0] < 0x20 && wps->w1.ave_level [0] [1] < 0x20) { - int32_t mask; - int cbits; - - for (cbits = 0; cbits < 33 && getbit (&wps->wvbits); ++cbits); - - if (cbits == 33) - return WORD_EOF; - - if (cbits < 2) - wps->w1.zeros_acc = cbits; - else { - for (mask = 1, wps->w1.zeros_acc = 0; --cbits; mask <<= 1) - if (getbit (&wps->wvbits)) - wps->w1.zeros_acc |= mask; - - wps->w1.zeros_acc |= mask; - } - - if (wps->w1.zeros_acc) - return 0; - } - } - - // count consecutive ones in bitstream, > 25 indicates error (or EOF) - - for (ones_count = 0; ones_count < 25 && getbit (&wps->wvbits); ++ones_count); - - if (ones_count == 25) - return WORD_EOF; - - k = (wps->w1.ave_level [0] [chan] + (wps->w1.ave_level [0] [chan] >> 3) + 0x40) >> 7; - k = count_bits (k); - - if (k & ~31) - return WORD_EOF; - - if (ones_count == 0) { - getbits (&avalue, k, &wps->wvbits); - avalue &= bitmask [k]; - } - else { - tmp1 = bitset [k]; - k = (wps->w1.ave_level [1] [chan] + (wps->w1.ave_level [1] [chan] >> 4) + 0x20) >> 6; - k = count_bits (k); - - if (k & ~31) - return WORD_EOF; - - if (ones_count == 1) { - getbits (&avalue, k, &wps->wvbits); - avalue &= bitmask [k]; - } - else { - tmp2 = bitset [k]; - - // If the ones count is exactly 24, then next 24 bits are literal - - if (ones_count == 24) { - getbits (&avalue, 24, &wps->wvbits); - avalue &= 0xffffff; - } - else { - k = (wps->w1.ave_level [2] [chan] + 0x10) >> 5; - k = count_bits (k); - - if (k & ~31) - return WORD_EOF; - - getbits (&avalue, k, &wps->wvbits); - avalue = (avalue & bitmask [k]) + (bitset [k] * (ones_count - 2)); - } - - wps->w1.ave_level [2] [chan] -= ((wps->w1.ave_level [2] [chan] + 0x8) >> 4); - wps->w1.ave_level [2] [chan] += avalue; - avalue += tmp2; - } - - wps->w1.ave_level [1] [chan] -= ((wps->w1.ave_level [1] [chan] + 0x10) >> 5); - wps->w1.ave_level [1] [chan] += avalue; - avalue += tmp1; - } - - wps->w1.ave_level [0] [chan] -= ((wps->w1.ave_level [0] [chan] + 0x20) >> 6); - wps->w1.ave_level [0] [chan] += avalue; - - return (avalue && getbit (&wps->wvbits)) ? -(int32_t)avalue : avalue; -} - -#define NUM_SAMPLES 128 - -static int32_t FASTCALL get_old_word1 (WavpackStream3 *wps, int chan) -{ - uint32_t avalue; - uint bc; - int k; - - if (!wps->w1.index [chan]) { - - int guess_k = (wps->w1.ave_k [chan] + 128) >> 8, ones; - - for (ones = 0; ones < 72 && getbit (&wps->wvbits); ++ones); - - if (ones == 72) - return WORD_EOF; - - if (ones % 3 == 1) - wps->w1.k_value [chan] = guess_k - (ones / 3) - 1; - else - wps->w1.k_value [chan] = guess_k + ones - ((ones + 1) / 3); - - wps->w1.ave_k [chan] -= (wps->w1.ave_k [chan] + 0x10) >> 5; - wps->w1.ave_k [chan] += wps->w1.k_value [chan] << 3; - } - - if (++wps->w1.index [chan] == NUM_SAMPLES) - wps->w1.index [chan] = 0; - - k = wps->w1.k_value [chan]; - getbits (&avalue, k, &wps->wvbits); - - for (bc = 0; bc < 32 && getbit (&wps->wvbits); ++bc); - - if (bc == 32 || (k & ~31)) - return WORD_EOF; - - avalue = (avalue & bitmask [k]) + bitset [k] * bc; - return (avalue && getbit (&wps->wvbits)) ? -(int32_t)avalue : avalue; -} - -static int32_t FASTCALL get_word2 (WavpackStream3 *wps, int chan) -{ - int cbits, delta_dbits, dbits; - int32_t value, mask = 1; - - cbits = 0; - - while (getbit (&wps->wvbits)) - if ((cbits += 2) == 50) - return WORD_EOF; - - if (getbit (&wps->wvbits)) - cbits++; - - if (cbits == 0) - delta_dbits = 0; - else if (cbits & 1) { - delta_dbits = (cbits + 1) / 2; - - if (wps->w2.last_delta_sign [chan] > 0) - delta_dbits *= -1; - - wps->w2.last_delta_sign [chan] = delta_dbits; - } - else { - delta_dbits = cbits / 2; - - if (wps->w2.last_delta_sign [chan] <= 0) - delta_dbits *= -1; - } - - dbits = (wps->w2.last_dbits [chan] += delta_dbits); - - if (dbits < 0 || dbits > 20) - return WORD_EOF; - - if (!dbits) - return 0L; - - if (wps->wphdr.bits) { - for (value = 1L << (dbits - 1); --dbits; mask <<= 1) - if (dbits < wps->wphdr.bits && getbit (&wps->wvbits)) - value |= mask; - } - else - for (value = 1L << (dbits - 1); --dbits; mask <<= 1) - if (getbit (&wps->wvbits)) - value |= mask; - - return getbit (&wps->wvbits) ? -(int32_t)value : value; -} - -static int32_t FASTCALL get_word3 (WavpackStream3 *wps, int chan) -{ - int cbits, delta_dbits, dbits; - int32_t value; - - for (cbits = 0; cbits < 72 && getbit (&wps->wvbits); ++cbits); - - if (cbits == 72) - return WORD_EOF; - - if (cbits || getbit (&wps->wvbits)) - ++cbits; - - if (!((cbits + 1) % 3)) - delta_dbits = (cbits + 1) / 3; - else - delta_dbits = -(cbits - cbits / 3); - - if (chan) { - dbits = (wps->w3.ave_dbits [1] >> 8) + 1 + delta_dbits; - wps->w3.ave_dbits [1] -= (wps->w3.ave_dbits [1] + 0x10) >> 5; - wps->w3.ave_dbits [1] += dbits << 3; - } - else { - dbits = (wps->w3.ave_dbits [0] >> 8) + 1 + delta_dbits; - wps->w3.ave_dbits [0] -= (wps->w3.ave_dbits [0] + 0x10) >> 5; - wps->w3.ave_dbits [0] += dbits << 3; - } - - if (dbits < 0 || dbits > 24) - return WORD_EOF; - - if (!dbits) - return 0L; - - if (wps->wphdr.bits && dbits > wps->wphdr.bits) { - getbits (&value, wps->wphdr.bits, &wps->wvbits); - - if (value & bitset [wps->wphdr.bits - 1]) - return -(int32_t)(value & bitmask [wps->wphdr.bits]) << (dbits - wps->wphdr.bits); - else - return ((value & bitmask [wps->wphdr.bits - 1]) | bitset [wps->wphdr.bits - 1]) << (dbits - wps->wphdr.bits); - } - else { - getbits (&value, dbits, &wps->wvbits); - - if (value & bitset [dbits - 1]) - return -(int32_t)(value & bitmask [dbits]); - else - return (value & bitmask [dbits - 1]) | bitset [dbits - 1]; - } -} - -static int FASTCALL _log2 (uint32_t avalue); - -static int32_t FASTCALL get_word4 (WavpackStream3 *wps, int chan, int32_t *correction) -{ - uint32_t base, ones_count, avalue; - int32_t value, low, mid, high; - int bitcount; - - // count consecutive ones in bitstream, > 25 indicates error (or EOF) - - for (ones_count = 0; ones_count < 25 && getbit (&wps->wvbits); ++ones_count); - - if (ones_count == 25) - return WORD_EOF; - - // if the ones count is exactly 24, then we switch to non-unary method - - if (ones_count == 24) { - int32_t mask; - int cbits; - - for (cbits = 0; cbits < 33 && getbit (&wps->wvbits); ++cbits); - - if (cbits == 33) - return WORD_EOF; - - if (cbits < 2) - ones_count = cbits; - else { - for (mask = 1, ones_count = 0; --cbits; mask <<= 1) - if (getbit (&wps->wvbits)) - ones_count |= mask; - - ones_count |= mask; - } - - ones_count += 24; - } - - if (!chan) { - int slow_log_0, slow_log_1, balance; - - if (wps->wphdr.flags & MONO_FLAG) { - wps->w4.bits_acc [0] += wps->w4.bitrate + _log2 (wps->w4.fast_level [0]) - _log2 (wps->w4.slow_level [0]) + (3 << 8); - - if (wps->w4.bits_acc [0] < 0) - wps->w4.bits_acc [0] = 0; - } - else { - slow_log_0 = _log2 (wps->w4.slow_level [0]); - slow_log_1 = _log2 (wps->w4.slow_level [1]); - - if (wps->wphdr.flags & JOINT_STEREO) - balance = (slow_log_1 - slow_log_0 + 257) >> 1; - else - balance = (slow_log_1 - slow_log_0 + 1) >> 1; - - wps->w4.bits_acc [0] += wps->w4.bitrate - balance + _log2 (wps->w4.fast_level [0]) - slow_log_0 + (3 << 8); - wps->w4.bits_acc [1] += wps->w4.bitrate + balance + _log2 (wps->w4.fast_level [1]) - slow_log_1 + (3 << 8); - - if (wps->w4.bits_acc [0] + wps->w4.bits_acc [1] < 0) - wps->w4.bits_acc [0] = wps->w4.bits_acc [1] = 0; - else if (wps->w4.bits_acc [0] < 0) { - wps->w4.bits_acc [1] += wps->w4.bits_acc [0]; - wps->w4.bits_acc [0] = 0; - } - else if (wps->w4.bits_acc [1] < 0) { - wps->w4.bits_acc [0] += wps->w4.bits_acc [1]; - wps->w4.bits_acc [1] = 0; - } - } - } - - base = (wps->w4.fast_level [chan] + 48) / 96; - bitcount = wps->w4.bits_acc [chan] >> 8; - wps->w4.bits_acc [chan] &= 0xff; - - if (!base) { - if (ones_count) - high = low = mid = (getbit (&wps->wvbits)) ? -(int32_t)ones_count : ones_count; - else - high = low = mid = 0; - } - else { - mid = (ones_count * 2 + 1) * base; - if (getbit (&wps->wvbits)) mid = -mid; - low = mid - base; - high = mid + base - 1; - - while (bitcount--) { - if (getbit (&wps->wvbits)) - mid = (high + (low = mid) + 1) >> 1; - else - mid = ((high = mid - 1) + low + 1) >> 1; - - if (high == low) - break; - } - } - - wps->w4.fast_level [chan] -= ((wps->w4.fast_level [chan] + 0x10) >> 5); - wps->w4.fast_level [chan] += (avalue = labs (mid)); - wps->w4.slow_level [chan] -= ((wps->w4.slow_level [chan] + 0x80) >> 8); - wps->w4.slow_level [chan] += avalue; - - if (bs_is_open (&wps->wvcbits)) { - - if (high != low) { - uint32_t maxcode = high - low; - int bitcount = count_bits (maxcode); - uint32_t extras = (1L << bitcount) - maxcode - 1; - - getbits (&avalue, bitcount - 1, &wps->wvcbits); - avalue &= bitmask [bitcount - 1]; - - if (avalue >= extras) { - avalue = (avalue << 1) - extras; - - if (getbit (&wps->wvcbits)) - ++avalue; - } - - value = (mid < 0) ? high - avalue : avalue + low; - - if (correction) - *correction = value - mid; - } - else if (correction) - *correction = 0; - } - - return mid; -} - -// This function calculates an approximate base-2 logarithm (with 8 bits of -// fraction) from the supplied value. Using logarithms makes comparing -// signal level values and calculating fractional bitrates much easier. - -static int FASTCALL _log2 (uint32_t avalue) -{ - int dbits; - - if ((avalue += avalue >> 9) < (1 << 8)) { - dbits = nbits_table [avalue]; - return (dbits << 8) + ((avalue << (9 - dbits)) & 0xff); - } - else { - if (avalue < (1L << 16)) - dbits = nbits_table [avalue >> 8] + 8; - else if (avalue < (1L << 24)) - dbits = nbits_table [avalue >> 16] + 16; - else - dbits = nbits_table [avalue >> 24] + 24; - - return (dbits << 8) + ((avalue >> (dbits - 9)) & 0xff); - } -} - -#endif - diff --git a/wavpack-4.5.0/src/unpack3.h b/wavpack-4.5.0/src/unpack3.h deleted file mode 100644 index 4461e0c..0000000 --- a/wavpack-4.5.0/src/unpack3.h +++ /dev/null @@ -1,113 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// **** WAVPACK **** // -// Hybrid Lossless Wavefile Compressor // -// Copyright (c) 1998 - 2006 Conifer Software. // -// All Rights Reserved. // -// Distributed under the BSD Software License (see license.txt) // -//////////////////////////////////////////////////////////////////////////// - -// wavpack3.h - -// This header file contains all the additional definitions required for -// decoding old (versions 1, 2 & 3) WavPack files. - -typedef struct { - ushort FormatTag, NumChannels; - uint32_t SampleRate, BytesPerSecond; - ushort BlockAlign, BitsPerSample; -} WaveHeader3; - -#define WaveHeader3Format "SSLLSS" - -typedef struct { - char ckID [4]; - int32_t ckSize; - short version; - short bits; // added for version 2.00 - short flags, shift; // added for version 3.00 - int32_t total_samples, crc, crc2; - char extension [4], extra_bc, extras [3]; -} WavpackHeader3; - -#define WavpackHeader3Format "4LSSSSLLL4L" - -// these flags added for version 3 - -#undef MONO_FLAG // these definitions changed for WavPack 4.0 -#undef CROSS_DECORR -#undef JOINT_STEREO - -#define MONO_FLAG 1 // not stereo -#define FAST_FLAG 2 // non-adaptive predictor and stereo mode -#define RAW_FLAG 4 // raw mode (no .wav header) -#define CALC_NOISE 8 // calc noise in lossy mode (no longer stored) -#define HIGH_FLAG 0x10 // high quality mode (all modes) -#define BYTES_3 0x20 // files have 3-byte samples -#define OVER_20 0x40 // samples are over 20 bits -#define WVC_FLAG 0x80 // create/use .wvc (no longer stored) -#define LOSSY_SHAPE 0x100 // noise shape (lossy mode only) -#define VERY_FAST_FLAG 0x200 // double fast (no longer stored) -#define NEW_HIGH_FLAG 0x400 // new high quality mode (lossless only) -#define CANCEL_EXTREME 0x800 // cancel EXTREME_DECORR -#define CROSS_DECORR 0x1000 // decorrelate chans (with EXTREME_DECORR flag) -#define NEW_DECORR_FLAG 0x2000 // new high-mode decorrelator -#define JOINT_STEREO 0x4000 // joint stereo (lossy and high lossless) -#define EXTREME_DECORR 0x8000 // extra decorrelation (+ enables other flags) - -#define STORED_FLAGS 0xfd77 // these are only flags that affect unpacking -#define NOT_STORED_FLAGS (~STORED_FLAGS & 0xffff) - -// BitStream stuff (bits.c) - -typedef struct bs3 { - void (*wrap)(struct bs3 *bs); - uchar *buf, *end, *ptr; - uint32_t bufsiz, fpos, sr; - WavpackStreamReader *reader; - int error, bc; - void *id; -} Bitstream3; - -#define K_DEPTH 3 -#define MAX_NTERMS3 18 - -typedef struct { - WavpackHeader3 wphdr; - Bitstream3 wvbits, wvcbits; - uint32_t sample_index; - int num_terms; - -#ifndef NO_SEEKING - struct index_point { - char saved; - uint32_t sample_index; - } index_points [256]; - - uchar *unpack_data; - uint32_t unpack_size; -#endif - - struct { - int32_t sum_level, left_level, right_level, diff_level; - int last_extra_bits, extra_bits_count, m; - int32_t error [2], crc; - int32_t sample [2] [2]; - int weight [2] [1]; - } dc; - - struct decorr_pass decorr_passes [MAX_NTERMS3]; - - struct { - uint index [2], k_value [2], ave_k [2]; - uint32_t zeros_acc, ave_level [K_DEPTH] [2]; - } w1; - - struct { int last_dbits [2], last_delta_sign [2], bit_limit; } w2; - - struct { int ave_dbits [2], bit_limit; } w3; - - struct { - uint32_t fast_level [2], slow_level [2]; - int bits_acc [2], bitrate; - } w4; -} WavpackStream3; diff --git a/wavpack-4.5.0/src/wavpack_local.h b/wavpack-4.5.0/src/wavpack_local.h deleted file mode 100644 index 4f8899c..0000000 --- a/wavpack-4.5.0/src/wavpack_local.h +++ /dev/null @@ -1,764 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// **** WAVPACK **** // -// Hybrid Lossless Wavefile Compressor // -// Copyright (c) 1998 - 2006 Conifer Software. // -// All Rights Reserved. // -// Distributed under the BSD Software License (see license.txt) // -//////////////////////////////////////////////////////////////////////////// - -// wavpack_local.h - -#ifndef WAVPACK_LOCAL_H -#define WAVPACK_LOCAL_H - -#if defined(WIN32) -#define FASTCALL __fastcall -#else -#define FASTCALL -#endif - -#if defined(WIN32) || \ - (defined(BYTE_ORDER) && defined(LITTLE_ENDIAN) && (BYTE_ORDER == LITTLE_ENDIAN)) -#define BITSTREAM_SHORTS // use "shorts" for reading/writing bitstreams - // (only works on little-endian machines) -#endif - -#include - -// This header file contains all the definitions required by WavPack. - -#if defined(_WIN32) && !defined(__MINGW32__) -#include -typedef unsigned __int64 uint64_t; -typedef unsigned __int32 uint32_t; -typedef unsigned __int16 uint16_t; -typedef unsigned __int8 uint8_t; -typedef __int64 int64_t; -typedef __int32 int32_t; -typedef __int16 int16_t; -typedef __int8 int8_t; -typedef float float32_t; -#else -#include -#endif - -typedef unsigned char uchar; - -#if !defined(__GNUC__) || defined(WIN32) -typedef unsigned short ushort; -typedef unsigned int uint; -#endif - -// Because the C99 specification states that "The order of allocation of -// bit-fields within a unit (high-order to low-order or low-order to -// high-order) is implementation-defined" (6.7.2.1), I decided to change -// the representation of floating-point values from a structure of -// bit-fields to a 32-bit integer with access macros. Note that the WavPack -// library doesn't use any floating-point math to implement compression of -// floating-point data (although a little floating-point math is used in -// high-level functions unrelated to the codec). - -typedef int32_t f32; - -#define get_mantissa(f) ((f) & 0x7fffff) -#define get_exponent(f) (((f) >> 23) & 0xff) -#define get_sign(f) (((f) >> 31) & 0x1) - -#define set_mantissa(f,v) (f) ^= (((f) ^ (v)) & 0x7fffff) -#define set_exponent(f,v) (f) ^= (((f) ^ ((v) << 23)) & 0x7f800000) -#define set_sign(f,v) (f) ^= (((f) ^ ((v) << 31)) & 0x80000000) - -#include - -#define FALSE 0 -#define TRUE 1 - -// ID3v1 and APEv2 TAG formats (may occur at the end of WavPack files) - -typedef struct { - char tag_id [3], title [30], artist [30], album [30]; - char year [4], comment [30], genre; -} ID3_Tag; - -typedef struct { - char ID [8]; - int32_t version, length, item_count, flags; - char res [8]; -} APE_Tag_Hdr; - -#define APE_Tag_Hdr_Format "8LLLL" - -typedef struct { - int32_t tag_file_pos; - ID3_Tag id3_tag; - APE_Tag_Hdr ape_tag_hdr; - char *ape_tag_data; -} M_Tag; - -// RIFF / wav header formats (these occur at the beginning of both wav files -// and pre-4.0 WavPack files that are not in the "raw" mode) - -typedef struct { - char ckID [4]; - uint32_t ckSize; - char formType [4]; -} RiffChunkHeader; - -typedef struct { - char ckID [4]; - uint32_t ckSize; -} ChunkHeader; - -#define ChunkHeaderFormat "4L" - -typedef struct { - ushort FormatTag, NumChannels; - uint32_t SampleRate, BytesPerSecond; - ushort BlockAlign, BitsPerSample; - ushort cbSize, ValidBitsPerSample; - int32_t ChannelMask; - ushort SubFormat; - char GUID [14]; -} WaveHeader; - -#define WaveHeaderFormat "SSLLSSSSLS" - -////////////////////////////// WavPack Header ///////////////////////////////// - -// Note that this is the ONLY structure that is written to (or read from) -// WavPack 4.0 files, and is the preamble to every block in both the .wv -// and .wvc files. - -typedef struct { - char ckID [4]; - uint32_t ckSize; - short version; - uchar track_no, index_no; - uint32_t total_samples, block_index, block_samples, flags, crc; -} WavpackHeader; - -#define WavpackHeaderFormat "4LS2LLLLL" - -// or-values for "flags" - -#define BYTES_STORED 3 // 1-4 bytes/sample -#define MONO_FLAG 4 // not stereo -#define HYBRID_FLAG 8 // hybrid mode -#define JOINT_STEREO 0x10 // joint stereo -#define CROSS_DECORR 0x20 // no-delay cross decorrelation -#define HYBRID_SHAPE 0x40 // noise shape (hybrid mode only) -#define FLOAT_DATA 0x80 // ieee 32-bit floating point data - -#define INT32_DATA 0x100 // special extended int handling -#define HYBRID_BITRATE 0x200 // bitrate noise (hybrid mode only) -#define HYBRID_BALANCE 0x400 // balance noise (hybrid stereo mode only) - -#define INITIAL_BLOCK 0x800 // initial block of multichannel segment -#define FINAL_BLOCK 0x1000 // final block of multichannel segment - -#define SHIFT_LSB 13 -#define SHIFT_MASK (0x1fL << SHIFT_LSB) - -#define MAG_LSB 18 -#define MAG_MASK (0x1fL << MAG_LSB) - -#define SRATE_LSB 23 -#define SRATE_MASK (0xfL << SRATE_LSB) - -#define FALSE_STEREO 0x40000000 // block is stereo, but data is mono - -#define IGNORED_FLAGS 0x18000000 // reserved, but ignore if encountered -#define NEW_SHAPING 0x20000000 // use IIR filter for negative shaping -#define UNKNOWN_FLAGS 0x80000000 // also reserved, but refuse decode if - // encountered - -#define MONO_DATA (MONO_FLAG | FALSE_STEREO) - -#define MIN_STREAM_VERS 0x402 // lowest stream version we'll decode -#define MAX_STREAM_VERS 0x410 // highest stream version we'll decode or encode -#define CUR_STREAM_VERS 0x407 // stream version we are [normally] writing now - - -//////////////////////////// WavPack Metadata ///////////////////////////////// - -// This is an internal representation of metadata. - -typedef struct { - int32_t byte_length; - void *data; - uchar id; -} WavpackMetadata; - -#define ID_UNIQUE 0x3f -#define ID_OPTIONAL_DATA 0x20 -#define ID_ODD_SIZE 0x40 -#define ID_LARGE 0x80 - -#define ID_DUMMY 0x0 -#define ID_ENCODER_INFO 0x1 -#define ID_DECORR_TERMS 0x2 -#define ID_DECORR_WEIGHTS 0x3 -#define ID_DECORR_SAMPLES 0x4 -#define ID_ENTROPY_VARS 0x5 -#define ID_HYBRID_PROFILE 0x6 -#define ID_SHAPING_WEIGHTS 0x7 -#define ID_FLOAT_INFO 0x8 -#define ID_INT32_INFO 0x9 -#define ID_WV_BITSTREAM 0xa -#define ID_WVC_BITSTREAM 0xb -#define ID_WVX_BITSTREAM 0xc -#define ID_CHANNEL_INFO 0xd - -#define ID_RIFF_HEADER (ID_OPTIONAL_DATA | 0x1) -#define ID_RIFF_TRAILER (ID_OPTIONAL_DATA | 0x2) -#define ID_REPLAY_GAIN (ID_OPTIONAL_DATA | 0x3) -#define ID_CUESHEET (ID_OPTIONAL_DATA | 0x4) -#define ID_CONFIG_BLOCK (ID_OPTIONAL_DATA | 0x5) -#define ID_MD5_CHECKSUM (ID_OPTIONAL_DATA | 0x6) -#define ID_SAMPLE_RATE (ID_OPTIONAL_DATA | 0x7) - -///////////////////////// WavPack Configuration /////////////////////////////// - -// This internal structure is used during encode to provide configuration to -// the encoding engine and during decoding to provide fle information back to -// the higher level functions. Not all fields are used in both modes. - -typedef struct { - float bitrate, shaping_weight; - int bits_per_sample, bytes_per_sample; - int qmode, flags, xmode, num_channels, float_norm_exp; - int32_t block_samples, extra_flags, sample_rate, channel_mask; - uchar md5_checksum [16], md5_read; - int num_tag_strings; - char **tag_strings; -} WavpackConfig; - -#define CONFIG_BYTES_STORED 3 // 1-4 bytes/sample -#define CONFIG_MONO_FLAG 4 // not stereo -#define CONFIG_HYBRID_FLAG 8 // hybrid mode -#define CONFIG_JOINT_STEREO 0x10 // joint stereo -#define CONFIG_CROSS_DECORR 0x20 // no-delay cross decorrelation -#define CONFIG_HYBRID_SHAPE 0x40 // noise shape (hybrid mode only) -#define CONFIG_FLOAT_DATA 0x80 // ieee 32-bit floating point data - -#define CONFIG_FAST_FLAG 0x200 // fast mode -#define CONFIG_HIGH_FLAG 0x800 // high quality mode -#define CONFIG_VERY_HIGH_FLAG 0x1000 // very high -#define CONFIG_BITRATE_KBPS 0x2000 // bitrate is kbps, not bits / sample -#define CONFIG_AUTO_SHAPING 0x4000 // automatic noise shaping -#define CONFIG_SHAPE_OVERRIDE 0x8000 // shaping mode specified -#define CONFIG_JOINT_OVERRIDE 0x10000 // joint-stereo mode specified -#define CONFIG_DYNAMIC_SHAPING 0x20000 // dynamic noise shaping -#define CONFIG_CREATE_EXE 0x40000 // create executable -#define CONFIG_CREATE_WVC 0x80000 // create correction file -#define CONFIG_OPTIMIZE_WVC 0x100000 // maximize bybrid compression -#define CONFIG_CALC_NOISE 0x800000 // calc noise in hybrid mode -#define CONFIG_LOSSY_MODE 0x1000000 // obsolete (for information) -#define CONFIG_EXTRA_MODE 0x2000000 // extra processing mode -#define CONFIG_SKIP_WVX 0x4000000 // no wvx stream w/ floats & big ints -#define CONFIG_MD5_CHECKSUM 0x8000000 // compute & store MD5 signature -#define CONFIG_MERGE_BLOCKS 0x10000000 // merge blocks of equal redundancy (for lossyWAV) -#define CONFIG_OPTIMIZE_MONO 0x80000000 // optimize for mono streams posing as stereo - -/* - * These config flags were never actually used, or are no longer used, or are - * used for something else now. They may be used in the future for what they - * say, or for something else. WavPack files in the wild *may* have some of - * these bit set in their config flags (with these older meanings), but only - * if the stream version is 0x410 or less than 0x407. Of course, this is not - * very important because once the file has been encoded, the config bits are - * just for information purposes (i.e., they do not affect decoding), - * -#define CONFIG_ADOBE_MODE 0x100 // "adobe" mode for 32-bit floats -#define CONFIG_VERY_FAST_FLAG 0x400 // double fast -#define CONFIG_COPY_TIME 0x20000 // copy file-time from source -#define CONFIG_QUALITY_MODE 0x200000 // psychoacoustic quality mode -#define CONFIG_RAW_FLAG 0x400000 // raw mode (not implemented yet) -#define CONFIG_QUIET_MODE 0x10000000 // don't report progress % -#define CONFIG_IGNORE_LENGTH 0x20000000 // ignore length in wav header -#define CONFIG_NEW_RIFF_HEADER 0x40000000 // generate new RIFF wav header - * - */ - -#define EXTRA_SCAN_ONLY 1 -#define EXTRA_STEREO_MODES 2 -#define EXTRA_TRY_DELTAS 8 -#define EXTRA_ADJUST_DELTAS 16 -#define EXTRA_SORT_FIRST 32 -#define EXTRA_BRANCHES 0x1c0 -#define EXTRA_SKIP_8TO16 512 -#define EXTRA_TERMS 0x3c00 -#define EXTRA_DUMP_TERMS 16384 -#define EXTRA_SORT_LAST 32768 - -//////////////////////////////// WavPack Stream /////////////////////////////// - -// This internal structure contains everything required to handle a WavPack -// "stream", which is defined as a stereo or mono stream of audio samples. For -// multichannel audio several of these would be required. Each stream contains -// pointers to hold a complete allocated block of WavPack data, although it's -// possible to decode WavPack blocks without buffering an entire block. - -typedef struct bs { -#ifdef BITSTREAM_SHORTS - unsigned short *buf, *end, *ptr; -#else - unsigned char *buf, *end, *ptr; -#endif - void (*wrap)(struct bs *bs); - int error, bc; - uint32_t sr; -} Bitstream; - -#define MAX_WRAPPER_BYTES 16777216 -#define MAX_STREAMS 8 -#define MAX_NTERMS 16 -#define MAX_TERM 8 - -struct decorr_pass { - int term, delta, weight_A, weight_B; - int32_t samples_A [MAX_TERM], samples_B [MAX_TERM]; - int32_t aweight_A, aweight_B; - int32_t sum_A, sum_B; -}; - -typedef struct { - char joint_stereo, delta, terms [MAX_NTERMS+1]; -} WavpackDecorrSpec; - -struct entropy_data { - uint32_t median [3], slow_level, error_limit; -}; - -struct words_data { - uint32_t bitrate_delta [2], bitrate_acc [2]; - uint32_t pend_data, holding_one, zeros_acc; - int holding_zero, pend_count; - struct entropy_data c [2]; -}; - -typedef struct { - WavpackHeader wphdr; - struct words_data w; - - uchar *blockbuff, *blockend; - uchar *block2buff, *block2end; - int32_t *sample_buffer; - - int bits, num_terms, mute_error, joint_stereo, false_stereo, shift; - int num_decorrs, num_passes, best_decorr, mask_decorr; - uint32_t sample_index, crc, crc_x, crc_wvx; - Bitstream wvbits, wvcbits, wvxbits; - int init_done, wvc_skip; - float delta_decay; - - uchar int32_sent_bits, int32_zeros, int32_ones, int32_dups; - uchar float_flags, float_shift, float_max_exp, float_norm_exp; - - struct { - int32_t shaping_acc [2], shaping_delta [2], error [2]; - double noise_sum, noise_ave, noise_max; - short *shaping_data, *shaping_array; - int32_t shaping_samples; - } dc; - - struct decorr_pass decorr_passes [MAX_NTERMS], analysis_pass; - const WavpackDecorrSpec *decorr_specs; -} WavpackStream; - -// flags for float_flags: - -#define FLOAT_SHIFT_ONES 1 // bits left-shifted into float = '1' -#define FLOAT_SHIFT_SAME 2 // bits left-shifted into float are the same -#define FLOAT_SHIFT_SENT 4 // bits shifted into float are sent literally -#define FLOAT_ZEROS_SENT 8 // "zeros" are not all real zeros -#define FLOAT_NEG_ZEROS 0x10 // contains negative zeros -#define FLOAT_EXCEPTIONS 0x20 // contains exceptions (inf, nan, etc.) - -/////////////////////////////// WavPack Context /////////////////////////////// - -// This internal structure holds everything required to encode or decode WavPack -// files. It is recommended that direct access to this structure be minimized -// and the provided utilities used instead. - -typedef struct { - int32_t (*read_bytes)(void *id, void *data, int32_t bcount); - uint32_t (*get_pos)(void *id); - int (*set_pos_abs)(void *id, uint32_t pos); - int (*set_pos_rel)(void *id, int32_t delta, int mode); - int (*push_back_byte)(void *id, int c); - uint32_t (*get_length)(void *id); - int (*can_seek)(void *id); - - // this callback is for writing edited tags only - int32_t (*write_bytes)(void *id, void *data, int32_t bcount); -} WavpackStreamReader; - -typedef int (*WavpackBlockOutput)(void *id, void *data, int32_t bcount); - -typedef struct { - WavpackConfig config; - - WavpackMetadata *metadata; - uint32_t metabytes; - int metacount; - - uchar *wrapper_data; - uint32_t wrapper_bytes; - - WavpackBlockOutput blockout; - void *wv_out, *wvc_out; - - WavpackStreamReader *reader; - void *wv_in, *wvc_in; - - uint32_t filelen, file2len, filepos, file2pos, total_samples, crc_errors, first_flags; - int wvc_flag, open_flags, norm_offset, reduced_channels, lossy_blocks, close_files; - uint32_t block_samples, ave_block_samples, block_boundary, max_samples, acc_samples, initial_index; - int riff_header_added, riff_header_created; - M_Tag m_tag; - - int current_stream, num_streams, stream_version; - WavpackStream *streams [MAX_STREAMS]; - void *stream3; - - char error_message [80]; -} WavpackContext; - -//////////////////////// function prototypes and macros ////////////////////// - -#define CLEAR(destin) memset (&destin, 0, sizeof (destin)); - -// these macros implement the weight application and update operations -// that are at the heart of the decorrelation loops - -#define apply_weight_i(weight, sample) ((weight * sample + 512) >> 10) - -#define apply_weight_f(weight, sample) (((((sample & 0xffff) * weight) >> 9) + \ - (((sample & ~0xffff) >> 9) * weight) + 1) >> 1) - -#if 1 // PERFCOND -#define apply_weight(weight, sample) (sample != (short) sample ? \ - apply_weight_f (weight, sample) : apply_weight_i (weight, sample)) -#else -#define apply_weight(weight, sample) ((int32_t)((weight * (int64_t) sample + 512) >> 10)) -#endif - -#if 1 // PERFCOND -#define update_weight(weight, delta, source, result) \ - if (source && result) { int32_t s = (int32_t) (source ^ result) >> 31; weight = (delta ^ s) + (weight - s); } -#elif 1 -#define update_weight(weight, delta, source, result) \ - if (source && result) weight += (((source ^ result) >> 30) | 1) * delta; -#else -#define update_weight(weight, delta, source, result) \ - if (source && result) (source ^ result) < 0 ? (weight -= delta) : (weight += delta); -#endif - -#define update_weight_d2(weight, delta, source, result) \ - if (source && result) weight -= (((source ^ result) >> 29) & 4) - 2; - -#define update_weight_clip(weight, delta, source, result) \ - if (source && result) { \ - const int32_t s = (source ^ result) >> 31; \ - if ((weight = (weight ^ s) + (delta - s)) > 1024) weight = 1024; \ - weight = (weight ^ s) - s; \ - } - -#define update_weight_clip_d2(weight, delta, source, result) \ - if (source && result) { \ - const int32_t s = (source ^ result) >> 31; \ - if ((weight = (weight ^ s) + (2 - s)) > 1024) weight = 1024; \ - weight = (weight ^ s) - s; \ - } - -// bits.c - -void bs_open_read (Bitstream *bs, void *buffer_start, void *buffer_end); -void bs_open_write (Bitstream *bs, void *buffer_start, void *buffer_end); -uint32_t bs_close_read (Bitstream *bs); -uint32_t bs_close_write (Bitstream *bs); - -int DoReadFile (FILE *hFile, void *lpBuffer, uint32_t nNumberOfBytesToRead, uint32_t *lpNumberOfBytesRead); -int DoWriteFile (FILE *hFile, void *lpBuffer, uint32_t nNumberOfBytesToWrite, uint32_t *lpNumberOfBytesWritten); -uint32_t DoGetFileSize (FILE *hFile), DoGetFilePosition (FILE *hFile); -int DoSetFilePositionRelative (FILE *hFile, int32_t pos, int mode); -int DoSetFilePositionAbsolute (FILE *hFile, uint32_t pos); -int DoUngetc (int c, FILE *hFile), DoDeleteFile (char *filename); -int DoCloseHandle (FILE *hFile), DoTruncateFile (FILE *hFile); - -#define bs_is_open(bs) ((bs)->ptr != NULL) - -#define getbit(bs) ( \ - (((bs)->bc) ? \ - ((bs)->bc--, (bs)->sr & 1) : \ - (((++((bs)->ptr) != (bs)->end) ? (void) 0 : (bs)->wrap (bs)), (bs)->bc = sizeof (*((bs)->ptr)) * 8 - 1, ((bs)->sr = *((bs)->ptr)) & 1) \ - ) ? \ - ((bs)->sr >>= 1, 1) : \ - ((bs)->sr >>= 1, 0) \ -) - -#define getbits(value, nbits, bs) { \ - while ((nbits) > (bs)->bc) { \ - if (++((bs)->ptr) == (bs)->end) (bs)->wrap (bs); \ - (bs)->sr |= (int32_t)*((bs)->ptr) << (bs)->bc; \ - (bs)->bc += sizeof (*((bs)->ptr)) * 8; \ - } \ - *(value) = (bs)->sr; \ - if ((bs)->bc > 32) { \ - (bs)->bc -= (nbits); \ - (bs)->sr = *((bs)->ptr) >> (sizeof (*((bs)->ptr)) * 8 - (bs)->bc); \ - } \ - else { \ - (bs)->bc -= (nbits); \ - (bs)->sr >>= (nbits); \ - } \ -} - -#define putbit(bit, bs) { if (bit) (bs)->sr |= (1 << (bs)->bc); \ - if (++((bs)->bc) == sizeof (*((bs)->ptr)) * 8) { \ - *((bs)->ptr) = (bs)->sr; \ - (bs)->sr = (bs)->bc = 0; \ - if (++((bs)->ptr) == (bs)->end) (bs)->wrap (bs); \ - }} - -#define putbit_0(bs) { \ - if (++((bs)->bc) == sizeof (*((bs)->ptr)) * 8) { \ - *((bs)->ptr) = (bs)->sr; \ - (bs)->sr = (bs)->bc = 0; \ - if (++((bs)->ptr) == (bs)->end) (bs)->wrap (bs); \ - }} - -#define putbit_1(bs) { (bs)->sr |= (1 << (bs)->bc); \ - if (++((bs)->bc) == sizeof (*((bs)->ptr)) * 8) { \ - *((bs)->ptr) = (bs)->sr; \ - (bs)->sr = (bs)->bc = 0; \ - if (++((bs)->ptr) == (bs)->end) (bs)->wrap (bs); \ - }} - -#define putbits(value, nbits, bs) { \ - (bs)->sr |= (int32_t)(value) << (bs)->bc; \ - if (((bs)->bc += (nbits)) >= sizeof (*((bs)->ptr)) * 8) \ - do { \ - *((bs)->ptr) = (bs)->sr; \ - (bs)->sr >>= sizeof (*((bs)->ptr)) * 8; \ - if (((bs)->bc -= sizeof (*((bs)->ptr)) * 8) > 32 - sizeof (*((bs)->ptr)) * 8) \ - (bs)->sr |= ((value) >> ((nbits) - (bs)->bc)); \ - if (++((bs)->ptr) == (bs)->end) (bs)->wrap (bs); \ - } while ((bs)->bc >= sizeof (*((bs)->ptr)) * 8); \ -} - -void little_endian_to_native (void *data, char *format); -void native_to_little_endian (void *data, char *format); - -// pack.c - -void pack_init (WavpackContext *wpc); -int pack_block (WavpackContext *wpc, int32_t *buffer); -double WavpackGetEncodedNoise (WavpackContext *wpc, double *peak); - -// unpack.c - -int unpack_init (WavpackContext *wpc); -int init_wv_bitstream (WavpackStream *wps, WavpackMetadata *wpmd); -int init_wvc_bitstream (WavpackStream *wps, WavpackMetadata *wpmd); -int init_wvx_bitstream (WavpackStream *wps, WavpackMetadata *wpmd); -int read_decorr_terms (WavpackStream *wps, WavpackMetadata *wpmd); -int read_decorr_weights (WavpackStream *wps, WavpackMetadata *wpmd); -int read_decorr_samples (WavpackStream *wps, WavpackMetadata *wpmd); -int read_shaping_info (WavpackStream *wps, WavpackMetadata *wpmd); -int read_float_info (WavpackStream *wps, WavpackMetadata *wpmd); -int read_int32_info (WavpackStream *wps, WavpackMetadata *wpmd); -int read_channel_info (WavpackContext *wpc, WavpackMetadata *wpmd); -int read_config_info (WavpackContext *wpc, WavpackMetadata *wpmd); -int read_sample_rate (WavpackContext *wpc, WavpackMetadata *wpmd); -int read_wrapper_data (WavpackContext *wpc, WavpackMetadata *wpmd); -int32_t unpack_samples (WavpackContext *wpc, int32_t *buffer, uint32_t sample_count); -int check_crc_error (WavpackContext *wpc); - -// unpack3.c - -WavpackContext *open_file3 (WavpackContext *wpc, char *error); -int32_t unpack_samples3 (WavpackContext *wpc, int32_t *buffer, uint32_t sample_count); -int seek_sample3 (WavpackContext *wpc, uint32_t desired_index); -uint32_t get_sample_index3 (WavpackContext *wpc); -void free_stream3 (WavpackContext *wpc); -int get_version3 (WavpackContext *wpc); - -// metadata.c stuff - -int read_metadata_buff (WavpackMetadata *wpmd, uchar *blockbuff, uchar **buffptr); -int write_metadata_block (WavpackContext *wpc); -int copy_metadata (WavpackMetadata *wpmd, uchar *buffer_start, uchar *buffer_end); -int add_to_metadata (WavpackContext *wpc, void *data, uint32_t bcount, uchar id); -int process_metadata (WavpackContext *wpc, WavpackMetadata *wpmd); -void free_metadata (WavpackMetadata *wpmd); - -// words.c stuff - -void init_words (WavpackStream *wps); -void word_set_bitrate (WavpackStream *wps); -void write_entropy_vars (WavpackStream *wps, WavpackMetadata *wpmd); -void write_hybrid_profile (WavpackStream *wps, WavpackMetadata *wpmd); -int read_entropy_vars (WavpackStream *wps, WavpackMetadata *wpmd); -int read_hybrid_profile (WavpackStream *wps, WavpackMetadata *wpmd); -int32_t FASTCALL send_word (WavpackStream *wps, int32_t value, int chan); -void send_words_lossless (WavpackStream *wps, int32_t *buffer, int32_t nsamples); -int32_t FASTCALL get_word (WavpackStream *wps, int chan, int32_t *correction); -int32_t get_words_lossless (WavpackStream *wps, int32_t *buffer, int32_t nsamples); -void flush_word (WavpackStream *wps); -int32_t nosend_word (WavpackStream *wps, int32_t value, int chan); -void scan_word (WavpackStream *wps, int32_t *samples, uint32_t num_samples, int dir); - -int log2s (int32_t value); -int32_t exp2s (int log); -uint32_t log2buffer (int32_t *samples, uint32_t num_samples, int limit); - -signed char store_weight (int weight); -int restore_weight (signed char weight); - -#define WORD_EOF ((int32_t)(1L << 31)) - -// float.c - -void write_float_info (WavpackStream *wps, WavpackMetadata *wpmd); -int scan_float_data (WavpackStream *wps, f32 *values, int32_t num_values); -void send_float_data (WavpackStream *wps, f32 *values, int32_t num_values); -int read_float_info (WavpackStream *wps, WavpackMetadata *wpmd); -void float_values (WavpackStream *wps, int32_t *values, int32_t num_values); -void WavpackFloatNormalize (int32_t *values, int32_t num_values, int delta_exp); - -// extra?.c - -// void analyze_stereo (WavpackContext *wpc, int32_t *samples); -// void analyze_mono (WavpackContext *wpc, int32_t *samples); -void execute_stereo (WavpackContext *wpc, int32_t *samples, int no_history, int do_samples); -void execute_mono (WavpackContext *wpc, int32_t *samples, int no_history, int do_samples); - -// wputils.c - -WavpackContext *WavpackOpenFileInputEx (WavpackStreamReader *reader, void *wv_id, void *wvc_id, char *error, int flags, int norm_offset); -WavpackContext *WavpackOpenFileInput (const wchar_t *infilename, char *error, int flags, int norm_offset); - -#define OPEN_WVC 0x1 // open/read "correction" file -#define OPEN_TAGS 0x2 // read ID3v1 / APEv2 tags (seekable file) -#define OPEN_WRAPPER 0x4 // make audio wrapper available (i.e. RIFF) -#define OPEN_2CH_MAX 0x8 // open multichannel as stereo (no downmix) -#define OPEN_NORMALIZE 0x10 // normalize floating point data to +/- 1.0 -#define OPEN_STREAMING 0x20 // "streaming" mode blindly unpacks blocks - // w/o regard to header file position info -#define OPEN_EDIT_TAGS 0x40 // allow editing of tags - -int WavpackGetMode (WavpackContext *wpc); - -#define MODE_WVC 0x1 -#define MODE_LOSSLESS 0x2 -#define MODE_HYBRID 0x4 -#define MODE_FLOAT 0x8 -#define MODE_VALID_TAG 0x10 -#define MODE_HIGH 0x20 -#define MODE_FAST 0x40 -#define MODE_EXTRA 0x80 // extra mode used, see MODE_XMODE for possible level -#define MODE_APETAG 0x100 -#define MODE_SFX 0x200 -#define MODE_VERY_HIGH 0x400 -#define MODE_MD5 0x800 -#define MODE_XMODE 0x7000 // mask for extra level (1-6, 0=unknown) -#define MODE_DNS 0x8000 - -char *WavpackGetErrorMessage (WavpackContext *wpc); -int WavpackGetVersion (WavpackContext *wpc); -uint32_t WavpackUnpackSamples (WavpackContext *wpc, int32_t *buffer, uint32_t samples); -uint32_t WavpackGetNumSamples (WavpackContext *wpc); -uint32_t WavpackGetSampleIndex (WavpackContext *wpc); -int WavpackGetNumErrors (WavpackContext *wpc); -int WavpackLossyBlocks (WavpackContext *wpc); -int WavpackSeekSample (WavpackContext *wpc, uint32_t sample); -WavpackContext *WavpackCloseFile (WavpackContext *wpc); -uint32_t WavpackGetSampleRate (WavpackContext *wpc); -int WavpackGetBitsPerSample (WavpackContext *wpc); -int WavpackGetBytesPerSample (WavpackContext *wpc); -int WavpackGetNumChannels (WavpackContext *wpc); -int WavpackGetChannelMask (WavpackContext *wpc); -int WavpackGetReducedChannels (WavpackContext *wpc); -int WavpackGetFloatNormExp (WavpackContext *wpc); -int WavpackGetMD5Sum (WavpackContext *wpc, uchar data [16]); -uint32_t WavpackGetWrapperBytes (WavpackContext *wpc); -uchar *WavpackGetWrapperData (WavpackContext *wpc); -void WavpackFreeWrapper (WavpackContext *wpc); -void WavpackSeekTrailingWrapper (WavpackContext *wpc); -double WavpackGetProgress (WavpackContext *wpc); -uint32_t WavpackGetFileSize (WavpackContext *wpc); -double WavpackGetRatio (WavpackContext *wpc); -double WavpackGetAverageBitrate (WavpackContext *wpc, int count_wvc); -double WavpackGetInstantBitrate (WavpackContext *wpc); -int WavpackGetNumTagItems (WavpackContext *wpc); -int WavpackGetTagItem (WavpackContext *wpc, const char *item, char *value, int size); -int WavpackGetTagItemIndexed (WavpackContext *wpc, int index, char *item, int size); -int WavpackAppendTagItem (WavpackContext *wpc, const char *item, const char *value, int vsize); -int WavpackDeleteTagItem (WavpackContext *wpc, const char *item); -int WavpackWriteTag (WavpackContext *wpc); - -WavpackContext *WavpackOpenFileOutput (WavpackBlockOutput blockout, void *wv_id, void *wvc_id); -int WavpackSetConfiguration (WavpackContext *wpc, WavpackConfig *config, uint32_t total_samples); -int WavpackAddWrapper (WavpackContext *wpc, void *data, uint32_t bcount); -int WavpackStoreMD5Sum (WavpackContext *wpc, uchar data [16]); -int WavpackPackInit (WavpackContext *wpc); -int WavpackPackSamples (WavpackContext *wpc, int32_t *sample_buffer, uint32_t sample_count); -int WavpackFlushSamples (WavpackContext *wpc); -void WavpackUpdateNumSamples (WavpackContext *wpc, void *first_block); -void *WavpackGetWrapperLocation (void *first_block, uint32_t *size); - -void WavpackLittleEndianToNative (void *data, char *format); -void WavpackNativeToLittleEndian (void *data, char *format); - -uint32_t WavpackGetLibraryVersion (void); -const char *WavpackGetLibraryVersionString (void); - -///////////////////////////// SIMD helper macros ///////////////////////////// - -#ifdef OPT_MMX - -#if defined (__GNUC__) && !defined (__INTEL_COMPILER) -//directly map to gcc's native builtins for faster code - -#if __GNUC__ < 4 -typedef int __di __attribute__ ((__mode__ (__DI__))); -typedef int __m64 __attribute__ ((__mode__ (__V2SI__))); -typedef int __v4hi __attribute__ ((__mode__ (__V4HI__))); -#define _m_paddsw(m1, m2) (__m64) __builtin_ia32_paddsw ((__v4hi) m1, (__v4hi) m2) -#define _m_pand(m1, m2) (__m64) __builtin_ia32_pand ((__di) m1, (__di) m2) -#define _m_pandn(m1, m2) (__m64) __builtin_ia32_pandn ((__di) m1, (__di) m2) -#define _m_pmaddwd(m1, m2) __builtin_ia32_pmaddwd ((__v4hi) m1, (__v4hi) m2) -#define _m_por(m1, m2) (__m64) __builtin_ia32_por ((__di) m1, (__di) m2) -#define _m_pxor(m1, m2) (__m64) __builtin_ia32_pxor ((__di) m1, (__di) m2) -#else -typedef int __m64 __attribute__ ((__vector_size__ (8))); -typedef short __m64_16 __attribute__ ((__vector_size__ (8))); -#define _m_paddsw(m1, m2) (__m64) __builtin_ia32_paddsw ((__m64_16) m1, (__m64_16) m2) -#define _m_pand(m1, m2) __builtin_ia32_pand (m1, m2) -#define _m_pandn(m1, m2) __builtin_ia32_pandn (m1, m2) -#define _m_pmaddwd(m1, m2) __builtin_ia32_pmaddwd ((__m64_16) m1, (__m64_16) m2) -#define _m_por(m1, m2) __builtin_ia32_por (m1, m2) -#define _m_pxor(m1, m2) __builtin_ia32_pxor (m1, m2) -#endif - -#define _m_paddd(m1, m2) __builtin_ia32_paddd (m1, m2) -#define _m_pcmpeqd(m1, m2) __builtin_ia32_pcmpeqd (m1, m2) -#define _m_pslldi(m1, m2) __builtin_ia32_pslld (m1, m2) -#define _m_psradi(m1, m2) __builtin_ia32_psrad (m1, m2) -#define _m_psrldi(m1, m2) __builtin_ia32_psrld (m1, m2) -#define _m_psubd(m1, m2) __builtin_ia32_psubd (m1, m2) -#define _m_punpckhdq(m1, m2) __builtin_ia32_punpckhdq (m1, m2) -#define _m_punpckldq(m1, m2) __builtin_ia32_punpckldq (m1, m2) -#define _mm_empty() __builtin_ia32_emms () -#define _mm_set_pi32(m1, m2) { m2, m1 } -#define _mm_set1_pi32(m) { m, m } - -#else -#include -#endif - -#endif //OPT_MMX - -#endif diff --git a/wavpack-4.5.0/src/wavpack_version.h b/wavpack-4.5.0/src/wavpack_version.h deleted file mode 100644 index 27e930d..0000000 --- a/wavpack-4.5.0/src/wavpack_version.h +++ /dev/null @@ -1,19 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// **** WAVPACK **** // -// Hybrid Lossless Wavefile Compressor // -// Copyright (c) 1998 - 2006 Conifer Software. // -// All Rights Reserved. // -// Distributed under the BSD Software License (see license.txt) // -//////////////////////////////////////////////////////////////////////////// - -// wavpack_version.h - -#ifndef WAVPACK_VERSION_H -#define WAVPACK_VERSION_H - -#define LIBWAVPACK_MAJOR 4 -#define LIBWAVPACK_MINOR 50 -#define LIBWAVPACK_MICRO 0 -#define LIBWAVPACK_VERSION_STRING "4.50.0" - -#endif diff --git a/wavpack-4.5.0/src/words.c b/wavpack-4.5.0/src/words.c deleted file mode 100644 index 600a011..0000000 --- a/wavpack-4.5.0/src/words.c +++ /dev/null @@ -1,1468 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// **** WAVPACK **** // -// Hybrid Lossless Wavefile Compressor // -// Copyright (c) 1998 - 2006 Conifer Software. // -// All Rights Reserved. // -//////////////////////////////////////////////////////////////////////////// - -// words.c - -// This module provides entropy word encoding and decoding functions using -// a variation on the Rice method. This was introduced in version 3.93 -// because it allows splitting the data into a "lossy" stream and a -// "correction" stream in a very efficient manner and is therefore ideal -// for the "hybrid" mode. For 4.0, the efficiency of this method was -// significantly improved by moving away from the normal Rice restriction of -// using powers of two for the modulus divisions and now the method can be -// used for both hybrid and pure lossless encoding. - -// Samples are divided by median probabilities at 5/7 (71.43%), 10/49 (20.41%), -// and 20/343 (5.83%). Each zone has 3.5 times fewer samples than the -// previous. Using standard Rice coding on this data would result in 1.4 -// bits per sample average (not counting sign bit). However, there is a -// very simple encoding that is over 99% efficient with this data and -// results in about 1.22 bits per sample. - -#include "wavpack_local.h" - -#include -#include - -#ifdef DEBUG_ALLOC -#define malloc malloc_db -#define realloc realloc_db -#define free free_db -void *malloc_db (uint32_t size); -void *realloc_db (void *ptr, uint32_t size); -void free_db (void *ptr); -int32_t dump_alloc (void); -#endif - -//////////////////////////////// local macros ///////////////////////////////// - -#define LIMIT_ONES 16 // maximum consecutive 1s sent for "div" data - -// these control the time constant "slow_level" which is used for hybrid mode -// that controls bitrate as a function of residual level (HYBRID_BITRATE). -#define SLS 8 -#define SLO ((1 << (SLS - 1))) - -// these control the time constant of the 3 median level breakpoints -#define DIV0 128 // 5/7 of samples -#define DIV1 64 // 10/49 of samples -#define DIV2 32 // 20/343 of samples - -// this macro retrieves the specified median breakpoint (without frac; min = 1) -#define GET_MED(med) (((c->median [med]) >> 4) + 1) - -// These macros update the specified median breakpoints. Note that the median -// is incremented when the sample is higher than the median, else decremented. -// They are designed so that the median will never drop below 1 and the value -// is essentially stationary if there are 2 increments for every 5 decrements. - -#define INC_MED0() (c->median [0] += ((c->median [0] + DIV0) / DIV0) * 5) -#define DEC_MED0() (c->median [0] -= ((c->median [0] + (DIV0-2)) / DIV0) * 2) -#define INC_MED1() (c->median [1] += ((c->median [1] + DIV1) / DIV1) * 5) -#define DEC_MED1() (c->median [1] -= ((c->median [1] + (DIV1-2)) / DIV1) * 2) -#define INC_MED2() (c->median [2] += ((c->median [2] + DIV2) / DIV2) * 5) -#define DEC_MED2() (c->median [2] -= ((c->median [2] + (DIV2-2)) / DIV2) * 2) - -#define count_bits(av) ( \ - (av) < (1 << 8) ? nbits_table [av] : \ - ( \ - (av) < (1L << 16) ? nbits_table [(av) >> 8] + 8 : \ - ((av) < (1L << 24) ? nbits_table [(av) >> 16] + 16 : nbits_table [(av) >> 24] + 24) \ - ) \ -) - -///////////////////////////// local table storage //////////////////////////// - -const uint32_t bitset [] = { - 1L << 0, 1L << 1, 1L << 2, 1L << 3, - 1L << 4, 1L << 5, 1L << 6, 1L << 7, - 1L << 8, 1L << 9, 1L << 10, 1L << 11, - 1L << 12, 1L << 13, 1L << 14, 1L << 15, - 1L << 16, 1L << 17, 1L << 18, 1L << 19, - 1L << 20, 1L << 21, 1L << 22, 1L << 23, - 1L << 24, 1L << 25, 1L << 26, 1L << 27, - 1L << 28, 1L << 29, 1L << 30, 1L << 31 -}; - -const uint32_t bitmask [] = { - (1L << 0) - 1, (1L << 1) - 1, (1L << 2) - 1, (1L << 3) - 1, - (1L << 4) - 1, (1L << 5) - 1, (1L << 6) - 1, (1L << 7) - 1, - (1L << 8) - 1, (1L << 9) - 1, (1L << 10) - 1, (1L << 11) - 1, - (1L << 12) - 1, (1L << 13) - 1, (1L << 14) - 1, (1L << 15) - 1, - (1L << 16) - 1, (1L << 17) - 1, (1L << 18) - 1, (1L << 19) - 1, - (1L << 20) - 1, (1L << 21) - 1, (1L << 22) - 1, (1L << 23) - 1, - (1L << 24) - 1, (1L << 25) - 1, (1L << 26) - 1, (1L << 27) - 1, - (1L << 28) - 1, (1L << 29) - 1, (1L << 30) - 1, 0x7fffffff -}; - -const char nbits_table [] = { - 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, // 0 - 15 - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, // 16 - 31 - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, // 32 - 47 - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, // 48 - 63 - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // 64 - 79 - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // 80 - 95 - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // 96 - 111 - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // 112 - 127 - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, // 128 - 143 - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, // 144 - 159 - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, // 160 - 175 - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, // 176 - 191 - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, // 192 - 207 - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, // 208 - 223 - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, // 224 - 239 - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 // 240 - 255 -}; - -static const uchar log2_table [] = { - 0x00, 0x01, 0x03, 0x04, 0x06, 0x07, 0x09, 0x0a, 0x0b, 0x0d, 0x0e, 0x10, 0x11, 0x12, 0x14, 0x15, - 0x16, 0x18, 0x19, 0x1a, 0x1c, 0x1d, 0x1e, 0x20, 0x21, 0x22, 0x24, 0x25, 0x26, 0x28, 0x29, 0x2a, - 0x2c, 0x2d, 0x2e, 0x2f, 0x31, 0x32, 0x33, 0x34, 0x36, 0x37, 0x38, 0x39, 0x3b, 0x3c, 0x3d, 0x3e, - 0x3f, 0x41, 0x42, 0x43, 0x44, 0x45, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4d, 0x4e, 0x4f, 0x50, 0x51, - 0x52, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63, - 0x64, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x74, 0x75, - 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, - 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, - 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, - 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb2, - 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc0, - 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcb, 0xcc, 0xcd, 0xce, - 0xcf, 0xd0, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd8, 0xd9, 0xda, 0xdb, - 0xdc, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe4, 0xe5, 0xe6, 0xe7, 0xe7, - 0xe8, 0xe9, 0xea, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xee, 0xef, 0xf0, 0xf1, 0xf1, 0xf2, 0xf3, 0xf4, - 0xf4, 0xf5, 0xf6, 0xf7, 0xf7, 0xf8, 0xf9, 0xf9, 0xfa, 0xfb, 0xfc, 0xfc, 0xfd, 0xfe, 0xff, 0xff -}; - -static const uchar exp2_table [] = { - 0x00, 0x01, 0x01, 0x02, 0x03, 0x03, 0x04, 0x05, 0x06, 0x06, 0x07, 0x08, 0x08, 0x09, 0x0a, 0x0b, - 0x0b, 0x0c, 0x0d, 0x0e, 0x0e, 0x0f, 0x10, 0x10, 0x11, 0x12, 0x13, 0x13, 0x14, 0x15, 0x16, 0x16, - 0x17, 0x18, 0x19, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1d, 0x1e, 0x1f, 0x20, 0x20, 0x21, 0x22, 0x23, - 0x24, 0x24, 0x25, 0x26, 0x27, 0x28, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3a, 0x3b, 0x3c, 0x3d, - 0x3e, 0x3f, 0x40, 0x41, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x48, 0x49, 0x4a, 0x4b, - 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, - 0x5b, 0x5c, 0x5d, 0x5e, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, - 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, - 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x87, 0x88, 0x89, 0x8a, - 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, - 0x9c, 0x9d, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, - 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, - 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc8, 0xc9, 0xca, 0xcb, 0xcd, 0xce, 0xcf, 0xd0, 0xd2, 0xd3, 0xd4, - 0xd6, 0xd7, 0xd8, 0xd9, 0xdb, 0xdc, 0xdd, 0xde, 0xe0, 0xe1, 0xe2, 0xe4, 0xe5, 0xe6, 0xe8, 0xe9, - 0xea, 0xec, 0xed, 0xee, 0xf0, 0xf1, 0xf2, 0xf4, 0xf5, 0xf6, 0xf8, 0xf9, 0xfa, 0xfc, 0xfd, 0xff -}; - -static const char ones_count_table [] = { - 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5, - 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6, - 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5, - 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,7, - 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5, - 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6, - 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5, - 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,8 -}; - -///////////////////////////// executable code //////////////////////////////// - -static int FASTCALL mylog2 (uint32_t avalue); - -// Initialize entropy encoder for the specified stream. In lossless mode there -// are no parameters to select; in hybrid mode the bitrate mode and value need -// be initialized. - -#ifndef NO_PACK - -void init_words (WavpackStream *wps) -{ - CLEAR (wps->w); - - if (wps->wphdr.flags & HYBRID_FLAG) - word_set_bitrate (wps); -} - -// Set up parameters for hybrid mode based on header flags and "bits" field. -// This is currently only set up for the HYBRID_BITRATE mode in which the -// allowed error varies with the residual level (from "slow_level"). The -// simpler mode (which is not used yet) has the error level directly -// controlled from the metadata. - -void word_set_bitrate (WavpackStream *wps) -{ - int bitrate_0, bitrate_1; - - if (wps->wphdr.flags & HYBRID_BITRATE) { - if (wps->wphdr.flags & FALSE_STEREO) - bitrate_0 = (wps->bits * 2 - 512) < 568 ? 0 : (wps->bits * 2 - 512) - 568; - else - bitrate_0 = wps->bits < 568 ? 0 : wps->bits - 568; - - if (!(wps->wphdr.flags & MONO_DATA)) { - - if (wps->wphdr.flags & HYBRID_BALANCE) - bitrate_1 = (wps->wphdr.flags & JOINT_STEREO) ? 256 : 0; - else { - bitrate_1 = bitrate_0; - - if (wps->wphdr.flags & JOINT_STEREO) { - if (bitrate_0 < 128) { - bitrate_1 += bitrate_0; - bitrate_0 = 0; - } - else { - bitrate_0 -= 128; - bitrate_1 += 128; - } - } - } - } - else - bitrate_1 = 0; - } - else - bitrate_0 = bitrate_1 = 0; - - wps->w.bitrate_acc [0] = (int32_t) bitrate_0 << 16; - wps->w.bitrate_acc [1] = (int32_t) bitrate_1 << 16; -} - -// Allocates the correct space in the metadata structure and writes the -// current median values to it. Values are converted from 32-bit unsigned -// to our internal 16-bit mylog2 values, and read_entropy_vars () is called -// to read the values back because we must compensate for the loss through -// the log function. - -void write_entropy_vars (WavpackStream *wps, WavpackMetadata *wpmd) -{ - uchar *byteptr; - int temp; - - byteptr = wpmd->data = malloc (12); - wpmd->id = ID_ENTROPY_VARS; - - *byteptr++ = temp = mylog2 (wps->w.c [0].median [0]); - *byteptr++ = temp >> 8; - *byteptr++ = temp = mylog2 (wps->w.c [0].median [1]); - *byteptr++ = temp >> 8; - *byteptr++ = temp = mylog2 (wps->w.c [0].median [2]); - *byteptr++ = temp >> 8; - - if (!(wps->wphdr.flags & MONO_DATA)) { - *byteptr++ = temp = mylog2 (wps->w.c [1].median [0]); - *byteptr++ = temp >> 8; - *byteptr++ = temp = mylog2 (wps->w.c [1].median [1]); - *byteptr++ = temp >> 8; - *byteptr++ = temp = mylog2 (wps->w.c [1].median [2]); - *byteptr++ = temp >> 8; - } - - wpmd->byte_length = (int32_t)(byteptr - (uchar *) wpmd->data); - read_entropy_vars (wps, wpmd); -} - -// Allocates enough space in the metadata structure and writes the current -// high word of the bitrate accumulator and the slow_level values to it. The -// slow_level values are converted from 32-bit unsigned to our internal 16-bit -// mylog2 values. Afterward, read_entropy_vars () is called to read the values -// back because we must compensate for the loss through the log function and -// the truncation of the bitrate. - -void write_hybrid_profile (WavpackStream *wps, WavpackMetadata *wpmd) -{ - uchar *byteptr; - int temp; - - word_set_bitrate (wps); - byteptr = wpmd->data = malloc (512); - wpmd->id = ID_HYBRID_PROFILE; - - if (wps->wphdr.flags & HYBRID_BITRATE) { - *byteptr++ = temp = log2s (wps->w.c [0].slow_level); - *byteptr++ = temp >> 8; - - if (!(wps->wphdr.flags & MONO_DATA)) { - *byteptr++ = temp = log2s (wps->w.c [1].slow_level); - *byteptr++ = temp >> 8; - } - } - - *byteptr++ = temp = wps->w.bitrate_acc [0] >> 16; - *byteptr++ = temp >> 8; - - if (!(wps->wphdr.flags & MONO_DATA)) { - *byteptr++ = temp = wps->w.bitrate_acc [1] >> 16; - *byteptr++ = temp >> 8; - } - - if (wps->w.bitrate_delta [0] | wps->w.bitrate_delta [1]) { - *byteptr++ = temp = log2s (wps->w.bitrate_delta [0]); - *byteptr++ = temp >> 8; - - if (!(wps->wphdr.flags & MONO_DATA)) { - *byteptr++ = temp = log2s (wps->w.bitrate_delta [1]); - *byteptr++ = temp >> 8; - } - } - - wpmd->byte_length = (int32_t)(byteptr - (uchar *) wpmd->data); - read_hybrid_profile (wps, wpmd); -} - -#endif - -// Read the median log2 values from the specifed metadata structure, convert -// them back to 32-bit unsigned values and store them. If length is not -// exactly correct then we flag and return an error. - -int read_entropy_vars (WavpackStream *wps, WavpackMetadata *wpmd) -{ - uchar *byteptr = wpmd->data; - - if (wpmd->byte_length != ((wps->wphdr.flags & MONO_DATA) ? 6 : 12)) - return FALSE; - - wps->w.c [0].median [0] = exp2s (byteptr [0] + (byteptr [1] << 8)); - wps->w.c [0].median [1] = exp2s (byteptr [2] + (byteptr [3] << 8)); - wps->w.c [0].median [2] = exp2s (byteptr [4] + (byteptr [5] << 8)); - - if (!(wps->wphdr.flags & MONO_DATA)) { - wps->w.c [1].median [0] = exp2s (byteptr [6] + (byteptr [7] << 8)); - wps->w.c [1].median [1] = exp2s (byteptr [8] + (byteptr [9] << 8)); - wps->w.c [1].median [2] = exp2s (byteptr [10] + (byteptr [11] << 8)); - } - - return TRUE; -} - -// Read the hybrid related values from the specifed metadata structure, convert -// them back to their internal formats and store them. The extended profile -// stuff is not implemented yet, so return an error if we get more data than -// we know what to do with. - -int read_hybrid_profile (WavpackStream *wps, WavpackMetadata *wpmd) -{ - uchar *byteptr = wpmd->data; - uchar *endptr = byteptr + wpmd->byte_length; - - if (wps->wphdr.flags & HYBRID_BITRATE) { - if (byteptr + (wps->wphdr.flags & MONO_DATA ? 2 : 4) > endptr) - return FALSE; - - wps->w.c [0].slow_level = exp2s (byteptr [0] + (byteptr [1] << 8)); - byteptr += 2; - - if (!(wps->wphdr.flags & MONO_DATA)) { - wps->w.c [1].slow_level = exp2s (byteptr [0] + (byteptr [1] << 8)); - byteptr += 2; - } - } - - if (byteptr + (wps->wphdr.flags & MONO_DATA ? 2 : 4) > endptr) - return FALSE; - - wps->w.bitrate_acc [0] = (int32_t)(byteptr [0] + (byteptr [1] << 8)) << 16; - byteptr += 2; - - if (!(wps->wphdr.flags & MONO_DATA)) { - wps->w.bitrate_acc [1] = (int32_t)(byteptr [0] + (byteptr [1] << 8)) << 16; - byteptr += 2; - } - - if (byteptr < endptr) { - if (byteptr + (wps->wphdr.flags & MONO_DATA ? 2 : 4) > endptr) - return FALSE; - - wps->w.bitrate_delta [0] = exp2s ((short)(byteptr [0] + (byteptr [1] << 8))); - byteptr += 2; - - if (!(wps->wphdr.flags & MONO_DATA)) { - wps->w.bitrate_delta [1] = exp2s ((short)(byteptr [0] + (byteptr [1] << 8))); - byteptr += 2; - } - - if (byteptr < endptr) - return FALSE; - } - else - wps->w.bitrate_delta [0] = wps->w.bitrate_delta [1] = 0; - - return TRUE; -} - -// This function is called during both encoding and decoding of hybrid data to -// update the "error_limit" variable which determines the maximum sample error -// allowed in the main bitstream. In the HYBRID_BITRATE mode (which is the only -// currently implemented) this is calculated from the slow_level values and the -// bitrate accumulators. Note that the bitrate accumulators can be changing. - -static void update_error_limit (WavpackStream *wps) -{ - int bitrate_0 = (wps->w.bitrate_acc [0] += wps->w.bitrate_delta [0]) >> 16; - - if (wps->wphdr.flags & MONO_DATA) { - if (wps->wphdr.flags & HYBRID_BITRATE) { - int slow_log_0 = (wps->w.c [0].slow_level + SLO) >> SLS; - - if (slow_log_0 - bitrate_0 > -0x100) - wps->w.c [0].error_limit = exp2s (slow_log_0 - bitrate_0 + 0x100); - else - wps->w.c [0].error_limit = 0; - } - else - wps->w.c [0].error_limit = exp2s (bitrate_0); - } - else { - int bitrate_1 = (wps->w.bitrate_acc [1] += wps->w.bitrate_delta [1]) >> 16; - - if (wps->wphdr.flags & HYBRID_BITRATE) { - int slow_log_0 = (wps->w.c [0].slow_level + SLO) >> SLS; - int slow_log_1 = (wps->w.c [1].slow_level + SLO) >> SLS; - - if (wps->wphdr.flags & HYBRID_BALANCE) { - int balance = (slow_log_1 - slow_log_0 + bitrate_1 + 1) >> 1; - - if (balance > bitrate_0) { - bitrate_1 = bitrate_0 * 2; - bitrate_0 = 0; - } - else if (-balance > bitrate_0) { - bitrate_0 = bitrate_0 * 2; - bitrate_1 = 0; - } - else { - bitrate_1 = bitrate_0 + balance; - bitrate_0 = bitrate_0 - balance; - } - } - - if (slow_log_0 - bitrate_0 > -0x100) - wps->w.c [0].error_limit = exp2s (slow_log_0 - bitrate_0 + 0x100); - else - wps->w.c [0].error_limit = 0; - - if (slow_log_1 - bitrate_1 > -0x100) - wps->w.c [1].error_limit = exp2s (slow_log_1 - bitrate_1 + 0x100); - else - wps->w.c [1].error_limit = 0; - } - else { - wps->w.c [0].error_limit = exp2s (bitrate_0); - wps->w.c [1].error_limit = exp2s (bitrate_1); - } - } -} - -#ifndef NO_PACK - -// This function writes the specified word to the open bitstream "wvbits" and, -// if the bitstream "wvcbits" is open, writes any correction data there. This -// function will work for either lossless or hybrid but because a version -// optimized for lossless exits below, it would normally be used for the hybrid -// mode only. The return value is the actual value stored to the stream (even -// if a correction file is being created) and is used as feedback to the -// predictor. - -int32_t FASTCALL send_word (WavpackStream *wps, int32_t value, int chan) -{ - struct entropy_data *c = wps->w.c + chan; - uint32_t ones_count, low, mid, high; - int sign = (value < 0) ? 1 : 0; - - if (wps->w.c [0].median [0] < 2 && !wps->w.holding_zero && wps->w.c [1].median [0] < 2) { - if (wps->w.zeros_acc) { - if (value) - flush_word (wps); - else { - c->slow_level -= (c->slow_level + SLO) >> SLS; - wps->w.zeros_acc++; - return 0; - } - } - else if (value) { - putbit_0 (&wps->wvbits); - } - else { - c->slow_level -= (c->slow_level + SLO) >> SLS; - CLEAR (wps->w.c [0].median); - CLEAR (wps->w.c [1].median); - wps->w.zeros_acc = 1; - return 0; - } - } - - if (sign) - value = ~value; - - if ((wps->wphdr.flags & HYBRID_FLAG) && !chan) - update_error_limit (wps); - - if (value < (int32_t) GET_MED (0)) { - ones_count = low = 0; - high = GET_MED (0) - 1; - DEC_MED0 (); - } - else { - low = GET_MED (0); - INC_MED0 (); - - if (value - low < GET_MED (1)) { - ones_count = 1; - high = low + GET_MED (1) - 1; - DEC_MED1 (); - } - else { - low += GET_MED (1); - INC_MED1 (); - - if (value - low < GET_MED (2)) { - ones_count = 2; - high = low + GET_MED (2) - 1; - DEC_MED2 (); - } - else { - ones_count = 2 + (value - low) / GET_MED (2); - low += (ones_count - 2) * GET_MED (2); - high = low + GET_MED (2) - 1; - INC_MED2 (); - } - } - } - - mid = (high + low + 1) >> 1; - - if (wps->w.holding_zero) { - if (ones_count) - wps->w.holding_one++; - - flush_word (wps); - - if (ones_count) { - wps->w.holding_zero = 1; - ones_count--; - } - else - wps->w.holding_zero = 0; - } - else - wps->w.holding_zero = 1; - - wps->w.holding_one = ones_count * 2; - - if (!c->error_limit) { - if (high != low) { - uint32_t maxcode = high - low, code = value - low; - int bitcount = count_bits (maxcode); - uint32_t extras = bitset [bitcount] - maxcode - 1; - - if (code < extras) { - wps->w.pend_data |= code << wps->w.pend_count; - wps->w.pend_count += bitcount - 1; - } - else { - wps->w.pend_data |= ((code + extras) >> 1) << wps->w.pend_count; - wps->w.pend_count += bitcount - 1; - wps->w.pend_data |= ((code + extras) & 1) << wps->w.pend_count++; - } - } - - mid = value; - } - else - while (high - low > c->error_limit) - if (value < (int32_t) mid) { - mid = ((high = mid - 1) + low + 1) >> 1; - wps->w.pend_count++; - } - else { - mid = (high + (low = mid) + 1) >> 1; - wps->w.pend_data |= bitset [wps->w.pend_count++]; - } - - wps->w.pend_data |= ((int32_t) sign << wps->w.pend_count++); - - if (!wps->w.holding_zero) - flush_word (wps); - - if (bs_is_open (&wps->wvcbits) && c->error_limit) { - uint32_t code = value - low, maxcode = high - low; - int bitcount = count_bits (maxcode); - uint32_t extras = bitset [bitcount] - maxcode - 1; - - if (bitcount) { - if (code < extras) { - putbits (code, bitcount - 1, &wps->wvcbits); - } - else { - putbits ((code + extras) >> 1, bitcount - 1, &wps->wvcbits); - putbit ((code + extras) & 1, &wps->wvcbits); - } - } - } - - if (wps->wphdr.flags & HYBRID_BITRATE) { - c->slow_level -= (c->slow_level + SLO) >> SLS; - c->slow_level += mylog2 (mid); - } - - return sign ? ~mid : mid; -} - -// This function is an optimized version of send_word() that only handles -// lossless (error_limit == 0) and sends an entire buffer of either mono or -// stereo data rather than a single sample. Unlike the generalized -// send_word(), it does not return values because it always encodes -// the exact value passed. - -void send_words_lossless (WavpackStream *wps, int32_t *buffer, int32_t nsamples) -{ - struct entropy_data *c = wps->w.c; - int32_t value, csamples; - - if (!(wps->wphdr.flags & MONO_DATA)) - nsamples *= 2; - - for (csamples = 0; csamples < nsamples; ++csamples) { - int sign = ((value = *buffer++) < 0) ? 1 : 0; - uint32_t ones_count, low, high; - - if (!(wps->wphdr.flags & MONO_DATA)) - c = wps->w.c + (csamples & 1); - - if (wps->w.c [0].median [0] < 2 && !wps->w.holding_zero && wps->w.c [1].median [0] < 2) { - if (wps->w.zeros_acc) { - if (value) - flush_word (wps); - else { - wps->w.zeros_acc++; - continue; - } - } - else if (value) { - putbit_0 (&wps->wvbits); - } - else { - CLEAR (wps->w.c [0].median); - CLEAR (wps->w.c [1].median); - wps->w.zeros_acc = 1; - continue; - } - } - - if (sign) - value = ~value; - - if (value < (int32_t) GET_MED (0)) { - ones_count = low = 0; - high = GET_MED (0) - 1; - DEC_MED0 (); - } - else { - low = GET_MED (0); - INC_MED0 (); - - if (value - low < GET_MED (1)) { - ones_count = 1; - high = low + GET_MED (1) - 1; - DEC_MED1 (); - } - else { - low += GET_MED (1); - INC_MED1 (); - - if (value - low < GET_MED (2)) { - ones_count = 2; - high = low + GET_MED (2) - 1; - DEC_MED2 (); - } - else { - ones_count = 2 + (value - low) / GET_MED (2); - low += (ones_count - 2) * GET_MED (2); - high = low + GET_MED (2) - 1; - INC_MED2 (); - } - } - } - - if (wps->w.holding_zero) { - if (ones_count) - wps->w.holding_one++; - - flush_word (wps); - - if (ones_count) { - wps->w.holding_zero = 1; - ones_count--; - } - else - wps->w.holding_zero = 0; - } - else - wps->w.holding_zero = 1; - - wps->w.holding_one = ones_count * 2; - - if (high != low) { - uint32_t maxcode = high - low, code = value - low; - int bitcount = count_bits (maxcode); - uint32_t extras = bitset [bitcount] - maxcode - 1; - - if (code < extras) { - wps->w.pend_data |= code << wps->w.pend_count; - wps->w.pend_count += bitcount - 1; - } - else { - wps->w.pend_data |= ((code + extras) >> 1) << wps->w.pend_count; - wps->w.pend_count += bitcount - 1; - wps->w.pend_data |= ((code + extras) & 1) << wps->w.pend_count++; - } - } - - wps->w.pend_data |= ((int32_t) sign << wps->w.pend_count++); - - if (!wps->w.holding_zero) - flush_word (wps); - } -} - -// Used by send_word() and send_word_lossless() to actually send most the -// accumulated data onto the bitstream. This is also called directly from -// clients when all words have been sent. - -void flush_word (WavpackStream *wps) -{ - if (wps->w.zeros_acc) { - int cbits = count_bits (wps->w.zeros_acc); - - while (cbits--) { - putbit_1 (&wps->wvbits); - } - - putbit_0 (&wps->wvbits); - - while (wps->w.zeros_acc > 1) { - putbit (wps->w.zeros_acc & 1, &wps->wvbits); - wps->w.zeros_acc >>= 1; - } - - wps->w.zeros_acc = 0; - } - - if (wps->w.holding_one) { -#ifdef LIMIT_ONES - if (wps->w.holding_one >= LIMIT_ONES) { - int cbits; - - putbits ((1L << LIMIT_ONES) - 1, LIMIT_ONES + 1, &wps->wvbits); - wps->w.holding_one -= LIMIT_ONES; - cbits = count_bits (wps->w.holding_one); - - while (cbits--) { - putbit_1 (&wps->wvbits); - } - - putbit_0 (&wps->wvbits); - - while (wps->w.holding_one > 1) { - putbit (wps->w.holding_one & 1, &wps->wvbits); - wps->w.holding_one >>= 1; - } - - wps->w.holding_zero = 0; - } - else - putbits (bitmask [wps->w.holding_one], wps->w.holding_one, &wps->wvbits); - - wps->w.holding_one = 0; -#else - do { - putbit_1 (&wps->wvbits); - } while (--wps->w.holding_one); -#endif - } - - if (wps->w.holding_zero) { - putbit_0 (&wps->wvbits); - wps->w.holding_zero = 0; - } - - if (wps->w.pend_count) { - putbits (wps->w.pend_data, wps->w.pend_count, &wps->wvbits); - wps->w.pend_data = wps->w.pend_count = 0; - } -} - -// This function is similar to send_word() except that no data is actually -// written to any stream, but it does return the value that would have been -// sent to a hybrid stream. It is used to determine beforehand how much noise -// will be added to samples. - -int32_t nosend_word (WavpackStream *wps, int32_t value, int chan) -{ - struct entropy_data *c = wps->w.c + chan; - uint32_t ones_count, low, mid, high; - int sign = (value < 0) ? 1 : 0; - - if (sign) - value = ~value; - - if ((wps->wphdr.flags & HYBRID_FLAG) && !chan) - update_error_limit (wps); - - if (value < (int32_t) GET_MED (0)) { - low = 0; - high = GET_MED (0) - 1; - DEC_MED0 (); - } - else { - low = GET_MED (0); - INC_MED0 (); - - if (value - low < GET_MED (1)) { - high = low + GET_MED (1) - 1; - DEC_MED1 (); - } - else { - low += GET_MED (1); - INC_MED1 (); - - if (value - low < GET_MED (2)) { - high = low + GET_MED (2) - 1; - DEC_MED2 (); - } - else { - ones_count = 2 + (value - low) / GET_MED (2); - low += (ones_count - 2) * GET_MED (2); - high = low + GET_MED (2) - 1; - INC_MED2 (); - } - } - } - - mid = (high + low + 1) >> 1; - - if (!c->error_limit) - mid = value; - else - while (high - low > c->error_limit) - if (value < (int32_t) mid) - mid = ((high = mid - 1) + low + 1) >> 1; - else - mid = (high + (low = mid) + 1) >> 1; - - c->slow_level -= (c->slow_level + SLO) >> SLS; - c->slow_level += mylog2 (mid); - - return sign ? ~mid : mid; -} - -// This function is used to scan some number of samples to set the variables -// "slow_level" and the "median" array. In pure symetrical encoding mode this -// would not be needed because these values would simply be continued from the -// previous block. However, in the -X modes and the 32-bit modes we cannot do -// this because parameters may change between blocks and the variables might -// not apply. This function can work in mono or stereo and can scan a block -// in either direction. - -void scan_word (WavpackStream *wps, int32_t *samples, uint32_t num_samples, int dir) -{ - uint32_t flags = wps->wphdr.flags, value, low; - struct entropy_data *c = wps->w.c; - int chan; - - init_words (wps); - - if (flags & MONO_DATA) { - if (dir < 0) { - samples += (num_samples - 1); - dir = -1; - } - else - dir = 1; - } - else { - if (dir < 0) { - samples += (num_samples - 1) * 2; - dir = -2; - } - else - dir = 2; - } - - while (num_samples--) { - - value = labs (samples [chan = 0]); - - if (flags & HYBRID_BITRATE) { - wps->w.c [0].slow_level -= (wps->w.c [0].slow_level + SLO) >> SLS; - wps->w.c [0].slow_level += mylog2 (value); - } - - if (value < GET_MED (0)) { - DEC_MED0 (); - } - else { - low = GET_MED (0); - INC_MED0 (); - - if (value - low < GET_MED (1)) { - DEC_MED1 (); - } - else { - low += GET_MED (1); - INC_MED1 (); - - if (value - low < GET_MED (2)) { - DEC_MED2 (); - } - else { - INC_MED2 (); - } - } - } - - if (!(flags & MONO_DATA)) { - value = labs (samples [chan = 1]); - c++; - - if (wps->wphdr.flags & HYBRID_BITRATE) { - wps->w.c [1].slow_level -= (wps->w.c [1].slow_level + SLO) >> SLS; - wps->w.c [1].slow_level += mylog2 (value); - } - - if (value < GET_MED (0)) { - DEC_MED0 (); - } - else { - low = GET_MED (0); - INC_MED0 (); - - if (value - low < GET_MED (1)) { - DEC_MED1 (); - } - else { - low += GET_MED (1); - INC_MED1 (); - - if (value - low < GET_MED (2)) { - DEC_MED2 (); - } - else { - INC_MED2 (); - } - } - } - - c--; - } - - samples += dir; - } -} - -#endif - -#ifndef NO_UNPACK - -static uint32_t FASTCALL read_code (Bitstream *bs, uint32_t maxcode); - -// Read the next word from the bitstream "wvbits" and return the value. This -// function can be used for hybrid or lossless streams, but since an -// optimized version is available for lossless this function would normally -// be used for hybrid only. If a hybrid lossless stream is being read then -// the "correction" offset is written at the specified pointer. A return value -// of WORD_EOF indicates that the end of the bitstream was reached (all 1s) or -// some other error occurred. - -int32_t FASTCALL get_word (WavpackStream *wps, int chan, int32_t *correction) -{ - register struct entropy_data *c = wps->w.c + chan; - uint32_t ones_count, low, mid, high; - int next8, sign; - int32_t value; - - if (correction) - *correction = 0; - - if (!(wps->w.c [0].median [0] & ~1) && !wps->w.holding_zero && !wps->w.holding_one && !(wps->w.c [1].median [0] & ~1)) { - uint32_t mask; - int cbits; - - if (wps->w.zeros_acc) { - if (--wps->w.zeros_acc) { - c->slow_level -= (c->slow_level + SLO) >> SLS; - return 0; - } - } - else { - for (cbits = 0; cbits < 33 && getbit (&wps->wvbits); ++cbits); - - if (cbits == 33) - return WORD_EOF; - - if (cbits < 2) - wps->w.zeros_acc = cbits; - else { - for (mask = 1, wps->w.zeros_acc = 0; --cbits; mask <<= 1) - if (getbit (&wps->wvbits)) - wps->w.zeros_acc |= mask; - - wps->w.zeros_acc |= mask; - } - - if (wps->w.zeros_acc) { - c->slow_level -= (c->slow_level + SLO) >> SLS; - CLEAR (wps->w.c [0].median); - CLEAR (wps->w.c [1].median); - return 0; - } - } - } - - if (wps->w.holding_zero) - ones_count = wps->w.holding_zero = 0; - else { - if (wps->wvbits.bc < 8) { - if (++(wps->wvbits.ptr) == wps->wvbits.end) - wps->wvbits.wrap (&wps->wvbits); - - next8 = (wps->wvbits.sr |= *(wps->wvbits.ptr) << wps->wvbits.bc) & 0xff; - wps->wvbits.bc += sizeof (*(wps->wvbits.ptr)) * 8; - } - else - next8 = wps->wvbits.sr & 0xff; - - if (next8 == 0xff) { - wps->wvbits.bc -= 8; - wps->wvbits.sr >>= 8; - - for (ones_count = 8; ones_count < (LIMIT_ONES + 1) && getbit (&wps->wvbits); ++ones_count); - - if (ones_count == (LIMIT_ONES + 1)) - return WORD_EOF; - - if (ones_count == LIMIT_ONES) { - uint32_t mask; - int cbits; - - for (cbits = 0; cbits < 33 && getbit (&wps->wvbits); ++cbits); - - if (cbits == 33) - return WORD_EOF; - - if (cbits < 2) - ones_count = cbits; - else { - for (mask = 1, ones_count = 0; --cbits; mask <<= 1) - if (getbit (&wps->wvbits)) - ones_count |= mask; - - ones_count |= mask; - } - - ones_count += LIMIT_ONES; - } - } - else { - wps->wvbits.bc -= (ones_count = ones_count_table [next8]) + 1; - wps->wvbits.sr >>= ones_count + 1; - } - - if (wps->w.holding_one) { - wps->w.holding_one = ones_count & 1; - ones_count = (ones_count >> 1) + 1; - } - else { - wps->w.holding_one = ones_count & 1; - ones_count >>= 1; - } - - wps->w.holding_zero = ~wps->w.holding_one & 1; - } - - if ((wps->wphdr.flags & HYBRID_FLAG) && !chan) - update_error_limit (wps); - - if (ones_count == 0) { - low = 0; - high = GET_MED (0) - 1; - DEC_MED0 (); - } - else { - low = GET_MED (0); - INC_MED0 (); - - if (ones_count == 1) { - high = low + GET_MED (1) - 1; - DEC_MED1 (); - } - else { - low += GET_MED (1); - INC_MED1 (); - - if (ones_count == 2) { - high = low + GET_MED (2) - 1; - DEC_MED2 (); - } - else { - low += (ones_count - 2) * GET_MED (2); - high = low + GET_MED (2) - 1; - INC_MED2 (); - } - } - } - - low &= 0x7fffffff; - high &= 0x7fffffff; - mid = (high + low + 1) >> 1; - - if (!c->error_limit) - mid = read_code (&wps->wvbits, high - low) + low; - else while (high - low > c->error_limit) { - if (getbit (&wps->wvbits)) - mid = (high + (low = mid) + 1) >> 1; - else - mid = ((high = mid - 1) + low + 1) >> 1; - } - - sign = getbit (&wps->wvbits); - - if (bs_is_open (&wps->wvcbits) && c->error_limit) { - value = read_code (&wps->wvcbits, high - low) + low; - - if (correction) - *correction = sign ? (mid - value) : (value - mid); - } - - if (wps->wphdr.flags & HYBRID_BITRATE) { - c->slow_level -= (c->slow_level + SLO) >> SLS; - c->slow_level += mylog2 (mid); - } - - return sign ? ~mid : mid; -} - -// This is an optimized version of get_word() that is used for lossless only -// (error_limit == 0). Also, rather than obtaining a single sample, it can be -// used to obtain an entire buffer of either mono or stereo samples. - -int32_t get_words_lossless (WavpackStream *wps, int32_t *buffer, int32_t nsamples) -{ - struct entropy_data *c = wps->w.c; - uint32_t ones_count, low, high; - Bitstream *bs = &wps->wvbits; - int32_t csamples; - - if (!(wps->wphdr.flags & MONO_DATA)) - nsamples *= 2; - - for (csamples = 0; csamples < nsamples; ++csamples) { - if (!(wps->wphdr.flags & MONO_DATA)) - c = wps->w.c + (csamples & 1); - - if (wps->w.c [0].median [0] < 2 && !wps->w.holding_zero && !wps->w.holding_one && wps->w.c [1].median [0] < 2) { - uint32_t mask; - int cbits; - - if (wps->w.zeros_acc) { - if (--wps->w.zeros_acc) { - *buffer++ = 0; - continue; - } - } - else { - for (cbits = 0; cbits < 33 && getbit (bs); ++cbits); - - if (cbits == 33) - break; - - if (cbits < 2) - wps->w.zeros_acc = cbits; - else { - for (mask = 1, wps->w.zeros_acc = 0; --cbits; mask <<= 1) - if (getbit (bs)) - wps->w.zeros_acc |= mask; - - wps->w.zeros_acc |= mask; - } - - if (wps->w.zeros_acc) { - CLEAR (wps->w.c [0].median); - CLEAR (wps->w.c [1].median); - *buffer++ = 0; - continue; - } - } - } - - if (wps->w.holding_zero) - ones_count = wps->w.holding_zero = 0; - else { - int next8; - - if (bs->bc < 8) { - if (++(bs->ptr) == bs->end) - bs->wrap (bs); - - next8 = (bs->sr |= *(bs->ptr) << bs->bc) & 0xff; - bs->bc += sizeof (*(bs->ptr)) * 8; - } - else - next8 = bs->sr & 0xff; - - if (next8 == 0xff) { - bs->bc -= 8; - bs->sr >>= 8; - - for (ones_count = 8; ones_count < (LIMIT_ONES + 1) && getbit (bs); ++ones_count); - - if (ones_count == (LIMIT_ONES + 1)) - break; - - if (ones_count == LIMIT_ONES) { - uint32_t mask; - int cbits; - - for (cbits = 0; cbits < 33 && getbit (bs); ++cbits); - - if (cbits == 33) - break; - - if (cbits < 2) - ones_count = cbits; - else { - for (mask = 1, ones_count = 0; --cbits; mask <<= 1) - if (getbit (bs)) - ones_count |= mask; - - ones_count |= mask; - } - - ones_count += LIMIT_ONES; - } - } - else { - bs->bc -= (ones_count = ones_count_table [next8]) + 1; - bs->sr >>= ones_count + 1; - } - - if (wps->w.holding_one) { - wps->w.holding_one = ones_count & 1; - ones_count = (ones_count >> 1) + 1; - } - else { - wps->w.holding_one = ones_count & 1; - ones_count >>= 1; - } - - wps->w.holding_zero = ~wps->w.holding_one & 1; - } - - if (ones_count == 0) { - low = 0; - high = GET_MED (0) - 1; - DEC_MED0 (); - } - else { - low = GET_MED (0); - INC_MED0 (); - - if (ones_count == 1) { - high = low + GET_MED (1) - 1; - DEC_MED1 (); - } - else { - low += GET_MED (1); - INC_MED1 (); - - if (ones_count == 2) { - high = low + GET_MED (2) - 1; - DEC_MED2 (); - } - else { - low += (ones_count - 2) * GET_MED (2); - high = low + GET_MED (2) - 1; - INC_MED2 (); - } - } - } - - low += read_code (bs, high - low); - *buffer++ = (getbit (bs)) ? ~low : low; - } - - return (wps->wphdr.flags & MONO_DATA) ? csamples : (csamples / 2); -} - -// Read a single unsigned value from the specified bitstream with a value -// from 0 to maxcode. If there are exactly a power of two number of possible -// codes then this will read a fixed number of bits; otherwise it reads the -// minimum number of bits and then determines whether another bit is needed -// to define the code. - -static uint32_t FASTCALL read_code (Bitstream *bs, uint32_t maxcode) -{ - uint32_t extras, code; - int bitcount; - - if (maxcode < 2) - return maxcode ? getbit (bs) : 0; - - bitcount = count_bits (maxcode); - extras = bitset [bitcount] - maxcode - 1; - - while (bs->bc < bitcount) { - if (++(bs->ptr) == bs->end) - bs->wrap (bs); - - bs->sr |= *(bs->ptr) << bs->bc; - bs->bc += sizeof (*(bs->ptr)) * 8; - } - - if ((code = bs->sr & bitmask [bitcount - 1]) >= extras) - code = (code << 1) - extras + ((bs->sr >> (bitcount - 1)) & 1); - else - bitcount--; - - if (bs->bc > 32) { - bs->bc -= bitcount; - bs->sr = *(bs->ptr) >> (sizeof (*(bs->ptr)) * 8 - bs->bc); - } - else { - bs->sr >>= bitcount; - bs->bc -= bitcount; - } - - return code; -} - -#endif - -// The concept of a base 2 logarithm is used in many parts of WavPack. It is -// a way of sufficiently accurately representing 32-bit signed and unsigned -// values storing only 16 bits (actually fewer). It is also used in the hybrid -// mode for quickly comparing the relative magnitude of large values (i.e. -// division) and providing smooth exponentials using only addition. - -// These are not strict logarithms in that they become linear around zero and -// can therefore represent both zero and negative values. They have 8 bits -// of precision and in "roundtrip" conversions the total error never exceeds 1 -// part in 225 except for the cases of +/-115 and +/-195 (which error by 1). - - -// This function returns the log2 for the specified 32-bit unsigned value. -// The maximum value allowed is about 0xff800000 and returns 8447. - -static int FASTCALL mylog2 (uint32_t avalue) -{ - int dbits; - - if ((avalue += avalue >> 9) < (1 << 8)) { - dbits = nbits_table [avalue]; - return (dbits << 8) + log2_table [(avalue << (9 - dbits)) & 0xff]; - } - else { - if (avalue < (1L << 16)) - dbits = nbits_table [avalue >> 8] + 8; - else if (avalue < (1L << 24)) - dbits = nbits_table [avalue >> 16] + 16; - else - dbits = nbits_table [avalue >> 24] + 24; - - return (dbits << 8) + log2_table [(avalue >> (dbits - 9)) & 0xff]; - } -} - -// This function scans a buffer of longs and accumulates the total log2 value -// of all the samples. This is useful for determining maximum compression -// because the bitstream storage required for entropy coding is proportional -// to the base 2 log of the samples. - -uint32_t log2buffer (int32_t *samples, uint32_t num_samples, int limit) -{ - uint32_t result = 0, avalue; - int dbits; - - while (num_samples--) { - avalue = abs (*samples++); - - if ((avalue += avalue >> 9) < (1 << 8)) { - dbits = nbits_table [avalue]; - result += (dbits << 8) + log2_table [(avalue << (9 - dbits)) & 0xff]; - } - else { - if (avalue < (1L << 16)) - dbits = nbits_table [avalue >> 8] + 8; - else if (avalue < (1L << 24)) - dbits = nbits_table [avalue >> 16] + 16; - else - dbits = nbits_table [avalue >> 24] + 24; - - result += dbits = (dbits << 8) + log2_table [(avalue >> (dbits - 9)) & 0xff]; - - if (limit && dbits >= limit) - return (uint32_t) -1; - } - } - - return result; -} - -// This function returns the log2 for the specified 32-bit signed value. -// All input values are valid and the return values are in the range of -// +/- 8192. - -int log2s (int32_t value) -{ - return (value < 0) ? -mylog2 (-value) : mylog2 (value); -} - -// This function returns the original integer represented by the supplied -// logarithm (at least within the provided accuracy). The log is signed, -// but since a full 32-bit value is returned this can be used for unsigned -// conversions as well (i.e. the input range is -8192 to +8447). - -int32_t exp2s (int log) -{ - uint32_t value; - - if (log < 0) - return -exp2s (-log); - - value = exp2_table [log & 0xff] | 0x100; - - if ((log >>= 8) <= 9) - return value >> (9 - log); - else - return value << (log - 9); -} - -// These two functions convert internal weights (which are normally +/-1024) -// to and from an 8-bit signed character version for storage in metadata. The -// weights are clipped here in the case that they are outside that range. - -signed char store_weight (int weight) -{ - if (weight > 1024) - weight = 1024; - else if (weight < -1024) - weight = -1024; - - if (weight > 0) - weight -= (weight + 64) >> 7; - - return (weight + 4) >> 3; -} - -int restore_weight (signed char weight) -{ - int result; - - if ((result = (int) weight << 3) > 0) - result += (result + 64) >> 7; - - return result; -} diff --git a/wavpack-4.5.0/src/wputils.c b/wavpack-4.5.0/src/wputils.c deleted file mode 100644 index 9afecfd..0000000 --- a/wavpack-4.5.0/src/wputils.c +++ /dev/null @@ -1,2928 +0,0 @@ -//////////////////////////////////////////////////////////////////////////// -// **** WAVPACK **** // -// Hybrid Lossless Wavefile Compressor // -// Copyright (c) 1998 - 2006 Conifer Software. // -// All Rights Reserved. // -// Distributed under the BSD Software License (see license.txt) // -//////////////////////////////////////////////////////////////////////////// - -// wputils.c - -// This module provides a high-level interface to reading and writing WavPack -// files. WavPack input files can be opened as standard "C" streams using a -// provided filename. However, an alternate entry uses stream-reading -// callbacks to make using another file I/O method easy. Note that in this -// case the user application is responsible for finding and opening the .wvc -// file if the use of them is desired. - -// For writing WavPack files there are no I/O routines used; a callback for -// writing completed blocks is provided. - -#include -#include -#include -#include -#include - -#ifdef WIN32 -#include -#endif - -#if defined(WIN32) && !defined(__MINGW32__) -#include "wavpack_version.h" -#endif - -#include "wavpack_local.h" - -#ifdef WIN32 -#define stricmp(x,y) _stricmp(x,y) -#define fileno _fileno -#else -#define stricmp(x,y) strcasecmp(x,y) -#endif - -#ifdef DEBUG_ALLOC -#define malloc malloc_db -#define realloc realloc_db -#define free free_db -void *malloc_db (uint32_t size); -void *realloc_db (void *ptr, uint32_t size); -void free_db (void *ptr); -int32_t dump_alloc (void); -#endif - -static void free_streams (WavpackContext *wpc); - -///////////////////////////// local table storage //////////////////////////// - -static const uint32_t sample_rates [] = { 6000, 8000, 9600, 11025, 12000, 16000, 22050, - 24000, 32000, 44100, 48000, 64000, 88200, 96000, 192000 }; - -///////////////////////////// executable code //////////////////////////////// - -#ifndef NO_TAGS -static int load_tag (WavpackContext *wpc); -static int valid_tag (M_Tag *m_tag); -static void free_tag (M_Tag *m_tag); -#endif - -#if !defined(NO_UNPACK) || defined(INFO_ONLY) - -static uint32_t read_next_header (WavpackStreamReader *reader, void *id, WavpackHeader *wphdr); -static uint32_t seek_final_index (WavpackStreamReader *reader, void *id); -static int read_wvc_block (WavpackContext *wpc); - -// This code provides an interface between the reader callback mechanism that -// WavPack uses internally and the standard fstream C library. - -#ifndef NO_USE_FSTREAMS - -static int32_t read_bytes (void *id, void *data, int32_t bcount) -{ - return (int32_t) fread (data, 1, bcount, (FILE*) id); -} - -static uint32_t get_pos (void *id) -{ - return ftell ((FILE*) id); -} - -static int set_pos_abs (void *id, uint32_t pos) -{ - return fseek (id, pos, SEEK_SET); -} - -static int set_pos_rel (void *id, int32_t delta, int mode) -{ - return fseek (id, delta, mode); -} - -static int push_back_byte (void *id, int c) -{ - return ungetc (c, id); -} - -static uint32_t get_length (void *id) -{ - FILE *file = id; - struct stat statbuf; - - if (!file || fstat (fileno (file), &statbuf) || !(statbuf.st_mode & S_IFREG)) - return 0; - - return statbuf.st_size; -} - -static int can_seek (void *id) -{ - FILE *file = id; - struct stat statbuf; - - return file && !fstat (fileno (file), &statbuf) && (statbuf.st_mode & S_IFREG); -} - -static int32_t write_bytes (void *id, void *data, int32_t bcount) -{ - return (int32_t) fwrite (data, 1, bcount, (FILE*) id); -} - -static WavpackStreamReader freader = { - read_bytes, get_pos, set_pos_abs, set_pos_rel, push_back_byte, get_length, can_seek, - write_bytes -}; - -// This function attempts to open the specified WavPack file for reading. If -// this fails for any reason then an appropriate message is copied to "error" -// (which must accept 80 characters) and NULL is returned, otherwise a -// pointer to a WavpackContext structure is returned (which is used to call -// all other functions in this module). A filename beginning with "-" is -// assumed to be stdin. The "flags" argument has the following bit mask -// values to specify details of the open operation: - -// OPEN_WVC: attempt to open/read "correction" file -// OPEN_TAGS: attempt to read ID3v1 / APEv2 tags (requires seekable file) -// OPEN_WRAPPER: make audio wrapper available (i.e. RIFF) to caller -// OPEN_2CH_MAX: open only first stream of multichannel file (usually L/R) -// OPEN_NORMALIZE: normalize floating point data to +/- 1.0 (w/ offset exp) -// OPEN_STREAMING: blindly unpacks blocks w/o regard to header file position -// OPEN_EDIT_TAGS: allow editing of tags (file must be writable) - -// Version 4.2 of the WavPack library adds the OPEN_STREAMING flag. This is -// essentially a "raw" mode where the library will simply decode any blocks -// fed it through the reader callback, regardless of where those blocks came -// from in a stream. The only requirement is that complete WavPack blocks are -// fed to the decoder (and this may require multiple blocks in multichannel -// mode) and that complete blocks are decoded (even if all samples are not -// actually required). All the blocks must contain the same number of channels -// and bit resolution, and the correction data must be either present or not. -// All other parameters may change from block to block (like lossy/lossless). -// Obviously, in this mode any seeking must be performed by the application -// (and again, decoding must start at the beginning of the block containing -// the seek sample). - -WavpackContext *WavpackOpenFileInput (const wchar_t *infilename, char *error, int flags, int norm_offset) -{ - const wchar_t *file_mode = (flags & OPEN_EDIT_TAGS) ? L"r+b" : L"rb"; - FILE *wv_id, *wvc_id; - WavpackContext *wpc; - - if (*infilename == L'-') { - wv_id = stdin; -#if defined(WIN32) - _setmode (fileno (stdin), O_BINARY); -#endif - } - else if ((wv_id = _wfopen (infilename, file_mode)) == NULL) { - strcpy (error, (flags & OPEN_EDIT_TAGS) ? "can't open file for editing" : "can't open file"); - return NULL; - } - - if (wv_id != stdin && (flags & OPEN_WVC)) { - wchar_t *in2filename = malloc ((wcslen (infilename) + 10) * sizeof(wchar_t)); - - wcscpy (in2filename, infilename); - wcscat (in2filename, L"c"); - wvc_id = _wfopen (in2filename, L"rb"); - free (in2filename); - } - else - wvc_id = NULL; - - wpc = WavpackOpenFileInputEx (&freader, wv_id, wvc_id, error, flags, norm_offset); - - if (!wpc) { - if (wv_id) - fclose (wv_id); - - if (wvc_id) - fclose (wvc_id); - } - else - wpc->close_files = TRUE; - - return wpc; -} - -#endif - -// This function is identical to WavpackOpenFileInput() except that instead -// of providing a filename to open, the caller provides a pointer to a set of -// reader callbacks and instances of up to two streams. The first of these -// streams is required and contains the regular WavPack data stream; the second -// contains the "correction" file if desired. Unlike the standard open -// function which handles the correction file transparently, in this case it -// is the responsibility of the caller to be aware of correction files. - -WavpackContext *WavpackOpenFileInputEx (WavpackStreamReader *reader, void *wv_id, void *wvc_id, char *error, int flags, int norm_offset) -{ - WavpackContext *wpc = malloc (sizeof (WavpackContext)); - WavpackStream *wps; - int num_blocks = 0; - uchar first_byte; - uint32_t bcount; - - if (!wpc) { - strcpy (error, "can't allocate memory"); - return NULL; - } - - CLEAR (*wpc); - wpc->wv_in = wv_id; - wpc->wvc_in = wvc_id; - wpc->reader = reader; - wpc->total_samples = (uint32_t) -1; - wpc->norm_offset = norm_offset; - wpc->open_flags = flags; - - wpc->filelen = wpc->reader->get_length (wpc->wv_in); - -#ifndef NO_TAGS - if ((flags & (OPEN_TAGS | OPEN_EDIT_TAGS)) && wpc->reader->can_seek (wpc->wv_in)) { - load_tag (wpc); - wpc->reader->set_pos_abs (wpc->wv_in, 0); - } -#endif - -#ifndef VER4_ONLY - if (wpc->reader->read_bytes (wpc->wv_in, &first_byte, 1) != 1) { - strcpy (error, "can't read all of WavPack file!"); - return WavpackCloseFile (wpc); - } - - wpc->reader->push_back_byte (wpc->wv_in, first_byte); - - if (first_byte == 'R') - return open_file3 (wpc, error); -#endif - - wpc->streams [0] = wps = malloc (sizeof (WavpackStream)); - wpc->num_streams = 1; - CLEAR (*wps); - - while (!wps->wphdr.block_samples) { - - wpc->filepos = wpc->reader->get_pos (wpc->wv_in); - bcount = read_next_header (wpc->reader, wpc->wv_in, &wps->wphdr); - - if (bcount == (uint32_t) -1 || - (!wps->wphdr.block_samples && num_blocks++ > 16)) { - strcpy (error, "not compatible with this version of WavPack file!"); - return WavpackCloseFile (wpc); - } - - wpc->filepos += bcount; - wps->blockbuff = malloc (wps->wphdr.ckSize + 8); - memcpy (wps->blockbuff, &wps->wphdr, 32); - - if (wpc->reader->read_bytes (wpc->wv_in, wps->blockbuff + 32, wps->wphdr.ckSize - 24) != wps->wphdr.ckSize - 24) { - strcpy (error, "can't read all of WavPack file!"); - return WavpackCloseFile (wpc); - } - - wps->init_done = FALSE; - - if (wps->wphdr.block_samples && !(flags & OPEN_STREAMING)) { - if (wps->wphdr.block_index || wps->wphdr.total_samples == (uint32_t) -1) { - wpc->initial_index = wps->wphdr.block_index; - wps->wphdr.block_index = 0; - - if (wpc->reader->can_seek (wpc->wv_in)) { - uint32_t pos_save = wpc->reader->get_pos (wpc->wv_in); - uint32_t final_index = seek_final_index (wpc->reader, wpc->wv_in); - - if (final_index != (uint32_t) -1) - wpc->total_samples = final_index - wpc->initial_index; - - wpc->reader->set_pos_abs (wpc->wv_in, pos_save); - } - } - else - wpc->total_samples = wps->wphdr.total_samples; - } - - if (wpc->wvc_in && wps->wphdr.block_samples && (wps->wphdr.flags & HYBRID_FLAG)) { - wpc->file2len = wpc->reader->get_length (wpc->wvc_in); - wpc->wvc_flag = TRUE; - } - - if (wpc->wvc_flag && !read_wvc_block (wpc)) { - strcpy (error, "not compatible with this version of correction file!"); - return WavpackCloseFile (wpc); - } - - if (!wps->init_done && !unpack_init (wpc)) { - strcpy (error, wpc->error_message [0] ? wpc->error_message : - "not compatible with this version of WavPack file!"); - - return WavpackCloseFile (wpc); - } - - wps->init_done = TRUE; - } - - wpc->config.flags &= ~0xff; - wpc->config.flags |= wps->wphdr.flags & 0xff; - wpc->config.bytes_per_sample = (wps->wphdr.flags & BYTES_STORED) + 1; - wpc->config.float_norm_exp = wps->float_norm_exp; - - wpc->config.bits_per_sample = (wpc->config.bytes_per_sample * 8) - - ((wps->wphdr.flags & SHIFT_MASK) >> SHIFT_LSB); - - if (!wpc->config.sample_rate) { - if (!wps || !wps->wphdr.block_samples || (wps->wphdr.flags & SRATE_MASK) == SRATE_MASK) - wpc->config.sample_rate = 44100; - else - wpc->config.sample_rate = sample_rates [(wps->wphdr.flags & SRATE_MASK) >> SRATE_LSB]; - } - - if (!wpc->config.num_channels) { - wpc->config.num_channels = (wps->wphdr.flags & MONO_FLAG) ? 1 : 2; - wpc->config.channel_mask = 0x5 - wpc->config.num_channels; - } - - if ((flags & OPEN_2CH_MAX) && !(wps->wphdr.flags & FINAL_BLOCK)) - wpc->reduced_channels = (wps->wphdr.flags & MONO_FLAG) ? 1 : 2; - - return wpc; -} - -// This function obtains general information about an open input file and -// returns a mask with the following bit values: - -// MODE_WVC: a .wvc file has been found and will be used for lossless -// MODE_LOSSLESS: file is lossless (either pure or hybrid) -// MODE_HYBRID: file is hybrid mode (either lossy or lossless) -// MODE_FLOAT: audio data is 32-bit ieee floating point -// MODE_VALID_TAG: file conatins a valid ID3v1 or APEv2 tag -// MODE_HIGH: file was created in "high" mode (information only) -// MODE_FAST: file was created in "fast" mode (information only) -// MODE_EXTRA: file was created using "extra" mode (information only) -// MODE_APETAG: file contains a valid APEv2 tag -// MODE_SFX: file was created as a "self-extracting" executable -// MODE_VERY_HIGH: file was created in the "very high" mode (or in -// the "high" mode prior to 4.4) -// MODE_MD5: file contains an MD5 checksum -// MODE_XMODE: level used for extra mode (1-6, 0=unknown) -// MODE_DNS: dynamic noise shaping - -int WavpackGetMode (WavpackContext *wpc) -{ - int mode = 0; - - if (wpc) { - if (wpc->config.flags & CONFIG_HYBRID_FLAG) - mode |= MODE_HYBRID; - else if (!(wpc->config.flags & CONFIG_LOSSY_MODE)) - mode |= MODE_LOSSLESS; - - if (wpc->wvc_flag) - mode |= (MODE_LOSSLESS | MODE_WVC); - - if (wpc->lossy_blocks) - mode &= ~MODE_LOSSLESS; - - if (wpc->config.flags & CONFIG_FLOAT_DATA) - mode |= MODE_FLOAT; - - if (wpc->config.flags & (CONFIG_HIGH_FLAG | CONFIG_VERY_HIGH_FLAG)) { - mode |= MODE_HIGH; - - if ((wpc->config.flags & CONFIG_VERY_HIGH_FLAG) || - (wpc->streams [0] && wpc->streams [0]->wphdr.version < 0x405)) - mode |= MODE_VERY_HIGH; - } - - if (wpc->config.flags & CONFIG_FAST_FLAG) - mode |= MODE_FAST; - - if (wpc->config.flags & CONFIG_EXTRA_MODE) - mode |= (MODE_EXTRA | (wpc->config.xmode << 12)); - - if (wpc->config.flags & CONFIG_CREATE_EXE) - mode |= MODE_SFX; - - if (wpc->config.flags & CONFIG_MD5_CHECKSUM) - mode |= MODE_MD5; - - if ((wpc->config.flags & CONFIG_HYBRID_FLAG) && (wpc->config.flags & CONFIG_DYNAMIC_SHAPING) && - wpc->streams [0] && wpc->streams [0]->wphdr.version >= 0x407) - mode |= MODE_DNS; - -#ifndef NO_TAGS - if (valid_tag (&wpc->m_tag)) { - mode |= MODE_VALID_TAG; - - if (valid_tag (&wpc->m_tag) == 'A') - mode |= MODE_APETAG; - } -#endif - } - - return mode; -} - -// This function returns the major version number of the WavPack program -// (or library) that created the open file. Currently, this can be 1 to 4. -// Minor versions are not recorded in WavPack files. - -int WavpackGetVersion (WavpackContext *wpc) -{ - if (wpc) { -#ifndef VER4_ONLY - if (wpc->stream3) - return get_version3 (wpc); -#endif - return 4; - } - - return 0; -} - -#endif - -// This function returns a pointer to a string describing the last error -// generated by WavPack. - -char *WavpackGetErrorMessage (WavpackContext *wpc) -{ - return wpc->error_message; -} - -#ifndef NO_UNPACK - -// Unpack the specified number of samples from the current file position. -// Note that "samples" here refers to "complete" samples, which would be -// 2 longs for stereo files or even more for multichannel files, so the -// required memory at "buffer" is 4 * samples * num_channels bytes. The -// audio data is returned right-justified in 32-bit longs in the endian -// mode native to the executing processor. So, if the original data was -// 16-bit, then the values returned would be +/-32k. Floating point data -// can also be returned if the source was floating point data (and this -// can be optionally normalized to +/-1.0 by using the appropriate flag -// in the call to WavpackOpenFileInput ()). The actual number of samples -// unpacked is returned, which should be equal to the number requested unless -// the end of fle is encountered or an error occurs. After all samples have -// been unpacked then 0 will be returned. - -uint32_t WavpackUnpackSamples (WavpackContext *wpc, int32_t *buffer, uint32_t samples) -{ - WavpackStream *wps = wpc->streams [wpc->current_stream = 0]; - uint32_t bcount, samples_unpacked = 0, samples_to_unpack; - int num_channels = wpc->config.num_channels; - int file_done = FALSE; - -#ifndef VER4_ONLY - if (wpc->stream3) - return unpack_samples3 (wpc, buffer, samples); -#endif - - while (samples) { - if (!wps->wphdr.block_samples || !(wps->wphdr.flags & INITIAL_BLOCK) || - wps->sample_index >= wps->wphdr.block_index + wps->wphdr.block_samples) { - - if (wpc->wrapper_bytes >= MAX_WRAPPER_BYTES) - break; - - free_streams (wpc); - wpc->filepos = wpc->reader->get_pos (wpc->wv_in); - bcount = read_next_header (wpc->reader, wpc->wv_in, &wps->wphdr); - - if (bcount == (uint32_t) -1) - break; - - if (wpc->open_flags & OPEN_STREAMING) - wps->wphdr.block_index = wps->sample_index = 0; - else - wps->wphdr.block_index -= wpc->initial_index; - - wpc->filepos += bcount; - wps->blockbuff = malloc (wps->wphdr.ckSize + 8); - memcpy (wps->blockbuff, &wps->wphdr, 32); - - if (wpc->reader->read_bytes (wpc->wv_in, wps->blockbuff + 32, wps->wphdr.ckSize - 24) != - wps->wphdr.ckSize - 24) { - strcpy (wpc->error_message, "can't read all of last block!"); - wps->wphdr.block_samples = 0; - wps->wphdr.ckSize = 24; - break; - } - - wps->init_done = FALSE; - - if (wps->wphdr.block_samples && wps->sample_index != wps->wphdr.block_index) - wpc->crc_errors++; - - if (wps->wphdr.block_samples && wpc->wvc_flag) - read_wvc_block (wpc); - - if (!wps->wphdr.block_samples) { - if (!wps->init_done && !unpack_init (wpc)) - wpc->crc_errors++; - - wps->init_done = TRUE; - } - } - - if (!wps->wphdr.block_samples || !(wps->wphdr.flags & INITIAL_BLOCK) || - wps->sample_index >= wps->wphdr.block_index + wps->wphdr.block_samples) - continue; - - if (wps->sample_index < wps->wphdr.block_index) { - samples_to_unpack = wps->wphdr.block_index - wps->sample_index; - - if (samples_to_unpack > 262144) { - strcpy (wpc->error_message, "discontinuity found, aborting file!"); - wps->wphdr.block_samples = 0; - wps->wphdr.ckSize = 24; - break; - } - - if (samples_to_unpack > samples) - samples_to_unpack = samples; - - wps->sample_index += samples_to_unpack; - samples_unpacked += samples_to_unpack; - samples -= samples_to_unpack; - - if (wpc->reduced_channels) - samples_to_unpack *= wpc->reduced_channels; - else - samples_to_unpack *= num_channels; - - while (samples_to_unpack--) - *buffer++ = 0; - - continue; - } - - samples_to_unpack = wps->wphdr.block_index + wps->wphdr.block_samples - wps->sample_index; - - if (samples_to_unpack > samples) - samples_to_unpack = samples; - - if (!wps->init_done && !unpack_init (wpc)) - wpc->crc_errors++; - - wps->init_done = TRUE; - - if (!wpc->reduced_channels && !(wps->wphdr.flags & FINAL_BLOCK)) { - int32_t *temp_buffer = malloc (samples_to_unpack * 8), *src, *dst; - int offset = 0; - uint32_t samcnt; - - while (1) { - if (wpc->current_stream == wpc->num_streams) { - wps = wpc->streams [wpc->num_streams++] = malloc (sizeof (WavpackStream)); - CLEAR (*wps); - bcount = read_next_header (wpc->reader, wpc->wv_in, &wps->wphdr); - - if (bcount == (uint32_t) -1) { - wpc->streams [0]->wphdr.block_samples = 0; - wpc->streams [0]->wphdr.ckSize = 24; - file_done = TRUE; - break; - } - - if (wpc->open_flags & OPEN_STREAMING) - wps->wphdr.block_index = wps->sample_index = 0; - else - wps->wphdr.block_index -= wpc->initial_index; - - wps->blockbuff = malloc (wps->wphdr.ckSize + 8); - memcpy (wps->blockbuff, &wps->wphdr, 32); - - if (wpc->reader->read_bytes (wpc->wv_in, wps->blockbuff + 32, wps->wphdr.ckSize - 24) != - wps->wphdr.ckSize - 24) { - wpc->streams [0]->wphdr.block_samples = 0; - wpc->streams [0]->wphdr.ckSize = 24; - file_done = TRUE; - break; - } - - wps->init_done = FALSE; - - if (wpc->wvc_flag) - read_wvc_block (wpc); - - if (!wps->init_done && !unpack_init (wpc)) - wpc->crc_errors++; - - wps->init_done = TRUE; - } - else - wps = wpc->streams [wpc->current_stream]; - - unpack_samples (wpc, src = temp_buffer, samples_to_unpack); - samcnt = samples_to_unpack; - dst = buffer + offset; - - if (wps->wphdr.flags & MONO_FLAG) { - while (samcnt--) { - dst [0] = *src++; - dst += num_channels; - } - - offset++; - } - else if (offset == num_channels - 1) { - while (samcnt--) { - dst [0] = src [0]; - dst += num_channels; - src += 2; - } - - wpc->crc_errors++; - offset++; - } - else { - while (samcnt--) { - dst [0] = *src++; - dst [1] = *src++; - dst += num_channels; - } - - offset += 2; - } - - if ((wps->wphdr.flags & FINAL_BLOCK) || wpc->num_streams == MAX_STREAMS || offset == num_channels) - break; - else - wpc->current_stream++; - } - - wps = wpc->streams [wpc->current_stream = 0]; - free (temp_buffer); - } - else - unpack_samples (wpc, buffer, samples_to_unpack); - - if (!(wps->wphdr.flags & FINAL_BLOCK) && wpc->num_streams == MAX_STREAMS) { - strcpy (wpc->error_message, "too many channels!"); - break; - } - - if (file_done) { - strcpy (wpc->error_message, "can't read all of last block!"); - break; - } - - if (wpc->reduced_channels) - buffer += samples_to_unpack * wpc->reduced_channels; - else - buffer += samples_to_unpack * num_channels; - - samples_unpacked += samples_to_unpack; - samples -= samples_to_unpack; - - if (wps->sample_index == wps->wphdr.block_index + wps->wphdr.block_samples) { - if (check_crc_error (wpc) && wps->blockbuff) { - - if (wpc->reader->can_seek (wpc->wv_in)) { - int32_t rseek = ((WavpackHeader *) wps->blockbuff)->ckSize / 3; - wpc->reader->set_pos_rel (wpc->wv_in, (rseek > 16384) ? -16384 : -rseek, SEEK_CUR); - } - - if (wpc->wvc_flag && wps->block2buff && wpc->reader->can_seek (wpc->wvc_in)) { - int32_t rseek = ((WavpackHeader *) wps->block2buff)->ckSize / 3; - wpc->reader->set_pos_rel (wpc->wvc_in, (rseek > 16384) ? -16384 : -rseek, SEEK_CUR); - } - - wpc->crc_errors++; - } - } - - if (wpc->total_samples != (uint32_t) -1 && wps->sample_index == wpc->total_samples) - break; - } - - return samples_unpacked; -} - -#ifndef NO_SEEKING - -static uint32_t find_sample (WavpackContext *wpc, void *infile, uint32_t header_pos, uint32_t sample); - -// Seek to the specifed sample index, returning TRUE on success. Note that -// files generated with version 4.0 or newer will seek almost immediately. -// Older files can take quite long if required to seek through unplayed -// portions of the file, but will create a seek map so that reverse seeks -// (or forward seeks to already scanned areas) will be very fast. After a -// FALSE return the file should not be accessed again (other than to close -// it); this is a fatal error. - -int WavpackSeekSample (WavpackContext *wpc, uint32_t sample) -{ - WavpackStream *wps = wpc->streams [wpc->current_stream = 0]; - uint32_t bcount, samples_to_skip; - int32_t *buffer; - - if (wpc->total_samples == (uint32_t) -1 || sample >= wpc->total_samples || - !wpc->reader->can_seek (wpc->wv_in) || (wpc->open_flags & OPEN_STREAMING) || - (wpc->wvc_flag && !wpc->reader->can_seek (wpc->wvc_in))) - return FALSE; - -#ifndef VER4_ONLY - if (wpc->stream3) - return seek_sample3 (wpc, sample); -#endif - - if (!wps->wphdr.block_samples || !(wps->wphdr.flags & INITIAL_BLOCK) || sample < wps->wphdr.block_index || - sample >= wps->wphdr.block_index + wps->wphdr.block_samples) { - - free_streams (wpc); - wpc->filepos = find_sample (wpc, wpc->wv_in, wpc->filepos, sample); - - if (wpc->filepos == (uint32_t) -1) - return FALSE; - - if (wpc->wvc_flag) { - wpc->file2pos = find_sample (wpc, wpc->wvc_in, 0, sample); - - if (wpc->file2pos == (uint32_t) -1) - return FALSE; - } - } - - if (!wps->blockbuff) { - wpc->reader->set_pos_abs (wpc->wv_in, wpc->filepos); - wpc->reader->read_bytes (wpc->wv_in, &wps->wphdr, sizeof (WavpackHeader)); - little_endian_to_native (&wps->wphdr, WavpackHeaderFormat); - wps->wphdr.block_index -= wpc->initial_index; - wps->blockbuff = malloc (wps->wphdr.ckSize + 8); - memcpy (wps->blockbuff, &wps->wphdr, sizeof (WavpackHeader)); - - if (wpc->reader->read_bytes (wpc->wv_in, wps->blockbuff + sizeof (WavpackHeader), wps->wphdr.ckSize - 24) != - wps->wphdr.ckSize - 24) { - free_streams (wpc); - return FALSE; - } - - wps->init_done = FALSE; - - if (wpc->wvc_flag) { - wpc->reader->set_pos_abs (wpc->wvc_in, wpc->file2pos); - wpc->reader->read_bytes (wpc->wvc_in, &wps->wphdr, sizeof (WavpackHeader)); - little_endian_to_native (&wps->wphdr, WavpackHeaderFormat); - wps->wphdr.block_index -= wpc->initial_index; - wps->block2buff = malloc (wps->wphdr.ckSize + 8); - memcpy (wps->block2buff, &wps->wphdr, sizeof (WavpackHeader)); - - if (wpc->reader->read_bytes (wpc->wvc_in, wps->block2buff + sizeof (WavpackHeader), wps->wphdr.ckSize - 24) != - wps->wphdr.ckSize - 24) { - free_streams (wpc); - return FALSE; - } - } - - if (!wps->init_done && !unpack_init (wpc)) { - free_streams (wpc); - return FALSE; - } - - wps->init_done = TRUE; - } - - while (!wpc->reduced_channels && !(wps->wphdr.flags & FINAL_BLOCK)) { - if (++wpc->current_stream == wpc->num_streams) { - - if (wpc->num_streams == MAX_STREAMS) { - free_streams (wpc); - return FALSE; - } - - wps = wpc->streams [wpc->num_streams++] = malloc (sizeof (WavpackStream)); - CLEAR (*wps); - bcount = read_next_header (wpc->reader, wpc->wv_in, &wps->wphdr); - - if (bcount == (uint32_t) -1) { - free_streams (wpc); - return FALSE; - } - - wps->blockbuff = malloc (wps->wphdr.ckSize + 8); - memcpy (wps->blockbuff, &wps->wphdr, 32); - - if (wpc->reader->read_bytes (wpc->wv_in, wps->blockbuff + 32, wps->wphdr.ckSize - 24) != - wps->wphdr.ckSize - 24) { - free_streams (wpc); - return FALSE; - } - - wps->init_done = FALSE; - - if (wpc->wvc_flag && !read_wvc_block (wpc)) { - free_streams (wpc); - return FALSE; - } - - if (!wps->init_done && !unpack_init (wpc)) { - free_streams (wpc); - return FALSE; - } - - wps->init_done = TRUE; - } - else - wps = wpc->streams [wpc->current_stream]; - } - - if (sample < wps->sample_index) { - for (wpc->current_stream = 0; wpc->current_stream < wpc->num_streams; wpc->current_stream++) - if (!unpack_init (wpc)) - return FALSE; - else - wpc->streams [wpc->current_stream]->init_done = TRUE; - } - - samples_to_skip = sample - wps->sample_index; - - if (samples_to_skip > 131072) { - free_streams (wpc); - return FALSE; - } - - if (samples_to_skip) { - buffer = malloc (samples_to_skip * 8); - - for (wpc->current_stream = 0; wpc->current_stream < wpc->num_streams; wpc->current_stream++) - unpack_samples (wpc, buffer, samples_to_skip); - - free (buffer); - } - - wpc->current_stream = 0; - return TRUE; -} - -#endif - -#ifndef NO_TAGS - -// Count and return the total number of tag items in the specified file. - -int WavpackGetNumTagItems (WavpackContext *wpc) -{ - int i = 0; - - while (WavpackGetTagItemIndexed (wpc, i, NULL, 0)) - ++i; - - return i; -} - -// Attempt to get the specified item from the specified file's ID3v1 or APEv2 -// tag. The "size" parameter specifies the amount of space available at "value", -// if the desired item will not fit in this space then ellipses (...) will -// be appended and the string terminated. Only text data are supported. The -// actual length of the string is returned (or 0 if no matching value found). -// Note that with APEv2 tags the length might not be the same as the number of -// characters because UTF-8 encoding is used. Also, APEv2 tags can have multiple -// (NULL separated) strings for a single value (this is why the length is -// returned). If this function is called with a NULL "value" pointer (or a -// zero "length") then only the actual length of the value data is returned -// (not counting the terminating NULL). This can be used to determine the -// actual memory to be allocated beforehand. - -static int get_ape_tag_item (M_Tag *m_tag, const char *item, char *value, int size); -static int get_id3_tag_item (M_Tag *m_tag, const char *item, char *value, int size); - -int WavpackGetTagItem (WavpackContext *wpc, const char *item, char *value, int size) -{ - M_Tag *m_tag = &wpc->m_tag; - - if (value && size) - *value = 0; - - if (m_tag->ape_tag_hdr.ID [0] == 'A') - return get_ape_tag_item (m_tag, item, value, size); - else if (m_tag->id3_tag.tag_id [0] == 'T') - return get_id3_tag_item (m_tag, item, value, size); - else - return 0; -} - -static int get_ape_tag_item (M_Tag *m_tag, const char *item, char *value, int size) -{ - char *p = m_tag->ape_tag_data; - char *q = p + m_tag->ape_tag_hdr.length - sizeof (APE_Tag_Hdr); - int i; - - for (i = 0; i < m_tag->ape_tag_hdr.item_count && q - p > 8; ++i) { - int vsize, flags, isize; - - vsize = * (int32_t *) p; p += 4; - flags = * (int32_t *) p; p += 4; - isize = (int) strnlen (p, q - p); - - little_endian_to_native (&vsize, "L"); - little_endian_to_native (&flags, "L"); - - if (vsize < 0 || vsize > m_tag->ape_tag_hdr.length || p + isize + vsize + 1 > q) - break; - - if (isize && vsize && !stricmp (item, p) && !(flags & 6)) { - - if (!value || !size) - return vsize; - - if (vsize < size) { - memcpy (value, p + isize + 1, vsize); - value [vsize] = 0; - return vsize; - } - else if (size >= 4) { - memcpy (value, p + isize + 1, size - 1); - value [size - 4] = value [size - 3] = value [size - 2] = '.'; - value [size - 1] = 0; - return size - 1; - } - else - return 0; - } - else - p += isize + vsize + 1; - } - - return 0; -} - -static void tagcpy (char *dest, char *src, int tag_size); - -static int get_id3_tag_item (M_Tag *m_tag, const char *item, char *value, int size) -{ - char lvalue [64]; - int len; - - lvalue [0] = 0; - - if (!stricmp (item, "title")) - tagcpy (lvalue, m_tag->id3_tag.title, sizeof (m_tag->id3_tag.title)); - else if (!stricmp (item, "artist")) - tagcpy (lvalue, m_tag->id3_tag.artist, sizeof (m_tag->id3_tag.artist)); - else if (!stricmp (item, "album")) - tagcpy (lvalue, m_tag->id3_tag.album, sizeof (m_tag->id3_tag.album)); - else if (!stricmp (item, "year")) - tagcpy (lvalue, m_tag->id3_tag.year, sizeof (m_tag->id3_tag.year)); - else if (!stricmp (item, "comment")) - tagcpy (lvalue, m_tag->id3_tag.comment, sizeof (m_tag->id3_tag.comment)); - else if (!stricmp (item, "track") && m_tag->id3_tag.comment [29] && !m_tag->id3_tag.comment [28]) - sprintf (lvalue, "%d", m_tag->id3_tag.comment [29]); - else - return 0; - - len = (int) strlen (lvalue); - - if (!value || !size) - return len; - - if (len < size) { - strcpy (value, lvalue); - return len; - } - else if (size >= 4) { - strncpy (value, lvalue, size - 1); - value [size - 4] = value [size - 3] = value [size - 2] = '.'; - value [size - 1] = 0; - return size - 1; - } - else - return 0; -} - -// This function looks up the tag item name by index and is used when the -// application wants to access all the items in the file's ID3v1 or APEv2 tag. -// Note that this function accesses only the item's name; WavpackGetTagItem() -// still must be called to get the actual value. The "size" parameter specifies -// the amount of space available at "item", if the desired item will not fit in -// this space then ellipses (...) will be appended and the string terminated. -// The actual length of the string is returned (or 0 if no item exists for -// index). If this function is called with a NULL "value" pointer (or a -// zero "length") then only the actual length of the item name is returned -// (not counting the terminating NULL). This can be used to determine the -// actual memory to be allocated beforehand. - -static int get_ape_tag_item_indexed (M_Tag *m_tag, int index, char *item, int size); -static int get_id3_tag_item_indexed (M_Tag *m_tag, int index, char *item, int size); - -int WavpackGetTagItemIndexed (WavpackContext *wpc, int index, char *item, int size) -{ - M_Tag *m_tag = &wpc->m_tag; - - if (item && size) - *item = 0; - - if (m_tag->ape_tag_hdr.ID [0] == 'A') - return get_ape_tag_item_indexed (m_tag, index, item, size); - else if (m_tag->id3_tag.tag_id [0] == 'T') - return get_id3_tag_item_indexed (m_tag, index, item, size); - else - return 0; -} - -static int get_ape_tag_item_indexed (M_Tag *m_tag, int index, char *item, int size) -{ - char *p = m_tag->ape_tag_data; - char *q = p + m_tag->ape_tag_hdr.length - sizeof (APE_Tag_Hdr); - int i; - - for (i = 0; i < m_tag->ape_tag_hdr.item_count && index >= 0 && q - p > 8; ++i) { - int vsize, flags, isize; - - vsize = * (int32_t *) p; p += 4; - flags = * (int32_t *) p; p += 4; - isize = (int) strnlen (p, q - p); - - little_endian_to_native (&vsize, "L"); - little_endian_to_native (&flags, "L"); - - if (vsize < 0 || vsize > m_tag->ape_tag_hdr.length || p + isize + vsize + 1 > q) - break; - - if (isize && vsize && !(flags & 6) && !index--) { - - if (!item || !size) - return isize; - - if (isize < size) { - memcpy (item, p, isize); - item [isize] = 0; - return isize; - } - else if (size >= 4) { - memcpy (item, p, size - 1); - item [size - 4] = item [size - 3] = item [size - 2] = '.'; - item [size - 1] = 0; - return size - 1; - } - else - return 0; - } - else - p += isize + vsize + 1; - } - - return 0; -} - -static int tagdata (char *src, int tag_size); - -static int get_id3_tag_item_indexed (M_Tag *m_tag, int index, char *item, int size) -{ - char lvalue [16]; - int len; - - lvalue [0] = 0; - - if (tagdata (m_tag->id3_tag.title, sizeof (m_tag->id3_tag.title)) && !index--) - strcpy (lvalue, "Title"); - else if (tagdata (m_tag->id3_tag.artist, sizeof (m_tag->id3_tag.artist)) && !index--) - strcpy (lvalue, "Artist"); - else if (tagdata (m_tag->id3_tag.album, sizeof (m_tag->id3_tag.album)) && !index--) - strcpy (lvalue, "Album"); - else if (tagdata (m_tag->id3_tag.year, sizeof (m_tag->id3_tag.year)) && !index--) - strcpy (lvalue, "Year"); - else if (tagdata (m_tag->id3_tag.comment, sizeof (m_tag->id3_tag.comment)) && !index--) - strcpy (lvalue, "Comment"); - else if (m_tag->id3_tag.comment [29] && !m_tag->id3_tag.comment [28] && !index--) - strcpy (lvalue, "Track"); - else - return 0; - - len = (int) strlen (lvalue); - - if (!item || !size) - return len; - - if (len < size) { - strcpy (item, lvalue); - return len; - } - else if (size >= 4) { - strncpy (item, lvalue, size - 1); - item [size - 4] = item [size - 3] = item [size - 2] = '.'; - item [size - 1] = 0; - return size - 1; - } - else - return 0; -} - -#endif - -#endif - -#ifndef NO_PACK - -// Open context for writing WavPack files. The returned context pointer is used -// in all following calls to the library. The "blockout" function will be used -// to store the actual completed WavPack blocks and will be called with the id -// pointers containing user defined data (one for the wv file and one for the -// wvc file). A return value of NULL indicates that memory could not be -// allocated for the context. - -WavpackContext *WavpackOpenFileOutput (WavpackBlockOutput blockout, void *wv_id, void *wvc_id) -{ - WavpackContext *wpc = malloc (sizeof (WavpackContext)); - - if (!wpc) - return NULL; - - CLEAR (*wpc); - wpc->blockout = blockout; - wpc->wv_out = wv_id; - wpc->wvc_out = wvc_id; - return wpc; -} - -// Set configuration for writing WavPack files. This must be done before -// sending any actual samples, however it is okay to send wrapper or other -// metadata before calling this. The "config" structure contains the following -// required information: - -// config->bytes_per_sample see WavpackGetBytesPerSample() for info -// config->bits_per_sample see WavpackGetBitsPerSample() for info -// config->channel_mask Microsoft standard (mono = 4, stereo = 3) -// config->num_channels self evident -// config->sample_rate self evident - -// In addition, the following fields and flags may be set: - -// config->flags: -// -------------- -// o CONFIG_HYBRID_FLAG select hybrid mode (must set bitrate) -// o CONFIG_JOINT_STEREO select joint stereo (must set override also) -// o CONFIG_JOINT_OVERRIDE override default joint stereo selection -// o CONFIG_HYBRID_SHAPE select hybrid noise shaping (set override & -// shaping_weight != 0.0) -// o CONFIG_SHAPE_OVERRIDE override default hybrid noise shaping -// (set CONFIG_HYBRID_SHAPE and shaping_weight) -// o CONFIG_FAST_FLAG "fast" compression mode -// o CONFIG_HIGH_FLAG "high" compression mode -// o CONFIG_BITRATE_KBPS hybrid bitrate is kbps, not bits / sample -// o CONFIG_CREATE_WVC create correction file -// o CONFIG_OPTIMIZE_WVC maximize bybrid compression (-cc option) -// o CONFIG_CALC_NOISE calc noise in hybrid mode -// o CONFIG_EXTRA_MODE extra processing mode (slow!) -// o CONFIG_SKIP_WVX no wvx stream for floats & large ints -// o CONFIG_MD5_CHECKSUM specify if you plan to store MD5 signature -// o CONFIG_CREATE_EXE specify if you plan to prepend sfx module -// o CONFIG_OPTIMIZE_MONO detect and optimize for mono files posing as -// stereo (uses a more recent stream format that -// is not compatible with decoders < 4.3) - -// config->bitrate hybrid bitrate in either bits/sample or kbps -// config->shaping_weight hybrid noise shaping coefficient override -// config->block_samples force samples per WavPack block (0 = use deflt) -// config->float_norm_exp select floating-point data (127 for +/-1.0) -// config->xmode extra mode processing value override - -// If the number of samples to be written is known then it should be passed -// here. If the duration is not known then pass -1. In the case that the size -// is not known (or the writing is terminated early) then it is suggested that -// the application retrieve the first block written and let the library update -// the total samples indication. A function is provided to do this update and -// it should be done to the "correction" file also. If this cannot be done -// (because a pipe is being used, for instance) then a valid WavPack will still -// be created, but when applications want to access that file they will have -// to seek all the way to the end to determine the actual duration. Also, if -// a RIFF header has been included then it should be updated as well or the -// WavPack file will not be directly unpackable to a valid wav file (although -// it will still be usable by itself). A return of FALSE indicates an error. - -int WavpackSetConfiguration (WavpackContext *wpc, WavpackConfig *config, uint32_t total_samples) -{ - uint32_t flags = (config->bytes_per_sample - 1), bps = 0, shift = 0; - uint32_t chan_mask = config->channel_mask; - int num_chans = config->num_channels; - int i; - - wpc->total_samples = total_samples; - wpc->config.sample_rate = config->sample_rate; - wpc->config.num_channels = config->num_channels; - wpc->config.channel_mask = config->channel_mask; - wpc->config.bits_per_sample = config->bits_per_sample; - wpc->config.bytes_per_sample = config->bytes_per_sample; - wpc->config.block_samples = config->block_samples; - wpc->config.flags = config->flags; - - if (config->flags & CONFIG_VERY_HIGH_FLAG) - wpc->config.flags |= CONFIG_HIGH_FLAG; - - if (config->float_norm_exp) { - wpc->config.float_norm_exp = config->float_norm_exp; - wpc->config.flags |= CONFIG_FLOAT_DATA; - flags |= FLOAT_DATA; - } - else - shift = (config->bytes_per_sample * 8) - config->bits_per_sample; - - for (i = 0; i < 15; ++i) - if (wpc->config.sample_rate == sample_rates [i]) - break; - - flags |= i << SRATE_LSB; - flags |= shift << SHIFT_LSB; - - if (config->flags & CONFIG_HYBRID_FLAG) { - flags |= HYBRID_FLAG | HYBRID_BITRATE | HYBRID_BALANCE; - - if (!(wpc->config.flags & CONFIG_SHAPE_OVERRIDE)) { - wpc->config.flags |= CONFIG_HYBRID_SHAPE | CONFIG_AUTO_SHAPING; - flags |= HYBRID_SHAPE | NEW_SHAPING; - } - else if (wpc->config.flags & CONFIG_HYBRID_SHAPE) { - wpc->config.shaping_weight = config->shaping_weight; - flags |= HYBRID_SHAPE | NEW_SHAPING; - } - - if (wpc->config.flags & CONFIG_OPTIMIZE_WVC) - flags |= CROSS_DECORR; - - if (config->flags & CONFIG_BITRATE_KBPS) { - bps = (uint32_t) floor (config->bitrate * 256000.0 / config->sample_rate / config->num_channels + 0.5); - - if (bps > (64 << 8)) - bps = 64 << 8; - } - else - bps = (uint32_t) floor (config->bitrate * 256.0 + 0.5); - } - else - flags |= CROSS_DECORR; - - if (!(config->flags & CONFIG_JOINT_OVERRIDE) || (config->flags & CONFIG_JOINT_STEREO)) - flags |= JOINT_STEREO; - - if (config->flags & CONFIG_CREATE_WVC) - wpc->wvc_flag = TRUE; - - wpc->stream_version = (config->flags & CONFIG_OPTIMIZE_MONO) ? MAX_STREAM_VERS : CUR_STREAM_VERS; - - for (wpc->current_stream = 0; num_chans; wpc->current_stream++) { - WavpackStream *wps = malloc (sizeof (WavpackStream)); - uint32_t stereo_mask, mono_mask; - int pos, chans = 0; - - wpc->streams [wpc->current_stream] = wps; - CLEAR (*wps); - - for (pos = 1; pos <= 18; ++pos) { - stereo_mask = 3 << (pos - 1); - mono_mask = 1 << (pos - 1); - - if ((chan_mask & stereo_mask) == stereo_mask && (mono_mask & 0x251)) { - chan_mask &= ~stereo_mask; - chans = 2; - break; - } - else if (chan_mask & mono_mask) { - chan_mask &= ~mono_mask; - chans = 1; - break; - } - } - - if (!chans) - chans = num_chans > 1 ? 2 : 1; - - num_chans -= chans; - - if (num_chans && wpc->current_stream == MAX_STREAMS - 1) - break; - - memcpy (wps->wphdr.ckID, "wvpk", 4); - wps->wphdr.ckSize = sizeof (WavpackHeader) - 8; - wps->wphdr.total_samples = wpc->total_samples; - wps->wphdr.version = wpc->stream_version; - wps->wphdr.flags = flags; - wps->bits = bps; - - if (!wpc->current_stream) - wps->wphdr.flags |= INITIAL_BLOCK; - - if (!num_chans) - wps->wphdr.flags |= FINAL_BLOCK; - - if (chans == 1) { - wps->wphdr.flags &= ~(JOINT_STEREO | CROSS_DECORR | HYBRID_BALANCE); - wps->wphdr.flags |= MONO_FLAG; - } - } - - wpc->num_streams = wpc->current_stream; - wpc->current_stream = 0; - - if (num_chans) { - strcpy (wpc->error_message, "too many channels!"); - return FALSE; - } - - if (config->flags & CONFIG_EXTRA_MODE) - wpc->config.xmode = config->xmode ? config->xmode : 1; - - return TRUE; -} - -// Prepare to actually pack samples by determining the size of the WavPack -// blocks and allocating sample buffers and initializing each stream. Call -// after WavpackSetConfiguration() and before WavpackPackSamples(). A return -// of FALSE indicates an error. - -int WavpackPackInit (WavpackContext *wpc) -{ - if (wpc->metabytes > 4096) - write_metadata_block (wpc); - - if (wpc->config.flags & CONFIG_HIGH_FLAG) - wpc->block_samples = wpc->config.sample_rate; - else if (!(wpc->config.sample_rate % 2)) - wpc->block_samples = wpc->config.sample_rate / 2; - else - wpc->block_samples = wpc->config.sample_rate; - - while (wpc->block_samples * wpc->config.num_channels > 150000) - wpc->block_samples /= 2; - - while (wpc->block_samples * wpc->config.num_channels < 40000) - wpc->block_samples *= 2; - - if (wpc->config.block_samples) { - if ((wpc->config.flags & CONFIG_MERGE_BLOCKS) && - wpc->block_samples > (uint32_t) wpc->config.block_samples) { - wpc->block_boundary = wpc->config.block_samples; - wpc->block_samples /= wpc->config.block_samples; - wpc->block_samples *= wpc->config.block_samples; - } - else - wpc->block_samples = wpc->config.block_samples; - } - - wpc->ave_block_samples = wpc->block_samples; - wpc->max_samples = wpc->block_samples + (wpc->block_samples >> 1); - - for (wpc->current_stream = 0; wpc->streams [wpc->current_stream]; wpc->current_stream++) { - WavpackStream *wps = wpc->streams [wpc->current_stream]; - - wps->sample_buffer = malloc (wpc->max_samples * (wps->wphdr.flags & MONO_FLAG ? 4 : 8)); - pack_init (wpc); - } - - return TRUE; -} - -// Pack the specified samples. Samples must be stored in longs in the native -// endian format of the executing processor. The number of samples specified -// indicates composite samples (sometimes called "frames"). So, the actual -// number of data points would be this "sample_count" times the number of -// channels. Note that samples are accumulated here until enough exist to -// create a complete WavPack block (or several blocks for multichannel audio). -// If an application wants to break a block at a specific sample, then it must -// simply call WavpackFlushSamples() to force an early termination. Completed -// WavPack blocks are send to the function provided in the initial call to -// WavpackOpenFileOutput(). A return of FALSE indicates an error. - -static int pack_streams (WavpackContext *wpc, uint32_t block_samples); -static int create_riff_header (WavpackContext *wpc); - -int WavpackPackSamples (WavpackContext *wpc, int32_t *sample_buffer, uint32_t sample_count) -{ - int nch = wpc->config.num_channels; - - while (sample_count) { - int32_t *source_pointer = sample_buffer; - uint samples_to_copy; - - if (!wpc->riff_header_added && !wpc->riff_header_created && !create_riff_header (wpc)) - return FALSE; - - if (wpc->acc_samples + sample_count > wpc->max_samples) - samples_to_copy = wpc->max_samples - wpc->acc_samples; - else - samples_to_copy = sample_count; - - for (wpc->current_stream = 0; wpc->streams [wpc->current_stream]; wpc->current_stream++) { - WavpackStream *wps = wpc->streams [wpc->current_stream]; - int32_t *dptr, *sptr, cnt; - - dptr = wps->sample_buffer + wpc->acc_samples * (wps->wphdr.flags & MONO_FLAG ? 1 : 2); - sptr = source_pointer; - cnt = samples_to_copy; - - if (wps->wphdr.flags & MONO_FLAG) { - while (cnt--) { - *dptr++ = *sptr; - sptr += nch; - } - - source_pointer++; - } - else { - while (cnt--) { - *dptr++ = sptr [0]; - *dptr++ = sptr [1]; - sptr += nch; - } - - source_pointer += 2; - } - } - - sample_buffer += samples_to_copy * nch; - sample_count -= samples_to_copy; - - if ((wpc->acc_samples += samples_to_copy) == wpc->max_samples && - !pack_streams (wpc, wpc->block_samples)) - return FALSE; - } - - return TRUE; -} - -// Flush all accumulated samples into WavPack blocks. This is normally called -// after all samples have been sent to WavpackPackSamples(), but can also be -// called to terminate a WavPack block at a specific sample (in other words it -// is possible to continue after this operation). This is also called to -// dump non-audio blocks like those holding metadata for various purposes. -// A return of FALSE indicates an error. - -int WavpackFlushSamples (WavpackContext *wpc) -{ - while (wpc->acc_samples) { - uint32_t block_samples; - - if (wpc->acc_samples > wpc->block_samples) - block_samples = wpc->acc_samples / 2; - else - block_samples = wpc->acc_samples; - - if (!pack_streams (wpc, block_samples)) - return FALSE; - } - - if (wpc->metacount) - write_metadata_block (wpc); - - return TRUE; -} - -// Note: The following function is no longer required because a proper wav -// header is now automatically generated for the application. However, if the -// application wants to generate its own header or wants to include additional -// chunks, then this function can still be used in which case the automatic -// wav header generation is suppressed. - -// Add wrapper (currently RIFF only) to WavPack blocks. This should be called -// before sending any audio samples for the RIFF header or after all samples -// have been sent for any RIFF trailer. WavpackFlushSamples() should be called -// between sending the last samples and calling this for trailer data to make -// sure that headers and trailers don't get mixed up in very short files. If -// the exact contents of the RIFF header are not known because, for example, -// the file duration is uncertain or trailing chunks are possible, simply write -// a "dummy" header of the correct length. When all data has been written it -// will be possible to read the first block written and update the header -// directly. An example of this can be found in the Audition filter. A -// return of FALSE indicates an error. - -int WavpackAddWrapper (WavpackContext *wpc, void *data, uint32_t bcount) -{ - uint32_t index = WavpackGetSampleIndex (wpc); - uchar meta_id; - - if (!index || index == (uint32_t) -1) { - wpc->riff_header_added = TRUE; - meta_id = ID_RIFF_HEADER; - } - else - meta_id = ID_RIFF_TRAILER; - - return add_to_metadata (wpc, data, bcount, meta_id); -} - -// Store computed MD5 sum in WavPack metadata. Note that the user must compute -// the 16 byte sum; it is not done here. A return of FALSE indicates an error. - -int WavpackStoreMD5Sum (WavpackContext *wpc, uchar data [16]) -{ - return add_to_metadata (wpc, data, 16, ID_MD5_CHECKSUM); -} - -static int create_riff_header (WavpackContext *wpc) -{ - RiffChunkHeader riffhdr; - ChunkHeader datahdr, fmthdr; - WaveHeader wavhdr; - - uint32_t total_samples = wpc->total_samples, total_data_bytes; - int32_t channel_mask = wpc->config.channel_mask; - int32_t sample_rate = wpc->config.sample_rate; - int bytes_per_sample = wpc->config.bytes_per_sample; - int bits_per_sample = wpc->config.bits_per_sample; - int format = (wpc->config.float_norm_exp) ? 3 : 1; - int num_channels = wpc->config.num_channels; - int wavhdrsize = 16; - - wpc->riff_header_created = TRUE; - - if (format == 3 && wpc->config.float_norm_exp != 127) { - strcpy (wpc->error_message, "can't create valid RIFF wav header for non-normalized floating data!"); - return FALSE; - } - - if (total_samples == (uint32_t) -1) - total_samples = 0x7ffff000 / (bytes_per_sample * num_channels); - - total_data_bytes = total_samples * bytes_per_sample * num_channels; - - CLEAR (wavhdr); - - wavhdr.FormatTag = format; - wavhdr.NumChannels = num_channels; - wavhdr.SampleRate = sample_rate; - wavhdr.BytesPerSecond = sample_rate * num_channels * bytes_per_sample; - wavhdr.BlockAlign = bytes_per_sample * num_channels; - wavhdr.BitsPerSample = bits_per_sample; - - if (num_channels > 2 || channel_mask != 0x5 - num_channels) { - wavhdrsize = sizeof (wavhdr); - wavhdr.cbSize = 22; - wavhdr.ValidBitsPerSample = bits_per_sample; - wavhdr.SubFormat = format; - wavhdr.ChannelMask = channel_mask; - wavhdr.FormatTag = 0xfffe; - wavhdr.BitsPerSample = bytes_per_sample * 8; - wavhdr.GUID [4] = 0x10; - wavhdr.GUID [6] = 0x80; - wavhdr.GUID [9] = 0xaa; - wavhdr.GUID [11] = 0x38; - wavhdr.GUID [12] = 0x9b; - wavhdr.GUID [13] = 0x71; - } - - strncpy (riffhdr.ckID, "RIFF", sizeof (riffhdr.ckID)); - strncpy (riffhdr.formType, "WAVE", sizeof (riffhdr.formType)); - riffhdr.ckSize = sizeof (riffhdr) + wavhdrsize + sizeof (datahdr) + total_data_bytes; - strncpy (fmthdr.ckID, "fmt ", sizeof (fmthdr.ckID)); - fmthdr.ckSize = wavhdrsize; - - strncpy (datahdr.ckID, "data", sizeof (datahdr.ckID)); - datahdr.ckSize = total_data_bytes; - - // write the RIFF chunks up to just before the data starts - - native_to_little_endian (&riffhdr, ChunkHeaderFormat); - native_to_little_endian (&fmthdr, ChunkHeaderFormat); - native_to_little_endian (&wavhdr, WaveHeaderFormat); - native_to_little_endian (&datahdr, ChunkHeaderFormat); - - return add_to_metadata (wpc, &riffhdr, sizeof (riffhdr), ID_RIFF_HEADER) && - add_to_metadata (wpc, &fmthdr, sizeof (fmthdr), ID_RIFF_HEADER) && - add_to_metadata (wpc, &wavhdr, wavhdrsize, ID_RIFF_HEADER) && - add_to_metadata (wpc, &datahdr, sizeof (datahdr), ID_RIFF_HEADER); -} - -static int pack_streams (WavpackContext *wpc, uint32_t block_samples) -{ - uint32_t max_blocksize, bcount; - uchar *outbuff, *outend, *out2buff, *out2end; - int result = TRUE; - - if ((wpc->config.flags & CONFIG_FLOAT_DATA) && !(wpc->config.flags & CONFIG_SKIP_WVX)) - max_blocksize = block_samples * 16 + 4096; - else - max_blocksize = block_samples * 10 + 4096; - - out2buff = (wpc->wvc_flag) ? malloc (max_blocksize) : NULL; - out2end = out2buff + max_blocksize; - outbuff = malloc (max_blocksize); - outend = outbuff + max_blocksize; - - for (wpc->current_stream = 0; wpc->streams [wpc->current_stream]; wpc->current_stream++) { - WavpackStream *wps = wpc->streams [wpc->current_stream]; - uint32_t flags = wps->wphdr.flags; - - flags &= ~MAG_MASK; - flags += (1 << MAG_LSB) * ((flags & BYTES_STORED) * 8 + 7); - - wps->wphdr.block_index = wps->sample_index; - wps->wphdr.block_samples = block_samples; - wps->wphdr.flags = flags; - wps->block2buff = out2buff; - wps->block2end = out2end; - wps->blockbuff = outbuff; - wps->blockend = outend; - - result = pack_block (wpc, wps->sample_buffer); - wps->blockbuff = wps->block2buff = NULL; - - if (wps->wphdr.block_samples != block_samples) - block_samples = wps->wphdr.block_samples; - - if (!result) { - strcpy (wpc->error_message, "output buffer overflowed!"); - break; - } - - bcount = ((WavpackHeader *) outbuff)->ckSize + 8; - native_to_little_endian ((WavpackHeader *) outbuff, WavpackHeaderFormat); - result = wpc->blockout (wpc->wv_out, outbuff, bcount); - - if (!result) { - strcpy (wpc->error_message, "can't write WavPack data, disk probably full!"); - break; - } - - wpc->filelen += bcount; - - if (out2buff) { - bcount = ((WavpackHeader *) out2buff)->ckSize + 8; - native_to_little_endian ((WavpackHeader *) out2buff, WavpackHeaderFormat); - result = wpc->blockout (wpc->wvc_out, out2buff, bcount); - - if (!result) { - strcpy (wpc->error_message, "can't write WavPack data, disk probably full!"); - break; - } - - wpc->file2len += bcount; - } - - if (wpc->acc_samples != block_samples) - memcpy (wps->sample_buffer, wps->sample_buffer + block_samples * (flags & MONO_FLAG ? 1 : 2), - (wpc->acc_samples - block_samples) * sizeof (int32_t) * (flags & MONO_FLAG ? 1 : 2)); - } - - wpc->current_stream = 0; - wpc->ave_block_samples = (wpc->ave_block_samples * 0x7 + block_samples + 0x4) >> 3; - wpc->acc_samples -= block_samples; - free (outbuff); - - if (out2buff) - free (out2buff); - - return result; -} - -// Given the pointer to the first block written (to either a .wv or .wvc file), -// update the block with the actual number of samples written. If the wav -// header was generated by the library, then it is updated also. This should -// be done if WavpackSetConfiguration() was called with an incorrect number -// of samples (or -1). It is the responsibility of the application to read and -// rewrite the block. An example of this can be found in the Audition filter. - -void WavpackUpdateNumSamples (WavpackContext *wpc, void *first_block) -{ - uint32_t wrapper_size; - - little_endian_to_native (first_block, WavpackHeaderFormat); - ((WavpackHeader *) first_block)->total_samples = WavpackGetSampleIndex (wpc); - - /* note that since the RIFF wrapper will not necessarily be properly aligned, - we copy it into a newly allocated buffer before modifying it */ - - if (wpc->riff_header_created) { - if (WavpackGetWrapperLocation (first_block, &wrapper_size)) { - uint32_t data_size = WavpackGetSampleIndex (wpc) * WavpackGetNumChannels (wpc) * WavpackGetBytesPerSample (wpc); - RiffChunkHeader *riffhdr; - ChunkHeader *datahdr; - void *wrapper_buff; - - riffhdr = wrapper_buff = malloc (wrapper_size); - memcpy (wrapper_buff, WavpackGetWrapperLocation (first_block, NULL), wrapper_size); - datahdr = (ChunkHeader *)((char *) riffhdr + wrapper_size - sizeof (ChunkHeader)); - - if (!strncmp (riffhdr->ckID, "RIFF", 4)) { - little_endian_to_native (riffhdr, ChunkHeaderFormat); - riffhdr->ckSize = wrapper_size + data_size - 8; - native_to_little_endian (riffhdr, ChunkHeaderFormat); - } - - if (!strncmp (datahdr->ckID, "data", 4)) { - little_endian_to_native (datahdr, ChunkHeaderFormat); - datahdr->ckSize = data_size; - native_to_little_endian (datahdr, ChunkHeaderFormat); - } - - memcpy (WavpackGetWrapperLocation (first_block, NULL), wrapper_buff, wrapper_size); - free (wrapper_buff); - } - } - - native_to_little_endian (first_block, WavpackHeaderFormat); -} - -// Note: The following function is no longer required because the wav header -// automatically generated for the application will also be updated by -// WavpackUpdateNumSamples (). However, if the application wants to generate -// its own header or wants to include additional chunks, then this function -// still must be used to update the application generated header. - -// Given the pointer to the first block written to a WavPack file, this -// function returns the location of the stored RIFF header that was originally -// written with WavpackAddWrapper(). This would normally be used to update -// the wav header to indicate that a different number of samples was actually -// written or if additional RIFF chunks are written at the end of the file. -// The "size" parameter can be set to non-NULL to obtain the exact size of the -// RIFF header, and the function will return FALSE if the header is not found -// in the block's metadata (or it is not a valid WavPack block). It is the -// responsibility of the application to read and rewrite the block. An example -// of this can be found in the Audition filter. - -static void *find_metadata (void *wavpack_block, int desired_id, uint32_t *size); - -void *WavpackGetWrapperLocation (void *first_block, uint32_t *size) -{ - void *loc; - - little_endian_to_native (first_block, WavpackHeaderFormat); - loc = find_metadata (first_block, ID_RIFF_HEADER, size); - native_to_little_endian (first_block, WavpackHeaderFormat); - - return loc; -} - -static void *find_metadata (void *wavpack_block, int desired_id, uint32_t *size) -{ - WavpackHeader *wphdr = wavpack_block; - uchar *dp, meta_id, c1, c2; - int32_t bcount, meta_bc; - - if (strncmp (wphdr->ckID, "wvpk", 4)) - return NULL; - - bcount = wphdr->ckSize - sizeof (WavpackHeader) + 8; - dp = (uchar *)(wphdr + 1); - - while (bcount >= 2) { - meta_id = *dp++; - c1 = *dp++; - - meta_bc = c1 << 1; - bcount -= 2; - - if (meta_id & ID_LARGE) { - if (bcount < 2) - break; - - c1 = *dp++; - c2 = *dp++; - meta_bc += ((uint32_t) c1 << 9) + ((uint32_t) c2 << 17); - bcount -= 2; - } - - if ((meta_id & ID_UNIQUE) == desired_id) { - if ((bcount - meta_bc) >= 0) { - if (size) - *size = meta_bc - ((meta_id & ID_ODD_SIZE) ? 1 : 0); - - return dp; - } - else - return NULL; - } - - bcount -= meta_bc; - dp += meta_bc; - } - - return NULL; -} - -#endif - -#ifndef NO_TAGS - -// Limited functionality to append APEv2 tags to WavPack files when they are -// created has been added for version 4.2. This function is used to append the -// specified field to the tag being created. If no tag has been started, then -// an empty one will be allocated first. When finished, use WavpackWriteTag() -// to write the completed tag to the file. Note that ID3 tags are not -// supported and that no editing of existing tags is allowed (there are several -// fine libraries available for this). A size parameter is included so that -// values containing multiple (NULL separated) strings can be written. - -int WavpackAppendTagItem (WavpackContext *wpc, const char *item, const char *value, int vsize) -{ - M_Tag *m_tag = &wpc->m_tag; - int isize = (int) strlen (item); - - while (WavpackDeleteTagItem (wpc, item)); - - if (!m_tag->ape_tag_hdr.ID [0]) { - strncpy (m_tag->ape_tag_hdr.ID, "APETAGEX", sizeof (m_tag->ape_tag_hdr.ID)); - m_tag->ape_tag_hdr.version = 2000; - m_tag->ape_tag_hdr.length = sizeof (m_tag->ape_tag_hdr); - m_tag->ape_tag_hdr.item_count = 0; - m_tag->ape_tag_hdr.flags = 0x80000000; - } - - if (m_tag->ape_tag_hdr.ID [0] == 'A') { - int new_item_len = vsize + isize + 9, flags = 0; - char *p; - - m_tag->ape_tag_hdr.item_count++; - m_tag->ape_tag_hdr.length += new_item_len; - p = m_tag->ape_tag_data = realloc (m_tag->ape_tag_data, m_tag->ape_tag_hdr.length); - p += m_tag->ape_tag_hdr.length - sizeof (APE_Tag_Hdr) - new_item_len; - native_to_little_endian (&vsize, "L"); - native_to_little_endian (&flags, "L"); - * (int32_t *) p = vsize; p += 4; - * (int32_t *) p = flags; p += 4; - little_endian_to_native (&vsize, "L"); - little_endian_to_native (&flags, "L"); - strcpy (p, item); - p += isize + 1; - memcpy (p, value, vsize); - - return TRUE; - } - else - return FALSE; -} - -int WavpackDeleteTagItem (WavpackContext *wpc, const char *item) -{ - M_Tag *m_tag = &wpc->m_tag; - - if (m_tag->ape_tag_hdr.ID [0] == 'A') { - char *p = m_tag->ape_tag_data; - char *q = p + m_tag->ape_tag_hdr.length - sizeof (APE_Tag_Hdr); - int i; - - for (i = 0; i < m_tag->ape_tag_hdr.item_count; ++i) { - int vsize, flags, isize; - - vsize = * (int32_t *) p; p += 4; - flags = * (int32_t *) p; p += 4; - isize = (int) strlen (p); - - little_endian_to_native (&vsize, "L"); - little_endian_to_native (&flags, "L"); - - if (p + isize + vsize + 1 > q) - break; - - if (isize && vsize && !stricmp (item, p)) { - char *d = p - 8; - - p += isize + vsize + 1; - - while (p < q) - *d++ = *p++; - - m_tag->ape_tag_hdr.length = (int32_t)(d - m_tag->ape_tag_data) + sizeof (APE_Tag_Hdr); - m_tag->ape_tag_hdr.item_count--; - return 1; - } - else - p += isize + vsize + 1; - } - } - - return 0; -} - -// Once a APEv2 tag has been created with WavpackAppendTag(), this function is -// used to write the completed tag to the end of the WavPack file. Note that -// this function uses the same "blockout" function that is used to write -// regular WavPack blocks, although that's where the similarity ends. - -static int write_tag_blockout (WavpackContext *wpc); -static int write_tag_reader (WavpackContext *wpc); - -int WavpackWriteTag (WavpackContext *wpc) -{ - if (wpc->blockout) - return write_tag_blockout (wpc); - else - return write_tag_reader (wpc); -} - -static int write_tag_blockout (WavpackContext *wpc) -{ - M_Tag *m_tag = &wpc->m_tag; - int result = TRUE; - - if (m_tag->ape_tag_hdr.ID [0] == 'A' && m_tag->ape_tag_hdr.item_count) { - m_tag->ape_tag_hdr.flags |= 0x20000000; - native_to_little_endian (&m_tag->ape_tag_hdr, APE_Tag_Hdr_Format); - result = wpc->blockout (wpc->wv_out, &m_tag->ape_tag_hdr, sizeof (m_tag->ape_tag_hdr)); - little_endian_to_native (&m_tag->ape_tag_hdr, APE_Tag_Hdr_Format); - - if (m_tag->ape_tag_hdr.length > sizeof (m_tag->ape_tag_hdr)) - result = wpc->blockout (wpc->wv_out, m_tag->ape_tag_data, m_tag->ape_tag_hdr.length - sizeof (m_tag->ape_tag_hdr)); - - m_tag->ape_tag_hdr.flags &= ~0x20000000; - native_to_little_endian (&m_tag->ape_tag_hdr, APE_Tag_Hdr_Format); - result = wpc->blockout (wpc->wv_out, &m_tag->ape_tag_hdr, sizeof (m_tag->ape_tag_hdr)); - little_endian_to_native (&m_tag->ape_tag_hdr, APE_Tag_Hdr_Format); - } - - if (!result) - strcpy (wpc->error_message, "can't write WavPack data, disk probably full!"); - - return result; -} - -static int write_tag_reader (WavpackContext *wpc) -{ - M_Tag *m_tag = &wpc->m_tag; - int32_t tag_size = 0; - int result = TRUE; - - if (m_tag->ape_tag_hdr.ID [0] == 'A' && m_tag->ape_tag_hdr.item_count && - m_tag->ape_tag_hdr.length > sizeof (m_tag->ape_tag_hdr)) - tag_size = m_tag->ape_tag_hdr.length + sizeof (m_tag->ape_tag_hdr); - - result = (wpc->open_flags & OPEN_EDIT_TAGS) && wpc->reader->can_seek (wpc->wv_in) && - !wpc->reader->set_pos_rel (wpc->wv_in, m_tag->tag_file_pos, SEEK_END); - - if (result && tag_size < -m_tag->tag_file_pos) { - int nullcnt = -m_tag->tag_file_pos - tag_size; - char zero [1] = { 0 }; - - while (nullcnt--) - wpc->reader->write_bytes (wpc->wv_in, &zero, 1); - } - - if (result && tag_size) { - m_tag->ape_tag_hdr.flags |= 0x20000000; - native_to_little_endian (&m_tag->ape_tag_hdr, APE_Tag_Hdr_Format); - result = (wpc->reader->write_bytes (wpc->wv_in, &m_tag->ape_tag_hdr, sizeof (m_tag->ape_tag_hdr)) == sizeof (m_tag->ape_tag_hdr)); - little_endian_to_native (&m_tag->ape_tag_hdr, APE_Tag_Hdr_Format); - result = (wpc->reader->write_bytes (wpc->wv_in, m_tag->ape_tag_data, m_tag->ape_tag_hdr.length - sizeof (m_tag->ape_tag_hdr)) == sizeof (m_tag->ape_tag_hdr)); - m_tag->ape_tag_hdr.flags &= ~0x20000000; - native_to_little_endian (&m_tag->ape_tag_hdr, APE_Tag_Hdr_Format); - result = (wpc->reader->write_bytes (wpc->wv_in, &m_tag->ape_tag_hdr, sizeof (m_tag->ape_tag_hdr)) == sizeof (m_tag->ape_tag_hdr)); - little_endian_to_native (&m_tag->ape_tag_hdr, APE_Tag_Hdr_Format); - } - - if (!result) - strcpy (wpc->error_message, "can't write WavPack data, disk probably full!"); - - return result; -} - -#endif - -// Get total number of samples contained in the WavPack file, or -1 if unknown - -uint32_t WavpackGetNumSamples (WavpackContext *wpc) -{ - return wpc ? wpc->total_samples : (uint32_t) -1; -} - -// Get the current sample index position, or -1 if unknown - -uint32_t WavpackGetSampleIndex (WavpackContext *wpc) -{ - if (wpc) { -#if !defined(VER4_ONLY) && !defined(NO_UNPACK) - if (wpc->stream3) - return get_sample_index3 (wpc); - else if (wpc->streams [0]) - return wpc->streams [0]->sample_index; -#else - if (wpc->streams [0]) - return wpc->streams [0]->sample_index; -#endif - } - - return (uint32_t) -1; -} - -// Get the number of errors encountered so far - -int WavpackGetNumErrors (WavpackContext *wpc) -{ - return wpc ? wpc->crc_errors : 0; -} - -// return TRUE if any uncorrected lossy blocks were actually written or read - -int WavpackLossyBlocks (WavpackContext *wpc) -{ - return wpc ? wpc->lossy_blocks : 0; -} - -// Calculate the progress through the file as a double from 0.0 (for begin) -// to 1.0 (for done). A return value of -1.0 indicates that the progress is -// unknown. - -double WavpackGetProgress (WavpackContext *wpc) -{ - if (wpc && wpc->total_samples != (uint32_t) -1 && wpc->total_samples != 0) - return (double) WavpackGetSampleIndex (wpc) / wpc->total_samples; - else - return -1.0; -} - -// Return the total size of the WavPack file(s) in bytes. - -uint32_t WavpackGetFileSize (WavpackContext *wpc) -{ - return wpc ? wpc->filelen + wpc->file2len : 0; -} - -// Calculate the ratio of the specified WavPack file size to the size of the -// original audio data as a double greater than 0.0 and (usually) smaller than -// 1.0. A value greater than 1.0 represents "negative" compression and a -// return value of 0.0 indicates that the ratio cannot be determined. - -double WavpackGetRatio (WavpackContext *wpc) -{ - if (wpc && wpc->total_samples != (uint32_t) -1 && wpc->filelen) { - double output_size = (double) wpc->total_samples * wpc->config.num_channels * - wpc->config.bytes_per_sample; - double input_size = (double) wpc->filelen + wpc->file2len; - - if (output_size >= 1.0 && input_size >= 1.0) - return input_size / output_size; - } - - return 0.0; -} - -// Calculate the average bitrate of the WavPack file in bits per second. A -// return of 0.0 indicates that the bitrate cannot be determined. An option is -// provided to use (or not use) any attendant .wvc file. - -double WavpackGetAverageBitrate (WavpackContext *wpc, int count_wvc) -{ - if (wpc && wpc->total_samples != (uint32_t) -1 && wpc->filelen) { - double output_time = (double) wpc->total_samples / wpc->config.sample_rate; - double input_size = (double) wpc->filelen + (count_wvc ? wpc->file2len : 0); - - if (output_time >= 0.1 && input_size >= 1.0) - return input_size * 8.0 / output_time; - } - - return 0.0; -} - -#ifndef NO_UNPACK - -// Calculate the bitrate of the current WavPack file block in bits per second. -// This can be used for an "instant" bit display and gets updated from about -// 1 to 4 times per second. A return of 0.0 indicates that the bitrate cannot -// be determined. - -double WavpackGetInstantBitrate (WavpackContext *wpc) -{ - if (wpc->stream3) - return WavpackGetAverageBitrate (wpc, TRUE); - - if (wpc && wpc->streams [0] && wpc->streams [0]->wphdr.block_samples) { - double output_time = (double) wpc->streams [0]->wphdr.block_samples / wpc->config.sample_rate; - double input_size = 0; - int si; - - for (si = 0; si < wpc->num_streams; ++si) { - if (wpc->streams [si]->blockbuff) - input_size += ((WavpackHeader *) wpc->streams [si]->blockbuff)->ckSize; - - if (wpc->streams [si]->block2buff) - input_size += ((WavpackHeader *) wpc->streams [si]->block2buff)->ckSize; - } - - if (output_time > 0.0 && input_size >= 1.0) - return input_size * 8.0 / output_time; - } - - return 0.0; -} - -#endif - -// Close the specified WavPack file and release all resources used by it. -// Returns NULL. - -WavpackContext *WavpackCloseFile (WavpackContext *wpc) -{ - free_streams (wpc); - - if (wpc->streams [0]) - free (wpc->streams [0]); - -#if !defined(VER4_ONLY) && !defined(NO_UNPACK) - if (wpc->stream3) - free_stream3 (wpc); -#endif - -#if !defined(NO_UNPACK) || defined(INFO_ONLY) - if (wpc->close_files) { -#ifndef NO_USE_FSTREAMS - if (wpc->wv_in != NULL) - fclose (wpc->wv_in); - - if (wpc->wvc_in != NULL) - fclose (wpc->wvc_in); -#endif - } - - WavpackFreeWrapper (wpc); -#endif - -#ifndef NO_TAGS - free_tag (&wpc->m_tag); -#endif - - free (wpc); - - return NULL; -} - -// Returns the sample rate of the specified WavPack file - -uint32_t WavpackGetSampleRate (WavpackContext *wpc) -{ - return wpc ? wpc->config.sample_rate : 44100; -} - -// Returns the number of channels of the specified WavPack file. Note that -// this is the actual number of channels contained in the file even if the -// OPEN_2CH_MAX flag was specified when the file was opened. - -int WavpackGetNumChannels (WavpackContext *wpc) -{ - return wpc ? wpc->config.num_channels : 2; -} - -// Returns the standard Microsoft channel mask for the specified WavPack -// file. A value of zero indicates that there is no speaker assignment -// information. - -int WavpackGetChannelMask (WavpackContext *wpc) -{ - return wpc ? wpc->config.channel_mask : 0; -} - -// Return the normalization value for floating point data (valid only -// if floating point data is present). A value of 127 indicates that -// the floating point range is +/- 1.0. Higher values indicate a -// larger floating point range. - -int WavpackGetFloatNormExp (WavpackContext *wpc) -{ - return wpc->config.float_norm_exp; -} - -// Returns the actual number of valid bits per sample contained in the -// original file, which may or may not be a multiple of 8. Floating data -// always has 32 bits, integers may be from 1 to 32 bits each. When this -// value is not a multiple of 8, then the "extra" bits are located in the -// LSBs of the results. That is, values are right justified when unpacked -// into ints, but are left justified in the number of bytes used by the -// original data. - -int WavpackGetBitsPerSample (WavpackContext *wpc) -{ - return wpc ? wpc->config.bits_per_sample : 16; -} - -// Returns the number of bytes used for each sample (1 to 4) in the original -// file. This is required information for the user of this module because the -// audio data is returned in the LOWER bytes of the long buffer and must be -// left-shifted 8, 16, or 24 bits if normalized longs are required. - -int WavpackGetBytesPerSample (WavpackContext *wpc) -{ - return wpc ? wpc->config.bytes_per_sample : 2; -} - -#if !defined(NO_UNPACK) || defined(INFO_ONLY) - -// If the OPEN_2CH_MAX flag is specified when opening the file, this function -// will return the actual number of channels decoded from the file (which may -// or may not be less than the actual number of channels, but will always be -// 1 or 2). Normally, this will be the front left and right channels of a -// multichannel file. - -int WavpackGetReducedChannels (WavpackContext *wpc) -{ - if (wpc) - return wpc->reduced_channels ? wpc->reduced_channels : wpc->config.num_channels; - else - return 2; -} - -// These routines are used to access (and free) header and trailer data that -// was retrieved from the Wavpack file. The header will be available before -// the samples are decoded and the trailer will be available after all samples -// have been read. - -uint32_t WavpackGetWrapperBytes (WavpackContext *wpc) -{ - return wpc ? wpc->wrapper_bytes : 0; -} - -uchar *WavpackGetWrapperData (WavpackContext *wpc) -{ - return wpc ? wpc->wrapper_data : NULL; -} - -void WavpackFreeWrapper (WavpackContext *wpc) -{ - if (wpc && wpc->wrapper_data) { - free (wpc->wrapper_data); - wpc->wrapper_data = NULL; - wpc->wrapper_bytes = 0; - } -} - -// Normally the trailing wrapper will not be available when a WavPack file is first -// opened for reading because it is stored in the final block of the file. This -// function forces a seek to the end of the file to pick up any trailing wrapper -// stored there (then use WavPackGetWrapper**() to obtain). This can obviously only -// be used for seekable files (not pipes) and is not available for pre-4.0 WavPack -// files. - -static void seek_riff_trailer (WavpackContext *wpc); - -void WavpackSeekTrailingWrapper (WavpackContext *wpc) -{ - if ((wpc->open_flags & OPEN_WRAPPER) && - wpc->reader->can_seek (wpc->wv_in) && !wpc->stream3) { - uint32_t pos_save = wpc->reader->get_pos (wpc->wv_in); - - seek_riff_trailer (wpc); - wpc->reader->set_pos_abs (wpc->wv_in, pos_save); - } -} - -// Get any MD5 checksum stored in the metadata (should be called after reading -// last sample or an extra seek will occur). A return value of FALSE indicates -// that no MD5 checksum was stored. - -static int seek_md5 (WavpackStreamReader *reader, void *id, uchar data [16]); - -int WavpackGetMD5Sum (WavpackContext *wpc, uchar data [16]) -{ - if (wpc->config.flags & CONFIG_MD5_CHECKSUM) { - if (wpc->config.md5_read) { - memcpy (data, wpc->config.md5_checksum, 16); - return TRUE; - } - else if (wpc->reader->can_seek (wpc->wv_in)) { - uint32_t pos_save = wpc->reader->get_pos (wpc->wv_in); - - wpc->config.md5_read = seek_md5 (wpc->reader, wpc->wv_in, wpc->config.md5_checksum); - wpc->reader->set_pos_abs (wpc->wv_in, pos_save); - - if (wpc->config.md5_read) { - memcpy (data, wpc->config.md5_checksum, 16); - return TRUE; - } - else - return FALSE; - } - } - - return FALSE; -} - -#endif - -// Free all memory allocated for raw WavPack blocks (for all allocated streams) -// and free all additonal streams. This does not free the default stream ([0]) -// which is always kept around. - -static void free_streams (WavpackContext *wpc) -{ - int si = wpc->num_streams; - - while (si--) { - if (wpc->streams [si]->blockbuff) { - free (wpc->streams [si]->blockbuff); - wpc->streams [si]->blockbuff = NULL; - } - - if (wpc->streams [si]->block2buff) { - free (wpc->streams [si]->block2buff); - wpc->streams [si]->block2buff = NULL; - } - - if (wpc->streams [si]->sample_buffer) { - free (wpc->streams [si]->sample_buffer); - wpc->streams [si]->sample_buffer = NULL; - } - - if (wpc->streams [si]->dc.shaping_data) { - free (wpc->streams [si]->dc.shaping_data); - wpc->streams [si]->dc.shaping_data = NULL; - } - - if (si) { - wpc->num_streams--; - free (wpc->streams [si]); - wpc->streams [si] = NULL; - } - } - - wpc->current_stream = 0; -} - -#ifndef NO_TAGS - -// Return TRUE is a valid ID3v1 or APEv2 tag has been loaded. - -static int valid_tag (M_Tag *m_tag) -{ - if (m_tag->ape_tag_hdr.ID [0] == 'A') - return 'A'; - else if (m_tag->id3_tag.tag_id [0] == 'T') - return 'T'; - else - return 0; -} - -// Free the data for any APEv2 tag that was allocated. - -static void free_tag (M_Tag *m_tag) -{ - if (m_tag->ape_tag_data) { - free (m_tag->ape_tag_data); - m_tag->ape_tag_data = NULL; - } -} - -#endif - -#if !defined(NO_UNPACK) || defined(INFO_ONLY) - -// Read from current file position until a valid 32-byte WavPack 4.0 header is -// found and read into the specified pointer. The number of bytes skipped is -// returned. If no WavPack header is found within 1 meg, then a -1 is returned -// to indicate the error. No additional bytes are read past the header and it -// is returned in the processor's native endian mode. Seeking is not required. - -static uint32_t read_next_header (WavpackStreamReader *reader, void *id, WavpackHeader *wphdr) -{ - unsigned char buffer [sizeof (*wphdr)], *sp = buffer + sizeof (*wphdr), *ep = sp; - uint32_t bytes_skipped = 0; - int bleft; - - while (1) { - if (sp < ep) { - bleft = (int)(ep - sp); - memcpy (buffer, sp, bleft); - } - else - bleft = 0; - - if (reader->read_bytes (id, buffer + bleft, sizeof (*wphdr) - bleft) != sizeof (*wphdr) - bleft) - return -1; - - sp = buffer; - - if (*sp++ == 'w' && *sp == 'v' && *++sp == 'p' && *++sp == 'k' && - !(*++sp & 1) && sp [2] < 16 && !sp [3] && (sp [2] || sp [1] || *sp > 24) && sp [5] == 4 && - sp [4] >= (MIN_STREAM_VERS & 0xff) && sp [4] <= (MAX_STREAM_VERS & 0xff) && sp [18] < 3 && !sp [19]) { - memcpy (wphdr, buffer, sizeof (*wphdr)); - little_endian_to_native (wphdr, WavpackHeaderFormat); - return bytes_skipped; - } - - while (sp < ep && *sp != 'w') - sp++; - - if ((bytes_skipped += (uint32_t)(sp - buffer)) > 1024 * 1024) - return -1; - } -} - -// This function is used to seek to end of a file to determine its actual -// length in samples by reading the last header block containing data. -// Currently, all WavPack files contain the sample length in the first block -// containing samples, however this might not always be the case. Obviously, -// this function requires a seekable file or stream and leaves the file -// pointer undefined. A return value of -1 indicates the length could not -// be determined. - -static uint32_t seek_final_index (WavpackStreamReader *reader, void *id) -{ - uint32_t result = (uint32_t) -1, bcount; - WavpackHeader wphdr; - uchar *tempbuff; - - if (reader->get_length (id) > 1200000L) - reader->set_pos_rel (id, -1048576L, SEEK_END); - else - reader->set_pos_abs (id, 0); - - while (1) { - bcount = read_next_header (reader, id, &wphdr); - - if (bcount == (uint32_t) -1) - return result; - - tempbuff = malloc (wphdr.ckSize + 8); - memcpy (tempbuff, &wphdr, 32); - - if (reader->read_bytes (id, tempbuff + 32, wphdr.ckSize - 24) != wphdr.ckSize - 24) { - free (tempbuff); - return result; - } - - free (tempbuff); - - if (wphdr.block_samples && (wphdr.flags & FINAL_BLOCK)) - result = wphdr.block_index + wphdr.block_samples; - } -} - -static int seek_md5 (WavpackStreamReader *reader, void *id, uchar data [16]) -{ - uchar meta_id, c1, c2; - uint32_t bcount, meta_bc; - WavpackHeader wphdr; - - if (reader->get_length (id) > 1200000L) - reader->set_pos_rel (id, -1048576L, SEEK_END); - - while (1) { - bcount = read_next_header (reader, id, &wphdr); - - if (bcount == (uint32_t) -1) - return FALSE; - - bcount = wphdr.ckSize - sizeof (WavpackHeader) + 8; - - while (bcount >= 2) { - if (reader->read_bytes (id, &meta_id, 1) != 1 || - reader->read_bytes (id, &c1, 1) != 1) - return FALSE; - - meta_bc = c1 << 1; - bcount -= 2; - - if (meta_id & ID_LARGE) { - if (bcount < 2 || reader->read_bytes (id, &c1, 1) != 1 || - reader->read_bytes (id, &c2, 1) != 1) - return FALSE; - - meta_bc += ((uint32_t) c1 << 9) + ((uint32_t) c2 << 17); - bcount -= 2; - } - - if (meta_id == ID_MD5_CHECKSUM) - return (meta_bc == 16 && bcount >= 16 && - reader->read_bytes (id, data, 16) == 16); - - reader->set_pos_rel (id, meta_bc, SEEK_CUR); - bcount -= meta_bc; - } - } -} - -static void seek_riff_trailer (WavpackContext *wpc) -{ - WavpackStreamReader *reader = wpc->reader; - void *id = wpc->wv_in; - uchar meta_id, c1, c2; - uint32_t bcount, meta_bc; - WavpackHeader wphdr; - - if (reader->get_length (id) > 1200000L) - reader->set_pos_rel (id, -1048576L, SEEK_END); - - while (1) { - bcount = read_next_header (reader, id, &wphdr); - - if (bcount == (uint32_t) -1) - return; - - bcount = wphdr.ckSize - sizeof (WavpackHeader) + 8; - - while (bcount >= 2) { - if (reader->read_bytes (id, &meta_id, 1) != 1 || - reader->read_bytes (id, &c1, 1) != 1) - return; - - meta_bc = c1 << 1; - bcount -= 2; - - if (meta_id & ID_LARGE) { - if (bcount < 2 || reader->read_bytes (id, &c1, 1) != 1 || - reader->read_bytes (id, &c2, 1) != 1) - return; - - meta_bc += ((uint32_t) c1 << 9) + ((uint32_t) c2 << 17); - bcount -= 2; - } - - if ((meta_id & ID_UNIQUE) == ID_RIFF_TRAILER) { - wpc->wrapper_data = realloc (wpc->wrapper_data, wpc->wrapper_bytes + meta_bc); - - if (reader->read_bytes (id, wpc->wrapper_data + wpc->wrapper_bytes, meta_bc) == meta_bc) - wpc->wrapper_bytes += meta_bc; - else - return; - } - else - reader->set_pos_rel (id, meta_bc, SEEK_CUR); - - bcount -= meta_bc; - } - } -} - -// Compare the regular wv file block header to a potential matching wvc -// file block header and return action code based on analysis: -// -// 0 = use wvc block (assuming rest of block is readable) -// 1 = bad match; try to read next wvc block -// -1 = bad match; ignore wvc file for this block and backup fp (if -// possible) and try to use this block next time - -static int match_wvc_header (WavpackHeader *wv_hdr, WavpackHeader *wvc_hdr) -{ - if (wv_hdr->block_index == wvc_hdr->block_index && - wv_hdr->block_samples == wvc_hdr->block_samples) { - int wvi = 0, wvci = 0; - - if (wv_hdr->flags == wvc_hdr->flags) - return 0; - - if (wv_hdr->flags & INITIAL_BLOCK) - wvi -= 1; - - if (wv_hdr->flags & FINAL_BLOCK) - wvi += 1; - - if (wvc_hdr->flags & INITIAL_BLOCK) - wvci -= 1; - - if (wvc_hdr->flags & FINAL_BLOCK) - wvci += 1; - - return (wvci - wvi < 0) ? 1 : -1; - } - - if ((int32_t)(wvc_hdr->block_index - wv_hdr->block_index) < 0) - return 1; - else - return -1; -} - -// Read the wvc block that matches the regular wv block that has been -// read for the current stream. If an exact match is not found then -// we either keep reading or back up and (possibly) use the block -// later. The skip_wvc flag is set if not matching wvc block is found -// so that we can still decode using only the lossy version (although -// we flag this as an error). A return of FALSE indicates a serious -// error (not just that we missed one wvc block). - -static int read_wvc_block (WavpackContext *wpc) -{ - WavpackStream *wps = wpc->streams [wpc->current_stream]; - uint32_t bcount, file2pos; - WavpackHeader wphdr; - int compare_result; - - while (1) { - file2pos = wpc->reader->get_pos (wpc->wvc_in); - bcount = read_next_header (wpc->reader, wpc->wvc_in, &wphdr); - - if (bcount == (uint32_t) -1) { - wps->wvc_skip = TRUE; - wpc->crc_errors++; - return FALSE; - } - - if (wpc->open_flags & OPEN_STREAMING) - wphdr.block_index = wps->sample_index = 0; - else - wphdr.block_index -= wpc->initial_index; - - if (wphdr.flags & INITIAL_BLOCK) - wpc->file2pos = file2pos + bcount; - - compare_result = match_wvc_header (&wps->wphdr, &wphdr); - - if (!compare_result) { - wps->block2buff = malloc (wphdr.ckSize + 8); - memcpy (wps->block2buff, &wphdr, 32); - - if (wpc->reader->read_bytes (wpc->wvc_in, wps->block2buff + 32, wphdr.ckSize - 24) != - wphdr.ckSize - 24 || (wphdr.flags & UNKNOWN_FLAGS)) { - free (wps->block2buff); - wps->block2buff = NULL; - wps->wvc_skip = TRUE; - wpc->crc_errors++; - return FALSE; - } - - wps->wvc_skip = FALSE; - memcpy (&wps->wphdr, &wphdr, 32); - return TRUE; - } - else if (compare_result == -1) { - wps->wvc_skip = TRUE; - wpc->reader->set_pos_rel (wpc->wvc_in, -32, SEEK_CUR); - wpc->crc_errors++; - return TRUE; - } - } -} - -#ifndef NO_SEEKING - -// Find a valid WavPack header, searching either from the current file position -// (or from the specified position if not -1) and store it (endian corrected) -// at the specified pointer. The return value is the exact file position of the -// header, although we may have actually read past it. Because this function -// is used for seeking to a specific audio sample, it only considers blocks -// that contain audio samples for the initial stream to be valid. - -#define BUFSIZE 4096 - -static uint32_t find_header (WavpackStreamReader *reader, void *id, uint32_t filepos, WavpackHeader *wphdr) -{ - unsigned char *buffer = malloc (BUFSIZE), *sp = buffer, *ep = buffer; - - if (filepos != (uint32_t) -1 && reader->set_pos_abs (id, filepos)) { - free (buffer); - return -1; - } - - while (1) { - int bleft; - - if (sp < ep) { - bleft = (int)(ep - sp); - memcpy (buffer, sp, bleft); - ep -= (sp - buffer); - sp = buffer; - } - else { - if (sp > ep) - if (reader->set_pos_rel (id, (int32_t)(sp - ep), SEEK_CUR)) { - free (buffer); - return -1; - } - - sp = ep = buffer; - bleft = 0; - } - - ep += reader->read_bytes (id, ep, BUFSIZE - bleft); - - if (ep - sp < 32) { - free (buffer); - return -1; - } - - while (sp + 32 <= ep) - if (*sp++ == 'w' && *sp == 'v' && *++sp == 'p' && *++sp == 'k' && - !(*++sp & 1) && sp [2] < 16 && !sp [3] && (sp [2] || sp [1] || *sp > 24) && sp [5] == 4 && - sp [4] >= (MIN_STREAM_VERS & 0xff) && sp [4] <= (MAX_STREAM_VERS & 0xff) && sp [18] < 3 && !sp [19]) { - memcpy (wphdr, sp - 4, sizeof (*wphdr)); - little_endian_to_native (wphdr, WavpackHeaderFormat); - - if (wphdr->block_samples && (wphdr->flags & INITIAL_BLOCK)) { - free (buffer); - return reader->get_pos (id) - (uint32_t)(ep - sp + 4); - } - - if (wphdr->ckSize > 1024) - sp += wphdr->ckSize - 1024; - } - } -} - -// Find the WavPack block that contains the specified sample. If "header_pos" -// is zero, then no information is assumed except the total number of samples -// in the file and its size in bytes. If "header_pos" is non-zero then we -// assume that it is the file position of the valid header image contained in -// the first stream and we can limit our search to either the portion above -// or below that point. If a .wvc file is being used, then this must be called -// for that file also. - -static uint32_t find_sample (WavpackContext *wpc, void *infile, uint32_t header_pos, uint32_t sample) -{ - WavpackStream *wps = wpc->streams [wpc->current_stream]; - uint32_t file_pos1 = 0, file_pos2 = wpc->reader->get_length (infile); - uint32_t sample_pos1 = 0, sample_pos2 = wpc->total_samples; - double ratio = 0.96; - int file_skip = 0; - - if (sample >= wpc->total_samples) - return -1; - - if (header_pos && wps->wphdr.block_samples) { - if (wps->wphdr.block_index > sample) { - sample_pos2 = wps->wphdr.block_index; - file_pos2 = header_pos; - } - else if (wps->wphdr.block_index + wps->wphdr.block_samples <= sample) { - sample_pos1 = wps->wphdr.block_index; - file_pos1 = header_pos; - } - else - return header_pos; - } - - while (1) { - double bytes_per_sample; - uint32_t seek_pos; - - bytes_per_sample = file_pos2 - file_pos1; - bytes_per_sample /= sample_pos2 - sample_pos1; - seek_pos = file_pos1 + (file_skip ? 32 : 0); - seek_pos += (uint32_t)(bytes_per_sample * (sample - sample_pos1) * ratio); - seek_pos = find_header (wpc->reader, infile, seek_pos, &wps->wphdr); - - if (seek_pos != (uint32_t) -1) - wps->wphdr.block_index -= wpc->initial_index; - - if (seek_pos == (uint32_t) -1 || seek_pos >= file_pos2) { - if (ratio > 0.0) { - if ((ratio -= 0.24) < 0.0) - ratio = 0.0; - } - else - return -1; - } - else if (wps->wphdr.block_index > sample) { - sample_pos2 = wps->wphdr.block_index; - file_pos2 = seek_pos; - } - else if (wps->wphdr.block_index + wps->wphdr.block_samples <= sample) { - - if (seek_pos == file_pos1) - file_skip = 1; - else { - sample_pos1 = wps->wphdr.block_index; - file_pos1 = seek_pos; - } - } - else - return seek_pos; - } -} - -#endif - -#ifndef NO_TAGS - -// This function attempts to load an ID3v1 or APEv2 tag from the specified -// file into the specified M_Tag structure. The ID3 tag fits in completely, -// but an APEv2 tag is variable length and so space must be allocated here -// to accomodate the data, and this will need to be freed later. A return -// value of TRUE indicates a valid tag was found and loaded. Note that the -// file pointer is undefined when this function exits. - -static int load_tag (WavpackContext *wpc) -{ - int ape_tag_length, ape_tag_items; - M_Tag *m_tag = &wpc->m_tag; - - CLEAR (*m_tag); - - while (1) { - - // attempt to find an APEv2 tag either at end-of-file or before a ID3v1 tag we found - - if (m_tag->id3_tag.tag_id [0] == 'T') - wpc->reader->set_pos_rel (wpc->wv_in, -(int32_t)(sizeof (APE_Tag_Hdr) + sizeof (ID3_Tag)), SEEK_END); - else - wpc->reader->set_pos_rel (wpc->wv_in, -(int32_t)sizeof (APE_Tag_Hdr), SEEK_END); - - if (wpc->reader->read_bytes (wpc->wv_in, &m_tag->ape_tag_hdr, sizeof (APE_Tag_Hdr)) == sizeof (APE_Tag_Hdr) && - !strncmp (m_tag->ape_tag_hdr.ID, "APETAGEX", 8)) { - - little_endian_to_native (&m_tag->ape_tag_hdr, APE_Tag_Hdr_Format); - - if (m_tag->ape_tag_hdr.version == 2000 && m_tag->ape_tag_hdr.item_count && - m_tag->ape_tag_hdr.length > sizeof (m_tag->ape_tag_hdr) && - m_tag->ape_tag_hdr.length < (1024 * 1024) && - (m_tag->ape_tag_data = malloc (m_tag->ape_tag_hdr.length)) != NULL) { - - ape_tag_items = m_tag->ape_tag_hdr.item_count; - ape_tag_length = m_tag->ape_tag_hdr.length; - - if (m_tag->id3_tag.tag_id [0] == 'T') - m_tag->tag_file_pos = -(int32_t)sizeof (ID3_Tag); - else - m_tag->tag_file_pos = 0; - - m_tag->tag_file_pos -= ape_tag_length + sizeof (APE_Tag_Hdr); - wpc->reader->set_pos_rel (wpc->wv_in, m_tag->tag_file_pos, SEEK_END); - memset (m_tag->ape_tag_data, 0, ape_tag_length); - - if (wpc->reader->read_bytes (wpc->wv_in, &m_tag->ape_tag_hdr, sizeof (APE_Tag_Hdr)) != - sizeof (APE_Tag_Hdr) || strncmp (m_tag->ape_tag_hdr.ID, "APETAGEX", 8)) { - free (m_tag->ape_tag_data); - CLEAR (*m_tag); - return FALSE; // something's wrong... - } - - little_endian_to_native (&m_tag->ape_tag_hdr, APE_Tag_Hdr_Format); - - if (m_tag->ape_tag_hdr.version != 2000 || m_tag->ape_tag_hdr.item_count != ape_tag_items || - m_tag->ape_tag_hdr.length != ape_tag_length) { - free (m_tag->ape_tag_data); - CLEAR (*m_tag); - return FALSE; // something's wrong... - } - - if (wpc->reader->read_bytes (wpc->wv_in, m_tag->ape_tag_data, - ape_tag_length - sizeof (APE_Tag_Hdr)) != ape_tag_length - sizeof (APE_Tag_Hdr)) { - free (m_tag->ape_tag_data); - CLEAR (*m_tag); - return FALSE; // something's wrong... - } - else { - CLEAR (m_tag->id3_tag); // ignore ID3v1 tag if we found APEv2 tag - return TRUE; - } - } - } - - if (m_tag->id3_tag.tag_id [0] == 'T') { // settle for the ID3v1 tag that we found - CLEAR (m_tag->ape_tag_hdr); - return TRUE; - } - - // look for ID3v1 tag if APEv2 tag not found during first pass - - m_tag->tag_file_pos = -(int32_t)sizeof (ID3_Tag); - wpc->reader->set_pos_rel (wpc->wv_in, m_tag->tag_file_pos, SEEK_END); - - if (wpc->reader->read_bytes (wpc->wv_in, &m_tag->id3_tag, sizeof (ID3_Tag)) != sizeof (ID3_Tag) || - strncmp (m_tag->id3_tag.tag_id, "TAG", 3)) { - CLEAR (*m_tag); - return FALSE; // neither type of tag found - } - } -} - -// Copy the specified ID3v1 tag value (with specified field size) from the -// source pointer to the destination, eliminating leading spaces and trailing -// spaces and nulls. - -static void tagcpy (char *dest, char *src, int tag_size) -{ - char *s1 = src, *s2 = src + tag_size - 1; - - if (*s2 && !s2 [-1]) - s2--; - - while (s1 <= s2) - if (*s1 == ' ') - ++s1; - else if (!*s2 || *s2 == ' ') - --s2; - else - break; - - while (*s1 && s1 <= s2) - *dest++ = *s1++; - - *dest = 0; -} - -static int tagdata (char *src, int tag_size) -{ - char *s1 = src, *s2 = src + tag_size - 1; - - if (*s2 && !s2 [-1]) - s2--; - - while (s1 <= s2) - if (*s1 == ' ') - ++s1; - else if (!*s2 || *s2 == ' ') - --s2; - else - break; - - return (*s1 && s1 <= s2); -} - -#endif - -#endif - -void WavpackLittleEndianToNative (void *data, char *format) -{ - little_endian_to_native (data, format); -} - -void WavpackNativeToLittleEndian (void *data, char *format) -{ - native_to_little_endian (data, format); -} - -uint32_t WavpackGetLibraryVersion (void) -{ - return (LIBWAVPACK_MAJOR<<16) - |(LIBWAVPACK_MINOR<<8) - |(LIBWAVPACK_MICRO<<0); -} - -const char *WavpackGetLibraryVersionString (void) -{ - return LIBWAVPACK_VERSION_STRING; -} -