1 /***************************************************************************
2 * Copyright 1991, 1992, 1993, 1994, 1995, 1996, 2001, 2002 *
3 * David R. Hill, Leonard Manzara, Craig Schock *
4 * *
5 * This program is free software: you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation, either version 3 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
17 ***************************************************************************/
18 // 2014-09
19 // This file was copied from Gnuspeech and modified by Marcelo Y. Matuda.
20
21 #include "EventList.h"
22
23 #include <cstring>
24 #include <iomanip>
25 #include <sstream>
26 #include <vector>
27
28 #include "Log.h"
29
30 #define DIPHONE 2
31 #define TRIPHONE 3
32 #define TETRAPHONE 4
33
34 #define INTONATION_CONFIG_FILE_NAME "/intonation"
35
36
37
38 namespace GS {
39 namespace TRMControlModel {
40
Event()41 Event::Event() : time(0), flag(0)
42 {
43 for (int i = 0; i < EVENTS_SIZE; ++i) {
44 events[i] = GS_EVENTLIST_INVALID_EVENT_VALUE;
45 }
46 }
47
EventList(const char * configDirPath,Model & model)48 EventList::EventList(const char* configDirPath, Model& model)
49 : model_(model)
50 , macroFlag_(0)
51 , microFlag_(0)
52 , driftFlag_(0)
53 , smoothIntonation_(1)
54 , globalTempo_(1.0)
55 , tgParameters_(5)
56 , useFixedIntonationParameters_(false)
57 , randSrc_(randDev_())
58 {
59 setUp();
60
61 list_.reserve(128);
62
63 initToneGroups(configDirPath);
64
65 for (int i = 0; i < 10; ++i) {
66 fixedIntonationParameters_[i] = 0.0;
67 }
68 for (int i = 0; i < TRM::Tube::TOTAL_REGIONS; ++i) {
69 radiusCoef[i] = 1.0;
70 }
71 }
72
~EventList()73 EventList::~EventList()
74 {
75 }
76
77 void
setUp()78 EventList::setUp()
79 {
80 list_.clear();
81
82 zeroRef_ = 0;
83 zeroIndex_ = 0;
84 duration_ = 0;
85 timeQuantization_ = 4;
86
87 multiplier_ = 1.0;
88 intonParms_ = nullptr;
89
90 postureData_.clear();
91 postureData_.push_back(PostureData());
92 postureTempo_.clear();
93 postureTempo_.push_back(1.0);
94 currentPosture_ = 0;
95
96 feet_.clear();
97 feet_.push_back(Foot());
98 currentFoot_ = 0;
99
100 toneGroups_.clear();
101 toneGroups_.push_back(ToneGroup());
102 currentToneGroup_ = 0;
103
104 ruleData_.clear();
105 ruleData_.push_back(RuleData());
106 currentRule_ = 0;
107 }
108
109 void
setUpDriftGenerator(double deviation,double sampleRate,double lowpassCutoff)110 EventList::setUpDriftGenerator(double deviation, double sampleRate, double lowpassCutoff)
111 {
112 driftGenerator_.setUp(deviation, sampleRate, lowpassCutoff);
113 }
114
115 const Posture*
getPostureAtIndex(unsigned int index) const116 EventList::getPostureAtIndex(unsigned int index) const
117 {
118 if (index > currentPosture_) {
119 return nullptr;
120 } else {
121 return postureData_[index].posture;
122 }
123 }
124
125 const PostureData*
getPostureDataAtIndex(unsigned int index) const126 EventList::getPostureDataAtIndex(unsigned int index) const
127 {
128 if (index > currentPosture_) {
129 return nullptr;
130 } else {
131 return &postureData_[index];
132 }
133 }
134
135 const RuleData*
getRuleAtIndex(unsigned int index) const136 EventList::getRuleAtIndex(unsigned int index) const
137 {
138 if (static_cast<int>(index) > currentRule_) {
139 return nullptr;
140 } else {
141 return &ruleData_[index];
142 }
143 }
144
145 void
setFixedIntonationParameters(float notionalPitch,float pretonicRange,float pretonicLift,float tonicRange,float tonicMovement)146 EventList::setFixedIntonationParameters(float notionalPitch, float pretonicRange, float pretonicLift, float tonicRange, float tonicMovement)
147 {
148 fixedIntonationParameters_[1] = notionalPitch;
149 fixedIntonationParameters_[2] = pretonicRange;
150 fixedIntonationParameters_[3] = pretonicLift;
151 fixedIntonationParameters_[5] = tonicRange;
152 fixedIntonationParameters_[6] = tonicMovement;
153 }
154
155 void
setRadiusCoef(const double * values)156 EventList::setRadiusCoef(const double* values)
157 {
158 for (int i = 0; i < TRM::Tube::TOTAL_REGIONS; ++i) {
159 radiusCoef[i] = values[i];
160 }
161 }
162
163 void
parseGroups(int index,int number,FILE * fp)164 EventList::parseGroups(int index, int number, FILE* fp)
165 {
166 char line[256];
167 tgParameters_[index].resize(10 * number);
168 for (int i = 0; i < number; ++i) {
169 fgets(line, 256, fp);
170 float* temp = &tgParameters_[index][i * 10];
171 sscanf(line, " %f %f %f %f %f %f %f %f %f %f",
172 &temp[0], &temp[1], &temp[2], &temp[3], &temp[4],
173 &temp[5], &temp[6], &temp[7], &temp[8], &temp[9]);
174 }
175 }
176
177 void
initToneGroups(const char * configDirPath)178 EventList::initToneGroups(const char* configDirPath)
179 {
180 FILE* fp;
181 char line[256];
182 int count = 0;
183
184 std::ostringstream path;
185 path << configDirPath << INTONATION_CONFIG_FILE_NAME;
186 fp = fopen(path.str().c_str(), "rb");
187 if (fp == NULL) {
188 THROW_EXCEPTION(IOException, "Could not open the file " << path.str().c_str() << '.');
189 }
190 while (fgets(line, 256, fp) != NULL) {
191 if ((line[0] == '#') || (line[0] == ' ')) {
192 // Skip.
193 } else if (strncmp(line, "TG", 2) == 0) {
194 sscanf(&line[2], " %d", &tgCount_[count]);
195 parseGroups(count, tgCount_[count], fp);
196 count++;
197 } else if (strncmp(line, "RANDOM", 6) == 0) {
198 sscanf(&line[6], " %f", &intonationRandom_);
199 }
200 }
201 fclose(fp);
202
203 if (Log::debugEnabled) {
204 printToneGroups();
205 }
206 }
207
208 void
printToneGroups()209 EventList::printToneGroups()
210 {
211 printf("===== Intonation configuration:\n");
212 printf("Intonation random = %f\n", intonationRandom_);
213 printf("Tone groups: %d %d %d %d %d\n", tgCount_[0], tgCount_[1], tgCount_[2], tgCount_[3], tgCount_[4]);
214
215 for (int i = 0; i < 5; i++) {
216 float* temp = &tgParameters_[i][0];
217 printf("Temp [%d] = %p\n", i, temp);
218 int j = 0;
219 for (int k = 0; k < tgCount_[i]; k++) {
220 printf("%f %f %f %f %f %f %f %f %f %f\n",
221 temp[j] , temp[j+1], temp[j+2], temp[j+3], temp[j+4],
222 temp[j+5], temp[j+6], temp[j+7], temp[j+8], temp[j+9]);
223 j += 10;
224 }
225 }
226 }
227
228 double
getBeatAtIndex(int ruleIndex) const229 EventList::getBeatAtIndex(int ruleIndex) const
230 {
231 if (ruleIndex > currentRule_) {
232 return 0.0;
233 } else {
234 return ruleData_[ruleIndex].beat;
235 }
236 }
237
238 void
newPostureWithObject(const Posture & p)239 EventList::newPostureWithObject(const Posture& p)
240 {
241 if (postureData_[currentPosture_].posture) {
242 postureData_.push_back(PostureData());
243 postureTempo_.push_back(1.0);
244 currentPosture_++;
245 }
246 postureTempo_[currentPosture_] = 1.0;
247 postureData_[currentPosture_].ruleTempo = 1.0;
248 postureData_[currentPosture_].posture = &p;
249 }
250
251 void
replaceCurrentPostureWith(const Posture & p)252 EventList::replaceCurrentPostureWith(const Posture& p)
253 {
254 if (postureData_[currentPosture_].posture) {
255 postureData_[currentPosture_].posture = &p;
256 } else {
257 postureData_[currentPosture_ - 1].posture = &p;
258 }
259 }
260
261 void
setCurrentToneGroupType(int type)262 EventList::setCurrentToneGroupType(int type)
263 {
264 toneGroups_[currentToneGroup_].type = type;
265 }
266
267 void
newFoot()268 EventList::newFoot()
269 {
270 if (currentPosture_ == 0) {
271 return;
272 }
273
274 feet_[currentFoot_++].end = currentPosture_;
275 newPosture();
276
277 feet_.push_back(Foot());
278 feet_[currentFoot_].start = currentPosture_;
279 feet_[currentFoot_].end = -1;
280 feet_[currentFoot_].tempo = 1.0;
281 }
282
283 void
setCurrentFootMarked()284 EventList::setCurrentFootMarked()
285 {
286 feet_[currentFoot_].marked = 1;
287 }
288
289 void
setCurrentFootLast()290 EventList::setCurrentFootLast()
291 {
292 feet_[currentFoot_].last = 1;
293 }
294
295 void
setCurrentFootTempo(double tempo)296 EventList::setCurrentFootTempo(double tempo)
297 {
298 feet_[currentFoot_].tempo = tempo;
299 }
300
301 void
setCurrentPostureTempo(double tempo)302 EventList::setCurrentPostureTempo(double tempo)
303 {
304 postureTempo_[currentPosture_] = tempo;
305 }
306
307 void
setCurrentPostureRuleTempo(float tempo)308 EventList::setCurrentPostureRuleTempo(float tempo)
309 {
310 postureData_[currentPosture_].ruleTempo = tempo;
311 }
312
313 void
newToneGroup()314 EventList::newToneGroup()
315 {
316 if (currentFoot_ == 0) {
317 return;
318 }
319
320 toneGroups_[currentToneGroup_++].endFoot = currentFoot_;
321 newFoot();
322
323 toneGroups_.push_back(ToneGroup());
324 toneGroups_[currentToneGroup_].startFoot = currentFoot_;
325 toneGroups_[currentToneGroup_].endFoot = -1;
326 }
327
328 void
newPosture()329 EventList::newPosture()
330 {
331 if (postureData_[currentPosture_].posture) {
332 postureData_.push_back(PostureData());
333 postureTempo_.push_back(1.0);
334 currentPosture_++;
335 }
336 postureTempo_[currentPosture_] = 1.0;
337 }
338
339 void
setCurrentPostureSyllable()340 EventList::setCurrentPostureSyllable()
341 {
342 postureData_[currentPosture_].syllable = 1;
343 }
344
345 Event*
insertEvent(int number,double time,double value)346 EventList::insertEvent(int number, double time, double value)
347 {
348 time = time * multiplier_;
349 if (time < 0.0) {
350 return nullptr;
351 }
352 if (time > (double) (duration_ + timeQuantization_)) {
353 return nullptr;
354 }
355
356 int tempTime = zeroRef_ + (int) time;
357 tempTime = (tempTime >> 2) << 2;
358 //if ((tempTime % timeQuantization) != 0) {
359 // tempTime++;
360 //}
361
362 if (list_.empty()) {
363 std::unique_ptr<Event> tempEvent(new Event());
364 tempEvent->time = tempTime;
365 if (number >= 0) {
366 tempEvent->setValue(value, number);
367 }
368 list_.push_back(std::move(tempEvent));
369 return list_.back().get();
370 }
371
372 int i;
373 for (i = list_.size() - 1; i >= zeroIndex_; i--) {
374 if (list_[i]->time == tempTime) {
375 if (number >= 0) {
376 list_[i]->setValue(value, number);
377 }
378 return list_[i].get();
379 }
380 if (list_[i]->time < tempTime) {
381 std::unique_ptr<Event> tempEvent(new Event());
382 tempEvent->time = tempTime;
383 if (number >= 0) {
384 tempEvent->setValue(value, number);
385 }
386 list_.insert(list_.begin() + (i + 1), std::move(tempEvent));
387 return list_[i + 1].get();
388 }
389 }
390
391 std::unique_ptr<Event> tempEvent(new Event());
392 tempEvent->time = tempTime;
393 if (number >= 0) {
394 tempEvent->setValue(value, number);
395 }
396 list_.insert(list_.begin() + (i + 1), std::move(tempEvent));
397 return list_[i + 1].get();
398 }
399
400 void
setZeroRef(int newValue)401 EventList::setZeroRef(int newValue)
402 {
403 zeroRef_ = newValue;
404 zeroIndex_ = 0;
405
406 if (list_.empty()) {
407 return;
408 }
409
410 for (int i = list_.size() - 1; i >= 0; i--) {
411 if (list_[i]->time < newValue) {
412 zeroIndex_ = i;
413 return;
414 }
415 }
416 }
417
418 double
createSlopeRatioEvents(const Transition::SlopeRatio & slopeRatio,double baseline,double parameterDelta,double min,double max,int eventIndex)419 EventList::createSlopeRatioEvents(
420 const Transition::SlopeRatio& slopeRatio,
421 double baseline, double parameterDelta, double min, double max, int eventIndex)
422 {
423 double temp = 0.0, temp1 = 0.0, intervalTime = 0.0, sum = 0.0, factor = 0.0;
424 double baseTime = 0.0, endTime = 0.0, totalTime = 0.0, delta = 0.0;
425 double startValue;
426 double pointTime, pointValue;
427
428 Transition::getPointData(*slopeRatio.pointList.front(), model_, pointTime, pointValue);
429 baseTime = pointTime;
430 startValue = pointValue;
431
432 Transition::getPointData(*slopeRatio.pointList.back(), model_, pointTime, pointValue);
433 endTime = pointTime;
434 delta = pointValue - startValue;
435
436 temp = slopeRatio.totalSlopeUnits();
437 totalTime = endTime - baseTime;
438
439 int numSlopes = slopeRatio.slopeList.size();
440 std::vector<double> newPointValues(numSlopes - 1);
441 for (int i = 1; i < numSlopes + 1; i++) {
442 temp1 = slopeRatio.slopeList[i - 1]->slope / temp; /* Calculate normal slope */
443
444 /* Calculate time interval */
445 intervalTime = Transition::getPointTime(*slopeRatio.pointList[i], model_)
446 - Transition::getPointTime(*slopeRatio.pointList[i - 1], model_);
447
448 /* Apply interval percentage to slope */
449 temp1 = temp1 * (intervalTime / totalTime);
450
451 /* Multiply by delta and add to last point */
452 temp1 = temp1 * delta;
453 sum += temp1;
454
455 if (i < numSlopes) {
456 newPointValues[i - 1] = temp1;
457 }
458 }
459 factor = delta / sum;
460 temp = startValue;
461
462 double value = 0.0;
463 for (unsigned int i = 0, size = slopeRatio.pointList.size(); i < size; i++) {
464 const Transition::Point& point = *slopeRatio.pointList[i];
465
466 if (i >= 1 && i < slopeRatio.pointList.size() - 1) {
467 pointTime = Transition::getPointTime(point, model_);
468
469 pointValue = newPointValues[i - 1];
470 pointValue *= factor;
471 pointValue += temp;
472 temp = pointValue;
473 } else {
474 Transition::getPointData(point, model_, pointTime, pointValue);
475 }
476
477 value = baseline + ((pointValue / 100.0) * parameterDelta);
478 if (value < min) {
479 value = min;
480 } else if (value > max) {
481 value = max;
482 }
483 if (!point.isPhantom) {
484 insertEvent(eventIndex, pointTime, value);
485 }
486 }
487
488 return value;
489 }
490
491 // It is assumed that postureList.size() >= 2.
492 void
applyRule(const Rule & rule,const std::vector<const Posture * > & postureList,const double * tempos,int postureIndex)493 EventList::applyRule(const Rule& rule, const std::vector<const Posture*>& postureList, const double* tempos, int postureIndex)
494 {
495 int cont;
496 int currentType;
497 double currentValueDelta, value, lastValue;
498 double ruleSymbols[5] = {0.0, 0.0, 0.0, 0.0, 0.0};
499 double tempTime;
500 double targets[4];
501 Event* tempEvent = nullptr;
502
503 rule.evaluateExpressionSymbols(tempos, postureList, model_, ruleSymbols);
504
505 multiplier_ = 1.0 / (double) (postureData_[postureIndex].ruleTempo);
506
507 int type = rule.numberOfExpressions();
508 setDuration((int) (ruleSymbols[0] * multiplier_));
509
510 ruleData_[currentRule_].firstPosture = postureIndex;
511 ruleData_[currentRule_].lastPosture = postureIndex + (type - 1);
512 ruleData_[currentRule_].beat = (ruleSymbols[1] * multiplier_) + (double) zeroRef_;
513 ruleData_[currentRule_++].duration = ruleSymbols[0] * multiplier_;
514 ruleData_.push_back(RuleData());
515
516 switch (type) {
517 /* Note: Case 4 should execute all of the below, case 3 the last two */
518 case 4:
519 if (postureList.size() == 4) {
520 postureData_[postureIndex + 3].onset = (double) zeroRef_ + ruleSymbols[1];
521 tempEvent = insertEvent(-1, ruleSymbols[3], 0.0);
522 if (tempEvent) tempEvent->flag = 1;
523 }
524 case 3:
525 if (postureList.size() >= 3) {
526 postureData_[postureIndex + 2].onset = (double) zeroRef_ + ruleSymbols[1];
527 tempEvent = insertEvent(-1, ruleSymbols[2], 0.0);
528 if (tempEvent) tempEvent->flag = 1;
529 }
530 case 2:
531 postureData_[postureIndex + 1].onset = (double) zeroRef_ + ruleSymbols[1];
532 tempEvent = insertEvent(-1, 0.0, 0.0);
533 if (tempEvent) tempEvent->flag = 1;
534 break;
535 }
536
537 //tempTargets = (List *) [rule parameterList];
538
539 /* Loop through the parameters */
540 for (unsigned int i = 0, size = model_.parameterList().size(); i < size; ++i) {
541 /* Get actual parameter target values */
542 targets[0] = postureList[0]->getParameterTarget(i);
543 targets[1] = postureList[1]->getParameterTarget(i);
544 targets[2] = (postureList.size() >= 3) ? postureList[2]->getParameterTarget(i) : 0.0;
545 targets[3] = (postureList.size() == 4) ? postureList[3]->getParameterTarget(i) : 0.0;
546
547 /* Optimization, Don't calculate if no changes occur */
548 cont = 1;
549 switch (type) {
550 case DIPHONE:
551 if (targets[0] == targets[1]) {
552 cont = 0;
553 }
554 break;
555 case TRIPHONE:
556 if ((targets[0] == targets[1]) && (targets[0] == targets[2])) {
557 cont = 0;
558 }
559 break;
560 case TETRAPHONE:
561 if ((targets[0] == targets[1]) && (targets[0] == targets[2]) && (targets[0] == targets[3])) {
562 cont = 0;
563 }
564 break;
565 }
566
567 insertEvent(i, 0.0, targets[0]);
568
569 if (cont) {
570 currentType = DIPHONE;
571 currentValueDelta = targets[1] - targets[0];
572 lastValue = targets[0];
573 //lastValue = 0.0;
574
575 const std::shared_ptr<Transition> transition = rule.getParamProfileTransition(i);
576 if (!transition) {
577 THROW_EXCEPTION(UnavailableResourceException, "Rule transition not found: " << i << '.');
578 }
579
580 /* Apply lists to parameter */
581 for (unsigned int j = 0; j < transition->pointOrSlopeList().size(); ++j) {
582 const Transition::PointOrSlope& pointOrSlope = *transition->pointOrSlopeList()[j];
583 if (pointOrSlope.isSlopeRatio()) {
584 const auto& slopeRatio = dynamic_cast<const Transition::SlopeRatio&>(pointOrSlope);
585
586 if (slopeRatio.pointList[0]->type != currentType) { //TODO: check pointList.size() > 0
587 currentType = slopeRatio.pointList[0]->type;
588 targets[currentType - 2] = lastValue;
589 currentValueDelta = targets[currentType - 1] - lastValue;
590 }
591 value = createSlopeRatioEvents(
592 slopeRatio, targets[currentType - 2], currentValueDelta,
593 min_[i], max_[i], i);
594 } else {
595 const auto& point = dynamic_cast<const Transition::Point&>(pointOrSlope);
596
597 if (point.type != currentType) {
598 currentType = point.type;
599 targets[currentType - 2] = lastValue;
600 currentValueDelta = targets[currentType - 1] - lastValue;
601 }
602 double pointTime;
603 Transition::getPointData(point, model_,
604 targets[currentType - 2], currentValueDelta, min_[i], max_[i],
605 pointTime, value);
606 if (!point.isPhantom) {
607 insertEvent(i, pointTime, value);
608 }
609 }
610 lastValue = value;
611 }
612 }
613 //else {
614 // insertEvent(i, 0.0, targets[0]);
615 //}
616 }
617
618 /* Special Event Profiles */
619 for (unsigned int i = 0, size = model_.parameterList().size(); i < size; ++i) {
620 const std::shared_ptr<Transition> specialTransition = rule.getSpecialProfileTransition(i);
621 if (specialTransition) {
622 for (unsigned int j = 0; j < specialTransition->pointOrSlopeList().size(); ++j) {
623 const Transition::PointOrSlope& pointOrSlope = *specialTransition->pointOrSlopeList()[j];
624 const auto& point = dynamic_cast<const Transition::Point&>(pointOrSlope);
625
626 /* calculate time of event */
627 tempTime = Transition::getPointTime(point, model_);
628
629 /* Calculate value of event */
630 value = ((point.value / 100.0) * (max_[i] - min_[i]));
631 //maxValue = value;
632
633 /* insert event into event list */
634 insertEvent(i + 16U, tempTime, value);
635 }
636 }
637 }
638
639 setZeroRef((int) (ruleSymbols[0] * multiplier_) + zeroRef_);
640 tempEvent = insertEvent(-1, 0.0, 0.0);
641 if (tempEvent) tempEvent->flag = 1;
642 }
643
644 void
generateEventList()645 EventList::generateEventList()
646 {
647 for (unsigned int i = 0; i < 16; i++) { //TODO: replace hard-coded value
648 const Parameter& param = model_.getParameter(i);
649 min_[i] = (double) param.minimum();
650 max_[i] = (double) param.maximum();
651 }
652
653 /* Calculate Rhythm including regression */
654 for (int i = 0; i < currentFoot_; i++) {
655 int rus = feet_[i].end - feet_[i].start + 1;
656 /* Apply rhythm model */
657 double footTempo;
658 if (feet_[i].marked) {
659 double tempTempo = 117.7 - (19.36 * (double) rus);
660 feet_[i].tempo -= tempTempo / 180.0;
661 footTempo = globalTempo_ * feet_[i].tempo;
662 } else {
663 double tempTempo = 18.5 - (2.08 * (double) rus);
664 feet_[i].tempo -= tempTempo / 140.0;
665 footTempo = globalTempo_ * feet_[i].tempo;
666 }
667 for (int j = feet_[i].start; j < feet_[i].end + 1; j++) {
668 postureTempo_[j] *= footTempo;
669 if (postureTempo_[j] < 0.2) {
670 postureTempo_[j] = 0.2;
671 } else if (postureTempo_[j] > 2.0) {
672 postureTempo_[j] = 2.0;
673 }
674 }
675 }
676
677 unsigned int basePostureIndex = 0;
678 std::vector<const Posture*> tempPostureList;
679 while (basePostureIndex < currentPosture_) {
680 tempPostureList.clear();
681 for (unsigned int i = 0; i < 4; i++) {
682 unsigned int postureIndex = basePostureIndex + i;
683 if (postureIndex <= currentPosture_ && postureData_[postureIndex].posture) {
684 tempPostureList.push_back(postureData_[postureIndex].posture);
685 } else {
686 break;
687 }
688 }
689 if (tempPostureList.size() < 2) {
690 break;
691 }
692 unsigned int ruleIndex = 0;
693 const Rule* tempRule = model_.findFirstMatchingRule(tempPostureList, ruleIndex);
694 if (tempRule == nullptr) {
695 THROW_EXCEPTION(UnavailableResourceException, "Could not find a matching rule.");
696 }
697
698 ruleData_[currentRule_].number = ruleIndex + 1U;
699
700 applyRule(*tempRule, tempPostureList, &postureTempo_[basePostureIndex], basePostureIndex);
701
702 basePostureIndex += tempRule->numberOfExpressions() - 1;
703 }
704
705 //[dataPtr[numElements-1] setFlag:1];
706 }
707
708 void
setFullTimeScale()709 EventList::setFullTimeScale()
710 {
711 zeroRef_ = 0;
712 zeroIndex_ = 0;
713 duration_ = list_.back()->time + 100;
714 }
715
716 void
applyIntonation()717 EventList::applyIntonation()
718 {
719 int tgRandom;
720 int firstFoot, endFoot;
721 int ruleIndex = 0, postureIndex;
722 int i, j, k;
723 double startTime, endTime, pretonicDelta, offsetTime = 0.0;
724 double randomSemitone, randomSlope;
725
726 zeroRef_ = 0;
727 zeroIndex_ = 0;
728 duration_ = list_.back()->time + 100;
729
730 intonationPoints_.clear();
731
732 std::shared_ptr<const Category> vocoidCategory = model_.findCategory("vocoid");
733 if (!vocoidCategory) {
734 THROW_EXCEPTION(UnavailableResourceException, "Could not find the category \"vocoid\".");
735 }
736
737 std::uniform_int_distribution<> intRandDist0(0, tgCount_[0] > 0 ? tgCount_[0] - 1 : 0);
738 std::uniform_int_distribution<> intRandDist1(0, tgCount_[1] > 0 ? tgCount_[1] - 1 : 0);
739 std::uniform_int_distribution<> intRandDist2(0, tgCount_[2] > 0 ? tgCount_[2] - 1 : 0);
740 std::uniform_int_distribution<> intRandDist3(0, tgCount_[3] > 0 ? tgCount_[3] - 1 : 0);
741
742 for (i = 0; i < currentToneGroup_; i++) {
743 firstFoot = toneGroups_[i].startFoot;
744 endFoot = toneGroups_[i].endFoot;
745
746 startTime = postureData_[feet_[firstFoot].start].onset;
747 endTime = postureData_[feet_[endFoot].end].onset;
748
749 //printf("Tg: %d First: %d end: %d StartTime: %f endTime: %f\n", i, firstFoot, endFoot, startTime, endTime);
750
751 if (useFixedIntonationParameters_) {
752 intonParms_ = fixedIntonationParameters_;
753 } else {
754 switch (toneGroups_[i].type) {
755 default:
756 case TONE_GROUP_TYPE_STATEMENT:
757 if (tgUseRandom_) {
758 tgRandom = intRandDist0(randSrc_);
759 } else {
760 tgRandom = 0;
761 }
762 intonParms_ = &tgParameters_[0][tgRandom * 10];
763 break;
764 case TONE_GROUP_TYPE_EXCLAMATION:
765 if (tgUseRandom_) {
766 tgRandom = intRandDist0(randSrc_);
767 } else {
768 tgRandom = 0;
769 }
770 intonParms_ = &tgParameters_[0][tgRandom * 10];
771 break;
772 case TONE_GROUP_TYPE_QUESTION:
773 if (tgUseRandom_) {
774 tgRandom = intRandDist1(randSrc_);
775 } else {
776 tgRandom = 0;
777 }
778 intonParms_ = &tgParameters_[1][tgRandom * 10];
779 break;
780 case TONE_GROUP_TYPE_CONTINUATION:
781 if (tgUseRandom_) {
782 tgRandom = intRandDist2(randSrc_);
783 } else {
784 tgRandom = 0;
785 }
786 intonParms_ = &tgParameters_[2][tgRandom * 10];
787 break;
788 case TONE_GROUP_TYPE_SEMICOLON:
789 if (tgUseRandom_) {
790 tgRandom = intRandDist3(randSrc_);
791 } else {
792 tgRandom = 0;
793 }
794 intonParms_ = &tgParameters_[3][tgRandom * 10];
795 break;
796 }
797 }
798
799 //printf("Intonation Parameters: Type : %d random: %d\n", toneGroups[i].type, tgRandom);
800 //for (j = 0; j<6; j++)
801 // printf("%f ", intonParms[j]);
802 //printf("\n");
803
804 pretonicDelta = (intonParms_[1]) / (endTime - startTime);
805 //printf("Pretonic Delta = %f time = %f\n", pretonicDelta, (endTime - startTime));
806
807 /* Set up intonation boundary variables */
808 for (j = firstFoot; j <= endFoot; j++) {
809 postureIndex = feet_[j].start;
810 while (!postureData_[postureIndex].posture->isMemberOfCategory(*vocoidCategory)) {
811 postureIndex++;
812 //printf("Checking posture %s for vocoid\n", [posture[postureIndex].posture symbol]);
813 if (postureIndex > feet_[j].end) {
814 postureIndex = feet_[j].start;
815 break;
816 }
817 }
818
819 if (!feet_[j].marked) {
820 for (k = 0; k < currentRule_; k++) {
821 if ((postureIndex >= ruleData_[k].firstPosture) && (postureIndex <= ruleData_[k].lastPosture)) {
822 ruleIndex = k;
823 break;
824 }
825 }
826
827 if (tgUseRandom_) {
828 randomSemitone = randDist_(randSrc_) * intonParms_[3] - intonParms_[3] / 2.0;
829 randomSlope = randDist_(randSrc_) * 0.015 + 0.01;
830 } else {
831 randomSemitone = 0.0;
832 randomSlope = 0.02;
833 }
834
835 //printf("postureIndex = %d onsetTime : %f Delta: %f\n", postureIndex,
836 // postures[postureIndex].onset-startTime,
837 // ((postures[postureIndex].onset-startTime)*pretonicDelta) + intonParms[1] + randomSemitone);
838
839 addIntonationPoint((postureData_[postureIndex].onset - startTime) * pretonicDelta + intonParms_[1] + randomSemitone,
840 offsetTime, randomSlope, ruleIndex);
841 } else { /* Tonic */
842 if (toneGroups_[i].type == 3) {
843 randomSlope = 0.01;
844 } else {
845 randomSlope = 0.02;
846 }
847
848 for (k = 0; k < currentRule_; k++) {
849 if ((postureIndex >= ruleData_[k].firstPosture) && (postureIndex <= ruleData_[k].lastPosture)) {
850 ruleIndex = k;
851 break;
852 }
853 }
854
855 if (tgUseRandom_) {
856 randomSemitone = randDist_(randSrc_) * intonParms_[6] - intonParms_[6] / 2.0;
857 randomSlope += randDist_(randSrc_) * 0.03;
858 } else {
859 randomSemitone = 0.0;
860 randomSlope += 0.03;
861 }
862 addIntonationPoint(intonParms_[2] + intonParms_[1] + randomSemitone,
863 offsetTime, randomSlope, ruleIndex);
864
865 postureIndex = feet_[j].end;
866 for (k = ruleIndex; k < currentRule_; k++) {
867 if ((postureIndex >= ruleData_[k].firstPosture) && (postureIndex <= ruleData_[k].lastPosture)) {
868 ruleIndex = k;
869 break;
870 }
871 }
872
873 addIntonationPoint(intonParms_[2] + intonParms_[1] + intonParms_[5],
874 0.0, 0.0, ruleIndex);
875 }
876 offsetTime = -40.0;
877 }
878 }
879 addIntonationPoint(intonParms_[2] + intonParms_[1] + intonParms_[5],
880 0.0, 0.0, currentRule_ - 1);
881 }
882
883 void
applyIntonationSmooth()884 EventList::applyIntonationSmooth()
885 {
886 setFullTimeScale();
887 //tempPoint = [[IntonationPoint alloc] initWithEventList: self];
888 //[tempPoint setSemitone: -20.0];
889 //[tempPoint setSemitone: -20.0];
890 //[tempPoint setRuleIndex: 0];
891 //[tempPoint setOffsetTime: 10.0 - [self getBeatAtIndex:(int) 0]];
892
893 //[intonationPoints insertObject: tempPoint at:0];
894
895 for (unsigned int j = 0; j < intonationPoints_.size() - 1; j++) {
896 const IntonationPoint& point1 = intonationPoints_[j];
897 const IntonationPoint& point2 = intonationPoints_[j + 1];
898
899 double x1 = point1.absoluteTime() / 4.0;
900 double y1 = point1.semitone() + 20.0;
901 double m1 = point1.slope();
902
903 double x2 = point2.absoluteTime() / 4.0;
904 double y2 = point2.semitone() + 20.0;
905 double m2 = point2.slope();
906
907 double x12 = x1 * x1;
908 double x13 = x12 * x1;
909
910 double x22 = x2 * x2;
911 double x23 = x22 * x2;
912
913 double denominator = x2 - x1;
914 denominator = denominator * denominator * denominator;
915
916 // double d = ( -(y2 * x13) + 3 * y2 * x12 * x2 + m2 * x13 * x2 + m1 * x12 * x22 - m2 * x12 * x22 - 3 * x1 * y1 * x22 - m1 * x1 * x23 + y1 * x23 )
917 // / denominator;
918 double c = ( -(m2 * x13) - 6 * y2 * x1 * x2 - 2 * m1 * x12 * x2 - m2 * x12 * x2 + 6 * x1 * y1 * x2 + m1 * x1 * x22 + 2 * m2 * x1 * x22 + m1 * x23 )
919 / denominator;
920 double b = ( 3 * y2 * x1 + m1 * x12 + 2 * m2 * x12 - 3 * x1 * y1 + 3 * x2 * y2 + m1 * x1 * x2 - m2 * x1 * x2 - 3 * y1 * x2 - 2 * m1 * x22 - m2 * x22 )
921 / denominator;
922 double a = ( -2 * y2 - m1 * x1 - m2 * x1 + 2 * y1 + m1 * x2 + m2 * x2) / denominator;
923
924 insertEvent(32, point1.absoluteTime(), point1.semitone());
925 //printf("Inserting Point %f\n", [point1 semitone]);
926 double yTemp = (3.0 * a * x12) + (2.0 * b * x1) + c;
927 insertEvent(33, point1.absoluteTime(), yTemp);
928 yTemp = (6.0 * a * x1) + (2.0 * b);
929 insertEvent(34, point1.absoluteTime(), yTemp);
930 yTemp = 6.0 * a;
931 insertEvent(35, point1.absoluteTime(), yTemp);
932 }
933 //[intonationPoints removeObjectAt:0];
934
935 //[self insertEvent:32 atTime: 0.0 withValue: -20.0]; /* A value of -20.0 in bin 32 should produce a
936 // linear interp to -20.0 */
937 }
938
939 void
addIntonationPoint(double semitone,double offsetTime,double slope,int ruleIndex)940 EventList::addIntonationPoint(double semitone, double offsetTime, double slope, int ruleIndex)
941 {
942 if (ruleIndex > currentRule_) {
943 return;
944 }
945
946 IntonationPoint iPoint(this);
947 iPoint.setRuleIndex(ruleIndex);
948 iPoint.setOffsetTime(offsetTime);
949 iPoint.setSemitone(semitone);
950 iPoint.setSlope(slope);
951
952 double time = iPoint.absoluteTime();
953 for (unsigned int i = 0; i < intonationPoints_.size(); i++) {
954 if (time < intonationPoints_[i].absoluteTime()) {
955 intonationPoints_.insert(intonationPoints_.begin() + i, iPoint);
956 return;
957 }
958 }
959
960 intonationPoints_.push_back(iPoint);
961 }
962
963 void
generateOutput(std::ostream & trmParamStream)964 EventList::generateOutput(std::ostream& trmParamStream)
965 {
966 double currentValues[36];
967 double currentDeltas[36];
968 double temp;
969 float table[16];
970
971 if (list_.empty()) {
972 return;
973 }
974
975 for (int i = 0; i < 16; i++) {
976 unsigned int j = 1;
977 while ((temp = list_[j]->getValue(i)) == GS_EVENTLIST_INVALID_EVENT_VALUE) {
978 j++;
979 if (j >= list_.size()) break;
980 }
981 currentValues[i] = list_[0]->getValue(i);
982 if (j < list_.size()) {
983 currentDeltas[i] = ((temp - currentValues[i]) / (double) (list_[j]->time)) * 4.0;
984 } else {
985 currentDeltas[i] = 0.0;
986 }
987 }
988 for (int i = 16; i < 36; i++) {
989 currentValues[i] = currentDeltas[i] = 0.0;
990 }
991
992 if (smoothIntonation_) {
993 unsigned int j = 0;
994 while ((temp = list_[j]->getValue(32)) == GS_EVENTLIST_INVALID_EVENT_VALUE) {
995 j++;
996 if (j >= list_.size()) break;
997 }
998 if (j < list_.size()) {
999 currentValues[32] = list_[j]->getValue(32);
1000 } else {
1001 currentValues[32] = 0.0;
1002 }
1003 currentDeltas[32] = 0.0;
1004 } else {
1005 unsigned int j = 1;
1006 while ((temp = list_[j]->getValue(32)) == GS_EVENTLIST_INVALID_EVENT_VALUE) {
1007 j++;
1008 if (j >= list_.size()) break;
1009 }
1010 currentValues[32] = list_[0]->getValue(32);
1011 if (j < list_.size()) {
1012 currentDeltas[32] = ((temp - currentValues[32]) / (double) (list_[j]->time)) * 4.0;
1013 } else {
1014 currentDeltas[32] = 0.0;
1015 }
1016 currentValues[32] = -20.0;
1017 }
1018
1019 unsigned int index = 1;
1020 int currentTime = 0;
1021 int nextTime = list_[1]->time;
1022 while (index < list_.size()) {
1023
1024 for (int j = 0; j < 16; j++) {
1025 table[j] = (float) currentValues[j] + (float) currentValues[j + 16];
1026 }
1027 if (!microFlag_) table[0] = 0.0;
1028 if (driftFlag_) table[0] += static_cast<float>(driftGenerator_.drift());
1029 if (macroFlag_) table[0] += static_cast<long>(currentValues[32]);
1030
1031 table[0] += static_cast<float>(pitchMean_);
1032
1033 trmParamStream << std::fixed << std::setprecision(3);
1034 trmParamStream << table[0];
1035 for (int k = 1; k < 7; ++k) {
1036 trmParamStream << ' ' << table[k];
1037 }
1038 for (int k = 7; k < 15; ++k) { // R1 - R8
1039 trmParamStream << ' ' << table[k] * radiusCoef[k - 7];
1040 }
1041 trmParamStream << ' ' << table[15];
1042 trmParamStream << '\n';
1043
1044 for (int j = 0; j < 32; j++) {
1045 if (currentDeltas[j]) {
1046 currentValues[j] += currentDeltas[j];
1047 }
1048 }
1049
1050 if (smoothIntonation_) {
1051 currentDeltas[34] += currentDeltas[35];
1052 currentDeltas[33] += currentDeltas[34];
1053 currentValues[32] += currentDeltas[33];
1054 } else {
1055 if (currentDeltas[32]) {
1056 currentValues[32] += currentDeltas[32];
1057 }
1058 }
1059 currentTime += 4;
1060
1061 if (currentTime >= nextTime) {
1062 ++index;
1063 if (index == list_.size()) {
1064 break;
1065 }
1066 nextTime = list_[index]->time;
1067 for (int j = 0; j < 33; j++) { /* 32? 33? */
1068 if (list_[index - 1]->getValue(j) != GS_EVENTLIST_INVALID_EVENT_VALUE) {
1069 unsigned int k = index;
1070 while ((temp = list_[k]->getValue(j)) == GS_EVENTLIST_INVALID_EVENT_VALUE) {
1071 if (k >= list_.size() - 1U) {
1072 currentDeltas[j] = 0.0;
1073 break;
1074 }
1075 k++;
1076 }
1077 if (temp != GS_EVENTLIST_INVALID_EVENT_VALUE) {
1078 currentDeltas[j] = (temp - currentValues[j]) /
1079 (double) (list_[k]->time - currentTime) * 4.0;
1080 }
1081 }
1082 }
1083 if (smoothIntonation_) {
1084 if (list_[index - 1]->getValue(33) != GS_EVENTLIST_INVALID_EVENT_VALUE) {
1085 currentValues[32] = list_[index - 1]->getValue(32);
1086 currentDeltas[32] = 0.0;
1087 currentDeltas[33] = list_[index - 1]->getValue(33);
1088 currentDeltas[34] = list_[index - 1]->getValue(34);
1089 currentDeltas[35] = list_[index - 1]->getValue(35);
1090 }
1091 }
1092 }
1093 }
1094
1095 if (Log::debugEnabled) {
1096 printDataStructures();
1097 }
1098 }
1099
1100 void
clearMacroIntonation()1101 EventList::clearMacroIntonation()
1102 {
1103 for (unsigned int i = 0, size = list_.size(); i < size; ++i) {
1104 auto& event = list_[i];
1105 for (unsigned int j = 32; j < 36; ++j) {
1106 event->setValue(GS_EVENTLIST_INVALID_EVENT_VALUE, j);
1107 }
1108 }
1109 }
1110
1111 void
printDataStructures()1112 EventList::printDataStructures()
1113 {
1114 printf("Tone Groups %d\n", currentToneGroup_);
1115 for (int i = 0; i < currentToneGroup_; i++) {
1116 printf("%d start: %d end: %d type: %d\n", i, toneGroups_[i].startFoot, toneGroups_[i].endFoot,
1117 toneGroups_[i].type);
1118 }
1119
1120 printf("\nFeet %d\n", currentFoot_);
1121 for (int i = 0; i < currentFoot_; i++) {
1122 printf("%d tempo: %f start: %d end: %d marked: %d last: %d onset1: %f onset2: %f\n", i, feet_[i].tempo,
1123 feet_[i].start, feet_[i].end, feet_[i].marked, feet_[i].last, feet_[i].onset1, feet_[i].onset2);
1124 }
1125
1126 printf("\nPostures %d\n", currentPosture_);
1127 for (unsigned int i = 0; i < currentPosture_; i++) {
1128 printf("%u \"%s\" tempo: %f syllable: %d onset: %f ruleTempo: %f\n",
1129 i, postureData_[i].posture->name().c_str(), postureTempo_[i], postureData_[i].syllable, postureData_[i].onset, postureData_[i].ruleTempo);
1130 }
1131
1132 printf("\nRules %d\n", currentRule_);
1133 for (int i = 0; i < currentRule_; i++) {
1134 printf("Number: %d start: %d end: %d duration %f\n", ruleData_[i].number, ruleData_[i].firstPosture,
1135 ruleData_[i].lastPosture, ruleData_[i].duration);
1136 }
1137 #if 0
1138 printf("\nEvents %lu\n", list_.size());
1139 for (unsigned int i = 0; i < list_.size(); i++) {
1140 const Event& event = *list_[i];
1141 printf(" Event: time=%d flag=%d\n Values: ", event.time, event.flag);
1142
1143 for (int j = 0; j < 16; j++) {
1144 printf("%.3f ", event.getValue(j));
1145 }
1146 printf("\n ");
1147 for (int j = 16; j < 32; j++) {
1148 printf("%.3f ", event.getValue(j));
1149 }
1150 printf("\n ");
1151 for (int j = 32; j < Event::EVENTS_SIZE; j++) {
1152 printf("%.3f ", event.getValue(j));
1153 }
1154 printf("\n");
1155 }
1156 #endif
1157 }
1158
1159 } /* namespace TRMControlModel */
1160 } /* namespace GS */
1161