Develop and Download Open Source Software

Browse Subversion Repository

Contents of /trunk/synthesis/Vocoder.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: 5446 byte(s)


1 /*
2 *
3 * Vocoder.cpp
4 * (c) HAL@shurabaP 2012-
5 *
6 * This class provides the interface to synthesize wave
7 * by Vocoder system.
8 *
9 * These files are distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 *
13 */
14 #include "Vocoder.h"
15
16 #include "SequenceModel.h"
17 #include "SynthesizerExpression.h"
18 #include "SynthesizerTrack.h"
19 #include "SynthesizerNote.h"
20 #include "SynthesizerPhrase.h"
21 #include "AbstractCorpus.h"
22
23 #include "audio/AudioChunk.h"
24
25 #include "../configure.h"
26 #include "Utility.h"
27
28 using namespace stand::synthesis;
29 using namespace stand::model;
30
31 Vocoder::Vocoder(AbstractVocoderEngine *engine, AbstractCorpus *corpus, QObject *parent) :
32 AbstractSynthesizer(parent)
33 {
34 setEngine(engine);
35 setCorpus(corpus);
36 }
37
38 Vocoder::~Vocoder()
39 {
40 }
41
42 bool Vocoder::synthesize(stand::io::audio::AudioChunk *dst, SynthesizerPhrase *phrase)
43 {
44 if(!_engine || !_corpus || !dst || !dst->format().isValid())
45 {
46 return false;
47 }
48
49 double msCurrent = phrase->msBegin();
50 dst->setMsLength(phrase->msEnd() - phrase->msBegin());
51 dst->clearBufferToZero();
52
53 const QVector<SynthesizerNote *> &notes = phrase->track()->notes();
54
55 for(int i = 0; i < notes.size(); i++)
56 {
57 if(notes[i]->msBegin() < phrase->msBegin())
58 {
59 continue;
60 }
61 if(notes[i]->msBegin() >= phrase->msEnd())
62 {
63 break;
64 }
65
66 if(_corpus->contains(AbstractCorpus::Key(notes[i], 0)))
67 {
68 // ������������������������������
69 SynthesizerNote *thisNote = notes[i];
70 SynthesizerNote *nextNote = (i + 1 < notes.size()) ? notes[i+1] : NULL;
71
72 msCurrent = qMax(msCurrent, thisNote->msBegin() - _corpus->msPreutterance(AbstractCorpus::Key(thisNote, 0.0)));
73
74 // ���������������������������������������������������������������������
75 if(nextNote)
76 {
77 msCurrent = _synthesizeOneNote(dst, msCurrent, thisNote, nextNote, phrase);
78 }
79 else
80 {
81 msCurrent = _synthesizeOneNote(dst, msCurrent, thisNote, phrase);
82 }
83 }
84 else
85 {
86 msCurrent = notes[i]->msEnd();
87 }
88 }
89 dst->setReadiness(true);
90
91 return true;
92 }
93
94 double Vocoder::_synthesizeOneNote(stand::io::audio::AudioChunk *dst, double msCurrent, SynthesizerNote *current, SynthesizerNote *next, SynthesizerPhrase *phrase)
95 {
96 VocoderFrame currentFrame(_engine->info()), nextFrame(_engine->info());
97
98 QVector<QPair<VocoderFrame *, double> > frames;
99 frames.resize(2);
100 frames[0].first = &currentFrame;
101 frames[1].first = &nextFrame;
102
103 double currentActualMs = current->msBegin() - _corpus->msPreutterance(AbstractCorpus::Key(current, 0));
104 double nextActualMs = next->msBegin() - _corpus->msPreutterance(AbstractCorpus::Key(next, 0));
105 double begin = qMax(currentActualMs, nextActualMs);
106 double length = current->msEnd() - begin;
107 if(length <= 0.0)
108 {
109 return _synthesizeOneNote(dst, msCurrent, current, phrase);
110 }
111
112 while(msCurrent < phrase->msEnd() && msCurrent < current->msEnd())
113 {
114 double f0 = phrase->track()->f0At(msCurrent);
115 if(f0 == 0.0)
116 {
117 f0 = stand::DefaultF0Value;
118 }
119
120 AbstractCorpus::Key currentKey(current, msCurrent - current->msBegin());
121 AbstractCorpus::Key nextKey(next, msCurrent - next->msBegin());
122
123 // ���������������������������������������
124 frames[0].second = qMax(0.0, qMin(1.0, 1.0 - (msCurrent - begin) / length));
125 frames[1].second = 1.0 - frames[0].second;
126
127 // ���������������������������������������������������
128 if(frames[0].second == 0.0)
129 {
130 _corpus->find(&currentFrame, nextKey, _engine);
131 }
132 else if(frames[0].second == 1.0)
133 {
134 _corpus->find(&currentFrame, currentKey, _engine);
135 }
136 else
137 {
138 _corpus->find(&currentFrame, currentKey, _engine);
139 _corpus->find(&nextFrame, nextKey, _engine);
140 _engine->morph(&currentFrame, frames);
141 }
142
143 _engine->synthesize(dst, &currentFrame, dst->samplesAtMsec(msCurrent));
144 msCurrent += 1000.0 / f0;//_engine->samplesForF0(f0);
145 }
146 return msCurrent;
147 }
148
149 double Vocoder::_synthesizeOneNote(stand::io::audio::AudioChunk *dst, double msCurrent, SynthesizerNote *current, SynthesizerPhrase *phrase)
150 {
151 VocoderFrame currentFrame(_engine->info());
152 while(msCurrent < phrase->msEnd() && msCurrent < current->msEnd())
153 {
154 double f0 = phrase->track()->f0At(msCurrent);
155 if(f0 < stand::utility::NoteFrequency(0) || f0 > stand::utility::NoteFrequency(128))
156 {
157 f0 = stand::DefaultF0Value;
158 }
159 AbstractCorpus::Key key(current, msCurrent - current->msBegin());
160 _corpus->find(&currentFrame, key, _engine);
161 _engine->synthesize(dst, &currentFrame, dst->samplesAtMsec(msCurrent));
162 msCurrent += 1000.0 / f0;//_engine->samplesForF0(f0) / (double)_engine->info().sampleRate() * 1000.0;
163 }
164 return msCurrent;
165 }
166
167

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