Optimizations to ma_interleave_pcm_frames().

This commit is contained in:
David Reid
2026-02-16 06:52:12 +10:00
parent 6851858937
commit e490db3085
2 changed files with 336 additions and 22 deletions
+152 -6
View File
@@ -52901,8 +52901,8 @@ MA_API void ma_deinterleave_pcm_frames(ma_format format, ma_uint32 channels, ma_
/*
You shouldn't really be calling this for mono streams, but I can imagine a situation where it is called
generically without the caller explicitly checking the channel count. We'll implement this in as a
memcpy() to keep it fast.
generically without the caller explicitly checking the channel count. We'll implement this as a memcpy()
to keep it fast.
*/
if (channels == 1) {
MA_COPY_MEMORY(ppDeinterleavedPCMFrames[0], pInterleavedPCMFrames, frameCount * ma_get_bytes_per_frame(format, channels));
@@ -53170,15 +53170,76 @@ MA_API void ma_deinterleave_pcm_frames(ma_format format, ma_uint32 channels, ma_
MA_API void ma_interleave_pcm_frames(ma_format format, ma_uint32 channels, ma_uint64 frameCount, const void** ppDeinterleavedPCMFrames, void* pInterleavedPCMFrames)
{
if (ppDeinterleavedPCMFrames == NULL || pInterleavedPCMFrames == NULL) {
return; /* Invalid args. */
}
/*
You shouldn't really be calling this for mono streams, but I can imagine a situation where it is called
generically without the caller explicitly checking the channel count. We'll implement this as a memcpy()
to keep it fast.
*/
if (channels == 1) {
MA_COPY_MEMORY(pInterleavedPCMFrames, ppDeinterleavedPCMFrames[0], frameCount * ma_get_bytes_per_frame(format, channels));
return;
}
switch (format)
{
case ma_format_u8:
{
ma_uint8* pDstU8 = (ma_uint8*)pInterleavedPCMFrames;
ma_uint64 iPCMFrame;
iPCMFrame = 0;
/* Specialization for stereo. */
if (channels == 2) {
const ma_uint8* pSrcU8_0 = (const ma_uint8*)ppDeinterleavedPCMFrames[0];
const ma_uint8* pSrcU8_1 = (const ma_uint8*)ppDeinterleavedPCMFrames[1];
ma_uint8* pDstU8Running = (ma_uint8*)pDstU8;
for (iPCMFrame = 0; iPCMFrame < frameCount; iPCMFrame += 1) {
pDstU8Running[0] = pSrcU8_0[iPCMFrame];
pDstU8Running[1] = pSrcU8_1[iPCMFrame];
pDstU8Running += 2;
}
}
for (; iPCMFrame < frameCount; iPCMFrame += 1) {
ma_uint32 iChannel;
for (iChannel = 0; iChannel < channels; iChannel += 1) {
const ma_uint8* pSrcU8 = (const ma_uint8*)ppDeinterleavedPCMFrames[iChannel];
pDstU8[iPCMFrame*channels+iChannel] = pSrcU8[iPCMFrame];
}
}
} break;
case ma_format_s16:
{
ma_int16* pDstS16 = (ma_int16*)pInterleavedPCMFrames;
ma_uint64 iPCMFrame;
for (iPCMFrame = 0; iPCMFrame < frameCount; ++iPCMFrame) {
iPCMFrame = 0;
/* Specialization for stereo. */
if (channels == 2) {
const ma_int16* pSrcS16_0 = (const ma_int16*)ppDeinterleavedPCMFrames[0];
const ma_int16* pSrcS16_1 = (const ma_int16*)ppDeinterleavedPCMFrames[1];
ma_int16* pDstS16Running = (ma_int16*)pDstS16;
for (iPCMFrame = 0; iPCMFrame < frameCount; iPCMFrame += 1) {
pDstS16Running[0] = pSrcS16_0[iPCMFrame];
pDstS16Running[1] = pSrcS16_1[iPCMFrame];
pDstS16Running += 2;
}
}
for (; iPCMFrame < frameCount; iPCMFrame += 1) {
ma_uint32 iChannel;
for (iChannel = 0; iChannel < channels; ++iChannel) {
for (iChannel = 0; iChannel < channels; iChannel += 1) {
const ma_int16* pSrcS16 = (const ma_int16*)ppDeinterleavedPCMFrames[iChannel];
pDstS16[iPCMFrame*channels+iChannel] = pSrcS16[iPCMFrame];
}
@@ -53189,15 +53250,100 @@ MA_API void ma_interleave_pcm_frames(ma_format format, ma_uint32 channels, ma_ui
{
float* pDstF32 = (float*)pInterleavedPCMFrames;
ma_uint64 iPCMFrame;
for (iPCMFrame = 0; iPCMFrame < frameCount; ++iPCMFrame) {
iPCMFrame = 0;
/* Specialization for stereo. */
if (channels == 2) {
const float* pSrcF32_0 = (const float*)ppDeinterleavedPCMFrames[0];
const float* pSrcF32_1 = (const float*)ppDeinterleavedPCMFrames[1];
float* pDstF32Running = (float*)pDstF32;
for (iPCMFrame = 0; iPCMFrame < frameCount; iPCMFrame += 1) {
pDstF32Running[0] = pSrcF32_0[iPCMFrame];
pDstF32Running[1] = pSrcF32_1[iPCMFrame];
pDstF32Running += 2;
}
}
for (; iPCMFrame < frameCount; iPCMFrame += 1) {
ma_uint32 iChannel;
for (iChannel = 0; iChannel < channels; ++iChannel) {
for (iChannel = 0; iChannel < channels; iChannel += 1) {
const float* pSrcF32 = (const float*)ppDeinterleavedPCMFrames[iChannel];
pDstF32[iPCMFrame*channels+iChannel] = pSrcF32[iPCMFrame];
}
}
} break;
case ma_format_s32:
{
ma_int32* pDstS32 = (ma_int32*)pInterleavedPCMFrames;
ma_uint64 iPCMFrame;
iPCMFrame = 0;
/* Specialization for stereo. */
if (channels == 2) {
const ma_uint32* pSrcU32_0 = (const ma_uint32*)ppDeinterleavedPCMFrames[0];
const ma_uint32* pSrcU32_1 = (const ma_uint32*)ppDeinterleavedPCMFrames[1];
ma_uint32* pDstU32Running = (ma_uint32*)pDstS32;
for (iPCMFrame = 0; iPCMFrame < frameCount; iPCMFrame += 1) {
pDstU32Running[0] = pSrcU32_0[iPCMFrame];
pDstU32Running[1] = pSrcU32_1[iPCMFrame];
pDstU32Running += 2;
}
}
for (; iPCMFrame < frameCount; iPCMFrame += 1) {
ma_uint32 iChannel;
for (iChannel = 0; iChannel < channels; iChannel += 1) {
const ma_int32* pSrcS32 = (const ma_int32*)ppDeinterleavedPCMFrames[iChannel];
pDstS32[iPCMFrame*channels+iChannel] = pSrcS32[iPCMFrame];
}
}
} break;
case ma_format_s24:
{
ma_uint8* pDstS24 = (ma_uint8*)pInterleavedPCMFrames;
ma_uint64 iPCMFrame;
iPCMFrame = 0;
if (channels == 2) {
const ma_uint8* pSrcS24_0 = (const ma_uint8*)ppDeinterleavedPCMFrames[0];
const ma_uint8* pSrcS24_1 = (const ma_uint8*)ppDeinterleavedPCMFrames[1];
ma_uint8* pDstS24Running = (ma_uint8*)pDstS24;
for (; iPCMFrame < frameCount; iPCMFrame += 1) {
pDstS24Running[0] = pSrcS24_0[0];
pDstS24Running[1] = pSrcS24_0[1];
pDstS24Running[2] = pSrcS24_0[2];
pDstS24Running[3] = pSrcS24_1[0];
pDstS24Running[4] = pSrcS24_1[1];
pDstS24Running[5] = pSrcS24_1[2];
pDstS24Running += 6;
pSrcS24_0 += 3;
pSrcS24_1 += 3;
}
}
for (; iPCMFrame < frameCount; iPCMFrame += 1) {
ma_uint32 iChannel;
for (iChannel = 0; iChannel < channels; iChannel += 1) {
const ma_uint8* pSrcS24 = (const ma_uint8*)ppDeinterleavedPCMFrames[iChannel];
pDstS24[(iPCMFrame*channels+iChannel)*3 + 0] = pSrcS24[iPCMFrame*3 + 0];
pDstS24[(iPCMFrame*channels+iChannel)*3 + 1] = pSrcS24[iPCMFrame*3 + 1];
pDstS24[(iPCMFrame*channels+iChannel)*3 + 2] = pSrcS24[iPCMFrame*3 + 2];
}
}
} break;
default:
{
ma_uint32 sampleSizeInBytes = ma_get_bytes_per_sample(format);