| 1 |
haruneko24 |
101 |
#include <cmath> |
| 2 |
|
|
|
| 3 |
|
|
#include "helper/ControlCommand.h" |
| 4 |
|
|
#include "envelope/Envelope.h" |
| 5 |
|
|
#include "Utility.h" |
| 6 |
|
|
#include "SequenceModel.h" |
| 7 |
|
|
#include "EventItem.h" |
| 8 |
|
|
#include "TrackItem.h" |
| 9 |
|
|
#include "ControlItem.h" |
| 10 |
|
|
|
| 11 |
|
|
#include "SecondOrderStyleGenerator.h" |
| 12 |
|
|
|
| 13 |
|
|
using namespace stand::echoes; |
| 14 |
|
|
|
| 15 |
|
|
SecondOrderStyleGenerator::SecondOrderStyleGenerator() |
| 16 |
|
|
{ |
| 17 |
|
|
} |
| 18 |
|
|
|
| 19 |
|
|
stand::view::helper::ControlCommand *SecondOrderStyleGenerator::styleCommand(stand::model::SequenceModel *sequence, int trackId, int tickBegin, int tickEnd, int tickResolution, double msFramePeriod) |
| 20 |
|
|
{ |
| 21 |
|
|
stand::view::helper::ControlCommand *c = new stand::view::helper::ControlCommand; |
| 22 |
|
|
|
| 23 |
|
|
stand::model::TrackItem *track = sequence->track(trackId); |
| 24 |
|
|
stand::model::ControlItem *pitch = track->control(track->data(track->PitchControlId, 0).toInt()); |
| 25 |
|
|
stand::model::TreeItem *events = track->events(); |
| 26 |
|
|
QVector<QPair<double, double> > notes; |
| 27 |
|
|
|
| 28 |
|
|
if(events->childCount() == 0) |
| 29 |
|
|
{ |
| 30 |
|
|
return NULL; |
| 31 |
|
|
} |
| 32 |
|
|
|
| 33 |
|
|
notes.resize(events->childCount()); |
| 34 |
|
|
for(int i = 0; i < events->childCount(); i++) |
| 35 |
|
|
{ |
| 36 |
|
|
stand::model::EventItem *item = static_cast<stand::model::EventItem *>(events->child(i)); |
| 37 |
|
|
notes[i] = QPair<double, double>(sequence->ms(item->tick()), sequence->ms(item->tick() + item->length())); |
| 38 |
|
|
qDebug("%f, %f", notes[i].first, notes[i].second); |
| 39 |
|
|
} |
| 40 |
|
|
|
| 41 |
|
|
double msBegin = sequence->ms(tickBegin); |
| 42 |
|
|
double msEnd = sequence->ms(tickEnd); |
| 43 |
|
|
int size = (msEnd - msBegin) / msFramePeriod + 0.5; |
| 44 |
|
|
double *stepImpulse = new double[size]; |
| 45 |
|
|
double *result = new double[size]; |
| 46 |
|
|
|
| 47 |
|
|
// ������������������������ |
| 48 |
|
|
for(int i = 0; i < size; i++) |
| 49 |
|
|
{ |
| 50 |
|
|
stepImpulse[i] = result[i] = 0.0; |
| 51 |
|
|
} |
| 52 |
|
|
|
| 53 |
|
|
int noteIndex = 0; |
| 54 |
|
|
for(double ms = msBegin; ms < msEnd && noteIndex < notes.size(); ms += msFramePeriod) |
| 55 |
|
|
{ |
| 56 |
|
|
// ������������������ |
| 57 |
|
|
if(ms < notes[noteIndex].first) |
| 58 |
|
|
{ |
| 59 |
|
|
continue; |
| 60 |
|
|
} |
| 61 |
|
|
if(ms > notes[noteIndex].second) |
| 62 |
|
|
{ |
| 63 |
|
|
noteIndex++; |
| 64 |
|
|
if(noteIndex == notes.size()) |
| 65 |
|
|
{ |
| 66 |
|
|
break; |
| 67 |
|
|
} |
| 68 |
|
|
} |
| 69 |
|
|
// ToDo: StepImpulse ������������������ |
| 70 |
|
|
int index = (ms - msBegin) / msFramePeriod; |
| 71 |
|
|
index = qMax(0, qMin(size - 1, index)); |
| 72 |
|
|
stepImpulse[index] = stand::utility::NoteFrequency(events->child(noteIndex)->data(stand::model::EventItem::NoteData, 0).toInt()); |
| 73 |
|
|
} |
| 74 |
|
|
// apply overshoot |
| 75 |
|
|
/* omega = 0.0348; |
| 76 |
|
|
xi = 0.5422; |
| 77 |
|
|
k = 0.0348; |
| 78 |
|
|
_applyH(stepImpulse, result, size, msFramePeriod); // (�������������)��������������������������������� |
| 79 |
|
|
*/ |
| 80 |
|
|
// apply preparation |
| 81 |
|
|
omega = 0.0292; |
| 82 |
|
|
xi = 0.6681; |
| 83 |
|
|
k = 0.0292; |
| 84 |
|
|
_applyH(result, stepImpulse, size, msFramePeriod); |
| 85 |
|
|
|
| 86 |
|
|
c->control = pitch; |
| 87 |
|
|
c->oldP = pitch->contour(tickBegin, tickEnd); |
| 88 |
|
|
|
| 89 |
|
|
_applyC(c, result, size, sequence, trackId, tickBegin, tickEnd, tickResolution, msFramePeriod); |
| 90 |
|
|
|
| 91 |
|
|
delete[] stepImpulse; |
| 92 |
|
|
delete[] result; |
| 93 |
|
|
|
| 94 |
|
|
return c; |
| 95 |
|
|
} |
| 96 |
|
|
|
| 97 |
|
|
void SecondOrderStyleGenerator::_applyH(double *dst, double *src, int size, double msFramePeriod) |
| 98 |
|
|
{ |
| 99 |
|
|
for(int i = 0; i < size; i++) |
| 100 |
|
|
{ |
| 101 |
|
|
if(src[i] == 0.0) |
| 102 |
|
|
{ |
| 103 |
|
|
continue; |
| 104 |
|
|
} |
| 105 |
|
|
for(int j = 0; j < 1024 && i + j < size; j++) |
| 106 |
|
|
{ |
| 107 |
|
|
dst[i + j] += src[i] * h(j * msFramePeriod) * 2; |
| 108 |
|
|
} |
| 109 |
|
|
} |
| 110 |
|
|
} |
| 111 |
|
|
|
| 112 |
|
|
double SecondOrderStyleGenerator::h(double sec) const |
| 113 |
|
|
{ |
| 114 |
|
|
/* ������������������������������������������������������������������ |
| 115 |
|
|
* k |
| 116 |
|
|
* H(s) = ---------------------------- |
| 117 |
|
|
* s^2 + 2xi omega s + omega^2 |
| 118 |
|
|
*-- |
| 119 |
|
|
* case |xi| < 1 && xi != 0: |
| 120 |
|
|
* |
| 121 |
|
|
* omega |
| 122 |
|
|
* h(t) = ------------------- exp(-xi omega t) sin omega (1 - xi^2)^(1 / 2) t) |
| 123 |
|
|
* (1 - xi^2)^(1/2) |
| 124 |
|
|
*-- |
| 125 |
|
|
* case |xi| == 1 |
| 126 |
|
|
* |
| 127 |
|
|
* h(t) = omega * omega * t * exp(-omega * t); |
| 128 |
|
|
* |
| 129 |
|
|
*-- |
| 130 |
|
|
* case |xi| > 1 |
| 131 |
|
|
* |
| 132 |
|
|
*/ |
| 133 |
|
|
|
| 134 |
|
|
if(fabs(xi) < 1) |
| 135 |
|
|
{ |
| 136 |
|
|
double t1 = sqrt(1 - xi * xi); |
| 137 |
|
|
double t2 = omega / t1 * exp(-xi * omega * sec) * sin(omega * sec * t1); |
| 138 |
|
|
return t2; |
| 139 |
|
|
} |
| 140 |
|
|
else if(fabs(xi) == 1) |
| 141 |
|
|
{ |
| 142 |
|
|
return omega * omega * sec * exp(-omega * sec); |
| 143 |
|
|
} |
| 144 |
|
|
else |
| 145 |
|
|
{ |
| 146 |
|
|
double t1 = sqrt(1 - xi * xi); |
| 147 |
|
|
double t2 = exp(omega * t1 * sec) - exp(-omega * t1 * sec); |
| 148 |
|
|
double t3 = omega / (2 * t1) * exp(-xi * omega * sec) * t2; |
| 149 |
|
|
return t3; |
| 150 |
|
|
} |
| 151 |
|
|
} |
| 152 |
|
|
|
| 153 |
|
|
void SecondOrderStyleGenerator::_applyC(stand::view::helper::ControlCommand *c, double *contour, int size, stand::model::SequenceModel *sequence, int trackId, int tickBegin, int tickEnd, int tickResolution, double msFramePeriod) |
| 154 |
|
|
{ |
| 155 |
|
|
double msBegin = sequence->ms(tickBegin); |
| 156 |
|
|
for(int tick = (tickBegin / tickResolution) * tickResolution; tick <= tickEnd; tick += tickResolution) |
| 157 |
|
|
{ |
| 158 |
|
|
double ms = sequence->ms(tick) - msBegin; |
| 159 |
|
|
int index = ms / msFramePeriod + 0.5; |
| 160 |
|
|
index = qMax(0, qMin(index, size - 1)); |
| 161 |
|
|
double value = contour[index]; |
| 162 |
|
|
c->newP.append(stand::utility::ControlPoint(tick, value)); |
| 163 |
|
|
} |
| 164 |
|
|
} |