musescore/MuseScore — pull request #1325 by CombatCube (2014-09-19 10:06:19+00:00)
Title: fix #4905: Crescendo/decrescendo playback

As Marc Sabetella pointed out, the code for this was already present, but not working. Let's start with updateHairpin(). It adds ramp/fixed anchor points to an overall velocity envelope of a staff so that calls to velo() would return the fixed amount, or interpolate between the current velocity and the Velocity Change parameter. If Velocity Change is 0, it will use the following fixed velocity as the end anchor (probably a dynamic that immediately follows). The only thing wrong with this code was handling of decrescendos. The user needs know what he's doing when setting Velocity Change to 0, or else a "p decrescendo f" will actually crescendo (if he sets Velocity Change to 20, it will go down and immediately jump back up to f, which is probably the correct interpretation).

updateHairpin() seemed to get called whenever it should, updating staff velocity anchor points whenever it got changed (paste/undo etc.). However, when renderMidi() calls updateVelo(), it clears the entire velocity event list. updateVelo() then creates new velocity events where dynamics are, but not where hairpins are. I changed the code to fix this, so after the velocity events are created for all the dynamics of a staff, updateHairpin() is called for all of its hairpins, thus creating a proper velocity envelope.

Finally, I changed the Inspector to allow values up to 127 in the Velocity/Velocity Change fields for dynamics and hairpins, respectively.