[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