mirror of
https://github.com/signalwire/freeswitch.git
synced 2026-11-15 13:58:32 +00:00
FS-4657 --resolve update libsndfile to its latest master
This commit is contained in:
1 parent
0c1f6ef2ed
commit
199a64bf6a
291 files changed
+25965
-5744
No files matched your search
@@ -0,0 +1,200 @@
|
||||
/*
|
||||
* Copyright (c) 2011 Apple Inc. All rights reserved.
|
||||
*
|
||||
* @APPLE_APACHE_LICENSE_HEADER_START@
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @APPLE_APACHE_LICENSE_HEADER_END@
|
||||
*/
|
||||
|
||||
/*
|
||||
File: ALACAudioTypes.h
|
||||
*/
|
||||
|
||||
#ifndef ALACAUDIOTYPES_H
|
||||
#define ALACAUDIOTYPES_H
|
||||
|
||||
/* Force these Mac OS specific things to zero. */
|
||||
#define PRAGMA_STRUCT_ALIGN 0
|
||||
#define PRAGMA_STRUCT_PACKPUSH 0
|
||||
#define PRAGMA_STRUCT_PACK 0
|
||||
#define PRAGMA_ONCE 0
|
||||
#define PRAGMA_MARK 0
|
||||
|
||||
|
||||
#if PRAGMA_ONCE
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "sfendian.h"
|
||||
|
||||
#if CPU_IS_BIG_ENDIAN == 1
|
||||
#define TARGET_RT_BIG_ENDIAN 1
|
||||
#else
|
||||
#define TARGET_RT_BIG_ENDIAN 0
|
||||
#endif
|
||||
|
||||
#define kChannelAtomSize 12
|
||||
|
||||
enum
|
||||
{
|
||||
kALAC_UnimplementedError = -4,
|
||||
kALAC_FileNotFoundError = -43,
|
||||
kALAC_ParamError = -50,
|
||||
kALAC_MemFullError = -108,
|
||||
fALAC_FrameLengthError = -666,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
kALACFormatAppleLossless = MAKE_MARKER ('a', 'l', 'a', 'c'),
|
||||
kALACFormatLinearPCM = MAKE_MARKER ('l', 'p', 'c', 'm')
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
kALACMaxChannels = 8,
|
||||
kALACMaxEscapeHeaderBytes = 8,
|
||||
kALACMaxSearches = 16,
|
||||
kALACMaxCoefs = 16,
|
||||
kALACDefaultFramesPerPacket = 4096
|
||||
};
|
||||
|
||||
typedef uint32_t ALACChannelLayoutTag;
|
||||
|
||||
enum
|
||||
{
|
||||
kALACFormatFlagIsFloat = (1 << 0), // 0x1
|
||||
kALACFormatFlagIsBigEndian = (1 << 1), // 0x2
|
||||
kALACFormatFlagIsSignedInteger = (1 << 2), // 0x4
|
||||
kALACFormatFlagIsPacked = (1 << 3), // 0x8
|
||||
kALACFormatFlagIsAlignedHigh = (1 << 4), // 0x10
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
#if TARGET_RT_BIG_ENDIAN
|
||||
kALACFormatFlagsNativeEndian = kALACFormatFlagIsBigEndian
|
||||
#else
|
||||
kALACFormatFlagsNativeEndian = 0
|
||||
#endif
|
||||
};
|
||||
|
||||
// this is required to be an IEEE 64bit float
|
||||
typedef double alac_float64_t;
|
||||
|
||||
// These are the Channel Layout Tags used in the Channel Layout Info portion of the ALAC magic cookie
|
||||
enum
|
||||
{
|
||||
kALACChannelLayoutTag_Mono = (100<<16) | 1, // C
|
||||
kALACChannelLayoutTag_Stereo = (101<<16) | 2, // L R
|
||||
kALACChannelLayoutTag_MPEG_3_0_B = (113<<16) | 3, // C L R
|
||||
kALACChannelLayoutTag_MPEG_4_0_B = (116<<16) | 4, // C L R Cs
|
||||
kALACChannelLayoutTag_MPEG_5_0_D = (120<<16) | 5, // C L R Ls Rs
|
||||
kALACChannelLayoutTag_MPEG_5_1_D = (124<<16) | 6, // C L R Ls Rs LFE
|
||||
kALACChannelLayoutTag_AAC_6_1 = (142<<16) | 7, // C L R Ls Rs Cs LFE
|
||||
kALACChannelLayoutTag_MPEG_7_1_B = (127<<16) | 8 // C Lc Rc L R Ls Rs LFE (doc: IS-13818-7 MPEG2-AAC)
|
||||
};
|
||||
|
||||
// ALAC currently only utilizes these channels layouts. There is a one for one correspondance between a
|
||||
// given number of channels and one of these layout tags
|
||||
static const ALACChannelLayoutTag ALACChannelLayoutTags[kALACMaxChannels] =
|
||||
{
|
||||
kALACChannelLayoutTag_Mono, // C
|
||||
kALACChannelLayoutTag_Stereo, // L R
|
||||
kALACChannelLayoutTag_MPEG_3_0_B, // C L R
|
||||
kALACChannelLayoutTag_MPEG_4_0_B, // C L R Cs
|
||||
kALACChannelLayoutTag_MPEG_5_0_D, // C L R Ls Rs
|
||||
kALACChannelLayoutTag_MPEG_5_1_D, // C L R Ls Rs LFE
|
||||
kALACChannelLayoutTag_AAC_6_1, // C L R Ls Rs Cs LFE
|
||||
kALACChannelLayoutTag_MPEG_7_1_B // C Lc Rc L R Ls Rs LFE (doc: IS-13818-7 MPEG2-AAC)
|
||||
};
|
||||
|
||||
// AudioChannelLayout from CoreAudioTypes.h. We never need the AudioChannelDescription so we remove it
|
||||
struct ALACAudioChannelLayout
|
||||
{
|
||||
ALACChannelLayoutTag mChannelLayoutTag;
|
||||
uint32_t mChannelBitmap;
|
||||
uint32_t mNumberChannelDescriptions;
|
||||
};
|
||||
typedef struct ALACAudioChannelLayout ALACAudioChannelLayout;
|
||||
|
||||
struct AudioFormatDescription
|
||||
{
|
||||
alac_float64_t mSampleRate;
|
||||
uint32_t mFormatID;
|
||||
uint32_t mFormatFlags;
|
||||
uint32_t mBytesPerPacket;
|
||||
uint32_t mFramesPerPacket;
|
||||
uint32_t mBytesPerFrame;
|
||||
uint32_t mChannelsPerFrame;
|
||||
uint32_t mBitsPerChannel;
|
||||
uint32_t mReserved;
|
||||
};
|
||||
typedef struct AudioFormatDescription AudioFormatDescription;
|
||||
|
||||
/* Lossless Definitions */
|
||||
|
||||
enum
|
||||
{
|
||||
kALACCodecFormat = MAKE_MARKER ('a', 'l', 'a', 'c'),
|
||||
kALACVersion = 0,
|
||||
kALACCompatibleVersion = kALACVersion,
|
||||
kALACDefaultFrameSize = 4096
|
||||
};
|
||||
|
||||
// note: this struct is wrapped in an 'alac' atom in the sample description extension area
|
||||
// note: in QT movies, it will be further wrapped in a 'wave' atom surrounded by 'frma' and 'term' atoms
|
||||
typedef struct ALACSpecificConfig
|
||||
{
|
||||
uint32_t frameLength;
|
||||
uint8_t compatibleVersion;
|
||||
uint8_t bitDepth; // max 32
|
||||
uint8_t pb; // 0 <= pb <= 255
|
||||
uint8_t mb;
|
||||
uint8_t kb;
|
||||
uint8_t numChannels;
|
||||
uint16_t maxRun;
|
||||
uint32_t maxFrameBytes;
|
||||
uint32_t avgBitRate;
|
||||
uint32_t sampleRate;
|
||||
|
||||
} ALACSpecificConfig;
|
||||
|
||||
|
||||
// The AudioChannelLayout atom type is not exposed yet so define it here
|
||||
enum
|
||||
{
|
||||
AudioChannelLayoutAID = MAKE_MARKER ('c', 'h', 'a', 'n')
|
||||
};
|
||||
|
||||
#if PRAGMA_STRUCT_ALIGN
|
||||
#pragma options align=reset
|
||||
#elif PRAGMA_STRUCT_PACKPUSH
|
||||
#pragma pack(pop)
|
||||
#elif PRAGMA_STRUCT_PACK
|
||||
#pragma pack()
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ALACAUDIOTYPES_H */
|
||||
@@ -0,0 +1,262 @@
|
||||
/*
|
||||
* Copyright (c) 2011 Apple Inc. All rights reserved.
|
||||
*
|
||||
* @APPLE_APACHE_LICENSE_HEADER_START@
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @APPLE_APACHE_LICENSE_HEADER_END@
|
||||
*/
|
||||
|
||||
/*=============================================================================
|
||||
File: ALACBitUtilities.c
|
||||
|
||||
$NoKeywords: $
|
||||
=============================================================================*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "ALACBitUtilities.h"
|
||||
|
||||
#define PRAGMA_MARK 0
|
||||
|
||||
// BitBufferInit
|
||||
//
|
||||
void BitBufferInit( BitBuffer * bits, uint8_t * buffer, uint32_t byteSize )
|
||||
{
|
||||
bits->cur = buffer;
|
||||
bits->end = bits->cur + byteSize;
|
||||
bits->bitIndex = 0;
|
||||
bits->byteSize = byteSize;
|
||||
}
|
||||
|
||||
// BitBufferRead
|
||||
//
|
||||
uint32_t BitBufferRead( BitBuffer * bits, uint8_t numBits )
|
||||
{
|
||||
uint32_t returnBits;
|
||||
|
||||
//Assert( numBits <= 16 );
|
||||
|
||||
returnBits = ((uint32_t)bits->cur[0] << 16) | ((uint32_t)bits->cur[1] << 8) | ((uint32_t)bits->cur[2]);
|
||||
returnBits = returnBits << bits->bitIndex;
|
||||
returnBits &= 0x00FFFFFF;
|
||||
|
||||
bits->bitIndex += numBits;
|
||||
|
||||
returnBits = returnBits >> (24 - numBits);
|
||||
|
||||
bits->cur += (bits->bitIndex >> 3);
|
||||
bits->bitIndex &= 7;
|
||||
|
||||
//Assert( bits->cur <= bits->end );
|
||||
|
||||
return returnBits;
|
||||
}
|
||||
|
||||
// BitBufferReadSmall
|
||||
//
|
||||
// Reads up to 8 bits
|
||||
uint8_t BitBufferReadSmall( BitBuffer * bits, uint8_t numBits )
|
||||
{
|
||||
uint16_t returnBits;
|
||||
|
||||
//Assert( numBits <= 8 );
|
||||
|
||||
returnBits = (bits->cur[0] << 8) | bits->cur[1];
|
||||
returnBits = returnBits << bits->bitIndex;
|
||||
|
||||
bits->bitIndex += numBits;
|
||||
|
||||
returnBits = returnBits >> (16 - numBits);
|
||||
|
||||
bits->cur += (bits->bitIndex >> 3);
|
||||
bits->bitIndex &= 7;
|
||||
|
||||
//Assert( bits->cur <= bits->end );
|
||||
|
||||
return (uint8_t)returnBits;
|
||||
}
|
||||
|
||||
// BitBufferReadOne
|
||||
//
|
||||
// Reads one byte
|
||||
uint8_t BitBufferReadOne( BitBuffer * bits )
|
||||
{
|
||||
uint8_t returnBits;
|
||||
|
||||
returnBits = (bits->cur[0] >> (7 - bits->bitIndex)) & 1;
|
||||
|
||||
bits->bitIndex++;
|
||||
|
||||
bits->cur += (bits->bitIndex >> 3);
|
||||
bits->bitIndex &= 7;
|
||||
|
||||
//Assert( bits->cur <= bits->end );
|
||||
|
||||
return returnBits;
|
||||
}
|
||||
|
||||
// BitBufferPeek
|
||||
//
|
||||
uint32_t BitBufferPeek( BitBuffer * bits, uint8_t numBits )
|
||||
{
|
||||
return ((((((uint32_t) bits->cur[0] << 16) | ((uint32_t) bits->cur[1] << 8) |
|
||||
((uint32_t) bits->cur[2])) << bits->bitIndex) & 0x00FFFFFF) >> (24 - numBits));
|
||||
}
|
||||
|
||||
// BitBufferPeekOne
|
||||
//
|
||||
uint32_t BitBufferPeekOne( BitBuffer * bits )
|
||||
{
|
||||
return ((bits->cur[0] >> (7 - bits->bitIndex)) & 1);
|
||||
}
|
||||
|
||||
// BitBufferUnpackBERSize
|
||||
//
|
||||
uint32_t BitBufferUnpackBERSize( BitBuffer * bits )
|
||||
{
|
||||
uint32_t size;
|
||||
uint8_t tmp;
|
||||
|
||||
for ( size = 0, tmp = 0x80u; tmp &= 0x80u; size = (size << 7u) | (tmp & 0x7fu) )
|
||||
tmp = (uint8_t) BitBufferReadSmall( bits, 8 );
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
// BitBufferGetPosition
|
||||
//
|
||||
uint32_t BitBufferGetPosition( BitBuffer * bits )
|
||||
{
|
||||
uint8_t * begin;
|
||||
|
||||
begin = bits->end - bits->byteSize;
|
||||
|
||||
return ((uint32_t)(bits->cur - begin) * 8) + bits->bitIndex;
|
||||
}
|
||||
|
||||
// BitBufferByteAlign
|
||||
//
|
||||
void BitBufferByteAlign( BitBuffer * bits, int32_t addZeros )
|
||||
{
|
||||
// align bit buffer to next byte boundary, writing zeros if requested
|
||||
if ( bits->bitIndex == 0 )
|
||||
return;
|
||||
|
||||
if ( addZeros )
|
||||
BitBufferWrite( bits, 0, 8 - bits->bitIndex );
|
||||
else
|
||||
BitBufferAdvance( bits, 8 - bits->bitIndex );
|
||||
}
|
||||
|
||||
// BitBufferAdvance
|
||||
//
|
||||
void BitBufferAdvance( BitBuffer * bits, uint32_t numBits )
|
||||
{
|
||||
if ( numBits )
|
||||
{
|
||||
bits->bitIndex += numBits;
|
||||
bits->cur += (bits->bitIndex >> 3);
|
||||
bits->bitIndex &= 7;
|
||||
}
|
||||
}
|
||||
|
||||
// BitBufferRewind
|
||||
//
|
||||
void BitBufferRewind( BitBuffer * bits, uint32_t numBits )
|
||||
{
|
||||
uint32_t numBytes;
|
||||
|
||||
if ( numBits == 0 )
|
||||
return;
|
||||
|
||||
if ( bits->bitIndex >= numBits )
|
||||
{
|
||||
bits->bitIndex -= numBits;
|
||||
return;
|
||||
}
|
||||
|
||||
numBits -= bits->bitIndex;
|
||||
bits->bitIndex = 0;
|
||||
|
||||
numBytes = numBits / 8;
|
||||
numBits = numBits % 8;
|
||||
|
||||
bits->cur -= numBytes;
|
||||
|
||||
if ( numBits > 0 )
|
||||
{
|
||||
bits->bitIndex = 8 - numBits;
|
||||
bits->cur--;
|
||||
}
|
||||
|
||||
if ( bits->cur < (bits->end - bits->byteSize) )
|
||||
{
|
||||
//DebugCMsg("BitBufferRewind: Rewound too far.");
|
||||
|
||||
bits->cur = (bits->end - bits->byteSize);
|
||||
bits->bitIndex = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// BitBufferWrite
|
||||
//
|
||||
void BitBufferWrite( BitBuffer * bits, uint32_t bitValues, uint32_t numBits )
|
||||
{
|
||||
uint32_t invBitIndex;
|
||||
|
||||
RequireAction( bits != NULL, return; );
|
||||
RequireActionSilent( numBits > 0, return; );
|
||||
|
||||
invBitIndex = 8 - bits->bitIndex;
|
||||
|
||||
while ( numBits > 0 )
|
||||
{
|
||||
uint32_t tmp;
|
||||
uint8_t shift;
|
||||
uint8_t mask;
|
||||
uint32_t curNum;
|
||||
|
||||
curNum = MIN( invBitIndex, numBits );
|
||||
|
||||
tmp = bitValues >> (numBits - curNum);
|
||||
|
||||
shift = (uint8_t)(invBitIndex - curNum);
|
||||
mask = 0xffu >> (8 - curNum); // must be done in two steps to avoid compiler sequencing ambiguity
|
||||
mask <<= shift;
|
||||
|
||||
bits->cur[0] = (bits->cur[0] & ~mask) | (((uint8_t) tmp << shift) & mask);
|
||||
numBits -= curNum;
|
||||
|
||||
// increment to next byte if need be
|
||||
invBitIndex -= curNum;
|
||||
if ( invBitIndex == 0 )
|
||||
{
|
||||
invBitIndex = 8;
|
||||
bits->cur++;
|
||||
}
|
||||
}
|
||||
|
||||
bits->bitIndex = 8 - invBitIndex;
|
||||
}
|
||||
|
||||
void BitBufferReset( BitBuffer * bits )
|
||||
//void BitBufferInit( BitBuffer * bits, uint8_t * buffer, uint32_t byteSize )
|
||||
{
|
||||
bits->cur = bits->end - bits->byteSize;
|
||||
bits->bitIndex = 0;
|
||||
}
|
||||
|
||||
#if PRAGMA_MARK
|
||||
#pragma mark -
|
||||
#endif
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright (c) 2011 Apple Inc. All rights reserved.
|
||||
*
|
||||
* @APPLE_APACHE_LICENSE_HEADER_START@
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @APPLE_APACHE_LICENSE_HEADER_END@
|
||||
*/
|
||||
|
||||
/*=============================================================================
|
||||
File: ALACBitUtilities.h
|
||||
|
||||
$NoKeywords: $
|
||||
=============================================================================*/
|
||||
|
||||
#ifndef __ALACBITUTILITIES_H
|
||||
#define __ALACBITUTILITIES_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(x, y) ( (x)<(y) ?(x) :(y) )
|
||||
#endif //MIN
|
||||
#ifndef MAX
|
||||
#define MAX(x, y) ( (x)>(y) ?(x): (y) )
|
||||
#endif //MAX
|
||||
|
||||
#define RequireAction(condition, action) if (!(condition)) { action }
|
||||
#define RequireActionSilent(condition, action) if (!(condition)) { action }
|
||||
#define RequireNoErr(condition, action) if ((condition)) { action }
|
||||
|
||||
enum
|
||||
{
|
||||
ALAC_noErr = 0
|
||||
};
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
|
||||
ID_SCE = 0, /* Single Channel Element */
|
||||
ID_CPE = 1, /* Channel Pair Element */
|
||||
ID_CCE = 2, /* Coupling Channel Element */
|
||||
ID_LFE = 3, /* LFE Channel Element */
|
||||
ID_DSE = 4, /* not yet supported */
|
||||
ID_PCE = 5,
|
||||
ID_FIL = 6,
|
||||
ID_END = 7
|
||||
} ELEMENT_TYPE;
|
||||
|
||||
// types
|
||||
typedef struct BitBuffer
|
||||
{
|
||||
uint8_t * cur;
|
||||
uint8_t * end;
|
||||
uint32_t bitIndex;
|
||||
uint32_t byteSize;
|
||||
|
||||
} BitBuffer;
|
||||
|
||||
/*
|
||||
BitBuffer routines
|
||||
- these routines take a fixed size buffer and read/write to it
|
||||
- bounds checking must be done by the client
|
||||
*/
|
||||
void BitBufferInit( BitBuffer * bits, uint8_t * buffer, uint32_t byteSize );
|
||||
uint32_t BitBufferRead( BitBuffer * bits, uint8_t numBits ); // note: cannot read more than 16 bits at a time
|
||||
uint8_t BitBufferReadSmall( BitBuffer * bits, uint8_t numBits );
|
||||
uint8_t BitBufferReadOne( BitBuffer * bits );
|
||||
uint32_t BitBufferPeek( BitBuffer * bits, uint8_t numBits ); // note: cannot read more than 16 bits at a time
|
||||
uint32_t BitBufferPeekOne( BitBuffer * bits );
|
||||
uint32_t BitBufferUnpackBERSize( BitBuffer * bits );
|
||||
uint32_t BitBufferGetPosition( BitBuffer * bits );
|
||||
void BitBufferByteAlign( BitBuffer * bits, int32_t addZeros );
|
||||
void BitBufferAdvance( BitBuffer * bits, uint32_t numBits );
|
||||
void BitBufferRewind( BitBuffer * bits, uint32_t numBits );
|
||||
void BitBufferWrite( BitBuffer * bits, uint32_t value, uint32_t numBits );
|
||||
void BitBufferReset( BitBuffer * bits);
|
||||
|
||||
#endif /* __BITUTILITIES_H */
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (c) 2011 Apple Inc. All rights reserved.
|
||||
*
|
||||
* @APPLE_APACHE_LICENSE_HEADER_START@
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @APPLE_APACHE_LICENSE_HEADER_END@
|
||||
*/
|
||||
|
||||
/*
|
||||
File: ALACDecoder.h
|
||||
*/
|
||||
|
||||
#ifndef _ALACDECODER_H
|
||||
#define _ALACDECODER_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "ALACAudioTypes.h"
|
||||
|
||||
struct BitBuffer;
|
||||
|
||||
class ALACDecoder
|
||||
{
|
||||
public:
|
||||
ALACDecoder();
|
||||
~ALACDecoder();
|
||||
|
||||
int32_t Init( void * inMagicCookie, uint32_t inMagicCookieSize );
|
||||
int32_t Decode( struct BitBuffer * bits, uint8_t * sampleBuffer, uint32_t numSamples, uint32_t numChannels, uint32_t * outNumSamples );
|
||||
|
||||
public:
|
||||
// decoding parameters (public for use in the analyzer)
|
||||
ALACSpecificConfig mConfig;
|
||||
|
||||
protected:
|
||||
int32_t FillElement( struct BitBuffer * bits );
|
||||
int32_t DataStreamElement( struct BitBuffer * bits );
|
||||
|
||||
uint16_t mActiveElements;
|
||||
|
||||
// decoding buffers
|
||||
int32_t * mMixBufferU;
|
||||
int32_t * mMixBufferV;
|
||||
int32_t * mPredictor;
|
||||
uint16_t * mShiftBuffer; // note: this points to mPredictor's memory but different
|
||||
// variable for clarity and type difference
|
||||
};
|
||||
|
||||
#endif /* _ALACDECODER_H */
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (c) 2011 Apple Inc. All rights reserved.
|
||||
*
|
||||
* @APPLE_APACHE_LICENSE_HEADER_START@
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @APPLE_APACHE_LICENSE_HEADER_END@
|
||||
*/
|
||||
|
||||
/*
|
||||
File: ALACEncoder.h
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "ALACAudioTypes.h"
|
||||
|
||||
|
||||
struct BitBuffer;
|
||||
|
||||
class ALACEncoder
|
||||
{
|
||||
public:
|
||||
ALACEncoder();
|
||||
virtual ~ALACEncoder();
|
||||
|
||||
virtual int32_t Encode(AudioFormatDescription theInputFormat, AudioFormatDescription theOutputFormat,
|
||||
unsigned char * theReadBuffer, unsigned char * theWriteBuffer, int32_t * ioNumBytes);
|
||||
virtual int32_t Finish( );
|
||||
|
||||
void SetFastMode( bool fast ) { mFastMode = fast; };
|
||||
|
||||
// this must be called *before* InitializeEncoder()
|
||||
void SetFrameSize( uint32_t frameSize ) { mFrameSize = frameSize; };
|
||||
|
||||
void GetConfig( ALACSpecificConfig & config );
|
||||
uint32_t GetMagicCookieSize(uint32_t inNumChannels);
|
||||
void GetMagicCookie( void * config, uint32_t * ioSize );
|
||||
|
||||
virtual int32_t InitializeEncoder(AudioFormatDescription theOutputFormat);
|
||||
|
||||
protected:
|
||||
virtual void GetSourceFormat( const AudioFormatDescription * source, AudioFormatDescription * output );
|
||||
|
||||
int32_t EncodeStereo( struct BitBuffer * bitstream, void * input, uint32_t stride, uint32_t channelIndex, uint32_t numSamples );
|
||||
int32_t EncodeStereoFast( struct BitBuffer * bitstream, void * input, uint32_t stride, uint32_t channelIndex, uint32_t numSamples );
|
||||
int32_t EncodeStereoEscape( struct BitBuffer * bitstream, void * input, uint32_t stride, uint32_t numSamples );
|
||||
int32_t EncodeMono( struct BitBuffer * bitstream, void * input, uint32_t stride, uint32_t channelIndex, uint32_t numSamples );
|
||||
|
||||
|
||||
// ALAC encoder parameters
|
||||
int16_t mBitDepth;
|
||||
bool mFastMode;
|
||||
|
||||
// encoding state
|
||||
int16_t mLastMixRes[kALACMaxChannels];
|
||||
|
||||
// encoding buffers
|
||||
int32_t * mMixBufferU;
|
||||
int32_t * mMixBufferV;
|
||||
int32_t * mPredictorU;
|
||||
int32_t * mPredictorV;
|
||||
uint16_t * mShiftBufferUV;
|
||||
|
||||
uint8_t * mWorkBuffer;
|
||||
|
||||
// per-channel coefficients buffers
|
||||
int16_t mCoefsU[kALACMaxChannels][kALACMaxSearches][kALACMaxCoefs];
|
||||
int16_t mCoefsV[kALACMaxChannels][kALACMaxSearches][kALACMaxCoefs];
|
||||
|
||||
// encoding statistics
|
||||
uint32_t mTotalBytesGenerated;
|
||||
uint32_t mAvgBitRate;
|
||||
uint32_t mMaxFrameBytes;
|
||||
uint32_t mFrameSize;
|
||||
uint32_t mMaxOutputBytes;
|
||||
uint32_t mNumChannels;
|
||||
uint32_t mOutputSampleRate;
|
||||
};
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 2011 Apple Inc. All rights reserved.
|
||||
** Copyright (C) 2013 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
*
|
||||
* @APPLE_APACHE_LICENSE_HEADER_START@
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @APPLE_APACHE_LICENSE_HEADER_END@
|
||||
*/
|
||||
|
||||
//
|
||||
// EndianPortable.h
|
||||
//
|
||||
// Copyright 2011 Apple Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef _EndianPortable_h
|
||||
#define _EndianPortable_h
|
||||
|
||||
#include <sfendian.h>
|
||||
|
||||
#define Swap16NtoB(x) H2BE_16(x)
|
||||
#define Swap16BtoN(x) BE2H_16(x)
|
||||
|
||||
#define Swap32NtoB(x) H2BE_32(x)
|
||||
#define Swap32BtoN(x) BE2H_32(x)
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,170 @@
|
||||
Apache License
|
||||
|
||||
Version 2.0, January 2004
|
||||
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction, and
|
||||
distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by the
|
||||
copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all other
|
||||
entities that control, are controlled by, or are under common control
|
||||
with that entity. For the purposes of this definition, "control" means
|
||||
(i) the power, direct or indirect, to cause the direction or management
|
||||
of such entity, whether by contract or otherwise, or (ii) ownership
|
||||
of fifty percent (50%) or more of the outstanding shares, or (iii)
|
||||
beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity exercising
|
||||
permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation source,
|
||||
and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but not
|
||||
limited to compiled object code, generated documentation, and
|
||||
conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or Object
|
||||
form, made available under the License, as indicated by a copyright
|
||||
notice that is included in or attached to the work (an example is
|
||||
provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including the original
|
||||
version of the Work and any modifications or additions to that Work or
|
||||
Derivative Works thereof, that is intentionally submitted to Licensor
|
||||
for inclusion in the Work by the copyright owner or by an individual
|
||||
or Legal Entity authorized to submit on behalf of the copyright owner.
|
||||
For the purposes of this definition, "submitted" means any form of
|
||||
electronic, verbal, or written communication sent to the Licensor
|
||||
or its representatives, including but not limited to communication
|
||||
on electronic mailing lists, source code control systems, and issue
|
||||
tracking systems that are managed by, or on behalf of, the Licensor
|
||||
for the purpose of discussing and improving the Work, but excluding
|
||||
communication that is conspicuously marked or otherwise designated in
|
||||
writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions
|
||||
of this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of, publicly
|
||||
display, publicly perform, sublicense, and distribute the Work and such
|
||||
Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except
|
||||
as stated in this section) patent license to make, have made, use,
|
||||
offer to sell, sell, import, and otherwise transfer the Work, where
|
||||
such license applies only to those patent claims licensable by such
|
||||
Contributor that are necessarily infringed by their Contribution(s)
|
||||
alone or by combination of their Contribution(s) with the Work to which
|
||||
such Contribution(s) was submitted. If You institute patent litigation
|
||||
against any entity (including a cross-claim or counterclaim in a
|
||||
lawsuit) alleging that the Work or a Contribution incorporated within
|
||||
the Work constitutes direct or contributory patent infringement, then
|
||||
any patent licenses granted to You under this License for that Work
|
||||
shall terminate as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You meet the
|
||||
following conditions:
|
||||
|
||||
You must give any other recipients of the Work or Derivative Works a
|
||||
copy of this License; and
|
||||
|
||||
You must cause any modified files to carry prominent notices stating
|
||||
that You changed the files; and
|
||||
|
||||
You must retain, in the Source form of any Derivative Works that You
|
||||
distribute, all copyright, patent, trademark, and attribution notices
|
||||
from the Source form of the Work, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works; and
|
||||
|
||||
If the Work includes a "NOTICE" text file as part of its distribution,
|
||||
then any Derivative Works that You distribute must include a readable
|
||||
copy of the attribution notices contained within such NOTICE file,
|
||||
excluding those notices that do not pertain to any part of the
|
||||
Derivative Works, in at least one of the following places: within a
|
||||
NOTICE text file distributed as part of the Derivative Works; within
|
||||
the Source form or documentation, if provided along with the Derivative
|
||||
Works; or, within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents of the
|
||||
NOTICE file are for informational purposes only and do not modify the
|
||||
License. You may add Your own attribution notices within Derivative
|
||||
Works that You distribute, alongside or as an addendum to the NOTICE
|
||||
text from the Work, provided that such additional attribution notices
|
||||
cannot be construed as modifying the License. You may add Your own
|
||||
copyright statement to Your modifications and may provide additional
|
||||
or different license terms and conditions for use, reproduction, or
|
||||
distribution of Your modifications, or for any such Derivative Works as
|
||||
a whole, provided Your use, reproduction, and distribution of the Work
|
||||
otherwise complies with the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work by
|
||||
You to the Licensor shall be under the terms and conditions of this
|
||||
License, without any additional terms or conditions. Notwithstanding
|
||||
the above, nothing herein shall supersede or modify the terms of any
|
||||
separate license agreement you may have executed with Licensor regarding
|
||||
such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or agreed
|
||||
to in writing, Licensor provides the Work (and each Contributor
|
||||
provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied, including, without
|
||||
limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT,
|
||||
MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
|
||||
solely responsible for determining the appropriateness of using or
|
||||
redistributing the Work and assume any risks associated with Your
|
||||
exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise, unless
|
||||
required by applicable law (such as deliberate and grossly negligent
|
||||
acts) or agreed to in writing, shall any Contributor be liable to You
|
||||
for damages, including any direct, indirect, special, incidental, or
|
||||
consequential damages of any character arising as a result of this
|
||||
License or out of the use or inability to use the Work (including but
|
||||
not limited to damages for loss of goodwill, work stoppage, computer
|
||||
failure or malfunction, or any and all other commercial damages or
|
||||
losses), even if such Contributor has been advised of the possibility of
|
||||
such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing the
|
||||
Work or Derivative Works thereof, You may choose to offer, and charge a
|
||||
fee for, acceptance of support, warranty, indemnity, or other liability
|
||||
obligations and/or rights consistent with this License. However, in
|
||||
accepting such obligations, You may act only on Your own behalf and
|
||||
on Your sole responsibility, not on behalf of any other Contributor,
|
||||
and only if You agree to indemnify, defend, and hold each Contributor
|
||||
harmless for any liability incurred by, or claims asserted against, such
|
||||
Contributor by reason of your accepting any such warranty or additional
|
||||
liability.
|
||||
@@ -0,0 +1,355 @@
|
||||
/*
|
||||
* Copyright (c) 2011 Apple Inc. All rights reserved.
|
||||
*
|
||||
* @APPLE_APACHE_LICENSE_HEADER_START@
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @APPLE_APACHE_LICENSE_HEADER_END@
|
||||
*/
|
||||
|
||||
/*
|
||||
File: ag_dec.c
|
||||
|
||||
Contains: Adaptive Golomb decode routines.
|
||||
|
||||
Copyright: (c) 2001-2011 Apple, Inc.
|
||||
*/
|
||||
|
||||
#include "aglib.h"
|
||||
#include "ALACBitUtilities.h"
|
||||
#include "ALACAudioTypes.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define CODE_TO_LONG_MAXBITS 32
|
||||
#define N_MAX_MEAN_CLAMP 0xffff
|
||||
#define N_MEAN_CLAMP_VAL 0xffff
|
||||
#define REPORT_VAL 40
|
||||
|
||||
#if __GNUC__
|
||||
#define ALWAYS_INLINE __attribute__((always_inline))
|
||||
#else
|
||||
#define ALWAYS_INLINE
|
||||
#endif
|
||||
|
||||
/* And on the subject of the CodeWarrior x86 compiler and inlining, I reworked a lot of this
|
||||
to help the compiler out. In many cases this required manual inlining or a macro. Sorry
|
||||
if it is ugly but the performance gains are well worth it.
|
||||
- WSK 5/19/04
|
||||
*/
|
||||
|
||||
void set_standard_ag_params(AGParamRecPtr params, uint32_t fullwidth, uint32_t sectorwidth)
|
||||
{
|
||||
/* Use
|
||||
fullwidth = sectorwidth = numOfSamples, for analog 1-dimensional type-short data,
|
||||
but use
|
||||
fullwidth = full image width, sectorwidth = sector (patch) width
|
||||
for such as image (2-dim.) data.
|
||||
*/
|
||||
set_ag_params( params, MB0, PB0, KB0, fullwidth, sectorwidth, MAX_RUN_DEFAULT );
|
||||
}
|
||||
|
||||
void set_ag_params(AGParamRecPtr params, uint32_t m, uint32_t p, uint32_t k, uint32_t f, uint32_t s, uint32_t maxrun)
|
||||
{
|
||||
params->mb = params->mb0 = m;
|
||||
params->pb = p;
|
||||
params->kb = k;
|
||||
params->wb = (1u<<params->kb)-1;
|
||||
params->qb = QB-params->pb;
|
||||
params->fw = f;
|
||||
params->sw = s;
|
||||
params->maxrun = maxrun;
|
||||
}
|
||||
|
||||
#if PRAGMA_MARK
|
||||
#pragma mark -
|
||||
#endif
|
||||
|
||||
|
||||
// note: implementing this with some kind of "count leading zeros" assembly is a big performance win
|
||||
static inline int32_t lead( int32_t m )
|
||||
{
|
||||
long j;
|
||||
unsigned long c = (1ul << 31);
|
||||
|
||||
for(j=0; j < 32; j++)
|
||||
{
|
||||
if((c & m) != 0)
|
||||
break;
|
||||
c >>= 1;
|
||||
}
|
||||
return (j);
|
||||
}
|
||||
|
||||
#define arithmin(a, b) ((a) < (b) ? (a) : (b))
|
||||
|
||||
static inline int32_t ALWAYS_INLINE lg3a( int32_t x)
|
||||
{
|
||||
int32_t result;
|
||||
|
||||
x += 3;
|
||||
result = lead(x);
|
||||
|
||||
return 31 - result;
|
||||
}
|
||||
|
||||
static inline uint32_t ALWAYS_INLINE read32bit( uint8_t * buffer )
|
||||
{
|
||||
// embedded CPUs typically can't read unaligned 32-bit words so just read the bytes
|
||||
uint32_t value;
|
||||
|
||||
value = ((uint32_t)buffer[0] << 24) | ((uint32_t)buffer[1] << 16) |
|
||||
((uint32_t)buffer[2] << 8) | (uint32_t)buffer[3];
|
||||
return value;
|
||||
|
||||
}
|
||||
|
||||
#if PRAGMA_MARK
|
||||
#pragma mark -
|
||||
#endif
|
||||
|
||||
#define get_next_fromlong(inlong, suff) ((inlong) >> (32 - (suff)))
|
||||
|
||||
|
||||
static inline uint32_t ALWAYS_INLINE
|
||||
getstreambits( uint8_t *in, int32_t bitoffset, int32_t numbits )
|
||||
{
|
||||
uint32_t load1, load2;
|
||||
uint32_t byteoffset = bitoffset / 8;
|
||||
uint32_t result;
|
||||
|
||||
//Assert( numbits <= 32 );
|
||||
|
||||
load1 = read32bit( in + byteoffset );
|
||||
|
||||
if ( (numbits + (bitoffset & 0x7)) > 32)
|
||||
{
|
||||
int32_t load2shift;
|
||||
|
||||
result = load1 << (bitoffset & 0x7);
|
||||
load2 = (uint32_t) in[byteoffset+4];
|
||||
load2shift = (8-(numbits + (bitoffset & 0x7)-32));
|
||||
load2 >>= load2shift;
|
||||
result >>= (32-numbits);
|
||||
result |= load2;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = load1 >> (32-numbits-(bitoffset & 7));
|
||||
}
|
||||
|
||||
// a shift of >= "the number of bits in the type of the value being shifted" results in undefined
|
||||
// behavior so don't try to shift by 32
|
||||
if ( numbits != (sizeof(result) * 8) )
|
||||
result &= ~(0xfffffffful << numbits);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static inline int32_t dyn_get(unsigned char *in, uint32_t *bitPos, uint32_t m, uint32_t k)
|
||||
{
|
||||
uint32_t tempbits = *bitPos;
|
||||
uint32_t result;
|
||||
uint32_t pre = 0, v;
|
||||
uint32_t streamlong;
|
||||
|
||||
streamlong = read32bit( in + (tempbits >> 3) );
|
||||
streamlong <<= (tempbits & 7);
|
||||
|
||||
/* find the number of bits in the prefix */
|
||||
{
|
||||
uint32_t notI = ~streamlong;
|
||||
pre = lead( notI);
|
||||
}
|
||||
|
||||
if(pre >= MAX_PREFIX_16)
|
||||
{
|
||||
pre = MAX_PREFIX_16;
|
||||
tempbits += pre;
|
||||
streamlong <<= pre;
|
||||
result = get_next_fromlong(streamlong,MAX_DATATYPE_BITS_16);
|
||||
tempbits += MAX_DATATYPE_BITS_16;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// all of the bits must fit within the long we have loaded
|
||||
//Assert(pre+1+k <= 32);
|
||||
|
||||
tempbits += pre;
|
||||
tempbits += 1;
|
||||
streamlong <<= pre+1;
|
||||
v = get_next_fromlong(streamlong, k);
|
||||
tempbits += k;
|
||||
|
||||
result = pre*m + v-1;
|
||||
|
||||
if(v<2) {
|
||||
result -= (v-1);
|
||||
tempbits -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
*bitPos = tempbits;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static inline int32_t dyn_get_32bit( uint8_t * in, uint32_t * bitPos, int32_t m, int32_t k, int32_t maxbits )
|
||||
{
|
||||
uint32_t tempbits = *bitPos;
|
||||
uint32_t v;
|
||||
uint32_t streamlong;
|
||||
uint32_t result;
|
||||
|
||||
streamlong = read32bit( in + (tempbits >> 3) );
|
||||
streamlong <<= (tempbits & 7);
|
||||
|
||||
/* find the number of bits in the prefix */
|
||||
{
|
||||
uint32_t notI = ~streamlong;
|
||||
result = lead( notI);
|
||||
}
|
||||
|
||||
if(result >= MAX_PREFIX_32)
|
||||
{
|
||||
result = getstreambits(in, tempbits+MAX_PREFIX_32, maxbits);
|
||||
tempbits += MAX_PREFIX_32 + maxbits;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* all of the bits must fit within the long we have loaded*/
|
||||
//Assert(k<=14);
|
||||
//Assert(result<MAX_PREFIX_32);
|
||||
//Assert(result+1+k <= 32);
|
||||
|
||||
tempbits += result;
|
||||
tempbits += 1;
|
||||
|
||||
if (k != 1)
|
||||
{
|
||||
streamlong <<= result+1;
|
||||
v = get_next_fromlong(streamlong, k);
|
||||
tempbits += k;
|
||||
tempbits -= 1;
|
||||
result = result*m;
|
||||
|
||||
if(v>=2)
|
||||
{
|
||||
result += (v-1);
|
||||
tempbits += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*bitPos = tempbits;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int32_t dyn_decomp( AGParamRecPtr params, BitBuffer * bitstream, int32_t * pc, int32_t numSamples, int32_t maxSize, uint32_t * outNumBits )
|
||||
{
|
||||
uint8_t *in;
|
||||
int32_t *outPtr = pc;
|
||||
uint32_t bitPos, startPos, maxPos;
|
||||
uint32_t j, m, k, n, c, mz;
|
||||
int32_t del, zmode;
|
||||
uint32_t mb;
|
||||
uint32_t pb_local = params->pb;
|
||||
uint32_t kb_local = params->kb;
|
||||
uint32_t wb_local = params->wb;
|
||||
int32_t status;
|
||||
|
||||
RequireAction( (bitstream != NULL) && (pc != NULL) && (outNumBits != NULL), return kALAC_ParamError; );
|
||||
*outNumBits = 0;
|
||||
|
||||
in = bitstream->cur;
|
||||
startPos = bitstream->bitIndex;
|
||||
maxPos = bitstream->byteSize * 8;
|
||||
bitPos = startPos;
|
||||
|
||||
mb = params->mb0;
|
||||
zmode = 0;
|
||||
|
||||
c = 0;
|
||||
status = ALAC_noErr;
|
||||
|
||||
while (c < (uint32_t) numSamples)
|
||||
{
|
||||
// bail if we've run off the end of the buffer
|
||||
RequireAction( bitPos < maxPos, status = kALAC_ParamError; goto Exit; );
|
||||
|
||||
m = (mb)>>QBSHIFT;
|
||||
k = lg3a(m);
|
||||
|
||||
k = arithmin(k, kb_local);
|
||||
m = (1<<k)-1;
|
||||
|
||||
n = dyn_get_32bit( in, &bitPos, m, k, maxSize );
|
||||
|
||||
// least significant bit is sign bit
|
||||
{
|
||||
uint32_t ndecode = n + zmode;
|
||||
int32_t multiplier = (- (ndecode&1));
|
||||
|
||||
multiplier |= 1;
|
||||
del = ((ndecode+1) >> 1) * (multiplier);
|
||||
}
|
||||
|
||||
*outPtr++ = del;
|
||||
|
||||
c++;
|
||||
|
||||
mb = pb_local*(n+zmode) + mb - ((pb_local*mb)>>QBSHIFT);
|
||||
|
||||
// update mean tracking
|
||||
if (n > N_MAX_MEAN_CLAMP)
|
||||
mb = N_MEAN_CLAMP_VAL;
|
||||
|
||||
zmode = 0;
|
||||
|
||||
if (((mb << MMULSHIFT) < QB) && (c < (uint32_t) numSamples))
|
||||
{
|
||||
zmode = 1;
|
||||
k = lead(mb) - BITOFF+((mb+MOFF)>>MDENSHIFT);
|
||||
mz = ((1<<k)-1) & wb_local;
|
||||
|
||||
n = dyn_get(in, &bitPos, mz, k);
|
||||
|
||||
RequireAction(c+n <= (uint32_t) numSamples, status = kALAC_ParamError; goto Exit; );
|
||||
|
||||
for(j=0; j < n; j++)
|
||||
{
|
||||
*outPtr++ = 0;
|
||||
++c;
|
||||
}
|
||||
|
||||
if(n >= 65535)
|
||||
zmode = 0;
|
||||
|
||||
mb = 0;
|
||||
}
|
||||
}
|
||||
|
||||
Exit:
|
||||
*outNumBits = (bitPos - startPos);
|
||||
BitBufferAdvance( bitstream, *outNumBits );
|
||||
RequireAction( bitstream->cur <= bitstream->end, status = kALAC_ParamError; );
|
||||
|
||||
return status;
|
||||
}
|
||||
@@ -0,0 +1,360 @@
|
||||
/*
|
||||
* Copyright (c) 2011 Apple Inc. All rights reserved.
|
||||
* Copyright (C) 2013 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
*
|
||||
* @APPLE_APACHE_LICENSE_HEADER_START@
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @APPLE_APACHE_LICENSE_HEADER_END@
|
||||
*/
|
||||
|
||||
/*
|
||||
File: ag_enc.c
|
||||
|
||||
Contains: Adaptive Golomb encode routines.
|
||||
|
||||
Copyright: (c) 2001-2011 Apple, Inc.
|
||||
*/
|
||||
|
||||
#include "aglib.h"
|
||||
#include "ALACBitUtilities.h"
|
||||
#include "EndianPortable.h"
|
||||
#include "ALACAudioTypes.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define CODE_TO_LONG_MAXBITS 32
|
||||
#define N_MAX_MEAN_CLAMP 0xffff
|
||||
#define N_MEAN_CLAMP_VAL 0xffff
|
||||
#define REPORT_VAL 40
|
||||
|
||||
#if __GNUC__
|
||||
#define ALWAYS_INLINE __attribute__((always_inline))
|
||||
#else
|
||||
#define ALWAYS_INLINE
|
||||
#endif
|
||||
|
||||
|
||||
/* And on the subject of the CodeWarrior x86 compiler and inlining, I reworked a lot of this
|
||||
to help the compiler out. In many cases this required manual inlining or a macro. Sorry
|
||||
if it is ugly but the performance gains are well worth it.
|
||||
- WSK 5/19/04
|
||||
*/
|
||||
|
||||
// note: implementing this with some kind of "count leading zeros" assembly is a big performance win
|
||||
static inline int32_t lead( int32_t m )
|
||||
{
|
||||
long j;
|
||||
unsigned long c = (1ul << 31);
|
||||
|
||||
for(j=0; j < 32; j++)
|
||||
{
|
||||
if((c & m) != 0)
|
||||
break;
|
||||
c >>= 1;
|
||||
}
|
||||
return (j);
|
||||
}
|
||||
|
||||
#define arithmin(a, b) ((a) < (b) ? (a) : (b))
|
||||
|
||||
static inline int32_t ALWAYS_INLINE lg3a( int32_t x)
|
||||
{
|
||||
int32_t result;
|
||||
|
||||
x += 3;
|
||||
result = lead(x);
|
||||
|
||||
return 31 - result;
|
||||
}
|
||||
|
||||
static inline int32_t ALWAYS_INLINE abs_func( int32_t a )
|
||||
{
|
||||
// note: the CW PPC intrinsic __abs() turns into these instructions so no need to try and use it
|
||||
int32_t isneg = a >> 31;
|
||||
int32_t xorval = a ^ isneg;
|
||||
int32_t result = xorval-isneg;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline uint32_t ALWAYS_INLINE read32bit( uint8_t * buffer )
|
||||
{
|
||||
// embedded CPUs typically can't read unaligned 32-bit words so just read the bytes
|
||||
uint32_t value;
|
||||
|
||||
value = ((uint32_t)buffer[0] << 24) | ((uint32_t)buffer[1] << 16) |
|
||||
((uint32_t)buffer[2] << 8) | (uint32_t)buffer[3];
|
||||
return value;
|
||||
}
|
||||
|
||||
#if PRAGMA_MARK
|
||||
#pragma mark -
|
||||
#endif
|
||||
|
||||
static inline int32_t dyn_code(int32_t m, int32_t k, int32_t n, uint32_t *outNumBits)
|
||||
{
|
||||
uint32_t divx, mod, de;
|
||||
uint32_t numBits;
|
||||
uint32_t value;
|
||||
|
||||
//Assert( n >= 0 );
|
||||
|
||||
divx = n/m;
|
||||
|
||||
if(divx >= MAX_PREFIX_16)
|
||||
{
|
||||
numBits = MAX_PREFIX_16 + MAX_DATATYPE_BITS_16;
|
||||
value = (((1<<MAX_PREFIX_16)-1)<<MAX_DATATYPE_BITS_16) + n;
|
||||
}
|
||||
else
|
||||
{
|
||||
mod = n%m;
|
||||
de = (mod == 0);
|
||||
numBits = divx + k + 1 - de;
|
||||
value = (((1<<divx)-1)<<(numBits-divx)) + mod + 1 - de;
|
||||
|
||||
// if coding this way is bigger than doing escape, then do escape
|
||||
if (numBits > MAX_PREFIX_16 + MAX_DATATYPE_BITS_16)
|
||||
{
|
||||
numBits = MAX_PREFIX_16 + MAX_DATATYPE_BITS_16;
|
||||
value = (((1<<MAX_PREFIX_16)-1)<<MAX_DATATYPE_BITS_16) + n;
|
||||
}
|
||||
}
|
||||
|
||||
*outNumBits = numBits;
|
||||
|
||||
return (int32_t) value;
|
||||
}
|
||||
|
||||
|
||||
static inline int32_t dyn_code_32bit(int32_t maxbits, uint32_t m, uint32_t k, uint32_t n, uint32_t *outNumBits, uint32_t *outValue, uint32_t *overflow, uint32_t *overflowbits)
|
||||
{
|
||||
uint32_t divx, mod, de;
|
||||
uint32_t numBits;
|
||||
uint32_t value;
|
||||
int32_t didOverflow = 0;
|
||||
|
||||
divx = n/m;
|
||||
|
||||
if (divx < MAX_PREFIX_32)
|
||||
{
|
||||
mod = n - (m * divx);
|
||||
|
||||
de = (mod == 0);
|
||||
numBits = divx + k + 1 - de;
|
||||
value = (((1<<divx)-1)<<(numBits-divx)) + mod + 1 - de;
|
||||
if (numBits > 25)
|
||||
goto codeasescape;
|
||||
}
|
||||
else
|
||||
{
|
||||
codeasescape:
|
||||
numBits = MAX_PREFIX_32;
|
||||
value = (((1<<MAX_PREFIX_32)-1));
|
||||
*overflow = n;
|
||||
*overflowbits = maxbits;
|
||||
didOverflow = 1;
|
||||
}
|
||||
|
||||
*outNumBits = numBits;
|
||||
*outValue = value;
|
||||
|
||||
return didOverflow;
|
||||
}
|
||||
|
||||
|
||||
static inline void ALWAYS_INLINE dyn_jam_noDeref(unsigned char *out, uint32_t bitPos, uint32_t numBits, uint32_t value)
|
||||
{
|
||||
uint32_t mask;
|
||||
uint32_t curr;
|
||||
uint32_t shift;
|
||||
|
||||
//Assert( numBits <= 32 );
|
||||
|
||||
curr = psf_get_be32 (out, bitPos >> 3);
|
||||
|
||||
shift = 32 - (bitPos & 7) - numBits;
|
||||
|
||||
mask = ~0u >> (32 - numBits); // mask must be created in two steps to avoid compiler sequencing ambiguity
|
||||
mask <<= shift;
|
||||
|
||||
value = (value << shift) & mask;
|
||||
value |= curr & ~mask;
|
||||
|
||||
psf_put_be32 (out, bitPos >> 3, value) ;
|
||||
}
|
||||
|
||||
|
||||
static inline void ALWAYS_INLINE dyn_jam_noDeref_large(unsigned char *out, uint32_t bitPos, uint32_t numBits, uint32_t value)
|
||||
{
|
||||
uint32_t w;
|
||||
uint32_t curr;
|
||||
uint32_t mask;
|
||||
int32_t shiftvalue = (32 - (bitPos&7) - numBits);
|
||||
|
||||
//Assert(numBits <= 32);
|
||||
|
||||
curr = psf_get_be32 (out, bitPos >> 3);
|
||||
|
||||
if (shiftvalue < 0)
|
||||
{
|
||||
uint8_t tailbyte;
|
||||
uint8_t *tailptr;
|
||||
|
||||
w = value >> -shiftvalue;
|
||||
mask = ~0u >> -shiftvalue;
|
||||
w |= (curr & ~mask);
|
||||
|
||||
tailptr = out + (bitPos>>3) + 4;
|
||||
tailbyte = (value << ((8+shiftvalue))) & 0xff;
|
||||
*tailptr = (uint8_t)tailbyte;
|
||||
}
|
||||
else
|
||||
{
|
||||
mask = ~0u >> (32 - numBits);
|
||||
mask <<= shiftvalue; // mask must be created in two steps to avoid compiler sequencing ambiguity
|
||||
|
||||
w = (value << shiftvalue) & mask;
|
||||
w |= curr & ~mask;
|
||||
}
|
||||
|
||||
psf_put_be32 (out, bitPos >> 3, w) ;
|
||||
}
|
||||
|
||||
|
||||
int32_t dyn_comp( AGParamRecPtr params, int32_t * pc, BitBuffer * bitstream, int32_t numSamples, int32_t bitSize, uint32_t * outNumBits )
|
||||
{
|
||||
unsigned char * out;
|
||||
uint32_t bitPos, startPos;
|
||||
uint32_t m, k, n, c, mz, nz;
|
||||
uint32_t numBits;
|
||||
uint32_t value;
|
||||
int32_t del, zmode;
|
||||
uint32_t overflow, overflowbits;
|
||||
int32_t status;
|
||||
|
||||
// shadow the variables in params so there's not the dereferencing overhead
|
||||
uint32_t mb, pb, kb, wb;
|
||||
int32_t rowPos = 0;
|
||||
int32_t rowSize = params->sw;
|
||||
int32_t rowJump = (params->fw) - rowSize;
|
||||
int32_t * inPtr = pc;
|
||||
|
||||
*outNumBits = 0;
|
||||
RequireAction( (bitSize >= 1) && (bitSize <= 32), return kALAC_ParamError; );
|
||||
|
||||
out = bitstream->cur;
|
||||
startPos = bitstream->bitIndex;
|
||||
bitPos = startPos;
|
||||
|
||||
mb = params->mb = params->mb0;
|
||||
pb = params->pb;
|
||||
kb = params->kb;
|
||||
wb = params->wb;
|
||||
zmode = 0;
|
||||
|
||||
c=0;
|
||||
status = ALAC_noErr;
|
||||
|
||||
while (c < (uint32_t) numSamples)
|
||||
{
|
||||
m = mb >> QBSHIFT;
|
||||
k = lg3a(m);
|
||||
if ( k > kb)
|
||||
{
|
||||
k = kb;
|
||||
}
|
||||
m = (1<<k)-1;
|
||||
|
||||
del = *inPtr++;
|
||||
rowPos++;
|
||||
|
||||
n = (abs_func(del) << 1) - ((del >> 31) & 1) - zmode;
|
||||
//Assert( 32-lead(n) <= bitSize );
|
||||
|
||||
if ( dyn_code_32bit(bitSize, m, k, n, &numBits, &value, &overflow, &overflowbits) )
|
||||
{
|
||||
dyn_jam_noDeref(out, bitPos, numBits, value);
|
||||
bitPos += numBits;
|
||||
dyn_jam_noDeref_large(out, bitPos, overflowbits, overflow);
|
||||
bitPos += overflowbits;
|
||||
}
|
||||
else
|
||||
{
|
||||
dyn_jam_noDeref(out, bitPos, numBits, value);
|
||||
bitPos += numBits;
|
||||
}
|
||||
|
||||
c++;
|
||||
if ( rowPos >= rowSize)
|
||||
{
|
||||
rowPos = 0;
|
||||
inPtr += rowJump;
|
||||
}
|
||||
|
||||
mb = pb * (n + zmode) + mb - ((pb *mb)>>QBSHIFT);
|
||||
|
||||
// update mean tracking if it's overflowed
|
||||
if (n > N_MAX_MEAN_CLAMP)
|
||||
mb = N_MEAN_CLAMP_VAL;
|
||||
|
||||
zmode = 0;
|
||||
|
||||
RequireAction(c <= (uint32_t) numSamples, status = kALAC_ParamError; goto Exit; );
|
||||
|
||||
if (((mb << MMULSHIFT) < QB) && (c < (uint32_t) numSamples))
|
||||
{
|
||||
zmode = 1;
|
||||
nz = 0;
|
||||
|
||||
while(c<(uint32_t) numSamples && *inPtr == 0)
|
||||
{
|
||||
/* Take care of wrap-around globals. */
|
||||
++inPtr;
|
||||
++nz;
|
||||
++c;
|
||||
if ( ++rowPos >= rowSize)
|
||||
{
|
||||
rowPos = 0;
|
||||
inPtr += rowJump;
|
||||
}
|
||||
|
||||
if(nz >= 65535)
|
||||
{
|
||||
zmode = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
k = lead(mb) - BITOFF+((mb+MOFF)>>MDENSHIFT);
|
||||
mz = ((1<<k)-1) & wb;
|
||||
|
||||
value = dyn_code(mz, k, nz, &numBits);
|
||||
dyn_jam_noDeref(out, bitPos, numBits, value);
|
||||
bitPos += numBits;
|
||||
|
||||
mb = 0;
|
||||
}
|
||||
}
|
||||
|
||||
*outNumBits = (bitPos - startPos);
|
||||
BitBufferAdvance( bitstream, *outNumBits );
|
||||
|
||||
Exit:
|
||||
return status;
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (c) 2011 Apple Inc. All rights reserved.
|
||||
*
|
||||
* @APPLE_APACHE_LICENSE_HEADER_START@
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @APPLE_APACHE_LICENSE_HEADER_END@
|
||||
*/
|
||||
|
||||
/*
|
||||
File: aglib.h
|
||||
|
||||
Copyright: (C) 2001-2011 Apple, Inc.
|
||||
*/
|
||||
|
||||
#ifndef AGLIB_H
|
||||
#define AGLIB_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define QBSHIFT 9
|
||||
#define QB (1<<QBSHIFT)
|
||||
#define PB0 40
|
||||
#define MB0 10
|
||||
#define KB0 14
|
||||
#define MAX_RUN_DEFAULT 255
|
||||
|
||||
#define MMULSHIFT 2
|
||||
#define MDENSHIFT (QBSHIFT - MMULSHIFT - 1)
|
||||
#define MOFF ((1<<(MDENSHIFT-2)))
|
||||
|
||||
#define BITOFF 24
|
||||
|
||||
/* Max. prefix of 1's. */
|
||||
#define MAX_PREFIX_16 9
|
||||
#define MAX_PREFIX_TOLONG_16 15
|
||||
#define MAX_PREFIX_32 9
|
||||
|
||||
/* Max. bits in 16-bit data type */
|
||||
#define MAX_DATATYPE_BITS_16 16
|
||||
|
||||
typedef struct AGParamRec
|
||||
{
|
||||
uint32_t mb, mb0, pb, kb, wb, qb;
|
||||
uint32_t fw, sw;
|
||||
|
||||
uint32_t maxrun;
|
||||
|
||||
// fw = 1, sw = 1;
|
||||
|
||||
} AGParamRec, *AGParamRecPtr;
|
||||
|
||||
struct BitBuffer;
|
||||
|
||||
void set_standard_ag_params(AGParamRecPtr params, uint32_t fullwidth, uint32_t sectorwidth);
|
||||
void set_ag_params(AGParamRecPtr params, uint32_t m, uint32_t p, uint32_t k, uint32_t f, uint32_t s, uint32_t maxrun);
|
||||
|
||||
int32_t dyn_comp(AGParamRecPtr params, int32_t * pc, struct BitBuffer * bitstream, int32_t numSamples, int32_t bitSize, uint32_t * outNumBits);
|
||||
int32_t dyn_decomp(AGParamRecPtr params, struct BitBuffer * bitstream, int32_t * pc, int32_t numSamples, int32_t maxSize, uint32_t * outNumBits);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif //#ifndef AGLIB_H
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright (c) 2011 Apple Inc. All rights reserved.
|
||||
* Copyright (C) 2012-2013 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
*
|
||||
* @APPLE_APACHE_LICENSE_HEADER_START@
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @APPLE_APACHE_LICENSE_HEADER_END@
|
||||
*/
|
||||
|
||||
/*
|
||||
File: alac_codec.h
|
||||
*/
|
||||
|
||||
#ifndef ALAC_CODEC_H
|
||||
#define ALAC_CODEC_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "ALACAudioTypes.h"
|
||||
|
||||
#define ALAC_FRAME_LENGTH 4096
|
||||
|
||||
struct BitBuffer;
|
||||
|
||||
typedef struct alac_decoder_s
|
||||
{
|
||||
// decoding parameters (public for use in the analyzer)
|
||||
ALACSpecificConfig mConfig;
|
||||
|
||||
uint16_t mActiveElements;
|
||||
|
||||
// decoding buffers
|
||||
int32_t mMixBufferU [ALAC_FRAME_LENGTH];
|
||||
int32_t mMixBufferV [ALAC_FRAME_LENGTH];
|
||||
union
|
||||
{
|
||||
int32_t mPredictor [ALAC_FRAME_LENGTH];
|
||||
uint16_t mShiftBuffer [ALAC_FRAME_LENGTH];
|
||||
} ;
|
||||
} ALAC_DECODER ;
|
||||
|
||||
typedef struct alac_encoder_s
|
||||
{
|
||||
// ALAC encoder parameters
|
||||
int16_t mBitDepth;
|
||||
|
||||
// encoding state
|
||||
int16_t mLastMixRes [kALACMaxChannels];
|
||||
|
||||
int32_t mFastMode;
|
||||
|
||||
// encoding buffers
|
||||
int32_t mMixBufferU [ALAC_FRAME_LENGTH] ;
|
||||
int32_t mMixBufferV [ALAC_FRAME_LENGTH] ;
|
||||
int32_t mPredictorU [ALAC_FRAME_LENGTH] ;
|
||||
int32_t mPredictorV [ALAC_FRAME_LENGTH] ;
|
||||
uint16_t mShiftBufferUV [2 * ALAC_FRAME_LENGTH] ;
|
||||
uint8_t mWorkBuffer [4 * ALAC_FRAME_LENGTH];
|
||||
|
||||
// per-channel coefficients buffers
|
||||
int16_t mCoefsU [kALACMaxChannels][kALACMaxSearches][kALACMaxCoefs];
|
||||
int16_t mCoefsV [kALACMaxChannels][kALACMaxSearches][kALACMaxCoefs];
|
||||
|
||||
// encoding statistics
|
||||
uint32_t mTotalBytesGenerated;
|
||||
uint32_t mAvgBitRate;
|
||||
uint32_t mMaxFrameBytes;
|
||||
uint32_t mFrameSize;
|
||||
uint32_t mMaxOutputBytes;
|
||||
uint32_t mNumChannels;
|
||||
uint32_t mOutputSampleRate;
|
||||
} ALAC_ENCODER ;
|
||||
|
||||
|
||||
int32_t alac_decoder_init (ALAC_DECODER *p, void * inMagicCookie, uint32_t inMagicCookieSize) ;
|
||||
int32_t alac_encoder_init (ALAC_ENCODER *p, uint32_t samplerate, uint32_t channels, uint32_t format_flags, uint32_t frameSize) ;
|
||||
|
||||
int32_t alac_decode (ALAC_DECODER *, struct BitBuffer * bits, int32_t * sampleBuffer,
|
||||
uint32_t numSamples, uint32_t numChannels, uint32_t * outNumSamples) ;
|
||||
|
||||
int32_t alac_encode (ALAC_ENCODER *p, uint32_t numChannels, uint32_t numSamples,
|
||||
int32_t * theReadBuffer, unsigned char * theWriteBuffer,
|
||||
uint32_t * ioNumBytes) ;
|
||||
|
||||
void alac_set_fastmode(ALAC_ENCODER * p, int32_t fast) ;
|
||||
|
||||
uint32_t alac_get_magic_cookie_size(uint32_t inNumChannels) ;
|
||||
void alac_get_magic_cookie(ALAC_ENCODER *p, void * config, uint32_t * ioSize) ;
|
||||
void alac_get_source_format(ALAC_ENCODER *p, const AudioFormatDescription * source, AudioFormatDescription * output) ;
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,646 @@
|
||||
/*
|
||||
* Copyright (c) 2011 Apple Inc. All rights reserved.
|
||||
* Copyright (C) 2012-2013 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
*
|
||||
* @APPLE_APACHE_LICENSE_HEADER_START@
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @APPLE_APACHE_LICENSE_HEADER_END@
|
||||
*/
|
||||
|
||||
/*
|
||||
File: ALACDecoder.cpp
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "alac_codec.h"
|
||||
|
||||
#include "dplib.h"
|
||||
#include "aglib.h"
|
||||
#include "matrixlib.h"
|
||||
|
||||
#include "ALACBitUtilities.h"
|
||||
#include "EndianPortable.h"
|
||||
|
||||
typedef enum
|
||||
{ false = 0,
|
||||
true = 1
|
||||
} bool ;
|
||||
|
||||
// constants/data
|
||||
const uint32_t kMaxBitDepth = 32; // max allowed bit depth is 32
|
||||
|
||||
|
||||
// prototypes
|
||||
static int32_t alac_fill_element (struct BitBuffer * bits) ;
|
||||
static int32_t alac_data_stream_element (struct BitBuffer * bits) ;
|
||||
|
||||
static void Zero32( int32_t * buffer, uint32_t numItems, uint32_t stride );
|
||||
|
||||
|
||||
/*
|
||||
Init()
|
||||
- initialize the decoder with the given configuration
|
||||
*/
|
||||
int32_t
|
||||
alac_decoder_init (ALAC_DECODER *p, void * inMagicCookie, uint32_t inMagicCookieSize)
|
||||
{
|
||||
int32_t status = ALAC_noErr;
|
||||
ALACSpecificConfig theConfig;
|
||||
uint8_t * theActualCookie = (uint8_t *)inMagicCookie;
|
||||
uint32_t theCookieBytesRemaining = inMagicCookieSize;
|
||||
|
||||
// For historical reasons the decoder needs to be resilient to magic cookies vended by older encoders.
|
||||
// As specified in the ALACMagicCookieDescription.txt document, there may be additional data encapsulating
|
||||
// the ALACSpecificConfig. This would consist of format ('frma') and 'alac' atoms which precede the
|
||||
// ALACSpecificConfig.
|
||||
// See ALACMagicCookieDescription.txt for additional documentation concerning the 'magic cookie'
|
||||
|
||||
// skip format ('frma') atom if present
|
||||
if (theActualCookie[4] == 'f' && theActualCookie[5] == 'r' && theActualCookie[6] == 'm' && theActualCookie[7] == 'a')
|
||||
{
|
||||
theActualCookie += 12;
|
||||
theCookieBytesRemaining -= 12;
|
||||
}
|
||||
|
||||
// skip 'alac' atom header if present
|
||||
if (theActualCookie[4] == 'a' && theActualCookie[5] == 'l' && theActualCookie[6] == 'a' && theActualCookie[7] == 'c')
|
||||
{
|
||||
theActualCookie += 12;
|
||||
theCookieBytesRemaining -= 12;
|
||||
}
|
||||
|
||||
// read the ALACSpecificConfig
|
||||
if (theCookieBytesRemaining >= sizeof(ALACSpecificConfig))
|
||||
{
|
||||
theConfig.frameLength = psf_get_be32 (theActualCookie, offsetof (ALACSpecificConfig, frameLength)) ;
|
||||
|
||||
if (theConfig.frameLength > ALAC_FRAME_LENGTH)
|
||||
return fALAC_FrameLengthError ;
|
||||
|
||||
theConfig.compatibleVersion = theActualCookie [offsetof (ALACSpecificConfig, compatibleVersion)] ;
|
||||
theConfig.bitDepth = theActualCookie [offsetof (ALACSpecificConfig, bitDepth)] ;
|
||||
theConfig.pb = theActualCookie [offsetof (ALACSpecificConfig, pb)] ;
|
||||
theConfig.mb = theActualCookie [offsetof (ALACSpecificConfig, mb)] ;
|
||||
theConfig.kb = theActualCookie [offsetof (ALACSpecificConfig, kb)] ;
|
||||
theConfig.numChannels = theActualCookie [offsetof (ALACSpecificConfig, numChannels)] ;
|
||||
theConfig.maxRun = psf_get_be16 (theActualCookie, offsetof (ALACSpecificConfig, maxRun)) ;
|
||||
theConfig.maxFrameBytes = psf_get_be32 (theActualCookie, offsetof (ALACSpecificConfig, maxFrameBytes)) ;
|
||||
theConfig.avgBitRate = psf_get_be32 (theActualCookie, offsetof (ALACSpecificConfig, avgBitRate)) ;
|
||||
theConfig.sampleRate = psf_get_be32 (theActualCookie, offsetof (ALACSpecificConfig, sampleRate)) ;
|
||||
|
||||
p->mConfig = theConfig;
|
||||
|
||||
RequireAction( p->mConfig.compatibleVersion <= kALACVersion, return kALAC_ParamError; );
|
||||
|
||||
RequireAction( (p->mMixBufferU != NULL) && (p->mMixBufferV != NULL) && (p->mPredictor != NULL),
|
||||
status = kALAC_MemFullError; goto Exit; );
|
||||
}
|
||||
else
|
||||
{
|
||||
status = kALAC_ParamError;
|
||||
}
|
||||
|
||||
// skip to Channel Layout Info
|
||||
// theActualCookie += sizeof(ALACSpecificConfig);
|
||||
|
||||
// Currently, the Channel Layout Info portion of the magic cookie (as defined in the
|
||||
// ALACMagicCookieDescription.txt document) is unused by the decoder.
|
||||
|
||||
Exit:
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
Decode()
|
||||
- the decoded samples are interleaved into the output buffer in the order they arrive in
|
||||
the bitstream
|
||||
*/
|
||||
int32_t
|
||||
alac_decode (ALAC_DECODER *p, struct BitBuffer * bits, int32_t * sampleBuffer, uint32_t numSamples, uint32_t numChannels, uint32_t * outNumSamples)
|
||||
{
|
||||
BitBuffer shiftBits;
|
||||
uint32_t bits1, bits2;
|
||||
uint8_t tag;
|
||||
uint8_t elementInstanceTag;
|
||||
AGParamRec agParams;
|
||||
uint32_t channelIndex;
|
||||
int16_t coefsU[32]; // max possible size is 32 although NUMCOEPAIRS is the current limit
|
||||
int16_t coefsV[32];
|
||||
uint8_t numU, numV;
|
||||
uint8_t mixBits;
|
||||
int8_t mixRes;
|
||||
uint16_t unusedHeader;
|
||||
uint8_t escapeFlag;
|
||||
uint32_t chanBits;
|
||||
uint8_t bytesShifted;
|
||||
uint32_t shift;
|
||||
uint8_t modeU, modeV;
|
||||
uint32_t denShiftU, denShiftV;
|
||||
uint16_t pbFactorU, pbFactorV;
|
||||
uint16_t pb;
|
||||
int32_t * out32;
|
||||
uint8_t headerByte;
|
||||
uint8_t partialFrame;
|
||||
uint32_t extraBits;
|
||||
int32_t val;
|
||||
uint32_t i, j;
|
||||
int32_t status;
|
||||
|
||||
RequireAction( (bits != NULL) && (sampleBuffer != NULL) && (outNumSamples != NULL), return kALAC_ParamError; );
|
||||
RequireAction( numChannels > 0, return kALAC_ParamError; );
|
||||
|
||||
p->mActiveElements = 0;
|
||||
channelIndex = 0;
|
||||
|
||||
status = ALAC_noErr;
|
||||
*outNumSamples = numSamples;
|
||||
|
||||
while ( status == ALAC_noErr )
|
||||
{
|
||||
// bail if we ran off the end of the buffer
|
||||
RequireAction( bits->cur < bits->end, status = kALAC_ParamError; goto Exit; );
|
||||
|
||||
// copy global decode params for this element
|
||||
pb = p->mConfig.pb;
|
||||
|
||||
// read element tag
|
||||
tag = BitBufferReadSmall( bits, 3 );
|
||||
switch ( tag )
|
||||
{
|
||||
case ID_SCE:
|
||||
case ID_LFE:
|
||||
{
|
||||
// mono/LFE channel
|
||||
elementInstanceTag = BitBufferReadSmall( bits, 4 );
|
||||
p->mActiveElements |= (1u << elementInstanceTag);
|
||||
|
||||
// read the 12 unused header bits
|
||||
unusedHeader = (uint16_t) BitBufferRead( bits, 12 );
|
||||
RequireAction( unusedHeader == 0, status = kALAC_ParamError; goto Exit; );
|
||||
|
||||
// read the 1-bit "partial frame" flag, 2-bit "shift-off" flag & 1-bit "escape" flag
|
||||
headerByte = (uint8_t) BitBufferRead( bits, 4 );
|
||||
|
||||
partialFrame = headerByte >> 3;
|
||||
|
||||
bytesShifted = (headerByte >> 1) & 0x3u;
|
||||
RequireAction( bytesShifted != 3, status = kALAC_ParamError; goto Exit; );
|
||||
|
||||
shift = bytesShifted * 8;
|
||||
|
||||
escapeFlag = headerByte & 0x1;
|
||||
|
||||
chanBits = p->mConfig.bitDepth - (bytesShifted * 8);
|
||||
|
||||
// check for partial frame to override requested numSamples
|
||||
if ( partialFrame != 0 )
|
||||
{
|
||||
numSamples = BitBufferRead( bits, 16 ) << 16;
|
||||
numSamples |= BitBufferRead( bits, 16 );
|
||||
}
|
||||
|
||||
if ( escapeFlag == 0 )
|
||||
{
|
||||
// compressed frame, read rest of parameters
|
||||
mixBits = (uint8_t) BitBufferRead( bits, 8 );
|
||||
mixRes = (int8_t) BitBufferRead( bits, 8 );
|
||||
//Assert( (mixBits == 0) && (mixRes == 0) ); // no mixing for mono
|
||||
|
||||
headerByte = (uint8_t) BitBufferRead( bits, 8 );
|
||||
modeU = headerByte >> 4;
|
||||
denShiftU = headerByte & 0xfu;
|
||||
|
||||
headerByte = (uint8_t) BitBufferRead( bits, 8 );
|
||||
pbFactorU = headerByte >> 5;
|
||||
numU = headerByte & 0x1fu;
|
||||
|
||||
for ( i = 0; i < numU; i++ )
|
||||
coefsU[i] = (int16_t) BitBufferRead( bits, 16 );
|
||||
|
||||
// if shift active, skip the the shift buffer but remember where it starts
|
||||
if ( bytesShifted != 0 )
|
||||
{
|
||||
shiftBits = *bits;
|
||||
BitBufferAdvance( bits, (bytesShifted * 8) * numSamples );
|
||||
}
|
||||
|
||||
// decompress
|
||||
set_ag_params( &agParams, p->mConfig.mb, (pb * pbFactorU) / 4, p->mConfig.kb, numSamples, numSamples, p->mConfig.maxRun );
|
||||
status = dyn_decomp( &agParams, bits, p->mPredictor, numSamples, chanBits, &bits1 );
|
||||
RequireNoErr( status, goto Exit; );
|
||||
|
||||
if ( modeU == 0 )
|
||||
{
|
||||
unpc_block( p->mPredictor, p->mMixBufferU, numSamples, &coefsU[0], numU, chanBits, denShiftU );
|
||||
}
|
||||
else
|
||||
{
|
||||
// the special "numActive == 31" mode can be done in-place
|
||||
unpc_block( p->mPredictor, p->mPredictor, numSamples, NULL, 31, chanBits, 0 );
|
||||
unpc_block( p->mPredictor, p->mMixBufferU, numSamples, &coefsU[0], numU, chanBits, denShiftU );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//Assert( bytesShifted == 0 );
|
||||
|
||||
// uncompressed frame, copy data into the mix buffer to use common output code
|
||||
shift = 32 - chanBits;
|
||||
if ( chanBits <= 16 )
|
||||
{
|
||||
for ( i = 0; i < numSamples; i++ )
|
||||
{
|
||||
val = (int32_t) BitBufferRead( bits, (uint8_t) chanBits );
|
||||
val = (val << shift) >> shift;
|
||||
p->mMixBufferU[i] = val;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// BitBufferRead() can't read more than 16 bits at a time so break up the reads
|
||||
extraBits = chanBits - 16;
|
||||
for ( i = 0; i < numSamples; i++ )
|
||||
{
|
||||
val = (int32_t) BitBufferRead( bits, 16 );
|
||||
val = (val << 16) >> shift;
|
||||
p->mMixBufferU[i] = val | BitBufferRead( bits, (uint8_t) extraBits );
|
||||
}
|
||||
}
|
||||
|
||||
mixBits = mixRes = 0;
|
||||
bits1 = chanBits * numSamples;
|
||||
bytesShifted = 0;
|
||||
}
|
||||
|
||||
// now read the shifted values into the shift buffer
|
||||
if ( bytesShifted != 0 )
|
||||
{
|
||||
shift = bytesShifted * 8;
|
||||
//Assert( shift <= 16 );
|
||||
|
||||
for ( i = 0; i < numSamples; i++ )
|
||||
p->mShiftBuffer[i] = (uint16_t) BitBufferRead( &shiftBits, (uint8_t) shift );
|
||||
}
|
||||
|
||||
// convert 32-bit integers into output buffer
|
||||
switch ( p->mConfig.bitDepth )
|
||||
{
|
||||
case 16:
|
||||
out32 = sampleBuffer + channelIndex;
|
||||
for ( i = 0, j = 0; i < numSamples; i++, j += numChannels )
|
||||
out32[j] = p->mMixBufferU[i] << 16;
|
||||
break;
|
||||
case 20:
|
||||
out32 = sampleBuffer + channelIndex;
|
||||
copyPredictorTo20( p->mMixBufferU, out32, numChannels, numSamples );
|
||||
break;
|
||||
case 24:
|
||||
out32 = sampleBuffer + channelIndex;
|
||||
if ( bytesShifted != 0 )
|
||||
copyPredictorTo24Shift( p->mMixBufferU, p->mShiftBuffer, out32, numChannels, numSamples, bytesShifted );
|
||||
else
|
||||
copyPredictorTo24( p->mMixBufferU, out32, numChannels, numSamples );
|
||||
break;
|
||||
case 32:
|
||||
out32 = sampleBuffer + channelIndex;
|
||||
if ( bytesShifted != 0 )
|
||||
copyPredictorTo32Shift( p->mMixBufferU, p->mShiftBuffer, out32, numChannels, numSamples, bytesShifted );
|
||||
else
|
||||
copyPredictorTo32( p->mMixBufferU, out32, numChannels, numSamples);
|
||||
break;
|
||||
}
|
||||
|
||||
channelIndex += 1;
|
||||
*outNumSamples = numSamples;
|
||||
break;
|
||||
}
|
||||
|
||||
case ID_CPE:
|
||||
{
|
||||
// if decoding this pair would take us over the max channels limit, bail
|
||||
if ( (channelIndex + 2) > numChannels )
|
||||
goto NoMoreChannels;
|
||||
|
||||
// stereo channel pair
|
||||
elementInstanceTag = BitBufferReadSmall( bits, 4 );
|
||||
p->mActiveElements |= (1u << elementInstanceTag);
|
||||
|
||||
// read the 12 unused header bits
|
||||
unusedHeader = (uint16_t) BitBufferRead( bits, 12 );
|
||||
RequireAction( unusedHeader == 0, status = kALAC_ParamError; goto Exit; );
|
||||
|
||||
// read the 1-bit "partial frame" flag, 2-bit "shift-off" flag & 1-bit "escape" flag
|
||||
headerByte = (uint8_t) BitBufferRead( bits, 4 );
|
||||
|
||||
partialFrame = headerByte >> 3;
|
||||
|
||||
bytesShifted = (headerByte >> 1) & 0x3u;
|
||||
RequireAction( bytesShifted != 3, status = kALAC_ParamError; goto Exit; );
|
||||
|
||||
shift = bytesShifted * 8;
|
||||
|
||||
escapeFlag = headerByte & 0x1;
|
||||
|
||||
chanBits = p->mConfig.bitDepth - (bytesShifted * 8) + 1;
|
||||
|
||||
// check for partial frame length to override requested numSamples
|
||||
if ( partialFrame != 0 )
|
||||
{
|
||||
numSamples = BitBufferRead( bits, 16 ) << 16;
|
||||
numSamples |= BitBufferRead( bits, 16 );
|
||||
}
|
||||
|
||||
if ( escapeFlag == 0 )
|
||||
{
|
||||
// compressed frame, read rest of parameters
|
||||
mixBits = (uint8_t) BitBufferRead( bits, 8 );
|
||||
mixRes = (int8_t) BitBufferRead( bits, 8 );
|
||||
|
||||
headerByte = (uint8_t) BitBufferRead( bits, 8 );
|
||||
modeU = headerByte >> 4;
|
||||
denShiftU = headerByte & 0xfu;
|
||||
|
||||
headerByte = (uint8_t) BitBufferRead( bits, 8 );
|
||||
pbFactorU = headerByte >> 5;
|
||||
numU = headerByte & 0x1fu;
|
||||
for ( i = 0; i < numU; i++ )
|
||||
coefsU[i] = (int16_t) BitBufferRead( bits, 16 );
|
||||
|
||||
headerByte = (uint8_t) BitBufferRead( bits, 8 );
|
||||
modeV = headerByte >> 4;
|
||||
denShiftV = headerByte & 0xfu;
|
||||
|
||||
headerByte = (uint8_t) BitBufferRead( bits, 8 );
|
||||
pbFactorV = headerByte >> 5;
|
||||
numV = headerByte & 0x1fu;
|
||||
for ( i = 0; i < numV; i++ )
|
||||
coefsV[i] = (int16_t) BitBufferRead( bits, 16 );
|
||||
|
||||
// if shift active, skip the interleaved shifted values but remember where they start
|
||||
if ( bytesShifted != 0 )
|
||||
{
|
||||
shiftBits = *bits;
|
||||
BitBufferAdvance( bits, (bytesShifted * 8) * 2 * numSamples );
|
||||
}
|
||||
|
||||
// decompress and run predictor for "left" channel
|
||||
set_ag_params( &agParams, p->mConfig.mb, (pb * pbFactorU) / 4, p->mConfig.kb, numSamples, numSamples, p->mConfig.maxRun );
|
||||
status = dyn_decomp( &agParams, bits, p->mPredictor, numSamples, chanBits, &bits1 );
|
||||
RequireNoErr( status, goto Exit; );
|
||||
|
||||
if ( modeU == 0 )
|
||||
{
|
||||
unpc_block( p->mPredictor, p->mMixBufferU, numSamples, &coefsU[0], numU, chanBits, denShiftU );
|
||||
}
|
||||
else
|
||||
{
|
||||
// the special "numActive == 31" mode can be done in-place
|
||||
unpc_block( p->mPredictor, p->mPredictor, numSamples, NULL, 31, chanBits, 0 );
|
||||
unpc_block( p->mPredictor, p->mMixBufferU, numSamples, &coefsU[0], numU, chanBits, denShiftU );
|
||||
}
|
||||
|
||||
// decompress and run predictor for "right" channel
|
||||
set_ag_params( &agParams, p->mConfig.mb, (pb * pbFactorV) / 4, p->mConfig.kb, numSamples, numSamples, p->mConfig.maxRun );
|
||||
status = dyn_decomp( &agParams, bits, p->mPredictor, numSamples, chanBits, &bits2 );
|
||||
RequireNoErr( status, goto Exit; );
|
||||
|
||||
if ( modeV == 0 )
|
||||
{
|
||||
unpc_block( p->mPredictor, p->mMixBufferV, numSamples, &coefsV[0], numV, chanBits, denShiftV );
|
||||
}
|
||||
else
|
||||
{
|
||||
// the special "numActive == 31" mode can be done in-place
|
||||
unpc_block( p->mPredictor, p->mPredictor, numSamples, NULL, 31, chanBits, 0 );
|
||||
unpc_block( p->mPredictor, p->mMixBufferV, numSamples, &coefsV[0], numV, chanBits, denShiftV );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//Assert( bytesShifted == 0 );
|
||||
|
||||
// uncompressed frame, copy data into the mix buffers to use common output code
|
||||
chanBits = p->mConfig.bitDepth;
|
||||
shift = 32 - chanBits;
|
||||
if ( chanBits <= 16 )
|
||||
{
|
||||
for ( i = 0; i < numSamples; i++ )
|
||||
{
|
||||
val = (int32_t) BitBufferRead( bits, (uint8_t) chanBits );
|
||||
val = (val << shift) >> shift;
|
||||
p->mMixBufferU[i] = val;
|
||||
|
||||
val = (int32_t) BitBufferRead( bits, (uint8_t) chanBits );
|
||||
val = (val << shift) >> shift;
|
||||
p->mMixBufferV[i] = val;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// BitBufferRead() can't read more than 16 bits at a time so break up the reads
|
||||
extraBits = chanBits - 16;
|
||||
for ( i = 0; i < numSamples; i++ )
|
||||
{
|
||||
val = (int32_t) BitBufferRead( bits, 16 );
|
||||
val = (val << 16) >> shift;
|
||||
p->mMixBufferU[i] = val | BitBufferRead( bits, (uint8_t)extraBits );
|
||||
|
||||
val = (int32_t) BitBufferRead( bits, 16 );
|
||||
val = (val << 16) >> shift;
|
||||
p->mMixBufferV[i] = val | BitBufferRead( bits, (uint8_t)extraBits );
|
||||
}
|
||||
}
|
||||
|
||||
bits1 = chanBits * numSamples;
|
||||
bits2 = chanBits * numSamples;
|
||||
mixBits = mixRes = 0;
|
||||
bytesShifted = 0;
|
||||
}
|
||||
|
||||
// now read the shifted values into the shift buffer
|
||||
if ( bytesShifted != 0 )
|
||||
{
|
||||
shift = bytesShifted * 8;
|
||||
//Assert( shift <= 16 );
|
||||
|
||||
for ( i = 0; i < (numSamples * 2); i += 2 )
|
||||
{
|
||||
p->mShiftBuffer[i + 0] = (uint16_t) BitBufferRead( &shiftBits, (uint8_t) shift );
|
||||
p->mShiftBuffer[i + 1] = (uint16_t) BitBufferRead( &shiftBits, (uint8_t) shift );
|
||||
}
|
||||
}
|
||||
|
||||
// un-mix the data and convert to output format
|
||||
// - note that mixRes = 0 means just interleave so we use that path for uncompressed frames
|
||||
switch ( p->mConfig.bitDepth )
|
||||
{
|
||||
case 16:
|
||||
out32 = sampleBuffer + channelIndex;
|
||||
unmix16( p->mMixBufferU, p->mMixBufferV, out32, numChannels, numSamples, mixBits, mixRes );
|
||||
break;
|
||||
case 20:
|
||||
out32 = sampleBuffer + channelIndex;
|
||||
unmix20( p->mMixBufferU, p->mMixBufferV, out32, numChannels, numSamples, mixBits, mixRes );
|
||||
break;
|
||||
case 24:
|
||||
out32 = sampleBuffer + channelIndex;
|
||||
unmix24( p->mMixBufferU, p->mMixBufferV, out32, numChannels, numSamples,
|
||||
mixBits, mixRes, p->mShiftBuffer, bytesShifted );
|
||||
break;
|
||||
case 32:
|
||||
out32 = sampleBuffer + channelIndex;
|
||||
unmix32( p->mMixBufferU, p->mMixBufferV, out32, numChannels, numSamples,
|
||||
mixBits, mixRes, p->mShiftBuffer, bytesShifted );
|
||||
break;
|
||||
}
|
||||
|
||||
channelIndex += 2;
|
||||
*outNumSamples = numSamples;
|
||||
break;
|
||||
}
|
||||
|
||||
case ID_CCE:
|
||||
case ID_PCE:
|
||||
{
|
||||
// unsupported element, bail
|
||||
//AssertNoErr( tag );
|
||||
status = kALAC_ParamError;
|
||||
break;
|
||||
}
|
||||
|
||||
case ID_DSE:
|
||||
{
|
||||
// data stream element -- parse but ignore
|
||||
status = alac_data_stream_element (bits) ;
|
||||
break;
|
||||
}
|
||||
|
||||
case ID_FIL:
|
||||
{
|
||||
// fill element -- parse but ignore
|
||||
status = alac_fill_element (bits) ;
|
||||
break;
|
||||
}
|
||||
|
||||
case ID_END:
|
||||
{
|
||||
// frame end, all done so byte align the frame and check for overruns
|
||||
BitBufferByteAlign( bits, false );
|
||||
//Assert( bits->cur == bits->end );
|
||||
goto Exit;
|
||||
}
|
||||
}
|
||||
|
||||
#if 0 // ! DEBUG
|
||||
// if we've decoded all of our channels, bail (but not in debug b/c we want to know if we're seeing bad bits)
|
||||
// - this also protects us if the config does not match the bitstream or crap data bits follow the audio bits
|
||||
if ( channelIndex >= numChannels )
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
NoMoreChannels:
|
||||
|
||||
// if we get here and haven't decoded all of the requested channels, fill the remaining channels with zeros
|
||||
for ( ; channelIndex < numChannels; channelIndex++ )
|
||||
{
|
||||
int32_t * fill32 = sampleBuffer + channelIndex;
|
||||
Zero32( fill32, numSamples, numChannels );
|
||||
}
|
||||
|
||||
Exit:
|
||||
return status;
|
||||
}
|
||||
|
||||
#if PRAGMA_MARK
|
||||
#pragma mark -
|
||||
#endif
|
||||
|
||||
/*
|
||||
FillElement()
|
||||
- they're just filler so we don't need 'em
|
||||
*/
|
||||
static int32_t
|
||||
alac_fill_element (struct BitBuffer * bits)
|
||||
{
|
||||
int16_t count;
|
||||
|
||||
// 4-bit count or (4-bit + 8-bit count) if 4-bit count == 15
|
||||
// - plus this weird -1 thing I still don't fully understand
|
||||
count = BitBufferReadSmall( bits, 4 );
|
||||
if ( count == 15 )
|
||||
count += (int16_t) BitBufferReadSmall( bits, 8 ) - 1;
|
||||
|
||||
BitBufferAdvance( bits, count * 8 );
|
||||
|
||||
RequireAction( bits->cur <= bits->end, return kALAC_ParamError; );
|
||||
|
||||
return ALAC_noErr;
|
||||
}
|
||||
|
||||
/*
|
||||
DataStreamElement()
|
||||
- we don't care about data stream elements so just skip them
|
||||
*/
|
||||
static int32_t
|
||||
alac_data_stream_element (struct BitBuffer * bits)
|
||||
{
|
||||
int32_t data_byte_align_flag;
|
||||
uint16_t count;
|
||||
|
||||
// the tag associates this data stream element with a given audio element
|
||||
|
||||
/* element_instance_tag = */ BitBufferReadSmall( bits, 4 );
|
||||
|
||||
data_byte_align_flag = BitBufferReadOne( bits );
|
||||
|
||||
// 8-bit count or (8-bit + 8-bit count) if 8-bit count == 255
|
||||
count = BitBufferReadSmall( bits, 8 );
|
||||
if ( count == 255 )
|
||||
count += BitBufferReadSmall( bits, 8 );
|
||||
|
||||
// the align flag means the bitstream should be byte-aligned before reading the following data bytes
|
||||
if ( data_byte_align_flag )
|
||||
BitBufferByteAlign( bits, false );
|
||||
|
||||
// skip the data bytes
|
||||
BitBufferAdvance( bits, count * 8 );
|
||||
|
||||
RequireAction( bits->cur <= bits->end, return kALAC_ParamError; );
|
||||
|
||||
return ALAC_noErr;
|
||||
}
|
||||
|
||||
/*
|
||||
ZeroN()
|
||||
- helper routines to clear out output channel buffers when decoding fewer channels than requested
|
||||
*/
|
||||
static void Zero32( int32_t * buffer, uint32_t numItems, uint32_t stride )
|
||||
{
|
||||
uint32_t indx;
|
||||
|
||||
if ( stride == 1 )
|
||||
{
|
||||
memset( buffer, 0, numItems * sizeof(int32_t) );
|
||||
}
|
||||
else
|
||||
{
|
||||
for ( indx = 0; indx < (numItems * stride); indx += stride )
|
||||
buffer[indx] = 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (c) 2011 Apple Inc. All rights reserved.
|
||||
*
|
||||
* @APPLE_APACHE_LICENSE_HEADER_START@
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @APPLE_APACHE_LICENSE_HEADER_END@
|
||||
*/
|
||||
|
||||
/*
|
||||
File: alac_decoder.h
|
||||
*/
|
||||
|
||||
#ifndef ALAC_DECODER_H
|
||||
#define ALAC_DECODER_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "ALACAudioTypes.h"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
false = 0,
|
||||
ALAC_TRUE = 1
|
||||
} bool ;
|
||||
|
||||
struct BitBuffer;
|
||||
|
||||
typedef struct alac_decoder
|
||||
{
|
||||
// decoding parameters (public for use in the analyzer)
|
||||
ALACSpecificConfig mConfig;
|
||||
|
||||
uint16_t mActiveElements;
|
||||
|
||||
// decoding buffers
|
||||
int32_t * mMixBufferU;
|
||||
int32_t * mMixBufferV;
|
||||
int32_t * mPredictor;
|
||||
uint16_t * mShiftBuffer; // note: this points to mPredictor's memory but different
|
||||
// variable for clarity and type difference
|
||||
} alac_decoder ;
|
||||
|
||||
alac_decoder * alac_decoder_new (void) ;
|
||||
void alac_decoder_delete (alac_decoder *) ;
|
||||
|
||||
int32_t alac_init (alac_decoder *p, void * inMagicCookie, uint32_t inMagicCookieSize) ;
|
||||
int32_t alac_decode (alac_decoder *, struct BitBuffer * bits, uint8_t * sampleBuffer, uint32_t numSamples, uint32_t numChannels, uint32_t * outNumSamples) ;
|
||||
|
||||
#endif /* ALAC_DECODER_H */
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,375 @@
|
||||
/*
|
||||
* Copyright (c) 2011 Apple Inc. All rights reserved.
|
||||
*
|
||||
* @APPLE_APACHE_LICENSE_HEADER_START@
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @APPLE_APACHE_LICENSE_HEADER_END@
|
||||
*/
|
||||
|
||||
/*
|
||||
File: dp_dec.c
|
||||
|
||||
Contains: Dynamic Predictor decode routines
|
||||
|
||||
Copyright: (c) 2001-2011 Apple, Inc.
|
||||
*/
|
||||
|
||||
|
||||
#include "dplib.h"
|
||||
#include <string.h>
|
||||
|
||||
#if __GNUC__
|
||||
#define ALWAYS_INLINE __attribute__((always_inline))
|
||||
#else
|
||||
#define ALWAYS_INLINE
|
||||
#endif
|
||||
|
||||
#define LOOP_ALIGN
|
||||
|
||||
static inline int32_t ALWAYS_INLINE sign_of_int( int32_t i )
|
||||
{
|
||||
int32_t negishift;
|
||||
|
||||
negishift = ((uint32_t)-i) >> 31;
|
||||
return negishift | (i >> 31);
|
||||
}
|
||||
|
||||
void unpc_block( int32_t * pc1, int32_t * out, int32_t num, int16_t * coefs, int32_t numactive, uint32_t chanbits, uint32_t denshift )
|
||||
{
|
||||
register int16_t a0, a1, a2, a3;
|
||||
register int32_t b0, b1, b2, b3;
|
||||
int32_t j, k, lim;
|
||||
int32_t sum1, sg, sgn, top, dd;
|
||||
int32_t * pout;
|
||||
int32_t del, del0;
|
||||
uint32_t chanshift = 32 - chanbits;
|
||||
int32_t denhalf = 1<<(denshift-1);
|
||||
|
||||
out[0] = pc1[0];
|
||||
if ( numactive == 0 )
|
||||
{
|
||||
// just copy if numactive == 0 (but don't bother if in/out pointers the same)
|
||||
if ( (num > 1) && (pc1 != out) )
|
||||
memcpy( &out[1], &pc1[1], (num - 1) * sizeof(int32_t) );
|
||||
return;
|
||||
}
|
||||
if ( numactive == 31 )
|
||||
{
|
||||
// short-circuit if numactive == 31
|
||||
int32_t prev;
|
||||
|
||||
/* this code is written such that the in/out buffers can be the same
|
||||
to conserve buffer space on embedded devices like the iPod
|
||||
|
||||
(original code)
|
||||
for ( j = 1; j < num; j++ )
|
||||
del = pc1[j] + out[j-1];
|
||||
out[j] = (del << chanshift) >> chanshift;
|
||||
*/
|
||||
prev = out[0];
|
||||
for ( j = 1; j < num; j++ )
|
||||
{
|
||||
del = pc1[j] + prev;
|
||||
prev = (del << chanshift) >> chanshift;
|
||||
out[j] = prev;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
for ( j = 1; j <= numactive; j++ )
|
||||
{
|
||||
del = pc1[j] + out[j-1];
|
||||
out[j] = (del << chanshift) >> chanshift;
|
||||
}
|
||||
|
||||
lim = numactive + 1;
|
||||
|
||||
if ( numactive == 4 )
|
||||
{
|
||||
// optimization for numactive == 4
|
||||
register int16_t ia0, ia1, ia2, ia3;
|
||||
register int32_t ib0, ib1, ib2, ib3;
|
||||
|
||||
ia0 = coefs[0];
|
||||
ia1 = coefs[1];
|
||||
ia2 = coefs[2];
|
||||
ia3 = coefs[3];
|
||||
|
||||
for ( j = lim; j < num; j++ )
|
||||
{
|
||||
LOOP_ALIGN
|
||||
|
||||
top = out[j - lim];
|
||||
pout = out + j - 1;
|
||||
|
||||
ib0 = top - pout[0];
|
||||
ib1 = top - pout[-1];
|
||||
ib2 = top - pout[-2];
|
||||
ib3 = top - pout[-3];
|
||||
|
||||
sum1 = (denhalf - ia0 * ib0 - ia1 * ib1 - ia2 * ib2 - ia3 * ib3) >> denshift;
|
||||
|
||||
del = pc1[j];
|
||||
del0 = del;
|
||||
sg = sign_of_int(del);
|
||||
del += top + sum1;
|
||||
|
||||
out[j] = (del << chanshift) >> chanshift;
|
||||
|
||||
if ( sg > 0 )
|
||||
{
|
||||
sgn = sign_of_int( ib3 );
|
||||
ia3 -= sgn;
|
||||
del0 -= (4 - 3) * ((sgn * ib3) >> denshift);
|
||||
if ( del0 <= 0 )
|
||||
continue;
|
||||
|
||||
sgn = sign_of_int( ib2 );
|
||||
ia2 -= sgn;
|
||||
del0 -= (4 - 2) * ((sgn * ib2) >> denshift);
|
||||
if ( del0 <= 0 )
|
||||
continue;
|
||||
|
||||
sgn = sign_of_int( ib1 );
|
||||
ia1 -= sgn;
|
||||
del0 -= (4 - 1) * ((sgn * ib1) >> denshift);
|
||||
if ( del0 <= 0 )
|
||||
continue;
|
||||
|
||||
ia0 -= sign_of_int( ib0 );
|
||||
}
|
||||
else if ( sg < 0 )
|
||||
{
|
||||
// note: to avoid unnecessary negations, we flip the value of "sgn"
|
||||
sgn = -sign_of_int( ib3 );
|
||||
ia3 -= sgn;
|
||||
del0 -= (4 - 3) * ((sgn * ib3) >> denshift);
|
||||
if ( del0 >= 0 )
|
||||
continue;
|
||||
|
||||
sgn = -sign_of_int( ib2 );
|
||||
ia2 -= sgn;
|
||||
del0 -= (4 - 2) * ((sgn * ib2) >> denshift);
|
||||
if ( del0 >= 0 )
|
||||
continue;
|
||||
|
||||
sgn = -sign_of_int( ib1 );
|
||||
ia1 -= sgn;
|
||||
del0 -= (4 - 1) * ((sgn * ib1) >> denshift);
|
||||
if ( del0 >= 0 )
|
||||
continue;
|
||||
|
||||
ia0 += sign_of_int( ib0 );
|
||||
}
|
||||
}
|
||||
|
||||
coefs[0] = ia0;
|
||||
coefs[1] = ia1;
|
||||
coefs[2] = ia2;
|
||||
coefs[3] = ia3;
|
||||
}
|
||||
else if ( numactive == 8 )
|
||||
{
|
||||
register int16_t a4, a5, a6, a7;
|
||||
register int32_t b4, b5, b6, b7;
|
||||
|
||||
// optimization for numactive == 8
|
||||
a0 = coefs[0];
|
||||
a1 = coefs[1];
|
||||
a2 = coefs[2];
|
||||
a3 = coefs[3];
|
||||
a4 = coefs[4];
|
||||
a5 = coefs[5];
|
||||
a6 = coefs[6];
|
||||
a7 = coefs[7];
|
||||
|
||||
for ( j = lim; j < num; j++ )
|
||||
{
|
||||
LOOP_ALIGN
|
||||
|
||||
top = out[j - lim];
|
||||
pout = out + j - 1;
|
||||
|
||||
b0 = top - (*pout--);
|
||||
b1 = top - (*pout--);
|
||||
b2 = top - (*pout--);
|
||||
b3 = top - (*pout--);
|
||||
b4 = top - (*pout--);
|
||||
b5 = top - (*pout--);
|
||||
b6 = top - (*pout--);
|
||||
b7 = top - (*pout);
|
||||
pout += 8;
|
||||
|
||||
sum1 = (denhalf - a0 * b0 - a1 * b1 - a2 * b2 - a3 * b3
|
||||
- a4 * b4 - a5 * b5 - a6 * b6 - a7 * b7) >> denshift;
|
||||
|
||||
del = pc1[j];
|
||||
del0 = del;
|
||||
sg = sign_of_int(del);
|
||||
del += top + sum1;
|
||||
|
||||
out[j] = (del << chanshift) >> chanshift;
|
||||
|
||||
if ( sg > 0 )
|
||||
{
|
||||
sgn = sign_of_int( b7 );
|
||||
a7 -= sgn;
|
||||
del0 -= 1 * ((sgn * b7) >> denshift);
|
||||
if ( del0 <= 0 )
|
||||
continue;
|
||||
|
||||
sgn = sign_of_int( b6 );
|
||||
a6 -= sgn;
|
||||
del0 -= 2 * ((sgn * b6) >> denshift);
|
||||
if ( del0 <= 0 )
|
||||
continue;
|
||||
|
||||
sgn = sign_of_int( b5 );
|
||||
a5 -= sgn;
|
||||
del0 -= 3 * ((sgn * b5) >> denshift);
|
||||
if ( del0 <= 0 )
|
||||
continue;
|
||||
|
||||
sgn = sign_of_int( b4 );
|
||||
a4 -= sgn;
|
||||
del0 -= 4 * ((sgn * b4) >> denshift);
|
||||
if ( del0 <= 0 )
|
||||
continue;
|
||||
|
||||
sgn = sign_of_int( b3 );
|
||||
a3 -= sgn;
|
||||
del0 -= 5 * ((sgn * b3) >> denshift);
|
||||
if ( del0 <= 0 )
|
||||
continue;
|
||||
|
||||
sgn = sign_of_int( b2 );
|
||||
a2 -= sgn;
|
||||
del0 -= 6 * ((sgn * b2) >> denshift);
|
||||
if ( del0 <= 0 )
|
||||
continue;
|
||||
|
||||
sgn = sign_of_int( b1 );
|
||||
a1 -= sgn;
|
||||
del0 -= 7 * ((sgn * b1) >> denshift);
|
||||
if ( del0 <= 0 )
|
||||
continue;
|
||||
|
||||
a0 -= sign_of_int( b0 );
|
||||
}
|
||||
else if ( sg < 0 )
|
||||
{
|
||||
// note: to avoid unnecessary negations, we flip the value of "sgn"
|
||||
sgn = -sign_of_int( b7 );
|
||||
a7 -= sgn;
|
||||
del0 -= 1 * ((sgn * b7) >> denshift);
|
||||
if ( del0 >= 0 )
|
||||
continue;
|
||||
|
||||
sgn = -sign_of_int( b6 );
|
||||
a6 -= sgn;
|
||||
del0 -= 2 * ((sgn * b6) >> denshift);
|
||||
if ( del0 >= 0 )
|
||||
continue;
|
||||
|
||||
sgn = -sign_of_int( b5 );
|
||||
a5 -= sgn;
|
||||
del0 -= 3 * ((sgn * b5) >> denshift);
|
||||
if ( del0 >= 0 )
|
||||
continue;
|
||||
|
||||
sgn = -sign_of_int( b4 );
|
||||
a4 -= sgn;
|
||||
del0 -= 4 * ((sgn * b4) >> denshift);
|
||||
if ( del0 >= 0 )
|
||||
continue;
|
||||
|
||||
sgn = -sign_of_int( b3 );
|
||||
a3 -= sgn;
|
||||
del0 -= 5 * ((sgn * b3) >> denshift);
|
||||
if ( del0 >= 0 )
|
||||
continue;
|
||||
|
||||
sgn = -sign_of_int( b2 );
|
||||
a2 -= sgn;
|
||||
del0 -= 6 * ((sgn * b2) >> denshift);
|
||||
if ( del0 >= 0 )
|
||||
continue;
|
||||
|
||||
sgn = -sign_of_int( b1 );
|
||||
a1 -= sgn;
|
||||
del0 -= 7 * ((sgn * b1) >> denshift);
|
||||
if ( del0 >= 0 )
|
||||
continue;
|
||||
|
||||
a0 += sign_of_int( b0 );
|
||||
}
|
||||
}
|
||||
|
||||
coefs[0] = a0;
|
||||
coefs[1] = a1;
|
||||
coefs[2] = a2;
|
||||
coefs[3] = a3;
|
||||
coefs[4] = a4;
|
||||
coefs[5] = a5;
|
||||
coefs[6] = a6;
|
||||
coefs[7] = a7;
|
||||
}
|
||||
else
|
||||
{
|
||||
// general case
|
||||
for ( j = lim; j < num; j++ )
|
||||
{
|
||||
LOOP_ALIGN
|
||||
|
||||
sum1 = 0;
|
||||
pout = out + j - 1;
|
||||
top = out[j-lim];
|
||||
|
||||
for ( k = 0; k < numactive; k++ )
|
||||
sum1 += coefs[k] * (pout[-k] - top);
|
||||
|
||||
del = pc1[j];
|
||||
del0 = del;
|
||||
sg = sign_of_int( del );
|
||||
del += top + ((sum1 + denhalf) >> denshift);
|
||||
out[j] = (del << chanshift) >> chanshift;
|
||||
|
||||
if ( sg > 0 )
|
||||
{
|
||||
for ( k = (numactive - 1); k >= 0; k-- )
|
||||
{
|
||||
dd = top - pout[-k];
|
||||
sgn = sign_of_int( dd );
|
||||
coefs[k] -= sgn;
|
||||
del0 -= (numactive - k) * ((sgn * dd) >> denshift);
|
||||
if ( del0 <= 0 )
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if ( sg < 0 )
|
||||
{
|
||||
for ( k = (numactive - 1); k >= 0; k-- )
|
||||
{
|
||||
dd = top - pout[-k];
|
||||
sgn = sign_of_int( dd );
|
||||
coefs[k] += sgn;
|
||||
del0 -= (numactive - k) * ((-sgn * dd) >> denshift);
|
||||
if ( del0 >= 0 )
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,380 @@
|
||||
/*
|
||||
* Copyright (c) 2011 Apple Inc. All rights reserved.
|
||||
*
|
||||
* @APPLE_APACHE_LICENSE_HEADER_START@
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @APPLE_APACHE_LICENSE_HEADER_END@
|
||||
*/
|
||||
|
||||
/*
|
||||
File: dp_enc.c
|
||||
|
||||
Contains: Dynamic Predictor encode routines
|
||||
|
||||
Copyright: (c) 2001-2011 Apple, Inc.
|
||||
*/
|
||||
|
||||
#include "dplib.h"
|
||||
#include <string.h>
|
||||
|
||||
#if __GNUC__
|
||||
#define ALWAYS_INLINE __attribute__((always_inline))
|
||||
#else
|
||||
#define ALWAYS_INLINE
|
||||
#endif
|
||||
|
||||
#define LOOP_ALIGN
|
||||
|
||||
void init_coefs( int16_t * coefs, uint32_t denshift, int32_t numPairs )
|
||||
{
|
||||
int32_t k;
|
||||
int32_t den = 1 << denshift;
|
||||
|
||||
coefs[0] = (AINIT * den) >> 4;
|
||||
coefs[1] = (BINIT * den) >> 4;
|
||||
coefs[2] = (CINIT * den) >> 4;
|
||||
for ( k = 3; k < numPairs; k++ )
|
||||
coefs[k] = 0;
|
||||
}
|
||||
|
||||
void copy_coefs( int16_t * srcCoefs, int16_t * dstCoefs, int32_t numPairs )
|
||||
{
|
||||
int32_t k;
|
||||
|
||||
for ( k = 0; k < numPairs; k++ )
|
||||
dstCoefs[k] = srcCoefs[k];
|
||||
}
|
||||
|
||||
static inline int32_t ALWAYS_INLINE sign_of_int( int32_t i )
|
||||
{
|
||||
int32_t negishift;
|
||||
|
||||
negishift = ((uint32_t)-i) >> 31;
|
||||
return negishift | (i >> 31);
|
||||
}
|
||||
|
||||
void pc_block( int32_t * in, int32_t * pc1, int32_t num, int16_t * coefs, int32_t numactive, uint32_t chanbits, uint32_t denshift )
|
||||
{
|
||||
register int16_t a0, a1, a2, a3;
|
||||
register int32_t b0, b1, b2, b3;
|
||||
int32_t j, k, lim;
|
||||
int32_t * pin;
|
||||
int32_t sum1, dd;
|
||||
int32_t sg, sgn;
|
||||
int32_t top;
|
||||
int32_t del, del0;
|
||||
uint32_t chanshift = 32 - chanbits;
|
||||
int32_t denhalf = 1 << (denshift - 1);
|
||||
|
||||
pc1[0] = in[0];
|
||||
if ( numactive == 0 )
|
||||
{
|
||||
// just copy if numactive == 0 (but don't bother if in/out pointers the same)
|
||||
if ( (num > 1) && (in != pc1) )
|
||||
memcpy( &pc1[1], &in[1], (num - 1) * sizeof(int32_t) );
|
||||
return;
|
||||
}
|
||||
if ( numactive == 31 )
|
||||
{
|
||||
// short-circuit if numactive == 31
|
||||
for( j = 1; j < num; j++ )
|
||||
{
|
||||
del = in[j] - in[j-1];
|
||||
pc1[j] = (del << chanshift) >> chanshift;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
for ( j = 1; j <= numactive; j++ )
|
||||
{
|
||||
del = in[j] - in[j-1];
|
||||
pc1[j] = (del << chanshift) >> chanshift;
|
||||
}
|
||||
|
||||
lim = numactive + 1;
|
||||
|
||||
if ( numactive == 4 )
|
||||
{
|
||||
// optimization for numactive == 4
|
||||
a0 = coefs[0];
|
||||
a1 = coefs[1];
|
||||
a2 = coefs[2];
|
||||
a3 = coefs[3];
|
||||
|
||||
for ( j = lim; j < num; j++ )
|
||||
{
|
||||
LOOP_ALIGN
|
||||
|
||||
top = in[j - lim];
|
||||
pin = in + j - 1;
|
||||
|
||||
b0 = top - pin[0];
|
||||
b1 = top - pin[-1];
|
||||
b2 = top - pin[-2];
|
||||
b3 = top - pin[-3];
|
||||
|
||||
sum1 = (denhalf - a0 * b0 - a1 * b1 - a2 * b2 - a3 * b3) >> denshift;
|
||||
|
||||
del = in[j] - top - sum1;
|
||||
del = (del << chanshift) >> chanshift;
|
||||
pc1[j] = del;
|
||||
del0 = del;
|
||||
|
||||
sg = sign_of_int(del);
|
||||
if ( sg > 0 )
|
||||
{
|
||||
sgn = sign_of_int( b3 );
|
||||
a3 -= sgn;
|
||||
del0 -= (4 - 3) * ((sgn * b3) >> denshift);
|
||||
if ( del0 <= 0 )
|
||||
continue;
|
||||
|
||||
sgn = sign_of_int( b2 );
|
||||
a2 -= sgn;
|
||||
del0 -= (4 - 2) * ((sgn * b2) >> denshift);
|
||||
if ( del0 <= 0 )
|
||||
continue;
|
||||
|
||||
sgn = sign_of_int( b1 );
|
||||
a1 -= sgn;
|
||||
del0 -= (4 - 1) * ((sgn * b1) >> denshift);
|
||||
if ( del0 <= 0 )
|
||||
continue;
|
||||
|
||||
a0 -= sign_of_int( b0 );
|
||||
}
|
||||
else if ( sg < 0 )
|
||||
{
|
||||
// note: to avoid unnecessary negations, we flip the value of "sgn"
|
||||
sgn = -sign_of_int( b3 );
|
||||
a3 -= sgn;
|
||||
del0 -= (4 - 3) * ((sgn * b3) >> denshift);
|
||||
if ( del0 >= 0 )
|
||||
continue;
|
||||
|
||||
sgn = -sign_of_int( b2 );
|
||||
a2 -= sgn;
|
||||
del0 -= (4 - 2) * ((sgn * b2) >> denshift);
|
||||
if ( del0 >= 0 )
|
||||
continue;
|
||||
|
||||
sgn = -sign_of_int( b1 );
|
||||
a1 -= sgn;
|
||||
del0 -= (4 - 1) * ((sgn * b1) >> denshift);
|
||||
if ( del0 >= 0 )
|
||||
continue;
|
||||
|
||||
a0 += sign_of_int( b0 );
|
||||
}
|
||||
}
|
||||
|
||||
coefs[0] = a0;
|
||||
coefs[1] = a1;
|
||||
coefs[2] = a2;
|
||||
coefs[3] = a3;
|
||||
}
|
||||
else if ( numactive == 8 )
|
||||
{
|
||||
// optimization for numactive == 8
|
||||
register int16_t a4, a5, a6, a7;
|
||||
register int32_t b4, b5, b6, b7;
|
||||
|
||||
a0 = coefs[0];
|
||||
a1 = coefs[1];
|
||||
a2 = coefs[2];
|
||||
a3 = coefs[3];
|
||||
a4 = coefs[4];
|
||||
a5 = coefs[5];
|
||||
a6 = coefs[6];
|
||||
a7 = coefs[7];
|
||||
|
||||
for ( j = lim; j < num; j++ )
|
||||
{
|
||||
LOOP_ALIGN
|
||||
|
||||
top = in[j - lim];
|
||||
pin = in + j - 1;
|
||||
|
||||
b0 = top - (*pin--);
|
||||
b1 = top - (*pin--);
|
||||
b2 = top - (*pin--);
|
||||
b3 = top - (*pin--);
|
||||
b4 = top - (*pin--);
|
||||
b5 = top - (*pin--);
|
||||
b6 = top - (*pin--);
|
||||
b7 = top - (*pin);
|
||||
pin += 8;
|
||||
|
||||
sum1 = (denhalf - a0 * b0 - a1 * b1 - a2 * b2 - a3 * b3
|
||||
- a4 * b4 - a5 * b5 - a6 * b6 - a7 * b7) >> denshift;
|
||||
|
||||
del = in[j] - top - sum1;
|
||||
del = (del << chanshift) >> chanshift;
|
||||
pc1[j] = del;
|
||||
del0 = del;
|
||||
|
||||
sg = sign_of_int(del);
|
||||
if ( sg > 0 )
|
||||
{
|
||||
sgn = sign_of_int( b7 );
|
||||
a7 -= sgn;
|
||||
del0 -= 1 * ((sgn * b7) >> denshift);
|
||||
if ( del0 <= 0 )
|
||||
continue;
|
||||
|
||||
sgn = sign_of_int( b6 );
|
||||
a6 -= sgn;
|
||||
del0 -= 2 * ((sgn * b6) >> denshift);
|
||||
if ( del0 <= 0 )
|
||||
continue;
|
||||
|
||||
sgn = sign_of_int( b5 );
|
||||
a5 -= sgn;
|
||||
del0 -= 3 * ((sgn * b5) >> denshift);
|
||||
if ( del0 <= 0 )
|
||||
continue;
|
||||
|
||||
sgn = sign_of_int( b4 );
|
||||
a4 -= sgn;
|
||||
del0 -= 4 * ((sgn * b4) >> denshift);
|
||||
if ( del0 <= 0 )
|
||||
continue;
|
||||
|
||||
sgn = sign_of_int( b3 );
|
||||
a3 -= sgn;
|
||||
del0 -= 5 * ((sgn * b3) >> denshift);
|
||||
if ( del0 <= 0 )
|
||||
continue;
|
||||
|
||||
sgn = sign_of_int( b2 );
|
||||
a2 -= sgn;
|
||||
del0 -= 6 * ((sgn * b2) >> denshift);
|
||||
if ( del0 <= 0 )
|
||||
continue;
|
||||
|
||||
sgn = sign_of_int( b1 );
|
||||
a1 -= sgn;
|
||||
del0 -= 7 * ((sgn * b1) >> denshift);
|
||||
if ( del0 <= 0 )
|
||||
continue;
|
||||
|
||||
a0 -= sign_of_int( b0 );
|
||||
}
|
||||
else if ( sg < 0 )
|
||||
{
|
||||
// note: to avoid unnecessary negations, we flip the value of "sgn"
|
||||
sgn = -sign_of_int( b7 );
|
||||
a7 -= sgn;
|
||||
del0 -= 1 * ((sgn * b7) >> denshift);
|
||||
if ( del0 >= 0 )
|
||||
continue;
|
||||
|
||||
sgn = -sign_of_int( b6 );
|
||||
a6 -= sgn;
|
||||
del0 -= 2 * ((sgn * b6) >> denshift);
|
||||
if ( del0 >= 0 )
|
||||
continue;
|
||||
|
||||
sgn = -sign_of_int( b5 );
|
||||
a5 -= sgn;
|
||||
del0 -= 3 * ((sgn * b5) >> denshift);
|
||||
if ( del0 >= 0 )
|
||||
continue;
|
||||
|
||||
sgn = -sign_of_int( b4 );
|
||||
a4 -= sgn;
|
||||
del0 -= 4 * ((sgn * b4) >> denshift);
|
||||
if ( del0 >= 0 )
|
||||
continue;
|
||||
|
||||
sgn = -sign_of_int( b3 );
|
||||
a3 -= sgn;
|
||||
del0 -= 5 * ((sgn * b3) >> denshift);
|
||||
if ( del0 >= 0 )
|
||||
continue;
|
||||
|
||||
sgn = -sign_of_int( b2 );
|
||||
a2 -= sgn;
|
||||
del0 -= 6 * ((sgn * b2) >> denshift);
|
||||
if ( del0 >= 0 )
|
||||
continue;
|
||||
|
||||
sgn = -sign_of_int( b1 );
|
||||
a1 -= sgn;
|
||||
del0 -= 7 * ((sgn * b1) >> denshift);
|
||||
if ( del0 >= 0 )
|
||||
continue;
|
||||
|
||||
a0 += sign_of_int( b0 );
|
||||
}
|
||||
}
|
||||
|
||||
coefs[0] = a0;
|
||||
coefs[1] = a1;
|
||||
coefs[2] = a2;
|
||||
coefs[3] = a3;
|
||||
coefs[4] = a4;
|
||||
coefs[5] = a5;
|
||||
coefs[6] = a6;
|
||||
coefs[7] = a7;
|
||||
}
|
||||
else
|
||||
{
|
||||
//pc_block_general:
|
||||
// general case
|
||||
for ( j = lim; j < num; j++ )
|
||||
{
|
||||
LOOP_ALIGN
|
||||
|
||||
top = in[j - lim];
|
||||
pin = in + j - 1;
|
||||
|
||||
sum1 = 0;
|
||||
for ( k = 0; k < numactive; k++ )
|
||||
sum1 -= coefs[k] * (top - pin[-k]);
|
||||
|
||||
del = in[j] - top - ((sum1 + denhalf) >> denshift);
|
||||
del = (del << chanshift) >> chanshift;
|
||||
pc1[j] = del;
|
||||
del0 = del;
|
||||
|
||||
sg = sign_of_int( del );
|
||||
if ( sg > 0 )
|
||||
{
|
||||
for ( k = (numactive - 1); k >= 0; k-- )
|
||||
{
|
||||
dd = top - pin[-k];
|
||||
sgn = sign_of_int( dd );
|
||||
coefs[k] -= sgn;
|
||||
del0 -= (numactive - k) * ((sgn * dd) >> denshift);
|
||||
if ( del0 <= 0 )
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if ( sg < 0 )
|
||||
{
|
||||
for ( k = (numactive - 1); k >= 0; k-- )
|
||||
{
|
||||
dd = top - pin[-k];
|
||||
sgn = sign_of_int( dd );
|
||||
coefs[k] += sgn;
|
||||
del0 -= (numactive - k) * ((-sgn * dd) >> denshift);
|
||||
if ( del0 >= 0 )
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (c) 2011 Apple Inc. All rights reserved.
|
||||
*
|
||||
* @APPLE_APACHE_LICENSE_HEADER_START@
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @APPLE_APACHE_LICENSE_HEADER_END@
|
||||
*/
|
||||
|
||||
/*
|
||||
File: dplib.h
|
||||
|
||||
Contains: Dynamic Predictor routines
|
||||
|
||||
Copyright: Copyright (C) 2001-2011 Apple, Inc.
|
||||
*/
|
||||
|
||||
#ifndef __DPLIB_H__
|
||||
#define __DPLIB_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// defines
|
||||
|
||||
#define DENSHIFT_MAX 15
|
||||
#define DENSHIFT_DEFAULT 9
|
||||
#define AINIT 38
|
||||
#define BINIT (-29)
|
||||
#define CINIT (-2)
|
||||
#define NUMCOEPAIRS 16
|
||||
|
||||
// prototypes
|
||||
|
||||
void init_coefs( int16_t * coefs, uint32_t denshift, int32_t numPairs );
|
||||
void copy_coefs( int16_t * srcCoefs, int16_t * dstCoefs, int32_t numPairs );
|
||||
|
||||
// NOTE: these routines read at least "numactive" samples so the i/o buffers must be at least that big
|
||||
|
||||
void pc_block( int32_t * in, int32_t * pc, int32_t num, int16_t * coefs, int32_t numactive, uint32_t chanbits, uint32_t denshift );
|
||||
void unpc_block( int32_t * pc, int32_t * out, int32_t num, int16_t * coefs, int32_t numactive, uint32_t chanbits, uint32_t denshift );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __DPLIB_H__ */
|
||||
@@ -0,0 +1,320 @@
|
||||
/*
|
||||
* Copyright (c) 2011 Apple Inc. All rights reserved.
|
||||
* Copyright (C) 2012 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
*
|
||||
* @APPLE_APACHE_LICENSE_HEADER_START@
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @APPLE_APACHE_LICENSE_HEADER_END@
|
||||
*/
|
||||
|
||||
/*
|
||||
File: matrix_dec.c
|
||||
|
||||
Contains: ALAC mixing/matrixing decode routines.
|
||||
|
||||
Copyright: (c) 2004-2011 Apple, Inc.
|
||||
*/
|
||||
|
||||
#include "matrixlib.h"
|
||||
#include "ALACAudioTypes.h"
|
||||
|
||||
// up to 24-bit "offset" macros for the individual bytes of a 20/24-bit word
|
||||
#if TARGET_RT_BIG_ENDIAN
|
||||
#define LBYTE 2
|
||||
#define MBYTE 1
|
||||
#define HBYTE 0
|
||||
#else
|
||||
#define LBYTE 0
|
||||
#define MBYTE 1
|
||||
#define HBYTE 2
|
||||
#endif
|
||||
|
||||
/*
|
||||
There is no plain middle-side option; instead there are various mixing
|
||||
modes including middle-side, each lossless, as embodied in the mix()
|
||||
and unmix() functions. These functions exploit a generalized middle-side
|
||||
transformation:
|
||||
|
||||
u := [(rL + (m-r)R)/m];
|
||||
v := L - R;
|
||||
|
||||
where [ ] denotes integer floor. The (lossless) inverse is
|
||||
|
||||
L = u + v - [rV/m];
|
||||
R = L - v;
|
||||
*/
|
||||
|
||||
// 16-bit routines
|
||||
|
||||
void unmix16( int32_t * u, int32_t * v, int32_t * out, uint32_t stride, int32_t numSamples, int32_t mixbits, int32_t mixres )
|
||||
{
|
||||
int32_t j;
|
||||
|
||||
if ( mixres != 0 )
|
||||
{
|
||||
/* matrixed stereo */
|
||||
for ( j = 0; j < numSamples; j++ )
|
||||
{
|
||||
int32_t l, r;
|
||||
|
||||
l = u[j] + v[j] - ((mixres * v[j]) >> mixbits);
|
||||
r = l - v[j];
|
||||
|
||||
out[0] = l << 16;
|
||||
out[1] = r << 16;
|
||||
out += stride;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Conventional separated stereo. */
|
||||
for ( j = 0; j < numSamples; j++ )
|
||||
{
|
||||
out[0] = u[j] << 16;
|
||||
out[1] = v[j] << 16;
|
||||
out += stride;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 20-bit routines
|
||||
// - the 20 bits of data are left-justified in 3 bytes of storage but right-aligned for input/output predictor buffers
|
||||
|
||||
void unmix20( int32_t * u, int32_t * v, int32_t * out, uint32_t stride, int32_t numSamples, int32_t mixbits, int32_t mixres )
|
||||
{
|
||||
int32_t j;
|
||||
|
||||
if ( mixres != 0 )
|
||||
{
|
||||
/* matrixed stereo */
|
||||
for ( j = 0; j < numSamples; j++ )
|
||||
{
|
||||
int32_t l, r;
|
||||
|
||||
l = u[j] + v[j] - ((mixres * v[j]) >> mixbits);
|
||||
r = l - v[j];
|
||||
|
||||
out[0] = l << 12;
|
||||
out[1] = r << 12;
|
||||
out += stride;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Conventional separated stereo. */
|
||||
for ( j = 0; j < numSamples; j++ )
|
||||
{
|
||||
out[0] = u[j] << 12;
|
||||
out[1] = v[j] << 12;
|
||||
out += stride;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 24-bit routines
|
||||
// - the 24 bits of data are right-justified in the input/output predictor buffers
|
||||
|
||||
void unmix24( int32_t * u, int32_t * v, int32_t * out, uint32_t stride, int32_t numSamples,
|
||||
int32_t mixbits, int32_t mixres, uint16_t * shiftUV, int32_t bytesShifted )
|
||||
{
|
||||
int32_t shift = bytesShifted * 8;
|
||||
int32_t l, r;
|
||||
int32_t j, k;
|
||||
|
||||
if ( mixres != 0 )
|
||||
{
|
||||
/* matrixed stereo */
|
||||
if ( bytesShifted != 0 )
|
||||
{
|
||||
for ( j = 0, k = 0; j < numSamples; j++, k += 2 )
|
||||
{
|
||||
l = u[j] + v[j] - ((mixres * v[j]) >> mixbits);
|
||||
r = l - v[j];
|
||||
|
||||
l = (l << shift) | (uint32_t) shiftUV[k + 0];
|
||||
r = (r << shift) | (uint32_t) shiftUV[k + 1];
|
||||
|
||||
out[0] = l << 8;
|
||||
out[1] = r << 8;
|
||||
out += stride;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for ( j = 0; j < numSamples; j++ )
|
||||
{
|
||||
l = u[j] + v[j] - ((mixres * v[j]) >> mixbits);
|
||||
r = l - v[j];
|
||||
|
||||
out[0] = l << 8;
|
||||
out[1] = r << 8;
|
||||
out += stride;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Conventional separated stereo. */
|
||||
if ( bytesShifted != 0 )
|
||||
{
|
||||
for ( j = 0, k = 0; j < numSamples; j++, k += 2 )
|
||||
{
|
||||
l = u[j];
|
||||
r = v[j];
|
||||
|
||||
l = (l << shift) | (uint32_t) shiftUV[k + 0];
|
||||
r = (r << shift) | (uint32_t) shiftUV[k + 1];
|
||||
|
||||
out[0] = l << 8;
|
||||
out[1] = r << 8;
|
||||
out += stride;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for ( j = 0; j < numSamples; j++ )
|
||||
{
|
||||
out[0] = u[j] << 8;
|
||||
out[1] = v[j] << 8;
|
||||
out += stride;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 32-bit routines
|
||||
// - note that these really expect the internal data width to be < 32 but the arrays are 32-bit
|
||||
// - otherwise, the calculations might overflow into the 33rd bit and be lost
|
||||
// - therefore, these routines deal with the specified "unused lower" bytes in the "shift" buffers
|
||||
|
||||
void unmix32( int32_t * u, int32_t * v, int32_t * out, uint32_t stride, int32_t numSamples,
|
||||
int32_t mixbits, int32_t mixres, uint16_t * shiftUV, int32_t bytesShifted )
|
||||
{
|
||||
int32_t shift = bytesShifted * 8;
|
||||
int32_t l, r;
|
||||
int32_t j, k;
|
||||
|
||||
if ( mixres != 0 )
|
||||
{
|
||||
//Assert( bytesShifted != 0 );
|
||||
|
||||
/* matrixed stereo with shift */
|
||||
for ( j = 0, k = 0; j < numSamples; j++, k += 2 )
|
||||
{
|
||||
int32_t lt, rt;
|
||||
|
||||
lt = u[j];
|
||||
rt = v[j];
|
||||
|
||||
l = lt + rt - ((mixres * rt) >> mixbits);
|
||||
r = l - rt;
|
||||
|
||||
out[0] = (l << shift) | (uint32_t) shiftUV[k + 0];
|
||||
out[1] = (r << shift) | (uint32_t) shiftUV[k + 1];
|
||||
out += stride;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( bytesShifted == 0 )
|
||||
{
|
||||
/* interleaving w/o shift */
|
||||
for ( j = 0; j < numSamples; j++ )
|
||||
{
|
||||
out[0] = u[j];
|
||||
out[1] = v[j];
|
||||
out += stride;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* interleaving with shift */
|
||||
for ( j = 0, k = 0; j < numSamples; j++, k += 2 )
|
||||
{
|
||||
out[0] = (u[j] << shift) | (uint32_t) shiftUV[k + 0];
|
||||
out[1] = (v[j] << shift) | (uint32_t) shiftUV[k + 1];
|
||||
out += stride;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 20/24-bit <-> 32-bit helper routines (not really matrixing but convenient to put here)
|
||||
|
||||
void copyPredictorTo24( int32_t * in, int32_t * out, uint32_t stride, int32_t numSamples )
|
||||
{
|
||||
int32_t j;
|
||||
|
||||
for ( j = 0; j < numSamples; j++ )
|
||||
{
|
||||
out[0] = in[j] << 8;
|
||||
out += stride;
|
||||
}
|
||||
}
|
||||
|
||||
void copyPredictorTo24Shift( int32_t * in, uint16_t * shift, int32_t * out, uint32_t stride, int32_t numSamples, int32_t bytesShifted )
|
||||
{
|
||||
int32_t shiftVal = bytesShifted * 8;
|
||||
int32_t j;
|
||||
|
||||
//Assert( bytesShifted != 0 );
|
||||
|
||||
for ( j = 0; j < numSamples; j++ )
|
||||
{
|
||||
int32_t val = in[j];
|
||||
|
||||
val = (val << shiftVal) | (uint32_t) shift[j];
|
||||
out[0] = val << 8;
|
||||
out += stride;
|
||||
}
|
||||
}
|
||||
|
||||
void copyPredictorTo20( int32_t * in, int32_t * out, uint32_t stride, int32_t numSamples )
|
||||
{
|
||||
int32_t j;
|
||||
|
||||
// 32-bit predictor values are right-aligned but 20-bit output values should be left-aligned
|
||||
// in the 24-bit output buffer
|
||||
for ( j = 0; j < numSamples; j++ )
|
||||
{
|
||||
out[0] = in[j] << 12;
|
||||
out += stride;
|
||||
}
|
||||
}
|
||||
|
||||
void copyPredictorTo32( int32_t * in, int32_t * out, uint32_t stride, int32_t numSamples )
|
||||
{
|
||||
int32_t i, j;
|
||||
|
||||
// this is only a subroutine to abstract the "iPod can only output 16-bit data" problem
|
||||
for ( i = 0, j = 0; i < numSamples; i++, j += stride )
|
||||
out[j] = in[i] << 8;
|
||||
}
|
||||
|
||||
void copyPredictorTo32Shift( int32_t * in, uint16_t * shift, int32_t * out, uint32_t stride, int32_t numSamples, int32_t bytesShifted )
|
||||
{
|
||||
int32_t * op = out;
|
||||
uint32_t shiftVal = bytesShifted * 8;
|
||||
int32_t j;
|
||||
|
||||
//Assert( bytesShifted != 0 );
|
||||
|
||||
// this is only a subroutine to abstract the "iPod can only output 16-bit data" problem
|
||||
for ( j = 0; j < numSamples; j++ )
|
||||
{
|
||||
op[0] = (in[j] << shiftVal) | (uint32_t) shift[j];
|
||||
op += stride;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,272 @@
|
||||
/*
|
||||
* Copyright (c) 2011 Apple Inc. All rights reserved.
|
||||
* Copyright (C) 2012 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
*
|
||||
* @APPLE_APACHE_LICENSE_HEADER_START@
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @APPLE_APACHE_LICENSE_HEADER_END@
|
||||
*/
|
||||
|
||||
/*
|
||||
File: matrix_enc.c
|
||||
|
||||
Contains: ALAC mixing/matrixing encode routines.
|
||||
|
||||
Copyright: (c) 2004-2011 Apple, Inc.
|
||||
*/
|
||||
|
||||
#include "matrixlib.h"
|
||||
#include "ALACAudioTypes.h"
|
||||
|
||||
/*
|
||||
There is no plain middle-side option; instead there are various mixing
|
||||
modes including middle-side, each lossless, as embodied in the mix()
|
||||
and unmix() functions. These functions exploit a generalized middle-side
|
||||
transformation:
|
||||
|
||||
u := [(rL + (m-r)R)/m];
|
||||
v := L - R;
|
||||
|
||||
where [ ] denotes integer floor. The (lossless) inverse is
|
||||
|
||||
L = u + v - [rV/m];
|
||||
R = L - v;
|
||||
*/
|
||||
|
||||
// 16-bit routines
|
||||
|
||||
void mix16( int32_t * in, uint32_t stride, int32_t * u, int32_t * v, int32_t numSamples, int32_t mixbits, int32_t mixres )
|
||||
{
|
||||
int32_t j;
|
||||
|
||||
if ( mixres != 0 )
|
||||
{
|
||||
int32_t mod = 1 << mixbits;
|
||||
int32_t m2;
|
||||
|
||||
/* matrixed stereo */
|
||||
m2 = mod - mixres;
|
||||
for ( j = 0; j < numSamples; j++ )
|
||||
{
|
||||
int32_t l, r;
|
||||
|
||||
l = in[0] >> 16;
|
||||
r = in[1] >> 16;
|
||||
in += stride;
|
||||
u[j] = (mixres * l + m2 * r) >> mixbits;
|
||||
v[j] = l - r;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Conventional separated stereo. */
|
||||
for ( j = 0; j < numSamples; j++ )
|
||||
{
|
||||
u[j] = in[0] >> 16;
|
||||
v[j] = in[1] >> 16;
|
||||
in += stride;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 20-bit routines
|
||||
// - the 20 bits of data are left-justified in 3 bytes of storage but right-aligned for input/output predictor buffers
|
||||
|
||||
void mix20( int32_t * in, uint32_t stride, int32_t * u, int32_t * v, int32_t numSamples, int32_t mixbits, int32_t mixres )
|
||||
{
|
||||
int32_t l, r;
|
||||
int32_t j;
|
||||
|
||||
if ( mixres != 0 )
|
||||
{
|
||||
/* matrixed stereo */
|
||||
int32_t mod = 1 << mixbits;
|
||||
int32_t m2 = mod - mixres;
|
||||
|
||||
for ( j = 0; j < numSamples; j++ )
|
||||
{
|
||||
l = in[0] >> 12;
|
||||
r = in[1] >> 12;
|
||||
in += stride;
|
||||
|
||||
u[j] = (mixres * l + m2 * r) >> mixbits;
|
||||
v[j] = l - r;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Conventional separated stereo. */
|
||||
for ( j = 0; j < numSamples; j++ )
|
||||
{
|
||||
u[j] = in[0] >> 12;
|
||||
v[j] = in[1] >> 12;
|
||||
in += stride;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 24-bit routines
|
||||
// - the 24 bits of data are right-justified in the input/output predictor buffers
|
||||
|
||||
void mix24( int32_t * in, uint32_t stride, int32_t * u, int32_t * v, int32_t numSamples,
|
||||
int32_t mixbits, int32_t mixres, uint16_t * shiftUV, int32_t bytesShifted )
|
||||
{
|
||||
int32_t l, r;
|
||||
int32_t shift = bytesShifted * 8;
|
||||
uint32_t mask = (1ul << shift) - 1;
|
||||
int32_t j, k;
|
||||
|
||||
if ( mixres != 0 )
|
||||
{
|
||||
/* matrixed stereo */
|
||||
int32_t mod = 1 << mixbits;
|
||||
int32_t m2 = mod - mixres;
|
||||
|
||||
if ( bytesShifted != 0 )
|
||||
{
|
||||
for ( j = 0, k = 0; j < numSamples; j++, k += 2 )
|
||||
{
|
||||
l = in[0] >> 8;
|
||||
r = in[1] >> 8;
|
||||
in += stride;
|
||||
|
||||
shiftUV[k + 0] = (uint16_t)(l & mask);
|
||||
shiftUV[k + 1] = (uint16_t)(r & mask);
|
||||
|
||||
l >>= shift;
|
||||
r >>= shift;
|
||||
|
||||
u[j] = (mixres * l + m2 * r) >> mixbits;
|
||||
v[j] = l - r;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for ( j = 0; j < numSamples; j++ )
|
||||
{
|
||||
l = in[0] >> 8;
|
||||
r = in[1] >> 8;
|
||||
in += stride;
|
||||
|
||||
u[j] = (mixres * l + m2 * r) >> mixbits;
|
||||
v[j] = l - r;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Conventional separated stereo. */
|
||||
if ( bytesShifted != 0 )
|
||||
{
|
||||
for ( j = 0, k = 0; j < numSamples; j++, k += 2 )
|
||||
{
|
||||
l = in[0] >> 8;
|
||||
r = in[1] >> 8;
|
||||
in += stride;
|
||||
|
||||
shiftUV[k + 0] = (uint16_t)(l & mask);
|
||||
shiftUV[k + 1] = (uint16_t)(r & mask);
|
||||
|
||||
l >>= shift;
|
||||
r >>= shift;
|
||||
|
||||
u[j] = l;
|
||||
v[j] = r;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for ( j = 0; j < numSamples; j++ )
|
||||
{
|
||||
l = in[0] >> 8;
|
||||
r = in[1] >> 8;
|
||||
in += stride;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 32-bit routines
|
||||
// - note that these really expect the internal data width to be < 32 but the arrays are 32-bit
|
||||
// - otherwise, the calculations might overflow into the 33rd bit and be lost
|
||||
// - therefore, these routines deal with the specified "unused lower" bytes in the "shift" buffers
|
||||
|
||||
void mix32( int32_t * in, uint32_t stride, int32_t * u, int32_t * v, int32_t numSamples,
|
||||
int32_t mixbits, int32_t mixres, uint16_t * shiftUV, int32_t bytesShifted )
|
||||
{
|
||||
int32_t shift = bytesShifted * 8;
|
||||
uint32_t mask = (1ul << shift) - 1;
|
||||
int32_t l, r;
|
||||
int32_t j, k;
|
||||
|
||||
if ( mixres != 0 )
|
||||
{
|
||||
int32_t mod = 1 << mixbits;
|
||||
int32_t m2;
|
||||
|
||||
//Assert( bytesShifted != 0 );
|
||||
|
||||
/* matrixed stereo with shift */
|
||||
m2 = mod - mixres;
|
||||
for ( j = 0, k = 0; j < numSamples; j++, k += 2 )
|
||||
{
|
||||
l = in[0];
|
||||
r = in[1];
|
||||
in += stride;
|
||||
|
||||
shiftUV[k + 0] = (uint16_t)(l & mask);
|
||||
shiftUV[k + 1] = (uint16_t)(r & mask);
|
||||
|
||||
l >>= shift;
|
||||
r >>= shift;
|
||||
|
||||
u[j] = (mixres * l + m2 * r) >> mixbits;
|
||||
v[j] = l - r;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( bytesShifted == 0 )
|
||||
{
|
||||
/* de-interleaving w/o shift */
|
||||
for ( j = 0; j < numSamples; j++ )
|
||||
{
|
||||
u[j] = in[0];
|
||||
v[j] = in[1];
|
||||
in += stride;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* de-interleaving with shift */
|
||||
for ( j = 0, k = 0; j < numSamples; j++, k += 2 )
|
||||
{
|
||||
l = in[0];
|
||||
r = in[1];
|
||||
in += stride;
|
||||
|
||||
shiftUV[k + 0] = (uint16_t)(l & mask);
|
||||
shiftUV[k + 1] = (uint16_t)(r & mask);
|
||||
|
||||
l >>= shift;
|
||||
r >>= shift;
|
||||
|
||||
u[j] = l;
|
||||
v[j] = r;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (c) 2011 Apple Inc. All rights reserved.
|
||||
* Copyright (C) 2012 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
*
|
||||
* @APPLE_APACHE_LICENSE_HEADER_START@
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @APPLE_APACHE_LICENSE_HEADER_END@
|
||||
*/
|
||||
|
||||
/*
|
||||
File: matrixlib.h
|
||||
|
||||
Contains: ALAC mixing/matrixing routines to/from 32-bit predictor buffers.
|
||||
|
||||
Copyright: Copyright (C) 2004 to 2011 Apple, Inc.
|
||||
*/
|
||||
|
||||
#ifndef __MATRIXLIB_H
|
||||
#define __MATRIXLIB_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// 16-bit routines
|
||||
void mix16( int32_t * in, uint32_t stride, int32_t * u, int32_t * v, int32_t numSamples, int32_t mixbits, int32_t mixres );
|
||||
void unmix16( int32_t * u, int32_t * v, int32_t * out, uint32_t stride, int32_t numSamples, int32_t mixbits, int32_t mixres );
|
||||
|
||||
// 20-bit routines
|
||||
void mix20( int32_t * in, uint32_t stride, int32_t * u, int32_t * v, int32_t numSamples, int32_t mixbits, int32_t mixres );
|
||||
void unmix20( int32_t * u, int32_t * v, int32_t * out, uint32_t stride, int32_t numSamples, int32_t mixbits, int32_t mixres );
|
||||
|
||||
// 24-bit routines
|
||||
// - 24-bit data sometimes compresses better by shifting off the bottom byte so these routines deal with
|
||||
// the specified "unused lower bytes" in the combined "shift" buffer
|
||||
void mix24( int32_t * in, uint32_t stride, int32_t * u, int32_t * v, int32_t numSamples,
|
||||
int32_t mixbits, int32_t mixres, uint16_t * shiftUV, int32_t bytesShifted );
|
||||
void unmix24( int32_t * u, int32_t * v, int32_t * out, uint32_t stride, int32_t numSamples,
|
||||
int32_t mixbits, int32_t mixres, uint16_t * shiftUV, int32_t bytesShifted );
|
||||
|
||||
// 32-bit routines
|
||||
// - note that these really expect the internal data width to be < 32-bit but the arrays are 32-bit
|
||||
// - otherwise, the calculations might overflow into the 33rd bit and be lost
|
||||
// - therefore, these routines deal with the specified "unused lower" bytes in the combined "shift" buffer
|
||||
void mix32( int32_t * in, uint32_t stride, int32_t * u, int32_t * v, int32_t numSamples,
|
||||
int32_t mixbits, int32_t mixres, uint16_t * shiftUV, int32_t bytesShifted );
|
||||
void unmix32( int32_t * u, int32_t * v, int32_t * out, uint32_t stride, int32_t numSamples,
|
||||
int32_t mixbits, int32_t mixres, uint16_t * shiftUV, int32_t bytesShifted );
|
||||
|
||||
// 20/24/32-bit <-> 32-bit helper routines (not really matrixing but convenient to put here)
|
||||
void copy20ToPredictor( int32_t * in, uint32_t stride, int32_t * out, int32_t numSamples );
|
||||
void copy24ToPredictor( int32_t * in, uint32_t stride, int32_t * out, int32_t numSamples );
|
||||
|
||||
void copyPredictorTo24( int32_t * in, int32_t * out, uint32_t stride, int32_t numSamples );
|
||||
void copyPredictorTo24Shift( int32_t * in, uint16_t * shift, int32_t * out, uint32_t stride, int32_t numSamples, int32_t bytesShifted );
|
||||
void copyPredictorTo20( int32_t * in, int32_t * out, uint32_t stride, int32_t numSamples );
|
||||
|
||||
void copyPredictorTo32( int32_t * in, int32_t * out, uint32_t stride, int32_t numSamples );
|
||||
void copyPredictorTo32Shift( int32_t * in, uint16_t * shift, int32_t * out, uint32_t stride, int32_t numSamples, int32_t bytesShifted );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __MATRIXLIB_H */
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** Copyright (C) 1999-2009 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
** Copyright (C) 1999-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
/*
|
||||
** Copyright (C) 1999-2009 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** Copyright (C) 1999-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program 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.
|
||||
**
|
||||
**
|
||||
** This program 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
|
||||
** along with this program; if not, write to the Free Software
|
||||
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
@@ -77,20 +77,20 @@ main (int argc, char *argv [])
|
||||
return 0 ;
|
||||
} /* main */
|
||||
|
||||
static void
|
||||
static void
|
||||
g721_test (void)
|
||||
{
|
||||
return ;
|
||||
} /* g721_test */
|
||||
|
||||
static void
|
||||
static void
|
||||
g723_test (double margin)
|
||||
{ static double orig_buffer [BUFFER_SIZE] ;
|
||||
static short orig [BUFFER_SIZE] ;
|
||||
static short data [BUFFER_SIZE] ;
|
||||
|
||||
G72x_STATE encoder_state, decoder_state ;
|
||||
|
||||
|
||||
long k ;
|
||||
int code, position, max_err ;
|
||||
|
||||
@@ -104,10 +104,10 @@ g723_test (double margin)
|
||||
|
||||
memset (data, 0, BUFFER_SIZE * sizeof (short)) ;
|
||||
memset (orig, 0, BUFFER_SIZE * sizeof (short)) ;
|
||||
|
||||
|
||||
printf (" g723_test : ") ;
|
||||
fflush (stdout) ;
|
||||
|
||||
|
||||
gen_signal_double (orig_buffer, 32000.0, BUFFER_SIZE) ;
|
||||
for (k = 0 ; k < BUFFER_SIZE ; k++)
|
||||
orig [k] = (short) orig_buffer [k] ;
|
||||
@@ -144,13 +144,13 @@ g723_test (double margin)
|
||||
#define SIGNAL_MAXVAL 30000.0
|
||||
#define DECAY_COUNT 1000
|
||||
|
||||
static void
|
||||
static void
|
||||
gen_signal_double (double *gendata, double scale, int gendatalen)
|
||||
{ int k, ramplen ;
|
||||
double amp = 0.0 ;
|
||||
|
||||
|
||||
ramplen = DECAY_COUNT ;
|
||||
|
||||
|
||||
for (k = 0 ; k < gendatalen ; k++)
|
||||
{ if (k <= ramplen)
|
||||
amp = scale * k / ((double) ramplen) ;
|
||||
@@ -160,11 +160,11 @@ gen_signal_double (double *gendata, double scale, int gendatalen)
|
||||
gendata [k] = amp * (0.4 * sin (33.3 * 2.0 * M_PI * ((double) (k+1)) / ((double) SAMPLE_RATE))
|
||||
+ 0.3 * cos (201.1 * 2.0 * M_PI * ((double) (k+1)) / ((double) SAMPLE_RATE))) ;
|
||||
} ;
|
||||
|
||||
|
||||
return ;
|
||||
} /* gen_signal_double */
|
||||
|
||||
static int
|
||||
static int
|
||||
error_function (double data, double orig, double margin)
|
||||
{ double error ;
|
||||
|
||||
@@ -174,7 +174,7 @@ error_function (double data, double orig, double margin)
|
||||
error = fabs (data - orig) / 3000.0 ;
|
||||
else
|
||||
error = fabs (data - orig) / fabs (orig) ;
|
||||
|
||||
|
||||
if (error > margin)
|
||||
{ printf ("\n\n*******************\nError : %f\n", error) ;
|
||||
return 1 ;
|
||||
@@ -182,21 +182,21 @@ error_function (double data, double orig, double margin)
|
||||
return 0 ;
|
||||
} /* error_function */
|
||||
|
||||
static int
|
||||
static int
|
||||
oct_save_short (short *a, short *b, int len)
|
||||
{ FILE *file ;
|
||||
int k ;
|
||||
|
||||
if (! (file = fopen ("error.dat", "w")))
|
||||
return 1 ;
|
||||
|
||||
|
||||
fprintf (file, "# Not created by Octave\n") ;
|
||||
|
||||
|
||||
fprintf (file, "# name: a\n") ;
|
||||
fprintf (file, "# type: matrix\n") ;
|
||||
fprintf (file, "# rows: %d\n", len) ;
|
||||
fprintf (file, "# columns: 1\n") ;
|
||||
|
||||
|
||||
for (k = 0 ; k < len ; k++)
|
||||
fprintf (file, "% d\n", a [k]) ;
|
||||
|
||||
@@ -204,7 +204,7 @@ oct_save_short (short *a, short *b, int len)
|
||||
fprintf (file, "# type: matrix\n") ;
|
||||
fprintf (file, "# rows: %d\n", len) ;
|
||||
fprintf (file, "# columns: 1\n") ;
|
||||
|
||||
|
||||
for (k = 0 ; k < len ; k++)
|
||||
fprintf (file, "% d\n", b [k]) ;
|
||||
|
||||
|
||||
@@ -1,100 +1,134 @@
|
||||
## Process this file with automake to produce Makefile.in
|
||||
|
||||
SUBDIRS = GSM610 G72x
|
||||
AUTOMAKE_OPTIONS = subdir-objects
|
||||
|
||||
INCLUDES = @EXTERNAL_CFLAGS@
|
||||
AM_CPPFLAGS = @EXTERNAL_CFLAGS@
|
||||
|
||||
lib_LTLIBRARIES = libsndfile.la
|
||||
include_HEADERS = sndfile.hh
|
||||
nodist_include_HEADERS = sndfile.h
|
||||
|
||||
noinst_LTLIBRARIES = libcommon.la
|
||||
noinst_LTLIBRARIES = GSM610/libgsm.la G72x/libg72x.la ALAC/libalac.la libcommon.la
|
||||
|
||||
OS_SPECIFIC_CFLAGS = @OS_SPECIFIC_CFLAGS@
|
||||
OS_SPECIFIC_LINKS = @OS_SPECIFIC_LINKS@
|
||||
|
||||
SYMBOL_FILES = Symbols.linux Symbols.darwin libsndfile-1.def Symbols.os2
|
||||
SYMBOL_FILES = Symbols.gnu-binutils Symbols.darwin libsndfile-1.def Symbols.os2 Symbols.static
|
||||
|
||||
EXTRA_DIST = sndfile.h.in config.h.in test_endswap.tpl test_endswap.def \
|
||||
$(SYMBOL_FILES) create_symbols_file.py binheader_writef_check.py
|
||||
$(SYMBOL_FILES) create_symbols_file.py binheader_writef_check.py \
|
||||
GSM610/README GSM610/COPYRIGHT GSM610/ChangeLog \
|
||||
G72x/README G72x/README.original G72x/ChangeLog \
|
||||
make-static-lib-hidden-privates.sh
|
||||
|
||||
noinst_HEADERS = common.h sfconfig.h sfendian.h wav_w64.h sf_unistd.h
|
||||
noinst_HEADERS = common.h sfconfig.h sfendian.h wav_w64.h sf_unistd.h ogg.h chanmap.h
|
||||
|
||||
noinst_PROGRAMS =
|
||||
check_PROGRAMS = test_main G72x/g72x_test
|
||||
|
||||
COMMON = common.c file_io.c command.c pcm.c ulaw.c alaw.c float32.c \
|
||||
double64.c ima_adpcm.c ms_adpcm.c gsm610.c dwvw.c vox_adpcm.c \
|
||||
interleave.c strings.c dither.c broadcast.c audio_detect.c \
|
||||
ima_oki_adpcm.c ima_oki_adpcm.h chunk.c
|
||||
interleave.c strings.c dither.c cart.c broadcast.c audio_detect.c \
|
||||
ima_oki_adpcm.c ima_oki_adpcm.h alac.c chunk.c ogg.c chanmap.c \
|
||||
windows.c id3.c $(WIN_VERSION_FILE)
|
||||
|
||||
FILESPECIFIC = sndfile.c aiff.c au.c avr.c caf.c dwd.c flac.c g72x.c htk.c ircam.c \
|
||||
macbinary3.c macos.c mat4.c mat5.c nist.c ogg.c paf.c pvf.c raw.c rx2.c sd2.c \
|
||||
sds.c svx.c txw.c voc.c wve.c w64.c wav_w64.c wav.c xi.c mpc2k.c rf64.c
|
||||
macbinary3.c macos.c mat4.c mat5.c nist.c paf.c pvf.c raw.c rx2.c sd2.c \
|
||||
sds.c svx.c txw.c voc.c wve.c w64.c wav_w64.c wav.c xi.c mpc2k.c rf64.c \
|
||||
ogg_vorbis.c ogg_speex.c ogg_pcm.c ogg_opus.c
|
||||
|
||||
CLEANFILES = *~ *.exe G72x/*.exe
|
||||
|
||||
if USE_WIN_VERSION_FILE
|
||||
WIN_VERSION_FILE = version-metadata.rc
|
||||
else
|
||||
WIN_VERSION_FILE =
|
||||
endif
|
||||
|
||||
#===============================================================================
|
||||
# MinGW requires -no-undefined if a DLL is to be built.
|
||||
libsndfile_la_LDFLAGS = -no-undefined -version-info @SHARED_VERSION_INFO@ @SHLIB_VERSION_ARG@
|
||||
libsndfile_la_SOURCES = $(FILESPECIFIC) $(noinst_HEADERS)
|
||||
nodist_libsndfile_la_SOURCES = $(nodist_include_HEADERS)
|
||||
libsndfile_la_LIBADD = libcommon.la GSM610/libgsm.la G72x/libg72x.la \
|
||||
@EXTERNAL_LIBS@ -lm
|
||||
libsndfile_la_LIBADD = GSM610/libgsm.la G72x/libg72x.la ALAC/libalac.la \
|
||||
libcommon.la @EXTERNAL_LIBS@ -lm
|
||||
|
||||
libcommon_la_SOURCES = $(COMMON)
|
||||
|
||||
#test_main_SOURCES = test_main.c test_main.h test_conversions.c test_float.c test_endswap.c \
|
||||
# test_audio_detect.c test_log_printf.c test_file_io.c test_ima_oki_adpcm.c
|
||||
#test_main_LDADD = libcommon.la
|
||||
#
|
||||
#
|
||||
#test_endswap.c: test_endswap.def test_endswap.tpl
|
||||
# autogen --writable test_endswap.def
|
||||
#======================================================================
|
||||
# Subdir libraries.
|
||||
|
||||
genfiles : $(SYMBOL_FILES)
|
||||
GSM610_libgsm_la_SOURCES = GSM610/config.h GSM610/gsm.h GSM610/gsm610_priv.h \
|
||||
GSM610/add.c GSM610/code.c GSM610/decode.c GSM610/gsm_create.c \
|
||||
GSM610/gsm_decode.c GSM610/gsm_destroy.c GSM610/gsm_encode.c \
|
||||
GSM610/gsm_option.c GSM610/long_term.c GSM610/lpc.c GSM610/preprocess.c \
|
||||
GSM610/rpe.c GSM610/short_term.c GSM610/table.c
|
||||
|
||||
# A single test programs.
|
||||
# It is not possible to place these in the tests/ directory because they
|
||||
# need access to the internals of the SF_PRIVATE struct.
|
||||
G72x_libg72x_la_SOURCES = G72x/g72x.h G72x/g72x_priv.h \
|
||||
G72x/g721.c G72x/g723_16.c G72x/g723_24.c G72x/g723_40.c G72x/g72x.c
|
||||
|
||||
check: $(noinst_PROGRAMS)
|
||||
@echo
|
||||
@echo
|
||||
@echo
|
||||
@echo "============================================================"
|
||||
@if [ -x /usr/bin/python2.5 ]; then $(srcdir)/binheader_writef_check.py $(srcdir)/*.c ; fi
|
||||
ALAC_libalac_la_SOURCES = ALAC/ALACAudioTypes.h ALAC/ALACBitUtilities.h \
|
||||
ALAC/EndianPortable.h ALAC/aglib.h ALAC/dplib.h ALAC/matrixlib.h \
|
||||
ALAC/alac_codec.h \
|
||||
ALAC/ALACBitUtilities.c ALAC/ag_dec.c \
|
||||
ALAC/ag_enc.c ALAC/dp_dec.c ALAC/dp_enc.c ALAC/matrix_dec.c \
|
||||
ALAC/matrix_enc.c ALAC/alac_decoder.c ALAC/alac_encoder.c
|
||||
|
||||
#===============================================================================
|
||||
# Test programs.
|
||||
|
||||
test_main_SOURCES = test_main.c test_main.h test_conversions.c test_float.c test_endswap.c \
|
||||
test_audio_detect.c test_log_printf.c test_file_io.c test_ima_oki_adpcm.c \
|
||||
test_strncpy_crlf.c test_broadcast_var.c test_cart_var.c
|
||||
test_main_LDADD = libcommon.la
|
||||
|
||||
G72x_g72x_test_SOURCES = G72x/g72x_test.c
|
||||
G72x_g72x_test_LDADD = G72x/libg72x.la
|
||||
|
||||
test_endswap.c: test_endswap.def test_endswap.tpl
|
||||
cd $(srcdir) && autogen --writable test_endswap.def && cd $(abs_builddir)
|
||||
|
||||
genfiles : $(SYMBOL_FILES) test_endswap.c
|
||||
|
||||
check :
|
||||
@if [ -x /usr/bin/python ]; then $(srcdir)/binheader_writef_check.py $(srcdir)/*.c ; fi
|
||||
G72x/g72x_test$(EXEEXT) all
|
||||
./test_main$(EXEEXT)
|
||||
@echo "============================================================"
|
||||
@echo
|
||||
@echo
|
||||
@echo
|
||||
|
||||
# Need this target to force building of test programs.
|
||||
checkprograms : $(check_PROGRAMS)
|
||||
|
||||
#======================================================================
|
||||
# Generate an OS specific Symbols files. This is done when the author
|
||||
# builds the distribution tarball. There should be not need for the
|
||||
# end user to create these files.
|
||||
|
||||
Symbols.linux: create_symbols_file.py
|
||||
./create_symbols_file.py linux $(VERSION) > $@
|
||||
Symbols.gnu-binutils: create_symbols_file.py
|
||||
python $(srcdir)/create_symbols_file.py linux $(VERSION) > $@
|
||||
|
||||
Symbols.darwin: create_symbols_file.py
|
||||
./create_symbols_file.py darwin $(VERSION) > $@
|
||||
python $(srcdir)/create_symbols_file.py darwin $(VERSION) > $@
|
||||
|
||||
libsndfile-1.def: create_symbols_file.py
|
||||
./create_symbols_file.py win32 $(VERSION) > $@
|
||||
python $(srcdir)/create_symbols_file.py win32 $(VERSION) > $@
|
||||
|
||||
Symbols.os2: create_symbols_file.py
|
||||
./create_symbols_file.py os2 $(VERSION) > $@
|
||||
python $(srcdir)/create_symbols_file.py os2 $(VERSION) > $@
|
||||
|
||||
Symbols.static: create_symbols_file.py
|
||||
python $(srcdir)/create_symbols_file.py static $(VERSION) > $@
|
||||
|
||||
# Fake dependancy to force the creation of these files.
|
||||
sndfile.o : $(SYMBOL_FILES)
|
||||
|
||||
#======================================================================
|
||||
# Building windows resource files (if needed).
|
||||
|
||||
.rc.lo:
|
||||
$(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --tag=RC --mode=compile $(RC) $(RCFLAGS) $< -o $@
|
||||
|
||||
#======================================================================
|
||||
# Disable autoheader.
|
||||
AUTOHEADER=echo
|
||||
|
||||
# Dependancies.
|
||||
|
||||
aiff.c au.c g72x.c ircam.c mat4.c mat5.c nist.c paf.c pvf.c : sndfile.h common.h
|
||||
raw.c svx.c voc.c w64.c wav.c wav_w64.c htk.c sd2.c rx2.c txw.c : sndfile.h common.h
|
||||
sds.c wve.c dwd.c ogg.c xi.c sndfile.c common.c file_io.c : sndfile.h common.h
|
||||
command.c pcm.c ulaw.c alaw.c float32.c double64.c ima_adpcm.c : sndfile.h common.h
|
||||
ms_adpcm.c gsm610.c dwvw.c vox_adpcm.c interleave.c strings.c : sndfile.h common.h
|
||||
dither.c : sndfile.h common.h
|
||||
|
||||
@@ -30,6 +30,7 @@ _sf_write_double
|
||||
_sf_strerror
|
||||
_sf_get_string
|
||||
_sf_set_string
|
||||
_sf_version_string
|
||||
_sf_open_fd
|
||||
_sf_open_virtual
|
||||
_sf_write_sync
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
; Auto-generated by create_symbols_file.py
|
||||
|
||||
LIBRARY sndfile1.dll
|
||||
LIBRARY sndfile1
|
||||
INITINSTANCE TERMINSTANCE
|
||||
CODE PRELOAD MOVEABLE DISCARDABLE
|
||||
DATA PRELOAD MOVEABLE MULTIPLE NONSHARED
|
||||
@@ -36,6 +36,7 @@ _sf_write_double @40
|
||||
_sf_strerror @50
|
||||
_sf_get_string @60
|
||||
_sf_set_string @61
|
||||
_sf_version_string @68
|
||||
_sf_open_fd @70
|
||||
_sf_open_virtual @80
|
||||
_sf_write_sync @90
|
||||
|
||||
+424
-258
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,966 @@
|
||||
/*
|
||||
** Copyright (C) 2011-2013 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program 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 program 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 program; if not, write to the Free Software
|
||||
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "sfconfig.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "sndfile.h"
|
||||
#include "sfendian.h"
|
||||
#include "common.h"
|
||||
#include "ALAC/alac_codec.h"
|
||||
#include "ALAC/ALACBitUtilities.h"
|
||||
|
||||
#define ALAC_MAX_FRAME_SIZE 8192
|
||||
#define ALAC_BYTE_BUFFER_SIZE 82000
|
||||
|
||||
|
||||
typedef struct
|
||||
{ uint32_t current, count, allocated ;
|
||||
uint32_t packet_size [] ;
|
||||
} PAKT_INFO ;
|
||||
|
||||
typedef struct
|
||||
{ sf_count_t input_data_pos ;
|
||||
|
||||
PAKT_INFO * pakt_info ;
|
||||
|
||||
int channels, final_write_block ;
|
||||
|
||||
uint32_t frames_this_block, partial_block_frames, frames_per_block ;
|
||||
uint32_t bits_per_sample, kuki_size ;
|
||||
|
||||
|
||||
/* Can't have a decoder and an encoder at the same time so stick
|
||||
** them in an un-named union.
|
||||
*/
|
||||
union
|
||||
{ ALAC_DECODER decoder ;
|
||||
ALAC_ENCODER encoder ;
|
||||
} ;
|
||||
|
||||
char enctmpname [512] ;
|
||||
FILE *enctmp ;
|
||||
|
||||
int buffer [] ;
|
||||
|
||||
} ALAC_PRIVATE ;
|
||||
|
||||
/*============================================================================================
|
||||
*/
|
||||
|
||||
static int alac_reader_init (SF_PRIVATE *psf, const ALAC_DECODER_INFO * info) ;
|
||||
static int alac_writer_init (SF_PRIVATE *psf) ;
|
||||
|
||||
static sf_count_t alac_reader_calc_frames (SF_PRIVATE *psf, ALAC_PRIVATE *plac) ;
|
||||
|
||||
static sf_count_t alac_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ;
|
||||
static sf_count_t alac_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ;
|
||||
static sf_count_t alac_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ;
|
||||
static sf_count_t alac_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ;
|
||||
|
||||
static sf_count_t alac_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ;
|
||||
static sf_count_t alac_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ;
|
||||
static sf_count_t alac_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ;
|
||||
static sf_count_t alac_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ;
|
||||
|
||||
static sf_count_t alac_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) ;
|
||||
|
||||
static int alac_close (SF_PRIVATE *psf) ;
|
||||
static int alac_byterate (SF_PRIVATE *psf) ;
|
||||
|
||||
static int alac_decode_block (SF_PRIVATE *psf, ALAC_PRIVATE *plac) ;
|
||||
static int alac_encode_block (SF_PRIVATE *psf, ALAC_PRIVATE *plac) ;
|
||||
|
||||
static uint32_t alac_kuki_read (SF_PRIVATE * psf, uint32_t kuki_offset, uint8_t * kuki, size_t kuki_maxlen) ;
|
||||
|
||||
static PAKT_INFO * alac_pakt_alloc (uint32_t initial_count) ;
|
||||
static PAKT_INFO * alac_pakt_read_decode (SF_PRIVATE * psf, uint32_t pakt_offset) ;
|
||||
static PAKT_INFO * alac_pakt_append (PAKT_INFO * info, uint32_t value) ;
|
||||
static uint8_t * alac_pakt_encode (const SF_PRIVATE *psf, uint32_t * pakt_size) ;
|
||||
static sf_count_t alac_pakt_block_offset (const PAKT_INFO *info, uint32_t block) ;
|
||||
|
||||
/*============================================================================================
|
||||
** ALAC Reader initialisation function.
|
||||
*/
|
||||
|
||||
int
|
||||
alac_init (SF_PRIVATE *psf, const ALAC_DECODER_INFO * info)
|
||||
{ int error ;
|
||||
|
||||
if ((psf->codec_data = calloc (1, sizeof (ALAC_PRIVATE) + psf->sf.channels * sizeof (int) * ALAC_MAX_FRAME_SIZE)) == NULL)
|
||||
return SFE_MALLOC_FAILED ;
|
||||
|
||||
psf->codec_close = alac_close ;
|
||||
|
||||
switch (psf->file.mode)
|
||||
{ case SFM_RDWR :
|
||||
return SFE_BAD_MODE_RW ;
|
||||
|
||||
case SFM_READ :
|
||||
if ((error = alac_reader_init (psf, info)))
|
||||
return error ;
|
||||
break ;
|
||||
|
||||
case SFM_WRITE :
|
||||
if ((error = alac_writer_init (psf)))
|
||||
return error ;
|
||||
break ;
|
||||
|
||||
default :
|
||||
psf_log_printf (psf, "%s : Bad psf->file.mode.\n", __func__) ;
|
||||
return SFE_INTERNAL ;
|
||||
} ;
|
||||
|
||||
psf->byterate = alac_byterate ;
|
||||
|
||||
return 0 ;
|
||||
} /* aiff_alac_init */
|
||||
|
||||
void
|
||||
alac_get_desc_chunk_items (int subformat, uint32_t *fmt_flags, uint32_t *frames_per_packet)
|
||||
{ switch (subformat)
|
||||
{ case SF_FORMAT_ALAC_16 :
|
||||
*fmt_flags = 1 ;
|
||||
break ;
|
||||
case SF_FORMAT_ALAC_20 :
|
||||
*fmt_flags = 2 ;
|
||||
break ;
|
||||
case SF_FORMAT_ALAC_24 :
|
||||
*fmt_flags = 3 ;
|
||||
break ;
|
||||
case SF_FORMAT_ALAC_32 :
|
||||
*fmt_flags = 4 ;
|
||||
break ;
|
||||
default :
|
||||
break ;
|
||||
} ;
|
||||
*frames_per_packet = ALAC_FRAME_LENGTH ;
|
||||
} /* alac_get_desc_chunk_items */
|
||||
|
||||
static int
|
||||
alac_close (SF_PRIVATE *psf)
|
||||
{ ALAC_PRIVATE *plac ;
|
||||
BUF_UNION ubuf ;
|
||||
|
||||
plac = psf->codec_data ;
|
||||
|
||||
if (psf->file.mode == SFM_WRITE)
|
||||
{ ALAC_ENCODER *penc = &plac->encoder ;
|
||||
SF_CHUNK_INFO chunk_info ;
|
||||
sf_count_t readcount ;
|
||||
uint32_t pakt_size = 0, saved_partial_block_frames ;
|
||||
uint8_t *kuki_data = (uint8_t *)malloc (plac->kuki_size);
|
||||
|
||||
if (!kuki_data)
|
||||
{
|
||||
return SFE_MALLOC_FAILED ;
|
||||
}
|
||||
|
||||
plac->final_write_block = 1 ;
|
||||
saved_partial_block_frames = plac->partial_block_frames ;
|
||||
|
||||
/* If a block has been partially assembled, write it out as the final block. */
|
||||
if (plac->partial_block_frames && plac->partial_block_frames < plac->frames_per_block)
|
||||
alac_encode_block (psf, plac) ;
|
||||
|
||||
plac->partial_block_frames = saved_partial_block_frames ;
|
||||
|
||||
alac_get_magic_cookie (penc, kuki_data, &plac->kuki_size) ;
|
||||
|
||||
memset (&chunk_info, 0, sizeof (chunk_info)) ;
|
||||
chunk_info.id_size = snprintf (chunk_info.id, sizeof (chunk_info.id), "kuki") ;
|
||||
chunk_info.data = kuki_data ;
|
||||
chunk_info.datalen = plac->kuki_size ;
|
||||
psf_save_write_chunk (&psf->wchunks, &chunk_info) ;
|
||||
|
||||
memset (&chunk_info, 0, sizeof (chunk_info)) ;
|
||||
chunk_info.id_size = snprintf (chunk_info.id, sizeof (chunk_info.id), "pakt") ;
|
||||
chunk_info.data = alac_pakt_encode (psf, &pakt_size) ;
|
||||
chunk_info.datalen = pakt_size ;
|
||||
psf_save_write_chunk (&psf->wchunks, &chunk_info) ;
|
||||
|
||||
free (chunk_info.data) ;
|
||||
chunk_info.data = NULL ;
|
||||
|
||||
psf->write_header (psf, 1) ;
|
||||
|
||||
if (plac->enctmp != NULL)
|
||||
{ fseek (plac->enctmp, 0, SEEK_SET) ;
|
||||
|
||||
while ((readcount = fread (ubuf.ucbuf, 1, sizeof (ubuf.ucbuf), plac->enctmp)) > 0)
|
||||
psf_fwrite (ubuf.ucbuf, 1, readcount, psf) ;
|
||||
fclose (plac->enctmp) ;
|
||||
remove (plac->enctmpname) ;
|
||||
} ;
|
||||
free(kuki_data);
|
||||
} ;
|
||||
|
||||
if (plac->pakt_info)
|
||||
free (plac->pakt_info) ;
|
||||
plac->pakt_info = NULL ;
|
||||
|
||||
return 0 ;
|
||||
} /* alac_close */
|
||||
|
||||
static int
|
||||
alac_byterate (SF_PRIVATE *psf)
|
||||
{
|
||||
if (psf->file.mode == SFM_READ)
|
||||
return (psf->datalength * psf->sf.samplerate) / psf->sf.frames ;
|
||||
|
||||
return -1 ;
|
||||
} /* alac_byterate */
|
||||
|
||||
/*============================================================================================
|
||||
** ALAC initialisation Functions.
|
||||
*/
|
||||
|
||||
static int
|
||||
alac_reader_init (SF_PRIVATE *psf, const ALAC_DECODER_INFO * info)
|
||||
{ ALAC_PRIVATE *plac ;
|
||||
uint32_t kuki_size ;
|
||||
union { uint8_t kuki [512] ; uint32_t alignment ; } u ;
|
||||
|
||||
if (info == NULL)
|
||||
{ psf_log_printf (psf, "%s : ALAC_DECODER_INFO is NULL.\n", __func__) ;
|
||||
return SFE_INTERNAL ;
|
||||
} ;
|
||||
|
||||
plac = psf->codec_data ;
|
||||
|
||||
plac->channels = psf->sf.channels ;
|
||||
plac->frames_per_block = info->frames_per_packet ;
|
||||
plac->bits_per_sample = info->bits_per_sample ;
|
||||
|
||||
if (plac->pakt_info != NULL)
|
||||
free (plac->pakt_info) ;
|
||||
plac->pakt_info = alac_pakt_read_decode (psf, info->pakt_offset) ;
|
||||
|
||||
|
||||
if (plac->pakt_info == NULL)
|
||||
{ psf_log_printf (psf, "%s : alac_pkt_read() returns NULL.\n", __func__) ;
|
||||
return SFE_MALLOC_FAILED ;
|
||||
} ;
|
||||
|
||||
/* Read in the ALAC cookie data and pass it to the init function. */
|
||||
kuki_size = alac_kuki_read (psf, info->kuki_offset, u.kuki, sizeof (u.kuki)) ;
|
||||
|
||||
alac_decoder_init (&plac->decoder, u.kuki, kuki_size) ;
|
||||
|
||||
switch (info->bits_per_sample)
|
||||
{ case 16 :
|
||||
case 20 :
|
||||
case 24 :
|
||||
case 32 :
|
||||
psf->read_short = alac_read_s ;
|
||||
psf->read_int = alac_read_i ;
|
||||
psf->read_float = alac_read_f ;
|
||||
psf->read_double = alac_read_d ;
|
||||
break ;
|
||||
|
||||
default :
|
||||
printf ("%s : info->bits_per_sample %u\n", __func__, info->bits_per_sample) ;
|
||||
return SFE_UNSUPPORTED_ENCODING ;
|
||||
} ;
|
||||
|
||||
psf->codec_close = alac_close ;
|
||||
psf->seek = alac_seek ;
|
||||
|
||||
psf->sf.frames = alac_reader_calc_frames (psf, plac) ;
|
||||
alac_seek (psf, SFM_READ, 0) ;
|
||||
|
||||
return 0 ;
|
||||
} /* alac_reader_init */
|
||||
|
||||
static int
|
||||
alac_writer_init (SF_PRIVATE *psf)
|
||||
{ ALAC_PRIVATE *plac ;
|
||||
uint32_t alac_format_flags = 0 ;
|
||||
|
||||
plac = psf->codec_data ;
|
||||
|
||||
if (psf->file.mode != SFM_WRITE)
|
||||
return SFE_BAD_MODE_RW ;
|
||||
|
||||
plac->channels = psf->sf.channels ;
|
||||
plac->kuki_size = alac_get_magic_cookie_size (psf->sf.channels) ;
|
||||
|
||||
psf->write_short = alac_write_s ;
|
||||
psf->write_int = alac_write_i ;
|
||||
psf->write_float = alac_write_f ;
|
||||
psf->write_double = alac_write_d ;
|
||||
|
||||
switch (SF_CODEC (psf->sf.format))
|
||||
{ case SF_FORMAT_ALAC_16 :
|
||||
alac_format_flags = 1 ;
|
||||
plac->bits_per_sample = 16 ;
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_ALAC_20 :
|
||||
alac_format_flags = 2 ;
|
||||
plac->bits_per_sample = 20 ;
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_ALAC_24 :
|
||||
alac_format_flags = 3 ;
|
||||
plac->bits_per_sample = 24 ;
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_ALAC_32 :
|
||||
alac_format_flags = 4 ;
|
||||
plac->bits_per_sample = 32 ;
|
||||
break ;
|
||||
|
||||
default :
|
||||
psf_log_printf (psf, "%s : Can't figure out bits per sample.\n", __func__) ;
|
||||
return SFE_UNIMPLEMENTED ;
|
||||
} ;
|
||||
|
||||
plac->frames_per_block = ALAC_FRAME_LENGTH ;
|
||||
|
||||
plac->pakt_info = alac_pakt_alloc (2000) ;
|
||||
|
||||
if ((plac->enctmp = psf_open_tmpfile (plac->enctmpname, sizeof (plac->enctmpname))) == NULL)
|
||||
{ psf_log_printf (psf, "Error : Failed to open temp file '%s' : \n", plac->enctmpname, strerror (errno)) ;
|
||||
return SFE_ALAC_FAIL_TMPFILE ;
|
||||
} ;
|
||||
|
||||
alac_encoder_init (&plac->encoder, psf->sf.samplerate, psf->sf.channels, alac_format_flags, ALAC_FRAME_LENGTH) ;
|
||||
|
||||
return 0 ;
|
||||
} /* alac_writer_init */
|
||||
|
||||
/*============================================================================================
|
||||
** ALAC block decoder and encoder.
|
||||
*/
|
||||
|
||||
static inline uint32_t
|
||||
alac_reader_next_packet_size (PAKT_INFO * info)
|
||||
{ if (info->current >= info->count)
|
||||
return 0 ;
|
||||
return info->packet_size [info->current++] ;
|
||||
} /* alac_reader_next_packet_size */
|
||||
|
||||
static sf_count_t
|
||||
alac_reader_calc_frames (SF_PRIVATE *psf, ALAC_PRIVATE *plac)
|
||||
{ sf_count_t frames = 0 ;
|
||||
uint32_t current_pos = 1, blocks = 0 ;
|
||||
|
||||
plac->pakt_info->current = 0 ;
|
||||
|
||||
while (current_pos < psf->filelength && current_pos > 0)
|
||||
{ current_pos = alac_reader_next_packet_size (plac->pakt_info) ;
|
||||
blocks = current_pos > 0 ? blocks + 1 : blocks ;
|
||||
} ;
|
||||
|
||||
if (blocks == 0)
|
||||
return 0 ;
|
||||
|
||||
/* Only count full blocks. */
|
||||
frames = plac->frames_per_block * (blocks - 1) ;
|
||||
|
||||
alac_seek (psf, SFM_READ, frames) ;
|
||||
alac_decode_block (psf, plac) ;
|
||||
frames += plac->frames_this_block ;
|
||||
|
||||
plac->pakt_info->current = 0 ;
|
||||
|
||||
return frames ;
|
||||
} /* alac_reader_calc_frames */
|
||||
|
||||
static int
|
||||
alac_decode_block (SF_PRIVATE *psf, ALAC_PRIVATE *plac)
|
||||
{ ALAC_DECODER *pdec = &plac->decoder ;
|
||||
uint8_t byte_buffer [ALAC_BYTE_BUFFER_SIZE] ;
|
||||
uint32_t packet_size ;
|
||||
BitBuffer bit_buffer ;
|
||||
|
||||
packet_size = alac_reader_next_packet_size (plac->pakt_info) ;
|
||||
if (packet_size == 0)
|
||||
{ if (plac->pakt_info->current < plac->pakt_info->count)
|
||||
psf_log_printf (psf, "packet_size is 0 (%d of %d)\n", plac->pakt_info->current, plac->pakt_info->count) ;
|
||||
return 0 ;
|
||||
} ;
|
||||
|
||||
psf_fseek (psf, plac->input_data_pos, SEEK_SET) ;
|
||||
|
||||
if (packet_size > SIGNED_SIZEOF (byte_buffer))
|
||||
{ psf_log_printf (psf, "%s : bad packet_size (%u)\n", __func__, packet_size) ;
|
||||
return 0 ;
|
||||
} ;
|
||||
|
||||
if ((packet_size != psf_fread (byte_buffer, 1, packet_size, psf)))
|
||||
return 0 ;
|
||||
|
||||
BitBufferInit (&bit_buffer, byte_buffer, packet_size) ;
|
||||
|
||||
plac->input_data_pos += packet_size ;
|
||||
plac->frames_this_block = 0 ;
|
||||
alac_decode (pdec, &bit_buffer, plac->buffer, plac->frames_per_block, psf->sf.channels, &plac->frames_this_block) ;
|
||||
|
||||
plac->partial_block_frames = 0 ;
|
||||
|
||||
return 1 ;
|
||||
} /* alac_decode_block */
|
||||
|
||||
|
||||
static int
|
||||
alac_encode_block (SF_PRIVATE * psf, ALAC_PRIVATE *plac)
|
||||
{ ALAC_ENCODER *penc = &plac->encoder ;
|
||||
uint32_t num_bytes = 0 ;
|
||||
uint8_t* byte_buffer = (uint8_t*)malloc (psf->sf.channels * ALAC_BYTE_BUFFER_SIZE) ;
|
||||
|
||||
if (!byte_buffer)
|
||||
{
|
||||
return SFE_MALLOC_FAILED ;
|
||||
}
|
||||
|
||||
alac_encode (penc, plac->channels, plac->partial_block_frames, plac->buffer, byte_buffer, &num_bytes) ;
|
||||
|
||||
if (fwrite (byte_buffer, 1, num_bytes, plac->enctmp) != num_bytes)
|
||||
{
|
||||
free (byte_buffer);
|
||||
return 0 ;
|
||||
}
|
||||
free(byte_buffer);
|
||||
|
||||
if ((plac->pakt_info = alac_pakt_append (plac->pakt_info, num_bytes)) == NULL)
|
||||
return 0 ;
|
||||
|
||||
plac->partial_block_frames = 0 ;
|
||||
|
||||
return 1 ;
|
||||
} /* alac_encode_block */
|
||||
|
||||
/*============================================================================================
|
||||
** ALAC read functions.
|
||||
*/
|
||||
|
||||
static sf_count_t
|
||||
alac_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
|
||||
{ ALAC_PRIVATE *plac ;
|
||||
int *iptr ;
|
||||
int k, readcount ;
|
||||
sf_count_t total = 0 ;
|
||||
|
||||
if ((plac = (ALAC_PRIVATE*) psf->codec_data) == NULL)
|
||||
return 0 ;
|
||||
|
||||
while (len > 0)
|
||||
{ if (plac->partial_block_frames >= plac->frames_this_block && alac_decode_block (psf, plac) == 0)
|
||||
break ;
|
||||
|
||||
readcount = (plac->frames_this_block - plac->partial_block_frames) * plac->channels ;
|
||||
readcount = readcount > len ? len : readcount ;
|
||||
|
||||
iptr = plac->buffer + plac->partial_block_frames * plac->channels ;
|
||||
|
||||
for (k = 0 ; k < readcount ; k++)
|
||||
ptr [total + k] = iptr [k] >> 16 ;
|
||||
|
||||
plac->partial_block_frames += readcount / plac->channels ;
|
||||
total += readcount ;
|
||||
len -= readcount ;
|
||||
} ;
|
||||
|
||||
return total ;
|
||||
} /* alac_read_s */
|
||||
|
||||
static sf_count_t
|
||||
alac_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
|
||||
{ ALAC_PRIVATE *plac ;
|
||||
int *iptr ;
|
||||
int k, readcount ;
|
||||
sf_count_t total = 0 ;
|
||||
|
||||
if ((plac = (ALAC_PRIVATE*) psf->codec_data) == NULL)
|
||||
return 0 ;
|
||||
|
||||
while (len > 0)
|
||||
{ if (plac->partial_block_frames >= plac->frames_this_block && alac_decode_block (psf, plac) == 0)
|
||||
break ;
|
||||
|
||||
readcount = (plac->frames_this_block - plac->partial_block_frames) * plac->channels ;
|
||||
readcount = readcount > len ? len : readcount ;
|
||||
|
||||
iptr = plac->buffer + plac->partial_block_frames * plac->channels ;
|
||||
|
||||
for (k = 0 ; k < readcount ; k++)
|
||||
ptr [total + k] = iptr [k] ;
|
||||
|
||||
plac->partial_block_frames += readcount / plac->channels ;
|
||||
total += readcount ;
|
||||
len -= readcount ;
|
||||
} ;
|
||||
|
||||
return total ;
|
||||
} /* alac_read_i */
|
||||
|
||||
static sf_count_t
|
||||
alac_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
|
||||
{ ALAC_PRIVATE *plac ;
|
||||
int *iptr ;
|
||||
int k, readcount ;
|
||||
sf_count_t total = 0 ;
|
||||
float normfact ;
|
||||
|
||||
if ((plac = (ALAC_PRIVATE*) psf->codec_data) == NULL)
|
||||
return 0 ;
|
||||
|
||||
normfact = (psf->norm_float == SF_TRUE) ? 1.0 / ((float) 0x80000000) : 1.0 ;
|
||||
|
||||
while (len > 0)
|
||||
{ if (plac->partial_block_frames >= plac->frames_this_block && alac_decode_block (psf, plac) == 0)
|
||||
break ;
|
||||
|
||||
readcount = (plac->frames_this_block - plac->partial_block_frames) * plac->channels ;
|
||||
readcount = readcount > len ? len : readcount ;
|
||||
|
||||
iptr = plac->buffer + plac->partial_block_frames * plac->channels ;
|
||||
|
||||
for (k = 0 ; k < readcount ; k++)
|
||||
ptr [total + k] = normfact * iptr [k] ;
|
||||
|
||||
plac->partial_block_frames += readcount / plac->channels ;
|
||||
total += readcount ;
|
||||
len -= readcount ;
|
||||
} ;
|
||||
|
||||
return total ;
|
||||
} /* alac_read_f */
|
||||
|
||||
static sf_count_t
|
||||
alac_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
|
||||
{ ALAC_PRIVATE *plac ;
|
||||
int *iptr ;
|
||||
int k, readcount ;
|
||||
sf_count_t total = 0 ;
|
||||
double normfact ;
|
||||
|
||||
if ((plac = (ALAC_PRIVATE*) psf->codec_data) == NULL)
|
||||
return 0 ;
|
||||
|
||||
normfact = (psf->norm_double == SF_TRUE) ? 1.0 / ((float) 0x80000000) : 1.0 ;
|
||||
|
||||
while (len > 0)
|
||||
{ if (plac->partial_block_frames >= plac->frames_this_block && alac_decode_block (psf, plac) == 0)
|
||||
break ;
|
||||
|
||||
readcount = (plac->frames_this_block - plac->partial_block_frames) * plac->channels ;
|
||||
readcount = readcount > len ? len : readcount ;
|
||||
|
||||
iptr = plac->buffer + plac->partial_block_frames * plac->channels ;
|
||||
|
||||
for (k = 0 ; k < readcount ; k++)
|
||||
ptr [total + k] = normfact * iptr [k] ;
|
||||
|
||||
plac->partial_block_frames += readcount / plac->channels ;
|
||||
total += readcount ;
|
||||
len -= readcount ;
|
||||
} ;
|
||||
|
||||
return total ;
|
||||
} /* alac_read_d */
|
||||
|
||||
/*============================================================================================
|
||||
*/
|
||||
|
||||
static sf_count_t
|
||||
alac_seek (SF_PRIVATE *psf, int mode, sf_count_t offset)
|
||||
{ ALAC_PRIVATE *plac ;
|
||||
int newblock, newsample ;
|
||||
|
||||
if (! psf->codec_data)
|
||||
return 0 ;
|
||||
plac = (ALAC_PRIVATE*) psf->codec_data ;
|
||||
|
||||
if (psf->datalength < 0 || psf->dataoffset < 0)
|
||||
{ psf->error = SFE_BAD_SEEK ;
|
||||
return PSF_SEEK_ERROR ;
|
||||
} ;
|
||||
|
||||
if (offset == 0)
|
||||
{ psf_fseek (psf, psf->dataoffset, SEEK_SET) ;
|
||||
|
||||
plac->frames_this_block = 0 ;
|
||||
plac->input_data_pos = psf->dataoffset ;
|
||||
plac->pakt_info->current = 0 ;
|
||||
return 0 ;
|
||||
} ;
|
||||
|
||||
if (offset < 0 || offset > plac->pakt_info->count * plac->frames_per_block)
|
||||
{ psf->error = SFE_BAD_SEEK ;
|
||||
return PSF_SEEK_ERROR ;
|
||||
} ;
|
||||
|
||||
newblock = offset / plac->frames_per_block ;
|
||||
newsample = offset % plac->frames_per_block ;
|
||||
|
||||
if (mode == SFM_READ)
|
||||
{ plac->input_data_pos = psf->dataoffset + alac_pakt_block_offset (plac->pakt_info, newblock) ;
|
||||
|
||||
plac->pakt_info->current = newblock ;
|
||||
alac_decode_block (psf, plac) ;
|
||||
plac->partial_block_frames = newsample ;
|
||||
}
|
||||
else
|
||||
{ /* What to do about write??? */
|
||||
psf->error = SFE_BAD_SEEK ;
|
||||
return PSF_SEEK_ERROR ;
|
||||
} ;
|
||||
|
||||
return newblock * plac->frames_per_block + newsample ;
|
||||
} /* alac_seek */
|
||||
|
||||
/*==========================================================================================
|
||||
** ALAC Write Functions.
|
||||
*/
|
||||
|
||||
static sf_count_t
|
||||
alac_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len)
|
||||
{ ALAC_PRIVATE *plac ;
|
||||
int *iptr ;
|
||||
int k, writecount ;
|
||||
sf_count_t total = 0 ;
|
||||
|
||||
if ((plac = (ALAC_PRIVATE*) psf->codec_data) == NULL)
|
||||
return 0 ;
|
||||
|
||||
while (len > 0)
|
||||
{ writecount = (plac->frames_per_block - plac->partial_block_frames) * plac->channels ;
|
||||
writecount = (writecount == 0 || writecount > len) ? len : writecount ;
|
||||
|
||||
iptr = plac->buffer + plac->partial_block_frames * plac->channels ;
|
||||
|
||||
for (k = 0 ; k < writecount ; k++)
|
||||
iptr [k] = ptr [total + k] << 16 ;
|
||||
|
||||
plac->partial_block_frames += writecount / plac->channels ;
|
||||
total += writecount ;
|
||||
len -= writecount ;
|
||||
|
||||
if (plac->partial_block_frames >= plac->frames_per_block)
|
||||
alac_encode_block (psf, plac) ;
|
||||
} ;
|
||||
|
||||
return total ;
|
||||
} /* alac_write_s */
|
||||
|
||||
static sf_count_t
|
||||
alac_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len)
|
||||
{ ALAC_PRIVATE *plac ;
|
||||
int *iptr ;
|
||||
int k, writecount ;
|
||||
sf_count_t total = 0 ;
|
||||
|
||||
if ((plac = (ALAC_PRIVATE*) psf->codec_data) == NULL)
|
||||
return 0 ;
|
||||
|
||||
while (len > 0)
|
||||
{ writecount = (plac->frames_per_block - plac->partial_block_frames) * plac->channels ;
|
||||
writecount = (writecount == 0 || writecount > len) ? len : writecount ;
|
||||
|
||||
iptr = plac->buffer + plac->partial_block_frames * plac->channels ;
|
||||
|
||||
for (k = 0 ; k < writecount ; k++)
|
||||
iptr [k] = ptr [total + k] ;
|
||||
|
||||
plac->partial_block_frames += writecount / plac->channels ;
|
||||
total += writecount ;
|
||||
len -= writecount ;
|
||||
|
||||
if (plac->partial_block_frames >= plac->frames_per_block)
|
||||
alac_encode_block (psf, plac) ;
|
||||
} ;
|
||||
|
||||
return total ;
|
||||
} /* alac_write_i */
|
||||
|
||||
static sf_count_t
|
||||
alac_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
|
||||
{ ALAC_PRIVATE *plac ;
|
||||
void (*convert) (const float *, int *t, int, int) ;
|
||||
int *iptr ;
|
||||
int writecount ;
|
||||
sf_count_t total = 0 ;
|
||||
|
||||
if ((plac = (ALAC_PRIVATE*) psf->codec_data) == NULL)
|
||||
return 0 ;
|
||||
|
||||
convert = (psf->add_clipping) ? psf_f2i_clip_array : psf_f2i_array ;
|
||||
|
||||
while (len > 0)
|
||||
{ writecount = (plac->frames_per_block - plac->partial_block_frames) * plac->channels ;
|
||||
writecount = (writecount == 0 || writecount > len) ? len : writecount ;
|
||||
|
||||
iptr = plac->buffer + plac->partial_block_frames * plac->channels ;
|
||||
|
||||
convert (ptr, iptr, writecount, psf->norm_float) ;
|
||||
|
||||
plac->partial_block_frames += writecount / plac->channels ;
|
||||
total += writecount ;
|
||||
len -= writecount ;
|
||||
|
||||
if (plac->partial_block_frames >= plac->frames_per_block)
|
||||
alac_encode_block (psf, plac) ;
|
||||
} ;
|
||||
|
||||
return total ;
|
||||
} /* alac_write_f */
|
||||
|
||||
static sf_count_t
|
||||
alac_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
|
||||
{ ALAC_PRIVATE *plac ;
|
||||
void (*convert) (const double *, int *t, int, int) ;
|
||||
int *iptr ;
|
||||
int writecount ;
|
||||
sf_count_t total = 0 ;
|
||||
|
||||
if ((plac = (ALAC_PRIVATE*) psf->codec_data) == NULL)
|
||||
return 0 ;
|
||||
|
||||
convert = (psf->add_clipping) ? psf_d2i_clip_array : psf_d2i_array ;
|
||||
|
||||
while (len > 0)
|
||||
{ writecount = (plac->frames_per_block - plac->partial_block_frames) * plac->channels ;
|
||||
writecount = (writecount == 0 || writecount > len) ? len : writecount ;
|
||||
|
||||
iptr = plac->buffer + plac->partial_block_frames * plac->channels ;
|
||||
|
||||
convert (ptr, iptr, writecount, psf->norm_float) ;
|
||||
|
||||
plac->partial_block_frames += writecount / plac->channels ;
|
||||
total += writecount ;
|
||||
len -= writecount ;
|
||||
|
||||
if (plac->partial_block_frames >= plac->frames_per_block)
|
||||
alac_encode_block (psf, plac) ;
|
||||
} ;
|
||||
|
||||
return total ;
|
||||
} /* alac_write_d */
|
||||
|
||||
/*==============================================================================
|
||||
** PAKT_INFO handling.
|
||||
*/
|
||||
|
||||
static PAKT_INFO *
|
||||
alac_pakt_alloc (uint32_t initial_count)
|
||||
{ PAKT_INFO * info ;
|
||||
|
||||
if ((info = calloc (1, sizeof (PAKT_INFO) + initial_count * sizeof (info->packet_size [0]))) == NULL)
|
||||
return NULL ;
|
||||
|
||||
info->allocated = initial_count ;
|
||||
info->current = 0 ;
|
||||
info->count = 0 ;
|
||||
|
||||
return info ;
|
||||
} /* alac_pakt_alloc */
|
||||
|
||||
static PAKT_INFO *
|
||||
alac_pakt_append (PAKT_INFO * info, uint32_t value)
|
||||
{
|
||||
if (info->count >= info->allocated)
|
||||
{ PAKT_INFO * temp ;
|
||||
uint32_t newcount = info->allocated + info->allocated / 2 ;
|
||||
|
||||
if ((temp = realloc (info, sizeof (PAKT_INFO) + newcount * sizeof (info->packet_size [0]))) == NULL)
|
||||
return NULL ;
|
||||
|
||||
info = temp ;
|
||||
info->allocated = newcount ;
|
||||
} ;
|
||||
|
||||
info->packet_size [info->count++] = value ;
|
||||
return info ;
|
||||
} /* alac_pakt_append */
|
||||
|
||||
static PAKT_INFO *
|
||||
alac_pakt_read_decode (SF_PRIVATE * psf, uint32_t UNUSED (pakt_offset))
|
||||
{ SF_CHUNK_INFO chunk_info ;
|
||||
PAKT_INFO * info = NULL ;
|
||||
uint8_t *pakt_data = NULL ;
|
||||
uint32_t bcount, value = 1, pakt_size ;
|
||||
SF_CHUNK_ITERATOR * chunk_iterator ;
|
||||
|
||||
|
||||
memset (&chunk_info, 0, sizeof (chunk_info)) ;
|
||||
snprintf (chunk_info.id, sizeof (chunk_info.id), "pakt") ;
|
||||
chunk_info.id_size = 4 ;
|
||||
|
||||
if ((chunk_iterator = psf_get_chunk_iterator (psf, chunk_info.id)) == NULL)
|
||||
{ printf ("%s %d : no chunk iterator found\n\n", __func__, __LINE__) ;
|
||||
free (chunk_info.data) ;
|
||||
chunk_info.data = NULL ;
|
||||
return NULL ;
|
||||
} ;
|
||||
|
||||
psf->get_chunk_size (psf, chunk_iterator, &chunk_info) ;
|
||||
|
||||
pakt_size = chunk_info.datalen ;
|
||||
chunk_info.data = pakt_data = malloc (pakt_size + 5) ;
|
||||
|
||||
if ((bcount = psf->get_chunk_data (psf, chunk_iterator, &chunk_info)) != SF_ERR_NO_ERROR)
|
||||
{ printf ("%s %d : %s\n\n", __func__, __LINE__, sf_error_number (bcount)) ;
|
||||
while (chunk_iterator)
|
||||
chunk_iterator = psf->next_chunk_iterator (psf, chunk_iterator) ;
|
||||
free (chunk_info.data) ;
|
||||
chunk_info.data = NULL ;
|
||||
return NULL ;
|
||||
} ;
|
||||
|
||||
while (chunk_iterator)
|
||||
chunk_iterator = psf->next_chunk_iterator (psf, chunk_iterator) ;
|
||||
|
||||
info = alac_pakt_alloc (pakt_size / 4) ;
|
||||
|
||||
/* Start at 24 bytes in, skipping over the 'pakt' chunks header. */
|
||||
for (bcount = 24 ; bcount < pakt_size && value != 0 ; )
|
||||
{ uint8_t byte ;
|
||||
int32_t count = 0 ;
|
||||
|
||||
value = 0 ;
|
||||
do
|
||||
{ byte = pakt_data [bcount + count] ;
|
||||
value = (value << 7) + (byte & 0x7F) ;
|
||||
|
||||
count ++ ;
|
||||
if (count > 5 || bcount + count > pakt_size)
|
||||
{ printf ("%s %d : Ooops! count %d bcount %d\n", __func__, __LINE__, count, bcount) ;
|
||||
value = 0 ;
|
||||
break ;
|
||||
} ;
|
||||
}
|
||||
while (byte & 0x80) ;
|
||||
|
||||
bcount += count ;
|
||||
|
||||
if ((info = alac_pakt_append (info, value)) == NULL)
|
||||
goto FreeExit ;
|
||||
} ;
|
||||
|
||||
free (pakt_data) ;
|
||||
|
||||
return info ;
|
||||
|
||||
FreeExit :
|
||||
free (pakt_data) ;
|
||||
free (info) ;
|
||||
return NULL ;
|
||||
} /* alac_pakt_read_decode */
|
||||
|
||||
static uint8_t *
|
||||
alac_pakt_encode (const SF_PRIVATE *psf, uint32_t * pakt_size_out)
|
||||
{ const ALAC_PRIVATE *plac ;
|
||||
const PAKT_INFO *info ;
|
||||
uint8_t *data ;
|
||||
uint32_t k, allocated, pakt_size ;
|
||||
|
||||
plac = psf->codec_data ;
|
||||
info = plac->pakt_info ;
|
||||
|
||||
allocated = 100 + 2 * info->count ;
|
||||
if ((data = calloc (1, allocated)) == NULL)
|
||||
return NULL ;
|
||||
|
||||
psf_put_be64 (data, 0, info->count) ;
|
||||
psf_put_be64 (data, 8, psf->sf.frames) ;
|
||||
psf_put_be32 (data, 20, kALACDefaultFramesPerPacket - plac->partial_block_frames) ;
|
||||
|
||||
/* Real 'pakt' data starts after 24 byte header. */
|
||||
pakt_size = 24 ;
|
||||
|
||||
for (k = 0 ; k < info->count ; k++)
|
||||
{ int32_t value = info->packet_size [k] ;
|
||||
|
||||
if ((value & 0x7f) == value)
|
||||
{ data [pakt_size++] = value ;
|
||||
continue ;
|
||||
} ;
|
||||
|
||||
if ((value & 0x3fff) == value)
|
||||
{ data [pakt_size++] = (value >> 7) | 0x80 ;
|
||||
data [pakt_size++] = value & 0x7f ;
|
||||
continue ;
|
||||
} ;
|
||||
|
||||
if ((value & 0x1fffff) == value)
|
||||
{ data [pakt_size++] = (value >> 14) | 0x80 ;
|
||||
data [pakt_size++] = ((value >> 7) & 0x7f) | 0x80 ;
|
||||
data [pakt_size++] = value & 0x7f ;
|
||||
continue ;
|
||||
} ;
|
||||
|
||||
if ((value & 0x0fffffff) == value)
|
||||
{ data [pakt_size++] = (value >> 21) | 0x80 ;
|
||||
data [pakt_size++] = ((value >> 14) & 0x7f) | 0x80 ;
|
||||
data [pakt_size++] = ((value >> 7) & 0x7f) | 0x80 ;
|
||||
data [pakt_size++] = value & 0x7f ;
|
||||
continue ;
|
||||
} ;
|
||||
|
||||
*pakt_size_out = 0 ;
|
||||
free (data) ;
|
||||
return NULL ;
|
||||
} ;
|
||||
|
||||
*pakt_size_out = pakt_size ;
|
||||
return data ;
|
||||
} /* alac_pakt_encode */
|
||||
|
||||
static sf_count_t
|
||||
alac_pakt_block_offset (const PAKT_INFO *info, uint32_t block)
|
||||
{ sf_count_t offset = 0 ;
|
||||
uint32_t k ;
|
||||
|
||||
for (k = 0 ; k < block ; k++)
|
||||
offset += info->packet_size [k] ;
|
||||
|
||||
return offset ;
|
||||
} /* alac_pakt_block_offset */
|
||||
|
||||
static uint32_t
|
||||
alac_kuki_read (SF_PRIVATE * psf, uint32_t kuki_offset, uint8_t * kuki, size_t kuki_maxlen)
|
||||
{ uint32_t marker ;
|
||||
uint64_t kuki_size ;
|
||||
|
||||
if (psf_fseek (psf, kuki_offset, SEEK_SET) != kuki_offset)
|
||||
return 0 ;
|
||||
|
||||
psf_fread (&marker, 1, sizeof (marker), psf) ;
|
||||
if (marker != MAKE_MARKER ('k', 'u', 'k', 'i'))
|
||||
return 0 ;
|
||||
|
||||
psf_fread (&kuki_size, 1, sizeof (kuki_size), psf) ;
|
||||
kuki_size = BE2H_64 (kuki_size) ;
|
||||
|
||||
if (kuki_size == 0 || kuki_size > kuki_maxlen)
|
||||
{ psf_log_printf (psf, "%s : Bad size (%D) of 'kuki' chunk.\n", __func__, kuki_size) ;
|
||||
return 0 ;
|
||||
} ;
|
||||
|
||||
psf_fread (kuki, 1, kuki_size, psf) ;
|
||||
|
||||
return kuki_size ;
|
||||
} /* alac_kuki_read */
|
||||
+45
-37
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** Copyright (C) 1999-2009 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
** Copyright (C) 1999-2012 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
@@ -47,14 +47,14 @@ static void d2alaw_array (const double *buffer, int count, unsigned char *ptr, d
|
||||
int
|
||||
alaw_init (SF_PRIVATE *psf)
|
||||
{
|
||||
if (psf->mode == SFM_READ || psf->mode == SFM_RDWR)
|
||||
if (psf->file.mode == SFM_READ || psf->file.mode == SFM_RDWR)
|
||||
{ psf->read_short = alaw_read_alaw2s ;
|
||||
psf->read_int = alaw_read_alaw2i ;
|
||||
psf->read_float = alaw_read_alaw2f ;
|
||||
psf->read_double = alaw_read_alaw2d ;
|
||||
} ;
|
||||
|
||||
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
|
||||
if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
|
||||
{ psf->write_short = alaw_write_s2alaw ;
|
||||
psf->write_int = alaw_write_i2alaw ;
|
||||
psf->write_float = alaw_write_f2alaw ;
|
||||
@@ -69,7 +69,7 @@ alaw_init (SF_PRIVATE *psf)
|
||||
else
|
||||
psf->datalength = 0 ;
|
||||
|
||||
psf->sf.frames = psf->datalength / psf->blockwidth ;
|
||||
psf->sf.frames = psf->blockwidth > 0 ? psf->datalength / psf->blockwidth : 0 ;
|
||||
|
||||
return 0 ;
|
||||
} /* alaw_init */
|
||||
@@ -286,7 +286,7 @@ unsigned char alaw_encode [2048 + 1] =
|
||||
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
|
||||
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
|
||||
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
|
||||
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x2a
|
||||
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa
|
||||
} ; /* alaw_encode */
|
||||
|
||||
static inline void
|
||||
@@ -358,16 +358,17 @@ d2alaw_array (const double *ptr, int count, unsigned char *buffer, double normfa
|
||||
|
||||
static sf_count_t
|
||||
alaw_read_alaw2s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
|
||||
{ int bufferlen, readcount ;
|
||||
{ BUF_UNION ubuf ;
|
||||
int bufferlen, readcount ;
|
||||
sf_count_t total = 0 ;
|
||||
|
||||
bufferlen = ARRAY_LEN (psf->u.ucbuf) ;
|
||||
bufferlen = ARRAY_LEN (ubuf.ucbuf) ;
|
||||
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
readcount = psf_fread (psf->u.ucbuf, 1, bufferlen, psf) ;
|
||||
alaw2s_array (psf->u.ucbuf, readcount, ptr + total) ;
|
||||
readcount = psf_fread (ubuf.ucbuf, 1, bufferlen, psf) ;
|
||||
alaw2s_array (ubuf.ucbuf, readcount, ptr + total) ;
|
||||
total += readcount ;
|
||||
if (readcount < bufferlen)
|
||||
break ;
|
||||
@@ -379,16 +380,17 @@ alaw_read_alaw2s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
|
||||
|
||||
static sf_count_t
|
||||
alaw_read_alaw2i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
|
||||
{ int bufferlen, readcount ;
|
||||
{ BUF_UNION ubuf ;
|
||||
int bufferlen, readcount ;
|
||||
sf_count_t total = 0 ;
|
||||
|
||||
bufferlen = ARRAY_LEN (psf->u.ucbuf) ;
|
||||
bufferlen = ARRAY_LEN (ubuf.ucbuf) ;
|
||||
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
readcount = psf_fread (psf->u.ucbuf, 1, bufferlen, psf) ;
|
||||
alaw2i_array (psf->u.ucbuf, readcount, ptr + total) ;
|
||||
readcount = psf_fread (ubuf.ucbuf, 1, bufferlen, psf) ;
|
||||
alaw2i_array (ubuf.ucbuf, readcount, ptr + total) ;
|
||||
total += readcount ;
|
||||
if (readcount < bufferlen)
|
||||
break ;
|
||||
@@ -400,19 +402,20 @@ alaw_read_alaw2i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
|
||||
|
||||
static sf_count_t
|
||||
alaw_read_alaw2f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
|
||||
{ int bufferlen, readcount ;
|
||||
{ BUF_UNION ubuf ;
|
||||
int bufferlen, readcount ;
|
||||
sf_count_t total = 0 ;
|
||||
float normfact ;
|
||||
|
||||
normfact = (psf->norm_float == SF_TRUE) ? 1.0 / ((float) 0x8000) : 1.0 ;
|
||||
|
||||
bufferlen = ARRAY_LEN (psf->u.ucbuf) ;
|
||||
bufferlen = ARRAY_LEN (ubuf.ucbuf) ;
|
||||
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
readcount = psf_fread (psf->u.ucbuf, 1, bufferlen, psf) ;
|
||||
alaw2f_array (psf->u.ucbuf, readcount, ptr + total, normfact) ;
|
||||
readcount = psf_fread (ubuf.ucbuf, 1, bufferlen, psf) ;
|
||||
alaw2f_array (ubuf.ucbuf, readcount, ptr + total, normfact) ;
|
||||
total += readcount ;
|
||||
if (readcount < bufferlen)
|
||||
break ;
|
||||
@@ -424,18 +427,19 @@ alaw_read_alaw2f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
|
||||
|
||||
static sf_count_t
|
||||
alaw_read_alaw2d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
|
||||
{ int bufferlen, readcount ;
|
||||
{ BUF_UNION ubuf ;
|
||||
int bufferlen, readcount ;
|
||||
sf_count_t total = 0 ;
|
||||
double normfact ;
|
||||
|
||||
normfact = (psf->norm_double) ? 1.0 / ((double) 0x8000) : 1.0 ;
|
||||
bufferlen = ARRAY_LEN (psf->u.ucbuf) ;
|
||||
bufferlen = ARRAY_LEN (ubuf.ucbuf) ;
|
||||
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
readcount = psf_fread (psf->u.ucbuf, 1, bufferlen, psf) ;
|
||||
alaw2d_array (psf->u.ucbuf, readcount, ptr + total, normfact) ;
|
||||
readcount = psf_fread (ubuf.ucbuf, 1, bufferlen, psf) ;
|
||||
alaw2d_array (ubuf.ucbuf, readcount, ptr + total, normfact) ;
|
||||
total += readcount ;
|
||||
if (readcount < bufferlen)
|
||||
break ;
|
||||
@@ -450,16 +454,17 @@ alaw_read_alaw2d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
|
||||
|
||||
static sf_count_t
|
||||
alaw_write_s2alaw (SF_PRIVATE *psf, const short *ptr, sf_count_t len)
|
||||
{ int bufferlen, writecount ;
|
||||
{ BUF_UNION ubuf ;
|
||||
int bufferlen, writecount ;
|
||||
sf_count_t total = 0 ;
|
||||
|
||||
bufferlen = ARRAY_LEN (psf->u.ucbuf) ;
|
||||
bufferlen = ARRAY_LEN (ubuf.ucbuf) ;
|
||||
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
s2alaw_array (ptr + total, bufferlen, psf->u.ucbuf) ;
|
||||
writecount = psf_fwrite (psf->u.ucbuf, 1, bufferlen, psf) ;
|
||||
s2alaw_array (ptr + total, bufferlen, ubuf.ucbuf) ;
|
||||
writecount = psf_fwrite (ubuf.ucbuf, 1, bufferlen, psf) ;
|
||||
total += writecount ;
|
||||
if (writecount < bufferlen)
|
||||
break ;
|
||||
@@ -471,16 +476,17 @@ alaw_write_s2alaw (SF_PRIVATE *psf, const short *ptr, sf_count_t len)
|
||||
|
||||
static sf_count_t
|
||||
alaw_write_i2alaw (SF_PRIVATE *psf, const int *ptr, sf_count_t len)
|
||||
{ int bufferlen, writecount ;
|
||||
{ BUF_UNION ubuf ;
|
||||
int bufferlen, writecount ;
|
||||
sf_count_t total = 0 ;
|
||||
|
||||
bufferlen = ARRAY_LEN (psf->u.ucbuf) ;
|
||||
bufferlen = ARRAY_LEN (ubuf.ucbuf) ;
|
||||
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
i2alaw_array (ptr + total, bufferlen, psf->u.ucbuf) ;
|
||||
writecount = psf_fwrite (psf->u.ucbuf, 1, bufferlen, psf) ;
|
||||
i2alaw_array (ptr + total, bufferlen, ubuf.ucbuf) ;
|
||||
writecount = psf_fwrite (ubuf.ucbuf, 1, bufferlen, psf) ;
|
||||
total += writecount ;
|
||||
if (writecount < bufferlen)
|
||||
break ;
|
||||
@@ -492,19 +498,20 @@ alaw_write_i2alaw (SF_PRIVATE *psf, const int *ptr, sf_count_t len)
|
||||
|
||||
static sf_count_t
|
||||
alaw_write_f2alaw (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
|
||||
{ int bufferlen, writecount ;
|
||||
{ BUF_UNION ubuf ;
|
||||
int bufferlen, writecount ;
|
||||
sf_count_t total = 0 ;
|
||||
float normfact ;
|
||||
|
||||
normfact = (psf->norm_float == SF_TRUE) ? (1.0 * 0x7FFF) / 16.0 : 1.0 / 16 ;
|
||||
|
||||
bufferlen = ARRAY_LEN (psf->u.ucbuf) ;
|
||||
bufferlen = ARRAY_LEN (ubuf.ucbuf) ;
|
||||
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
f2alaw_array (ptr + total, bufferlen, psf->u.ucbuf, normfact) ;
|
||||
writecount = psf_fwrite (psf->u.ucbuf, 1, bufferlen, psf) ;
|
||||
f2alaw_array (ptr + total, bufferlen, ubuf.ucbuf, normfact) ;
|
||||
writecount = psf_fwrite (ubuf.ucbuf, 1, bufferlen, psf) ;
|
||||
total += writecount ;
|
||||
if (writecount < bufferlen)
|
||||
break ;
|
||||
@@ -516,19 +523,20 @@ alaw_write_f2alaw (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
|
||||
|
||||
static sf_count_t
|
||||
alaw_write_d2alaw (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
|
||||
{ int bufferlen, writecount ;
|
||||
{ BUF_UNION ubuf ;
|
||||
int bufferlen, writecount ;
|
||||
sf_count_t total = 0 ;
|
||||
double normfact ;
|
||||
|
||||
normfact = (psf->norm_double) ? (1.0 * 0x7FFF) / 16.0 : 1.0 / 16.0 ;
|
||||
|
||||
bufferlen = ARRAY_LEN (psf->u.ucbuf) ;
|
||||
bufferlen = ARRAY_LEN (ubuf.ucbuf) ;
|
||||
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
d2alaw_array (ptr + total, bufferlen, psf->u.ucbuf, normfact) ;
|
||||
writecount = psf_fwrite (psf->u.ucbuf, 1, bufferlen, psf) ;
|
||||
d2alaw_array (ptr + total, bufferlen, ubuf.ucbuf, normfact) ;
|
||||
writecount = psf_fwrite (ubuf.ucbuf, 1, bufferlen, psf) ;
|
||||
total += writecount ;
|
||||
if (writecount < bufferlen)
|
||||
break ;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** Copyright (C) 1999-2009 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
** Copyright (C) 1999-2012 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
@@ -81,8 +81,8 @@ typedef struct
|
||||
{ int dataoffset ;
|
||||
int datasize ;
|
||||
int encoding ;
|
||||
int samplerate ;
|
||||
int channels ;
|
||||
int samplerate ;
|
||||
int channels ;
|
||||
} AU_FMT ;
|
||||
|
||||
|
||||
@@ -106,7 +106,7 @@ au_open (SF_PRIVATE *psf)
|
||||
{ int subformat ;
|
||||
int error = 0 ;
|
||||
|
||||
if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->filelength > 0))
|
||||
if (psf->file.mode == SFM_READ || (psf->file.mode == SFM_RDWR && psf->filelength > 0))
|
||||
{ if ((error = au_read_header (psf)))
|
||||
return error ;
|
||||
} ;
|
||||
@@ -116,7 +116,7 @@ au_open (SF_PRIVATE *psf)
|
||||
|
||||
subformat = SF_CODEC (psf->sf.format) ;
|
||||
|
||||
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
|
||||
if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
|
||||
{ psf->endian = SF_ENDIAN (psf->sf.format) ;
|
||||
if (CPU_IS_LITTLE_ENDIAN && psf->endian == SF_ENDIAN_CPU)
|
||||
psf->endian = SF_ENDIAN_LITTLE ;
|
||||
@@ -189,7 +189,7 @@ au_open (SF_PRIVATE *psf)
|
||||
static int
|
||||
au_close (SF_PRIVATE *psf)
|
||||
{
|
||||
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
|
||||
if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
|
||||
au_write_header (psf, SF_TRUE) ;
|
||||
|
||||
return 0 ;
|
||||
@@ -211,8 +211,6 @@ au_write_header (SF_PRIVATE *psf, int calc_length)
|
||||
psf->datalength = psf->filelength - psf->dataoffset ;
|
||||
if (psf->dataend)
|
||||
psf->datalength -= psf->filelength - psf->dataend ;
|
||||
|
||||
psf->sf.frames = psf->datalength / (psf->bytewidth * psf->sf.channels) ;
|
||||
} ;
|
||||
|
||||
encoding = au_format_to_encoding (SF_CODEC (psf->sf.format)) ;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** Copyright (C) 1999-2009 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
** Copyright (C) 1999-2012 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
@@ -60,7 +60,7 @@ audio_detect (SF_PRIVATE * psf, AUDIO_DETECT *ad, const unsigned char * data, in
|
||||
" be_int_24_32 : %d\n",
|
||||
vote.le_float, vote.be_float, vote.le_int_24_32, vote.be_int_24_32) ;
|
||||
|
||||
if (0) puts (psf->logbuffer) ;
|
||||
if (0) puts (psf->parselog.buf) ;
|
||||
|
||||
if (ad->endianness == SF_ENDIAN_LITTLE && vote.le_float > (3 * datalen) / 4)
|
||||
{ /* Almost certainly 32 bit floats. */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** Copyright (C) 2004-2009 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
** Copyright (C) 2004-2012 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
@@ -80,7 +80,7 @@ int
|
||||
avr_open (SF_PRIVATE *psf)
|
||||
{ int error = 0 ;
|
||||
|
||||
if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->filelength > 0))
|
||||
if (psf->file.mode == SFM_READ || (psf->file.mode == SFM_RDWR && psf->filelength > 0))
|
||||
{ if ((error = avr_read_header (psf)))
|
||||
return error ;
|
||||
} ;
|
||||
@@ -88,9 +88,8 @@ avr_open (SF_PRIVATE *psf)
|
||||
if ((SF_CONTAINER (psf->sf.format)) != SF_FORMAT_AVR)
|
||||
return SFE_BAD_OPEN_FORMAT ;
|
||||
|
||||
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
|
||||
{ psf->endian = SF_ENDIAN (psf->sf.format) ;
|
||||
psf->endian = SF_ENDIAN_BIG ;
|
||||
if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
|
||||
{ psf->endian = SF_ENDIAN_BIG ;
|
||||
|
||||
if (avr_write_header (psf, SF_FALSE))
|
||||
return psf->error ;
|
||||
@@ -239,7 +238,7 @@ avr_write_header (SF_PRIVATE *psf, int calc_length)
|
||||
static int
|
||||
avr_close (SF_PRIVATE *psf)
|
||||
{
|
||||
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
|
||||
if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
|
||||
avr_write_header (psf, SF_TRUE) ;
|
||||
|
||||
return 0 ;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/python2.5
|
||||
#!/usr/bin/python
|
||||
|
||||
# Copyright (C) 2006 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
# Copyright (C) 2006-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
#
|
||||
# All rights reserved.
|
||||
#
|
||||
@@ -48,19 +48,19 @@ def find_binheader_writefs (data):
|
||||
def find_format_string (s):
|
||||
fmt = re.search ('"([^"]+)"', s)
|
||||
if not fmt:
|
||||
print "Bad format in :\n\n\t%s\n\n" % s
|
||||
print ("Bad format in :\n\n\t%s\n\n" % s)
|
||||
sys.exit (1)
|
||||
fmt = fmt.groups ()
|
||||
if len (fmt) != 1:
|
||||
print "Bad format in :\n\n\t%s\n\n" % s
|
||||
print ("Bad format in :\n\n\t%s\n\n" % s)
|
||||
sys.exit (1)
|
||||
return _whitespace_re.sub ("", fmt [0])
|
||||
|
||||
def get_param_list (data):
|
||||
dlist = re.search ("\((.+)\)\s*;", data)
|
||||
dlist = dlist.groups ()[0]
|
||||
dlist = string.split (dlist, ",")
|
||||
dlist = [string.strip (x) for x in dlist]
|
||||
dlist = dlist.split(",")
|
||||
dlist = [x.strip() for x in dlist]
|
||||
return dlist [2:]
|
||||
|
||||
def handle_file (fname):
|
||||
@@ -88,29 +88,30 @@ def handle_file (fname):
|
||||
# print item
|
||||
# print " param [%d] %c : %s <-> %s" % (param_index, ch, params [param_index], params [param_index + 1])
|
||||
|
||||
if string.find (params [param_index + 1], "sizeof") < 0 \
|
||||
and string.find (params [param_index + 1], "make_size_t") < 0 \
|
||||
and string.find (params [param_index + 1], "strlen") < 0:
|
||||
if errors == 0: print
|
||||
print "\n%s :" % fname
|
||||
print " param [%d] %c : %s <-> %s" % (param_index, ch, params [param_index], params [param_index + 1])
|
||||
print " %s" % item
|
||||
# print (params [param_index + 1])
|
||||
if params [param_index + 1].find ("sizeof") < 0 \
|
||||
and params [param_index + 1].find ("make_size_t") < 0 \
|
||||
and params [param_index + 1].find ("strlen") < 0:
|
||||
if errors == 0: sys.stdout.write ("\n")
|
||||
print ("\n%s :" % fname)
|
||||
print (" param [%d] %c : %s <-> %s" % (param_index, ch, params [param_index], params [param_index + 1]))
|
||||
print (" %s" % item)
|
||||
errors += 1
|
||||
param_index += 2
|
||||
|
||||
|
||||
return errors
|
||||
|
||||
#===============================================================================
|
||||
|
||||
if len (sys.argv) > 1:
|
||||
print "%s\n binheader_writef_check :" % sys.argv [0],
|
||||
sys.stdout.write ("\n binheader_writef_check :")
|
||||
sys.stdout.flush ()
|
||||
errors = 0
|
||||
for fname in sys.argv [1:]:
|
||||
errors += handle_file (fname)
|
||||
if errors > 0:
|
||||
print "\nErrors : %d\n" % errors
|
||||
print ("\nErrors : %d\n" % errors)
|
||||
sys.exit (1)
|
||||
|
||||
print "ok"
|
||||
print ("ok\n")
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
** Copyright (C) 2006-2013 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
** Copyright (C) 2006 Paul Davis <paul@linuxaudiosystems.com>
|
||||
** Copyright (C) 2006-2009 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
@@ -17,13 +17,15 @@
|
||||
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "sfconfig.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
static void strncpy_crlf (char *dest, const char *src, size_t destmax, size_t srcmax) ;
|
||||
|
||||
static int gen_coding_history (char * added_history, int added_history_max, const SF_INFO * psfinfo) ;
|
||||
|
||||
static inline size_t
|
||||
@@ -32,29 +34,16 @@ bc_min_size (const SF_BROADCAST_INFO* info)
|
||||
return 0 ;
|
||||
|
||||
return offsetof (SF_BROADCAST_INFO, coding_history) + info->coding_history_size ;
|
||||
} /* broadcast_size */
|
||||
} /* bc_min_size */
|
||||
|
||||
|
||||
static inline size_t
|
||||
bc_var_coding_hist_size (const SF_BROADCAST_VAR* var)
|
||||
{ return var->size - offsetof (SF_BROADCAST_VAR, binfo.coding_history) ;
|
||||
} /* broadcast_size */
|
||||
|
||||
SF_BROADCAST_VAR*
|
||||
broadcast_var_alloc (size_t datasize)
|
||||
{ SF_BROADCAST_VAR * data ;
|
||||
|
||||
if ((data = calloc (1, datasize)) != NULL)
|
||||
data->size = datasize ;
|
||||
|
||||
return data ;
|
||||
SF_BROADCAST_INFO_16K*
|
||||
broadcast_var_alloc (void)
|
||||
{ return calloc (1, sizeof (SF_BROADCAST_INFO_16K)) ;
|
||||
} /* broadcast_var_alloc */
|
||||
|
||||
|
||||
int
|
||||
broadcast_var_set (SF_PRIVATE *psf, const SF_BROADCAST_INFO * info, size_t datasize)
|
||||
{ char added_history [256] ;
|
||||
int added_history_len, len ;
|
||||
{ size_t len ;
|
||||
|
||||
if (info == NULL)
|
||||
return SF_FALSE ;
|
||||
@@ -64,42 +53,41 @@ broadcast_var_set (SF_PRIVATE *psf, const SF_BROADCAST_INFO * info, size_t datas
|
||||
return SF_FALSE ;
|
||||
} ;
|
||||
|
||||
added_history_len = gen_coding_history (added_history, sizeof (added_history), &(psf->sf)) ;
|
||||
if (datasize >= sizeof (SF_BROADCAST_INFO_16K))
|
||||
{ psf->error = SFE_BAD_BROADCAST_INFO_TOO_BIG ;
|
||||
return SF_FALSE ;
|
||||
} ;
|
||||
|
||||
if (psf->broadcast_var != NULL)
|
||||
{ size_t coding_hist_offset = offsetof (SF_BROADCAST_INFO, coding_history) ;
|
||||
|
||||
if (psf->broadcast_var->binfo.coding_history_size + added_history_len < datasize - coding_hist_offset)
|
||||
{ free (psf->broadcast_var) ;
|
||||
psf->broadcast_var = NULL ;
|
||||
if (psf->broadcast_16k == NULL)
|
||||
{ if ((psf->broadcast_16k = broadcast_var_alloc ()) == NULL)
|
||||
{ psf->error = SFE_MALLOC_FAILED ;
|
||||
return SF_FALSE ;
|
||||
} ;
|
||||
} ;
|
||||
|
||||
if (psf->broadcast_var == NULL)
|
||||
{ int size = datasize + added_history_len + 512 ;
|
||||
/* Only copy the first part of the struct. */
|
||||
memcpy (psf->broadcast_16k, info, offsetof (SF_BROADCAST_INFO, coding_history)) ;
|
||||
|
||||
psf->broadcast_var = calloc (1, size) ;
|
||||
psf->broadcast_var->size = size ;
|
||||
psf_strlcpy_crlf (psf->broadcast_16k->coding_history, info->coding_history, sizeof (psf->broadcast_16k->coding_history), datasize - offsetof (SF_BROADCAST_INFO, coding_history)) ;
|
||||
len = strlen (psf->broadcast_16k->coding_history) ;
|
||||
|
||||
if (len > 0 && psf->broadcast_16k->coding_history [len - 1] != '\n')
|
||||
psf_strlcat (psf->broadcast_16k->coding_history, sizeof (psf->broadcast_16k->coding_history), "\r\n") ;
|
||||
|
||||
if (psf->file.mode == SFM_WRITE)
|
||||
{ char added_history [256] ;
|
||||
|
||||
gen_coding_history (added_history, sizeof (added_history), &(psf->sf)) ;
|
||||
psf_strlcat (psf->broadcast_16k->coding_history, sizeof (psf->broadcast_16k->coding_history), added_history) ;
|
||||
} ;
|
||||
|
||||
memcpy (&(psf->broadcast_var->binfo), info, offsetof (SF_BROADCAST_INFO, coding_history)) ;
|
||||
|
||||
strncpy_crlf (psf->broadcast_var->binfo.coding_history, info->coding_history, bc_var_coding_hist_size (psf->broadcast_var), info->coding_history_size) ;
|
||||
len = strlen (psf->broadcast_var->binfo.coding_history) ;
|
||||
|
||||
if (len > 0 && psf->broadcast_var->binfo.coding_history [len] != '\n')
|
||||
strncat (psf->broadcast_var->binfo.coding_history, "\r\n", 2) ;
|
||||
|
||||
if (psf->mode == SFM_WRITE)
|
||||
strncat (psf->broadcast_var->binfo.coding_history, added_history, strlen (added_history)) ;
|
||||
|
||||
psf->broadcast_var->binfo.coding_history_size = strlen (psf->broadcast_var->binfo.coding_history) ;
|
||||
|
||||
/* Fore coding_history_size to be even. */
|
||||
psf->broadcast_var->binfo.coding_history_size += (psf->broadcast_var->binfo.coding_history_size & 1) ? 1 : 0 ;
|
||||
/* Force coding_history_size to be even. */
|
||||
len = strlen (psf->broadcast_16k->coding_history) ;
|
||||
len += (len & 1) ? 1 : 0 ;
|
||||
psf->broadcast_16k->coding_history_size = len ;
|
||||
|
||||
/* Currently writing this version. */
|
||||
psf->broadcast_var->binfo.version = 1 ;
|
||||
psf->broadcast_16k->version = 1 ;
|
||||
|
||||
return SF_TRUE ;
|
||||
} /* broadcast_var_set */
|
||||
@@ -109,54 +97,19 @@ int
|
||||
broadcast_var_get (SF_PRIVATE *psf, SF_BROADCAST_INFO * data, size_t datasize)
|
||||
{ size_t size ;
|
||||
|
||||
if (psf->broadcast_var == NULL)
|
||||
if (psf->broadcast_16k == NULL)
|
||||
return SF_FALSE ;
|
||||
|
||||
size = SF_MIN (datasize, bc_min_size (&(psf->broadcast_var->binfo))) ;
|
||||
size = SF_MIN (datasize, bc_min_size ((const SF_BROADCAST_INFO *) psf->broadcast_16k)) ;
|
||||
|
||||
memcpy (data, &(psf->broadcast_var->binfo), size) ;
|
||||
memcpy (data, psf->broadcast_16k, size) ;
|
||||
|
||||
return SF_TRUE ;
|
||||
} /* broadcast_var_set */
|
||||
} /* broadcast_var_get */
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
** Strncpy which converts all line endings to CR/LF.
|
||||
*/
|
||||
|
||||
static void
|
||||
strncpy_crlf (char *dest, const char *src, size_t destmax, size_t srcmax)
|
||||
{ char * destend = dest + destmax - 1 ;
|
||||
const char * srcend = src + srcmax ;
|
||||
|
||||
while (dest < destend && src < srcend)
|
||||
{ if ((src [0] == '\r' && src [1] == '\n') || (src [0] == '\n' && src [1] == '\r'))
|
||||
{ *dest++ = '\r' ;
|
||||
*dest++ = '\n' ;
|
||||
src += 2 ;
|
||||
continue ;
|
||||
} ;
|
||||
|
||||
if (src [0] == '\r')
|
||||
{ *dest++ = '\r' ;
|
||||
*dest++ = '\n' ;
|
||||
src += 1 ;
|
||||
continue ;
|
||||
} ;
|
||||
|
||||
if (src [0] == '\n')
|
||||
{ *dest++ = '\r' ;
|
||||
*dest++ = '\n' ;
|
||||
src += 1 ;
|
||||
continue ;
|
||||
} ;
|
||||
|
||||
*dest++ = *src++ ;
|
||||
} ;
|
||||
|
||||
/* Make sure dest is terminated. */
|
||||
*dest = 0 ;
|
||||
} /* strncpy_crlf */
|
||||
|
||||
static int
|
||||
gen_coding_history (char * added_history, int added_history_max, const SF_INFO * psfinfo)
|
||||
{ char chnstr [16] ;
|
||||
@@ -168,16 +121,16 @@ gen_coding_history (char * added_history, int added_history_max, const SF_INFO *
|
||||
** Parameter Variable string <allowed option> Unit
|
||||
** ==========================================================================================
|
||||
** Coding Algorithm A=<ANALOGUE, PCM, MPEG1L1, MPEG1L2, MPEG1L3,
|
||||
** MPEG2L1, MPEG2L2, MPEG2L3>
|
||||
** MPEG2L1, MPEG2L2, MPEG2L3>
|
||||
** Sampling frequency F=<11000,22050,24000,32000,44100,48000> [Hz]
|
||||
** Bit-rate B=<any bit-rate allowed in MPEG 2 (ISO/IEC [kbit/s per channel]
|
||||
** 13818-3)>
|
||||
** 13818-3)>
|
||||
** Word Length W=<8, 12, 14, 16, 18, 20, 22, 24> [bits]
|
||||
** Mode M=<mono, stereo, dual-mono, joint-stereo>
|
||||
** Text, free string T=<a free ASCII-text string for in house use.
|
||||
** This string should contain no commas (ASCII
|
||||
** 2Chex). Examples of the contents: ID-No; codec
|
||||
** type; A/D type>
|
||||
** This string should contain no commas (ASCII
|
||||
** 2Chex). Examples of the contents: ID-No; codec
|
||||
** type; A/D type>
|
||||
*/
|
||||
|
||||
switch (psfinfo->channels)
|
||||
@@ -185,11 +138,11 @@ gen_coding_history (char * added_history, int added_history_max, const SF_INFO *
|
||||
return SF_FALSE ;
|
||||
|
||||
case 1 :
|
||||
strncpy (chnstr, "mono", sizeof (chnstr)) ;
|
||||
psf_strlcpy (chnstr, sizeof (chnstr), "mono") ;
|
||||
break ;
|
||||
|
||||
case 2 :
|
||||
strncpy (chnstr, "stereo", sizeof (chnstr)) ;
|
||||
psf_strlcpy (chnstr, sizeof (chnstr), "stereo") ;
|
||||
break ;
|
||||
|
||||
default :
|
||||
@@ -227,7 +180,7 @@ gen_coding_history (char * added_history, int added_history_max, const SF_INFO *
|
||||
} ;
|
||||
|
||||
count = snprintf (added_history, added_history_max,
|
||||
"A=PCM,F=%u,W=%hu,M=%s,T=%s-%s\r\n",
|
||||
"A=PCM,F=%u,W=%d,M=%s,T=%s-%s\r\n",
|
||||
psfinfo->samplerate, width, chnstr, PACKAGE, VERSION) ;
|
||||
|
||||
if (count >= added_history_max)
|
||||
|
||||
+337
-69
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** Copyright (C) 2005-2009 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
** Copyright (C) 2005-2013 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
@@ -23,10 +23,14 @@
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <math.h>
|
||||
#ifdef HAVE_INTTYPES_H
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
|
||||
#include "sndfile.h"
|
||||
#include "sfendian.h"
|
||||
#include "common.h"
|
||||
#include "chanmap.h"
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
** Macros to handle big/little endian issues.
|
||||
@@ -73,15 +77,21 @@
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{ unsigned char srate [8] ;
|
||||
unsigned int fmt_id ;
|
||||
unsigned int fmt_flags ;
|
||||
unsigned int pkt_bytes ;
|
||||
unsigned int pkt_frames ;
|
||||
unsigned int channels_per_frame ;
|
||||
unsigned int bits_per_chan ;
|
||||
{ uint8_t srate [8] ;
|
||||
uint32_t fmt_id ;
|
||||
uint32_t fmt_flags ;
|
||||
uint32_t pkt_bytes ;
|
||||
uint32_t frames_per_packet ;
|
||||
uint32_t channels_per_frame ;
|
||||
uint32_t bits_per_chan ;
|
||||
} DESC_CHUNK ;
|
||||
|
||||
typedef struct
|
||||
{ int chanmap_tag ;
|
||||
|
||||
ALAC_DECODER_INFO alac ;
|
||||
} CAF_PRIVATE ;
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
** Private static functions.
|
||||
*/
|
||||
@@ -89,6 +99,13 @@ typedef struct
|
||||
static int caf_close (SF_PRIVATE *psf) ;
|
||||
static int caf_read_header (SF_PRIVATE *psf) ;
|
||||
static int caf_write_header (SF_PRIVATE *psf, int calc_length) ;
|
||||
static int caf_command (SF_PRIVATE *psf, int command, void *data, int datasize) ;
|
||||
static int caf_read_chanmap (SF_PRIVATE * psf, sf_count_t chunk_size) ;
|
||||
|
||||
static int caf_set_chunk (SF_PRIVATE *psf, const SF_CHUNK_INFO * chunk_info) ;
|
||||
static SF_CHUNK_ITERATOR * caf_next_chunk_iterator (SF_PRIVATE *psf, SF_CHUNK_ITERATOR * iterator) ;
|
||||
static int caf_get_chunk_size (SF_PRIVATE *psf, const SF_CHUNK_ITERATOR * iterator, SF_CHUNK_INFO * chunk_info) ;
|
||||
static int caf_get_chunk_data (SF_PRIVATE *psf, const SF_CHUNK_ITERATOR * iterator, SF_CHUNK_INFO * chunk_info) ;
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
** Public function.
|
||||
@@ -96,16 +113,26 @@ static int caf_write_header (SF_PRIVATE *psf, int calc_length) ;
|
||||
|
||||
int
|
||||
caf_open (SF_PRIVATE *psf)
|
||||
{ int subformat, format, error = 0 ;
|
||||
{ CAF_PRIVATE * pcaf ;
|
||||
int subformat, format, error = 0 ;
|
||||
|
||||
if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->filelength > 0))
|
||||
if ((psf->container_data = calloc (1, sizeof (CAF_PRIVATE))) == NULL)
|
||||
return SFE_MALLOC_FAILED ;
|
||||
|
||||
pcaf = psf->container_data ;
|
||||
|
||||
if (psf->file.mode == SFM_READ || (psf->file.mode == SFM_RDWR && psf->filelength > 0))
|
||||
{ if ((error = caf_read_header (psf)))
|
||||
return error ;
|
||||
|
||||
psf->next_chunk_iterator = caf_next_chunk_iterator ;
|
||||
psf->get_chunk_size = caf_get_chunk_size ;
|
||||
psf->get_chunk_data = caf_get_chunk_data ;
|
||||
} ;
|
||||
|
||||
subformat = SF_CODEC (psf->sf.format) ;
|
||||
|
||||
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
|
||||
if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
|
||||
{ if (psf->is_pipe)
|
||||
return SFE_NO_PIPE_WRITE ;
|
||||
|
||||
@@ -115,20 +142,20 @@ caf_open (SF_PRIVATE *psf)
|
||||
|
||||
psf->blockwidth = psf->bytewidth * psf->sf.channels ;
|
||||
|
||||
if (psf->mode != SFM_RDWR || psf->filelength < 44)
|
||||
if (psf->file.mode != SFM_RDWR || psf->filelength < 44)
|
||||
{ psf->filelength = 0 ;
|
||||
psf->datalength = 0 ;
|
||||
psf->dataoffset = 0 ;
|
||||
psf->sf.frames = 0 ;
|
||||
} ;
|
||||
|
||||
psf->str_flags = SF_STR_ALLOW_START ;
|
||||
psf->strings.flags = SF_STR_ALLOW_START ;
|
||||
|
||||
/*
|
||||
** By default, add the peak chunk to floating point files. Default behaviour
|
||||
** can be switched off using sf_command (SFC_SET_PEAK_CHUNK, SF_FALSE).
|
||||
*/
|
||||
if (psf->mode == SFM_WRITE && (subformat == SF_FORMAT_FLOAT || subformat == SF_FORMAT_DOUBLE))
|
||||
if (psf->file.mode == SFM_WRITE && (subformat == SF_FORMAT_FLOAT || subformat == SF_FORMAT_DOUBLE))
|
||||
{ if ((psf->peak_info = peak_info_calloc (psf->sf.channels)) == NULL)
|
||||
return SFE_MALLOC_FAILED ;
|
||||
psf->peak_info->peak_loc = SF_PEAK_START ;
|
||||
@@ -137,11 +164,12 @@ caf_open (SF_PRIVATE *psf)
|
||||
if ((error = caf_write_header (psf, SF_FALSE)) != 0)
|
||||
return error ;
|
||||
|
||||
psf->write_header = caf_write_header ;
|
||||
psf->write_header = caf_write_header ;
|
||||
psf->set_chunk = caf_set_chunk ;
|
||||
} ;
|
||||
|
||||
psf->container_close = caf_close ;
|
||||
/*psf->command = caf_command ;*/
|
||||
psf->command = caf_command ;
|
||||
|
||||
switch (subformat)
|
||||
{ case SF_FORMAT_PCM_S8 :
|
||||
@@ -167,6 +195,18 @@ caf_open (SF_PRIVATE *psf)
|
||||
case SF_FORMAT_DOUBLE :
|
||||
error = double64_init (psf) ;
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_ALAC_16 :
|
||||
case SF_FORMAT_ALAC_20 :
|
||||
case SF_FORMAT_ALAC_24 :
|
||||
case SF_FORMAT_ALAC_32 :
|
||||
if (psf->file.mode == SFM_READ)
|
||||
/* Only pass the ALAC_DECODER_INFO in read mode. */
|
||||
error = alac_init (psf, &pcaf->alac) ;
|
||||
else
|
||||
error = alac_init (psf, NULL) ;
|
||||
break ;
|
||||
|
||||
/* Lite remove end */
|
||||
|
||||
default :
|
||||
@@ -179,22 +219,72 @@ caf_open (SF_PRIVATE *psf)
|
||||
static int
|
||||
caf_close (SF_PRIVATE *psf)
|
||||
{
|
||||
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
|
||||
if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
|
||||
caf_write_header (psf, SF_TRUE) ;
|
||||
|
||||
return 0 ;
|
||||
} /* caf_close */
|
||||
|
||||
static int
|
||||
caf_command (SF_PRIVATE * psf, int command, void * UNUSED (data), int UNUSED (datasize))
|
||||
{ CAF_PRIVATE *pcaf ;
|
||||
|
||||
if ((pcaf = psf->container_data) == NULL)
|
||||
return SFE_INTERNAL ;
|
||||
|
||||
switch (command)
|
||||
{ case SFC_SET_CHANNEL_MAP_INFO :
|
||||
pcaf->chanmap_tag = aiff_caf_find_channel_layout_tag (psf->channel_map, psf->sf.channels) ;
|
||||
return (pcaf->chanmap_tag != 0) ;
|
||||
|
||||
default :
|
||||
break ;
|
||||
} ;
|
||||
|
||||
return 0 ;
|
||||
} /* caf_command */
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static int
|
||||
decode_desc_chunk (SF_PRIVATE *psf, const DESC_CHUNK *desc)
|
||||
{ int format ;
|
||||
{ int format = SF_FORMAT_CAF ;
|
||||
|
||||
psf->sf.channels = desc->channels_per_frame ;
|
||||
|
||||
format = SF_FORMAT_CAF | (psf->endian == SF_ENDIAN_LITTLE ? SF_ENDIAN_LITTLE : 0) ;
|
||||
if (desc->fmt_id == alac_MARKER)
|
||||
{ CAF_PRIVATE *pcaf ;
|
||||
|
||||
if ((pcaf = psf->container_data) != NULL)
|
||||
{ switch (desc->fmt_flags)
|
||||
{ case 1 :
|
||||
pcaf->alac.bits_per_sample = 16 ;
|
||||
format |= SF_FORMAT_ALAC_16 ;
|
||||
break ;
|
||||
case 2 :
|
||||
pcaf->alac.bits_per_sample = 20 ;
|
||||
format |= SF_FORMAT_ALAC_20 ;
|
||||
break ;
|
||||
case 3 :
|
||||
pcaf->alac.bits_per_sample = 24 ;
|
||||
format |= SF_FORMAT_ALAC_24 ;
|
||||
break ;
|
||||
case 4 :
|
||||
pcaf->alac.bits_per_sample = 32 ;
|
||||
format |= SF_FORMAT_ALAC_32 ;
|
||||
break ;
|
||||
default :
|
||||
psf_log_printf (psf, "Bad ALAC format flag value of %d\n", desc->fmt_flags) ;
|
||||
} ;
|
||||
|
||||
pcaf->alac.frames_per_packet = desc->frames_per_packet ;
|
||||
} ;
|
||||
|
||||
return format ;
|
||||
} ;
|
||||
|
||||
format |= psf->endian == SF_ENDIAN_LITTLE ? SF_ENDIAN_LITTLE : 0 ;
|
||||
|
||||
if (desc->fmt_id == lpcm_MARKER && desc->fmt_flags & 1)
|
||||
{ /* Floating point data. */
|
||||
@@ -208,12 +298,7 @@ decode_desc_chunk (SF_PRIVATE *psf, const DESC_CHUNK *desc)
|
||||
} ;
|
||||
} ;
|
||||
|
||||
if ((desc->fmt_flags & 1) != 0)
|
||||
{ psf_log_printf (psf, "**** Ooops, 'desc' chunk suggests float data, but other info invalid.\n") ;
|
||||
return 0 ;
|
||||
} ;
|
||||
|
||||
if (desc->fmt_id == lpcm_MARKER)
|
||||
if (desc->fmt_id == lpcm_MARKER && (desc->fmt_flags & 1) == 0)
|
||||
{ /* Integer data. */
|
||||
if (desc->bits_per_chan == 32 && desc->pkt_bytes == 4 * desc->channels_per_frame)
|
||||
{ psf->bytewidth = 4 ;
|
||||
@@ -243,16 +328,23 @@ decode_desc_chunk (SF_PRIVATE *psf, const DESC_CHUNK *desc)
|
||||
return format | SF_FORMAT_ULAW ;
|
||||
} ;
|
||||
|
||||
psf_log_printf (psf, "**** Unknown format identifier.\n") ;
|
||||
|
||||
return 0 ;
|
||||
} /* decode_desc_chunk */
|
||||
|
||||
static int
|
||||
caf_read_header (SF_PRIVATE *psf)
|
||||
{ DESC_CHUNK desc ;
|
||||
{ CAF_PRIVATE *pcaf ;
|
||||
BUF_UNION ubuf ;
|
||||
DESC_CHUNK desc ;
|
||||
sf_count_t chunk_size ;
|
||||
double srate ;
|
||||
short version, flags ;
|
||||
int marker, k, have_data = 0 ;
|
||||
int marker, k, have_data = 0, error ;
|
||||
|
||||
if ((pcaf = psf->container_data) == NULL)
|
||||
return SFE_INTERNAL ;
|
||||
|
||||
memset (&desc, 0, sizeof (desc)) ;
|
||||
|
||||
@@ -262,10 +354,10 @@ caf_read_header (SF_PRIVATE *psf)
|
||||
if (marker != caff_MARKER)
|
||||
return SFE_CAF_NOT_CAF ;
|
||||
|
||||
psf_binheader_readf (psf, "mE8b", &marker, &chunk_size, psf->u.ucbuf, 8) ;
|
||||
srate = double64_be_read (psf->u.ucbuf) ;
|
||||
snprintf (psf->u.cbuf, sizeof (psf->u.cbuf), "%5.3f", srate) ;
|
||||
psf_log_printf (psf, "%M : %D\n Sample rate : %s\n", marker, chunk_size, psf->u.cbuf) ;
|
||||
psf_binheader_readf (psf, "mE8b", &marker, &chunk_size, ubuf.ucbuf, 8) ;
|
||||
srate = double64_be_read (ubuf.ucbuf) ;
|
||||
snprintf (ubuf.cbuf, sizeof (ubuf.cbuf), "%5.3f", srate) ;
|
||||
psf_log_printf (psf, "%M : %D\n Sample rate : %s\n", marker, chunk_size, ubuf.cbuf) ;
|
||||
if (marker != desc_MARKER)
|
||||
return SFE_CAF_NO_DESC ;
|
||||
|
||||
@@ -276,13 +368,13 @@ caf_read_header (SF_PRIVATE *psf)
|
||||
|
||||
psf->sf.samplerate = lrint (srate) ;
|
||||
|
||||
psf_binheader_readf (psf, "mE44444", &desc.fmt_id, &desc.fmt_flags, &desc.pkt_bytes, &desc.pkt_frames,
|
||||
psf_binheader_readf (psf, "mE44444", &desc.fmt_id, &desc.fmt_flags, &desc.pkt_bytes, &desc.frames_per_packet,
|
||||
&desc.channels_per_frame, &desc.bits_per_chan) ;
|
||||
psf_log_printf (psf, " Format id : %M\n Format flags : %x\n Bytes / packet : %u\n"
|
||||
" Frames / packet : %u\n Channels / frame : %u\n Bits / channel : %u\n",
|
||||
desc.fmt_id, desc.fmt_flags, desc.pkt_bytes, desc.pkt_frames, desc.channels_per_frame, desc.bits_per_chan) ;
|
||||
desc.fmt_id, desc.fmt_flags, desc.pkt_bytes, desc.frames_per_packet, desc.channels_per_frame, desc.bits_per_chan) ;
|
||||
|
||||
if (desc.channels_per_frame > 200)
|
||||
if (desc.channels_per_frame > SF_MAX_CHANNELS)
|
||||
{ psf_log_printf (psf, "**** Bad channels per frame value %u.\n", desc.channels_per_frame) ;
|
||||
return SFE_MALFORMED_FILE ;
|
||||
} ;
|
||||
@@ -292,14 +384,23 @@ caf_read_header (SF_PRIVATE *psf)
|
||||
|
||||
psf->sf.channels = desc.channels_per_frame ;
|
||||
|
||||
while (have_data == 0 && psf_ftell (psf) < psf->filelength - SIGNED_SIZEOF (marker))
|
||||
{ psf_binheader_readf (psf, "mE8", &marker, &chunk_size) ;
|
||||
while (psf_ftell (psf) < psf->filelength)
|
||||
{ marker = 0 ;
|
||||
chunk_size = 0 ;
|
||||
|
||||
psf_binheader_readf (psf, "mE8", &marker, &chunk_size) ;
|
||||
if (marker == 0)
|
||||
{ psf_log_printf (psf, "Have 0 marker.\n") ;
|
||||
break ;
|
||||
} ;
|
||||
|
||||
psf_store_read_chunk_u32 (&psf->rchunks, marker, psf_ftell (psf), chunk_size) ;
|
||||
|
||||
switch (marker)
|
||||
{ case peak_MARKER :
|
||||
psf_log_printf (psf, "%M : %D\n", marker, chunk_size) ;
|
||||
if (chunk_size != CAF_PEAK_CHUNK_SIZE (psf->sf.channels))
|
||||
{ psf_binheader_readf (psf, "j", (int) chunk_size) ;
|
||||
{ psf_binheader_readf (psf, "j", make_size_t (chunk_size)) ;
|
||||
psf_log_printf (psf, "*** File PEAK chunk %D should be %d.\n", chunk_size, CAF_PEAK_CHUNK_SIZE (psf->sf.channels)) ;
|
||||
return SFE_CAF_BAD_PEAK ;
|
||||
} ;
|
||||
@@ -311,7 +412,7 @@ caf_read_header (SF_PRIVATE *psf)
|
||||
psf_binheader_readf (psf, "E4", & (psf->peak_info->edit_number)) ;
|
||||
psf_log_printf (psf, " edit count : %d\n", psf->peak_info->edit_number) ;
|
||||
|
||||
psf_log_printf (psf, " Ch Position Value\n") ;
|
||||
psf_log_printf (psf, " Ch Position Value\n") ;
|
||||
for (k = 0 ; k < psf->sf.channels ; k++)
|
||||
{ sf_count_t position ;
|
||||
float value ;
|
||||
@@ -320,29 +421,95 @@ caf_read_header (SF_PRIVATE *psf)
|
||||
psf->peak_info->peaks [k].value = value ;
|
||||
psf->peak_info->peaks [k].position = position ;
|
||||
|
||||
snprintf (psf->u.cbuf, sizeof (psf->u.cbuf), " %2d %-12ld %g\n", k, (long) position, value) ;
|
||||
psf_log_printf (psf, psf->u.cbuf) ;
|
||||
snprintf (ubuf.cbuf, sizeof (ubuf.cbuf), " %2d %-12" PRId64 " %g\n", k, position, value) ;
|
||||
psf_log_printf (psf, ubuf.cbuf) ;
|
||||
} ;
|
||||
|
||||
psf->peak_info->peak_loc = SF_PEAK_START ;
|
||||
break ;
|
||||
|
||||
case chan_MARKER :
|
||||
if (chunk_size < 12)
|
||||
{ psf_log_printf (psf, "%M : %D (should be >= 12)\n", marker, chunk_size) ;
|
||||
psf_binheader_readf (psf, "j", make_size_t (chunk_size)) ;
|
||||
break ;
|
||||
}
|
||||
|
||||
psf_log_printf (psf, "%M : %D\n", marker, chunk_size) ;
|
||||
|
||||
if ((error = caf_read_chanmap (psf, chunk_size)))
|
||||
return error ;
|
||||
break ;
|
||||
|
||||
case free_MARKER :
|
||||
psf_log_printf (psf, "%M : %D\n", marker, chunk_size) ;
|
||||
psf_binheader_readf (psf, "j", (int) chunk_size) ;
|
||||
psf_binheader_readf (psf, "j", make_size_t (chunk_size)) ;
|
||||
break ;
|
||||
|
||||
case data_MARKER :
|
||||
psf_log_printf (psf, "%M : %D\n", marker, chunk_size) ;
|
||||
psf_binheader_readf (psf, "E4", &k) ;
|
||||
psf_log_printf (psf, " edit : %u\n", k) ;
|
||||
|
||||
if (chunk_size == -1)
|
||||
{ psf_log_printf (psf, "%M : -1\n") ;
|
||||
chunk_size = psf->filelength - psf->headindex ;
|
||||
}
|
||||
else if (psf->filelength > 0 && psf->filelength < psf->headindex + chunk_size - 16)
|
||||
psf_log_printf (psf, "%M : %D (should be %D)\n", marker, chunk_size, psf->filelength - psf->headindex - 8) ;
|
||||
else
|
||||
psf_log_printf (psf, "%M : %D\n", marker, chunk_size) ;
|
||||
|
||||
|
||||
psf->dataoffset = psf->headindex ;
|
||||
|
||||
/* Subtract the 4 bytes of the 'edit' field above. */
|
||||
psf->datalength = chunk_size - 4 ;
|
||||
|
||||
psf_binheader_readf (psf, "j", psf->datalength) ;
|
||||
have_data = 1 ;
|
||||
break ;
|
||||
|
||||
default :
|
||||
psf_log_printf (psf, " %M : %D (skipped)\n", marker, chunk_size) ;
|
||||
psf_binheader_readf (psf, "j", (int) chunk_size) ;
|
||||
case kuki_MARKER :
|
||||
psf_log_printf (psf, "%M : %D\n", marker, chunk_size) ;
|
||||
pcaf->alac.kuki_offset = psf_ftell (psf) - 12 ;
|
||||
psf_binheader_readf (psf, "j", make_size_t (chunk_size)) ;
|
||||
break ;
|
||||
|
||||
case pakt_MARKER :
|
||||
psf_log_printf (psf, "%M : %D\n", marker, chunk_size) ;
|
||||
|
||||
psf_binheader_readf (psf, "E8844", &pcaf->alac.packets, &pcaf->alac.valid_frames,
|
||||
&pcaf->alac.priming_frames, &pcaf->alac.remainder_frames) ;
|
||||
|
||||
psf_log_printf (psf,
|
||||
" Packets : %D\n"
|
||||
" Valid frames : %D\n"
|
||||
" Priming frames : %d\n"
|
||||
" Remainder frames : %d\n",
|
||||
pcaf->alac.packets, pcaf->alac.valid_frames, pcaf->alac.priming_frames,
|
||||
pcaf->alac.remainder_frames
|
||||
) ;
|
||||
|
||||
if (pcaf->alac.packets == 0 && pcaf->alac.valid_frames == 0
|
||||
&& pcaf->alac.priming_frames == 0 && pcaf->alac.remainder_frames == 0)
|
||||
psf_log_printf (psf, "*** 'pakt' chunk header is all zero.\n") ;
|
||||
|
||||
pcaf->alac.pakt_offset = psf_ftell (psf) - 12 ;
|
||||
psf_binheader_readf (psf, "j", make_size_t (chunk_size) - 24) ;
|
||||
break ;
|
||||
|
||||
default :
|
||||
psf_log_printf (psf, "%M : %D (skipped)\n", marker, chunk_size) ;
|
||||
psf_binheader_readf (psf, "j", make_size_t (chunk_size)) ;
|
||||
break ;
|
||||
} ;
|
||||
|
||||
if (! psf->sf.seekable && have_data)
|
||||
break ;
|
||||
|
||||
if (psf_ftell (psf) >= psf->filelength - SIGNED_SIZEOF (chunk_size))
|
||||
{ psf_log_printf (psf, "End\n") ;
|
||||
break ;
|
||||
} ;
|
||||
} ;
|
||||
|
||||
@@ -351,12 +518,10 @@ caf_read_header (SF_PRIVATE *psf)
|
||||
return SFE_MALFORMED_FILE ;
|
||||
} ;
|
||||
|
||||
psf_log_printf (psf, "End\n") ;
|
||||
|
||||
psf->dataoffset = psf_ftell (psf) ;
|
||||
psf->datalength = psf->filelength - psf->dataoffset ;
|
||||
psf->endian = (desc.fmt_flags & 2) ? SF_ENDIAN_LITTLE : SF_ENDIAN_BIG ;
|
||||
|
||||
psf_fseek (psf, psf->dataoffset, SEEK_SET) ;
|
||||
|
||||
if ((psf->sf.format = decode_desc_chunk (psf, &desc)) == 0)
|
||||
return SFE_UNSUPPORTED_ENCODING ;
|
||||
|
||||
@@ -371,9 +536,15 @@ caf_read_header (SF_PRIVATE *psf)
|
||||
|
||||
static int
|
||||
caf_write_header (SF_PRIVATE *psf, int calc_length)
|
||||
{ DESC_CHUNK desc ;
|
||||
{ BUF_UNION ubuf ;
|
||||
CAF_PRIVATE *pcaf ;
|
||||
DESC_CHUNK desc ;
|
||||
sf_count_t current, free_len ;
|
||||
int subformat ;
|
||||
uint32_t uk ;
|
||||
int subformat, append_free_block = SF_TRUE ;
|
||||
|
||||
if ((pcaf = psf->container_data) == NULL)
|
||||
return SFE_INTERNAL ;
|
||||
|
||||
memset (&desc, 0, sizeof (desc)) ;
|
||||
|
||||
@@ -402,8 +573,8 @@ caf_write_header (SF_PRIVATE *psf, int calc_length)
|
||||
/* 'desc' marker and chunk size. */
|
||||
psf_binheader_writef (psf, "Em8", desc_MARKER, (sf_count_t) (sizeof (DESC_CHUNK))) ;
|
||||
|
||||
double64_be_write (1.0 * psf->sf.samplerate, psf->u.ucbuf) ;
|
||||
psf_binheader_writef (psf, "b", psf->u.ucbuf, make_size_t (8)) ;
|
||||
double64_be_write (1.0 * psf->sf.samplerate, ubuf.ucbuf) ;
|
||||
psf_binheader_writef (psf, "b", ubuf.ucbuf, make_size_t (8)) ;
|
||||
|
||||
subformat = SF_CODEC (psf->sf.format) ;
|
||||
|
||||
@@ -425,7 +596,7 @@ caf_write_header (SF_PRIVATE *psf, int calc_length)
|
||||
desc.fmt_id = lpcm_MARKER ;
|
||||
psf->bytewidth = 1 ;
|
||||
desc.pkt_bytes = psf->bytewidth * psf->sf.channels ;
|
||||
desc.pkt_frames = 1 ;
|
||||
desc.frames_per_packet = 1 ;
|
||||
desc.channels_per_frame = psf->sf.channels ;
|
||||
desc.bits_per_chan = 8 ;
|
||||
break ;
|
||||
@@ -434,7 +605,7 @@ caf_write_header (SF_PRIVATE *psf, int calc_length)
|
||||
desc.fmt_id = lpcm_MARKER ;
|
||||
psf->bytewidth = 2 ;
|
||||
desc.pkt_bytes = psf->bytewidth * psf->sf.channels ;
|
||||
desc.pkt_frames = 1 ;
|
||||
desc.frames_per_packet = 1 ;
|
||||
desc.channels_per_frame = psf->sf.channels ;
|
||||
desc.bits_per_chan = 16 ;
|
||||
break ;
|
||||
@@ -442,7 +613,7 @@ caf_write_header (SF_PRIVATE *psf, int calc_length)
|
||||
case SF_FORMAT_PCM_24 :
|
||||
psf->bytewidth = 3 ;
|
||||
desc.pkt_bytes = psf->bytewidth * psf->sf.channels ;
|
||||
desc.pkt_frames = 1 ;
|
||||
desc.frames_per_packet = 1 ;
|
||||
desc.channels_per_frame = psf->sf.channels ;
|
||||
desc.bits_per_chan = 24 ;
|
||||
desc.fmt_id = lpcm_MARKER ;
|
||||
@@ -452,7 +623,7 @@ caf_write_header (SF_PRIVATE *psf, int calc_length)
|
||||
desc.fmt_id = lpcm_MARKER ;
|
||||
psf->bytewidth = 4 ;
|
||||
desc.pkt_bytes = psf->bytewidth * psf->sf.channels ;
|
||||
desc.pkt_frames = 1 ;
|
||||
desc.frames_per_packet = 1 ;
|
||||
desc.channels_per_frame = psf->sf.channels ;
|
||||
desc.bits_per_chan = 32 ;
|
||||
break ;
|
||||
@@ -462,7 +633,7 @@ caf_write_header (SF_PRIVATE *psf, int calc_length)
|
||||
desc.fmt_flags |= 1 ;
|
||||
psf->bytewidth = 4 ;
|
||||
desc.pkt_bytes = psf->bytewidth * psf->sf.channels ;
|
||||
desc.pkt_frames = 1 ;
|
||||
desc.frames_per_packet = 1 ;
|
||||
desc.channels_per_frame = psf->sf.channels ;
|
||||
desc.bits_per_chan = 32 ;
|
||||
break ;
|
||||
@@ -472,7 +643,7 @@ caf_write_header (SF_PRIVATE *psf, int calc_length)
|
||||
desc.fmt_flags |= 1 ;
|
||||
psf->bytewidth = 8 ;
|
||||
desc.pkt_bytes = psf->bytewidth * psf->sf.channels ;
|
||||
desc.pkt_frames = 1 ;
|
||||
desc.frames_per_packet = 1 ;
|
||||
desc.channels_per_frame = psf->sf.channels ;
|
||||
desc.bits_per_chan = 64 ;
|
||||
break ;
|
||||
@@ -481,7 +652,7 @@ caf_write_header (SF_PRIVATE *psf, int calc_length)
|
||||
desc.fmt_id = alaw_MARKER ;
|
||||
psf->bytewidth = 1 ;
|
||||
desc.pkt_bytes = psf->bytewidth * psf->sf.channels ;
|
||||
desc.pkt_frames = 1 ;
|
||||
desc.frames_per_packet = 1 ;
|
||||
desc.channels_per_frame = psf->sf.channels ;
|
||||
desc.bits_per_chan = 8 ;
|
||||
break ;
|
||||
@@ -490,19 +661,30 @@ caf_write_header (SF_PRIVATE *psf, int calc_length)
|
||||
desc.fmt_id = ulaw_MARKER ;
|
||||
psf->bytewidth = 1 ;
|
||||
desc.pkt_bytes = psf->bytewidth * psf->sf.channels ;
|
||||
desc.pkt_frames = 1 ;
|
||||
desc.frames_per_packet = 1 ;
|
||||
desc.channels_per_frame = psf->sf.channels ;
|
||||
desc.bits_per_chan = 8 ;
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_ALAC_16 :
|
||||
case SF_FORMAT_ALAC_20 :
|
||||
case SF_FORMAT_ALAC_24 :
|
||||
case SF_FORMAT_ALAC_32 :
|
||||
desc.fmt_id = alac_MARKER ;
|
||||
desc.pkt_bytes = psf->bytewidth * psf->sf.channels ;
|
||||
desc.channels_per_frame = psf->sf.channels ;
|
||||
alac_get_desc_chunk_items (subformat, &desc.fmt_flags, &desc.frames_per_packet) ;
|
||||
append_free_block = SF_FALSE ;
|
||||
break ;
|
||||
|
||||
default :
|
||||
return SFE_UNIMPLEMENTED ;
|
||||
} ;
|
||||
|
||||
psf_binheader_writef (psf, "mE44444", desc.fmt_id, desc.fmt_flags, desc.pkt_bytes, desc.pkt_frames, desc.channels_per_frame, desc.bits_per_chan) ;
|
||||
psf_binheader_writef (psf, "mE44444", desc.fmt_id, desc.fmt_flags, desc.pkt_bytes, desc.frames_per_packet, desc.channels_per_frame, desc.bits_per_chan) ;
|
||||
|
||||
#if 0
|
||||
if (psf->str_flags & SF_STR_LOCATE_START)
|
||||
if (psf->strings.flags & SF_STR_LOCATE_START)
|
||||
caf_write_strings (psf, SF_STR_LOCATE_START) ;
|
||||
#endif
|
||||
|
||||
@@ -513,13 +695,22 @@ caf_write_header (SF_PRIVATE *psf, int calc_length)
|
||||
psf_binheader_writef (psf, "Ef8", (float) psf->peak_info->peaks [k].value, psf->peak_info->peaks [k].position) ;
|
||||
} ;
|
||||
|
||||
/* Add free chunk so that the actual audio data starts at a multiple 0x1000. */
|
||||
free_len = 0x1000 - psf->headindex - 16 - 12 ;
|
||||
while (free_len < 0)
|
||||
free_len += 0x1000 ;
|
||||
psf_binheader_writef (psf, "Em8z", free_MARKER, free_len, (int) free_len) ;
|
||||
if (psf->channel_map && pcaf->chanmap_tag)
|
||||
psf_binheader_writef (psf, "Em8444", chan_MARKER, (sf_count_t) 12, pcaf->chanmap_tag, 0, 0) ;
|
||||
|
||||
psf_binheader_writef (psf, "Em84", data_MARKER, psf->datalength, 0) ;
|
||||
/* Write custom headers. */
|
||||
for (uk = 0 ; uk < psf->wchunks.used ; uk++)
|
||||
psf_binheader_writef (psf, "m44b", (int) psf->wchunks.chunks [uk].mark32, 0, psf->wchunks.chunks [uk].len, psf->wchunks.chunks [uk].data, make_size_t (psf->wchunks.chunks [uk].len)) ;
|
||||
|
||||
if (append_free_block)
|
||||
{ /* Add free chunk so that the actual audio data starts at a multiple 0x1000. */
|
||||
free_len = 0x1000 - psf->headindex - 16 - 12 ;
|
||||
while (free_len < 0)
|
||||
free_len += 0x1000 ;
|
||||
psf_binheader_writef (psf, "Em8z", free_MARKER, free_len, (int) free_len) ;
|
||||
} ;
|
||||
|
||||
psf_binheader_writef (psf, "Em84", data_MARKER, psf->datalength + 4, 0) ;
|
||||
|
||||
psf_fwrite (psf->header, psf->headindex, 1, psf) ;
|
||||
if (psf->error)
|
||||
@@ -534,3 +725,80 @@ caf_write_header (SF_PRIVATE *psf, int calc_length)
|
||||
return psf->error ;
|
||||
} /* caf_write_header */
|
||||
|
||||
static int
|
||||
caf_read_chanmap (SF_PRIVATE * psf, sf_count_t chunk_size)
|
||||
{ const AIFF_CAF_CHANNEL_MAP * map_info ;
|
||||
unsigned channel_bitmap, channel_decriptions, bytesread ;
|
||||
int layout_tag ;
|
||||
|
||||
bytesread = psf_binheader_readf (psf, "E444", &layout_tag, &channel_bitmap, &channel_decriptions) ;
|
||||
|
||||
map_info = aiff_caf_of_channel_layout_tag (layout_tag) ;
|
||||
|
||||
psf_log_printf (psf, " Tag : %x\n", layout_tag) ;
|
||||
if (map_info)
|
||||
psf_log_printf (psf, " Layout : %s\n", map_info->name) ;
|
||||
|
||||
if (bytesread < chunk_size)
|
||||
psf_binheader_readf (psf, "j", chunk_size - bytesread) ;
|
||||
|
||||
if (map_info->channel_map != NULL)
|
||||
{ size_t chanmap_size = psf->sf.channels * sizeof (psf->channel_map [0]) ;
|
||||
|
||||
free (psf->channel_map) ;
|
||||
|
||||
if ((psf->channel_map = malloc (chanmap_size)) == NULL)
|
||||
return SFE_MALLOC_FAILED ;
|
||||
|
||||
memcpy (psf->channel_map, map_info->channel_map, chanmap_size) ;
|
||||
} ;
|
||||
|
||||
return 0 ;
|
||||
} /* caf_read_chanmap */
|
||||
|
||||
/*==============================================================================
|
||||
*/
|
||||
|
||||
static int
|
||||
caf_set_chunk (SF_PRIVATE *psf, const SF_CHUNK_INFO * chunk_info)
|
||||
{ return psf_save_write_chunk (&psf->wchunks, chunk_info) ;
|
||||
} /* caf_set_chunk */
|
||||
|
||||
static SF_CHUNK_ITERATOR *
|
||||
caf_next_chunk_iterator (SF_PRIVATE *psf, SF_CHUNK_ITERATOR * iterator)
|
||||
{ return psf_next_chunk_iterator (&psf->rchunks, iterator) ;
|
||||
} /* caf_next_chunk_iterator */
|
||||
|
||||
static int
|
||||
caf_get_chunk_size (SF_PRIVATE *psf, const SF_CHUNK_ITERATOR * iterator, SF_CHUNK_INFO * chunk_info)
|
||||
{ int indx ;
|
||||
|
||||
if ((indx = psf_find_read_chunk_iterator (&psf->rchunks, iterator)) < 0)
|
||||
return SFE_UNKNOWN_CHUNK ;
|
||||
|
||||
chunk_info->datalen = psf->rchunks.chunks [indx].len ;
|
||||
|
||||
return SFE_NO_ERROR ;
|
||||
} /* caf_get_chunk_size */
|
||||
|
||||
static int
|
||||
caf_get_chunk_data (SF_PRIVATE *psf, const SF_CHUNK_ITERATOR * iterator, SF_CHUNK_INFO * chunk_info)
|
||||
{ int indx ;
|
||||
sf_count_t pos ;
|
||||
|
||||
if ((indx = psf_find_read_chunk_iterator (&psf->rchunks, iterator)) < 0)
|
||||
return SFE_UNKNOWN_CHUNK ;
|
||||
|
||||
if (chunk_info->data == NULL)
|
||||
return SFE_BAD_CHUNK_DATA_PTR ;
|
||||
|
||||
chunk_info->id_size = psf->rchunks.chunks [indx].id_size ;
|
||||
memcpy (chunk_info->id, psf->rchunks.chunks [indx].id, sizeof (chunk_info->id) / sizeof (*chunk_info->id)) ;
|
||||
|
||||
pos = psf_ftell (psf) ;
|
||||
psf_fseek (psf, psf->rchunks.chunks [indx].offset, SEEK_SET) ;
|
||||
psf_fread (chunk_info->data, SF_MIN (chunk_info->datalen, psf->rchunks.chunks [indx].len), 1, psf) ;
|
||||
psf_fseek (psf, pos, SEEK_SET) ;
|
||||
|
||||
return SFE_NO_ERROR ;
|
||||
} /* caf_get_chunk_data */
|
||||
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
** Copyright (C) 2012 Chris Roberts <c.roberts@csrfm.com>
|
||||
** Copyright (C) 2006-2013 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
** Copyright (C) 2006 Paul Davis <paul@linuxaudiosystems.com>
|
||||
**
|
||||
** This program 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 program 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 program; if not, write to the Free Software
|
||||
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "sfconfig.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "common.h"
|
||||
|
||||
|
||||
|
||||
static inline size_t
|
||||
cart_min_size (const SF_CART_INFO* info)
|
||||
{ if (info == NULL)
|
||||
return 0 ;
|
||||
|
||||
return offsetof (SF_CART_INFO, tag_text) + info->tag_text_size ;
|
||||
} /* cart_min_size */
|
||||
|
||||
SF_CART_INFO_16K*
|
||||
cart_var_alloc (void)
|
||||
{ SF_CART_INFO_16K* thing ;
|
||||
thing = malloc (sizeof (SF_CART_INFO_16K)) ;
|
||||
return thing ;
|
||||
} /* cart_var_alloc */
|
||||
|
||||
int
|
||||
cart_var_set (SF_PRIVATE *psf, const SF_CART_INFO * info, size_t datasize)
|
||||
{ size_t len ;
|
||||
|
||||
if (info == NULL)
|
||||
return SF_FALSE ;
|
||||
|
||||
if (cart_min_size (info) > datasize)
|
||||
{ psf->error = SFE_BAD_CART_INFO_SIZE ;
|
||||
return SF_FALSE ;
|
||||
} ;
|
||||
|
||||
if (datasize >= sizeof (SF_CART_INFO_16K))
|
||||
{ psf->error = SFE_BAD_CART_INFO_TOO_BIG ;
|
||||
return SF_FALSE ;
|
||||
} ;
|
||||
|
||||
if (psf->cart_16k == NULL)
|
||||
{ if ((psf->cart_16k = cart_var_alloc ()) == NULL)
|
||||
{ psf->error = SFE_MALLOC_FAILED ;
|
||||
return SF_FALSE ;
|
||||
} ;
|
||||
} ;
|
||||
|
||||
memcpy (psf->cart_16k, info, offsetof (SF_CART_INFO, tag_text)) ;
|
||||
psf_strlcpy_crlf (psf->cart_16k->tag_text, info->tag_text, sizeof (psf->cart_16k->tag_text), datasize - offsetof (SF_CART_INFO, tag_text)) ;
|
||||
|
||||
len = strlen (psf->cart_16k->tag_text) ;
|
||||
|
||||
if (len > 0 && psf->cart_16k->tag_text [len - 1] != '\n')
|
||||
psf_strlcat (psf->cart_16k->tag_text, sizeof (psf->cart_16k->tag_text), "\r\n") ;
|
||||
|
||||
/* Force tag_text_size to be even. */
|
||||
len = strlen (psf->cart_16k->tag_text) ;
|
||||
len += (len & 1) ? 1 : 2 ;
|
||||
|
||||
psf->cart_16k->tag_text_size = len ;
|
||||
|
||||
return SF_TRUE ;
|
||||
} /* cart_var_set */
|
||||
|
||||
|
||||
int
|
||||
cart_var_get (SF_PRIVATE *psf, SF_CART_INFO * data, size_t datasize)
|
||||
{ size_t size ;
|
||||
if (psf->cart_16k == NULL)
|
||||
return SF_FALSE ;
|
||||
|
||||
size = SF_MIN (datasize, cart_min_size ((const SF_CART_INFO *) psf->cart_16k)) ;
|
||||
|
||||
memcpy (data, psf->cart_16k, size) ;
|
||||
|
||||
return SF_TRUE ;
|
||||
} /* cart_var_get */
|
||||
|
||||
|
||||
@@ -0,0 +1,262 @@
|
||||
/*
|
||||
** Copyright (C) 2009-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program 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 program 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 program; if not, write to the Free Software
|
||||
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
** Mostly from "Apple Core Audio Format Specification 1.0":
|
||||
**
|
||||
** http://developer.apple.com/documentation/MusicAudio/Reference/CAFSpec/CAFSpec.pdf
|
||||
*/
|
||||
|
||||
#include "sfconfig.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "sndfile.h"
|
||||
#include "common.h"
|
||||
#include "chanmap.h"
|
||||
|
||||
|
||||
static const AIFF_CAF_CHANNEL_MAP zero_chan [] =
|
||||
{ { (0 << 16) | 0, NULL, "Use channel descriptions." },
|
||||
{ (1 << 16) | 0, NULL, "Use channel bitmap." }
|
||||
} ; /* zero_chan */
|
||||
|
||||
|
||||
static const int one_chan_mono [1] = { SF_CHANNEL_MAP_MONO } ;
|
||||
|
||||
static const AIFF_CAF_CHANNEL_MAP one_chan [] =
|
||||
{ { (100 << 16) | 1, one_chan_mono, "mono" }
|
||||
} ; /* one_chan */
|
||||
|
||||
|
||||
static const int two_channel_stereo [2] = { SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT } ;
|
||||
|
||||
static const AIFF_CAF_CHANNEL_MAP two_chan [] =
|
||||
{ { (101 << 16) | 2, two_channel_stereo, "stereo (L, R)" },
|
||||
{ (102 << 16) | 2, two_channel_stereo, "stereo headphones (L, R)" },
|
||||
#if 0
|
||||
{ (103 << 16) | 2, NULL, "matrix stereo (Lt, Rt)" },
|
||||
{ (104 << 16) | 2, NULL, "2 channels (mid, side)" },
|
||||
{ (105 << 16) | 2, NULL, "coincident mic pair" },
|
||||
{ (106 << 16) | 2, NULL, "binaural stereo (L, R)"
|
||||
}
|
||||
#endif
|
||||
} ; /* two_chan */
|
||||
|
||||
|
||||
static const int three_channel_mpeg_30a [3] =
|
||||
{ SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT, SF_CHANNEL_MAP_CENTER } ;
|
||||
static const int three_channel_mpeg_30b [3] =
|
||||
{ SF_CHANNEL_MAP_CENTER, SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT } ;
|
||||
static const int three_channel_itu_21 [3] =
|
||||
{ SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT, SF_CHANNEL_MAP_REAR_CENTER } ;
|
||||
static const int three_channel_dvd_4 [3] =
|
||||
{ SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT, SF_CHANNEL_MAP_LFE } ;
|
||||
|
||||
static const AIFF_CAF_CHANNEL_MAP three_chan [] =
|
||||
{ { (113 << 16) | 3, three_channel_mpeg_30a, "MPEG 3 0 A (L, R, C)" },
|
||||
{ (114 << 16) | 3, three_channel_mpeg_30b, "MPEG 3 0 B (C, L, R)" },
|
||||
{ (131 << 16) | 3, three_channel_itu_21, "ITU 2.1 (L, R, Cs)" },
|
||||
{ (133 << 16) | 3, three_channel_dvd_4, "DVD 4 (L, R, LFE)" }
|
||||
} ; /* three_chan */
|
||||
|
||||
|
||||
static const int four_channel_ambisonc_b [4] =
|
||||
{ SF_CHANNEL_MAP_AMBISONIC_B_W, SF_CHANNEL_MAP_AMBISONIC_B_X, SF_CHANNEL_MAP_AMBISONIC_B_Y, SF_CHANNEL_MAP_AMBISONIC_B_Z } ;
|
||||
static const int four_channel_quad [4] =
|
||||
{ SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT, SF_CHANNEL_MAP_REAR_LEFT, SF_CHANNEL_MAP_REAR_RIGHT } ;
|
||||
static const int four_channel_mpeg_40a [4] =
|
||||
{ SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT, SF_CHANNEL_MAP_CENTER, SF_CHANNEL_MAP_REAR_CENTER } ;
|
||||
static const int four_channel_mpeg_40b [4] =
|
||||
{ SF_CHANNEL_MAP_CENTER, SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT, SF_CHANNEL_MAP_REAR_CENTER } ;
|
||||
static const int four_channel_itu_23 [4] =
|
||||
{ SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT, SF_CHANNEL_MAP_REAR_LEFT, SF_CHANNEL_MAP_REAR_RIGHT } ;
|
||||
static const int four_channel_dvd_5 [4] =
|
||||
{ SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT, SF_CHANNEL_MAP_LFE, SF_CHANNEL_MAP_REAR_CENTER } ;
|
||||
static const int four_channel_dvd_10 [4] =
|
||||
{ SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT, SF_CHANNEL_MAP_CENTER, SF_CHANNEL_MAP_LFE } ;
|
||||
|
||||
static const AIFF_CAF_CHANNEL_MAP four_chan [] =
|
||||
{ { (107 << 16) | 4, four_channel_ambisonc_b, "ambisonic B (W, X, Y, Z)" },
|
||||
{ (108 << 16) | 4, four_channel_quad, "quad (Lfront, Rfront, Lrear, Rrear)" },
|
||||
{ (115 << 16) | 4, four_channel_mpeg_40a, "MPEG 4.0 A (L, R, C, Cs)" },
|
||||
{ (116 << 16) | 4, four_channel_mpeg_40b, "MPEG 4.0 B (C, L, R, Cs)" },
|
||||
{ (132 << 16) | 4, four_channel_itu_23, "ITU 2.3 (L, R, Ls, Rs)" },
|
||||
{ (134 << 16) | 4, four_channel_dvd_5, "DVD 5 (L, R, LFE, Cs)" },
|
||||
{ (136 << 16) | 4, four_channel_dvd_10, "DVD 10 (L, R, C, LFE)" }
|
||||
} ; /* four_chan */
|
||||
|
||||
|
||||
static const int five_channel_pentagonal [5] =
|
||||
{ SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT, SF_CHANNEL_MAP_REAR_LEFT, SF_CHANNEL_MAP_REAR_RIGHT, SF_CHANNEL_MAP_CENTER } ;
|
||||
static const int five_channel_mpeg_50_a [5] =
|
||||
{ SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT, SF_CHANNEL_MAP_CENTER, SF_CHANNEL_MAP_REAR_LEFT, SF_CHANNEL_MAP_REAR_RIGHT } ;
|
||||
static const int five_channel_mpeg_50_b [5] =
|
||||
{ SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT, SF_CHANNEL_MAP_REAR_LEFT, SF_CHANNEL_MAP_REAR_RIGHT, SF_CHANNEL_MAP_CENTER } ;
|
||||
static const int five_channel_mpeg_50_c [5] =
|
||||
{ SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_CENTER, SF_CHANNEL_MAP_RIGHT, SF_CHANNEL_MAP_REAR_LEFT, SF_CHANNEL_MAP_REAR_RIGHT } ;
|
||||
static const int five_channel_mpeg_50_d [5] =
|
||||
{ SF_CHANNEL_MAP_CENTER, SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT, SF_CHANNEL_MAP_REAR_LEFT, SF_CHANNEL_MAP_REAR_RIGHT } ;
|
||||
static const int five_channel_dvd_6 [5] =
|
||||
{ SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT, SF_CHANNEL_MAP_LFE, SF_CHANNEL_MAP_REAR_LEFT, SF_CHANNEL_MAP_REAR_RIGHT } ;
|
||||
static const int five_channel_dvd_11 [5] =
|
||||
{ SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT, SF_CHANNEL_MAP_CENTER, SF_CHANNEL_MAP_LFE, SF_CHANNEL_MAP_REAR_CENTER } ;
|
||||
static const int five_channel_dvd_18 [5] =
|
||||
{ SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT, SF_CHANNEL_MAP_REAR_LEFT, SF_CHANNEL_MAP_REAR_RIGHT, SF_CHANNEL_MAP_LFE } ;
|
||||
|
||||
static const AIFF_CAF_CHANNEL_MAP five_chan [] =
|
||||
{ { (109 << 16) | 5, five_channel_pentagonal, "pentagonal (L, R, Lrear, Rrear, C)" },
|
||||
{ (117 << 16) | 5, five_channel_mpeg_50_a, "MPEG 5.0 A (L, R, C, Ls, Rs)" },
|
||||
{ (118 << 16) | 5, five_channel_mpeg_50_b, "MPEG 5.0 B (L, R, Ls, Rs, C)" },
|
||||
{ (119 << 16) | 5, five_channel_mpeg_50_c, "MPEG 5.0 C (L, C, R, Ls, Rs,)" },
|
||||
{ (120 << 16) | 5, five_channel_mpeg_50_d, "MPEG 5.0 D (C, L, R, Ls, Rs)" },
|
||||
{ (135 << 16) | 5, five_channel_dvd_6, "DVD 6 (L, R, LFE, Ls, Rs)" },
|
||||
{ (137 << 16) | 5, five_channel_dvd_11, "DVD 11 (L, R, C, LFE, Cs)" },
|
||||
{ (138 << 16) | 5, five_channel_dvd_18, "DVD 18 (L, R, Ls, Rs, LFE)" }
|
||||
} ; /* five_chan */
|
||||
|
||||
|
||||
static const int six_channel_mpeg_51_a [6] =
|
||||
{ SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT, SF_CHANNEL_MAP_CENTER, SF_CHANNEL_MAP_LFE, SF_CHANNEL_MAP_REAR_LEFT, SF_CHANNEL_MAP_REAR_RIGHT } ;
|
||||
static const int six_channel_mpeg_51_b [6] =
|
||||
{ SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT, SF_CHANNEL_MAP_REAR_LEFT, SF_CHANNEL_MAP_REAR_RIGHT, SF_CHANNEL_MAP_CENTER, SF_CHANNEL_MAP_LFE } ;
|
||||
static const int six_channel_mpeg_51_c [6] =
|
||||
{ SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_CENTER, SF_CHANNEL_MAP_RIGHT, SF_CHANNEL_MAP_REAR_LEFT, SF_CHANNEL_MAP_REAR_RIGHT, SF_CHANNEL_MAP_LFE } ;
|
||||
static const int six_channel_mpeg_51_d [6] =
|
||||
{ SF_CHANNEL_MAP_CENTER, SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT, SF_CHANNEL_MAP_REAR_LEFT, SF_CHANNEL_MAP_REAR_RIGHT, SF_CHANNEL_MAP_LFE } ;
|
||||
static const int six_channel_audio_unit_60 [6] =
|
||||
{ SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT, SF_CHANNEL_MAP_REAR_LEFT, SF_CHANNEL_MAP_REAR_RIGHT, SF_CHANNEL_MAP_CENTER, SF_CHANNEL_MAP_REAR_CENTER } ;
|
||||
static const int six_channel_aac_60 [6] =
|
||||
{ SF_CHANNEL_MAP_CENTER, SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT, SF_CHANNEL_MAP_REAR_LEFT, SF_CHANNEL_MAP_REAR_RIGHT, SF_CHANNEL_MAP_REAR_CENTER } ;
|
||||
|
||||
static const AIFF_CAF_CHANNEL_MAP six_chan [] =
|
||||
{ { (110 << 16) | 6, NULL, "hexagonal (L, R, Lr, Rr, C, Rear)" },
|
||||
{ (121 << 16) | 6, six_channel_mpeg_51_a, "MPEG 5.1 A (L, R, C, LFE, Ls, Rs)" },
|
||||
{ (122 << 16) | 6, six_channel_mpeg_51_b, "MPEG 5.1 B (L, R, Ls, Rs, C, LFE)" },
|
||||
{ (123 << 16) | 6, six_channel_mpeg_51_c, "MPEG 5.1 C (L, C, R, Ls, Rs, LFE)" },
|
||||
{ (124 << 16) | 6, six_channel_mpeg_51_d, "MPEG 5.1 D (C, L, R, Ls, Rs, LFE)" },
|
||||
{ (139 << 16) | 6, six_channel_audio_unit_60, "AudioUnit 6.0 (L, R, Ls, Rs, C, Cs)" },
|
||||
{ (141 << 16) | 6, six_channel_aac_60, "AAC 6.0 (C, L, R, Ls, Rs, Cs)" }
|
||||
} ; /* six_chan */
|
||||
|
||||
|
||||
static const int six_channel_mpeg_61a [7] =
|
||||
{ SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT, SF_CHANNEL_MAP_CENTER, SF_CHANNEL_MAP_LFE, SF_CHANNEL_MAP_REAR_LEFT, SF_CHANNEL_MAP_REAR_RIGHT, SF_CHANNEL_MAP_REAR_CENTER } ;
|
||||
static const int six_channel_aac_61 [7] =
|
||||
{ SF_CHANNEL_MAP_CENTER, SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT, SF_CHANNEL_MAP_REAR_LEFT, SF_CHANNEL_MAP_REAR_RIGHT, SF_CHANNEL_MAP_REAR_CENTER, SF_CHANNEL_MAP_LFE } ;
|
||||
|
||||
static const AIFF_CAF_CHANNEL_MAP seven_chan [] =
|
||||
{ { (125 << 16) | 7, six_channel_mpeg_61a, "MPEG 6.1 A (L, R, C, LFE, Ls, Rs, Cs)" },
|
||||
{ (140 << 16) | 7, NULL, "AudioUnit 7.0 (L, R, Ls, Rs, C, Rls, Rrs)" },
|
||||
{ (142 << 16) | 7, six_channel_aac_61, "AAC 6.1 (C, L, R, Ls, Rs, Cs, Lfe)" },
|
||||
{ (143 << 16) | 7, NULL, "AAC 7.0 (C, L, R, Ls, Rs, Rls, Rrs,)" }
|
||||
} ; /* seven_chan */
|
||||
|
||||
|
||||
static const AIFF_CAF_CHANNEL_MAP eight_chan [] =
|
||||
{ { (111 << 16) | 8, NULL,
|
||||
// front left, front right, rear left, rear right,
|
||||
// front center, rear center, side left, side right
|
||||
"octagonal (Lf, Rf, Lr, Rr, Cf, Cr, Ls, Rs)"
|
||||
},
|
||||
{ (112 << 16) | 8, NULL,
|
||||
// left, right, rear left, rear right
|
||||
// top left, top right, top rear left, top rear right
|
||||
"cube (L, R, Lrear, Rrear, Ltop, Rtop, Ltoprear, Rtoprear)"
|
||||
},
|
||||
{ (126 << 16) | 8, NULL, "MPEG 7.1 A (L, R, C, LFE, Ls, Rs, Lc, Rc)" },
|
||||
{ (127 << 16) | 8, NULL, "MPEG 7.1 B (C, Lc, Rc, L, R, Ls, Rs, LFE)" },
|
||||
{ (128 << 16) | 8, NULL, "MPEG 7.1 C (L, R, C, LFE, Ls, R, Rls, Rrs)" },
|
||||
{ (129 << 16) | 8, NULL, "Emagic Default 7.1 (L, R, Ls, Rs, C, LFE, Lc, Rc)" },
|
||||
{ (130 << 16) | 8, NULL,
|
||||
// (ITU_5_1 plus a matrix encoded stereo mix)
|
||||
"SMPTE DTV (L, R, C, LFE, Ls, Rs, Lt, Rt)"
|
||||
},
|
||||
{ (144 << 16) | 8, NULL, "AAC octagonal (C, L, R, Ls, Rs, Rls, Rrs, Cs)" }
|
||||
} ; /* eight_chan */
|
||||
|
||||
|
||||
|
||||
#if 0
|
||||
|
||||
TMH_10_2_std = (145 << 16) | 16,
|
||||
// L R C Vhc Lsd Rsd Ls Rs Vhl Vhr Lw Rw Csd Cs LFE1 LFE2
|
||||
|
||||
TMH_10_2_full = (146 << 16) | 21,
|
||||
// TMH_10_2_std plus: Lc Rc HI VI Haptic
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct
|
||||
{ const AIFF_CAF_CHANNEL_MAP * map ;
|
||||
int len ;
|
||||
} MAP_MAP ;
|
||||
|
||||
static const MAP_MAP map [] =
|
||||
{ { zero_chan, ARRAY_LEN (zero_chan) },
|
||||
{ one_chan, ARRAY_LEN (one_chan) },
|
||||
{ two_chan, ARRAY_LEN (two_chan) },
|
||||
{ three_chan, ARRAY_LEN (three_chan) },
|
||||
{ four_chan, ARRAY_LEN (four_chan) },
|
||||
{ five_chan, ARRAY_LEN (five_chan) },
|
||||
{ six_chan, ARRAY_LEN (six_chan) },
|
||||
{ seven_chan, ARRAY_LEN (seven_chan) },
|
||||
{ eight_chan, ARRAY_LEN (eight_chan) }
|
||||
} ; /* map */
|
||||
|
||||
|
||||
int
|
||||
aiff_caf_find_channel_layout_tag (const int *chan_map, int channels)
|
||||
{ const AIFF_CAF_CHANNEL_MAP * curr_map ;
|
||||
unsigned k, len ;
|
||||
|
||||
if (channels < 1 || channels > ARRAY_LEN (map))
|
||||
return 0 ;
|
||||
|
||||
curr_map = map [channels].map ;
|
||||
len = map [channels].len ;
|
||||
|
||||
for (k = 0 ; k < len ; k++)
|
||||
if (curr_map [k].channel_map != NULL)
|
||||
if (memcmp (chan_map, curr_map [k].channel_map, channels * sizeof (chan_map [0])) == 0)
|
||||
return curr_map [k].channel_layout_tag ;
|
||||
|
||||
return 0 ;
|
||||
} /* aiff_caf_find_channel_layout_tag */
|
||||
|
||||
const AIFF_CAF_CHANNEL_MAP *
|
||||
aiff_caf_of_channel_layout_tag (int tag)
|
||||
{ const AIFF_CAF_CHANNEL_MAP * curr_map ;
|
||||
unsigned k, len ;
|
||||
int channels = tag & 0xffff ;
|
||||
|
||||
if (channels < 0 || channels > ARRAY_LEN (map))
|
||||
return NULL ;
|
||||
|
||||
curr_map = map [channels].map ;
|
||||
len = map [channels].len ;
|
||||
|
||||
for (k = 0 ; k < len ; k++)
|
||||
if (curr_map [k].channel_layout_tag == tag)
|
||||
return curr_map + k ;
|
||||
|
||||
return NULL ;
|
||||
} /* aiff_caf_of_channel_layout_tag */
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
** Copyright (C) 2009-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program 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 program 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 program; if not, write to the Free Software
|
||||
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{ /* The tag in the AIFF or CAF file. */
|
||||
int channel_layout_tag ;
|
||||
|
||||
/* The equivalent array of SF_CHANNEL_MAP_* entries. */
|
||||
const int * channel_map ;
|
||||
|
||||
const char * name ;
|
||||
} AIFF_CAF_CHANNEL_MAP ;
|
||||
|
||||
|
||||
int aiff_caf_find_channel_layout_tag (const int *chan_map, int channels) ;
|
||||
|
||||
const AIFF_CAF_CHANNEL_MAP * aiff_caf_of_channel_layout_tag (int tag) ;
|
||||
+218
-17
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
** Copyright (C) 2008-2009 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
** Copyright (C) 2008-2012 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
** Copyright (C) 2012 IOhannes m zmoelnig, IEM <zmoelnig@iem.at>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
@@ -25,30 +26,230 @@
|
||||
#include "sfendian.h"
|
||||
#include "common.h"
|
||||
|
||||
static int64_t
|
||||
hash_of_str (const char * str)
|
||||
{ int64_t marker = 0 ;
|
||||
int k ;
|
||||
|
||||
void
|
||||
pchk4_store (PRIV_CHUNK4 * pchk, int marker, sf_count_t offset, sf_count_t len)
|
||||
{
|
||||
if (pchk->count >= ARRAY_LEN (pchk->l))
|
||||
return ;
|
||||
for (k = 0 ; str [k] ; k++)
|
||||
marker = marker * 0x7f + ((const uint8_t *) str) [k] ;
|
||||
|
||||
pchk->l [pchk->count].chunk = marker ;
|
||||
pchk->l [pchk->count].offset = offset ;
|
||||
pchk->l [pchk->count].len = len ;
|
||||
return marker ;
|
||||
} /* hash_of_str */
|
||||
|
||||
pchk->count ++ ;
|
||||
SF_CHUNK_ITERATOR *
|
||||
psf_get_chunk_iterator (SF_PRIVATE * psf, const char * marker_str)
|
||||
{ const READ_CHUNKS * pchk = &psf->rchunks ;
|
||||
int idx ;
|
||||
|
||||
return ;
|
||||
} /* pchk4_store */
|
||||
if (marker_str)
|
||||
idx = psf_find_read_chunk_str (pchk, marker_str) ;
|
||||
else
|
||||
idx = pchk->used > 0 ? 0 : -1 ;
|
||||
|
||||
if (idx < 0)
|
||||
return NULL ;
|
||||
|
||||
if (psf->iterator == NULL)
|
||||
{ psf->iterator = calloc (1, sizeof (SF_CHUNK_ITERATOR)) ;
|
||||
if (psf->iterator == NULL)
|
||||
return NULL ;
|
||||
} ;
|
||||
|
||||
psf->iterator->sndfile = (SNDFILE *) psf ;
|
||||
|
||||
if (marker_str)
|
||||
{ int64_t hash ;
|
||||
size_t marker_len ;
|
||||
union
|
||||
{ uint32_t marker ;
|
||||
char str [5] ;
|
||||
} u ;
|
||||
|
||||
snprintf (u.str, sizeof (u.str), "%s", marker_str) ;
|
||||
|
||||
marker_len = strlen (marker_str) ;
|
||||
if (marker_len > 64)
|
||||
marker_len = 64 ;
|
||||
|
||||
hash = marker_len > 4 ? hash_of_str (marker_str) : u.marker ;
|
||||
|
||||
memcpy (psf->iterator->id, marker_str, marker_len) ;
|
||||
psf->iterator->id_size = marker_len ;
|
||||
psf->iterator->hash = hash ;
|
||||
}
|
||||
|
||||
psf->iterator->current = idx ;
|
||||
|
||||
return psf->iterator ;
|
||||
} /* psf_get_chunk_iterator */
|
||||
|
||||
SF_CHUNK_ITERATOR *
|
||||
psf_next_chunk_iterator (const READ_CHUNKS * pchk , SF_CHUNK_ITERATOR * iterator)
|
||||
{ int64_t hash = iterator->hash ;
|
||||
uint32_t k ;
|
||||
|
||||
iterator->current++ ;
|
||||
|
||||
if (hash)
|
||||
{ for (k = iterator->current ; k < pchk->used ; k++)
|
||||
if (pchk->chunks [k].hash == hash)
|
||||
{ iterator->current = k ;
|
||||
return iterator ;
|
||||
}
|
||||
}
|
||||
else if (iterator->current < pchk->used)
|
||||
return iterator ;
|
||||
|
||||
/* No match, clear iterator and return NULL */
|
||||
memset (iterator, 0, sizeof (*iterator)) ;
|
||||
return NULL ;
|
||||
} /* psf_next_chunk_iterator */
|
||||
|
||||
static int
|
||||
psf_store_read_chunk (READ_CHUNKS * pchk, const READ_CHUNK * rchunk)
|
||||
{ if (pchk->count == 0)
|
||||
{ pchk->used = 0 ;
|
||||
pchk->count = 20 ;
|
||||
pchk->chunks = calloc (pchk->count, sizeof (READ_CHUNK)) ;
|
||||
}
|
||||
else if (pchk->used > pchk->count)
|
||||
return SFE_INTERNAL ;
|
||||
else if (pchk->used == pchk->count)
|
||||
{ READ_CHUNK * old_ptr = pchk->chunks ;
|
||||
int new_count = 3 * (pchk->count + 1) / 2 ;
|
||||
|
||||
pchk->chunks = realloc (old_ptr, new_count * sizeof (READ_CHUNK)) ;
|
||||
if (pchk->chunks == NULL)
|
||||
{ pchk->chunks = old_ptr ;
|
||||
return SFE_MALLOC_FAILED ;
|
||||
} ;
|
||||
pchk->count = new_count ;
|
||||
} ;
|
||||
|
||||
pchk->chunks [pchk->used] = *rchunk ;
|
||||
|
||||
pchk->used ++ ;
|
||||
|
||||
return SFE_NO_ERROR ;
|
||||
} /* psf_store_read_chunk */
|
||||
|
||||
int
|
||||
pchk4_find (PRIV_CHUNK4 * pchk, int marker)
|
||||
{ int k ;
|
||||
psf_store_read_chunk_u32 (READ_CHUNKS * pchk, uint32_t marker, sf_count_t offset, uint32_t len)
|
||||
{ READ_CHUNK rchunk ;
|
||||
|
||||
for (k = 0 ; k < pchk->count ; k++)
|
||||
if (pchk->l [k].chunk == marker)
|
||||
memset (&rchunk, 0, sizeof (rchunk)) ;
|
||||
|
||||
rchunk.hash = marker ;
|
||||
rchunk.mark32 = marker ;
|
||||
rchunk.offset = offset ;
|
||||
rchunk.len = len ;
|
||||
|
||||
rchunk.id_size = 4 ;
|
||||
memcpy (rchunk.id, &marker, rchunk.id_size) ;
|
||||
|
||||
return psf_store_read_chunk (pchk, &rchunk) ;
|
||||
} /* psf_store_read_chunk_u32 */
|
||||
|
||||
int
|
||||
psf_find_read_chunk_str (const READ_CHUNKS * pchk, const char * marker_str)
|
||||
{ int64_t hash ;
|
||||
uint32_t k ;
|
||||
union
|
||||
{ uint32_t marker ;
|
||||
char str [5] ;
|
||||
} u ;
|
||||
|
||||
snprintf (u.str, sizeof (u.str), "%s", marker_str) ;
|
||||
|
||||
hash = strlen (marker_str) > 4 ? hash_of_str (marker_str) : u.marker ;
|
||||
|
||||
for (k = 0 ; k < pchk->used ; k++)
|
||||
if (pchk->chunks [k].hash == hash)
|
||||
return k ;
|
||||
|
||||
return -1 ;
|
||||
} /* pchk4_find */
|
||||
} /* psf_find_read_chunk_str */
|
||||
|
||||
int
|
||||
psf_find_read_chunk_m32 (const READ_CHUNKS * pchk, uint32_t marker)
|
||||
{ uint32_t k ;
|
||||
|
||||
for (k = 0 ; k < pchk->used ; k++)
|
||||
if (pchk->chunks [k].mark32 == marker)
|
||||
return k ;
|
||||
|
||||
return -1 ;
|
||||
} /* psf_find_read_chunk_m32 */
|
||||
int
|
||||
psf_find_read_chunk_iterator (const READ_CHUNKS * pchk, const SF_CHUNK_ITERATOR * marker)
|
||||
{ if (marker->current < pchk->used)
|
||||
return marker->current ;
|
||||
|
||||
return -1 ;
|
||||
} /* psf_find_read_chunk_iterator */
|
||||
|
||||
int
|
||||
psf_store_read_chunk_str (READ_CHUNKS * pchk, const char * marker_str, sf_count_t offset, uint32_t len)
|
||||
{ READ_CHUNK rchunk ;
|
||||
union
|
||||
{ uint32_t marker ;
|
||||
char str [5] ;
|
||||
} u ;
|
||||
size_t marker_len ;
|
||||
|
||||
memset (&rchunk, 0, sizeof (rchunk)) ;
|
||||
snprintf (u.str, sizeof (u.str), "%s", marker_str) ;
|
||||
|
||||
marker_len = strlen (marker_str) ;
|
||||
|
||||
rchunk.hash = marker_len > 4 ? hash_of_str (marker_str) : u.marker ;
|
||||
rchunk.mark32 = u.marker ;
|
||||
rchunk.offset = offset ;
|
||||
rchunk.len = len ;
|
||||
|
||||
rchunk.id_size = marker_len > 64 ? 64 : marker_len ;
|
||||
memcpy (rchunk.id, marker_str, rchunk.id_size) ;
|
||||
|
||||
return psf_store_read_chunk (pchk, &rchunk) ;
|
||||
} /* psf_store_read_chunk_str */
|
||||
|
||||
int
|
||||
psf_save_write_chunk (WRITE_CHUNKS * pchk, const SF_CHUNK_INFO * chunk_info)
|
||||
{ union
|
||||
{ uint32_t marker ;
|
||||
char str [5] ;
|
||||
} u ;
|
||||
uint32_t len ;
|
||||
|
||||
if (pchk->count == 0)
|
||||
{ pchk->used = 0 ;
|
||||
pchk->count = 20 ;
|
||||
pchk->chunks = calloc (pchk->count, sizeof (WRITE_CHUNK)) ;
|
||||
}
|
||||
else if (pchk->used >= pchk->count)
|
||||
{ WRITE_CHUNK * old_ptr = pchk->chunks ;
|
||||
int new_count = 3 * (pchk->count + 1) / 2 ;
|
||||
|
||||
pchk->chunks = realloc (old_ptr, new_count * sizeof (WRITE_CHUNK)) ;
|
||||
if (pchk->chunks == NULL)
|
||||
{ pchk->chunks = old_ptr ;
|
||||
return SFE_MALLOC_FAILED ;
|
||||
} ;
|
||||
} ;
|
||||
|
||||
len = chunk_info->datalen ;
|
||||
while (len & 3) len ++ ;
|
||||
|
||||
snprintf (u.str, sizeof (u.str), "%s", chunk_info->id) ;
|
||||
|
||||
pchk->chunks [pchk->used].hash = strlen (chunk_info->id) > 4 ? hash_of_str (chunk_info->id) : u.marker ;
|
||||
pchk->chunks [pchk->used].mark32 = u.marker ;
|
||||
pchk->chunks [pchk->used].len = len ;
|
||||
pchk->chunks [pchk->used].data = psf_memdup (chunk_info->data, chunk_info->datalen) ;
|
||||
|
||||
pchk->used ++ ;
|
||||
|
||||
return SFE_NO_ERROR ;
|
||||
} /* psf_save_write_chunk */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** Copyright (C) 2001-2009 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
** Copyright (C) 2001-2013 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
@@ -47,6 +47,10 @@ static SF_FORMAT_INFO const simple_formats [] =
|
||||
"AU (Sun/Next 8-bit u-law)", "au"
|
||||
},
|
||||
|
||||
{ SF_FORMAT_CAF | SF_FORMAT_ALAC_16,
|
||||
"CAF (Apple 16 bit ALAC)", "caf"
|
||||
},
|
||||
|
||||
{ SF_FORMAT_CAF | SF_FORMAT_PCM_16,
|
||||
"CAF (Apple 16 bit PCM)", "caf"
|
||||
},
|
||||
@@ -115,28 +119,30 @@ static SF_FORMAT_INFO const major_formats [] =
|
||||
{
|
||||
{ SF_FORMAT_AIFF, "AIFF (Apple/SGI)", "aiff" },
|
||||
{ SF_FORMAT_AU, "AU (Sun/NeXT)", "au" },
|
||||
{ SF_FORMAT_AVR, "AVR (Audio Visual Research)", "avr" },
|
||||
{ SF_FORMAT_CAF, "CAF (Apple Core Audio File)", "caf" },
|
||||
{ SF_FORMAT_AVR, "AVR (Audio Visual Research)", "avr" },
|
||||
{ SF_FORMAT_CAF, "CAF (Apple Core Audio File)", "caf" },
|
||||
#if HAVE_EXTERNAL_LIBS
|
||||
{ SF_FORMAT_FLAC, "FLAC (FLAC Lossless Audio Codec)", "flac" },
|
||||
{ SF_FORMAT_FLAC, "FLAC (Free Lossless Audio Codec)", "flac" },
|
||||
#endif
|
||||
{ SF_FORMAT_HTK, "HTK (HMM Tool Kit)", "htk" },
|
||||
{ SF_FORMAT_SVX, "IFF (Amiga IFF/SVX8/SV16)", "iff" },
|
||||
{ SF_FORMAT_MAT4, "MAT4 (GNU Octave 2.0 / Matlab 4.2)", "mat" },
|
||||
{ SF_FORMAT_MAT5, "MAT5 (GNU Octave 2.1 / Matlab 5.0)", "mat" },
|
||||
{ SF_FORMAT_MPC2K, "MPC (Akai MPC 2k)", "mpc" },
|
||||
#if HAVE_EXTERNAL_LIBS
|
||||
{ SF_FORMAT_OGG, "OGG (OGG Container format)", "oga" },
|
||||
{ SF_FORMAT_OGG, "OGG (OGG Container format)", "oga" },
|
||||
#endif
|
||||
{ SF_FORMAT_PAF, "PAF (Ensoniq PARIS)", "paf" },
|
||||
{ SF_FORMAT_PVF, "PVF (Portable Voice Format)", "pvf" },
|
||||
{ SF_FORMAT_RAW, "RAW (header-less)", "raw" },
|
||||
{ SF_FORMAT_RAW, "RAW (header-less)", "raw" },
|
||||
{ SF_FORMAT_RF64, "RF64 (RIFF 64)", "rf64" },
|
||||
{ SF_FORMAT_SD2, "SD2 (Sound Designer II)", "sd2" },
|
||||
{ SF_FORMAT_SDS, "SDS (Midi Sample Dump Standard)", "sds" },
|
||||
{ SF_FORMAT_IRCAM, "SF (Berkeley/IRCAM/CARL)", "sf" },
|
||||
{ SF_FORMAT_VOC, "VOC (Creative Labs)", "voc" },
|
||||
{ SF_FORMAT_W64, "W64 (SoundFoundry WAVE 64)", "w64" },
|
||||
{ SF_FORMAT_WAV, "WAV (Microsoft)", "wav" },
|
||||
{ SF_FORMAT_NIST, "WAV (NIST Sphere)", "wav" },
|
||||
{ SF_FORMAT_NIST, "WAV (NIST Sphere)", "wav" },
|
||||
{ SF_FORMAT_WAVEX, "WAVEX (Microsoft)", "wav" },
|
||||
{ SF_FORMAT_WVE, "WVE (Psion Series 3)", "wve" },
|
||||
{ SF_FORMAT_XI, "XI (FastTracker 2)", "xi" },
|
||||
@@ -198,6 +204,11 @@ static SF_FORMAT_INFO subtype_formats [] =
|
||||
#if HAVE_EXTERNAL_LIBS
|
||||
{ SF_FORMAT_VORBIS, "Vorbis", NULL },
|
||||
#endif
|
||||
|
||||
{ SF_FORMAT_ALAC_16, "16 bit ALAC", NULL },
|
||||
{ SF_FORMAT_ALAC_20, "20 bit ALAC", NULL },
|
||||
{ SF_FORMAT_ALAC_24, "24 bit ALAC", NULL },
|
||||
{ SF_FORMAT_ALAC_32, "32 bit ALAC", NULL },
|
||||
} ; /* subtype_formats */
|
||||
|
||||
int
|
||||
@@ -210,7 +221,9 @@ psf_get_format_subtype (SF_FORMAT_INFO *data)
|
||||
{ int indx ;
|
||||
|
||||
if (data->format < 0 || data->format >= (SIGNED_SIZEOF (subtype_formats) / SIGNED_SIZEOF (SF_FORMAT_INFO)))
|
||||
{ data->format = 0 ;
|
||||
return SFE_BAD_COMMAND_PARAM ;
|
||||
} ;
|
||||
|
||||
indx = data->format ;
|
||||
memcpy (data, &(subtype_formats [indx]), sizeof (SF_FORMAT_INFO)) ;
|
||||
@@ -256,7 +269,8 @@ psf_get_format_info (SF_FORMAT_INFO *data)
|
||||
|
||||
double
|
||||
psf_calc_signal_max (SF_PRIVATE *psf, int normalize)
|
||||
{ sf_count_t position ;
|
||||
{ BUF_UNION ubuf ;
|
||||
sf_count_t position ;
|
||||
double max_val, temp, *data ;
|
||||
int k, len, readcount, save_state ;
|
||||
|
||||
@@ -280,8 +294,9 @@ psf_calc_signal_max (SF_PRIVATE *psf, int normalize)
|
||||
/* Go to start of file. */
|
||||
sf_seek ((SNDFILE*) psf, 0, SEEK_SET) ;
|
||||
|
||||
data = psf->u.dbuf ;
|
||||
len = ARRAY_LEN (psf->u.dbuf) ;
|
||||
data = ubuf.dbuf ;
|
||||
/* Make sure len is an integer multiple of the channel count. */
|
||||
len = ARRAY_LEN (ubuf.dbuf) - (ARRAY_LEN (ubuf.dbuf) % psf->sf.channels) ;
|
||||
|
||||
for (readcount = 1, max_val = 0.0 ; readcount > 0 ; /* nothing */)
|
||||
{ readcount = sf_read_double ((SNDFILE*) psf, data, len) ;
|
||||
@@ -300,7 +315,8 @@ psf_calc_signal_max (SF_PRIVATE *psf, int normalize)
|
||||
|
||||
int
|
||||
psf_calc_max_all_channels (SF_PRIVATE *psf, double *peaks, int normalize)
|
||||
{ sf_count_t position ;
|
||||
{ BUF_UNION ubuf ;
|
||||
sf_count_t position ;
|
||||
double temp, *data ;
|
||||
int k, len, readcount, save_state ;
|
||||
int chan ;
|
||||
@@ -321,9 +337,9 @@ psf_calc_max_all_channels (SF_PRIVATE *psf, double *peaks, int normalize)
|
||||
position = sf_seek ((SNDFILE*) psf, 0, SEEK_CUR) ; /* Get current position in file */
|
||||
sf_seek ((SNDFILE*) psf, 0, SEEK_SET) ; /* Go to start of file. */
|
||||
|
||||
len = ARRAY_LEN (psf->u.dbuf) ;
|
||||
len = ARRAY_LEN (ubuf.dbuf) ;
|
||||
|
||||
data = psf->u.dbuf ;
|
||||
data = ubuf.dbuf ;
|
||||
|
||||
chan = 0 ;
|
||||
readcount = len ;
|
||||
|
||||
+280
-33
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** Copyright (C) 1999-2009 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
** Copyright (C) 1999-2013 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
@@ -20,30 +20,35 @@
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef MSC_VER
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <ctype.h>
|
||||
#include <math.h>
|
||||
#include <time.h>
|
||||
#ifndef _MSC_VER
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
#include "sndfile.h"
|
||||
#include "sfendian.h"
|
||||
#include "common.h"
|
||||
|
||||
/*-----------------------------------------------------------------------------------------------
|
||||
** psf_log_printf allows libsndfile internal functions to print to an internal logbuffer which
|
||||
** psf_log_printf allows libsndfile internal functions to print to an internal parselog which
|
||||
** can later be displayed.
|
||||
** The format specifiers are as for printf but without the field width and other modifiers.
|
||||
** Printing is performed to the logbuffer char array of the SF_PRIVATE struct.
|
||||
** Printing is performed to the parselog char array of the SF_PRIVATE struct.
|
||||
** Printing is done in such a way as to guarantee that the log never overflows the end of the
|
||||
** logbuffer array.
|
||||
** parselog array.
|
||||
*/
|
||||
|
||||
static inline void
|
||||
log_putchar (SF_PRIVATE *psf, char ch)
|
||||
{ if (psf->logindex < SIGNED_SIZEOF (psf->logbuffer) - 1)
|
||||
{ psf->logbuffer [psf->logindex++] = ch ;
|
||||
psf->logbuffer [psf->logindex] = 0 ;
|
||||
{ if (psf->parselog.indx < SIGNED_SIZEOF (psf->parselog.buf) - 1)
|
||||
{ psf->parselog.buf [psf->parselog.indx++] = ch ;
|
||||
psf->parselog.buf [psf->parselog.indx] = 0 ;
|
||||
} ;
|
||||
return ;
|
||||
} /* log_putchar */
|
||||
@@ -757,37 +762,37 @@ psf_binheader_writef (SF_PRIVATE *psf, const char *format, ...)
|
||||
|
||||
#if (CPU_IS_BIG_ENDIAN == 1)
|
||||
#define GET_MARKER(ptr) ( ((ptr) [0] << 24) | ((ptr) [1] << 16) | \
|
||||
((ptr) [2] << 8) | ((ptr) [3]) )
|
||||
((ptr) [2] << 8) | ((ptr) [3]))
|
||||
|
||||
#elif (CPU_IS_LITTLE_ENDIAN == 1)
|
||||
#define GET_MARKER(ptr) ( ((ptr) [0]) | ((ptr) [1] << 8) | \
|
||||
((ptr) [2] << 16) | ((ptr) [3] << 24) )
|
||||
((ptr) [2] << 16) | ((ptr) [3] << 24))
|
||||
|
||||
#else
|
||||
# error "Cannot determine endian-ness of processor."
|
||||
#endif
|
||||
|
||||
#define GET_LE_SHORT(ptr) ( ((ptr) [1] << 8) | ((ptr) [0]) )
|
||||
#define GET_BE_SHORT(ptr) ( ((ptr) [0] << 8) | ((ptr) [1]) )
|
||||
#define GET_LE_SHORT(ptr) (((ptr) [1] << 8) | ((ptr) [0]))
|
||||
#define GET_BE_SHORT(ptr) (((ptr) [0] << 8) | ((ptr) [1]))
|
||||
|
||||
#define GET_LE_3BYTE(ptr) ( ((ptr) [2] << 16) | ((ptr) [1] << 8) | ((ptr) [0]) )
|
||||
#define GET_BE_3BYTE(ptr) ( ((ptr) [0] << 16) | ((ptr) [1] << 8) | ((ptr) [2]) )
|
||||
#define GET_LE_3BYTE(ptr) ( ((ptr) [2] << 16) | ((ptr) [1] << 8) | ((ptr) [0]))
|
||||
#define GET_BE_3BYTE(ptr) ( ((ptr) [0] << 16) | ((ptr) [1] << 8) | ((ptr) [2]))
|
||||
|
||||
#define GET_LE_INT(ptr) ( ((ptr) [3] << 24) | ((ptr) [2] << 16) | \
|
||||
((ptr) [1] << 8) | ((ptr) [0]) )
|
||||
#define GET_LE_INT(ptr) ( ((ptr) [3] << 24) | ((ptr) [2] << 16) | \
|
||||
((ptr) [1] << 8) | ((ptr) [0]))
|
||||
|
||||
#define GET_BE_INT(ptr) ( ((ptr) [0] << 24) | ((ptr) [1] << 16) | \
|
||||
((ptr) [2] << 8) | ((ptr) [3]) )
|
||||
#define GET_BE_INT(ptr) ( ((ptr) [0] << 24) | ((ptr) [1] << 16) | \
|
||||
((ptr) [2] << 8) | ((ptr) [3]))
|
||||
|
||||
#define GET_LE_8BYTE(ptr) ( (((sf_count_t) (ptr) [7]) << 56) | (((sf_count_t) (ptr) [6]) << 48) | \
|
||||
(((sf_count_t) (ptr) [5]) << 40) | (((sf_count_t) (ptr) [4]) << 32) | \
|
||||
(((sf_count_t) (ptr) [3]) << 24) | (((sf_count_t) (ptr) [2]) << 16) | \
|
||||
(((sf_count_t) (ptr) [1]) << 8 ) | ((ptr) [0]))
|
||||
#define GET_LE_8BYTE(ptr) ( (((sf_count_t) (ptr) [7]) << 56) | (((sf_count_t) (ptr) [6]) << 48) | \
|
||||
(((sf_count_t) (ptr) [5]) << 40) | (((sf_count_t) (ptr) [4]) << 32) | \
|
||||
(((sf_count_t) (ptr) [3]) << 24) | (((sf_count_t) (ptr) [2]) << 16) | \
|
||||
(((sf_count_t) (ptr) [1]) << 8) | ((ptr) [0]))
|
||||
|
||||
#define GET_BE_8BYTE(ptr) ( (((sf_count_t) (ptr) [0]) << 56) | (((sf_count_t) (ptr) [1]) << 48) | \
|
||||
(((sf_count_t) (ptr) [2]) << 40) | (((sf_count_t) (ptr) [3]) << 32) | \
|
||||
(((sf_count_t) (ptr) [4]) << 24) | (((sf_count_t) (ptr) [5]) << 16) | \
|
||||
(((sf_count_t) (ptr) [6]) << 8 ) | ((ptr) [7]))
|
||||
#define GET_BE_8BYTE(ptr) ( (((sf_count_t) (ptr) [0]) << 56) | (((sf_count_t) (ptr) [1]) << 48) | \
|
||||
(((sf_count_t) (ptr) [2]) << 40) | (((sf_count_t) (ptr) [3]) << 32) | \
|
||||
(((sf_count_t) (ptr) [4]) << 24) | (((sf_count_t) (ptr) [5]) << 16) | \
|
||||
(((sf_count_t) (ptr) [6]) << 8) | ((ptr) [7]))
|
||||
|
||||
|
||||
|
||||
@@ -1026,7 +1031,7 @@ psf_binheader_readf (SF_PRIVATE *psf, char const *format, ...)
|
||||
strptr = va_arg (argptr, char *) ;
|
||||
size = strlen (strptr) + 1 ;
|
||||
size += (size & 1) ;
|
||||
longdata = H2LE_INT (size) ;
|
||||
longdata = H2LE_32 (size) ;
|
||||
get_int (psf, longdata) ;
|
||||
memcpy (&(psf->header [psf->headindex]), strptr, size) ;
|
||||
psf->headindex += size ;
|
||||
@@ -1035,14 +1040,14 @@ psf_binheader_readf (SF_PRIVATE *psf, char const *format, ...)
|
||||
|
||||
case 'b' :
|
||||
charptr = va_arg (argptr, char*) ;
|
||||
count = va_arg (argptr, int) ;
|
||||
count = va_arg (argptr, size_t) ;
|
||||
if (count > 0)
|
||||
byte_count += header_read (psf, charptr, count) ;
|
||||
break ;
|
||||
|
||||
case 'G' :
|
||||
charptr = va_arg (argptr, char*) ;
|
||||
count = va_arg (argptr, int) ;
|
||||
count = va_arg (argptr, size_t) ;
|
||||
if (count > 0)
|
||||
byte_count += header_gets (psf, charptr, count) ;
|
||||
break ;
|
||||
@@ -1061,14 +1066,14 @@ psf_binheader_readf (SF_PRIVATE *psf, char const *format, ...)
|
||||
|
||||
case 'p' :
|
||||
/* Get the seek position first. */
|
||||
count = va_arg (argptr, int) ;
|
||||
count = va_arg (argptr, size_t) ;
|
||||
header_seek (psf, count, SEEK_SET) ;
|
||||
byte_count = count ;
|
||||
break ;
|
||||
|
||||
case 'j' :
|
||||
/* Get the seek position first. */
|
||||
count = va_arg (argptr, int) ;
|
||||
count = va_arg (argptr, size_t) ;
|
||||
header_seek (psf, count, SEEK_CUR) ;
|
||||
byte_count += count ;
|
||||
break ;
|
||||
@@ -1133,7 +1138,7 @@ psf_hexdump (const void *ptr, int len)
|
||||
printf ("%08X: ", k) ;
|
||||
for (m = 0 ; m < 16 && k + m < len ; m++)
|
||||
{ printf (m == 8 ? " %02X " : "%02X ", data [k + m] & 0xFF) ;
|
||||
ascii [m] = isprint (data [k + m]) ? data [k + m] : '.' ;
|
||||
ascii [m] = psf_isprint (data [k + m]) ? data [k + m] : '.' ;
|
||||
} ;
|
||||
|
||||
if (m <= 8) printf (" ") ;
|
||||
@@ -1151,7 +1156,10 @@ psf_log_SF_INFO (SF_PRIVATE *psf)
|
||||
{ psf_log_printf (psf, "---------------------------------\n") ;
|
||||
|
||||
psf_log_printf (psf, " Sample rate : %d\n", psf->sf.samplerate) ;
|
||||
psf_log_printf (psf, " Frames : %D\n", psf->sf.frames) ;
|
||||
if (psf->sf.frames == SF_COUNT_MAX)
|
||||
psf_log_printf (psf, " Frames : unknown\n") ;
|
||||
else
|
||||
psf_log_printf (psf, " Frames : %D\n", psf->sf.frames) ;
|
||||
psf_log_printf (psf, " Channels : %d\n", psf->sf.channels) ;
|
||||
|
||||
psf_log_printf (psf, " Format : 0x%X\n", psf->sf.format) ;
|
||||
@@ -1208,7 +1216,7 @@ psf_sanitize_string (char * cptr, int len)
|
||||
do
|
||||
{
|
||||
len -- ;
|
||||
cptr [len] = isprint (cptr [len]) ? cptr [len] : '.' ;
|
||||
cptr [len] = psf_isprint (cptr [len]) ? cptr [len] : '.' ;
|
||||
}
|
||||
while (len > 0) ;
|
||||
} /* psf_sanitize_string */
|
||||
@@ -1315,6 +1323,79 @@ psf_rand_int32 (void)
|
||||
return value ;
|
||||
} /* psf_rand_int32 */
|
||||
|
||||
void
|
||||
append_snprintf (char * dest, size_t maxlen, const char * fmt, ...)
|
||||
{ size_t len = strlen (dest) ;
|
||||
|
||||
if (len < maxlen)
|
||||
{ va_list ap ;
|
||||
|
||||
va_start (ap, fmt) ;
|
||||
vsnprintf (dest + len, maxlen - len, fmt, ap) ;
|
||||
va_end (ap) ;
|
||||
} ;
|
||||
|
||||
return ;
|
||||
} /* append_snprintf */
|
||||
|
||||
|
||||
void
|
||||
psf_strlcpy_crlf (char *dest, const char *src, size_t destmax, size_t srcmax)
|
||||
{ /* Must be minus 2 so it can still expand a single trailing '\n' or '\r'. */
|
||||
char * destend = dest + destmax - 2 ;
|
||||
const char * srcend = src + srcmax ;
|
||||
|
||||
while (dest < destend && src < srcend)
|
||||
{ if ((src [0] == '\r' && src [1] == '\n') || (src [0] == '\n' && src [1] == '\r'))
|
||||
{ *dest++ = '\r' ;
|
||||
*dest++ = '\n' ;
|
||||
src += 2 ;
|
||||
continue ;
|
||||
} ;
|
||||
|
||||
if (src [0] == '\r')
|
||||
{ *dest++ = '\r' ;
|
||||
*dest++ = '\n' ;
|
||||
src += 1 ;
|
||||
continue ;
|
||||
} ;
|
||||
|
||||
if (src [0] == '\n')
|
||||
{ *dest++ = '\r' ;
|
||||
*dest++ = '\n' ;
|
||||
src += 1 ;
|
||||
continue ;
|
||||
} ;
|
||||
|
||||
*dest++ = *src++ ;
|
||||
} ;
|
||||
|
||||
/* Make sure dest is terminated. */
|
||||
*dest = 0 ;
|
||||
} /* psf_strlcpy_crlf */
|
||||
|
||||
sf_count_t
|
||||
psf_decode_frame_count (SF_PRIVATE *psf)
|
||||
{ sf_count_t count, readlen, total = 0 ;
|
||||
BUF_UNION ubuf ;
|
||||
|
||||
/* If we're reading from a pipe or the file is too long, just return SF_COUNT_MAX. */
|
||||
if (psf_is_pipe (psf) || psf->datalength > 0x1000000)
|
||||
return SF_COUNT_MAX ;
|
||||
|
||||
psf_fseek (psf, psf->dataoffset, SEEK_SET) ;
|
||||
|
||||
readlen = ARRAY_LEN (ubuf.ibuf) / psf->sf.channels ;
|
||||
readlen *= psf->sf.channels ;
|
||||
|
||||
while ((count = psf->read_int (psf, ubuf.ibuf, readlen)) > 0)
|
||||
total += count ;
|
||||
|
||||
psf_fseek (psf, psf->dataoffset, SEEK_SET) ;
|
||||
|
||||
return total / psf->sf.channels ;
|
||||
} /* psf_decode_frame_count */
|
||||
|
||||
/*==============================================================================
|
||||
*/
|
||||
|
||||
@@ -1413,3 +1494,169 @@ str_of_endianness (int end)
|
||||
/* Zero length string for SF_ENDIAN_FILE. */
|
||||
return "" ;
|
||||
} /* str_of_endianness */
|
||||
|
||||
/*==============================================================================
|
||||
*/
|
||||
|
||||
void
|
||||
psf_f2s_array (const float *src, short *dest, int count, int normalize)
|
||||
{ float normfact ;
|
||||
|
||||
normfact = normalize ? (1.0 * 0x7FFF) : 1.0 ;
|
||||
while (--count >= 0)
|
||||
dest [count] = lrintf (src [count] * normfact) ;
|
||||
|
||||
return ;
|
||||
} /* psf_f2s_array */
|
||||
|
||||
void
|
||||
psf_f2s_clip_array (const float *src, short *dest, int count, int normalize)
|
||||
{ float normfact, scaled_value ;
|
||||
|
||||
normfact = normalize ? (1.0 * 0x8000) : 1.0 ;
|
||||
|
||||
while (--count >= 0)
|
||||
{ scaled_value = src [count] * normfact ;
|
||||
if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFF))
|
||||
{ dest [count] = 0x7FFF ;
|
||||
continue ;
|
||||
} ;
|
||||
if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x1000))
|
||||
{ dest [count] = 0x8000 ;
|
||||
continue ;
|
||||
} ;
|
||||
|
||||
dest [count] = lrintf (scaled_value) ;
|
||||
} ;
|
||||
|
||||
return ;
|
||||
} /* psf_f2s_clip_array */
|
||||
|
||||
void
|
||||
psf_d2s_array (const double *src, short *dest, int count, int normalize)
|
||||
{ double normfact ;
|
||||
|
||||
normfact = normalize ? (1.0 * 0x7FFF) : 1.0 ;
|
||||
while (--count >= 0)
|
||||
dest [count] = lrint (src [count] * normfact) ;
|
||||
|
||||
return ;
|
||||
} /* psf_f2s_array */
|
||||
|
||||
void
|
||||
psf_d2s_clip_array (const double *src, short *dest, int count, int normalize)
|
||||
{ double normfact, scaled_value ;
|
||||
|
||||
normfact = normalize ? (1.0 * 0x8000) : 1.0 ;
|
||||
|
||||
while (--count >= 0)
|
||||
{ scaled_value = src [count] * normfact ;
|
||||
if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFF))
|
||||
{ dest [count] = 0x7FFF ;
|
||||
continue ;
|
||||
} ;
|
||||
if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x1000))
|
||||
{ dest [count] = 0x8000 ;
|
||||
continue ;
|
||||
} ;
|
||||
|
||||
dest [count] = lrint (scaled_value) ;
|
||||
} ;
|
||||
|
||||
return ;
|
||||
} /* psf_d2s_clip_array */
|
||||
|
||||
|
||||
void
|
||||
psf_f2i_array (const float *src, int *dest, int count, int normalize)
|
||||
{ float normfact ;
|
||||
|
||||
normfact = normalize ? (1.0 * 0x7FFFFFFF) : 1.0 ;
|
||||
while (--count >= 0)
|
||||
dest [count] = lrintf (src [count] * normfact) ;
|
||||
|
||||
return ;
|
||||
} /* psf_f2i_array */
|
||||
|
||||
void
|
||||
psf_f2i_clip_array (const float *src, int *dest, int count, int normalize)
|
||||
{ float normfact, scaled_value ;
|
||||
|
||||
normfact = normalize ? (8.0 * 0x10000000) : 1.0 ;
|
||||
|
||||
while (--count >= 0)
|
||||
{ scaled_value = src [count] * normfact ;
|
||||
if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF))
|
||||
{ dest [count] = 0x7FFFFFFF ;
|
||||
continue ;
|
||||
} ;
|
||||
if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000))
|
||||
{ dest [count] = 0x80000000 ;
|
||||
continue ;
|
||||
} ;
|
||||
|
||||
dest [count] = lrintf (scaled_value) ;
|
||||
} ;
|
||||
|
||||
return ;
|
||||
} /* psf_f2i_clip_array */
|
||||
|
||||
void
|
||||
psf_d2i_array (const double *src, int *dest, int count, int normalize)
|
||||
{ double normfact ;
|
||||
|
||||
normfact = normalize ? (1.0 * 0x7FFFFFFF) : 1.0 ;
|
||||
while (--count >= 0)
|
||||
dest [count] = lrint (src [count] * normfact) ;
|
||||
|
||||
return ;
|
||||
} /* psf_f2i_array */
|
||||
|
||||
void
|
||||
psf_d2i_clip_array (const double *src, int *dest, int count, int normalize)
|
||||
{ double normfact, scaled_value ;
|
||||
|
||||
normfact = normalize ? (8.0 * 0x10000000) : 1.0 ;
|
||||
|
||||
while (--count >= 0)
|
||||
{ scaled_value = src [count] * normfact ;
|
||||
if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF))
|
||||
{ dest [count] = 0x7FFFFFFF ;
|
||||
continue ;
|
||||
} ;
|
||||
if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000))
|
||||
{ dest [count] = 0x80000000 ;
|
||||
continue ;
|
||||
} ;
|
||||
|
||||
dest [count] = lrint (scaled_value) ;
|
||||
} ;
|
||||
|
||||
return ;
|
||||
} /* psf_d2i_clip_array */
|
||||
|
||||
FILE *
|
||||
psf_open_tmpfile (char * fname, size_t fnamelen)
|
||||
{ const char * tmpdir ;
|
||||
FILE * file ;
|
||||
|
||||
if (OS_IS_WIN32)
|
||||
tmpdir = getenv ("TEMP") ;
|
||||
else
|
||||
{ tmpdir = getenv ("TMPDIR") ;
|
||||
tmpdir = tmpdir == NULL ? "/tmp" : tmpdir ;
|
||||
} ;
|
||||
|
||||
// if (tmpdir && access (tmpdir, R_OK | W_OK | X_OK) == 0)
|
||||
{ snprintf (fname, fnamelen, "%s/%x%x-alac.tmp", tmpdir, psf_rand_int32 (), psf_rand_int32 ()) ;
|
||||
if ((file = fopen (fname, "wb+")) != NULL)
|
||||
return file ;
|
||||
} ;
|
||||
|
||||
snprintf (fname, fnamelen, "%x%x-alac.tmp", psf_rand_int32 (), psf_rand_int32 ()) ;
|
||||
if ((file = fopen (fname, "wb+")) != NULL)
|
||||
return file ;
|
||||
|
||||
memset (fname, 0, fnamelen) ;
|
||||
return NULL ;
|
||||
} /* psf_open_tmpfile */
|
||||
+309
-103
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** Copyright (C) 1999-2009 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
** Copyright (C) 1999-2013 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
@@ -22,15 +22,16 @@
|
||||
#include "sfconfig.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#if HAVE_STDINT_H
|
||||
#include <stdint.h>
|
||||
#elif HAVE_INTTYPES_H
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
|
||||
#ifndef SNDFILE_H
|
||||
#include "sndfile.h"
|
||||
#elif HAVE_INTTYPES_H
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -39,7 +40,9 @@
|
||||
|
||||
#if (SIZEOF_LONG == 8)
|
||||
# define SF_PLATFORM_S64(x) x##l
|
||||
#elif COMPILER_IS_GCC || __SUNPRO_C
|
||||
#elif (SIZEOF_LONG_LONG == 8)
|
||||
# define SF_PLATFORM_S64(x) x##ll
|
||||
#elif COMPILER_IS_GCC
|
||||
# define SF_PLATFORM_S64(x) x##ll
|
||||
#elif OS_IS_WIN32
|
||||
# define SF_PLATFORM_S64(x) x##I64
|
||||
@@ -67,16 +70,15 @@
|
||||
# define WARN_UNUSED
|
||||
#endif
|
||||
|
||||
#define SF_BUFFER_LEN (8192*2)
|
||||
#define SF_BUFFER_LEN (8192)
|
||||
#define SF_FILENAME_LEN (512)
|
||||
#define SF_SYSERR_LEN (256)
|
||||
#define SF_MAX_STRINGS (32)
|
||||
#define SF_STR_BUFFER_LEN (8192)
|
||||
#define SF_HEADER_LEN (4100 + SF_STR_BUFFER_LEN)
|
||||
#define SF_HEADER_LEN (12292)
|
||||
#define SF_PARSELOG_LEN (2048)
|
||||
|
||||
#define PSF_SEEK_ERROR ((sf_count_t) -1)
|
||||
|
||||
|
||||
#define BITWIDTH2BYTES(x) (((x) + 7) / 8)
|
||||
|
||||
/* For some reason sizeof returns an unsigned value which causes
|
||||
@@ -87,32 +89,40 @@
|
||||
|
||||
#define ARRAY_LEN(x) ((int) (sizeof (x) / sizeof ((x) [0])))
|
||||
|
||||
#define NOT(x) (! (x))
|
||||
|
||||
#if (COMPILER_IS_GCC == 1)
|
||||
#define SF_MAX(x,y) ({ \
|
||||
#define SF_MAX(x, y) ({ \
|
||||
typeof (x) sf_max_x1 = (x) ; \
|
||||
typeof (y) sf_max_y1 = (y) ; \
|
||||
(void) (&sf_max_x1 == &sf_max_y1) ; \
|
||||
sf_max_x1 > sf_max_y1 ? sf_max_x1 : sf_max_y1 ; })
|
||||
|
||||
#define SF_MIN(x,y) ({ \
|
||||
#define SF_MIN(x, y) ({ \
|
||||
typeof (x) sf_min_x2 = (x) ; \
|
||||
typeof (y) sf_min_y2 = (y) ; \
|
||||
(void) (&sf_min_x2 == &sf_min_y2) ; \
|
||||
sf_min_x2 < sf_min_y2 ? sf_min_x2 : sf_min_y2 ; })
|
||||
#else
|
||||
#define SF_MAX(a,b) ((a) > (b) ? (a) : (b))
|
||||
#define SF_MIN(a,b) ((a) < (b) ? (a) : (b))
|
||||
#define SF_MAX(a, b) ((a) > (b) ? (a) : (b))
|
||||
#define SF_MIN(a, b) ((a) < (b) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
|
||||
#define COMPILE_TIME_ASSERT(e) (sizeof (struct { int : - !! (e) ; }))
|
||||
|
||||
|
||||
#define SF_MAX_CHANNELS 256
|
||||
|
||||
|
||||
/*
|
||||
* Macros for spliting the format file of SF_INFI into contrainer type,
|
||||
* Macros for spliting the format file of SF_INFO into container type,
|
||||
** codec type and endian-ness.
|
||||
*/
|
||||
#define SF_CONTAINER(x) ((x) & SF_FORMAT_TYPEMASK)
|
||||
#define SF_CODEC(x) ((x) & SF_FORMAT_SUBMASK)
|
||||
#define SF_ENDIAN(x) ((x) & SF_FORMAT_ENDMASK)
|
||||
|
||||
|
||||
enum
|
||||
{ /* PEAK chunk location. */
|
||||
SF_PEAK_START = 42,
|
||||
@@ -143,6 +153,8 @@ enum
|
||||
|
||||
enum
|
||||
{ /* Work in progress. */
|
||||
SF_FORMAT_SPEEX = 0x5000000,
|
||||
SF_FORMAT_OGGFLAC = 0x5000001,
|
||||
|
||||
/* Formats supported read only. */
|
||||
SF_FORMAT_TXW = 0x4030000, /* Yamaha TX16 sampler file */
|
||||
@@ -162,6 +174,22 @@ enum
|
||||
SF_FORMAT_PCM_N = 0x1030
|
||||
} ;
|
||||
|
||||
/*---------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{ unsigned kuki_offset ;
|
||||
unsigned pakt_offset ;
|
||||
|
||||
unsigned bits_per_sample ;
|
||||
unsigned frames_per_packet ;
|
||||
|
||||
int64_t packets ;
|
||||
int64_t valid_frames ;
|
||||
int32_t priming_frames ;
|
||||
int32_t remainder_frames ;
|
||||
} ALAC_DECODER_INFO ;
|
||||
|
||||
/*---------------------------------------------------------------------------------------
|
||||
** PEAK_CHUNK - This chunk type is common to both AIFF and WAVE files although their
|
||||
** endian encodings are different.
|
||||
@@ -183,19 +211,8 @@ typedef struct
|
||||
/* CAF */
|
||||
unsigned int edit_number ;
|
||||
|
||||
#if HAVE_FLEXIBLE_ARRAY
|
||||
/* the per channel peak info */
|
||||
PEAK_POS peaks [] ;
|
||||
#else
|
||||
/*
|
||||
** This is not ISO compliant C. It works on some compilers which
|
||||
** don't support the ISO standard flexible struct array which is
|
||||
** used above. If your compiler doesn't like this I suggest you find
|
||||
** youself a 1999 ISO C standards compilant compiler. GCC-3.X is
|
||||
** highly recommended.
|
||||
*/
|
||||
PEAK_POS peaks [0] ;
|
||||
#endif
|
||||
} PEAK_INFO ;
|
||||
|
||||
static inline PEAK_INFO *
|
||||
@@ -206,94 +223,180 @@ peak_info_calloc (int channels)
|
||||
typedef struct
|
||||
{ int type ;
|
||||
int flags ;
|
||||
char *str ;
|
||||
size_t offset ;
|
||||
} STR_DATA ;
|
||||
|
||||
typedef struct
|
||||
{ int64_t hash ;
|
||||
char id [64] ;
|
||||
unsigned id_size ;
|
||||
uint32_t mark32 ;
|
||||
sf_count_t offset ;
|
||||
uint32_t len ;
|
||||
} READ_CHUNK ;
|
||||
|
||||
typedef struct
|
||||
{ int64_t hash ;
|
||||
uint32_t mark32 ;
|
||||
uint32_t len ;
|
||||
void *data ;
|
||||
} WRITE_CHUNK ;
|
||||
|
||||
typedef struct
|
||||
{ uint32_t count ;
|
||||
uint32_t used ;
|
||||
READ_CHUNK *chunks ;
|
||||
} READ_CHUNKS ;
|
||||
typedef struct
|
||||
{ uint32_t count ;
|
||||
uint32_t used ;
|
||||
WRITE_CHUNK *chunks ;
|
||||
} WRITE_CHUNKS ;
|
||||
|
||||
struct SF_CHUNK_ITERATOR
|
||||
{ uint32_t current ;
|
||||
int64_t hash ;
|
||||
char id [64] ;
|
||||
unsigned id_size ;
|
||||
SNDFILE *sndfile ;
|
||||
} ;
|
||||
|
||||
static inline size_t
|
||||
make_size_t (int x)
|
||||
{ return (size_t) x ;
|
||||
} /* size_t_of_int */
|
||||
|
||||
typedef SF_BROADCAST_INFO_VAR (16 * 1024) SF_BROADCAST_INFO_16K ;
|
||||
|
||||
typedef SF_CART_INFO_VAR (16 * 1024) SF_CART_INFO_16K ;
|
||||
|
||||
#if SIZEOF_WCHAR_T == 2
|
||||
typedef wchar_t sfwchar_t ;
|
||||
#else
|
||||
typedef int16_t sfwchar_t ;
|
||||
#endif
|
||||
|
||||
|
||||
static inline void *
|
||||
psf_memdup (const void *src, size_t n)
|
||||
{ void * mem = calloc (1, n & 3 ? n + 4 - (n & 3) : n) ;
|
||||
return memcpy (mem, src, n) ;
|
||||
} /* psf_memdup */
|
||||
|
||||
/*
|
||||
** This version of isprint specifically ignores any locale info. Its used for
|
||||
** determining which characters can be printed in things like hexdumps.
|
||||
*/
|
||||
static inline int
|
||||
psf_isprint (int ch)
|
||||
{ return (ch >= ' ' && ch <= '~') ;
|
||||
} /* psf_isprint */
|
||||
|
||||
/*=======================================================================================
|
||||
** SF_PRIVATE stuct - a pointer to this struct is passed back to the caller of the
|
||||
** sf_open_XXXX functions. The caller however has no knowledge of the struct's
|
||||
** contents.
|
||||
*/
|
||||
|
||||
|
||||
typedef struct
|
||||
{ int size ;
|
||||
SF_BROADCAST_INFO binfo ;
|
||||
} SF_BROADCAST_VAR ;
|
||||
|
||||
typedef struct sf_private_tag
|
||||
{
|
||||
/* Canary in a coal mine. */
|
||||
char canary [64] ;
|
||||
|
||||
/* Force the compiler to double align the start of buffer. */
|
||||
union
|
||||
{ double dbuf [SF_BUFFER_LEN / sizeof (double)] ;
|
||||
#if (defined (SIZEOF_INT64_T) && (SIZEOF_INT64_T == 8))
|
||||
int64_t lbuf [SF_BUFFER_LEN / sizeof (int64_t)] ;
|
||||
#else
|
||||
long lbuf [SF_BUFFER_LEN / sizeof (double)] ;
|
||||
#endif
|
||||
float fbuf [SF_BUFFER_LEN / sizeof (float)] ;
|
||||
int ibuf [SF_BUFFER_LEN / sizeof (int)] ;
|
||||
short sbuf [SF_BUFFER_LEN / sizeof (short)] ;
|
||||
char cbuf [SF_BUFFER_LEN / sizeof (char)] ;
|
||||
signed char scbuf [SF_BUFFER_LEN / sizeof (signed char)] ;
|
||||
unsigned char ucbuf [SF_BUFFER_LEN / sizeof (signed char)] ;
|
||||
} u ;
|
||||
{ char c [SF_FILENAME_LEN] ;
|
||||
sfwchar_t wc [SF_FILENAME_LEN] ;
|
||||
} path ;
|
||||
|
||||
char filepath [SF_FILENAME_LEN] ;
|
||||
char rsrcpath [SF_FILENAME_LEN] ;
|
||||
char directory [SF_FILENAME_LEN] ;
|
||||
char filename [SF_FILENAME_LEN / 4] ;
|
||||
union
|
||||
{ char c [SF_FILENAME_LEN] ;
|
||||
sfwchar_t wc [SF_FILENAME_LEN] ;
|
||||
} dir ;
|
||||
|
||||
char syserr [SF_SYSERR_LEN] ;
|
||||
|
||||
/* logbuffer and logindex should only be changed within the logging functions
|
||||
** of common.c
|
||||
*/
|
||||
char logbuffer [SF_BUFFER_LEN] ;
|
||||
unsigned char header [SF_HEADER_LEN] ; /* Must be unsigned */
|
||||
int rwf_endian ; /* Header endian-ness flag. */
|
||||
|
||||
/* Storage and housekeeping data for adding/reading strings from
|
||||
** sound files.
|
||||
*/
|
||||
STR_DATA strings [SF_MAX_STRINGS] ;
|
||||
char str_storage [SF_STR_BUFFER_LEN] ;
|
||||
char *str_end ;
|
||||
int str_flags ;
|
||||
|
||||
/* Guard value. If this changes the buffers above have overflowed. */
|
||||
int Magick ;
|
||||
|
||||
unsigned unique_id ;
|
||||
|
||||
/* Index variables for maintaining logbuffer and header above. */
|
||||
int logindex ;
|
||||
int headindex, headend ;
|
||||
int has_text ;
|
||||
int do_not_close_descriptor ;
|
||||
union
|
||||
{ char c [SF_FILENAME_LEN / 4] ;
|
||||
sfwchar_t wc [SF_FILENAME_LEN / 4] ;
|
||||
} name ;
|
||||
|
||||
#if USE_WINDOWS_API
|
||||
/*
|
||||
** These fields can only be used in src/file_io.c.
|
||||
** They are basically the same as a windows file HANDLE.
|
||||
*/
|
||||
void *hfile, *hrsrc, *hsaved ;
|
||||
void *handle, *hsaved ;
|
||||
|
||||
int use_wchar ;
|
||||
#else
|
||||
/* These fields can only be used in src/file_io.c. */
|
||||
int filedes, rsrcdes, savedes ;
|
||||
int filedes, savedes ;
|
||||
#endif
|
||||
|
||||
int do_not_close_descriptor ;
|
||||
int mode ; /* Open mode : SFM_READ, SFM_WRITE or SFM_RDWR. */
|
||||
} PSF_FILE ;
|
||||
|
||||
|
||||
|
||||
typedef union
|
||||
{ double dbuf [SF_BUFFER_LEN / sizeof (double)] ;
|
||||
#if (defined (SIZEOF_INT64_T) && (SIZEOF_INT64_T == 8))
|
||||
int64_t lbuf [SF_BUFFER_LEN / sizeof (int64_t)] ;
|
||||
#else
|
||||
long lbuf [SF_BUFFER_LEN / sizeof (double)] ;
|
||||
#endif
|
||||
float fbuf [SF_BUFFER_LEN / sizeof (float)] ;
|
||||
int ibuf [SF_BUFFER_LEN / sizeof (int)] ;
|
||||
short sbuf [SF_BUFFER_LEN / sizeof (short)] ;
|
||||
char cbuf [SF_BUFFER_LEN / sizeof (char)] ;
|
||||
signed char scbuf [SF_BUFFER_LEN / sizeof (signed char)] ;
|
||||
unsigned char ucbuf [SF_BUFFER_LEN / sizeof (signed char)] ;
|
||||
} BUF_UNION ;
|
||||
|
||||
|
||||
|
||||
typedef struct sf_private_tag
|
||||
{
|
||||
/* Canary in a coal mine. */
|
||||
union
|
||||
{ /* Place a double here to encourage double alignment. */
|
||||
double d [2] ;
|
||||
char c [16] ;
|
||||
} canary ;
|
||||
|
||||
PSF_FILE file, rsrc ;
|
||||
|
||||
char syserr [SF_SYSERR_LEN] ;
|
||||
|
||||
/* parselog and indx should only be changed within the logging functions
|
||||
** of common.c
|
||||
*/
|
||||
struct
|
||||
{ char buf [SF_PARSELOG_LEN] ;
|
||||
int indx ;
|
||||
} parselog ;
|
||||
|
||||
unsigned char header [SF_HEADER_LEN] ; /* Must be unsigned */
|
||||
int rwf_endian ; /* Header endian-ness flag. */
|
||||
|
||||
/* Storage and housekeeping data for adding/reading strings from
|
||||
** sound files.
|
||||
*/
|
||||
struct
|
||||
{ STR_DATA data [SF_MAX_STRINGS] ;
|
||||
char *storage ;
|
||||
size_t storage_len ;
|
||||
size_t storage_used ;
|
||||
uint32_t flags ;
|
||||
} strings ;
|
||||
|
||||
/* Guard value. If this changes the buffers above have overflowed. */
|
||||
int Magick ;
|
||||
|
||||
unsigned unique_id ;
|
||||
|
||||
/* Index variables for maintaining parselog and header above. */
|
||||
int headindex, headend ;
|
||||
int has_text ;
|
||||
|
||||
int error ;
|
||||
|
||||
int mode ; /* Open mode : SFM_READ, SFM_WRITE or SFM_RDWR. */
|
||||
int endian ; /* File endianness : SF_ENDIAN_LITTLE or SF_ENDIAN_BIG. */
|
||||
int data_endswap ; /* Need to endswap data? */
|
||||
|
||||
@@ -323,7 +426,10 @@ typedef struct sf_private_tag
|
||||
SF_INSTRUMENT *instrument ;
|
||||
|
||||
/* Broadcast (EBU) Info */
|
||||
SF_BROADCAST_VAR *broadcast_var ;
|
||||
SF_BROADCAST_INFO_16K *broadcast_16k ;
|
||||
|
||||
/* Cart (AES46) Info */
|
||||
SF_CART_INFO_16K *cart_16k ;
|
||||
|
||||
/* Channel map data (if present) : an array of ints. */
|
||||
int *channel_map ;
|
||||
@@ -379,6 +485,7 @@ typedef struct sf_private_tag
|
||||
sf_count_t (*seek) (struct sf_private_tag*, int mode, sf_count_t samples_from_start) ;
|
||||
int (*write_header) (struct sf_private_tag*, int calc_length) ;
|
||||
int (*command) (struct sf_private_tag*, int command, void *data, int datasize) ;
|
||||
int (*byterate) (struct sf_private_tag*) ;
|
||||
|
||||
/*
|
||||
** Separate close functions for the codec and the container.
|
||||
@@ -393,6 +500,17 @@ typedef struct sf_private_tag
|
||||
int virtual_io ;
|
||||
SF_VIRTUAL_IO vio ;
|
||||
void *vio_user_data ;
|
||||
|
||||
/* Chunk get/set. */
|
||||
SF_CHUNK_ITERATOR *iterator ;
|
||||
|
||||
READ_CHUNKS rchunks ;
|
||||
WRITE_CHUNKS wchunks ;
|
||||
|
||||
int (*set_chunk) (struct sf_private_tag*, const SF_CHUNK_INFO * chunk_info) ;
|
||||
SF_CHUNK_ITERATOR * (*next_chunk_iterator) (struct sf_private_tag*, SF_CHUNK_ITERATOR * iterator) ;
|
||||
int (*get_chunk_size) (struct sf_private_tag*, const SF_CHUNK_ITERATOR * iterator, SF_CHUNK_INFO * chunk_info) ;
|
||||
int (*get_chunk_data) (struct sf_private_tag*, const SF_CHUNK_ITERATOR * iterator, SF_CHUNK_INFO * chunk_info) ;
|
||||
} SF_PRIVATE ;
|
||||
|
||||
|
||||
@@ -415,6 +533,7 @@ enum
|
||||
SFE_BAD_FILE_PTR,
|
||||
SFE_BAD_INT_PTR,
|
||||
SFE_BAD_STAT_SIZE,
|
||||
SFE_NO_TEMP_DIR,
|
||||
SFE_MALLOC_FAILED,
|
||||
SFE_UNIMPLEMENTED,
|
||||
SFE_BAD_READ_ALIGN,
|
||||
@@ -453,6 +572,9 @@ enum
|
||||
SFE_RDWR_BAD_HEADER,
|
||||
SFE_CMD_HAS_DATA,
|
||||
SFE_BAD_BROADCAST_INFO_SIZE,
|
||||
SFE_BAD_BROADCAST_INFO_TOO_BIG,
|
||||
SFE_BAD_CART_INFO_SIZE,
|
||||
SFE_BAD_CART_INFO_TOO_BIG,
|
||||
|
||||
SFE_STR_NO_SUPPORT,
|
||||
SFE_STR_NOT_WRITE,
|
||||
@@ -506,6 +628,7 @@ enum
|
||||
SFE_PAF_VERSION,
|
||||
SFE_PAF_UNKNOWN_FORMAT,
|
||||
SFE_PAF_SHORT_HEADER,
|
||||
SFE_PAF_BAD_CHANNELS,
|
||||
|
||||
SFE_SVX_NO_FORM,
|
||||
SFE_SVX_NO_BODY,
|
||||
@@ -584,6 +707,13 @@ enum
|
||||
SFE_VORBIS_ENCODER_BUG,
|
||||
|
||||
SFE_RF64_NOT_RF64,
|
||||
SFE_BAD_CHUNK_PTR,
|
||||
SFE_UNKNOWN_CHUNK,
|
||||
SFE_BAD_CHUNK_FORMAT,
|
||||
SFE_BAD_CHUNK_MARKER,
|
||||
SFE_BAD_CHUNK_DATA_PTR,
|
||||
|
||||
SFE_ALAC_FAIL_TMPFILE,
|
||||
|
||||
SFE_MAX_ERROR /* This must be last in list. */
|
||||
} ;
|
||||
@@ -595,13 +725,13 @@ int u_bitwidth_to_subformat (int bits) ;
|
||||
/* Functions for reading and writing floats and doubles on processors
|
||||
** with non-IEEE floats/doubles.
|
||||
*/
|
||||
float float32_be_read (unsigned char *cptr) ;
|
||||
float float32_le_read (unsigned char *cptr) ;
|
||||
float float32_be_read (const unsigned char *cptr) ;
|
||||
float float32_le_read (const unsigned char *cptr) ;
|
||||
void float32_be_write (float in, unsigned char *out) ;
|
||||
void float32_le_write (float in, unsigned char *out) ;
|
||||
|
||||
double double64_be_read (unsigned char *cptr) ;
|
||||
double double64_le_read (unsigned char *cptr) ;
|
||||
double double64_be_read (const unsigned char *cptr) ;
|
||||
double double64_le_read (const unsigned char *cptr) ;
|
||||
void double64_be_write (double in, unsigned char *out) ;
|
||||
void double64_le_write (double in, unsigned char *out) ;
|
||||
|
||||
@@ -612,6 +742,11 @@ void psf_log_SF_INFO (SF_PRIVATE *psf) ;
|
||||
|
||||
int32_t psf_rand_int32 (void) ;
|
||||
|
||||
void append_snprintf (char * dest, size_t maxlen, const char * fmt, ...) ;
|
||||
void psf_strlcpy_crlf (char *dest, const char *src, size_t destmax, size_t srcmax) ;
|
||||
|
||||
sf_count_t psf_decode_frame_count (SF_PRIVATE *psf) ;
|
||||
|
||||
/* Functions used when writing file headers. */
|
||||
|
||||
int psf_binheader_writef (SF_PRIVATE *psf, const char *format, ...) ;
|
||||
@@ -665,13 +800,15 @@ int macos_guess_file_type (SF_PRIVATE *psf, const char *filename) ;
|
||||
** some 32 bit OSes. Implementation in file_io.c.
|
||||
*/
|
||||
|
||||
int psf_fopen (SF_PRIVATE *psf, const char *pathname, int flags) ;
|
||||
int psf_set_stdio (SF_PRIVATE *psf, int mode) ;
|
||||
int psf_fopen (SF_PRIVATE *psf) ;
|
||||
int psf_set_stdio (SF_PRIVATE *psf) ;
|
||||
int psf_file_valid (SF_PRIVATE *psf) ;
|
||||
void psf_set_file (SF_PRIVATE *psf, int fd) ;
|
||||
void psf_init_files (SF_PRIVATE *psf) ;
|
||||
void psf_use_rsrc (SF_PRIVATE *psf, int on_off) ;
|
||||
|
||||
SNDFILE * psf_open_file (SF_PRIVATE *psf, SF_INFO *sfinfo) ;
|
||||
|
||||
sf_count_t psf_fseek (SF_PRIVATE *psf, sf_count_t offset, int whence) ;
|
||||
sf_count_t psf_fread (void *ptr, sf_count_t bytes, sf_count_t count, SF_PRIVATE *psf) ;
|
||||
sf_count_t psf_fwrite (const void *ptr, sf_count_t bytes, sf_count_t count, SF_PRIVATE *psf) ;
|
||||
@@ -687,7 +824,7 @@ int psf_ftruncate (SF_PRIVATE *psf, sf_count_t len) ;
|
||||
int psf_fclose (SF_PRIVATE *psf) ;
|
||||
|
||||
/* Open and close the resource fork of a file. */
|
||||
int psf_open_rsrc (SF_PRIVATE *psf, int mode) ;
|
||||
int psf_open_rsrc (SF_PRIVATE *psf) ;
|
||||
int psf_close_rsrc (SF_PRIVATE *psf) ;
|
||||
|
||||
/*
|
||||
@@ -722,10 +859,16 @@ int caf_open (SF_PRIVATE *psf) ;
|
||||
int mpc2k_open (SF_PRIVATE *psf) ;
|
||||
int rf64_open (SF_PRIVATE *psf) ;
|
||||
|
||||
int ogg_vorbis_open (SF_PRIVATE *psf) ;
|
||||
int ogg_speex_open (SF_PRIVATE *psf) ;
|
||||
int ogg_pcm_open (SF_PRIVATE *psf) ;
|
||||
int ogg_opus_open (SF_PRIVATE *psf) ;
|
||||
int ogg_open (SF_PRIVATE *psf) ;
|
||||
|
||||
|
||||
/* In progress. Do not currently work. */
|
||||
|
||||
int mpeg_open (SF_PRIVATE *psf) ;
|
||||
int ogg_open (SF_PRIVATE *psf) ;
|
||||
int rx2_open (SF_PRIVATE *psf) ;
|
||||
int txw_open (SF_PRIVATE *psf) ;
|
||||
int wve_open (SF_PRIVATE *psf) ;
|
||||
@@ -747,6 +890,7 @@ int gsm610_init (SF_PRIVATE *psf) ;
|
||||
int vox_adpcm_init (SF_PRIVATE *psf) ;
|
||||
int flac_init (SF_PRIVATE *psf) ;
|
||||
int g72x_init (SF_PRIVATE * psf) ;
|
||||
int alac_init (SF_PRIVATE *psf, const ALAC_DECODER_INFO * info) ;
|
||||
|
||||
int dither_init (SF_PRIVATE *psf, int mode) ;
|
||||
|
||||
@@ -761,18 +905,51 @@ int interleave_init (SF_PRIVATE *psf) ;
|
||||
** Chunk logging functions.
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{ struct
|
||||
{ int chunk ;
|
||||
sf_count_t offset ;
|
||||
sf_count_t len ;
|
||||
} l [100] ;
|
||||
SF_CHUNK_ITERATOR * psf_get_chunk_iterator (SF_PRIVATE * psf, const char * marker_str) ;
|
||||
SF_CHUNK_ITERATOR * psf_next_chunk_iterator (const READ_CHUNKS * pchk , SF_CHUNK_ITERATOR *iterator) ;
|
||||
int psf_store_read_chunk_u32 (READ_CHUNKS * pchk, uint32_t marker, sf_count_t offset, uint32_t len) ;
|
||||
int psf_store_read_chunk_str (READ_CHUNKS * pchk, const char * marker, sf_count_t offset, uint32_t len) ;
|
||||
int psf_save_write_chunk (WRITE_CHUNKS * pchk, const SF_CHUNK_INFO * chunk_info) ;
|
||||
int psf_find_read_chunk_str (const READ_CHUNKS * pchk, const char * marker) ;
|
||||
int psf_find_read_chunk_m32 (const READ_CHUNKS * pchk, uint32_t marker) ;
|
||||
int psf_find_read_chunk_iterator (const READ_CHUNKS * pchk, const SF_CHUNK_ITERATOR * marker) ;
|
||||
|
||||
int count ;
|
||||
} PRIV_CHUNK4 ;
|
||||
int psf_find_write_chunk (WRITE_CHUNKS * pchk, const char * marker) ;
|
||||
|
||||
void pchk4_store (PRIV_CHUNK4 * pchk, int marker, sf_count_t offset, sf_count_t len) ;
|
||||
int pchk4_find (PRIV_CHUNK4 * pchk, int marker) ;
|
||||
static inline int
|
||||
fourcc_to_marker (const SF_CHUNK_INFO * chunk_info)
|
||||
{ const unsigned char * cptr ;
|
||||
|
||||
if (chunk_info->id_size != 4)
|
||||
return 0 ;
|
||||
|
||||
cptr = (const unsigned char *) chunk_info->id ;
|
||||
return (cptr [3] << 24) + (cptr [2] << 16) + (cptr [1] << 8) + cptr [0] ;
|
||||
} /* fourcc_to_marker */
|
||||
|
||||
/*------------------------------------------------------------------------------------
|
||||
** Functions that work like OpenBSD's strlcpy/strlcat to replace strncpy/strncat.
|
||||
**
|
||||
** See : http://www.gratisoft.us/todd/papers/strlcpy.html
|
||||
**
|
||||
** These functions are available on *BSD, but are not avaialble everywhere so we
|
||||
** implement them here.
|
||||
**
|
||||
** The argument order has been changed to that of strncpy/strncat to cause
|
||||
** compiler errors if code is carelessly converted from one to the other.
|
||||
*/
|
||||
|
||||
static inline void
|
||||
psf_strlcat (char *dest, size_t n, const char *src)
|
||||
{ strncat (dest, src, n - strlen (dest) - 1) ;
|
||||
dest [n - 1] = 0 ;
|
||||
} /* psf_strlcat */
|
||||
|
||||
static inline void
|
||||
psf_strlcpy (char *dest, size_t n, const char *src)
|
||||
{ strncpy (dest, src, n - 1) ;
|
||||
dest [n - 1] = 0 ;
|
||||
} /* psf_strlcpy */
|
||||
|
||||
/*------------------------------------------------------------------------------------
|
||||
** Other helper functions.
|
||||
@@ -787,18 +964,26 @@ void psf_sanitize_string (char * cptr, int len) ;
|
||||
/* Generate the current date as a string. */
|
||||
void psf_get_date_str (char *str, int maxlen) ;
|
||||
|
||||
SF_BROADCAST_VAR* broadcast_var_alloc (size_t datasize) ;
|
||||
SF_BROADCAST_INFO_16K * broadcast_var_alloc (void) ;
|
||||
int broadcast_var_set (SF_PRIVATE *psf, const SF_BROADCAST_INFO * data, size_t datasize) ;
|
||||
int broadcast_var_get (SF_PRIVATE *psf, SF_BROADCAST_INFO * data, size_t datasize) ;
|
||||
|
||||
|
||||
SF_CART_INFO_16K * cart_var_alloc (void) ;
|
||||
int cart_var_set (SF_PRIVATE *psf, const SF_CART_INFO * date, size_t datasize) ;
|
||||
int cart_var_get (SF_PRIVATE *psf, SF_CART_INFO * data, size_t datasize) ;
|
||||
|
||||
typedef struct
|
||||
{ int channels ;
|
||||
int endianness ;
|
||||
} AUDIO_DETECT ;
|
||||
|
||||
int audio_detect (SF_PRIVATE * psf, AUDIO_DETECT *ad, const unsigned char * data, int datalen) ;
|
||||
int id3_skip (SF_PRIVATE * psf) ;
|
||||
|
||||
void alac_get_desc_chunk_items (int subformat, uint32_t *fmt_flags, uint32_t *frames_per_packet) ;
|
||||
|
||||
FILE * psf_open_tmpfile (char * fname, size_t fnamelen) ;
|
||||
|
||||
/*------------------------------------------------------------------------------------
|
||||
** Helper/debug functions.
|
||||
@@ -834,5 +1019,26 @@ int sf_dither_float (const SF_DITHER_INFO *dither, const float *in, float *out,
|
||||
int sf_dither_double (const SF_DITHER_INFO *dither, const double *in, double *out, int count) ;
|
||||
#endif
|
||||
|
||||
/*------------------------------------------------------------------------------------
|
||||
** Data conversion functions.
|
||||
*/
|
||||
|
||||
static inline short
|
||||
psf_short_of_int (int x)
|
||||
{ return (x >> 16) ;
|
||||
}
|
||||
|
||||
void psf_f2s_array (const float *src, short *dest, int count, int normalize) ;
|
||||
void psf_f2s_clip_array (const float *src, short *dest, int count, int normalize) ;
|
||||
|
||||
void psf_d2s_array (const double *src, short *dest, int count, int normalize) ;
|
||||
void psf_d2s_clip_array (const double *src, short *dest, int count, int normalize) ;
|
||||
|
||||
void psf_f2i_array (const float *src, int *dest, int count, int normalize) ;
|
||||
void psf_f2i_clip_array (const float *src, int *dest, int count, int normalize) ;
|
||||
|
||||
void psf_d2i_array (const double *src, int *dest, int count, int normalize) ;
|
||||
void psf_d2i_clip_array (const double *src, int *dest, int count, int normalize) ;
|
||||
|
||||
#endif /* SNDFILE_COMMON_H */
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
# Copyright (C) 2003-2007 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
# Copyright (C) 2003-2012 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
#
|
||||
# All rights reserved.
|
||||
#
|
||||
@@ -39,89 +39,107 @@ import re, sys
|
||||
# the ordinal values in the second column.
|
||||
|
||||
ALL_SYMBOLS = (
|
||||
( "sf_command", 1 ),
|
||||
( "sf_open", 2 ),
|
||||
( "sf_close", 3 ),
|
||||
( "sf_seek", 4 ),
|
||||
( "sf_error", 7 ),
|
||||
( "sf_perror", 8 ),
|
||||
( "sf_error_str", 9 ),
|
||||
( "sf_error_number", 10 ),
|
||||
( "sf_format_check", 11 ),
|
||||
( "sf_read_raw", 16 ),
|
||||
( "sf_readf_short", 17 ),
|
||||
( "sf_readf_int", 18 ),
|
||||
( "sf_readf_float", 19 ),
|
||||
( "sf_readf_double", 20 ),
|
||||
( "sf_read_short", 21 ),
|
||||
( "sf_read_int", 22 ),
|
||||
( "sf_read_float", 23 ),
|
||||
( "sf_read_double", 24 ),
|
||||
( "sf_write_raw", 32 ),
|
||||
( "sf_writef_short", 33 ),
|
||||
( "sf_writef_int", 34 ),
|
||||
( "sf_writef_float", 35 ),
|
||||
( "sf_writef_double", 36 ),
|
||||
( "sf_write_short", 37 ),
|
||||
( "sf_write_int", 38 ),
|
||||
( "sf_write_float", 39 ),
|
||||
( "sf_write_double", 40 ),
|
||||
( "sf_strerror", 50 ),
|
||||
( "sf_get_string", 60 ),
|
||||
( "sf_set_string", 61 ),
|
||||
( "sf_open_fd", 70 ),
|
||||
( "sf_open_virtual", 80 ),
|
||||
( "sf_write_sync", 90 )
|
||||
( "sf_command", 1 ),
|
||||
( "sf_open", 2 ),
|
||||
( "sf_close", 3 ),
|
||||
( "sf_seek", 4 ),
|
||||
( "sf_error", 7 ),
|
||||
( "sf_perror", 8 ),
|
||||
( "sf_error_str", 9 ),
|
||||
( "sf_error_number", 10 ),
|
||||
( "sf_format_check", 11 ),
|
||||
( "sf_read_raw", 16 ),
|
||||
( "sf_readf_short", 17 ),
|
||||
( "sf_readf_int", 18 ),
|
||||
( "sf_readf_float", 19 ),
|
||||
( "sf_readf_double", 20 ),
|
||||
( "sf_read_short", 21 ),
|
||||
( "sf_read_int", 22 ),
|
||||
( "sf_read_float", 23 ),
|
||||
( "sf_read_double", 24 ),
|
||||
( "sf_write_raw", 32 ),
|
||||
( "sf_writef_short", 33 ),
|
||||
( "sf_writef_int", 34 ),
|
||||
( "sf_writef_float", 35 ),
|
||||
( "sf_writef_double", 36 ),
|
||||
( "sf_write_short", 37 ),
|
||||
( "sf_write_int", 38 ),
|
||||
( "sf_write_float", 39 ),
|
||||
( "sf_write_double", 40 ),
|
||||
( "sf_strerror", 50 ),
|
||||
( "sf_get_string", 60 ),
|
||||
( "sf_set_string", 61 ),
|
||||
( "sf_version_string", 68 ),
|
||||
( "sf_open_fd", 70 ),
|
||||
( "sf_wchar_open", 71 ),
|
||||
( "sf_open_virtual", 80 ),
|
||||
( "sf_write_sync", 90 ),
|
||||
( "sf_set_chunk", 100 ),
|
||||
( "sf_get_chunk_size", 101 ),
|
||||
( "sf_get_chunk_data", 102 ),
|
||||
( "sf_get_chunk_iterator", 103 ),
|
||||
( "sf_next_chunk_iterator", 104 ),
|
||||
( "sf_current_byterate", 110 )
|
||||
)
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
def linux_symbols (progname, version):
|
||||
print "# Auto-generated by %s\n" %progname
|
||||
print "libsndfile.so.%s" % version
|
||||
print "{"
|
||||
print " global:"
|
||||
print ("# Auto-generated by %s\n" %progname)
|
||||
print ("libsndfile.so.%s" % version)
|
||||
print ("{")
|
||||
print (" global:")
|
||||
for name, ordinal in ALL_SYMBOLS:
|
||||
print " %s ;" % name
|
||||
print " local:"
|
||||
print " * ;"
|
||||
print "} ;"
|
||||
print
|
||||
if name == "sf_wchar_open":
|
||||
continue
|
||||
print (" %s ;" % name)
|
||||
print (" local:")
|
||||
print (" * ;")
|
||||
print ("} ;")
|
||||
sys.stdout.write ("\n")
|
||||
return
|
||||
|
||||
def darwin_symbols (progname, version):
|
||||
print "# Auto-generated by %s\n" %progname
|
||||
print ("# Auto-generated by %s\n" %progname)
|
||||
for name, ordinal in ALL_SYMBOLS:
|
||||
print "_%s" % name
|
||||
print
|
||||
if name == "sf_wchar_open":
|
||||
continue
|
||||
print ("_%s" % name)
|
||||
sys.stdout.write ("\n")
|
||||
return
|
||||
|
||||
def win32_symbols (progname, version, name):
|
||||
print "; Auto-generated by %s\n" %progname
|
||||
print "LIBRARY %s-%s.dll" % (name, re.sub ("\..*", "", version))
|
||||
print "EXPORTS\n"
|
||||
print ("; Auto-generated by %s\n" %progname)
|
||||
print ("LIBRARY %s-%s.dll" % (name, re.sub ("\..*", "", version)))
|
||||
print ("EXPORTS\n")
|
||||
for name, ordinal in ALL_SYMBOLS:
|
||||
print "%-20s @%s" % (name, ordinal)
|
||||
print
|
||||
print ("%-20s @%s" % (name, ordinal))
|
||||
sys.stdout.write ("\n")
|
||||
return
|
||||
|
||||
def os2_symbols (progname, version, name):
|
||||
print "; Auto-generated by %s\n" %progname
|
||||
print "LIBRARY %s%s.dll" % (name, re.sub ("\..*", "", version))
|
||||
print "INITINSTANCE TERMINSTANCE"
|
||||
print "CODE PRELOAD MOVEABLE DISCARDABLE"
|
||||
print "DATA PRELOAD MOVEABLE MULTIPLE NONSHARED"
|
||||
print "EXPORTS\n"
|
||||
print ("; Auto-generated by %s\n" %progname)
|
||||
print ("LIBRARY %s%s" % (name, re.sub ("\..*", "", version)))
|
||||
print ("INITINSTANCE TERMINSTANCE")
|
||||
print ("CODE PRELOAD MOVEABLE DISCARDABLE")
|
||||
print ("DATA PRELOAD MOVEABLE MULTIPLE NONSHARED")
|
||||
print ("EXPORTS\n")
|
||||
for name, ordinal in ALL_SYMBOLS:
|
||||
print "_%-20s @%s" % (name, ordinal)
|
||||
print
|
||||
if name == "sf_wchar_open":
|
||||
continue
|
||||
print ("_%-20s @%s" % (name, ordinal))
|
||||
sys.stdout.write ("\n")
|
||||
return
|
||||
|
||||
def plain_symbols (progname, version, name):
|
||||
for name, ordinal in ALL_SYMBOLS:
|
||||
print (name)
|
||||
|
||||
def no_symbols (os_name):
|
||||
print
|
||||
print "No known way of restricting exported symbols on '%s'." % os_name
|
||||
print "If you know a way, please contact the author."
|
||||
print
|
||||
sys.stdout.write ("\n")
|
||||
print ("No known way of restricting exported symbols on '%s'." % os_name)
|
||||
print ("If you know a way, please contact the author.")
|
||||
sys.stdout.write ("\n")
|
||||
return
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
@@ -129,22 +147,23 @@ def no_symbols (os_name):
|
||||
progname = re.sub (".*[\\/]", "", sys.argv [0])
|
||||
|
||||
if len (sys.argv) != 3:
|
||||
print
|
||||
print "Usage : %s <target OS name> <libsndfile version>." % progname
|
||||
print
|
||||
print " Currently supported values for target OS are:"
|
||||
print " linux"
|
||||
print " darwin (ie MacOSX)"
|
||||
print " win32 (ie wintendo)"
|
||||
print " cygwin (Cygwin on wintendo)"
|
||||
print " os2 (OS/2)"
|
||||
print
|
||||
sys.stdout.write ("\n")
|
||||
print ("Usage : %s <target OS name> <libsndfile version>." % progname)
|
||||
sys.stdout.write ("\n")
|
||||
print (" Currently supported values for target OS are:")
|
||||
print (" linux")
|
||||
print (" darwin (ie MacOSX)")
|
||||
print (" win32 (ie wintendo)")
|
||||
print (" cygwin (Cygwin on wintendo)")
|
||||
print (" os2 (OS/2)")
|
||||
print (" plain (plain list of symbols)")
|
||||
sys.stdout.write ("\n")
|
||||
sys.exit (1)
|
||||
|
||||
os_name = sys.argv [1]
|
||||
version = re.sub ("\.[a-z0-9]+$", "", sys.argv [2])
|
||||
|
||||
if os_name == "linux":
|
||||
if os_name == "linux" or os_name == "gnu" or os_name == "binutils":
|
||||
linux_symbols (progname, version)
|
||||
elif os_name == "darwin":
|
||||
darwin_symbols (progname, version)
|
||||
@@ -154,6 +173,8 @@ elif os_name == "cygwin":
|
||||
win32_symbols (progname, version, "cygsndfile")
|
||||
elif os_name == "os2":
|
||||
os2_symbols (progname, version, "sndfile")
|
||||
elif os_name == "static":
|
||||
plain_symbols (progname, version, "")
|
||||
else:
|
||||
no_symbols (os_name)
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** Copyright (C) 2003-2009 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
** Copyright (C) 2003-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
|
||||
+107
-92
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** Copyright (C) 1999-2009 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
** Copyright (C) 1999-2012 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
@@ -95,7 +95,7 @@ double64_init (SF_PRIVATE *psf)
|
||||
|
||||
psf->blockwidth = sizeof (double) * psf->sf.channels ;
|
||||
|
||||
if (psf->mode == SFM_READ || psf->mode == SFM_RDWR)
|
||||
if (psf->file.mode == SFM_READ || psf->file.mode == SFM_RDWR)
|
||||
{ switch (psf->endian + double64_caps)
|
||||
{ case (SF_ENDIAN_BIG + DOUBLE_CAN_RW_BE) :
|
||||
psf->data_endswap = SF_FALSE ;
|
||||
@@ -166,7 +166,7 @@ double64_init (SF_PRIVATE *psf)
|
||||
} ;
|
||||
} ;
|
||||
|
||||
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
|
||||
if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
|
||||
{ switch (psf->endian + double64_caps)
|
||||
{ case (SF_ENDIAN_LITTLE + DOUBLE_CAN_RW_LE) :
|
||||
psf->data_endswap = SF_FALSE ;
|
||||
@@ -276,7 +276,7 @@ double64_init (SF_PRIVATE *psf)
|
||||
*/
|
||||
|
||||
double
|
||||
double64_be_read (unsigned char *cptr)
|
||||
double64_be_read (const unsigned char *cptr)
|
||||
{ int exponent, negative, upper, lower ;
|
||||
double dvalue ;
|
||||
|
||||
@@ -309,7 +309,7 @@ double64_be_read (unsigned char *cptr)
|
||||
} /* double64_be_read */
|
||||
|
||||
double
|
||||
double64_le_read (unsigned char *cptr)
|
||||
double64_le_read (const unsigned char *cptr)
|
||||
{ int exponent, negative, upper, lower ;
|
||||
double dvalue ;
|
||||
|
||||
@@ -554,24 +554,25 @@ f2d_array (const float *src, double *dest, int count)
|
||||
|
||||
static sf_count_t
|
||||
host_read_d2s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
|
||||
{ void (*convert) (const double *, int, short *, double) ;
|
||||
{ BUF_UNION ubuf ;
|
||||
void (*convert) (const double *, int, short *, double) ;
|
||||
int bufferlen, readcount ;
|
||||
sf_count_t total = 0 ;
|
||||
double scale ;
|
||||
|
||||
convert = (psf->add_clipping) ? d2s_clip_array : d2s_array ;
|
||||
bufferlen = ARRAY_LEN (psf->u.dbuf) ;
|
||||
bufferlen = ARRAY_LEN (ubuf.dbuf) ;
|
||||
scale = (psf->float_int_mult == 0) ? 1.0 : 0x7FFF / psf->float_max ;
|
||||
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
readcount = psf_fread (psf->u.dbuf, sizeof (double), bufferlen, psf) ;
|
||||
readcount = psf_fread (ubuf.dbuf, sizeof (double), bufferlen, psf) ;
|
||||
|
||||
if (psf->data_endswap == SF_TRUE)
|
||||
endswap_double_array (psf->u.dbuf, readcount) ;
|
||||
endswap_double_array (ubuf.dbuf, readcount) ;
|
||||
|
||||
convert (psf->u.dbuf, readcount, ptr + total, scale) ;
|
||||
convert (ubuf.dbuf, readcount, ptr + total, scale) ;
|
||||
total += readcount ;
|
||||
len -= readcount ;
|
||||
if (readcount < bufferlen)
|
||||
@@ -583,24 +584,25 @@ host_read_d2s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
|
||||
|
||||
static sf_count_t
|
||||
host_read_d2i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
|
||||
{ void (*convert) (const double *, int, int *, double) ;
|
||||
{ BUF_UNION ubuf ;
|
||||
void (*convert) (const double *, int, int *, double) ;
|
||||
int bufferlen, readcount ;
|
||||
sf_count_t total = 0 ;
|
||||
double scale ;
|
||||
|
||||
convert = (psf->add_clipping) ? d2i_clip_array : d2i_array ;
|
||||
bufferlen = ARRAY_LEN (psf->u.dbuf) ;
|
||||
bufferlen = ARRAY_LEN (ubuf.dbuf) ;
|
||||
scale = (psf->float_int_mult == 0) ? 1.0 : 0x7FFFFFFF / psf->float_max ;
|
||||
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
readcount = psf_fread (psf->u.dbuf, sizeof (double), bufferlen, psf) ;
|
||||
readcount = psf_fread (ubuf.dbuf, sizeof (double), bufferlen, psf) ;
|
||||
|
||||
if (psf->data_endswap == SF_TRUE)
|
||||
endswap_double_array (psf->u.dbuf, bufferlen) ;
|
||||
endswap_double_array (ubuf.dbuf, bufferlen) ;
|
||||
|
||||
convert (psf->u.dbuf, readcount, ptr + total, scale) ;
|
||||
convert (ubuf.dbuf, readcount, ptr + total, scale) ;
|
||||
total += readcount ;
|
||||
len -= readcount ;
|
||||
if (readcount < bufferlen)
|
||||
@@ -612,20 +614,21 @@ host_read_d2i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
|
||||
|
||||
static sf_count_t
|
||||
host_read_d2f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
|
||||
{ int bufferlen, readcount ;
|
||||
{ BUF_UNION ubuf ;
|
||||
int bufferlen, readcount ;
|
||||
sf_count_t total = 0 ;
|
||||
|
||||
bufferlen = ARRAY_LEN (psf->u.dbuf) ;
|
||||
bufferlen = ARRAY_LEN (ubuf.dbuf) ;
|
||||
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
readcount = psf_fread (psf->u.dbuf, sizeof (double), bufferlen, psf) ;
|
||||
readcount = psf_fread (ubuf.dbuf, sizeof (double), bufferlen, psf) ;
|
||||
|
||||
if (psf->data_endswap == SF_TRUE)
|
||||
endswap_double_array (psf->u.dbuf, bufferlen) ;
|
||||
endswap_double_array (ubuf.dbuf, bufferlen) ;
|
||||
|
||||
d2f_array (psf->u.dbuf, readcount, ptr + total) ;
|
||||
d2f_array (ubuf.dbuf, readcount, ptr + total) ;
|
||||
total += readcount ;
|
||||
len -= readcount ;
|
||||
if (readcount < bufferlen)
|
||||
@@ -667,26 +670,27 @@ host_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
|
||||
|
||||
static sf_count_t
|
||||
host_write_s2d (SF_PRIVATE *psf, const short *ptr, sf_count_t len)
|
||||
{ int bufferlen, writecount ;
|
||||
{ BUF_UNION ubuf ;
|
||||
int bufferlen, writecount ;
|
||||
sf_count_t total = 0 ;
|
||||
double scale ;
|
||||
|
||||
scale = (psf->scale_int_float == 0) ? 1.0 : 1.0 / 0x8000 ;
|
||||
bufferlen = ARRAY_LEN (psf->u.dbuf) ;
|
||||
bufferlen = ARRAY_LEN (ubuf.dbuf) ;
|
||||
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
|
||||
s2d_array (ptr + total, psf->u.dbuf, bufferlen, scale) ;
|
||||
s2d_array (ptr + total, ubuf.dbuf, bufferlen, scale) ;
|
||||
|
||||
if (psf->peak_info)
|
||||
double64_peak_update (psf, psf->u.dbuf, bufferlen, total / psf->sf.channels) ;
|
||||
double64_peak_update (psf, ubuf.dbuf, bufferlen, total / psf->sf.channels) ;
|
||||
|
||||
if (psf->data_endswap == SF_TRUE)
|
||||
endswap_double_array (psf->u.dbuf, bufferlen) ;
|
||||
endswap_double_array (ubuf.dbuf, bufferlen) ;
|
||||
|
||||
writecount = psf_fwrite (psf->u.dbuf, sizeof (double), bufferlen, psf) ;
|
||||
writecount = psf_fwrite (ubuf.dbuf, sizeof (double), bufferlen, psf) ;
|
||||
total += writecount ;
|
||||
if (writecount < bufferlen)
|
||||
break ;
|
||||
@@ -698,25 +702,26 @@ host_write_s2d (SF_PRIVATE *psf, const short *ptr, sf_count_t len)
|
||||
|
||||
static sf_count_t
|
||||
host_write_i2d (SF_PRIVATE *psf, const int *ptr, sf_count_t len)
|
||||
{ int bufferlen, writecount ;
|
||||
{ BUF_UNION ubuf ;
|
||||
int bufferlen, writecount ;
|
||||
sf_count_t total = 0 ;
|
||||
double scale ;
|
||||
|
||||
scale = (psf->scale_int_float == 0) ? 1.0 : 1.0 / (8.0 * 0x10000000) ;
|
||||
bufferlen = ARRAY_LEN (psf->u.dbuf) ;
|
||||
bufferlen = ARRAY_LEN (ubuf.dbuf) ;
|
||||
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
i2d_array (ptr + total, psf->u.dbuf, bufferlen, scale) ;
|
||||
i2d_array (ptr + total, ubuf.dbuf, bufferlen, scale) ;
|
||||
|
||||
if (psf->peak_info)
|
||||
double64_peak_update (psf, psf->u.dbuf, bufferlen, total / psf->sf.channels) ;
|
||||
double64_peak_update (psf, ubuf.dbuf, bufferlen, total / psf->sf.channels) ;
|
||||
|
||||
if (psf->data_endswap == SF_TRUE)
|
||||
endswap_double_array (psf->u.dbuf, bufferlen) ;
|
||||
endswap_double_array (ubuf.dbuf, bufferlen) ;
|
||||
|
||||
writecount = psf_fwrite (psf->u.dbuf, sizeof (double), bufferlen, psf) ;
|
||||
writecount = psf_fwrite (ubuf.dbuf, sizeof (double), bufferlen, psf) ;
|
||||
total += writecount ;
|
||||
if (writecount < bufferlen)
|
||||
break ;
|
||||
@@ -728,23 +733,24 @@ host_write_i2d (SF_PRIVATE *psf, const int *ptr, sf_count_t len)
|
||||
|
||||
static sf_count_t
|
||||
host_write_f2d (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
|
||||
{ int bufferlen, writecount ;
|
||||
{ BUF_UNION ubuf ;
|
||||
int bufferlen, writecount ;
|
||||
sf_count_t total = 0 ;
|
||||
|
||||
bufferlen = ARRAY_LEN (psf->u.dbuf) ;
|
||||
bufferlen = ARRAY_LEN (ubuf.dbuf) ;
|
||||
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
f2d_array (ptr + total, psf->u.dbuf, bufferlen) ;
|
||||
f2d_array (ptr + total, ubuf.dbuf, bufferlen) ;
|
||||
|
||||
if (psf->peak_info)
|
||||
double64_peak_update (psf, psf->u.dbuf, bufferlen, total / psf->sf.channels) ;
|
||||
double64_peak_update (psf, ubuf.dbuf, bufferlen, total / psf->sf.channels) ;
|
||||
|
||||
if (psf->data_endswap == SF_TRUE)
|
||||
endswap_double_array (psf->u.dbuf, bufferlen) ;
|
||||
endswap_double_array (ubuf.dbuf, bufferlen) ;
|
||||
|
||||
writecount = psf_fwrite (psf->u.dbuf, sizeof (double), bufferlen, psf) ;
|
||||
writecount = psf_fwrite (ubuf.dbuf, sizeof (double), bufferlen, psf) ;
|
||||
total += writecount ;
|
||||
if (writecount < bufferlen)
|
||||
break ;
|
||||
@@ -756,7 +762,8 @@ host_write_f2d (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
|
||||
|
||||
static sf_count_t
|
||||
host_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
|
||||
{ int bufferlen, writecount ;
|
||||
{ BUF_UNION ubuf ;
|
||||
int bufferlen, writecount ;
|
||||
sf_count_t total = 0 ;
|
||||
|
||||
if (psf->peak_info)
|
||||
@@ -765,15 +772,15 @@ host_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
|
||||
if (psf->data_endswap != SF_TRUE)
|
||||
return psf_fwrite (ptr, sizeof (double), len, psf) ;
|
||||
|
||||
bufferlen = ARRAY_LEN (psf->u.dbuf) ;
|
||||
bufferlen = ARRAY_LEN (ubuf.dbuf) ;
|
||||
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
|
||||
endswap_double_copy (psf->u.dbuf, ptr + total, bufferlen) ;
|
||||
endswap_double_copy (ubuf.dbuf, ptr + total, bufferlen) ;
|
||||
|
||||
writecount = psf_fwrite (psf->u.dbuf, sizeof (double), bufferlen, psf) ;
|
||||
writecount = psf_fwrite (ubuf.dbuf, sizeof (double), bufferlen, psf) ;
|
||||
total += writecount ;
|
||||
if (writecount < bufferlen)
|
||||
break ;
|
||||
@@ -788,24 +795,25 @@ host_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
|
||||
|
||||
static sf_count_t
|
||||
replace_read_d2s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
|
||||
{ int bufferlen, readcount ;
|
||||
{ BUF_UNION ubuf ;
|
||||
int bufferlen, readcount ;
|
||||
sf_count_t total = 0 ;
|
||||
double scale ;
|
||||
|
||||
bufferlen = ARRAY_LEN (psf->u.dbuf) ;
|
||||
bufferlen = ARRAY_LEN (ubuf.dbuf) ;
|
||||
scale = (psf->float_int_mult == 0) ? 1.0 : 0x7FFF / psf->float_max ;
|
||||
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
readcount = psf_fread (psf->u.dbuf, sizeof (double), bufferlen, psf) ;
|
||||
readcount = psf_fread (ubuf.dbuf, sizeof (double), bufferlen, psf) ;
|
||||
|
||||
if (psf->data_endswap == SF_TRUE)
|
||||
endswap_double_array (psf->u.dbuf, bufferlen) ;
|
||||
endswap_double_array (ubuf.dbuf, bufferlen) ;
|
||||
|
||||
d2bd_read (psf->u.dbuf, bufferlen) ;
|
||||
d2bd_read (ubuf.dbuf, bufferlen) ;
|
||||
|
||||
d2s_array (psf->u.dbuf, readcount, ptr + total, scale) ;
|
||||
d2s_array (ubuf.dbuf, readcount, ptr + total, scale) ;
|
||||
total += readcount ;
|
||||
if (readcount < bufferlen)
|
||||
break ;
|
||||
@@ -817,24 +825,25 @@ replace_read_d2s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
|
||||
|
||||
static sf_count_t
|
||||
replace_read_d2i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
|
||||
{ int bufferlen, readcount ;
|
||||
{ BUF_UNION ubuf ;
|
||||
int bufferlen, readcount ;
|
||||
sf_count_t total = 0 ;
|
||||
double scale ;
|
||||
|
||||
bufferlen = ARRAY_LEN (psf->u.dbuf) ;
|
||||
bufferlen = ARRAY_LEN (ubuf.dbuf) ;
|
||||
scale = (psf->float_int_mult == 0) ? 1.0 : 0x7FFFFFFF / psf->float_max ;
|
||||
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
readcount = psf_fread (psf->u.dbuf, sizeof (double), bufferlen, psf) ;
|
||||
readcount = psf_fread (ubuf.dbuf, sizeof (double), bufferlen, psf) ;
|
||||
|
||||
if (psf->data_endswap == SF_TRUE)
|
||||
endswap_double_array (psf->u.dbuf, bufferlen) ;
|
||||
endswap_double_array (ubuf.dbuf, bufferlen) ;
|
||||
|
||||
d2bd_read (psf->u.dbuf, bufferlen) ;
|
||||
d2bd_read (ubuf.dbuf, bufferlen) ;
|
||||
|
||||
d2i_array (psf->u.dbuf, readcount, ptr + total, scale) ;
|
||||
d2i_array (ubuf.dbuf, readcount, ptr + total, scale) ;
|
||||
total += readcount ;
|
||||
if (readcount < bufferlen)
|
||||
break ;
|
||||
@@ -846,22 +855,23 @@ replace_read_d2i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
|
||||
|
||||
static sf_count_t
|
||||
replace_read_d2f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
|
||||
{ int bufferlen, readcount ;
|
||||
{ BUF_UNION ubuf ;
|
||||
int bufferlen, readcount ;
|
||||
sf_count_t total = 0 ;
|
||||
|
||||
bufferlen = ARRAY_LEN (psf->u.dbuf) ;
|
||||
bufferlen = ARRAY_LEN (ubuf.dbuf) ;
|
||||
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
readcount = psf_fread (psf->u.dbuf, sizeof (double), bufferlen, psf) ;
|
||||
readcount = psf_fread (ubuf.dbuf, sizeof (double), bufferlen, psf) ;
|
||||
|
||||
if (psf->data_endswap == SF_TRUE)
|
||||
endswap_double_array (psf->u.dbuf, bufferlen) ;
|
||||
endswap_double_array (ubuf.dbuf, bufferlen) ;
|
||||
|
||||
d2bd_read (psf->u.dbuf, bufferlen) ;
|
||||
d2bd_read (ubuf.dbuf, bufferlen) ;
|
||||
|
||||
memcpy (ptr + total, psf->u.dbuf, bufferlen * sizeof (double)) ;
|
||||
memcpy (ptr + total, ubuf.dbuf, bufferlen * sizeof (double)) ;
|
||||
|
||||
total += readcount ;
|
||||
if (readcount < bufferlen)
|
||||
@@ -874,23 +884,24 @@ replace_read_d2f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
|
||||
|
||||
static sf_count_t
|
||||
replace_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
|
||||
{ int bufferlen, readcount ;
|
||||
{ BUF_UNION ubuf ;
|
||||
int bufferlen, readcount ;
|
||||
sf_count_t total = 0 ;
|
||||
|
||||
/* FIXME : This is probably nowhere near optimal. */
|
||||
bufferlen = ARRAY_LEN (psf->u.dbuf) ;
|
||||
bufferlen = ARRAY_LEN (ubuf.dbuf) ;
|
||||
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
readcount = psf_fread (psf->u.dbuf, sizeof (double), bufferlen, psf) ;
|
||||
readcount = psf_fread (ubuf.dbuf, sizeof (double), bufferlen, psf) ;
|
||||
|
||||
if (psf->data_endswap == SF_TRUE)
|
||||
endswap_double_array (psf->u.dbuf, readcount) ;
|
||||
endswap_double_array (ubuf.dbuf, readcount) ;
|
||||
|
||||
d2bd_read (psf->u.dbuf, readcount) ;
|
||||
d2bd_read (ubuf.dbuf, readcount) ;
|
||||
|
||||
memcpy (ptr + total, psf->u.dbuf, readcount * sizeof (double)) ;
|
||||
memcpy (ptr + total, ubuf.dbuf, readcount * sizeof (double)) ;
|
||||
|
||||
total += readcount ;
|
||||
if (readcount < bufferlen)
|
||||
@@ -903,27 +914,28 @@ replace_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
|
||||
|
||||
static sf_count_t
|
||||
replace_write_s2d (SF_PRIVATE *psf, const short *ptr, sf_count_t len)
|
||||
{ int bufferlen, writecount ;
|
||||
{ BUF_UNION ubuf ;
|
||||
int bufferlen, writecount ;
|
||||
sf_count_t total = 0 ;
|
||||
double scale ;
|
||||
|
||||
scale = (psf->scale_int_float == 0) ? 1.0 : 1.0 / 0x8000 ;
|
||||
bufferlen = ARRAY_LEN (psf->u.dbuf) ;
|
||||
bufferlen = ARRAY_LEN (ubuf.dbuf) ;
|
||||
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
s2d_array (ptr + total, psf->u.dbuf, bufferlen, scale) ;
|
||||
s2d_array (ptr + total, ubuf.dbuf, bufferlen, scale) ;
|
||||
|
||||
if (psf->peak_info)
|
||||
double64_peak_update (psf, psf->u.dbuf, bufferlen, total / psf->sf.channels) ;
|
||||
double64_peak_update (psf, ubuf.dbuf, bufferlen, total / psf->sf.channels) ;
|
||||
|
||||
bd2d_write (psf->u.dbuf, bufferlen) ;
|
||||
bd2d_write (ubuf.dbuf, bufferlen) ;
|
||||
|
||||
if (psf->data_endswap == SF_TRUE)
|
||||
endswap_double_array (psf->u.dbuf, bufferlen) ;
|
||||
endswap_double_array (ubuf.dbuf, bufferlen) ;
|
||||
|
||||
writecount = psf_fwrite (psf->u.dbuf, sizeof (double), bufferlen, psf) ;
|
||||
writecount = psf_fwrite (ubuf.dbuf, sizeof (double), bufferlen, psf) ;
|
||||
total += writecount ;
|
||||
if (writecount < bufferlen)
|
||||
break ;
|
||||
@@ -935,27 +947,28 @@ replace_write_s2d (SF_PRIVATE *psf, const short *ptr, sf_count_t len)
|
||||
|
||||
static sf_count_t
|
||||
replace_write_i2d (SF_PRIVATE *psf, const int *ptr, sf_count_t len)
|
||||
{ int bufferlen, writecount ;
|
||||
{ BUF_UNION ubuf ;
|
||||
int bufferlen, writecount ;
|
||||
sf_count_t total = 0 ;
|
||||
double scale ;
|
||||
|
||||
scale = (psf->scale_int_float == 0) ? 1.0 : 1.0 / (8.0 * 0x10000000) ;
|
||||
bufferlen = ARRAY_LEN (psf->u.dbuf) ;
|
||||
bufferlen = ARRAY_LEN (ubuf.dbuf) ;
|
||||
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
i2d_array (ptr + total, psf->u.dbuf, bufferlen, scale) ;
|
||||
i2d_array (ptr + total, ubuf.dbuf, bufferlen, scale) ;
|
||||
|
||||
if (psf->peak_info)
|
||||
double64_peak_update (psf, psf->u.dbuf, bufferlen, total / psf->sf.channels) ;
|
||||
double64_peak_update (psf, ubuf.dbuf, bufferlen, total / psf->sf.channels) ;
|
||||
|
||||
bd2d_write (psf->u.dbuf, bufferlen) ;
|
||||
bd2d_write (ubuf.dbuf, bufferlen) ;
|
||||
|
||||
if (psf->data_endswap == SF_TRUE)
|
||||
endswap_double_array (psf->u.dbuf, bufferlen) ;
|
||||
endswap_double_array (ubuf.dbuf, bufferlen) ;
|
||||
|
||||
writecount = psf_fwrite (psf->u.dbuf, sizeof (double), bufferlen, psf) ;
|
||||
writecount = psf_fwrite (ubuf.dbuf, sizeof (double), bufferlen, psf) ;
|
||||
total += writecount ;
|
||||
if (writecount < bufferlen)
|
||||
break ;
|
||||
@@ -967,22 +980,23 @@ replace_write_i2d (SF_PRIVATE *psf, const int *ptr, sf_count_t len)
|
||||
|
||||
static sf_count_t
|
||||
replace_write_f2d (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
|
||||
{ int bufferlen, writecount ;
|
||||
{ BUF_UNION ubuf ;
|
||||
int bufferlen, writecount ;
|
||||
sf_count_t total = 0 ;
|
||||
|
||||
bufferlen = ARRAY_LEN (psf->u.dbuf) ;
|
||||
bufferlen = ARRAY_LEN (ubuf.dbuf) ;
|
||||
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
f2d_array (ptr + total, psf->u.dbuf, bufferlen) ;
|
||||
f2d_array (ptr + total, ubuf.dbuf, bufferlen) ;
|
||||
|
||||
bd2d_write (psf->u.dbuf, bufferlen) ;
|
||||
bd2d_write (ubuf.dbuf, bufferlen) ;
|
||||
|
||||
if (psf->data_endswap == SF_TRUE)
|
||||
endswap_double_array (psf->u.dbuf, bufferlen) ;
|
||||
endswap_double_array (ubuf.dbuf, bufferlen) ;
|
||||
|
||||
writecount = psf_fwrite (psf->u.dbuf, sizeof (double), bufferlen, psf) ;
|
||||
writecount = psf_fwrite (ubuf.dbuf, sizeof (double), bufferlen, psf) ;
|
||||
total += writecount ;
|
||||
if (writecount < bufferlen)
|
||||
break ;
|
||||
@@ -994,27 +1008,28 @@ replace_write_f2d (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
|
||||
|
||||
static sf_count_t
|
||||
replace_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
|
||||
{ int bufferlen, writecount ;
|
||||
{ BUF_UNION ubuf ;
|
||||
int bufferlen, writecount ;
|
||||
sf_count_t total = 0 ;
|
||||
|
||||
/* FIXME : This is probably nowhere near optimal. */
|
||||
if (psf->peak_info)
|
||||
double64_peak_update (psf, ptr, len, 0) ;
|
||||
|
||||
bufferlen = ARRAY_LEN (psf->u.dbuf) ;
|
||||
bufferlen = ARRAY_LEN (ubuf.dbuf) ;
|
||||
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
|
||||
memcpy (psf->u.dbuf, ptr + total, bufferlen * sizeof (double)) ;
|
||||
memcpy (ubuf.dbuf, ptr + total, bufferlen * sizeof (double)) ;
|
||||
|
||||
bd2d_write (psf->u.dbuf, bufferlen) ;
|
||||
bd2d_write (ubuf.dbuf, bufferlen) ;
|
||||
|
||||
if (psf->data_endswap == SF_TRUE)
|
||||
endswap_double_array (psf->u.dbuf, bufferlen) ;
|
||||
endswap_double_array (ubuf.dbuf, bufferlen) ;
|
||||
|
||||
writecount = psf_fwrite (psf->u.dbuf, sizeof (double), bufferlen, psf) ;
|
||||
writecount = psf_fwrite (ubuf.dbuf, sizeof (double), bufferlen, psf) ;
|
||||
total += writecount ;
|
||||
if (writecount < bufferlen)
|
||||
break ;
|
||||
|
||||
+13
-14
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** Copyright (C) 2002-2009 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
** Copyright (C) 2002-2012 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
@@ -69,9 +69,9 @@ static int dwd_close (SF_PRIVATE *psf) ;
|
||||
|
||||
int
|
||||
dwd_open (SF_PRIVATE *psf)
|
||||
{ int subformat, error = 0 ;
|
||||
{ int error = 0 ;
|
||||
|
||||
if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->filelength > 0))
|
||||
if (psf->file.mode == SFM_READ || (psf->file.mode == SFM_RDWR && psf->filelength > 0))
|
||||
{ if ((error = dwd_read_header (psf)))
|
||||
return error ;
|
||||
} ;
|
||||
@@ -79,9 +79,7 @@ dwd_open (SF_PRIVATE *psf)
|
||||
if ((SF_CONTAINER (psf->sf.format)) != SF_FORMAT_DWD)
|
||||
return SFE_BAD_OPEN_FORMAT ;
|
||||
|
||||
subformat = SF_CODEC (psf->sf.format) ;
|
||||
|
||||
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
|
||||
if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
|
||||
{
|
||||
/*-psf->endian = SF_ENDIAN (psf->sf.format) ;
|
||||
if (CPU_IS_LITTLE_ENDIAN && psf->endian == SF_ENDIAN_CPU)
|
||||
@@ -124,16 +122,17 @@ typedef struct
|
||||
|
||||
static int
|
||||
dwd_read_header (SF_PRIVATE *psf)
|
||||
{ DWD_HEADER dwdh ;
|
||||
{ BUF_UNION ubuf ;
|
||||
DWD_HEADER dwdh ;
|
||||
|
||||
memset (psf->u.cbuf, 0, sizeof (psf->u.cbuf)) ;
|
||||
memset (ubuf.cbuf, 0, sizeof (ubuf.cbuf)) ;
|
||||
/* Set position to start of file to begin reading header. */
|
||||
psf_binheader_readf (psf, "pb", 0, psf->u.cbuf, DWD_IDENTIFIER_LEN) ;
|
||||
psf_binheader_readf (psf, "pb", 0, ubuf.cbuf, DWD_IDENTIFIER_LEN) ;
|
||||
|
||||
if (memcmp (psf->u.cbuf, DWD_IDENTIFIER, DWD_IDENTIFIER_LEN) != 0)
|
||||
if (memcmp (ubuf.cbuf, DWD_IDENTIFIER, DWD_IDENTIFIER_LEN) != 0)
|
||||
return SFE_DWD_NO_DWD ;
|
||||
|
||||
psf_log_printf (psf, "Read only : DiamondWare Digitized (.dwd)\n", psf->u.cbuf) ;
|
||||
psf_log_printf (psf, "Read only : DiamondWare Digitized (.dwd)\n", ubuf.cbuf) ;
|
||||
|
||||
psf_binheader_readf (psf, "11", &dwdh.major, &dwdh.minor) ;
|
||||
psf_binheader_readf (psf, "e4j1", &dwdh.id, 1, &dwdh.compression) ;
|
||||
@@ -152,9 +151,9 @@ dwd_read_header (SF_PRIVATE *psf)
|
||||
else
|
||||
psf_log_printf (psf, "None\n") ;
|
||||
|
||||
psf_log_printf (psf, " Sample Rate : %d\n Channels : %d\n"
|
||||
" Bit Width : %d\n",
|
||||
dwdh.srate, dwdh.channels, dwdh.bitwidth) ;
|
||||
psf_log_printf (psf, " Sample Rate : %d\n Channels : %d\n"
|
||||
" Bit Width : %d\n",
|
||||
dwdh.srate, dwdh.channels, dwdh.bitwidth) ;
|
||||
|
||||
switch (dwdh.bitwidth)
|
||||
{ case 8 :
|
||||
|
||||
+54
-42
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** Copyright (C) 2002-2009 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
** Copyright (C) 2002-2012 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
@@ -38,7 +38,7 @@
|
||||
#include "common.h"
|
||||
|
||||
typedef struct
|
||||
{ int dwm_maxsize, bit_width, max_delta, span ;
|
||||
{ int bit_width, dwm_maxsize, max_delta, span ;
|
||||
int samplecount ;
|
||||
int bit_count, bits, last_delta_width, last_sample ;
|
||||
struct
|
||||
@@ -61,7 +61,8 @@ static sf_count_t dwvw_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t le
|
||||
static sf_count_t dwvw_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ;
|
||||
|
||||
static sf_count_t dwvw_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) ;
|
||||
static int dwvw_close (SF_PRIVATE *psf) ;
|
||||
static int dwvw_close (SF_PRIVATE *psf) ;
|
||||
static int dwvw_byterate (SF_PRIVATE *psf) ;
|
||||
|
||||
static int dwvw_decode_data (SF_PRIVATE *psf, DWVW_PRIVATE *pdwvw, int *ptr, int len) ;
|
||||
static int dwvw_decode_load_bits (SF_PRIVATE *psf, DWVW_PRIVATE *pdwvw, int bit_count) ;
|
||||
@@ -86,29 +87,24 @@ dwvw_init (SF_PRIVATE *psf, int bitwidth)
|
||||
if (bitwidth > 24)
|
||||
return SFE_DWVW_BAD_BITWIDTH ;
|
||||
|
||||
if (psf->mode == SFM_RDWR)
|
||||
if (psf->file.mode == SFM_RDWR)
|
||||
return SFE_BAD_MODE_RW ;
|
||||
|
||||
if ((pdwvw = calloc (1, sizeof (DWVW_PRIVATE))) == NULL)
|
||||
return SFE_MALLOC_FAILED ;
|
||||
|
||||
psf->codec_data = (void*) pdwvw ;
|
||||
|
||||
pdwvw->bit_width = bitwidth ;
|
||||
pdwvw->dwm_maxsize = bitwidth / 2 ;
|
||||
pdwvw->max_delta = 1 << (bitwidth - 1) ;
|
||||
pdwvw->span = 1 << bitwidth ;
|
||||
|
||||
dwvw_read_reset (pdwvw) ;
|
||||
|
||||
if (psf->mode == SFM_READ)
|
||||
if (psf->file.mode == SFM_READ)
|
||||
{ psf->read_short = dwvw_read_s ;
|
||||
psf->read_int = dwvw_read_i ;
|
||||
psf->read_float = dwvw_read_f ;
|
||||
psf->read_double = dwvw_read_d ;
|
||||
} ;
|
||||
|
||||
if (psf->mode == SFM_WRITE)
|
||||
if (psf->file.mode == SFM_WRITE)
|
||||
{ psf->write_short = dwvw_write_s ;
|
||||
psf->write_int = dwvw_write_i ;
|
||||
psf->write_float = dwvw_write_f ;
|
||||
@@ -117,11 +113,12 @@ dwvw_init (SF_PRIVATE *psf, int bitwidth)
|
||||
|
||||
psf->codec_close = dwvw_close ;
|
||||
psf->seek = dwvw_seek ;
|
||||
psf->byterate = dwvw_byterate ;
|
||||
|
||||
/* FIXME : This is bogus. */
|
||||
psf->sf.frames = SF_COUNT_MAX ;
|
||||
psf->datalength = psf->sf.frames ;
|
||||
/* EMXIF : This is bogus. */
|
||||
if (psf->file.mode == SFM_READ)
|
||||
{ psf->sf.frames = psf_decode_frame_count (psf) ;
|
||||
dwvw_read_reset (pdwvw) ;
|
||||
} ;
|
||||
|
||||
return 0 ;
|
||||
} /* dwvw_init */
|
||||
@@ -137,7 +134,7 @@ dwvw_close (SF_PRIVATE *psf)
|
||||
return 0 ;
|
||||
pdwvw = (DWVW_PRIVATE*) psf->codec_data ;
|
||||
|
||||
if (psf->mode == SFM_WRITE)
|
||||
if (psf->file.mode == SFM_WRITE)
|
||||
{ static int last_values [12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } ;
|
||||
|
||||
/* Write 8 zero samples to fully flush output. */
|
||||
@@ -174,6 +171,14 @@ dwvw_seek (SF_PRIVATE *psf, int UNUSED (mode), sf_count_t offset)
|
||||
return PSF_SEEK_ERROR ;
|
||||
} /* dwvw_seek */
|
||||
|
||||
static int
|
||||
dwvw_byterate (SF_PRIVATE *psf)
|
||||
{
|
||||
if (psf->file.mode == SFM_READ)
|
||||
return (psf->datalength * psf->sf.samplerate) / psf->sf.frames ;
|
||||
|
||||
return -1 ;
|
||||
} /* dwvw_byterate */
|
||||
|
||||
/*==============================================================================
|
||||
*/
|
||||
@@ -181,6 +186,7 @@ dwvw_seek (SF_PRIVATE *psf, int UNUSED (mode), sf_count_t offset)
|
||||
static sf_count_t
|
||||
dwvw_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
|
||||
{ DWVW_PRIVATE *pdwvw ;
|
||||
BUF_UNION ubuf ;
|
||||
int *iptr ;
|
||||
int k, bufferlen, readcount = 0, count ;
|
||||
sf_count_t total = 0 ;
|
||||
@@ -189,8 +195,8 @@ dwvw_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
|
||||
return 0 ;
|
||||
pdwvw = (DWVW_PRIVATE*) psf->codec_data ;
|
||||
|
||||
iptr = psf->u.ibuf ;
|
||||
bufferlen = ARRAY_LEN (psf->u.ibuf) ;
|
||||
iptr = ubuf.ibuf ;
|
||||
bufferlen = ARRAY_LEN (ubuf.ibuf) ;
|
||||
while (len > 0)
|
||||
{ readcount = (len >= bufferlen) ? bufferlen : len ;
|
||||
count = dwvw_decode_data (psf, pdwvw, iptr, readcount) ;
|
||||
@@ -234,8 +240,9 @@ dwvw_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
|
||||
static sf_count_t
|
||||
dwvw_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
|
||||
{ DWVW_PRIVATE *pdwvw ;
|
||||
int *iptr ;
|
||||
int k, bufferlen, readcount = 0, count ;
|
||||
BUF_UNION ubuf ;
|
||||
int *iptr ;
|
||||
int k, bufferlen, readcount = 0, count ;
|
||||
sf_count_t total = 0 ;
|
||||
float normfact ;
|
||||
|
||||
@@ -245,8 +252,8 @@ dwvw_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
|
||||
|
||||
normfact = (psf->norm_float == SF_TRUE) ? 1.0 / ((float) 0x80000000) : 1.0 ;
|
||||
|
||||
iptr = psf->u.ibuf ;
|
||||
bufferlen = ARRAY_LEN (psf->u.ibuf) ;
|
||||
iptr = ubuf.ibuf ;
|
||||
bufferlen = ARRAY_LEN (ubuf.ibuf) ;
|
||||
while (len > 0)
|
||||
{ readcount = (len >= bufferlen) ? bufferlen : len ;
|
||||
count = dwvw_decode_data (psf, pdwvw, iptr, readcount) ;
|
||||
@@ -265,8 +272,9 @@ dwvw_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
|
||||
static sf_count_t
|
||||
dwvw_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
|
||||
{ DWVW_PRIVATE *pdwvw ;
|
||||
int *iptr ;
|
||||
int k, bufferlen, readcount = 0, count ;
|
||||
BUF_UNION ubuf ;
|
||||
int *iptr ;
|
||||
int k, bufferlen, readcount = 0, count ;
|
||||
sf_count_t total = 0 ;
|
||||
double normfact ;
|
||||
|
||||
@@ -276,8 +284,8 @@ dwvw_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
|
||||
|
||||
normfact = (psf->norm_double == SF_TRUE) ? 1.0 / ((double) 0x80000000) : 1.0 ;
|
||||
|
||||
iptr = psf->u.ibuf ;
|
||||
bufferlen = ARRAY_LEN (psf->u.ibuf) ;
|
||||
iptr = ubuf.ibuf ;
|
||||
bufferlen = ARRAY_LEN (ubuf.ibuf) ;
|
||||
while (len > 0)
|
||||
{ readcount = (len >= bufferlen) ? bufferlen : len ;
|
||||
count = dwvw_decode_data (psf, pdwvw, iptr, readcount) ;
|
||||
@@ -307,7 +315,7 @@ dwvw_decode_data (SF_PRIVATE *psf, DWVW_PRIVATE *pdwvw, int *ptr, int len)
|
||||
delta_width_modifier = dwvw_decode_load_bits (psf, pdwvw, -1) ;
|
||||
|
||||
/* Check for end of input bit stream. Break loop if end. */
|
||||
if (delta_width_modifier < 0)
|
||||
if (delta_width_modifier < 0 || (pdwvw->b.end == 0 && count == 0))
|
||||
break ;
|
||||
|
||||
if (delta_width_modifier && dwvw_decode_load_bits (psf, pdwvw, 1))
|
||||
@@ -406,13 +414,14 @@ dwvw_decode_load_bits (SF_PRIVATE *psf, DWVW_PRIVATE *pdwvw, int bit_count)
|
||||
|
||||
static void
|
||||
dwvw_read_reset (DWVW_PRIVATE *pdwvw)
|
||||
{ pdwvw->samplecount = 0 ;
|
||||
pdwvw->b.index = 0 ;
|
||||
pdwvw->b.end = 0 ;
|
||||
pdwvw->bit_count = 0 ;
|
||||
pdwvw->bits = 0 ;
|
||||
pdwvw->last_delta_width = 0 ;
|
||||
pdwvw->last_sample = 0 ;
|
||||
{ int bitwidth = pdwvw->bit_width ;
|
||||
|
||||
memset (pdwvw, 0, sizeof (DWVW_PRIVATE)) ;
|
||||
|
||||
pdwvw->bit_width = bitwidth ;
|
||||
pdwvw->dwm_maxsize = bitwidth / 2 ;
|
||||
pdwvw->max_delta = 1 << (bitwidth - 1) ;
|
||||
pdwvw->span = 1 << bitwidth ;
|
||||
} /* dwvw_read_reset */
|
||||
|
||||
static void
|
||||
@@ -461,9 +470,9 @@ dump_bits (DWVW_PRIVATE *pdwvw)
|
||||
} /* dump_bits */
|
||||
#endif
|
||||
|
||||
#define HIGHEST_BIT(x,count) \
|
||||
#define HIGHEST_BIT(x, count) \
|
||||
{ int y = x ; \
|
||||
(count) = 0 ; \
|
||||
(count) = 0 ; \
|
||||
while (y) \
|
||||
{ (count) ++ ; \
|
||||
y >>= 1 ; \
|
||||
@@ -548,6 +557,7 @@ dwvw_encode_data (SF_PRIVATE *psf, DWVW_PRIVATE *pdwvw, const int *ptr, int len)
|
||||
static sf_count_t
|
||||
dwvw_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len)
|
||||
{ DWVW_PRIVATE *pdwvw ;
|
||||
BUF_UNION ubuf ;
|
||||
int *iptr ;
|
||||
int k, bufferlen, writecount = 0, count ;
|
||||
sf_count_t total = 0 ;
|
||||
@@ -556,8 +566,8 @@ dwvw_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len)
|
||||
return 0 ;
|
||||
pdwvw = (DWVW_PRIVATE*) psf->codec_data ;
|
||||
|
||||
iptr = psf->u.ibuf ;
|
||||
bufferlen = ARRAY_LEN (psf->u.ibuf) ;
|
||||
iptr = ubuf.ibuf ;
|
||||
bufferlen = ARRAY_LEN (ubuf.ibuf) ;
|
||||
while (len > 0)
|
||||
{ writecount = (len >= bufferlen) ? bufferlen : len ;
|
||||
for (k = 0 ; k < writecount ; k++)
|
||||
@@ -601,6 +611,7 @@ dwvw_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len)
|
||||
static sf_count_t
|
||||
dwvw_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
|
||||
{ DWVW_PRIVATE *pdwvw ;
|
||||
BUF_UNION ubuf ;
|
||||
int *iptr ;
|
||||
int k, bufferlen, writecount = 0, count ;
|
||||
sf_count_t total = 0 ;
|
||||
@@ -612,8 +623,8 @@ dwvw_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
|
||||
|
||||
normfact = (psf->norm_float == SF_TRUE) ? (1.0 * 0x7FFFFFFF) : 1.0 ;
|
||||
|
||||
iptr = psf->u.ibuf ;
|
||||
bufferlen = ARRAY_LEN (psf->u.ibuf) ;
|
||||
iptr = ubuf.ibuf ;
|
||||
bufferlen = ARRAY_LEN (ubuf.ibuf) ;
|
||||
while (len > 0)
|
||||
{ writecount = (len >= bufferlen) ? bufferlen : len ;
|
||||
for (k = 0 ; k < writecount ; k++)
|
||||
@@ -632,6 +643,7 @@ dwvw_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
|
||||
static sf_count_t
|
||||
dwvw_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
|
||||
{ DWVW_PRIVATE *pdwvw ;
|
||||
BUF_UNION ubuf ;
|
||||
int *iptr ;
|
||||
int k, bufferlen, writecount = 0, count ;
|
||||
sf_count_t total = 0 ;
|
||||
@@ -643,8 +655,8 @@ dwvw_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
|
||||
|
||||
normfact = (psf->norm_double == SF_TRUE) ? (1.0 * 0x7FFFFFFF) : 1.0 ;
|
||||
|
||||
iptr = psf->u.ibuf ;
|
||||
bufferlen = ARRAY_LEN (psf->u.ibuf) ;
|
||||
iptr = ubuf.ibuf ;
|
||||
bufferlen = ARRAY_LEN (ubuf.ibuf) ;
|
||||
while (len > 0)
|
||||
{ writecount = (len >= bufferlen) ? bufferlen : len ;
|
||||
for (k = 0 ; k < writecount ; k++)
|
||||
|
||||
+195
-174
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** Copyright (C) 2002-2009 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
** Copyright (C) 2002-2013 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
** Copyright (C) 2003 Ross Bencina <rbencina@iprimus.com.au>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
@@ -73,26 +73,24 @@ static void psf_log_syserr (SF_PRIVATE *psf, int error) ;
|
||||
*/
|
||||
|
||||
static int psf_close_fd (int fd) ;
|
||||
static int psf_open_fd (const char * path, int mode) ;
|
||||
static int psf_open_fd (PSF_FILE * pfile) ;
|
||||
static sf_count_t psf_get_filelen_fd (int fd) ;
|
||||
|
||||
int
|
||||
psf_fopen (SF_PRIVATE *psf, const char *pathname, int open_mode)
|
||||
psf_fopen (SF_PRIVATE *psf)
|
||||
{
|
||||
psf->error = 0 ;
|
||||
psf->filedes = psf_open_fd (pathname, open_mode) ;
|
||||
psf->file.filedes = psf_open_fd (&psf->file) ;
|
||||
|
||||
if (psf->filedes == - SFE_BAD_OPEN_MODE)
|
||||
if (psf->file.filedes == - SFE_BAD_OPEN_MODE)
|
||||
{ psf->error = SFE_BAD_OPEN_MODE ;
|
||||
psf->filedes = -1 ;
|
||||
psf->file.filedes = -1 ;
|
||||
return psf->error ;
|
||||
} ;
|
||||
|
||||
if (psf->filedes == -1)
|
||||
if (psf->file.filedes == -1)
|
||||
psf_log_syserr (psf, errno) ;
|
||||
|
||||
psf->mode = open_mode ;
|
||||
|
||||
return psf->error ;
|
||||
} /* psf_fopen */
|
||||
|
||||
@@ -100,43 +98,40 @@ int
|
||||
psf_fclose (SF_PRIVATE *psf)
|
||||
{ int retval ;
|
||||
|
||||
if (psf->filedes == -1)
|
||||
return -1; /* already closed */
|
||||
|
||||
if (psf->virtual_io)
|
||||
return 0 ;
|
||||
|
||||
if (psf->do_not_close_descriptor)
|
||||
{ psf->filedes = -1 ;
|
||||
if (psf->file.do_not_close_descriptor)
|
||||
{ psf->file.filedes = -1 ;
|
||||
return 0 ;
|
||||
} ;
|
||||
|
||||
if ((retval = psf_close_fd (psf->filedes)) == -1)
|
||||
if ((retval = psf_close_fd (psf->file.filedes)) == -1)
|
||||
psf_log_syserr (psf, errno) ;
|
||||
|
||||
psf->filedes = -1 ;
|
||||
psf->file.filedes = -1 ;
|
||||
|
||||
return retval ;
|
||||
} /* psf_fclose */
|
||||
|
||||
int
|
||||
psf_open_rsrc (SF_PRIVATE *psf, int open_mode)
|
||||
psf_open_rsrc (SF_PRIVATE *psf)
|
||||
{
|
||||
if (psf->rsrcdes > 0)
|
||||
if (psf->rsrc.filedes > 0)
|
||||
return 0 ;
|
||||
|
||||
/* Test for MacOSX style resource fork on HPFS or HPFS+ filesystems. */
|
||||
snprintf (psf->rsrcpath, sizeof (psf->rsrcpath), "%s/rsrc", psf->filepath) ;
|
||||
snprintf (psf->rsrc.path.c, sizeof (psf->rsrc.path.c), "%s/..namedfork/rsrc", psf->file.path.c) ;
|
||||
psf->error = SFE_NO_ERROR ;
|
||||
if ((psf->rsrcdes = psf_open_fd (psf->rsrcpath, open_mode)) >= 0)
|
||||
{ psf->rsrclength = psf_get_filelen_fd (psf->rsrcdes) ;
|
||||
if (psf->rsrclength > 0 || (open_mode & SFM_WRITE))
|
||||
if ((psf->rsrc.filedes = psf_open_fd (&psf->rsrc)) >= 0)
|
||||
{ psf->rsrclength = psf_get_filelen_fd (psf->rsrc.filedes) ;
|
||||
if (psf->rsrclength > 0 || (psf->rsrc.mode & SFM_WRITE))
|
||||
return SFE_NO_ERROR ;
|
||||
psf_close_fd (psf->rsrcdes) ;
|
||||
psf->rsrcdes = -1 ;
|
||||
psf_close_fd (psf->rsrc.filedes) ;
|
||||
psf->rsrc.filedes = -1 ;
|
||||
} ;
|
||||
|
||||
if (psf->rsrcdes == - SFE_BAD_OPEN_MODE)
|
||||
if (psf->rsrc.filedes == - SFE_BAD_OPEN_MODE)
|
||||
{ psf->error = SFE_BAD_OPEN_MODE ;
|
||||
return psf->error ;
|
||||
} ;
|
||||
@@ -145,10 +140,10 @@ psf_open_rsrc (SF_PRIVATE *psf, int open_mode)
|
||||
** Now try for a resource fork stored as a separate file in the same
|
||||
** directory, but preceded with a dot underscore.
|
||||
*/
|
||||
snprintf (psf->rsrcpath, sizeof (psf->rsrcpath), "%s._%s", psf->directory, psf->filename) ;
|
||||
snprintf (psf->rsrc.path.c, sizeof (psf->rsrc.path.c), "%s._%s", psf->file.dir.c, psf->file.name.c) ;
|
||||
psf->error = SFE_NO_ERROR ;
|
||||
if ((psf->rsrcdes = psf_open_fd (psf->rsrcpath, open_mode)) >= 0)
|
||||
{ psf->rsrclength = psf_get_filelen_fd (psf->rsrcdes) ;
|
||||
if ((psf->rsrc.filedes = psf_open_fd (&psf->rsrc)) >= 0)
|
||||
{ psf->rsrclength = psf_get_filelen_fd (psf->rsrc.filedes) ;
|
||||
return SFE_NO_ERROR ;
|
||||
} ;
|
||||
|
||||
@@ -156,18 +151,18 @@ psf_open_rsrc (SF_PRIVATE *psf, int open_mode)
|
||||
** Now try for a resource fork stored in a separate file in the
|
||||
** .AppleDouble/ directory.
|
||||
*/
|
||||
snprintf (psf->rsrcpath, sizeof (psf->rsrcpath), "%s.AppleDouble/%s", psf->directory, psf->filename) ;
|
||||
snprintf (psf->rsrc.path.c, sizeof (psf->rsrc.path.c), "%s.AppleDouble/%s", psf->file.dir.c, psf->file.name.c) ;
|
||||
psf->error = SFE_NO_ERROR ;
|
||||
if ((psf->rsrcdes = psf_open_fd (psf->rsrcpath, open_mode)) >= 0)
|
||||
{ psf->rsrclength = psf_get_filelen_fd (psf->rsrcdes) ;
|
||||
if ((psf->rsrc.filedes = psf_open_fd (&psf->rsrc)) >= 0)
|
||||
{ psf->rsrclength = psf_get_filelen_fd (psf->rsrc.filedes) ;
|
||||
return SFE_NO_ERROR ;
|
||||
} ;
|
||||
|
||||
/* No resource file found. */
|
||||
if (psf->rsrcdes == -1)
|
||||
if (psf->rsrc.filedes == -1)
|
||||
psf_log_syserr (psf, errno) ;
|
||||
|
||||
psf->rsrcdes = -1 ;
|
||||
psf->rsrc.filedes = -1 ;
|
||||
|
||||
return psf->error ;
|
||||
} /* psf_open_rsrc */
|
||||
@@ -179,7 +174,7 @@ psf_get_filelen (SF_PRIVATE *psf)
|
||||
if (psf->virtual_io)
|
||||
return psf->vio.get_filelen (psf->vio_user_data) ;
|
||||
|
||||
filelen = psf_get_filelen_fd (psf->filedes) ;
|
||||
filelen = psf_get_filelen_fd (psf->file.filedes) ;
|
||||
|
||||
if (filelen == -1)
|
||||
{ psf_log_syserr (psf, errno) ;
|
||||
@@ -191,7 +186,7 @@ psf_get_filelen (SF_PRIVATE *psf)
|
||||
return (sf_count_t) -1 ;
|
||||
} ;
|
||||
|
||||
switch (psf->mode)
|
||||
switch (psf->file.mode)
|
||||
{ case SFM_WRITE :
|
||||
filelen = filelen - psf->fileoffset ;
|
||||
break ;
|
||||
@@ -219,28 +214,26 @@ psf_get_filelen (SF_PRIVATE *psf)
|
||||
|
||||
int
|
||||
psf_close_rsrc (SF_PRIVATE *psf)
|
||||
{
|
||||
if (psf->rsrcdes >= 0)
|
||||
psf_close_fd (psf->rsrcdes) ;
|
||||
psf->rsrcdes = -1 ;
|
||||
{ psf_close_fd (psf->rsrc.filedes) ;
|
||||
psf->rsrc.filedes = -1 ;
|
||||
return 0 ;
|
||||
} /* psf_close_rsrc */
|
||||
|
||||
int
|
||||
psf_set_stdio (SF_PRIVATE *psf, int mode)
|
||||
psf_set_stdio (SF_PRIVATE *psf)
|
||||
{ int error = 0 ;
|
||||
|
||||
switch (mode)
|
||||
switch (psf->file.mode)
|
||||
{ case SFM_RDWR :
|
||||
error = SFE_OPEN_PIPE_RDWR ;
|
||||
break ;
|
||||
|
||||
case SFM_READ :
|
||||
psf->filedes = 0 ;
|
||||
psf->file.filedes = 0 ;
|
||||
break ;
|
||||
|
||||
case SFM_WRITE :
|
||||
psf->filedes = 1 ;
|
||||
psf->file.filedes = 1 ;
|
||||
break ;
|
||||
|
||||
default :
|
||||
@@ -254,29 +247,31 @@ psf_set_stdio (SF_PRIVATE *psf, int mode)
|
||||
|
||||
void
|
||||
psf_set_file (SF_PRIVATE *psf, int fd)
|
||||
{ psf->filedes = fd ;
|
||||
{ psf->file.filedes = fd ;
|
||||
} /* psf_set_file */
|
||||
|
||||
int
|
||||
psf_file_valid (SF_PRIVATE *psf)
|
||||
{ return (psf->filedes >= 0) ? SF_TRUE : SF_FALSE ;
|
||||
{ return (psf->file.filedes >= 0) ? SF_TRUE : SF_FALSE ;
|
||||
} /* psf_set_file */
|
||||
|
||||
sf_count_t
|
||||
psf_fseek (SF_PRIVATE *psf, sf_count_t offset, int whence)
|
||||
{ sf_count_t new_position ;
|
||||
{ sf_count_t current_pos, new_position ;
|
||||
|
||||
if (psf->virtual_io)
|
||||
return psf->vio.seek (offset, whence, psf->vio_user_data) ;
|
||||
|
||||
current_pos = psf_ftell (psf) ;
|
||||
|
||||
switch (whence)
|
||||
{ case SEEK_SET :
|
||||
offset += psf->fileoffset ;
|
||||
break ;
|
||||
|
||||
case SEEK_END :
|
||||
if (psf->mode == SFM_WRITE)
|
||||
{ new_position = lseek (psf->filedes, offset, whence) ;
|
||||
if (psf->file.mode == SFM_WRITE)
|
||||
{ new_position = lseek (psf->file.filedes, offset, whence) ;
|
||||
|
||||
if (new_position < 0)
|
||||
psf_log_syserr (psf, errno) ;
|
||||
@@ -289,15 +284,25 @@ psf_fseek (SF_PRIVATE *psf, sf_count_t offset, int whence)
|
||||
** get the offset wrt the start of file.
|
||||
*/
|
||||
whence = SEEK_SET ;
|
||||
offset = lseek (psf->filedes, 0, SEEK_END) + offset ;
|
||||
offset = lseek (psf->file.filedes, 0, SEEK_END) + offset ;
|
||||
break ;
|
||||
|
||||
case SEEK_CUR :
|
||||
/* Translate a SEEK_CUR into a SEEK_SET. */
|
||||
offset += current_pos ;
|
||||
whence = SEEK_SET ;
|
||||
break ;
|
||||
|
||||
default :
|
||||
/* No need to do anything about SEEK_CUR. */
|
||||
break ;
|
||||
/* We really should not be here. */
|
||||
psf_log_printf (psf, "psf_fseek : whence is %d *****.\n", whence) ;
|
||||
return 0 ;
|
||||
} ;
|
||||
|
||||
new_position = lseek (psf->filedes, offset, whence) ;
|
||||
if (current_pos != offset)
|
||||
new_position = lseek (psf->file.filedes, offset, whence) ;
|
||||
else
|
||||
new_position = offset ;
|
||||
|
||||
if (new_position < 0)
|
||||
psf_log_syserr (psf, errno) ;
|
||||
@@ -325,7 +330,7 @@ psf_fread (void *ptr, sf_count_t bytes, sf_count_t items, SF_PRIVATE *psf)
|
||||
{ /* Break the read down to a sensible size. */
|
||||
count = (items > SENSIBLE_SIZE) ? SENSIBLE_SIZE : (ssize_t) items ;
|
||||
|
||||
count = read (psf->filedes, ((char*) ptr) + total, (size_t) count) ;
|
||||
count = read (psf->file.filedes, ((char*) ptr) + total, (size_t) count) ;
|
||||
|
||||
if (count == -1)
|
||||
{ if (errno == EINTR)
|
||||
@@ -366,7 +371,7 @@ psf_fwrite (const void *ptr, sf_count_t bytes, sf_count_t items, SF_PRIVATE *psf
|
||||
{ /* Break the writes down to a sensible size. */
|
||||
count = (items > SENSIBLE_SIZE) ? SENSIBLE_SIZE : items ;
|
||||
|
||||
count = write (psf->filedes, ((const char*) ptr) + total, count) ;
|
||||
count = write (psf->file.filedes, ((const char*) ptr) + total, count) ;
|
||||
|
||||
if (count == -1)
|
||||
{ if (errno == EINTR)
|
||||
@@ -399,7 +404,7 @@ psf_ftell (SF_PRIVATE *psf)
|
||||
if (psf->is_pipe)
|
||||
return psf->pipeoffset ;
|
||||
|
||||
pos = lseek (psf->filedes, 0, SEEK_CUR) ;
|
||||
pos = lseek (psf->file.filedes, 0, SEEK_CUR) ;
|
||||
|
||||
if (pos == ((sf_count_t) -1))
|
||||
{ psf_log_syserr (psf, errno) ;
|
||||
@@ -413,6 +418,9 @@ static int
|
||||
psf_close_fd (int fd)
|
||||
{ int retval ;
|
||||
|
||||
if (fd < 0)
|
||||
return 0 ;
|
||||
|
||||
while ((retval = close (fd)) == -1 && errno == EINTR)
|
||||
/* Do nothing. */ ;
|
||||
|
||||
@@ -425,7 +433,7 @@ psf_fgets (char *buffer, sf_count_t bufsize, SF_PRIVATE *psf)
|
||||
sf_count_t count ;
|
||||
|
||||
while (k < bufsize - 1)
|
||||
{ count = read (psf->filedes, &(buffer [k]), 1) ;
|
||||
{ count = read (psf->file.filedes, &(buffer [k]), 1) ;
|
||||
|
||||
if (count == -1)
|
||||
{ if (errno == EINTR)
|
||||
@@ -451,7 +459,7 @@ psf_is_pipe (SF_PRIVATE *psf)
|
||||
if (psf->virtual_io)
|
||||
return SF_FALSE ;
|
||||
|
||||
if (fstat (psf->filedes, &statbuf) == -1)
|
||||
if (fstat (psf->file.filedes, &statbuf) == -1)
|
||||
{ psf_log_syserr (psf, errno) ;
|
||||
/* Default to maximum safety. */
|
||||
return SF_TRUE ;
|
||||
@@ -465,19 +473,22 @@ psf_is_pipe (SF_PRIVATE *psf)
|
||||
|
||||
static sf_count_t
|
||||
psf_get_filelen_fd (int fd)
|
||||
{ struct stat statbuf ;
|
||||
{
|
||||
#if (SIZEOF_OFF_T == 4 && SIZEOF_SF_COUNT_T == 8 && HAVE_FSTAT64)
|
||||
struct stat64 statbuf ;
|
||||
|
||||
/*
|
||||
** Sanity check.
|
||||
** If everything is OK, this will be optimised out.
|
||||
*/
|
||||
if (sizeof (statbuf.st_size) == 4 && sizeof (sf_count_t) == 8)
|
||||
return (sf_count_t) -SFE_BAD_STAT_SIZE ;
|
||||
if (fstat64 (fd, &statbuf) == -1)
|
||||
return (sf_count_t) -1 ;
|
||||
|
||||
return statbuf.st_size ;
|
||||
#else
|
||||
struct stat statbuf ;
|
||||
|
||||
if (fstat (fd, &statbuf) == -1)
|
||||
return (sf_count_t) -1 ;
|
||||
|
||||
return statbuf.st_size ;
|
||||
#endif
|
||||
} /* psf_get_filelen_fd */
|
||||
|
||||
int
|
||||
@@ -491,7 +502,7 @@ psf_ftruncate (SF_PRIVATE *psf, sf_count_t len)
|
||||
if ((sizeof (off_t) < sizeof (sf_count_t)) && len > 0x7FFFFFFF)
|
||||
return -1 ;
|
||||
|
||||
retval = ftruncate (psf->filedes, len) ;
|
||||
retval = ftruncate (psf->file.filedes, len) ;
|
||||
|
||||
if (retval == -1)
|
||||
psf_log_syserr (psf, errno) ;
|
||||
@@ -501,28 +512,28 @@ psf_ftruncate (SF_PRIVATE *psf, sf_count_t len)
|
||||
|
||||
void
|
||||
psf_init_files (SF_PRIVATE *psf)
|
||||
{ psf->filedes = -1 ;
|
||||
psf->rsrcdes = -1 ;
|
||||
psf->savedes = -1 ;
|
||||
{ psf->file.filedes = -1 ;
|
||||
psf->rsrc.filedes = -1 ;
|
||||
psf->file.savedes = -1 ;
|
||||
} /* psf_init_files */
|
||||
|
||||
void
|
||||
psf_use_rsrc (SF_PRIVATE *psf, int on_off)
|
||||
{
|
||||
if (on_off)
|
||||
{ if (psf->filedes != psf->rsrcdes)
|
||||
{ psf->savedes = psf->filedes ;
|
||||
psf->filedes = psf->rsrcdes ;
|
||||
{ if (psf->file.filedes != psf->rsrc.filedes)
|
||||
{ psf->file.savedes = psf->file.filedes ;
|
||||
psf->file.filedes = psf->rsrc.filedes ;
|
||||
} ;
|
||||
}
|
||||
else if (psf->filedes == psf->rsrcdes)
|
||||
psf->filedes = psf->savedes ;
|
||||
else if (psf->file.filedes == psf->rsrc.filedes)
|
||||
psf->file.filedes = psf->file.savedes ;
|
||||
|
||||
return ;
|
||||
} /* psf_use_rsrc */
|
||||
|
||||
static int
|
||||
psf_open_fd (const char * pathname, int open_mode)
|
||||
psf_open_fd (PSF_FILE * pfile)
|
||||
{ int fd, oflag, mode ;
|
||||
|
||||
/*
|
||||
@@ -530,13 +541,13 @@ psf_open_fd (const char * pathname, int open_mode)
|
||||
** be optimised out. This is meant to catch the problems caused by
|
||||
** "sfconfig.h" being included after <stdio.h>.
|
||||
*/
|
||||
if (sizeof (off_t) != sizeof (sf_count_t))
|
||||
{ puts ("\n\n*** Fatal error : sizeof (off_t) != sizeof (sf_count_t)") ;
|
||||
if (sizeof (sf_count_t) != 8)
|
||||
{ puts ("\n\n*** Fatal error : sizeof (sf_count_t) != 8") ;
|
||||
puts ("*** This means that libsndfile was not configured correctly.\n") ;
|
||||
exit (1) ;
|
||||
} ;
|
||||
|
||||
switch (open_mode)
|
||||
switch (pfile->mode)
|
||||
{ case SFM_READ :
|
||||
oflag = O_RDONLY | O_BINARY ;
|
||||
mode = 0 ;
|
||||
@@ -558,9 +569,9 @@ psf_open_fd (const char * pathname, int open_mode)
|
||||
} ;
|
||||
|
||||
if (mode == 0)
|
||||
fd = open (pathname, oflag) ;
|
||||
fd = open (pfile->path.c, oflag) ;
|
||||
else
|
||||
fd = open (pathname, oflag, mode) ;
|
||||
fd = open (pfile->path.c, oflag, mode) ;
|
||||
|
||||
return fd ;
|
||||
} /* psf_open_fd */
|
||||
@@ -581,10 +592,10 @@ void
|
||||
psf_fsync (SF_PRIVATE *psf)
|
||||
{
|
||||
#if HAVE_FSYNC
|
||||
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
|
||||
fsync (psf->filedes) ;
|
||||
if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
|
||||
fsync (psf->file.filedes) ;
|
||||
#else
|
||||
psf = NULL ;
|
||||
psf = NULL ;
|
||||
#endif
|
||||
} /* psf_fsync */
|
||||
|
||||
@@ -596,20 +607,18 @@ psf_fsync (SF_PRIVATE *psf)
|
||||
#include <io.h>
|
||||
|
||||
static int psf_close_handle (HANDLE handle) ;
|
||||
static HANDLE psf_open_handle (const char * path, int mode) ;
|
||||
static HANDLE psf_open_handle (PSF_FILE * pfile) ;
|
||||
static sf_count_t psf_get_filelen_handle (HANDLE handle) ;
|
||||
|
||||
/* USE_WINDOWS_API */ int
|
||||
psf_fopen (SF_PRIVATE *psf, const char *pathname, int open_mode)
|
||||
psf_fopen (SF_PRIVATE *psf)
|
||||
{
|
||||
psf->error = 0 ;
|
||||
psf->hfile = psf_open_handle (pathname, open_mode) ;
|
||||
psf->file.handle = psf_open_handle (&psf->file) ;
|
||||
|
||||
if (psf->hfile == NULL)
|
||||
if (psf->file.handle == NULL)
|
||||
psf_log_syserr (psf, GetLastError ()) ;
|
||||
|
||||
psf->mode = open_mode ;
|
||||
|
||||
return psf->error ;
|
||||
} /* psf_fopen */
|
||||
|
||||
@@ -620,30 +629,30 @@ psf_fclose (SF_PRIVATE *psf)
|
||||
if (psf->virtual_io)
|
||||
return 0 ;
|
||||
|
||||
if (psf->do_not_close_descriptor)
|
||||
{ psf->hfile = NULL ;
|
||||
if (psf->file.do_not_close_descriptor)
|
||||
{ psf->file.handle = NULL ;
|
||||
return 0 ;
|
||||
} ;
|
||||
|
||||
if ((retval = psf_close_handle (psf->hfile)) == -1)
|
||||
if ((retval = psf_close_handle (psf->file.handle)) == -1)
|
||||
psf_log_syserr (psf, GetLastError ()) ;
|
||||
|
||||
psf->hfile = NULL ;
|
||||
psf->file.handle = NULL ;
|
||||
|
||||
return retval ;
|
||||
} /* psf_fclose */
|
||||
|
||||
/* USE_WINDOWS_API */ int
|
||||
psf_open_rsrc (SF_PRIVATE *psf, int open_mode)
|
||||
psf_open_rsrc (SF_PRIVATE *psf)
|
||||
{
|
||||
if (psf->hrsrc != NULL)
|
||||
if (psf->rsrc.handle != NULL)
|
||||
return 0 ;
|
||||
|
||||
/* Test for MacOSX style resource fork on HPFS or HPFS+ filesystems. */
|
||||
snprintf (psf->rsrcpath, sizeof (psf->rsrcpath), "%s/rsrc", psf->filepath) ;
|
||||
snprintf (psf->rsrc.path.c, sizeof (psf->rsrc.path.c), "%s/rsrc", psf->file.path.c) ;
|
||||
psf->error = SFE_NO_ERROR ;
|
||||
if ((psf->hrsrc = psf_open_handle (psf->rsrcpath, open_mode)) != NULL)
|
||||
{ psf->rsrclength = psf_get_filelen_handle (psf->hrsrc) ;
|
||||
if ((psf->rsrc.handle = psf_open_handle (&psf->rsrc)) != NULL)
|
||||
{ psf->rsrclength = psf_get_filelen_handle (psf->rsrc.handle) ;
|
||||
return SFE_NO_ERROR ;
|
||||
} ;
|
||||
|
||||
@@ -651,10 +660,10 @@ psf_open_rsrc (SF_PRIVATE *psf, int open_mode)
|
||||
** Now try for a resource fork stored as a separate file in the same
|
||||
** directory, but preceded with a dot underscore.
|
||||
*/
|
||||
snprintf (psf->rsrcpath, sizeof (psf->rsrcpath), "%s._%s", psf->directory, psf->filename) ;
|
||||
snprintf (psf->rsrc.path.c, sizeof (psf->rsrc.path.c), "%s._%s", psf->file.dir.c, psf->file.name.c) ;
|
||||
psf->error = SFE_NO_ERROR ;
|
||||
if ((psf->hrsrc = psf_open_handle (psf->rsrcpath, open_mode)) != NULL)
|
||||
{ psf->rsrclength = psf_get_filelen_handle (psf->hrsrc) ;
|
||||
if ((psf->rsrc.handle = psf_open_handle (&psf->rsrc)) != NULL)
|
||||
{ psf->rsrclength = psf_get_filelen_handle (psf->rsrc.handle) ;
|
||||
return SFE_NO_ERROR ;
|
||||
} ;
|
||||
|
||||
@@ -662,18 +671,18 @@ psf_open_rsrc (SF_PRIVATE *psf, int open_mode)
|
||||
** Now try for a resource fork stored in a separate file in the
|
||||
** .AppleDouble/ directory.
|
||||
*/
|
||||
snprintf (psf->rsrcpath, sizeof (psf->rsrcpath), "%s.AppleDouble/%s", psf->directory, psf->filename) ;
|
||||
snprintf (psf->rsrc.path.c, sizeof (psf->rsrc.path.c), "%s.AppleDouble/%s", psf->file.dir.c, psf->file.name.c) ;
|
||||
psf->error = SFE_NO_ERROR ;
|
||||
if ((psf->hrsrc = psf_open_handle (psf->rsrcpath, open_mode)) != NULL)
|
||||
{ psf->rsrclength = psf_get_filelen_handle (psf->hrsrc) ;
|
||||
if ((psf->rsrc.handle = psf_open_handle (&psf->rsrc)) != NULL)
|
||||
{ psf->rsrclength = psf_get_filelen_handle (psf->rsrc.handle) ;
|
||||
return SFE_NO_ERROR ;
|
||||
} ;
|
||||
|
||||
/* No resource file found. */
|
||||
if (psf->hrsrc == NULL)
|
||||
if (psf->rsrc.handle == NULL)
|
||||
psf_log_syserr (psf, GetLastError ()) ;
|
||||
|
||||
psf->hrsrc = NULL ;
|
||||
psf->rsrc.handle = NULL ;
|
||||
|
||||
return psf->error ;
|
||||
} /* psf_open_rsrc */
|
||||
@@ -685,7 +694,7 @@ psf_get_filelen (SF_PRIVATE *psf)
|
||||
if (psf->virtual_io)
|
||||
return psf->vio.get_filelen (psf->vio_user_data) ;
|
||||
|
||||
filelen = psf_get_filelen_handle (psf->hfile) ;
|
||||
filelen = psf_get_filelen_handle (psf->file.handle) ;
|
||||
|
||||
if (filelen == -1)
|
||||
{ psf_log_syserr (psf, errno) ;
|
||||
@@ -697,7 +706,7 @@ psf_get_filelen (SF_PRIVATE *psf)
|
||||
return (sf_count_t) -1 ;
|
||||
} ;
|
||||
|
||||
switch (psf->mode)
|
||||
switch (psf->file.mode)
|
||||
{ case SFM_WRITE :
|
||||
filelen = filelen - psf->fileoffset ;
|
||||
break ;
|
||||
@@ -725,34 +734,34 @@ psf_get_filelen (SF_PRIVATE *psf)
|
||||
|
||||
/* USE_WINDOWS_API */ void
|
||||
psf_init_files (SF_PRIVATE *psf)
|
||||
{ psf->hfile = NULL ;
|
||||
psf->hrsrc = NULL ;
|
||||
psf->hsaved = NULL ;
|
||||
{ psf->file.handle = NULL ;
|
||||
psf->rsrc.handle = NULL ;
|
||||
psf->file.hsaved = NULL ;
|
||||
} /* psf_init_files */
|
||||
|
||||
/* USE_WINDOWS_API */ void
|
||||
psf_use_rsrc (SF_PRIVATE *psf, int on_off)
|
||||
{
|
||||
if (on_off)
|
||||
{ if (psf->hfile != psf->hrsrc)
|
||||
{ psf->hsaved = psf->hfile ;
|
||||
psf->hfile = psf->hrsrc ;
|
||||
{ if (psf->file.handle != psf->rsrc.handle)
|
||||
{ psf->file.hsaved = psf->file.handle ;
|
||||
psf->file.handle = psf->rsrc.handle ;
|
||||
} ;
|
||||
}
|
||||
else if (psf->hfile == psf->hrsrc)
|
||||
psf->hfile = psf->hsaved ;
|
||||
else if (psf->file.handle == psf->rsrc.handle)
|
||||
psf->file.handle = psf->file.hsaved ;
|
||||
|
||||
return ;
|
||||
} /* psf_use_rsrc */
|
||||
|
||||
/* USE_WINDOWS_API */ static HANDLE
|
||||
psf_open_handle (const char * pathname, int open_mode)
|
||||
psf_open_handle (PSF_FILE * pfile)
|
||||
{ DWORD dwDesiredAccess ;
|
||||
DWORD dwShareMode ;
|
||||
DWORD dwCreationDistribution ;
|
||||
HANDLE handle ;
|
||||
|
||||
switch (open_mode)
|
||||
switch (pfile->mode)
|
||||
{ case SFM_READ :
|
||||
dwDesiredAccess = GENERIC_READ ;
|
||||
dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE ;
|
||||
@@ -775,15 +784,26 @@ psf_open_handle (const char * pathname, int open_mode)
|
||||
return NULL ;
|
||||
} ;
|
||||
|
||||
handle = CreateFile (
|
||||
pathname, /* pointer to name of the file */
|
||||
dwDesiredAccess, /* access (read-write) mode */
|
||||
dwShareMode, /* share mode */
|
||||
0, /* pointer to security attributes */
|
||||
dwCreationDistribution, /* how to create */
|
||||
FILE_ATTRIBUTE_NORMAL, /* file attributes (could use FILE_FLAG_SEQUENTIAL_SCAN) */
|
||||
NULL /* handle to file with attributes to copy */
|
||||
) ;
|
||||
if (pfile->use_wchar)
|
||||
handle = CreateFileW (
|
||||
pfile->path.wc, /* pointer to name of the file */
|
||||
dwDesiredAccess, /* access (read-write) mode */
|
||||
dwShareMode, /* share mode */
|
||||
0, /* pointer to security attributes */
|
||||
dwCreationDistribution, /* how to create */
|
||||
FILE_ATTRIBUTE_NORMAL, /* file attributes (could use FILE_FLAG_SEQUENTIAL_SCAN) */
|
||||
NULL /* handle to file with attributes to copy */
|
||||
) ;
|
||||
else
|
||||
handle = CreateFile (
|
||||
pfile->path.c, /* pointer to name of the file */
|
||||
dwDesiredAccess, /* access (read-write) mode */
|
||||
dwShareMode, /* share mode */
|
||||
0, /* pointer to security attributes */
|
||||
dwCreationDistribution, /* how to create */
|
||||
FILE_ATTRIBUTE_NORMAL, /* file attributes (could use FILE_FLAG_SEQUENTIAL_SCAN) */
|
||||
NULL /* handle to file with attributes to copy */
|
||||
) ;
|
||||
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
return NULL ;
|
||||
@@ -819,32 +839,30 @@ psf_log_syserr (SF_PRIVATE *psf, int error)
|
||||
|
||||
/* USE_WINDOWS_API */ int
|
||||
psf_close_rsrc (SF_PRIVATE *psf)
|
||||
{
|
||||
if (psf->hrsrc != NULL)
|
||||
psf_close_handle (psf->hrsrc) ;
|
||||
psf->hrsrc = NULL ;
|
||||
{ psf_close_handle (psf->rsrc.handle) ;
|
||||
psf->rsrc.handle = NULL ;
|
||||
return 0 ;
|
||||
} /* psf_close_rsrc */
|
||||
|
||||
|
||||
/* USE_WINDOWS_API */ int
|
||||
psf_set_stdio (SF_PRIVATE *psf, int mode)
|
||||
psf_set_stdio (SF_PRIVATE *psf)
|
||||
{ HANDLE handle = NULL ;
|
||||
int error = 0 ;
|
||||
|
||||
switch (mode)
|
||||
switch (psf->file.mode)
|
||||
{ case SFM_RDWR :
|
||||
error = SFE_OPEN_PIPE_RDWR ;
|
||||
break ;
|
||||
|
||||
case SFM_READ :
|
||||
handle = GetStdHandle (STD_INPUT_HANDLE) ;
|
||||
psf->do_not_close_descriptor = 1 ;
|
||||
psf->file.do_not_close_descriptor = 1 ;
|
||||
break ;
|
||||
|
||||
case SFM_WRITE :
|
||||
handle = GetStdHandle (STD_OUTPUT_HANDLE) ;
|
||||
psf->do_not_close_descriptor = 1 ;
|
||||
psf->file.do_not_close_descriptor = 1 ;
|
||||
break ;
|
||||
|
||||
default :
|
||||
@@ -852,7 +870,7 @@ psf_set_stdio (SF_PRIVATE *psf, int mode)
|
||||
break ;
|
||||
} ;
|
||||
|
||||
psf->hfile = handle ;
|
||||
psf->file.handle = handle ;
|
||||
psf->filelength = 0 ;
|
||||
|
||||
return error ;
|
||||
@@ -866,14 +884,14 @@ psf_set_file (SF_PRIVATE *psf, int fd)
|
||||
osfhandle = _get_osfhandle (fd) ;
|
||||
handle = (HANDLE) osfhandle ;
|
||||
|
||||
psf->hfile = handle ;
|
||||
psf->file.handle = handle ;
|
||||
} /* psf_set_file */
|
||||
|
||||
/* USE_WINDOWS_API */ int
|
||||
psf_file_valid (SF_PRIVATE *psf)
|
||||
{ if (psf->hfile == NULL)
|
||||
{ if (psf->file.handle == NULL)
|
||||
return SF_FALSE ;
|
||||
if (psf->hfile == INVALID_HANDLE_VALUE)
|
||||
if (psf->file.handle == INVALID_HANDLE_VALUE)
|
||||
return SF_FALSE ;
|
||||
return SF_TRUE ;
|
||||
} /* psf_set_file */
|
||||
@@ -906,7 +924,7 @@ psf_fseek (SF_PRIVATE *psf, sf_count_t offset, int whence)
|
||||
lDistanceToMove = (DWORD) (offset & 0xFFFFFFFF) ;
|
||||
lDistanceToMoveHigh = (DWORD) ((offset >> 32) & 0xFFFFFFFF) ;
|
||||
|
||||
dwResult = SetFilePointer (psf->hfile, lDistanceToMove, &lDistanceToMoveHigh, dwMoveMethod) ;
|
||||
dwResult = SetFilePointer (psf->file.handle, lDistanceToMove, &lDistanceToMoveHigh, dwMoveMethod) ;
|
||||
|
||||
if (dwResult == 0xFFFFFFFF)
|
||||
dwError = GetLastError () ;
|
||||
@@ -942,7 +960,7 @@ psf_fread (void *ptr, sf_count_t bytes, sf_count_t items, SF_PRIVATE *psf)
|
||||
{ /* Break the writes down to a sensible size. */
|
||||
count = (items > SENSIBLE_SIZE) ? SENSIBLE_SIZE : (ssize_t) items ;
|
||||
|
||||
if (ReadFile (psf->hfile, ((char*) ptr) + total, count, &dwNumberOfBytesRead, 0) == 0)
|
||||
if (ReadFile (psf->file.handle, ((char*) ptr) + total, count, &dwNumberOfBytesRead, 0) == 0)
|
||||
{ psf_log_syserr (psf, GetLastError ()) ;
|
||||
break ;
|
||||
}
|
||||
@@ -965,7 +983,7 @@ psf_fread (void *ptr, sf_count_t bytes, sf_count_t items, SF_PRIVATE *psf)
|
||||
/* USE_WINDOWS_API */ sf_count_t
|
||||
psf_fwrite (const void *ptr, sf_count_t bytes, sf_count_t items, SF_PRIVATE *psf)
|
||||
{ sf_count_t total = 0 ;
|
||||
ssize_t count ;
|
||||
ssize_t count ;
|
||||
DWORD dwNumberOfBytesWritten ;
|
||||
|
||||
if (psf->virtual_io)
|
||||
@@ -981,7 +999,7 @@ psf_fwrite (const void *ptr, sf_count_t bytes, sf_count_t items, SF_PRIVATE *psf
|
||||
{ /* Break the writes down to a sensible size. */
|
||||
count = (items > SENSIBLE_SIZE) ? SENSIBLE_SIZE : (ssize_t) items ;
|
||||
|
||||
if (WriteFile (psf->hfile, ((const char*) ptr) + total, count, &dwNumberOfBytesWritten, 0) == 0)
|
||||
if (WriteFile (psf->file.handle, ((const char*) ptr) + total, count, &dwNumberOfBytesWritten, 0) == 0)
|
||||
{ psf_log_syserr (psf, GetLastError ()) ;
|
||||
break ;
|
||||
}
|
||||
@@ -1016,7 +1034,7 @@ psf_ftell (SF_PRIVATE *psf)
|
||||
lDistanceToMoveLow = 0 ;
|
||||
lDistanceToMoveHigh = 0 ;
|
||||
|
||||
dwResult = SetFilePointer (psf->hfile, lDistanceToMoveLow, &lDistanceToMoveHigh, FILE_CURRENT) ;
|
||||
dwResult = SetFilePointer (psf->file.handle, lDistanceToMoveLow, &lDistanceToMoveHigh, FILE_CURRENT) ;
|
||||
|
||||
if (dwResult == 0xFFFFFFFF)
|
||||
dwError = GetLastError () ;
|
||||
@@ -1035,7 +1053,10 @@ psf_ftell (SF_PRIVATE *psf)
|
||||
|
||||
/* USE_WINDOWS_API */ static int
|
||||
psf_close_handle (HANDLE handle)
|
||||
{ if (CloseHandle (handle) == 0)
|
||||
{ if (handle == NULL)
|
||||
return 0 ;
|
||||
|
||||
if (CloseHandle (handle) == 0)
|
||||
return -1 ;
|
||||
|
||||
return 0 ;
|
||||
@@ -1048,7 +1069,7 @@ psf_fgets (char *buffer, sf_count_t bufsize, SF_PRIVATE *psf)
|
||||
DWORD dwNumberOfBytesRead ;
|
||||
|
||||
while (k < bufsize - 1)
|
||||
{ if (ReadFile (psf->hfile, &(buffer [k]), 1, &dwNumberOfBytesRead, 0) == 0)
|
||||
{ if (ReadFile (psf->file.handle, &(buffer [k]), 1, &dwNumberOfBytesRead, 0) == 0)
|
||||
{ psf_log_syserr (psf, GetLastError ()) ;
|
||||
break ;
|
||||
}
|
||||
@@ -1071,7 +1092,7 @@ psf_is_pipe (SF_PRIVATE *psf)
|
||||
if (psf->virtual_io)
|
||||
return SF_FALSE ;
|
||||
|
||||
if (GetFileType (psf->hfile) == FILE_TYPE_DISK)
|
||||
if (GetFileType (psf->file.handle) == FILE_TYPE_DISK)
|
||||
return SF_FALSE ;
|
||||
|
||||
/* Default to maximum safety. */
|
||||
@@ -1098,7 +1119,7 @@ psf_get_filelen_handle (HANDLE handle)
|
||||
|
||||
/* USE_WINDOWS_API */ void
|
||||
psf_fsync (SF_PRIVATE *psf)
|
||||
{ FlushFileBuffers (psf->hfile) ;
|
||||
{ FlushFileBuffers (psf->file.handle) ;
|
||||
} /* psf_fsync */
|
||||
|
||||
|
||||
@@ -1120,7 +1141,7 @@ psf_ftruncate (SF_PRIVATE *psf, sf_count_t len)
|
||||
lDistanceToMoveLow = (DWORD) (len & 0xFFFFFFFF) ;
|
||||
lDistanceToMoveHigh = (DWORD) ((len >> 32) & 0xFFFFFFFF) ;
|
||||
|
||||
dwResult = SetFilePointer (psf->hfile, lDistanceToMoveLow, &lDistanceToMoveHigh, FILE_BEGIN) ;
|
||||
dwResult = SetFilePointer (psf->file.handle, lDistanceToMoveLow, &lDistanceToMoveHigh, FILE_BEGIN) ;
|
||||
|
||||
if (dwResult == 0xFFFFFFFF)
|
||||
dwError = GetLastError () ;
|
||||
@@ -1135,7 +1156,7 @@ psf_ftruncate (SF_PRIVATE *psf, sf_count_t len)
|
||||
** which guarantees that the new portion of the file will be zeroed.
|
||||
** Not sure if this is important or not.
|
||||
*/
|
||||
if (SetEndOfFile (psf->hfile) == 0)
|
||||
if (SetEndOfFile (psf->file.handle) == 0)
|
||||
{ retval = -1 ;
|
||||
psf_log_syserr (psf, GetLastError ()) ;
|
||||
} ;
|
||||
@@ -1191,14 +1212,14 @@ psf_fopen (SF_PRIVATE *psf, const char *pathname, int open_mode)
|
||||
} ;
|
||||
|
||||
if (mode == 0)
|
||||
psf->filedes = open (pathname, oflag) ;
|
||||
psf->file.filedes = open (pathname, oflag) ;
|
||||
else
|
||||
psf->filedes = open (pathname, oflag, mode) ;
|
||||
psf->file.filedes = open (pathname, oflag, mode) ;
|
||||
|
||||
if (psf->filedes == -1)
|
||||
if (psf->file.filedes == -1)
|
||||
psf_log_syserr (psf, errno) ;
|
||||
|
||||
return psf->filedes ;
|
||||
return psf->file.filedes ;
|
||||
} /* psf_fopen */
|
||||
|
||||
/* Win32 */ sf_count_t
|
||||
@@ -1214,8 +1235,8 @@ psf_fseek (SF_PRIVATE *psf, sf_count_t offset, int whence)
|
||||
break ;
|
||||
|
||||
case SEEK_END :
|
||||
if (psf->mode == SFM_WRITE)
|
||||
{ new_position = _lseeki64 (psf->filedes, offset, whence) ;
|
||||
if (psf->file.mode == SFM_WRITE)
|
||||
{ new_position = _lseeki64 (psf->file.filedes, offset, whence) ;
|
||||
|
||||
if (new_position < 0)
|
||||
psf_log_syserr (psf, errno) ;
|
||||
@@ -1228,7 +1249,7 @@ psf_fseek (SF_PRIVATE *psf, sf_count_t offset, int whence)
|
||||
** get the offset wrt the start of file.
|
||||
*/
|
||||
whence = SEEK_SET ;
|
||||
offset = _lseeki64 (psf->filedes, 0, SEEK_END) + offset ;
|
||||
offset = _lseeki64 (psf->file.filedes, 0, SEEK_END) + offset ;
|
||||
break ;
|
||||
|
||||
default :
|
||||
@@ -1243,9 +1264,9 @@ psf_fseek (SF_PRIVATE *psf, sf_count_t offset, int whence)
|
||||
*** Use the _telli64() function instead.
|
||||
*/
|
||||
if (offset == 0 && whence == SEEK_CUR)
|
||||
new_position = _telli64 (psf->filedes) ;
|
||||
new_position = _telli64 (psf->file.filedes) ;
|
||||
else
|
||||
new_position = _lseeki64 (psf->filedes, offset, whence) ;
|
||||
new_position = _lseeki64 (psf->file.filedes, offset, whence) ;
|
||||
|
||||
if (new_position < 0)
|
||||
psf_log_syserr (psf, errno) ;
|
||||
@@ -1258,7 +1279,7 @@ psf_fseek (SF_PRIVATE *psf, sf_count_t offset, int whence)
|
||||
/* Win32 */ sf_count_t
|
||||
psf_fread (void *ptr, sf_count_t bytes, sf_count_t items, SF_PRIVATE *psf)
|
||||
{ sf_count_t total = 0 ;
|
||||
ssize_t count ;
|
||||
ssize_t count ;
|
||||
|
||||
if (psf->virtual_io)
|
||||
return psf->vio.read (ptr, bytes*items, psf->vio_user_data) / bytes ;
|
||||
@@ -1273,7 +1294,7 @@ psf_fread (void *ptr, sf_count_t bytes, sf_count_t items, SF_PRIVATE *psf)
|
||||
{ /* Break the writes down to a sensible size. */
|
||||
count = (items > SENSIBLE_SIZE) ? SENSIBLE_SIZE : (ssize_t) items ;
|
||||
|
||||
count = read (psf->filedes, ((char*) ptr) + total, (size_t) count) ;
|
||||
count = read (psf->file.filedes, ((char*) ptr) + total, (size_t) count) ;
|
||||
|
||||
if (count == -1)
|
||||
{ if (errno == EINTR)
|
||||
@@ -1296,7 +1317,7 @@ psf_fread (void *ptr, sf_count_t bytes, sf_count_t items, SF_PRIVATE *psf)
|
||||
/* Win32 */ sf_count_t
|
||||
psf_fwrite (const void *ptr, sf_count_t bytes, sf_count_t items, SF_PRIVATE *psf)
|
||||
{ sf_count_t total = 0 ;
|
||||
ssize_t count ;
|
||||
ssize_t count ;
|
||||
|
||||
if (psf->virtual_io)
|
||||
return psf->vio.write (ptr, bytes*items, psf->vio_user_data) / bytes ;
|
||||
@@ -1311,7 +1332,7 @@ psf_fwrite (const void *ptr, sf_count_t bytes, sf_count_t items, SF_PRIVATE *psf
|
||||
{ /* Break the writes down to a sensible size. */
|
||||
count = (items > SENSIBLE_SIZE) ? SENSIBLE_SIZE : items ;
|
||||
|
||||
count = write (psf->filedes, ((const char*) ptr) + total, count) ;
|
||||
count = write (psf->file.filedes, ((const char*) ptr) + total, count) ;
|
||||
|
||||
if (count == -1)
|
||||
{ if (errno == EINTR)
|
||||
@@ -1338,7 +1359,7 @@ psf_ftell (SF_PRIVATE *psf)
|
||||
if (psf->virtual_io)
|
||||
return psf->vio.tell (psf->vio_user_data) ;
|
||||
|
||||
pos = _telli64 (psf->filedes) ;
|
||||
pos = _telli64 (psf->file.filedes) ;
|
||||
|
||||
if (pos == ((sf_count_t) -1))
|
||||
{ psf_log_syserr (psf, errno) ;
|
||||
@@ -1352,13 +1373,13 @@ psf_ftell (SF_PRIVATE *psf)
|
||||
psf_fclose (SF_PRIVATE *psf)
|
||||
{ int retval ;
|
||||
|
||||
while ((retval = close (psf->filedes)) == -1 && errno == EINTR)
|
||||
while ((retval = close (psf->file.filedes)) == -1 && errno == EINTR)
|
||||
/* Do nothing. */ ;
|
||||
|
||||
if (retval == -1)
|
||||
psf_log_syserr (psf, errno) ;
|
||||
|
||||
psf->filedes = -1 ;
|
||||
psf->file.filedes = -1 ;
|
||||
|
||||
return retval ;
|
||||
} /* psf_fclose */
|
||||
@@ -1369,7 +1390,7 @@ psf_fgets (char *buffer, sf_count_t bufsize, SF_PRIVATE *psf)
|
||||
sf_count_t count ;
|
||||
|
||||
while (k < bufsize - 1)
|
||||
{ count = read (psf->filedes, &(buffer [k]), 1) ;
|
||||
{ count = read (psf->file.filedes, &(buffer [k]), 1) ;
|
||||
|
||||
if (count == -1)
|
||||
{ if (errno == EINTR)
|
||||
@@ -1396,7 +1417,7 @@ psf_is_pipe (SF_PRIVATE *psf)
|
||||
return SF_FALSE ;
|
||||
|
||||
/* Not sure if this works. */
|
||||
if (fstat (psf->filedes, &statbuf) == -1)
|
||||
if (fstat (psf->file.filedes, &statbuf) == -1)
|
||||
{ psf_log_syserr (psf, errno) ;
|
||||
/* Default to maximum safety. */
|
||||
return SF_TRUE ;
|
||||
@@ -1420,7 +1441,7 @@ psf_get_filelen (SF_PRIVATE *psf)
|
||||
*/
|
||||
struct _stati64 statbuf ;
|
||||
|
||||
if (_fstati64 (psf->filedes, &statbuf))
|
||||
if (_fstati64 (psf->file.filedes, &statbuf))
|
||||
{ psf_log_syserr (psf, errno) ;
|
||||
return (sf_count_t) -1 ;
|
||||
} ;
|
||||
@@ -1432,7 +1453,7 @@ psf_get_filelen (SF_PRIVATE *psf)
|
||||
if (psf->virtual_io)
|
||||
return psf->vio.get_filelen (psf->vio_user_data) ;
|
||||
|
||||
if ((current = _telli64 (psf->filedes)) < 0)
|
||||
if ((current = _telli64 (psf->file.filedes)) < 0)
|
||||
{ psf_log_syserr (psf, errno) ;
|
||||
return (sf_count_t) -1 ;
|
||||
} ;
|
||||
@@ -1450,17 +1471,17 @@ psf_get_filelen (SF_PRIVATE *psf)
|
||||
** by libsndfile and changing the license to GPL at the same time.
|
||||
*/
|
||||
|
||||
_lseeki64 (psf->filedes, 0, SEEK_END) ;
|
||||
_lseeki64 (psf->file.filedes, 0, SEEK_END) ;
|
||||
|
||||
if ((filelen = _lseeki64 (psf->filedes, 0, SEEK_END)) < 0)
|
||||
if ((filelen = _lseeki64 (psf->file.filedes, 0, SEEK_END)) < 0)
|
||||
{ psf_log_syserr (psf, errno) ;
|
||||
return (sf_count_t) -1 ;
|
||||
} ;
|
||||
|
||||
if (filelen > current)
|
||||
_lseeki64 (psf->filedes, current, SEEK_SET) ;
|
||||
_lseeki64 (psf->file.filedes, current, SEEK_SET) ;
|
||||
|
||||
switch (psf->mode)
|
||||
switch (psf->file.mode)
|
||||
{ case SFM_WRITE :
|
||||
filelen = filelen - psf->fileoffset ;
|
||||
break ;
|
||||
@@ -1504,7 +1525,7 @@ psf_ftruncate (SF_PRIVATE *psf, sf_count_t len)
|
||||
if (len > 0x7FFFFFFF)
|
||||
return -1 ;
|
||||
|
||||
retval = chsize (psf->filedes, len) ;
|
||||
retval = chsize (psf->file.filedes, len) ;
|
||||
|
||||
if (retval == -1)
|
||||
psf_log_syserr (psf, errno) ;
|
||||
|
||||
+135
-66
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** Copyright (C) 2004-2009 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
** Copyright (C) 2004-2013 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
** Copyright (C) 2004 Tobias Gehrig <tgehrig@ira.uka.de>
|
||||
**
|
||||
** This program is free software ; you can redistribute it and/or modify
|
||||
@@ -35,12 +35,12 @@
|
||||
#include <FLAC/stream_encoder.h>
|
||||
#include <FLAC/metadata.h>
|
||||
|
||||
#include "sfendian.h"
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
** Private static functions.
|
||||
*/
|
||||
|
||||
#define FLAC_DEFAULT_COMPRESSION_LEVEL 5
|
||||
|
||||
#define ENC_BUFFER_SIZE 8192
|
||||
|
||||
typedef enum
|
||||
@@ -69,6 +69,8 @@ typedef struct
|
||||
|
||||
const FLAC__Frame *frame ;
|
||||
FLAC__bool bufferbackup ;
|
||||
|
||||
unsigned compression ;
|
||||
} FLAC_PRIVATE ;
|
||||
|
||||
typedef struct
|
||||
@@ -77,6 +79,7 @@ typedef struct
|
||||
} FLAC_TAG ;
|
||||
|
||||
static sf_count_t flac_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) ;
|
||||
static int flac_byterate (SF_PRIVATE *psf) ;
|
||||
static int flac_close (SF_PRIVATE *psf) ;
|
||||
|
||||
static int flac_enc_init (SF_PRIVATE *psf) ;
|
||||
@@ -122,10 +125,6 @@ static FLAC__StreamEncoderSeekStatus sf_flac_enc_seek_callback (const FLAC__Stre
|
||||
static FLAC__StreamEncoderTellStatus sf_flac_enc_tell_callback (const FLAC__StreamEncoder *encoder, FLAC__uint64 *absolute_byte_offset, void *client_data) ;
|
||||
static FLAC__StreamEncoderWriteStatus sf_flac_enc_write_callback (const FLAC__StreamEncoder *encoder, const FLAC__byte buffer [], size_t bytes, unsigned samples, unsigned current_frame, void *client_data) ;
|
||||
|
||||
static const int legal_sample_rates [] =
|
||||
{ 8000, 16000, 22050, 24000, 32000, 44100, 48000, 96000
|
||||
} ;
|
||||
|
||||
static void
|
||||
s2flac8_array (const short *src, FLAC__int32 *dest, int count)
|
||||
{ while (--count >= 0)
|
||||
@@ -153,8 +152,8 @@ i2flac8_array (const int *src, FLAC__int32 *dest, int count)
|
||||
static void
|
||||
i2flac16_array (const int *src, FLAC__int32 *dest, int count)
|
||||
{
|
||||
while (--count >= 0)
|
||||
dest [count] = src [count] >> 16 ;
|
||||
while (--count >= 0)
|
||||
dest [count] = src [count] >> 16 ;
|
||||
} /* i2flac16_array */
|
||||
|
||||
static void
|
||||
@@ -306,7 +305,7 @@ sf_flac_read_callback (const FLAC__StreamDecoder * UNUSED (decoder), FLAC__byte
|
||||
if (*bytes > 0 && psf->error == 0)
|
||||
return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE ;
|
||||
|
||||
return FLAC__STREAM_DECODER_READ_STATUS_ABORT ;
|
||||
return FLAC__STREAM_DECODER_READ_STATUS_ABORT ;
|
||||
} /* sf_flac_read_callback */
|
||||
|
||||
static FLAC__StreamDecoderSeekStatus
|
||||
@@ -348,7 +347,7 @@ sf_flac_eof_callback (const FLAC__StreamDecoder *UNUSED (decoder), void *client_
|
||||
if (psf_ftell (psf) == psf->filelength)
|
||||
return SF_TRUE ;
|
||||
|
||||
return SF_FALSE ;
|
||||
return SF_FALSE ;
|
||||
} /* sf_flac_eof_callback */
|
||||
|
||||
static FLAC__StreamDecoderWriteStatus
|
||||
@@ -377,7 +376,9 @@ sf_flac_meta_get_vorbiscomments (SF_PRIVATE *psf, const FLAC__StreamMetadata *me
|
||||
{ "comment", SF_STR_COMMENT },
|
||||
{ "date", SF_STR_DATE },
|
||||
{ "album", SF_STR_ALBUM },
|
||||
{ "license", SF_STR_LICENSE }
|
||||
{ "license", SF_STR_LICENSE },
|
||||
{ "tracknumber", SF_STR_TRACKNUMBER },
|
||||
{ "genre", SF_STR_GENRE }
|
||||
} ;
|
||||
|
||||
const char *value, *cptr ;
|
||||
@@ -411,7 +412,14 @@ sf_flac_meta_callback (const FLAC__StreamDecoder * UNUSED (decoder), const FLAC_
|
||||
psf->sf.samplerate = metadata->data.stream_info.sample_rate ;
|
||||
psf->sf.frames = metadata->data.stream_info.total_samples ;
|
||||
|
||||
psf_log_printf (psf, "FLAC Stream Metadata\n Channels : %d\n Sample rate : %d\n Frames : %D\n", psf->sf.channels, psf->sf.samplerate, psf->sf.frames) ;
|
||||
psf_log_printf (psf, "FLAC Stream Metadata\n Channels : %d\n Sample rate : %d\n", psf->sf.channels, psf->sf.samplerate) ;
|
||||
|
||||
if (psf->sf.frames == 0)
|
||||
{ psf_log_printf (psf, " Frames : 0 (bumping to SF_COUNT_MAX)\n") ;
|
||||
psf->sf.frames = SF_COUNT_MAX ;
|
||||
}
|
||||
else
|
||||
psf_log_printf (psf, " Frames : %D\n", psf->sf.frames) ;
|
||||
|
||||
switch (metadata->data.stream_info.bits_per_sample)
|
||||
{ case 8 :
|
||||
@@ -501,7 +509,7 @@ sf_flac_enc_seek_callback (const FLAC__StreamEncoder * UNUSED (encoder), FLAC__u
|
||||
if (psf->error)
|
||||
return FLAC__STREAM_ENCODER_SEEK_STATUS_ERROR ;
|
||||
|
||||
return FLAC__STREAM_ENCODER_SEEK_STATUS_OK ;
|
||||
return FLAC__STREAM_ENCODER_SEEK_STATUS_OK ;
|
||||
} /* sf_flac_enc_seek_callback */
|
||||
|
||||
static FLAC__StreamEncoderTellStatus
|
||||
@@ -531,7 +539,7 @@ flac_write_strings (SF_PRIVATE *psf, FLAC_PRIVATE* pflac)
|
||||
int k, string_count = 0 ;
|
||||
|
||||
for (k = 0 ; k < SF_MAX_STRINGS ; k++)
|
||||
{ if (psf->strings [k].type != 0)
|
||||
{ if (psf->strings.data [k].type != 0)
|
||||
string_count ++ ;
|
||||
} ;
|
||||
|
||||
@@ -543,10 +551,10 @@ flac_write_strings (SF_PRIVATE *psf, FLAC_PRIVATE* pflac)
|
||||
return ;
|
||||
} ;
|
||||
|
||||
for (k = 0 ; k < SF_MAX_STRINGS && psf->strings [k].type != 0 ; k++)
|
||||
for (k = 0 ; k < SF_MAX_STRINGS && psf->strings.data [k].type != 0 ; k++)
|
||||
{ const char * key, * value ;
|
||||
|
||||
switch (psf->strings [k].type)
|
||||
switch (psf->strings.data [k].type)
|
||||
{ case SF_STR_SOFTWARE :
|
||||
key = "software" ;
|
||||
break ;
|
||||
@@ -571,11 +579,17 @@ flac_write_strings (SF_PRIVATE *psf, FLAC_PRIVATE* pflac)
|
||||
case SF_STR_LICENSE :
|
||||
key = "license" ;
|
||||
break ;
|
||||
case SF_STR_TRACKNUMBER :
|
||||
key = "tracknumber" ;
|
||||
break ;
|
||||
case SF_STR_GENRE :
|
||||
key = "genre" ;
|
||||
break ;
|
||||
default :
|
||||
continue ;
|
||||
} ;
|
||||
|
||||
value = psf->strings [k].str ;
|
||||
value = psf->strings.storage + psf->strings.data [k].offset ;
|
||||
|
||||
FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair (&entry, key, value) ;
|
||||
FLAC__metadata_object_vorbiscomment_append_comment (pflac->metadata, entry, /* copy */ SF_FALSE) ;
|
||||
@@ -620,24 +634,28 @@ flac_open (SF_PRIVATE *psf)
|
||||
FLAC_PRIVATE* pflac = calloc (1, sizeof (FLAC_PRIVATE)) ;
|
||||
psf->codec_data = pflac ;
|
||||
|
||||
if (psf->mode == SFM_RDWR)
|
||||
/* Set the default value here. Over-ridden later if necessary. */
|
||||
pflac->compression = FLAC_DEFAULT_COMPRESSION_LEVEL ;
|
||||
|
||||
|
||||
if (psf->file.mode == SFM_RDWR)
|
||||
return SFE_BAD_MODE_RW ;
|
||||
|
||||
if (psf->mode == SFM_READ)
|
||||
if (psf->file.mode == SFM_READ)
|
||||
{ if ((error = flac_read_header (psf)))
|
||||
return error ;
|
||||
} ;
|
||||
|
||||
subformat = SF_CODEC (psf->sf.format) ;
|
||||
|
||||
if (psf->mode == SFM_WRITE)
|
||||
if (psf->file.mode == SFM_WRITE)
|
||||
{ if ((SF_CONTAINER (psf->sf.format)) != SF_FORMAT_FLAC)
|
||||
return SFE_BAD_OPEN_FORMAT ;
|
||||
|
||||
psf->endian = SF_ENDIAN_BIG ;
|
||||
psf->sf.seekable = 0 ;
|
||||
|
||||
psf->str_flags = SF_STR_ALLOW_START ;
|
||||
psf->strings.flags = SF_STR_ALLOW_START ;
|
||||
|
||||
if ((error = flac_enc_init (psf)))
|
||||
return error ;
|
||||
@@ -647,14 +665,12 @@ flac_open (SF_PRIVATE *psf)
|
||||
|
||||
psf->datalength = psf->filelength ;
|
||||
psf->dataoffset = 0 ;
|
||||
psf->blockwidth = 0 ;
|
||||
psf->bytewidth = 1 ;
|
||||
|
||||
psf->container_close = flac_close ;
|
||||
psf->seek = flac_seek ;
|
||||
psf->command = flac_command ;
|
||||
psf->byterate = flac_byterate ;
|
||||
|
||||
psf->blockwidth = psf->bytewidth * psf->sf.channels ;
|
||||
psf->command = flac_command ;
|
||||
|
||||
switch (subformat)
|
||||
{ case SF_FORMAT_PCM_S8 : /* 8-bit FLAC. */
|
||||
@@ -683,7 +699,7 @@ flac_close (SF_PRIVATE *psf)
|
||||
if (pflac->metadata != NULL)
|
||||
FLAC__metadata_object_delete (pflac->metadata) ;
|
||||
|
||||
if (psf->mode == SFM_WRITE)
|
||||
if (psf->file.mode == SFM_WRITE)
|
||||
{ FLAC__stream_encoder_finish (pflac->fse) ;
|
||||
FLAC__stream_encoder_delete (pflac->fse) ;
|
||||
|
||||
@@ -691,7 +707,7 @@ flac_close (SF_PRIVATE *psf)
|
||||
free (pflac->encbuffer) ;
|
||||
} ;
|
||||
|
||||
if (psf->mode == SFM_READ)
|
||||
if (psf->file.mode == SFM_READ)
|
||||
{ FLAC__stream_decoder_finish (pflac->fsd) ;
|
||||
FLAC__stream_decoder_delete (pflac->fsd) ;
|
||||
} ;
|
||||
@@ -709,17 +725,16 @@ static int
|
||||
flac_enc_init (SF_PRIVATE *psf)
|
||||
{ FLAC_PRIVATE* pflac = (FLAC_PRIVATE*) psf->codec_data ;
|
||||
unsigned bps ;
|
||||
int k, found ;
|
||||
|
||||
found = 0 ;
|
||||
for (k = 0 ; k < ARRAY_LEN (legal_sample_rates) ; k++)
|
||||
if (psf->sf.samplerate == legal_sample_rates [k])
|
||||
{ found = 1 ;
|
||||
break ;
|
||||
} ;
|
||||
|
||||
if (found == 0)
|
||||
/* To cite the flac FAQ at
|
||||
** http://flac.sourceforge.net/faq.html#general__samples
|
||||
** "FLAC supports linear sample rates from 1Hz - 655350Hz in 1Hz
|
||||
** increments."
|
||||
*/
|
||||
if (psf->sf.samplerate < 1 || psf->sf.samplerate > 655350)
|
||||
{ psf_log_printf (psf, "flac sample rate out of range.\n", psf->sf.samplerate) ;
|
||||
return SFE_FLAC_BAD_SAMPLE_RATE ;
|
||||
} ;
|
||||
|
||||
psf_fseek (psf, 0, SEEK_SET) ;
|
||||
|
||||
@@ -739,6 +754,8 @@ flac_enc_init (SF_PRIVATE *psf)
|
||||
break ;
|
||||
} ;
|
||||
|
||||
if (pflac->fse)
|
||||
FLAC__stream_encoder_delete (pflac->fse) ;
|
||||
if ((pflac->fse = FLAC__stream_encoder_new ()) == NULL)
|
||||
return SFE_FLAC_NEW_DECODER ;
|
||||
|
||||
@@ -757,6 +774,11 @@ flac_enc_init (SF_PRIVATE *psf)
|
||||
return SFE_FLAC_INIT_DECODER ;
|
||||
} ;
|
||||
|
||||
if (! FLAC__stream_encoder_set_compression_level (pflac->fse, pflac->compression))
|
||||
{ psf_log_printf (psf, "FLAC__stream_encoder_set_compression_level (%d) return false.\n", pflac->compression) ;
|
||||
return SFE_FLAC_INIT_DECODER ;
|
||||
} ;
|
||||
|
||||
return 0 ;
|
||||
} /* flac_enc_init */
|
||||
|
||||
@@ -765,6 +787,8 @@ flac_read_header (SF_PRIVATE *psf)
|
||||
{ FLAC_PRIVATE* pflac = (FLAC_PRIVATE*) psf->codec_data ;
|
||||
|
||||
psf_fseek (psf, 0, SEEK_SET) ;
|
||||
if (pflac->fsd)
|
||||
FLAC__stream_decoder_delete (pflac->fsd) ;
|
||||
if ((pflac->fsd = FLAC__stream_decoder_new ()) == NULL)
|
||||
return SFE_FLAC_NEW_DECODER ;
|
||||
|
||||
@@ -788,34 +812,59 @@ flac_read_header (SF_PRIVATE *psf)
|
||||
} /* flac_read_header */
|
||||
|
||||
static int
|
||||
flac_command (SF_PRIVATE * UNUSED (psf), int UNUSED (command), void * UNUSED (data), int UNUSED (datasize))
|
||||
{
|
||||
return 0 ;
|
||||
flac_command (SF_PRIVATE * psf, int command, void * data, int datasize)
|
||||
{ FLAC_PRIVATE* pflac = (FLAC_PRIVATE*) psf->codec_data ;
|
||||
double quality ;
|
||||
|
||||
switch (command)
|
||||
{ case SFC_SET_COMPRESSION_LEVEL :
|
||||
if (data == NULL || datasize != sizeof (double))
|
||||
return SF_FALSE ;
|
||||
|
||||
if (psf->have_written)
|
||||
return SF_FALSE ;
|
||||
|
||||
/* FLAC compression level is in the range [0, 8] while libsndfile takes
|
||||
** values in the range [0.0, 1.0]. Massage the libsndfile value here.
|
||||
*/
|
||||
quality = (*((double *) data)) * 8.0 ;
|
||||
/* Clip range. */
|
||||
pflac->compression = lrint (SF_MAX (0.0, SF_MIN (8.0, quality))) ;
|
||||
|
||||
psf_log_printf (psf, "%s : Setting SFC_SET_COMPRESSION_LEVEL to %u.\n", __func__, pflac->compression) ;
|
||||
|
||||
if (flac_enc_init (psf))
|
||||
return SF_FALSE ;
|
||||
|
||||
return SF_TRUE ;
|
||||
|
||||
default :
|
||||
return SF_FALSE ;
|
||||
} ;
|
||||
|
||||
return SF_FALSE ;
|
||||
} /* flac_command */
|
||||
|
||||
int
|
||||
flac_init (SF_PRIVATE *psf)
|
||||
{
|
||||
if (psf->mode == SFM_RDWR)
|
||||
if (psf->file.mode == SFM_RDWR)
|
||||
return SFE_BAD_MODE_RW ;
|
||||
|
||||
if (psf->mode == SFM_READ)
|
||||
if (psf->file.mode == SFM_READ)
|
||||
{ psf->read_short = flac_read_flac2s ;
|
||||
psf->read_int = flac_read_flac2i ;
|
||||
psf->read_float = flac_read_flac2f ;
|
||||
psf->read_double = flac_read_flac2d ;
|
||||
} ;
|
||||
|
||||
if (psf->mode == SFM_WRITE)
|
||||
if (psf->file.mode == SFM_WRITE)
|
||||
{ psf->write_short = flac_write_s2flac ;
|
||||
psf->write_int = flac_write_i2flac ;
|
||||
psf->write_float = flac_write_f2flac ;
|
||||
psf->write_double = flac_write_d2flac ;
|
||||
} ;
|
||||
|
||||
psf->bytewidth = 1 ;
|
||||
psf->blockwidth = psf->sf.channels ;
|
||||
|
||||
if (psf->filelength > psf->dataoffset)
|
||||
psf->datalength = (psf->dataend) ? psf->dataend - psf->dataoffset : psf->filelength - psf->dataoffset ;
|
||||
else
|
||||
@@ -954,7 +1003,7 @@ flac_write_s2flac (SF_PRIVATE *psf, const short *ptr, sf_count_t len)
|
||||
while (len > 0)
|
||||
{ writecount = (len >= bufferlen) ? bufferlen : (int) len ;
|
||||
convert (ptr + total, buffer, writecount) ;
|
||||
if (FLAC__stream_encoder_process_interleaved (pflac->fse, buffer, writecount/psf->sf.channels))
|
||||
if (FLAC__stream_encoder_process_interleaved (pflac->fse, buffer, writecount / psf->sf.channels))
|
||||
thiswrite = writecount ;
|
||||
else
|
||||
break ;
|
||||
@@ -996,7 +1045,7 @@ flac_write_i2flac (SF_PRIVATE *psf, const int *ptr, sf_count_t len)
|
||||
while (len > 0)
|
||||
{ writecount = (len >= bufferlen) ? bufferlen : (int) len ;
|
||||
convert (ptr + total, buffer, writecount) ;
|
||||
if (FLAC__stream_encoder_process_interleaved (pflac->fse, buffer, writecount/psf->sf.channels))
|
||||
if (FLAC__stream_encoder_process_interleaved (pflac->fse, buffer, writecount / psf->sf.channels))
|
||||
thiswrite = writecount ;
|
||||
else
|
||||
break ;
|
||||
@@ -1038,7 +1087,7 @@ flac_write_f2flac (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
|
||||
while (len > 0)
|
||||
{ writecount = (len >= bufferlen) ? bufferlen : (int) len ;
|
||||
convert (ptr + total, buffer, writecount, psf->norm_float) ;
|
||||
if (FLAC__stream_encoder_process_interleaved (pflac->fse, buffer, writecount/psf->sf.channels))
|
||||
if (FLAC__stream_encoder_process_interleaved (pflac->fse, buffer, writecount / psf->sf.channels))
|
||||
thiswrite = writecount ;
|
||||
else
|
||||
break ;
|
||||
@@ -1076,23 +1125,22 @@ f2flac8_clip_array (const float *src, FLAC__int32 *dest, int count, int normaliz
|
||||
|
||||
static void
|
||||
f2flac16_clip_array (const float *src, FLAC__int32 *dest, int count, int normalize)
|
||||
{
|
||||
float normfact, scaled_value ;
|
||||
{ float normfact, scaled_value ;
|
||||
|
||||
normfact = normalize ? (8.0 * 0x1000) : 1.0 ;
|
||||
normfact = normalize ? (8.0 * 0x1000) : 1.0 ;
|
||||
|
||||
while (--count >= 0) {
|
||||
scaled_value = src [count] * normfact ;
|
||||
if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFF)) {
|
||||
dest [count] = 0x7FFF ;
|
||||
continue ;
|
||||
}
|
||||
if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x1000)) {
|
||||
dest [count] = 0x8000 ;
|
||||
continue ;
|
||||
}
|
||||
dest [count] = lrintf (scaled_value) ;
|
||||
}
|
||||
while (--count >= 0)
|
||||
{ scaled_value = src [count] * normfact ;
|
||||
if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFF))
|
||||
{ dest [count] = 0x7FFF ;
|
||||
continue ;
|
||||
} ;
|
||||
if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x1000))
|
||||
{ dest [count] = 0x8000 ;
|
||||
continue ;
|
||||
} ;
|
||||
dest [count] = lrintf (scaled_value) ;
|
||||
} ;
|
||||
} /* f2flac16_clip_array */
|
||||
|
||||
static void
|
||||
@@ -1170,7 +1218,7 @@ flac_write_d2flac (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
|
||||
while (len > 0)
|
||||
{ writecount = (len >= bufferlen) ? bufferlen : (int) len ;
|
||||
convert (ptr + total, buffer, writecount, psf->norm_double) ;
|
||||
if (FLAC__stream_encoder_process_interleaved (pflac->fse, buffer, writecount/psf->sf.channels))
|
||||
if (FLAC__stream_encoder_process_interleaved (pflac->fse, buffer, writecount / psf->sf.channels))
|
||||
thiswrite = writecount ;
|
||||
else
|
||||
break ;
|
||||
@@ -1288,13 +1336,24 @@ flac_seek (SF_PRIVATE *psf, int UNUSED (mode), sf_count_t offset)
|
||||
|
||||
pflac->frame = NULL ;
|
||||
|
||||
if (psf->mode == SFM_READ)
|
||||
if (psf->file.mode == SFM_READ)
|
||||
{ FLAC__uint64 position ;
|
||||
|
||||
if (FLAC__stream_decoder_seek_absolute (pflac->fsd, offset))
|
||||
{ FLAC__stream_decoder_get_decode_position (pflac->fsd, &position) ;
|
||||
return offset ;
|
||||
} ;
|
||||
|
||||
if (offset == psf->sf.frames)
|
||||
{ /*
|
||||
** If we've been asked to seek to the very end of the file, libFLAC
|
||||
** will return an error. However, we know the length of the file so
|
||||
** instead of returning an error, we can return the offset.
|
||||
*/
|
||||
return offset ;
|
||||
} ;
|
||||
|
||||
psf->error = SFE_BAD_SEEK ;
|
||||
return ((sf_count_t) -1) ;
|
||||
} ;
|
||||
|
||||
@@ -1304,6 +1363,16 @@ flac_seek (SF_PRIVATE *psf, int UNUSED (mode), sf_count_t offset)
|
||||
return ((sf_count_t) -1) ;
|
||||
} /* flac_seek */
|
||||
|
||||
static int
|
||||
flac_byterate (SF_PRIVATE *psf)
|
||||
{
|
||||
if (psf->file.mode == SFM_READ)
|
||||
return (psf->datalength * psf->sf.samplerate) / psf->sf.frames ;
|
||||
|
||||
return -1 ;
|
||||
} /* flac_byterate */
|
||||
|
||||
|
||||
#else /* HAVE_EXTERNAL_LIBS */
|
||||
|
||||
int
|
||||
|
||||
+115
-99
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** Copyright (C) 1999-2009 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
** Copyright (C) 1999-2012 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
@@ -92,7 +92,7 @@ float32_init (SF_PRIVATE *psf)
|
||||
|
||||
psf->blockwidth = sizeof (float) * psf->sf.channels ;
|
||||
|
||||
if (psf->mode == SFM_READ || psf->mode == SFM_RDWR)
|
||||
if (psf->file.mode == SFM_READ || psf->file.mode == SFM_RDWR)
|
||||
{ switch (psf->endian + float_caps)
|
||||
{ case (SF_ENDIAN_BIG + FLOAT_CAN_RW_BE) :
|
||||
psf->data_endswap = SF_FALSE ;
|
||||
@@ -163,7 +163,7 @@ float32_init (SF_PRIVATE *psf)
|
||||
} ;
|
||||
} ;
|
||||
|
||||
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
|
||||
if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
|
||||
{ switch (psf->endian + float_caps)
|
||||
{ case (SF_ENDIAN_LITTLE + FLOAT_CAN_RW_LE) :
|
||||
psf->data_endswap = SF_FALSE ;
|
||||
@@ -241,13 +241,13 @@ float32_init (SF_PRIVATE *psf)
|
||||
else
|
||||
psf->datalength = 0 ;
|
||||
|
||||
psf->sf.frames = psf->datalength / psf->blockwidth ;
|
||||
psf->sf.frames = psf->blockwidth > 0 ? psf->datalength / psf->blockwidth : 0 ;
|
||||
|
||||
return 0 ;
|
||||
} /* float32_init */
|
||||
|
||||
float
|
||||
float32_be_read (unsigned char *cptr)
|
||||
float32_be_read (const unsigned char *cptr)
|
||||
{ int exponent, mantissa, negative ;
|
||||
float fvalue ;
|
||||
|
||||
@@ -275,7 +275,7 @@ float32_be_read (unsigned char *cptr)
|
||||
} /* float32_be_read */
|
||||
|
||||
float
|
||||
float32_le_read (unsigned char *cptr)
|
||||
float32_le_read (const unsigned char *cptr)
|
||||
{ int exponent, mantissa, negative ;
|
||||
float fvalue ;
|
||||
|
||||
@@ -444,7 +444,7 @@ f2s_clip_array (const float *src, int count, short *dest, float scale)
|
||||
|
||||
if (CPU_CLIPS_POSITIVE == 0 && tmp > 32767.0)
|
||||
dest [count] = SHRT_MAX ;
|
||||
else if (CPU_CLIPS_NEGATIVE == 0 && tmp < 32768.0)
|
||||
else if (CPU_CLIPS_NEGATIVE == 0 && tmp < -32768.0)
|
||||
dest [count] = SHRT_MIN ;
|
||||
else
|
||||
dest [count] = lrintf (tmp) ;
|
||||
@@ -505,25 +505,26 @@ d2f_array (const double *src, float *dest, int count)
|
||||
|
||||
static sf_count_t
|
||||
host_read_f2s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
|
||||
{ void (*convert) (const float *, int, short *, float) ;
|
||||
{ BUF_UNION ubuf ;
|
||||
void (*convert) (const float *, int, short *, float) ;
|
||||
int bufferlen, readcount ;
|
||||
sf_count_t total = 0 ;
|
||||
float scale ;
|
||||
|
||||
convert = (psf->add_clipping) ? f2s_clip_array : f2s_array ;
|
||||
bufferlen = ARRAY_LEN (psf->u.fbuf) ;
|
||||
bufferlen = ARRAY_LEN (ubuf.fbuf) ;
|
||||
scale = (psf->float_int_mult == 0) ? 1.0 : 0x7FFF / psf->float_max ;
|
||||
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
readcount = psf_fread (psf->u.fbuf, sizeof (float), bufferlen, psf) ;
|
||||
readcount = psf_fread (ubuf.fbuf, sizeof (float), bufferlen, psf) ;
|
||||
|
||||
/* Fix me : Need lef2s_array */
|
||||
if (psf->data_endswap == SF_TRUE)
|
||||
endswap_int_array (psf->u.ibuf, bufferlen) ;
|
||||
endswap_int_array (ubuf.ibuf, bufferlen) ;
|
||||
|
||||
f2s_array (psf->u.fbuf, readcount, ptr + total, scale) ;
|
||||
convert (ubuf.fbuf, readcount, ptr + total, scale) ;
|
||||
total += readcount ;
|
||||
if (readcount < bufferlen)
|
||||
break ;
|
||||
@@ -535,24 +536,25 @@ host_read_f2s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
|
||||
|
||||
static sf_count_t
|
||||
host_read_f2i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
|
||||
{ void (*convert) (const float *, int, int *, float) ;
|
||||
{ BUF_UNION ubuf ;
|
||||
void (*convert) (const float *, int, int *, float) ;
|
||||
int bufferlen, readcount ;
|
||||
sf_count_t total = 0 ;
|
||||
float scale ;
|
||||
|
||||
convert = (psf->add_clipping) ? f2i_clip_array : f2i_array ;
|
||||
bufferlen = ARRAY_LEN (psf->u.fbuf) ;
|
||||
bufferlen = ARRAY_LEN (ubuf.fbuf) ;
|
||||
scale = (psf->float_int_mult == 0) ? 1.0 : 0x7FFFFFFF / psf->float_max ;
|
||||
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
readcount = psf_fread (psf->u.fbuf, sizeof (float), bufferlen, psf) ;
|
||||
readcount = psf_fread (ubuf.fbuf, sizeof (float), bufferlen, psf) ;
|
||||
|
||||
if (psf->data_endswap == SF_TRUE)
|
||||
endswap_int_array (psf->u.ibuf, bufferlen) ;
|
||||
endswap_int_array (ubuf.ibuf, bufferlen) ;
|
||||
|
||||
convert (psf->u.fbuf, readcount, ptr + total, scale) ;
|
||||
convert (ubuf.fbuf, readcount, ptr + total, scale) ;
|
||||
total += readcount ;
|
||||
if (readcount < bufferlen)
|
||||
break ;
|
||||
@@ -564,20 +566,21 @@ host_read_f2i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
|
||||
|
||||
static sf_count_t
|
||||
host_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
|
||||
{ int bufferlen, readcount ;
|
||||
{ BUF_UNION ubuf ;
|
||||
int bufferlen, readcount ;
|
||||
sf_count_t total = 0 ;
|
||||
|
||||
if (psf->data_endswap != SF_TRUE)
|
||||
return psf_fread (ptr, sizeof (float), len, psf) ;
|
||||
|
||||
bufferlen = ARRAY_LEN (psf->u.fbuf) ;
|
||||
bufferlen = ARRAY_LEN (ubuf.fbuf) ;
|
||||
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
readcount = psf_fread (psf->u.fbuf, sizeof (float), bufferlen, psf) ;
|
||||
readcount = psf_fread (ubuf.fbuf, sizeof (float), bufferlen, psf) ;
|
||||
|
||||
endswap_int_copy ((int*) (ptr + total), psf->u.ibuf, readcount) ;
|
||||
endswap_int_copy ((int*) (ptr + total), ubuf.ibuf, readcount) ;
|
||||
|
||||
total += readcount ;
|
||||
if (readcount < bufferlen)
|
||||
@@ -590,21 +593,22 @@ host_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
|
||||
|
||||
static sf_count_t
|
||||
host_read_f2d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
|
||||
{ int bufferlen, readcount ;
|
||||
{ BUF_UNION ubuf ;
|
||||
int bufferlen, readcount ;
|
||||
sf_count_t total = 0 ;
|
||||
|
||||
bufferlen = ARRAY_LEN (psf->u.fbuf) ;
|
||||
bufferlen = ARRAY_LEN (ubuf.fbuf) ;
|
||||
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
readcount = psf_fread (psf->u.fbuf, sizeof (float), bufferlen, psf) ;
|
||||
readcount = psf_fread (ubuf.fbuf, sizeof (float), bufferlen, psf) ;
|
||||
|
||||
if (psf->data_endswap == SF_TRUE)
|
||||
endswap_int_array (psf->u.ibuf, bufferlen) ;
|
||||
endswap_int_array (ubuf.ibuf, bufferlen) ;
|
||||
|
||||
/* Fix me : Need lef2d_array */
|
||||
f2d_array (psf->u.fbuf, readcount, ptr + total) ;
|
||||
f2d_array (ubuf.fbuf, readcount, ptr + total) ;
|
||||
total += readcount ;
|
||||
if (readcount < bufferlen)
|
||||
break ;
|
||||
@@ -616,26 +620,27 @@ host_read_f2d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
|
||||
|
||||
static sf_count_t
|
||||
host_write_s2f (SF_PRIVATE *psf, const short *ptr, sf_count_t len)
|
||||
{ int bufferlen, writecount ;
|
||||
{ BUF_UNION ubuf ;
|
||||
int bufferlen, writecount ;
|
||||
sf_count_t total = 0 ;
|
||||
float scale ;
|
||||
|
||||
/* Erik */
|
||||
scale = (psf->scale_int_float == 0) ? 1.0 : 1.0 / 0x8000 ;
|
||||
bufferlen = ARRAY_LEN (psf->u.fbuf) ;
|
||||
bufferlen = ARRAY_LEN (ubuf.fbuf) ;
|
||||
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
s2f_array (ptr + total, psf->u.fbuf, bufferlen, scale) ;
|
||||
s2f_array (ptr + total, ubuf.fbuf, bufferlen, scale) ;
|
||||
|
||||
if (psf->peak_info)
|
||||
float32_peak_update (psf, psf->u.fbuf, bufferlen, total / psf->sf.channels) ;
|
||||
float32_peak_update (psf, ubuf.fbuf, bufferlen, total / psf->sf.channels) ;
|
||||
|
||||
if (psf->data_endswap == SF_TRUE)
|
||||
endswap_int_array (psf->u.ibuf, bufferlen) ;
|
||||
endswap_int_array (ubuf.ibuf, bufferlen) ;
|
||||
|
||||
writecount = psf_fwrite (psf->u.fbuf, sizeof (float), bufferlen, psf) ;
|
||||
writecount = psf_fwrite (ubuf.fbuf, sizeof (float), bufferlen, psf) ;
|
||||
total += writecount ;
|
||||
if (writecount < bufferlen)
|
||||
break ;
|
||||
@@ -647,25 +652,26 @@ host_write_s2f (SF_PRIVATE *psf, const short *ptr, sf_count_t len)
|
||||
|
||||
static sf_count_t
|
||||
host_write_i2f (SF_PRIVATE *psf, const int *ptr, sf_count_t len)
|
||||
{ int bufferlen, writecount ;
|
||||
{ BUF_UNION ubuf ;
|
||||
int bufferlen, writecount ;
|
||||
sf_count_t total = 0 ;
|
||||
float scale ;
|
||||
|
||||
scale = (psf->scale_int_float == 0) ? 1.0 : 1.0 / (8.0 * 0x10000000) ;
|
||||
bufferlen = ARRAY_LEN (psf->u.fbuf) ;
|
||||
bufferlen = ARRAY_LEN (ubuf.fbuf) ;
|
||||
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
i2f_array (ptr + total, psf->u.fbuf, bufferlen, scale) ;
|
||||
i2f_array (ptr + total, ubuf.fbuf, bufferlen, scale) ;
|
||||
|
||||
if (psf->peak_info)
|
||||
float32_peak_update (psf, psf->u.fbuf, bufferlen, total / psf->sf.channels) ;
|
||||
float32_peak_update (psf, ubuf.fbuf, bufferlen, total / psf->sf.channels) ;
|
||||
|
||||
if (psf->data_endswap == SF_TRUE)
|
||||
endswap_int_array (psf->u.ibuf, bufferlen) ;
|
||||
endswap_int_array (ubuf.ibuf, bufferlen) ;
|
||||
|
||||
writecount = psf_fwrite (psf->u.fbuf, sizeof (float) , bufferlen, psf) ;
|
||||
writecount = psf_fwrite (ubuf.fbuf, sizeof (float) , bufferlen, psf) ;
|
||||
total += writecount ;
|
||||
if (writecount < bufferlen)
|
||||
break ;
|
||||
@@ -677,7 +683,8 @@ host_write_i2f (SF_PRIVATE *psf, const int *ptr, sf_count_t len)
|
||||
|
||||
static sf_count_t
|
||||
host_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
|
||||
{ int bufferlen, writecount ;
|
||||
{ BUF_UNION ubuf ;
|
||||
int bufferlen, writecount ;
|
||||
sf_count_t total = 0 ;
|
||||
|
||||
if (psf->peak_info)
|
||||
@@ -686,15 +693,15 @@ host_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
|
||||
if (psf->data_endswap != SF_TRUE)
|
||||
return psf_fwrite (ptr, sizeof (float), len, psf) ;
|
||||
|
||||
bufferlen = ARRAY_LEN (psf->u.fbuf) ;
|
||||
bufferlen = ARRAY_LEN (ubuf.fbuf) ;
|
||||
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
|
||||
endswap_int_copy (psf->u.ibuf, (const int*) (ptr + total), bufferlen) ;
|
||||
endswap_int_copy (ubuf.ibuf, (const int*) (ptr + total), bufferlen) ;
|
||||
|
||||
writecount = psf_fwrite (psf->u.fbuf, sizeof (float), bufferlen, psf) ;
|
||||
writecount = psf_fwrite (ubuf.fbuf, sizeof (float), bufferlen, psf) ;
|
||||
total += writecount ;
|
||||
if (writecount < bufferlen)
|
||||
break ;
|
||||
@@ -706,24 +713,25 @@ host_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
|
||||
|
||||
static sf_count_t
|
||||
host_write_d2f (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
|
||||
{ int bufferlen, writecount ;
|
||||
{ BUF_UNION ubuf ;
|
||||
int bufferlen, writecount ;
|
||||
sf_count_t total = 0 ;
|
||||
|
||||
bufferlen = ARRAY_LEN (psf->u.fbuf) ;
|
||||
bufferlen = ARRAY_LEN (ubuf.fbuf) ;
|
||||
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
|
||||
d2f_array (ptr + total, psf->u.fbuf, bufferlen) ;
|
||||
d2f_array (ptr + total, ubuf.fbuf, bufferlen) ;
|
||||
|
||||
if (psf->peak_info)
|
||||
float32_peak_update (psf, psf->u.fbuf, bufferlen, total / psf->sf.channels) ;
|
||||
float32_peak_update (psf, ubuf.fbuf, bufferlen, total / psf->sf.channels) ;
|
||||
|
||||
if (psf->data_endswap == SF_TRUE)
|
||||
endswap_int_array (psf->u.ibuf, bufferlen) ;
|
||||
endswap_int_array (ubuf.ibuf, bufferlen) ;
|
||||
|
||||
writecount = psf_fwrite (psf->u.fbuf, sizeof (float), bufferlen, psf) ;
|
||||
writecount = psf_fwrite (ubuf.fbuf, sizeof (float), bufferlen, psf) ;
|
||||
total += writecount ;
|
||||
if (writecount < bufferlen)
|
||||
break ;
|
||||
@@ -738,24 +746,25 @@ host_write_d2f (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
|
||||
|
||||
static sf_count_t
|
||||
replace_read_f2s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
|
||||
{ int bufferlen, readcount ;
|
||||
{ BUF_UNION ubuf ;
|
||||
int bufferlen, readcount ;
|
||||
sf_count_t total = 0 ;
|
||||
float scale ;
|
||||
|
||||
bufferlen = ARRAY_LEN (psf->u.fbuf) ;
|
||||
bufferlen = ARRAY_LEN (ubuf.fbuf) ;
|
||||
scale = (psf->float_int_mult == 0) ? 1.0 : 0x7FFF / psf->float_max ;
|
||||
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
readcount = psf_fread (psf->u.fbuf, sizeof (float), bufferlen, psf) ;
|
||||
readcount = psf_fread (ubuf.fbuf, sizeof (float), bufferlen, psf) ;
|
||||
|
||||
if (psf->data_endswap == SF_TRUE)
|
||||
endswap_int_array (psf->u.ibuf, bufferlen) ;
|
||||
endswap_int_array (ubuf.ibuf, bufferlen) ;
|
||||
|
||||
bf2f_array (psf->u.fbuf, bufferlen) ;
|
||||
bf2f_array (ubuf.fbuf, bufferlen) ;
|
||||
|
||||
f2s_array (psf->u.fbuf, readcount, ptr + total, scale) ;
|
||||
f2s_array (ubuf.fbuf, readcount, ptr + total, scale) ;
|
||||
total += readcount ;
|
||||
if (readcount < bufferlen)
|
||||
break ;
|
||||
@@ -767,24 +776,25 @@ replace_read_f2s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
|
||||
|
||||
static sf_count_t
|
||||
replace_read_f2i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
|
||||
{ int bufferlen, readcount ;
|
||||
{ BUF_UNION ubuf ;
|
||||
int bufferlen, readcount ;
|
||||
sf_count_t total = 0 ;
|
||||
float scale ;
|
||||
|
||||
bufferlen = ARRAY_LEN (psf->u.fbuf) ;
|
||||
bufferlen = ARRAY_LEN (ubuf.fbuf) ;
|
||||
scale = (psf->float_int_mult == 0) ? 1.0 : 0x7FFF / psf->float_max ;
|
||||
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
readcount = psf_fread (psf->u.fbuf, sizeof (float), bufferlen, psf) ;
|
||||
readcount = psf_fread (ubuf.fbuf, sizeof (float), bufferlen, psf) ;
|
||||
|
||||
if (psf->data_endswap == SF_TRUE)
|
||||
endswap_int_array (psf->u.ibuf, bufferlen) ;
|
||||
endswap_int_array (ubuf.ibuf, bufferlen) ;
|
||||
|
||||
bf2f_array (psf->u.fbuf, bufferlen) ;
|
||||
bf2f_array (ubuf.fbuf, bufferlen) ;
|
||||
|
||||
f2i_array (psf->u.fbuf, readcount, ptr + total, scale) ;
|
||||
f2i_array (ubuf.fbuf, readcount, ptr + total, scale) ;
|
||||
total += readcount ;
|
||||
if (readcount < bufferlen)
|
||||
break ;
|
||||
@@ -796,24 +806,25 @@ replace_read_f2i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
|
||||
|
||||
static sf_count_t
|
||||
replace_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
|
||||
{ int bufferlen, readcount ;
|
||||
{ BUF_UNION ubuf ;
|
||||
int bufferlen, readcount ;
|
||||
sf_count_t total = 0 ;
|
||||
|
||||
/* FIX THIS */
|
||||
|
||||
bufferlen = ARRAY_LEN (psf->u.fbuf) ;
|
||||
bufferlen = ARRAY_LEN (ubuf.fbuf) ;
|
||||
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
readcount = psf_fread (psf->u.fbuf, sizeof (float), bufferlen, psf) ;
|
||||
readcount = psf_fread (ubuf.fbuf, sizeof (float), bufferlen, psf) ;
|
||||
|
||||
if (psf->data_endswap == SF_TRUE)
|
||||
endswap_int_array (psf->u.ibuf, bufferlen) ;
|
||||
endswap_int_array (ubuf.ibuf, bufferlen) ;
|
||||
|
||||
bf2f_array (psf->u.fbuf, bufferlen) ;
|
||||
bf2f_array (ubuf.fbuf, bufferlen) ;
|
||||
|
||||
memcpy (ptr + total, psf->u.fbuf, bufferlen * sizeof (float)) ;
|
||||
memcpy (ptr + total, ubuf.fbuf, bufferlen * sizeof (float)) ;
|
||||
|
||||
total += readcount ;
|
||||
if (readcount < bufferlen)
|
||||
@@ -826,22 +837,23 @@ replace_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
|
||||
|
||||
static sf_count_t
|
||||
replace_read_f2d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
|
||||
{ int bufferlen, readcount ;
|
||||
{ BUF_UNION ubuf ;
|
||||
int bufferlen, readcount ;
|
||||
sf_count_t total = 0 ;
|
||||
|
||||
bufferlen = ARRAY_LEN (psf->u.fbuf) ;
|
||||
bufferlen = ARRAY_LEN (ubuf.fbuf) ;
|
||||
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
readcount = psf_fread (psf->u.fbuf, sizeof (float), bufferlen, psf) ;
|
||||
readcount = psf_fread (ubuf.fbuf, sizeof (float), bufferlen, psf) ;
|
||||
|
||||
if (psf->data_endswap == SF_TRUE)
|
||||
endswap_int_array (psf->u.ibuf, bufferlen) ;
|
||||
endswap_int_array (ubuf.ibuf, bufferlen) ;
|
||||
|
||||
bf2f_array (psf->u.fbuf, bufferlen) ;
|
||||
bf2f_array (ubuf.fbuf, bufferlen) ;
|
||||
|
||||
f2d_array (psf->u.fbuf, readcount, ptr + total) ;
|
||||
f2d_array (ubuf.fbuf, readcount, ptr + total) ;
|
||||
total += readcount ;
|
||||
if (readcount < bufferlen)
|
||||
break ;
|
||||
@@ -853,27 +865,28 @@ replace_read_f2d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
|
||||
|
||||
static sf_count_t
|
||||
replace_write_s2f (SF_PRIVATE *psf, const short *ptr, sf_count_t len)
|
||||
{ int bufferlen, writecount ;
|
||||
{ BUF_UNION ubuf ;
|
||||
int bufferlen, writecount ;
|
||||
sf_count_t total = 0 ;
|
||||
float scale ;
|
||||
|
||||
scale = (psf->scale_int_float == 0) ? 1.0 : 1.0 / 0x8000 ;
|
||||
bufferlen = ARRAY_LEN (psf->u.fbuf) ;
|
||||
bufferlen = ARRAY_LEN (ubuf.fbuf) ;
|
||||
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
s2f_array (ptr + total, psf->u.fbuf, bufferlen, scale) ;
|
||||
s2f_array (ptr + total, ubuf.fbuf, bufferlen, scale) ;
|
||||
|
||||
if (psf->peak_info)
|
||||
float32_peak_update (psf, psf->u.fbuf, bufferlen, total / psf->sf.channels) ;
|
||||
float32_peak_update (psf, ubuf.fbuf, bufferlen, total / psf->sf.channels) ;
|
||||
|
||||
f2bf_array (psf->u.fbuf, bufferlen) ;
|
||||
f2bf_array (ubuf.fbuf, bufferlen) ;
|
||||
|
||||
if (psf->data_endswap == SF_TRUE)
|
||||
endswap_int_array (psf->u.ibuf, bufferlen) ;
|
||||
endswap_int_array (ubuf.ibuf, bufferlen) ;
|
||||
|
||||
writecount = psf_fwrite (psf->u.fbuf, sizeof (float), bufferlen, psf) ;
|
||||
writecount = psf_fwrite (ubuf.fbuf, sizeof (float), bufferlen, psf) ;
|
||||
total += writecount ;
|
||||
if (writecount < bufferlen)
|
||||
break ;
|
||||
@@ -885,27 +898,28 @@ replace_write_s2f (SF_PRIVATE *psf, const short *ptr, sf_count_t len)
|
||||
|
||||
static sf_count_t
|
||||
replace_write_i2f (SF_PRIVATE *psf, const int *ptr, sf_count_t len)
|
||||
{ int bufferlen, writecount ;
|
||||
{ BUF_UNION ubuf ;
|
||||
int bufferlen, writecount ;
|
||||
sf_count_t total = 0 ;
|
||||
float scale ;
|
||||
|
||||
scale = (psf->scale_int_float == 0) ? 1.0 : 1.0 / (8.0 * 0x10000000) ;
|
||||
bufferlen = ARRAY_LEN (psf->u.fbuf) ;
|
||||
bufferlen = ARRAY_LEN (ubuf.fbuf) ;
|
||||
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
i2f_array (ptr + total, psf->u.fbuf, bufferlen, scale) ;
|
||||
i2f_array (ptr + total, ubuf.fbuf, bufferlen, scale) ;
|
||||
|
||||
if (psf->peak_info)
|
||||
float32_peak_update (psf, psf->u.fbuf, bufferlen, total / psf->sf.channels) ;
|
||||
float32_peak_update (psf, ubuf.fbuf, bufferlen, total / psf->sf.channels) ;
|
||||
|
||||
f2bf_array (psf->u.fbuf, bufferlen) ;
|
||||
f2bf_array (ubuf.fbuf, bufferlen) ;
|
||||
|
||||
if (psf->data_endswap == SF_TRUE)
|
||||
endswap_int_array (psf->u.ibuf, bufferlen) ;
|
||||
endswap_int_array (ubuf.ibuf, bufferlen) ;
|
||||
|
||||
writecount = psf_fwrite (psf->u.fbuf, sizeof (float), bufferlen, psf) ;
|
||||
writecount = psf_fwrite (ubuf.fbuf, sizeof (float), bufferlen, psf) ;
|
||||
total += writecount ;
|
||||
if (writecount < bufferlen)
|
||||
break ;
|
||||
@@ -917,27 +931,28 @@ replace_write_i2f (SF_PRIVATE *psf, const int *ptr, sf_count_t len)
|
||||
|
||||
static sf_count_t
|
||||
replace_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
|
||||
{ int bufferlen, writecount ;
|
||||
{ BUF_UNION ubuf ;
|
||||
int bufferlen, writecount ;
|
||||
sf_count_t total = 0 ;
|
||||
|
||||
/* FIX THIS */
|
||||
if (psf->peak_info)
|
||||
float32_peak_update (psf, ptr, len, 0) ;
|
||||
|
||||
bufferlen = ARRAY_LEN (psf->u.fbuf) ;
|
||||
bufferlen = ARRAY_LEN (ubuf.fbuf) ;
|
||||
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
|
||||
memcpy (psf->u.fbuf, ptr + total, bufferlen * sizeof (float)) ;
|
||||
memcpy (ubuf.fbuf, ptr + total, bufferlen * sizeof (float)) ;
|
||||
|
||||
f2bf_array (psf->u.fbuf, bufferlen) ;
|
||||
f2bf_array (ubuf.fbuf, bufferlen) ;
|
||||
|
||||
if (psf->data_endswap == SF_TRUE)
|
||||
endswap_int_array (psf->u.ibuf, bufferlen) ;
|
||||
endswap_int_array (ubuf.ibuf, bufferlen) ;
|
||||
|
||||
writecount = psf_fwrite (psf->u.fbuf, sizeof (float) , bufferlen, psf) ;
|
||||
writecount = psf_fwrite (ubuf.fbuf, sizeof (float) , bufferlen, psf) ;
|
||||
total += writecount ;
|
||||
if (writecount < bufferlen)
|
||||
break ;
|
||||
@@ -949,25 +964,26 @@ replace_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
|
||||
|
||||
static sf_count_t
|
||||
replace_write_d2f (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
|
||||
{ int bufferlen, writecount ;
|
||||
{ BUF_UNION ubuf ;
|
||||
int bufferlen, writecount ;
|
||||
sf_count_t total = 0 ;
|
||||
|
||||
bufferlen = ARRAY_LEN (psf->u.fbuf) ;
|
||||
bufferlen = ARRAY_LEN (ubuf.fbuf) ;
|
||||
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
d2f_array (ptr + total, psf->u.fbuf, bufferlen) ;
|
||||
d2f_array (ptr + total, ubuf.fbuf, bufferlen) ;
|
||||
|
||||
if (psf->peak_info)
|
||||
float32_peak_update (psf, psf->u.fbuf, bufferlen, total / psf->sf.channels) ;
|
||||
float32_peak_update (psf, ubuf.fbuf, bufferlen, total / psf->sf.channels) ;
|
||||
|
||||
f2bf_array (psf->u.fbuf, bufferlen) ;
|
||||
f2bf_array (ubuf.fbuf, bufferlen) ;
|
||||
|
||||
if (psf->data_endswap == SF_TRUE)
|
||||
endswap_int_array (psf->u.ibuf, bufferlen) ;
|
||||
endswap_int_array (ubuf.ibuf, bufferlen) ;
|
||||
|
||||
writecount = psf_fwrite (psf->u.fbuf, sizeof (float), bufferlen, psf) ;
|
||||
writecount = psf_fwrite (ubuf.fbuf, sizeof (float), bufferlen, psf) ;
|
||||
total += writecount ;
|
||||
if (writecount < bufferlen)
|
||||
break ;
|
||||
|
||||
+27
-23
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** Copyright (C) 1999-2009 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
** Copyright (C) 1999-2012 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
@@ -112,8 +112,6 @@ g72x_init (SF_PRIVATE * psf)
|
||||
default : return SFE_UNIMPLEMENTED ;
|
||||
} ;
|
||||
|
||||
psf->blockwidth = psf->bytewidth = 1 ;
|
||||
|
||||
psf->filelength = psf_get_filelen (psf) ;
|
||||
if (psf->filelength < psf->dataoffset)
|
||||
psf->filelength = psf->dataoffset ;
|
||||
@@ -122,7 +120,7 @@ g72x_init (SF_PRIVATE * psf)
|
||||
if (psf->dataend > 0)
|
||||
psf->datalength -= psf->filelength - psf->dataend ;
|
||||
|
||||
if (psf->mode == SFM_READ)
|
||||
if (psf->file.mode == SFM_READ)
|
||||
{ pg72x->private = g72x_reader_init (codec, &(pg72x->blocksize), &(pg72x->samplesperblock)) ;
|
||||
if (pg72x->private == NULL)
|
||||
return SFE_MALLOC_FAILED ;
|
||||
@@ -134,7 +132,7 @@ g72x_init (SF_PRIVATE * psf)
|
||||
psf->read_float = g72x_read_f ;
|
||||
psf->read_double = g72x_read_d ;
|
||||
|
||||
psf->seek = g72x_seek ;
|
||||
psf->seek = g72x_seek ;
|
||||
|
||||
if (psf->datalength % pg72x->blocksize)
|
||||
{ psf_log_printf (psf, "*** Odd psf->datalength (%D) should be a multiple of %d\n", psf->datalength, pg72x->blocksize) ;
|
||||
@@ -147,7 +145,7 @@ g72x_init (SF_PRIVATE * psf)
|
||||
|
||||
psf_g72x_decode_block (psf, pg72x) ;
|
||||
}
|
||||
else if (psf->mode == SFM_WRITE)
|
||||
else if (psf->file.mode == SFM_WRITE)
|
||||
{ pg72x->private = g72x_writer_init (codec, &(pg72x->blocksize), &(pg72x->samplesperblock)) ;
|
||||
if (pg72x->private == NULL)
|
||||
return SFE_MALLOC_FAILED ;
|
||||
@@ -253,7 +251,8 @@ g72x_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
|
||||
|
||||
static sf_count_t
|
||||
g72x_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
|
||||
{ G72x_PRIVATE *pg72x ;
|
||||
{ BUF_UNION ubuf ;
|
||||
G72x_PRIVATE *pg72x ;
|
||||
short *sptr ;
|
||||
int k, bufferlen, readcount = 0, count ;
|
||||
sf_count_t total = 0 ;
|
||||
@@ -262,7 +261,7 @@ g72x_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
|
||||
return 0 ;
|
||||
pg72x = (G72x_PRIVATE*) psf->codec_data ;
|
||||
|
||||
sptr = psf->u.sbuf ;
|
||||
sptr = ubuf.sbuf ;
|
||||
bufferlen = SF_BUFFER_LEN / sizeof (short) ;
|
||||
while (len > 0)
|
||||
{ readcount = (len >= bufferlen) ? bufferlen : len ;
|
||||
@@ -282,7 +281,8 @@ g72x_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
|
||||
|
||||
static sf_count_t
|
||||
g72x_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
|
||||
{ G72x_PRIVATE *pg72x ;
|
||||
{ BUF_UNION ubuf ;
|
||||
G72x_PRIVATE *pg72x ;
|
||||
short *sptr ;
|
||||
int k, bufferlen, readcount = 0, count ;
|
||||
sf_count_t total = 0 ;
|
||||
@@ -294,7 +294,7 @@ g72x_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
|
||||
|
||||
normfact = (psf->norm_float == SF_TRUE) ? 1.0 / ((float) 0x8000) : 1.0 ;
|
||||
|
||||
sptr = psf->u.sbuf ;
|
||||
sptr = ubuf.sbuf ;
|
||||
bufferlen = SF_BUFFER_LEN / sizeof (short) ;
|
||||
while (len > 0)
|
||||
{ readcount = (len >= bufferlen) ? bufferlen : len ;
|
||||
@@ -313,7 +313,8 @@ g72x_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
|
||||
|
||||
static sf_count_t
|
||||
g72x_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
|
||||
{ G72x_PRIVATE *pg72x ;
|
||||
{ BUF_UNION ubuf ;
|
||||
G72x_PRIVATE *pg72x ;
|
||||
short *sptr ;
|
||||
int k, bufferlen, readcount = 0, count ;
|
||||
sf_count_t total = 0 ;
|
||||
@@ -325,7 +326,7 @@ g72x_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
|
||||
|
||||
normfact = (psf->norm_double == SF_TRUE) ? 1.0 / ((double) 0x8000) : 1.0 ;
|
||||
|
||||
sptr = psf->u.sbuf ;
|
||||
sptr = ubuf.sbuf ;
|
||||
bufferlen = SF_BUFFER_LEN / sizeof (short) ;
|
||||
while (len > 0)
|
||||
{ readcount = (len >= bufferlen) ? bufferlen : len ;
|
||||
@@ -401,7 +402,7 @@ g72x_seek (SF_PRIVATE *psf, int UNUSED (mode), sf_count_t UNUSED (offset))
|
||||
** return PSF_SEEK_ERROR ;
|
||||
** } ;
|
||||
**
|
||||
** if (psf->mode == SFM_READ)
|
||||
** if (psf->file.mode == SFM_READ)
|
||||
** { psf_fseek (psf, psf->dataoffset + newblock * pg72x->blocksize, SEEK_SET) ;
|
||||
** pg72x->block_curr = newblock ;
|
||||
** psf_g72x_decode_block (psf, pg72x) ;
|
||||
@@ -491,7 +492,8 @@ g72x_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len)
|
||||
|
||||
static sf_count_t
|
||||
g72x_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len)
|
||||
{ G72x_PRIVATE *pg72x ;
|
||||
{ BUF_UNION ubuf ;
|
||||
G72x_PRIVATE *pg72x ;
|
||||
short *sptr ;
|
||||
int k, bufferlen, writecount = 0, count ;
|
||||
sf_count_t total = 0 ;
|
||||
@@ -500,8 +502,8 @@ g72x_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len)
|
||||
return 0 ;
|
||||
pg72x = (G72x_PRIVATE*) psf->codec_data ;
|
||||
|
||||
sptr = psf->u.sbuf ;
|
||||
bufferlen = ((SF_BUFFER_LEN / psf->blockwidth) * psf->blockwidth) / sizeof (short) ;
|
||||
sptr = ubuf.sbuf ;
|
||||
bufferlen = SF_BUFFER_LEN / sizeof (short) ;
|
||||
while (len > 0)
|
||||
{ writecount = (len >= bufferlen) ? bufferlen : len ;
|
||||
for (k = 0 ; k < writecount ; k++)
|
||||
@@ -518,7 +520,8 @@ g72x_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len)
|
||||
|
||||
static sf_count_t
|
||||
g72x_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
|
||||
{ G72x_PRIVATE *pg72x ;
|
||||
{ BUF_UNION ubuf ;
|
||||
G72x_PRIVATE *pg72x ;
|
||||
short *sptr ;
|
||||
int k, bufferlen, writecount = 0, count ;
|
||||
sf_count_t total = 0 ;
|
||||
@@ -530,8 +533,8 @@ g72x_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
|
||||
|
||||
normfact = (psf->norm_float == SF_TRUE) ? (1.0 * 0x8000) : 1.0 ;
|
||||
|
||||
sptr = psf->u.sbuf ;
|
||||
bufferlen = ((SF_BUFFER_LEN / psf->blockwidth) * psf->blockwidth) / sizeof (short) ;
|
||||
sptr = ubuf.sbuf ;
|
||||
bufferlen = SF_BUFFER_LEN / sizeof (short) ;
|
||||
while (len > 0)
|
||||
{ writecount = (len >= bufferlen) ? bufferlen : len ;
|
||||
for (k = 0 ; k < writecount ; k++)
|
||||
@@ -549,7 +552,8 @@ g72x_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
|
||||
|
||||
static sf_count_t
|
||||
g72x_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
|
||||
{ G72x_PRIVATE *pg72x ;
|
||||
{ BUF_UNION ubuf ;
|
||||
G72x_PRIVATE *pg72x ;
|
||||
short *sptr ;
|
||||
int k, bufferlen, writecount = 0, count ;
|
||||
sf_count_t total = 0 ;
|
||||
@@ -561,8 +565,8 @@ g72x_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
|
||||
|
||||
normfact = (psf->norm_double == SF_TRUE) ? (1.0 * 0x8000) : 1.0 ;
|
||||
|
||||
sptr = psf->u.sbuf ;
|
||||
bufferlen = ((SF_BUFFER_LEN / psf->blockwidth) * psf->blockwidth) / sizeof (short) ;
|
||||
sptr = ubuf.sbuf ;
|
||||
bufferlen = SF_BUFFER_LEN / sizeof (short) ;
|
||||
while (len > 0)
|
||||
{ writecount = (len >= bufferlen) ? bufferlen : len ;
|
||||
for (k = 0 ; k < writecount ; k++)
|
||||
@@ -584,7 +588,7 @@ g72x_close (SF_PRIVATE *psf)
|
||||
|
||||
pg72x = (G72x_PRIVATE*) psf->codec_data ;
|
||||
|
||||
if (psf->mode == SFM_WRITE)
|
||||
if (psf->file.mode == SFM_WRITE)
|
||||
{ /* If a block has been partially assembled, write it out
|
||||
** as the final block.
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** Copyright (C) 1999-2009 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
** Copyright (C) 1999-2012 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
@@ -84,7 +84,7 @@ gsm610_init (SF_PRIVATE *psf)
|
||||
return SFE_INTERNAL ;
|
||||
} ;
|
||||
|
||||
if (psf->mode == SFM_RDWR)
|
||||
if (psf->file.mode == SFM_RDWR)
|
||||
return SFE_BAD_MODE_RW ;
|
||||
|
||||
psf->sf.seekable = SF_FALSE ;
|
||||
@@ -132,7 +132,7 @@ Need separate gsm_data structs for encode and decode.
|
||||
break ;
|
||||
} ;
|
||||
|
||||
if (psf->mode == SFM_READ)
|
||||
if (psf->file.mode == SFM_READ)
|
||||
{ if (psf->datalength % pgsm610->blocksize == 0)
|
||||
pgsm610->blocks = psf->datalength / pgsm610->blocksize ;
|
||||
else if (psf->datalength % pgsm610->blocksize == 1 && pgsm610->blocksize == GSM610_BLOCKSIZE)
|
||||
@@ -162,7 +162,7 @@ Need separate gsm_data structs for encode and decode.
|
||||
psf->read_double = gsm610_read_d ;
|
||||
} ;
|
||||
|
||||
if (psf->mode == SFM_WRITE)
|
||||
if (psf->file.mode == SFM_WRITE)
|
||||
{ pgsm610->blockcount = 0 ;
|
||||
pgsm610->samplecount = 0 ;
|
||||
|
||||
@@ -194,7 +194,7 @@ gsm610_wav_decode_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610)
|
||||
pgsm610->samplecount = 0 ;
|
||||
|
||||
if (pgsm610->blockcount > pgsm610->blocks)
|
||||
{ memset (pgsm610->samples, 0, WAV_W64_GSM610_SAMPLES * sizeof (short)) ;
|
||||
{ memset (pgsm610->samples, 0, sizeof (pgsm610->samples)) ;
|
||||
return 1 ;
|
||||
} ;
|
||||
|
||||
@@ -222,7 +222,7 @@ gsm610_decode_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610)
|
||||
pgsm610->samplecount = 0 ;
|
||||
|
||||
if (pgsm610->blockcount > pgsm610->blocks)
|
||||
{ memset (pgsm610->samples, 0, GSM610_SAMPLES * sizeof (short)) ;
|
||||
{ memset (pgsm610->samples, 0, sizeof (pgsm610->samples)) ;
|
||||
return 1 ;
|
||||
} ;
|
||||
|
||||
@@ -243,7 +243,7 @@ gsm610_read_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610, short *ptr, int len
|
||||
|
||||
while (indx < len)
|
||||
{ if (pgsm610->blockcount >= pgsm610->blocks && pgsm610->samplecount >= pgsm610->samplesperblock)
|
||||
{ memset (&(ptr [indx]), 0, (len - indx) * sizeof (short)) ;
|
||||
{ memset (ptr + indx, 0, (len - indx) * sizeof (short)) ;
|
||||
return total ;
|
||||
} ;
|
||||
|
||||
@@ -290,6 +290,7 @@ gsm610_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
|
||||
static sf_count_t
|
||||
gsm610_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
|
||||
{ GSM610_PRIVATE *pgsm610 ;
|
||||
BUF_UNION ubuf ;
|
||||
short *sptr ;
|
||||
int k, bufferlen, readcount = 0, count ;
|
||||
sf_count_t total = 0 ;
|
||||
@@ -298,8 +299,8 @@ gsm610_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
|
||||
return 0 ;
|
||||
pgsm610 = (GSM610_PRIVATE*) psf->codec_data ;
|
||||
|
||||
sptr = psf->u.sbuf ;
|
||||
bufferlen = ARRAY_LEN (psf->u.sbuf) ;
|
||||
sptr = ubuf.sbuf ;
|
||||
bufferlen = ARRAY_LEN (ubuf.sbuf) ;
|
||||
while (len > 0)
|
||||
{ readcount = (len >= bufferlen) ? bufferlen : len ;
|
||||
count = gsm610_read_block (psf, pgsm610, sptr, readcount) ;
|
||||
@@ -315,6 +316,7 @@ gsm610_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
|
||||
static sf_count_t
|
||||
gsm610_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
|
||||
{ GSM610_PRIVATE *pgsm610 ;
|
||||
BUF_UNION ubuf ;
|
||||
short *sptr ;
|
||||
int k, bufferlen, readcount = 0, count ;
|
||||
sf_count_t total = 0 ;
|
||||
@@ -326,8 +328,8 @@ gsm610_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
|
||||
|
||||
normfact = (psf->norm_float == SF_TRUE) ? 1.0 / ((float) 0x8000) : 1.0 ;
|
||||
|
||||
sptr = psf->u.sbuf ;
|
||||
bufferlen = ARRAY_LEN (psf->u.sbuf) ;
|
||||
sptr = ubuf.sbuf ;
|
||||
bufferlen = ARRAY_LEN (ubuf.sbuf) ;
|
||||
while (len > 0)
|
||||
{ readcount = (len >= bufferlen) ? bufferlen : len ;
|
||||
count = gsm610_read_block (psf, pgsm610, sptr, readcount) ;
|
||||
@@ -343,6 +345,7 @@ gsm610_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
|
||||
static sf_count_t
|
||||
gsm610_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
|
||||
{ GSM610_PRIVATE *pgsm610 ;
|
||||
BUF_UNION ubuf ;
|
||||
short *sptr ;
|
||||
int k, bufferlen, readcount = 0, count ;
|
||||
sf_count_t total = 0 ;
|
||||
@@ -354,8 +357,8 @@ gsm610_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
|
||||
return 0 ;
|
||||
pgsm610 = (GSM610_PRIVATE*) psf->codec_data ;
|
||||
|
||||
sptr = psf->u.sbuf ;
|
||||
bufferlen = ARRAY_LEN (psf->u.sbuf) ;
|
||||
sptr = ubuf.sbuf ;
|
||||
bufferlen = ARRAY_LEN (ubuf.sbuf) ;
|
||||
while (len > 0)
|
||||
{ readcount = (len >= bufferlen) ? bufferlen : len ;
|
||||
count = gsm610_read_block (psf, pgsm610, sptr, readcount) ;
|
||||
@@ -406,7 +409,7 @@ gsm610_seek (SF_PRIVATE *psf, int UNUSED (mode), sf_count_t offset)
|
||||
newblock = offset / pgsm610->samplesperblock ;
|
||||
newsample = offset % pgsm610->samplesperblock ;
|
||||
|
||||
if (psf->mode == SFM_READ)
|
||||
if (psf->file.mode == SFM_READ)
|
||||
{ if (psf->read_current != newblock * pgsm610->samplesperblock + newsample)
|
||||
{ psf_fseek (psf, psf->dataoffset + newblock * pgsm610->samplesperblock, SEEK_SET) ;
|
||||
pgsm610->blockcount = newblock ;
|
||||
@@ -441,7 +444,7 @@ gsm610_encode_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610)
|
||||
pgsm610->blockcount ++ ;
|
||||
|
||||
/* Set samples to zero for next block. */
|
||||
memset (pgsm610->samples, 0, WAV_W64_GSM610_SAMPLES * sizeof (short)) ;
|
||||
memset (pgsm610->samples, 0, sizeof (pgsm610->samples)) ;
|
||||
|
||||
return 1 ;
|
||||
} /* gsm610_encode_block */
|
||||
@@ -452,7 +455,7 @@ gsm610_wav_encode_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610)
|
||||
|
||||
/* Encode the samples. */
|
||||
gsm_encode (pgsm610->gsm_data, pgsm610->samples, pgsm610->block) ;
|
||||
gsm_encode (pgsm610->gsm_data, pgsm610->samples+WAV_W64_GSM610_SAMPLES/2, pgsm610->block+WAV_W64_GSM610_BLOCKSIZE/2) ;
|
||||
gsm_encode (pgsm610->gsm_data, pgsm610->samples+WAV_W64_GSM610_SAMPLES / 2, pgsm610->block+WAV_W64_GSM610_BLOCKSIZE / 2) ;
|
||||
|
||||
/* Write the block to disk. */
|
||||
if ((k = psf_fwrite (pgsm610->block, 1, WAV_W64_GSM610_BLOCKSIZE, psf)) != WAV_W64_GSM610_BLOCKSIZE)
|
||||
@@ -462,7 +465,7 @@ gsm610_wav_encode_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610)
|
||||
pgsm610->blockcount ++ ;
|
||||
|
||||
/* Set samples to zero for next block. */
|
||||
memset (pgsm610->samples, 0, WAV_W64_GSM610_SAMPLES * sizeof (short)) ;
|
||||
memset (pgsm610->samples, 0, sizeof (pgsm610->samples)) ;
|
||||
|
||||
return 1 ;
|
||||
} /* gsm610_wav_encode_block */
|
||||
@@ -517,6 +520,7 @@ gsm610_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len)
|
||||
static sf_count_t
|
||||
gsm610_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len)
|
||||
{ GSM610_PRIVATE *pgsm610 ;
|
||||
BUF_UNION ubuf ;
|
||||
short *sptr ;
|
||||
int k, bufferlen, writecount = 0, count ;
|
||||
sf_count_t total = 0 ;
|
||||
@@ -525,8 +529,8 @@ gsm610_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len)
|
||||
return 0 ;
|
||||
pgsm610 = (GSM610_PRIVATE*) psf->codec_data ;
|
||||
|
||||
sptr = psf->u.sbuf ;
|
||||
bufferlen = ARRAY_LEN (psf->u.sbuf) ;
|
||||
sptr = ubuf.sbuf ;
|
||||
bufferlen = ARRAY_LEN (ubuf.sbuf) ;
|
||||
while (len > 0)
|
||||
{ writecount = (len >= bufferlen) ? bufferlen : len ;
|
||||
for (k = 0 ; k < writecount ; k++)
|
||||
@@ -542,6 +546,7 @@ gsm610_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len)
|
||||
static sf_count_t
|
||||
gsm610_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
|
||||
{ GSM610_PRIVATE *pgsm610 ;
|
||||
BUF_UNION ubuf ;
|
||||
short *sptr ;
|
||||
int k, bufferlen, writecount = 0, count ;
|
||||
sf_count_t total = 0 ;
|
||||
@@ -553,8 +558,8 @@ gsm610_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
|
||||
|
||||
normfact = (psf->norm_float == SF_TRUE) ? (1.0 * 0x7FFF) : 1.0 ;
|
||||
|
||||
sptr = psf->u.sbuf ;
|
||||
bufferlen = ARRAY_LEN (psf->u.sbuf) ;
|
||||
sptr = ubuf.sbuf ;
|
||||
bufferlen = ARRAY_LEN (ubuf.sbuf) ;
|
||||
while (len > 0)
|
||||
{ writecount = (len >= bufferlen) ? bufferlen : len ;
|
||||
for (k = 0 ; k < writecount ; k++)
|
||||
@@ -570,6 +575,7 @@ gsm610_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
|
||||
static sf_count_t
|
||||
gsm610_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
|
||||
{ GSM610_PRIVATE *pgsm610 ;
|
||||
BUF_UNION ubuf ;
|
||||
short *sptr ;
|
||||
int k, bufferlen, writecount = 0, count ;
|
||||
sf_count_t total = 0 ;
|
||||
@@ -581,8 +587,8 @@ gsm610_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
|
||||
|
||||
normfact = (psf->norm_double == SF_TRUE) ? (1.0 * 0x7FFF) : 1.0 ;
|
||||
|
||||
sptr = psf->u.sbuf ;
|
||||
bufferlen = ARRAY_LEN (psf->u.sbuf) ;
|
||||
sptr = ubuf.sbuf ;
|
||||
bufferlen = ARRAY_LEN (ubuf.sbuf) ;
|
||||
while (len > 0)
|
||||
{ writecount = (len >= bufferlen) ? bufferlen : len ;
|
||||
for (k = 0 ; k < writecount ; k++)
|
||||
@@ -604,7 +610,7 @@ gsm610_close (SF_PRIVATE *psf)
|
||||
|
||||
pgsm610 = (GSM610_PRIVATE*) psf->codec_data ;
|
||||
|
||||
if (psf->mode == SFM_WRITE)
|
||||
if (psf->file.mode == SFM_WRITE)
|
||||
{ /* If a block has been partially assembled, write it out
|
||||
** as the final block.
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** Copyright (C) 2002-2009 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
** Copyright (C) 2002-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
@@ -55,14 +55,14 @@ htk_open (SF_PRIVATE *psf)
|
||||
if (psf->is_pipe)
|
||||
return SFE_HTK_NO_PIPE ;
|
||||
|
||||
if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->filelength > 0))
|
||||
if (psf->file.mode == SFM_READ || (psf->file.mode == SFM_RDWR && psf->filelength > 0))
|
||||
{ if ((error = htk_read_header (psf)))
|
||||
return error ;
|
||||
} ;
|
||||
|
||||
subformat = SF_CODEC (psf->sf.format) ;
|
||||
|
||||
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
|
||||
if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
|
||||
{ if ((SF_CONTAINER (psf->sf.format)) != SF_FORMAT_HTK)
|
||||
return SFE_BAD_OPEN_FORMAT ;
|
||||
|
||||
@@ -95,7 +95,7 @@ htk_open (SF_PRIVATE *psf)
|
||||
static int
|
||||
htk_close (SF_PRIVATE *psf)
|
||||
{
|
||||
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
|
||||
if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
|
||||
htk_write_header (psf, SF_TRUE) ;
|
||||
|
||||
return 0 ;
|
||||
@@ -195,10 +195,17 @@ htk_read_header (SF_PRIVATE *psf)
|
||||
return SFE_HTK_NOT_WAVEFORM ;
|
||||
|
||||
psf->sf.channels = 1 ;
|
||||
psf->sf.samplerate = 10000000 / sample_period ;
|
||||
|
||||
psf_log_printf (psf, "HTK Waveform file\n Sample Count : %d\n Sample Period : %d => %d Hz\n",
|
||||
sample_count, sample_period, psf->sf.samplerate) ;
|
||||
if (sample_period > 0)
|
||||
{ psf->sf.samplerate = 10000000 / sample_period ;
|
||||
psf_log_printf (psf, "HTK Waveform file\n Sample Count : %d\n Sample Period : %d => %d Hz\n",
|
||||
sample_count, sample_period, psf->sf.samplerate) ;
|
||||
}
|
||||
else
|
||||
{ psf->sf.samplerate = 16000 ;
|
||||
psf_log_printf (psf, "HTK Waveform file\n Sample Count : %d\n Sample Period : %d (should be > 0) => Guessed sample rate %d Hz\n",
|
||||
sample_count, sample_period, psf->sf.samplerate) ;
|
||||
} ;
|
||||
|
||||
psf->sf.format = SF_FORMAT_HTK | SF_FORMAT_PCM_16 ;
|
||||
psf->bytewidth = 2 ;
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
** Copyright (C) 2010-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program 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 program 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 program; if not, write to the Free Software
|
||||
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "sfconfig.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "sndfile.h"
|
||||
#include "sfendian.h"
|
||||
#include "common.h"
|
||||
|
||||
int
|
||||
id3_skip (SF_PRIVATE * psf)
|
||||
{ unsigned char buf [10] ;
|
||||
|
||||
memset (buf, 0, sizeof (buf)) ;
|
||||
psf_binheader_readf (psf, "pb", 0, buf, 10) ;
|
||||
|
||||
if (buf [0] == 'I' && buf [1] == 'D' && buf [2] == '3')
|
||||
{ int offset = buf [6] & 0x7f ;
|
||||
offset = (offset << 7) | (buf [7] & 0x7f) ;
|
||||
offset = (offset << 7) | (buf [8] & 0x7f) ;
|
||||
offset = (offset << 7) | (buf [9] & 0x7f) ;
|
||||
|
||||
psf_log_printf (psf, "ID3 length : %d\n--------------------\n", offset) ;
|
||||
|
||||
/* Never want to jump backwards in a file. */
|
||||
if (offset < 0)
|
||||
return 0 ;
|
||||
|
||||
/* Calculate new file offset and position ourselves there. */
|
||||
psf->fileoffset += offset + 10 ;
|
||||
psf_binheader_readf (psf, "p", psf->fileoffset) ;
|
||||
|
||||
return 1 ;
|
||||
} ;
|
||||
|
||||
return 0 ;
|
||||
} /* id3_skip */
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** Copyright (C) 1999-2009 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
** Copyright (C) 1999-2013 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
@@ -37,11 +37,7 @@ typedef struct IMA_ADPCM_PRIVATE_tag
|
||||
int stepindx [2] ;
|
||||
unsigned char *block ;
|
||||
short *samples ;
|
||||
#if HAVE_FLEXIBLE_ARRAY
|
||||
short data [] ; /* ISO C99 struct flexible array. */
|
||||
#else
|
||||
short data [0] ; /* This is a hack and might not work. */
|
||||
#endif
|
||||
} IMA_ADPCM_PRIVATE ;
|
||||
|
||||
/*============================================================================================
|
||||
@@ -50,9 +46,9 @@ typedef struct IMA_ADPCM_PRIVATE_tag
|
||||
|
||||
static int ima_indx_adjust [16] =
|
||||
{ -1, -1, -1, -1, /* +0 - +3, decrease the step size */
|
||||
2, 4, 6, 8, /* +4 - +7, increase the step size */
|
||||
-1, -1, -1, -1, /* -0 - -3, decrease the step size */
|
||||
2, 4, 6, 8, /* -4 - -7, increase the step size */
|
||||
+2, +4, +6, +8, /* +4 - +7, increase the step size */
|
||||
-1, -1, -1, -1, /* -0 - -3, decrease the step size */
|
||||
+2, +4, +6, +8, /* -4 - -7, increase the step size */
|
||||
} ;
|
||||
|
||||
static int ima_step_size [89] =
|
||||
@@ -116,14 +112,14 @@ wav_w64_ima_init (SF_PRIVATE *psf, int blockalign, int samplesperblock)
|
||||
return SFE_INTERNAL ;
|
||||
} ;
|
||||
|
||||
if (psf->mode == SFM_RDWR)
|
||||
if (psf->file.mode == SFM_RDWR)
|
||||
return SFE_BAD_MODE_RW ;
|
||||
|
||||
if (psf->mode == SFM_READ)
|
||||
if (psf->file.mode == SFM_READ)
|
||||
if ((error = ima_reader_init (psf, blockalign, samplesperblock)))
|
||||
return error ;
|
||||
|
||||
if (psf->mode == SFM_WRITE)
|
||||
if (psf->file.mode == SFM_WRITE)
|
||||
if ((error = ima_writer_init (psf, blockalign)))
|
||||
return error ;
|
||||
|
||||
@@ -137,14 +133,14 @@ int
|
||||
aiff_ima_init (SF_PRIVATE *psf, int blockalign, int samplesperblock)
|
||||
{ int error ;
|
||||
|
||||
if (psf->mode == SFM_RDWR)
|
||||
if (psf->file.mode == SFM_RDWR)
|
||||
return SFE_BAD_MODE_RW ;
|
||||
|
||||
if (psf->mode == SFM_READ)
|
||||
if (psf->file.mode == SFM_READ)
|
||||
if ((error = ima_reader_init (psf, blockalign, samplesperblock)))
|
||||
return error ;
|
||||
|
||||
if (psf->mode == SFM_WRITE)
|
||||
if (psf->file.mode == SFM_WRITE)
|
||||
if ((error = ima_writer_init (psf, blockalign)))
|
||||
return error ;
|
||||
|
||||
@@ -159,7 +155,7 @@ ima_close (SF_PRIVATE *psf)
|
||||
|
||||
pima = (IMA_ADPCM_PRIVATE*) psf->codec_data ;
|
||||
|
||||
if (psf->mode == SFM_WRITE)
|
||||
if (psf->file.mode == SFM_WRITE)
|
||||
{ /* If a block has been partially assembled, write it out
|
||||
** as the final block.
|
||||
*/
|
||||
@@ -181,18 +177,16 @@ ima_reader_init (SF_PRIVATE *psf, int blockalign, int samplesperblock)
|
||||
{ IMA_ADPCM_PRIVATE *pima ;
|
||||
int pimasize, count ;
|
||||
|
||||
if (psf->mode != SFM_READ)
|
||||
if (psf->file.mode != SFM_READ)
|
||||
return SFE_BAD_MODE_RW ;
|
||||
|
||||
pimasize = sizeof (IMA_ADPCM_PRIVATE) + blockalign * psf->sf.channels + 3 * psf->sf.channels * samplesperblock ;
|
||||
|
||||
if (! (pima = malloc (pimasize)))
|
||||
if (! (pima = calloc (1, pimasize)))
|
||||
return SFE_MALLOC_FAILED ;
|
||||
|
||||
psf->codec_data = (void*) pima ;
|
||||
|
||||
memset (pima, 0, pimasize) ;
|
||||
|
||||
pima->samples = pima->data ;
|
||||
pima->block = (unsigned char*) (pima->data + samplesperblock * psf->sf.channels) ;
|
||||
|
||||
@@ -204,7 +198,7 @@ ima_reader_init (SF_PRIVATE *psf, int blockalign, int samplesperblock)
|
||||
psf->datalength = (psf->dataend) ? psf->dataend - psf->dataoffset :
|
||||
psf->filelength - psf->dataoffset ;
|
||||
|
||||
if (pima->blocksize == 0)
|
||||
if (pima->blocksize == 0)
|
||||
{ psf_log_printf (psf, "*** Error : pima->blocksize should not be zero.\n") ;
|
||||
return SFE_INTERNAL ;
|
||||
} ;
|
||||
@@ -238,7 +232,6 @@ ima_reader_init (SF_PRIVATE *psf, int blockalign, int samplesperblock)
|
||||
default :
|
||||
psf_log_printf (psf, "ima_reader_init: bad psf->sf.format\n") ;
|
||||
return SFE_INTERNAL ;
|
||||
break ;
|
||||
} ;
|
||||
|
||||
pima->decode_block (psf, pima) ; /* Read first block. */
|
||||
@@ -254,8 +247,8 @@ ima_reader_init (SF_PRIVATE *psf, int blockalign, int samplesperblock)
|
||||
static int
|
||||
aiff_ima_decode_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima)
|
||||
{ unsigned char *blockdata ;
|
||||
int chan, k, diff, bytecode ;
|
||||
short step, stepindx, predictor, *sampledata ;
|
||||
int chan, k, diff, bytecode, predictor ;
|
||||
short step, stepindx, *sampledata ;
|
||||
|
||||
static int count = 0 ;
|
||||
count ++ ;
|
||||
@@ -307,6 +300,11 @@ count ++ ;
|
||||
if (bytecode & 8) diff = -diff ;
|
||||
|
||||
predictor += diff ;
|
||||
if (predictor < -32768)
|
||||
predictor = -32768 ;
|
||||
else if (predictor > 32767)
|
||||
predictor = 32767 ;
|
||||
|
||||
pima->samples [pima->channels * k + chan] = predictor ;
|
||||
} ;
|
||||
} ;
|
||||
@@ -376,7 +374,7 @@ aiff_ima_encode_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima)
|
||||
{ blockindx = chan * pima->blocksize + 2 + indx / 2 ;
|
||||
|
||||
pima->block [blockindx] = pima->samples [indx] & 0x0F ;
|
||||
pima->block [blockindx] |= (pima->samples [indx + pima->channels] << 4) & 0xF0 ;
|
||||
pima->block [blockindx] |= (pima->samples [indx + chan] << 4) & 0xF0 ;
|
||||
} ;
|
||||
} ;
|
||||
|
||||
@@ -394,7 +392,7 @@ aiff_ima_encode_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima)
|
||||
|
||||
static int
|
||||
wav_w64_ima_decode_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima)
|
||||
{ int chan, k, current, blockindx, indx, indxstart, diff ;
|
||||
{ int chan, k, predictor, blockindx, indx, indxstart, diff ;
|
||||
short step, bytecode, stepindx [2] ;
|
||||
|
||||
pima->blockcount ++ ;
|
||||
@@ -411,9 +409,9 @@ wav_w64_ima_decode_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima)
|
||||
/* Read and check the block header. */
|
||||
|
||||
for (chan = 0 ; chan < pima->channels ; chan++)
|
||||
{ current = pima->block [chan*4] | (pima->block [chan*4+1] << 8) ;
|
||||
if (current & 0x8000)
|
||||
current -= 0x10000 ;
|
||||
{ predictor = pima->block [chan*4] | (pima->block [chan*4+1] << 8) ;
|
||||
if (predictor & 0x8000)
|
||||
predictor -= 0x10000 ;
|
||||
|
||||
stepindx [chan] = pima->block [chan*4+2] ;
|
||||
stepindx [chan] = clamp_ima_step_index (stepindx [chan]) ;
|
||||
@@ -422,7 +420,7 @@ wav_w64_ima_decode_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima)
|
||||
if (pima->block [chan*4+3] != 0)
|
||||
psf_log_printf (psf, "IMA ADPCM synchronisation error.\n") ;
|
||||
|
||||
pima->samples [chan] = current ;
|
||||
pima->samples [chan] = predictor ;
|
||||
} ;
|
||||
|
||||
/*
|
||||
@@ -455,7 +453,7 @@ wav_w64_ima_decode_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima)
|
||||
bytecode = pima->samples [k] & 0xF ;
|
||||
|
||||
step = ima_step_size [stepindx [chan]] ;
|
||||
current = pima->samples [k - pima->channels] ;
|
||||
predictor = pima->samples [k - pima->channels] ;
|
||||
|
||||
diff = step >> 3 ;
|
||||
if (bytecode & 1)
|
||||
@@ -467,17 +465,17 @@ wav_w64_ima_decode_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima)
|
||||
if (bytecode & 8)
|
||||
diff = -diff ;
|
||||
|
||||
current += diff ;
|
||||
predictor += diff ;
|
||||
|
||||
if (current > 32767)
|
||||
current = 32767 ;
|
||||
else if (current < -32768)
|
||||
current = -32768 ;
|
||||
if (predictor > 32767)
|
||||
predictor = 32767 ;
|
||||
else if (predictor < -32768)
|
||||
predictor = -32768 ;
|
||||
|
||||
stepindx [chan] += ima_indx_adjust [bytecode] ;
|
||||
stepindx [chan] = clamp_ima_step_index (stepindx [chan]) ;
|
||||
|
||||
pima->samples [k] = current ;
|
||||
pima->samples [k] = predictor ;
|
||||
} ;
|
||||
|
||||
return 1 ;
|
||||
@@ -623,6 +621,7 @@ ima_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
|
||||
static sf_count_t
|
||||
ima_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
|
||||
{ IMA_ADPCM_PRIVATE *pima ;
|
||||
BUF_UNION ubuf ;
|
||||
short *sptr ;
|
||||
int k, bufferlen, readcount, count ;
|
||||
sf_count_t total = 0 ;
|
||||
@@ -631,8 +630,8 @@ ima_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
|
||||
return 0 ;
|
||||
pima = (IMA_ADPCM_PRIVATE*) psf->codec_data ;
|
||||
|
||||
sptr = psf->u.sbuf ;
|
||||
bufferlen = ARRAY_LEN (psf->u.sbuf) ;
|
||||
sptr = ubuf.sbuf ;
|
||||
bufferlen = ARRAY_LEN (ubuf.sbuf) ;
|
||||
while (len > 0)
|
||||
{ readcount = (len >= bufferlen) ? bufferlen : (int) len ;
|
||||
count = ima_read_block (psf, pima, sptr, readcount) ;
|
||||
@@ -650,6 +649,7 @@ ima_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
|
||||
static sf_count_t
|
||||
ima_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
|
||||
{ IMA_ADPCM_PRIVATE *pima ;
|
||||
BUF_UNION ubuf ;
|
||||
short *sptr ;
|
||||
int k, bufferlen, readcount, count ;
|
||||
sf_count_t total = 0 ;
|
||||
@@ -661,8 +661,8 @@ ima_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
|
||||
|
||||
normfact = (psf->norm_float == SF_TRUE) ? 1.0 / ((float) 0x8000) : 1.0 ;
|
||||
|
||||
sptr = psf->u.sbuf ;
|
||||
bufferlen = ARRAY_LEN (psf->u.sbuf) ;
|
||||
sptr = ubuf.sbuf ;
|
||||
bufferlen = ARRAY_LEN (ubuf.sbuf) ;
|
||||
while (len > 0)
|
||||
{ readcount = (len >= bufferlen) ? bufferlen : (int) len ;
|
||||
count = ima_read_block (psf, pima, sptr, readcount) ;
|
||||
@@ -680,6 +680,7 @@ ima_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
|
||||
static sf_count_t
|
||||
ima_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
|
||||
{ IMA_ADPCM_PRIVATE *pima ;
|
||||
BUF_UNION ubuf ;
|
||||
short *sptr ;
|
||||
int k, bufferlen, readcount, count ;
|
||||
sf_count_t total = 0 ;
|
||||
@@ -691,8 +692,8 @@ ima_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
|
||||
|
||||
normfact = (psf->norm_double == SF_TRUE) ? 1.0 / ((double) 0x8000) : 1.0 ;
|
||||
|
||||
sptr = psf->u.sbuf ;
|
||||
bufferlen = ARRAY_LEN (psf->u.sbuf) ;
|
||||
sptr = ubuf.sbuf ;
|
||||
bufferlen = ARRAY_LEN (ubuf.sbuf) ;
|
||||
while (len > 0)
|
||||
{ readcount = (len >= bufferlen) ? bufferlen : (int) len ;
|
||||
count = ima_read_block (psf, pima, sptr, readcount) ;
|
||||
@@ -724,9 +725,7 @@ ima_seek (SF_PRIVATE *psf, int mode, sf_count_t offset)
|
||||
if (offset == 0)
|
||||
{ psf_fseek (psf, psf->dataoffset, SEEK_SET) ;
|
||||
pima->blockcount = 0 ;
|
||||
if (pima->decode_block) {
|
||||
pima->decode_block (psf, pima) ;
|
||||
}
|
||||
pima->decode_block (psf, pima) ;
|
||||
pima->samplecount = 0 ;
|
||||
return 0 ;
|
||||
} ;
|
||||
@@ -764,7 +763,7 @@ ima_writer_init (SF_PRIVATE *psf, int blockalign)
|
||||
int samplesperblock ;
|
||||
unsigned int pimasize ;
|
||||
|
||||
if (psf->mode != SFM_WRITE)
|
||||
if (psf->file.mode != SFM_WRITE)
|
||||
return SFE_BAD_MODE_RW ;
|
||||
|
||||
samplesperblock = 2 * (blockalign - 4 * psf->sf.channels) / psf->sf.channels + 1 ;
|
||||
@@ -798,7 +797,6 @@ ima_writer_init (SF_PRIVATE *psf, int blockalign)
|
||||
default :
|
||||
psf_log_printf (psf, "ima_reader_init: bad psf->sf.format\n") ;
|
||||
return SFE_INTERNAL ;
|
||||
break ;
|
||||
} ;
|
||||
|
||||
psf->write_short = ima_write_s ;
|
||||
@@ -861,6 +859,7 @@ ima_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len)
|
||||
static sf_count_t
|
||||
ima_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len)
|
||||
{ IMA_ADPCM_PRIVATE *pima ;
|
||||
BUF_UNION ubuf ;
|
||||
short *sptr ;
|
||||
int k, bufferlen, writecount, count ;
|
||||
sf_count_t total = 0 ;
|
||||
@@ -869,8 +868,8 @@ ima_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len)
|
||||
return 0 ;
|
||||
pima = (IMA_ADPCM_PRIVATE*) psf->codec_data ;
|
||||
|
||||
sptr = psf->u.sbuf ;
|
||||
bufferlen = ARRAY_LEN (psf->u.sbuf) ;
|
||||
sptr = ubuf.sbuf ;
|
||||
bufferlen = ARRAY_LEN (ubuf.sbuf) ;
|
||||
while (len > 0)
|
||||
{ writecount = (len >= bufferlen) ? bufferlen : (int) len ;
|
||||
for (k = 0 ; k < writecount ; k++)
|
||||
@@ -888,6 +887,7 @@ ima_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len)
|
||||
static sf_count_t
|
||||
ima_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
|
||||
{ IMA_ADPCM_PRIVATE *pima ;
|
||||
BUF_UNION ubuf ;
|
||||
short *sptr ;
|
||||
int k, bufferlen, writecount, count ;
|
||||
sf_count_t total = 0 ;
|
||||
@@ -899,8 +899,8 @@ ima_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
|
||||
|
||||
normfact = (psf->norm_float == SF_TRUE) ? (1.0 * 0x7FFF) : 1.0 ;
|
||||
|
||||
sptr = psf->u.sbuf ;
|
||||
bufferlen = ARRAY_LEN (psf->u.sbuf) ;
|
||||
sptr = ubuf.sbuf ;
|
||||
bufferlen = ARRAY_LEN (ubuf.sbuf) ;
|
||||
while (len > 0)
|
||||
{ writecount = (len >= bufferlen) ? bufferlen : (int) len ;
|
||||
for (k = 0 ; k < writecount ; k++)
|
||||
@@ -918,6 +918,7 @@ ima_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
|
||||
static sf_count_t
|
||||
ima_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
|
||||
{ IMA_ADPCM_PRIVATE *pima ;
|
||||
BUF_UNION ubuf ;
|
||||
short *sptr ;
|
||||
int k, bufferlen, writecount, count ;
|
||||
sf_count_t total = 0 ;
|
||||
@@ -929,8 +930,8 @@ ima_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
|
||||
|
||||
normfact = (psf->norm_double == SF_TRUE) ? (1.0 * 0x7FFF) : 1.0 ;
|
||||
|
||||
sptr = psf->u.sbuf ;
|
||||
bufferlen = ARRAY_LEN (psf->u.sbuf) ;
|
||||
sptr = ubuf.sbuf ;
|
||||
bufferlen = ARRAY_LEN (ubuf.sbuf) ;
|
||||
while (len > 0)
|
||||
{ writecount = (len >= bufferlen) ? bufferlen : (int) len ;
|
||||
for (k = 0 ; k < writecount ; k++)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
** Copyright (C) 2007-2012 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
** Copyright (c) 2007 <robs@users.sourceforge.net>
|
||||
** Copyright (C) 2007-2009 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** 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
|
||||
@@ -19,6 +19,8 @@
|
||||
|
||||
/* ADPCM: IMA, OKI <==> 16-bit PCM. */
|
||||
|
||||
#include "sfconfig.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/* Set up for libsndfile environment: */
|
||||
@@ -75,7 +77,7 @@ adpcm_decode (IMA_OKI_ADPCM * state, int code)
|
||||
s = ((state->steps [state->step_index] * s) >> 3) & state->mask ;
|
||||
|
||||
if (code & 8)
|
||||
s = -s ;
|
||||
s = -s ;
|
||||
s += state->last_output ;
|
||||
|
||||
if (s < MIN_SAMPLE || s > MAX_SAMPLE)
|
||||
@@ -137,7 +139,7 @@ ima_oki_adpcm_encode_block (IMA_OKI_ADPCM * state)
|
||||
|
||||
/*
|
||||
** The codec expects an even number of input samples.
|
||||
**
|
||||
**
|
||||
** Samples should always be passed in even length blocks. If the last block to
|
||||
** be encoded is odd length, extend that block by one zero valued sample.
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
** Copyright (C) 2007-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
** Copyright (c) 2007 <robs@users.sourceforge.net>
|
||||
** Copyright (C) 2007-2009 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** 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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** Copyright (C) 2002-2009 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
** Copyright (C) 2002-2013 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
@@ -53,7 +53,7 @@ int
|
||||
interleave_init (SF_PRIVATE *psf)
|
||||
{ INTERLEAVE_DATA *pdata ;
|
||||
|
||||
if (psf->mode != SFM_READ)
|
||||
if (psf->file.mode != SFM_READ)
|
||||
return SFE_INTERLEAVE_MODE ;
|
||||
|
||||
if (psf->interleave)
|
||||
@@ -287,9 +287,8 @@ interleave_read_double (SF_PRIVATE *psf, double *ptr, sf_count_t len)
|
||||
*/
|
||||
|
||||
static sf_count_t
|
||||
interleave_seek (SF_PRIVATE *psf, int mode, sf_count_t samples_from_start)
|
||||
{ psf = psf ; mode = mode ;
|
||||
|
||||
interleave_seek (SF_PRIVATE * UNUSED (psf), int UNUSED (mode), sf_count_t samples_from_start)
|
||||
{
|
||||
/*
|
||||
** Do nothing here. This is a place holder to prevent the default
|
||||
** seek function from being called.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** Copyright (C) 2001-2009 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
** Copyright (C) 2001-2012 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
@@ -80,14 +80,14 @@ ircam_open (SF_PRIVATE *psf)
|
||||
{ int subformat ;
|
||||
int error = SFE_NO_ERROR ;
|
||||
|
||||
if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->filelength > 0))
|
||||
if (psf->file.mode == SFM_READ || (psf->file.mode == SFM_RDWR && psf->filelength > 0))
|
||||
{ if ((error = ircam_read_header (psf)))
|
||||
return error ;
|
||||
} ;
|
||||
|
||||
subformat = SF_CODEC (psf->sf.format) ;
|
||||
|
||||
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
|
||||
if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
|
||||
{ if ((SF_CONTAINER (psf->sf.format)) != SF_FORMAT_IRCAM)
|
||||
return SFE_BAD_OPEN_FORMAT ;
|
||||
|
||||
@@ -95,7 +95,7 @@ ircam_open (SF_PRIVATE *psf)
|
||||
if (psf->endian == 0 || psf->endian == SF_ENDIAN_CPU)
|
||||
psf->endian = (CPU_IS_BIG_ENDIAN) ? SF_ENDIAN_BIG : SF_ENDIAN_LITTLE ;
|
||||
|
||||
psf->dataoffset = IRCAM_DATA_OFFSET ;
|
||||
psf->dataoffset = IRCAM_DATA_OFFSET ;
|
||||
|
||||
if ((error = ircam_write_header (psf, SF_FALSE)))
|
||||
return error ;
|
||||
@@ -163,9 +163,10 @@ ircam_read_header (SF_PRIVATE *psf)
|
||||
|
||||
psf->sf.samplerate = (int) samplerate ;
|
||||
|
||||
psf_log_printf (psf, " Sample Rate : %d\n"
|
||||
" Channels : %d\n"
|
||||
" Encoding : %X => %s\n", psf->sf.samplerate, psf->sf.channels, encoding, get_encoding_str (encoding)) ;
|
||||
psf_log_printf (psf, " Sample Rate : %d\n"
|
||||
" Channels : %d\n"
|
||||
" Encoding : %X => %s\n",
|
||||
psf->sf.samplerate, psf->sf.channels, encoding, get_encoding_str (encoding)) ;
|
||||
|
||||
switch (encoding)
|
||||
{ case IRCAM_PCM_16 :
|
||||
|
||||
@@ -33,7 +33,9 @@ sf_write_double @40
|
||||
sf_strerror @50
|
||||
sf_get_string @60
|
||||
sf_set_string @61
|
||||
sf_version_string @68
|
||||
sf_open_fd @70
|
||||
sf_wchar_open @71
|
||||
sf_open_virtual @80
|
||||
sf_write_sync @90
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** Copyright (C) 2003-2009 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
** Copyright (C) 2003-2012 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
@@ -25,7 +25,7 @@
|
||||
#include "sfendian.h"
|
||||
#include "common.h"
|
||||
|
||||
#if (OS_IS_MACOSX == 1)
|
||||
#if (OSX_DARWIN_VERSION >= 1)
|
||||
|
||||
int
|
||||
macbinary3_open (SF_PRIVATE * UNUSED (psf))
|
||||
@@ -41,5 +41,5 @@ macbinary3_open (SF_PRIVATE * UNUSED (psf))
|
||||
return 0 ;
|
||||
} /* macbinary3_open */
|
||||
|
||||
#endif /* OS_IS_MACOSX */
|
||||
#endif /* OSX_DARWIN_VERSION */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** Copyright (C) 2003-2009 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
** Copyright (C) 2003-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
#!/bin/bash -e
|
||||
|
||||
# This script takes a static library and removes all non-public symbols.
|
||||
# Ie, it makes a static lib whose symbols are far less likely to clash with
|
||||
# the symbols of another shared or static library.
|
||||
|
||||
grep sf_ Symbols.gnu-binutils | sed -e "s/[ ;]//g" > Symbols.static
|
||||
|
||||
ld -r --whole-archive .libs/libsndfile.a -o libsndfile_a.o
|
||||
|
||||
objcopy --keep-global-symbols=Symbols.static libsndfile_a.o libsndfile.o
|
||||
|
||||
rm -f libsndfile.a
|
||||
ar cru libsndfile.a libsndfile.o
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** Copyright (C) 2002-2009 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
** Copyright (C) 2002-2013 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
@@ -76,7 +76,7 @@ int
|
||||
mat4_open (SF_PRIVATE *psf)
|
||||
{ int subformat, error = 0 ;
|
||||
|
||||
if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->filelength > 0))
|
||||
if (psf->file.mode == SFM_READ || (psf->file.mode == SFM_RDWR && psf->filelength > 0))
|
||||
{ if ((error = mat4_read_header (psf)))
|
||||
return error ;
|
||||
} ;
|
||||
@@ -86,7 +86,7 @@ mat4_open (SF_PRIVATE *psf)
|
||||
|
||||
subformat = SF_CODEC (psf->sf.format) ;
|
||||
|
||||
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
|
||||
if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
|
||||
{ if (psf->is_pipe)
|
||||
return SFE_NO_PIPE_WRITE ;
|
||||
|
||||
@@ -135,7 +135,7 @@ mat4_open (SF_PRIVATE *psf)
|
||||
static int
|
||||
mat4_close (SF_PRIVATE *psf)
|
||||
{
|
||||
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
|
||||
if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
|
||||
mat4_write_header (psf, SF_TRUE) ;
|
||||
|
||||
return 0 ;
|
||||
@@ -206,8 +206,9 @@ mat4_write_header (SF_PRIVATE *psf, int calc_length)
|
||||
|
||||
static int
|
||||
mat4_read_header (SF_PRIVATE *psf)
|
||||
{ int marker, rows, cols, imag ;
|
||||
unsigned namesize ;
|
||||
{ char buffer [256] ;
|
||||
uint32_t marker, namesize ;
|
||||
int rows, cols, imag ;
|
||||
double value ;
|
||||
const char *marker_str ;
|
||||
char name [64] ;
|
||||
@@ -244,8 +245,8 @@ mat4_read_header (SF_PRIVATE *psf)
|
||||
|
||||
psf_binheader_readf (psf, "d", &value) ;
|
||||
|
||||
snprintf (psf->u.cbuf, sizeof (psf->u.cbuf), " Value : %f\n", value) ;
|
||||
psf_log_printf (psf, psf->u.cbuf) ;
|
||||
snprintf (buffer, sizeof (buffer), " Value : %f\n", value) ;
|
||||
psf_log_printf (psf, buffer) ;
|
||||
|
||||
if ((rows != 1) || (cols != 1))
|
||||
return SFE_MAT4_NO_SAMPLERATE ;
|
||||
|
||||
+28
-20
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** Copyright (C) 2002-2009 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
** Copyright (C) 2002-2012 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
@@ -86,7 +86,7 @@ int
|
||||
mat5_open (SF_PRIVATE *psf)
|
||||
{ int subformat, error = 0 ;
|
||||
|
||||
if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->filelength > 0))
|
||||
if (psf->file.mode == SFM_READ || (psf->file.mode == SFM_RDWR && psf->filelength > 0))
|
||||
{ if ((error = mat5_read_header (psf)))
|
||||
return error ;
|
||||
} ;
|
||||
@@ -96,7 +96,7 @@ mat5_open (SF_PRIVATE *psf)
|
||||
|
||||
subformat = SF_CODEC (psf->sf.format) ;
|
||||
|
||||
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
|
||||
if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
|
||||
{ if (psf->is_pipe)
|
||||
return SFE_NO_PIPE_WRITE ;
|
||||
|
||||
@@ -143,7 +143,7 @@ mat5_open (SF_PRIVATE *psf)
|
||||
static int
|
||||
mat5_close (SF_PRIVATE *psf)
|
||||
{
|
||||
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
|
||||
if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
|
||||
mat5_write_header (psf, SF_TRUE) ;
|
||||
|
||||
return 0 ;
|
||||
@@ -157,6 +157,7 @@ mat5_write_header (SF_PRIVATE *psf, int calc_length)
|
||||
{ static const char *filename = "MATLAB 5.0 MAT-file, written by " PACKAGE "-" VERSION ", " ;
|
||||
static const char *sr_name = "samplerate\0\0\0\0\0\0\0\0\0\0\0" ;
|
||||
static const char *wd_name = "wavedata\0" ;
|
||||
char buffer [256] ;
|
||||
sf_count_t current, datasize ;
|
||||
int encoding ;
|
||||
|
||||
@@ -204,11 +205,11 @@ mat5_write_header (SF_PRIVATE *psf, int calc_length)
|
||||
psf->headindex = 0 ;
|
||||
psf_fseek (psf, 0, SEEK_SET) ;
|
||||
|
||||
psf_get_date_str (psf->u.cbuf, sizeof (psf->u.scbuf)) ;
|
||||
psf_binheader_writef (psf, "bb", filename, strlen (filename), psf->u.cbuf, strlen (psf->u.cbuf) + 1) ;
|
||||
psf_get_date_str (buffer, sizeof (buffer)) ;
|
||||
psf_binheader_writef (psf, "bb", filename, strlen (filename), buffer, strlen (buffer) + 1) ;
|
||||
|
||||
memset (psf->u.scbuf, ' ', 124 - psf->headindex) ;
|
||||
psf_binheader_writef (psf, "b", psf->u.scbuf, make_size_t (124 - psf->headindex)) ;
|
||||
memset (buffer, ' ', 124 - psf->headindex) ;
|
||||
psf_binheader_writef (psf, "b", buffer, make_size_t (124 - psf->headindex)) ;
|
||||
|
||||
psf->rwf_endian = psf->endian ;
|
||||
|
||||
@@ -257,38 +258,39 @@ mat5_write_header (SF_PRIVATE *psf, int calc_length)
|
||||
|
||||
static int
|
||||
mat5_read_header (SF_PRIVATE *psf)
|
||||
{ char name [32] ;
|
||||
{ char buffer [256], name [32] ;
|
||||
short version, endian ;
|
||||
int type, flags1, flags2, rows, cols ;
|
||||
unsigned size ;
|
||||
int have_samplerate = 1 ;
|
||||
|
||||
psf_binheader_readf (psf, "pb", 0, psf->u.cbuf, 124) ;
|
||||
psf_binheader_readf (psf, "pb", 0, buffer, 124) ;
|
||||
|
||||
psf->u.scbuf [125] = 0 ;
|
||||
buffer [125] = 0 ;
|
||||
|
||||
if (strlen (psf->u.cbuf) >= 124)
|
||||
if (strlen (buffer) >= 124)
|
||||
return SFE_UNIMPLEMENTED ;
|
||||
|
||||
if (strstr (psf->u.cbuf, "MATLAB 5.0 MAT-file") == psf->u.cbuf)
|
||||
psf_log_printf (psf, "%s\n", psf->u.scbuf) ;
|
||||
if (strstr (buffer, "MATLAB 5.0 MAT-file") == buffer)
|
||||
psf_log_printf (psf, "%s\n", buffer) ;
|
||||
|
||||
|
||||
psf_binheader_readf (psf, "E22", &version, &endian) ;
|
||||
|
||||
if (endian == MI_MARKER)
|
||||
{ psf->endian = psf->rwf_endian = SF_ENDIAN_BIG ;
|
||||
if (CPU_IS_LITTLE_ENDIAN) version = ENDSWAP_SHORT (version) ;
|
||||
if (CPU_IS_LITTLE_ENDIAN) version = ENDSWAP_16 (version) ;
|
||||
}
|
||||
else if (endian == IM_MARKER)
|
||||
{ psf->endian = psf->rwf_endian = SF_ENDIAN_LITTLE ;
|
||||
if (CPU_IS_BIG_ENDIAN) version = ENDSWAP_SHORT (version) ;
|
||||
if (CPU_IS_BIG_ENDIAN) version = ENDSWAP_16 (version) ;
|
||||
}
|
||||
else
|
||||
return SFE_MAT5_BAD_ENDIAN ;
|
||||
|
||||
if ((CPU_IS_LITTLE_ENDIAN && endian == IM_MARKER) ||
|
||||
(CPU_IS_BIG_ENDIAN && endian == MI_MARKER))
|
||||
version = ENDSWAP_SHORT (version) ;
|
||||
version = ENDSWAP_16 (version) ;
|
||||
|
||||
psf_log_printf (psf, "Version : 0x%04X\n", version) ;
|
||||
psf_log_printf (psf, "Endian : 0x%04X => %s\n", endian,
|
||||
@@ -317,11 +319,13 @@ mat5_read_header (SF_PRIVATE *psf)
|
||||
return SFE_MAT5_NO_BLOCK ;
|
||||
|
||||
psf_binheader_readf (psf, "44", &rows, &cols) ;
|
||||
psf_log_printf (psf, " Rows : %X Cols : %d\n", rows, cols) ;
|
||||
psf_log_printf (psf, " Rows : %d Cols : %d\n", rows, cols) ;
|
||||
|
||||
if (rows != 1 || cols != 1)
|
||||
return SFE_MAT5_SAMPLE_RATE ;
|
||||
|
||||
{ if (psf->sf.samplerate == 0)
|
||||
psf->sf.samplerate = 44100 ;
|
||||
have_samplerate = 0 ;
|
||||
}
|
||||
psf_binheader_readf (psf, "4", &type) ;
|
||||
|
||||
if (type == MAT5_TYPE_SCHAR)
|
||||
@@ -355,6 +359,9 @@ mat5_read_header (SF_PRIVATE *psf)
|
||||
|
||||
psf_binheader_readf (psf, "44", &type, &size) ;
|
||||
|
||||
if (!have_samplerate)
|
||||
goto skip_samplerate ;
|
||||
|
||||
switch (type)
|
||||
{ case MAT5_TYPE_DOUBLE :
|
||||
{ double samplerate ;
|
||||
@@ -445,6 +452,7 @@ mat5_read_header (SF_PRIVATE *psf)
|
||||
psf_binheader_readf (psf, "44", &type, &size) ;
|
||||
psf_log_printf (psf, " Type : %X Size : %d\n", type, size) ;
|
||||
|
||||
skip_samplerate :
|
||||
/*++++++++++++++++++++++++++++++++++++++++++++++++++*/
|
||||
|
||||
if (rows == 0 && cols == 0)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** Copyright (C) 2008-2009 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
** Copyright (C) 2008-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
@@ -38,7 +38,7 @@
|
||||
** 1 byte: loopMode (0 no loop, 1 forward looping)
|
||||
** 1 byte: number of beat in loop
|
||||
** 1 uint16: sampleRate
|
||||
**
|
||||
**
|
||||
** DATA
|
||||
** Data are always non compressed 16 bits interleaved
|
||||
*/
|
||||
@@ -63,10 +63,9 @@ static int mpc2k_read_header (SF_PRIVATE *psf) ;
|
||||
|
||||
int
|
||||
mpc2k_open (SF_PRIVATE *psf)
|
||||
{ int subformat ;
|
||||
int error = 0 ;
|
||||
{ int error = 0 ;
|
||||
|
||||
if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->filelength > 0))
|
||||
if (psf->file.mode == SFM_READ || (psf->file.mode == SFM_RDWR && psf->filelength > 0))
|
||||
{ if ((error = mpc2k_read_header (psf)))
|
||||
return error ;
|
||||
} ;
|
||||
@@ -74,9 +73,7 @@ mpc2k_open (SF_PRIVATE *psf)
|
||||
if ((SF_CONTAINER (psf->sf.format)) != SF_FORMAT_MPC2K)
|
||||
return SFE_BAD_OPEN_FORMAT ;
|
||||
|
||||
subformat = SF_CODEC (psf->sf.format) ;
|
||||
|
||||
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
|
||||
if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
|
||||
{ if (mpc2k_write_header (psf, SF_FALSE))
|
||||
return psf->error ;
|
||||
|
||||
@@ -98,7 +95,7 @@ mpc2k_open (SF_PRIVATE *psf)
|
||||
static int
|
||||
mpc2k_close (SF_PRIVATE *psf)
|
||||
{
|
||||
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
|
||||
if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
|
||||
mpc2k_write_header (psf, SF_TRUE) ;
|
||||
|
||||
return 0 ;
|
||||
@@ -134,7 +131,7 @@ mpc2k_write_header (SF_PRIVATE *psf, int calc_length)
|
||||
if (psf->is_pipe == SF_FALSE)
|
||||
psf_fseek (psf, 0, SEEK_SET) ;
|
||||
|
||||
snprintf (sample_name, sizeof (sample_name), "%s ", psf->filename) ;
|
||||
snprintf (sample_name, sizeof (sample_name), "%s ", psf->file.name.c) ;
|
||||
|
||||
psf_binheader_writef (psf, "e11b", 1, 4, sample_name, make_size_t (HEADER_NAME_LEN)) ;
|
||||
psf_binheader_writef (psf, "e111", 100, 0, (psf->sf.channels - 1) & 1) ;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** Copyright (C) 1999-2009 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
** Copyright (C) 1999-2013 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
@@ -44,11 +44,7 @@ typedef struct
|
||||
sf_count_t samplecount ;
|
||||
short *samples ;
|
||||
unsigned char *block ;
|
||||
#if HAVE_FLEXIBLE_ARRAY
|
||||
short dummydata [] ; /* ISO C99 struct flexible array. */
|
||||
#else
|
||||
short dummydata [0] ; /* This is a hack an might not work. */
|
||||
#endif
|
||||
} MSADPCM_PRIVATE ;
|
||||
|
||||
/*============================================================================================
|
||||
@@ -137,15 +133,14 @@ wav_w64_msadpcm_init (SF_PRIVATE *psf, int blockalign, int samplesperblock)
|
||||
return SFE_INTERNAL ;
|
||||
} ;
|
||||
|
||||
if (psf->mode == SFM_WRITE)
|
||||
if (psf->file.mode == SFM_WRITE)
|
||||
samplesperblock = 2 + 2 * (blockalign - 7 * psf->sf.channels) / psf->sf.channels ;
|
||||
|
||||
pmssize = sizeof (MSADPCM_PRIVATE) + blockalign + 3 * psf->sf.channels * samplesperblock ;
|
||||
|
||||
if (! (psf->codec_data = malloc (pmssize)))
|
||||
if (! (psf->codec_data = calloc (1, pmssize)))
|
||||
return SFE_MALLOC_FAILED ;
|
||||
pms = (MSADPCM_PRIVATE*) psf->codec_data ;
|
||||
memset (pms, 0, pmssize) ;
|
||||
|
||||
pms->samples = pms->dummydata ;
|
||||
pms->block = (unsigned char*) (pms->dummydata + psf->sf.channels * samplesperblock) ;
|
||||
@@ -159,8 +154,8 @@ wav_w64_msadpcm_init (SF_PRIVATE *psf, int blockalign, int samplesperblock)
|
||||
return SFE_INTERNAL ;
|
||||
} ;
|
||||
|
||||
if (psf->mode == SFM_READ)
|
||||
{ pms->dataremaining = psf->datalength ;
|
||||
if (psf->file.mode == SFM_READ)
|
||||
{ pms->dataremaining = psf->datalength ;
|
||||
|
||||
if (psf->datalength % pms->blocksize)
|
||||
pms->blocks = psf->datalength / pms->blocksize + 1 ;
|
||||
@@ -185,7 +180,7 @@ wav_w64_msadpcm_init (SF_PRIVATE *psf, int blockalign, int samplesperblock)
|
||||
psf->read_double = msadpcm_read_d ;
|
||||
} ;
|
||||
|
||||
if (psf->mode == SFM_WRITE)
|
||||
if (psf->file.mode == SFM_WRITE)
|
||||
{ pms->samples = pms->dummydata ;
|
||||
|
||||
pms->samplecount = 0 ;
|
||||
@@ -207,9 +202,9 @@ msadpcm_decode_block (SF_PRIVATE *psf, MSADPCM_PRIVATE *pms)
|
||||
{ int chan, k, blockindx, sampleindx ;
|
||||
short bytecode, bpred [2], chan_idelta [2] ;
|
||||
|
||||
int predict ;
|
||||
int current ;
|
||||
int idelta ;
|
||||
int predict ;
|
||||
int current ;
|
||||
int idelta ;
|
||||
|
||||
pms->blockcount ++ ;
|
||||
pms->samplecount = 0 ;
|
||||
@@ -278,7 +273,7 @@ msadpcm_decode_block (SF_PRIVATE *psf, MSADPCM_PRIVATE *pms)
|
||||
sampleindx = 2 * pms->channels ;
|
||||
while (blockindx < pms->blocksize)
|
||||
{ bytecode = pms->block [blockindx++] ;
|
||||
pms->samples [sampleindx++] = (bytecode >> 4) & 0x0F ;
|
||||
pms->samples [sampleindx++] = (bytecode >> 4) & 0x0F ;
|
||||
pms->samples [sampleindx++] = bytecode & 0x0F ;
|
||||
} ;
|
||||
|
||||
@@ -297,7 +292,7 @@ msadpcm_decode_block (SF_PRIVATE *psf, MSADPCM_PRIVATE *pms)
|
||||
if (bytecode & 0x8)
|
||||
bytecode -= 0x10 ;
|
||||
|
||||
predict = ((pms->samples [k - pms->channels] * AdaptCoeff1 [bpred [chan]])
|
||||
predict = ((pms->samples [k - pms->channels] * AdaptCoeff1 [bpred [chan]])
|
||||
+ (pms->samples [k - 2 * pms->channels] * AdaptCoeff2 [bpred [chan]])) >> 8 ; /* => / 256 => FIXED_POINT_COEFF_BASE == 256 */
|
||||
current = (bytecode * idelta) + predict ;
|
||||
|
||||
@@ -364,6 +359,7 @@ msadpcm_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
|
||||
static sf_count_t
|
||||
msadpcm_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
|
||||
{ MSADPCM_PRIVATE *pms ;
|
||||
BUF_UNION ubuf ;
|
||||
short *sptr ;
|
||||
int k, bufferlen, readcount = 0, count ;
|
||||
sf_count_t total = 0 ;
|
||||
@@ -372,8 +368,8 @@ msadpcm_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
|
||||
return 0 ;
|
||||
pms = (MSADPCM_PRIVATE*) psf->codec_data ;
|
||||
|
||||
sptr = psf->u.sbuf ;
|
||||
bufferlen = ARRAY_LEN (psf->u.sbuf) ;
|
||||
sptr = ubuf.sbuf ;
|
||||
bufferlen = ARRAY_LEN (ubuf.sbuf) ;
|
||||
while (len > 0)
|
||||
{ readcount = (len >= bufferlen) ? bufferlen : len ;
|
||||
count = msadpcm_read_block (psf, pms, sptr, readcount) ;
|
||||
@@ -390,6 +386,7 @@ msadpcm_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
|
||||
static sf_count_t
|
||||
msadpcm_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
|
||||
{ MSADPCM_PRIVATE *pms ;
|
||||
BUF_UNION ubuf ;
|
||||
short *sptr ;
|
||||
int k, bufferlen, readcount = 0, count ;
|
||||
sf_count_t total = 0 ;
|
||||
@@ -400,8 +397,8 @@ msadpcm_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
|
||||
pms = (MSADPCM_PRIVATE*) psf->codec_data ;
|
||||
|
||||
normfact = (psf->norm_float == SF_TRUE) ? 1.0 / ((float) 0x8000) : 1.0 ;
|
||||
sptr = psf->u.sbuf ;
|
||||
bufferlen = ARRAY_LEN (psf->u.sbuf) ;
|
||||
sptr = ubuf.sbuf ;
|
||||
bufferlen = ARRAY_LEN (ubuf.sbuf) ;
|
||||
while (len > 0)
|
||||
{ readcount = (len >= bufferlen) ? bufferlen : len ;
|
||||
count = msadpcm_read_block (psf, pms, sptr, readcount) ;
|
||||
@@ -418,6 +415,7 @@ msadpcm_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
|
||||
static sf_count_t
|
||||
msadpcm_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
|
||||
{ MSADPCM_PRIVATE *pms ;
|
||||
BUF_UNION ubuf ;
|
||||
short *sptr ;
|
||||
int k, bufferlen, readcount = 0, count ;
|
||||
sf_count_t total = 0 ;
|
||||
@@ -429,8 +427,8 @@ msadpcm_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
|
||||
return 0 ;
|
||||
pms = (MSADPCM_PRIVATE*) psf->codec_data ;
|
||||
|
||||
sptr = psf->u.sbuf ;
|
||||
bufferlen = ARRAY_LEN (psf->u.sbuf) ;
|
||||
sptr = ubuf.sbuf ;
|
||||
bufferlen = ARRAY_LEN (ubuf.sbuf) ;
|
||||
while (len > 0)
|
||||
{ readcount = (len >= bufferlen) ? bufferlen : len ;
|
||||
count = msadpcm_read_block (psf, pms, sptr, readcount) ;
|
||||
@@ -674,6 +672,7 @@ msadpcm_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len)
|
||||
static sf_count_t
|
||||
msadpcm_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len)
|
||||
{ MSADPCM_PRIVATE *pms ;
|
||||
BUF_UNION ubuf ;
|
||||
short *sptr ;
|
||||
int k, bufferlen, writecount, count ;
|
||||
sf_count_t total = 0 ;
|
||||
@@ -682,8 +681,8 @@ msadpcm_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len)
|
||||
return 0 ;
|
||||
pms = (MSADPCM_PRIVATE*) psf->codec_data ;
|
||||
|
||||
sptr = psf->u.sbuf ;
|
||||
bufferlen = ARRAY_LEN (psf->u.sbuf) ;
|
||||
sptr = ubuf.sbuf ;
|
||||
bufferlen = ARRAY_LEN (ubuf.sbuf) ;
|
||||
while (len > 0)
|
||||
{ writecount = (len >= bufferlen) ? bufferlen : len ;
|
||||
for (k = 0 ; k < writecount ; k++)
|
||||
@@ -700,6 +699,7 @@ msadpcm_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len)
|
||||
static sf_count_t
|
||||
msadpcm_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
|
||||
{ MSADPCM_PRIVATE *pms ;
|
||||
BUF_UNION ubuf ;
|
||||
short *sptr ;
|
||||
int k, bufferlen, writecount, count ;
|
||||
sf_count_t total = 0 ;
|
||||
@@ -711,8 +711,8 @@ msadpcm_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
|
||||
|
||||
normfact = (psf->norm_float == SF_TRUE) ? (1.0 * 0x7FFF) : 1.0 ;
|
||||
|
||||
sptr = psf->u.sbuf ;
|
||||
bufferlen = ARRAY_LEN (psf->u.sbuf) ;
|
||||
sptr = ubuf.sbuf ;
|
||||
bufferlen = ARRAY_LEN (ubuf.sbuf) ;
|
||||
while (len > 0)
|
||||
{ writecount = (len >= bufferlen) ? bufferlen : len ;
|
||||
for (k = 0 ; k < writecount ; k++)
|
||||
@@ -729,6 +729,7 @@ msadpcm_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
|
||||
static sf_count_t
|
||||
msadpcm_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
|
||||
{ MSADPCM_PRIVATE *pms ;
|
||||
BUF_UNION ubuf ;
|
||||
short *sptr ;
|
||||
int k, bufferlen, writecount, count ;
|
||||
sf_count_t total = 0 ;
|
||||
@@ -740,8 +741,8 @@ msadpcm_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
|
||||
return 0 ;
|
||||
pms = (MSADPCM_PRIVATE*) psf->codec_data ;
|
||||
|
||||
sptr = psf->u.sbuf ;
|
||||
bufferlen = ARRAY_LEN (psf->u.sbuf) ;
|
||||
sptr = ubuf.sbuf ;
|
||||
bufferlen = ARRAY_LEN (ubuf.sbuf) ;
|
||||
while (len > 0)
|
||||
{ writecount = (len >= bufferlen) ? bufferlen : len ;
|
||||
for (k = 0 ; k < writecount ; k++)
|
||||
@@ -764,7 +765,7 @@ msadpcm_close (SF_PRIVATE *psf)
|
||||
|
||||
pms = (MSADPCM_PRIVATE*) psf->codec_data ;
|
||||
|
||||
if (psf->mode == SFM_WRITE)
|
||||
if (psf->file.mode == SFM_WRITE)
|
||||
{ /* Now we know static int for certain the length of the file we can
|
||||
** re-write the header.
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
** Copyright (C) 2002-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program 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 program 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 program; if not, write to the Free Software
|
||||
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "sfconfig.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "sndfile.h"
|
||||
#include "sfendian.h"
|
||||
#include "common.h"
|
||||
|
||||
#if (ENABLE_EXPERIMENTAL_CODE == 0)
|
||||
|
||||
int
|
||||
new_open (SF_PRIVATE *psf)
|
||||
{ if (psf)
|
||||
return SFE_UNIMPLEMENTED ;
|
||||
return (psf && 0) ;
|
||||
} /* new_open */
|
||||
|
||||
#else
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
** Macros to handle big/little endian issues.
|
||||
*/
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
** Typedefs.
|
||||
*/
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
** Private static functions.
|
||||
*/
|
||||
|
||||
static int new_read_header (SF_PRIVATE *psf) ;
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
** Public function.
|
||||
*/
|
||||
|
||||
int
|
||||
new_open (SF_PRIVATE *psf)
|
||||
{ int subformat, error = 0 ;
|
||||
|
||||
if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
|
||||
return SFE_UNIMPLEMENTED ;
|
||||
|
||||
if ((error = new_read_header (psf)))
|
||||
return error ;
|
||||
|
||||
if ((SF_CONTAINER (psf->sf.format)) != SF_FORMAT_WVE)
|
||||
return SFE_BAD_OPEN_FORMAT ;
|
||||
|
||||
subformat = SF_CODEC (psf->sf.format) ;
|
||||
|
||||
return error ;
|
||||
} /* new_open */
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static int
|
||||
new_read_header (SF_PRIVATE *psf)
|
||||
{ int marker ;
|
||||
|
||||
/* Set position to start of file to begin reading header. */
|
||||
psf_binheader_readf (psf, "pm", 0, &marker) ;
|
||||
if (marker != ALAW_MARKER)
|
||||
return SFE_WVE_NOT_WVE ;
|
||||
|
||||
psf_binheader_readf (psf, "m", &marker) ;
|
||||
if (marker != SOUN_MARKER)
|
||||
return SFE_WVE_NOT_WVE ;
|
||||
|
||||
psf_binheader_readf (psf, "m", &marker) ;
|
||||
if (marker != DFIL_MARKER)
|
||||
return SFE_WVE_NOT_WVE ;
|
||||
|
||||
psf_log_printf (psf, "Read only : Psion Alaw\n"
|
||||
" Sample Rate : 8000\n"
|
||||
" Channels : 1\n"
|
||||
" Encoding : A-law\n") ;
|
||||
|
||||
psf->dataoffset = 0x20 ;
|
||||
psf->datalength = psf->filelength - psf->dataoffset ;
|
||||
|
||||
psf->sf.format = SF_FORMAT_WVE | SF_FORMAT_ALAW ;
|
||||
psf->sf.samplerate = 8000 ;
|
||||
psf->sf.frames = psf->datalength ;
|
||||
psf->sf.channels = 1 ;
|
||||
|
||||
return alaw_init (psf) ;
|
||||
} /* new_read_header */
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#endif
|
||||
+31
-15
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** Copyright (C) 1999-2009 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
** Copyright (C) 1999-2012 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
@@ -54,12 +54,12 @@ int
|
||||
nist_open (SF_PRIVATE *psf)
|
||||
{ int error ;
|
||||
|
||||
if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->filelength > 0))
|
||||
if (psf->file.mode == SFM_READ || (psf->file.mode == SFM_RDWR && psf->filelength > 0))
|
||||
{ if ((error = nist_read_header (psf)))
|
||||
return error ;
|
||||
} ;
|
||||
|
||||
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
|
||||
if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
|
||||
{ if (psf->is_pipe)
|
||||
return SFE_NO_PIPE_WRITE ;
|
||||
|
||||
@@ -118,15 +118,12 @@ static char bad_header [] =
|
||||
|
||||
static int
|
||||
nist_read_header (SF_PRIVATE *psf)
|
||||
{ char *psf_header ;
|
||||
int bitwidth = 0, bytes = 0, count, encoding ;
|
||||
{ char psf_header [NIST_HEADER_LENGTH + 2] ;
|
||||
int bitwidth = 0, count, encoding ;
|
||||
unsigned bytes = 0 ;
|
||||
char str [64], *cptr ;
|
||||
long samples ;
|
||||
|
||||
psf->sf.format = SF_FORMAT_NIST ;
|
||||
|
||||
psf_header = psf->u.cbuf ;
|
||||
|
||||
if (sizeof (psf->header) <= NIST_HEADER_LENGTH)
|
||||
return SFE_INTERNAL ;
|
||||
|
||||
@@ -164,7 +161,9 @@ nist_read_header (SF_PRIVATE *psf)
|
||||
{ sscanf (cptr, "sample_coding -s%d %63s", &count, str) ;
|
||||
|
||||
if (strcmp (str, "pcm") == 0)
|
||||
{ /* Correct this later when we find out the bitwidth. */
|
||||
encoding = SF_FORMAT_PCM_U8 ;
|
||||
}
|
||||
else if (strcmp (str, "alaw") == 0)
|
||||
encoding = SF_FORMAT_ALAW ;
|
||||
else if ((strcmp (str, "ulaw") == 0) || (strcmp (str, "mu-law") == 0))
|
||||
@@ -193,19 +192,23 @@ nist_read_header (SF_PRIVATE *psf)
|
||||
psf->endian = (CPU_IS_BIG_ENDIAN) ? SF_ENDIAN_BIG : SF_ENDIAN_LITTLE ;
|
||||
|
||||
/* This is where we figure out endian-ness. */
|
||||
if ((cptr = strstr (psf_header, "sample_byte_format -s")))
|
||||
{ sscanf (cptr, "sample_byte_format -s%d %8s", &bytes, str) ;
|
||||
if ((cptr = strstr (psf_header, "sample_byte_format -s"))
|
||||
&& sscanf (cptr, "sample_byte_format -s%u %8s", &bytes, str) == 2)
|
||||
{
|
||||
if (bytes != strlen (str))
|
||||
psf_log_printf (psf, "Weird sample_byte_format : strlen '%s' != %d\n", str, bytes) ;
|
||||
|
||||
if (bytes > 1)
|
||||
{ if (psf->bytewidth == 0)
|
||||
psf->bytewidth = bytes ;
|
||||
else if (psf->bytewidth != bytes)
|
||||
else if (psf->bytewidth - bytes != 0)
|
||||
{ psf_log_printf (psf, "psf->bytewidth (%d) != bytes (%d)\n", psf->bytewidth, bytes) ;
|
||||
return SFE_NIST_BAD_ENCODING ;
|
||||
} ;
|
||||
|
||||
if (strstr (str, "01") == str)
|
||||
if (strcmp (str, "01") == 0)
|
||||
psf->endian = SF_ENDIAN_LITTLE ;
|
||||
else if (strstr (str, "10"))
|
||||
else if (strcmp (str, "10") == 0)
|
||||
psf->endian = SF_ENDIAN_BIG ;
|
||||
else
|
||||
{ psf_log_printf (psf, "Weird endian-ness : %s\n", str) ;
|
||||
@@ -255,13 +258,26 @@ nist_read_header (SF_PRIVATE *psf)
|
||||
else
|
||||
return SFE_UNIMPLEMENTED ;
|
||||
|
||||
/* Sanitize psf->sf.format. */
|
||||
switch (SF_CODEC (psf->sf.format))
|
||||
{ case SF_FORMAT_ULAW :
|
||||
case SF_FORMAT_ALAW :
|
||||
case SF_FORMAT_PCM_U8 :
|
||||
/* Blank out endian bits. */
|
||||
psf->sf.format = SF_FORMAT_NIST | SF_CODEC (psf->sf.format) ;
|
||||
break ;
|
||||
|
||||
default :
|
||||
break ;
|
||||
} ;
|
||||
|
||||
return 0 ;
|
||||
} /* nist_read_header */
|
||||
|
||||
static int
|
||||
nist_close (SF_PRIVATE *psf)
|
||||
{
|
||||
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
|
||||
if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
|
||||
nist_write_header (psf, SF_TRUE) ;
|
||||
|
||||
return 0 ;
|
||||
|
||||
+132
-1037
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
** Copyright (C) 2008-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program 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 program 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 program ; if not, write to the Free Software
|
||||
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef SF_SRC_OGG_H
|
||||
|
||||
enum
|
||||
{ OGG_ANNODEX = 300,
|
||||
OGG_ANXDATA,
|
||||
OGG_FLAC,
|
||||
OGG_FLAC0,
|
||||
OGG_PCM,
|
||||
OGG_SPEEX,
|
||||
OGG_VORBIS,
|
||||
} ;
|
||||
|
||||
typedef struct
|
||||
{ /* Sync and verify incoming physical bitstream */
|
||||
ogg_sync_state osync ;
|
||||
/* Take physical pages, weld into a logical stream of packets */
|
||||
ogg_stream_state ostream ;
|
||||
/* One Ogg bitstream page. Vorbis packets are inside */
|
||||
ogg_page opage ;
|
||||
/* One raw packet of data for decode */
|
||||
ogg_packet opacket ;
|
||||
int eos ;
|
||||
int codec ;
|
||||
} OGG_PRIVATE ;
|
||||
|
||||
|
||||
#define readint(buf, base) (((buf [base + 3] << 24) & 0xff000000) | \
|
||||
((buf [base + 2] <<16) & 0xff0000) | \
|
||||
((buf [base + 1] << 8) & 0xff00) | \
|
||||
(buf [base] & 0xff))
|
||||
|
||||
|
||||
|
||||
#endif /* SF_SRC_OGG_H */
|
||||
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
** Copyright (C) 2013 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program 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 program 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 program ; if not, write to the Free Software
|
||||
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
|
||||
#include "sfconfig.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <time.h>
|
||||
#include <math.h>
|
||||
|
||||
#if HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "sndfile.h"
|
||||
#include "sfendian.h"
|
||||
#include "common.h"
|
||||
|
||||
#if (ENABLE_EXPERIMENTAL_CODE && HAVE_EXTERNAL_LIBS)
|
||||
|
||||
#include <ogg/ogg.h>
|
||||
|
||||
#include "ogg.h"
|
||||
|
||||
typedef struct
|
||||
{ int32_t serialno ;
|
||||
|
||||
|
||||
void * state ;
|
||||
} OPUS_PRIVATE ;
|
||||
|
||||
static int ogg_opus_read_header (SF_PRIVATE * psf) ;
|
||||
static int ogg_opus_close (SF_PRIVATE *psf) ;
|
||||
|
||||
int
|
||||
ogg_opus_open (SF_PRIVATE *psf)
|
||||
{ OGG_PRIVATE* odata = psf->container_data ;
|
||||
OPUS_PRIVATE* oopus = calloc (1, sizeof (OPUS_PRIVATE)) ;
|
||||
int error = 0 ;
|
||||
|
||||
if (odata == NULL)
|
||||
{ psf_log_printf (psf, "%s : odata is NULL???\n", __func__) ;
|
||||
return SFE_INTERNAL ;
|
||||
} ;
|
||||
|
||||
psf->codec_data = oopus ;
|
||||
if (oopus == NULL)
|
||||
return SFE_MALLOC_FAILED ;
|
||||
|
||||
if (psf->file.mode == SFM_RDWR)
|
||||
return SFE_BAD_MODE_RW ;
|
||||
|
||||
if (psf->file.mode == SFM_READ)
|
||||
{ /* Call this here so it only gets called once, so no memory is leaked. */
|
||||
ogg_sync_init (&odata->osync) ;
|
||||
|
||||
if ((error = ogg_opus_read_header (psf)))
|
||||
return error ;
|
||||
|
||||
#if 0
|
||||
psf->read_short = ogg_opus_read_s ;
|
||||
psf->read_int = ogg_opus_read_i ;
|
||||
psf->read_float = ogg_opus_read_f ;
|
||||
psf->read_double = ogg_opus_read_d ;
|
||||
psf->sf.frames = ogg_opus_length (psf) ;
|
||||
#endif
|
||||
} ;
|
||||
|
||||
psf->codec_close = ogg_opus_close ;
|
||||
|
||||
if (psf->file.mode == SFM_WRITE)
|
||||
{
|
||||
#if 0
|
||||
/* Set the default oopus quality here. */
|
||||
vdata->quality = 0.4 ;
|
||||
|
||||
psf->write_header = ogg_opus_write_header ;
|
||||
psf->write_short = ogg_opus_write_s ;
|
||||
psf->write_int = ogg_opus_write_i ;
|
||||
psf->write_float = ogg_opus_write_f ;
|
||||
psf->write_double = ogg_opus_write_d ;
|
||||
#endif
|
||||
|
||||
psf->sf.frames = SF_COUNT_MAX ; /* Unknown really */
|
||||
psf->strings.flags = SF_STR_ALLOW_START ;
|
||||
} ;
|
||||
|
||||
psf->bytewidth = 1 ;
|
||||
psf->blockwidth = psf->bytewidth * psf->sf.channels ;
|
||||
|
||||
#if 0
|
||||
psf->seek = ogg_opus_seek ;
|
||||
psf->command = ogg_opus_command ;
|
||||
#endif
|
||||
|
||||
/* FIXME, FIXME, FIXME : Hack these here for now and correct later. */
|
||||
psf->sf.format = SF_FORMAT_OGG | SF_FORMAT_SPEEX ;
|
||||
psf->sf.sections = 1 ;
|
||||
|
||||
psf->datalength = 1 ;
|
||||
psf->dataoffset = 0 ;
|
||||
/* End FIXME. */
|
||||
|
||||
return error ;
|
||||
} /* ogg_opus_open */
|
||||
|
||||
static int
|
||||
ogg_opus_read_header (SF_PRIVATE * UNUSED (psf))
|
||||
{
|
||||
return 0 ;
|
||||
} /* ogg_opus_read_header */
|
||||
|
||||
static int
|
||||
ogg_opus_close (SF_PRIVATE * UNUSED (psf))
|
||||
{
|
||||
|
||||
|
||||
return 0 ;
|
||||
} /* ogg_opus_close */
|
||||
|
||||
|
||||
#else /* ENABLE_EXPERIMENTAL_CODE && HAVE_EXTERNAL_LIBS */
|
||||
|
||||
int
|
||||
ogg_opus_open (SF_PRIVATE *psf)
|
||||
{
|
||||
psf_log_printf (psf, "This version of libsndfile was compiled without Ogg/Opus support.\n") ;
|
||||
return SFE_UNIMPLEMENTED ;
|
||||
} /* ogg_opus_open */
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
** Copyright (C) 2008-2012 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program 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 program 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 program ; if not, write to the Free Software
|
||||
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
|
||||
#include "sfconfig.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <time.h>
|
||||
#include <math.h>
|
||||
|
||||
#if HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "sndfile.h"
|
||||
#include "sfendian.h"
|
||||
#include "common.h"
|
||||
|
||||
#if (ENABLE_EXPERIMENTAL_CODE && HAVE_EXTERNAL_LIBS)
|
||||
|
||||
#include <ogg/ogg.h>
|
||||
|
||||
#include "ogg.h"
|
||||
|
||||
typedef struct
|
||||
{ int32_t serialno ;
|
||||
|
||||
|
||||
void * state ;
|
||||
} OPCM_PRIVATE ;
|
||||
|
||||
static int opcm_read_header (SF_PRIVATE * psf) ;
|
||||
static int opcm_close (SF_PRIVATE *psf) ;
|
||||
|
||||
int
|
||||
ogg_pcm_open (SF_PRIVATE *psf)
|
||||
{ OGG_PRIVATE* odata = psf->container_data ;
|
||||
OPCM_PRIVATE* opcm = calloc (1, sizeof (OPCM_PRIVATE)) ;
|
||||
int error = 0 ;
|
||||
|
||||
if (odata == NULL)
|
||||
{ psf_log_printf (psf, "%s : odata is NULL???\n", __func__) ;
|
||||
return SFE_INTERNAL ;
|
||||
} ;
|
||||
|
||||
psf->codec_data = opcm ;
|
||||
if (opcm == NULL)
|
||||
return SFE_MALLOC_FAILED ;
|
||||
|
||||
if (psf->file.mode == SFM_RDWR)
|
||||
return SFE_BAD_MODE_RW ;
|
||||
|
||||
if (psf->file.mode == SFM_READ)
|
||||
{ /* Call this here so it only gets called once, so no memory is leaked. */
|
||||
ogg_sync_init (&odata->osync) ;
|
||||
|
||||
if ((error = opcm_read_header (psf)))
|
||||
return error ;
|
||||
|
||||
#if 0
|
||||
psf->read_short = opcm_read_s ;
|
||||
psf->read_int = opcm_read_i ;
|
||||
psf->read_float = opcm_read_f ;
|
||||
psf->read_double = opcm_read_d ;
|
||||
psf->sf.frames = opcm_length (psf) ;
|
||||
#endif
|
||||
} ;
|
||||
|
||||
psf->codec_close = opcm_close ;
|
||||
|
||||
if (psf->file.mode == SFM_WRITE)
|
||||
{
|
||||
#if 0
|
||||
/* Set the default opcm quality here. */
|
||||
vdata->quality = 0.4 ;
|
||||
|
||||
psf->write_header = opcm_write_header ;
|
||||
psf->write_short = opcm_write_s ;
|
||||
psf->write_int = opcm_write_i ;
|
||||
psf->write_float = opcm_write_f ;
|
||||
psf->write_double = opcm_write_d ;
|
||||
#endif
|
||||
|
||||
psf->sf.frames = SF_COUNT_MAX ; /* Unknown really */
|
||||
psf->strings.flags = SF_STR_ALLOW_START ;
|
||||
} ;
|
||||
|
||||
psf->bytewidth = 1 ;
|
||||
psf->blockwidth = psf->bytewidth * psf->sf.channels ;
|
||||
|
||||
#if 0
|
||||
psf->seek = opcm_seek ;
|
||||
psf->command = opcm_command ;
|
||||
#endif
|
||||
|
||||
/* FIXME, FIXME, FIXME : Hack these here for now and correct later. */
|
||||
psf->sf.format = SF_FORMAT_OGG | SF_FORMAT_SPEEX ;
|
||||
psf->sf.sections = 1 ;
|
||||
|
||||
psf->datalength = 1 ;
|
||||
psf->dataoffset = 0 ;
|
||||
/* End FIXME. */
|
||||
|
||||
return error ;
|
||||
} /* ogg_pcm_open */
|
||||
|
||||
static int
|
||||
opcm_read_header (SF_PRIVATE * UNUSED (psf))
|
||||
{
|
||||
return 0 ;
|
||||
} /* opcm_read_header */
|
||||
|
||||
static int
|
||||
opcm_close (SF_PRIVATE * UNUSED (psf))
|
||||
{
|
||||
|
||||
|
||||
return 0 ;
|
||||
} /* opcm_close */
|
||||
|
||||
|
||||
|
||||
/*
|
||||
encoded_speex_frames = (frames_per_packet * Packets)
|
||||
= 1 * 272
|
||||
= 272
|
||||
|
||||
audio_samples = encoded_speex_frames * frame_size
|
||||
= 272 * 640
|
||||
= 174080
|
||||
|
||||
duration = audio_samples / rate
|
||||
= 174080 / 44100
|
||||
= 3.947
|
||||
*/
|
||||
|
||||
#else /* ENABLE_EXPERIMENTAL_CODE && HAVE_EXTERNAL_LIBS */
|
||||
|
||||
int
|
||||
ogg_pcm_open (SF_PRIVATE *psf)
|
||||
{
|
||||
psf_log_printf (psf, "This version of libsndfile was compiled without Ogg/Speex support.\n") ;
|
||||
return SFE_UNIMPLEMENTED ;
|
||||
} /* ogg_pcm_open */
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,425 @@
|
||||
/*
|
||||
** Copyright (C) 2008-2012 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program 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 program 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 program ; if not, write to the Free Software
|
||||
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
|
||||
#include "sfconfig.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <time.h>
|
||||
#include <math.h>
|
||||
|
||||
#if HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "sndfile.h"
|
||||
#include "sfendian.h"
|
||||
#include "common.h"
|
||||
|
||||
#if (ENABLE_EXPERIMENTAL_CODE && HAVE_EXTERNAL_LIBS)
|
||||
|
||||
#include <ogg/ogg.h>
|
||||
|
||||
#include <speex/speex.h>
|
||||
#include <speex/speex_stereo.h>
|
||||
#include <speex/speex_header.h>
|
||||
#include <speex/speex_callbacks.h>
|
||||
|
||||
#include "ogg.h"
|
||||
|
||||
#define OGG_SPX_READ_SIZE 200
|
||||
|
||||
typedef struct
|
||||
{ SpeexBits bits ;
|
||||
|
||||
int32_t serialno ;
|
||||
|
||||
int frame_size, granule_frame_size, nframes ;
|
||||
int force_mode ;
|
||||
|
||||
SpeexStereoState stereo ;
|
||||
SpeexHeader header ;
|
||||
|
||||
void * state ;
|
||||
} SPX_PRIVATE ;
|
||||
|
||||
static int spx_read_header (SF_PRIVATE * psf) ;
|
||||
static int spx_close (SF_PRIVATE *psf) ;
|
||||
static void *spx_header_read (SF_PRIVATE * psf, ogg_packet *op, spx_int32_t enh_enabled, int force_mode) ;
|
||||
static void spx_print_comments (const char *comments, int length) ;
|
||||
|
||||
int
|
||||
ogg_speex_open (SF_PRIVATE *psf)
|
||||
{ OGG_PRIVATE* odata = psf->container_data ;
|
||||
SPX_PRIVATE* spx = calloc (1, sizeof (SPX_PRIVATE)) ;
|
||||
int error = 0 ;
|
||||
|
||||
if (odata == NULL)
|
||||
{ psf_log_printf (psf, "%s : odata is NULL???\n", __func__) ;
|
||||
return SFE_INTERNAL ;
|
||||
} ;
|
||||
|
||||
psf->codec_data = spx ;
|
||||
if (spx == NULL)
|
||||
return SFE_MALLOC_FAILED ;
|
||||
|
||||
if (psf->file.mode == SFM_RDWR)
|
||||
return SFE_BAD_MODE_RW ;
|
||||
|
||||
if (psf->file.mode == SFM_READ)
|
||||
{ /* Call this here so it only gets called once, so no memory is leaked. */
|
||||
ogg_sync_init (&odata->osync) ;
|
||||
|
||||
if ((error = spx_read_header (psf)))
|
||||
return error ;
|
||||
|
||||
#if 0
|
||||
psf->read_short = spx_read_s ;
|
||||
psf->read_int = spx_read_i ;
|
||||
psf->read_float = spx_read_f ;
|
||||
psf->read_double = spx_read_d ;
|
||||
psf->sf.frames = spx_length (psf) ;
|
||||
#endif
|
||||
} ;
|
||||
|
||||
psf->codec_close = spx_close ;
|
||||
|
||||
if (psf->file.mode == SFM_WRITE)
|
||||
{
|
||||
#if 0
|
||||
/* Set the default spx quality here. */
|
||||
vdata->quality = 0.4 ;
|
||||
|
||||
psf->write_header = spx_write_header ;
|
||||
psf->write_short = spx_write_s ;
|
||||
psf->write_int = spx_write_i ;
|
||||
psf->write_float = spx_write_f ;
|
||||
psf->write_double = spx_write_d ;
|
||||
#endif
|
||||
|
||||
psf->sf.frames = SF_COUNT_MAX ; /* Unknown really */
|
||||
psf->strings.flags = SF_STR_ALLOW_START ;
|
||||
} ;
|
||||
|
||||
psf->bytewidth = 1 ;
|
||||
psf->blockwidth = psf->bytewidth * psf->sf.channels ;
|
||||
|
||||
#if 0
|
||||
psf->seek = spx_seek ;
|
||||
psf->command = spx_command ;
|
||||
#endif
|
||||
|
||||
/* FIXME, FIXME, FIXME : Hack these here for now and correct later. */
|
||||
psf->sf.format = SF_FORMAT_OGG | SF_FORMAT_SPEEX ;
|
||||
psf->sf.sections = 1 ;
|
||||
|
||||
psf->datalength = 1 ;
|
||||
psf->dataoffset = 0 ;
|
||||
/* End FIXME. */
|
||||
|
||||
return error ;
|
||||
} /* ogg_speex_open */
|
||||
|
||||
#define le_short (x) (x)
|
||||
|
||||
static int
|
||||
spx_read_header (SF_PRIVATE * psf)
|
||||
{ static SpeexStereoState STEREO_INIT = SPEEX_STEREO_STATE_INIT ;
|
||||
|
||||
OGG_PRIVATE* odata = psf->container_data ;
|
||||
SPX_PRIVATE* spx = psf->codec_data ;
|
||||
|
||||
ogg_int64_t page_granule = 0 ;
|
||||
int stream_init = 0 ;
|
||||
int page_nb_packets = 0 ;
|
||||
int packet_count = 0 ;
|
||||
int enh_enabled = 1 ;
|
||||
int force_mode = -1 ;
|
||||
char * data ;
|
||||
int nb_read ;
|
||||
int lookahead ;
|
||||
|
||||
printf ("%s %d\n", __func__, __LINE__) ;
|
||||
|
||||
psf_log_printf (psf, "Speex header\n") ;
|
||||
odata->eos = 0 ;
|
||||
|
||||
/* Reset ogg stuff which has already been used in src/ogg.c. */
|
||||
ogg_stream_reset (&odata->ostream) ;
|
||||
ogg_sync_reset (&odata->osync) ;
|
||||
|
||||
/* Seek to start of stream. */
|
||||
psf_fseek (psf, 0, SEEK_SET) ;
|
||||
|
||||
/* Initialize. */
|
||||
ogg_sync_init (&odata->osync) ;
|
||||
speex_bits_init (&spx->bits) ;
|
||||
|
||||
/* Set defaults. */
|
||||
psf->sf.channels = -1 ;
|
||||
psf->sf.samplerate = 0 ;
|
||||
spx->stereo = STEREO_INIT ;
|
||||
|
||||
/* Get a pointer to the ogg buffer and read data into it. */
|
||||
data = ogg_sync_buffer (&odata->osync, OGG_SPX_READ_SIZE) ;
|
||||
nb_read = psf_fread (data, 1, OGG_SPX_READ_SIZE, psf) ;
|
||||
ogg_sync_wrote (&odata->osync, nb_read) ;
|
||||
|
||||
/* Now we chew on Ogg packets. */
|
||||
while (ogg_sync_pageout (&odata->osync, &odata->opage) == 1)
|
||||
{ if (stream_init == 0)
|
||||
{ ogg_stream_init (&odata->ostream, ogg_page_serialno (&odata->opage)) ;
|
||||
stream_init = 1 ;
|
||||
} ;
|
||||
|
||||
if (ogg_page_serialno (&odata->opage) != odata->ostream.serialno)
|
||||
{ /* so all streams are read. */
|
||||
ogg_stream_reset_serialno (&odata->ostream, ogg_page_serialno (&odata->opage)) ;
|
||||
} ;
|
||||
|
||||
/*Add page to the bitstream*/
|
||||
ogg_stream_pagein (&odata->ostream, &odata->opage) ;
|
||||
page_granule = ogg_page_granulepos (&odata->opage) ;
|
||||
page_nb_packets = ogg_page_packets (&odata->opage) ;
|
||||
|
||||
/*Extract all available packets*/
|
||||
while (odata->eos == 0 && ogg_stream_packetout (&odata->ostream, &odata->opacket) == 1)
|
||||
{ if (odata->opacket.bytes >= 8 && memcmp (odata->opacket.packet, "Speex ", 8) == 0)
|
||||
{ spx->serialno = odata->ostream.serialno ;
|
||||
} ;
|
||||
|
||||
if (spx->serialno == -1 || odata->ostream.serialno != spx->serialno)
|
||||
break ;
|
||||
|
||||
if (packet_count == 0)
|
||||
{ spx->state = spx_header_read (psf, &odata->opacket, enh_enabled, force_mode) ;
|
||||
if (! spx->state)
|
||||
break ;
|
||||
|
||||
speex_decoder_ctl (spx->state, SPEEX_GET_LOOKAHEAD, &lookahead) ;
|
||||
if (spx->nframes == 0)
|
||||
spx->nframes = 1 ;
|
||||
}
|
||||
else if (packet_count == 1)
|
||||
{ spx_print_comments ((const char*) odata->opacket.packet, odata->opacket.bytes) ;
|
||||
}
|
||||
else if (packet_count < 2 + spx->header.extra_headers)
|
||||
{ /* Ignore extra headers */
|
||||
}
|
||||
packet_count ++ ;
|
||||
} ;
|
||||
} ;
|
||||
|
||||
psf_log_printf (psf, "End\n") ;
|
||||
|
||||
psf_log_printf (psf, "packet_count %d\n", packet_count) ;
|
||||
psf_log_printf (psf, "page_nb_packets %d\n", page_nb_packets) ;
|
||||
psf_log_printf (psf, "page_granule %lld\n", page_granule) ;
|
||||
|
||||
return 0 ;
|
||||
} /* spx_read_header */
|
||||
|
||||
static int
|
||||
spx_close (SF_PRIVATE *psf)
|
||||
{ SPX_PRIVATE* spx = psf->codec_data ;
|
||||
|
||||
if (spx->state)
|
||||
speex_decoder_destroy (spx->state) ;
|
||||
|
||||
if (spx)
|
||||
speex_bits_destroy (&spx->bits) ;
|
||||
|
||||
return 0 ;
|
||||
} /* spx_close */
|
||||
|
||||
|
||||
|
||||
static void *
|
||||
spx_header_read (SF_PRIVATE * psf, ogg_packet *op, spx_int32_t enh_enabled, int force_mode)
|
||||
{ SPX_PRIVATE* spx = psf->codec_data ;
|
||||
void *st ;
|
||||
const SpeexMode *mode ;
|
||||
SpeexHeader *tmp_header ;
|
||||
int modeID ;
|
||||
SpeexCallback callback ;
|
||||
|
||||
tmp_header = speex_packet_to_header ((char*) op->packet, op->bytes) ;
|
||||
if (tmp_header == NULL)
|
||||
{ psf_log_printf (psf, "Cannot read Speex header\n") ;
|
||||
return NULL ;
|
||||
} ;
|
||||
|
||||
memcpy (&spx->header, tmp_header, sizeof (spx->header)) ;
|
||||
free (tmp_header) ;
|
||||
tmp_header = NULL ;
|
||||
|
||||
if (spx->header.mode >= SPEEX_NB_MODES || spx->header.mode < 0)
|
||||
{ psf_log_printf (psf, "Mode number %d does not (yet/any longer) exist in this version\n", spx->header.mode) ;
|
||||
return NULL ;
|
||||
} ;
|
||||
|
||||
modeID = spx->header.mode ;
|
||||
if (force_mode != -1)
|
||||
modeID = force_mode ;
|
||||
|
||||
mode = speex_lib_get_mode (modeID) ;
|
||||
|
||||
if (spx->header.speex_version_id > 1)
|
||||
{ psf_log_printf (psf, "This file was encoded with Speex bit-stream version %d, which I don't know how to decode\n", spx->header.speex_version_id) ;
|
||||
return NULL ;
|
||||
} ;
|
||||
|
||||
if (mode->bitstream_version < spx->header.mode_bitstream_version)
|
||||
{ psf_log_printf (psf, "The file was encoded with a newer version of Speex. You need to upgrade in order to play it.\n") ;
|
||||
return NULL ;
|
||||
} ;
|
||||
|
||||
if (mode->bitstream_version > spx->header.mode_bitstream_version)
|
||||
{ psf_log_printf (psf, "The file was encoded with an older version of Speex. You would need to downgrade the version in order to play it.\n") ;
|
||||
return NULL ;
|
||||
} ;
|
||||
|
||||
st = speex_decoder_init (mode) ;
|
||||
if (!st)
|
||||
{ psf_log_printf (psf, "Decoder initialization failed.\n") ;
|
||||
return NULL ;
|
||||
} ;
|
||||
|
||||
speex_decoder_ctl (st, SPEEX_SET_ENH, &enh_enabled) ;
|
||||
speex_decoder_ctl (st, SPEEX_GET_FRAME_SIZE, &spx->frame_size) ;
|
||||
spx->granule_frame_size = spx->frame_size ;
|
||||
|
||||
if (!psf->sf.samplerate)
|
||||
psf->sf.samplerate = spx->header.rate ;
|
||||
/* Adjust rate if --force-* options are used */
|
||||
if (force_mode != -1)
|
||||
{ if (spx->header.mode < force_mode)
|
||||
{ psf->sf.samplerate <<= (force_mode - spx->header.mode) ;
|
||||
spx->granule_frame_size >>= (force_mode - spx->header.mode) ;
|
||||
} ;
|
||||
if (spx->header.mode > force_mode)
|
||||
{ psf->sf.samplerate >>= (spx->header.mode - force_mode) ;
|
||||
spx->granule_frame_size <<= (spx->header.mode - force_mode) ;
|
||||
} ;
|
||||
} ;
|
||||
|
||||
speex_decoder_ctl (st, SPEEX_SET_SAMPLING_RATE, &psf->sf.samplerate) ;
|
||||
|
||||
spx->nframes = spx->header.frames_per_packet ;
|
||||
|
||||
if (psf->sf.channels == -1)
|
||||
psf->sf.channels = spx->header.nb_channels ;
|
||||
|
||||
if (! (psf->sf.channels == 1))
|
||||
{ psf->sf.channels = 2 ;
|
||||
callback.callback_id = SPEEX_INBAND_STEREO ;
|
||||
callback.func = speex_std_stereo_request_handler ;
|
||||
callback.data = &spx->stereo ;
|
||||
speex_decoder_ctl (st, SPEEX_SET_HANDLER, &callback) ;
|
||||
} ;
|
||||
|
||||
spx->header.speex_version [sizeof (spx->header.speex_version) - 1] = 0 ;
|
||||
|
||||
psf_log_printf (psf, " Encoder ver : %s\n Frames/packet : %d\n",
|
||||
spx->header.speex_version, spx->header.frames_per_packet) ;
|
||||
|
||||
if (spx->header.bitrate > 0)
|
||||
psf_log_printf (psf, " Bit rate : %d\n", spx->header.bitrate) ;
|
||||
|
||||
psf_log_printf (psf, " Sample rate : %d\n Mode : %s\n VBR : %s\n Channels : %d\n",
|
||||
psf->sf.samplerate, mode->modeName, (spx->header.vbr ? "yes" : "no"), psf->sf.channels) ;
|
||||
|
||||
psf_log_printf (psf, " Extra headers : %d\n", spx->header.extra_headers) ;
|
||||
|
||||
return st ;
|
||||
} /* spx_header_read */
|
||||
|
||||
|
||||
static void
|
||||
spx_print_comments (const char *c, int length)
|
||||
{
|
||||
const char *end ;
|
||||
int len, i, nb_fields ;
|
||||
|
||||
printf ("%s %d\n", __func__, __LINE__) ;
|
||||
if (length < 8)
|
||||
{ fprintf (stderr, "Invalid/corrupted comments\n") ;
|
||||
return ;
|
||||
}
|
||||
end = c + length ;
|
||||
len = readint (c, 0) ;
|
||||
c += 4 ;
|
||||
if (len < 0 || c + len > end)
|
||||
{ fprintf (stderr, "Invalid/corrupted comments\n") ;
|
||||
return ;
|
||||
}
|
||||
(void) fwrite (c, 1, len, stderr) ;
|
||||
c += len ;
|
||||
fprintf (stderr, "\n") ;
|
||||
if (c + 4 > end)
|
||||
{ fprintf (stderr, "Invalid/corrupted comments\n") ;
|
||||
return ;
|
||||
}
|
||||
nb_fields = readint (c, 0) ;
|
||||
c += 4 ;
|
||||
for (i = 0 ; i < nb_fields ; i++)
|
||||
{ if (c + 4 > end)
|
||||
{ fprintf (stderr, "Invalid/corrupted comments\n") ;
|
||||
return ;
|
||||
} ;
|
||||
len = readint (c, 0) ;
|
||||
c += 4 ;
|
||||
if (len < 0 || c + len > end)
|
||||
{ fprintf (stderr, "Invalid/corrupted comments\n") ;
|
||||
return ;
|
||||
}
|
||||
(void) fwrite (c, 1, len, stderr) ;
|
||||
c += len ;
|
||||
fprintf (stderr, "\n") ;
|
||||
} ;
|
||||
return ;
|
||||
} /* spx_print_comments */
|
||||
|
||||
|
||||
/*
|
||||
encoded_speex_frames = (frames_per_packet * Packets)
|
||||
= 1 * 272
|
||||
= 272
|
||||
|
||||
audio_samples = encoded_speex_frames * frame_size
|
||||
= 272 * 640
|
||||
= 174080
|
||||
|
||||
duration = audio_samples / rate
|
||||
= 174080 / 44100
|
||||
= 3.947
|
||||
*/
|
||||
|
||||
#else /* ENABLE_EXPERIMENTAL_CODE && HAVE_EXTERNAL_LIBS */
|
||||
|
||||
int
|
||||
ogg_speex_open (SF_PRIVATE *psf)
|
||||
{
|
||||
psf_log_printf (psf, "This version of libsndfile was compiled without Ogg/Speex support.\n") ;
|
||||
return SFE_UNIMPLEMENTED ;
|
||||
} /* ogg_speex_open */
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large.
Load diff
+63
-74
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** Copyright (C) 1999-2009 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
** Copyright (C) 1999-2013 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
@@ -52,23 +52,19 @@
|
||||
typedef struct
|
||||
{ int version ;
|
||||
int endianness ;
|
||||
int samplerate ;
|
||||
int format ;
|
||||
int samplerate ;
|
||||
int format ;
|
||||
int channels ;
|
||||
int source ;
|
||||
} PAF_FMT ;
|
||||
|
||||
typedef struct
|
||||
{ int max_blocks, channels, samplesperblock, blocksize ;
|
||||
{ int max_blocks, channels, blocksize ;
|
||||
int read_block, write_block, read_count, write_count ;
|
||||
sf_count_t sample_count ;
|
||||
int *samples ;
|
||||
unsigned char *block ;
|
||||
#if HAVE_FLEXIBLE_ARRAY
|
||||
int data [] ; /* ISO C99 struct flexible array. */
|
||||
#else
|
||||
int data [1] ; /* This is a hack and may not work. */
|
||||
#endif
|
||||
} PAF24_PRIVATE ;
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
@@ -108,14 +104,14 @@ paf_open (SF_PRIVATE *psf)
|
||||
|
||||
psf->dataoffset = PAF_HEADER_LENGTH ;
|
||||
|
||||
if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->filelength > 0))
|
||||
if (psf->file.mode == SFM_READ || (psf->file.mode == SFM_RDWR && psf->filelength > 0))
|
||||
{ if ((error = paf_read_header (psf)))
|
||||
return error ;
|
||||
} ;
|
||||
|
||||
subformat = SF_CODEC (psf->sf.format) ;
|
||||
|
||||
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
|
||||
if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
|
||||
{ if ((SF_CONTAINER (psf->sf.format)) != SF_FORMAT_PAF)
|
||||
return SFE_BAD_OPEN_FORMAT ;
|
||||
|
||||
@@ -163,6 +159,9 @@ paf_read_header (SF_PRIVATE *psf)
|
||||
{ PAF_FMT paf_fmt ;
|
||||
int marker ;
|
||||
|
||||
if (psf->filelength < PAF_HEADER_LENGTH)
|
||||
return SFE_PAF_SHORT_HEADER ;
|
||||
|
||||
memset (&paf_fmt, 0, sizeof (paf_fmt)) ;
|
||||
psf_binheader_readf (psf, "pm", 0, &marker) ;
|
||||
|
||||
@@ -199,8 +198,8 @@ paf_read_header (SF_PRIVATE *psf)
|
||||
psf->endian = SF_ENDIAN_BIG ;
|
||||
} ;
|
||||
|
||||
if (psf->filelength < PAF_HEADER_LENGTH)
|
||||
return SFE_PAF_SHORT_HEADER ;
|
||||
if (paf_fmt.channels < 1 || paf_fmt.channels > SF_MAX_CHANNELS)
|
||||
return SFE_PAF_BAD_CHANNELS ;
|
||||
|
||||
psf->datalength = psf->filelength - psf->dataoffset ;
|
||||
|
||||
@@ -356,20 +355,18 @@ paf24_init (SF_PRIVATE *psf)
|
||||
*/
|
||||
psf->last_op = 0 ;
|
||||
|
||||
if (! (psf->codec_data = malloc (paf24size)))
|
||||
if (! (psf->codec_data = calloc (1, paf24size)))
|
||||
return SFE_MALLOC_FAILED ;
|
||||
|
||||
ppaf24 = (PAF24_PRIVATE*) psf->codec_data ;
|
||||
memset (ppaf24, 0, paf24size) ;
|
||||
|
||||
ppaf24->channels = psf->sf.channels ;
|
||||
ppaf24->samples = ppaf24->data ;
|
||||
ppaf24->block = (unsigned char*) (ppaf24->data + PAF24_SAMPLES_PER_BLOCK * ppaf24->channels) ;
|
||||
|
||||
ppaf24->blocksize = PAF24_BLOCK_SIZE * ppaf24->channels ;
|
||||
ppaf24->samplesperblock = PAF24_SAMPLES_PER_BLOCK ;
|
||||
|
||||
if (psf->mode == SFM_READ || psf->mode == SFM_RDWR)
|
||||
if (psf->file.mode == SFM_READ || psf->file.mode == SFM_RDWR)
|
||||
{ paf24_read_block (psf, ppaf24) ; /* Read first block. */
|
||||
|
||||
psf->read_short = paf24_read_s ;
|
||||
@@ -378,7 +375,7 @@ paf24_init (SF_PRIVATE *psf)
|
||||
psf->read_double = paf24_read_d ;
|
||||
} ;
|
||||
|
||||
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
|
||||
if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
|
||||
{ psf->write_short = paf24_write_s ;
|
||||
psf->write_int = paf24_write_i ;
|
||||
psf->write_float = paf24_write_f ;
|
||||
@@ -392,7 +389,7 @@ paf24_init (SF_PRIVATE *psf)
|
||||
psf->datalength = psf->filelength - psf->dataoffset ;
|
||||
|
||||
if (psf->datalength % PAF24_BLOCK_SIZE)
|
||||
{ if (psf->mode == SFM_READ)
|
||||
{ if (psf->file.mode == SFM_READ)
|
||||
psf_log_printf (psf, "*** Warning : file seems to be truncated.\n") ;
|
||||
ppaf24->max_blocks = psf->datalength / ppaf24->blocksize + 1 ;
|
||||
}
|
||||
@@ -400,12 +397,12 @@ paf24_init (SF_PRIVATE *psf)
|
||||
ppaf24->max_blocks = psf->datalength / ppaf24->blocksize ;
|
||||
|
||||
ppaf24->read_block = 0 ;
|
||||
if (psf->mode == SFM_RDWR)
|
||||
if (psf->file.mode == SFM_RDWR)
|
||||
ppaf24->write_block = ppaf24->max_blocks ;
|
||||
else
|
||||
ppaf24->write_block = 0 ;
|
||||
|
||||
psf->sf.frames = ppaf24->samplesperblock * ppaf24->max_blocks ;
|
||||
psf->sf.frames = PAF24_SAMPLES_PER_BLOCK * ppaf24->max_blocks ;
|
||||
ppaf24->sample_count = psf->sf.frames ;
|
||||
|
||||
return 0 ;
|
||||
@@ -426,8 +423,8 @@ paf24_seek (SF_PRIVATE *psf, int mode, sf_count_t offset)
|
||||
if (mode == SFM_READ && ppaf24->write_count > 0)
|
||||
paf24_write_block (psf, ppaf24) ;
|
||||
|
||||
newblock = offset / ppaf24->samplesperblock ;
|
||||
newsample = offset % ppaf24->samplesperblock ;
|
||||
newblock = offset / PAF24_SAMPLES_PER_BLOCK ;
|
||||
newsample = offset % PAF24_SAMPLES_PER_BLOCK ;
|
||||
|
||||
switch (mode)
|
||||
{ case SFM_READ :
|
||||
@@ -460,7 +457,7 @@ paf24_seek (SF_PRIVATE *psf, int mode, sf_count_t offset)
|
||||
return PSF_SEEK_ERROR ;
|
||||
} ;
|
||||
|
||||
return newblock * ppaf24->samplesperblock + newsample ;
|
||||
return newblock * PAF24_SAMPLES_PER_BLOCK + newsample ;
|
||||
} /* paf24_seek */
|
||||
|
||||
static int
|
||||
@@ -472,7 +469,7 @@ paf24_close (SF_PRIVATE *psf)
|
||||
|
||||
ppaf24 = (PAF24_PRIVATE*) psf->codec_data ;
|
||||
|
||||
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
|
||||
if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
|
||||
{ if (ppaf24->write_count > 0)
|
||||
paf24_write_block (psf, ppaf24) ;
|
||||
} ;
|
||||
@@ -490,8 +487,8 @@ paf24_read_block (SF_PRIVATE *psf, PAF24_PRIVATE *ppaf24)
|
||||
ppaf24->read_block ++ ;
|
||||
ppaf24->read_count = 0 ;
|
||||
|
||||
if (ppaf24->read_block * ppaf24->samplesperblock > ppaf24->sample_count)
|
||||
{ memset (ppaf24->samples, 0, ppaf24->samplesperblock * ppaf24->channels) ;
|
||||
if (ppaf24->read_block * PAF24_SAMPLES_PER_BLOCK > ppaf24->sample_count)
|
||||
{ memset (ppaf24->samples, 0, PAF24_SAMPLES_PER_BLOCK * ppaf24->channels) ;
|
||||
return 1 ;
|
||||
} ;
|
||||
|
||||
@@ -500,29 +497,15 @@ paf24_read_block (SF_PRIVATE *psf, PAF24_PRIVATE *ppaf24)
|
||||
psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, ppaf24->blocksize) ;
|
||||
|
||||
|
||||
if (CPU_IS_LITTLE_ENDIAN)
|
||||
{ /* Do endian swapping if necessary. */
|
||||
if (psf->endian == SF_ENDIAN_BIG)
|
||||
endswap_int_array (ppaf24->data, 8 * ppaf24->channels) ;
|
||||
/* Do endian swapping if necessary. */
|
||||
if (psf->endian == SF_ENDIAN_BIG)
|
||||
endswap_int_array (ppaf24->data, 8 * ppaf24->channels) ;
|
||||
|
||||
/* Unpack block. */
|
||||
for (k = 0 ; k < PAF24_SAMPLES_PER_BLOCK * ppaf24->channels ; k++)
|
||||
{ channel = k % ppaf24->channels ;
|
||||
cptr = ppaf24->block + PAF24_BLOCK_SIZE * channel + 3 * (k / ppaf24->channels) ;
|
||||
ppaf24->samples [k] = (cptr [0] << 8) | (cptr [1] << 16) | (cptr [2] << 24) ;
|
||||
} ;
|
||||
}
|
||||
else
|
||||
{ /* Do endian swapping if necessary. */
|
||||
if (psf->endian == SF_ENDIAN_BIG)
|
||||
endswap_int_array (ppaf24->data, 8 * ppaf24->channels) ;
|
||||
|
||||
/* Unpack block. */
|
||||
for (k = 0 ; k < PAF24_SAMPLES_PER_BLOCK * ppaf24->channels ; k++)
|
||||
{ channel = k % ppaf24->channels ;
|
||||
cptr = ppaf24->block + PAF24_BLOCK_SIZE * channel + 3 * (k / ppaf24->channels) ;
|
||||
ppaf24->samples [k] = (cptr [0] << 8) | (cptr [1] << 16) | (cptr [2] << 24) ;
|
||||
} ;
|
||||
/* Unpack block. */
|
||||
for (k = 0 ; k < PAF24_SAMPLES_PER_BLOCK * ppaf24->channels ; k++)
|
||||
{ channel = k % ppaf24->channels ;
|
||||
cptr = ppaf24->block + PAF24_BLOCK_SIZE * channel + 3 * (k / ppaf24->channels) ;
|
||||
ppaf24->samples [k] = (cptr [0] << 8) | (cptr [1] << 16) | (cptr [2] << 24) ;
|
||||
} ;
|
||||
|
||||
return 1 ;
|
||||
@@ -533,15 +516,15 @@ paf24_read (SF_PRIVATE *psf, PAF24_PRIVATE *ppaf24, int *ptr, int len)
|
||||
{ int count, total = 0 ;
|
||||
|
||||
while (total < len)
|
||||
{ if (ppaf24->read_block * ppaf24->samplesperblock >= ppaf24->sample_count)
|
||||
{ if (ppaf24->read_block * PAF24_SAMPLES_PER_BLOCK >= ppaf24->sample_count)
|
||||
{ memset (&(ptr [total]), 0, (len - total) * sizeof (int)) ;
|
||||
return total ;
|
||||
} ;
|
||||
|
||||
if (ppaf24->read_count >= ppaf24->samplesperblock)
|
||||
if (ppaf24->read_count >= PAF24_SAMPLES_PER_BLOCK)
|
||||
paf24_read_block (psf, ppaf24) ;
|
||||
|
||||
count = (ppaf24->samplesperblock - ppaf24->read_count) * ppaf24->channels ;
|
||||
count = (PAF24_SAMPLES_PER_BLOCK - ppaf24->read_count) * ppaf24->channels ;
|
||||
count = (len - total > count) ? count : len - total ;
|
||||
|
||||
memcpy (&(ptr [total]), &(ppaf24->samples [ppaf24->read_count * ppaf24->channels]), count * sizeof (int)) ;
|
||||
@@ -554,7 +537,8 @@ paf24_read (SF_PRIVATE *psf, PAF24_PRIVATE *ppaf24, int *ptr, int len)
|
||||
|
||||
static sf_count_t
|
||||
paf24_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
|
||||
{ PAF24_PRIVATE *ppaf24 ;
|
||||
{ BUF_UNION ubuf ;
|
||||
PAF24_PRIVATE *ppaf24 ;
|
||||
int *iptr ;
|
||||
int k, bufferlen, readcount, count ;
|
||||
sf_count_t total = 0 ;
|
||||
@@ -563,8 +547,8 @@ paf24_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
|
||||
return 0 ;
|
||||
ppaf24 = (PAF24_PRIVATE*) psf->codec_data ;
|
||||
|
||||
iptr = psf->u.ibuf ;
|
||||
bufferlen = ARRAY_LEN (psf->u.ibuf) ;
|
||||
iptr = ubuf.ibuf ;
|
||||
bufferlen = ARRAY_LEN (ubuf.ibuf) ;
|
||||
while (len > 0)
|
||||
{ readcount = (len >= bufferlen) ? bufferlen : len ;
|
||||
count = paf24_read (psf, ppaf24, iptr, readcount) ;
|
||||
@@ -592,7 +576,8 @@ paf24_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
|
||||
|
||||
static sf_count_t
|
||||
paf24_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
|
||||
{ PAF24_PRIVATE *ppaf24 ;
|
||||
{ BUF_UNION ubuf ;
|
||||
PAF24_PRIVATE *ppaf24 ;
|
||||
int *iptr ;
|
||||
int k, bufferlen, readcount, count ;
|
||||
sf_count_t total = 0 ;
|
||||
@@ -604,8 +589,8 @@ paf24_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
|
||||
|
||||
normfact = (psf->norm_float == SF_TRUE) ? (1.0 / 0x80000000) : (1.0 / 0x100) ;
|
||||
|
||||
iptr = psf->u.ibuf ;
|
||||
bufferlen = ARRAY_LEN (psf->u.ibuf) ;
|
||||
iptr = ubuf.ibuf ;
|
||||
bufferlen = ARRAY_LEN (ubuf.ibuf) ;
|
||||
while (len > 0)
|
||||
{ readcount = (len >= bufferlen) ? bufferlen : len ;
|
||||
count = paf24_read (psf, ppaf24, iptr, readcount) ;
|
||||
@@ -619,7 +604,8 @@ paf24_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
|
||||
|
||||
static sf_count_t
|
||||
paf24_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
|
||||
{ PAF24_PRIVATE *ppaf24 ;
|
||||
{ BUF_UNION ubuf ;
|
||||
PAF24_PRIVATE *ppaf24 ;
|
||||
int *iptr ;
|
||||
int k, bufferlen, readcount, count ;
|
||||
sf_count_t total = 0 ;
|
||||
@@ -631,8 +617,8 @@ paf24_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
|
||||
|
||||
normfact = (psf->norm_double == SF_TRUE) ? (1.0 / 0x80000000) : (1.0 / 0x100) ;
|
||||
|
||||
iptr = psf->u.ibuf ;
|
||||
bufferlen = ARRAY_LEN (psf->u.ibuf) ;
|
||||
iptr = ubuf.ibuf ;
|
||||
bufferlen = ARRAY_LEN (ubuf.ibuf) ;
|
||||
while (len > 0)
|
||||
{ readcount = (len >= bufferlen) ? bufferlen : len ;
|
||||
count = paf24_read (psf, ppaf24, iptr, readcount) ;
|
||||
@@ -686,10 +672,10 @@ paf24_write_block (SF_PRIVATE *psf, PAF24_PRIVATE *ppaf24)
|
||||
if ((k = psf_fwrite (ppaf24->block, 1, ppaf24->blocksize, psf)) != ppaf24->blocksize)
|
||||
psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", k, ppaf24->blocksize) ;
|
||||
|
||||
if (ppaf24->sample_count < ppaf24->write_block * ppaf24->samplesperblock + ppaf24->write_count)
|
||||
ppaf24->sample_count = ppaf24->write_block * ppaf24->samplesperblock + ppaf24->write_count ;
|
||||
if (ppaf24->sample_count < ppaf24->write_block * PAF24_SAMPLES_PER_BLOCK + ppaf24->write_count)
|
||||
ppaf24->sample_count = ppaf24->write_block * PAF24_SAMPLES_PER_BLOCK + ppaf24->write_count ;
|
||||
|
||||
if (ppaf24->write_count == ppaf24->samplesperblock)
|
||||
if (ppaf24->write_count == PAF24_SAMPLES_PER_BLOCK)
|
||||
{ ppaf24->write_block ++ ;
|
||||
ppaf24->write_count = 0 ;
|
||||
} ;
|
||||
@@ -702,7 +688,7 @@ paf24_write (SF_PRIVATE *psf, PAF24_PRIVATE *ppaf24, const int *ptr, int len)
|
||||
{ int count, total = 0 ;
|
||||
|
||||
while (total < len)
|
||||
{ count = (ppaf24->samplesperblock - ppaf24->write_count) * ppaf24->channels ;
|
||||
{ count = (PAF24_SAMPLES_PER_BLOCK - ppaf24->write_count) * ppaf24->channels ;
|
||||
|
||||
if (count > len - total)
|
||||
count = len - total ;
|
||||
@@ -711,7 +697,7 @@ paf24_write (SF_PRIVATE *psf, PAF24_PRIVATE *ppaf24, const int *ptr, int len)
|
||||
total += count ;
|
||||
ppaf24->write_count += count / ppaf24->channels ;
|
||||
|
||||
if (ppaf24->write_count >= ppaf24->samplesperblock)
|
||||
if (ppaf24->write_count >= PAF24_SAMPLES_PER_BLOCK)
|
||||
paf24_write_block (psf, ppaf24) ;
|
||||
} ;
|
||||
|
||||
@@ -720,7 +706,8 @@ paf24_write (SF_PRIVATE *psf, PAF24_PRIVATE *ppaf24, const int *ptr, int len)
|
||||
|
||||
static sf_count_t
|
||||
paf24_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len)
|
||||
{ PAF24_PRIVATE *ppaf24 ;
|
||||
{ BUF_UNION ubuf ;
|
||||
PAF24_PRIVATE *ppaf24 ;
|
||||
int *iptr ;
|
||||
int k, bufferlen, writecount = 0, count ;
|
||||
sf_count_t total = 0 ;
|
||||
@@ -729,8 +716,8 @@ paf24_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len)
|
||||
return 0 ;
|
||||
ppaf24 = (PAF24_PRIVATE*) psf->codec_data ;
|
||||
|
||||
iptr = psf->u.ibuf ;
|
||||
bufferlen = ARRAY_LEN (psf->u.ibuf) ;
|
||||
iptr = ubuf.ibuf ;
|
||||
bufferlen = ARRAY_LEN (ubuf.ibuf) ;
|
||||
while (len > 0)
|
||||
{ writecount = (len >= bufferlen) ? bufferlen : len ;
|
||||
for (k = 0 ; k < writecount ; k++)
|
||||
@@ -770,7 +757,8 @@ paf24_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len)
|
||||
|
||||
static sf_count_t
|
||||
paf24_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
|
||||
{ PAF24_PRIVATE *ppaf24 ;
|
||||
{ BUF_UNION ubuf ;
|
||||
PAF24_PRIVATE *ppaf24 ;
|
||||
int *iptr ;
|
||||
int k, bufferlen, writecount = 0, count ;
|
||||
sf_count_t total = 0 ;
|
||||
@@ -782,8 +770,8 @@ paf24_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
|
||||
|
||||
normfact = (psf->norm_float == SF_TRUE) ? (1.0 * 0x7FFFFFFF) : (1.0 / 0x100) ;
|
||||
|
||||
iptr = psf->u.ibuf ;
|
||||
bufferlen = ARRAY_LEN (psf->u.ibuf) ;
|
||||
iptr = ubuf.ibuf ;
|
||||
bufferlen = ARRAY_LEN (ubuf.ibuf) ;
|
||||
while (len > 0)
|
||||
{ writecount = (len >= bufferlen) ? bufferlen : len ;
|
||||
for (k = 0 ; k < writecount ; k++)
|
||||
@@ -800,7 +788,8 @@ paf24_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
|
||||
|
||||
static sf_count_t
|
||||
paf24_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
|
||||
{ PAF24_PRIVATE *ppaf24 ;
|
||||
{ BUF_UNION ubuf ;
|
||||
PAF24_PRIVATE *ppaf24 ;
|
||||
int *iptr ;
|
||||
int k, bufferlen, writecount = 0, count ;
|
||||
sf_count_t total = 0 ;
|
||||
@@ -812,8 +801,8 @@ paf24_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
|
||||
|
||||
normfact = (psf->norm_double == SF_TRUE) ? (1.0 * 0x7FFFFFFF) : (1.0 / 0x100) ;
|
||||
|
||||
iptr = psf->u.ibuf ;
|
||||
bufferlen = ARRAY_LEN (psf->u.ibuf) ;
|
||||
iptr = ubuf.ibuf ;
|
||||
bufferlen = ARRAY_LEN (ubuf.ibuf) ;
|
||||
while (len > 0)
|
||||
{ writecount = (len >= bufferlen) ? bufferlen : len ;
|
||||
for (k = 0 ; k < writecount ; k++)
|
||||
|
||||
+323
-263
File diff suppressed because it is too large.
Load diff
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** Copyright (C) 2002-2009 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
** Copyright (C) 2002-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
@@ -51,14 +51,14 @@ pvf_open (SF_PRIVATE *psf)
|
||||
{ int subformat ;
|
||||
int error = 0 ;
|
||||
|
||||
if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->filelength > 0))
|
||||
if (psf->file.mode == SFM_READ || (psf->file.mode == SFM_RDWR && psf->filelength > 0))
|
||||
{ if ((error = pvf_read_header (psf)))
|
||||
return error ;
|
||||
} ;
|
||||
|
||||
subformat = SF_CODEC (psf->sf.format) ;
|
||||
|
||||
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
|
||||
if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
|
||||
{ if ((SF_CONTAINER (psf->sf.format)) != SF_FORMAT_PVF)
|
||||
return SFE_BAD_OPEN_FORMAT ;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** Copyright (C) 1999-2009 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
** Copyright (C) 1999-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
|
||||
+286
-56
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
** Copyright (C) 2008-2009 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
** Copyright (C) 2008-2013 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
** Copyright (C) 2009 Uli Franke <cls@nebadje.org>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
@@ -19,6 +20,9 @@
|
||||
/*
|
||||
** This format documented at:
|
||||
** http://www.sr.se/utveckling/tu/bwf/prog/RF_64v1_4.pdf
|
||||
**
|
||||
** But this may be a better reference:
|
||||
** http://www.ebu.ch/CMSimages/en/tec_doc_t3306-2007_tcm6-42570.pdf
|
||||
*/
|
||||
|
||||
#include "sfconfig.h"
|
||||
@@ -44,6 +48,11 @@
|
||||
#define fact_MARKER MAKE_MARKER ('f', 'a', 'c', 't')
|
||||
#define data_MARKER MAKE_MARKER ('d', 'a', 't', 'a')
|
||||
|
||||
#define bext_MARKER MAKE_MARKER ('b', 'e', 'x', 't')
|
||||
#define cart_MARKER MAKE_MARKER ('c', 'a', 'r', 't')
|
||||
#define OggS_MARKER MAKE_MARKER ('O', 'g', 'g', 'S')
|
||||
#define wvpk_MARKER MAKE_MARKER ('w', 'v', 'p', 'k')
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
** Typedefs.
|
||||
*/
|
||||
@@ -52,9 +61,10 @@
|
||||
** Private static functions.
|
||||
*/
|
||||
|
||||
static int rf64_read_header (SF_PRIVATE *psf) ;
|
||||
static int rf64_read_header (SF_PRIVATE *psf, int *blockalign, int *framesperblock) ;
|
||||
static int rf64_write_header (SF_PRIVATE *psf, int calc_length) ;
|
||||
static int rf64_close (SF_PRIVATE *psf) ;
|
||||
static int rf64_command (SF_PRIVATE *psf, int command, void * UNUSED (data), int datasize) ;
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
** Public function.
|
||||
@@ -64,17 +74,19 @@ int
|
||||
rf64_open (SF_PRIVATE *psf)
|
||||
{ WAV_PRIVATE *wpriv ;
|
||||
int subformat, error = 0 ;
|
||||
int blockalign, framesperblock ;
|
||||
|
||||
if ((wpriv = calloc (1, sizeof (WAV_PRIVATE))) == NULL)
|
||||
return SFE_MALLOC_FAILED ;
|
||||
psf->container_data = wpriv ;
|
||||
wpriv->wavex_ambisonic = SF_AMBISONIC_NONE ;
|
||||
|
||||
/* All RF64 files are little endian. */
|
||||
psf->endian = SF_ENDIAN_LITTLE ;
|
||||
|
||||
|
||||
if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->filelength > 0))
|
||||
{ if ((error = rf64_read_header (psf)) != 0)
|
||||
if (psf->file.mode == SFM_READ || (psf->file.mode == SFM_RDWR && psf->filelength > 0))
|
||||
{ if ((error = rf64_read_header (psf, &blockalign, &framesperblock)) != 0)
|
||||
return error ;
|
||||
} ;
|
||||
|
||||
@@ -83,7 +95,7 @@ rf64_open (SF_PRIVATE *psf)
|
||||
|
||||
subformat = psf->sf.format & SF_FORMAT_SUBMASK ;
|
||||
|
||||
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
|
||||
if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
|
||||
{ if (psf->is_pipe)
|
||||
return SFE_NO_PIPE_WRITE ;
|
||||
|
||||
@@ -96,6 +108,7 @@ rf64_open (SF_PRIVATE *psf)
|
||||
} ;
|
||||
|
||||
psf->container_close = rf64_close ;
|
||||
psf->command = rf64_command ;
|
||||
|
||||
switch (subformat)
|
||||
{ case SF_FORMAT_PCM_U8 :
|
||||
@@ -132,68 +145,162 @@ rf64_open (SF_PRIVATE *psf)
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
*/
|
||||
enum
|
||||
{ HAVE_ds64 = 0x01,
|
||||
HAVE_fmt = 0x02,
|
||||
HAVE_bext = 0x04,
|
||||
HAVE_data = 0x08,
|
||||
HAVE_cart = 0x10
|
||||
} ;
|
||||
|
||||
#define HAVE_CHUNK(CHUNK) ((parsestage & CHUNK) != 0)
|
||||
|
||||
static int
|
||||
rf64_read_header (SF_PRIVATE *psf)
|
||||
{ WAV_PRIVATE *wpriv ;
|
||||
sf_count_t riff_size, data_size ;
|
||||
unsigned int size32 ;
|
||||
int marker, marks [2], error, done = 0 ;
|
||||
rf64_read_header (SF_PRIVATE *psf, int *blockalign, int *framesperblock)
|
||||
{ WAV_PRIVATE *wpriv ;
|
||||
WAV_FMT *wav_fmt ;
|
||||
sf_count_t riff_size = 0, frame_count = 0, ds64_datalength = 0 ;
|
||||
uint32_t marks [2], size32, parsestage = 0 ;
|
||||
int marker, error, done = 0, format = 0 ;
|
||||
|
||||
if ((wpriv = psf->container_data) == NULL)
|
||||
return SFE_INTERNAL ;
|
||||
wav_fmt = &wpriv->wav_fmt ;
|
||||
|
||||
/* Set position to start of file to begin reading header. */
|
||||
psf_binheader_readf (psf, "pmmm", 0, &marker, marks, marks + 1) ;
|
||||
if (marker != RF64_MARKER || marks [0] != FFFF_MARKER || marks [1] != WAVE_MARKER)
|
||||
if (marker != RF64_MARKER || marks [1] != WAVE_MARKER)
|
||||
return SFE_RF64_NOT_RF64 ;
|
||||
|
||||
psf_log_printf (psf, "%M\n %M\n", RF64_MARKER, WAVE_MARKER) ;
|
||||
if (marks [0] == FFFF_MARKER)
|
||||
psf_log_printf (psf, "%M\n %M\n", RF64_MARKER, WAVE_MARKER) ;
|
||||
else
|
||||
psf_log_printf (psf, "%M : 0x%x (should be 0xFFFFFFFF)\n %M\n", RF64_MARKER, WAVE_MARKER) ;
|
||||
|
||||
while (! done)
|
||||
while (NOT (done))
|
||||
{ psf_binheader_readf (psf, "em4", &marker, &size32) ;
|
||||
|
||||
switch (marker)
|
||||
{ case ds64_MARKER :
|
||||
{ unsigned int table_len, bytesread ;
|
||||
|
||||
/* Read ds64 sizes (3 8-byte words). */
|
||||
bytesread = psf_binheader_readf (psf, "888", &riff_size, &ds64_datalength, &frame_count) ;
|
||||
|
||||
/* Read table length. */
|
||||
bytesread += psf_binheader_readf (psf, "4", &table_len) ;
|
||||
/* Skip table for now. (this was "table_len + 4", why?) */
|
||||
bytesread += psf_binheader_readf (psf, "j", table_len) ;
|
||||
|
||||
if (size32 == bytesread)
|
||||
psf_log_printf (psf, "%M : %u\n", marker, size32) ;
|
||||
else if (size32 >= bytesread + 4)
|
||||
{ unsigned int next ;
|
||||
psf_binheader_readf (psf, "m", &next) ;
|
||||
if (next == fmt_MARKER)
|
||||
{ psf_log_printf (psf, "%M : %u (should be %u)\n", marker, size32, bytesread) ;
|
||||
psf_binheader_readf (psf, "j", -4) ;
|
||||
}
|
||||
else
|
||||
{ psf_log_printf (psf, "%M : %u\n", marker, size32) ;
|
||||
psf_binheader_readf (psf, "j", size32 - bytesread - 4) ;
|
||||
} ;
|
||||
} ;
|
||||
|
||||
if (psf->filelength != riff_size + 8)
|
||||
psf_log_printf (psf, " Riff size : %D (should be %D)\n", riff_size, psf->filelength - 8) ;
|
||||
else
|
||||
psf_log_printf (psf, " Riff size : %D\n", riff_size) ;
|
||||
|
||||
psf_log_printf (psf, " Data size : %D\n", ds64_datalength) ;
|
||||
|
||||
psf_log_printf (psf, " Frames : %D\n", frame_count) ;
|
||||
psf_log_printf (psf, " Table length : %u\n", table_len) ;
|
||||
|
||||
} ;
|
||||
parsestage |= HAVE_ds64 ;
|
||||
break ;
|
||||
|
||||
case fmt_MARKER:
|
||||
psf_log_printf (psf, "%M : %u\n", marker, size32) ;
|
||||
|
||||
psf_binheader_readf (psf, "888", &riff_size, &data_size, &psf->sf.frames) ;
|
||||
psf_log_printf (psf, " Riff size : %D\n Data size : %D\n Frames : %D\n",
|
||||
riff_size, data_size, psf->sf.frames) ;
|
||||
|
||||
psf_binheader_readf (psf, "4", &size32) ;
|
||||
psf_log_printf (psf, " Table len : %u\n", size32) ;
|
||||
|
||||
psf_binheader_readf (psf, "jm4", size32 + 4, &marker, &size32) ;
|
||||
psf_log_printf (psf, "%M : %u\n", marker, size32) ;
|
||||
|
||||
if ((error = wav_w64_read_fmt_chunk (psf, size32)) != 0)
|
||||
return error ;
|
||||
psf->sf.format = SF_FORMAT_RF64 | (psf->sf.format & SF_FORMAT_SUBMASK) ;
|
||||
format = wav_fmt->format ;
|
||||
parsestage |= HAVE_fmt ;
|
||||
break ;
|
||||
|
||||
case bext_MARKER :
|
||||
if ((error = wav_read_bext_chunk (psf, size32)) != 0)
|
||||
return error ;
|
||||
parsestage |= HAVE_bext ;
|
||||
break ;
|
||||
|
||||
case cart_MARKER :
|
||||
if ((error = wav_read_cart_chunk (psf, size32)) != 0)
|
||||
return error ;
|
||||
parsestage |= HAVE_cart ;
|
||||
break ;
|
||||
|
||||
case data_MARKER :
|
||||
psf_log_printf (psf, "%M : %x\n", marker, size32) ;
|
||||
psf->dataoffset = psf->headindex ;
|
||||
done = SF_TRUE ;
|
||||
break ;
|
||||
/* see wav for more sophisticated parsing -> implement state machine with parsestage */
|
||||
|
||||
if (HAVE_CHUNK (HAVE_ds64))
|
||||
{ if (size32 == 0xffffffff)
|
||||
psf_log_printf (psf, "%M : 0x%x\n", marker, size32) ;
|
||||
else
|
||||
psf_log_printf (psf, "%M : 0x%x (should be 0xffffffff\n", marker, size32) ;
|
||||
psf->datalength = ds64_datalength ;
|
||||
}
|
||||
else
|
||||
{ if (size32 == 0xffffffff)
|
||||
{ psf_log_printf (psf, "%M : 0x%x\n", marker, size32) ;
|
||||
psf_log_printf (psf, " *** Data length not specified no 'ds64' chunk.\n") ;
|
||||
}
|
||||
else
|
||||
{ psf_log_printf (psf, "%M : 0x%x\n**** Weird, RF64 file without a 'ds64' chunk and no valid 'data' size.\n", marker, size32) ;
|
||||
psf->datalength = size32 ;
|
||||
} ;
|
||||
} ;
|
||||
|
||||
psf->dataoffset = psf_ftell (psf) ;
|
||||
|
||||
if (psf->dataoffset > 0)
|
||||
{ if (size32 == 0 && riff_size == 8 && psf->filelength > 44)
|
||||
{ psf_log_printf (psf, " *** Looks like a WAV file which wasn't closed properly. Fixing it.\n") ;
|
||||
psf->datalength = psf->filelength - psf->dataoffset ;
|
||||
} ;
|
||||
|
||||
/* Only set dataend if there really is data at the end. */
|
||||
if (psf->datalength + psf->dataoffset < psf->filelength)
|
||||
psf->dataend = psf->datalength + psf->dataoffset ;
|
||||
|
||||
if (NOT (psf->sf.seekable) || psf->dataoffset < 0)
|
||||
break ;
|
||||
|
||||
/* Seek past data and continue reading header. */
|
||||
psf_fseek (psf, psf->datalength, SEEK_CUR) ;
|
||||
|
||||
if (psf_ftell (psf) != psf->datalength + psf->dataoffset)
|
||||
psf_log_printf (psf, " *** psf_fseek past end error ***\n") ;
|
||||
break ;
|
||||
} ;
|
||||
break ;
|
||||
|
||||
default :
|
||||
if (isprint ((marker >> 24) & 0xFF) && isprint ((marker >> 16) & 0xFF)
|
||||
&& isprint ((marker >> 8) & 0xFF) && isprint (marker & 0xFF))
|
||||
{ psf_binheader_readf (psf, "4", &size32) ;
|
||||
psf_log_printf (psf, "*** %M : %d (unknown marker)\n", marker, size32) ;
|
||||
{ psf_log_printf (psf, "*** %M : %d (unknown marker)\n", marker, size32) ;
|
||||
if (size32 < 8)
|
||||
done = SF_TRUE ;
|
||||
psf_binheader_readf (psf, "j", size32) ;
|
||||
break ;
|
||||
} ;
|
||||
if (psf_ftell (psf) & 0x03)
|
||||
{ psf_log_printf (psf, " Unknown chunk marker at position %d. Resynching.\n", size32 - 4) ;
|
||||
{ psf_log_printf (psf, " Unknown chunk marker at position 0x%x. Resynching.\n", size32 - 4) ;
|
||||
psf_binheader_readf (psf, "j", -3) ;
|
||||
break ;
|
||||
} ;
|
||||
psf_log_printf (psf, "*** Unknown chunk marker (%X) at position %D. Exiting parser.\n", marker, psf_ftell (psf) - 4) ;
|
||||
psf_log_printf (psf, "*** Unknown chunk marker (0x%X) at position 0x%X. Exiting parser.\n", marker, psf_ftell (psf) - 4) ;
|
||||
done = SF_TRUE ;
|
||||
break ;
|
||||
} ; /* switch (marker) */
|
||||
@@ -204,6 +311,99 @@ rf64_read_header (SF_PRIVATE *psf)
|
||||
} ;
|
||||
} ;
|
||||
|
||||
if (psf->dataoffset <= 0)
|
||||
return SFE_WAV_NO_DATA ;
|
||||
|
||||
/* WAVs can be little or big endian */
|
||||
psf->endian = psf->rwf_endian ;
|
||||
|
||||
psf_fseek (psf, psf->dataoffset, SEEK_SET) ;
|
||||
|
||||
if (psf->is_pipe == 0)
|
||||
{ /*
|
||||
** Check for 'wvpk' at the start of the DATA section. Not able to
|
||||
** handle this.
|
||||
*/
|
||||
psf_binheader_readf (psf, "4", &marker) ;
|
||||
if (marker == wvpk_MARKER || marker == OggS_MARKER)
|
||||
return SFE_WAV_WVPK_DATA ;
|
||||
} ;
|
||||
|
||||
/* Seek to start of DATA section. */
|
||||
psf_fseek (psf, psf->dataoffset, SEEK_SET) ;
|
||||
|
||||
if (psf->blockwidth)
|
||||
{ if (psf->filelength - psf->dataoffset < psf->datalength)
|
||||
psf->sf.frames = (psf->filelength - psf->dataoffset) / psf->blockwidth ;
|
||||
else
|
||||
psf->sf.frames = psf->datalength / psf->blockwidth ;
|
||||
} ;
|
||||
|
||||
if (frame_count != psf->sf.frames)
|
||||
psf_log_printf (psf, "*** Calculated frame count %d does not match value from 'ds64' chunk of %d.\n", psf->sf.frames, frame_count) ;
|
||||
|
||||
switch (format)
|
||||
{
|
||||
case WAVE_FORMAT_EXTENSIBLE :
|
||||
|
||||
/* with WAVE_FORMAT_EXTENSIBLE the psf->sf.format field is already set. We just have to set the major to rf64 */
|
||||
psf->sf.format = (psf->sf.format & ~SF_FORMAT_TYPEMASK) | SF_FORMAT_RF64 ;
|
||||
|
||||
if (psf->sf.format == (SF_FORMAT_WAVEX | SF_FORMAT_MS_ADPCM))
|
||||
{ *blockalign = wav_fmt->msadpcm.blockalign ;
|
||||
*framesperblock = wav_fmt->msadpcm.samplesperblock ;
|
||||
} ;
|
||||
break ;
|
||||
|
||||
case WAVE_FORMAT_PCM :
|
||||
psf->sf.format = SF_FORMAT_RF64 | u_bitwidth_to_subformat (psf->bytewidth * 8) ;
|
||||
break ;
|
||||
|
||||
case WAVE_FORMAT_MULAW :
|
||||
case IBM_FORMAT_MULAW :
|
||||
psf->sf.format = (SF_FORMAT_RF64 | SF_FORMAT_ULAW) ;
|
||||
break ;
|
||||
|
||||
case WAVE_FORMAT_ALAW :
|
||||
case IBM_FORMAT_ALAW :
|
||||
psf->sf.format = (SF_FORMAT_RF64 | SF_FORMAT_ALAW) ;
|
||||
break ;
|
||||
|
||||
case WAVE_FORMAT_MS_ADPCM :
|
||||
psf->sf.format = (SF_FORMAT_RF64 | SF_FORMAT_MS_ADPCM) ;
|
||||
*blockalign = wav_fmt->msadpcm.blockalign ;
|
||||
*framesperblock = wav_fmt->msadpcm.samplesperblock ;
|
||||
break ;
|
||||
|
||||
case WAVE_FORMAT_IMA_ADPCM :
|
||||
psf->sf.format = (SF_FORMAT_RF64 | SF_FORMAT_IMA_ADPCM) ;
|
||||
*blockalign = wav_fmt->ima.blockalign ;
|
||||
*framesperblock = wav_fmt->ima.samplesperblock ;
|
||||
break ;
|
||||
|
||||
case WAVE_FORMAT_GSM610 :
|
||||
psf->sf.format = (SF_FORMAT_RF64 | SF_FORMAT_GSM610) ;
|
||||
break ;
|
||||
|
||||
case WAVE_FORMAT_IEEE_FLOAT :
|
||||
psf->sf.format = SF_FORMAT_RF64 ;
|
||||
psf->sf.format |= (psf->bytewidth == 8) ? SF_FORMAT_DOUBLE : SF_FORMAT_FLOAT ;
|
||||
break ;
|
||||
|
||||
case WAVE_FORMAT_G721_ADPCM :
|
||||
psf->sf.format = SF_FORMAT_RF64 | SF_FORMAT_G721_32 ;
|
||||
break ;
|
||||
|
||||
default : return SFE_UNIMPLEMENTED ;
|
||||
} ;
|
||||
|
||||
if (wpriv->fmt_is_broken)
|
||||
wav_w64_analyze (psf) ;
|
||||
|
||||
/* Only set the format endian-ness if its non-standard big-endian. */
|
||||
if (psf->endian == SF_ENDIAN_BIG)
|
||||
psf->sf.format |= SF_ENDIAN_BIG ;
|
||||
|
||||
return 0 ;
|
||||
} /* rf64_read_header */
|
||||
|
||||
@@ -242,9 +442,9 @@ static const EXT_SUBFORMAT MSGUID_SUBTYPE_AMBISONIC_B_FORMAT_IEEE_FLOAT =
|
||||
|
||||
|
||||
static int
|
||||
wavex_write_fmt_chunk (SF_PRIVATE *psf)
|
||||
rf64_write_fmt_chunk (SF_PRIVATE *psf)
|
||||
{ WAV_PRIVATE *wpriv ;
|
||||
int subformat, fmt_size, add_fact_chunk = 0 ;
|
||||
int subformat, fmt_size ;
|
||||
|
||||
if ((wpriv = psf->container_data) == NULL)
|
||||
return SFE_INTERNAL ;
|
||||
@@ -281,6 +481,8 @@ wavex_write_fmt_chunk (SF_PRIVATE *psf)
|
||||
*/
|
||||
if (wpriv->wavex_ambisonic != SF_AMBISONIC_NONE)
|
||||
psf_binheader_writef (psf, "4", 0) ;
|
||||
else if (wpriv->wavex_channelmask != 0)
|
||||
psf_binheader_writef (psf, "4", wpriv->wavex_channelmask) ;
|
||||
else
|
||||
{ /*
|
||||
** Ok some liberty is taken here to use the most commonly used channel masks
|
||||
@@ -345,22 +547,11 @@ wavex_write_fmt_chunk (SF_PRIVATE *psf)
|
||||
wavex_write_guid (psf, &MSGUID_SUBTYPE_ALAW) ;
|
||||
break ;
|
||||
|
||||
#if 0
|
||||
/* This is dead code due to return in previous switch statement. */
|
||||
case SF_FORMAT_MS_ADPCM : /* todo, GUID exists */
|
||||
wavex_write_guid (psf, &MSGUID_SUBTYPE_MS_ADPCM) ;
|
||||
break ;
|
||||
return SFE_UNIMPLEMENTED ;
|
||||
#endif
|
||||
|
||||
default : return SFE_UNIMPLEMENTED ;
|
||||
} ;
|
||||
|
||||
if (add_fact_chunk)
|
||||
psf_binheader_writef (psf, "tm48", fact_MARKER, 4, psf->sf.frames) ;
|
||||
|
||||
return 0 ;
|
||||
} /* wavex_write_fmt_chunk */
|
||||
} /* rf64_write_fmt_chunk */
|
||||
|
||||
|
||||
static int
|
||||
@@ -375,7 +566,6 @@ rf64_write_header (SF_PRIVATE *psf, int calc_length)
|
||||
|
||||
if (calc_length)
|
||||
{ psf->filelength = psf_get_filelen (psf) ;
|
||||
|
||||
psf->datalength = psf->filelength - psf->dataoffset ;
|
||||
|
||||
if (psf->dataend)
|
||||
@@ -392,7 +582,8 @@ rf64_write_header (SF_PRIVATE *psf, int calc_length)
|
||||
|
||||
psf_binheader_writef (psf, "em4m", RF64_MARKER, 0xffffffff, WAVE_MARKER) ;
|
||||
|
||||
psf_binheader_writef (psf, "m488844", ds64_MARKER, 32, psf->filelength, psf->datalength, psf->sf.frames, 0, 0x005c0064) ;
|
||||
/* Currently no table. */
|
||||
psf_binheader_writef (psf, "m48884", ds64_MARKER, 28, psf->filelength - 8, psf->datalength, psf->sf.frames, 0) ;
|
||||
|
||||
/* WAVE and 'fmt ' markers. */
|
||||
psf_binheader_writef (psf, "m", fmt_MARKER) ;
|
||||
@@ -406,7 +597,7 @@ rf64_write_header (SF_PRIVATE *psf, int calc_length)
|
||||
|
||||
case SF_FORMAT_WAVEX :
|
||||
case SF_FORMAT_RF64 :
|
||||
if ((error = wavex_write_fmt_chunk (psf)) != 0)
|
||||
if ((error = rf64_write_fmt_chunk (psf)) != 0)
|
||||
return error ;
|
||||
break ;
|
||||
|
||||
@@ -414,9 +605,14 @@ rf64_write_header (SF_PRIVATE *psf, int calc_length)
|
||||
return SFE_UNIMPLEMENTED ;
|
||||
} ;
|
||||
|
||||
if (psf->broadcast_16k != NULL)
|
||||
wav_write_bext_chunk (psf) ;
|
||||
|
||||
if (psf->cart_16k != NULL)
|
||||
wav_write_cart_chunk (psf) ;
|
||||
#if 0
|
||||
/* The LIST/INFO chunk. */
|
||||
if (psf->str_flags & SF_STR_LOCATE_START)
|
||||
if (psf->strings.flags & SF_STR_LOCATE_START)
|
||||
wav_write_strings (psf, SF_STR_LOCATE_START) ;
|
||||
|
||||
if (psf->peak_info != NULL && psf->peak_info->peak_loc == SF_PEAK_START)
|
||||
@@ -426,8 +622,8 @@ rf64_write_header (SF_PRIVATE *psf, int calc_length)
|
||||
psf_binheader_writef (psf, "ft8", (float) psf->peak_info->peaks [k].value, psf->peak_info->peaks [k].position) ;
|
||||
} ;
|
||||
|
||||
if (psf->broadcast_info != NULL)
|
||||
wav_write_bext_chunk (psf) ;
|
||||
// if (psf->broadcast_info != NULL)
|
||||
// wav_write_bext_chunk (psf) ;
|
||||
|
||||
if (psf->instrument != NULL)
|
||||
{ int tmp ;
|
||||
@@ -446,7 +642,7 @@ rf64_write_header (SF_PRIVATE *psf, int calc_length)
|
||||
{ int type ;
|
||||
|
||||
type = psf->instrument->loops [tmp].mode ;
|
||||
type = (type == SF_LOOP_FORWARD ? 0 : type==SF_LOOP_BACKWARD ? 2 : type == SF_LOOP_ALTERNATING ? 1 : 32) ;
|
||||
type = (type == SF_LOOP_FORWARD ? 0 : type == SF_LOOP_BACKWARD ? 2 : type == SF_LOOP_ALTERNATING ? 1 : 32) ;
|
||||
|
||||
psf_binheader_writef (psf, "44", tmp, type) ;
|
||||
psf_binheader_writef (psf, "44", psf->instrument->loops [tmp].start, psf->instrument->loops [tmp].end) ;
|
||||
@@ -475,7 +671,7 @@ rf64_write_header (SF_PRIVATE *psf, int calc_length)
|
||||
|
||||
psf->dataoffset = psf->headindex ;
|
||||
|
||||
if (! has_data)
|
||||
if (NOT (has_data))
|
||||
psf_fseek (psf, psf->dataoffset, SEEK_SET) ;
|
||||
else if (current > 0)
|
||||
psf_fseek (psf, current, SEEK_SET) ;
|
||||
@@ -486,7 +682,7 @@ rf64_write_header (SF_PRIVATE *psf, int calc_length)
|
||||
static int
|
||||
rf64_close (SF_PRIVATE *psf)
|
||||
{
|
||||
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
|
||||
if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
|
||||
{ // rf64_write_tailer (psf) ;
|
||||
|
||||
psf->write_header (psf, SF_TRUE) ;
|
||||
@@ -494,3 +690,37 @@ rf64_close (SF_PRIVATE *psf)
|
||||
|
||||
return 0 ;
|
||||
} /* rf64_close */
|
||||
|
||||
static int
|
||||
rf64_command (SF_PRIVATE *psf, int command, void * UNUSED (data), int datasize)
|
||||
{ WAV_PRIVATE *wpriv ;
|
||||
|
||||
if ((wpriv = psf->container_data) == NULL)
|
||||
return SFE_INTERNAL ;
|
||||
|
||||
switch (command)
|
||||
{ case SFC_WAVEX_SET_AMBISONIC :
|
||||
if ((SF_CONTAINER (psf->sf.format)) == SF_FORMAT_WAVEX)
|
||||
{ if (datasize == SF_AMBISONIC_NONE)
|
||||
wpriv->wavex_ambisonic = SF_AMBISONIC_NONE ;
|
||||
else if (datasize == SF_AMBISONIC_B_FORMAT)
|
||||
wpriv->wavex_ambisonic = SF_AMBISONIC_B_FORMAT ;
|
||||
else
|
||||
return 0 ;
|
||||
} ;
|
||||
return wpriv->wavex_ambisonic ;
|
||||
|
||||
case SFC_WAVEX_GET_AMBISONIC :
|
||||
return wpriv->wavex_ambisonic ;
|
||||
|
||||
case SFC_SET_CHANNEL_MAP_INFO :
|
||||
wpriv->wavex_channelmask = wavex_gen_channel_mask (psf->channel_map, psf->sf.channels) ;
|
||||
return (wpriv->wavex_channelmask != 0) ;
|
||||
|
||||
default :
|
||||
break ;
|
||||
} ;
|
||||
|
||||
return 0 ;
|
||||
} /* rf64_command */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** Copyright (C) 2001-2009 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
** Copyright (C) 2001-2012 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
@@ -80,10 +80,9 @@ rx2_open (SF_PRIVATE *psf)
|
||||
"Additional/PencilTool", "Disabled"
|
||||
} ;
|
||||
|
||||
BUF_UNION ubuf ;
|
||||
int error, marker, length, glob_offset, slce_count, frames ;
|
||||
|
||||
int sdat_length = 0, slce_total = 0 ;
|
||||
|
||||
int n_channels ;
|
||||
|
||||
|
||||
@@ -119,14 +118,14 @@ rx2_open (SF_PRIVATE *psf)
|
||||
/* Get name length */
|
||||
length = 0 ;
|
||||
psf_binheader_readf (psf, "1", &length) ;
|
||||
if (length >= SIGNED_SIZEOF (psf->u.cbuf))
|
||||
if (length >= SIGNED_SIZEOF (ubuf.cbuf))
|
||||
{ psf_log_printf (psf, " Text : %d *** Error : Too sf_count_t!\n") ;
|
||||
return -1001 ;
|
||||
}
|
||||
|
||||
memset (psf->u.cbuf, 0, sizeof (psf->u.cbuf)) ;
|
||||
psf_binheader_readf (psf, "b", psf->u.cbuf, length) ;
|
||||
psf_log_printf (psf, " Text : \"%s\"\n", psf->u.cbuf) ;
|
||||
memset (ubuf.cbuf, 0, sizeof (ubuf.cbuf)) ;
|
||||
psf_binheader_readf (psf, "b", ubuf.cbuf, length) ;
|
||||
psf_log_printf (psf, " Text : \"%s\"\n", ubuf.cbuf) ;
|
||||
|
||||
/* Jump to GLOB offset position. */
|
||||
if (glob_offset & 1)
|
||||
@@ -253,7 +252,7 @@ rx2_open (SF_PRIVATE *psf)
|
||||
break ;
|
||||
} ;
|
||||
|
||||
puts (psf->logbuffer) ;
|
||||
puts (psf->parselog.buf) ;
|
||||
puts ("-----------------------------------") ;
|
||||
|
||||
printf ("SDAT length : %d\n", sdat_length) ;
|
||||
@@ -270,7 +269,7 @@ rx2_open (SF_PRIVATE *psf)
|
||||
|
||||
puts (" ") ;
|
||||
|
||||
psf->logbuffer [0] = 0 ;
|
||||
psf->parselog.buf [0] = 0 ;
|
||||
|
||||
/* OK, have the header although not too sure what it all means. */
|
||||
|
||||
@@ -306,7 +305,7 @@ rx2_open (SF_PRIVATE *psf)
|
||||
static int
|
||||
rx2_close (SF_PRIVATE *psf)
|
||||
{
|
||||
if (psf->mode == SFM_WRITE)
|
||||
if (psf->file.mode == SFM_WRITE)
|
||||
{ /* Now we know for certain the length of the file we can re-write
|
||||
** correct values for the FORM, 8SVX and BODY chunks.
|
||||
*/
|
||||
|
||||
+70
-47
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** Copyright (C) 2001-2009 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
** Copyright (C) 2001-2013 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
** Copyright (C) 2004 Paavo Jumppanen
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
@@ -104,12 +104,12 @@ sd2_open (SF_PRIVATE *psf)
|
||||
/* SD2 is always big endian. */
|
||||
psf->endian = SF_ENDIAN_BIG ;
|
||||
|
||||
if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->rsrclength > 0))
|
||||
if (psf->file.mode == SFM_READ || (psf->file.mode == SFM_RDWR && psf->rsrclength > 0))
|
||||
{ psf_use_rsrc (psf, SF_TRUE) ;
|
||||
valid = psf_file_valid (psf) ;
|
||||
psf_use_rsrc (psf, SF_FALSE) ;
|
||||
if (! valid)
|
||||
{ psf_log_printf (psf, "sd2_open : psf->rsrcdes < 0\n") ;
|
||||
{ psf_log_printf (psf, "sd2_open : psf->rsrc.filedes < 0\n") ;
|
||||
return SFE_SD2_BAD_RSRC ;
|
||||
} ;
|
||||
|
||||
@@ -128,8 +128,9 @@ sd2_open (SF_PRIVATE *psf)
|
||||
psf->dataoffset = 0 ;
|
||||
|
||||
/* Only open and write the resource in RDWR mode is its current length is zero. */
|
||||
if (psf->mode == SFM_WRITE || (psf->mode == SFM_RDWR && psf->rsrclength == 0))
|
||||
{ psf_open_rsrc (psf, psf->mode) ;
|
||||
if (psf->file.mode == SFM_WRITE || (psf->file.mode == SFM_RDWR && psf->rsrclength == 0))
|
||||
{ psf->rsrc.mode = psf->file.mode ;
|
||||
psf_open_rsrc (psf) ;
|
||||
|
||||
error = sd2_write_rsrc_fork (psf, SF_FALSE) ;
|
||||
|
||||
@@ -148,6 +149,7 @@ sd2_open (SF_PRIVATE *psf)
|
||||
{ case SF_FORMAT_PCM_S8 : /* 8-bit linear PCM. */
|
||||
case SF_FORMAT_PCM_16 : /* 16-bit linear PCM. */
|
||||
case SF_FORMAT_PCM_24 : /* 24-bit linear PCM */
|
||||
case SF_FORMAT_PCM_32 : /* 32-bit linear PCM */
|
||||
error = pcm_init (psf) ;
|
||||
break ;
|
||||
|
||||
@@ -172,7 +174,7 @@ error_cleanup:
|
||||
static int
|
||||
sd2_close (SF_PRIVATE *psf)
|
||||
{
|
||||
if (psf->mode == SFM_WRITE)
|
||||
if (psf->file.mode == SFM_WRITE)
|
||||
{ /* Now we know for certain the audio_length of the file we can re-write
|
||||
** correct values for the FORM, 8SVX and BODY chunks.
|
||||
*/
|
||||
@@ -222,7 +224,7 @@ write_marker (unsigned char * data, int offset, int value)
|
||||
} /* write_marker */
|
||||
|
||||
static void
|
||||
write_str (unsigned char * data, int offset, char * buffer, int buffer_len)
|
||||
write_str (unsigned char * data, int offset, const char * buffer, int buffer_len)
|
||||
{ memcpy (data + offset, buffer, buffer_len) ;
|
||||
} /* write_str */
|
||||
|
||||
@@ -281,8 +283,8 @@ sd2_write_rsrc_fork (SF_PRIVATE *psf, int UNUSED (calc_length))
|
||||
write_int (rsrc.rsrc_data, 4, rsrc.map_offset) ;
|
||||
write_int (rsrc.rsrc_data, 8, rsrc.data_length) ;
|
||||
|
||||
write_char (rsrc.rsrc_data, 0x30, strlen (psf->filename)) ;
|
||||
write_str (rsrc.rsrc_data, 0x31, psf->filename, strlen (psf->filename)) ;
|
||||
write_char (rsrc.rsrc_data, 0x30, strlen (psf->file.name.c)) ;
|
||||
write_str (rsrc.rsrc_data, 0x31, psf->file.name.c, strlen (psf->file.name.c)) ;
|
||||
|
||||
write_short (rsrc.rsrc_data, 0x50, 0) ;
|
||||
write_marker (rsrc.rsrc_data, 0x52, Sd2f_MARKER) ;
|
||||
@@ -369,44 +371,61 @@ sd2_write_rsrc_fork (SF_PRIVATE *psf, int UNUSED (calc_length))
|
||||
*/
|
||||
|
||||
static inline int
|
||||
read_char (const unsigned char * data, int offset)
|
||||
{ return data [offset] ;
|
||||
} /* read_char */
|
||||
read_rsrc_char (const SD2_RSRC *prsrc, int offset)
|
||||
{ const unsigned char * data = prsrc->rsrc_data ;
|
||||
if (offset < 0 || offset >= prsrc->rsrc_len)
|
||||
return 0 ;
|
||||
return data [offset] ;
|
||||
} /* read_rsrc_char */
|
||||
|
||||
static inline int
|
||||
read_short (const unsigned char * data, int offset)
|
||||
{ return (data [offset] << 8) + data [offset + 1] ;
|
||||
} /* read_short */
|
||||
read_rsrc_short (const SD2_RSRC *prsrc, int offset)
|
||||
{ const unsigned char * data = prsrc->rsrc_data ;
|
||||
if (offset < 0 || offset + 1 >= prsrc->rsrc_len)
|
||||
return 0 ;
|
||||
return (data [offset] << 8) + data [offset + 1] ;
|
||||
} /* read_rsrc_short */
|
||||
|
||||
static inline int
|
||||
read_int (const unsigned char * data, int offset)
|
||||
{ return (data [offset] << 24) + (data [offset + 1] << 16) + (data [offset + 2] << 8) + data [offset + 3] ;
|
||||
} /* read_int */
|
||||
read_rsrc_int (const SD2_RSRC *prsrc, int offset)
|
||||
{ const unsigned char * data = prsrc->rsrc_data ;
|
||||
if (offset < 0 || offset + 3 >= prsrc->rsrc_len)
|
||||
return 0 ;
|
||||
return (data [offset] << 24) + (data [offset + 1] << 16) + (data [offset + 2] << 8) + data [offset + 3] ;
|
||||
} /* read_rsrc_int */
|
||||
|
||||
static inline int
|
||||
read_marker (const unsigned char * data, int offset)
|
||||
{
|
||||
read_rsrc_marker (const SD2_RSRC *prsrc, int offset)
|
||||
{ const unsigned char * data = prsrc->rsrc_data ;
|
||||
|
||||
if (offset < 0 || offset + 3 >= prsrc->rsrc_len)
|
||||
return 0 ;
|
||||
|
||||
if (CPU_IS_BIG_ENDIAN)
|
||||
return (data [offset] << 24) + (data [offset + 1] << 16) + (data [offset + 2] << 8) + data [offset + 3] ;
|
||||
else if (CPU_IS_LITTLE_ENDIAN)
|
||||
if (CPU_IS_LITTLE_ENDIAN)
|
||||
return data [offset] + (data [offset + 1] << 8) + (data [offset + 2] << 16) + (data [offset + 3] << 24) ;
|
||||
else
|
||||
return 0x666 ;
|
||||
} /* read_marker */
|
||||
|
||||
return 0 ;
|
||||
} /* read_rsrc_marker */
|
||||
|
||||
static void
|
||||
read_str (const unsigned char * data, int offset, char * buffer, int buffer_len)
|
||||
{ int k ;
|
||||
read_rsrc_str (const SD2_RSRC *prsrc, int offset, char * buffer, int buffer_len)
|
||||
{ const unsigned char * data = prsrc->rsrc_data ;
|
||||
int k ;
|
||||
|
||||
memset (buffer, 0, buffer_len) ;
|
||||
|
||||
if (offset < 0 || offset + buffer_len >= prsrc->rsrc_len)
|
||||
return ;
|
||||
|
||||
for (k = 0 ; k < buffer_len - 1 ; k++)
|
||||
{ if (isprint (data [offset + k]) == 0)
|
||||
{ if (psf_isprint (data [offset + k]) == 0)
|
||||
return ;
|
||||
buffer [k] = data [offset + k] ;
|
||||
} ;
|
||||
return ;
|
||||
} /* read_str */
|
||||
} /* read_rsrc_str */
|
||||
|
||||
static int
|
||||
sd2_parse_rsrc_fork (SF_PRIVATE *psf)
|
||||
@@ -433,17 +452,17 @@ sd2_parse_rsrc_fork (SF_PRIVATE *psf)
|
||||
/* Reset the header storage because we have changed to the rsrcdes. */
|
||||
psf->headindex = psf->headend = rsrc.rsrc_len ;
|
||||
|
||||
rsrc.data_offset = read_int (rsrc.rsrc_data, 0) ;
|
||||
rsrc.map_offset = read_int (rsrc.rsrc_data, 4) ;
|
||||
rsrc.data_length = read_int (rsrc.rsrc_data, 8) ;
|
||||
rsrc.map_length = read_int (rsrc.rsrc_data, 12) ;
|
||||
rsrc.data_offset = read_rsrc_int (&rsrc, 0) ;
|
||||
rsrc.map_offset = read_rsrc_int (&rsrc, 4) ;
|
||||
rsrc.data_length = read_rsrc_int (&rsrc, 8) ;
|
||||
rsrc.map_length = read_rsrc_int (&rsrc, 12) ;
|
||||
|
||||
if (rsrc.data_offset == 0x51607 && rsrc.map_offset == 0x20000)
|
||||
{ psf_log_printf (psf, "Trying offset of 0x52 bytes.\n") ;
|
||||
rsrc.data_offset = read_int (rsrc.rsrc_data, 0x52 + 0) + 0x52 ;
|
||||
rsrc.map_offset = read_int (rsrc.rsrc_data, 0x52 + 4) + 0x52 ;
|
||||
rsrc.data_length = read_int (rsrc.rsrc_data, 0x52 + 8) ;
|
||||
rsrc.map_length = read_int (rsrc.rsrc_data, 0x52 + 12) ;
|
||||
rsrc.data_offset = read_rsrc_int (&rsrc, 0x52 + 0) + 0x52 ;
|
||||
rsrc.map_offset = read_rsrc_int (&rsrc, 0x52 + 4) + 0x52 ;
|
||||
rsrc.data_length = read_rsrc_int (&rsrc, 0x52 + 8) ;
|
||||
rsrc.map_length = read_rsrc_int (&rsrc, 0x52 + 12) ;
|
||||
} ;
|
||||
|
||||
psf_log_printf (psf, " data offset : 0x%04X\n map offset : 0x%04X\n"
|
||||
@@ -486,7 +505,7 @@ sd2_parse_rsrc_fork (SF_PRIVATE *psf)
|
||||
goto parse_rsrc_fork_cleanup ;
|
||||
} ;
|
||||
|
||||
rsrc.string_offset = rsrc.map_offset + read_short (rsrc.rsrc_data, rsrc.map_offset + 26) ;
|
||||
rsrc.string_offset = rsrc.map_offset + read_rsrc_short (&rsrc, rsrc.map_offset + 26) ;
|
||||
if (rsrc.string_offset > rsrc.rsrc_len)
|
||||
{ psf_log_printf (psf, "Bad string offset (%d).\n", rsrc.string_offset) ;
|
||||
error = SFE_SD2_BAD_RSRC ;
|
||||
@@ -495,7 +514,7 @@ sd2_parse_rsrc_fork (SF_PRIVATE *psf)
|
||||
|
||||
rsrc.type_offset = rsrc.map_offset + 30 ;
|
||||
|
||||
rsrc.type_count = read_short (rsrc.rsrc_data, rsrc.map_offset + 28) + 1 ;
|
||||
rsrc.type_count = read_rsrc_short (&rsrc, rsrc.map_offset + 28) + 1 ;
|
||||
if (rsrc.type_count < 1)
|
||||
{ psf_log_printf (psf, "Bad type count.\n") ;
|
||||
error = SFE_SD2_BAD_RSRC ;
|
||||
@@ -511,11 +530,11 @@ sd2_parse_rsrc_fork (SF_PRIVATE *psf)
|
||||
|
||||
rsrc.str_index = -1 ;
|
||||
for (k = 0 ; k < rsrc.type_count ; k ++)
|
||||
{ marker = read_marker (rsrc.rsrc_data, rsrc.type_offset + k * 8) ;
|
||||
{ marker = read_rsrc_marker (&rsrc, rsrc.type_offset + k * 8) ;
|
||||
|
||||
if (marker == STR_MARKER)
|
||||
{ rsrc.str_index = k ;
|
||||
rsrc.str_count = read_short (rsrc.rsrc_data, rsrc.type_offset + k * 8 + 4) + 1 ;
|
||||
rsrc.str_count = read_rsrc_short (&rsrc, rsrc.type_offset + k * 8 + 4) + 1 ;
|
||||
error = parse_str_rsrc (psf, &rsrc) ;
|
||||
goto parse_rsrc_fork_cleanup ;
|
||||
} ;
|
||||
@@ -547,26 +566,26 @@ parse_str_rsrc (SF_PRIVATE *psf, SD2_RSRC * rsrc)
|
||||
for (k = 0 ; data_offset + data_len < rsrc->rsrc_len ; k++)
|
||||
{ int slen ;
|
||||
|
||||
slen = read_char (rsrc->rsrc_data, str_offset) ;
|
||||
read_str (rsrc->rsrc_data, str_offset + 1, name, SF_MIN (SIGNED_SIZEOF (name), slen + 1)) ;
|
||||
slen = read_rsrc_char (rsrc, str_offset) ;
|
||||
read_rsrc_str (rsrc, str_offset + 1, name, SF_MIN (SIGNED_SIZEOF (name), slen + 1)) ;
|
||||
str_offset += slen + 1 ;
|
||||
|
||||
rsrc_id = read_short (rsrc->rsrc_data, rsrc->item_offset + k * 12) ;
|
||||
rsrc_id = read_rsrc_short (rsrc, rsrc->item_offset + k * 12) ;
|
||||
|
||||
data_offset = rsrc->data_offset + read_int (rsrc->rsrc_data, rsrc->item_offset + k * 12 + 4) ;
|
||||
data_offset = rsrc->data_offset + read_rsrc_int (rsrc, rsrc->item_offset + k * 12 + 4) ;
|
||||
if (data_offset < 0 || data_offset > rsrc->rsrc_len)
|
||||
{ psf_log_printf (psf, "Exiting parser on data offset of %d.\n", data_offset) ;
|
||||
break ;
|
||||
} ;
|
||||
|
||||
data_len = read_int (rsrc->rsrc_data, data_offset) ;
|
||||
data_len = read_rsrc_int (rsrc, data_offset) ;
|
||||
if (data_len < 0 || data_len > rsrc->rsrc_len)
|
||||
{ psf_log_printf (psf, "Exiting parser on data length of %d.\n", data_len) ;
|
||||
break ;
|
||||
} ;
|
||||
|
||||
slen = read_char (rsrc->rsrc_data, data_offset + 4) ;
|
||||
read_str (rsrc->rsrc_data, data_offset + 5, value, SF_MIN (SIGNED_SIZEOF (value), slen + 1)) ;
|
||||
slen = read_rsrc_char (rsrc, data_offset + 4) ;
|
||||
read_rsrc_str (rsrc, data_offset + 5, value, SF_MIN (SIGNED_SIZEOF (value), slen + 1)) ;
|
||||
|
||||
psf_log_printf (psf, " 0x%04x %4d %4d %3d '%s'\n", data_offset, rsrc_id, data_len, slen, value) ;
|
||||
|
||||
@@ -619,6 +638,10 @@ parse_str_rsrc (SF_PRIVATE *psf, SD2_RSRC * rsrc)
|
||||
psf->sf.format = SF_FORMAT_SD2 | SF_FORMAT_PCM_24 ;
|
||||
break ;
|
||||
|
||||
case 4 :
|
||||
psf->sf.format = SF_FORMAT_SD2 | SF_FORMAT_PCM_32 ;
|
||||
break ;
|
||||
|
||||
default :
|
||||
psf_log_printf (psf, "Bad sample size (%d)\n", rsrc->sample_size) ;
|
||||
return SFE_SD2_BAD_SAMPLE_SIZE ;
|
||||
|
||||
+91
-55
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** Copyright (C) 2002-2009 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
** Copyright (C) 2002-2012 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
@@ -56,6 +56,7 @@ typedef struct tag_SDS_PRIVATE
|
||||
int read_samples [SDS_BLOCK_SIZE / 2] ; /* Maximum samples per block */
|
||||
|
||||
int write_block, write_count ;
|
||||
int total_written ;
|
||||
unsigned char write_data [SDS_BLOCK_SIZE] ;
|
||||
int write_samples [SDS_BLOCK_SIZE / 2] ; /* Maximum samples per block */
|
||||
} SDS_PRIVATE ;
|
||||
@@ -82,6 +83,7 @@ static sf_count_t sds_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len
|
||||
static sf_count_t sds_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ;
|
||||
|
||||
static sf_count_t sds_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) ;
|
||||
static int sds_byterate (SF_PRIVATE * psf) ;
|
||||
|
||||
static int sds_2byte_read (SF_PRIVATE *psf, SDS_PRIVATE *psds) ;
|
||||
static int sds_3byte_read (SF_PRIVATE *psf, SDS_PRIVATE *psds) ;
|
||||
@@ -111,7 +113,7 @@ sds_open (SF_PRIVATE *psf)
|
||||
return SFE_MALLOC_FAILED ;
|
||||
psf->codec_data = psds ;
|
||||
|
||||
if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->filelength > 0))
|
||||
if (psf->file.mode == SFM_READ || (psf->file.mode == SFM_RDWR && psf->filelength > 0))
|
||||
{ if ((error = sds_read_header (psf, psds)))
|
||||
return error ;
|
||||
} ;
|
||||
@@ -119,7 +121,7 @@ sds_open (SF_PRIVATE *psf)
|
||||
if ((SF_CONTAINER (psf->sf.format)) != SF_FORMAT_SDS)
|
||||
return SFE_BAD_OPEN_FORMAT ;
|
||||
|
||||
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
|
||||
if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
|
||||
{ if (sds_write_header (psf, SF_FALSE))
|
||||
return psf->error ;
|
||||
|
||||
@@ -131,8 +133,9 @@ sds_open (SF_PRIVATE *psf)
|
||||
if ((error = sds_init (psf, psds)) != 0)
|
||||
return error ;
|
||||
|
||||
psf->seek = sds_seek ;
|
||||
psf->container_close = sds_close ;
|
||||
psf->seek = sds_seek ;
|
||||
psf->byterate = sds_byterate ;
|
||||
|
||||
psf->blockwidth = 0 ;
|
||||
|
||||
@@ -145,7 +148,7 @@ sds_open (SF_PRIVATE *psf)
|
||||
static int
|
||||
sds_close (SF_PRIVATE *psf)
|
||||
{
|
||||
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
|
||||
if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
|
||||
{ SDS_PRIVATE *psds ;
|
||||
|
||||
if ((psds = (SDS_PRIVATE *) psf->codec_data) == NULL)
|
||||
@@ -186,7 +189,7 @@ sds_init (SF_PRIVATE *psf, SDS_PRIVATE *psds)
|
||||
psds->samplesperblock = SDS_AUDIO_BYTES_PER_BLOCK / 4 ;
|
||||
} ;
|
||||
|
||||
if (psf->mode == SFM_READ || psf->mode == SFM_RDWR)
|
||||
if (psf->file.mode == SFM_READ || psf->file.mode == SFM_RDWR)
|
||||
{ psf->read_short = sds_read_s ;
|
||||
psf->read_int = sds_read_i ;
|
||||
psf->read_float = sds_read_f ;
|
||||
@@ -196,7 +199,7 @@ sds_init (SF_PRIVATE *psf, SDS_PRIVATE *psds)
|
||||
psds->reader (psf, psds) ;
|
||||
} ;
|
||||
|
||||
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
|
||||
if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
|
||||
{ psf->write_short = sds_write_s ;
|
||||
psf->write_int = sds_write_i ;
|
||||
psf->write_float = sds_write_f ;
|
||||
@@ -219,26 +222,47 @@ sds_read_header (SF_PRIVATE *psf, SDS_PRIVATE *psds)
|
||||
if (marker != 0xF07E || byte != 0x01)
|
||||
return SFE_SDS_NOT_SDS ;
|
||||
|
||||
psf_log_printf (psf, "Midi Sample Dump Standard (.sds)\nF07E\n Midi Channel : %d\n", channel) ;
|
||||
|
||||
bytesread += psf_binheader_readf (psf, "e213", &sample_no, &bitwidth, &samp_period) ;
|
||||
|
||||
bytesread += psf_binheader_readf (psf, "e2", &sample_no) ;
|
||||
sample_no = SDS_3BYTE_TO_INT_DECODE (sample_no) ;
|
||||
|
||||
psf_log_printf (psf, "Midi Sample Dump Standard (.sds)\nF07E\n"
|
||||
" Midi Channel : %d\n Sample Number : %d\n",
|
||||
channel, sample_no) ;
|
||||
|
||||
bytesread += psf_binheader_readf (psf, "e13", &bitwidth, &samp_period) ;
|
||||
|
||||
samp_period = SDS_3BYTE_TO_INT_DECODE (samp_period) ;
|
||||
|
||||
psds->bitwidth = bitwidth ;
|
||||
|
||||
psf->sf.samplerate = 1000000000 / samp_period ;
|
||||
if (psds->bitwidth > 1)
|
||||
psf_log_printf (psf, " Bit Width : %d\n", psds->bitwidth) ;
|
||||
else
|
||||
{ psf_log_printf (psf, " Bit Width : %d (should be > 1)\n", psds->bitwidth) ;
|
||||
return SFE_SDS_BAD_BIT_WIDTH ;
|
||||
} ;
|
||||
|
||||
psf_log_printf (psf, " Sample Number : %d\n"
|
||||
" Bit Width : %d\n"
|
||||
if (samp_period > 0)
|
||||
{ psf->sf.samplerate = 1000000000 / samp_period ;
|
||||
|
||||
psf_log_printf (psf, " Sample Period : %d\n"
|
||||
" Sample Rate : %d\n",
|
||||
sample_no, psds->bitwidth, psf->sf.samplerate) ;
|
||||
samp_period, psf->sf.samplerate) ;
|
||||
}
|
||||
else
|
||||
{ psf->sf.samplerate = 16000 ;
|
||||
|
||||
psf_log_printf (psf, " Sample Period : %d (should be > 0)\n"
|
||||
" Sample Rate : %d (guessed)\n",
|
||||
samp_period, psf->sf.samplerate) ;
|
||||
} ;
|
||||
|
||||
bytesread += psf_binheader_readf (psf, "e3331", &data_length, &sustain_loop_start, &sustain_loop_end, &loop_type) ;
|
||||
|
||||
data_length = SDS_3BYTE_TO_INT_DECODE (data_length) ;
|
||||
|
||||
psf->sf.frames = psds->frames = data_length ;
|
||||
|
||||
sustain_loop_start = SDS_3BYTE_TO_INT_DECODE (sustain_loop_start) ;
|
||||
sustain_loop_end = SDS_3BYTE_TO_INT_DECODE (sustain_loop_end) ;
|
||||
|
||||
@@ -251,13 +275,6 @@ sds_read_header (SF_PRIVATE *psf, SDS_PRIVATE *psds)
|
||||
psf->dataoffset = SDS_DATA_OFFSET ;
|
||||
psf->datalength = psf->filelength - psf->dataoffset ;
|
||||
|
||||
if (data_length != psf->filelength - psf->dataoffset)
|
||||
{ psf_log_printf (psf, " Datalength : %d (truncated data??? %d)\n", data_length, psf->filelength - psf->dataoffset) ;
|
||||
data_length = psf->filelength - psf->dataoffset ;
|
||||
}
|
||||
else
|
||||
psf_log_printf (psf, " Datalength : %d\n", data_length) ;
|
||||
|
||||
bytesread += psf_binheader_readf (psf, "1", &byte) ;
|
||||
if (byte != 0xF7)
|
||||
psf_log_printf (psf, "bad end : %X\n", byte & 0xFF) ;
|
||||
@@ -281,9 +298,6 @@ sds_read_header (SF_PRIVATE *psf, SDS_PRIVATE *psds)
|
||||
|
||||
psf_log_printf (psf, "Frames : %d\n", blockcount * psds->samplesperblock) ;
|
||||
|
||||
psf->sf.frames = blockcount * psds->samplesperblock ;
|
||||
psds->frames = blockcount * psds->samplesperblock ;
|
||||
|
||||
/* Always Mono */
|
||||
psf->sf.channels = 1 ;
|
||||
psf->sf.sections = 1 ;
|
||||
@@ -337,7 +351,7 @@ sds_write_header (SF_PRIVATE *psf, int calc_length)
|
||||
current = psf_ftell (psf) ;
|
||||
|
||||
if (calc_length)
|
||||
psf->sf.frames = psds->total_blocks * psds->samplesperblock + psds->write_count ;
|
||||
psf->sf.frames = psds->total_written ;
|
||||
|
||||
if (psds->write_count > 0)
|
||||
{ int current_count = psds->write_count ;
|
||||
@@ -378,9 +392,9 @@ sds_write_header (SF_PRIVATE *psf, int calc_length)
|
||||
|
||||
psf_binheader_writef (psf, "e213", 0, psds->bitwidth, samp_period) ;
|
||||
|
||||
data_length = SDS_INT_TO_3BYTE_ENCODE (psds->total_blocks * SDS_BLOCK_SIZE) ;
|
||||
data_length = SDS_INT_TO_3BYTE_ENCODE (psds->total_written) ;
|
||||
sustain_loop_start = SDS_INT_TO_3BYTE_ENCODE (0) ;
|
||||
sustain_loop_end = SDS_INT_TO_3BYTE_ENCODE (psf->sf.frames) ;
|
||||
sustain_loop_end = SDS_INT_TO_3BYTE_ENCODE (0) ;
|
||||
|
||||
psf_binheader_writef (psf, "e33311", data_length, sustain_loop_start, sustain_loop_end, loop_type, 0xF7) ;
|
||||
|
||||
@@ -429,7 +443,7 @@ sds_2byte_read (SF_PRIVATE *psf, SDS_PRIVATE *psds)
|
||||
{ printf ("Error 1 : %02X\n", checksum & 0xFF) ;
|
||||
}
|
||||
|
||||
for (k = 2 ; k < SDS_BLOCK_SIZE - 3 ; k ++)
|
||||
for (k = 2 ; k <= SDS_BLOCK_SIZE - 3 ; k ++)
|
||||
checksum ^= psds->read_data [k] ;
|
||||
|
||||
checksum &= 0x7F ;
|
||||
@@ -473,7 +487,7 @@ sds_3byte_read (SF_PRIVATE *psf, SDS_PRIVATE *psds)
|
||||
{ printf ("Error 1 : %02X\n", checksum & 0xFF) ;
|
||||
}
|
||||
|
||||
for (k = 2 ; k < SDS_BLOCK_SIZE - 3 ; k ++)
|
||||
for (k = 2 ; k <= SDS_BLOCK_SIZE - 3 ; k ++)
|
||||
checksum ^= psds->read_data [k] ;
|
||||
|
||||
checksum &= 0x7F ;
|
||||
@@ -517,7 +531,7 @@ sds_4byte_read (SF_PRIVATE *psf, SDS_PRIVATE *psds)
|
||||
{ printf ("Error 1 : %02X\n", checksum & 0xFF) ;
|
||||
}
|
||||
|
||||
for (k = 2 ; k < SDS_BLOCK_SIZE - 3 ; k ++)
|
||||
for (k = 2 ; k <= SDS_BLOCK_SIZE - 3 ; k ++)
|
||||
checksum ^= psds->read_data [k] ;
|
||||
|
||||
checksum &= 0x7F ;
|
||||
@@ -538,7 +552,8 @@ sds_4byte_read (SF_PRIVATE *psf, SDS_PRIVATE *psds)
|
||||
|
||||
static sf_count_t
|
||||
sds_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
|
||||
{ SDS_PRIVATE *psds ;
|
||||
{ BUF_UNION ubuf ;
|
||||
SDS_PRIVATE *psds ;
|
||||
int *iptr ;
|
||||
int k, bufferlen, readcount, count ;
|
||||
sf_count_t total = 0 ;
|
||||
@@ -547,8 +562,8 @@ sds_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
|
||||
return 0 ;
|
||||
psds = (SDS_PRIVATE*) psf->codec_data ;
|
||||
|
||||
iptr = psf->u.ibuf ;
|
||||
bufferlen = ARRAY_LEN (psf->u.ibuf) ;
|
||||
iptr = ubuf.ibuf ;
|
||||
bufferlen = ARRAY_LEN (ubuf.ibuf) ;
|
||||
while (len > 0)
|
||||
{ readcount = (len >= bufferlen) ? bufferlen : len ;
|
||||
count = sds_read (psf, psds, iptr, readcount) ;
|
||||
@@ -577,7 +592,8 @@ sds_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
|
||||
|
||||
static sf_count_t
|
||||
sds_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
|
||||
{ SDS_PRIVATE *psds ;
|
||||
{ BUF_UNION ubuf ;
|
||||
SDS_PRIVATE *psds ;
|
||||
int *iptr ;
|
||||
int k, bufferlen, readcount, count ;
|
||||
sf_count_t total = 0 ;
|
||||
@@ -592,8 +608,8 @@ sds_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
|
||||
else
|
||||
normfact = 1.0 / (1 << psds->bitwidth) ;
|
||||
|
||||
iptr = psf->u.ibuf ;
|
||||
bufferlen = ARRAY_LEN (psf->u.ibuf) ;
|
||||
iptr = ubuf.ibuf ;
|
||||
bufferlen = ARRAY_LEN (ubuf.ibuf) ;
|
||||
while (len > 0)
|
||||
{ readcount = (len >= bufferlen) ? bufferlen : len ;
|
||||
count = sds_read (psf, psds, iptr, readcount) ;
|
||||
@@ -608,7 +624,8 @@ sds_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
|
||||
|
||||
static sf_count_t
|
||||
sds_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
|
||||
{ SDS_PRIVATE *psds ;
|
||||
{ BUF_UNION ubuf ;
|
||||
SDS_PRIVATE *psds ;
|
||||
int *iptr ;
|
||||
int k, bufferlen, readcount, count ;
|
||||
sf_count_t total = 0 ;
|
||||
@@ -623,8 +640,8 @@ sds_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
|
||||
else
|
||||
normfact = 1.0 / (1 << psds->bitwidth) ;
|
||||
|
||||
iptr = psf->u.ibuf ;
|
||||
bufferlen = ARRAY_LEN (psf->u.ibuf) ;
|
||||
iptr = ubuf.ibuf ;
|
||||
bufferlen = ARRAY_LEN (ubuf.ibuf) ;
|
||||
while (len > 0)
|
||||
{ readcount = (len >= bufferlen) ? bufferlen : len ;
|
||||
count = sds_read (psf, psds, iptr, readcount) ;
|
||||
@@ -737,6 +754,15 @@ sds_seek (SF_PRIVATE *psf, int mode, sf_count_t seek_from_start)
|
||||
return seek_from_start ;
|
||||
} /* sds_seek */
|
||||
|
||||
static int
|
||||
sds_byterate (SF_PRIVATE * psf)
|
||||
{
|
||||
if (psf->file.mode == SFM_READ)
|
||||
return (psf->datalength * psf->sf.samplerate) / psf->sf.frames ;
|
||||
|
||||
return -1 ;
|
||||
} /* sds_byterate */
|
||||
|
||||
/*==============================================================================
|
||||
*/
|
||||
|
||||
@@ -749,7 +775,8 @@ sds_2byte_write (SF_PRIVATE *psf, SDS_PRIVATE *psds)
|
||||
psds->write_data [0] = 0xF0 ;
|
||||
psds->write_data [1] = 0x7E ;
|
||||
psds->write_data [2] = 0 ; /* Channel number */
|
||||
psds->write_data [3] = psds->write_block & 0x7F ; /* Packet number */
|
||||
psds->write_data [3] = 2 ;
|
||||
psds->write_data [4] = psds->write_block & 0x7F ; /* Packet number */
|
||||
|
||||
ucptr = psds->write_data + 5 ;
|
||||
for (k = 0 ; k < 120 ; k += 2)
|
||||
@@ -760,7 +787,7 @@ sds_2byte_write (SF_PRIVATE *psf, SDS_PRIVATE *psds)
|
||||
} ;
|
||||
|
||||
checksum = psds->write_data [1] ;
|
||||
for (k = 2 ; k < SDS_BLOCK_SIZE - 3 ; k ++)
|
||||
for (k = 2 ; k <= SDS_BLOCK_SIZE - 3 ; k ++)
|
||||
checksum ^= psds->write_data [k] ;
|
||||
checksum &= 0x7F ;
|
||||
|
||||
@@ -789,7 +816,8 @@ sds_3byte_write (SF_PRIVATE *psf, SDS_PRIVATE *psds)
|
||||
psds->write_data [0] = 0xF0 ;
|
||||
psds->write_data [1] = 0x7E ;
|
||||
psds->write_data [2] = 0 ; /* Channel number */
|
||||
psds->write_data [3] = psds->write_block & 0x7F ; /* Packet number */
|
||||
psds->write_data [3] = 2 ;
|
||||
psds->write_data [4] = psds->write_block & 0x7F ; /* Packet number */
|
||||
|
||||
ucptr = psds->write_data + 5 ;
|
||||
for (k = 0 ; k < 120 ; k += 3)
|
||||
@@ -801,7 +829,7 @@ sds_3byte_write (SF_PRIVATE *psf, SDS_PRIVATE *psds)
|
||||
} ;
|
||||
|
||||
checksum = psds->write_data [1] ;
|
||||
for (k = 2 ; k < SDS_BLOCK_SIZE - 3 ; k ++)
|
||||
for (k = 2 ; k <= SDS_BLOCK_SIZE - 3 ; k ++)
|
||||
checksum ^= psds->write_data [k] ;
|
||||
checksum &= 0x7F ;
|
||||
|
||||
@@ -830,7 +858,8 @@ sds_4byte_write (SF_PRIVATE *psf, SDS_PRIVATE *psds)
|
||||
psds->write_data [0] = 0xF0 ;
|
||||
psds->write_data [1] = 0x7E ;
|
||||
psds->write_data [2] = 0 ; /* Channel number */
|
||||
psds->write_data [3] = psds->write_block & 0x7F ; /* Packet number */
|
||||
psds->write_data [3] = 2 ;
|
||||
psds->write_data [4] = psds->write_block & 0x7F ; /* Packet number */
|
||||
|
||||
ucptr = psds->write_data + 5 ;
|
||||
for (k = 0 ; k < 120 ; k += 4)
|
||||
@@ -843,7 +872,7 @@ sds_4byte_write (SF_PRIVATE *psf, SDS_PRIVATE *psds)
|
||||
} ;
|
||||
|
||||
checksum = psds->write_data [1] ;
|
||||
for (k = 2 ; k < SDS_BLOCK_SIZE - 3 ; k ++)
|
||||
for (k = 2 ; k <= SDS_BLOCK_SIZE - 3 ; k ++)
|
||||
checksum ^= psds->write_data [k] ;
|
||||
checksum &= 0x7F ;
|
||||
|
||||
@@ -865,7 +894,8 @@ sds_4byte_write (SF_PRIVATE *psf, SDS_PRIVATE *psds)
|
||||
|
||||
static sf_count_t
|
||||
sds_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len)
|
||||
{ SDS_PRIVATE *psds ;
|
||||
{ BUF_UNION ubuf ;
|
||||
SDS_PRIVATE *psds ;
|
||||
int *iptr ;
|
||||
int k, bufferlen, writecount, count ;
|
||||
sf_count_t total = 0 ;
|
||||
@@ -873,9 +903,10 @@ sds_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len)
|
||||
if (psf->codec_data == NULL)
|
||||
return 0 ;
|
||||
psds = (SDS_PRIVATE*) psf->codec_data ;
|
||||
psds->total_written += len ;
|
||||
|
||||
iptr = psf->u.ibuf ;
|
||||
bufferlen = ARRAY_LEN (psf->u.ibuf) ;
|
||||
iptr = ubuf.ibuf ;
|
||||
bufferlen = ARRAY_LEN (ubuf.ibuf) ;
|
||||
while (len > 0)
|
||||
{ writecount = (len >= bufferlen) ? bufferlen : len ;
|
||||
for (k = 0 ; k < writecount ; k++)
|
||||
@@ -896,6 +927,7 @@ sds_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len)
|
||||
if (psf->codec_data == NULL)
|
||||
return 0 ;
|
||||
psds = (SDS_PRIVATE*) psf->codec_data ;
|
||||
psds->total_written += len ;
|
||||
|
||||
total = sds_write (psf, psds, ptr, len) ;
|
||||
|
||||
@@ -904,7 +936,8 @@ sds_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len)
|
||||
|
||||
static sf_count_t
|
||||
sds_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
|
||||
{ SDS_PRIVATE *psds ;
|
||||
{ BUF_UNION ubuf ;
|
||||
SDS_PRIVATE *psds ;
|
||||
int *iptr ;
|
||||
int k, bufferlen, writecount, count ;
|
||||
sf_count_t total = 0 ;
|
||||
@@ -913,14 +946,15 @@ sds_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
|
||||
if (psf->codec_data == NULL)
|
||||
return 0 ;
|
||||
psds = (SDS_PRIVATE*) psf->codec_data ;
|
||||
psds->total_written += len ;
|
||||
|
||||
if (psf->norm_float == SF_TRUE)
|
||||
normfact = 1.0 * 0x80000000 ;
|
||||
else
|
||||
normfact = 1.0 * (1 << psds->bitwidth) ;
|
||||
|
||||
iptr = psf->u.ibuf ;
|
||||
bufferlen = ARRAY_LEN (psf->u.ibuf) ;
|
||||
iptr = ubuf.ibuf ;
|
||||
bufferlen = ARRAY_LEN (ubuf.ibuf) ;
|
||||
while (len > 0)
|
||||
{ writecount = (len >= bufferlen) ? bufferlen : len ;
|
||||
for (k = 0 ; k < writecount ; k++)
|
||||
@@ -935,7 +969,8 @@ sds_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
|
||||
|
||||
static sf_count_t
|
||||
sds_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
|
||||
{ SDS_PRIVATE *psds ;
|
||||
{ BUF_UNION ubuf ;
|
||||
SDS_PRIVATE *psds ;
|
||||
int *iptr ;
|
||||
int k, bufferlen, writecount, count ;
|
||||
sf_count_t total = 0 ;
|
||||
@@ -944,14 +979,15 @@ sds_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
|
||||
if (psf->codec_data == NULL)
|
||||
return 0 ;
|
||||
psds = (SDS_PRIVATE*) psf->codec_data ;
|
||||
psds->total_written += len ;
|
||||
|
||||
if (psf->norm_double == SF_TRUE)
|
||||
normfact = 1.0 * 0x80000000 ;
|
||||
else
|
||||
normfact = 1.0 * (1 << psds->bitwidth) ;
|
||||
|
||||
iptr = psf->u.ibuf ;
|
||||
bufferlen = ARRAY_LEN (psf->u.ibuf) ;
|
||||
iptr = ubuf.ibuf ;
|
||||
bufferlen = ARRAY_LEN (ubuf.ibuf) ;
|
||||
while (len > 0)
|
||||
{ writecount = (len >= bufferlen) ? bufferlen : len ;
|
||||
for (k = 0 ; k < writecount ; k++)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** Copyright (C) 2002-2009 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
** Copyright (C) 2002-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
@@ -34,15 +34,17 @@
|
||||
#define S_IXUSR 0000100 /* execute/search permission, owner */
|
||||
#endif
|
||||
|
||||
#define S_IRWXG 0000070 /* rwx, group */
|
||||
#define S_IRGRP 0000040 /* read permission, group */
|
||||
#define S_IWGRP 0000020 /* write permission, grougroup */
|
||||
#define S_IXGRP 0000010 /* execute/search permission, group */
|
||||
/* Windows doesn't have group permissions so set all these to zero. */
|
||||
#define S_IRWXG 0 /* rwx, group */
|
||||
#define S_IRGRP 0 /* read permission, group */
|
||||
#define S_IWGRP 0 /* write permission, grougroup */
|
||||
#define S_IXGRP 0 /* execute/search permission, group */
|
||||
|
||||
#define S_IRWXO 0000007 /* rwx, other */
|
||||
#define S_IROTH 0000004 /* read permission, other */
|
||||
#define S_IWOTH 0000002 /* write permission, other */
|
||||
#define S_IXOTH 0000001 /* execute/search permission, other */
|
||||
/* Windows doesn't have others permissions so set all these to zero. */
|
||||
#define S_IRWXO 0 /* rwx, other */
|
||||
#define S_IROTH 0 /* read permission, other */
|
||||
#define S_IWOTH 0 /* write permission, other */
|
||||
#define S_IXOTH 0 /* execute/search permission, other */
|
||||
|
||||
#ifndef S_ISFIFO
|
||||
#define S_ISFIFO(mode) (((mode) & _S_IFMT) == _S_IFIFO)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** Copyright (C) 2005-2009 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
** Copyright (C) 2005-2013 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
@@ -53,6 +53,10 @@
|
||||
#define HAVE_ENDIAN_H 0
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_FSTAT64
|
||||
#define HAVE_FSTAT64 0
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_FSYNC
|
||||
#define HAVE_FSYNC 0
|
||||
#endif
|
||||
@@ -73,14 +77,6 @@
|
||||
#define HAVE_MMAP 0
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_PREAD
|
||||
#define HAVE_PREAD 0
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_PWRITE
|
||||
#define HAVE_PWRITE 0
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_SETLOCALE
|
||||
#define HAVE_SETLOCALE 0
|
||||
#endif
|
||||
@@ -93,9 +89,27 @@
|
||||
#define HAVE_STDINT_H 0
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_SYS_WAIT_H
|
||||
#define HAVE_SYS_WAIT_H 0
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_UNISTD_H
|
||||
#define HAVE_UNISTD_H 0
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_PIPE
|
||||
#define HAVE_PIPE 0
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_WAITPID
|
||||
#define HAVE_WAITPID 0
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_X86INTRIN_H
|
||||
#define HAVE_X86INTRIN_H 0
|
||||
#endif
|
||||
|
||||
#define CPU_IS_X86 (defined __i486__ || defined __i586__ || defined __i686__ || defined __x86_64__)
|
||||
#define CPU_IS_X86_64 (defined __x86_64__)
|
||||
|
||||
#endif
|
||||
+147
-105
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** Copyright (C) 1999-2009 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
** Copyright (C) 1999-2013 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
@@ -21,38 +21,72 @@
|
||||
|
||||
#include "sfconfig.h"
|
||||
|
||||
#if HAVE_STDINT_H
|
||||
#include <stdint.h>
|
||||
#elif HAVE_INTTYPES_H
|
||||
#ifndef WIN32
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
|
||||
#if (defined (SIZEOF_INT64_T) && (SIZEOF_INT64_T == 8))
|
||||
/* Good, we have int64_t. */
|
||||
#elif (defined (SIZEOF_LONG_LONG) && (SIZEOF_LONG_LONG == 8))
|
||||
typedef long long int64_t ;
|
||||
#elif (defined (SIZEOF_LONG) && (SIZEOF_LONG == 8))
|
||||
typedef long int64_t ;
|
||||
#elif (defined (WIN32) || defined (_WIN32))
|
||||
typedef __int64 int64_t ;
|
||||
#else
|
||||
#error "No 64 bit integer type."
|
||||
|
||||
#if COMPILER_IS_GCC && CPU_IS_X86
|
||||
|
||||
static inline int16_t
|
||||
ENDSWAP_16 (int16_t x)
|
||||
{ int16_t y ;
|
||||
__asm__ ("rorw $8, %w0" : "=r" (y) : "0" (x) : "cc") ;
|
||||
return y ;
|
||||
} /* ENDSWAP_16 */
|
||||
|
||||
static inline int32_t
|
||||
ENDSWAP_32 (int32_t x)
|
||||
{ int32_t y ;
|
||||
__asm__ ("bswap %0" : "=r" (y) : "0" (x)) ;
|
||||
return y ;
|
||||
} /* ENDSWAP_32 */
|
||||
|
||||
#if CPU_IS_X86_64
|
||||
|
||||
static inline int64_t
|
||||
ENDSWAP_64X (int64_t x)
|
||||
{ int64_t y ;
|
||||
__asm__ ("bswap %q0" : "=r" (y) : "0" (x)) ;
|
||||
return y ;
|
||||
} /* ENDSWAP_64X */
|
||||
|
||||
#define ENDSWAP_64 ENDSWAP_64X
|
||||
|
||||
#endif
|
||||
|
||||
#if HAVE_BYTESWAP_H
|
||||
|
||||
#elif HAVE_BYTESWAP_H /* Linux, any CPU */
|
||||
#include <byteswap.h>
|
||||
|
||||
#define ENDSWAP_SHORT(x) ((short) bswap_16 (x))
|
||||
#define ENDSWAP_INT(x) ((int) bswap_32 (x))
|
||||
#define ENDSWAP_16(x) (bswap_16 (x))
|
||||
#define ENDSWAP_32(x) (bswap_32 (x))
|
||||
#define ENDSWAP_64(x) (bswap_64 (x))
|
||||
|
||||
#else
|
||||
|
||||
#define ENDSWAP_SHORT(x) ((((x) >> 8) & 0xFF) + (((x) & 0xFF) << 8))
|
||||
#define ENDSWAP_INT(x) ((((x) >> 24) & 0xFF) + (((x) >> 8) & 0xFF00) + (((x) & 0xFF00) << 8) + (((x) & 0xFF) << 24))
|
||||
#define ENDSWAP_16(x) ((((x) >> 8) & 0xFF) + (((x) & 0xFF) << 8))
|
||||
#define ENDSWAP_32(x) ((((x) >> 24) & 0xFF) + (((x) >> 8) & 0xFF00) + (((x) & 0xFF00) << 8) + (((x) & 0xFF) << 24))
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef ENDSWAP_64
|
||||
static inline uint64_t
|
||||
ENDSWAP_64 (uint64_t x)
|
||||
{ union
|
||||
{ uint32_t parts [2] ;
|
||||
uint64_t whole ;
|
||||
} u ;
|
||||
uint32_t temp ;
|
||||
|
||||
u.whole = x ;
|
||||
temp = u.parts [0] ;
|
||||
u.parts [0] = ENDSWAP_32 (u.parts [1]) ;
|
||||
u.parts [1] = ENDSWAP_32 (temp) ;
|
||||
return u.whole ;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Many file types (ie WAV, AIFF) use sets of four consecutive bytes as a
|
||||
** marker indicating different sections of the file.
|
||||
@@ -61,9 +95,9 @@ typedef __int64 int64_t ;
|
||||
*/
|
||||
|
||||
#if (CPU_IS_LITTLE_ENDIAN == 1)
|
||||
#define MAKE_MARKER(a,b,c,d) ((a) | ((b) << 8) | ((c) << 16) | ((d) << 24))
|
||||
#define MAKE_MARKER(a, b, c, d) ((uint32_t) ((a) | ((b) << 8) | ((c) << 16) | (((uint32_t) (d)) << 24)))
|
||||
#elif (CPU_IS_BIG_ENDIAN == 1)
|
||||
#define MAKE_MARKER(a,b,c,d) (((a) << 24) | ((b) << 16) | ((c) << 8) | (d))
|
||||
#define MAKE_MARKER(a, b, c, d) ((uint32_t) ((((uint32_t) (a)) << 24) | ((b) << 16) | ((c) << 8) | (d)))
|
||||
#else
|
||||
#error "Target CPU endian-ness unknown. May need to hand edit src/sfconfig.h"
|
||||
#endif
|
||||
@@ -76,34 +110,102 @@ typedef __int64 int64_t ;
|
||||
*/
|
||||
|
||||
#if (CPU_IS_LITTLE_ENDIAN == 1)
|
||||
#define LES2H_SHORT(x) (x)
|
||||
#define LEI2H_INT(x) (x)
|
||||
#define LE2H_16(x) (x)
|
||||
#define LE2H_32(x) (x)
|
||||
|
||||
#define BES2H_SHORT(x) ENDSWAP_SHORT (x)
|
||||
#define BEI2H_INT(x) ENDSWAP_INT (x)
|
||||
#define BE2H_16(x) ENDSWAP_16 (x)
|
||||
#define BE2H_32(x) ENDSWAP_32 (x)
|
||||
#define BE2H_64(x) ENDSWAP_64 (x)
|
||||
|
||||
#define H2BE_SHORT(x) ENDSWAP_SHORT (x)
|
||||
#define H2BE_INT(x) ENDSWAP_INT (x)
|
||||
#define H2BE_16(x) ENDSWAP_16 (x)
|
||||
#define H2BE_32(x) ENDSWAP_32 (x)
|
||||
|
||||
#elif (CPU_IS_BIG_ENDIAN == 1)
|
||||
#define LES2H_SHORT(x) ENDSWAP_SHORT (x)
|
||||
#define LEI2H_INT(x) ENDSWAP_INT (x)
|
||||
#define LE2H_16(x) ENDSWAP_16 (x)
|
||||
#define LE2H_32(x) ENDSWAP_32 (x)
|
||||
|
||||
#define BES2H_SHORT(x) (x)
|
||||
#define BEI2H_INT(x) (x)
|
||||
#define BE2H_16(x) (x)
|
||||
#define BE2H_32(x) (x)
|
||||
#define BE2H_64(x) (x)
|
||||
|
||||
#define H2LE_SHORT(x) ENDSWAP_SHORT (x)
|
||||
#define H2LE_INT(x) ENDSWAP_INT (x)
|
||||
#define H2BE_16(x) (x)
|
||||
#define H2BE_32(x) (x)
|
||||
|
||||
#define H2LE_16(x) ENDSWAP_16 (x)
|
||||
#define H2LE_32(x) ENDSWAP_32 (x)
|
||||
|
||||
#else
|
||||
#error "Target CPU endian-ness unknown. May need to hand edit src/sfconfig.h"
|
||||
#endif
|
||||
|
||||
#define LET2H_SHORT_PTR(x) ((x) [1] + ((x) [2] << 8))
|
||||
#define LET2H_INT_PTR(x) (((x) [0] << 8) + ((x) [1] << 16) + ((x) [2] << 24))
|
||||
#define LET2H_16_PTR(x) ((x) [1] + ((x) [2] << 8))
|
||||
#define LET2H_32_PTR(x) (((x) [0] << 8) + ((x) [1] << 16) + ((x) [2] << 24))
|
||||
|
||||
#define BET2H_SHORT_PTR(x) (((x) [0] << 8) + (x) [1])
|
||||
#define BET2H_INT_PTR(x) (((x) [0] << 24) + ((x) [1] << 16) + ((x) [2] << 8))
|
||||
#define BET2H_16_PTR(x) (((x) [0] << 8) + (x) [1])
|
||||
#define BET2H_32_PTR(x) (((x) [0] << 24) + ((x) [1] << 16) + ((x) [2] << 8))
|
||||
|
||||
static inline void
|
||||
psf_put_be64 (uint8_t *ptr, int offset, int64_t value)
|
||||
{
|
||||
ptr [offset] = value >> 56 ;
|
||||
ptr [offset + 1] = value >> 48 ;
|
||||
ptr [offset + 2] = value >> 40 ;
|
||||
ptr [offset + 3] = value >> 32 ;
|
||||
ptr [offset + 4] = value >> 24 ;
|
||||
ptr [offset + 5] = value >> 16 ;
|
||||
ptr [offset + 6] = value >> 8 ;
|
||||
ptr [offset + 7] = value ;
|
||||
} /* psf_put_be64 */
|
||||
|
||||
static inline void
|
||||
psf_put_be32 (uint8_t *ptr, int offset, int32_t value)
|
||||
{
|
||||
ptr [offset] = value >> 24 ;
|
||||
ptr [offset + 1] = value >> 16 ;
|
||||
ptr [offset + 2] = value >> 8 ;
|
||||
ptr [offset + 3] = value ;
|
||||
} /* psf_put_be32 */
|
||||
|
||||
static inline void
|
||||
psf_put_be16 (uint8_t *ptr, int offset, int16_t value)
|
||||
{
|
||||
ptr [offset] = value >> 8 ;
|
||||
ptr [offset + 1] = value ;
|
||||
} /* psf_put_be16 */
|
||||
|
||||
static inline int64_t
|
||||
psf_get_be64 (uint8_t *ptr, int offset)
|
||||
{ int64_t value ;
|
||||
|
||||
value = ptr [offset] << 24 ;
|
||||
value += ptr [offset + 1] << 16 ;
|
||||
value += ptr [offset + 2] << 8 ;
|
||||
value += ptr [offset + 3] ;
|
||||
|
||||
value <<= 32 ;
|
||||
|
||||
value += ptr [offset + 4] << 24 ;
|
||||
value += ptr [offset + 5] << 16 ;
|
||||
value += ptr [offset + 6] << 8 ;
|
||||
value += ptr [offset + 7] ;
|
||||
return value ;
|
||||
} /* psf_get_be64 */
|
||||
|
||||
static inline int32_t
|
||||
psf_get_be32 (uint8_t *ptr, int offset)
|
||||
{ int32_t value ;
|
||||
|
||||
value = ptr [offset] << 24 ;
|
||||
value += ptr [offset + 1] << 16 ;
|
||||
value += ptr [offset + 2] << 8 ;
|
||||
value += ptr [offset + 3] ;
|
||||
return value ;
|
||||
} /* psf_get_be32 */
|
||||
|
||||
static inline int16_t
|
||||
psf_get_be16 (uint8_t *ptr, int offset)
|
||||
{ return (ptr [offset] << 8) + ptr [offset + 1] ;
|
||||
} /* psf_get_be16 */
|
||||
|
||||
/*-----------------------------------------------------------------------------------------------
|
||||
** Generic functions for performing endian swapping on integer arrays.
|
||||
@@ -115,7 +217,7 @@ endswap_short_array (short *ptr, int len)
|
||||
|
||||
while (--len >= 0)
|
||||
{ temp = ptr [len] ;
|
||||
ptr [len] = ENDSWAP_SHORT (temp) ;
|
||||
ptr [len] = ENDSWAP_16 (temp) ;
|
||||
} ;
|
||||
} /* endswap_short_array */
|
||||
|
||||
@@ -123,7 +225,7 @@ static inline void
|
||||
endswap_short_copy (short *dest, const short *src, int len)
|
||||
{
|
||||
while (--len >= 0)
|
||||
{ dest [len] = ENDSWAP_SHORT (src [len]) ;
|
||||
{ dest [len] = ENDSWAP_16 (src [len]) ;
|
||||
} ;
|
||||
} /* endswap_short_copy */
|
||||
|
||||
@@ -133,7 +235,7 @@ endswap_int_array (int *ptr, int len)
|
||||
|
||||
while (--len >= 0)
|
||||
{ temp = ptr [len] ;
|
||||
ptr [len] = ENDSWAP_INT (temp) ;
|
||||
ptr [len] = ENDSWAP_32 (temp) ;
|
||||
} ;
|
||||
} /* endswap_int_array */
|
||||
|
||||
@@ -141,22 +243,20 @@ static inline void
|
||||
endswap_int_copy (int *dest, const int *src, int len)
|
||||
{
|
||||
while (--len >= 0)
|
||||
{ dest [len] = ENDSWAP_INT (src [len]) ;
|
||||
{ dest [len] = ENDSWAP_32 (src [len]) ;
|
||||
} ;
|
||||
} /* endswap_int_copy */
|
||||
|
||||
/*========================================================================================
|
||||
*/
|
||||
|
||||
#if (HAVE_BYTESWAP_H && defined (SIZEOF_INT64_T) && (SIZEOF_INT64_T == 8))
|
||||
|
||||
static inline void
|
||||
endswap_int64_t_array (int64_t *ptr, int len)
|
||||
{ int64_t value ;
|
||||
|
||||
while (--len >= 0)
|
||||
{ value = ptr [len] ;
|
||||
ptr [len] = bswap_64 (value) ;
|
||||
ptr [len] = ENDSWAP_64 (value) ;
|
||||
} ;
|
||||
} /* endswap_int64_t_array */
|
||||
|
||||
@@ -166,78 +266,20 @@ endswap_int64_t_copy (int64_t *dest, const int64_t *src, int len)
|
||||
|
||||
while (--len >= 0)
|
||||
{ value = src [len] ;
|
||||
dest [len] = bswap_64 (value) ;
|
||||
dest [len] = ENDSWAP_64 (value) ;
|
||||
} ;
|
||||
} /* endswap_int64_t_copy */
|
||||
|
||||
#else
|
||||
|
||||
static inline void
|
||||
endswap_int64_t_array (int64_t *ptr, int len)
|
||||
{ unsigned char *ucptr, temp ;
|
||||
|
||||
ucptr = (unsigned char *) ptr ;
|
||||
ucptr += 8 * len ;
|
||||
while (--len >= 0)
|
||||
{ ucptr -= 8 ;
|
||||
|
||||
temp = ucptr [0] ;
|
||||
ucptr [0] = ucptr [7] ;
|
||||
ucptr [7] = temp ;
|
||||
|
||||
temp = ucptr [1] ;
|
||||
ucptr [1] = ucptr [6] ;
|
||||
ucptr [6] = temp ;
|
||||
|
||||
temp = ucptr [2] ;
|
||||
ucptr [2] = ucptr [5] ;
|
||||
ucptr [5] = temp ;
|
||||
|
||||
temp = ucptr [3] ;
|
||||
ucptr [3] = ucptr [4] ;
|
||||
ucptr [4] = temp ;
|
||||
} ;
|
||||
} /* endswap_int64_t_array */
|
||||
|
||||
static inline void
|
||||
endswap_int64_t_copy (int64_t *dest, const int64_t *src, int len)
|
||||
{ const unsigned char *psrc ;
|
||||
unsigned char *pdest ;
|
||||
|
||||
if (dest == src)
|
||||
{ endswap_int64_t_array (dest, len) ;
|
||||
return ;
|
||||
} ;
|
||||
|
||||
psrc = ((const unsigned char *) src) + 8 * len ;
|
||||
pdest = ((unsigned char *) dest) + 8 * len ;
|
||||
while (--len >= 0)
|
||||
{ psrc -= 8 ;
|
||||
pdest -= 8 ;
|
||||
|
||||
pdest [0] = psrc [7] ;
|
||||
pdest [2] = psrc [5] ;
|
||||
pdest [4] = psrc [3] ;
|
||||
pdest [6] = psrc [1] ;
|
||||
pdest [7] = psrc [0] ;
|
||||
pdest [1] = psrc [6] ;
|
||||
pdest [3] = psrc [4] ;
|
||||
pdest [5] = psrc [2] ;
|
||||
} ;
|
||||
} /* endswap_int64_t_copy */
|
||||
|
||||
#endif
|
||||
|
||||
/* A couple of wrapper functions. */
|
||||
|
||||
static inline void
|
||||
endswap_float_array (float *ptr, int len)
|
||||
{ endswap_int_array ((void *) ptr, len) ;
|
||||
{ endswap_int_array ((int *) ptr, len) ;
|
||||
} /* endswap_float_array */
|
||||
|
||||
static inline void
|
||||
endswap_double_array (double *ptr, int len)
|
||||
{ endswap_int64_t_array ((void *) ptr, len) ;
|
||||
{ endswap_int64_t_array ((int64_t *) ptr, len) ;
|
||||
} /* endswap_double_array */
|
||||
|
||||
static inline void
|
||||
|
||||
+503
-209
File diff suppressed because it is too large.
Load diff
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** Copyright (C) 1999-2009 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
** Copyright (C) 1999-2013 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
@@ -30,6 +30,7 @@
|
||||
#define SNDFILE_1
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -105,6 +106,11 @@ enum
|
||||
|
||||
SF_FORMAT_VORBIS = 0x0060, /* Xiph Vorbis encoding. */
|
||||
|
||||
SF_FORMAT_ALAC_16 = 0x0070, /* Apple Lossless Audio Codec (16 bit). */
|
||||
SF_FORMAT_ALAC_20 = 0x0071, /* Apple Lossless Audio Codec (20 bit). */
|
||||
SF_FORMAT_ALAC_24 = 0x0072, /* Apple Lossless Audio Codec (24 bit). */
|
||||
SF_FORMAT_ALAC_32 = 0x0073, /* Apple Lossless Audio Codec (32 bit). */
|
||||
|
||||
/* Endian-ness options. */
|
||||
|
||||
SF_ENDIAN_FILE = 0x00000000, /* Default file endian-ness. */
|
||||
@@ -192,6 +198,11 @@ enum
|
||||
SFC_WAVEX_GET_AMBISONIC = 0x1201,
|
||||
|
||||
SFC_SET_VBR_ENCODING_QUALITY = 0x1300,
|
||||
SFC_SET_COMPRESSION_LEVEL = 0x1301,
|
||||
|
||||
/* Cart Chunk support */
|
||||
SFC_SET_CART_INFO = 0x1400,
|
||||
SFC_GET_CART_INFO = 0x1401,
|
||||
|
||||
/* Following commands for testing only. */
|
||||
SFC_TEST_IEEE_FLOAT_REPLACE = 0x6001,
|
||||
@@ -199,7 +210,7 @@ enum
|
||||
/*
|
||||
** SFC_SET_ADD_* values are deprecated and will disappear at some
|
||||
** time in the future. They are guaranteed to be here up to and
|
||||
** including version 1.0.8 to avoid breakage of existng software.
|
||||
** including version 1.0.8 to avoid breakage of existing software.
|
||||
** They currently do nothing and will continue to do nothing.
|
||||
*/
|
||||
SFC_SET_ADD_DITHER_ON_WRITE = 0x1070,
|
||||
@@ -221,7 +232,9 @@ enum
|
||||
SF_STR_COMMENT = 0x05,
|
||||
SF_STR_DATE = 0x06,
|
||||
SF_STR_ALBUM = 0x07,
|
||||
SF_STR_LICENSE = 0x08
|
||||
SF_STR_LICENSE = 0x08,
|
||||
SF_STR_TRACKNUMBER = 0x09,
|
||||
SF_STR_GENRE = 0x10
|
||||
} ;
|
||||
|
||||
/*
|
||||
@@ -230,7 +243,7 @@ enum
|
||||
*/
|
||||
|
||||
#define SF_STR_FIRST SF_STR_TITLE
|
||||
#define SF_STR_LAST SF_STR_LICENSE
|
||||
#define SF_STR_LAST SF_STR_GENRE
|
||||
|
||||
enum
|
||||
{ /* True and false */
|
||||
@@ -267,27 +280,34 @@ enum
|
||||
enum
|
||||
{ SF_CHANNEL_MAP_INVALID = 0,
|
||||
SF_CHANNEL_MAP_MONO = 1,
|
||||
SF_CHANNEL_MAP_LEFT,
|
||||
SF_CHANNEL_MAP_RIGHT,
|
||||
SF_CHANNEL_MAP_CENTER,
|
||||
SF_CHANNEL_MAP_LEFT, /* Apple calls this 'Left' */
|
||||
SF_CHANNEL_MAP_RIGHT, /* Apple calls this 'Right' */
|
||||
SF_CHANNEL_MAP_CENTER, /* Apple calls this 'Center' */
|
||||
SF_CHANNEL_MAP_FRONT_LEFT,
|
||||
SF_CHANNEL_MAP_FRONT_RIGHT,
|
||||
SF_CHANNEL_MAP_FRONT_CENTER,
|
||||
SF_CHANNEL_MAP_REAR_CENTER,
|
||||
SF_CHANNEL_MAP_REAR_LEFT,
|
||||
SF_CHANNEL_MAP_REAR_RIGHT,
|
||||
SF_CHANNEL_MAP_LFE,
|
||||
SF_CHANNEL_MAP_FRONT_LEFT_OF_CENTER,
|
||||
SF_CHANNEL_MAP_FRONT_RIGHT_OF_CENTER,
|
||||
SF_CHANNEL_MAP_SIDE_LEFT,
|
||||
SF_CHANNEL_MAP_SIDE_RIGHT,
|
||||
SF_CHANNEL_MAP_TOP_CENTER,
|
||||
SF_CHANNEL_MAP_TOP_FRONT_LEFT,
|
||||
SF_CHANNEL_MAP_TOP_FRONT_RIGHT,
|
||||
SF_CHANNEL_MAP_TOP_FRONT_CENTER,
|
||||
SF_CHANNEL_MAP_TOP_REAR_LEFT,
|
||||
SF_CHANNEL_MAP_TOP_REAR_RIGHT,
|
||||
SF_CHANNEL_MAP_TOP_REAR_CENTER
|
||||
SF_CHANNEL_MAP_REAR_CENTER, /* Apple calls this 'Center Surround', Msft calls this 'Back Center' */
|
||||
SF_CHANNEL_MAP_REAR_LEFT, /* Apple calls this 'Left Surround', Msft calls this 'Back Left' */
|
||||
SF_CHANNEL_MAP_REAR_RIGHT, /* Apple calls this 'Right Surround', Msft calls this 'Back Right' */
|
||||
SF_CHANNEL_MAP_LFE, /* Apple calls this 'LFEScreen', Msft calls this 'Low Frequency' */
|
||||
SF_CHANNEL_MAP_FRONT_LEFT_OF_CENTER, /* Apple calls this 'Left Center' */
|
||||
SF_CHANNEL_MAP_FRONT_RIGHT_OF_CENTER, /* Apple calls this 'Right Center */
|
||||
SF_CHANNEL_MAP_SIDE_LEFT, /* Apple calls this 'Left Surround Direct' */
|
||||
SF_CHANNEL_MAP_SIDE_RIGHT, /* Apple calls this 'Right Surround Direct' */
|
||||
SF_CHANNEL_MAP_TOP_CENTER, /* Apple calls this 'Top Center Surround' */
|
||||
SF_CHANNEL_MAP_TOP_FRONT_LEFT, /* Apple calls this 'Vertical Height Left' */
|
||||
SF_CHANNEL_MAP_TOP_FRONT_RIGHT, /* Apple calls this 'Vertical Height Right' */
|
||||
SF_CHANNEL_MAP_TOP_FRONT_CENTER, /* Apple calls this 'Vertical Height Center' */
|
||||
SF_CHANNEL_MAP_TOP_REAR_LEFT, /* Apple and MS call this 'Top Back Left' */
|
||||
SF_CHANNEL_MAP_TOP_REAR_RIGHT, /* Apple and MS call this 'Top Back Right' */
|
||||
SF_CHANNEL_MAP_TOP_REAR_CENTER, /* Apple and MS call this 'Top Back Center' */
|
||||
|
||||
SF_CHANNEL_MAP_AMBISONIC_B_W,
|
||||
SF_CHANNEL_MAP_AMBISONIC_B_X,
|
||||
SF_CHANNEL_MAP_AMBISONIC_B_Y,
|
||||
SF_CHANNEL_MAP_AMBISONIC_B_Z,
|
||||
|
||||
SF_CHANNEL_MAP_MAX
|
||||
} ;
|
||||
|
||||
|
||||
@@ -296,13 +316,14 @@ enum
|
||||
typedef struct SNDFILE_tag SNDFILE ;
|
||||
|
||||
/* The following typedef is system specific and is defined when libsndfile is
|
||||
** compiled. sf_count_t can be one of loff_t (Linux), off_t (*BSD), off64_t
|
||||
** (Solaris), __int64_t (Win32) etc. On windows, we need to allow the same
|
||||
** header file to be compiler by both GCC and the microsoft compiler.
|
||||
** compiled. sf_count_t will be a 64 bit value when the underlying OS allows
|
||||
** 64 bit file offsets.
|
||||
** On windows, we need to allow the same header file to be compiler by both GCC
|
||||
** and the Microsoft compiler.
|
||||
*/
|
||||
|
||||
#ifdef _MSCVER
|
||||
typedef __int64_t sf_count_t ;
|
||||
#if (defined (_MSCVER) || defined (_MSC_VER))
|
||||
typedef __int64 sf_count_t ;
|
||||
#define SF_COUNT_MAX 0x7fffffffffffffffi64
|
||||
#else
|
||||
typedef @TYPEOF_SF_COUNT_T@ sf_count_t ;
|
||||
@@ -310,9 +331,9 @@ typedef @TYPEOF_SF_COUNT_T@ sf_count_t ;
|
||||
#endif
|
||||
|
||||
|
||||
/* A pointer to a SF_INFO structure is passed to sf_open_read () and filled in.
|
||||
/* A pointer to a SF_INFO structure is passed to sf_open () and filled in.
|
||||
** On write, the SF_INFO structure is filled in by the user and passed into
|
||||
** sf_open_write ().
|
||||
** sf_open ().
|
||||
*/
|
||||
|
||||
struct SF_INFO
|
||||
@@ -396,9 +417,9 @@ typedef struct
|
||||
|
||||
struct
|
||||
{ int mode ;
|
||||
unsigned int start ;
|
||||
unsigned int end ;
|
||||
unsigned int count ;
|
||||
uint32_t start ;
|
||||
uint32_t end ;
|
||||
uint32_t count ;
|
||||
} loops [16] ; /* make variable in a sensible way */
|
||||
} SF_INSTRUMENT ;
|
||||
|
||||
@@ -416,7 +437,7 @@ typedef struct
|
||||
/* a full bar of 7/8 is 7 beats */
|
||||
|
||||
float bpm ; /* suggestion, as it can be calculated using other fields:*/
|
||||
/* file's lenght, file's sampleRate and our time_sig_den*/
|
||||
/* file's length, file's sampleRate and our time_sig_den*/
|
||||
/* -> bpms are always the amount of _quarter notes_ per minute */
|
||||
|
||||
int root_key ; /* MIDI note, or -1 for None */
|
||||
@@ -429,23 +450,56 @@ typedef struct
|
||||
*/
|
||||
#define SF_BROADCAST_INFO_VAR(coding_hist_size) \
|
||||
struct \
|
||||
{ char description [256] ; \
|
||||
char originator [32] ; \
|
||||
char originator_reference [32] ; \
|
||||
char origination_date [10] ; \
|
||||
char origination_time [8] ; \
|
||||
unsigned int time_reference_low ; \
|
||||
unsigned int time_reference_high ; \
|
||||
short version ; \
|
||||
char umid [64] ; \
|
||||
char reserved [190] ; \
|
||||
unsigned int coding_history_size ; \
|
||||
char coding_history [coding_hist_size] ; \
|
||||
{ char description [256] ; \
|
||||
char originator [32] ; \
|
||||
char originator_reference [32] ; \
|
||||
char origination_date [10] ; \
|
||||
char origination_time [8] ; \
|
||||
uint32_t time_reference_low ; \
|
||||
uint32_t time_reference_high ; \
|
||||
short version ; \
|
||||
char umid [64] ; \
|
||||
char reserved [190] ; \
|
||||
uint32_t coding_history_size ; \
|
||||
char coding_history [coding_hist_size] ; \
|
||||
}
|
||||
|
||||
/* SF_BROADCAST_INFO is the above struct with coding_history field of 256 bytes. */
|
||||
typedef SF_BROADCAST_INFO_VAR (256) SF_BROADCAST_INFO ;
|
||||
|
||||
struct SF_CART_TIMER
|
||||
{ char usage[4] ;
|
||||
int32_t value ;
|
||||
} ;
|
||||
|
||||
typedef struct SF_CART_TIMER SF_CART_TIMER ;
|
||||
|
||||
#define SF_CART_INFO_VAR(p_tag_text_size) \
|
||||
struct \
|
||||
{ char version [4] ; \
|
||||
char title [64] ; \
|
||||
char artist [64] ; \
|
||||
char cut_id [64] ; \
|
||||
char client_id [64] ; \
|
||||
char category [64] ; \
|
||||
char classification [64] ; \
|
||||
char out_cue [64] ; \
|
||||
char start_date [10] ; \
|
||||
char start_time [8] ; \
|
||||
char end_date [10] ; \
|
||||
char end_time [8] ; \
|
||||
char producer_app_id [64] ; \
|
||||
char producer_app_version [64] ; \
|
||||
char user_def [64] ; \
|
||||
int32_t level_reference ; \
|
||||
SF_CART_TIMER post_timers [8] ; \
|
||||
char reserved [276] ; \
|
||||
char url [1024] ; \
|
||||
uint32_t tag_text_size ; \
|
||||
char tag_text[p_tag_text_size] ; \
|
||||
}
|
||||
|
||||
typedef SF_CART_INFO_VAR (256) SF_CART_INFO ;
|
||||
|
||||
/* Virtual I/O functionality. */
|
||||
|
||||
@@ -465,6 +519,7 @@ struct SF_VIRTUAL_IO
|
||||
|
||||
typedef struct SF_VIRTUAL_IO SF_VIRTUAL_IO ;
|
||||
|
||||
|
||||
/* Open the specified file for read, write or both. On error, this will
|
||||
** return a NULL pointer. To find the error number, pass a NULL SNDFILE
|
||||
** to sf_strerror ().
|
||||
@@ -473,9 +528,10 @@ typedef struct SF_VIRTUAL_IO SF_VIRTUAL_IO ;
|
||||
|
||||
SNDFILE* sf_open (const char *path, int mode, SF_INFO *sfinfo) ;
|
||||
|
||||
|
||||
/* Use the existing file descriptor to create a SNDFILE object. If close_desc
|
||||
** is TRUE, the file descriptor will be closed when sf_close() is called. If
|
||||
** it is FALSE, the descritor will not be closed.
|
||||
** it is FALSE, the descriptor will not be closed.
|
||||
** When passed a descriptor like this, the library will assume that the start
|
||||
** of file header is at the current file offset. This allows sound files within
|
||||
** larger container files to be read and/or written.
|
||||
@@ -489,18 +545,21 @@ SNDFILE* sf_open_fd (int fd, int mode, SF_INFO *sfinfo, int close_desc) ;
|
||||
|
||||
SNDFILE* sf_open_virtual (SF_VIRTUAL_IO *sfvirtual, int mode, SF_INFO *sfinfo, void *user_data) ;
|
||||
|
||||
|
||||
/* sf_error () returns a error number which can be translated to a text
|
||||
** string using sf_error_number().
|
||||
*/
|
||||
|
||||
int sf_error (SNDFILE *sndfile) ;
|
||||
|
||||
|
||||
/* sf_strerror () returns to the caller a pointer to the current error message for
|
||||
** the given SNDFILE.
|
||||
*/
|
||||
|
||||
const char* sf_strerror (SNDFILE *sndfile) ;
|
||||
|
||||
|
||||
/* sf_error_number () allows the retrieval of the error string for each internal
|
||||
** error number.
|
||||
**
|
||||
@@ -508,8 +567,9 @@ const char* sf_strerror (SNDFILE *sndfile) ;
|
||||
|
||||
const char* sf_error_number (int errnum) ;
|
||||
|
||||
|
||||
/* The following two error functions are deprecated but they will remain in the
|
||||
** library for the forseeable future. The function sf_strerror() should be used
|
||||
** library for the foreseeable future. The function sf_strerror() should be used
|
||||
** in their place.
|
||||
*/
|
||||
|
||||
@@ -521,10 +581,12 @@ int sf_error_str (SNDFILE *sndfile, char* str, size_t len) ;
|
||||
|
||||
int sf_command (SNDFILE *sndfile, int command, void *data, int datasize) ;
|
||||
|
||||
|
||||
/* Return TRUE if fields of the SF_INFO struct are a valid combination of values. */
|
||||
|
||||
int sf_format_check (const SF_INFO *info) ;
|
||||
|
||||
|
||||
/* Seek within the waveform data chunk of the SNDFILE. sf_seek () uses
|
||||
** the same values for whence (SEEK_SET, SEEK_CUR and SEEK_END) as
|
||||
** stdio.h function fseek ().
|
||||
@@ -537,8 +599,15 @@ int sf_format_check (const SF_INFO *info) ;
|
||||
** On error all of these functions return -1.
|
||||
*/
|
||||
|
||||
enum
|
||||
{ SF_SEEK_SET = SEEK_SET,
|
||||
SF_SEEK_CUR = SEEK_CUR,
|
||||
SF_SEEK_END = SEEK_END
|
||||
} ;
|
||||
|
||||
sf_count_t sf_seek (SNDFILE *sndfile, sf_count_t frames, int whence) ;
|
||||
|
||||
|
||||
/* Functions for retrieving and setting string data within sound files.
|
||||
** Not all file types support this features; AIFF and WAV do. For both
|
||||
** functions, the str_type parameter must be one of the SF_STR_* values
|
||||
@@ -551,12 +620,31 @@ int sf_set_string (SNDFILE *sndfile, int str_type, const char* str) ;
|
||||
|
||||
const char* sf_get_string (SNDFILE *sndfile, int str_type) ;
|
||||
|
||||
|
||||
/* Return the library version string. */
|
||||
|
||||
const char * sf_version_string (void) ;
|
||||
|
||||
/* Return the current byterate at this point in the file. The byte rate in this
|
||||
** case is the number of bytes per second of audio data. For instance, for a
|
||||
** stereo, 18 bit PCM encoded file with an 16kHz sample rate, the byte rate
|
||||
** would be 2 (stereo) * 2 (two bytes per sample) * 16000 => 64000 bytes/sec.
|
||||
** For some file formats the returned value will be accurate and exact, for some
|
||||
** it will be a close approximation, for some it will be the average bitrate for
|
||||
** the whole file and for some it will be a time varying value that was accurate
|
||||
** when the file was most recently read or written.
|
||||
** To get the bitrate, multiple this value by 8.
|
||||
** Returns -1 for unknown.
|
||||
*/
|
||||
int sf_current_byterate (SNDFILE *sndfile) ;
|
||||
|
||||
/* Functions for reading/writing the waveform data of a sound file.
|
||||
*/
|
||||
|
||||
sf_count_t sf_read_raw (SNDFILE *sndfile, void *ptr, sf_count_t bytes) ;
|
||||
sf_count_t sf_write_raw (SNDFILE *sndfile, const void *ptr, sf_count_t bytes) ;
|
||||
|
||||
|
||||
/* Functions for reading and writing the data chunk in terms of frames.
|
||||
** The number of items actually read/written = frames * number of channels.
|
||||
** sf_xxxx_raw read/writes the raw data bytes from/to the file
|
||||
@@ -579,6 +667,7 @@ sf_count_t sf_writef_float (SNDFILE *sndfile, const float *ptr, sf_count_t frame
|
||||
sf_count_t sf_readf_double (SNDFILE *sndfile, double *ptr, sf_count_t frames) ;
|
||||
sf_count_t sf_writef_double (SNDFILE *sndfile, const double *ptr, sf_count_t frames) ;
|
||||
|
||||
|
||||
/* Functions for reading and writing the data chunk in terms of items.
|
||||
** Otherwise similar to above.
|
||||
** All of these read/write function return number of items read/written.
|
||||
@@ -596,6 +685,7 @@ sf_count_t sf_write_float (SNDFILE *sndfile, const float *ptr, sf_count_t items)
|
||||
sf_count_t sf_read_double (SNDFILE *sndfile, double *ptr, sf_count_t items) ;
|
||||
sf_count_t sf_write_double (SNDFILE *sndfile, const double *ptr, sf_count_t items) ;
|
||||
|
||||
|
||||
/* Close the SNDFILE and clean up all memory allocations associated with this
|
||||
** file.
|
||||
** Returns 0 on success, or an error number.
|
||||
@@ -603,6 +693,7 @@ sf_count_t sf_write_double (SNDFILE *sndfile, const double *ptr, sf_count_t item
|
||||
|
||||
int sf_close (SNDFILE *sndfile) ;
|
||||
|
||||
|
||||
/* If the file is opened SFM_WRITE or SFM_RDWR, call fsync() on the file
|
||||
** to force the writing of data to disk. If the file is opened SFM_READ
|
||||
** no action is taken.
|
||||
@@ -610,8 +701,124 @@ int sf_close (SNDFILE *sndfile) ;
|
||||
|
||||
void sf_write_sync (SNDFILE *sndfile) ;
|
||||
|
||||
|
||||
|
||||
/* The function sf_wchar_open() is Windows Only!
|
||||
** Open a file passing in a Windows Unicode filename. Otherwise, this is
|
||||
** the same as sf_open().
|
||||
**
|
||||
** In order for this to work, you need to do the following:
|
||||
**
|
||||
** #include <windows.h>
|
||||
** #define ENABLE_SNDFILE_WINDOWS_PROTOTYPES 1
|
||||
** #including <sndfile.h>
|
||||
*/
|
||||
|
||||
#if (defined (ENABLE_SNDFILE_WINDOWS_PROTOTYPES) && ENABLE_SNDFILE_WINDOWS_PROTOTYPES)
|
||||
SNDFILE* sf_wchar_open (LPCWSTR wpath, int mode, SF_INFO *sfinfo) ;
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
/* Getting and setting of chunks from within a sound file.
|
||||
**
|
||||
** These functions allow the getting and setting of chunks within a sound file
|
||||
** (for those formats which allow it).
|
||||
**
|
||||
** These functions fail safely. Specifically, they will not allow you to overwrite
|
||||
** existing chunks or add extra versions of format specific reserved chunks but
|
||||
** should allow you to retrieve any and all chunks (may not be implemented for
|
||||
** all chunks or all file formats).
|
||||
*/
|
||||
|
||||
struct SF_CHUNK_INFO
|
||||
{ char id [64] ; /* The chunk identifier. */
|
||||
unsigned id_size ; /* The size of the chunk identifier. */
|
||||
unsigned datalen ; /* The size of that data. */
|
||||
void *data ; /* Pointer to the data. */
|
||||
} ;
|
||||
|
||||
typedef struct SF_CHUNK_INFO SF_CHUNK_INFO ;
|
||||
|
||||
/* Set the specified chunk info (must be done before any audio data is written
|
||||
** to the file). This will fail for format specific reserved chunks.
|
||||
** The chunk_info->data pointer must be valid until the file is closed.
|
||||
** Returns SF_ERR_NO_ERROR on success or non-zero on failure.
|
||||
*/
|
||||
int sf_set_chunk (SNDFILE * sndfile, const SF_CHUNK_INFO * chunk_info) ;
|
||||
|
||||
/*
|
||||
** An opaque structure to an iterator over the all chunks of a given id
|
||||
*/
|
||||
typedef struct SF_CHUNK_ITERATOR SF_CHUNK_ITERATOR ;
|
||||
|
||||
/* Get an iterator for all chunks matching chunk_info.
|
||||
** The iterator will point to the first chunk matching chunk_info.
|
||||
** Chunks are matching, if (chunk_info->id) matches the first
|
||||
** (chunk_info->id_size) bytes of a chunk found in the SNDFILE* handle.
|
||||
** If chunk_info is NULL, an iterator to all chunks in the SNDFILE* handle
|
||||
** is returned.
|
||||
** The values of chunk_info->datalen and chunk_info->data are ignored.
|
||||
** If no matching chunks are found in the sndfile, NULL is returned.
|
||||
** The returned iterator will stay valid until one of the following occurs:
|
||||
** a) The sndfile is closed.
|
||||
** b) A new chunk is added using sf_set_chunk().
|
||||
** c) Another chunk iterator function is called on the same SNDFILE* handle
|
||||
** that causes the iterator to be modified.
|
||||
** The memory for the iterator belongs to the SNDFILE* handle and is freed when
|
||||
** sf_close() is called.
|
||||
*/
|
||||
SF_CHUNK_ITERATOR *
|
||||
sf_get_chunk_iterator (SNDFILE * sndfile, const SF_CHUNK_INFO * chunk_info) ;
|
||||
|
||||
/* Iterate through chunks by incrementing the iterator.
|
||||
** Increments the iterator and returns a handle to the new one.
|
||||
** After this call, iterator will no longer be valid, and you must use the
|
||||
** newly returned handle from now on.
|
||||
** The returned handle can be used to access the next chunk matching
|
||||
** the criteria as defined in sf_get_chunk_iterator().
|
||||
** If iterator points to the last chunk, this will free all resources
|
||||
** associated with iterator and return NULL.
|
||||
** The returned iterator will stay valid until sf_get_chunk_iterator_next
|
||||
** is called again, the sndfile is closed or a new chunk us added.
|
||||
*/
|
||||
SF_CHUNK_ITERATOR *
|
||||
sf_next_chunk_iterator (SF_CHUNK_ITERATOR * iterator) ;
|
||||
|
||||
|
||||
/* Get the size of the specified chunk.
|
||||
** If the specified chunk exists, the size will be returned in the
|
||||
** datalen field of the SF_CHUNK_INFO struct.
|
||||
** Additionally, the id of the chunk will be copied to the id
|
||||
** field of the SF_CHUNK_INFO struct and it's id_size field will
|
||||
** be updated accordingly.
|
||||
** If the chunk doesn't exist chunk_info->datalen will be zero, and the
|
||||
** id and id_size fields will be undefined.
|
||||
** The function will return SF_ERR_NO_ERROR on success or non-zero on
|
||||
** failure.
|
||||
*/
|
||||
int
|
||||
sf_get_chunk_size (const SF_CHUNK_ITERATOR * it, SF_CHUNK_INFO * chunk_info) ;
|
||||
|
||||
/* Get the specified chunk data.
|
||||
** If the specified chunk exists, up to chunk_info->datalen bytes of
|
||||
** the chunk data will be copied into the chunk_info->data buffer
|
||||
** (allocated by the caller) and the chunk_info->datalen field
|
||||
** updated to reflect the size of the data. The id and id_size
|
||||
** field will be updated according to the retrieved chunk
|
||||
** If the chunk doesn't exist chunk_info->datalen will be zero, and the
|
||||
** id and id_size fields will be undefined.
|
||||
** The function will return SF_ERR_NO_ERROR on success or non-zero on
|
||||
** failure.
|
||||
*/
|
||||
int
|
||||
sf_get_chunk_data (const SF_CHUNK_ITERATOR * it, SF_CHUNK_INFO * chunk_info) ;
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* SNDFILE_H */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** Copyright (C) 2005-2007 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
** Copyright (C) 2005-2012 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** All rights reserved.
|
||||
**
|
||||
@@ -77,6 +77,16 @@ class SndfileHandle
|
||||
int format = 0, int channels = 0, int samplerate = 0) ;
|
||||
SndfileHandle (std::string const & path, int mode = SFM_READ,
|
||||
int format = 0, int channels = 0, int samplerate = 0) ;
|
||||
SndfileHandle (int fd, bool close_desc, int mode = SFM_READ,
|
||||
int format = 0, int channels = 0, int samplerate = 0) ;
|
||||
SndfileHandle (SF_VIRTUAL_IO &sfvirtual, void *user_data, int mode = SFM_READ,
|
||||
int format = 0, int channels = 0, int samplerate = 0) ;
|
||||
|
||||
#ifdef ENABLE_SNDFILE_WINDOWS_PROTOTYPES
|
||||
SndfileHandle (LPCWSTR wpath, int mode = SFM_READ,
|
||||
int format = 0, int channels = 0, int samplerate = 0) ;
|
||||
#endif
|
||||
|
||||
~SndfileHandle (void) ;
|
||||
|
||||
SndfileHandle (const SndfileHandle &orig) ;
|
||||
@@ -132,6 +142,11 @@ class SndfileHandle
|
||||
sf_count_t readRaw (void *ptr, sf_count_t bytes) ;
|
||||
sf_count_t writeRaw (const void *ptr, sf_count_t bytes) ;
|
||||
|
||||
/**< Raw access to the handle. SndfileHandle keeps ownership. */
|
||||
SNDFILE * rawHandle (void) ;
|
||||
|
||||
/**< Take ownership of handle, if reference count is 1. */
|
||||
SNDFILE * takeOwnership (void) ;
|
||||
} ;
|
||||
|
||||
/*==============================================================================
|
||||
@@ -191,6 +206,53 @@ SndfileHandle::SndfileHandle (std::string const & path, int mode, int fmt, int c
|
||||
return ;
|
||||
} /* SndfileHandle std::string constructor */
|
||||
|
||||
inline
|
||||
SndfileHandle::SndfileHandle (int fd, bool close_desc, int mode, int fmt, int chans, int srate)
|
||||
: p (NULL)
|
||||
{
|
||||
if (fd < 0)
|
||||
return ;
|
||||
|
||||
p = new (std::nothrow) SNDFILE_ref () ;
|
||||
|
||||
if (p != NULL)
|
||||
{ p->ref = 1 ;
|
||||
|
||||
p->sfinfo.frames = 0 ;
|
||||
p->sfinfo.channels = chans ;
|
||||
p->sfinfo.format = fmt ;
|
||||
p->sfinfo.samplerate = srate ;
|
||||
p->sfinfo.sections = 0 ;
|
||||
p->sfinfo.seekable = 0 ;
|
||||
|
||||
p->sf = sf_open_fd (fd, mode, &p->sfinfo, close_desc) ;
|
||||
} ;
|
||||
|
||||
return ;
|
||||
} /* SndfileHandle fd constructor */
|
||||
|
||||
inline
|
||||
SndfileHandle::SndfileHandle (SF_VIRTUAL_IO &sfvirtual, void *user_data, int mode, int fmt, int chans, int srate)
|
||||
: p (NULL)
|
||||
{
|
||||
p = new (std::nothrow) SNDFILE_ref () ;
|
||||
|
||||
if (p != NULL)
|
||||
{ p->ref = 1 ;
|
||||
|
||||
p->sfinfo.frames = 0 ;
|
||||
p->sfinfo.channels = chans ;
|
||||
p->sfinfo.format = fmt ;
|
||||
p->sfinfo.samplerate = srate ;
|
||||
p->sfinfo.sections = 0 ;
|
||||
p->sfinfo.seekable = 0 ;
|
||||
|
||||
p->sf = sf_open_virtual (&sfvirtual, mode, &p->sfinfo, user_data) ;
|
||||
} ;
|
||||
|
||||
return ;
|
||||
} /* SndfileHandle std::string constructor */
|
||||
|
||||
inline
|
||||
SndfileHandle::~SndfileHandle (void)
|
||||
{ if (p != NULL && --p->ref == 0)
|
||||
@@ -249,7 +311,7 @@ SndfileHandle::getString (int str_type) const
|
||||
{ return sf_get_string (p->sf, str_type) ; }
|
||||
|
||||
inline int
|
||||
SndfileHandle::formatCheck(int fmt, int chans, int srate)
|
||||
SndfileHandle::formatCheck (int fmt, int chans, int srate)
|
||||
{
|
||||
SF_INFO sfinfo ;
|
||||
|
||||
@@ -337,6 +399,48 @@ inline sf_count_t
|
||||
SndfileHandle::writeRaw (const void *ptr, sf_count_t bytes)
|
||||
{ return sf_write_raw (p->sf, ptr, bytes) ; }
|
||||
|
||||
inline SNDFILE *
|
||||
SndfileHandle::rawHandle (void)
|
||||
{ return (p ? p->sf : NULL) ; }
|
||||
|
||||
inline SNDFILE *
|
||||
SndfileHandle::takeOwnership (void)
|
||||
{
|
||||
if (p == NULL || (p->ref != 1))
|
||||
return NULL ;
|
||||
|
||||
SNDFILE * sf = p->sf ;
|
||||
p->sf = NULL ;
|
||||
delete p ;
|
||||
p = NULL ;
|
||||
return sf ;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_SNDFILE_WINDOWS_PROTOTYPES
|
||||
|
||||
inline
|
||||
SndfileHandle::SndfileHandle (LPCWSTR wpath, int mode, int fmt, int chans, int srate)
|
||||
: p (NULL)
|
||||
{
|
||||
p = new (std::nothrow) SNDFILE_ref () ;
|
||||
|
||||
if (p != NULL)
|
||||
{ p->ref = 1 ;
|
||||
|
||||
p->sfinfo.frames = 0 ;
|
||||
p->sfinfo.channels = chans ;
|
||||
p->sfinfo.format = fmt ;
|
||||
p->sfinfo.samplerate = srate ;
|
||||
p->sfinfo.sections = 0 ;
|
||||
p->sfinfo.seekable = 0 ;
|
||||
|
||||
p->sf = sf_wchar_open (wpath, mode, &p->sfinfo) ;
|
||||
} ;
|
||||
|
||||
return ;
|
||||
} /* SndfileHandle const wchar_t * constructor */
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* SNDFILE_HH */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** Copyright (C) 2001-2009 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
** Copyright (C) 2001-2012 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
@@ -32,9 +32,9 @@ static void hexdump (void *data, int len) ;
|
||||
|
||||
int
|
||||
psf_store_string (SF_PRIVATE *psf, int str_type, const char *str)
|
||||
{ static char lsf_name [] = PACKAGE "-" VERSION ;
|
||||
static char bracket_name [] = " (" PACKAGE "-" VERSION ")" ;
|
||||
int k, str_len, len_remaining, str_flags, str_type_replace = 0 ;
|
||||
{ char new_str [128] ;
|
||||
size_t str_len ;
|
||||
int k, str_flags ;
|
||||
|
||||
if (str == NULL)
|
||||
return SFE_STR_BAD_STRING ;
|
||||
@@ -42,10 +42,10 @@ psf_store_string (SF_PRIVATE *psf, int str_type, const char *str)
|
||||
str_len = strlen (str) ;
|
||||
|
||||
/* A few extra checks for write mode. */
|
||||
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
|
||||
{ if ((psf->str_flags & SF_STR_ALLOW_START) == 0)
|
||||
if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
|
||||
{ if ((psf->strings.flags & SF_STR_ALLOW_START) == 0)
|
||||
return SFE_STR_NO_SUPPORT ;
|
||||
if (psf->have_written && (psf->str_flags & SF_STR_ALLOW_END) == 0)
|
||||
if (psf->have_written && (psf->strings.flags & SF_STR_ALLOW_END) == 0)
|
||||
return SFE_STR_NO_SUPPORT ;
|
||||
/* Only allow zero length strings for software. */
|
||||
if (str_type != SF_STR_SOFTWARE && str_len == 0)
|
||||
@@ -55,17 +55,17 @@ psf_store_string (SF_PRIVATE *psf, int str_type, const char *str)
|
||||
/* Find the next free slot in table. */
|
||||
for (k = 0 ; k < SF_MAX_STRINGS ; k++)
|
||||
{ /* If we find a matching entry clear it. */
|
||||
if (psf->strings [k].type == str_type)
|
||||
psf->strings [k].type = -1 ;
|
||||
if (psf->strings.data [k].type == str_type)
|
||||
psf->strings.data [k].type = -1 ;
|
||||
|
||||
if (psf->strings [k].type == 0)
|
||||
if (psf->strings.data [k].type == 0)
|
||||
break ;
|
||||
} ;
|
||||
|
||||
/* Determine flags */
|
||||
str_flags = SF_STR_LOCATE_START ;
|
||||
if (psf->mode == SFM_RDWR || psf->have_written || str_type_replace)
|
||||
{ if ((psf->str_flags & SF_STR_ALLOW_END) == 0)
|
||||
if (psf->file.mode == SFM_RDWR || psf->have_written)
|
||||
{ if ((psf->strings.flags & SF_STR_ALLOW_END) == 0)
|
||||
return SFE_STR_NO_ADD_END ;
|
||||
str_flags = SF_STR_LOCATE_END ;
|
||||
} ;
|
||||
@@ -74,54 +74,40 @@ psf_store_string (SF_PRIVATE *psf, int str_type, const char *str)
|
||||
if (k >= SF_MAX_STRINGS)
|
||||
return SFE_STR_MAX_COUNT ;
|
||||
|
||||
if (k == 0 && psf->str_end != NULL)
|
||||
{ psf_log_printf (psf, "SFE_STR_WEIRD : k == 0 && psf->str_end != NULL\n") ;
|
||||
if (k == 0 && psf->strings.storage_used != 0)
|
||||
{ psf_log_printf (psf, "SFE_STR_WEIRD : k == 0 && psf->strings.storage_used != 0\n") ;
|
||||
return SFE_STR_WEIRD ;
|
||||
} ;
|
||||
|
||||
if (k != 0 && psf->str_end == NULL)
|
||||
{ psf_log_printf (psf, "SFE_STR_WEIRD : k != 0 && psf->str_end == NULL\n") ;
|
||||
if (k != 0 && psf->strings.storage_used == 0)
|
||||
{ psf_log_printf (psf, "SFE_STR_WEIRD : k != 0 && psf->strings.storage_used == 0\n") ;
|
||||
return SFE_STR_WEIRD ;
|
||||
} ;
|
||||
|
||||
/* Special case for the first string. */
|
||||
if (k == 0)
|
||||
psf->str_end = psf->str_storage ;
|
||||
|
||||
len_remaining = SIGNED_SIZEOF (psf->str_storage) - (psf->str_end - psf->str_storage) ;
|
||||
|
||||
if (len_remaining < str_len + 2)
|
||||
return SFE_STR_MAX_DATA ;
|
||||
psf->strings.storage_used = 0 ;
|
||||
|
||||
switch (str_type)
|
||||
{ case SF_STR_SOFTWARE :
|
||||
/* In write mode, want to append libsndfile-version to string. */
|
||||
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
|
||||
{ psf->strings [k].type = str_type ;
|
||||
psf->strings [k].str = psf->str_end ;
|
||||
psf->strings [k].flags = str_flags ;
|
||||
|
||||
memcpy (psf->str_end, str, str_len + 1) ;
|
||||
psf->str_end += str_len ;
|
||||
|
||||
/*
|
||||
** If the supplied string does not already contain a
|
||||
** libsndfile-X.Y.Z component, then add it.
|
||||
*/
|
||||
if (strstr (str, PACKAGE) == NULL && len_remaining > (int) (strlen (bracket_name) + str_len + 2))
|
||||
{ if (strlen (str) == 0)
|
||||
strncat (psf->str_end, lsf_name, len_remaining) ;
|
||||
if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
|
||||
{ if (strstr (str, PACKAGE) == NULL)
|
||||
{ /*
|
||||
** If the supplied string does not already contain a
|
||||
** libsndfile-X.Y.Z component, then add it.
|
||||
*/
|
||||
if (strlen (str) == 0)
|
||||
snprintf (new_str, sizeof (new_str), "%s-%s", PACKAGE, VERSION) ;
|
||||
else
|
||||
strncat (psf->str_end, bracket_name, len_remaining) ;
|
||||
psf->str_end += strlen (psf->str_end) ;
|
||||
} ;
|
||||
snprintf (new_str, sizeof (new_str), "%s (%s-%s)", str, PACKAGE, VERSION) ;
|
||||
}
|
||||
else
|
||||
snprintf (new_str, sizeof (new_str), "%s", str) ;
|
||||
|
||||
/* Plus one to catch string terminator. */
|
||||
psf->str_end += 1 ;
|
||||
break ;
|
||||
str = new_str ;
|
||||
} ;
|
||||
|
||||
/* Fall though if not write mode. */
|
||||
break ;
|
||||
|
||||
case SF_STR_TITLE :
|
||||
case SF_STR_COPYRIGHT :
|
||||
@@ -130,13 +116,8 @@ psf_store_string (SF_PRIVATE *psf, int str_type, const char *str)
|
||||
case SF_STR_DATE :
|
||||
case SF_STR_ALBUM :
|
||||
case SF_STR_LICENSE :
|
||||
psf->strings [k].type = str_type ;
|
||||
psf->strings [k].str = psf->str_end ;
|
||||
psf->strings [k].flags = str_flags ;
|
||||
|
||||
/* Plus one to catch string terminator. */
|
||||
memcpy (psf->str_end, str, str_len + 1) ;
|
||||
psf->str_end += str_len + 1 ;
|
||||
case SF_STR_TRACKNUMBER :
|
||||
case SF_STR_GENRE :
|
||||
break ;
|
||||
|
||||
default :
|
||||
@@ -144,16 +125,39 @@ psf_store_string (SF_PRIVATE *psf, int str_type, const char *str)
|
||||
return SFE_STR_BAD_TYPE ;
|
||||
} ;
|
||||
|
||||
psf->str_flags |= str_flags ;
|
||||
/* Plus one to catch string terminator. */
|
||||
str_len = strlen (str) + 1 ;
|
||||
|
||||
if (psf->strings.storage_used + str_len + 1 > psf->strings.storage_len)
|
||||
{ char * temp = psf->strings.storage ;
|
||||
size_t newlen = 2 * psf->strings.storage_len + str_len + 1 ;
|
||||
|
||||
newlen = newlen < 256 ? 256 : newlen ;
|
||||
|
||||
if ((psf->strings.storage = realloc (temp, newlen)) == NULL)
|
||||
{ psf->strings.storage = temp ;
|
||||
return SFE_MALLOC_FAILED ;
|
||||
} ;
|
||||
|
||||
psf->strings.storage_len = newlen ;
|
||||
} ;
|
||||
|
||||
psf->strings.data [k].type = str_type ;
|
||||
psf->strings.data [k].offset = psf->strings.storage_used ;
|
||||
psf->strings.data [k].flags = str_flags ;
|
||||
|
||||
memcpy (psf->strings.storage + psf->strings.storage_used, str, str_len) ;
|
||||
psf->strings.storage_used += str_len ;
|
||||
|
||||
psf->strings.flags |= str_flags ;
|
||||
|
||||
#if STRINGS_DEBUG
|
||||
psf_log_printf (psf, "str_storage : %X\n", (int) psf->str_storage) ;
|
||||
psf_log_printf (psf, "str_end : %X\n", (int) psf->str_end) ;
|
||||
psf_log_printf (psf, "sizeof (str_storage) : %d\n", SIGNED_SIZEOF (psf->str_storage)) ;
|
||||
psf_log_printf (psf, "used : %d\n", (int ) (psf->str_end - psf->str_storage)) ;
|
||||
psf_log_printf (psf, "remaining : %d\n", SIGNED_SIZEOF (psf->str_storage) - (psf->str_end - psf->str_storage)) ;
|
||||
psf_log_printf (psf, "str_storage : %p\n", psf->strings.storage) ;
|
||||
psf_log_printf (psf, "storage_used : %u\n", psf->strings.storage_used) ;
|
||||
psf_log_printf (psf, "used : %d\n", psf->strings.storage_used) ;
|
||||
psf_log_printf (psf, "remaining : %d\n", psf->strings.storage_len - psf->strings.storage_used ;
|
||||
|
||||
hexdump (psf->str_storage, 300) ;
|
||||
hexdump (psf->strings.storage, 300) ;
|
||||
#endif
|
||||
|
||||
return 0 ;
|
||||
@@ -161,7 +165,7 @@ psf_store_string (SF_PRIVATE *psf, int str_type, const char *str)
|
||||
|
||||
int
|
||||
psf_set_string (SF_PRIVATE *psf, int str_type, const char *str)
|
||||
{ if (psf->mode == SFM_READ)
|
||||
{ if (psf->file.mode == SFM_READ)
|
||||
return SFE_STR_NOT_WRITE ;
|
||||
|
||||
return psf_store_string (psf, str_type, str) ;
|
||||
@@ -172,8 +176,8 @@ psf_get_string (SF_PRIVATE *psf, int str_type)
|
||||
{ int k ;
|
||||
|
||||
for (k = 0 ; k < SF_MAX_STRINGS ; k++)
|
||||
if (str_type == psf->strings [k].type)
|
||||
return psf->strings [k].str ;
|
||||
if (str_type == psf->strings.data [k].type)
|
||||
return psf->strings.storage + psf->strings.data [k].offset ;
|
||||
|
||||
return NULL ;
|
||||
} /* psf_get_string */
|
||||
@@ -183,7 +187,7 @@ psf_location_string_count (const SF_PRIVATE * psf, int location)
|
||||
{ int k, count = 0 ;
|
||||
|
||||
for (k = 0 ; k < SF_MAX_STRINGS ; k++)
|
||||
if (psf->strings [k].type > 0 && psf->strings [k].flags & location)
|
||||
if (psf->strings.data [k].type > 0 && psf->strings.data [k].flags & location)
|
||||
count ++ ;
|
||||
|
||||
return count ;
|
||||
@@ -208,7 +212,7 @@ hexdump (void *data, int len)
|
||||
printf ("%02X ", ptr [k] & 0xFF) ;
|
||||
printf (" ") ;
|
||||
for (k = 0 ; k < 16 ; k++)
|
||||
printf ("%c", isprint (ptr [k]) ? ptr [k] : '.') ;
|
||||
printf ("%c", psf_isprint (ptr [k]) ? ptr [k] : '.') ;
|
||||
puts ("") ;
|
||||
ptr += 16 ;
|
||||
len -= 16 ;
|
||||
|
||||
+23
-14
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** Copyright (C) 1999-2009 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
** Copyright (C) 1999-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
@@ -82,7 +82,7 @@ int
|
||||
svx_open (SF_PRIVATE *psf)
|
||||
{ int error ;
|
||||
|
||||
if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->filelength > 0))
|
||||
if (psf->file.mode == SFM_READ || (psf->file.mode == SFM_RDWR && psf->filelength > 0))
|
||||
{ if ((error = svx_read_header (psf)))
|
||||
return error ;
|
||||
|
||||
@@ -95,7 +95,7 @@ svx_open (SF_PRIVATE *psf)
|
||||
psf_fseek (psf, psf->dataoffset, SEEK_SET) ;
|
||||
} ;
|
||||
|
||||
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
|
||||
if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
|
||||
{ if (psf->is_pipe)
|
||||
return SFE_NO_PIPE_WRITE ;
|
||||
|
||||
@@ -140,7 +140,7 @@ svx_read_header (SF_PRIVATE *psf)
|
||||
memset (&vhdr, 0, sizeof (vhdr)) ;
|
||||
psf_binheader_readf (psf, "p", 0) ;
|
||||
|
||||
/* Set default number of channels. Currently can't handle stereo SVX files. */
|
||||
/* Set default number of channels. Modify later if necessary */
|
||||
psf->sf.channels = 1 ;
|
||||
|
||||
psf->sf.format = SF_FORMAT_SVX ;
|
||||
@@ -252,12 +252,12 @@ svx_read_header (SF_PRIVATE *psf)
|
||||
|
||||
psf_log_printf (psf, " %M : %d\n", marker, dword) ;
|
||||
|
||||
if (strlen (psf->filename) != dword)
|
||||
{ if (dword > sizeof (psf->filename) - 1)
|
||||
if (strlen (psf->file.name.c) != dword)
|
||||
{ if (dword > sizeof (psf->file.name.c) - 1)
|
||||
return SFE_SVX_BAD_NAME_LENGTH ;
|
||||
|
||||
psf_binheader_readf (psf, "b", psf->filename, dword) ;
|
||||
psf->filename [dword] = 0 ;
|
||||
psf_binheader_readf (psf, "b", psf->file.name.c, dword) ;
|
||||
psf->file.name.c [dword] = 0 ;
|
||||
}
|
||||
else
|
||||
psf_binheader_readf (psf, "j", dword) ;
|
||||
@@ -283,9 +283,15 @@ svx_read_header (SF_PRIVATE *psf)
|
||||
psf_log_printf (psf, " %M : %d\n", marker, dword) ;
|
||||
|
||||
bytecount += psf_binheader_readf (psf, "E4", &channels) ;
|
||||
psf->sf.channels = channels ;
|
||||
|
||||
psf_log_printf (psf, " Channels : %d\n", channels) ;
|
||||
if (channels == 2 || channels == 4)
|
||||
psf_log_printf (psf, " Channels : %d => mono\n", channels) ;
|
||||
else if (channels == 6)
|
||||
{ psf->sf.channels = 2 ;
|
||||
psf_log_printf (psf, " Channels : %d => stereo\n", channels) ;
|
||||
}
|
||||
else
|
||||
psf_log_printf (psf, " Channels : %d *** assuming mono\n", channels) ;
|
||||
|
||||
psf_binheader_readf (psf, "j", dword - bytecount) ;
|
||||
break ;
|
||||
@@ -304,8 +310,8 @@ svx_read_header (SF_PRIVATE *psf)
|
||||
break ;
|
||||
|
||||
default :
|
||||
if (isprint ((marker >> 24) & 0xFF) && isprint ((marker >> 16) & 0xFF)
|
||||
&& isprint ((marker >> 8) & 0xFF) && isprint (marker & 0xFF))
|
||||
if (psf_isprint ((marker >> 24) & 0xFF) && psf_isprint ((marker >> 16) & 0xFF)
|
||||
&& psf_isprint ((marker >> 8) & 0xFF) && psf_isprint (marker & 0xFF))
|
||||
{ psf_binheader_readf (psf, "E4", &dword) ;
|
||||
|
||||
psf_log_printf (psf, "%M : %d (unknown marker)\n", marker, dword) ;
|
||||
@@ -342,7 +348,7 @@ svx_read_header (SF_PRIVATE *psf)
|
||||
static int
|
||||
svx_close (SF_PRIVATE *psf)
|
||||
{
|
||||
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
|
||||
if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
|
||||
svx_write_header (psf, SF_TRUE) ;
|
||||
|
||||
return 0 ;
|
||||
@@ -385,8 +391,11 @@ svx_write_header (SF_PRIVATE *psf, int calc_length)
|
||||
/* VHDR : volume */
|
||||
psf_binheader_writef (psf, "E4", (psf->bytewidth == 1) ? 0xFF : 0xFFFF) ;
|
||||
|
||||
if (psf->sf.channels == 2)
|
||||
psf_binheader_writef (psf, "Em44", CHAN_MARKER, 4, 6) ;
|
||||
|
||||
/* Filename and annotation strings. */
|
||||
psf_binheader_writef (psf, "Emsms", NAME_MARKER, psf->filename, ANNO_MARKER, annotation) ;
|
||||
psf_binheader_writef (psf, "Emsms", NAME_MARKER, psf->file.name.c, ANNO_MARKER, annotation) ;
|
||||
|
||||
/* BODY marker and size. */
|
||||
psf_binheader_writef (psf, "Etm8", BODY_MARKER, (psf->datalength < 0) ?
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** Copyright (C) 2007-2009 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
** Copyright (C) 2007-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
@@ -88,8 +88,7 @@ test_audio_detect (void)
|
||||
ad.endianness = SF_ENDIAN_LITTLE ;
|
||||
ad.channels = 1 ;
|
||||
if (audio_detect (&psf, &ad, float_le_mono, sizeof (float_le_mono)) != SF_FORMAT_FLOAT)
|
||||
{ if (errors == 0) puts ("\nFailed tests :\n") ;
|
||||
puts (" float_le_mono") ;
|
||||
{ puts (" float_le_mono") ;
|
||||
errors ++ ;
|
||||
} ;
|
||||
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
** Copyright (C) 2010-2012 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program 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 program 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 program; if not, write to the Free Software
|
||||
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "sfconfig.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#include "test_main.h"
|
||||
|
||||
#define BCAST_MAX 512
|
||||
|
||||
typedef SF_BROADCAST_INFO_VAR (BCAST_MAX) SF_BROADCAST_INFO_512 ;
|
||||
|
||||
static void
|
||||
fill_coding_history (SF_BROADCAST_INFO_512 * bi)
|
||||
{ static const char *lines [] =
|
||||
{ "Lorem ipsum dolor sit amet,\nconsectetur adipiscing elit.",
|
||||
"Donec dignissim erat\nvehicula libero condimentum\ndictum porta augue faucibus.",
|
||||
"Maecenas nec turpis\nsit amet quam\nfaucibus adipiscing.",
|
||||
"Mauris aliquam,\nlectus interdum\ntincidunt luctus.",
|
||||
"\n\n\n\n\n\n\n\n\n\n\n\n",
|
||||
"In auctor lorem\nvel est euismod\ncondimentum.",
|
||||
"\n\n\n\n\n\n\n\n\n\n\n\n",
|
||||
"Ut vitae magna\nid dui placerat vehicula\nin id lectus.",
|
||||
"\n\n\n\n\n\n\n\n\n\n\n\n",
|
||||
"Sed lacus leo,\nmolestie et luctus ac,\ntincidunt sit amet nisi.",
|
||||
"\n\n\n\n\n\n\n\n\n\n\n\n",
|
||||
"Sed ligula neque,\ngravida semper vulputate laoreet,\ngravida eu tellus.",
|
||||
"Donec dolor dolor,\nscelerisque in consequat ornare,\ntempor nec nisl."
|
||||
} ;
|
||||
int k ;
|
||||
|
||||
bi->coding_history [0] = 0 ;
|
||||
|
||||
for (k = 0 ; strlen (bi->coding_history) < bi->coding_history_size - 1 ; k ++)
|
||||
append_snprintf (bi->coding_history, bi->coding_history_size, "%s\n", lines [k % ARRAY_LEN (lines)]) ;
|
||||
|
||||
return ;
|
||||
} /* fill_coding_listory */
|
||||
|
||||
static void
|
||||
test_broadcast_var_set (void)
|
||||
{ SF_PRIVATE sf_private, *psf ;
|
||||
int k ;
|
||||
|
||||
psf = &sf_private ;
|
||||
memset (psf, 0, sizeof (sf_private)) ;
|
||||
|
||||
print_test_name ("Testing broadcast_var_set ") ;
|
||||
|
||||
for (k = 64 ; k < BCAST_MAX ; k++)
|
||||
{
|
||||
SF_BROADCAST_INFO_512 bi ;
|
||||
|
||||
memset (&bi, 0, sizeof (bi)) ;
|
||||
|
||||
bi.coding_history_size = k ;
|
||||
fill_coding_history (&bi) ;
|
||||
bi.coding_history_size -- ;
|
||||
|
||||
broadcast_var_set (psf, (SF_BROADCAST_INFO*) &bi, sizeof (bi)) ;
|
||||
} ;
|
||||
|
||||
if (psf->broadcast_16k != NULL)
|
||||
free (psf->broadcast_16k) ;
|
||||
|
||||
puts ("ok") ;
|
||||
} /* test_broadcast_var_set */
|
||||
|
||||
static void
|
||||
test_broadcast_var_zero (void)
|
||||
{ SF_PRIVATE sf_private, *psf ;
|
||||
SF_BROADCAST_INFO_VAR (0) bi ;
|
||||
|
||||
psf = &sf_private ;
|
||||
memset (psf, 0, sizeof (sf_private)) ;
|
||||
psf->file.mode = SFM_RDWR ;
|
||||
|
||||
print_test_name ("Testing broadcast_var_zero ") ;
|
||||
|
||||
memset (&bi, 0, sizeof (bi)) ;
|
||||
|
||||
broadcast_var_set (psf, (SF_BROADCAST_INFO*) &bi, sizeof (bi)) ;
|
||||
|
||||
if (psf->broadcast_16k->coding_history_size != 0)
|
||||
{ printf ("\n\nLine %d: coding_history_size %d should be zero.\n\n", __LINE__, psf->broadcast_16k->coding_history_size) ;
|
||||
exit (1) ;
|
||||
} ;
|
||||
|
||||
if (psf->broadcast_16k != NULL)
|
||||
free (psf->broadcast_16k) ;
|
||||
|
||||
puts ("ok") ;
|
||||
} /* test_broadcast_var_zero */
|
||||
|
||||
void
|
||||
test_broadcast_var (void)
|
||||
{ test_broadcast_var_set () ;
|
||||
test_broadcast_var_zero () ;
|
||||
} /* test_broadcast_var */
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
** Copyright (C) 2010-2013 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program 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 program 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 program; if not, write to the Free Software
|
||||
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "sfconfig.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#include "test_main.h"
|
||||
|
||||
#define CART_MAX 512
|
||||
|
||||
typedef SF_CART_INFO_VAR (CART_MAX) SF_CART_INFO_512 ;
|
||||
|
||||
static void
|
||||
fill_tag_text (SF_CART_INFO_512 * ci)
|
||||
{ static const char *lines [] =
|
||||
{ "Lorem ipsum dolor sit amet,\nconsectetur adipiscing elit.",
|
||||
"Donec dignissim erat\nvehicula libero condimentum\ndictum porta augue faucibus.",
|
||||
"Maecenas nec turpis\nsit amet quam\nfaucibus adipiscing.",
|
||||
"Mauris aliquam,\nlectus interdum\ntincidunt luctus.",
|
||||
"\n\n\n\n\n\n\n\n\n\n\n\n",
|
||||
"In auctor lorem\nvel est euismod\ncondimentum.",
|
||||
"\n\n\n\n\n\n\n\n\n\n\n\n",
|
||||
"Ut vitae magna\nid dui placerat vehicula\nin id lectus.",
|
||||
"\n\n\n\n\n\n\n\n\n\n\n\n",
|
||||
"Sed lacus leo,\nmolestie et luctus ac,\ntincidunt sit amet nisi.",
|
||||
"\n\n\n\n\n\n\n\n\n\n\n\n",
|
||||
"Sed ligula neque,\ngravida semper vulputate laoreet,\ngravida eu tellus.",
|
||||
"Donec dolor dolor,\nscelerisque in consequat ornare,\ntempor nec nisl."
|
||||
} ;
|
||||
int k ;
|
||||
|
||||
ci->tag_text [0] = 0 ;
|
||||
|
||||
for (k = 0 ; strlen (ci->tag_text) < ci->tag_text_size - 1 ; k ++)
|
||||
append_snprintf (ci->tag_text, ci->tag_text_size, "%s\n", lines [k % ARRAY_LEN (lines)]) ;
|
||||
|
||||
return ;
|
||||
} /* fill_tag_text */
|
||||
|
||||
void
|
||||
test_cart_var (void)
|
||||
{ SF_PRIVATE sf_private, *psf ;
|
||||
SF_CART_TIMER timer ;
|
||||
int k ;
|
||||
|
||||
psf = &sf_private ;
|
||||
memset (psf, 0, sizeof (sf_private)) ;
|
||||
|
||||
print_test_name ("Testing cart_var_set ") ;
|
||||
|
||||
for (k = 64 ; k < CART_MAX ; k++)
|
||||
{
|
||||
SF_CART_INFO_512 ci ;
|
||||
|
||||
memset (&ci, 0, sizeof (ci)) ;
|
||||
|
||||
memset (&timer, 0, sizeof (timer)) ;
|
||||
memcpy (ci.post_timers, &timer, sizeof (timer)) ;
|
||||
|
||||
ci.tag_text_size = k ;
|
||||
fill_tag_text (&ci) ;
|
||||
ci.tag_text_size -- ;
|
||||
|
||||
cart_var_set (psf, (SF_CART_INFO*) &ci, sizeof (ci)) ;
|
||||
} ;
|
||||
|
||||
if (psf->cart_16k != NULL)
|
||||
free (psf->cart_16k) ;
|
||||
|
||||
puts ("ok") ;
|
||||
} /* test_cart_var */
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** Copyright (C) 2006-2009 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
** Copyright (C) 2006-2012 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
@@ -20,7 +20,6 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <errno.h>
|
||||
@@ -34,7 +33,7 @@
|
||||
** This is a bit rough, but it is the nicest way to do it.
|
||||
*/
|
||||
|
||||
#define cmp_test(line,ival,tval,str) \
|
||||
#define cmp_test(line, ival, tval, str) \
|
||||
if (ival != tval) \
|
||||
{ printf (str, line, ival, tval) ; \
|
||||
exit (1) ; \
|
||||
@@ -62,7 +61,10 @@ conversion_test (char endian)
|
||||
psf = &sf_private ;
|
||||
memset (psf, 0, sizeof (sf_private)) ;
|
||||
|
||||
if (psf_fopen (psf, filename, SFM_WRITE) != 0)
|
||||
psf->file.mode = SFM_WRITE ;
|
||||
snprintf (psf->file.path.c, sizeof (psf->file.path.c), "%s", filename) ;
|
||||
|
||||
if (psf_fopen (psf) != 0)
|
||||
{ printf ("\n\nError : failed to open file '%s' for write.\n\n", filename) ;
|
||||
exit (1) ;
|
||||
} ;
|
||||
@@ -72,7 +74,11 @@ conversion_test (char endian)
|
||||
psf_fclose (psf) ;
|
||||
|
||||
memset (psf, 0, sizeof (sf_private)) ;
|
||||
if (psf_fopen (psf, filename, SFM_READ) != 0)
|
||||
|
||||
psf->file.mode = SFM_READ ;
|
||||
snprintf (psf->file.path.c, sizeof (psf->file.path.c), "%s", filename) ;
|
||||
|
||||
if (psf_fopen (psf) != 0)
|
||||
{ printf ("\n\nError : failed to open file '%s' for read.\n\n", filename) ;
|
||||
exit (1) ;
|
||||
} ;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** Copyright (C) 2002-2009 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
** Copyright (C) 2002-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
|
||||
@@ -18,3 +18,23 @@ int_type = {
|
||||
format = FMT_INT64 ;
|
||||
} ;
|
||||
|
||||
int_size = {
|
||||
name = 16 ;
|
||||
typename = int16_t ;
|
||||
value = 0x4142 ;
|
||||
strval = "AB" ;
|
||||
} ;
|
||||
|
||||
int_size = {
|
||||
name = 32 ;
|
||||
typename = int32_t ;
|
||||
value = 0x30313233 ;
|
||||
strval = "0123" ;
|
||||
} ;
|
||||
|
||||
int_size = {
|
||||
name = 64 ;
|
||||
typename = int64_t ;
|
||||
value = 0x3031323334353637 ;
|
||||
strval = "01234567" ;
|
||||
} ;
|
||||
@@ -1,6 +1,6 @@
|
||||
[+ AutoGen5 template c +]
|
||||
/*
|
||||
** Copyright (C) 2002-2005 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
** Copyright (C) 2002-2013 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
@@ -105,6 +105,34 @@ test_endswap_[+ (get "name") +] (void)
|
||||
[+ ENDFOR int_type
|
||||
+]
|
||||
|
||||
[+ FOR int_size +]
|
||||
static void
|
||||
test_psf_put_be[+ (get "name") +] (void)
|
||||
{ const char *test = "[+ (get "strval") +]" ;
|
||||
uint8_t array [32] ;
|
||||
int k ;
|
||||
|
||||
printf (" %-40s : ", __func__) ;
|
||||
fflush (stdout) ;
|
||||
|
||||
for (k = 0 ; k < 10 ; k++)
|
||||
{ memset (array, 0, sizeof (array)) ;
|
||||
|
||||
psf_put_be[+ (get "name") +] (array, k, [+ (get "value") +]) ;
|
||||
if (memcmp (array + k, test, sizeof ([+ (get "typename") +])) != 0)
|
||||
{ printf ("\n\nLine %d : Put failed at index %d.\n", __LINE__, k) ;
|
||||
exit (1) ;
|
||||
} ;
|
||||
if (psf_get_be[+ (get "name") +] (array, k) != [+ (get "value") +])
|
||||
{ printf ("\n\nLine %d : Get failed at index %d.\n", __LINE__, k) ;
|
||||
exit (1) ;
|
||||
} ;
|
||||
} ;
|
||||
|
||||
puts ("ok") ;
|
||||
} /* test_psf_put_be[+ (get "name") +] */
|
||||
[+ ENDFOR int_size
|
||||
+]
|
||||
|
||||
void
|
||||
test_endswap (void)
|
||||
@@ -113,5 +141,11 @@ test_endswap (void)
|
||||
+] test_endswap_[+ (get "name") +] () ;
|
||||
[+ ENDFOR int_type
|
||||
+]
|
||||
|
||||
[+ FOR int_size
|
||||
+] test_psf_put_be[+ (get "name") +] () ;
|
||||
[+ ENDFOR int_endsize
|
||||
+]
|
||||
|
||||
} /* test_endswap */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** Copyright (C) 2002-2009 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
** Copyright (C) 2002-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
@@ -27,6 +27,7 @@
|
||||
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
@@ -68,10 +69,11 @@ file_open_test (const char *filename)
|
||||
exit (1) ;
|
||||
} ;
|
||||
|
||||
snprintf (psf->filename, sizeof (psf->filename), "%s", filename) ;
|
||||
psf->file.mode = SFM_READ ;
|
||||
snprintf (psf->file.path.c, sizeof (psf->file.path.c), "%s", filename) ;
|
||||
|
||||
/* Test that open for read fails if the file doesn't exist. */
|
||||
error = psf_fopen (psf, psf->filename, SFM_READ) ;
|
||||
error = psf_fopen (psf) ;
|
||||
if (error == 0)
|
||||
{ printf ("\n\nLine %d: psf_fopen() should have failed.\n\n", __LINE__) ;
|
||||
exit (1) ;
|
||||
@@ -81,26 +83,26 @@ file_open_test (const char *filename)
|
||||
psf->error = SFE_NO_ERROR ;
|
||||
|
||||
/* Test file open in write mode. */
|
||||
psf->mode = SFM_WRITE ;
|
||||
psf->file.mode = SFM_WRITE ;
|
||||
test_open_or_die (psf, __LINE__) ;
|
||||
|
||||
test_close_or_die (psf, __LINE__) ;
|
||||
|
||||
unlink (psf->filename) ;
|
||||
unlink (psf->file.path.c) ;
|
||||
|
||||
/* Test file open in read/write mode for a non-existant file. */
|
||||
psf->mode = SFM_RDWR ;
|
||||
psf->file.mode = SFM_RDWR ;
|
||||
test_open_or_die (psf, __LINE__) ;
|
||||
|
||||
test_close_or_die (psf, __LINE__) ;
|
||||
|
||||
/* Test file open in read/write mode for an existing file. */
|
||||
psf->mode = SFM_RDWR ;
|
||||
psf->file.mode = SFM_RDWR ;
|
||||
test_open_or_die (psf, __LINE__) ;
|
||||
|
||||
test_close_or_die (psf, __LINE__) ;
|
||||
|
||||
unlink (psf->filename) ;
|
||||
unlink (psf->file.path.c) ;
|
||||
puts ("ok") ;
|
||||
} /* file_open_test */
|
||||
|
||||
@@ -121,17 +123,17 @@ file_read_write_test (const char *filename)
|
||||
|
||||
memset (&sf_data, 0, sizeof (sf_data)) ;
|
||||
psf = &sf_data ;
|
||||
snprintf (psf->filename, sizeof (psf->filename), "%s", filename) ;
|
||||
snprintf (psf->file.path.c, sizeof (psf->file.path.c), "%s", filename) ;
|
||||
|
||||
/* Test file open in write mode. */
|
||||
psf->mode = SFM_WRITE ;
|
||||
psf->file.mode = SFM_WRITE ;
|
||||
test_open_or_die (psf, __LINE__) ;
|
||||
|
||||
make_data (data_out, ARRAY_LEN (data_out), 1) ;
|
||||
test_write_or_die (psf, data_out, sizeof (data_out [0]), ARRAY_LEN (data_out), sizeof (data_out), __LINE__) ;
|
||||
|
||||
if ((retval = psf_get_filelen (psf)) != sizeof (data_out))
|
||||
{ printf ("\n\nLine %d: file length after write is not correct (%ld should be %d).\n\n", __LINE__, (long) retval, (int) sizeof (data_out)) ;
|
||||
{ printf ("\n\nLine %d: file length after write is not correct (%" PRId64 " should be %zd).\n\n", __LINE__, retval, sizeof (data_out)) ;
|
||||
if (retval == 0)
|
||||
printf ("An fsync() may be necessary before fstat() in psf_get_filelen().\n\n") ;
|
||||
exit (1) ;
|
||||
@@ -141,7 +143,7 @@ file_read_write_test (const char *filename)
|
||||
test_write_or_die (psf, data_out, ARRAY_LEN (data_out), sizeof (data_out [0]), 2 * sizeof (data_out), __LINE__) ;
|
||||
|
||||
if ((retval = psf_get_filelen (psf)) != 2 * sizeof (data_out))
|
||||
{ printf ("\n\nLine %d: file length after write is not correct. (%ld should be %d)\n\n", __LINE__, (long) retval, 2 * ((int) sizeof (data_out))) ;
|
||||
{ printf ("\n\nLine %d: file length after write is not correct. (%" PRId64 " should be %zd)\n\n", __LINE__, retval, 2 * sizeof (data_out)) ;
|
||||
exit (1) ;
|
||||
} ;
|
||||
|
||||
@@ -156,7 +158,7 @@ file_read_write_test (const char *filename)
|
||||
print_test_name ("Testing file read") ;
|
||||
|
||||
/* Test file open in write mode. */
|
||||
psf->mode = SFM_READ ;
|
||||
psf->file.mode = SFM_READ ;
|
||||
test_open_or_die (psf, __LINE__) ;
|
||||
|
||||
make_data (data_out, ARRAY_LEN (data_out), 1) ;
|
||||
@@ -180,7 +182,7 @@ file_read_write_test (const char *filename)
|
||||
print_test_name ("Testing file seek") ;
|
||||
|
||||
/* Test file open in read/write mode. */
|
||||
psf->mode = SFM_RDWR ;
|
||||
psf->file.mode = SFM_RDWR ;
|
||||
test_open_or_die (psf, __LINE__) ;
|
||||
|
||||
test_seek_or_die (psf, 0, SEEK_SET, 0, __LINE__) ;
|
||||
@@ -218,12 +220,12 @@ file_read_write_test (const char *filename)
|
||||
print_test_name ("Testing file offset") ;
|
||||
|
||||
/* Test file open in read/write mode. */
|
||||
psf->mode = SFM_RDWR ;
|
||||
psf->file.mode = SFM_RDWR ;
|
||||
psf->fileoffset = sizeof (data_out [0]) * ARRAY_LEN (data_out) ;
|
||||
test_open_or_die (psf, __LINE__) ;
|
||||
|
||||
if ((retval = psf_get_filelen (psf)) != 3 * sizeof (data_out))
|
||||
{ printf ("\n\nLine %d: file length after write is not correct. (%ld should be %d)\n\n", __LINE__, (long) retval, 3 * ((int) sizeof (data_out))) ;
|
||||
{ printf ("\n\nLine %d: file length after write is not correct. (%" PRId64 " should be %zd)\n\n", __LINE__, retval, 3 * sizeof (data_out)) ;
|
||||
exit (1) ;
|
||||
} ;
|
||||
|
||||
@@ -234,12 +236,12 @@ file_read_write_test (const char *filename)
|
||||
|
||||
/* final test with psf->fileoffset == 0. */
|
||||
|
||||
psf->mode = SFM_RDWR ;
|
||||
psf->file.mode = SFM_RDWR ;
|
||||
psf->fileoffset = 0 ;
|
||||
test_open_or_die (psf, __LINE__) ;
|
||||
|
||||
if ((retval = psf_get_filelen (psf)) != 3 * sizeof (data_out))
|
||||
{ printf ("\n\nLine %d: file length after write is not correct. (%ld should be %d)\n\n", __LINE__, (long) retval, 3 * ((int) sizeof (data_out))) ;
|
||||
{ printf ("\n\nLine %d: file length after write is not correct. (%" PRId64 " should be %zd)\n\n", __LINE__, retval, 3 * sizeof (data_out)) ;
|
||||
exit (1) ;
|
||||
} ;
|
||||
|
||||
@@ -277,20 +279,20 @@ file_truncate_test (const char *filename)
|
||||
memset (buffer, 0xEE, sizeof (buffer)) ;
|
||||
|
||||
psf = &sf_data ;
|
||||
snprintf (psf->filename, sizeof (psf->filename), "%s", filename) ;
|
||||
snprintf (psf->file.path.c, sizeof (psf->file.path.c), "%s", filename) ;
|
||||
|
||||
/*
|
||||
** Open the file write mode, write 0xEE data and then extend the file
|
||||
** using truncate (the extended data should be 0x00).
|
||||
*/
|
||||
psf->mode = SFM_WRITE ;
|
||||
psf->file.mode = SFM_WRITE ;
|
||||
test_open_or_die (psf, __LINE__) ;
|
||||
test_write_or_die (psf, buffer, sizeof (buffer) / 2, 1, sizeof (buffer) / 2, __LINE__) ;
|
||||
psf_ftruncate (psf, sizeof (buffer)) ;
|
||||
test_close_or_die (psf, __LINE__) ;
|
||||
|
||||
/* Open the file in read mode and check the data. */
|
||||
psf->mode = SFM_READ ;
|
||||
psf->file.mode = SFM_READ ;
|
||||
test_open_or_die (psf, __LINE__) ;
|
||||
test_read_or_die (psf, buffer, sizeof (buffer), 1, sizeof (buffer), __LINE__) ;
|
||||
test_close_or_die (psf, __LINE__) ;
|
||||
@@ -308,13 +310,13 @@ file_truncate_test (const char *filename)
|
||||
} ;
|
||||
|
||||
/* Open the file in read/write and shorten the file using truncate. */
|
||||
psf->mode = SFM_RDWR ;
|
||||
psf->file.mode = SFM_RDWR ;
|
||||
test_open_or_die (psf, __LINE__) ;
|
||||
psf_ftruncate (psf, sizeof (buffer) / 4) ;
|
||||
test_close_or_die (psf, __LINE__) ;
|
||||
|
||||
/* Check the file length. */
|
||||
psf->mode = SFM_READ ;
|
||||
psf->file.mode = SFM_READ ;
|
||||
test_open_or_die (psf, __LINE__) ;
|
||||
test_seek_or_die (psf, 0, SEEK_END, SIGNED_SIZEOF (buffer) / 4, __LINE__) ;
|
||||
test_close_or_die (psf, __LINE__) ;
|
||||
@@ -331,7 +333,7 @@ test_open_or_die (SF_PRIVATE *psf, int linenum)
|
||||
{ int error ;
|
||||
|
||||
/* Test that open for read fails if the file doesn't exist. */
|
||||
error = psf_fopen (psf, psf->filename, psf->mode) ;
|
||||
error = psf_fopen (psf) ;
|
||||
if (error)
|
||||
{ printf ("\n\nLine %d: psf_fopen() failed : %s\n\n", linenum, strerror (errno)) ;
|
||||
exit (1) ;
|
||||
@@ -344,7 +346,7 @@ test_close_or_die (SF_PRIVATE *psf, int linenum)
|
||||
{
|
||||
psf_fclose (psf) ;
|
||||
if (psf_file_valid (psf))
|
||||
{ printf ("\n\nLine %d: psf->filedes should not be valid.\n\n", linenum) ;
|
||||
{ printf ("\n\nLine %d: psf->file.filedes should not be valid.\n\n", linenum) ;
|
||||
exit (1) ;
|
||||
} ;
|
||||
|
||||
@@ -356,12 +358,12 @@ test_write_or_die (SF_PRIVATE *psf, void *data, sf_count_t bytes, sf_count_t ite
|
||||
|
||||
retval = psf_fwrite (data, bytes, items, psf) ;
|
||||
if (retval != items)
|
||||
{ printf ("\n\nLine %d: psf_write() returned %ld (should be %ld)\n\n", linenum, (long) retval, (long) items) ;
|
||||
{ printf ("\n\nLine %d: psf_write() returned %" PRId64 " (should be %" PRId64 ")\n\n", linenum, retval, items) ;
|
||||
exit (1) ;
|
||||
} ;
|
||||
|
||||
if ((retval = psf_ftell (psf)) != new_position)
|
||||
{ printf ("\n\nLine %d: file length after write is not correct. (%ld should be %ld)\n\n", linenum, (long) retval, (long) new_position) ;
|
||||
{ printf ("\n\nLine %d: file length after write is not correct. (%" PRId64 " should be %" PRId64 ")\n\n", linenum, retval, new_position) ;
|
||||
exit (1) ;
|
||||
} ;
|
||||
|
||||
@@ -374,12 +376,12 @@ test_read_or_die (SF_PRIVATE *psf, void *data, sf_count_t bytes, sf_count_t item
|
||||
|
||||
retval = psf_fread (data, bytes, items, psf) ;
|
||||
if (retval != items)
|
||||
{ printf ("\n\nLine %d: psf_write() returned %ld (should be %ld)\n\n", linenum, (long) retval, (long) items) ;
|
||||
{ printf ("\n\nLine %d: psf_write() returned %" PRId64 " (should be %" PRId64 ")\n\n", linenum, retval, items) ;
|
||||
exit (1) ;
|
||||
} ;
|
||||
|
||||
if ((retval = psf_ftell (psf)) != new_position)
|
||||
{ printf ("\n\nLine %d: file length after write is not correct. (%ld should be %ld)\n\n", linenum, (long) retval, (long) new_position) ;
|
||||
{ printf ("\n\nLine %d: file length after write is not correct. (%" PRId64 " should be %" PRId64 ")\n\n", linenum, retval, new_position) ;
|
||||
exit (1) ;
|
||||
} ;
|
||||
|
||||
@@ -393,8 +395,8 @@ test_seek_or_die (SF_PRIVATE *psf, sf_count_t offset, int whence, sf_count_t new
|
||||
retval = psf_fseek (psf, offset, whence) ;
|
||||
|
||||
if (retval != new_position)
|
||||
{ printf ("\n\nLine %d: psf_fseek() failed. New position is %ld (should be %ld).\n\n",
|
||||
linenum, (long) retval, (long) new_position) ;
|
||||
{ printf ("\n\nLine %d: psf_fseek() failed. New position is %" PRId64 " (should be %" PRId64 ").\n\n",
|
||||
linenum, retval, new_position) ;
|
||||
exit (1) ;
|
||||
} ;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** Copyright (C) 2006-2009 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
** Copyright (C) 2006-2012 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
@@ -48,7 +48,7 @@ test_float_convert (void)
|
||||
test = float32_le_read (bytes) ;
|
||||
|
||||
if (fabs (data [k] - test) > 1e-20)
|
||||
{ printf ("\n\nLine %d : Test %d, little endian error %.15g -> %.15g.\n\n", __LINE__, k, data [k], test ) ;
|
||||
{ printf ("\n\nLine %d : Test %d, little endian error %.15g -> %.15g.\n\n", __LINE__, k, data [k], test) ;
|
||||
exit (1) ;
|
||||
} ;
|
||||
|
||||
@@ -85,7 +85,7 @@ test_double_convert (void)
|
||||
test = double64_le_read (bytes) ;
|
||||
|
||||
if (fabs (data [k] - test) > 1e-20)
|
||||
{ printf ("\n\nLine %d : Test %d, little endian error %.15g -> %.15g.\n\n", __LINE__, k, data [k], test ) ;
|
||||
{ printf ("\n\nLine %d : Test %d, little endian error %.15g -> %.15g.\n\n", __LINE__, k, data [k], test) ;
|
||||
exit (1) ;
|
||||
} ;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
** Copyright (C) 2007-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
** Copyright (c) 2007 <robs@users.sourceforge.net>
|
||||
** Copyright (C) 2007-2009 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** 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
|
||||
@@ -17,6 +17,8 @@
|
||||
** Fifth Floor, 51 Franklin Street, Boston, MA 02111-1301, USA.
|
||||
*/
|
||||
|
||||
#include "sfconfig.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "test_main.h"
|
||||
@@ -71,7 +73,7 @@ test_oki_adpcm (void)
|
||||
print_test_name ("Testing ima/oki decoder") ;
|
||||
|
||||
ima_oki_adpcm_init (&adpcm, IMA_OKI_ADPCM_TYPE_OKI) ;
|
||||
for (i = 0 ; i < ARRAY_LEN (test_pcm) - 1 ; i += j)
|
||||
for (i = 0 ; i < ARRAY_LEN (test_pcm) - 1 ; i += 2)
|
||||
{ code = adpcm_encode (&adpcm, test_pcm [i]) ;
|
||||
code = (code << 4) | adpcm_encode (&adpcm, test_pcm [i + 1]) ;
|
||||
if (code != test_codes [i / 2])
|
||||
|
||||
Loaded 100 of 291 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user