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_AudioGroupPool.cpp include/amuse/AudioGroupPool.hpp)
|
||||||
atdna(atdna_AudioGroupProject.cpp include/amuse/AudioGroupProject.hpp)
|
atdna(atdna_AudioGroupProject.cpp include/amuse/AudioGroupProject.hpp)
|
||||||
|
atdna(atdna_AudioGroupSampleDirectory.cpp include/amuse/AudioGroupSampleDirectory.hpp)
|
||||||
|
|
||||||
set(SOURCES
|
set(SOURCES
|
||||||
lib/AudioGroup.cpp
|
lib/AudioGroup.cpp
|
||||||
|
@ -45,7 +46,8 @@ set(SOURCES
|
||||||
lib/DSPCodec.cpp
|
lib/DSPCodec.cpp
|
||||||
lib/N64MusyXCodec.cpp
|
lib/N64MusyXCodec.cpp
|
||||||
atdna_AudioGroupPool.cpp
|
atdna_AudioGroupPool.cpp
|
||||||
atdna_AudioGroupProject.cpp)
|
atdna_AudioGroupProject.cpp
|
||||||
|
atdna_AudioGroupSampleDirectory.cpp)
|
||||||
|
|
||||||
set(HEADERS
|
set(HEADERS
|
||||||
include/amuse/AudioGroup.hpp
|
include/amuse/AudioGroup.hpp
|
||||||
|
|
|
@ -211,7 +211,6 @@ void MainWindow::importAction()
|
||||||
|
|
||||||
QFileInfo fInfo(path);
|
QFileInfo fInfo(path);
|
||||||
QString newPath = QFileInfo(fInfo.dir(), newName).filePath();
|
QString newPath = QFileInfo(fInfo.dir(), newName).filePath();
|
||||||
printf("%s\n", newPath.toUtf8().data());
|
|
||||||
if (!MkPath(fInfo.dir(), newName, this))
|
if (!MkPath(fInfo.dir(), newName, this))
|
||||||
return;
|
return;
|
||||||
if (!setProjectPath(newPath))
|
if (!setProjectPath(newPath))
|
||||||
|
@ -227,7 +226,7 @@ void MainWindow::importAction()
|
||||||
auto data = amuse::ContainerRegistry::LoadContainer(QStringToSysString(dir.filePath(fPath)).c_str());
|
auto data = amuse::ContainerRegistry::LoadContainer(QStringToSysString(dir.filePath(fPath)).c_str());
|
||||||
for (auto& p : data)
|
for (auto& p : data)
|
||||||
if (!m_projectModel->importGroupData(SysStringToQString(p.first), std::move(p.second),
|
if (!m_projectModel->importGroupData(SysStringToQString(p.first), std::move(p.second),
|
||||||
ProjectModel::ImportMode(impMode), this))
|
ProjectModel::ImportMode(impMode)))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_projectModel->saveToFile(this);
|
m_projectModel->saveToFile(this);
|
||||||
|
@ -256,7 +255,7 @@ void MainWindow::importAction()
|
||||||
auto data = amuse::ContainerRegistry::LoadContainer(QStringToSysString(path).c_str());
|
auto data = amuse::ContainerRegistry::LoadContainer(QStringToSysString(path).c_str());
|
||||||
for (auto& p : data)
|
for (auto& p : data)
|
||||||
if (!m_projectModel->importGroupData(SysStringToQString(p.first), std::move(p.second),
|
if (!m_projectModel->importGroupData(SysStringToQString(p.first), std::move(p.second),
|
||||||
ProjectModel::ImportMode(impMode), this))
|
ProjectModel::ImportMode(impMode)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_projectModel->saveToFile(this);
|
m_projectModel->saveToFile(this);
|
||||||
|
@ -328,7 +327,7 @@ void MainWindow::onFocusChanged(QWidget* old, QWidget* now)
|
||||||
if (QLineEdit* le = qobject_cast<QLineEdit*>(now))
|
if (QLineEdit* le = qobject_cast<QLineEdit*>(now))
|
||||||
{
|
{
|
||||||
m_undoConn = connect(m_ui.actionUndo, SIGNAL(triggered()), le, SLOT(undo()));
|
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_ui.actionUndo->setEnabled(le->isUndoAvailable());
|
||||||
m_redoConn = connect(m_ui.actionRedo, SIGNAL(triggered()), le, SLOT(redo()));
|
m_redoConn = connect(m_ui.actionRedo, SIGNAL(triggered()), le, SLOT(redo()));
|
||||||
m_ui.actionRedo->setEnabled(le->isRedoAvailable());
|
m_ui.actionRedo->setEnabled(le->isRedoAvailable());
|
||||||
|
|
|
@ -17,111 +17,40 @@ ProjectModel::ProjectGroup::ProjectGroup(amuse::IntrusiveAudioGroupData&& data)
|
||||||
m_sdir(amuse::AudioGroupSampleDirectory::CreateAudioGroupSampleDirectory(m_data))
|
m_sdir(amuse::AudioGroupSampleDirectory::CreateAudioGroupSampleDirectory(m_data))
|
||||||
{}
|
{}
|
||||||
|
|
||||||
bool ProjectModel::importGroupData(const QString& groupName,
|
bool ProjectModel::importGroupData(const QString& groupName, amuse::IntrusiveAudioGroupData&& data, ImportMode mode)
|
||||||
amuse::IntrusiveAudioGroupData&& data,
|
|
||||||
ImportMode mode, QWidget* parent)
|
|
||||||
{
|
{
|
||||||
amuse::SongId::CurNameDB = &m_songDb;
|
setIdDatabases();
|
||||||
amuse::SongId::CurNameDB = &m_sfxDb;
|
|
||||||
|
|
||||||
ProjectGroup& grp = m_groups.insert(std::make_pair(groupName, std::move(data))).first->second;
|
ProjectGroup& grp = m_groups.insert(std::make_pair(groupName, std::move(data))).first->second;
|
||||||
|
grp.setIdDatabases();
|
||||||
for (const auto& p : grp.m_proj.songGroups())
|
amuse::AudioGroupProject::BootstrapObjectIDs(grp.m_data);
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ProjectModel::saveToFile(QWidget* parent)
|
bool ProjectModel::saveToFile(QWidget* parent)
|
||||||
{
|
{
|
||||||
amuse::SongId::CurNameDB = &m_songDb;
|
setIdDatabases();
|
||||||
amuse::SongId::CurNameDB = &m_sfxDb;
|
|
||||||
|
|
||||||
if (!MkPath(m_dir.path(), parent))
|
if (!MkPath(m_dir.path(), parent))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
for (auto& g : m_groups)
|
for (auto& g : m_groups)
|
||||||
{
|
{
|
||||||
athena::io::YAMLDocWriter w("amuse::Group");
|
|
||||||
|
|
||||||
QDir dir(QFileInfo(m_dir, g.first).filePath());
|
QDir dir(QFileInfo(m_dir, g.first).filePath());
|
||||||
if (!MkPath(dir.path(), parent))
|
if (!MkPath(dir.path(), parent))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (auto __v = w.enterSubVector("songGroups"))
|
g.second.setIdDatabases();
|
||||||
{
|
{
|
||||||
for (const auto& p : g.second.m_proj.songGroups())
|
athena::io::FileWriter fo(QStringToSysString(dir.filePath("!project.yaml")));
|
||||||
{
|
g.second.m_proj.toYAML(fo);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (auto __v = w.enterSubVector("sfxGroups"))
|
|
||||||
{
|
{
|
||||||
for (const auto& p : g.second.m_proj.sfxGroups())
|
athena::io::FileWriter fo(QStringToSysString(dir.filePath("!pool.yaml")));
|
||||||
{
|
g.second.m_pool.toYAML(fo);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
//g.second.m_sdir.sampleEntries()
|
||||||
athena::io::FileWriter fo(QStringToSysString(dir.filePath("project.yaml")));
|
|
||||||
w.finish(&fo);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -25,8 +25,21 @@ public:
|
||||||
amuse::AudioGroupProject m_proj;
|
amuse::AudioGroupProject m_proj;
|
||||||
amuse::AudioGroupPool m_pool;
|
amuse::AudioGroupPool m_pool;
|
||||||
amuse::AudioGroupSampleDirectory m_sdir;
|
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);
|
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:
|
private:
|
||||||
|
@ -36,11 +49,16 @@ private:
|
||||||
amuse::NameDB m_sfxDb;
|
amuse::NameDB m_sfxDb;
|
||||||
std::map<QString, ProjectGroup> m_groups;
|
std::map<QString, ProjectGroup> m_groups;
|
||||||
|
|
||||||
|
void setIdDatabases()
|
||||||
|
{
|
||||||
|
amuse::SongId::CurNameDB = &m_songDb;
|
||||||
|
amuse::SFXId::CurNameDB = &m_sfxDb;
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit ProjectModel(const QString& path, QObject* parent = Q_NULLPTR);
|
explicit ProjectModel(const QString& path, QObject* parent = Q_NULLPTR);
|
||||||
|
|
||||||
bool importGroupData(const QString& groupName, amuse::IntrusiveAudioGroupData&& data,
|
bool importGroupData(const QString& groupName, amuse::IntrusiveAudioGroupData&& data, ImportMode mode);
|
||||||
ImportMode mode, QWidget* parent);
|
|
||||||
bool saveToFile(QWidget* parent);
|
bool saveToFile(QWidget* parent);
|
||||||
|
|
||||||
QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const;
|
QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const;
|
||||||
|
|
|
@ -119,8 +119,12 @@ struct SoundMacro
|
||||||
AddIVars,
|
AddIVars,
|
||||||
IfEqual = 0x70,
|
IfEqual = 0x70,
|
||||||
IfLess,
|
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 */
|
/** Base command interface. All versions of MusyX encode little-endian parameters */
|
||||||
struct ICmd : LittleDNAV
|
struct ICmd : LittleDNAV
|
||||||
{
|
{
|
||||||
|
@ -148,7 +152,7 @@ struct SoundMacro
|
||||||
AT_DECL_DNA_YAML
|
AT_DECL_DNA_YAML
|
||||||
AT_DECL_DNAV
|
AT_DECL_DNAV
|
||||||
Value<atInt8> key;
|
Value<atInt8> key;
|
||||||
ObjectIdDNA<athena::Little> macro;
|
SoundMacroIdDNA<athena::Little> macro;
|
||||||
Value<atUint16> macroStep;
|
Value<atUint16> macroStep;
|
||||||
bool Do(SoundMacroState& st, Voice& vox) const;
|
bool Do(SoundMacroState& st, Voice& vox) const;
|
||||||
CmdOp Isa() const { return CmdOp::SplitKey; }
|
CmdOp Isa() const { return CmdOp::SplitKey; }
|
||||||
|
@ -158,7 +162,7 @@ struct SoundMacro
|
||||||
AT_DECL_DNA_YAML
|
AT_DECL_DNA_YAML
|
||||||
AT_DECL_DNAV
|
AT_DECL_DNAV
|
||||||
Value<atInt8> velocity;
|
Value<atInt8> velocity;
|
||||||
ObjectIdDNA<athena::Little> macro;
|
SoundMacroIdDNA<athena::Little> macro;
|
||||||
Value<atUint16> macroStep;
|
Value<atUint16> macroStep;
|
||||||
bool Do(SoundMacroState& st, Voice& vox) const;
|
bool Do(SoundMacroState& st, Voice& vox) const;
|
||||||
CmdOp Isa() const { return CmdOp::SplitVel; }
|
CmdOp Isa() const { return CmdOp::SplitVel; }
|
||||||
|
@ -193,7 +197,7 @@ struct SoundMacro
|
||||||
AT_DECL_DNA_YAML
|
AT_DECL_DNA_YAML
|
||||||
AT_DECL_DNAV
|
AT_DECL_DNAV
|
||||||
Seek<1, athena::SeekOrigin::Current> dummy;
|
Seek<1, athena::SeekOrigin::Current> dummy;
|
||||||
ObjectIdDNA<athena::Little> macro;
|
SoundMacroIdDNA<athena::Little> macro;
|
||||||
Value<atUint16> macroStep;
|
Value<atUint16> macroStep;
|
||||||
bool Do(SoundMacroState& st, Voice& vox) const;
|
bool Do(SoundMacroState& st, Voice& vox) const;
|
||||||
CmdOp Isa() const { return CmdOp::Goto; }
|
CmdOp Isa() const { return CmdOp::Goto; }
|
||||||
|
@ -216,7 +220,7 @@ struct SoundMacro
|
||||||
AT_DECL_DNA_YAML
|
AT_DECL_DNA_YAML
|
||||||
AT_DECL_DNAV
|
AT_DECL_DNAV
|
||||||
Value<atInt8> addNote;
|
Value<atInt8> addNote;
|
||||||
ObjectIdDNA<athena::Little> macro;
|
SoundMacroIdDNA<athena::Little> macro;
|
||||||
Value<atUint16> macroStep;
|
Value<atUint16> macroStep;
|
||||||
Value<atUint8> priority;
|
Value<atUint8> priority;
|
||||||
Value<atUint8> maxVoices;
|
Value<atUint8> maxVoices;
|
||||||
|
@ -237,7 +241,7 @@ struct SoundMacro
|
||||||
AT_DECL_DNA_YAML
|
AT_DECL_DNA_YAML
|
||||||
AT_DECL_DNAV
|
AT_DECL_DNAV
|
||||||
Value<atInt8> modValue;
|
Value<atInt8> modValue;
|
||||||
ObjectIdDNA<athena::Little> macro;
|
SoundMacroIdDNA<athena::Little> macro;
|
||||||
Value<atUint16> macroStep;
|
Value<atUint16> macroStep;
|
||||||
Value<atUint8> priority;
|
Value<atUint8> priority;
|
||||||
Value<atUint8> maxVoices;
|
Value<atUint8> maxVoices;
|
||||||
|
@ -258,7 +262,7 @@ struct SoundMacro
|
||||||
{
|
{
|
||||||
AT_DECL_DNA_YAML
|
AT_DECL_DNA_YAML
|
||||||
AT_DECL_DNAV
|
AT_DECL_DNAV
|
||||||
ObjectIdDNA<athena::Little> table;
|
TableIdDNA<athena::Little> table;
|
||||||
Value<bool> dlsMode;
|
Value<bool> dlsMode;
|
||||||
bool Do(SoundMacroState& st, Voice& vox) const;
|
bool Do(SoundMacroState& st, Voice& vox) const;
|
||||||
CmdOp Isa() const { return CmdOp::SetAdsr; }
|
CmdOp Isa() const { return CmdOp::SetAdsr; }
|
||||||
|
@ -269,7 +273,7 @@ struct SoundMacro
|
||||||
AT_DECL_DNAV
|
AT_DECL_DNAV
|
||||||
Value<atInt8> scale;
|
Value<atInt8> scale;
|
||||||
Value<atInt8> add;
|
Value<atInt8> add;
|
||||||
ObjectIdDNA<athena::Little> table;
|
TableIdDNA<athena::Little> table;
|
||||||
Value<bool> originalVol;
|
Value<bool> originalVol;
|
||||||
bool Do(SoundMacroState& st, Voice& vox) const;
|
bool Do(SoundMacroState& st, Voice& vox) const;
|
||||||
CmdOp Isa() const { return CmdOp::ScaleVolume; }
|
CmdOp Isa() const { return CmdOp::ScaleVolume; }
|
||||||
|
@ -290,7 +294,7 @@ struct SoundMacro
|
||||||
AT_DECL_DNAV
|
AT_DECL_DNAV
|
||||||
Value<atInt8> scale;
|
Value<atInt8> scale;
|
||||||
Value<atInt8> add;
|
Value<atInt8> add;
|
||||||
ObjectIdDNA<athena::Little> table;
|
TableIdDNA<athena::Little> table;
|
||||||
Value<bool> msSwitch;
|
Value<bool> msSwitch;
|
||||||
Value<atUint16> fadeTime;
|
Value<atUint16> fadeTime;
|
||||||
bool Do(SoundMacroState& st, Voice& vox) const;
|
bool Do(SoundMacroState& st, Voice& vox) const;
|
||||||
|
@ -325,7 +329,7 @@ struct SoundMacro
|
||||||
AT_DECL_DNA_YAML
|
AT_DECL_DNA_YAML
|
||||||
AT_DECL_DNAV
|
AT_DECL_DNAV
|
||||||
Value<atUint8> rnd;
|
Value<atUint8> rnd;
|
||||||
ObjectIdDNA<athena::Little> macro;
|
SoundMacroIdDNA<athena::Little> macro;
|
||||||
Value<atUint16> macroStep;
|
Value<atUint16> macroStep;
|
||||||
bool Do(SoundMacroState& st, Voice& vox) const;
|
bool Do(SoundMacroState& st, Voice& vox) const;
|
||||||
CmdOp Isa() const { return CmdOp::SplitRnd; }
|
CmdOp Isa() const { return CmdOp::SplitRnd; }
|
||||||
|
@ -336,7 +340,7 @@ struct SoundMacro
|
||||||
AT_DECL_DNAV
|
AT_DECL_DNAV
|
||||||
Value<atInt8> scale;
|
Value<atInt8> scale;
|
||||||
Value<atInt8> add;
|
Value<atInt8> add;
|
||||||
ObjectIdDNA<athena::Little> table;
|
TableIdDNA<athena::Little> table;
|
||||||
Value<bool> msSwitch;
|
Value<bool> msSwitch;
|
||||||
Value<atUint16> ticksPerMs;
|
Value<atUint16> ticksPerMs;
|
||||||
bool Do(SoundMacroState& st, Voice& vox) const;
|
bool Do(SoundMacroState& st, Voice& vox) const;
|
||||||
|
@ -474,7 +478,7 @@ struct SoundMacro
|
||||||
{
|
{
|
||||||
AT_DECL_DNA_YAML
|
AT_DECL_DNA_YAML
|
||||||
AT_DECL_DNAV
|
AT_DECL_DNAV
|
||||||
ObjectIdDNA<athena::Little> table;
|
TableIdDNA<athena::Little> table;
|
||||||
Seek<1, athena::SeekOrigin::Current> seek;
|
Seek<1, athena::SeekOrigin::Current> seek;
|
||||||
Value<atInt8> keys;
|
Value<atInt8> keys;
|
||||||
Value<atInt8> cents;
|
Value<atInt8> cents;
|
||||||
|
@ -521,7 +525,7 @@ struct SoundMacro
|
||||||
AT_DECL_DNA_YAML
|
AT_DECL_DNA_YAML
|
||||||
AT_DECL_DNAV
|
AT_DECL_DNAV
|
||||||
Seek<1, athena::SeekOrigin::Current> seek;
|
Seek<1, athena::SeekOrigin::Current> seek;
|
||||||
ObjectIdDNA<athena::Little> macro;
|
SoundMacroIdDNA<athena::Little> macro;
|
||||||
Value<atUint16> macroStep;
|
Value<atUint16> macroStep;
|
||||||
bool Do(SoundMacroState& st, Voice& vox) const;
|
bool Do(SoundMacroState& st, Voice& vox) const;
|
||||||
CmdOp Isa() const { return CmdOp::GoSub; }
|
CmdOp Isa() const { return CmdOp::GoSub; }
|
||||||
|
@ -531,7 +535,7 @@ struct SoundMacro
|
||||||
AT_DECL_DNA_YAML
|
AT_DECL_DNA_YAML
|
||||||
AT_DECL_DNAV
|
AT_DECL_DNAV
|
||||||
Value<atUint8> event;
|
Value<atUint8> event;
|
||||||
ObjectIdDNA<athena::Little> macro;
|
SoundMacroIdDNA<athena::Little> macro;
|
||||||
Value<atUint16> macroStep;
|
Value<atUint16> macroStep;
|
||||||
bool Do(SoundMacroState& st, Voice& vox) const;
|
bool Do(SoundMacroState& st, Voice& vox) const;
|
||||||
CmdOp Isa() const { return CmdOp::TrapEvent; }
|
CmdOp Isa() const { return CmdOp::TrapEvent; }
|
||||||
|
@ -549,7 +553,7 @@ struct SoundMacro
|
||||||
AT_DECL_DNA_YAML
|
AT_DECL_DNA_YAML
|
||||||
AT_DECL_DNAV
|
AT_DECL_DNAV
|
||||||
Value<bool> isVar;
|
Value<bool> isVar;
|
||||||
ObjectIdDNA<athena::Little> macro;
|
SoundMacroIdDNA<athena::Little> macro;
|
||||||
Value<atUint8> vid;
|
Value<atUint8> vid;
|
||||||
Value<atUint8> variable;
|
Value<atUint8> variable;
|
||||||
bool Do(SoundMacroState& st, Voice& vox) const;
|
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
|
/** Maps individual MIDI keys to sound-entity as indexed in table
|
||||||
* (macro-voice, keymap, layer) */
|
* (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> transpose;
|
||||||
Value<atInt8> pan; /* -128 for surround-channel only */
|
Value<atInt8> pan; /* -128 for surround-channel only */
|
||||||
Value<atInt8> prioOffset;
|
Value<atInt8> prioOffset;
|
||||||
Seek<3, athena::Current> pad;
|
Seek<3, athena::Current> pad;
|
||||||
};
|
};
|
||||||
|
struct Keymap : BigDNA
|
||||||
/** Maps ranges of MIDI keys to sound-entity (macro-voice, keymap, layer) */
|
|
||||||
struct LayerMapping : LittleDNA
|
|
||||||
{
|
{
|
||||||
AT_DECL_DNA_YAML
|
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> keyLo;
|
||||||
Value<atInt8> keyHi;
|
Value<atInt8> keyHi;
|
||||||
Value<atInt8> transpose;
|
Value<atInt8> transpose;
|
||||||
|
@ -1051,6 +1087,42 @@ struct LayerMapping : LittleDNA
|
||||||
Value<atInt8> prioOffset;
|
Value<atInt8> prioOffset;
|
||||||
Value<atInt8> span;
|
Value<atInt8> span;
|
||||||
Value<atInt8> pan;
|
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 */
|
/** Database of functional objects within Audio Group */
|
||||||
|
@ -1073,6 +1145,8 @@ public:
|
||||||
const ADSR* tableAsAdsr(ObjectId id) const;
|
const ADSR* tableAsAdsr(ObjectId id) const;
|
||||||
const ADSRDLS* tableAsAdsrDLS(ObjectId id) const { return reinterpret_cast<const ADSRDLS*>(tableAsAdsr(id)); }
|
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)); }
|
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
|
PageEntryDNA : BigDNA
|
||||||
{
|
{
|
||||||
AT_DECL_DNA_YAML
|
AT_DECL_DNA_YAML
|
||||||
ObjectIdDNA<DNAEn> objId;
|
PageObjectIdDNA<DNAEn> objId;
|
||||||
Value<atUint8> priority;
|
Value<atUint8> priority;
|
||||||
Value<atUint8> maxVoices;
|
Value<atUint8> maxVoices;
|
||||||
Value<atUint8> programNo;
|
Value<atUint8> programNo;
|
||||||
|
@ -59,19 +59,20 @@ struct SongGroupIndex : AudioGroupIndex
|
||||||
struct AT_SPECIALIZE_PARMS(athena::Endian::Big, athena::Endian::Little)
|
struct AT_SPECIALIZE_PARMS(athena::Endian::Big, athena::Endian::Little)
|
||||||
MusyX1PageEntryDNA : BigDNA
|
MusyX1PageEntryDNA : BigDNA
|
||||||
{
|
{
|
||||||
AT_DECL_DNA_YAML
|
AT_DECL_DNA
|
||||||
ObjectIdDNA<DNAEn> objId;
|
PageObjectIdDNA<DNAEn> objId;
|
||||||
Value<atUint8> priority;
|
Value<atUint8> priority;
|
||||||
Value<atUint8> maxVoices;
|
Value<atUint8> maxVoices;
|
||||||
Value<atUint8> unk;
|
Value<atUint8> unk;
|
||||||
Value<atUint8> programNo;
|
Value<atUint8> programNo;
|
||||||
Seek<2, athena::Current> pad;
|
Seek<2, athena::Current> pad;
|
||||||
};
|
};
|
||||||
struct PageEntry
|
struct PageEntry : BigDNA
|
||||||
{
|
{
|
||||||
ObjectId objId;
|
AT_DECL_DNA_YAML
|
||||||
atUint8 priority;
|
PageObjectIdDNA<athena::Big> objId;
|
||||||
atUint8 maxVoices;
|
Value<atUint8> priority;
|
||||||
|
Value<atUint8> maxVoices;
|
||||||
|
|
||||||
PageEntry() = default;
|
PageEntry() = default;
|
||||||
|
|
||||||
|
@ -87,7 +88,7 @@ struct SongGroupIndex : AudioGroupIndex
|
||||||
PageEntryDNA<DNAEn> toDNA(uint8_t programNo) const
|
PageEntryDNA<DNAEn> toDNA(uint8_t programNo) const
|
||||||
{
|
{
|
||||||
PageEntryDNA<DNAEn> ret;
|
PageEntryDNA<DNAEn> ret;
|
||||||
ret.objId.id = objId;
|
ret.objId = objId;
|
||||||
ret.priority = priority;
|
ret.priority = priority;
|
||||||
ret.maxVoices = maxVoices;
|
ret.maxVoices = maxVoices;
|
||||||
ret.programNo = programNo;
|
ret.programNo = programNo;
|
||||||
|
@ -132,9 +133,9 @@ struct SFXGroupIndex : AudioGroupIndex
|
||||||
struct AT_SPECIALIZE_PARMS(athena::Endian::Big, athena::Endian::Little)
|
struct AT_SPECIALIZE_PARMS(athena::Endian::Big, athena::Endian::Little)
|
||||||
SFXEntryDNA : BigDNA
|
SFXEntryDNA : BigDNA
|
||||||
{
|
{
|
||||||
AT_DECL_DNA_YAML
|
AT_DECL_DNA
|
||||||
SFXIdDNA<DNAEn> defineId;
|
SFXIdDNA<DNAEn> sfxId;
|
||||||
ObjectIdDNA<DNAEn> objId;
|
SoundMacroIdDNA<DNAEn> macro;
|
||||||
Value<atUint8> priority;
|
Value<atUint8> priority;
|
||||||
Value<atUint8> maxVoices;
|
Value<atUint8> maxVoices;
|
||||||
Value<atUint8> defVel;
|
Value<atUint8> defVel;
|
||||||
|
@ -142,28 +143,29 @@ struct SFXGroupIndex : AudioGroupIndex
|
||||||
Value<atUint8> defKey;
|
Value<atUint8> defKey;
|
||||||
Seek<1, athena::Current> pad;
|
Seek<1, athena::Current> pad;
|
||||||
};
|
};
|
||||||
struct SFXEntry
|
struct SFXEntry : BigDNA
|
||||||
{
|
{
|
||||||
ObjectId objId;
|
AT_DECL_DNA_YAML
|
||||||
atUint8 priority;
|
SoundMacroIdDNA<athena::Big> macro;
|
||||||
atUint8 maxVoices;
|
Value<atUint8> priority;
|
||||||
atUint8 defVel;
|
Value<atUint8> maxVoices;
|
||||||
atUint8 panning;
|
Value<atUint8> defVel;
|
||||||
atUint8 defKey;
|
Value<atUint8> panning;
|
||||||
|
Value<atUint8> defKey;
|
||||||
|
|
||||||
SFXEntry() = default;
|
SFXEntry() = default;
|
||||||
|
|
||||||
template <athena::Endian DNAE>
|
template <athena::Endian DNAE>
|
||||||
SFXEntry(const SFXEntryDNA<DNAE>& in)
|
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) {}
|
defVel(in.defVel), panning(in.panning), defKey(in.defKey) {}
|
||||||
|
|
||||||
template <athena::Endian DNAEn>
|
template <athena::Endian DNAEn>
|
||||||
SFXEntryDNA<DNAEn> toDNA(SFXId defineId) const
|
SFXEntryDNA<DNAEn> toDNA(SFXId id) const
|
||||||
{
|
{
|
||||||
SFXEntryDNA<DNAEn> ret;
|
SFXEntryDNA<DNAEn> ret;
|
||||||
ret.defineId.id = defineId;
|
ret.sfxId.id = id;
|
||||||
ret.objId.id = objId;
|
ret.macro = macro;
|
||||||
ret.priority = priority;
|
ret.priority = priority;
|
||||||
ret.maxVoices = maxVoices;
|
ret.maxVoices = maxVoices;
|
||||||
ret.defVel = defVel;
|
ret.defVel = defVel;
|
||||||
|
@ -185,14 +187,21 @@ class AudioGroupProject
|
||||||
AudioGroupProject(athena::io::IStreamReader& r, GCNDataTag);
|
AudioGroupProject(athena::io::IStreamReader& r, GCNDataTag);
|
||||||
template <athena::Endian DNAE>
|
template <athena::Endian DNAE>
|
||||||
static AudioGroupProject _AudioGroupProject(athena::io::IStreamReader& r, bool absOffs);
|
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:
|
public:
|
||||||
static AudioGroupProject CreateAudioGroupProject(const AudioGroupData& data);
|
static AudioGroupProject CreateAudioGroupProject(const AudioGroupData& data);
|
||||||
|
static void BootstrapObjectIDs(const AudioGroupData& data);
|
||||||
|
|
||||||
const SongGroupIndex* getSongGroupIndex(int groupId) const;
|
const SongGroupIndex* getSongGroupIndex(int groupId) const;
|
||||||
const SFXGroupIndex* getSFXGroupIndex(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, SongGroupIndex>& songGroups() const { return m_songGroups; }
|
||||||
const std::unordered_map<int, SFXGroupIndex>& sfxGroups() const { return m_sfxGroups; }
|
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;
|
friend class AudioGroup;
|
||||||
|
|
||||||
public:
|
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
|
struct Entry
|
||||||
{
|
{
|
||||||
uint16_t m_sfxId;
|
atUint32 m_sampleOff;
|
||||||
uint32_t m_sampleOff;
|
atUint32 m_unk;
|
||||||
uint32_t m_unk;
|
atUint8 m_pitch;
|
||||||
uint8_t m_pitch;
|
atUint16 m_sampleRate;
|
||||||
uint16_t m_sampleRate;
|
atUint32 m_numSamples; // Top 8 bits is SampleFormat
|
||||||
uint32_t m_numSamples;
|
atUint32 m_loopStartSample;
|
||||||
uint32_t m_loopStartSample;
|
atUint32 m_loopLengthSamples;
|
||||||
uint32_t m_loopLengthSamples;
|
atUint32 m_adpcmParmOffset;
|
||||||
uint32_t m_adpcmParmOffset;
|
|
||||||
void swapBig();
|
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 {
|
union ADPCMParms {
|
||||||
struct DSPParms
|
struct DSPParms
|
||||||
{
|
{
|
||||||
|
@ -47,15 +134,15 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unordered_map<uint16_t, std::pair<Entry, ADPCMParms>> m_entries;
|
std::unordered_map<SFXId, std::pair<Entry, ADPCMParms>> m_entries;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AudioGroupSampleDirectory(const unsigned char* data, GCNDataTag);
|
AudioGroupSampleDirectory(athena::io::IStreamReader& r, GCNDataTag);
|
||||||
AudioGroupSampleDirectory(const unsigned char* data, const unsigned char* sampData, bool absOffs, N64DataTag);
|
AudioGroupSampleDirectory(athena::io::IStreamReader& r, const unsigned char* sampData, bool absOffs, N64DataTag);
|
||||||
AudioGroupSampleDirectory(const unsigned char* data, bool absOffs, PCDataTag);
|
AudioGroupSampleDirectory(athena::io::IStreamReader& r, bool absOffs, PCDataTag);
|
||||||
static AudioGroupSampleDirectory CreateAudioGroupSampleDirectory(const AudioGroupData& data);
|
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>;
|
using LittleDNAV = athena::io::DNAVYaml<athena::Little>;
|
||||||
|
|
||||||
/** Common ID structure statically tagging
|
/** Common ID structure statically tagging
|
||||||
* SoundMacros, Tables, Keymaps, Layers */
|
* SoundMacros, Tables, Keymaps, Layers, Samples, SFX, Songs */
|
||||||
struct ObjectId
|
struct ObjectId
|
||||||
{
|
{
|
||||||
uint16_t id = 0xffff;
|
uint16_t id = 0xffff;
|
||||||
|
@ -47,7 +47,6 @@ struct ObjectId
|
||||||
ObjectId& operator=(uint16_t idIn) { id = idIn; return *this; }
|
ObjectId& operator=(uint16_t idIn) { id = idIn; return *this; }
|
||||||
static thread_local NameDB* CurNameDB;
|
static thread_local NameDB* CurNameDB;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <athena::Endian DNAEn>
|
template <athena::Endian DNAEn>
|
||||||
struct AT_SPECIALIZE_PARMS(athena::Endian::Big, athena::Endian::Little)
|
struct AT_SPECIALIZE_PARMS(athena::Endian::Big, athena::Endian::Little)
|
||||||
ObjectIdDNA : BigDNA
|
ObjectIdDNA : BigDNA
|
||||||
|
@ -56,57 +55,52 @@ ObjectIdDNA : BigDNA
|
||||||
void _read(athena::io::YAMLDocReader& r);
|
void _read(athena::io::YAMLDocReader& r);
|
||||||
void _write(athena::io::YAMLDocWriter& w);
|
void _write(athena::io::YAMLDocWriter& w);
|
||||||
ObjectId id;
|
ObjectId id;
|
||||||
|
ObjectIdDNA() = default;
|
||||||
|
ObjectIdDNA(ObjectId idIn) : id(idIn) {}
|
||||||
|
operator ObjectId() const { return id; }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SampleId : ObjectId
|
#define DECL_ID_TYPE(type) \
|
||||||
{
|
struct type : ObjectId \
|
||||||
using ObjectId::ObjectId;
|
{ \
|
||||||
SampleId(const ObjectId& id) : ObjectId(id) {}
|
using ObjectId::ObjectId; \
|
||||||
static thread_local NameDB* CurNameDB;
|
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>
|
template <athena::Endian DNAEn>
|
||||||
struct AT_SPECIALIZE_PARMS(athena::Endian::Big, athena::Endian::Little)
|
struct AT_SPECIALIZE_PARMS(athena::Endian::Big, athena::Endian::Little)
|
||||||
SampleIdDNA : BigDNA
|
PageObjectIdDNA : BigDNA
|
||||||
{
|
{
|
||||||
AT_DECL_EXPLICIT_DNA_YAML
|
AT_DECL_EXPLICIT_DNA_YAML
|
||||||
void _read(athena::io::YAMLDocReader& r);
|
void _read(athena::io::YAMLDocReader& r);
|
||||||
void _write(athena::io::YAMLDocWriter& w);
|
void _write(athena::io::YAMLDocWriter& w);
|
||||||
SampleId id;
|
ObjectId id;
|
||||||
};
|
PageObjectIdDNA() = default;
|
||||||
|
PageObjectIdDNA(ObjectId idIn) : id(idIn) {}
|
||||||
struct SongId : ObjectId
|
operator ObjectId() const { return id; }
|
||||||
{
|
|
||||||
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;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct LittleUInt24 : LittleDNA
|
struct LittleUInt24 : LittleDNA
|
||||||
|
@ -422,30 +416,34 @@ struct N64DataTag
|
||||||
struct PCDataTag
|
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
|
namespace std
|
||||||
{
|
{
|
||||||
template<>
|
#define DECL_ID_HASH(type) \
|
||||||
struct hash<amuse::ObjectId>
|
template<> \
|
||||||
{
|
struct hash<amuse::type> \
|
||||||
size_t operator()(const amuse::ObjectId& val) const noexcept { return val.id; }
|
{ \
|
||||||
};
|
size_t operator()(const amuse::type& 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; }
|
|
||||||
};
|
};
|
||||||
|
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
|
namespace amuse
|
||||||
|
@ -454,17 +452,20 @@ struct NameDB
|
||||||
{
|
{
|
||||||
enum class Type
|
enum class Type
|
||||||
{
|
{
|
||||||
SoundMacro = 0,
|
SoundMacro,
|
||||||
Table = 1,
|
Table,
|
||||||
Keymap = 4,
|
Keymap,
|
||||||
Layer = 8
|
Layer,
|
||||||
|
Song,
|
||||||
|
SFX,
|
||||||
|
Sample
|
||||||
};
|
};
|
||||||
|
|
||||||
std::unordered_map<std::string, ObjectId> m_stringToId;
|
std::unordered_map<std::string, ObjectId> m_stringToId;
|
||||||
std::unordered_map<ObjectId, std::string> m_idToString;
|
std::unordered_map<ObjectId, std::string> m_idToString;
|
||||||
|
|
||||||
ObjectId generateId(Type tp);
|
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 registerPair(std::string_view str, ObjectId id);
|
||||||
std::string_view resolveNameFromId(ObjectId id) const;
|
std::string_view resolveNameFromId(ObjectId id) const;
|
||||||
ObjectId resolveIdFromName(std::string_view str) 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 _allocateVoice(double sampleRate, bool dynamicPitch);
|
||||||
std::list<std::shared_ptr<Voice>>::iterator _destroyVoice(std::list<std::shared_ptr<Voice>>::iterator it);
|
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);
|
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);
|
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);
|
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,
|
std::shared_ptr<Voice> _startChildMacro(ObjectId macroId, int macroStep, double ticksPerSec, uint8_t midiKey,
|
||||||
uint8_t midiVel, uint8_t midiMod, bool pushPc = false);
|
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 */
|
/** Allocate parallel macro and tie to voice for possible emitter influence */
|
||||||
std::shared_ptr<Voice> startChildMacro(int8_t addNote, ObjectId macroId, int macroStep);
|
std::shared_ptr<Voice> startChildMacro(int8_t addNote, ObjectId macroId, int macroStep);
|
||||||
|
|
||||||
/** Load specified Sound Object from within group into voice */
|
/** Load specified SoundMacro Object from within group into voice */
|
||||||
bool loadSoundObject(ObjectId objectId, int macroStep, double ticksPerSec, uint8_t midiKey, uint8_t midiVel,
|
bool loadMacroObject(SoundMacroId macroId, int macroStep, double ticksPerSec, uint8_t midiKey, uint8_t midiVel,
|
||||||
uint8_t midiMod, bool pushPc = false);
|
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 */
|
/** Signals voice to begin fade-out (or defer if sustained), eventually reaching silence */
|
||||||
void keyOff();
|
void keyOff();
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ namespace amuse
|
||||||
AudioGroup::AudioGroup(const AudioGroupData& data, GCNDataTag)
|
AudioGroup::AudioGroup(const AudioGroupData& data, GCNDataTag)
|
||||||
: m_proj(AudioGroupProject::CreateAudioGroupProject(data))
|
: m_proj(AudioGroupProject::CreateAudioGroupProject(data))
|
||||||
, m_pool(AudioGroupPool::CreateAudioGroupPool(data))
|
, m_pool(AudioGroupPool::CreateAudioGroupPool(data))
|
||||||
, m_sdir(data.getSdir(), GCNDataTag{})
|
, m_sdir(AudioGroupSampleDirectory::CreateAudioGroupSampleDirectory(data))
|
||||||
, m_samp(data.getSamp())
|
, m_samp(data.getSamp())
|
||||||
, m_fmt(DataFormat::GCN)
|
, m_fmt(DataFormat::GCN)
|
||||||
{
|
{
|
||||||
|
@ -16,7 +16,7 @@ AudioGroup::AudioGroup(const AudioGroupData& data, GCNDataTag)
|
||||||
AudioGroup::AudioGroup(const AudioGroupData& data, bool absOffs, N64DataTag)
|
AudioGroup::AudioGroup(const AudioGroupData& data, bool absOffs, N64DataTag)
|
||||||
: m_proj(AudioGroupProject::CreateAudioGroupProject(data))
|
: m_proj(AudioGroupProject::CreateAudioGroupProject(data))
|
||||||
, m_pool(AudioGroupPool::CreateAudioGroupPool(data))
|
, m_pool(AudioGroupPool::CreateAudioGroupPool(data))
|
||||||
, m_sdir(data.getSdir(), data.getSamp(), absOffs, N64DataTag{})
|
, m_sdir(AudioGroupSampleDirectory::CreateAudioGroupSampleDirectory(data))
|
||||||
, m_samp(data.getSamp())
|
, m_samp(data.getSamp())
|
||||||
, m_fmt(DataFormat::N64)
|
, m_fmt(DataFormat::N64)
|
||||||
{
|
{
|
||||||
|
@ -25,7 +25,7 @@ AudioGroup::AudioGroup(const AudioGroupData& data, bool absOffs, N64DataTag)
|
||||||
AudioGroup::AudioGroup(const AudioGroupData& data, bool absOffs, PCDataTag)
|
AudioGroup::AudioGroup(const AudioGroupData& data, bool absOffs, PCDataTag)
|
||||||
: m_proj(AudioGroupProject::CreateAudioGroupProject(data))
|
: m_proj(AudioGroupProject::CreateAudioGroupProject(data))
|
||||||
, m_pool(AudioGroupPool::CreateAudioGroupPool(data))
|
, m_pool(AudioGroupPool::CreateAudioGroupPool(data))
|
||||||
, m_sdir(data.getSdir(), absOffs, PCDataTag{})
|
, m_sdir(AudioGroupSampleDirectory::CreateAudioGroupSampleDirectory(data))
|
||||||
, m_samp(data.getSamp())
|
, m_samp(data.getSamp())
|
||||||
, m_fmt(DataFormat::PC)
|
, m_fmt(DataFormat::PC)
|
||||||
{
|
{
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
#include "athena/MemoryReader.hpp"
|
#include "athena/MemoryReader.hpp"
|
||||||
#include "logvisor/logvisor.hpp"
|
#include "logvisor/logvisor.hpp"
|
||||||
|
|
||||||
|
using namespace std::literals;
|
||||||
|
|
||||||
namespace amuse
|
namespace amuse
|
||||||
{
|
{
|
||||||
static logvisor::Module Log("amuse::AudioGroupPool");
|
static logvisor::Module Log("amuse::AudioGroupPool");
|
||||||
|
@ -75,8 +77,9 @@ AudioGroupPool AudioGroupPool::_AudioGroupPool(athena::io::IStreamReader& r)
|
||||||
ObjectHeader<DNAE> objHead;
|
ObjectHeader<DNAE> objHead;
|
||||||
atInt64 startPos = r.position();
|
atInt64 startPos = r.position();
|
||||||
objHead.read(r);
|
objHead.read(r);
|
||||||
Keymap& km = ret.m_keymaps[objHead.objectId.id];
|
KeymapDNA<DNAE> kmData;
|
||||||
km.read(r);
|
kmData.read(r);
|
||||||
|
ret.m_keymaps[objHead.objectId.id] = kmData;
|
||||||
r.seek(startPos + objHead.size, athena::Begin);
|
r.seek(startPos + objHead.size, athena::Begin);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -95,8 +98,9 @@ AudioGroupPool AudioGroupPool::_AudioGroupPool(athena::io::IStreamReader& r)
|
||||||
lm.reserve(count);
|
lm.reserve(count);
|
||||||
for (uint32_t i = 0; i < count; ++i)
|
for (uint32_t i = 0; i < count; ++i)
|
||||||
{
|
{
|
||||||
lm.emplace_back();
|
LayerMappingDNA<DNAE> lmData;
|
||||||
lm.back().read(r);
|
lmData.read(r);
|
||||||
|
lm.push_back(lmData);
|
||||||
}
|
}
|
||||||
r.seek(startPos + objHead.size, athena::Begin);
|
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());
|
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 <>
|
template <>
|
||||||
void amuse::Curve::Enumerate<LittleDNA::Read>(athena::io::IStreamReader& r)
|
void amuse::Curve::Enumerate<LittleDNA::Read>(athena::io::IStreamReader& r)
|
||||||
{
|
{
|
||||||
|
@ -368,17 +774,18 @@ void amuse::Curve::Enumerate<LittleDNA::BinarySize>(size_t& sz)
|
||||||
template <>
|
template <>
|
||||||
void amuse::Curve::Enumerate<LittleDNA::ReadYaml>(athena::io::YAMLDocReader& r)
|
void amuse::Curve::Enumerate<LittleDNA::ReadYaml>(athena::io::YAMLDocReader& r)
|
||||||
{
|
{
|
||||||
r.enumerate(nullptr, data);
|
r.enumerate("data", data);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
void amuse::Curve::Enumerate<LittleDNA::WriteYaml>(athena::io::YAMLDocWriter& w)
|
void amuse::Curve::Enumerate<LittleDNA::WriteYaml>(athena::io::YAMLDocWriter& w)
|
||||||
{
|
{
|
||||||
w.enumerate(nullptr, data);
|
w.enumerate("data", data);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* amuse::Curve::DNAType()
|
const char* amuse::Curve::DNAType()
|
||||||
{
|
{
|
||||||
return "amuse::ADSR";
|
return "amuse::ADSR";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,7 +72,7 @@ AudioGroupProject::AudioGroupProject(athena::io::IStreamReader& r, GCNDataTag)
|
||||||
{
|
{
|
||||||
SFXGroupIndex::SFXEntryDNA<athena::Big> entry;
|
SFXGroupIndex::SFXEntryDNA<athena::Big> entry;
|
||||||
entry.read(r);
|
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);
|
r.seek(header.midiSetupsOff, athena::Begin);
|
||||||
while (r.position() < header.groupEndOff)
|
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);
|
r.seek(2, athena::Current);
|
||||||
std::array<SongGroupIndex::MIDISetup, 16>& setup = idx.m_midiSetups[songId];
|
std::array<SongGroupIndex::MIDISetup, 16>& setup = idx.m_midiSetups[songId];
|
||||||
for (int i = 0; i < 16 ; ++i)
|
for (int i = 0; i < 16 ; ++i)
|
||||||
|
@ -151,7 +152,8 @@ AudioGroupProject AudioGroupProject::_AudioGroupProject(athena::io::IStreamReade
|
||||||
r.seek(subDataOff + header.midiSetupsOff, athena::Begin);
|
r.seek(subDataOff + header.midiSetupsOff, athena::Begin);
|
||||||
while (r.position() < groupBegin + header.groupEndOff)
|
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);
|
r.seek(2, athena::Current);
|
||||||
std::array<SongGroupIndex::MIDISetup, 16>& setup = idx.m_midiSetups[songId];
|
std::array<SongGroupIndex::MIDISetup, 16>& setup = idx.m_midiSetups[songId];
|
||||||
for (int i = 0; i < 16 ; ++i)
|
for (int i = 0; i < 16 ; ++i)
|
||||||
|
@ -169,7 +171,8 @@ AudioGroupProject AudioGroupProject::_AudioGroupProject(athena::io::IStreamReade
|
||||||
|
|
||||||
/* SFX entries */
|
/* SFX entries */
|
||||||
r.seek(subDataOff + header.pageTableOff, athena::Begin);
|
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);
|
r.seek(2, athena::Current);
|
||||||
idx.m_sfxEntries.reserve(count);
|
idx.m_sfxEntries.reserve(count);
|
||||||
for (int i = 0; i < count; ++i)
|
for (int i = 0; i < count; ++i)
|
||||||
|
@ -177,7 +180,7 @@ AudioGroupProject AudioGroupProject::_AudioGroupProject(athena::io::IStreamReade
|
||||||
SFXGroupIndex::SFXEntryDNA<DNAE> entry;
|
SFXGroupIndex::SFXEntryDNA<DNAE> entry;
|
||||||
entry.read(r);
|
entry.read(r);
|
||||||
r.seek(2, athena::Current);
|
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
|
const SongGroupIndex* AudioGroupProject::getSongGroupIndex(int groupId) const
|
||||||
{
|
{
|
||||||
auto search = m_songGroups.find(groupId);
|
auto search = m_songGroups.find(groupId);
|
||||||
|
@ -221,4 +412,93 @@ const SFXGroupIndex* AudioGroupProject::getSFXGroupIndex(int groupId) const
|
||||||
return nullptr;
|
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/Common.hpp"
|
||||||
#include "amuse/AudioGroupData.hpp"
|
#include "amuse/AudioGroupData.hpp"
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <athena/MemoryReader.hpp>
|
||||||
|
|
||||||
namespace amuse
|
namespace amuse
|
||||||
{
|
{
|
||||||
|
|
||||||
void AudioGroupSampleDirectory::Entry::swapBig()
|
static bool AtEnd32(athena::io::IStreamReader& r)
|
||||||
{
|
{
|
||||||
m_sfxId = SBig(m_sfxId);
|
uint32_t v = r.readUint32Big();
|
||||||
m_sampleOff = SBig(m_sampleOff);
|
r.seek(-4, athena::Current);
|
||||||
m_unk = SBig(m_unk);
|
return v == 0xffffffff;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioGroupSampleDirectory::ADPCMParms::swapBigDSP()
|
void AudioGroupSampleDirectory::ADPCMParms::swapBigDSP()
|
||||||
|
@ -37,177 +33,94 @@ void AudioGroupSampleDirectory::ADPCMParms::swapBigVADPCM()
|
||||||
allCoefs[i] = SBig(allCoefs[i]);
|
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 (!AtEnd32(r))
|
||||||
while (*reinterpret_cast<const uint32_t*>(cur) != 0xffffffff)
|
|
||||||
{
|
{
|
||||||
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)];
|
for (auto& p : m_entries)
|
||||||
store.first = *ent;
|
{
|
||||||
store.first.swapBig();
|
if (p.second.first.m_adpcmParmOffset)
|
||||||
|
|
||||||
if (store.first.m_adpcmParmOffset)
|
|
||||||
{
|
{
|
||||||
const AudioGroupSampleDirectory::ADPCMParms* adpcm =
|
r.seek(p.second.first.m_adpcmParmOffset, athena::Begin);
|
||||||
reinterpret_cast<const AudioGroupSampleDirectory::ADPCMParms*>(data + store.first.m_adpcmParmOffset);
|
r.readUBytesToBuf(&p.second.second, sizeof(ADPCMParms::DSPParms));
|
||||||
store.second.dsp = adpcm->dsp;
|
p.second.second.swapBigDSP();
|
||||||
store.second.swapBigDSP();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cur += 32;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct MusyX1SdirEntry
|
AudioGroupSampleDirectory::AudioGroupSampleDirectory(athena::io::IStreamReader& r, const unsigned char* sampData,
|
||||||
{
|
|
||||||
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,
|
|
||||||
bool absOffs, N64DataTag)
|
bool absOffs, N64DataTag)
|
||||||
{
|
{
|
||||||
const unsigned char* cur = data;
|
|
||||||
|
|
||||||
if (absOffs)
|
if (absOffs)
|
||||||
{
|
{
|
||||||
while (*reinterpret_cast<const uint32_t*>(cur) != 0xffffffff)
|
while (!AtEnd32(r))
|
||||||
{
|
{
|
||||||
MusyX1AbsSdirEntry ent = *reinterpret_cast<const MusyX1AbsSdirEntry*>(cur);
|
MusyX1AbsSdirEntry<athena::Big> ent;
|
||||||
ent.swapBig();
|
ent.read(r);
|
||||||
|
|
||||||
std::pair<Entry, ADPCMParms>& store = m_entries[ent.m_sfxId];
|
std::pair<Entry, ADPCMParms>& store = m_entries[ent.m_sfxId];
|
||||||
ent.setIntoMusyX2(store.first);
|
store.first = ent;
|
||||||
|
|
||||||
memmove(&store.second.vadpcm.m_coefs, sampData + ent.m_sampleOff, 256);
|
|
||||||
store.second.swapBigVADPCM();
|
|
||||||
|
|
||||||
cur += 28;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
while (*reinterpret_cast<const uint32_t*>(cur) != 0xffffffff)
|
while (!AtEnd32(r))
|
||||||
{
|
{
|
||||||
MusyX1SdirEntry ent = *reinterpret_cast<const MusyX1SdirEntry*>(cur);
|
MusyX1SdirEntry<athena::Big> ent;
|
||||||
ent.swapBig();
|
ent.read(r);
|
||||||
|
|
||||||
std::pair<Entry, ADPCMParms>& store = m_entries[ent.m_sfxId];
|
std::pair<Entry, ADPCMParms>& store = m_entries[ent.m_sfxId];
|
||||||
ent.setIntoMusyX2(store.first);
|
store.first = ent;
|
||||||
|
|
||||||
memmove(&store.second.vadpcm.m_coefs, sampData + ent.m_sampleOff, 256);
|
|
||||||
store.second.swapBigVADPCM();
|
|
||||||
|
|
||||||
cur += 24;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
if (absOffs)
|
||||||
{
|
{
|
||||||
while (*reinterpret_cast<const uint32_t*>(cur) != 0xffffffff)
|
while (!AtEnd32(r))
|
||||||
{
|
{
|
||||||
const MusyX1AbsSdirEntry* ent = reinterpret_cast<const MusyX1AbsSdirEntry*>(cur);
|
MusyX1AbsSdirEntry<athena::Little> ent;
|
||||||
|
ent.read(r);
|
||||||
std::pair<Entry, ADPCMParms>& store = m_entries[ent->m_sfxId];
|
std::pair<Entry, ADPCMParms>& store = m_entries[ent.m_sfxId];
|
||||||
ent->setIntoMusyX2(store.first);
|
store.first = ent;
|
||||||
|
|
||||||
cur += 28;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
while (*reinterpret_cast<const uint32_t*>(cur) != 0xffffffff)
|
while (!AtEnd32(r))
|
||||||
{
|
{
|
||||||
const MusyX1SdirEntry* ent = reinterpret_cast<const MusyX1SdirEntry*>(cur);
|
MusyX1SdirEntry<athena::Little> ent;
|
||||||
|
ent.read(r);
|
||||||
std::pair<Entry, ADPCMParms>& store = m_entries[ent->m_sfxId];
|
std::pair<Entry, ADPCMParms>& store = m_entries[ent.m_sfxId];
|
||||||
ent->setIntoMusyX2(store.first);
|
store.first = ent;
|
||||||
|
|
||||||
cur += 24;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AudioGroupSampleDirectory AudioGroupSampleDirectory::CreateAudioGroupSampleDirectory(const AudioGroupData& data)
|
AudioGroupSampleDirectory AudioGroupSampleDirectory::CreateAudioGroupSampleDirectory(const AudioGroupData& data)
|
||||||
{
|
{
|
||||||
|
athena::io::MemoryReader r(data.getSdir(), data.getSdirSize());
|
||||||
switch (data.getDataFormat())
|
switch (data.getDataFormat())
|
||||||
{
|
{
|
||||||
case DataFormat::GCN:
|
case DataFormat::GCN:
|
||||||
default:
|
default:
|
||||||
return AudioGroupSampleDirectory(data.getSdir(), GCNDataTag{});
|
return AudioGroupSampleDirectory(r, GCNDataTag{});
|
||||||
case DataFormat::N64:
|
case DataFormat::N64:
|
||||||
return AudioGroupSampleDirectory(data.getSdir(), data.getSamp(), data.getAbsoluteProjOffsets(), N64DataTag{});
|
return AudioGroupSampleDirectory(r, data.getSamp(), data.getAbsoluteProjOffsets(), N64DataTag{});
|
||||||
case DataFormat::PC:
|
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");
|
static logvisor::Module Log("amuse");
|
||||||
|
|
||||||
thread_local NameDB* ObjectId::CurNameDB = nullptr;
|
#define DEFINE_ID_TYPE(type, typeName) \
|
||||||
thread_local NameDB* SampleId::CurNameDB = nullptr;
|
thread_local NameDB* type::CurNameDB = nullptr; \
|
||||||
thread_local NameDB* SongId::CurNameDB = nullptr;
|
template<> template<> \
|
||||||
thread_local NameDB* SFXId::CurNameDB = nullptr;
|
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<>
|
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();
|
id = reader.readUint16Little();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<> template<>
|
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);
|
writer.writeUint16Little(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<> template<>
|
template<> template<>
|
||||||
void ObjectIdDNA<athena::Little>::Enumerate<BigDNA::BinarySize>(size_t& sz)
|
void PageObjectIdDNA<athena::Little>::Enumerate<BigDNA::BinarySize>(size_t& sz)
|
||||||
{
|
{
|
||||||
sz += 2;
|
sz += 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<> template<>
|
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);
|
_read(reader);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<> template<>
|
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);
|
_write(writer);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<> template<>
|
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();
|
id = reader.readUint16Big();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<> template<>
|
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);
|
writer.writeUint16Big(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<> template<>
|
template<> template<>
|
||||||
void ObjectIdDNA<athena::Big>::Enumerate<BigDNA::BinarySize>(size_t& sz)
|
void PageObjectIdDNA<athena::Big>::Enumerate<BigDNA::BinarySize>(size_t& sz)
|
||||||
{
|
{
|
||||||
sz += 2;
|
sz += 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<> template<>
|
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);
|
_read(reader);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<> template<>
|
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);
|
_write(writer);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <athena::Endian DNAE>
|
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);
|
std::string name = r.readString(nullptr);
|
||||||
if (!ObjectId::CurNameDB)
|
if (!KeymapId::CurNameDB || !LayersId::CurNameDB)
|
||||||
Log.report(logvisor::Fatal, "Unable to resolve object name %s, no database present", name.c_str());
|
Log.report(logvisor::Fatal, "Unable to resolve keymap or layers name %s, no database present", name.c_str());
|
||||||
id = ObjectId::CurNameDB->resolveIdFromName(name);
|
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>
|
template <athena::Endian DNAE>
|
||||||
void ObjectIdDNA<DNAE>::_write(athena::io::YAMLDocWriter& w)
|
void PageObjectIdDNA<DNAE>::_write(athena::io::YAMLDocWriter& w)
|
||||||
{
|
{
|
||||||
if (!ObjectId::CurNameDB)
|
if (!KeymapId::CurNameDB || !LayersId::CurNameDB)
|
||||||
Log.report(logvisor::Fatal, "Unable to resolve object ID %d, no database present", id.id);
|
Log.report(logvisor::Fatal, "Unable to resolve keymap or layers ID %d, no database present", id.id);
|
||||||
std::string_view name = ObjectId::CurNameDB->resolveNameFromId(id);
|
if (id.id == 0xffff)
|
||||||
w.writeString(nullptr, name);
|
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>
|
template <athena::Endian DNAE>
|
||||||
const char* ObjectIdDNA<DNAE>::DNAType()
|
const char* PageObjectIdDNA<DNAE>::DNAType()
|
||||||
{
|
{
|
||||||
return "amuse::ObjectId";
|
return "amuse::PageObjectIdDNA";
|
||||||
}
|
|
||||||
|
|
||||||
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";
|
|
||||||
}
|
}
|
||||||
|
template struct PageObjectIdDNA<athena::Big>;
|
||||||
|
template struct PageObjectIdDNA<athena::Little>;
|
||||||
|
|
||||||
ObjectId NameDB::generateId(Type tp)
|
ObjectId NameDB::generateId(Type tp)
|
||||||
{
|
{
|
||||||
uint16_t upperMatch = uint16_t(tp) << 8;
|
uint16_t maxMatch = uint16_t(tp == Type::Layer ? 0x8000 : 0);
|
||||||
uint16_t maxMatch = 0;
|
|
||||||
for (const auto& p : m_idToString)
|
for (const auto& p : m_idToString)
|
||||||
if ((p.first & 0xff00) == upperMatch && (p.first & 0xff) >= maxMatch)
|
if (p.first >= maxMatch)
|
||||||
maxMatch = (p.first & 0xff) + 1;
|
maxMatch = p.first + 1;
|
||||||
return upperMatch | maxMatch;
|
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];
|
char name[32];
|
||||||
switch (tp)
|
switch (tp)
|
||||||
{
|
{
|
||||||
case Type::SoundMacro:
|
case Type::SoundMacro:
|
||||||
snprintf(name, 32, "macro%d", id.id & 0xff);
|
snprintf(name, 32, "macro%04X", id.id);
|
||||||
break;
|
break;
|
||||||
case Type::Table:
|
case Type::Table:
|
||||||
snprintf(name, 32, "table%d", id.id & 0xff);
|
snprintf(name, 32, "table%04X", id.id);
|
||||||
break;
|
break;
|
||||||
case Type::Keymap:
|
case Type::Keymap:
|
||||||
snprintf(name, 32, "keymap%d", id.id & 0xff);
|
snprintf(name, 32, "keymap%04X", id.id);
|
||||||
break;
|
break;
|
||||||
case Type::Layer:
|
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;
|
break;
|
||||||
default:
|
default:
|
||||||
snprintf(name, 32, "obj%04X", id.id);
|
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);
|
auto search = m_idToString.find(id);
|
||||||
if (search == m_idToString.cend())
|
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;
|
return search->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -403,12 +257,6 @@ ObjectId NameDB::resolveIdFromName(std::string_view str) const
|
||||||
return search->second;
|
return search->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
template struct ObjectIdDNA<athena::Big>;
|
|
||||||
template struct ObjectIdDNA<athena::Little>;
|
|
||||||
|
|
||||||
template struct SampleIdDNA<athena::Big>;
|
|
||||||
template struct SampleIdDNA<athena::Little>;
|
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
void LittleUInt24::Enumerate<LittleDNA::Read>(athena::io::IStreamReader& reader)
|
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 =
|
std::list<std::shared_ptr<Voice>>::iterator ret =
|
||||||
_allocateVoice(*grp, std::get<1>(search->second), NativeSampleRate, true, false, smx);
|
_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);
|
_destroyVoice(ret);
|
||||||
return {};
|
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 =
|
std::list<std::shared_ptr<Voice>>::iterator vox =
|
||||||
_allocateVoice(*grp, std::get<1>(search->second), NativeSampleRate, true, true, smx);
|
_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);
|
_destroyVoice(vox);
|
||||||
return {};
|
return {};
|
||||||
|
|
|
@ -247,19 +247,24 @@ std::shared_ptr<Voice> Sequencer::ChannelState::keyOn(uint8_t note, uint8_t velo
|
||||||
(*ret)->installCtrlValues(m_ctrlVals);
|
(*ret)->installCtrlValues(m_ctrlVals);
|
||||||
|
|
||||||
ObjectId oid;
|
ObjectId oid;
|
||||||
|
bool res;
|
||||||
if (m_parent->m_songGroup)
|
if (m_parent->m_songGroup)
|
||||||
|
{
|
||||||
oid = m_page->objId;
|
oid = m_page->objId;
|
||||||
|
res = (*ret)->loadPageObject(oid, m_parent->m_ticksPerSec, note, velocity, m_ctrlVals[1]);
|
||||||
|
}
|
||||||
else if (m_parent->m_sfxMappings.size())
|
else if (m_parent->m_sfxMappings.size())
|
||||||
{
|
{
|
||||||
size_t lookupIdx = note % m_parent->m_sfxMappings.size();
|
size_t lookupIdx = note % m_parent->m_sfxMappings.size();
|
||||||
const SFXGroupIndex::SFXEntry* sfxEntry = m_parent->m_sfxMappings[lookupIdx];
|
const SFXGroupIndex::SFXEntry* sfxEntry = m_parent->m_sfxMappings[lookupIdx];
|
||||||
oid = sfxEntry->objId;
|
oid = sfxEntry->macro;
|
||||||
note = sfxEntry->defKey;
|
note = sfxEntry->defKey;
|
||||||
|
res = (*ret)->loadMacroObject(oid, 0, m_parent->m_ticksPerSec, note, velocity, m_ctrlVals[1]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
if (!(*ret)->loadSoundObject(oid, 0, m_parent->m_ticksPerSec, note, velocity, m_ctrlVals[1]))
|
if (!res)
|
||||||
{
|
{
|
||||||
m_parent->m_engine._destroyVoice(ret);
|
m_parent->m_engine._destroyVoice(ret);
|
||||||
return {};
|
return {};
|
||||||
|
|
|
@ -152,7 +152,7 @@ bool SoundMacro::CmdSplitKey::Do(SoundMacroState& st, Voice& vox) const
|
||||||
if (macro.id == std::get<0>(st.m_pc.back()))
|
if (macro.id == std::get<0>(st.m_pc.back()))
|
||||||
st._setPC(macroStep);
|
st._setPC(macroStep);
|
||||||
else
|
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;
|
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()))
|
if (macro.id == std::get<0>(st.m_pc.back()))
|
||||||
st._setPC(macroStep);
|
st._setPC(macroStep);
|
||||||
else
|
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;
|
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()))
|
if (macro.id == std::get<0>(st.m_pc.back()))
|
||||||
st._setPC(macroStep);
|
st._setPC(macroStep);
|
||||||
else
|
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;
|
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()))
|
if (macro.id == std::get<0>(st.m_pc.back()))
|
||||||
st._setPC(macroStep);
|
st._setPC(macroStep);
|
||||||
else
|
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;
|
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()))
|
if (macro.id == std::get<0>(st.m_pc.back()))
|
||||||
st._setPC(macroStep);
|
st._setPC(macroStep);
|
||||||
else
|
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;
|
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()),
|
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));
|
std::get<1>(st.m_pc.back())->assertPC(macroStep));
|
||||||
else
|
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()));
|
vox._setObjectId(std::get<0>(st.m_pc.back()));
|
||||||
|
|
||||||
|
|
|
@ -49,7 +49,7 @@ void Voice::_macroSampleEnd()
|
||||||
m_state.m_inWait = false;
|
m_state.m_inWait = false;
|
||||||
}
|
}
|
||||||
else
|
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);
|
m_state.m_initKey, m_state.m_initVel, m_state.m_initMod);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -734,7 +734,7 @@ std::shared_ptr<Voice> Voice::_startChildMacro(ObjectId macroId, int macroStep,
|
||||||
uint8_t midiVel, uint8_t midiMod, bool pushPc)
|
uint8_t midiVel, uint8_t midiMod, bool pushPc)
|
||||||
{
|
{
|
||||||
std::list<std::shared_ptr<Voice>>::iterator vox = _allocateVoice(NativeSampleRate, true);
|
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);
|
_destroyVoice(vox);
|
||||||
return {};
|
return {};
|
||||||
|
@ -751,9 +751,11 @@ std::shared_ptr<Voice> Voice::startChildMacro(int8_t addNote, ObjectId macroId,
|
||||||
m_state.m_initMod);
|
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)
|
uint8_t midiKey, uint8_t midiVel, uint8_t midiMod, bool pushPc)
|
||||||
{
|
{
|
||||||
|
m_objectId = id;
|
||||||
|
|
||||||
if (m_state.m_pc.empty())
|
if (m_state.m_pc.empty())
|
||||||
m_state.initialize(id, macroData, macroStep, ticksPerSec, midiKey, midiVel, midiMod);
|
m_state.initialize(id, macroData, macroStep, ticksPerSec, midiKey, midiVel, midiMod);
|
||||||
else
|
else
|
||||||
|
@ -768,19 +770,19 @@ bool Voice::_loadSoundMacro(ObjectId id, const SoundMacro* macroData, int macroS
|
||||||
return true;
|
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)
|
uint8_t midiKey, uint8_t midiVel, uint8_t midiMod, bool pushPc)
|
||||||
{
|
{
|
||||||
const Keymap& km = keymap[midiKey];
|
const Keymap& km = keymap[midiKey];
|
||||||
midiKey += km.transpose;
|
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;
|
m_curVol = 1.f;
|
||||||
_setPan((km.pan - 64) / 64.f);
|
_setPan((km.pan - 64) / 64.f);
|
||||||
_setSurroundPan(-1.f);
|
_setSurroundPan(-1.f);
|
||||||
return ret;
|
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)
|
uint8_t midiKey, uint8_t midiVel, uint8_t midiMod, bool pushPc)
|
||||||
{
|
{
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
|
@ -791,7 +793,7 @@ bool Voice::_loadLayer(ObjectId id, const std::vector<LayerMapping>& layer, int
|
||||||
uint8_t mappingKey = midiKey + mapping.transpose;
|
uint8_t mappingKey = midiKey + mapping.transpose;
|
||||||
if (m_voxState != VoiceState::Playing)
|
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;
|
m_curVol = mapping.volume / 127.f;
|
||||||
_setPan((mapping.pan - 64) / 64.f);
|
_setPan((mapping.pan - 64) / 64.f);
|
||||||
_setSurroundPan((mapping.span - 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
|
else
|
||||||
{
|
{
|
||||||
std::shared_ptr<Voice> vox =
|
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)
|
if (vox)
|
||||||
{
|
{
|
||||||
vox->m_curVol = mapping.volume / 127.f;
|
vox->m_curVol = mapping.volume / 127.f;
|
||||||
|
@ -813,31 +815,35 @@ bool Voice::_loadLayer(ObjectId id, const std::vector<LayerMapping>& layer, int
|
||||||
return ret;
|
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)
|
uint8_t midiMod, bool pushPc)
|
||||||
{
|
{
|
||||||
if (m_destroyed)
|
if (m_destroyed)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const SoundMacro* macroData = m_audioGroup.getPool().soundMacro(objectId);
|
const SoundMacro* macroData = m_audioGroup.getPool().soundMacro(macroId);
|
||||||
if (macroData)
|
if (macroData)
|
||||||
{
|
return _loadSoundMacro(macroId, macroData, macroStep, ticksPerSec, midiKey, midiVel, midiMod, pushPc);
|
||||||
m_objectId = objectId;
|
|
||||||
return _loadSoundMacro(objectId, macroData, macroStep, ticksPerSec, midiKey, midiVel, midiMod, pushPc);
|
|
||||||
}
|
|
||||||
|
|
||||||
const Keymap* keymap = m_audioGroup.getPool().keymap(objectId);
|
return false;
|
||||||
if (keymap)
|
}
|
||||||
{
|
|
||||||
m_objectId = objectId;
|
|
||||||
return _loadKeymap(objectId, keymap, macroStep, ticksPerSec, midiKey, midiVel, midiMod, pushPc);
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::vector<LayerMapping>* layer = m_audioGroup.getPool().layer(objectId);
|
bool Voice::loadPageObject(ObjectId objectId, double ticksPerSec, uint8_t midiKey, uint8_t midiVel, uint8_t midiMod)
|
||||||
if (layer)
|
{
|
||||||
|
if (m_destroyed)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (objectId.id & 0x8000)
|
||||||
{
|
{
|
||||||
m_objectId = objectId;
|
const std::vector<LayerMapping>* layer = m_audioGroup.getPool().layer(objectId);
|
||||||
return _loadLayer(objectId, *layer, macroStep, ticksPerSec, midiKey, midiVel, midiMod, pushPc);
|
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;
|
return false;
|
||||||
|
@ -868,7 +874,7 @@ void Voice::keyOff()
|
||||||
m_state.m_inWait = false;
|
m_state.m_inWait = false;
|
||||||
}
|
}
|
||||||
else
|
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);
|
m_state.m_initVel, m_state.m_initMod);
|
||||||
}
|
}
|
||||||
else if (!m_curSample || m_curSample->first.m_loopLengthSamples)
|
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()))
|
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);
|
std::get<2>(m_state.m_pc.back()) = std::get<1>(m_state.m_pc.back())->assertPC(m_messageTrap.macroStep);
|
||||||
else
|
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);
|
m_state.m_initVel, m_state.m_initMod);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue