Commit cae21b02 authored by Florent Jacquemard's avatar Florent Jacquemard
Browse files

new group tempo

new class Tempo : base class, constant tempo value
Gtest for class Tempo
parent 595b3ed5
......@@ -385,6 +385,8 @@
4332105824FC171600A3A053 /* Root.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4332105724FC171600A3A053 /* Root.cpp */; };
4332790F260E450C00D6AD17 /* KeyS.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4373B456225163CC00D49D6C /* KeyS.cpp */; };
433DA74925EEA62100144F63 /* RewriteMulti.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 433DA74725EEA62100144F63 /* RewriteMulti.cpp */; };
4341014626C17999000AA03E /* Tempo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4341014426C17999000AA03E /* Tempo.cpp */; };
4341014826C18D6F000AA03E /* TestTempo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4341014726C18D6F000AA03E /* TestTempo.cpp */; };
43448D5F25097627007ECBA5 /* ScoreBuilder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43467766247AB20F008A146B /* ScoreBuilder.cpp */; };
4345A544263410EE00297B18 /* RunTerm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 430046E42604CF3F000E9898 /* RunTerm.cpp */; };
4345A5502634111100297B18 /* RunInnero.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43631EC826186E7C004CC60F /* RunInnero.cpp */; };
......@@ -1229,6 +1231,9 @@
433D3ED01FE48B2E0082FA85 /* PtrSK.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = PtrSK.hpp; sourceTree = "<group>"; };
433DA74725EEA62100144F63 /* RewriteMulti.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = RewriteMulti.cpp; sourceTree = "<group>"; };
433DA74825EEA62100144F63 /* RewriteMulti.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = RewriteMulti.hpp; sourceTree = "<group>"; };
4341014426C17999000AA03E /* Tempo.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Tempo.cpp; sourceTree = "<group>"; };
4341014526C17999000AA03E /* Tempo.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Tempo.hpp; sourceTree = "<group>"; };
4341014726C18D6F000AA03E /* TestTempo.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = TestTempo.cpp; sourceTree = "<group>"; };
434221EA20248F59003F4656 /* Atable.tpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; path = Atable.tpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };
434221EB20248F59003F4656 /* Atable.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Atable.hpp; sourceTree = "<group>"; };
43467766247AB20F008A146B /* ScoreBuilder.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ScoreBuilder.cpp; sourceTree = "<group>"; };
......@@ -1772,6 +1777,7 @@
432B717920777C2B00C5BCAD /* segment */,
32C34D2B1EC1A0610031D1E1 /* weight */,
327AEFDB1DD8BFF4005354D8 /* schemata */,
4341014326C17916000AA03E /* tempo */,
436362091FDDAED7003C053F /* table */,
43516C7F207D1C0700028E34 /* parsers */,
43333F6A2211AE71003DD83D /* parsing */,
......@@ -2300,6 +2306,15 @@
path = spdlog;
sourceTree = "<group>";
};
4341014326C17916000AA03E /* tempo */ = {
isa = PBXGroup;
children = (
4341014526C17999000AA03E /* Tempo.hpp */,
4341014426C17999000AA03E /* Tempo.cpp */,
);
path = tempo;
sourceTree = "<group>";
};
43516C7F207D1C0700028E34 /* parsers */ = {
isa = PBXGroup;
children = (
......@@ -2631,6 +2646,7 @@
43D0E40A2301B20A001C12C1 /* TestRecordQueue.cpp */,
4357C18C2303F7F700D66E74 /* TestTableInstances.cpp */,
4357C18E2303FD7E00D66E74 /* TestTableParse.cpp */,
4341014726C18D6F000AA03E /* TestTempo.cpp */,
);
path = GTests;
sourceTree = "<group>";
......@@ -3436,6 +3452,7 @@
435B1D68256DA6B600927C77 /* SMPrinter.cpp in Sources */,
432D3F7C257CF35A009B2363 /* SMMEI.cpp in Sources */,
43AE7B1325C8101A00BE80C3 /* RewriteStaccato.cpp in Sources */,
4341014626C17999000AA03E /* Tempo.cpp in Sources */,
4313D8DE2613231800702519 /* RunCompare.cpp in Sources */,
43552EBE22A69BAF00C557BA /* Spiral.cpp in Sources */,
4396086E25DC4CE40058E46A /* PSshortest.cpp in Sources */,
......@@ -3811,6 +3828,7 @@
43250B1625D806A400116C3E /* TempoChange.cpp in Sources */,
43250B1725D806A400116C3E /* Spanning.cpp in Sources */,
43250B1825D806A400116C3E /* Line.cpp in Sources */,
4341014826C18D6F000AA03E /* TestTempo.cpp in Sources */,
43250B1925D806A400116C3E /* Slur.cpp in Sources */,
43250B1A25D806A400116C3E /* Volta.cpp in Sources */,
43250B1B25D806A400116C3E /* Octava.cpp in Sources */,
......
......@@ -163,9 +163,6 @@ void WCFG::print(std::ostream& o) const
}
void DepthMarking::mark_rec(state_t s, int d, const WCFG& wcfg)
{
assert (d >= 0);
......@@ -177,7 +174,7 @@ void DepthMarking::mark_rec(state_t s, int d, const WCFG& wcfg)
i++)
{
// enumerate the states in the body of the current transition
for (Body::const_iterator j = i->cbegin();
for (Production::Body::const_iterator j = i->cbegin();
j != i->cend();
j++)
{
......
......@@ -97,7 +97,7 @@ public:
/// @return whether the pair (kp, it) is registered in the instance table.
bool exists(const K& kp, std::shared_ptr<const R> it) const;
inline bool empty() { return _instances.empty(); }
inline bool empty() const { return _instances.empty(); }
/// nb of concrete keys registered in this table.
inline size_t size() { return _instances.size(); }
......
......@@ -203,7 +203,7 @@ private: // table access and construction
/// @param k key, must be complete.
/// @return a pointer to the record (in table)
/// where the runs have been added.
shared_ptr<R> addComplete(const K& k);
std::shared_ptr<R> addComplete(const K& k);
/// the record rec is filled with all runs with target k
......@@ -212,7 +212,7 @@ private: // table access and construction
/// @param rec record to fill with runs targeting k.
/// it must be nun-NULL, and of key k.
/// @return the number of runs added to the table
size_t addComplete(const K& k, shared_ptr<R> rec);
size_t addComplete(const K& k, std::shared_ptr<R> rec);
/// the table of instances is updated with all runs
/// for all the complete instances of k.
......@@ -233,7 +233,7 @@ private: // table access and construction
/// otherwise rec is NULL.
/// @warning must be called by addComplete or addPartial.
/// @return the number of runs added to the table
size_t add(const K& k, shared_ptr<R> rec);
size_t add(const K& k, std::shared_ptr<R> rec);
/// add possible instances of run r
......@@ -248,8 +248,8 @@ private: // table access and construction
/// @param r run can be complete or partial. must be non-NULL.
/// @return the number of runs added to the table
size_t add(const K& k,
shared_ptr<R> rec,
shared_ptr<RunInner<K>> r);
std::shared_ptr<R> rec,
std::shared_ptr<RunInner<K>> r);
/// particular case of add(k, rec, r)
......@@ -260,14 +260,14 @@ private: // table access and construction
/// @param r run must be partial and inner. must be non-NULL.
/// @return the number of runs added to the table.
size_t addUpdate(const K& k,
shared_ptr<R> rec,
shared_ptr<RunInner<K>> r);
std::shared_ptr<R> rec,
std::shared_ptr<RunInner<K>> r);
/// dispatching to addUpdatePartial or addUpdateComplete.
size_t addUpdateNext(const K& k,
shared_ptr<R> rec,
shared_ptr<RunInner<K>> r,
std::shared_ptr<R> rec,
std::shared_ptr<RunInner<K>> r,
const K& next);
......@@ -281,8 +281,8 @@ private: // table access and construction
/// must be partial.
/// @return the number of runs added to the table
size_t addUpdatePartial(const K& k,
shared_ptr<R> rec,
shared_ptr<RunInner<K>> r,
std::shared_ptr<R> rec,
std::shared_ptr<RunInner<K>> r,
const K& next);
......@@ -296,8 +296,8 @@ private: // table access and construction
/// must be complete.
/// @return the number of runs added to the table
size_t addUpdateComplete(const K& k,
shared_ptr<R> rec,
shared_ptr<RunInner<K>> r,
std::shared_ptr<R> rec,
std::shared_ptr<RunInner<K>> r,
const K& next);
......@@ -310,9 +310,9 @@ private: // table access and construction
/// @param nextarg record, next argument for r. must not be NULL.
/// @return the number of runs added to the table
size_t addUpdateFinal(const K& k,
shared_ptr<R> rec,
shared_ptr<RunInner<K>> r,
shared_ptr<R> nextarg);
std::shared_ptr<R> rec,
std::shared_ptr<RunInner<K>> r,
std::shared_ptr<R> nextarg);
/// particular case of add(k, rec, r)
......@@ -323,7 +323,7 @@ private: // table access and construction
/// @param r run must be complete and inner. must be non-NULL.
/// @return the number of runs added to the table
size_t addInstanciate(const K& k,
shared_ptr<RunInner<K>> r);
std::shared_ptr<RunInner<K>> r);
/// particular case of add(k, rec).
......@@ -341,7 +341,7 @@ private: // table access and construction
/// @param tr nullary transition of base SWATA.
/// @return the number of runs added to the table
size_t addLeafComplete(const K& k,
shared_ptr<R> rec,
std::shared_ptr<R> rec,
const Transition& tr);
......@@ -372,8 +372,8 @@ private: // table access and construction
/// @param r run must be complete. must be non-NULL.
/// @return the number of runs added to the table
size_t addTable(const K& k,
shared_ptr<R> rec,
shared_ptr<Run> r);
std::shared_ptr<R> rec,
std::shared_ptr<Run> r);
// the record pointed by i (second param) is updated
......
......@@ -188,7 +188,7 @@ std::shared_ptr<R> TableParse<K,R,H>::addComplete(const K& k)
// kc must be complete.
// rec must point to the record associated to kc.
template <class K, class R, class H>
size_t TableParse<K,R,H>::addComplete(const K& kc, shared_ptr<R> rec)
size_t TableParse<K,R,H>::addComplete(const K& kc, std::shared_ptr<R> rec)
{
assert(kc.complete());
assert(rec);
......@@ -224,7 +224,7 @@ size_t TableParse<K,R,H>::addPartial(const K& kp)
// if k complete then rec must point ot the associated record in table.
template <class K, class R, class H>
size_t TableParse<K,R,H>::add(const K& k,
shared_ptr<R> rec)
std::shared_ptr<R> rec)
{
// TRACE("TableParse: add entry {} ({})", k, ((k.partial())?"partial":"complete"));
assert(k.partial() || k.complete());
......@@ -256,7 +256,7 @@ size_t TableParse<K,R,H>::add(const K& k,
const K& kc = p.target();
assert(kc.complete());
assert(kc.instance(k)); // k == kc if k complete
std:shared_ptr<RunTerm> rc = p.run();
std::shared_ptr<RunTerm> rc = p.run();
assert(rc != nullptr);
assert(rc->complete());
if (k.partial())
......
......@@ -37,6 +37,7 @@ template<class K, class R, class H> using MapIterator =
/// main table for parsing.
/// it is a mapping of keys into records
///
/// Parameters:
/// - K = concrete key class (index rows in the table)
......
......@@ -65,14 +65,14 @@ std::shared_ptr<R> TableRecords<K,R,H>::find(const K& k)
if (newrec) // record rec is new and empty and has no key
{
TRACE("TableParse[{}].addComplete: new record in table for key {}", k);
TRACE("TableRecords[{}].addComplete: new record in table for key {}", k);
/// @todo move next 2 lines to TableParse
// size_t ret = addComplete(k, rec);
//TRACE("TableParse[{}].addComplete: {} runs added", k, ret);
}
else // k and record already done, skip
{
TRACE("TableParse[{}].addComplete: complete key already in table,\
TRACE("TableRecords[{}].addComplete: complete key already in table,\
skip", k);
}
return rec;
......@@ -115,7 +115,7 @@ void TableRecords<K,R,H>::initRecord(const K& k, std::shared_ptr<R> rec)
assert(rec);
assert(rec->key().complete());
// rec->setKey(k);
TRACE("TableParse: new record in table for key {}", k);
TRACE("TableRecords: new record in table for key {}", k);
_nb_rows++;
}
......@@ -142,7 +142,7 @@ TableRecords<K,R,H>::addemplace(const K& k, bool& newrec)
// init with components of the entry in table
if (newrec)
{
TRACE("TableParse: new record in table for key {}", k);
TRACE("TableRecords: new record in table for key {}", k);
_nb_rows++;
}
......
......@@ -39,9 +39,7 @@ public:
MeterSig(const MeterSig& ts);
/**
* Destructor
*/
/// Destructor
~MeterSig() {};
MeterSig& operator=(const MeterSig& rhs);
......@@ -60,7 +58,7 @@ public:
/// @todo move to Event ?
Rational MTUtoWhole(mtu_t d) const;
/// cast duration wrt this time signature,
/// cast given duration wrt this time signature,
/// from MTU (number of bars) into the exponent of 2 of CMN note value:
/// - -2 quadruple whole note (longa)
/// - -1 double whole note (breve)
......@@ -69,7 +67,7 @@ public:
/// - 2 quarter note.
/// - 3 8th note.
/// - ...
/// @param d duration in mtu, must not be 0.
/// @param d duration to cast, in mtu, must not be 0.
cmnd_t MTUtoCMN(mtu_t d) const;
/// measure where the beat divided by 3.
......
......@@ -89,6 +89,9 @@
#include "TropicalWeight.hpp"
#include "ViterbiWeight.hpp"
// tempo and tempo inference
#include "Tempo.hpp"
// automata
#include "Label.hpp"
#include "SymbLabel.hpp"
......
//
// Tempo.cpp
// squant2
//
// Created by Florent Jacquemard on 09/08/2021.
// Copyright © 2021 Florent Jacquemard. All rights reserved.
//
#include "Tempo.hpp"
namespace tempo {
Tempo::Tempo(rtu_t spb):
_val(spb)
{
assert(spb > 0);
}
Tempo::Tempo(int bpm, const ScoreModel::MeterSig& ts)
{
assert(bpm > 0);
assert(bpm < 1024);
rtu_t bps = (rtu_t) bpm;
// beat per second
bps /= 60;
// bar per second
bps /= ts.beats();
// second per bar
assert(bps > 0);
_val = 1/bps;
}
Tempo::Tempo(const Tempo& t):
_val(t._val)
{ }
Tempo::~Tempo()
{ }
Tempo& Tempo::operator=(const Tempo& rhs)
{
if(this != &rhs)
{
_val = rhs._val;
};
return *this;
}
bool Tempo::operator==(const Tempo& rhs) const
{
return (this->_val == rhs._val);
}
rtu_t Tempo::spb() const
{
assert(_val > 0);
return _val;
}
mtu_t Tempo::bps() const
{
// beats per second
rtu_t rbps = 1/_val;
return toRational(rbps);
}
int Tempo::bpm(int bpb) const
{
assert(bpb > 1);
assert(_val > 0);
// bar per second
rtu_t bps = 1/_val;
// beat per second
bps *= bpb;
// beat per minute
return (int) (bps * 60);
}
int Tempo::bpm(const ScoreModel::MeterSig& ts) const
{
return bpm(ts.beats());
}
int Tempo::barpm() const
{
assert(_val > 0);
// bar per second
rtu_t bps = 1/_val;
// bar per minute
return (int) (bps * 60);
}
void Tempo::print(std::ostream& o) const
{
assert(_val > 0);
o << _val << " s/bar";
o << "(" << barpm() << " bar/m)";
}
std::ostream& operator<<(std::ostream& o, const Tempo& t)
{
t.print(o);
return o;
}
} // end namespace tempo
//
// Tempo.hpp
// squant2
//
// Created by Florent Jacquemard on 09/08/2021.
// Copyright © 2021 Florent Jacquemard. All rights reserved.
//
/// @defgroup tempo Tempo module
///
/// @addtogroup tempo
/// @{
#ifndef Tempo_hpp
#define Tempo_hpp
#include <stdio.h>
#include <assert.h>
#include <math.h>
#include <iostream>
#include "RTU.hpp"
#include "MTU.hpp"
#include "MeterSig.hpp"
namespace tempo {
/// @brief base class for tempo inference
/// one fixed tempo value and convertions
class Tempo
{
public:
/// constant tempo value given inn second per bar
/// @param spb number of second per bar
Tempo(rtu_t spb);
/// constant tempo value given in bpm
/// @param bpm number of beats per minute
Tempo(int bpm, const ScoreModel::MeterSig& ts);
/// copy
Tempo(const Tempo& t);
~Tempo();
Tempo& operator=(const Tempo& rhs);
bool operator==(const Tempo& rhs) const;
/// number of second per bar
rtu_t spb() const;
/// number of bar per second
mtu_t bps() const;
/// rounded number of beats per minute
/// @param bpb number of beat per bar
int bpm(int bpb) const;
/// rounded number of beats per minute
/// @param ts a time signature
int bpm(const ScoreModel::MeterSig& ts) const;
void print(std::ostream& o) const;
protected:
rtu_t _val;
private:
/// reounded bar per minute
int barpm() const;
};
std::ostream& operator<<(std::ostream&, const Tempo&);
} // end namespace tempo
#endif /* Tempo_hpp */
/// @}
......@@ -24,7 +24,7 @@ TEST(TestRuney, TestTerminal)
const label_t a = SymbLabel::make_note();
const Weight w1 = TropicalWeight::make_one();
Transition t1 = Transition(a, w1);
parsing::Run<KeyS> r0 = parsing::Run<KeyS>(t1, a, w1);
parsing::RunTerm r0 = parsing::RunTerm(t1, a, w1, 1);
EXPECT_FALSE(r0.inner());
EXPECT_TRUE(r0.terminal());
EXPECT_EQ(r0.label(), a);
......@@ -45,7 +45,8 @@ TEST(TestRuney, TestBinary)
const label_t a = SymbLabel::make_note();
Weight w1 = TropicalWeight::make_one().make(0.25);
Transition t1 = Transition(a, w1);
const parsing::Run<KeyS>* r0 = new parsing::Run<KeyS>(t1, a, w1);
const parsing::RunInner<KeyS> r0 =
parsing::RunInner<KeyS>(t1, a, w1);
// binary symbol
const label_t b = SymbLabel::make_tuple(2);
......@@ -53,7 +54,9 @@ TEST(TestRuney, TestBinary)
Weight w2 = w1.make(8);
Transition t2 = Transition(b, w2);
const parsing::Run<KeyS> r2 = parsing::Run<KeyS>(t2, b, w2);
const parsing::RunInner<KeyS> r2 =
parsing::RunInner<KeyS>(t2, b, w2);
EXPECT_TRUE(r2.inner());
EXPECT_FALSE(r2.terminal());
EXPECT_EQ(r2.label(), b);
......@@ -79,7 +82,7 @@ TEST(TestRuney, TestBinary)
state_t q2 = 2;
KeyS* k2 = new KeyS(q2, env);
RecordOne<KeyS>* rec2 = new RecordOne<KeyS>(weightMax<KeyS>);
const parsing::Run<KeyS>* r00 = new parsing::Run<KeyS>(*r0); // copy
const parsing::Run<KeyS>* r00 = new parsing::RunInner<KeyS>(r0); // copy
rec2->initKey(k2);
rec2->add(r00);
// copy/update
......
......@@ -24,7 +24,7 @@ TEST(TestTableParse, TestEmpty)
ParsingEnv* env = new ParsingEnv(); // empty, not used here
TableParse<KeyS, RecordOne<KeyS>, KeySHasher>* tab0 =
new TableParse<KeyS, RecordOne<KeyS>, KeySHasher>(env, weightMax<KeyS>);
new TableParse<KeyS, RecordOne<KeyS>, KeySHasher>(*env);
EXPECT_TRUE(tab0->empty());
delete tab0;
......
//
// TestTempo.cpp
// GTests
//
// Created by Florent Jacquemard on 09/08/2021.
// Copyright © 2021 Florent Jacquemard. All rights reserved.
//
#include <stdio.h>
#include "gtest/gtest.h"
#include "Tempo.hpp"
using namespace tempo;
TEST(TestTempo, TestT44)
{
Tempo t1 = Tempo(4); // 4 seconds per bar
ScoreModel::MeterSig ts = ScoreModel::MeterSig(4,4);
EXPECT_EQ(t1.spb(), 4.0);
EXPECT_EQ(t1.bps().numerator(), 1);
EXPECT_EQ(t1.bps().denominator(), 4);
EXPECT_EQ(t1.bpm(4), 60);
EXPECT_EQ(t1.bpm(ts), 60);
Tempo t2 = Tempo(60, ts);
EXPECT_TRUE(t1 == t2);
}
......@@ -133,7 +133,7 @@ TEST(TestWeight, TestViterbiWeight)
// zero