Add mod_count parameter to fluid_list_check_linked_mod()

1)@param mod_count number of modulators in table list_mod:
  - If > 0, the function assumes that list_mod is a table and
    initializes it as a list of modulators chained by next field, so that the caller
    doesn't need to do this initialization. This is appropriate when the
    function is called from fluid_voice_add_mod2().

  - If 0, the function assumes that mod_list is a list of modulators with next
    field properly initalialized by the caller. This is appropriate when the
    function is called from the soundfont loader.

 2) Test 11 is added to test_modulator_links.c allowing to test	this new  parameter.
This commit is contained in:
jjceresa 2019-09-17 18:35:47 +02:00
parent 7510d908f3
commit 03d518eeba
2 changed files with 213 additions and 48 deletions

View File

@ -1855,10 +1855,18 @@ fluid_list_copy_linked_mod(const fluid_mod_t *list_mod, int dest_idx, int new_id
* When called by the soundfont loader, it is a good pratice to do full check.
* (see fluid_zone_check_mod()).
*
* @param list_mod, pointer on modulators list.
* @param list_mod, pointer on table or modulators list.
* On input, the list may contains any unlinked or linked modulators.
* On output, invalid modulators are marked invalid with amount value forced
* to 0.
* @param mod_count number of modulators in table list_mod:
* - If > 0, the function assumes that list_mod is a table and initializes it
* as a list of modulators chained by next field, so that the caller doesn't
* need to do this initialization. This is appropriate when the function is
* called from fluid_voice_add_mod2().
* - If 0, the function assumes that mod_list is a list of modulators with next
* field properly initalialized by the caller. This is appropriate when the
* function is called from the soundfont loader.
*
* @param linked_mod, if not NULL, address of pointer on linked modulators
* list returned.
@ -1878,56 +1886,69 @@ fluid_list_copy_linked_mod(const fluid_mod_t *list_mod, int dest_idx, int new_id
* - FLUID_FAILED if failed (memory error).
*/
int
fluid_list_check_linked_mod(char *list_name, fluid_mod_t *list_mod,
fluid_mod_t **linked_mod,
int linked_count)
fluid_list_check_linked_mod(char *list_name,
fluid_mod_t *list_mod, int mod_count,
fluid_mod_t **linked_mod, int linked_count)
{
int result;
/* path is a flags table state to register valid modulators belonging
to valid complete linked modulator paths */
unsigned char *path;
fluid_mod_t *mod;
int count; /* number of modulators in list_mod. */
/* count number of modulators in list_mod */
count = fluid_get_count_mod(list_mod);
if(!count)
if (mod_count > 0) /* list_mod is a table */
{
int i, count;
/* intialize list_mod as a list */
for (i = 0, count = mod_count-1; i < count; i++)
{
list_mod[i].next = &list_mod[i+1];
}
list_mod[count].next = NULL; /* last next field must be NULL */
}
else /* lis_mod is a list of modulators */
{
mod_count = fluid_get_count_mod(list_mod);
}
if(!mod_count)
{ /* There are no modulators, no need to go further */
return 0;
}
/* path allocation (on stack) */
path = alloca(sizeof(*path) * count);
path = alloca(sizeof(*path) * mod_count);
/* initialize path:
- reset bits FLUID_PATH_VALID, FLUID_PATH_CURRENT
- set bits FLUID_MOD_VALID
*/
FLUID_MEMSET(path, FLUID_MOD_VALID, count);
FLUID_MEMSET(path, FLUID_MOD_VALID, mod_count);
/* checks valid modulator sources (specs SF 2.01 7.4, 7.8, 8.2.1).*/
/* checks identic modulators in the list (specs SF 2.01 7.4, 7.8). */
if(list_name != NULL)
{
mod = list_mod; /* first modulator in list_mod */
count = 0;
mod_count = 0;
while(mod)
{
char list_mod_name[256];
/* prepare modulator name: zonename/#modulator */
FLUID_SNPRINTF(list_mod_name, sizeof(list_mod_name),"%s/mod%d", list_name, count);
FLUID_SNPRINTF(list_mod_name, sizeof(list_mod_name),"%s/mod%d",
list_name, mod_count);
/* has mod invalid sources ? */
if(!fluid_mod_check_sources (mod, list_mod_name)
/* or is mod identic to any following modulator ? */
||fluid_zone_is_mod_identic(mod, list_mod_name))
{ /* marks this modulator invalid for future checks */
path[count] &= ~FLUID_MOD_VALID;
path[mod_count] &= ~FLUID_MOD_VALID;
mod->amount = 0;
}
count++;
mod_count++;
mod = mod->next;
}
}
@ -1941,20 +1962,21 @@ fluid_list_check_linked_mod(char *list_name, fluid_mod_t *list_mod,
(specifications SF 2.01 7.4, 7.8) */
if(list_name != NULL)
{
count = 0; /* number of modulators in list_mod. */
mod_count = 0; /* number of modulators in list_mod. */
mod = list_mod; /* first modulator in list_mod */
while(mod)
{
if( /* Check linked mod only not in discovered paths */
fluid_mod_is_linked(mod)
/* Check if mod doesn't belong to any discovered paths */
&& !(path[count] & FLUID_PATH_CURRENT) )
&& !(path[mod_count] & FLUID_PATH_CURRENT) )
{
mod->amount = 0; /* marked invalid */
FLUID_LOG(FLUID_WARN, "Invalid isolated path %s/mod%d", list_name, count);
FLUID_LOG(FLUID_WARN, "Invalid isolated path %s/mod%d",
list_name, mod_count);
}
mod = mod->next;
count++;
mod_count++;
}
}
@ -2093,7 +2115,8 @@ fluid_zone_check_mod(char *zone_name, fluid_mod_t **list_mod,
Then, clone valid linked modulators paths from list_mod to linked_mod
(The linked modulators list is allocated and returned in linked_mod).
*/
if(fluid_list_check_linked_mod(zone_name, *list_mod, linked_mod, 0) == FLUID_FAILED)
if(fluid_list_check_linked_mod(zone_name, *list_mod, 0,
linked_mod, 0) == FLUID_FAILED)
{
return FLUID_FAILED;
}

View File

@ -7,9 +7,9 @@
//----------------------------------------------------------------------------
/* external functions */
int
fluid_list_check_linked_mod(char *list_name, fluid_mod_t *list_mod,
fluid_mod_t **linked_mod,
int linked_count);
fluid_list_check_linked_mod(char *list_name,
fluid_mod_t *list_mod, int mod_count,
fluid_mod_t **linked_mod, int linked_count);
void delete_fluid_list_mod(fluid_mod_t *list_mod);
@ -55,7 +55,8 @@ int main(void)
fluid_mod_set_dest (mod2, GEN_ATTENUATION);
// Return must be 0
linked_count = fluid_list_check_linked_mod("test zone with simple modulators", list_of_mods, NULL, 0);
linked_count = fluid_list_check_linked_mod("test zone with simple modulators",
list_of_mods, 0, NULL, 0);
TEST_ASSERT(linked_count == 0);
// order of modulators remains the same
@ -80,7 +81,8 @@ int main(void)
// - NULL must be returned in linked_mod
// - 0 must be returned in linked_count
linked_mod = mod0; // initialize linked_mod to non NULL.
linked_count = fluid_list_check_linked_mod("test zone with simple modulators", list_of_mods, &linked_mod, 0);
linked_count = fluid_list_check_linked_mod("test zone with simple modulators",
list_of_mods, 0, &linked_mod, 0);
TEST_ASSERT(linked_count == 0);
TEST_ASSERT(linked_mod == NULL);
}
@ -113,7 +115,8 @@ int main(void)
fluid_mod_set_dest (mod2, FLUID_MOD_LINK_DEST | 0);
// Return must be 3
linked_count = fluid_list_check_linked_mod("test zone with linked modulators", list_of_mods, NULL, 0);
linked_count = fluid_list_check_linked_mod("test zone with linked modulators",
list_of_mods, 0, NULL, 0);
TEST_ASSERT(linked_count == 3);
// order not changed
@ -138,7 +141,8 @@ int main(void)
// - not NULL must be returned in linked_mod
// - 3 must be returned in linked_count
linked_mod = NULL; // initialize linked_mod to NULL.
linked_count = fluid_list_check_linked_mod("test zone with linked modulators", list_of_mods, &linked_mod, 0);
linked_count = fluid_list_check_linked_mod("test zone with linked modulators",
list_of_mods, 0, &linked_mod, 0);
TEST_ASSERT(linked_count == 3);
TEST_ASSERT(linked_mod != NULL);
delete_fluid_list_mod(linked_mod);
@ -157,7 +161,8 @@ int main(void)
list_of_mods = mod0;
// Return must be 3
linked_count = fluid_list_check_linked_mod("test zone with linked modulators", list_of_mods, NULL, 0);
linked_count = fluid_list_check_linked_mod("test zone with linked modulators",
list_of_mods, 0, NULL, 0);
TEST_ASSERT(linked_count == 3);
TEST_ASSERT(list_of_mods == mod0);
@ -181,7 +186,8 @@ int main(void)
// - not NULL must be returned in linked_mod
// - 3 must be returned in linked_count
linked_mod = NULL; // initialize linked_mod to NULL.
linked_count = fluid_list_check_linked_mod("test zone with linked modulators", list_of_mods, &linked_mod, 0);
linked_count = fluid_list_check_linked_mod("test zone with linked modulators",
list_of_mods, 0, &linked_mod, 0);
TEST_ASSERT(linked_count == 3);
TEST_ASSERT(linked_mod != NULL);
delete_fluid_list_mod(linked_mod);
@ -206,7 +212,8 @@ int main(void)
list_of_mods = mod0;
// Return must be 3
linked_count = fluid_list_check_linked_mod("test zone with linked modulators", list_of_mods, NULL, 0);
linked_count = fluid_list_check_linked_mod("test zone with linked modulators",
list_of_mods, 0, NULL, 0);
TEST_ASSERT(linked_count == 3);
TEST_ASSERT(list_of_mods == mod0);
@ -232,7 +239,8 @@ int main(void)
// - not NULL must be returned in linked_mod
// - 3 must be returned in linked_count
linked_mod = NULL; // initialize linked_mod to NULL.
linked_count = fluid_list_check_linked_mod("test zone with linked modulators", list_of_mods, &linked_mod, 0);
linked_count = fluid_list_check_linked_mod("test zone with linked modulators",
list_of_mods, 0, &linked_mod, 0);
TEST_ASSERT(linked_count == 3);
TEST_ASSERT(linked_mod != NULL);
delete_fluid_list_mod(linked_mod);
@ -255,7 +263,8 @@ int main(void)
list_of_mods = mod0;
// Return must be 4
linked_count = fluid_list_check_linked_mod("test zone with linked modulators", list_of_mods, NULL, 0);
linked_count = fluid_list_check_linked_mod("test zone with linked modulators",
list_of_mods, 0, NULL, 0);
TEST_ASSERT(linked_count == 4);
TEST_ASSERT(list_of_mods == mod0);
@ -281,7 +290,8 @@ int main(void)
// - not NULL must be returned in linked_mod
// - 4 must be returned in linked_count
linked_mod = NULL; // initialize linked_mod to NULL.
linked_count = fluid_list_check_linked_mod("test zone with linked modulators", list_of_mods, &linked_mod, 0);
linked_count = fluid_list_check_linked_mod("test zone with linked modulators",
list_of_mods, 0, &linked_mod, 0);
TEST_ASSERT(linked_count == 4);
TEST_ASSERT(linked_mod != NULL);
delete_fluid_list_mod(linked_mod);
@ -305,7 +315,8 @@ int main(void)
list_of_mods = mod0;
// Return must be 2
linked_count = fluid_list_check_linked_mod("test zone with circular linked modulators", list_of_mods, NULL, 0);
linked_count = fluid_list_check_linked_mod("test zone with circular linked modulators",
list_of_mods, 0, NULL, 0);
TEST_ASSERT(linked_count == 2);
TEST_ASSERT(list_of_mods == mod0);
@ -344,7 +355,8 @@ int main(void)
mod0->next = mod1;
list_of_mods = mod0;
// It remains at least one linked path : mod2->mod0. Return must be 2
linked_count = fluid_list_check_linked_mod("test zone with circular linked modulators", list_of_mods, NULL, 0);
linked_count = fluid_list_check_linked_mod("test zone with circular linked modulators",
list_of_mods, 0, NULL, 0);
TEST_ASSERT(linked_count == 2);
TEST_ASSERT(list_of_mods == mod0);
@ -370,7 +382,8 @@ int main(void)
// - not NULL must be returned in linked_mod
// - 2 must be returned in linked_count
linked_mod = NULL; // initialize linked_mod to NULL.
linked_count = fluid_list_check_linked_mod("test zone with circular linked modulators", list_of_mods, &linked_mod, 0);
linked_count = fluid_list_check_linked_mod("test zone with circular linked modulators",
list_of_mods, 0, &linked_mod, 0);
TEST_ASSERT(linked_count == 2);
TEST_ASSERT(linked_mod != NULL);
delete_fluid_list_mod(linked_mod);
@ -402,7 +415,8 @@ int main(void)
// Circular path is: CC->mod2, mod0, mod1.
// Remaining path CC->mod3-> is without destination.
// It remains no linked path : mod2->mod0. Return must be 0
linked_count = fluid_list_check_linked_mod("test zone with circular linked modulators", list_of_mods, NULL, 0);
linked_count = fluid_list_check_linked_mod("test zone with circular linked modulators",
list_of_mods, 0, NULL, 0);
TEST_ASSERT(linked_count == 0);
TEST_ASSERT(list_of_mods == mod0);
@ -428,7 +442,8 @@ int main(void)
// - NULL must be returned in linked_mod
// - 0 must be returned in linked_count
linked_mod = mod0; // initialize linked_mod to not NULL.
linked_count = fluid_list_check_linked_mod("test zone with circular linked modulators", list_of_mods, &linked_mod, 0);
linked_count = fluid_list_check_linked_mod("test zone with circular linked modulators",
list_of_mods, 0, &linked_mod, 0);
TEST_ASSERT(linked_count == 0);
TEST_ASSERT(linked_mod == NULL);
}
@ -463,7 +478,8 @@ int main(void)
fluid_mod_set_dest (mod3, FLUID_MOD_LINK_DEST | 2);
// return must be 0
linked_count = fluid_list_check_linked_mod("test zone with circular linked modulators", list_of_mods, NULL, 0);
linked_count = fluid_list_check_linked_mod("test zone with circular linked modulators",
list_of_mods, 0, NULL, 0);
TEST_ASSERT(linked_count == 0);
TEST_ASSERT(list_of_mods == mod0);
@ -509,7 +525,8 @@ int main(void)
fluid_mod_set_dest (mod3, FLUID_MOD_LINK_DEST | 1);
// return must be 0
linked_count = fluid_list_check_linked_mod("test zone with circular linked modulators", list_of_mods, NULL, 0);
linked_count = fluid_list_check_linked_mod("test zone with circular linked modulators",
list_of_mods, 0, NULL, 0);
TEST_ASSERT(linked_count == 0);
TEST_ASSERT(list_of_mods == mod0);
@ -556,7 +573,8 @@ int main(void)
fluid_mod_set_dest (mod3, FLUID_MOD_LINK_DEST | 1);
// return must be 0
linked_count = fluid_list_check_linked_mod("test zone with circular linked modulators", list_of_mods, NULL, 0);
linked_count = fluid_list_check_linked_mod("test zone with circular linked modulators",
list_of_mods, 0, NULL, 0);
TEST_ASSERT(linked_count == 0);
TEST_ASSERT(list_of_mods == mod0);
@ -605,7 +623,8 @@ int main(void)
fluid_mod_set_dest (mod3, FLUID_MOD_LINK_DEST | 1);
// return must be 2
linked_count = fluid_list_check_linked_mod("test zone with circular linked modulators", list_of_mods, NULL, 0);
linked_count = fluid_list_check_linked_mod("test zone with circular linked modulators",
list_of_mods, 0, NULL, 0);
TEST_ASSERT(linked_count == 2);
TEST_ASSERT(list_of_mods == mod0);
@ -651,7 +670,8 @@ int main(void)
fluid_mod_set_dest (mod2, FLUID_MOD_LINK_DEST | 0);
// return must be 0
linked_count = fluid_list_check_linked_mod("test zone with invalid linked modulators", list_of_mods, NULL, 0);
linked_count = fluid_list_check_linked_mod("test zone with invalid linked modulators",
list_of_mods, 0, NULL, 0);
TEST_ASSERT(linked_count == 0);
// order is not changed
@ -695,7 +715,8 @@ int main(void)
fluid_mod_set_dest (mod2, FLUID_MOD_LINK_DEST | 0);
// return must be 2
linked_count = fluid_list_check_linked_mod("test zone with invalid linked modulators", list_of_mods, NULL, 0);
linked_count = fluid_list_check_linked_mod("test zone with invalid linked modulators",
list_of_mods, 0, NULL, 0);
TEST_ASSERT(linked_count == 2);
// order is not changed
@ -744,7 +765,8 @@ int main(void)
list_of_mods = mod0;
// return must be 2
linked_count = fluid_list_check_linked_mod("test zone with isolated modulators", list_of_mods, NULL, 0);
linked_count = fluid_list_check_linked_mod("test zone with isolated modulators",
list_of_mods, 0, NULL, 0);
TEST_ASSERT(linked_count == 2);
TEST_ASSERT(list_of_mods == mod0);
@ -770,7 +792,8 @@ int main(void)
// - not NULL must be returned in linked_mod
// - 2 must be returned in linked_count
linked_mod = NULL; // initialize linked_mod to NULL.
linked_count = fluid_list_check_linked_mod("test zone with linked modulators", list_of_mods, &linked_mod, 0);
linked_count = fluid_list_check_linked_mod("test zone with linked modulators",
list_of_mods, 0, &linked_mod, 0);
TEST_ASSERT(linked_count == 2);
TEST_ASSERT(linked_mod != NULL);
delete_fluid_list_mod(linked_mod);
@ -860,7 +883,7 @@ int main(void)
// linked_mod1 is allocated internally.
linked_mod1 = NULL;
linked_count1_out = fluid_list_check_linked_mod("linked_mod1(internal)",
list_mod1, &linked_mod1, 0);
list_mod1, 0, &linked_mod1, 0);
// linked_mod1 is expected to be not NULL
TEST_ASSERT(linked_mod1 != NULL);
// Modulators in input list list_mod1 are fully valid. This leads to
@ -875,7 +898,7 @@ int main(void)
// linked_mod2 is expected to be not NULL
TEST_ASSERT(linked_mod2 != NULL);
linked_count2_out = fluid_list_check_linked_mod("linked_mod2(external)",
list_mod2, &linked_mod2,
list_mod2, 0, &linked_mod2,
linked_count2_in);
// Modulators in input list list_mod2 are fully valid. This leads to
// linked_count2_out that is expected to be equal to mod_count.
@ -884,12 +907,131 @@ int main(void)
// identic element.
TEST_ASSERT(fluid_list_test_identity(linked_mod1, linked_mod2) == TRUE);
// freeing
// freeing: linked_mod2 is supplied as a table on stack. It must not freed !
delete_fluid_list_mod(list_mod1);
delete_fluid_list_mod(list_mod2);
delete_fluid_list_mod(linked_mod1);
}
// Test 11: same as test 10 except input list_mod2 is a table supplied by the caller
// - List_mod2 is expected to be initialized as a list. Both list_mod1 and list_mod2
// lists are compared and expected to have identic element.
//
// - Both linked_mod1 and linked_mod2 lists are compared and expected to have identic
// element.
printf("\nTest 11: same as test 10 except list_mod2 is a table supplied by the caller\n");
{
/* One valid complex modulators with 5 members */
/* table : att<-m0<-m1<-m2<- */
/* m0<-m3<-m4<- */
fluid_mod_t mod_table[] =
{
/* Gen<-mod0-link<- */
{
// dest , src1 , flags1 , src2 , flags2
GEN_VOLENVHOLD , FLUID_MOD_LINK_SRC, FLUID_MOD_GC , FLUID_MOD_NONE , FLUID_MOD_GC,
// amount, link, next
1.0 , 0.0 , NULL
},
/* mod0<-mod1<- */
{
// dest , src1 , flags1 , src2 , flags2
0|FLUID_MOD_LINK_DEST, FLUID_MOD_LINK_SRC, FLUID_MOD_GC , FLUID_MOD_VELOCITY, FLUID_MOD_GC,
// amount, link, next
2.0 , 0.0 , NULL
},
/* mod1<-mod2<- */
{
// dest , src1 , flags1 , src2 , flags2
1|FLUID_MOD_LINK_DEST, 2 , FLUID_MOD_CC , FLUID_MOD_NONE , FLUID_MOD_GC,
// amount, link, next
3.0 , 0.0 , NULL
},
/* mod0<-mod3<- */
{
// dest , src1 , flags1 , src2 , flags2
0|FLUID_MOD_LINK_DEST, FLUID_MOD_LINK_SRC, FLUID_MOD_GC , FLUID_MOD_NONE , FLUID_MOD_GC,
// amount, link, next
4.0 , 0.0 , NULL
},
/* mod3<-mod4<- */
{
// dest , src1 , flags1 , src2 , flags2
3|FLUID_MOD_LINK_DEST, 2 , FLUID_MOD_CC , FLUID_MOD_NONE , FLUID_MOD_GC,
// amount, link, next
5.0 , 0.0 , NULL
}
};
//--- Input lists build from the table mod_table
int mod_count; // number of modulators in table mod_table.
fluid_mod_t * list_mod1; // first input list, build from mod_table.
fluid_mod_t * list_mod2; // supplied by the caller as a table.
//--- first output list of linked modulators (allocated internally):
fluid_mod_t * linked_mod1; // first output list of linked modulators.
int linked_count1_out; // count of modulators returned in linked_mod1.
//--- second output list of linked modulators. The table is given by the caller:
fluid_mod_t * linked_mod2; // second output list of linked modulators (in table).
int linked_count2_in; // length of linked_mod2 table (in modulator number).
int linked_count2_out; // count of modulators returned in linked_mod2.
//---------------------------------------------
// Same as test 10: build input lists list_mod1:
mod_count = sizeof(mod_table) / sizeof(fluid_mod_t);
TEST_ASSERT(mod_count == 5);
list_mod1 = fluid_build_list(mod_table, mod_count);
// list_mod1 and list_mod2 are expected not NULL, and count of modulators
// is expected to be equal to mod_count.
TEST_ASSERT(list_mod1 != NULL);
TEST_ASSERT(fluid_get_count_mod(list_mod1) == mod_count);
//---------------------------------------------
// Same as test 10: building output list linked_mod1 by calling fluid_list_check_linked_mod().
// list_mod1 is supplied as a list.
// linked_mod1 is allocated internally.
linked_mod1 = NULL;
linked_count1_out = fluid_list_check_linked_mod("linked_mod1(internal)",
list_mod1, 0, &linked_mod1, 0);
// linked_mod1 is expected to be not NULL
TEST_ASSERT(linked_mod1 != NULL);
// Modulators in input list list_mod1 are fully valid. This leads to
// linked_count1_out that is expected to be equal to mod_count.
TEST_ASSERT(linked_count1_out == mod_count);
//---------------------------------------------
// building output list linked_mod2 by calling fluid_list_check_linked_mod().
// list_mod2 is supplied as a table.
list_mod2 = mod_table;
// linked_mod2 is allocated externally on (stack) in a table.
linked_count2_in = mod_count;
linked_mod2 = alloca( linked_count2_in * sizeof(fluid_mod_t));
// linked_mod2 is expected to be not NULL
TEST_ASSERT(linked_mod2 != NULL);
linked_count2_out = fluid_list_check_linked_mod("list_mod2(table)-linked_mod2(external)",
list_mod2, mod_count, &linked_mod2,
linked_count2_in);
// Table list_mod2 is espected to be initialized as a list.
TEST_ASSERT(fluid_get_count_mod(list_mod2) == mod_count);
// Both list_mod1 and list_mod2 lists are compared and expected to have identic
// element.
TEST_ASSERT(fluid_list_test_identity(list_mod1, list_mod2) == TRUE);
// Same as test 10. Modulators in input list list_mod2 are fully valid. This leads to
// linked_count2_out that is expected to be equal to mod_count.
TEST_ASSERT(linked_count2_out == mod_count);
// Both linked_mod1 and linked_mod2 lists are compared and expected to have
// identic element.
TEST_ASSERT(fluid_list_test_identity(linked_mod1, linked_mod2) == TRUE);
// freeing: list_mod2 is supplied as a table. It must not freed !
// linked_mod2 is supplied as a table on stack. It must not freed !
delete_fluid_list_mod(list_mod1);
delete_fluid_list_mod(linked_mod1);
}
delete_fluid_mod(mod0);
delete_fluid_mod(mod1);
delete_fluid_mod(mod2);