diff --git a/miniaudio.h b/miniaudio.h index fd8bdc01..7d0da2ce 100644 --- a/miniaudio.h +++ b/miniaudio.h @@ -5819,6 +5819,10 @@ MA_API ma_channel_converter_config ma_channel_converter_config_init(ma_format fo typedef struct { + /* Memory management. */ + void* _pHeap; + ma_bool32 _ownsHeap; + ma_format format; ma_uint32 channelsIn; ma_uint32 channelsOut; @@ -5833,9 +5837,13 @@ typedef struct ma_int32** s16; } weights; /* [in][out] */ - /* Memory management. */ - void* _pHeap; - ma_bool32 _ownsHeap; + /* + In order to avoid micro heap allocations for the channel map when using a small channel count, + we will have a small local array here for the in and out channel maps. If the channel count + exceeds the capacity of these channel maps it'll fall back to the heap. + */ + ma_channel _smallChannelMapIn[2]; + ma_channel _smallChannelMapOut[2]; } ma_channel_converter; MA_API ma_result ma_channel_converter_get_heap_size(const ma_channel_converter_config* pConfig, size_t* pHeapSizeInBytes); @@ -63128,17 +63136,19 @@ static ma_result ma_channel_converter_get_heap_layout(const ma_channel_converter return MA_INVALID_ARGS; } + MA_ZERO_OBJECT(pHeapLayout); + pHeapLayout->sizeInBytes = 0; /* Input channel map. Only need to allocate this if we have an input channel map (otherwise default channel map is assumed). */ pHeapLayout->channelMapInOffset = pHeapLayout->sizeInBytes; - if (pConfig->pChannelMapIn != NULL) { + if (pConfig->pChannelMapIn != NULL && pConfig->channelsIn > ma_countof(((ma_channel_converter*)0)->_smallChannelMapIn)) { pHeapLayout->sizeInBytes += sizeof(ma_channel) * pConfig->channelsIn; } /* Output channel map. Only need to allocate this if we have an output channel map (otherwise default channel map is assumed). */ pHeapLayout->channelMapOutOffset = pHeapLayout->sizeInBytes; - if (pConfig->pChannelMapOut != NULL) { + if (pConfig->pChannelMapOut != NULL && pConfig->channelsOut > ma_countof(((ma_channel_converter*)0)->_smallChannelMapOut)) { pHeapLayout->sizeInBytes += sizeof(ma_channel) * pConfig->channelsOut; } @@ -63213,14 +63223,24 @@ MA_API ma_result ma_channel_converter_init_preallocated(const ma_channel_convert pConverter->mixingMode = pConfig->mixingMode; if (pConfig->pChannelMapIn != NULL) { - pConverter->pChannelMapIn = (ma_channel*)ma_offset_ptr(pHeap, heapLayout.channelMapInOffset); + if (pConfig->channelsIn > ma_countof(pConverter->_smallChannelMapIn)) { + pConverter->pChannelMapIn = (ma_channel*)ma_offset_ptr(pHeap, heapLayout.channelMapInOffset); + } else { + pConverter->pChannelMapIn = pConverter->_smallChannelMapIn; + } + ma_channel_map_copy_or_default(pConverter->pChannelMapIn, pConfig->channelsIn, pConfig->pChannelMapIn, pConfig->channelsIn); } else { pConverter->pChannelMapIn = NULL; /* Use default channel map. */ } if (pConfig->pChannelMapOut != NULL) { - pConverter->pChannelMapOut = (ma_channel*)ma_offset_ptr(pHeap, heapLayout.channelMapOutOffset); + if (pConfig->channelsOut > ma_countof(pConverter->_smallChannelMapOut)) { + pConverter->pChannelMapOut = (ma_channel*)ma_offset_ptr(pHeap, heapLayout.channelMapOutOffset); + } else { + pConverter->pChannelMapOut = pConverter->_smallChannelMapOut; + } + ma_channel_map_copy_or_default(pConverter->pChannelMapOut, pConfig->channelsOut, pConfig->pChannelMapOut, pConfig->channelsOut); } else { pConverter->pChannelMapOut = NULL; /* Use default channel map. */