Add Polymono Support (#306)

This commit implements the polymono functionality as per MIDI spec.
closes #306
resolves #158

Squashed commit of the following:

commit b56e92b378f21b7fbc189e8c580d85e679c2ee3f
Merge: 07f4c53 30c9dda
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Sat Mar 3 14:20:23 2018 +0100

    Merge branch 'master' into polymono

commit 07f4c53b9a0e46f511134d39d72073523fc3e202
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Fri Mar 2 16:51:46 2018 +0100

    update API docs for polymono

commit 82c74ff07251e0fb34b15a066f501bf1e968a51c
Merge: f07e515 ba2c053
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Fri Mar 2 10:41:43 2018 +0100

    Merge branch 'master' into polymono

commit f07e515ebdeb3d075bd9307ebf8768a6ffaae3e3
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Fri Mar 2 10:39:44 2018 +0100

    clarify comment

commit 7635825325a168f9ee383afd8023d82d4c33c185
Author: jjceresa <jjc_fluid@orange.fr>
Date:   Thu Mar 1 04:13:52 2018 +0100

    Enhancement of portamento performance calculation.
    - The lost of performance is now -0.5% rather -12%.

commit 09cb1d3ec6ced215adec9faa09fac5cae6c0f8fc
Author: jjceresa <jjc_fluid@orange.fr>
Date:   Wed Feb 21 19:40:17 2018 +0100

    moving polymono commands among synth commands

commit 63b8c480226b15d5d5bee5de8e1722a93ff69493
Author: jjceresa <jjc_fluid@orange.fr>
Date:   Wed Feb 21 03:16:10 2018 +0100

    fixes comments, FLUID_INLINE, update pdf

commit 49c1ee39d2ef525ac0af22ab22a4d8f8d49ab0e9
Merge: 200c860 4a0a736
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Sun Feb 11 17:38:31 2018 +0100

    Merge branch 'master' into polymono

commit 200c8609582560d781c0d49b99a9d02bdb7d2a2a
Author: jjceresa <jjc_fluid@orange.fr>
Date:   Thu Feb 8 23:27:28 2018 +0100

    Fixes typos, update /doc/polymono

commit 9f6474cee712f947a0227957acbb4d1e4f56f2d6
Merge: cb7f43f 28b1bef
Author: jjceresa <jjc_fluid@orange.fr>
Date:   Wed Feb 7 00:44:52 2018 +0100

    merge before updating pdf document.

commit cb7f43feb56edeed016b0b3ad7293fbd64beb7ae
Author: jjceresa <jjc_fluid@orange.fr>
Date:   Wed Feb 7 00:40:52 2018 +0100

    fixes typos in pdf document

commit 28b1bef97a498ea5e15fdffb57b861998642bd5a
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Tue Feb 6 23:02:05 2018 +0100

    avoid type redefinition warning

commit 551940854053ccf0ff0d4cfd21d0e6328a9e657c
Author: jjceresa <jjc_fluid@orange.fr>
Date:   Tue Feb 6 18:58:16 2018 +0100

    cleanup fluid_synth.c

commit 263f9badcb7f75bf8027df60abb20b3354ea67e2
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Tue Feb 6 16:36:55 2018 +0100

    cleanup fluid_synth.h

commit fd58bc0c22756b67e75c80ed8efecfed9baf2901
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Tue Feb 6 16:30:46 2018 +0100

    move synth API macros back to fluid_synth.c

commit 101ea0961a18c4724d7bd7f4d47f5a7fc27bb679
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Tue Feb 6 16:17:15 2018 +0100

    rename fluid_synth_mono.c to fluid_synth_monopoly.c

commit ec60840304fdebf4d854a0879045249e9a90af79
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Tue Feb 6 16:05:06 2018 +0100

    move fluid_synth_polymono functions back to fluid_synth.c

commit b18e99d34fcfef1444f235bed4c866985433f072
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Tue Feb 6 15:43:18 2018 +0100

    explicitly check for default_vel2att_mod

commit ceeba2af7824c3e12f6a5302d79d4e582732141d
Author: jjceresa <jjc_fluid@orange.fr>
Date:   Sun Feb 4 22:30:17 2018 +0100

    Using INVALID_NOTE instead of -1
    - polishing fluid_synth_noteon_monopoly_legato().
    - Adds chapter "introducing Poly/mono basic channels API" (2.6.1) in pdf.

commit 04d1a2119ad4847797c9cfc848a4158c6b0b3ce8
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Sun Feb 4 19:49:25 2018 +0100

    const correctness

commit 7583bc24ad21df5e01b73b685f50e8a2eef3b2f3
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Sun Feb 4 19:45:05 2018 +0100

    fix naming convention

commit a8e109f9f1ec3a55b6e0b9bfd9163e6dd4ea9e09
Author: jjceresa <jjc_fluid@orange.fr>
Date:   Sun Feb 4 01:39:58 2018 +0100

    fixes comments, update pdf

commit 1f33394a6579f9ee7341246df3e110db6926abeb
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Sat Feb 3 17:19:33 2018 +0100

    remove duplicate comments

commit e9451695aafece991af74ee2cfb9368d256c728a
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Sat Feb 3 17:06:09 2018 +0100

    specify enum types explicitly

commit f810f1942eaf19447ed29487209e227d7c4f8bd6
Author: jjceresa <jjc_fluid@orange.fr>
Date:   Fri Feb 2 18:54:03 2018 +0100

    fix construction of new_mode - cleanup comment

commit 3108da38ecc877e2f7428db0a988e1f05d324743
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Fri Feb 2 11:42:44 2018 +0100

    cleanup fluid_synth_cc_LOCAL()

commit d61eea6aeff75cfb051e4baf546ff26073c2e62b
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Fri Feb 2 11:18:46 2018 +0100

    inline warn string

commit b7ed427470309e85c44da632f6fe9a319fc49683
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Fri Feb 2 11:16:14 2018 +0100

    unlock API mutex

commit bc12603c993bf4af8ad260e18fd79f46e98c0785
Author: jjceresa <jjc_fluid@orange.fr>
Date:   Fri Feb 2 00:33:04 2018 +0100

    fix comments in fluid_synth_polymono.c

commit 34d8b73d856e3a0f664bfc816f20beff5f340627
Author: jjceresa <jjc_fluid@orange.fr>
Date:   Thu Feb 1 23:59:27 2018 +0100

    fixes typos in comments

commit eba067d735118077bf6bd8bb4ebb4bdab5046258
Author: jjceresa <jjc_fluid@orange.fr>
Date:   Thu Feb 1 23:47:58 2018 +0100

    moving fluid_synth_check_next_basic_channel()

commit 7976be599a4940ec0dc4420954ef8cfe310dd386
Author: jjceresa <jjc_fluid@orange.fr>
Date:   Wed Jan 31 23:26:42 2018 +0100

    fluid_synth_set_basic_channel_LOCAL cannot change an existing basic
    channels.
    - Both fluid_synth_set_basic_channel_LOCAL() and
      fluid_synth_set_basic_channel_LOCAL() behave the same way.
    - Update documentation pdf.

commit a22d1a35fac5b4f697c1d41ae3e368a61a27d653
Author: jjceresa <jjc_fluid@orange.fr>
Date:   Tue Jan 30 14:07:50 2018 +0100

    command setbasicchannels can change an existing basic channel.
    - fix comments.
    - update documentation pdf.

commit 4777f7b1f428935691be7d1289cb244c56137793
Author: jjceresa <jjc_fluid@orange.fr>
Date:   Mon Jan 29 23:37:16 2018 +0100

    fluid_synth_set_basic_channel() is not allowed to change an existing basic channel

commit 5161e4cec71a5c09eed08510458544257b7a66b2
Merge: 435d062 2a4b208
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Sat Jan 27 14:40:58 2018 +0100

    Merge branch 'master' into polymono

commit 435d062513583dea397686ec8fd442eba732f820
Author: jjceresa <jjc_fluid@orange.fr>
Date:   Sat Jan 27 00:09:42 2018 +0100

    Fixes typos, update pdf documentation

commit 13a8c6c6dd1a7dc861e367aed286c7f071b4e0ea
Author: jjceresa <jjc_fluid@orange.fr>
Date:   Fri Jan 26 19:49:18 2018 +0100

    correct comments of fluid_synth_set_basic_channel()
    - comments compliant with MIDI spec when val is 0.
      "means all possible channels from basic channel to
       MIDI count - 1".

commit 0689257d8f1e880617a6039b677c1fe26a02d27b
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Thu Jan 25 20:03:07 2018 +0100

    remove redundant channel mode flags from public API

commit d632e30c419652cbb5e986fb35aeaf055dfc5b43
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Thu Jan 25 19:57:11 2018 +0100

    make fluid_synth_get_basic_channel() only return MIDI modes

    not fluidsynth's internal flags

commit d1aa433e4a9aa1121bfaa78e1aa33e7ea5a88bae
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Thu Jan 25 19:43:42 2018 +0100

    update API doc of fluid_synth_reset_basic_channel()

commit b96f17b0c95a43e172da876108cb50756d023f94
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Thu Jan 25 19:34:21 2018 +0100

    make val of fluid_synth_set_basic_channel() compliant to MIDI spec

commit 904fd36bc1fa7013665190d3a54469094892c0ec
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Thu Jan 25 19:25:16 2018 +0100

    rename fluid_synth_reset_basic_channels() to fluid_synth_reset_basic_channel()

commit 15a52f6bdfda37f5b25909ad566405543b4c0572
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Thu Jan 25 19:21:00 2018 +0100

    API doc cleanup and clarification

commit 74c22da6fbfc3444cba448945579e451c28a333b
Author: jjceresa <jjc_fluid@orange.fr>
Date:   Wed Jan 24 13:50:45 2018 +0100

    Fixes mores comments in synth.h, fluid_cmd.c, fluid_synth_polymono.c

commit 6718cfe68e8e4209bfc396d53bdc71f27edea1ba
Author: jjceresa <jjc_fluid@orange.fr>
Date:   Tue Jan 23 20:19:17 2018 +0100

    fix build, fix minor comments

commit 9a4d9afc4230a3ff1ebfe8f5035ddd4aee1d4484
Author: jjceresa <jjc_fluid@orange.fr>
Date:   Tue Jan 23 19:53:12 2018 +0100

    Cleanup basic channels API.
    - Removing fluid_basic_channels_infos struct.
    - Removing fluid_synth_get_basic_channels() API.
    - Clarifying fluid_synth_reset_basic_channels() API and fluid_synth_set_basic_channel() APIs.
    - Changes commands resetbasicchannels , setbasicchannels accordling to API changes.
    - Replace fluid_synth_get_channel_mode() API by fluid_synth_get_basic_channel() API.

commit a2ec80ded11f95fcbde842c69b69efd8023c0e44
Author: jjceresa <jjc_fluid@orange.fr>
Date:   Fri Jan 19 13:35:32 2018 +0100

    update examples in /doc/polymono, fix comments

commit 1f283c49551d546db2394ba376291f716f8f3bbc
Author: jjceresa <jjc_fluid@orange.fr>
Date:   Thu Jan 18 18:15:47 2018 +0100

    remame SIZE_MONOLIST to FLUID_CHANNEL_SIZE_MONOLIST

commit 06093a23e42379ba05ba888937bc9351208583c0
Author: jjceresa <jjc_fluid@orange.fr>
Date:   Thu Jan 18 16:08:43 2018 +0100

    Adding comments compliant with MIDI specs.
    - Adding comments compliant with MIDI spec. for val parameters.
    - Cleanup comments.
    - Cleanup pdf document.

commit 87e1dbda569b91f5f585232e4ca9086ac579b350
Author: jjceresa <jjc_fluid@orange.fr>
Date:   Mon Jan 15 10:23:43 2018 +0100

    Adding fluid_synth_get_previous_basic_channel()

commit 82fa1702643a506667c6d997962ac63381ce81ce
Author: jjceresa <jjc_fluid@orange.fr>
Date:   Sun Jan 14 11:28:37 2018 +0100

    adding fluid_channel_update_legato_staccato_state()

commit 3309b6f172c56e9cb7c95fbeb09f6ebfe88351da
Author: jjceresa <jjc_fluid@orange.fr>
Date:   Fri Jan 12 22:49:22 2018 +0100

    integrates fluid_channel_keep_lastnote_monolist()

commit 92f1e9230d065c8153baf64b77222891de417c99
Author: jjceresa <jjc_fluid@orange.fr>
Date:   Thu Jan 11 02:24:53 2018 +0100

    adds comments

commit f4241272d8fdd70da268fbdf04458055f084c446
Author: jjceresa <jjc_fluid@orange.fr>
Date:   Thu Jan 11 01:32:53 2018 +0100

    Removing prev field in mononote struct
    - this is replaced by adding i_prev parameter in  functions
      fluid_channel_search_monolist(),fluid_channel_remove_monolist().

commit b09da5ed213ba36279755a306c379d33e3cd3716
Author: jjceresa <jjc_fluid@orange.fr>
Date:   Thu Jan 11 01:28:11 2018 +0100

    update comment API, update pdf

commit 3308ca252d1f5894be6d9c26bb1763a2efb6a5a9
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Wed Jan 10 11:01:45 2018 +0100

    use fluid_cb2amp rather than fluid_atten2amp

    fixes build

commit 6d648f44aeb1132e0f576521c2f35c4e30e7122f
Merge: f881a08 37218ba
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Wed Jan 10 11:00:41 2018 +0100

    Merge branch 'master' into polymono

commit f881a08e6b3019f07a675e3dc11972364f1e4620
Author: jjceresa <jjc_fluid@orange.fr>
Date:   Wed Jan 10 09:51:23 2018 +0100

    naming convention for fluid_synth_polymono

commit bfb359a3299c7c6cc3384aa11a63eac354d93b62
Author: jjceresa <jjc_fluid@orange.fr>
Date:   Tue Jan 9 13:16:52 2018 +0100

    apply allman braces

commit 9275d7ae677463f8354c1163d9fd5af92a669b40
Author: jjceresa <jjc_fluid@orange.fr>
Date:   Tue Jan 9 11:23:18 2018 +0100

    adding result checking functions

commit 6e3c804ca4a43394929b6f77b6f43d486ea1db24
Author: jjceresa <jjc_fluid@orange.fr>
Date:   Mon Jan 8 12:48:39 2018 +0100

    removing tabs mixed with spaces

commit 94c46a8b689db7ce2e214f574d061d1f61f73e4b
Author: jjceresa <jjc_fluid@orange.fr>
Date:   Sun Jan 7 19:29:01 2018 +0100

    fix comment

commit 1bedf8d5d4c547a7d7c9b920e7bfefa8204ed894
Author: jjceresa <jjc_fluid@orange.fr>
Date:   Sun Jan 7 19:05:06 2018 +0100

    rename key_sustained, cleanup, fix typos

commit 959144acad2312085ade3071c2cfa5b82ab87511
Author: jjceresa <jjc_fluid@orange.fr>
Date:   Sun Jan 7 04:36:27 2018 +0100

    fix typos in comments

commit c7b25cfd120f70c5b4092e5c625e903eeb40afdc
Author: jjceresa <jjc_fluid@orange.fr>
Date:   Sun Jan 7 04:17:15 2018 +0100

    cleanup on search/remove monolist functions

commit 756424065e67913b09a1945413cde4513f727426
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Sat Jan 6 20:22:22 2018 +0100

    fix typo

commit da991a236fac2e273aa9d60acb89061db956e980
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Sat Jan 6 20:20:51 2018 +0100

    use FLUID_STRCMP wrapper macro

commit 0dc6d9bcd06615f9d33dfea7beec5fa29dc7230c
Author: jjceresa <jjc_fluid@orange.fr>
Date:   Sat Jan 6 00:22:48 2018 +0100

    simplify arguments checking functions

commit 0103aa4ab08ab3cc8fe12906e8193f6a2a1984bd
Author: jjceresa <jjc_fluid@orange.fr>
Date:   Fri Jan 5 16:57:12 2018 +0100

    fix build warning

commit 26773a567b894e2720038a26752b56b8705f4464
Author: jjceresa <jjc_fluid@orange.fr>
Date:   Fri Jan 5 16:04:17 2018 +0100

    declare release_voice_on_same_note_LOCAL in fluid_synth.h

commit 693ba8d300d824674b3d3d0dea0d89eb46a83e69
Author: jjceresa <jjc_fluid@orange.fr>
Date:   Fri Jan 5 15:50:39 2018 +0100

    fix global cc, update comment, update pdf

commit 9d35a509480aef4ea5be09c453fc0c5ce7e53077
Author: jjceresa <jjc_fluid@orange.fr>
Date:   Fri Jan 5 14:44:22 2018 +0100

    adding arguments checking functions

commit bd63cd2021bf46a78454884ba5c76a9659d3e5ee
Author: jjceresa <jjc_fluid@orange.fr>
Date:   Thu Jan 4 18:01:57 2018 +0100

    missing static const

commit 4d24109b457a038cfb70d7e2fbe7fbbd1e25d05c
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Wed Jan 3 20:04:38 2018 +0100

    apply naming convention to is_valid_note

commit b1b6738b982cddd4c08839f557a46a6c8b23fa02
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Wed Jan 3 20:00:46 2018 +0100

    reoder fluid_channel_* declarations

commit 56279b2622d738c1c910d7c64a30ab055670a6a1
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Wed Jan 3 19:56:40 2018 +0100

    move fluid_channel_*() functions to fluid_chan.c

commit 2e54feb3beb0b89ec2203de259fa93c5343f1dfe
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Wed Jan 3 19:30:46 2018 +0100

    more naming convention for fluid_synth_mono.c

commit cd84bf96af7b4219920b5b070fbbf606eb5a21ef
Author: jjceresa <jjc_fluid@orange.fr>
Date:   Wed Jan 3 18:57:13 2018 +0100

    simplify portamemto pitch calc.

commit af98b362ed0d471c46b7f1475c3c0de469d4f432
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Wed Jan 3 10:37:42 2018 +0100

    readd accidently removed custom_breath2att_mod

    fix build

commit 1a4d5d392bee44677ed8e633d2acf4589b3dfdf6
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Wed Jan 3 10:35:16 2018 +0100

    make fluid_gen_info static again

commit da4481dc278069cdc7452cd5e533613191df4830
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Wed Jan 3 10:35:08 2018 +0100

    fix comments

commit fa6734bcdc66c581de39ff8db56d737852111a86
Merge: 47a0718 dd2b78a
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Wed Jan 3 10:14:35 2018 +0100

    Merge branch 'master' into polymono

commit 47a0718175ca8bd900d8ed823d502f0ef004a7d5
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Wed Jan 3 10:11:36 2018 +0100

    cleanup fluid_synth_*() forward decl.

commit c730bcf296c0e5895158ef08bbee278a33e43e93
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Wed Jan 3 10:06:32 2018 +0100

    move polymono fluid_channel_* macros to fluid_chan.h

commit 228c7bca6a17c13ac5a82d8faaf3fbc1fba39162
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Wed Jan 3 09:57:09 2018 +0100

    apply naming convention to polymono helper macros

commit 0d2e16497f93b02649041a7dd5ff0697e94b443c
Author: jjceresa <jjc_fluid@orange.fr>
Date:   Mon Jan 1 22:36:10 2018 +0100

    move param checking, FLUID_API_ENTRY_CHAN to API, cleanup

commit 1d73cec83bc4da75b754191db0105097874c8f39
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Mon Jan 1 17:52:59 2018 +0100

    remove redundant null termination for FLUID_SNPRINTF

commit bca5472c347ef17203dfe7d37311a24b1c608b64
Merge: e64b08a 70dffe7
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Mon Jan 1 17:49:25 2018 +0100

    Merge branch 'master' into polymono

commit e64b08a800976bd5176a594f93ea4e050db5846c
Author: jjceresa <jjc_fluid@orange.fr>
Date:   Sun Dec 31 15:22:54 2017 +0100

    fix scope mode names

commit fba23b6a018a96c4cb3779b43de79eb1b82b0495
Author: jjceresa <jjc_fluid@orange.fr>
Date:   Sun Dec 31 14:53:11 2017 +0100

    fix comments, typo errors, update doc

commit 330826eb4739e8521a31d58205359a353e7fc9ef
Author: jjceresa <jjc_fluid@orange.fr>
Date:   Sun Dec 31 05:34:37 2017 +0100

    adding mode name for shell command

commit 52689198d1224540b36fc584aad0d885c9eea39a
Author: jjceresa <jjc_fluid@orange.fr>
Date:   Sat Dec 30 22:48:37 2017 +0100

    update doc API fluid_synth_set_basic_channel()

commit 329df43f5d67a99b8dcdf2c7c6dd35bec6b3e356
Author: jjceresa <jjc_fluid@orange.fr>
Date:   Sat Dec 30 19:18:45 2017 +0100

    fluid_synth_get_channel_mode() return basicchan

commit 29de66116b2bf7a1545818a0604adf5a0559420f
Author: jjceresa <jjc_fluid@orange.fr>
Date:   Sat Dec 30 17:59:32 2017 +0100

    Simplfying fluid_synth_set_basic_channel signature
    - also cleanup variable declarations (static, scope, ...).
    - calling fluid_synth_set_basic_channel_LOCAL() instead of
      fluid_synth_set_basic_channel().

commit 5e9bc3977a9a3616ac4697c6b16e186656cd2baf
Author: jjceresa <jjc_fluid@orange.fr>
Date:   Sat Dec 30 03:39:24 2017 +0100

    cleanup status variable and rename variables

commit 650ad51af9fcb1fa88ab64cfad868ce0d80fc917
Author: jjceresa <jjc_fluid@orange.fr>
Date:   Sat Dec 30 00:55:16 2017 +0100

    remove basic channels settings
    update FluidPolyMono-0004.pdf
    - removing basic channels settings.
    - addding comment for Global channel.

commit 1bbb520ab9b5c9b5cb954f3bc3d0ecf929237369
Author: jjceresa <jjc_fluid@orange.fr>
Date:   Sat Dec 30 00:49:31 2017 +0100

    update comments on breat flags

commit 795321aa8710c409dccd4773ccd8491f5427a7d9
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Fri Dec 29 20:28:30 2017 +0100

    reorder synth API macros

commit e1589234d01a62e304e8edf53107e5a404829367
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Fri Dec 29 20:20:52 2017 +0100

    introduce FLUID_API_RETURN_IF_CHAN_DISABLED macro for synth

    to reduce nesting

commit f8dee9b6ab02140d2104167fe7d273bfcf597abb
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Fri Dec 29 19:42:15 2017 +0100

    correct API comment of fluid_synth_cc()

commit 41083f4b970fa46e652609f92302f228dc6fe550
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Fri Dec 29 10:49:43 2017 +0100

    fix build

    forgot to commit fluid_synth.c

commit ac04f365c715615f44885445ba7666050c655525
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Fri Dec 29 10:49:03 2017 +0100

    remove redundant fluid_channel_get_cc_portamento helper macro

commit d707f5e0bc8807c4c43b51eb0503ef91f0d5c8b9
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Fri Dec 29 10:45:13 2017 +0100

    fix naming of fluid_channel helper macros

commit fa38f6a9b2c3250f9dd77e5fd94a7107790ad1f6
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Fri Dec 29 10:44:49 2017 +0100

    handle BREATH_MSB is switch-case

commit c68c7eb40cd020f0a0b068d8497328692c8e0800
Author: jjceresa <jjc_fluid@orange.fr>
Date:   Fri Dec 29 00:20:10 2017 +0100

    fix comment in enum fluid_basic_channel_modes

commit 56a63af296bc90f8b0e8bd075e7b4b57d2425310
Merge: c29e401 d35601a
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Thu Dec 28 20:33:19 2017 +0100

    Merge branch 'polymono' of https://github.com/FluidSynth/fluidsynth into polymono

commit c29e40157921a2de0abe8e8d7ff467ea63bc33a7
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Thu Dec 28 20:32:33 2017 +0100

    reorder polymono API calls

    to place them after the other synth functions

commit 6ac82ff2b7a4b4079ec5121b40fe06bd13a4d08c
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Thu Dec 28 20:29:52 2017 +0100

    cleanup polymono API comments

commit d35601ae5a71bfbb11f2e6ea79c5a7bf766f6983
Author: jjceresa <jjc_fluid@orange.fr>
Date:   Thu Dec 28 19:15:10 2017 +0100

    Fix typo in FluidPolyMono-0004.pdf
    Cleanup fluid_synth.c

commit 731c59bcd64ac4e1ef06decf36774ed771c7bd41
Author: jjceresa <jjc_fluid@orange.fr>
Date:   Thu Dec 28 16:50:03 2017 +0100

    Fix parameters checking in commands with no arguments.

commit 6d0fa0f53ed07edaf0a71bc219d807ee35a5f50d
Author: jjceresa <jjc_fluid@orange.fr>
Date:   Wed Dec 27 11:33:58 2017 +0100

    update doc/polymono/readme.txt

commit 3fa932e9188e27241be4acb4c4d3360ba630eda7
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Sun Dec 24 22:20:05 2017 +0100

    - Fix typos errors.

commit 59e2ed3cc52c782dbad17847f083b96fff004165
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Sun Dec 24 00:03:57 2017 +0100

    Comments additions.

commit 88f11588750b1e8196508c19e32e98ca540bf3f2
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Sat Dec 23 23:42:21 2017 +0100

    Removing fluid_voice_update_release() signature.

commit 9b8cd5e5532a6f87ed516b83f728509f2ad0d890
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Sat Dec 23 23:38:50 2017 +0100

    Removing fluid_voice_update_release().

    - removing fluid_voice_update_release().
    - adding comments.

commit 2787d150deb0c64519507f4fbfa8ef58a28d11b9
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Sat Dec 23 23:24:55 2017 +0100

    Using fluid_voice_release() in legato mode 0.

    substitute fluid_voice_update_release() by fluid_voice_release().

commit 68f7c7778b07a384d3d1648bb34bcf705a05affb
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Sat Dec 23 23:14:12 2017 +0100

    Add comments to poly/mono public API.

commit 51cedfdfed88883e00f08e4e9253f5bf08cb5287
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Sat Dec 23 00:55:09 2017 +0100

    Update FluidPolyMono-0004.pdf

    -Cleanup chapter 1.
    -Update doc API.

commit 1ac23daf6dd10f1d1c0afc52bf1d7182d4d0538f
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Fri Dec 22 23:12:38 2017 +0100

    Change enum in fluid_cmd.c

commit 902f603c102689b58f86dfd789c01155d26c8bd8
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Fri Dec 22 23:09:38 2017 +0100

    Change enum names in fluid_synth_polymono.c

commit df52819193c058cbce9201af647e740931889900
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Fri Dec 22 23:03:59 2017 +0100

    Change enum names in fluid_synth_mono.c

commit 8aea95e0f4276d9904f9428e9a2cc93d8188a3e3
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Fri Dec 22 22:56:29 2017 +0100

    Change enum names in fluid_chan.c

commit da0e94c2a8d8d7af8c5bbd81de7fa4cb7953372b
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Fri Dec 22 22:52:54 2017 +0100

    Change legato and portamento enum

    -Change enum LegatoMode to enum fluid__channel_legato_mode.
    -Change enum PortamentoModeto enum fluid__fluid__channel_portamento_mode

commit 75309ef3a322050b4d452144028ca909fef0977c
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Fri Dec 22 19:22:30 2017 +0100

    Channel mode and Breath in commands

    Make use of enum fluid_basic_channel_mode_flags.

commit 0aca0a4e9405dc2201f7201904a0192af0f4f5d4
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Fri Dec 22 19:14:12 2017 +0100

    Channel mode and breath   in fluid_synth_polymono.c

    Make use of new enum fluid_basic_channel_mode_flags

commit 4828760f45326884322d850ec50401825ded997b
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Fri Dec 22 18:52:59 2017 +0100

    Rename enum in Fluid_synth_mono.c

    Make use of new values enum fluid_basic_channel_mode_flags

commit a0246d16ed5db3d5771a9a60c13d66c628e11447
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Fri Dec 22 18:44:31 2017 +0100

    Rename enum in fluid_synth.c

    Make use of new enum  fluid_basic_channel_mode_flags

commit ba6dea233ab6667361eaefbb0e9b8cacbab6724f
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Fri Dec 22 18:10:34 2017 +0100

    Change MONO name

    Change MONO to FLUID_CHANNEL_POLY_OFF

commit 091bf7f3eeab75f1d5766592da9e6a0b1b1da5f4
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Fri Dec 22 18:04:48 2017 +0100

    Renaming enum fluid_basic_channel_mode_flags

    -Renaming enum fluid_basic_channel_mode_flags values.
    -Integrating Breath mode in enum fluid_basic_channel_mode_flags values.

commit de945f2bb3af2692f9268e3afb37093709d47845
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Fri Dec 22 03:56:40 2017 +0100

    Move signatures to fluid_chan.h

commit 614b74202b7c2d6aaf6b75cc524c908523549e37
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Fri Dec 22 03:54:36 2017 +0100

    Add sigature functions.

    void fluid_channel_set_onenote_monolist(fluid_channel_t* chan, unsigned char key, unsigned char vel);
    void fluid_channel_clear_monolist(fluid_channel_t* chan);
    void fluid_channel_invalid_prev_note_staccato(fluid_channel_t* chan);
    void fluid_channel_cc_legato(fluid_channel_t* chan, int value);
    void fluid_channel_cc_breath_note_on_off(fluid_channel_t* chan, int value);

commit 963a37a36f3c2b2d494deeb472efe8b4ce5365a7
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Fri Dec 22 01:39:25 2017 +0100

    fix incorrect cast

    fix incorrect unsigned cast.
    remove unused extern.

commit 67ff72659f4e83a0e0e24912e919071ae692f590
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Wed Dec 20 23:45:12 2017 +0100

    fix comments - fix help commands strings

commit 2c4aff8773a363fa5902f1425c302bd4da8c8c68
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Wed Dec 20 23:11:53 2017 +0100

    Fix comments.

commit 301712ac4686d2768aa6d441492a172f805c7fc4
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Wed Dec 20 23:02:55 2017 +0100

    Update FluidPolyMono-0004.pdf

commit d4c4d0fc1382ee8795d3565d2373e8c2f36600a4
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Wed Dec 20 22:45:07 2017 +0100

    Update FluidPolyMono-0004.pdf

commit 410b073565395ce6bc73194c99d9f8d48d632642
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Wed Dec 20 22:33:44 2017 +0100

    Add files via upload

commit 0ce5bc65a676144631a3264ef27a6602b87152ae
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Wed Dec 20 19:27:16 2017 +0100

    Update poly_mono_4.txt

commit 088fd806464187dc23e07c843c3a25925a94313f
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Wed Dec 20 19:22:36 2017 +0100

    Adds files leg_port_00.txt - leg_port_01.txt

commit 9b98446a3f1c49c7bfcd51eb00a726eb918cdb70
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Wed Dec 20 19:13:29 2017 +0100

    Delete leg_por_4.txt

commit c832a9b123af5456bce860197786f50555111652
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Wed Dec 20 19:13:12 2017 +0100

    Delete leg_por_3.txt

commit 8cacbb99375b37310e30c1a681bcdcb204a9bd91
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Wed Dec 20 19:12:57 2017 +0100

    Delete leg_por_2.txt

commit af04826db6ca384ed1797fcedf9200db40bbe458
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Wed Dec 20 19:12:42 2017 +0100

    Delete leg_por_1.txt

commit 0cdf52de97779720917839f842d776eb7e1a7856
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Wed Dec 20 19:12:25 2017 +0100

    Delete leg_por_0.txt

commit d750fe34dbd918bf0f3e6be391befc16c962bd1d
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Wed Dec 20 19:10:12 2017 +0100

    Update leg_01.txt

commit 1d9541d8cddb3a761d26739556275560d43acc10
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Wed Dec 20 19:08:53 2017 +0100

    Update leg_00.txt

commit 237f6d500c375aea569930c675ff3463796e71b6
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Wed Dec 20 19:03:44 2017 +0100

    Delete Legato_demo.sf2

commit e875c02fbe8bf11fb3cb3ffc847e1d786c952a15
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Wed Dec 20 19:01:34 2017 +0100

    Update readme.txt

    Removing soundfont file

commit 07335cfdb93a6b65d595debdef7973b53adfb62e
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Wed Dec 20 00:36:23 2017 +0100

    Add FluidPolyMono-0004.pdf

commit aa94b3fe12a1301a23c10a3f69a8212d18c36d8e
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Wed Dec 20 00:34:36 2017 +0100

    Update readme.txt

commit 3aa942922149541102f2c46584aac1aa1341c5ab
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Wed Dec 20 00:33:54 2017 +0100

    Delete FluidPolyMono-0003.pdf

commit ddd9b2de37d056a20b430f113e351ea6c786fc8e
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Wed Dec 20 00:30:52 2017 +0100

    documentation files adding/update

         leg_00.txt
         leg_01.txt
         poly_mono_0.txt
         poly_mono_1.txt
         poly_mono_2.txt
         poly_mono_3.txt
         poly_mono_4.txt
         poly_mono_5.txt

commit 89983fb42eb54a6bab5b6045e5a31a6800ef23ba
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Wed Dec 20 00:26:50 2017 +0100

    Update readme.txt

    Removing legato modes 0,3,4
    Tutorials examples addition chapter 2.1
         poly_mono_0.txt
         poly_mono_1.txt
         poly_mono_2.txt
         poly_mono_3.txt
         poly_mono_4.txt
         poly_mono_5.txt

commit dcedce20d79d317c834bfd6c961a3fdf87ed1f7f
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Wed Dec 20 00:17:56 2017 +0100

    Delete leg_2.txt

commit a9d765def0170e204027abfa42fc02acfdd47704
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Wed Dec 20 00:17:29 2017 +0100

    Delete leg_1.txt

commit 8e0fc533d69cb261c0cfd6a8f58fe729b758ab0e
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Wed Dec 20 00:17:00 2017 +0100

    Delete leg_4.txt

commit ae670075e592241830ef539c9bf26c4cd84a3a47
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Wed Dec 20 00:16:14 2017 +0100

    Delete leg_3.txt

commit 6040f7575277f53c8803155d58fd158cb8e29a5f
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Wed Dec 20 00:15:23 2017 +0100

    Delete leg_0.txt

commit 1e8c4ad4dc7b6ecd0727a73b0ac814679b9fd4f3
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Tue Dec 19 23:34:03 2017 +0100

    fix build type conflict.

commit a0fa4debd6fc21d652edfabaaf963b31babcd045
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Tue Dec 19 23:21:10 2017 +0100

    Removing legato modes (0,3,4).

commit f53476bfc0c46b313f5b293243a3f3b6d9c3af64
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Tue Dec 19 23:01:50 2017 +0100

    Removing legato modes (0,3,4).

commit d69868bdb8179e1eb75661d6b02799de0d7a3e48
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Tue Dec 19 22:57:22 2017 +0100

    Removing legato modes (0,3,4).

commit ebd37fdb680e3062f0174fe7c414b3fce6b8c60f
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Tue Dec 19 22:53:38 2017 +0100

    Removing legato modes (0,3,4).

commit 265eeb4f321a8bab54ae6aa700474d96a3c83951
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Tue Dec 19 22:47:25 2017 +0100

    Removing legato modes (0,3,4).

commit 601216e83e01953c58ceabd0e44cc4f361d1c4ae
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Tue Dec 19 22:44:18 2017 +0100

    Removing legato modes (0,3,4).

commit 16b0e65697d57d3bc653e3419d924799b37e3a01
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Tue Dec 19 22:39:17 2017 +0100

    Removing legato modes (0,3,4).

commit 5c4b9322e7b6f8600be9849d869233f20beb3d4c
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Tue Dec 19 22:31:16 2017 +0100

    Two legato modes 1 and 2 (rnumbered 0 and 1).

    Removing legato modes (0,3,4).
    Legato modes 1,2 are numbered 0,1 respectively.

commit 8c4096910e9e44c896f7169345d6a262a17e522d
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Tue Dec 19 22:25:33 2017 +0100

    Two legato modes 0 and 1 (dfefault mode: 1).

commit fb4205b215648efc1949708073f68237eed8679a
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Tue Dec 19 22:20:56 2017 +0100

    Two legato modes 1 and 2 (rnumbered 0 and 1).

    Removing legato modes (0,3,4).
    Legato modes 1,2 are numbered 0,1 respectively.

commit d0adfe31f4961d034483a95705ac8b86839cf11d
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Sat Dec 16 11:42:31 2017 +0100

    refactor poly mono bit flags

commit da5ac8dd79479b6a19f5c3608be7ec3507a5b637
Merge: 13754fa 07a167c
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Sat Dec 16 10:37:34 2017 +0100

    Merge branch 'master' into polymono

commit 13754fad6acbce51bdf5b57526a4ca243948a3ed
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Fri Dec 15 19:38:04 2017 +0100

    Fix bug in new_fluid_preset_zone().

    Add missing initialization since moving ignoreInstrumentZone check to fluid_zone_inside_range().

commit 64dc235485a004e7b0f6e8f9afae1375321f6afa
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Wed Dec 13 13:41:32 2017 +0100

    move ignoreInstrumentZone check to fluid_zone_inside_range()

commit 427a513e2caac645bc571a8fbe7e3a513f874fa1
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Wed Dec 13 13:20:36 2017 +0100

    fix spelling of IGNORE_INST_ZONE

commit c9b74903f1e54976b0ed3e5d4aa5e5a2ba2f8c1c
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Wed Dec 13 13:17:32 2017 +0100

    remove redundant NULL check

    fixes #302

commit 9c8f41be408475ebc8a16dbf468067c795ee5830
Merge: 09fcf6c 5806d9e
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Sun Dec 10 10:03:31 2017 +0100

    Merge branch 'master' into polymono

commit 09fcf6c3fc36739a29b79008224dd0b46f827cd1
Merge: 9440884 1629f9f
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Sat Dec 9 15:16:51 2017 +0100

    Merge branch 'master' into polymono

commit 944088440f4c91ce712909a12af1332b09b9a1c5
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Tue Dec 5 00:51:55 2017 +0100

    fix bug GEN_VELRANGE

commit 73caf02a323776bd320d30624ebe4dd60a1c940f
Author: derselbst <tom.mbrt@gmail.com>
Date:   Sun Dec 3 14:59:30 2017 +0100

    cleanup

commit b0f43feac5de166f5791d6203d4c78f9f4f3ab38
Author: derselbst <tom.mbrt@gmail.com>
Date:   Sun Dec 3 14:31:45 2017 +0100

    rename fluid_inst_zone_range_t to fluid_zone_range_t

    find . -type f -exec sed -i 's/fluid_inst_zone_range_t/fluid_zone_range_t/g' {} +

commit 133b418ca5641579eb22cacb5059c48b642b8f5e
Author: derselbst <tom.mbrt@gmail.com>
Date:   Sun Dec 3 14:28:45 2017 +0100

    make use of range struct for presets as well

    remove code duplications

commit 42e23a5e398520959bf1124439539e0f278a80fc
Author: derselbst <tom.mbrt@gmail.com>
Date:   Sun Dec 3 13:44:33 2017 +0100

    remove zone_range from _fluid_synth_t

    prefer explicit parameter passing rather than hacky non-threadsafe param struct saving

commit 2bc061557b9aedb9a2c0f891488aeb1122272395
Merge: 6037bdb cdfe8d3
Author: derselbst <tom.mbrt@gmail.com>
Date:   Sun Dec 3 13:31:57 2017 +0100

    Merge branch 'master' into polymono

commit 6037bdbd30f793b007c589b5f870cabea2c85c6a
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Wed Nov 29 23:45:10 2017 +0100

    fix parameter flfuid_voice_init()

commit bb0da222bd420989b63b0229568b178e8da3e293
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Wed Nov 29 23:24:12 2017 +0100

    fix IGNORE_INST_Z0NE

commit d8752cc835b52eda6122dba7d6ab2354a7e83deb
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Wed Nov 29 23:16:56 2017 +0100

    fix fluid_voice_init in voice.h

commit 41e4b77fe5f6fc0766b1974d5031d516a7ff0c11
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Wed Nov 29 23:04:45 2017 +0100

    Add zone_range tp poly_mono.c

commit f3550d18e74845a09800af8aef12f5c5da21fc7b
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Wed Nov 29 22:51:30 2017 +0100

    Add zone_range to fluid_voice_init()

commit 2e9ebad6cb5bd44e82674e87ef4fb7b88b9b9445
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Wed Nov 29 22:48:13 2017 +0100

    Add zone_range to fluid_voice_t

commit d779583c490d85ea8b14481fcedbe50efda27aed
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Wed Nov 29 22:41:45 2017 +0100

    restore fluid_synth_alloc_voice signature

    restore fluid_synth_alloc_voice signature  to synth.h

commit 27a4e4407843cfb7c7c86b6a99c0f10d43ad4326
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Wed Nov 29 22:36:06 2017 +0100

    Add zone_range to fluid_synth.c

    Restore API signature luid_synth_alloc_voice()

commit f4749fc88372a32b055a6dcb6a1b00e247d15c6b
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Wed Nov 29 22:27:03 2017 +0100

    Add zone_range to fluid_synth.h

commit 7250f40d7aa3dc074c3ffd6dfb1e6aa2821c26f2
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Wed Nov 29 22:24:37 2017 +0100

    Add zone_range to ramsfont

commit a3ffce39355c7fcb86c25ae5c0254758a502b1f3
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Wed Nov 29 22:19:39 2017 +0100

    Adding zone_range.

commit e2f99a91e58950373f99032eb1fa752805ed8eee
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Wed Nov 29 22:03:44 2017 +0100

    type fluid_inst_zone_range_t

commit adb5e74311b6010289d7f672985cc24f9153bcfd
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Wed Nov 29 21:57:05 2017 +0100

    Adding fluid_inst_zone_range_t  in fluid_inst_zone_t

commit 89ed46f063301096f0ce4a3b673a8fce3b6c4cde
Merge: 45773e1 7ed5d1f
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Fri Nov 24 17:40:17 2017 +0100

    Merge branch 'master' into polymono

commit 45773e14d21a56085da7344d0168fb87a9a58607
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Thu Nov 23 23:44:10 2017 +0100

    Ignore voices when there is no instrument zone.

commit 156eb2f547cff9e0bca43830ed35f9bb315e48c4
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Sat Nov 11 00:03:29 2017 +0100

    Fix warning build

commit 1b1233014a3d8b1fdf043d1fdd4ea51cb6b0aaf9
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Fri Nov 10 20:06:23 2017 +0100

    Fix fluid_voice_is_on(voice)

commit 88317aaaa8e33f999393a0a582110642e1726e93
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Fri Nov 10 19:55:30 2017 +0100

    Replacement of macro _ON(voice )

    Replacement of macro _ON() by fluid_voice_is_on()
    Note : fluid_voice_is_on() isn't yet in fluid_voice.h, so to avoid a failing build
    we define fluid_voice_is_on() extern.

commit 0ba247f2c6c5b93c3354069b791b46be9d9b6235
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Fri Nov 10 18:35:34 2017 +0100

    Fix functions naming in chapter 4.

commit aeaceefa24b03f0ff28b6fb734c56ab40d16fbf8
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Fri Nov 10 18:34:25 2017 +0100

    Delete FluidPolyMono-0003.pdf

commit 24f1fa56974dde407007b48f065f0779d78ddfb5
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Fri Nov 10 18:31:25 2017 +0100

    Addition of missing comments

    Comments in fluid_synth_noteon_LOCAL(),
    fluid_synth_damp_voices_by_sustain_LOCAL(),
    fluid_synth_damp_voices_by_sostenuto_LOCAL()

commit 023a101642fc246c542e900cabdbc1dae24829f0
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Thu Nov 9 23:15:59 2017 +0100

    renaming functions

commit 87e26ff24b7f30731ff59878f444c58747dc3277
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Thu Nov 9 23:08:46 2017 +0100

    Renaming functions

commit 1b41b67e6fd9ec4ee789abc0448bec8db8923046
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Thu Nov 9 23:04:54 2017 +0100

    renaming functions

commit 486dfed111bce8e48b4bad59d0330e4593e92cbf
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Thu Nov 9 22:59:41 2017 +0100

    Renaming functions

commit 0d5269520b652114251c13f0d87b2c8ec062a60c
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Thu Nov 9 22:01:24 2017 +0100

    Fix build

commit 7c0c3c2944ee15a69d7e1b6c1ae6d4c35f062156
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Thu Nov 9 21:58:46 2017 +0100

    Fix build

commit 1c7958250d48bdfa46b7df8918d087323ee9bc4c
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Thu Nov 9 20:15:35 2017 +0100

    fix build

commit dd4c86a2245c76c74781fa3dfa236cd9acfd225e
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Thu Nov 9 20:02:32 2017 +0100

    Fix build

commit 490d0745dc6e6338b2641f68bac8da86a83b6ed7
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Thu Nov 9 19:49:29 2017 +0100

    Add macro #define _ON(voice) to fix build

commit 553a1dc13b87ea0158c7dd2cab8aa7787dc60f2f
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Thu Nov 9 18:26:04 2017 +0100

    Fix build in legato_on_off()

commit e075c1e7ba695f3529422c74a77ed2571368a729
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Thu Nov 9 18:22:10 2017 +0100

    Fix comments

commit fe763339e3ac3872afcb7bbf557884d31306868a
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Thu Nov 9 18:19:01 2017 +0100

    Fix comments

commit 662a3632d863fab6e9a949e4030f3018cea49660
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Thu Nov 9 16:41:37 2017 +0100

    Updating Chapter 4

commit e15a0198fe6af9c52004159933faeb7cc7bdb0fc
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Thu Nov 9 16:40:30 2017 +0100

    Delete FluidPolyMono-0003.pdf

commit 5bec835f3aa7c4d605a04d66b7eadce9aaf2e276
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Thu Nov 9 16:01:00 2017 +0100

    Renaming fluid_synth_noteon_mono_legato()

    Renaming fluid_synth_noteon_mono_legato() to fluid_synth_noteon_monopoly_legato()

commit 1192769461366dbe496ae41d3ba24f97418013eb
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Thu Nov 9 15:56:17 2017 +0100

    Renaming fluid_synth_noteon_mono_legato()

    Renaming fluid_synth_noteon_mono_legato() to fluid_synth_noteon_monopoly_legato()

commit f76b3062f8ec32ad0cc361af3b4755db128e020e
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Thu Nov 9 15:52:51 2017 +0100

    Renaming fluid_synth_noteon_mono_legato()

    Renaming fluid_synth_noteon_mono_legato() to fluid_synth_noteon_monopoly_legato()

commit b80684df57523f55f346c95e4731756715821572
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Thu Nov 9 15:47:57 2017 +0100

    Renaming fluid_synth_noteon_mono_legato()

    Renaming fluid_synth_noteon_mono_legato() to fluid_synth_noteon_monopoly_legato()

commit 181affa17f9099fb3606ee326ee819ad4736cc6b
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Thu Nov 9 15:45:51 2017 +0100

    Renaming fluid_synth_noteon_mono_legato()

    Renaming fluid_synth_noteon_mono_legato() to fluid_synth_noteon_monopoly_legato()

commit 2efbfa98c7a2f80a11a8847ff3d89cc2d545f971
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Thu Nov 9 00:11:39 2017 +0100

    Update documentation

    Addition of figures in chapter 4.
    Part 4: Appendices for understanding implementations in FluidSynth.

commit a32b12b15c37669c1c1bda9228955bacd9844400
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Thu Nov 9 00:08:26 2017 +0100

    Delete FluidPolyMono-0003.pdf

commit ee3820fedd5024131ecbf0f6a66936792c651818
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Thu Nov 9 00:01:45 2017 +0100

    Comments addition

    Comment addition about the size of monolist SIZE_MONOLIST.

commit fbf496d8f7c79ed8a72ffb22a12f0ead28815084
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Wed Nov 8 23:57:59 2017 +0100

    Comments addition

    Comments addition relative to FluidPolyMono-0003.pdf chapter 4:
    "Appendices for understanding implementations in FluidSynth"

commit af551859b7558e73915c6fefab873c0ebb46221c
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Tue Nov 7 00:29:30 2017 +0100

    Update FluidPolyMono.pdf

    Removing obsoletes chapters.
    Adding appendices for understanding implementations in FluidSynth (see chapter 4).

commit 8953f099bcfbeb58ecbf0b4ad69e97d004cef7bd
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Tue Nov 7 00:26:36 2017 +0100

    Delete FluidPolyMono-0003.pdf

commit d000ddac93df0c12ecbe4b2de6b3d4fee1b6b06e
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Tue Nov 7 00:23:33 2017 +0100

    Fix typos errors

commit 539c0b3c5db214765ada1ac214391bea33aa2f97
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Tue Nov 7 00:19:06 2017 +0100

    Fix typos errors

commit 168669bb603fff83166e3c8df1aff972415dd921
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Sun Nov 5 03:11:11 2017 +0100

    correction typos erros

commit 8afb104f880660c08556f712aa804c2cb889eb2d
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Sun Nov 5 02:16:02 2017 +0100

    Adding a new chapter.

    Adding chapter :  3.11.	PART 3: APPENDICES FOR UNDERSTANDING IMPLEMENTATIONS IN FS.

commit d21a528e474e13d62ac4141d224b9d1d16ca8a29
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Sun Nov 5 02:13:16 2017 +0100

    delete FluidPolyMono-0003.pdf

commit 942d911dc886ef391cb8975b93c4380c1c4d8977
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Sun Nov 5 02:07:08 2017 +0100

    changes functions name

    invalid_prev_note_staccato(), legato_on_off(),breath_note_on_off()

commit 62c2529ae3f983797713b64cdaaa2e4c2cb2e3c9
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Sun Nov 5 02:01:03 2017 +0100

    Changes names functions

    invalid_prev_note_staccato(),legato_on_off(), breath_note_on_off()

commit 10271467d86530b16ef606ddbda964215e73690e
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Sun Nov 5 01:53:35 2017 +0100

    update functions documentation

    Documentation addition.
    Correct get_fromkey_portamento_legato() name.
    Changes names: legato_on_off(), breath_note_on_off(),invalid_prev_note_staccato()

commit decf7817706a5ade25903730d11135acfee77817
Merge: 84ee8b3 30c0a72
Author: derselbst <tom.mbrt@gmail.com>
Date:   Sat Nov 4 08:52:21 2017 +0100

    Merge branch 'master' into polymono

commit 84ee8b3304d87485cd21d802214d670183e51c17
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Thu Nov 2 20:18:03 2017 +0100

    Polishing and documenting

commit 99eaf83cef87555926c0078eb38912901a80b003
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Thu Nov 2 20:14:36 2017 +0100

    Polishing and documenting

commit 172a9b0cae9aef9a18abb31aa4c2d7543b4ea054
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Thu Nov 2 19:43:51 2017 +0100

    Polishing

commit 0d0b47181df5cea717ab848e88e5e87a2ce643e1
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Thu Nov 2 19:00:41 2017 +0100

    Polishing

commit f55273986d847e99814bd92d8fc109dea02a85f3
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Thu Nov 2 18:50:38 2017 +0100

    Polishing

commit fb6f0eac8ce50a987ff438e942d59d1c24b769c4
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Thu Nov 2 18:43:54 2017 +0100

    Polishing

commit fe8e7f692d89be52a95ae2726b1b20870c7fe042
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Thu Nov 2 18:35:56 2017 +0100

    Polishing

commit 8e37f562c14141c573a13bb43e9612a3586e672e
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Thu Nov 2 18:23:06 2017 +0100

    polishing

commit 8a20a766f995c3c5d9928bb46270758fc92c29a1
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Thu Nov 2 18:18:25 2017 +0100

    polishing

commit 3dab1a0edc973c0ddfa762b214a22dff4d2e9bb5
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Mon Oct 30 01:23:11 2017 +0100

    Again avoid macros

    Avoid GetPortamentoMode, GetLegatoMode macros

commit d39cfe5a199cb7179a174d11dadbfd2bcb992088
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Mon Oct 30 01:18:44 2017 +0100

    Again avoiding macros

    Avoid GetChanPortamentoMode, GetChanLegatoMode macros

commit bb519495956f5e3d0bc5264d3aea491e5de85afb
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Mon Oct 30 01:11:54 2017 +0100

    Again avoiding macros

    Avoiding GetChanLegatoMode, GetChanPortamentoMode macros

commit c31449626ad195b3fd44215f8bd51be8cfcc6a29
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Mon Oct 30 00:40:05 2017 +0100

    Add FluidPolyMono-0003.pdf

    Adding explanations about the legato detector (3.4.3).
    Adding example about breathmode (3.4.5).

commit 53f215e602156ecfbb8aeef81ba7a19e201313d4
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Mon Oct 30 00:38:15 2017 +0100

    Delete FluidPolyMono-0003.pdf

commit 7dcde051986ae8b17c0613e83f0253db647dd1ee
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Mon Oct 30 00:30:20 2017 +0100

    Again avoiding macros

commit 8afbb4503a98d9caa9a85f703d19740bd07ade36
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Mon Oct 30 00:24:57 2017 +0100

    Again avoid macros

commit 4e2a6750c15973cb2515c2f9b7971d821b04031a
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Mon Oct 30 00:16:04 2017 +0100

    Again avoid macros

commit 21ae600907287e87f35a8f9c1cd1e0fe6e920565
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Mon Oct 30 00:02:41 2017 +0100

    Again avoiding macros

commit a0ec029bd886682b3d88ed8150ef90c29a75eec7
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Sun Oct 29 23:46:53 2017 +0100

    Again avoiding macros

commit 1e583799f6690253bfcad4cbc4fb5fb0f5b9fa99
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Sun Oct 29 23:18:26 2017 +0100

    avoiding macros

commit d92445b99f0a3fd7f896bd03afca05eaa1271b9c
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Fri Oct 27 16:37:34 2017 +0200

    Avoid nested macros

commit 71d6a180cb574a754e30a821b52b1a975bc4b2f6
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Fri Oct 27 16:13:30 2017 +0200

    avoid nested macros

commit e22013c37d01734c4bc535eba65e6b2cd8db0aad
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Fri Oct 27 15:40:47 2017 +0200

    Avoid nested macros

commit 92ba702ffca8284470f45d6568ffa6d81be3a5db
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Fri Oct 27 14:54:19 2017 +0200

    Cleanup macro.

commit 2a31e93320907779cd7f56d62991bcce00bedaba
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Fri Oct 27 14:49:52 2017 +0200

    Removing nested macros.

commit 9433f2bf2c91939fddb67ba24057225c9e1be7a7
Merge: 71f7c35 cdd9f75
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Thu Oct 26 19:56:02 2017 +0200

    Merge branch 'master' into polymono

commit 71f7c35a77e8192596f95df6894dae5e2a653dc2
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Wed Oct 25 10:38:05 2017 +0200

    remove static from fluid_gen_info to fix build

commit 6c70db9065f81bc323eadcd654a5d5800ca4622c
Merge: 1dbae28 e485129
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Wed Oct 25 09:55:15 2017 +0200

    Merge branch 'master' into polymono

commit 1dbae2874f68d1eb62db2ab34dcb4e3e1105f47d
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Tue Oct 24 03:02:32 2017 +0200

    Add FluidPolyMono-0003.pdf

    Correction API documentation (see 2.6.1, 2.6.4)

commit f01b955de22c4551821199aa670c713a4456e14a
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Tue Oct 24 02:57:18 2017 +0200

    Delete FluidPolyMono-0003.pdf

commit b557289b5f6c3ccb531c6c38b45fc61e089a83bc
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Tue Oct 24 02:55:31 2017 +0200

    Replacing FLUID_POLYMONO_WARNING by FLUID_FAILED

commit 2d06adef8af6e8d2cef2e03ab669270a727a1742
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Tue Oct 24 02:52:06 2017 +0200

    Replacing  FLUID_POLYMONO_WARNING by FLUID_FAILED

commit 06108d9f7a61f8773cac02bc32749859e415794e
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Tue Oct 24 02:38:23 2017 +0200

    Replacing FLUID_POLYMONO_WARNING by FLUID_FAILED

commit 66b85fb38ec24bb3468e5b8c205a8b15a0002272
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Fri Oct 20 16:08:46 2017 +0200

    Polymono documentation has moved to ./doc/polymono

commit 1a03ef03e1ad1043152224cf604ec2bb47756f74
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Fri Oct 20 15:41:21 2017 +0200

    Adapt functions names to follow fluidsynth conventions.

commit d40cf8798612eea9accf41aba7e325d6a69f326e
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Fri Oct 20 15:33:42 2017 +0200

    Adapt functions naming to follow fluidsynth conventions.

commit 49423cb8bfb7b19b9164d6e642b4549468f003f7
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Fri Oct 20 15:28:08 2017 +0200

    Adapt functions names to fluidsynth conventions

    Avoiding  abbreviations.
    Change functions names to follow fluidsynth conventions

commit bc5345ab1c37173cf075b6572dbff5d8bd57a85a
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Fri Oct 20 14:56:41 2017 +0200

    Clarify variables spelling and bug fix

    Avoiding  abbreviations in comments and variables names.
    Bug fix.

commit 1f0a1ad3cbf1180ed242eb5997b18b79a98db6ba
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Fri Oct 20 14:48:00 2017 +0200

    Clarify variables meaning

    avoiding abbreviations in comment and variables.

commit c947686bfc8d6adde47c831a411d639938df8428
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Fri Oct 20 14:35:05 2017 +0200

    Clarify comments.

    Avoiding abbreviations on comments

commit 7e7296e276b1c9ef254788634e5e2bc565dec211
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Fri Oct 20 01:34:53 2017 +0200

    Adding others documentation files.

commit 4a6417ff8fb3afa60f6cd39f6b299759e122398c
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Fri Oct 20 01:32:02 2017 +0200

    Create readme.txt

commit 3babbed01e6fb3a264bb61d6e0be0d67e45cd853
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Wed Oct 18 16:27:48 2017 +0200

    Update and fix API parameters checking in fluid_synth_polymono.c

    Fix correction in Poly/Mono API
    fluid_synth_get_channel_mode()
    fluid_synth_set_legato_mode(), fluid_synth_get_legato_mode()
    fluid_synth_set_portamento_mode(), fluid_synth_get_portamento_mode()
    fluid_synth_set_breath_mode(),fluid_synth_get_breath_mode()

commit 98234eb7c146c75bd25cef0813b1f1b12d93ad84
Merge: bb7b483 b908c04
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Wed Oct 18 13:18:05 2017 +0200

    Merge branch 'master' into polymono

commit bb7b48340cde04ee7c8e0d19942e45de3fa5197e
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Wed Oct 18 12:51:19 2017 +0200

    fix param check for fluid_synth_set_basic_channel()

commit b2157bdc4aa614647ff0a32d46b53941999d6fed
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Wed Oct 18 12:34:14 2017 +0200

    another param check fix for fluid_synth_reset_basic_channels()

commit 2ff7dccb555099f1f508e5318aa295338638123a
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Wed Oct 18 10:52:40 2017 +0200

    correctly check parameters and enter synth API

    for fluid_synth_reset_basic_channels()

commit 55ca184b1fa1a2bfa61918d155e9b8d7a32d2c0e
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Wed Oct 18 10:29:05 2017 +0200

    move synth API entry macros to header

    so they are usable in polymono and mono synth files

commit deb1ea53a121625eaa913b9b16f4a63a8eb4183e
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Wed Oct 18 10:25:17 2017 +0200

    Revert "Update API parameter checking"

    This reverts commit 8ca4c7d16130c928580f410af9c79663fc8d069e. Crashes if synth == NULL

commit 8ca4c7d16130c928580f410af9c79663fc8d069e
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Tue Oct 17 20:50:26 2017 +0200

    Update API parameter checking

    Update Poly mono API parameters checking to be thread safe.

commit d5b95232efcc14c072d9237c26a5bd68fe647b69
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Mon Oct 16 18:25:48 2017 +0200

    Cleaning up the documentation

    Cleaning up the documentation, comments, typos errors.

commit 72d9cdfc99cef9da1638adfde86138444a8f6817
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Mon Oct 16 17:45:52 2017 +0200

    cleaning up the API documentation

    cleaning up the API documentation and comments so it is usable with doxygen.

commit bf587f4998267ebfbbc7682abdb1abec3fc12009
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Sun Oct 15 13:31:24 2017 +0200

    move polymono shell commands to fluid_cmd

    and fix build

commit 20d417e83b42ea0403f484d4c45d3723a3616c13
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Sun Oct 15 13:30:49 2017 +0200

    fix public synth portamento function decl

commit f1a9856f5f79c1fd7e9e31bdf2c1c3276545ad94
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Sun Oct 15 11:34:48 2017 +0200

    move function decl. to header

commit 4c75d038973413e97e9c52b19237cae4850e592b
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Sun Oct 15 11:12:17 2017 +0200

    fluid_synth_noteoff_monopoly(): use voice getter functions

commit fa00735fa1af49089026abf30f6763e3481bccf2
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Sun Oct 15 11:05:00 2017 +0200

    fix declaration of fluid_voice_noteoff()

commit f53c00f2e0defa91a49185919b4ea451e4b58ac9
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Sun Oct 15 11:02:18 2017 +0200

    fix broken merge of fluid_synth_program_change()

commit c18f88df9a8fd80a0ad58ad3a08ea12c6eb10681
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Sun Oct 15 11:01:58 2017 +0200

    reorder modulator decalaration

commit 12b378244be1b137dfc1e18e4e928bed8073e7c2
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Sun Oct 15 10:42:30 2017 +0200

    rename breath2att modulator

commit ba3b3c855a8dbcab1a4b8601f52577600061fd42
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Sun Oct 15 10:35:42 2017 +0200

    manually resolved conflict in fluid_synth_alloc_voice()

    for polymono

commit 7b31b8605c94bea44dbacc0779ded1ef7b3eaaab
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Sat Oct 14 11:25:49 2017 +0200

    fix indentation

commit 1d1d03cb3a27a99643e5f6a4d701b137191cd1b1
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Sat Oct 14 11:24:52 2017 +0200

    manually merge fluid_synth_noteoff_monopoly()

commit f8fa5d6534553fbb7d617f06620fd3b746349cdd
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Sat Oct 14 11:12:37 2017 +0200

    refactor fluid_voice_noteoff() to return void

commit 3430db0dce1ff0084da60beb157fb36ca1a23c7d
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Sat Oct 14 10:35:45 2017 +0200

    add PDF documenting polymono functionality

commit e3818abe427a14bcd05d7c959cd6d125533b4219
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Sat Oct 14 10:34:52 2017 +0200

    manually resolve fluid_voice_calculate_pitch() conflict

commit b94d42b3923bfcab0a270903ad69bba2d3531089
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Tue Oct 10 22:49:16 2017 +0200

    move polymono synth files to correct dir

commit 2719e03cfce460a132477080d383e5de5de70fed
Merge: badddc5 0902b26
Author: derselbst <tom.mbrt@googlemail.com>
Date:   Tue Oct 10 21:03:49 2017 +0200

    Merge branch 'master' into polymono

    a few too complex conflicts remain unresolved

commit badddc5b43e064b597c72992434a9786f1367597
Author: jjceresa <32781294+jjceresa@users.noreply.github.com>
Date:   Mon Oct 9 17:50:58 2017 +0200

    applied jjc's poly mono patch

    start of poly/mono implementation, addressing #158
This commit is contained in:
jjceresa 2018-03-03 14:22:51 +01:00 committed by derselbst
parent 30c9ddaed5
commit e24a41a447
43 changed files with 4055 additions and 432 deletions

View file

@ -125,6 +125,13 @@ Changes in FluidSynth 2.0.0 concerning developers:
- struct _fluid_preset_t
- add an additional general-purpose IIR filter, see fluid_synth_set_custom_filter()
- add a custom sinusoidal modulator mapping function, see #FLUID_MOD_SIN
- implement polymono support according to MIDI specs:
- add basic channel support, see fluid_synth_reset_basic_channel(), fluid_synth_set_basic_channel(), fluid_synth_get_basic_channel()
- implement MIDI modes Omni On, Omni Off, Poly, Mono, see #fluid_basic_channel_modes
- implement portamento control, see fluid_synth_set_portamento_mode(), fluid_synth_get_portamento_mode()
- implement legato control, see fluid_synth_set_legato_mode(), fluid_synth_get_legato_mode()
- implement breath control, see fluid_synth_set_breath_mode(), fluid_synth_get_breath_mode()
\section NewIn1_1_9 Whats new in 1.1.9?

Binary file not shown.

103
doc/polymono/leg_00.txt Normal file
View file

@ -0,0 +1,103 @@
echo "legato mode 0 (retrigger), egal velocity on n1,n2,n3..."
echo "---------------------------------------------------------"
# Sounfont: GeneralUser GS 1.471 S. Christian Collins
# Some presets
# 0: Piano 0 ; short release
# 16:organ 24:guitar
# 52: Choir Aahs 53: Voice Oohs
#
# 56:trumpet 57:trombone 58:tuba 59:muted trumpet
# 60:French horn 61:Brass section
# 62:Synth brass 1 63:Synth Brass 2
# 64:Soprano sax 65:Alto sax 66:Tenor sax 67:Baritone sax.
# 68:Oboe 69:English horn 70:Bassoon 71:Clarinet
# 72:piccolo 73:Flute 74:Recorder 75:Pan flute
#
# 99:atmosphere; attack longer than organ, release longer than piano
# 100:brillance , 101:gobelin
echo "preset 73:flute"
prog 0 73
echo "legato mode:0"
setlegatomode 0 0
echo "legato On"
cc 0 68 127
echo "noteon C 60 vel=127, during 1000 ms"
noteon 0 60 127
sleep 1000
echo "noteon D,legato up C->D (60->62, vel=127), during 1000 ms"
echo "noteoff C"
noteon 0 62 127
noteoff 0 60
sleep 1000
echo "noteon E,legato up D->E (62->64, vel=127), during 1000 ms"
echo "noteoff D"
noteon 0 64 127
noteoff 0 62
sleep 1000
echo "noteon F,legato up E->F (64->65, vel=127), during 1000 ms"
echo "noteoff E"
noteon 0 65 127
noteoff 0 64
sleep 1000
echo "noteon G,legato up F->G (65->67, vel=127), during 1000 ms"
echo "noteoff F"
noteon 0 67 127
noteoff 0 65
sleep 1000
echo "noteon A,legato up G->A (67->69, vel=127), during 1000 ms"
echo "noteoff G"
noteon 0 69 127
noteoff 0 67
sleep 1000
echo "noteon B,legato up A->B (69->71, vel=127), during 1000 ms"
echo "noteoff A"
noteon 0 71 127
noteoff 0 69
sleep 1000
echo "noteon C,legato up B->C (71->72, vel=127), during 1000 ms"
echo "noteoff B"
noteon 0 72 127
noteoff 0 71
sleep 1000
echo "noteon B,legato down C->B (72->71, vel=127), during 1000 ms"
echo "noteoff C"
noteon 0 71 127
noteoff 0 72
sleep 1000
echo "noteon A,legato down B->A (71->69, vel=127), during 1000 ms"
echo "noteoff B"
noteon 0 69 127
noteoff 0 71
sleep 1000
echo "noteon G,legato down A->G (69->67, vel=127), during 1000 ms"
echo "noteoff A"
noteon 0 67 127
noteoff 0 69
sleep 1000
echo "noteon F,legato down G->F (67->65, vel=127), during 1000 ms"
echo "noteoff G"
noteon 0 65 127
noteoff 0 67
sleep 1000
echo "noteon E,legato down F->E (65->64, vel=127), during 1000 ms"
echo "noteoff F"
noteon 0 64 127
noteoff 0 65
sleep 1000
echo "noteon D,legato down E->D (64->62, vel=127), during 1000 ms"
echo "noteoff E"
noteon 0 62 127
noteoff 0 64
sleep 1000
echo "noteon C,legato down D->C (62->60, vel=127), during 1000 ms"
echo "noteoff D"
noteon 0 60 127
noteoff 0 62
sleep 1000
echo "noteoff C"
noteoff 0 60
sleep 1000
echo "legato Off"
cc 0 68 0
echo "End legato mode 1 (retrigger_1)"

103
doc/polymono/leg_01.txt Normal file
View file

@ -0,0 +1,103 @@
echo "legato mode 1 (multi-retrigger), egal velocity on n1,n2,n3..."
echo "-------------------------------------------------------------"
# Sounfont: GeneralUser GS 1.471 S. Christian Collins
# Some presets
# 0: Piano 0 ; short release
# 16:organ 24:guitar
# 52: Choir Aahs 53: Voice Oohs
#
# 56:trumpet 57:trombone 58:tuba 59:muted trumpet
# 60:French horn 61:Brass section
# 62:Synth brass 1 63:Synth Brass 2
# 64:Soprano sax 65:Alto sax 66:Tenor sax 67:Baritone sax.
# 68:Oboe 69:English horn 70:Bassoon 71:Clarinet
# 72:piccolo 73:Flute 74:Recorder 75:Pan flute
#
# 99:atmosphere; attack longer than organ, release longer than piano
# 100:brillance , 101:gobelin
echo "preset 73:flute"
prog 0 73
echo "legato mode:1"
setlegatomode 0 1
echo "legato On"
cc 0 68 127
echo "noteon C 60 vel=127, during 1000 ms"
noteon 0 60 127
sleep 1000
echo "noteon D,legato up C->D (60->62, vel=127), during 1000 ms"
echo "noteoff C"
noteon 0 62 127
noteoff 0 60
sleep 1000
echo "noteon E,legato up D->E (62->64, vel=127), during 1000 ms"
echo "noteoff D"
noteon 0 64 127
noteoff 0 62
sleep 1000
echo "noteon F,legato up E->F (64->65, vel=127), during 1000 ms"
echo "noteoff E"
noteon 0 65 127
noteoff 0 64
sleep 1000
echo "noteon G,legato up F->G (65->67, vel=127), during 1000 ms"
echo "noteoff F"
noteon 0 67 127
noteoff 0 65
sleep 1000
echo "noteon A,legato up G->A (67->69, vel=127), during 1000 ms"
echo "noteoff G"
noteon 0 69 127
noteoff 0 67
sleep 1000
echo "noteon B,legato up A->B (69->71, vel=127), during 1000 ms"
echo "noteoff A"
noteon 0 71 127
noteoff 0 69
sleep 1000
echo "noteon C,legato up B->C (71->72, vel=127), during 1000 ms"
echo "noteoff B"
noteon 0 72 127
noteoff 0 71
sleep 1000
echo "noteon B,legato down C->B (72->71, vel=127), during 1000 ms"
echo "noteoff C"
noteon 0 71 127
noteoff 0 72
sleep 1000
echo "noteon A,legato down B->A (71->69, vel=127), during 1000 ms"
echo "noteoff B"
noteon 0 69 127
noteoff 0 71
sleep 1000
echo "noteon G,legato down A->G (69->67, vel=127), during 1000 ms"
echo "noteoff A"
noteon 0 67 127
noteoff 0 69
sleep 1000
echo "noteon F,legato down G->F (67->65, vel=127), during 1000 ms"
echo "noteoff G"
noteon 0 65 127
noteoff 0 67
sleep 1000
echo "noteon E,legato down F->E (65->64, vel=127), during 1000 ms"
echo "noteoff F"
noteon 0 64 127
noteoff 0 65
sleep 1000
echo "noteon D,legato down E->D (64->62, vel=127), during 1000 ms"
echo "noteoff E"
noteon 0 62 127
noteoff 0 64
sleep 1000
echo "noteon C,legato down D->C (62->60, vel=127), during 1000 ms"
echo "noteoff D"
noteon 0 60 127
noteoff 0 62
sleep 1000
echo "noteoff C"
noteoff 0 60
sleep 1000
echo "legato Off"
cc 0 68 0
echo "End legato mode 2 (multi-retrigger)"

107
doc/polymono/leg_por_00.txt Normal file
View file

@ -0,0 +1,107 @@
echo "legato mode 0 (retrigger), egal velocity on n1,n2,n3..."
echo "with portamento."
echo "---------------------------------------------------------"
# Sounfont: GeneralUser GS 1.471 S. Christian Collins
# Some presets
# 0: Piano 0 ; short release
# 16:organ 24:guitar
# 52: Choir Aahs 53: Voice Oohs
#
# 56:trumpet 57:trombone 58:tuba 59:muted trumpet
# 60:French horn 61:Brass section
# 62:Synth brass 1 63:Synth Brass 2
# 64:Soprano sax 65:Alto sax 66:Tenor sax 67:Baritone sax.
# 68:Oboe 69:English horn 70:Bassoon 71:Clarinet
# 72:piccolo 73:Flute 74:Recorder 75:Pan flute
#
# 99:atmosphere; attack longer than organ, release longer than piano
# 100:brillance , 101:gobelin
echo "preset 73:flute"
prog 0 73
echo "legato mode:0"
setlegatomode 0 0
echo "legato On, portamento On"
cc 0 68 127
cc 0 5 2
cc 0 65 127
echo "noteon C 60 vel=127, during 1000 ms"
noteon 0 60 127
sleep 1000
echo "noteon D,legato up C->D (60->62, vel=127), during 1000 ms"
echo "noteoff C"
noteon 0 62 127
noteoff 0 60
sleep 1000
echo "noteon E,legato up D->E (62->64, vel=127), during 1000 ms"
echo "noteoff D"
noteon 0 64 127
noteoff 0 62
sleep 1000
echo "noteon F,legato up E->F (64->65, vel=127), during 1000 ms"
echo "noteoff E"
noteon 0 65 127
noteoff 0 64
sleep 1000
echo "noteon G,legato up F->G (65->67, vel=127), during 1000 ms"
echo "noteoff F"
noteon 0 67 127
noteoff 0 65
sleep 1000
echo "noteon A,legato up G->A (67->69, vel=127), during 1000 ms"
echo "noteoff G"
noteon 0 69 127
noteoff 0 67
sleep 1000
echo "noteon B,legato up A->B (69->71, vel=127), during 1000 ms"
echo "noteoff A"
noteon 0 71 127
noteoff 0 69
sleep 1000
echo "noteon C,legato up B->C (71->72, vel=127), during 1000 ms"
echo "noteoff B"
noteon 0 72 127
noteoff 0 71
sleep 1000
echo "noteon B,legato down C->B (72->71, vel=127), during 1000 ms"
echo "noteoff C"
noteon 0 71 127
noteoff 0 72
sleep 1000
echo "noteon A,legato down B->A (71->69, vel=127), during 1000 ms"
echo "noteoff B"
noteon 0 69 127
noteoff 0 71
sleep 1000
echo "noteon G,legato down A->G (69->67, vel=127), during 1000 ms"
echo "noteoff A"
noteon 0 67 127
noteoff 0 69
sleep 1000
echo "noteon F,legato down G->F (67->65, vel=127), during 1000 ms"
echo "noteoff G"
noteon 0 65 127
noteoff 0 67
sleep 1000
echo "noteon E,legato down F->E (65->64, vel=127), during 1000 ms"
echo "noteoff F"
noteon 0 64 127
noteoff 0 65
sleep 1000
echo "noteon D,legato down E->D (64->62, vel=127), during 1000 ms"
echo "noteoff E"
noteon 0 62 127
noteoff 0 64
sleep 1000
echo "noteon C,legato down D->C (62->60, vel=127), during 1000 ms"
echo "noteoff D"
noteon 0 60 127
noteoff 0 62
sleep 1000
echo "noteoff C"
noteoff 0 60
sleep 1000
echo "legato Off, portamento off"
cc 0 68 0
cc 0 65 0
echo "End legato mode 1 (retrigger_1) with portamento"

107
doc/polymono/leg_por_01.txt Normal file
View file

@ -0,0 +1,107 @@
echo "legato mode 1 (multi-retrigger), egal velocity on n1,n2,n3..."
echo "with portamento."
echo "-------------------------------------------------------------"
# Sounfont: GeneralUser GS 1.471 S. Christian Collins
# Some presets
# 0: Piano 0 ; short release
# 16:organ 24:guitar
# 52: Choir Aahs 53: Voice Oohs
#
# 56:trumpet 57:trombone 58:tuba 59:muted trumpet
# 60:French horn 61:Brass section
# 62:Synth brass 1 63:Synth Brass 2
# 64:Soprano sax 65:Alto sax 66:Tenor sax 67:Baritone sax.
# 68:Oboe 69:English horn 70:Bassoon 71:Clarinet
# 72:piccolo 73:Flute 74:Recorder 75:Pan flute
#
# 99:atmosphere; attack longer than organ, release longer than piano
# 100:brillance , 101:gobelin
echo "preset 73:flute"
prog 0 73
echo "legato mode:1"
setlegatomode 0 1
echo "legato On, portamento On"
cc 0 68 127
cc 0 5 2
cc 0 65 127
echo "noteon C 60 vel=127, during 1000 ms"
noteon 0 60 127
sleep 1000
echo "noteon D,legato up C->D (60->62, vel=127), during 1000 ms"
echo "noteoff C"
noteon 0 62 127
noteoff 0 60
sleep 1000
echo "noteon E,legato up D->E (62->64, vel=127), during 1000 ms"
echo "noteoff D"
noteon 0 64 127
noteoff 0 62
sleep 1000
echo "noteon F,legato up E->F (64->65, vel=127), during 1000 ms"
echo "noteoff E"
noteon 0 65 127
noteoff 0 64
sleep 1000
echo "noteon G,legato up F->G (65->67, vel=127), during 1000 ms"
echo "noteoff F"
noteon 0 67 127
noteoff 0 65
sleep 1000
echo "noteon A,legato up G->A (67->69, vel=127), during 1000 ms"
echo "noteoff G"
noteon 0 69 127
noteoff 0 67
sleep 1000
echo "noteon B,legato up A->B (69->71, vel=127), during 1000 ms"
echo "noteoff A"
noteon 0 71 127
noteoff 0 69
sleep 1000
echo "noteon C,legato up B->C (71->72, vel=127), during 1000 ms"
echo "noteoff B"
noteon 0 72 127
noteoff 0 71
sleep 1000
echo "noteon B,legato down C->B (72->71, vel=127), during 1000 ms"
echo "noteoff C"
noteon 0 71 127
noteoff 0 72
sleep 1000
echo "noteon A,legato down B->A (71->69, vel=127), during 1000 ms"
echo "noteoff B"
noteon 0 69 127
noteoff 0 71
sleep 1000
echo "noteon G,legato down A->G (69->67, vel=127), during 1000 ms"
echo "noteoff A"
noteon 0 67 127
noteoff 0 69
sleep 1000
echo "noteon F,legato down G->F (67->65, vel=127), during 1000 ms"
echo "noteoff G"
noteon 0 65 127
noteoff 0 67
sleep 1000
echo "noteon E,legato down F->E (65->64, vel=127), during 1000 ms"
echo "noteoff F"
noteon 0 64 127
noteoff 0 65
sleep 1000
echo "noteon D,legato down E->D (64->62, vel=127), during 1000 ms"
echo "noteoff E"
noteon 0 62 127
noteoff 0 64
sleep 1000
echo "noteon C,legato down D->C (62->60, vel=127), during 1000 ms"
echo "noteoff D"
noteon 0 60 127
noteoff 0 62
sleep 1000
echo "noteoff C"
noteoff 0 60
sleep 1000
echo "legato Off, portamento off"
cc 0 68 0
cc 0 65 0
echo "End legato mode 2 (multi-retrigger) with portamento"

View file

@ -0,0 +1,8 @@
# What are default 'basic channels' in FluidSynth ?
#--------------------------------------------------
# At initialization the default basic channel is defined by settings (see 2.2).
# type the command basicchannels to display actual basic channels.
basicchannels
# end

View file

@ -0,0 +1,25 @@
# How to change the whole set of actual basic channels ?
# -------------------------------------------------------------
# Assuming you want to set 2 groups of channels
# Group 1: first channel 5 in poly mode, only one channel
# Group 2: first channel 10 in mono mode , only one channel
# Group 1 should have following settings:
# basic channel 5, mode poly, omni off, (mode 2).
# Group 2 should have the following settings:
# basic channel 10, mode mono, omni off, (mode 3), composed of one channel.
# First use the command resetbasicchannels to reset all basic channels
resetbasicchannels
# Then use command setbasicchannels using numbered mode:
setbasicchannels 5 2 0 10 3 1
# or using named mode:
# setbasicchannels 5 poly_omnioff 0 10 mono_omnioff 1
# Use basicchannels command to verify your settings
basicchannels
# end

View file

@ -0,0 +1,22 @@
# How to add a new basic channel among others actual basic channels ?
# -------------------------------------------------------------------
# Perhaps you have already set several groups of basics channels and
# you want add a new one without modifying actual groups.
# Assuming following actual groups:
# Basic channel: 5, poly omni off(mode 2), nbr: 1
# Basic channel: 10, mono omni off(mode 3), nbr: 1
# Now we want to add a new group 3:
# Group 3 should have the following settings:
# basic channel 13, mode mono, omni off, (mode 3) composed of 2 channels.
# Use command setbasicchannels using numbered mode:
setbasicchannels 13 3 2
# or using named mode:
# setbasicchannels 13 mono_omnioff 2
Use basicchannels command to verify your settings
basicchannels
# end

View file

@ -0,0 +1,26 @@
# How to change an actual basic channel ?
# ---------------------------------------
# Perhaps you have already set several groups of basics channels
# and you want change the settings of one.
# Assuming following actual groups:
# -Group 1:Basic channel: 5, poly omni off(mode 2), nbr: 1
# -Group 2:Basic channel: 10, mono omni off(mode 3), nbr: 1
# -Group 3:Basic channel: 13, mono omni off(mode 3), nbr: 2
# Now we want to change group 1:
# Group 1 should have the following settings:
# -basic channel 5, mode poly, omni on, (mode 0) composed of 4 channels in this group.
#First use the command resetbasicchannels to clear the group intended to be changed.
resetbasicchannels 5
# Then use command setbasicchannels using numbered mode:
setbasicchannels 5 0 4
# or Using named mode:
# setbasicchannels 5 poly_omnion 4
# Use basicchannels command to verify your settings
basicchannels
# end

View file

@ -0,0 +1,25 @@
# How to change an actual basic channel and an add new one ?
# --------------------------------------------------------
# Note that command setbasicchannels allows to add or change
# groups of basics channels.
#
# Note also that the commands allows this to more than one
# groups executing only one command:
# The following command restores Group 1 to the state:
# -Group 1:Basic channel: 5, poly omni off(mode 2), nbr: 1
# Then adds a new group:
# -Group 0:Basic channel: 2, mono omni on(mode 1), composed of 3 possible channels in this group
#First use the command resetbasicchannels to clear the group intended to be changed.
resetbasicchannels 5
# Use command setbasicchannels to change a group and add a new one, using numbered mode:
setbasicchannels 5 2 0 2 1 3
# or using named mode:
# setbasicchannels 5 poly_omnioff 0 2 mono_omnion 3
# Use basicchannels command to verify your settings
basicchannels
# end

View file

@ -0,0 +1,9 @@
# How to know the state of one or more MIDI channels ?
# -----------------------------------------------------
# Use the command channelsmode [chan1 chan2 ….]
channelsmode
# To display the state of MIDI channels 2,5, 10, 13 only
channelsmode 2 5 10 13
# end

22
doc/polymono/readme.txt Normal file
View file

@ -0,0 +1,22 @@
/fluidSynth/doc/polymono directory contains:
1) FluidPolyMono-0004.pdf, the documentation of poly/mono functionalities.
2) tutorials examples files:
2.1) tutorials chapter 2.1
poly_mono_0.txt
poly_mono_1.txt
poly_mono_2.txt
poly_mono_3.txt
poly_mono_4.txt
poly_mono_5.txt
2.2) tutorials chapter 3.1
leg_00.txt
leg_01.txt
leg_por_00.txt
leg_por_01.txt
This tutorials files are usable directly on the FluidSynth console application.
There are described in the pdf file (chapters 2.1 and 3.1).
jean-jacques ceresa

View file

@ -50,7 +50,6 @@ FLUIDSYNTH_API fluid_synth_t* new_fluid_synth(fluid_settings_t* settings);
FLUIDSYNTH_API void delete_fluid_synth(fluid_synth_t* synth);
FLUIDSYNTH_API fluid_settings_t* fluid_synth_get_settings(fluid_synth_t* synth);
/* MIDI channel messages */
FLUIDSYNTH_API int fluid_synth_noteon(fluid_synth_t* synth, int chan, int key, int vel);
@ -124,11 +123,6 @@ FLUIDSYNTH_API int fluid_synth_get_bank_offset(fluid_synth_t* synth, int sfont_i
/* Reverb */
/*
*
* Reverb
*
*/
FLUIDSYNTH_API int fluid_synth_set_reverb(fluid_synth_t* synth, double roomsize,
double damping, double width, double level);
@ -303,7 +297,8 @@ typedef int (*fluid_audio_callback_t)(fluid_synth_t* synth, int len,
/* Synthesizer's interface to handle SoundFont loaders */
FLUIDSYNTH_API void fluid_synth_add_sfloader(fluid_synth_t* synth, fluid_sfloader_t* loader);
FLUIDSYNTH_API fluid_voice_t* fluid_synth_alloc_voice(fluid_synth_t* synth, fluid_sample_t* sample,
FLUIDSYNTH_API fluid_voice_t* fluid_synth_alloc_voice(fluid_synth_t* synth,
fluid_sample_t* sample,
int channum, int key, int vel);
FLUIDSYNTH_API void fluid_synth_start_voice(fluid_synth_t* synth, fluid_voice_t* voice);
FLUIDSYNTH_API void fluid_synth_get_voicelist(fluid_synth_t* synth,
@ -330,6 +325,84 @@ FLUIDSYNTH_API int fluid_synth_set_custom_filter(fluid_synth_t*, int type, int f
FLUIDSYNTH_API fluid_ladspa_fx_t *fluid_synth_get_ladspa_fx(fluid_synth_t *synth);
/* API: Poly mono mode */
/** Interface to poly/mono mode variables
*
* Channel mode bits OR-ed together so that it matches with the midi spec: poly omnion (0), mono omnion (1), poly omnioff (2), mono omnioff (3)
*/
enum fluid_channel_mode_flags
{
FLUID_CHANNEL_POLY_OFF = 0x01, /**< if flag is set, the basic channel is in mono on state, if not set poly is on */
FLUID_CHANNEL_OMNI_OFF = 0x02, /**< if flag is set, the basic channel is in omni off state, if not set omni is on */
};
/** Indicates the breath mode a channel is set to */
enum fluid_channel_breath_flags
{
FLUID_CHANNEL_BREATH_POLY = 0x10, /**< when channel is poly, this flag indicates that the default velocity to initial attenuation modulator is replaced by a breath to initial attenuation modulator */
FLUID_CHANNEL_BREATH_MONO = 0x20, /**< when channel is mono, this flag indicates that the default velocity to initial attenuation modulator is replaced by a breath modulator */
FLUID_CHANNEL_BREATH_SYNC = 0x40, /**< when channel is mono, this flag indicates that the breath controler(MSB)triggers noteon/noteoff on the running note */
};
/** Indicates the mode a basic channel is set to */
enum fluid_basic_channel_modes
{
FLUID_CHANNEL_MODE_MASK = (FLUID_CHANNEL_OMNI_OFF | FLUID_CHANNEL_POLY_OFF), /**< Mask Poly and Omni bits of #fluid_channel_mode_flags, usually only used internally */
FLUID_CHANNEL_MODE_OMNION_POLY = FLUID_CHANNEL_MODE_MASK & (~FLUID_CHANNEL_OMNI_OFF & ~FLUID_CHANNEL_POLY_OFF), /**< corresponds to MIDI mode 0 */
FLUID_CHANNEL_MODE_OMNION_MONO = FLUID_CHANNEL_MODE_MASK & (~FLUID_CHANNEL_OMNI_OFF & FLUID_CHANNEL_POLY_OFF), /**< corresponds to MIDI mode 1 */
FLUID_CHANNEL_MODE_OMNIOFF_POLY = FLUID_CHANNEL_MODE_MASK & (FLUID_CHANNEL_OMNI_OFF & ~FLUID_CHANNEL_POLY_OFF), /**< corresponds to MIDI mode 2 */
FLUID_CHANNEL_MODE_OMNIOFF_MONO = FLUID_CHANNEL_MODE_MASK & (FLUID_CHANNEL_OMNI_OFF | FLUID_CHANNEL_POLY_OFF), /**< corresponds to MIDI mode 3 */
FLUID_CHANNEL_MODE_LAST /**< @internal Value defines the count of basic channel modes (#fluid_basic_channel_modes) @warning This symbol is not part of the public API and ABI stability guarantee and may change at any time! */
};
FLUIDSYNTH_API int fluid_synth_reset_basic_channel(fluid_synth_t* synth, int chan);
FLUIDSYNTH_API int fluid_synth_get_basic_channel(fluid_synth_t* synth, int chan,
int *basic_chan_out,
int *mode_chan_out,
int *basic_val_out );
FLUIDSYNTH_API int fluid_synth_set_basic_channel(fluid_synth_t* synth, int chan, int mode, int val);
/** Interface to mono legato mode
*
* Indicates the legato mode a channel is set to
* n1,n2,n3,.. is a legato passage. n1 is the first note, and n2,n3,n4 are played legato with previous note. */
enum fluid_channel_legato_mode
{
FLUID_CHANNEL_LEGATO_MODE_RETRIGGER, /**< Mode 0 - Release previous note, start a new note */
FLUID_CHANNEL_LEGATO_MODE_MULTI_RETRIGGER, /**< Mode 1 - On contiguous notes retrigger in attack section using current value, shape attack using current dynamic and make use of previous voices if any */
FLUID_CHANNEL_LEGATO_MODE_LAST /**< @internal Value defines the count of legato modes (#fluid_channel_legato_mode) @warning This symbol is not part of the public API and ABI stability guarantee and may change at any time! */
};
FLUIDSYNTH_API int fluid_synth_set_legato_mode(fluid_synth_t* synth, int chan, int legatomode);
FLUIDSYNTH_API int fluid_synth_get_legato_mode(fluid_synth_t* synth, int chan, int *legatomode);
/** Interface to portamento mode
*
* Indicates the portamento mode a channel is set to
*/
enum fluid_channel_portamento_mode
{
FLUID_CHANNEL_PORTAMENTO_MODE_EACH_NOTE, /**< Mode 0 - Portamento on each note (staccato or legato) */
FLUID_CHANNEL_PORTAMENTO_MODE_LEGATO_ONLY, /**< Mode 1 - Portamento only on legato note */
FLUID_CHANNEL_PORTAMENTO_MODE_STACCATO_ONLY, /**< Mode 2 - Portamento only on staccato note */
FLUID_CHANNEL_PORTAMENTO_MODE_LAST /**< @internal Value defines the count of portamento modes (#fluid_channel_portamento_mode) @warning This symbol is not part of the public API and ABI stability guarantee and may change at any time! */
};
FLUIDSYNTH_API int fluid_synth_set_portamento_mode(fluid_synth_t* synth,
int chan, int portamentomode);
FLUIDSYNTH_API int fluid_synth_get_portamento_mode(fluid_synth_t* synth,
int chan, int * portamentomode);
/* Interface to breath mode */
FLUIDSYNTH_API int fluid_synth_set_breath_mode(fluid_synth_t* synth,
int chan, int breathmode);
FLUIDSYNTH_API int fluid_synth_get_breath_mode(fluid_synth_t* synth,
int chan, int *breathmode);
#ifdef __cplusplus
}
#endif

View file

@ -157,6 +157,7 @@ set ( libfluidsynth_SOURCES
synth/fluid_mod.h
synth/fluid_synth.c
synth/fluid_synth.h
synth/fluid_synth_monopoly.c
synth/fluid_tuning.c
synth/fluid_tuning.h
synth/fluid_voice.c

View file

@ -78,30 +78,32 @@ void fluid_shell_settings(fluid_settings_t* settings)
/** the table of all handled commands */
static const fluid_cmd_t fluid_commands[] = {
/* general commands */
{ "help", "general", fluid_handle_help,
"help Show help topics ('help TOPIC' for more info)" },
"help Shows help topics ('help TOPIC' for more info)" },
{ "quit", "general", fluid_handle_quit,
"quit Quit the synthesizer" },
{ "source", "general", fluid_handle_source,
"source filename Load a file and parse every line as a command" },
"source filename Loads a file and parse every line as a command" },
/* event commands */
{ "noteon", "event", fluid_handle_noteon,
"noteon chan key vel Send noteon" },
"noteon chan key vel Sends noteon" },
{ "noteoff", "event", fluid_handle_noteoff,
"noteoff chan key Send noteoff" },
"noteoff chan key Sends noteoff" },
{ "pitch_bend", "event", fluid_handle_pitch_bend,
"pitch_bend chan offset Bend pitch" },
"pitch_bend chan offset Bends pitch" },
{ "pitch_bend_range", "event", fluid_handle_pitch_bend_range,
"pitch_bend chan range Set bend pitch range" },
"pitch_bend chan range Sets bend pitch range" },
{ "cc", "event", fluid_handle_cc,
"cc chan ctrl value Send control-change message" },
"cc chan ctrl value Sends control-change message" },
{ "prog", "event", fluid_handle_prog,
"prog chan num Send program-change message" },
"prog chan num Sends program-change message" },
{ "select", "event", fluid_handle_select,
"select chan sfont bank prog Combination of bank-select and program-change" },
{ "load", "general", fluid_handle_load,
"load file [reset] [bankofs] Load SoundFont (reset=0|1, def 1; bankofs=n, def 0)" },
"load file [reset] [bankofs] Loads SoundFont (reset=0|1, def 1; bankofs=n, def 0)" },
{ "unload", "general", fluid_handle_unload,
"unload id [reset] Unload SoundFont by ID (reset=0|1, default 1)"},
"unload id [reset] Unloads SoundFont by ID (reset=0|1, default 1)"},
{ "reload", "general", fluid_handle_reload,
"reload id Reload the SoundFont with the specified ID" },
{ "fonts", "general", fluid_handle_fonts,
@ -114,6 +116,28 @@ static const fluid_cmd_t fluid_commands[] = {
"interp num Choose interpolation method for all channels" },
{ "interpc", "general", fluid_handle_interpc,
"interpc chan num Choose interpolation method for one channel" },
/* polymono commands */
{ "basicchannels", "polymono", fluid_handle_basicchannels,
"basicchannels Prints the list of basic channels"},
{ "resetbasicchannels", "polymono", fluid_handle_resetbasicchannels,
"resetbasicchannels [chan1 chan2..] Resets all or some basic channels"},
{ "setbasicchannels", "polymono", fluid_handle_setbasicchannels,
"setbasicchannels [chan mode val...] Sets default, adds basic channels"},
{ "channelsmode", "polymono", fluid_handle_channelsmode,
"channelsmode [chan1 chan2..] Prints channels mode"},
{ "legatomode", "polymono", fluid_handle_legatomode,
"legatomode [chan1 chan2..] Prints channels legato mode"},
{ "setlegatomode", "polymono", fluid_handle_setlegatomode,
"setlegatomode chan mode [chan mode..] Sets legato mode"},
{ "portamentomode", "polymono", fluid_handle_portamentomode,
"portamentomode [chan1 chan2..] Prints channels portamento mode"},
{ "setportamentomode", "polymono", fluid_handle_setportamentomode,
"setportamentomode chan mode [chan mode..] Sets portamento mode"},
{ "breathmode", "polymono", fluid_handle_breathmode,
"breathmode [chan1 chan2..] Prints channels breath mode"},
{ "setbreathmode", "polymono", fluid_handle_setbreathmode,
"setbreathmode chan poly(1/0) mono(1/0) breath_sync(1/0) [..] Sets breath mode"},
/* reverb commands */
{ "rev_preset", "reverb", fluid_handle_reverbpreset,
"rev_preset num Load preset num into the reverb unit" },
{ "rev_setroomsize", "reverb", fluid_handle_reverbsetroomsize,
@ -126,6 +150,7 @@ static const fluid_cmd_t fluid_commands[] = {
"rev_setlevel num Change reverb level" },
{ "reverb", "reverb", fluid_handle_reverb,
"reverb [0|1|on|off] Turn the reverb on or off" },
/* chorus commands */
{ "cho_set_nr", "chorus", fluid_handle_chorusnr,
"cho_set_nr n Use n delay lines (default 3)" },
{ "cho_set_level", "chorus", fluid_handle_choruslevel,
@ -140,6 +165,7 @@ static const fluid_cmd_t fluid_commands[] = {
"gain value Set the master gain (0 < gain < 5)" },
{ "voice_count", "general", fluid_handle_voice_count,
"voice_count Get number of active synthesis voices" },
/* tuning commands */
{ "tuning", "tuning", fluid_handle_tuning,
"tuning name bank prog Create a tuning with name, bank number, \n"
" and program number (0 <= bank,prog <= 127)" },
@ -155,6 +181,7 @@ static const fluid_cmd_t fluid_commands[] = {
"dumptuning bank prog Print the pitch details of the tuning" },
{ "reset", "general", fluid_handle_reset,
"reset System reset (all notes off, reset controllers)" },
/* settings commands */
{ "set", "settings", fluid_handle_set,
"set name value Set the value of a controller or settings" },
{ "get", "settings", fluid_handle_get,
@ -165,7 +192,10 @@ static const fluid_cmd_t fluid_commands[] = {
"settings Print out all settings" },
{ "echo", "general", fluid_handle_echo,
"echo arg Print arg" },
/* LADSPA-related commands */
/* Sleep command, useful to insert a delay between commands */
{ "sleep", "general", fluid_handle_sleep,
"sleep duration sleep duration(in ms)" },
/* LADSPA-related commands */
#ifdef LADSPA
{ "ladspa_effect", "ladspa", fluid_handle_ladspa_effect,
"ladspa_effect Create a new effect from a LADSPA plugin"},
@ -184,6 +214,7 @@ static const fluid_cmd_t fluid_commands[] = {
{ "ladspa_reset", "ladspa", fluid_handle_ladspa_reset,
"ladspa_reset Stop and reset LADSPA effects"},
#endif
/* router commands */
{ "router_clear", "router", fluid_handle_router_clear,
"router_clear Clears all routing rules from the midi router"},
{ "router_default", "router", fluid_handle_router_default,
@ -619,7 +650,7 @@ fluid_handle_channels(void* data, int ac, char** av, fluid_ostream_t out)
int verbose = 0;
int i;
if (ac > 0 && strcmp( av[0], "-verbose") == 0) verbose = 1;
if (ac > 0 && FLUID_STRCMP( av[0], "-verbose") == 0) verbose = 1;
for (i = 0; i < fluid_synth_count_midi_channels(handler->synth); i++) {
preset = fluid_synth_get_channel_preset(handler->synth, i);
@ -873,9 +904,9 @@ fluid_handle_reverb(void* data, int ac, char** av, fluid_ostream_t out)
return FLUID_FAILED;
}
if ((strcmp(av[0], "0") == 0) || (strcmp(av[0], "off") == 0)) {
if ((FLUID_STRCMP(av[0], "0") == 0) || (FLUID_STRCMP(av[0], "off") == 0)) {
fluid_synth_set_reverb_on(handler->synth,0);
} else if ((strcmp(av[0], "1") == 0) || (strcmp(av[0], "on") == 0)) {
} else if ((FLUID_STRCMP(av[0], "1") == 0) || (FLUID_STRCMP(av[0], "on") == 0)) {
fluid_synth_set_reverb_on(handler->synth,1);
} else {
fluid_ostream_printf(out, "reverb: invalid arguments %s [0|1|on|off]", av[0]);
@ -960,9 +991,9 @@ fluid_handle_chorus(void* data, int ac, char** av, fluid_ostream_t out)
return FLUID_FAILED;
}
if ((strcmp(av[0], "0") == 0) || (strcmp(av[0], "off") == 0)) {
if ((FLUID_STRCMP(av[0], "0") == 0) || (FLUID_STRCMP(av[0], "off") == 0)) {
fluid_synth_set_chorus_on(handler->synth,0);
} else if ((strcmp(av[0], "1") == 0) || (strcmp(av[0], "on") == 0)) {
} else if ((FLUID_STRCMP(av[0], "1") == 0) || (FLUID_STRCMP(av[0], "on") == 0)) {
fluid_synth_set_chorus_on(handler->synth,1);
} else {
fluid_ostream_printf(out, "chorus: invalid arguments %s [0|1|on|off]", av[0]);
@ -990,6 +1021,28 @@ fluid_handle_echo(void* data, int ac, char** av, fluid_ostream_t out)
return FLUID_OK;
}
/* Purpose:
* Sleep during a time in ms
* The command itself is useful to insert a delay between commands.
* It can help for exemple to build a small song using noteon/noteoff commands
* in a command file.
*/
int
fluid_handle_sleep(void *data, int ac, char** av, fluid_ostream_t out)
{
if (ac < 1) {
fluid_ostream_printf(out, "sleep: too few arguments.\n");
return -1;
}
if (!fluid_is_number(av[0])) {
fluid_ostream_printf(out, "sleep: argument should be a number in ms.\n");
return -1;
}
fluid_msleep(atoi(av[0])); /* delay in milliseconds */
return 0;
}
int
fluid_handle_source(void* data, int ac, char** av, fluid_ostream_t out)
{
@ -1651,7 +1704,7 @@ fluid_handle_help(void* data, int ac, char** av, fluid_ostream_t out)
if (ac >= 1) {
topic = av[0];
}
if (strcmp(topic,"help") == 0){
if (FLUID_STRCMP(topic,"help") == 0){
/* "help help": Print a list of all topics */
fluid_ostream_printf(out,
"*** Help topics:***\n"
@ -1660,7 +1713,7 @@ fluid_handle_help(void* data, int ac, char** av, fluid_ostream_t out)
int listed_first_time = 1;
unsigned int ii;
for (ii = 0; ii < i; ii++){
if (strcmp(fluid_commands[i].topic, fluid_commands[ii].topic) == 0){
if (FLUID_STRCMP(fluid_commands[i].topic, fluid_commands[ii].topic) == 0){
listed_first_time = 0;
}; /* if topic has already been listed */
}; /* for all topics (inner loop) */
@ -1672,7 +1725,7 @@ fluid_handle_help(void* data, int ac, char** av, fluid_ostream_t out)
/* help (arbitrary topic or "all") */
for (i = 0; i < FLUID_N_ELEMENTS(fluid_commands); i++) {
if (fluid_commands[i].help != NULL) {
if (strcmp(topic,"all") == 0 || strcmp(topic,fluid_commands[i].topic) == 0){
if (FLUID_STRCMP(topic,"all") == 0 || FLUID_STRCMP(topic,fluid_commands[i].topic) == 0){
fluid_ostream_printf(out, "%s\n", fluid_commands[i].help);
count++;
}; /* if it matches the topic */
@ -1869,6 +1922,785 @@ int fluid_handle_router_par2(void* data, int ac, char** av, fluid_ostream_t out)
return FLUID_OK;
}
/** commands Poly/mono mode *************************************************/
static const char * mode_name[]={"poly omni on (0)","mono omni on (1)",
"poly omni off(2)","mono omni off(3)"};
/*
Prints result message for commands: basicchannels, resetbasicchannels.
Prints all basic channels and print a warning if there is no basic channel.
@param synth the synth instance.
@param out output stream.
*/
static int print_basic_channels(fluid_synth_t* synth, fluid_ostream_t out)
{
static const char * warning_msg = "Warning: no basic channels. All MIDI channels are disabled.\n"
"Make use of setbasicchannels to set at least a default basic channel.\n";
int n_chan= synth->midi_channels;
int i , n= 0;
/* prints all basic channels */
for (i =0; i< n_chan; i++)
{
int basic_chan, mode_chan,val;
if( fluid_synth_get_basic_channel(synth, i, &basic_chan, &mode_chan, &val) == FLUID_OK)
{
if (basic_chan == i)
{
n++;
fluid_ostream_printf(out,"Basic channel:%3d, %s, nbr:%3d\n", i,
mode_name[mode_chan & FLUID_CHANNEL_MODE_MASK ],
val);
}
}
else
{
return FLUID_FAILED; /* error */
}
}
/* prints a warning if there is no basic channel */
if (n == 0)
{
fluid_ostream_printf(out, warning_msg);
}
return FLUID_OK;
}
/*-----------------------------------------------------------------------------
basicchannels
Prints the list of all MIDI basic channels informations
example:
Basic channel: 0, poly omni on (0), nbr: 3
Basic channel: 3, poly omni off(2), nbr: 1
Basic channel: 8, mono omni off(3), nbr: 2
Basic channel: 13, mono omni on (1), nbr: 3
*/
int fluid_handle_basicchannels (void* data, int ac, char** av,
fluid_ostream_t out)
{
FLUID_ENTRY_COMMAND(data);
fluid_synth_t* synth = handler->synth;
return print_basic_channels(synth, out);
}
/*
Searchs a mode name and returns the channel mode number.
name must be: poly_omnion, mono_omnion, poly_omnioff, mono_omnioff.
@param name to search.
@return channel mode number (0 to 3) if name is valid, -1 otherwise.
*/
static int get_channel_mode_num(char * name)
{
/* argument names for channel mode parameter (see resetbasicchannels and
setbasicchannels commands*/
static const char * name_channel_mode [FLUID_CHANNEL_MODE_LAST]=
{"poly_omnion","mono_omnion","poly_omnioff","mono_omnioff"};
int i;
for (i = 0 ; i < FLUID_CHANNEL_MODE_LAST;i++)
{
if ( ! FLUID_STRCMP (name, name_channel_mode[i]))
{
return i;
}
}
return -1;
}
static const char *invalid_arg_msg ="invalid argument\n";
/*
checks basic channels arguments: chan1 mode1 val chan2 mode2 val2 ...
All arguments can be numeric. mode parameter can be a name.
Each group entry must have 3 parameters (chan,mode,val).
@param ac argument count.
@param av argument table.
@param out output stream.
@param name_cde command name prefix.
@return 0 if arguments are valid, -1 otherwise.
*/
static int check_basicchannels_arguments(int ac, char** av,
fluid_ostream_t out, char const * name_cde)
{
static const char *too_few_arg_msg = "too few argument, chan mode val [chan mode val]...\n";
int i;
for (i = 0; i < ac; i++)
{
/* checks parameters for list entries: chan1 mode1 val chan2 mode2 val2 ...*/
/* all parameters can be numeric. mode parameter can be a name. */
if (!fluid_is_number(av[i]) &&
( (i % 3 != 1) || get_channel_mode_num(av[i]) < 0 ))
{
fluid_ostream_printf(out, "%s: %s",name_cde, invalid_arg_msg);
return -1;
}
}
if (ac % 3)
{ /* each group entry needs 3 parameters: basicchan,mode,val */
fluid_ostream_printf(out, "%s: channel %d, %s\n",name_cde,
atoi(av[((ac/3) * 3)]),too_few_arg_msg);
return -1;
}
return 0;
}
/*
checks channels arguments: chan1 chan2 ...
all arguments must be numeric.
@param ac argument count.
@param av argument table.
@param out output stream.
@param name_cde command name prefix.
@return 0 if arguments are valid, -1 otherwise.
*/
static int check_channels_arguments(int ac, char** av,
fluid_ostream_t out, char const * name_cde)
{
int i;
for (i = 0; i < ac; i++)
{
if (!fluid_is_number(av[i]))
{
fluid_ostream_printf(out, "%s: %s",name_cde, invalid_arg_msg);
return -1;
}
}
return 0;
}
/*-----------------------------------------------------------------------------
resetbasicchannels
With no parameters the command resets all basic channels.
Note: Be aware than when a synth instance has no basic channels, all channels
are disabled.
In the intend to get some MIDI channels enabled, use the command setbasicchannels.
resetbasicchannels chan1 [chan2 . . .]
Resets basic channel group chan1, basic channel group chan2 . . .
*/
int fluid_handle_resetbasicchannels (void* data, int ac, char** av,
fluid_ostream_t out)
{
static const char * name_cde="resetbasicchannels";
FLUID_ENTRY_COMMAND(data);
fluid_synth_t* synth = handler->synth;
/* checks channels arguments: chan1 chan2 .... */
if (check_channels_arguments(ac,av,out,name_cde ) < 0)
{
return -1;
}
if (ac )
{ /* resetbasicchannels chan1 [chan2 . . .] */
int i;
for (i = 0; i < ac; i++)
{
int chan = atoi(av[i]);
int result = fluid_synth_reset_basic_channel(synth, chan);
if (result == FLUID_FAILED)
{
fluid_ostream_printf(out,"%s: channel %3d, %s", name_cde, chan,invalid_arg_msg);
}
}
}
else
{
/* resets all basic channels */
fluid_synth_reset_basic_channel(synth, -1);
}
/* prints result */
return print_basic_channels(synth, out);
}
/*-----------------------------------------------------------------------------
setbasicchannels
With no parameters the command sets one channel basic at basic channel 0 in
Omni On Poly (i.e all the MIDI channels are polyphonic).
setbasicchannels chan1 mode1 nbr1 [chan2 mode2 nbr2] ... ...
Adds basic channel 1 and 2
The command fails if any channels overlaps any existing basic channel groups.
To make room if necessary, existing basic channel groups can be cleared using
resetbasicchannels command.
Mode can be a numeric value or a name:
numeric: 0 to 3 or
name: poly_omnion , mono_omnion, poly_omnioff, mono_omnioff.
*/
int fluid_handle_setbasicchannels (void* data, int ac, char** av,
fluid_ostream_t out)
{
static const char * name_cde="setbasicchannels";
FLUID_ENTRY_COMMAND(data);
fluid_synth_t* synth = handler->synth;
int result;
int i,n ;
if(!ac)
{
/* sets one default basic channel */
fluid_synth_reset_basic_channel(synth, -1); /* reset all basic channels */
/* sets one basic channel Omni On Poly (i.e all the MIDI channels are polyphonic) */
fluid_synth_set_basic_channel( synth, 0, FLUID_CHANNEL_MODE_OMNION_POLY,0);
return 0;
}
/* checks parameters: chan1 mode1 val1 chan2 mode2 val2 */
if (check_basicchannels_arguments(ac,av,out,name_cde) < 0)
{
return -1;
}
n = ac / 3; /* number of basic channel information */
for (i = 0; i < n; i++)
{
int basicchan, mode, val;
basicchan = atoi(av[(i * 3)]); /* chan is numeric */
if (fluid_is_number(av[(i * 3)+1]))
{ /* chan is numeric */
mode = atoi(av[(i * 3)+1]);
}
else
{ /* mode is a name */
mode = get_channel_mode_num(av[(i * 3)+1]);
}
val = atoi(av[(i * 3)+2]); /* val is numeric */
/* changes or sets basic channels */
result = fluid_synth_set_basic_channel(synth, basicchan, mode, val);
if (result == FLUID_FAILED)
{
fluid_ostream_printf(out,"%s: channel %3d, mode %3d, nbr %3d, %s",
name_cde, basicchan, mode, val, invalid_arg_msg);
}
}
return 0;
}
/*
Print result message : "channel:x is outside MIDI channel count(y)"
for commands: channelsmode, portamentomode, legatomode, breathmode,setbreathmode.
@param out output stream.
@param name_cde command name prefix.
@param chan, MIDI channel number x.
@param n_chan, number of MIDI channels y.
*/
static void print_channel_is_outside_count(fluid_ostream_t out, char const * name_cde,
int chan, int n_chan)
{
fluid_ostream_printf(out,"%s: channel %3d is outside MIDI channel count(%d)\n",
name_cde, chan, n_chan);
}
/*-----------------------------------------------------------------------------
channelsmode
Prints channel mode of all MIDI channels (Poly/mono, Enabled, Basic Channel)
example
Channel , Status , Type , Mode , Nbr of channels
channel: 0, disabled
channel: 1, disabled
channel: 2, disabled
channel: 3, disabled
channel: 4, disabled
channel: 5, enabled, basic channel, mono omni off(3), nbr: 2
channel: 6, enabled, -- , mono , --
channel: 7, disabled
channel: 8, disabled
channel: 9, disabled
channel: 10, enabled, basic channel, mono omni off(3), nbr: 4
channel: 11, enabled, -- , mono , --
channel: 12, enabled, -- , mono , --
channel: 13, enabled, -- , mono , --
channel: 14, disabled
channel: 15, disabled
channelsmode chan1 chan2
Prints only channel mode of MIDI channels chan1, chan2
*/
int fluid_handle_channelsmode (void* data, int ac, char** av,
fluid_ostream_t out)
{
static const char * header =
"Channel , Status , Type , Mode , Nbr of channels\n";
static const char * name_cde="channelsmode";
FLUID_ENTRY_COMMAND(data);
fluid_synth_t* synth = handler->synth;
int i, n, n_chan= synth->midi_channels;
/* checks parameters: chan1 chan2 .... */
if (check_channels_arguments(ac,av,out,name_cde) < 0)
{
return -1;
}
if (ac )
{
n = ac; /* prints ac MIDI channels number */
}
else
{
n= n_chan; /* prints all MIDI channels number */
}
/* prints header */
fluid_ostream_printf(out, header);
for (i = 0; i < n; i++)
{
int basic_chan, mode, val;
int chan = ac ? atoi(av[i]): i;
int result = fluid_synth_get_basic_channel(synth, chan, &basic_chan, &mode, &val);
if (result == FLUID_OK)
{
if(basic_chan != FLUID_FAILED)
{ /* This channel is enabled */
const char * p_basicchan; /* field basic channel */
const char * p_mode; /* field mode */
const char *p_nbr; /* field Nbr */
static const char * blank="--"; /* field empty */
if (chan == basic_chan)
{ /* This channel is a basic channel */
char nbr[10]; /* field Nbr */
FLUID_SNPRINTF(nbr,sizeof(nbr),"nbr:%3d",val);
p_nbr = nbr;
p_mode = mode_name[mode];
p_basicchan = "basic channel";
}
else
{ /* This channel is member of a basic channel group */
p_basicchan = blank;
if(mode & FLUID_CHANNEL_POLY_OFF) p_mode = "mono";
else p_mode = "poly";
p_nbr = blank;
}
fluid_ostream_printf(out,
"channel:%3d, enabled, %-13s, %-16s, %s\n",
chan,
p_basicchan,
p_mode,
p_nbr);
}
else
{
fluid_ostream_printf(out, "channel:%3d, disabled\n", chan);
}
}
else
{
print_channel_is_outside_count(out, name_cde, chan, n_chan);
if(i < n-1)
{
fluid_ostream_printf(out, header);
}
}
}
return 0;
}
/** commands mono legato mode ***********************************************/
/*
Prints result message for commands: legatomode, portamentomode.
@param result result from the command (FLUID_OK,FLUID_FAILED).
@param out output stream.
@param name_cde command name prefix.
@param chan MIDI channel number to display.
@param name_mode name of the mode to display.
@param n_chan, number of MIDI channels.
*/
static void print_result_get_channel_mode(int result, fluid_ostream_t out,
char const * name_cde, int chan,
char const * name_mode, int n_chan )
{
if (result == FLUID_OK)
{
fluid_ostream_printf(out,"%s: channel %3d, %s\n", name_cde, chan, name_mode);
}
else
{
print_channel_is_outside_count(out, name_cde, chan, n_chan);
}
}
/*-----------------------------------------------------------------------------
legatomode
Prints legato mode of all MIDI channels
example
channel: 0, (1)multi-retrigger
channel: 1, (0)retrigger
channel: 2, (1)multi-retrigger
.....
legatomode chan1 chan2
Prints only legato mode of MIDI channels chan1, chan2
*/
int fluid_handle_legatomode(void* data, int ac, char** av,
fluid_ostream_t out)
{
static const char * name_cde="legatomode";
static const char * name_legato_mode[FLUID_CHANNEL_LEGATO_MODE_LAST]=
{ "(0)retrigger","(1)multi-retrigger" };
FLUID_ENTRY_COMMAND(data);
fluid_synth_t* synth = handler->synth;
int mode = 0;
int i, n, n_chan= synth->midi_channels;
/* checks channels arguments: chan1 chan2 .... */
if (check_channels_arguments(ac, av, out, name_cde) < 0)
{
return -1;
}
if (ac )
{
n = ac; /* prints ac MIDI channels number */
}
else
{
n= n_chan; /* prints all MIDI channels number */
}
/* prints header */
fluid_ostream_printf(out,"Channel , legato mode\n");
for (i = 0; i < n; i++)
{
int chan = ac ? atoi(av[i]): i;
int result = fluid_synth_get_legato_mode(synth, chan, &mode);
print_result_get_channel_mode(result, out, name_cde, chan, name_legato_mode[mode], n_chan);
}
return 0;
}
/*
checks channels arguments by group:
-example by group of 2 arguments: chan1 val1 chan2 val2 .. ..
-example by group of 4 arguments: chan1 val1 val2 val3 chan2 val1 val2 val3 ....
all arguments must be numeric.
@param ac argument count.
@param av argument table.
@param nbr_arg_group number of arguments by group expected.
@param out output stream.
@param name_cde command name prefix.
@param nbr_arg_group_msg message when the number of argument by group is invalid.
@return 0 if arguments are valid, -1 otherwise.
*/
static int check_channels_group_arguments(int ac, char** av, int nbr_arg_group,
fluid_ostream_t out,
char const * name_cde,
char const * nbr_arg_group_msg
)
{
if (ac)
{
/* checks channels numeric arguments */
if (check_channels_arguments(ac, av, out, name_cde) < 0)
{
return -1;
}
if (ac % nbr_arg_group)
{ /* each group entry needs nbr_arg_group parameters */
fluid_ostream_printf(out, "%s: channel %d, %s\n",name_cde,
atoi(av[((ac/nbr_arg_group) * nbr_arg_group)]),
nbr_arg_group_msg);
return -1;
}
}
else
{
fluid_ostream_printf(out, "%s: %s",name_cde, nbr_arg_group_msg);
return -1;
}
return 0;
}
/*
Prints result message for commands: setlegatomode, setportamentomode.
@param result result from the command (FLUID_FAILED).
@param out output stream.
@param name_cde command name prefix.
@param chan, MIDI channel number to display.
@param mode, mode value to display.
*/
static void print_result_set_channel_mode(int result, fluid_ostream_t out,
char const * name_cde,
int chan, int mode)
{
if (result == FLUID_FAILED)
{
fluid_ostream_printf(out,"%s: channel %3d, mode %3d, %s", name_cde, chan, mode, invalid_arg_msg);
}
}
static const char *too_few_arg_chan_mode_msg = "too few argument, chan mode [chan mode]...\n";
/*-----------------------------------------------------------------------------
setlegatomode chan0 mode1 [chan1 mode0] .. ..
Changes legato mode for channels chan0 and [chan1]
*/
int fluid_handle_setlegatomode(void* data, int ac, char** av,
fluid_ostream_t out)
{
static const char * name_cde="setlegatomode";
FLUID_ENTRY_COMMAND(data);
fluid_synth_t* synth = handler->synth;
int i,n ;
/* checks channels arguments by group of 2: chan1 val1 chan2 val1 .. ..*/
if (check_channels_group_arguments(ac, av, 2, out, name_cde, too_few_arg_chan_mode_msg) < 0)
{
return -1;
}
n = ac / 2; /* number of legato groups informations */
for (i = 0; i < n; i++)
{
int chan = atoi(av[(i * 2)]);
int mode = atoi(av[(i * 2)+1]);
/* changes legato mode */
int result = fluid_synth_set_legato_mode(synth,chan,mode);
print_result_set_channel_mode(result, out, name_cde, chan, mode);
}
return 0;
}
/** commands mono/poly portamento mode **************************************/
/*-----------------------------------------------------------------------------
portamentomode
Prints portamento mode of all MIDI channels
example
channel: 0, (2)staccato only
channel: 1, (1)legato only
channel: 2, (0)each note
channel: 3, (1)legato only
.....
portamentomode chan1 chan2
Prints only portamento mode of MIDI channels chan1, chan2
*/
int fluid_handle_portamentomode(void* data, int ac, char** av,
fluid_ostream_t out)
{
static const char * name_cde="portamentomode";
static const char * name_portamento_mode[FLUID_CHANNEL_PORTAMENTO_MODE_LAST]=
{ "(0)each note", "(1)legato only", "(2)staccato only" };
FLUID_ENTRY_COMMAND(data);
fluid_synth_t* synth = handler->synth;
int mode = 0;
int i, n, n_chan= synth->midi_channels;
/* checks channels arguments: chan1 chan2 . . . */
if (check_channels_arguments(ac, av, out, name_cde) < 0)
{
return -1;
}
if (ac )
{
n = ac; /* prints ac MIDI channels number */
}
else
{
n= n_chan; /* prints all MIDI channels number */
}
/* prints header */
fluid_ostream_printf(out,"Channel , portamento mode\n");
for (i = 0; i < n; i++)
{
int chan = ac ? atoi(av[i]): i;
int result = fluid_synth_get_portamento_mode(synth, chan, &mode);
print_result_get_channel_mode(result, out, name_cde, chan, name_portamento_mode[mode], n_chan);
}
return 0;
}
/*-----------------------------------------------------------------------------
setportamentomode chan1 mode1 [chan2 mode2] .. ..
Changes portamento mode for channels chan1 and [chan2]
*/
int fluid_handle_setportamentomode(void* data, int ac, char** av,
fluid_ostream_t out)
{
static const char * name_cde="setportamentomode";
FLUID_ENTRY_COMMAND(data);
fluid_synth_t* synth = handler->synth;
int i,n ;
/* checks channels arguments by group of 2: chan1 val1 chan2 val1 .. .. */
if (check_channels_group_arguments(ac, av, 2, out, name_cde, too_few_arg_chan_mode_msg) < 0)
{
return -1;
}
n = ac / 2; /* number of portamento groups informations */
for (i = 0; i < n; i++)
{
int chan = atoi(av[(i * 2)]);
int mode = atoi(av[(i * 2)+1]);
/* changes portamento mode */
int result = fluid_synth_set_portamento_mode(synth,chan,mode);
print_result_set_channel_mode(result, out, name_cde, chan, mode);
}
return 0;
}
/** commands mono/poly breath mode *******************************************/
/*-----------------------------------------------------------------------------
breathmode
Prints breath options of all MIDI channels.
poly breath on/off, mono breath on/off, breath sync on/off
example
Channel , poly breath , mono breath , breath sync
channel: 0, off , off , off
channel: 1, off , off , off
channel: 2, off , off , off
.....
breathmode chan1 chan2
Prints only breath mode of MIDI channels chan1, chan2
*/
int fluid_handle_breathmode(void* data, int ac, char** av,
fluid_ostream_t out)
{
static const char * name_cde="breathmode";
static const char * header="Channel , poly breath , mono breath , breath sync\n";
FLUID_ENTRY_COMMAND(data);
fluid_synth_t* synth = handler->synth;
int breathmode;
int i, n, n_chan= synth->midi_channels;
/* checks channels arguments: chan1 chan2 . . . */
if (check_channels_arguments(ac, av, out, name_cde) < 0)
{
return -1;
}
if (ac )
{
n = ac; /* prints ac MIDI channels number */
}
else
{
n= n_chan; /* prints all MIDI channels number */
}
/* prints header */
fluid_ostream_printf(out, header);
for (i = 0; i < n; i++)
{
int chan = ac ? atoi(av[i]): i;
int result = fluid_synth_get_breath_mode(synth, chan, &breathmode);
if (result == FLUID_OK)
{
static const char * on_msg ="on";
static const char * off_msg ="off";
const char * msg_poly_breath, * msg_mono_breath, * msg_breath_sync;
if (breathmode & FLUID_CHANNEL_BREATH_POLY)
{
msg_poly_breath =on_msg;
}
else
{
msg_poly_breath = off_msg;
}
if (breathmode & FLUID_CHANNEL_BREATH_MONO)
{
msg_mono_breath =on_msg;
}
else
{
msg_mono_breath = off_msg;
}
if (breathmode & FLUID_CHANNEL_BREATH_SYNC)
{
msg_breath_sync =on_msg;
}
else
{
msg_breath_sync = off_msg;
}
fluid_ostream_printf(out,"channel:%3d, %-12s, %-12s, %-11s\n",chan,
msg_poly_breath, msg_mono_breath, msg_breath_sync);
}
else
{
print_channel_is_outside_count(out, name_cde, chan, n_chan);
if(i < n-1)
{
fluid_ostream_printf(out, header);
}
}
}
return 0;
}
/*-----------------------------------------------------------------------------
setbreathmode chan1 poly_breath_mode(1/0) mono_breath_mode(1/0) mono_breath_sync(1/0)
Changes breath options for channels chan1 [chan2] .. ..
Example: setbreathmode 4 0 1 1
Parameter 1 is the channel number (i.e 4).
Parameter 2 is the " Breath modulator " enable/disable for poly mode (i.e disabled).
Parameter 3 is the " Breath modulator " enabe/disable for mono mode (i.e enabled).
Parameter 4 is "breath sync noteOn/Off" enable/disable for mono mode only (i.e enabled).
*/
int fluid_handle_setbreathmode(void* data, int ac, char** av,
fluid_ostream_t out)
{
static const char * name_cde="setbreathmode";
static const char *too_few_arg_breath_msg =
"too few argument:\nchan 1/0(breath poly) 1/0(breath mono) 1/0(breath sync mono)[..]\n";
FLUID_ENTRY_COMMAND(data);
fluid_synth_t* synth = handler->synth;
int i,n, n_chan= synth->midi_channels;
/* checks channels arguments by group of 4:
chan1 val1 val2 val3 chan2 val1 val2 val3 .... ....*/
if (check_channels_group_arguments(ac, av, 4, out, name_cde, too_few_arg_breath_msg) < 0)
{
return -1;
}
n = ac / 4; /* number of breath groups informations */
for (i = 0; i < n; i++)
{
int result;
int chan = atoi(av[(i * 4)]);
int poly_breath = atoi(av[(i * 4)+1]);
int mono_breath = atoi(av[(i * 4)+2]);
int breath_sync = atoi(av[(i * 4)+3]);
int breath_infos = 0;
/* changes breath infos */
if(poly_breath) breath_infos |= FLUID_CHANNEL_BREATH_POLY;
if(mono_breath) breath_infos |= FLUID_CHANNEL_BREATH_MONO;
if(breath_sync) breath_infos |= FLUID_CHANNEL_BREATH_SYNC;
result = fluid_synth_set_breath_mode(synth,chan,breath_infos);
if (result == FLUID_FAILED)
{
print_channel_is_outside_count(out, name_cde, chan, n_chan);
}
}
return 0;
}
#ifdef LADSPA
#define CHECK_LADSPA_ENABLED(_fx, _out) \

View file

@ -84,6 +84,19 @@ int fluid_handle_router_chan(void* data, int ac, char** av, fluid_ostream_t out)
int fluid_handle_router_par1(void* data, int ac, char** av, fluid_ostream_t out);
int fluid_handle_router_par2(void* data, int ac, char** av, fluid_ostream_t out);
int fluid_handle_basicchannels (void* data, int ac, char** av, fluid_ostream_t out);
int fluid_handle_resetbasicchannels (void* data, int ac, char** av, fluid_ostream_t out);
int fluid_handle_setbasicchannels (void* data, int ac, char** av, fluid_ostream_t out);
int fluid_handle_channelsmode (void* data, int ac, char** av, fluid_ostream_t out);
int fluid_handle_legatomode(void* data, int ac, char** av, fluid_ostream_t out);
int fluid_handle_setlegatomode(void* data, int ac, char** av, fluid_ostream_t out);
int fluid_handle_portamentomode(void* data, int ac, char** av, fluid_ostream_t out);
int fluid_handle_setportamentomode(void* data, int ac, char** av, fluid_ostream_t out);
int fluid_handle_breathmode(void* data, int ac, char** av, fluid_ostream_t out);
int fluid_handle_setbreathmode(void* data, int ac, char** av, fluid_ostream_t out);
int fluid_handle_sleep(void *data, int ac, char** av, fluid_ostream_t out);
#ifdef LADSPA
int fluid_handle_ladspa_effect(void *data, int ac, char **av, fluid_ostream_t out);
int fluid_handle_ladspa_link(void *data, int ac, char **av, fluid_ostream_t out);
@ -95,6 +108,7 @@ int fluid_handle_ladspa_stop(void *data, int ac, char **av, fluid_ostream_t out)
int fluid_handle_ladspa_reset(void *data, int ac, char **av, fluid_ostream_t out);
#endif
/**
* Command handler function prototype.
* @param data User defined data

View file

@ -145,7 +145,7 @@ fluid_lash_run (void * data)
while ( (config = lash_get_config (fluid_lash_client)) )
{
if (strcmp (lash_config_get_key (config), "soundfont count") == 0)
if (FLUID_STRCMP (lash_config_get_key (config), "soundfont count") == 0)
pending_restores = lash_config_get_value_int (config);
else
{

View file

@ -48,13 +48,13 @@ static pid_t _gettid(void) {
}
static int translate_error(const char *name) {
if (strcmp(name, DBUS_ERROR_NO_MEMORY) == 0)
if (FLUID_STRCMP(name, DBUS_ERROR_NO_MEMORY) == 0)
return -ENOMEM;
if (strcmp(name, DBUS_ERROR_SERVICE_UNKNOWN) == 0 ||
strcmp(name, DBUS_ERROR_NAME_HAS_NO_OWNER) == 0)
if (FLUID_STRCMP(name, DBUS_ERROR_SERVICE_UNKNOWN) == 0 ||
FLUID_STRCMP(name, DBUS_ERROR_NAME_HAS_NO_OWNER) == 0)
return -ENOENT;
if (strcmp(name, DBUS_ERROR_ACCESS_DENIED) == 0 ||
strcmp(name, DBUS_ERROR_AUTH_FAILED) == 0)
if (FLUID_STRCMP(name, DBUS_ERROR_ACCESS_DENIED) == 0 ||
FLUID_STRCMP(name, DBUS_ERROR_AUTH_FAILED) == 0)
return -EACCES;
return -EIO;

View file

@ -216,7 +216,7 @@ new_fluid_portaudio_driver (fluid_settings_t *settings, fluid_synth_t *synth)
outputParams.suggestedLatency = (PaTime)period_size / sample_rate;
/* Locate the device if specified */
if (strcmp (device, PORTAUDIO_DEFAULT_DEVICE) != 0)
if (FLUID_STRCMP (device, PORTAUDIO_DEFAULT_DEVICE) != 0)
{ /* The intended device is not the default device name, so we search
a device among available devices */
int numDevices;
@ -239,7 +239,7 @@ new_fluid_portaudio_driver (fluid_settings_t *settings, fluid_synth_t *synth)
if(name)
{
/* We see if the name corresponds to audio.portaudio.device */
char found = (strcmp (device, name) == 0);
char found = (FLUID_STRCMP (device, name) == 0);
FLUID_FREE (name);
if(found)

View file

@ -115,19 +115,19 @@ new_fluid_pulse_audio_driver2(fluid_settings_t* settings,
fluid_settings_getint(settings, "audio.pulseaudio.adjust-latency", &adjust_latency);
if (media_role != NULL) {
if (strcmp(media_role, "") != 0) {
if (FLUID_STRCMP(media_role, "") != 0) {
g_setenv("PULSE_PROP_media.role", media_role, TRUE);
}
FLUID_FREE (media_role); /* -- free media_role string */
}
if (server && strcmp (server, "default") == 0)
if (server && FLUID_STRCMP (server, "default") == 0)
{
FLUID_FREE (server); /* -- free server string */
server = NULL;
}
if (device && strcmp (device, "default") == 0)
if (device && FLUID_STRCMP (device, "default") == 0)
{
FLUID_FREE (device); /* -- free device string */
device = NULL;

View file

@ -70,13 +70,13 @@ void process_o_cmd_line_option(fluid_settings_t* settings, char* optarg)
}
/* did user request list of settings */
if (strcmp (optarg, "help") == 0)
if (FLUID_STRCMP (optarg, "help") == 0)
{
option_help = 1;
return;
}
if (strcmp (optarg, "") == 0) {
if (FLUID_STRCMP (optarg, "") == 0) {
fprintf (stderr, "Invalid -o option (name part is empty)\n");
return;
}
@ -374,7 +374,7 @@ int main(int argc, char** argv)
else fluid_settings_setstr(settings, "audio.driver", optarg);
break;
case 'C':
if ((optarg != NULL) && ((strcmp(optarg, "0") == 0) || (strcmp(optarg, "no") == 0))) {
if ((optarg != NULL) && ((FLUID_STRCMP(optarg, "0") == 0) || (FLUID_STRCMP(optarg, "no") == 0))) {
fluid_settings_setint(settings, "synth.chorus.active", FALSE);
} else {
fluid_settings_setint(settings, "synth.chorus.active", TRUE);
@ -473,7 +473,7 @@ int main(int argc, char** argv)
fluid_settings_setstr(settings, "midi.portname", optarg);
break;
case 'R':
if ((optarg != NULL) && ((strcmp(optarg, "0") == 0) || (strcmp(optarg, "no") == 0))) {
if ((optarg != NULL) && ((FLUID_STRCMP(optarg, "0") == 0) || (FLUID_STRCMP(optarg, "no") == 0))) {
fluid_settings_setint(settings, "synth.reverb.active", FALSE);
} else {
fluid_settings_setint(settings, "synth.reverb.active", TRUE);

View file

@ -349,7 +349,7 @@ fluid_midi_file_read_track(fluid_midi_file *mf, fluid_player_t *player, int num)
"An non-ascii track header found, corrupt file");
return FLUID_FAILED;
} else if (strcmp((char *) id, "MTrk") == 0) {
} else if (FLUID_STRCMP((char *) id, "MTrk") == 0) {
found_track = 1;

View file

@ -106,7 +106,7 @@ enum fluid_midi_control_change {
PORTAMENTO_SWITCH = 0x41,
SOSTENUTO_SWITCH = 0x42,
SOFT_PEDAL_SWITCH = 0x43,
LEGATO_SWITCH = 0x45,
LEGATO_SWITCH = 0x44,
HOLD2_SWITCH = 0x45,
SOUND_CTRL1 = 0x46,
SOUND_CTRL2 = 0x47,

View file

@ -252,7 +252,7 @@ static fluid_seq_id_t get_fluidsynth_dest(fluid_sequencer_t* seq)
for (i = 0; i < j; i++) {
id = fluid_sequencer_get_client_id(seq, i);
name = fluid_sequencer_get_client_name(seq, id);
if (name && (strcmp(name, "fluidsynth") == 0)) {
if (name && (FLUID_STRCMP(name, "fluidsynth") == 0)) {
return id;
}
}

View file

@ -95,9 +95,11 @@ fluid_adsr_env_calc(fluid_adsr_env_t* env, int is_volenv)
env->section++;
env->count = 0;
}
else env->count++;
env->val = x;
env->count++;
}
/* This one cannot be inlined since it is referenced in

View file

@ -319,11 +319,37 @@ fluid_rvoice_write (fluid_rvoice_t* voice, fluid_real_t *dsp_buf)
* buffer. It is the ratio between the frequencies of original
* waveform and output waveform.*/
voice->dsp.phase_incr = fluid_ct2hz_real(voice->dsp.pitch +
voice->dsp.pitchoffset +
fluid_lfo_get_val(&voice->envlfo.modlfo) * voice->envlfo.modlfo_to_pitch
+ fluid_lfo_get_val(&voice->envlfo.viblfo) * voice->envlfo.viblfo_to_pitch
+ fluid_adsr_env_get_val(&voice->envlfo.modenv) * voice->envlfo.modenv_to_pitch)
/ voice->dsp.root_pitch_hz;
/******************* portamento ****************/
/* pitchoffset is updated if enabled.
Pitchoffset will be added to dsp pitch at next phase calculation time */
/* In most cases portamento will be disabled. Thus first verify that portamento is
* enabled before updating pitchoffset and before disabling portamento when necessary,
* in order to keep the performance loss at minimum.
* If the algorithm would first update pitchoffset and then verify if portamento
* needs to be disabled, there would be a significant performance drop on a x87 FPU
*/
if (voice->dsp.pitchinc > 0.0f)
{ /* portamento is enabled, so update pitchoffset */
voice->dsp.pitchoffset += voice->dsp.pitchinc;
/* when pitchoffset reaches 0.0f, portamento is disabled */
if (voice->dsp.pitchoffset > 0.0f)
voice->dsp.pitchoffset = voice->dsp.pitchinc = 0.0f;
}
else if (voice->dsp.pitchinc < 0.0f)
{ /* portamento is enabled, so update pitchoffset */
voice->dsp.pitchoffset += voice->dsp.pitchinc;
/* when pitchoffset reaches 0.0f, portamento is disabled */
if (voice->dsp.pitchoffset < 0.0f)
voice->dsp.pitchoffset = voice->dsp.pitchinc = 0.0f;
}
fluid_check_fpe ("voice_write phase calculation");
/* if phase_incr is not advancing, set it to the minimum fraction value (prevent stuckage) */
@ -363,11 +389,11 @@ fluid_rvoice_write (fluid_rvoice_t* voice, fluid_real_t *dsp_buf)
/*************** resonant filter ******************/
fluid_iir_filter_calc(&voice->resonant_filter, voice->dsp.output_rate,
fluid_lfo_get_val(&voice->envlfo.modlfo) * voice->envlfo.modlfo_to_fc +
fluid_adsr_env_get_val(&voice->envlfo.modenv) * voice->envlfo.modenv_to_fc);
fluid_lfo_get_val(&voice->envlfo.modlfo) * voice->envlfo.modlfo_to_fc +
fluid_adsr_env_get_val(&voice->envlfo.modenv) * voice->envlfo.modenv_to_fc);
fluid_iir_filter_apply(&voice->resonant_filter, dsp_buf, count);
/* additional custom filter - only uses the fixed modulator, no lfos... */
fluid_iir_filter_calc(&voice->resonant_custom_filter, voice->dsp.output_rate, 0);
fluid_iir_filter_apply(&voice->resonant_custom_filter, dsp_buf, count);
@ -478,7 +504,11 @@ fluid_rvoice_reset(fluid_rvoice_t* voice)
calculate the volume increment during
processing */
/* mod env initialization*/
/* legato initialization */
voice->dsp.pitchoffset = 0.0; /* portamento initialization */
voice->dsp.pitchinc = 0.0;
/* mod env initialization*/
fluid_adsr_env_reset(&voice->envlfo.modenv);
/* vol env initialization */
@ -530,6 +560,102 @@ fluid_rvoice_noteoff(fluid_rvoice_t* voice, unsigned int min_ticks)
fluid_adsr_env_set_section(&voice->envlfo.modenv, FLUID_VOICE_ENVRELEASE);
}
/**
* skips to Attack section
*
* Updates vol and attack data
* Correction on volume val to achieve equivalent amplitude at noteOn legato
*
* @param voice the synthesis voice to be updated
*/
static FLUID_INLINE void fluid_rvoice_local_retrigger_attack (fluid_rvoice_t* voice)
{
/* skips to Attack section */
/* Once in Attack section, current count must be reset, to be sure
that the section will be not be prematurely finished. */
fluid_adsr_env_set_section(&voice->envlfo.volenv, FLUID_VOICE_ENVATTACK);
{
/* Correction on volume val to achieve equivalent amplitude at noteOn legato */
fluid_env_data_t* env_data;
fluid_real_t peak = fluid_cb2amp (voice->dsp.attenuation);
fluid_real_t prev_peak = fluid_cb2amp (voice->dsp.prev_attenuation);
voice->envlfo.volenv.val = (voice->envlfo.volenv.val * prev_peak) / peak;
/* Correction on slope direction for Attack section */
env_data = &voice->envlfo.volenv.data[FLUID_VOICE_ENVATTACK];
if(voice->envlfo.volenv.val <=1.0f)
{ /* slope attack for legato note needs to be positive from val up to 1 */
env_data->increment = 1.0f / env_data->count;
env_data->min = -1.0f; env_data->max = 1.0f;
}
else
{ /* slope attack for legato note needs to be negative: from val down to 1 */
env_data->increment = -voice->envlfo.volenv.val / env_data->count;
env_data->min = 1.0f; env_data->max = voice->envlfo.volenv.val;
}
}
}
/**
* Used by legato Mode : multi_retrigger
* see fluid_synth_noteon_mono_legato_multi_retrigger()
* @param voice the synthesis voice to be updated
*/
void
fluid_rvoice_multi_retrigger_attack (fluid_rvoice_t* voice)
{
int section = fluid_adsr_env_get_section(&voice->envlfo.volenv);
/*-------------------------------------------------------------------------
Section skip for volume envelope
--------------------------------------------------------------------------*/
if (section >= FLUID_VOICE_ENVHOLD)
{
/* DECAY, SUSTAIN,RELEASE section use logarithmic scaling. Calculates new
volenv_val to achieve equivalent amplitude during the attack phase
for seamless volume transition. */
fluid_real_t amp_cb, env_value;
amp_cb = 960.0f * (1.0f - fluid_adsr_env_get_val(&voice->envlfo.volenv));
env_value = fluid_cb2amp(amp_cb); /* a bit of optimization */
fluid_clip (env_value, 0.0, 1.0);
fluid_adsr_env_set_val(&voice->envlfo.volenv, env_value);
/* next, skips to Attack section */
}
/* skips to Attack section from any section */
/* Update vol and attack data */
fluid_rvoice_local_retrigger_attack(voice);
/*-------------------------------------------------------------------------
Section skip for modulation envelope
--------------------------------------------------------------------------*/
/* Skips from any section to ATTACK section */
fluid_adsr_env_set_section(&voice->envlfo.modenv, FLUID_VOICE_ENVATTACK);
/* Actually (v 1.1.6) all sections are linear, so there is no need to
correct val value. However soundfont 2.01/2.4 spec. says that Attack should
be convex (see issue #153 from Christian Collins). In the case Attack
section would be changed to a non linear shape it will be necessary to do
a correction for seamless val transition. Here is the place to do this */
}
/**
* sets the portamento dsp parameters: dsp.pitchoffset, dsp.pitchinc
* @param voice rvoice to set portamento.
* @param countinc increment count number.
* @param pitchoffset pitch offset to apply to voice dsp.pitch.
*
* Notes:
* 1) To get continuous portamento between consecutive noteOn (n1,n2,n3...),
* pitchoffset is accumulated in current dsp pitchoffset.
* 2) And to get constant portamento duration, dsp pitch increment is updated.
*/
void fluid_rvoice_set_portamento(fluid_rvoice_t * voice, unsigned int countinc,
fluid_real_t pitchoffset)
{
if (countinc)
{
voice->dsp.pitchoffset += pitchoffset;
voice->dsp.pitchinc = - voice->dsp.pitchoffset / countinc;
}
/* Then during the voice processing (in fluid_rvoice_write()),
dsp.pitchoffset will be incremented by dsp pitchinc. */
}
void
fluid_rvoice_set_output_rate(fluid_rvoice_t* voice, fluid_real_t value)
@ -559,6 +685,7 @@ fluid_rvoice_set_pitch(fluid_rvoice_t* voice, fluid_real_t value)
void
fluid_rvoice_set_attenuation(fluid_rvoice_t* voice, fluid_real_t value)
{
voice->dsp.prev_attenuation = voice->dsp.attenuation;
voice->dsp.attenuation = value;
}

View file

@ -96,6 +96,10 @@ struct _fluid_rvoice_dsp_t
int loopend; /* Note: first point following the loop (superimposed on loopstart) */
enum fluid_loop samplemode;
/* Stuff needed for portamento calculations */
fluid_real_t pitchoffset; /* the portamento range in midicents */
fluid_real_t pitchinc; /* the portamento increment in midicents */
/* Stuff needed for phase calculations */
fluid_real_t pitch; /* the pitch in midicents */
@ -106,6 +110,8 @@ struct _fluid_rvoice_dsp_t
int has_looped; /* Flag that is set as soon as the first loop is completed. */
fluid_real_t attenuation; /* the attenuation in centibels */
fluid_real_t prev_attenuation; /* the previous attenuation in centibels
used by fluid_rvoice_multi_retrigger_attack() */
fluid_real_t min_attenuation_cB; /* Estimate on the smallest possible attenuation
* during the lifetime of the voice */
fluid_real_t amplitude_that_reaches_noise_floor_nonloop;
@ -167,7 +173,9 @@ void fluid_rvoice_buffers_set_mapping(fluid_rvoice_buffers_t* buffers,
unsigned int bufnum, int mapping);
/* Dynamic update functions */
void fluid_rvoice_set_portamento(fluid_rvoice_t * voice, unsigned int countinc,
fluid_real_t pitchoffset);
void fluid_rvoice_multi_retrigger_attack(fluid_rvoice_t* voice);
void fluid_rvoice_noteoff(fluid_rvoice_t* voice, unsigned int min_ticks);
void fluid_rvoice_voiceoff(fluid_rvoice_t* voice);
void fluid_rvoice_reset(fluid_rvoice_t* voice);

View file

@ -103,6 +103,9 @@ fluid_rvoice_event_dispatch(fluid_rvoice_event_t* event)
EVENTFUNC_I1(fluid_rvoice_noteoff, fluid_rvoice_t*);
EVENTFUNC_0(fluid_rvoice_voiceoff, fluid_rvoice_t*);
EVENTFUNC_0(fluid_rvoice_reset, fluid_rvoice_t*);
EVENTFUNC_0(fluid_rvoice_multi_retrigger_attack, fluid_rvoice_t*);
EVENTFUNC_IR(fluid_rvoice_set_portamento, fluid_rvoice_t*);
EVENTFUNC_IIR4(fluid_adsr_env_set_data, fluid_adsr_env_t*);

View file

@ -25,6 +25,7 @@
#include "fluid_defsfont.h"
#include "fluid_sfont.h"
#include "fluid_sys.h"
#include "fluid_synth.h"
#if LIBSNDFILE_SUPPORT
#include <sndfile.h>
@ -52,7 +53,7 @@
*/
fluid_sfloader_t* new_fluid_defsfloader(fluid_settings_t* settings)
{
fluid_sfloader_t* loader;
fluid_sfloader_t* loader;
fluid_return_val_if_fail(settings != NULL, NULL);
loader = new_fluid_sfloader(fluid_defsfloader_load, delete_fluid_sfloader);
@ -64,7 +65,7 @@ fluid_sfloader_t* new_fluid_defsfloader(fluid_settings_t* settings)
}
fluid_sfloader_set_data(loader, settings);
return loader;
}
@ -91,7 +92,7 @@ fluid_sfont_t* fluid_defsfloader_load(fluid_sfloader_t* loader, const char* file
{
return NULL;
}
fluid_sfont_set_iteration_start(sfont, fluid_defsfont_sfont_iteration_start);
fluid_sfont_set_iteration_next(sfont, fluid_defsfont_sfont_iteration_next);
fluid_sfont_set_data(sfont, defsfont);
@ -274,7 +275,7 @@ static int fluid_cached_sampledata_load(char *filename,
}
for (cached_sampledata = all_cached_sampledata; cached_sampledata; cached_sampledata = cached_sampledata->next) {
if (strcmp(filename, cached_sampledata->filename))
if (FLUID_STRCMP(filename, cached_sampledata->filename))
continue;
if (cached_sampledata->modification_time != modification_time)
continue;
@ -854,7 +855,7 @@ fluid_defpreset_noteon(fluid_defpreset_t* preset, fluid_synth_t* synth, int chan
/* check if the note falls into the key and velocity range of this
preset */
if (fluid_preset_zone_inside_range(preset_zone, key, vel)) {
if (fluid_zone_inside_range(&preset_zone->range, key, vel)) {
inst = fluid_preset_zone_get_inst(preset_zone);
global_inst_zone = fluid_inst_get_global_zone(inst);
@ -862,7 +863,6 @@ fluid_defpreset_noteon(fluid_defpreset_t* preset, fluid_synth_t* synth, int chan
/* run thru all the zones of this instrument */
inst_zone = fluid_inst_get_zone(inst);
while (inst_zone != NULL) {
/* make sure this instrument zone has a valid sample */
sample = fluid_inst_zone_get_sample(inst_zone);
if ((sample == NULL) || fluid_sample_in_rom(sample)) {
@ -870,15 +870,14 @@ fluid_defpreset_noteon(fluid_defpreset_t* preset, fluid_synth_t* synth, int chan
continue;
}
/* check if the note falls into the key and velocity range of this
instrument */
/* check if the instrument zone is ignored and the note falls into
the key and velocity range of this instrument zone.
An instrument zone must be ignored when its voice is already running
played by a legato passage (see fluid_synth_noteon_monopoly_legato()) */
if (fluid_zone_inside_range(&inst_zone->range, key, vel)) {
if (fluid_inst_zone_inside_range(inst_zone, key, vel) && (sample != NULL)) {
/* this is a good zone. allocate a new synthesis process and
initialize it */
voice = fluid_synth_alloc_voice(synth, sample, chan, key, vel);
/* this is a good zone. allocate a new synthesis process and initialize it */
voice = fluid_synth_alloc_voice_LOCAL(synth, sample, chan, key, vel, &inst_zone->range);
if (voice == NULL) {
return FLUID_FAILED;
}
@ -1144,6 +1143,11 @@ fluid_defpreset_get_global_zone(fluid_defpreset_t* preset)
return preset->global_zone;
}
/***************************************************************
*
* PRESET_ZONE
*/
/*
* fluid_preset_zone_next
*/
@ -1176,10 +1180,11 @@ new_fluid_preset_zone(char *name)
}
FLUID_STRCPY(zone->name, name);
zone->inst = NULL;
zone->keylo = 0;
zone->keyhi = 128;
zone->vello = 0;
zone->velhi = 128;
zone->range.keylo = 0;
zone->range.keyhi = 128;
zone->range.vello = 0;
zone->range.velhi = 128;
zone->range.ignore = FALSE;
/* Flag all generators as unused (default, they will be set when they are found
* in the sound font).
@ -1189,11 +1194,6 @@ new_fluid_preset_zone(char *name)
return zone;
}
/***************************************************************
*
* PRESET_ZONE
*/
/*
* delete_fluid_preset_zone
*/
@ -1230,12 +1230,12 @@ fluid_preset_zone_import_sfont(fluid_preset_zone_t* zone, SFZone *sfzone, fluid_
sfgen = (SFGen *) r->data;
switch (sfgen->id) {
case GEN_KEYRANGE:
zone->keylo = (int) sfgen->amount.range.lo;
zone->keyhi = (int) sfgen->amount.range.hi;
zone->range.keylo = sfgen->amount.range.lo;
zone->range.keyhi = sfgen->amount.range.hi;
break;
case GEN_VELRANGE:
zone->vello = (int) sfgen->amount.range.lo;
zone->velhi = (int) sfgen->amount.range.hi;
zone->range.vello = sfgen->amount.range.lo;
zone->range.velhi = sfgen->amount.range.hi;
break;
case GEN_ATTENUATION:
/* EMU8k/10k hardware applies a scale factor to initial attenuation generator values set at
@ -1257,7 +1257,8 @@ fluid_preset_zone_import_sfont(fluid_preset_zone_t* zone, SFZone *sfzone, fluid_
FLUID_LOG(FLUID_ERR, "Out of memory");
return FLUID_FAILED;
}
if (fluid_inst_import_sfont(zone->inst, (SFInst *) sfzone->instsamp->data, sfont) != FLUID_OK) {
if (fluid_inst_import_sfont(zone, zone->inst,
(SFInst *) sfzone->instsamp->data, sfont) != FLUID_OK) {
return FLUID_FAILED;
}
}
@ -1404,17 +1405,6 @@ fluid_preset_zone_get_inst(fluid_preset_zone_t* zone)
return zone->inst;
}
/*
* fluid_preset_zone_inside_range
*/
int
fluid_preset_zone_inside_range(fluid_preset_zone_t* zone, int key, int vel)
{
return ((zone->keylo <= key) &&
(zone->keyhi >= key) &&
(zone->vello <= vel) &&
(zone->velhi >= vel));
}
/***************************************************************
*
@ -1474,7 +1464,8 @@ fluid_inst_set_global_zone(fluid_inst_t* inst, fluid_inst_zone_t* zone)
* fluid_inst_import_sfont
*/
int
fluid_inst_import_sfont(fluid_inst_t* inst, SFInst *sfinst, fluid_defsfont_t* sfont)
fluid_inst_import_sfont(fluid_preset_zone_t* zonePZ, fluid_inst_t* inst,
SFInst *sfinst, fluid_defsfont_t* sfont)
{
fluid_list_t *p;
SFZone* sfzone;
@ -1500,7 +1491,7 @@ fluid_inst_import_sfont(fluid_inst_t* inst, SFInst *sfinst, fluid_defsfont_t* sf
return FLUID_FAILED;
}
if (fluid_inst_zone_import_sfont(zone, sfzone, sfont) != FLUID_OK) {
if (fluid_inst_zone_import_sfont(zonePZ,zone, sfzone, sfont) != FLUID_OK) {
delete_fluid_inst_zone(zone);
return FLUID_FAILED;
}
@ -1580,11 +1571,11 @@ new_fluid_inst_zone(char* name)
}
FLUID_STRCPY(zone->name, name);
zone->sample = NULL;
zone->keylo = 0;
zone->keyhi = 128;
zone->vello = 0;
zone->velhi = 128;
zone->range.keylo = 0;
zone->range.keyhi = 128;
zone->range.vello = 0;
zone->range.velhi = 128;
zone->range.ignore = FALSE;
/* Flag the generators as unused.
* This also sets the generator values to default, but they will be overwritten anyway, if used.*/
fluid_gen_set_default_values(&zone->gen[0]);
@ -1627,7 +1618,8 @@ fluid_inst_zone_next(fluid_inst_zone_t* zone)
* fluid_inst_zone_import_sfont
*/
int
fluid_inst_zone_import_sfont(fluid_inst_zone_t* zone, SFZone *sfzone, fluid_defsfont_t* sfont)
fluid_inst_zone_import_sfont(fluid_preset_zone_t* preset_zone, fluid_inst_zone_t* zone,
SFZone *sfzone, fluid_defsfont_t* sfont)
{
fluid_list_t *r;
SFGen* sfgen;
@ -1637,12 +1629,12 @@ fluid_inst_zone_import_sfont(fluid_inst_zone_t* zone, SFZone *sfzone, fluid_defs
sfgen = (SFGen *) r->data;
switch (sfgen->id) {
case GEN_KEYRANGE:
zone->keylo = (int) sfgen->amount.range.lo;
zone->keyhi = (int) sfgen->amount.range.hi;
zone->range.keylo = sfgen->amount.range.lo;
zone->range.keyhi = sfgen->amount.range.hi;
break;
case GEN_VELRANGE:
zone->vello = (int) sfgen->amount.range.lo;
zone->velhi = (int) sfgen->amount.range.hi;
zone->range.vello = sfgen->amount.range.lo;
zone->range.velhi = sfgen->amount.range.hi;
break;
case GEN_ATTENUATION:
/* EMU8k/10k hardware applies a scale factor to initial attenuation generator values set at
@ -1659,6 +1651,13 @@ fluid_inst_zone_import_sfont(fluid_inst_zone_t* zone, SFZone *sfzone, fluid_defs
}
r = fluid_list_next(r);
}
/* adjust instrument zone keyrange to integrate preset zone keyrange */
if (preset_zone->range.keylo > zone->range.keylo) zone->range.keylo = preset_zone->range.keylo;
if (preset_zone->range.keyhi < zone->range.keyhi) zone->range.keyhi = preset_zone->range.keyhi;
/* adjust instrument zone to integrate preset zone velrange */
if (preset_zone->range.vello > zone->range.vello) zone->range.vello = preset_zone->range.vello;
if (preset_zone->range.velhi < zone->range.velhi) zone->range.velhi = preset_zone->range.velhi;
/* FIXME */
/* if (zone->gen[GEN_EXCLUSIVECLASS].flags == GEN_SET) { */
@ -1808,16 +1807,20 @@ fluid_inst_zone_get_sample(fluid_inst_zone_t* zone)
return zone->sample;
}
/*
* fluid_inst_zone_inside_range
*/
int
fluid_inst_zone_inside_range(fluid_inst_zone_t* zone, int key, int vel)
fluid_zone_inside_range(fluid_zone_range_t* range, int key, int vel)
{
return ((zone->keylo <= key) &&
(zone->keyhi >= key) &&
(zone->vello <= vel) &&
(zone->velhi >= vel));
/* ignoreInstrumentZone is set in mono legato playing */
int ignore_zone = range->ignore;
/* Reset the 'ignore' request */
range->ignore = FALSE;
return !ignore_zone && ((range->keylo <= key) &&
(range->keyhi >= key) &&
(range->vello <= vel) &&
(range->velhi >= vel));
}
/***************************************************************

View file

@ -343,7 +343,18 @@ typedef struct _fluid_defsfont_t fluid_defsfont_t;
typedef struct _fluid_defpreset_t fluid_defpreset_t;
typedef struct _fluid_preset_zone_t fluid_preset_zone_t;
typedef struct _fluid_inst_t fluid_inst_t;
typedef struct _fluid_inst_zone_t fluid_inst_zone_t;
typedef struct _fluid_inst_zone_t fluid_inst_zone_t; /**< Soundfont Instrument Zone */
/* defines the velocity and key range for a zone */
struct _fluid_zone_range_t
{
int keylo;
int keyhi;
int vello;
int velhi;
unsigned char ignore; /* set to TRUE for legato playing to ignore this range zone */
};
/*
@ -367,6 +378,7 @@ int fluid_defpreset_preset_get_banknum(fluid_preset_t* preset);
int fluid_defpreset_preset_get_num(fluid_preset_t* preset);
int fluid_defpreset_preset_noteon(fluid_preset_t* preset, fluid_synth_t* synth, int chan, int key, int vel);
int fluid_zone_inside_range(fluid_zone_range_t* zone_range, int key, int vel);
/*
* fluid_defsfont_t
@ -441,10 +453,7 @@ struct _fluid_preset_zone_t
fluid_preset_zone_t* next;
char* name;
fluid_inst_t* inst;
int keylo;
int keyhi;
int vello;
int velhi;
fluid_zone_range_t range;
fluid_gen_t gen[GEN_LAST];
fluid_mod_t * mod; /* List of modulators */
};
@ -453,7 +462,6 @@ fluid_preset_zone_t* new_fluid_preset_zone(char* name);
void delete_fluid_preset_zone(fluid_preset_zone_t* zone);
fluid_preset_zone_t* fluid_preset_zone_next(fluid_preset_zone_t* preset);
int fluid_preset_zone_import_sfont(fluid_preset_zone_t* zone, SFZone* sfzone, fluid_defsfont_t* sfont);
int fluid_preset_zone_inside_range(fluid_preset_zone_t* zone, int key, int vel);
fluid_inst_t* fluid_preset_zone_get_inst(fluid_preset_zone_t* zone);
/*
@ -467,8 +475,9 @@ struct _fluid_inst_t
};
fluid_inst_t* new_fluid_inst(void);
int fluid_inst_import_sfont(fluid_preset_zone_t* zonePZ, fluid_inst_t* inst,
SFInst *sfinst, fluid_defsfont_t* sfont);
void delete_fluid_inst(fluid_inst_t* inst);
int fluid_inst_import_sfont(fluid_inst_t* inst, SFInst *sfinst, fluid_defsfont_t* sfont);
int fluid_inst_set_global_zone(fluid_inst_t* inst, fluid_inst_zone_t* zone);
int fluid_inst_add_zone(fluid_inst_t* inst, fluid_inst_zone_t* zone);
fluid_inst_zone_t* fluid_inst_get_zone(fluid_inst_t* inst);
@ -482,19 +491,17 @@ struct _fluid_inst_zone_t
fluid_inst_zone_t* next;
char* name;
fluid_sample_t* sample;
int keylo;
int keyhi;
int vello;
int velhi;
fluid_zone_range_t range;
fluid_gen_t gen[GEN_LAST];
fluid_mod_t * mod; /* List of modulators */
};
fluid_inst_zone_t* new_fluid_inst_zone(char* name);
void delete_fluid_inst_zone(fluid_inst_zone_t* zone);
fluid_inst_zone_t* fluid_inst_zone_next(fluid_inst_zone_t* zone);
int fluid_inst_zone_import_sfont(fluid_inst_zone_t* zone, SFZone *sfzone, fluid_defsfont_t* sfont);
int fluid_inst_zone_inside_range(fluid_inst_zone_t* zone, int key, int vel);
int fluid_inst_zone_import_sfont(fluid_preset_zone_t* zonePZ,
fluid_inst_zone_t* zone, SFZone *sfzone, fluid_defsfont_t* sfont);
fluid_sample_t* fluid_inst_zone_get_sample(fluid_inst_zone_t* zone);

View file

@ -91,7 +91,7 @@ fluid_ramsfont_create_sfont()
if (ramsfont == NULL) {
return NULL;
}
sfont = new_fluid_sfont(fluid_ramsfont_sfont_get_name,
fluid_ramsfont_sfont_get_preset,
fluid_ramsfont_sfont_delete);
@ -99,11 +99,11 @@ fluid_ramsfont_create_sfont()
{
return NULL;
}
fluid_sfont_set_iteration_start(sfont, fluid_ramsfont_sfont_iteration_start);
fluid_sfont_set_iteration_next(sfont, fluid_ramsfont_sfont_iteration_next);
fluid_sfont_set_data(sfont, ramsfont);
return sfont;
}
@ -631,8 +631,8 @@ fluid_rampreset_add_sample (fluid_rampreset_t* preset, fluid_sample_t* sample,
}
izone->sample = sample;
izone->keylo = lokey;
izone->keyhi = hikey;
izone->range.keylo = lokey;
izone->range.keyhi = hikey;
// give the preset the name of the sample
FLUID_MEMCPY(preset->name, sample->name, 20);
@ -881,7 +881,7 @@ fluid_rampreset_noteon (fluid_rampreset_t* preset, fluid_synth_t* synth, int cha
/* check if the note falls into the key and velocity range of this
preset */
if (fluid_preset_zone_inside_range(preset_zone, key, vel)) {
if (fluid_zone_inside_range(&preset_zone->range, key, vel)) {
inst = fluid_preset_zone_get_inst(preset_zone);
global_inst_zone = fluid_inst_get_global_zone(inst);
@ -889,7 +889,7 @@ fluid_rampreset_noteon (fluid_rampreset_t* preset, fluid_synth_t* synth, int cha
/* run thru all the zones of this instrument */
inst_zone = fluid_inst_get_zone(inst);
while (inst_zone != NULL) {
/* make sure this instrument zone has a valid sample */
sample = fluid_inst_zone_get_sample(inst_zone);
if ((sample == NULL) || fluid_sample_in_rom(sample)) {
@ -897,15 +897,14 @@ fluid_rampreset_noteon (fluid_rampreset_t* preset, fluid_synth_t* synth, int cha
continue;
}
/* check if the note falls into the key and velocity range of this
instrument */
/* check if the instrument zone doesn't be ignored and the note falls into
the key and velocity range of this instrument zone.
An instrument zone must be ignored when its voice is already running
played by a legato passage (see fluid_synth_noteon_monopoly_legato()) */
if (fluid_zone_inside_range(&inst_zone->range, key, vel)) {
if (fluid_inst_zone_inside_range(inst_zone, key, vel) && (sample != NULL)) {
/* this is a good zone. allocate a new synthesis process and
initialize it */
voice = fluid_synth_alloc_voice(synth, sample, chan, key, vel);
/* this is a good zone. allocate a new synthesis process and initialize it */
voice = fluid_synth_alloc_voice_LOCAL(synth, sample, chan, key, vel, &inst_zone->range);
if (voice == NULL) {
return FLUID_FAILED;
}

View file

@ -65,10 +65,27 @@ static void
fluid_channel_init(fluid_channel_t* chan)
{
fluid_preset_t *newpreset;
int prognum, banknum;
int i, prognum, banknum;
chan->sostenuto_orderid = 0;
/*--- Init poly/mono modes variables --------------------------------------*/
chan->mode = 0;
chan->mode_val = 0;
/* monophonic list initialization */
for (i=0; i < FLUID_CHANNEL_SIZE_MONOLIST; i++)
{
chan->monolist[i].next = i+1;
}
chan->monolist[FLUID_CHANNEL_SIZE_MONOLIST -1].next = 0; /* ending element chained to the 1st */
chan->i_last = chan->n_notes = 0; /* clears the list */
chan->i_first = chan->monolist[chan->i_last].next; /* first note index in the list */
fluid_channel_clear_prev_note(chan); /* Mark previous note invalid */
/*---*/
chan->key_mono_sustained = INVALID_NOTE; /* No previous mono note sustained */
chan->legatomode = FLUID_CHANNEL_LEGATO_MODE_MULTI_RETRIGGER; /* Default mode */
chan->portamentomode = FLUID_CHANNEL_PORTAMENTO_MODE_LEGATO_ONLY; /* Default mode */
/*--- End of poly/mono initialization --------------------------------------*/
chan->channel_type = (chan->channum == 9) ? CHANNEL_TYPE_DRUM : CHANNEL_TYPE_MELODIC;
prognum = 0;
banknum = (chan->channel_type == CHANNEL_TYPE_DRUM) ? DRUM_INST_BANK : 0;
@ -131,6 +148,8 @@ fluid_channel_init_ctrl(fluid_channel_t* chan, int is_all_ctrl_off)
for (i = 0; i < 128; i++) {
fluid_channel_set_cc (chan, i, 0);
}
fluid_channel_clear_portamento(chan); /* Clear PTC receive */
chan->previous_cc_breath = 0;/* Reset previous breath */
}
/* Reset polyphonic key pressure on all voices */
@ -300,3 +319,309 @@ fluid_channel_get_sfont_bank_prog(fluid_channel_t* chan, int *sfont,
if (bank) *bank = (sfont_bank_prog & BANK_MASKVAL) >> BANK_SHIFTVAL;
if (prog) *prog = (sfont_bank_prog & PROG_MASKVAL) >> PROG_SHIFTVAL;
}
/**
* Updates legato/ staccato playing state
* The function is called:
* - on noteon before adding a note into the monolist.
* - on noteoff after removing a note out of the monolist.
* @param chan fluid_channel_t.
*/
static void
fluid_channel_update_legato_staccato_state(fluid_channel_t* chan)
{
/* Updates legato/ staccato playing state */
if (chan->n_notes)
{
chan->mode |= FLUID_CHANNEL_LEGATO_PLAYING; /* Legato state */
}
else
{
chan->mode &= ~ FLUID_CHANNEL_LEGATO_PLAYING; /* Staccato state */
}
}
/**
* Adds a note into the monophonic list. The function is part of the legato
* detector. fluid_channel_add_monolist() is intended to be called by
* fluid_synth_noteon_mono_LOCAL().
*
* When a note is added at noteOn each element is use in the forward direction
* and indexed by i_last variable.
*
* @param chan fluid_channel_t.
* @param key MIDI note number (0-127).
* @param vel MIDI velocity (0-127, 0=noteoff).
* @param onenote. When 1 the function adds the note but the monophonic list
* keeps only one note (used on noteOn poly).
* Note: i_last index keeps a trace of the most recent note added.
* prev_note keeps a trace of the note prior i_last note.
* FLUID_CHANNEL_LEGATO_PLAYING bit keeps trace of legato/staccato playing state.
*
* More informations in FluidPolyMono-0004.pdf chapter 4 (Appendices).
*/
void
fluid_channel_add_monolist(fluid_channel_t* chan, unsigned char key,
unsigned char vel, unsigned char onenote)
{
unsigned char i_last = chan->i_last;
/* Updates legato/ staccato playing state */
fluid_channel_update_legato_staccato_state(chan);
if (chan->n_notes)
{
/* keeps trace of the note prior last note */
chan->prev_note = chan->monolist[i_last].note;
}
/* moves i_last forward before writing new note */
i_last = chan->monolist[i_last].next;
chan->i_last = i_last; /* now ilast indexes the last note */
chan->monolist[i_last].note = key; /* we save note and velocity */
chan->monolist[i_last].vel = vel;
if (onenote)
{ /* clears monolist before one note addition */
chan->i_first = i_last;
chan->n_notes = 0;
}
if(chan->n_notes < FLUID_CHANNEL_SIZE_MONOLIST)
{
chan->n_notes++; /* updates n_notes */
}
else
{ /* The end of buffer is reach. So circular motion for i_first */
/* i_first index is moved forward */
chan->i_first = chan->monolist[i_last].next;
}
}
/**
* Searching a note in the monophonic list. The function is part of the legato
* detector. fluid_channel_search_monolist() is intended to be called by
* fluid_synth_noteoff_mono_LOCAL().
*
* The search starts from the first note in the list indexed by i_first
* @param chan fluid_channel_t.
* @param key MIDI note number (0-127) to search.
* @param i_prev pointer on returned index of the note prior the note to search.
* @return index of the note if find, FLUID_FAILED otherwise.
*
*/
int
fluid_channel_search_monolist(fluid_channel_t* chan, unsigned char key , int * i_prev)
{
short n = chan->n_notes; /* number of notes in monophonic list */
short j,i= chan->i_first; /* searching starts from i_first included */
for (j=0 ; j < n ; j++)
{
if(chan->monolist[i].note == key)
{
if (i == chan->i_first)
{ /* tracking index of the previous note (i_prev) */
for (j = chan->i_last ; n < FLUID_CHANNEL_SIZE_MONOLIST; n++)
{
j =chan->monolist[j].next;
}
* i_prev = j; /* returns index of the previous note */
}
return i; /* returns index of the note to search */
}
* i_prev = i; /* tracking index of the previous note (i_prev) */
i = chan->monolist[i].next; /* next element */
}
return FLUID_FAILED; /* not found */
}
/**
* removes a note from the monophonic list. The function is part of
* the legato detector.
* fluid_channel_remove_monolist() is intended to be called by
* fluid_synth_noteoff_mono_LOCAL().
*
* When a note is removed at noteOff the element concerned is fast unlinked
* and relinked after the i_last element.
*
* @param chan fluid_channel_t.
* @param
* i, index of the note to remove. If i is invalid or the list is
* empty, the function do nothing and returns FLUID_FAILED.
* @param
* On input, i_prev is a pointer on index of the note previous i.
* On output i_prev is a pointer on index of the note previous i if i is the last note
* in the list,FLUID_FAILED otherwise. When the returned index is valid it means
* a legato detection on noteoff.
*
* Note: the following variables in Channel keeps trace of the situation.
* - i_last index keeps a trace of the most recent note played even if
* the list is empty.
* - prev_note keeps a trace of the note removed if it is i_last.
* - FLUID_CHANNEL_LEGATO_PLAYING bit keeps a trace of legato/staccato playing state.
*
* More informations in FluidPolyMono-0004.pdf chapter 4 (Appendices).
*/
void
fluid_channel_remove_monolist(fluid_channel_t* chan, int i, int * i_prev)
{
unsigned char i_last = chan->i_last;
/* checks if index is valid */
if( i < 0 || i >= FLUID_CHANNEL_SIZE_MONOLIST || !chan->n_notes)
{
* i_prev = FLUID_FAILED;
}
/* The element is about to be removed and inserted between i_last and next */
/* Note: when i is egal to i_last or egal to i_first, removing/inserting
isn't necessary */
if (i == i_last)
{ /* Removing/Inserting isn't necessary */
/* keeps trace of the note prior last note */
chan->prev_note= chan->monolist[i_last].note;
/* moves i_last backward to the previous */
chan->i_last = *i_prev; /* i_last index is moved backward */
}
else
{ /* i is before i_last */
if(i == chan->i_first)
{
/* Removing/inserting isn't necessary */
/* i_first index is moved forward to the next element*/
chan->i_first = chan->monolist[i].next;
}
else
{ /* i is between i_first and i_last */
/* Unlinks element i and inserts after i_last */
chan->monolist[* i_prev].next = chan->monolist[i].next; /* unlinks i */
/*inserts i after i_last */
chan->monolist[i].next = chan->monolist[i_last].next;
chan->monolist[i_last].next = i;
}
* i_prev = FLUID_FAILED;
}
chan->n_notes--; /* updates the number of note in the list */
/* Updates legato/ staccato playing state */
fluid_channel_update_legato_staccato_state(chan);
}
/**
* On noteOff on a polyphonic channel,the monophonic list is fully flushed.
*
* @param chan fluid_channel_t.
* Note: i_last index keeps a trace of the most recent note played even if
* the list is empty.
* prev_note keeps a trace of the note i_last .
* FLUID_CHANNEL_LEGATO_PLAYING bit keeps a trace of legato/staccato playing.
*/
void fluid_channel_clear_monolist(fluid_channel_t* chan)
{
/* keeps trace off the most recent note played */
chan->prev_note= chan->monolist[chan->i_last].note;
/* flushes the monolist */
chan->i_first = chan->monolist[chan->i_last].next;
chan->n_notes = 0;
/* Update legato/ sataccato playing state */
chan->mode &= ~ FLUID_CHANNEL_LEGATO_PLAYING; /* Staccato state */
}
/**
* On noteOn on a polyphonic channel,adds the note into the monophonic list
* keeping only this note.
* @param
* chan fluid_channel_t.
* key, vel, note and velocity added in the monolist
* Note: i_last index keeps a trace of the most recent note inserted.
* prev_note keeps a trace of the note prior i_last note.
* FLUID_CHANNEL_LEGATO_PLAYING bit keeps trace of legato/staccato playing.
*/
void fluid_channel_set_onenote_monolist(fluid_channel_t* chan, unsigned char key,
unsigned char vel)
{
fluid_channel_add_monolist(chan, key, vel,1);
}
/**
* The function changes the state (Valid/Invalid) of the previous note played in
* a staccato manner (fluid_channel_prev_note()).
* When potamento mode 'each note' or 'staccato only' is selected, on next
* noteOn a portamento will be started from the most recent note played
* staccato.
* It will be possible that it isn't appropriate. To give the musician the
* possibility to choose a portamento from this note , prev_note will be forced
* to invalid state on noteOff if portamento pedal is Off.
*
* The function is intended to be called when the following event occurs:
* - On noteOff (in poly or mono mode), to mark prev_note invalid.
* - On Portamento Off(in poly or mono mode), to mark prev_note invalid.
* @param chan fluid_channel_t.
*/
void fluid_channel_invalid_prev_note_staccato(fluid_channel_t* chan)
{
/* checks if the playing is staccato */
if(!(chan->mode & FLUID_CHANNEL_LEGATO_PLAYING))
/* checks if portamento pedal is off */
if(! fluid_channel_portamento(chan))
{ /* forces prev_note invalid */
fluid_channel_clear_prev_note(chan);
}
/* else prev_note still remains valid for next fromkey portamento */
}
/**
* The function handles poly/mono commutation on legato pedal On/Off.
* @param chan fluid_channel_t.
* @param value, value of the CC legato.
*/
void fluid_channel_cc_legato(fluid_channel_t* chan, int value)
{
/* Special handling of the monophonic list */
if (!(chan->mode & FLUID_CHANNEL_POLY_OFF) && chan->n_notes) /* The monophonic list have notes */
{
if (value < 64 ) /* legato is released */
{ /* returns from monophonic to polyphonic with notes in the monophonic list */
/* The monophonic list is flushed keeping last note only
Note: i_last index keeps a trace of the most recent note played.
prev_note keeps a trace of the note i_last.
FLUID_CHANNEL_LEGATO_PLAYING bit keeps trace of legato/staccato playing.
*/
chan->i_first = chan->i_last;
chan->n_notes = 1;
}
else /* legato is depressed */
{ /* Inters in monophonic from polyphonic with note in monophonic list */
/* Stops the running note to remain coherent with Breath Sync mode */
if ((chan->mode & FLUID_CHANNEL_BREATH_SYNC) && !fluid_channel_breath_msb(chan))
{
fluid_synth_noteoff_monopoly(chan->synth,chan->channum,
fluid_channel_last_note(chan),1);
}
}
}
}
/**
* The function handles CC Breath On/Off detection. When a channel is in
* Breath Sync mode and in monophonic playing, the breath controller allows
* to trigger noteon/noteoff note when the musician starts to breath (noteon) and
* stops to breath (noteoff).
* @param chan fluid_channel_t.
* @param value, value of the CC Breath..
*/
void fluid_channel_cc_breath_note_on_off(fluid_channel_t* chan, int value)
{
if ((chan->mode & FLUID_CHANNEL_BREATH_SYNC) && fluid_channel_is_playing_mono(chan) &&
(chan->n_notes))
{
/* The monophonic list isn't empty */
if((value > 0) && (chan->previous_cc_breath == 0))
{ /* CC Breath On detection */
fluid_synth_noteon_mono_staccato(chan->synth,chan->channum,
fluid_channel_last_note(chan),
fluid_channel_last_vel(chan));
}
else if( (value == 0) && (chan->previous_cc_breath > 0))
{ /* CC Breath Off detection */
fluid_synth_noteoff_monopoly(chan->synth, chan->channum,
fluid_channel_last_note(chan), 1);
}
}
chan->previous_cc_breath = value;
}

View file

@ -25,6 +25,50 @@
#include "fluid_midi.h"
#include "fluid_tuning.h"
/* The mononophonic list is part of the legato detector for monophonic mode */
/* see fluid_synth_monopoly.c about a description of the legato detector device */
/* Size of the monophonic list
- 1 is the minimum. it allows playing legato passage of any number
of notes on noteon only.
- Size above 1 allows playing legato on noteon but also on noteOff.
This allows the musician to play fast trills.
This feature is particularly usful when the MIDI input device is a keyboard.
Choosing a size of 10 is sufficient (because most musicians have only 10
fingers when playing a monophonic instrument).
*/
#define FLUID_CHANNEL_SIZE_MONOLIST 10
/*
The monophonic list
+------------------------------------------------+
| +----+ +----+ +----+ +----+ |
| |note| |note| |note| |note| |
+--->|vel |-->|vel |-->....-->|vel |-->|vel |----+
+----+ +----+ +----+ +----+
/|\ /|\
| |
i_first i_last
The monophonic list is a circular buffer of FLUID_CHANNEL_SIZE_MONOLIST elements.
Each element is linked forward at initialisation time.
- when a note is added at noteOn (see fluid_channel_add_monolist()) each
element is use in the forward direction and indexed by i_last variable.
- when a note is removed at noteOff (see fluid_channel_remove_monolist()),
the element concerned is fast unlinked and relinked after the i_last element.
The most recent note added is indexed by i_last.
The most ancient note added is the first note indexed by i_first. i_first is
moving in the forward direction in a circular manner.
*/
struct mononote
{
unsigned char next; /* next note */
unsigned char note; /* note */
unsigned char vel; /* velocity */
};
/*
* fluid_channel_t
*
@ -35,7 +79,23 @@ struct _fluid_channel_t
{
fluid_synth_t* synth; /**< Parent synthesizer instance */
int channum; /**< MIDI channel number */
/* Poly Mono variables see macro access description */
int mode; /**< Poly Mono mode */
int mode_val; /**< number of channel in basic channel group */
/* monophonic list - legato detector */
struct mononote monolist[FLUID_CHANNEL_SIZE_MONOLIST]; /**< monophonic list */
unsigned char i_first; /**< First note index */
unsigned char i_last; /**< most recent note index since the most recent add */
unsigned char prev_note; /**< previous note of the most recent add/remove */
unsigned char n_notes; /**< actual number of notes in the list */
/*--*/
int key_mono_sustained; /**< previous sustained monophonic note */
enum fluid_channel_legato_mode legatomode; /**< legato mode */
enum fluid_channel_portamento_mode portamentomode; /**< portamento mode */
int previous_cc_breath; /**< Previous Breath */
/*- End of Poly/mono variables description */
int sfont_bank_prog; /**< SoundFont ID (bit 21-31), bank (bit 7-20), program (bit 0-6) */
fluid_preset_t* preset; /**< Selected preset */
@ -136,6 +196,12 @@ int fluid_channel_get_interp_method(fluid_channel_t* chan);
((chan)->tuning_prog)
#define fluid_channel_set_tuning_prog(chan, prog) \
((chan)->tuning_prog = (prog))
#define fluid_channel_portamentotime(_c) \
((_c)->cc[PORTAMENTO_TIME_MSB] * 128 + (_c)->cc[PORTAMENTO_TIME_LSB])
#define fluid_channel_portamento(_c) ((_c)->cc[PORTAMENTO_SWITCH] >= 64)
#define fluid_channel_breath_msb(_c) ((_c)->cc[BREATH_MSB] > 0)
#define fluid_channel_clear_portamento(_c) ((_c)->cc[PORTAMENTO_CTRL] = INVALID_NOTE)
#define fluid_channel_legato(_c) ((_c)->cc[LEGATO_SWITCH] >= 64)
#define fluid_channel_sustained(_c) ((_c)->cc[SUSTAIN_SWITCH] >= 64)
#define fluid_channel_sostenuto(_c) ((_c)->cc[SOSTENUTO_SWITCH] >= 64)
#define fluid_channel_set_gen(_c, _n, _v, _a) { (_c)->gen[_n] = _v; (_c)->gen_abs[_n] = _a; }
@ -144,4 +210,83 @@ int fluid_channel_get_interp_method(fluid_channel_t* chan);
#define fluid_channel_get_min_note_length_ticks(chan) \
((chan)->synth->min_note_length_ticks)
/* Macros interface to poly/mono mode variables */
#define MASK_BASICCHANINFOS (FLUID_CHANNEL_MODE_MASK|FLUID_CHANNEL_BASIC|FLUID_CHANNEL_ENABLED)
/* Set the basic channel infos for a MIDI basic channel */
#define fluid_channel_set_basic_channel_info(chan,Infos) \
(chan->mode = (chan->mode & ~MASK_BASICCHANINFOS) | (Infos & MASK_BASICCHANINFOS))
/* Reset the basic channel infos for a MIDI basic channel */
#define fluid_channel_reset_basic_channel_info(chan) (chan->mode &= ~MASK_BASICCHANINFOS)
/* Macros interface to breath variables */
#define FLUID_CHANNEL_BREATH_MASK (FLUID_CHANNEL_BREATH_POLY|FLUID_CHANNEL_BREATH_MONO|FLUID_CHANNEL_BREATH_SYNC)
/* Set the breath infos for a MIDI channel */
#define fluid_channel_set_breath_info(chan,BreathInfos) \
(chan->mode = (chan->mode & ~FLUID_CHANNEL_BREATH_MASK) | (BreathInfos & FLUID_CHANNEL_BREATH_MASK))
/* Get the breath infos for a MIDI channel */
#define fluid_channel_get_breath_info(chan) (chan->mode & FLUID_CHANNEL_BREATH_MASK)
/* Returns true when channel is mono or legato is on */
#define fluid_channel_is_playing_mono(chan) ((chan->mode & FLUID_CHANNEL_POLY_OFF) ||\
fluid_channel_legato(chan))
/* Macros interface to monophonic list variables */
#define INVALID_NOTE 255
/* Returns true when a note is a valid note */
#define fluid_channel_is_valid_note(n) (n != INVALID_NOTE)
/* Marks prev_note as invalid. */
#define fluid_channel_clear_prev_note(chan) (chan->prev_note = INVALID_NOTE)
/* Returns the most recent note from i_last entry of the monophonic list */
#define fluid_channel_last_note(chan) (chan->monolist[chan->i_last].note)
/* Returns the most recent velocity from i_last entry of the monophonic list */
#define fluid_channel_last_vel(chan) (chan->monolist[chan->i_last].vel)
/*
prev_note is used to determine fromkey_portamento as well as
fromkey_legato (see fluid_synth_get_fromkey_portamento_legato()).
prev_note is updated on noteOn/noteOff mono by the legato detector as this:
- On noteOn mono, before adding a new note into the monolist,the most
recent note in the list (i.e at i_last position) is kept in prev_note.
- Similarly, on noteOff mono , before removing a note out of the monolist,
the most recent note (i.e those at i_last position) is kept in prev_note.
*/
#define fluid_channel_prev_note(chan) (chan->prev_note)
/* Interface to poly/mono mode variables */
enum fluid_channel_mode_flags_internal
{
FLUID_CHANNEL_BASIC = 0x04, /**< if flag set the corresponding midi channel is a basic channel */
FLUID_CHANNEL_ENABLED = 0x08, /**< if flag set the corresponding midi channel is enabled, else disabled, i.e. channel ignores any MIDI messages */
/*
FLUID_CHANNEL_LEGATO_PLAYING bit of channel mode keeps trace of the legato /staccato
state playing.
FLUID_CHANNEL_LEGATO_PLAYING bit is updated on noteOn/noteOff mono by the legato detector:
- On noteOn, before inserting a new note into the monolist.
- On noteOff, after removing a note out of the monolist.
- On noteOn, this state is used by fluid_synth_noteon_mono_LOCAL()
to play the current note legato or staccato.
- On noteOff, this state is used by fluid_synth_noteoff_mono_LOCAL()
to play the current noteOff legato with the most recent note.
*/
/* bit7, 1: means legato playing , 0: means staccato playing */
FLUID_CHANNEL_LEGATO_PLAYING = 0x80
};
/* End of interface to monophonic list variables */
void fluid_channel_add_monolist(fluid_channel_t* chan, unsigned char key, unsigned char vel, unsigned char onenote);
int fluid_channel_search_monolist(fluid_channel_t* chan, unsigned char key , int * i_prev);
void fluid_channel_remove_monolist(fluid_channel_t* chan, int i, int * i_prev);
void fluid_channel_clear_monolist(fluid_channel_t* chan);
void fluid_channel_set_onenote_monolist(fluid_channel_t* chan, unsigned char key, unsigned char vel);
void fluid_channel_invalid_prev_note_staccato(fluid_channel_t* chan);
void fluid_channel_cc_legato(fluid_channel_t* chan, int value);
void fluid_channel_cc_breath_note_on_off(fluid_channel_t* chan, int value);
#endif /* _FLUID_CHAN_H */

File diff suppressed because it is too large Load diff

View file

@ -46,7 +46,6 @@
#define FLUID_UNSET_PROGRAM 128 /* Program number used to unset a preset */
/***************************************************************
*
* ENUM
@ -136,6 +135,7 @@ struct _fluid_synth_t
int active_voice_count; /**< count of active voices */
unsigned int noteid; /**< the id is incremented for every new note. it's used for noteoff's */
unsigned int storeid;
int fromkey_portamento; /**< fromkey portamento */
fluid_rvoice_eventhandler_t* eventhandler;
double reverb_roomsize; /**< Shadow of reverb roomsize */
@ -174,13 +174,6 @@ fluid_preset_t* fluid_synth_find_preset(fluid_synth_t* synth,
unsigned int banknum,
unsigned int prognum);
void fluid_synth_sfont_unref (fluid_synth_t *synth, fluid_sfont_t *sfont);
int fluid_synth_all_notes_off(fluid_synth_t* synth, int chan);
int fluid_synth_all_sounds_off(fluid_synth_t* synth, int chan);
int fluid_synth_kill_voice(fluid_synth_t* synth, fluid_voice_t * voice);
void fluid_synth_print_voice(fluid_synth_t* synth);
void fluid_synth_dither_s16(int *dither_index, int len, float* lin, float* rin,
void* lout, int loff, int lincr,
@ -198,8 +191,6 @@ int fluid_synth_set_chorus_full(fluid_synth_t* synth, int set, int nr, double le
fluid_sample_timer_t* new_fluid_sample_timer(fluid_synth_t* synth, fluid_timer_callback_t callback, void* data);
void delete_fluid_sample_timer(fluid_synth_t* synth, fluid_sample_timer_t* timer);
void fluid_synth_api_enter(fluid_synth_t* synth);
void fluid_synth_api_exit(fluid_synth_t* synth);
void fluid_synth_process_event_queue(fluid_synth_t* synth);
@ -209,7 +200,19 @@ int fluid_synth_set_gen2 (fluid_synth_t* synth, int chan,
/*
* misc
*/
void fluid_synth_settings(fluid_settings_t* settings);
/* extern declared in fluid_synth_monopoly.c */
int fluid_synth_noteon_mono_staccato(fluid_synth_t* synth,int chan,int key,int vel);
int fluid_synth_noteon_mono_LOCAL(fluid_synth_t* synth, int chan, int key, int vel);
int fluid_synth_noteoff_mono_LOCAL(fluid_synth_t* synth, int chan, int key);
int fluid_synth_noteon_monopoly_legato(fluid_synth_t* synth, int chan, int fromkey, int tokey, int vel);
int fluid_synth_noteoff_monopoly(fluid_synth_t* synth, int chan, int key, char Mono);
fluid_voice_t*
fluid_synth_alloc_voice_LOCAL(fluid_synth_t* synth, fluid_sample_t* sample, int chan, int key, int vel, fluid_zone_range_t* zone_range);
void fluid_synth_release_voice_on_same_note_LOCAL(fluid_synth_t* synth, int chan, int key);
#endif /* _FLUID_SYNTH_H */

View file

@ -0,0 +1,685 @@
/* FluidSynth - A Software Synthesizer
*
* Copyright (C) 2003 Peter Hanappe and others.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public License
* as published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA
*/
#include "fluid_synth.h"
#include "fluid_chan.h"
#include "fluid_defsfont.h"
/******************************************************************************
The legato detector is composed as this,
variables:
- monolist: monophonic list variable.
- prev_note: to store the most recent note before adding on noteon or before
removing on noteoff.
- FLUID_CHANNEL_LEGATO_PLAYING: legato/staccato state bit that informs on
legato or staccato playing.
functions:
- fluid_channel_add_monolist(), for inserting a new note.
- fluid_channel_search_monolist(), for searching the position of a note
into the list.
- fluid_channel_remove_monolist(), for removing a note from the list.
The monophonic list
+------------------------------------------------+
| +----+ +----+ +----+ +----+ |
| |note| |note| |note| |note| |
+--->|vel |-->|vel |-->....-->|vel |-->|vel |----+
+----+ +----+ +----+ +----+
/|\ /|\
| |
i_first i_last
The list allows an easy automatic detection of a legato passage when it is
played on a MIDI keyboard input device.
It is useful also when the input device is an ewi (electronic wind instrument)
or evi (electronic valve instrument) and these instruments are unable to send
MIDI CC legato on/off.
The list memorizes the notes in playing order.
- (a) On noteOn n2, if a previous note n1 exists, there is a legato
detection with n1 (with or without portamento from n1 to n2 See note below).
- (b) On noteOff of the running note n2, if a previous note n1 exists,
there is a legato detection from n2 to n1, allowing fast trills playing
(with or without portamento from n2 to n1. See note below).
Notes in the list are inserted to the end of the list that works like a
circular buffer.The features are:
1) It is always possible to play an infinite legato passage in
direct order (n1_On,n2_On,n3_On,....).
2) Playing legato in the reverse order (n10_Off, n9_Off,,...) helps in
fast trills playing as the list memorizes 10 most recent notes.
3) Playing an infinite lagato passage in ascendant or descendant order,
without playing trills is always possible using the usual way like this:
First we begin with an ascendant passage,
n1On, (n2On,n1Off), (n3On,n2Off) , (n4On,n3Off), then
we continue with a descendant passage
(n3On,n4off), (n2On,n3off), (n1On,n2off), n1Off...and so on
Each MIDI channel have a legato detector.
Note:
Portamento is a feature independant of the legato detector. So
portamento isn't part of the lagato detector. However portamento
(when enabled) is triggered at noteOn (like legato). Like in legato
situation it is usual to have a portamento from a note 'fromkey' to another
note 'tokey'. Portamento fromkey note choice is determined at noteOn by
fluid_synth_get_fromkey_portamento_legato() (see below).
More informations in FluidPolyMono-0004.pdf chapter 4 (Appendices).
******************************************************************************/
/*****************************************************************************
Portamento related functions in Poly or Mono mode
******************************************************************************/
/**
* fluid_synth_get_fromkey_portamento_legato returns two informations:
* - fromkey note for portamento.
* - fromkey note for legato.
* +-----> fromkey_portamento
* ______|________
* portamento modes >------->| |
* | get_fromkey |
* Porta.on/off >------------------------->|_______________|
* (PTC) |
* +-----> fromkey_legato
*
* The functions is intended to be call on noteOn mono
* see fluid_synth_noteon_mono_staccato(), fluid_synth_noteon_monopoly_legato()
* -------
* 1)The function determines if a portamento must occur on next noteOn.
* The value returned is 'fromkey portamento' which is the pitchstart key
* of a portamento, as function of PTC or (default_fromkey, prev_note) both
* if Portamento On. By order of precedence the result is:
* 1.1) PTC have precedence over Portamento On.
* If CC PTC has been received, its value supersedes and any
* portamento pedal On, default_fromkey,prev_note or portamento mode.
* 1.2) Otherwise ,when Portamento On the function takes the following value:
* - default_fromkey if valid
* - otherwise prev_note(prev_note is the note prior the most recent
* note played).
* Then portamento mode is applied to validate the value choosen.
* Where portamento mode is:
* - each note, a portamento occurs on each note.
* - legato only, portamento only on notes played legato.
* - staccato only, portamento only on notes played staccato.
* 1.3) Otherwise, portamento is off,INVALID_NOTE is returned (portamento is disabled).
* ------
* 2)The function determines if a legato playing must occur on next noteOn.
* 'fromkey legato note' is returned as a function of default_fromkey, PTC,
* current mono/poly mode,actual 'staccato/legato' playing state and prev_note.
* By order of precedence the result is:
* 2.1) If valid, default_fromkey have precedence over any others values.
* 2.2) Otherwise if CC PTC has been received its value is returned.
* 2.3) Otherwise fromkey legato is determined from the mono/poly mode,
* the actual 'staccato/legato' playing state (FLUID_CHANNEL_LEGATO_PLAYING) and prev_note
* as this:
* - in (poly/Mono) staccato , INVALID_NOTE is returned.
* - in poly legato , actually we don't want playing legato. So
* INVALID_NOTE is returned.
* - in mono legato , prev_note is returned.
*
* On input
* @param chan fluid_channel_t.
* @param defaultFromkey, the defaut 'fromkey portamento' note or 'fromkey legato'
* note (see description above).
*
* @return
* 1)'fromkey portamento' is returned in fluid_synth_t.fromkey_portamento.
* If valid,it means that portamento is enabled .
*
* 2)The 'fromkey legato' note is returned.
*
* Notes about usage:
* The function is intended to be called when the following event occurs:
* - On noteOn (Poly or Mono) after insertion in the monophonic list.
* - On noteOff(mono legato playing). In this case, default_fromkey must be valid.
*
* Typical calling usage:
* - In poly, default_fromkey must be INVALID_NOTE.
* - In mono staccato playing,default_fromkey must be INVALID_NOTE.
* - In mono legato playing,default_fromkey must be valid.
*/
static unsigned char fluid_synth_get_fromkey_portamento_legato(fluid_channel_t* chan,
unsigned char default_fromkey)
{
unsigned char ptc = fluid_channel_get_cc(chan, PORTAMENTO_CTRL);
if(fluid_channel_is_valid_note(ptc))
{ /* CC PTC has been received */
fluid_channel_clear_portamento(chan); /* clears the CC PTC receive */
chan->synth->fromkey_portamento = ptc;/* returns fromkey portamento */
/* returns fromkey legato */
if(!fluid_channel_is_valid_note(default_fromkey))
{
default_fromkey= ptc;
}
}
else
{ /* determines and returns fromkey portamento */
unsigned char fromkey_portamento = INVALID_NOTE;
if(fluid_channel_portamento(chan))
{ /* Portamento when Portamento pedal is On */
/* 'fromkey portamento'is determined from the portamento mode
and the most recent note played (prev_note)*/
unsigned char portamentomode = chan->portamentomode;
if(fluid_channel_is_valid_note(default_fromkey))
{
fromkey_portamento = default_fromkey; /* on each note */
}
else
{
fromkey_portamento = fluid_channel_prev_note(chan); /* on each note */
}
if(portamentomode == FLUID_CHANNEL_PORTAMENTO_MODE_LEGATO_ONLY)
{ /* Mode portamento:legato only */
if(!(chan->mode & FLUID_CHANNEL_LEGATO_PLAYING))
{
fromkey_portamento = INVALID_NOTE;
}
}
else if(portamentomode == FLUID_CHANNEL_PORTAMENTO_MODE_STACCATO_ONLY)
{ /* Mode portamento:staccato only */
if(chan->mode & FLUID_CHANNEL_LEGATO_PLAYING)
{
fromkey_portamento = INVALID_NOTE;
}
}
/* else Mode portamento: on each note (staccato/legato) */
}
/* Returns fromkey portamento */
chan->synth->fromkey_portamento = fromkey_portamento;
/* Determines and returns fromkey legato */
if(!fluid_channel_is_valid_note(default_fromkey))
{
/* in staccato (poly/Mono) returns INVALID_NOTE */
/* In mono mode legato playing returns the note prior most
recent note played */
if (fluid_channel_is_playing_mono(chan) && (chan->mode & FLUID_CHANNEL_LEGATO_PLAYING))
{
default_fromkey = fluid_channel_prev_note(chan); /* note prior last note */
}
/* In poly mode legato playing, actually we don't want playing legato.
So returns INVALID_NOTE */
}
}
return default_fromkey; /* Returns legato fromkey */
}
/*****************************************************************************
noteon - noteoff functions in Mono mode
******************************************************************************/
/*
* noteon - noteoff on a channel in "monophonic playing".
*
* A channel needs to be played monophonic if this channel has been set in
* monophonic mode by basic channel API.(see fluid_synth_polymono.c).
* A channel needs also to be played monophonic if it has been set in
* polyphonic mode and legato pedal is On during the playing.
* When a channel is in "monophonic playing" state, only one note at a time can be
* played in a staccato or legato manner (with or without portamento).
* More informations in FluidPolyMono-0004.pdf chapter 4 (Appendices).
* _______________
* ________________ | noteon |
* | legato detector| O-->| mono_staccato |--*-> preset_noteon
* noteon_mono ->| (add_monolist) |--O-- |_______________| | (with or without)
* LOCAL |________________| O /|\ | (portamento)
* /|\ set_onenote | | fromkey |
* | | | portamento|
* noteOn poly >---*------------------* | |
* | | |
* | _____ |________ |
* portamento modes >--- | ->| | |
* | | get_fromkey | |
* Porta.on/off >--------------------- | ->|_______________| |
* (PTC) | | |
* | fromkey | fromkey |
* | legato | portamento|
* | _____\|/_______ |
* *-->| noteon |--/
* | | monopoly |
* | | legato |----> voices
* legato modes >------- | ->|_______________| triggering
* | (with or without)
* | (portamento)
* |
* |
* noteOff poly >---*----------------- | ---------+
* | clear | |
* _\|/_____________ | |
* | legato detector | O |
* noteoff_mono->|(search_monolist)|-O-- _____\|/_______
* LOCAL |(remove_monolist)| O-->| noteoff |
* |_________________| | monopoly |----> noteoff
* Sust.on/off >------------------------->|_______________|
* Sost.on/off
------------------------------------------------------------------------------*/
int fluid_synth_noteoff_monopoly(fluid_synth_t* synth, int chan, int key,
char Mono);
int fluid_synth_noteon_monopoly_legato(fluid_synth_t* synth, int chan,
int fromkey, int tokey, int vel);
/**
* Plays a noteon event for a Synth instance in "monophonic playing" state.
* Please see the description above about "monophonic playing".
* _______________
* ________________ | noteon |
* | legato detector| O-->| mono_staccato |--->preset_noteon
* noteon_mono ->| (add_monolist) |--O-- |_______________|
* LOCAL |________________| O
* |
* |
* |
* |
* |
* |
* |
* |
* |
* | _______________
* | | noteon |
* +-->| monopoly |
* | legato |---> voices
* |_______________| triggering
*
* The function uses the legato detector (see above) to determine if the note must
* be played staccato or legato.
*
* @param synth instance.
* @param chan MIDI channel number (0 to MIDI channel count - 1).
* @param key MIDI note number (0-127).
* @param vel MIDI velocity (0-127).
* @return FLUID_OK on success, FLUID_FAILED otherwise.
*/
int fluid_synth_noteon_mono_LOCAL(fluid_synth_t* synth, int chan,
int key, int vel)
{
fluid_channel_t* channel = synth->channel[chan];
/* Adds the note into the monophonic list */
fluid_channel_add_monolist(channel,(unsigned char)key,(unsigned char)vel,0);
/* in Breath Sync mode, the noteon triggering is postponed
until the musician starts blowing in the breath controller */
if (!(channel->mode & FLUID_CHANNEL_BREATH_SYNC) ||
fluid_channel_breath_msb(channel) )
{
/* legato/staccato playing detection */
if(channel->mode & FLUID_CHANNEL_LEGATO_PLAYING)
{ /* legato playing */
/* legato from prev_note to key */
/* the voices from prev_note key number are to be used to play key number */
/* fromkey must be valid */
return fluid_synth_noteon_monopoly_legato(synth, chan,
fluid_channel_prev_note(channel), key, vel);
}
else
{ /* staccato playing */
return fluid_synth_noteon_mono_staccato(synth, chan, key, vel);
}
}
else return FLUID_OK;
}
/**
* Plays a noteoff event for a Synth instance in "monophonic playing" state.
* Please see the description above about "monophonic playing"
*
* _______________
* | noteon |
* +-->| monopoly |
* | | legato |----> voices
* | |_______________| triggering
* | (with or without)
* | (portamento)
* |
* |
* |
* |
* |
* |
* _________________ |
* | legato detector | O
* noteoff_mono->|(search_monolist)|-O-- _______________
* LOCAL |(remove_monolist)| O-->| noteoff |
* |_________________| | monopoly |----> noteoff
* |_______________|
*
* The function uses the legato detector (see above) to determine if the noteoff must
* be played staccato or legato.
*
* @param synth instance.
* @param chan MIDI channel number (0 to MIDI channel count - 1).
* @param key MIDI note number (0-127).
* @return FLUID_OK on success, FLUID_FAILED otherwise.
*/
int fluid_synth_noteoff_mono_LOCAL(fluid_synth_t* synth, int chan, int key)
{
int status;
int i,i_prev;
fluid_channel_t* channel = synth->channel[chan];
/* searching the note in the monophonic list */
i=fluid_channel_search_monolist(channel, (unsigned char)key , &i_prev);
if (i >= 0)
{ /* the note is in the monophonic list */
/* Removes the note from the monophonic list */
fluid_channel_remove_monolist(channel,i , &i_prev);
/* in Breath Sync mode, the noteoff triggering is done
if the musician is blowing in the breath controller */
if (!(channel->mode & FLUID_CHANNEL_BREATH_SYNC) ||
fluid_channel_breath_msb(channel) )
{
/* legato playing detection */
if(channel->mode & FLUID_CHANNEL_LEGATO_PLAYING)
{ /* the list contains others notes */
if(i_prev >= 0)
{ /* legato playing detection on noteoff */
/* legato from key to i_prev key */
/* the voices from key number are to be used to
play i_prev key number. */
status = fluid_synth_noteon_monopoly_legato(synth, chan,
key, channel->monolist[i_prev].note,
channel->monolist[i_prev].vel);
}
/* else the note doesn't need to be played off */
else
{
status = FLUID_OK;
}
}
else
{ /* the monophonic list is empty */
/* plays the monophonic note noteoff and eventually held
by sustain/sostenuto */
status = fluid_synth_noteoff_monopoly(synth, chan, key, 1);
}
}
else
{
status = FLUID_OK;
}
}
else
{ /* the note is not found in the list so the note was
played On when the channel was in polyphonic playing */
/* plays the noteoff as for polyphonic */
status = fluid_synth_noteoff_monopoly(synth, chan, key, 0);
}
return status;
}
/*----------------------------------------------------------------------------
staccato playing
-----------------------------------------------------------------------------*/
/**
* Plays noteon for a monophonic note in staccato manner.
* Please see the description above about "monophonic playing".
* _______________
* | noteon |
* noteon_mono >------------------------>| mono_staccato |----> preset_noteon
* |_______________| (with or without)
* LOCAL /|\ (portamento)
* | fromkey
* | portamento
* |
* |
* ______|________
* portamento modes >----->| |
* | get_fromkey |
* Porta.on/off >----------------------->|_______________|
* Portamento
* (PTC)
*
* We are in staccato situation (where no previous note have been depressed).
* Before the note been passed to fluid_preset_noteon(), the function must determine
* the from_key_portamento parameter used by fluid_preset_noteon().
*
* from_key_portamento is returned by fluid_synth_get_fromkey_portamento_legato() function.
* fromkey_portamento is set to valid/invalid key value depending of the portamento
* modes (see portamento mode API) , CC portamento On/Off , and CC portamento control
* (PTC).
*
* @param synth instance.
* @param chan MIDI channel number (0 to MIDI channel count - 1).
* @param key MIDI note number (0-127).
* @param vel MIDI velocity (0-127).
* @return FLUID_OK on success, FLUID_FAILED otherwise.
*/
int
fluid_synth_noteon_mono_staccato(fluid_synth_t* synth,int chan,int key,int vel)
{
fluid_channel_t* channel = synth->channel[chan];
/* Before playing a new note, if a previous monophonic note is currently
sustained it needs to be released */
fluid_synth_release_voice_on_same_note_LOCAL(synth,chan, channel->key_mono_sustained);
/* Get possible 'fromkey portamento' */
fluid_synth_get_fromkey_portamento_legato( channel, INVALID_NOTE);
/* The note needs to be played by voices allocation */
return fluid_preset_noteon(channel->preset, synth, chan, key, vel);
}
/**
* Plays noteoff for a polyphonic or monophonic note
* Please see the description above about "monophonic playing".
*
*
* noteOff poly >---------------------------------+
* |
* |
* |
* noteoff_mono _____\|/_______
* LOCAL >------------------------->| noteoff |
* | monopoly |----> noteoff
* Sust.on/off >------------------------->|_______________|
* Sost.on/off
*
* The function has the same behaviour when the noteoff is poly of mono, except
* that for mono noteoff, if any pedal (sustain or sostenuto ) is depressed, the
* key is memorized. This is neccessary when the next mono note will be played
* staccato, as any current mono note currently sustained will need to be released
* (see fluid_synth_noteon_mono_staccato()).
* Note also that for a monophonic legato passage, the function is called only when
* the last noteoff of the passage occurs. That means that if sustain or sostenuto
* is depressed, only the last note of a legato passage will be sustained.
*
* @param synth instance.
* @param chan MIDI channel number (0 to MIDI channel count - 1).
* @param key MIDI note number (0-127).
* @param Mono, 1 noteoff on monophonic note.
* 0 noteoff on polyphonic note.
* @return FLUID_OK on success, FLUID_FAILED otherwise.
*
* Note: On return, on monophonic, possible sustained note is memorized in
* key_mono_sustained. Memorization is done here on noteOff.
*/
int fluid_synth_noteoff_monopoly(fluid_synth_t* synth, int chan, int key,
char Mono)
{
int status = FLUID_FAILED;
fluid_voice_t* voice;
int i;
fluid_channel_t* channel = synth->channel[chan];
/* Key_sustained is prepared to return no note sustained (INVALID_NOTE) */
if (Mono)
{
channel->key_mono_sustained = INVALID_NOTE; /* no mono note sustained */
}
/* noteoff for all voices with same chan and same key */
for (i = 0; i < synth->polyphony; i++)
{
voice = synth->voice[i];
if (fluid_voice_is_on(voice) &&
fluid_voice_get_channel(voice) == chan &&
fluid_voice_get_key(voice) == key)
{
if (synth->verbose)
{
int used_voices = 0;
int k;
for (k = 0; k < synth->polyphony; k++)
{
if (!_AVAILABLE(synth->voice[k]))
{
used_voices++;
}
}
FLUID_LOG(FLUID_INFO, "noteoff\t%d\t%d\t%d\t%05d\t%.3f\t%d",
fluid_voice_get_channel(voice), fluid_voice_get_key(voice), 0,
fluid_voice_get_id(voice),
(fluid_curtime() - synth->start) / 1000.0f,
used_voices);
} /* if verbose */
fluid_voice_noteoff(voice);
/* noteoff on monophonic note */
/* Key memorization if the note is sustained */
if(Mono &&
(fluid_voice_is_sustained(voice) || fluid_voice_is_sostenuto(voice)))
{
channel->key_mono_sustained = key;
}
status = FLUID_OK;
} /* if voice on */
} /* for all voices */
return status;
}
/*----------------------------------------------------------------------------
legato playing
-----------------------------------------------------------------------------*/
/**
* Plays noteon for a monophonic note played legato.
* Please see the description above about "monophonic playing".
*
*
* _______________
* portamento modes >----->| |
* | get_fromkey |
* Porta.on/off >----------------------->|_______________|
* Portamento |
* (PTC) | +-->preset_noteon
* fromkey | fromkey | (with or without)
* legato | portamento| (portamento)
* _____\|/_______ |
* | noteon |--+
* noteon_mono >------------------------>| monopoly |
* LOCAL | legato |----->voices
* |_______________| triggering
* /|\ (with or without)
* | (portamento)
* legato modes >-----------------+
*
* We are in legato situation (where a previous note has been depressed).
* The function must determine the from_key_portamento and from_key_legato parameters
* used respectively by fluid_preset_noteon() function and voices triggering functions.
*
* from_key_portamento and from_key_legato are returned by
* fluid_synth_get_fromkey_portamento_legato() function.
* fromkey_portamento is set to valid/invalid key value depending of the portamento
* modes (see portamento mode API), CC portamento On/Off, and CC portamento control
* (PTC).
* Then, depending of the legato modes (see legato mode API), the function will call
* the appropriate triggering functions.
* @param synth instance.
* @param chan MIDI channel number (0 to MIDI channel count - 1).
* @param fromkey MIDI note number (0-127).
* @param tokey MIDI note number (0-127).
* @param vel MIDI velocity (0-127).
* @return FLUID_OK on success, FLUID_FAILED otherwise.
*
* Note: The voices with key 'fromkey' are to be used to play key 'tokey'.
* The function is able to play legato through Preset Zone(s) (PZ) and
* Instrument Zone(s) (IZ) as far as possible.
* When key tokey is outside the current Instrument Zone, Preset Zone,
* current 'fromkey' voices are released. If necessary new voices
* are restarted when tokey enters inside new Instrument(s) Zones,Preset Zone(s).
* More informations in FluidPolyMono-0004.pdf chapter 4.7 (Appendices).
*/
int fluid_synth_noteon_monopoly_legato(fluid_synth_t* synth, int chan,
int fromkey, int tokey, int vel)
{
fluid_channel_t* channel = synth->channel[chan];
unsigned char legatomode = channel->legatomode;
fluid_voice_t* voice;
int i ;
/* Gets possible 'fromkey portamento' and possible 'fromkey legato' note */
fromkey = fluid_synth_get_fromkey_portamento_legato( channel, (unsigned char)fromkey);
if (fluid_channel_is_valid_note(fromkey)) for (i = 0; i < synth->polyphony; i++)
{
/* searching fromkey voices: only those who don't have 'note off' */
voice = synth->voice[i];
if (fluid_voice_is_on(voice) &&
fluid_voice_get_channel(voice) == chan &&
fluid_voice_get_key(voice) == fromkey)
{
fluid_zone_range_t * zone_range = voice->zone_range;
/* Ignores voice when there is no instrument zone (i.e no zone_range). Otherwise
checks if tokey is inside the range of the running voice */
if (zone_range && fluid_zone_inside_range(zone_range, tokey, vel))
{
switch (legatomode)
{
case FLUID_CHANNEL_LEGATO_MODE_RETRIGGER: /* mode 0 */
fluid_voice_release(voice); /* normal release */
break;
case FLUID_CHANNEL_LEGATO_MODE_MULTI_RETRIGGER: /* mode 1 */
/* Skip in attack section */
fluid_voice_update_multi_retrigger_attack(voice,tokey,vel);
/* Starts portamento if enabled */
if(fluid_channel_is_valid_note(synth->fromkey_portamento))
{
/* Sends portamento parameters to the voice dsp */
fluid_voice_update_portamento(voice,
synth->fromkey_portamento,
tokey);
}
/* The voice is now used to play tokey in legato manner */
/* Marks this Instrument Zone to be ignored during next
fluid_preset_noteon() */
zone_range->ignore = TRUE;
break;
default: /* Invalid mode: this should never happen */
FLUID_LOG(FLUID_WARN, "Failed to execute legato mode: %d",
legatomode);
return FLUID_FAILED;
}
}
else
{ /* tokey note is outside the voice range, so the voice is released */
fluid_voice_release(voice);
}
}
}
/* May be,tokey will enter in new others Insrument Zone(s),Preset Zone(s), in
this case it needs to be played by voices allocation */
return fluid_preset_noteon(channel->preset,synth,chan,tokey,vel);
}

View file

@ -27,6 +27,7 @@
#include "fluid_sys.h"
#include "fluid_sfont.h"
#include "fluid_rvoice_event.h"
#include "fluid_defsfont.h"
/* used for filter turn off optimization - if filter cutoff is above the
specified value and filter q is below the other value, turn filter off */
@ -241,9 +242,14 @@ delete_fluid_voice(fluid_voice_t* voice)
/* fluid_voice_init
*
* Initialize the synthesis process
* inst_zone, the Instrument Zone contains the sample, Keyrange,Velrange
* of the voice.
* When playing legato (n1,n2) in mono mode, n2 will use n1 voices
* as far as n2 still enters in Keyrange,Velrange of n1.
*/
int
fluid_voice_init(fluid_voice_t* voice, fluid_sample_t* sample,
fluid_voice_init(fluid_voice_t* voice, fluid_sample_t* sample,
fluid_zone_range_t *inst_zone_range,
fluid_channel_t* channel, int key, int vel, unsigned int id,
unsigned int start_time, fluid_real_t gain)
{
@ -266,6 +272,7 @@ fluid_voice_init(fluid_voice_t* voice, fluid_sample_t* sample,
if (voice->sample)
fluid_voice_off(voice);
voice->zone_range = inst_zone_range; /* Instrument zone range for legato */
voice->id = id;
voice->chan = fluid_channel_get_num(channel);
voice->key = (unsigned char) key;
@ -453,14 +460,18 @@ fluid_voice_calculate_gain_amplitude(const fluid_voice_t* voice, fluid_real_t ga
return gain * voice->synth_gain / (INT24_MAX * 1.0f);
}
void
fluid_voice_calculate_gen_pitch(fluid_voice_t* voice)
/* Useful to return the nominal pitch of a key */
/* The nominal pitch is dependant of voice->root_pitch,tuning, and
GEN_SCALETUNE generator.
This is useful to set the value of GEN_PITCH generator on noteOn.
This is useful to get the beginning/ending pitch for portamento.
*/
fluid_real_t fluid_voice_calculate_pitch(fluid_voice_t* voice, int key)
{
fluid_tuning_t* tuning;
fluid_real_t x;
fluid_real_t x,pitch;
/* The GEN_PITCH is a hack to fit the pitch bend controller into the
* modulator paradigm. Now the nominal pitch of the key is set.
/* Now the nominal pitch of the key is returned.
* Note about SCALETUNE: SF2.01 8.1.3 says, that this generator is a
* non-realtime parameter. So we don't allow modulation (as opposed
* to fluid_voice_gen_value(voice, GEN_SCALETUNE) When the scale tuning is varied,
@ -469,15 +480,22 @@ fluid_voice_calculate_gen_pitch(fluid_voice_t* voice)
if (fluid_channel_has_tuning(voice->channel)) {
tuning = fluid_channel_get_tuning (voice->channel);
x = fluid_tuning_get_pitch (tuning, (int)(voice->root_pitch / 100.0f));
voice->gen[GEN_PITCH].val = voice->gen[GEN_SCALETUNE].val / 100.0f *
(fluid_tuning_get_pitch (tuning, fluid_voice_get_actual_key(voice)) - x) + x;
pitch = voice->gen[GEN_SCALETUNE].val / 100.0f *
(fluid_tuning_get_pitch (tuning, key) - x) + x;
} else {
voice->gen[GEN_PITCH].val = voice->gen[GEN_SCALETUNE].val
* (fluid_voice_get_actual_key(voice) - voice->root_pitch / 100.0f) + voice->root_pitch;
pitch = voice->gen[GEN_SCALETUNE].val
* (key - voice->root_pitch / 100.0f) + voice->root_pitch;
}
return pitch;
}
void
fluid_voice_calculate_gen_pitch(fluid_voice_t* voice)
{
voice->gen[GEN_PITCH].val = fluid_voice_calculate_pitch(voice, fluid_voice_get_actual_key(voice));
}
/*
* fluid_voice_calculate_runtime_synthesis_parameters
*
@ -596,6 +614,17 @@ fluid_voice_calculate_runtime_synthesis_parameters(fluid_voice_t* voice)
fluid_voice_update_param(voice, list_of_generators_to_initialize[n]);
}
/* Start portamento if enabled */
{ /* fromkey note comes from "GetFromKeyPortamentoLegato()" detector.
When fromkey is set to ValidNote , portamento is started */
/* Return fromkey portamento */
int fromkey = voice->channel->synth->fromkey_portamento;
if(fluid_channel_is_valid_note(fromkey))
{ /* Send portamento parameters to the voice dsp */
fluid_voice_update_portamento(voice,fromkey, fluid_voice_get_actual_key(voice));
}
}
/* Make an estimate on how loud this voice can get at any time (attenuation). */
UPDATE_RVOICE_R1(fluid_rvoice_set_min_attenuation_cB,
fluid_voice_get_lower_boundary_for_attenuation(voice));
@ -701,7 +730,7 @@ fluid_voice_update_param(fluid_voice_t* voice, int gen)
/* range checking is done in the fluid_pan and fluid_balance functions */
voice->pan = fluid_voice_gen_value(voice, GEN_PAN);
voice->balance = fluid_voice_gen_value(voice, GEN_CUSTOM_BALANCE);
/* left amp */
UPDATE_RVOICE_BUFFERS2(fluid_rvoice_buffers_set_amp, 0,
fluid_voice_calculate_gain_amplitude(voice,
@ -798,7 +827,7 @@ fluid_voice_update_param(fluid_voice_t* voice, int gen)
case GEN_CUSTOM_FILTERQ:
UPDATE_RVOICE_CUSTOM_FILTER1(fluid_iir_filter_set_q, x);
break;
case GEN_MODLFOTOPITCH:
fluid_clip(x, -12000.0, 12000.0);
UPDATE_RVOICE_R1(fluid_rvoice_set_modlfo_to_pitch, x);
@ -1164,6 +1193,72 @@ int fluid_voice_modulate_all(fluid_voice_t* voice)
return FLUID_OK;
}
/** legato update functions --------------------------------------------------*/
/* Updates voice portamento parameters
*
* @voice voice the synthesis voice
* @fromkey the beginning pitch of portamento.
* @tokey the ending pitch of portamento.
*
* The function calculates pitch offset and increment, then these parameters
* are send to the dsp.
*/
void fluid_voice_update_portamento (fluid_voice_t* voice, int fromkey,int tokey)
{
fluid_channel_t* channel= voice->channel;
/* calculates pitch offset */
fluid_real_t PitchBeg = fluid_voice_calculate_pitch(voice,fromkey);
fluid_real_t PitchEnd = fluid_voice_calculate_pitch(voice,tokey);
fluid_real_t pitchoffset = PitchBeg - PitchEnd;
/* Calculates increment countinc */
/* Increment is function of PortamentoTime (ms)*/
unsigned int countinc = (unsigned int)(((fluid_real_t)voice->output_rate *
0.001f *
(fluid_real_t)fluid_channel_portamentotime(channel)) /
(fluid_real_t)FLUID_BUFSIZE +0.5);
/* Sends portamento parameters to the voice dsp */
UPDATE_RVOICE2(fluid_rvoice_set_portamento, countinc, pitchoffset);
}
/*---------------------------------------------------------------*/
/*legato mode 1: multi_retrigger
*
* Modulates all generators dependent of key,vel.
* Forces the voice envelopes in the attack section (legato mode 1).
*
* @voice voice the synthesis voice
* @tokey the new key to be applied to this voice.
* @vel the new velocity to be applied to this voice.
*/
void fluid_voice_update_multi_retrigger_attack(fluid_voice_t* voice,
int tokey, int vel)
{
voice->key = tokey; /* new note */
voice->vel = vel; /* new velocity */
/* Updates generators dependent of velocity */
/* Modulates GEN_ATTENUATION (and others ) before calling
fluid_rvoice_multi_retrigger_attack().*/
fluid_voice_modulate(voice, FALSE, FLUID_MOD_VELOCITY);
/* Updates generator dependent of voice->key */
fluid_voice_update_param(voice, GEN_KEYTOMODENVHOLD);
fluid_voice_update_param(voice, GEN_KEYTOMODENVDECAY);
fluid_voice_update_param(voice, GEN_KEYTOVOLENVHOLD);
fluid_voice_update_param(voice, GEN_KEYTOVOLENVDECAY);
/* Updates pitch generator */
fluid_voice_calculate_gen_pitch(voice);
fluid_voice_update_param(voice, GEN_PITCH);
/* updates adsr generator */
UPDATE_RVOICE0(fluid_rvoice_multi_retrigger_attack);
}
/** end of legato update functions */
/*
Force the voice into release stage. Useful anywhere a voice
needs to be damped even if pedals (sustain sostenuto) are depressed.
@ -1183,8 +1278,9 @@ fluid_voice_release(fluid_voice_t* voice)
* fluid_voice_noteoff
*
* Sending a noteoff event will advance the envelopes to section 5 (release).
* The function is convenient for polyphonic or monophonic note
*/
int
void
fluid_voice_noteoff(fluid_voice_t* voice)
{
fluid_channel_t* channel;
@ -1201,13 +1297,11 @@ fluid_voice_noteoff(fluid_voice_t* voice)
}
/* Or sustain a note under Sustain pedal */
else if (fluid_channel_sustained(channel)) {
voice->status = FLUID_VOICE_SUSTAINED;
voice->status = FLUID_VOICE_SUSTAINED;
}
/* Or force the voice to release stage */
else
fluid_voice_release(voice);
return FLUID_OK;
}
/*

View file

@ -33,7 +33,6 @@
#define NO_CHANNEL 0xff
typedef struct _fluid_overflow_prio_t fluid_overflow_prio_t;
struct _fluid_overflow_prio_t
@ -73,6 +72,7 @@ struct _fluid_voice_t
fluid_gen_t gen[GEN_LAST];
fluid_mod_t mod[FLUID_NUM_MOD];
int mod_count;
fluid_zone_range_t * zone_range; /* instrument zone range*/
fluid_sample_t* sample; /* Pointer to sample (dupe in rvoice) */
/* basic parameters */
@ -123,7 +123,8 @@ void fluid_voice_calculate_gen_pitch(fluid_voice_t* voice);
int fluid_voice_write (fluid_voice_t* voice, fluid_real_t *dsp_buf);
int fluid_voice_init(fluid_voice_t* voice, fluid_sample_t* sample,
int fluid_voice_init(fluid_voice_t* voice, fluid_sample_t* sample,
fluid_zone_range_t *inst_zone_range,
fluid_channel_t* channel, int key, int vel,
unsigned int id, unsigned int time, fluid_real_t gain);
@ -146,8 +147,15 @@ int fluid_voice_set_output_rate(fluid_voice_t* voice, fluid_real_t value);
function.*/
void fluid_voice_update_param(fluid_voice_t* voice, int gen);
/** legato modes */
/* force in the attack section for legato mode multi_retrigger: 1 */
void fluid_voice_update_multi_retrigger_attack(fluid_voice_t* voice,int tokey, int vel);
/* Update portamento parameter */
void fluid_voice_update_portamento (fluid_voice_t* voice, int fromkey, int tokey);
void fluid_voice_release(fluid_voice_t* voice);
int fluid_voice_noteoff(fluid_voice_t* voice);
void fluid_voice_noteoff(fluid_voice_t* voice);
void fluid_voice_off(fluid_voice_t* voice);
void fluid_voice_stop(fluid_voice_t* voice);
void fluid_voice_overflow_rvoice_finished(fluid_voice_t* voice);

View file

@ -1209,7 +1209,7 @@ fluid_str_equal (const void *v1, const void *v2)
const char *string1 = v1;
const char *string2 = v2;
return strcmp (string1, string2) == 0;
return FLUID_STRCMP (string1, string2) == 0;
}
/**

View file

@ -915,7 +915,7 @@ fluid_istream_gets (fluid_istream_t in, char* buf, int len)
* @return Number of bytes written or -1 on error
*/
int
fluid_ostream_printf (fluid_ostream_t out, char* format, ...)
fluid_ostream_printf (fluid_ostream_t out, const char* format, ...)
{
char buf[4096];
va_list args;

View file

@ -341,7 +341,7 @@ typedef GModule fluid_module_t;
fluid_istream_t fluid_get_stdin (void);
fluid_ostream_t fluid_get_stdout (void);
int fluid_istream_readline(fluid_istream_t in, fluid_ostream_t out, char* prompt, char* buf, int len);
int fluid_ostream_printf (fluid_ostream_t out, char* format, ...);
int fluid_ostream_printf (fluid_ostream_t out, const char* format, ...);
/* The function should return 0 if no error occured, non-zero
otherwise. If the function return non-zero, the socket will be

View file

@ -199,6 +199,7 @@ typedef struct _fluid_hashtable_t fluid_hashtable_t;
typedef struct _fluid_client_t fluid_client_t;
typedef struct _fluid_server_socket_t fluid_server_socket_t;
typedef struct _fluid_sample_timer_t fluid_sample_timer_t;
typedef struct _fluid_zone_range_t fluid_zone_range_t;
/***************************************************************
*