Should be the last of the trunk, gotta finish the branches/tags, but thats the main bulk transferred.
git-svn-id: http://pcsx2.googlecode.com/svn/trunk@426 96395faa-99c1-11dd-bbfe-3dabce05a288
|
@ -0,0 +1,350 @@
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
///
|
||||||
|
/// Win32 version of the AMD 3DNow! optimized routines for AMD K6-2/Athlon
|
||||||
|
/// processors. All 3DNow! optimized functions have been gathered into this
|
||||||
|
/// single source code file, regardless to their class or original source code
|
||||||
|
/// file, in order to ease porting the library to other compiler and processor
|
||||||
|
/// platforms.
|
||||||
|
///
|
||||||
|
/// By the way; the performance gain depends heavily on the CPU generation: On
|
||||||
|
/// K6-2 these routines provided speed-up of even 2.4 times, while on Athlon the
|
||||||
|
/// difference to the original routines stayed at unremarkable 8%! Such a small
|
||||||
|
/// improvement on Athlon is due to 3DNow can perform only two operations in
|
||||||
|
/// parallel, and obviously also the Athlon FPU is doing a very good job with
|
||||||
|
/// the standard C floating point routines! Here these routines are anyway,
|
||||||
|
/// although it might not be worth the effort to convert these to GCC platform,
|
||||||
|
/// for Athlon CPU at least. The situation is different regarding the SSE
|
||||||
|
/// optimizations though, thanks to the four parallel operations of SSE that
|
||||||
|
/// already make a difference.
|
||||||
|
///
|
||||||
|
/// This file is to be compiled in Windows platform with Microsoft Visual C++
|
||||||
|
/// Compiler. Please see '3dnow_gcc.cpp' for the gcc compiler version for all
|
||||||
|
/// GNU platforms (if file supplied).
|
||||||
|
///
|
||||||
|
/// NOTICE: If using Visual Studio 6.0, you'll need to install the "Visual C++
|
||||||
|
/// 6.0 processor pack" update to support 3DNow! instruction set. The update is
|
||||||
|
/// available for download at Microsoft Developers Network, see here:
|
||||||
|
/// http://msdn.microsoft.com/vstudio/downloads/tools/ppack/default.aspx
|
||||||
|
///
|
||||||
|
/// If the above URL is expired or removed, go to "http://msdn.microsoft.com" and
|
||||||
|
/// perform a search with keywords "processor pack".
|
||||||
|
///
|
||||||
|
/// Author : Copyright (c) Olli Parviainen
|
||||||
|
/// Author e-mail : oparviai 'at' iki.fi
|
||||||
|
/// SoundTouch WWW: http://www.surina.net/soundtouch
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Last changed : $Date: 2006/02/05 16:44:06 $
|
||||||
|
// File revision : $Revision: 1.10 $
|
||||||
|
//
|
||||||
|
// $Id: 3dnow_win.cpp,v 1.10 2006/02/05 16:44:06 Olli Exp $
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// License :
|
||||||
|
//
|
||||||
|
// SoundTouch audio processing library
|
||||||
|
// Copyright (c) Olli Parviainen
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU Lesser General Public
|
||||||
|
// License as published by the Free Software Foundation; either
|
||||||
|
// version 2.1 of the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include "cpu_detect.h"
|
||||||
|
#include "STTypes.h"
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
|
#error "wrong platform - this source code file is exclusively for Win32 platform"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
using namespace soundtouch;
|
||||||
|
|
||||||
|
#ifdef ALLOW_3DNOW
|
||||||
|
// 3DNow! routines available only with float sample type
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// implementation of 3DNow! optimized functions of class 'TDStretch3DNow'
|
||||||
|
//
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include "TDStretch.h"
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
|
// these are declared in 'TDStretch.cpp'
|
||||||
|
extern int scanOffsets[4][24];
|
||||||
|
|
||||||
|
|
||||||
|
// Calculates cross correlation of two buffers
|
||||||
|
double TDStretch3DNow::calcCrossCorrStereo(const float *pV1, const float *pV2) const
|
||||||
|
{
|
||||||
|
uint overlapLengthLocal = overlapLength;
|
||||||
|
float corr;
|
||||||
|
|
||||||
|
// Calculates the cross-correlation value between 'pV1' and 'pV2' vectors
|
||||||
|
/*
|
||||||
|
c-pseudocode:
|
||||||
|
|
||||||
|
corr = 0;
|
||||||
|
for (i = 0; i < overlapLength / 4; i ++)
|
||||||
|
{
|
||||||
|
corr += pV1[0] * pV2[0];
|
||||||
|
pV1[1] * pV2[1];
|
||||||
|
pV1[2] * pV2[2];
|
||||||
|
pV1[3] * pV2[3];
|
||||||
|
pV1[4] * pV2[4];
|
||||||
|
pV1[5] * pV2[5];
|
||||||
|
pV1[6] * pV2[6];
|
||||||
|
pV1[7] * pV2[7];
|
||||||
|
|
||||||
|
pV1 += 8;
|
||||||
|
pV2 += 8;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
_asm
|
||||||
|
{
|
||||||
|
// give prefetch hints to CPU of what data are to be needed soonish.
|
||||||
|
// give more aggressive hints on pV1 as that changes more between different calls
|
||||||
|
// while pV2 stays the same.
|
||||||
|
prefetch [pV1]
|
||||||
|
prefetch [pV2]
|
||||||
|
prefetch [pV1 + 32]
|
||||||
|
|
||||||
|
mov eax, dword ptr pV2
|
||||||
|
mov ebx, dword ptr pV1
|
||||||
|
|
||||||
|
pxor mm0, mm0
|
||||||
|
|
||||||
|
mov ecx, overlapLengthLocal
|
||||||
|
shr ecx, 2 // div by four
|
||||||
|
|
||||||
|
loop1:
|
||||||
|
movq mm1, [eax]
|
||||||
|
prefetch [eax + 32] // give a prefetch hint to CPU what data are to be needed soonish
|
||||||
|
pfmul mm1, [ebx]
|
||||||
|
prefetch [ebx + 64] // give a prefetch hint to CPU what data are to be needed soonish
|
||||||
|
|
||||||
|
movq mm2, [eax + 8]
|
||||||
|
pfadd mm0, mm1
|
||||||
|
pfmul mm2, [ebx + 8]
|
||||||
|
|
||||||
|
movq mm3, [eax + 16]
|
||||||
|
pfadd mm0, mm2
|
||||||
|
pfmul mm3, [ebx + 16]
|
||||||
|
|
||||||
|
movq mm4, [eax + 24]
|
||||||
|
pfadd mm0, mm3
|
||||||
|
pfmul mm4, [ebx + 24]
|
||||||
|
|
||||||
|
add eax, 32
|
||||||
|
pfadd mm0, mm4
|
||||||
|
add ebx, 32
|
||||||
|
|
||||||
|
dec ecx
|
||||||
|
jnz loop1
|
||||||
|
|
||||||
|
// add halfs of mm0 together and return the result.
|
||||||
|
// note: mm1 is used as a dummy parameter only, we actually don't care about it's value
|
||||||
|
pfacc mm0, mm1
|
||||||
|
movd corr, mm0
|
||||||
|
femms
|
||||||
|
}
|
||||||
|
|
||||||
|
return corr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// implementation of 3DNow! optimized functions of class 'FIRFilter'
|
||||||
|
//
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include "FIRFilter.h"
|
||||||
|
|
||||||
|
FIRFilter3DNow::FIRFilter3DNow() : FIRFilter()
|
||||||
|
{
|
||||||
|
filterCoeffsUnalign = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
FIRFilter3DNow::~FIRFilter3DNow()
|
||||||
|
{
|
||||||
|
delete[] filterCoeffsUnalign;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// (overloaded) Calculates filter coefficients for 3DNow! routine
|
||||||
|
void FIRFilter3DNow::setCoefficients(const float *coeffs, uint newLength, uint uResultDivFactor)
|
||||||
|
{
|
||||||
|
uint i;
|
||||||
|
float fDivider;
|
||||||
|
|
||||||
|
FIRFilter::setCoefficients(coeffs, newLength, uResultDivFactor);
|
||||||
|
|
||||||
|
// Scale the filter coefficients so that it won't be necessary to scale the filtering result
|
||||||
|
// also rearrange coefficients suitably for 3DNow!
|
||||||
|
// Ensure that filter coeffs array is aligned to 16-byte boundary
|
||||||
|
delete[] filterCoeffsUnalign;
|
||||||
|
filterCoeffsUnalign = new float[2 * newLength + 4];
|
||||||
|
filterCoeffsAlign = (float *)(((uint)filterCoeffsUnalign + 15) & -16);
|
||||||
|
|
||||||
|
fDivider = (float)resultDivider;
|
||||||
|
|
||||||
|
// rearrange the filter coefficients for mmx routines
|
||||||
|
for (i = 0; i < newLength; i ++)
|
||||||
|
{
|
||||||
|
filterCoeffsAlign[2 * i + 0] =
|
||||||
|
filterCoeffsAlign[2 * i + 1] = coeffs[i + 0] / fDivider;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 3DNow!-optimized version of the filter routine for stereo sound
|
||||||
|
uint FIRFilter3DNow::evaluateFilterStereo(float *dest, const float *src, const uint numSamples) const
|
||||||
|
{
|
||||||
|
float *filterCoeffsLocal = filterCoeffsAlign;
|
||||||
|
uint count = (numSamples - length) & -2;
|
||||||
|
uint lengthLocal = length / 4;
|
||||||
|
|
||||||
|
assert(length != 0);
|
||||||
|
assert(count % 2 == 0);
|
||||||
|
|
||||||
|
/* original code:
|
||||||
|
|
||||||
|
double suml1, suml2;
|
||||||
|
double sumr1, sumr2;
|
||||||
|
uint i, j;
|
||||||
|
|
||||||
|
for (j = 0; j < count; j += 2)
|
||||||
|
{
|
||||||
|
const float *ptr;
|
||||||
|
|
||||||
|
suml1 = sumr1 = 0.0;
|
||||||
|
suml2 = sumr2 = 0.0;
|
||||||
|
ptr = src;
|
||||||
|
filterCoeffsLocal = filterCoeffs;
|
||||||
|
for (i = 0; i < lengthLocal; i ++)
|
||||||
|
{
|
||||||
|
// unroll loop for efficiency.
|
||||||
|
|
||||||
|
suml1 += ptr[0] * filterCoeffsLocal[0] +
|
||||||
|
ptr[2] * filterCoeffsLocal[2] +
|
||||||
|
ptr[4] * filterCoeffsLocal[4] +
|
||||||
|
ptr[6] * filterCoeffsLocal[6];
|
||||||
|
|
||||||
|
sumr1 += ptr[1] * filterCoeffsLocal[1] +
|
||||||
|
ptr[3] * filterCoeffsLocal[3] +
|
||||||
|
ptr[5] * filterCoeffsLocal[5] +
|
||||||
|
ptr[7] * filterCoeffsLocal[7];
|
||||||
|
|
||||||
|
suml2 += ptr[8] * filterCoeffsLocal[0] +
|
||||||
|
ptr[10] * filterCoeffsLocal[2] +
|
||||||
|
ptr[12] * filterCoeffsLocal[4] +
|
||||||
|
ptr[14] * filterCoeffsLocal[6];
|
||||||
|
|
||||||
|
sumr2 += ptr[9] * filterCoeffsLocal[1] +
|
||||||
|
ptr[11] * filterCoeffsLocal[3] +
|
||||||
|
ptr[13] * filterCoeffsLocal[5] +
|
||||||
|
ptr[15] * filterCoeffsLocal[7];
|
||||||
|
|
||||||
|
ptr += 16;
|
||||||
|
filterCoeffsLocal += 8;
|
||||||
|
}
|
||||||
|
dest[0] = (float)suml1;
|
||||||
|
dest[1] = (float)sumr1;
|
||||||
|
dest[2] = (float)suml2;
|
||||||
|
dest[3] = (float)sumr2;
|
||||||
|
|
||||||
|
src += 4;
|
||||||
|
dest += 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
|
_asm
|
||||||
|
{
|
||||||
|
mov eax, dword ptr dest
|
||||||
|
mov ebx, dword ptr src
|
||||||
|
mov edx, count
|
||||||
|
shr edx, 1
|
||||||
|
|
||||||
|
loop1:
|
||||||
|
// "outer loop" : during each round 2*2 output samples are calculated
|
||||||
|
prefetch [ebx] // give a prefetch hint to CPU what data are to be needed soonish
|
||||||
|
prefetch [filterCoeffsLocal] // give a prefetch hint to CPU what data are to be needed soonish
|
||||||
|
|
||||||
|
mov esi, ebx
|
||||||
|
mov edi, filterCoeffsLocal
|
||||||
|
pxor mm0, mm0
|
||||||
|
pxor mm1, mm1
|
||||||
|
mov ecx, lengthLocal
|
||||||
|
|
||||||
|
loop2:
|
||||||
|
// "inner loop" : during each round four FIR filter taps are evaluated for 2*2 output samples
|
||||||
|
movq mm2, [edi]
|
||||||
|
movq mm3, mm2
|
||||||
|
prefetch [edi + 32] // give a prefetch hint to CPU what data are to be needed soonish
|
||||||
|
pfmul mm2, [esi]
|
||||||
|
prefetch [esi + 32] // give a prefetch hint to CPU what data are to be needed soonish
|
||||||
|
pfmul mm3, [esi + 8]
|
||||||
|
|
||||||
|
movq mm4, [edi + 8]
|
||||||
|
movq mm5, mm4
|
||||||
|
pfadd mm0, mm2
|
||||||
|
pfmul mm4, [esi + 8]
|
||||||
|
pfadd mm1, mm3
|
||||||
|
pfmul mm5, [esi + 16]
|
||||||
|
|
||||||
|
movq mm2, [edi + 16]
|
||||||
|
movq mm6, mm2
|
||||||
|
pfadd mm0, mm4
|
||||||
|
pfmul mm2, [esi + 16]
|
||||||
|
pfadd mm1, mm5
|
||||||
|
pfmul mm6, [esi + 24]
|
||||||
|
|
||||||
|
movq mm3, [edi + 24]
|
||||||
|
movq mm7, mm3
|
||||||
|
pfadd mm0, mm2
|
||||||
|
pfmul mm3, [esi + 24]
|
||||||
|
pfadd mm1, mm6
|
||||||
|
pfmul mm7, [esi + 32]
|
||||||
|
add esi, 32
|
||||||
|
pfadd mm0, mm3
|
||||||
|
add edi, 32
|
||||||
|
pfadd mm1, mm7
|
||||||
|
|
||||||
|
dec ecx
|
||||||
|
jnz loop2
|
||||||
|
|
||||||
|
movq [eax], mm0
|
||||||
|
add ebx, 16
|
||||||
|
movq [eax + 8], mm1
|
||||||
|
add eax, 16
|
||||||
|
|
||||||
|
dec edx
|
||||||
|
jnz loop1
|
||||||
|
|
||||||
|
femms
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif // ALLOW_3DNOW
|
|
@ -0,0 +1,184 @@
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
///
|
||||||
|
/// FIR low-pass (anti-alias) filter with filter coefficient design routine and
|
||||||
|
/// MMX optimization.
|
||||||
|
///
|
||||||
|
/// Anti-alias filter is used to prevent folding of high frequencies when
|
||||||
|
/// transposing the sample rate with interpolation.
|
||||||
|
///
|
||||||
|
/// Author : Copyright (c) Olli Parviainen
|
||||||
|
/// Author e-mail : oparviai 'at' iki.fi
|
||||||
|
/// SoundTouch WWW: http://www.surina.net/soundtouch
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Last changed : $Date: 2006/02/05 16:44:06 $
|
||||||
|
// File revision : $Revision: 1.9 $
|
||||||
|
//
|
||||||
|
// $Id: AAFilter.cpp,v 1.9 2006/02/05 16:44:06 Olli Exp $
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// License :
|
||||||
|
//
|
||||||
|
// SoundTouch audio processing library
|
||||||
|
// Copyright (c) Olli Parviainen
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU Lesser General Public
|
||||||
|
// License as published by the Free Software Foundation; either
|
||||||
|
// version 2.1 of the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include <memory.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "AAFilter.h"
|
||||||
|
#include "FIRFilter.h"
|
||||||
|
|
||||||
|
using namespace soundtouch;
|
||||||
|
|
||||||
|
#define PI 3.141592655357989
|
||||||
|
#define TWOPI (2 * PI)
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
*
|
||||||
|
* Implementation of the class 'AAFilter'
|
||||||
|
*
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
AAFilter::AAFilter(const uint length)
|
||||||
|
{
|
||||||
|
pFIR = FIRFilter::newInstance();
|
||||||
|
cutoffFreq = 0.5;
|
||||||
|
setLength(length);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
AAFilter::~AAFilter()
|
||||||
|
{
|
||||||
|
delete pFIR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Sets new anti-alias filter cut-off edge frequency, scaled to
|
||||||
|
// sampling frequency (nyquist frequency = 0.5).
|
||||||
|
// The filter will cut frequencies higher than the given frequency.
|
||||||
|
void AAFilter::setCutoffFreq(const double newCutoffFreq)
|
||||||
|
{
|
||||||
|
cutoffFreq = newCutoffFreq;
|
||||||
|
calculateCoeffs();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Sets number of FIR filter taps
|
||||||
|
void AAFilter::setLength(const uint newLength)
|
||||||
|
{
|
||||||
|
length = newLength;
|
||||||
|
calculateCoeffs();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Calculates coefficients for a low-pass FIR filter using Hamming window
|
||||||
|
void AAFilter::calculateCoeffs()
|
||||||
|
{
|
||||||
|
uint i;
|
||||||
|
double cntTemp, temp, tempCoeff,h, w;
|
||||||
|
double fc2, wc;
|
||||||
|
double scaleCoeff, sum;
|
||||||
|
double *work;
|
||||||
|
SAMPLETYPE *coeffs;
|
||||||
|
|
||||||
|
assert(length > 0);
|
||||||
|
assert(length % 4 == 0);
|
||||||
|
assert(cutoffFreq >= 0);
|
||||||
|
assert(cutoffFreq <= 0.5);
|
||||||
|
|
||||||
|
work = new double[length];
|
||||||
|
coeffs = new SAMPLETYPE[length];
|
||||||
|
|
||||||
|
fc2 = 2.0 * cutoffFreq;
|
||||||
|
wc = PI * fc2;
|
||||||
|
tempCoeff = TWOPI / (double)length;
|
||||||
|
|
||||||
|
sum = 0;
|
||||||
|
for (i = 0; i < length; i ++)
|
||||||
|
{
|
||||||
|
cntTemp = (double)i - (double)(length / 2);
|
||||||
|
|
||||||
|
temp = cntTemp * wc;
|
||||||
|
if (temp != 0)
|
||||||
|
{
|
||||||
|
h = fc2 * sin(temp) / temp; // sinc function
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
h = 1.0;
|
||||||
|
}
|
||||||
|
w = 0.54 + 0.46 * cos(tempCoeff * cntTemp); // hamming window
|
||||||
|
|
||||||
|
temp = w * h;
|
||||||
|
work[i] = temp;
|
||||||
|
|
||||||
|
// calc net sum of coefficients
|
||||||
|
sum += temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ensure the sum of coefficients is larger than zero
|
||||||
|
assert(sum > 0);
|
||||||
|
|
||||||
|
// ensure we've really designed a lowpass filter...
|
||||||
|
assert(work[length/2] > 0);
|
||||||
|
assert(work[length/2 + 1] > -1e-6);
|
||||||
|
assert(work[length/2 - 1] > -1e-6);
|
||||||
|
|
||||||
|
// Calculate a scaling coefficient in such a way that the result can be
|
||||||
|
// divided by 16384
|
||||||
|
scaleCoeff = 16384.0f / sum;
|
||||||
|
|
||||||
|
for (i = 0; i < length; i ++)
|
||||||
|
{
|
||||||
|
// scale & round to nearest integer
|
||||||
|
temp = work[i] * scaleCoeff;
|
||||||
|
temp += (temp >= 0) ? 0.5 : -0.5;
|
||||||
|
// ensure no overfloods
|
||||||
|
assert(temp >= -32768 && temp <= 32767);
|
||||||
|
coeffs[i] = (SAMPLETYPE)temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set coefficients. Use divide factor 14 => divide result by 2^14 = 16384
|
||||||
|
pFIR->setCoefficients(coeffs, length, 14);
|
||||||
|
|
||||||
|
delete[] work;
|
||||||
|
delete[] coeffs;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Applies the filter to the given sequence of samples.
|
||||||
|
// Note : The amount of outputted samples is by value of 'filter length'
|
||||||
|
// smaller than the amount of input samples.
|
||||||
|
uint AAFilter::evaluate(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSamples, uint numChannels) const
|
||||||
|
{
|
||||||
|
return pFIR->evaluate(dest, src, numSamples, numChannels);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint AAFilter::getLength() const
|
||||||
|
{
|
||||||
|
return pFIR->getLength();
|
||||||
|
}
|
|
@ -0,0 +1,91 @@
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
///
|
||||||
|
/// Sampled sound tempo changer/time stretch algorithm. Changes the sound tempo
|
||||||
|
/// while maintaining the original pitch by using a time domain WSOLA-like method
|
||||||
|
/// with several performance-increasing tweaks.
|
||||||
|
///
|
||||||
|
/// Anti-alias filter is used to prevent folding of high frequencies when
|
||||||
|
/// transposing the sample rate with interpolation.
|
||||||
|
///
|
||||||
|
/// Author : Copyright (c) Olli Parviainen
|
||||||
|
/// Author e-mail : oparviai 'at' iki.fi
|
||||||
|
/// SoundTouch WWW: http://www.surina.net/soundtouch
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Last changed : $Date: 2006/02/05 16:44:06 $
|
||||||
|
// File revision : $Revision: 1.10 $
|
||||||
|
//
|
||||||
|
// $Id: AAFilter.h,v 1.10 2006/02/05 16:44:06 Olli Exp $
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// License :
|
||||||
|
//
|
||||||
|
// SoundTouch audio processing library
|
||||||
|
// Copyright (c) Olli Parviainen
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU Lesser General Public
|
||||||
|
// License as published by the Free Software Foundation; either
|
||||||
|
// version 2.1 of the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef AAFilter_H
|
||||||
|
#define AAFilter_H
|
||||||
|
|
||||||
|
#include "STTypes.h"
|
||||||
|
|
||||||
|
namespace soundtouch
|
||||||
|
{
|
||||||
|
|
||||||
|
class AAFilter
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
class FIRFilter *pFIR;
|
||||||
|
|
||||||
|
/// Low-pass filter cut-off frequency, negative = invalid
|
||||||
|
double cutoffFreq;
|
||||||
|
|
||||||
|
/// num of filter taps
|
||||||
|
uint length;
|
||||||
|
|
||||||
|
/// Calculate the FIR coefficients realizing the given cutoff-frequency
|
||||||
|
void calculateCoeffs();
|
||||||
|
public:
|
||||||
|
AAFilter(uint length);
|
||||||
|
|
||||||
|
~AAFilter();
|
||||||
|
|
||||||
|
/// Sets new anti-alias filter cut-off edge frequency, scaled to sampling
|
||||||
|
/// frequency (nyquist frequency = 0.5). The filter will cut off the
|
||||||
|
/// frequencies than that.
|
||||||
|
void setCutoffFreq(double newCutoffFreq);
|
||||||
|
|
||||||
|
/// Sets number of FIR filter taps, i.e. ~filter complexity
|
||||||
|
void setLength(uint newLength);
|
||||||
|
|
||||||
|
uint getLength() const;
|
||||||
|
|
||||||
|
/// Applies the filter to the given sequence of samples.
|
||||||
|
/// Note : The amount of outputted samples is by value of 'filter length'
|
||||||
|
/// smaller than the amount of input samples.
|
||||||
|
uint evaluate(SAMPLETYPE *dest,
|
||||||
|
const SAMPLETYPE *src,
|
||||||
|
uint numSamples,
|
||||||
|
uint numChannels) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,159 @@
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
///
|
||||||
|
/// Beats-per-minute (BPM) detection routine.
|
||||||
|
///
|
||||||
|
/// The beat detection algorithm works as follows:
|
||||||
|
/// - Use function 'inputSamples' to input a chunks of samples to the class for
|
||||||
|
/// analysis. It's a good idea to enter a large sound file or stream in smallish
|
||||||
|
/// chunks of around few kilosamples in order not to extinguish too much RAM memory.
|
||||||
|
/// - Input sound data is decimated to approx 500 Hz to reduce calculation burden,
|
||||||
|
/// which is basically ok as low (bass) frequencies mostly determine the beat rate.
|
||||||
|
/// Simple averaging is used for anti-alias filtering because the resulting signal
|
||||||
|
/// quality isn't of that high importance.
|
||||||
|
/// - Decimated sound data is enveloped, i.e. the amplitude shape is detected by
|
||||||
|
/// taking absolute value that's smoothed by sliding average. Signal levels that
|
||||||
|
/// are below a couple of times the general RMS amplitude level are cut away to
|
||||||
|
/// leave only notable peaks there.
|
||||||
|
/// - Repeating sound patterns (e.g. beats) are detected by calculating short-term
|
||||||
|
/// autocorrelation function of the enveloped signal.
|
||||||
|
/// - After whole sound data file has been analyzed as above, the bpm level is
|
||||||
|
/// detected by function 'getBpm' that finds the highest peak of the autocorrelation
|
||||||
|
/// function, calculates it's precise location and converts this reading to bpm's.
|
||||||
|
///
|
||||||
|
/// Author : Copyright (c) Olli Parviainen
|
||||||
|
/// Author e-mail : oparviai 'at' iki.fi
|
||||||
|
/// SoundTouch WWW: http://www.surina.net/soundtouch
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Last changed : $Date: 2006/02/05 16:44:06 $
|
||||||
|
// File revision : $Revision: 1.5 $
|
||||||
|
//
|
||||||
|
// $Id: BPMDetect.h,v 1.5 2006/02/05 16:44:06 Olli Exp $
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// License :
|
||||||
|
//
|
||||||
|
// SoundTouch audio processing library
|
||||||
|
// Copyright (c) Olli Parviainen
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU Lesser General Public
|
||||||
|
// License as published by the Free Software Foundation; either
|
||||||
|
// version 2.1 of the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef _BPMDetect_H_
|
||||||
|
#define _BPMDetect_H_
|
||||||
|
|
||||||
|
#include "STTypes.h"
|
||||||
|
#include "FIFOSampleBuffer.h"
|
||||||
|
|
||||||
|
/// Minimum allowed BPM rate. Used to restrict accepted result above a reasonable limit.
|
||||||
|
#define MIN_BPM 45
|
||||||
|
|
||||||
|
/// Maximum allowed BPM rate. Used to restrict accepted result below a reasonable limit.
|
||||||
|
#define MAX_BPM 230
|
||||||
|
|
||||||
|
|
||||||
|
/// Class for calculating BPM rate for audio data.
|
||||||
|
class BPMDetect
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
/// Auto-correlation accumulator bins.
|
||||||
|
float *xcorr;
|
||||||
|
|
||||||
|
/// Amplitude envelope sliding average approximation level accumulator
|
||||||
|
float envelopeAccu;
|
||||||
|
|
||||||
|
/// RMS volume sliding average approximation level accumulator
|
||||||
|
float RMSVolumeAccu;
|
||||||
|
|
||||||
|
/// Sample average counter.
|
||||||
|
int decimateCount;
|
||||||
|
|
||||||
|
/// Sample average accumulator for FIFO-like decimation.
|
||||||
|
soundtouch::LONG_SAMPLETYPE decimateSum;
|
||||||
|
|
||||||
|
/// Decimate sound by this coefficient to reach approx. 500 Hz.
|
||||||
|
int decimateBy;
|
||||||
|
|
||||||
|
/// Auto-correlation window length
|
||||||
|
int windowLen;
|
||||||
|
|
||||||
|
/// Number of channels (1 = mono, 2 = stereo)
|
||||||
|
int channels;
|
||||||
|
|
||||||
|
/// sample rate
|
||||||
|
int sampleRate;
|
||||||
|
|
||||||
|
/// Beginning of auto-correlation window: Autocorrelation isn't being updated for
|
||||||
|
/// the first these many correlation bins.
|
||||||
|
int windowStart;
|
||||||
|
|
||||||
|
/// FIFO-buffer for decimated processing samples.
|
||||||
|
soundtouch::FIFOSampleBuffer *buffer;
|
||||||
|
|
||||||
|
/// Initialize the class for processing.
|
||||||
|
void init(int numChannels, int sampleRate);
|
||||||
|
|
||||||
|
/// Updates auto-correlation function for given number of decimated samples that
|
||||||
|
/// are read from the internal 'buffer' pipe (samples aren't removed from the pipe
|
||||||
|
/// though).
|
||||||
|
void updateXCorr(int process_samples /// How many samples are processed.
|
||||||
|
);
|
||||||
|
|
||||||
|
/// Decimates samples to approx. 500 Hz.
|
||||||
|
///
|
||||||
|
/// \return Number of output samples.
|
||||||
|
int decimate(soundtouch::SAMPLETYPE *dest, ///< Destination buffer
|
||||||
|
const soundtouch::SAMPLETYPE *src, ///< Source sample buffer
|
||||||
|
int numsamples ///< Number of source samples.
|
||||||
|
);
|
||||||
|
|
||||||
|
/// Calculates amplitude envelope for the buffer of samples.
|
||||||
|
/// Result is output to 'samples'.
|
||||||
|
void calcEnvelope(soundtouch::SAMPLETYPE *samples, ///< Pointer to input/output data buffer
|
||||||
|
int numsamples ///< Number of samples in buffer
|
||||||
|
);
|
||||||
|
|
||||||
|
public:
|
||||||
|
/// Constructor.
|
||||||
|
BPMDetect(int numChannels, ///< Number of channels in sample data.
|
||||||
|
int sampleRate ///< Sample rate in Hz.
|
||||||
|
);
|
||||||
|
|
||||||
|
/// Destructor.
|
||||||
|
virtual ~BPMDetect();
|
||||||
|
|
||||||
|
/// Inputs a block of samples for analyzing: Envelopes the samples and then
|
||||||
|
/// updates the autocorrelation estimation. When whole song data has been input
|
||||||
|
/// in smaller blocks using this function, read the resulting bpm with 'getBpm'
|
||||||
|
/// function.
|
||||||
|
///
|
||||||
|
/// Notice that data in 'samples' array can be disrupted in processing.
|
||||||
|
void inputSamples(soundtouch::SAMPLETYPE *samples, ///< Pointer to input/working data buffer
|
||||||
|
int numSamples ///< Number of samples in buffer
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
/// Analyzes the results and returns the BPM rate. Use this function to read result
|
||||||
|
/// after whole song data has been input to the class by consecutive calls of
|
||||||
|
/// 'inputSamples' function.
|
||||||
|
///
|
||||||
|
/// \return Beats-per-minute rate, or zero if detection failed.
|
||||||
|
float getBpm();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // _BPMDetect_H_
|
|
@ -0,0 +1,252 @@
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
///
|
||||||
|
/// A buffer class for temporarily storaging sound samples, operates as a
|
||||||
|
/// first-in-first-out pipe.
|
||||||
|
///
|
||||||
|
/// Samples are added to the end of the sample buffer with the 'putSamples'
|
||||||
|
/// function, and are received from the beginning of the buffer by calling
|
||||||
|
/// the 'receiveSamples' function. The class automatically removes the
|
||||||
|
/// outputted samples from the buffer, as well as grows the buffer size
|
||||||
|
/// whenever necessary.
|
||||||
|
///
|
||||||
|
/// Author : Copyright (c) Olli Parviainen
|
||||||
|
/// Author e-mail : oparviai 'at' iki.fi
|
||||||
|
/// SoundTouch WWW: http://www.surina.net/soundtouch
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Last changed : $Date: 2006/02/05 16:44:06 $
|
||||||
|
// File revision : $Revision: 1.11 $
|
||||||
|
//
|
||||||
|
// $Id: FIFOSampleBuffer.cpp,v 1.11 2006/02/05 16:44:06 Olli Exp $
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// License :
|
||||||
|
//
|
||||||
|
// SoundTouch audio processing library
|
||||||
|
// Copyright (c) Olli Parviainen
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU Lesser General Public
|
||||||
|
// License as published by the Free Software Foundation; either
|
||||||
|
// version 2.1 of the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <memory.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
#include "FIFOSampleBuffer.h"
|
||||||
|
|
||||||
|
using namespace soundtouch;
|
||||||
|
|
||||||
|
// Constructor
|
||||||
|
FIFOSampleBuffer::FIFOSampleBuffer(uint numChannels)
|
||||||
|
{
|
||||||
|
sizeInBytes = 0; // reasonable initial value
|
||||||
|
buffer = NULL; //new SAMPLETYPE[sizeInBytes / sizeof(SAMPLETYPE)];
|
||||||
|
bufferUnaligned = NULL;
|
||||||
|
samplesInBuffer = 0;
|
||||||
|
bufferPos = 0;
|
||||||
|
channels = numChannels;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
FIFOSampleBuffer::~FIFOSampleBuffer()
|
||||||
|
{
|
||||||
|
delete[] bufferUnaligned;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Sets number of channels, 1 = mono, 2 = stereo
|
||||||
|
void FIFOSampleBuffer::setChannels(const uint numChannels)
|
||||||
|
{
|
||||||
|
uint usedBytes;
|
||||||
|
|
||||||
|
usedBytes = channels * samplesInBuffer;
|
||||||
|
channels = numChannels;
|
||||||
|
samplesInBuffer = usedBytes / channels;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// if output location pointer 'bufferPos' isn't zero, 'rewinds' the buffer and
|
||||||
|
// zeroes this pointer by copying samples from the 'bufferPos' pointer
|
||||||
|
// location on to the beginning of the buffer.
|
||||||
|
void FIFOSampleBuffer::rewind()
|
||||||
|
{
|
||||||
|
if (bufferPos)
|
||||||
|
{
|
||||||
|
memmove(buffer, ptrBegin(), sizeof(SAMPLETYPE) * channels * samplesInBuffer);
|
||||||
|
bufferPos = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Adds 'numSamples' pcs of samples from the 'samples' memory position to
|
||||||
|
// the sample buffer.
|
||||||
|
void FIFOSampleBuffer::putSamples(const SAMPLETYPE *samples, uint numSamples)
|
||||||
|
{
|
||||||
|
memcpy(ptrEnd(numSamples), samples, sizeof(SAMPLETYPE) * numSamples * channels);
|
||||||
|
samplesInBuffer += numSamples;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Increases the number of samples in the buffer without copying any actual
|
||||||
|
// samples.
|
||||||
|
//
|
||||||
|
// This function is used to update the number of samples in the sample buffer
|
||||||
|
// when accessing the buffer directly with 'ptrEnd' function. Please be
|
||||||
|
// careful though!
|
||||||
|
void FIFOSampleBuffer::putSamples(uint numSamples)
|
||||||
|
{
|
||||||
|
uint req;
|
||||||
|
|
||||||
|
req = samplesInBuffer + numSamples;
|
||||||
|
ensureCapacity(req);
|
||||||
|
samplesInBuffer += numSamples;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Returns a pointer to the end of the used part of the sample buffer (i.e.
|
||||||
|
// where the new samples are to be inserted). This function may be used for
|
||||||
|
// inserting new samples into the sample buffer directly. Please be careful!
|
||||||
|
//
|
||||||
|
// Parameter 'slackCapacity' tells the function how much free capacity (in
|
||||||
|
// terms of samples) there _at least_ should be, in order to the caller to
|
||||||
|
// succesfully insert all the required samples to the buffer. When necessary,
|
||||||
|
// the function grows the buffer size to comply with this requirement.
|
||||||
|
//
|
||||||
|
// When using this function as means for inserting new samples, also remember
|
||||||
|
// to increase the sample count afterwards, by calling the
|
||||||
|
// 'putSamples(numSamples)' function.
|
||||||
|
SAMPLETYPE *FIFOSampleBuffer::ptrEnd(uint slackCapacity)
|
||||||
|
{
|
||||||
|
ensureCapacity(samplesInBuffer + slackCapacity);
|
||||||
|
return buffer + samplesInBuffer * channels;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Returns a pointer to the beginning of the currently non-outputted samples.
|
||||||
|
// This function is provided for accessing the output samples directly.
|
||||||
|
// Please be careful!
|
||||||
|
//
|
||||||
|
// When using this function to output samples, also remember to 'remove' the
|
||||||
|
// outputted samples from the buffer by calling the
|
||||||
|
// 'receiveSamples(numSamples)' function
|
||||||
|
SAMPLETYPE *FIFOSampleBuffer::ptrBegin() const
|
||||||
|
{
|
||||||
|
return buffer + bufferPos * channels;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Ensures that the buffer has enought capacity, i.e. space for _at least_
|
||||||
|
// 'capacityRequirement' number of samples. The buffer is grown in steps of
|
||||||
|
// 4 kilobytes to eliminate the need for frequently growing up the buffer,
|
||||||
|
// as well as to round the buffer size up to the virtual memory page size.
|
||||||
|
void FIFOSampleBuffer::ensureCapacity(uint capacityRequirement)
|
||||||
|
{
|
||||||
|
SAMPLETYPE *tempUnaligned, *temp;
|
||||||
|
|
||||||
|
if (capacityRequirement > getCapacity())
|
||||||
|
{
|
||||||
|
// enlarge the buffer in 4kbyte steps (round up to next 4k boundary)
|
||||||
|
sizeInBytes = (capacityRequirement * channels * sizeof(SAMPLETYPE) + 4095) & -4096;
|
||||||
|
assert(sizeInBytes % 2 == 0);
|
||||||
|
tempUnaligned = new SAMPLETYPE[sizeInBytes / sizeof(SAMPLETYPE) + 16 / sizeof(SAMPLETYPE)];
|
||||||
|
if (tempUnaligned == NULL)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Couldn't allocate memory!\n");
|
||||||
|
}
|
||||||
|
temp = (SAMPLETYPE *)(((ulongptr)tempUnaligned + 15) & -16);
|
||||||
|
memcpy(temp, ptrBegin(), samplesInBuffer * channels * sizeof(SAMPLETYPE));
|
||||||
|
delete[] bufferUnaligned;
|
||||||
|
buffer = temp;
|
||||||
|
bufferUnaligned = tempUnaligned;
|
||||||
|
bufferPos = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// simply rewind the buffer (if necessary)
|
||||||
|
rewind();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Returns the current buffer capacity in terms of samples
|
||||||
|
uint FIFOSampleBuffer::getCapacity() const
|
||||||
|
{
|
||||||
|
return sizeInBytes / (channels * sizeof(SAMPLETYPE));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Returns the number of samples currently in the buffer
|
||||||
|
uint FIFOSampleBuffer::numSamples() const
|
||||||
|
{
|
||||||
|
return samplesInBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Output samples from beginning of the sample buffer. Copies demanded number
|
||||||
|
// of samples to output and removes them from the sample buffer. If there
|
||||||
|
// are less than 'numsample' samples in the buffer, returns all available.
|
||||||
|
//
|
||||||
|
// Returns number of samples copied.
|
||||||
|
uint FIFOSampleBuffer::receiveSamples(SAMPLETYPE *output, uint maxSamples)
|
||||||
|
{
|
||||||
|
uint num;
|
||||||
|
|
||||||
|
num = (maxSamples > samplesInBuffer) ? samplesInBuffer : maxSamples;
|
||||||
|
|
||||||
|
memcpy(output, ptrBegin(), channels * sizeof(SAMPLETYPE) * num);
|
||||||
|
return receiveSamples(num);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Removes samples from the beginning of the sample buffer without copying them
|
||||||
|
// anywhere. Used to reduce the number of samples in the buffer, when accessing
|
||||||
|
// the sample buffer with the 'ptrBegin' function.
|
||||||
|
uint FIFOSampleBuffer::receiveSamples(uint maxSamples)
|
||||||
|
{
|
||||||
|
if (maxSamples >= samplesInBuffer)
|
||||||
|
{
|
||||||
|
uint temp;
|
||||||
|
|
||||||
|
temp = samplesInBuffer;
|
||||||
|
samplesInBuffer = 0;
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
samplesInBuffer -= maxSamples;
|
||||||
|
bufferPos += maxSamples;
|
||||||
|
|
||||||
|
return maxSamples;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Returns nonzero if the sample buffer is empty
|
||||||
|
int FIFOSampleBuffer::isEmpty() const
|
||||||
|
{
|
||||||
|
return (samplesInBuffer == 0) ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Clears the sample buffer
|
||||||
|
void FIFOSampleBuffer::clear()
|
||||||
|
{
|
||||||
|
samplesInBuffer = 0;
|
||||||
|
bufferPos = 0;
|
||||||
|
}
|
|
@ -0,0 +1,174 @@
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
///
|
||||||
|
/// A buffer class for temporarily storaging sound samples, operates as a
|
||||||
|
/// first-in-first-out pipe.
|
||||||
|
///
|
||||||
|
/// Samples are added to the end of the sample buffer with the 'putSamples'
|
||||||
|
/// function, and are received from the beginning of the buffer by calling
|
||||||
|
/// the 'receiveSamples' function. The class automatically removes the
|
||||||
|
/// output samples from the buffer as well as grows the storage size
|
||||||
|
/// whenever necessary.
|
||||||
|
///
|
||||||
|
/// Author : Copyright (c) Olli Parviainen
|
||||||
|
/// Author e-mail : oparviai 'at' iki.fi
|
||||||
|
/// SoundTouch WWW: http://www.surina.net/soundtouch
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Last changed : $Date: 2006/02/05 16:44:06 $
|
||||||
|
// File revision : $Revision: 1.9 $
|
||||||
|
//
|
||||||
|
// $Id: FIFOSampleBuffer.h,v 1.9 2006/02/05 16:44:06 Olli Exp $
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// License :
|
||||||
|
//
|
||||||
|
// SoundTouch audio processing library
|
||||||
|
// Copyright (c) Olli Parviainen
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU Lesser General Public
|
||||||
|
// License as published by the Free Software Foundation; either
|
||||||
|
// version 2.1 of the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef FIFOSampleBuffer_H
|
||||||
|
#define FIFOSampleBuffer_H
|
||||||
|
|
||||||
|
#include "FIFOSamplePipe.h"
|
||||||
|
|
||||||
|
namespace soundtouch
|
||||||
|
{
|
||||||
|
|
||||||
|
/// Sample buffer working in FIFO (first-in-first-out) principle. The class takes
|
||||||
|
/// care of storage size adjustment and data moving during input/output operations.
|
||||||
|
///
|
||||||
|
/// Notice that in case of stereo audio, one sample is considered to consist of
|
||||||
|
/// both channel data.
|
||||||
|
class FIFOSampleBuffer : public FIFOSamplePipe
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
/// Sample buffer.
|
||||||
|
SAMPLETYPE *buffer;
|
||||||
|
|
||||||
|
// Raw unaligned buffer memory. 'buffer' is made aligned by pointing it to first
|
||||||
|
// 16-byte aligned location of this buffer
|
||||||
|
SAMPLETYPE *bufferUnaligned;
|
||||||
|
|
||||||
|
/// Sample buffer size in bytes
|
||||||
|
uint sizeInBytes;
|
||||||
|
|
||||||
|
/// How many samples are currently in buffer.
|
||||||
|
uint samplesInBuffer;
|
||||||
|
|
||||||
|
/// Channels, 1=mono, 2=stereo.
|
||||||
|
uint channels;
|
||||||
|
|
||||||
|
/// Current position pointer to the buffer. This pointer is increased when samples are
|
||||||
|
/// removed from the pipe so that it's necessary to actually rewind buffer (move data)
|
||||||
|
/// only new data when is put to the pipe.
|
||||||
|
uint bufferPos;
|
||||||
|
|
||||||
|
/// Rewind the buffer by moving data from position pointed by 'bufferPos' to real
|
||||||
|
/// beginning of the buffer.
|
||||||
|
void rewind();
|
||||||
|
|
||||||
|
/// Ensures that the buffer has capacity for at least this many samples.
|
||||||
|
void ensureCapacity(const uint capacityRequirement);
|
||||||
|
|
||||||
|
/// Returns current capacity.
|
||||||
|
uint getCapacity() const;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/// Constructor
|
||||||
|
FIFOSampleBuffer(uint numChannels = 2 ///< Number of channels, 1=mono, 2=stereo.
|
||||||
|
///< Default is stereo.
|
||||||
|
);
|
||||||
|
|
||||||
|
/// destructor
|
||||||
|
~FIFOSampleBuffer();
|
||||||
|
|
||||||
|
/// Returns a pointer to the beginning of the output samples.
|
||||||
|
/// This function is provided for accessing the output samples directly.
|
||||||
|
/// Please be careful for not to corrupt the book-keeping!
|
||||||
|
///
|
||||||
|
/// When using this function to output samples, also remember to 'remove' the
|
||||||
|
/// output samples from the buffer by calling the
|
||||||
|
/// 'receiveSamples(numSamples)' function
|
||||||
|
virtual SAMPLETYPE *ptrBegin() const;
|
||||||
|
|
||||||
|
/// Returns a pointer to the end of the used part of the sample buffer (i.e.
|
||||||
|
/// where the new samples are to be inserted). This function may be used for
|
||||||
|
/// inserting new samples into the sample buffer directly. Please be careful
|
||||||
|
/// not corrupt the book-keeping!
|
||||||
|
///
|
||||||
|
/// When using this function as means for inserting new samples, also remember
|
||||||
|
/// to increase the sample count afterwards, by calling the
|
||||||
|
/// 'putSamples(numSamples)' function.
|
||||||
|
SAMPLETYPE *ptrEnd(
|
||||||
|
uint slackCapacity ///< How much free capacity (in samples) there _at least_
|
||||||
|
///< should be so that the caller can succesfully insert the
|
||||||
|
///< desired samples to the buffer. If necessary, the function
|
||||||
|
///< grows the buffer size to comply with this requirement.
|
||||||
|
);
|
||||||
|
|
||||||
|
/// Adds 'numSamples' pcs of samples from the 'samples' memory position to
|
||||||
|
/// the sample buffer.
|
||||||
|
virtual void putSamples(const SAMPLETYPE *samples, ///< Pointer to samples.
|
||||||
|
uint numSamples ///< Number of samples to insert.
|
||||||
|
);
|
||||||
|
|
||||||
|
/// Adjusts the book-keeping to increase number of samples in the buffer without
|
||||||
|
/// copying any actual samples.
|
||||||
|
///
|
||||||
|
/// This function is used to update the number of samples in the sample buffer
|
||||||
|
/// when accessing the buffer directly with 'ptrEnd' function. Please be
|
||||||
|
/// careful though!
|
||||||
|
virtual void putSamples(uint numSamples ///< Number of samples been inserted.
|
||||||
|
);
|
||||||
|
|
||||||
|
/// Output samples from beginning of the sample buffer. Copies requested samples to
|
||||||
|
/// output buffer and removes them from the sample buffer. If there are less than
|
||||||
|
/// 'numsample' samples in the buffer, returns all that available.
|
||||||
|
///
|
||||||
|
/// \return Number of samples returned.
|
||||||
|
virtual uint receiveSamples(SAMPLETYPE *output, ///< Buffer where to copy output samples.
|
||||||
|
uint maxSamples ///< How many samples to receive at max.
|
||||||
|
);
|
||||||
|
|
||||||
|
/// Adjusts book-keeping so that given number of samples are removed from beginning of the
|
||||||
|
/// sample buffer without copying them anywhere.
|
||||||
|
///
|
||||||
|
/// Used to reduce the number of samples in the buffer when accessing the sample buffer directly
|
||||||
|
/// with 'ptrBegin' function.
|
||||||
|
virtual uint receiveSamples(uint maxSamples ///< Remove this many samples from the beginning of pipe.
|
||||||
|
);
|
||||||
|
|
||||||
|
/// Returns number of samples currently available.
|
||||||
|
virtual uint numSamples() const;
|
||||||
|
|
||||||
|
/// Sets number of channels, 1 = mono, 2 = stereo.
|
||||||
|
void setChannels(uint numChannels);
|
||||||
|
|
||||||
|
/// Returns nonzero if there aren't any samples available for outputting.
|
||||||
|
virtual int isEmpty() const;
|
||||||
|
|
||||||
|
/// Clears all the samples.
|
||||||
|
virtual void clear();
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,217 @@
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
///
|
||||||
|
/// 'FIFOSamplePipe' : An abstract base class for classes that manipulate sound
|
||||||
|
/// samples by operating like a first-in-first-out pipe: New samples are fed
|
||||||
|
/// into one end of the pipe with the 'putSamples' function, and the processed
|
||||||
|
/// samples are received from the other end with the 'receiveSamples' function.
|
||||||
|
///
|
||||||
|
/// 'FIFOProcessor' : A base class for classes the do signal processing with
|
||||||
|
/// the samples while operating like a first-in-first-out pipe. When samples
|
||||||
|
/// are input with the 'putSamples' function, the class processes them
|
||||||
|
/// and moves the processed samples to the given 'output' pipe object, which
|
||||||
|
/// may be either another processing stage, or a fifo sample buffer object.
|
||||||
|
///
|
||||||
|
/// Author : Copyright (c) Olli Parviainen
|
||||||
|
/// Author e-mail : oparviai 'at' iki.fi
|
||||||
|
/// SoundTouch WWW: http://www.surina.net/soundtouch
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Last changed : $Date: 2006/02/05 16:44:06 $
|
||||||
|
// File revision : $Revision: 1.8 $
|
||||||
|
//
|
||||||
|
// $Id: FIFOSamplePipe.h,v 1.8 2006/02/05 16:44:06 Olli Exp $
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// License :
|
||||||
|
//
|
||||||
|
// SoundTouch audio processing library
|
||||||
|
// Copyright (c) Olli Parviainen
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU Lesser General Public
|
||||||
|
// License as published by the Free Software Foundation; either
|
||||||
|
// version 2.1 of the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef FIFOSamplePipe_H
|
||||||
|
#define FIFOSamplePipe_H
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "STTypes.h"
|
||||||
|
|
||||||
|
namespace soundtouch
|
||||||
|
{
|
||||||
|
|
||||||
|
/// Abstract base class for FIFO (first-in-first-out) sample processing classes.
|
||||||
|
class FIFOSamplePipe
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/// Returns a pointer to the beginning of the output samples.
|
||||||
|
/// This function is provided for accessing the output samples directly.
|
||||||
|
/// Please be careful for not to corrupt the book-keeping!
|
||||||
|
///
|
||||||
|
/// When using this function to output samples, also remember to 'remove' the
|
||||||
|
/// output samples from the buffer by calling the
|
||||||
|
/// 'receiveSamples(numSamples)' function
|
||||||
|
virtual SAMPLETYPE *ptrBegin() const = 0;
|
||||||
|
|
||||||
|
/// Adds 'numSamples' pcs of samples from the 'samples' memory position to
|
||||||
|
/// the sample buffer.
|
||||||
|
virtual void putSamples(const SAMPLETYPE *samples, ///< Pointer to samples.
|
||||||
|
uint numSamples ///< Number of samples to insert.
|
||||||
|
) = 0;
|
||||||
|
|
||||||
|
|
||||||
|
// Moves samples from the 'other' pipe instance to this instance.
|
||||||
|
void moveSamples(FIFOSamplePipe &other ///< Other pipe instance where from the receive the data.
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int oNumSamples = other.numSamples();
|
||||||
|
|
||||||
|
putSamples(other.ptrBegin(), oNumSamples);
|
||||||
|
other.receiveSamples(oNumSamples);
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Output samples from beginning of the sample buffer. Copies requested samples to
|
||||||
|
/// output buffer and removes them from the sample buffer. If there are less than
|
||||||
|
/// 'numsample' samples in the buffer, returns all that available.
|
||||||
|
///
|
||||||
|
/// \return Number of samples returned.
|
||||||
|
virtual uint receiveSamples(SAMPLETYPE *output, ///< Buffer where to copy output samples.
|
||||||
|
uint maxSamples ///< How many samples to receive at max.
|
||||||
|
) = 0;
|
||||||
|
|
||||||
|
/// Adjusts book-keeping so that given number of samples are removed from beginning of the
|
||||||
|
/// sample buffer without copying them anywhere.
|
||||||
|
///
|
||||||
|
/// Used to reduce the number of samples in the buffer when accessing the sample buffer directly
|
||||||
|
/// with 'ptrBegin' function.
|
||||||
|
virtual uint receiveSamples(uint maxSamples ///< Remove this many samples from the beginning of pipe.
|
||||||
|
) = 0;
|
||||||
|
|
||||||
|
/// Returns number of samples currently available.
|
||||||
|
virtual uint numSamples() const = 0;
|
||||||
|
|
||||||
|
// Returns nonzero if there aren't any samples available for outputting.
|
||||||
|
virtual int isEmpty() const = 0;
|
||||||
|
|
||||||
|
/// Clears all the samples.
|
||||||
|
virtual void clear() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// Base-class for sound processing routines working in FIFO principle. With this base
|
||||||
|
/// class it's easy to implement sound processing stages that can be chained together,
|
||||||
|
/// so that samples that are fed into beginning of the pipe automatically go through
|
||||||
|
/// all the processing stages.
|
||||||
|
///
|
||||||
|
/// When samples are input to this class, they're first processed and then put to
|
||||||
|
/// the FIFO pipe that's defined as output of this class. This output pipe can be
|
||||||
|
/// either other processing stage or a FIFO sample buffer.
|
||||||
|
class FIFOProcessor :public FIFOSamplePipe
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
/// Internal pipe where processed samples are put.
|
||||||
|
FIFOSamplePipe *output;
|
||||||
|
|
||||||
|
/// Sets output pipe.
|
||||||
|
void setOutPipe(FIFOSamplePipe *pOutput)
|
||||||
|
{
|
||||||
|
assert(output == NULL);
|
||||||
|
assert(pOutput != NULL);
|
||||||
|
output = pOutput;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Constructor. Doesn't define output pipe; it has to be set be
|
||||||
|
/// 'setOutPipe' function.
|
||||||
|
FIFOProcessor()
|
||||||
|
{
|
||||||
|
output = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Constructor. Configures output pipe.
|
||||||
|
FIFOProcessor(FIFOSamplePipe *pOutput ///< Output pipe.
|
||||||
|
)
|
||||||
|
{
|
||||||
|
output = pOutput;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Destructor.
|
||||||
|
virtual ~FIFOProcessor()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Returns a pointer to the beginning of the output samples.
|
||||||
|
/// This function is provided for accessing the output samples directly.
|
||||||
|
/// Please be careful for not to corrupt the book-keeping!
|
||||||
|
///
|
||||||
|
/// When using this function to output samples, also remember to 'remove' the
|
||||||
|
/// output samples from the buffer by calling the
|
||||||
|
/// 'receiveSamples(numSamples)' function
|
||||||
|
virtual SAMPLETYPE *ptrBegin() const
|
||||||
|
{
|
||||||
|
return output->ptrBegin();
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/// Output samples from beginning of the sample buffer. Copies requested samples to
|
||||||
|
/// output buffer and removes them from the sample buffer. If there are less than
|
||||||
|
/// 'numsample' samples in the buffer, returns all that available.
|
||||||
|
///
|
||||||
|
/// \return Number of samples returned.
|
||||||
|
virtual uint receiveSamples(SAMPLETYPE *outBuffer, ///< Buffer where to copy output samples.
|
||||||
|
uint maxSamples ///< How many samples to receive at max.
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return output->receiveSamples(outBuffer, maxSamples);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Adjusts book-keeping so that given number of samples are removed from beginning of the
|
||||||
|
/// sample buffer without copying them anywhere.
|
||||||
|
///
|
||||||
|
/// Used to reduce the number of samples in the buffer when accessing the sample buffer directly
|
||||||
|
/// with 'ptrBegin' function.
|
||||||
|
virtual uint receiveSamples(uint maxSamples ///< Remove this many samples from the beginning of pipe.
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return output->receiveSamples(maxSamples);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Returns number of samples currently available.
|
||||||
|
virtual uint numSamples() const
|
||||||
|
{
|
||||||
|
return output->numSamples();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Returns nonzero if there aren't any samples available for outputting.
|
||||||
|
virtual int isEmpty() const
|
||||||
|
{
|
||||||
|
return output->isEmpty();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,272 @@
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
///
|
||||||
|
/// General FIR digital filter routines with MMX optimization.
|
||||||
|
///
|
||||||
|
/// Note : MMX optimized functions reside in a separate, platform-specific file,
|
||||||
|
/// e.g. 'mmx_win.cpp' or 'mmx_gcc.cpp'
|
||||||
|
///
|
||||||
|
/// Author : Copyright (c) Olli Parviainen
|
||||||
|
/// Author e-mail : oparviai 'at' iki.fi
|
||||||
|
/// SoundTouch WWW: http://www.surina.net/soundtouch
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Last changed : $Date: 2006/02/05 16:44:06 $
|
||||||
|
// File revision : $Revision: 1.16 $
|
||||||
|
//
|
||||||
|
// $Id: FIRFilter.cpp,v 1.16 2006/02/05 16:44:06 Olli Exp $
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// License :
|
||||||
|
//
|
||||||
|
// SoundTouch audio processing library
|
||||||
|
// Copyright (c) Olli Parviainen
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU Lesser General Public
|
||||||
|
// License as published by the Free Software Foundation; either
|
||||||
|
// version 2.1 of the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include <memory.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include "FIRFilter.h"
|
||||||
|
#include "cpu_detect.h"
|
||||||
|
|
||||||
|
using namespace soundtouch;
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
*
|
||||||
|
* Implementation of the class 'FIRFilter'
|
||||||
|
*
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
FIRFilter::FIRFilter()
|
||||||
|
{
|
||||||
|
resultDivFactor = 0;
|
||||||
|
length = 0;
|
||||||
|
lengthDiv8 = 0;
|
||||||
|
filterCoeffs = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
FIRFilter::~FIRFilter()
|
||||||
|
{
|
||||||
|
delete[] filterCoeffs;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Usual C-version of the filter routine for stereo sound
|
||||||
|
uint FIRFilter::evaluateFilterStereo(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSamples) const
|
||||||
|
{
|
||||||
|
uint i, j, end;
|
||||||
|
LONG_SAMPLETYPE suml, sumr;
|
||||||
|
#ifdef FLOAT_SAMPLES
|
||||||
|
// when using floating point samples, use a scaler instead of a divider
|
||||||
|
// because division is much slower operation than multiplying.
|
||||||
|
double dScaler = 1.0 / (double)resultDivider;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
assert(length != 0);
|
||||||
|
|
||||||
|
end = 2 * (numSamples - length);
|
||||||
|
|
||||||
|
for (j = 0; j < end; j += 2)
|
||||||
|
{
|
||||||
|
const SAMPLETYPE *ptr;
|
||||||
|
|
||||||
|
suml = sumr = 0;
|
||||||
|
ptr = src + j;
|
||||||
|
|
||||||
|
for (i = 0; i < length; i += 4)
|
||||||
|
{
|
||||||
|
// loop is unrolled by factor of 4 here for efficiency
|
||||||
|
suml += ptr[2 * i + 0] * filterCoeffs[i + 0] +
|
||||||
|
ptr[2 * i + 2] * filterCoeffs[i + 1] +
|
||||||
|
ptr[2 * i + 4] * filterCoeffs[i + 2] +
|
||||||
|
ptr[2 * i + 6] * filterCoeffs[i + 3];
|
||||||
|
sumr += ptr[2 * i + 1] * filterCoeffs[i + 0] +
|
||||||
|
ptr[2 * i + 3] * filterCoeffs[i + 1] +
|
||||||
|
ptr[2 * i + 5] * filterCoeffs[i + 2] +
|
||||||
|
ptr[2 * i + 7] * filterCoeffs[i + 3];
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef INTEGER_SAMPLES
|
||||||
|
suml >>= resultDivFactor;
|
||||||
|
sumr >>= resultDivFactor;
|
||||||
|
// saturate to 16 bit integer limits
|
||||||
|
suml = (suml < -32768) ? -32768 : (suml > 32767) ? 32767 : suml;
|
||||||
|
// saturate to 16 bit integer limits
|
||||||
|
sumr = (sumr < -32768) ? -32768 : (sumr > 32767) ? 32767 : sumr;
|
||||||
|
#else
|
||||||
|
suml *= dScaler;
|
||||||
|
sumr *= dScaler;
|
||||||
|
#endif // INTEGER_SAMPLES
|
||||||
|
dest[j] = (SAMPLETYPE)suml;
|
||||||
|
dest[j + 1] = (SAMPLETYPE)sumr;
|
||||||
|
}
|
||||||
|
return numSamples - length;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Usual C-version of the filter routine for mono sound
|
||||||
|
uint FIRFilter::evaluateFilterMono(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSamples) const
|
||||||
|
{
|
||||||
|
uint i, j, end;
|
||||||
|
LONG_SAMPLETYPE sum;
|
||||||
|
#ifdef FLOAT_SAMPLES
|
||||||
|
// when using floating point samples, use a scaler instead of a divider
|
||||||
|
// because division is much slower operation than multiplying.
|
||||||
|
double dScaler = 1.0 / (double)resultDivider;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
assert(length != 0);
|
||||||
|
|
||||||
|
end = numSamples - length;
|
||||||
|
for (j = 0; j < end; j ++)
|
||||||
|
{
|
||||||
|
sum = 0;
|
||||||
|
for (i = 0; i < length; i += 4)
|
||||||
|
{
|
||||||
|
// loop is unrolled by factor of 4 here for efficiency
|
||||||
|
sum += src[i + 0] * filterCoeffs[i + 0] +
|
||||||
|
src[i + 1] * filterCoeffs[i + 1] +
|
||||||
|
src[i + 2] * filterCoeffs[i + 2] +
|
||||||
|
src[i + 3] * filterCoeffs[i + 3];
|
||||||
|
}
|
||||||
|
#ifdef INTEGER_SAMPLES
|
||||||
|
sum >>= resultDivFactor;
|
||||||
|
// saturate to 16 bit integer limits
|
||||||
|
sum = (sum < -32768) ? -32768 : (sum > 32767) ? 32767 : sum;
|
||||||
|
#else
|
||||||
|
sum *= dScaler;
|
||||||
|
#endif // INTEGER_SAMPLES
|
||||||
|
dest[j] = (SAMPLETYPE)sum;
|
||||||
|
src ++;
|
||||||
|
}
|
||||||
|
return end;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Set filter coeffiecients and length.
|
||||||
|
//
|
||||||
|
// Throws an exception if filter length isn't divisible by 8
|
||||||
|
void FIRFilter::setCoefficients(const SAMPLETYPE *coeffs, uint newLength, uint uResultDivFactor)
|
||||||
|
{
|
||||||
|
assert(newLength > 0);
|
||||||
|
if (newLength % 8) throw std::runtime_error("FIR filter length not divisible by 8");
|
||||||
|
|
||||||
|
lengthDiv8 = newLength / 8;
|
||||||
|
length = lengthDiv8 * 8;
|
||||||
|
assert(length == newLength);
|
||||||
|
|
||||||
|
resultDivFactor = uResultDivFactor;
|
||||||
|
#ifdef INTEGER_SAMPLES
|
||||||
|
resultDivider = (SAMPLETYPE)(1<<resultDivFactor);
|
||||||
|
#else
|
||||||
|
resultDivider = (SAMPLETYPE)powf(2, (SAMPLETYPE)resultDivFactor);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
delete[] filterCoeffs;
|
||||||
|
filterCoeffs = new SAMPLETYPE[length];
|
||||||
|
memcpy(filterCoeffs, coeffs, length * sizeof(SAMPLETYPE));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint FIRFilter::getLength() const
|
||||||
|
{
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Applies the filter to the given sequence of samples.
|
||||||
|
//
|
||||||
|
// Note : The amount of outputted samples is by value of 'filter_length'
|
||||||
|
// smaller than the amount of input samples.
|
||||||
|
uint FIRFilter::evaluate(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSamples, uint numChannels) const
|
||||||
|
{
|
||||||
|
assert(numChannels == 1 || numChannels == 2);
|
||||||
|
|
||||||
|
assert(length > 0);
|
||||||
|
assert(lengthDiv8 * 8 == length);
|
||||||
|
if (numSamples < length) return 0;
|
||||||
|
assert(resultDivFactor >= 0);
|
||||||
|
if (numChannels == 2)
|
||||||
|
{
|
||||||
|
return evaluateFilterStereo(dest, src, numSamples);
|
||||||
|
} else {
|
||||||
|
return evaluateFilterMono(dest, src, numSamples);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Operator 'new' is overloaded so that it automatically creates a suitable instance
|
||||||
|
// depending on if we've a MMX-capable CPU available or not.
|
||||||
|
void * FIRFilter::operator new(size_t s)
|
||||||
|
{
|
||||||
|
// Notice! don't use "new FIRFilter" directly, use "newInstance" to create a new instance instead!
|
||||||
|
throw std::runtime_error("Don't use 'new FIRFilter', use 'newInstance' member instead!");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
FIRFilter * FIRFilter::newInstance()
|
||||||
|
{
|
||||||
|
uint uExtensions = 0;
|
||||||
|
|
||||||
|
#if !defined(_MSC_VER) || !defined(__x86_64__)
|
||||||
|
uExtensions = detectCPUextensions();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Check if MMX/SSE/3DNow! instruction set extensions supported by CPU
|
||||||
|
|
||||||
|
#ifdef ALLOW_MMX
|
||||||
|
// MMX routines available only with integer sample types
|
||||||
|
if (uExtensions & SUPPORT_MMX)
|
||||||
|
{
|
||||||
|
return ::new FIRFilterMMX;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif // ALLOW_MMX
|
||||||
|
|
||||||
|
#ifdef ALLOW_SSE
|
||||||
|
if (uExtensions & SUPPORT_SSE)
|
||||||
|
{
|
||||||
|
// SSE support
|
||||||
|
return ::new FIRFilterSSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif // ALLOW_SSE
|
||||||
|
|
||||||
|
#ifdef ALLOW_3DNOW
|
||||||
|
if (uExtensions & SUPPORT_3DNOW)
|
||||||
|
{
|
||||||
|
// 3DNow! support
|
||||||
|
return ::new FIRFilter3DNow;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif // ALLOW_3DNOW
|
||||||
|
|
||||||
|
{
|
||||||
|
// ISA optimizations not supported, use plain C version
|
||||||
|
return ::new FIRFilter;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,163 @@
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
///
|
||||||
|
/// General FIR digital filter routines with MMX optimization.
|
||||||
|
///
|
||||||
|
/// Note : MMX optimized functions reside in a separate, platform-specific file,
|
||||||
|
/// e.g. 'mmx_win.cpp' or 'mmx_gcc.cpp'
|
||||||
|
///
|
||||||
|
/// Author : Copyright (c) Olli Parviainen
|
||||||
|
/// Author e-mail : oparviai 'at' iki.fi
|
||||||
|
/// SoundTouch WWW: http://www.surina.net/soundtouch
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Last changed : $Date: 2006/02/05 16:44:06 $
|
||||||
|
// File revision : $Revision: 1.17 $
|
||||||
|
//
|
||||||
|
// $Id: FIRFilter.h,v 1.17 2006/02/05 16:44:06 Olli Exp $
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// License :
|
||||||
|
//
|
||||||
|
// SoundTouch audio processing library
|
||||||
|
// Copyright (c) Olli Parviainen
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU Lesser General Public
|
||||||
|
// License as published by the Free Software Foundation; either
|
||||||
|
// version 2.1 of the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef FIRFilter_H
|
||||||
|
#define FIRFilter_H
|
||||||
|
|
||||||
|
#include "STTypes.h"
|
||||||
|
|
||||||
|
namespace soundtouch
|
||||||
|
{
|
||||||
|
|
||||||
|
class FIRFilter
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
// Number of FIR filter taps
|
||||||
|
uint length;
|
||||||
|
// Number of FIR filter taps divided by 8
|
||||||
|
uint lengthDiv8;
|
||||||
|
|
||||||
|
// Result divider factor in 2^k format
|
||||||
|
uint resultDivFactor;
|
||||||
|
|
||||||
|
// Result divider value.
|
||||||
|
SAMPLETYPE resultDivider;
|
||||||
|
|
||||||
|
// Memory for filter coefficients
|
||||||
|
SAMPLETYPE *filterCoeffs;
|
||||||
|
|
||||||
|
virtual uint evaluateFilterStereo(SAMPLETYPE *dest,
|
||||||
|
const SAMPLETYPE *src,
|
||||||
|
uint numSamples) const;
|
||||||
|
virtual uint evaluateFilterMono(SAMPLETYPE *dest,
|
||||||
|
const SAMPLETYPE *src,
|
||||||
|
uint numSamples) const;
|
||||||
|
|
||||||
|
public:
|
||||||
|
FIRFilter();
|
||||||
|
virtual ~FIRFilter();
|
||||||
|
|
||||||
|
/// Operator 'new' is overloaded so that it automatically creates a suitable instance
|
||||||
|
/// depending on if we've a MMX-capable CPU available or not.
|
||||||
|
void * operator new(size_t s);
|
||||||
|
|
||||||
|
static FIRFilter *newInstance();
|
||||||
|
|
||||||
|
/// Applies the filter to the given sequence of samples.
|
||||||
|
/// Note : The amount of outputted samples is by value of 'filter_length'
|
||||||
|
/// smaller than the amount of input samples.
|
||||||
|
///
|
||||||
|
/// \return Number of samples copied to 'dest'.
|
||||||
|
uint evaluate(SAMPLETYPE *dest,
|
||||||
|
const SAMPLETYPE *src,
|
||||||
|
uint numSamples,
|
||||||
|
uint numChannels) const;
|
||||||
|
|
||||||
|
uint getLength() const;
|
||||||
|
|
||||||
|
virtual void setCoefficients(const SAMPLETYPE *coeffs,
|
||||||
|
uint newLength,
|
||||||
|
uint uResultDivFactor);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Optional subclasses that implement CPU-specific optimizations:
|
||||||
|
|
||||||
|
#ifdef ALLOW_MMX
|
||||||
|
|
||||||
|
/// Class that implements MMX optimized functions exclusive for 16bit integer samples type.
|
||||||
|
class FIRFilterMMX : public FIRFilter
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
short *filterCoeffsUnalign;
|
||||||
|
short *filterCoeffsAlign;
|
||||||
|
|
||||||
|
virtual uint evaluateFilterStereo(short *dest, const short *src, uint numSamples) const;
|
||||||
|
public:
|
||||||
|
FIRFilterMMX();
|
||||||
|
~FIRFilterMMX();
|
||||||
|
|
||||||
|
virtual void setCoefficients(const short *coeffs, uint newLength, uint uResultDivFactor);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // ALLOW_MMX
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef ALLOW_3DNOW
|
||||||
|
|
||||||
|
/// Class that implements 3DNow! optimized functions exclusive for floating point samples type.
|
||||||
|
class FIRFilter3DNow : public FIRFilter
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
float *filterCoeffsUnalign;
|
||||||
|
float *filterCoeffsAlign;
|
||||||
|
|
||||||
|
virtual uint evaluateFilterStereo(float *dest, const float *src, uint numSamples) const;
|
||||||
|
public:
|
||||||
|
FIRFilter3DNow();
|
||||||
|
~FIRFilter3DNow();
|
||||||
|
virtual void setCoefficients(const float *coeffs, uint newLength, uint uResultDivFactor);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // ALLOW_3DNOW
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef ALLOW_SSE
|
||||||
|
/// Class that implements SSE optimized functions exclusive for floating point samples type.
|
||||||
|
class FIRFilterSSE : public FIRFilter
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
float *filterCoeffsUnalign;
|
||||||
|
float *filterCoeffsAlign;
|
||||||
|
|
||||||
|
virtual uint evaluateFilterStereo(float *dest, const float *src, uint numSamples) const;
|
||||||
|
public:
|
||||||
|
FIRFilterSSE();
|
||||||
|
~FIRFilterSSE();
|
||||||
|
|
||||||
|
virtual void setCoefficients(const float *coeffs, uint newLength, uint uResultDivFactor);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // ALLOW_SSE
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // FIRFilter_H
|
|
@ -0,0 +1,46 @@
|
||||||
|
## Process this file with automake to create Makefile.in
|
||||||
|
##
|
||||||
|
## $Id: Makefile.am,v 1.3 2006/02/05 18:33:34 Olli Exp $
|
||||||
|
##
|
||||||
|
## Copyright (C) 2003 - David W. Durham
|
||||||
|
##
|
||||||
|
## This file is part of SoundTouch, an audio processing library for pitch/time adjustments
|
||||||
|
##
|
||||||
|
## SoundTouch is free software; you can redistribute it and/or modify it under the
|
||||||
|
## terms of the GNU General Public License as published by the Free Software
|
||||||
|
## Foundation; either version 2 of the License, or (at your option) any later
|
||||||
|
## version.
|
||||||
|
##
|
||||||
|
## SoundTouch is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
## WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||||
|
## A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
##
|
||||||
|
## You should have received a copy of the GNU General Public License along with
|
||||||
|
## this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
||||||
|
## Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
|
|
||||||
|
AUTOMAKE_OPTIONS = foreign
|
||||||
|
|
||||||
|
noinst_HEADERS=AAFilter.h cpu_detect.h FIRFilter.h RateTransposer.h TDStretch.h cpu_detect_x86_gcc.cpp
|
||||||
|
noinst_LIBRARIES = libSoundTouch.a
|
||||||
|
|
||||||
|
if X86_64
|
||||||
|
libSoundTouch_a_CXXFLAGS = -fPIC
|
||||||
|
libSoundTouch_a_CFLAGS = -fPIC
|
||||||
|
else
|
||||||
|
libSoundTouch_a_CXXFLAGS = -msse -mmmx
|
||||||
|
libSoundTouch_a_CFLAGS = -msse -mmmx
|
||||||
|
endif
|
||||||
|
|
||||||
|
#lib_LTLIBRARIES=libSoundTouch.la
|
||||||
|
# the mmx_gcc.cpp and cpu_detect_x86_gcc.cpp may need to be conditionally included here from things discovered in configure.ac
|
||||||
|
libSoundTouch_a_SOURCES=AAFilter.cpp FIRFilter.cpp FIFOSampleBuffer.cpp mmx_optimized.cpp sse_optimized.cpp \
|
||||||
|
RateTransposer.cpp SoundTouch.cpp TDStretch.cpp WavFile.cpp cpu_detect_x86_gcc.cpp
|
||||||
|
|
||||||
|
# ??? test for -fcheck-new in configure.ac
|
||||||
|
# other compiler flags to add
|
||||||
|
AM_CXXFLAGS=-O3 -msse -fcheck-new -I../../include
|
||||||
|
|
||||||
|
# other linking flags to add
|
||||||
|
#libSoundTouch_la_LIBADD=
|
||||||
|
|
|
@ -0,0 +1,626 @@
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
///
|
||||||
|
/// Sample rate transposer. Changes sample rate by using linear interpolation
|
||||||
|
/// together with anti-alias filtering (first order interpolation with anti-
|
||||||
|
/// alias filtering should be quite adequate for this application)
|
||||||
|
///
|
||||||
|
/// Author : Copyright (c) Olli Parviainen
|
||||||
|
/// Author e-mail : oparviai 'at' iki.fi
|
||||||
|
/// SoundTouch WWW: http://www.surina.net/soundtouch
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Last changed : $Date: 2006/03/19 10:05:49 $
|
||||||
|
// File revision : $Revision: 1.13 $
|
||||||
|
//
|
||||||
|
// $Id: RateTransposer.cpp,v 1.13 2006/03/19 10:05:49 Olli Exp $
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// License :
|
||||||
|
//
|
||||||
|
// SoundTouch audio processing library
|
||||||
|
// Copyright (c) Olli Parviainen
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU Lesser General Public
|
||||||
|
// License as published by the Free Software Foundation; either
|
||||||
|
// version 2.1 of the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include <memory.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include "RateTransposer.h"
|
||||||
|
#include "AAFilter.h"
|
||||||
|
|
||||||
|
using namespace soundtouch;
|
||||||
|
|
||||||
|
|
||||||
|
/// A linear samplerate transposer class that uses integer arithmetics.
|
||||||
|
/// for the transposing.
|
||||||
|
class RateTransposerInteger : public RateTransposer
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
int iSlopeCount;
|
||||||
|
uint uRate;
|
||||||
|
SAMPLETYPE sPrevSampleL, sPrevSampleR;
|
||||||
|
|
||||||
|
virtual void resetRegisters();
|
||||||
|
|
||||||
|
virtual uint transposeStereo(SAMPLETYPE *dest,
|
||||||
|
const SAMPLETYPE *src,
|
||||||
|
uint numSamples);
|
||||||
|
virtual uint transposeMono(SAMPLETYPE *dest,
|
||||||
|
const SAMPLETYPE *src,
|
||||||
|
uint numSamples);
|
||||||
|
|
||||||
|
public:
|
||||||
|
RateTransposerInteger();
|
||||||
|
virtual ~RateTransposerInteger();
|
||||||
|
|
||||||
|
/// Sets new target rate. Normal rate = 1.0, smaller values represent slower
|
||||||
|
/// rate, larger faster rates.
|
||||||
|
virtual void setRate(float newRate);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/// A linear samplerate transposer class that uses floating point arithmetics
|
||||||
|
/// for the transposing.
|
||||||
|
class RateTransposerFloat : public RateTransposer
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
float fSlopeCount;
|
||||||
|
float fRateStep;
|
||||||
|
SAMPLETYPE sPrevSampleL, sPrevSampleR;
|
||||||
|
|
||||||
|
virtual void resetRegisters();
|
||||||
|
|
||||||
|
virtual uint transposeStereo(SAMPLETYPE *dest,
|
||||||
|
const SAMPLETYPE *src,
|
||||||
|
uint numSamples);
|
||||||
|
virtual uint transposeMono(SAMPLETYPE *dest,
|
||||||
|
const SAMPLETYPE *src,
|
||||||
|
uint numSamples);
|
||||||
|
|
||||||
|
public:
|
||||||
|
RateTransposerFloat();
|
||||||
|
virtual ~RateTransposerFloat();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef min
|
||||||
|
#define min(a,b) ((a > b) ? b : a)
|
||||||
|
#define max(a,b) ((a < b) ? b : a)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
// Operator 'new' is overloaded so that it automatically creates a suitable instance
|
||||||
|
// depending on if we've a MMX/SSE/etc-capable CPU available or not.
|
||||||
|
void * RateTransposer::operator new(size_t s)
|
||||||
|
{
|
||||||
|
// Notice! don't use "new TDStretch" directly, use "newInstance" to create a new instance instead!
|
||||||
|
assert(FALSE);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
RateTransposer *RateTransposer::newInstance()
|
||||||
|
{
|
||||||
|
#ifdef INTEGER_SAMPLES
|
||||||
|
return ::new RateTransposerInteger;
|
||||||
|
#else
|
||||||
|
return ::new RateTransposerFloat;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Constructor
|
||||||
|
RateTransposer::RateTransposer() : FIFOProcessor(&outputBuffer)
|
||||||
|
{
|
||||||
|
uChannels = 2;
|
||||||
|
bUseAAFilter = TRUE;
|
||||||
|
|
||||||
|
// Instantiates the anti-alias filter with default tap length
|
||||||
|
// of 32
|
||||||
|
pAAFilter = new AAFilter(32);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
RateTransposer::~RateTransposer()
|
||||||
|
{
|
||||||
|
delete pAAFilter;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// Enables/disables the anti-alias filter. Zero to disable, nonzero to enable
|
||||||
|
void RateTransposer::enableAAFilter(const BOOL newMode)
|
||||||
|
{
|
||||||
|
bUseAAFilter = newMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Returns nonzero if anti-alias filter is enabled.
|
||||||
|
BOOL RateTransposer::isAAFilterEnabled() const
|
||||||
|
{
|
||||||
|
return bUseAAFilter;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
AAFilter *RateTransposer::getAAFilter() const
|
||||||
|
{
|
||||||
|
return pAAFilter;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Sets new target uRate. Normal uRate = 1.0, smaller values represent slower
|
||||||
|
// uRate, larger faster uRates.
|
||||||
|
void RateTransposer::setRate(float newRate)
|
||||||
|
{
|
||||||
|
float fCutoff;
|
||||||
|
|
||||||
|
fRate = newRate;
|
||||||
|
|
||||||
|
// design a new anti-alias filter
|
||||||
|
if (newRate > 1.0f)
|
||||||
|
{
|
||||||
|
fCutoff = 0.5f / newRate;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fCutoff = 0.5f * newRate;
|
||||||
|
}
|
||||||
|
pAAFilter->setCutoffFreq(fCutoff);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Outputs as many samples of the 'outputBuffer' as possible, and if there's
|
||||||
|
// any room left, outputs also as many of the incoming samples as possible.
|
||||||
|
// The goal is to drive the outputBuffer empty.
|
||||||
|
//
|
||||||
|
// It's allowed for 'output' and 'input' parameters to point to the same
|
||||||
|
// memory position.
|
||||||
|
void RateTransposer::flushStoreBuffer()
|
||||||
|
{
|
||||||
|
if (storeBuffer.isEmpty()) return;
|
||||||
|
|
||||||
|
outputBuffer.moveSamples(storeBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Adds 'numSamples' pcs of samples from the 'samples' memory position into
|
||||||
|
// the input of the object.
|
||||||
|
void RateTransposer::putSamples(const SAMPLETYPE *samples, uint numSamples)
|
||||||
|
{
|
||||||
|
processSamples(samples, numSamples);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Transposes up the sample rate, causing the observed playback 'rate' of the
|
||||||
|
// sound to decrease
|
||||||
|
void RateTransposer::upsample(const SAMPLETYPE *src, uint numSamples)
|
||||||
|
{
|
||||||
|
int count, sizeTemp, num;
|
||||||
|
|
||||||
|
// If the parameter 'uRate' value is smaller than 'SCALE', first transpose
|
||||||
|
// the samples and then apply the anti-alias filter to remove aliasing.
|
||||||
|
|
||||||
|
// First check that there's enough room in 'storeBuffer'
|
||||||
|
// (+16 is to reserve some slack in the destination buffer)
|
||||||
|
sizeTemp = (int)((float)numSamples / fRate + 16.0f);
|
||||||
|
|
||||||
|
// Transpose the samples, store the result into the end of "storeBuffer"
|
||||||
|
count = transpose(storeBuffer.ptrEnd(sizeTemp), src, numSamples);
|
||||||
|
storeBuffer.putSamples(count);
|
||||||
|
|
||||||
|
// Apply the anti-alias filter to samples in "store output", output the
|
||||||
|
// result to "dest"
|
||||||
|
num = storeBuffer.numSamples();
|
||||||
|
count = pAAFilter->evaluate(outputBuffer.ptrEnd(num),
|
||||||
|
storeBuffer.ptrBegin(), num, uChannels);
|
||||||
|
outputBuffer.putSamples(count);
|
||||||
|
|
||||||
|
// Remove the processed samples from "storeBuffer"
|
||||||
|
storeBuffer.receiveSamples(count);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Transposes down the sample rate, causing the observed playback 'rate' of the
|
||||||
|
// sound to increase
|
||||||
|
void RateTransposer::downsample(const SAMPLETYPE *src, uint numSamples)
|
||||||
|
{
|
||||||
|
int count, sizeTemp;
|
||||||
|
|
||||||
|
// If the parameter 'uRate' value is larger than 'SCALE', first apply the
|
||||||
|
// anti-alias filter to remove high frequencies (prevent them from folding
|
||||||
|
// over the lover frequencies), then transpose. */
|
||||||
|
|
||||||
|
// Add the new samples to the end of the storeBuffer */
|
||||||
|
storeBuffer.putSamples(src, numSamples);
|
||||||
|
|
||||||
|
// Anti-alias filter the samples to prevent folding and output the filtered
|
||||||
|
// data to tempBuffer. Note : because of the FIR filter length, the
|
||||||
|
// filtering routine takes in 'filter_length' more samples than it outputs.
|
||||||
|
assert(tempBuffer.isEmpty());
|
||||||
|
sizeTemp = storeBuffer.numSamples();
|
||||||
|
|
||||||
|
count = pAAFilter->evaluate(tempBuffer.ptrEnd(sizeTemp),
|
||||||
|
storeBuffer.ptrBegin(), sizeTemp, uChannels);
|
||||||
|
|
||||||
|
// Remove the filtered samples from 'storeBuffer'
|
||||||
|
storeBuffer.receiveSamples(count);
|
||||||
|
|
||||||
|
// Transpose the samples (+16 is to reserve some slack in the destination buffer)
|
||||||
|
sizeTemp = (int)((float)numSamples / fRate + 16.0f);
|
||||||
|
count = transpose(outputBuffer.ptrEnd(sizeTemp), tempBuffer.ptrBegin(), count);
|
||||||
|
outputBuffer.putSamples(count);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Transposes sample rate by applying anti-alias filter to prevent folding.
|
||||||
|
// Returns amount of samples returned in the "dest" buffer.
|
||||||
|
// The maximum amount of samples that can be returned at a time is set by
|
||||||
|
// the 'set_returnBuffer_size' function.
|
||||||
|
void RateTransposer::processSamples(const SAMPLETYPE *src, uint numSamples)
|
||||||
|
{
|
||||||
|
uint count;
|
||||||
|
uint sizeReq;
|
||||||
|
|
||||||
|
if (numSamples == 0) return;
|
||||||
|
assert(pAAFilter);
|
||||||
|
|
||||||
|
// If anti-alias filter is turned off, simply transpose without applying
|
||||||
|
// the filter
|
||||||
|
if (bUseAAFilter == FALSE)
|
||||||
|
{
|
||||||
|
sizeReq = (int)((float)numSamples / fRate + 1.0f);
|
||||||
|
count = transpose(outputBuffer.ptrEnd(sizeReq), src, numSamples);
|
||||||
|
outputBuffer.putSamples(count);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transpose with anti-alias filter
|
||||||
|
if (fRate < 1.0f)
|
||||||
|
{
|
||||||
|
upsample(src, numSamples);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
downsample(src, numSamples);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Transposes the sample rate of the given samples using linear interpolation.
|
||||||
|
// Returns the number of samples returned in the "dest" buffer
|
||||||
|
inline uint RateTransposer::transpose(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSamples)
|
||||||
|
{
|
||||||
|
if (uChannels == 2)
|
||||||
|
{
|
||||||
|
return transposeStereo(dest, src, numSamples);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return transposeMono(dest, src, numSamples);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Sets the number of channels, 1 = mono, 2 = stereo
|
||||||
|
void RateTransposer::setChannels(const uint numchannels)
|
||||||
|
{
|
||||||
|
if (uChannels == numchannels) return;
|
||||||
|
|
||||||
|
assert(numchannels == 1 || numchannels == 2);
|
||||||
|
uChannels = numchannels;
|
||||||
|
|
||||||
|
storeBuffer.setChannels(uChannels);
|
||||||
|
tempBuffer.setChannels(uChannels);
|
||||||
|
outputBuffer.setChannels(uChannels);
|
||||||
|
|
||||||
|
// Inits the linear interpolation registers
|
||||||
|
resetRegisters();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Clears all the samples in the object
|
||||||
|
void RateTransposer::clear()
|
||||||
|
{
|
||||||
|
outputBuffer.clear();
|
||||||
|
storeBuffer.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Returns nonzero if there aren't any samples available for outputting.
|
||||||
|
uint RateTransposer::isEmpty()
|
||||||
|
{
|
||||||
|
int res;
|
||||||
|
|
||||||
|
res = FIFOProcessor::isEmpty();
|
||||||
|
if (res == 0) return 0;
|
||||||
|
return storeBuffer.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// RateTransposerInteger - integer arithmetic implementation
|
||||||
|
//
|
||||||
|
|
||||||
|
/// fixed-point interpolation routine precision
|
||||||
|
#define SCALE 65536
|
||||||
|
|
||||||
|
// Constructor
|
||||||
|
RateTransposerInteger::RateTransposerInteger() : RateTransposer()
|
||||||
|
{
|
||||||
|
// call these here as these are virtual functions; calling these
|
||||||
|
// from the base class constructor wouldn't execute the overloaded
|
||||||
|
// versions (<master yoda>peculiar C++ can be</my>).
|
||||||
|
resetRegisters();
|
||||||
|
setRate(1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
RateTransposerInteger::~RateTransposerInteger()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void RateTransposerInteger::resetRegisters()
|
||||||
|
{
|
||||||
|
iSlopeCount = 0;
|
||||||
|
sPrevSampleL =
|
||||||
|
sPrevSampleR = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Transposes the sample rate of the given samples using linear interpolation.
|
||||||
|
// 'Mono' version of the routine. Returns the number of samples returned in
|
||||||
|
// the "dest" buffer
|
||||||
|
uint RateTransposerInteger::transposeMono(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSamples)
|
||||||
|
{
|
||||||
|
unsigned int i, used;
|
||||||
|
LONG_SAMPLETYPE temp, vol1;
|
||||||
|
|
||||||
|
used = 0;
|
||||||
|
i = 0;
|
||||||
|
|
||||||
|
// Process the last sample saved from the previous call first...
|
||||||
|
while (iSlopeCount <= SCALE)
|
||||||
|
{
|
||||||
|
vol1 = (LONG_SAMPLETYPE)(SCALE - iSlopeCount);
|
||||||
|
temp = vol1 * sPrevSampleL + iSlopeCount * src[0];
|
||||||
|
dest[i] = (SAMPLETYPE)(temp / SCALE);
|
||||||
|
i++;
|
||||||
|
iSlopeCount += uRate;
|
||||||
|
}
|
||||||
|
// now always (iSlopeCount > SCALE)
|
||||||
|
iSlopeCount -= SCALE;
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
while (iSlopeCount > SCALE)
|
||||||
|
{
|
||||||
|
iSlopeCount -= SCALE;
|
||||||
|
used ++;
|
||||||
|
if (used >= numSamples - 1) goto end;
|
||||||
|
}
|
||||||
|
vol1 = (LONG_SAMPLETYPE)(SCALE - iSlopeCount);
|
||||||
|
temp = src[used] * vol1 + iSlopeCount * src[used + 1];
|
||||||
|
dest[i] = (SAMPLETYPE)(temp / SCALE);
|
||||||
|
|
||||||
|
i++;
|
||||||
|
iSlopeCount += uRate;
|
||||||
|
}
|
||||||
|
end:
|
||||||
|
// Store the last sample for the next round
|
||||||
|
sPrevSampleL = src[numSamples - 1];
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Transposes the sample rate of the given samples using linear interpolation.
|
||||||
|
// 'Stereo' version of the routine. Returns the number of samples returned in
|
||||||
|
// the "dest" buffer
|
||||||
|
uint RateTransposerInteger::transposeStereo(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSamples)
|
||||||
|
{
|
||||||
|
unsigned int srcPos, i, used;
|
||||||
|
LONG_SAMPLETYPE temp, vol1;
|
||||||
|
|
||||||
|
if (numSamples == 0) return 0; // no samples, no work
|
||||||
|
|
||||||
|
used = 0;
|
||||||
|
i = 0;
|
||||||
|
|
||||||
|
// Process the last sample saved from the sPrevSampleLious call first...
|
||||||
|
while (iSlopeCount <= SCALE)
|
||||||
|
{
|
||||||
|
vol1 = (LONG_SAMPLETYPE)(SCALE - iSlopeCount);
|
||||||
|
temp = vol1 * sPrevSampleL + iSlopeCount * src[0];
|
||||||
|
dest[2 * i] = (SAMPLETYPE)(temp / SCALE);
|
||||||
|
temp = vol1 * sPrevSampleR + iSlopeCount * src[1];
|
||||||
|
dest[2 * i + 1] = (SAMPLETYPE)(temp / SCALE);
|
||||||
|
i++;
|
||||||
|
iSlopeCount += uRate;
|
||||||
|
}
|
||||||
|
// now always (iSlopeCount > SCALE)
|
||||||
|
iSlopeCount -= SCALE;
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
while (iSlopeCount > SCALE)
|
||||||
|
{
|
||||||
|
iSlopeCount -= SCALE;
|
||||||
|
used ++;
|
||||||
|
if (used >= numSamples - 1) goto end;
|
||||||
|
}
|
||||||
|
srcPos = 2 * used;
|
||||||
|
vol1 = (LONG_SAMPLETYPE)(SCALE - iSlopeCount);
|
||||||
|
temp = src[srcPos] * vol1 + iSlopeCount * src[srcPos + 2];
|
||||||
|
dest[2 * i] = (SAMPLETYPE)(temp / SCALE);
|
||||||
|
temp = src[srcPos + 1] * vol1 + iSlopeCount * src[srcPos + 3];
|
||||||
|
dest[2 * i + 1] = (SAMPLETYPE)(temp / SCALE);
|
||||||
|
|
||||||
|
i++;
|
||||||
|
iSlopeCount += uRate;
|
||||||
|
}
|
||||||
|
end:
|
||||||
|
// Store the last sample for the next round
|
||||||
|
sPrevSampleL = src[2 * numSamples - 2];
|
||||||
|
sPrevSampleR = src[2 * numSamples - 1];
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Sets new target uRate. Normal uRate = 1.0, smaller values represent slower
|
||||||
|
// uRate, larger faster uRates.
|
||||||
|
void RateTransposerInteger::setRate(float newRate)
|
||||||
|
{
|
||||||
|
uRate = (int)(newRate * SCALE + 0.5f);
|
||||||
|
RateTransposer::setRate(newRate);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// RateTransposerFloat - floating point arithmetic implementation
|
||||||
|
//
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Constructor
|
||||||
|
RateTransposerFloat::RateTransposerFloat() : RateTransposer()
|
||||||
|
{
|
||||||
|
// call these here as these are virtual functions; calling these
|
||||||
|
// from the base class constructor wouldn't execute the overloaded
|
||||||
|
// versions (<master yoda>peculiar C++ can be</my>).
|
||||||
|
resetRegisters();
|
||||||
|
setRate(1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
RateTransposerFloat::~RateTransposerFloat()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void RateTransposerFloat::resetRegisters()
|
||||||
|
{
|
||||||
|
fSlopeCount = 0;
|
||||||
|
sPrevSampleL =
|
||||||
|
sPrevSampleR = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Transposes the sample rate of the given samples using linear interpolation.
|
||||||
|
// 'Mono' version of the routine. Returns the number of samples returned in
|
||||||
|
// the "dest" buffer
|
||||||
|
uint RateTransposerFloat::transposeMono(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSamples)
|
||||||
|
{
|
||||||
|
unsigned int i, used;
|
||||||
|
|
||||||
|
used = 0;
|
||||||
|
i = 0;
|
||||||
|
|
||||||
|
// Process the last sample saved from the previous call first...
|
||||||
|
while (fSlopeCount <= 1.0f)
|
||||||
|
{
|
||||||
|
dest[i] = (SAMPLETYPE)((1.0f - fSlopeCount) * sPrevSampleL + fSlopeCount * src[0]);
|
||||||
|
i++;
|
||||||
|
fSlopeCount += fRate;
|
||||||
|
}
|
||||||
|
fSlopeCount -= 1.0f;
|
||||||
|
|
||||||
|
if (numSamples == 1) goto end;
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
while (fSlopeCount > 1.0f)
|
||||||
|
{
|
||||||
|
fSlopeCount -= 1.0f;
|
||||||
|
used ++;
|
||||||
|
if (used >= numSamples - 1) goto end;
|
||||||
|
}
|
||||||
|
dest[i] = (SAMPLETYPE)((1.0f - fSlopeCount) * src[used] + fSlopeCount * src[used + 1]);
|
||||||
|
i++;
|
||||||
|
fSlopeCount += fRate;
|
||||||
|
}
|
||||||
|
end:
|
||||||
|
// Store the last sample for the next round
|
||||||
|
sPrevSampleL = src[numSamples - 1];
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Transposes the sample rate of the given samples using linear interpolation.
|
||||||
|
// 'Mono' version of the routine. Returns the number of samples returned in
|
||||||
|
// the "dest" buffer
|
||||||
|
uint RateTransposerFloat::transposeStereo(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSamples)
|
||||||
|
{
|
||||||
|
unsigned int srcPos, i, used;
|
||||||
|
|
||||||
|
if (numSamples == 0) return 0; // no samples, no work
|
||||||
|
|
||||||
|
used = 0;
|
||||||
|
i = 0;
|
||||||
|
|
||||||
|
// Process the last sample saved from the sPrevSampleLious call first...
|
||||||
|
while (fSlopeCount <= 1.0f)
|
||||||
|
{
|
||||||
|
dest[2 * i] = (SAMPLETYPE)((1.0f - fSlopeCount) * sPrevSampleL + fSlopeCount * src[0]);
|
||||||
|
dest[2 * i + 1] = (SAMPLETYPE)((1.0f - fSlopeCount) * sPrevSampleR + fSlopeCount * src[1]);
|
||||||
|
i++;
|
||||||
|
fSlopeCount += fRate;
|
||||||
|
}
|
||||||
|
// now always (iSlopeCount > 1.0f)
|
||||||
|
fSlopeCount -= 1.0f;
|
||||||
|
|
||||||
|
if (numSamples == 1) goto end;
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
while (fSlopeCount > 1.0f)
|
||||||
|
{
|
||||||
|
fSlopeCount -= 1.0f;
|
||||||
|
used ++;
|
||||||
|
if (used >= numSamples - 1) goto end;
|
||||||
|
}
|
||||||
|
srcPos = 2 * used;
|
||||||
|
|
||||||
|
dest[2 * i] = (SAMPLETYPE)((1.0f - fSlopeCount) * src[srcPos]
|
||||||
|
+ fSlopeCount * src[srcPos + 2]);
|
||||||
|
dest[2 * i + 1] = (SAMPLETYPE)((1.0f - fSlopeCount) * src[srcPos + 1]
|
||||||
|
+ fSlopeCount * src[srcPos + 3]);
|
||||||
|
|
||||||
|
i++;
|
||||||
|
fSlopeCount += fRate;
|
||||||
|
}
|
||||||
|
end:
|
||||||
|
// Store the last sample for the next round
|
||||||
|
sPrevSampleL = src[2 * numSamples - 2];
|
||||||
|
sPrevSampleR = src[2 * numSamples - 1];
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
|
@ -0,0 +1,162 @@
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
///
|
||||||
|
/// Sample rate transposer. Changes sample rate by using linear interpolation
|
||||||
|
/// together with anti-alias filtering (first order interpolation with anti-
|
||||||
|
/// alias filtering should be quite adequate for this application).
|
||||||
|
///
|
||||||
|
/// Use either of the derived classes of 'RateTransposerInteger' or
|
||||||
|
/// 'RateTransposerFloat' for corresponding integer/floating point tranposing
|
||||||
|
/// algorithm implementation.
|
||||||
|
///
|
||||||
|
/// Author : Copyright (c) Olli Parviainen
|
||||||
|
/// Author e-mail : oparviai 'at' iki.fi
|
||||||
|
/// SoundTouch WWW: http://www.surina.net/soundtouch
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Last changed : $Date: 2006/02/05 16:44:06 $
|
||||||
|
// File revision : $Revision: 1.10 $
|
||||||
|
//
|
||||||
|
// $Id: RateTransposer.h,v 1.10 2006/02/05 16:44:06 Olli Exp $
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// License :
|
||||||
|
//
|
||||||
|
// SoundTouch audio processing library
|
||||||
|
// Copyright (c) Olli Parviainen
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU Lesser General Public
|
||||||
|
// License as published by the Free Software Foundation; either
|
||||||
|
// version 2.1 of the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef RateTransposer_H
|
||||||
|
#define RateTransposer_H
|
||||||
|
|
||||||
|
#include "AAFilter.h"
|
||||||
|
#include "FIFOSamplePipe.h"
|
||||||
|
#include "FIFOSampleBuffer.h"
|
||||||
|
|
||||||
|
#include "STTypes.h"
|
||||||
|
|
||||||
|
namespace soundtouch
|
||||||
|
{
|
||||||
|
|
||||||
|
/// A common linear samplerate transposer class.
|
||||||
|
///
|
||||||
|
/// Note: Use function "RateTransposer::newInstance()" to create a new class
|
||||||
|
/// instance instead of the "new" operator; that function automatically
|
||||||
|
/// chooses a correct implementation depending on if integer or floating
|
||||||
|
/// arithmetics are to be used.
|
||||||
|
class RateTransposer : public FIFOProcessor
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
/// Anti-alias filter object
|
||||||
|
AAFilter *pAAFilter;
|
||||||
|
|
||||||
|
float fRate;
|
||||||
|
|
||||||
|
uint uChannels;
|
||||||
|
|
||||||
|
/// Buffer for collecting samples to feed the anti-alias filter between
|
||||||
|
/// two batches
|
||||||
|
FIFOSampleBuffer storeBuffer;
|
||||||
|
|
||||||
|
/// Buffer for keeping samples between transposing & anti-alias filter
|
||||||
|
FIFOSampleBuffer tempBuffer;
|
||||||
|
|
||||||
|
/// Output sample buffer
|
||||||
|
FIFOSampleBuffer outputBuffer;
|
||||||
|
|
||||||
|
BOOL bUseAAFilter;
|
||||||
|
|
||||||
|
void init();
|
||||||
|
|
||||||
|
virtual void resetRegisters() = 0;
|
||||||
|
|
||||||
|
virtual uint transposeStereo(SAMPLETYPE *dest,
|
||||||
|
const SAMPLETYPE *src,
|
||||||
|
uint numSamples) = 0;
|
||||||
|
virtual uint transposeMono(SAMPLETYPE *dest,
|
||||||
|
const SAMPLETYPE *src,
|
||||||
|
uint numSamples) = 0;
|
||||||
|
uint transpose(SAMPLETYPE *dest,
|
||||||
|
const SAMPLETYPE *src,
|
||||||
|
uint numSamples);
|
||||||
|
|
||||||
|
void flushStoreBuffer();
|
||||||
|
|
||||||
|
void downsample(const SAMPLETYPE *src,
|
||||||
|
uint numSamples);
|
||||||
|
void upsample(const SAMPLETYPE *src,
|
||||||
|
uint numSamples);
|
||||||
|
|
||||||
|
/// Transposes sample rate by applying anti-alias filter to prevent folding.
|
||||||
|
/// Returns amount of samples returned in the "dest" buffer.
|
||||||
|
/// The maximum amount of samples that can be returned at a time is set by
|
||||||
|
/// the 'set_returnBuffer_size' function.
|
||||||
|
void processSamples(const SAMPLETYPE *src,
|
||||||
|
uint numSamples);
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
RateTransposer();
|
||||||
|
virtual ~RateTransposer();
|
||||||
|
|
||||||
|
/// Operator 'new' is overloaded so that it automatically creates a suitable instance
|
||||||
|
/// depending on if we're to use integer or floating point arithmetics.
|
||||||
|
void *operator new(size_t s);
|
||||||
|
|
||||||
|
/// Use this function instead of "new" operator to create a new instance of this class.
|
||||||
|
/// This function automatically chooses a correct implementation, depending on if
|
||||||
|
/// integer ot floating point arithmetics are to be used.
|
||||||
|
static RateTransposer *newInstance();
|
||||||
|
|
||||||
|
/// Returns the output buffer object
|
||||||
|
FIFOSamplePipe *getOutput() { return &outputBuffer; };
|
||||||
|
|
||||||
|
/// Returns the store buffer object
|
||||||
|
FIFOSamplePipe *getStore() { return &storeBuffer; };
|
||||||
|
|
||||||
|
/// Return anti-alias filter object
|
||||||
|
AAFilter *getAAFilter() const;
|
||||||
|
|
||||||
|
/// Enables/disables the anti-alias filter. Zero to disable, nonzero to enable
|
||||||
|
void enableAAFilter(BOOL newMode);
|
||||||
|
|
||||||
|
/// Returns nonzero if anti-alias filter is enabled.
|
||||||
|
BOOL isAAFilterEnabled() const;
|
||||||
|
|
||||||
|
/// Sets new target rate. Normal rate = 1.0, smaller values represent slower
|
||||||
|
/// rate, larger faster rates.
|
||||||
|
virtual void setRate(float newRate);
|
||||||
|
|
||||||
|
/// Sets the number of channels, 1 = mono, 2 = stereo
|
||||||
|
void setChannels(uint channels);
|
||||||
|
|
||||||
|
/// Adds 'numSamples' pcs of samples from the 'samples' memory position into
|
||||||
|
/// the input of the object.
|
||||||
|
void putSamples(const SAMPLETYPE *samples, uint numSamples);
|
||||||
|
|
||||||
|
/// Clears all the samples in the object
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
/// Returns nonzero if there aren't any samples available for outputting.
|
||||||
|
uint isEmpty();
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,202 @@
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
///
|
||||||
|
/// Common type definitions for SoundTouch audio processing library.
|
||||||
|
///
|
||||||
|
/// Author : Copyright (c) Olli Parviainen
|
||||||
|
/// Author e-mail : oparviai 'at' iki.fi
|
||||||
|
/// SoundTouch WWW: http://www.surina.net/soundtouch
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Last changed : $Date: 2006/02/05 16:44:06 $
|
||||||
|
// File revision : $Revision: 1.16 $
|
||||||
|
//
|
||||||
|
// $Id: STTypes.h,v 1.16 2006/02/05 16:44:06 Olli Exp $
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// License :
|
||||||
|
//
|
||||||
|
// SoundTouch audio processing library
|
||||||
|
// Copyright (c) Olli Parviainen
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU Lesser General Public
|
||||||
|
// License as published by the Free Software Foundation; either
|
||||||
|
// version 2.1 of the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef STTypes_H
|
||||||
|
#define STTypes_H
|
||||||
|
|
||||||
|
//#define INTEGER_SAMPLES 1
|
||||||
|
|
||||||
|
typedef unsigned int uint;
|
||||||
|
typedef unsigned long ulong;
|
||||||
|
|
||||||
|
#ifdef __x86_64__
|
||||||
|
typedef unsigned long long ulongptr;
|
||||||
|
#else
|
||||||
|
typedef unsigned long ulongptr;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
// In GCC, include soundtouch_config.h made by config scritps
|
||||||
|
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||||
|
#define HAVE_INTTYPES_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `m' library (-lm). */
|
||||||
|
#define HAVE_LIBM 1
|
||||||
|
|
||||||
|
/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
|
||||||
|
to 0 otherwise. */
|
||||||
|
#define HAVE_MALLOC 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <memory.h> header file. */
|
||||||
|
#define HAVE_MEMORY_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <stdint.h> header file. */
|
||||||
|
#define HAVE_STDINT_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||||
|
#define HAVE_STDLIB_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <strings.h> header file. */
|
||||||
|
#define HAVE_STRINGS_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <string.h> header file. */
|
||||||
|
#define HAVE_STRING_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||||
|
#define HAVE_SYS_STAT_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||||
|
#define HAVE_SYS_TYPES_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <unistd.h> header file. */
|
||||||
|
#define HAVE_UNISTD_H 1
|
||||||
|
|
||||||
|
/* Use Integer as Sample type */
|
||||||
|
//#define INTEGER_SAMPLES 1
|
||||||
|
|
||||||
|
/* Define as the return type of signal handlers (`int' or `void'). */
|
||||||
|
#define RETSIGTYPE void
|
||||||
|
|
||||||
|
/* Define to 1 if you have the ANSI C header files. */
|
||||||
|
#define STDC_HEADERS 1
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _WINDEF_
|
||||||
|
// if these aren't defined already by Windows headers, define now
|
||||||
|
|
||||||
|
typedef int BOOL;
|
||||||
|
|
||||||
|
#ifndef FALSE
|
||||||
|
#define FALSE 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef TRUE
|
||||||
|
#define TRUE 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // _WINDEF_
|
||||||
|
|
||||||
|
|
||||||
|
namespace soundtouch
|
||||||
|
{
|
||||||
|
/// Activate these undef's to overrule the possible sampletype
|
||||||
|
/// setting inherited from some other header file:
|
||||||
|
//#undef INTEGER_SAMPLES
|
||||||
|
//#undef FLOAT_SAMPLES
|
||||||
|
|
||||||
|
#if !(INTEGER_SAMPLES || FLOAT_SAMPLES)
|
||||||
|
|
||||||
|
/// Choose either 32bit floating point or 16bit integer sampletype
|
||||||
|
/// by choosing one of the following defines, unless this selection
|
||||||
|
/// has already been done in some other file.
|
||||||
|
////
|
||||||
|
/// Notes:
|
||||||
|
/// - In Windows environment, choose the sample format with the
|
||||||
|
/// following defines.
|
||||||
|
/// - In GNU environment, the floating point samples are used by
|
||||||
|
/// default, but integer samples can be chosen by giving the
|
||||||
|
/// following switch to the configure script:
|
||||||
|
/// ./configure --enable-integer-samples
|
||||||
|
/// However, if you still prefer to select the sample format here
|
||||||
|
/// also in GNU environment, then please #undef the INTEGER_SAMPLE
|
||||||
|
/// and FLOAT_SAMPLE defines first as in comments above.
|
||||||
|
//#define INTEGER_SAMPLES 1 //< 16bit integer samples
|
||||||
|
#define FLOAT_SAMPLES 1 //< 32bit float samples
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// Define this to allow CPU-specific assembler optimizations. Notice that
|
||||||
|
/// having this enabled on non-x86 platforms doesn't matter; the compiler can
|
||||||
|
/// drop unsupported extensions on different platforms automatically.
|
||||||
|
/// However, if you're having difficulties getting the optimized routines
|
||||||
|
/// compiled with your compler (e.g. some gcc compiler versions may be picky),
|
||||||
|
/// you may wish to disable the optimizations to make the library compile.
|
||||||
|
#if !defined(_MSC_VER) || !defined(__x86_64__)
|
||||||
|
#define ALLOW_OPTIMIZATIONS 1
|
||||||
|
#define ALLOW_NONEXACT_SIMD_OPTIMIZATION 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
// If defined, allows the SIMD-optimized routines to take minor shortcuts
|
||||||
|
// for improved performance. Undefine to require faithfully similar SIMD
|
||||||
|
// calculations as in normal C implementation.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef INTEGER_SAMPLES
|
||||||
|
// 16bit integer sample type
|
||||||
|
typedef short SAMPLETYPE;
|
||||||
|
// data type for sample accumulation: Use 32bit integer to prevent overflows
|
||||||
|
typedef long LONG_SAMPLETYPE;
|
||||||
|
|
||||||
|
#ifdef FLOAT_SAMPLES
|
||||||
|
// check that only one sample type is defined
|
||||||
|
#error "conflicting sample types defined"
|
||||||
|
#endif // FLOAT_SAMPLES
|
||||||
|
|
||||||
|
#ifdef ALLOW_OPTIMIZATIONS
|
||||||
|
#if (_WIN32 || __i386__ || __x86_64__)
|
||||||
|
// Allow MMX optimizations
|
||||||
|
#define ALLOW_MMX 1
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
// floating point samples
|
||||||
|
typedef float SAMPLETYPE;
|
||||||
|
// data type for sample accumulation: Use double to utilize full precision.
|
||||||
|
typedef double LONG_SAMPLETYPE;
|
||||||
|
|
||||||
|
#ifdef ALLOW_OPTIMIZATIONS
|
||||||
|
// Allow 3DNow! and SSE optimizations
|
||||||
|
#if _WIN32
|
||||||
|
// #define ALLOW_3DNOW 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (_WIN32 || __i386__ || __x86_64__)
|
||||||
|
#define ALLOW_SSE 1
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // INTEGER_SAMPLES
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,474 @@
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
///
|
||||||
|
/// SoundTouch - main class for tempo/pitch/rate adjusting routines.
|
||||||
|
///
|
||||||
|
/// Notes:
|
||||||
|
/// - Initialize the SoundTouch object instance by setting up the sound stream
|
||||||
|
/// parameters with functions 'setSampleRate' and 'setChannels', then set
|
||||||
|
/// desired tempo/pitch/rate settings with the corresponding functions.
|
||||||
|
///
|
||||||
|
/// - The SoundTouch class behaves like a first-in-first-out pipeline: The
|
||||||
|
/// samples that are to be processed are fed into one of the pipe by calling
|
||||||
|
/// function 'putSamples', while the ready processed samples can be read
|
||||||
|
/// from the other end of the pipeline with function 'receiveSamples'.
|
||||||
|
///
|
||||||
|
/// - The SoundTouch processing classes require certain sized 'batches' of
|
||||||
|
/// samples in order to process the sound. For this reason the classes buffer
|
||||||
|
/// incoming samples until there are enough of samples available for
|
||||||
|
/// processing, then they carry out the processing step and consequently
|
||||||
|
/// make the processed samples available for outputting.
|
||||||
|
///
|
||||||
|
/// - For the above reason, the processing routines introduce a certain
|
||||||
|
/// 'latency' between the input and output, so that the samples input to
|
||||||
|
/// SoundTouch may not be immediately available in the output, and neither
|
||||||
|
/// the amount of outputtable samples may not immediately be in direct
|
||||||
|
/// relationship with the amount of previously input samples.
|
||||||
|
///
|
||||||
|
/// - The tempo/pitch/rate control parameters can be altered during processing.
|
||||||
|
/// Please notice though that they aren't currently protected by semaphores,
|
||||||
|
/// so in multi-thread application external semaphore protection may be
|
||||||
|
/// required.
|
||||||
|
///
|
||||||
|
/// - This class utilizes classes 'TDStretch' for tempo change (without modifying
|
||||||
|
/// pitch) and 'RateTransposer' for changing the playback rate (that is, both
|
||||||
|
/// tempo and pitch in the same ratio) of the sound. The third available control
|
||||||
|
/// 'pitch' (change pitch but maintain tempo) is produced by a combination of
|
||||||
|
/// combining the two other controls.
|
||||||
|
///
|
||||||
|
/// Author : Copyright (c) Olli Parviainen
|
||||||
|
/// Author e-mail : oparviai 'at' iki.fi
|
||||||
|
/// SoundTouch WWW: http://www.surina.net/soundtouch
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Last changed : $Date: 2006/02/05 16:44:06 $
|
||||||
|
// File revision : $Revision: 1.13 $
|
||||||
|
//
|
||||||
|
// $Id: SoundTouch.cpp,v 1.13 2006/02/05 16:44:06 Olli Exp $
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// License :
|
||||||
|
//
|
||||||
|
// SoundTouch audio processing library
|
||||||
|
// Copyright (c) Olli Parviainen
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU Lesser General Public
|
||||||
|
// License as published by the Free Software Foundation; either
|
||||||
|
// version 2.1 of the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <memory.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "SoundTouch.h"
|
||||||
|
#include "TDStretch.h"
|
||||||
|
#include "RateTransposer.h"
|
||||||
|
#include "cpu_detect.h"
|
||||||
|
|
||||||
|
using namespace soundtouch;
|
||||||
|
|
||||||
|
/// Print library version string
|
||||||
|
extern "C" void soundtouch_ac_test()
|
||||||
|
{
|
||||||
|
printf("SoundTouch Version: %s\n",SOUNDTOUCH_VERSION);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SoundTouch::SoundTouch()
|
||||||
|
{
|
||||||
|
// Initialize rate transposer and tempo changer instances
|
||||||
|
|
||||||
|
pRateTransposer = RateTransposer::newInstance();
|
||||||
|
pTDStretch = TDStretch::newInstance();
|
||||||
|
|
||||||
|
setOutPipe(pTDStretch);
|
||||||
|
|
||||||
|
rate = tempo = 0;
|
||||||
|
|
||||||
|
virtualPitch =
|
||||||
|
virtualRate =
|
||||||
|
virtualTempo = 1.0;
|
||||||
|
|
||||||
|
calcEffectiveRateAndTempo();
|
||||||
|
|
||||||
|
channels = 0;
|
||||||
|
bSrateSet = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
SoundTouch::~SoundTouch()
|
||||||
|
{
|
||||||
|
delete pRateTransposer;
|
||||||
|
delete pTDStretch;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// Get SoundTouch library version string
|
||||||
|
const char *SoundTouch::getVersionString()
|
||||||
|
{
|
||||||
|
static const char *_version = SOUNDTOUCH_VERSION;
|
||||||
|
|
||||||
|
return _version;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Get SoundTouch library version Id
|
||||||
|
uint SoundTouch::getVersionId()
|
||||||
|
{
|
||||||
|
return SOUNDTOUCH_VERSION_ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Sets the number of channels, 1 = mono, 2 = stereo
|
||||||
|
void SoundTouch::setChannels(uint numChannels)
|
||||||
|
{
|
||||||
|
if (numChannels != 1 && numChannels != 2)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Illegal number of channels");
|
||||||
|
}
|
||||||
|
channels = numChannels;
|
||||||
|
pRateTransposer->setChannels(numChannels);
|
||||||
|
pTDStretch->setChannels(numChannels);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Sets new rate control value. Normal rate = 1.0, smaller values
|
||||||
|
// represent slower rate, larger faster rates.
|
||||||
|
void SoundTouch::setRate(float newRate)
|
||||||
|
{
|
||||||
|
virtualRate = newRate;
|
||||||
|
calcEffectiveRateAndTempo();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Sets new rate control value as a difference in percents compared
|
||||||
|
// to the original rate (-50 .. +100 %)
|
||||||
|
void SoundTouch::setRateChange(float newRate)
|
||||||
|
{
|
||||||
|
virtualRate = 1.0f + 0.01f * newRate;
|
||||||
|
calcEffectiveRateAndTempo();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Sets new tempo control value. Normal tempo = 1.0, smaller values
|
||||||
|
// represent slower tempo, larger faster tempo.
|
||||||
|
void SoundTouch::setTempo(float newTempo)
|
||||||
|
{
|
||||||
|
virtualTempo = newTempo;
|
||||||
|
calcEffectiveRateAndTempo();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Sets new tempo control value as a difference in percents compared
|
||||||
|
// to the original tempo (-50 .. +100 %)
|
||||||
|
void SoundTouch::setTempoChange(float newTempo)
|
||||||
|
{
|
||||||
|
virtualTempo = 1.0f + 0.01f * newTempo;
|
||||||
|
calcEffectiveRateAndTempo();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Sets new pitch control value. Original pitch = 1.0, smaller values
|
||||||
|
// represent lower pitches, larger values higher pitch.
|
||||||
|
void SoundTouch::setPitch(float newPitch)
|
||||||
|
{
|
||||||
|
virtualPitch = newPitch;
|
||||||
|
calcEffectiveRateAndTempo();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Sets pitch change in octaves compared to the original pitch
|
||||||
|
// (-1.00 .. +1.00)
|
||||||
|
void SoundTouch::setPitchOctaves(float newPitch)
|
||||||
|
{
|
||||||
|
virtualPitch = (float)exp(0.69314718056f * newPitch);
|
||||||
|
calcEffectiveRateAndTempo();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Sets pitch change in semi-tones compared to the original pitch
|
||||||
|
// (-12 .. +12)
|
||||||
|
void SoundTouch::setPitchSemiTones(int newPitch)
|
||||||
|
{
|
||||||
|
setPitchOctaves((float)newPitch / 12.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void SoundTouch::setPitchSemiTones(float newPitch)
|
||||||
|
{
|
||||||
|
setPitchOctaves(newPitch / 12.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Calculates 'effective' rate and tempo values from the
|
||||||
|
// nominal control values.
|
||||||
|
void SoundTouch::calcEffectiveRateAndTempo()
|
||||||
|
{
|
||||||
|
float oldTempo = tempo;
|
||||||
|
float oldRate = rate;
|
||||||
|
|
||||||
|
tempo = virtualTempo / virtualPitch;
|
||||||
|
rate = virtualPitch * virtualRate;
|
||||||
|
|
||||||
|
if (rate != oldRate) pRateTransposer->setRate(rate);
|
||||||
|
if (tempo != oldTempo) pTDStretch->setTempo(tempo);
|
||||||
|
|
||||||
|
if (rate > 1.0f)
|
||||||
|
{
|
||||||
|
if (output != pRateTransposer)
|
||||||
|
{
|
||||||
|
FIFOSamplePipe *transOut;
|
||||||
|
|
||||||
|
assert(output == pTDStretch);
|
||||||
|
// move samples in the current output buffer to the output of pRateTransposer
|
||||||
|
transOut = pRateTransposer->getOutput();
|
||||||
|
transOut->moveSamples(*output);
|
||||||
|
// move samples in tempo changer's input to pitch transposer's input
|
||||||
|
pRateTransposer->moveSamples(*pTDStretch->getInput());
|
||||||
|
|
||||||
|
output = pRateTransposer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (output != pTDStretch)
|
||||||
|
{
|
||||||
|
FIFOSamplePipe *tempoOut;
|
||||||
|
|
||||||
|
assert(output == pRateTransposer);
|
||||||
|
// move samples in the current output buffer to the output of pTDStretch
|
||||||
|
tempoOut = pTDStretch->getOutput();
|
||||||
|
tempoOut->moveSamples(*output);
|
||||||
|
// move samples in pitch transposer's store buffer to tempo changer's input
|
||||||
|
pTDStretch->moveSamples(*pRateTransposer->getStore());
|
||||||
|
|
||||||
|
output = pTDStretch;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Sets sample rate.
|
||||||
|
void SoundTouch::setSampleRate(uint srate)
|
||||||
|
{
|
||||||
|
bSrateSet = TRUE;
|
||||||
|
// set sample rate, leave other tempo changer parameters as they are.
|
||||||
|
pTDStretch->setParameters(srate);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Adds 'numSamples' pcs of samples from the 'samples' memory position into
|
||||||
|
// the input of the object.
|
||||||
|
void SoundTouch::putSamples(const SAMPLETYPE *samples, uint numSamples)
|
||||||
|
{
|
||||||
|
if (bSrateSet == FALSE)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("SoundTouch : Sample rate not defined");
|
||||||
|
}
|
||||||
|
else if (channels == 0)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("SoundTouch : Number of channels not defined");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transpose the rate of the new samples if necessary
|
||||||
|
/* Bypass the nominal setting - can introduce a click in sound when tempo/pitch control crosses the nominal value...
|
||||||
|
if (rate == 1.0f)
|
||||||
|
{
|
||||||
|
// The rate value is same as the original, simply evaluate the tempo changer.
|
||||||
|
assert(output == pTDStretch);
|
||||||
|
if (pRateTransposer->isEmpty() == 0)
|
||||||
|
{
|
||||||
|
// yet flush the last samples in the pitch transposer buffer
|
||||||
|
// (may happen if 'rate' changes from a non-zero value to zero)
|
||||||
|
pTDStretch->moveSamples(*pRateTransposer);
|
||||||
|
}
|
||||||
|
pTDStretch->putSamples(samples, numSamples);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
else if (rate <= 1.0f)
|
||||||
|
{
|
||||||
|
// transpose the rate down, output the transposed sound to tempo changer buffer
|
||||||
|
assert(output == pTDStretch);
|
||||||
|
pRateTransposer->putSamples(samples, numSamples);
|
||||||
|
pTDStretch->moveSamples(*pRateTransposer);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assert(rate > 1.0f);
|
||||||
|
// evaluate the tempo changer, then transpose the rate up,
|
||||||
|
assert(output == pRateTransposer);
|
||||||
|
pTDStretch->putSamples(samples, numSamples);
|
||||||
|
pRateTransposer->moveSamples(*pTDStretch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Flushes the last samples from the processing pipeline to the output.
|
||||||
|
// Clears also the internal processing buffers.
|
||||||
|
//
|
||||||
|
// Note: This function is meant for extracting the last samples of a sound
|
||||||
|
// stream. This function may introduce additional blank samples in the end
|
||||||
|
// of the sound stream, and thus it's not recommended to call this function
|
||||||
|
// in the middle of a sound stream.
|
||||||
|
void SoundTouch::flush()
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
uint nOut;
|
||||||
|
SAMPLETYPE buff[128];
|
||||||
|
|
||||||
|
nOut = numSamples();
|
||||||
|
|
||||||
|
memset(buff, 0, 128 * sizeof(SAMPLETYPE));
|
||||||
|
// "Push" the last active samples out from the processing pipeline by
|
||||||
|
// feeding blank samples into the processing pipeline until new,
|
||||||
|
// processed samples appear in the output (not however, more than
|
||||||
|
// 8ksamples in any case)
|
||||||
|
for (i = 0; i < 128; i ++)
|
||||||
|
{
|
||||||
|
putSamples(buff, 64);
|
||||||
|
if (numSamples() != nOut) break; // new samples have appeared in the output!
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear working buffers
|
||||||
|
pRateTransposer->clear();
|
||||||
|
pTDStretch->clearInput();
|
||||||
|
// yet leave the 'tempoChanger' output intouched as that's where the
|
||||||
|
// flushed samples are!
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Changes a setting controlling the processing system behaviour. See the
|
||||||
|
// 'SETTING_...' defines for available setting ID's.
|
||||||
|
BOOL SoundTouch::setSetting(uint settingId, uint value)
|
||||||
|
{
|
||||||
|
uint sampleRate, sequenceMs, seekWindowMs, overlapMs;
|
||||||
|
|
||||||
|
// read current tdstretch routine parameters
|
||||||
|
pTDStretch->getParameters(&sampleRate, &sequenceMs, &seekWindowMs, &overlapMs);
|
||||||
|
|
||||||
|
switch (settingId)
|
||||||
|
{
|
||||||
|
case SETTING_USE_AA_FILTER :
|
||||||
|
// enables / disabless anti-alias filter
|
||||||
|
pRateTransposer->enableAAFilter((value != 0) ? TRUE : FALSE);
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
case SETTING_AA_FILTER_LENGTH :
|
||||||
|
// sets anti-alias filter length
|
||||||
|
pRateTransposer->getAAFilter()->setLength(value);
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
case SETTING_USE_QUICKSEEK :
|
||||||
|
// enables / disables tempo routine quick seeking algorithm
|
||||||
|
pTDStretch->enableQuickSeek((value != 0) ? TRUE : FALSE);
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
case SETTING_SEQUENCE_MS:
|
||||||
|
// change time-stretch sequence duration parameter
|
||||||
|
pTDStretch->setParameters(sampleRate, value, seekWindowMs, overlapMs);
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
case SETTING_SEEKWINDOW_MS:
|
||||||
|
// change time-stretch seek window length parameter
|
||||||
|
pTDStretch->setParameters(sampleRate, sequenceMs, value, overlapMs);
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
case SETTING_OVERLAP_MS:
|
||||||
|
// change time-stretch overlap length parameter
|
||||||
|
pTDStretch->setParameters(sampleRate, sequenceMs, seekWindowMs, value);
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
default :
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Reads a setting controlling the processing system behaviour. See the
|
||||||
|
// 'SETTING_...' defines for available setting ID's.
|
||||||
|
//
|
||||||
|
// Returns the setting value.
|
||||||
|
uint SoundTouch::getSetting(uint settingId) const
|
||||||
|
{
|
||||||
|
uint temp;
|
||||||
|
|
||||||
|
switch (settingId)
|
||||||
|
{
|
||||||
|
case SETTING_USE_AA_FILTER :
|
||||||
|
return pRateTransposer->isAAFilterEnabled();
|
||||||
|
|
||||||
|
case SETTING_AA_FILTER_LENGTH :
|
||||||
|
return pRateTransposer->getAAFilter()->getLength();
|
||||||
|
|
||||||
|
case SETTING_USE_QUICKSEEK :
|
||||||
|
return pTDStretch->isQuickSeekEnabled();
|
||||||
|
|
||||||
|
case SETTING_SEQUENCE_MS:
|
||||||
|
pTDStretch->getParameters(NULL, &temp, NULL, NULL);
|
||||||
|
return temp;
|
||||||
|
|
||||||
|
case SETTING_SEEKWINDOW_MS:
|
||||||
|
pTDStretch->getParameters(NULL, NULL, &temp, NULL);
|
||||||
|
return temp;
|
||||||
|
|
||||||
|
case SETTING_OVERLAP_MS:
|
||||||
|
pTDStretch->getParameters(NULL, NULL, NULL, &temp);
|
||||||
|
return temp;
|
||||||
|
|
||||||
|
default :
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Clears all the samples in the object's output and internal processing
|
||||||
|
// buffers.
|
||||||
|
void SoundTouch::clear()
|
||||||
|
{
|
||||||
|
pRateTransposer->clear();
|
||||||
|
pTDStretch->clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// Returns number of samples currently unprocessed.
|
||||||
|
uint SoundTouch::numUnprocessedSamples() const
|
||||||
|
{
|
||||||
|
FIFOSamplePipe * psp;
|
||||||
|
if (pTDStretch)
|
||||||
|
{
|
||||||
|
psp = pTDStretch->getInput();
|
||||||
|
if (psp)
|
||||||
|
{
|
||||||
|
return psp->numSamples();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,252 @@
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
///
|
||||||
|
/// SoundTouch - main class for tempo/pitch/rate adjusting routines.
|
||||||
|
///
|
||||||
|
/// Notes:
|
||||||
|
/// - Initialize the SoundTouch object instance by setting up the sound stream
|
||||||
|
/// parameters with functions 'setSampleRate' and 'setChannels', then set
|
||||||
|
/// desired tempo/pitch/rate settings with the corresponding functions.
|
||||||
|
///
|
||||||
|
/// - The SoundTouch class behaves like a first-in-first-out pipeline: The
|
||||||
|
/// samples that are to be processed are fed into one of the pipe by calling
|
||||||
|
/// function 'putSamples', while the ready processed samples can be read
|
||||||
|
/// from the other end of the pipeline with function 'receiveSamples'.
|
||||||
|
///
|
||||||
|
/// - The SoundTouch processing classes require certain sized 'batches' of
|
||||||
|
/// samples in order to process the sound. For this reason the classes buffer
|
||||||
|
/// incoming samples until there are enough of samples available for
|
||||||
|
/// processing, then they carry out the processing step and consequently
|
||||||
|
/// make the processed samples available for outputting.
|
||||||
|
///
|
||||||
|
/// - For the above reason, the processing routines introduce a certain
|
||||||
|
/// 'latency' between the input and output, so that the samples input to
|
||||||
|
/// SoundTouch may not be immediately available in the output, and neither
|
||||||
|
/// the amount of outputtable samples may not immediately be in direct
|
||||||
|
/// relationship with the amount of previously input samples.
|
||||||
|
///
|
||||||
|
/// - The tempo/pitch/rate control parameters can be altered during processing.
|
||||||
|
/// Please notice though that they aren't currently protected by semaphores,
|
||||||
|
/// so in multi-thread application external semaphore protection may be
|
||||||
|
/// required.
|
||||||
|
///
|
||||||
|
/// - This class utilizes classes 'TDStretch' for tempo change (without modifying
|
||||||
|
/// pitch) and 'RateTransposer' for changing the playback rate (that is, both
|
||||||
|
/// tempo and pitch in the same ratio) of the sound. The third available control
|
||||||
|
/// 'pitch' (change pitch but maintain tempo) is produced by a combination of
|
||||||
|
/// combining the two other controls.
|
||||||
|
///
|
||||||
|
/// Author : Copyright (c) Olli Parviainen
|
||||||
|
/// Author e-mail : oparviai 'at' iki.fi
|
||||||
|
/// SoundTouch WWW: http://www.surina.net/soundtouch
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Last changed : $Date: 2006/02/05 16:44:06 $
|
||||||
|
// File revision : $Revision: 1.14 $
|
||||||
|
//
|
||||||
|
// $Id: SoundTouch.h,v 1.14 2006/02/05 16:44:06 Olli Exp $
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// License :
|
||||||
|
//
|
||||||
|
// SoundTouch audio processing library
|
||||||
|
// Copyright (c) Olli Parviainen
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU Lesser General Public
|
||||||
|
// License as published by the Free Software Foundation; either
|
||||||
|
// version 2.1 of the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef SoundTouch_H
|
||||||
|
#define SoundTouch_H
|
||||||
|
|
||||||
|
#include "FIFOSamplePipe.h"
|
||||||
|
#include "STTypes.h"
|
||||||
|
|
||||||
|
namespace soundtouch
|
||||||
|
{
|
||||||
|
|
||||||
|
/// Soundtouch library version string
|
||||||
|
#define SOUNDTOUCH_VERSION "1.3.1"
|
||||||
|
|
||||||
|
/// SoundTouch library version id
|
||||||
|
#define SOUNDTOUCH_VERSION_ID 010301
|
||||||
|
|
||||||
|
//
|
||||||
|
// Available setting IDs for the 'setSetting' & 'get_setting' functions:
|
||||||
|
|
||||||
|
/// Enable/disable anti-alias filter in pitch transposer (0 = disable)
|
||||||
|
#define SETTING_USE_AA_FILTER 0
|
||||||
|
|
||||||
|
/// Pitch transposer anti-alias filter length (8 .. 128 taps, default = 32)
|
||||||
|
#define SETTING_AA_FILTER_LENGTH 1
|
||||||
|
|
||||||
|
/// Enable/disable quick seeking algorithm in tempo changer routine
|
||||||
|
/// (enabling quick seeking lowers CPU utilization but causes a minor sound
|
||||||
|
/// quality compromising)
|
||||||
|
#define SETTING_USE_QUICKSEEK 2
|
||||||
|
|
||||||
|
/// Time-stretch algorithm single processing sequence length in milliseconds. This determines
|
||||||
|
/// to how long sequences the original sound is chopped in the time-stretch algorithm.
|
||||||
|
/// See "STTypes.h" or README for more information.
|
||||||
|
#define SETTING_SEQUENCE_MS 3
|
||||||
|
|
||||||
|
/// Time-stretch algorithm seeking window length in milliseconds for algorithm that finds the
|
||||||
|
/// best possible overlapping location. This determines from how wide window the algorithm
|
||||||
|
/// may look for an optimal joining location when mixing the sound sequences back together.
|
||||||
|
/// See "STTypes.h" or README for more information.
|
||||||
|
#define SETTING_SEEKWINDOW_MS 4
|
||||||
|
|
||||||
|
/// Time-stretch algorithm overlap length in milliseconds. When the chopped sound sequences
|
||||||
|
/// are mixed back together, to form a continuous sound stream, this parameter defines over
|
||||||
|
/// how long period the two consecutive sequences are let to overlap each other.
|
||||||
|
/// See "STTypes.h" or README for more information.
|
||||||
|
#define SETTING_OVERLAP_MS 5
|
||||||
|
|
||||||
|
|
||||||
|
class SoundTouch : public FIFOProcessor
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
/// Rate transposer class instance
|
||||||
|
class RateTransposer *pRateTransposer;
|
||||||
|
|
||||||
|
/// Time-stretch class instance
|
||||||
|
class TDStretch *pTDStretch;
|
||||||
|
|
||||||
|
/// Virtual pitch parameter. Effective rate & tempo are calculated from these parameters.
|
||||||
|
float virtualRate;
|
||||||
|
|
||||||
|
/// Virtual pitch parameter. Effective rate & tempo are calculated from these parameters.
|
||||||
|
float virtualTempo;
|
||||||
|
|
||||||
|
/// Virtual pitch parameter. Effective rate & tempo are calculated from these parameters.
|
||||||
|
float virtualPitch;
|
||||||
|
|
||||||
|
/// Flag: Has sample rate been set?
|
||||||
|
BOOL bSrateSet;
|
||||||
|
|
||||||
|
/// Calculates effective rate & tempo valuescfrom 'virtualRate', 'virtualTempo' and
|
||||||
|
/// 'virtualPitch' parameters.
|
||||||
|
void calcEffectiveRateAndTempo();
|
||||||
|
|
||||||
|
protected :
|
||||||
|
/// Number of channels
|
||||||
|
uint channels;
|
||||||
|
|
||||||
|
/// Effective 'rate' value calculated from 'virtualRate', 'virtualTempo' and 'virtualPitch'
|
||||||
|
float rate;
|
||||||
|
|
||||||
|
/// Effective 'tempo' value calculated from 'virtualRate', 'virtualTempo' and 'virtualPitch'
|
||||||
|
float tempo;
|
||||||
|
|
||||||
|
public:
|
||||||
|
SoundTouch();
|
||||||
|
virtual ~SoundTouch();
|
||||||
|
|
||||||
|
/// Get SoundTouch library version string
|
||||||
|
static const char *getVersionString();
|
||||||
|
|
||||||
|
/// Get SoundTouch library version Id
|
||||||
|
static uint getVersionId();
|
||||||
|
|
||||||
|
/// Sets new rate control value. Normal rate = 1.0, smaller values
|
||||||
|
/// represent slower rate, larger faster rates.
|
||||||
|
void setRate(float newRate);
|
||||||
|
|
||||||
|
/// Sets new tempo control value. Normal tempo = 1.0, smaller values
|
||||||
|
/// represent slower tempo, larger faster tempo.
|
||||||
|
void setTempo(float newTempo);
|
||||||
|
|
||||||
|
/// Sets new rate control value as a difference in percents compared
|
||||||
|
/// to the original rate (-50 .. +100 %)
|
||||||
|
void setRateChange(float newRate);
|
||||||
|
|
||||||
|
/// Sets new tempo control value as a difference in percents compared
|
||||||
|
/// to the original tempo (-50 .. +100 %)
|
||||||
|
void setTempoChange(float newTempo);
|
||||||
|
|
||||||
|
/// Sets new pitch control value. Original pitch = 1.0, smaller values
|
||||||
|
/// represent lower pitches, larger values higher pitch.
|
||||||
|
void setPitch(float newPitch);
|
||||||
|
|
||||||
|
/// Sets pitch change in octaves compared to the original pitch
|
||||||
|
/// (-1.00 .. +1.00)
|
||||||
|
void setPitchOctaves(float newPitch);
|
||||||
|
|
||||||
|
/// Sets pitch change in semi-tones compared to the original pitch
|
||||||
|
/// (-12 .. +12)
|
||||||
|
void setPitchSemiTones(int newPitch);
|
||||||
|
void setPitchSemiTones(float newPitch);
|
||||||
|
|
||||||
|
/// Sets the number of channels, 1 = mono, 2 = stereo
|
||||||
|
void setChannels(uint numChannels);
|
||||||
|
|
||||||
|
/// Sets sample rate.
|
||||||
|
void setSampleRate(uint srate);
|
||||||
|
|
||||||
|
/// Flushes the last samples from the processing pipeline to the output.
|
||||||
|
/// Clears also the internal processing buffers.
|
||||||
|
//
|
||||||
|
/// Note: This function is meant for extracting the last samples of a sound
|
||||||
|
/// stream. This function may introduce additional blank samples in the end
|
||||||
|
/// of the sound stream, and thus it's not recommended to call this function
|
||||||
|
/// in the middle of a sound stream.
|
||||||
|
void flush();
|
||||||
|
|
||||||
|
/// Adds 'numSamples' pcs of samples from the 'samples' memory position into
|
||||||
|
/// the input of the object. Notice that sample rate _has_to_ be set before
|
||||||
|
/// calling this function, otherwise throws a runtime_error exception.
|
||||||
|
virtual void putSamples(
|
||||||
|
const SAMPLETYPE *samples, ///< Pointer to sample buffer.
|
||||||
|
uint numSamples ///< Number of samples in buffer. Notice
|
||||||
|
///< that in case of stereo-sound a single sample
|
||||||
|
///< contains data for both channels.
|
||||||
|
);
|
||||||
|
|
||||||
|
/// Clears all the samples in the object's output and internal processing
|
||||||
|
/// buffers.
|
||||||
|
virtual void clear();
|
||||||
|
|
||||||
|
/// Changes a setting controlling the processing system behaviour. See the
|
||||||
|
/// 'SETTING_...' defines for available setting ID's.
|
||||||
|
///
|
||||||
|
/// \return 'TRUE' if the setting was succesfully changed
|
||||||
|
BOOL setSetting(uint settingId, ///< Setting ID number. see SETTING_... defines.
|
||||||
|
uint value ///< New setting value.
|
||||||
|
);
|
||||||
|
|
||||||
|
/// Reads a setting controlling the processing system behaviour. See the
|
||||||
|
/// 'SETTING_...' defines for available setting ID's.
|
||||||
|
///
|
||||||
|
/// \return the setting value.
|
||||||
|
uint getSetting(uint settingId ///< Setting ID number, see SETTING_... defines.
|
||||||
|
) const;
|
||||||
|
|
||||||
|
/// Returns number of samples currently unprocessed.
|
||||||
|
virtual uint numUnprocessedSamples() const;
|
||||||
|
|
||||||
|
|
||||||
|
/// Other handy functions that are implemented in the ancestor classes (see
|
||||||
|
/// classes 'FIFOProcessor' and 'FIFOSamplePipe')
|
||||||
|
///
|
||||||
|
/// - receiveSamples() : Use this function to receive 'ready' processed samples from SoundTouch.
|
||||||
|
/// - numSamples() : Get number of 'ready' samples that can be received with
|
||||||
|
/// function 'receiveSamples()'
|
||||||
|
/// - isEmpty() : Returns nonzero if there aren't any 'ready' samples.
|
||||||
|
/// - clear() : Clears all samples from ready/processing buffers.
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -0,0 +1,940 @@
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
///
|
||||||
|
/// Sampled sound tempo changer/time stretch algorithm. Changes the sound tempo
|
||||||
|
/// while maintaining the original pitch by using a time domain WSOLA-like
|
||||||
|
/// method with several performance-increasing tweaks.
|
||||||
|
///
|
||||||
|
/// Note : MMX optimized functions reside in a separate, platform-specific
|
||||||
|
/// file, e.g. 'mmx_win.cpp' or 'mmx_gcc.cpp'
|
||||||
|
///
|
||||||
|
/// Author : Copyright (c) Olli Parviainen
|
||||||
|
/// Author e-mail : oparviai 'at' iki.fi
|
||||||
|
/// SoundTouch WWW: http://www.surina.net/soundtouch
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Last changed : $Date: 2006/02/05 16:44:06 $
|
||||||
|
// File revision : $Revision: 1.24 $
|
||||||
|
//
|
||||||
|
// $Id: TDStretch.cpp,v 1.24 2006/02/05 16:44:06 Olli Exp $
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// License :
|
||||||
|
//
|
||||||
|
// SoundTouch audio processing library
|
||||||
|
// Copyright (c) Olli Parviainen
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU Lesser General Public
|
||||||
|
// License as published by the Free Software Foundation; either
|
||||||
|
// version 2.1 of the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <memory.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include "STTypes.h"
|
||||||
|
#include "cpu_detect.h"
|
||||||
|
#include "TDStretch.h"
|
||||||
|
|
||||||
|
using namespace soundtouch;
|
||||||
|
|
||||||
|
#ifndef min
|
||||||
|
#define min(a,b) ((a > b) ? b : a)
|
||||||
|
#define max(a,b) ((a < b) ? b : a)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
*
|
||||||
|
* Constant definitions
|
||||||
|
*
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
// Table for the hierarchical mixing position seeking algorithm
|
||||||
|
int scanOffsets[4][24]={
|
||||||
|
{ 124, 186, 248, 310, 372, 434, 496, 558, 620, 682, 744, 806,
|
||||||
|
868, 930, 992, 1054, 1116, 1178, 1240, 1302, 1364, 1426, 1488, 0},
|
||||||
|
{-100, -75, -50, -25, 25, 50, 75, 100, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||||
|
{ -20, -15, -10, -5, 5, 10, 15, 20, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||||
|
{ -4, -3, -2, -1, 1, 2, 3, 4, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
*
|
||||||
|
* Implementation of the class 'TDStretch'
|
||||||
|
*
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
TDStretch::TDStretch() : FIFOProcessor(&outputBuffer)
|
||||||
|
{
|
||||||
|
bQuickseek = FALSE;
|
||||||
|
channels = 2;
|
||||||
|
bMidBufferDirty = FALSE;
|
||||||
|
|
||||||
|
pMidBuffer = NULL;
|
||||||
|
pRefMidBufferUnaligned = NULL;
|
||||||
|
overlapLength = 0;
|
||||||
|
|
||||||
|
setParameters(48000, DEFAULT_SEQUENCE_MS, DEFAULT_SEEKWINDOW_MS, DEFAULT_OVERLAP_MS);
|
||||||
|
|
||||||
|
setTempo(1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
TDStretch::~TDStretch()
|
||||||
|
{
|
||||||
|
delete[] pMidBuffer;
|
||||||
|
delete[] pRefMidBufferUnaligned;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Calculates the x having the closest 2^x value for the given value
|
||||||
|
static int _getClosest2Power(double value)
|
||||||
|
{
|
||||||
|
return (int)(log(value) / log(2.0) + 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Sets routine control parameters. These control are certain time constants
|
||||||
|
// defining how the sound is stretched to the desired duration.
|
||||||
|
//
|
||||||
|
// 'sampleRate' = sample rate of the sound
|
||||||
|
// 'sequenceMS' = one processing sequence length in milliseconds (default = 82 ms)
|
||||||
|
// 'seekwindowMS' = seeking window length for scanning the best overlapping
|
||||||
|
// position (default = 28 ms)
|
||||||
|
// 'overlapMS' = overlapping length (default = 12 ms)
|
||||||
|
|
||||||
|
void TDStretch::setParameters(uint aSampleRate, uint aSequenceMS,
|
||||||
|
uint aSeekWindowMS, uint aOverlapMS)
|
||||||
|
{
|
||||||
|
this->sampleRate = aSampleRate;
|
||||||
|
this->sequenceMs = aSequenceMS;
|
||||||
|
this->seekWindowMs = aSeekWindowMS;
|
||||||
|
this->overlapMs = aOverlapMS;
|
||||||
|
|
||||||
|
seekLength = (sampleRate * seekWindowMs) / 1000;
|
||||||
|
seekWindowLength = (sampleRate * sequenceMs) / 1000;
|
||||||
|
|
||||||
|
maxOffset = seekLength;
|
||||||
|
|
||||||
|
calculateOverlapLength(overlapMs);
|
||||||
|
|
||||||
|
// set tempo to recalculate 'sampleReq'
|
||||||
|
setTempo(tempo);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// Get routine control parameters, see setParameters() function.
|
||||||
|
/// Any of the parameters to this function can be NULL, in such case corresponding parameter
|
||||||
|
/// value isn't returned.
|
||||||
|
void TDStretch::getParameters(uint *pSampleRate, uint *pSequenceMs, uint *pSeekWindowMs, uint *pOverlapMs)
|
||||||
|
{
|
||||||
|
if (pSampleRate)
|
||||||
|
{
|
||||||
|
*pSampleRate = sampleRate;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pSequenceMs)
|
||||||
|
{
|
||||||
|
*pSequenceMs = sequenceMs;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pSeekWindowMs)
|
||||||
|
{
|
||||||
|
*pSeekWindowMs = seekWindowMs;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pOverlapMs)
|
||||||
|
{
|
||||||
|
*pOverlapMs = overlapMs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Overlaps samples in 'midBuffer' with the samples in 'input'
|
||||||
|
void TDStretch::overlapMono(SAMPLETYPE *output, const SAMPLETYPE *input) const
|
||||||
|
{
|
||||||
|
int i, itemp;
|
||||||
|
|
||||||
|
for (i = 0; i < (int)overlapLength ; i ++)
|
||||||
|
{
|
||||||
|
itemp = overlapLength - i;
|
||||||
|
output[i] = (input[i] * i + pMidBuffer[i] * itemp ) / overlapLength; // >> overlapDividerBits;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void TDStretch::clearMidBuffer()
|
||||||
|
{
|
||||||
|
if (bMidBufferDirty)
|
||||||
|
{
|
||||||
|
memset(pMidBuffer, 0, 2 * sizeof(SAMPLETYPE) * overlapLength);
|
||||||
|
bMidBufferDirty = FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TDStretch::clearInput()
|
||||||
|
{
|
||||||
|
inputBuffer.clear();
|
||||||
|
clearMidBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Clears the sample buffers
|
||||||
|
void TDStretch::clear()
|
||||||
|
{
|
||||||
|
outputBuffer.clear();
|
||||||
|
inputBuffer.clear();
|
||||||
|
clearMidBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Enables/disables the quick position seeking algorithm. Zero to disable, nonzero
|
||||||
|
// to enable
|
||||||
|
void TDStretch::enableQuickSeek(BOOL enable)
|
||||||
|
{
|
||||||
|
bQuickseek = enable;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Returns nonzero if the quick seeking algorithm is enabled.
|
||||||
|
BOOL TDStretch::isQuickSeekEnabled() const
|
||||||
|
{
|
||||||
|
return bQuickseek;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Seeks for the optimal overlap-mixing position.
|
||||||
|
uint TDStretch::seekBestOverlapPosition(const SAMPLETYPE *refPos)
|
||||||
|
{
|
||||||
|
if (channels == 2)
|
||||||
|
{
|
||||||
|
// stereo sound
|
||||||
|
if (bQuickseek)
|
||||||
|
{
|
||||||
|
return seekBestOverlapPositionStereoQuick(refPos);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return seekBestOverlapPositionStereo(refPos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// mono sound
|
||||||
|
if (bQuickseek)
|
||||||
|
{
|
||||||
|
return seekBestOverlapPositionMonoQuick(refPos);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return seekBestOverlapPositionMono(refPos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Overlaps samples in 'midBuffer' with the samples in 'inputBuffer' at position
|
||||||
|
// of 'ovlPos'.
|
||||||
|
inline void TDStretch::overlap(SAMPLETYPE *output, const SAMPLETYPE *input, uint ovlPos) const
|
||||||
|
{
|
||||||
|
if (channels == 2)
|
||||||
|
{
|
||||||
|
// stereo sound
|
||||||
|
overlapStereo(output, input + 2 * ovlPos);
|
||||||
|
} else {
|
||||||
|
// mono sound.
|
||||||
|
overlapMono(output, input + ovlPos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Seeks for the optimal overlap-mixing position. The 'stereo' version of the
|
||||||
|
// routine
|
||||||
|
//
|
||||||
|
// The best position is determined as the position where the two overlapped
|
||||||
|
// sample sequences are 'most alike', in terms of the highest cross-correlation
|
||||||
|
// value over the overlapping period
|
||||||
|
uint TDStretch::seekBestOverlapPositionStereo(const SAMPLETYPE *refPos)
|
||||||
|
{
|
||||||
|
uint bestOffs;
|
||||||
|
LONG_SAMPLETYPE bestCorr, corr;
|
||||||
|
uint i;
|
||||||
|
|
||||||
|
// Slopes the amplitudes of the 'midBuffer' samples
|
||||||
|
precalcCorrReferenceStereo();
|
||||||
|
|
||||||
|
bestCorr = INT_MIN;
|
||||||
|
bestOffs = 0;
|
||||||
|
|
||||||
|
// Scans for the best correlation value by testing each possible position
|
||||||
|
// over the permitted range.
|
||||||
|
for (i = 0; i < seekLength; i ++)
|
||||||
|
{
|
||||||
|
// Calculates correlation value for the mixing position corresponding
|
||||||
|
// to 'i'
|
||||||
|
corr = calcCrossCorrStereo(refPos + 2 * i, pRefMidBuffer);
|
||||||
|
|
||||||
|
// Checks for the highest correlation value
|
||||||
|
if (corr > bestCorr)
|
||||||
|
{
|
||||||
|
bestCorr = corr;
|
||||||
|
bestOffs = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// clear cross correlation routine state if necessary (is so e.g. in MMX routines).
|
||||||
|
clearCrossCorrState();
|
||||||
|
|
||||||
|
return bestOffs;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Seeks for the optimal overlap-mixing position. The 'stereo' version of the
|
||||||
|
// routine
|
||||||
|
//
|
||||||
|
// The best position is determined as the position where the two overlapped
|
||||||
|
// sample sequences are 'most alike', in terms of the highest cross-correlation
|
||||||
|
// value over the overlapping period
|
||||||
|
uint TDStretch::seekBestOverlapPositionStereoQuick(const SAMPLETYPE *refPos)
|
||||||
|
{
|
||||||
|
uint j;
|
||||||
|
uint bestOffs;
|
||||||
|
LONG_SAMPLETYPE bestCorr, corr;
|
||||||
|
uint scanCount, corrOffset, tempOffset;
|
||||||
|
|
||||||
|
// Slopes the amplitude of the 'midBuffer' samples
|
||||||
|
precalcCorrReferenceStereo();
|
||||||
|
|
||||||
|
bestCorr = INT_MIN;
|
||||||
|
bestOffs = 0;
|
||||||
|
corrOffset = 0;
|
||||||
|
tempOffset = 0;
|
||||||
|
|
||||||
|
// Scans for the best correlation value using four-pass hierarchical search.
|
||||||
|
//
|
||||||
|
// The look-up table 'scans' has hierarchical position adjusting steps.
|
||||||
|
// In first pass the routine searhes for the highest correlation with
|
||||||
|
// relatively coarse steps, then rescans the neighbourhood of the highest
|
||||||
|
// correlation with better resolution and so on.
|
||||||
|
for (scanCount = 0;scanCount < 4; scanCount ++)
|
||||||
|
{
|
||||||
|
j = 0;
|
||||||
|
while (scanOffsets[scanCount][j])
|
||||||
|
{
|
||||||
|
tempOffset = corrOffset + scanOffsets[scanCount][j];
|
||||||
|
if (tempOffset >= seekLength) break;
|
||||||
|
|
||||||
|
// Calculates correlation value for the mixing position corresponding
|
||||||
|
// to 'tempOffset'
|
||||||
|
corr = calcCrossCorrStereo(refPos + 2 * tempOffset, pRefMidBuffer);
|
||||||
|
|
||||||
|
// Checks for the highest correlation value
|
||||||
|
if (corr > bestCorr)
|
||||||
|
{
|
||||||
|
bestCorr = corr;
|
||||||
|
bestOffs = tempOffset;
|
||||||
|
}
|
||||||
|
j ++;
|
||||||
|
}
|
||||||
|
corrOffset = bestOffs;
|
||||||
|
}
|
||||||
|
// clear cross correlation routine state if necessary (is so e.g. in MMX routines).
|
||||||
|
clearCrossCorrState();
|
||||||
|
|
||||||
|
return bestOffs;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Seeks for the optimal overlap-mixing position. The 'mono' version of the
|
||||||
|
// routine
|
||||||
|
//
|
||||||
|
// The best position is determined as the position where the two overlapped
|
||||||
|
// sample sequences are 'most alike', in terms of the highest cross-correlation
|
||||||
|
// value over the overlapping period
|
||||||
|
uint TDStretch::seekBestOverlapPositionMono(const SAMPLETYPE *refPos)
|
||||||
|
{
|
||||||
|
uint bestOffs;
|
||||||
|
LONG_SAMPLETYPE bestCorr, corr;
|
||||||
|
uint tempOffset;
|
||||||
|
const SAMPLETYPE *compare;
|
||||||
|
|
||||||
|
// Slopes the amplitude of the 'midBuffer' samples
|
||||||
|
precalcCorrReferenceMono();
|
||||||
|
|
||||||
|
bestCorr = INT_MIN;
|
||||||
|
bestOffs = 0;
|
||||||
|
|
||||||
|
// Scans for the best correlation value by testing each possible position
|
||||||
|
// over the permitted range.
|
||||||
|
for (tempOffset = 0; tempOffset < seekLength; tempOffset ++)
|
||||||
|
{
|
||||||
|
compare = refPos + tempOffset;
|
||||||
|
|
||||||
|
// Calculates correlation value for the mixing position corresponding
|
||||||
|
// to 'tempOffset'
|
||||||
|
corr = calcCrossCorrMono(pRefMidBuffer, compare);
|
||||||
|
|
||||||
|
// Checks for the highest correlation value
|
||||||
|
if (corr > bestCorr)
|
||||||
|
{
|
||||||
|
bestCorr = corr;
|
||||||
|
bestOffs = tempOffset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// clear cross correlation routine state if necessary (is so e.g. in MMX routines).
|
||||||
|
clearCrossCorrState();
|
||||||
|
|
||||||
|
return bestOffs;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Seeks for the optimal overlap-mixing position. The 'mono' version of the
|
||||||
|
// routine
|
||||||
|
//
|
||||||
|
// The best position is determined as the position where the two overlapped
|
||||||
|
// sample sequences are 'most alike', in terms of the highest cross-correlation
|
||||||
|
// value over the overlapping period
|
||||||
|
uint TDStretch::seekBestOverlapPositionMonoQuick(const SAMPLETYPE *refPos)
|
||||||
|
{
|
||||||
|
uint j;
|
||||||
|
uint bestOffs;
|
||||||
|
LONG_SAMPLETYPE bestCorr, corr;
|
||||||
|
uint scanCount, corrOffset, tempOffset;
|
||||||
|
|
||||||
|
// Slopes the amplitude of the 'midBuffer' samples
|
||||||
|
precalcCorrReferenceMono();
|
||||||
|
|
||||||
|
bestCorr = INT_MIN;
|
||||||
|
bestOffs = 0;
|
||||||
|
corrOffset = 0;
|
||||||
|
tempOffset = 0;
|
||||||
|
|
||||||
|
// Scans for the best correlation value using four-pass hierarchical search.
|
||||||
|
//
|
||||||
|
// The look-up table 'scans' has hierarchical position adjusting steps.
|
||||||
|
// In first pass the routine searhes for the highest correlation with
|
||||||
|
// relatively coarse steps, then rescans the neighbourhood of the highest
|
||||||
|
// correlation with better resolution and so on.
|
||||||
|
for (scanCount = 0;scanCount < 4; scanCount ++)
|
||||||
|
{
|
||||||
|
j = 0;
|
||||||
|
while (scanOffsets[scanCount][j])
|
||||||
|
{
|
||||||
|
tempOffset = corrOffset + scanOffsets[scanCount][j];
|
||||||
|
if (tempOffset >= seekLength) break;
|
||||||
|
|
||||||
|
// Calculates correlation value for the mixing position corresponding
|
||||||
|
// to 'tempOffset'
|
||||||
|
corr = calcCrossCorrMono(refPos + tempOffset, pRefMidBuffer);
|
||||||
|
|
||||||
|
// Checks for the highest correlation value
|
||||||
|
if (corr > bestCorr)
|
||||||
|
{
|
||||||
|
bestCorr = corr;
|
||||||
|
bestOffs = tempOffset;
|
||||||
|
}
|
||||||
|
j ++;
|
||||||
|
}
|
||||||
|
corrOffset = bestOffs;
|
||||||
|
}
|
||||||
|
// clear cross correlation routine state if necessary (is so e.g. in MMX routines).
|
||||||
|
clearCrossCorrState();
|
||||||
|
|
||||||
|
return bestOffs;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// clear cross correlation routine state if necessary
|
||||||
|
void TDStretch::clearCrossCorrState()
|
||||||
|
{
|
||||||
|
// default implementation is empty.
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Sets new target tempo. Normal tempo = 'SCALE', smaller values represent slower
|
||||||
|
// tempo, larger faster tempo.
|
||||||
|
void TDStretch::setTempo(float newTempo)
|
||||||
|
{
|
||||||
|
uint intskip;
|
||||||
|
|
||||||
|
tempo = newTempo;
|
||||||
|
|
||||||
|
// Calculate ideal skip length (according to tempo value)
|
||||||
|
nominalSkip = tempo * (seekWindowLength - overlapLength);
|
||||||
|
skipFract = 0;
|
||||||
|
intskip = (int)(nominalSkip + 0.5f);
|
||||||
|
|
||||||
|
// Calculate how many samples are needed in the 'inputBuffer' to
|
||||||
|
// process another batch of samples
|
||||||
|
sampleReq = max(intskip + overlapLength, seekWindowLength) + maxOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Sets the number of channels, 1 = mono, 2 = stereo
|
||||||
|
void TDStretch::setChannels(uint numChannels)
|
||||||
|
{
|
||||||
|
if (channels == numChannels) return;
|
||||||
|
assert(numChannels == 1 || numChannels == 2);
|
||||||
|
|
||||||
|
channels = numChannels;
|
||||||
|
inputBuffer.setChannels(channels);
|
||||||
|
outputBuffer.setChannels(channels);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// nominal tempo, no need for processing, just pass the samples through
|
||||||
|
// to outputBuffer
|
||||||
|
void TDStretch::processNominalTempo()
|
||||||
|
{
|
||||||
|
assert(tempo == 1.0f);
|
||||||
|
|
||||||
|
if (bMidBufferDirty)
|
||||||
|
{
|
||||||
|
// If there are samples in pMidBuffer waiting for overlapping,
|
||||||
|
// do a single sliding overlapping with them in order to prevent a
|
||||||
|
// clicking distortion in the output sound
|
||||||
|
if (inputBuffer.numSamples() < overlapLength)
|
||||||
|
{
|
||||||
|
// wait until we've got overlapLength input samples
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Mix the samples in the beginning of 'inputBuffer' with the
|
||||||
|
// samples in 'midBuffer' using sliding overlapping
|
||||||
|
overlap(outputBuffer.ptrEnd(overlapLength), inputBuffer.ptrBegin(), 0);
|
||||||
|
outputBuffer.putSamples(overlapLength);
|
||||||
|
inputBuffer.receiveSamples(overlapLength);
|
||||||
|
clearMidBuffer();
|
||||||
|
// now we've caught the nominal sample flow and may switch to
|
||||||
|
// bypass mode
|
||||||
|
}
|
||||||
|
|
||||||
|
// Simply bypass samples from input to output
|
||||||
|
outputBuffer.moveSamples(inputBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Processes as many processing frames of the samples 'inputBuffer', store
|
||||||
|
// the result into 'outputBuffer'
|
||||||
|
void TDStretch::processSamples()
|
||||||
|
{
|
||||||
|
uint ovlSkip, offset;
|
||||||
|
int temp;
|
||||||
|
|
||||||
|
/* Removed this small optimization - can introduce a click to sound when tempo setting
|
||||||
|
crosses the nominal value
|
||||||
|
if (tempo == 1.0f)
|
||||||
|
{
|
||||||
|
// tempo not changed from the original, so bypass the processing
|
||||||
|
processNominalTempo();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (bMidBufferDirty == FALSE)
|
||||||
|
{
|
||||||
|
// if midBuffer is empty, move the first samples of the input stream
|
||||||
|
// into it
|
||||||
|
if (inputBuffer.numSamples() < overlapLength)
|
||||||
|
{
|
||||||
|
// wait until we've got overlapLength samples
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
memcpy(pMidBuffer, inputBuffer.ptrBegin(), channels * overlapLength * sizeof(SAMPLETYPE));
|
||||||
|
inputBuffer.receiveSamples(overlapLength);
|
||||||
|
bMidBufferDirty = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process samples as long as there are enough samples in 'inputBuffer'
|
||||||
|
// to form a processing frame.
|
||||||
|
while (inputBuffer.numSamples() >= sampleReq)
|
||||||
|
{
|
||||||
|
// If tempo differs from the normal ('SCALE'), scan for the best overlapping
|
||||||
|
// position
|
||||||
|
offset = seekBestOverlapPosition(inputBuffer.ptrBegin());
|
||||||
|
|
||||||
|
// Mix the samples in the 'inputBuffer' at position of 'offset' with the
|
||||||
|
// samples in 'midBuffer' using sliding overlapping
|
||||||
|
// ... first partially overlap with the end of the previous sequence
|
||||||
|
// (that's in 'midBuffer')
|
||||||
|
overlap(outputBuffer.ptrEnd(overlapLength), inputBuffer.ptrBegin(), offset);
|
||||||
|
outputBuffer.putSamples(overlapLength);
|
||||||
|
|
||||||
|
// ... then copy sequence samples from 'inputBuffer' to output
|
||||||
|
temp = (seekWindowLength - 2 * overlapLength);// & 0xfffffffe;
|
||||||
|
if (temp > 0)
|
||||||
|
{
|
||||||
|
outputBuffer.putSamples(inputBuffer.ptrBegin() + channels * (offset + overlapLength), temp);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copies the end of the current sequence from 'inputBuffer' to
|
||||||
|
// 'midBuffer' for being mixed with the beginning of the next
|
||||||
|
// processing sequence and so on
|
||||||
|
assert(offset + seekWindowLength <= inputBuffer.numSamples());
|
||||||
|
memcpy(pMidBuffer, inputBuffer.ptrBegin() + channels * (offset + seekWindowLength - overlapLength),
|
||||||
|
channels * sizeof(SAMPLETYPE) * overlapLength);
|
||||||
|
bMidBufferDirty = TRUE;
|
||||||
|
|
||||||
|
// Remove the processed samples from the input buffer. Update
|
||||||
|
// the difference between integer & nominal skip step to 'skipFract'
|
||||||
|
// in order to prevent the error from accumulating over time.
|
||||||
|
skipFract += nominalSkip; // real skip size
|
||||||
|
ovlSkip = (int)skipFract; // rounded to integer skip
|
||||||
|
skipFract -= ovlSkip; // maintain the fraction part, i.e. real vs. integer skip
|
||||||
|
inputBuffer.receiveSamples(ovlSkip);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Adds 'numsamples' pcs of samples from the 'samples' memory position into
|
||||||
|
// the input of the object.
|
||||||
|
void TDStretch::putSamples(const SAMPLETYPE *samples, uint numSamples)
|
||||||
|
{
|
||||||
|
// Add the samples into the input buffer
|
||||||
|
inputBuffer.putSamples(samples, numSamples);
|
||||||
|
// Process the samples in input buffer
|
||||||
|
processSamples();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// Set new overlap length parameter & reallocate RefMidBuffer if necessary.
|
||||||
|
void TDStretch::acceptNewOverlapLength(uint newOverlapLength)
|
||||||
|
{
|
||||||
|
uint prevOvl;
|
||||||
|
|
||||||
|
prevOvl = overlapLength;
|
||||||
|
overlapLength = newOverlapLength;
|
||||||
|
|
||||||
|
if (overlapLength > prevOvl)
|
||||||
|
{
|
||||||
|
delete[] pMidBuffer;
|
||||||
|
delete[] pRefMidBufferUnaligned;
|
||||||
|
|
||||||
|
pMidBuffer = new SAMPLETYPE[overlapLength * 2];
|
||||||
|
bMidBufferDirty = TRUE;
|
||||||
|
clearMidBuffer();
|
||||||
|
|
||||||
|
pRefMidBufferUnaligned = new SAMPLETYPE[2 * overlapLength + 16 / sizeof(SAMPLETYPE)];
|
||||||
|
// ensure that 'pRefMidBuffer' is aligned to 16 byte boundary for efficiency
|
||||||
|
pRefMidBuffer = (SAMPLETYPE *)((((ulongptr)pRefMidBufferUnaligned) + 15) & -16);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Operator 'new' is overloaded so that it automatically creates a suitable instance
|
||||||
|
// depending on if we've a MMX/SSE/etc-capable CPU available or not.
|
||||||
|
void * TDStretch::operator new(size_t s)
|
||||||
|
{
|
||||||
|
// Notice! don't use "new TDStretch" directly, use "newInstance" to create a new instance instead!
|
||||||
|
assert(FALSE);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TDStretch * TDStretch::newInstance()
|
||||||
|
{
|
||||||
|
uint uExtensions = 0;
|
||||||
|
|
||||||
|
#if !defined(_MSC_VER) || !defined(__x86_64__)
|
||||||
|
uExtensions = detectCPUextensions();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Check if MMX/SSE/3DNow! instruction set extensions supported by CPU
|
||||||
|
|
||||||
|
#ifdef ALLOW_MMX
|
||||||
|
// MMX routines available only with integer sample types
|
||||||
|
if (uExtensions & SUPPORT_MMX)
|
||||||
|
{
|
||||||
|
return ::new TDStretchMMX;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif // ALLOW_MMX
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef ALLOW_SSE
|
||||||
|
if (uExtensions & SUPPORT_SSE)
|
||||||
|
{
|
||||||
|
// SSE support
|
||||||
|
return ::new TDStretchSSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif // ALLOW_SSE
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef ALLOW_3DNOW
|
||||||
|
if (uExtensions & SUPPORT_3DNOW)
|
||||||
|
{
|
||||||
|
// 3DNow! support
|
||||||
|
return ::new TDStretch3DNow;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif // ALLOW_3DNOW
|
||||||
|
|
||||||
|
{
|
||||||
|
// ISA optimizations not supported, use plain C version
|
||||||
|
return ::new TDStretch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Integer arithmetics specific algorithm implementations.
|
||||||
|
//
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifdef INTEGER_SAMPLES
|
||||||
|
|
||||||
|
// Slopes the amplitude of the 'midBuffer' samples so that cross correlation
|
||||||
|
// is faster to calculate
|
||||||
|
void TDStretch::precalcCorrReferenceStereo()
|
||||||
|
{
|
||||||
|
int i, cnt2;
|
||||||
|
int temp, temp2;
|
||||||
|
|
||||||
|
for (i=0 ; i < (int)overlapLength ;i ++)
|
||||||
|
{
|
||||||
|
temp = i * (overlapLength - i);
|
||||||
|
cnt2 = i * 2;
|
||||||
|
|
||||||
|
temp2 = (pMidBuffer[cnt2] * temp) / slopingDivider;
|
||||||
|
pRefMidBuffer[cnt2] = (short)(temp2);
|
||||||
|
temp2 = (pMidBuffer[cnt2 + 1] * temp) / slopingDivider;
|
||||||
|
pRefMidBuffer[cnt2 + 1] = (short)(temp2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Slopes the amplitude of the 'midBuffer' samples so that cross correlation
|
||||||
|
// is faster to calculate
|
||||||
|
void TDStretch::precalcCorrReferenceMono()
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
long temp;
|
||||||
|
long temp2;
|
||||||
|
|
||||||
|
for (i=0 ; i < (int)overlapLength ;i ++)
|
||||||
|
{
|
||||||
|
temp = i * (overlapLength - i);
|
||||||
|
temp2 = (pMidBuffer[i] * temp) / slopingDivider;
|
||||||
|
pRefMidBuffer[i] = (short)temp2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Overlaps samples in 'midBuffer' with the samples in 'input'. The 'Stereo'
|
||||||
|
// version of the routine.
|
||||||
|
void TDStretch::overlapStereo(short *output, const short *input) const
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
short temp;
|
||||||
|
uint cnt2;
|
||||||
|
|
||||||
|
for (i = 0; i < (int)overlapLength ; i ++)
|
||||||
|
{
|
||||||
|
temp = (short)(overlapLength - i);
|
||||||
|
cnt2 = 2 * i;
|
||||||
|
output[cnt2] = (input[cnt2] * i + pMidBuffer[cnt2] * temp ) / overlapLength;
|
||||||
|
output[cnt2 + 1] = (input[cnt2 + 1] * i + pMidBuffer[cnt2 + 1] * temp ) / overlapLength;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Calculates overlap period length in samples.
|
||||||
|
/// Integer version rounds overlap length to closest power of 2
|
||||||
|
/// for a divide scaling operation.
|
||||||
|
void TDStretch::calculateOverlapLength(uint overlapMs)
|
||||||
|
{
|
||||||
|
uint newOvl;
|
||||||
|
|
||||||
|
overlapDividerBits = _getClosest2Power((sampleRate * overlapMs) / 1000.0);
|
||||||
|
if (overlapDividerBits > 9) overlapDividerBits = 9;
|
||||||
|
if (overlapDividerBits < 4) overlapDividerBits = 4;
|
||||||
|
newOvl = 1<<overlapDividerBits;
|
||||||
|
|
||||||
|
acceptNewOverlapLength(newOvl);
|
||||||
|
|
||||||
|
// calculate sloping divider so that crosscorrelation operation won't
|
||||||
|
// overflow 32-bit register. Max. sum of the crosscorrelation sum without
|
||||||
|
// divider would be 2^30*(N^3-N)/3, where N = overlap length
|
||||||
|
slopingDivider = (newOvl * newOvl - 1) / 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
long TDStretch::calcCrossCorrMono(const short *mixingPos, const short *compare) const
|
||||||
|
{
|
||||||
|
long corr;
|
||||||
|
uint i;
|
||||||
|
|
||||||
|
corr = 0;
|
||||||
|
for (i = 1; i < overlapLength; i ++)
|
||||||
|
{
|
||||||
|
corr += (mixingPos[i] * compare[i]) >> overlapDividerBits;
|
||||||
|
}
|
||||||
|
|
||||||
|
return corr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
long TDStretch::calcCrossCorrStereo(const short *mixingPos, const short *compare) const
|
||||||
|
{
|
||||||
|
long corr;
|
||||||
|
uint i;
|
||||||
|
|
||||||
|
corr = 0;
|
||||||
|
for (i = 2; i < 2 * overlapLength; i += 2)
|
||||||
|
{
|
||||||
|
corr += (mixingPos[i] * compare[i] +
|
||||||
|
mixingPos[i + 1] * compare[i + 1]) >> overlapDividerBits;
|
||||||
|
}
|
||||||
|
|
||||||
|
return corr;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // INTEGER_SAMPLES
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Floating point arithmetics specific algorithm implementations.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifdef FLOAT_SAMPLES
|
||||||
|
|
||||||
|
|
||||||
|
// Slopes the amplitude of the 'midBuffer' samples so that cross correlation
|
||||||
|
// is faster to calculate
|
||||||
|
void TDStretch::precalcCorrReferenceStereo()
|
||||||
|
{
|
||||||
|
int i, cnt2;
|
||||||
|
float temp;
|
||||||
|
|
||||||
|
for (i=0 ; i < (int)overlapLength ;i ++)
|
||||||
|
{
|
||||||
|
temp = (float)i * (float)(overlapLength - i);
|
||||||
|
cnt2 = i * 2;
|
||||||
|
pRefMidBuffer[cnt2] = (float)(pMidBuffer[cnt2] * temp);
|
||||||
|
pRefMidBuffer[cnt2 + 1] = (float)(pMidBuffer[cnt2 + 1] * temp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Slopes the amplitude of the 'midBuffer' samples so that cross correlation
|
||||||
|
// is faster to calculate
|
||||||
|
void TDStretch::precalcCorrReferenceMono()
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
float temp;
|
||||||
|
|
||||||
|
for (i=0 ; i < (int)overlapLength ;i ++)
|
||||||
|
{
|
||||||
|
temp = (float)i * (float)(overlapLength - i);
|
||||||
|
pRefMidBuffer[i] = (float)(pMidBuffer[i] * temp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// SSE-optimized version of the function overlapStereo
|
||||||
|
void TDStretch::overlapStereo(float *output, const float *input) const
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
uint cnt2;
|
||||||
|
float fTemp;
|
||||||
|
float fScale;
|
||||||
|
float fi;
|
||||||
|
|
||||||
|
fScale = 1.0f / (float)overlapLength;
|
||||||
|
|
||||||
|
for (i = 0; i < (int)overlapLength ; i ++)
|
||||||
|
{
|
||||||
|
fTemp = (float)(overlapLength - i) * fScale;
|
||||||
|
fi = (float)i * fScale;
|
||||||
|
cnt2 = 2 * i;
|
||||||
|
output[cnt2 + 0] = input[cnt2 + 0] * fi + pMidBuffer[cnt2 + 0] * fTemp;
|
||||||
|
output[cnt2 + 1] = input[cnt2 + 1] * fi + pMidBuffer[cnt2 + 1] * fTemp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Calculates overlap period length in samples.
|
||||||
|
void TDStretch::calculateOverlapLength(uint overlapMs)
|
||||||
|
{
|
||||||
|
uint newOvl;
|
||||||
|
|
||||||
|
newOvl = (sampleRate * overlapMs) / 1000;
|
||||||
|
if (newOvl < 16) newOvl = 16;
|
||||||
|
|
||||||
|
// must be divisible by 8
|
||||||
|
newOvl -= newOvl % 8;
|
||||||
|
|
||||||
|
acceptNewOverlapLength(newOvl);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
double TDStretch::calcCrossCorrMono(const float *mixingPos, const float *compare) const
|
||||||
|
{
|
||||||
|
double corr;
|
||||||
|
uint i;
|
||||||
|
|
||||||
|
corr = 0;
|
||||||
|
for (i = 1; i < overlapLength; i ++)
|
||||||
|
{
|
||||||
|
corr += mixingPos[i] * compare[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return corr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
double TDStretch::calcCrossCorrStereo(const float *mixingPos, const float *compare) const
|
||||||
|
{
|
||||||
|
double corr;
|
||||||
|
uint i;
|
||||||
|
|
||||||
|
corr = 0;
|
||||||
|
for (i = 2; i < 2 * overlapLength; i += 2)
|
||||||
|
{
|
||||||
|
corr += mixingPos[i] * compare[i] +
|
||||||
|
mixingPos[i + 1] * compare[i + 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
return corr;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // FLOAT_SAMPLES
|
|
@ -0,0 +1,236 @@
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
///
|
||||||
|
/// Sampled sound tempo changer/time stretch algorithm. Changes the sound tempo
|
||||||
|
/// while maintaining the original pitch by using a time domain WSOLA-like method
|
||||||
|
/// with several performance-increasing tweaks.
|
||||||
|
///
|
||||||
|
/// Note : MMX optimized functions reside in a separate, platform-specific file,
|
||||||
|
/// e.g. 'mmx_win.cpp' or 'mmx_gcc.cpp'
|
||||||
|
///
|
||||||
|
/// Author : Copyright (c) Olli Parviainen
|
||||||
|
/// Author e-mail : oparviai 'at' iki.fi
|
||||||
|
/// SoundTouch WWW: http://www.surina.net/soundtouch
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Last changed : $Date: 2006/02/05 16:44:06 $
|
||||||
|
// File revision : $Revision: 1.16 $
|
||||||
|
//
|
||||||
|
// $Id: TDStretch.h,v 1.16 2006/02/05 16:44:06 Olli Exp $
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// License :
|
||||||
|
//
|
||||||
|
// SoundTouch audio processing library
|
||||||
|
// Copyright (c) Olli Parviainen
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU Lesser General Public
|
||||||
|
// License as published by the Free Software Foundation; either
|
||||||
|
// version 2.1 of the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef TDStretch_H
|
||||||
|
#define TDStretch_H
|
||||||
|
|
||||||
|
#include "STTypes.h"
|
||||||
|
#include "RateTransposer.h"
|
||||||
|
#include "FIFOSamplePipe.h"
|
||||||
|
|
||||||
|
namespace soundtouch
|
||||||
|
{
|
||||||
|
|
||||||
|
// Default values for sound processing parameters:
|
||||||
|
|
||||||
|
/// Default length of a single processing sequence, in milliseconds. This determines to how
|
||||||
|
/// long sequences the original sound is chopped in the time-stretch algorithm.
|
||||||
|
///
|
||||||
|
/// The larger this value is, the lesser sequences are used in processing. In principle
|
||||||
|
/// a bigger value sounds better when slowing down tempo, but worse when increasing tempo
|
||||||
|
/// and vice versa.
|
||||||
|
///
|
||||||
|
/// Increasing this value reduces computational burden & vice versa.
|
||||||
|
#define DEFAULT_SEQUENCE_MS 61
|
||||||
|
|
||||||
|
#define DEFAULT_SEEKWINDOW_MS 18
|
||||||
|
|
||||||
|
#define DEFAULT_OVERLAP_MS 7
|
||||||
|
|
||||||
|
|
||||||
|
/// Class that does the time-stretch (tempo change) effect for the processed
|
||||||
|
/// sound.
|
||||||
|
class TDStretch : public FIFOProcessor
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
uint channels;
|
||||||
|
uint sampleReq;
|
||||||
|
float tempo;
|
||||||
|
|
||||||
|
SAMPLETYPE *pMidBuffer;
|
||||||
|
SAMPLETYPE *pRefMidBuffer;
|
||||||
|
SAMPLETYPE *pRefMidBufferUnaligned;
|
||||||
|
uint overlapLength;
|
||||||
|
uint overlapDividerBits;
|
||||||
|
uint slopingDivider;
|
||||||
|
uint seekLength;
|
||||||
|
uint seekWindowLength;
|
||||||
|
uint maxOffset;
|
||||||
|
float nominalSkip;
|
||||||
|
float skipFract;
|
||||||
|
FIFOSampleBuffer outputBuffer;
|
||||||
|
FIFOSampleBuffer inputBuffer;
|
||||||
|
BOOL bQuickseek;
|
||||||
|
BOOL bMidBufferDirty;
|
||||||
|
|
||||||
|
uint sampleRate;
|
||||||
|
uint sequenceMs;
|
||||||
|
uint seekWindowMs;
|
||||||
|
uint overlapMs;
|
||||||
|
|
||||||
|
void acceptNewOverlapLength(uint newOverlapLength);
|
||||||
|
|
||||||
|
virtual void clearCrossCorrState();
|
||||||
|
void calculateOverlapLength(uint overlapMs);
|
||||||
|
|
||||||
|
virtual LONG_SAMPLETYPE calcCrossCorrStereo(const SAMPLETYPE *mixingPos, const SAMPLETYPE *compare) const;
|
||||||
|
virtual LONG_SAMPLETYPE calcCrossCorrMono(const SAMPLETYPE *mixingPos, const SAMPLETYPE *compare) const;
|
||||||
|
|
||||||
|
virtual uint seekBestOverlapPositionStereo(const SAMPLETYPE *refPos);
|
||||||
|
virtual uint seekBestOverlapPositionStereoQuick(const SAMPLETYPE *refPos);
|
||||||
|
virtual uint seekBestOverlapPositionMono(const SAMPLETYPE *refPos);
|
||||||
|
virtual uint seekBestOverlapPositionMonoQuick(const SAMPLETYPE *refPos);
|
||||||
|
uint seekBestOverlapPosition(const SAMPLETYPE *refPos);
|
||||||
|
|
||||||
|
virtual void overlapStereo(SAMPLETYPE *output, const SAMPLETYPE *input) const;
|
||||||
|
virtual void overlapMono(SAMPLETYPE *output, const SAMPLETYPE *input) const;
|
||||||
|
|
||||||
|
void clearMidBuffer();
|
||||||
|
void overlap(SAMPLETYPE *output, const SAMPLETYPE *input, uint ovlPos) const;
|
||||||
|
|
||||||
|
void precalcCorrReferenceMono();
|
||||||
|
void precalcCorrReferenceStereo();
|
||||||
|
|
||||||
|
void processNominalTempo();
|
||||||
|
|
||||||
|
/// Changes the tempo of the given sound samples.
|
||||||
|
/// Returns amount of samples returned in the "output" buffer.
|
||||||
|
/// The maximum amount of samples that can be returned at a time is set by
|
||||||
|
/// the 'set_returnBuffer_size' function.
|
||||||
|
void processSamples();
|
||||||
|
|
||||||
|
public:
|
||||||
|
TDStretch();
|
||||||
|
virtual ~TDStretch();
|
||||||
|
|
||||||
|
/// Operator 'new' is overloaded so that it automatically creates a suitable instance
|
||||||
|
/// depending on if we've a MMX/SSE/etc-capable CPU available or not.
|
||||||
|
void *operator new(size_t s);
|
||||||
|
|
||||||
|
/// Use this function instead of "new" operator to create a new instance of this class.
|
||||||
|
/// This function automatically chooses a correct feature set depending on if the CPU
|
||||||
|
/// supports MMX/SSE/etc extensions.
|
||||||
|
static TDStretch *newInstance();
|
||||||
|
|
||||||
|
/// Returns the output buffer object
|
||||||
|
FIFOSamplePipe *getOutput() { return &outputBuffer; };
|
||||||
|
|
||||||
|
/// Returns the input buffer object
|
||||||
|
FIFOSamplePipe *getInput() { return &inputBuffer; };
|
||||||
|
|
||||||
|
/// Sets new target tempo. Normal tempo = 'SCALE', smaller values represent slower
|
||||||
|
/// tempo, larger faster tempo.
|
||||||
|
void setTempo(float newTempo);
|
||||||
|
|
||||||
|
/// Returns nonzero if there aren't any samples available for outputting.
|
||||||
|
virtual void clear();
|
||||||
|
|
||||||
|
/// Clears the input buffer
|
||||||
|
void clearInput();
|
||||||
|
|
||||||
|
/// Sets the number of channels, 1 = mono, 2 = stereo
|
||||||
|
void setChannels(uint numChannels);
|
||||||
|
|
||||||
|
/// Enables/disables the quick position seeking algorithm. Zero to disable,
|
||||||
|
/// nonzero to enable
|
||||||
|
void enableQuickSeek(BOOL enable);
|
||||||
|
|
||||||
|
/// Returns nonzero if the quick seeking algorithm is enabled.
|
||||||
|
BOOL isQuickSeekEnabled() const;
|
||||||
|
|
||||||
|
/// Sets routine control parameters. These control are certain time constants
|
||||||
|
/// defining how the sound is stretched to the desired duration.
|
||||||
|
//
|
||||||
|
/// 'sampleRate' = sample rate of the sound
|
||||||
|
/// 'sequenceMS' = one processing sequence length in milliseconds
|
||||||
|
/// 'seekwindowMS' = seeking window length for scanning the best overlapping
|
||||||
|
/// position
|
||||||
|
/// 'overlapMS' = overlapping length
|
||||||
|
void setParameters(uint sampleRate, ///< Samplerate of sound being processed (Hz)
|
||||||
|
uint sequenceMS = DEFAULT_SEQUENCE_MS, ///< Single processing sequence length (ms)
|
||||||
|
uint seekwindowMS = DEFAULT_SEEKWINDOW_MS, ///< Offset seeking window length (ms)
|
||||||
|
uint overlapMS = DEFAULT_OVERLAP_MS ///< Sequence overlapping length (ms)
|
||||||
|
);
|
||||||
|
|
||||||
|
/// Get routine control parameters, see setParameters() function.
|
||||||
|
/// Any of the parameters to this function can be NULL, in such case corresponding parameter
|
||||||
|
/// value isn't returned.
|
||||||
|
void getParameters(uint *pSampleRate, uint *pSequenceMs, uint *pSeekWindowMs, uint *pOverlapMs);
|
||||||
|
|
||||||
|
/// Adds 'numsamples' pcs of samples from the 'samples' memory position into
|
||||||
|
/// the input of the object.
|
||||||
|
virtual void putSamples(
|
||||||
|
const SAMPLETYPE *samples, ///< Input sample data
|
||||||
|
uint numSamples ///< Number of samples in 'samples' so that one sample
|
||||||
|
///< contains both channels if stereo
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Implementation-specific class declarations:
|
||||||
|
|
||||||
|
//#ifdef ALLOW_MMX
|
||||||
|
// /// Class that implements MMX optimized routines for 16bit integer samples type.
|
||||||
|
// class TDStretchMMX : public TDStretch
|
||||||
|
// {
|
||||||
|
// protected:
|
||||||
|
// long calcCrossCorrStereo(const short *mixingPos, const short *compare) const;
|
||||||
|
// virtual void overlapStereo(short *output, const short *input) const;
|
||||||
|
// virtual void clearCrossCorrState();
|
||||||
|
// };
|
||||||
|
//#endif /// ALLOW_MMX
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//#ifdef ALLOW_3DNOW
|
||||||
|
// /// Class that implements 3DNow! optimized routines for floating point samples type.
|
||||||
|
// class TDStretch3DNow : public TDStretch
|
||||||
|
// {
|
||||||
|
// protected:
|
||||||
|
// double calcCrossCorrStereo(const float *mixingPos, const float *compare) const;
|
||||||
|
// };
|
||||||
|
//#endif /// ALLOW_3DNOW
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef ALLOW_SSE
|
||||||
|
/// Class that implements SSE optimized routines for floating point samples type.
|
||||||
|
class TDStretchSSE : public TDStretch
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
double calcCrossCorrStereo(const float *mixingPos, const float *compare) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /// ALLOW_SSE
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif /// TDStretch_H
|
|
@ -0,0 +1,714 @@
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
///
|
||||||
|
/// Classes for easy reading & writing of WAV sound files.
|
||||||
|
///
|
||||||
|
/// For big-endian CPU, define _BIG_ENDIAN_ during compile-time to correctly
|
||||||
|
/// parse the WAV files with such processors.
|
||||||
|
///
|
||||||
|
/// Admittingly, more complete WAV reader routines may exist in public domain,
|
||||||
|
/// but the reason for 'yet another' one is that those generic WAV reader
|
||||||
|
/// libraries are exhaustingly large and cumbersome! Wanted to have something
|
||||||
|
/// simpler here, i.e. something that's not already larger than rest of the
|
||||||
|
/// SoundTouch/SoundStretch program...
|
||||||
|
///
|
||||||
|
/// Author : Copyright (c) Olli Parviainen
|
||||||
|
/// Author e-mail : oparviai 'at' iki.fi
|
||||||
|
/// SoundTouch WWW: http://www.surina.net/soundtouch
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Last changed : $Date: 2006/02/05 16:44:06 $
|
||||||
|
// File revision : $Revision: 1.15 $
|
||||||
|
//
|
||||||
|
// $Id: WavFile.cpp,v 1.15 2006/02/05 16:44:06 Olli Exp $
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// License :
|
||||||
|
//
|
||||||
|
// SoundTouch audio processing library
|
||||||
|
// Copyright (c) Olli Parviainen
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU Lesser General Public
|
||||||
|
// License as published by the Free Software Foundation; either
|
||||||
|
// version 2.1 of the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <string>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
#include "WavFile.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
const static char riffStr[] = "RIFF";
|
||||||
|
const static char waveStr[] = "WAVE";
|
||||||
|
const static char fmtStr[] = "fmt ";
|
||||||
|
const static char dataStr[] = "data";
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Helper functions for swapping byte order to correctly read/write WAV files
|
||||||
|
// with big-endian CPU's: Define compile-time definition _BIG_ENDIAN_ to
|
||||||
|
// turn-on the conversion if it appears necessary.
|
||||||
|
//
|
||||||
|
// For example, Intel x86 is little-endian and doesn't require conversion,
|
||||||
|
// while PowerPC of Mac's and many other RISC cpu's are big-endian.
|
||||||
|
|
||||||
|
#ifdef BYTE_ORDER
|
||||||
|
// In gcc compiler detect the byte order automatically
|
||||||
|
#if BYTE_ORDER == BIG_ENDIAN
|
||||||
|
// big-endian platform.
|
||||||
|
#define _BIG_ENDIAN_
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _BIG_ENDIAN_
|
||||||
|
// big-endian CPU, swap bytes in 16 & 32 bit words
|
||||||
|
|
||||||
|
// helper-function to swap byte-order of 32bit integer
|
||||||
|
static inline void _swap32(unsigned int &dwData)
|
||||||
|
{
|
||||||
|
dwData = ((dwData >> 24) & 0x000000FF) |
|
||||||
|
((dwData >> 8) & 0x0000FF00) |
|
||||||
|
((dwData << 8) & 0x00FF0000) |
|
||||||
|
((dwData << 24) & 0xFF000000);
|
||||||
|
}
|
||||||
|
|
||||||
|
// helper-function to swap byte-order of 16bit integer
|
||||||
|
static inline void _swap16(unsigned short &wData)
|
||||||
|
{
|
||||||
|
wData = ((wData >> 8) & 0x00FF) |
|
||||||
|
((wData << 8) & 0xFF00);
|
||||||
|
}
|
||||||
|
|
||||||
|
// helper-function to swap byte-order of buffer of 16bit integers
|
||||||
|
static inline void _swap16Buffer(unsigned short *pData, unsigned int dwNumWords)
|
||||||
|
{
|
||||||
|
unsigned long i;
|
||||||
|
|
||||||
|
for (i = 0; i < dwNumWords; i ++)
|
||||||
|
{
|
||||||
|
_swap16(pData[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#else // BIG_ENDIAN
|
||||||
|
// little-endian CPU, WAV file is ok as such
|
||||||
|
|
||||||
|
// dummy helper-function
|
||||||
|
static inline void _swap32(unsigned int &dwData)
|
||||||
|
{
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
// dummy helper-function
|
||||||
|
static inline void _swap16(unsigned short &wData)
|
||||||
|
{
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
// dummy helper-function
|
||||||
|
static inline void _swap16Buffer(unsigned short *pData, unsigned int dwNumBytes)
|
||||||
|
{
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // BIG_ENDIAN
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Class WavInFile
|
||||||
|
//
|
||||||
|
|
||||||
|
WavInFile::WavInFile(const char *fileName)
|
||||||
|
{
|
||||||
|
int hdrsOk;
|
||||||
|
|
||||||
|
// Try to open the file for reading
|
||||||
|
fptr = fopen(fileName, "rb");
|
||||||
|
if (fptr == NULL)
|
||||||
|
{
|
||||||
|
// didn't succeed
|
||||||
|
string msg = "Error : Unable to open file \"";
|
||||||
|
msg += fileName;
|
||||||
|
msg += "\" for reading.";
|
||||||
|
throw runtime_error(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read the file headers
|
||||||
|
hdrsOk = readWavHeaders();
|
||||||
|
if (hdrsOk != 0)
|
||||||
|
{
|
||||||
|
// Something didn't match in the wav file headers
|
||||||
|
string msg = "File \"";
|
||||||
|
msg += fileName;
|
||||||
|
msg += "\" is corrupt or not a WAV file";
|
||||||
|
throw runtime_error(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (header.format.fixed != 1)
|
||||||
|
{
|
||||||
|
string msg = "File \"";
|
||||||
|
msg += fileName;
|
||||||
|
msg += "\" uses unsupported encoding.";
|
||||||
|
throw runtime_error(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
dataRead = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
WavInFile::~WavInFile()
|
||||||
|
{
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void WavInFile::rewind()
|
||||||
|
{
|
||||||
|
int hdrsOk;
|
||||||
|
|
||||||
|
fseek(fptr, 0, SEEK_SET);
|
||||||
|
hdrsOk = readWavHeaders();
|
||||||
|
assert(hdrsOk == 0);
|
||||||
|
dataRead = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int WavInFile::checkCharTags()
|
||||||
|
{
|
||||||
|
// header.format.fmt should equal to 'fmt '
|
||||||
|
if (memcmp(fmtStr, header.format.fmt, 4) != 0) return -1;
|
||||||
|
// header.data.data_field should equal to 'data'
|
||||||
|
if (memcmp(dataStr, header.data.data_field, 4) != 0) return -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int WavInFile::read(char *buffer, int maxElems)
|
||||||
|
{
|
||||||
|
int numBytes;
|
||||||
|
uint afterDataRead;
|
||||||
|
|
||||||
|
// ensure it's 8 bit format
|
||||||
|
if (header.format.bits_per_sample != 8)
|
||||||
|
{
|
||||||
|
throw runtime_error("Error: WavInFile::read(char*, int) works only with 8bit samples.");
|
||||||
|
}
|
||||||
|
assert(sizeof(char) == 1);
|
||||||
|
|
||||||
|
numBytes = maxElems;
|
||||||
|
afterDataRead = dataRead + numBytes;
|
||||||
|
if (afterDataRead > header.data.data_len)
|
||||||
|
{
|
||||||
|
// Don't read more samples than are marked available in header
|
||||||
|
numBytes = header.data.data_len - dataRead;
|
||||||
|
assert(numBytes >= 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
numBytes = fread(buffer, 1, numBytes, fptr);
|
||||||
|
dataRead += numBytes;
|
||||||
|
|
||||||
|
return numBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int WavInFile::read(short *buffer, int maxElems)
|
||||||
|
{
|
||||||
|
unsigned int afterDataRead;
|
||||||
|
int numBytes;
|
||||||
|
int numElems;
|
||||||
|
|
||||||
|
if (header.format.bits_per_sample == 8)
|
||||||
|
{
|
||||||
|
// 8 bit format
|
||||||
|
char *temp = new char[maxElems];
|
||||||
|
int i;
|
||||||
|
|
||||||
|
numElems = read(temp, maxElems);
|
||||||
|
// convert from 8 to 16 bit
|
||||||
|
for (i = 0; i < numElems; i ++)
|
||||||
|
{
|
||||||
|
buffer[i] = temp[i] << 8;
|
||||||
|
}
|
||||||
|
delete[] temp;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 16 bit format
|
||||||
|
assert(header.format.bits_per_sample == 16);
|
||||||
|
assert(sizeof(short) == 2);
|
||||||
|
|
||||||
|
numBytes = maxElems * 2;
|
||||||
|
afterDataRead = dataRead + numBytes;
|
||||||
|
if (afterDataRead > header.data.data_len)
|
||||||
|
{
|
||||||
|
// Don't read more samples than are marked available in header
|
||||||
|
numBytes = header.data.data_len - dataRead;
|
||||||
|
assert(numBytes >= 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
numBytes = fread(buffer, 1, numBytes, fptr);
|
||||||
|
dataRead += numBytes;
|
||||||
|
numElems = numBytes / 2;
|
||||||
|
|
||||||
|
// 16bit samples, swap byte order if necessary
|
||||||
|
_swap16Buffer((unsigned short *)buffer, numElems);
|
||||||
|
}
|
||||||
|
|
||||||
|
return numElems;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int WavInFile::read(float *buffer, int maxElems)
|
||||||
|
{
|
||||||
|
short *temp = new short[maxElems];
|
||||||
|
int num;
|
||||||
|
int i;
|
||||||
|
double fscale;
|
||||||
|
|
||||||
|
num = read(temp, maxElems);
|
||||||
|
|
||||||
|
fscale = 1.0 / 32768.0;
|
||||||
|
// convert to floats, scale to range [-1..+1[
|
||||||
|
for (i = 0; i < num; i ++)
|
||||||
|
{
|
||||||
|
buffer[i] = (float)(fscale * (double)temp[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
delete[] temp;
|
||||||
|
|
||||||
|
return num;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int WavInFile::eof() const
|
||||||
|
{
|
||||||
|
// return true if all data has been read or file eof has reached
|
||||||
|
return (dataRead == header.data.data_len || feof(fptr));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void WavInFile::close()
|
||||||
|
{
|
||||||
|
fclose(fptr);
|
||||||
|
fptr = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// test if character code is between a white space ' ' and little 'z'
|
||||||
|
static int isAlpha(char c)
|
||||||
|
{
|
||||||
|
return (c >= ' ' && c <= 'z') ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// test if all characters are between a white space ' ' and little 'z'
|
||||||
|
static int isAlphaStr(char *str)
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
|
||||||
|
c = str[0];
|
||||||
|
while (c)
|
||||||
|
{
|
||||||
|
if (isAlpha(c) == 0) return 0;
|
||||||
|
str ++;
|
||||||
|
c = str[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int WavInFile::readRIFFBlock()
|
||||||
|
{
|
||||||
|
fread(&(header.riff), sizeof(WavRiff), 1, fptr);
|
||||||
|
|
||||||
|
// swap 32bit data byte order if necessary
|
||||||
|
_swap32((unsigned int &)header.riff.package_len);
|
||||||
|
|
||||||
|
// header.riff.riff_char should equal to 'RIFF');
|
||||||
|
if (memcmp(riffStr, header.riff.riff_char, 4) != 0) return -1;
|
||||||
|
// header.riff.wave should equal to 'WAVE'
|
||||||
|
if (memcmp(waveStr, header.riff.wave, 4) != 0) return -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int WavInFile::readHeaderBlock()
|
||||||
|
{
|
||||||
|
char label[5];
|
||||||
|
string sLabel;
|
||||||
|
|
||||||
|
// lead label string
|
||||||
|
fread(label, 1, 4, fptr);
|
||||||
|
label[4] = 0;
|
||||||
|
|
||||||
|
if (isAlphaStr(label) == 0) return -1; // not a valid label
|
||||||
|
|
||||||
|
// Decode blocks according to their label
|
||||||
|
if (strcmp(label, fmtStr) == 0)
|
||||||
|
{
|
||||||
|
int nLen, nDump;
|
||||||
|
|
||||||
|
// 'fmt ' block
|
||||||
|
memcpy(header.format.fmt, fmtStr, 4);
|
||||||
|
|
||||||
|
// read length of the format field
|
||||||
|
fread(&nLen, sizeof(int), 1, fptr);
|
||||||
|
// swap byte order if necessary
|
||||||
|
_swap32((unsigned int &)nLen); // int format_len;
|
||||||
|
header.format.format_len = nLen;
|
||||||
|
|
||||||
|
// calculate how much length differs from expected
|
||||||
|
nDump = nLen - (sizeof(header.format) - 8);
|
||||||
|
|
||||||
|
// if format_len is larger than expected, read only as much data as we've space for
|
||||||
|
if (nDump > 0)
|
||||||
|
{
|
||||||
|
nLen = sizeof(header.format) - 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
// read data
|
||||||
|
fread(&(header.format.fixed), nLen, 1, fptr);
|
||||||
|
|
||||||
|
// swap byte order if necessary
|
||||||
|
_swap16((unsigned short &)header.format.fixed); // short int fixed;
|
||||||
|
_swap16((unsigned short &)header.format.channel_number); // short int channel_number;
|
||||||
|
_swap32((unsigned int &)header.format.sample_rate); // int sample_rate;
|
||||||
|
_swap32((unsigned int &)header.format.byte_rate); // int byte_rate;
|
||||||
|
_swap16((unsigned short &)header.format.byte_per_sample); // short int byte_per_sample;
|
||||||
|
_swap16((unsigned short &)header.format.bits_per_sample); // short int bits_per_sample;
|
||||||
|
|
||||||
|
// if format_len is larger than expected, skip the extra data
|
||||||
|
if (nDump > 0)
|
||||||
|
{
|
||||||
|
fseek(fptr, nDump, SEEK_CUR);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else if (strcmp(label, dataStr) == 0)
|
||||||
|
{
|
||||||
|
// 'data' block
|
||||||
|
memcpy(header.data.data_field, dataStr, 4);
|
||||||
|
fread(&(header.data.data_len), sizeof(uint), 1, fptr);
|
||||||
|
|
||||||
|
// swap byte order if necessary
|
||||||
|
_swap32((unsigned int &)header.data.data_len);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uint len, i;
|
||||||
|
uint temp;
|
||||||
|
// unknown block
|
||||||
|
|
||||||
|
// read length
|
||||||
|
fread(&len, sizeof(len), 1, fptr);
|
||||||
|
// scan through the block
|
||||||
|
for (i = 0; i < len; i ++)
|
||||||
|
{
|
||||||
|
fread(&temp, 1, 1, fptr);
|
||||||
|
if (feof(fptr)) return -1; // unexpected eof
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int WavInFile::readWavHeaders()
|
||||||
|
{
|
||||||
|
int res;
|
||||||
|
|
||||||
|
memset(&header, 0, sizeof(header));
|
||||||
|
|
||||||
|
res = readRIFFBlock();
|
||||||
|
if (res) return 1;
|
||||||
|
// read header blocks until data block is found
|
||||||
|
do
|
||||||
|
{
|
||||||
|
// read header blocks
|
||||||
|
res = readHeaderBlock();
|
||||||
|
if (res < 0) return 1; // error in file structure
|
||||||
|
} while (res == 0);
|
||||||
|
// check that all required tags are legal
|
||||||
|
return checkCharTags();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint WavInFile::getNumChannels() const
|
||||||
|
{
|
||||||
|
return header.format.channel_number;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint WavInFile::getNumBits() const
|
||||||
|
{
|
||||||
|
return header.format.bits_per_sample;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint WavInFile::getBytesPerSample() const
|
||||||
|
{
|
||||||
|
return getNumChannels() * getNumBits() / 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint WavInFile::getSampleRate() const
|
||||||
|
{
|
||||||
|
return header.format.sample_rate;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
uint WavInFile::getDataSizeInBytes() const
|
||||||
|
{
|
||||||
|
return header.data.data_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint WavInFile::getNumSamples() const
|
||||||
|
{
|
||||||
|
return header.data.data_len / header.format.byte_per_sample;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint WavInFile::getLengthMS() const
|
||||||
|
{
|
||||||
|
uint numSamples;
|
||||||
|
uint sampleRate;
|
||||||
|
|
||||||
|
numSamples = getNumSamples();
|
||||||
|
sampleRate = getSampleRate();
|
||||||
|
|
||||||
|
assert(numSamples < UINT_MAX / 1000);
|
||||||
|
return (1000 * numSamples / sampleRate);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Class WavOutFile
|
||||||
|
//
|
||||||
|
|
||||||
|
WavOutFile::WavOutFile(const char *fileName, int sampleRate, int bits, int channels)
|
||||||
|
{
|
||||||
|
bytesWritten = 0;
|
||||||
|
fptr = fopen(fileName, "wb");
|
||||||
|
if (fptr == NULL)
|
||||||
|
{
|
||||||
|
string msg = "Error : Unable to open file \"";
|
||||||
|
msg += fileName;
|
||||||
|
msg += "\" for writing.";
|
||||||
|
//pmsg = msg.c_str;
|
||||||
|
throw runtime_error(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
fillInHeader(sampleRate, bits, channels);
|
||||||
|
writeHeader();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
WavOutFile::~WavOutFile()
|
||||||
|
{
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void WavOutFile::fillInHeader(uint sampleRate, uint bits, uint channels)
|
||||||
|
{
|
||||||
|
// fill in the 'riff' part..
|
||||||
|
|
||||||
|
// copy string 'RIFF' to riff_char
|
||||||
|
memcpy(&(header.riff.riff_char), riffStr, 4);
|
||||||
|
// package_len unknown so far
|
||||||
|
header.riff.package_len = 0;
|
||||||
|
// copy string 'WAVE' to wave
|
||||||
|
memcpy(&(header.riff.wave), waveStr, 4);
|
||||||
|
|
||||||
|
|
||||||
|
// fill in the 'format' part..
|
||||||
|
|
||||||
|
// copy string 'fmt ' to fmt
|
||||||
|
memcpy(&(header.format.fmt), fmtStr, 4);
|
||||||
|
|
||||||
|
header.format.format_len = 0x10;
|
||||||
|
header.format.fixed = 1;
|
||||||
|
header.format.channel_number = (short)channels;
|
||||||
|
header.format.sample_rate = sampleRate;
|
||||||
|
header.format.bits_per_sample = (short)bits;
|
||||||
|
header.format.byte_per_sample = (short)(bits * channels / 8);
|
||||||
|
header.format.byte_rate = header.format.byte_per_sample * sampleRate;
|
||||||
|
header.format.sample_rate = sampleRate;
|
||||||
|
|
||||||
|
// fill in the 'data' part..
|
||||||
|
|
||||||
|
// copy string 'data' to data_field
|
||||||
|
memcpy(&(header.data.data_field), dataStr, 4);
|
||||||
|
// data_len unknown so far
|
||||||
|
header.data.data_len = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void WavOutFile::finishHeader()
|
||||||
|
{
|
||||||
|
// supplement the file length into the header structure
|
||||||
|
header.riff.package_len = bytesWritten + 36;
|
||||||
|
header.data.data_len = bytesWritten;
|
||||||
|
|
||||||
|
writeHeader();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void WavOutFile::writeHeader()
|
||||||
|
{
|
||||||
|
WavHeader hdrTemp;
|
||||||
|
|
||||||
|
// swap byte order if necessary
|
||||||
|
hdrTemp = header;
|
||||||
|
_swap32((unsigned int &)hdrTemp.riff.package_len);
|
||||||
|
_swap32((unsigned int &)hdrTemp.format.format_len);
|
||||||
|
_swap16((unsigned short &)hdrTemp.format.fixed);
|
||||||
|
_swap16((unsigned short &)hdrTemp.format.channel_number);
|
||||||
|
_swap32((unsigned int &)hdrTemp.format.sample_rate);
|
||||||
|
_swap32((unsigned int &)hdrTemp.format.byte_rate);
|
||||||
|
_swap16((unsigned short &)hdrTemp.format.byte_per_sample);
|
||||||
|
_swap16((unsigned short &)hdrTemp.format.bits_per_sample);
|
||||||
|
_swap32((unsigned int &)hdrTemp.data.data_len);
|
||||||
|
|
||||||
|
// write the supplemented header in the beginning of the file
|
||||||
|
fseek(fptr, 0, SEEK_SET);
|
||||||
|
fwrite(&hdrTemp, sizeof(hdrTemp), 1, fptr);
|
||||||
|
// jump back to the end of the file
|
||||||
|
fseek(fptr, 0, SEEK_END);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void WavOutFile::close()
|
||||||
|
{
|
||||||
|
finishHeader();
|
||||||
|
fclose(fptr);
|
||||||
|
fptr = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void WavOutFile::write(const char *buffer, int numElems)
|
||||||
|
{
|
||||||
|
int res;
|
||||||
|
|
||||||
|
if (header.format.bits_per_sample != 8)
|
||||||
|
{
|
||||||
|
throw runtime_error("Error: WavOutFile::write(const char*, int) accepts only 8bit samples.");
|
||||||
|
}
|
||||||
|
assert(sizeof(char) == 1);
|
||||||
|
|
||||||
|
res = fwrite(buffer, 1, numElems, fptr);
|
||||||
|
if (res != numElems)
|
||||||
|
{
|
||||||
|
throw runtime_error("Error while writing to a wav file.");
|
||||||
|
}
|
||||||
|
|
||||||
|
bytesWritten += numElems;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void WavOutFile::write(const short *buffer, int numElems)
|
||||||
|
{
|
||||||
|
int res;
|
||||||
|
|
||||||
|
// 16 bit samples
|
||||||
|
if (numElems < 1) return; // nothing to do
|
||||||
|
|
||||||
|
if (header.format.bits_per_sample == 8)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
char *temp = new char[numElems];
|
||||||
|
// convert from 16bit format to 8bit format
|
||||||
|
for (i = 0; i < numElems; i ++)
|
||||||
|
{
|
||||||
|
temp[i] = buffer[i] >> 8;
|
||||||
|
}
|
||||||
|
// write in 8bit format
|
||||||
|
write(temp, numElems);
|
||||||
|
delete[] temp;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 16bit format
|
||||||
|
unsigned short *pTemp = new unsigned short[numElems];
|
||||||
|
|
||||||
|
assert(header.format.bits_per_sample == 16);
|
||||||
|
|
||||||
|
// allocate temp buffer to swap byte order if necessary
|
||||||
|
memcpy(pTemp, buffer, numElems * 2);
|
||||||
|
_swap16Buffer(pTemp, numElems);
|
||||||
|
|
||||||
|
res = fwrite(pTemp, 2, numElems, fptr);
|
||||||
|
|
||||||
|
delete[] pTemp;
|
||||||
|
|
||||||
|
if (res != numElems)
|
||||||
|
{
|
||||||
|
throw runtime_error("Error while writing to a wav file.");
|
||||||
|
}
|
||||||
|
bytesWritten += 2 * numElems;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void WavOutFile::write(const float *buffer, int numElems)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
short *temp = new short[numElems];
|
||||||
|
int iTemp;
|
||||||
|
|
||||||
|
// convert to 16 bit integer
|
||||||
|
for (i = 0; i < numElems; i ++)
|
||||||
|
{
|
||||||
|
// convert to integer
|
||||||
|
iTemp = (int)(32768.0f * buffer[i]);
|
||||||
|
|
||||||
|
// saturate
|
||||||
|
if (iTemp < -32768) iTemp = -32768;
|
||||||
|
if (iTemp > 32767) iTemp = 32767;
|
||||||
|
temp[i] = (short)iTemp;
|
||||||
|
}
|
||||||
|
|
||||||
|
write(temp, numElems);
|
||||||
|
|
||||||
|
delete[] temp;
|
||||||
|
}
|
|
@ -0,0 +1,253 @@
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
///
|
||||||
|
/// Classes for easy reading & writing of WAV sound files.
|
||||||
|
///
|
||||||
|
/// For big-endian CPU, define BIG_ENDIAN during compile-time to correctly
|
||||||
|
/// parse the WAV files with such processors.
|
||||||
|
///
|
||||||
|
/// Admittingly, more complete WAV reader routines may exist in public domain, but
|
||||||
|
/// the reason for 'yet another' one is that those generic WAV reader libraries are
|
||||||
|
/// exhaustingly large and cumbersome! Wanted to have something simpler here, i.e.
|
||||||
|
/// something that's not already larger than rest of the SoundTouch/SoundStretch program...
|
||||||
|
///
|
||||||
|
/// Author : Copyright (c) Olli Parviainen
|
||||||
|
/// Author e-mail : oparviai 'at' iki.fi
|
||||||
|
/// SoundTouch WWW: http://www.surina.net/soundtouch
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Last changed : $Date: 2006/02/05 16:44:06 $
|
||||||
|
// File revision : $Revision: 1.7 $
|
||||||
|
//
|
||||||
|
// $Id: WavFile.h,v 1.7 2006/02/05 16:44:06 Olli Exp $
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// License :
|
||||||
|
//
|
||||||
|
// SoundTouch audio processing library
|
||||||
|
// Copyright (c) Olli Parviainen
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU Lesser General Public
|
||||||
|
// License as published by the Free Software Foundation; either
|
||||||
|
// version 2.1 of the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef WAVFILE_H
|
||||||
|
#define WAVFILE_H
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#ifndef uint
|
||||||
|
typedef unsigned int uint;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/// WAV audio file 'riff' section header
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
char riff_char[4];
|
||||||
|
int package_len;
|
||||||
|
char wave[4];
|
||||||
|
} WavRiff;
|
||||||
|
|
||||||
|
/// WAV audio file 'format' section header
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
char fmt[4];
|
||||||
|
int format_len;
|
||||||
|
short fixed;
|
||||||
|
short channel_number;
|
||||||
|
int sample_rate;
|
||||||
|
int byte_rate;
|
||||||
|
short byte_per_sample;
|
||||||
|
short bits_per_sample;
|
||||||
|
} WavFormat;
|
||||||
|
|
||||||
|
/// WAV audio file 'data' section header
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
char data_field[4];
|
||||||
|
uint data_len;
|
||||||
|
} WavData;
|
||||||
|
|
||||||
|
|
||||||
|
/// WAV audio file header
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
WavRiff riff;
|
||||||
|
WavFormat format;
|
||||||
|
WavData data;
|
||||||
|
} WavHeader;
|
||||||
|
|
||||||
|
|
||||||
|
/// Class for reading WAV audio files.
|
||||||
|
class WavInFile
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
/// File pointer.
|
||||||
|
FILE *fptr;
|
||||||
|
|
||||||
|
/// Counter of how many bytes of sample data have been read from the file.
|
||||||
|
uint dataRead;
|
||||||
|
|
||||||
|
/// WAV header information
|
||||||
|
WavHeader header;
|
||||||
|
|
||||||
|
/// Read WAV file headers.
|
||||||
|
/// \return zero if all ok, nonzero if file format is invalid.
|
||||||
|
int readWavHeaders();
|
||||||
|
|
||||||
|
/// Checks WAV file header tags.
|
||||||
|
/// \return zero if all ok, nonzero if file format is invalid.
|
||||||
|
int checkCharTags();
|
||||||
|
|
||||||
|
/// Reads a single WAV file header block.
|
||||||
|
/// \return zero if all ok, nonzero if file format is invalid.
|
||||||
|
int readHeaderBlock();
|
||||||
|
|
||||||
|
/// Reads WAV file 'riff' block
|
||||||
|
int readRIFFBlock();
|
||||||
|
|
||||||
|
public:
|
||||||
|
/// Constructor: Opens the given WAV file. If the file can't be opened,
|
||||||
|
/// throws 'runtime_error' exception.
|
||||||
|
WavInFile(const char *filename);
|
||||||
|
|
||||||
|
/// Destructor: Closes the file.
|
||||||
|
~WavInFile();
|
||||||
|
|
||||||
|
/// Close the file. Notice that file is automatically closed also when the
|
||||||
|
/// class instance is deleted.
|
||||||
|
void close();
|
||||||
|
|
||||||
|
/// Rewind to beginning of the file
|
||||||
|
void rewind();
|
||||||
|
|
||||||
|
/// Get sample rate.
|
||||||
|
uint getSampleRate() const;
|
||||||
|
|
||||||
|
/// Get number of bits per sample, i.e. 8 or 16.
|
||||||
|
uint getNumBits() const;
|
||||||
|
|
||||||
|
/// Get sample data size in bytes. Ahem, this should return same information as
|
||||||
|
/// 'getBytesPerSample'...
|
||||||
|
uint getDataSizeInBytes() const;
|
||||||
|
|
||||||
|
/// Get total number of samples in file.
|
||||||
|
uint getNumSamples() const;
|
||||||
|
|
||||||
|
/// Get number of bytes per audio sample (e.g. 16bit stereo = 4 bytes/sample)
|
||||||
|
uint getBytesPerSample() const;
|
||||||
|
|
||||||
|
/// Get number of audio channels in the file (1=mono, 2=stereo)
|
||||||
|
uint getNumChannels() const;
|
||||||
|
|
||||||
|
/// Get the audio file length in milliseconds
|
||||||
|
uint getLengthMS() const;
|
||||||
|
|
||||||
|
/// Reads audio samples from the WAV file. This routine works only for 8 bit samples.
|
||||||
|
/// Reads given number of elements from the file or if end-of-file reached, as many
|
||||||
|
/// elements as are left in the file.
|
||||||
|
///
|
||||||
|
/// \return Number of 8-bit integers read from the file.
|
||||||
|
int read(char *buffer, int maxElems);
|
||||||
|
|
||||||
|
/// Reads audio samples from the WAV file to 16 bit integer format. Reads given number
|
||||||
|
/// of elements from the file or if end-of-file reached, as many elements as are
|
||||||
|
/// left in the file.
|
||||||
|
///
|
||||||
|
/// \return Number of 16-bit integers read from the file.
|
||||||
|
int read(short *buffer, ///< Pointer to buffer where to read data.
|
||||||
|
int maxElems ///< Size of 'buffer' array (number of array elements).
|
||||||
|
);
|
||||||
|
|
||||||
|
/// Reads audio samples from the WAV file to floating point format, converting
|
||||||
|
/// sample values to range [-1,1[. Reads given number of elements from the file
|
||||||
|
/// or if end-of-file reached, as many elements as are left in the file.
|
||||||
|
///
|
||||||
|
/// \return Number of elements read from the file.
|
||||||
|
int read(float *buffer, ///< Pointer to buffer where to read data.
|
||||||
|
int maxElems ///< Size of 'buffer' array (number of array elements).
|
||||||
|
);
|
||||||
|
|
||||||
|
/// Check end-of-file.
|
||||||
|
///
|
||||||
|
/// \return Nonzero if end-of-file reached.
|
||||||
|
int eof() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// Class for writing WAV audio files.
|
||||||
|
class WavOutFile
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
/// Pointer to the WAV file
|
||||||
|
FILE *fptr;
|
||||||
|
|
||||||
|
/// WAV file header data.
|
||||||
|
WavHeader header;
|
||||||
|
|
||||||
|
/// Counter of how many bytes have been written to the file so far.
|
||||||
|
int bytesWritten;
|
||||||
|
|
||||||
|
/// Fills in WAV file header information.
|
||||||
|
void fillInHeader(const uint sampleRate, const uint bits, const uint channels);
|
||||||
|
|
||||||
|
/// Finishes the WAV file header by supplementing information of amount of
|
||||||
|
/// data written to file etc
|
||||||
|
void finishHeader();
|
||||||
|
|
||||||
|
/// Writes the WAV file header.
|
||||||
|
void writeHeader();
|
||||||
|
|
||||||
|
public:
|
||||||
|
/// Constructor: Creates a new WAV file. Throws a 'runtime_error' exception
|
||||||
|
/// if file creation fails.
|
||||||
|
WavOutFile(const char *fileName, ///< Filename
|
||||||
|
int sampleRate, ///< Sample rate (e.g. 44100 etc)
|
||||||
|
int bits, ///< Bits per sample (8 or 16 bits)
|
||||||
|
int channels ///< Number of channels (1=mono, 2=stereo)
|
||||||
|
);
|
||||||
|
|
||||||
|
/// Destructor: Finalizes & closes the WAV file.
|
||||||
|
~WavOutFile();
|
||||||
|
|
||||||
|
/// Write data to WAV file. This function works only with 8bit samples.
|
||||||
|
/// Throws a 'runtime_error' exception if writing to file fails.
|
||||||
|
void write(const char *buffer, ///< Pointer to sample data buffer.
|
||||||
|
int numElems ///< How many array items are to be written to file.
|
||||||
|
);
|
||||||
|
|
||||||
|
/// Write data to WAV file. Throws a 'runtime_error' exception if writing to
|
||||||
|
/// file fails.
|
||||||
|
void write(const short *buffer, ///< Pointer to sample data buffer.
|
||||||
|
int numElems ///< How many array items are to be written to file.
|
||||||
|
);
|
||||||
|
|
||||||
|
/// Write data to WAV file in floating point format, saturating sample values to range
|
||||||
|
/// [-1..+1[. Throws a 'runtime_error' exception if writing to file fails.
|
||||||
|
void write(const float *buffer, ///< Pointer to sample data buffer.
|
||||||
|
int numElems ///< How many array items are to be written to file.
|
||||||
|
);
|
||||||
|
|
||||||
|
/// Finalize & close the WAV file. Automatically supplements the WAV file header
|
||||||
|
/// information according to written data etc.
|
||||||
|
///
|
||||||
|
/// Notice that file is automatically closed also when the class instance is deleted.
|
||||||
|
void close();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,62 @@
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
///
|
||||||
|
/// A header file for detecting the Intel MMX instructions set extension.
|
||||||
|
///
|
||||||
|
/// Please see 'mmx_win.cpp', 'mmx_cpp.cpp' and 'mmx_non_x86.cpp' for the
|
||||||
|
/// routine implementations for x86 Windows, x86 gnu version and non-x86
|
||||||
|
/// platforms, respectively.
|
||||||
|
///
|
||||||
|
/// Author : Copyright (c) Olli Parviainen
|
||||||
|
/// Author e-mail : oparviai 'at' iki.fi
|
||||||
|
/// SoundTouch WWW: http://www.surina.net/soundtouch
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Last changed : $Date: 2006/02/05 16:44:06 $
|
||||||
|
// File revision : $Revision: 1.4 $
|
||||||
|
//
|
||||||
|
// $Id: cpu_detect.h,v 1.4 2006/02/05 16:44:06 Olli Exp $
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// License :
|
||||||
|
//
|
||||||
|
// SoundTouch audio processing library
|
||||||
|
// Copyright (c) Olli Parviainen
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU Lesser General Public
|
||||||
|
// License as published by the Free Software Foundation; either
|
||||||
|
// version 2.1 of the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef _CPU_DETECT_H_
|
||||||
|
#define _CPU_DETECT_H_
|
||||||
|
|
||||||
|
#include "STTypes.h"
|
||||||
|
|
||||||
|
#define SUPPORT_MMX 0x0001
|
||||||
|
#define SUPPORT_3DNOW 0x0002
|
||||||
|
#define SUPPORT_ALTIVEC 0x0004
|
||||||
|
#define SUPPORT_SSE 0x0008
|
||||||
|
#define SUPPORT_SSE2 0x0010
|
||||||
|
|
||||||
|
/// Checks which instruction set extensions are supported by the CPU.
|
||||||
|
///
|
||||||
|
/// \return A bitmask of supported extensions, see SUPPORT_... defines.
|
||||||
|
uint detectCPUextensions(void);
|
||||||
|
|
||||||
|
/// Disables given set of instruction extensions. See SUPPORT_... defines.
|
||||||
|
void disableExtensions(uint wDisableMask);
|
||||||
|
|
||||||
|
#endif // _CPU_DETECT_H_
|
|
@ -0,0 +1,138 @@
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
///
|
||||||
|
/// gcc version of the x86 CPU detect routine.
|
||||||
|
///
|
||||||
|
/// This file is to be compiled on any platform with the GNU C compiler.
|
||||||
|
/// Compiler. Please see 'cpu_detect_x86_win.cpp' for the x86 Windows version
|
||||||
|
/// of this file.
|
||||||
|
///
|
||||||
|
/// Author : Copyright (c) Olli Parviainen
|
||||||
|
/// Author e-mail : oparviai 'at' iki.fi
|
||||||
|
/// SoundTouch WWW: http://www.surina.net/soundtouch
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Last changed : $Date: 2006/02/05 16:44:06 $
|
||||||
|
// File revision : $Revision: 1.6 $
|
||||||
|
//
|
||||||
|
// $Id: cpu_detect_x86_gcc.cpp,v 1.6 2006/02/05 16:44:06 Olli Exp $
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// License :
|
||||||
|
//
|
||||||
|
// SoundTouch audio processing library
|
||||||
|
// Copyright (c) Olli Parviainen
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU Lesser General Public
|
||||||
|
// License as published by the Free Software Foundation; either
|
||||||
|
// version 2.1 of the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <string>
|
||||||
|
#include "cpu_detect.h"
|
||||||
|
|
||||||
|
#ifndef __GNUC__
|
||||||
|
#error wrong platform - this source code file is for the GNU C compiler.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// processor instructions extension detection routines
|
||||||
|
//
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
// Flag variable indicating whick ISA extensions are disabled (for debugging)
|
||||||
|
static uint _dwDisabledISA = 0x00; // 0xffffffff; //<- use this to disable all extensions
|
||||||
|
|
||||||
|
// Disables given set of instruction extensions. See SUPPORT_... defines.
|
||||||
|
void disableExtensions(uint dwDisableMask)
|
||||||
|
{
|
||||||
|
_dwDisabledISA = dwDisableMask;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// Checks which instruction set extensions are supported by the CPU.
|
||||||
|
uint detectCPUextensions(void)
|
||||||
|
{
|
||||||
|
#ifndef __i386__
|
||||||
|
return 0; // always disable extensions on non-x86 platforms.
|
||||||
|
#else
|
||||||
|
uint res = 0;
|
||||||
|
|
||||||
|
if (_dwDisabledISA == 0xffffffff) return 0;
|
||||||
|
|
||||||
|
asm volatile(
|
||||||
|
"\n\txor %%esi, %%esi" // clear %%esi = result register
|
||||||
|
// check if 'cpuid' instructions is available by toggling eflags bit 21
|
||||||
|
|
||||||
|
"\n\tpushf" // save eflags to stack
|
||||||
|
"\n\tpop %%eax" // load eax from stack (with eflags)
|
||||||
|
"\n\tmovl %%eax, %%ecx" // save the original eflags values to ecx
|
||||||
|
"\n\txor $0x00200000, %%eax" // toggle bit 21
|
||||||
|
"\n\tpush %%eax" // store toggled eflags to stack
|
||||||
|
"\n\tpopf" // load eflags from stack
|
||||||
|
"\n\tpushf" // save updated eflags to stack
|
||||||
|
"\n\tpop %%eax" // load from stack
|
||||||
|
"\n\txor %%edx, %%edx" // clear edx for defaulting no mmx
|
||||||
|
"\n\tcmp %%ecx, %%eax" // compare to original eflags values
|
||||||
|
"\n\tjz end" // jumps to 'end' if cpuid not present
|
||||||
|
|
||||||
|
// cpuid instruction available, test for presence of mmx instructions
|
||||||
|
|
||||||
|
"\n\tmovl $1, %%eax"
|
||||||
|
"\n\tcpuid"
|
||||||
|
// movl $0x00800000, %edx // force enable MMX
|
||||||
|
"\n\ttest $0x00800000, %%edx"
|
||||||
|
"\n\tjz end" // branch if MMX not available
|
||||||
|
|
||||||
|
"\n\tor $0x01, %%esi" // otherwise add MMX support bit
|
||||||
|
|
||||||
|
"\n\ttest $0x02000000, %%edx"
|
||||||
|
"\n\tjz test3DNow" // branch if SSE not available
|
||||||
|
|
||||||
|
"\n\tor $0x08, %%esi" // otherwise add SSE support bit
|
||||||
|
|
||||||
|
"\n\ttest3DNow:"
|
||||||
|
// test for precense of AMD extensions
|
||||||
|
"\n\tmov $0x80000000, %%eax"
|
||||||
|
"\n\tcpuid"
|
||||||
|
"\n\tcmp $0x80000000, %%eax"
|
||||||
|
"\n\tjbe end" // branch if no AMD extensions detected
|
||||||
|
|
||||||
|
// test for precense of 3DNow! extension
|
||||||
|
"\n\tmov $0x80000001, %%eax"
|
||||||
|
"\n\tcpuid"
|
||||||
|
"\n\ttest $0x80000000, %%edx"
|
||||||
|
"\n\tjz end" // branch if 3DNow! not detected
|
||||||
|
|
||||||
|
"\n\tor $0x02, %%esi" // otherwise add 3DNow support bit
|
||||||
|
|
||||||
|
"\n\tend:"
|
||||||
|
|
||||||
|
"\n\tmov %%esi, %0"
|
||||||
|
|
||||||
|
: "=r" (res)
|
||||||
|
: /* no inputs */
|
||||||
|
: "%edx", "%eax", "%ecx", "%esi" );
|
||||||
|
|
||||||
|
return res & ~_dwDisabledISA;
|
||||||
|
#endif
|
||||||
|
}
|
|
@ -0,0 +1,126 @@
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
///
|
||||||
|
/// Win32 version of the x86 CPU detect routine.
|
||||||
|
///
|
||||||
|
/// This file is to be compiled in Windows platform with Microsoft Visual C++
|
||||||
|
/// Compiler. Please see 'cpu_detect_x86_gcc.cpp' for the gcc compiler version
|
||||||
|
/// for all GNU platforms.
|
||||||
|
///
|
||||||
|
/// Author : Copyright (c) Olli Parviainen
|
||||||
|
/// Author e-mail : oparviai 'at' iki.fi
|
||||||
|
/// SoundTouch WWW: http://www.surina.net/soundtouch
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Last changed : $Date: 2006/02/05 16:44:06 $
|
||||||
|
// File revision : $Revision: 1.10 $
|
||||||
|
//
|
||||||
|
// $Id: cpu_detect_x86_win.cpp,v 1.10 2006/02/05 16:44:06 Olli Exp $
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// License :
|
||||||
|
//
|
||||||
|
// SoundTouch audio processing library
|
||||||
|
// Copyright (c) Olli Parviainen
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU Lesser General Public
|
||||||
|
// License as published by the Free Software Foundation; either
|
||||||
|
// version 2.1 of the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include "cpu_detect.h"
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
|
#error wrong platform - this source code file is exclusively for Win32 platform
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// processor instructions extension detection routines
|
||||||
|
//
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Flag variable indicating whick ISA extensions are disabled (for debugging)
|
||||||
|
static uint _dwDisabledISA = 0x00; // 0xffffffff; //<- use this to disable all extensions
|
||||||
|
|
||||||
|
|
||||||
|
// Disables given set of instruction extensions. See SUPPORT_... defines.
|
||||||
|
void disableExtensions(uint dwDisableMask)
|
||||||
|
{
|
||||||
|
_dwDisabledISA = dwDisableMask;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// Checks which instruction set extensions are supported by the CPU.
|
||||||
|
uint detectCPUextensions(void)
|
||||||
|
{
|
||||||
|
uint res = 0;
|
||||||
|
|
||||||
|
if (_dwDisabledISA == 0xffffffff) return 0;
|
||||||
|
|
||||||
|
_asm
|
||||||
|
{
|
||||||
|
; check if 'cpuid' instructions is available by toggling eflags bit 21
|
||||||
|
;
|
||||||
|
xor esi, esi ; clear esi = result register
|
||||||
|
|
||||||
|
pushfd ; save eflags to stack
|
||||||
|
pop eax ; load eax from stack (with eflags)
|
||||||
|
mov ecx, eax ; save the original eflags values to ecx
|
||||||
|
xor eax, 0x00200000 ; toggle bit 21
|
||||||
|
push eax ; store toggled eflags to stack
|
||||||
|
popfd ; load eflags from stack
|
||||||
|
pushfd ; save updated eflags to stack
|
||||||
|
pop eax ; load from stack
|
||||||
|
xor edx, edx ; clear edx for defaulting no mmx
|
||||||
|
cmp eax, ecx ; compare to original eflags values
|
||||||
|
jz end ; jumps to 'end' if cpuid not present
|
||||||
|
|
||||||
|
; cpuid instruction available, test for presence of mmx instructions
|
||||||
|
mov eax, 1
|
||||||
|
cpuid
|
||||||
|
test edx, 0x00800000
|
||||||
|
jz end ; branch if MMX not available
|
||||||
|
|
||||||
|
or esi, SUPPORT_MMX ; otherwise add MMX support bit
|
||||||
|
|
||||||
|
test edx, 0x02000000
|
||||||
|
jz test3DNow ; branch if SSE not available
|
||||||
|
|
||||||
|
or esi, SUPPORT_SSE ; otherwise add SSE support bit
|
||||||
|
|
||||||
|
test3DNow:
|
||||||
|
; test for precense of AMD extensions
|
||||||
|
mov eax, 0x80000000
|
||||||
|
cpuid
|
||||||
|
cmp eax, 0x80000000
|
||||||
|
jbe end ; branch if no AMD extensions detected
|
||||||
|
|
||||||
|
; test for precense of 3DNow! extension
|
||||||
|
mov eax, 0x80000001
|
||||||
|
cpuid
|
||||||
|
test edx, 0x80000000
|
||||||
|
jz end ; branch if 3DNow! not detected
|
||||||
|
|
||||||
|
or esi, SUPPORT_3DNOW ; otherwise add 3DNow support bit
|
||||||
|
|
||||||
|
end:
|
||||||
|
|
||||||
|
mov res, esi
|
||||||
|
}
|
||||||
|
|
||||||
|
return res & ~_dwDisabledISA;
|
||||||
|
}
|
|
@ -0,0 +1,305 @@
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
///
|
||||||
|
/// MMX optimized routines. All MMX optimized functions have been gathered into
|
||||||
|
/// this single source code file, regardless to their class or original source
|
||||||
|
/// code file, in order to ease porting the library to other compiler and
|
||||||
|
/// processor platforms.
|
||||||
|
///
|
||||||
|
/// The MMX-optimizations are programmed using MMX compiler intrinsics that
|
||||||
|
/// are supported both by Microsoft Visual C++ and GCC compilers, so this file
|
||||||
|
/// should compile with both toolsets.
|
||||||
|
///
|
||||||
|
/// NOTICE: If using Visual Studio 6.0, you'll need to install the "Visual C++
|
||||||
|
/// 6.0 processor pack" update to support compiler intrinsic syntax. The update
|
||||||
|
/// is available for download at Microsoft Developers Network, see here:
|
||||||
|
/// http://msdn.microsoft.com/vstudio/downloads/tools/ppack/default.aspx
|
||||||
|
///
|
||||||
|
/// Author : Copyright (c) Olli Parviainen
|
||||||
|
/// Author e-mail : oparviai 'at' iki.fi
|
||||||
|
/// SoundTouch WWW: http://www.surina.net/soundtouch
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Last changed : $Date: 2006/02/06 18:52:43 $
|
||||||
|
// File revision : $Revision: 1.1 $
|
||||||
|
//
|
||||||
|
// $Id: mmx_optimized.cpp,v 1.1 2006/02/06 18:52:43 Olli Exp $
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// License :
|
||||||
|
//
|
||||||
|
// SoundTouch audio processing library
|
||||||
|
// Copyright (c) Olli Parviainen
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU Lesser General Public
|
||||||
|
// License as published by the Free Software Foundation; either
|
||||||
|
// version 2.1 of the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include "STTypes.h"
|
||||||
|
|
||||||
|
#ifdef ALLOW_MMX
|
||||||
|
// MMX routines available only with integer sample type
|
||||||
|
|
||||||
|
#if !(_WIN32 || __i386__ || __x86_64__)
|
||||||
|
#error "wrong platform - this source code file is exclusively for x86 platforms"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
using namespace soundtouch;
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// implementation of MMX optimized functions of class 'TDStretchMMX'
|
||||||
|
//
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include "TDStretch.h"
|
||||||
|
#include <mmintrin.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
|
|
||||||
|
// Calculates cross correlation of two buffers
|
||||||
|
long TDStretchMMX::calcCrossCorrStereo(const short *pV1, const short *pV2) const
|
||||||
|
{
|
||||||
|
const __m64 *pVec1, *pVec2;
|
||||||
|
__m64 shifter;
|
||||||
|
__m64 accu;
|
||||||
|
long corr;
|
||||||
|
uint i;
|
||||||
|
|
||||||
|
pVec1 = (__m64*)pV1;
|
||||||
|
pVec2 = (__m64*)pV2;
|
||||||
|
|
||||||
|
shifter = _m_from_int(overlapDividerBits);
|
||||||
|
accu = _mm_setzero_si64();
|
||||||
|
|
||||||
|
// Process 4 parallel sets of 2 * stereo samples each during each
|
||||||
|
// round to improve CPU-level parallellization.
|
||||||
|
for (i = 0; i < overlapLength / 8; i ++)
|
||||||
|
{
|
||||||
|
__m64 temp;
|
||||||
|
|
||||||
|
// dictionary of instructions:
|
||||||
|
// _m_pmaddwd : 4*16bit multiply-add, resulting two 32bits = [a0*b0+a1*b1 ; a2*b2+a3*b3]
|
||||||
|
// _mm_add_pi32 : 2*32bit add
|
||||||
|
// _m_psrad : 32bit right-shift
|
||||||
|
|
||||||
|
temp = _mm_add_pi32(_mm_madd_pi16(pVec1[0], pVec2[0]),
|
||||||
|
_mm_madd_pi16(pVec1[1], pVec2[1]));
|
||||||
|
accu = _mm_add_pi32(accu, _mm_sra_pi32(temp, shifter));
|
||||||
|
|
||||||
|
temp = _mm_add_pi32(_mm_madd_pi16(pVec1[2], pVec2[2]),
|
||||||
|
_mm_madd_pi16(pVec1[3], pVec2[3]));
|
||||||
|
accu = _mm_add_pi32(accu, _mm_sra_pi32(temp, shifter));
|
||||||
|
|
||||||
|
pVec1 += 4;
|
||||||
|
pVec2 += 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
// copy hi-dword of mm0 to lo-dword of mm1, then sum mmo+mm1
|
||||||
|
// and finally store the result into the variable "corr"
|
||||||
|
|
||||||
|
accu = _mm_add_pi32(accu, _mm_srli_si64(accu, 32));
|
||||||
|
corr = _m_to_int(accu);
|
||||||
|
|
||||||
|
// Clear MMS state
|
||||||
|
_m_empty();
|
||||||
|
|
||||||
|
return corr;
|
||||||
|
// Note: Warning about the missing EMMS instruction is harmless
|
||||||
|
// as it'll be called elsewhere.
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void TDStretchMMX::clearCrossCorrState()
|
||||||
|
{
|
||||||
|
// Clear MMS state
|
||||||
|
_m_empty();
|
||||||
|
//_asm EMMS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// MMX-optimized version of the function overlapStereo
|
||||||
|
void TDStretchMMX::overlapStereo(short *output, const short *input) const
|
||||||
|
{
|
||||||
|
const __m64 *pVinput, *pVMidBuf;
|
||||||
|
__m64 *pVdest;
|
||||||
|
__m64 mix1, mix2, adder, shifter;
|
||||||
|
uint i;
|
||||||
|
|
||||||
|
pVinput = (const __m64*)input;
|
||||||
|
pVMidBuf = (const __m64*)pMidBuffer;
|
||||||
|
pVdest = (__m64*)output;
|
||||||
|
|
||||||
|
// mix1 = mixer values for 1st stereo sample
|
||||||
|
// mix1 = mixer values for 2nd stereo sample
|
||||||
|
// adder = adder for updating mixer values after each round
|
||||||
|
|
||||||
|
mix1 = _mm_set_pi16(0, overlapLength, 0, overlapLength);
|
||||||
|
adder = _mm_set_pi16(1, -1, 1, -1);
|
||||||
|
mix2 = _mm_add_pi16(mix1, adder);
|
||||||
|
adder = _mm_add_pi16(adder, adder);
|
||||||
|
|
||||||
|
shifter = _m_from_int(overlapDividerBits);
|
||||||
|
|
||||||
|
for (i = 0; i < overlapLength / 4; i ++)
|
||||||
|
{
|
||||||
|
__m64 temp1, temp2;
|
||||||
|
|
||||||
|
// load & shuffle data so that input & mixbuffer data samples are paired
|
||||||
|
temp1 = _mm_unpacklo_pi16(pVMidBuf[0], pVinput[0]); // = i0l m0l i0r m0r
|
||||||
|
temp2 = _mm_unpackhi_pi16(pVMidBuf[0], pVinput[0]); // = i1l m1l i1r m1r
|
||||||
|
|
||||||
|
// temp = (temp .* mix) >> shifter
|
||||||
|
temp1 = _mm_sra_pi32(_mm_madd_pi16(temp1, mix1), shifter);
|
||||||
|
temp2 = _mm_sra_pi32(_mm_madd_pi16(temp2, mix2), shifter);
|
||||||
|
pVdest[0] = _mm_packs_pi32(temp1, temp2); // pack 2*2*32bit => 4*16bit
|
||||||
|
|
||||||
|
// update mix += adder
|
||||||
|
mix1 = _mm_add_pi16(mix1, adder);
|
||||||
|
mix2 = _mm_add_pi16(mix2, adder);
|
||||||
|
|
||||||
|
// --- second round begins here ---
|
||||||
|
|
||||||
|
// load & shuffle data so that input & mixbuffer data samples are paired
|
||||||
|
temp1 = _mm_unpacklo_pi16(pVMidBuf[1], pVinput[1]); // = i2l m2l i2r m2r
|
||||||
|
temp2 = _mm_unpackhi_pi16(pVMidBuf[1], pVinput[1]); // = i3l m3l i3r m3r
|
||||||
|
|
||||||
|
// temp = (temp .* mix) >> shifter
|
||||||
|
temp1 = _mm_sra_pi32(_mm_madd_pi16(temp1, mix1), shifter);
|
||||||
|
temp2 = _mm_sra_pi32(_mm_madd_pi16(temp2, mix2), shifter);
|
||||||
|
pVdest[1] = _mm_packs_pi32(temp1, temp2); // pack 2*2*32bit => 4*16bit
|
||||||
|
|
||||||
|
// update mix += adder
|
||||||
|
mix1 = _mm_add_pi16(mix1, adder);
|
||||||
|
mix2 = _mm_add_pi16(mix2, adder);
|
||||||
|
|
||||||
|
pVinput += 2;
|
||||||
|
pVMidBuf += 2;
|
||||||
|
pVdest += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
_m_empty(); // clear MMS state
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// implementation of MMX optimized functions of class 'FIRFilter'
|
||||||
|
//
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include "FIRFilter.h"
|
||||||
|
|
||||||
|
|
||||||
|
FIRFilterMMX::FIRFilterMMX() : FIRFilter()
|
||||||
|
{
|
||||||
|
filterCoeffsUnalign = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
FIRFilterMMX::~FIRFilterMMX()
|
||||||
|
{
|
||||||
|
delete[] filterCoeffsUnalign;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// (overloaded) Calculates filter coefficients for MMX routine
|
||||||
|
void FIRFilterMMX::setCoefficients(const short *coeffs, uint newLength, uint uResultDivFactor)
|
||||||
|
{
|
||||||
|
uint i;
|
||||||
|
FIRFilter::setCoefficients(coeffs, newLength, uResultDivFactor);
|
||||||
|
|
||||||
|
// Ensure that filter coeffs array is aligned to 16-byte boundary
|
||||||
|
delete[] filterCoeffsUnalign;
|
||||||
|
filterCoeffsUnalign = new short[2 * newLength + 8];
|
||||||
|
filterCoeffsAlign = (short *)(((ulongptr)filterCoeffsUnalign + 15) & -16);
|
||||||
|
|
||||||
|
// rearrange the filter coefficients for mmx routines
|
||||||
|
for (i = 0;i < length; i += 4)
|
||||||
|
{
|
||||||
|
filterCoeffsAlign[2 * i + 0] = coeffs[i + 0];
|
||||||
|
filterCoeffsAlign[2 * i + 1] = coeffs[i + 2];
|
||||||
|
filterCoeffsAlign[2 * i + 2] = coeffs[i + 0];
|
||||||
|
filterCoeffsAlign[2 * i + 3] = coeffs[i + 2];
|
||||||
|
|
||||||
|
filterCoeffsAlign[2 * i + 4] = coeffs[i + 1];
|
||||||
|
filterCoeffsAlign[2 * i + 5] = coeffs[i + 3];
|
||||||
|
filterCoeffsAlign[2 * i + 6] = coeffs[i + 1];
|
||||||
|
filterCoeffsAlign[2 * i + 7] = coeffs[i + 3];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// mmx-optimized version of the filter routine for stereo sound
|
||||||
|
uint FIRFilterMMX::evaluateFilterStereo(short *dest, const short *src, const uint numSamples) const
|
||||||
|
{
|
||||||
|
// Create stack copies of the needed member variables for asm routines :
|
||||||
|
uint i, j;
|
||||||
|
__m64 *pVdest = (__m64*)dest;
|
||||||
|
|
||||||
|
if (length < 2) return 0;
|
||||||
|
|
||||||
|
for (i = 0; i < numSamples / 2; i ++)
|
||||||
|
{
|
||||||
|
__m64 accu1;
|
||||||
|
__m64 accu2;
|
||||||
|
const __m64 *pVsrc = (const __m64*)src;
|
||||||
|
const __m64 *pVfilter = (const __m64*)filterCoeffsAlign;
|
||||||
|
|
||||||
|
accu1 = accu2 = _mm_setzero_si64();
|
||||||
|
for (j = 0; j < lengthDiv8 * 2; j ++)
|
||||||
|
{
|
||||||
|
__m64 temp1, temp2;
|
||||||
|
|
||||||
|
temp1 = _mm_unpacklo_pi16(pVsrc[0], pVsrc[1]); // = l2 l0 r2 r0
|
||||||
|
temp2 = _mm_unpackhi_pi16(pVsrc[0], pVsrc[1]); // = l3 l1 r3 r1
|
||||||
|
|
||||||
|
accu1 = _mm_add_pi32(accu1, _mm_madd_pi16(temp1, pVfilter[0])); // += l2*f2+l0*f0 r2*f2+r0*f0
|
||||||
|
accu1 = _mm_add_pi32(accu1, _mm_madd_pi16(temp2, pVfilter[1])); // += l3*f3+l1*f1 r3*f3+r1*f1
|
||||||
|
|
||||||
|
temp1 = _mm_unpacklo_pi16(pVsrc[1], pVsrc[2]); // = l4 l2 r4 r2
|
||||||
|
|
||||||
|
accu2 = _mm_add_pi32(accu2, _mm_madd_pi16(temp2, pVfilter[0])); // += l3*f2+l1*f0 r3*f2+r1*f0
|
||||||
|
accu2 = _mm_add_pi32(accu2, _mm_madd_pi16(temp1, pVfilter[1])); // += l4*f3+l2*f1 r4*f3+r2*f1
|
||||||
|
|
||||||
|
// accu1 += l2*f2+l0*f0 r2*f2+r0*f0
|
||||||
|
// += l3*f3+l1*f1 r3*f3+r1*f1
|
||||||
|
|
||||||
|
// accu2 += l3*f2+l1*f0 r3*f2+r1*f0
|
||||||
|
// l4*f3+l2*f1 r4*f3+r2*f1
|
||||||
|
|
||||||
|
pVfilter += 2;
|
||||||
|
pVsrc += 2;
|
||||||
|
}
|
||||||
|
// accu >>= resultDivFactor
|
||||||
|
accu1 = _mm_srai_pi32(accu1, resultDivFactor);
|
||||||
|
accu2 = _mm_srai_pi32(accu2, resultDivFactor);
|
||||||
|
|
||||||
|
// pack 2*2*32bits => 4*16 bits
|
||||||
|
pVdest[0] = _mm_packs_pi32(accu1, accu2);
|
||||||
|
src += 4;
|
||||||
|
pVdest ++;
|
||||||
|
}
|
||||||
|
|
||||||
|
_m_empty(); // clear emms state
|
||||||
|
|
||||||
|
return (numSamples & 0xfffffffe) - length;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // ALLOW_MMX
|
|
@ -0,0 +1,484 @@
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
///
|
||||||
|
/// SSE optimized routines for Pentium-III, Athlon-XP and later CPUs. All SSE
|
||||||
|
/// optimized functions have been gathered into this single source
|
||||||
|
/// code file, regardless to their class or original source code file, in order
|
||||||
|
/// to ease porting the library to other compiler and processor platforms.
|
||||||
|
///
|
||||||
|
/// The SSE-optimizations are programmed using SSE compiler intrinsics that
|
||||||
|
/// are supported both by Microsoft Visual C++ and GCC compilers, so this file
|
||||||
|
/// should compile with both toolsets.
|
||||||
|
///
|
||||||
|
/// NOTICE: If using Visual Studio 6.0, you'll need to install the "Visual C++
|
||||||
|
/// 6.0 processor pack" update to support SSE instruction set. The update is
|
||||||
|
/// available for download at Microsoft Developers Network, see here:
|
||||||
|
/// http://msdn.microsoft.com/vstudio/downloads/tools/ppack/default.aspx
|
||||||
|
///
|
||||||
|
/// If the above URL is expired or removed, go to "http://msdn.microsoft.com" and
|
||||||
|
/// perform a search with keywords "processor pack".
|
||||||
|
///
|
||||||
|
/// Author : Copyright (c) Olli Parviainen
|
||||||
|
/// Author e-mail : oparviai 'at' iki.fi
|
||||||
|
/// SoundTouch WWW: http://www.surina.net/soundtouch
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Last changed : $Date: 2006/02/05 16:44:06 $
|
||||||
|
// File revision : $Revision: 1.2 $
|
||||||
|
//
|
||||||
|
// $Id: sse_optimized.cpp,v 1.2 2006/02/05 16:44:06 Olli Exp $
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// License :
|
||||||
|
//
|
||||||
|
// SoundTouch audio processing library
|
||||||
|
// Copyright (c) Olli Parviainen
|
||||||
|
//
|
||||||
|
// This library is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU Lesser General Public
|
||||||
|
// License as published by the Free Software Foundation; either
|
||||||
|
// version 2.1 of the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public
|
||||||
|
// License along with this library; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include "cpu_detect.h"
|
||||||
|
#include "STTypes.h"
|
||||||
|
|
||||||
|
using namespace soundtouch;
|
||||||
|
|
||||||
|
#ifdef ALLOW_SSE
|
||||||
|
|
||||||
|
// SSE routines available only with float sample type
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// implementation of SSE optimized functions of class 'TDStretchSSE'
|
||||||
|
//
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include "TDStretch.h"
|
||||||
|
#include <xmmintrin.h>
|
||||||
|
|
||||||
|
// Calculates cross correlation of two buffers
|
||||||
|
double TDStretchSSE::calcCrossCorrStereo(const float *pV1, const float *pV2) const
|
||||||
|
{
|
||||||
|
uint i;
|
||||||
|
__m128 vSum, *pVec2;
|
||||||
|
|
||||||
|
// Note. It means a major slow-down if the routine needs to tolerate
|
||||||
|
// unaligned __m128 memory accesses. It's way faster if we can skip
|
||||||
|
// unaligned slots and use _mm_load_ps instruction instead of _mm_loadu_ps.
|
||||||
|
// This can mean up to ~ 10-fold difference (incl. part of which is
|
||||||
|
// due to skipping every second round for stereo sound though).
|
||||||
|
//
|
||||||
|
// Compile-time define ALLOW_NONEXACT_SIMD_OPTIMIZATION is provided
|
||||||
|
// for choosing if this little cheating is allowed.
|
||||||
|
|
||||||
|
#ifdef ALLOW_NONEXACT_SIMD_OPTIMIZATION
|
||||||
|
// Little cheating allowed, return valid correlation only for
|
||||||
|
// aligned locations, meaning every second round for stereo sound.
|
||||||
|
|
||||||
|
#define _MM_LOAD _mm_load_ps
|
||||||
|
|
||||||
|
if (((ulong)pV1) & 15) return -1e50; // skip unaligned locations
|
||||||
|
|
||||||
|
#else
|
||||||
|
// No cheating allowed, use unaligned load & take the resulting
|
||||||
|
// performance hit.
|
||||||
|
#define _MM_LOAD _mm_loadu_ps
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ensure overlapLength is divisible by 8
|
||||||
|
assert((overlapLength % 8) == 0);
|
||||||
|
|
||||||
|
// Calculates the cross-correlation value between 'pV1' and 'pV2' vectors
|
||||||
|
// Note: pV2 _must_ be aligned to 16-bit boundary, pV1 need not.
|
||||||
|
pVec2 = (__m128*)pV2;
|
||||||
|
vSum = _mm_setzero_ps();
|
||||||
|
|
||||||
|
// Unroll the loop by factor of 4 * 4 operations
|
||||||
|
for (i = 0; i < overlapLength / 8; i ++)
|
||||||
|
{
|
||||||
|
// vSum += pV1[0..3] * pV2[0..3]
|
||||||
|
vSum = _mm_add_ps(vSum, _mm_mul_ps(_MM_LOAD(pV1),pVec2[0]));
|
||||||
|
|
||||||
|
// vSum += pV1[4..7] * pV2[4..7]
|
||||||
|
vSum = _mm_add_ps(vSum, _mm_mul_ps(_MM_LOAD(pV1 + 4), pVec2[1]));
|
||||||
|
|
||||||
|
// vSum += pV1[8..11] * pV2[8..11]
|
||||||
|
vSum = _mm_add_ps(vSum, _mm_mul_ps(_MM_LOAD(pV1 + 8), pVec2[2]));
|
||||||
|
|
||||||
|
// vSum += pV1[12..15] * pV2[12..15]
|
||||||
|
vSum = _mm_add_ps(vSum, _mm_mul_ps(_MM_LOAD(pV1 + 12), pVec2[3]));
|
||||||
|
|
||||||
|
pV1 += 16;
|
||||||
|
pVec2 += 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
// return value = vSum[0] + vSum[1] + vSum[2] + vSum[3]
|
||||||
|
float *pvSum = (float*)&vSum;
|
||||||
|
return (double)(pvSum[0] + pvSum[1] + pvSum[2] + pvSum[3]);
|
||||||
|
|
||||||
|
/* This is approximately corresponding routine in C-language:
|
||||||
|
double corr;
|
||||||
|
uint i;
|
||||||
|
|
||||||
|
// Calculates the cross-correlation value between 'pV1' and 'pV2' vectors
|
||||||
|
corr = 0.0;
|
||||||
|
for (i = 0; i < overlapLength / 8; i ++)
|
||||||
|
{
|
||||||
|
corr += pV1[0] * pV2[0] +
|
||||||
|
pV1[1] * pV2[1] +
|
||||||
|
pV1[2] * pV2[2] +
|
||||||
|
pV1[3] * pV2[3] +
|
||||||
|
pV1[4] * pV2[4] +
|
||||||
|
pV1[5] * pV2[5] +
|
||||||
|
pV1[6] * pV2[6] +
|
||||||
|
pV1[7] * pV2[7] +
|
||||||
|
pV1[8] * pV2[8] +
|
||||||
|
pV1[9] * pV2[9] +
|
||||||
|
pV1[10] * pV2[10] +
|
||||||
|
pV1[11] * pV2[11] +
|
||||||
|
pV1[12] * pV2[12] +
|
||||||
|
pV1[13] * pV2[13] +
|
||||||
|
pV1[14] * pV2[14] +
|
||||||
|
pV1[15] * pV2[15];
|
||||||
|
|
||||||
|
pV1 += 16;
|
||||||
|
pV2 += 16;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* This is corresponding routine in assembler. This may be teeny-weeny bit faster
|
||||||
|
than intrinsic version, but more difficult to maintain & get compiled on multiple
|
||||||
|
platforms.
|
||||||
|
|
||||||
|
uint overlapLengthLocal = overlapLength;
|
||||||
|
float corr;
|
||||||
|
|
||||||
|
_asm
|
||||||
|
{
|
||||||
|
// Very important note: data in 'pV2' _must_ be aligned to
|
||||||
|
// 16-byte boundary!
|
||||||
|
|
||||||
|
// give prefetch hints to CPU of what data are to be needed soonish
|
||||||
|
// give more aggressive hints on pV1 as that changes while pV2 stays
|
||||||
|
// same between runs
|
||||||
|
prefetcht0 [pV1]
|
||||||
|
prefetcht0 [pV2]
|
||||||
|
prefetcht0 [pV1 + 32]
|
||||||
|
|
||||||
|
mov eax, dword ptr pV1
|
||||||
|
mov ebx, dword ptr pV2
|
||||||
|
|
||||||
|
xorps xmm0, xmm0
|
||||||
|
|
||||||
|
mov ecx, overlapLengthLocal
|
||||||
|
shr ecx, 3 // div by eight
|
||||||
|
|
||||||
|
loop1:
|
||||||
|
prefetcht0 [eax + 64] // give a prefetch hint to CPU what data are to be needed soonish
|
||||||
|
prefetcht0 [ebx + 32] // give a prefetch hint to CPU what data are to be needed soonish
|
||||||
|
movups xmm1, [eax]
|
||||||
|
mulps xmm1, [ebx]
|
||||||
|
addps xmm0, xmm1
|
||||||
|
|
||||||
|
movups xmm2, [eax + 16]
|
||||||
|
mulps xmm2, [ebx + 16]
|
||||||
|
addps xmm0, xmm2
|
||||||
|
|
||||||
|
prefetcht0 [eax + 96] // give a prefetch hint to CPU what data are to be needed soonish
|
||||||
|
prefetcht0 [ebx + 64] // give a prefetch hint to CPU what data are to be needed soonish
|
||||||
|
|
||||||
|
movups xmm3, [eax + 32]
|
||||||
|
mulps xmm3, [ebx + 32]
|
||||||
|
addps xmm0, xmm3
|
||||||
|
|
||||||
|
movups xmm4, [eax + 48]
|
||||||
|
mulps xmm4, [ebx + 48]
|
||||||
|
addps xmm0, xmm4
|
||||||
|
|
||||||
|
add eax, 64
|
||||||
|
add ebx, 64
|
||||||
|
|
||||||
|
dec ecx
|
||||||
|
jnz loop1
|
||||||
|
|
||||||
|
// add the four floats of xmm0 together and return the result.
|
||||||
|
|
||||||
|
movhlps xmm1, xmm0 // move 3 & 4 of xmm0 to 1 & 2 of xmm1
|
||||||
|
addps xmm1, xmm0
|
||||||
|
movaps xmm2, xmm1
|
||||||
|
shufps xmm2, xmm2, 0x01 // move 2 of xmm2 as 1 of xmm2
|
||||||
|
addss xmm2, xmm1
|
||||||
|
movss corr, xmm2
|
||||||
|
}
|
||||||
|
|
||||||
|
return (double)corr;
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// implementation of SSE optimized functions of class 'FIRFilter'
|
||||||
|
//
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include "FIRFilter.h"
|
||||||
|
|
||||||
|
FIRFilterSSE::FIRFilterSSE() : FIRFilter()
|
||||||
|
{
|
||||||
|
filterCoeffsUnalign = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
FIRFilterSSE::~FIRFilterSSE()
|
||||||
|
{
|
||||||
|
delete[] filterCoeffsUnalign;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// (overloaded) Calculates filter coefficients for SSE routine
|
||||||
|
void FIRFilterSSE::setCoefficients(const float *coeffs, uint newLength, uint uResultDivFactor)
|
||||||
|
{
|
||||||
|
uint i;
|
||||||
|
float fDivider;
|
||||||
|
|
||||||
|
FIRFilter::setCoefficients(coeffs, newLength, uResultDivFactor);
|
||||||
|
|
||||||
|
// Scale the filter coefficients so that it won't be necessary to scale the filtering result
|
||||||
|
// also rearrange coefficients suitably for 3DNow!
|
||||||
|
// Ensure that filter coeffs array is aligned to 16-byte boundary
|
||||||
|
delete[] filterCoeffsUnalign;
|
||||||
|
filterCoeffsUnalign = new float[2 * newLength + 4];
|
||||||
|
filterCoeffsAlign = (float *)(((unsigned long)filterCoeffsUnalign + 15) & -16);
|
||||||
|
|
||||||
|
fDivider = (float)resultDivider;
|
||||||
|
|
||||||
|
// rearrange the filter coefficients for mmx routines
|
||||||
|
for (i = 0; i < newLength; i ++)
|
||||||
|
{
|
||||||
|
filterCoeffsAlign[2 * i + 0] =
|
||||||
|
filterCoeffsAlign[2 * i + 1] = coeffs[i + 0] / fDivider;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// SSE-optimized version of the filter routine for stereo sound
|
||||||
|
uint FIRFilterSSE::evaluateFilterStereo(float *dest, const float *source, uint numSamples) const
|
||||||
|
{
|
||||||
|
int count = (numSamples - length) & -2;
|
||||||
|
int j;
|
||||||
|
|
||||||
|
assert(count % 2 == 0);
|
||||||
|
|
||||||
|
if (count < 2) return 0;
|
||||||
|
|
||||||
|
assert((length % 8) == 0);
|
||||||
|
assert(((unsigned long)filterCoeffsAlign) % 16 == 0);
|
||||||
|
|
||||||
|
// filter is evaluated for two stereo samples with each iteration, thus use of 'j += 2'
|
||||||
|
for (j = 0; j < count; j += 2)
|
||||||
|
{
|
||||||
|
const float *pSrc;
|
||||||
|
const __m128 *pFil;
|
||||||
|
__m128 sum1, sum2;
|
||||||
|
uint i;
|
||||||
|
|
||||||
|
pSrc = source; // source audio data
|
||||||
|
pFil = (__m128*)filterCoeffsAlign; // filter coefficients. NOTE: Assumes coefficients
|
||||||
|
// are aligned to 16-byte boundary
|
||||||
|
sum1 = sum2 = _mm_setzero_ps();
|
||||||
|
|
||||||
|
for (i = 0; i < length / 8; i ++)
|
||||||
|
{
|
||||||
|
// Unroll loop for efficiency & calculate filter for 2*2 stereo samples
|
||||||
|
// at each pass
|
||||||
|
|
||||||
|
// sum1 is accu for 2*2 filtered stereo sound data at the primary sound data offset
|
||||||
|
// sum2 is accu for 2*2 filtered stereo sound data for the next sound sample offset.
|
||||||
|
|
||||||
|
sum1 = _mm_add_ps(sum1, _mm_mul_ps(_mm_loadu_ps(pSrc) , pFil[0]));
|
||||||
|
sum2 = _mm_add_ps(sum2, _mm_mul_ps(_mm_loadu_ps(pSrc + 2), pFil[0]));
|
||||||
|
|
||||||
|
sum1 = _mm_add_ps(sum1, _mm_mul_ps(_mm_loadu_ps(pSrc + 4), pFil[1]));
|
||||||
|
sum2 = _mm_add_ps(sum2, _mm_mul_ps(_mm_loadu_ps(pSrc + 6), pFil[1]));
|
||||||
|
|
||||||
|
sum1 = _mm_add_ps(sum1, _mm_mul_ps(_mm_loadu_ps(pSrc + 8) , pFil[2]));
|
||||||
|
sum2 = _mm_add_ps(sum2, _mm_mul_ps(_mm_loadu_ps(pSrc + 10), pFil[2]));
|
||||||
|
|
||||||
|
sum1 = _mm_add_ps(sum1, _mm_mul_ps(_mm_loadu_ps(pSrc + 12), pFil[3]));
|
||||||
|
sum2 = _mm_add_ps(sum2, _mm_mul_ps(_mm_loadu_ps(pSrc + 14), pFil[3]));
|
||||||
|
|
||||||
|
pSrc += 16;
|
||||||
|
pFil += 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now sum1 and sum2 both have a filtered 2-channel sample each, but we still need
|
||||||
|
// to sum the two hi- and lo-floats of these registers together.
|
||||||
|
|
||||||
|
// post-shuffle & add the filtered values and store to dest.
|
||||||
|
_mm_storeu_ps(dest, _mm_add_ps(
|
||||||
|
_mm_shuffle_ps(sum1, sum2, _MM_SHUFFLE(1,0,3,2)), // s2_1 s2_0 s1_3 s1_2
|
||||||
|
_mm_shuffle_ps(sum1, sum2, _MM_SHUFFLE(3,2,1,0)) // s2_3 s2_2 s1_1 s1_0
|
||||||
|
));
|
||||||
|
source += 4;
|
||||||
|
dest += 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ideas for further improvement:
|
||||||
|
// 1. If it could be guaranteed that 'source' were always aligned to 16-byte
|
||||||
|
// boundary, a faster aligned '_mm_load_ps' instruction could be used.
|
||||||
|
// 2. If it could be guaranteed that 'dest' were always aligned to 16-byte
|
||||||
|
// boundary, a faster '_mm_store_ps' instruction could be used.
|
||||||
|
|
||||||
|
return (uint)count;
|
||||||
|
|
||||||
|
/* original routine in C-language. please notice the C-version has differently
|
||||||
|
organized coefficients though.
|
||||||
|
double suml1, suml2;
|
||||||
|
double sumr1, sumr2;
|
||||||
|
uint i, j;
|
||||||
|
|
||||||
|
for (j = 0; j < count; j += 2)
|
||||||
|
{
|
||||||
|
const float *ptr;
|
||||||
|
const float *pFil;
|
||||||
|
|
||||||
|
suml1 = sumr1 = 0.0;
|
||||||
|
suml2 = sumr2 = 0.0;
|
||||||
|
ptr = src;
|
||||||
|
pFil = filterCoeffs;
|
||||||
|
for (i = 0; i < lengthLocal; i ++)
|
||||||
|
{
|
||||||
|
// unroll loop for efficiency.
|
||||||
|
|
||||||
|
suml1 += ptr[0] * pFil[0] +
|
||||||
|
ptr[2] * pFil[2] +
|
||||||
|
ptr[4] * pFil[4] +
|
||||||
|
ptr[6] * pFil[6];
|
||||||
|
|
||||||
|
sumr1 += ptr[1] * pFil[1] +
|
||||||
|
ptr[3] * pFil[3] +
|
||||||
|
ptr[5] * pFil[5] +
|
||||||
|
ptr[7] * pFil[7];
|
||||||
|
|
||||||
|
suml2 += ptr[8] * pFil[0] +
|
||||||
|
ptr[10] * pFil[2] +
|
||||||
|
ptr[12] * pFil[4] +
|
||||||
|
ptr[14] * pFil[6];
|
||||||
|
|
||||||
|
sumr2 += ptr[9] * pFil[1] +
|
||||||
|
ptr[11] * pFil[3] +
|
||||||
|
ptr[13] * pFil[5] +
|
||||||
|
ptr[15] * pFil[7];
|
||||||
|
|
||||||
|
ptr += 16;
|
||||||
|
pFil += 8;
|
||||||
|
}
|
||||||
|
dest[0] = (float)suml1;
|
||||||
|
dest[1] = (float)sumr1;
|
||||||
|
dest[2] = (float)suml2;
|
||||||
|
dest[3] = (float)sumr2;
|
||||||
|
|
||||||
|
src += 4;
|
||||||
|
dest += 4;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* Similar routine in assembly, again obsoleted due to maintainability
|
||||||
|
_asm
|
||||||
|
{
|
||||||
|
// Very important note: data in 'src' _must_ be aligned to
|
||||||
|
// 16-byte boundary!
|
||||||
|
mov edx, count
|
||||||
|
mov ebx, dword ptr src
|
||||||
|
mov eax, dword ptr dest
|
||||||
|
shr edx, 1
|
||||||
|
|
||||||
|
loop1:
|
||||||
|
// "outer loop" : during each round 2*2 output samples are calculated
|
||||||
|
|
||||||
|
// give prefetch hints to CPU of what data are to be needed soonish
|
||||||
|
prefetcht0 [ebx]
|
||||||
|
prefetcht0 [filterCoeffsLocal]
|
||||||
|
|
||||||
|
mov esi, ebx
|
||||||
|
mov edi, filterCoeffsLocal
|
||||||
|
xorps xmm0, xmm0
|
||||||
|
xorps xmm1, xmm1
|
||||||
|
mov ecx, lengthLocal
|
||||||
|
|
||||||
|
loop2:
|
||||||
|
// "inner loop" : during each round eight FIR filter taps are evaluated for 2*2 samples
|
||||||
|
prefetcht0 [esi + 32] // give a prefetch hint to CPU what data are to be needed soonish
|
||||||
|
prefetcht0 [edi + 32] // give a prefetch hint to CPU what data are to be needed soonish
|
||||||
|
|
||||||
|
movups xmm2, [esi] // possibly unaligned load
|
||||||
|
movups xmm3, [esi + 8] // possibly unaligned load
|
||||||
|
mulps xmm2, [edi]
|
||||||
|
mulps xmm3, [edi]
|
||||||
|
addps xmm0, xmm2
|
||||||
|
addps xmm1, xmm3
|
||||||
|
|
||||||
|
movups xmm4, [esi + 16] // possibly unaligned load
|
||||||
|
movups xmm5, [esi + 24] // possibly unaligned load
|
||||||
|
mulps xmm4, [edi + 16]
|
||||||
|
mulps xmm5, [edi + 16]
|
||||||
|
addps xmm0, xmm4
|
||||||
|
addps xmm1, xmm5
|
||||||
|
|
||||||
|
prefetcht0 [esi + 64] // give a prefetch hint to CPU what data are to be needed soonish
|
||||||
|
prefetcht0 [edi + 64] // give a prefetch hint to CPU what data are to be needed soonish
|
||||||
|
|
||||||
|
movups xmm6, [esi + 32] // possibly unaligned load
|
||||||
|
movups xmm7, [esi + 40] // possibly unaligned load
|
||||||
|
mulps xmm6, [edi + 32]
|
||||||
|
mulps xmm7, [edi + 32]
|
||||||
|
addps xmm0, xmm6
|
||||||
|
addps xmm1, xmm7
|
||||||
|
|
||||||
|
movups xmm4, [esi + 48] // possibly unaligned load
|
||||||
|
movups xmm5, [esi + 56] // possibly unaligned load
|
||||||
|
mulps xmm4, [edi + 48]
|
||||||
|
mulps xmm5, [edi + 48]
|
||||||
|
addps xmm0, xmm4
|
||||||
|
addps xmm1, xmm5
|
||||||
|
|
||||||
|
add esi, 64
|
||||||
|
add edi, 64
|
||||||
|
dec ecx
|
||||||
|
jnz loop2
|
||||||
|
|
||||||
|
// Now xmm0 and xmm1 both have a filtered 2-channel sample each, but we still need
|
||||||
|
// to sum the two hi- and lo-floats of these registers together.
|
||||||
|
|
||||||
|
movhlps xmm2, xmm0 // xmm2 = xmm2_3 xmm2_2 xmm0_3 xmm0_2
|
||||||
|
movlhps xmm2, xmm1 // xmm2 = xmm1_1 xmm1_0 xmm0_3 xmm0_2
|
||||||
|
shufps xmm0, xmm1, 0xe4 // xmm0 = xmm1_3 xmm1_2 xmm0_1 xmm0_0
|
||||||
|
addps xmm0, xmm2
|
||||||
|
|
||||||
|
movaps [eax], xmm0
|
||||||
|
add ebx, 16
|
||||||
|
add eax, 16
|
||||||
|
|
||||||
|
dec edx
|
||||||
|
jnz loop1
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // ALLOW_SSE
|
|
@ -0,0 +1,43 @@
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------
|
||||||
|
|
||||||
|
This program, "bzip2", the associated library "libbzip2", and all
|
||||||
|
documentation, are copyright (C) 1996-2006 Julian R Seward. All
|
||||||
|
rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions
|
||||||
|
are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
2. The origin of this software must not be misrepresented; you must
|
||||||
|
not claim that you wrote the original software. If you use this
|
||||||
|
software in a product, an acknowledgment in the product
|
||||||
|
documentation would be appreciated but is not required.
|
||||||
|
|
||||||
|
3. Altered source versions must be plainly marked as such, and must
|
||||||
|
not be misrepresented as being the original software.
|
||||||
|
|
||||||
|
4. The name of the author may not be used to endorse or promote
|
||||||
|
products derived from this software without specific prior written
|
||||||
|
permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
|
||||||
|
|
||||||
|
Julian Seward, Cambridge, UK.
|
||||||
|
jseward@bzip.org
|
||||||
|
bzip2/libbzip2 version 1.0.4 of 20 December 2006
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------
|
|
@ -0,0 +1,205 @@
|
||||||
|
|
||||||
|
This is the README for bzip2/libzip2.
|
||||||
|
This version is fully compatible with the previous public releases.
|
||||||
|
|
||||||
|
------------------------------------------------------------------
|
||||||
|
This file is part of bzip2/libbzip2, a program and library for
|
||||||
|
lossless, block-sorting data compression.
|
||||||
|
|
||||||
|
bzip2/libbzip2 version 1.0.4 of 20 December 2006
|
||||||
|
Copyright (C) 1996-2006 Julian Seward <jseward@bzip.org>
|
||||||
|
|
||||||
|
Please read the WARNING, DISCLAIMER and PATENTS sections in this file.
|
||||||
|
|
||||||
|
This program is released under the terms of the license contained
|
||||||
|
in the file LICENSE.
|
||||||
|
------------------------------------------------------------------
|
||||||
|
|
||||||
|
Complete documentation is available in Postscript form (manual.ps),
|
||||||
|
PDF (manual.pdf) or html (manual.html). A plain-text version of the
|
||||||
|
manual page is available as bzip2.txt.
|
||||||
|
|
||||||
|
|
||||||
|
HOW TO BUILD -- UNIX
|
||||||
|
|
||||||
|
Type 'make'. This builds the library libbz2.a and then the programs
|
||||||
|
bzip2 and bzip2recover. Six self-tests are run. If the self-tests
|
||||||
|
complete ok, carry on to installation:
|
||||||
|
|
||||||
|
To install in /usr/local/bin, /usr/local/lib, /usr/local/man and
|
||||||
|
/usr/local/include, type
|
||||||
|
|
||||||
|
make install
|
||||||
|
|
||||||
|
To install somewhere else, eg, /xxx/yyy/{bin,lib,man,include}, type
|
||||||
|
|
||||||
|
make install PREFIX=/xxx/yyy
|
||||||
|
|
||||||
|
If you are (justifiably) paranoid and want to see what 'make install'
|
||||||
|
is going to do, you can first do
|
||||||
|
|
||||||
|
make -n install or
|
||||||
|
make -n install PREFIX=/xxx/yyy respectively.
|
||||||
|
|
||||||
|
The -n instructs make to show the commands it would execute, but not
|
||||||
|
actually execute them.
|
||||||
|
|
||||||
|
|
||||||
|
HOW TO BUILD -- UNIX, shared library libbz2.so.
|
||||||
|
|
||||||
|
Do 'make -f Makefile-libbz2_so'. This Makefile seems to work for
|
||||||
|
Linux-ELF (RedHat 7.2 on an x86 box), with gcc. I make no claims
|
||||||
|
that it works for any other platform, though I suspect it probably
|
||||||
|
will work for most platforms employing both ELF and gcc.
|
||||||
|
|
||||||
|
bzip2-shared, a client of the shared library, is also built, but not
|
||||||
|
self-tested. So I suggest you also build using the normal Makefile,
|
||||||
|
since that conducts a self-test. A second reason to prefer the
|
||||||
|
version statically linked to the library is that, on x86 platforms,
|
||||||
|
building shared objects makes a valuable register (%ebx) unavailable
|
||||||
|
to gcc, resulting in a slowdown of 10%-20%, at least for bzip2.
|
||||||
|
|
||||||
|
Important note for people upgrading .so's from 0.9.0/0.9.5 to version
|
||||||
|
1.0.X. All the functions in the library have been renamed, from (eg)
|
||||||
|
bzCompress to BZ2_bzCompress, to avoid namespace pollution.
|
||||||
|
Unfortunately this means that the libbz2.so created by
|
||||||
|
Makefile-libbz2_so will not work with any program which used an older
|
||||||
|
version of the library. I do encourage library clients to make the
|
||||||
|
effort to upgrade to use version 1.0, since it is both faster and more
|
||||||
|
robust than previous versions.
|
||||||
|
|
||||||
|
|
||||||
|
HOW TO BUILD -- Windows 95, NT, DOS, Mac, etc.
|
||||||
|
|
||||||
|
It's difficult for me to support compilation on all these platforms.
|
||||||
|
My approach is to collect binaries for these platforms, and put them
|
||||||
|
on the master web site (http://www.bzip.org). Look there. However
|
||||||
|
(FWIW), bzip2-1.0.X is very standard ANSI C and should compile
|
||||||
|
unmodified with MS Visual C. If you have difficulties building, you
|
||||||
|
might want to read README.COMPILATION.PROBLEMS.
|
||||||
|
|
||||||
|
At least using MS Visual C++ 6, you can build from the unmodified
|
||||||
|
sources by issuing, in a command shell:
|
||||||
|
|
||||||
|
nmake -f makefile.msc
|
||||||
|
|
||||||
|
(you may need to first run the MSVC-provided script VCVARS32.BAT
|
||||||
|
so as to set up paths to the MSVC tools correctly).
|
||||||
|
|
||||||
|
|
||||||
|
VALIDATION
|
||||||
|
|
||||||
|
Correct operation, in the sense that a compressed file can always be
|
||||||
|
decompressed to reproduce the original, is obviously of paramount
|
||||||
|
importance. To validate bzip2, I used a modified version of Mark
|
||||||
|
Nelson's churn program. Churn is an automated test driver which
|
||||||
|
recursively traverses a directory structure, using bzip2 to compress
|
||||||
|
and then decompress each file it encounters, and checking that the
|
||||||
|
decompressed data is the same as the original.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Please read and be aware of the following:
|
||||||
|
|
||||||
|
WARNING:
|
||||||
|
|
||||||
|
This program and library (attempts to) compress data by
|
||||||
|
performing several non-trivial transformations on it.
|
||||||
|
Unless you are 100% familiar with *all* the algorithms
|
||||||
|
contained herein, and with the consequences of modifying them,
|
||||||
|
you should NOT meddle with the compression or decompression
|
||||||
|
machinery. Incorrect changes can and very likely *will*
|
||||||
|
lead to disastrous loss of data.
|
||||||
|
|
||||||
|
|
||||||
|
DISCLAIMER:
|
||||||
|
|
||||||
|
I TAKE NO RESPONSIBILITY FOR ANY LOSS OF DATA ARISING FROM THE
|
||||||
|
USE OF THIS PROGRAM/LIBRARY, HOWSOEVER CAUSED.
|
||||||
|
|
||||||
|
Every compression of a file implies an assumption that the
|
||||||
|
compressed file can be decompressed to reproduce the original.
|
||||||
|
Great efforts in design, coding and testing have been made to
|
||||||
|
ensure that this program works correctly. However, the complexity
|
||||||
|
of the algorithms, and, in particular, the presence of various
|
||||||
|
special cases in the code which occur with very low but non-zero
|
||||||
|
probability make it impossible to rule out the possibility of bugs
|
||||||
|
remaining in the program. DO NOT COMPRESS ANY DATA WITH THIS
|
||||||
|
PROGRAM UNLESS YOU ARE PREPARED TO ACCEPT THE POSSIBILITY, HOWEVER
|
||||||
|
SMALL, THAT THE DATA WILL NOT BE RECOVERABLE.
|
||||||
|
|
||||||
|
That is not to say this program is inherently unreliable.
|
||||||
|
Indeed, I very much hope the opposite is true. bzip2/libbzip2
|
||||||
|
has been carefully constructed and extensively tested.
|
||||||
|
|
||||||
|
|
||||||
|
PATENTS:
|
||||||
|
|
||||||
|
To the best of my knowledge, bzip2/libbzip2 does not use any
|
||||||
|
patented algorithms. However, I do not have the resources
|
||||||
|
to carry out a patent search. Therefore I cannot give any
|
||||||
|
guarantee of the above statement.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
WHAT'S NEW IN 0.9.0 (as compared to 0.1pl2) ?
|
||||||
|
|
||||||
|
* Approx 10% faster compression, 30% faster decompression
|
||||||
|
* -t (test mode) is a lot quicker
|
||||||
|
* Can decompress concatenated compressed files
|
||||||
|
* Programming interface, so programs can directly read/write .bz2 files
|
||||||
|
* Less restrictive (BSD-style) licensing
|
||||||
|
* Flag handling more compatible with GNU gzip
|
||||||
|
* Much more documentation, i.e., a proper user manual
|
||||||
|
* Hopefully, improved portability (at least of the library)
|
||||||
|
|
||||||
|
WHAT'S NEW IN 0.9.5 ?
|
||||||
|
|
||||||
|
* Compression speed is much less sensitive to the input
|
||||||
|
data than in previous versions. Specifically, the very
|
||||||
|
slow performance caused by repetitive data is fixed.
|
||||||
|
* Many small improvements in file and flag handling.
|
||||||
|
* A Y2K statement.
|
||||||
|
|
||||||
|
WHAT'S NEW IN 1.0.0 ?
|
||||||
|
|
||||||
|
See the CHANGES file.
|
||||||
|
|
||||||
|
WHAT'S NEW IN 1.0.2 ?
|
||||||
|
|
||||||
|
See the CHANGES file.
|
||||||
|
|
||||||
|
WHAT'S NEW IN 1.0.3 ?
|
||||||
|
|
||||||
|
See the CHANGES file.
|
||||||
|
|
||||||
|
WHAT'S NEW IN 1.0.4 ?
|
||||||
|
|
||||||
|
See the CHANGES file.
|
||||||
|
|
||||||
|
|
||||||
|
I hope you find bzip2 useful. Feel free to contact me at
|
||||||
|
jseward@bzip.org
|
||||||
|
if you have any suggestions or queries. Many people mailed me with
|
||||||
|
comments, suggestions and patches after the releases of bzip-0.15,
|
||||||
|
bzip-0.21, and bzip2 versions 0.1pl2, 0.9.0, 0.9.5, 1.0.0, 1.0.1,
|
||||||
|
1.0.2 and 1.0.3, and the changes in bzip2 are largely a result of this
|
||||||
|
feedback. I thank you for your comments.
|
||||||
|
|
||||||
|
bzip2's "home" is http://www.bzip.org/
|
||||||
|
|
||||||
|
Julian Seward
|
||||||
|
jseward@bzip.org
|
||||||
|
Cambridge, UK.
|
||||||
|
|
||||||
|
18 July 1996 (version 0.15)
|
||||||
|
25 August 1996 (version 0.21)
|
||||||
|
7 August 1997 (bzip2, version 0.1)
|
||||||
|
29 August 1997 (bzip2, version 0.1pl2)
|
||||||
|
23 August 1998 (bzip2, version 0.9.0)
|
||||||
|
8 June 1999 (bzip2, version 0.9.5)
|
||||||
|
4 Sept 1999 (bzip2, version 0.9.5d)
|
||||||
|
5 May 2000 (bzip2, version 1.0pre8)
|
||||||
|
30 December 2001 (bzip2, version 1.0.2pre1)
|
||||||
|
15 February 2005 (bzip2, version 1.0.3)
|
||||||
|
20 December 2006 (bzip2, version 1.0.4)
|
|
@ -0,0 +1,282 @@
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------*/
|
||||||
|
/*--- Public header file for the library. ---*/
|
||||||
|
/*--- bzlib.h ---*/
|
||||||
|
/*-------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------
|
||||||
|
This file is part of bzip2/libbzip2, a program and library for
|
||||||
|
lossless, block-sorting data compression.
|
||||||
|
|
||||||
|
bzip2/libbzip2 version 1.0.4 of 20 December 2006
|
||||||
|
Copyright (C) 1996-2006 Julian Seward <jseward@bzip.org>
|
||||||
|
|
||||||
|
Please read the WARNING, DISCLAIMER and PATENTS sections in the
|
||||||
|
README file.
|
||||||
|
|
||||||
|
This program is released under the terms of the license contained
|
||||||
|
in the file LICENSE.
|
||||||
|
------------------------------------------------------------------ */
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef _BZLIB_H
|
||||||
|
#define _BZLIB_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define BZ_RUN 0
|
||||||
|
#define BZ_FLUSH 1
|
||||||
|
#define BZ_FINISH 2
|
||||||
|
|
||||||
|
#define BZ_OK 0
|
||||||
|
#define BZ_RUN_OK 1
|
||||||
|
#define BZ_FLUSH_OK 2
|
||||||
|
#define BZ_FINISH_OK 3
|
||||||
|
#define BZ_STREAM_END 4
|
||||||
|
#define BZ_SEQUENCE_ERROR (-1)
|
||||||
|
#define BZ_PARAM_ERROR (-2)
|
||||||
|
#define BZ_MEM_ERROR (-3)
|
||||||
|
#define BZ_DATA_ERROR (-4)
|
||||||
|
#define BZ_DATA_ERROR_MAGIC (-5)
|
||||||
|
#define BZ_IO_ERROR (-6)
|
||||||
|
#define BZ_UNEXPECTED_EOF (-7)
|
||||||
|
#define BZ_OUTBUFF_FULL (-8)
|
||||||
|
#define BZ_CONFIG_ERROR (-9)
|
||||||
|
|
||||||
|
typedef
|
||||||
|
struct {
|
||||||
|
char *next_in;
|
||||||
|
unsigned int avail_in;
|
||||||
|
unsigned int total_in_lo32;
|
||||||
|
unsigned int total_in_hi32;
|
||||||
|
|
||||||
|
char *next_out;
|
||||||
|
unsigned int avail_out;
|
||||||
|
unsigned int total_out_lo32;
|
||||||
|
unsigned int total_out_hi32;
|
||||||
|
|
||||||
|
void *state;
|
||||||
|
|
||||||
|
void *(*bzalloc)(void *,int,int);
|
||||||
|
void (*bzfree)(void *,void *);
|
||||||
|
void *opaque;
|
||||||
|
}
|
||||||
|
bz_stream;
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef BZ_IMPORT
|
||||||
|
#define BZ_EXPORT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef BZ_NO_STDIO
|
||||||
|
/* Need a definitition for FILE */
|
||||||
|
#include <stdio.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
# include <windows.h>
|
||||||
|
# ifdef small
|
||||||
|
/* windows.h define small to char */
|
||||||
|
# undef small
|
||||||
|
# endif
|
||||||
|
# ifdef BZ_EXPORT
|
||||||
|
# define BZ_API(func) WINAPI func
|
||||||
|
# define BZ_EXTERN extern
|
||||||
|
# else
|
||||||
|
/* import windows dll dynamically */
|
||||||
|
# define BZ_API(func) (WINAPI * func)
|
||||||
|
# define BZ_EXTERN
|
||||||
|
# endif
|
||||||
|
#else
|
||||||
|
# define BZ_API(func) func
|
||||||
|
# define BZ_EXTERN extern
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*-- Core (low-level) library functions --*/
|
||||||
|
|
||||||
|
BZ_EXTERN int BZ_API(BZ2_bzCompressInit) (
|
||||||
|
bz_stream* strm,
|
||||||
|
int blockSize100k,
|
||||||
|
int verbosity,
|
||||||
|
int workFactor
|
||||||
|
);
|
||||||
|
|
||||||
|
BZ_EXTERN int BZ_API(BZ2_bzCompress) (
|
||||||
|
bz_stream* strm,
|
||||||
|
int action
|
||||||
|
);
|
||||||
|
|
||||||
|
BZ_EXTERN int BZ_API(BZ2_bzCompressEnd) (
|
||||||
|
bz_stream* strm
|
||||||
|
);
|
||||||
|
|
||||||
|
BZ_EXTERN int BZ_API(BZ2_bzDecompressInit) (
|
||||||
|
bz_stream *strm,
|
||||||
|
int verbosity,
|
||||||
|
int small
|
||||||
|
);
|
||||||
|
|
||||||
|
BZ_EXTERN int BZ_API(BZ2_bzDecompress) (
|
||||||
|
bz_stream* strm
|
||||||
|
);
|
||||||
|
|
||||||
|
BZ_EXTERN int BZ_API(BZ2_bzDecompressEnd) (
|
||||||
|
bz_stream *strm
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*-- High(er) level library functions --*/
|
||||||
|
|
||||||
|
#ifndef BZ_NO_STDIO
|
||||||
|
#define BZ_MAX_UNUSED 5000
|
||||||
|
|
||||||
|
typedef void BZFILE;
|
||||||
|
|
||||||
|
BZ_EXTERN BZFILE* BZ_API(BZ2_bzReadOpen) (
|
||||||
|
int* bzerror,
|
||||||
|
FILE* f,
|
||||||
|
int verbosity,
|
||||||
|
int small,
|
||||||
|
void* unused,
|
||||||
|
int nUnused
|
||||||
|
);
|
||||||
|
|
||||||
|
BZ_EXTERN void BZ_API(BZ2_bzReadClose) (
|
||||||
|
int* bzerror,
|
||||||
|
BZFILE* b
|
||||||
|
);
|
||||||
|
|
||||||
|
BZ_EXTERN void BZ_API(BZ2_bzReadGetUnused) (
|
||||||
|
int* bzerror,
|
||||||
|
BZFILE* b,
|
||||||
|
void** unused,
|
||||||
|
int* nUnused
|
||||||
|
);
|
||||||
|
|
||||||
|
BZ_EXTERN int BZ_API(BZ2_bzRead) (
|
||||||
|
int* bzerror,
|
||||||
|
BZFILE* b,
|
||||||
|
void* buf,
|
||||||
|
int len
|
||||||
|
);
|
||||||
|
|
||||||
|
BZ_EXTERN BZFILE* BZ_API(BZ2_bzWriteOpen) (
|
||||||
|
int* bzerror,
|
||||||
|
FILE* f,
|
||||||
|
int blockSize100k,
|
||||||
|
int verbosity,
|
||||||
|
int workFactor
|
||||||
|
);
|
||||||
|
|
||||||
|
BZ_EXTERN void BZ_API(BZ2_bzWrite) (
|
||||||
|
int* bzerror,
|
||||||
|
BZFILE* b,
|
||||||
|
void* buf,
|
||||||
|
int len
|
||||||
|
);
|
||||||
|
|
||||||
|
BZ_EXTERN void BZ_API(BZ2_bzWriteClose) (
|
||||||
|
int* bzerror,
|
||||||
|
BZFILE* b,
|
||||||
|
int abandon,
|
||||||
|
unsigned int* nbytes_in,
|
||||||
|
unsigned int* nbytes_out
|
||||||
|
);
|
||||||
|
|
||||||
|
BZ_EXTERN void BZ_API(BZ2_bzWriteClose64) (
|
||||||
|
int* bzerror,
|
||||||
|
BZFILE* b,
|
||||||
|
int abandon,
|
||||||
|
unsigned int* nbytes_in_lo32,
|
||||||
|
unsigned int* nbytes_in_hi32,
|
||||||
|
unsigned int* nbytes_out_lo32,
|
||||||
|
unsigned int* nbytes_out_hi32
|
||||||
|
);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*-- Utility functions --*/
|
||||||
|
|
||||||
|
BZ_EXTERN int BZ_API(BZ2_bzBuffToBuffCompress) (
|
||||||
|
char* dest,
|
||||||
|
unsigned int* destLen,
|
||||||
|
char* source,
|
||||||
|
unsigned int sourceLen,
|
||||||
|
int blockSize100k,
|
||||||
|
int verbosity,
|
||||||
|
int workFactor
|
||||||
|
);
|
||||||
|
|
||||||
|
BZ_EXTERN int BZ_API(BZ2_bzBuffToBuffDecompress) (
|
||||||
|
char* dest,
|
||||||
|
unsigned int* destLen,
|
||||||
|
char* source,
|
||||||
|
unsigned int sourceLen,
|
||||||
|
int small,
|
||||||
|
int verbosity
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
/*--
|
||||||
|
Code contributed by Yoshioka Tsuneo (tsuneo@rr.iij4u.or.jp)
|
||||||
|
to support better zlib compatibility.
|
||||||
|
This code is not _officially_ part of libbzip2 (yet);
|
||||||
|
I haven't tested it, documented it, or considered the
|
||||||
|
threading-safeness of it.
|
||||||
|
If this code breaks, please contact both Yoshioka and me.
|
||||||
|
--*/
|
||||||
|
|
||||||
|
BZ_EXTERN const char * BZ_API(BZ2_bzlibVersion) (
|
||||||
|
void
|
||||||
|
);
|
||||||
|
|
||||||
|
#ifndef BZ_NO_STDIO
|
||||||
|
BZ_EXTERN BZFILE * BZ_API(BZ2_bzopen) (
|
||||||
|
const char *path,
|
||||||
|
const char *mode
|
||||||
|
);
|
||||||
|
|
||||||
|
BZ_EXTERN BZFILE * BZ_API(BZ2_bzdopen) (
|
||||||
|
int fd,
|
||||||
|
const char *mode
|
||||||
|
);
|
||||||
|
|
||||||
|
BZ_EXTERN int BZ_API(BZ2_bzread) (
|
||||||
|
BZFILE* b,
|
||||||
|
void* buf,
|
||||||
|
int len
|
||||||
|
);
|
||||||
|
|
||||||
|
BZ_EXTERN int BZ_API(BZ2_bzwrite) (
|
||||||
|
BZFILE* b,
|
||||||
|
void* buf,
|
||||||
|
int len
|
||||||
|
);
|
||||||
|
|
||||||
|
BZ_EXTERN int BZ_API(BZ2_bzflush) (
|
||||||
|
BZFILE* b
|
||||||
|
);
|
||||||
|
|
||||||
|
BZ_EXTERN void BZ_API(BZ2_bzclose) (
|
||||||
|
BZFILE* b
|
||||||
|
);
|
||||||
|
|
||||||
|
BZ_EXTERN const char * BZ_API(BZ2_bzerror) (
|
||||||
|
BZFILE *b,
|
||||||
|
int *errnum
|
||||||
|
);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------*/
|
||||||
|
/*--- end bzlib.h ---*/
|
||||||
|
/*-------------------------------------------------------------*/
|
|
@ -0,0 +1,503 @@
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------*/
|
||||||
|
/*--- Private header file for the library. ---*/
|
||||||
|
/*--- bzlib_private.h ---*/
|
||||||
|
/*-------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------
|
||||||
|
This file is part of bzip2/libbzip2, a program and library for
|
||||||
|
lossless, block-sorting data compression.
|
||||||
|
|
||||||
|
bzip2/libbzip2 version 1.0.4 of 20 December 2006
|
||||||
|
Copyright (C) 1996-2006 Julian Seward <jseward@bzip.org>
|
||||||
|
|
||||||
|
Please read the WARNING, DISCLAIMER and PATENTS sections in the
|
||||||
|
README file.
|
||||||
|
|
||||||
|
This program is released under the terms of the license contained
|
||||||
|
in the file LICENSE.
|
||||||
|
------------------------------------------------------------------ */
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef _BZLIB_PRIVATE_H
|
||||||
|
#define _BZLIB_PRIVATE_H
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#ifndef BZ_NO_STDIO
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <string.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "bzlib.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*-- General stuff. --*/
|
||||||
|
|
||||||
|
#define BZ_VERSION "1.0.4, 20-Dec-2006"
|
||||||
|
|
||||||
|
typedef char Char;
|
||||||
|
typedef unsigned char Bool;
|
||||||
|
typedef unsigned char UChar;
|
||||||
|
typedef int Int32;
|
||||||
|
typedef unsigned int UInt32;
|
||||||
|
typedef short Int16;
|
||||||
|
typedef unsigned short UInt16;
|
||||||
|
|
||||||
|
#define True ((Bool)1)
|
||||||
|
#define False ((Bool)0)
|
||||||
|
|
||||||
|
#ifndef __GNUC__
|
||||||
|
#define __inline__ /* */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef BZ_NO_STDIO
|
||||||
|
|
||||||
|
extern void BZ2_bz__AssertH__fail ( int errcode );
|
||||||
|
#define AssertH(cond,errcode) \
|
||||||
|
{ if (!(cond)) BZ2_bz__AssertH__fail ( errcode ); }
|
||||||
|
|
||||||
|
#if BZ_DEBUG
|
||||||
|
#define AssertD(cond,msg) \
|
||||||
|
{ if (!(cond)) { \
|
||||||
|
fprintf ( stderr, \
|
||||||
|
"\n\nlibbzip2(debug build): internal error\n\t%s\n", msg );\
|
||||||
|
exit(1); \
|
||||||
|
}}
|
||||||
|
#else
|
||||||
|
#define AssertD(cond,msg) /* */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define VPrintf0(zf) \
|
||||||
|
fprintf(stderr,zf)
|
||||||
|
#define VPrintf1(zf,za1) \
|
||||||
|
fprintf(stderr,zf,za1)
|
||||||
|
#define VPrintf2(zf,za1,za2) \
|
||||||
|
fprintf(stderr,zf,za1,za2)
|
||||||
|
#define VPrintf3(zf,za1,za2,za3) \
|
||||||
|
fprintf(stderr,zf,za1,za2,za3)
|
||||||
|
#define VPrintf4(zf,za1,za2,za3,za4) \
|
||||||
|
fprintf(stderr,zf,za1,za2,za3,za4)
|
||||||
|
#define VPrintf5(zf,za1,za2,za3,za4,za5) \
|
||||||
|
fprintf(stderr,zf,za1,za2,za3,za4,za5)
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
extern void bz_internal_error ( int errcode );
|
||||||
|
#define AssertH(cond,errcode) \
|
||||||
|
{ if (!(cond)) bz_internal_error ( errcode ); }
|
||||||
|
#define AssertD(cond,msg) do { } while (0)
|
||||||
|
#define VPrintf0(zf) do { } while (0)
|
||||||
|
#define VPrintf1(zf,za1) do { } while (0)
|
||||||
|
#define VPrintf2(zf,za1,za2) do { } while (0)
|
||||||
|
#define VPrintf3(zf,za1,za2,za3) do { } while (0)
|
||||||
|
#define VPrintf4(zf,za1,za2,za3,za4) do { } while (0)
|
||||||
|
#define VPrintf5(zf,za1,za2,za3,za4,za5) do { } while (0)
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#define BZALLOC(nnn) (strm->bzalloc)(strm->opaque,(nnn),1)
|
||||||
|
#define BZFREE(ppp) (strm->bzfree)(strm->opaque,(ppp))
|
||||||
|
|
||||||
|
|
||||||
|
/*-- Header bytes. --*/
|
||||||
|
|
||||||
|
#define BZ_HDR_B 0x42 /* 'B' */
|
||||||
|
#define BZ_HDR_Z 0x5a /* 'Z' */
|
||||||
|
#define BZ_HDR_h 0x68 /* 'h' */
|
||||||
|
#define BZ_HDR_0 0x30 /* '0' */
|
||||||
|
|
||||||
|
/*-- Constants for the back end. --*/
|
||||||
|
|
||||||
|
#define BZ_MAX_ALPHA_SIZE 258
|
||||||
|
#define BZ_MAX_CODE_LEN 23
|
||||||
|
|
||||||
|
#define BZ_RUNA 0
|
||||||
|
#define BZ_RUNB 1
|
||||||
|
|
||||||
|
#define BZ_N_GROUPS 6
|
||||||
|
#define BZ_G_SIZE 50
|
||||||
|
#define BZ_N_ITERS 4
|
||||||
|
|
||||||
|
#define BZ_MAX_SELECTORS (2 + (900000 / BZ_G_SIZE))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*-- Stuff for randomising repetitive blocks. --*/
|
||||||
|
|
||||||
|
extern Int32 BZ2_rNums[512];
|
||||||
|
|
||||||
|
#define BZ_RAND_DECLS \
|
||||||
|
Int32 rNToGo; \
|
||||||
|
Int32 rTPos \
|
||||||
|
|
||||||
|
#define BZ_RAND_INIT_MASK \
|
||||||
|
s->rNToGo = 0; \
|
||||||
|
s->rTPos = 0 \
|
||||||
|
|
||||||
|
#define BZ_RAND_MASK ((s->rNToGo == 1) ? 1 : 0)
|
||||||
|
|
||||||
|
#define BZ_RAND_UPD_MASK \
|
||||||
|
if (s->rNToGo == 0) { \
|
||||||
|
s->rNToGo = BZ2_rNums[s->rTPos]; \
|
||||||
|
s->rTPos++; \
|
||||||
|
if (s->rTPos == 512) s->rTPos = 0; \
|
||||||
|
} \
|
||||||
|
s->rNToGo--;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*-- Stuff for doing CRCs. --*/
|
||||||
|
|
||||||
|
extern UInt32 BZ2_crc32Table[256];
|
||||||
|
|
||||||
|
#define BZ_INITIALISE_CRC(crcVar) \
|
||||||
|
{ \
|
||||||
|
crcVar = 0xffffffffL; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define BZ_FINALISE_CRC(crcVar) \
|
||||||
|
{ \
|
||||||
|
crcVar = ~(crcVar); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define BZ_UPDATE_CRC(crcVar,cha) \
|
||||||
|
{ \
|
||||||
|
crcVar = (crcVar << 8) ^ \
|
||||||
|
BZ2_crc32Table[(crcVar >> 24) ^ \
|
||||||
|
((UChar)cha)]; \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*-- States and modes for compression. --*/
|
||||||
|
|
||||||
|
#define BZ_M_IDLE 1
|
||||||
|
#define BZ_M_RUNNING 2
|
||||||
|
#define BZ_M_FLUSHING 3
|
||||||
|
#define BZ_M_FINISHING 4
|
||||||
|
|
||||||
|
#define BZ_S_OUTPUT 1
|
||||||
|
#define BZ_S_INPUT 2
|
||||||
|
|
||||||
|
#define BZ_N_RADIX 2
|
||||||
|
#define BZ_N_QSORT 12
|
||||||
|
#define BZ_N_SHELL 18
|
||||||
|
#define BZ_N_OVERSHOOT (BZ_N_RADIX + BZ_N_QSORT + BZ_N_SHELL + 2)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*-- Structure holding all the compression-side stuff. --*/
|
||||||
|
|
||||||
|
typedef
|
||||||
|
struct {
|
||||||
|
/* pointer back to the struct bz_stream */
|
||||||
|
bz_stream* strm;
|
||||||
|
|
||||||
|
/* mode this stream is in, and whether inputting */
|
||||||
|
/* or outputting data */
|
||||||
|
Int32 mode;
|
||||||
|
Int32 state;
|
||||||
|
|
||||||
|
/* remembers avail_in when flush/finish requested */
|
||||||
|
UInt32 avail_in_expect;
|
||||||
|
|
||||||
|
/* for doing the block sorting */
|
||||||
|
UInt32* arr1;
|
||||||
|
UInt32* arr2;
|
||||||
|
UInt32* ftab;
|
||||||
|
Int32 origPtr;
|
||||||
|
|
||||||
|
/* aliases for arr1 and arr2 */
|
||||||
|
UInt32* ptr;
|
||||||
|
UChar* block;
|
||||||
|
UInt16* mtfv;
|
||||||
|
UChar* zbits;
|
||||||
|
|
||||||
|
/* for deciding when to use the fallback sorting algorithm */
|
||||||
|
Int32 workFactor;
|
||||||
|
|
||||||
|
/* run-length-encoding of the input */
|
||||||
|
UInt32 state_in_ch;
|
||||||
|
Int32 state_in_len;
|
||||||
|
BZ_RAND_DECLS;
|
||||||
|
|
||||||
|
/* input and output limits and current posns */
|
||||||
|
Int32 nblock;
|
||||||
|
Int32 nblockMAX;
|
||||||
|
Int32 numZ;
|
||||||
|
Int32 state_out_pos;
|
||||||
|
|
||||||
|
/* map of bytes used in block */
|
||||||
|
Int32 nInUse;
|
||||||
|
Bool inUse[256];
|
||||||
|
UChar unseqToSeq[256];
|
||||||
|
|
||||||
|
/* the buffer for bit stream creation */
|
||||||
|
UInt32 bsBuff;
|
||||||
|
Int32 bsLive;
|
||||||
|
|
||||||
|
/* block and combined CRCs */
|
||||||
|
UInt32 blockCRC;
|
||||||
|
UInt32 combinedCRC;
|
||||||
|
|
||||||
|
/* misc administratium */
|
||||||
|
Int32 verbosity;
|
||||||
|
Int32 blockNo;
|
||||||
|
Int32 blockSize100k;
|
||||||
|
|
||||||
|
/* stuff for coding the MTF values */
|
||||||
|
Int32 nMTF;
|
||||||
|
Int32 mtfFreq [BZ_MAX_ALPHA_SIZE];
|
||||||
|
UChar selector [BZ_MAX_SELECTORS];
|
||||||
|
UChar selectorMtf[BZ_MAX_SELECTORS];
|
||||||
|
|
||||||
|
UChar len [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
|
||||||
|
Int32 code [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
|
||||||
|
Int32 rfreq [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
|
||||||
|
/* second dimension: only 3 needed; 4 makes index calculations faster */
|
||||||
|
UInt32 len_pack[BZ_MAX_ALPHA_SIZE][4];
|
||||||
|
|
||||||
|
}
|
||||||
|
EState;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*-- externs for compression. --*/
|
||||||
|
|
||||||
|
extern void
|
||||||
|
BZ2_blockSort ( EState* );
|
||||||
|
|
||||||
|
extern void
|
||||||
|
BZ2_compressBlock ( EState*, Bool );
|
||||||
|
|
||||||
|
extern void
|
||||||
|
BZ2_bsInitWrite ( EState* );
|
||||||
|
|
||||||
|
extern void
|
||||||
|
BZ2_hbAssignCodes ( Int32*, UChar*, Int32, Int32, Int32 );
|
||||||
|
|
||||||
|
extern void
|
||||||
|
BZ2_hbMakeCodeLengths ( UChar*, Int32*, Int32, Int32 );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*-- states for decompression. --*/
|
||||||
|
|
||||||
|
#define BZ_X_IDLE 1
|
||||||
|
#define BZ_X_OUTPUT 2
|
||||||
|
|
||||||
|
#define BZ_X_MAGIC_1 10
|
||||||
|
#define BZ_X_MAGIC_2 11
|
||||||
|
#define BZ_X_MAGIC_3 12
|
||||||
|
#define BZ_X_MAGIC_4 13
|
||||||
|
#define BZ_X_BLKHDR_1 14
|
||||||
|
#define BZ_X_BLKHDR_2 15
|
||||||
|
#define BZ_X_BLKHDR_3 16
|
||||||
|
#define BZ_X_BLKHDR_4 17
|
||||||
|
#define BZ_X_BLKHDR_5 18
|
||||||
|
#define BZ_X_BLKHDR_6 19
|
||||||
|
#define BZ_X_BCRC_1 20
|
||||||
|
#define BZ_X_BCRC_2 21
|
||||||
|
#define BZ_X_BCRC_3 22
|
||||||
|
#define BZ_X_BCRC_4 23
|
||||||
|
#define BZ_X_RANDBIT 24
|
||||||
|
#define BZ_X_ORIGPTR_1 25
|
||||||
|
#define BZ_X_ORIGPTR_2 26
|
||||||
|
#define BZ_X_ORIGPTR_3 27
|
||||||
|
#define BZ_X_MAPPING_1 28
|
||||||
|
#define BZ_X_MAPPING_2 29
|
||||||
|
#define BZ_X_SELECTOR_1 30
|
||||||
|
#define BZ_X_SELECTOR_2 31
|
||||||
|
#define BZ_X_SELECTOR_3 32
|
||||||
|
#define BZ_X_CODING_1 33
|
||||||
|
#define BZ_X_CODING_2 34
|
||||||
|
#define BZ_X_CODING_3 35
|
||||||
|
#define BZ_X_MTF_1 36
|
||||||
|
#define BZ_X_MTF_2 37
|
||||||
|
#define BZ_X_MTF_3 38
|
||||||
|
#define BZ_X_MTF_4 39
|
||||||
|
#define BZ_X_MTF_5 40
|
||||||
|
#define BZ_X_MTF_6 41
|
||||||
|
#define BZ_X_ENDHDR_2 42
|
||||||
|
#define BZ_X_ENDHDR_3 43
|
||||||
|
#define BZ_X_ENDHDR_4 44
|
||||||
|
#define BZ_X_ENDHDR_5 45
|
||||||
|
#define BZ_X_ENDHDR_6 46
|
||||||
|
#define BZ_X_CCRC_1 47
|
||||||
|
#define BZ_X_CCRC_2 48
|
||||||
|
#define BZ_X_CCRC_3 49
|
||||||
|
#define BZ_X_CCRC_4 50
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*-- Constants for the fast MTF decoder. --*/
|
||||||
|
|
||||||
|
#define MTFA_SIZE 4096
|
||||||
|
#define MTFL_SIZE 16
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*-- Structure holding all the decompression-side stuff. --*/
|
||||||
|
|
||||||
|
typedef
|
||||||
|
struct {
|
||||||
|
/* pointer back to the struct bz_stream */
|
||||||
|
bz_stream* strm;
|
||||||
|
|
||||||
|
/* state indicator for this stream */
|
||||||
|
Int32 state;
|
||||||
|
|
||||||
|
/* for doing the final run-length decoding */
|
||||||
|
UChar state_out_ch;
|
||||||
|
Int32 state_out_len;
|
||||||
|
Bool blockRandomised;
|
||||||
|
BZ_RAND_DECLS;
|
||||||
|
|
||||||
|
/* the buffer for bit stream reading */
|
||||||
|
UInt32 bsBuff;
|
||||||
|
Int32 bsLive;
|
||||||
|
|
||||||
|
/* misc administratium */
|
||||||
|
Int32 blockSize100k;
|
||||||
|
Bool smallDecompress;
|
||||||
|
Int32 currBlockNo;
|
||||||
|
Int32 verbosity;
|
||||||
|
|
||||||
|
/* for undoing the Burrows-Wheeler transform */
|
||||||
|
Int32 origPtr;
|
||||||
|
UInt32 tPos;
|
||||||
|
Int32 k0;
|
||||||
|
Int32 unzftab[256];
|
||||||
|
Int32 nblock_used;
|
||||||
|
Int32 cftab[257];
|
||||||
|
Int32 cftabCopy[257];
|
||||||
|
|
||||||
|
/* for undoing the Burrows-Wheeler transform (FAST) */
|
||||||
|
UInt32 *tt;
|
||||||
|
|
||||||
|
/* for undoing the Burrows-Wheeler transform (SMALL) */
|
||||||
|
UInt16 *ll16;
|
||||||
|
UChar *ll4;
|
||||||
|
|
||||||
|
/* stored and calculated CRCs */
|
||||||
|
UInt32 storedBlockCRC;
|
||||||
|
UInt32 storedCombinedCRC;
|
||||||
|
UInt32 calculatedBlockCRC;
|
||||||
|
UInt32 calculatedCombinedCRC;
|
||||||
|
|
||||||
|
/* map of bytes used in block */
|
||||||
|
Int32 nInUse;
|
||||||
|
Bool inUse[256];
|
||||||
|
Bool inUse16[16];
|
||||||
|
UChar seqToUnseq[256];
|
||||||
|
|
||||||
|
/* for decoding the MTF values */
|
||||||
|
UChar mtfa [MTFA_SIZE];
|
||||||
|
Int32 mtfbase[256 / MTFL_SIZE];
|
||||||
|
UChar selector [BZ_MAX_SELECTORS];
|
||||||
|
UChar selectorMtf[BZ_MAX_SELECTORS];
|
||||||
|
UChar len [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
|
||||||
|
|
||||||
|
Int32 limit [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
|
||||||
|
Int32 base [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
|
||||||
|
Int32 perm [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
|
||||||
|
Int32 minLens[BZ_N_GROUPS];
|
||||||
|
|
||||||
|
/* save area for scalars in the main decompress code */
|
||||||
|
Int32 save_i;
|
||||||
|
Int32 save_j;
|
||||||
|
Int32 save_t;
|
||||||
|
Int32 save_alphaSize;
|
||||||
|
Int32 save_nGroups;
|
||||||
|
Int32 save_nSelectors;
|
||||||
|
Int32 save_EOB;
|
||||||
|
Int32 save_groupNo;
|
||||||
|
Int32 save_groupPos;
|
||||||
|
Int32 save_nextSym;
|
||||||
|
Int32 save_nblockMAX;
|
||||||
|
Int32 save_nblock;
|
||||||
|
Int32 save_es;
|
||||||
|
Int32 save_N;
|
||||||
|
Int32 save_curr;
|
||||||
|
Int32 save_zt;
|
||||||
|
Int32 save_zn;
|
||||||
|
Int32 save_zvec;
|
||||||
|
Int32 save_zj;
|
||||||
|
Int32 save_gSel;
|
||||||
|
Int32 save_gMinlen;
|
||||||
|
Int32* save_gLimit;
|
||||||
|
Int32* save_gBase;
|
||||||
|
Int32* save_gPerm;
|
||||||
|
|
||||||
|
}
|
||||||
|
DState;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*-- Macros for decompression. --*/
|
||||||
|
|
||||||
|
#define BZ_GET_FAST(cccc) \
|
||||||
|
s->tPos = s->tt[s->tPos]; \
|
||||||
|
cccc = (UChar)(s->tPos & 0xff); \
|
||||||
|
s->tPos >>= 8;
|
||||||
|
|
||||||
|
#define BZ_GET_FAST_C(cccc) \
|
||||||
|
c_tPos = c_tt[c_tPos]; \
|
||||||
|
cccc = (UChar)(c_tPos & 0xff); \
|
||||||
|
c_tPos >>= 8;
|
||||||
|
|
||||||
|
#define SET_LL4(i,n) \
|
||||||
|
{ if (((i) & 0x1) == 0) \
|
||||||
|
s->ll4[(i) >> 1] = (s->ll4[(i) >> 1] & 0xf0) | (n); else \
|
||||||
|
s->ll4[(i) >> 1] = (s->ll4[(i) >> 1] & 0x0f) | ((n) << 4); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define GET_LL4(i) \
|
||||||
|
((((UInt32)(s->ll4[(i) >> 1])) >> (((i) << 2) & 0x4)) & 0xF)
|
||||||
|
|
||||||
|
#define SET_LL(i,n) \
|
||||||
|
{ s->ll16[i] = (UInt16)(n & 0x0000ffff); \
|
||||||
|
SET_LL4(i, n >> 16); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define GET_LL(i) \
|
||||||
|
(((UInt32)s->ll16[i]) | (GET_LL4(i) << 16))
|
||||||
|
|
||||||
|
#define BZ_GET_SMALL(cccc) \
|
||||||
|
cccc = BZ2_indexIntoF ( s->tPos, s->cftab ); \
|
||||||
|
s->tPos = GET_LL(s->tPos);
|
||||||
|
|
||||||
|
|
||||||
|
/*-- externs for decompression. --*/
|
||||||
|
|
||||||
|
extern Int32
|
||||||
|
BZ2_indexIntoF ( Int32, Int32* );
|
||||||
|
|
||||||
|
extern Int32
|
||||||
|
BZ2_decompress ( DState* );
|
||||||
|
|
||||||
|
extern void
|
||||||
|
BZ2_hbCreateDecodeTables ( Int32*, Int32*, Int32*, UChar*,
|
||||||
|
Int32, Int32, Int32 );
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*-- BZ_NO_STDIO seems to make NULL disappear on some platforms. --*/
|
||||||
|
|
||||||
|
#ifdef BZ_NO_STDIO
|
||||||
|
#ifndef NULL
|
||||||
|
#define NULL 0
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------*/
|
||||||
|
/*--- end bzlib_private.h ---*/
|
||||||
|
/*-------------------------------------------------------------*/
|
|
@ -0,0 +1,672 @@
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------*/
|
||||||
|
/*--- Compression machinery (not incl block sorting) ---*/
|
||||||
|
/*--- compress.c ---*/
|
||||||
|
/*-------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------
|
||||||
|
This file is part of bzip2/libbzip2, a program and library for
|
||||||
|
lossless, block-sorting data compression.
|
||||||
|
|
||||||
|
bzip2/libbzip2 version 1.0.4 of 20 December 2006
|
||||||
|
Copyright (C) 1996-2006 Julian Seward <jseward@bzip.org>
|
||||||
|
|
||||||
|
Please read the WARNING, DISCLAIMER and PATENTS sections in the
|
||||||
|
README file.
|
||||||
|
|
||||||
|
This program is released under the terms of the license contained
|
||||||
|
in the file LICENSE.
|
||||||
|
------------------------------------------------------------------ */
|
||||||
|
|
||||||
|
|
||||||
|
/* CHANGES
|
||||||
|
0.9.0 -- original version.
|
||||||
|
0.9.0a/b -- no changes in this file.
|
||||||
|
0.9.0c -- changed setting of nGroups in sendMTFValues()
|
||||||
|
so as to do a bit better on small files
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "bzlib_private.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*---------------------------------------------------*/
|
||||||
|
/*--- Bit stream I/O ---*/
|
||||||
|
/*---------------------------------------------------*/
|
||||||
|
|
||||||
|
/*---------------------------------------------------*/
|
||||||
|
void BZ2_bsInitWrite ( EState* s )
|
||||||
|
{
|
||||||
|
s->bsLive = 0;
|
||||||
|
s->bsBuff = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*---------------------------------------------------*/
|
||||||
|
static
|
||||||
|
void bsFinishWrite ( EState* s )
|
||||||
|
{
|
||||||
|
while (s->bsLive > 0) {
|
||||||
|
s->zbits[s->numZ] = (UChar)(s->bsBuff >> 24);
|
||||||
|
s->numZ++;
|
||||||
|
s->bsBuff <<= 8;
|
||||||
|
s->bsLive -= 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*---------------------------------------------------*/
|
||||||
|
#define bsNEEDW(nz) \
|
||||||
|
{ \
|
||||||
|
while (s->bsLive >= 8) { \
|
||||||
|
s->zbits[s->numZ] \
|
||||||
|
= (UChar)(s->bsBuff >> 24); \
|
||||||
|
s->numZ++; \
|
||||||
|
s->bsBuff <<= 8; \
|
||||||
|
s->bsLive -= 8; \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*---------------------------------------------------*/
|
||||||
|
static
|
||||||
|
__inline__
|
||||||
|
void bsW ( EState* s, Int32 n, UInt32 v )
|
||||||
|
{
|
||||||
|
bsNEEDW ( n );
|
||||||
|
s->bsBuff |= (v << (32 - s->bsLive - n));
|
||||||
|
s->bsLive += n;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*---------------------------------------------------*/
|
||||||
|
static
|
||||||
|
void bsPutUInt32 ( EState* s, UInt32 u )
|
||||||
|
{
|
||||||
|
bsW ( s, 8, (u >> 24) & 0xffL );
|
||||||
|
bsW ( s, 8, (u >> 16) & 0xffL );
|
||||||
|
bsW ( s, 8, (u >> 8) & 0xffL );
|
||||||
|
bsW ( s, 8, u & 0xffL );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*---------------------------------------------------*/
|
||||||
|
static
|
||||||
|
void bsPutUChar ( EState* s, UChar c )
|
||||||
|
{
|
||||||
|
bsW( s, 8, (UInt32)c );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*---------------------------------------------------*/
|
||||||
|
/*--- The back end proper ---*/
|
||||||
|
/*---------------------------------------------------*/
|
||||||
|
|
||||||
|
/*---------------------------------------------------*/
|
||||||
|
static
|
||||||
|
void makeMaps_e ( EState* s )
|
||||||
|
{
|
||||||
|
Int32 i;
|
||||||
|
s->nInUse = 0;
|
||||||
|
for (i = 0; i < 256; i++)
|
||||||
|
if (s->inUse[i]) {
|
||||||
|
s->unseqToSeq[i] = s->nInUse;
|
||||||
|
s->nInUse++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*---------------------------------------------------*/
|
||||||
|
static
|
||||||
|
void generateMTFValues ( EState* s )
|
||||||
|
{
|
||||||
|
UChar yy[256];
|
||||||
|
Int32 i, j;
|
||||||
|
Int32 zPend;
|
||||||
|
Int32 wr;
|
||||||
|
Int32 EOB;
|
||||||
|
|
||||||
|
/*
|
||||||
|
After sorting (eg, here),
|
||||||
|
s->arr1 [ 0 .. s->nblock-1 ] holds sorted order,
|
||||||
|
and
|
||||||
|
((UChar*)s->arr2) [ 0 .. s->nblock-1 ]
|
||||||
|
holds the original block data.
|
||||||
|
|
||||||
|
The first thing to do is generate the MTF values,
|
||||||
|
and put them in
|
||||||
|
((UInt16*)s->arr1) [ 0 .. s->nblock-1 ].
|
||||||
|
Because there are strictly fewer or equal MTF values
|
||||||
|
than block values, ptr values in this area are overwritten
|
||||||
|
with MTF values only when they are no longer needed.
|
||||||
|
|
||||||
|
The final compressed bitstream is generated into the
|
||||||
|
area starting at
|
||||||
|
(UChar*) (&((UChar*)s->arr2)[s->nblock])
|
||||||
|
|
||||||
|
These storage aliases are set up in bzCompressInit(),
|
||||||
|
except for the last one, which is arranged in
|
||||||
|
compressBlock().
|
||||||
|
*/
|
||||||
|
UInt32* ptr = s->ptr;
|
||||||
|
UChar* block = s->block;
|
||||||
|
UInt16* mtfv = s->mtfv;
|
||||||
|
|
||||||
|
makeMaps_e ( s );
|
||||||
|
EOB = s->nInUse+1;
|
||||||
|
|
||||||
|
for (i = 0; i <= EOB; i++) s->mtfFreq[i] = 0;
|
||||||
|
|
||||||
|
wr = 0;
|
||||||
|
zPend = 0;
|
||||||
|
for (i = 0; i < s->nInUse; i++) yy[i] = (UChar) i;
|
||||||
|
|
||||||
|
for (i = 0; i < s->nblock; i++) {
|
||||||
|
UChar ll_i;
|
||||||
|
AssertD ( wr <= i, "generateMTFValues(1)" );
|
||||||
|
j = ptr[i]-1; if (j < 0) j += s->nblock;
|
||||||
|
ll_i = s->unseqToSeq[block[j]];
|
||||||
|
AssertD ( ll_i < s->nInUse, "generateMTFValues(2a)" );
|
||||||
|
|
||||||
|
if (yy[0] == ll_i) {
|
||||||
|
zPend++;
|
||||||
|
} else {
|
||||||
|
|
||||||
|
if (zPend > 0) {
|
||||||
|
zPend--;
|
||||||
|
while (True) {
|
||||||
|
if (zPend & 1) {
|
||||||
|
mtfv[wr] = BZ_RUNB; wr++;
|
||||||
|
s->mtfFreq[BZ_RUNB]++;
|
||||||
|
} else {
|
||||||
|
mtfv[wr] = BZ_RUNA; wr++;
|
||||||
|
s->mtfFreq[BZ_RUNA]++;
|
||||||
|
}
|
||||||
|
if (zPend < 2) break;
|
||||||
|
zPend = (zPend - 2) / 2;
|
||||||
|
};
|
||||||
|
zPend = 0;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
register UChar rtmp;
|
||||||
|
register UChar* ryy_j;
|
||||||
|
register UChar rll_i;
|
||||||
|
rtmp = yy[1];
|
||||||
|
yy[1] = yy[0];
|
||||||
|
ryy_j = &(yy[1]);
|
||||||
|
rll_i = ll_i;
|
||||||
|
while ( rll_i != rtmp ) {
|
||||||
|
register UChar rtmp2;
|
||||||
|
ryy_j++;
|
||||||
|
rtmp2 = rtmp;
|
||||||
|
rtmp = *ryy_j;
|
||||||
|
*ryy_j = rtmp2;
|
||||||
|
};
|
||||||
|
yy[0] = rtmp;
|
||||||
|
j = ryy_j - &(yy[0]);
|
||||||
|
mtfv[wr] = j+1; wr++; s->mtfFreq[j+1]++;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (zPend > 0) {
|
||||||
|
zPend--;
|
||||||
|
while (True) {
|
||||||
|
if (zPend & 1) {
|
||||||
|
mtfv[wr] = BZ_RUNB; wr++;
|
||||||
|
s->mtfFreq[BZ_RUNB]++;
|
||||||
|
} else {
|
||||||
|
mtfv[wr] = BZ_RUNA; wr++;
|
||||||
|
s->mtfFreq[BZ_RUNA]++;
|
||||||
|
}
|
||||||
|
if (zPend < 2) break;
|
||||||
|
zPend = (zPend - 2) / 2;
|
||||||
|
};
|
||||||
|
zPend = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
mtfv[wr] = EOB; wr++; s->mtfFreq[EOB]++;
|
||||||
|
|
||||||
|
s->nMTF = wr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*---------------------------------------------------*/
|
||||||
|
#define BZ_LESSER_ICOST 0
|
||||||
|
#define BZ_GREATER_ICOST 15
|
||||||
|
|
||||||
|
static
|
||||||
|
void sendMTFValues ( EState* s )
|
||||||
|
{
|
||||||
|
Int32 v, t, i, j, gs, ge, totc, bt, bc, iter;
|
||||||
|
Int32 nSelectors, alphaSize, minLen, maxLen, selCtr;
|
||||||
|
Int32 nGroups, nBytes;
|
||||||
|
|
||||||
|
/*--
|
||||||
|
UChar len [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
|
||||||
|
is a global since the decoder also needs it.
|
||||||
|
|
||||||
|
Int32 code[BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
|
||||||
|
Int32 rfreq[BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
|
||||||
|
are also globals only used in this proc.
|
||||||
|
Made global to keep stack frame size small.
|
||||||
|
--*/
|
||||||
|
|
||||||
|
|
||||||
|
UInt16 cost[BZ_N_GROUPS];
|
||||||
|
Int32 fave[BZ_N_GROUPS];
|
||||||
|
|
||||||
|
UInt16* mtfv = s->mtfv;
|
||||||
|
|
||||||
|
if (s->verbosity >= 3)
|
||||||
|
VPrintf3( " %d in block, %d after MTF & 1-2 coding, "
|
||||||
|
"%d+2 syms in use\n",
|
||||||
|
s->nblock, s->nMTF, s->nInUse );
|
||||||
|
|
||||||
|
alphaSize = s->nInUse+2;
|
||||||
|
for (t = 0; t < BZ_N_GROUPS; t++)
|
||||||
|
for (v = 0; v < alphaSize; v++)
|
||||||
|
s->len[t][v] = BZ_GREATER_ICOST;
|
||||||
|
|
||||||
|
/*--- Decide how many coding tables to use ---*/
|
||||||
|
AssertH ( s->nMTF > 0, 3001 );
|
||||||
|
if (s->nMTF < 200) nGroups = 2; else
|
||||||
|
if (s->nMTF < 600) nGroups = 3; else
|
||||||
|
if (s->nMTF < 1200) nGroups = 4; else
|
||||||
|
if (s->nMTF < 2400) nGroups = 5; else
|
||||||
|
nGroups = 6;
|
||||||
|
|
||||||
|
/*--- Generate an initial set of coding tables ---*/
|
||||||
|
{
|
||||||
|
Int32 nPart, remF, tFreq, aFreq;
|
||||||
|
|
||||||
|
nPart = nGroups;
|
||||||
|
remF = s->nMTF;
|
||||||
|
gs = 0;
|
||||||
|
while (nPart > 0) {
|
||||||
|
tFreq = remF / nPart;
|
||||||
|
ge = gs-1;
|
||||||
|
aFreq = 0;
|
||||||
|
while (aFreq < tFreq && ge < alphaSize-1) {
|
||||||
|
ge++;
|
||||||
|
aFreq += s->mtfFreq[ge];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ge > gs
|
||||||
|
&& nPart != nGroups && nPart != 1
|
||||||
|
&& ((nGroups-nPart) % 2 == 1)) {
|
||||||
|
aFreq -= s->mtfFreq[ge];
|
||||||
|
ge--;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s->verbosity >= 3)
|
||||||
|
VPrintf5( " initial group %d, [%d .. %d], "
|
||||||
|
"has %d syms (%4.1f%%)\n",
|
||||||
|
nPart, gs, ge, aFreq,
|
||||||
|
(100.0 * (float)aFreq) / (float)(s->nMTF) );
|
||||||
|
|
||||||
|
for (v = 0; v < alphaSize; v++)
|
||||||
|
if (v >= gs && v <= ge)
|
||||||
|
s->len[nPart-1][v] = BZ_LESSER_ICOST; else
|
||||||
|
s->len[nPart-1][v] = BZ_GREATER_ICOST;
|
||||||
|
|
||||||
|
nPart--;
|
||||||
|
gs = ge+1;
|
||||||
|
remF -= aFreq;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---
|
||||||
|
Iterate up to BZ_N_ITERS times to improve the tables.
|
||||||
|
---*/
|
||||||
|
for (iter = 0; iter < BZ_N_ITERS; iter++) {
|
||||||
|
|
||||||
|
for (t = 0; t < nGroups; t++) fave[t] = 0;
|
||||||
|
|
||||||
|
for (t = 0; t < nGroups; t++)
|
||||||
|
for (v = 0; v < alphaSize; v++)
|
||||||
|
s->rfreq[t][v] = 0;
|
||||||
|
|
||||||
|
/*---
|
||||||
|
Set up an auxiliary length table which is used to fast-track
|
||||||
|
the common case (nGroups == 6).
|
||||||
|
---*/
|
||||||
|
if (nGroups == 6) {
|
||||||
|
for (v = 0; v < alphaSize; v++) {
|
||||||
|
s->len_pack[v][0] = (s->len[1][v] << 16) | s->len[0][v];
|
||||||
|
s->len_pack[v][1] = (s->len[3][v] << 16) | s->len[2][v];
|
||||||
|
s->len_pack[v][2] = (s->len[5][v] << 16) | s->len[4][v];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nSelectors = 0;
|
||||||
|
totc = 0;
|
||||||
|
gs = 0;
|
||||||
|
while (True) {
|
||||||
|
|
||||||
|
/*--- Set group start & end marks. --*/
|
||||||
|
if (gs >= s->nMTF) break;
|
||||||
|
ge = gs + BZ_G_SIZE - 1;
|
||||||
|
if (ge >= s->nMTF) ge = s->nMTF-1;
|
||||||
|
|
||||||
|
/*--
|
||||||
|
Calculate the cost of this group as coded
|
||||||
|
by each of the coding tables.
|
||||||
|
--*/
|
||||||
|
for (t = 0; t < nGroups; t++) cost[t] = 0;
|
||||||
|
|
||||||
|
if (nGroups == 6 && 50 == ge-gs+1) {
|
||||||
|
/*--- fast track the common case ---*/
|
||||||
|
register UInt32 cost01, cost23, cost45;
|
||||||
|
register UInt16 icv;
|
||||||
|
cost01 = cost23 = cost45 = 0;
|
||||||
|
|
||||||
|
# define BZ_ITER(nn) \
|
||||||
|
icv = mtfv[gs+(nn)]; \
|
||||||
|
cost01 += s->len_pack[icv][0]; \
|
||||||
|
cost23 += s->len_pack[icv][1]; \
|
||||||
|
cost45 += s->len_pack[icv][2]; \
|
||||||
|
|
||||||
|
BZ_ITER(0); BZ_ITER(1); BZ_ITER(2); BZ_ITER(3); BZ_ITER(4);
|
||||||
|
BZ_ITER(5); BZ_ITER(6); BZ_ITER(7); BZ_ITER(8); BZ_ITER(9);
|
||||||
|
BZ_ITER(10); BZ_ITER(11); BZ_ITER(12); BZ_ITER(13); BZ_ITER(14);
|
||||||
|
BZ_ITER(15); BZ_ITER(16); BZ_ITER(17); BZ_ITER(18); BZ_ITER(19);
|
||||||
|
BZ_ITER(20); BZ_ITER(21); BZ_ITER(22); BZ_ITER(23); BZ_ITER(24);
|
||||||
|
BZ_ITER(25); BZ_ITER(26); BZ_ITER(27); BZ_ITER(28); BZ_ITER(29);
|
||||||
|
BZ_ITER(30); BZ_ITER(31); BZ_ITER(32); BZ_ITER(33); BZ_ITER(34);
|
||||||
|
BZ_ITER(35); BZ_ITER(36); BZ_ITER(37); BZ_ITER(38); BZ_ITER(39);
|
||||||
|
BZ_ITER(40); BZ_ITER(41); BZ_ITER(42); BZ_ITER(43); BZ_ITER(44);
|
||||||
|
BZ_ITER(45); BZ_ITER(46); BZ_ITER(47); BZ_ITER(48); BZ_ITER(49);
|
||||||
|
|
||||||
|
# undef BZ_ITER
|
||||||
|
|
||||||
|
cost[0] = cost01 & 0xffff; cost[1] = cost01 >> 16;
|
||||||
|
cost[2] = cost23 & 0xffff; cost[3] = cost23 >> 16;
|
||||||
|
cost[4] = cost45 & 0xffff; cost[5] = cost45 >> 16;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
/*--- slow version which correctly handles all situations ---*/
|
||||||
|
for (i = gs; i <= ge; i++) {
|
||||||
|
UInt16 icv = mtfv[i];
|
||||||
|
for (t = 0; t < nGroups; t++) cost[t] += s->len[t][icv];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*--
|
||||||
|
Find the coding table which is best for this group,
|
||||||
|
and record its identity in the selector table.
|
||||||
|
--*/
|
||||||
|
bc = 999999999; bt = -1;
|
||||||
|
for (t = 0; t < nGroups; t++)
|
||||||
|
if (cost[t] < bc) { bc = cost[t]; bt = t; };
|
||||||
|
totc += bc;
|
||||||
|
fave[bt]++;
|
||||||
|
s->selector[nSelectors] = bt;
|
||||||
|
nSelectors++;
|
||||||
|
|
||||||
|
/*--
|
||||||
|
Increment the symbol frequencies for the selected table.
|
||||||
|
--*/
|
||||||
|
if (nGroups == 6 && 50 == ge-gs+1) {
|
||||||
|
/*--- fast track the common case ---*/
|
||||||
|
|
||||||
|
# define BZ_ITUR(nn) s->rfreq[bt][ mtfv[gs+(nn)] ]++
|
||||||
|
|
||||||
|
BZ_ITUR(0); BZ_ITUR(1); BZ_ITUR(2); BZ_ITUR(3); BZ_ITUR(4);
|
||||||
|
BZ_ITUR(5); BZ_ITUR(6); BZ_ITUR(7); BZ_ITUR(8); BZ_ITUR(9);
|
||||||
|
BZ_ITUR(10); BZ_ITUR(11); BZ_ITUR(12); BZ_ITUR(13); BZ_ITUR(14);
|
||||||
|
BZ_ITUR(15); BZ_ITUR(16); BZ_ITUR(17); BZ_ITUR(18); BZ_ITUR(19);
|
||||||
|
BZ_ITUR(20); BZ_ITUR(21); BZ_ITUR(22); BZ_ITUR(23); BZ_ITUR(24);
|
||||||
|
BZ_ITUR(25); BZ_ITUR(26); BZ_ITUR(27); BZ_ITUR(28); BZ_ITUR(29);
|
||||||
|
BZ_ITUR(30); BZ_ITUR(31); BZ_ITUR(32); BZ_ITUR(33); BZ_ITUR(34);
|
||||||
|
BZ_ITUR(35); BZ_ITUR(36); BZ_ITUR(37); BZ_ITUR(38); BZ_ITUR(39);
|
||||||
|
BZ_ITUR(40); BZ_ITUR(41); BZ_ITUR(42); BZ_ITUR(43); BZ_ITUR(44);
|
||||||
|
BZ_ITUR(45); BZ_ITUR(46); BZ_ITUR(47); BZ_ITUR(48); BZ_ITUR(49);
|
||||||
|
|
||||||
|
# undef BZ_ITUR
|
||||||
|
|
||||||
|
} else {
|
||||||
|
/*--- slow version which correctly handles all situations ---*/
|
||||||
|
for (i = gs; i <= ge; i++)
|
||||||
|
s->rfreq[bt][ mtfv[i] ]++;
|
||||||
|
}
|
||||||
|
|
||||||
|
gs = ge+1;
|
||||||
|
}
|
||||||
|
if (s->verbosity >= 3) {
|
||||||
|
VPrintf2 ( " pass %d: size is %d, grp uses are ",
|
||||||
|
iter+1, totc/8 );
|
||||||
|
for (t = 0; t < nGroups; t++)
|
||||||
|
VPrintf1 ( "%d ", fave[t] );
|
||||||
|
VPrintf0 ( "\n" );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*--
|
||||||
|
Recompute the tables based on the accumulated frequencies.
|
||||||
|
--*/
|
||||||
|
/* maxLen was changed from 20 to 17 in bzip2-1.0.3. See
|
||||||
|
comment in huffman.c for details. */
|
||||||
|
for (t = 0; t < nGroups; t++)
|
||||||
|
BZ2_hbMakeCodeLengths ( &(s->len[t][0]), &(s->rfreq[t][0]),
|
||||||
|
alphaSize, 17 /*20*/ );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
AssertH( nGroups < 8, 3002 );
|
||||||
|
AssertH( nSelectors < 32768 &&
|
||||||
|
nSelectors <= (2 + (900000 / BZ_G_SIZE)),
|
||||||
|
3003 );
|
||||||
|
|
||||||
|
|
||||||
|
/*--- Compute MTF values for the selectors. ---*/
|
||||||
|
{
|
||||||
|
UChar pos[BZ_N_GROUPS], ll_i, tmp2, tmp;
|
||||||
|
for (i = 0; i < nGroups; i++) pos[i] = i;
|
||||||
|
for (i = 0; i < nSelectors; i++) {
|
||||||
|
ll_i = s->selector[i];
|
||||||
|
j = 0;
|
||||||
|
tmp = pos[j];
|
||||||
|
while ( ll_i != tmp ) {
|
||||||
|
j++;
|
||||||
|
tmp2 = tmp;
|
||||||
|
tmp = pos[j];
|
||||||
|
pos[j] = tmp2;
|
||||||
|
};
|
||||||
|
pos[0] = tmp;
|
||||||
|
s->selectorMtf[i] = j;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*--- Assign actual codes for the tables. --*/
|
||||||
|
for (t = 0; t < nGroups; t++) {
|
||||||
|
minLen = 32;
|
||||||
|
maxLen = 0;
|
||||||
|
for (i = 0; i < alphaSize; i++) {
|
||||||
|
if (s->len[t][i] > maxLen) maxLen = s->len[t][i];
|
||||||
|
if (s->len[t][i] < minLen) minLen = s->len[t][i];
|
||||||
|
}
|
||||||
|
AssertH ( !(maxLen > 17 /*20*/ ), 3004 );
|
||||||
|
AssertH ( !(minLen < 1), 3005 );
|
||||||
|
BZ2_hbAssignCodes ( &(s->code[t][0]), &(s->len[t][0]),
|
||||||
|
minLen, maxLen, alphaSize );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*--- Transmit the mapping table. ---*/
|
||||||
|
{
|
||||||
|
Bool inUse16[16];
|
||||||
|
for (i = 0; i < 16; i++) {
|
||||||
|
inUse16[i] = False;
|
||||||
|
for (j = 0; j < 16; j++)
|
||||||
|
if (s->inUse[i * 16 + j]) inUse16[i] = True;
|
||||||
|
}
|
||||||
|
|
||||||
|
nBytes = s->numZ;
|
||||||
|
for (i = 0; i < 16; i++)
|
||||||
|
if (inUse16[i]) bsW(s,1,1); else bsW(s,1,0);
|
||||||
|
|
||||||
|
for (i = 0; i < 16; i++)
|
||||||
|
if (inUse16[i])
|
||||||
|
for (j = 0; j < 16; j++) {
|
||||||
|
if (s->inUse[i * 16 + j]) bsW(s,1,1); else bsW(s,1,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s->verbosity >= 3)
|
||||||
|
VPrintf1( " bytes: mapping %d, ", s->numZ-nBytes );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*--- Now the selectors. ---*/
|
||||||
|
nBytes = s->numZ;
|
||||||
|
bsW ( s, 3, nGroups );
|
||||||
|
bsW ( s, 15, nSelectors );
|
||||||
|
for (i = 0; i < nSelectors; i++) {
|
||||||
|
for (j = 0; j < s->selectorMtf[i]; j++) bsW(s,1,1);
|
||||||
|
bsW(s,1,0);
|
||||||
|
}
|
||||||
|
if (s->verbosity >= 3)
|
||||||
|
VPrintf1( "selectors %d, ", s->numZ-nBytes );
|
||||||
|
|
||||||
|
/*--- Now the coding tables. ---*/
|
||||||
|
nBytes = s->numZ;
|
||||||
|
|
||||||
|
for (t = 0; t < nGroups; t++) {
|
||||||
|
Int32 curr = s->len[t][0];
|
||||||
|
bsW ( s, 5, curr );
|
||||||
|
for (i = 0; i < alphaSize; i++) {
|
||||||
|
while (curr < s->len[t][i]) { bsW(s,2,2); curr++; /* 10 */ };
|
||||||
|
while (curr > s->len[t][i]) { bsW(s,2,3); curr--; /* 11 */ };
|
||||||
|
bsW ( s, 1, 0 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s->verbosity >= 3)
|
||||||
|
VPrintf1 ( "code lengths %d, ", s->numZ-nBytes );
|
||||||
|
|
||||||
|
/*--- And finally, the block data proper ---*/
|
||||||
|
nBytes = s->numZ;
|
||||||
|
selCtr = 0;
|
||||||
|
gs = 0;
|
||||||
|
while (True) {
|
||||||
|
if (gs >= s->nMTF) break;
|
||||||
|
ge = gs + BZ_G_SIZE - 1;
|
||||||
|
if (ge >= s->nMTF) ge = s->nMTF-1;
|
||||||
|
AssertH ( s->selector[selCtr] < nGroups, 3006 );
|
||||||
|
|
||||||
|
if (nGroups == 6 && 50 == ge-gs+1) {
|
||||||
|
/*--- fast track the common case ---*/
|
||||||
|
UInt16 mtfv_i;
|
||||||
|
UChar* s_len_sel_selCtr
|
||||||
|
= &(s->len[s->selector[selCtr]][0]);
|
||||||
|
Int32* s_code_sel_selCtr
|
||||||
|
= &(s->code[s->selector[selCtr]][0]);
|
||||||
|
|
||||||
|
# define BZ_ITAH(nn) \
|
||||||
|
mtfv_i = mtfv[gs+(nn)]; \
|
||||||
|
bsW ( s, \
|
||||||
|
s_len_sel_selCtr[mtfv_i], \
|
||||||
|
s_code_sel_selCtr[mtfv_i] )
|
||||||
|
|
||||||
|
BZ_ITAH(0); BZ_ITAH(1); BZ_ITAH(2); BZ_ITAH(3); BZ_ITAH(4);
|
||||||
|
BZ_ITAH(5); BZ_ITAH(6); BZ_ITAH(7); BZ_ITAH(8); BZ_ITAH(9);
|
||||||
|
BZ_ITAH(10); BZ_ITAH(11); BZ_ITAH(12); BZ_ITAH(13); BZ_ITAH(14);
|
||||||
|
BZ_ITAH(15); BZ_ITAH(16); BZ_ITAH(17); BZ_ITAH(18); BZ_ITAH(19);
|
||||||
|
BZ_ITAH(20); BZ_ITAH(21); BZ_ITAH(22); BZ_ITAH(23); BZ_ITAH(24);
|
||||||
|
BZ_ITAH(25); BZ_ITAH(26); BZ_ITAH(27); BZ_ITAH(28); BZ_ITAH(29);
|
||||||
|
BZ_ITAH(30); BZ_ITAH(31); BZ_ITAH(32); BZ_ITAH(33); BZ_ITAH(34);
|
||||||
|
BZ_ITAH(35); BZ_ITAH(36); BZ_ITAH(37); BZ_ITAH(38); BZ_ITAH(39);
|
||||||
|
BZ_ITAH(40); BZ_ITAH(41); BZ_ITAH(42); BZ_ITAH(43); BZ_ITAH(44);
|
||||||
|
BZ_ITAH(45); BZ_ITAH(46); BZ_ITAH(47); BZ_ITAH(48); BZ_ITAH(49);
|
||||||
|
|
||||||
|
# undef BZ_ITAH
|
||||||
|
|
||||||
|
} else {
|
||||||
|
/*--- slow version which correctly handles all situations ---*/
|
||||||
|
for (i = gs; i <= ge; i++) {
|
||||||
|
bsW ( s,
|
||||||
|
s->len [s->selector[selCtr]] [mtfv[i]],
|
||||||
|
s->code [s->selector[selCtr]] [mtfv[i]] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
gs = ge+1;
|
||||||
|
selCtr++;
|
||||||
|
}
|
||||||
|
AssertH( selCtr == nSelectors, 3007 );
|
||||||
|
|
||||||
|
if (s->verbosity >= 3)
|
||||||
|
VPrintf1( "codes %d\n", s->numZ-nBytes );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*---------------------------------------------------*/
|
||||||
|
void BZ2_compressBlock ( EState* s, Bool is_last_block )
|
||||||
|
{
|
||||||
|
if (s->nblock > 0) {
|
||||||
|
|
||||||
|
BZ_FINALISE_CRC ( s->blockCRC );
|
||||||
|
s->combinedCRC = (s->combinedCRC << 1) | (s->combinedCRC >> 31);
|
||||||
|
s->combinedCRC ^= s->blockCRC;
|
||||||
|
if (s->blockNo > 1) s->numZ = 0;
|
||||||
|
|
||||||
|
if (s->verbosity >= 2)
|
||||||
|
VPrintf4( " block %d: crc = 0x%08x, "
|
||||||
|
"combined CRC = 0x%08x, size = %d\n",
|
||||||
|
s->blockNo, s->blockCRC, s->combinedCRC, s->nblock );
|
||||||
|
|
||||||
|
BZ2_blockSort ( s );
|
||||||
|
}
|
||||||
|
|
||||||
|
s->zbits = (UChar*) (&((UChar*)s->arr2)[s->nblock]);
|
||||||
|
|
||||||
|
/*-- If this is the first block, create the stream header. --*/
|
||||||
|
if (s->blockNo == 1) {
|
||||||
|
BZ2_bsInitWrite ( s );
|
||||||
|
bsPutUChar ( s, BZ_HDR_B );
|
||||||
|
bsPutUChar ( s, BZ_HDR_Z );
|
||||||
|
bsPutUChar ( s, BZ_HDR_h );
|
||||||
|
bsPutUChar ( s, (UChar)(BZ_HDR_0 + s->blockSize100k) );
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s->nblock > 0) {
|
||||||
|
|
||||||
|
bsPutUChar ( s, 0x31 ); bsPutUChar ( s, 0x41 );
|
||||||
|
bsPutUChar ( s, 0x59 ); bsPutUChar ( s, 0x26 );
|
||||||
|
bsPutUChar ( s, 0x53 ); bsPutUChar ( s, 0x59 );
|
||||||
|
|
||||||
|
/*-- Now the block's CRC, so it is in a known place. --*/
|
||||||
|
bsPutUInt32 ( s, s->blockCRC );
|
||||||
|
|
||||||
|
/*--
|
||||||
|
Now a single bit indicating (non-)randomisation.
|
||||||
|
As of version 0.9.5, we use a better sorting algorithm
|
||||||
|
which makes randomisation unnecessary. So always set
|
||||||
|
the randomised bit to 'no'. Of course, the decoder
|
||||||
|
still needs to be able to handle randomised blocks
|
||||||
|
so as to maintain backwards compatibility with
|
||||||
|
older versions of bzip2.
|
||||||
|
--*/
|
||||||
|
bsW(s,1,0);
|
||||||
|
|
||||||
|
bsW ( s, 24, s->origPtr );
|
||||||
|
generateMTFValues ( s );
|
||||||
|
sendMTFValues ( s );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*-- If this is the last block, add the stream trailer. --*/
|
||||||
|
if (is_last_block) {
|
||||||
|
|
||||||
|
bsPutUChar ( s, 0x17 ); bsPutUChar ( s, 0x72 );
|
||||||
|
bsPutUChar ( s, 0x45 ); bsPutUChar ( s, 0x38 );
|
||||||
|
bsPutUChar ( s, 0x50 ); bsPutUChar ( s, 0x90 );
|
||||||
|
bsPutUInt32 ( s, s->combinedCRC );
|
||||||
|
if (s->verbosity >= 2)
|
||||||
|
VPrintf1( " final combined CRC = 0x%08x\n ", s->combinedCRC );
|
||||||
|
bsFinishWrite ( s );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------*/
|
||||||
|
/*--- end compress.c ---*/
|
||||||
|
/*-------------------------------------------------------------*/
|
|
@ -0,0 +1,104 @@
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------*/
|
||||||
|
/*--- Table for doing CRCs ---*/
|
||||||
|
/*--- crctable.c ---*/
|
||||||
|
/*-------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------
|
||||||
|
This file is part of bzip2/libbzip2, a program and library for
|
||||||
|
lossless, block-sorting data compression.
|
||||||
|
|
||||||
|
bzip2/libbzip2 version 1.0.4 of 20 December 2006
|
||||||
|
Copyright (C) 1996-2006 Julian Seward <jseward@bzip.org>
|
||||||
|
|
||||||
|
Please read the WARNING, DISCLAIMER and PATENTS sections in the
|
||||||
|
README file.
|
||||||
|
|
||||||
|
This program is released under the terms of the license contained
|
||||||
|
in the file LICENSE.
|
||||||
|
------------------------------------------------------------------ */
|
||||||
|
|
||||||
|
|
||||||
|
#include "bzlib_private.h"
|
||||||
|
|
||||||
|
/*--
|
||||||
|
I think this is an implementation of the AUTODIN-II,
|
||||||
|
Ethernet & FDDI 32-bit CRC standard. Vaguely derived
|
||||||
|
from code by Rob Warnock, in Section 51 of the
|
||||||
|
comp.compression FAQ.
|
||||||
|
--*/
|
||||||
|
|
||||||
|
UInt32 BZ2_crc32Table[256] = {
|
||||||
|
|
||||||
|
/*-- Ugly, innit? --*/
|
||||||
|
|
||||||
|
0x00000000L, 0x04c11db7L, 0x09823b6eL, 0x0d4326d9L,
|
||||||
|
0x130476dcL, 0x17c56b6bL, 0x1a864db2L, 0x1e475005L,
|
||||||
|
0x2608edb8L, 0x22c9f00fL, 0x2f8ad6d6L, 0x2b4bcb61L,
|
||||||
|
0x350c9b64L, 0x31cd86d3L, 0x3c8ea00aL, 0x384fbdbdL,
|
||||||
|
0x4c11db70L, 0x48d0c6c7L, 0x4593e01eL, 0x4152fda9L,
|
||||||
|
0x5f15adacL, 0x5bd4b01bL, 0x569796c2L, 0x52568b75L,
|
||||||
|
0x6a1936c8L, 0x6ed82b7fL, 0x639b0da6L, 0x675a1011L,
|
||||||
|
0x791d4014L, 0x7ddc5da3L, 0x709f7b7aL, 0x745e66cdL,
|
||||||
|
0x9823b6e0L, 0x9ce2ab57L, 0x91a18d8eL, 0x95609039L,
|
||||||
|
0x8b27c03cL, 0x8fe6dd8bL, 0x82a5fb52L, 0x8664e6e5L,
|
||||||
|
0xbe2b5b58L, 0xbaea46efL, 0xb7a96036L, 0xb3687d81L,
|
||||||
|
0xad2f2d84L, 0xa9ee3033L, 0xa4ad16eaL, 0xa06c0b5dL,
|
||||||
|
0xd4326d90L, 0xd0f37027L, 0xddb056feL, 0xd9714b49L,
|
||||||
|
0xc7361b4cL, 0xc3f706fbL, 0xceb42022L, 0xca753d95L,
|
||||||
|
0xf23a8028L, 0xf6fb9d9fL, 0xfbb8bb46L, 0xff79a6f1L,
|
||||||
|
0xe13ef6f4L, 0xe5ffeb43L, 0xe8bccd9aL, 0xec7dd02dL,
|
||||||
|
0x34867077L, 0x30476dc0L, 0x3d044b19L, 0x39c556aeL,
|
||||||
|
0x278206abL, 0x23431b1cL, 0x2e003dc5L, 0x2ac12072L,
|
||||||
|
0x128e9dcfL, 0x164f8078L, 0x1b0ca6a1L, 0x1fcdbb16L,
|
||||||
|
0x018aeb13L, 0x054bf6a4L, 0x0808d07dL, 0x0cc9cdcaL,
|
||||||
|
0x7897ab07L, 0x7c56b6b0L, 0x71159069L, 0x75d48ddeL,
|
||||||
|
0x6b93dddbL, 0x6f52c06cL, 0x6211e6b5L, 0x66d0fb02L,
|
||||||
|
0x5e9f46bfL, 0x5a5e5b08L, 0x571d7dd1L, 0x53dc6066L,
|
||||||
|
0x4d9b3063L, 0x495a2dd4L, 0x44190b0dL, 0x40d816baL,
|
||||||
|
0xaca5c697L, 0xa864db20L, 0xa527fdf9L, 0xa1e6e04eL,
|
||||||
|
0xbfa1b04bL, 0xbb60adfcL, 0xb6238b25L, 0xb2e29692L,
|
||||||
|
0x8aad2b2fL, 0x8e6c3698L, 0x832f1041L, 0x87ee0df6L,
|
||||||
|
0x99a95df3L, 0x9d684044L, 0x902b669dL, 0x94ea7b2aL,
|
||||||
|
0xe0b41de7L, 0xe4750050L, 0xe9362689L, 0xedf73b3eL,
|
||||||
|
0xf3b06b3bL, 0xf771768cL, 0xfa325055L, 0xfef34de2L,
|
||||||
|
0xc6bcf05fL, 0xc27dede8L, 0xcf3ecb31L, 0xcbffd686L,
|
||||||
|
0xd5b88683L, 0xd1799b34L, 0xdc3abdedL, 0xd8fba05aL,
|
||||||
|
0x690ce0eeL, 0x6dcdfd59L, 0x608edb80L, 0x644fc637L,
|
||||||
|
0x7a089632L, 0x7ec98b85L, 0x738aad5cL, 0x774bb0ebL,
|
||||||
|
0x4f040d56L, 0x4bc510e1L, 0x46863638L, 0x42472b8fL,
|
||||||
|
0x5c007b8aL, 0x58c1663dL, 0x558240e4L, 0x51435d53L,
|
||||||
|
0x251d3b9eL, 0x21dc2629L, 0x2c9f00f0L, 0x285e1d47L,
|
||||||
|
0x36194d42L, 0x32d850f5L, 0x3f9b762cL, 0x3b5a6b9bL,
|
||||||
|
0x0315d626L, 0x07d4cb91L, 0x0a97ed48L, 0x0e56f0ffL,
|
||||||
|
0x1011a0faL, 0x14d0bd4dL, 0x19939b94L, 0x1d528623L,
|
||||||
|
0xf12f560eL, 0xf5ee4bb9L, 0xf8ad6d60L, 0xfc6c70d7L,
|
||||||
|
0xe22b20d2L, 0xe6ea3d65L, 0xeba91bbcL, 0xef68060bL,
|
||||||
|
0xd727bbb6L, 0xd3e6a601L, 0xdea580d8L, 0xda649d6fL,
|
||||||
|
0xc423cd6aL, 0xc0e2d0ddL, 0xcda1f604L, 0xc960ebb3L,
|
||||||
|
0xbd3e8d7eL, 0xb9ff90c9L, 0xb4bcb610L, 0xb07daba7L,
|
||||||
|
0xae3afba2L, 0xaafbe615L, 0xa7b8c0ccL, 0xa379dd7bL,
|
||||||
|
0x9b3660c6L, 0x9ff77d71L, 0x92b45ba8L, 0x9675461fL,
|
||||||
|
0x8832161aL, 0x8cf30badL, 0x81b02d74L, 0x857130c3L,
|
||||||
|
0x5d8a9099L, 0x594b8d2eL, 0x5408abf7L, 0x50c9b640L,
|
||||||
|
0x4e8ee645L, 0x4a4ffbf2L, 0x470cdd2bL, 0x43cdc09cL,
|
||||||
|
0x7b827d21L, 0x7f436096L, 0x7200464fL, 0x76c15bf8L,
|
||||||
|
0x68860bfdL, 0x6c47164aL, 0x61043093L, 0x65c52d24L,
|
||||||
|
0x119b4be9L, 0x155a565eL, 0x18197087L, 0x1cd86d30L,
|
||||||
|
0x029f3d35L, 0x065e2082L, 0x0b1d065bL, 0x0fdc1becL,
|
||||||
|
0x3793a651L, 0x3352bbe6L, 0x3e119d3fL, 0x3ad08088L,
|
||||||
|
0x2497d08dL, 0x2056cd3aL, 0x2d15ebe3L, 0x29d4f654L,
|
||||||
|
0xc5a92679L, 0xc1683bceL, 0xcc2b1d17L, 0xc8ea00a0L,
|
||||||
|
0xd6ad50a5L, 0xd26c4d12L, 0xdf2f6bcbL, 0xdbee767cL,
|
||||||
|
0xe3a1cbc1L, 0xe760d676L, 0xea23f0afL, 0xeee2ed18L,
|
||||||
|
0xf0a5bd1dL, 0xf464a0aaL, 0xf9278673L, 0xfde69bc4L,
|
||||||
|
0x89b8fd09L, 0x8d79e0beL, 0x803ac667L, 0x84fbdbd0L,
|
||||||
|
0x9abc8bd5L, 0x9e7d9662L, 0x933eb0bbL, 0x97ffad0cL,
|
||||||
|
0xafb010b1L, 0xab710d06L, 0xa6322bdfL, 0xa2f33668L,
|
||||||
|
0xbcb4666dL, 0xb8757bdaL, 0xb5365d03L, 0xb1f740b4L
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------*/
|
||||||
|
/*--- end crctable.c ---*/
|
||||||
|
/*-------------------------------------------------------------*/
|
|
@ -0,0 +1,626 @@
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------*/
|
||||||
|
/*--- Decompression machinery ---*/
|
||||||
|
/*--- decompress.c ---*/
|
||||||
|
/*-------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------
|
||||||
|
This file is part of bzip2/libbzip2, a program and library for
|
||||||
|
lossless, block-sorting data compression.
|
||||||
|
|
||||||
|
bzip2/libbzip2 version 1.0.4 of 20 December 2006
|
||||||
|
Copyright (C) 1996-2006 Julian Seward <jseward@bzip.org>
|
||||||
|
|
||||||
|
Please read the WARNING, DISCLAIMER and PATENTS sections in the
|
||||||
|
README file.
|
||||||
|
|
||||||
|
This program is released under the terms of the license contained
|
||||||
|
in the file LICENSE.
|
||||||
|
------------------------------------------------------------------ */
|
||||||
|
|
||||||
|
|
||||||
|
#include "bzlib_private.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*---------------------------------------------------*/
|
||||||
|
static
|
||||||
|
void makeMaps_d ( DState* s )
|
||||||
|
{
|
||||||
|
Int32 i;
|
||||||
|
s->nInUse = 0;
|
||||||
|
for (i = 0; i < 256; i++)
|
||||||
|
if (s->inUse[i]) {
|
||||||
|
s->seqToUnseq[s->nInUse] = i;
|
||||||
|
s->nInUse++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*---------------------------------------------------*/
|
||||||
|
#define RETURN(rrr) \
|
||||||
|
{ retVal = rrr; goto save_state_and_return; };
|
||||||
|
|
||||||
|
#define GET_BITS(lll,vvv,nnn) \
|
||||||
|
case lll: s->state = lll; \
|
||||||
|
while (True) { \
|
||||||
|
if (s->bsLive >= nnn) { \
|
||||||
|
UInt32 v; \
|
||||||
|
v = (s->bsBuff >> \
|
||||||
|
(s->bsLive-nnn)) & ((1 << nnn)-1); \
|
||||||
|
s->bsLive -= nnn; \
|
||||||
|
vvv = v; \
|
||||||
|
break; \
|
||||||
|
} \
|
||||||
|
if (s->strm->avail_in == 0) RETURN(BZ_OK); \
|
||||||
|
s->bsBuff \
|
||||||
|
= (s->bsBuff << 8) | \
|
||||||
|
((UInt32) \
|
||||||
|
(*((UChar*)(s->strm->next_in)))); \
|
||||||
|
s->bsLive += 8; \
|
||||||
|
s->strm->next_in++; \
|
||||||
|
s->strm->avail_in--; \
|
||||||
|
s->strm->total_in_lo32++; \
|
||||||
|
if (s->strm->total_in_lo32 == 0) \
|
||||||
|
s->strm->total_in_hi32++; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define GET_UCHAR(lll,uuu) \
|
||||||
|
GET_BITS(lll,uuu,8)
|
||||||
|
|
||||||
|
#define GET_BIT(lll,uuu) \
|
||||||
|
GET_BITS(lll,uuu,1)
|
||||||
|
|
||||||
|
/*---------------------------------------------------*/
|
||||||
|
#define GET_MTF_VAL(label1,label2,lval) \
|
||||||
|
{ \
|
||||||
|
if (groupPos == 0) { \
|
||||||
|
groupNo++; \
|
||||||
|
if (groupNo >= nSelectors) \
|
||||||
|
RETURN(BZ_DATA_ERROR); \
|
||||||
|
groupPos = BZ_G_SIZE; \
|
||||||
|
gSel = s->selector[groupNo]; \
|
||||||
|
gMinlen = s->minLens[gSel]; \
|
||||||
|
gLimit = &(s->limit[gSel][0]); \
|
||||||
|
gPerm = &(s->perm[gSel][0]); \
|
||||||
|
gBase = &(s->base[gSel][0]); \
|
||||||
|
} \
|
||||||
|
groupPos--; \
|
||||||
|
zn = gMinlen; \
|
||||||
|
GET_BITS(label1, zvec, zn); \
|
||||||
|
while (1) { \
|
||||||
|
if (zn > 20 /* the longest code */) \
|
||||||
|
RETURN(BZ_DATA_ERROR); \
|
||||||
|
if (zvec <= gLimit[zn]) break; \
|
||||||
|
zn++; \
|
||||||
|
GET_BIT(label2, zj); \
|
||||||
|
zvec = (zvec << 1) | zj; \
|
||||||
|
}; \
|
||||||
|
if (zvec - gBase[zn] < 0 \
|
||||||
|
|| zvec - gBase[zn] >= BZ_MAX_ALPHA_SIZE) \
|
||||||
|
RETURN(BZ_DATA_ERROR); \
|
||||||
|
lval = gPerm[zvec - gBase[zn]]; \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*---------------------------------------------------*/
|
||||||
|
Int32 BZ2_decompress ( DState* s )
|
||||||
|
{
|
||||||
|
UChar uc;
|
||||||
|
Int32 retVal;
|
||||||
|
Int32 minLen, maxLen;
|
||||||
|
bz_stream* strm = s->strm;
|
||||||
|
|
||||||
|
/* stuff that needs to be saved/restored */
|
||||||
|
Int32 i;
|
||||||
|
Int32 j;
|
||||||
|
Int32 t;
|
||||||
|
Int32 alphaSize;
|
||||||
|
Int32 nGroups;
|
||||||
|
Int32 nSelectors;
|
||||||
|
Int32 EOB;
|
||||||
|
Int32 groupNo;
|
||||||
|
Int32 groupPos;
|
||||||
|
Int32 nextSym;
|
||||||
|
Int32 nblockMAX;
|
||||||
|
Int32 nblock;
|
||||||
|
Int32 es;
|
||||||
|
Int32 N;
|
||||||
|
Int32 curr;
|
||||||
|
Int32 zt;
|
||||||
|
Int32 zn;
|
||||||
|
Int32 zvec;
|
||||||
|
Int32 zj;
|
||||||
|
Int32 gSel;
|
||||||
|
Int32 gMinlen;
|
||||||
|
Int32* gLimit;
|
||||||
|
Int32* gBase;
|
||||||
|
Int32* gPerm;
|
||||||
|
|
||||||
|
if (s->state == BZ_X_MAGIC_1) {
|
||||||
|
/*initialise the save area*/
|
||||||
|
s->save_i = 0;
|
||||||
|
s->save_j = 0;
|
||||||
|
s->save_t = 0;
|
||||||
|
s->save_alphaSize = 0;
|
||||||
|
s->save_nGroups = 0;
|
||||||
|
s->save_nSelectors = 0;
|
||||||
|
s->save_EOB = 0;
|
||||||
|
s->save_groupNo = 0;
|
||||||
|
s->save_groupPos = 0;
|
||||||
|
s->save_nextSym = 0;
|
||||||
|
s->save_nblockMAX = 0;
|
||||||
|
s->save_nblock = 0;
|
||||||
|
s->save_es = 0;
|
||||||
|
s->save_N = 0;
|
||||||
|
s->save_curr = 0;
|
||||||
|
s->save_zt = 0;
|
||||||
|
s->save_zn = 0;
|
||||||
|
s->save_zvec = 0;
|
||||||
|
s->save_zj = 0;
|
||||||
|
s->save_gSel = 0;
|
||||||
|
s->save_gMinlen = 0;
|
||||||
|
s->save_gLimit = NULL;
|
||||||
|
s->save_gBase = NULL;
|
||||||
|
s->save_gPerm = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*restore from the save area*/
|
||||||
|
i = s->save_i;
|
||||||
|
j = s->save_j;
|
||||||
|
t = s->save_t;
|
||||||
|
alphaSize = s->save_alphaSize;
|
||||||
|
nGroups = s->save_nGroups;
|
||||||
|
nSelectors = s->save_nSelectors;
|
||||||
|
EOB = s->save_EOB;
|
||||||
|
groupNo = s->save_groupNo;
|
||||||
|
groupPos = s->save_groupPos;
|
||||||
|
nextSym = s->save_nextSym;
|
||||||
|
nblockMAX = s->save_nblockMAX;
|
||||||
|
nblock = s->save_nblock;
|
||||||
|
es = s->save_es;
|
||||||
|
N = s->save_N;
|
||||||
|
curr = s->save_curr;
|
||||||
|
zt = s->save_zt;
|
||||||
|
zn = s->save_zn;
|
||||||
|
zvec = s->save_zvec;
|
||||||
|
zj = s->save_zj;
|
||||||
|
gSel = s->save_gSel;
|
||||||
|
gMinlen = s->save_gMinlen;
|
||||||
|
gLimit = s->save_gLimit;
|
||||||
|
gBase = s->save_gBase;
|
||||||
|
gPerm = s->save_gPerm;
|
||||||
|
|
||||||
|
retVal = BZ_OK;
|
||||||
|
|
||||||
|
switch (s->state) {
|
||||||
|
|
||||||
|
GET_UCHAR(BZ_X_MAGIC_1, uc);
|
||||||
|
if (uc != BZ_HDR_B) RETURN(BZ_DATA_ERROR_MAGIC);
|
||||||
|
|
||||||
|
GET_UCHAR(BZ_X_MAGIC_2, uc);
|
||||||
|
if (uc != BZ_HDR_Z) RETURN(BZ_DATA_ERROR_MAGIC);
|
||||||
|
|
||||||
|
GET_UCHAR(BZ_X_MAGIC_3, uc)
|
||||||
|
if (uc != BZ_HDR_h) RETURN(BZ_DATA_ERROR_MAGIC);
|
||||||
|
|
||||||
|
GET_BITS(BZ_X_MAGIC_4, s->blockSize100k, 8)
|
||||||
|
if (s->blockSize100k < (BZ_HDR_0 + 1) ||
|
||||||
|
s->blockSize100k > (BZ_HDR_0 + 9)) RETURN(BZ_DATA_ERROR_MAGIC);
|
||||||
|
s->blockSize100k -= BZ_HDR_0;
|
||||||
|
|
||||||
|
if (s->smallDecompress) {
|
||||||
|
s->ll16 = BZALLOC( s->blockSize100k * 100000 * sizeof(UInt16) );
|
||||||
|
s->ll4 = BZALLOC(
|
||||||
|
((1 + s->blockSize100k * 100000) >> 1) * sizeof(UChar)
|
||||||
|
);
|
||||||
|
if (s->ll16 == NULL || s->ll4 == NULL) RETURN(BZ_MEM_ERROR);
|
||||||
|
} else {
|
||||||
|
s->tt = BZALLOC( s->blockSize100k * 100000 * sizeof(Int32) );
|
||||||
|
if (s->tt == NULL) RETURN(BZ_MEM_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
GET_UCHAR(BZ_X_BLKHDR_1, uc);
|
||||||
|
|
||||||
|
if (uc == 0x17) goto endhdr_2;
|
||||||
|
if (uc != 0x31) RETURN(BZ_DATA_ERROR);
|
||||||
|
GET_UCHAR(BZ_X_BLKHDR_2, uc);
|
||||||
|
if (uc != 0x41) RETURN(BZ_DATA_ERROR);
|
||||||
|
GET_UCHAR(BZ_X_BLKHDR_3, uc);
|
||||||
|
if (uc != 0x59) RETURN(BZ_DATA_ERROR);
|
||||||
|
GET_UCHAR(BZ_X_BLKHDR_4, uc);
|
||||||
|
if (uc != 0x26) RETURN(BZ_DATA_ERROR);
|
||||||
|
GET_UCHAR(BZ_X_BLKHDR_5, uc);
|
||||||
|
if (uc != 0x53) RETURN(BZ_DATA_ERROR);
|
||||||
|
GET_UCHAR(BZ_X_BLKHDR_6, uc);
|
||||||
|
if (uc != 0x59) RETURN(BZ_DATA_ERROR);
|
||||||
|
|
||||||
|
s->currBlockNo++;
|
||||||
|
if (s->verbosity >= 2)
|
||||||
|
VPrintf1 ( "\n [%d: huff+mtf ", s->currBlockNo );
|
||||||
|
|
||||||
|
s->storedBlockCRC = 0;
|
||||||
|
GET_UCHAR(BZ_X_BCRC_1, uc);
|
||||||
|
s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc);
|
||||||
|
GET_UCHAR(BZ_X_BCRC_2, uc);
|
||||||
|
s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc);
|
||||||
|
GET_UCHAR(BZ_X_BCRC_3, uc);
|
||||||
|
s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc);
|
||||||
|
GET_UCHAR(BZ_X_BCRC_4, uc);
|
||||||
|
s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc);
|
||||||
|
|
||||||
|
GET_BITS(BZ_X_RANDBIT, s->blockRandomised, 1);
|
||||||
|
|
||||||
|
s->origPtr = 0;
|
||||||
|
GET_UCHAR(BZ_X_ORIGPTR_1, uc);
|
||||||
|
s->origPtr = (s->origPtr << 8) | ((Int32)uc);
|
||||||
|
GET_UCHAR(BZ_X_ORIGPTR_2, uc);
|
||||||
|
s->origPtr = (s->origPtr << 8) | ((Int32)uc);
|
||||||
|
GET_UCHAR(BZ_X_ORIGPTR_3, uc);
|
||||||
|
s->origPtr = (s->origPtr << 8) | ((Int32)uc);
|
||||||
|
|
||||||
|
if (s->origPtr < 0)
|
||||||
|
RETURN(BZ_DATA_ERROR);
|
||||||
|
if (s->origPtr > 10 + 100000*s->blockSize100k)
|
||||||
|
RETURN(BZ_DATA_ERROR);
|
||||||
|
|
||||||
|
/*--- Receive the mapping table ---*/
|
||||||
|
for (i = 0; i < 16; i++) {
|
||||||
|
GET_BIT(BZ_X_MAPPING_1, uc);
|
||||||
|
if (uc == 1)
|
||||||
|
s->inUse16[i] = True; else
|
||||||
|
s->inUse16[i] = False;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < 256; i++) s->inUse[i] = False;
|
||||||
|
|
||||||
|
for (i = 0; i < 16; i++)
|
||||||
|
if (s->inUse16[i])
|
||||||
|
for (j = 0; j < 16; j++) {
|
||||||
|
GET_BIT(BZ_X_MAPPING_2, uc);
|
||||||
|
if (uc == 1) s->inUse[i * 16 + j] = True;
|
||||||
|
}
|
||||||
|
makeMaps_d ( s );
|
||||||
|
if (s->nInUse == 0) RETURN(BZ_DATA_ERROR);
|
||||||
|
alphaSize = s->nInUse+2;
|
||||||
|
|
||||||
|
/*--- Now the selectors ---*/
|
||||||
|
GET_BITS(BZ_X_SELECTOR_1, nGroups, 3);
|
||||||
|
if (nGroups < 2 || nGroups > 6) RETURN(BZ_DATA_ERROR);
|
||||||
|
GET_BITS(BZ_X_SELECTOR_2, nSelectors, 15);
|
||||||
|
if (nSelectors < 1) RETURN(BZ_DATA_ERROR);
|
||||||
|
for (i = 0; i < nSelectors; i++) {
|
||||||
|
j = 0;
|
||||||
|
while (True) {
|
||||||
|
GET_BIT(BZ_X_SELECTOR_3, uc);
|
||||||
|
if (uc == 0) break;
|
||||||
|
j++;
|
||||||
|
if (j >= nGroups) RETURN(BZ_DATA_ERROR);
|
||||||
|
}
|
||||||
|
s->selectorMtf[i] = j;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*--- Undo the MTF values for the selectors. ---*/
|
||||||
|
{
|
||||||
|
UChar pos[BZ_N_GROUPS], tmp, v;
|
||||||
|
for (v = 0; v < nGroups; v++) pos[v] = v;
|
||||||
|
|
||||||
|
for (i = 0; i < nSelectors; i++) {
|
||||||
|
v = s->selectorMtf[i];
|
||||||
|
tmp = pos[v];
|
||||||
|
while (v > 0) { pos[v] = pos[v-1]; v--; }
|
||||||
|
pos[0] = tmp;
|
||||||
|
s->selector[i] = tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*--- Now the coding tables ---*/
|
||||||
|
for (t = 0; t < nGroups; t++) {
|
||||||
|
GET_BITS(BZ_X_CODING_1, curr, 5);
|
||||||
|
for (i = 0; i < alphaSize; i++) {
|
||||||
|
while (True) {
|
||||||
|
if (curr < 1 || curr > 20) RETURN(BZ_DATA_ERROR);
|
||||||
|
GET_BIT(BZ_X_CODING_2, uc);
|
||||||
|
if (uc == 0) break;
|
||||||
|
GET_BIT(BZ_X_CODING_3, uc);
|
||||||
|
if (uc == 0) curr++; else curr--;
|
||||||
|
}
|
||||||
|
s->len[t][i] = curr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*--- Create the Huffman decoding tables ---*/
|
||||||
|
for (t = 0; t < nGroups; t++) {
|
||||||
|
minLen = 32;
|
||||||
|
maxLen = 0;
|
||||||
|
for (i = 0; i < alphaSize; i++) {
|
||||||
|
if (s->len[t][i] > maxLen) maxLen = s->len[t][i];
|
||||||
|
if (s->len[t][i] < minLen) minLen = s->len[t][i];
|
||||||
|
}
|
||||||
|
BZ2_hbCreateDecodeTables (
|
||||||
|
&(s->limit[t][0]),
|
||||||
|
&(s->base[t][0]),
|
||||||
|
&(s->perm[t][0]),
|
||||||
|
&(s->len[t][0]),
|
||||||
|
minLen, maxLen, alphaSize
|
||||||
|
);
|
||||||
|
s->minLens[t] = minLen;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*--- Now the MTF values ---*/
|
||||||
|
|
||||||
|
EOB = s->nInUse+1;
|
||||||
|
nblockMAX = 100000 * s->blockSize100k;
|
||||||
|
groupNo = -1;
|
||||||
|
groupPos = 0;
|
||||||
|
|
||||||
|
for (i = 0; i <= 255; i++) s->unzftab[i] = 0;
|
||||||
|
|
||||||
|
/*-- MTF init --*/
|
||||||
|
{
|
||||||
|
Int32 ii, jj, kk;
|
||||||
|
kk = MTFA_SIZE-1;
|
||||||
|
for (ii = 256 / MTFL_SIZE - 1; ii >= 0; ii--) {
|
||||||
|
for (jj = MTFL_SIZE-1; jj >= 0; jj--) {
|
||||||
|
s->mtfa[kk] = (UChar)(ii * MTFL_SIZE + jj);
|
||||||
|
kk--;
|
||||||
|
}
|
||||||
|
s->mtfbase[ii] = kk + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-- end MTF init --*/
|
||||||
|
|
||||||
|
nblock = 0;
|
||||||
|
GET_MTF_VAL(BZ_X_MTF_1, BZ_X_MTF_2, nextSym);
|
||||||
|
|
||||||
|
while (True) {
|
||||||
|
|
||||||
|
if (nextSym == EOB) break;
|
||||||
|
|
||||||
|
if (nextSym == BZ_RUNA || nextSym == BZ_RUNB) {
|
||||||
|
|
||||||
|
es = -1;
|
||||||
|
N = 1;
|
||||||
|
do {
|
||||||
|
if (nextSym == BZ_RUNA) es = es + (0+1) * N; else
|
||||||
|
if (nextSym == BZ_RUNB) es = es + (1+1) * N;
|
||||||
|
N = N * 2;
|
||||||
|
GET_MTF_VAL(BZ_X_MTF_3, BZ_X_MTF_4, nextSym);
|
||||||
|
}
|
||||||
|
while (nextSym == BZ_RUNA || nextSym == BZ_RUNB);
|
||||||
|
|
||||||
|
es++;
|
||||||
|
uc = s->seqToUnseq[ s->mtfa[s->mtfbase[0]] ];
|
||||||
|
s->unzftab[uc] += es;
|
||||||
|
|
||||||
|
if (s->smallDecompress)
|
||||||
|
while (es > 0) {
|
||||||
|
if (nblock >= nblockMAX) RETURN(BZ_DATA_ERROR);
|
||||||
|
s->ll16[nblock] = (UInt16)uc;
|
||||||
|
nblock++;
|
||||||
|
es--;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
while (es > 0) {
|
||||||
|
if (nblock >= nblockMAX) RETURN(BZ_DATA_ERROR);
|
||||||
|
s->tt[nblock] = (UInt32)uc;
|
||||||
|
nblock++;
|
||||||
|
es--;
|
||||||
|
};
|
||||||
|
|
||||||
|
continue;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
if (nblock >= nblockMAX) RETURN(BZ_DATA_ERROR);
|
||||||
|
|
||||||
|
/*-- uc = MTF ( nextSym-1 ) --*/
|
||||||
|
{
|
||||||
|
Int32 ii, jj, kk, pp, lno, off;
|
||||||
|
UInt32 nn;
|
||||||
|
nn = (UInt32)(nextSym - 1);
|
||||||
|
|
||||||
|
if (nn < MTFL_SIZE) {
|
||||||
|
/* avoid general-case expense */
|
||||||
|
pp = s->mtfbase[0];
|
||||||
|
uc = s->mtfa[pp+nn];
|
||||||
|
while (nn > 3) {
|
||||||
|
Int32 z = pp+nn;
|
||||||
|
s->mtfa[(z) ] = s->mtfa[(z)-1];
|
||||||
|
s->mtfa[(z)-1] = s->mtfa[(z)-2];
|
||||||
|
s->mtfa[(z)-2] = s->mtfa[(z)-3];
|
||||||
|
s->mtfa[(z)-3] = s->mtfa[(z)-4];
|
||||||
|
nn -= 4;
|
||||||
|
}
|
||||||
|
while (nn > 0) {
|
||||||
|
s->mtfa[(pp+nn)] = s->mtfa[(pp+nn)-1]; nn--;
|
||||||
|
};
|
||||||
|
s->mtfa[pp] = uc;
|
||||||
|
} else {
|
||||||
|
/* general case */
|
||||||
|
lno = nn / MTFL_SIZE;
|
||||||
|
off = nn % MTFL_SIZE;
|
||||||
|
pp = s->mtfbase[lno] + off;
|
||||||
|
uc = s->mtfa[pp];
|
||||||
|
while (pp > s->mtfbase[lno]) {
|
||||||
|
s->mtfa[pp] = s->mtfa[pp-1]; pp--;
|
||||||
|
};
|
||||||
|
s->mtfbase[lno]++;
|
||||||
|
while (lno > 0) {
|
||||||
|
s->mtfbase[lno]--;
|
||||||
|
s->mtfa[s->mtfbase[lno]]
|
||||||
|
= s->mtfa[s->mtfbase[lno-1] + MTFL_SIZE - 1];
|
||||||
|
lno--;
|
||||||
|
}
|
||||||
|
s->mtfbase[0]--;
|
||||||
|
s->mtfa[s->mtfbase[0]] = uc;
|
||||||
|
if (s->mtfbase[0] == 0) {
|
||||||
|
kk = MTFA_SIZE-1;
|
||||||
|
for (ii = 256 / MTFL_SIZE-1; ii >= 0; ii--) {
|
||||||
|
for (jj = MTFL_SIZE-1; jj >= 0; jj--) {
|
||||||
|
s->mtfa[kk] = s->mtfa[s->mtfbase[ii] + jj];
|
||||||
|
kk--;
|
||||||
|
}
|
||||||
|
s->mtfbase[ii] = kk + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-- end uc = MTF ( nextSym-1 ) --*/
|
||||||
|
|
||||||
|
s->unzftab[s->seqToUnseq[uc]]++;
|
||||||
|
if (s->smallDecompress)
|
||||||
|
s->ll16[nblock] = (UInt16)(s->seqToUnseq[uc]); else
|
||||||
|
s->tt[nblock] = (UInt32)(s->seqToUnseq[uc]);
|
||||||
|
nblock++;
|
||||||
|
|
||||||
|
GET_MTF_VAL(BZ_X_MTF_5, BZ_X_MTF_6, nextSym);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now we know what nblock is, we can do a better sanity
|
||||||
|
check on s->origPtr.
|
||||||
|
*/
|
||||||
|
if (s->origPtr < 0 || s->origPtr >= nblock)
|
||||||
|
RETURN(BZ_DATA_ERROR);
|
||||||
|
|
||||||
|
/*-- Set up cftab to facilitate generation of T^(-1) --*/
|
||||||
|
s->cftab[0] = 0;
|
||||||
|
for (i = 1; i <= 256; i++) s->cftab[i] = s->unzftab[i-1];
|
||||||
|
for (i = 1; i <= 256; i++) s->cftab[i] += s->cftab[i-1];
|
||||||
|
for (i = 0; i <= 256; i++) {
|
||||||
|
if (s->cftab[i] < 0 || s->cftab[i] > nblock) {
|
||||||
|
/* s->cftab[i] can legitimately be == nblock */
|
||||||
|
RETURN(BZ_DATA_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
s->state_out_len = 0;
|
||||||
|
s->state_out_ch = 0;
|
||||||
|
BZ_INITIALISE_CRC ( s->calculatedBlockCRC );
|
||||||
|
s->state = BZ_X_OUTPUT;
|
||||||
|
if (s->verbosity >= 2) VPrintf0 ( "rt+rld" );
|
||||||
|
|
||||||
|
if (s->smallDecompress) {
|
||||||
|
|
||||||
|
/*-- Make a copy of cftab, used in generation of T --*/
|
||||||
|
for (i = 0; i <= 256; i++) s->cftabCopy[i] = s->cftab[i];
|
||||||
|
|
||||||
|
/*-- compute the T vector --*/
|
||||||
|
for (i = 0; i < nblock; i++) {
|
||||||
|
uc = (UChar)(s->ll16[i]);
|
||||||
|
SET_LL(i, s->cftabCopy[uc]);
|
||||||
|
s->cftabCopy[uc]++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-- Compute T^(-1) by pointer reversal on T --*/
|
||||||
|
i = s->origPtr;
|
||||||
|
j = GET_LL(i);
|
||||||
|
do {
|
||||||
|
Int32 tmp = GET_LL(j);
|
||||||
|
SET_LL(j, i);
|
||||||
|
i = j;
|
||||||
|
j = tmp;
|
||||||
|
}
|
||||||
|
while (i != s->origPtr);
|
||||||
|
|
||||||
|
s->tPos = s->origPtr;
|
||||||
|
s->nblock_used = 0;
|
||||||
|
if (s->blockRandomised) {
|
||||||
|
BZ_RAND_INIT_MASK;
|
||||||
|
BZ_GET_SMALL(s->k0); s->nblock_used++;
|
||||||
|
BZ_RAND_UPD_MASK; s->k0 ^= BZ_RAND_MASK;
|
||||||
|
} else {
|
||||||
|
BZ_GET_SMALL(s->k0); s->nblock_used++;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
/*-- compute the T^(-1) vector --*/
|
||||||
|
for (i = 0; i < nblock; i++) {
|
||||||
|
uc = (UChar)(s->tt[i] & 0xff);
|
||||||
|
s->tt[s->cftab[uc]] |= (i << 8);
|
||||||
|
s->cftab[uc]++;
|
||||||
|
}
|
||||||
|
|
||||||
|
s->tPos = s->tt[s->origPtr] >> 8;
|
||||||
|
s->nblock_used = 0;
|
||||||
|
if (s->blockRandomised) {
|
||||||
|
BZ_RAND_INIT_MASK;
|
||||||
|
BZ_GET_FAST(s->k0); s->nblock_used++;
|
||||||
|
BZ_RAND_UPD_MASK; s->k0 ^= BZ_RAND_MASK;
|
||||||
|
} else {
|
||||||
|
BZ_GET_FAST(s->k0); s->nblock_used++;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
RETURN(BZ_OK);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
endhdr_2:
|
||||||
|
|
||||||
|
GET_UCHAR(BZ_X_ENDHDR_2, uc);
|
||||||
|
if (uc != 0x72) RETURN(BZ_DATA_ERROR);
|
||||||
|
GET_UCHAR(BZ_X_ENDHDR_3, uc);
|
||||||
|
if (uc != 0x45) RETURN(BZ_DATA_ERROR);
|
||||||
|
GET_UCHAR(BZ_X_ENDHDR_4, uc);
|
||||||
|
if (uc != 0x38) RETURN(BZ_DATA_ERROR);
|
||||||
|
GET_UCHAR(BZ_X_ENDHDR_5, uc);
|
||||||
|
if (uc != 0x50) RETURN(BZ_DATA_ERROR);
|
||||||
|
GET_UCHAR(BZ_X_ENDHDR_6, uc);
|
||||||
|
if (uc != 0x90) RETURN(BZ_DATA_ERROR);
|
||||||
|
|
||||||
|
s->storedCombinedCRC = 0;
|
||||||
|
GET_UCHAR(BZ_X_CCRC_1, uc);
|
||||||
|
s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc);
|
||||||
|
GET_UCHAR(BZ_X_CCRC_2, uc);
|
||||||
|
s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc);
|
||||||
|
GET_UCHAR(BZ_X_CCRC_3, uc);
|
||||||
|
s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc);
|
||||||
|
GET_UCHAR(BZ_X_CCRC_4, uc);
|
||||||
|
s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc);
|
||||||
|
|
||||||
|
s->state = BZ_X_IDLE;
|
||||||
|
RETURN(BZ_STREAM_END);
|
||||||
|
|
||||||
|
default: AssertH ( False, 4001 );
|
||||||
|
}
|
||||||
|
|
||||||
|
AssertH ( False, 4002 );
|
||||||
|
|
||||||
|
save_state_and_return:
|
||||||
|
|
||||||
|
s->save_i = i;
|
||||||
|
s->save_j = j;
|
||||||
|
s->save_t = t;
|
||||||
|
s->save_alphaSize = alphaSize;
|
||||||
|
s->save_nGroups = nGroups;
|
||||||
|
s->save_nSelectors = nSelectors;
|
||||||
|
s->save_EOB = EOB;
|
||||||
|
s->save_groupNo = groupNo;
|
||||||
|
s->save_groupPos = groupPos;
|
||||||
|
s->save_nextSym = nextSym;
|
||||||
|
s->save_nblockMAX = nblockMAX;
|
||||||
|
s->save_nblock = nblock;
|
||||||
|
s->save_es = es;
|
||||||
|
s->save_N = N;
|
||||||
|
s->save_curr = curr;
|
||||||
|
s->save_zt = zt;
|
||||||
|
s->save_zn = zn;
|
||||||
|
s->save_zvec = zvec;
|
||||||
|
s->save_zj = zj;
|
||||||
|
s->save_gSel = gSel;
|
||||||
|
s->save_gMinlen = gMinlen;
|
||||||
|
s->save_gLimit = gLimit;
|
||||||
|
s->save_gBase = gBase;
|
||||||
|
s->save_gPerm = gPerm;
|
||||||
|
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------*/
|
||||||
|
/*--- end decompress.c ---*/
|
||||||
|
/*-------------------------------------------------------------*/
|
|
@ -0,0 +1,205 @@
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------*/
|
||||||
|
/*--- Huffman coding low-level stuff ---*/
|
||||||
|
/*--- huffman.c ---*/
|
||||||
|
/*-------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------
|
||||||
|
This file is part of bzip2/libbzip2, a program and library for
|
||||||
|
lossless, block-sorting data compression.
|
||||||
|
|
||||||
|
bzip2/libbzip2 version 1.0.4 of 20 December 2006
|
||||||
|
Copyright (C) 1996-2006 Julian Seward <jseward@bzip.org>
|
||||||
|
|
||||||
|
Please read the WARNING, DISCLAIMER and PATENTS sections in the
|
||||||
|
README file.
|
||||||
|
|
||||||
|
This program is released under the terms of the license contained
|
||||||
|
in the file LICENSE.
|
||||||
|
------------------------------------------------------------------ */
|
||||||
|
|
||||||
|
|
||||||
|
#include "bzlib_private.h"
|
||||||
|
|
||||||
|
/*---------------------------------------------------*/
|
||||||
|
#define WEIGHTOF(zz0) ((zz0) & 0xffffff00)
|
||||||
|
#define DEPTHOF(zz1) ((zz1) & 0x000000ff)
|
||||||
|
#define MYMAX(zz2,zz3) ((zz2) > (zz3) ? (zz2) : (zz3))
|
||||||
|
|
||||||
|
#define ADDWEIGHTS(zw1,zw2) \
|
||||||
|
(WEIGHTOF(zw1)+WEIGHTOF(zw2)) | \
|
||||||
|
(1 + MYMAX(DEPTHOF(zw1),DEPTHOF(zw2)))
|
||||||
|
|
||||||
|
#define UPHEAP(z) \
|
||||||
|
{ \
|
||||||
|
Int32 zz, tmp; \
|
||||||
|
zz = z; tmp = heap[zz]; \
|
||||||
|
while (weight[tmp] < weight[heap[zz >> 1]]) { \
|
||||||
|
heap[zz] = heap[zz >> 1]; \
|
||||||
|
zz >>= 1; \
|
||||||
|
} \
|
||||||
|
heap[zz] = tmp; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define DOWNHEAP(z) \
|
||||||
|
{ \
|
||||||
|
Int32 zz, yy, tmp; \
|
||||||
|
zz = z; tmp = heap[zz]; \
|
||||||
|
while (True) { \
|
||||||
|
yy = zz << 1; \
|
||||||
|
if (yy > nHeap) break; \
|
||||||
|
if (yy < nHeap && \
|
||||||
|
weight[heap[yy+1]] < weight[heap[yy]]) \
|
||||||
|
yy++; \
|
||||||
|
if (weight[tmp] < weight[heap[yy]]) break; \
|
||||||
|
heap[zz] = heap[yy]; \
|
||||||
|
zz = yy; \
|
||||||
|
} \
|
||||||
|
heap[zz] = tmp; \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*---------------------------------------------------*/
|
||||||
|
void BZ2_hbMakeCodeLengths ( UChar *len,
|
||||||
|
Int32 *freq,
|
||||||
|
Int32 alphaSize,
|
||||||
|
Int32 maxLen )
|
||||||
|
{
|
||||||
|
/*--
|
||||||
|
Nodes and heap entries run from 1. Entry 0
|
||||||
|
for both the heap and nodes is a sentinel.
|
||||||
|
--*/
|
||||||
|
Int32 nNodes, nHeap, n1, n2, i, j, k;
|
||||||
|
Bool tooLong;
|
||||||
|
|
||||||
|
Int32 heap [ BZ_MAX_ALPHA_SIZE + 2 ];
|
||||||
|
Int32 weight [ BZ_MAX_ALPHA_SIZE * 2 ];
|
||||||
|
Int32 parent [ BZ_MAX_ALPHA_SIZE * 2 ];
|
||||||
|
|
||||||
|
for (i = 0; i < alphaSize; i++)
|
||||||
|
weight[i+1] = (freq[i] == 0 ? 1 : freq[i]) << 8;
|
||||||
|
|
||||||
|
while (True) {
|
||||||
|
|
||||||
|
nNodes = alphaSize;
|
||||||
|
nHeap = 0;
|
||||||
|
|
||||||
|
heap[0] = 0;
|
||||||
|
weight[0] = 0;
|
||||||
|
parent[0] = -2;
|
||||||
|
|
||||||
|
for (i = 1; i <= alphaSize; i++) {
|
||||||
|
parent[i] = -1;
|
||||||
|
nHeap++;
|
||||||
|
heap[nHeap] = i;
|
||||||
|
UPHEAP(nHeap);
|
||||||
|
}
|
||||||
|
|
||||||
|
AssertH( nHeap < (BZ_MAX_ALPHA_SIZE+2), 2001 );
|
||||||
|
|
||||||
|
while (nHeap > 1) {
|
||||||
|
n1 = heap[1]; heap[1] = heap[nHeap]; nHeap--; DOWNHEAP(1);
|
||||||
|
n2 = heap[1]; heap[1] = heap[nHeap]; nHeap--; DOWNHEAP(1);
|
||||||
|
nNodes++;
|
||||||
|
parent[n1] = parent[n2] = nNodes;
|
||||||
|
weight[nNodes] = ADDWEIGHTS(weight[n1], weight[n2]);
|
||||||
|
parent[nNodes] = -1;
|
||||||
|
nHeap++;
|
||||||
|
heap[nHeap] = nNodes;
|
||||||
|
UPHEAP(nHeap);
|
||||||
|
}
|
||||||
|
|
||||||
|
AssertH( nNodes < (BZ_MAX_ALPHA_SIZE * 2), 2002 );
|
||||||
|
|
||||||
|
tooLong = False;
|
||||||
|
for (i = 1; i <= alphaSize; i++) {
|
||||||
|
j = 0;
|
||||||
|
k = i;
|
||||||
|
while (parent[k] >= 0) { k = parent[k]; j++; }
|
||||||
|
len[i-1] = j;
|
||||||
|
if (j > maxLen) tooLong = True;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! tooLong) break;
|
||||||
|
|
||||||
|
/* 17 Oct 04: keep-going condition for the following loop used
|
||||||
|
to be 'i < alphaSize', which missed the last element,
|
||||||
|
theoretically leading to the possibility of the compressor
|
||||||
|
looping. However, this count-scaling step is only needed if
|
||||||
|
one of the generated Huffman code words is longer than
|
||||||
|
maxLen, which up to and including version 1.0.2 was 20 bits,
|
||||||
|
which is extremely unlikely. In version 1.0.3 maxLen was
|
||||||
|
changed to 17 bits, which has minimal effect on compression
|
||||||
|
ratio, but does mean this scaling step is used from time to
|
||||||
|
time, enough to verify that it works.
|
||||||
|
|
||||||
|
This means that bzip2-1.0.3 and later will only produce
|
||||||
|
Huffman codes with a maximum length of 17 bits. However, in
|
||||||
|
order to preserve backwards compatibility with bitstreams
|
||||||
|
produced by versions pre-1.0.3, the decompressor must still
|
||||||
|
handle lengths of up to 20. */
|
||||||
|
|
||||||
|
for (i = 1; i <= alphaSize; i++) {
|
||||||
|
j = weight[i] >> 8;
|
||||||
|
j = 1 + (j / 2);
|
||||||
|
weight[i] = j << 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*---------------------------------------------------*/
|
||||||
|
void BZ2_hbAssignCodes ( Int32 *code,
|
||||||
|
UChar *length,
|
||||||
|
Int32 minLen,
|
||||||
|
Int32 maxLen,
|
||||||
|
Int32 alphaSize )
|
||||||
|
{
|
||||||
|
Int32 n, vec, i;
|
||||||
|
|
||||||
|
vec = 0;
|
||||||
|
for (n = minLen; n <= maxLen; n++) {
|
||||||
|
for (i = 0; i < alphaSize; i++)
|
||||||
|
if (length[i] == n) { code[i] = vec; vec++; };
|
||||||
|
vec <<= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*---------------------------------------------------*/
|
||||||
|
void BZ2_hbCreateDecodeTables ( Int32 *limit,
|
||||||
|
Int32 *base,
|
||||||
|
Int32 *perm,
|
||||||
|
UChar *length,
|
||||||
|
Int32 minLen,
|
||||||
|
Int32 maxLen,
|
||||||
|
Int32 alphaSize )
|
||||||
|
{
|
||||||
|
Int32 pp, i, j, vec;
|
||||||
|
|
||||||
|
pp = 0;
|
||||||
|
for (i = minLen; i <= maxLen; i++)
|
||||||
|
for (j = 0; j < alphaSize; j++)
|
||||||
|
if (length[j] == i) { perm[pp] = j; pp++; };
|
||||||
|
|
||||||
|
for (i = 0; i < BZ_MAX_CODE_LEN; i++) base[i] = 0;
|
||||||
|
for (i = 0; i < alphaSize; i++) base[length[i]+1]++;
|
||||||
|
|
||||||
|
for (i = 1; i < BZ_MAX_CODE_LEN; i++) base[i] += base[i-1];
|
||||||
|
|
||||||
|
for (i = 0; i < BZ_MAX_CODE_LEN; i++) limit[i] = 0;
|
||||||
|
vec = 0;
|
||||||
|
|
||||||
|
for (i = minLen; i <= maxLen; i++) {
|
||||||
|
vec += (base[i+1] - base[i]);
|
||||||
|
limit[i] = vec-1;
|
||||||
|
vec <<= 1;
|
||||||
|
}
|
||||||
|
for (i = minLen + 1; i <= maxLen; i++)
|
||||||
|
base[i] = ((limit[i-1] + 1) << 1) - base[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------*/
|
||||||
|
/*--- end huffman.c ---*/
|
||||||
|
/*-------------------------------------------------------------*/
|
|
@ -0,0 +1,84 @@
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------*/
|
||||||
|
/*--- Table for randomising repetitive blocks ---*/
|
||||||
|
/*--- randtable.c ---*/
|
||||||
|
/*-------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------
|
||||||
|
This file is part of bzip2/libbzip2, a program and library for
|
||||||
|
lossless, block-sorting data compression.
|
||||||
|
|
||||||
|
bzip2/libbzip2 version 1.0.4 of 20 December 2006
|
||||||
|
Copyright (C) 1996-2006 Julian Seward <jseward@bzip.org>
|
||||||
|
|
||||||
|
Please read the WARNING, DISCLAIMER and PATENTS sections in the
|
||||||
|
README file.
|
||||||
|
|
||||||
|
This program is released under the terms of the license contained
|
||||||
|
in the file LICENSE.
|
||||||
|
------------------------------------------------------------------ */
|
||||||
|
|
||||||
|
|
||||||
|
#include "bzlib_private.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*---------------------------------------------*/
|
||||||
|
Int32 BZ2_rNums[512] = {
|
||||||
|
619, 720, 127, 481, 931, 816, 813, 233, 566, 247,
|
||||||
|
985, 724, 205, 454, 863, 491, 741, 242, 949, 214,
|
||||||
|
733, 859, 335, 708, 621, 574, 73, 654, 730, 472,
|
||||||
|
419, 436, 278, 496, 867, 210, 399, 680, 480, 51,
|
||||||
|
878, 465, 811, 169, 869, 675, 611, 697, 867, 561,
|
||||||
|
862, 687, 507, 283, 482, 129, 807, 591, 733, 623,
|
||||||
|
150, 238, 59, 379, 684, 877, 625, 169, 643, 105,
|
||||||
|
170, 607, 520, 932, 727, 476, 693, 425, 174, 647,
|
||||||
|
73, 122, 335, 530, 442, 853, 695, 249, 445, 515,
|
||||||
|
909, 545, 703, 919, 874, 474, 882, 500, 594, 612,
|
||||||
|
641, 801, 220, 162, 819, 984, 589, 513, 495, 799,
|
||||||
|
161, 604, 958, 533, 221, 400, 386, 867, 600, 782,
|
||||||
|
382, 596, 414, 171, 516, 375, 682, 485, 911, 276,
|
||||||
|
98, 553, 163, 354, 666, 933, 424, 341, 533, 870,
|
||||||
|
227, 730, 475, 186, 263, 647, 537, 686, 600, 224,
|
||||||
|
469, 68, 770, 919, 190, 373, 294, 822, 808, 206,
|
||||||
|
184, 943, 795, 384, 383, 461, 404, 758, 839, 887,
|
||||||
|
715, 67, 618, 276, 204, 918, 873, 777, 604, 560,
|
||||||
|
951, 160, 578, 722, 79, 804, 96, 409, 713, 940,
|
||||||
|
652, 934, 970, 447, 318, 353, 859, 672, 112, 785,
|
||||||
|
645, 863, 803, 350, 139, 93, 354, 99, 820, 908,
|
||||||
|
609, 772, 154, 274, 580, 184, 79, 626, 630, 742,
|
||||||
|
653, 282, 762, 623, 680, 81, 927, 626, 789, 125,
|
||||||
|
411, 521, 938, 300, 821, 78, 343, 175, 128, 250,
|
||||||
|
170, 774, 972, 275, 999, 639, 495, 78, 352, 126,
|
||||||
|
857, 956, 358, 619, 580, 124, 737, 594, 701, 612,
|
||||||
|
669, 112, 134, 694, 363, 992, 809, 743, 168, 974,
|
||||||
|
944, 375, 748, 52, 600, 747, 642, 182, 862, 81,
|
||||||
|
344, 805, 988, 739, 511, 655, 814, 334, 249, 515,
|
||||||
|
897, 955, 664, 981, 649, 113, 974, 459, 893, 228,
|
||||||
|
433, 837, 553, 268, 926, 240, 102, 654, 459, 51,
|
||||||
|
686, 754, 806, 760, 493, 403, 415, 394, 687, 700,
|
||||||
|
946, 670, 656, 610, 738, 392, 760, 799, 887, 653,
|
||||||
|
978, 321, 576, 617, 626, 502, 894, 679, 243, 440,
|
||||||
|
680, 879, 194, 572, 640, 724, 926, 56, 204, 700,
|
||||||
|
707, 151, 457, 449, 797, 195, 791, 558, 945, 679,
|
||||||
|
297, 59, 87, 824, 713, 663, 412, 693, 342, 606,
|
||||||
|
134, 108, 571, 364, 631, 212, 174, 643, 304, 329,
|
||||||
|
343, 97, 430, 751, 497, 314, 983, 374, 822, 928,
|
||||||
|
140, 206, 73, 263, 980, 736, 876, 478, 430, 305,
|
||||||
|
170, 514, 364, 692, 829, 82, 855, 953, 676, 246,
|
||||||
|
369, 970, 294, 750, 807, 827, 150, 790, 288, 923,
|
||||||
|
804, 378, 215, 828, 592, 281, 565, 555, 710, 82,
|
||||||
|
896, 831, 547, 261, 524, 462, 293, 465, 502, 56,
|
||||||
|
661, 821, 976, 991, 658, 869, 905, 758, 745, 193,
|
||||||
|
768, 550, 608, 933, 378, 286, 215, 979, 792, 961,
|
||||||
|
61, 688, 793, 644, 986, 403, 106, 366, 905, 644,
|
||||||
|
372, 567, 466, 434, 645, 210, 389, 550, 919, 135,
|
||||||
|
780, 773, 635, 389, 707, 100, 626, 958, 165, 504,
|
||||||
|
920, 176, 193, 713, 857, 265, 203, 50, 668, 108,
|
||||||
|
645, 990, 626, 197, 510, 357, 358, 850, 858, 364,
|
||||||
|
936, 638
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------*/
|
||||||
|
/*--- end randtable.c ---*/
|
||||||
|
/*-------------------------------------------------------------*/
|
|
@ -0,0 +1,855 @@
|
||||||
|
|
||||||
|
ChangeLog file for zlib
|
||||||
|
|
||||||
|
Changes in 1.2.3 (18 July 2005)
|
||||||
|
- Apply security vulnerability fixes to contrib/infback9 as well
|
||||||
|
- Clean up some text files (carriage returns, trailing space)
|
||||||
|
- Update testzlib, vstudio, masmx64, and masmx86 in contrib [Vollant]
|
||||||
|
|
||||||
|
Changes in 1.2.2.4 (11 July 2005)
|
||||||
|
- Add inflatePrime() function for starting inflation at bit boundary
|
||||||
|
- Avoid some Visual C warnings in deflate.c
|
||||||
|
- Avoid more silly Visual C warnings in inflate.c and inftrees.c for 64-bit
|
||||||
|
compile
|
||||||
|
- Fix some spelling errors in comments [Betts]
|
||||||
|
- Correct inflateInit2() error return documentation in zlib.h
|
||||||
|
- Added zran.c example of compressed data random access to examples
|
||||||
|
directory, shows use of inflatePrime()
|
||||||
|
- Fix cast for assignments to strm->state in inflate.c and infback.c
|
||||||
|
- Fix zlibCompileFlags() in zutil.c to use 1L for long shifts [Oberhumer]
|
||||||
|
- Move declarations of gf2 functions to right place in crc32.c [Oberhumer]
|
||||||
|
- Add cast in trees.c t avoid a warning [Oberhumer]
|
||||||
|
- Avoid some warnings in fitblk.c, gun.c, gzjoin.c in examples [Oberhumer]
|
||||||
|
- Update make_vms.com [Zinser]
|
||||||
|
- Initialize state->write in inflateReset() since copied in inflate_fast()
|
||||||
|
- Be more strict on incomplete code sets in inflate_table() and increase
|
||||||
|
ENOUGH and MAXD -- this repairs a possible security vulnerability for
|
||||||
|
invalid inflate input. Thanks to Tavis Ormandy and Markus Oberhumer for
|
||||||
|
discovering the vulnerability and providing test cases.
|
||||||
|
- Add ia64 support to configure for HP-UX [Smith]
|
||||||
|
- Add error return to gzread() for format or i/o error [Levin]
|
||||||
|
- Use malloc.h for OS/2 [Necasek]
|
||||||
|
|
||||||
|
Changes in 1.2.2.3 (27 May 2005)
|
||||||
|
- Replace 1U constants in inflate.c and inftrees.c for 64-bit compile
|
||||||
|
- Typecast fread() return values in gzio.c [Vollant]
|
||||||
|
- Remove trailing space in minigzip.c outmode (VC++ can't deal with it)
|
||||||
|
- Fix crc check bug in gzread() after gzungetc() [Heiner]
|
||||||
|
- Add the deflateTune() function to adjust internal compression parameters
|
||||||
|
- Add a fast gzip decompressor, gun.c, to examples (use of inflateBack)
|
||||||
|
- Remove an incorrect assertion in examples/zpipe.c
|
||||||
|
- Add C++ wrapper in infback9.h [Donais]
|
||||||
|
- Fix bug in inflateCopy() when decoding fixed codes
|
||||||
|
- Note in zlib.h how much deflateSetDictionary() actually uses
|
||||||
|
- Remove USE_DICT_HEAD in deflate.c (would mess up inflate if used)
|
||||||
|
- Add _WIN32_WCE to define WIN32 in zconf.in.h [Spencer]
|
||||||
|
- Don't include stderr.h or errno.h for _WIN32_WCE in zutil.h [Spencer]
|
||||||
|
- Add gzdirect() function to indicate transparent reads
|
||||||
|
- Update contrib/minizip [Vollant]
|
||||||
|
- Fix compilation of deflate.c when both ASMV and FASTEST [Oberhumer]
|
||||||
|
- Add casts in crc32.c to avoid warnings [Oberhumer]
|
||||||
|
- Add contrib/masmx64 [Vollant]
|
||||||
|
- Update contrib/asm586, asm686, masmx86, testzlib, vstudio [Vollant]
|
||||||
|
|
||||||
|
Changes in 1.2.2.2 (30 December 2004)
|
||||||
|
- Replace structure assignments in deflate.c and inflate.c with zmemcpy to
|
||||||
|
avoid implicit memcpy calls (portability for no-library compilation)
|
||||||
|
- Increase sprintf() buffer size in gzdopen() to allow for large numbers
|
||||||
|
- Add INFLATE_STRICT to check distances against zlib header
|
||||||
|
- Improve WinCE errno handling and comments [Chang]
|
||||||
|
- Remove comment about no gzip header processing in FAQ
|
||||||
|
- Add Z_FIXED strategy option to deflateInit2() to force fixed trees
|
||||||
|
- Add updated make_vms.com [Coghlan], update README
|
||||||
|
- Create a new "examples" directory, move gzappend.c there, add zpipe.c,
|
||||||
|
fitblk.c, gzlog.[ch], gzjoin.c, and zlib_how.html.
|
||||||
|
- Add FAQ entry and comments in deflate.c on uninitialized memory access
|
||||||
|
- Add Solaris 9 make options in configure [Gilbert]
|
||||||
|
- Allow strerror() usage in gzio.c for STDC
|
||||||
|
- Fix DecompressBuf in contrib/delphi/ZLib.pas [ManChesTer]
|
||||||
|
- Update contrib/masmx86/inffas32.asm and gvmat32.asm [Vollant]
|
||||||
|
- Use z_off_t for adler32_combine() and crc32_combine() lengths
|
||||||
|
- Make adler32() much faster for small len
|
||||||
|
- Use OS_CODE in deflate() default gzip header
|
||||||
|
|
||||||
|
Changes in 1.2.2.1 (31 October 2004)
|
||||||
|
- Allow inflateSetDictionary() call for raw inflate
|
||||||
|
- Fix inflate header crc check bug for file names and comments
|
||||||
|
- Add deflateSetHeader() and gz_header structure for custom gzip headers
|
||||||
|
- Add inflateGetheader() to retrieve gzip headers
|
||||||
|
- Add crc32_combine() and adler32_combine() functions
|
||||||
|
- Add alloc_func, free_func, in_func, out_func to Z_PREFIX list
|
||||||
|
- Use zstreamp consistently in zlib.h (inflate_back functions)
|
||||||
|
- Remove GUNZIP condition from definition of inflate_mode in inflate.h
|
||||||
|
and in contrib/inflate86/inffast.S [Truta, Anderson]
|
||||||
|
- Add support for AMD64 in contrib/inflate86/inffas86.c [Anderson]
|
||||||
|
- Update projects/README.projects and projects/visualc6 [Truta]
|
||||||
|
- Update win32/DLL_FAQ.txt [Truta]
|
||||||
|
- Avoid warning under NO_GZCOMPRESS in gzio.c; fix typo [Truta]
|
||||||
|
- Deprecate Z_ASCII; use Z_TEXT instead [Truta]
|
||||||
|
- Use a new algorithm for setting strm->data_type in trees.c [Truta]
|
||||||
|
- Do not define an exit() prototype in zutil.c unless DEBUG defined
|
||||||
|
- Remove prototype of exit() from zutil.c, example.c, minigzip.c [Truta]
|
||||||
|
- Add comment in zlib.h for Z_NO_FLUSH parameter to deflate()
|
||||||
|
- Fix Darwin build version identification [Peterson]
|
||||||
|
|
||||||
|
Changes in 1.2.2 (3 October 2004)
|
||||||
|
- Update zlib.h comments on gzip in-memory processing
|
||||||
|
- Set adler to 1 in inflateReset() to support Java test suite [Walles]
|
||||||
|
- Add contrib/dotzlib [Ravn]
|
||||||
|
- Update win32/DLL_FAQ.txt [Truta]
|
||||||
|
- Update contrib/minizip [Vollant]
|
||||||
|
- Move contrib/visual-basic.txt to old/ [Truta]
|
||||||
|
- Fix assembler builds in projects/visualc6/ [Truta]
|
||||||
|
|
||||||
|
Changes in 1.2.1.2 (9 September 2004)
|
||||||
|
- Update INDEX file
|
||||||
|
- Fix trees.c to update strm->data_type (no one ever noticed!)
|
||||||
|
- Fix bug in error case in inflate.c, infback.c, and infback9.c [Brown]
|
||||||
|
- Add "volatile" to crc table flag declaration (for DYNAMIC_CRC_TABLE)
|
||||||
|
- Add limited multitasking protection to DYNAMIC_CRC_TABLE
|
||||||
|
- Add NO_vsnprintf for VMS in zutil.h [Mozilla]
|
||||||
|
- Don't declare strerror() under VMS [Mozilla]
|
||||||
|
- Add comment to DYNAMIC_CRC_TABLE to use get_crc_table() to initialize
|
||||||
|
- Update contrib/ada [Anisimkov]
|
||||||
|
- Update contrib/minizip [Vollant]
|
||||||
|
- Fix configure to not hardcode directories for Darwin [Peterson]
|
||||||
|
- Fix gzio.c to not return error on empty files [Brown]
|
||||||
|
- Fix indentation; update version in contrib/delphi/ZLib.pas and
|
||||||
|
contrib/pascal/zlibpas.pas [Truta]
|
||||||
|
- Update mkasm.bat in contrib/masmx86 [Truta]
|
||||||
|
- Update contrib/untgz [Truta]
|
||||||
|
- Add projects/README.projects [Truta]
|
||||||
|
- Add project for MS Visual C++ 6.0 in projects/visualc6 [Cadieux, Truta]
|
||||||
|
- Update win32/DLL_FAQ.txt [Truta]
|
||||||
|
- Update list of Z_PREFIX symbols in zconf.h [Randers-Pehrson, Truta]
|
||||||
|
- Remove an unnecessary assignment to curr in inftrees.c [Truta]
|
||||||
|
- Add OS/2 to exe builds in configure [Poltorak]
|
||||||
|
- Remove err dummy parameter in zlib.h [Kientzle]
|
||||||
|
|
||||||
|
Changes in 1.2.1.1 (9 January 2004)
|
||||||
|
- Update email address in README
|
||||||
|
- Several FAQ updates
|
||||||
|
- Fix a big fat bug in inftrees.c that prevented decoding valid
|
||||||
|
dynamic blocks with only literals and no distance codes --
|
||||||
|
Thanks to "Hot Emu" for the bug report and sample file
|
||||||
|
- Add a note to puff.c on no distance codes case.
|
||||||
|
|
||||||
|
Changes in 1.2.1 (17 November 2003)
|
||||||
|
- Remove a tab in contrib/gzappend/gzappend.c
|
||||||
|
- Update some interfaces in contrib for new zlib functions
|
||||||
|
- Update zlib version number in some contrib entries
|
||||||
|
- Add Windows CE definition for ptrdiff_t in zutil.h [Mai, Truta]
|
||||||
|
- Support shared libraries on Hurd and KFreeBSD [Brown]
|
||||||
|
- Fix error in NO_DIVIDE option of adler32.c
|
||||||
|
|
||||||
|
Changes in 1.2.0.8 (4 November 2003)
|
||||||
|
- Update version in contrib/delphi/ZLib.pas and contrib/pascal/zlibpas.pas
|
||||||
|
- Add experimental NO_DIVIDE #define in adler32.c
|
||||||
|
- Possibly faster on some processors (let me know if it is)
|
||||||
|
- Correct Z_BLOCK to not return on first inflate call if no wrap
|
||||||
|
- Fix strm->data_type on inflate() return to correctly indicate EOB
|
||||||
|
- Add deflatePrime() function for appending in the middle of a byte
|
||||||
|
- Add contrib/gzappend for an example of appending to a stream
|
||||||
|
- Update win32/DLL_FAQ.txt [Truta]
|
||||||
|
- Delete Turbo C comment in README [Truta]
|
||||||
|
- Improve some indentation in zconf.h [Truta]
|
||||||
|
- Fix infinite loop on bad input in configure script [Church]
|
||||||
|
- Fix gzeof() for concatenated gzip files [Johnson]
|
||||||
|
- Add example to contrib/visual-basic.txt [Michael B.]
|
||||||
|
- Add -p to mkdir's in Makefile.in [vda]
|
||||||
|
- Fix configure to properly detect presence or lack of printf functions
|
||||||
|
- Add AS400 support [Monnerat]
|
||||||
|
- Add a little Cygwin support [Wilson]
|
||||||
|
|
||||||
|
Changes in 1.2.0.7 (21 September 2003)
|
||||||
|
- Correct some debug formats in contrib/infback9
|
||||||
|
- Cast a type in a debug statement in trees.c
|
||||||
|
- Change search and replace delimiter in configure from % to # [Beebe]
|
||||||
|
- Update contrib/untgz to 0.2 with various fixes [Truta]
|
||||||
|
- Add build support for Amiga [Nikl]
|
||||||
|
- Remove some directories in old that have been updated to 1.2
|
||||||
|
- Add dylib building for Mac OS X in configure and Makefile.in
|
||||||
|
- Remove old distribution stuff from Makefile
|
||||||
|
- Update README to point to DLL_FAQ.txt, and add comment on Mac OS X
|
||||||
|
- Update links in README
|
||||||
|
|
||||||
|
Changes in 1.2.0.6 (13 September 2003)
|
||||||
|
- Minor FAQ updates
|
||||||
|
- Update contrib/minizip to 1.00 [Vollant]
|
||||||
|
- Remove test of gz functions in example.c when GZ_COMPRESS defined [Truta]
|
||||||
|
- Update POSTINC comment for 68060 [Nikl]
|
||||||
|
- Add contrib/infback9 with deflate64 decoding (unsupported)
|
||||||
|
- For MVS define NO_vsnprintf and undefine FAR [van Burik]
|
||||||
|
- Add pragma for fdopen on MVS [van Burik]
|
||||||
|
|
||||||
|
Changes in 1.2.0.5 (8 September 2003)
|
||||||
|
- Add OF to inflateBackEnd() declaration in zlib.h
|
||||||
|
- Remember start when using gzdopen in the middle of a file
|
||||||
|
- Use internal off_t counters in gz* functions to properly handle seeks
|
||||||
|
- Perform more rigorous check for distance-too-far in inffast.c
|
||||||
|
- Add Z_BLOCK flush option to return from inflate at block boundary
|
||||||
|
- Set strm->data_type on return from inflate
|
||||||
|
- Indicate bits unused, if at block boundary, and if in last block
|
||||||
|
- Replace size_t with ptrdiff_t in crc32.c, and check for correct size
|
||||||
|
- Add condition so old NO_DEFLATE define still works for compatibility
|
||||||
|
- FAQ update regarding the Windows DLL [Truta]
|
||||||
|
- INDEX update: add qnx entry, remove aix entry [Truta]
|
||||||
|
- Install zlib.3 into mandir [Wilson]
|
||||||
|
- Move contrib/zlib_dll_FAQ.txt to win32/DLL_FAQ.txt; update [Truta]
|
||||||
|
- Adapt the zlib interface to the new DLL convention guidelines [Truta]
|
||||||
|
- Introduce ZLIB_WINAPI macro to allow the export of functions using
|
||||||
|
the WINAPI calling convention, for Visual Basic [Vollant, Truta]
|
||||||
|
- Update msdos and win32 scripts and makefiles [Truta]
|
||||||
|
- Export symbols by name, not by ordinal, in win32/zlib.def [Truta]
|
||||||
|
- Add contrib/ada [Anisimkov]
|
||||||
|
- Move asm files from contrib/vstudio/vc70_32 to contrib/asm386 [Truta]
|
||||||
|
- Rename contrib/asm386 to contrib/masmx86 [Truta, Vollant]
|
||||||
|
- Add contrib/masm686 [Truta]
|
||||||
|
- Fix offsets in contrib/inflate86 and contrib/masmx86/inffas32.asm
|
||||||
|
[Truta, Vollant]
|
||||||
|
- Update contrib/delphi; rename to contrib/pascal; add example [Truta]
|
||||||
|
- Remove contrib/delphi2; add a new contrib/delphi [Truta]
|
||||||
|
- Avoid inclusion of the nonstandard <memory.h> in contrib/iostream,
|
||||||
|
and fix some method prototypes [Truta]
|
||||||
|
- Fix the ZCR_SEED2 constant to avoid warnings in contrib/minizip
|
||||||
|
[Truta]
|
||||||
|
- Avoid the use of backslash (\) in contrib/minizip [Vollant]
|
||||||
|
- Fix file time handling in contrib/untgz; update makefiles [Truta]
|
||||||
|
- Update contrib/vstudio/vc70_32 to comply with the new DLL guidelines
|
||||||
|
[Vollant]
|
||||||
|
- Remove contrib/vstudio/vc15_16 [Vollant]
|
||||||
|
- Rename contrib/vstudio/vc70_32 to contrib/vstudio/vc7 [Truta]
|
||||||
|
- Update README.contrib [Truta]
|
||||||
|
- Invert the assignment order of match_head and s->prev[...] in
|
||||||
|
INSERT_STRING [Truta]
|
||||||
|
- Compare TOO_FAR with 32767 instead of 32768, to avoid 16-bit warnings
|
||||||
|
[Truta]
|
||||||
|
- Compare function pointers with 0, not with NULL or Z_NULL [Truta]
|
||||||
|
- Fix prototype of syncsearch in inflate.c [Truta]
|
||||||
|
- Introduce ASMINF macro to be enabled when using an ASM implementation
|
||||||
|
of inflate_fast [Truta]
|
||||||
|
- Change NO_DEFLATE to NO_GZCOMPRESS [Truta]
|
||||||
|
- Modify test_gzio in example.c to take a single file name as a
|
||||||
|
parameter [Truta]
|
||||||
|
- Exit the example.c program if gzopen fails [Truta]
|
||||||
|
- Add type casts around strlen in example.c [Truta]
|
||||||
|
- Remove casting to sizeof in minigzip.c; give a proper type
|
||||||
|
to the variable compared with SUFFIX_LEN [Truta]
|
||||||
|
- Update definitions of STDC and STDC99 in zconf.h [Truta]
|
||||||
|
- Synchronize zconf.h with the new Windows DLL interface [Truta]
|
||||||
|
- Use SYS16BIT instead of __32BIT__ to distinguish between
|
||||||
|
16- and 32-bit platforms [Truta]
|
||||||
|
- Use far memory allocators in small 16-bit memory models for
|
||||||
|
Turbo C [Truta]
|
||||||
|
- Add info about the use of ASMV, ASMINF and ZLIB_WINAPI in
|
||||||
|
zlibCompileFlags [Truta]
|
||||||
|
- Cygwin has vsnprintf [Wilson]
|
||||||
|
- In Windows16, OS_CODE is 0, as in MSDOS [Truta]
|
||||||
|
- In Cygwin, OS_CODE is 3 (Unix), not 11 (Windows32) [Wilson]
|
||||||
|
|
||||||
|
Changes in 1.2.0.4 (10 August 2003)
|
||||||
|
- Minor FAQ updates
|
||||||
|
- Be more strict when checking inflateInit2's windowBits parameter
|
||||||
|
- Change NO_GUNZIP compile option to NO_GZIP to cover deflate as well
|
||||||
|
- Add gzip wrapper option to deflateInit2 using windowBits
|
||||||
|
- Add updated QNX rule in configure and qnx directory [Bonnefoy]
|
||||||
|
- Make inflate distance-too-far checks more rigorous
|
||||||
|
- Clean up FAR usage in inflate
|
||||||
|
- Add casting to sizeof() in gzio.c and minigzip.c
|
||||||
|
|
||||||
|
Changes in 1.2.0.3 (19 July 2003)
|
||||||
|
- Fix silly error in gzungetc() implementation [Vollant]
|
||||||
|
- Update contrib/minizip and contrib/vstudio [Vollant]
|
||||||
|
- Fix printf format in example.c
|
||||||
|
- Correct cdecl support in zconf.in.h [Anisimkov]
|
||||||
|
- Minor FAQ updates
|
||||||
|
|
||||||
|
Changes in 1.2.0.2 (13 July 2003)
|
||||||
|
- Add ZLIB_VERNUM in zlib.h for numerical preprocessor comparisons
|
||||||
|
- Attempt to avoid warnings in crc32.c for pointer-int conversion
|
||||||
|
- Add AIX to configure, remove aix directory [Bakker]
|
||||||
|
- Add some casts to minigzip.c
|
||||||
|
- Improve checking after insecure sprintf() or vsprintf() calls
|
||||||
|
- Remove #elif's from crc32.c
|
||||||
|
- Change leave label to inf_leave in inflate.c and infback.c to avoid
|
||||||
|
library conflicts
|
||||||
|
- Remove inflate gzip decoding by default--only enable gzip decoding by
|
||||||
|
special request for stricter backward compatibility
|
||||||
|
- Add zlibCompileFlags() function to return compilation information
|
||||||
|
- More typecasting in deflate.c to avoid warnings
|
||||||
|
- Remove leading underscore from _Capital #defines [Truta]
|
||||||
|
- Fix configure to link shared library when testing
|
||||||
|
- Add some Windows CE target adjustments [Mai]
|
||||||
|
- Remove #define ZLIB_DLL in zconf.h [Vollant]
|
||||||
|
- Add zlib.3 [Rodgers]
|
||||||
|
- Update RFC URL in deflate.c and algorithm.txt [Mai]
|
||||||
|
- Add zlib_dll_FAQ.txt to contrib [Truta]
|
||||||
|
- Add UL to some constants [Truta]
|
||||||
|
- Update minizip and vstudio [Vollant]
|
||||||
|
- Remove vestigial NEED_DUMMY_RETURN from zconf.in.h
|
||||||
|
- Expand use of NO_DUMMY_DECL to avoid all dummy structures
|
||||||
|
- Added iostream3 to contrib [Schwardt]
|
||||||
|
- Replace rewind() with fseek() for WinCE [Truta]
|
||||||
|
- Improve setting of zlib format compression level flags
|
||||||
|
- Report 0 for huffman and rle strategies and for level == 0 or 1
|
||||||
|
- Report 2 only for level == 6
|
||||||
|
- Only deal with 64K limit when necessary at compile time [Truta]
|
||||||
|
- Allow TOO_FAR check to be turned off at compile time [Truta]
|
||||||
|
- Add gzclearerr() function [Souza]
|
||||||
|
- Add gzungetc() function
|
||||||
|
|
||||||
|
Changes in 1.2.0.1 (17 March 2003)
|
||||||
|
- Add Z_RLE strategy for run-length encoding [Truta]
|
||||||
|
- When Z_RLE requested, restrict matches to distance one
|
||||||
|
- Update zlib.h, minigzip.c, gzopen(), gzdopen() for Z_RLE
|
||||||
|
- Correct FASTEST compilation to allow level == 0
|
||||||
|
- Clean up what gets compiled for FASTEST
|
||||||
|
- Incorporate changes to zconf.in.h [Vollant]
|
||||||
|
- Refine detection of Turbo C need for dummy returns
|
||||||
|
- Refine ZLIB_DLL compilation
|
||||||
|
- Include additional header file on VMS for off_t typedef
|
||||||
|
- Try to use _vsnprintf where it supplants vsprintf [Vollant]
|
||||||
|
- Add some casts in inffast.c
|
||||||
|
- Enchance comments in zlib.h on what happens if gzprintf() tries to
|
||||||
|
write more than 4095 bytes before compression
|
||||||
|
- Remove unused state from inflateBackEnd()
|
||||||
|
- Remove exit(0) from minigzip.c, example.c
|
||||||
|
- Get rid of all those darn tabs
|
||||||
|
- Add "check" target to Makefile.in that does the same thing as "test"
|
||||||
|
- Add "mostlyclean" and "maintainer-clean" targets to Makefile.in
|
||||||
|
- Update contrib/inflate86 [Anderson]
|
||||||
|
- Update contrib/testzlib, contrib/vstudio, contrib/minizip [Vollant]
|
||||||
|
- Add msdos and win32 directories with makefiles [Truta]
|
||||||
|
- More additions and improvements to the FAQ
|
||||||
|
|
||||||
|
Changes in 1.2.0 (9 March 2003)
|
||||||
|
- New and improved inflate code
|
||||||
|
- About 20% faster
|
||||||
|
- Does not allocate 32K window unless and until needed
|
||||||
|
- Automatically detects and decompresses gzip streams
|
||||||
|
- Raw inflate no longer needs an extra dummy byte at end
|
||||||
|
- Added inflateBack functions using a callback interface--even faster
|
||||||
|
than inflate, useful for file utilities (gzip, zip)
|
||||||
|
- Added inflateCopy() function to record state for random access on
|
||||||
|
externally generated deflate streams (e.g. in gzip files)
|
||||||
|
- More readable code (I hope)
|
||||||
|
- New and improved crc32()
|
||||||
|
- About 50% faster, thanks to suggestions from Rodney Brown
|
||||||
|
- Add deflateBound() and compressBound() functions
|
||||||
|
- Fix memory leak in deflateInit2()
|
||||||
|
- Permit setting dictionary for raw deflate (for parallel deflate)
|
||||||
|
- Fix const declaration for gzwrite()
|
||||||
|
- Check for some malloc() failures in gzio.c
|
||||||
|
- Fix bug in gzopen() on single-byte file 0x1f
|
||||||
|
- Fix bug in gzread() on concatenated file with 0x1f at end of buffer
|
||||||
|
and next buffer doesn't start with 0x8b
|
||||||
|
- Fix uncompress() to return Z_DATA_ERROR on truncated input
|
||||||
|
- Free memory at end of example.c
|
||||||
|
- Remove MAX #define in trees.c (conflicted with some libraries)
|
||||||
|
- Fix static const's in deflate.c, gzio.c, and zutil.[ch]
|
||||||
|
- Declare malloc() and free() in gzio.c if STDC not defined
|
||||||
|
- Use malloc() instead of calloc() in zutil.c if int big enough
|
||||||
|
- Define STDC for AIX
|
||||||
|
- Add aix/ with approach for compiling shared library on AIX
|
||||||
|
- Add HP-UX support for shared libraries in configure
|
||||||
|
- Add OpenUNIX support for shared libraries in configure
|
||||||
|
- Use $cc instead of gcc to build shared library
|
||||||
|
- Make prefix directory if needed when installing
|
||||||
|
- Correct Macintosh avoidance of typedef Byte in zconf.h
|
||||||
|
- Correct Turbo C memory allocation when under Linux
|
||||||
|
- Use libz.a instead of -lz in Makefile (assure use of compiled library)
|
||||||
|
- Update configure to check for snprintf or vsnprintf functions and their
|
||||||
|
return value, warn during make if using an insecure function
|
||||||
|
- Fix configure problem with compile-time knowledge of HAVE_UNISTD_H that
|
||||||
|
is lost when library is used--resolution is to build new zconf.h
|
||||||
|
- Documentation improvements (in zlib.h):
|
||||||
|
- Document raw deflate and inflate
|
||||||
|
- Update RFCs URL
|
||||||
|
- Point out that zlib and gzip formats are different
|
||||||
|
- Note that Z_BUF_ERROR is not fatal
|
||||||
|
- Document string limit for gzprintf() and possible buffer overflow
|
||||||
|
- Note requirement on avail_out when flushing
|
||||||
|
- Note permitted values of flush parameter of inflate()
|
||||||
|
- Add some FAQs (and even answers) to the FAQ
|
||||||
|
- Add contrib/inflate86/ for x86 faster inflate
|
||||||
|
- Add contrib/blast/ for PKWare Data Compression Library decompression
|
||||||
|
- Add contrib/puff/ simple inflate for deflate format description
|
||||||
|
|
||||||
|
Changes in 1.1.4 (11 March 2002)
|
||||||
|
- ZFREE was repeated on same allocation on some error conditions.
|
||||||
|
This creates a security problem described in
|
||||||
|
http://www.zlib.org/advisory-2002-03-11.txt
|
||||||
|
- Returned incorrect error (Z_MEM_ERROR) on some invalid data
|
||||||
|
- Avoid accesses before window for invalid distances with inflate window
|
||||||
|
less than 32K.
|
||||||
|
- force windowBits > 8 to avoid a bug in the encoder for a window size
|
||||||
|
of 256 bytes. (A complete fix will be available in 1.1.5).
|
||||||
|
|
||||||
|
Changes in 1.1.3 (9 July 1998)
|
||||||
|
- fix "an inflate input buffer bug that shows up on rare but persistent
|
||||||
|
occasions" (Mark)
|
||||||
|
- fix gzread and gztell for concatenated .gz files (Didier Le Botlan)
|
||||||
|
- fix gzseek(..., SEEK_SET) in write mode
|
||||||
|
- fix crc check after a gzeek (Frank Faubert)
|
||||||
|
- fix miniunzip when the last entry in a zip file is itself a zip file
|
||||||
|
(J Lillge)
|
||||||
|
- add contrib/asm586 and contrib/asm686 (Brian Raiter)
|
||||||
|
See http://www.muppetlabs.com/~breadbox/software/assembly.html
|
||||||
|
- add support for Delphi 3 in contrib/delphi (Bob Dellaca)
|
||||||
|
- add support for C++Builder 3 and Delphi 3 in contrib/delphi2 (Davide Moretti)
|
||||||
|
- do not exit prematurely in untgz if 0 at start of block (Magnus Holmgren)
|
||||||
|
- use macro EXTERN instead of extern to support DLL for BeOS (Sander Stoks)
|
||||||
|
- added a FAQ file
|
||||||
|
|
||||||
|
- Support gzdopen on Mac with Metrowerks (Jason Linhart)
|
||||||
|
- Do not redefine Byte on Mac (Brad Pettit & Jason Linhart)
|
||||||
|
- define SEEK_END too if SEEK_SET is not defined (Albert Chin-A-Young)
|
||||||
|
- avoid some warnings with Borland C (Tom Tanner)
|
||||||
|
- fix a problem in contrib/minizip/zip.c for 16-bit MSDOS (Gilles Vollant)
|
||||||
|
- emulate utime() for WIN32 in contrib/untgz (Gilles Vollant)
|
||||||
|
- allow several arguments to configure (Tim Mooney, Frodo Looijaard)
|
||||||
|
- use libdir and includedir in Makefile.in (Tim Mooney)
|
||||||
|
- support shared libraries on OSF1 V4 (Tim Mooney)
|
||||||
|
- remove so_locations in "make clean" (Tim Mooney)
|
||||||
|
- fix maketree.c compilation error (Glenn, Mark)
|
||||||
|
- Python interface to zlib now in Python 1.5 (Jeremy Hylton)
|
||||||
|
- new Makefile.riscos (Rich Walker)
|
||||||
|
- initialize static descriptors in trees.c for embedded targets (Nick Smith)
|
||||||
|
- use "foo-gz" in example.c for RISCOS and VMS (Nick Smith)
|
||||||
|
- add the OS/2 files in Makefile.in too (Andrew Zabolotny)
|
||||||
|
- fix fdopen and halloc macros for Microsoft C 6.0 (Tom Lane)
|
||||||
|
- fix maketree.c to allow clean compilation of inffixed.h (Mark)
|
||||||
|
- fix parameter check in deflateCopy (Gunther Nikl)
|
||||||
|
- cleanup trees.c, use compressed_len only in debug mode (Christian Spieler)
|
||||||
|
- Many portability patches by Christian Spieler:
|
||||||
|
. zutil.c, zutil.h: added "const" for zmem*
|
||||||
|
. Make_vms.com: fixed some typos
|
||||||
|
. Make_vms.com: msdos/Makefile.*: removed zutil.h from some dependency lists
|
||||||
|
. msdos/Makefile.msc: remove "default rtl link library" info from obj files
|
||||||
|
. msdos/Makefile.*: use model-dependent name for the built zlib library
|
||||||
|
. msdos/Makefile.emx, nt/Makefile.emx, nt/Makefile.gcc:
|
||||||
|
new makefiles, for emx (DOS/OS2), emx&rsxnt and mingw32 (Windows 9x / NT)
|
||||||
|
- use define instead of typedef for Bytef also for MSC small/medium (Tom Lane)
|
||||||
|
- replace __far with _far for better portability (Christian Spieler, Tom Lane)
|
||||||
|
- fix test for errno.h in configure (Tim Newsham)
|
||||||
|
|
||||||
|
Changes in 1.1.2 (19 March 98)
|
||||||
|
- added contrib/minzip, mini zip and unzip based on zlib (Gilles Vollant)
|
||||||
|
See http://www.winimage.com/zLibDll/unzip.html
|
||||||
|
- preinitialize the inflate tables for fixed codes, to make the code
|
||||||
|
completely thread safe (Mark)
|
||||||
|
- some simplifications and slight speed-up to the inflate code (Mark)
|
||||||
|
- fix gzeof on non-compressed files (Allan Schrum)
|
||||||
|
- add -std1 option in configure for OSF1 to fix gzprintf (Martin Mokrejs)
|
||||||
|
- use default value of 4K for Z_BUFSIZE for 16-bit MSDOS (Tim Wegner + Glenn)
|
||||||
|
- added os2/Makefile.def and os2/zlib.def (Andrew Zabolotny)
|
||||||
|
- add shared lib support for UNIX_SV4.2MP (MATSUURA Takanori)
|
||||||
|
- do not wrap extern "C" around system includes (Tom Lane)
|
||||||
|
- mention zlib binding for TCL in README (Andreas Kupries)
|
||||||
|
- added amiga/Makefile.pup for Amiga powerUP SAS/C PPC (Andreas Kleinert)
|
||||||
|
- allow "make install prefix=..." even after configure (Glenn Randers-Pehrson)
|
||||||
|
- allow "configure --prefix $HOME" (Tim Mooney)
|
||||||
|
- remove warnings in example.c and gzio.c (Glenn Randers-Pehrson)
|
||||||
|
- move Makefile.sas to amiga/Makefile.sas
|
||||||
|
|
||||||
|
Changes in 1.1.1 (27 Feb 98)
|
||||||
|
- fix macros _tr_tally_* in deflate.h for debug mode (Glenn Randers-Pehrson)
|
||||||
|
- remove block truncation heuristic which had very marginal effect for zlib
|
||||||
|
(smaller lit_bufsize than in gzip 1.2.4) and degraded a little the
|
||||||
|
compression ratio on some files. This also allows inlining _tr_tally for
|
||||||
|
matches in deflate_slow.
|
||||||
|
- added msdos/Makefile.w32 for WIN32 Microsoft Visual C++ (Bob Frazier)
|
||||||
|
|
||||||
|
Changes in 1.1.0 (24 Feb 98)
|
||||||
|
- do not return STREAM_END prematurely in inflate (John Bowler)
|
||||||
|
- revert to the zlib 1.0.8 inflate to avoid the gcc 2.8.0 bug (Jeremy Buhler)
|
||||||
|
- compile with -DFASTEST to get compression code optimized for speed only
|
||||||
|
- in minigzip, try mmap'ing the input file first (Miguel Albrecht)
|
||||||
|
- increase size of I/O buffers in minigzip.c and gzio.c (not a big gain
|
||||||
|
on Sun but significant on HP)
|
||||||
|
|
||||||
|
- add a pointer to experimental unzip library in README (Gilles Vollant)
|
||||||
|
- initialize variable gcc in configure (Chris Herborth)
|
||||||
|
|
||||||
|
Changes in 1.0.9 (17 Feb 1998)
|
||||||
|
- added gzputs and gzgets functions
|
||||||
|
- do not clear eof flag in gzseek (Mark Diekhans)
|
||||||
|
- fix gzseek for files in transparent mode (Mark Diekhans)
|
||||||
|
- do not assume that vsprintf returns the number of bytes written (Jens Krinke)
|
||||||
|
- replace EXPORT with ZEXPORT to avoid conflict with other programs
|
||||||
|
- added compress2 in zconf.h, zlib.def, zlib.dnt
|
||||||
|
- new asm code from Gilles Vollant in contrib/asm386
|
||||||
|
- simplify the inflate code (Mark):
|
||||||
|
. Replace ZALLOC's in huft_build() with single ZALLOC in inflate_blocks_new()
|
||||||
|
. ZALLOC the length list in inflate_trees_fixed() instead of using stack
|
||||||
|
. ZALLOC the value area for huft_build() instead of using stack
|
||||||
|
. Simplify Z_FINISH check in inflate()
|
||||||
|
|
||||||
|
- Avoid gcc 2.8.0 comparison bug a little differently than zlib 1.0.8
|
||||||
|
- in inftrees.c, avoid cc -O bug on HP (Farshid Elahi)
|
||||||
|
- in zconf.h move the ZLIB_DLL stuff earlier to avoid problems with
|
||||||
|
the declaration of FAR (Gilles VOllant)
|
||||||
|
- install libz.so* with mode 755 (executable) instead of 644 (Marc Lehmann)
|
||||||
|
- read_buf buf parameter of type Bytef* instead of charf*
|
||||||
|
- zmemcpy parameters are of type Bytef*, not charf* (Joseph Strout)
|
||||||
|
- do not redeclare unlink in minigzip.c for WIN32 (John Bowler)
|
||||||
|
- fix check for presence of directories in "make install" (Ian Willis)
|
||||||
|
|
||||||
|
Changes in 1.0.8 (27 Jan 1998)
|
||||||
|
- fixed offsets in contrib/asm386/gvmat32.asm (Gilles Vollant)
|
||||||
|
- fix gzgetc and gzputc for big endian systems (Markus Oberhumer)
|
||||||
|
- added compress2() to allow setting the compression level
|
||||||
|
- include sys/types.h to get off_t on some systems (Marc Lehmann & QingLong)
|
||||||
|
- use constant arrays for the static trees in trees.c instead of computing
|
||||||
|
them at run time (thanks to Ken Raeburn for this suggestion). To create
|
||||||
|
trees.h, compile with GEN_TREES_H and run "make test".
|
||||||
|
- check return code of example in "make test" and display result
|
||||||
|
- pass minigzip command line options to file_compress
|
||||||
|
- simplifying code of inflateSync to avoid gcc 2.8 bug
|
||||||
|
|
||||||
|
- support CC="gcc -Wall" in configure -s (QingLong)
|
||||||
|
- avoid a flush caused by ftell in gzopen for write mode (Ken Raeburn)
|
||||||
|
- fix test for shared library support to avoid compiler warnings
|
||||||
|
- zlib.lib -> zlib.dll in msdos/zlib.rc (Gilles Vollant)
|
||||||
|
- check for TARGET_OS_MAC in addition to MACOS (Brad Pettit)
|
||||||
|
- do not use fdopen for Metrowerks on Mac (Brad Pettit))
|
||||||
|
- add checks for gzputc and gzputc in example.c
|
||||||
|
- avoid warnings in gzio.c and deflate.c (Andreas Kleinert)
|
||||||
|
- use const for the CRC table (Ken Raeburn)
|
||||||
|
- fixed "make uninstall" for shared libraries
|
||||||
|
- use Tracev instead of Trace in infblock.c
|
||||||
|
- in example.c use correct compressed length for test_sync
|
||||||
|
- suppress +vnocompatwarnings in configure for HPUX (not always supported)
|
||||||
|
|
||||||
|
Changes in 1.0.7 (20 Jan 1998)
|
||||||
|
- fix gzseek which was broken in write mode
|
||||||
|
- return error for gzseek to negative absolute position
|
||||||
|
- fix configure for Linux (Chun-Chung Chen)
|
||||||
|
- increase stack space for MSC (Tim Wegner)
|
||||||
|
- get_crc_table and inflateSyncPoint are EXPORTed (Gilles Vollant)
|
||||||
|
- define EXPORTVA for gzprintf (Gilles Vollant)
|
||||||
|
- added man page zlib.3 (Rick Rodgers)
|
||||||
|
- for contrib/untgz, fix makedir() and improve Makefile
|
||||||
|
|
||||||
|
- check gzseek in write mode in example.c
|
||||||
|
- allocate extra buffer for seeks only if gzseek is actually called
|
||||||
|
- avoid signed/unsigned comparisons (Tim Wegner, Gilles Vollant)
|
||||||
|
- add inflateSyncPoint in zconf.h
|
||||||
|
- fix list of exported functions in nt/zlib.dnt and mdsos/zlib.def
|
||||||
|
|
||||||
|
Changes in 1.0.6 (19 Jan 1998)
|
||||||
|
- add functions gzprintf, gzputc, gzgetc, gztell, gzeof, gzseek, gzrewind and
|
||||||
|
gzsetparams (thanks to Roland Giersig and Kevin Ruland for some of this code)
|
||||||
|
- Fix a deflate bug occurring only with compression level 0 (thanks to
|
||||||
|
Andy Buckler for finding this one).
|
||||||
|
- In minigzip, pass transparently also the first byte for .Z files.
|
||||||
|
- return Z_BUF_ERROR instead of Z_OK if output buffer full in uncompress()
|
||||||
|
- check Z_FINISH in inflate (thanks to Marc Schluper)
|
||||||
|
- Implement deflateCopy (thanks to Adam Costello)
|
||||||
|
- make static libraries by default in configure, add --shared option.
|
||||||
|
- move MSDOS or Windows specific files to directory msdos
|
||||||
|
- suppress the notion of partial flush to simplify the interface
|
||||||
|
(but the symbol Z_PARTIAL_FLUSH is kept for compatibility with 1.0.4)
|
||||||
|
- suppress history buffer provided by application to simplify the interface
|
||||||
|
(this feature was not implemented anyway in 1.0.4)
|
||||||
|
- next_in and avail_in must be initialized before calling inflateInit or
|
||||||
|
inflateInit2
|
||||||
|
- add EXPORT in all exported functions (for Windows DLL)
|
||||||
|
- added Makefile.nt (thanks to Stephen Williams)
|
||||||
|
- added the unsupported "contrib" directory:
|
||||||
|
contrib/asm386/ by Gilles Vollant <info@winimage.com>
|
||||||
|
386 asm code replacing longest_match().
|
||||||
|
contrib/iostream/ by Kevin Ruland <kevin@rodin.wustl.edu>
|
||||||
|
A C++ I/O streams interface to the zlib gz* functions
|
||||||
|
contrib/iostream2/ by Tyge Løvset <Tyge.Lovset@cmr.no>
|
||||||
|
Another C++ I/O streams interface
|
||||||
|
contrib/untgz/ by "Pedro A. Aranda Guti\irrez" <paag@tid.es>
|
||||||
|
A very simple tar.gz file extractor using zlib
|
||||||
|
contrib/visual-basic.txt by Carlos Rios <c_rios@sonda.cl>
|
||||||
|
How to use compress(), uncompress() and the gz* functions from VB.
|
||||||
|
- pass params -f (filtered data), -h (huffman only), -1 to -9 (compression
|
||||||
|
level) in minigzip (thanks to Tom Lane)
|
||||||
|
|
||||||
|
- use const for rommable constants in deflate
|
||||||
|
- added test for gzseek and gztell in example.c
|
||||||
|
- add undocumented function inflateSyncPoint() (hack for Paul Mackerras)
|
||||||
|
- add undocumented function zError to convert error code to string
|
||||||
|
(for Tim Smithers)
|
||||||
|
- Allow compilation of gzio with -DNO_DEFLATE to avoid the compression code.
|
||||||
|
- Use default memcpy for Symantec MSDOS compiler.
|
||||||
|
- Add EXPORT keyword for check_func (needed for Windows DLL)
|
||||||
|
- add current directory to LD_LIBRARY_PATH for "make test"
|
||||||
|
- create also a link for libz.so.1
|
||||||
|
- added support for FUJITSU UXP/DS (thanks to Toshiaki Nomura)
|
||||||
|
- use $(SHAREDLIB) instead of libz.so in Makefile.in (for HPUX)
|
||||||
|
- added -soname for Linux in configure (Chun-Chung Chen,
|
||||||
|
- assign numbers to the exported functions in zlib.def (for Windows DLL)
|
||||||
|
- add advice in zlib.h for best usage of deflateSetDictionary
|
||||||
|
- work around compiler bug on Atari (cast Z_NULL in call of s->checkfn)
|
||||||
|
- allow compilation with ANSI keywords only enabled for TurboC in large model
|
||||||
|
- avoid "versionString"[0] (Borland bug)
|
||||||
|
- add NEED_DUMMY_RETURN for Borland
|
||||||
|
- use variable z_verbose for tracing in debug mode (L. Peter Deutsch).
|
||||||
|
- allow compilation with CC
|
||||||
|
- defined STDC for OS/2 (David Charlap)
|
||||||
|
- limit external names to 8 chars for MVS (Thomas Lund)
|
||||||
|
- in minigzip.c, use static buffers only for 16-bit systems
|
||||||
|
- fix suffix check for "minigzip -d foo.gz"
|
||||||
|
- do not return an error for the 2nd of two consecutive gzflush() (Felix Lee)
|
||||||
|
- use _fdopen instead of fdopen for MSC >= 6.0 (Thomas Fanslau)
|
||||||
|
- added makelcc.bat for lcc-win32 (Tom St Denis)
|
||||||
|
- in Makefile.dj2, use copy and del instead of install and rm (Frank Donahoe)
|
||||||
|
- Avoid expanded $Id$. Use "rcs -kb" or "cvs admin -kb" to avoid Id expansion.
|
||||||
|
- check for unistd.h in configure (for off_t)
|
||||||
|
- remove useless check parameter in inflate_blocks_free
|
||||||
|
- avoid useless assignment of s->check to itself in inflate_blocks_new
|
||||||
|
- do not flush twice in gzclose (thanks to Ken Raeburn)
|
||||||
|
- rename FOPEN as F_OPEN to avoid clash with /usr/include/sys/file.h
|
||||||
|
- use NO_ERRNO_H instead of enumeration of operating systems with errno.h
|
||||||
|
- work around buggy fclose on pipes for HP/UX
|
||||||
|
- support zlib DLL with BORLAND C++ 5.0 (thanks to Glenn Randers-Pehrson)
|
||||||
|
- fix configure if CC is already equal to gcc
|
||||||
|
|
||||||
|
Changes in 1.0.5 (3 Jan 98)
|
||||||
|
- Fix inflate to terminate gracefully when fed corrupted or invalid data
|
||||||
|
- Use const for rommable constants in inflate
|
||||||
|
- Eliminate memory leaks on error conditions in inflate
|
||||||
|
- Removed some vestigial code in inflate
|
||||||
|
- Update web address in README
|
||||||
|
|
||||||
|
Changes in 1.0.4 (24 Jul 96)
|
||||||
|
- In very rare conditions, deflate(s, Z_FINISH) could fail to produce an EOF
|
||||||
|
bit, so the decompressor could decompress all the correct data but went
|
||||||
|
on to attempt decompressing extra garbage data. This affected minigzip too.
|
||||||
|
- zlibVersion and gzerror return const char* (needed for DLL)
|
||||||
|
- port to RISCOS (no fdopen, no multiple dots, no unlink, no fileno)
|
||||||
|
- use z_error only for DEBUG (avoid problem with DLLs)
|
||||||
|
|
||||||
|
Changes in 1.0.3 (2 Jul 96)
|
||||||
|
- use z_streamp instead of z_stream *, which is now a far pointer in MSDOS
|
||||||
|
small and medium models; this makes the library incompatible with previous
|
||||||
|
versions for these models. (No effect in large model or on other systems.)
|
||||||
|
- return OK instead of BUF_ERROR if previous deflate call returned with
|
||||||
|
avail_out as zero but there is nothing to do
|
||||||
|
- added memcmp for non STDC compilers
|
||||||
|
- define NO_DUMMY_DECL for more Mac compilers (.h files merged incorrectly)
|
||||||
|
- define __32BIT__ if __386__ or i386 is defined (pb. with Watcom and SCO)
|
||||||
|
- better check for 16-bit mode MSC (avoids problem with Symantec)
|
||||||
|
|
||||||
|
Changes in 1.0.2 (23 May 96)
|
||||||
|
- added Windows DLL support
|
||||||
|
- added a function zlibVersion (for the DLL support)
|
||||||
|
- fixed declarations using Bytef in infutil.c (pb with MSDOS medium model)
|
||||||
|
- Bytef is define's instead of typedef'd only for Borland C
|
||||||
|
- avoid reading uninitialized memory in example.c
|
||||||
|
- mention in README that the zlib format is now RFC1950
|
||||||
|
- updated Makefile.dj2
|
||||||
|
- added algorithm.doc
|
||||||
|
|
||||||
|
Changes in 1.0.1 (20 May 96) [1.0 skipped to avoid confusion]
|
||||||
|
- fix array overlay in deflate.c which sometimes caused bad compressed data
|
||||||
|
- fix inflate bug with empty stored block
|
||||||
|
- fix MSDOS medium model which was broken in 0.99
|
||||||
|
- fix deflateParams() which could generated bad compressed data.
|
||||||
|
- Bytef is define'd instead of typedef'ed (work around Borland bug)
|
||||||
|
- added an INDEX file
|
||||||
|
- new makefiles for DJGPP (Makefile.dj2), 32-bit Borland (Makefile.b32),
|
||||||
|
Watcom (Makefile.wat), Amiga SAS/C (Makefile.sas)
|
||||||
|
- speed up adler32 for modern machines without auto-increment
|
||||||
|
- added -ansi for IRIX in configure
|
||||||
|
- static_init_done in trees.c is an int
|
||||||
|
- define unlink as delete for VMS
|
||||||
|
- fix configure for QNX
|
||||||
|
- add configure branch for SCO and HPUX
|
||||||
|
- avoid many warnings (unused variables, dead assignments, etc...)
|
||||||
|
- no fdopen for BeOS
|
||||||
|
- fix the Watcom fix for 32 bit mode (define FAR as empty)
|
||||||
|
- removed redefinition of Byte for MKWERKS
|
||||||
|
- work around an MWKERKS bug (incorrect merge of all .h files)
|
||||||
|
|
||||||
|
Changes in 0.99 (27 Jan 96)
|
||||||
|
- allow preset dictionary shared between compressor and decompressor
|
||||||
|
- allow compression level 0 (no compression)
|
||||||
|
- add deflateParams in zlib.h: allow dynamic change of compression level
|
||||||
|
and compression strategy.
|
||||||
|
- test large buffers and deflateParams in example.c
|
||||||
|
- add optional "configure" to build zlib as a shared library
|
||||||
|
- suppress Makefile.qnx, use configure instead
|
||||||
|
- fixed deflate for 64-bit systems (detected on Cray)
|
||||||
|
- fixed inflate_blocks for 64-bit systems (detected on Alpha)
|
||||||
|
- declare Z_DEFLATED in zlib.h (possible parameter for deflateInit2)
|
||||||
|
- always return Z_BUF_ERROR when deflate() has nothing to do
|
||||||
|
- deflateInit and inflateInit are now macros to allow version checking
|
||||||
|
- prefix all global functions and types with z_ with -DZ_PREFIX
|
||||||
|
- make falloc completely reentrant (inftrees.c)
|
||||||
|
- fixed very unlikely race condition in ct_static_init
|
||||||
|
- free in reverse order of allocation to help memory manager
|
||||||
|
- use zlib-1.0/* instead of zlib/* inside the tar.gz
|
||||||
|
- make zlib warning-free with "gcc -O3 -Wall -Wwrite-strings -Wpointer-arith
|
||||||
|
-Wconversion -Wstrict-prototypes -Wmissing-prototypes"
|
||||||
|
- allow gzread on concatenated .gz files
|
||||||
|
- deflateEnd now returns Z_DATA_ERROR if it was premature
|
||||||
|
- deflate is finally (?) fully deterministic (no matches beyond end of input)
|
||||||
|
- Document Z_SYNC_FLUSH
|
||||||
|
- add uninstall in Makefile
|
||||||
|
- Check for __cpluplus in zlib.h
|
||||||
|
- Better test in ct_align for partial flush
|
||||||
|
- avoid harmless warnings for Borland C++
|
||||||
|
- initialize hash_head in deflate.c
|
||||||
|
- avoid warning on fdopen (gzio.c) for HP cc -Aa
|
||||||
|
- include stdlib.h for STDC compilers
|
||||||
|
- include errno.h for Cray
|
||||||
|
- ignore error if ranlib doesn't exist
|
||||||
|
- call ranlib twice for NeXTSTEP
|
||||||
|
- use exec_prefix instead of prefix for libz.a
|
||||||
|
- renamed ct_* as _tr_* to avoid conflict with applications
|
||||||
|
- clear z->msg in inflateInit2 before any error return
|
||||||
|
- initialize opaque in example.c, gzio.c, deflate.c and inflate.c
|
||||||
|
- fixed typo in zconf.h (_GNUC__ => __GNUC__)
|
||||||
|
- check for WIN32 in zconf.h and zutil.c (avoid farmalloc in 32-bit mode)
|
||||||
|
- fix typo in Make_vms.com (f$trnlnm -> f$getsyi)
|
||||||
|
- in fcalloc, normalize pointer if size > 65520 bytes
|
||||||
|
- don't use special fcalloc for 32 bit Borland C++
|
||||||
|
- use STDC instead of __GO32__ to avoid redeclaring exit, calloc, etc...
|
||||||
|
- use Z_BINARY instead of BINARY
|
||||||
|
- document that gzclose after gzdopen will close the file
|
||||||
|
- allow "a" as mode in gzopen.
|
||||||
|
- fix error checking in gzread
|
||||||
|
- allow skipping .gz extra-field on pipes
|
||||||
|
- added reference to Perl interface in README
|
||||||
|
- put the crc table in FAR data (I dislike more and more the medium model :)
|
||||||
|
- added get_crc_table
|
||||||
|
- added a dimension to all arrays (Borland C can't count).
|
||||||
|
- workaround Borland C bug in declaration of inflate_codes_new & inflate_fast
|
||||||
|
- guard against multiple inclusion of *.h (for precompiled header on Mac)
|
||||||
|
- Watcom C pretends to be Microsoft C small model even in 32 bit mode.
|
||||||
|
- don't use unsized arrays to avoid silly warnings by Visual C++:
|
||||||
|
warning C4746: 'inflate_mask' : unsized array treated as '__far'
|
||||||
|
(what's wrong with far data in far model?).
|
||||||
|
- define enum out of inflate_blocks_state to allow compilation with C++
|
||||||
|
|
||||||
|
Changes in 0.95 (16 Aug 95)
|
||||||
|
- fix MSDOS small and medium model (now easier to adapt to any compiler)
|
||||||
|
- inlined send_bits
|
||||||
|
- fix the final (:-) bug for deflate with flush (output was correct but
|
||||||
|
not completely flushed in rare occasions).
|
||||||
|
- default window size is same for compression and decompression
|
||||||
|
(it's now sufficient to set MAX_WBITS in zconf.h).
|
||||||
|
- voidp -> voidpf and voidnp -> voidp (for consistency with other
|
||||||
|
typedefs and because voidnp was not near in large model).
|
||||||
|
|
||||||
|
Changes in 0.94 (13 Aug 95)
|
||||||
|
- support MSDOS medium model
|
||||||
|
- fix deflate with flush (could sometimes generate bad output)
|
||||||
|
- fix deflateReset (zlib header was incorrectly suppressed)
|
||||||
|
- added support for VMS
|
||||||
|
- allow a compression level in gzopen()
|
||||||
|
- gzflush now calls fflush
|
||||||
|
- For deflate with flush, flush even if no more input is provided.
|
||||||
|
- rename libgz.a as libz.a
|
||||||
|
- avoid complex expression in infcodes.c triggering Turbo C bug
|
||||||
|
- work around a problem with gcc on Alpha (in INSERT_STRING)
|
||||||
|
- don't use inline functions (problem with some gcc versions)
|
||||||
|
- allow renaming of Byte, uInt, etc... with #define.
|
||||||
|
- avoid warning about (unused) pointer before start of array in deflate.c
|
||||||
|
- avoid various warnings in gzio.c, example.c, infblock.c, adler32.c, zutil.c
|
||||||
|
- avoid reserved word 'new' in trees.c
|
||||||
|
|
||||||
|
Changes in 0.93 (25 June 95)
|
||||||
|
- temporarily disable inline functions
|
||||||
|
- make deflate deterministic
|
||||||
|
- give enough lookahead for PARTIAL_FLUSH
|
||||||
|
- Set binary mode for stdin/stdout in minigzip.c for OS/2
|
||||||
|
- don't even use signed char in inflate (not portable enough)
|
||||||
|
- fix inflate memory leak for segmented architectures
|
||||||
|
|
||||||
|
Changes in 0.92 (3 May 95)
|
||||||
|
- don't assume that char is signed (problem on SGI)
|
||||||
|
- Clear bit buffer when starting a stored block
|
||||||
|
- no memcpy on Pyramid
|
||||||
|
- suppressed inftest.c
|
||||||
|
- optimized fill_window, put longest_match inline for gcc
|
||||||
|
- optimized inflate on stored blocks.
|
||||||
|
- untabify all sources to simplify patches
|
||||||
|
|
||||||
|
Changes in 0.91 (2 May 95)
|
||||||
|
- Default MEM_LEVEL is 8 (not 9 for Unix) as documented in zlib.h
|
||||||
|
- Document the memory requirements in zconf.h
|
||||||
|
- added "make install"
|
||||||
|
- fix sync search logic in inflateSync
|
||||||
|
- deflate(Z_FULL_FLUSH) now works even if output buffer too short
|
||||||
|
- after inflateSync, don't scare people with just "lo world"
|
||||||
|
- added support for DJGPP
|
||||||
|
|
||||||
|
Changes in 0.9 (1 May 95)
|
||||||
|
- don't assume that zalloc clears the allocated memory (the TurboC bug
|
||||||
|
was Mark's bug after all :)
|
||||||
|
- let again gzread copy uncompressed data unchanged (was working in 0.71)
|
||||||
|
- deflate(Z_FULL_FLUSH), inflateReset and inflateSync are now fully implemented
|
||||||
|
- added a test of inflateSync in example.c
|
||||||
|
- moved MAX_WBITS to zconf.h because users might want to change that.
|
||||||
|
- document explicitly that zalloc(64K) on MSDOS must return a normalized
|
||||||
|
pointer (zero offset)
|
||||||
|
- added Makefiles for Microsoft C, Turbo C, Borland C++
|
||||||
|
- faster crc32()
|
||||||
|
|
||||||
|
Changes in 0.8 (29 April 95)
|
||||||
|
- added fast inflate (inffast.c)
|
||||||
|
- deflate(Z_FINISH) now returns Z_STREAM_END when done. Warning: this
|
||||||
|
is incompatible with previous versions of zlib which returned Z_OK.
|
||||||
|
- work around a TurboC compiler bug (bad code for b << 0, see infutil.h)
|
||||||
|
(actually that was not a compiler bug, see 0.81 above)
|
||||||
|
- gzread no longer reads one extra byte in certain cases
|
||||||
|
- In gzio destroy(), don't reference a freed structure
|
||||||
|
- avoid many warnings for MSDOS
|
||||||
|
- avoid the ERROR symbol which is used by MS Windows
|
||||||
|
|
||||||
|
Changes in 0.71 (14 April 95)
|
||||||
|
- Fixed more MSDOS compilation problems :( There is still a bug with
|
||||||
|
TurboC large model.
|
||||||
|
|
||||||
|
Changes in 0.7 (14 April 95)
|
||||||
|
- Added full inflate support.
|
||||||
|
- Simplified the crc32() interface. The pre- and post-conditioning
|
||||||
|
(one's complement) is now done inside crc32(). WARNING: this is
|
||||||
|
incompatible with previous versions; see zlib.h for the new usage.
|
||||||
|
|
||||||
|
Changes in 0.61 (12 April 95)
|
||||||
|
- workaround for a bug in TurboC. example and minigzip now work on MSDOS.
|
||||||
|
|
||||||
|
Changes in 0.6 (11 April 95)
|
||||||
|
- added minigzip.c
|
||||||
|
- added gzdopen to reopen a file descriptor as gzFile
|
||||||
|
- added transparent reading of non-gziped files in gzread.
|
||||||
|
- fixed bug in gzread (don't read crc as data)
|
||||||
|
- fixed bug in destroy (gzio.c) (don't return Z_STREAM_END for gzclose).
|
||||||
|
- don't allocate big arrays in the stack (for MSDOS)
|
||||||
|
- fix some MSDOS compilation problems
|
||||||
|
|
||||||
|
Changes in 0.5:
|
||||||
|
- do real compression in deflate.c. Z_PARTIAL_FLUSH is supported but
|
||||||
|
not yet Z_FULL_FLUSH.
|
||||||
|
- support decompression but only in a single step (forced Z_FINISH)
|
||||||
|
- added opaque object for zalloc and zfree.
|
||||||
|
- added deflateReset and inflateReset
|
||||||
|
- added a variable zlib_version for consistency checking.
|
||||||
|
- renamed the 'filter' parameter of deflateInit2 as 'strategy'.
|
||||||
|
Added Z_FILTERED and Z_HUFFMAN_ONLY constants.
|
||||||
|
|
||||||
|
Changes in 0.4:
|
||||||
|
- avoid "zip" everywhere, use zlib instead of ziplib.
|
||||||
|
- suppress Z_BLOCK_FLUSH, interpret Z_PARTIAL_FLUSH as block flush
|
||||||
|
if compression method == 8.
|
||||||
|
- added adler32 and crc32
|
||||||
|
- renamed deflateOptions as deflateInit2, call one or the other but not both
|
||||||
|
- added the method parameter for deflateInit2.
|
||||||
|
- added inflateInit2
|
||||||
|
- simplied considerably deflateInit and inflateInit by not supporting
|
||||||
|
user-provided history buffer. This is supported only in deflateInit2
|
||||||
|
and inflateInit2.
|
||||||
|
|
||||||
|
Changes in 0.3:
|
||||||
|
- prefix all macro names with Z_
|
||||||
|
- use Z_FINISH instead of deflateEnd to finish compression.
|
||||||
|
- added Z_HUFFMAN_ONLY
|
||||||
|
- added gzerror()
|
|
@ -0,0 +1,6 @@
|
||||||
|
noinst_LIBRARIES = libpcsx2zlib.a
|
||||||
|
|
||||||
|
libpcsx2zlib_a_SOURCES = \
|
||||||
|
adler32.c crc32.c deflate.h inffast.c inflate.c inftrees.h trees.h zlib.h \
|
||||||
|
crc32.h gzio.c inffast.h inflate.h uncompr.c zutil.c \
|
||||||
|
compress.c deflate.c infback.c inffixed.h inftrees.c trees.c zconf.h zutil.h
|
|
@ -0,0 +1,125 @@
|
||||||
|
ZLIB DATA COMPRESSION LIBRARY
|
||||||
|
|
||||||
|
zlib 1.2.3 is a general purpose data compression library. All the code is
|
||||||
|
thread safe. The data format used by the zlib library is described by RFCs
|
||||||
|
(Request for Comments) 1950 to 1952 in the files
|
||||||
|
http://www.ietf.org/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate format)
|
||||||
|
and rfc1952.txt (gzip format). These documents are also available in other
|
||||||
|
formats from ftp://ftp.uu.net/graphics/png/documents/zlib/zdoc-index.html
|
||||||
|
|
||||||
|
All functions of the compression library are documented in the file zlib.h
|
||||||
|
(volunteer to write man pages welcome, contact zlib@gzip.org). A usage example
|
||||||
|
of the library is given in the file example.c which also tests that the library
|
||||||
|
is working correctly. Another example is given in the file minigzip.c. The
|
||||||
|
compression library itself is composed of all source files except example.c and
|
||||||
|
minigzip.c.
|
||||||
|
|
||||||
|
To compile all files and run the test program, follow the instructions given at
|
||||||
|
the top of Makefile. In short "make test; make install" should work for most
|
||||||
|
machines. For Unix: "./configure; make test; make install". For MSDOS, use one
|
||||||
|
of the special makefiles such as Makefile.msc. For VMS, use make_vms.com.
|
||||||
|
|
||||||
|
Questions about zlib should be sent to <zlib@gzip.org>, or to Gilles Vollant
|
||||||
|
<info@winimage.com> for the Windows DLL version. The zlib home page is
|
||||||
|
http://www.zlib.org or http://www.gzip.org/zlib/ Before reporting a problem,
|
||||||
|
please check this site to verify that you have the latest version of zlib;
|
||||||
|
otherwise get the latest version and check whether the problem still exists or
|
||||||
|
not.
|
||||||
|
|
||||||
|
PLEASE read the zlib FAQ http://www.gzip.org/zlib/zlib_faq.html before asking
|
||||||
|
for help.
|
||||||
|
|
||||||
|
Mark Nelson <markn@ieee.org> wrote an article about zlib for the Jan. 1997
|
||||||
|
issue of Dr. Dobb's Journal; a copy of the article is available in
|
||||||
|
http://dogma.net/markn/articles/zlibtool/zlibtool.htm
|
||||||
|
|
||||||
|
The changes made in version 1.2.3 are documented in the file ChangeLog.
|
||||||
|
|
||||||
|
Unsupported third party contributions are provided in directory "contrib".
|
||||||
|
|
||||||
|
A Java implementation of zlib is available in the Java Development Kit
|
||||||
|
http://java.sun.com/j2se/1.4.2/docs/api/java/util/zip/package-summary.html
|
||||||
|
See the zlib home page http://www.zlib.org for details.
|
||||||
|
|
||||||
|
A Perl interface to zlib written by Paul Marquess <pmqs@cpan.org> is in the
|
||||||
|
CPAN (Comprehensive Perl Archive Network) sites
|
||||||
|
http://www.cpan.org/modules/by-module/Compress/
|
||||||
|
|
||||||
|
A Python interface to zlib written by A.M. Kuchling <amk@amk.ca> is
|
||||||
|
available in Python 1.5 and later versions, see
|
||||||
|
http://www.python.org/doc/lib/module-zlib.html
|
||||||
|
|
||||||
|
A zlib binding for TCL written by Andreas Kupries <a.kupries@westend.com> is
|
||||||
|
availlable at http://www.oche.de/~akupries/soft/trf/trf_zip.html
|
||||||
|
|
||||||
|
An experimental package to read and write files in .zip format, written on top
|
||||||
|
of zlib by Gilles Vollant <info@winimage.com>, is available in the
|
||||||
|
contrib/minizip directory of zlib.
|
||||||
|
|
||||||
|
|
||||||
|
Notes for some targets:
|
||||||
|
|
||||||
|
- For Windows DLL versions, please see win32/DLL_FAQ.txt
|
||||||
|
|
||||||
|
- For 64-bit Irix, deflate.c must be compiled without any optimization. With
|
||||||
|
-O, one libpng test fails. The test works in 32 bit mode (with the -n32
|
||||||
|
compiler flag). The compiler bug has been reported to SGI.
|
||||||
|
|
||||||
|
- zlib doesn't work with gcc 2.6.3 on a DEC 3000/300LX under OSF/1 2.1 it works
|
||||||
|
when compiled with cc.
|
||||||
|
|
||||||
|
- On Digital Unix 4.0D (formely OSF/1) on AlphaServer, the cc option -std1 is
|
||||||
|
necessary to get gzprintf working correctly. This is done by configure.
|
||||||
|
|
||||||
|
- zlib doesn't work on HP-UX 9.05 with some versions of /bin/cc. It works with
|
||||||
|
other compilers. Use "make test" to check your compiler.
|
||||||
|
|
||||||
|
- gzdopen is not supported on RISCOS, BEOS and by some Mac compilers.
|
||||||
|
|
||||||
|
- For PalmOs, see http://palmzlib.sourceforge.net/
|
||||||
|
|
||||||
|
- When building a shared, i.e. dynamic library on Mac OS X, the library must be
|
||||||
|
installed before testing (do "make install" before "make test"), since the
|
||||||
|
library location is specified in the library.
|
||||||
|
|
||||||
|
|
||||||
|
Acknowledgments:
|
||||||
|
|
||||||
|
The deflate format used by zlib was defined by Phil Katz. The deflate
|
||||||
|
and zlib specifications were written by L. Peter Deutsch. Thanks to all the
|
||||||
|
people who reported problems and suggested various improvements in zlib;
|
||||||
|
they are too numerous to cite here.
|
||||||
|
|
||||||
|
Copyright notice:
|
||||||
|
|
||||||
|
(C) 1995-2004 Jean-loup Gailly and Mark Adler
|
||||||
|
|
||||||
|
This software is provided 'as-is', without any express or implied
|
||||||
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
arising from the use of this software.
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute it
|
||||||
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. The origin of this software must not be misrepresented; you must not
|
||||||
|
claim that you wrote the original software. If you use this software
|
||||||
|
in a product, an acknowledgment in the product documentation would be
|
||||||
|
appreciated but is not required.
|
||||||
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
misrepresented as being the original software.
|
||||||
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
|
|
||||||
|
Jean-loup Gailly Mark Adler
|
||||||
|
jloup@gzip.org madler@alumni.caltech.edu
|
||||||
|
|
||||||
|
If you use the zlib library in a product, we would appreciate *not*
|
||||||
|
receiving lengthy legal documents to sign. The sources are provided
|
||||||
|
for free but without warranty of any kind. The library has been
|
||||||
|
entirely written by Jean-loup Gailly and Mark Adler; it does not
|
||||||
|
include third-party code.
|
||||||
|
|
||||||
|
If you redistribute modified sources, we would appreciate that you include
|
||||||
|
in the file ChangeLog history information documenting your changes. Please
|
||||||
|
read the FAQ for more information on the distribution of modified source
|
||||||
|
versions.
|
|
@ -0,0 +1,149 @@
|
||||||
|
/* adler32.c -- compute the Adler-32 checksum of a data stream
|
||||||
|
* Copyright (C) 1995-2004 Mark Adler
|
||||||
|
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* @(#) $Id$ */
|
||||||
|
|
||||||
|
#define ZLIB_INTERNAL
|
||||||
|
#include "zlib.h"
|
||||||
|
|
||||||
|
#define BASE 65521UL /* largest prime smaller than 65536 */
|
||||||
|
#define NMAX 5552
|
||||||
|
/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
|
||||||
|
|
||||||
|
#define DO1(buf,i) {adler += (buf)[i]; sum2 += adler;}
|
||||||
|
#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1);
|
||||||
|
#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2);
|
||||||
|
#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4);
|
||||||
|
#define DO16(buf) DO8(buf,0); DO8(buf,8);
|
||||||
|
|
||||||
|
/* use NO_DIVIDE if your processor does not do division in hardware */
|
||||||
|
#ifdef NO_DIVIDE
|
||||||
|
# define MOD(a) \
|
||||||
|
do { \
|
||||||
|
if (a >= (BASE << 16)) a -= (BASE << 16); \
|
||||||
|
if (a >= (BASE << 15)) a -= (BASE << 15); \
|
||||||
|
if (a >= (BASE << 14)) a -= (BASE << 14); \
|
||||||
|
if (a >= (BASE << 13)) a -= (BASE << 13); \
|
||||||
|
if (a >= (BASE << 12)) a -= (BASE << 12); \
|
||||||
|
if (a >= (BASE << 11)) a -= (BASE << 11); \
|
||||||
|
if (a >= (BASE << 10)) a -= (BASE << 10); \
|
||||||
|
if (a >= (BASE << 9)) a -= (BASE << 9); \
|
||||||
|
if (a >= (BASE << 8)) a -= (BASE << 8); \
|
||||||
|
if (a >= (BASE << 7)) a -= (BASE << 7); \
|
||||||
|
if (a >= (BASE << 6)) a -= (BASE << 6); \
|
||||||
|
if (a >= (BASE << 5)) a -= (BASE << 5); \
|
||||||
|
if (a >= (BASE << 4)) a -= (BASE << 4); \
|
||||||
|
if (a >= (BASE << 3)) a -= (BASE << 3); \
|
||||||
|
if (a >= (BASE << 2)) a -= (BASE << 2); \
|
||||||
|
if (a >= (BASE << 1)) a -= (BASE << 1); \
|
||||||
|
if (a >= BASE) a -= BASE; \
|
||||||
|
} while (0)
|
||||||
|
# define MOD4(a) \
|
||||||
|
do { \
|
||||||
|
if (a >= (BASE << 4)) a -= (BASE << 4); \
|
||||||
|
if (a >= (BASE << 3)) a -= (BASE << 3); \
|
||||||
|
if (a >= (BASE << 2)) a -= (BASE << 2); \
|
||||||
|
if (a >= (BASE << 1)) a -= (BASE << 1); \
|
||||||
|
if (a >= BASE) a -= BASE; \
|
||||||
|
} while (0)
|
||||||
|
#else
|
||||||
|
# define MOD(a) a %= BASE
|
||||||
|
# define MOD4(a) a %= BASE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ========================================================================= */
|
||||||
|
uLong ZEXPORT adler32(adler, buf, len)
|
||||||
|
uLong adler;
|
||||||
|
const Bytef *buf;
|
||||||
|
uInt len;
|
||||||
|
{
|
||||||
|
unsigned long sum2;
|
||||||
|
unsigned n;
|
||||||
|
|
||||||
|
/* split Adler-32 into component sums */
|
||||||
|
sum2 = (adler >> 16) & 0xffff;
|
||||||
|
adler &= 0xffff;
|
||||||
|
|
||||||
|
/* in case user likes doing a byte at a time, keep it fast */
|
||||||
|
if (len == 1) {
|
||||||
|
adler += buf[0];
|
||||||
|
if (adler >= BASE)
|
||||||
|
adler -= BASE;
|
||||||
|
sum2 += adler;
|
||||||
|
if (sum2 >= BASE)
|
||||||
|
sum2 -= BASE;
|
||||||
|
return adler | (sum2 << 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* initial Adler-32 value (deferred check for len == 1 speed) */
|
||||||
|
if (buf == Z_NULL)
|
||||||
|
return 1L;
|
||||||
|
|
||||||
|
/* in case short lengths are provided, keep it somewhat fast */
|
||||||
|
if (len < 16) {
|
||||||
|
while (len--) {
|
||||||
|
adler += *buf++;
|
||||||
|
sum2 += adler;
|
||||||
|
}
|
||||||
|
if (adler >= BASE)
|
||||||
|
adler -= BASE;
|
||||||
|
MOD4(sum2); /* only added so many BASE's */
|
||||||
|
return adler | (sum2 << 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* do length NMAX blocks -- requires just one modulo operation */
|
||||||
|
while (len >= NMAX) {
|
||||||
|
len -= NMAX;
|
||||||
|
n = NMAX / 16; /* NMAX is divisible by 16 */
|
||||||
|
do {
|
||||||
|
DO16(buf); /* 16 sums unrolled */
|
||||||
|
buf += 16;
|
||||||
|
} while (--n);
|
||||||
|
MOD(adler);
|
||||||
|
MOD(sum2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* do remaining bytes (less than NMAX, still just one modulo) */
|
||||||
|
if (len) { /* avoid modulos if none remaining */
|
||||||
|
while (len >= 16) {
|
||||||
|
len -= 16;
|
||||||
|
DO16(buf);
|
||||||
|
buf += 16;
|
||||||
|
}
|
||||||
|
while (len--) {
|
||||||
|
adler += *buf++;
|
||||||
|
sum2 += adler;
|
||||||
|
}
|
||||||
|
MOD(adler);
|
||||||
|
MOD(sum2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* return recombined sums */
|
||||||
|
return adler | (sum2 << 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ========================================================================= */
|
||||||
|
uLong ZEXPORT adler32_combine(adler1, adler2, len2)
|
||||||
|
uLong adler1;
|
||||||
|
uLong adler2;
|
||||||
|
z_off_t len2;
|
||||||
|
{
|
||||||
|
unsigned long sum1;
|
||||||
|
unsigned long sum2;
|
||||||
|
unsigned rem;
|
||||||
|
|
||||||
|
/* the derivation of this formula is left as an exercise for the reader */
|
||||||
|
rem = (unsigned)(len2 % BASE);
|
||||||
|
sum1 = adler1 & 0xffff;
|
||||||
|
sum2 = rem * sum1;
|
||||||
|
MOD(sum2);
|
||||||
|
sum1 += (adler2 & 0xffff) + BASE - 1;
|
||||||
|
sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem;
|
||||||
|
if (sum1 > BASE) sum1 -= BASE;
|
||||||
|
if (sum1 > BASE) sum1 -= BASE;
|
||||||
|
if (sum2 > (BASE << 1)) sum2 -= (BASE << 1);
|
||||||
|
if (sum2 > BASE) sum2 -= BASE;
|
||||||
|
return sum1 | (sum2 << 16);
|
||||||
|
}
|
|
@ -0,0 +1,79 @@
|
||||||
|
/* compress.c -- compress a memory buffer
|
||||||
|
* Copyright (C) 1995-2003 Jean-loup Gailly.
|
||||||
|
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* @(#) $Id$ */
|
||||||
|
|
||||||
|
#define ZLIB_INTERNAL
|
||||||
|
#include "zlib.h"
|
||||||
|
|
||||||
|
/* ===========================================================================
|
||||||
|
Compresses the source buffer into the destination buffer. The level
|
||||||
|
parameter has the same meaning as in deflateInit. sourceLen is the byte
|
||||||
|
length of the source buffer. Upon entry, destLen is the total size of the
|
||||||
|
destination buffer, which must be at least 0.1% larger than sourceLen plus
|
||||||
|
12 bytes. Upon exit, destLen is the actual size of the compressed buffer.
|
||||||
|
|
||||||
|
compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
|
||||||
|
memory, Z_BUF_ERROR if there was not enough room in the output buffer,
|
||||||
|
Z_STREAM_ERROR if the level parameter is invalid.
|
||||||
|
*/
|
||||||
|
int ZEXPORT compress2 (dest, destLen, source, sourceLen, level)
|
||||||
|
Bytef *dest;
|
||||||
|
uLongf *destLen;
|
||||||
|
const Bytef *source;
|
||||||
|
uLong sourceLen;
|
||||||
|
int level;
|
||||||
|
{
|
||||||
|
z_stream stream;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
stream.next_in = (Bytef*)source;
|
||||||
|
stream.avail_in = (uInt)sourceLen;
|
||||||
|
#ifdef MAXSEG_64K
|
||||||
|
/* Check for source > 64K on 16-bit machine: */
|
||||||
|
if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR;
|
||||||
|
#endif
|
||||||
|
stream.next_out = dest;
|
||||||
|
stream.avail_out = (uInt)*destLen;
|
||||||
|
if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;
|
||||||
|
|
||||||
|
stream.zalloc = (alloc_func)0;
|
||||||
|
stream.zfree = (free_func)0;
|
||||||
|
stream.opaque = (voidpf)0;
|
||||||
|
|
||||||
|
err = deflateInit(&stream, level);
|
||||||
|
if (err != Z_OK) return err;
|
||||||
|
|
||||||
|
err = deflate(&stream, Z_FINISH);
|
||||||
|
if (err != Z_STREAM_END) {
|
||||||
|
deflateEnd(&stream);
|
||||||
|
return err == Z_OK ? Z_BUF_ERROR : err;
|
||||||
|
}
|
||||||
|
*destLen = stream.total_out;
|
||||||
|
|
||||||
|
err = deflateEnd(&stream);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===========================================================================
|
||||||
|
*/
|
||||||
|
int ZEXPORT compress (dest, destLen, source, sourceLen)
|
||||||
|
Bytef *dest;
|
||||||
|
uLongf *destLen;
|
||||||
|
const Bytef *source;
|
||||||
|
uLong sourceLen;
|
||||||
|
{
|
||||||
|
return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===========================================================================
|
||||||
|
If the default memLevel or windowBits for deflateInit() is changed, then
|
||||||
|
this function needs to be updated.
|
||||||
|
*/
|
||||||
|
uLong ZEXPORT compressBound (sourceLen)
|
||||||
|
uLong sourceLen;
|
||||||
|
{
|
||||||
|
return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + 11;
|
||||||
|
}
|
|
@ -0,0 +1,423 @@
|
||||||
|
/* crc32.c -- compute the CRC-32 of a data stream
|
||||||
|
* Copyright (C) 1995-2005 Mark Adler
|
||||||
|
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||||
|
*
|
||||||
|
* Thanks to Rodney Brown <rbrown64@csc.com.au> for his contribution of faster
|
||||||
|
* CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing
|
||||||
|
* tables for updating the shift register in one step with three exclusive-ors
|
||||||
|
* instead of four steps with four exclusive-ors. This results in about a
|
||||||
|
* factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* @(#) $Id$ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore
|
||||||
|
protection on the static variables used to control the first-use generation
|
||||||
|
of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should
|
||||||
|
first call get_crc_table() to initialize the tables before allowing more than
|
||||||
|
one thread to use crc32().
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef MAKECRCH
|
||||||
|
# include <stdio.h>
|
||||||
|
# ifndef DYNAMIC_CRC_TABLE
|
||||||
|
# define DYNAMIC_CRC_TABLE
|
||||||
|
# endif /* !DYNAMIC_CRC_TABLE */
|
||||||
|
#endif /* MAKECRCH */
|
||||||
|
|
||||||
|
#include "zutil.h" /* for STDC and FAR definitions */
|
||||||
|
|
||||||
|
#define local static
|
||||||
|
|
||||||
|
/* Find a four-byte integer type for crc32_little() and crc32_big(). */
|
||||||
|
#ifndef NOBYFOUR
|
||||||
|
# ifdef STDC /* need ANSI C limits.h to determine sizes */
|
||||||
|
# include <limits.h>
|
||||||
|
# define BYFOUR
|
||||||
|
# if (UINT_MAX == 0xffffffffUL)
|
||||||
|
typedef unsigned int u4;
|
||||||
|
# else
|
||||||
|
# if (ULONG_MAX == 0xffffffffUL)
|
||||||
|
typedef unsigned long u4;
|
||||||
|
# else
|
||||||
|
# if (USHRT_MAX == 0xffffffffUL)
|
||||||
|
typedef unsigned short u4;
|
||||||
|
# else
|
||||||
|
# undef BYFOUR /* can't find a four-byte integer type! */
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
# endif /* STDC */
|
||||||
|
#endif /* !NOBYFOUR */
|
||||||
|
|
||||||
|
/* Definitions for doing the crc four data bytes at a time. */
|
||||||
|
#ifdef BYFOUR
|
||||||
|
# define REV(w) (((w)>>24)+(((w)>>8)&0xff00)+ \
|
||||||
|
(((w)&0xff00)<<8)+(((w)&0xff)<<24))
|
||||||
|
local unsigned long crc32_little OF((unsigned long,
|
||||||
|
const unsigned char FAR *, unsigned));
|
||||||
|
local unsigned long crc32_big OF((unsigned long,
|
||||||
|
const unsigned char FAR *, unsigned));
|
||||||
|
# define TBLS 8
|
||||||
|
#else
|
||||||
|
# define TBLS 1
|
||||||
|
#endif /* BYFOUR */
|
||||||
|
|
||||||
|
/* Local functions for crc concatenation */
|
||||||
|
local unsigned long gf2_matrix_times OF((unsigned long *mat,
|
||||||
|
unsigned long vec));
|
||||||
|
local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat));
|
||||||
|
|
||||||
|
#ifdef DYNAMIC_CRC_TABLE
|
||||||
|
|
||||||
|
local volatile int crc_table_empty = 1;
|
||||||
|
local unsigned long FAR crc_table[TBLS][256];
|
||||||
|
local void make_crc_table OF((void));
|
||||||
|
#ifdef MAKECRCH
|
||||||
|
local void write_table OF((FILE *, const unsigned long FAR *));
|
||||||
|
#endif /* MAKECRCH */
|
||||||
|
/*
|
||||||
|
Generate tables for a byte-wise 32-bit CRC calculation on the polynomial:
|
||||||
|
x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1.
|
||||||
|
|
||||||
|
Polynomials over GF(2) are represented in binary, one bit per coefficient,
|
||||||
|
with the lowest powers in the most significant bit. Then adding polynomials
|
||||||
|
is just exclusive-or, and multiplying a polynomial by x is a right shift by
|
||||||
|
one. If we call the above polynomial p, and represent a byte as the
|
||||||
|
polynomial q, also with the lowest power in the most significant bit (so the
|
||||||
|
byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p,
|
||||||
|
where a mod b means the remainder after dividing a by b.
|
||||||
|
|
||||||
|
This calculation is done using the shift-register method of multiplying and
|
||||||
|
taking the remainder. The register is initialized to zero, and for each
|
||||||
|
incoming bit, x^32 is added mod p to the register if the bit is a one (where
|
||||||
|
x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by
|
||||||
|
x (which is shifting right by one and adding x^32 mod p if the bit shifted
|
||||||
|
out is a one). We start with the highest power (least significant bit) of
|
||||||
|
q and repeat for all eight bits of q.
|
||||||
|
|
||||||
|
The first table is simply the CRC of all possible eight bit values. This is
|
||||||
|
all the information needed to generate CRCs on data a byte at a time for all
|
||||||
|
combinations of CRC register values and incoming bytes. The remaining tables
|
||||||
|
allow for word-at-a-time CRC calculation for both big-endian and little-
|
||||||
|
endian machines, where a word is four bytes.
|
||||||
|
*/
|
||||||
|
local void make_crc_table()
|
||||||
|
{
|
||||||
|
unsigned long c;
|
||||||
|
int n, k;
|
||||||
|
unsigned long poly; /* polynomial exclusive-or pattern */
|
||||||
|
/* terms of polynomial defining this crc (except x^32): */
|
||||||
|
static volatile int first = 1; /* flag to limit concurrent making */
|
||||||
|
static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};
|
||||||
|
|
||||||
|
/* See if another task is already doing this (not thread-safe, but better
|
||||||
|
than nothing -- significantly reduces duration of vulnerability in
|
||||||
|
case the advice about DYNAMIC_CRC_TABLE is ignored) */
|
||||||
|
if (first) {
|
||||||
|
first = 0;
|
||||||
|
|
||||||
|
/* make exclusive-or pattern from polynomial (0xedb88320UL) */
|
||||||
|
poly = 0UL;
|
||||||
|
for (n = 0; n < sizeof(p)/sizeof(unsigned char); n++)
|
||||||
|
poly |= 1UL << (31 - p[n]);
|
||||||
|
|
||||||
|
/* generate a crc for every 8-bit value */
|
||||||
|
for (n = 0; n < 256; n++) {
|
||||||
|
c = (unsigned long)n;
|
||||||
|
for (k = 0; k < 8; k++)
|
||||||
|
c = c & 1 ? poly ^ (c >> 1) : c >> 1;
|
||||||
|
crc_table[0][n] = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef BYFOUR
|
||||||
|
/* generate crc for each value followed by one, two, and three zeros,
|
||||||
|
and then the byte reversal of those as well as the first table */
|
||||||
|
for (n = 0; n < 256; n++) {
|
||||||
|
c = crc_table[0][n];
|
||||||
|
crc_table[4][n] = REV(c);
|
||||||
|
for (k = 1; k < 4; k++) {
|
||||||
|
c = crc_table[0][c & 0xff] ^ (c >> 8);
|
||||||
|
crc_table[k][n] = c;
|
||||||
|
crc_table[k + 4][n] = REV(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* BYFOUR */
|
||||||
|
|
||||||
|
crc_table_empty = 0;
|
||||||
|
}
|
||||||
|
else { /* not first */
|
||||||
|
/* wait for the other guy to finish (not efficient, but rare) */
|
||||||
|
while (crc_table_empty)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef MAKECRCH
|
||||||
|
/* write out CRC tables to crc32.h */
|
||||||
|
{
|
||||||
|
FILE *out;
|
||||||
|
|
||||||
|
out = fopen("crc32.h", "w");
|
||||||
|
if (out == NULL) return;
|
||||||
|
fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n");
|
||||||
|
fprintf(out, " * Generated automatically by crc32.c\n */\n\n");
|
||||||
|
fprintf(out, "local const unsigned long FAR ");
|
||||||
|
fprintf(out, "crc_table[TBLS][256] =\n{\n {\n");
|
||||||
|
write_table(out, crc_table[0]);
|
||||||
|
# ifdef BYFOUR
|
||||||
|
fprintf(out, "#ifdef BYFOUR\n");
|
||||||
|
for (k = 1; k < 8; k++) {
|
||||||
|
fprintf(out, " },\n {\n");
|
||||||
|
write_table(out, crc_table[k]);
|
||||||
|
}
|
||||||
|
fprintf(out, "#endif\n");
|
||||||
|
# endif /* BYFOUR */
|
||||||
|
fprintf(out, " }\n};\n");
|
||||||
|
fclose(out);
|
||||||
|
}
|
||||||
|
#endif /* MAKECRCH */
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef MAKECRCH
|
||||||
|
local void write_table(out, table)
|
||||||
|
FILE *out;
|
||||||
|
const unsigned long FAR *table;
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
|
||||||
|
for (n = 0; n < 256; n++)
|
||||||
|
fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ", table[n],
|
||||||
|
n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", "));
|
||||||
|
}
|
||||||
|
#endif /* MAKECRCH */
|
||||||
|
|
||||||
|
#else /* !DYNAMIC_CRC_TABLE */
|
||||||
|
/* ========================================================================
|
||||||
|
* Tables of CRC-32s of all single-byte values, made by make_crc_table().
|
||||||
|
*/
|
||||||
|
#include "crc32.h"
|
||||||
|
#endif /* DYNAMIC_CRC_TABLE */
|
||||||
|
|
||||||
|
/* =========================================================================
|
||||||
|
* This function can be used by asm versions of crc32()
|
||||||
|
*/
|
||||||
|
const unsigned long FAR * ZEXPORT get_crc_table()
|
||||||
|
{
|
||||||
|
#ifdef DYNAMIC_CRC_TABLE
|
||||||
|
if (crc_table_empty)
|
||||||
|
make_crc_table();
|
||||||
|
#endif /* DYNAMIC_CRC_TABLE */
|
||||||
|
return (const unsigned long FAR *)crc_table;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ========================================================================= */
|
||||||
|
#define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8)
|
||||||
|
#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1
|
||||||
|
|
||||||
|
/* ========================================================================= */
|
||||||
|
unsigned long ZEXPORT crc32(crc, buf, len)
|
||||||
|
unsigned long crc;
|
||||||
|
const unsigned char FAR *buf;
|
||||||
|
unsigned len;
|
||||||
|
{
|
||||||
|
if (buf == Z_NULL) return 0UL;
|
||||||
|
|
||||||
|
#ifdef DYNAMIC_CRC_TABLE
|
||||||
|
if (crc_table_empty)
|
||||||
|
make_crc_table();
|
||||||
|
#endif /* DYNAMIC_CRC_TABLE */
|
||||||
|
|
||||||
|
#ifdef BYFOUR
|
||||||
|
if (sizeof(void *) == sizeof(ptrdiff_t)) {
|
||||||
|
u4 endian;
|
||||||
|
|
||||||
|
endian = 1;
|
||||||
|
if (*((unsigned char *)(&endian)))
|
||||||
|
return crc32_little(crc, buf, len);
|
||||||
|
else
|
||||||
|
return crc32_big(crc, buf, len);
|
||||||
|
}
|
||||||
|
#endif /* BYFOUR */
|
||||||
|
crc = crc ^ 0xffffffffUL;
|
||||||
|
while (len >= 8) {
|
||||||
|
DO8;
|
||||||
|
len -= 8;
|
||||||
|
}
|
||||||
|
if (len) do {
|
||||||
|
DO1;
|
||||||
|
} while (--len);
|
||||||
|
return crc ^ 0xffffffffUL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef BYFOUR
|
||||||
|
|
||||||
|
/* ========================================================================= */
|
||||||
|
#define DOLIT4 c ^= *buf4++; \
|
||||||
|
c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \
|
||||||
|
crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24]
|
||||||
|
#define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4
|
||||||
|
|
||||||
|
/* ========================================================================= */
|
||||||
|
local unsigned long crc32_little(crc, buf, len)
|
||||||
|
unsigned long crc;
|
||||||
|
const unsigned char FAR *buf;
|
||||||
|
unsigned len;
|
||||||
|
{
|
||||||
|
register u4 c;
|
||||||
|
register const u4 FAR *buf4;
|
||||||
|
|
||||||
|
c = (u4)crc;
|
||||||
|
c = ~c;
|
||||||
|
while (len && ((ptrdiff_t)buf & 3)) {
|
||||||
|
c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
|
||||||
|
len--;
|
||||||
|
}
|
||||||
|
|
||||||
|
buf4 = (const u4 FAR *)(const void FAR *)buf;
|
||||||
|
while (len >= 32) {
|
||||||
|
DOLIT32;
|
||||||
|
len -= 32;
|
||||||
|
}
|
||||||
|
while (len >= 4) {
|
||||||
|
DOLIT4;
|
||||||
|
len -= 4;
|
||||||
|
}
|
||||||
|
buf = (const unsigned char FAR *)buf4;
|
||||||
|
|
||||||
|
if (len) do {
|
||||||
|
c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
|
||||||
|
} while (--len);
|
||||||
|
c = ~c;
|
||||||
|
return (unsigned long)c;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ========================================================================= */
|
||||||
|
#define DOBIG4 c ^= *++buf4; \
|
||||||
|
c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \
|
||||||
|
crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24]
|
||||||
|
#define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4
|
||||||
|
|
||||||
|
/* ========================================================================= */
|
||||||
|
local unsigned long crc32_big(crc, buf, len)
|
||||||
|
unsigned long crc;
|
||||||
|
const unsigned char FAR *buf;
|
||||||
|
unsigned len;
|
||||||
|
{
|
||||||
|
register u4 c;
|
||||||
|
register const u4 FAR *buf4;
|
||||||
|
|
||||||
|
c = REV((u4)crc);
|
||||||
|
c = ~c;
|
||||||
|
while (len && ((ptrdiff_t)buf & 3)) {
|
||||||
|
c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
|
||||||
|
len--;
|
||||||
|
}
|
||||||
|
|
||||||
|
buf4 = (const u4 FAR *)(const void FAR *)buf;
|
||||||
|
buf4--;
|
||||||
|
while (len >= 32) {
|
||||||
|
DOBIG32;
|
||||||
|
len -= 32;
|
||||||
|
}
|
||||||
|
while (len >= 4) {
|
||||||
|
DOBIG4;
|
||||||
|
len -= 4;
|
||||||
|
}
|
||||||
|
buf4++;
|
||||||
|
buf = (const unsigned char FAR *)buf4;
|
||||||
|
|
||||||
|
if (len) do {
|
||||||
|
c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
|
||||||
|
} while (--len);
|
||||||
|
c = ~c;
|
||||||
|
return (unsigned long)(REV(c));
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* BYFOUR */
|
||||||
|
|
||||||
|
#define GF2_DIM 32 /* dimension of GF(2) vectors (length of CRC) */
|
||||||
|
|
||||||
|
/* ========================================================================= */
|
||||||
|
local unsigned long gf2_matrix_times(mat, vec)
|
||||||
|
unsigned long *mat;
|
||||||
|
unsigned long vec;
|
||||||
|
{
|
||||||
|
unsigned long sum;
|
||||||
|
|
||||||
|
sum = 0;
|
||||||
|
while (vec) {
|
||||||
|
if (vec & 1)
|
||||||
|
sum ^= *mat;
|
||||||
|
vec >>= 1;
|
||||||
|
mat++;
|
||||||
|
}
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ========================================================================= */
|
||||||
|
local void gf2_matrix_square(square, mat)
|
||||||
|
unsigned long *square;
|
||||||
|
unsigned long *mat;
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
|
||||||
|
for (n = 0; n < GF2_DIM; n++)
|
||||||
|
square[n] = gf2_matrix_times(mat, mat[n]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ========================================================================= */
|
||||||
|
uLong ZEXPORT crc32_combine(crc1, crc2, len2)
|
||||||
|
uLong crc1;
|
||||||
|
uLong crc2;
|
||||||
|
z_off_t len2;
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
unsigned long row;
|
||||||
|
unsigned long even[GF2_DIM]; /* even-power-of-two zeros operator */
|
||||||
|
unsigned long odd[GF2_DIM]; /* odd-power-of-two zeros operator */
|
||||||
|
|
||||||
|
/* degenerate case */
|
||||||
|
if (len2 == 0)
|
||||||
|
return crc1;
|
||||||
|
|
||||||
|
/* put operator for one zero bit in odd */
|
||||||
|
odd[0] = 0xedb88320L; /* CRC-32 polynomial */
|
||||||
|
row = 1;
|
||||||
|
for (n = 1; n < GF2_DIM; n++) {
|
||||||
|
odd[n] = row;
|
||||||
|
row <<= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* put operator for two zero bits in even */
|
||||||
|
gf2_matrix_square(even, odd);
|
||||||
|
|
||||||
|
/* put operator for four zero bits in odd */
|
||||||
|
gf2_matrix_square(odd, even);
|
||||||
|
|
||||||
|
/* apply len2 zeros to crc1 (first square will put the operator for one
|
||||||
|
zero byte, eight zero bits, in even) */
|
||||||
|
do {
|
||||||
|
/* apply zeros operator for this bit of len2 */
|
||||||
|
gf2_matrix_square(even, odd);
|
||||||
|
if (len2 & 1)
|
||||||
|
crc1 = gf2_matrix_times(even, crc1);
|
||||||
|
len2 >>= 1;
|
||||||
|
|
||||||
|
/* if no more bits set, then done */
|
||||||
|
if (len2 == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* another iteration of the loop with odd and even swapped */
|
||||||
|
gf2_matrix_square(odd, even);
|
||||||
|
if (len2 & 1)
|
||||||
|
crc1 = gf2_matrix_times(odd, crc1);
|
||||||
|
len2 >>= 1;
|
||||||
|
|
||||||
|
/* if no more bits set, then done */
|
||||||
|
} while (len2 != 0);
|
||||||
|
|
||||||
|
/* return combined crc */
|
||||||
|
crc1 ^= crc2;
|
||||||
|
return crc1;
|
||||||
|
}
|
|
@ -0,0 +1,441 @@
|
||||||
|
/* crc32.h -- tables for rapid CRC calculation
|
||||||
|
* Generated automatically by crc32.c
|
||||||
|
*/
|
||||||
|
|
||||||
|
local const unsigned long FAR crc_table[TBLS][256] =
|
||||||
|
{
|
||||||
|
{
|
||||||
|
0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL,
|
||||||
|
0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL,
|
||||||
|
0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL,
|
||||||
|
0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL,
|
||||||
|
0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL,
|
||||||
|
0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL,
|
||||||
|
0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL,
|
||||||
|
0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL,
|
||||||
|
0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL,
|
||||||
|
0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL,
|
||||||
|
0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL,
|
||||||
|
0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL,
|
||||||
|
0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL,
|
||||||
|
0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL,
|
||||||
|
0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL,
|
||||||
|
0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL,
|
||||||
|
0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL,
|
||||||
|
0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL,
|
||||||
|
0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL,
|
||||||
|
0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL,
|
||||||
|
0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL,
|
||||||
|
0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL,
|
||||||
|
0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL,
|
||||||
|
0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL,
|
||||||
|
0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL,
|
||||||
|
0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL,
|
||||||
|
0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL,
|
||||||
|
0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL,
|
||||||
|
0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL,
|
||||||
|
0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL,
|
||||||
|
0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL,
|
||||||
|
0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL,
|
||||||
|
0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL,
|
||||||
|
0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL,
|
||||||
|
0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL,
|
||||||
|
0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL,
|
||||||
|
0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL,
|
||||||
|
0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL,
|
||||||
|
0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL,
|
||||||
|
0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL,
|
||||||
|
0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL,
|
||||||
|
0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL,
|
||||||
|
0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL,
|
||||||
|
0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL,
|
||||||
|
0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL,
|
||||||
|
0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL,
|
||||||
|
0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL,
|
||||||
|
0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL,
|
||||||
|
0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL,
|
||||||
|
0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL,
|
||||||
|
0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL,
|
||||||
|
0x2d02ef8dUL
|
||||||
|
#ifdef BYFOUR
|
||||||
|
},
|
||||||
|
{
|
||||||
|
0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL,
|
||||||
|
0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL,
|
||||||
|
0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL,
|
||||||
|
0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL,
|
||||||
|
0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL,
|
||||||
|
0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL,
|
||||||
|
0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL,
|
||||||
|
0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL,
|
||||||
|
0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL,
|
||||||
|
0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL,
|
||||||
|
0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL,
|
||||||
|
0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL,
|
||||||
|
0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL,
|
||||||
|
0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL,
|
||||||
|
0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL,
|
||||||
|
0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL,
|
||||||
|
0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL,
|
||||||
|
0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL,
|
||||||
|
0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL,
|
||||||
|
0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL,
|
||||||
|
0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL,
|
||||||
|
0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL,
|
||||||
|
0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL,
|
||||||
|
0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL,
|
||||||
|
0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL,
|
||||||
|
0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL,
|
||||||
|
0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL,
|
||||||
|
0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL,
|
||||||
|
0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL,
|
||||||
|
0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL,
|
||||||
|
0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL,
|
||||||
|
0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL,
|
||||||
|
0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL,
|
||||||
|
0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL,
|
||||||
|
0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL,
|
||||||
|
0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL,
|
||||||
|
0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL,
|
||||||
|
0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL,
|
||||||
|
0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL,
|
||||||
|
0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL,
|
||||||
|
0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL,
|
||||||
|
0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL,
|
||||||
|
0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL,
|
||||||
|
0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL,
|
||||||
|
0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL,
|
||||||
|
0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL,
|
||||||
|
0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL,
|
||||||
|
0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL,
|
||||||
|
0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL,
|
||||||
|
0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL,
|
||||||
|
0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL,
|
||||||
|
0x9324fd72UL
|
||||||
|
},
|
||||||
|
{
|
||||||
|
0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL,
|
||||||
|
0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL,
|
||||||
|
0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL,
|
||||||
|
0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL,
|
||||||
|
0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL,
|
||||||
|
0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL,
|
||||||
|
0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL,
|
||||||
|
0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL,
|
||||||
|
0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL,
|
||||||
|
0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL,
|
||||||
|
0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL,
|
||||||
|
0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL,
|
||||||
|
0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL,
|
||||||
|
0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL,
|
||||||
|
0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL,
|
||||||
|
0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL,
|
||||||
|
0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL,
|
||||||
|
0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL,
|
||||||
|
0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL,
|
||||||
|
0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL,
|
||||||
|
0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL,
|
||||||
|
0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL,
|
||||||
|
0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL,
|
||||||
|
0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL,
|
||||||
|
0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL,
|
||||||
|
0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL,
|
||||||
|
0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL,
|
||||||
|
0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL,
|
||||||
|
0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL,
|
||||||
|
0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL,
|
||||||
|
0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL,
|
||||||
|
0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL,
|
||||||
|
0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL,
|
||||||
|
0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL,
|
||||||
|
0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL,
|
||||||
|
0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL,
|
||||||
|
0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL,
|
||||||
|
0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL,
|
||||||
|
0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL,
|
||||||
|
0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL,
|
||||||
|
0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL,
|
||||||
|
0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL,
|
||||||
|
0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL,
|
||||||
|
0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL,
|
||||||
|
0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL,
|
||||||
|
0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL,
|
||||||
|
0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL,
|
||||||
|
0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL,
|
||||||
|
0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL,
|
||||||
|
0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL,
|
||||||
|
0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL,
|
||||||
|
0xbe9834edUL
|
||||||
|
},
|
||||||
|
{
|
||||||
|
0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL,
|
||||||
|
0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL,
|
||||||
|
0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL,
|
||||||
|
0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL,
|
||||||
|
0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL,
|
||||||
|
0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL,
|
||||||
|
0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL,
|
||||||
|
0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL,
|
||||||
|
0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL,
|
||||||
|
0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL,
|
||||||
|
0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL,
|
||||||
|
0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL,
|
||||||
|
0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL,
|
||||||
|
0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL,
|
||||||
|
0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL,
|
||||||
|
0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL,
|
||||||
|
0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL,
|
||||||
|
0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL,
|
||||||
|
0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL,
|
||||||
|
0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL,
|
||||||
|
0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL,
|
||||||
|
0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL,
|
||||||
|
0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL,
|
||||||
|
0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL,
|
||||||
|
0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL,
|
||||||
|
0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL,
|
||||||
|
0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL,
|
||||||
|
0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL,
|
||||||
|
0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL,
|
||||||
|
0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL,
|
||||||
|
0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL,
|
||||||
|
0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL,
|
||||||
|
0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL,
|
||||||
|
0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL,
|
||||||
|
0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL,
|
||||||
|
0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL,
|
||||||
|
0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL,
|
||||||
|
0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL,
|
||||||
|
0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL,
|
||||||
|
0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL,
|
||||||
|
0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL,
|
||||||
|
0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL,
|
||||||
|
0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL,
|
||||||
|
0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL,
|
||||||
|
0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL,
|
||||||
|
0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL,
|
||||||
|
0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL,
|
||||||
|
0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL,
|
||||||
|
0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL,
|
||||||
|
0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL,
|
||||||
|
0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL,
|
||||||
|
0xde0506f1UL
|
||||||
|
},
|
||||||
|
{
|
||||||
|
0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL,
|
||||||
|
0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL,
|
||||||
|
0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL,
|
||||||
|
0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL,
|
||||||
|
0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL,
|
||||||
|
0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL,
|
||||||
|
0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL,
|
||||||
|
0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL,
|
||||||
|
0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL,
|
||||||
|
0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL,
|
||||||
|
0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL,
|
||||||
|
0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL,
|
||||||
|
0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL,
|
||||||
|
0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL,
|
||||||
|
0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL,
|
||||||
|
0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL,
|
||||||
|
0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL,
|
||||||
|
0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL,
|
||||||
|
0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL,
|
||||||
|
0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL,
|
||||||
|
0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL,
|
||||||
|
0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL,
|
||||||
|
0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL,
|
||||||
|
0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL,
|
||||||
|
0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL,
|
||||||
|
0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL,
|
||||||
|
0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL,
|
||||||
|
0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL,
|
||||||
|
0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL,
|
||||||
|
0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL,
|
||||||
|
0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL,
|
||||||
|
0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL,
|
||||||
|
0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL,
|
||||||
|
0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL,
|
||||||
|
0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL,
|
||||||
|
0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL,
|
||||||
|
0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL,
|
||||||
|
0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL,
|
||||||
|
0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL,
|
||||||
|
0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL,
|
||||||
|
0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL,
|
||||||
|
0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL,
|
||||||
|
0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL,
|
||||||
|
0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL,
|
||||||
|
0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL,
|
||||||
|
0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL,
|
||||||
|
0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL,
|
||||||
|
0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL,
|
||||||
|
0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL,
|
||||||
|
0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL,
|
||||||
|
0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL,
|
||||||
|
0x8def022dUL
|
||||||
|
},
|
||||||
|
{
|
||||||
|
0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL,
|
||||||
|
0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL,
|
||||||
|
0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL,
|
||||||
|
0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL,
|
||||||
|
0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL,
|
||||||
|
0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL,
|
||||||
|
0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL,
|
||||||
|
0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL,
|
||||||
|
0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL,
|
||||||
|
0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL,
|
||||||
|
0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL,
|
||||||
|
0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL,
|
||||||
|
0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL,
|
||||||
|
0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL,
|
||||||
|
0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL,
|
||||||
|
0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL,
|
||||||
|
0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL,
|
||||||
|
0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL,
|
||||||
|
0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL,
|
||||||
|
0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL,
|
||||||
|
0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL,
|
||||||
|
0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL,
|
||||||
|
0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL,
|
||||||
|
0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL,
|
||||||
|
0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL,
|
||||||
|
0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL,
|
||||||
|
0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL,
|
||||||
|
0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL,
|
||||||
|
0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL,
|
||||||
|
0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL,
|
||||||
|
0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL,
|
||||||
|
0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL,
|
||||||
|
0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL,
|
||||||
|
0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL,
|
||||||
|
0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL,
|
||||||
|
0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL,
|
||||||
|
0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL,
|
||||||
|
0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL,
|
||||||
|
0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL,
|
||||||
|
0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL,
|
||||||
|
0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL,
|
||||||
|
0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL,
|
||||||
|
0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL,
|
||||||
|
0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL,
|
||||||
|
0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL,
|
||||||
|
0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL,
|
||||||
|
0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL,
|
||||||
|
0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL,
|
||||||
|
0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL,
|
||||||
|
0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL,
|
||||||
|
0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL,
|
||||||
|
0x72fd2493UL
|
||||||
|
},
|
||||||
|
{
|
||||||
|
0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL,
|
||||||
|
0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL,
|
||||||
|
0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL,
|
||||||
|
0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL,
|
||||||
|
0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL,
|
||||||
|
0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL,
|
||||||
|
0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL,
|
||||||
|
0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL,
|
||||||
|
0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL,
|
||||||
|
0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL,
|
||||||
|
0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL,
|
||||||
|
0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL,
|
||||||
|
0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL,
|
||||||
|
0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL,
|
||||||
|
0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL,
|
||||||
|
0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL,
|
||||||
|
0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL,
|
||||||
|
0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL,
|
||||||
|
0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL,
|
||||||
|
0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL,
|
||||||
|
0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL,
|
||||||
|
0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL,
|
||||||
|
0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL,
|
||||||
|
0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL,
|
||||||
|
0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL,
|
||||||
|
0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL,
|
||||||
|
0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL,
|
||||||
|
0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL,
|
||||||
|
0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL,
|
||||||
|
0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL,
|
||||||
|
0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL,
|
||||||
|
0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL,
|
||||||
|
0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL,
|
||||||
|
0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL,
|
||||||
|
0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL,
|
||||||
|
0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL,
|
||||||
|
0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL,
|
||||||
|
0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL,
|
||||||
|
0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL,
|
||||||
|
0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL,
|
||||||
|
0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL,
|
||||||
|
0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL,
|
||||||
|
0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL,
|
||||||
|
0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL,
|
||||||
|
0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL,
|
||||||
|
0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL,
|
||||||
|
0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL,
|
||||||
|
0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL,
|
||||||
|
0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL,
|
||||||
|
0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL,
|
||||||
|
0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL,
|
||||||
|
0xed3498beUL
|
||||||
|
},
|
||||||
|
{
|
||||||
|
0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL,
|
||||||
|
0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL,
|
||||||
|
0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL,
|
||||||
|
0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL,
|
||||||
|
0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL,
|
||||||
|
0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL,
|
||||||
|
0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL,
|
||||||
|
0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL,
|
||||||
|
0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL,
|
||||||
|
0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL,
|
||||||
|
0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL,
|
||||||
|
0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL,
|
||||||
|
0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL,
|
||||||
|
0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL,
|
||||||
|
0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL,
|
||||||
|
0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL,
|
||||||
|
0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL,
|
||||||
|
0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL,
|
||||||
|
0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL,
|
||||||
|
0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL,
|
||||||
|
0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL,
|
||||||
|
0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL,
|
||||||
|
0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL,
|
||||||
|
0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL,
|
||||||
|
0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL,
|
||||||
|
0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL,
|
||||||
|
0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL,
|
||||||
|
0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL,
|
||||||
|
0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL,
|
||||||
|
0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL,
|
||||||
|
0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL,
|
||||||
|
0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL,
|
||||||
|
0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL,
|
||||||
|
0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL,
|
||||||
|
0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL,
|
||||||
|
0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL,
|
||||||
|
0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL,
|
||||||
|
0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL,
|
||||||
|
0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL,
|
||||||
|
0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL,
|
||||||
|
0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL,
|
||||||
|
0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL,
|
||||||
|
0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL,
|
||||||
|
0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL,
|
||||||
|
0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL,
|
||||||
|
0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL,
|
||||||
|
0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL,
|
||||||
|
0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL,
|
||||||
|
0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL,
|
||||||
|
0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL,
|
||||||
|
0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL,
|
||||||
|
0xf10605deUL
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
};
|
|
@ -0,0 +1,331 @@
|
||||||
|
/* deflate.h -- internal compression state
|
||||||
|
* Copyright (C) 1995-2004 Jean-loup Gailly
|
||||||
|
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* WARNING: this file should *not* be used by applications. It is
|
||||||
|
part of the implementation of the compression library and is
|
||||||
|
subject to change. Applications should only use zlib.h.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* @(#) $Id$ */
|
||||||
|
|
||||||
|
#ifndef DEFLATE_H
|
||||||
|
#define DEFLATE_H
|
||||||
|
|
||||||
|
#include "zutil.h"
|
||||||
|
|
||||||
|
/* define NO_GZIP when compiling if you want to disable gzip header and
|
||||||
|
trailer creation by deflate(). NO_GZIP would be used to avoid linking in
|
||||||
|
the crc code when it is not needed. For shared libraries, gzip encoding
|
||||||
|
should be left enabled. */
|
||||||
|
#ifndef NO_GZIP
|
||||||
|
# define GZIP
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ===========================================================================
|
||||||
|
* Internal compression state.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define LENGTH_CODES 29
|
||||||
|
/* number of length codes, not counting the special END_BLOCK code */
|
||||||
|
|
||||||
|
#define LITERALS 256
|
||||||
|
/* number of literal bytes 0..255 */
|
||||||
|
|
||||||
|
#define L_CODES (LITERALS+1+LENGTH_CODES)
|
||||||
|
/* number of Literal or Length codes, including the END_BLOCK code */
|
||||||
|
|
||||||
|
#define D_CODES 30
|
||||||
|
/* number of distance codes */
|
||||||
|
|
||||||
|
#define BL_CODES 19
|
||||||
|
/* number of codes used to transfer the bit lengths */
|
||||||
|
|
||||||
|
#define HEAP_SIZE (2*L_CODES+1)
|
||||||
|
/* maximum heap size */
|
||||||
|
|
||||||
|
#define MAX_BITS 15
|
||||||
|
/* All codes must not exceed MAX_BITS bits */
|
||||||
|
|
||||||
|
#define INIT_STATE 42
|
||||||
|
#define EXTRA_STATE 69
|
||||||
|
#define NAME_STATE 73
|
||||||
|
#define COMMENT_STATE 91
|
||||||
|
#define HCRC_STATE 103
|
||||||
|
#define BUSY_STATE 113
|
||||||
|
#define FINISH_STATE 666
|
||||||
|
/* Stream status */
|
||||||
|
|
||||||
|
|
||||||
|
/* Data structure describing a single value and its code string. */
|
||||||
|
typedef struct ct_data_s {
|
||||||
|
union {
|
||||||
|
ush freq; /* frequency count */
|
||||||
|
ush code; /* bit string */
|
||||||
|
} fc;
|
||||||
|
union {
|
||||||
|
ush dad; /* father node in Huffman tree */
|
||||||
|
ush len; /* length of bit string */
|
||||||
|
} dl;
|
||||||
|
} FAR ct_data;
|
||||||
|
|
||||||
|
#define Freq fc.freq
|
||||||
|
#define Code fc.code
|
||||||
|
#define Dad dl.dad
|
||||||
|
#define Len dl.len
|
||||||
|
|
||||||
|
typedef struct static_tree_desc_s static_tree_desc;
|
||||||
|
|
||||||
|
typedef struct tree_desc_s {
|
||||||
|
ct_data *dyn_tree; /* the dynamic tree */
|
||||||
|
int max_code; /* largest code with non zero frequency */
|
||||||
|
static_tree_desc *stat_desc; /* the corresponding static tree */
|
||||||
|
} FAR tree_desc;
|
||||||
|
|
||||||
|
typedef ush Pos;
|
||||||
|
typedef Pos FAR Posf;
|
||||||
|
typedef unsigned IPos;
|
||||||
|
|
||||||
|
/* A Pos is an index in the character window. We use short instead of int to
|
||||||
|
* save space in the various tables. IPos is used only for parameter passing.
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct internal_state {
|
||||||
|
z_streamp strm; /* pointer back to this zlib stream */
|
||||||
|
int status; /* as the name implies */
|
||||||
|
Bytef *pending_buf; /* output still pending */
|
||||||
|
ulg pending_buf_size; /* size of pending_buf */
|
||||||
|
Bytef *pending_out; /* next pending byte to output to the stream */
|
||||||
|
uInt pending; /* nb of bytes in the pending buffer */
|
||||||
|
int wrap; /* bit 0 true for zlib, bit 1 true for gzip */
|
||||||
|
gz_headerp gzhead; /* gzip header information to write */
|
||||||
|
uInt gzindex; /* where in extra, name, or comment */
|
||||||
|
Byte method; /* STORED (for zip only) or DEFLATED */
|
||||||
|
int last_flush; /* value of flush param for previous deflate call */
|
||||||
|
|
||||||
|
/* used by deflate.c: */
|
||||||
|
|
||||||
|
uInt w_size; /* LZ77 window size (32K by default) */
|
||||||
|
uInt w_bits; /* log2(w_size) (8..16) */
|
||||||
|
uInt w_mask; /* w_size - 1 */
|
||||||
|
|
||||||
|
Bytef *window;
|
||||||
|
/* Sliding window. Input bytes are read into the second half of the window,
|
||||||
|
* and move to the first half later to keep a dictionary of at least wSize
|
||||||
|
* bytes. With this organization, matches are limited to a distance of
|
||||||
|
* wSize-MAX_MATCH bytes, but this ensures that IO is always
|
||||||
|
* performed with a length multiple of the block size. Also, it limits
|
||||||
|
* the window size to 64K, which is quite useful on MSDOS.
|
||||||
|
* To do: use the user input buffer as sliding window.
|
||||||
|
*/
|
||||||
|
|
||||||
|
ulg window_size;
|
||||||
|
/* Actual size of window: 2*wSize, except when the user input buffer
|
||||||
|
* is directly used as sliding window.
|
||||||
|
*/
|
||||||
|
|
||||||
|
Posf *prev;
|
||||||
|
/* Link to older string with same hash index. To limit the size of this
|
||||||
|
* array to 64K, this link is maintained only for the last 32K strings.
|
||||||
|
* An index in this array is thus a window index modulo 32K.
|
||||||
|
*/
|
||||||
|
|
||||||
|
Posf *head; /* Heads of the hash chains or NIL. */
|
||||||
|
|
||||||
|
uInt ins_h; /* hash index of string to be inserted */
|
||||||
|
uInt hash_size; /* number of elements in hash table */
|
||||||
|
uInt hash_bits; /* log2(hash_size) */
|
||||||
|
uInt hash_mask; /* hash_size-1 */
|
||||||
|
|
||||||
|
uInt hash_shift;
|
||||||
|
/* Number of bits by which ins_h must be shifted at each input
|
||||||
|
* step. It must be such that after MIN_MATCH steps, the oldest
|
||||||
|
* byte no longer takes part in the hash key, that is:
|
||||||
|
* hash_shift * MIN_MATCH >= hash_bits
|
||||||
|
*/
|
||||||
|
|
||||||
|
long block_start;
|
||||||
|
/* Window position at the beginning of the current output block. Gets
|
||||||
|
* negative when the window is moved backwards.
|
||||||
|
*/
|
||||||
|
|
||||||
|
uInt match_length; /* length of best match */
|
||||||
|
IPos prev_match; /* previous match */
|
||||||
|
int match_available; /* set if previous match exists */
|
||||||
|
uInt strstart; /* start of string to insert */
|
||||||
|
uInt match_start; /* start of matching string */
|
||||||
|
uInt lookahead; /* number of valid bytes ahead in window */
|
||||||
|
|
||||||
|
uInt prev_length;
|
||||||
|
/* Length of the best match at previous step. Matches not greater than this
|
||||||
|
* are discarded. This is used in the lazy match evaluation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
uInt max_chain_length;
|
||||||
|
/* To speed up deflation, hash chains are never searched beyond this
|
||||||
|
* length. A higher limit improves compression ratio but degrades the
|
||||||
|
* speed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
uInt max_lazy_match;
|
||||||
|
/* Attempt to find a better match only when the current match is strictly
|
||||||
|
* smaller than this value. This mechanism is used only for compression
|
||||||
|
* levels >= 4.
|
||||||
|
*/
|
||||||
|
# define max_insert_length max_lazy_match
|
||||||
|
/* Insert new strings in the hash table only if the match length is not
|
||||||
|
* greater than this length. This saves time but degrades compression.
|
||||||
|
* max_insert_length is used only for compression levels <= 3.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int level; /* compression level (1..9) */
|
||||||
|
int strategy; /* favor or force Huffman coding*/
|
||||||
|
|
||||||
|
uInt good_match;
|
||||||
|
/* Use a faster search when the previous match is longer than this */
|
||||||
|
|
||||||
|
int nice_match; /* Stop searching when current match exceeds this */
|
||||||
|
|
||||||
|
/* used by trees.c: */
|
||||||
|
/* Didn't use ct_data typedef below to supress compiler warning */
|
||||||
|
struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */
|
||||||
|
struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */
|
||||||
|
struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */
|
||||||
|
|
||||||
|
struct tree_desc_s l_desc; /* desc. for literal tree */
|
||||||
|
struct tree_desc_s d_desc; /* desc. for distance tree */
|
||||||
|
struct tree_desc_s bl_desc; /* desc. for bit length tree */
|
||||||
|
|
||||||
|
ush bl_count[MAX_BITS+1];
|
||||||
|
/* number of codes at each bit length for an optimal tree */
|
||||||
|
|
||||||
|
int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */
|
||||||
|
int heap_len; /* number of elements in the heap */
|
||||||
|
int heap_max; /* element of largest frequency */
|
||||||
|
/* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
|
||||||
|
* The same heap array is used to build all trees.
|
||||||
|
*/
|
||||||
|
|
||||||
|
uch depth[2*L_CODES+1];
|
||||||
|
/* Depth of each subtree used as tie breaker for trees of equal frequency
|
||||||
|
*/
|
||||||
|
|
||||||
|
uchf *l_buf; /* buffer for literals or lengths */
|
||||||
|
|
||||||
|
uInt lit_bufsize;
|
||||||
|
/* Size of match buffer for literals/lengths. There are 4 reasons for
|
||||||
|
* limiting lit_bufsize to 64K:
|
||||||
|
* - frequencies can be kept in 16 bit counters
|
||||||
|
* - if compression is not successful for the first block, all input
|
||||||
|
* data is still in the window so we can still emit a stored block even
|
||||||
|
* when input comes from standard input. (This can also be done for
|
||||||
|
* all blocks if lit_bufsize is not greater than 32K.)
|
||||||
|
* - if compression is not successful for a file smaller than 64K, we can
|
||||||
|
* even emit a stored file instead of a stored block (saving 5 bytes).
|
||||||
|
* This is applicable only for zip (not gzip or zlib).
|
||||||
|
* - creating new Huffman trees less frequently may not provide fast
|
||||||
|
* adaptation to changes in the input data statistics. (Take for
|
||||||
|
* example a binary file with poorly compressible code followed by
|
||||||
|
* a highly compressible string table.) Smaller buffer sizes give
|
||||||
|
* fast adaptation but have of course the overhead of transmitting
|
||||||
|
* trees more frequently.
|
||||||
|
* - I can't count above 4
|
||||||
|
*/
|
||||||
|
|
||||||
|
uInt last_lit; /* running index in l_buf */
|
||||||
|
|
||||||
|
ushf *d_buf;
|
||||||
|
/* Buffer for distances. To simplify the code, d_buf and l_buf have
|
||||||
|
* the same number of elements. To use different lengths, an extra flag
|
||||||
|
* array would be necessary.
|
||||||
|
*/
|
||||||
|
|
||||||
|
ulg opt_len; /* bit length of current block with optimal trees */
|
||||||
|
ulg static_len; /* bit length of current block with static trees */
|
||||||
|
uInt matches; /* number of string matches in current block */
|
||||||
|
int last_eob_len; /* bit length of EOB code for last block */
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
ulg compressed_len; /* total bit length of compressed file mod 2^32 */
|
||||||
|
ulg bits_sent; /* bit length of compressed data sent mod 2^32 */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ush bi_buf;
|
||||||
|
/* Output buffer. bits are inserted starting at the bottom (least
|
||||||
|
* significant bits).
|
||||||
|
*/
|
||||||
|
int bi_valid;
|
||||||
|
/* Number of valid bits in bi_buf. All bits above the last valid bit
|
||||||
|
* are always zero.
|
||||||
|
*/
|
||||||
|
|
||||||
|
} FAR deflate_state;
|
||||||
|
|
||||||
|
/* Output a byte on the stream.
|
||||||
|
* IN assertion: there is enough room in pending_buf.
|
||||||
|
*/
|
||||||
|
#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);}
|
||||||
|
|
||||||
|
|
||||||
|
#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
|
||||||
|
/* Minimum amount of lookahead, except at the end of the input file.
|
||||||
|
* See deflate.c for comments about the MIN_MATCH+1.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD)
|
||||||
|
/* In order to simplify the code, particularly on 16 bit machines, match
|
||||||
|
* distances are limited to MAX_DIST instead of WSIZE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* in trees.c */
|
||||||
|
void _tr_init OF((deflate_state *s));
|
||||||
|
int _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc));
|
||||||
|
void _tr_flush_block OF((deflate_state *s, charf *buf, ulg stored_len,
|
||||||
|
int eof));
|
||||||
|
void _tr_align OF((deflate_state *s));
|
||||||
|
void _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len,
|
||||||
|
int eof));
|
||||||
|
|
||||||
|
#define d_code(dist) \
|
||||||
|
((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)])
|
||||||
|
/* Mapping from a distance to a distance code. dist is the distance - 1 and
|
||||||
|
* must not have side effects. _dist_code[256] and _dist_code[257] are never
|
||||||
|
* used.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef DEBUG
|
||||||
|
/* Inline versions of _tr_tally for speed: */
|
||||||
|
|
||||||
|
#if defined(GEN_TREES_H) || !defined(STDC)
|
||||||
|
extern uch _length_code[];
|
||||||
|
extern uch _dist_code[];
|
||||||
|
#else
|
||||||
|
extern const uch _length_code[];
|
||||||
|
extern const uch _dist_code[];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
# define _tr_tally_lit(s, c, flush) \
|
||||||
|
{ uch cc = (c); \
|
||||||
|
s->d_buf[s->last_lit] = 0; \
|
||||||
|
s->l_buf[s->last_lit++] = cc; \
|
||||||
|
s->dyn_ltree[cc].Freq++; \
|
||||||
|
flush = (s->last_lit == s->lit_bufsize-1); \
|
||||||
|
}
|
||||||
|
# define _tr_tally_dist(s, distance, length, flush) \
|
||||||
|
{ uch len = (length); \
|
||||||
|
ush dist = (distance); \
|
||||||
|
s->d_buf[s->last_lit] = dist; \
|
||||||
|
s->l_buf[s->last_lit++] = len; \
|
||||||
|
dist--; \
|
||||||
|
s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \
|
||||||
|
s->dyn_dtree[d_code(dist)].Freq++; \
|
||||||
|
flush = (s->last_lit == s->lit_bufsize-1); \
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c)
|
||||||
|
# define _tr_tally_dist(s, distance, length, flush) \
|
||||||
|
flush = _tr_tally(s, distance, length)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* DEFLATE_H */
|
|
@ -0,0 +1,623 @@
|
||||||
|
/* infback.c -- inflate using a call-back interface
|
||||||
|
* Copyright (C) 1995-2005 Mark Adler
|
||||||
|
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
This code is largely copied from inflate.c. Normally either infback.o or
|
||||||
|
inflate.o would be linked into an application--not both. The interface
|
||||||
|
with inffast.c is retained so that optimized assembler-coded versions of
|
||||||
|
inflate_fast() can be used with either inflate.c or infback.c.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "zutil.h"
|
||||||
|
#include "inftrees.h"
|
||||||
|
#include "inflate.h"
|
||||||
|
#include "inffast.h"
|
||||||
|
|
||||||
|
/* function prototypes */
|
||||||
|
local void fixedtables OF((struct inflate_state FAR *state));
|
||||||
|
|
||||||
|
/*
|
||||||
|
strm provides memory allocation functions in zalloc and zfree, or
|
||||||
|
Z_NULL to use the library memory allocation functions.
|
||||||
|
|
||||||
|
windowBits is in the range 8..15, and window is a user-supplied
|
||||||
|
window and output buffer that is 2**windowBits bytes.
|
||||||
|
*/
|
||||||
|
int ZEXPORT inflateBackInit_(strm, windowBits, window, version, stream_size)
|
||||||
|
z_streamp strm;
|
||||||
|
int windowBits;
|
||||||
|
unsigned char FAR *window;
|
||||||
|
const char *version;
|
||||||
|
int stream_size;
|
||||||
|
{
|
||||||
|
struct inflate_state FAR *state;
|
||||||
|
|
||||||
|
if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
|
||||||
|
stream_size != (int)(sizeof(z_stream)))
|
||||||
|
return Z_VERSION_ERROR;
|
||||||
|
if (strm == Z_NULL || window == Z_NULL ||
|
||||||
|
windowBits < 8 || windowBits > 15)
|
||||||
|
return Z_STREAM_ERROR;
|
||||||
|
strm->msg = Z_NULL; /* in case we return an error */
|
||||||
|
if (strm->zalloc == (alloc_func)0) {
|
||||||
|
strm->zalloc = zcalloc;
|
||||||
|
strm->opaque = (voidpf)0;
|
||||||
|
}
|
||||||
|
if (strm->zfree == (free_func)0) strm->zfree = zcfree;
|
||||||
|
state = (struct inflate_state FAR *)ZALLOC(strm, 1,
|
||||||
|
sizeof(struct inflate_state));
|
||||||
|
if (state == Z_NULL) return Z_MEM_ERROR;
|
||||||
|
Tracev((stderr, "inflate: allocated\n"));
|
||||||
|
strm->state = (struct internal_state FAR *)state;
|
||||||
|
state->dmax = 32768U;
|
||||||
|
state->wbits = windowBits;
|
||||||
|
state->wsize = 1U << windowBits;
|
||||||
|
state->window = window;
|
||||||
|
state->write = 0;
|
||||||
|
state->whave = 0;
|
||||||
|
return Z_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Return state with length and distance decoding tables and index sizes set to
|
||||||
|
fixed code decoding. Normally this returns fixed tables from inffixed.h.
|
||||||
|
If BUILDFIXED is defined, then instead this routine builds the tables the
|
||||||
|
first time it's called, and returns those tables the first time and
|
||||||
|
thereafter. This reduces the size of the code by about 2K bytes, in
|
||||||
|
exchange for a little execution time. However, BUILDFIXED should not be
|
||||||
|
used for threaded applications, since the rewriting of the tables and virgin
|
||||||
|
may not be thread-safe.
|
||||||
|
*/
|
||||||
|
local void fixedtables(state)
|
||||||
|
struct inflate_state FAR *state;
|
||||||
|
{
|
||||||
|
#ifdef BUILDFIXED
|
||||||
|
static int virgin = 1;
|
||||||
|
static code *lenfix, *distfix;
|
||||||
|
static code fixed[544];
|
||||||
|
|
||||||
|
/* build fixed huffman tables if first call (may not be thread safe) */
|
||||||
|
if (virgin) {
|
||||||
|
unsigned sym, bits;
|
||||||
|
static code *next;
|
||||||
|
|
||||||
|
/* literal/length table */
|
||||||
|
sym = 0;
|
||||||
|
while (sym < 144) state->lens[sym++] = 8;
|
||||||
|
while (sym < 256) state->lens[sym++] = 9;
|
||||||
|
while (sym < 280) state->lens[sym++] = 7;
|
||||||
|
while (sym < 288) state->lens[sym++] = 8;
|
||||||
|
next = fixed;
|
||||||
|
lenfix = next;
|
||||||
|
bits = 9;
|
||||||
|
inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work);
|
||||||
|
|
||||||
|
/* distance table */
|
||||||
|
sym = 0;
|
||||||
|
while (sym < 32) state->lens[sym++] = 5;
|
||||||
|
distfix = next;
|
||||||
|
bits = 5;
|
||||||
|
inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work);
|
||||||
|
|
||||||
|
/* do this just once */
|
||||||
|
virgin = 0;
|
||||||
|
}
|
||||||
|
#else /* !BUILDFIXED */
|
||||||
|
# include "inffixed.h"
|
||||||
|
#endif /* BUILDFIXED */
|
||||||
|
state->lencode = lenfix;
|
||||||
|
state->lenbits = 9;
|
||||||
|
state->distcode = distfix;
|
||||||
|
state->distbits = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Macros for inflateBack(): */
|
||||||
|
|
||||||
|
/* Load returned state from inflate_fast() */
|
||||||
|
#define LOAD() \
|
||||||
|
do { \
|
||||||
|
put = strm->next_out; \
|
||||||
|
left = strm->avail_out; \
|
||||||
|
next = strm->next_in; \
|
||||||
|
have = strm->avail_in; \
|
||||||
|
hold = state->hold; \
|
||||||
|
bits = state->bits; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
/* Set state from registers for inflate_fast() */
|
||||||
|
#define RESTORE() \
|
||||||
|
do { \
|
||||||
|
strm->next_out = put; \
|
||||||
|
strm->avail_out = left; \
|
||||||
|
strm->next_in = next; \
|
||||||
|
strm->avail_in = have; \
|
||||||
|
state->hold = hold; \
|
||||||
|
state->bits = bits; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
/* Clear the input bit accumulator */
|
||||||
|
#define INITBITS() \
|
||||||
|
do { \
|
||||||
|
hold = 0; \
|
||||||
|
bits = 0; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
/* Assure that some input is available. If input is requested, but denied,
|
||||||
|
then return a Z_BUF_ERROR from inflateBack(). */
|
||||||
|
#define PULL() \
|
||||||
|
do { \
|
||||||
|
if (have == 0) { \
|
||||||
|
have = in(in_desc, &next); \
|
||||||
|
if (have == 0) { \
|
||||||
|
next = Z_NULL; \
|
||||||
|
ret = Z_BUF_ERROR; \
|
||||||
|
goto inf_leave; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
/* Get a byte of input into the bit accumulator, or return from inflateBack()
|
||||||
|
with an error if there is no input available. */
|
||||||
|
#define PULLBYTE() \
|
||||||
|
do { \
|
||||||
|
PULL(); \
|
||||||
|
have--; \
|
||||||
|
hold += (unsigned long)(*next++) << bits; \
|
||||||
|
bits += 8; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
/* Assure that there are at least n bits in the bit accumulator. If there is
|
||||||
|
not enough available input to do that, then return from inflateBack() with
|
||||||
|
an error. */
|
||||||
|
#define NEEDBITS(n) \
|
||||||
|
do { \
|
||||||
|
while (bits < (unsigned)(n)) \
|
||||||
|
PULLBYTE(); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
/* Return the low n bits of the bit accumulator (n < 16) */
|
||||||
|
#define BITS(n) \
|
||||||
|
((unsigned)hold & ((1U << (n)) - 1))
|
||||||
|
|
||||||
|
/* Remove n bits from the bit accumulator */
|
||||||
|
#define DROPBITS(n) \
|
||||||
|
do { \
|
||||||
|
hold >>= (n); \
|
||||||
|
bits -= (unsigned)(n); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
/* Remove zero to seven bits as needed to go to a byte boundary */
|
||||||
|
#define BYTEBITS() \
|
||||||
|
do { \
|
||||||
|
hold >>= bits & 7; \
|
||||||
|
bits -= bits & 7; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
/* Assure that some output space is available, by writing out the window
|
||||||
|
if it's full. If the write fails, return from inflateBack() with a
|
||||||
|
Z_BUF_ERROR. */
|
||||||
|
#define ROOM() \
|
||||||
|
do { \
|
||||||
|
if (left == 0) { \
|
||||||
|
put = state->window; \
|
||||||
|
left = state->wsize; \
|
||||||
|
state->whave = left; \
|
||||||
|
if (out(out_desc, put, left)) { \
|
||||||
|
ret = Z_BUF_ERROR; \
|
||||||
|
goto inf_leave; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
/*
|
||||||
|
strm provides the memory allocation functions and window buffer on input,
|
||||||
|
and provides information on the unused input on return. For Z_DATA_ERROR
|
||||||
|
returns, strm will also provide an error message.
|
||||||
|
|
||||||
|
in() and out() are the call-back input and output functions. When
|
||||||
|
inflateBack() needs more input, it calls in(). When inflateBack() has
|
||||||
|
filled the window with output, or when it completes with data in the
|
||||||
|
window, it calls out() to write out the data. The application must not
|
||||||
|
change the provided input until in() is called again or inflateBack()
|
||||||
|
returns. The application must not change the window/output buffer until
|
||||||
|
inflateBack() returns.
|
||||||
|
|
||||||
|
in() and out() are called with a descriptor parameter provided in the
|
||||||
|
inflateBack() call. This parameter can be a structure that provides the
|
||||||
|
information required to do the read or write, as well as accumulated
|
||||||
|
information on the input and output such as totals and check values.
|
||||||
|
|
||||||
|
in() should return zero on failure. out() should return non-zero on
|
||||||
|
failure. If either in() or out() fails, than inflateBack() returns a
|
||||||
|
Z_BUF_ERROR. strm->next_in can be checked for Z_NULL to see whether it
|
||||||
|
was in() or out() that caused in the error. Otherwise, inflateBack()
|
||||||
|
returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format
|
||||||
|
error, or Z_MEM_ERROR if it could not allocate memory for the state.
|
||||||
|
inflateBack() can also return Z_STREAM_ERROR if the input parameters
|
||||||
|
are not correct, i.e. strm is Z_NULL or the state was not initialized.
|
||||||
|
*/
|
||||||
|
int ZEXPORT inflateBack(strm, in, in_desc, out, out_desc)
|
||||||
|
z_streamp strm;
|
||||||
|
in_func in;
|
||||||
|
void FAR *in_desc;
|
||||||
|
out_func out;
|
||||||
|
void FAR *out_desc;
|
||||||
|
{
|
||||||
|
struct inflate_state FAR *state;
|
||||||
|
unsigned char FAR *next; /* next input */
|
||||||
|
unsigned char FAR *put; /* next output */
|
||||||
|
unsigned have, left; /* available input and output */
|
||||||
|
unsigned long hold; /* bit buffer */
|
||||||
|
unsigned bits; /* bits in bit buffer */
|
||||||
|
unsigned copy; /* number of stored or match bytes to copy */
|
||||||
|
unsigned char FAR *from; /* where to copy match bytes from */
|
||||||
|
code this; /* current decoding table entry */
|
||||||
|
code last; /* parent table entry */
|
||||||
|
unsigned len; /* length to copy for repeats, bits to drop */
|
||||||
|
int ret; /* return code */
|
||||||
|
static const unsigned short order[19] = /* permutation of code lengths */
|
||||||
|
{16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
|
||||||
|
|
||||||
|
/* Check that the strm exists and that the state was initialized */
|
||||||
|
if (strm == Z_NULL || strm->state == Z_NULL)
|
||||||
|
return Z_STREAM_ERROR;
|
||||||
|
state = (struct inflate_state FAR *)strm->state;
|
||||||
|
|
||||||
|
/* Reset the state */
|
||||||
|
strm->msg = Z_NULL;
|
||||||
|
state->mode = TYPE;
|
||||||
|
state->last = 0;
|
||||||
|
state->whave = 0;
|
||||||
|
next = strm->next_in;
|
||||||
|
have = next != Z_NULL ? strm->avail_in : 0;
|
||||||
|
hold = 0;
|
||||||
|
bits = 0;
|
||||||
|
put = state->window;
|
||||||
|
left = state->wsize;
|
||||||
|
|
||||||
|
/* Inflate until end of block marked as last */
|
||||||
|
for (;;)
|
||||||
|
switch (state->mode) {
|
||||||
|
case TYPE:
|
||||||
|
/* determine and dispatch block type */
|
||||||
|
if (state->last) {
|
||||||
|
BYTEBITS();
|
||||||
|
state->mode = DONE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
NEEDBITS(3);
|
||||||
|
state->last = BITS(1);
|
||||||
|
DROPBITS(1);
|
||||||
|
switch (BITS(2)) {
|
||||||
|
case 0: /* stored block */
|
||||||
|
Tracev((stderr, "inflate: stored block%s\n",
|
||||||
|
state->last ? " (last)" : ""));
|
||||||
|
state->mode = STORED;
|
||||||
|
break;
|
||||||
|
case 1: /* fixed block */
|
||||||
|
fixedtables(state);
|
||||||
|
Tracev((stderr, "inflate: fixed codes block%s\n",
|
||||||
|
state->last ? " (last)" : ""));
|
||||||
|
state->mode = LEN; /* decode codes */
|
||||||
|
break;
|
||||||
|
case 2: /* dynamic block */
|
||||||
|
Tracev((stderr, "inflate: dynamic codes block%s\n",
|
||||||
|
state->last ? " (last)" : ""));
|
||||||
|
state->mode = TABLE;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
strm->msg = (char *)"invalid block type";
|
||||||
|
state->mode = BAD;
|
||||||
|
}
|
||||||
|
DROPBITS(2);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case STORED:
|
||||||
|
/* get and verify stored block length */
|
||||||
|
BYTEBITS(); /* go to byte boundary */
|
||||||
|
NEEDBITS(32);
|
||||||
|
if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
|
||||||
|
strm->msg = (char *)"invalid stored block lengths";
|
||||||
|
state->mode = BAD;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
state->length = (unsigned)hold & 0xffff;
|
||||||
|
Tracev((stderr, "inflate: stored length %u\n",
|
||||||
|
state->length));
|
||||||
|
INITBITS();
|
||||||
|
|
||||||
|
/* copy stored block from input to output */
|
||||||
|
while (state->length != 0) {
|
||||||
|
copy = state->length;
|
||||||
|
PULL();
|
||||||
|
ROOM();
|
||||||
|
if (copy > have) copy = have;
|
||||||
|
if (copy > left) copy = left;
|
||||||
|
zmemcpy(put, next, copy);
|
||||||
|
have -= copy;
|
||||||
|
next += copy;
|
||||||
|
left -= copy;
|
||||||
|
put += copy;
|
||||||
|
state->length -= copy;
|
||||||
|
}
|
||||||
|
Tracev((stderr, "inflate: stored end\n"));
|
||||||
|
state->mode = TYPE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TABLE:
|
||||||
|
/* get dynamic table entries descriptor */
|
||||||
|
NEEDBITS(14);
|
||||||
|
state->nlen = BITS(5) + 257;
|
||||||
|
DROPBITS(5);
|
||||||
|
state->ndist = BITS(5) + 1;
|
||||||
|
DROPBITS(5);
|
||||||
|
state->ncode = BITS(4) + 4;
|
||||||
|
DROPBITS(4);
|
||||||
|
#ifndef PKZIP_BUG_WORKAROUND
|
||||||
|
if (state->nlen > 286 || state->ndist > 30) {
|
||||||
|
strm->msg = (char *)"too many length or distance symbols";
|
||||||
|
state->mode = BAD;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
Tracev((stderr, "inflate: table sizes ok\n"));
|
||||||
|
|
||||||
|
/* get code length code lengths (not a typo) */
|
||||||
|
state->have = 0;
|
||||||
|
while (state->have < state->ncode) {
|
||||||
|
NEEDBITS(3);
|
||||||
|
state->lens[order[state->have++]] = (unsigned short)BITS(3);
|
||||||
|
DROPBITS(3);
|
||||||
|
}
|
||||||
|
while (state->have < 19)
|
||||||
|
state->lens[order[state->have++]] = 0;
|
||||||
|
state->next = state->codes;
|
||||||
|
state->lencode = (code const FAR *)(state->next);
|
||||||
|
state->lenbits = 7;
|
||||||
|
ret = inflate_table(CODES, state->lens, 19, &(state->next),
|
||||||
|
&(state->lenbits), state->work);
|
||||||
|
if (ret) {
|
||||||
|
strm->msg = (char *)"invalid code lengths set";
|
||||||
|
state->mode = BAD;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Tracev((stderr, "inflate: code lengths ok\n"));
|
||||||
|
|
||||||
|
/* get length and distance code code lengths */
|
||||||
|
state->have = 0;
|
||||||
|
while (state->have < state->nlen + state->ndist) {
|
||||||
|
for (;;) {
|
||||||
|
this = state->lencode[BITS(state->lenbits)];
|
||||||
|
if ((unsigned)(this.bits) <= bits) break;
|
||||||
|
PULLBYTE();
|
||||||
|
}
|
||||||
|
if (this.val < 16) {
|
||||||
|
NEEDBITS(this.bits);
|
||||||
|
DROPBITS(this.bits);
|
||||||
|
state->lens[state->have++] = this.val;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (this.val == 16) {
|
||||||
|
NEEDBITS(this.bits + 2);
|
||||||
|
DROPBITS(this.bits);
|
||||||
|
if (state->have == 0) {
|
||||||
|
strm->msg = (char *)"invalid bit length repeat";
|
||||||
|
state->mode = BAD;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
len = (unsigned)(state->lens[state->have - 1]);
|
||||||
|
copy = 3 + BITS(2);
|
||||||
|
DROPBITS(2);
|
||||||
|
}
|
||||||
|
else if (this.val == 17) {
|
||||||
|
NEEDBITS(this.bits + 3);
|
||||||
|
DROPBITS(this.bits);
|
||||||
|
len = 0;
|
||||||
|
copy = 3 + BITS(3);
|
||||||
|
DROPBITS(3);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
NEEDBITS(this.bits + 7);
|
||||||
|
DROPBITS(this.bits);
|
||||||
|
len = 0;
|
||||||
|
copy = 11 + BITS(7);
|
||||||
|
DROPBITS(7);
|
||||||
|
}
|
||||||
|
if (state->have + copy > state->nlen + state->ndist) {
|
||||||
|
strm->msg = (char *)"invalid bit length repeat";
|
||||||
|
state->mode = BAD;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
while (copy--)
|
||||||
|
state->lens[state->have++] = (unsigned short)len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* handle error breaks in while */
|
||||||
|
if (state->mode == BAD) break;
|
||||||
|
|
||||||
|
/* build code tables */
|
||||||
|
state->next = state->codes;
|
||||||
|
state->lencode = (code const FAR *)(state->next);
|
||||||
|
state->lenbits = 9;
|
||||||
|
ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),
|
||||||
|
&(state->lenbits), state->work);
|
||||||
|
if (ret) {
|
||||||
|
strm->msg = (char *)"invalid literal/lengths set";
|
||||||
|
state->mode = BAD;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
state->distcode = (code const FAR *)(state->next);
|
||||||
|
state->distbits = 6;
|
||||||
|
ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,
|
||||||
|
&(state->next), &(state->distbits), state->work);
|
||||||
|
if (ret) {
|
||||||
|
strm->msg = (char *)"invalid distances set";
|
||||||
|
state->mode = BAD;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Tracev((stderr, "inflate: codes ok\n"));
|
||||||
|
state->mode = LEN;
|
||||||
|
|
||||||
|
case LEN:
|
||||||
|
/* use inflate_fast() if we have enough input and output */
|
||||||
|
if (have >= 6 && left >= 258) {
|
||||||
|
RESTORE();
|
||||||
|
if (state->whave < state->wsize)
|
||||||
|
state->whave = state->wsize - left;
|
||||||
|
inflate_fast(strm, state->wsize);
|
||||||
|
LOAD();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get a literal, length, or end-of-block code */
|
||||||
|
for (;;) {
|
||||||
|
this = state->lencode[BITS(state->lenbits)];
|
||||||
|
if ((unsigned)(this.bits) <= bits) break;
|
||||||
|
PULLBYTE();
|
||||||
|
}
|
||||||
|
if (this.op && (this.op & 0xf0) == 0) {
|
||||||
|
last = this;
|
||||||
|
for (;;) {
|
||||||
|
this = state->lencode[last.val +
|
||||||
|
(BITS(last.bits + last.op) >> last.bits)];
|
||||||
|
if ((unsigned)(last.bits + this.bits) <= bits) break;
|
||||||
|
PULLBYTE();
|
||||||
|
}
|
||||||
|
DROPBITS(last.bits);
|
||||||
|
}
|
||||||
|
DROPBITS(this.bits);
|
||||||
|
state->length = (unsigned)this.val;
|
||||||
|
|
||||||
|
/* process literal */
|
||||||
|
if (this.op == 0) {
|
||||||
|
Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ?
|
||||||
|
"inflate: literal '%c'\n" :
|
||||||
|
"inflate: literal 0x%02x\n", this.val));
|
||||||
|
ROOM();
|
||||||
|
*put++ = (unsigned char)(state->length);
|
||||||
|
left--;
|
||||||
|
state->mode = LEN;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* process end of block */
|
||||||
|
if (this.op & 32) {
|
||||||
|
Tracevv((stderr, "inflate: end of block\n"));
|
||||||
|
state->mode = TYPE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* invalid code */
|
||||||
|
if (this.op & 64) {
|
||||||
|
strm->msg = (char *)"invalid literal/length code";
|
||||||
|
state->mode = BAD;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* length code -- get extra bits, if any */
|
||||||
|
state->extra = (unsigned)(this.op) & 15;
|
||||||
|
if (state->extra != 0) {
|
||||||
|
NEEDBITS(state->extra);
|
||||||
|
state->length += BITS(state->extra);
|
||||||
|
DROPBITS(state->extra);
|
||||||
|
}
|
||||||
|
Tracevv((stderr, "inflate: length %u\n", state->length));
|
||||||
|
|
||||||
|
/* get distance code */
|
||||||
|
for (;;) {
|
||||||
|
this = state->distcode[BITS(state->distbits)];
|
||||||
|
if ((unsigned)(this.bits) <= bits) break;
|
||||||
|
PULLBYTE();
|
||||||
|
}
|
||||||
|
if ((this.op & 0xf0) == 0) {
|
||||||
|
last = this;
|
||||||
|
for (;;) {
|
||||||
|
this = state->distcode[last.val +
|
||||||
|
(BITS(last.bits + last.op) >> last.bits)];
|
||||||
|
if ((unsigned)(last.bits + this.bits) <= bits) break;
|
||||||
|
PULLBYTE();
|
||||||
|
}
|
||||||
|
DROPBITS(last.bits);
|
||||||
|
}
|
||||||
|
DROPBITS(this.bits);
|
||||||
|
if (this.op & 64) {
|
||||||
|
strm->msg = (char *)"invalid distance code";
|
||||||
|
state->mode = BAD;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
state->offset = (unsigned)this.val;
|
||||||
|
|
||||||
|
/* get distance extra bits, if any */
|
||||||
|
state->extra = (unsigned)(this.op) & 15;
|
||||||
|
if (state->extra != 0) {
|
||||||
|
NEEDBITS(state->extra);
|
||||||
|
state->offset += BITS(state->extra);
|
||||||
|
DROPBITS(state->extra);
|
||||||
|
}
|
||||||
|
if (state->offset > state->wsize - (state->whave < state->wsize ?
|
||||||
|
left : 0)) {
|
||||||
|
strm->msg = (char *)"invalid distance too far back";
|
||||||
|
state->mode = BAD;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Tracevv((stderr, "inflate: distance %u\n", state->offset));
|
||||||
|
|
||||||
|
/* copy match from window to output */
|
||||||
|
do {
|
||||||
|
ROOM();
|
||||||
|
copy = state->wsize - state->offset;
|
||||||
|
if (copy < left) {
|
||||||
|
from = put + copy;
|
||||||
|
copy = left - copy;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
from = put - state->offset;
|
||||||
|
copy = left;
|
||||||
|
}
|
||||||
|
if (copy > state->length) copy = state->length;
|
||||||
|
state->length -= copy;
|
||||||
|
left -= copy;
|
||||||
|
do {
|
||||||
|
*put++ = *from++;
|
||||||
|
} while (--copy);
|
||||||
|
} while (state->length != 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DONE:
|
||||||
|
/* inflate stream terminated properly -- write leftover output */
|
||||||
|
ret = Z_STREAM_END;
|
||||||
|
if (left < state->wsize) {
|
||||||
|
if (out(out_desc, state->window, state->wsize - left))
|
||||||
|
ret = Z_BUF_ERROR;
|
||||||
|
}
|
||||||
|
goto inf_leave;
|
||||||
|
|
||||||
|
case BAD:
|
||||||
|
ret = Z_DATA_ERROR;
|
||||||
|
goto inf_leave;
|
||||||
|
|
||||||
|
default: /* can't happen, but makes compilers happy */
|
||||||
|
ret = Z_STREAM_ERROR;
|
||||||
|
goto inf_leave;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return unused input */
|
||||||
|
inf_leave:
|
||||||
|
strm->next_in = next;
|
||||||
|
strm->avail_in = have;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ZEXPORT inflateBackEnd(strm)
|
||||||
|
z_streamp strm;
|
||||||
|
{
|
||||||
|
if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0)
|
||||||
|
return Z_STREAM_ERROR;
|
||||||
|
ZFREE(strm, strm->state);
|
||||||
|
strm->state = Z_NULL;
|
||||||
|
Tracev((stderr, "inflate: end\n"));
|
||||||
|
return Z_OK;
|
||||||
|
}
|
|
@ -0,0 +1,318 @@
|
||||||
|
/* inffast.c -- fast decoding
|
||||||
|
* Copyright (C) 1995-2004 Mark Adler
|
||||||
|
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "zutil.h"
|
||||||
|
#include "inftrees.h"
|
||||||
|
#include "inflate.h"
|
||||||
|
#include "inffast.h"
|
||||||
|
|
||||||
|
#ifndef ASMINF
|
||||||
|
|
||||||
|
/* Allow machine dependent optimization for post-increment or pre-increment.
|
||||||
|
Based on testing to date,
|
||||||
|
Pre-increment preferred for:
|
||||||
|
- PowerPC G3 (Adler)
|
||||||
|
- MIPS R5000 (Randers-Pehrson)
|
||||||
|
Post-increment preferred for:
|
||||||
|
- none
|
||||||
|
No measurable difference:
|
||||||
|
- Pentium III (Anderson)
|
||||||
|
- M68060 (Nikl)
|
||||||
|
*/
|
||||||
|
#ifdef POSTINC
|
||||||
|
# define OFF 0
|
||||||
|
# define PUP(a) *(a)++
|
||||||
|
#else
|
||||||
|
# define OFF 1
|
||||||
|
# define PUP(a) *++(a)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
Decode literal, length, and distance codes and write out the resulting
|
||||||
|
literal and match bytes until either not enough input or output is
|
||||||
|
available, an end-of-block is encountered, or a data error is encountered.
|
||||||
|
When large enough input and output buffers are supplied to inflate(), for
|
||||||
|
example, a 16K input buffer and a 64K output buffer, more than 95% of the
|
||||||
|
inflate execution time is spent in this routine.
|
||||||
|
|
||||||
|
Entry assumptions:
|
||||||
|
|
||||||
|
state->mode == LEN
|
||||||
|
strm->avail_in >= 6
|
||||||
|
strm->avail_out >= 258
|
||||||
|
start >= strm->avail_out
|
||||||
|
state->bits < 8
|
||||||
|
|
||||||
|
On return, state->mode is one of:
|
||||||
|
|
||||||
|
LEN -- ran out of enough output space or enough available input
|
||||||
|
TYPE -- reached end of block code, inflate() to interpret next block
|
||||||
|
BAD -- error in block data
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
|
||||||
|
- The maximum input bits used by a length/distance pair is 15 bits for the
|
||||||
|
length code, 5 bits for the length extra, 15 bits for the distance code,
|
||||||
|
and 13 bits for the distance extra. This totals 48 bits, or six bytes.
|
||||||
|
Therefore if strm->avail_in >= 6, then there is enough input to avoid
|
||||||
|
checking for available input while decoding.
|
||||||
|
|
||||||
|
- The maximum bytes that a single length/distance pair can output is 258
|
||||||
|
bytes, which is the maximum length that can be coded. inflate_fast()
|
||||||
|
requires strm->avail_out >= 258 for each loop to avoid checking for
|
||||||
|
output space.
|
||||||
|
*/
|
||||||
|
void inflate_fast(strm, start)
|
||||||
|
z_streamp strm;
|
||||||
|
unsigned start; /* inflate()'s starting value for strm->avail_out */
|
||||||
|
{
|
||||||
|
struct inflate_state FAR *state;
|
||||||
|
unsigned char FAR *in; /* local strm->next_in */
|
||||||
|
unsigned char FAR *last; /* while in < last, enough input available */
|
||||||
|
unsigned char FAR *out; /* local strm->next_out */
|
||||||
|
unsigned char FAR *beg; /* inflate()'s initial strm->next_out */
|
||||||
|
unsigned char FAR *end; /* while out < end, enough space available */
|
||||||
|
#ifdef INFLATE_STRICT
|
||||||
|
unsigned dmax; /* maximum distance from zlib header */
|
||||||
|
#endif
|
||||||
|
unsigned wsize; /* window size or zero if not using window */
|
||||||
|
unsigned whave; /* valid bytes in the window */
|
||||||
|
unsigned write; /* window write index */
|
||||||
|
unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */
|
||||||
|
unsigned long hold; /* local strm->hold */
|
||||||
|
unsigned bits; /* local strm->bits */
|
||||||
|
code const FAR *lcode; /* local strm->lencode */
|
||||||
|
code const FAR *dcode; /* local strm->distcode */
|
||||||
|
unsigned lmask; /* mask for first level of length codes */
|
||||||
|
unsigned dmask; /* mask for first level of distance codes */
|
||||||
|
code this; /* retrieved table entry */
|
||||||
|
unsigned op; /* code bits, operation, extra bits, or */
|
||||||
|
/* window position, window bytes to copy */
|
||||||
|
unsigned len; /* match length, unused bytes */
|
||||||
|
unsigned dist; /* match distance */
|
||||||
|
unsigned char FAR *from; /* where to copy match from */
|
||||||
|
|
||||||
|
/* copy state to local variables */
|
||||||
|
state = (struct inflate_state FAR *)strm->state;
|
||||||
|
in = strm->next_in - OFF;
|
||||||
|
last = in + (strm->avail_in - 5);
|
||||||
|
out = strm->next_out - OFF;
|
||||||
|
beg = out - (start - strm->avail_out);
|
||||||
|
end = out + (strm->avail_out - 257);
|
||||||
|
#ifdef INFLATE_STRICT
|
||||||
|
dmax = state->dmax;
|
||||||
|
#endif
|
||||||
|
wsize = state->wsize;
|
||||||
|
whave = state->whave;
|
||||||
|
write = state->write;
|
||||||
|
window = state->window;
|
||||||
|
hold = state->hold;
|
||||||
|
bits = state->bits;
|
||||||
|
lcode = state->lencode;
|
||||||
|
dcode = state->distcode;
|
||||||
|
lmask = (1U << state->lenbits) - 1;
|
||||||
|
dmask = (1U << state->distbits) - 1;
|
||||||
|
|
||||||
|
/* decode literals and length/distances until end-of-block or not enough
|
||||||
|
input data or output space */
|
||||||
|
do {
|
||||||
|
if (bits < 15) {
|
||||||
|
hold += (unsigned long)(PUP(in)) << bits;
|
||||||
|
bits += 8;
|
||||||
|
hold += (unsigned long)(PUP(in)) << bits;
|
||||||
|
bits += 8;
|
||||||
|
}
|
||||||
|
this = lcode[hold & lmask];
|
||||||
|
dolen:
|
||||||
|
op = (unsigned)(this.bits);
|
||||||
|
hold >>= op;
|
||||||
|
bits -= op;
|
||||||
|
op = (unsigned)(this.op);
|
||||||
|
if (op == 0) { /* literal */
|
||||||
|
Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ?
|
||||||
|
"inflate: literal '%c'\n" :
|
||||||
|
"inflate: literal 0x%02x\n", this.val));
|
||||||
|
PUP(out) = (unsigned char)(this.val);
|
||||||
|
}
|
||||||
|
else if (op & 16) { /* length base */
|
||||||
|
len = (unsigned)(this.val);
|
||||||
|
op &= 15; /* number of extra bits */
|
||||||
|
if (op) {
|
||||||
|
if (bits < op) {
|
||||||
|
hold += (unsigned long)(PUP(in)) << bits;
|
||||||
|
bits += 8;
|
||||||
|
}
|
||||||
|
len += (unsigned)hold & ((1U << op) - 1);
|
||||||
|
hold >>= op;
|
||||||
|
bits -= op;
|
||||||
|
}
|
||||||
|
Tracevv((stderr, "inflate: length %u\n", len));
|
||||||
|
if (bits < 15) {
|
||||||
|
hold += (unsigned long)(PUP(in)) << bits;
|
||||||
|
bits += 8;
|
||||||
|
hold += (unsigned long)(PUP(in)) << bits;
|
||||||
|
bits += 8;
|
||||||
|
}
|
||||||
|
this = dcode[hold & dmask];
|
||||||
|
dodist:
|
||||||
|
op = (unsigned)(this.bits);
|
||||||
|
hold >>= op;
|
||||||
|
bits -= op;
|
||||||
|
op = (unsigned)(this.op);
|
||||||
|
if (op & 16) { /* distance base */
|
||||||
|
dist = (unsigned)(this.val);
|
||||||
|
op &= 15; /* number of extra bits */
|
||||||
|
if (bits < op) {
|
||||||
|
hold += (unsigned long)(PUP(in)) << bits;
|
||||||
|
bits += 8;
|
||||||
|
if (bits < op) {
|
||||||
|
hold += (unsigned long)(PUP(in)) << bits;
|
||||||
|
bits += 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dist += (unsigned)hold & ((1U << op) - 1);
|
||||||
|
#ifdef INFLATE_STRICT
|
||||||
|
if (dist > dmax) {
|
||||||
|
strm->msg = (char *)"invalid distance too far back";
|
||||||
|
state->mode = BAD;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
hold >>= op;
|
||||||
|
bits -= op;
|
||||||
|
Tracevv((stderr, "inflate: distance %u\n", dist));
|
||||||
|
op = (unsigned)(out - beg); /* max distance in output */
|
||||||
|
if (dist > op) { /* see if copy from window */
|
||||||
|
op = dist - op; /* distance back in window */
|
||||||
|
if (op > whave) {
|
||||||
|
strm->msg = (char *)"invalid distance too far back";
|
||||||
|
state->mode = BAD;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
from = window - OFF;
|
||||||
|
if (write == 0) { /* very common case */
|
||||||
|
from += wsize - op;
|
||||||
|
if (op < len) { /* some from window */
|
||||||
|
len -= op;
|
||||||
|
do {
|
||||||
|
PUP(out) = PUP(from);
|
||||||
|
} while (--op);
|
||||||
|
from = out - dist; /* rest from output */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (write < op) { /* wrap around window */
|
||||||
|
from += wsize + write - op;
|
||||||
|
op -= write;
|
||||||
|
if (op < len) { /* some from end of window */
|
||||||
|
len -= op;
|
||||||
|
do {
|
||||||
|
PUP(out) = PUP(from);
|
||||||
|
} while (--op);
|
||||||
|
from = window - OFF;
|
||||||
|
if (write < len) { /* some from start of window */
|
||||||
|
op = write;
|
||||||
|
len -= op;
|
||||||
|
do {
|
||||||
|
PUP(out) = PUP(from);
|
||||||
|
} while (--op);
|
||||||
|
from = out - dist; /* rest from output */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else { /* contiguous in window */
|
||||||
|
from += write - op;
|
||||||
|
if (op < len) { /* some from window */
|
||||||
|
len -= op;
|
||||||
|
do {
|
||||||
|
PUP(out) = PUP(from);
|
||||||
|
} while (--op);
|
||||||
|
from = out - dist; /* rest from output */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (len > 2) {
|
||||||
|
PUP(out) = PUP(from);
|
||||||
|
PUP(out) = PUP(from);
|
||||||
|
PUP(out) = PUP(from);
|
||||||
|
len -= 3;
|
||||||
|
}
|
||||||
|
if (len) {
|
||||||
|
PUP(out) = PUP(from);
|
||||||
|
if (len > 1)
|
||||||
|
PUP(out) = PUP(from);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
from = out - dist; /* copy direct from output */
|
||||||
|
do { /* minimum length is three */
|
||||||
|
PUP(out) = PUP(from);
|
||||||
|
PUP(out) = PUP(from);
|
||||||
|
PUP(out) = PUP(from);
|
||||||
|
len -= 3;
|
||||||
|
} while (len > 2);
|
||||||
|
if (len) {
|
||||||
|
PUP(out) = PUP(from);
|
||||||
|
if (len > 1)
|
||||||
|
PUP(out) = PUP(from);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ((op & 64) == 0) { /* 2nd level distance code */
|
||||||
|
this = dcode[this.val + (hold & ((1U << op) - 1))];
|
||||||
|
goto dodist;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
strm->msg = (char *)"invalid distance code";
|
||||||
|
state->mode = BAD;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ((op & 64) == 0) { /* 2nd level length code */
|
||||||
|
this = lcode[this.val + (hold & ((1U << op) - 1))];
|
||||||
|
goto dolen;
|
||||||
|
}
|
||||||
|
else if (op & 32) { /* end-of-block */
|
||||||
|
Tracevv((stderr, "inflate: end of block\n"));
|
||||||
|
state->mode = TYPE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
strm->msg = (char *)"invalid literal/length code";
|
||||||
|
state->mode = BAD;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while (in < last && out < end);
|
||||||
|
|
||||||
|
/* return unused bytes (on entry, bits < 8, so in won't go too far back) */
|
||||||
|
len = bits >> 3;
|
||||||
|
in -= len;
|
||||||
|
bits -= len << 3;
|
||||||
|
hold &= (1U << bits) - 1;
|
||||||
|
|
||||||
|
/* update state and return */
|
||||||
|
strm->next_in = in + OFF;
|
||||||
|
strm->next_out = out + OFF;
|
||||||
|
strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last));
|
||||||
|
strm->avail_out = (unsigned)(out < end ?
|
||||||
|
257 + (end - out) : 257 - (out - end));
|
||||||
|
state->hold = hold;
|
||||||
|
state->bits = bits;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe):
|
||||||
|
- Using bit fields for code structure
|
||||||
|
- Different op definition to avoid & for extra bits (do & for table bits)
|
||||||
|
- Three separate decoding do-loops for direct, window, and write == 0
|
||||||
|
- Special case for distance > 1 copies to do overlapped load and store copy
|
||||||
|
- Explicit branch predictions (based on measured branch probabilities)
|
||||||
|
- Deferring match copy and interspersed it with decoding subsequent codes
|
||||||
|
- Swapping literal/length else
|
||||||
|
- Swapping window/direct else
|
||||||
|
- Larger unrolled copy loops (three is about right)
|
||||||
|
- Moving len -= 3 statement into middle of loop
|
||||||
|
*/
|
||||||
|
|
||||||
|
#endif /* !ASMINF */
|
|
@ -0,0 +1,11 @@
|
||||||
|
/* inffast.h -- header to use inffast.c
|
||||||
|
* Copyright (C) 1995-2003 Mark Adler
|
||||||
|
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* WARNING: this file should *not* be used by applications. It is
|
||||||
|
part of the implementation of the compression library and is
|
||||||
|
subject to change. Applications should only use zlib.h.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void inflate_fast OF((z_streamp strm, unsigned start));
|
|
@ -0,0 +1,94 @@
|
||||||
|
/* inffixed.h -- table for decoding fixed codes
|
||||||
|
* Generated automatically by makefixed().
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* WARNING: this file should *not* be used by applications. It
|
||||||
|
is part of the implementation of the compression library and
|
||||||
|
is subject to change. Applications should only use zlib.h.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static const code lenfix[512] = {
|
||||||
|
{96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48},
|
||||||
|
{0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128},
|
||||||
|
{0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59},
|
||||||
|
{0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176},
|
||||||
|
{0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20},
|
||||||
|
{21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100},
|
||||||
|
{0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8},
|
||||||
|
{0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216},
|
||||||
|
{18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76},
|
||||||
|
{0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114},
|
||||||
|
{0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2},
|
||||||
|
{0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148},
|
||||||
|
{20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42},
|
||||||
|
{0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86},
|
||||||
|
{0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15},
|
||||||
|
{0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236},
|
||||||
|
{16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62},
|
||||||
|
{0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142},
|
||||||
|
{0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31},
|
||||||
|
{0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162},
|
||||||
|
{0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25},
|
||||||
|
{0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105},
|
||||||
|
{0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4},
|
||||||
|
{0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202},
|
||||||
|
{17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69},
|
||||||
|
{0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125},
|
||||||
|
{0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13},
|
||||||
|
{0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195},
|
||||||
|
{19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35},
|
||||||
|
{0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91},
|
||||||
|
{0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19},
|
||||||
|
{0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246},
|
||||||
|
{16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55},
|
||||||
|
{0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135},
|
||||||
|
{0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99},
|
||||||
|
{0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190},
|
||||||
|
{0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16},
|
||||||
|
{20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96},
|
||||||
|
{0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6},
|
||||||
|
{0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209},
|
||||||
|
{17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72},
|
||||||
|
{0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116},
|
||||||
|
{0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4},
|
||||||
|
{0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153},
|
||||||
|
{20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44},
|
||||||
|
{0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82},
|
||||||
|
{0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11},
|
||||||
|
{0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229},
|
||||||
|
{16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58},
|
||||||
|
{0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138},
|
||||||
|
{0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51},
|
||||||
|
{0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173},
|
||||||
|
{0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30},
|
||||||
|
{0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110},
|
||||||
|
{0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0},
|
||||||
|
{0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195},
|
||||||
|
{16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65},
|
||||||
|
{0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121},
|
||||||
|
{0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9},
|
||||||
|
{0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258},
|
||||||
|
{19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37},
|
||||||
|
{0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93},
|
||||||
|
{0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23},
|
||||||
|
{0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251},
|
||||||
|
{16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51},
|
||||||
|
{0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131},
|
||||||
|
{0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67},
|
||||||
|
{0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183},
|
||||||
|
{0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23},
|
||||||
|
{64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103},
|
||||||
|
{0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9},
|
||||||
|
{0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223},
|
||||||
|
{18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79},
|
||||||
|
{0,9,255}
|
||||||
|
};
|
||||||
|
|
||||||
|
static const code distfix[32] = {
|
||||||
|
{16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025},
|
||||||
|
{21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193},
|
||||||
|
{18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385},
|
||||||
|
{19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577},
|
||||||
|
{16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073},
|
||||||
|
{22,5,193},{64,5,0}
|
||||||
|
};
|
|
@ -0,0 +1,115 @@
|
||||||
|
/* inflate.h -- internal inflate state definition
|
||||||
|
* Copyright (C) 1995-2004 Mark Adler
|
||||||
|
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* WARNING: this file should *not* be used by applications. It is
|
||||||
|
part of the implementation of the compression library and is
|
||||||
|
subject to change. Applications should only use zlib.h.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* define NO_GZIP when compiling if you want to disable gzip header and
|
||||||
|
trailer decoding by inflate(). NO_GZIP would be used to avoid linking in
|
||||||
|
the crc code when it is not needed. For shared libraries, gzip decoding
|
||||||
|
should be left enabled. */
|
||||||
|
#ifndef NO_GZIP
|
||||||
|
# define GUNZIP
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Possible inflate modes between inflate() calls */
|
||||||
|
typedef enum {
|
||||||
|
HEAD, /* i: waiting for magic header */
|
||||||
|
FLAGS, /* i: waiting for method and flags (gzip) */
|
||||||
|
TIME, /* i: waiting for modification time (gzip) */
|
||||||
|
OS, /* i: waiting for extra flags and operating system (gzip) */
|
||||||
|
EXLEN, /* i: waiting for extra length (gzip) */
|
||||||
|
EXTRA, /* i: waiting for extra bytes (gzip) */
|
||||||
|
NAME, /* i: waiting for end of file name (gzip) */
|
||||||
|
COMMENT, /* i: waiting for end of comment (gzip) */
|
||||||
|
HCRC, /* i: waiting for header crc (gzip) */
|
||||||
|
DICTID, /* i: waiting for dictionary check value */
|
||||||
|
DICT, /* waiting for inflateSetDictionary() call */
|
||||||
|
TYPE, /* i: waiting for type bits, including last-flag bit */
|
||||||
|
TYPEDO, /* i: same, but skip check to exit inflate on new block */
|
||||||
|
STORED, /* i: waiting for stored size (length and complement) */
|
||||||
|
COPY, /* i/o: waiting for input or output to copy stored block */
|
||||||
|
TABLE, /* i: waiting for dynamic block table lengths */
|
||||||
|
LENLENS, /* i: waiting for code length code lengths */
|
||||||
|
CODELENS, /* i: waiting for length/lit and distance code lengths */
|
||||||
|
LEN, /* i: waiting for length/lit code */
|
||||||
|
LENEXT, /* i: waiting for length extra bits */
|
||||||
|
DIST, /* i: waiting for distance code */
|
||||||
|
DISTEXT, /* i: waiting for distance extra bits */
|
||||||
|
MATCH, /* o: waiting for output space to copy string */
|
||||||
|
LIT, /* o: waiting for output space to write literal */
|
||||||
|
CHECK, /* i: waiting for 32-bit check value */
|
||||||
|
LENGTH, /* i: waiting for 32-bit length (gzip) */
|
||||||
|
DONE, /* finished check, done -- remain here until reset */
|
||||||
|
BAD, /* got a data error -- remain here until reset */
|
||||||
|
MEM, /* got an inflate() memory error -- remain here until reset */
|
||||||
|
SYNC /* looking for synchronization bytes to restart inflate() */
|
||||||
|
} inflate_mode;
|
||||||
|
|
||||||
|
/*
|
||||||
|
State transitions between above modes -
|
||||||
|
|
||||||
|
(most modes can go to the BAD or MEM mode -- not shown for clarity)
|
||||||
|
|
||||||
|
Process header:
|
||||||
|
HEAD -> (gzip) or (zlib)
|
||||||
|
(gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME
|
||||||
|
NAME -> COMMENT -> HCRC -> TYPE
|
||||||
|
(zlib) -> DICTID or TYPE
|
||||||
|
DICTID -> DICT -> TYPE
|
||||||
|
Read deflate blocks:
|
||||||
|
TYPE -> STORED or TABLE or LEN or CHECK
|
||||||
|
STORED -> COPY -> TYPE
|
||||||
|
TABLE -> LENLENS -> CODELENS -> LEN
|
||||||
|
Read deflate codes:
|
||||||
|
LEN -> LENEXT or LIT or TYPE
|
||||||
|
LENEXT -> DIST -> DISTEXT -> MATCH -> LEN
|
||||||
|
LIT -> LEN
|
||||||
|
Process trailer:
|
||||||
|
CHECK -> LENGTH -> DONE
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* state maintained between inflate() calls. Approximately 7K bytes. */
|
||||||
|
struct inflate_state {
|
||||||
|
inflate_mode mode; /* current inflate mode */
|
||||||
|
int last; /* true if processing last block */
|
||||||
|
int wrap; /* bit 0 true for zlib, bit 1 true for gzip */
|
||||||
|
int havedict; /* true if dictionary provided */
|
||||||
|
int flags; /* gzip header method and flags (0 if zlib) */
|
||||||
|
unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */
|
||||||
|
unsigned long check; /* protected copy of check value */
|
||||||
|
unsigned long total; /* protected copy of output count */
|
||||||
|
gz_headerp head; /* where to save gzip header information */
|
||||||
|
/* sliding window */
|
||||||
|
unsigned wbits; /* log base 2 of requested window size */
|
||||||
|
unsigned wsize; /* window size or zero if not using window */
|
||||||
|
unsigned whave; /* valid bytes in the window */
|
||||||
|
unsigned write; /* window write index */
|
||||||
|
unsigned char FAR *window; /* allocated sliding window, if needed */
|
||||||
|
/* bit accumulator */
|
||||||
|
unsigned long hold; /* input bit accumulator */
|
||||||
|
unsigned bits; /* number of bits in "in" */
|
||||||
|
/* for string and stored block copying */
|
||||||
|
unsigned length; /* literal or length of data to copy */
|
||||||
|
unsigned offset; /* distance back to copy string from */
|
||||||
|
/* for table and code decoding */
|
||||||
|
unsigned extra; /* extra bits needed */
|
||||||
|
/* fixed and dynamic code tables */
|
||||||
|
code const FAR *lencode; /* starting table for length/literal codes */
|
||||||
|
code const FAR *distcode; /* starting table for distance codes */
|
||||||
|
unsigned lenbits; /* index bits for lencode */
|
||||||
|
unsigned distbits; /* index bits for distcode */
|
||||||
|
/* dynamic table building */
|
||||||
|
unsigned ncode; /* number of code length code lengths */
|
||||||
|
unsigned nlen; /* number of length code lengths */
|
||||||
|
unsigned ndist; /* number of distance code lengths */
|
||||||
|
unsigned have; /* number of code lengths in lens[] */
|
||||||
|
code FAR *next; /* next available space in codes[] */
|
||||||
|
unsigned short lens[320]; /* temporary storage for code lengths */
|
||||||
|
unsigned short work[288]; /* work area for code table building */
|
||||||
|
code codes[ENOUGH]; /* space for code tables */
|
||||||
|
};
|
|
@ -0,0 +1,329 @@
|
||||||
|
/* inftrees.c -- generate Huffman trees for efficient decoding
|
||||||
|
* Copyright (C) 1995-2005 Mark Adler
|
||||||
|
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "zutil.h"
|
||||||
|
#include "inftrees.h"
|
||||||
|
|
||||||
|
#define MAXBITS 15
|
||||||
|
|
||||||
|
const char inflate_copyright[] =
|
||||||
|
" inflate 1.2.3 Copyright 1995-2005 Mark Adler ";
|
||||||
|
/*
|
||||||
|
If you use the zlib library in a product, an acknowledgment is welcome
|
||||||
|
in the documentation of your product. If for some reason you cannot
|
||||||
|
include such an acknowledgment, I would appreciate that you keep this
|
||||||
|
copyright string in the executable of your product.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Build a set of tables to decode the provided canonical Huffman code.
|
||||||
|
The code lengths are lens[0..codes-1]. The result starts at *table,
|
||||||
|
whose indices are 0..2^bits-1. work is a writable array of at least
|
||||||
|
lens shorts, which is used as a work area. type is the type of code
|
||||||
|
to be generated, CODES, LENS, or DISTS. On return, zero is success,
|
||||||
|
-1 is an invalid code, and +1 means that ENOUGH isn't enough. table
|
||||||
|
on return points to the next available entry's address. bits is the
|
||||||
|
requested root table index bits, and on return it is the actual root
|
||||||
|
table index bits. It will differ if the request is greater than the
|
||||||
|
longest code or if it is less than the shortest code.
|
||||||
|
*/
|
||||||
|
int inflate_table(type, lens, codes, table, bits, work)
|
||||||
|
codetype type;
|
||||||
|
unsigned short FAR *lens;
|
||||||
|
unsigned codes;
|
||||||
|
code FAR * FAR *table;
|
||||||
|
unsigned FAR *bits;
|
||||||
|
unsigned short FAR *work;
|
||||||
|
{
|
||||||
|
unsigned len; /* a code's length in bits */
|
||||||
|
unsigned sym; /* index of code symbols */
|
||||||
|
unsigned min, max; /* minimum and maximum code lengths */
|
||||||
|
unsigned root; /* number of index bits for root table */
|
||||||
|
unsigned curr; /* number of index bits for current table */
|
||||||
|
unsigned drop; /* code bits to drop for sub-table */
|
||||||
|
int left; /* number of prefix codes available */
|
||||||
|
unsigned used; /* code entries in table used */
|
||||||
|
unsigned huff; /* Huffman code */
|
||||||
|
unsigned incr; /* for incrementing code, index */
|
||||||
|
unsigned fill; /* index for replicating entries */
|
||||||
|
unsigned low; /* low bits for current root entry */
|
||||||
|
unsigned mask; /* mask for low root bits */
|
||||||
|
code this; /* table entry for duplication */
|
||||||
|
code FAR *next; /* next available space in table */
|
||||||
|
const unsigned short FAR *base; /* base value table to use */
|
||||||
|
const unsigned short FAR *extra; /* extra bits table to use */
|
||||||
|
int end; /* use base and extra for symbol > end */
|
||||||
|
unsigned short count[MAXBITS+1]; /* number of codes of each length */
|
||||||
|
unsigned short offs[MAXBITS+1]; /* offsets in table for each length */
|
||||||
|
static const unsigned short lbase[31] = { /* Length codes 257..285 base */
|
||||||
|
3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
|
||||||
|
35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
|
||||||
|
static const unsigned short lext[31] = { /* Length codes 257..285 extra */
|
||||||
|
16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
|
||||||
|
19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 201, 196};
|
||||||
|
static const unsigned short dbase[32] = { /* Distance codes 0..29 base */
|
||||||
|
1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
|
||||||
|
257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
|
||||||
|
8193, 12289, 16385, 24577, 0, 0};
|
||||||
|
static const unsigned short dext[32] = { /* Distance codes 0..29 extra */
|
||||||
|
16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22,
|
||||||
|
23, 23, 24, 24, 25, 25, 26, 26, 27, 27,
|
||||||
|
28, 28, 29, 29, 64, 64};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Process a set of code lengths to create a canonical Huffman code. The
|
||||||
|
code lengths are lens[0..codes-1]. Each length corresponds to the
|
||||||
|
symbols 0..codes-1. The Huffman code is generated by first sorting the
|
||||||
|
symbols by length from short to long, and retaining the symbol order
|
||||||
|
for codes with equal lengths. Then the code starts with all zero bits
|
||||||
|
for the first code of the shortest length, and the codes are integer
|
||||||
|
increments for the same length, and zeros are appended as the length
|
||||||
|
increases. For the deflate format, these bits are stored backwards
|
||||||
|
from their more natural integer increment ordering, and so when the
|
||||||
|
decoding tables are built in the large loop below, the integer codes
|
||||||
|
are incremented backwards.
|
||||||
|
|
||||||
|
This routine assumes, but does not check, that all of the entries in
|
||||||
|
lens[] are in the range 0..MAXBITS. The caller must assure this.
|
||||||
|
1..MAXBITS is interpreted as that code length. zero means that that
|
||||||
|
symbol does not occur in this code.
|
||||||
|
|
||||||
|
The codes are sorted by computing a count of codes for each length,
|
||||||
|
creating from that a table of starting indices for each length in the
|
||||||
|
sorted table, and then entering the symbols in order in the sorted
|
||||||
|
table. The sorted table is work[], with that space being provided by
|
||||||
|
the caller.
|
||||||
|
|
||||||
|
The length counts are used for other purposes as well, i.e. finding
|
||||||
|
the minimum and maximum length codes, determining if there are any
|
||||||
|
codes at all, checking for a valid set of lengths, and looking ahead
|
||||||
|
at length counts to determine sub-table sizes when building the
|
||||||
|
decoding tables.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */
|
||||||
|
for (len = 0; len <= MAXBITS; len++)
|
||||||
|
count[len] = 0;
|
||||||
|
for (sym = 0; sym < codes; sym++)
|
||||||
|
count[lens[sym]]++;
|
||||||
|
|
||||||
|
/* bound code lengths, force root to be within code lengths */
|
||||||
|
root = *bits;
|
||||||
|
for (max = MAXBITS; max >= 1; max--)
|
||||||
|
if (count[max] != 0) break;
|
||||||
|
if (root > max) root = max;
|
||||||
|
if (max == 0) { /* no symbols to code at all */
|
||||||
|
this.op = (unsigned char)64; /* invalid code marker */
|
||||||
|
this.bits = (unsigned char)1;
|
||||||
|
this.val = (unsigned short)0;
|
||||||
|
*(*table)++ = this; /* make a table to force an error */
|
||||||
|
*(*table)++ = this;
|
||||||
|
*bits = 1;
|
||||||
|
return 0; /* no symbols, but wait for decoding to report error */
|
||||||
|
}
|
||||||
|
for (min = 1; min <= MAXBITS; min++)
|
||||||
|
if (count[min] != 0) break;
|
||||||
|
if (root < min) root = min;
|
||||||
|
|
||||||
|
/* check for an over-subscribed or incomplete set of lengths */
|
||||||
|
left = 1;
|
||||||
|
for (len = 1; len <= MAXBITS; len++) {
|
||||||
|
left <<= 1;
|
||||||
|
left -= count[len];
|
||||||
|
if (left < 0) return -1; /* over-subscribed */
|
||||||
|
}
|
||||||
|
if (left > 0 && (type == CODES || max != 1))
|
||||||
|
return -1; /* incomplete set */
|
||||||
|
|
||||||
|
/* generate offsets into symbol table for each length for sorting */
|
||||||
|
offs[1] = 0;
|
||||||
|
for (len = 1; len < MAXBITS; len++)
|
||||||
|
offs[len + 1] = offs[len] + count[len];
|
||||||
|
|
||||||
|
/* sort symbols by length, by symbol order within each length */
|
||||||
|
for (sym = 0; sym < codes; sym++)
|
||||||
|
if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Create and fill in decoding tables. In this loop, the table being
|
||||||
|
filled is at next and has curr index bits. The code being used is huff
|
||||||
|
with length len. That code is converted to an index by dropping drop
|
||||||
|
bits off of the bottom. For codes where len is less than drop + curr,
|
||||||
|
those top drop + curr - len bits are incremented through all values to
|
||||||
|
fill the table with replicated entries.
|
||||||
|
|
||||||
|
root is the number of index bits for the root table. When len exceeds
|
||||||
|
root, sub-tables are created pointed to by the root entry with an index
|
||||||
|
of the low root bits of huff. This is saved in low to check for when a
|
||||||
|
new sub-table should be started. drop is zero when the root table is
|
||||||
|
being filled, and drop is root when sub-tables are being filled.
|
||||||
|
|
||||||
|
When a new sub-table is needed, it is necessary to look ahead in the
|
||||||
|
code lengths to determine what size sub-table is needed. The length
|
||||||
|
counts are used for this, and so count[] is decremented as codes are
|
||||||
|
entered in the tables.
|
||||||
|
|
||||||
|
used keeps track of how many table entries have been allocated from the
|
||||||
|
provided *table space. It is checked when a LENS table is being made
|
||||||
|
against the space in *table, ENOUGH, minus the maximum space needed by
|
||||||
|
the worst case distance code, MAXD. This should never happen, but the
|
||||||
|
sufficiency of ENOUGH has not been proven exhaustively, hence the check.
|
||||||
|
This assumes that when type == LENS, bits == 9.
|
||||||
|
|
||||||
|
sym increments through all symbols, and the loop terminates when
|
||||||
|
all codes of length max, i.e. all codes, have been processed. This
|
||||||
|
routine permits incomplete codes, so another loop after this one fills
|
||||||
|
in the rest of the decoding tables with invalid code markers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* set up for code type */
|
||||||
|
switch (type) {
|
||||||
|
case CODES:
|
||||||
|
base = extra = work; /* dummy value--not used */
|
||||||
|
end = 19;
|
||||||
|
break;
|
||||||
|
case LENS:
|
||||||
|
base = lbase;
|
||||||
|
base -= 257;
|
||||||
|
extra = lext;
|
||||||
|
extra -= 257;
|
||||||
|
end = 256;
|
||||||
|
break;
|
||||||
|
default: /* DISTS */
|
||||||
|
base = dbase;
|
||||||
|
extra = dext;
|
||||||
|
end = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* initialize state for loop */
|
||||||
|
huff = 0; /* starting code */
|
||||||
|
sym = 0; /* starting code symbol */
|
||||||
|
len = min; /* starting code length */
|
||||||
|
next = *table; /* current table to fill in */
|
||||||
|
curr = root; /* current table index bits */
|
||||||
|
drop = 0; /* current bits to drop from code for index */
|
||||||
|
low = (unsigned)(-1); /* trigger new sub-table when len > root */
|
||||||
|
used = 1U << root; /* use root table entries */
|
||||||
|
mask = used - 1; /* mask for comparing low */
|
||||||
|
|
||||||
|
/* check available table space */
|
||||||
|
if (type == LENS && used >= ENOUGH - MAXD)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
/* process all codes and make table entries */
|
||||||
|
for (;;) {
|
||||||
|
/* create table entry */
|
||||||
|
this.bits = (unsigned char)(len - drop);
|
||||||
|
if ((int)(work[sym]) < end) {
|
||||||
|
this.op = (unsigned char)0;
|
||||||
|
this.val = work[sym];
|
||||||
|
}
|
||||||
|
else if ((int)(work[sym]) > end) {
|
||||||
|
this.op = (unsigned char)(extra[work[sym]]);
|
||||||
|
this.val = base[work[sym]];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.op = (unsigned char)(32 + 64); /* end of block */
|
||||||
|
this.val = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* replicate for those indices with low len bits equal to huff */
|
||||||
|
incr = 1U << (len - drop);
|
||||||
|
fill = 1U << curr;
|
||||||
|
min = fill; /* save offset to next table */
|
||||||
|
do {
|
||||||
|
fill -= incr;
|
||||||
|
next[(huff >> drop) + fill] = this;
|
||||||
|
} while (fill != 0);
|
||||||
|
|
||||||
|
/* backwards increment the len-bit code huff */
|
||||||
|
incr = 1U << (len - 1);
|
||||||
|
while (huff & incr)
|
||||||
|
incr >>= 1;
|
||||||
|
if (incr != 0) {
|
||||||
|
huff &= incr - 1;
|
||||||
|
huff += incr;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
huff = 0;
|
||||||
|
|
||||||
|
/* go to next symbol, update count, len */
|
||||||
|
sym++;
|
||||||
|
if (--(count[len]) == 0) {
|
||||||
|
if (len == max) break;
|
||||||
|
len = lens[work[sym]];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* create new sub-table if needed */
|
||||||
|
if (len > root && (huff & mask) != low) {
|
||||||
|
/* if first time, transition to sub-tables */
|
||||||
|
if (drop == 0)
|
||||||
|
drop = root;
|
||||||
|
|
||||||
|
/* increment past last table */
|
||||||
|
next += min; /* here min is 1 << curr */
|
||||||
|
|
||||||
|
/* determine length of next table */
|
||||||
|
curr = len - drop;
|
||||||
|
left = (int)(1 << curr);
|
||||||
|
while (curr + drop < max) {
|
||||||
|
left -= count[curr + drop];
|
||||||
|
if (left <= 0) break;
|
||||||
|
curr++;
|
||||||
|
left <<= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check for enough space */
|
||||||
|
used += 1U << curr;
|
||||||
|
if (type == LENS && used >= ENOUGH - MAXD)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
/* point entry in root table to sub-table */
|
||||||
|
low = huff & mask;
|
||||||
|
(*table)[low].op = (unsigned char)curr;
|
||||||
|
(*table)[low].bits = (unsigned char)root;
|
||||||
|
(*table)[low].val = (unsigned short)(next - *table);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Fill in rest of table for incomplete codes. This loop is similar to the
|
||||||
|
loop above in incrementing huff for table indices. It is assumed that
|
||||||
|
len is equal to curr + drop, so there is no loop needed to increment
|
||||||
|
through high index bits. When the current sub-table is filled, the loop
|
||||||
|
drops back to the root table to fill in any remaining entries there.
|
||||||
|
*/
|
||||||
|
this.op = (unsigned char)64; /* invalid code marker */
|
||||||
|
this.bits = (unsigned char)(len - drop);
|
||||||
|
this.val = (unsigned short)0;
|
||||||
|
while (huff != 0) {
|
||||||
|
/* when done with sub-table, drop back to root table */
|
||||||
|
if (drop != 0 && (huff & mask) != low) {
|
||||||
|
drop = 0;
|
||||||
|
len = root;
|
||||||
|
next = *table;
|
||||||
|
this.bits = (unsigned char)len;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* put invalid code marker in table */
|
||||||
|
next[huff >> drop] = this;
|
||||||
|
|
||||||
|
/* backwards increment the len-bit code huff */
|
||||||
|
incr = 1U << (len - 1);
|
||||||
|
while (huff & incr)
|
||||||
|
incr >>= 1;
|
||||||
|
if (incr != 0) {
|
||||||
|
huff &= incr - 1;
|
||||||
|
huff += incr;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
huff = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set return parameters */
|
||||||
|
*table += used;
|
||||||
|
*bits = root;
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
/* inftrees.h -- header to use inftrees.c
|
||||||
|
* Copyright (C) 1995-2005 Mark Adler
|
||||||
|
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* WARNING: this file should *not* be used by applications. It is
|
||||||
|
part of the implementation of the compression library and is
|
||||||
|
subject to change. Applications should only use zlib.h.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Structure for decoding tables. Each entry provides either the
|
||||||
|
information needed to do the operation requested by the code that
|
||||||
|
indexed that table entry, or it provides a pointer to another
|
||||||
|
table that indexes more bits of the code. op indicates whether
|
||||||
|
the entry is a pointer to another table, a literal, a length or
|
||||||
|
distance, an end-of-block, or an invalid code. For a table
|
||||||
|
pointer, the low four bits of op is the number of index bits of
|
||||||
|
that table. For a length or distance, the low four bits of op
|
||||||
|
is the number of extra bits to get after the code. bits is
|
||||||
|
the number of bits in this code or part of the code to drop off
|
||||||
|
of the bit buffer. val is the actual byte to output in the case
|
||||||
|
of a literal, the base length or distance, or the offset from
|
||||||
|
the current table to the next table. Each entry is four bytes. */
|
||||||
|
typedef struct {
|
||||||
|
unsigned char op; /* operation, extra bits, table bits */
|
||||||
|
unsigned char bits; /* bits in this part of the code */
|
||||||
|
unsigned short val; /* offset in table or code value */
|
||||||
|
} code;
|
||||||
|
|
||||||
|
/* op values as set by inflate_table():
|
||||||
|
00000000 - literal
|
||||||
|
0000tttt - table link, tttt != 0 is the number of table index bits
|
||||||
|
0001eeee - length or distance, eeee is the number of extra bits
|
||||||
|
01100000 - end of block
|
||||||
|
01000000 - invalid code
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Maximum size of dynamic tree. The maximum found in a long but non-
|
||||||
|
exhaustive search was 1444 code structures (852 for length/literals
|
||||||
|
and 592 for distances, the latter actually the result of an
|
||||||
|
exhaustive search). The true maximum is not known, but the value
|
||||||
|
below is more than safe. */
|
||||||
|
#define ENOUGH 2048
|
||||||
|
#define MAXD 592
|
||||||
|
|
||||||
|
/* Type of code to build for inftable() */
|
||||||
|
typedef enum {
|
||||||
|
CODES,
|
||||||
|
LENS,
|
||||||
|
DISTS
|
||||||
|
} codetype;
|
||||||
|
|
||||||
|
extern int inflate_table OF((codetype type, unsigned short FAR *lens,
|
||||||
|
unsigned codes, code FAR * FAR *table,
|
||||||
|
unsigned FAR *bits, unsigned short FAR *work));
|
|
@ -0,0 +1,128 @@
|
||||||
|
/* header created automatically with -DGEN_TREES_H */
|
||||||
|
|
||||||
|
local const ct_data static_ltree[L_CODES+2] = {
|
||||||
|
{{ 12},{ 8}}, {{140},{ 8}}, {{ 76},{ 8}}, {{204},{ 8}}, {{ 44},{ 8}},
|
||||||
|
{{172},{ 8}}, {{108},{ 8}}, {{236},{ 8}}, {{ 28},{ 8}}, {{156},{ 8}},
|
||||||
|
{{ 92},{ 8}}, {{220},{ 8}}, {{ 60},{ 8}}, {{188},{ 8}}, {{124},{ 8}},
|
||||||
|
{{252},{ 8}}, {{ 2},{ 8}}, {{130},{ 8}}, {{ 66},{ 8}}, {{194},{ 8}},
|
||||||
|
{{ 34},{ 8}}, {{162},{ 8}}, {{ 98},{ 8}}, {{226},{ 8}}, {{ 18},{ 8}},
|
||||||
|
{{146},{ 8}}, {{ 82},{ 8}}, {{210},{ 8}}, {{ 50},{ 8}}, {{178},{ 8}},
|
||||||
|
{{114},{ 8}}, {{242},{ 8}}, {{ 10},{ 8}}, {{138},{ 8}}, {{ 74},{ 8}},
|
||||||
|
{{202},{ 8}}, {{ 42},{ 8}}, {{170},{ 8}}, {{106},{ 8}}, {{234},{ 8}},
|
||||||
|
{{ 26},{ 8}}, {{154},{ 8}}, {{ 90},{ 8}}, {{218},{ 8}}, {{ 58},{ 8}},
|
||||||
|
{{186},{ 8}}, {{122},{ 8}}, {{250},{ 8}}, {{ 6},{ 8}}, {{134},{ 8}},
|
||||||
|
{{ 70},{ 8}}, {{198},{ 8}}, {{ 38},{ 8}}, {{166},{ 8}}, {{102},{ 8}},
|
||||||
|
{{230},{ 8}}, {{ 22},{ 8}}, {{150},{ 8}}, {{ 86},{ 8}}, {{214},{ 8}},
|
||||||
|
{{ 54},{ 8}}, {{182},{ 8}}, {{118},{ 8}}, {{246},{ 8}}, {{ 14},{ 8}},
|
||||||
|
{{142},{ 8}}, {{ 78},{ 8}}, {{206},{ 8}}, {{ 46},{ 8}}, {{174},{ 8}},
|
||||||
|
{{110},{ 8}}, {{238},{ 8}}, {{ 30},{ 8}}, {{158},{ 8}}, {{ 94},{ 8}},
|
||||||
|
{{222},{ 8}}, {{ 62},{ 8}}, {{190},{ 8}}, {{126},{ 8}}, {{254},{ 8}},
|
||||||
|
{{ 1},{ 8}}, {{129},{ 8}}, {{ 65},{ 8}}, {{193},{ 8}}, {{ 33},{ 8}},
|
||||||
|
{{161},{ 8}}, {{ 97},{ 8}}, {{225},{ 8}}, {{ 17},{ 8}}, {{145},{ 8}},
|
||||||
|
{{ 81},{ 8}}, {{209},{ 8}}, {{ 49},{ 8}}, {{177},{ 8}}, {{113},{ 8}},
|
||||||
|
{{241},{ 8}}, {{ 9},{ 8}}, {{137},{ 8}}, {{ 73},{ 8}}, {{201},{ 8}},
|
||||||
|
{{ 41},{ 8}}, {{169},{ 8}}, {{105},{ 8}}, {{233},{ 8}}, {{ 25},{ 8}},
|
||||||
|
{{153},{ 8}}, {{ 89},{ 8}}, {{217},{ 8}}, {{ 57},{ 8}}, {{185},{ 8}},
|
||||||
|
{{121},{ 8}}, {{249},{ 8}}, {{ 5},{ 8}}, {{133},{ 8}}, {{ 69},{ 8}},
|
||||||
|
{{197},{ 8}}, {{ 37},{ 8}}, {{165},{ 8}}, {{101},{ 8}}, {{229},{ 8}},
|
||||||
|
{{ 21},{ 8}}, {{149},{ 8}}, {{ 85},{ 8}}, {{213},{ 8}}, {{ 53},{ 8}},
|
||||||
|
{{181},{ 8}}, {{117},{ 8}}, {{245},{ 8}}, {{ 13},{ 8}}, {{141},{ 8}},
|
||||||
|
{{ 77},{ 8}}, {{205},{ 8}}, {{ 45},{ 8}}, {{173},{ 8}}, {{109},{ 8}},
|
||||||
|
{{237},{ 8}}, {{ 29},{ 8}}, {{157},{ 8}}, {{ 93},{ 8}}, {{221},{ 8}},
|
||||||
|
{{ 61},{ 8}}, {{189},{ 8}}, {{125},{ 8}}, {{253},{ 8}}, {{ 19},{ 9}},
|
||||||
|
{{275},{ 9}}, {{147},{ 9}}, {{403},{ 9}}, {{ 83},{ 9}}, {{339},{ 9}},
|
||||||
|
{{211},{ 9}}, {{467},{ 9}}, {{ 51},{ 9}}, {{307},{ 9}}, {{179},{ 9}},
|
||||||
|
{{435},{ 9}}, {{115},{ 9}}, {{371},{ 9}}, {{243},{ 9}}, {{499},{ 9}},
|
||||||
|
{{ 11},{ 9}}, {{267},{ 9}}, {{139},{ 9}}, {{395},{ 9}}, {{ 75},{ 9}},
|
||||||
|
{{331},{ 9}}, {{203},{ 9}}, {{459},{ 9}}, {{ 43},{ 9}}, {{299},{ 9}},
|
||||||
|
{{171},{ 9}}, {{427},{ 9}}, {{107},{ 9}}, {{363},{ 9}}, {{235},{ 9}},
|
||||||
|
{{491},{ 9}}, {{ 27},{ 9}}, {{283},{ 9}}, {{155},{ 9}}, {{411},{ 9}},
|
||||||
|
{{ 91},{ 9}}, {{347},{ 9}}, {{219},{ 9}}, {{475},{ 9}}, {{ 59},{ 9}},
|
||||||
|
{{315},{ 9}}, {{187},{ 9}}, {{443},{ 9}}, {{123},{ 9}}, {{379},{ 9}},
|
||||||
|
{{251},{ 9}}, {{507},{ 9}}, {{ 7},{ 9}}, {{263},{ 9}}, {{135},{ 9}},
|
||||||
|
{{391},{ 9}}, {{ 71},{ 9}}, {{327},{ 9}}, {{199},{ 9}}, {{455},{ 9}},
|
||||||
|
{{ 39},{ 9}}, {{295},{ 9}}, {{167},{ 9}}, {{423},{ 9}}, {{103},{ 9}},
|
||||||
|
{{359},{ 9}}, {{231},{ 9}}, {{487},{ 9}}, {{ 23},{ 9}}, {{279},{ 9}},
|
||||||
|
{{151},{ 9}}, {{407},{ 9}}, {{ 87},{ 9}}, {{343},{ 9}}, {{215},{ 9}},
|
||||||
|
{{471},{ 9}}, {{ 55},{ 9}}, {{311},{ 9}}, {{183},{ 9}}, {{439},{ 9}},
|
||||||
|
{{119},{ 9}}, {{375},{ 9}}, {{247},{ 9}}, {{503},{ 9}}, {{ 15},{ 9}},
|
||||||
|
{{271},{ 9}}, {{143},{ 9}}, {{399},{ 9}}, {{ 79},{ 9}}, {{335},{ 9}},
|
||||||
|
{{207},{ 9}}, {{463},{ 9}}, {{ 47},{ 9}}, {{303},{ 9}}, {{175},{ 9}},
|
||||||
|
{{431},{ 9}}, {{111},{ 9}}, {{367},{ 9}}, {{239},{ 9}}, {{495},{ 9}},
|
||||||
|
{{ 31},{ 9}}, {{287},{ 9}}, {{159},{ 9}}, {{415},{ 9}}, {{ 95},{ 9}},
|
||||||
|
{{351},{ 9}}, {{223},{ 9}}, {{479},{ 9}}, {{ 63},{ 9}}, {{319},{ 9}},
|
||||||
|
{{191},{ 9}}, {{447},{ 9}}, {{127},{ 9}}, {{383},{ 9}}, {{255},{ 9}},
|
||||||
|
{{511},{ 9}}, {{ 0},{ 7}}, {{ 64},{ 7}}, {{ 32},{ 7}}, {{ 96},{ 7}},
|
||||||
|
{{ 16},{ 7}}, {{ 80},{ 7}}, {{ 48},{ 7}}, {{112},{ 7}}, {{ 8},{ 7}},
|
||||||
|
{{ 72},{ 7}}, {{ 40},{ 7}}, {{104},{ 7}}, {{ 24},{ 7}}, {{ 88},{ 7}},
|
||||||
|
{{ 56},{ 7}}, {{120},{ 7}}, {{ 4},{ 7}}, {{ 68},{ 7}}, {{ 36},{ 7}},
|
||||||
|
{{100},{ 7}}, {{ 20},{ 7}}, {{ 84},{ 7}}, {{ 52},{ 7}}, {{116},{ 7}},
|
||||||
|
{{ 3},{ 8}}, {{131},{ 8}}, {{ 67},{ 8}}, {{195},{ 8}}, {{ 35},{ 8}},
|
||||||
|
{{163},{ 8}}, {{ 99},{ 8}}, {{227},{ 8}}
|
||||||
|
};
|
||||||
|
|
||||||
|
local const ct_data static_dtree[D_CODES] = {
|
||||||
|
{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}},
|
||||||
|
{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}},
|
||||||
|
{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}},
|
||||||
|
{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}},
|
||||||
|
{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}},
|
||||||
|
{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}}
|
||||||
|
};
|
||||||
|
|
||||||
|
const uch _dist_code[DIST_CODE_LEN] = {
|
||||||
|
0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8,
|
||||||
|
8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10,
|
||||||
|
10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
|
||||||
|
11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
|
||||||
|
12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13,
|
||||||
|
13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
|
||||||
|
13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
|
||||||
|
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
|
||||||
|
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
|
||||||
|
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15,
|
||||||
|
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
||||||
|
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
||||||
|
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17,
|
||||||
|
18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22,
|
||||||
|
23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
|
||||||
|
24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
|
||||||
|
26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
|
||||||
|
26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27,
|
||||||
|
27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
|
||||||
|
27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
|
||||||
|
28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
|
||||||
|
28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
|
||||||
|
28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
|
||||||
|
29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
|
||||||
|
29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
|
||||||
|
29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29
|
||||||
|
};
|
||||||
|
|
||||||
|
const uch _length_code[MAX_MATCH-MIN_MATCH+1]= {
|
||||||
|
0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12,
|
||||||
|
13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16,
|
||||||
|
17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19,
|
||||||
|
19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
|
||||||
|
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22,
|
||||||
|
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23,
|
||||||
|
23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
|
||||||
|
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
|
||||||
|
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
|
||||||
|
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26,
|
||||||
|
26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
|
||||||
|
26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
|
||||||
|
27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28
|
||||||
|
};
|
||||||
|
|
||||||
|
local const int base_length[LENGTH_CODES] = {
|
||||||
|
0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56,
|
||||||
|
64, 80, 96, 112, 128, 160, 192, 224, 0
|
||||||
|
};
|
||||||
|
|
||||||
|
local const int base_dist[D_CODES] = {
|
||||||
|
0, 1, 2, 3, 4, 6, 8, 12, 16, 24,
|
||||||
|
32, 48, 64, 96, 128, 192, 256, 384, 512, 768,
|
||||||
|
1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576
|
||||||
|
};
|
||||||
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
/* uncompr.c -- decompress a memory buffer
|
||||||
|
* Copyright (C) 1995-2003 Jean-loup Gailly.
|
||||||
|
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* @(#) $Id$ */
|
||||||
|
|
||||||
|
#define ZLIB_INTERNAL
|
||||||
|
#include "zlib.h"
|
||||||
|
|
||||||
|
/* ===========================================================================
|
||||||
|
Decompresses the source buffer into the destination buffer. sourceLen is
|
||||||
|
the byte length of the source buffer. Upon entry, destLen is the total
|
||||||
|
size of the destination buffer, which must be large enough to hold the
|
||||||
|
entire uncompressed data. (The size of the uncompressed data must have
|
||||||
|
been saved previously by the compressor and transmitted to the decompressor
|
||||||
|
by some mechanism outside the scope of this compression library.)
|
||||||
|
Upon exit, destLen is the actual size of the compressed buffer.
|
||||||
|
This function can be used to decompress a whole file at once if the
|
||||||
|
input file is mmap'ed.
|
||||||
|
|
||||||
|
uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
|
||||||
|
enough memory, Z_BUF_ERROR if there was not enough room in the output
|
||||||
|
buffer, or Z_DATA_ERROR if the input data was corrupted.
|
||||||
|
*/
|
||||||
|
int ZEXPORT uncompress (dest, destLen, source, sourceLen)
|
||||||
|
Bytef *dest;
|
||||||
|
uLongf *destLen;
|
||||||
|
const Bytef *source;
|
||||||
|
uLong sourceLen;
|
||||||
|
{
|
||||||
|
z_stream stream;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
stream.next_in = (Bytef*)source;
|
||||||
|
stream.avail_in = (uInt)sourceLen;
|
||||||
|
/* Check for source > 64K on 16-bit machine: */
|
||||||
|
if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR;
|
||||||
|
|
||||||
|
stream.next_out = dest;
|
||||||
|
stream.avail_out = (uInt)*destLen;
|
||||||
|
if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;
|
||||||
|
|
||||||
|
stream.zalloc = (alloc_func)0;
|
||||||
|
stream.zfree = (free_func)0;
|
||||||
|
|
||||||
|
err = inflateInit(&stream);
|
||||||
|
if (err != Z_OK) return err;
|
||||||
|
|
||||||
|
err = inflate(&stream, Z_FINISH);
|
||||||
|
if (err != Z_STREAM_END) {
|
||||||
|
inflateEnd(&stream);
|
||||||
|
if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0))
|
||||||
|
return Z_DATA_ERROR;
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
*destLen = stream.total_out;
|
||||||
|
|
||||||
|
err = inflateEnd(&stream);
|
||||||
|
return err;
|
||||||
|
}
|
|
@ -0,0 +1,332 @@
|
||||||
|
/* zconf.h -- configuration of the zlib compression library
|
||||||
|
* Copyright (C) 1995-2005 Jean-loup Gailly.
|
||||||
|
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* @(#) $Id$ */
|
||||||
|
|
||||||
|
#ifndef ZCONF_H
|
||||||
|
#define ZCONF_H
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If you *really* need a unique prefix for all types and library functions,
|
||||||
|
* compile with -DZ_PREFIX. The "standard" zlib should be compiled without it.
|
||||||
|
*/
|
||||||
|
#ifdef Z_PREFIX
|
||||||
|
# define deflateInit_ z_deflateInit_
|
||||||
|
# define deflate z_deflate
|
||||||
|
# define deflateEnd z_deflateEnd
|
||||||
|
# define inflateInit_ z_inflateInit_
|
||||||
|
# define inflate z_inflate
|
||||||
|
# define inflateEnd z_inflateEnd
|
||||||
|
# define deflateInit2_ z_deflateInit2_
|
||||||
|
# define deflateSetDictionary z_deflateSetDictionary
|
||||||
|
# define deflateCopy z_deflateCopy
|
||||||
|
# define deflateReset z_deflateReset
|
||||||
|
# define deflateParams z_deflateParams
|
||||||
|
# define deflateBound z_deflateBound
|
||||||
|
# define deflatePrime z_deflatePrime
|
||||||
|
# define inflateInit2_ z_inflateInit2_
|
||||||
|
# define inflateSetDictionary z_inflateSetDictionary
|
||||||
|
# define inflateSync z_inflateSync
|
||||||
|
# define inflateSyncPoint z_inflateSyncPoint
|
||||||
|
# define inflateCopy z_inflateCopy
|
||||||
|
# define inflateReset z_inflateReset
|
||||||
|
# define inflateBack z_inflateBack
|
||||||
|
# define inflateBackEnd z_inflateBackEnd
|
||||||
|
# define compress z_compress
|
||||||
|
# define compress2 z_compress2
|
||||||
|
# define compressBound z_compressBound
|
||||||
|
# define uncompress z_uncompress
|
||||||
|
# define adler32 z_adler32
|
||||||
|
# define crc32 z_crc32
|
||||||
|
# define get_crc_table z_get_crc_table
|
||||||
|
# define zError z_zError
|
||||||
|
|
||||||
|
# define alloc_func z_alloc_func
|
||||||
|
# define free_func z_free_func
|
||||||
|
# define in_func z_in_func
|
||||||
|
# define out_func z_out_func
|
||||||
|
# define Byte z_Byte
|
||||||
|
# define uInt z_uInt
|
||||||
|
# define uLong z_uLong
|
||||||
|
# define Bytef z_Bytef
|
||||||
|
# define charf z_charf
|
||||||
|
# define intf z_intf
|
||||||
|
# define uIntf z_uIntf
|
||||||
|
# define uLongf z_uLongf
|
||||||
|
# define voidpf z_voidpf
|
||||||
|
# define voidp z_voidp
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__MSDOS__) && !defined(MSDOS)
|
||||||
|
# define MSDOS
|
||||||
|
#endif
|
||||||
|
#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2)
|
||||||
|
# define OS2
|
||||||
|
#endif
|
||||||
|
#if defined(_WINDOWS) && !defined(WINDOWS)
|
||||||
|
# define WINDOWS
|
||||||
|
#endif
|
||||||
|
#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__)
|
||||||
|
# ifndef WIN32
|
||||||
|
# define WIN32
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32)
|
||||||
|
# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__)
|
||||||
|
# ifndef SYS16BIT
|
||||||
|
# define SYS16BIT
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Compile with -DMAXSEG_64K if the alloc function cannot allocate more
|
||||||
|
* than 64k bytes at a time (needed on systems with 16-bit int).
|
||||||
|
*/
|
||||||
|
#ifdef SYS16BIT
|
||||||
|
# define MAXSEG_64K
|
||||||
|
#endif
|
||||||
|
#ifdef MSDOS
|
||||||
|
# define UNALIGNED_OK
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __STDC_VERSION__
|
||||||
|
# ifndef STDC
|
||||||
|
# define STDC
|
||||||
|
# endif
|
||||||
|
# if __STDC_VERSION__ >= 199901L
|
||||||
|
# ifndef STDC99
|
||||||
|
# define STDC99
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus))
|
||||||
|
# define STDC
|
||||||
|
#endif
|
||||||
|
#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__))
|
||||||
|
# define STDC
|
||||||
|
#endif
|
||||||
|
#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32))
|
||||||
|
# define STDC
|
||||||
|
#endif
|
||||||
|
#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__))
|
||||||
|
# define STDC
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */
|
||||||
|
# define STDC
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef STDC
|
||||||
|
# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */
|
||||||
|
# define const /* note: need a more gentle solution here */
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Some Mac compilers merge all .h files incorrectly: */
|
||||||
|
#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__)
|
||||||
|
# define NO_DUMMY_DECL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Maximum value for memLevel in deflateInit2 */
|
||||||
|
#ifndef MAX_MEM_LEVEL
|
||||||
|
# ifdef MAXSEG_64K
|
||||||
|
# define MAX_MEM_LEVEL 8
|
||||||
|
# else
|
||||||
|
# define MAX_MEM_LEVEL 9
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Maximum value for windowBits in deflateInit2 and inflateInit2.
|
||||||
|
* WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
|
||||||
|
* created by gzip. (Files created by minigzip can still be extracted by
|
||||||
|
* gzip.)
|
||||||
|
*/
|
||||||
|
#ifndef MAX_WBITS
|
||||||
|
# define MAX_WBITS 15 /* 32K LZ77 window */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* The memory requirements for deflate are (in bytes):
|
||||||
|
(1 << (windowBits+2)) + (1 << (memLevel+9))
|
||||||
|
that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values)
|
||||||
|
plus a few kilobytes for small objects. For example, if you want to reduce
|
||||||
|
the default memory requirements from 256K to 128K, compile with
|
||||||
|
make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
|
||||||
|
Of course this will generally degrade compression (there's no free lunch).
|
||||||
|
|
||||||
|
The memory requirements for inflate are (in bytes) 1 << windowBits
|
||||||
|
that is, 32K for windowBits=15 (default value) plus a few kilobytes
|
||||||
|
for small objects.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Type declarations */
|
||||||
|
|
||||||
|
#ifndef OF /* function prototypes */
|
||||||
|
# ifdef STDC
|
||||||
|
# define OF(args) args
|
||||||
|
# else
|
||||||
|
# define OF(args) ()
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* The following definitions for FAR are needed only for MSDOS mixed
|
||||||
|
* model programming (small or medium model with some far allocations).
|
||||||
|
* This was tested only with MSC; for other MSDOS compilers you may have
|
||||||
|
* to define NO_MEMCPY in zutil.h. If you don't need the mixed model,
|
||||||
|
* just define FAR to be empty.
|
||||||
|
*/
|
||||||
|
#ifdef SYS16BIT
|
||||||
|
# if defined(M_I86SM) || defined(M_I86MM)
|
||||||
|
/* MSC small or medium model */
|
||||||
|
# define SMALL_MEDIUM
|
||||||
|
# ifdef _MSC_VER
|
||||||
|
# define FAR _far
|
||||||
|
# else
|
||||||
|
# define FAR far
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
# if (defined(__SMALL__) || defined(__MEDIUM__))
|
||||||
|
/* Turbo C small or medium model */
|
||||||
|
# define SMALL_MEDIUM
|
||||||
|
# ifdef __BORLANDC__
|
||||||
|
# define FAR _far
|
||||||
|
# else
|
||||||
|
# define FAR far
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(WINDOWS) || defined(WIN32)
|
||||||
|
/* If building or using zlib as a DLL, define ZLIB_DLL.
|
||||||
|
* This is not mandatory, but it offers a little performance increase.
|
||||||
|
*/
|
||||||
|
# ifdef ZLIB_DLL
|
||||||
|
# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500))
|
||||||
|
# ifdef ZLIB_INTERNAL
|
||||||
|
# define ZEXTERN extern __declspec(dllexport)
|
||||||
|
# else
|
||||||
|
# define ZEXTERN extern __declspec(dllimport)
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
# endif /* ZLIB_DLL */
|
||||||
|
/* If building or using zlib with the WINAPI/WINAPIV calling convention,
|
||||||
|
* define ZLIB_WINAPI.
|
||||||
|
* Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI.
|
||||||
|
*/
|
||||||
|
# ifdef ZLIB_WINAPI
|
||||||
|
# ifdef FAR
|
||||||
|
# undef FAR
|
||||||
|
# endif
|
||||||
|
# include <windows.h>
|
||||||
|
/* No need for _export, use ZLIB.DEF instead. */
|
||||||
|
/* For complete Windows compatibility, use WINAPI, not __stdcall. */
|
||||||
|
# define ZEXPORT WINAPI
|
||||||
|
# ifdef WIN32
|
||||||
|
# define ZEXPORTVA WINAPIV
|
||||||
|
# else
|
||||||
|
# define ZEXPORTVA FAR CDECL
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined (__BEOS__)
|
||||||
|
# ifdef ZLIB_DLL
|
||||||
|
# ifdef ZLIB_INTERNAL
|
||||||
|
# define ZEXPORT __declspec(dllexport)
|
||||||
|
# define ZEXPORTVA __declspec(dllexport)
|
||||||
|
# else
|
||||||
|
# define ZEXPORT __declspec(dllimport)
|
||||||
|
# define ZEXPORTVA __declspec(dllimport)
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef ZEXTERN
|
||||||
|
# define ZEXTERN extern
|
||||||
|
#endif
|
||||||
|
#ifndef ZEXPORT
|
||||||
|
# define ZEXPORT
|
||||||
|
#endif
|
||||||
|
#ifndef ZEXPORTVA
|
||||||
|
# define ZEXPORTVA
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef FAR
|
||||||
|
# define FAR
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(__MACTYPES__)
|
||||||
|
typedef unsigned char Byte; /* 8 bits */
|
||||||
|
#endif
|
||||||
|
typedef unsigned int uInt; /* 16 bits or more */
|
||||||
|
typedef unsigned long uLong; /* 32 bits or more */
|
||||||
|
|
||||||
|
#ifdef SMALL_MEDIUM
|
||||||
|
/* Borland C/C++ and some old MSC versions ignore FAR inside typedef */
|
||||||
|
# define Bytef Byte FAR
|
||||||
|
#else
|
||||||
|
typedef Byte FAR Bytef;
|
||||||
|
#endif
|
||||||
|
typedef char FAR charf;
|
||||||
|
typedef int FAR intf;
|
||||||
|
typedef uInt FAR uIntf;
|
||||||
|
typedef uLong FAR uLongf;
|
||||||
|
|
||||||
|
#ifdef STDC
|
||||||
|
typedef void const *voidpc;
|
||||||
|
typedef void FAR *voidpf;
|
||||||
|
typedef void *voidp;
|
||||||
|
#else
|
||||||
|
typedef Byte const *voidpc;
|
||||||
|
typedef Byte FAR *voidpf;
|
||||||
|
typedef Byte *voidp;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 0 /* HAVE_UNISTD_H -- this line is updated by ./configure */
|
||||||
|
# include <sys/types.h> /* for off_t */
|
||||||
|
# include <unistd.h> /* for SEEK_* and off_t */
|
||||||
|
# ifdef VMS
|
||||||
|
# include <unixio.h> /* for off_t */
|
||||||
|
# endif
|
||||||
|
# define z_off_t off_t
|
||||||
|
#endif
|
||||||
|
#ifndef SEEK_SET
|
||||||
|
# define SEEK_SET 0 /* Seek from beginning of file. */
|
||||||
|
# define SEEK_CUR 1 /* Seek from current position. */
|
||||||
|
# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */
|
||||||
|
#endif
|
||||||
|
#ifndef z_off_t
|
||||||
|
# define z_off_t long
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__OS400__)
|
||||||
|
# define NO_vsnprintf
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__MVS__)
|
||||||
|
# define NO_vsnprintf
|
||||||
|
# ifdef FAR
|
||||||
|
# undef FAR
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* MVS linker does not support external names larger than 8 bytes */
|
||||||
|
#if defined(__MVS__)
|
||||||
|
# pragma map(deflateInit_,"DEIN")
|
||||||
|
# pragma map(deflateInit2_,"DEIN2")
|
||||||
|
# pragma map(deflateEnd,"DEEND")
|
||||||
|
# pragma map(deflateBound,"DEBND")
|
||||||
|
# pragma map(inflateInit_,"ININ")
|
||||||
|
# pragma map(inflateInit2_,"ININ2")
|
||||||
|
# pragma map(inflateEnd,"INEND")
|
||||||
|
# pragma map(inflateSync,"INSY")
|
||||||
|
# pragma map(inflateSetDictionary,"INSEDI")
|
||||||
|
# pragma map(compressBound,"CMBND")
|
||||||
|
# pragma map(inflate_table,"INTABL")
|
||||||
|
# pragma map(inflate_fast,"INFA")
|
||||||
|
# pragma map(inflate_copyright,"INCOPY")
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* ZCONF_H */
|
|
@ -0,0 +1,318 @@
|
||||||
|
/* zutil.c -- target dependent utility functions for the compression library
|
||||||
|
* Copyright (C) 1995-2005 Jean-loup Gailly.
|
||||||
|
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* @(#) $Id$ */
|
||||||
|
|
||||||
|
#include "zutil.h"
|
||||||
|
|
||||||
|
#ifndef NO_DUMMY_DECL
|
||||||
|
struct internal_state {int dummy;}; /* for buggy compilers */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
const char * const z_errmsg[10] = {
|
||||||
|
"need dictionary", /* Z_NEED_DICT 2 */
|
||||||
|
"stream end", /* Z_STREAM_END 1 */
|
||||||
|
"", /* Z_OK 0 */
|
||||||
|
"file error", /* Z_ERRNO (-1) */
|
||||||
|
"stream error", /* Z_STREAM_ERROR (-2) */
|
||||||
|
"data error", /* Z_DATA_ERROR (-3) */
|
||||||
|
"insufficient memory", /* Z_MEM_ERROR (-4) */
|
||||||
|
"buffer error", /* Z_BUF_ERROR (-5) */
|
||||||
|
"incompatible version",/* Z_VERSION_ERROR (-6) */
|
||||||
|
""};
|
||||||
|
|
||||||
|
|
||||||
|
const char * ZEXPORT zlibVersion()
|
||||||
|
{
|
||||||
|
return ZLIB_VERSION;
|
||||||
|
}
|
||||||
|
|
||||||
|
uLong ZEXPORT zlibCompileFlags()
|
||||||
|
{
|
||||||
|
uLong flags;
|
||||||
|
|
||||||
|
flags = 0;
|
||||||
|
switch (sizeof(uInt)) {
|
||||||
|
case 2: break;
|
||||||
|
case 4: flags += 1; break;
|
||||||
|
case 8: flags += 2; break;
|
||||||
|
default: flags += 3;
|
||||||
|
}
|
||||||
|
switch (sizeof(uLong)) {
|
||||||
|
case 2: break;
|
||||||
|
case 4: flags += 1 << 2; break;
|
||||||
|
case 8: flags += 2 << 2; break;
|
||||||
|
default: flags += 3 << 2;
|
||||||
|
}
|
||||||
|
switch (sizeof(voidpf)) {
|
||||||
|
case 2: break;
|
||||||
|
case 4: flags += 1 << 4; break;
|
||||||
|
case 8: flags += 2 << 4; break;
|
||||||
|
default: flags += 3 << 4;
|
||||||
|
}
|
||||||
|
switch (sizeof(z_off_t)) {
|
||||||
|
case 2: break;
|
||||||
|
case 4: flags += 1 << 6; break;
|
||||||
|
case 8: flags += 2 << 6; break;
|
||||||
|
default: flags += 3 << 6;
|
||||||
|
}
|
||||||
|
#ifdef DEBUG
|
||||||
|
flags += 1 << 8;
|
||||||
|
#endif
|
||||||
|
#if defined(ASMV) || defined(ASMINF)
|
||||||
|
flags += 1 << 9;
|
||||||
|
#endif
|
||||||
|
#ifdef ZLIB_WINAPI
|
||||||
|
flags += 1 << 10;
|
||||||
|
#endif
|
||||||
|
#ifdef BUILDFIXED
|
||||||
|
flags += 1 << 12;
|
||||||
|
#endif
|
||||||
|
#ifdef DYNAMIC_CRC_TABLE
|
||||||
|
flags += 1 << 13;
|
||||||
|
#endif
|
||||||
|
#ifdef NO_GZCOMPRESS
|
||||||
|
flags += 1L << 16;
|
||||||
|
#endif
|
||||||
|
#ifdef NO_GZIP
|
||||||
|
flags += 1L << 17;
|
||||||
|
#endif
|
||||||
|
#ifdef PKZIP_BUG_WORKAROUND
|
||||||
|
flags += 1L << 20;
|
||||||
|
#endif
|
||||||
|
#ifdef FASTEST
|
||||||
|
flags += 1L << 21;
|
||||||
|
#endif
|
||||||
|
#ifdef STDC
|
||||||
|
# ifdef NO_vsnprintf
|
||||||
|
flags += 1L << 25;
|
||||||
|
# ifdef HAS_vsprintf_void
|
||||||
|
flags += 1L << 26;
|
||||||
|
# endif
|
||||||
|
# else
|
||||||
|
# ifdef HAS_vsnprintf_void
|
||||||
|
flags += 1L << 26;
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
#else
|
||||||
|
flags += 1L << 24;
|
||||||
|
# ifdef NO_snprintf
|
||||||
|
flags += 1L << 25;
|
||||||
|
# ifdef HAS_sprintf_void
|
||||||
|
flags += 1L << 26;
|
||||||
|
# endif
|
||||||
|
# else
|
||||||
|
# ifdef HAS_snprintf_void
|
||||||
|
flags += 1L << 26;
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
return flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
|
||||||
|
# ifndef verbose
|
||||||
|
# define verbose 0
|
||||||
|
# endif
|
||||||
|
int z_verbose = verbose;
|
||||||
|
|
||||||
|
void z_error (m)
|
||||||
|
char *m;
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%s\n", m);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* exported to allow conversion of error code to string for compress() and
|
||||||
|
* uncompress()
|
||||||
|
*/
|
||||||
|
const char * ZEXPORT zError(err)
|
||||||
|
int err;
|
||||||
|
{
|
||||||
|
return ERR_MSG(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(_WIN32_WCE)
|
||||||
|
/* The Microsoft C Run-Time Library for Windows CE doesn't have
|
||||||
|
* errno. We define it as a global variable to simplify porting.
|
||||||
|
* Its value is always 0 and should not be used.
|
||||||
|
*/
|
||||||
|
int errno = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef HAVE_MEMCPY
|
||||||
|
|
||||||
|
void zmemcpy(dest, source, len)
|
||||||
|
Bytef* dest;
|
||||||
|
const Bytef* source;
|
||||||
|
uInt len;
|
||||||
|
{
|
||||||
|
if (len == 0) return;
|
||||||
|
do {
|
||||||
|
*dest++ = *source++; /* ??? to be unrolled */
|
||||||
|
} while (--len != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int zmemcmp(s1, s2, len)
|
||||||
|
const Bytef* s1;
|
||||||
|
const Bytef* s2;
|
||||||
|
uInt len;
|
||||||
|
{
|
||||||
|
uInt j;
|
||||||
|
|
||||||
|
for (j = 0; j < len; j++) {
|
||||||
|
if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void zmemzero(dest, len)
|
||||||
|
Bytef* dest;
|
||||||
|
uInt len;
|
||||||
|
{
|
||||||
|
if (len == 0) return;
|
||||||
|
do {
|
||||||
|
*dest++ = 0; /* ??? to be unrolled */
|
||||||
|
} while (--len != 0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef SYS16BIT
|
||||||
|
|
||||||
|
#ifdef __TURBOC__
|
||||||
|
/* Turbo C in 16-bit mode */
|
||||||
|
|
||||||
|
# define MY_ZCALLOC
|
||||||
|
|
||||||
|
/* Turbo C malloc() does not allow dynamic allocation of 64K bytes
|
||||||
|
* and farmalloc(64K) returns a pointer with an offset of 8, so we
|
||||||
|
* must fix the pointer. Warning: the pointer must be put back to its
|
||||||
|
* original form in order to free it, use zcfree().
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define MAX_PTR 10
|
||||||
|
/* 10*64K = 640K */
|
||||||
|
|
||||||
|
local int next_ptr = 0;
|
||||||
|
|
||||||
|
typedef struct ptr_table_s {
|
||||||
|
voidpf org_ptr;
|
||||||
|
voidpf new_ptr;
|
||||||
|
} ptr_table;
|
||||||
|
|
||||||
|
local ptr_table table[MAX_PTR];
|
||||||
|
/* This table is used to remember the original form of pointers
|
||||||
|
* to large buffers (64K). Such pointers are normalized with a zero offset.
|
||||||
|
* Since MSDOS is not a preemptive multitasking OS, this table is not
|
||||||
|
* protected from concurrent access. This hack doesn't work anyway on
|
||||||
|
* a protected system like OS/2. Use Microsoft C instead.
|
||||||
|
*/
|
||||||
|
|
||||||
|
voidpf zcalloc (voidpf opaque, unsigned items, unsigned size)
|
||||||
|
{
|
||||||
|
voidpf buf = opaque; /* just to make some compilers happy */
|
||||||
|
ulg bsize = (ulg)items*size;
|
||||||
|
|
||||||
|
/* If we allocate less than 65520 bytes, we assume that farmalloc
|
||||||
|
* will return a usable pointer which doesn't have to be normalized.
|
||||||
|
*/
|
||||||
|
if (bsize < 65520L) {
|
||||||
|
buf = farmalloc(bsize);
|
||||||
|
if (*(ush*)&buf != 0) return buf;
|
||||||
|
} else {
|
||||||
|
buf = farmalloc(bsize + 16L);
|
||||||
|
}
|
||||||
|
if (buf == NULL || next_ptr >= MAX_PTR) return NULL;
|
||||||
|
table[next_ptr].org_ptr = buf;
|
||||||
|
|
||||||
|
/* Normalize the pointer to seg:0 */
|
||||||
|
*((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4;
|
||||||
|
*(ush*)&buf = 0;
|
||||||
|
table[next_ptr++].new_ptr = buf;
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
void zcfree (voidpf opaque, voidpf ptr)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
if (*(ush*)&ptr != 0) { /* object < 64K */
|
||||||
|
farfree(ptr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* Find the original pointer */
|
||||||
|
for (n = 0; n < next_ptr; n++) {
|
||||||
|
if (ptr != table[n].new_ptr) continue;
|
||||||
|
|
||||||
|
farfree(table[n].org_ptr);
|
||||||
|
while (++n < next_ptr) {
|
||||||
|
table[n-1] = table[n];
|
||||||
|
}
|
||||||
|
next_ptr--;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ptr = opaque; /* just to make some compilers happy */
|
||||||
|
Assert(0, "zcfree: ptr not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* __TURBOC__ */
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef M_I86
|
||||||
|
/* Microsoft C in 16-bit mode */
|
||||||
|
|
||||||
|
# define MY_ZCALLOC
|
||||||
|
|
||||||
|
#if (!defined(_MSC_VER) || (_MSC_VER <= 600))
|
||||||
|
# define _halloc halloc
|
||||||
|
# define _hfree hfree
|
||||||
|
#endif
|
||||||
|
|
||||||
|
voidpf zcalloc (voidpf opaque, unsigned items, unsigned size)
|
||||||
|
{
|
||||||
|
if (opaque) opaque = 0; /* to make compiler happy */
|
||||||
|
return _halloc((long)items, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void zcfree (voidpf opaque, voidpf ptr)
|
||||||
|
{
|
||||||
|
if (opaque) opaque = 0; /* to make compiler happy */
|
||||||
|
_hfree(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* M_I86 */
|
||||||
|
|
||||||
|
#endif /* SYS16BIT */
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef MY_ZCALLOC /* Any system without a special alloc function */
|
||||||
|
|
||||||
|
#ifndef STDC
|
||||||
|
extern voidp malloc OF((uInt size));
|
||||||
|
extern voidp calloc OF((uInt items, uInt size));
|
||||||
|
extern void free OF((voidpf ptr));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
voidpf zcalloc (opaque, items, size)
|
||||||
|
voidpf opaque;
|
||||||
|
unsigned items;
|
||||||
|
unsigned size;
|
||||||
|
{
|
||||||
|
if (opaque) items += size - size; /* make compiler happy */
|
||||||
|
return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) :
|
||||||
|
(voidpf)calloc(items, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void zcfree (opaque, ptr)
|
||||||
|
voidpf opaque;
|
||||||
|
voidpf ptr;
|
||||||
|
{
|
||||||
|
free(ptr);
|
||||||
|
if (opaque) return; /* make compiler happy */
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* MY_ZCALLOC */
|
|
@ -0,0 +1,269 @@
|
||||||
|
/* zutil.h -- internal interface and configuration of the compression library
|
||||||
|
* Copyright (C) 1995-2005 Jean-loup Gailly.
|
||||||
|
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* WARNING: this file should *not* be used by applications. It is
|
||||||
|
part of the implementation of the compression library and is
|
||||||
|
subject to change. Applications should only use zlib.h.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* @(#) $Id$ */
|
||||||
|
|
||||||
|
#ifndef ZUTIL_H
|
||||||
|
#define ZUTIL_H
|
||||||
|
|
||||||
|
#define ZLIB_INTERNAL
|
||||||
|
#include "zlib.h"
|
||||||
|
|
||||||
|
#ifdef STDC
|
||||||
|
# ifndef _WIN32_WCE
|
||||||
|
# include <stddef.h>
|
||||||
|
# endif
|
||||||
|
# include <string.h>
|
||||||
|
# include <stdlib.h>
|
||||||
|
#endif
|
||||||
|
#ifdef NO_ERRNO_H
|
||||||
|
# ifdef _WIN32_WCE
|
||||||
|
/* The Microsoft C Run-Time Library for Windows CE doesn't have
|
||||||
|
* errno. We define it as a global variable to simplify porting.
|
||||||
|
* Its value is always 0 and should not be used. We rename it to
|
||||||
|
* avoid conflict with other libraries that use the same workaround.
|
||||||
|
*/
|
||||||
|
# define errno z_errno
|
||||||
|
# endif
|
||||||
|
extern int errno;
|
||||||
|
#else
|
||||||
|
# ifndef _WIN32_WCE
|
||||||
|
# include <errno.h>
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef local
|
||||||
|
# define local static
|
||||||
|
#endif
|
||||||
|
/* compile with -Dlocal if your debugger can't find static symbols */
|
||||||
|
|
||||||
|
typedef unsigned char uch;
|
||||||
|
typedef uch FAR uchf;
|
||||||
|
typedef unsigned short ush;
|
||||||
|
typedef ush FAR ushf;
|
||||||
|
typedef unsigned long ulg;
|
||||||
|
|
||||||
|
extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
|
||||||
|
/* (size given to avoid silly warnings with Visual C++) */
|
||||||
|
|
||||||
|
#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)]
|
||||||
|
|
||||||
|
#define ERR_RETURN(strm,err) \
|
||||||
|
return (strm->msg = (char*)ERR_MSG(err), (err))
|
||||||
|
/* To be used only when the state is known to be valid */
|
||||||
|
|
||||||
|
/* common constants */
|
||||||
|
|
||||||
|
#ifndef DEF_WBITS
|
||||||
|
# define DEF_WBITS MAX_WBITS
|
||||||
|
#endif
|
||||||
|
/* default windowBits for decompression. MAX_WBITS is for compression only */
|
||||||
|
|
||||||
|
#if MAX_MEM_LEVEL >= 8
|
||||||
|
# define DEF_MEM_LEVEL 9
|
||||||
|
#else
|
||||||
|
# define DEF_MEM_LEVEL MAX_MEM_LEVEL
|
||||||
|
#endif
|
||||||
|
/* default memLevel */
|
||||||
|
|
||||||
|
#define STORED_BLOCK 0
|
||||||
|
#define STATIC_TREES 1
|
||||||
|
#define DYN_TREES 2
|
||||||
|
/* The three kinds of block type */
|
||||||
|
|
||||||
|
#define MIN_MATCH 3
|
||||||
|
#define MAX_MATCH 258
|
||||||
|
/* The minimum and maximum match lengths */
|
||||||
|
|
||||||
|
#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */
|
||||||
|
|
||||||
|
/* target dependencies */
|
||||||
|
|
||||||
|
#if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32))
|
||||||
|
# define OS_CODE 0x00
|
||||||
|
# if defined(__TURBOC__) || defined(__BORLANDC__)
|
||||||
|
# if(__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__))
|
||||||
|
/* Allow compilation with ANSI keywords only enabled */
|
||||||
|
void _Cdecl farfree( void *block );
|
||||||
|
void *_Cdecl farmalloc( unsigned long nbytes );
|
||||||
|
# else
|
||||||
|
# include <alloc.h>
|
||||||
|
# endif
|
||||||
|
# else /* MSC or DJGPP */
|
||||||
|
# include <malloc.h>
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef AMIGA
|
||||||
|
# define OS_CODE 0x01
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(VAXC) || defined(VMS)
|
||||||
|
# define OS_CODE 0x02
|
||||||
|
# define F_OPEN(name, mode) \
|
||||||
|
fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512")
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(ATARI) || defined(atarist)
|
||||||
|
# define OS_CODE 0x05
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef OS2
|
||||||
|
# define OS_CODE 0x06
|
||||||
|
# ifdef M_I86
|
||||||
|
#include <malloc.h>
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(MACOS) || defined(TARGET_OS_MAC)
|
||||||
|
# define OS_CODE 0x07
|
||||||
|
# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os
|
||||||
|
# include <unix.h> /* for fdopen */
|
||||||
|
# else
|
||||||
|
# ifndef fdopen
|
||||||
|
# define fdopen(fd,mode) NULL /* No fdopen() */
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef TOPS20
|
||||||
|
# define OS_CODE 0x0a
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
# ifndef __CYGWIN__ /* Cygwin is Unix, not Win32 */
|
||||||
|
# define OS_CODE 0x0b
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __50SERIES /* Prime/PRIMOS */
|
||||||
|
# define OS_CODE 0x0f
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(_BEOS_) || defined(RISCOS)
|
||||||
|
# define fdopen(fd,mode) NULL /* No fdopen() */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (defined(_MSC_VER) && (_MSC_VER > 600))
|
||||||
|
# if defined(_WIN32_WCE)
|
||||||
|
# define fdopen(fd,mode) NULL /* No fdopen() */
|
||||||
|
# ifndef _PTRDIFF_T_DEFINED
|
||||||
|
typedef int ptrdiff_t;
|
||||||
|
# define _PTRDIFF_T_DEFINED
|
||||||
|
# endif
|
||||||
|
# else
|
||||||
|
# define fdopen(fd,type) _fdopen(fd,type)
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* common defaults */
|
||||||
|
|
||||||
|
#ifndef OS_CODE
|
||||||
|
# define OS_CODE 0x03 /* assume Unix */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef F_OPEN
|
||||||
|
# define F_OPEN(name, mode) fopen((name), (mode))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* functions */
|
||||||
|
|
||||||
|
#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550)
|
||||||
|
# ifndef HAVE_VSNPRINTF
|
||||||
|
# define HAVE_VSNPRINTF
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
#if defined(__CYGWIN__)
|
||||||
|
# ifndef HAVE_VSNPRINTF
|
||||||
|
# define HAVE_VSNPRINTF
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
#ifndef HAVE_VSNPRINTF
|
||||||
|
# ifdef MSDOS
|
||||||
|
/* vsnprintf may exist on some MS-DOS compilers (DJGPP?),
|
||||||
|
but for now we just assume it doesn't. */
|
||||||
|
# define NO_vsnprintf
|
||||||
|
# endif
|
||||||
|
# ifdef __TURBOC__
|
||||||
|
# define NO_vsnprintf
|
||||||
|
# endif
|
||||||
|
# ifdef WIN32
|
||||||
|
/* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */
|
||||||
|
# if !defined(vsnprintf) && !defined(NO_vsnprintf)
|
||||||
|
# define vsnprintf _vsnprintf
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
# ifdef __SASC
|
||||||
|
# define NO_vsnprintf
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
#ifdef VMS
|
||||||
|
# define NO_vsnprintf
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(pyr)
|
||||||
|
# define NO_MEMCPY
|
||||||
|
#endif
|
||||||
|
#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__)
|
||||||
|
/* Use our own functions for small and medium model with MSC <= 5.0.
|
||||||
|
* You may have to use the same strategy for Borland C (untested).
|
||||||
|
* The __SC__ check is for Symantec.
|
||||||
|
*/
|
||||||
|
# define NO_MEMCPY
|
||||||
|
#endif
|
||||||
|
#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY)
|
||||||
|
# define HAVE_MEMCPY
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_MEMCPY
|
||||||
|
# ifdef SMALL_MEDIUM /* MSDOS small or medium model */
|
||||||
|
# define zmemcpy _fmemcpy
|
||||||
|
# define zmemcmp _fmemcmp
|
||||||
|
# define zmemzero(dest, len) _fmemset(dest, 0, len)
|
||||||
|
# else
|
||||||
|
# define zmemcpy memcpy
|
||||||
|
# define zmemcmp memcmp
|
||||||
|
# define zmemzero(dest, len) memset(dest, 0, len)
|
||||||
|
# endif
|
||||||
|
#else
|
||||||
|
extern void zmemcpy OF((Bytef* dest, const Bytef* source, uInt len));
|
||||||
|
extern int zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len));
|
||||||
|
extern void zmemzero OF((Bytef* dest, uInt len));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Diagnostic functions */
|
||||||
|
#ifdef DEBUG
|
||||||
|
# include <stdio.h>
|
||||||
|
extern int z_verbose;
|
||||||
|
extern void z_error OF((char *m));
|
||||||
|
# define Assert(cond,msg) {if(!(cond)) z_error(msg);}
|
||||||
|
# define Trace(x) {if (z_verbose>=0) fprintf x ;}
|
||||||
|
# define Tracev(x) {if (z_verbose>0) fprintf x ;}
|
||||||
|
# define Tracevv(x) {if (z_verbose>1) fprintf x ;}
|
||||||
|
# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;}
|
||||||
|
# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;}
|
||||||
|
#else
|
||||||
|
# define Assert(cond,msg)
|
||||||
|
# define Trace(x)
|
||||||
|
# define Tracev(x)
|
||||||
|
# define Tracevv(x)
|
||||||
|
# define Tracec(c,x)
|
||||||
|
# define Tracecv(c,x)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size));
|
||||||
|
void zcfree OF((voidpf opaque, voidpf ptr));
|
||||||
|
|
||||||
|
#define ZALLOC(strm, items, size) \
|
||||||
|
(*((strm)->zalloc))((strm)->opaque, (items), (size))
|
||||||
|
#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr))
|
||||||
|
#define TRY_FREE(s, p) {if (p) ZFREE(s, p);}
|
||||||
|
|
||||||
|
#endif /* ZUTIL_H */
|
After Width: | Height: | Size: 245 KiB |
|
@ -0,0 +1,868 @@
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: \n"
|
||||||
|
"POT-Creation-Date: \n"
|
||||||
|
"PO-Revision-Date: 2006-11-17 02:05+0100\n"
|
||||||
|
"Last-Translator: Simon Lindell <Doomangel_91@hotmail.com>\n"
|
||||||
|
"Language-Team: \n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=iso-8859-1\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
|
||||||
|
msgid "%s: Error loading %s: %s"
|
||||||
|
msgstr "%s: Kan ej ladda %s: %s"
|
||||||
|
|
||||||
|
msgid "&About..."
|
||||||
|
msgstr "&Om..."
|
||||||
|
|
||||||
|
msgid "&Arguments"
|
||||||
|
msgstr "&Argument"
|
||||||
|
|
||||||
|
msgid "&Config"
|
||||||
|
msgstr "&Konfiguration"
|
||||||
|
|
||||||
|
msgid "&Configure"
|
||||||
|
msgstr "&Konfigurera"
|
||||||
|
|
||||||
|
msgid "&Debug"
|
||||||
|
msgstr "&Debug"
|
||||||
|
|
||||||
|
msgid "&File"
|
||||||
|
msgstr "&Arkiv"
|
||||||
|
|
||||||
|
msgid "&Graphics"
|
||||||
|
msgstr "&Grafik"
|
||||||
|
|
||||||
|
msgid "&Help"
|
||||||
|
msgstr "&Hjälp"
|
||||||
|
|
||||||
|
msgid "&Language"
|
||||||
|
msgstr "&Språk"
|
||||||
|
|
||||||
|
msgid "&Load"
|
||||||
|
msgstr "&Ladda"
|
||||||
|
|
||||||
|
msgid "&Logging"
|
||||||
|
msgstr "&Loggar"
|
||||||
|
|
||||||
|
msgid "&Low"
|
||||||
|
msgstr "&Låg"
|
||||||
|
|
||||||
|
msgid "&Memcards"
|
||||||
|
msgstr "&Minneskort"
|
||||||
|
|
||||||
|
msgid "&Misc"
|
||||||
|
msgstr "&Övrigt"
|
||||||
|
|
||||||
|
msgid "&Open ELF File"
|
||||||
|
msgstr "&Öppna ELF fil"
|
||||||
|
|
||||||
|
msgid "&Other..."
|
||||||
|
msgstr "&Annat..."
|
||||||
|
|
||||||
|
msgid "&Patches"
|
||||||
|
msgstr "&Patchar"
|
||||||
|
|
||||||
|
msgid "&Process Priority"
|
||||||
|
msgstr "&Process Prioritet"
|
||||||
|
|
||||||
|
msgid "&Remote Debugging"
|
||||||
|
msgstr "&Fjärrstyrd Debug"
|
||||||
|
|
||||||
|
msgid "&Run"
|
||||||
|
msgstr "&Kör"
|
||||||
|
|
||||||
|
msgid "&Run CD"
|
||||||
|
msgstr "&Kör CD"
|
||||||
|
|
||||||
|
msgid "&Save"
|
||||||
|
msgstr "&Spara"
|
||||||
|
|
||||||
|
msgid "&Sound"
|
||||||
|
msgstr "&Ljud"
|
||||||
|
|
||||||
|
msgid "&States"
|
||||||
|
msgstr "Sparpunkter"
|
||||||
|
|
||||||
|
msgid "*PCSX2*: Error Loading State %d"
|
||||||
|
msgstr "*PCSX2*: Kan inte ladda sparpunkt %d"
|
||||||
|
|
||||||
|
msgid "*PCSX2*: Error Loading State %s"
|
||||||
|
msgstr "*PCSX2*: Kan inte ladda sparpunkt %s"
|
||||||
|
|
||||||
|
msgid "*PCSX2*: Error Saving State %d"
|
||||||
|
msgstr "*PCSX2*: Kan inte spara sparpunkt %d"
|
||||||
|
|
||||||
|
msgid "*PCSX2*: Error Saving State %s"
|
||||||
|
msgstr "*PCSX2*: Kan inte spara sparpunkt %s"
|
||||||
|
|
||||||
|
msgid "*PCSX2*: Loaded State %d"
|
||||||
|
msgstr "*PCSX2*: Sparpunkt laddad %d"
|
||||||
|
|
||||||
|
msgid "*PCSX2*: Loaded State %s"
|
||||||
|
msgstr "*PCSX2*: Sparpunkt laddad %s"
|
||||||
|
|
||||||
|
msgid "*PCSX2*: Saving State %d"
|
||||||
|
msgstr "*PCSX2*: Sparar punkt %d"
|
||||||
|
|
||||||
|
msgid "*PCSX2*: Saving State %s"
|
||||||
|
msgstr "*PCSX2*: Sparar punkt %s"
|
||||||
|
|
||||||
|
msgid "0x"
|
||||||
|
msgstr "0x"
|
||||||
|
|
||||||
|
msgid "About"
|
||||||
|
msgstr "Om"
|
||||||
|
|
||||||
|
msgid "About PCSX2"
|
||||||
|
msgstr "Om PCSX2"
|
||||||
|
|
||||||
|
msgid "About..."
|
||||||
|
msgstr "Om..."
|
||||||
|
|
||||||
|
msgid "Address "
|
||||||
|
msgstr "Address"
|
||||||
|
|
||||||
|
msgid "All Files"
|
||||||
|
msgstr "Alla Filer"
|
||||||
|
|
||||||
|
msgid "Arabic"
|
||||||
|
msgstr "Arabiska"
|
||||||
|
|
||||||
|
msgid "Arguments"
|
||||||
|
msgstr "Argument"
|
||||||
|
|
||||||
|
msgid "Bios"
|
||||||
|
msgstr "BIOS"
|
||||||
|
|
||||||
|
msgid "Bios Log"
|
||||||
|
msgstr "BIOS Log"
|
||||||
|
|
||||||
|
msgid "Bulgarian"
|
||||||
|
msgstr "Bulgariska"
|
||||||
|
|
||||||
|
msgid "C&dvdrom"
|
||||||
|
msgstr "C&DVDROM"
|
||||||
|
|
||||||
|
msgid "C&ontrollers"
|
||||||
|
msgstr "K&ontroller"
|
||||||
|
|
||||||
|
msgid "C&pu"
|
||||||
|
msgstr "C&PU"
|
||||||
|
|
||||||
|
msgid "CDVDinit error: %d"
|
||||||
|
msgstr "CDVD Initieringsfel: %d"
|
||||||
|
|
||||||
|
msgid "Cancel"
|
||||||
|
msgstr "Avbryt"
|
||||||
|
|
||||||
|
msgid "Cannot load '%s', wrong PS2E version (%x != %x)"
|
||||||
|
msgstr "Kan inte ladda '%s',Fel PS2E version (%x != %x)"
|
||||||
|
|
||||||
|
msgid "Catalan"
|
||||||
|
msgstr "Kataloniska"
|
||||||
|
|
||||||
|
msgid "Cdr Log"
|
||||||
|
msgstr "CDR Log"
|
||||||
|
|
||||||
|
msgid "Cdvdrom"
|
||||||
|
msgstr "CDVDROM"
|
||||||
|
|
||||||
|
msgid "Clear BPs"
|
||||||
|
msgstr "Rensa BPs"
|
||||||
|
|
||||||
|
msgid "Close"
|
||||||
|
msgstr "Stäng"
|
||||||
|
|
||||||
|
msgid "Conf"
|
||||||
|
msgstr "Konfiguration"
|
||||||
|
|
||||||
|
msgid "Configuration"
|
||||||
|
msgstr "Konfiguration"
|
||||||
|
|
||||||
|
msgid "Configure"
|
||||||
|
msgstr "Konfigurera"
|
||||||
|
|
||||||
|
msgid "Configure..."
|
||||||
|
msgstr "Konfigurera"
|
||||||
|
|
||||||
|
msgid "Controllers"
|
||||||
|
msgstr "Kontroller"
|
||||||
|
|
||||||
|
msgid "Cop0 Log"
|
||||||
|
msgstr "COP0 Log"
|
||||||
|
|
||||||
|
msgid "Could Not Load CDVD Plugin '%s': %s"
|
||||||
|
msgstr "Kunde inte ladda CDVD Plugin '%s': %s"
|
||||||
|
|
||||||
|
msgid "Could Not Load DEV9 Plugin '%s': %s"
|
||||||
|
msgstr "Kunde inte ladda DEV9 Plugin '%s': %s"
|
||||||
|
|
||||||
|
msgid "Could Not Load FW Plugin '%s': %s"
|
||||||
|
msgstr "Kunde inte ladda Firewire Plugin '%s': %s"
|
||||||
|
|
||||||
|
msgid "Could Not Load GS Plugin '%s': %s"
|
||||||
|
msgstr "Kunde inte ladda Grafik Plugin '%s': %s"
|
||||||
|
|
||||||
|
msgid "Could Not Load PAD1 Plugin '%s': %s"
|
||||||
|
msgstr "Kunde inte ladda PAD1 Plugin '%s': %s"
|
||||||
|
|
||||||
|
msgid "Could Not Load PAD2 Plugin '%s': %s"
|
||||||
|
msgstr "Kunde inte ladda PAD2 Plugin '%s': %s"
|
||||||
|
|
||||||
|
msgid "Could Not Load SPU2 Plugin '%s': %s"
|
||||||
|
msgstr "Kunde inte ladda SPU2 Plugin '%s': %s"
|
||||||
|
|
||||||
|
msgid "Could Not Load USB Plugin '%s': %s"
|
||||||
|
msgstr "Kunde inte ladda USB Plugin '%s': %s"
|
||||||
|
|
||||||
|
msgid "Could not create threads or event"
|
||||||
|
msgstr "Kunde inte skapa trådar eller händelse."
|
||||||
|
|
||||||
|
msgid "Could not open '%s' directory"
|
||||||
|
msgstr "Kunde inte öppna mappen '%s'"
|
||||||
|
|
||||||
|
msgid "Couldn't find pixmap file: %s"
|
||||||
|
msgstr "Kunde inte hitta pixmap filen: %s"
|
||||||
|
|
||||||
|
msgid "Cpu"
|
||||||
|
msgstr "CPU"
|
||||||
|
|
||||||
|
msgid "Cpu Config"
|
||||||
|
msgstr "CPU Konfiguration"
|
||||||
|
|
||||||
|
msgid "Cpu Log"
|
||||||
|
msgstr "CPU Log"
|
||||||
|
|
||||||
|
msgid "D&ev9"
|
||||||
|
msgstr "D&ev9"
|
||||||
|
|
||||||
|
msgid "DEV9init error: %d"
|
||||||
|
msgstr "DEV9 Initieringsfel: %d"
|
||||||
|
|
||||||
|
msgid "Data "
|
||||||
|
msgstr "Data"
|
||||||
|
|
||||||
|
msgid "Debug"
|
||||||
|
msgstr "Debug"
|
||||||
|
|
||||||
|
msgid "Dev9"
|
||||||
|
msgstr "Dev9"
|
||||||
|
|
||||||
|
msgid "Disable Recompiler"
|
||||||
|
msgstr "Avaktivera Omkompilerare"
|
||||||
|
|
||||||
|
msgid "Disable VUs recompilation"
|
||||||
|
msgstr "Inaktivera VUs omkompilation"
|
||||||
|
|
||||||
|
msgid "Dma Log"
|
||||||
|
msgstr "DMA Log"
|
||||||
|
|
||||||
|
msgid "Dump File = \"dump.txt\""
|
||||||
|
msgstr "Dumpa Fil = \"dump.txt\""
|
||||||
|
|
||||||
|
msgid "Dump code"
|
||||||
|
msgstr "Dumpa kod"
|
||||||
|
|
||||||
|
msgid "Dutch"
|
||||||
|
msgstr "Hollendska"
|
||||||
|
|
||||||
|
msgid "E&xecute"
|
||||||
|
msgstr "K&ör"
|
||||||
|
|
||||||
|
msgid "E&xit"
|
||||||
|
msgstr "&Avsluta"
|
||||||
|
|
||||||
|
msgid "EE Debug Mode"
|
||||||
|
msgstr "EE Debug Läge"
|
||||||
|
|
||||||
|
msgid "EE Logs"
|
||||||
|
msgstr "EE Logs"
|
||||||
|
|
||||||
|
msgid "Elf Log"
|
||||||
|
msgstr "ELF Log"
|
||||||
|
|
||||||
|
msgid "Emulator"
|
||||||
|
msgstr "Emulator"
|
||||||
|
|
||||||
|
msgid "Enable Console Output"
|
||||||
|
msgstr "Aktivera konsol"
|
||||||
|
|
||||||
|
msgid "Enable Patches"
|
||||||
|
msgstr "Aktivera patcher"
|
||||||
|
|
||||||
|
msgid "Enable Reg Caching"
|
||||||
|
msgstr "Aktivera Reg Cachning"
|
||||||
|
|
||||||
|
msgid "English"
|
||||||
|
msgstr "Engelska"
|
||||||
|
|
||||||
|
msgid "Enter &Debugger..."
|
||||||
|
msgstr "Starta &Debugger..."
|
||||||
|
|
||||||
|
msgid "Enter Debugger ..."
|
||||||
|
msgstr "Starta &Debugger"
|
||||||
|
|
||||||
|
msgid "Error Loading Symbol"
|
||||||
|
msgstr "Kunde inte ladda symbol"
|
||||||
|
|
||||||
|
msgid "Error Opening CDVD Plugin"
|
||||||
|
msgstr "Kunde inte öppna CD-ROM Plugin"
|
||||||
|
|
||||||
|
msgid "Error Opening DEV9 Plugin"
|
||||||
|
msgstr "Kunde inte öppna DEV9 Plugin"
|
||||||
|
|
||||||
|
msgid "Error Opening FW Plugin"
|
||||||
|
msgstr "Kunde inte öppna Firewire Plugin"
|
||||||
|
|
||||||
|
msgid "Error Opening GS Plugin"
|
||||||
|
msgstr "Kunde inte öppna Grafik Plugin"
|
||||||
|
|
||||||
|
msgid "Error Opening PAD1 Plugin"
|
||||||
|
msgstr "Kunde inte öppna PAD1 Plugin"
|
||||||
|
|
||||||
|
msgid "Error Opening PAD2 Plugin"
|
||||||
|
msgstr "Kunde inte öppna PAD2 Plugin"
|
||||||
|
|
||||||
|
msgid "Error Opening SPU2 Plugin"
|
||||||
|
msgstr "Kunde inte öppna SPU2 Plugin"
|
||||||
|
|
||||||
|
msgid "Error Opening USB Plugin"
|
||||||
|
msgstr "Kunde inte öppna USB Plugin"
|
||||||
|
|
||||||
|
msgid "Error allocating memory"
|
||||||
|
msgstr "Kunde inte allokollera minne"
|
||||||
|
|
||||||
|
msgid "Error initializing Recompiler, switching to Interpreter"
|
||||||
|
msgstr "Kunde inte initiera omkompilerare, går till Interpreter"
|
||||||
|
|
||||||
|
msgid "Error loading pixmap file: %s"
|
||||||
|
msgstr "Kunde inte öppna pixmap Fil: %s"
|
||||||
|
|
||||||
|
msgid "Exit"
|
||||||
|
msgstr "Avsluta"
|
||||||
|
|
||||||
|
msgid "FW"
|
||||||
|
msgstr "Firewire"
|
||||||
|
|
||||||
|
msgid "FWinit error: %d"
|
||||||
|
msgstr "Firewire Initieringsfel: %d"
|
||||||
|
|
||||||
|
msgid "Failed loading MemCard %s"
|
||||||
|
msgstr "Kunde inte ladda minneskort: %s"
|
||||||
|
|
||||||
|
msgid "File"
|
||||||
|
msgstr "Arkiv"
|
||||||
|
|
||||||
|
msgid "Fill in the command line arguments for opened program:"
|
||||||
|
msgstr "Fyll i kommando rads argumenten för det öppnade programmet:"
|
||||||
|
|
||||||
|
msgid "Fire&Wire"
|
||||||
|
msgstr "Fire&Wire"
|
||||||
|
|
||||||
|
msgid "First Controller"
|
||||||
|
msgstr "Första kontrollern"
|
||||||
|
|
||||||
|
msgid "Fpu Log"
|
||||||
|
msgstr "FPU Log"
|
||||||
|
|
||||||
|
msgid "French"
|
||||||
|
msgstr "Franska"
|
||||||
|
|
||||||
|
msgid "From 0x"
|
||||||
|
msgstr "Från 0x"
|
||||||
|
|
||||||
|
msgid "GIF Log"
|
||||||
|
msgstr "GIF Log"
|
||||||
|
|
||||||
|
msgid "GPU Log"
|
||||||
|
msgstr "GPU Log"
|
||||||
|
|
||||||
|
msgid "GSinit error: %d"
|
||||||
|
msgstr "Grafiska Syncen kunde inte initieras: %d"
|
||||||
|
|
||||||
|
msgid "German"
|
||||||
|
msgstr "Tyska"
|
||||||
|
|
||||||
|
msgid "Go"
|
||||||
|
msgstr "Starta"
|
||||||
|
|
||||||
|
msgid "Graphics"
|
||||||
|
msgstr "Grafik"
|
||||||
|
|
||||||
|
msgid "Greek"
|
||||||
|
msgstr "Grekiska"
|
||||||
|
|
||||||
|
msgid "Greets to:"
|
||||||
|
msgstr "Hälsningar till:"
|
||||||
|
|
||||||
|
msgid ""
|
||||||
|
"Greets to: Bobbi, Keith, CpUMasteR, Nave, Snake785, Raziel\n"
|
||||||
|
"Special thanks to: Sjeep, Dreamtime, F|RES, BGnome, MrBrown, \n"
|
||||||
|
"Seta-San, Skarmeth, blackd_wd, _Demo_\n"
|
||||||
|
"Credits: Hiryu && Sjeep for their libcdvd (iso parsing and filesystem driver code)\n"
|
||||||
|
"Some betatester/support dudes: bositman, Seta-san, falcon4ever, jegHegy, Razorblade, CKemu, Belmont, parotaku, crushtest, ChaosCode"
|
||||||
|
msgstr ""
|
||||||
|
"Hälsningar till: Bobbi, Keith, CpUMasteR, Nave, Snake785, Raziel\n"
|
||||||
|
"Danke an: Sjeep, Dreamtime, F|RES, BGnome, MrBrown, \n"
|
||||||
|
"Seta-San, Skarmeth, blackd_wd, _Demo_\n"
|
||||||
|
"Meriten: Hiryu && Sjeep fr Ihre libcdvd (ISO Parsing und Filesystem Treiber Code)\n"
|
||||||
|
"Einige Betatester/Hilfskrfte: bositman, Seta-san, falcon4ever, jegHegy, Razorblade, CKemu"
|
||||||
|
|
||||||
|
msgid "Gte Log"
|
||||||
|
msgstr "GTE Log"
|
||||||
|
|
||||||
|
msgid "Help"
|
||||||
|
msgstr "Hjälp"
|
||||||
|
|
||||||
|
msgid "High"
|
||||||
|
msgstr "Hög"
|
||||||
|
|
||||||
|
msgid "Hw Log"
|
||||||
|
msgstr "Hårdvaru Log"
|
||||||
|
|
||||||
|
msgid "IOP Debug Mode"
|
||||||
|
msgstr "IOP Debug läge"
|
||||||
|
|
||||||
|
msgid "IOP Log"
|
||||||
|
msgstr "IOP Log"
|
||||||
|
|
||||||
|
msgid "IOP Logs"
|
||||||
|
msgstr "IOP Log"
|
||||||
|
|
||||||
|
msgid "IPU Log"
|
||||||
|
msgstr "IPU Log"
|
||||||
|
|
||||||
|
msgid "If you don't know what to write leave it blank"
|
||||||
|
msgstr "Om du inte vet vad du ska skriva, lämna den tom"
|
||||||
|
|
||||||
|
msgid ""
|
||||||
|
"In debugger:\n"
|
||||||
|
"Put EE in stop state\n"
|
||||||
|
"and IOP in run state"
|
||||||
|
msgstr ""
|
||||||
|
"I Debugger: \n"
|
||||||
|
"Sätt EE i stoppad status\n"
|
||||||
|
"och IOP i pågående status"
|
||||||
|
|
||||||
|
msgid ""
|
||||||
|
"In debugger:\n"
|
||||||
|
"Put IOP in stop state\n"
|
||||||
|
"and EE in run state"
|
||||||
|
msgstr ""
|
||||||
|
"I Debugger: \n"
|
||||||
|
"Sätt IOP i stoppad status\n"
|
||||||
|
"och EE i pågående status"
|
||||||
|
|
||||||
|
msgid "Interpreter -The slowest but the most compatible cpu core"
|
||||||
|
msgstr "Interpreter -Den långsammaste men mest kompitabla cpu kärnan"
|
||||||
|
|
||||||
|
msgid "Italian"
|
||||||
|
msgstr "Italienska"
|
||||||
|
|
||||||
|
msgid "Japanese"
|
||||||
|
msgstr "Japanska"
|
||||||
|
|
||||||
|
msgid "Language"
|
||||||
|
msgstr "Språk"
|
||||||
|
|
||||||
|
msgid "Load"
|
||||||
|
msgstr "Ladda"
|
||||||
|
|
||||||
|
msgid "Load Elf"
|
||||||
|
msgstr "Ladda Elf"
|
||||||
|
|
||||||
|
msgid "Log"
|
||||||
|
msgstr "Log"
|
||||||
|
|
||||||
|
msgid "Log On/Off"
|
||||||
|
msgstr "Loggning På/Av"
|
||||||
|
|
||||||
|
msgid "Log to STDOUT"
|
||||||
|
msgstr "Logga till STDOUT"
|
||||||
|
|
||||||
|
msgid "Logging"
|
||||||
|
msgstr "Loggning"
|
||||||
|
|
||||||
|
msgid "MMI Log"
|
||||||
|
msgstr "MMI Log"
|
||||||
|
|
||||||
|
msgid "Mem Log"
|
||||||
|
msgstr "Minnes Log"
|
||||||
|
|
||||||
|
msgid "Memcard Manager"
|
||||||
|
msgstr "Minneskorts Skötare"
|
||||||
|
|
||||||
|
msgid "Memory Card 1"
|
||||||
|
msgstr "Minneskort 1"
|
||||||
|
|
||||||
|
msgid "Memory Card 2"
|
||||||
|
msgstr "Minneskort 2"
|
||||||
|
|
||||||
|
msgid "Memory Dump"
|
||||||
|
msgstr "Minnesdump"
|
||||||
|
|
||||||
|
msgid ""
|
||||||
|
"Nah, you have to be in\n"
|
||||||
|
"Interpreter Mode to debug"
|
||||||
|
msgstr ""
|
||||||
|
"Nej, du måste vara i\n"
|
||||||
|
"Interpreter läge för att debugga"
|
||||||
|
|
||||||
|
msgid "New Patch"
|
||||||
|
msgstr "Ny Patch"
|
||||||
|
|
||||||
|
msgid "Normal"
|
||||||
|
msgstr "Normal"
|
||||||
|
|
||||||
|
msgid "Not enough params for inicommand\n"
|
||||||
|
msgstr "Inte tillräckligt med parametrar för inikommando\n"
|
||||||
|
|
||||||
|
msgid "Note: this is intented for developers only."
|
||||||
|
msgstr "Notera: detta är endast menat för utvecklare."
|
||||||
|
|
||||||
|
msgid "Notice on debugging EE"
|
||||||
|
msgstr "Notis på EE debug"
|
||||||
|
|
||||||
|
msgid "Notice on debugging IOP"
|
||||||
|
msgstr "Notis på IOP debug"
|
||||||
|
|
||||||
|
msgid "OK"
|
||||||
|
msgstr "Ok"
|
||||||
|
|
||||||
|
msgid "Ok"
|
||||||
|
msgstr "Ok"
|
||||||
|
|
||||||
|
msgid "Options"
|
||||||
|
msgstr "Alternativ"
|
||||||
|
|
||||||
|
msgid "Other..."
|
||||||
|
msgstr "Annat..."
|
||||||
|
|
||||||
|
msgid "PAD1init error: %d"
|
||||||
|
msgstr "Kunde inte initiera Pad1: %d"
|
||||||
|
|
||||||
|
msgid "PAD2init error: %d"
|
||||||
|
msgstr "Kunde inte initiera pad2: %d"
|
||||||
|
|
||||||
|
msgid "PCSX"
|
||||||
|
msgstr "PCSX"
|
||||||
|
|
||||||
|
msgid ""
|
||||||
|
"PCSX2\r\r\r\n"
|
||||||
|
"Version x.x"
|
||||||
|
msgstr ""
|
||||||
|
"PCSX2\r\r\r\n"
|
||||||
|
"Version x.x"
|
||||||
|
|
||||||
|
msgid "PCSX2 %s Compile Date - %s %s"
|
||||||
|
msgstr "PCSX2 %s Kompilerat: %s %s"
|
||||||
|
|
||||||
|
msgid "PCSX2 Debugger"
|
||||||
|
msgstr "PCSX2 Debugger"
|
||||||
|
|
||||||
|
msgid "PCSX2 EMU\n"
|
||||||
|
msgstr "PCSX2 Emulator\n"
|
||||||
|
|
||||||
|
msgid ""
|
||||||
|
"PCSX2 For Linux\n"
|
||||||
|
"Version %s"
|
||||||
|
msgstr ""
|
||||||
|
"PCSX2 För Linux\n"
|
||||||
|
"Version %s"
|
||||||
|
|
||||||
|
msgid "PCSX2 Msg"
|
||||||
|
msgstr "PCSX2 Meddelande"
|
||||||
|
|
||||||
|
msgid "PCSX2 Quitting\n"
|
||||||
|
msgstr "PCSX2 Stänger\n"
|
||||||
|
|
||||||
|
msgid "PCSX2 State Format"
|
||||||
|
msgstr "PCSX2 Sparpunktsformat"
|
||||||
|
|
||||||
|
msgid ""
|
||||||
|
"PCSX2 a ps2 emulator\n"
|
||||||
|
"\n"
|
||||||
|
"written by:\n"
|
||||||
|
"linuzappz, shadow, florin,\n"
|
||||||
|
"alexey silinov, asadr, goldfinger,\n"
|
||||||
|
"nachbrenner, auMatt, loser\n"
|
||||||
|
"\n"
|
||||||
|
"Webmaster: Thorgal"
|
||||||
|
msgstr ""
|
||||||
|
"PCSX2 - En PS2 Emulator\n"
|
||||||
|
"\n"
|
||||||
|
"Skriven av:\n"
|
||||||
|
"linuzappz, shadow, florin,\n"
|
||||||
|
"alexey silinov, saqibakhtar, goldfinger,\n"
|
||||||
|
"Nachbrenner, auMatt, loser\n"
|
||||||
|
"\n"
|
||||||
|
"Webmaster: Thorgal"
|
||||||
|
|
||||||
|
msgid "Pad Log"
|
||||||
|
msgstr "PAD Log"
|
||||||
|
|
||||||
|
msgid "Patches Browser"
|
||||||
|
msgstr "Patch Utforskare"
|
||||||
|
|
||||||
|
msgid "Pcsx About"
|
||||||
|
msgstr "PCSX om"
|
||||||
|
|
||||||
|
msgid "Pcsx2 Msg"
|
||||||
|
msgstr "PCSX2 Meddelande"
|
||||||
|
|
||||||
|
msgid "Pcsx2 needs to be configured"
|
||||||
|
msgstr "PCSX2 måste konfigureras"
|
||||||
|
|
||||||
|
msgid "Plugins & Bios"
|
||||||
|
msgstr "Plugins & BIOS"
|
||||||
|
|
||||||
|
msgid "Portuguese"
|
||||||
|
msgstr "Portugisiska"
|
||||||
|
|
||||||
|
msgid "Processor doesn't supports MMX, can't run recompiler without that"
|
||||||
|
msgstr "Processorn är inte kompitabel med MMX, kan inte köra omkompilerare utan det."
|
||||||
|
|
||||||
|
msgid "Program arguments"
|
||||||
|
msgstr "ProgramArgument"
|
||||||
|
|
||||||
|
msgid "Ps2 Memory Card (*.ps2)"
|
||||||
|
msgstr "PS2 Minneskort (*.ps2)"
|
||||||
|
|
||||||
|
msgid "Ps2 Output"
|
||||||
|
msgstr "PS2 Konsol"
|
||||||
|
|
||||||
|
msgid "RPC Log"
|
||||||
|
msgstr "RPC Log"
|
||||||
|
|
||||||
|
msgid "Raw Dump"
|
||||||
|
msgstr "Rådata dump"
|
||||||
|
|
||||||
|
msgid "Re&set"
|
||||||
|
msgstr "&Starta om"
|
||||||
|
|
||||||
|
msgid "Ready"
|
||||||
|
msgstr "Redo"
|
||||||
|
|
||||||
|
msgid "Recompiler - Much faster than Intepreter(Needs MMX)"
|
||||||
|
msgstr "Omkompilerare - Mycket snabbare än Interpreter(Kräver MMX)"
|
||||||
|
|
||||||
|
msgid "Recompiler Options"
|
||||||
|
msgstr "Omkompilerarens alternativ"
|
||||||
|
|
||||||
|
msgid "Recompiler+VuRecs - The fastest setting (Needs SSE,SSE2)"
|
||||||
|
msgstr "Omkompilerare + VuRecs - Snabbaste alternativer (Kräver SSE,SSE2)"
|
||||||
|
|
||||||
|
msgid "Refresh List"
|
||||||
|
msgstr "Uppdatera Lista"
|
||||||
|
|
||||||
|
msgid "Reset"
|
||||||
|
msgstr "Starta om"
|
||||||
|
|
||||||
|
msgid "Resetting..."
|
||||||
|
msgstr "Startar om..."
|
||||||
|
|
||||||
|
msgid "Romanian"
|
||||||
|
msgstr "Rumenska"
|
||||||
|
|
||||||
|
msgid "Run"
|
||||||
|
msgstr "Kör"
|
||||||
|
|
||||||
|
msgid "Run CD"
|
||||||
|
msgstr "Kör CD"
|
||||||
|
|
||||||
|
msgid "Russian"
|
||||||
|
msgstr "Ryska"
|
||||||
|
|
||||||
|
msgid "SPR Log"
|
||||||
|
msgstr "SPR Log"
|
||||||
|
|
||||||
|
msgid "SPU2init error: %d"
|
||||||
|
msgstr "Kunde inte initiera SPU2: %d"
|
||||||
|
|
||||||
|
msgid "SYMs Log"
|
||||||
|
msgstr "SYMs Log"
|
||||||
|
|
||||||
|
msgid "Save"
|
||||||
|
msgstr "Spara"
|
||||||
|
|
||||||
|
msgid "Save Patch"
|
||||||
|
msgstr "Spara Patch"
|
||||||
|
|
||||||
|
msgid "Search game name patch:"
|
||||||
|
msgstr "Sök efter spelpatch:"
|
||||||
|
|
||||||
|
msgid "Second Controller"
|
||||||
|
msgstr "Andra kontrollern"
|
||||||
|
|
||||||
|
msgid "Select Bios Dir"
|
||||||
|
msgstr "Välj BIOS mapp"
|
||||||
|
|
||||||
|
msgid "Select Bios Directory"
|
||||||
|
msgstr "Välj BIOS mapp"
|
||||||
|
|
||||||
|
msgid "Select Mcd"
|
||||||
|
msgstr "Välj Mcd"
|
||||||
|
|
||||||
|
msgid "Select Plugins Dir"
|
||||||
|
msgstr "Välj plugin mapp"
|
||||||
|
|
||||||
|
msgid "Select Plugins Directory"
|
||||||
|
msgstr "Välj pluginmapp"
|
||||||
|
|
||||||
|
msgid "Select Psx Elf File"
|
||||||
|
msgstr "Välj PSX Elf Fil"
|
||||||
|
|
||||||
|
msgid "Select State File"
|
||||||
|
msgstr "Välj sparpunktsfil"
|
||||||
|
|
||||||
|
msgid "Set BP Addr"
|
||||||
|
msgstr "Set BP Address"
|
||||||
|
|
||||||
|
msgid "Set BP Count"
|
||||||
|
msgstr "Set BP Räknare"
|
||||||
|
|
||||||
|
msgid "Set Bios Directory"
|
||||||
|
msgstr "Set BIOS mapp"
|
||||||
|
|
||||||
|
msgid "Set Dump Addr (in Hex):"
|
||||||
|
msgstr "Set Dump Address (i hexadecimalt tal):"
|
||||||
|
|
||||||
|
msgid "Set New BP Address (in Hex):"
|
||||||
|
msgstr "Set ny BP Address (i hexadecimalt tal)"
|
||||||
|
|
||||||
|
msgid "Set New BP Count (in Hex):"
|
||||||
|
msgstr "Set ny BP räkning (i hexadecimalt tal):"
|
||||||
|
|
||||||
|
msgid "Set New PC Address (in Hex):"
|
||||||
|
msgstr "Set ny PC address (i hexadecimalt tal):"
|
||||||
|
|
||||||
|
msgid "Set PC"
|
||||||
|
msgstr "Set PC"
|
||||||
|
|
||||||
|
msgid "Set Plugins Directory"
|
||||||
|
msgstr "Set Plugin Mapp"
|
||||||
|
|
||||||
|
msgid "SetBreakPoint Addr"
|
||||||
|
msgstr "Set BP Address"
|
||||||
|
|
||||||
|
msgid "SetPCDlg"
|
||||||
|
msgstr "Set PC Dialog"
|
||||||
|
|
||||||
|
msgid "Sif Log"
|
||||||
|
msgstr "SIF Log"
|
||||||
|
|
||||||
|
msgid "Skip"
|
||||||
|
msgstr "Skippa"
|
||||||
|
|
||||||
|
msgid "Slot &1"
|
||||||
|
msgstr "Slot &1"
|
||||||
|
|
||||||
|
msgid "Slot &2"
|
||||||
|
msgstr "Slot &2"
|
||||||
|
|
||||||
|
msgid "Slot &3"
|
||||||
|
msgstr "Slot &3"
|
||||||
|
|
||||||
|
msgid "Slot &4"
|
||||||
|
msgstr "Slot &4"
|
||||||
|
|
||||||
|
msgid "Slot &5"
|
||||||
|
msgstr "Slot &5"
|
||||||
|
|
||||||
|
msgid "Slot 1"
|
||||||
|
msgstr "Slot 1"
|
||||||
|
|
||||||
|
msgid "Slot 2"
|
||||||
|
msgstr "Slot 2"
|
||||||
|
|
||||||
|
msgid "Slot 3"
|
||||||
|
msgstr "Slot 3"
|
||||||
|
|
||||||
|
msgid "Slot 4"
|
||||||
|
msgstr "Slot 4"
|
||||||
|
|
||||||
|
msgid "Slot 5"
|
||||||
|
msgstr "Slot 5"
|
||||||
|
|
||||||
|
msgid "Sound"
|
||||||
|
msgstr "Ljud"
|
||||||
|
|
||||||
|
msgid "Spanish"
|
||||||
|
msgstr "Spanska"
|
||||||
|
|
||||||
|
msgid "States"
|
||||||
|
msgstr "Sparpunkter"
|
||||||
|
|
||||||
|
msgid "Step"
|
||||||
|
msgstr "Steg"
|
||||||
|
|
||||||
|
msgid "Test"
|
||||||
|
msgstr "Test"
|
||||||
|
|
||||||
|
msgid "Test..."
|
||||||
|
msgstr "Test"
|
||||||
|
|
||||||
|
msgid "This plugin reports that should not work correctly"
|
||||||
|
msgstr "Denna plugin rapporterar att den funkar bra"
|
||||||
|
|
||||||
|
msgid "This plugin reports that should work correctly"
|
||||||
|
msgstr "Denna plugin rapporterar att den funkar bra"
|
||||||
|
|
||||||
|
msgid ""
|
||||||
|
"Tip: If you don't know what to write\n"
|
||||||
|
"leave it blank"
|
||||||
|
msgstr ""
|
||||||
|
"Tips: Om du inte vet vad du ska skriva\n"
|
||||||
|
"lämna den tom"
|
||||||
|
|
||||||
|
msgid "To 0x"
|
||||||
|
msgstr "Till 0x"
|
||||||
|
|
||||||
|
msgid "Turkish"
|
||||||
|
msgstr "Turkiska"
|
||||||
|
|
||||||
|
msgid "U&SB"
|
||||||
|
msgstr "U&SB"
|
||||||
|
|
||||||
|
msgid "USBinit error: %d"
|
||||||
|
msgstr "Kunde inte initiera Usb: %d"
|
||||||
|
|
||||||
|
msgid "Unable to hack in %s%s\n"
|
||||||
|
msgstr ""
|
||||||
|
"Kunde inte hacka %s%s \n"
|
||||||
|
"\n"
|
||||||
|
|
||||||
|
msgid "Unable to load bios: '%s', PCSX2 can't run without that"
|
||||||
|
msgstr "Kunde inte ladda BIOS: '%s', PCSX2 Kan inte funka utan det!"
|
||||||
|
|
||||||
|
msgid "Unrecoverable error while running recompiler"
|
||||||
|
msgstr "Ireparabelt fel under omkompilerarens körning"
|
||||||
|
|
||||||
|
msgid "Usb"
|
||||||
|
msgstr "USB"
|
||||||
|
|
||||||
|
msgid "VU Micro Log"
|
||||||
|
msgstr "VU Micro Log"
|
||||||
|
|
||||||
|
msgid "VU0 Log"
|
||||||
|
msgstr "VU0 Log"
|
||||||
|
|
||||||
|
msgid "Vif Log"
|
||||||
|
msgstr "VIF Log"
|
||||||
|
|
||||||
|
msgid "button69"
|
||||||
|
msgstr "Knapp 69"
|
||||||
|
|
||||||
|
msgid "button70"
|
||||||
|
msgstr "Knapp70"
|
||||||
|
|
||||||
|
msgid "memWrite32"
|
||||||
|
msgstr "memWrite32"
|
||||||
|
|
||||||
|
msgid "patch file for this game not found. Can't apply any patches\n"
|
||||||
|
msgstr "Hittade ingen patch för detta spel. Kan inte applicera patch. \n"
|
||||||
|
|
||||||
|
msgid "written by..."
|
||||||
|
msgstr "Skrivet av..."
|
||||||
|
|
After Width: | Height: | Size: 544 B |
After Width: | Height: | Size: 486 B |
After Width: | Height: | Size: 477 B |
After Width: | Height: | Size: 518 B |
After Width: | Height: | Size: 455 B |
After Width: | Height: | Size: 511 B |
After Width: | Height: | Size: 304 B |
After Width: | Height: | Size: 305 B |
After Width: | Height: | Size: 305 B |
After Width: | Height: | Size: 305 B |
After Width: | Height: | Size: 304 B |
|
@ -0,0 +1,4 @@
|
||||||
|
gametitle= Resident Evil 4 [SLUS 21134] (U)
|
||||||
|
comment=
|
||||||
|
//ZeroGS Patch - GAME_NOTARGETCLUT
|
||||||
|
zerogs=00001000
|
|
@ -0,0 +1,4 @@
|
||||||
|
gametitle= Sims - The Urbz, The [SLES 52908] (E)
|
||||||
|
comment=
|
||||||
|
//ZeroGS Patch - GAME_NOQUICKRESOLVE
|
||||||
|
zerogs=00000800
|
|
@ -0,0 +1,13 @@
|
||||||
|
gametitle=Driving Emotion Type-S [SLPS 20007] (J)
|
||||||
|
comment= patches by Nachbrenner
|
||||||
|
//Skip OP_MOVIE
|
||||||
|
//patch=0,EE,001c1818,word,1000000c
|
||||||
|
//MTGS: fix GS_CSR in "sceGsExecStoreImage"
|
||||||
|
patch=0,EE,00276ad0,word,34420002
|
||||||
|
patch=0,EE,00276aa0,word,34630002
|
||||||
|
//MTGS: fix GS_CSR in custom function
|
||||||
|
patch=0,EE,00251ac4,word,00000000
|
||||||
|
//disable BGM
|
||||||
|
patch=0,EE,00221914,word,24020000
|
||||||
|
patch=0,EE,002218c8,word,03e00008
|
||||||
|
patch=0,EE,002218cc,word,00000000
|
|
@ -0,0 +1,4 @@
|
||||||
|
gametitle=Samurai Warriors Xtreme Legends
|
||||||
|
comment=Skips Videos by bositman
|
||||||
|
//Skip Videos
|
||||||
|
patch=0,EE,00126bb0,word,24020001
|