I am writing a QT multimedia audio test application. As part of the application, I need to process each audio sample from the microphone directly. The audio source device signals QAudioBuffer's at regular capture intervals containing audio data in different formats, I am having trouble converging the QAudioFormat::SampleFormat::FLoat format to QAudioFormat::SampleFormat::Int32 but I am not sure how. The float values are 32 bit IEEE floats. The code below shows my in place conversion to 24 bit PCM audio. Note that I am actually converting to big endian as the datagrams containing the audio data are for RTP packets which need to be in big endian order.
// sample conversion
void
in_place_reorder(std::span<uint8_t> buffer, const QAudioFormat& rFormat)
{
if constexpr (std::endian::native == std::endian::little) {
switch (rFormat.sampleFormat()) {
case QAudioFormat::Float:
{
// IEEE 32 bit float
const auto audio_float = std::span<float>{
reinterpret_cast<float*>(buffer.data()),
buffer.size_bytes() >> 2
};
auto audio_int32 = std::span<uint32_t>{
reinterpret_cast<uint32_t*>(buffer.data()),
buffer.size_bytes() >> 2
};
for (auto i=0u; i<audio_float.size(); ++i) {
const auto temp = audio_float[i] * (1<<23);
//temp *= (1 << 23);
audio_int32[i] = std::byteswap(
static_cast<int32_t>(temp));
}
}
break;
case QAudioFormat::Int32:
{
// signed pcm32 or float (32 bit)
auto audio = std::span<uint32_t>{
reinterpret_cast<uint32_t*>(buffer.data()),
buffer.size_bytes()>>2
};
// convert 32 bit audio to 24 bit (with MSByte set to 0's)
for (auto& next : audio) {
// native math before byte swapping
next >>= 8;
next = std::byteswap(next);
}
}
break;
case QAudioFormat::Unknown:
{
// APT-X audio 3 byte packed
for (auto i = 0u; i < buffer.size_bytes(); i+=3) {
std::swap(buffer[i], buffer[i + 2]);
}
}
break;
case QAudioFormat::SampleFormat::Int16:
{
auto audio = std::span<uint16_t>{
reinterpret_cast<uint16_t*>(buffer.data()),
buffer.size_bytes()>>1
};
for (auto& next : audio) {
next = std::byteswap(next);
}
}
break;
case QAudioFormat::UInt8:
case QAudioFormat::NSampleFormats:
default:
break;
}
}
};