Browse Source

ALSA: added support for SND_PCM_FORMAT_S24_LE devices.

tags/2021-05-28
jules 12 years ago
parent
commit
69dcde0f4d
2 changed files with 60 additions and 37 deletions
  1. +30
    -11
      modules/juce_audio_basics/buffers/juce_AudioDataConverters.h
  2. +30
    -26
      modules/juce_audio_devices/native/juce_linux_ALSA.cpp

+ 30
- 11
modules/juce_audio_basics/buffers/juce_AudioDataConverters.h View File

@@ -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);


+ 30
- 26
modules/juce_audio_devices/native/juce_linux_ALSA.cpp View File

@@ -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);
}
//==============================================================================


Loading…
Cancel
Save