Created
August 31, 2014 05:42
-
-
Save cjxgm/6ccdcb1197cc6ef063f9 to your computer and use it in GitHub Desktop.
bnd timecode: beat + numer/denom
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdexcept> | |
#include <iostream> | |
#include <chrono> | |
using std::cout; | |
using std::endl; | |
// numer | |
// beat + ------- = beat (add) numer (over) denom -> band or bnd | |
// denom | |
// must NOT reduce! | |
struct bnd | |
{ | |
using beat_type = int; | |
using numer_type = int; | |
using denom_type = numer_type; | |
beat_type b = 0; | |
numer_type n = 0; | |
denom_type d = 1; | |
bnd() = default; | |
bnd(beat_type b_, numer_type n_, denom_type d_) | |
: b{b_}, n{n_}, d{d_} | |
{ | |
if (!d_) throw std::invalid_argument{"denominator cannot be zero."}; | |
b += n / d; | |
n %= d; | |
} | |
explicit operator double() const { return b + double(n)/d; } | |
}; | |
bool operator<(bnd const& a, bnd const& b) | |
{ | |
if (a.b < b.b) return true; | |
if (a.b > b.b) return false; | |
return (a.n*b.d < b.n*a.d); | |
} | |
template <class T> | |
decltype(auto) operator*(bnd const& time, T b) | |
{ | |
static_assert(std::is_integral<T>(), | |
"a bnd can only be mutiplied by an integral."); | |
return b*time.b + b*time.n / time.d; | |
} | |
bool operator==(bnd const& a, bnd const& b) | |
{ | |
return (a.b == b.b && a.n*b.d == b.n*a.d); | |
} | |
std::ostream& operator<<(std::ostream& o, bnd const& time) | |
{ | |
o << time.b << "+" << time.n << "/" << time.d; | |
return o; | |
} | |
template <class Duration> | |
Duration bnd_to_time(bnd const& b, int bpm) | |
{ | |
using rep = typename Duration::rep; | |
using period = typename Duration::period; | |
return Duration((b * period::den) * 60 / period::num / bpm); | |
} | |
int main() | |
{ | |
bnd a{1, 8, 6}; | |
bnd b{1, 4, 3}; | |
cout << a << " == " << b << " -> " << (a == b) << endl; | |
cout << a << " < " << b << " -> " << (a < b) << endl; | |
cout << double(a) << endl; | |
cout << double(b) << endl; | |
cout << a*2 << endl; | |
cout << a*3 << endl; | |
cout << a*4 << endl; | |
cout << a*5 << endl; | |
cout << a*6 << endl; | |
cout << a*10000 << endl; | |
cout << double(a)*1.2 << endl; | |
cout << a << "beat at 72bpm = " | |
<< bnd_to_time<std::chrono::milliseconds>(a, 72).count() | |
<< "ms" << endl; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment