lilypond-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Suggested patch to make midiMaximumVolume take effect without initial dy


From: Anders Pilegaard
Subject: Suggested patch to make midiMaximumVolume take effect without initial dynamic
Date: Sat, 9 Mar 2013 20:57:26 +0100

Hello all.

This is getting a bit long, so here's a brief overview of what's in
this mail:

 - I'm proposing a patch so setting midiMaximumVolume (and
   midiMinimumVolume) doesn't require an initial explicit dynamic like
   \ff

 - I'd like some feedback on the patch and the regression tests, some
   of which are ... strange ...

Attached:  Suggested patch, and output from regression test.


Background
----------

 I'm singing in a choir, and I'm using lilypond to create "practice
voices".  Oh, and sometimes I also prepare sheet music ... :-)

Briefly, practice voices in my setup are midi files, suited for
practising one specific voice of a choral arrangement.  The midi file
contains all voices, and accompaniment if relevant - but all voices
except one are much lower volume, so they "stay in the background".
Ie. you can hear your own voice clearly, while the rest are lower
volume, but still audible.  Sometimes I also lower the tempo, or add a
metronome, or ...  Example at:

  http://hadstenblandedekor.dk/Nodetest/OComeAllYeFaithful/

I find that Lilypond is quite well suited for this, as I can write the
music once, and then create a number of these practice voices easily.

And now we come to the reason why I wrote this: I'm using
midiMaximumVolume to scale down the "background" voices - and I'm
finding it increasingly annoying that I *have* to add a dynamic before
the setting takes effect.  Example (reduced from piano accompaniment
part of a piece I made practice voices for):

  \score {
    \new Staff \with { midiMaximumVolume = #0.3 } {
      c'8\ff e' g' e'
      <<
        { c'8 e' g' e' c'2 } \\ { c'2 c'8 e' g' e' }
      >>
    }
    \layout {}
    \midi {}
  }

The first \ff sets the volume for the first 4 notes as expected - but
the remaining notes are still at full volume.  Probably since the \\
introduces new voice contexts.  To get all of this music to have the
intended volume I need to issue an \ff in every direct and indirect
context ... :-( ... :

  \score {
    \new Staff \with { midiMaximumVolume = #0.3 } {
      c'8\ff e' g' e'
      <<
        { c'8\ff e' g' e' c'2 } \\ { c'2\ff c'8 e' g' e' }
      >>
    }
    \layout {}
    \midi {}
  }


That's what I mean by annoying ... :-) ...

In other words, I'd like to get rid of *all* the \ff's in the example
above.  Well, I'm a programmer, and this is open source - so I set out
trying to fix this myself to work as I wanted it to ... :-) ...  The
status is that I *do* have something that seems to work - but it may
have some unwanted side-effects.  So I'm presenting it here for
comments.

I've been reading through the contributors guide, and I have been
running the regression tests.  I'm attaching the patch, and the
current regression test.


The patch
---------

My idea is to ensure that the volume is *always* initialised in
Dynamic_performer::process_music.  The code to do that is mostly
copied from what happens if there is an actual script event.

The constant 0.71 was obtained by calculating backwards from the
default velocity value (0x5a) in the Midi_note constructor,
midi-item.cc line 179.

I found that I had to create and announce an Audio_element_info for
the change to take effect.  There could well be other, more elegant
ways to get this to work ... ?


Backward compatibility notes
----------------------------

As far as the music itself goes there are a few cases:

 - Music that doesn't set midiMaximumVolume or midiMinimumVolume will
   be unchanged, as the default dynamic setting is chosen so the
   calculated midi velocity is the same as the current default when no
   volume is set.

 - Music that sets midiMaximumVolume or midiMinimumVolume and has
   initial dynamic expressions will be unchanged - the explicit
   dynamic takes effect before the first midi note is created.

 - Music that sets midiMaximumVolume or midiMinimumVolume but doesn't
   have an initial dynamic _expression_ will change.  In the current
   version such would be an error, so I don't expect many of those.  I
   hope it is ok that those change ... ?


Regressions
-----------

(Based on git commit 5c44c7e89f7871f2949a5507b1f5c38d6b02a447)

This part gave me some surprises.

 1) There are additional midi events, setting channel volume to 100.
 2) Midi track assignments have changed.
 3) Some error messages have disappeared! ("programming error: Parsed
    object should be dead ...")
 4) Similar to 3, others have appeared, still others have changed ... ?
 5) Some graphical score outputs have changed!
 6) An expected warning "(De)crescendo with unspecified starting
    volume in MIDI" has disappeared.

I think 6 is not serious.  The warning has gone away because my patch
now always explicitly sets midi volume.  Would this hurt anyone?

After some thought, I *think* 1 is the cause of 2 and 5.  With my
change the first midi event from a given context comes much earlier
than previously, and very likely in another order.  This could well
influence the track assignment.  And the graphical changes seem to be
a further consequence, as the track numbering change causes other
voice names to be displayed in front of the staves when converted by
midi2ly.

On the other hand I have no idea what to think about 3 and 4.  I can
see from searches that similar errors have been previously discussed -
and removed(?).  My build was done with "./configure
--disable-optimising --disable-documentation".  It seems like my patch
doesn't really change the status quo - some errors are added while
others are removed.  Maybe they can just be ignored?

On the topic of the extra midi events: Are they actually needed?  They
already appear whenever there's a dynamic event (eg. \ff) - but they
don't seem to (any more?) have any real use?  They are created by
Midi_dynamic::to_string (midi-item.cc line 265), and in all the cases
I've seen so far audio_->silent_ has been true, so they end up setting
channel volume to 100.

There are some indications in
Staff_performer::acknowledge_audio_element (staff-performer.cc, line
321) that these Audio_dynamic events should perhaps be completely
silent - ie. removed?  But I haven't dug deep enough in the code to
really understand the implications of the various alternatives here.

Could these Midi dynamic events be completely removed?  If so, I could
look into making another patch to remove them ...

Comments, pointers and suggestions are more than welcome!

Best regards,
  Anders Pilegaard

Attachment: 0001-Make-midiM-imumVolume-take-effect-when-voice-is-crea.patch
Description: Binary data

Attachment: test-results.tar.gz
Description: GNU Zip compressed data


reply via email to

[Prev in Thread] Current Thread [Next in Thread]