Commit fea2cba2 authored by David Reid's avatar David Reid

Add support for offsets to the low-level mixing API.

parent fe85a132
......@@ -599,7 +599,7 @@ ma_mixer_mix_pcm_frames()
ma_mixer_begin()
ma_mixer_end()
*/
MA_API ma_result ma_mixer_mix_pcm_frames(ma_mixer* pMixer, const void* pFramesIn, ma_uint64 frameCountIn, float volume, ma_format formatIn, ma_uint32 channelsIn);
MA_API ma_result ma_mixer_mix_pcm_frames(ma_mixer* pMixer, const void* pFramesIn, ma_uint64 offsetInFrames, ma_uint64 frameCountIn, float volume, ma_format formatIn, ma_uint32 channelsIn);
/*
Mixes audio data from a data source
......@@ -645,9 +645,9 @@ See Also
ma_mixer_begin()
ma_mixer_end()
*/
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, 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, ma_uint64* pFrameCountOut, float volume, ma_effect* pEffect); /* Caller is the consumer. */
MA_API ma_result ma_mixer_mix_data_source(ma_mixer* pMixer, ma_data_source* pDataSource, ma_uint64 offsetInFrames, 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 offsetInFrames, 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 offsetInFrames, 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_get_volume(ma_mixer* pMixer, float* pVolume);
......@@ -2463,7 +2463,7 @@ MA_API ma_result ma_mixer_end(ma_mixer* pMixer, ma_mixer* pParentMixer, void* pF
return MA_SUCCESS;
}
MA_API ma_result ma_mixer_mix_pcm_frames(ma_mixer* pMixer, const void* pFramesIn, ma_uint64 frameCountIn, float volume, ma_format formatIn, ma_uint32 channelsIn)
MA_API ma_result ma_mixer_mix_pcm_frames(ma_mixer* pMixer, const void* pFramesIn, ma_uint64 offsetInFrames, ma_uint64 frameCountIn, float volume, ma_format formatIn, ma_uint32 channelsIn)
{
if (pMixer == NULL || pFramesIn == NULL) {
return MA_INVALID_ARGS;
......@@ -2473,16 +2473,16 @@ MA_API ma_result ma_mixer_mix_pcm_frames(ma_mixer* pMixer, const void* pFramesIn
return MA_INVALID_ARGS; /* Passing in too many input frames. */
}
ma_mix_pcm_frames(pMixer->pAccumulationBuffer, pFramesIn, frameCountIn, formatIn, channelsIn, volume);
ma_mix_pcm_frames(ma_offset_ptr(pMixer->pAccumulationBuffer, offsetInFrames * ma_get_accumulation_bytes_per_frame(pMixer->format, pMixer->channels)), pFramesIn, frameCountIn, formatIn, channelsIn, volume);
return MA_SUCCESS;
}
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)
static ma_result ma_mixer_mix_data_source_mmap(ma_mixer* pMixer, ma_data_source* pDataSource, ma_uint64 offsetInFrames, 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_uint64 totalFramesProcessed = 0;
void* pRunningAccumulationBuffer = pMixer->pAccumulationBuffer;
void* pRunningAccumulationBuffer = NULL;
ma_bool32 preEffectConversionRequired = MA_FALSE;
ma_format effectFormatIn = ma_format_unknown;
ma_uint32 effectChannelsIn = 0;
......@@ -2496,10 +2496,13 @@ static ma_result ma_mixer_mix_data_source_mmap(ma_mixer* pMixer, ma_data_source*
*pFrameCountOut = 0;
}
if (frameCountIn > pMixer->mixingState.frameCountIn) {
if ((offsetInFrames + frameCountIn) > pMixer->mixingState.frameCountIn) {
return MA_INVALID_ARGS; /* Passing in too many input frames. */
}
/* Initially offset the accumulation buffer by the offset. */
pRunningAccumulationBuffer = ma_offset_ptr(pMixer->pAccumulationBuffer, offsetInFrames * ma_get_accumulation_bytes_per_frame(pMixer->format, pMixer->channels));
if (pEffect != NULL) {
/* We need to know the effect's input and output data format before we'll be able to apply it properly. */
result = ma_effect_get_input_data_format(pEffect, &effectFormatIn, &effectChannelsIn, NULL);
......@@ -2597,7 +2600,7 @@ static ma_result ma_mixer_mix_data_source_mmap(ma_mixer* pMixer, ma_data_source*
return result;
}
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)
static ma_result ma_mixer_mix_data_source_read(ma_mixer* pMixer, ma_data_source* pDataSource, ma_uint64 offsetInFrames, 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_uint8 preMixBuffer[MA_DATA_CONVERTER_STACK_BUFFER_SIZE];
......@@ -2617,7 +2620,7 @@ static ma_result ma_mixer_mix_data_source_read(ma_mixer* pMixer, ma_data_source*
*pFrameCountOut = 0;
}
if (frameCountIn > pMixer->mixingState.frameCountIn) {
if ((offsetInFrames + frameCountIn) > pMixer->mixingState.frameCountIn) {
return MA_INVALID_ARGS; /* Passing in too many input frames. */
}
......@@ -2642,7 +2645,9 @@ static ma_result ma_mixer_mix_data_source_read(ma_mixer* pMixer, ma_data_source*
preMixBufferCap = sizeof(preMixBuffer) / ma_get_bytes_per_frame(preMixFormat, preMixChannels);
totalFramesProcessed = 0;
pRunningAccumulationBuffer = pMixer->pAccumulationBuffer;
/* Initially offset the accumulation buffer by the offset. */
pRunningAccumulationBuffer = ma_offset_ptr(pMixer->pAccumulationBuffer, offsetInFrames * ma_get_accumulation_bytes_per_frame(pMixer->format, pMixer->channels));
while (totalFramesProcessed < frameCountIn) {
ma_uint64 framesRead;
......@@ -2714,7 +2719,7 @@ static ma_result ma_mixer_mix_data_source_read(ma_mixer* pMixer, ma_data_source*
return result;
}
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_data_source(ma_mixer* pMixer, ma_data_source* pDataSource, ma_uint64 offsetInFrames, ma_uint64 frameCountIn, ma_uint64* pFrameCountOut, float volume, ma_effect* pEffect, ma_bool32 loop)
{
ma_result result;
ma_format formatIn;
......@@ -2738,10 +2743,10 @@ MA_API ma_result ma_mixer_mix_data_source(ma_mixer* pMixer, ma_data_source* pDat
if (supportsMMap) {
/* Fast path. This is memory mapping mode. */
return ma_mixer_mix_data_source_mmap(pMixer, pDataSourceCallbacks, frameCountIn, pFrameCountOut, volume, pEffect, formatIn, channelsIn, loop);
return ma_mixer_mix_data_source_mmap(pMixer, pDataSourceCallbacks, offsetInFrames, frameCountIn, pFrameCountOut, volume, pEffect, formatIn, channelsIn, loop);
} else {
/* Slow path. This is reading mode. */
return ma_mixer_mix_data_source_read(pMixer, pDataSourceCallbacks, frameCountIn, pFrameCountOut, volume, pEffect, formatIn, channelsIn, loop);
return ma_mixer_mix_data_source_read(pMixer, pDataSourceCallbacks, offsetInFrames, frameCountIn, pFrameCountOut, volume, pEffect, formatIn, channelsIn, loop);
}
}
......@@ -2815,18 +2820,18 @@ static ma_result ma_rb_data_source_init(ma_rb* pRB, ma_format format, ma_uint32
return MA_SUCCESS;
}
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)
MA_API ma_result ma_mixer_mix_rb(ma_mixer* pMixer, ma_rb* pRB, ma_uint64 offsetInFrames, 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. */
ma_rb_data_source ds;
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, 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. */
return ma_mixer_mix_data_source(pMixer, &ds, offsetInFrames, 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, ma_uint64* pFrameCountOut, float volume, ma_effect* pEffect)
MA_API ma_result ma_mixer_mix_pcm_rb(ma_mixer* pMixer, ma_pcm_rb* pRB, ma_uint64 offsetInFrames, ma_uint64 frameCountIn, ma_uint64* pFrameCountOut, float volume, ma_effect* pEffect)
{
return ma_mixer_mix_rb(pMixer, &pRB->rb, frameCountIn, pFrameCountOut, volume, pEffect, pRB->format, pRB->channels);
return ma_mixer_mix_rb(pMixer, &pRB->rb, offsetInFrames, frameCountIn, pFrameCountOut, volume, pEffect, pRB->format, pRB->channels);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment