mirror of
https://github.com/mackron/miniaudio.git
synced 2026-04-22 00:06:59 +02:00
Add output parameter for number of frames mixed to ma_mixer_mix_*().
This commit is contained in:
@@ -37,7 +37,7 @@ void data_callback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uin
|
|||||||
{
|
{
|
||||||
size_t iDataSource;
|
size_t iDataSource;
|
||||||
for (iDataSource = 0; iDataSource < g_dataSourceCount; iDataSource += 1) {
|
for (iDataSource = 0; iDataSource < g_dataSourceCount; iDataSource += 1) {
|
||||||
ma_mixer_mix_data_source(&g_mixer, &g_dataSources[iDataSource], frameCountIn, 1, NULL, MA_TRUE);
|
ma_mixer_mix_data_source(&g_mixer, &g_dataSources[iDataSource], frameCountIn, NULL, 1, NULL, MA_TRUE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ma_mixer_end(&g_mixer, NULL, ma_offset_ptr(pOutput, framesProcessed * bpf));
|
ma_mixer_end(&g_mixer, NULL, ma_offset_ptr(pOutput, framesProcessed * bpf));
|
||||||
@@ -182,6 +182,7 @@ int main(int argc, char** argv)
|
|||||||
&resourceManager,
|
&resourceManager,
|
||||||
argv[iFile+1],
|
argv[iFile+1],
|
||||||
MA_DATA_SOURCE_FLAG_DECODE | MA_DATA_SOURCE_FLAG_ASYNC /*| MA_DATA_SOURCE_FLAG_STREAM*/,
|
MA_DATA_SOURCE_FLAG_DECODE | MA_DATA_SOURCE_FLAG_ASYNC /*| MA_DATA_SOURCE_FLAG_STREAM*/,
|
||||||
|
NULL, /* Async notification. */
|
||||||
&g_dataSources[iFile]);
|
&g_dataSources[iFile]);
|
||||||
|
|
||||||
if (result != MA_SUCCESS) {
|
if (result != MA_SUCCESS) {
|
||||||
@@ -212,7 +213,7 @@ int main(int argc, char** argv)
|
|||||||
|
|
||||||
/* Our data sources need to be explicitly uninitialized. ma_resource_manager_uninit() will not do it for us. */
|
/* Our data sources need to be explicitly uninitialized. ma_resource_manager_uninit() will not do it for us. */
|
||||||
for (iFile = 0; (size_t)iFile < g_dataSourceCount; iFile += 1) {
|
for (iFile = 0; (size_t)iFile < g_dataSourceCount; iFile += 1) {
|
||||||
ma_resource_manager_data_source_uninit(&resourceManager, &g_dataSources[iFile]);
|
ma_resource_manager_data_source_uninit(&g_dataSources[iFile]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Uninitialize the resource manager after each data source. */
|
/* Uninitialize the resource manager after each data source. */
|
||||||
|
|||||||
@@ -4980,6 +4980,7 @@ static void ma_engine_mix_sound(ma_engine* pEngine, ma_sound_group* pGroup, ma_s
|
|||||||
{
|
{
|
||||||
if (pSound->isPlaying) {
|
if (pSound->isPlaying) {
|
||||||
ma_result result = MA_SUCCESS;
|
ma_result result = MA_SUCCESS;
|
||||||
|
ma_uint64 framesProcessed;
|
||||||
|
|
||||||
/* If the pitch has changed we need to update the resampler. */
|
/* If the pitch has changed we need to update the resampler. */
|
||||||
if (pSound->effect.oldPitch != pSound->effect.pitch) {
|
if (pSound->effect.oldPitch != pSound->effect.pitch) {
|
||||||
@@ -4998,10 +4999,10 @@ static void ma_engine_mix_sound(ma_engine* pEngine, ma_sound_group* pGroup, ma_s
|
|||||||
effect we need to make sure we run it through the mixer because it may require us to update internal state for things like echo effects.
|
effect we need to make sure we run it through the mixer because it may require us to update internal state for things like echo effects.
|
||||||
*/
|
*/
|
||||||
if (pSound->volume > 0 || ma_engine_effect_is_passthrough(&pSound->effect) == MA_FALSE) {
|
if (pSound->volume > 0 || ma_engine_effect_is_passthrough(&pSound->effect) == MA_FALSE) {
|
||||||
result = ma_mixer_mix_data_source(&pGroup->mixer, pSound->pDataSource, frameCount, pSound->volume, &pSound->effect, pSound->isLooping);
|
result = ma_mixer_mix_data_source(&pGroup->mixer, pSound->pDataSource, frameCount, &framesProcessed, pSound->volume, &pSound->effect, pSound->isLooping);
|
||||||
} else {
|
} else {
|
||||||
/* The sound is muted. We want to move time forward, but it be made faster by simply seeking instead of reading. We also want to bypass mixing completely. */
|
/* The sound is muted. We want to move time forward, but it be made faster by simply seeking instead of reading. We also want to bypass mixing completely. */
|
||||||
result = ma_data_source_seek_pcm_frames(pSound->pDataSource, frameCount, NULL, pSound->isLooping);
|
result = ma_data_source_seek_pcm_frames(pSound->pDataSource, frameCount, &framesProcessed, pSound->isLooping);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If fading out we need to stop the sound if it's done fading. */
|
/* If fading out we need to stop the sound if it's done fading. */
|
||||||
|
|||||||
+39
-20
@@ -617,6 +617,9 @@ frameCountIn (in)
|
|||||||
The number of frames to mix. This cannot exceed the number of input frames returned by `ma_mixer_begin()`. If it does, an error will be returned. If it is
|
The number of frames to mix. This cannot exceed the number of input frames returned by `ma_mixer_begin()`. If it does, an error will be returned. If it is
|
||||||
less, silence will be mixed to make up the excess.
|
less, silence will be mixed to make up the excess.
|
||||||
|
|
||||||
|
pFrameCountOut (out)
|
||||||
|
Receives the number of frames that were processed from the data source.
|
||||||
|
|
||||||
formatIn (in)
|
formatIn (in)
|
||||||
The sample format of the input data.
|
The sample format of the input data.
|
||||||
|
|
||||||
@@ -642,9 +645,9 @@ See Also
|
|||||||
ma_mixer_begin()
|
ma_mixer_begin()
|
||||||
ma_mixer_end()
|
ma_mixer_end()
|
||||||
*/
|
*/
|
||||||
MA_API ma_result ma_mixer_mix_data_source(ma_mixer* pMixer, ma_data_source* pDataSource, ma_uint64 frameCountIn, float volume, ma_effect* pEffect, ma_bool32 loop);
|
MA_API ma_result ma_mixer_mix_data_source(ma_mixer* pMixer, ma_data_source* pDataSource, ma_uint64 frameCountIn, ma_uint64* pFrameCountOut, float volume, ma_effect* pEffect, ma_bool32 loop);
|
||||||
MA_API ma_result ma_mixer_mix_rb(ma_mixer* pMixer, ma_rb* pRB, ma_uint64 frameCountIn, float volume, ma_effect* pEffect, ma_format formatIn, ma_uint32 channelsIn); /* Caller is the consumer. */
|
MA_API ma_result ma_mixer_mix_rb(ma_mixer* pMixer, ma_rb* pRB, ma_uint64 frameCountIn, ma_uint64* pFrameCountOut, float volume, ma_effect* pEffect, ma_format formatIn, ma_uint32 channelsIn); /* Caller is the consumer. */
|
||||||
MA_API ma_result ma_mixer_mix_pcm_rb(ma_mixer* pMixer, ma_pcm_rb* pRB, ma_uint64 frameCountIn, float volume, ma_effect* pEffect); /* Caller is the consumer. */
|
MA_API ma_result ma_mixer_mix_pcm_rb(ma_mixer* pMixer, ma_pcm_rb* pRB, ma_uint64 frameCountIn, ma_uint64* pFrameCountOut, float volume, ma_effect* pEffect); /* Caller is the consumer. */
|
||||||
|
|
||||||
MA_API ma_result ma_mixer_set_volume(ma_mixer* pMixer, float volume);
|
MA_API ma_result ma_mixer_set_volume(ma_mixer* pMixer, float volume);
|
||||||
MA_API ma_result ma_mixer_get_volume(ma_mixer* pMixer, float* pVolume);
|
MA_API ma_result ma_mixer_get_volume(ma_mixer* pMixer, float* pVolume);
|
||||||
@@ -2475,7 +2478,7 @@ MA_API ma_result ma_mixer_mix_pcm_frames(ma_mixer* pMixer, const void* pFramesIn
|
|||||||
return MA_SUCCESS;
|
return MA_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ma_result ma_mixer_mix_data_source_mmap(ma_mixer* pMixer, ma_data_source* pDataSource, ma_uint64 frameCount, float volume, ma_effect* pEffect, ma_format formatIn, ma_uint32 channelsIn, ma_bool32 loop)
|
static ma_result ma_mixer_mix_data_source_mmap(ma_mixer* pMixer, ma_data_source* pDataSource, ma_uint64 frameCountIn, ma_uint64* pFrameCountOut, float volume, ma_effect* pEffect, ma_format formatIn, ma_uint32 channelsIn, ma_bool32 loop)
|
||||||
{
|
{
|
||||||
ma_result result = MA_SUCCESS;
|
ma_result result = MA_SUCCESS;
|
||||||
ma_uint64 totalFramesProcessed = 0;
|
ma_uint64 totalFramesProcessed = 0;
|
||||||
@@ -2489,7 +2492,11 @@ static ma_result ma_mixer_mix_data_source_mmap(ma_mixer* pMixer, ma_data_source*
|
|||||||
MA_ASSERT(pMixer != NULL);
|
MA_ASSERT(pMixer != NULL);
|
||||||
MA_ASSERT(pDataSource != NULL);
|
MA_ASSERT(pDataSource != NULL);
|
||||||
|
|
||||||
if (frameCount > pMixer->mixingState.frameCountIn) {
|
if (pFrameCountOut != NULL) {
|
||||||
|
*pFrameCountOut = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (frameCountIn > pMixer->mixingState.frameCountIn) {
|
||||||
return MA_INVALID_ARGS; /* Passing in too many input frames. */
|
return MA_INVALID_ARGS; /* Passing in too many input frames. */
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2508,9 +2515,9 @@ static ma_result ma_mixer_mix_data_source_mmap(ma_mixer* pMixer, ma_data_source*
|
|||||||
preEffectConversionRequired = (formatIn != effectFormatIn || channelsIn != effectChannelsIn);
|
preEffectConversionRequired = (formatIn != effectFormatIn || channelsIn != effectChannelsIn);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (totalFramesProcessed < frameCount) {
|
while (totalFramesProcessed < frameCountIn) {
|
||||||
void* pMappedBuffer;
|
void* pMappedBuffer;
|
||||||
ma_uint64 framesToProcess = frameCount - totalFramesProcessed;
|
ma_uint64 framesToProcess = frameCountIn - totalFramesProcessed;
|
||||||
|
|
||||||
if (pEffect == NULL) {
|
if (pEffect == NULL) {
|
||||||
/* Fast path. Mix directly from the data source and don't bother applying an effect. */
|
/* Fast path. Mix directly from the data source and don't bother applying an effect. */
|
||||||
@@ -2546,7 +2553,7 @@ static ma_result ma_mixer_mix_data_source_mmap(ma_mixer* pMixer, ma_data_source*
|
|||||||
/* We need to map our input data first. The input data will be either fed directly into the effect, or will be converted first. */
|
/* We need to map our input data first. The input data will be either fed directly into the effect, or will be converted first. */
|
||||||
result = ma_data_source_map(pDataSource, &pMappedBuffer, &framesMapped);
|
result = ma_data_source_map(pDataSource, &pMappedBuffer, &framesMapped);
|
||||||
if (result != MA_SUCCESS) {
|
if (result != MA_SUCCESS) {
|
||||||
return result;
|
break; /* Failed to map. Abort. */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We have the data from the data source so no we can apply the effect. */
|
/* We have the data from the data source so no we can apply the effect. */
|
||||||
@@ -2578,15 +2585,19 @@ static ma_result ma_mixer_mix_data_source_mmap(ma_mixer* pMixer, ma_data_source*
|
|||||||
break; /* We've reached the end and we're not looping. */
|
break; /* We've reached the end and we're not looping. */
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return result; /* An error occurred. */
|
break; /* An error occurred. */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (pFrameCountOut != NULL) {
|
||||||
|
*pFrameCountOut = totalFramesProcessed;
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ma_result ma_mixer_mix_data_source_read(ma_mixer* pMixer, ma_data_source* pDataSource, ma_uint64 frameCount, float volume, ma_effect* pEffect, ma_format formatIn, ma_uint32 channelsIn, ma_bool32 loop)
|
static ma_result ma_mixer_mix_data_source_read(ma_mixer* pMixer, ma_data_source* pDataSource, ma_uint64 frameCountIn, ma_uint64* pFrameCountOut, float volume, ma_effect* pEffect, ma_format formatIn, ma_uint32 channelsIn, ma_bool32 loop)
|
||||||
{
|
{
|
||||||
ma_result result = MA_SUCCESS;
|
ma_result result = MA_SUCCESS;
|
||||||
ma_uint8 preMixBuffer[MA_DATA_CONVERTER_STACK_BUFFER_SIZE];
|
ma_uint8 preMixBuffer[MA_DATA_CONVERTER_STACK_BUFFER_SIZE];
|
||||||
@@ -2602,7 +2613,11 @@ static ma_result ma_mixer_mix_data_source_read(ma_mixer* pMixer, ma_data_source*
|
|||||||
MA_ASSERT(pMixer != NULL);
|
MA_ASSERT(pMixer != NULL);
|
||||||
MA_ASSERT(pDataSource != NULL);
|
MA_ASSERT(pDataSource != NULL);
|
||||||
|
|
||||||
if (frameCount > pMixer->mixingState.frameCountIn) {
|
if (pFrameCountOut != NULL) {
|
||||||
|
*pFrameCountOut = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (frameCountIn > pMixer->mixingState.frameCountIn) {
|
||||||
return MA_INVALID_ARGS; /* Passing in too many input frames. */
|
return MA_INVALID_ARGS; /* Passing in too many input frames. */
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2629,9 +2644,9 @@ static ma_result ma_mixer_mix_data_source_read(ma_mixer* pMixer, ma_data_source*
|
|||||||
totalFramesProcessed = 0;
|
totalFramesProcessed = 0;
|
||||||
pRunningAccumulationBuffer = pMixer->pAccumulationBuffer;
|
pRunningAccumulationBuffer = pMixer->pAccumulationBuffer;
|
||||||
|
|
||||||
while (totalFramesProcessed < frameCount) {
|
while (totalFramesProcessed < frameCountIn) {
|
||||||
ma_uint64 framesRead;
|
ma_uint64 framesRead;
|
||||||
ma_uint64 framesToRead = frameCount - totalFramesProcessed;
|
ma_uint64 framesToRead = frameCountIn - totalFramesProcessed;
|
||||||
if (framesToRead > preMixBufferCap) {
|
if (framesToRead > preMixBufferCap) {
|
||||||
framesToRead = preMixBufferCap;
|
framesToRead = preMixBufferCap;
|
||||||
}
|
}
|
||||||
@@ -2692,10 +2707,14 @@ static ma_result ma_mixer_mix_data_source_read(ma_mixer* pMixer, ma_data_source*
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (pFrameCountOut != NULL) {
|
||||||
|
*pFrameCountOut = totalFramesProcessed;
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
MA_API ma_result ma_mixer_mix_data_source(ma_mixer* pMixer, ma_data_source* pDataSource, ma_uint64 frameCountIn, float volume, ma_effect* pEffect, ma_bool32 loop)
|
MA_API ma_result ma_mixer_mix_data_source(ma_mixer* pMixer, ma_data_source* pDataSource, ma_uint64 frameCountIn, ma_uint64* pFrameCountOut, float volume, ma_effect* pEffect, ma_bool32 loop)
|
||||||
{
|
{
|
||||||
ma_result result;
|
ma_result result;
|
||||||
ma_format formatIn;
|
ma_format formatIn;
|
||||||
@@ -2719,10 +2738,10 @@ MA_API ma_result ma_mixer_mix_data_source(ma_mixer* pMixer, ma_data_source* pDat
|
|||||||
|
|
||||||
if (supportsMMap) {
|
if (supportsMMap) {
|
||||||
/* Fast path. This is memory mapping mode. */
|
/* Fast path. This is memory mapping mode. */
|
||||||
return ma_mixer_mix_data_source_mmap(pMixer, pDataSourceCallbacks, frameCountIn, volume, pEffect, formatIn, channelsIn, loop);
|
return ma_mixer_mix_data_source_mmap(pMixer, pDataSourceCallbacks, frameCountIn, pFrameCountOut, volume, pEffect, formatIn, channelsIn, loop);
|
||||||
} else {
|
} else {
|
||||||
/* Slow path. This is reading mode. */
|
/* Slow path. This is reading mode. */
|
||||||
return ma_mixer_mix_data_source_read(pMixer, pDataSourceCallbacks, frameCountIn, volume, pEffect, formatIn, channelsIn, loop);
|
return ma_mixer_mix_data_source_read(pMixer, pDataSourceCallbacks, frameCountIn, pFrameCountOut, volume, pEffect, formatIn, channelsIn, loop);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2796,18 +2815,18 @@ static ma_result ma_rb_data_source_init(ma_rb* pRB, ma_format format, ma_uint32
|
|||||||
return MA_SUCCESS;
|
return MA_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
MA_API ma_result ma_mixer_mix_rb(ma_mixer* pMixer, ma_rb* pRB, ma_uint64 frameCountIn, float volume, ma_effect* pEffect, ma_format formatIn, ma_uint32 channelsIn)
|
MA_API ma_result ma_mixer_mix_rb(ma_mixer* pMixer, ma_rb* pRB, ma_uint64 frameCountIn, ma_uint64* pFrameCountOut, float volume, ma_effect* pEffect, ma_format formatIn, ma_uint32 channelsIn)
|
||||||
{
|
{
|
||||||
/* Ring buffer mixing can be implemented in terms of a memory mapped data source. */
|
/* Ring buffer mixing can be implemented in terms of a memory mapped data source. */
|
||||||
ma_rb_data_source ds;
|
ma_rb_data_source ds;
|
||||||
ma_rb_data_source_init(pRB, formatIn, channelsIn, &ds); /* Will never fail and does not require an uninit() implementation. */
|
ma_rb_data_source_init(pRB, formatIn, channelsIn, &ds); /* Will never fail and does not require an uninit() implementation. */
|
||||||
|
|
||||||
return ma_mixer_mix_data_source(pMixer, &ds, frameCountIn, volume, pEffect, MA_TRUE); /* Ring buffers always loop, but the loop parameter will never actually be used because ma_rb_data_source__on_unmap() will never return MA_AT_END. */
|
return ma_mixer_mix_data_source(pMixer, &ds, frameCountIn, pFrameCountOut, volume, pEffect, MA_TRUE); /* Ring buffers always loop, but the loop parameter will never actually be used because ma_rb_data_source__on_unmap() will never return MA_AT_END. */
|
||||||
}
|
}
|
||||||
|
|
||||||
MA_API ma_result ma_mixer_mix_pcm_rb(ma_mixer* pMixer, ma_pcm_rb* pRB, ma_uint64 frameCountIn, float volume, ma_effect* pEffect)
|
MA_API ma_result ma_mixer_mix_pcm_rb(ma_mixer* pMixer, ma_pcm_rb* pRB, ma_uint64 frameCountIn, ma_uint64* pFrameCountOut, float volume, ma_effect* pEffect)
|
||||||
{
|
{
|
||||||
return ma_mixer_mix_rb(pMixer, &pRB->rb, frameCountIn, volume, pEffect, pRB->format, pRB->channels);
|
return ma_mixer_mix_rb(pMixer, &pRB->rb, frameCountIn, pFrameCountOut, volume, pEffect, pRB->format, pRB->channels);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user