mirror of
https://github.com/ZDoom/fluidsynth.git
synced 2025-04-17 13:19:09 +00:00
Merge branch '2.1.x' into master
This commit is contained in:
commit
9690c0dd73
3 changed files with 45 additions and 16 deletions
|
@ -493,7 +493,8 @@ fluid_rvoice_buffers_check_bufnum(fluid_rvoice_buffers_t *buffers, unsigned int
|
|||
|
||||
for(i = buffers->count; i <= bufnum; i++)
|
||||
{
|
||||
buffers->bufs[i].amp = 0.0f;
|
||||
buffers->bufs[i].target_amp = 0.0f;
|
||||
buffers->bufs[i].current_amp = 0.0f;
|
||||
}
|
||||
|
||||
buffers->count = bufnum + 1;
|
||||
|
@ -512,7 +513,7 @@ DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_buffers_set_amp)
|
|||
return;
|
||||
}
|
||||
|
||||
buffers->bufs[bufnum].amp = value;
|
||||
buffers->bufs[bufnum].target_amp = value;
|
||||
}
|
||||
|
||||
DECLARE_FLUID_RVOICE_FUNCTION(fluid_rvoice_buffers_set_mapping)
|
||||
|
|
|
@ -143,8 +143,14 @@ struct _fluid_rvoice_buffers_t
|
|||
unsigned int count; /* Number of records in "bufs" */
|
||||
struct
|
||||
{
|
||||
fluid_real_t amp;
|
||||
int mapping; /* Mapping to mixdown buffer index */
|
||||
/* the actual, linearly interpolated amplitude with which the dsp sample should be mixed into the buf */
|
||||
fluid_real_t current_amp;
|
||||
|
||||
/* the desired amplitude [...] mixed into the buf (directly set by e.g. rapidly changing PAN events) */
|
||||
fluid_real_t target_amp;
|
||||
|
||||
/* Mapping to mixdown buffer index */
|
||||
int mapping;
|
||||
} bufs[FLUID_RVOICE_MAX_BUFS];
|
||||
};
|
||||
|
||||
|
|
|
@ -429,28 +429,50 @@ fluid_rvoice_buffers_mix(fluid_rvoice_buffers_t *buffers,
|
|||
for(i = 0; i < bufcount; i++)
|
||||
{
|
||||
fluid_real_t *FLUID_RESTRICT buf = get_dest_buf(buffers, i, dest_bufs, dest_bufcount);
|
||||
fluid_real_t amp = buffers->bufs[i].amp;
|
||||
fluid_real_t target_amp = buffers->bufs[i].target_amp;
|
||||
fluid_real_t current_amp = buffers->bufs[i].current_amp;
|
||||
fluid_real_t amp_incr;
|
||||
|
||||
if(buf == NULL || amp == 0.0f)
|
||||
if(buf == NULL || (current_amp == 0.0f && target_amp == 0.0f))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
amp_incr = (target_amp - current_amp) / FLUID_BUFSIZE;
|
||||
|
||||
FLUID_ASSERT((uintptr_t)buf % FLUID_DEFAULT_ALIGNMENT == 0);
|
||||
|
||||
/* mixdown sample_count samples in the current buffer buf
|
||||
Note, that this loop could be unrolled by FLUID_BUFSIZE elements */
|
||||
/* Mixdown sample_count samples in the current buffer buf
|
||||
*
|
||||
* For the first FLUID_BUFSIZE samples, we linearly interpolate the buffers amplitude to
|
||||
* avoid clicks/pops when rapidly changing the channels panning (issue 768).
|
||||
*
|
||||
* We could have squashed this into one single loop by using an if clause within the loop body.
|
||||
* But it seems like having two separate loops is easier for compilers to understand, and therefore
|
||||
* auto-vectorizing the loops.
|
||||
*/
|
||||
#pragma omp simd aligned(dsp_buf,buf:FLUID_DEFAULT_ALIGNMENT)
|
||||
|
||||
for(dsp_i = 0; dsp_i < sample_count; dsp_i++)
|
||||
for(dsp_i = 0; dsp_i < FLUID_BUFSIZE; dsp_i++)
|
||||
{
|
||||
// Index by blocks (not by samples) to let the compiler know that we always start accessing
|
||||
// buf and dsp_buf at the FLUID_BUFSIZE*sizeof(fluid_real_t) byte boundary and never somewhere
|
||||
// in between.
|
||||
// A good compiler should understand: Aha, so I don't need to add a peel loop when vectorizing
|
||||
// this loop. Great.
|
||||
buf[start_block * FLUID_BUFSIZE + dsp_i] += amp * dsp_buf[start_block * FLUID_BUFSIZE + dsp_i];
|
||||
// We cannot simply increment current_amp by amp_incr during every iteration, as this would create a dependency and prevent vectorization.
|
||||
buf[start_block * FLUID_BUFSIZE + dsp_i] += (current_amp + amp_incr * dsp_i) * dsp_buf[start_block * FLUID_BUFSIZE + dsp_i];
|
||||
}
|
||||
|
||||
if(target_amp > 0)
|
||||
{
|
||||
/* Note, that this loop could be unrolled by FLUID_BUFSIZE elements */
|
||||
#pragma omp simd aligned(dsp_buf,buf:FLUID_DEFAULT_ALIGNMENT)
|
||||
for(dsp_i = FLUID_BUFSIZE; dsp_i < sample_count; dsp_i++)
|
||||
{
|
||||
// Index by blocks (not by samples) to let the compiler know that we always start accessing
|
||||
// buf and dsp_buf at the FLUID_BUFSIZE*sizeof(fluid_real_t) byte boundary and never somewhere
|
||||
// in between.
|
||||
// A good compiler should understand: Aha, so I don't need to add a peel loop when vectorizing
|
||||
// this loop. Great.
|
||||
buf[start_block * FLUID_BUFSIZE + dsp_i] += target_amp * dsp_buf[start_block * FLUID_BUFSIZE + dsp_i];
|
||||
}
|
||||
}
|
||||
buffers->bufs[i].current_amp = target_amp;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue