forked from kbinani/libvsq
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathMeasureLineIterator.hpp
More file actions
175 lines (162 loc) · 4.92 KB
/
MeasureLineIterator.hpp
File metadata and controls
175 lines (162 loc) · 4.92 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
/**
* MeasureLineIterator.hpp
* Copyright © 2012 kbinani
*
* This file is part of libvsq.
*
* libvsq is free software; you can redistribute it and/or
* modify it under the terms of the BSD License.
*
* libvsq is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
#ifndef __MeasureLineIterator_hpp__
#define __MeasureLineIterator_hpp__
#include "vsqglobal.hpp"
#include "TimesigList.hpp"
#include "MeasureLine.hpp"
VSQ_BEGIN_NAMESPACE
/**
* @brief 小節を区切る線の情報を順に返す反復子
*/
class MeasureLineIterator
{
private:
/**
* @brief 補助線の間隔として利用可能な最小時間(tick単位)
*/
const static tick_t MIN_ASSIST_LINE_STEP = 15;
const TimesigList *list;
tick_t endTick;
int i;
tick_t tick;
int currentDenominator;
int currentNumerator;
tick_t actualStepLength;
tick_t temporaryEndTick;
tick_t currentTick;
int barCount;
tick_t assistLineStep;
tick_t stepLength;
public:
class InvalidAssistLineStep : public std::exception{
};
public:
/**
* @brief 小節線の情報を取得する区間を指定し、初期化する
* @param list テンポ変更リスト
*/
explicit MeasureLineIterator( const TimesigList *list, tick_t assistLineStep = 0 ){
this->list = list;
endTick = 0;
i = 0;
temporaryEndTick = -1;
tick = 0;
if( assistLineStep < 0 || assistLineStep % MIN_ASSIST_LINE_STEP != 0 ){
throw InvalidAssistLineStep();
}
this->assistLineStep = assistLineStep;
this->reset( endTick );
}
/**
* @brief 次の小節線が取得可能かどうかを取得する
* @return 取得可能であれば true を返す
*/
bool hasNext(){
if( tick <= endTick ){
return true;
}else{
return false;
}
}
/**
* @brief 次の小節線を取得する
* @return 次の小節線の情報
*/
MeasureLine next(){
int mod = stepLength * currentNumerator;
if( tick < temporaryEndTick ){
if( (tick - currentTick) % mod == 0 ){
return returnBorder();
}else{
return returnOther();
}
}
if( i < list->size() ){
currentDenominator = list->get( i ).denominator;
currentNumerator = list->get( i ).numerator;
currentTick = list->get( i ).getClock();
int local_bar_count = list->get( i ).barCount;
int denom = currentDenominator;
if( denom <= 0 ){
denom = 4;
}
stepLength = 480 * 4 / denom;
if( 0 < assistLineStep && assistLineStep < stepLength ){
actualStepLength = assistLineStep;
}else{
actualStepLength = stepLength;
}
mod = stepLength * currentNumerator;
barCount = local_bar_count - 1;
temporaryEndTick = endTick;
if( i + 1 < list->size() ){
temporaryEndTick = list->get( i + 1 ).getClock();
}
i++;
tick = currentTick;
if( tick < temporaryEndTick ){
if( (tick - currentTick) % mod == 0 ){
return returnBorder();
}else{
return returnOther();
}
}
}else{
if( (tick - currentTick) % mod == 0 ){
return returnBorder();
}else{
return returnOther();
}
}
return MeasureLine( 0, 0, 4, 4, true, false );
}
/**
* @brief 反復子をリセットする
* @param endTick 反復を行う最大の時刻(tick単位)を指定する
* @todo startTick を指定できるようにする
*/
void reset( tick_t endTick ){
this->endTick = endTick;
this->i = 0;
this->temporaryEndTick = -1;
this->tick = 0;
this->currentDenominator = 0;
this->currentNumerator = 0;
this->actualStepLength = 0;
this->currentTick = 0;
this->barCount = 0;
this->stepLength = 0;
}
private:
/**
* @brief 小節の境界を表す MeasureLine のインスタンスを返す
*/
MeasureLine returnBorder(){
barCount++;
MeasureLine ret( tick, barCount, currentNumerator, currentDenominator, true, false );
tick += actualStepLength;
return ret;
}
/**
* @brief 小節の境界でない MeasureLine のインスタンスを返す
*/
MeasureLine returnOther(){
MeasureLine ret( tick, barCount, currentNumerator, currentDenominator, false, (tick - currentTick) % stepLength != 0 );
tick += actualStepLength;
return ret;
}
};
VSQ_END_NAMESPACE
#endif