aboutsummaryrefslogtreecommitdiff
path: root/utils/gen_adldata
diff options
context:
space:
mode:
Diffstat (limited to 'utils/gen_adldata')
-rw-r--r--utils/gen_adldata/CMakeLists.txt5
-rw-r--r--utils/gen_adldata/gen_adldata.cc3
-rw-r--r--utils/gen_adldata/measurer.cpp155
-rw-r--r--utils/gen_adldata/measurer.h6
-rw-r--r--utils/gen_adldata/progs_cache.h7
5 files changed, 121 insertions, 55 deletions
diff --git a/utils/gen_adldata/CMakeLists.txt b/utils/gen_adldata/CMakeLists.txt
index e214534..46c2525 100644
--- a/utils/gen_adldata/CMakeLists.txt
+++ b/utils/gen_adldata/CMakeLists.txt
@@ -19,6 +19,11 @@ list(APPEND GEN_ADLDATA_SRC
ini/ini_processing.cpp
)
+#add_definitions(-DGEN_ADLDATA_DEEP_DEBUG)
+#list(APPEND GEN_ADLDATA_SRC
+# ../midiplay/wave_writer.c
+#)
+
if(USE_DOSBOX_EMULATOR)
set(HAS_EMULATOR TRUE)
list(APPEND GEN_ADLDATA_SRC
diff --git a/utils/gen_adldata/gen_adldata.cc b/utils/gen_adldata/gen_adldata.cc
index f0c1265..2b94ab6 100644
--- a/utils/gen_adldata/gen_adldata.cc
+++ b/utils/gen_adldata/gen_adldata.cc
@@ -341,6 +341,7 @@ int main(int argc, char**argv)
std::fprintf(outFile, "{\n");
MeasureThreaded measureCounter;
+#ifndef GEN_ADLDATA_DEEP_DEBUG // Skip slowest place to work with a debug
{
std::printf("Beginning to generate measures data... (hardware concurrency of %d)\n", std::thread::hardware_concurrency());
std::fflush(stdout);
@@ -358,6 +359,7 @@ int main(int argc, char**argv)
measureCounter.waitAll();
measureCounter.SaveCache("fm_banks/adldata-cache.dat");
}
+#endif
std::printf("Writing generated measure data...\n");
std::fflush(stdout);
@@ -566,6 +568,7 @@ int main(int argc, char**argv)
std::fflush(stdout);
for(size_t b = 0; b < db.instruments.size(); ++b)
{
+ assert(db.instruments[b].instId == b);
measureCounter.run(db, db.instruments[b]);
}
std::fflush(stdout);
diff --git a/utils/gen_adldata/measurer.cpp b/utils/gen_adldata/measurer.cpp
index 1b49011..23e3883 100644
--- a/utils/gen_adldata/measurer.cpp
+++ b/utils/gen_adldata/measurer.cpp
@@ -2,6 +2,10 @@
#include "file_formats/common.h"
#include <cmath>
+#ifdef GEN_ADLDATA_DEEP_DEBUG
+#include "../midiplay/wave_writer.h"
+#endif
+
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
@@ -58,6 +62,14 @@ static const uint16_t g_operatorsMap[(NUM_OF_CHANNELS + NUM_OF_RM_CHANNELS) * 2]
0x011, 0xFFF // operator 13
};
+//! Channel map to regoster offsets
+static const uint16_t g_channelsMap[NUM_OF_CHANNELS] =
+{
+ 0x000, 0x001, 0x002, 0x003, 0x004, 0x005, 0x006, 0x007, 0x008, // 0..8
+ 0x100, 0x101, 0x102, 0x103, 0x104, 0x105, 0x106, 0x107, 0x108, // 9..17 (secondary set)
+ 0x006, 0x007, 0x008, 0x008, 0x008 // <- hw percussions, hihats and cymbals using tom-tom's channel as pitch source
+};
+
template <class T>
class AudioHistory
@@ -130,8 +142,11 @@ struct TinySynth
{
OPLChipBase *m_chip;
unsigned m_notesNum;
- int m_notenum;
- int8_t m_fineTune;
+ unsigned m_actualNotesNum;
+ bool m_isReal4op;
+ bool m_isPseudo4op;
+ int m_playNoteNum;
+ int8_t m_voice1Detune;
int16_t m_noteOffsets[2];
unsigned m_x[2];
@@ -146,6 +161,8 @@ struct TinySynth
m_chip->setRate(g_outputRate);
+ for(size_t a = 0; a < 18; ++a)
+ m_chip->writeReg(0xB0 + g_channelsMap[a], 0x00);
for(unsigned a = 0; a < 18; a += 2)
m_chip->writeReg((uint16_t)initdata[a], (uint8_t)initdata[a + 1]);
}
@@ -173,20 +190,19 @@ struct TinySynth
}
std::memset(m_x, 0, sizeof(m_x));
- m_notenum = in.notenum >= 128 ? (in.notenum - 128) : in.notenum;
- if(m_notenum == 0)
- m_notenum = 25;
+ m_playNoteNum = in.notenum >= 128 ? (in.notenum - 128) : in.notenum;
+ m_isReal4op = in.real4op && !in.pseudo4op;
+ m_isPseudo4op = in.pseudo4op;
+ if(m_playNoteNum == 0)
+ m_playNoteNum = 25;
m_notesNum = in.insno1 == in.insno2 ? 1 : 2;
- m_fineTune = 0;
+ m_actualNotesNum = (m_isReal4op ? 1 : m_notesNum);
+ m_voice1Detune = 0;
m_noteOffsets[0] = rawData[0].finetune;
m_noteOffsets[1] = rawData[1].finetune;
if(in.pseudo4op)
- m_fineTune = in.voice2_fine_tune;
- if(in.real4op)
- {
- m_chip->writeReg(0x105, 1);
- m_chip->writeReg(0x104, 0xFF);
- }
+ m_voice1Detune = in.voice2_fine_tune;
+ m_chip->writeReg(0x104, in.real4op ? (1 << 6) - 1 : 0x00);
//For cleaner measurement, disable tremolo and vibrato
rawData[0].data[0] &= 0x3F;
@@ -206,9 +222,8 @@ struct TinySynth
void setInstrument(const BanksDump &db, const BanksDump::InstrumentEntry &ins)
{
- // TODO: Implement this function correctly!
- bool is4ops = ((ins.instFlags & BanksDump::InstrumentEntry::WOPL_Ins_4op) != 0);
bool isPseudo4ops = ((ins.instFlags & BanksDump::InstrumentEntry::WOPL_Ins_Pseudo4op) != 0);
+ bool is4ops = ((ins.instFlags & BanksDump::InstrumentEntry::WOPL_Ins_4op) != 0) && !isPseudo4ops;
size_t opsNum = (is4ops || isPseudo4ops) ? 4 : 2;
BanksDump::Operator ops[4];
assert(ins.ops[0] >= 0);
@@ -224,24 +239,25 @@ struct TinySynth
}
std::memset(m_x, 0, sizeof(m_x));
- m_notenum = ins.percussionKeyNumber >= 128 ? (ins.percussionKeyNumber - 128) : ins.percussionKeyNumber;
- if(m_notenum == 0)
- m_notenum = 25;
+ m_playNoteNum = ins.percussionKeyNumber >= 128 ? (ins.percussionKeyNumber - 128) : ins.percussionKeyNumber;
+ m_isReal4op = is4ops;
+ m_isPseudo4op = isPseudo4ops;
+ if(m_playNoteNum == 0)
+ m_playNoteNum = 60;
m_notesNum = opsNum / 2;
- m_fineTune = 0;
+ m_actualNotesNum = (m_isReal4op ? 1 : m_notesNum);
+ m_voice1Detune = 0;
m_noteOffsets[0] = ins.noteOffset1;
m_noteOffsets[1] = ins.noteOffset2;
if(isPseudo4ops)
- m_fineTune = ins.secondVoiceDetune;
- if(is4ops)
- {
- m_chip->writeReg(0x105, 1);
- m_chip->writeReg(0x104, 0xFF);
- }
+ m_voice1Detune = ins.secondVoiceDetune;
+ m_chip->writeReg(0x104, is4ops ? (1 << 6) - 1 : 0x00);
//For cleaner measurement, disable tremolo and vibrato
- ops[0].d_E862 &= 0xFFFF3F3F;
- ops[1].d_E862 &= 0xFFFF3F3F;
+ ops[0].d_E862 &= 0xFFFFFF3F;
+ ops[1].d_E862 &= 0xFFFFFF3F;
+ ops[2].d_E862 &= 0xFFFFFF3F;
+ ops[3].d_E862 &= 0xFFFFFF3F;
// rawData[0].data[0] &= 0x3F;
// rawData[0].data[1] &= 0x3F;
// rawData[1].data[0] &= 0x3F;
@@ -252,16 +268,19 @@ struct TinySynth
static const uint8_t data[4] = {0x20, 0x60, 0x80, 0xE0};
uint16_t o1 = g_operatorsMap[0];
uint16_t o2 = g_operatorsMap[1];
- unsigned x = ops[0].d_E862, y = ops[1].d_E862;
+ size_t opOffset = (n * 2);
+ uint_fast32_t x1 = ops[opOffset + 0].d_E862, y1 = ops[opOffset + 1].d_E862;
+ uint_fast8_t x2 = ops[opOffset + 0].d_40, y2 = ops[opOffset + 1].d_40;
+ uint_fast8_t fbConn = (ins.fbConn >> (n * 8)) & 0xFF;
- for(size_t a = 0; a < 4; ++a, x >>= 8, y >>= 8)
+ for(size_t a = 0; a < 4; ++a, x1 >>= 8, y1 >>= 8)
{
- if(o1 != 0xFFF)
- m_chip->writeReg(data[a] + o1, x & 0xFF);
- if(o2 != 0xFFF)
- m_chip->writeReg(data[a] + o2, y & 0xFF);
+ m_chip->writeReg(data[a] + o1, x1 & 0xFF);
+ m_chip->writeReg(data[a] + o2, y1 & 0xFF);
}
- m_chip->writeReg(0xC0 + n * 8, (ins.fbConn >> n * 8) & 0xFF);
+ m_chip->writeReg(0xC0 + (n * 8), fbConn | 0x30);
+ m_chip->writeReg(0x40 + o1, x2 & 0xFF);
+ m_chip->writeReg(0x40 + o2, y2 & 0xFF);
}
// for(unsigned n = 0; n < m_notesNum; ++n)
@@ -269,27 +288,25 @@ struct TinySynth
// static const unsigned char patchdata[11] =
// {0x20, 0x23, 0x60, 0x63, 0x80, 0x83, 0xE0, 0xE3, 0x40, 0x43, 0xC0};
// for(unsigned a = 0; a < 10; ++a)
-// {
// m_chip->writeReg(patchdata[a] + n * 8, rawData[n].data[a]);
-// }
-// m_chip->writeReg(patchdata[10] + n * 8, (ins.fbConn >> n * 8) & 0xFF);
+// m_chip->writeReg(patchdata[10] + n * 8, rawData[n].data[10] | 0x30);
// }
}
void noteOn()
{
std::memset(m_x, 0, sizeof(m_x));
- for(unsigned n = 0; n < m_notesNum; ++n)
+ for(unsigned n = 0; n < m_actualNotesNum; ++n)
{
- double hertz = 172.00093 * std::exp(0.057762265 * (m_notenum + m_noteOffsets[n]));
+ double hertz = 172.00093 * std::exp(0.057762265 * (m_playNoteNum + m_noteOffsets[n]));
if(hertz > 131071)
{
std::fprintf(stdout, "%s:%d:0: warning: Why does note %d + note-offset %d produce hertz %g?\n", __FILE__, __LINE__,
- m_notenum, m_noteOffsets[n], hertz);
+ m_playNoteNum, m_noteOffsets[n], hertz);
std::fflush(stdout);
hertz = 131071;
}
- m_x[n] = 0x2000;
+ m_x[n] = 0x2000u;
while(hertz >= 1023.5)
{
hertz /= 2.0; // Calculate octave
@@ -298,16 +315,16 @@ struct TinySynth
m_x[n] += (unsigned int)(hertz + 0.5);
// Keyon the note
- m_chip->writeReg(0xA0 + n * 3, m_x[n] & 0xFF);
- m_chip->writeReg(0xB0 + n * 3, m_x[n] >> 8);
+ m_chip->writeReg(0xA0 + (n * 3), m_x[n] & 0xFF);
+ m_chip->writeReg(0xB0 + (n * 3), (m_x[n] >> 8) & 0xFF);
}
}
void noteOff()
{
// Keyoff the note
- for(unsigned n = 0; n < m_notesNum; ++n)
- m_chip->writeReg(0xB0 + n * 3, (m_x[n] >> 8) & 0xDF);
+ for(unsigned n = 0; n < m_actualNotesNum; ++n)
+ m_chip->writeReg(0xB0 + (n * 3), (m_x[n] >> 8) & 0xDF);
}
void generate(int16_t *output, size_t frames)
@@ -528,6 +545,19 @@ DurationInfo MeasureDurations(BanksDump &db, const BanksDump::InstrumentEntry &i
synth.setInstrument(db, ins);
synth.noteOn();
+#ifdef GEN_ADLDATA_DEEP_DEBUG
+ /*****************DEBUG******************/
+ char waveFileOut[80] = "";
+ std::snprintf(waveFileOut, 80, "fm_banks/_deep_debug/%04lu_%s_%u_an_%u_no.wav",
+ ins.instId, synth.m_isPseudo4op ? "pseudo4op" :
+ synth.m_isReal4op ? "4op" : "2op",
+ synth.m_actualNotesNum,
+ synth.m_notesNum);
+ void *waveCtx = ctx_wave_open(g_outputRate, waveFileOut);
+ ctx_wave_enable_stereo(waveCtx);
+ /*****************DEBUG******************/
+#endif
+
/* For capturing */
const unsigned max_silent = 6;
const unsigned max_on = 40;
@@ -566,6 +596,11 @@ DurationInfo MeasureDurations(BanksDump &db, const BanksDump::InstrumentEntry &i
size_t blocksize = samples_per_interval - i;
blocksize = (blocksize < audioBufferLength) ? blocksize : audioBufferLength;
synth.generate(audioBuffer, blocksize);
+#ifdef GEN_ADLDATA_DEEP_DEBUG
+ /***************DEBUG******************/
+ ctx_wave_write(waveCtx, audioBuffer, blocksize * 2);
+ /***************DEBUG******************/
+#endif
for (unsigned j = 0; j < blocksize; ++j)
{
int16_t s = audioBuffer[2 * j];
@@ -697,11 +732,26 @@ DurationInfo MeasureDurations(BanksDump &db, const BanksDump::InstrumentEntry &i
db.instruments[ins.instId].delay_on_ms = result.ms_sound_kon;
db.instruments[ins.instId].delay_off_ms = result.ms_sound_koff;
+ if(result.nosound)
+ db.instruments[ins.instId].instFlags |= BanksDump::InstrumentEntry::WOPL_Ins_IsBlank;
+#ifdef GEN_ADLDATA_DEEP_DEBUG
+ /***************DEBUG******************/
+ ctx_wave_close(waveCtx);
+ /***************DEBUG******************/
+#endif
return result;
}
+MeasureThreaded::MeasureThreaded() :
+ m_semaphore(int(std::thread::hardware_concurrency()) * 2),
+ m_done(0),
+ m_cache_matches(0)
+{
+ DosBoxOPL3::globalPreInit();
+}
+
void MeasureThreaded::LoadCache(const char *fileName)
{
m_durationInfo.clear();
@@ -983,7 +1033,7 @@ void MeasureThreaded::LoadCacheX(const char *fileName)
OperatorsKey k;
DurationInfo v;
- uint8_t data_k[4];
+ uint8_t data_k[5];
for(auto &kv : k)
{
@@ -1000,8 +1050,8 @@ void MeasureThreaded::LoadCacheX(const char *fileName)
kv = static_cast<int_fast32_t>(toSint32LE(data));
}
- auto ret = std::fread(data_k, 1, 4, in);
- if(ret != 4)
+ auto ret = std::fread(data_k, 1, 5, in);
+ if(ret != 5)
{
std::fclose(in);
std::printf("Failed to load CacheX: unexpected end of file.\n"
@@ -1012,6 +1062,7 @@ void MeasureThreaded::LoadCacheX(const char *fileName)
v.ms_sound_kon = static_cast<int_fast64_t>(toUint16LE(data_k + 0));
v.ms_sound_koff = static_cast<int_fast64_t>(toUint16LE(data_k + 2));
+ v.nosound = (data_k[4] == 0x01);
m_durationInfoX.insert({k, v});
itemsCount--;
@@ -1043,12 +1094,13 @@ void MeasureThreaded::SaveCacheX(const char *fileName)
const OperatorsKey &k = it->first;
const DurationInfo &v = it->second;
- uint8_t data_k[4] =
+ uint8_t data_k[5] =
{
static_cast<uint8_t>((v.ms_sound_kon >> 0) & 0xFF),
static_cast<uint8_t>((v.ms_sound_kon >> 8) & 0xFF),
static_cast<uint8_t>((v.ms_sound_koff >> 0) & 0xFF),
- static_cast<uint8_t>((v.ms_sound_koff >> 8) & 0xFF)
+ static_cast<uint8_t>((v.ms_sound_koff >> 8) & 0xFF),
+ static_cast<uint8_t>(v.nosound ? 0x01 : 0x00)
};
for(auto &kv : k)
@@ -1062,7 +1114,7 @@ void MeasureThreaded::SaveCacheX(const char *fileName)
};
std::fwrite(data, 1, 4, out);
}
- std::fwrite(data_k, 1, 4, out);
+ std::fwrite(data_k, 1, 5, out);
}
std::fclose(out);
}
@@ -1178,6 +1230,7 @@ void MeasureThreaded::destData::callback(void *myself)
destData *s = reinterpret_cast<destData *>(myself);
DurationInfo info;
DosBoxOPL3 dosbox;
+ // NukedOPL3 dosbox;
if(s->bd)
{
@@ -1192,6 +1245,8 @@ void MeasureThreaded::destData::callback(void *myself)
const DurationInfo &di = cachedEntry->second;
s->bd_ins->delay_on_ms = di.ms_sound_kon;
s->bd_ins->delay_off_ms = di.ms_sound_koff;
+ if(di.nosound)
+ s->bd_ins->instFlags |= BanksDump::InstrumentEntry::WOPL_Ins_IsBlank;
s->myself->m_cache_matches++;
goto endWork;
}
diff --git a/utils/gen_adldata/measurer.h b/utils/gen_adldata/measurer.h
index ed7810a..d2b8a76 100644
--- a/utils/gen_adldata/measurer.h
+++ b/utils/gen_adldata/measurer.h
@@ -59,11 +59,7 @@ struct MeasureThreaded
typedef std::map<ins, DurationInfo> DurationInfoCache;
typedef std::map<OperatorsKey, DurationInfo> DurationInfoCacheX;
- MeasureThreaded() :
- m_semaphore(int(std::thread::hardware_concurrency()) * 2),
- m_done(0),
- m_cache_matches(0)
- {}
+ MeasureThreaded();
Semaphore m_semaphore;
std::mutex m_durationInfo_mx;
diff --git a/utils/gen_adldata/progs_cache.h b/utils/gen_adldata/progs_cache.h
index 09f75f6..34e42a3 100644
--- a/utils/gen_adldata/progs_cache.h
+++ b/utils/gen_adldata/progs_cache.h
@@ -335,6 +335,13 @@ struct BanksDump
uint_fast32_t opId = 0;
uint_fast32_t d_E862 = 0;
uint_fast32_t d_40 = 0;
+ explicit Operator() {}
+ Operator(const Operator &o)
+ {
+ opId = o.opId;
+ d_E862 = o.d_E862;
+ d_40 = o.d_40;
+ }
bool operator==(const Operator &o)
{
return ((d_E862 == o.d_E862) && (d_40 == o.d_40));