mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-11 23:54:18 +00:00
ALSA: added support for SND_PCM_FORMAT_S24_LE devices.
This commit is contained in:
parent
0b32caaaf0
commit
69dcde0f4d
2 changed files with 59 additions and 36 deletions
|
|
@ -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);
|
||||
const int type = formatsToTry [i + 1];
|
||||
bitDepth = type & 255;
|
||||
|
||||
JUCE_ALSA_LOG ("format: bitDepth=" << bitDepth << ", isFloat="
|
||||
<< isFloat << ", isLittleEndian=" << isLittleEndian
|
||||
<< ", numChannels=" << numChannels);
|
||||
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);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue