Weekly status update May 23rd to May 29th

Posted 7 years ago

Hi,
I'm already doing quite some blogging but I think having a short week summary is actually a good idea to see if I'm on track and have a short overview what is going on without too much detail.

The week started with a very technical blog post about volume in Fluidsynth. There was some good conversation with lasconic and churchorganist. I think I'm quite sure which road I'll take to have good (de)crescendo. I'll focus on CC11 over velocity - there might be three options in MuseScore after that:

  1. traditional pure velocity based volume (for instruments like piano)
  2. CC11 based volume with traditional velocity values
  3. CC11 based volume with a fixed velocity value

The second options should disable volume changes via velocity in Fluidsynth.

Right after posting that post I started working on legato. I just skipped the attack, hold and decay and started right away with sustain - which sadly sounds awful right now. To detect if the note should be played legato I used Midi CC68 and modified the renderSpanners method in rendermidi.cpp to render these events for slurs. I'm not sure if I should maybe render the start with a little delay so that it should never happen that the first note is played without attack/hold/decay but actually having some state in Fluidsynth might be better. But I don't know how that should be realized right now.
I know I needed little fades between the notes to have a better sound. But I realized that it is not possible the way envelops are treated right now in MuseScore Fluidsynth. Have a look at this picture:
ADSR_MS_vs_Fluid.png

I created a Sounfont with a very short envelope phases (shortest I could enter in polyphone) as you can see in upstream Fluidsynth below it seems rendered properly as in MuseScore attack seems quite longer and release is left out completely. That is because Fluidsynth switches envelopes just for a single buffer - so if your buffer is 1024 samples the shortest envelope duration is 1024 samples! Which might be a lot too much for short translation between legato notes. Upstream Fluidsynth doesn't have that problem because it has an internal buffer of 64 - so it's shortest phases are 64 samples. Werner thinks that not depending on buffer size (which you do if you have a fixed 64 sample internal buffer) is something that makes MuseScore Fluidsynth better. So I could have something like an internal buffer or call the routine several times (so that at least no coping in necessary) to fill the buffer - but it would also depend on the buffer being a multiple of whatever internal value you use and wouldn't be that clean after all. I'll try to determine exact (like sample accurate) switches between envelope phases and have them rendered accordingly. That will very likely also fix another bug that I stumbled upon this week.

I also did a look how Sibelius 6.1.0 on OSX handled crescendo and legato. Sadly there is no single note (de)crescendo nor a special treatment of legato in sound. But legatos midi is different than the MuseScore one. Have a look at this picture:
LegatoMIDI_MS_vs_Sibelius.png
The one above is Sibelius the one below is MuseScore. Sibelius renders the midi more like I would expect it to be rendered. For legato there should be some overlap (that would also be nice for having a proper cross fade between the notes during crescendo). Currently MuseScore just renders legato notes with a length of 100% - they should probably be rendered with 110% and moved 5% ahead in time. That is something I'll plan to fix as well in next week. But I'll have a look at recent versions of finale and sibelius (there are trial versions) and have a look how they do (de)crescendo and legato in recent versions.

I also discovered a bug in Fluidsynth that it will distort a sample if the loop contains the whole sample. (There is some sanity checking going on which checks if the loop is larger than the sample and cuts it to a smaller part. But there is an <= which should probably better just < since I don't know why a loop shouldn't start at sample start.)

A also dived a little more into Zerberus code (which is quite clearly - also because it is not that big) but I got a little interested what is actually happening for interpolation. It is basically a cubic interpolation. But it is not so easy to understand it from code. I might write a bigger blog article about that later.

I also had a look at recent Fluidsynth and the code is quite different (mostly because it is refactored a lot) compared to our code in MuseScore. I thought about maybe switching to just use the library of Fluidsynth but Werner didn't like that idea because he thinks our Fluidsynth has several advantages to upstream Fluidsynth including:

  • SF3
  • on demand loading of instruments
  • no internal buffer

So that blog post got a little bigger than I thought. But hopefully you get an idea what is going on!


Comments

In reply to by [DELETED] 5

That means generate CC11 events while still using velocity. Then disable the effect of velocity on the volume - that way you have velocity switching and all other means that the different velocity would give and still being able to use CC11 for (de)crescendo in an easy way!