Metro Style Appとして作成してみます。
Revision | 7de079ab4c091508cd5a5ee86ca8a6cb27b41e2b (tree) |
---|---|
Time | 2012-05-19 16:21:31 |
Author | sfpgmr <sfpg@user...> |
Commiter | sfpgmr |
とりあえず音が出るようになった。
@@ -40,7 +40,6 @@ App::App() | ||
40 | 40 | { |
41 | 41 | InitializeComponent(); |
42 | 42 | Suspending += ref new SuspendingEventHandler(this, &App::OnSuspending); |
43 | - | |
44 | 43 | } |
45 | 44 | |
46 | 45 | /// <summary> |
@@ -0,0 +1,12 @@ | ||
1 | +#include "pch.h" | |
2 | +#include "Sequencer.h" | |
3 | + | |
4 | + | |
5 | +Sequencer::Sequencer(void) | |
6 | +{ | |
7 | +} | |
8 | + | |
9 | + | |
10 | +Sequencer::~Sequencer(void) | |
11 | +{ | |
12 | +} |
@@ -0,0 +1,8 @@ | ||
1 | +#pragma once | |
2 | +class Sequencer | |
3 | +{ | |
4 | +public: | |
5 | + Sequencer(void); | |
6 | + ~Sequencer(void); | |
7 | +}; | |
8 | + |
@@ -107,6 +107,7 @@ | ||
107 | 107 | <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> |
108 | 108 | <ClCompile> |
109 | 109 | <StructMemberAlignment>16Bytes</StructMemberAlignment> |
110 | + <EnableEnhancedInstructionSet>AdvancedVectorExtensions</EnableEnhancedInstructionSet> | |
110 | 111 | </ClCompile> |
111 | 112 | <Link> |
112 | 113 | <AdditionalDependencies>d2d1.lib;d3d11.lib;dxgi.lib;ole32.lib;windowscodecs.lib;dwrite.lib;xaudio2.lib;mfcore.lib;mfplat.lib;mfreadwrite.lib;%(AdditionalDependencies)</AdditionalDependencies> |
@@ -121,6 +122,7 @@ | ||
121 | 122 | <ClCompile> |
122 | 123 | <FloatingPointModel>Fast</FloatingPointModel> |
123 | 124 | <EnableParallelCodeGeneration>true</EnableParallelCodeGeneration> |
125 | + <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion> | |
124 | 126 | </ClCompile> |
125 | 127 | </ItemDefinitionGroup> |
126 | 128 | <ItemGroup> |
@@ -149,6 +151,7 @@ | ||
149 | 151 | </ClInclude> |
150 | 152 | <ClInclude Include="SampleOverlay.h" /> |
151 | 153 | <ClInclude Include="GameMain.h" /> |
154 | + <ClInclude Include="Sequencer.h" /> | |
152 | 155 | <ClInclude Include="sf_com.h" /> |
153 | 156 | <ClInclude Include="sf_memory.h" /> |
154 | 157 | <ClInclude Include="SoundDriver.h" /> |
@@ -211,9 +214,12 @@ | ||
211 | 214 | </ClCompile> |
212 | 215 | <ClCompile Include="SampleOverlay.cpp" /> |
213 | 216 | <ClCompile Include="GameMain.cpp" /> |
217 | + <ClCompile Include="Sequencer.cpp" /> | |
214 | 218 | <ClCompile Include="sf_com.cpp" /> |
215 | 219 | <ClCompile Include="SoundDriver.cpp" /> |
216 | - <ClCompile Include="WaveTableSynth.cpp" /> | |
220 | + <ClCompile Include="WaveTableSynth.cpp"> | |
221 | + <AssemblerOutput Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">AssemblyAndSourceCode</AssemblerOutput> | |
222 | + </ClCompile> | |
217 | 223 | </ItemGroup> |
218 | 224 | <ItemGroup> |
219 | 225 | <FxCompile Include="BasicSprites.GeometryShader.gs.hlsl"> |
@@ -84,7 +84,7 @@ namespace sf { | ||
84 | 84 | // 再計算する |
85 | 85 | format_.Format.nAvgBytesPerSec = alt_format->Format.nSamplesPerSec * format_.Format.nBlockAlign; |
86 | 86 | // もう一回チェックする。 |
87 | - // サンプルレート以外でサポートしていない点があれば例外が発生する。 | |
87 | + // サンプルレート以外でサポートしていない設定があれば例外が発生する。 | |
88 | 88 | alt_format.reset(); |
89 | 89 | ThrowIfErr(audioClient_->IsFormatSupported( |
90 | 90 | AUDCLNT_SHAREMODE_SHARED, |
@@ -136,7 +136,14 @@ namespace sf { | ||
136 | 136 | eventHolder_.reset(::CreateEventEx(NULL, NULL, 0, EVENT_MODIFY_STATE | SYNCHRONIZE)); |
137 | 137 | audioClient_->SetEventHandle(eventHolder_.get()); |
138 | 138 | synth_.reset(new WaveTableSynth(format_)); |
139 | + | |
140 | + synth_->ProcessBuffer(buffer_[bufferIndex_],bufferSize_); | |
141 | + BYTE* rawBuffer; | |
142 | + ThrowIfErr(audioRenderClient_->GetBuffer(bufferSize_,&rawBuffer)); | |
143 | + audioRenderClient_->ReleaseBuffer(bufferSize_,0); | |
144 | + bufferIndex_ = (bufferIndex_ + 1) & 0x1; | |
139 | 145 | synth_->ProcessBuffer(buffer_[bufferIndex_],bufferSize_); |
146 | + | |
140 | 147 | ThrowIfErr(audioClient_->Start()); |
141 | 148 | } |
142 | 149 |
@@ -159,6 +166,7 @@ namespace sf { | ||
159 | 166 | ::memcpy(rawBuffer,buffer_[bufferIndex_].get(),bufferByteCount_); |
160 | 167 | audioRenderClient_->ReleaseBuffer(bufferSize_,0); |
161 | 168 | bufferIndex_ = (bufferIndex_ + 1) & 0x1; |
169 | + ZeroMemory(buffer_[bufferIndex_].get(),bufferByteCount_); | |
162 | 170 | synth_->ProcessBuffer(buffer_[bufferIndex_],bufferSize_); |
163 | 171 | } |
164 | 172 | } |
@@ -1,7 +1,11 @@ | ||
1 | 1 | #include "pch.h" |
2 | +//#include "xbyak\xbyak.h" | |
2 | 3 | #include "WaveTableSynth.h" |
3 | 4 | |
5 | +using namespace std::placeholders; | |
6 | + | |
4 | 7 | namespace sf { |
8 | + | |
5 | 9 | void makeWaveFormat(WAVEFORMATEXTENSIBLE& format, |
6 | 10 | int sample_rate = 44100,int channels = 2,int bits_per_sample = 32,int valid_bits_per_sample = 32, |
7 | 11 | uint32_t type = WAVE_FORMAT_EXTENSIBLE, |
@@ -31,8 +35,619 @@ namespace sf { | ||
31 | 35 | format.nAvgBytesPerSec = format.nSamplesPerSec * format.nBlockAlign; |
32 | 36 | }; |
33 | 37 | |
38 | + struct WaveTableSynth::impl { | |
39 | + | |
40 | + impl(){}; | |
41 | + explicit impl(WAVEFORMATEXTENSIBLE& format) : format_(format) | |
42 | + { | |
43 | + | |
44 | + // 鋸波テーブルを作る | |
45 | + { | |
46 | + WaveTable sawtbl; | |
47 | + sawtbl.SampleRate(440.0f); | |
48 | + sawtbl.BasePitch(1.0f); | |
49 | + sawtbl.Stereo(false); | |
50 | + | |
51 | + float v = -1.0f,d = 2.0f / 32.0f; | |
52 | + for(int i = 0;i < 32;++i) | |
53 | + { | |
54 | + // if(i < 15) v = -1.0f; else v = 1.0f; | |
55 | + sawtbl.WaveData().push_back(v) ; | |
56 | + v += d; | |
57 | + } | |
58 | + waveTable_.push_back(sawtbl); | |
59 | + } | |
60 | + | |
61 | + // 矩形波テーブルを作る | |
62 | + { | |
63 | + WaveTable squaretbl; | |
64 | + squaretbl.SampleRate(440.0f); | |
65 | + squaretbl.BasePitch(1.0f); | |
66 | + squaretbl.Stereo(false); | |
67 | + | |
68 | + float v = 0.0f; | |
69 | + for(int i = 0;i < 32;++i) | |
70 | + { | |
71 | + if(i < 15) v = -1.0f; else v = 1.0f; | |
72 | + squaretbl.WaveData().push_back(v) ; | |
73 | + } | |
74 | + waveTable_.push_back(squaretbl); | |
75 | + } | |
76 | + | |
77 | + // 三角波テーブル | |
78 | + { | |
79 | + WaveTable tritbl; | |
80 | + tritbl.SampleRate(440.0f); | |
81 | + tritbl.BasePitch(1.0f); | |
82 | + tritbl.Stereo(false); | |
83 | + | |
84 | + float v = -1.0f,d = 2.0f / 16.0f; | |
85 | + for(int i = 0;i < 32;++i) | |
86 | + { | |
87 | + if(i < 15) d = -d; | |
88 | + tritbl.WaveData().push_back(v) ; | |
89 | + v += d; | |
90 | + } | |
91 | + waveTable_.push_back(tritbl); | |
92 | + } | |
93 | + | |
94 | + // sinテーブル | |
95 | + { | |
96 | + WaveTable sintbl; | |
97 | + sintbl.SampleRate(440.0f); | |
98 | + sintbl.BasePitch(1.0f); | |
99 | + sintbl.Stereo(false); | |
100 | + | |
101 | + float v = 0.0f,d = 2.0f * M_PI / 128.0f; | |
102 | + for(int i = 0;i < 128;++i) | |
103 | + { | |
104 | + sintbl.WaveData().push_back(sinf(v)); | |
105 | + v += d; | |
106 | + } | |
107 | + waveTable_.push_back(sintbl); | |
108 | + } | |
109 | + | |
110 | + | |
111 | + | |
112 | + | |
113 | + | |
114 | + // ::OutputDebugStringW((boost::wformat(L"waveTable size: %d") % waveTable_[0].WaveData().size()).str().c_str()); | |
115 | + | |
116 | + // timberのセットアップ | |
117 | + Timber timber; | |
118 | + timber.waveTableNo = 3; | |
119 | + timber.amplitude.gain = 1.0f; | |
120 | + timber.amplitude.envelope.attackTime = 0.0f; | |
121 | + timber.amplitude.envelope.decayTime = 0.5f; | |
122 | + timber.amplitude.envelope.sustainLevel = 0.25f; | |
123 | + timber.amplitude.envelope.releaseTime = 3.0f; | |
124 | + timber.amplitude.envelope.gain = 1.0f; | |
125 | + | |
126 | + timbers_.push_back(timber); | |
127 | + | |
128 | + // Voiceのセットアップ | |
129 | + for(int i = 0; i < 1;++i){ | |
130 | + voices_.push_back(Voice(waveTable_,format.Format.nSamplesPerSec)); | |
131 | + voices_[i].SetTimber(&timbers_[0]); | |
132 | + voices_[i].NoteOn(1.0f,1.0f); | |
133 | + } | |
134 | + | |
135 | + }; | |
136 | + | |
137 | + ~impl(){}; | |
138 | + | |
139 | + void Restart(){}; | |
140 | + void ProcessBuffer(boost::shared_array<float> arr,int bufferSize) | |
141 | + { | |
142 | + // 今のところ出力はステレオ前提 | |
143 | + float *ptr = arr.get(); | |
144 | + float buffer[2]; | |
145 | + for(int i = 0;i < bufferSize;++i) | |
146 | + { | |
147 | + for(int j = 0;j < voices_.size();++j) | |
148 | + { | |
149 | + voices_[j].Process(buffer); | |
150 | + *ptr += buffer[0]; | |
151 | + *(ptr + 1) += buffer[1]; | |
152 | + } | |
153 | + ptr += 2; | |
154 | + } | |
155 | + | |
156 | + // サイン波の生成 | |
157 | + | |
158 | + //static float sampleIncrement = (440.0f /* Hz */ * (M_PI * 2.0f)) / (float)format_.Format.nSamplesPerSec; | |
159 | + //static float theta = 0.0f; | |
160 | + | |
161 | + //for (size_t i = 0 ; i < bufferSize ; ++i) | |
162 | + //{ | |
163 | + // float sinValue = sinf( theta ); | |
164 | + // int offset = i * format_.Format.nChannels; | |
165 | + // for(size_t j = 0 ;j < format_.Format.nChannels; j++) | |
166 | + // { | |
167 | + // arr[offset + j] = sinValue; | |
168 | + // } | |
169 | + // theta += sampleIncrement; | |
170 | + //} | |
171 | + } | |
172 | + | |
173 | + struct Envelope | |
174 | + { | |
175 | + Envelope() : | |
176 | + attackTime(0.0f), | |
177 | + decayTime(0.5f), | |
178 | + sustainLevel(0.5f), | |
179 | + releaseTime(3.0f),gain(1.0f) | |
180 | + {} | |
181 | + float attackTime; | |
182 | + float decayTime; | |
183 | + float sustainLevel; | |
184 | + float releaseTime; | |
185 | + float gain; | |
186 | + }; | |
187 | + | |
188 | + struct Oscillator | |
189 | + { | |
190 | + virtual void Process(float * data,float delta) = 0; | |
191 | + virtual bool Stereo() const = 0; | |
192 | + }; | |
193 | + struct WaveTable : public Oscillator | |
194 | + { | |
195 | + typedef std::vector<float> WaveDataType; | |
196 | + typedef std::function<void (float * ,float)> ProcessorType; | |
197 | + | |
198 | + WaveTable() : waveCounter_(0.0f),stereo_(false) | |
199 | + { | |
200 | + Stereo(false); | |
201 | + }; | |
202 | + | |
203 | + WaveTable(const WaveTable& src) : | |
204 | + sampleRate_(src.sampleRate_),// | |
205 | + basePitch_(src.basePitch_), | |
206 | + waveCounter_(src.waveCounter_), | |
207 | + waveData_(src.waveData_) | |
208 | + { | |
209 | + Stereo(src.stereo_); | |
210 | + } | |
211 | + | |
212 | + void Process(float * data,float delta) | |
213 | + { | |
214 | + processor_(data,delta); | |
215 | + } | |
216 | + | |
217 | + bool Stereo() const {return stereo_;} | |
218 | + void Stereo(bool v) { | |
219 | + stereo_ = v; | |
220 | + if(v) | |
221 | + { | |
222 | + processor_ = [&](float * data,float delta) -> void | |
223 | + { | |
224 | + waveCounter_ += delta; | |
225 | + | |
226 | + if(waveData_.size() <= (int)(waveCounter_ * 2.0f)) | |
227 | + { | |
228 | + waveCounter_ -= (float)waveData_.size() / 2.0f; | |
229 | + } | |
230 | + | |
231 | + int index = (float) waveCounter_; | |
232 | + float *src = &waveData_[index * 2]; | |
233 | + *data = *src; | |
234 | + ++data;++src; | |
235 | + *data = *src; | |
236 | + | |
237 | + }; | |
238 | + } else { | |
239 | + processor_ = [&](float * data,float delta) -> void | |
240 | + { | |
241 | + waveCounter_ += delta; | |
242 | + if(waveData_.size() <= (int)(waveCounter_)) | |
243 | + { | |
244 | + waveCounter_ -= (float)waveData_.size(); | |
245 | + } | |
246 | + int index = (int) waveCounter_; | |
247 | + float d = waveData_[index]; | |
248 | + *data++ = d; | |
249 | + *data = d; | |
250 | + | |
251 | + | |
252 | + }; | |
253 | + } | |
254 | + } | |
255 | + WaveDataType& WaveData() {return waveData_;} | |
256 | + void WaveData(const WaveDataType& src) | |
257 | + { | |
258 | + waveData_ = src; | |
259 | + } | |
260 | + | |
261 | + void SampleRate(float s) {sampleRate_ = s;} | |
262 | + float SampleRate() const {return sampleRate_;} | |
263 | + void BasePitch(float v) {basePitch_ = v;} | |
264 | + float BasePitch() { return basePitch_ ;} | |
265 | + private: | |
266 | + bool stereo_; | |
267 | + float sampleRate_;// | |
268 | + float basePitch_; | |
269 | + float waveCounter_; | |
270 | + ProcessorType processor_; | |
271 | + WaveDataType waveData_; | |
272 | + }; | |
273 | + | |
274 | + struct LFO | |
275 | + { | |
276 | + LFO(){} | |
277 | + WaveTable* waveForm; | |
278 | + bool startNoteOn; | |
279 | + float freq; | |
280 | + float gain; | |
281 | + }; | |
282 | + | |
283 | + struct Filter | |
284 | + { | |
285 | + int type; | |
286 | + float level; | |
287 | + float resonance; | |
288 | + Envelope envelope; | |
289 | + LFO lfo; | |
290 | + }; | |
291 | + | |
292 | + struct Amplitude | |
293 | + { | |
294 | + Amplitude() : gain(1.0f) {} | |
295 | + float gain; | |
296 | + Envelope envelope; | |
297 | + LFO lfo; | |
298 | + }; | |
299 | + | |
300 | + struct Pitch { | |
301 | + Pitch() : pitch(1.0f){} | |
302 | + float pitch; | |
303 | + Envelope envelope; | |
304 | + LFO lfo; | |
305 | + }; | |
306 | + | |
307 | + struct Pan { | |
308 | + Pan() : pan(0.5f) {}; | |
309 | + float pan; | |
310 | + Envelope envelope; | |
311 | + LFO lfo; | |
312 | + }; | |
34 | 313 | |
35 | - WaveTableSynth::WaveTableSynth(WAVEFORMATEXTENSIBLE& format ) : format_(format) | |
314 | + struct Timber | |
315 | + { | |
316 | + Timber() : waveTableNo(0){}; | |
317 | + int waveTableNo; | |
318 | + Amplitude amplitude; | |
319 | + Filter filter; | |
320 | + Pitch pitch; | |
321 | + Pan pan; | |
322 | + }; | |
323 | + | |
324 | + struct Program { | |
325 | + std::wstring name; | |
326 | + Timber Timber; | |
327 | + }; | |
328 | + | |
329 | + enum struct EnvelopeStatus | |
330 | + { | |
331 | + None,Attack,Decay,Sustain,Release,End | |
332 | + }; | |
333 | + | |
334 | + struct EnvelopeController | |
335 | + { | |
336 | + EnvelopeController() : envelope_(nullptr),stepTime_(1.0f / 44100.0f) | |
337 | + { | |
338 | + } | |
339 | + | |
340 | + void Reset() | |
341 | + { | |
342 | + status_ = EnvelopeStatus::None; | |
343 | + } | |
344 | + | |
345 | + void Init(Envelope * env,float sampleRate) | |
346 | + { | |
347 | + envelope_ = env; | |
348 | + stepTime_ = 1.0f / sampleRate; | |
349 | + } | |
350 | + void Attack() | |
351 | + { | |
352 | + if(envelope_->attackTime == 0.0f) | |
353 | + { | |
354 | + value_ = 1.0f; | |
355 | + return Decay(); | |
356 | + } | |
357 | + status_ = EnvelopeStatus::Attack; | |
358 | + delta_ = stepTime_ / envelope_->attackTime; | |
359 | + value_ = 0.0f; | |
360 | + | |
361 | + } | |
362 | + | |
363 | + void Decay() | |
364 | + { | |
365 | + if(envelope_->sustainLevel == 1.0f) | |
366 | + { | |
367 | + Sustain(); | |
368 | + } | |
369 | + delta_ = (1.0f - envelope_->sustainLevel) * stepTime_ / (envelope_->decayTime); | |
370 | + status_ = EnvelopeStatus::Decay; | |
371 | + } | |
372 | + | |
373 | + void Sustain() | |
374 | + { | |
375 | + | |
376 | + if(envelope_->sustainLevel == 0.0f) | |
377 | + { | |
378 | + status_ = EnvelopeStatus::End; | |
379 | + } | |
380 | + | |
381 | + status_ = EnvelopeStatus::Sustain; | |
382 | + } | |
383 | + | |
384 | + void Release() | |
385 | + { | |
386 | + delta_ = (value_) * stepTime_ / (envelope_->decayTime); | |
387 | + status_ = EnvelopeStatus::Release; | |
388 | + } | |
389 | + | |
390 | + float Process() | |
391 | + { | |
392 | + switch (status_) | |
393 | + { | |
394 | + case EnvelopeStatus::Attack: | |
395 | + value_ += delta_; | |
396 | + if(value_ >= 1.0f) | |
397 | + { | |
398 | + value_ = 1.0f; | |
399 | + Decay(); | |
400 | + } | |
401 | + break; | |
402 | + case EnvelopeStatus::Decay: | |
403 | + value_ -= delta_; | |
404 | + if(value_ <= envelope_->sustainLevel) | |
405 | + { | |
406 | + value_ = envelope_->sustainLevel; | |
407 | + Sustain(); | |
408 | + } | |
409 | + break; | |
410 | + case EnvelopeStatus::Sustain: | |
411 | + { | |
412 | + value_ = envelope_->sustainLevel; | |
413 | + } | |
414 | + break; | |
415 | + case EnvelopeStatus::Release: | |
416 | + { | |
417 | + value_ -= delta_; | |
418 | + if(value_ <= 0.0f) | |
419 | + { | |
420 | + value_ = 0.0f; | |
421 | + } | |
422 | + status_ = EnvelopeStatus::End; | |
423 | + } | |
424 | + break; | |
425 | + } | |
426 | + return value_ * envelope_->gain; | |
427 | + } | |
428 | + | |
429 | + EnvelopeStatus GetStatus() | |
430 | + { | |
431 | + return status_; | |
432 | + } | |
433 | + private: | |
434 | + Envelope* envelope_; | |
435 | + EnvelopeStatus status_; | |
436 | + float delta_; | |
437 | + float stepTime_; | |
438 | + float time_; | |
439 | + float value_; | |
440 | + }; | |
441 | + | |
442 | + struct LFOController | |
443 | + { | |
444 | + LFOController() : lfo_(nullptr),value_(0.0f),stepTime_(0.0f) {}; | |
445 | + void SetLFO(LFO *lfo) | |
446 | + { | |
447 | + lfo_ = lfo; | |
448 | + } | |
449 | + void Init() | |
450 | + { | |
451 | + assert(lfo_ != nullptr); | |
452 | + }; | |
453 | + void Reset() | |
454 | + { | |
455 | + assert(lfo_ != nullptr); | |
456 | + } | |
457 | + void Process() | |
458 | + { | |
459 | + assert(lfo_ != nullptr); | |
460 | + }; | |
461 | + private: | |
462 | + LFO * lfo_; | |
463 | + EnvelopeController envelopeController_; | |
464 | + float value_; | |
465 | + float stepTime_; | |
466 | + }; | |
467 | + | |
468 | + typedef std::vector<WaveTable> WaveTablesType; | |
469 | + | |
470 | + struct Voice | |
471 | + { | |
472 | + | |
473 | + Voice(WaveTablesType& waveTables,float sampleRate) | |
474 | + : | |
475 | + timber_(nullptr), | |
476 | + waveTables_(waveTables), | |
477 | + noteOn_(false), | |
478 | + isFree_(true), | |
479 | + pitchOffset_(1.0f), | |
480 | + volumeOffset_(1.0f), | |
481 | + stepTime_(0.0f), | |
482 | + currentTime_(0.0f), | |
483 | + curentIndex_(0), | |
484 | + pan_(0.5f), | |
485 | + sampleRate_(sampleRate), | |
486 | + pitchDelta_(0.0f), | |
487 | + pitchCounter_(0.0f), | |
488 | + waveSize_(0), | |
489 | + waveTable_(nullptr) | |
490 | + {}; | |
491 | + | |
492 | + Voice(const Voice& src) | |
493 | + : | |
494 | + timber_(src.timber_), | |
495 | + waveTables_(src.waveTables_), | |
496 | + noteOn_(src.noteOn_), | |
497 | + isFree_(src.isFree_), | |
498 | + pitchOffset_(src.pitchOffset_), | |
499 | + volumeOffset_(src.volumeOffset_), | |
500 | + stepTime_(src.stepTime_), | |
501 | + currentTime_(src.currentTime_), | |
502 | + curentIndex_(src.curentIndex_), | |
503 | + pan_(src.pan_), | |
504 | + sampleRate_(src.sampleRate_), | |
505 | + pitchDelta_(src.pitchDelta_), | |
506 | + pitchCounter_(src.pitchCounter_), | |
507 | + waveSize_(src.waveSize_), | |
508 | + waveTable_(src.waveTable_), | |
509 | + ampEnv(src.ampEnv), | |
510 | + ampLFO(src.ampLFO), | |
511 | + filterEnv(src.filterEnv), | |
512 | + filterLFO(src.filterLFO), | |
513 | + pitchEnv(src.pitchEnv), | |
514 | + pitchLFO(src.pitchLFO), | |
515 | + panEnv(src.panEnv), | |
516 | + panLFO(src.panLFO) | |
517 | + { | |
518 | + | |
519 | + } | |
520 | + | |
521 | + void SetSampleRate(float sampleRate) | |
522 | + { | |
523 | + sampleRate_ = sampleRate; | |
524 | + } | |
525 | + | |
526 | + void SetTimber(Timber* timber) | |
527 | + { | |
528 | + timber_ = timber; | |
529 | + waveTable_ = &(waveTables_[timber_->waveTableNo]); | |
530 | + ampEnv.Init(&(timber_->amplitude.envelope),sampleRate_); | |
531 | + filterEnv.Init(&(timber_->filter.envelope),sampleRate_); | |
532 | + pitchEnv.Init(&(timber_->pitch.envelope),sampleRate_); | |
533 | + panEnv.Init(&(timber_->pitch.envelope),sampleRate_); | |
534 | + } | |
535 | + | |
536 | + void Process(float* buffer) // 1サンプル分の処理を行う | |
537 | + { | |
538 | + // assert(!isFree_); | |
539 | + | |
540 | + //currentTime_ += stepTime_; | |
541 | + | |
542 | + //pitchCounter_ += pitchDelta_ * pitchOffset_ * waveTable_->BasePitch() * pitchEnv.Process() * timber_->pitch.pitch; | |
543 | + | |
544 | + //if(pitchCounter_ >= (waveSize_ - 1.0f)) | |
545 | + //{ | |
546 | + // pitchCounter_ -= (waveSize_ - 1.0f); | |
547 | + //} | |
548 | + | |
549 | + float waveData[2]; | |
550 | + | |
551 | + waveTable_->Process(waveData,pitchDelta_ * pitchOffset_ * waveTable_->BasePitch() * pitchEnv.Process() * timber_->pitch.pitch ); | |
552 | + | |
553 | + float volume = ampEnv.Process(); | |
554 | + if(volume > 1.0f) | |
555 | + { | |
556 | + volume = 1.0f; | |
557 | + } | |
558 | + | |
559 | + waveData[0] = waveData[0] * volume * volumeOffset_; | |
560 | + waveData[1] = waveData[1] * volume * volumeOffset_; | |
561 | + | |
562 | + // クリッピング | |
563 | + | |
564 | + //if(waveData > 1.0f) waveData = 1.0f; | |
565 | + //if(waveData < 1.0f) waveData = -1.0f; | |
566 | + | |
567 | + buffer[0] = waveData[0]; //* pan_; | |
568 | + buffer[1] = waveData[1]; //* (1.0f - pan_); | |
569 | + | |
570 | + if(!noteOn_ && ampEnv.GetStatus() == EnvelopeStatus::End) | |
571 | + { | |
572 | + isFree_ = true; | |
573 | + } | |
574 | + } | |
575 | + | |
576 | + bool isFree() {return isFree_;} | |
577 | + | |
578 | + void NoteOn(float pitch,float volume) | |
579 | + { | |
580 | + if(!noteOn_){ | |
581 | + noteOn_ = true; | |
582 | + pitchOffset_ = pitch; | |
583 | + volumeOffset_ = volume; | |
584 | + stepTime_ = 1.0f / sampleRate_; | |
585 | + pitchDelta_ = waveTable_->SampleRate() * ((float)waveTable_->WaveData().size()) / sampleRate_ ; | |
586 | + // waveSize_ = (float)waveTable_->waveData.size(); | |
587 | + currentTime_ = 0.0f; | |
588 | + curentIndex_ = 0; | |
589 | + pan_ = timber_->pan.pan; | |
590 | + pitchCounter_ = 0.0f; | |
591 | + ampEnv.Attack(); | |
592 | + filterEnv.Attack(); | |
593 | + pitchEnv.Attack(); | |
594 | + panEnv.Attack(); | |
595 | + } | |
596 | + } | |
597 | + | |
598 | + void NoteOff() | |
599 | + { | |
600 | + if(noteOn_) | |
601 | + { | |
602 | + noteOn_ = false; | |
603 | + ampEnv.Release(); | |
604 | + filterEnv.Release(); | |
605 | + pitchEnv.Release(); | |
606 | + panEnv.Release(); | |
607 | + } | |
608 | + } | |
609 | + | |
610 | + private: | |
611 | + Timber* timber_; | |
612 | + WaveTablesType& waveTables_; | |
613 | + bool noteOn_; | |
614 | + bool isFree_; | |
615 | + float pitchOffset_; | |
616 | + float volumeOffset_; | |
617 | + float stepTime_; | |
618 | + float currentTime_; | |
619 | + int curentIndex_; | |
620 | + float pan_; | |
621 | + float sampleRate_; | |
622 | + float pitchDelta_; | |
623 | + float pitchCounter_; | |
624 | + float waveSize_; | |
625 | + WaveTable *waveTable_; | |
626 | + EnvelopeController ampEnv; | |
627 | + LFOController ampLFO; | |
628 | + EnvelopeController filterEnv; | |
629 | + LFOController filterLFO; | |
630 | + EnvelopeController pitchEnv; | |
631 | + LFOController pitchLFO; | |
632 | + EnvelopeController panEnv; | |
633 | + LFOController panLFO; | |
634 | + }; | |
635 | + | |
636 | + typedef std::vector<Voice> VoicesType; | |
637 | + typedef std::vector<Timber> TimbersType; | |
638 | + typedef std::vector<Program> ProgramsType; | |
639 | + | |
640 | + private: | |
641 | + WAVEFORMATEXTENSIBLE format_; | |
642 | + ProgramsType programs_;// プリセット | |
643 | + TimbersType timbers_; | |
644 | + VoicesType voices_; // Max 64 Voices | |
645 | + WaveTablesType waveTable_; | |
646 | + }; | |
647 | + | |
648 | + WaveTableSynth::WaveTableSynth() : impl_(new WaveTableSynth::impl()){}; | |
649 | + | |
650 | + WaveTableSynth::WaveTableSynth(WAVEFORMATEXTENSIBLE& format ) : impl_(new WaveTableSynth::impl(format)) | |
36 | 651 | { |
37 | 652 | } |
38 | 653 |
@@ -43,20 +658,11 @@ namespace sf { | ||
43 | 658 | |
44 | 659 | void WaveTableSynth::ProcessBuffer(boost::shared_array<float> arr,int bufferSize) |
45 | 660 | { |
46 | - // サイン波の生成 | |
47 | - | |
48 | - static float sampleIncrement = (440.0f /* Hz */ * (M_PI * 2.0f)) / (float)format_.Format.nSamplesPerSec; | |
49 | - static float theta = 0.0f; | |
661 | + impl_->ProcessBuffer(arr,bufferSize); | |
662 | + } | |
50 | 663 | |
51 | - for (size_t i = 0 ; i < bufferSize ; ++i) | |
52 | - { | |
53 | - float sinValue = sinf( theta ); | |
54 | - int offset = i * format_.Format.nChannels; | |
55 | - for(size_t j = 0 ;j < format_.Format.nChannels; j++) | |
56 | - { | |
57 | - arr[offset + j] = sinValue; | |
58 | - } | |
59 | - theta += sampleIncrement; | |
60 | - } | |
664 | + void WaveTableSynth::Restart() | |
665 | + { | |
666 | + impl_->Restart(); | |
61 | 667 | } |
62 | 668 | } |
@@ -3,70 +3,13 @@ | ||
3 | 3 | namespace sf { |
4 | 4 | struct WaveTableSynth |
5 | 5 | { |
6 | - WaveTableSynth(){}; | |
6 | + WaveTableSynth(); | |
7 | 7 | explicit WaveTableSynth(WAVEFORMATEXTENSIBLE& format); |
8 | 8 | ~WaveTableSynth(); |
9 | - | |
10 | - void Restart(){}; | |
11 | - | |
9 | + void Restart(); | |
12 | 10 | void ProcessBuffer(boost::shared_array<float> arr,int bufferSize); |
13 | - | |
14 | - struct Envelope | |
15 | - { | |
16 | - float attack_time; | |
17 | - float decay_time; | |
18 | - float sustain_time; | |
19 | - float suatain_level; | |
20 | - float release_time; | |
21 | - }; | |
22 | - | |
23 | - struct LFO | |
24 | - { | |
25 | - float freq; | |
26 | - float level; | |
27 | - Envelope envelope; | |
28 | - }; | |
29 | - | |
30 | - | |
31 | - struct Filter | |
32 | - { | |
33 | - int type; | |
34 | - float level; | |
35 | - float resonance; | |
36 | - Envelope envelope; | |
37 | - LFO lfo; | |
38 | - }; | |
39 | - | |
40 | - struct Amplitude | |
41 | - { | |
42 | - float gain; | |
43 | - Envelope envelope; | |
44 | - LFO lfo; | |
45 | - }; | |
46 | - | |
47 | - struct Pitch { | |
48 | - float pitch; | |
49 | - Envelope envelope; | |
50 | - LFO lfo; | |
51 | - }; | |
52 | - | |
53 | - struct Timber | |
54 | - { | |
55 | - std::vector<float> waveTable; | |
56 | - Amplitude amplitude; | |
57 | - Filter filter; | |
58 | - Pitch pitch; | |
59 | - }; | |
60 | - | |
61 | - struct Voice | |
62 | - { | |
63 | - Timber* timber_; | |
64 | - float pitch_; | |
65 | - }; | |
66 | - | |
67 | 11 | private: |
68 | - WAVEFORMATEXTENSIBLE format_; | |
69 | - Voice Voices_[64]; // 64 Voices | |
70 | - ; | |
12 | + struct impl; | |
13 | + std::unique_ptr<impl> impl_; | |
71 | 14 | }; |
72 | 15 | } |
@@ -45,7 +45,7 @@ | ||
45 | 45 | #include "boost/format.hpp" |
46 | 46 | #include "boost/lexical_cast.hpp" |
47 | 47 | #include "boost/shared_array.hpp" |
48 | -#include "boost/ptr_vector.hpp" | |
48 | +#include "boost/ptr_container/ptr_array.hpp" | |
49 | 49 | |
50 | 50 | #include "sf_com.h" |
51 | 51 | #include "sf_memory.h" |