mirror of
https://github.com/mackron/miniaudio.git
synced 2026-04-22 00:06:59 +02:00
Fix some bugs with interleaving/deinterleaving.
This commit is contained in:
@@ -689,6 +689,34 @@ typedef struct
|
|||||||
} mal_timer;
|
} mal_timer;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct mal_format_converter mal_format_converter;
|
||||||
|
typedef mal_uint32 (* mal_format_converter_read_proc) (mal_format_converter* pConverter, mal_uint32 frameCount, void* pFramesOut, void* pUserData);
|
||||||
|
typedef mal_uint32 (* mal_format_converter_read_separated_proc)(mal_format_converter* pConverter, mal_uint32 frameCount, void** ppSamplesOut, void* pUserData);
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
mal_format formatIn;
|
||||||
|
mal_format formatOut;
|
||||||
|
mal_uint32 channels;
|
||||||
|
mal_stream_format streamFormatIn;
|
||||||
|
mal_stream_format streamFormatOut;
|
||||||
|
mal_dither_mode ditherMode;
|
||||||
|
} mal_format_converter_config;
|
||||||
|
|
||||||
|
struct mal_format_converter
|
||||||
|
{
|
||||||
|
mal_format_converter_config config;
|
||||||
|
mal_format_converter_read_proc onRead;
|
||||||
|
mal_format_converter_read_separated_proc onReadSeparated;
|
||||||
|
void* pUserData;
|
||||||
|
void (* onConvertPCM)(void* dst, const void* src, mal_uint64 count, mal_dither_mode ditherMode);
|
||||||
|
void (* onInterleavePCM)(void* dst, const void** src, mal_uint64 frameCount, mal_uint32 channels);
|
||||||
|
void (* onDeinterleavePCM)(void** dst, const void* src, mal_uint64 frameCount, mal_uint32 channels);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct mal_src mal_src;
|
typedef struct mal_src mal_src;
|
||||||
typedef mal_uint32 (* mal_src_read_proc)(mal_src* pSRC, mal_uint32 frameCount, void* pFramesOut, void* pUserData); // Returns the number of frames that were read.
|
typedef mal_uint32 (* mal_src_read_proc)(mal_src* pSRC, mal_uint32 frameCount, void* pFramesOut, void* pUserData); // Returns the number of frames that were read.
|
||||||
|
|
||||||
@@ -758,6 +786,7 @@ struct mal_dsp
|
|||||||
mal_dsp_config config;
|
mal_dsp_config config;
|
||||||
mal_dsp_read_proc onRead;
|
mal_dsp_read_proc onRead;
|
||||||
void* pUserDataForOnRead;
|
void* pUserDataForOnRead;
|
||||||
|
mal_format_converter formatConverter;
|
||||||
mal_src src; // For sample rate conversion.
|
mal_src src; // For sample rate conversion.
|
||||||
mal_channel channelMapInPostMix[MAL_MAX_CHANNELS]; // <-- When mixing, new channels may need to be created. This represents the channel map after mixing.
|
mal_channel channelMapInPostMix[MAL_MAX_CHANNELS]; // <-- When mixing, new channels may need to be created. This represents the channel map after mixing.
|
||||||
mal_channel channelShuffleTable[MAL_MAX_CHANNELS];
|
mal_channel channelShuffleTable[MAL_MAX_CHANNELS];
|
||||||
@@ -1642,6 +1671,8 @@ mal_uint32 mal_device_get_buffer_size_in_bytes(mal_device* pDevice);
|
|||||||
// Thread Safety: SAFE
|
// Thread Safety: SAFE
|
||||||
// This is API is pure.
|
// This is API is pure.
|
||||||
mal_uint32 mal_get_sample_size_in_bytes(mal_format format);
|
mal_uint32 mal_get_sample_size_in_bytes(mal_format format);
|
||||||
|
static inline mal_uint32 mal_get_bytes_per_sample(mal_format format) { return mal_get_sample_size_in_bytes(format); }
|
||||||
|
static inline mal_uint32 mal_get_bytes_per_frame(mal_format format, mal_uint32 channels) { return mal_get_bytes_per_sample(format) * channels; }
|
||||||
|
|
||||||
// Helper function for initializing a mal_context_config object.
|
// Helper function for initializing a mal_context_config object.
|
||||||
mal_context_config mal_context_config_init(mal_log_proc onLog);
|
mal_context_config mal_context_config_init(mal_log_proc onLog);
|
||||||
@@ -1747,33 +1778,6 @@ void mal_get_standard_channel_map(mal_standard_channel_map standardChannelMap, m
|
|||||||
//
|
//
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
typedef struct mal_format_converter mal_format_converter;
|
|
||||||
|
|
||||||
// Callback for reading input data for the format converter.
|
|
||||||
typedef mal_uint32 (* mal_format_converter_read_proc) (mal_format_converter* pConverter, mal_uint32 frameCount, void* pFramesOut, void* pUserData);
|
|
||||||
typedef mal_uint32 (* mal_format_converter_read_separated_proc)(mal_format_converter* pConverter, mal_uint32 frameCount, void** ppSamplesOut, void* pUserData);
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
mal_format formatIn;
|
|
||||||
mal_format formatOut;
|
|
||||||
mal_uint32 channels;
|
|
||||||
mal_stream_format streamFormatIn;
|
|
||||||
mal_stream_format streamFormatOut;
|
|
||||||
mal_dither_mode ditherMode;
|
|
||||||
} mal_format_converter_config;
|
|
||||||
|
|
||||||
struct mal_format_converter
|
|
||||||
{
|
|
||||||
mal_format_converter_config config;
|
|
||||||
mal_format_converter_read_proc onRead;
|
|
||||||
mal_format_converter_read_separated_proc onReadSeparated;
|
|
||||||
void* pUserData;
|
|
||||||
void (* onConvertPCM)(void* dst, const void* src, mal_uint64 count, mal_dither_mode ditherMode);
|
|
||||||
void (* onInterleavePCM)(void* dst, const void** src, mal_uint64 frameCount, mal_uint32 channels);
|
|
||||||
void (* onDeinterleavePCM)(void** dst, const void* src, mal_uint64 frameCount, mal_uint32 channels);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Initializes a format converter.
|
// Initializes a format converter.
|
||||||
mal_result mal_format_converter_init(const mal_format_converter_config* pConfig, mal_format_converter_read_proc onRead, void* pUserData, mal_format_converter* pConverter);
|
mal_result mal_format_converter_init(const mal_format_converter_config* pConfig, mal_format_converter_read_proc onRead, void* pUserData, mal_format_converter* pConverter);
|
||||||
|
|
||||||
@@ -15968,9 +15972,9 @@ void mal_pcm_interleave_s24__reference(void* dst, const void** src, mal_uint64 f
|
|||||||
for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
|
for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
|
||||||
mal_uint32 iChannel;
|
mal_uint32 iChannel;
|
||||||
for (iChannel = 0; iChannel < channels; iChannel += 1) {
|
for (iChannel = 0; iChannel < channels; iChannel += 1) {
|
||||||
dst8[iFrame*3*channels + iChannel + 0] = src8[iChannel][iFrame*3 + 0];
|
dst8[iFrame*3*channels + iChannel*3 + 0] = src8[iChannel][iFrame*3 + 0];
|
||||||
dst8[iFrame*3*channels + iChannel + 1] = src8[iChannel][iFrame*3 + 1];
|
dst8[iFrame*3*channels + iChannel*3 + 1] = src8[iChannel][iFrame*3 + 1];
|
||||||
dst8[iFrame*3*channels + iChannel + 2] = src8[iChannel][iFrame*3 + 2];
|
dst8[iFrame*3*channels + iChannel*3 + 2] = src8[iChannel][iFrame*3 + 2];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -15999,9 +16003,9 @@ void mal_pcm_deinterleave_s24__reference(void** dst, const void* src, mal_uint64
|
|||||||
for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
|
for (iFrame = 0; iFrame < frameCount; iFrame += 1) {
|
||||||
mal_uint32 iChannel;
|
mal_uint32 iChannel;
|
||||||
for (iChannel = 0; iChannel < channels; iChannel += 1) {
|
for (iChannel = 0; iChannel < channels; iChannel += 1) {
|
||||||
dst8[iChannel][iFrame*3 + 0] = src8[iFrame*3*channels + iChannel + 0];
|
dst8[iChannel][iFrame*3 + 0] = src8[iFrame*3*channels + iChannel*3 + 0];
|
||||||
dst8[iChannel][iFrame*3 + 1] = src8[iFrame*3*channels + iChannel + 1];
|
dst8[iChannel][iFrame*3 + 1] = src8[iFrame*3*channels + iChannel*3 + 1];
|
||||||
dst8[iChannel][iFrame*3 + 2] = src8[iFrame*3*channels + iChannel + 2];
|
dst8[iChannel][iFrame*3 + 2] = src8[iFrame*3*channels + iChannel*3 + 2];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -16748,6 +16752,11 @@ mal_uint64 mal_format_converter_read_frames(mal_format_converter* pConverter, ma
|
|||||||
mal_uint8 tempSamplesOfOutFormat[MAL_MAX_CHANNELS][MAL_MAX_PCM_SAMPLE_SIZE_IN_BYTES * 128];
|
mal_uint8 tempSamplesOfOutFormat[MAL_MAX_CHANNELS][MAL_MAX_PCM_SAMPLE_SIZE_IN_BYTES * 128];
|
||||||
mal_assert(sizeof(tempSamplesOfOutFormat[0]) <= 0xFFFFFFFFF);
|
mal_assert(sizeof(tempSamplesOfOutFormat[0]) <= 0xFFFFFFFFF);
|
||||||
|
|
||||||
|
void* ppTempSampleOfOutFormat[MAL_MAX_CHANNELS];
|
||||||
|
for (mal_uint32 i = 0; i < pConverter->config.channels; ++i) {
|
||||||
|
ppTempSampleOfOutFormat[i] = &tempSamplesOfOutFormat[i];
|
||||||
|
}
|
||||||
|
|
||||||
mal_uint32 maxFramesToReadAtATime = sizeof(tempSamplesOfOutFormat[0]) / sampleSizeIn;
|
mal_uint32 maxFramesToReadAtATime = sizeof(tempSamplesOfOutFormat[0]) / sampleSizeIn;
|
||||||
|
|
||||||
while (totalFramesRead < frameCount) {
|
while (totalFramesRead < frameCount) {
|
||||||
@@ -16761,7 +16770,7 @@ mal_uint64 mal_format_converter_read_frames(mal_format_converter* pConverter, ma
|
|||||||
|
|
||||||
if (pConverter->config.formatIn == pConverter->config.formatOut) {
|
if (pConverter->config.formatIn == pConverter->config.formatOut) {
|
||||||
// Only interleaving.
|
// Only interleaving.
|
||||||
framesJustRead = (mal_uint32)pConverter->onReadSeparated(pConverter, (mal_uint32)framesToReadRightNow, (void**)tempSamplesOfOutFormat, pConverter->pUserData);
|
framesJustRead = (mal_uint32)pConverter->onReadSeparated(pConverter, (mal_uint32)framesToReadRightNow, ppTempSampleOfOutFormat, pConverter->pUserData);
|
||||||
if (framesJustRead == 0) {
|
if (framesJustRead == 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -16769,7 +16778,13 @@ mal_uint64 mal_format_converter_read_frames(mal_format_converter* pConverter, ma
|
|||||||
// Interleaving + Conversion. Convert first, then interleave.
|
// Interleaving + Conversion. Convert first, then interleave.
|
||||||
mal_uint8 tempSamplesOfInFormat[MAL_MAX_CHANNELS][MAL_MAX_PCM_SAMPLE_SIZE_IN_BYTES * 128];
|
mal_uint8 tempSamplesOfInFormat[MAL_MAX_CHANNELS][MAL_MAX_PCM_SAMPLE_SIZE_IN_BYTES * 128];
|
||||||
|
|
||||||
framesJustRead = (mal_uint32)pConverter->onReadSeparated(pConverter, (mal_uint32)framesToReadRightNow, (void**)tempSamplesOfInFormat, pConverter->pUserData);
|
void* ppTempSampleOfInFormat[MAL_MAX_CHANNELS];
|
||||||
|
for (mal_uint32 i = 0; i < pConverter->config.channels; ++i) {
|
||||||
|
ppTempSampleOfInFormat[i] = &tempSamplesOfInFormat[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
framesJustRead = (mal_uint32)pConverter->onReadSeparated(pConverter, (mal_uint32)framesToReadRightNow, ppTempSampleOfInFormat, pConverter->pUserData);
|
||||||
if (framesJustRead == 0) {
|
if (framesJustRead == 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -16779,7 +16794,7 @@ mal_uint64 mal_format_converter_read_frames(mal_format_converter* pConverter, ma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pConverter->onInterleavePCM(pNextFramesOut, (void**)tempSamplesOfOutFormat, framesJustRead, pConverter->config.channels);
|
pConverter->onInterleavePCM(pNextFramesOut, ppTempSampleOfOutFormat, framesJustRead, pConverter->config.channels);
|
||||||
|
|
||||||
totalFramesRead += framesJustRead;
|
totalFramesRead += framesJustRead;
|
||||||
pNextFramesOut += framesJustRead * frameSizeIn;
|
pNextFramesOut += framesJustRead * frameSizeIn;
|
||||||
@@ -16854,7 +16869,7 @@ mal_uint64 mal_format_converter_read_frames_separated(mal_format_converter* pCon
|
|||||||
framesToReadRightNow = 0xFFFFFFFF;
|
framesToReadRightNow = 0xFFFFFFFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
mal_uint32 framesJustRead = (mal_uint32)pConverter->onReadSeparated(pConverter, (mal_uint32)framesToReadRightNow, (void**)ppNextSamplesOut, pConverter->pUserData);
|
mal_uint32 framesJustRead = (mal_uint32)pConverter->onReadSeparated(pConverter, (mal_uint32)framesToReadRightNow, ppNextSamplesOut, pConverter->pUserData);
|
||||||
if (framesJustRead == 0) {
|
if (framesJustRead == 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -16878,7 +16893,7 @@ mal_uint64 mal_format_converter_read_frames_separated(mal_format_converter* pCon
|
|||||||
framesToReadRightNow = maxFramesToReadAtATime;
|
framesToReadRightNow = maxFramesToReadAtATime;
|
||||||
}
|
}
|
||||||
|
|
||||||
mal_uint32 framesJustRead = (mal_uint32)pConverter->onReadSeparated(pConverter, (mal_uint32)framesToReadRightNow, (void**)ppNextSamplesOut, pConverter->pUserData);
|
mal_uint32 framesJustRead = (mal_uint32)pConverter->onReadSeparated(pConverter, (mal_uint32)framesToReadRightNow, ppNextSamplesOut, pConverter->pUserData);
|
||||||
if (framesJustRead == 0) {
|
if (framesJustRead == 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
+298
-1
@@ -443,7 +443,7 @@ int do_format_conversion_test(mal_format formatIn, mal_format formatOut)
|
|||||||
onConvertPCM(pConvertedData, pBaseData, (mal_uint32)benchmarkFrameCount, mal_dither_mode_none);
|
onConvertPCM(pConvertedData, pBaseData, (mal_uint32)benchmarkFrameCount, mal_dither_mode_none);
|
||||||
result = mal_pcm_compare(pBenchmarkData, pConvertedData, benchmarkFrameCount, formatOut, allowedDifference);
|
result = mal_pcm_compare(pBenchmarkData, pConvertedData, benchmarkFrameCount, formatOut, allowedDifference);
|
||||||
if (result == 0) {
|
if (result == 0) {
|
||||||
printf("PASSED.\n");
|
printf("PASSED\n");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
printf("FAILED. Out of memory.\n");
|
printf("FAILED. Out of memory.\n");
|
||||||
@@ -648,6 +648,294 @@ int do_format_conversion_tests()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int compare_interleaved_and_separated_buffers(const void* interleaved, const void** separated, mal_uint32 frameCount, mal_uint32 channels, mal_format format)
|
||||||
|
{
|
||||||
|
mal_uint32 bytesPerSample = mal_get_sample_size_in_bytes(format);
|
||||||
|
|
||||||
|
const mal_uint8* interleaved8 = (const mal_uint8*)interleaved;
|
||||||
|
const mal_uint8** separated8 = (const mal_uint8**)separated;
|
||||||
|
|
||||||
|
for (mal_uint32 iFrame = 0; iFrame < frameCount; iFrame += 1) {
|
||||||
|
const mal_uint8* interleavedFrame = interleaved8 + iFrame*channels*bytesPerSample;
|
||||||
|
|
||||||
|
for (mal_uint32 iChannel = 0; iChannel < channels; iChannel += 1) {
|
||||||
|
const mal_uint8* separatedFrame = separated8[iChannel] + iFrame*bytesPerSample;
|
||||||
|
|
||||||
|
int result = memcmp(interleavedFrame + iChannel*bytesPerSample, separatedFrame, bytesPerSample);
|
||||||
|
if (result != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Getting here means nothing failed.
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int do_interleaving_test(mal_format format)
|
||||||
|
{
|
||||||
|
// This test is simple. We start with a deinterleaved buffer. We then test interleaving. Then we deinterleave the interleaved buffer
|
||||||
|
// and compare that the original. It should be bit-perfect. We do this for all channel counts.
|
||||||
|
|
||||||
|
int result = 0;
|
||||||
|
|
||||||
|
switch (format)
|
||||||
|
{
|
||||||
|
case mal_format_u8:
|
||||||
|
{
|
||||||
|
mal_uint8 src [MAL_MAX_CHANNELS][64];
|
||||||
|
mal_uint8 dst [MAL_MAX_CHANNELS][64];
|
||||||
|
mal_uint8 dsti[MAL_MAX_CHANNELS*64];
|
||||||
|
void* ppSrc[MAL_MAX_CHANNELS];
|
||||||
|
void* ppDst[MAL_MAX_CHANNELS];
|
||||||
|
|
||||||
|
mal_uint32 frameCount = mal_countof(src[0]);
|
||||||
|
mal_uint32 channelCount = mal_countof(src);
|
||||||
|
for (mal_uint32 iChannel = 0; iChannel < channelCount; iChannel += 1) {
|
||||||
|
for (mal_uint32 iFrame = 0; iFrame < frameCount; iFrame += 1) {
|
||||||
|
src[iChannel][iFrame] = (mal_uint8)iChannel;
|
||||||
|
}
|
||||||
|
|
||||||
|
ppSrc[iChannel] = &src[iChannel];
|
||||||
|
ppDst[iChannel] = &dst[iChannel];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now test every channel count.
|
||||||
|
for (mal_uint32 i = 0; i < channelCount; ++i) {
|
||||||
|
mal_uint32 channelCountForThisIteration = i + 1;
|
||||||
|
|
||||||
|
// Interleave.
|
||||||
|
mal_pcm_interleave_u8__reference(dsti, ppSrc, frameCount, channelCountForThisIteration);
|
||||||
|
if (compare_interleaved_and_separated_buffers(dsti, ppSrc, frameCount, channelCountForThisIteration, format) != 0) {
|
||||||
|
printf("FAILED. Separated to Interleaved (Channels = %u)\n", i);
|
||||||
|
result = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deinterleave.
|
||||||
|
mal_pcm_deinterleave_u8__reference(ppDst, dsti, frameCount, channelCountForThisIteration);
|
||||||
|
if (compare_interleaved_and_separated_buffers(dsti, ppDst, frameCount, channelCountForThisIteration, format) != 0) {
|
||||||
|
printf("FAILED. Interleaved to Separated (Channels = %u)\n", i);
|
||||||
|
result = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case mal_format_s16:
|
||||||
|
{
|
||||||
|
mal_int16 src [MAL_MAX_CHANNELS][64];
|
||||||
|
mal_int16 dst [MAL_MAX_CHANNELS][64];
|
||||||
|
mal_int16 dsti[MAL_MAX_CHANNELS*64];
|
||||||
|
void* ppSrc[MAL_MAX_CHANNELS];
|
||||||
|
void* ppDst[MAL_MAX_CHANNELS];
|
||||||
|
|
||||||
|
mal_uint32 frameCount = mal_countof(src[0]);
|
||||||
|
mal_uint32 channelCount = mal_countof(src);
|
||||||
|
for (mal_uint32 iChannel = 0; iChannel < channelCount; iChannel += 1) {
|
||||||
|
for (mal_uint32 iFrame = 0; iFrame < frameCount; iFrame += 1) {
|
||||||
|
src[iChannel][iFrame] = (mal_int16)iChannel;
|
||||||
|
}
|
||||||
|
|
||||||
|
ppSrc[iChannel] = &src[iChannel];
|
||||||
|
ppDst[iChannel] = &dst[iChannel];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now test every channel count.
|
||||||
|
for (mal_uint32 i = 0; i < channelCount; ++i) {
|
||||||
|
mal_uint32 channelCountForThisIteration = i + 1;
|
||||||
|
|
||||||
|
// Interleave.
|
||||||
|
mal_pcm_interleave_s16__reference(dsti, ppSrc, frameCount, channelCountForThisIteration);
|
||||||
|
if (compare_interleaved_and_separated_buffers(dsti, ppSrc, frameCount, channelCountForThisIteration, format) != 0) {
|
||||||
|
printf("FAILED. Separated to Interleaved (Channels = %u)\n", i);
|
||||||
|
result = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deinterleave.
|
||||||
|
mal_pcm_deinterleave_s16__reference(ppDst, dsti, frameCount, channelCountForThisIteration);
|
||||||
|
if (compare_interleaved_and_separated_buffers(dsti, ppDst, frameCount, channelCountForThisIteration, format) != 0) {
|
||||||
|
printf("FAILED. Interleaved to Separated (Channels = %u)\n", i);
|
||||||
|
result = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case mal_format_s24:
|
||||||
|
{
|
||||||
|
mal_uint8 src [MAL_MAX_CHANNELS][64*3];
|
||||||
|
mal_uint8 dst [MAL_MAX_CHANNELS][64*3];
|
||||||
|
mal_uint8 dsti[MAL_MAX_CHANNELS*64*3];
|
||||||
|
void* ppSrc[MAL_MAX_CHANNELS];
|
||||||
|
void* ppDst[MAL_MAX_CHANNELS];
|
||||||
|
|
||||||
|
mal_uint32 frameCount = mal_countof(src[0])/3;
|
||||||
|
mal_uint32 channelCount = mal_countof(src);
|
||||||
|
for (mal_uint32 iChannel = 0; iChannel < channelCount; iChannel += 1) {
|
||||||
|
for (mal_uint32 iFrame = 0; iFrame < frameCount; iFrame += 1) {
|
||||||
|
src[iChannel][iFrame*3 + 0] = (mal_uint8)iChannel;
|
||||||
|
src[iChannel][iFrame*3 + 1] = (mal_uint8)iChannel;
|
||||||
|
src[iChannel][iFrame*3 + 2] = (mal_uint8)iChannel;
|
||||||
|
}
|
||||||
|
|
||||||
|
ppSrc[iChannel] = &src[iChannel];
|
||||||
|
ppDst[iChannel] = &dst[iChannel];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now test every channel count.
|
||||||
|
for (mal_uint32 i = 0; i < channelCount; ++i) {
|
||||||
|
mal_uint32 channelCountForThisIteration = i + 1;
|
||||||
|
|
||||||
|
// Interleave.
|
||||||
|
mal_pcm_interleave_s24__reference(dsti, ppSrc, frameCount, channelCountForThisIteration);
|
||||||
|
if (compare_interleaved_and_separated_buffers(dsti, ppSrc, frameCount, channelCountForThisIteration, format) != 0) {
|
||||||
|
printf("FAILED. Separated to Interleaved (Channels = %u)\n", channelCountForThisIteration);
|
||||||
|
result = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deinterleave.
|
||||||
|
mal_pcm_deinterleave_s24__reference(ppDst, dsti, frameCount, channelCountForThisIteration);
|
||||||
|
if (compare_interleaved_and_separated_buffers(dsti, ppDst, frameCount, channelCountForThisIteration, format) != 0) {
|
||||||
|
printf("FAILED. Interleaved to Separated (Channels = %u)\n", channelCountForThisIteration);
|
||||||
|
result = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case mal_format_s32:
|
||||||
|
{
|
||||||
|
mal_int32 src [MAL_MAX_CHANNELS][64];
|
||||||
|
mal_int32 dst [MAL_MAX_CHANNELS][64];
|
||||||
|
mal_int32 dsti[MAL_MAX_CHANNELS*64];
|
||||||
|
void* ppSrc[MAL_MAX_CHANNELS];
|
||||||
|
void* ppDst[MAL_MAX_CHANNELS];
|
||||||
|
|
||||||
|
mal_uint32 frameCount = mal_countof(src[0]);
|
||||||
|
mal_uint32 channelCount = mal_countof(src);
|
||||||
|
for (mal_uint32 iChannel = 0; iChannel < channelCount; iChannel += 1) {
|
||||||
|
for (mal_uint32 iFrame = 0; iFrame < frameCount; iFrame += 1) {
|
||||||
|
src[iChannel][iFrame] = (mal_int32)iChannel;
|
||||||
|
}
|
||||||
|
|
||||||
|
ppSrc[iChannel] = &src[iChannel];
|
||||||
|
ppDst[iChannel] = &dst[iChannel];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now test every channel count.
|
||||||
|
for (mal_uint32 i = 0; i < channelCount; ++i) {
|
||||||
|
mal_uint32 channelCountForThisIteration = i + 1;
|
||||||
|
|
||||||
|
// Interleave.
|
||||||
|
mal_pcm_interleave_s32__reference(dsti, ppSrc, frameCount, channelCountForThisIteration);
|
||||||
|
if (compare_interleaved_and_separated_buffers(dsti, ppSrc, frameCount, channelCountForThisIteration, format) != 0) {
|
||||||
|
printf("FAILED. Separated to Interleaved (Channels = %u)\n", i);
|
||||||
|
result = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deinterleave.
|
||||||
|
mal_pcm_deinterleave_s32__reference(ppDst, dsti, frameCount, channelCountForThisIteration);
|
||||||
|
if (compare_interleaved_and_separated_buffers(dsti, ppDst, frameCount, channelCountForThisIteration, format) != 0) {
|
||||||
|
printf("FAILED. Interleaved to Separated (Channels = %u)\n", i);
|
||||||
|
result = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case mal_format_f32:
|
||||||
|
{
|
||||||
|
float src [MAL_MAX_CHANNELS][64];
|
||||||
|
float dst [MAL_MAX_CHANNELS][64];
|
||||||
|
float dsti[MAL_MAX_CHANNELS*64];
|
||||||
|
void* ppSrc[MAL_MAX_CHANNELS];
|
||||||
|
void* ppDst[MAL_MAX_CHANNELS];
|
||||||
|
|
||||||
|
mal_uint32 frameCount = mal_countof(src[0]);
|
||||||
|
mal_uint32 channelCount = mal_countof(src);
|
||||||
|
for (mal_uint32 iChannel = 0; iChannel < channelCount; iChannel += 1) {
|
||||||
|
for (mal_uint32 iFrame = 0; iFrame < frameCount; iFrame += 1) {
|
||||||
|
src[iChannel][iFrame] = (float)iChannel;
|
||||||
|
}
|
||||||
|
|
||||||
|
ppSrc[iChannel] = &src[iChannel];
|
||||||
|
ppDst[iChannel] = &dst[iChannel];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now test every channel count.
|
||||||
|
for (mal_uint32 i = 0; i < channelCount; ++i) {
|
||||||
|
mal_uint32 channelCountForThisIteration = i + 1;
|
||||||
|
|
||||||
|
// Interleave.
|
||||||
|
mal_pcm_interleave_f32__reference(dsti, ppSrc, frameCount, channelCountForThisIteration);
|
||||||
|
if (compare_interleaved_and_separated_buffers(dsti, ppSrc, frameCount, channelCountForThisIteration, format) != 0) {
|
||||||
|
printf("FAILED. Separated to Interleaved (Channels = %u)\n", i);
|
||||||
|
result = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deinterleave.
|
||||||
|
mal_pcm_deinterleave_f32__reference(ppDst, dsti, frameCount, channelCountForThisIteration);
|
||||||
|
if (compare_interleaved_and_separated_buffers(dsti, ppDst, frameCount, channelCountForThisIteration, format) != 0) {
|
||||||
|
printf("FAILED. Interleaved to Separated (Channels = %u)\n", i);
|
||||||
|
result = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
printf("Unknown format.");
|
||||||
|
result = -1;
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (result == 0) {
|
||||||
|
printf("PASSED\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int do_interleaving_tests()
|
||||||
|
{
|
||||||
|
int result = 0;
|
||||||
|
|
||||||
|
printf("u8... ");
|
||||||
|
if (do_interleaving_test(mal_format_u8) != 0) {
|
||||||
|
result = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("s16... ");
|
||||||
|
if (do_interleaving_test(mal_format_s16) != 0) {
|
||||||
|
result = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("s24... ");
|
||||||
|
if (do_interleaving_test(mal_format_s24) != 0) {
|
||||||
|
result = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("s32... ");
|
||||||
|
if (do_interleaving_test(mal_format_s32) != 0) {
|
||||||
|
result = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("f32... ");
|
||||||
|
if (do_interleaving_test(mal_format_f32) != 0) {
|
||||||
|
result = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int do_backend_test(mal_backend backend)
|
int do_backend_test(mal_backend backend)
|
||||||
{
|
{
|
||||||
mal_result result = MAL_SUCCESS;
|
mal_result result = MAL_SUCCESS;
|
||||||
@@ -887,6 +1175,15 @@ int main(int argc, char** argv)
|
|||||||
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
|
||||||
|
printf("=== TESTING INTERLEAVING/DEINTERLEAVING ===\n");
|
||||||
|
result = do_interleaving_tests();
|
||||||
|
if (result < 0) {
|
||||||
|
hasErrorOccurred = MAL_TRUE;
|
||||||
|
}
|
||||||
|
printf("=== END TESTING INTERLEAVING/DEINTERLEAVING ===\n");
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
printf("=== TESTING BACKENDS ===\n");
|
printf("=== TESTING BACKENDS ===\n");
|
||||||
result = do_backend_tests();
|
result = do_backend_tests();
|
||||||
if (result < 0) {
|
if (result < 0) {
|
||||||
|
|||||||
Reference in New Issue
Block a user