Develop and Download Open Source Software

Browse Subversion Repository

Contents of /trunk/echoes/EchoesStyleGenerator.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 101 - (show annotations) (download) (as text)
Fri Feb 1 01:09:56 2013 UTC (11 years, 1 month ago) by haruneko24
File MIME type: text/x-c++src
File size: 6930 byte(s)


1 #include <qmath.h>
2 #include <cmath>
3 #include "helper/ControlCommand.h"
4 #include "EchoesAnalysis.h"
5 #include "EchoesSegment.h"
6 #include "EchoesStyleModel.h"
7 #include "SequenceModel.h"
8 #include "ControlItem.h"
9 #include "TrackItem.h"
10 #include "envelope/Envelope.h"
11 #include "Utility.h"
12
13 #include "EchoesStyleGenerator.h"
14
15 using namespace stand::echoes;
16
17 EchoesStyleGenerator::EchoesStyleGenerator(EchoesStyleModel *style)
18 {
19 setStyle(style);
20 }
21
22 EchoesStyleGenerator::~EchoesStyleGenerator()
23 {
24 }
25
26 EchoesStyleModel *EchoesStyleGenerator::style()
27 {
28 return _style;
29 }
30
31 void EchoesStyleGenerator::setStyle(EchoesStyleModel *style)
32 {
33 _style = style;
34 }
35
36 stand::view::helper::ControlCommand *EchoesStyleGenerator::styleCommand(stand::model::SequenceModel *sequence, int trackId, int tickBegin, int tickEnd, int tickResolution, double msFramePeriod)
37 {
38 if(!sequence)
39 {
40 qDebug("EchoesStyleGenerator::styleCommand(); // invalid args.");
41 return NULL;
42 }
43 QList<EchoesPhrase> phrases = EchoesAnalysis::phraseFromSequence(sequence, trackId, tickBegin, tickEnd);
44
45 if(phrases.empty())
46 {
47 qDebug("EchoesStyleGenerator::styleCommand(); // Range(%d to %d) has no data.", tickBegin, tickEnd);
48 return NULL;
49 }
50
51 // 'segments' is the list of corresponding segments to phrases.
52 QList<EchoesSegment> segments;
53 for(int i = 0; i < phrases.size(); i++)
54 {
55 segments.append(_style->findNearest(phrases.at(i)));
56 }
57
58 stand::view::helper::ControlCommand *parent = new stand::view::helper::ControlCommand;
59 for(int i = 0; i < phrases.size(); i++)
60 {
61 _calculatePhrase(phrases[i], segments[i], sequence, trackId, tickResolution, msFramePeriod, parent);
62 }
63 return parent;
64 }
65
66 stand::view::helper::ControlCommand *EchoesStyleGenerator::_calculatePhrase(const EchoesPhrase &phrase, const EchoesSegment &source, stand::model::SequenceModel *sequence, int trackId, int tickResolution, double framePeriod, stand::view::helper::ControlCommand *parent)
67 {
68 stand::view::helper::ControlCommand *pitch = new stand::view::helper::ControlCommand(parent);
69 stand::view::helper::ControlCommand *volume = new stand::view::helper::ControlCommand(parent);
70 stand::model::TrackItem *track = sequence->track(trackId);
71 stand::model::ControlItem *pitchControl = track->control(track->data(track->PitchControlId, 0).toInt());
72 stand::model::ControlItem *volumeControl = track->control(track->data(track->VolumeControlId, 0).toInt());
73
74 pitch->control = pitchControl;
75 volume->control = volumeControl;
76 int tickBegin = sequence->tick(phrase.notes().first().msPosition());
77 int tickEnd = sequence->tick(phrase.notes().last().msPosition() + phrase.notes().last().msLength());
78 pitch->oldP = pitchControl->contour(tickBegin, tickEnd);
79 volume->oldP = volumeControl->contour(tickBegin ,tickEnd);
80
81 int firstIndex = 0, lastIndex = 0;
82 QList<_Data> data;
83 while(lastIndex < phrase.notes().size())
84 {
85 const EchoesNote &first = phrase.notes().at(firstIndex);
86 const EchoesNote &last = phrase.notes().at(lastIndex);
87
88 // ������������������������������
89 if(first.msPosition() + first.msLength() + 20.0 < last.msPosition())
90 {
91 firstIndex++;
92 continue;
93 }
94 QPair<EchoesNote, EchoesNote> pair = source.phrase()->find(first, last);
95 _Data d = {QPair<EchoesNote, EchoesNote>(first, last), pair, pair.first.noteNumber(), pair.second.noteNumber() - pair.first.noteNumber(), source.pitch(), source.volume()};
96 data.append(d);
97 firstIndex = lastIndex;
98 lastIndex++;
99 }
100
101 _morph(pitch, volume, data, tickResolution, framePeriod, sequence);
102
103 return pitch;
104 }
105
106 void EchoesStyleGenerator::_morph(stand::view::helper::ControlCommand *pitch, stand::view::helper::ControlCommand *volume, QList<_Data> &data, int tickResolution, double framePeriod, stand::model::SequenceModel * sequence)
107 {
108 int size = (data.last().target.second.msPosition() + data.last().target.second.msLength() - data.first().target.first.msPosition()) / framePeriod + 0.5;
109
110 double *pitchContour = new double[size];
111 double *volumeContour = new double[size];
112
113 for(int i = 0; i < size; i++)
114 {
115 pitchContour[i] = 0;
116 volumeContour[i] = -24.0;
117 }
118
119 for(int i = 0; i < data.size(); i++)
120 {
121 for(double ms = data[i].target.first.msPosition(); ms < data[i].target.second.msPosition(); ms += framePeriod)
122 {
123 int index = ms / framePeriod + 0.5;
124 double rate = (ms - data[i].target.first.msPosition()) / (data[i].target.second.msPosition() - data[i].target.first.msPosition());
125 double localMs = rate * (data[i].source.second.msPosition() - data[i].source.first.msPosition()) + data[i].source.first.msPosition();
126 index = qMax(0, qMin(index, size - 1));
127 pitchContour[index] += rate * data[i].pitch->at(localMs) / stand::utility::NoteFrequency(data[i].source.first.noteNumber()) * stand::utility::NoteFrequency(data[i].target.first.noteNumber());
128 volumeContour[index] += rate * data[i].volume->at(localMs);
129 }
130
131 for(double ms = data[i].target.second.msPosition(); ms <= data[i].target.second.msPosition() + data[i].target.second.msLength(); ms += framePeriod)
132 {
133 int index = ms / framePeriod + 0.5;
134 double rate = 1.0 - (ms - data[i].target.second.msPosition())/ data[i].target.second.msLength();
135 double localMs = (1.0 - rate) * data[i].source.second.msLength() + data[i].source.second.msPosition();
136 index = qMax(0, qMin(index, size - 1));
137 pitchContour[index] += rate * data[i].pitch->at(localMs) / stand::utility::NoteFrequency(data[i].source.second.noteNumber()) * stand::utility::NoteFrequency(data[i].target.second.noteNumber());
138 volumeContour[index] += rate * data[i].volume->at(localMs);
139 }
140 }
141
142 stand::utility::envelope::Envelope pitchEnvelope(pitchContour, size, framePeriod, true);
143 stand::utility::envelope::Envelope volumeEnvelope(volumeContour, size, framePeriod, true);
144
145 int tickBegin = sequence->tick(data.first().target.first.msPosition());
146 int tickEnd = sequence->tick(data.last().target.second.msPosition() + data.last().target.second.msLength());
147 for(int tick = tickBegin / tickResolution * tickResolution; tick <= tickEnd; tick += tickResolution)
148 {
149 double ms = sequence->ms(tick) - data.first().target.first.msPosition();
150 double f0 = pitchEnvelope.at(ms);
151 double vol = volumeEnvelope.at(ms);
152 pitch->newP.append(stand::utility::ControlPoint(tick, f0));
153 volume->newP.append(stand::utility::ControlPoint(tick, vol));
154 }
155
156 }
157

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26