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 "bank.hpp"
27 #include <stdio.h>
28 #include <utility>
29 #include "instrument_io.hpp"
30 #include "format/wopn_file.h"
31 
BtBank(std::vector<int> ids,std::vector<std::string> names)32 BtBank::BtBank(std::vector<int> ids, std::vector<std::string> names)
33 	: ids_(std::move(ids)),
34 	  names_(std::move(names))
35 {
36 }
37 
BtBank(std::vector<int> ids,std::vector<std::string> names,std::vector<BinaryContainer> instSecs,BinaryContainer propSec,uint32_t version)38 BtBank::BtBank(std::vector<int> ids, std::vector<std::string> names,
39 			   std::vector<BinaryContainer> instSecs, BinaryContainer propSec, uint32_t version)
40 	: instCtrs_(std::move(instSecs)),
41 	  propCtr_(std::move(propSec)),
42 	  ids_(std::move(ids)),
43 	  names_(std::move(names)),
44 	  version_(version)
45 {
46 }
47 
~BtBank()48 BtBank::~BtBank()
49 {
50 }
51 
getNumInstruments() const52 size_t BtBank::getNumInstruments() const
53 {
54 	return ids_.size();
55 }
56 
getInstrumentIdentifier(size_t index) const57 std::string BtBank::getInstrumentIdentifier(size_t index) const
58 {
59 	return std::to_string(ids_.at(index));
60 }
61 
getInstrumentName(size_t index) const62 std::string BtBank::getInstrumentName(size_t index) const
63 {
64 	return names_.at(index);
65 }
66 
loadInstrument(size_t index,std::weak_ptr<InstrumentsManager> instMan,int instNum) const67 AbstractInstrument* BtBank::loadInstrument(size_t index, std::weak_ptr<InstrumentsManager> instMan, int instNum) const
68 {
69 	return InstrumentIO::loadBTBInstrument(instCtrs_.at(static_cast<size_t>(index)), propCtr_, instMan, instNum, version_);
70 }
71 
72 /******************************/
operator ()(WOPNFile * x)73 void WopnBank::WOPNDeleter::operator()(WOPNFile *x)
74 {
75 	WOPN_Free(x);
76 }
77 
78 struct WopnBank::InstEntry
79 {
80 	WOPNInstrument *inst;
81 	struct ValuesType
82 	{
83 		bool percussive : 1;
84 		unsigned msb : 7;
85 		unsigned lsb : 7;
86 		unsigned nth : 7;
87 	} vals;
88 };
89 
WopnBank(WOPNFile * wopn)90 WopnBank::WopnBank(WOPNFile *wopn)
91 	: wopn_(wopn)
92 {
93 	unsigned numM = wopn->banks_count_melodic;
94 	unsigned numP = wopn->banks_count_percussion;
95 
96 	size_t instMax = 128 * (numP + numM);
97 	entries_.reserve(instMax);
98 
99 	for (size_t i = 0; i < instMax; ++i) {
100 		InstEntry ent;
101 		ent.vals.percussive = (i / 128) >= numM;
102 		WOPNBank& bank = ent.vals.percussive
103 						 ? wopn->banks_percussive[(i / 128) - numM]
104 						 : wopn->banks_melodic[i / 128];
105 		ent.vals.msb = bank.bank_midi_msb;
106 		ent.vals.lsb = bank.bank_midi_lsb;
107 		ent.vals.nth = i % 128;
108 		ent.inst = &bank.ins[ent.vals.nth];
109 		if ((ent.inst->inst_flags & WOPN_Ins_IsBlank) == 0)
110 			entries_.push_back(ent);
111 	}
112 
113 	entries_.shrink_to_fit();
114 }
115 
~WopnBank()116 WopnBank::~WopnBank()
117 {
118 }
119 
getNumInstruments() const120 size_t WopnBank::getNumInstruments() const
121 {
122 	return entries_.size();
123 }
124 
getInstrumentIdentifier(size_t index) const125 std::string WopnBank::getInstrumentIdentifier(size_t index) const
126 {
127 	const InstEntry &ent = entries_.at(index);
128 	char identifier[64];
129 	sprintf(identifier, "%c%03d:%03d:%03d", "MP"[ent.vals.percussive],
130 			ent.vals.msb, ent.vals.lsb, ent.vals.nth);
131 	return identifier;
132 }
133 
getInstrumentName(size_t index) const134 std::string WopnBank::getInstrumentName(size_t index) const
135 {
136 	const InstEntry &ent = entries_.at(index);
137 	return ent.inst->inst_name;
138 }
139 
loadInstrument(size_t index,std::weak_ptr<InstrumentsManager> instMan,int instNum) const140 AbstractInstrument* WopnBank::loadInstrument(size_t index, std::weak_ptr<InstrumentsManager> instMan, int instNum) const
141 {
142 	const InstEntry &ent = entries_.at(index);
143 	return InstrumentIO::loadWOPNInstrument(*ent.inst, instMan, instNum);
144 }
145 
146 /******************************/
FfBank(std::vector<int> ids,std::vector<std::string> names,std::vector<BinaryContainer> ctrs)147 FfBank::FfBank(std::vector<int> ids, std::vector<std::string> names, std::vector<BinaryContainer> ctrs)
148 	: ids_(ids), names_(names), instCtrs_(ctrs)
149 {
150 }
151 
getNumInstruments() const152 size_t FfBank::getNumInstruments() const
153 {
154 	return ids_.size();
155 }
156 
getInstrumentIdentifier(size_t index) const157 std::string FfBank::getInstrumentIdentifier(size_t index) const
158 {
159 	return std::to_string(ids_.at(index));
160 }
161 
getInstrumentName(size_t index) const162 std::string FfBank::getInstrumentName(size_t index) const
163 {
164 	return names_.at(index);
165 }
166 
loadInstrument(size_t index,std::weak_ptr<InstrumentsManager> instMan,int instNum) const167 AbstractInstrument* FfBank::loadInstrument(size_t index, std::weak_ptr<InstrumentsManager> instMan, int instNum) const
168 {
169 	return InstrumentIO::loadFFInstrument(instCtrs_.at(index), names_.at(index), instMan, instNum);
170 }
171 
setInstrumentName(size_t index,const std::string & name)172 void FfBank::setInstrumentName(size_t index, const std::string& name)
173 {
174 	names_.at(index) = name;
175 }
176 
177 /******************************/
PpcBank(std::vector<int> ids,std::vector<std::vector<uint8_t>> samples)178 PpcBank::PpcBank(std::vector<int> ids, std::vector<std::vector<uint8_t> > samples)
179 	: ids_(ids), samples_(samples)
180 {
181 }
182 
getNumInstruments() const183 size_t PpcBank::getNumInstruments() const
184 {
185 	return samples_.size();
186 }
187 
getInstrumentIdentifier(size_t index) const188 std::string PpcBank::getInstrumentIdentifier(size_t index) const
189 {
190 	return std::to_string(ids_.at(index));
191 }
192 
getInstrumentName(size_t index) const193 std::string PpcBank::getInstrumentName(size_t index) const
194 {
195 	(void)index;
196 	return "";
197 }
198 
loadInstrument(size_t index,std::weak_ptr<InstrumentsManager> instMan,int instNum) const199 AbstractInstrument* PpcBank::loadInstrument(size_t index, std::weak_ptr<InstrumentsManager> instMan, int instNum) const
200 {
201 	return InstrumentIO::loadPPCInstrument(samples_.at(index), instMan, instNum);
202 }
203 
204 /******************************/
PviBank(std::vector<int> ids,std::vector<std::vector<uint8_t>> samples)205 PviBank::PviBank(std::vector<int> ids, std::vector<std::vector<uint8_t> > samples)
206 	: ids_(ids), samples_(samples)
207 {
208 }
209 
getNumInstruments() const210 size_t PviBank::getNumInstruments() const
211 {
212 	return samples_.size();
213 }
214 
getInstrumentIdentifier(size_t index) const215 std::string PviBank::getInstrumentIdentifier(size_t index) const
216 {
217 	return std::to_string(ids_.at(index));
218 }
219 
getInstrumentName(size_t index) const220 std::string PviBank::getInstrumentName(size_t index) const
221 {
222 	(void)index;
223 	return "";
224 }
225 
loadInstrument(size_t index,std::weak_ptr<InstrumentsManager> instMan,int instNum) const226 AbstractInstrument* PviBank::loadInstrument(size_t index, std::weak_ptr<InstrumentsManager> instMan, int instNum) const
227 {
228 	return InstrumentIO::loadPVIInstrument(samples_.at(index), instMan, instNum);
229 }
230 
231 /******************************/
Mucom88Bank(std::vector<int> ids,std::vector<std::string> names,std::vector<BinaryContainer> ctrs)232 Mucom88Bank::Mucom88Bank(std::vector<int> ids, std::vector<std::string> names, std::vector<BinaryContainer> ctrs)
233 	: ids_(ids), names_(names), instCtrs_(ctrs)
234 {
235 }
236 
getNumInstruments() const237 size_t Mucom88Bank::getNumInstruments() const
238 {
239 	return ids_.size();
240 }
241 
getInstrumentIdentifier(size_t index) const242 std::string Mucom88Bank::getInstrumentIdentifier(size_t index) const
243 {
244 	return std::to_string(ids_.at(index));
245 }
246 
getInstrumentName(size_t index) const247 std::string Mucom88Bank::getInstrumentName(size_t index) const
248 {
249 	return names_.at(index);
250 }
251 
loadInstrument(size_t index,std::weak_ptr<InstrumentsManager> instMan,int instNum) const252 AbstractInstrument* Mucom88Bank::loadInstrument(size_t index, std::weak_ptr<InstrumentsManager> instMan, int instNum) const
253 {
254 	return InstrumentIO::loadMUCOM88Instrument(instCtrs_.at(index), names_.at(index), instMan, instNum);
255 }
256 
setInstrumentName(size_t index,const std::string & name)257 void Mucom88Bank::setInstrumentName(size_t index, const std::string& name)
258 {
259 	names_.at(index) = name;
260 }
261