mirror of https://github.com/AxioDL/amuse.git
More athena refactoring
This commit is contained in:
parent
4c884d019d
commit
26cfa07f77
|
@ -18,6 +18,7 @@ endif()
|
|||
|
||||
atdna(atdna_AudioGroupPool.cpp include/amuse/AudioGroupPool.hpp)
|
||||
atdna(atdna_AudioGroupProject.cpp include/amuse/AudioGroupProject.hpp)
|
||||
atdna(atdna_AudioGroupSampleDirectory.cpp include/amuse/AudioGroupSampleDirectory.hpp)
|
||||
|
||||
set(SOURCES
|
||||
lib/AudioGroup.cpp
|
||||
|
@ -45,7 +46,8 @@ set(SOURCES
|
|||
lib/DSPCodec.cpp
|
||||
lib/N64MusyXCodec.cpp
|
||||
atdna_AudioGroupPool.cpp
|
||||
atdna_AudioGroupProject.cpp)
|
||||
atdna_AudioGroupProject.cpp
|
||||
atdna_AudioGroupSampleDirectory.cpp)
|
||||
|
||||
set(HEADERS
|
||||
include/amuse/AudioGroup.hpp
|
||||
|
|
|
@ -211,7 +211,6 @@ void MainWindow::importAction()
|
|||
|
||||
QFileInfo fInfo(path);
|
||||
QString newPath = QFileInfo(fInfo.dir(), newName).filePath();
|
||||
printf("%s\n", newPath.toUtf8().data());
|
||||
if (!MkPath(fInfo.dir(), newName, this))
|
||||
return;
|
||||
if (!setProjectPath(newPath))
|
||||
|
@ -227,7 +226,7 @@ void MainWindow::importAction()
|
|||
auto data = amuse::ContainerRegistry::LoadContainer(QStringToSysString(dir.filePath(fPath)).c_str());
|
||||
for (auto& p : data)
|
||||
if (!m_projectModel->importGroupData(SysStringToQString(p.first), std::move(p.second),
|
||||
ProjectModel::ImportMode(impMode), this))
|
||||
ProjectModel::ImportMode(impMode)))
|
||||
return;
|
||||
}
|
||||
m_projectModel->saveToFile(this);
|
||||
|
@ -256,7 +255,7 @@ void MainWindow::importAction()
|
|||
auto data = amuse::ContainerRegistry::LoadContainer(QStringToSysString(path).c_str());
|
||||
for (auto& p : data)
|
||||
if (!m_projectModel->importGroupData(SysStringToQString(p.first), std::move(p.second),
|
||||
ProjectModel::ImportMode(impMode), this))
|
||||
ProjectModel::ImportMode(impMode)))
|
||||
return;
|
||||
|
||||
m_projectModel->saveToFile(this);
|
||||
|
@ -328,7 +327,7 @@ void MainWindow::onFocusChanged(QWidget* old, QWidget* now)
|
|||
if (QLineEdit* le = qobject_cast<QLineEdit*>(now))
|
||||
{
|
||||
m_undoConn = connect(m_ui.actionUndo, SIGNAL(triggered()), le, SLOT(undo()));
|
||||
m_canUndoConn = connect(le, SIGNAL(textChanged()), this, SLOT(onTextEdited()));
|
||||
m_canUndoConn = connect(le, SIGNAL(textChanged(const QString&)), this, SLOT(onTextEdited()));
|
||||
m_ui.actionUndo->setEnabled(le->isUndoAvailable());
|
||||
m_redoConn = connect(m_ui.actionRedo, SIGNAL(triggered()), le, SLOT(redo()));
|
||||
m_ui.actionRedo->setEnabled(le->isRedoAvailable());
|
||||
|
|
|
@ -17,111 +17,40 @@ ProjectModel::ProjectGroup::ProjectGroup(amuse::IntrusiveAudioGroupData&& data)
|
|||
m_sdir(amuse::AudioGroupSampleDirectory::CreateAudioGroupSampleDirectory(m_data))
|
||||
{}
|
||||
|
||||
bool ProjectModel::importGroupData(const QString& groupName,
|
||||
amuse::IntrusiveAudioGroupData&& data,
|
||||
ImportMode mode, QWidget* parent)
|
||||
bool ProjectModel::importGroupData(const QString& groupName, amuse::IntrusiveAudioGroupData&& data, ImportMode mode)
|
||||
{
|
||||
amuse::SongId::CurNameDB = &m_songDb;
|
||||
amuse::SongId::CurNameDB = &m_sfxDb;
|
||||
setIdDatabases();
|
||||
|
||||
ProjectGroup& grp = m_groups.insert(std::make_pair(groupName, std::move(data))).first->second;
|
||||
|
||||
for (const auto& p : grp.m_proj.songGroups())
|
||||
{
|
||||
for (const auto& song : p.second.m_midiSetups)
|
||||
{
|
||||
char name[16];
|
||||
snprintf(name, 16, "song%d", song.first.id);
|
||||
m_songDb.registerPair(name, song.first);
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& p : grp.m_proj.sfxGroups())
|
||||
{
|
||||
for (const auto& sfx : p.second.m_sfxEntries)
|
||||
{
|
||||
char name[16];
|
||||
snprintf(name, 16, "sfx%d", sfx.first.id);
|
||||
m_sfxDb.registerPair(name, sfx.first);
|
||||
}
|
||||
}
|
||||
grp.setIdDatabases();
|
||||
amuse::AudioGroupProject::BootstrapObjectIDs(grp.m_data);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ProjectModel::saveToFile(QWidget* parent)
|
||||
{
|
||||
amuse::SongId::CurNameDB = &m_songDb;
|
||||
amuse::SongId::CurNameDB = &m_sfxDb;
|
||||
setIdDatabases();
|
||||
|
||||
if (!MkPath(m_dir.path(), parent))
|
||||
return false;
|
||||
|
||||
for (auto& g : m_groups)
|
||||
{
|
||||
athena::io::YAMLDocWriter w("amuse::Group");
|
||||
|
||||
QDir dir(QFileInfo(m_dir, g.first).filePath());
|
||||
if (!MkPath(dir.path(), parent))
|
||||
return false;
|
||||
|
||||
if (auto __v = w.enterSubVector("songGroups"))
|
||||
g.second.setIdDatabases();
|
||||
{
|
||||
for (const auto& p : g.second.m_proj.songGroups())
|
||||
{
|
||||
if (auto __r = w.enterSubRecord(nullptr))
|
||||
{
|
||||
if (auto __v2 = w.enterSubRecord("normPages"))
|
||||
{
|
||||
for (const auto& pg : p.second.m_normPages)
|
||||
{
|
||||
char name[16];
|
||||
snprintf(name, 16, "%d", pg.first);
|
||||
if (auto __r2 = w.enterSubRecord(name))
|
||||
pg.second.toDNA<athena::Big>(pg.first).write(w);
|
||||
}
|
||||
}
|
||||
if (auto __v2 = w.enterSubRecord("drumPages"))
|
||||
{
|
||||
for (const auto& pg : p.second.m_drumPages)
|
||||
{
|
||||
char name[16];
|
||||
snprintf(name, 16, "%d", pg.first);
|
||||
if (auto __r2 = w.enterSubRecord(name))
|
||||
pg.second.toDNA<athena::Big>(pg.first).write(w);
|
||||
}
|
||||
}
|
||||
if (auto __v2 = w.enterSubRecord("songs"))
|
||||
{
|
||||
for (const auto& song : p.second.m_midiSetups)
|
||||
{
|
||||
if (auto __v3 = w.enterSubVector(m_songDb.resolveNameFromId(song.first).data()))
|
||||
for (int i = 0; i < 16; ++i)
|
||||
if (auto __r2 = w.enterSubRecord(nullptr))
|
||||
song.second[i].write(w);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
athena::io::FileWriter fo(QStringToSysString(dir.filePath("!project.yaml")));
|
||||
g.second.m_proj.toYAML(fo);
|
||||
}
|
||||
|
||||
if (auto __v = w.enterSubVector("sfxGroups"))
|
||||
{
|
||||
for (const auto& p : g.second.m_proj.sfxGroups())
|
||||
{
|
||||
if (auto __r = w.enterSubRecord(nullptr))
|
||||
{
|
||||
for (const auto& sfx : p.second.m_sfxEntries)
|
||||
{
|
||||
if (auto __r2 = w.enterSubRecord(m_sfxDb.resolveNameFromId(sfx.first).data()))
|
||||
sfx.second.toDNA<athena::Big>(sfx.first).write(w);
|
||||
}
|
||||
}
|
||||
}
|
||||
athena::io::FileWriter fo(QStringToSysString(dir.filePath("!pool.yaml")));
|
||||
g.second.m_pool.toYAML(fo);
|
||||
}
|
||||
|
||||
athena::io::FileWriter fo(QStringToSysString(dir.filePath("project.yaml")));
|
||||
w.finish(&fo);
|
||||
//g.second.m_sdir.sampleEntries()
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -25,8 +25,21 @@ public:
|
|||
amuse::AudioGroupProject m_proj;
|
||||
amuse::AudioGroupPool m_pool;
|
||||
amuse::AudioGroupSampleDirectory m_sdir;
|
||||
amuse::NameDB m_soundMacroDb;
|
||||
amuse::NameDB m_sampleDb;
|
||||
amuse::NameDB m_tableDb;
|
||||
amuse::NameDB m_keymapDb;
|
||||
amuse::NameDB m_layersDb;
|
||||
|
||||
explicit ProjectGroup(amuse::IntrusiveAudioGroupData&& data);
|
||||
void setIdDatabases()
|
||||
{
|
||||
amuse::SoundMacroId::CurNameDB = &m_soundMacroDb;
|
||||
amuse::SampleId::CurNameDB = &m_sampleDb;
|
||||
amuse::TableId::CurNameDB = &m_tableDb;
|
||||
amuse::KeymapId::CurNameDB = &m_keymapDb;
|
||||
amuse::LayersId::CurNameDB = &m_layersDb;
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
|
@ -36,11 +49,16 @@ private:
|
|||
amuse::NameDB m_sfxDb;
|
||||
std::map<QString, ProjectGroup> m_groups;
|
||||
|
||||
void setIdDatabases()
|
||||
{
|
||||
amuse::SongId::CurNameDB = &m_songDb;
|
||||
amuse::SFXId::CurNameDB = &m_sfxDb;
|
||||
}
|
||||
|
||||
public:
|
||||
explicit ProjectModel(const QString& path, QObject* parent = Q_NULLPTR);
|
||||
|
||||
bool importGroupData(const QString& groupName, amuse::IntrusiveAudioGroupData&& data,
|
||||
ImportMode mode, QWidget* parent);
|
||||
bool importGroupData(const QString& groupName, amuse::IntrusiveAudioGroupData&& data, ImportMode mode);
|
||||
bool saveToFile(QWidget* parent);
|
||||
|
||||
QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const;
|
||||
|
|
|
@ -119,8 +119,12 @@ struct SoundMacro
|
|||
AddIVars,
|
||||
IfEqual = 0x70,
|
||||
IfLess,
|
||||
Invalid = 0xff
|
||||
};
|
||||
|
||||
static std::string_view CmdOpToStr(CmdOp op);
|
||||
static CmdOp CmdStrToOp(std::string_view op);
|
||||
|
||||
/** Base command interface. All versions of MusyX encode little-endian parameters */
|
||||
struct ICmd : LittleDNAV
|
||||
{
|
||||
|
@ -148,7 +152,7 @@ struct SoundMacro
|
|||
AT_DECL_DNA_YAML
|
||||
AT_DECL_DNAV
|
||||
Value<atInt8> key;
|
||||
ObjectIdDNA<athena::Little> macro;
|
||||
SoundMacroIdDNA<athena::Little> macro;
|
||||
Value<atUint16> macroStep;
|
||||
bool Do(SoundMacroState& st, Voice& vox) const;
|
||||
CmdOp Isa() const { return CmdOp::SplitKey; }
|
||||
|
@ -158,7 +162,7 @@ struct SoundMacro
|
|||
AT_DECL_DNA_YAML
|
||||
AT_DECL_DNAV
|
||||
Value<atInt8> velocity;
|
||||
ObjectIdDNA<athena::Little> macro;
|
||||
SoundMacroIdDNA<athena::Little> macro;
|
||||
Value<atUint16> macroStep;
|
||||
bool Do(SoundMacroState& st, Voice& vox) const;
|
||||
CmdOp Isa() const { return CmdOp::SplitVel; }
|
||||
|
@ -193,7 +197,7 @@ struct SoundMacro
|
|||
AT_DECL_DNA_YAML
|
||||
AT_DECL_DNAV
|
||||
Seek<1, athena::SeekOrigin::Current> dummy;
|
||||
ObjectIdDNA<athena::Little> macro;
|
||||
SoundMacroIdDNA<athena::Little> macro;
|
||||
Value<atUint16> macroStep;
|
||||
bool Do(SoundMacroState& st, Voice& vox) const;
|
||||
CmdOp Isa() const { return CmdOp::Goto; }
|
||||
|
@ -216,7 +220,7 @@ struct SoundMacro
|
|||
AT_DECL_DNA_YAML
|
||||
AT_DECL_DNAV
|
||||
Value<atInt8> addNote;
|
||||
ObjectIdDNA<athena::Little> macro;
|
||||
SoundMacroIdDNA<athena::Little> macro;
|
||||
Value<atUint16> macroStep;
|
||||
Value<atUint8> priority;
|
||||
Value<atUint8> maxVoices;
|
||||
|
@ -237,7 +241,7 @@ struct SoundMacro
|
|||
AT_DECL_DNA_YAML
|
||||
AT_DECL_DNAV
|
||||
Value<atInt8> modValue;
|
||||
ObjectIdDNA<athena::Little> macro;
|
||||
SoundMacroIdDNA<athena::Little> macro;
|
||||
Value<atUint16> macroStep;
|
||||
Value<atUint8> priority;
|
||||
Value<atUint8> maxVoices;
|
||||
|
@ -258,7 +262,7 @@ struct SoundMacro
|
|||
{
|
||||
AT_DECL_DNA_YAML
|
||||
AT_DECL_DNAV
|
||||
ObjectIdDNA<athena::Little> table;
|
||||
TableIdDNA<athena::Little> table;
|
||||
Value<bool> dlsMode;
|
||||
bool Do(SoundMacroState& st, Voice& vox) const;
|
||||
CmdOp Isa() const { return CmdOp::SetAdsr; }
|
||||
|
@ -269,7 +273,7 @@ struct SoundMacro
|
|||
AT_DECL_DNAV
|
||||
Value<atInt8> scale;
|
||||
Value<atInt8> add;
|
||||
ObjectIdDNA<athena::Little> table;
|
||||
TableIdDNA<athena::Little> table;
|
||||
Value<bool> originalVol;
|
||||
bool Do(SoundMacroState& st, Voice& vox) const;
|
||||
CmdOp Isa() const { return CmdOp::ScaleVolume; }
|
||||
|
@ -290,7 +294,7 @@ struct SoundMacro
|
|||
AT_DECL_DNAV
|
||||
Value<atInt8> scale;
|
||||
Value<atInt8> add;
|
||||
ObjectIdDNA<athena::Little> table;
|
||||
TableIdDNA<athena::Little> table;
|
||||
Value<bool> msSwitch;
|
||||
Value<atUint16> fadeTime;
|
||||
bool Do(SoundMacroState& st, Voice& vox) const;
|
||||
|
@ -325,7 +329,7 @@ struct SoundMacro
|
|||
AT_DECL_DNA_YAML
|
||||
AT_DECL_DNAV
|
||||
Value<atUint8> rnd;
|
||||
ObjectIdDNA<athena::Little> macro;
|
||||
SoundMacroIdDNA<athena::Little> macro;
|
||||
Value<atUint16> macroStep;
|
||||
bool Do(SoundMacroState& st, Voice& vox) const;
|
||||
CmdOp Isa() const { return CmdOp::SplitRnd; }
|
||||
|
@ -336,7 +340,7 @@ struct SoundMacro
|
|||
AT_DECL_DNAV
|
||||
Value<atInt8> scale;
|
||||
Value<atInt8> add;
|
||||
ObjectIdDNA<athena::Little> table;
|
||||
TableIdDNA<athena::Little> table;
|
||||
Value<bool> msSwitch;
|
||||
Value<atUint16> ticksPerMs;
|
||||
bool Do(SoundMacroState& st, Voice& vox) const;
|
||||
|
@ -474,7 +478,7 @@ struct SoundMacro
|
|||
{
|
||||
AT_DECL_DNA_YAML
|
||||
AT_DECL_DNAV
|
||||
ObjectIdDNA<athena::Little> table;
|
||||
TableIdDNA<athena::Little> table;
|
||||
Seek<1, athena::SeekOrigin::Current> seek;
|
||||
Value<atInt8> keys;
|
||||
Value<atInt8> cents;
|
||||
|
@ -521,7 +525,7 @@ struct SoundMacro
|
|||
AT_DECL_DNA_YAML
|
||||
AT_DECL_DNAV
|
||||
Seek<1, athena::SeekOrigin::Current> seek;
|
||||
ObjectIdDNA<athena::Little> macro;
|
||||
SoundMacroIdDNA<athena::Little> macro;
|
||||
Value<atUint16> macroStep;
|
||||
bool Do(SoundMacroState& st, Voice& vox) const;
|
||||
CmdOp Isa() const { return CmdOp::GoSub; }
|
||||
|
@ -531,7 +535,7 @@ struct SoundMacro
|
|||
AT_DECL_DNA_YAML
|
||||
AT_DECL_DNAV
|
||||
Value<atUint8> event;
|
||||
ObjectIdDNA<athena::Little> macro;
|
||||
SoundMacroIdDNA<athena::Little> macro;
|
||||
Value<atUint16> macroStep;
|
||||
bool Do(SoundMacroState& st, Voice& vox) const;
|
||||
CmdOp Isa() const { return CmdOp::TrapEvent; }
|
||||
|
@ -549,7 +553,7 @@ struct SoundMacro
|
|||
AT_DECL_DNA_YAML
|
||||
AT_DECL_DNAV
|
||||
Value<bool> isVar;
|
||||
ObjectIdDNA<athena::Little> macro;
|
||||
SoundMacroIdDNA<athena::Little> macro;
|
||||
Value<atUint8> vid;
|
||||
Value<atUint8> variable;
|
||||
bool Do(SoundMacroState& st, Voice& vox) const;
|
||||
|
@ -1031,19 +1035,51 @@ struct Curve : ITable
|
|||
|
||||
/** Maps individual MIDI keys to sound-entity as indexed in table
|
||||
* (macro-voice, keymap, layer) */
|
||||
struct Keymap : LittleDNA
|
||||
template <athena::Endian DNAEn>
|
||||
struct AT_SPECIALIZE_PARMS(athena::Endian::Big, athena::Endian::Little)
|
||||
KeymapDNA : BigDNA
|
||||
{
|
||||
AT_DECL_DNA_YAML
|
||||
AT_DECL_DNA
|
||||
SoundMacroIdDNA<DNAEn> macro;
|
||||
Value<atInt8> transpose;
|
||||
Value<atInt8> pan; /* -128 for surround-channel only */
|
||||
Value<atInt8> prioOffset;
|
||||
Seek<3, athena::Current> pad;
|
||||
};
|
||||
|
||||
/** Maps ranges of MIDI keys to sound-entity (macro-voice, keymap, layer) */
|
||||
struct LayerMapping : LittleDNA
|
||||
struct Keymap : BigDNA
|
||||
{
|
||||
AT_DECL_DNA_YAML
|
||||
SoundMacroIdDNA<athena::Big> macro;
|
||||
Value<atInt8> transpose;
|
||||
Value<atInt8> pan; /* -128 for surround-channel only */
|
||||
Value<atInt8> prioOffset;
|
||||
|
||||
Keymap() = default;
|
||||
|
||||
template <athena::Endian DNAE>
|
||||
Keymap(const KeymapDNA<DNAE>& in)
|
||||
: macro(in.macro.id), transpose(in.transpose), pan(in.pan),
|
||||
prioOffset(in.prioOffset) {}
|
||||
|
||||
template <athena::Endian DNAEn>
|
||||
KeymapDNA<DNAEn> toDNA() const
|
||||
{
|
||||
KeymapDNA<DNAEn> ret;
|
||||
ret.macro.id = macro;
|
||||
ret.transpose = transpose;
|
||||
ret.pan = pan;
|
||||
ret.prioOffset = prioOffset;
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
/** Maps ranges of MIDI keys to sound-entity (macro-voice, keymap, layer) */
|
||||
template <athena::Endian DNAEn>
|
||||
struct AT_SPECIALIZE_PARMS(athena::Endian::Big, athena::Endian::Little)
|
||||
LayerMappingDNA : BigDNA
|
||||
{
|
||||
AT_DECL_DNA
|
||||
SoundMacroIdDNA<DNAEn> macro;
|
||||
Value<atInt8> keyLo;
|
||||
Value<atInt8> keyHi;
|
||||
Value<atInt8> transpose;
|
||||
|
@ -1051,6 +1087,42 @@ struct LayerMapping : LittleDNA
|
|||
Value<atInt8> prioOffset;
|
||||
Value<atInt8> span;
|
||||
Value<atInt8> pan;
|
||||
Seek<3, athena::Current> pad;
|
||||
};
|
||||
struct LayerMapping : BigDNA
|
||||
{
|
||||
AT_DECL_DNA_YAML
|
||||
SoundMacroIdDNA<athena::Big> macro;
|
||||
Value<atInt8> keyLo;
|
||||
Value<atInt8> keyHi;
|
||||
Value<atInt8> transpose;
|
||||
Value<atInt8> volume;
|
||||
Value<atInt8> prioOffset;
|
||||
Value<atInt8> span;
|
||||
Value<atInt8> pan;
|
||||
|
||||
LayerMapping() = default;
|
||||
|
||||
template <athena::Endian DNAE>
|
||||
LayerMapping(const LayerMappingDNA<DNAE>& in)
|
||||
: macro(in.macro.id), keyLo(in.keyLo), keyHi(in.keyHi),
|
||||
transpose(in.transpose), volume(in.volume), prioOffset(in.prioOffset),
|
||||
span(in.span), pan(in.pan) {}
|
||||
|
||||
template <athena::Endian DNAEn>
|
||||
LayerMappingDNA<DNAEn> toDNA() const
|
||||
{
|
||||
LayerMappingDNA<DNAEn> ret;
|
||||
ret.macro.id = macro;
|
||||
ret.keyLo = keyLo;
|
||||
ret.keyHi = keyHi;
|
||||
ret.transpose = transpose;
|
||||
ret.volume = volume;
|
||||
ret.prioOffset = prioOffset;
|
||||
ret.span = span;
|
||||
ret.pan = pan;
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
/** Database of functional objects within Audio Group */
|
||||
|
@ -1073,6 +1145,8 @@ public:
|
|||
const ADSR* tableAsAdsr(ObjectId id) const;
|
||||
const ADSRDLS* tableAsAdsrDLS(ObjectId id) const { return reinterpret_cast<const ADSRDLS*>(tableAsAdsr(id)); }
|
||||
const Curve* tableAsCurves(ObjectId id) const { return reinterpret_cast<const Curve*>(tableAsAdsr(id)); }
|
||||
|
||||
bool toYAML(athena::io::IStreamWriter& w) const;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@ struct SongGroupIndex : AudioGroupIndex
|
|||
PageEntryDNA : BigDNA
|
||||
{
|
||||
AT_DECL_DNA_YAML
|
||||
ObjectIdDNA<DNAEn> objId;
|
||||
PageObjectIdDNA<DNAEn> objId;
|
||||
Value<atUint8> priority;
|
||||
Value<atUint8> maxVoices;
|
||||
Value<atUint8> programNo;
|
||||
|
@ -59,19 +59,20 @@ struct SongGroupIndex : AudioGroupIndex
|
|||
struct AT_SPECIALIZE_PARMS(athena::Endian::Big, athena::Endian::Little)
|
||||
MusyX1PageEntryDNA : BigDNA
|
||||
{
|
||||
AT_DECL_DNA_YAML
|
||||
ObjectIdDNA<DNAEn> objId;
|
||||
AT_DECL_DNA
|
||||
PageObjectIdDNA<DNAEn> objId;
|
||||
Value<atUint8> priority;
|
||||
Value<atUint8> maxVoices;
|
||||
Value<atUint8> unk;
|
||||
Value<atUint8> programNo;
|
||||
Seek<2, athena::Current> pad;
|
||||
};
|
||||
struct PageEntry
|
||||
struct PageEntry : BigDNA
|
||||
{
|
||||
ObjectId objId;
|
||||
atUint8 priority;
|
||||
atUint8 maxVoices;
|
||||
AT_DECL_DNA_YAML
|
||||
PageObjectIdDNA<athena::Big> objId;
|
||||
Value<atUint8> priority;
|
||||
Value<atUint8> maxVoices;
|
||||
|
||||
PageEntry() = default;
|
||||
|
||||
|
@ -87,7 +88,7 @@ struct SongGroupIndex : AudioGroupIndex
|
|||
PageEntryDNA<DNAEn> toDNA(uint8_t programNo) const
|
||||
{
|
||||
PageEntryDNA<DNAEn> ret;
|
||||
ret.objId.id = objId;
|
||||
ret.objId = objId;
|
||||
ret.priority = priority;
|
||||
ret.maxVoices = maxVoices;
|
||||
ret.programNo = programNo;
|
||||
|
@ -132,9 +133,9 @@ struct SFXGroupIndex : AudioGroupIndex
|
|||
struct AT_SPECIALIZE_PARMS(athena::Endian::Big, athena::Endian::Little)
|
||||
SFXEntryDNA : BigDNA
|
||||
{
|
||||
AT_DECL_DNA_YAML
|
||||
SFXIdDNA<DNAEn> defineId;
|
||||
ObjectIdDNA<DNAEn> objId;
|
||||
AT_DECL_DNA
|
||||
SFXIdDNA<DNAEn> sfxId;
|
||||
SoundMacroIdDNA<DNAEn> macro;
|
||||
Value<atUint8> priority;
|
||||
Value<atUint8> maxVoices;
|
||||
Value<atUint8> defVel;
|
||||
|
@ -142,28 +143,29 @@ struct SFXGroupIndex : AudioGroupIndex
|
|||
Value<atUint8> defKey;
|
||||
Seek<1, athena::Current> pad;
|
||||
};
|
||||
struct SFXEntry
|
||||
struct SFXEntry : BigDNA
|
||||
{
|
||||
ObjectId objId;
|
||||
atUint8 priority;
|
||||
atUint8 maxVoices;
|
||||
atUint8 defVel;
|
||||
atUint8 panning;
|
||||
atUint8 defKey;
|
||||
AT_DECL_DNA_YAML
|
||||
SoundMacroIdDNA<athena::Big> macro;
|
||||
Value<atUint8> priority;
|
||||
Value<atUint8> maxVoices;
|
||||
Value<atUint8> defVel;
|
||||
Value<atUint8> panning;
|
||||
Value<atUint8> defKey;
|
||||
|
||||
SFXEntry() = default;
|
||||
|
||||
template <athena::Endian DNAE>
|
||||
SFXEntry(const SFXEntryDNA<DNAE>& in)
|
||||
: objId(in.objId.id), priority(in.priority), maxVoices(in.maxVoices),
|
||||
: macro(in.macro.id), priority(in.priority), maxVoices(in.maxVoices),
|
||||
defVel(in.defVel), panning(in.panning), defKey(in.defKey) {}
|
||||
|
||||
template <athena::Endian DNAEn>
|
||||
SFXEntryDNA<DNAEn> toDNA(SFXId defineId) const
|
||||
SFXEntryDNA<DNAEn> toDNA(SFXId id) const
|
||||
{
|
||||
SFXEntryDNA<DNAEn> ret;
|
||||
ret.defineId.id = defineId;
|
||||
ret.objId.id = objId;
|
||||
ret.sfxId.id = id;
|
||||
ret.macro = macro;
|
||||
ret.priority = priority;
|
||||
ret.maxVoices = maxVoices;
|
||||
ret.defVel = defVel;
|
||||
|
@ -185,14 +187,21 @@ class AudioGroupProject
|
|||
AudioGroupProject(athena::io::IStreamReader& r, GCNDataTag);
|
||||
template <athena::Endian DNAE>
|
||||
static AudioGroupProject _AudioGroupProject(athena::io::IStreamReader& r, bool absOffs);
|
||||
|
||||
static void BootstrapObjectIDs(athena::io::IStreamReader& r, GCNDataTag);
|
||||
template <athena::Endian DNAE>
|
||||
static void BootstrapObjectIDs(athena::io::IStreamReader& r, bool absOffs);
|
||||
public:
|
||||
static AudioGroupProject CreateAudioGroupProject(const AudioGroupData& data);
|
||||
static void BootstrapObjectIDs(const AudioGroupData& data);
|
||||
|
||||
const SongGroupIndex* getSongGroupIndex(int groupId) const;
|
||||
const SFXGroupIndex* getSFXGroupIndex(int groupId) const;
|
||||
|
||||
const std::unordered_map<int, SongGroupIndex>& songGroups() const { return m_songGroups; }
|
||||
const std::unordered_map<int, SFXGroupIndex>& sfxGroups() const { return m_sfxGroups; }
|
||||
|
||||
bool toYAML(athena::io::IStreamWriter& w) const;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -15,19 +15,106 @@ class AudioGroupSampleDirectory
|
|||
friend class AudioGroup;
|
||||
|
||||
public:
|
||||
enum class SampleFormat : atUint8
|
||||
{
|
||||
DSP,
|
||||
DSP2,
|
||||
PCM,
|
||||
N64
|
||||
};
|
||||
|
||||
template <athena::Endian DNAEn>
|
||||
struct AT_SPECIALIZE_PARMS(athena::Endian::Big, athena::Endian::Little)
|
||||
EntryDNA : BigDNA
|
||||
{
|
||||
AT_DECL_DNA
|
||||
SFXIdDNA<DNAEn> m_sfxId;
|
||||
Value<atUint32, DNAEn> m_sampleOff;
|
||||
Value<atUint32, DNAEn> m_unk;
|
||||
Value<atUint8, DNAEn> m_pitch;
|
||||
Seek<1, athena::Current> pad;
|
||||
Value<atUint16, DNAEn> m_sampleRate;
|
||||
Value<atUint32, DNAEn> m_numSamples; // Top 8 bits is SampleFormat
|
||||
Value<atUint32, DNAEn> m_loopStartSample;
|
||||
Value<atUint32, DNAEn> m_loopLengthSamples;
|
||||
Value<atUint32, DNAEn> m_adpcmParmOffset;
|
||||
};
|
||||
template <athena::Endian DNAEn>
|
||||
struct AT_SPECIALIZE_PARMS(athena::Endian::Big, athena::Endian::Little)
|
||||
MusyX1SdirEntry : BigDNA
|
||||
{
|
||||
AT_DECL_DNA
|
||||
SFXIdDNA<DNAEn> m_sfxId;
|
||||
Value<atUint32, DNAEn> m_sampleOff;
|
||||
Value<atUint32, DNAEn> m_pitchSampleRate;
|
||||
Value<atUint32, DNAEn> m_numSamples;
|
||||
Value<atUint32, DNAEn> m_loopStartSample;
|
||||
Value<atUint32, DNAEn> m_loopLengthSamples;
|
||||
};
|
||||
template <athena::Endian DNAEn>
|
||||
struct AT_SPECIALIZE_PARMS(athena::Endian::Big, athena::Endian::Little)
|
||||
MusyX1AbsSdirEntry : BigDNA
|
||||
{
|
||||
AT_DECL_DNA
|
||||
SFXIdDNA<DNAEn> m_sfxId;
|
||||
Value<uint32_t, DNAEn> m_sampleOff;
|
||||
Value<uint32_t, DNAEn> m_unk;
|
||||
Value<uint32_t, DNAEn> m_pitchSampleRate;
|
||||
Value<uint32_t, DNAEn> m_numSamples;
|
||||
Value<uint32_t, DNAEn> m_loopStartSample;
|
||||
Value<uint32_t, DNAEn> m_loopLengthSamples;
|
||||
};
|
||||
struct Entry
|
||||
{
|
||||
uint16_t m_sfxId;
|
||||
uint32_t m_sampleOff;
|
||||
uint32_t m_unk;
|
||||
uint8_t m_pitch;
|
||||
uint16_t m_sampleRate;
|
||||
uint32_t m_numSamples;
|
||||
uint32_t m_loopStartSample;
|
||||
uint32_t m_loopLengthSamples;
|
||||
uint32_t m_adpcmParmOffset;
|
||||
void swapBig();
|
||||
atUint32 m_sampleOff;
|
||||
atUint32 m_unk;
|
||||
atUint8 m_pitch;
|
||||
atUint16 m_sampleRate;
|
||||
atUint32 m_numSamples; // Top 8 bits is SampleFormat
|
||||
atUint32 m_loopStartSample;
|
||||
atUint32 m_loopLengthSamples;
|
||||
atUint32 m_adpcmParmOffset;
|
||||
|
||||
Entry() = default;
|
||||
|
||||
template <athena::Endian DNAE>
|
||||
Entry(const EntryDNA<DNAE>& in)
|
||||
: m_sampleOff(in.m_sampleOff), m_unk(in.m_unk), m_pitch(in.m_pitch),
|
||||
m_sampleRate(in.m_sampleRate), m_numSamples(in.m_numSamples),
|
||||
m_loopStartSample(in.m_loopStartSample), m_loopLengthSamples(in.m_loopLengthSamples),
|
||||
m_adpcmParmOffset(in.m_adpcmParmOffset) {}
|
||||
|
||||
template <athena::Endian DNAE>
|
||||
Entry(const MusyX1SdirEntry<DNAE>& in)
|
||||
: m_sampleOff(in.m_sampleOff), m_unk(0), m_pitch(in.m_pitchSampleRate >> 24),
|
||||
m_sampleRate(in.m_pitchSampleRate & 0xffff), m_numSamples(in.m_numSamples),
|
||||
m_loopStartSample(in.m_loopStartSample), m_loopLengthSamples(in.m_loopLengthSamples),
|
||||
m_adpcmParmOffset(0) {}
|
||||
|
||||
template <athena::Endian DNAE>
|
||||
Entry(const MusyX1AbsSdirEntry<DNAE>& in)
|
||||
: m_sampleOff(in.m_sampleOff), m_unk(in.m_unk), m_pitch(in.m_pitchSampleRate >> 24),
|
||||
m_sampleRate(in.m_pitchSampleRate & 0xffff), m_numSamples(in.m_numSamples),
|
||||
m_loopStartSample(in.m_loopStartSample), m_loopLengthSamples(in.m_loopLengthSamples),
|
||||
m_adpcmParmOffset(0) {}
|
||||
|
||||
template <athena::Endian DNAEn>
|
||||
EntryDNA<DNAEn> toDNA(SFXId id) const
|
||||
{
|
||||
EntryDNA<DNAEn> ret;
|
||||
ret.m_sfxId.id = id;
|
||||
ret.m_sampleOff = m_sampleOff;
|
||||
ret.m_unk = m_unk;
|
||||
ret.m_pitch = m_pitch;
|
||||
ret.m_sampleRate = m_sampleRate;
|
||||
ret.m_numSamples = m_numSamples;
|
||||
ret.m_loopStartSample = m_loopStartSample;
|
||||
ret.m_loopLengthSamples = m_loopLengthSamples;
|
||||
ret.m_adpcmParmOffset = m_adpcmParmOffset;
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
union ADPCMParms {
|
||||
struct DSPParms
|
||||
{
|
||||
|
@ -47,15 +134,15 @@ public:
|
|||
};
|
||||
|
||||
private:
|
||||
std::unordered_map<uint16_t, std::pair<Entry, ADPCMParms>> m_entries;
|
||||
std::unordered_map<SFXId, std::pair<Entry, ADPCMParms>> m_entries;
|
||||
|
||||
public:
|
||||
AudioGroupSampleDirectory(const unsigned char* data, GCNDataTag);
|
||||
AudioGroupSampleDirectory(const unsigned char* data, const unsigned char* sampData, bool absOffs, N64DataTag);
|
||||
AudioGroupSampleDirectory(const unsigned char* data, bool absOffs, PCDataTag);
|
||||
AudioGroupSampleDirectory(athena::io::IStreamReader& r, GCNDataTag);
|
||||
AudioGroupSampleDirectory(athena::io::IStreamReader& r, const unsigned char* sampData, bool absOffs, N64DataTag);
|
||||
AudioGroupSampleDirectory(athena::io::IStreamReader& r, bool absOffs, PCDataTag);
|
||||
static AudioGroupSampleDirectory CreateAudioGroupSampleDirectory(const AudioGroupData& data);
|
||||
|
||||
const std::unordered_map<uint16_t, std::pair<Entry, ADPCMParms>>& sampleEntries() const { return m_entries; }
|
||||
const std::unordered_map<SFXId, std::pair<Entry, ADPCMParms>>& sampleEntries() const { return m_entries; }
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@ using BigDNAV = athena::io::DNAVYaml<athena::Big>;
|
|||
using LittleDNAV = athena::io::DNAVYaml<athena::Little>;
|
||||
|
||||
/** Common ID structure statically tagging
|
||||
* SoundMacros, Tables, Keymaps, Layers */
|
||||
* SoundMacros, Tables, Keymaps, Layers, Samples, SFX, Songs */
|
||||
struct ObjectId
|
||||
{
|
||||
uint16_t id = 0xffff;
|
||||
|
@ -47,7 +47,6 @@ struct ObjectId
|
|||
ObjectId& operator=(uint16_t idIn) { id = idIn; return *this; }
|
||||
static thread_local NameDB* CurNameDB;
|
||||
};
|
||||
|
||||
template <athena::Endian DNAEn>
|
||||
struct AT_SPECIALIZE_PARMS(athena::Endian::Big, athena::Endian::Little)
|
||||
ObjectIdDNA : BigDNA
|
||||
|
@ -56,57 +55,52 @@ ObjectIdDNA : BigDNA
|
|||
void _read(athena::io::YAMLDocReader& r);
|
||||
void _write(athena::io::YAMLDocWriter& w);
|
||||
ObjectId id;
|
||||
ObjectIdDNA() = default;
|
||||
ObjectIdDNA(ObjectId idIn) : id(idIn) {}
|
||||
operator ObjectId() const { return id; }
|
||||
};
|
||||
|
||||
struct SampleId : ObjectId
|
||||
{
|
||||
using ObjectId::ObjectId;
|
||||
SampleId(const ObjectId& id) : ObjectId(id) {}
|
||||
static thread_local NameDB* CurNameDB;
|
||||
#define DECL_ID_TYPE(type) \
|
||||
struct type : ObjectId \
|
||||
{ \
|
||||
using ObjectId::ObjectId; \
|
||||
type(const ObjectId& id) : ObjectId(id) {} \
|
||||
static thread_local NameDB* CurNameDB; \
|
||||
}; \
|
||||
template <athena::Endian DNAEn> \
|
||||
struct AT_SPECIALIZE_PARMS(athena::Endian::Big, athena::Endian::Little) \
|
||||
type##DNA : BigDNA \
|
||||
{ \
|
||||
AT_DECL_EXPLICIT_DNA_YAML \
|
||||
void _read(athena::io::YAMLDocReader& r); \
|
||||
void _write(athena::io::YAMLDocWriter& w); \
|
||||
type id; \
|
||||
type##DNA() = default; \
|
||||
type##DNA(type idIn) : id(idIn) {} \
|
||||
operator type() const { return id; } \
|
||||
};
|
||||
DECL_ID_TYPE(SoundMacroId)
|
||||
DECL_ID_TYPE(SampleId)
|
||||
DECL_ID_TYPE(TableId)
|
||||
DECL_ID_TYPE(KeymapId)
|
||||
DECL_ID_TYPE(LayersId)
|
||||
DECL_ID_TYPE(SongId)
|
||||
DECL_ID_TYPE(SFXId)
|
||||
|
||||
/* MusyX has object polymorphism between Keymaps and Layers when
|
||||
* referenced by a song group's page object. When the upper bit is set,
|
||||
* this indicates a layer type. */
|
||||
template <athena::Endian DNAEn>
|
||||
struct AT_SPECIALIZE_PARMS(athena::Endian::Big, athena::Endian::Little)
|
||||
SampleIdDNA : BigDNA
|
||||
PageObjectIdDNA : BigDNA
|
||||
{
|
||||
AT_DECL_EXPLICIT_DNA_YAML
|
||||
void _read(athena::io::YAMLDocReader& r);
|
||||
void _write(athena::io::YAMLDocWriter& w);
|
||||
SampleId id;
|
||||
};
|
||||
|
||||
struct SongId : ObjectId
|
||||
{
|
||||
using ObjectId::ObjectId;
|
||||
SongId(const ObjectId& id) : ObjectId(id) {}
|
||||
static thread_local NameDB* CurNameDB;
|
||||
};
|
||||
|
||||
template <athena::Endian DNAEn>
|
||||
struct AT_SPECIALIZE_PARMS(athena::Endian::Big, athena::Endian::Little)
|
||||
SongIdDNA : BigDNA
|
||||
{
|
||||
AT_DECL_EXPLICIT_DNA_YAML
|
||||
void _read(athena::io::YAMLDocReader& r);
|
||||
void _write(athena::io::YAMLDocWriter& w);
|
||||
SongId id;
|
||||
};
|
||||
|
||||
struct SFXId : ObjectId
|
||||
{
|
||||
using ObjectId::ObjectId;
|
||||
SFXId(const ObjectId& id) : ObjectId(id) {}
|
||||
static thread_local NameDB* CurNameDB;
|
||||
};
|
||||
|
||||
template <athena::Endian DNAEn>
|
||||
struct AT_SPECIALIZE_PARMS(athena::Endian::Big, athena::Endian::Little)
|
||||
SFXIdDNA : BigDNA
|
||||
{
|
||||
AT_DECL_EXPLICIT_DNA_YAML
|
||||
void _read(athena::io::YAMLDocReader& r);
|
||||
void _write(athena::io::YAMLDocWriter& w);
|
||||
SFXId id;
|
||||
ObjectId id;
|
||||
PageObjectIdDNA() = default;
|
||||
PageObjectIdDNA(ObjectId idIn) : id(idIn) {}
|
||||
operator ObjectId() const { return id; }
|
||||
};
|
||||
|
||||
struct LittleUInt24 : LittleDNA
|
||||
|
@ -422,30 +416,34 @@ struct N64DataTag
|
|||
struct PCDataTag
|
||||
{
|
||||
};
|
||||
|
||||
template <class T>
|
||||
static std::vector<std::pair<typename T::key_type,
|
||||
std::reference_wrapper<const typename T::mapped_type>>> SortUnorderedMap(const T& um)
|
||||
{
|
||||
std::vector<std::pair<typename T::key_type,
|
||||
std::reference_wrapper<const typename T::mapped_type>>> ret(um.cbegin(), um.cend());
|
||||
std::sort(ret.begin(), ret.end(), [](const auto& a, const auto& b) { return a.first < b.first; });
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
namespace std
|
||||
{
|
||||
template<>
|
||||
struct hash<amuse::ObjectId>
|
||||
{
|
||||
size_t operator()(const amuse::ObjectId& val) const noexcept { return val.id; }
|
||||
};
|
||||
template<>
|
||||
struct hash<amuse::SampleId>
|
||||
{
|
||||
size_t operator()(const amuse::SampleId& val) const noexcept { return val.id; }
|
||||
};
|
||||
template<>
|
||||
struct hash<amuse::SongId>
|
||||
{
|
||||
size_t operator()(const amuse::SongId& val) const noexcept { return val.id; }
|
||||
};
|
||||
template<>
|
||||
struct hash<amuse::SFXId>
|
||||
{
|
||||
size_t operator()(const amuse::SFXId& val) const noexcept { return val.id; }
|
||||
#define DECL_ID_HASH(type) \
|
||||
template<> \
|
||||
struct hash<amuse::type> \
|
||||
{ \
|
||||
size_t operator()(const amuse::type& val) const noexcept { return val.id; } \
|
||||
};
|
||||
DECL_ID_HASH(ObjectId)
|
||||
DECL_ID_HASH(SoundMacroId)
|
||||
DECL_ID_HASH(SampleId)
|
||||
DECL_ID_HASH(TableId)
|
||||
DECL_ID_HASH(KeymapId)
|
||||
DECL_ID_HASH(LayersId)
|
||||
DECL_ID_HASH(SongId)
|
||||
DECL_ID_HASH(SFXId)
|
||||
}
|
||||
|
||||
namespace amuse
|
||||
|
@ -454,17 +452,20 @@ struct NameDB
|
|||
{
|
||||
enum class Type
|
||||
{
|
||||
SoundMacro = 0,
|
||||
Table = 1,
|
||||
Keymap = 4,
|
||||
Layer = 8
|
||||
SoundMacro,
|
||||
Table,
|
||||
Keymap,
|
||||
Layer,
|
||||
Song,
|
||||
SFX,
|
||||
Sample
|
||||
};
|
||||
|
||||
std::unordered_map<std::string, ObjectId> m_stringToId;
|
||||
std::unordered_map<ObjectId, std::string> m_idToString;
|
||||
|
||||
ObjectId generateId(Type tp);
|
||||
static std::string generateName(ObjectId id);
|
||||
static std::string generateName(ObjectId id, Type tp);
|
||||
std::string_view registerPair(std::string_view str, ObjectId id);
|
||||
std::string_view resolveNameFromId(ObjectId id) const;
|
||||
ObjectId resolveIdFromName(std::string_view str) const;
|
||||
|
|
|
@ -171,11 +171,11 @@ class Voice : public Entity
|
|||
std::list<std::shared_ptr<Voice>>::iterator _allocateVoice(double sampleRate, bool dynamicPitch);
|
||||
std::list<std::shared_ptr<Voice>>::iterator _destroyVoice(std::list<std::shared_ptr<Voice>>::iterator it);
|
||||
|
||||
bool _loadSoundMacro(ObjectId id, const SoundMacro* macroData, int macroStep, double ticksPerSec,
|
||||
bool _loadSoundMacro(SoundMacroId id, const SoundMacro* macroData, int macroStep, double ticksPerSec,
|
||||
uint8_t midiKey, uint8_t midiVel, uint8_t midiMod, bool pushPc = false);
|
||||
bool _loadKeymap(ObjectId id, const Keymap* keymap, int macroStep, double ticksPerSec, uint8_t midiKey,
|
||||
bool _loadKeymap(const Keymap* keymap, double ticksPerSec, uint8_t midiKey,
|
||||
uint8_t midiVel, uint8_t midiMod, bool pushPc = false);
|
||||
bool _loadLayer(ObjectId id, const std::vector<LayerMapping>& layer, int macroStep, double ticksPerSec,
|
||||
bool _loadLayer(const std::vector<LayerMapping>& layer, double ticksPerSec,
|
||||
uint8_t midiKey, uint8_t midiVel, uint8_t midiMod, bool pushPc = false);
|
||||
std::shared_ptr<Voice> _startChildMacro(ObjectId macroId, int macroStep, double ticksPerSec, uint8_t midiKey,
|
||||
uint8_t midiVel, uint8_t midiMod, bool pushPc = false);
|
||||
|
@ -222,10 +222,13 @@ public:
|
|||
/** Allocate parallel macro and tie to voice for possible emitter influence */
|
||||
std::shared_ptr<Voice> startChildMacro(int8_t addNote, ObjectId macroId, int macroStep);
|
||||
|
||||
/** Load specified Sound Object from within group into voice */
|
||||
bool loadSoundObject(ObjectId objectId, int macroStep, double ticksPerSec, uint8_t midiKey, uint8_t midiVel,
|
||||
/** Load specified SoundMacro Object from within group into voice */
|
||||
bool loadMacroObject(SoundMacroId macroId, int macroStep, double ticksPerSec, uint8_t midiKey, uint8_t midiVel,
|
||||
uint8_t midiMod, bool pushPc = false);
|
||||
|
||||
/** Load specified song page object (Keymap/Layer) from within group into voice */
|
||||
bool loadPageObject(ObjectId objectId, double ticksPerSec, uint8_t midiKey, uint8_t midiVel, uint8_t midiMod);
|
||||
|
||||
/** Signals voice to begin fade-out (or defer if sustained), eventually reaching silence */
|
||||
void keyOff();
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ namespace amuse
|
|||
AudioGroup::AudioGroup(const AudioGroupData& data, GCNDataTag)
|
||||
: m_proj(AudioGroupProject::CreateAudioGroupProject(data))
|
||||
, m_pool(AudioGroupPool::CreateAudioGroupPool(data))
|
||||
, m_sdir(data.getSdir(), GCNDataTag{})
|
||||
, m_sdir(AudioGroupSampleDirectory::CreateAudioGroupSampleDirectory(data))
|
||||
, m_samp(data.getSamp())
|
||||
, m_fmt(DataFormat::GCN)
|
||||
{
|
||||
|
@ -16,7 +16,7 @@ AudioGroup::AudioGroup(const AudioGroupData& data, GCNDataTag)
|
|||
AudioGroup::AudioGroup(const AudioGroupData& data, bool absOffs, N64DataTag)
|
||||
: m_proj(AudioGroupProject::CreateAudioGroupProject(data))
|
||||
, m_pool(AudioGroupPool::CreateAudioGroupPool(data))
|
||||
, m_sdir(data.getSdir(), data.getSamp(), absOffs, N64DataTag{})
|
||||
, m_sdir(AudioGroupSampleDirectory::CreateAudioGroupSampleDirectory(data))
|
||||
, m_samp(data.getSamp())
|
||||
, m_fmt(DataFormat::N64)
|
||||
{
|
||||
|
@ -25,7 +25,7 @@ AudioGroup::AudioGroup(const AudioGroupData& data, bool absOffs, N64DataTag)
|
|||
AudioGroup::AudioGroup(const AudioGroupData& data, bool absOffs, PCDataTag)
|
||||
: m_proj(AudioGroupProject::CreateAudioGroupProject(data))
|
||||
, m_pool(AudioGroupPool::CreateAudioGroupPool(data))
|
||||
, m_sdir(data.getSdir(), absOffs, PCDataTag{})
|
||||
, m_sdir(AudioGroupSampleDirectory::CreateAudioGroupSampleDirectory(data))
|
||||
, m_samp(data.getSamp())
|
||||
, m_fmt(DataFormat::PC)
|
||||
{
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
#include "athena/MemoryReader.hpp"
|
||||
#include "logvisor/logvisor.hpp"
|
||||
|
||||
using namespace std::literals;
|
||||
|
||||
namespace amuse
|
||||
{
|
||||
static logvisor::Module Log("amuse::AudioGroupPool");
|
||||
|
@ -75,8 +77,9 @@ AudioGroupPool AudioGroupPool::_AudioGroupPool(athena::io::IStreamReader& r)
|
|||
ObjectHeader<DNAE> objHead;
|
||||
atInt64 startPos = r.position();
|
||||
objHead.read(r);
|
||||
Keymap& km = ret.m_keymaps[objHead.objectId.id];
|
||||
km.read(r);
|
||||
KeymapDNA<DNAE> kmData;
|
||||
kmData.read(r);
|
||||
ret.m_keymaps[objHead.objectId.id] = kmData;
|
||||
r.seek(startPos + objHead.size, athena::Begin);
|
||||
}
|
||||
}
|
||||
|
@ -95,8 +98,9 @@ AudioGroupPool AudioGroupPool::_AudioGroupPool(athena::io::IStreamReader& r)
|
|||
lm.reserve(count);
|
||||
for (uint32_t i = 0; i < count; ++i)
|
||||
{
|
||||
lm.emplace_back();
|
||||
lm.back().read(r);
|
||||
LayerMappingDNA<DNAE> lmData;
|
||||
lmData.read(r);
|
||||
lm.push_back(lmData);
|
||||
}
|
||||
r.seek(startPos + objHead.size, athena::Begin);
|
||||
}
|
||||
|
@ -347,6 +351,408 @@ const ADSR* AudioGroupPool::tableAsAdsr(ObjectId id) const
|
|||
return static_cast<const ADSR*>(search->second.get());
|
||||
}
|
||||
|
||||
std::string_view SoundMacro::CmdOpToStr(CmdOp op)
|
||||
{
|
||||
switch (op)
|
||||
{
|
||||
case CmdOp::End:
|
||||
return "End"sv;
|
||||
case CmdOp::Stop:
|
||||
return "Stop"sv;
|
||||
case CmdOp::SplitKey:
|
||||
return "SplitKey"sv;
|
||||
case CmdOp::SplitVel:
|
||||
return "SplitVel"sv;
|
||||
case CmdOp::WaitTicks:
|
||||
return "WaitTicks"sv;
|
||||
case CmdOp::Loop:
|
||||
return "Loop"sv;
|
||||
case CmdOp::Goto:
|
||||
return "Goto"sv;
|
||||
case CmdOp::WaitMs:
|
||||
return "WaitMs"sv;
|
||||
case CmdOp::PlayMacro:
|
||||
return "PlayMacro"sv;
|
||||
case CmdOp::SendKeyOff:
|
||||
return "SendKeyOff"sv;
|
||||
case CmdOp::SplitMod:
|
||||
return "SplitMod"sv;
|
||||
case CmdOp::PianoPan:
|
||||
return "PianoPan"sv;
|
||||
case CmdOp::SetAdsr:
|
||||
return "SetAdsr"sv;
|
||||
case CmdOp::ScaleVolume:
|
||||
return "ScaleVolume"sv;
|
||||
case CmdOp::Panning:
|
||||
return "Panning"sv;
|
||||
case CmdOp::Envelope:
|
||||
return "Envelope"sv;
|
||||
case CmdOp::StartSample:
|
||||
return "StartSample"sv;
|
||||
case CmdOp::StopSample:
|
||||
return "StopSample"sv;
|
||||
case CmdOp::KeyOff:
|
||||
return "KeyOff"sv;
|
||||
case CmdOp::SplitRnd:
|
||||
return "SplitRnd"sv;
|
||||
case CmdOp::FadeIn:
|
||||
return "FadeIn"sv;
|
||||
case CmdOp::Spanning:
|
||||
return "Spanning"sv;
|
||||
case CmdOp::SetAdsrCtrl:
|
||||
return "SetAdsrCtrl"sv;
|
||||
case CmdOp::RndNote:
|
||||
return "RndNote"sv;
|
||||
case CmdOp::AddNote:
|
||||
return "AddNote"sv;
|
||||
case CmdOp::SetNote:
|
||||
return "SetNote"sv;
|
||||
case CmdOp::LastNote:
|
||||
return "LastNote"sv;
|
||||
case CmdOp::Portamento:
|
||||
return "Portamento"sv;
|
||||
case CmdOp::Vibrato:
|
||||
return "Vibrato"sv;
|
||||
case CmdOp::PitchSweep1:
|
||||
return "PitchSweep1"sv;
|
||||
case CmdOp::PitchSweep2:
|
||||
return "PitchSweep2"sv;
|
||||
case CmdOp::SetPitch:
|
||||
return "SetPitch"sv;
|
||||
case CmdOp::SetPitchAdsr:
|
||||
return "SetPitchAdsr"sv;
|
||||
case CmdOp::ScaleVolumeDLS:
|
||||
return "ScaleVolumeDLS"sv;
|
||||
case CmdOp::Mod2Vibrange:
|
||||
return "Mod2Vibrange"sv;
|
||||
case CmdOp::SetupTremolo:
|
||||
return "SetupTremolo"sv;
|
||||
case CmdOp::Return:
|
||||
return "Return"sv;
|
||||
case CmdOp::GoSub:
|
||||
return "GoSub"sv;
|
||||
case CmdOp::TrapEvent:
|
||||
return "TrapEvent"sv;
|
||||
case CmdOp::UntrapEvent:
|
||||
return "UntrapEvent"sv;
|
||||
case CmdOp::SendMessage:
|
||||
return "SendMessage"sv;
|
||||
case CmdOp::GetMessage:
|
||||
return "GetMessage"sv;
|
||||
case CmdOp::GetVid:
|
||||
return "GetVid"sv;
|
||||
case CmdOp::AddAgeCount:
|
||||
return "AddAgeCount"sv;
|
||||
case CmdOp::SetAgeCount:
|
||||
return "SetAgeCount"sv;
|
||||
case CmdOp::SendFlag:
|
||||
return "SendFlag"sv;
|
||||
case CmdOp::PitchWheelR:
|
||||
return "PitchWheelR"sv;
|
||||
case CmdOp::SetPriority:
|
||||
return "SetPriority"sv;
|
||||
case CmdOp::AddPriority:
|
||||
return "AddPriority"sv;
|
||||
case CmdOp::AgeCntSpeed:
|
||||
return "AgeCntSpeed"sv;
|
||||
case CmdOp::AgeCntVel:
|
||||
return "AgeCntVel"sv;
|
||||
case CmdOp::VolSelect:
|
||||
return "VolSelect"sv;
|
||||
case CmdOp::PanSelect:
|
||||
return "PanSelect"sv;
|
||||
case CmdOp::PitchWheelSelect:
|
||||
return "PitchWheelSelect"sv;
|
||||
case CmdOp::ModWheelSelect:
|
||||
return "ModWheelSelect"sv;
|
||||
case CmdOp::PedalSelect:
|
||||
return "PedalSelect"sv;
|
||||
case CmdOp::PortamentoSelect:
|
||||
return "PortamentoSelect"sv;
|
||||
case CmdOp::ReverbSelect:
|
||||
return "ReverbSelect"sv;
|
||||
case CmdOp::SpanSelect:
|
||||
return "SpanSelect"sv;
|
||||
case CmdOp::DopplerSelect:
|
||||
return "DopplerSelect"sv;
|
||||
case CmdOp::TremoloSelect:
|
||||
return "TremoloSelect"sv;
|
||||
case CmdOp::PreASelect:
|
||||
return "PreASelect"sv;
|
||||
case CmdOp::PreBSelect:
|
||||
return "PreBSelect"sv;
|
||||
case CmdOp::PostBSelect:
|
||||
return "PostBSelect"sv;
|
||||
case CmdOp::AuxAFXSelect:
|
||||
return "AuxAFXSelect"sv;
|
||||
case CmdOp::AuxBFXSelect:
|
||||
return "AuxBFXSelect"sv;
|
||||
case CmdOp::SetupLFO:
|
||||
return "SetupLFO"sv;
|
||||
case CmdOp::ModeSelect:
|
||||
return "ModeSelect"sv;
|
||||
case CmdOp::SetKeygroup:
|
||||
return "SetKeygroup"sv;
|
||||
case CmdOp::SRCmodeSelect:
|
||||
return "SRCmodeSelect"sv;
|
||||
case CmdOp::AddVars:
|
||||
return "AddVars"sv;
|
||||
case CmdOp::SubVars:
|
||||
return "SubVars"sv;
|
||||
case CmdOp::MulVars:
|
||||
return "MulVars"sv;
|
||||
case CmdOp::DivVars:
|
||||
return "DivVars"sv;
|
||||
case CmdOp::AddIVars:
|
||||
return "AddIVars"sv;
|
||||
case CmdOp::IfEqual:
|
||||
return "IfEqual"sv;
|
||||
case CmdOp::IfLess:
|
||||
return "IfLess"sv;
|
||||
default:
|
||||
return ""sv;
|
||||
}
|
||||
}
|
||||
|
||||
SoundMacro::CmdOp SoundMacro::CmdStrToOp(std::string_view op)
|
||||
{
|
||||
if (!CompareCaseInsensitive(op.data(), "End"))
|
||||
return CmdOp::End;
|
||||
else if (!CompareCaseInsensitive(op.data(), "Stop"))
|
||||
return CmdOp::Stop;
|
||||
else if (!CompareCaseInsensitive(op.data(), "SplitKey"))
|
||||
return CmdOp::SplitKey;
|
||||
else if (!CompareCaseInsensitive(op.data(), "SplitVel"))
|
||||
return CmdOp::SplitVel;
|
||||
else if (!CompareCaseInsensitive(op.data(), "WaitTicks"))
|
||||
return CmdOp::WaitTicks;
|
||||
else if (!CompareCaseInsensitive(op.data(), "Loop"))
|
||||
return CmdOp::Loop;
|
||||
else if (!CompareCaseInsensitive(op.data(), "Goto"))
|
||||
return CmdOp::Goto;
|
||||
else if (!CompareCaseInsensitive(op.data(), "WaitMs"))
|
||||
return CmdOp::WaitMs;
|
||||
else if (!CompareCaseInsensitive(op.data(), "PlayMacro"))
|
||||
return CmdOp::PlayMacro;
|
||||
else if (!CompareCaseInsensitive(op.data(), "SendKeyOff"))
|
||||
return CmdOp::SendKeyOff;
|
||||
else if (!CompareCaseInsensitive(op.data(), "SplitMod"))
|
||||
return CmdOp::SplitMod;
|
||||
else if (!CompareCaseInsensitive(op.data(), "PianoPan"))
|
||||
return CmdOp::PianoPan;
|
||||
else if (!CompareCaseInsensitive(op.data(), "SetAdsr"))
|
||||
return CmdOp::SetAdsr;
|
||||
else if (!CompareCaseInsensitive(op.data(), "ScaleVolume"))
|
||||
return CmdOp::ScaleVolume;
|
||||
else if (!CompareCaseInsensitive(op.data(), "Panning"))
|
||||
return CmdOp::Panning;
|
||||
else if (!CompareCaseInsensitive(op.data(), "Envelope"))
|
||||
return CmdOp::Envelope;
|
||||
else if (!CompareCaseInsensitive(op.data(), "StartSample"))
|
||||
return CmdOp::StartSample;
|
||||
else if (!CompareCaseInsensitive(op.data(), "StopSample"))
|
||||
return CmdOp::StopSample;
|
||||
else if (!CompareCaseInsensitive(op.data(), "KeyOff"))
|
||||
return CmdOp::KeyOff;
|
||||
else if (!CompareCaseInsensitive(op.data(), "SplitRnd"))
|
||||
return CmdOp::SplitRnd;
|
||||
else if (!CompareCaseInsensitive(op.data(), "FadeIn"))
|
||||
return CmdOp::FadeIn;
|
||||
else if (!CompareCaseInsensitive(op.data(), "Spanning"))
|
||||
return CmdOp::Spanning;
|
||||
else if (!CompareCaseInsensitive(op.data(), "SetAdsrCtrl"))
|
||||
return CmdOp::SetAdsrCtrl;
|
||||
else if (!CompareCaseInsensitive(op.data(), "RndNote"))
|
||||
return CmdOp::RndNote;
|
||||
else if (!CompareCaseInsensitive(op.data(), "AddNote"))
|
||||
return CmdOp::AddNote;
|
||||
else if (!CompareCaseInsensitive(op.data(), "SetNote"))
|
||||
return CmdOp::SetNote;
|
||||
else if (!CompareCaseInsensitive(op.data(), "LastNote"))
|
||||
return CmdOp::LastNote;
|
||||
else if (!CompareCaseInsensitive(op.data(), "Portamento"))
|
||||
return CmdOp::Portamento;
|
||||
else if (!CompareCaseInsensitive(op.data(), "Vibrato"))
|
||||
return CmdOp::Vibrato;
|
||||
else if (!CompareCaseInsensitive(op.data(), "PitchSweep1"))
|
||||
return CmdOp::PitchSweep1;
|
||||
else if (!CompareCaseInsensitive(op.data(), "PitchSweep2"))
|
||||
return CmdOp::PitchSweep2;
|
||||
else if (!CompareCaseInsensitive(op.data(), "SetPitch"))
|
||||
return CmdOp::SetPitch;
|
||||
else if (!CompareCaseInsensitive(op.data(), "SetPitchAdsr"))
|
||||
return CmdOp::SetPitchAdsr;
|
||||
else if (!CompareCaseInsensitive(op.data(), "ScaleVolumeDLS"))
|
||||
return CmdOp::ScaleVolumeDLS;
|
||||
else if (!CompareCaseInsensitive(op.data(), "Mod2Vibrange"))
|
||||
return CmdOp::Mod2Vibrange;
|
||||
else if (!CompareCaseInsensitive(op.data(), "SetupTremolo"))
|
||||
return CmdOp::SetupTremolo;
|
||||
else if (!CompareCaseInsensitive(op.data(), "Return"))
|
||||
return CmdOp::Return;
|
||||
else if (!CompareCaseInsensitive(op.data(), "GoSub"))
|
||||
return CmdOp::GoSub;
|
||||
else if (!CompareCaseInsensitive(op.data(), "TrapEvent"))
|
||||
return CmdOp::TrapEvent;
|
||||
else if (!CompareCaseInsensitive(op.data(), "UntrapEvent"))
|
||||
return CmdOp::UntrapEvent;
|
||||
else if (!CompareCaseInsensitive(op.data(), "SendMessage"))
|
||||
return CmdOp::SendMessage;
|
||||
else if (!CompareCaseInsensitive(op.data(), "GetMessage"))
|
||||
return CmdOp::GetMessage;
|
||||
else if (!CompareCaseInsensitive(op.data(), "GetVid"))
|
||||
return CmdOp::GetVid;
|
||||
else if (!CompareCaseInsensitive(op.data(), "AddAgeCount"))
|
||||
return CmdOp::AddAgeCount;
|
||||
else if (!CompareCaseInsensitive(op.data(), "SetAgeCount"))
|
||||
return CmdOp::SetAgeCount;
|
||||
else if (!CompareCaseInsensitive(op.data(), "SendFlag"))
|
||||
return CmdOp::SendFlag;
|
||||
else if (!CompareCaseInsensitive(op.data(), "PitchWheelR"))
|
||||
return CmdOp::PitchWheelR;
|
||||
else if (!CompareCaseInsensitive(op.data(), "SetPriority"))
|
||||
return CmdOp::SetPriority;
|
||||
else if (!CompareCaseInsensitive(op.data(), "AddPriority"))
|
||||
return CmdOp::AddPriority;
|
||||
else if (!CompareCaseInsensitive(op.data(), "AgeCntSpeed"))
|
||||
return CmdOp::AgeCntSpeed;
|
||||
else if (!CompareCaseInsensitive(op.data(), "AgeCntVel"))
|
||||
return CmdOp::AgeCntVel;
|
||||
else if (!CompareCaseInsensitive(op.data(), "VolSelect"))
|
||||
return CmdOp::VolSelect;
|
||||
else if (!CompareCaseInsensitive(op.data(), "PanSelect"))
|
||||
return CmdOp::PanSelect;
|
||||
else if (!CompareCaseInsensitive(op.data(), "PitchWheelSelect"))
|
||||
return CmdOp::PitchWheelSelect;
|
||||
else if (!CompareCaseInsensitive(op.data(), "ModWheelSelect"))
|
||||
return CmdOp::ModWheelSelect;
|
||||
else if (!CompareCaseInsensitive(op.data(), "PedalSelect"))
|
||||
return CmdOp::PedalSelect;
|
||||
else if (!CompareCaseInsensitive(op.data(), "PortamentoSelect"))
|
||||
return CmdOp::PortamentoSelect;
|
||||
else if (!CompareCaseInsensitive(op.data(), "ReverbSelect"))
|
||||
return CmdOp::ReverbSelect;
|
||||
else if (!CompareCaseInsensitive(op.data(), "SpanSelect"))
|
||||
return CmdOp::SpanSelect;
|
||||
else if (!CompareCaseInsensitive(op.data(), "DopplerSelect"))
|
||||
return CmdOp::DopplerSelect;
|
||||
else if (!CompareCaseInsensitive(op.data(), "TremoloSelect"))
|
||||
return CmdOp::TremoloSelect;
|
||||
else if (!CompareCaseInsensitive(op.data(), "PreASelect"))
|
||||
return CmdOp::PreASelect;
|
||||
else if (!CompareCaseInsensitive(op.data(), "PreBSelect"))
|
||||
return CmdOp::PreBSelect;
|
||||
else if (!CompareCaseInsensitive(op.data(), "PostBSelect"))
|
||||
return CmdOp::PostBSelect;
|
||||
else if (!CompareCaseInsensitive(op.data(), "AuxAFXSelect"))
|
||||
return CmdOp::AuxAFXSelect;
|
||||
else if (!CompareCaseInsensitive(op.data(), "AuxBFXSelect"))
|
||||
return CmdOp::AuxBFXSelect;
|
||||
else if (!CompareCaseInsensitive(op.data(), "SetupLFO"))
|
||||
return CmdOp::SetupLFO;
|
||||
else if (!CompareCaseInsensitive(op.data(), "ModeSelect"))
|
||||
return CmdOp::ModeSelect;
|
||||
else if (!CompareCaseInsensitive(op.data(), "SetKeygroup"))
|
||||
return CmdOp::SetKeygroup;
|
||||
else if (!CompareCaseInsensitive(op.data(), "SRCmodeSelect"))
|
||||
return CmdOp::SRCmodeSelect;
|
||||
else if (!CompareCaseInsensitive(op.data(), "AddVars"))
|
||||
return CmdOp::AddVars;
|
||||
else if (!CompareCaseInsensitive(op.data(), "SubVars"))
|
||||
return CmdOp::SubVars;
|
||||
else if (!CompareCaseInsensitive(op.data(), "MulVars"))
|
||||
return CmdOp::MulVars;
|
||||
else if (!CompareCaseInsensitive(op.data(), "DivVars"))
|
||||
return CmdOp::DivVars;
|
||||
else if (!CompareCaseInsensitive(op.data(), "AddIVars"))
|
||||
return CmdOp::AddIVars;
|
||||
else if (!CompareCaseInsensitive(op.data(), "IfEqual"))
|
||||
return CmdOp::IfEqual;
|
||||
else if (!CompareCaseInsensitive(op.data(), "IfLess"))
|
||||
return CmdOp::IfLess;
|
||||
return CmdOp::Invalid;
|
||||
}
|
||||
|
||||
bool AudioGroupPool::toYAML(athena::io::IStreamWriter& writer) const
|
||||
{
|
||||
athena::io::YAMLDocWriter w("amuse::Pool");
|
||||
|
||||
if (!m_soundMacros.empty())
|
||||
{
|
||||
if (auto __r = w.enterSubRecord("soundMacros"))
|
||||
{
|
||||
for (const auto& p : SortUnorderedMap(m_soundMacros))
|
||||
{
|
||||
if (auto __v = w.enterSubVector(SoundMacroId::CurNameDB->resolveNameFromId(p.first).data()))
|
||||
{
|
||||
for (const auto& c : p.second.get().m_cmds)
|
||||
{
|
||||
if (auto __r2 = w.enterSubRecord(nullptr))
|
||||
{
|
||||
w.setStyle(athena::io::YAMLNodeStyle::Flow);
|
||||
w.writeString("cmdOp", SoundMacro::CmdOpToStr(c->Isa()));
|
||||
c->write(w);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_tables.empty())
|
||||
{
|
||||
if (auto __r = w.enterSubRecord("tables"))
|
||||
{
|
||||
for (const auto& p : SortUnorderedMap(m_tables))
|
||||
{
|
||||
if (auto __v = w.enterSubRecord(TableId::CurNameDB->resolveNameFromId(p.first).data()))
|
||||
{
|
||||
w.setStyle(athena::io::YAMLNodeStyle::Flow);
|
||||
p.second.get()->write(w);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_keymaps.empty())
|
||||
{
|
||||
if (auto __r = w.enterSubRecord("keymaps"))
|
||||
{
|
||||
for (const auto& p : SortUnorderedMap(m_keymaps))
|
||||
{
|
||||
if (auto __v = w.enterSubRecord(KeymapId::CurNameDB->resolveNameFromId(p.first).data()))
|
||||
{
|
||||
w.setStyle(athena::io::YAMLNodeStyle::Flow);
|
||||
p.second.get().write(w);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_layers.empty())
|
||||
{
|
||||
if (auto __r = w.enterSubRecord("layers"))
|
||||
{
|
||||
for (const auto& p : SortUnorderedMap(m_layers))
|
||||
{
|
||||
if (auto __v = w.enterSubVector(LayersId::CurNameDB->resolveNameFromId(p.first).data()))
|
||||
{
|
||||
for (const auto& lm : p.second.get())
|
||||
{
|
||||
if (auto __r2 = w.enterSubRecord(nullptr))
|
||||
{
|
||||
w.setStyle(athena::io::YAMLNodeStyle::Flow);
|
||||
lm.write(w);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return w.finish(&writer);
|
||||
}
|
||||
|
||||
template <>
|
||||
void amuse::Curve::Enumerate<LittleDNA::Read>(athena::io::IStreamReader& r)
|
||||
{
|
||||
|
@ -368,17 +774,18 @@ void amuse::Curve::Enumerate<LittleDNA::BinarySize>(size_t& sz)
|
|||
template <>
|
||||
void amuse::Curve::Enumerate<LittleDNA::ReadYaml>(athena::io::YAMLDocReader& r)
|
||||
{
|
||||
r.enumerate(nullptr, data);
|
||||
r.enumerate("data", data);
|
||||
}
|
||||
|
||||
template <>
|
||||
void amuse::Curve::Enumerate<LittleDNA::WriteYaml>(athena::io::YAMLDocWriter& w)
|
||||
{
|
||||
w.enumerate(nullptr, data);
|
||||
w.enumerate("data", data);
|
||||
}
|
||||
|
||||
const char* amuse::Curve::DNAType()
|
||||
{
|
||||
return "amuse::ADSR";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -72,7 +72,7 @@ AudioGroupProject::AudioGroupProject(athena::io::IStreamReader& r, GCNDataTag)
|
|||
{
|
||||
SFXGroupIndex::SFXEntryDNA<athena::Big> entry;
|
||||
entry.read(r);
|
||||
idx.m_sfxEntries[entry.defineId.id] = entry;
|
||||
idx.m_sfxEntries[entry.sfxId.id] = entry;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -120,7 +120,8 @@ AudioGroupProject AudioGroupProject::_AudioGroupProject(athena::io::IStreamReade
|
|||
r.seek(header.midiSetupsOff, athena::Begin);
|
||||
while (r.position() < header.groupEndOff)
|
||||
{
|
||||
uint16_t songId = r.readUint16Big();
|
||||
uint16_t songId;
|
||||
athena::io::Read<athena::io::PropType::None>::Do<decltype(songId), DNAE>({}, songId, r);
|
||||
r.seek(2, athena::Current);
|
||||
std::array<SongGroupIndex::MIDISetup, 16>& setup = idx.m_midiSetups[songId];
|
||||
for (int i = 0; i < 16 ; ++i)
|
||||
|
@ -151,7 +152,8 @@ AudioGroupProject AudioGroupProject::_AudioGroupProject(athena::io::IStreamReade
|
|||
r.seek(subDataOff + header.midiSetupsOff, athena::Begin);
|
||||
while (r.position() < groupBegin + header.groupEndOff)
|
||||
{
|
||||
uint16_t songId = r.readUint16Big();
|
||||
uint16_t songId;
|
||||
athena::io::Read<athena::io::PropType::None>::Do<decltype(songId), DNAE>({}, songId, r);
|
||||
r.seek(2, athena::Current);
|
||||
std::array<SongGroupIndex::MIDISetup, 16>& setup = idx.m_midiSetups[songId];
|
||||
for (int i = 0; i < 16 ; ++i)
|
||||
|
@ -169,7 +171,8 @@ AudioGroupProject AudioGroupProject::_AudioGroupProject(athena::io::IStreamReade
|
|||
|
||||
/* SFX entries */
|
||||
r.seek(subDataOff + header.pageTableOff, athena::Begin);
|
||||
uint16_t count = r.readUint16Big();
|
||||
uint16_t count;
|
||||
athena::io::Read<athena::io::PropType::None>::Do<decltype(count), DNAE>({}, count, r);
|
||||
r.seek(2, athena::Current);
|
||||
idx.m_sfxEntries.reserve(count);
|
||||
for (int i = 0; i < count; ++i)
|
||||
|
@ -177,7 +180,7 @@ AudioGroupProject AudioGroupProject::_AudioGroupProject(athena::io::IStreamReade
|
|||
SFXGroupIndex::SFXEntryDNA<DNAE> entry;
|
||||
entry.read(r);
|
||||
r.seek(2, athena::Current);
|
||||
idx.m_sfxEntries[entry.defineId.id] = entry;
|
||||
idx.m_sfxEntries[entry.sfxId.id] = entry;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -205,6 +208,194 @@ AudioGroupProject AudioGroupProject::CreateAudioGroupProject(const AudioGroupDat
|
|||
}
|
||||
}
|
||||
|
||||
template <athena::Endian DNAE>
|
||||
static void ReadRangedObjectIds(NameDB* db, athena::io::IStreamReader& r, NameDB::Type tp)
|
||||
{
|
||||
uint16_t id;
|
||||
athena::io::Read<athena::io::PropType::None>::Do<decltype(id), DNAE>({}, id, r);
|
||||
if ((id & 0x8000) == 0x8000)
|
||||
{
|
||||
uint16_t endId;
|
||||
athena::io::Read<athena::io::PropType::None>::Do<decltype(endId), DNAE>({}, endId, r);
|
||||
for (uint16_t i = uint16_t(id & 0x7fff); i <= uint16_t(endId & 0x7fff); ++i)
|
||||
{
|
||||
ObjectId useId = i;
|
||||
if (tp == NameDB::Type::Layer)
|
||||
useId.id |= 0x8000;
|
||||
db->registerPair(NameDB::generateName(useId, tp), useId);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
db->registerPair(NameDB::generateName(id, tp), id);
|
||||
}
|
||||
}
|
||||
|
||||
void AudioGroupProject::BootstrapObjectIDs(athena::io::IStreamReader& r, GCNDataTag)
|
||||
{
|
||||
while (!AtEnd32(r))
|
||||
{
|
||||
GroupHeader<athena::Big> header;
|
||||
header.read(r);
|
||||
|
||||
/* Sound Macros */
|
||||
r.seek(header.soundMacroIdsOff, athena::Begin);
|
||||
while (!AtEnd16(r))
|
||||
ReadRangedObjectIds<athena::Big>(SoundMacroId::CurNameDB, r, NameDB::Type::SoundMacro);
|
||||
|
||||
/* Samples */
|
||||
r.seek(header.samplIdsOff, athena::Begin);
|
||||
while (!AtEnd16(r))
|
||||
ReadRangedObjectIds<athena::Big>(SampleId::CurNameDB, r, NameDB::Type::Sample);
|
||||
|
||||
/* Tables */
|
||||
r.seek(header.tableIdsOff, athena::Begin);
|
||||
while (!AtEnd16(r))
|
||||
ReadRangedObjectIds<athena::Big>(TableId::CurNameDB, r, NameDB::Type::Table);
|
||||
|
||||
/* Keymaps */
|
||||
r.seek(header.keymapIdsOff, athena::Begin);
|
||||
while (!AtEnd16(r))
|
||||
ReadRangedObjectIds<athena::Big>(KeymapId::CurNameDB, r, NameDB::Type::Keymap);
|
||||
|
||||
/* Layers */
|
||||
r.seek(header.layerIdsOff, athena::Begin);
|
||||
while (!AtEnd16(r))
|
||||
ReadRangedObjectIds<athena::Big>(LayersId::CurNameDB, r, NameDB::Type::Layer);
|
||||
|
||||
if (header.type == GroupType::Song)
|
||||
{
|
||||
/* MIDI setups */
|
||||
r.seek(header.midiSetupsOff, athena::Begin);
|
||||
while (r.position() < header.groupEndOff)
|
||||
{
|
||||
uint16_t id = r.readUint16Big();
|
||||
SongId::CurNameDB->registerPair(NameDB::generateName(id, NameDB::Type::Song), id);
|
||||
r.seek(2 + 5 * 16, athena::Current);
|
||||
}
|
||||
}
|
||||
else if (header.type == GroupType::SFX)
|
||||
{
|
||||
/* SFX entries */
|
||||
r.seek(header.pageTableOff, athena::Begin);
|
||||
uint16_t count = r.readUint16Big();
|
||||
r.seek(2, athena::Current);
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
SFXGroupIndex::SFXEntryDNA<athena::Big> entry;
|
||||
entry.read(r);
|
||||
SFXId::CurNameDB->registerPair(
|
||||
NameDB::generateName(entry.sfxId.id, NameDB::Type::SFX), entry.sfxId.id);
|
||||
}
|
||||
}
|
||||
|
||||
r.seek(header.groupEndOff, athena::Begin);
|
||||
}
|
||||
}
|
||||
|
||||
template <athena::Endian DNAE>
|
||||
void AudioGroupProject::BootstrapObjectIDs(athena::io::IStreamReader& r, bool absOffs)
|
||||
{
|
||||
while (!AtEnd32(r))
|
||||
{
|
||||
atInt64 groupBegin = r.position();
|
||||
atInt64 subDataOff = absOffs ? 0 : groupBegin + 8;
|
||||
GroupHeader<DNAE> header;
|
||||
header.read(r);
|
||||
|
||||
/* Sound Macros */
|
||||
r.seek(subDataOff + header.soundMacroIdsOff, athena::Begin);
|
||||
while (!AtEnd16(r))
|
||||
ReadRangedObjectIds<DNAE>(SoundMacroId::CurNameDB, r, NameDB::Type::SoundMacro);
|
||||
|
||||
/* Samples */
|
||||
r.seek(subDataOff + header.samplIdsOff, athena::Begin);
|
||||
while (!AtEnd16(r))
|
||||
ReadRangedObjectIds<DNAE>(SampleId::CurNameDB, r, NameDB::Type::Sample);
|
||||
|
||||
/* Tables */
|
||||
r.seek(subDataOff + header.tableIdsOff, athena::Begin);
|
||||
while (!AtEnd16(r))
|
||||
ReadRangedObjectIds<DNAE>(TableId::CurNameDB, r, NameDB::Type::Table);
|
||||
|
||||
/* Keymaps */
|
||||
r.seek(subDataOff + header.keymapIdsOff, athena::Begin);
|
||||
while (!AtEnd16(r))
|
||||
ReadRangedObjectIds<DNAE>(KeymapId::CurNameDB, r, NameDB::Type::Keymap);
|
||||
|
||||
/* Layers */
|
||||
r.seek(subDataOff + header.layerIdsOff, athena::Begin);
|
||||
while (!AtEnd16(r))
|
||||
ReadRangedObjectIds<DNAE>(LayersId::CurNameDB, r, NameDB::Type::Layer);
|
||||
|
||||
if (header.type == GroupType::Song)
|
||||
{
|
||||
/* MIDI setups */
|
||||
if (absOffs)
|
||||
{
|
||||
r.seek(header.midiSetupsOff, athena::Begin);
|
||||
while (r.position() < header.groupEndOff)
|
||||
{
|
||||
uint16_t id;
|
||||
athena::io::Read<athena::io::PropType::None>::Do<decltype(id), DNAE>({}, id, r);
|
||||
SongId::CurNameDB->registerPair(NameDB::generateName(id, NameDB::Type::Song), id);
|
||||
r.seek(2 + 5 * 16, athena::Current);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
r.seek(subDataOff + header.midiSetupsOff, athena::Begin);
|
||||
while (r.position() < groupBegin + header.groupEndOff)
|
||||
{
|
||||
uint16_t id;
|
||||
athena::io::Read<athena::io::PropType::None>::Do<decltype(id), DNAE>({}, id, r);
|
||||
SongId::CurNameDB->registerPair(NameDB::generateName(id, NameDB::Type::Song), id);
|
||||
r.seek(2 + 8 * 16, athena::Current);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (header.type == GroupType::SFX)
|
||||
{
|
||||
/* SFX entries */
|
||||
r.seek(subDataOff + header.pageTableOff, athena::Begin);
|
||||
uint16_t count;
|
||||
athena::io::Read<athena::io::PropType::None>::Do<decltype(count), DNAE>({}, count, r);
|
||||
r.seek(2, athena::Current);
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
SFXGroupIndex::SFXEntryDNA<DNAE> entry;
|
||||
entry.read(r);
|
||||
r.seek(2, athena::Current);
|
||||
SFXId::CurNameDB->registerPair(
|
||||
NameDB::generateName(entry.sfxId.id, NameDB::Type::SFX), entry.sfxId.id);
|
||||
}
|
||||
}
|
||||
|
||||
if (absOffs)
|
||||
r.seek(header.groupEndOff, athena::Begin);
|
||||
else
|
||||
r.seek(groupBegin + header.groupEndOff, athena::Begin);
|
||||
}
|
||||
}
|
||||
|
||||
void AudioGroupProject::BootstrapObjectIDs(const AudioGroupData& data)
|
||||
{
|
||||
athena::io::MemoryReader r(data.getProj(), data.getProjSize());
|
||||
switch (data.getDataFormat())
|
||||
{
|
||||
case DataFormat::GCN:
|
||||
default:
|
||||
BootstrapObjectIDs(r, GCNDataTag{});
|
||||
break;
|
||||
case DataFormat::N64:
|
||||
BootstrapObjectIDs<athena::Big>(r, data.getAbsoluteProjOffsets());
|
||||
break;
|
||||
case DataFormat::PC:
|
||||
BootstrapObjectIDs<athena::Little>(r, data.getAbsoluteProjOffsets());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const SongGroupIndex* AudioGroupProject::getSongGroupIndex(int groupId) const
|
||||
{
|
||||
auto search = m_songGroups.find(groupId);
|
||||
|
@ -221,4 +412,93 @@ const SFXGroupIndex* AudioGroupProject::getSFXGroupIndex(int groupId) const
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
bool AudioGroupProject::toYAML(athena::io::IStreamWriter& writer) const
|
||||
{
|
||||
athena::io::YAMLDocWriter w("amuse::Project");
|
||||
|
||||
if (!m_songGroups.empty())
|
||||
{
|
||||
if (auto __v = w.enterSubVector("songGroups"))
|
||||
{
|
||||
for (const auto& p : SortUnorderedMap(m_songGroups))
|
||||
{
|
||||
if (auto __r = w.enterSubRecord(nullptr))
|
||||
{
|
||||
if (!p.second.get().m_normPages.empty())
|
||||
{
|
||||
if (auto __v2 = w.enterSubRecord("normPages"))
|
||||
{
|
||||
for (const auto& pg : SortUnorderedMap(p.second.get().m_normPages))
|
||||
{
|
||||
char name[16];
|
||||
snprintf(name, 16, "%d", pg.first);
|
||||
if (auto __r2 = w.enterSubRecord(name))
|
||||
{
|
||||
w.setStyle(athena::io::YAMLNodeStyle::Flow);
|
||||
pg.second.get().write(w);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!p.second.get().m_drumPages.empty())
|
||||
{
|
||||
if (auto __v2 = w.enterSubRecord("drumPages"))
|
||||
{
|
||||
for (const auto& pg : SortUnorderedMap(p.second.get().m_drumPages))
|
||||
{
|
||||
char name[16];
|
||||
snprintf(name, 16, "%d", pg.first);
|
||||
if (auto __r2 = w.enterSubRecord(name))
|
||||
{
|
||||
w.setStyle(athena::io::YAMLNodeStyle::Flow);
|
||||
pg.second.get().write(w);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!p.second.get().m_midiSetups.empty())
|
||||
{
|
||||
if (auto __v2 = w.enterSubRecord("songs"))
|
||||
{
|
||||
for (const auto& song : SortUnorderedMap(p.second.get().m_midiSetups))
|
||||
{
|
||||
if (auto __v3 = w.enterSubVector(SongId::CurNameDB->resolveNameFromId(song.first).data()))
|
||||
for (int i = 0; i < 16; ++i)
|
||||
if (auto __r2 = w.enterSubRecord(nullptr))
|
||||
{
|
||||
w.setStyle(athena::io::YAMLNodeStyle::Flow);
|
||||
song.second.get()[i].write(w);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_sfxGroups.empty())
|
||||
{
|
||||
if (auto __v = w.enterSubVector("sfxGroups"))
|
||||
{
|
||||
for (const auto& p : SortUnorderedMap(m_sfxGroups))
|
||||
{
|
||||
if (auto __r = w.enterSubRecord(nullptr))
|
||||
{
|
||||
for (const auto& sfx : SortUnorderedMap(p.second.get().m_sfxEntries))
|
||||
{
|
||||
if (auto __r2 = w.enterSubRecord(SFXId::CurNameDB->resolveNameFromId(sfx.first).data()))
|
||||
{
|
||||
w.setStyle(athena::io::YAMLNodeStyle::Flow);
|
||||
sfx.second.get().write(w);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return w.finish(&writer);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2,20 +2,16 @@
|
|||
#include "amuse/Common.hpp"
|
||||
#include "amuse/AudioGroupData.hpp"
|
||||
#include <cstring>
|
||||
#include <athena/MemoryReader.hpp>
|
||||
|
||||
namespace amuse
|
||||
{
|
||||
|
||||
void AudioGroupSampleDirectory::Entry::swapBig()
|
||||
static bool AtEnd32(athena::io::IStreamReader& r)
|
||||
{
|
||||
m_sfxId = SBig(m_sfxId);
|
||||
m_sampleOff = SBig(m_sampleOff);
|
||||
m_unk = SBig(m_unk);
|
||||
m_sampleRate = SBig(m_sampleRate);
|
||||
m_numSamples = SBig(m_numSamples);
|
||||
m_loopStartSample = SBig(m_loopStartSample);
|
||||
m_loopLengthSamples = SBig(m_loopLengthSamples);
|
||||
m_adpcmParmOffset = SBig(m_adpcmParmOffset);
|
||||
uint32_t v = r.readUint32Big();
|
||||
r.seek(-4, athena::Current);
|
||||
return v == 0xffffffff;
|
||||
}
|
||||
|
||||
void AudioGroupSampleDirectory::ADPCMParms::swapBigDSP()
|
||||
|
@ -37,177 +33,94 @@ void AudioGroupSampleDirectory::ADPCMParms::swapBigVADPCM()
|
|||
allCoefs[i] = SBig(allCoefs[i]);
|
||||
}
|
||||
|
||||
AudioGroupSampleDirectory::AudioGroupSampleDirectory(const unsigned char* data, GCNDataTag)
|
||||
AudioGroupSampleDirectory::AudioGroupSampleDirectory(athena::io::IStreamReader& r, GCNDataTag)
|
||||
{
|
||||
const unsigned char* cur = data;
|
||||
while (*reinterpret_cast<const uint32_t*>(cur) != 0xffffffff)
|
||||
while (!AtEnd32(r))
|
||||
{
|
||||
const AudioGroupSampleDirectory::Entry* ent = reinterpret_cast<const AudioGroupSampleDirectory::Entry*>(cur);
|
||||
EntryDNA<athena::Big> ent;
|
||||
ent.read(r);
|
||||
std::pair<Entry, ADPCMParms>& store = m_entries[ent.m_sfxId];
|
||||
store.first = ent;
|
||||
}
|
||||
|
||||
std::pair<Entry, ADPCMParms>& store = m_entries[SBig(ent->m_sfxId)];
|
||||
store.first = *ent;
|
||||
store.first.swapBig();
|
||||
|
||||
if (store.first.m_adpcmParmOffset)
|
||||
for (auto& p : m_entries)
|
||||
{
|
||||
if (p.second.first.m_adpcmParmOffset)
|
||||
{
|
||||
const AudioGroupSampleDirectory::ADPCMParms* adpcm =
|
||||
reinterpret_cast<const AudioGroupSampleDirectory::ADPCMParms*>(data + store.first.m_adpcmParmOffset);
|
||||
store.second.dsp = adpcm->dsp;
|
||||
store.second.swapBigDSP();
|
||||
r.seek(p.second.first.m_adpcmParmOffset, athena::Begin);
|
||||
r.readUBytesToBuf(&p.second.second, sizeof(ADPCMParms::DSPParms));
|
||||
p.second.second.swapBigDSP();
|
||||
}
|
||||
|
||||
cur += 32;
|
||||
}
|
||||
}
|
||||
|
||||
struct MusyX1SdirEntry
|
||||
{
|
||||
uint16_t m_sfxId;
|
||||
uint32_t m_sampleOff;
|
||||
uint32_t m_pitchSampleRate;
|
||||
uint32_t m_numSamples;
|
||||
uint32_t m_loopStartSample;
|
||||
uint32_t m_loopLengthSamples;
|
||||
|
||||
void swapBig()
|
||||
{
|
||||
m_sfxId = SBig(m_sfxId);
|
||||
m_sampleOff = SBig(m_sampleOff);
|
||||
m_pitchSampleRate = SBig(m_pitchSampleRate);
|
||||
m_numSamples = SBig(m_numSamples);
|
||||
m_loopStartSample = SBig(m_loopStartSample);
|
||||
m_loopLengthSamples = SBig(m_loopLengthSamples);
|
||||
}
|
||||
|
||||
void setIntoMusyX2(AudioGroupSampleDirectory::Entry& ent) const
|
||||
{
|
||||
ent.m_sfxId = m_sfxId;
|
||||
ent.m_sampleOff = m_sampleOff;
|
||||
ent.m_unk = 0;
|
||||
ent.m_pitch = m_pitchSampleRate >> 24;
|
||||
ent.m_sampleRate = m_pitchSampleRate & 0xffff;
|
||||
ent.m_numSamples = m_numSamples;
|
||||
ent.m_loopStartSample = m_loopStartSample;
|
||||
ent.m_loopLengthSamples = m_loopLengthSamples;
|
||||
ent.m_adpcmParmOffset = 0;
|
||||
}
|
||||
};
|
||||
|
||||
struct MusyX1AbsSdirEntry
|
||||
{
|
||||
uint16_t m_sfxId;
|
||||
uint32_t m_sampleOff;
|
||||
uint32_t m_unk;
|
||||
uint32_t m_pitchSampleRate;
|
||||
uint32_t m_numSamples;
|
||||
uint32_t m_loopStartSample;
|
||||
uint32_t m_loopLengthSamples;
|
||||
|
||||
void swapBig()
|
||||
{
|
||||
m_sfxId = SBig(m_sfxId);
|
||||
m_sampleOff = SBig(m_sampleOff);
|
||||
m_unk = SBig(m_unk);
|
||||
m_pitchSampleRate = SBig(m_pitchSampleRate);
|
||||
m_numSamples = SBig(m_numSamples);
|
||||
m_loopStartSample = SBig(m_loopStartSample);
|
||||
m_loopLengthSamples = SBig(m_loopLengthSamples);
|
||||
}
|
||||
|
||||
void setIntoMusyX2(AudioGroupSampleDirectory::Entry& ent) const
|
||||
{
|
||||
ent.m_sfxId = m_sfxId;
|
||||
ent.m_sampleOff = m_sampleOff;
|
||||
ent.m_unk = m_unk;
|
||||
ent.m_pitch = m_pitchSampleRate >> 24;
|
||||
ent.m_sampleRate = m_pitchSampleRate & 0xffff;
|
||||
ent.m_numSamples = m_numSamples;
|
||||
ent.m_loopStartSample = m_loopStartSample;
|
||||
ent.m_loopLengthSamples = m_loopLengthSamples;
|
||||
ent.m_adpcmParmOffset = 0;
|
||||
}
|
||||
};
|
||||
|
||||
AudioGroupSampleDirectory::AudioGroupSampleDirectory(const unsigned char* data, const unsigned char* sampData,
|
||||
AudioGroupSampleDirectory::AudioGroupSampleDirectory(athena::io::IStreamReader& r, const unsigned char* sampData,
|
||||
bool absOffs, N64DataTag)
|
||||
{
|
||||
const unsigned char* cur = data;
|
||||
|
||||
if (absOffs)
|
||||
{
|
||||
while (*reinterpret_cast<const uint32_t*>(cur) != 0xffffffff)
|
||||
while (!AtEnd32(r))
|
||||
{
|
||||
MusyX1AbsSdirEntry ent = *reinterpret_cast<const MusyX1AbsSdirEntry*>(cur);
|
||||
ent.swapBig();
|
||||
|
||||
MusyX1AbsSdirEntry<athena::Big> ent;
|
||||
ent.read(r);
|
||||
std::pair<Entry, ADPCMParms>& store = m_entries[ent.m_sfxId];
|
||||
ent.setIntoMusyX2(store.first);
|
||||
|
||||
memmove(&store.second.vadpcm.m_coefs, sampData + ent.m_sampleOff, 256);
|
||||
store.second.swapBigVADPCM();
|
||||
|
||||
cur += 28;
|
||||
store.first = ent;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (*reinterpret_cast<const uint32_t*>(cur) != 0xffffffff)
|
||||
while (!AtEnd32(r))
|
||||
{
|
||||
MusyX1SdirEntry ent = *reinterpret_cast<const MusyX1SdirEntry*>(cur);
|
||||
ent.swapBig();
|
||||
|
||||
MusyX1SdirEntry<athena::Big> ent;
|
||||
ent.read(r);
|
||||
std::pair<Entry, ADPCMParms>& store = m_entries[ent.m_sfxId];
|
||||
ent.setIntoMusyX2(store.first);
|
||||
|
||||
memmove(&store.second.vadpcm.m_coefs, sampData + ent.m_sampleOff, 256);
|
||||
store.second.swapBigVADPCM();
|
||||
|
||||
cur += 24;
|
||||
store.first = ent;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& p : m_entries)
|
||||
{
|
||||
memcpy(&p.second.second, sampData + p.second.first.m_sampleOff, sizeof(ADPCMParms::VADPCMParms));
|
||||
p.second.second.swapBigVADPCM();
|
||||
}
|
||||
}
|
||||
|
||||
AudioGroupSampleDirectory::AudioGroupSampleDirectory(const unsigned char* data, bool absOffs, PCDataTag)
|
||||
AudioGroupSampleDirectory::AudioGroupSampleDirectory(athena::io::IStreamReader& r, bool absOffs, PCDataTag)
|
||||
{
|
||||
const unsigned char* cur = data;
|
||||
|
||||
if (absOffs)
|
||||
{
|
||||
while (*reinterpret_cast<const uint32_t*>(cur) != 0xffffffff)
|
||||
while (!AtEnd32(r))
|
||||
{
|
||||
const MusyX1AbsSdirEntry* ent = reinterpret_cast<const MusyX1AbsSdirEntry*>(cur);
|
||||
|
||||
std::pair<Entry, ADPCMParms>& store = m_entries[ent->m_sfxId];
|
||||
ent->setIntoMusyX2(store.first);
|
||||
|
||||
cur += 28;
|
||||
MusyX1AbsSdirEntry<athena::Little> ent;
|
||||
ent.read(r);
|
||||
std::pair<Entry, ADPCMParms>& store = m_entries[ent.m_sfxId];
|
||||
store.first = ent;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (*reinterpret_cast<const uint32_t*>(cur) != 0xffffffff)
|
||||
while (!AtEnd32(r))
|
||||
{
|
||||
const MusyX1SdirEntry* ent = reinterpret_cast<const MusyX1SdirEntry*>(cur);
|
||||
|
||||
std::pair<Entry, ADPCMParms>& store = m_entries[ent->m_sfxId];
|
||||
ent->setIntoMusyX2(store.first);
|
||||
|
||||
cur += 24;
|
||||
MusyX1SdirEntry<athena::Little> ent;
|
||||
ent.read(r);
|
||||
std::pair<Entry, ADPCMParms>& store = m_entries[ent.m_sfxId];
|
||||
store.first = ent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AudioGroupSampleDirectory AudioGroupSampleDirectory::CreateAudioGroupSampleDirectory(const AudioGroupData& data)
|
||||
{
|
||||
athena::io::MemoryReader r(data.getSdir(), data.getSdirSize());
|
||||
switch (data.getDataFormat())
|
||||
{
|
||||
case DataFormat::GCN:
|
||||
default:
|
||||
return AudioGroupSampleDirectory(data.getSdir(), GCNDataTag{});
|
||||
return AudioGroupSampleDirectory(r, GCNDataTag{});
|
||||
case DataFormat::N64:
|
||||
return AudioGroupSampleDirectory(data.getSdir(), data.getSamp(), data.getAbsoluteProjOffsets(), N64DataTag{});
|
||||
return AudioGroupSampleDirectory(r, data.getSamp(), data.getAbsoluteProjOffsets(), N64DataTag{});
|
||||
case DataFormat::PC:
|
||||
return AudioGroupSampleDirectory(data.getSdir(), data.getAbsoluteProjOffsets(), PCDataTag{});
|
||||
return AudioGroupSampleDirectory(r, data.getAbsoluteProjOffsets(), PCDataTag{});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
462
lib/Common.cpp
462
lib/Common.cpp
|
@ -5,374 +5,228 @@ namespace amuse
|
|||
{
|
||||
static logvisor::Module Log("amuse");
|
||||
|
||||
thread_local NameDB* ObjectId::CurNameDB = nullptr;
|
||||
thread_local NameDB* SampleId::CurNameDB = nullptr;
|
||||
thread_local NameDB* SongId::CurNameDB = nullptr;
|
||||
thread_local NameDB* SFXId::CurNameDB = nullptr;
|
||||
#define DEFINE_ID_TYPE(type, typeName) \
|
||||
thread_local NameDB* type::CurNameDB = nullptr; \
|
||||
template<> template<> \
|
||||
void type##DNA<athena::Little>::Enumerate<BigDNA::Read>(athena::io::IStreamReader& reader) \
|
||||
{ \
|
||||
id = reader.readUint16Little(); \
|
||||
} \
|
||||
template<> template<> \
|
||||
void type##DNA<athena::Little>::Enumerate<BigDNA::Write>(athena::io::IStreamWriter& writer) \
|
||||
{ \
|
||||
writer.writeUint16Little(id); \
|
||||
} \
|
||||
template<> template<> \
|
||||
void type##DNA<athena::Little>::Enumerate<BigDNA::BinarySize>(size_t& sz) \
|
||||
{ \
|
||||
sz += 2; \
|
||||
} \
|
||||
template<> template<> \
|
||||
void type##DNA<athena::Little>::Enumerate<BigDNA::ReadYaml>(athena::io::YAMLDocReader& reader) \
|
||||
{ \
|
||||
_read(reader); \
|
||||
} \
|
||||
template<> template<> \
|
||||
void type##DNA<athena::Little>::Enumerate<BigDNA::WriteYaml>(athena::io::YAMLDocWriter& writer) \
|
||||
{ \
|
||||
_write(writer); \
|
||||
} \
|
||||
template<> template<> \
|
||||
void type##DNA<athena::Big>::Enumerate<BigDNA::Read>(athena::io::IStreamReader& reader) \
|
||||
{ \
|
||||
id = reader.readUint16Big(); \
|
||||
} \
|
||||
template<> template<> \
|
||||
void type##DNA<athena::Big>::Enumerate<BigDNA::Write>(athena::io::IStreamWriter& writer) \
|
||||
{ \
|
||||
writer.writeUint16Big(id); \
|
||||
} \
|
||||
template<> template<> \
|
||||
void type##DNA<athena::Big>::Enumerate<BigDNA::BinarySize>(size_t& sz) \
|
||||
{ \
|
||||
sz += 2; \
|
||||
} \
|
||||
template<> template<> \
|
||||
void type##DNA<athena::Big>::Enumerate<BigDNA::ReadYaml>(athena::io::YAMLDocReader& reader) \
|
||||
{ \
|
||||
_read(reader); \
|
||||
} \
|
||||
template<> template<> \
|
||||
void type##DNA<athena::Big>::Enumerate<BigDNA::WriteYaml>(athena::io::YAMLDocWriter& writer) \
|
||||
{ \
|
||||
_write(writer); \
|
||||
} \
|
||||
template <athena::Endian DNAE> \
|
||||
void type##DNA<DNAE>::_read(athena::io::YAMLDocReader& r) \
|
||||
{ \
|
||||
std::string name = r.readString(nullptr); \
|
||||
if (!type::CurNameDB) \
|
||||
Log.report(logvisor::Fatal, "Unable to resolve " typeName " name %s, no database present", name.c_str()); \
|
||||
if (name.empty()) \
|
||||
{ \
|
||||
id.id = 0xffff; \
|
||||
return; \
|
||||
} \
|
||||
id = type::CurNameDB->resolveIdFromName(name); \
|
||||
} \
|
||||
template <athena::Endian DNAE> \
|
||||
void type##DNA<DNAE>::_write(athena::io::YAMLDocWriter& w) \
|
||||
{ \
|
||||
if (!type::CurNameDB) \
|
||||
Log.report(logvisor::Fatal, "Unable to resolve " typeName " ID %d, no database present", id.id); \
|
||||
if (id.id == 0xffff) \
|
||||
return; \
|
||||
std::string_view name = type::CurNameDB->resolveNameFromId(id); \
|
||||
w.writeString(nullptr, name); \
|
||||
} \
|
||||
template <athena::Endian DNAE> \
|
||||
const char* type##DNA<DNAE>::DNAType() \
|
||||
{ \
|
||||
return "amuse::" #type "DNA"; \
|
||||
} \
|
||||
template struct type##DNA<athena::Big>; \
|
||||
template struct type##DNA<athena::Little>;
|
||||
|
||||
DEFINE_ID_TYPE(ObjectId, "object")
|
||||
DEFINE_ID_TYPE(SoundMacroId, "SoundMacro")
|
||||
DEFINE_ID_TYPE(SampleId, "sample")
|
||||
DEFINE_ID_TYPE(TableId, "table")
|
||||
DEFINE_ID_TYPE(KeymapId, "keymap")
|
||||
DEFINE_ID_TYPE(LayersId, "layers")
|
||||
DEFINE_ID_TYPE(SongId, "song")
|
||||
DEFINE_ID_TYPE(SFXId, "sfx")
|
||||
|
||||
template<> template<>
|
||||
void ObjectIdDNA<athena::Little>::Enumerate<BigDNA::Read>(athena::io::IStreamReader& reader)
|
||||
void PageObjectIdDNA<athena::Little>::Enumerate<BigDNA::Read>(athena::io::IStreamReader& reader)
|
||||
{
|
||||
id = reader.readUint16Little();
|
||||
}
|
||||
|
||||
template<> template<>
|
||||
void ObjectIdDNA<athena::Little>::Enumerate<BigDNA::Write>(athena::io::IStreamWriter& writer)
|
||||
void PageObjectIdDNA<athena::Little>::Enumerate<BigDNA::Write>(athena::io::IStreamWriter& writer)
|
||||
{
|
||||
writer.writeUint16Little(id);
|
||||
}
|
||||
|
||||
template<> template<>
|
||||
void ObjectIdDNA<athena::Little>::Enumerate<BigDNA::BinarySize>(size_t& sz)
|
||||
void PageObjectIdDNA<athena::Little>::Enumerate<BigDNA::BinarySize>(size_t& sz)
|
||||
{
|
||||
sz += 2;
|
||||
}
|
||||
|
||||
template<> template<>
|
||||
void ObjectIdDNA<athena::Little>::Enumerate<BigDNA::ReadYaml>(athena::io::YAMLDocReader& reader)
|
||||
void PageObjectIdDNA<athena::Little>::Enumerate<BigDNA::ReadYaml>(athena::io::YAMLDocReader& reader)
|
||||
{
|
||||
_read(reader);
|
||||
}
|
||||
|
||||
template<> template<>
|
||||
void ObjectIdDNA<athena::Little>::Enumerate<BigDNA::WriteYaml>(athena::io::YAMLDocWriter& writer)
|
||||
void PageObjectIdDNA<athena::Little>::Enumerate<BigDNA::WriteYaml>(athena::io::YAMLDocWriter& writer)
|
||||
{
|
||||
_write(writer);
|
||||
}
|
||||
|
||||
template<> template<>
|
||||
void ObjectIdDNA<athena::Big>::Enumerate<BigDNA::Read>(athena::io::IStreamReader& reader)
|
||||
void PageObjectIdDNA<athena::Big>::Enumerate<BigDNA::Read>(athena::io::IStreamReader& reader)
|
||||
{
|
||||
id = reader.readUint16Big();
|
||||
}
|
||||
|
||||
template<> template<>
|
||||
void ObjectIdDNA<athena::Big>::Enumerate<BigDNA::Write>(athena::io::IStreamWriter& writer)
|
||||
void PageObjectIdDNA<athena::Big>::Enumerate<BigDNA::Write>(athena::io::IStreamWriter& writer)
|
||||
{
|
||||
writer.writeUint16Big(id);
|
||||
}
|
||||
|
||||
template<> template<>
|
||||
void ObjectIdDNA<athena::Big>::Enumerate<BigDNA::BinarySize>(size_t& sz)
|
||||
void PageObjectIdDNA<athena::Big>::Enumerate<BigDNA::BinarySize>(size_t& sz)
|
||||
{
|
||||
sz += 2;
|
||||
}
|
||||
|
||||
template<> template<>
|
||||
void ObjectIdDNA<athena::Big>::Enumerate<BigDNA::ReadYaml>(athena::io::YAMLDocReader& reader)
|
||||
void PageObjectIdDNA<athena::Big>::Enumerate<BigDNA::ReadYaml>(athena::io::YAMLDocReader& reader)
|
||||
{
|
||||
_read(reader);
|
||||
}
|
||||
|
||||
template<> template<>
|
||||
void ObjectIdDNA<athena::Big>::Enumerate<BigDNA::WriteYaml>(athena::io::YAMLDocWriter& writer)
|
||||
void PageObjectIdDNA<athena::Big>::Enumerate<BigDNA::WriteYaml>(athena::io::YAMLDocWriter& writer)
|
||||
{
|
||||
_write(writer);
|
||||
}
|
||||
|
||||
template <athena::Endian DNAE>
|
||||
void ObjectIdDNA<DNAE>::_read(athena::io::YAMLDocReader& r)
|
||||
void PageObjectIdDNA<DNAE>::_read(athena::io::YAMLDocReader& r)
|
||||
{
|
||||
std::string name = r.readString(nullptr);
|
||||
if (!ObjectId::CurNameDB)
|
||||
Log.report(logvisor::Fatal, "Unable to resolve object name %s, no database present", name.c_str());
|
||||
id = ObjectId::CurNameDB->resolveIdFromName(name);
|
||||
if (!KeymapId::CurNameDB || !LayersId::CurNameDB)
|
||||
Log.report(logvisor::Fatal, "Unable to resolve keymap or layers name %s, no database present", name.c_str());
|
||||
if (name.empty())
|
||||
{
|
||||
id.id = 0xffff;
|
||||
return;
|
||||
}
|
||||
auto search = KeymapId::CurNameDB->m_stringToId.find(name);
|
||||
if (search == KeymapId::CurNameDB->m_stringToId.cend())
|
||||
{
|
||||
search = LayersId::CurNameDB->m_stringToId.find(name);
|
||||
if (search == LayersId::CurNameDB->m_stringToId.cend())
|
||||
Log.report(logvisor::Fatal, "Unable to resolve name %s", name.c_str());
|
||||
}
|
||||
id = search->second;
|
||||
}
|
||||
|
||||
template <athena::Endian DNAE>
|
||||
void ObjectIdDNA<DNAE>::_write(athena::io::YAMLDocWriter& w)
|
||||
void PageObjectIdDNA<DNAE>::_write(athena::io::YAMLDocWriter& w)
|
||||
{
|
||||
if (!ObjectId::CurNameDB)
|
||||
Log.report(logvisor::Fatal, "Unable to resolve object ID %d, no database present", id.id);
|
||||
std::string_view name = ObjectId::CurNameDB->resolveNameFromId(id);
|
||||
w.writeString(nullptr, name);
|
||||
if (!KeymapId::CurNameDB || !LayersId::CurNameDB)
|
||||
Log.report(logvisor::Fatal, "Unable to resolve keymap or layers ID %d, no database present", id.id);
|
||||
if (id.id == 0xffff)
|
||||
return;
|
||||
if (id.id & 0x8000)
|
||||
{
|
||||
std::string_view name = LayersId::CurNameDB->resolveNameFromId(id);
|
||||
w.writeString(nullptr, name);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string_view name = KeymapId::CurNameDB->resolveNameFromId(id);
|
||||
w.writeString(nullptr, name);
|
||||
}
|
||||
}
|
||||
|
||||
template <athena::Endian DNAE>
|
||||
const char* ObjectIdDNA<DNAE>::DNAType()
|
||||
const char* PageObjectIdDNA<DNAE>::DNAType()
|
||||
{
|
||||
return "amuse::ObjectId";
|
||||
}
|
||||
|
||||
template<> template<>
|
||||
void SampleIdDNA<athena::Little>::Enumerate<BigDNA::Read>(athena::io::IStreamReader& reader)
|
||||
{
|
||||
id = reader.readUint16Little();
|
||||
}
|
||||
|
||||
template<> template<>
|
||||
void SampleIdDNA<athena::Little>::Enumerate<BigDNA::Write>(athena::io::IStreamWriter& writer)
|
||||
{
|
||||
writer.writeUint16Little(id);
|
||||
}
|
||||
|
||||
template<> template<>
|
||||
void SampleIdDNA<athena::Little>::Enumerate<BigDNA::BinarySize>(size_t& sz)
|
||||
{
|
||||
sz += 2;
|
||||
}
|
||||
|
||||
template<> template<>
|
||||
void SampleIdDNA<athena::Little>::Enumerate<BigDNA::ReadYaml>(athena::io::YAMLDocReader& reader)
|
||||
{
|
||||
_read(reader);
|
||||
}
|
||||
|
||||
template<> template<>
|
||||
void SampleIdDNA<athena::Little>::Enumerate<BigDNA::WriteYaml>(athena::io::YAMLDocWriter& writer)
|
||||
{
|
||||
_write(writer);
|
||||
}
|
||||
|
||||
template<> template<>
|
||||
void SampleIdDNA<athena::Big>::Enumerate<BigDNA::Read>(athena::io::IStreamReader& reader)
|
||||
{
|
||||
id = reader.readUint16Big();
|
||||
}
|
||||
|
||||
template<> template<>
|
||||
void SampleIdDNA<athena::Big>::Enumerate<BigDNA::Write>(athena::io::IStreamWriter& writer)
|
||||
{
|
||||
writer.writeUint16Big(id);
|
||||
}
|
||||
|
||||
template<> template<>
|
||||
void SampleIdDNA<athena::Big>::Enumerate<BigDNA::BinarySize>(size_t& sz)
|
||||
{
|
||||
sz += 2;
|
||||
}
|
||||
|
||||
template<> template<>
|
||||
void SampleIdDNA<athena::Big>::Enumerate<BigDNA::ReadYaml>(athena::io::YAMLDocReader& reader)
|
||||
{
|
||||
_read(reader);
|
||||
}
|
||||
|
||||
template<> template<>
|
||||
void SampleIdDNA<athena::Big>::Enumerate<BigDNA::WriteYaml>(athena::io::YAMLDocWriter& writer)
|
||||
{
|
||||
_write(writer);
|
||||
}
|
||||
|
||||
template <athena::Endian DNAE>
|
||||
void SampleIdDNA<DNAE>::_read(athena::io::YAMLDocReader& r)
|
||||
{
|
||||
std::string name = r.readString(nullptr);
|
||||
if (!SampleId::CurNameDB)
|
||||
Log.report(logvisor::Fatal, "Unable to resolve sample name %s, no database present", name.c_str());
|
||||
id = SampleId::CurNameDB->resolveIdFromName(name);
|
||||
}
|
||||
|
||||
template <athena::Endian DNAE>
|
||||
void SampleIdDNA<DNAE>::_write(athena::io::YAMLDocWriter& w)
|
||||
{
|
||||
if (!SampleId::CurNameDB)
|
||||
Log.report(logvisor::Fatal, "Unable to resolve sample ID %d, no database present", id.id);
|
||||
std::string_view name = SampleId::CurNameDB->resolveNameFromId(id);
|
||||
w.writeString(nullptr, name);
|
||||
}
|
||||
|
||||
template <athena::Endian DNAE>
|
||||
const char* SampleIdDNA<DNAE>::DNAType()
|
||||
{
|
||||
return "amuse::SampleId";
|
||||
}
|
||||
|
||||
template<> template<>
|
||||
void SongIdDNA<athena::Little>::Enumerate<BigDNA::Read>(athena::io::IStreamReader& reader)
|
||||
{
|
||||
id = reader.readUint16Little();
|
||||
}
|
||||
|
||||
template<> template<>
|
||||
void SongIdDNA<athena::Little>::Enumerate<BigDNA::Write>(athena::io::IStreamWriter& writer)
|
||||
{
|
||||
writer.writeUint16Little(id);
|
||||
}
|
||||
|
||||
template<> template<>
|
||||
void SongIdDNA<athena::Little>::Enumerate<BigDNA::BinarySize>(size_t& sz)
|
||||
{
|
||||
sz += 2;
|
||||
}
|
||||
|
||||
template<> template<>
|
||||
void SongIdDNA<athena::Little>::Enumerate<BigDNA::ReadYaml>(athena::io::YAMLDocReader& reader)
|
||||
{
|
||||
_read(reader);
|
||||
}
|
||||
|
||||
template<> template<>
|
||||
void SongIdDNA<athena::Little>::Enumerate<BigDNA::WriteYaml>(athena::io::YAMLDocWriter& writer)
|
||||
{
|
||||
_write(writer);
|
||||
}
|
||||
|
||||
template<> template<>
|
||||
void SongIdDNA<athena::Big>::Enumerate<BigDNA::Read>(athena::io::IStreamReader& reader)
|
||||
{
|
||||
id = reader.readUint16Big();
|
||||
}
|
||||
|
||||
template<> template<>
|
||||
void SongIdDNA<athena::Big>::Enumerate<BigDNA::Write>(athena::io::IStreamWriter& writer)
|
||||
{
|
||||
writer.writeUint16Big(id);
|
||||
}
|
||||
|
||||
template<> template<>
|
||||
void SongIdDNA<athena::Big>::Enumerate<BigDNA::BinarySize>(size_t& sz)
|
||||
{
|
||||
sz += 2;
|
||||
}
|
||||
|
||||
template<> template<>
|
||||
void SongIdDNA<athena::Big>::Enumerate<BigDNA::ReadYaml>(athena::io::YAMLDocReader& reader)
|
||||
{
|
||||
_read(reader);
|
||||
}
|
||||
|
||||
template<> template<>
|
||||
void SongIdDNA<athena::Big>::Enumerate<BigDNA::WriteYaml>(athena::io::YAMLDocWriter& writer)
|
||||
{
|
||||
_write(writer);
|
||||
}
|
||||
|
||||
template <athena::Endian DNAE>
|
||||
void SongIdDNA<DNAE>::_read(athena::io::YAMLDocReader& r)
|
||||
{
|
||||
std::string name = r.readString(nullptr);
|
||||
if (!SongId::CurNameDB)
|
||||
Log.report(logvisor::Fatal, "Unable to resolve song name %s, no database present", name.c_str());
|
||||
id = SongId::CurNameDB->resolveIdFromName(name);
|
||||
}
|
||||
|
||||
template <athena::Endian DNAE>
|
||||
void SongIdDNA<DNAE>::_write(athena::io::YAMLDocWriter& w)
|
||||
{
|
||||
if (!SongId::CurNameDB)
|
||||
Log.report(logvisor::Fatal, "Unable to resolve song ID %d, no database present", id.id);
|
||||
std::string_view name = SongId::CurNameDB->resolveNameFromId(id);
|
||||
w.writeString(nullptr, name);
|
||||
}
|
||||
|
||||
template <athena::Endian DNAE>
|
||||
const char* SongIdDNA<DNAE>::DNAType()
|
||||
{
|
||||
return "amuse::SongId";
|
||||
}
|
||||
|
||||
template<> template<>
|
||||
void SFXIdDNA<athena::Little>::Enumerate<BigDNA::Read>(athena::io::IStreamReader& reader)
|
||||
{
|
||||
id = reader.readUint16Little();
|
||||
}
|
||||
|
||||
template<> template<>
|
||||
void SFXIdDNA<athena::Little>::Enumerate<BigDNA::Write>(athena::io::IStreamWriter& writer)
|
||||
{
|
||||
writer.writeUint16Little(id);
|
||||
}
|
||||
|
||||
template<> template<>
|
||||
void SFXIdDNA<athena::Little>::Enumerate<BigDNA::BinarySize>(size_t& sz)
|
||||
{
|
||||
sz += 2;
|
||||
}
|
||||
|
||||
template<> template<>
|
||||
void SFXIdDNA<athena::Little>::Enumerate<BigDNA::ReadYaml>(athena::io::YAMLDocReader& reader)
|
||||
{
|
||||
_read(reader);
|
||||
}
|
||||
|
||||
template<> template<>
|
||||
void SFXIdDNA<athena::Little>::Enumerate<BigDNA::WriteYaml>(athena::io::YAMLDocWriter& writer)
|
||||
{
|
||||
_write(writer);
|
||||
}
|
||||
|
||||
template<> template<>
|
||||
void SFXIdDNA<athena::Big>::Enumerate<BigDNA::Read>(athena::io::IStreamReader& reader)
|
||||
{
|
||||
id = reader.readUint16Big();
|
||||
}
|
||||
|
||||
template<> template<>
|
||||
void SFXIdDNA<athena::Big>::Enumerate<BigDNA::Write>(athena::io::IStreamWriter& writer)
|
||||
{
|
||||
writer.writeUint16Big(id);
|
||||
}
|
||||
|
||||
template<> template<>
|
||||
void SFXIdDNA<athena::Big>::Enumerate<BigDNA::BinarySize>(size_t& sz)
|
||||
{
|
||||
sz += 2;
|
||||
}
|
||||
|
||||
template<> template<>
|
||||
void SFXIdDNA<athena::Big>::Enumerate<BigDNA::ReadYaml>(athena::io::YAMLDocReader& reader)
|
||||
{
|
||||
_read(reader);
|
||||
}
|
||||
|
||||
template<> template<>
|
||||
void SFXIdDNA<athena::Big>::Enumerate<BigDNA::WriteYaml>(athena::io::YAMLDocWriter& writer)
|
||||
{
|
||||
_write(writer);
|
||||
}
|
||||
|
||||
template <athena::Endian DNAE>
|
||||
void SFXIdDNA<DNAE>::_read(athena::io::YAMLDocReader& r)
|
||||
{
|
||||
std::string name = r.readString(nullptr);
|
||||
if (!SFXId::CurNameDB)
|
||||
Log.report(logvisor::Fatal, "Unable to resolve song name %s, no database present", name.c_str());
|
||||
id = SFXId::CurNameDB->resolveIdFromName(name);
|
||||
}
|
||||
|
||||
template <athena::Endian DNAE>
|
||||
void SFXIdDNA<DNAE>::_write(athena::io::YAMLDocWriter& w)
|
||||
{
|
||||
if (!SFXId::CurNameDB)
|
||||
Log.report(logvisor::Fatal, "Unable to resolve song ID %d, no database present", id.id);
|
||||
std::string_view name = SFXId::CurNameDB->resolveNameFromId(id);
|
||||
w.writeString(nullptr, name);
|
||||
}
|
||||
|
||||
template <athena::Endian DNAE>
|
||||
const char* SFXIdDNA<DNAE>::DNAType()
|
||||
{
|
||||
return "amuse::SFXId";
|
||||
return "amuse::PageObjectIdDNA";
|
||||
}
|
||||
template struct PageObjectIdDNA<athena::Big>;
|
||||
template struct PageObjectIdDNA<athena::Little>;
|
||||
|
||||
ObjectId NameDB::generateId(Type tp)
|
||||
{
|
||||
uint16_t upperMatch = uint16_t(tp) << 8;
|
||||
uint16_t maxMatch = 0;
|
||||
uint16_t maxMatch = uint16_t(tp == Type::Layer ? 0x8000 : 0);
|
||||
for (const auto& p : m_idToString)
|
||||
if ((p.first & 0xff00) == upperMatch && (p.first & 0xff) >= maxMatch)
|
||||
maxMatch = (p.first & 0xff) + 1;
|
||||
return upperMatch | maxMatch;
|
||||
if (p.first >= maxMatch)
|
||||
maxMatch = p.first + 1;
|
||||
return maxMatch;
|
||||
}
|
||||
|
||||
std::string NameDB::generateName(ObjectId id)
|
||||
std::string NameDB::generateName(ObjectId id, Type tp)
|
||||
{
|
||||
Type tp = Type(id.id >> 8);
|
||||
char name[32];
|
||||
switch (tp)
|
||||
{
|
||||
case Type::SoundMacro:
|
||||
snprintf(name, 32, "macro%d", id.id & 0xff);
|
||||
snprintf(name, 32, "macro%04X", id.id);
|
||||
break;
|
||||
case Type::Table:
|
||||
snprintf(name, 32, "table%d", id.id & 0xff);
|
||||
snprintf(name, 32, "table%04X", id.id);
|
||||
break;
|
||||
case Type::Keymap:
|
||||
snprintf(name, 32, "keymap%d", id.id & 0xff);
|
||||
snprintf(name, 32, "keymap%04X", id.id);
|
||||
break;
|
||||
case Type::Layer:
|
||||
snprintf(name, 32, "layers%d", id.id & 0xff);
|
||||
snprintf(name, 32, "layers%04X", id.id);
|
||||
break;
|
||||
case Type::Song:
|
||||
snprintf(name, 32, "song%04X", id.id);
|
||||
break;
|
||||
case Type::SFX:
|
||||
snprintf(name, 32, "sfx%04X", id.id);
|
||||
break;
|
||||
case Type::Sample:
|
||||
snprintf(name, 32, "sample%04X", id.id);
|
||||
break;
|
||||
default:
|
||||
snprintf(name, 32, "obj%04X", id.id);
|
||||
|
@ -391,7 +245,7 @@ std::string_view NameDB::resolveNameFromId(ObjectId id) const
|
|||
{
|
||||
auto search = m_idToString.find(id);
|
||||
if (search == m_idToString.cend())
|
||||
Log.report(logvisor::Fatal, "Unable to resolve ID %d", id.id);
|
||||
Log.report(logvisor::Fatal, "Unable to resolve ID 0x%04X", id.id);
|
||||
return search->second;
|
||||
}
|
||||
|
||||
|
@ -403,12 +257,6 @@ ObjectId NameDB::resolveIdFromName(std::string_view str) const
|
|||
return search->second;
|
||||
}
|
||||
|
||||
template struct ObjectIdDNA<athena::Big>;
|
||||
template struct ObjectIdDNA<athena::Little>;
|
||||
|
||||
template struct SampleIdDNA<athena::Big>;
|
||||
template struct SampleIdDNA<athena::Little>;
|
||||
|
||||
template<>
|
||||
void LittleUInt24::Enumerate<LittleDNA::Read>(athena::io::IStreamReader& reader)
|
||||
{
|
||||
|
|
|
@ -307,7 +307,7 @@ std::shared_ptr<Voice> Engine::fxStart(int sfxId, float vol, float pan, std::wea
|
|||
std::list<std::shared_ptr<Voice>>::iterator ret =
|
||||
_allocateVoice(*grp, std::get<1>(search->second), NativeSampleRate, true, false, smx);
|
||||
|
||||
if (!(*ret)->loadSoundObject(entry->objId, 0, 1000.f, entry->defKey, entry->defVel, 0))
|
||||
if (!(*ret)->loadMacroObject(entry->macro.id, 0, 1000.f, entry->defKey, entry->defVel, 0))
|
||||
{
|
||||
_destroyVoice(ret);
|
||||
return {};
|
||||
|
@ -335,7 +335,7 @@ std::shared_ptr<Emitter> Engine::addEmitter(const float* pos, const float* dir,
|
|||
std::list<std::shared_ptr<Voice>>::iterator vox =
|
||||
_allocateVoice(*grp, std::get<1>(search->second), NativeSampleRate, true, true, smx);
|
||||
|
||||
if (!(*vox)->loadSoundObject(entry->objId, 0, 1000.f, entry->defKey, entry->defVel, 0))
|
||||
if (!(*vox)->loadMacroObject(entry->macro, 0, 1000.f, entry->defKey, entry->defVel, 0))
|
||||
{
|
||||
_destroyVoice(vox);
|
||||
return {};
|
||||
|
|
|
@ -247,19 +247,24 @@ std::shared_ptr<Voice> Sequencer::ChannelState::keyOn(uint8_t note, uint8_t velo
|
|||
(*ret)->installCtrlValues(m_ctrlVals);
|
||||
|
||||
ObjectId oid;
|
||||
bool res;
|
||||
if (m_parent->m_songGroup)
|
||||
{
|
||||
oid = m_page->objId;
|
||||
res = (*ret)->loadPageObject(oid, m_parent->m_ticksPerSec, note, velocity, m_ctrlVals[1]);
|
||||
}
|
||||
else if (m_parent->m_sfxMappings.size())
|
||||
{
|
||||
size_t lookupIdx = note % m_parent->m_sfxMappings.size();
|
||||
const SFXGroupIndex::SFXEntry* sfxEntry = m_parent->m_sfxMappings[lookupIdx];
|
||||
oid = sfxEntry->objId;
|
||||
oid = sfxEntry->macro;
|
||||
note = sfxEntry->defKey;
|
||||
res = (*ret)->loadMacroObject(oid, 0, m_parent->m_ticksPerSec, note, velocity, m_ctrlVals[1]);
|
||||
}
|
||||
else
|
||||
return {};
|
||||
|
||||
if (!(*ret)->loadSoundObject(oid, 0, m_parent->m_ticksPerSec, note, velocity, m_ctrlVals[1]))
|
||||
if (!res)
|
||||
{
|
||||
m_parent->m_engine._destroyVoice(ret);
|
||||
return {};
|
||||
|
|
|
@ -152,7 +152,7 @@ bool SoundMacro::CmdSplitKey::Do(SoundMacroState& st, Voice& vox) const
|
|||
if (macro.id == std::get<0>(st.m_pc.back()))
|
||||
st._setPC(macroStep);
|
||||
else
|
||||
vox.loadSoundObject(macro.id, macroStep, st.m_ticksPerSec, st.m_initKey, st.m_initVel, st.m_initMod);
|
||||
vox.loadMacroObject(macro.id, macroStep, st.m_ticksPerSec, st.m_initKey, st.m_initVel, st.m_initMod);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -166,7 +166,7 @@ bool SoundMacro::CmdSplitVel::Do(SoundMacroState& st, Voice& vox) const
|
|||
if (macro.id == std::get<0>(st.m_pc.back()))
|
||||
st._setPC(macroStep);
|
||||
else
|
||||
vox.loadSoundObject(macro.id, macroStep, st.m_ticksPerSec, st.m_initKey, st.m_initVel, st.m_initMod);
|
||||
vox.loadMacroObject(macro.id, macroStep, st.m_ticksPerSec, st.m_initKey, st.m_initVel, st.m_initMod);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -238,7 +238,7 @@ bool SoundMacro::CmdGoto::Do(SoundMacroState& st, Voice& vox) const
|
|||
if (macro.id == std::get<0>(st.m_pc.back()))
|
||||
st._setPC(macroStep);
|
||||
else
|
||||
vox.loadSoundObject(macro.id, macroStep, st.m_ticksPerSec, st.m_initKey, st.m_initVel, st.m_initMod);
|
||||
vox.loadMacroObject(macro.id, macroStep, st.m_ticksPerSec, st.m_initKey, st.m_initVel, st.m_initMod);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -312,7 +312,7 @@ bool SoundMacro::CmdSplitMod::Do(SoundMacroState& st, Voice& vox) const
|
|||
if (macro.id == std::get<0>(st.m_pc.back()))
|
||||
st._setPC(macroStep);
|
||||
else
|
||||
vox.loadSoundObject(macro.id, macroStep, st.m_ticksPerSec, st.m_initKey, st.m_initVel, st.m_initMod);
|
||||
vox.loadMacroObject(macro.id, macroStep, st.m_ticksPerSec, st.m_initKey, st.m_initVel, st.m_initMod);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -420,7 +420,7 @@ bool SoundMacro::CmdSplitRnd::Do(SoundMacroState& st, Voice& vox) const
|
|||
if (macro.id == std::get<0>(st.m_pc.back()))
|
||||
st._setPC(macroStep);
|
||||
else
|
||||
vox.loadSoundObject(macro.id, macroStep, st.m_ticksPerSec, st.m_initKey, st.m_initVel, st.m_initMod);
|
||||
vox.loadMacroObject(macro.id, macroStep, st.m_ticksPerSec, st.m_initKey, st.m_initVel, st.m_initMod);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -641,8 +641,7 @@ bool SoundMacro::CmdGoSub::Do(SoundMacroState& st, Voice& vox) const
|
|||
st.m_pc.emplace_back(std::get<0>(st.m_pc.back()), std::get<1>(st.m_pc.back()),
|
||||
std::get<1>(st.m_pc.back())->assertPC(macroStep));
|
||||
else
|
||||
vox.loadSoundObject(macro.id, macroStep, st.m_ticksPerSec, st.m_initKey, st.m_initVel, st.m_initMod, true);
|
||||
|
||||
vox.loadMacroObject(macro.id, macroStep, st.m_ticksPerSec, st.m_initKey, st.m_initVel, st.m_initMod, true);
|
||||
|
||||
vox._setObjectId(std::get<0>(st.m_pc.back()));
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@ void Voice::_macroSampleEnd()
|
|||
m_state.m_inWait = false;
|
||||
}
|
||||
else
|
||||
loadSoundObject(m_sampleEndTrap.macroId, m_sampleEndTrap.macroStep, m_state.m_ticksPerSec,
|
||||
loadMacroObject(m_sampleEndTrap.macroId, m_sampleEndTrap.macroStep, m_state.m_ticksPerSec,
|
||||
m_state.m_initKey, m_state.m_initVel, m_state.m_initMod);
|
||||
}
|
||||
else
|
||||
|
@ -734,7 +734,7 @@ std::shared_ptr<Voice> Voice::_startChildMacro(ObjectId macroId, int macroStep,
|
|||
uint8_t midiVel, uint8_t midiMod, bool pushPc)
|
||||
{
|
||||
std::list<std::shared_ptr<Voice>>::iterator vox = _allocateVoice(NativeSampleRate, true);
|
||||
if (!(*vox)->loadSoundObject(macroId, macroStep, ticksPerSec, midiKey, midiVel, midiMod, pushPc))
|
||||
if (!(*vox)->loadMacroObject(macroId, macroStep, ticksPerSec, midiKey, midiVel, midiMod, pushPc))
|
||||
{
|
||||
_destroyVoice(vox);
|
||||
return {};
|
||||
|
@ -751,9 +751,11 @@ std::shared_ptr<Voice> Voice::startChildMacro(int8_t addNote, ObjectId macroId,
|
|||
m_state.m_initMod);
|
||||
}
|
||||
|
||||
bool Voice::_loadSoundMacro(ObjectId id, const SoundMacro* macroData, int macroStep, double ticksPerSec,
|
||||
bool Voice::_loadSoundMacro(SoundMacroId id, const SoundMacro* macroData, int macroStep, double ticksPerSec,
|
||||
uint8_t midiKey, uint8_t midiVel, uint8_t midiMod, bool pushPc)
|
||||
{
|
||||
m_objectId = id;
|
||||
|
||||
if (m_state.m_pc.empty())
|
||||
m_state.initialize(id, macroData, macroStep, ticksPerSec, midiKey, midiVel, midiMod);
|
||||
else
|
||||
|
@ -768,19 +770,19 @@ bool Voice::_loadSoundMacro(ObjectId id, const SoundMacro* macroData, int macroS
|
|||
return true;
|
||||
}
|
||||
|
||||
bool Voice::_loadKeymap(ObjectId id, const Keymap* keymap, int macroStep, double ticksPerSec,
|
||||
bool Voice::_loadKeymap(const Keymap* keymap, double ticksPerSec,
|
||||
uint8_t midiKey, uint8_t midiVel, uint8_t midiMod, bool pushPc)
|
||||
{
|
||||
const Keymap& km = keymap[midiKey];
|
||||
midiKey += km.transpose;
|
||||
bool ret = loadSoundObject(id, macroStep, ticksPerSec, midiKey, midiVel, midiMod, pushPc);
|
||||
bool ret = loadMacroObject(km.macro.id, 0, ticksPerSec, midiKey, midiVel, midiMod, pushPc);
|
||||
m_curVol = 1.f;
|
||||
_setPan((km.pan - 64) / 64.f);
|
||||
_setSurroundPan(-1.f);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool Voice::_loadLayer(ObjectId id, const std::vector<LayerMapping>& layer, int macroStep, double ticksPerSec,
|
||||
bool Voice::_loadLayer(const std::vector<LayerMapping>& layer, double ticksPerSec,
|
||||
uint8_t midiKey, uint8_t midiVel, uint8_t midiMod, bool pushPc)
|
||||
{
|
||||
bool ret = false;
|
||||
|
@ -791,7 +793,7 @@ bool Voice::_loadLayer(ObjectId id, const std::vector<LayerMapping>& layer, int
|
|||
uint8_t mappingKey = midiKey + mapping.transpose;
|
||||
if (m_voxState != VoiceState::Playing)
|
||||
{
|
||||
ret |= loadSoundObject(id, macroStep, ticksPerSec, mappingKey, midiVel, midiMod, pushPc);
|
||||
ret |= loadMacroObject(mapping.macro.id, 0, ticksPerSec, mappingKey, midiVel, midiMod, pushPc);
|
||||
m_curVol = mapping.volume / 127.f;
|
||||
_setPan((mapping.pan - 64) / 64.f);
|
||||
_setSurroundPan((mapping.span - 64) / 64.f);
|
||||
|
@ -799,7 +801,7 @@ bool Voice::_loadLayer(ObjectId id, const std::vector<LayerMapping>& layer, int
|
|||
else
|
||||
{
|
||||
std::shared_ptr<Voice> vox =
|
||||
_startChildMacro(id, macroStep, ticksPerSec, mappingKey, midiVel, midiMod, pushPc);
|
||||
_startChildMacro(mapping.macro.id, 0, ticksPerSec, mappingKey, midiVel, midiMod, pushPc);
|
||||
if (vox)
|
||||
{
|
||||
vox->m_curVol = mapping.volume / 127.f;
|
||||
|
@ -813,31 +815,35 @@ bool Voice::_loadLayer(ObjectId id, const std::vector<LayerMapping>& layer, int
|
|||
return ret;
|
||||
}
|
||||
|
||||
bool Voice::loadSoundObject(ObjectId objectId, int macroStep, double ticksPerSec, uint8_t midiKey, uint8_t midiVel,
|
||||
bool Voice::loadMacroObject(SoundMacroId macroId, int macroStep, double ticksPerSec, uint8_t midiKey, uint8_t midiVel,
|
||||
uint8_t midiMod, bool pushPc)
|
||||
{
|
||||
if (m_destroyed)
|
||||
return false;
|
||||
|
||||
const SoundMacro* macroData = m_audioGroup.getPool().soundMacro(objectId);
|
||||
const SoundMacro* macroData = m_audioGroup.getPool().soundMacro(macroId);
|
||||
if (macroData)
|
||||
{
|
||||
m_objectId = objectId;
|
||||
return _loadSoundMacro(objectId, macroData, macroStep, ticksPerSec, midiKey, midiVel, midiMod, pushPc);
|
||||
}
|
||||
return _loadSoundMacro(macroId, macroData, macroStep, ticksPerSec, midiKey, midiVel, midiMod, pushPc);
|
||||
|
||||
const Keymap* keymap = m_audioGroup.getPool().keymap(objectId);
|
||||
if (keymap)
|
||||
{
|
||||
m_objectId = objectId;
|
||||
return _loadKeymap(objectId, keymap, macroStep, ticksPerSec, midiKey, midiVel, midiMod, pushPc);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const std::vector<LayerMapping>* layer = m_audioGroup.getPool().layer(objectId);
|
||||
if (layer)
|
||||
bool Voice::loadPageObject(ObjectId objectId, double ticksPerSec, uint8_t midiKey, uint8_t midiVel, uint8_t midiMod)
|
||||
{
|
||||
if (m_destroyed)
|
||||
return false;
|
||||
|
||||
if (objectId.id & 0x8000)
|
||||
{
|
||||
m_objectId = objectId;
|
||||
return _loadLayer(objectId, *layer, macroStep, ticksPerSec, midiKey, midiVel, midiMod, pushPc);
|
||||
const std::vector<LayerMapping>* layer = m_audioGroup.getPool().layer(objectId);
|
||||
if (layer)
|
||||
return _loadLayer(*layer, ticksPerSec, midiKey, midiVel, midiMod);
|
||||
}
|
||||
else
|
||||
{
|
||||
const Keymap* keymap = m_audioGroup.getPool().keymap(objectId);
|
||||
if (keymap)
|
||||
return _loadKeymap(keymap, ticksPerSec, midiKey, midiVel, midiMod);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -868,7 +874,7 @@ void Voice::keyOff()
|
|||
m_state.m_inWait = false;
|
||||
}
|
||||
else
|
||||
loadSoundObject(m_keyoffTrap.macroId, m_keyoffTrap.macroStep, m_state.m_ticksPerSec, m_state.m_initKey,
|
||||
loadMacroObject(m_keyoffTrap.macroId, m_keyoffTrap.macroStep, m_state.m_ticksPerSec, m_state.m_initKey,
|
||||
m_state.m_initVel, m_state.m_initMod);
|
||||
}
|
||||
else if (!m_curSample || m_curSample->first.m_loopLengthSamples)
|
||||
|
@ -890,7 +896,7 @@ void Voice::message(int32_t val)
|
|||
if (m_messageTrap.macroId == std::get<0>(m_state.m_pc.back()))
|
||||
std::get<2>(m_state.m_pc.back()) = std::get<1>(m_state.m_pc.back())->assertPC(m_messageTrap.macroStep);
|
||||
else
|
||||
loadSoundObject(m_messageTrap.macroId, m_messageTrap.macroStep, m_state.m_ticksPerSec, m_state.m_initKey,
|
||||
loadMacroObject(m_messageTrap.macroId, m_messageTrap.macroStep, m_state.m_ticksPerSec, m_state.m_initKey,
|
||||
m_state.m_initVel, m_state.m_initMod);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue