20static constexpr unsigned CHANNELS = 11;
35using Log = vector<LogEvent>;
39static void error(
const string& message)
41 cout << message <<
'\n';
45static void saveWav(
const string& filename,
const Samples& data)
48 writer.write16mono(&data[0], data.size());
51static void loadWav(
const string& filename,
Samples& data)
54 assert(wav.getFreq() == 3579545 / 72);
56 auto rawData = wav.getData();
57 data.assign(rawData, rawData + wav.getSize());
60static void loadWav(
Samples& data)
63 loadWav(filename, data);
66static void createSilence(
const Log& log,
Samples& result)
77 const Samples* expectedSamples[CHANNELS])
79 cout <<
" test " <<
testName <<
" ...\n";
81 Samples generatedSamples[CHANNELS];
85 for (
auto& w : l.regWrites) {
86 core.writeReg(w.reg, w.val);
89 unsigned samples = l.samples;
93 unsigned oldSize = generatedSamples[0].size();
94 for (
unsigned i = 0; i < CHANNELS; ++i) {
95 generatedSamples[i].resize(oldSize + samples);
96 bufs[i] = &generatedSamples[i][oldSize];
106 for (
unsigned i = 0; i < CHANNELS; ++i) {
107 for (
unsigned j = 0; j < generatedSamples[i].size(); ++j) {
108 int s = generatedSamples[i][j];
110 assert(s == int16_t(s));
111 generatedSamples[i][j] = s;
116 for (
unsigned i = 0; i < CHANNELS; ++i) {
117 string msg =
strCat(
"Error in channel ", i,
": ");
119 if (generatedSamples[i].
size() != expectedSamples[i]->
size()) {
120 strAppend(msg,
"wrong size, expected ", expectedSamples[i]->
size(),
121 " but got ", generatedSamples[i].
size());
123 }
else if (generatedSamples[i] != *expectedSamples[i]) {
131 strAppend(msg,
" writing data to ", filename);
133 saveWav(filename, generatedSamples[i]);
138static void testSingleChannel(
YM2413Core& core,
const Log& log,
139 const Samples& channelData,
unsigned channelNum)
142 createSilence(log, silence);
144 const Samples* samples[CHANNELS];
145 for (
unsigned i = 0; i < CHANNELS; ++i) {
146 if (i == channelNum) {
147 samples[i] = &channelData;
149 samples[i] = &silence;
153 test(core, log, samples);
165 log.push_back(event);
168 createSilence(log, silence);
170 const Samples* samples[CHANNELS];
171 for (
unsigned i = 0; i < CHANNELS; ++i) {
172 samples[i] = &silence;
175 test(core, log, samples);
184 event.
regWrites.emplace_back(0x30, 0x10);
185 event.regWrites.emplace_back(0x10, 0xAD);
186 event.regWrites.emplace_back(0x20, 0x14);
187 event.samples = 11000;
188 log.push_back(event);
192 event.
regWrites.emplace_back(0x20, 0x16);
193 event.samples = 11000;
194 log.push_back(event);
198 event.
regWrites.emplace_back(0x20, 0x06);
199 event.samples = 11000;
200 log.push_back(event);
205 testSingleChannel(core, log, gold, 0);
208template<
typename CORE,
typename FUNC>
void testOnCore(FUNC f)
214template<
typename CORE>
static void testAll(
const string& coreName_)
217 cout <<
"Testing YM2413 core " <<
coreName <<
'\n';
218 testOnCore<CORE>(testSilence);
219 testOnCore<CORE>(testViolin);
225 testAll<YM2413Okazaki:: YM2413>(
"Okazaki");
226 testAll<YM2413Burczynski::YM2413>(
"Burczynski");
vector< RegWrite > RegWrites
This class represents a filename.
Base class for writing WAV files.
Abstract interface for the YM2413 core.
virtual float getAmplificationFactor() const =0
Returns normalization factor.
virtual void generateChannels(std::span< float *, 9+5 > bufs, unsigned num)=0
Generate the sound output.
constexpr double log(double x)
This file implemented 3 utility functions:
size_t size(std::string_view utf8)
void strAppend(std::string &result, Ts &&...ts)
vector< RegWrite > regWrites
RegWrite(byte reg_, byte val_)