Merge branch '2.0.x' into master

This commit is contained in:
derselbst 2019-10-27 16:51:35 +01:00
commit 644668a776
3 changed files with 46 additions and 19 deletions

View file

@ -22,6 +22,7 @@ All the source code examples in this document are in the public domain; you can
- \ref Disclaimer - \ref Disclaimer
- \ref Introduction - \ref Introduction
- \ref NewIn2_1_0 - \ref NewIn2_1_0
- \ref NewIn2_0_8
- \ref NewIn2_0_7 - \ref NewIn2_0_7
- \ref NewIn2_0_6 - \ref NewIn2_0_6
- \ref NewIn2_0_5 - \ref NewIn2_0_5
@ -68,7 +69,8 @@ What is FluidSynth?
\section NewIn2_1_0 Whats new in 2.1.0? \section NewIn2_1_0 Whats new in 2.1.0?
- fluid_sample_set_sound_data() caused broken sound when copying sample data - new reverb engine
- chorus is now stereophonic
- smallest allowed chorus speed is now 0.1 Hz (previously 0.29 Hz) - smallest allowed chorus speed is now 0.1 Hz (previously 0.29 Hz)
- the following audio drivers were added: - the following audio drivers were added:
- opensles - opensles
@ -76,6 +78,10 @@ What is FluidSynth?
- sdl2 - sdl2
- waveout - waveout
\section NewIn2_0_8 Whats new in 2.0.8?
- fluid_sample_set_sound_data() caused broken sound when copying sample data
\section NewIn2_0_7 Whats new in 2.0.7? \section NewIn2_0_7 Whats new in 2.0.7?
- fluid_free() has been added to allow proper deallocation by programming languages other than C/C++ - fluid_free() has been added to allow proper deallocation by programming languages other than C/C++

View file

@ -360,14 +360,14 @@ get_dest_buf(fluid_rvoice_buffers_t *buffers, int index,
} }
/** /**
* Mix data down to buffers * Mix samples down from internal dsp_buf to output buffers
* *
* @param buffers Destination buffer(s) * @param buffers Destination buffer(s)
* @param dsp_buf Mono sample source * @param dsp_buf Mono sample source
* @param start_block Block to start mixing at * @param start_block starting sample in dsp_buf
* @param sample_count number of samples to mix following \c start_block * @param sample_count number of samples to mix following \c start_block
* @param dest_bufs Array of buffers to mixdown to * @param dest_bufs Array of buffers to mixdown to
* @param dest_bufcount Length of dest_bufs * @param dest_bufcount Length of dest_bufs (i.e count of buffers)
*/ */
static void static void
fluid_rvoice_buffers_mix(fluid_rvoice_buffers_t *buffers, fluid_rvoice_buffers_mix(fluid_rvoice_buffers_t *buffers,
@ -375,9 +375,11 @@ fluid_rvoice_buffers_mix(fluid_rvoice_buffers_t *buffers,
int start_block, int sample_count, int start_block, int sample_count,
fluid_real_t **dest_bufs, int dest_bufcount) fluid_real_t **dest_bufs, int dest_bufcount)
{ {
/* buffers count to mixdown to */
int bufcount = buffers->count; int bufcount = buffers->count;
int i, dsp_i; int i, dsp_i;
/* if there is nothing to mix, return immediatly */
if(sample_count <= 0 || dest_bufcount <= 0) if(sample_count <= 0 || dest_bufcount <= 0)
{ {
return; return;
@ -386,6 +388,7 @@ fluid_rvoice_buffers_mix(fluid_rvoice_buffers_t *buffers,
FLUID_ASSERT((uintptr_t)dsp_buf % FLUID_DEFAULT_ALIGNMENT == 0); FLUID_ASSERT((uintptr_t)dsp_buf % FLUID_DEFAULT_ALIGNMENT == 0);
FLUID_ASSERT((uintptr_t)(&dsp_buf[start_block * FLUID_BUFSIZE]) % FLUID_DEFAULT_ALIGNMENT == 0); FLUID_ASSERT((uintptr_t)(&dsp_buf[start_block * FLUID_BUFSIZE]) % FLUID_DEFAULT_ALIGNMENT == 0);
/* mixdown for each buffer */
for(i = 0; i < bufcount; i++) for(i = 0; i < bufcount; i++)
{ {
fluid_real_t *FLUID_RESTRICT buf = get_dest_buf(buffers, i, dest_bufs, dest_bufcount); fluid_real_t *FLUID_RESTRICT buf = get_dest_buf(buffers, i, dest_bufs, dest_bufcount);
@ -398,11 +401,17 @@ fluid_rvoice_buffers_mix(fluid_rvoice_buffers_t *buffers,
FLUID_ASSERT((uintptr_t)buf % FLUID_DEFAULT_ALIGNMENT == 0); 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 */
#pragma omp simd aligned(dsp_buf,buf:FLUID_DEFAULT_ALIGNMENT) #pragma omp simd aligned(dsp_buf,buf:FLUID_DEFAULT_ALIGNMENT)
for(dsp_i = 0; dsp_i < sample_count; dsp_i++)
for(dsp_i = (start_block * FLUID_BUFSIZE); dsp_i < sample_count; dsp_i++)
{ {
buf[dsp_i] += amp * dsp_buf[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];
} }
} }
} }
@ -417,30 +426,42 @@ fluid_mixer_buffers_render_one(fluid_mixer_buffers_t *buffers,
fluid_rvoice_t *rvoice, fluid_real_t **dest_bufs, fluid_rvoice_t *rvoice, fluid_real_t **dest_bufs,
unsigned int dest_bufcount, fluid_real_t *src_buf, int blockcount) unsigned int dest_bufcount, fluid_real_t *src_buf, int blockcount)
{ {
int i, total_samples = 0, start_block = 0; int i, total_samples = 0, last_block_mixed = 0;
for(i = 0; i < blockcount; i++) for(i = 0; i < blockcount; i++)
{ {
/* render one block in src_buf */
int s = fluid_rvoice_write(rvoice, &src_buf[FLUID_BUFSIZE * i]); int s = fluid_rvoice_write(rvoice, &src_buf[FLUID_BUFSIZE * i]);
if(s == -1) if(s == -1)
{ {
start_block += s; /* the voice is silent, mix back all the previously rendered sound */
s = FLUID_BUFSIZE; fluid_rvoice_buffers_mix(&rvoice->buffers, src_buf, last_block_mixed,
total_samples - (last_block_mixed*FLUID_BUFSIZE),
dest_bufs, dest_bufcount);
last_block_mixed = i+1; /* future block start index to mix from */
total_samples += FLUID_BUFSIZE; /* accumulate samples count rendered */
} }
else
total_samples += s;
if(s < FLUID_BUFSIZE)
{ {
break; /* the voice wasn't quiet. Some samples have been rendered [0..FLUID_BUFSIZE] */
total_samples += s;
if(s < FLUID_BUFSIZE)
{
/* voice has finished */
break;
}
} }
} }
fluid_rvoice_buffers_mix(&rvoice->buffers, src_buf, -start_block, total_samples - ((-start_block)*FLUID_BUFSIZE), dest_bufs, dest_bufcount); /* Now mix the remaining blocks from last_block_mixed to total_sample */
fluid_rvoice_buffers_mix(&rvoice->buffers, src_buf, last_block_mixed,
total_samples - (last_block_mixed*FLUID_BUFSIZE),
dest_bufs, dest_bufcount);
if(total_samples < blockcount * FLUID_BUFSIZE) if(total_samples < blockcount * FLUID_BUFSIZE)
{ {
/* voice has finished */
fluid_finish_rvoice(buffers, rvoice); fluid_finish_rvoice(buffers, rvoice);
} }
} }
@ -602,7 +623,7 @@ fluid_mixer_buffers_zero(fluid_mixer_buffers_t *buffers, int current_blockcount)
static int static int
fluid_mixer_buffers_init(fluid_mixer_buffers_t *buffers, fluid_rvoice_mixer_t *mixer) fluid_mixer_buffers_init(fluid_mixer_buffers_t *buffers, fluid_rvoice_mixer_t *mixer)
{ {
const int samplecount = FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT; static const int samplecount = FLUID_BUFSIZE * FLUID_MIXER_MAX_BUFFERS_DEFAULT;
buffers->mixer = mixer; buffers->mixer = mixer;
buffers->buf_count = mixer->buffers.buf_count; buffers->buf_count = mixer->buffers.buf_count;

View file

@ -275,7 +275,7 @@ do { strncpy(_dst,_src,_n); \
#define FLUID_LOG fluid_log #define FLUID_LOG fluid_log
#endif #endif
#ifdef DEBUG #ifdef DEBUG && !defined(NDEBUG)
#define FLUID_ASSERT(a) g_assert(a) #define FLUID_ASSERT(a) g_assert(a)
#else #else
#define FLUID_ASSERT(a) #define FLUID_ASSERT(a)