Use ma_resampler instead of ma_linear_resampler for sound nodes.

This is infrastructure work for supporting custom resamplers for the
pitching and Doppler effects for sounds.

Public issue https://github.com/mackron/miniaudio/issues/965
This commit is contained in:
David Reid
2026-01-06 18:37:05 +10:00
parent 065e6eadb5
commit 919a01ae4a
+16 -14
View File
@@ -11166,7 +11166,7 @@ typedef struct
ma_uint32 volumeSmoothTimeInPCMFrames;
ma_mono_expansion_mode monoExpansionMode;
ma_fader fader;
ma_linear_resampler resampler; /* For pitch shift. */
ma_resampler resampler; /* For pitch shift. */
ma_spatializer spatializer;
ma_panner panner;
ma_gainer volumeGainer; /* This will only be used if volumeSmoothTimeInPCMFrames is > 0. */
@@ -76581,7 +76581,7 @@ static void ma_engine_node_update_pitch_if_required(ma_engine_node* pEngineNode)
if (isUpdateRequired) {
float basePitch = (float)pEngineNode->sampleRate / ma_engine_get_sample_rate(pEngineNode->pEngine);
ma_linear_resampler_set_rate_ratio(&pEngineNode->resampler, basePitch * pEngineNode->oldPitch * pEngineNode->oldDopplerPitch);
ma_resampler_set_rate_ratio(&pEngineNode->resampler, basePitch * pEngineNode->oldPitch * pEngineNode->oldDopplerPitch);
}
}
@@ -76741,7 +76741,7 @@ static void ma_engine_node_process_pcm_frames__general(ma_engine_node* pEngineNo
ma_uint64 resampleFrameCountIn = framesAvailableIn;
ma_uint64 resampleFrameCountOut = framesAvailableOut;
ma_linear_resampler_process_pcm_frames(&pEngineNode->resampler, pRunningFramesIn, &resampleFrameCountIn, pWorkingBuffer, &resampleFrameCountOut);
ma_resampler_process_pcm_frames(&pEngineNode->resampler, pRunningFramesIn, &resampleFrameCountIn, pWorkingBuffer, &resampleFrameCountOut);
isWorkingBufferValid = MA_TRUE;
framesJustProcessedIn = (ma_uint32)resampleFrameCountIn;
@@ -77056,9 +77056,10 @@ static ma_result ma_engine_node_get_heap_layout(const ma_engine_node_config* pCo
ma_result result;
size_t tempHeapSize;
ma_node_config baseNodeConfig;
ma_linear_resampler_config resamplerConfig;
ma_resampler_config resamplerConfig;
ma_spatializer_config spatializerConfig;
ma_gainer_config gainerConfig;
ma_uint32 sampleRate;
ma_uint32 channelsIn;
ma_uint32 channelsOut;
ma_channel defaultStereoChannelMap[2] = {MA_CHANNEL_SIDE_LEFT, MA_CHANNEL_SIDE_RIGHT}; /* <-- Consistent with the default channel map of a stereo listener. Means channel conversion can run on a fast path. */
@@ -77077,6 +77078,7 @@ static ma_result ma_engine_node_get_heap_layout(const ma_engine_node_config* pCo
pHeapLayout->sizeInBytes = 0;
sampleRate = (pConfig->sampleRate > 0) ? pConfig->sampleRate : ma_engine_get_sample_rate(pConfig->pEngine);
channelsIn = (pConfig->channelsIn != 0) ? pConfig->channelsIn : ma_engine_get_channels(pConfig->pEngine);
channelsOut = (pConfig->channelsOut != 0) ? pConfig->channelsOut : ma_engine_get_channels(pConfig->pEngine);
@@ -77096,10 +77098,10 @@ static ma_result ma_engine_node_get_heap_layout(const ma_engine_node_config* pCo
/* Resmapler. */
resamplerConfig = ma_linear_resampler_config_init(ma_format_f32, channelsIn, 1, 1); /* Input and output sample rates don't affect the calculation of the heap size. */
resamplerConfig.lpfOrder = 0;
resamplerConfig = ma_resampler_config_init(ma_format_f32, channelsIn, sampleRate, ma_engine_get_sample_rate(pConfig->pEngine), ma_resample_algorithm_linear);
resamplerConfig.linear.lpfOrder = 0;
result = ma_linear_resampler_get_heap_size(&resamplerConfig, &tempHeapSize);
result = ma_resampler_get_heap_size(&resamplerConfig, &tempHeapSize);
if (result != MA_SUCCESS) {
return result; /* Failed to retrieve the size of the heap for the resampler. */
}
@@ -77167,7 +77169,7 @@ MA_API ma_result ma_engine_node_init_preallocated(const ma_engine_node_config* p
ma_result result;
ma_engine_node_heap_layout heapLayout;
ma_node_config baseNodeConfig;
ma_linear_resampler_config resamplerConfig;
ma_resampler_config resamplerConfig;
ma_fader_config faderConfig;
ma_spatializer_config spatializerConfig;
ma_panner_config pannerConfig;
@@ -77242,10 +77244,10 @@ MA_API ma_result ma_engine_node_init_preallocated(const ma_engine_node_config* p
*/
/* We'll always do resampling first. */
resamplerConfig = ma_linear_resampler_config_init(ma_format_f32, baseNodeConfig.pInputChannels[0], pEngineNode->sampleRate, ma_engine_get_sample_rate(pEngineNode->pEngine));
resamplerConfig.lpfOrder = 0; /* <-- Need to disable low-pass filtering for pitch shifting for now because there's cases where the biquads are becoming unstable. Need to figure out a better fix for this. */
resamplerConfig = ma_resampler_config_init(ma_format_f32, baseNodeConfig.pInputChannels[0], pEngineNode->sampleRate, ma_engine_get_sample_rate(pEngineNode->pEngine), ma_resample_algorithm_linear);
resamplerConfig.linear.lpfOrder = 0; /* <-- Need to disable low-pass filtering for pitch shifting for now because there's cases where the biquads are becoming unstable. Need to figure out a better fix for this. */
result = ma_linear_resampler_init_preallocated(&resamplerConfig, ma_offset_ptr(pHeap, heapLayout.resamplerOffset), &pEngineNode->resampler);
result = ma_resampler_init_preallocated(&resamplerConfig, ma_offset_ptr(pHeap, heapLayout.resamplerOffset), &pEngineNode->resampler);
if (result != MA_SUCCESS) {
goto error1;
}
@@ -77304,7 +77306,7 @@ MA_API ma_result ma_engine_node_init_preallocated(const ma_engine_node_config* p
/* No need for allocation callbacks here because we use a preallocated heap. */
error3: ma_spatializer_uninit(&pEngineNode->spatializer, NULL);
error2: ma_linear_resampler_uninit(&pEngineNode->resampler, NULL);
error2: ma_resampler_uninit(&pEngineNode->resampler, NULL);
error1: ma_node_uninit(&pEngineNode->baseNode, NULL);
error0: return result;
}
@@ -77353,7 +77355,7 @@ MA_API void ma_engine_node_uninit(ma_engine_node* pEngineNode, const ma_allocati
}
ma_spatializer_uninit(&pEngineNode->spatializer, pAllocationCallbacks);
ma_linear_resampler_uninit(&pEngineNode->resampler, pAllocationCallbacks);
ma_resampler_uninit(&pEngineNode->resampler, pAllocationCallbacks);
/* Free the heap last. */
if (pEngineNode->_ownsHeap) {
@@ -79407,7 +79409,7 @@ MA_API ma_result ma_sound_get_data_format(const ma_sound* pSound, ma_format* pFo
}
if (pSampleRate != NULL) {
*pSampleRate = pSound->engineNode.resampler.config.sampleRateIn;
*pSampleRate = pSound->engineNode.resampler.sampleRateIn;
}
if (pChannelMap != NULL) {