[LAD] C++11 user defined literals: Musical duration

Mario Lang mlang at delysid.org
Mon Feb 18 18:10:08 UTC 2013


hi.

The following just manifested itself while experimenting with code.  I
find it quite neat since it makes for quite natural looking constants:

class duration_log
{
  int8_t log;
public:
  constexpr duration_log(int log) : log(log) {}
  constexpr operator int() const { return log; }
  template<char...> friend duration_log constexpr operator"" _th();
};

           duration_log constexpr            maxima               =         3;
           duration_log constexpr            longa                =         2;
           duration_log constexpr            breve                =         1;
           duration_log constexpr            whole                =         0;
           duration_log constexpr            half                 =        -1;
           duration_log constexpr            quarter              =        -2;
template<> duration_log constexpr operator"" _th<'8'          >() { return -3; }
template<> duration_log constexpr operator"" _th<'1', '6'     >() { return -4; }
template<> duration_log constexpr operator"" _th<'3', '2'     >() { return -5; }
template<> duration_log constexpr operator"" _th<'6', '4'     >() { return -6; }
template<> duration_log constexpr operator"" _th<'1', '2', '8'>() { return -7; }
template<> duration_log constexpr operator"" _th<'2', '5', '6'>() { return -8; }

---

(there is actually no need for the wrapper class duration_log, but it
 makes it easier to play with overloaded functions.  You could of course
 just replace duration_log with int, if you do not care for type safety.)

Now I can write things like "16_th" or "64_th".

It turns out that there is a quite neat formula for the typical music
notation duration calculation.  Given that the base rhythmic type is
expressed as a log (as in LilyPond for instance), the rational number of
the duration with a certain amount of dots and time modification (tuple) can be
written like this:

#include <boost/rational.hpp>

template<typename Rational = boost::rational<int>>
inline Rational augmented_rational( int log, unsigned dots
                                  , int numerator, int denominator
                                  )
{
  return log < 0 ? Rational { ((1 << (dots + 1)) - 1) * numerator
                            , denominator << -log << dots
                            }
                 : Rational { (((1 << (dots + 1)) - 1) << log) * numerator
                            , denominator << dots
                            };
}

---

This is quite efficient since there is no need to multiply or manipulate
rational numbers in any way.  You just get the final value straight out
of the expression.

Comments?

-- 
CYa,
  ⡍⠁⠗⠊⠕


More information about the Linux-audio-dev mailing list