| @@ -71,9 +71,9 @@ public: | |||
| { | |||
| public: | |||
| template <class SampleFormatType> static inline float getAsFloat (SampleFormatType& s) noexcept { return s.getAsFloatBE(); } | |||
| template <class SampleFormatType> static inline void setAsFloat (SampleFormatType& s, float newValue) noexcept { s.setAsFloatBE (newValue); } | |||
| template <class SampleFormatType> static inline void setAsFloat (SampleFormatType& s, float newValue) noexcept { s.setAsFloatBE (newValue); } | |||
| template <class SampleFormatType> static inline int32 getAsInt32 (SampleFormatType& s) noexcept { return s.getAsInt32BE(); } | |||
| template <class SampleFormatType> static inline void setAsInt32 (SampleFormatType& s, int32 newValue) noexcept { s.setAsInt32BE (newValue); } | |||
| template <class SampleFormatType> static inline void setAsInt32 (SampleFormatType& s, int32 newValue) noexcept { s.setAsInt32BE (newValue); } | |||
| template <class SourceType, class DestType> static inline void copyFrom (DestType& dest, SourceType& source) noexcept { dest.copyFromBE (source); } | |||
| enum { isBigEndian = 1 }; | |||
| }; | |||
| @@ -82,9 +82,9 @@ public: | |||
| { | |||
| public: | |||
| template <class SampleFormatType> static inline float getAsFloat (SampleFormatType& s) noexcept { return s.getAsFloatLE(); } | |||
| template <class SampleFormatType> static inline void setAsFloat (SampleFormatType& s, float newValue) noexcept { s.setAsFloatLE (newValue); } | |||
| template <class SampleFormatType> static inline void setAsFloat (SampleFormatType& s, float newValue) noexcept { s.setAsFloatLE (newValue); } | |||
| template <class SampleFormatType> static inline int32 getAsInt32 (SampleFormatType& s) noexcept { return s.getAsInt32LE(); } | |||
| template <class SampleFormatType> static inline void setAsInt32 (SampleFormatType& s, int32 newValue) noexcept { s.setAsInt32LE (newValue); } | |||
| template <class SampleFormatType> static inline void setAsInt32 (SampleFormatType& s, int32 newValue) noexcept { s.setAsInt32LE (newValue); } | |||
| template <class SourceType, class DestType> static inline void copyFrom (DestType& dest, SourceType& source) noexcept { dest.copyFromLE (source); } | |||
| enum { isBigEndian = 0 }; | |||
| }; | |||
| @@ -205,11 +205,11 @@ public: | |||
| inline void skip (int numSamples) noexcept { data += numSamples; } | |||
| inline float getAsFloatLE() const noexcept { return (float) ((1.0 / (1.0 + maxValue)) * (int32) ByteOrder::swapIfBigEndian (*data)); } | |||
| inline float getAsFloatBE() const noexcept { return (float) ((1.0 / (1.0 + maxValue)) * (int32) ByteOrder::swapIfLittleEndian (*data)); } | |||
| inline void setAsFloatLE (float newValue) noexcept { *data = ByteOrder::swapIfBigEndian ((uint32) (maxValue * jlimit (-1.0, 1.0, (double) newValue))); } | |||
| inline void setAsFloatLE (float newValue) noexcept { *data = ByteOrder::swapIfBigEndian ((uint32) (maxValue * jlimit (-1.0, 1.0, (double) newValue))); } | |||
| inline void setAsFloatBE (float newValue) noexcept { *data = ByteOrder::swapIfLittleEndian ((uint32) (maxValue * jlimit (-1.0, 1.0, (double) newValue))); } | |||
| inline int32 getAsInt32LE() const noexcept { return (int32) ByteOrder::swapIfBigEndian (*data); } | |||
| inline int32 getAsInt32LE() const noexcept { return (int32) ByteOrder::swapIfBigEndian (*data); } | |||
| inline int32 getAsInt32BE() const noexcept { return (int32) ByteOrder::swapIfLittleEndian (*data); } | |||
| inline void setAsInt32LE (int32 newValue) noexcept { *data = ByteOrder::swapIfBigEndian ((uint32) newValue); } | |||
| inline void setAsInt32LE (int32 newValue) noexcept { *data = ByteOrder::swapIfBigEndian ((uint32) newValue); } | |||
| inline void setAsInt32BE (int32 newValue) noexcept { *data = ByteOrder::swapIfLittleEndian ((uint32) newValue); } | |||
| inline void clear() noexcept { *data = 0; } | |||
| inline void clearMultiple (int num) noexcept { zeromem (data, (size_t) (num * bytesPerSample)) ;} | |||
| @@ -221,6 +221,27 @@ public: | |||
| enum { bytesPerSample = 4, maxValue = 0x7fffffff, resolution = 1, isFloat = 0 }; | |||
| }; | |||
| /** A 32-bit integer type, of which only the bottom 24 bits are used. */ | |||
| class Int24in32 : public Int32 | |||
| { | |||
| public: | |||
| inline Int24in32 (void* d) noexcept : Int32 (d) {} | |||
| inline float getAsFloatLE() const noexcept { return (float) ((1.0 / (1.0 + maxValue)) * (int32) ByteOrder::swapIfBigEndian (*data)); } | |||
| inline float getAsFloatBE() const noexcept { return (float) ((1.0 / (1.0 + maxValue)) * (int32) ByteOrder::swapIfLittleEndian (*data)); } | |||
| inline void setAsFloatLE (float newValue) noexcept { *data = ByteOrder::swapIfBigEndian ((uint32) (maxValue * jlimit (-1.0, 1.0, (double) newValue))); } | |||
| inline void setAsFloatBE (float newValue) noexcept { *data = ByteOrder::swapIfLittleEndian ((uint32) (maxValue * jlimit (-1.0, 1.0, (double) newValue))); } | |||
| inline int32 getAsInt32LE() const noexcept { return (int32) ByteOrder::swapIfBigEndian (*data) << 8; } | |||
| inline int32 getAsInt32BE() const noexcept { return (int32) ByteOrder::swapIfLittleEndian (*data) << 8; } | |||
| inline void setAsInt32LE (int32 newValue) noexcept { *data = ByteOrder::swapIfBigEndian ((uint32) newValue >> 8); } | |||
| inline void setAsInt32BE (int32 newValue) noexcept { *data = ByteOrder::swapIfLittleEndian ((uint32) newValue >> 8); } | |||
| template <class SourceType> inline void copyFromLE (SourceType& source) noexcept { setAsInt32LE (source.getAsInt32()); } | |||
| template <class SourceType> inline void copyFromBE (SourceType& source) noexcept { setAsInt32BE (source.getAsInt32()); } | |||
| inline void copyFromSameType (Int24in32& source) noexcept { *data = *source.data; } | |||
| enum { bytesPerSample = 4, maxValue = 0x7fffff, resolution = (1 << 8), isFloat = 0 }; | |||
| }; | |||
| class Float32 | |||
| { | |||
| public: | |||
| @@ -591,9 +612,7 @@ public: | |||
| : sourceChannels (numSourceChannels), destChannels (numDestChannels) | |||
| {} | |||
| ~ConverterInstance() {} | |||
| void convertSamples (void* dest, const void* source, int numSamples) const | |||
| void convertSamples (void* dest, const void* source, int numSamples) const override | |||
| { | |||
| SourceSampleType s (source, sourceChannels); | |||
| DestSampleType d (dest, destChannels); | |||
| @@ -601,7 +620,7 @@ public: | |||
| } | |||
| void convertSamples (void* dest, int destSubChannel, | |||
| const void* source, int sourceSubChannel, int numSamples) const | |||
| const void* source, int sourceSubChannel, int numSamples) const override | |||
| { | |||
| jassert (destSubChannel < destChannels && sourceSubChannel < sourceChannels); | |||
| @@ -211,7 +211,7 @@ public: | |||
| return false; | |||
| } | |||
| enum { isFloatBit = 1 << 16, isLittleEndianBit = 1 << 17 }; | |||
| enum { isFloatBit = 1 << 16, isLittleEndianBit = 1 << 17, onlyUseLower24Bits = 1 << 18 }; | |||
| const int formatsToTry[] = { SND_PCM_FORMAT_FLOAT_LE, 32 | isFloatBit | isLittleEndianBit, | |||
| SND_PCM_FORMAT_FLOAT_BE, 32 | isFloatBit, | |||
| @@ -219,6 +219,7 @@ public: | |||
| SND_PCM_FORMAT_S32_BE, 32, | |||
| SND_PCM_FORMAT_S24_3LE, 24 | isLittleEndianBit, | |||
| SND_PCM_FORMAT_S24_3BE, 24, | |||
| SND_PCM_FORMAT_S24_LE, 32 | isLittleEndianBit | onlyUseLower24Bits, | |||
| SND_PCM_FORMAT_S16_LE, 16 | isLittleEndianBit, | |||
| SND_PCM_FORMAT_S16_BE, 16 }; | |||
| bitDepth = 0; | |||
| @@ -227,14 +228,14 @@ public: | |||
| { | |||
| if (snd_pcm_hw_params_set_format (handle, hwParams, (_snd_pcm_format) formatsToTry [i]) >= 0) | |||
| { | |||
| bitDepth = formatsToTry [i + 1] & 255; | |||
| const bool isFloat = (formatsToTry [i + 1] & isFloatBit) != 0; | |||
| const bool isLittleEndian = (formatsToTry [i + 1] & isLittleEndianBit) != 0; | |||
| converter = createConverter (isInput, bitDepth, isFloat, isLittleEndian, numChannels); | |||
| JUCE_ALSA_LOG ("format: bitDepth=" << bitDepth << ", isFloat=" | |||
| << isFloat << ", isLittleEndian=" << isLittleEndian | |||
| << ", numChannels=" << numChannels); | |||
| const int type = formatsToTry [i + 1]; | |||
| bitDepth = type & 255; | |||
| converter = createConverter (isInput, bitDepth, | |||
| (type & isFloatBit) != 0, | |||
| (type & isLittleEndianBit) != 0, | |||
| (type & onlyUseLower24Bits) != 0, | |||
| numChannels); | |||
| break; | |||
| } | |||
| } | |||
| @@ -397,30 +398,33 @@ private: | |||
| return new AudioData::ConverterInstance <AudioData::Pointer <SampleType, AudioData::BigEndian, AudioData::Interleaved, AudioData::Const>, DestType> (numInterleavedChannels, 1); | |||
| } | |||
| else | |||
| { | |||
| typedef AudioData::Pointer <AudioData::Float32, AudioData::NativeEndian, AudioData::NonInterleaved, AudioData::Const> SourceType; | |||
| if (isLittleEndian) | |||
| return new AudioData::ConverterInstance <SourceType, AudioData::Pointer <SampleType, AudioData::LittleEndian, AudioData::Interleaved, AudioData::NonConst> > (1, numInterleavedChannels); | |||
| typedef AudioData::Pointer <AudioData::Float32, AudioData::NativeEndian, AudioData::NonInterleaved, AudioData::Const> SourceType; | |||
| return new AudioData::ConverterInstance <SourceType, AudioData::Pointer <SampleType, AudioData::BigEndian, AudioData::Interleaved, AudioData::NonConst> > (1, numInterleavedChannels); | |||
| } | |||
| if (isLittleEndian) | |||
| return new AudioData::ConverterInstance <SourceType, AudioData::Pointer <SampleType, AudioData::LittleEndian, AudioData::Interleaved, AudioData::NonConst> > (1, numInterleavedChannels); | |||
| return new AudioData::ConverterInstance <SourceType, AudioData::Pointer <SampleType, AudioData::BigEndian, AudioData::Interleaved, AudioData::NonConst> > (1, numInterleavedChannels); | |||
| } | |||
| }; | |||
| static AudioData::Converter* createConverter (const bool forInput, const int bitDepth, const bool isFloat, const bool isLittleEndian, const int numInterleavedChannels) | |||
| static AudioData::Converter* createConverter (bool forInput, int bitDepth, | |||
| bool isFloat, bool isLittleEndian, bool useOnlyLower24Bits, | |||
| int numInterleavedChannels) | |||
| { | |||
| switch (bitDepth) | |||
| { | |||
| case 16: return ConverterHelper <AudioData::Int16>::createConverter (forInput, isLittleEndian, numInterleavedChannels); | |||
| case 24: return ConverterHelper <AudioData::Int24>::createConverter (forInput, isLittleEndian, numInterleavedChannels); | |||
| case 32: return isFloat ? ConverterHelper <AudioData::Float32>::createConverter (forInput, isLittleEndian, numInterleavedChannels) | |||
| : ConverterHelper <AudioData::Int32>::createConverter (forInput, isLittleEndian, numInterleavedChannels); | |||
| default: jassertfalse; break; // unsupported format! | |||
| } | |||
| JUCE_ALSA_LOG ("format: bitDepth=" << bitDepth << ", isFloat=" << isFloat | |||
| << ", isLittleEndian=" << isLittleEndian << ", numChannels=" << numInterleavedChannels); | |||
| return nullptr; | |||
| if (isFloat) return ConverterHelper <AudioData::Float32>::createConverter (forInput, isLittleEndian, numInterleavedChannels); | |||
| if (bitDepth == 16) return ConverterHelper <AudioData::Int16> ::createConverter (forInput, isLittleEndian, numInterleavedChannels); | |||
| if (bitDepth == 24) return ConverterHelper <AudioData::Int24> ::createConverter (forInput, isLittleEndian, numInterleavedChannels); | |||
| jassert (bitDepth == 32); | |||
| if (useOnlyLower24Bits) | |||
| return ConverterHelper <AudioData::Int24in32>::createConverter (forInput, isLittleEndian, numInterleavedChannels); | |||
| return ConverterHelper <AudioData::Int32>::createConverter (forInput, isLittleEndian, numInterleavedChannels); | |||
| } | |||
| //============================================================================== | |||