1 /*
2 * Copyright (C) 2018-2020 Rerrah
3 *
4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation
6 * files (the "Software"), to deal in the Software without
7 * restriction, including without limitation the rights to use,
8 * copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following
11 * conditions:
12 *
13 * The above copyright notice and this permission notice shall be
14 * included in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 * OTHER DEALINGS IN THE SOFTWARE.
24 */
25
26 #include "bamboo_tracker.hpp"
27 #include <algorithm>
28 #include <utility>
29 #include <unordered_set>
30 #include <exception>
31 #include <unordered_map>
32 #include "commands.hpp"
33 #include "io_handlers.hpp"
34 #include "bank.hpp"
35 #include "song_length_calculator.hpp"
36
37 const uint32_t BambooTracker::CHIP_CLOCK = 3993600 * 2;
38
BambooTracker(std::weak_ptr<Configuration> config)39 BambooTracker::BambooTracker(std::weak_ptr<Configuration> config)
40 : instMan_(std::make_shared<InstrumentsManager>(config.lock()->getOverwriteUnusedUneditedPropety())),
41 tickCounter_(std::make_shared<TickCounter>()),
42 mod_(std::make_shared<Module>()),
43 curOctave_(4),
44 curSongNum_(0),
45 curTrackNum_(0),
46 curOrderNum_(0),
47 curStepNum_(0),
48 curInstNum_(-1),
49 curVolume_(127),
50 mkOrder_(-1),
51 mkStep_(-1),
52 isFollowPlay_(true)
53 {
54 opnaCtrl_ = std::make_shared<OPNAController>(
55 static_cast<chip::Emu>(config.lock()->getEmulator()),
56 CHIP_CLOCK,
57 config.lock()->getSampleRate(),
58 config.lock()->getBufferLength());
59 setMasterVolume(config.lock()->getMixerVolumeMaster());
60 setMasterVolumeFM(config.lock()->getMixerVolumeFM());
61 setMasterVolumeSSG(config.lock()->getMixerVolumeSSG());
62
63 songStyle_ = mod_->getSong(curSongNum_).getStyle();
64 jamMan_ = std::make_unique<JamManager>();
65
66 playback_ = std::make_unique<PlaybackManager>(
67 opnaCtrl_, instMan_, tickCounter_, mod_, config.lock()->getRetrieveChannelState());
68
69 storeOnlyUsedSamples_ = config.lock()->getWriteOnlyUsedSamples();
70 volFMReversed_ = config.lock()->getReverseFMVolumeOrder();
71 }
72
73 /********** Change configuration **********/
changeConfiguration(std::weak_ptr<Configuration> config)74 void BambooTracker::changeConfiguration(std::weak_ptr<Configuration> config)
75 {
76 setStreamRate(static_cast<int>(config.lock()->getSampleRate()));
77 setStreamDuration(static_cast<int>(config.lock()->getBufferLength()));
78 setMasterVolume(config.lock()->getMixerVolumeMaster());
79 if (mod_->getMixerType() == MixerType::UNSPECIFIED) {
80 setMasterVolumeFM(config.lock()->getMixerVolumeFM());
81 setMasterVolumeSSG(config.lock()->getMixerVolumeSSG());
82 }
83 playback_->setChannelRetrieving(config.lock()->getRetrieveChannelState());
84 instMan_->setPropertyFindMode(config.lock()->getOverwriteUnusedUneditedPropety());
85 storeOnlyUsedSamples_ = config.lock()->getWriteOnlyUsedSamples();
86 volFMReversed_ = config.lock()->getReverseFMVolumeOrder();
87 }
88
89 /********** Current octave **********/
setCurrentOctave(int octave)90 void BambooTracker::setCurrentOctave(int octave)
91 {
92 curOctave_ = octave;
93 }
94
getCurrentOctave() const95 int BambooTracker::getCurrentOctave() const
96 {
97 return curOctave_;
98 }
99
100 /********** Current volume **********/
setCurrentVolume(int volume)101 void BambooTracker::setCurrentVolume(int volume)
102 {
103 curVolume_ = volume;
104 }
105
getCurrentVolume() const106 int BambooTracker::getCurrentVolume() const
107 {
108 return curVolume_;
109 }
110
111 /********** Current track **********/
setCurrentTrack(int num)112 void BambooTracker::setCurrentTrack(int num)
113 {
114 curTrackNum_ = num;
115 }
116
getCurrentTrackAttribute() const117 TrackAttribute BambooTracker::getCurrentTrackAttribute() const
118 {
119 TrackAttribute ret = songStyle_.trackAttribs.at(static_cast<size_t>(curTrackNum_));
120 return ret;
121 }
122
123 /********** Current instrument **********/
setCurrentInstrument(int n)124 void BambooTracker::setCurrentInstrument(int n)
125 {
126 curInstNum_ = n;
127 }
128
getCurrentInstrumentNumber() const129 int BambooTracker::getCurrentInstrumentNumber() const
130 {
131 return curInstNum_;
132 }
133
134 /********** Instrument edit **********/
addInstrument(int num,InstrumentType type,std::string name)135 void BambooTracker::addInstrument(int num, InstrumentType type, std::string name)
136 {
137 comMan_.invoke(std::make_unique<AddInstrumentCommand>(instMan_, num, type, name));
138 }
139
removeInstrument(int num)140 void BambooTracker::removeInstrument(int num)
141 {
142 comMan_.invoke(std::make_unique<RemoveInstrumentCommand>(instMan_, num));
143 }
144
getInstrument(int num)145 std::unique_ptr<AbstractInstrument> BambooTracker::getInstrument(int num)
146 {
147 std::shared_ptr<AbstractInstrument> inst = instMan_->getInstrumentSharedPtr(num);
148 if (inst == nullptr) return std::unique_ptr<AbstractInstrument>();
149 else return std::unique_ptr<AbstractInstrument>(inst->clone());
150 }
151
cloneInstrument(int num,int refNum)152 void BambooTracker::cloneInstrument(int num, int refNum)
153 {
154 comMan_.invoke(std::make_unique<cloneInstrumentCommand>(instMan_, num, refNum));
155 }
156
deepCloneInstrument(int num,int refNum)157 void BambooTracker::deepCloneInstrument(int num, int refNum)
158 {
159 comMan_.invoke(std::make_unique<DeepCloneInstrumentCommand>(instMan_, num, refNum));
160 }
161
swapInstruments(int a,int b,bool patternChange)162 void BambooTracker::swapInstruments(int a, int b, bool patternChange)
163 {
164 comMan_.invoke(std::make_unique<SwapInstrumentsCommand>(instMan_, mod_, a, b, curSongNum_, patternChange));
165 }
166
loadInstrument(BinaryContainer & container,std::string path,int instNum)167 void BambooTracker::loadInstrument(BinaryContainer& container, std::string path, int instNum)
168 {
169 auto inst = InstrumentIO::loadInstrument(container, path, instMan_, instNum);
170 comMan_.invoke(std::make_unique<AddInstrumentCommand>(
171 instMan_, std::unique_ptr<AbstractInstrument>(inst)));
172 }
173
saveInstrument(BinaryContainer & container,int instNum)174 void BambooTracker::saveInstrument(BinaryContainer& container, int instNum)
175 {
176 InstrumentIO::saveInstrument(container, instMan_, instNum);
177 }
178
importInstrument(const AbstractBank & bank,size_t index,int instNum)179 void BambooTracker::importInstrument(const AbstractBank &bank, size_t index, int instNum)
180 {
181 auto inst = bank.loadInstrument(index, instMan_, instNum);
182 comMan_.invoke(std::make_unique<AddInstrumentCommand>(
183 instMan_, std::unique_ptr<AbstractInstrument>(inst)));
184 }
185
exportInstruments(BinaryContainer & container,std::vector<int> instNums)186 void BambooTracker::exportInstruments(BinaryContainer& container, std::vector<int> instNums)
187 {
188 BankIO::saveBank(container, instNums, instMan_);
189 }
190
findFirstFreeInstrumentNumber() const191 int BambooTracker::findFirstFreeInstrumentNumber() const
192 {
193 return instMan_->findFirstFreeInstrument();
194 }
195
setInstrumentName(int num,std::string name)196 void BambooTracker::setInstrumentName(int num, std::string name)
197 {
198 comMan_.invoke(std::make_unique<ChangeInstrumentNameCommand>(instMan_, num, name));
199 }
200
clearAllInstrument()201 void BambooTracker::clearAllInstrument()
202 {
203 instMan_->clearAll();
204 }
205
getInstrumentIndices() const206 std::vector<int> BambooTracker::getInstrumentIndices() const
207 {
208 return instMan_->getInstrumentIndices();
209 }
210
getUnusedInstrumentIndices() const211 std::vector<int> BambooTracker::getUnusedInstrumentIndices() const
212 {
213 std::vector<int> unused;
214 std::unordered_set<int> regdInsts = mod_->getRegisterdInstruments();
215 for (auto& inst : instMan_->getInstrumentIndices()) {
216 if (!regdInsts.count(inst)) unused.push_back(inst);
217 }
218 return unused;
219 }
220
clearUnusedInstrumentProperties()221 void BambooTracker::clearUnusedInstrumentProperties()
222 {
223 instMan_->clearUnusedInstrumentProperties();
224 }
225
getInstrumentNames() const226 std::vector<std::string> BambooTracker::getInstrumentNames() const
227 {
228 return instMan_->getInstrumentNameList();
229 }
230
checkDuplicateInstruments() const231 std::vector<std::vector<int>> BambooTracker::checkDuplicateInstruments() const
232 {
233 return instMan_->checkDuplicateInstruments();
234 }
235
236 //--- FM
setEnvelopeFMParameter(int envNum,FMEnvelopeParameter param,int value)237 void BambooTracker::setEnvelopeFMParameter(int envNum, FMEnvelopeParameter param, int value)
238 {
239 instMan_->setEnvelopeFMParameter(envNum, param, value);
240 opnaCtrl_->updateInstrumentFMEnvelopeParameter(envNum, param);
241 }
242
setEnvelopeFMOperatorEnable(int envNum,int opNum,bool enable)243 void BambooTracker::setEnvelopeFMOperatorEnable(int envNum, int opNum, bool enable)
244 {
245 instMan_->setEnvelopeFMOperatorEnabled(envNum, opNum, enable);
246 opnaCtrl_->setInstrumentFMOperatorEnabled(envNum, opNum);
247 }
248
setInstrumentFMEnvelope(int instNum,int envNum)249 void BambooTracker::setInstrumentFMEnvelope(int instNum, int envNum)
250 {
251 instMan_->setInstrumentFMEnvelope(instNum, envNum);
252 opnaCtrl_->updateInstrumentFM(instNum);
253 }
254
getEnvelopeFMUsers(int envNum) const255 std::vector<int> BambooTracker::getEnvelopeFMUsers(int envNum) const
256 {
257 return instMan_->getEnvelopeFMUsers(envNum);
258 }
259
setLFOFMParameter(int lfoNum,FMLFOParameter param,int value)260 void BambooTracker::setLFOFMParameter(int lfoNum, FMLFOParameter param, int value)
261 {
262 instMan_->setLFOFMParameter(lfoNum, param, value);
263 opnaCtrl_->updateInstrumentFMLFOParameter(lfoNum, param);
264 }
265
setInstrumentFMLFOEnabled(int instNum,bool enabled)266 void BambooTracker::setInstrumentFMLFOEnabled(int instNum, bool enabled)
267 {
268 instMan_->setInstrumentFMLFOEnabled(instNum, enabled);
269 opnaCtrl_->updateInstrumentFM(instNum);
270 }
271
setInstrumentFMLFO(int instNum,int lfoNum)272 void BambooTracker::setInstrumentFMLFO(int instNum, int lfoNum)
273 {
274 instMan_->setInstrumentFMLFO(instNum, lfoNum);
275 opnaCtrl_->updateInstrumentFM(instNum);
276 }
277
getLFOFMUsers(int lfoNum) const278 std::vector<int> BambooTracker::getLFOFMUsers(int lfoNum) const
279 {
280 return instMan_->getLFOFMUsers(lfoNum);
281 }
282
addOperatorSequenceFMSequenceCommand(FMEnvelopeParameter param,int opSeqNum,int type,int data)283 void BambooTracker::addOperatorSequenceFMSequenceCommand(FMEnvelopeParameter param, int opSeqNum, int type, int data)
284 {
285 instMan_->addOperatorSequenceFMSequenceCommand(param, opSeqNum, type, data);
286 }
287
removeOperatorSequenceFMSequenceCommand(FMEnvelopeParameter param,int opSeqNum)288 void BambooTracker::removeOperatorSequenceFMSequenceCommand(FMEnvelopeParameter param, int opSeqNum)
289 {
290 instMan_->removeOperatorSequenceFMSequenceCommand(param, opSeqNum);
291 }
292
setOperatorSequenceFMSequenceCommand(FMEnvelopeParameter param,int opSeqNum,int cnt,int type,int data)293 void BambooTracker::setOperatorSequenceFMSequenceCommand(FMEnvelopeParameter param, int opSeqNum, int cnt, int type, int data)
294 {
295 instMan_->setOperatorSequenceFMSequenceCommand(param, opSeqNum, cnt, type, data);
296 }
297
setOperatorSequenceFMLoops(FMEnvelopeParameter param,int opSeqNum,std::vector<int> begins,std::vector<int> ends,std::vector<int> times)298 void BambooTracker::setOperatorSequenceFMLoops(FMEnvelopeParameter param, int opSeqNum, std::vector<int> begins, std::vector<int> ends, std::vector<int> times)
299 {
300 instMan_->setOperatorSequenceFMLoops(param, opSeqNum, std::move(begins), std::move(ends), std::move(times));
301 }
302
setOperatorSequenceFMRelease(FMEnvelopeParameter param,int opSeqNum,ReleaseType type,int begin)303 void BambooTracker::setOperatorSequenceFMRelease(FMEnvelopeParameter param, int opSeqNum, ReleaseType type, int begin)
304 {
305 instMan_->setOperatorSequenceFMRelease(param, opSeqNum, type, begin);
306 }
307
setInstrumentFMOperatorSequence(int instNum,FMEnvelopeParameter param,int opSeqNum)308 void BambooTracker::setInstrumentFMOperatorSequence(int instNum, FMEnvelopeParameter param, int opSeqNum)
309 {
310 instMan_->setInstrumentFMOperatorSequence(instNum, param, opSeqNum);
311 opnaCtrl_->updateInstrumentFM(instNum);
312 }
313
setInstrumentFMOperatorSequenceEnabled(int instNum,FMEnvelopeParameter param,bool enabled)314 void BambooTracker::setInstrumentFMOperatorSequenceEnabled(int instNum, FMEnvelopeParameter param, bool enabled)
315 {
316 instMan_->setInstrumentFMOperatorSequenceEnabled(instNum, param, enabled);
317 opnaCtrl_->updateInstrumentFM(instNum);
318 }
319
getOperatorSequenceFMUsers(FMEnvelopeParameter param,int opSeqNum) const320 std::vector<int> BambooTracker::getOperatorSequenceFMUsers(FMEnvelopeParameter param, int opSeqNum) const
321 {
322 return instMan_->getOperatorSequenceFMUsers(param, opSeqNum);
323 }
324
setArpeggioFMType(int arpNum,SequenceType type)325 void BambooTracker::setArpeggioFMType(int arpNum, SequenceType type)
326 {
327 instMan_->setArpeggioFMType(arpNum, type);
328 }
329
addArpeggioFMSequenceCommand(int arpNum,int type,int data)330 void BambooTracker::addArpeggioFMSequenceCommand(int arpNum, int type, int data)
331 {
332 instMan_->addArpeggioFMSequenceCommand(arpNum, type, data);
333 }
334
removeArpeggioFMSequenceCommand(int arpNum)335 void BambooTracker::removeArpeggioFMSequenceCommand(int arpNum)
336 {
337 instMan_->removeArpeggioFMSequenceCommand(arpNum);
338 }
339
setArpeggioFMSequenceCommand(int arpNum,int cnt,int type,int data)340 void BambooTracker::setArpeggioFMSequenceCommand(int arpNum, int cnt, int type, int data)
341 {
342 instMan_->setArpeggioFMSequenceCommand(arpNum, cnt, type, data);
343 }
344
setArpeggioFMLoops(int arpNum,std::vector<int> begins,std::vector<int> ends,std::vector<int> times)345 void BambooTracker::setArpeggioFMLoops(int arpNum, std::vector<int> begins, std::vector<int> ends, std::vector<int> times)
346 {
347 instMan_->setArpeggioFMLoops(arpNum, std::move(begins), std::move(ends), std::move(times));
348 }
349
setArpeggioFMRelease(int arpNum,ReleaseType type,int begin)350 void BambooTracker::setArpeggioFMRelease(int arpNum, ReleaseType type, int begin)
351 {
352 instMan_->setArpeggioFMRelease(arpNum, type, begin);
353 }
354
setInstrumentFMArpeggio(int instNum,FMOperatorType op,int arpNum)355 void BambooTracker::setInstrumentFMArpeggio(int instNum, FMOperatorType op, int arpNum)
356 {
357 instMan_->setInstrumentFMArpeggio(instNum, op, arpNum);
358 opnaCtrl_->updateInstrumentFM(instNum);
359 }
360
setInstrumentFMArpeggioEnabled(int instNum,FMOperatorType op,bool enabled)361 void BambooTracker::setInstrumentFMArpeggioEnabled(int instNum, FMOperatorType op, bool enabled)
362 {
363 instMan_->setInstrumentFMArpeggioEnabled(instNum, op, enabled);
364 opnaCtrl_->updateInstrumentFM(instNum);
365 }
366
getArpeggioFMUsers(int arpNum) const367 std::vector<int> BambooTracker::getArpeggioFMUsers(int arpNum) const
368 {
369 return instMan_->getArpeggioFMUsers(arpNum);
370 }
371
setPitchFMType(int ptNum,SequenceType type)372 void BambooTracker::setPitchFMType(int ptNum, SequenceType type)
373 {
374 instMan_->setPitchFMType(ptNum, type);
375 }
376
addPitchFMSequenceCommand(int ptNum,int type,int data)377 void BambooTracker::addPitchFMSequenceCommand(int ptNum, int type, int data)
378 {
379 instMan_->addPitchFMSequenceCommand(ptNum, type, data);
380 }
381
removePitchFMSequenceCommand(int ptNum)382 void BambooTracker::removePitchFMSequenceCommand(int ptNum)
383 {
384 instMan_->removePitchFMSequenceCommand(ptNum);
385 }
386
setPitchFMSequenceCommand(int ptNum,int cnt,int type,int data)387 void BambooTracker::setPitchFMSequenceCommand(int ptNum, int cnt, int type, int data)
388 {
389 instMan_->setPitchFMSequenceCommand(ptNum, cnt, type, data);
390 }
391
setPitchFMLoops(int ptNum,std::vector<int> begins,std::vector<int> ends,std::vector<int> times)392 void BambooTracker::setPitchFMLoops(int ptNum, std::vector<int> begins, std::vector<int> ends, std::vector<int> times)
393 {
394 instMan_->setPitchFMLoops(ptNum, std::move(begins), std::move(ends), std::move(times));
395 }
396
setPitchFMRelease(int ptNum,ReleaseType type,int begin)397 void BambooTracker::setPitchFMRelease(int ptNum, ReleaseType type, int begin)
398 {
399 instMan_->setPitchFMRelease(ptNum, type, begin);
400 }
401
setInstrumentFMPitch(int instNum,FMOperatorType op,int ptNum)402 void BambooTracker::setInstrumentFMPitch(int instNum, FMOperatorType op, int ptNum)
403 {
404 instMan_->setInstrumentFMPitch(instNum, op, ptNum);
405 opnaCtrl_->updateInstrumentFM(instNum);
406 }
407
setInstrumentFMPitchEnabled(int instNum,FMOperatorType op,bool enabled)408 void BambooTracker::setInstrumentFMPitchEnabled(int instNum, FMOperatorType op, bool enabled)
409 {
410 instMan_->setInstrumentFMPitchEnabled(instNum, op, enabled);
411 opnaCtrl_->updateInstrumentFM(instNum);
412 }
413
getPitchFMUsers(int ptNum) const414 std::vector<int> BambooTracker::getPitchFMUsers(int ptNum) const
415 {
416 return instMan_->getPitchFMUsers(ptNum);
417 }
418
setInstrumentFMEnvelopeResetEnabled(int instNum,FMOperatorType op,bool enabled)419 void BambooTracker::setInstrumentFMEnvelopeResetEnabled(int instNum, FMOperatorType op, bool enabled)
420 {
421 instMan_->setInstrumentFMEnvelopeResetEnabled(instNum, op, enabled);
422 opnaCtrl_->updateInstrumentFM(instNum);
423 }
424
425 //--- SSG
addWaveformSSGSequenceCommand(int wfNum,int type,int data)426 void BambooTracker::addWaveformSSGSequenceCommand(int wfNum, int type, int data)
427 {
428 instMan_->addWaveformSSGSequenceCommand(wfNum, type, data);
429 }
430
removeWaveformSSGSequenceCommand(int wfNum)431 void BambooTracker::removeWaveformSSGSequenceCommand(int wfNum)
432 {
433 instMan_->removeWaveformSSGSequenceCommand(wfNum);
434 }
435
setWaveformSSGSequenceCommand(int wfNum,int cnt,int type,int data)436 void BambooTracker::setWaveformSSGSequenceCommand(int wfNum, int cnt, int type, int data)
437 {
438 instMan_->setWaveformSSGSequenceCommand(wfNum, cnt, type, data);
439 }
440
setWaveformSSGLoops(int wfNum,std::vector<int> begins,std::vector<int> ends,std::vector<int> times)441 void BambooTracker::setWaveformSSGLoops(int wfNum, std::vector<int> begins, std::vector<int> ends, std::vector<int> times)
442 {
443 instMan_->setWaveformSSGLoops(wfNum, std::move(begins), std::move(ends), std::move(times));
444 }
445
setWaveformSSGRelease(int wfNum,ReleaseType type,int begin)446 void BambooTracker::setWaveformSSGRelease(int wfNum, ReleaseType type, int begin)
447 {
448 instMan_->setWaveformSSGRelease(wfNum, type, begin);
449 }
450
setInstrumentSSGWaveform(int instNum,int wfNum)451 void BambooTracker::setInstrumentSSGWaveform(int instNum, int wfNum)
452 {
453 instMan_->setInstrumentSSGWaveform(instNum, wfNum);
454 opnaCtrl_->updateInstrumentSSG(instNum);
455 }
456
setInstrumentSSGWaveformEnabled(int instNum,bool enabled)457 void BambooTracker::setInstrumentSSGWaveformEnabled(int instNum, bool enabled)
458 {
459 instMan_->setInstrumentSSGWaveformEnabled(instNum, enabled);
460 opnaCtrl_->updateInstrumentSSG(instNum);
461 }
462
getWaveformSSGUsers(int wfNum) const463 std::vector<int> BambooTracker::getWaveformSSGUsers(int wfNum) const
464 {
465 return instMan_->getWaveformSSGUsers(wfNum);
466 }
467
addToneNoiseSSGSequenceCommand(int tnNum,int type,int data)468 void BambooTracker::addToneNoiseSSGSequenceCommand(int tnNum, int type, int data)
469 {
470 instMan_->addToneNoiseSSGSequenceCommand(tnNum, type, data);
471 }
472
removeToneNoiseSSGSequenceCommand(int tnNum)473 void BambooTracker::removeToneNoiseSSGSequenceCommand(int tnNum)
474 {
475 instMan_->removeToneNoiseSSGSequenceCommand(tnNum);
476 }
477
setToneNoiseSSGSequenceCommand(int tnNum,int cnt,int type,int data)478 void BambooTracker::setToneNoiseSSGSequenceCommand(int tnNum, int cnt, int type, int data)
479 {
480 instMan_->setToneNoiseSSGSequenceCommand(tnNum, cnt, type, data);
481 }
482
setToneNoiseSSGLoops(int tnNum,std::vector<int> begins,std::vector<int> ends,std::vector<int> times)483 void BambooTracker::setToneNoiseSSGLoops(int tnNum, std::vector<int> begins, std::vector<int> ends, std::vector<int> times)
484 {
485 instMan_->setToneNoiseSSGLoops(tnNum, std::move(begins), std::move(ends), std::move(times));
486 }
487
setToneNoiseSSGRelease(int tnNum,ReleaseType type,int begin)488 void BambooTracker::setToneNoiseSSGRelease(int tnNum, ReleaseType type, int begin)
489 {
490 instMan_->setToneNoiseSSGRelease(tnNum, type, begin);
491 }
492
setInstrumentSSGToneNoise(int instNum,int tnNum)493 void BambooTracker::setInstrumentSSGToneNoise(int instNum, int tnNum)
494 {
495 instMan_->setInstrumentSSGToneNoise(instNum, tnNum);
496 opnaCtrl_->updateInstrumentSSG(instNum);
497 }
498
setInstrumentSSGToneNoiseEnabled(int instNum,bool enabled)499 void BambooTracker::setInstrumentSSGToneNoiseEnabled(int instNum, bool enabled)
500 {
501 instMan_->setInstrumentSSGToneNoiseEnabled(instNum, enabled);
502 opnaCtrl_->updateInstrumentSSG(instNum);
503 }
504
getToneNoiseSSGUsers(int tnNum) const505 std::vector<int> BambooTracker::getToneNoiseSSGUsers(int tnNum) const
506 {
507 return instMan_->getToneNoiseSSGUsers(tnNum);
508 }
509
addEnvelopeSSGSequenceCommand(int envNum,int type,int data)510 void BambooTracker::addEnvelopeSSGSequenceCommand(int envNum, int type, int data)
511 {
512 instMan_->addEnvelopeSSGSequenceCommand(envNum, type, data);
513 }
514
removeEnvelopeSSGSequenceCommand(int envNum)515 void BambooTracker::removeEnvelopeSSGSequenceCommand(int envNum)
516 {
517 instMan_->removeEnvelopeSSGSequenceCommand(envNum);
518 }
519
setEnvelopeSSGSequenceCommand(int envNum,int cnt,int type,int data)520 void BambooTracker::setEnvelopeSSGSequenceCommand(int envNum, int cnt, int type, int data)
521 {
522 instMan_->setEnvelopeSSGSequenceCommand(envNum, cnt, type, data);
523 }
524
setEnvelopeSSGLoops(int envNum,std::vector<int> begins,std::vector<int> ends,std::vector<int> times)525 void BambooTracker::setEnvelopeSSGLoops(int envNum, std::vector<int> begins, std::vector<int> ends, std::vector<int> times)
526 {
527 instMan_->setEnvelopeSSGLoops(envNum, std::move(begins), std::move(ends), std::move(times));
528 }
529
setEnvelopeSSGRelease(int envNum,ReleaseType type,int begin)530 void BambooTracker::setEnvelopeSSGRelease(int envNum, ReleaseType type, int begin)
531 {
532 instMan_->setEnvelopeSSGRelease(envNum, type, begin);
533 }
534
setInstrumentSSGEnvelope(int instNum,int envNum)535 void BambooTracker::setInstrumentSSGEnvelope(int instNum, int envNum)
536 {
537 instMan_->setInstrumentSSGEnvelope(instNum, envNum);
538 opnaCtrl_->updateInstrumentSSG(instNum);
539 }
540
setInstrumentSSGEnvelopeEnabled(int instNum,bool enabled)541 void BambooTracker::setInstrumentSSGEnvelopeEnabled(int instNum, bool enabled)
542 {
543 instMan_->setInstrumentSSGEnvelopeEnabled(instNum, enabled);
544 opnaCtrl_->updateInstrumentSSG(instNum);
545 }
546
getEnvelopeSSGUsers(int envNum) const547 std::vector<int> BambooTracker::getEnvelopeSSGUsers(int envNum) const
548 {
549 return instMan_->getEnvelopeSSGUsers(envNum);
550 }
551
setArpeggioSSGType(int arpNum,SequenceType type)552 void BambooTracker::setArpeggioSSGType(int arpNum, SequenceType type)
553 {
554 instMan_->setArpeggioSSGType(arpNum, type);
555 }
556
addArpeggioSSGSequenceCommand(int arpNum,int type,int data)557 void BambooTracker::addArpeggioSSGSequenceCommand(int arpNum, int type, int data)
558 {
559 instMan_->addArpeggioSSGSequenceCommand(arpNum, type, data);
560 }
561
removeArpeggioSSGSequenceCommand(int arpNum)562 void BambooTracker::removeArpeggioSSGSequenceCommand(int arpNum)
563 {
564 instMan_->removeArpeggioSSGSequenceCommand(arpNum);
565 }
566
setArpeggioSSGSequenceCommand(int arpNum,int cnt,int type,int data)567 void BambooTracker::setArpeggioSSGSequenceCommand(int arpNum, int cnt, int type, int data)
568 {
569 instMan_->setArpeggioSSGSequenceCommand(arpNum, cnt, type, data);
570 }
571
setArpeggioSSGLoops(int arpNum,std::vector<int> begins,std::vector<int> ends,std::vector<int> times)572 void BambooTracker::setArpeggioSSGLoops(int arpNum, std::vector<int> begins, std::vector<int> ends, std::vector<int> times)
573 {
574 instMan_->setArpeggioSSGLoops(arpNum, std::move(begins), std::move(ends), std::move(times));
575 }
576
setArpeggioSSGRelease(int arpNum,ReleaseType type,int begin)577 void BambooTracker::setArpeggioSSGRelease(int arpNum, ReleaseType type, int begin)
578 {
579 instMan_->setArpeggioSSGRelease(arpNum, type, begin);
580 }
581
setInstrumentSSGArpeggio(int instNum,int arpNum)582 void BambooTracker::setInstrumentSSGArpeggio(int instNum, int arpNum)
583 {
584 instMan_->setInstrumentSSGArpeggio(instNum, arpNum);
585 opnaCtrl_->updateInstrumentSSG(instNum);
586 }
587
setInstrumentSSGArpeggioEnabled(int instNum,bool enabled)588 void BambooTracker::setInstrumentSSGArpeggioEnabled(int instNum, bool enabled)
589 {
590 instMan_->setInstrumentSSGArpeggioEnabled(instNum, enabled);
591 opnaCtrl_->updateInstrumentSSG(instNum);
592 }
593
getArpeggioSSGUsers(int arpNum) const594 std::vector<int> BambooTracker::getArpeggioSSGUsers(int arpNum) const
595 {
596 return instMan_->getArpeggioSSGUsers(arpNum);
597 }
598
setPitchSSGType(int ptNum,SequenceType type)599 void BambooTracker::setPitchSSGType(int ptNum, SequenceType type)
600 {
601 instMan_->setPitchSSGType(ptNum, type);
602 }
603
addPitchSSGSequenceCommand(int ptNum,int type,int data)604 void BambooTracker::addPitchSSGSequenceCommand(int ptNum, int type, int data)
605 {
606 instMan_->addPitchSSGSequenceCommand(ptNum, type, data);
607 }
608
removePitchSSGSequenceCommand(int ptNum)609 void BambooTracker::removePitchSSGSequenceCommand(int ptNum)
610 {
611 instMan_->removePitchSSGSequenceCommand(ptNum);
612 }
613
setPitchSSGSequenceCommand(int ptNum,int cnt,int type,int data)614 void BambooTracker::setPitchSSGSequenceCommand(int ptNum, int cnt, int type, int data)
615 {
616 instMan_->setPitchSSGSequenceCommand(ptNum, cnt, type, data);
617 }
618
setPitchSSGLoops(int ptNum,std::vector<int> begins,std::vector<int> ends,std::vector<int> times)619 void BambooTracker::setPitchSSGLoops(int ptNum, std::vector<int> begins, std::vector<int> ends, std::vector<int> times)
620 {
621 instMan_->setPitchSSGLoops(ptNum, std::move(begins), std::move(ends), std::move(times));
622 }
623
setPitchSSGRelease(int ptNum,ReleaseType type,int begin)624 void BambooTracker::setPitchSSGRelease(int ptNum, ReleaseType type, int begin)
625 {
626 instMan_->setPitchSSGRelease(ptNum, type, begin);
627 }
628
setInstrumentSSGPitch(int instNum,int ptNum)629 void BambooTracker::setInstrumentSSGPitch(int instNum, int ptNum)
630 {
631 instMan_->setInstrumentSSGPitch(instNum, ptNum);
632 opnaCtrl_->updateInstrumentSSG(instNum);
633 }
634
setInstrumentSSGPitchEnabled(int instNum,bool enabled)635 void BambooTracker::setInstrumentSSGPitchEnabled(int instNum, bool enabled)
636 {
637 instMan_->setInstrumentSSGPitchEnabled(instNum, enabled);
638 opnaCtrl_->updateInstrumentSSG(instNum);
639 }
640
getPitchSSGUsers(int ptNum) const641 std::vector<int> BambooTracker::getPitchSSGUsers(int ptNum) const
642 {
643 return instMan_->getPitchSSGUsers(ptNum);
644 }
645
646 //--- ADPCM
getADPCMLimit() const647 size_t BambooTracker::getADPCMLimit() const
648 {
649 return opnaCtrl_->getDRAMSize();
650 }
651
652
getADPCMStoredSize() const653 size_t BambooTracker::getADPCMStoredSize() const
654 {
655 return opnaCtrl_->getADPCMStoredSize();
656 }
657
setSampleADPCMRootKeyNumber(int sampNum,int n)658 void BambooTracker::setSampleADPCMRootKeyNumber(int sampNum, int n)
659 {
660 instMan_->setSampleADPCMRootKeyNumber(sampNum, n);
661 // opnaCtrl is changed through refInstADPCM (shared_ptr)
662 }
663
getSampleADPCMRootKeyNumber(int sampNum) const664 int BambooTracker::getSampleADPCMRootKeyNumber(int sampNum) const
665 {
666 return instMan_->getSampleADPCMRootKeyNumber(sampNum);
667 }
668
setSampleADPCMRootDeltaN(int sampNum,int dn)669 void BambooTracker::setSampleADPCMRootDeltaN(int sampNum, int dn)
670 {
671 instMan_->setSampleADPCMRootDeltaN(sampNum, dn);
672 // opnaCtrl is changed through refInstADPCM (shared_ptr)
673 }
674
getSampleADPCMRootDeltaN(int sampNum) const675 int BambooTracker::getSampleADPCMRootDeltaN(int sampNum) const
676 {
677 return instMan_->getSampleADPCMRootDeltaN(sampNum);
678 }
679
setSampleADPCMRepeatEnabled(int sampNum,bool enabled)680 void BambooTracker::setSampleADPCMRepeatEnabled(int sampNum, bool enabled)
681 {
682 instMan_->setSampleADPCMRepeatEnabled(sampNum, enabled);
683 // opnaCtrl is changed through refInstADPCM (shared_ptr)
684 }
685
getSampleADPCMRepeatEnabled(int sampNum) const686 bool BambooTracker::getSampleADPCMRepeatEnabled(int sampNum) const
687 {
688 return instMan_->isSampleADPCMRepeatable(sampNum);
689 }
690
storeSampleADPCMRawSample(int sampNum,std::vector<uint8_t> sample)691 void BambooTracker::storeSampleADPCMRawSample(int sampNum, std::vector<uint8_t> sample)
692 {
693 instMan_->storeSampleADPCMRawSample(sampNum, sample);
694 }
695
getSampleADPCMRawSample(int sampNum) const696 std::vector<uint8_t> BambooTracker::getSampleADPCMRawSample(int sampNum) const
697 {
698 return instMan_->getSampleADPCMRawSample(sampNum);
699 }
700
clearSampleADPCMRawSample(int sampNum)701 void BambooTracker::clearSampleADPCMRawSample(int sampNum)
702 {
703 instMan_->clearSampleADPCMRawSample(sampNum);
704 }
705
assignSampleADPCMRawSamples()706 void BambooTracker::assignSampleADPCMRawSamples()
707 {
708 opnaCtrl_->clearSamplesADPCM();
709 std::vector<int> idcs = storeOnlyUsedSamples_ ? instMan_->getSampleADPCMValidIndices()
710 : instMan_->getSampleADPCMEntriedIndices();
711 for (auto sampNum : idcs) {
712 std::vector<size_t> addresses
713 = opnaCtrl_->storeSampleADPCM(instMan_->getSampleADPCMRawSample(sampNum));
714 instMan_->setSampleADPCMStartAddress(sampNum, addresses[0]);
715 instMan_->setSampleADPCMStopAddress(sampNum, addresses[1]);
716 }
717 }
718
getSampleADPCMStartAddress(int sampNum) const719 size_t BambooTracker::getSampleADPCMStartAddress(int sampNum) const
720 {
721 return instMan_->getSampleADPCMStartAddress(sampNum);
722 }
723
getSampleADPCMStopAddress(int sampNum) const724 size_t BambooTracker::getSampleADPCMStopAddress(int sampNum) const
725 {
726 return instMan_->getSampleADPCMStopAddress(sampNum);
727 }
728
setInstrumentADPCMSample(int instNum,int sampNum)729 void BambooTracker::setInstrumentADPCMSample(int instNum, int sampNum)
730 {
731 instMan_->setInstrumentADPCMSample(instNum, sampNum);
732 opnaCtrl_->updateInstrumentADPCM(instNum);
733 }
734
getSampleADPCMUsers(int sampNum) const735 std::vector<int> BambooTracker::getSampleADPCMUsers(int sampNum) const
736 {
737 return instMan_->getSampleADPCMUsers(sampNum);
738 }
739
addEnvelopeADPCMSequenceCommand(int envNum,int type,int data)740 void BambooTracker::addEnvelopeADPCMSequenceCommand(int envNum, int type, int data)
741 {
742 instMan_->addEnvelopeADPCMSequenceCommand(envNum, type, data);
743 }
744
removeEnvelopeADPCMSequenceCommand(int envNum)745 void BambooTracker::removeEnvelopeADPCMSequenceCommand(int envNum)
746 {
747 instMan_->removeEnvelopeADPCMSequenceCommand(envNum);
748 }
749
setEnvelopeADPCMSequenceCommand(int envNum,int cnt,int type,int data)750 void BambooTracker::setEnvelopeADPCMSequenceCommand(int envNum, int cnt, int type, int data)
751 {
752 instMan_->setEnvelopeADPCMSequenceCommand(envNum, cnt, type, data);
753 }
754
setEnvelopeADPCMLoops(int envNum,std::vector<int> begins,std::vector<int> ends,std::vector<int> times)755 void BambooTracker::setEnvelopeADPCMLoops(int envNum, std::vector<int> begins, std::vector<int> ends, std::vector<int> times)
756 {
757 instMan_->setEnvelopeADPCMLoops(envNum, std::move(begins), std::move(ends), std::move(times));
758 }
759
setEnvelopeADPCMRelease(int envNum,ReleaseType type,int begin)760 void BambooTracker::setEnvelopeADPCMRelease(int envNum, ReleaseType type, int begin)
761 {
762 instMan_->setEnvelopeADPCMRelease(envNum, type, begin);
763 }
764
setInstrumentADPCMEnvelope(int instNum,int envNum)765 void BambooTracker::setInstrumentADPCMEnvelope(int instNum, int envNum)
766 {
767 instMan_->setInstrumentADPCMEnvelope(instNum, envNum);
768 opnaCtrl_->updateInstrumentADPCM(instNum);
769 }
770
setInstrumentADPCMEnvelopeEnabled(int instNum,bool enabled)771 void BambooTracker::setInstrumentADPCMEnvelopeEnabled(int instNum, bool enabled)
772 {
773 instMan_->setInstrumentADPCMEnvelopeEnabled(instNum, enabled);
774 opnaCtrl_->updateInstrumentADPCM(instNum);
775 }
776
getEnvelopeADPCMUsers(int envNum) const777 std::vector<int> BambooTracker::getEnvelopeADPCMUsers(int envNum) const
778 {
779 return instMan_->getEnvelopeADPCMUsers(envNum);
780 }
781
setArpeggioADPCMType(int arpNum,SequenceType type)782 void BambooTracker::setArpeggioADPCMType(int arpNum, SequenceType type)
783 {
784 instMan_->setArpeggioADPCMType(arpNum, type);
785 }
786
addArpeggioADPCMSequenceCommand(int arpNum,int type,int data)787 void BambooTracker::addArpeggioADPCMSequenceCommand(int arpNum, int type, int data)
788 {
789 instMan_->addArpeggioADPCMSequenceCommand(arpNum, type, data);
790 }
791
removeArpeggioADPCMSequenceCommand(int arpNum)792 void BambooTracker::removeArpeggioADPCMSequenceCommand(int arpNum)
793 {
794 instMan_->removeArpeggioADPCMSequenceCommand(arpNum);
795 }
796
setArpeggioADPCMSequenceCommand(int arpNum,int cnt,int type,int data)797 void BambooTracker::setArpeggioADPCMSequenceCommand(int arpNum, int cnt, int type, int data)
798 {
799 instMan_->setArpeggioADPCMSequenceCommand(arpNum, cnt, type, data);
800 }
801
setArpeggioADPCMLoops(int arpNum,std::vector<int> begins,std::vector<int> ends,std::vector<int> times)802 void BambooTracker::setArpeggioADPCMLoops(int arpNum, std::vector<int> begins, std::vector<int> ends, std::vector<int> times)
803 {
804 instMan_->setArpeggioADPCMLoops(arpNum, std::move(begins), std::move(ends), std::move(times));
805 }
806
setArpeggioADPCMRelease(int arpNum,ReleaseType type,int begin)807 void BambooTracker::setArpeggioADPCMRelease(int arpNum, ReleaseType type, int begin)
808 {
809 instMan_->setArpeggioADPCMRelease(arpNum, type, begin);
810 }
811
setInstrumentADPCMArpeggio(int instNum,int arpNum)812 void BambooTracker::setInstrumentADPCMArpeggio(int instNum, int arpNum)
813 {
814 instMan_->setInstrumentADPCMArpeggio(instNum, arpNum);
815 opnaCtrl_->updateInstrumentADPCM(instNum);
816 }
817
setInstrumentADPCMArpeggioEnabled(int instNum,bool enabled)818 void BambooTracker::setInstrumentADPCMArpeggioEnabled(int instNum, bool enabled)
819 {
820 instMan_->setInstrumentADPCMArpeggioEnabled(instNum, enabled);
821 opnaCtrl_->updateInstrumentADPCM(instNum);
822 }
823
getArpeggioADPCMUsers(int arpNum) const824 std::vector<int> BambooTracker::getArpeggioADPCMUsers(int arpNum) const
825 {
826 return instMan_->getArpeggioADPCMUsers(arpNum);
827 }
828
setPitchADPCMType(int ptNum,SequenceType type)829 void BambooTracker::setPitchADPCMType(int ptNum, SequenceType type)
830 {
831 instMan_->setPitchADPCMType(ptNum, type);
832 }
833
addPitchADPCMSequenceCommand(int ptNum,int type,int data)834 void BambooTracker::addPitchADPCMSequenceCommand(int ptNum, int type, int data)
835 {
836 instMan_->addPitchADPCMSequenceCommand(ptNum, type, data);
837 }
838
removePitchADPCMSequenceCommand(int ptNum)839 void BambooTracker::removePitchADPCMSequenceCommand(int ptNum)
840 {
841 instMan_->removePitchADPCMSequenceCommand(ptNum);
842 }
843
setPitchADPCMSequenceCommand(int ptNum,int cnt,int type,int data)844 void BambooTracker::setPitchADPCMSequenceCommand(int ptNum, int cnt, int type, int data)
845 {
846 instMan_->setPitchADPCMSequenceCommand(ptNum, cnt, type, data);
847 }
848
setPitchADPCMLoops(int ptNum,std::vector<int> begins,std::vector<int> ends,std::vector<int> times)849 void BambooTracker::setPitchADPCMLoops(int ptNum, std::vector<int> begins, std::vector<int> ends, std::vector<int> times)
850 {
851 instMan_->setPitchADPCMLoops(ptNum, std::move(begins), std::move(ends), std::move(times));
852 }
853
setPitchADPCMRelease(int ptNum,ReleaseType type,int begin)854 void BambooTracker::setPitchADPCMRelease(int ptNum, ReleaseType type, int begin)
855 {
856 instMan_->setPitchADPCMRelease(ptNum, type, begin);
857 }
858
setInstrumentADPCMPitch(int instNum,int ptNum)859 void BambooTracker::setInstrumentADPCMPitch(int instNum, int ptNum)
860 {
861 instMan_->setInstrumentADPCMPitch(instNum, ptNum);
862 opnaCtrl_->updateInstrumentADPCM(instNum);
863 }
864
setInstrumentADPCMPitchEnabled(int instNum,bool enabled)865 void BambooTracker::setInstrumentADPCMPitchEnabled(int instNum, bool enabled)
866 {
867 instMan_->setInstrumentADPCMPitchEnabled(instNum, enabled);
868 opnaCtrl_->updateInstrumentADPCM(instNum);
869 }
870
getPitchADPCMUsers(int ptNum) const871 std::vector<int> BambooTracker::getPitchADPCMUsers(int ptNum) const
872 {
873 return instMan_->getPitchADPCMUsers(ptNum);
874 }
875
876 //--- Drumkit
setInstrumentDrumkitSample(int instNum,int key,int sampNum)877 void BambooTracker::setInstrumentDrumkitSample(int instNum, int key, int sampNum)
878 {
879 instMan_->setInstrumentDrumkitSamples(instNum, key, sampNum);
880 opnaCtrl_->updateInstrumentDrumkit(instNum, key);
881 }
882
setInstrumentDrumkitSampleEnabled(int instNum,int key,bool enabled)883 void BambooTracker::setInstrumentDrumkitSampleEnabled(int instNum, int key, bool enabled)
884 {
885 instMan_->setInstrumentDrumkitSamplesEnabled(instNum, key, enabled);
886 opnaCtrl_->updateInstrumentADPCM(instNum);
887 }
888
setInstrumentDrumkitPitch(int instNum,int key,int pitch)889 void BambooTracker::setInstrumentDrumkitPitch(int instNum, int key, int pitch)
890 {
891 instMan_->setInstrumentDrumkitPitch(instNum, key, pitch);
892 opnaCtrl_->updateInstrumentDrumkit(instNum, key);
893 }
894
895 /********** Song edit **********/
getCurrentSongNumber() const896 int BambooTracker::getCurrentSongNumber() const
897 {
898 return curSongNum_;
899 }
900
setCurrentSongNumber(int num)901 void BambooTracker::setCurrentSongNumber(int num)
902 {
903 curSongNum_ = num;
904 curTrackNum_ = 0;
905 curOrderNum_ = 0;
906 curStepNum_ = 0;
907 mkOrder_ = -1;
908 mkStep_ = -1;
909
910 auto& song = mod_->getSong(curSongNum_);
911 songStyle_ = song.getStyle();
912
913 playback_->setSong(mod_, curSongNum_);
914
915 /*jamMan_->clear();*/
916
917 // Reset
918 opnaCtrl_->reset();
919 opnaCtrl_->setMode(songStyle_.type);
920 tickCounter_->resetCount();
921 tickCounter_->setTempo(song.getTempo());
922 tickCounter_->setSpeed(song.getSpeed());
923 tickCounter_->setGroove(mod_->getGroove(song.getGroove()).getSequence());
924 tickCounter_->setGrooveTrigger(song.isUsedTempo() ? GrooveTrigger::Invalid
925 : GrooveTrigger::ValidByGlobal);
926
927 std::unordered_map<SoundSource, int> pairs = {
928 { SoundSource::FM, getFMChannelCount(songStyle_.type) },
929 { SoundSource::SSG, 3 },
930 { SoundSource::RHYTHM, 6 },
931 { SoundSource::ADPCM, 1 },
932 };
933 for (auto& pair : pairs) {
934 muteState_[pair.first] = std::vector<bool>(pair.second, false);
935 for (int i = 0; i < pair.second; ++i) opnaCtrl_->setMuteState(pair.first, i, false);
936 }
937 }
938
939 /********** Order edit **********/
getCurrentOrderNumber() const940 int BambooTracker::getCurrentOrderNumber() const
941 {
942 return curOrderNum_;
943 }
944
setCurrentOrderNumber(int num)945 void BambooTracker::setCurrentOrderNumber(int num)
946 {
947 curOrderNum_ = num;
948 }
949
950 /********** Pattern edit **********/
getCurrentStepNumber() const951 int BambooTracker::getCurrentStepNumber() const
952 {
953 return curStepNum_;
954 }
955
setCurrentStepNumber(int num)956 void BambooTracker::setCurrentStepNumber(int num)
957 {
958 curStepNum_ = num;
959 }
960
961 /********** Undo-Redo **********/
undo()962 void BambooTracker::undo()
963 {
964 comMan_.undo();
965 }
966
redo()967 void BambooTracker::redo()
968 {
969 comMan_.redo();
970 }
971
clearCommandHistory()972 void BambooTracker::clearCommandHistory()
973 {
974 comMan_.clear();
975 }
976
977 /********** Jam mode **********/
toggleJamMode()978 void BambooTracker::toggleJamMode()
979 {
980 if (jamMan_->toggleJamMode() && !isPlaySong()) {
981 jamMan_->polyphonic(true);
982 }
983 else {
984 jamMan_->polyphonic(false);
985 }
986 }
987
isJamMode() const988 bool BambooTracker::isJamMode() const
989 {
990 return jamMan_->isJamMode();
991 }
992
jamKeyOn(JamKey key,bool volumeSet)993 void BambooTracker::jamKeyOn(JamKey key, bool volumeSet)
994 {
995 int keyNum = octaveAndNoteToNoteNumber(curOctave_, JamManager::jamKeyToNote(key));
996 const TrackAttribute& attrib = songStyle_.trackAttribs[static_cast<size_t>(curTrackNum_)];
997 funcJamKeyOn(key, keyNum, attrib, volumeSet);
998 }
999
jamKeyOn(int keyNum,bool volumeSet)1000 void BambooTracker::jamKeyOn(int keyNum, bool volumeSet)
1001 {
1002 const TrackAttribute& attrib = songStyle_.trackAttribs[static_cast<size_t>(curTrackNum_)];
1003 funcJamKeyOn(JamKey::MidiKey, keyNum, attrib, volumeSet);
1004 }
1005
jamKeyOnForced(JamKey key,SoundSource src,bool volumeSet,std::shared_ptr<AbstractInstrument> inst)1006 void BambooTracker::jamKeyOnForced(JamKey key, SoundSource src, bool volumeSet, std::shared_ptr<AbstractInstrument> inst)
1007 {
1008 int keyNum = octaveAndNoteToNoteNumber(curOctave_, JamManager::jamKeyToNote(key));
1009 auto it = std::find_if(songStyle_.trackAttribs.begin(), songStyle_.trackAttribs.end(),
1010 [src](TrackAttribute& attrib) { return attrib.source == src; });
1011 funcJamKeyOn(key, keyNum, *it, volumeSet, inst);
1012 }
1013
jamKeyOnForced(int keyNum,SoundSource src,bool volumeSet,std::shared_ptr<AbstractInstrument> inst)1014 void BambooTracker::jamKeyOnForced(int keyNum, SoundSource src, bool volumeSet, std::shared_ptr<AbstractInstrument> inst)
1015 {
1016 auto it = std::find_if(songStyle_.trackAttribs.begin(), songStyle_.trackAttribs.end(),
1017 [src](TrackAttribute& attrib) { return attrib.source == src; });
1018 funcJamKeyOn(JamKey::MidiKey, keyNum, *it, volumeSet, inst);
1019 }
1020
funcJamKeyOn(JamKey key,int keyNum,const TrackAttribute & attrib,bool volumeSet,std::shared_ptr<AbstractInstrument> inst)1021 void BambooTracker::funcJamKeyOn(JamKey key, int keyNum, const TrackAttribute& attrib, bool volumeSet,
1022 std::shared_ptr<AbstractInstrument> inst)
1023 {
1024 if (playback_->isPlayingStep()) playback_->stopPlaySong(); // Reset
1025
1026 if (attrib.source == SoundSource::RHYTHM) {
1027 if (volumeSet)
1028 opnaCtrl_->setVolumeRhythm(attrib.channelInSource, std::min(curVolume_, 0x1f));
1029 opnaCtrl_->setKeyOnFlagRhythm(attrib.channelInSource);
1030 opnaCtrl_->updateRegisterStates();
1031 }
1032 else {
1033 std::vector<JamKeyData>&& list = jamMan_->keyOn(key, attrib.channelInSource, attrib.source, keyNum);
1034 if (list.size() == 2) { // Key off
1035 JamKeyData& offData = list[1];
1036 switch (offData.source) {
1037 case SoundSource::FM:
1038 if (songStyle_.type == SongType::FM3chExpanded && offData.channelInSource == 2) {
1039 opnaCtrl_->keyOffFM(2, true);
1040 opnaCtrl_->keyOffFM(6, true);
1041 opnaCtrl_->keyOffFM(7, true);
1042 opnaCtrl_->keyOffFM(8, true);
1043 }
1044 else {
1045 opnaCtrl_->keyOffFM(offData.channelInSource, true);
1046 }
1047 break;
1048 case SoundSource::SSG:
1049 opnaCtrl_->keyOffSSG(offData.channelInSource, true);
1050 break;
1051 case SoundSource::ADPCM:
1052 opnaCtrl_->keyOffADPCM(true);
1053 break;
1054 default:
1055 break;
1056 }
1057 }
1058
1059 if (!inst) { // Use current instrument if not specified
1060 inst = instMan_->getInstrumentSharedPtr(curInstNum_);
1061 }
1062 JamKeyData& onData = list.front();
1063
1064 Note note;
1065 int octave, pitch;
1066 if (key == JamKey::MidiKey) {
1067 auto octNote = noteNumberToOctaveAndNote(onData.keyNum);
1068 note = octNote.second;
1069 octave = octNote.first;
1070 }
1071 else {
1072 note = JamManager::jamKeyToNote(onData.key);
1073 octave = JamManager::calcOctave(curOctave_, onData.key);
1074 if (octave > 7) { // Tone range check
1075 octave = 7;
1076 note = Note::B;
1077 }
1078 }
1079 pitch = 0;
1080
1081 switch (onData.source) {
1082 case SoundSource::FM:
1083 if (auto fm = std::dynamic_pointer_cast<InstrumentFM>(inst))
1084 opnaCtrl_->setInstrumentFM(onData.channelInSource, fm);
1085 if (volumeSet) {
1086 int vol;
1087 if (volFMReversed_) vol = (curVolume_ < 0x80) ? (0x7f - curVolume_) : 0;
1088 else vol = std::min(curVolume_, 0x7f);
1089 opnaCtrl_->setVolumeFM(onData.channelInSource, vol);
1090 }
1091 if (songStyle_.type == SongType::FM3chExpanded && onData.channelInSource == 2) {
1092 opnaCtrl_->keyOnFM(2, note, octave, pitch, true);
1093 opnaCtrl_->keyOnFM(6, note, octave, pitch, true);
1094 opnaCtrl_->keyOnFM(7, note, octave, pitch, true);
1095 opnaCtrl_->keyOnFM(8, note, octave, pitch, true);
1096 }
1097 else {
1098 opnaCtrl_->keyOnFM(onData.channelInSource, note, octave, pitch, true);
1099 }
1100 break;
1101 case SoundSource::SSG:
1102 if (auto ssg = std::dynamic_pointer_cast<InstrumentSSG>(inst))
1103 opnaCtrl_->setInstrumentSSG(onData.channelInSource, ssg);
1104 if (volumeSet)
1105 opnaCtrl_->setVolumeSSG(onData.channelInSource, std::min(curVolume_, 0xf));
1106 opnaCtrl_->keyOnSSG(onData.channelInSource, note, octave, pitch, true);
1107 break;
1108 case SoundSource::ADPCM:
1109 if (auto adpcm = std::dynamic_pointer_cast<InstrumentADPCM>(inst))
1110 opnaCtrl_->setInstrumentADPCM(adpcm);
1111 else if (auto kit = std::dynamic_pointer_cast<InstrumentDrumkit>(inst))
1112 opnaCtrl_->setInstrumentDrumkit(kit);
1113 if (volumeSet) opnaCtrl_->setVolumeADPCM(curVolume_);
1114 opnaCtrl_->keyOnADPCM(note, octave, pitch, true);
1115 break;
1116 default:
1117 break;
1118 }
1119 }
1120 }
1121
jamKeyOff(JamKey key)1122 void BambooTracker::jamKeyOff(JamKey key)
1123 {
1124 int keyNum = octaveAndNoteToNoteNumber(curOctave_, JamManager::jamKeyToNote(key));
1125 const TrackAttribute& attrib = songStyle_.trackAttribs[static_cast<size_t>(curTrackNum_)];
1126 funcJamKeyOff(key, keyNum, attrib);
1127 }
1128
jamKeyOff(int keyNum)1129 void BambooTracker::jamKeyOff(int keyNum)
1130 {
1131 const TrackAttribute& attrib = songStyle_.trackAttribs[static_cast<size_t>(curTrackNum_)];
1132 funcJamKeyOff(JamKey::MidiKey, keyNum, attrib);
1133 }
1134
jamKeyOffForced(JamKey key,SoundSource src)1135 void BambooTracker::jamKeyOffForced(JamKey key, SoundSource src)
1136 {
1137 int keyNum = octaveAndNoteToNoteNumber(curOctave_, JamManager::jamKeyToNote(key));
1138 auto it = std::find_if(songStyle_.trackAttribs.begin(), songStyle_.trackAttribs.end(),
1139 [src](TrackAttribute& attrib) { return attrib.source == src; });
1140 funcJamKeyOff(key, keyNum, *it);
1141 }
1142
jamKeyOffForced(int keyNum,SoundSource src)1143 void BambooTracker::jamKeyOffForced(int keyNum, SoundSource src)
1144 {
1145 auto it = std::find_if(songStyle_.trackAttribs.begin(), songStyle_.trackAttribs.end(),
1146 [src](TrackAttribute& attrib) { return attrib.source == src; });
1147 funcJamKeyOff(JamKey::MidiKey, keyNum, *it);
1148 }
1149
funcJamKeyOff(JamKey key,int keyNum,const TrackAttribute & attrib)1150 void BambooTracker::funcJamKeyOff(JamKey key, int keyNum, const TrackAttribute& attrib)
1151 {
1152 if (attrib.source == SoundSource::RHYTHM) {
1153 opnaCtrl_->setKeyOffFlagRhythm(attrib.channelInSource);
1154 opnaCtrl_->updateRegisterStates();
1155 }
1156 else {
1157 JamKeyData&& data = jamMan_->keyOff(key, keyNum);
1158
1159 if (data.channelInSource > -1) { // Key still sound
1160 switch (data.source) {
1161 case SoundSource::FM:
1162 if (songStyle_.type == SongType::FM3chExpanded && data.channelInSource == 2) {
1163 opnaCtrl_->keyOffFM(2, true);
1164 opnaCtrl_->keyOffFM(6, true);
1165 opnaCtrl_->keyOffFM(7, true);
1166 opnaCtrl_->keyOffFM(8, true);
1167 }
1168 else {
1169 opnaCtrl_->keyOffFM(data.channelInSource, true);
1170 }
1171 break;
1172 case SoundSource::SSG:
1173 opnaCtrl_->keyOffSSG(data.channelInSource, true);
1174 break;
1175 case SoundSource::ADPCM:
1176 opnaCtrl_->keyOffADPCM(true);
1177 break;
1178 default:
1179 break;
1180 }
1181 }
1182 }
1183 }
1184
assignADPCMBeforeForcedJamKeyOn(std::shared_ptr<AbstractInstrument> inst)1185 std::vector<std::vector<size_t>> BambooTracker::assignADPCMBeforeForcedJamKeyOn(std::shared_ptr<AbstractInstrument> inst)
1186 {
1187 switch (inst->getType()) {
1188 case InstrumentType::ADPCM:
1189 {
1190 opnaCtrl_->clearSamplesADPCM();
1191 return { opnaCtrl_->storeSampleADPCM(
1192 std::dynamic_pointer_cast<InstrumentADPCM>(inst)->getRawSample()) };
1193 }
1194 case InstrumentType::Drumkit:
1195 {
1196 opnaCtrl_->clearSamplesADPCM();
1197 std::vector<std::vector<size_t>> addrs;
1198 auto kit = std::dynamic_pointer_cast<InstrumentDrumkit>(inst);
1199 for (const int& key : kit->getAssignedKeys()) {
1200 int samp = kit->getSampleNumber(key);
1201 if (addrs.size() <= static_cast<size_t>(samp)) addrs.resize(samp + 1);
1202 if (addrs[samp].empty()) addrs[samp] = opnaCtrl_->storeSampleADPCM(kit->getRawSample(key));
1203 }
1204 return addrs;
1205 }
1206 default:
1207 return {};
1208 }
1209 }
1210
1211 /********** Play song **********/
startPlaySong()1212 void BambooTracker::startPlaySong()
1213 {
1214 playback_->startPlaySong(curOrderNum_);
1215 startPlay();
1216
1217 if (isFollowPlay_) curStepNum_ = 0;
1218 }
1219
startPlayFromStart()1220 void BambooTracker::startPlayFromStart()
1221 {
1222 playback_->startPlayFromStart();
1223 startPlay();
1224
1225 if (isFollowPlay_) {
1226 curOrderNum_ = 0;
1227 curStepNum_ = 0;
1228 }
1229 }
1230
startPlayPattern()1231 void BambooTracker::startPlayPattern()
1232 {
1233 playback_->startPlayPattern(curOrderNum_);
1234 startPlay();
1235
1236 if (isFollowPlay_) curStepNum_ = 0;
1237 }
1238
startPlayFromCurrentStep()1239 void BambooTracker::startPlayFromCurrentStep()
1240 {
1241 playback_->startPlayFromPosition(curOrderNum_, curStepNum_);
1242 startPlay();
1243 }
1244
startPlayFromMarker()1245 bool BambooTracker::startPlayFromMarker()
1246 {
1247 Song& song = mod_->getSong(curSongNum_);
1248 if (mkOrder_ != -1 && mkOrder_ < static_cast<int>(song.getOrderSize())
1249 && mkStep_ != -1 && mkStep_ < static_cast<int>(song.getPatternSizeFromOrderNumber(mkOrder_))) {
1250 playback_->startPlayFromPosition(mkOrder_, mkStep_);
1251 startPlay();
1252 return true;
1253 }
1254 return false;
1255 }
1256
playStep()1257 void BambooTracker::playStep()
1258 {
1259 playback_->playStep(curOrderNum_, curStepNum_);
1260 for (auto& pair : muteState_) {
1261 for (size_t i = 0; i < pair.second.size(); ++i) {
1262 opnaCtrl_->setMuteState(pair.first, static_cast<int>(i), pair.second[i]);
1263 }
1264 }
1265 }
1266
startPlay()1267 void BambooTracker::startPlay()
1268 {
1269 jamMan_->polyphonic(false);
1270
1271 for (auto& pair : muteState_) {
1272 for (size_t i = 0; i < pair.second.size(); ++i) {
1273 opnaCtrl_->setMuteState(pair.first, static_cast<int>(i), pair.second[i]);
1274 }
1275 }
1276 }
1277
stopPlaySong()1278 void BambooTracker::stopPlaySong()
1279 {
1280 playback_->stopPlaySong();
1281 jamMan_->polyphonic(true);
1282
1283 for (auto& pair : muteState_) {
1284 for (size_t i = 0; i < pair.second.size(); ++i) {
1285 opnaCtrl_->setMuteState(pair.first, static_cast<int>(i), false);
1286 }
1287 }
1288 }
1289
isPlaySong() const1290 bool BambooTracker::isPlaySong() const
1291 {
1292 return playback_->isPlaySong();
1293 }
1294
setTrackMuteState(int trackNum,bool isMute)1295 void BambooTracker::setTrackMuteState(int trackNum, bool isMute)
1296 {
1297 auto& ta = songStyle_.trackAttribs[static_cast<size_t>(trackNum)];
1298 muteState_.at(ta.source).at(static_cast<size_t>(ta.channelInSource)) = isMute;
1299 if (isPlaySong()) opnaCtrl_->setMuteState(ta.source, ta.channelInSource, isMute);
1300 }
1301
isMute(int trackNum)1302 bool BambooTracker::isMute(int trackNum)
1303 {
1304 auto& ta = songStyle_.trackAttribs[static_cast<size_t>(trackNum)];
1305 return muteState_.at(ta.source).at(ta.channelInSource);
1306 }
1307
setFollowPlay(bool isFollowed)1308 void BambooTracker::setFollowPlay(bool isFollowed)
1309 {
1310 isFollowPlay_ = isFollowed;
1311 if (isFollowed) {
1312 int odr = playback_->getPlayingOrderNumber();
1313 if (odr >= 0) {
1314 curOrderNum_ = odr;
1315 curStepNum_ = playback_->getPlayingStepNumber();
1316 }
1317 }
1318 }
1319
isFollowPlay() const1320 bool BambooTracker::isFollowPlay() const
1321 {
1322 return isFollowPlay_;
1323 }
1324
getPlayingOrderNumber() const1325 int BambooTracker::getPlayingOrderNumber() const
1326 {
1327 return playback_->getPlayingOrderNumber();
1328 }
1329
getPlayingStepNumber() const1330 int BambooTracker::getPlayingStepNumber() const
1331 {
1332 return playback_->getPlayingStepNumber();
1333 }
1334
setMarker(int order,int step)1335 void BambooTracker::setMarker(int order, int step)
1336 {
1337 if (mkOrder_ == order && mkStep_ == step) {
1338 mkOrder_ = -1;
1339 mkStep_ = -1;
1340 }
1341 else {
1342 mkOrder_ = order;
1343 mkStep_ = step;
1344 }
1345 }
1346
getMarkerOrder() const1347 int BambooTracker::getMarkerOrder() const
1348 {
1349 return mkOrder_;
1350 }
1351
getMarkerStep() const1352 int BambooTracker::getMarkerStep() const
1353 {
1354 return mkStep_;
1355 }
1356
1357 /********** Export **********/
exportToWav(WavContainer & container,int loopCnt,std::function<bool ()> bar)1358 bool BambooTracker::exportToWav(WavContainer& container, int loopCnt, std::function<bool()> bar)
1359 {
1360 int tmpRate = opnaCtrl_->getRate();
1361 opnaCtrl_->setRate(static_cast<int>(container.getSampleRate()));
1362 size_t sampCnt = static_cast<size_t>(opnaCtrl_->getRate() * opnaCtrl_->getDuration() / 1000);
1363 size_t intrCnt = static_cast<size_t>(opnaCtrl_->getRate()) / mod_->getTickFrequency();
1364 size_t intrCntRest = 0;
1365 std::vector<int16_t> dumbuf(sampCnt << 1);
1366
1367 int endOrder = 0;
1368 int endStep = 0;
1369 size_t dummy = 0;
1370 checkNextPositionOfLastStepAndStepSize(curSongNum_, endOrder, endStep, dummy, dummy);
1371 bool endFlag = false;
1372 bool tmpFollow = std::exchange(isFollowPlay_, false);
1373 std::shared_ptr<chip::WavExportContainer> exCntr = std::make_shared<chip::WavExportContainer>();
1374 opnaCtrl_->setExportContainer(exCntr);
1375 startPlayFromStart();
1376
1377 while (true) {
1378 size_t sampCntRest = sampCnt;
1379 while (sampCntRest) {
1380 if (!intrCntRest) { // Interruption
1381 intrCntRest = intrCnt; // Set counts to next interruption
1382
1383 if (!streamCountUp()) {
1384 if (bar()) { // Update lambda function
1385 stopPlaySong();
1386 isFollowPlay_ = tmpFollow;
1387 return false;
1388 }
1389
1390 int playOrder = playback_->getPlayingOrderNumber();
1391 int playStep = playback_->getPlayingStepNumber();
1392 if ((playOrder == -1 && playStep == -1)
1393 || (playOrder == endOrder && playStep == endStep && !(loopCnt--))){
1394 endFlag = true;
1395 break;
1396 }
1397 }
1398 }
1399
1400 size_t count = std::min(intrCntRest, sampCntRest);
1401 sampCntRest -= count;
1402 intrCntRest -= count;
1403
1404 opnaCtrl_->getStreamSamples(&dumbuf[0], count);
1405 }
1406
1407 if (endFlag) break;
1408 }
1409
1410 opnaCtrl_->setExportContainer();
1411 stopPlaySong();
1412 isFollowPlay_ = tmpFollow;
1413 opnaCtrl_->setRate(tmpRate);
1414
1415 container.storeSample(exCntr->getStream());
1416
1417 return true;
1418 }
1419
exportToVgm(BinaryContainer & container,int target,bool gd3TagEnabled,GD3Tag tag,std::function<bool ()> bar)1420 bool BambooTracker::exportToVgm(BinaryContainer& container, int target, bool gd3TagEnabled,
1421 GD3Tag tag, std::function<bool()> bar)
1422 {
1423 int tmpRate = opnaCtrl_->getRate();
1424 opnaCtrl_->setRate(44100);
1425 double dblIntrCnt = 44100.0 / static_cast<double>(mod_->getTickFrequency());
1426 size_t intrCnt = static_cast<size_t>(dblIntrCnt);
1427 double intrCntDiff = dblIntrCnt - intrCnt;
1428 double intrCntRest = 0;
1429 std::vector<int16_t> dumbuf((intrCnt + 1) << 1);
1430
1431 int loopOrder = 0;
1432 int loopStep = 0;
1433 size_t dummy = 0;
1434 checkNextPositionOfLastStepAndStepSize(curSongNum_, loopOrder, loopStep, dummy, dummy);
1435 bool loopFlag = (loopOrder != -1);
1436 int endCnt = (loopOrder == -1) ? 0 : 1;
1437 bool tmpFollow = std::exchange(isFollowPlay_, false);
1438 uint32_t loopPoint = 0;
1439 uint32_t loopPointSamples = 0;
1440
1441 std::shared_ptr<chip::VgmExportContainer> exCntr
1442 = std::make_shared<chip::VgmExportContainer>(target, mod_->getTickFrequency());
1443
1444 // Set ADPCM
1445 opnaCtrl_->clearSamplesADPCM();
1446 std::vector<uint8_t> rom;
1447 for (auto sampNum : instMan_->getSampleADPCMValidIndices()) {
1448 std::vector<uint8_t> sample = instMan_->getSampleADPCMRawSample(sampNum);
1449 std::vector<size_t> addresses = opnaCtrl_->storeSampleADPCM(sample);
1450 instMan_->setSampleADPCMStartAddress(sampNum, addresses[0]);
1451 instMan_->setSampleADPCMStopAddress(sampNum, addresses[1]);
1452
1453 rom.resize((addresses[1] + 1) << 5);
1454 std::copy(sample.begin(), sample.end(), rom.begin() + static_cast<int>(addresses[0] << 5));
1455 }
1456 exCntr->setDataBlock(std::move(rom));
1457
1458 opnaCtrl_->setExportContainer(exCntr);
1459 startPlayFromStart();
1460 exCntr->forceMoveLoopPoint();
1461
1462 while (true) {
1463 if (!streamCountUp()) {
1464 if (bar()) { // Update lambda function
1465 stopPlaySong();
1466 isFollowPlay_ = tmpFollow;
1467 return false;
1468 }
1469
1470 int playOrder = playback_->getPlayingOrderNumber();
1471 int playStep = playback_->getPlayingStepNumber();
1472 if (playOrder == loopOrder && playStep == loopStep && !(endCnt--)) break;
1473
1474 if (loopFlag && loopOrder == playOrder && loopStep == playStep) {
1475 loopPoint = exCntr->setLoopPoint();
1476 loopPointSamples = exCntr->getSampleLength();
1477 }
1478 }
1479
1480 intrCntRest += intrCntDiff;
1481 size_t extraIntrCnt = static_cast<size_t>(intrCntRest);
1482 intrCntRest -= extraIntrCnt;
1483 opnaCtrl_->getStreamSamples(&dumbuf[0], intrCnt + extraIntrCnt);
1484 }
1485
1486 opnaCtrl_->setExportContainer();
1487 stopPlaySong();
1488 isFollowPlay_ = tmpFollow;
1489 opnaCtrl_->setRate(tmpRate);
1490
1491 try {
1492 ExportHandler::writeVgm(container, target, exCntr->getData(), CHIP_CLOCK, mod_->getTickFrequency(),
1493 loopFlag, loopPoint, exCntr->getSampleLength() - loopPointSamples,
1494 exCntr->getSampleLength(), gd3TagEnabled, tag);
1495 return true;
1496 } catch (...) {
1497 throw;
1498 }
1499 }
1500
exportToS98(BinaryContainer & container,int target,bool tagEnabled,S98Tag tag,int rate,std::function<bool ()> bar)1501 bool BambooTracker::exportToS98(BinaryContainer& container, int target, bool tagEnabled,
1502 S98Tag tag, int rate, std::function<bool()> bar)
1503 {
1504 int tmpRate = opnaCtrl_->getRate();
1505 opnaCtrl_->setRate(rate);
1506 double dblIntrCnt = static_cast<double>(rate) / static_cast<double>(mod_->getTickFrequency());
1507 size_t intrCnt = static_cast<size_t>(dblIntrCnt);
1508 double intrCntDiff = dblIntrCnt - intrCnt;
1509 double intrCntRest = 0;
1510 std::vector<int16_t> dumbuf((intrCnt + 1) << 1);
1511
1512 int loopOrder = 0;
1513 int loopStep = 0;
1514 size_t dummy = 0;
1515 checkNextPositionOfLastStepAndStepSize(curSongNum_, loopOrder, loopStep, dummy, dummy);
1516 bool loopFlag = (loopOrder != -1);
1517 int endCnt = (loopOrder == -1) ? 0 : 1;
1518 bool tmpFollow = std::exchange(isFollowPlay_, false);
1519 uint32_t loopPoint = 0;
1520 std::shared_ptr<chip::S98ExportContainer> exCntr = std::make_shared<chip::S98ExportContainer>(target);
1521 opnaCtrl_->setExportContainer(exCntr);
1522 startPlayFromStart();
1523 assignSampleADPCMRawSamples();
1524 exCntr->forceMoveLoopPoint();
1525
1526 while (true) {
1527 exCntr->getData(); // Set wait counts
1528 if (!streamCountUp()) {
1529 if (bar()) { // Update lambda function
1530 stopPlaySong();
1531 isFollowPlay_ = tmpFollow;
1532 return false;
1533 }
1534
1535 int playOrder = playback_->getPlayingOrderNumber();
1536 int playStep = playback_->getPlayingStepNumber();
1537 if (playOrder == loopOrder && playStep == loopStep && !(endCnt--)) break;
1538
1539 if (loopFlag && loopOrder == playOrder && loopStep == playStep) {
1540 loopPoint = exCntr->setLoopPoint();
1541 }
1542 }
1543
1544 intrCntRest += intrCntDiff;
1545 size_t extraIntrCnt = static_cast<size_t>(intrCntRest);
1546 intrCntRest -= extraIntrCnt;
1547 opnaCtrl_->getStreamSamples(&dumbuf[0], intrCnt + extraIntrCnt);
1548 }
1549
1550 opnaCtrl_->setExportContainer();
1551 stopPlaySong();
1552 isFollowPlay_ = tmpFollow;
1553 opnaCtrl_->setRate(tmpRate);
1554
1555 try {
1556 ExportHandler::writeS98(container, target, exCntr->getData(), CHIP_CLOCK, static_cast<uint32_t>(rate),
1557 loopFlag, loopPoint, tagEnabled, tag);
1558 return true;
1559 } catch (...) {
1560 throw;
1561 }
1562 }
1563
checkNextPositionOfLastStepAndStepSize(int songNum,int & endOrder,int & endStep,size_t & nIntroStep,size_t & nLoopStep) const1564 void BambooTracker::checkNextPositionOfLastStepAndStepSize(int songNum, int& endOrder, int& endStep, size_t& nIntroStep, size_t& nLoopStep) const
1565 {
1566 Song& song = mod_->getSong(songNum);
1567 endOrder = 0;
1568 endStep = 0;
1569
1570 int lastOrder = static_cast<int>(song.getOrderSize()) - 1;
1571 std::unordered_map<int, int> orderStepMap;
1572 int orderN = 0;
1573 size_t stepCnt = 0;
1574 do {
1575 endOrder = (endOrder + 1) % (lastOrder + 1);
1576 endStep = 0;
1577
1578 int stepN = static_cast<int>(getPatternSizeFromOrderNumber(songNum, orderN)) - 1;
1579 for (auto attrib : songStyle_.trackAttribs) {
1580 Step& step = song.getTrack(attrib.number).getPatternFromOrderNumber(orderN).getStep(stepN);
1581 for (int i = 0; i < 4; ++i) {
1582 Effect&& eff = Effect::makeEffectData(attrib.source, step.getEffectID(i), step.getEffectValue(i));
1583 switch (eff.type) {
1584 case EffectType::PositionJump:
1585 if (eff.value <= lastOrder) {
1586 endOrder = eff.value;
1587 endStep = 0;
1588 }
1589 break;
1590 case EffectType::SongEnd:
1591 endOrder = -1;
1592 endStep = -1;
1593 break;
1594 case EffectType::PatternBreak:
1595 if (orderN == lastOrder
1596 && eff.value < static_cast<int>(getPatternSizeFromOrderNumber(songNum, 0))) {
1597 endOrder = 0;
1598 endStep = eff.value;
1599 }
1600 else if (eff.value < static_cast<int>(getPatternSizeFromOrderNumber(songNum, orderN + 1))) {
1601 endOrder = orderN + 1;
1602 endStep = eff.value;
1603 }
1604 break;
1605 default:
1606 break;
1607 }
1608 }
1609 }
1610
1611 orderStepMap[orderN] = stepCnt;
1612 stepCnt += song.getPatternSizeFromOrderNumber(orderN);
1613 orderN = endOrder;
1614 } while (orderN != -1 && !orderStepMap.count(orderN)); // stopped song or jumped to played order
1615
1616 if (orderN == -1) {
1617 nIntroStep = stepCnt;
1618 nLoopStep = 0;
1619 }
1620 else {
1621 nIntroStep = orderStepMap[orderN];
1622 nLoopStep = stepCnt - orderStepMap[orderN];
1623 }
1624 }
1625
1626 /********** Real chip interface **********/
useSCCI(scci::SoundInterfaceManager * manager)1627 void BambooTracker::useSCCI(scci::SoundInterfaceManager* manager)
1628 {
1629 opnaCtrl_->useSCCI(manager);
1630 }
1631
useC86CTL(C86ctlBase * base)1632 void BambooTracker::useC86CTL(C86ctlBase* base)
1633 {
1634 opnaCtrl_->useC86CTL(base);
1635 }
1636
getRealChipinterface() const1637 RealChipInterface BambooTracker::getRealChipinterface() const
1638 {
1639 if (opnaCtrl_->isUsedSCCI()) return RealChipInterface::SCCI;
1640 else if (opnaCtrl_->isUsedC86CTL()) return RealChipInterface::C86CTL;
1641 else return RealChipInterface::NONE;
1642 }
1643
1644 /********** Stream events **********/
streamCountUp()1645 int BambooTracker::streamCountUp()
1646 {
1647 int state = playback_->streamCountUp();
1648 if (!state && isFollowPlay_ && !playback_->isPlayingStep()) { // Step
1649 int odr = playback_->getPlayingOrderNumber();
1650 if (odr >= 0) {
1651 curOrderNum_ = odr;
1652 curStepNum_ = playback_->getPlayingStepNumber();
1653 }
1654 }
1655 return state;
1656 }
1657
getStreamSamples(int16_t * container,size_t nSamples)1658 void BambooTracker::getStreamSamples(int16_t *container, size_t nSamples)
1659 {
1660 opnaCtrl_->getStreamSamples(container, nSamples);
1661 }
1662
killSound()1663 void BambooTracker::killSound()
1664 {
1665 jamMan_->clear();
1666 opnaCtrl_->reset();
1667 }
1668
1669 /********** Stream details **********/
getStreamRate() const1670 int BambooTracker::getStreamRate() const
1671 {
1672 return opnaCtrl_->getRate();
1673 }
1674
setStreamRate(int rate)1675 void BambooTracker::setStreamRate(int rate)
1676 {
1677 opnaCtrl_->setRate(rate);
1678 }
1679
getStreamDuration() const1680 int BambooTracker::getStreamDuration() const
1681 {
1682 return opnaCtrl_->getDuration();
1683 }
1684
setStreamDuration(int duration)1685 void BambooTracker::setStreamDuration(int duration)
1686 {
1687 opnaCtrl_->setDuration(duration);
1688 }
1689
getStreamTempo() const1690 int BambooTracker::getStreamTempo() const
1691 {
1692 return tickCounter_->getTempo();
1693 }
1694
getStreamSpeed() const1695 int BambooTracker::getStreamSpeed() const
1696 {
1697 return tickCounter_->getSpeed();
1698 }
1699
getStreamGrooveEnabled() const1700 bool BambooTracker::getStreamGrooveEnabled() const
1701 {
1702 return tickCounter_->getGrooveEnabled();
1703 }
1704
setMasterVolume(int percentage)1705 void BambooTracker::setMasterVolume(int percentage)
1706 {
1707 opnaCtrl_->setMasterVolume(percentage);
1708 }
1709
setMasterVolumeFM(double dB)1710 void BambooTracker::setMasterVolumeFM(double dB)
1711 {
1712 opnaCtrl_->setMasterVolumeFM(dB);
1713 }
1714
setMasterVolumeSSG(double dB)1715 void BambooTracker::setMasterVolumeSSG(double dB)
1716 {
1717 opnaCtrl_->setMasterVolumeSSG(dB);
1718 }
1719
1720 /********** Module details **********/
1721 /*----- Module -----*/
makeNewModule()1722 void BambooTracker::makeNewModule()
1723 {
1724 stopPlaySong();
1725
1726 clearAllInstrument();
1727
1728 opnaCtrl_->reset();
1729
1730 mod_ = std::make_shared<Module>();
1731
1732 tickCounter_->setInterruptRate(mod_->getTickFrequency());
1733
1734 setCurrentSongNumber(0);
1735 curInstNum_ = -1;
1736
1737 clearCommandHistory();
1738 }
1739
loadModule(BinaryContainer & container)1740 void BambooTracker::loadModule(BinaryContainer& container)
1741 {
1742 makeNewModule();
1743
1744 std::exception_ptr ep;
1745 try {
1746 ModuleIO::loadModule(container, mod_, instMan_);
1747 }
1748 catch (...) {
1749 ep = std::current_exception();
1750 }
1751
1752 tickCounter_->setInterruptRate(mod_->getTickFrequency());
1753 setCurrentSongNumber(0);
1754 clearCommandHistory();
1755
1756 if (ep) std::rethrow_exception(ep);
1757 }
1758
saveModule(BinaryContainer & container)1759 void BambooTracker::saveModule(BinaryContainer& container)
1760 {
1761 ModuleIO::saveModule(container, mod_, instMan_);
1762 }
1763
setModulePath(std::string path)1764 void BambooTracker::setModulePath(std::string path)
1765 {
1766 mod_->setFilePath(path);
1767 }
1768
getModulePath() const1769 std::string BambooTracker::getModulePath() const
1770 {
1771 return mod_->getFilePath();
1772 }
1773
setModuleTitle(std::string title)1774 void BambooTracker::setModuleTitle(std::string title)
1775 {
1776 mod_->setTitle(title);
1777 }
1778
getModuleTitle() const1779 std::string BambooTracker::getModuleTitle() const
1780 {
1781 return mod_->getTitle();
1782 }
1783
setModuleAuthor(std::string author)1784 void BambooTracker::setModuleAuthor(std::string author)
1785 {
1786 mod_->setAuthor(author);
1787 }
1788
getModuleAuthor() const1789 std::string BambooTracker::getModuleAuthor() const
1790 {
1791 return mod_->getAuthor();
1792 }
1793
setModuleCopyright(std::string copyright)1794 void BambooTracker::setModuleCopyright(std::string copyright)
1795 {
1796 mod_->setCopyright(copyright);
1797 }
1798
getModuleCopyright() const1799 std::string BambooTracker::getModuleCopyright() const
1800 {
1801 return mod_->getCopyright();
1802 }
1803
setModuleComment(std::string comment)1804 void BambooTracker::setModuleComment(std::string comment)
1805 {
1806 mod_->setComment(comment);
1807 }
1808
getModuleComment() const1809 std::string BambooTracker::getModuleComment() const
1810 {
1811 return mod_->getComment();
1812 }
1813
setModuleTickFrequency(unsigned int freq)1814 void BambooTracker::setModuleTickFrequency(unsigned int freq)
1815 {
1816 mod_->setTickFrequency(freq);
1817 tickCounter_->setInterruptRate(freq);
1818 }
1819
getModuleTickFrequency() const1820 unsigned int BambooTracker::getModuleTickFrequency() const
1821 {
1822 return mod_->getTickFrequency();
1823 }
1824
setModuleStepHighlight1Distance(size_t dist)1825 void BambooTracker::setModuleStepHighlight1Distance(size_t dist)
1826 {
1827 mod_->setStepHighlight1Distance(dist);
1828 }
1829
getModuleStepHighlight1Distance() const1830 size_t BambooTracker::getModuleStepHighlight1Distance() const
1831 {
1832 return mod_->getStepHighlight1Distance();
1833 }
1834
setModuleStepHighlight2Distance(size_t dist)1835 void BambooTracker::setModuleStepHighlight2Distance(size_t dist)
1836 {
1837 mod_->setStepHighlight2Distance(dist);
1838 }
1839
getModuleStepHighlight2Distance() const1840 size_t BambooTracker::getModuleStepHighlight2Distance() const
1841 {
1842 return mod_->getStepHighlight2Distance();
1843 }
1844
setModuleMixerType(MixerType type)1845 void BambooTracker::setModuleMixerType(MixerType type)
1846 {
1847 mod_->setMixerType(type);
1848 }
1849
getModuleMixerType() const1850 MixerType BambooTracker::getModuleMixerType() const
1851 {
1852 return mod_->getMixerType();
1853 }
1854
setModuleCustomMixerFMLevel(double level)1855 void BambooTracker::setModuleCustomMixerFMLevel(double level)
1856 {
1857 mod_->setCustomMixerFMLevel(level);
1858 }
1859
getModuleCustomMixerFMLevel() const1860 double BambooTracker::getModuleCustomMixerFMLevel() const
1861 {
1862 return mod_->getCustomMixerFMLevel();
1863 }
1864
setModuleCustomMixerSSGLevel(double level)1865 void BambooTracker::setModuleCustomMixerSSGLevel(double level)
1866 {
1867 mod_->setCustomMixerSSGLevel(level);
1868 }
1869
getModuleCustomMixerSSGLevel() const1870 double BambooTracker::getModuleCustomMixerSSGLevel() const
1871 {
1872 return mod_->getCustomMixerSSGLevel();
1873 }
1874
getGrooveCount() const1875 size_t BambooTracker::getGrooveCount() const
1876 {
1877 return mod_->getGrooveCount();
1878 }
1879
setGroove(int num,std::vector<int> seq)1880 void BambooTracker::setGroove(int num, std::vector<int> seq)
1881 {
1882 mod_->setGroove(num, std::move(seq));
1883 }
1884
setGrooves(std::vector<std::vector<int>> seqs)1885 void BambooTracker::setGrooves(std::vector<std::vector<int>> seqs)
1886 {
1887 mod_->setGrooves(std::move(seqs));
1888 }
1889
getGroove(int num) const1890 std::vector<int> BambooTracker::getGroove(int num) const
1891 {
1892 return mod_->getGroove(num).getSequence();
1893 }
1894
clearUnusedPatterns()1895 void BambooTracker::clearUnusedPatterns()
1896 {
1897 mod_->clearUnusedPatterns();
1898 }
1899
replaceDuplicateInstrumentsInPatterns(std::vector<std::vector<int>> list)1900 void BambooTracker::replaceDuplicateInstrumentsInPatterns(std::vector<std::vector<int>> list)
1901 {
1902 std::unordered_map<int, int> map;
1903 for (auto& group : list) {
1904 for (size_t i = 1; i < group.size(); ++i) {
1905 map.emplace(group[i], group.front());
1906 }
1907 }
1908
1909 mod_->replaceDuplicateInstrumentsInPatterns(map);
1910 }
1911
clearUnusedADPCMSamples()1912 void BambooTracker::clearUnusedADPCMSamples()
1913 {
1914 instMan_->clearUnusedSamplesADPCM();
1915 }
1916
1917 /*----- Song -----*/
setSongTitle(int songNum,std::string title)1918 void BambooTracker::setSongTitle(int songNum, std::string title)
1919 {
1920 mod_->getSong(songNum).setTitle(title);
1921 }
1922
getSongTitle(int songNum) const1923 std::string BambooTracker::getSongTitle(int songNum) const
1924 {
1925 return mod_->getSong(songNum).getTitle();
1926 }
1927
setSongTempo(int songNum,int tempo)1928 void BambooTracker::setSongTempo(int songNum, int tempo)
1929 {
1930 mod_->getSong(songNum).setTempo(tempo);
1931 if (curSongNum_ == songNum) tickCounter_->setTempo(tempo);
1932 }
1933
getSongTempo(int songNum) const1934 int BambooTracker::getSongTempo(int songNum) const
1935 {
1936 return mod_->getSong(songNum).getTempo();
1937 }
1938
setSongGroove(int songNum,int groove)1939 void BambooTracker::setSongGroove(int songNum, int groove)
1940 {
1941 mod_->getSong(songNum).setGroove(groove);
1942 tickCounter_->setGroove(mod_->getGroove(groove).getSequence());
1943 }
1944
getSongGroove(int songNum) const1945 int BambooTracker::getSongGroove(int songNum) const
1946 {
1947 return mod_->getSong(songNum).getGroove();
1948 }
1949
toggleTempoOrGrooveInSong(int songNum,bool isTempo)1950 void BambooTracker::toggleTempoOrGrooveInSong(int songNum, bool isTempo)
1951 {
1952 mod_->getSong(songNum).toggleTempoOrGroove(isTempo);
1953 tickCounter_->setGrooveTrigger(isTempo ? GrooveTrigger::Invalid
1954 : GrooveTrigger::ValidByGlobal);
1955 }
1956
isUsedTempoInSong(int songNum) const1957 bool BambooTracker::isUsedTempoInSong(int songNum) const
1958 {
1959 return mod_->getSong(songNum).isUsedTempo();
1960 }
1961
getSongStyle(int songNum) const1962 SongStyle BambooTracker::getSongStyle(int songNum) const
1963 {
1964 return mod_->getSong(songNum).getStyle();
1965 }
1966
changeSongType(int songNum,SongType type)1967 void BambooTracker::changeSongType(int songNum, SongType type)
1968 {
1969 mod_->getSong(songNum).changeType(type);
1970 }
1971
setSongSpeed(int songNum,int speed)1972 void BambooTracker::setSongSpeed(int songNum, int speed)
1973 {
1974 mod_->getSong(songNum).setSpeed(speed);
1975 if (curSongNum_ == songNum) tickCounter_->setSpeed(speed);
1976 }
1977
getSongSpeed(int songNum) const1978 int BambooTracker::getSongSpeed(int songNum) const
1979 {
1980 return mod_->getSong(songNum).getSpeed();
1981 }
1982
getSongCount() const1983 size_t BambooTracker::getSongCount() const
1984 {
1985 return mod_->getSongCount();
1986 }
1987
addSong(SongType songType,std::string title)1988 void BambooTracker::addSong(SongType songType, std::string title)
1989 {
1990 mod_->addSong(songType, title);
1991 }
1992
sortSongs(std::vector<int> numbers)1993 void BambooTracker::sortSongs(std::vector<int> numbers)
1994 {
1995 mod_->sortSongs(std::move(numbers));
1996 }
1997
getAllStepCount(int songNum,size_t loopCnt) const1998 size_t BambooTracker::getAllStepCount(int songNum, size_t loopCnt) const
1999 {
2000 size_t introSize = 0;
2001 size_t loopSize = 0;
2002 int dummy1 = 0;
2003 int dummy2 = 0;
2004 checkNextPositionOfLastStepAndStepSize(songNum, dummy1, dummy2, introSize, loopSize);
2005 return introSize + loopSize * loopCnt;
2006 }
2007
transposeSong(int songNum,int seminotes,std::vector<int> excludeInsts)2008 void BambooTracker::transposeSong(int songNum, int seminotes, std::vector<int> excludeInsts)
2009 {
2010 mod_->getSong(songNum).transpose(seminotes, excludeInsts);
2011 }
2012
swapTracks(int songNum,int track1,int track2)2013 void BambooTracker::swapTracks(int songNum, int track1, int track2)
2014 {
2015 mod_->getSong(songNum).swapTracks(track1, track2);
2016 }
2017
calculateSongLength(int songNum) const2018 double BambooTracker::calculateSongLength(int songNum) const
2019 {
2020 SongLengthCalculator calculator(*mod_.get(), songNum);
2021 return calculator.calculateBySecond();
2022 }
2023
2024 /*----- Bookmark -----*/
addBookmark(int songNum,std::string name,int order,int step)2025 void BambooTracker::addBookmark(int songNum, std::string name, int order, int step)
2026 {
2027 mod_->getSong(songNum).addBookmark(name, order, step);
2028 }
2029
changeBookmark(int songNum,int i,std::string name,int order,int step)2030 void BambooTracker::changeBookmark(int songNum, int i, std::string name, int order, int step)
2031 {
2032 mod_->getSong(songNum).changeBookmark(i, name, order, step);
2033 }
2034
removeBookmark(int songNum,int i)2035 void BambooTracker::removeBookmark(int songNum, int i)
2036 {
2037 mod_->getSong(songNum).removeBookmark(i);
2038 }
2039
clearBookmark(int songNum)2040 void BambooTracker::clearBookmark(int songNum)
2041 {
2042 mod_->getSong(songNum).clearBookmark();
2043 }
2044
swapBookmarks(int songNum,int a,int b)2045 void BambooTracker::swapBookmarks(int songNum, int a, int b)
2046 {
2047 mod_->getSong(songNum).swapBookmarks(a, b);
2048 }
2049
sortBookmarkByPosition(int songNum)2050 void BambooTracker::sortBookmarkByPosition(int songNum)
2051 {
2052 mod_->getSong(songNum).sortBookmarkByPosition();
2053 }
sortBookmarkByName(int songNum)2054 void BambooTracker::sortBookmarkByName(int songNum)
2055 {
2056 mod_->getSong(songNum).sortBookmarkByName();
2057 }
2058
getBookmark(int songNum,int i) const2059 Bookmark BambooTracker::getBookmark(int songNum, int i) const
2060 {
2061 return mod_->getSong(songNum).getBookmark(i);
2062 }
2063
findBookmarks(int songNum,int order,int step)2064 std::vector<int> BambooTracker::findBookmarks(int songNum, int order, int step)
2065 {
2066 return mod_->getSong(songNum).findBookmarks(order, step);
2067 }
2068
getPreviousBookmark(int songNum,int order,int step)2069 Bookmark BambooTracker::getPreviousBookmark(int songNum, int order, int step)
2070 {
2071 return mod_->getSong(songNum).getPreviousBookmark(order, step);
2072 }
2073
getNextBookmark(int songNum,int order,int step)2074 Bookmark BambooTracker::getNextBookmark(int songNum, int order, int step)
2075 {
2076 return mod_->getSong(songNum).getNextBookmark(order, step);
2077 }
2078
getBookmarkSize(int songNum) const2079 size_t BambooTracker::getBookmarkSize(int songNum) const
2080 {
2081 return mod_->getSong(songNum).getBookmarkSize();
2082 }
2083
2084 /*----- Track -----*/
setEffectDisplayWidth(int songNum,int trackNum,size_t w)2085 void BambooTracker::setEffectDisplayWidth(int songNum, int trackNum, size_t w)
2086 {
2087 mod_->getSong(songNum).getTrack(trackNum).setEffectDisplayWidth(w);
2088 }
2089
getEffectDisplayWidth(int songNum,int trackNum) const2090 size_t BambooTracker::getEffectDisplayWidth(int songNum, int trackNum) const
2091 {
2092 return mod_->getSong(songNum).getTrack(trackNum).getEffectDisplayWidth();
2093 }
2094
2095 /*----- Order -----*/
getOrderData(int songNum,int orderNum) const2096 std::vector<OrderData> BambooTracker::getOrderData(int songNum, int orderNum) const
2097 {
2098 return mod_->getSong(songNum).getOrderData(orderNum);
2099 }
2100
setOrderPatternDigit(int songNum,int trackNum,int orderNum,int patternNum,bool secondEntry)2101 void BambooTracker::setOrderPatternDigit(int songNum, int trackNum, int orderNum, int patternNum, bool secondEntry)
2102 {
2103 comMan_.invoke(std::make_unique<SetPatternToOrderCommand>(mod_, songNum, trackNum, orderNum, patternNum, secondEntry));
2104 }
2105
insertOrderBelow(int songNum,int orderNum)2106 void BambooTracker::insertOrderBelow(int songNum, int orderNum)
2107 {
2108 comMan_.invoke(std::make_unique<InsertOrderBelowCommand>(mod_, songNum, orderNum));
2109 }
2110
deleteOrder(int songNum,int orderNum)2111 void BambooTracker::deleteOrder(int songNum, int orderNum)
2112 {
2113 comMan_.invoke(std::make_unique<DeleteOrderCommand>(mod_, songNum, orderNum));
2114 }
2115
pasteOrderCells(int songNum,int beginTrack,int beginOrder,std::vector<std::vector<std::string>> cells)2116 void BambooTracker::pasteOrderCells(int songNum, int beginTrack, int beginOrder,
2117 std::vector<std::vector<std::string>> cells)
2118 {
2119 // Arrange data
2120 std::vector<std::vector<std::string>> d;
2121 size_t w = songStyle_.trackAttribs.size() - static_cast<size_t>(beginTrack);
2122 size_t h = getOrderSize(songNum) - static_cast<size_t>(beginOrder);
2123
2124 size_t width = std::min(cells.at(0).size(), w);
2125 size_t height = std::min(cells.size(), h);
2126
2127 for (size_t i = 0; i < height; ++i) {
2128 d.emplace_back();
2129 for (size_t j = 0; j < width; ++j) {
2130 d.at(i).push_back(cells.at(i).at(j));
2131 }
2132 }
2133
2134 comMan_.invoke(std::make_unique<PasteCopiedDataToOrderCommand>(mod_, songNum, beginTrack, beginOrder, std::move(d)));
2135 }
2136
duplicateOrder(int songNum,int orderNum)2137 void BambooTracker::duplicateOrder(int songNum, int orderNum)
2138 {
2139 comMan_.invoke(std::make_unique<DuplicateOrderCommand>(mod_, songNum, orderNum));
2140 }
2141
MoveOrder(int songNum,int orderNum,bool isUp)2142 void BambooTracker::MoveOrder(int songNum, int orderNum, bool isUp)
2143 {
2144 comMan_.invoke(std::make_unique<MoveOrderCommand>(mod_, songNum, orderNum, isUp));
2145 }
2146
clonePatterns(int songNum,int beginOrder,int beginTrack,int endOrder,int endTrack)2147 void BambooTracker::clonePatterns(int songNum, int beginOrder, int beginTrack, int endOrder, int endTrack)
2148 {
2149 comMan_.invoke(std::make_unique<ClonePatternsCommand>(mod_, songNum, beginOrder, beginTrack, endOrder, endTrack));
2150 }
2151
cloneOrder(int songNum,int orderNum)2152 void BambooTracker::cloneOrder(int songNum, int orderNum)
2153 {
2154 comMan_.invoke(std::make_unique<CloneOrderCommand>(mod_, songNum, orderNum));
2155 }
2156
getOrderSize(int songNum) const2157 size_t BambooTracker::getOrderSize(int songNum) const
2158 {
2159 return mod_->getSong(songNum).getOrderSize();
2160 }
2161
canAddNewOrder(int songNum) const2162 bool BambooTracker::canAddNewOrder(int songNum) const
2163 {
2164 return mod_->getSong(songNum).canAddNewOrder();
2165 }
2166
2167 /*----- Pattern -----*/
getStepNoteNumber(int songNum,int trackNum,int orderNum,int stepNum) const2168 int BambooTracker::getStepNoteNumber(int songNum, int trackNum, int orderNum, int stepNum) const
2169 {
2170 return mod_->getSong(songNum).getTrack(trackNum).getPatternFromOrderNumber(orderNum)
2171 .getStep(stepNum).getNoteNumber();
2172 }
2173
setStepNote(int songNum,int trackNum,int orderNum,int stepNum,int octave,Note note,bool instMask,bool volMask)2174 void BambooTracker::setStepNote(int songNum, int trackNum, int orderNum, int stepNum, int octave, Note note, bool instMask, bool volMask)
2175 {
2176 int nn = octaveAndNoteToNoteNumber(octave, note);
2177 SoundSource src = songStyle_.trackAttribs.at(static_cast<size_t>(trackNum)).source;
2178
2179 int in = -1;
2180 if (!instMask && curInstNum_ != -1
2181 && (src == instMan_->getInstrumentSharedPtr(curInstNum_)->getSoundSource())) {
2182 in = curInstNum_;
2183 }
2184 bool fmReversed = (volFMReversed_ && src == SoundSource::FM);
2185
2186 comMan_.invoke(std::make_unique<SetKeyOnToStepCommand>(mod_, songNum, trackNum, orderNum, stepNum, nn, instMask, in, volMask, curVolume_, fmReversed));
2187 }
2188
setStepKeyOff(int songNum,int trackNum,int orderNum,int stepNum)2189 void BambooTracker::setStepKeyOff(int songNum, int trackNum, int orderNum, int stepNum)
2190 {
2191 comMan_.invoke(std::make_unique<SetKeyOffToStepCommand>(mod_, songNum, trackNum, orderNum, stepNum));
2192 }
2193
setEchoBufferAccess(int songNum,int trackNum,int orderNum,int stepNum,int bufNum)2194 void BambooTracker::setEchoBufferAccess(int songNum, int trackNum, int orderNum, int stepNum, int bufNum)
2195 {
2196 comMan_.invoke(std::make_unique<SetEchoBufferAccessCommand>(mod_, songNum, trackNum, orderNum, stepNum, bufNum));
2197 }
2198
eraseStepNote(int songNum,int trackNum,int orderNum,int stepNum)2199 void BambooTracker::eraseStepNote(int songNum, int trackNum, int orderNum, int stepNum)
2200 {
2201 comMan_.invoke(std::make_unique<EraseStepCommand>(mod_, songNum, trackNum, orderNum, stepNum));
2202 }
2203
getStepInstrument(int songNum,int trackNum,int orderNum,int stepNum) const2204 int BambooTracker::getStepInstrument(int songNum, int trackNum, int orderNum, int stepNum) const
2205 {
2206 return mod_->getSong(songNum).getTrack(trackNum).getPatternFromOrderNumber(orderNum)
2207 .getStep(stepNum).getInstrumentNumber();
2208 }
2209
setStepInstrumentDigit(int songNum,int trackNum,int orderNum,int stepNum,int instNum,bool secondEntry)2210 void BambooTracker::setStepInstrumentDigit(int songNum, int trackNum, int orderNum, int stepNum, int instNum, bool secondEntry)
2211 {
2212 comMan_.invoke(std::make_unique<SetInstrumentToStepCommand>(mod_, songNum, trackNum, orderNum, stepNum, instNum, secondEntry));
2213 }
2214
eraseStepInstrument(int songNum,int trackNum,int orderNum,int stepNum)2215 void BambooTracker::eraseStepInstrument(int songNum, int trackNum, int orderNum, int stepNum)
2216 {
2217 comMan_.invoke(std::make_unique<EraseInstrumentInStepCommand>(mod_, songNum, trackNum, orderNum, stepNum));
2218 }
2219
getStepVolume(int songNum,int trackNum,int orderNum,int stepNum) const2220 int BambooTracker::getStepVolume(int songNum, int trackNum, int orderNum, int stepNum) const
2221 {
2222 return mod_->getSong(songNum).getTrack(trackNum).getPatternFromOrderNumber(orderNum)
2223 .getStep(stepNum).getVolume();
2224 }
2225
setStepVolumeDigit(int songNum,int trackNum,int orderNum,int stepNum,int volume,bool secondEntry)2226 int BambooTracker::setStepVolumeDigit(int songNum, int trackNum, int orderNum, int stepNum, int volume, bool secondEntry)
2227 {
2228 bool fmReversed = (volFMReversed_
2229 && songStyle_.trackAttribs.at(static_cast<size_t>(trackNum)).source == SoundSource::FM);
2230 comMan_.invoke(std::make_unique<SetVolumeToStepCommand>(mod_, songNum, trackNum, orderNum, stepNum, volume, fmReversed, secondEntry));
2231 curVolume_ = mod_->getSong(songNum).getTrack(trackNum).getPatternFromOrderNumber(orderNum).getStep(stepNum).getVolume();
2232 if (fmReversed && curVolume_ < 0x80) curVolume_ = 0x7f - curVolume_;
2233 return curVolume_;
2234 }
2235
eraseStepVolume(int songNum,int trackNum,int orderNum,int stepNum)2236 void BambooTracker::eraseStepVolume(int songNum, int trackNum, int orderNum, int stepNum)
2237 {
2238 comMan_.invoke(std::make_unique<EraseVolumeInStepCommand>(mod_, songNum, trackNum, orderNum, stepNum));
2239 }
2240
getStepEffectID(int songNum,int trackNum,int orderNum,int stepNum,int n) const2241 std::string BambooTracker::getStepEffectID(int songNum, int trackNum, int orderNum, int stepNum, int n) const
2242 {
2243 return mod_->getSong(songNum).getTrack(trackNum).getPatternFromOrderNumber(orderNum)
2244 .getStep(stepNum).getEffectID(n);
2245 }
2246
setStepEffectIDCharacter(int songNum,int trackNum,int orderNum,int stepNum,int n,std::string id,bool fillValue00,bool secondEntry)2247 void BambooTracker::setStepEffectIDCharacter(int songNum, int trackNum, int orderNum, int stepNum, int n, std::string id, bool fillValue00, bool secondEntry)
2248 {
2249 comMan_.invoke(std::make_unique<SetEffectIDToStepCommand>(mod_, songNum, trackNum, orderNum, stepNum, n, id, fillValue00, secondEntry));
2250 }
2251
getStepEffectValue(int songNum,int trackNum,int orderNum,int stepNum,int n) const2252 int BambooTracker::getStepEffectValue(int songNum, int trackNum, int orderNum, int stepNum, int n) const
2253 {
2254 return mod_->getSong(songNum).getTrack(trackNum).getPatternFromOrderNumber(orderNum)
2255 .getStep(stepNum).getEffectValue(n);
2256 }
2257
setStepEffectValueDigit(int songNum,int trackNum,int orderNum,int stepNum,int n,int value,EffectDisplayControl ctrl,bool secondEntry)2258 void BambooTracker::setStepEffectValueDigit(int songNum, int trackNum, int orderNum, int stepNum, int n, int value, EffectDisplayControl ctrl, bool secondEntry)
2259 {
2260 comMan_.invoke(std::make_unique<SetEffectValueToStepCommand>(mod_, songNum, trackNum, orderNum, stepNum, n, value, ctrl, secondEntry));
2261 }
2262
eraseStepEffect(int songNum,int trackNum,int orderNum,int stepNum,int n)2263 void BambooTracker::eraseStepEffect(int songNum, int trackNum, int orderNum, int stepNum, int n)
2264 {
2265 comMan_.invoke(std::make_unique<EraseEffectInStepCommand>(mod_, songNum, trackNum, orderNum, stepNum, n));
2266 }
2267
eraseStepEffectValue(int songNum,int trackNum,int orderNum,int stepNum,int n)2268 void BambooTracker::eraseStepEffectValue(int songNum, int trackNum, int orderNum, int stepNum, int n)
2269 {
2270 comMan_.invoke(std::make_unique<EraseEffectValueInStepCommand>(mod_, songNum, trackNum, orderNum, stepNum, n));
2271 }
2272
insertStep(int songNum,int trackNum,int orderNum,int stepNum)2273 void BambooTracker::insertStep(int songNum, int trackNum, int orderNum, int stepNum)
2274 {
2275 comMan_.invoke(std::make_unique<InsertStepCommand>(mod_, songNum, trackNum, orderNum, stepNum));
2276 }
2277
deletePreviousStep(int songNum,int trackNum,int orderNum,int stepNum)2278 void BambooTracker::deletePreviousStep(int songNum, int trackNum, int orderNum, int stepNum)
2279 {
2280 comMan_.invoke(std::make_unique<DeletePreviousStepCommand>(mod_, songNum, trackNum, orderNum, stepNum));
2281 }
2282
pastePatternCells(int songNum,int beginTrack,int beginColmn,int beginOrder,int beginStep,std::vector<std::vector<std::string>> cells)2283 void BambooTracker::pastePatternCells(int songNum, int beginTrack, int beginColmn, int beginOrder, int beginStep,
2284 std::vector<std::vector<std::string>> cells)
2285 {
2286 std::vector<std::vector<std::string>> d
2287 = arrangePatternDataCells(songNum, beginTrack, beginColmn, beginOrder, beginStep, std::move(cells));
2288
2289 comMan_.invoke(std::make_unique<PasteCopiedDataToPatternCommand>(
2290 mod_, songNum, beginTrack, beginColmn, beginOrder, beginStep, std::move(d)));
2291 }
2292
pasteMixPatternCells(int songNum,int beginTrack,int beginColmn,int beginOrder,int beginStep,std::vector<std::vector<std::string>> cells)2293 void BambooTracker::pasteMixPatternCells(int songNum, int beginTrack, int beginColmn, int beginOrder, int beginStep,
2294 std::vector<std::vector<std::string>> cells)
2295 {
2296 std::vector<std::vector<std::string>> d
2297 = arrangePatternDataCells(songNum, beginTrack, beginColmn, beginOrder, beginStep, std::move(cells));
2298
2299 comMan_.invoke(std::make_unique<PasteMixCopiedDataToPatternCommand>(
2300 mod_, songNum, beginTrack, beginColmn, beginOrder, beginStep, std::move(d)));
2301 }
2302
pasteOverwritePatternCells(int songNum,int beginTrack,int beginColmn,int beginOrder,int beginStep,std::vector<std::vector<std::string>> cells)2303 void BambooTracker::pasteOverwritePatternCells(int songNum, int beginTrack, int beginColmn, int beginOrder,
2304 int beginStep, std::vector<std::vector<std::string>> cells)
2305 {
2306 std::vector<std::vector<std::string>> d
2307 = arrangePatternDataCells(songNum, beginTrack, beginColmn, beginOrder, beginStep, std::move(cells));
2308
2309 comMan_.invoke(std::make_unique<PasteOverwriteCopiedDataToPatternCommand>(
2310 mod_, songNum, beginTrack, beginColmn, beginOrder, beginStep, std::move(d)));
2311 }
2312
pasteInsertPatternCells(int songNum,int beginTrack,int beginColmn,int beginOrder,int beginStep,std::vector<std::vector<std::string>> cells)2313 void BambooTracker::pasteInsertPatternCells(int songNum, int beginTrack, int beginColmn, int beginOrder,
2314 int beginStep, std::vector<std::vector<std::string>> cells)
2315 {
2316 std::vector<std::vector<std::string>> d
2317 = arrangePatternDataCells(songNum, beginTrack, beginColmn, beginOrder, beginStep, std::move(cells));
2318
2319 comMan_.invoke(std::make_unique<PasteInsertCopiedDataToPatternCommand>(
2320 mod_, songNum, beginTrack, beginColmn, beginOrder, beginStep, std::move(d)));
2321 }
2322
arrangePatternDataCells(int songNum,int beginTrack,int beginColmn,int beginOrder,int beginStep,std::vector<std::vector<std::string>> cells)2323 std::vector<std::vector<std::string>> BambooTracker::arrangePatternDataCells(int songNum, int beginTrack, int beginColmn, int beginOrder, int beginStep,
2324 std::vector<std::vector<std::string>> cells)
2325 {
2326 std::vector<std::vector<std::string>> d;
2327 size_t w = (songStyle_.trackAttribs.size() - static_cast<size_t>(beginTrack) - 1) * 11
2328 + (11 - static_cast<size_t>(beginColmn));
2329 size_t h = getPatternSizeFromOrderNumber(songNum, beginOrder) - static_cast<size_t>(beginStep);
2330
2331 size_t width = std::min(cells.at(0).size(), w);
2332 size_t height = std::min(cells.size(), h);
2333
2334 for (size_t i = 0; i < height; ++i) {
2335 d.emplace_back();
2336 for (size_t j = 0; j < width; ++j) {
2337 d.at(i).push_back(cells.at(i).at(j));
2338 }
2339 }
2340
2341 return d;
2342 }
2343
erasePatternCells(int songNum,int beginTrack,int beginColmn,int beginOrder,int beginStep,int endTrack,int endColmn,int endStep)2344 void BambooTracker::erasePatternCells(int songNum, int beginTrack, int beginColmn, int beginOrder, int beginStep,
2345 int endTrack, int endColmn, int endStep)
2346 {
2347 comMan_.invoke(std::make_unique<EraseCellsInPatternCommand>(
2348 mod_, songNum, beginTrack, beginColmn, beginOrder, beginStep, endTrack, endColmn, endStep));
2349 }
2350
transposeNoteInPattern(int songNum,int beginTrack,int beginOrder,int beginStep,int endTrack,int endStep,int seminote)2351 void BambooTracker::transposeNoteInPattern(int songNum, int beginTrack, int beginOrder, int beginStep,
2352 int endTrack, int endStep, int seminote)
2353 {
2354 comMan_.invoke(std::make_unique<TransposeNoteInPatternCommand>(
2355 mod_, songNum, beginTrack, beginOrder, beginStep, endTrack, endStep, seminote));
2356 }
2357
changeValuesInPattern(int songNum,int beginTrack,int beginColumn,int beginOrder,int beginStep,int endTrack,int endColumn,int endStep,int value)2358 void BambooTracker::changeValuesInPattern(int songNum, int beginTrack, int beginColumn, int beginOrder,
2359 int beginStep, int endTrack, int endColumn, int endStep, int value)
2360 {
2361 comMan_.invoke(std::make_unique<ChangeValuesInPatternCommand>(
2362 mod_, songNum, beginTrack, beginColumn, beginOrder, beginStep,
2363 endTrack, endColumn, endStep, value, volFMReversed_));
2364 }
2365
expandPattern(int songNum,int beginTrack,int beginColmn,int beginOrder,int beginStep,int endTrack,int endColmn,int endStep)2366 void BambooTracker::expandPattern(int songNum, int beginTrack, int beginColmn, int beginOrder, int beginStep,
2367 int endTrack, int endColmn, int endStep)
2368 {
2369 comMan_.invoke(std::make_unique<ExpandPatternCommand>(
2370 mod_, songNum, beginTrack, beginColmn, beginOrder, beginStep, endTrack, endColmn, endStep));
2371 }
2372
shrinkPattern(int songNum,int beginTrack,int beginColmn,int beginOrder,int beginStep,int endTrack,int endColmn,int endStep)2373 void BambooTracker::shrinkPattern(int songNum, int beginTrack, int beginColmn, int beginOrder, int beginStep,
2374 int endTrack, int endColmn, int endStep)
2375 {
2376 comMan_.invoke(std::make_unique<ShrinkPatternCommand>(
2377 mod_, songNum, beginTrack, beginColmn, beginOrder, beginStep, endTrack, endColmn, endStep));
2378 }
2379
interpolatePattern(int songNum,int beginTrack,int beginColmn,int beginOrder,int beginStep,int endTrack,int endColmn,int endStep)2380 void BambooTracker::interpolatePattern(int songNum, int beginTrack, int beginColmn, int beginOrder, int beginStep,
2381 int endTrack, int endColmn, int endStep)
2382 {
2383 comMan_.invoke(std::make_unique<InterpolatePatternCommand>(
2384 mod_, songNum, beginTrack, beginColmn, beginOrder, beginStep, endTrack, endColmn, endStep));
2385 }
2386
reversePattern(int songNum,int beginTrack,int beginColmn,int beginOrder,int beginStep,int endTrack,int endColmn,int endStep)2387 void BambooTracker::reversePattern(int songNum, int beginTrack, int beginColmn, int beginOrder, int beginStep,
2388 int endTrack, int endColmn, int endStep)
2389 {
2390 comMan_.invoke(std::make_unique<ReversePatternCommand>(
2391 mod_, songNum, beginTrack, beginColmn, beginOrder, beginStep, endTrack, endColmn, endStep));
2392 }
2393
replaceInstrumentInPattern(int songNum,int beginTrack,int beginOrder,int beginStep,int endTrack,int endStep,int newInstNum)2394 void BambooTracker::replaceInstrumentInPattern(int songNum, int beginTrack, int beginOrder, int beginStep,
2395 int endTrack, int endStep, int newInstNum)
2396 {
2397 comMan_.invoke(std::make_unique<ReplaceInstrumentInPatternCommand>(
2398 mod_, songNum, beginTrack, beginOrder, beginStep, endTrack, endStep, newInstNum));
2399 }
2400
getPatternSizeFromOrderNumber(int songNum,int orderNum) const2401 size_t BambooTracker::getPatternSizeFromOrderNumber(int songNum, int orderNum) const
2402 {
2403 return mod_->getSong(songNum).getPatternSizeFromOrderNumber(orderNum);
2404 }
2405
setDefaultPatternSize(int songNum,size_t size)2406 void BambooTracker::setDefaultPatternSize(int songNum, size_t size)
2407 {
2408 mod_->getSong(songNum).setDefaultPatternSize(size);
2409 playback_->checkPlayPosition(static_cast<int>(size));
2410 }
2411
getDefaultPatternSize(int songNum) const2412 size_t BambooTracker::getDefaultPatternSize(int songNum) const
2413 {
2414 return mod_->getSong(songNum).getDefaultPatternSize();
2415 }
2416
getOutputHistory(int16_t * container)2417 void BambooTracker::getOutputHistory(int16_t* container)
2418 {
2419 opnaCtrl_->getOutputHistory(container);
2420 }
2421