Browse Source

Fixed an iOS stat call and an image loading bug.

tags/2021-05-28
Julian Storer 15 years ago
parent
commit
769e6d185d
8 changed files with 806 additions and 34 deletions
  1. +146
    -21
      juce_amalgamated.cpp
  2. +262
    -1
      juce_amalgamated.h
  3. +108
    -0
      src/audio/dsp/juce_AudioDataConverters.cpp
  4. +268
    -0
      src/audio/dsp/juce_AudioDataConverters.h
  5. +1
    -1
      src/core/juce_StandardHeader.h
  6. +17
    -9
      src/native/common/juce_posix_SharedCode.h
  7. +3
    -1
      src/native/mac/juce_mac_CoreGraphicsContext.mm
  8. +1
    -1
      src/native/mac/juce_mac_Files.mm

+ 146
- 21
juce_amalgamated.cpp View File

@@ -27180,6 +27180,111 @@ void AudioDataConverters::deinterleaveSamples (const float* const source,
}
}

#if JUCE_UNIT_TESTS

/*class AudioConversionTests : public UnitTest
{
public:
AudioConversionTests() : UnitTest ("Audio data conversion") {}

template <class SourceType, class DestType>
struct Test5
{
static void test (UnitTest& unitTest)
{
const int numSamples = 2048;
int32 original [numSamples], converted [numSamples], reversed [numSamples];

{
SourceType d (original);

for (int i = 0; i < numSamples / 2; ++i)
{
d.setAsFloat (Random::getSystemRandom().nextFloat() * 2.0f - 1.0f);
d.advance();
d.setAsInt32 (Random::getSystemRandom().nextInt());
d.advance();
}
}

// convert data from the source to dest format..
ScopedPointer<AudioData::Converter> conv (new AudioData::ConverterInstance <SourceType, DestType>());
conv->copySamples (converted, original, numSamples);

// ..and back again..
conv = new AudioData::ConverterInstance <DestType, SourceType>();
zerostruct (reversed);
conv->copySamples (reversed, converted, numSamples);

{
int biggestDiff = 0;
SourceType d1 (original);
SourceType d2 (reversed);

const int errorMargin = 2 * DestType::get32BitResolution() + SourceType::get32BitResolution();

for (int i = 0; i < numSamples; ++i)
{
biggestDiff = jmax (biggestDiff, std::abs (d1.getAsInt32() - d2.getAsInt32()));
d1.advance();
d2.advance();
}

unitTest.expect (biggestDiff <= errorMargin);
}
}
};

template <class SourceType, class FormatType>
struct Test3
{
static void test (UnitTest& unitTest)
{
Test5 <SourceType, AudioData::Pointer <FormatType, AudioData::BigEndian, AudioData::NonInterleaved> >::test (unitTest);
Test5 <SourceType, AudioData::Pointer <FormatType, AudioData::LittleEndian, AudioData::NonInterleaved> >::test (unitTest);
}
};

template <class SourceType>
struct Test2
{
static void test (UnitTest& unitTest)
{
Test3 <SourceType, AudioData::Int16>::test (unitTest);
Test3 <SourceType, AudioData::Int24>::test (unitTest);
Test3 <SourceType, AudioData::Int32>::test (unitTest);
Test3 <SourceType, AudioData::Float32>::test (unitTest);
Test3 <SourceType, AudioData::Int8>::test (unitTest);
}
};

template <class FormatType>
struct Test1
{
static void test (UnitTest& unitTest)
{
Test2 <AudioData::Pointer <FormatType, AudioData::BigEndian, AudioData::NonInterleaved> >::test (unitTest);
Test2 <AudioData::Pointer <FormatType, AudioData::LittleEndian, AudioData::NonInterleaved> >::test (unitTest);
}
};

void runTest()
{
beginTest ("Round-trip conversion");

Test1 <AudioData::Int8>::test (*this);
Test1 <AudioData::Int16>::test (*this);
Test1 <AudioData::Int24>::test (*this);
Test1 <AudioData::Int32>::test (*this);
Test1 <AudioData::Float32>::test (*this);
}
};

static AudioConversionTests audioConversionUnitTests;
*/

#endif

END_JUCE_NAMESPACE
/*** End of inlined file: juce_AudioDataConverters.cpp ***/

@@ -254969,15 +255074,25 @@ bool File::setAsCurrentWorkingDirectory() const
return chdir (getFullPathName().toUTF8()) == 0;
}

static bool juce_stat (const String& fileName, struct stat& info)
#if JUCE_IOS
typedef struct stat64 juce_statStruct; // (need to use the 64-bit version to work around a simulator bug)
#else
typedef struct stat juce_statStruct;
#endif

static bool juce_stat (const String& fileName, juce_statStruct& info)
{
return fileName.isNotEmpty()
#if JUCE_IOS
&& (stat64 (fileName.toUTF8(), &info) == 0);
#else
&& (stat (fileName.toUTF8(), &info) == 0);
#endif
}

bool File::isDirectory() const
{
struct stat info;
juce_statStruct info;

return fullPath.isEmpty()
|| (juce_stat (fullPath, info) && ((info.st_mode & S_IFDIR) != 0));
@@ -254996,7 +255111,7 @@ bool File::existsAsFile() const

int64 File::getSize() const
{
struct stat info;
juce_statStruct info;
return juce_stat (fullPath, info) ? info.st_size : 0;
}

@@ -255013,9 +255128,8 @@ bool File::hasWriteAccess() const

bool File::setFileReadOnlyInternal (const bool shouldBeReadOnly) const
{
struct stat info;
const int res = stat (fullPath.toUTF8(), &info);
if (res != 0)
juce_statStruct info;
if (! juce_stat (fullPath, info))
return false;

info.st_mode &= 0777; // Just permissions
@@ -255035,9 +255149,8 @@ void File::getFileTimesInternal (int64& modificationTime, int64& accessTime, int
accessTime = 0;
creationTime = 0;

struct stat info;
const int res = stat (fullPath.toUTF8(), &info);
if (res == 0)
juce_statStruct info;
if (juce_stat (fullPath, info))
{
modificationTime = (int64) info.st_mtime * 1000;
accessTime = (int64) info.st_atime * 1000;
@@ -264762,15 +264875,25 @@ bool File::setAsCurrentWorkingDirectory() const
return chdir (getFullPathName().toUTF8()) == 0;
}

static bool juce_stat (const String& fileName, struct stat& info)
#if JUCE_IOS
typedef struct stat64 juce_statStruct; // (need to use the 64-bit version to work around a simulator bug)
#else
typedef struct stat juce_statStruct;
#endif

static bool juce_stat (const String& fileName, juce_statStruct& info)
{
return fileName.isNotEmpty()
#if JUCE_IOS
&& (stat64 (fileName.toUTF8(), &info) == 0);
#else
&& (stat (fileName.toUTF8(), &info) == 0);
#endif
}

bool File::isDirectory() const
{
struct stat info;
juce_statStruct info;

return fullPath.isEmpty()
|| (juce_stat (fullPath, info) && ((info.st_mode & S_IFDIR) != 0));
@@ -264789,7 +264912,7 @@ bool File::existsAsFile() const

int64 File::getSize() const
{
struct stat info;
juce_statStruct info;
return juce_stat (fullPath, info) ? info.st_size : 0;
}

@@ -264806,9 +264929,8 @@ bool File::hasWriteAccess() const

bool File::setFileReadOnlyInternal (const bool shouldBeReadOnly) const
{
struct stat info;
const int res = stat (fullPath.toUTF8(), &info);
if (res != 0)
juce_statStruct info;
if (! juce_stat (fullPath, info))
return false;

info.st_mode &= 0777; // Just permissions
@@ -264828,9 +264950,8 @@ void File::getFileTimesInternal (int64& modificationTime, int64& accessTime, int
accessTime = 0;
creationTime = 0;

struct stat info;
const int res = stat (fullPath.toUTF8(), &info);
if (res == 0)
juce_statStruct info;
if (juce_stat (fullPath, info))
{
modificationTime = (int64) info.st_mtime * 1000;
accessTime = (int64) info.st_atime * 1000;
@@ -265548,7 +265669,7 @@ public:

if (isDir != 0 || fileSize != 0 || modTime != 0 || creationTime != 0)
{
struct stat info;
juce_statStruct info;
const bool statOk = juce_stat (path, info);

if (isDir != 0) *isDir = statOk && ((info.st_mode & S_IFDIR) != 0);
@@ -267393,7 +267514,9 @@ const Image juce_loadWithCoreImage (InputStream& input)

#if JUCE_IOS
JUCE_AUTORELEASEPOOL
UIImage* image = [UIImage imageWithData: [NSData dataWithBytesNoCopy: data.getData() length: data.getSize()]];
UIImage* image = [UIImage imageWithData: [NSData dataWithBytesNoCopy: data.getData()
length: data.getSize()
freeWhenDone: NO]];

if (image != nil)
{
@@ -272073,7 +272196,9 @@ const Image juce_loadWithCoreImage (InputStream& input)

#if JUCE_IOS
JUCE_AUTORELEASEPOOL
UIImage* image = [UIImage imageWithData: [NSData dataWithBytesNoCopy: data.getData() length: data.getSize()]];
UIImage* image = [UIImage imageWithData: [NSData dataWithBytesNoCopy: data.getData()
length: data.getSize()
freeWhenDone: NO]];

if (image != nil)
{


+ 262
- 1
juce_amalgamated.h View File

@@ -64,7 +64,7 @@
*/
#define JUCE_MAJOR_VERSION 1
#define JUCE_MINOR_VERSION 52
#define JUCE_BUILDNUMBER 67
#define JUCE_BUILDNUMBER 68

/** Current Juce version number.

@@ -37771,6 +37771,267 @@ private:
#ifndef __JUCE_AUDIODATACONVERTERS_JUCEHEADER__
#define __JUCE_AUDIODATACONVERTERS_JUCEHEADER__

/**

*/
/*
struct JUCE_API AudioData
{
xxx need to add int range limiting..

struct BigEndian
{
template <class SampleFormatType> static inline float getAsFloat (SampleFormatType& s) throw() { return s.getAsFloatBE(); }
template <class SampleFormatType> static inline void setAsFloat (SampleFormatType& s, float newValue) throw() { s.setAsFloatBE (newValue); }
template <class SampleFormatType> static inline int32 getAsInt32 (SampleFormatType& s) throw() { return s.getAsInt32BE(); }
template <class SampleFormatType> static inline void setAsInt32 (SampleFormatType& s, int32 newValue) throw() { s.setAsInt32BE (newValue); }
template <class SourceType, class DestType> static inline void copyFrom (DestType& dest, SourceType& source) throw() { dest.copyFromBE (source); }
};

struct LittleEndian
{
template <class SampleFormatType> static inline float getAsFloat (SampleFormatType& s) throw() { return s.getAsFloatLE(); }
template <class SampleFormatType> static inline void setAsFloat (SampleFormatType& s, float newValue) throw() { s.setAsFloatLE (newValue); }
template <class SampleFormatType> static inline int32 getAsInt32 (SampleFormatType& s) throw() { return s.getAsInt32LE(); }
template <class SampleFormatType> static inline void setAsInt32 (SampleFormatType& s, int32 newValue) throw() { s.setAsInt32LE (newValue); }
template <class SourceType, class DestType> static inline void copyFrom (DestType& dest, SourceType& source) throw() { dest.copyFromLE (source); }
};

#if JUCE_BIG_ENDIAN
typedef BigEndian NativeEndian;
#else
typedef LittleEndian NativeEndian;
#endif

struct Int8
{
inline Int8 (void* data_) : data (static_cast <int8*> (data_)) {}

inline void advance() throw() { ++data; }
inline void skip (int numSamples) throw() { data += numSamples; }
inline float getAsFloatLE() const throw() { return (float) (*data * (1.0 / maxValue)); }
inline float getAsFloatBE() const throw() { return (float) (*data * (1.0 / maxValue)); }
inline void setAsFloatLE (float newValue) throw() { *data = (int8) roundToInt (newValue * (double) maxValue); }
inline void setAsFloatBE (float newValue) throw() { *data = (int8) roundToInt (newValue * (double) maxValue); }
inline int32 getAsInt32LE() const throw() { return (int) (*data << 24); }
inline int32 getAsInt32BE() const throw() { return (int) (*data << 24); }
inline void setAsInt32LE (int newValue) throw() { *data = (int8) (newValue >> 24); }
inline void setAsInt32BE (int newValue) throw() { *data = (int8) (newValue >> 24); }

template <class SourceType> inline void copyFromLE (SourceType& source) throw() { setAsInt32LE (source.getAsInt32()); }
template <class SourceType> inline void copyFromBE (SourceType& source) throw() { setAsInt32BE (source.getAsInt32()); }
inline void copyFromSameType (Int8& source) throw() { *data = *source.data; }

int8* data;
enum { maxValue = 0x80, resolution = 0x1000000, isFloat = 0 };
};

struct Int16
{
inline Int16 (void* data_) : data (static_cast <uint16*> (data_)) {}

inline void advance() throw() { ++data; }
inline void skip (int numSamples) throw() { data += numSamples; }
inline float getAsFloatLE() const throw() { return (float) ((1.0 / maxValue) * (int16) ByteOrder::swapIfBigEndian (*data)); }
inline float getAsFloatBE() const throw() { return (float) ((1.0 / maxValue) * (int16) ByteOrder::swapIfLittleEndian (*data)); }
inline void setAsFloatLE (float newValue) throw() { *data = ByteOrder::swapIfBigEndian ((uint16) roundToInt (newValue * (double) maxValue)); }
inline void setAsFloatBE (float newValue) throw() { *data = ByteOrder::swapIfLittleEndian ((uint16) roundToInt (newValue * (double) maxValue)); }
inline int32 getAsInt32LE() const throw() { return (int32) (ByteOrder::swapIfBigEndian ((uint16) *data) << 16); }
inline int32 getAsInt32BE() const throw() { return (int32) (ByteOrder::swapIfLittleEndian ((uint16) *data) << 16); }
inline void setAsInt32LE (int32 newValue) throw() { *data = ByteOrder::swapIfBigEndian ((uint16) (newValue >> 16)); }
inline void setAsInt32BE (int32 newValue) throw() { *data = ByteOrder::swapIfLittleEndian ((uint16) (newValue >> 16)); }

template <class SourceType> inline void copyFromLE (SourceType& source) throw() { setAsInt32LE (source.getAsInt32()); }
template <class SourceType> inline void copyFromBE (SourceType& source) throw() { setAsInt32BE (source.getAsInt32()); }
inline void copyFromSameType (Int16& source) throw() { *data = *source.data; }

uint16* data;
enum { maxValue = 0x8000, resolution = 0x10000, isFloat = 0 };
};

struct Int24
{
inline Int24 (void* data_) : data (static_cast <char*> (data_)) {}

inline void advance() throw() { data += 3; }
inline void skip (int numSamples) throw() { data += 3 * numSamples; }

inline float getAsFloatLE() const throw() { return (float) (ByteOrder::littleEndian24Bit (data) * (1.0 / maxValue)); }
inline float getAsFloatBE() const throw() { return (float) (ByteOrder::bigEndian24Bit (data) * (1.0 / maxValue)); }
inline void setAsFloatLE (float newValue) throw() { ByteOrder::littleEndian24BitToChars (roundToInt (newValue * (double) maxValue), data); }
inline void setAsFloatBE (float newValue) throw() { ByteOrder::bigEndian24BitToChars (roundToInt (newValue * (double) maxValue), data); }
inline int32 getAsInt32LE() const throw() { return (int32) ByteOrder::littleEndian24Bit (data) << 8; }
inline int32 getAsInt32BE() const throw() { return (int32) ByteOrder::bigEndian24Bit (data) << 8; }
inline void setAsInt32LE (int32 newValue) throw() { ByteOrder::littleEndian24BitToChars (newValue >> 8, data); }
inline void setAsInt32BE (int32 newValue) throw() { ByteOrder::bigEndian24BitToChars (newValue >> 8, data); }

template <class SourceType> inline void copyFromLE (SourceType& source) throw() { setAsInt32LE (source.getAsInt32()); }
template <class SourceType> inline void copyFromBE (SourceType& source) throw() { setAsInt32BE (source.getAsInt32()); }
inline void copyFromSameType (Int24& source) throw() { data[0] = source.data[0]; data[1] = source.data[1]; data[2] = source.data[2]; }

char* data;
enum { maxValue = 0x800000, resolution = 0x100, isFloat = 0 };
};

struct Int32
{
inline Int32 (void* data_) : data (static_cast <uint32*> (data_)) {}

inline void advance() throw() { ++data; }
inline void skip (int numSamples) throw() { data += numSamples; }
inline float getAsFloatLE() const throw() { return (float) ((1.0 / (1.0 + maxValue)) * (int32) ByteOrder::swapIfBigEndian (*data)); }
inline float getAsFloatBE() const throw() { return (float) ((1.0 / (1.0 + maxValue)) * (int32) ByteOrder::swapIfLittleEndian (*data)); }
inline void setAsFloatLE (float newValue) throw() { *data = ByteOrder::swapIfBigEndian ((uint32) roundToInt (newValue * (1.0 + maxValue))); }
inline void setAsFloatBE (float newValue) throw() { *data = ByteOrder::swapIfLittleEndian ((uint32) roundToInt (newValue * (1.0 + maxValue))); }
inline int32 getAsInt32LE() const throw() { return (int32) ByteOrder::swapIfBigEndian (*data); }
inline int32 getAsInt32BE() const throw() { return (int32) ByteOrder::swapIfLittleEndian (*data); }
inline void setAsInt32LE (int32 newValue) throw() { *data = ByteOrder::swapIfBigEndian ((uint32) newValue); }
inline void setAsInt32BE (int32 newValue) throw() { *data = ByteOrder::swapIfLittleEndian ((uint32) newValue); }

template <class SourceType> inline void copyFromLE (SourceType& source) throw() { setAsInt32LE (source.getAsInt32()); }
template <class SourceType> inline void copyFromBE (SourceType& source) throw() { setAsInt32BE (source.getAsInt32()); }
inline void copyFromSameType (Int32& source) throw() { *data = *source.data; }

uint32* data;
enum { maxValue = 0x7fffffff, resolution = 1, isFloat = 0 };
};

struct Float32
{
inline Float32 (void* data_) : data (static_cast <float*> (data_)) {}

inline void advance() throw() { ++data; }
inline void skip (int numSamples) throw() { data += numSamples; }

#if JUCE_BIG_ENDIAN
inline float getAsFloatBE() const throw() { return *data; }
inline void setAsFloatBE (float newValue) throw() { *data = newValue; }
inline float getAsFloatLE() const throw() { union { uint32 asInt; float asFloat; } n; n.asInt = ByteOrder::swap (*(uint32*) data); return n.asFloat; }
inline void setAsFloatLE (float newValue) throw() { union { uint32 asInt; float asFloat; } n; n.asFloat = newValue; *(uint32*) data = ByteOrder::swap (n.asInt); }
#else
inline float getAsFloatLE() const throw() { return *data; }
inline void setAsFloatLE (float newValue) throw() { *data = newValue; }
inline float getAsFloatBE() const throw() { union { uint32 asInt; float asFloat; } n; n.asInt = ByteOrder::swap (*(uint32*) data); return n.asFloat; }
inline void setAsFloatBE (float newValue) throw() { union { uint32 asInt; float asFloat; } n; n.asFloat = newValue; *(uint32*) data = ByteOrder::swap (n.asInt); }
#endif

inline int32 getAsInt32LE() const throw() { return (int32) roundToInt (getAsFloatLE() * (1.0 + maxValue)); }
inline int32 getAsInt32BE() const throw() { return (int32) roundToInt (getAsFloatBE() * (1.0 + maxValue)); }
inline void setAsInt32LE (int32 newValue) throw() { setAsFloatLE ((float) (newValue * (1.0 / (1.0 + maxValue)))); }
inline void setAsInt32BE (int32 newValue) throw() { setAsFloatBE ((float) (newValue * (1.0 / (1.0 + maxValue)))); }

template <class SourceType> inline void copyFromLE (SourceType& source) throw() { setAsFloatLE (source.getAsFloat()); }
template <class SourceType> inline void copyFromBE (SourceType& source) throw() { setAsFloatBE (source.getAsFloat()); }
inline void copyFromSameType (Float32& source) throw() { *data = *source.data; }

float* data;
enum { maxValue = 0x7fffffff, resolution = 0x100, isFloat = 1 };
};

struct NonInterleaved
{
inline NonInterleaved () throw() {}
inline NonInterleaved (const int numChannels) throw()
{ jassert (numChannels == 1); } // If you hit this assert, you're trying to create a non-interleaved pointer with more than one interleaved channel..

template <class SampleFormatType> inline void advance (SampleFormatType& s) throw() { s.advance(); }
};

struct Interleaved
{
inline Interleaved () throw() : numChannels (1) {}
inline Interleaved (const int numChannels_) throw() : numChannels (numChannels_) {}
template <class SampleFormatType> inline void advance (SampleFormatType& s) throw() { s.skip (numChannels); }

const int numChannels;
};

template <class SampleFormat,
class Endianness,
class InterleavingType>
class Pointer
{
public:
Pointer (const void* sourceData)
: data (const_cast <void*> (sourceData))
{
}

Pointer (const void* sourceData, int numInterleavedChannels)
: data (const_cast <void*> (sourceData)),
interleaving (numInterleavedChannels)
{
}

inline float getAsFloat() const throw() { return Endianness::getAsFloat (data); }
inline void setAsFloat (float newValue) throw() { Endianness::setAsFloat (data, newValue); }

inline int32 getAsInt32() const throw() { return Endianness::getAsInt32 (data); }
inline void setAsInt32 (int32 newValue) throw() { Endianness::setAsInt32 (data, newValue); }

inline void advance() throw() { interleaving.advance (data); }

void copySamples (Pointer& source, int numSamples)
{
while (--numSamples >= 0)
{
data.copyFromSameType (source.data);
advance();
source.advance();
}
}

template <class OtherPointerType>
void copySamples (OtherPointerType& source, int numSamples)
{
while (--numSamples >= 0)
{
Endianness::copyFrom (data, source);
advance();
source.advance();
}
}

bool isFloatingPoint() const throw() { return (bool) SampleFormat::isFloat; }
static int get32BitResolution() throw() { return (int) SampleFormat::resolution; }

typedef Endianness EndiannessType;

private:

SampleFormat data;
InterleavingType interleaving;
};

class Converter
{
public:
virtual ~Converter() {}

virtual void copySamples (void* dest, const void* source, int numSamples) const = 0;
};

template <class SourceSampleType, class DestSampleType>
class ConverterInstance : public Converter
{
public:
ConverterInstance() {}
~ConverterInstance() {}

void copySamples (void* const dest, const void* const source, const int numSamples) const
{
SourceSampleType s (source);
DestSampleType d (dest);
d.copySamples (s, numSamples);
}

private:
ConverterInstance (const ConverterInstance&);
ConverterInstance& operator= (const ConverterInstance&);
};
};
*/

/**
A set of routines to convert buffers of 32-bit floating point data to and from
various integer formats.


+ 108
- 0
src/audio/dsp/juce_AudioDataConverters.cpp View File

@@ -531,5 +531,113 @@ void AudioDataConverters::deinterleaveSamples (const float* const source,
}
}
#if JUCE_UNIT_TESTS
#include "../../utilities/juce_UnitTest.h"
#include "../../core/juce_Random.h"
/*class AudioConversionTests : public UnitTest
{
public:
AudioConversionTests() : UnitTest ("Audio data conversion") {}
template <class SourceType, class DestType>
struct Test5
{
static void test (UnitTest& unitTest)
{
const int numSamples = 2048;
int32 original [numSamples], converted [numSamples], reversed [numSamples];
{
SourceType d (original);
for (int i = 0; i < numSamples / 2; ++i)
{
d.setAsFloat (Random::getSystemRandom().nextFloat() * 2.0f - 1.0f);
d.advance();
d.setAsInt32 (Random::getSystemRandom().nextInt());
d.advance();
}
}
// convert data from the source to dest format..
ScopedPointer<AudioData::Converter> conv (new AudioData::ConverterInstance <SourceType, DestType>());
conv->copySamples (converted, original, numSamples);
// ..and back again..
conv = new AudioData::ConverterInstance <DestType, SourceType>();
zerostruct (reversed);
conv->copySamples (reversed, converted, numSamples);
{
int biggestDiff = 0;
SourceType d1 (original);
SourceType d2 (reversed);
const int errorMargin = 2 * DestType::get32BitResolution() + SourceType::get32BitResolution();
for (int i = 0; i < numSamples; ++i)
{
biggestDiff = jmax (biggestDiff, std::abs (d1.getAsInt32() - d2.getAsInt32()));
d1.advance();
d2.advance();
}
unitTest.expect (biggestDiff <= errorMargin);
}
}
};
template <class SourceType, class FormatType>
struct Test3
{
static void test (UnitTest& unitTest)
{
Test5 <SourceType, AudioData::Pointer <FormatType, AudioData::BigEndian, AudioData::NonInterleaved> >::test (unitTest);
Test5 <SourceType, AudioData::Pointer <FormatType, AudioData::LittleEndian, AudioData::NonInterleaved> >::test (unitTest);
}
};
template <class SourceType>
struct Test2
{
static void test (UnitTest& unitTest)
{
Test3 <SourceType, AudioData::Int16>::test (unitTest);
Test3 <SourceType, AudioData::Int24>::test (unitTest);
Test3 <SourceType, AudioData::Int32>::test (unitTest);
Test3 <SourceType, AudioData::Float32>::test (unitTest);
Test3 <SourceType, AudioData::Int8>::test (unitTest);
}
};
template <class FormatType>
struct Test1
{
static void test (UnitTest& unitTest)
{
Test2 <AudioData::Pointer <FormatType, AudioData::BigEndian, AudioData::NonInterleaved> >::test (unitTest);
Test2 <AudioData::Pointer <FormatType, AudioData::LittleEndian, AudioData::NonInterleaved> >::test (unitTest);
}
};
void runTest()
{
beginTest ("Round-trip conversion");
Test1 <AudioData::Int8>::test (*this);
Test1 <AudioData::Int16>::test (*this);
Test1 <AudioData::Int24>::test (*this);
Test1 <AudioData::Int32>::test (*this);
Test1 <AudioData::Float32>::test (*this);
}
};
static AudioConversionTests audioConversionUnitTests;
*/
#endif
END_JUCE_NAMESPACE

+ 268
- 0
src/audio/dsp/juce_AudioDataConverters.h View File

@@ -26,6 +26,274 @@
#ifndef __JUCE_AUDIODATACONVERTERS_JUCEHEADER__
#define __JUCE_AUDIODATACONVERTERS_JUCEHEADER__
//==============================================================================
/**
*/
/*
struct JUCE_API AudioData
{
xxx need to add int range limiting..
//==============================================================================
struct BigEndian
{
template <class SampleFormatType> static inline float getAsFloat (SampleFormatType& s) throw() { return s.getAsFloatBE(); }
template <class SampleFormatType> static inline void setAsFloat (SampleFormatType& s, float newValue) throw() { s.setAsFloatBE (newValue); }
template <class SampleFormatType> static inline int32 getAsInt32 (SampleFormatType& s) throw() { return s.getAsInt32BE(); }
template <class SampleFormatType> static inline void setAsInt32 (SampleFormatType& s, int32 newValue) throw() { s.setAsInt32BE (newValue); }
template <class SourceType, class DestType> static inline void copyFrom (DestType& dest, SourceType& source) throw() { dest.copyFromBE (source); }
};
struct LittleEndian
{
template <class SampleFormatType> static inline float getAsFloat (SampleFormatType& s) throw() { return s.getAsFloatLE(); }
template <class SampleFormatType> static inline void setAsFloat (SampleFormatType& s, float newValue) throw() { s.setAsFloatLE (newValue); }
template <class SampleFormatType> static inline int32 getAsInt32 (SampleFormatType& s) throw() { return s.getAsInt32LE(); }
template <class SampleFormatType> static inline void setAsInt32 (SampleFormatType& s, int32 newValue) throw() { s.setAsInt32LE (newValue); }
template <class SourceType, class DestType> static inline void copyFrom (DestType& dest, SourceType& source) throw() { dest.copyFromLE (source); }
};
#if JUCE_BIG_ENDIAN
typedef BigEndian NativeEndian;
#else
typedef LittleEndian NativeEndian;
#endif
//==============================================================================
struct Int8
{
inline Int8 (void* data_) : data (static_cast <int8*> (data_)) {}
inline void advance() throw() { ++data; }
inline void skip (int numSamples) throw() { data += numSamples; }
inline float getAsFloatLE() const throw() { return (float) (*data * (1.0 / maxValue)); }
inline float getAsFloatBE() const throw() { return (float) (*data * (1.0 / maxValue)); }
inline void setAsFloatLE (float newValue) throw() { *data = (int8) roundToInt (newValue * (double) maxValue); }
inline void setAsFloatBE (float newValue) throw() { *data = (int8) roundToInt (newValue * (double) maxValue); }
inline int32 getAsInt32LE() const throw() { return (int) (*data << 24); }
inline int32 getAsInt32BE() const throw() { return (int) (*data << 24); }
inline void setAsInt32LE (int newValue) throw() { *data = (int8) (newValue >> 24); }
inline void setAsInt32BE (int newValue) throw() { *data = (int8) (newValue >> 24); }
template <class SourceType> inline void copyFromLE (SourceType& source) throw() { setAsInt32LE (source.getAsInt32()); }
template <class SourceType> inline void copyFromBE (SourceType& source) throw() { setAsInt32BE (source.getAsInt32()); }
inline void copyFromSameType (Int8& source) throw() { *data = *source.data; }
int8* data;
enum { maxValue = 0x80, resolution = 0x1000000, isFloat = 0 };
};
struct Int16
{
inline Int16 (void* data_) : data (static_cast <uint16*> (data_)) {}
inline void advance() throw() { ++data; }
inline void skip (int numSamples) throw() { data += numSamples; }
inline float getAsFloatLE() const throw() { return (float) ((1.0 / maxValue) * (int16) ByteOrder::swapIfBigEndian (*data)); }
inline float getAsFloatBE() const throw() { return (float) ((1.0 / maxValue) * (int16) ByteOrder::swapIfLittleEndian (*data)); }
inline void setAsFloatLE (float newValue) throw() { *data = ByteOrder::swapIfBigEndian ((uint16) roundToInt (newValue * (double) maxValue)); }
inline void setAsFloatBE (float newValue) throw() { *data = ByteOrder::swapIfLittleEndian ((uint16) roundToInt (newValue * (double) maxValue)); }
inline int32 getAsInt32LE() const throw() { return (int32) (ByteOrder::swapIfBigEndian ((uint16) *data) << 16); }
inline int32 getAsInt32BE() const throw() { return (int32) (ByteOrder::swapIfLittleEndian ((uint16) *data) << 16); }
inline void setAsInt32LE (int32 newValue) throw() { *data = ByteOrder::swapIfBigEndian ((uint16) (newValue >> 16)); }
inline void setAsInt32BE (int32 newValue) throw() { *data = ByteOrder::swapIfLittleEndian ((uint16) (newValue >> 16)); }
template <class SourceType> inline void copyFromLE (SourceType& source) throw() { setAsInt32LE (source.getAsInt32()); }
template <class SourceType> inline void copyFromBE (SourceType& source) throw() { setAsInt32BE (source.getAsInt32()); }
inline void copyFromSameType (Int16& source) throw() { *data = *source.data; }
uint16* data;
enum { maxValue = 0x8000, resolution = 0x10000, isFloat = 0 };
};
struct Int24
{
inline Int24 (void* data_) : data (static_cast <char*> (data_)) {}
inline void advance() throw() { data += 3; }
inline void skip (int numSamples) throw() { data += 3 * numSamples; }
inline float getAsFloatLE() const throw() { return (float) (ByteOrder::littleEndian24Bit (data) * (1.0 / maxValue)); }
inline float getAsFloatBE() const throw() { return (float) (ByteOrder::bigEndian24Bit (data) * (1.0 / maxValue)); }
inline void setAsFloatLE (float newValue) throw() { ByteOrder::littleEndian24BitToChars (roundToInt (newValue * (double) maxValue), data); }
inline void setAsFloatBE (float newValue) throw() { ByteOrder::bigEndian24BitToChars (roundToInt (newValue * (double) maxValue), data); }
inline int32 getAsInt32LE() const throw() { return (int32) ByteOrder::littleEndian24Bit (data) << 8; }
inline int32 getAsInt32BE() const throw() { return (int32) ByteOrder::bigEndian24Bit (data) << 8; }
inline void setAsInt32LE (int32 newValue) throw() { ByteOrder::littleEndian24BitToChars (newValue >> 8, data); }
inline void setAsInt32BE (int32 newValue) throw() { ByteOrder::bigEndian24BitToChars (newValue >> 8, data); }
template <class SourceType> inline void copyFromLE (SourceType& source) throw() { setAsInt32LE (source.getAsInt32()); }
template <class SourceType> inline void copyFromBE (SourceType& source) throw() { setAsInt32BE (source.getAsInt32()); }
inline void copyFromSameType (Int24& source) throw() { data[0] = source.data[0]; data[1] = source.data[1]; data[2] = source.data[2]; }
char* data;
enum { maxValue = 0x800000, resolution = 0x100, isFloat = 0 };
};
struct Int32
{
inline Int32 (void* data_) : data (static_cast <uint32*> (data_)) {}
inline void advance() throw() { ++data; }
inline void skip (int numSamples) throw() { data += numSamples; }
inline float getAsFloatLE() const throw() { return (float) ((1.0 / (1.0 + maxValue)) * (int32) ByteOrder::swapIfBigEndian (*data)); }
inline float getAsFloatBE() const throw() { return (float) ((1.0 / (1.0 + maxValue)) * (int32) ByteOrder::swapIfLittleEndian (*data)); }
inline void setAsFloatLE (float newValue) throw() { *data = ByteOrder::swapIfBigEndian ((uint32) roundToInt (newValue * (1.0 + maxValue))); }
inline void setAsFloatBE (float newValue) throw() { *data = ByteOrder::swapIfLittleEndian ((uint32) roundToInt (newValue * (1.0 + maxValue))); }
inline int32 getAsInt32LE() const throw() { return (int32) ByteOrder::swapIfBigEndian (*data); }
inline int32 getAsInt32BE() const throw() { return (int32) ByteOrder::swapIfLittleEndian (*data); }
inline void setAsInt32LE (int32 newValue) throw() { *data = ByteOrder::swapIfBigEndian ((uint32) newValue); }
inline void setAsInt32BE (int32 newValue) throw() { *data = ByteOrder::swapIfLittleEndian ((uint32) newValue); }
template <class SourceType> inline void copyFromLE (SourceType& source) throw() { setAsInt32LE (source.getAsInt32()); }
template <class SourceType> inline void copyFromBE (SourceType& source) throw() { setAsInt32BE (source.getAsInt32()); }
inline void copyFromSameType (Int32& source) throw() { *data = *source.data; }
uint32* data;
enum { maxValue = 0x7fffffff, resolution = 1, isFloat = 0 };
};
struct Float32
{
inline Float32 (void* data_) : data (static_cast <float*> (data_)) {}
inline void advance() throw() { ++data; }
inline void skip (int numSamples) throw() { data += numSamples; }
#if JUCE_BIG_ENDIAN
inline float getAsFloatBE() const throw() { return *data; }
inline void setAsFloatBE (float newValue) throw() { *data = newValue; }
inline float getAsFloatLE() const throw() { union { uint32 asInt; float asFloat; } n; n.asInt = ByteOrder::swap (*(uint32*) data); return n.asFloat; }
inline void setAsFloatLE (float newValue) throw() { union { uint32 asInt; float asFloat; } n; n.asFloat = newValue; *(uint32*) data = ByteOrder::swap (n.asInt); }
#else
inline float getAsFloatLE() const throw() { return *data; }
inline void setAsFloatLE (float newValue) throw() { *data = newValue; }
inline float getAsFloatBE() const throw() { union { uint32 asInt; float asFloat; } n; n.asInt = ByteOrder::swap (*(uint32*) data); return n.asFloat; }
inline void setAsFloatBE (float newValue) throw() { union { uint32 asInt; float asFloat; } n; n.asFloat = newValue; *(uint32*) data = ByteOrder::swap (n.asInt); }
#endif
inline int32 getAsInt32LE() const throw() { return (int32) roundToInt (getAsFloatLE() * (1.0 + maxValue)); }
inline int32 getAsInt32BE() const throw() { return (int32) roundToInt (getAsFloatBE() * (1.0 + maxValue)); }
inline void setAsInt32LE (int32 newValue) throw() { setAsFloatLE ((float) (newValue * (1.0 / (1.0 + maxValue)))); }
inline void setAsInt32BE (int32 newValue) throw() { setAsFloatBE ((float) (newValue * (1.0 / (1.0 + maxValue)))); }
template <class SourceType> inline void copyFromLE (SourceType& source) throw() { setAsFloatLE (source.getAsFloat()); }
template <class SourceType> inline void copyFromBE (SourceType& source) throw() { setAsFloatBE (source.getAsFloat()); }
inline void copyFromSameType (Float32& source) throw() { *data = *source.data; }
float* data;
enum { maxValue = 0x7fffffff, resolution = 0x100, isFloat = 1 };
};
//==============================================================================
struct NonInterleaved
{
inline NonInterleaved () throw() {}
inline NonInterleaved (const int numChannels) throw()
{ jassert (numChannels == 1); } // If you hit this assert, you're trying to create a non-interleaved pointer with more than one interleaved channel..
template <class SampleFormatType> inline void advance (SampleFormatType& s) throw() { s.advance(); }
};
struct Interleaved
{
inline Interleaved () throw() : numChannels (1) {}
inline Interleaved (const int numChannels_) throw() : numChannels (numChannels_) {}
template <class SampleFormatType> inline void advance (SampleFormatType& s) throw() { s.skip (numChannels); }
const int numChannels;
};
//==============================================================================
template <class SampleFormat,
class Endianness,
class InterleavingType>
class Pointer
{
public:
Pointer (const void* sourceData)
: data (const_cast <void*> (sourceData))
{
}
Pointer (const void* sourceData, int numInterleavedChannels)
: data (const_cast <void*> (sourceData)),
interleaving (numInterleavedChannels)
{
}
//==============================================================================
inline float getAsFloat() const throw() { return Endianness::getAsFloat (data); }
inline void setAsFloat (float newValue) throw() { Endianness::setAsFloat (data, newValue); }
inline int32 getAsInt32() const throw() { return Endianness::getAsInt32 (data); }
inline void setAsInt32 (int32 newValue) throw() { Endianness::setAsInt32 (data, newValue); }
inline void advance() throw() { interleaving.advance (data); }
void copySamples (Pointer& source, int numSamples)
{
while (--numSamples >= 0)
{
data.copyFromSameType (source.data);
advance();
source.advance();
}
}
template <class OtherPointerType>
void copySamples (OtherPointerType& source, int numSamples)
{
while (--numSamples >= 0)
{
Endianness::copyFrom (data, source);
advance();
source.advance();
}
}
bool isFloatingPoint() const throw() { return (bool) SampleFormat::isFloat; }
static int get32BitResolution() throw() { return (int) SampleFormat::resolution; }
typedef Endianness EndiannessType;
private:
//==============================================================================
SampleFormat data;
InterleavingType interleaving;
};
//==============================================================================
class Converter
{
public:
virtual ~Converter() {}
virtual void copySamples (void* dest, const void* source, int numSamples) const = 0;
};
//==============================================================================
template <class SourceSampleType, class DestSampleType>
class ConverterInstance : public Converter
{
public:
ConverterInstance() {}
~ConverterInstance() {}
void copySamples (void* const dest, const void* const source, const int numSamples) const
{
SourceSampleType s (source);
DestSampleType d (dest);
d.copySamples (s, numSamples);
}
private:
ConverterInstance (const ConverterInstance&);
ConverterInstance& operator= (const ConverterInstance&);
};
};
*/
//==============================================================================
/**


+ 1
- 1
src/core/juce_StandardHeader.h View File

@@ -33,7 +33,7 @@
*/
#define JUCE_MAJOR_VERSION 1
#define JUCE_MINOR_VERSION 52
#define JUCE_BUILDNUMBER 67
#define JUCE_BUILDNUMBER 68
/** Current Juce version number.


+ 17
- 9
src/native/common/juce_posix_SharedCode.h View File

@@ -220,15 +220,25 @@ bool File::setAsCurrentWorkingDirectory() const
}
//==============================================================================
static bool juce_stat (const String& fileName, struct stat& info)
#if JUCE_IOS
typedef struct stat64 juce_statStruct; // (need to use the 64-bit version to work around a simulator bug)
#else
typedef struct stat juce_statStruct;
#endif
static bool juce_stat (const String& fileName, juce_statStruct& info)
{
return fileName.isNotEmpty()
#if JUCE_IOS
&& (stat64 (fileName.toUTF8(), &info) == 0);
#else
&& (stat (fileName.toUTF8(), &info) == 0);
#endif
}
bool File::isDirectory() const
{
struct stat info;
juce_statStruct info;
return fullPath.isEmpty()
|| (juce_stat (fullPath, info) && ((info.st_mode & S_IFDIR) != 0));
@@ -247,7 +257,7 @@ bool File::existsAsFile() const
int64 File::getSize() const
{
struct stat info;
juce_statStruct info;
return juce_stat (fullPath, info) ? info.st_size : 0;
}
@@ -265,9 +275,8 @@ bool File::hasWriteAccess() const
bool File::setFileReadOnlyInternal (const bool shouldBeReadOnly) const
{
struct stat info;
const int res = stat (fullPath.toUTF8(), &info);
if (res != 0)
juce_statStruct info;
if (! juce_stat (fullPath, info))
return false;
info.st_mode &= 0777; // Just permissions
@@ -287,9 +296,8 @@ void File::getFileTimesInternal (int64& modificationTime, int64& accessTime, int
accessTime = 0;
creationTime = 0;
struct stat info;
const int res = stat (fullPath.toUTF8(), &info);
if (res == 0)
juce_statStruct info;
if (juce_stat (fullPath, info))
{
modificationTime = (int64) info.st_mtime * 1000;
accessTime = (int64) info.st_atime * 1000;


+ 3
- 1
src/native/mac/juce_mac_CoreGraphicsContext.mm View File

@@ -779,7 +779,9 @@ const Image juce_loadWithCoreImage (InputStream& input)
#if JUCE_IOS
JUCE_AUTORELEASEPOOL
UIImage* image = [UIImage imageWithData: [NSData dataWithBytesNoCopy: data.getData() length: data.getSize()]];
UIImage* image = [UIImage imageWithData: [NSData dataWithBytesNoCopy: data.getData()
length: data.getSize()
freeWhenDone: NO]];
if (image != nil)
{


+ 1
- 1
src/native/mac/juce_mac_Files.mm View File

@@ -309,7 +309,7 @@ public:
if (isDir != 0 || fileSize != 0 || modTime != 0 || creationTime != 0)
{
struct stat info;
juce_statStruct info;
const bool statOk = juce_stat (path, info);
if (isDir != 0) *isDir = statOk && ((info.st_mode & S_IFDIR) != 0);


Loading…
Cancel
Save