New code style refactor

This commit is contained in:
Jack Andersen 2018-12-07 19:20:09 -10:00
parent b4c073c373
commit a7a408cc66
111 changed files with 30851 additions and 37670 deletions

View File

@ -1,5 +1,5 @@
--- ---
IndentWidth: 4 BasedOnStyle: LLVM
ColumnLimit: 120 ColumnLimit: 120
UseTab: Never UseTab: Never
--- ---
@ -8,7 +8,6 @@ DerivePointerAlignment: false
PointerAlignment: Left PointerAlignment: Left
AlignAfterOpenBracket: Align AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false AlignConsecutiveAssignments: false
BreakBeforeBraces: Allman
IndentCaseLabels: false IndentCaseLabels: false
AllowShortBlocksOnASingleLine: true AllowShortBlocksOnASingleLine: true
AlignOperands: true AlignOperands: true
@ -16,7 +15,6 @@ AlignTrailingComments: true
AlwaysBreakBeforeMultilineStrings: true AlwaysBreakBeforeMultilineStrings: true
AlwaysBreakTemplateDeclarations: true AlwaysBreakTemplateDeclarations: true
BreakConstructorInitializersBeforeComma: true BreakConstructorInitializersBeforeComma: true
BreakStringLiterals: true
AlwaysBreakAfterReturnType: None AlwaysBreakAfterReturnType: None
AlwaysBreakAfterDefinitionReturnType: None AlwaysBreakAfterDefinitionReturnType: None
AllowShortFunctionsOnASingleLine: All AllowShortFunctionsOnASingleLine: All
@ -25,6 +23,6 @@ NamespaceIndentation: None
BinPackArguments: true BinPackArguments: true
BinPackParameters: true BinPackParameters: true
SortIncludes: false SortIncludes: false
AccessModifierOffset: -4 AccessModifierOffset: -2
ConstructorInitializerIndentWidth: 0 ConstructorInitializerIndentWidth: 0
ConstructorInitializerAllOnOneLineOrOnePerLine: true ConstructorInitializerAllOnOneLineOrOnePerLine: true

View File

@ -5,30 +5,26 @@
#include <amuse/BooBackend.hpp> #include <amuse/BooBackend.hpp>
#include <boo/audiodev/IAudioVoiceEngine.hpp> #include <boo/audiodev/IAudioVoiceEngine.hpp>
@interface DataOutlineView : NSOutlineView @interface DataOutlineView : NSOutlineView {
{
@public @public
IBOutlet NSButton* removeDataButton; IBOutlet NSButton* removeDataButton;
IBOutlet NSMenuItem* deleteMenuItem; IBOutlet NSMenuItem* deleteMenuItem;
} }
@end @end
@interface SamplesTableController : NSObject <NSTableViewDataSource, NSTableViewDelegate> @interface SamplesTableController : NSObject <NSTableViewDataSource, NSTableViewDelegate> {
{
AudioGroupFilePresenter* presenter; AudioGroupFilePresenter* presenter;
} }
- (id)initWithAudioGroupPresenter:(AudioGroupFilePresenter*)present; - (id)initWithAudioGroupPresenter:(AudioGroupFilePresenter*)present;
@end @end
@interface SFXTableController : NSObject <NSTableViewDataSource, NSTableViewDelegate> @interface SFXTableController : NSObject <NSTableViewDataSource, NSTableViewDelegate> {
{
AudioGroupFilePresenter* presenter; AudioGroupFilePresenter* presenter;
} }
- (id)initWithAudioGroupPresenter:(AudioGroupFilePresenter*)present; - (id)initWithAudioGroupPresenter:(AudioGroupFilePresenter*)present;
@end @end
@interface AppDelegate : NSObject <NSApplicationDelegate, AudioGroupClient> @interface AppDelegate : NSObject <NSApplicationDelegate, AudioGroupClient> {
{
IBOutlet NSWindow* mainWindow; IBOutlet NSWindow* mainWindow;
IBOutlet NSOutlineView* dataOutline; IBOutlet NSOutlineView* dataOutline;
IBOutlet NSSearchField* dataSearchField; IBOutlet NSSearchField* dataSearchField;
@ -56,4 +52,3 @@
- (void)startSFX:(int)sfxId; - (void)startSFX:(int)sfxId;
- (void)startSample:(int)sampId; - (void)startSample:(int)sampId;
@end @end

View File

@ -19,8 +19,7 @@
- (amuse::Engine&)getAmuseEngine; - (amuse::Engine&)getAmuseEngine;
@end @end
struct AudioGroupDataCollection struct AudioGroupDataCollection {
{
std::string m_name; std::string m_name;
NSURL* m_proj; NSURL* m_proj;
NSURL* m_pool; NSURL* m_pool;
@ -35,19 +34,14 @@ struct AudioGroupDataCollection
std::vector<uint8_t> m_sdirData; std::vector<uint8_t> m_sdirData;
std::vector<uint8_t> m_sampData; std::vector<uint8_t> m_sampData;
struct MetaData struct MetaData {
{
amuse::DataFormat fmt; amuse::DataFormat fmt;
uint32_t absOffs; uint32_t absOffs;
uint32_t active; uint32_t active;
MetaData(amuse::DataFormat fmtIn, uint32_t absOffsIn, uint32_t activeIn) MetaData(amuse::DataFormat fmtIn, uint32_t absOffsIn, uint32_t activeIn)
: fmt(fmtIn), absOffs(absOffsIn), active(activeIn) : fmt(fmtIn), absOffs(absOffsIn), active(activeIn) {}
{
}
MetaData(athena::io::FileReader& r) MetaData(athena::io::FileReader& r)
: fmt(amuse::DataFormat(r.readUint32Little())), absOffs(r.readUint32Little()), active(r.readUint32Little()) : fmt(amuse::DataFormat(r.readUint32Little())), absOffs(r.readUint32Little()), active(r.readUint32Little()) {}
{
}
}; };
std::experimental::optional<MetaData> m_metaData; std::experimental::optional<MetaData> m_metaData;
@ -64,8 +58,7 @@ struct AudioGroupDataCollection
bool loadMeta(AudioGroupFilePresenter* presenter); bool loadMeta(AudioGroupFilePresenter* presenter);
AudioGroupDataCollection(std::string_view name, NSURL* proj, NSURL* pool, NSURL* sdir, NSURL* samp, NSURL* meta); AudioGroupDataCollection(std::string_view name, NSURL* proj, NSURL* pool, NSURL* sdir, NSURL* samp, NSURL* meta);
bool isDataComplete() const bool isDataComplete() const {
{
return m_projData.size() && m_poolData.size() && m_sdirData.size() && m_sampData.size() && m_metaData; return m_projData.size() && m_poolData.size() && m_sdirData.size() && m_sampData.size() && m_metaData;
} }
bool _attemptLoad(AudioGroupFilePresenter* presenter); bool _attemptLoad(AudioGroupFilePresenter* presenter);
@ -75,8 +68,7 @@ struct AudioGroupDataCollection
void disable(AudioGroupFilePresenter* presenter); void disable(AudioGroupFilePresenter* presenter);
}; };
struct AudioGroupCollection struct AudioGroupCollection {
{
NSURL* m_url; NSURL* m_url;
AudioGroupCollectionToken* m_token; AudioGroupCollectionToken* m_token;
@ -93,24 +85,21 @@ struct AudioGroupCollection
void addSamples(std::vector<AudioGroupSampleToken*>& vecOut); void addSamples(std::vector<AudioGroupSampleToken*>& vecOut);
}; };
@interface AudioGroupDataToken : NSObject @interface AudioGroupDataToken : NSObject {
{
@public @public
AudioGroupDataCollection* m_collection; AudioGroupDataCollection* m_collection;
} }
- (id)initWithDataCollection:(AudioGroupDataCollection*)collection; - (id)initWithDataCollection:(AudioGroupDataCollection*)collection;
@end @end
@interface AudioGroupCollectionToken : NSObject @interface AudioGroupCollectionToken : NSObject {
{
@public @public
AudioGroupCollection* m_collection; AudioGroupCollection* m_collection;
} }
- (id)initWithCollection:(AudioGroupCollection*)collection; - (id)initWithCollection:(AudioGroupCollection*)collection;
@end @end
@interface AudioGroupSFXToken : NSObject @interface AudioGroupSFXToken : NSObject {
{
@public @public
NSAttributedString* m_name; NSAttributedString* m_name;
int m_loadId; int m_loadId;
@ -119,20 +108,17 @@ struct AudioGroupCollection
- (id)initWithName:(NSAttributedString*)name loadId:(int)loadId sfx:(const amuse::SFXGroupIndex::SFXEntry*)sfx; - (id)initWithName:(NSAttributedString*)name loadId:(int)loadId sfx:(const amuse::SFXGroupIndex::SFXEntry*)sfx;
@end @end
@interface AudioGroupSampleToken : NSObject @interface AudioGroupSampleToken : NSObject {
{
@public @public
NSAttributedString* m_name; NSAttributedString* m_name;
const std::pair<amuse::AudioGroupSampleDirectory::Entry, amuse::AudioGroupSampleDirectory::ADPCMParms>* m_sample; const std::pair<amuse::AudioGroupSampleDirectory::Entry, amuse::AudioGroupSampleDirectory::ADPCMParms>* m_sample;
} }
- (id) - (id)initWithName:(NSAttributedString*)name
initWithName:(NSAttributedString*)name samp:(const std::pair<amuse::AudioGroupSampleDirectory::Entry,
samp:(const std::pair<amuse::AudioGroupSampleDirectory::Entry, amuse::AudioGroupSampleDirectory::ADPCMParms>*) amuse::AudioGroupSampleDirectory::ADPCMParms>*)sample;
sample;
@end @end
@interface AudioGroupToken : NSObject @interface AudioGroupToken : NSObject {
{
@public @public
NSString* m_name; NSString* m_name;
int m_id; int m_id;
@ -143,8 +129,7 @@ initWithName:(NSAttributedString*)name
- (id)initWithName:(NSString*)name id:(int)gid sfxGroup:(const amuse::SFXGroupIndex*)group; - (id)initWithName:(NSString*)name id:(int)gid sfxGroup:(const amuse::SFXGroupIndex*)group;
@end @end
@interface AudioGroupFilePresenter : NSObject <NSFilePresenter, NSOutlineViewDataSource, NSOutlineViewDelegate> @interface AudioGroupFilePresenter : NSObject <NSFilePresenter, NSOutlineViewDataSource, NSOutlineViewDelegate> {
{
@public @public
id<AudioGroupClient> m_audioGroupClient; id<AudioGroupClient> m_audioGroupClient;
NSURL* m_groupURL; NSURL* m_groupURL;
@ -164,4 +149,3 @@ initWithName:(NSAttributedString*)name
- (void)setSearchFilter:(NSString*)str; - (void)setSearchFilter:(NSString*)str;
- (void)removeSelectedItem; - (void)removeSelectedItem;
@end @end

View File

@ -19,21 +19,18 @@
@class AudioUnitViewController; @class AudioUnitViewController;
namespace amuse namespace amuse {
{
/** Backend voice allocator implementation for AudioUnit mixer */ /** Backend voice allocator implementation for AudioUnit mixer */
class AudioUnitBackendVoiceAllocator : public BooBackendVoiceAllocator class AudioUnitBackendVoiceAllocator : public BooBackendVoiceAllocator {
{
public: public:
AudioUnitBackendVoiceAllocator(boo::IAudioVoiceEngine& booEngine) : BooBackendVoiceAllocator(booEngine) {} AudioUnitBackendVoiceAllocator(boo::IAudioVoiceEngine& booEngine) : BooBackendVoiceAllocator(booEngine) {}
}; };
void RegisterAudioUnit(); void RegisterAudioUnit();
} } // namespace amuse
@interface AmuseAudioUnit : AUAudioUnit <AudioGroupClient> @interface AmuseAudioUnit : AUAudioUnit <AudioGroupClient> {
{
@public @public
AudioUnitViewController* m_viewController; AudioUnitViewController* m_viewController;
std::unique_ptr<boo::IAudioVoiceEngine> m_booBackend; std::unique_ptr<boo::IAudioVoiceEngine> m_booBackend;

View File

@ -5,19 +5,16 @@
@class AmuseAudioUnit; @class AmuseAudioUnit;
@interface GroupBrowserDelegate : NSObject <NSBrowserDelegate> @interface GroupBrowserDelegate : NSObject <NSBrowserDelegate> {
{
AmuseAudioUnit* m_audioUnit; AmuseAudioUnit* m_audioUnit;
} }
- (id)initWithAudioUnit:(AmuseAudioUnit*)au; - (id)initWithAudioUnit:(AmuseAudioUnit*)au;
@end @end
@interface AudioUnitViewController : AUViewController <AUAudioUnitFactory> @interface AudioUnitViewController : AUViewController <AUAudioUnitFactory> {
{
@public @public
AmuseAudioUnit* m_audioUnit; AmuseAudioUnit* m_audioUnit;
IBOutlet NSBrowser* m_groupBrowser; IBOutlet NSBrowser* m_groupBrowser;
GroupBrowserDelegate* m_groupBrowserDelegate; GroupBrowserDelegate* m_groupBrowserDelegate;
} }
@end @end

File diff suppressed because it is too large Load Diff

View File

@ -10,9 +10,8 @@
class ADSREditor; class ADSREditor;
class ADSRView : public QWidget class ADSRView : public QWidget {
{ Q_OBJECT
Q_OBJECT
friend class ADSRControls; friend class ADSRControls;
amuse::ObjToken<ProjectModel::ADSRNode> m_node; amuse::ObjToken<ProjectModel::ADSRNode> m_node;
QFont m_gridFont; QFont m_gridFont;
@ -21,6 +20,7 @@ Q_OBJECT
int m_dragPoint = -1; int m_dragPoint = -1;
uint64_t m_cycleIdx = 0; uint64_t m_cycleIdx = 0;
ADSREditor* getEditor() const; ADSREditor* getEditor() const;
public: public:
explicit ADSRView(QWidget* parent = Q_NULLPTR); explicit ADSRView(QWidget* parent = Q_NULLPTR);
void loadData(ProjectModel::ADSRNode* node); void loadData(ProjectModel::ADSRNode* node);
@ -33,9 +33,8 @@ public:
void mouseMoveEvent(QMouseEvent* ev); void mouseMoveEvent(QMouseEvent* ev);
}; };
class ADSRControls : public QFrame class ADSRControls : public QFrame {
{ Q_OBJECT
Q_OBJECT
friend class ADSRView; friend class ADSRView;
QDoubleSpinBox* m_attack; QDoubleSpinBox* m_attack;
QDoubleSpinBox* m_decay; QDoubleSpinBox* m_decay;
@ -51,6 +50,7 @@ Q_OBJECT
void setAttackAndDecay(double attack, double decay, uint64_t cycleCount); void setAttackAndDecay(double attack, double decay, uint64_t cycleCount);
void setDecayAndSustain(double decay, double sustain, uint64_t cycleCount); void setDecayAndSustain(double decay, double sustain, uint64_t cycleCount);
void setRelease(double release, uint64_t cycleCount); void setRelease(double release, uint64_t cycleCount);
public: public:
explicit ADSRControls(QWidget* parent = Q_NULLPTR); explicit ADSRControls(QWidget* parent = Q_NULLPTR);
void loadData(); void loadData();
@ -65,18 +65,16 @@ public slots:
void keyToDecayChanged(double val); void keyToDecayChanged(double val);
}; };
class ADSREditor : public EditorWidget class ADSREditor : public EditorWidget {
{ Q_OBJECT
Q_OBJECT
friend class ADSRView; friend class ADSRView;
friend class ADSRControls; friend class ADSRControls;
ADSRView* m_adsrView; ADSRView* m_adsrView;
ADSRControls* m_controls; ADSRControls* m_controls;
public: public:
explicit ADSREditor(QWidget* parent = Q_NULLPTR); explicit ADSREditor(QWidget* parent = Q_NULLPTR);
bool loadData(ProjectModel::ADSRNode* node); bool loadData(ProjectModel::ADSRNode* node);
void unloadData(); void unloadData();
ProjectModel::INode* currentNode() const; ProjectModel::INode* currentNode() const;
}; };

View File

@ -4,8 +4,7 @@
#include <QObject> #include <QObject>
#include <QProcess> #include <QProcess>
boo::SystemString QStringToSysString(const QString& str) boo::SystemString QStringToSysString(const QString& str) {
{
#ifdef _WIN32 #ifdef _WIN32
return (wchar_t*)str.utf16(); return (wchar_t*)str.utf16();
#else #else
@ -13,8 +12,7 @@ boo::SystemString QStringToSysString(const QString& str)
#endif #endif
} }
QString SysStringToQString(const boo::SystemString& str) QString SysStringToQString(const boo::SystemString& str) {
{
#ifdef _WIN32 #ifdef _WIN32
return QString::fromStdWString(str); return QString::fromStdWString(str);
#else #else
@ -22,16 +20,13 @@ QString SysStringToQString(const boo::SystemString& str)
#endif #endif
} }
bool MkPath(const QString& path, UIMessenger& messenger) bool MkPath(const QString& path, UIMessenger& messenger) {
{
QFileInfo fInfo(path); QFileInfo fInfo(path);
return MkPath(fInfo.dir(), fInfo.fileName(), messenger); return MkPath(fInfo.dir(), fInfo.fileName(), messenger);
} }
bool MkPath(const QDir& dir, const QString& file, UIMessenger& messenger) bool MkPath(const QDir& dir, const QString& file, UIMessenger& messenger) {
{ if (!dir.mkpath(file)) {
if (!dir.mkpath(file))
{
QString msg = QString(MainWindow::tr("A directory at '%1/%2' could not be created.")).arg(dir.path()).arg(file); QString msg = QString(MainWindow::tr("A directory at '%1/%2' could not be created.")).arg(dir.path()).arg(file);
messenger.critical(MainWindow::tr("Unable to create directory"), msg); messenger.critical(MainWindow::tr("Unable to create directory"), msg);
return false; return false;
@ -39,25 +34,21 @@ bool MkPath(const QDir& dir, const QString& file, UIMessenger& messenger)
return true; return true;
} }
void ShowInGraphicalShell(QWidget* parent, const QString& pathIn) void ShowInGraphicalShell(QWidget* parent, const QString& pathIn) {
{
const QFileInfo fileInfo(pathIn); const QFileInfo fileInfo(pathIn);
// Mac, Windows support folder or file. // Mac, Windows support folder or file.
#if defined(Q_OS_WIN) #if defined(Q_OS_WIN)
QString paths = QProcessEnvironment::systemEnvironment().value(QStringLiteral("Path")); QString paths = QProcessEnvironment::systemEnvironment().value(QStringLiteral("Path"));
QString explorer; QString explorer;
for (QString path : paths.split(QStringLiteral(";"))) for (QString path : paths.split(QStringLiteral(";"))) {
{
QFileInfo finfo(QDir(path), QStringLiteral("explorer.exe")); QFileInfo finfo(QDir(path), QStringLiteral("explorer.exe"));
if (finfo.exists()) if (finfo.exists()) {
{
explorer = finfo.filePath(); explorer = finfo.filePath();
break; break;
} }
} }
if (explorer.isEmpty()) { if (explorer.isEmpty()) {
QMessageBox::warning(parent, QMessageBox::warning(parent, MainWindow::tr("Launching Windows Explorer Failed"),
MainWindow::tr("Launching Windows Explorer Failed"),
MainWindow::tr("Could not find explorer.exe in path to launch Windows Explorer.")); MainWindow::tr("Could not find explorer.exe in path to launch Windows Explorer."));
return; return;
} }
@ -73,8 +64,7 @@ void ShowInGraphicalShell(QWidget* parent, const QString& pathIn)
.arg(fileInfo.canonicalFilePath()); .arg(fileInfo.canonicalFilePath());
QProcess::execute(QLatin1String("/usr/bin/osascript"), scriptArgs); QProcess::execute(QLatin1String("/usr/bin/osascript"), scriptArgs);
scriptArgs.clear(); scriptArgs.clear();
scriptArgs << QLatin1String("-e") scriptArgs << QLatin1String("-e") << QLatin1String("tell application \"Finder\" to activate");
<< QLatin1String("tell application \"Finder\" to activate");
QProcess::execute(QLatin1String("/usr/bin/osascript"), scriptArgs); QProcess::execute(QLatin1String("/usr/bin/osascript"), scriptArgs);
#else #else
// we cannot select a file here, because no file browser really supports it... // we cannot select a file here, because no file browser really supports it...
@ -85,8 +75,7 @@ void ShowInGraphicalShell(QWidget* parent, const QString& pathIn)
#endif #endif
} }
QString ShowInGraphicalShellString() QString ShowInGraphicalShellString() {
{
#if defined(Q_OS_WIN) #if defined(Q_OS_WIN)
return MainWindow::tr("Show in Explorer"); return MainWindow::tr("Show in Explorer");
#elif defined(Q_OS_MAC) #elif defined(Q_OS_MAC)
@ -96,8 +85,7 @@ QString ShowInGraphicalShellString()
#endif #endif
} }
QTransform RectToRect(const QRectF& from, const QRectF& to) QTransform RectToRect(const QRectF& from, const QRectF& to) {
{
QPolygonF orig(from); QPolygonF orig(from);
orig.pop_back(); orig.pop_back();
QPolygonF resize(to); QPolygonF resize(to);

View File

@ -8,31 +8,26 @@
class MainWindow; class MainWindow;
extern MainWindow* g_MainWindow; extern MainWindow* g_MainWindow;
class UIMessenger : public QObject class UIMessenger : public QObject {
{
Q_OBJECT Q_OBJECT
public: public:
using QObject::QObject; using QObject::QObject;
signals: signals:
QMessageBox::StandardButton information(const QString &title, QMessageBox::StandardButton information(const QString& title, const QString& text,
const QString &text, QMessageBox::StandardButtons buttons = QMessageBox::Ok, QMessageBox::StandardButtons buttons = QMessageBox::Ok,
QMessageBox::StandardButton defaultButton = QMessageBox::NoButton); QMessageBox::StandardButton defaultButton = QMessageBox::NoButton);
int question(const QString &title, int question(const QString& title, const QString& text, const QString& button0Text,
const QString& text, const QString& button1Text = QString(), const QString& button2Text = QString(),
const QString& button0Text, int defaultButtonNumber = 0, int escapeButtonNumber = -1);
const QString& button1Text = QString(), QMessageBox::StandardButton
const QString& button2Text = QString(), question(const QString& title, const QString& text,
int defaultButtonNumber = 0, QMessageBox::StandardButtons buttons = QMessageBox::StandardButtons(QMessageBox::Yes | QMessageBox::No),
int escapeButtonNumber = -1);
QMessageBox::StandardButton question(const QString &title,
const QString &text, QMessageBox::StandardButtons buttons =
QMessageBox::StandardButtons(QMessageBox::Yes | QMessageBox::No),
QMessageBox::StandardButton defaultButton = QMessageBox::NoButton); QMessageBox::StandardButton defaultButton = QMessageBox::NoButton);
QMessageBox::StandardButton warning(const QString &title, QMessageBox::StandardButton warning(const QString& title, const QString& text,
const QString &text, QMessageBox::StandardButtons buttons = QMessageBox::Ok, QMessageBox::StandardButtons buttons = QMessageBox::Ok,
QMessageBox::StandardButton defaultButton = QMessageBox::NoButton); QMessageBox::StandardButton defaultButton = QMessageBox::NoButton);
QMessageBox::StandardButton critical(const QString &title, QMessageBox::StandardButton critical(const QString& title, const QString& text,
const QString &text, QMessageBox::StandardButtons buttons = QMessageBox::Ok, QMessageBox::StandardButtons buttons = QMessageBox::Ok,
QMessageBox::StandardButton defaultButton = QMessageBox::NoButton); QMessageBox::StandardButton defaultButton = QMessageBox::NoButton);
}; };
@ -45,22 +40,14 @@ bool MkPath(const QDir& dir, const QString& file, UIMessenger& messenger);
void ShowInGraphicalShell(QWidget* parent, const QString& pathIn); void ShowInGraphicalShell(QWidget* parent, const QString& pathIn);
QString ShowInGraphicalShellString(); QString ShowInGraphicalShellString();
static QLatin1String StringViewToQString(std::string_view sv) static QLatin1String StringViewToQString(std::string_view sv) { return QLatin1String(sv.data(), int(sv.size())); }
{
return QLatin1String(sv.data(), int(sv.size()));
}
/* Used for generating transform matrices to map SVG coordinate space */ /* Used for generating transform matrices to map SVG coordinate space */
QTransform RectToRect(const QRectF& from, const QRectF& to); QTransform RectToRect(const QRectF& from, const QRectF& to);
namespace std namespace std {
{ template <>
template<> struct hash<QString> struct hash<QString> {
{ std::size_t operator()(const QString& s) const noexcept { return qHash(s); }
std::size_t operator()(const QString& s) const noexcept
{
return qHash(s);
}
}; };
} } // namespace std

View File

@ -6,36 +6,30 @@
#include <QMouseEvent> #include <QMouseEvent>
#include <QJSValueIterator> #include <QJSValueIterator>
class CurveEditUndoCommand : public EditorUndoCommand class CurveEditUndoCommand : public EditorUndoCommand {
{
uint8_t m_redoData[128]; uint8_t m_redoData[128];
uint8_t m_undoData[128]; uint8_t m_undoData[128];
bool m_usedExpr; bool m_usedExpr;
bool m_undid = false; bool m_undid = false;
public: public:
CurveEditUndoCommand(const uint8_t* redoData, bool usedExpr, CurveEditUndoCommand(const uint8_t* redoData, bool usedExpr, amuse::ObjToken<ProjectModel::CurveNode> node)
amuse::ObjToken<ProjectModel::CurveNode> node) : EditorUndoCommand(node.get(), CurveControls::tr("Edit Curve")), m_usedExpr(usedExpr) {
: EditorUndoCommand(node.get(), CurveControls::tr("Edit Curve")), m_usedExpr(usedExpr)
{
std::memcpy(m_redoData, redoData, 128); std::memcpy(m_redoData, redoData, 128);
} }
void undo() void undo() {
{
m_undid = true; m_undid = true;
amuse::ITable& table = **m_node.cast<ProjectModel::CurveNode>()->m_obj; amuse::ITable& table = **m_node.cast<ProjectModel::CurveNode>()->m_obj;
if (table.Isa() == amuse::ITable::Type::Curve) if (table.Isa() == amuse::ITable::Type::Curve) {
{
amuse::Curve& curve = static_cast<amuse::Curve&>(table); amuse::Curve& curve = static_cast<amuse::Curve&>(table);
curve.data.resize(128); curve.data.resize(128);
std::memcpy(curve.data.data(), m_undoData, 128); std::memcpy(curve.data.data(), m_undoData, 128);
} }
EditorUndoCommand::undo(); EditorUndoCommand::undo();
} }
void redo() void redo() {
{
amuse::ITable& table = **m_node.cast<ProjectModel::CurveNode>()->m_obj; amuse::ITable& table = **m_node.cast<ProjectModel::CurveNode>()->m_obj;
if (table.Isa() == amuse::ITable::Type::Curve) if (table.Isa() == amuse::ITable::Type::Curve) {
{
amuse::Curve& curve = static_cast<amuse::Curve&>(table); amuse::Curve& curve = static_cast<amuse::Curve&>(table);
curve.data.resize(128); curve.data.resize(128);
std::memcpy(m_undoData, curve.data.data(), 128); std::memcpy(m_undoData, curve.data.data(), 128);
@ -44,10 +38,8 @@ public:
if (m_undid) if (m_undid)
EditorUndoCommand::redo(); EditorUndoCommand::redo();
} }
bool mergeWith(const QUndoCommand* other) bool mergeWith(const QUndoCommand* other) {
{ if (other->id() == id() && !m_usedExpr && !static_cast<const CurveEditUndoCommand*>(other)->m_usedExpr) {
if (other->id() == id() && !m_usedExpr && !static_cast<const CurveEditUndoCommand*>(other)->m_usedExpr)
{
std::memcpy(m_redoData, static_cast<const CurveEditUndoCommand*>(other)->m_redoData, 128); std::memcpy(m_redoData, static_cast<const CurveEditUndoCommand*>(other)->m_redoData, 128);
return true; return true;
} }
@ -56,28 +48,15 @@ public:
int id() const { return int(Id::CurveEdit); } int id() const { return int(Id::CurveEdit); }
}; };
CurveEditor* CurveView::getEditor() const CurveEditor* CurveView::getEditor() const { return qobject_cast<CurveEditor*>(parentWidget()); }
{
return qobject_cast<CurveEditor*>(parentWidget());
}
void CurveView::loadData(ProjectModel::CurveNode* node) void CurveView::loadData(ProjectModel::CurveNode* node) { m_node = node; }
{
m_node = node;
}
void CurveView::unloadData() void CurveView::unloadData() { m_node.reset(); }
{
m_node.reset();
}
ProjectModel::INode* CurveView::currentNode() const ProjectModel::INode* CurveView::currentNode() const { return m_node.get(); }
{
return m_node.get();
}
void CurveView::paintEvent(QPaintEvent* ev) void CurveView::paintEvent(QPaintEvent* ev) {
{
if (!m_node) if (!m_node)
return; return;
amuse::ITable& table = **m_node->m_obj; amuse::ITable& table = **m_node->m_obj;
@ -94,8 +73,7 @@ void CurveView::paintEvent(QPaintEvent* ev)
painter.setPen(QPen(QColor(127, 127, 127), penWidth)); painter.setPen(QPen(QColor(127, 127, 127), penWidth));
painter.setFont(m_gridFont); painter.setFont(m_gridFont);
qreal yIncrement = (height() - 16.0) / 10.0; qreal yIncrement = (height() - 16.0) / 10.0;
for (int i = 0; i < 11; ++i) for (int i = 0; i < 11; ++i) {
{
qreal thisY = i * yIncrement; qreal thisY = i * yIncrement;
qreal textY = thisY - (i == 0 ? 2.0 : (i == 10 ? 16.0 : 8.0)); qreal textY = thisY - (i == 0 ? 2.0 : (i == 10 ? 16.0 : 8.0));
painter.drawStaticText(QPointF(0.0, textY), m_percentTexts[i]); painter.drawStaticText(QPointF(0.0, textY), m_percentTexts[i]);
@ -103,8 +81,7 @@ void CurveView::paintEvent(QPaintEvent* ev)
} }
qreal xIncrement = (width() - 30.0) / 10.0; qreal xIncrement = (width() - 30.0) / 10.0;
for (int i = 0; i < 11; ++i) for (int i = 0; i < 11; ++i) {
{
qreal thisX = i * xIncrement + 30.0; qreal thisX = i * xIncrement + 30.0;
qreal textX = thisX - (i == 10 ? 30.0 : 15.0); qreal textX = thisX - (i == 10 ? 30.0 : 15.0);
painter.drawStaticText(QPointF(textX, height() - 16.0), m_percentTextsCenter[i]); painter.drawStaticText(QPointF(textX, height() - 16.0), m_percentTextsCenter[i]);
@ -115,15 +92,13 @@ void CurveView::paintEvent(QPaintEvent* ev)
xIncrement = (width() - 30.0) / 127.0; xIncrement = (width() - 30.0) / 127.0;
QPointF lastPt; QPointF lastPt;
painter.setPen(QPen(Qt::white, penWidth * 3.0)); painter.setPen(QPen(Qt::white, penWidth * 3.0));
for (i = 0; i < curve.data.size(); ++i) for (i = 0; i < curve.data.size(); ++i) {
{
QPointF thisPt(i * xIncrement + 30.0, (height() - 16.0) - (height() - 16.0) * (curve.data[i] / 127.0)); QPointF thisPt(i * xIncrement + 30.0, (height() - 16.0) - (height() - 16.0) * (curve.data[i] / 127.0));
if (i) if (i)
painter.drawLine(lastPt, thisPt); painter.drawLine(lastPt, thisPt);
lastPt = thisPt; lastPt = thisPt;
} }
for (; i < 128; ++i) for (; i < 128; ++i) {
{
QPointF thisPt(i * xIncrement + 30.0, height() - 16.0); QPointF thisPt(i * xIncrement + 30.0, height() - 16.0);
if (i) if (i)
painter.drawLine(lastPt, thisPt); painter.drawLine(lastPt, thisPt);
@ -131,13 +106,9 @@ void CurveView::paintEvent(QPaintEvent* ev)
} }
} }
void CurveView::mousePressEvent(QMouseEvent* ev) void CurveView::mousePressEvent(QMouseEvent* ev) { mouseMoveEvent(ev); }
{
mouseMoveEvent(ev);
}
void CurveView::mouseMoveEvent(QMouseEvent* ev) void CurveView::mouseMoveEvent(QMouseEvent* ev) {
{
CurveView* view = getEditor()->m_curveView; CurveView* view = getEditor()->m_curveView;
amuse::ITable& table = **view->m_node->m_obj; amuse::ITable& table = **view->m_node->m_obj;
if (table.Isa() != amuse::ITable::Type::Curve) if (table.Isa() != amuse::ITable::Type::Curve)
@ -159,11 +130,8 @@ void CurveView::mouseMoveEvent(QMouseEvent* ev)
update(); update();
} }
CurveView::CurveView(QWidget* parent) CurveView::CurveView(QWidget* parent) : QWidget(parent) {
: QWidget(parent) for (int i = 0; i < 11; ++i) {
{
for (int i = 0; i < 11; ++i)
{
m_percentTexts[i].setText(QStringLiteral("%1%").arg(100 - i * 10)); m_percentTexts[i].setText(QStringLiteral("%1%").arg(100 - i * 10));
m_percentTexts[i].setTextOption(QTextOption(Qt::AlignVCenter | Qt::AlignRight)); m_percentTexts[i].setTextOption(QTextOption(Qt::AlignVCenter | Qt::AlignRight));
m_percentTexts[i].setTextWidth(28.0); m_percentTexts[i].setTextWidth(28.0);
@ -174,25 +142,19 @@ CurveView::CurveView(QWidget* parent)
m_gridFont.setPointSize(8); m_gridFont.setPointSize(8);
} }
CurveEditor* CurveControls::getEditor() const CurveEditor* CurveControls::getEditor() const { return qobject_cast<CurveEditor*>(parentWidget()); }
{
return qobject_cast<CurveEditor*>(parentWidget());
}
void CurveControls::loadData() void CurveControls::loadData() {
{
m_lineEdit->setDisabled(false); m_lineEdit->setDisabled(false);
m_setExpr->setDisabled(false); m_setExpr->setDisabled(false);
} }
void CurveControls::unloadData() void CurveControls::unloadData() {
{
m_lineEdit->setDisabled(true); m_lineEdit->setDisabled(true);
m_setExpr->setDisabled(true); m_setExpr->setDisabled(true);
} }
void CurveControls::exprCommit() void CurveControls::exprCommit() {
{
CurveView* view = getEditor()->m_curveView; CurveView* view = getEditor()->m_curveView;
amuse::ITable& table = **view->m_node->m_obj; amuse::ITable& table = **view->m_node->m_obj;
if (table.Isa() != amuse::ITable::Type::Curve) if (table.Isa() != amuse::ITable::Type::Curve)
@ -204,21 +166,15 @@ void CurveControls::exprCommit()
uint8_t newData[128]; uint8_t newData[128];
std::memcpy(newData, curve.data.data(), 128); std::memcpy(newData, curve.data.data(), 128);
bool notANumber = false; bool notANumber = false;
for (int i = 0; i < 128; ++i) for (int i = 0; i < 128; ++i) {
{
m_engine.globalObject().setProperty(QStringLiteral("x"), i / 127.0); m_engine.globalObject().setProperty(QStringLiteral("x"), i / 127.0);
QJSValue val = m_engine.evaluate(progText); QJSValue val = m_engine.evaluate(progText);
if (val.isError()) if (val.isError()) {
{
m_errLabel->setText(val.toString()); m_errLabel->setText(val.toString());
return; return;
} } else if (val.isNumber()) {
else if (val.isNumber())
{
newData[i] = uint8_t(amuse::clamp(0, int(std::round(val.toNumber() * 127.0)), 127)); newData[i] = uint8_t(amuse::clamp(0, int(std::round(val.toNumber() * 127.0)), 127));
} } else {
else
{
notANumber = true; notANumber = true;
newData[i] = 0; newData[i] = 0;
} }
@ -230,14 +186,9 @@ void CurveControls::exprCommit()
view->update(); view->update();
} }
void CurveControls::resizeEvent(QResizeEvent* ev) void CurveControls::resizeEvent(QResizeEvent* ev) { m_errLabel->setGeometry(22, 78, width() - 44, 14); }
{
m_errLabel->setGeometry(22, 78, width() - 44, 14);
}
CurveControls::CurveControls(QWidget* parent) CurveControls::CurveControls(QWidget* parent) : QFrame(parent) {
: QFrame(parent)
{
setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
setFixedHeight(100); setFixedHeight(100);
setFrameShape(QFrame::StyledPanel); setFrameShape(QFrame::StyledPanel);
@ -282,10 +233,10 @@ CurveControls::CurveControls(QWidget* parent)
setLayout(mainLayout); setLayout(mainLayout);
QJSValueIterator it(m_engine.globalObject().property(QStringLiteral("Math"))); QJSValueIterator it(m_engine.globalObject().property(QStringLiteral("Math")));
QString docStr = tr("Expression interpreter mapping x:[0,1] to y:[0,1] with the following constants and functions available:\n"); QString docStr =
tr("Expression interpreter mapping x:[0,1] to y:[0,1] with the following constants and functions available:\n");
bool needsComma = false; bool needsComma = false;
while (it.hasNext()) while (it.hasNext()) {
{
it.next(); it.next();
m_engine.globalObject().setProperty(it.name(), it.value()); m_engine.globalObject().setProperty(it.name(), it.value());
if (needsComma) if (needsComma)
@ -296,27 +247,21 @@ CurveControls::CurveControls(QWidget* parent)
m_lineEdit->setToolTip(docStr); m_lineEdit->setToolTip(docStr);
} }
bool CurveEditor::loadData(ProjectModel::CurveNode* node) bool CurveEditor::loadData(ProjectModel::CurveNode* node) {
{
m_curveView->loadData(node); m_curveView->loadData(node);
m_controls->loadData(); m_controls->loadData();
return true; return true;
} }
void CurveEditor::unloadData() void CurveEditor::unloadData() {
{
m_curveView->unloadData(); m_curveView->unloadData();
m_controls->unloadData(); m_controls->unloadData();
} }
ProjectModel::INode* CurveEditor::currentNode() const ProjectModel::INode* CurveEditor::currentNode() const { return m_curveView->currentNode(); }
{
return m_curveView->currentNode();
}
CurveEditor::CurveEditor(QWidget* parent) CurveEditor::CurveEditor(QWidget* parent)
: EditorWidget(parent), m_curveView(new CurveView), m_controls(new CurveControls) : EditorWidget(parent), m_curveView(new CurveView), m_controls(new CurveControls) {
{
QVBoxLayout* layout = new QVBoxLayout; QVBoxLayout* layout = new QVBoxLayout;
layout->setContentsMargins(QMargins()); layout->setContentsMargins(QMargins());
layout->setSpacing(1); layout->setSpacing(1);

View File

@ -10,15 +10,15 @@
class CurveEditor; class CurveEditor;
class CurveView : public QWidget class CurveView : public QWidget {
{ Q_OBJECT
Q_OBJECT
friend class CurveControls; friend class CurveControls;
amuse::ObjToken<ProjectModel::CurveNode> m_node; amuse::ObjToken<ProjectModel::CurveNode> m_node;
QFont m_gridFont; QFont m_gridFont;
QStaticText m_percentTexts[11]; QStaticText m_percentTexts[11];
QStaticText m_percentTextsCenter[11]; QStaticText m_percentTextsCenter[11];
CurveEditor* getEditor() const; CurveEditor* getEditor() const;
public: public:
explicit CurveView(QWidget* parent = Q_NULLPTR); explicit CurveView(QWidget* parent = Q_NULLPTR);
void loadData(ProjectModel::CurveNode* node); void loadData(ProjectModel::CurveNode* node);
@ -30,15 +30,15 @@ public:
void mouseMoveEvent(QMouseEvent* ev); void mouseMoveEvent(QMouseEvent* ev);
}; };
class CurveControls : public QFrame class CurveControls : public QFrame {
{ Q_OBJECT
Q_OBJECT
friend class CurveView; friend class CurveView;
QLineEdit* m_lineEdit; QLineEdit* m_lineEdit;
QLabel* m_errLabel; QLabel* m_errLabel;
QPushButton* m_setExpr; QPushButton* m_setExpr;
QJSEngine m_engine; QJSEngine m_engine;
CurveEditor* getEditor() const; CurveEditor* getEditor() const;
public: public:
explicit CurveControls(QWidget* parent = Q_NULLPTR); explicit CurveControls(QWidget* parent = Q_NULLPTR);
void loadData(); void loadData();
@ -48,17 +48,16 @@ public slots:
void exprCommit(); void exprCommit();
}; };
class CurveEditor : public EditorWidget class CurveEditor : public EditorWidget {
{ Q_OBJECT
Q_OBJECT
friend class CurveView; friend class CurveView;
friend class CurveControls; friend class CurveControls;
CurveView* m_curveView; CurveView* m_curveView;
CurveControls* m_controls; CurveControls* m_controls;
public: public:
explicit CurveEditor(QWidget* parent = Q_NULLPTR); explicit CurveEditor(QWidget* parent = Q_NULLPTR);
bool loadData(ProjectModel::CurveNode* node); bool loadData(ProjectModel::CurveNode* node);
void unloadData(); void unloadData();
ProjectModel::INode* currentNode() const; ProjectModel::INode* currentNode() const;
}; };

View File

@ -3,25 +3,13 @@
#include <QStandardItemModel> #include <QStandardItemModel>
#include <QHBoxLayout> #include <QHBoxLayout>
EditorWidget::EditorWidget(QWidget* parent) EditorWidget::EditorWidget(QWidget* parent) : QWidget(parent) {}
: QWidget(parent)
{
} void EditorUndoCommand::undo() { g_MainWindow->openEditor(m_node.get()); }
void EditorUndoCommand::undo() void EditorUndoCommand::redo() { g_MainWindow->openEditor(m_node.get()); }
{
g_MainWindow->openEditor(m_node.get());
}
void EditorUndoCommand::redo() FieldSlider::FieldSlider(QWidget* parent) : QWidget(parent), m_slider(Qt::Horizontal) {
{
g_MainWindow->openEditor(m_node.get());
}
FieldSlider::FieldSlider(QWidget* parent)
: QWidget(parent), m_slider(Qt::Horizontal)
{
setFixedHeight(22); setFixedHeight(22);
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
QHBoxLayout* layout = new QHBoxLayout; QHBoxLayout* layout = new QHBoxLayout;
@ -34,15 +22,12 @@ FieldSlider::FieldSlider(QWidget* parent)
m_slider.setValue(0); m_slider.setValue(0);
} }
void FieldSlider::doValueChanged(int value) void FieldSlider::doValueChanged(int value) {
{
m_value.setText(QString::number(value)); m_value.setText(QString::number(value));
emit valueChanged(value); emit valueChanged(value);
} }
FieldDoubleSlider::FieldDoubleSlider(QWidget* parent) FieldDoubleSlider::FieldDoubleSlider(QWidget* parent) : QWidget(parent), m_slider(Qt::Horizontal) {
: QWidget(parent), m_slider(Qt::Horizontal)
{
setFixedHeight(22); setFixedHeight(22);
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
QHBoxLayout* layout = new QHBoxLayout; QHBoxLayout* layout = new QHBoxLayout;
@ -56,13 +41,11 @@ FieldDoubleSlider::FieldDoubleSlider(QWidget* parent)
m_slider.setValue(0); m_slider.setValue(0);
} }
double FieldDoubleSlider::value() const double FieldDoubleSlider::value() const {
{
double t = m_slider.value() / 1000.0; double t = m_slider.value() / 1000.0;
return t * (m_max - m_min) + m_min; return t * (m_max - m_min) + m_min;
} }
void FieldDoubleSlider::setValue(double value) void FieldDoubleSlider::setValue(double value) {
{
if (value < m_min) if (value < m_min)
value = m_min; value = m_min;
else if (value > m_max) else if (value > m_max)
@ -72,9 +55,9 @@ void FieldDoubleSlider::setValue(double value)
m_slider.setValue(int(t * 1000.0)); m_slider.setValue(int(t * 1000.0));
doValueChanged(int(t * 1000.0)); doValueChanged(int(t * 1000.0));
} }
void FieldDoubleSlider::setRange(double min, double max) void FieldDoubleSlider::setRange(double min, double max) {
{ m_min = min;
m_min = min; m_max = max; m_max = max;
double curValue = value(); double curValue = value();
if (curValue < min) if (curValue < min)
setValue(min); setValue(min);
@ -82,8 +65,7 @@ void FieldDoubleSlider::setRange(double min, double max)
setValue(max); setValue(max);
} }
void FieldDoubleSlider::doValueChanged(int value) void FieldDoubleSlider::doValueChanged(int value) {
{
double t = value / 1000.0; double t = value / 1000.0;
t = t * (m_max - m_min) + m_min; t = t * (m_max - m_min) + m_min;
m_value.setText(QString::number(t, 'g', 2)); m_value.setText(QString::number(t, 'g', 2));
@ -91,8 +73,7 @@ void FieldDoubleSlider::doValueChanged(int value)
} }
FieldProjectNode::FieldProjectNode(ProjectModel::CollectionNode* collection, QWidget* parent) FieldProjectNode::FieldProjectNode(ProjectModel::CollectionNode* collection, QWidget* parent)
: QWidget(parent), m_comboBox(this), m_button(this) : QWidget(parent), m_comboBox(this), m_button(this) {
{
m_button.setDisabled(true); m_button.setDisabled(true);
m_button.setFixedSize(30, 30); m_button.setFixedSize(30, 30);
m_comboBox.setFixedHeight(30); m_comboBox.setFixedHeight(30);
@ -110,12 +91,10 @@ FieldProjectNode::FieldProjectNode(ProjectModel::CollectionNode* collection, QWi
setCollection(collection); setCollection(collection);
} }
void FieldProjectNode::setCollection(ProjectModel::CollectionNode* collection) void FieldProjectNode::setCollection(ProjectModel::CollectionNode* collection) {
{
m_collection = collection; m_collection = collection;
if (!collection) if (!collection) {
{
m_comboBox.setModel(new QStandardItemModel(0, 1, this)); m_comboBox.setModel(new QStandardItemModel(0, 1, this));
m_button.setDisabled(true); m_button.setDisabled(true);
return; return;
@ -126,14 +105,12 @@ void FieldProjectNode::setCollection(ProjectModel::CollectionNode* collection)
m_comboBox.setRootModelIndex(model->getNullProxy()->mapFromSource(model->index(collection))); m_comboBox.setRootModelIndex(model->getNullProxy()->mapFromSource(model->index(collection)));
} }
void FieldProjectNode::_currentIndexChanged(int index) void FieldProjectNode::_currentIndexChanged(int index) {
{
m_button.setEnabled(index != 0); m_button.setEnabled(index != 0);
emit currentIndexChanged(index); emit currentIndexChanged(index);
} }
ProjectModel::BasePoolObjectNode* FieldProjectNode::currentNode() const ProjectModel::BasePoolObjectNode* FieldProjectNode::currentNode() const {
{
int index = m_comboBox.currentIndex(); int index = m_comboBox.currentIndex();
if (index == 0) if (index == 0)
return nullptr; return nullptr;
@ -141,26 +118,22 @@ ProjectModel::BasePoolObjectNode* FieldProjectNode::currentNode() const
return m_collection->nodeOfIndex(index - 1); return m_collection->nodeOfIndex(index - 1);
} }
bool FieldProjectNode::event(QEvent* ev) bool FieldProjectNode::event(QEvent* ev) {
{ if (ev->type() == QEvent::User) {
if (ev->type() == QEvent::User)
{
showPopup(); showPopup();
return true; return true;
} }
return QWidget::event(ev); return QWidget::event(ev);
} }
void FieldProjectNode::openCurrent() void FieldProjectNode::openCurrent() {
{
if (ProjectModel::BasePoolObjectNode* node = currentNode()) if (ProjectModel::BasePoolObjectNode* node = currentNode())
if (!g_MainWindow->isUiDisabled()) if (!g_MainWindow->isUiDisabled())
g_MainWindow->openEditor(node); g_MainWindow->openEditor(node);
} }
FieldPageObjectNode::FieldPageObjectNode(ProjectModel::GroupNode* group, QWidget* parent) FieldPageObjectNode::FieldPageObjectNode(ProjectModel::GroupNode* group, QWidget* parent)
: QWidget(parent), m_comboBox(this), m_button(this) : QWidget(parent), m_comboBox(this), m_button(this) {
{
m_button.setDisabled(true); m_button.setDisabled(true);
m_button.setFixedSize(30, 30); m_button.setFixedSize(30, 30);
m_comboBox.setFixedHeight(30); m_comboBox.setFixedHeight(30);
@ -178,12 +151,10 @@ FieldPageObjectNode::FieldPageObjectNode(ProjectModel::GroupNode* group, QWidget
setGroup(group); setGroup(group);
} }
void FieldPageObjectNode::setGroup(ProjectModel::GroupNode* group) void FieldPageObjectNode::setGroup(ProjectModel::GroupNode* group) {
{
m_group = group; m_group = group;
if (!group) if (!group) {
{
m_comboBox.setModel(new QStandardItemModel(0, 1, this)); m_comboBox.setModel(new QStandardItemModel(0, 1, this));
m_button.setDisabled(true); m_button.setDisabled(true);
return; return;
@ -194,49 +165,42 @@ void FieldPageObjectNode::setGroup(ProjectModel::GroupNode* group)
m_comboBox.setRootModelIndex(model->getPageObjectProxy()->mapFromSource(model->index(group))); m_comboBox.setRootModelIndex(model->getPageObjectProxy()->mapFromSource(model->index(group)));
} }
void FieldPageObjectNode::_currentIndexChanged(int index) void FieldPageObjectNode::_currentIndexChanged(int index) {
{
m_button.setEnabled(index != 0); m_button.setEnabled(index != 0);
emit currentIndexChanged(index); emit currentIndexChanged(index);
} }
ProjectModel::BasePoolObjectNode* FieldPageObjectNode::currentNode() const ProjectModel::BasePoolObjectNode* FieldPageObjectNode::currentNode() const {
{
int index = m_comboBox.currentIndex(); int index = m_comboBox.currentIndex();
if (index == 0) if (index == 0) {
{
return nullptr; return nullptr;
} } else {
else
{
ProjectModel* model = g_MainWindow->projectModel(); ProjectModel* model = g_MainWindow->projectModel();
return static_cast<ProjectModel::BasePoolObjectNode*>( return static_cast<ProjectModel::BasePoolObjectNode*>(model->node(model->getPageObjectProxy()->mapToSource(
model->node(model->getPageObjectProxy()->mapToSource(
model->getPageObjectProxy()->index(index, 0, m_comboBox.rootModelIndex())))); model->getPageObjectProxy()->index(index, 0, m_comboBox.rootModelIndex()))));
} }
} }
bool FieldPageObjectNode::event(QEvent* ev) bool FieldPageObjectNode::event(QEvent* ev) {
{ if (ev->type() == QEvent::User) {
if (ev->type() == QEvent::User)
{
showPopup(); showPopup();
return true; return true;
} }
return QWidget::event(ev); return QWidget::event(ev);
} }
void FieldPageObjectNode::openCurrent() void FieldPageObjectNode::openCurrent() {
{
if (ProjectModel::BasePoolObjectNode* node = currentNode()) if (ProjectModel::BasePoolObjectNode* node = currentNode())
if (!g_MainWindow->isUiDisabled()) if (!g_MainWindow->isUiDisabled())
g_MainWindow->openEditor(node); g_MainWindow->openEditor(node);
} }
AddRemoveButtons::AddRemoveButtons(QWidget* parent) AddRemoveButtons::AddRemoveButtons(QWidget* parent)
: QWidget(parent), m_addAction(tr("Add Row")), m_addButton(this), : QWidget(parent)
m_removeAction(tr("Remove Row")), m_removeButton(this) , m_addAction(tr("Add Row"))
{ , m_addButton(this)
, m_removeAction(tr("Remove Row"))
, m_removeButton(this) {
setFixedSize(64, 32); setFixedSize(64, 32);
m_addAction.setIcon(QIcon(QStringLiteral(":/icons/IconAdd.svg"))); m_addAction.setIcon(QIcon(QStringLiteral(":/icons/IconAdd.svg")));
@ -254,19 +218,11 @@ AddRemoveButtons::AddRemoveButtons(QWidget* parent)
static QIcon ListingDeleteIcon; static QIcon ListingDeleteIcon;
static QIcon ListingDeleteHoveredIcon; static QIcon ListingDeleteHoveredIcon;
void ListingDeleteButton::enterEvent(QEvent* event) void ListingDeleteButton::enterEvent(QEvent* event) { setIcon(ListingDeleteHoveredIcon); }
{
setIcon(ListingDeleteHoveredIcon);
}
void ListingDeleteButton::leaveEvent(QEvent* event) void ListingDeleteButton::leaveEvent(QEvent* event) { setIcon(ListingDeleteIcon); }
{
setIcon(ListingDeleteIcon);
}
ListingDeleteButton::ListingDeleteButton(QWidget* parent) ListingDeleteButton::ListingDeleteButton(QWidget* parent) : QPushButton(parent) {
: QPushButton(parent)
{
if (ListingDeleteIcon.isNull()) if (ListingDeleteIcon.isNull())
ListingDeleteIcon = QIcon(QStringLiteral(":/icons/IconSoundMacroDelete.svg")); ListingDeleteIcon = QIcon(QStringLiteral(":/icons/IconSoundMacroDelete.svg"));
if (ListingDeleteHoveredIcon.isNull()) if (ListingDeleteHoveredIcon.isNull())
@ -279,14 +235,11 @@ ListingDeleteButton::ListingDeleteButton(QWidget* parent)
setIcon(ListingDeleteIcon); setIcon(ListingDeleteIcon);
} }
bool BaseObjectDelegate::editorEvent(QEvent *event, QAbstractItemModel* model, bool BaseObjectDelegate::editorEvent(QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option,
const QStyleOptionViewItem &option, const QModelIndex &index) const QModelIndex& index) {
{ if (event->type() == QEvent::MouseButtonPress) {
if (event->type() == QEvent::MouseButtonPress)
{
QMouseEvent* ev = static_cast<QMouseEvent*>(event); QMouseEvent* ev = static_cast<QMouseEvent*>(event);
if (ev->button() == Qt::RightButton) if (ev->button() == Qt::RightButton) {
{
ProjectModel::INode* node = getNode(model, index); ProjectModel::INode* node = getNode(model, index);
ContextMenu* menu = new ContextMenu; ContextMenu* menu = new ContextMenu;
@ -309,15 +262,13 @@ bool BaseObjectDelegate::editorEvent(QEvent *event, QAbstractItemModel* model,
return false; return false;
} }
void BaseObjectDelegate::doOpenEditor() void BaseObjectDelegate::doOpenEditor() {
{
QAction* act = static_cast<QAction*>(sender()); QAction* act = static_cast<QAction*>(sender());
if (ProjectModel::INode* node = reinterpret_cast<ProjectModel::INode*>(act->data().value<void*>())) if (ProjectModel::INode* node = reinterpret_cast<ProjectModel::INode*>(act->data().value<void*>()))
g_MainWindow->openEditor(node); g_MainWindow->openEditor(node);
} }
void BaseObjectDelegate::doFindUsages() void BaseObjectDelegate::doFindUsages() {
{
QAction* act = static_cast<QAction*>(sender()); QAction* act = static_cast<QAction*>(sender());
if (ProjectModel::INode* node = reinterpret_cast<ProjectModel::INode*>(act->data().value<void*>())) if (ProjectModel::INode* node = reinterpret_cast<ProjectModel::INode*>(act->data().value<void*>()))
g_MainWindow->findUsages(node); g_MainWindow->findUsages(node);

View File

@ -15,8 +15,7 @@
#include <QStyledItemDelegate> #include <QStyledItemDelegate>
#include "ProjectModel.hpp" #include "ProjectModel.hpp"
class EditorWidget : public QWidget class EditorWidget : public QWidget {
{
Q_OBJECT Q_OBJECT
public: public:
explicit EditorWidget(QWidget* parent = Q_NULLPTR); explicit EditorWidget(QWidget* parent = Q_NULLPTR);
@ -32,12 +31,10 @@ public slots:
virtual void itemDeleteAction() {} virtual void itemDeleteAction() {}
}; };
class EditorUndoCommand : public QUndoCommand class EditorUndoCommand : public QUndoCommand {
{
protected: protected:
amuse::ObjToken<ProjectModel::INode> m_node; amuse::ObjToken<ProjectModel::INode> m_node;
enum class Id enum class Id {
{
SMChangeVal, SMChangeVal,
SampLoop, SampLoop,
SampPitch, SampPitch,
@ -52,30 +49,28 @@ protected:
ADSRKeyToDecay, ADSRKeyToDecay,
CurveEdit CurveEdit
}; };
public: public:
EditorUndoCommand(amuse::ObjToken<ProjectModel::INode> node, EditorUndoCommand(amuse::ObjToken<ProjectModel::INode> node, const QString& text, QUndoCommand* parent = nullptr)
const QString& text, QUndoCommand* parent = nullptr)
: QUndoCommand(text, parent), m_node(node) {} : QUndoCommand(text, parent), m_node(node) {}
void undo(); void undo();
void redo(); void redo();
}; };
class FieldSpinBox : public QSpinBox class FieldSpinBox : public QSpinBox {
{
Q_OBJECT Q_OBJECT
public: public:
explicit FieldSpinBox(QWidget* parent = Q_NULLPTR) explicit FieldSpinBox(QWidget* parent = Q_NULLPTR) : QSpinBox(parent) {}
: QSpinBox(parent) {}
/* Don't scroll */ /* Don't scroll */
void wheelEvent(QWheelEvent* event) { event->ignore(); } void wheelEvent(QWheelEvent* event) { event->ignore(); }
}; };
class FieldSlider : public QWidget class FieldSlider : public QWidget {
{ Q_OBJECT
Q_OBJECT
QSlider m_slider; QSlider m_slider;
QLabel m_value; QLabel m_value;
public: public:
explicit FieldSlider(QWidget* parent = Q_NULLPTR); explicit FieldSlider(QWidget* parent = Q_NULLPTR);
@ -83,7 +78,10 @@ public:
void wheelEvent(QWheelEvent* event) { event->ignore(); } void wheelEvent(QWheelEvent* event) { event->ignore(); }
int value() const { return m_slider.value(); } int value() const { return m_slider.value(); }
void setValue(int value) { m_slider.setValue(value); doValueChanged(value); } void setValue(int value) {
m_slider.setValue(value);
doValueChanged(value);
}
void setRange(int min, int max) { m_slider.setRange(min, max); } void setRange(int min, int max) { m_slider.setRange(min, max); }
private slots: private slots:
@ -92,13 +90,13 @@ signals:
void valueChanged(int value); void valueChanged(int value);
}; };
class FieldDoubleSlider : public QWidget class FieldDoubleSlider : public QWidget {
{
Q_OBJECT Q_OBJECT
QSlider m_slider; QSlider m_slider;
QLabel m_value; QLabel m_value;
double m_min = 0.0; double m_min = 0.0;
double m_max = 1.0; double m_max = 1.0;
public: public:
explicit FieldDoubleSlider(QWidget* parent = Q_NULLPTR); explicit FieldDoubleSlider(QWidget* parent = Q_NULLPTR);
@ -115,23 +113,21 @@ signals:
void valueChanged(double value); void valueChanged(double value);
}; };
class FieldComboBox : public QComboBox class FieldComboBox : public QComboBox {
{
Q_OBJECT Q_OBJECT
public: public:
explicit FieldComboBox(QWidget* parent = Q_NULLPTR) explicit FieldComboBox(QWidget* parent = Q_NULLPTR) : QComboBox(parent) {}
: QComboBox(parent) {}
/* Don't scroll */ /* Don't scroll */
void wheelEvent(QWheelEvent* event) { event->ignore(); } void wheelEvent(QWheelEvent* event) { event->ignore(); }
}; };
class FieldProjectNode : public QWidget class FieldProjectNode : public QWidget {
{
Q_OBJECT Q_OBJECT
ProjectModel::CollectionNode* m_collection; ProjectModel::CollectionNode* m_collection;
FieldComboBox m_comboBox; FieldComboBox m_comboBox;
QPushButton m_button; QPushButton m_button;
public: public:
explicit FieldProjectNode(ProjectModel::CollectionNode* collection = Q_NULLPTR, QWidget* parent = Q_NULLPTR); explicit FieldProjectNode(ProjectModel::CollectionNode* collection = Q_NULLPTR, QWidget* parent = Q_NULLPTR);
void setCollection(ProjectModel::CollectionNode* collection); void setCollection(ProjectModel::CollectionNode* collection);
@ -149,12 +145,12 @@ signals:
void currentIndexChanged(int); void currentIndexChanged(int);
}; };
class FieldPageObjectNode : public QWidget class FieldPageObjectNode : public QWidget {
{
Q_OBJECT Q_OBJECT
ProjectModel::GroupNode* m_group; ProjectModel::GroupNode* m_group;
FieldComboBox m_comboBox; FieldComboBox m_comboBox;
QPushButton m_button; QPushButton m_button;
public: public:
explicit FieldPageObjectNode(ProjectModel::GroupNode* group = Q_NULLPTR, QWidget* parent = Q_NULLPTR); explicit FieldPageObjectNode(ProjectModel::GroupNode* group = Q_NULLPTR, QWidget* parent = Q_NULLPTR);
void setGroup(ProjectModel::GroupNode* group); void setGroup(ProjectModel::GroupNode* group);
@ -174,13 +170,12 @@ signals:
}; };
template <class T> template <class T>
class EditorFieldNode : public T class EditorFieldNode : public T {
{
bool m_deferPopupOpen = true; bool m_deferPopupOpen = true;
public: public:
using T::T; using T::T;
bool shouldPopupOpen() bool shouldPopupOpen() {
{
bool ret = m_deferPopupOpen; bool ret = m_deferPopupOpen;
m_deferPopupOpen = false; m_deferPopupOpen = false;
return ret; return ret;
@ -191,11 +186,9 @@ using EditorFieldProjectNode = EditorFieldNode<FieldProjectNode>;
using EditorFieldPageObjectNode = EditorFieldNode<FieldPageObjectNode>; using EditorFieldPageObjectNode = EditorFieldNode<FieldPageObjectNode>;
template <int MIN, int MAX> template <int MIN, int MAX>
class RangedValueFactory : public QItemEditorFactory class RangedValueFactory : public QItemEditorFactory {
{
public: public:
QWidget* createEditor(int userType, QWidget *parent) const QWidget* createEditor(int userType, QWidget* parent) const {
{
QSpinBox* sb = new QSpinBox(parent); QSpinBox* sb = new QSpinBox(parent);
sb->setFrame(false); sb->setFrame(false);
sb->setMinimum(MIN); sb->setMinimum(MIN);
@ -204,49 +197,45 @@ public:
} }
}; };
class AddRemoveButtons : public QWidget class AddRemoveButtons : public QWidget {
{ Q_OBJECT
Q_OBJECT
QAction m_addAction; QAction m_addAction;
QToolButton m_addButton; QToolButton m_addButton;
QAction m_removeAction; QAction m_removeAction;
QToolButton m_removeButton; QToolButton m_removeButton;
public: public:
explicit AddRemoveButtons(QWidget* parent = Q_NULLPTR); explicit AddRemoveButtons(QWidget* parent = Q_NULLPTR);
QAction* addAction() { return &m_addAction; } QAction* addAction() { return &m_addAction; }
QAction* removeAction() { return &m_removeAction; } QAction* removeAction() { return &m_removeAction; }
}; };
class ListingDeleteButton : public QPushButton class ListingDeleteButton : public QPushButton {
{ Q_OBJECT
Q_OBJECT
public: public:
explicit ListingDeleteButton(QWidget* parent = Q_NULLPTR); explicit ListingDeleteButton(QWidget* parent = Q_NULLPTR);
void enterEvent(QEvent* event); void enterEvent(QEvent* event);
void leaveEvent(QEvent* event); void leaveEvent(QEvent* event);
}; };
class ContextMenu : public QMenu class ContextMenu : public QMenu {
{
public: public:
void hideEvent(QHideEvent* ev) void hideEvent(QHideEvent* ev) {
{
QMenu::hideEvent(ev); QMenu::hideEvent(ev);
deleteLater(); deleteLater();
} }
}; };
class BaseObjectDelegate : public QStyledItemDelegate class BaseObjectDelegate : public QStyledItemDelegate {
{
Q_OBJECT Q_OBJECT
protected: protected:
virtual ProjectModel::INode* getNode(const QAbstractItemModel* model, const QModelIndex& index) const = 0; virtual ProjectModel::INode* getNode(const QAbstractItemModel* model, const QModelIndex& index) const = 0;
public: public:
explicit BaseObjectDelegate(QObject* parent = Q_NULLPTR) : QStyledItemDelegate(parent) {} explicit BaseObjectDelegate(QObject* parent = Q_NULLPTR) : QStyledItemDelegate(parent) {}
bool editorEvent(QEvent *event, QAbstractItemModel *model, bool editorEvent(QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option,
const QStyleOptionViewItem &option, const QModelIndex &index); const QModelIndex& index);
private slots: private slots:
void doOpenEditor(); void doOpenEditor();
void doFindUsages(); void doFindUsages();
}; };

View File

@ -6,71 +6,37 @@
#include <QApplication> #include <QApplication>
#include <QScrollBar> #include <QScrollBar>
const QString NaturalKeyNames[] = const QString NaturalKeyNames[] = {QStringLiteral("C"), QStringLiteral("D"), QStringLiteral("E"), QStringLiteral("F"),
{ QStringLiteral("G"), QStringLiteral("A"), QStringLiteral("B")};
QStringLiteral("C"),
QStringLiteral("D"),
QStringLiteral("E"),
QStringLiteral("F"),
QStringLiteral("G"),
QStringLiteral("A"),
QStringLiteral("B")
};
const QString SharpKeyNames[] = const QString SharpKeyNames[] = {QStringLiteral("Cs"), QStringLiteral("Ds"), QStringLiteral("Fs"), QStringLiteral("Gs"),
{ QStringLiteral("As")};
QStringLiteral("Cs"),
QStringLiteral("Ds"),
QStringLiteral("Fs"),
QStringLiteral("Gs"),
QStringLiteral("As")
};
const QString KeyStrings[] = const QString KeyStrings[] = {QStringLiteral("C"), QStringLiteral("C#"), QStringLiteral("D"), QStringLiteral("D#"),
{ QStringLiteral("E"), QStringLiteral("F"), QStringLiteral("F#"), QStringLiteral("G"),
QStringLiteral("C"), QStringLiteral("G#"), QStringLiteral("A"), QStringLiteral("A#"), QStringLiteral("B")};
QStringLiteral("C#"),
QStringLiteral("D"),
QStringLiteral("D#"),
QStringLiteral("E"),
QStringLiteral("F"),
QStringLiteral("F#"),
QStringLiteral("G"),
QStringLiteral("G#"),
QStringLiteral("A"),
QStringLiteral("A#"),
QStringLiteral("B")
};
const int NaturalKeyNumbers[] = const int NaturalKeyNumbers[] = {0, 2, 4, 5, 7, 9, 11};
{
0, 2, 4, 5, 7, 9, 11
};
const int SharpKeyNumbers[] = const int SharpKeyNumbers[] = {1, 3, 6, 8, 10};
{
1, 3, 6, 8, 10
};
KeyboardOctave::KeyboardOctave(int octave, const QString& svgPath, QWidget* parent) KeyboardOctave::KeyboardOctave(int octave, const QString& svgPath, QWidget* parent)
: QSvgWidget(svgPath, parent), m_octave(octave) : QSvgWidget(svgPath, parent), m_octave(octave) {
{
for (int i = 0; i < 7; ++i) for (int i = 0; i < 7; ++i)
if (renderer()->elementExists(NaturalKeyNames[i])) if (renderer()->elementExists(NaturalKeyNames[i]))
m_natural[i] = renderer()->matrixForElement(NaturalKeyNames[i]). m_natural[i] =
mapRect(renderer()->boundsOnElement(NaturalKeyNames[i])); renderer()->matrixForElement(NaturalKeyNames[i]).mapRect(renderer()->boundsOnElement(NaturalKeyNames[i]));
for (int i = 0; i < 5; ++i) for (int i = 0; i < 5; ++i)
if (renderer()->elementExists(SharpKeyNames[i])) if (renderer()->elementExists(SharpKeyNames[i]))
m_sharp[i] = renderer()->matrixForElement(SharpKeyNames[i]). m_sharp[i] =
mapRect(renderer()->boundsOnElement(SharpKeyNames[i])); renderer()->matrixForElement(SharpKeyNames[i]).mapRect(renderer()->boundsOnElement(SharpKeyNames[i]));
/* The parent keyboard manages all mouse events */ /* The parent keyboard manages all mouse events */
setAttribute(Qt::WA_TransparentForMouseEvents); setAttribute(Qt::WA_TransparentForMouseEvents);
} }
int KeyboardOctave::getKey(const QPoint& localPos) const int KeyboardOctave::getKey(const QPoint& localPos) const {
{
QPointF localPoint = m_widgetToSvg.map(localPos); QPointF localPoint = m_widgetToSvg.map(localPos);
for (int i = 0; i < 5; ++i) for (int i = 0; i < 5; ++i)
if (m_sharp[i].contains(localPoint)) if (m_sharp[i].contains(localPoint))
@ -81,20 +47,14 @@ int KeyboardOctave::getKey(const QPoint& localPos) const
return -1; return -1;
} }
void KeyboardOctave::resizeEvent(QResizeEvent *event) void KeyboardOctave::resizeEvent(QResizeEvent* event) { m_widgetToSvg = RectToRect(rect(), renderer()->viewBoxF()); }
{
m_widgetToSvg = RectToRect(rect(), renderer()->viewBoxF());
}
KeyboardWidget::KeyboardWidget(QWidget* parent) KeyboardWidget::KeyboardWidget(QWidget* parent) : QWidget(parent) {
: QWidget(parent)
{
QHBoxLayout* layout = new QHBoxLayout(this); QHBoxLayout* layout = new QHBoxLayout(this);
layout->setContentsMargins(QMargins()); layout->setContentsMargins(QMargins());
layout->setSpacing(0); layout->setSpacing(0);
for (int i = 0; i < 10; ++i) for (int i = 0; i < 10; ++i) {
{
m_widgets[i] = new KeyboardOctave(i, QStringLiteral(":/bg/keyboard.svg"), this); m_widgets[i] = new KeyboardOctave(i, QStringLiteral(":/bg/keyboard.svg"), this);
m_widgets[i]->setGeometry(QRect(0, 0, 141, 50)); m_widgets[i]->setGeometry(QRect(0, 0, 141, 50));
m_widgets[i]->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred)); m_widgets[i]->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred));
@ -110,10 +70,8 @@ KeyboardWidget::KeyboardWidget(QWidget* parent)
setMouseTracking(true); setMouseTracking(true);
} }
std::pair<int, int> KeyboardWidget::_getOctaveAndKey(QMouseEvent* event) const std::pair<int, int> KeyboardWidget::_getOctaveAndKey(QMouseEvent* event) const {
{ for (KeyboardOctave* oct : m_widgets) {
for (KeyboardOctave* oct : m_widgets)
{
QPoint localPos = oct->mapFromParent(event->pos()); QPoint localPos = oct->mapFromParent(event->pos());
if (oct->rect().contains(localPos)) if (oct->rect().contains(localPos))
return {oct->getOctave(), oct->getKey(localPos)}; return {oct->getOctave(), oct->getKey(localPos)};
@ -121,151 +79,110 @@ std::pair<int, int> KeyboardWidget::_getOctaveAndKey(QMouseEvent* event) const
return {-1, -1}; return {-1, -1};
} }
void KeyboardWidget::_startKey(int octave, int key) void KeyboardWidget::_startKey(int octave, int key) { emit notePressed(octave * 12 + key); }
{
emit notePressed(octave * 12 + key);
}
void KeyboardWidget::_stopKey() void KeyboardWidget::_stopKey() { emit noteReleased(); }
{
emit noteReleased();
}
void KeyboardWidget::_moveOnKey(int octave, int key) void KeyboardWidget::_moveOnKey(int octave, int key) {
{ if (m_lastOctave != octave || m_lastKey != key) {
if (m_lastOctave != octave || m_lastKey != key)
{
m_lastOctave = octave; m_lastOctave = octave;
m_lastKey = key; m_lastKey = key;
if (m_statusFocus) if (m_statusFocus)
m_statusFocus->setMessage(QStringLiteral("%1%2 (%3)"). m_statusFocus->setMessage(
arg(KeyStrings[key]).arg(octave - 1).arg(octave * 12 + key)); QStringLiteral("%1%2 (%3)").arg(KeyStrings[key]).arg(octave - 1).arg(octave * 12 + key));
if (m_holding) if (m_holding)
_startKey(octave, key); _startKey(octave, key);
} }
} }
void KeyboardWidget::_pressOnKey(int octave, int key) void KeyboardWidget::_pressOnKey(int octave, int key) {
{
_moveOnKey(octave, key); _moveOnKey(octave, key);
m_holding = true; m_holding = true;
_startKey(octave, key); _startKey(octave, key);
} }
void KeyboardWidget::mouseMoveEvent(QMouseEvent* event) void KeyboardWidget::mouseMoveEvent(QMouseEvent* event) {
{
std::pair<int, int> ok = _getOctaveAndKey(event); std::pair<int, int> ok = _getOctaveAndKey(event);
if (ok.first != -1 && ok.second != -1) if (ok.first != -1 && ok.second != -1)
_moveOnKey(ok.first, ok.second); _moveOnKey(ok.first, ok.second);
} }
void KeyboardWidget::mousePressEvent(QMouseEvent* event) void KeyboardWidget::mousePressEvent(QMouseEvent* event) {
{
std::pair<int, int> ok = _getOctaveAndKey(event); std::pair<int, int> ok = _getOctaveAndKey(event);
if (ok.first != -1 && ok.second != -1) if (ok.first != -1 && ok.second != -1)
_pressOnKey(ok.first, ok.second); _pressOnKey(ok.first, ok.second);
} }
void KeyboardWidget::mouseReleaseEvent(QMouseEvent* event) void KeyboardWidget::mouseReleaseEvent(QMouseEvent* event) {
{
_stopKey(); _stopKey();
m_holding = false; m_holding = false;
} }
void KeyboardWidget::enterEvent(QEvent* event) void KeyboardWidget::enterEvent(QEvent* event) {
{
if (m_statusFocus) if (m_statusFocus)
m_statusFocus->enter(); m_statusFocus->enter();
} }
void KeyboardWidget::leaveEvent(QEvent* event) void KeyboardWidget::leaveEvent(QEvent* event) {
{
if (m_statusFocus) if (m_statusFocus)
m_statusFocus->exit(); m_statusFocus->exit();
} }
void KeyboardWidget::wheelEvent(QWheelEvent* event) void KeyboardWidget::wheelEvent(QWheelEvent* event) {
{ if (QScrollArea* scroll = qobject_cast<QScrollArea*>(parentWidget()->parentWidget())) {
if (QScrollArea* scroll = qobject_cast<QScrollArea*>(parentWidget()->parentWidget()))
{
/* Send wheel event directly to the scroll bar */ /* Send wheel event directly to the scroll bar */
QApplication::sendEvent(scroll->horizontalScrollBar(), event); QApplication::sendEvent(scroll->horizontalScrollBar(), event);
} }
} }
void KeyboardWidget::showEvent(QShowEvent* event) void KeyboardWidget::showEvent(QShowEvent* event) {
{ if (QScrollArea* scroll = qobject_cast<QScrollArea*>(parentWidget()->parentWidget())) {
if (QScrollArea* scroll = qobject_cast<QScrollArea*>(parentWidget()->parentWidget()))
{
/* Scroll to C1 */ /* Scroll to C1 */
scroll->ensureVisible(141 * 2 + scroll->width(), 0, 0, 0); scroll->ensureVisible(141 * 2 + scroll->width(), 0, 0, 0);
} }
} }
KeyboardSlider::KeyboardSlider(QWidget* parent) KeyboardSlider::KeyboardSlider(QWidget* parent) : QSlider(parent) {}
: QSlider(parent)
{}
void KeyboardSlider::enterEvent(QEvent* event) void KeyboardSlider::enterEvent(QEvent* event) {
{
if (m_statusFocus) if (m_statusFocus)
m_statusFocus->enter(); m_statusFocus->enter();
} }
void KeyboardSlider::leaveEvent(QEvent* event) void KeyboardSlider::leaveEvent(QEvent* event) {
{
if (m_statusFocus) if (m_statusFocus)
m_statusFocus->exit(); m_statusFocus->exit();
} }
void KeyboardSlider::setStatusFocus(StatusBarFocus* statusFocus) void KeyboardSlider::setStatusFocus(StatusBarFocus* statusFocus) {
{
m_statusFocus = statusFocus; m_statusFocus = statusFocus;
QString str = stringOfValue(value()); QString str = stringOfValue(value());
m_statusFocus->setMessage(str); m_statusFocus->setMessage(str);
setToolTip(str); setToolTip(str);
} }
void KeyboardSlider::sliderChange(SliderChange change) void KeyboardSlider::sliderChange(SliderChange change) {
{
QSlider::sliderChange(change); QSlider::sliderChange(change);
if (m_statusFocus && change == QAbstractSlider::SliderValueChange) if (m_statusFocus && change == QAbstractSlider::SliderValueChange) {
{
QString str = stringOfValue(value()); QString str = stringOfValue(value());
m_statusFocus->setMessage(str); m_statusFocus->setMessage(str);
setToolTip(str); setToolTip(str);
} }
} }
VelocitySlider::VelocitySlider(QWidget* parent) VelocitySlider::VelocitySlider(QWidget* parent) : KeyboardSlider(parent) {}
: KeyboardSlider(parent)
{}
QString VelocitySlider::stringOfValue(int value) const QString VelocitySlider::stringOfValue(int value) const { return tr("Velocity: %1").arg(value); }
{
return tr("Velocity: %1").arg(value);
}
ModulationSlider::ModulationSlider(QWidget* parent) ModulationSlider::ModulationSlider(QWidget* parent) : KeyboardSlider(parent) {}
: KeyboardSlider(parent)
{}
QString ModulationSlider::stringOfValue(int value) const QString ModulationSlider::stringOfValue(int value) const { return tr("Modulation: %1").arg(value); }
{
return tr("Modulation: %1").arg(value);
}
PitchSlider::PitchSlider(QWidget* parent) PitchSlider::PitchSlider(QWidget* parent) : KeyboardSlider(parent) {}
: KeyboardSlider(parent)
{}
QString PitchSlider::stringOfValue(int value) const QString PitchSlider::stringOfValue(int value) const { return tr("Pitch: %1").arg(value / 2048.0, 0, 'g', 2); }
{
return tr("Pitch: %1").arg(value / 2048.0, 0, 'g', 2);
}
void PitchSlider::mouseReleaseEvent(QMouseEvent *ev) void PitchSlider::mouseReleaseEvent(QMouseEvent* ev) {
{
KeyboardSlider::mouseReleaseEvent(ev); KeyboardSlider::mouseReleaseEvent(ev);
setValue(0); setValue(0);
} }

View File

@ -15,22 +15,21 @@ extern const int SharpKeyNumbers[5];
class KeyboardWidget; class KeyboardWidget;
class KeyboardOctave : public QSvgWidget class KeyboardOctave : public QSvgWidget {
{
Q_OBJECT Q_OBJECT
int m_octave; int m_octave;
QRectF m_natural[7]; QRectF m_natural[7];
QRectF m_sharp[5]; QRectF m_sharp[5];
QTransform m_widgetToSvg; QTransform m_widgetToSvg;
public: public:
explicit KeyboardOctave(int octave, const QString& svgPath, QWidget* parent = Q_NULLPTR); explicit KeyboardOctave(int octave, const QString& svgPath, QWidget* parent = Q_NULLPTR);
int getOctave() const { return m_octave; } int getOctave() const { return m_octave; }
int getKey(const QPoint& localPos) const; int getKey(const QPoint& localPos) const;
void resizeEvent(QResizeEvent *event); void resizeEvent(QResizeEvent* event);
}; };
class KeyboardWidget : public QWidget class KeyboardWidget : public QWidget {
{
Q_OBJECT Q_OBJECT
KeyboardOctave* m_widgets[11]; KeyboardOctave* m_widgets[11];
StatusBarFocus* m_statusFocus = nullptr; StatusBarFocus* m_statusFocus = nullptr;
@ -53,20 +52,20 @@ public:
void mouseReleaseEvent(QMouseEvent* event); void mouseReleaseEvent(QMouseEvent* event);
void enterEvent(QEvent* event); void enterEvent(QEvent* event);
void leaveEvent(QEvent* event); void leaveEvent(QEvent* event);
void wheelEvent(QWheelEvent *event); void wheelEvent(QWheelEvent* event);
void showEvent(QShowEvent *event); void showEvent(QShowEvent* event);
signals: signals:
void notePressed(int key); void notePressed(int key);
void noteReleased(); void noteReleased();
}; };
class KeyboardSlider : public QSlider class KeyboardSlider : public QSlider {
{
Q_OBJECT Q_OBJECT
protected: protected:
StatusBarFocus* m_statusFocus = nullptr; StatusBarFocus* m_statusFocus = nullptr;
virtual QString stringOfValue(int value) const = 0; virtual QString stringOfValue(int value) const = 0;
public: public:
explicit KeyboardSlider(QWidget* parent = Q_NULLPTR); explicit KeyboardSlider(QWidget* parent = Q_NULLPTR);
void enterEvent(QEvent* event); void enterEvent(QEvent* event);
@ -75,30 +74,28 @@ public:
void sliderChange(SliderChange change); void sliderChange(SliderChange change);
}; };
class VelocitySlider : public KeyboardSlider class VelocitySlider : public KeyboardSlider {
{
Q_OBJECT Q_OBJECT
QString stringOfValue(int value) const; QString stringOfValue(int value) const;
public: public:
explicit VelocitySlider(QWidget* parent = Q_NULLPTR); explicit VelocitySlider(QWidget* parent = Q_NULLPTR);
}; };
class ModulationSlider : public KeyboardSlider class ModulationSlider : public KeyboardSlider {
{
Q_OBJECT Q_OBJECT
QString stringOfValue(int value) const; QString stringOfValue(int value) const;
public: public:
explicit ModulationSlider(QWidget* parent = Q_NULLPTR); explicit ModulationSlider(QWidget* parent = Q_NULLPTR);
}; };
class PitchSlider : public KeyboardSlider class PitchSlider : public KeyboardSlider {
{ Q_OBJECT
Q_OBJECT
QString stringOfValue(int value) const; QString stringOfValue(int value) const;
public: public:
explicit PitchSlider(QWidget* parent = Q_NULLPTR); explicit PitchSlider(QWidget* parent = Q_NULLPTR);
void mouseReleaseEvent(QMouseEvent *ev); void mouseReleaseEvent(QMouseEvent* ev);
void wheelEvent(QWheelEvent* ev) { ev->ignore(); } void wheelEvent(QWheelEvent* ev) { ev->ignore(); }
}; };

View File

@ -5,131 +5,59 @@
#include <QPainter> #include <QPainter>
#include <QScrollBar> #include <QScrollBar>
static const int HueTable[] = static const int HueTable[] = {0, 30, 60, 80, 120, 170, 200, 240, 280, 320};
{
0, 30, 60, 80, 120, 170, 200, 240, 280, 320
};
static const int SaturationTable[] = static const int SaturationTable[] = {255, 255, 255, 255, 255, 127, 127, 127, 127, 127, 63, 63, 63};
{
255, 255, 255, 255, 255, 127, 127, 127, 127, 127, 63, 63, 63
};
static const int ValueTable[] = static const int ValueTable[] = {240, 200, 160, 120, 80, 240, 200, 160, 120, 80, 240, 200, 160};
{
240, 200, 160, 120, 80, 240, 200, 160, 120, 80, 240, 200, 160
};
static const QPoint PointTable[] = static const QPoint PointTable[] = {{21, 180}, {41, 104}, {61, 180}, {86, 104}, {101, 180}, {141, 180},
{ {156, 104}, {181, 180}, {201, 104}, {221, 180}, {246, 104}, {261, 180}};
{21, 180},
{41, 104},
{61, 180},
{86, 104},
{101, 180},
{141, 180},
{156, 104},
{181, 180},
{201, 104},
{221, 180},
{246, 104},
{261, 180}
};
static const int RadiusTable[] = static const int RadiusTable[] = {14, 10, 14, 10, 14, 14, 10, 14, 10, 14, 10, 14};
{
14,
10,
14,
10,
14,
14,
10,
14,
10,
14,
10,
14
};
static const QColor PenColorTable[] = static const QColor PenColorTable[] = {Qt::black, Qt::white, Qt::black, Qt::white, Qt::black, Qt::black,
{ Qt::white, Qt::black, Qt::white, Qt::black, Qt::white, Qt::black};
Qt::black,
Qt::white,
Qt::black,
Qt::white,
Qt::black,
Qt::black,
Qt::white,
Qt::black,
Qt::white,
Qt::black,
Qt::white,
Qt::black
};
static const QColor NeutralColorTable[] = static const QColor NeutralColorTable[] = {Qt::white, Qt::black, Qt::white, Qt::black, Qt::white, Qt::white,
{ Qt::black, Qt::white, Qt::black, Qt::white, Qt::black, Qt::white};
Qt::white,
Qt::black,
Qt::white,
Qt::black,
Qt::white,
Qt::white,
Qt::black,
Qt::white,
Qt::black,
Qt::white,
Qt::black,
Qt::white
};
PaintButton::PaintButton(QWidget* parent) PaintButton::PaintButton(QWidget* parent) : QPushButton(parent) {
: QPushButton(parent)
{
setIcon(QIcon(QStringLiteral(":/icons/IconPaintbrush.svg"))); setIcon(QIcon(QStringLiteral(":/icons/IconPaintbrush.svg")));
setIconSize(QSize(26, 26)); setIconSize(QSize(26, 26));
setFixedSize(46, 46); setFixedSize(46, 46);
setToolTip(tr("Activate brush to apply values to keys")); setToolTip(tr("Activate brush to apply values to keys"));
} }
KeymapEditor* KeymapView::getEditor() const KeymapEditor* KeymapView::getEditor() const {
{
return qobject_cast<KeymapEditor*>(parentWidget()->parentWidget()->parentWidget()); return qobject_cast<KeymapEditor*>(parentWidget()->parentWidget()->parentWidget());
} }
void KeymapView::loadData(ProjectModel::KeymapNode* node) void KeymapView::loadData(ProjectModel::KeymapNode* node) { m_node = node; }
{
m_node = node;
}
void KeymapView::unloadData() void KeymapView::unloadData() {
{
m_node.reset(); m_node.reset();
std::fill(std::begin(m_keyPalettes), std::end(m_keyPalettes), -1); std::fill(std::begin(m_keyPalettes), std::end(m_keyPalettes), -1);
} }
ProjectModel::INode* KeymapView::currentNode() const ProjectModel::INode* KeymapView::currentNode() const { return m_node.get(); }
{
return m_node.get();
}
void KeymapView::drawKey(QPainter& painter, const QRect& octaveRect, qreal penWidth, void KeymapView::drawKey(QPainter& painter, const QRect& octaveRect, qreal penWidth, const QColor* keyPalette, int o,
const QColor* keyPalette, int o, int k) const int k) const {
{
int keyIdx = o * 12 + k; int keyIdx = o * 12 + k;
int keyPalIdx = m_keyPalettes[keyIdx]; int keyPalIdx = m_keyPalettes[keyIdx];
painter.setPen(QPen(PenColorTable[k], penWidth)); painter.setPen(QPen(PenColorTable[k], penWidth));
painter.setBrush(keyPalIdx < 0 ? NeutralColorTable[k] : keyPalette[keyPalIdx]); painter.setBrush(keyPalIdx < 0 ? NeutralColorTable[k] : keyPalette[keyPalIdx]);
painter.drawEllipse(PointTable[k] + octaveRect.topLeft(), RadiusTable[k], RadiusTable[k]); painter.drawEllipse(PointTable[k] + octaveRect.topLeft(), RadiusTable[k], RadiusTable[k]);
painter.setTransform(QTransform().translate( painter.setTransform(
PointTable[k].x() + octaveRect.left() - 13, PointTable[k].y() + octaveRect.top() - 20).rotate(-90.0)); QTransform()
.translate(PointTable[k].x() + octaveRect.left() - 13, PointTable[k].y() + octaveRect.top() - 20)
.rotate(-90.0));
painter.drawStaticText(QPointF{}, m_keyTexts[keyIdx]); painter.drawStaticText(QPointF{}, m_keyTexts[keyIdx]);
painter.setTransform(QTransform()); painter.setTransform(QTransform());
} }
void KeymapView::paintEvent(QPaintEvent* ev) void KeymapView::paintEvent(QPaintEvent* ev) {
{
QPainter painter(this); QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing); painter.setRenderHint(QPainter::Antialiasing);
@ -140,32 +68,25 @@ void KeymapView::paintEvent(QPaintEvent* ev)
painter.setFont(m_keyFont); painter.setFont(m_keyFont);
int kbY = height() / 2 - 100; int kbY = height() / 2 - 100;
for (int o = 0; o < 10; ++o) for (int o = 0; o < 10; ++o) {
{
QRect thisRect(o * 280, kbY, 280, 200); QRect thisRect(o * 280, kbY, 280, 200);
if (ev->rect().intersects(thisRect)) if (ev->rect().intersects(thisRect)) {
{
m_octaveRenderer.render(&painter, thisRect); m_octaveRenderer.render(&painter, thisRect);
for (int k = 0; k < 12; ++k) for (int k = 0; k < 12; ++k)
drawKey(painter, thisRect, penWidth, keyPalette, o, k); drawKey(painter, thisRect, penWidth, keyPalette, o, k);
} }
} }
QRect thisRect(2800, kbY, 202, 200); QRect thisRect(2800, kbY, 202, 200);
if (ev->rect().intersects(thisRect)) if (ev->rect().intersects(thisRect)) {
{
m_lastOctaveRenderer.render(&painter, thisRect); m_lastOctaveRenderer.render(&painter, thisRect);
for (int k = 0; k < 8; ++k) for (int k = 0; k < 8; ++k)
drawKey(painter, thisRect, penWidth, keyPalette, 10, k); drawKey(painter, thisRect, penWidth, keyPalette, 10, k);
} }
} }
void KeymapView::mousePressEvent(QMouseEvent* ev) void KeymapView::mousePressEvent(QMouseEvent* ev) { mouseMoveEvent(ev); }
{
mouseMoveEvent(ev);
}
int KeymapView::getKey(const QPoint& localPos) const int KeymapView::getKey(const QPoint& localPos) const {
{
QPointF localPoint = m_widgetToSvg.map(localPos); QPointF localPoint = m_widgetToSvg.map(localPos);
for (int i = 0; i < 5; ++i) for (int i = 0; i < 5; ++i)
if (m_sharp[i].contains(localPoint)) if (m_sharp[i].contains(localPoint))
@ -176,27 +97,24 @@ int KeymapView::getKey(const QPoint& localPos) const
return -1; return -1;
} }
void KeymapView::mouseMoveEvent(QMouseEvent* ev) void KeymapView::mouseMoveEvent(QMouseEvent* ev) {
{
int octave = ev->x() / 280; int octave = ev->x() / 280;
int key = getKey(ev->pos() - QPoint(octave * 280, height() / 2 - 100)); int key = getKey(ev->pos() - QPoint(octave * 280, height() / 2 - 100));
if (octave >= 0 && key >= 0) if (octave >= 0 && key >= 0)
getEditor()->touchKey(octave * 12 + key, ev->modifiers() & Qt::ShiftModifier); getEditor()->touchKey(octave * 12 + key, ev->modifiers() & Qt::ShiftModifier);
} }
void KeymapView::wheelEvent(QWheelEvent* event) void KeymapView::wheelEvent(QWheelEvent* event) {
{ if (QScrollArea* scroll = qobject_cast<QScrollArea*>(parentWidget()->parentWidget())) {
if (QScrollArea* scroll = qobject_cast<QScrollArea*>(parentWidget()->parentWidget()))
{
/* Send wheel event directly to the scroll bar */ /* Send wheel event directly to the scroll bar */
QApplication::sendEvent(scroll->horizontalScrollBar(), event); QApplication::sendEvent(scroll->horizontalScrollBar(), event);
} }
} }
KeymapView::KeymapView(QWidget* parent) KeymapView::KeymapView(QWidget* parent)
: QWidget(parent), m_octaveRenderer(QStringLiteral(":/bg/keyboard.svg")), : QWidget(parent)
m_lastOctaveRenderer(QStringLiteral(":/bg/keyboard_last.svg")) , m_octaveRenderer(QStringLiteral(":/bg/keyboard.svg"))
{ , m_lastOctaveRenderer(QStringLiteral(":/bg/keyboard_last.svg")) {
setMinimumWidth(3002); setMinimumWidth(3002);
int k = 0; int k = 0;
@ -208,32 +126,25 @@ KeymapView::KeymapView(QWidget* parent)
for (int i = 0; i < 7; ++i) for (int i = 0; i < 7; ++i)
if (m_octaveRenderer.elementExists(NaturalKeyNames[i])) if (m_octaveRenderer.elementExists(NaturalKeyNames[i]))
m_natural[i] = m_octaveRenderer.matrixForElement(NaturalKeyNames[i]). m_natural[i] = m_octaveRenderer.matrixForElement(NaturalKeyNames[i])
mapRect(m_octaveRenderer.boundsOnElement(NaturalKeyNames[i])); .mapRect(m_octaveRenderer.boundsOnElement(NaturalKeyNames[i]));
for (int i = 0; i < 5; ++i) for (int i = 0; i < 5; ++i)
if (m_octaveRenderer.elementExists(SharpKeyNames[i])) if (m_octaveRenderer.elementExists(SharpKeyNames[i]))
m_sharp[i] = m_octaveRenderer.matrixForElement(SharpKeyNames[i]). m_sharp[i] = m_octaveRenderer.matrixForElement(SharpKeyNames[i])
mapRect(m_octaveRenderer.boundsOnElement(SharpKeyNames[i])); .mapRect(m_octaveRenderer.boundsOnElement(SharpKeyNames[i]));
m_widgetToSvg = RectToRect(QRect(0, 0, 280, 200), m_octaveRenderer.viewBoxF()); m_widgetToSvg = RectToRect(QRect(0, 0, 280, 200), m_octaveRenderer.viewBoxF());
} }
KeymapEditor* KeymapControls::getEditor() const KeymapEditor* KeymapControls::getEditor() const { return qobject_cast<KeymapEditor*>(parentWidget()); }
{
return qobject_cast<KeymapEditor*>(parentWidget());
}
void KeymapControls::setPaintIdx(int idx) void KeymapControls::setPaintIdx(int idx) {
{
QPalette palette = m_paintButton->palette(); QPalette palette = m_paintButton->palette();
if (idx < 0) if (idx < 0) {
{
palette.setColor(QPalette::Background, QWidget::palette().color(QPalette::Background)); palette.setColor(QPalette::Background, QWidget::palette().color(QPalette::Background));
palette.setColor(QPalette::Button, QWidget::palette().color(QPalette::Button)); palette.setColor(QPalette::Button, QWidget::palette().color(QPalette::Button));
} } else {
else
{
const QColor* keyPalette = getEditor()->m_paintPalette; const QColor* keyPalette = getEditor()->m_paintPalette;
palette.setColor(QPalette::Background, keyPalette[idx]); palette.setColor(QPalette::Background, keyPalette[idx]);
palette.setColor(QPalette::Button, keyPalette[idx].darker(300)); palette.setColor(QPalette::Button, keyPalette[idx].darker(300));
@ -241,20 +152,16 @@ void KeymapControls::setPaintIdx(int idx)
m_paintButton->setPalette(palette); m_paintButton->setPalette(palette);
} }
void KeymapControls::setKeymap(const amuse::Keymap& km) void KeymapControls::setKeymap(const amuse::Keymap& km) {
{
m_enableUpdate = false; m_enableUpdate = false;
int idx = m_macro->collection()->indexOfId(km.macro.id); int idx = m_macro->collection()->indexOfId(km.macro.id);
m_macro->setCurrentIndex(idx + 1); m_macro->setCurrentIndex(idx + 1);
m_transpose->setValue(km.transpose); m_transpose->setValue(km.transpose);
if (km.pan == -128) if (km.pan == -128) {
{
m_pan->setDisabled(true); m_pan->setDisabled(true);
m_pan->setValue(true); m_pan->setValue(true);
m_surround->setChecked(true); m_surround->setChecked(true);
} } else {
else
{
m_pan->setEnabled(true); m_pan->setEnabled(true);
m_pan->setValue(km.pan); m_pan->setValue(km.pan);
m_surround->setChecked(false); m_surround->setChecked(false);
@ -263,11 +170,10 @@ void KeymapControls::setKeymap(const amuse::Keymap& km)
m_enableUpdate = true; m_enableUpdate = true;
} }
void KeymapControls::loadData(ProjectModel::KeymapNode* node) void KeymapControls::loadData(ProjectModel::KeymapNode* node) {
{
m_enableUpdate = false; m_enableUpdate = false;
m_macro->setCollection(g_MainWindow->projectModel()->getGroupNode(node)-> m_macro->setCollection(
getCollectionOfType(ProjectModel::INode::Type::SoundMacro)); g_MainWindow->projectModel()->getGroupNode(node)->getCollectionOfType(ProjectModel::INode::Type::SoundMacro));
m_macro->setDisabled(false); m_macro->setDisabled(false);
m_transpose->setDisabled(false); m_transpose->setDisabled(false);
m_transpose->setValue(0); m_transpose->setValue(0);
@ -282,8 +188,7 @@ void KeymapControls::loadData(ProjectModel::KeymapNode* node)
m_enableUpdate = true; m_enableUpdate = true;
} }
void KeymapControls::unloadData() void KeymapControls::unloadData() {
{
m_enableUpdate = false; m_enableUpdate = false;
m_macro->setCollection(nullptr); m_macro->setCollection(nullptr);
m_macro->setDisabled(true); m_macro->setDisabled(true);
@ -296,22 +201,17 @@ void KeymapControls::unloadData()
m_enableUpdate = true; m_enableUpdate = true;
} }
void KeymapControls::controlChanged() void KeymapControls::controlChanged() {
{ if (m_enableUpdate) {
if (m_enableUpdate)
{
amuse::Keymap km; amuse::Keymap km;
km.macro.id = m_macro->currentIndex() == 0 ? amuse::SoundMacroId{} : km.macro.id = m_macro->currentIndex() == 0 ? amuse::SoundMacroId{}
m_macro->collection()->idOfIndex(m_macro->currentIndex() - 1); : m_macro->collection()->idOfIndex(m_macro->currentIndex() - 1);
km.transpose = int8_t(m_transpose->value()); km.transpose = int8_t(m_transpose->value());
km.pan = int8_t(m_pan->value()); km.pan = int8_t(m_pan->value());
if (m_surround->isChecked()) if (m_surround->isChecked()) {
{
km.pan = -128; km.pan = -128;
m_pan->setDisabled(true); m_pan->setDisabled(true);
} } else {
else
{
m_pan->setEnabled(true); m_pan->setEnabled(true);
} }
km.prioOffset = int8_t(m_prioOffset->value()); km.prioOffset = int8_t(m_prioOffset->value());
@ -319,26 +219,20 @@ void KeymapControls::controlChanged()
} }
} }
void KeymapControls::paintButtonPressed() void KeymapControls::paintButtonPressed() {
{
KeymapEditor* editor = getEditor(); KeymapEditor* editor = getEditor();
if (!editor->m_inPaint) if (!editor->m_inPaint) {
{
editor->setCursor(QCursor(QPixmap(QStringLiteral(":/icons/IconPaintbrush.svg")), 2, 30)); editor->setCursor(QCursor(QPixmap(QStringLiteral(":/icons/IconPaintbrush.svg")), 2, 30));
editor->m_inPaint = true; editor->m_inPaint = true;
m_paintButton->setDown(true); m_paintButton->setDown(true);
} } else {
else
{
editor->unsetCursor(); editor->unsetCursor();
editor->m_inPaint = false; editor->m_inPaint = false;
m_paintButton->setDown(false); m_paintButton->setDown(false);
} }
} }
KeymapControls::KeymapControls(QWidget* parent) KeymapControls::KeymapControls(QWidget* parent) : QFrame(parent) {
: QFrame(parent)
{
setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
setFixedHeight(100); setFixedHeight(100);
setFrameShape(QFrame::StyledPanel); setFrameShape(QFrame::StyledPanel);
@ -417,23 +311,18 @@ KeymapControls::KeymapControls(QWidget* parent)
setLayout(mainLayout); setLayout(mainLayout);
} }
void KeymapEditor::_touch() void KeymapEditor::_touch() {
{
if (m_controlKeymap.macro.id == 0xffff) if (m_controlKeymap.macro.id == 0xffff)
m_controls->setPaintIdx(-1); m_controls->setPaintIdx(-1);
else else
m_controls->setPaintIdx(getConfigIdx(m_controlKeymap.configKey())); m_controls->setPaintIdx(getConfigIdx(m_controlKeymap.configKey()));
} }
void KeymapEditor::touchKey(int key, bool bulk) void KeymapEditor::touchKey(int key, bool bulk) {
{ if (m_inPaint) {
if (m_inPaint) if (bulk) {
{
if (bulk)
{
uint64_t refKey = (*m_kmView->m_node->m_obj)[key].configKey(); uint64_t refKey = (*m_kmView->m_node->m_obj)[key].configKey();
for (int i = 0; i < 128; ++i) for (int i = 0; i < 128; ++i) {
{
amuse::Keymap& km = (*m_kmView->m_node->m_obj)[i]; amuse::Keymap& km = (*m_kmView->m_node->m_obj)[i];
if (km.configKey() != refKey) if (km.configKey() != refKey)
continue; continue;
@ -445,9 +334,7 @@ void KeymapEditor::touchKey(int key, bool bulk)
else else
m_kmView->m_keyPalettes[i] = allocateConfigIdx(km.configKey()); m_kmView->m_keyPalettes[i] = allocateConfigIdx(km.configKey());
} }
} } else {
else
{
amuse::Keymap& km = (*m_kmView->m_node->m_obj)[key]; amuse::Keymap& km = (*m_kmView->m_node->m_obj)[key];
if (km.macro.id != 0xffff) if (km.macro.id != 0xffff)
deallocateConfigIdx(km.configKey()); deallocateConfigIdx(km.configKey());
@ -459,9 +346,7 @@ void KeymapEditor::touchKey(int key, bool bulk)
} }
m_kmView->update(); m_kmView->update();
} } else {
else
{
amuse::Keymap& km = (*m_kmView->m_node->m_obj)[key]; amuse::Keymap& km = (*m_kmView->m_node->m_obj)[key];
m_controlKeymap = km; m_controlKeymap = km;
m_controls->setKeymap(km); m_controls->setKeymap(km);
@ -469,23 +354,19 @@ void KeymapEditor::touchKey(int key, bool bulk)
} }
} }
void KeymapEditor::touchControl(const amuse::Keymap& km) void KeymapEditor::touchControl(const amuse::Keymap& km) {
{
m_controlKeymap = km; m_controlKeymap = km;
_touch(); _touch();
} }
int KeymapEditor::allocateConfigIdx(uint64_t key) int KeymapEditor::allocateConfigIdx(uint64_t key) {
{
auto search = m_configToIdx.find(key); auto search = m_configToIdx.find(key);
if (search != m_configToIdx.end()) if (search != m_configToIdx.end()) {
{
++search->second.second; ++search->second.second;
return search->second.first; return search->second.first;
} }
for (int i = 0; i < 129; ++i) for (int i = 0; i < 129; ++i)
if (!m_idxBitmap[i]) if (!m_idxBitmap[i]) {
{
m_configToIdx[key] = std::make_pair(i, 1); m_configToIdx[key] = std::make_pair(i, 1);
m_idxBitmap.set(i); m_idxBitmap.set(i);
return i; return i;
@ -493,14 +374,11 @@ int KeymapEditor::allocateConfigIdx(uint64_t key)
Q_UNREACHABLE(); Q_UNREACHABLE();
} }
void KeymapEditor::deallocateConfigIdx(uint64_t key) void KeymapEditor::deallocateConfigIdx(uint64_t key) {
{
auto search = m_configToIdx.find(key); auto search = m_configToIdx.find(key);
if (search != m_configToIdx.end()) if (search != m_configToIdx.end()) {
{
--search->second.second; --search->second.second;
if (search->second.second == 0) if (search->second.second == 0) {
{
m_idxBitmap.reset(search->second.first); m_idxBitmap.reset(search->second.first);
m_configToIdx.erase(search); m_configToIdx.erase(search);
} }
@ -509,8 +387,7 @@ void KeymapEditor::deallocateConfigIdx(uint64_t key)
Q_UNREACHABLE(); Q_UNREACHABLE();
} }
int KeymapEditor::getConfigIdx(uint64_t key) const int KeymapEditor::getConfigIdx(uint64_t key) const {
{
auto search = m_configToIdx.find(key); auto search = m_configToIdx.find(key);
if (search != m_configToIdx.end()) if (search != m_configToIdx.end())
return search->second.first; return search->second.first;
@ -520,15 +397,12 @@ int KeymapEditor::getConfigIdx(uint64_t key) const
Q_UNREACHABLE(); Q_UNREACHABLE();
} }
bool KeymapEditor::loadData(ProjectModel::KeymapNode* node) bool KeymapEditor::loadData(ProjectModel::KeymapNode* node) {
{ if (m_kmView->m_node.get() != node) {
if (m_kmView->m_node.get() != node)
{
m_configToIdx.clear(); m_configToIdx.clear();
m_idxBitmap.reset(); m_idxBitmap.reset();
for (int i = 0; i < 128; ++i) for (int i = 0; i < 128; ++i) {
{
amuse::Keymap& km = (*node->m_obj)[i]; amuse::Keymap& km = (*node->m_obj)[i];
if (km.macro.id == 0xffff) if (km.macro.id == 0xffff)
m_kmView->m_keyPalettes[i] = -1; m_kmView->m_keyPalettes[i] = -1;
@ -548,8 +422,7 @@ bool KeymapEditor::loadData(ProjectModel::KeymapNode* node)
return true; return true;
} }
void KeymapEditor::unloadData() void KeymapEditor::unloadData() {
{
m_configToIdx.clear(); m_configToIdx.clear();
m_idxBitmap.reset(); m_idxBitmap.reset();
m_kmView->unloadData(); m_kmView->unloadData();
@ -560,17 +433,11 @@ void KeymapEditor::unloadData()
unsetCursor(); unsetCursor();
} }
ProjectModel::INode* KeymapEditor::currentNode() const ProjectModel::INode* KeymapEditor::currentNode() const { return m_kmView->currentNode(); }
{
return m_kmView->currentNode();
}
void KeymapEditor::keyPressEvent(QKeyEvent* event) void KeymapEditor::keyPressEvent(QKeyEvent* event) {
{ if (event->key() == Qt::Key_Escape) {
if (event->key() == Qt::Key_Escape) if (m_inPaint) {
{
if (m_inPaint)
{
m_inPaint = false; m_inPaint = false;
m_controls->m_paintButton->setDown(false); m_controls->m_paintButton->setDown(false);
unsetCursor(); unsetCursor();
@ -579,9 +446,7 @@ void KeymapEditor::keyPressEvent(QKeyEvent* event)
} }
KeymapEditor::KeymapEditor(QWidget* parent) KeymapEditor::KeymapEditor(QWidget* parent)
: EditorWidget(parent), m_scrollArea(new QScrollArea), : EditorWidget(parent), m_scrollArea(new QScrollArea), m_kmView(new KeymapView), m_controls(new KeymapControls) {
m_kmView(new KeymapView), m_controls(new KeymapControls)
{
int k = 0; int k = 0;
for (int i = 0; i < 13; ++i) for (int i = 0; i < 13; ++i)

View File

@ -13,9 +13,8 @@
class KeymapEditor; class KeymapEditor;
class PaintButton : public QPushButton class PaintButton : public QPushButton {
{ Q_OBJECT
Q_OBJECT
public: public:
explicit PaintButton(QWidget* parent = Q_NULLPTR); explicit PaintButton(QWidget* parent = Q_NULLPTR);
void mouseReleaseEvent(QMouseEvent* event) { event->ignore(); } void mouseReleaseEvent(QMouseEvent* event) { event->ignore(); }
@ -24,9 +23,8 @@ public:
void keyPressEvent(QKeyEvent* event) { event->ignore(); } void keyPressEvent(QKeyEvent* event) { event->ignore(); }
}; };
class KeymapView : public QWidget class KeymapView : public QWidget {
{ Q_OBJECT
Q_OBJECT
friend class KeymapControls; friend class KeymapControls;
friend class KeymapEditor; friend class KeymapEditor;
amuse::ObjToken<ProjectModel::KeymapNode> m_node; amuse::ObjToken<ProjectModel::KeymapNode> m_node;
@ -40,8 +38,9 @@ Q_OBJECT
int m_keyPalettes[128]; int m_keyPalettes[128];
KeymapEditor* getEditor() const; KeymapEditor* getEditor() const;
int getKey(const QPoint& localPos) const; int getKey(const QPoint& localPos) const;
void drawKey(QPainter& painter, const QRect& octaveRect, qreal penWidth, void drawKey(QPainter& painter, const QRect& octaveRect, qreal penWidth, const QColor* keyPalette, int o,
const QColor* keyPalette, int o, int k) const; int k) const;
public: public:
explicit KeymapView(QWidget* parent = Q_NULLPTR); explicit KeymapView(QWidget* parent = Q_NULLPTR);
void loadData(ProjectModel::KeymapNode* node); void loadData(ProjectModel::KeymapNode* node);
@ -54,9 +53,8 @@ public:
void wheelEvent(QWheelEvent* event); void wheelEvent(QWheelEvent* event);
}; };
class KeymapControls : public QFrame class KeymapControls : public QFrame {
{ Q_OBJECT
Q_OBJECT
friend class KeymapView; friend class KeymapView;
friend class KeymapEditor; friend class KeymapEditor;
FieldProjectNode* m_macro; FieldProjectNode* m_macro;
@ -69,6 +67,7 @@ Q_OBJECT
KeymapEditor* getEditor() const; KeymapEditor* getEditor() const;
void setPaintIdx(int idx); void setPaintIdx(int idx);
void setKeymap(const amuse::Keymap& km); void setKeymap(const amuse::Keymap& km);
public: public:
explicit KeymapControls(QWidget* parent = Q_NULLPTR); explicit KeymapControls(QWidget* parent = Q_NULLPTR);
void loadData(ProjectModel::KeymapNode* node); void loadData(ProjectModel::KeymapNode* node);
@ -78,9 +77,8 @@ public slots:
void paintButtonPressed(); void paintButtonPressed();
}; };
class KeymapEditor : public EditorWidget class KeymapEditor : public EditorWidget {
{ Q_OBJECT
Q_OBJECT
friend class KeymapView; friend class KeymapView;
friend class KeymapControls; friend class KeymapControls;
QScrollArea* m_scrollArea; QScrollArea* m_scrollArea;
@ -97,6 +95,7 @@ Q_OBJECT
int allocateConfigIdx(uint64_t key); int allocateConfigIdx(uint64_t key);
void deallocateConfigIdx(uint64_t key); void deallocateConfigIdx(uint64_t key);
int getConfigIdx(uint64_t key) const; int getConfigIdx(uint64_t key) const;
public: public:
explicit KeymapEditor(QWidget* parent = Q_NULLPTR); explicit KeymapEditor(QWidget* parent = Q_NULLPTR);
bool loadData(ProjectModel::KeymapNode* node); bool loadData(ProjectModel::KeymapNode* node);
@ -104,4 +103,3 @@ public:
ProjectModel::INode* currentNode() const; ProjectModel::INode* currentNode() const;
void keyPressEvent(QKeyEvent* event); void keyPressEvent(QKeyEvent* event);
}; };

View File

@ -4,22 +4,20 @@
#include <QScrollBar> #include <QScrollBar>
#include <QMimeData> #include <QMimeData>
class LayerDataChangeUndoCommand : public EditorUndoCommand class LayerDataChangeUndoCommand : public EditorUndoCommand {
{
QModelIndex m_index; QModelIndex m_index;
int m_undoVal, m_redoVal; int m_undoVal, m_redoVal;
bool m_undid = false; bool m_undid = false;
public: public:
explicit LayerDataChangeUndoCommand(ProjectModel::LayersNode* node, const QString& text, explicit LayerDataChangeUndoCommand(ProjectModel::LayersNode* node, const QString& text, QModelIndex index,
QModelIndex index, int redoVal) int redoVal)
: EditorUndoCommand(node, text), m_index(index), m_redoVal(redoVal) {} : EditorUndoCommand(node, text), m_index(index), m_redoVal(redoVal) {}
void undo() void undo() {
{
m_undid = true; m_undid = true;
amuse::LayerMapping& layer = (*static_cast<ProjectModel::LayersNode*>(m_node.get())->m_obj)[m_index.row()]; amuse::LayerMapping& layer = (*static_cast<ProjectModel::LayersNode*>(m_node.get())->m_obj)[m_index.row()];
switch (m_index.column()) switch (m_index.column()) {
{
case 0: case 0:
layer.macro.id = m_undoVal; layer.macro.id = m_undoVal;
break; break;
@ -50,12 +48,10 @@ public:
EditorUndoCommand::undo(); EditorUndoCommand::undo();
} }
void redo() void redo() {
{
amuse::LayerMapping& layer = (*static_cast<ProjectModel::LayersNode*>(m_node.get())->m_obj)[m_index.row()]; amuse::LayerMapping& layer = (*static_cast<ProjectModel::LayersNode*>(m_node.get())->m_obj)[m_index.row()];
switch (m_index.column()) switch (m_index.column()) {
{
case 0: case 0:
m_undoVal = layer.macro.id; m_undoVal = layer.macro.id;
layer.macro.id = m_redoVal; layer.macro.id = m_redoVal;
@ -97,11 +93,9 @@ public:
} }
}; };
SoundMacroDelegate::SoundMacroDelegate(QObject* parent) SoundMacroDelegate::SoundMacroDelegate(QObject* parent) : BaseObjectDelegate(parent) {}
: BaseObjectDelegate(parent) {}
ProjectModel::INode* SoundMacroDelegate::getNode(const QAbstractItemModel* __model, const QModelIndex& index) const ProjectModel::INode* SoundMacroDelegate::getNode(const QAbstractItemModel* __model, const QModelIndex& index) const {
{
const LayersModel* model = static_cast<const LayersModel*>(__model); const LayersModel* model = static_cast<const LayersModel*>(__model);
const amuse::LayerMapping& layer = (*model->m_node->m_obj)[index.row()]; const amuse::LayerMapping& layer = (*model->m_node->m_obj)[index.row()];
ProjectModel::GroupNode* group = g_MainWindow->projectModel()->getGroupNode(model->m_node.get()); ProjectModel::GroupNode* group = g_MainWindow->projectModel()->getGroupNode(model->m_node.get());
@ -109,8 +103,8 @@ ProjectModel::INode* SoundMacroDelegate::getNode(const QAbstractItemModel* __mod
return smColl->nodeOfId(layer.macro.id); return smColl->nodeOfId(layer.macro.id);
} }
QWidget* SoundMacroDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const QWidget* SoundMacroDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& option,
{ const QModelIndex& index) const {
const LayersModel* model = static_cast<const LayersModel*>(index.model()); const LayersModel* model = static_cast<const LayersModel*>(index.model());
ProjectModel::GroupNode* group = g_MainWindow->projectModel()->getGroupNode(model->m_node.get()); ProjectModel::GroupNode* group = g_MainWindow->projectModel()->getGroupNode(model->m_node.get());
EditorFieldProjectNode* cb = EditorFieldProjectNode* cb =
@ -119,8 +113,7 @@ QWidget* SoundMacroDelegate::createEditor(QWidget* parent, const QStyleOptionVie
return cb; return cb;
} }
void SoundMacroDelegate::setEditorData(QWidget* editor, const QModelIndex& index) const void SoundMacroDelegate::setEditorData(QWidget* editor, const QModelIndex& index) const {
{
const LayersModel* model = static_cast<const LayersModel*>(index.model()); const LayersModel* model = static_cast<const LayersModel*>(index.model());
const amuse::LayerMapping& layer = (*model->m_node->m_obj)[index.row()]; const amuse::LayerMapping& layer = (*model->m_node->m_obj)[index.row()];
ProjectModel::GroupNode* group = g_MainWindow->projectModel()->getGroupNode(model->m_node.get()); ProjectModel::GroupNode* group = g_MainWindow->projectModel()->getGroupNode(model->m_node.get());
@ -130,8 +123,7 @@ void SoundMacroDelegate::setEditorData(QWidget* editor, const QModelIndex& index
QApplication::postEvent(editor, new QEvent(QEvent::User)); QApplication::postEvent(editor, new QEvent(QEvent::User));
} }
void SoundMacroDelegate::setModelData(QWidget* editor, QAbstractItemModel* m, const QModelIndex& index) const void SoundMacroDelegate::setModelData(QWidget* editor, QAbstractItemModel* m, const QModelIndex& index) const {
{
const LayersModel* model = static_cast<const LayersModel*>(m); const LayersModel* model = static_cast<const LayersModel*>(m);
amuse::LayerMapping& layer = (*model->m_node->m_obj)[index.row()]; amuse::LayerMapping& layer = (*model->m_node->m_obj)[index.row()];
ProjectModel::GroupNode* group = g_MainWindow->projectModel()->getGroupNode(model->m_node.get()); ProjectModel::GroupNode* group = g_MainWindow->projectModel()->getGroupNode(model->m_node.get());
@ -142,32 +134,26 @@ void SoundMacroDelegate::setModelData(QWidget* editor, QAbstractItemModel* m, co
id = smColl->idOfIndex(idx - 1); id = smColl->idOfIndex(idx - 1);
if (layer.macro.id == id) if (layer.macro.id == id)
return; return;
g_MainWindow->pushUndoCommand(new LayerDataChangeUndoCommand(model->m_node.get(), g_MainWindow->pushUndoCommand(new LayerDataChangeUndoCommand(
tr("Change %1").arg(m->headerData(0, Qt::Horizontal).toString()), index, id.id)); model->m_node.get(), tr("Change %1").arg(m->headerData(0, Qt::Horizontal).toString()), index, id.id));
emit m->dataChanged(index, index, {Qt::DisplayRole, Qt::EditRole}); emit m->dataChanged(index, index, {Qt::DisplayRole, Qt::EditRole});
} }
void SoundMacroDelegate::smIndexChanged() void SoundMacroDelegate::smIndexChanged() { emit commitData(static_cast<QWidget*>(sender())); }
{
emit commitData(static_cast<QWidget*>(sender()));
}
void LayersModel::loadData(ProjectModel::LayersNode* node) void LayersModel::loadData(ProjectModel::LayersNode* node) {
{
beginResetModel(); beginResetModel();
m_node = node; m_node = node;
endResetModel(); endResetModel();
} }
void LayersModel::unloadData() void LayersModel::unloadData() {
{
beginResetModel(); beginResetModel();
m_node.reset(); m_node.reset();
endResetModel(); endResetModel();
} }
int LayersModel::rowCount(const QModelIndex& parent) const int LayersModel::rowCount(const QModelIndex& parent) const {
{
if (parent.isValid()) if (parent.isValid())
return 0; return 0;
if (!m_node) if (!m_node)
@ -175,27 +161,22 @@ int LayersModel::rowCount(const QModelIndex& parent) const
return int(m_node->m_obj->size()) + 1; return int(m_node->m_obj->size()) + 1;
} }
int LayersModel::columnCount(const QModelIndex& parent) const int LayersModel::columnCount(const QModelIndex& parent) const {
{
if (parent.isValid()) if (parent.isValid())
return 0; return 0;
return 8; return 8;
} }
QVariant LayersModel::data(const QModelIndex& index, int role) const QVariant LayersModel::data(const QModelIndex& index, int role) const {
{
if (!m_node) if (!m_node)
return QVariant(); return QVariant();
if (index.row() == m_node->m_obj->size()) if (index.row() == m_node->m_obj->size())
return QVariant(); return QVariant();
const amuse::LayerMapping& layer = (*m_node->m_obj)[index.row()]; const amuse::LayerMapping& layer = (*m_node->m_obj)[index.row()];
if (role == Qt::DisplayRole || role == Qt::EditRole) if (role == Qt::DisplayRole || role == Qt::EditRole) {
{ switch (index.column()) {
switch (index.column()) case 0: {
{
case 0:
{
ProjectModel::GroupNode* group = g_MainWindow->projectModel()->getGroupNode(m_node.get()); ProjectModel::GroupNode* group = g_MainWindow->projectModel()->getGroupNode(m_node.get());
ProjectModel::CollectionNode* smColl = group->getCollectionOfType(ProjectModel::INode::Type::SoundMacro); ProjectModel::CollectionNode* smColl = group->getCollectionOfType(ProjectModel::INode::Type::SoundMacro);
if (ProjectModel::BasePoolObjectNode* node = smColl->nodeOfId(layer.macro.id)) if (ProjectModel::BasePoolObjectNode* node = smColl->nodeOfId(layer.macro.id))
@ -224,14 +205,12 @@ QVariant LayersModel::data(const QModelIndex& index, int role) const
return QVariant(); return QVariant();
} }
bool LayersModel::setData(const QModelIndex& index, const QVariant& value, int role) bool LayersModel::setData(const QModelIndex& index, const QVariant& value, int role) {
{
if (!m_node || role != Qt::EditRole) if (!m_node || role != Qt::EditRole)
return false; return false;
const amuse::LayerMapping& layer = (*m_node->m_obj)[index.row()]; const amuse::LayerMapping& layer = (*m_node->m_obj)[index.row()];
switch (index.column()) switch (index.column()) {
{
case 0: case 0:
if (layer.macro.id == value.toInt()) if (layer.macro.id == value.toInt())
return false; return false;
@ -268,19 +247,16 @@ bool LayersModel::setData(const QModelIndex& index, const QVariant& value, int r
return false; return false;
} }
g_MainWindow->pushUndoCommand(new LayerDataChangeUndoCommand(m_node.get(), g_MainWindow->pushUndoCommand(new LayerDataChangeUndoCommand(
tr("Change %1").arg(headerData(index.column(), Qt::Horizontal).toString()), index, value.toInt())); m_node.get(), tr("Change %1").arg(headerData(index.column(), Qt::Horizontal).toString()), index, value.toInt()));
emit dataChanged(index, index, {Qt::DisplayRole, Qt::EditRole}); emit dataChanged(index, index, {Qt::DisplayRole, Qt::EditRole});
return false; return false;
} }
QVariant LayersModel::headerData(int section, Qt::Orientation orientation, int role) const QVariant LayersModel::headerData(int section, Qt::Orientation orientation, int role) const {
{ if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
if (orientation == Qt::Horizontal && role == Qt::DisplayRole) switch (section) {
{
switch (section)
{
case 0: case 0:
return tr("SoundMacro"); return tr("SoundMacro");
case 1: case 1:
@ -304,8 +280,7 @@ QVariant LayersModel::headerData(int section, Qt::Orientation orientation, int r
return QVariant(); return QVariant();
} }
Qt::ItemFlags LayersModel::flags(const QModelIndex& index) const Qt::ItemFlags LayersModel::flags(const QModelIndex& index) const {
{
if (!index.isValid()) if (!index.isValid())
return Qt::NoItemFlags; return Qt::NoItemFlags;
if (index.row() == m_node->m_obj->size()) if (index.row() == m_node->m_obj->size())
@ -313,27 +288,20 @@ Qt::ItemFlags LayersModel::flags(const QModelIndex& index) const
return Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled; return Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled;
} }
Qt::DropActions LayersModel::supportedDropActions() const Qt::DropActions LayersModel::supportedDropActions() const { return Qt::MoveAction; }
{
return Qt::MoveAction;
}
Qt::DropActions LayersModel::supportedDragActions() const Qt::DropActions LayersModel::supportedDragActions() const { return Qt::MoveAction; }
{
return Qt::MoveAction;
}
class LayerRowMoveCommand : public EditorUndoCommand class LayerRowMoveCommand : public EditorUndoCommand {
{
LayersTableView* m_view; LayersTableView* m_view;
int m_undoPos, m_redoPos, m_count; int m_undoPos, m_redoPos, m_count;
bool m_undid = false; bool m_undid = false;
public: public:
explicit LayerRowMoveCommand(ProjectModel::LayersNode* node, const QString& text, LayersTableView* view, explicit LayerRowMoveCommand(ProjectModel::LayersNode* node, const QString& text, LayersTableView* view, int undoPos,
int undoPos, int redoPos, int count) int redoPos, int count)
: EditorUndoCommand(node, text), m_view(view), m_undoPos(undoPos), m_redoPos(redoPos), m_count(count) {} : EditorUndoCommand(node, text), m_view(view), m_undoPos(undoPos), m_redoPos(redoPos), m_count(count) {}
void undo() void undo() {
{
m_undid = true; m_undid = true;
EditorUndoCommand::undo(); EditorUndoCommand::undo();
if (m_redoPos > m_undoPos) if (m_redoPos > m_undoPos)
@ -341,17 +309,15 @@ public:
else else
m_view->model()->moveRows(QModelIndex(), m_redoPos, m_count, QModelIndex(), m_undoPos + 1); m_view->model()->moveRows(QModelIndex(), m_redoPos, m_count, QModelIndex(), m_undoPos + 1);
} }
void redo() void redo() {
{
if (m_undid) if (m_undid)
EditorUndoCommand::redo(); EditorUndoCommand::redo();
m_view->model()->moveRows(QModelIndex(), m_undoPos, m_count, QModelIndex(), m_redoPos); m_view->model()->moveRows(QModelIndex(), m_undoPos, m_count, QModelIndex(), m_redoPos);
} }
}; };
bool LayersModel::dropMimeData(const QMimeData* data, Qt::DropAction action, bool LayersModel::dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column,
int row, int column, const QModelIndex& parent) const QModelIndex& parent) {
{
// check if the action is supported // check if the action is supported
if (!data || action != Qt::MoveAction) if (!data || action != Qt::MoveAction)
return false; return false;
@ -389,82 +355,86 @@ bool LayersModel::dropMimeData(const QMimeData* data, Qt::DropAction action,
count += 1; count += 1;
int dest = parent.row(); int dest = parent.row();
if (dest >= start) if (dest >= start) {
{
if (dest - start < count) if (dest - start < count)
return false; return false;
dest += 1; dest += 1;
} }
g_MainWindow->pushUndoCommand(new LayerRowMoveCommand(m_node.get(), g_MainWindow->pushUndoCommand(new LayerRowMoveCommand(m_node.get(), count > 1 ? tr("Move Layers") : tr("Move Layer"),
count > 1 ? tr("Move Layers") : tr("Move Layer"), &static_cast<LayersEditor*>(QObject::parent())->m_tableView,
&static_cast<LayersEditor*>(QObject::parent())->m_tableView, start, dest, count)); start, dest, count));
return true; return true;
} }
class LayerRowUndoCommand : public EditorUndoCommand class LayerRowUndoCommand : public EditorUndoCommand {
{
protected: protected:
LayersTableView* m_view; LayersTableView* m_view;
std::vector<std::pair<amuse::LayerMapping, int>> m_data; std::vector<std::pair<amuse::LayerMapping, int>> m_data;
bool m_undid = false; bool m_undid = false;
void add() void add() {
{
m_view->selectionModel()->clearSelection(); m_view->selectionModel()->clearSelection();
for (const auto& p : m_data) for (const auto& p : m_data) {
{
static_cast<LayersModel*>(m_view->model())->_insertRow(p.second, p.first); static_cast<LayersModel*>(m_view->model())->_insertRow(p.second, p.first);
m_view->setCurrentIndex(m_view->model()->index(p.second, 0)); m_view->setCurrentIndex(m_view->model()->index(p.second, 0));
} }
} }
void del() void del() {
{ for (auto it = m_data.rbegin(); it != m_data.rend(); ++it) {
for (auto it = m_data.rbegin(); it != m_data.rend(); ++it)
{
it->first = static_cast<LayersModel*>(m_view->model())->_removeRow(it->second); it->first = static_cast<LayersModel*>(m_view->model())->_removeRow(it->second);
} }
} }
void undo() void undo() {
{
m_undid = true; m_undid = true;
EditorUndoCommand::undo(); EditorUndoCommand::undo();
} }
void redo() void redo() {
{
if (m_undid) if (m_undid)
EditorUndoCommand::redo(); EditorUndoCommand::redo();
} }
public: public:
explicit LayerRowUndoCommand(ProjectModel::LayersNode* node, const QString& text, LayersTableView* view, explicit LayerRowUndoCommand(ProjectModel::LayersNode* node, const QString& text, LayersTableView* view,
std::vector<std::pair<amuse::LayerMapping, int>>&& data) std::vector<std::pair<amuse::LayerMapping, int>>&& data)
: EditorUndoCommand(node, text), m_view(view), m_data(std::move(data)) {} : EditorUndoCommand(node, text), m_view(view), m_data(std::move(data)) {}
}; };
class LayerRowAddUndoCommand : public LayerRowUndoCommand class LayerRowAddUndoCommand : public LayerRowUndoCommand {
{
using base = LayerRowUndoCommand; using base = LayerRowUndoCommand;
public: public:
explicit LayerRowAddUndoCommand(ProjectModel::LayersNode* node, const QString& text, LayersTableView* view, explicit LayerRowAddUndoCommand(ProjectModel::LayersNode* node, const QString& text, LayersTableView* view,
std::vector<std::pair<amuse::LayerMapping, int>>&& data) std::vector<std::pair<amuse::LayerMapping, int>>&& data)
: LayerRowUndoCommand(node, text, view, std::move(data)) {} : LayerRowUndoCommand(node, text, view, std::move(data)) {}
void undo() { base::undo(); base::del(); } void undo() {
void redo() { base::redo(); base::add(); } base::undo();
base::del();
}
void redo() {
base::redo();
base::add();
}
}; };
class LayerRowDelUndoCommand : public LayerRowUndoCommand class LayerRowDelUndoCommand : public LayerRowUndoCommand {
{
using base = LayerRowUndoCommand; using base = LayerRowUndoCommand;
public: public:
explicit LayerRowDelUndoCommand(ProjectModel::LayersNode* node, const QString& text, LayersTableView* view, explicit LayerRowDelUndoCommand(ProjectModel::LayersNode* node, const QString& text, LayersTableView* view,
std::vector<std::pair<amuse::LayerMapping, int>>&& data) std::vector<std::pair<amuse::LayerMapping, int>>&& data)
: LayerRowUndoCommand(node, text, view, std::move(data)) {} : LayerRowUndoCommand(node, text, view, std::move(data)) {}
void undo() { base::undo(); base::add(); } void undo() {
void redo() { base::redo(); base::del(); } base::undo();
base::add();
}
void redo() {
base::redo();
base::del();
}
}; };
bool LayersModel::insertRows(int row, int count, const QModelIndex& parent) bool LayersModel::insertRows(int row, int count, const QModelIndex& parent) {
{
if (!m_node) if (!m_node)
return false; return false;
beginInsertRows(parent, row, row + count - 1); beginInsertRows(parent, row, row + count - 1);
@ -475,16 +445,13 @@ bool LayersModel::insertRows(int row, int count, const QModelIndex& parent)
} }
bool LayersModel::moveRows(const QModelIndex& sourceParent, int sourceRow, int count, bool LayersModel::moveRows(const QModelIndex& sourceParent, int sourceRow, int count,
const QModelIndex& destinationParent, int destinationChild) const QModelIndex& destinationParent, int destinationChild) {
{
if (!m_node) if (!m_node)
return false; return false;
bool moving = beginMoveRows(sourceParent, sourceRow, sourceRow + count - 1, destinationParent, destinationChild); bool moving = beginMoveRows(sourceParent, sourceRow, sourceRow + count - 1, destinationParent, destinationChild);
std::vector<amuse::LayerMapping>& layers = *m_node->m_obj; std::vector<amuse::LayerMapping>& layers = *m_node->m_obj;
if (destinationChild < sourceRow) if (destinationChild < sourceRow) {
{ for (int i = 0; i < count; ++i) {
for (int i = 0; i < count; ++i)
{
amuse::LayerMapping tmp = std::move(layers[sourceRow]); amuse::LayerMapping tmp = std::move(layers[sourceRow]);
for (int j = sourceRow; j != destinationChild; --j) for (int j = sourceRow; j != destinationChild; --j)
layers[j] = std::move(layers[j - 1]); layers[j] = std::move(layers[j - 1]);
@ -492,11 +459,8 @@ bool LayersModel::moveRows(const QModelIndex& sourceParent, int sourceRow, int c
++sourceRow; ++sourceRow;
++destinationChild; ++destinationChild;
} }
} } else if (destinationChild > sourceRow) {
else if (destinationChild > sourceRow) for (int i = 0; i < count; ++i) {
{
for (int i = 0; i < count; ++i)
{
amuse::LayerMapping tmp = std::move(layers[sourceRow]); amuse::LayerMapping tmp = std::move(layers[sourceRow]);
for (int j = sourceRow; j != destinationChild - 1; ++j) for (int j = sourceRow; j != destinationChild - 1; ++j)
layers[j] = std::move(layers[j + 1]); layers[j] = std::move(layers[j + 1]);
@ -508,8 +472,7 @@ bool LayersModel::moveRows(const QModelIndex& sourceParent, int sourceRow, int c
return true; return true;
} }
bool LayersModel::removeRows(int row, int count, const QModelIndex& parent) bool LayersModel::removeRows(int row, int count, const QModelIndex& parent) {
{
if (!m_node) if (!m_node)
return false; return false;
beginRemoveRows(parent, row, row + count - 1); beginRemoveRows(parent, row, row + count - 1);
@ -519,8 +482,7 @@ bool LayersModel::removeRows(int row, int count, const QModelIndex& parent)
return true; return true;
} }
void LayersModel::_insertRow(int row, const amuse::LayerMapping& data) void LayersModel::_insertRow(int row, const amuse::LayerMapping& data) {
{
if (!m_node) if (!m_node)
return; return;
beginInsertRows(QModelIndex(), row, row); beginInsertRows(QModelIndex(), row, row);
@ -529,8 +491,7 @@ void LayersModel::_insertRow(int row, const amuse::LayerMapping& data)
endInsertRows(); endInsertRows();
} }
amuse::LayerMapping LayersModel::_removeRow(int row) amuse::LayerMapping LayersModel::_removeRow(int row) {
{
if (!m_node) if (!m_node)
return {}; return {};
beginRemoveRows(QModelIndex(), row, row); beginRemoveRows(QModelIndex(), row, row);
@ -541,12 +502,9 @@ amuse::LayerMapping LayersModel::_removeRow(int row)
return ret; return ret;
} }
LayersModel::LayersModel(QObject* parent) LayersModel::LayersModel(QObject* parent) : QAbstractTableModel(parent) {}
: QAbstractTableModel(parent)
{}
void LayersTableView::deleteSelection() void LayersTableView::deleteSelection() {
{
QModelIndexList list = selectionModel()->selectedRows(); QModelIndexList list = selectionModel()->selectedRows();
if (list.isEmpty()) if (list.isEmpty())
return; return;
@ -555,13 +513,12 @@ void LayersTableView::deleteSelection()
for (QModelIndex idx : list) for (QModelIndex idx : list)
data.push_back(std::make_pair(amuse::LayerMapping{}, idx.row())); data.push_back(std::make_pair(amuse::LayerMapping{}, idx.row()));
std::sort(data.begin(), data.end(), [](const auto& a, const auto& b) { return a.second < b.second; }); std::sort(data.begin(), data.end(), [](const auto& a, const auto& b) { return a.second < b.second; });
g_MainWindow->pushUndoCommand( g_MainWindow->pushUndoCommand(new LayerRowDelUndoCommand(static_cast<LayersModel*>(model())->m_node.get(),
new LayerRowDelUndoCommand(static_cast<LayersModel*>(model())->m_node.get(), data.size() > 1 ? tr("Delete Layers") : tr("Delete Layer"),
data.size() > 1 ? tr("Delete Layers") : tr("Delete Layer"), this, std::move(data))); this, std::move(data)));
} }
void LayersTableView::setModel(QAbstractItemModel* model) void LayersTableView::setModel(QAbstractItemModel* model) {
{
QTableView::setModel(model); QTableView::setModel(model);
horizontalHeader()->setMinimumSectionSize(75); horizontalHeader()->setMinimumSectionSize(75);
horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch); horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch);
@ -581,9 +538,7 @@ void LayersTableView::setModel(QAbstractItemModel* model)
horizontalHeader()->resizeSection(7, 75); horizontalHeader()->resizeSection(7, 75);
} }
LayersTableView::LayersTableView(QWidget* parent) LayersTableView::LayersTableView(QWidget* parent) : QTableView(parent) {
: QTableView(parent)
{
setSelectionBehavior(QAbstractItemView::SelectRows); setSelectionBehavior(QAbstractItemView::SelectRows);
setSelectionMode(QAbstractItemView::ExtendedSelection); setSelectionMode(QAbstractItemView::ExtendedSelection);
setDragDropMode(QAbstractItemView::InternalMove); setDragDropMode(QAbstractItemView::InternalMove);
@ -604,76 +559,59 @@ LayersTableView::LayersTableView(QWidget* parent)
setItemDelegateForColumn(7, &m_unsignedDelegate); setItemDelegateForColumn(7, &m_unsignedDelegate);
} }
bool LayersEditor::loadData(ProjectModel::LayersNode* node) bool LayersEditor::loadData(ProjectModel::LayersNode* node) {
{
m_model.loadData(node); m_model.loadData(node);
return true; return true;
} }
void LayersEditor::unloadData() void LayersEditor::unloadData() { m_model.unloadData(); }
{
m_model.unloadData();
}
ProjectModel::INode* LayersEditor::currentNode() const ProjectModel::INode* LayersEditor::currentNode() const { return m_model.m_node.get(); }
{
return m_model.m_node.get();
}
void LayersEditor::resizeEvent(QResizeEvent* ev) void LayersEditor::resizeEvent(QResizeEvent* ev) {
{
m_tableView.setGeometry(QRect({}, ev->size())); m_tableView.setGeometry(QRect({}, ev->size()));
m_addRemoveButtons.move(0, ev->size().height() - 32); m_addRemoveButtons.move(0, ev->size().height() - 32);
} }
void LayersEditor::rowsInserted(const QModelIndex& parent, int first, int last) void LayersEditor::rowsInserted(const QModelIndex& parent, int first, int last) {
{
m_tableView.scrollTo(m_tableView.model()->index(first, 0)); m_tableView.scrollTo(m_tableView.model()->index(first, 0));
} }
void LayersEditor::rowsMoved(const QModelIndex& parent, int start, int end, const QModelIndex& destination, int row) void LayersEditor::rowsMoved(const QModelIndex& parent, int start, int end, const QModelIndex& destination, int row) {
{
m_tableView.scrollTo(m_tableView.model()->index(row, 0)); m_tableView.scrollTo(m_tableView.model()->index(row, 0));
} }
void LayersEditor::doAdd() void LayersEditor::doAdd() {
{
QModelIndex idx = m_tableView.selectionModel()->currentIndex(); QModelIndex idx = m_tableView.selectionModel()->currentIndex();
std::vector<std::pair<amuse::LayerMapping, int>> data; std::vector<std::pair<amuse::LayerMapping, int>> data;
if (!idx.isValid()) if (!idx.isValid())
data.push_back(std::make_pair(amuse::LayerMapping{}, m_model.rowCount() - 1)); data.push_back(std::make_pair(amuse::LayerMapping{}, m_model.rowCount() - 1));
else else
data.push_back(std::make_pair(amuse::LayerMapping{}, idx.row())); data.push_back(std::make_pair(amuse::LayerMapping{}, idx.row()));
g_MainWindow->pushUndoCommand(new LayerRowAddUndoCommand(m_model.m_node.get(), g_MainWindow->pushUndoCommand(
tr("Add Layer"), &m_tableView, std::move(data))); new LayerRowAddUndoCommand(m_model.m_node.get(), tr("Add Layer"), &m_tableView, std::move(data)));
} }
void LayersEditor::doSelectionChanged() void LayersEditor::doSelectionChanged() {
{
m_addRemoveButtons.removeAction()->setDisabled(m_tableView.selectionModel()->selectedRows().isEmpty()); m_addRemoveButtons.removeAction()->setDisabled(m_tableView.selectionModel()->selectedRows().isEmpty());
g_MainWindow->updateFocus(); g_MainWindow->updateFocus();
} }
AmuseItemEditFlags LayersEditor::itemEditFlags() const AmuseItemEditFlags LayersEditor::itemEditFlags() const {
{
return m_tableView.selectionModel()->selectedRows().isEmpty() ? AmuseItemNone : AmuseItemDelete; return m_tableView.selectionModel()->selectedRows().isEmpty() ? AmuseItemNone : AmuseItemDelete;
} }
void LayersEditor::itemDeleteAction() void LayersEditor::itemDeleteAction() { m_tableView.deleteSelection(); }
{
m_tableView.deleteSelection();
}
LayersEditor::LayersEditor(QWidget* parent) LayersEditor::LayersEditor(QWidget* parent)
: EditorWidget(parent), m_model(this), m_tableView(this), m_addRemoveButtons(this) : EditorWidget(parent), m_model(this), m_tableView(this), m_addRemoveButtons(this) {
{
m_tableView.setModel(&m_model); m_tableView.setModel(&m_model);
connect(m_tableView.selectionModel(), SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)), connect(m_tableView.selectionModel(), SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)), this,
this, SLOT(doSelectionChanged())); SLOT(doSelectionChanged()));
connect(&m_model, SIGNAL(rowsInserted(const QModelIndex&, int, int)), connect(&m_model, SIGNAL(rowsInserted(const QModelIndex&, int, int)), this,
this, SLOT(rowsInserted(const QModelIndex&, int, int))); SLOT(rowsInserted(const QModelIndex&, int, int)));
connect(&m_model, SIGNAL(rowsMoved(const QModelIndex&, int, int, const QModelIndex&, int)), connect(&m_model, SIGNAL(rowsMoved(const QModelIndex&, int, int, const QModelIndex&, int)), this,
this, SLOT(rowsMoved(const QModelIndex&, int, int, const QModelIndex&, int))); SLOT(rowsMoved(const QModelIndex&, int, int, const QModelIndex&, int)));
m_addRemoveButtons.addAction()->setToolTip(tr("Add new layer mapping")); m_addRemoveButtons.addAction()->setToolTip(tr("Add new layer mapping"));
connect(m_addRemoveButtons.addAction(), SIGNAL(triggered(bool)), this, SLOT(doAdd())); connect(m_addRemoveButtons.addAction(), SIGNAL(triggered(bool)), this, SLOT(doAdd()));

View File

@ -7,11 +7,11 @@
#include <QToolButton> #include <QToolButton>
#include <QStyledItemDelegate> #include <QStyledItemDelegate>
class SoundMacroDelegate : public BaseObjectDelegate class SoundMacroDelegate : public BaseObjectDelegate {
{
Q_OBJECT Q_OBJECT
protected: protected:
ProjectModel::INode* getNode(const QAbstractItemModel* model, const QModelIndex& index) const; ProjectModel::INode* getNode(const QAbstractItemModel* model, const QModelIndex& index) const;
public: public:
explicit SoundMacroDelegate(QObject* parent = Q_NULLPTR); explicit SoundMacroDelegate(QObject* parent = Q_NULLPTR);
QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const; QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const;
@ -21,13 +21,13 @@ private slots:
void smIndexChanged(); void smIndexChanged();
}; };
class LayersModel : public QAbstractTableModel class LayersModel : public QAbstractTableModel {
{
Q_OBJECT Q_OBJECT
friend class LayersEditor; friend class LayersEditor;
friend class SoundMacroDelegate; friend class SoundMacroDelegate;
friend class LayersTableView; friend class LayersTableView;
amuse::ObjToken<ProjectModel::LayersNode> m_node; amuse::ObjToken<ProjectModel::LayersNode> m_node;
public: public:
explicit LayersModel(QObject* parent = Q_NULLPTR); explicit LayersModel(QObject* parent = Q_NULLPTR);
void loadData(ProjectModel::LayersNode* node); void loadData(ProjectModel::LayersNode* node);
@ -41,38 +41,37 @@ public:
Qt::ItemFlags flags(const QModelIndex& index) const; Qt::ItemFlags flags(const QModelIndex& index) const;
Qt::DropActions supportedDropActions() const; Qt::DropActions supportedDropActions() const;
Qt::DropActions supportedDragActions() const; Qt::DropActions supportedDragActions() const;
bool dropMimeData(const QMimeData *data, Qt::DropAction action, bool dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent);
int row, int column, const QModelIndex &parent);
bool insertRows(int row, int count, const QModelIndex& parent = QModelIndex()); bool insertRows(int row, int count, const QModelIndex& parent = QModelIndex());
bool moveRows(const QModelIndex& sourceParent, int sourceRow, int count, bool moveRows(const QModelIndex& sourceParent, int sourceRow, int count, const QModelIndex& destinationParent,
const QModelIndex& destinationParent, int destinationChild); int destinationChild);
bool removeRows(int row, int count, const QModelIndex& parent = QModelIndex()); bool removeRows(int row, int count, const QModelIndex& parent = QModelIndex());
void _insertRow(int row, const amuse::LayerMapping& data); void _insertRow(int row, const amuse::LayerMapping& data);
amuse::LayerMapping _removeRow(int row); amuse::LayerMapping _removeRow(int row);
}; };
class LayersTableView : public QTableView class LayersTableView : public QTableView {
{
Q_OBJECT Q_OBJECT
SoundMacroDelegate m_smDelegate; SoundMacroDelegate m_smDelegate;
RangedValueFactory<-128, 127> m_signedFactory; RangedValueFactory<-128, 127> m_signedFactory;
RangedValueFactory<0, 127> m_unsignedFactory; RangedValueFactory<0, 127> m_unsignedFactory;
QStyledItemDelegate m_signedDelegate, m_unsignedDelegate; QStyledItemDelegate m_signedDelegate, m_unsignedDelegate;
public: public:
explicit LayersTableView(QWidget* parent = Q_NULLPTR); explicit LayersTableView(QWidget* parent = Q_NULLPTR);
void setModel(QAbstractItemModel* model); void setModel(QAbstractItemModel* model);
void deleteSelection(); void deleteSelection();
}; };
class LayersEditor : public EditorWidget class LayersEditor : public EditorWidget {
{
Q_OBJECT Q_OBJECT
friend class LayersModel; friend class LayersModel;
LayersModel m_model; LayersModel m_model;
LayersTableView m_tableView; LayersTableView m_tableView;
AddRemoveButtons m_addRemoveButtons; AddRemoveButtons m_addRemoveButtons;
public: public:
explicit LayersEditor(QWidget* parent = Q_NULLPTR); explicit LayersEditor(QWidget* parent = Q_NULLPTR);
bool loadData(ProjectModel::LayersNode* node); bool loadData(ProjectModel::LayersNode* node);
@ -87,4 +86,3 @@ private slots:
void doSelectionChanged(); void doSelectionChanged();
void itemDeleteAction(); void itemDeleteAction();
}; };

View File

@ -1,13 +1,10 @@
#include "MIDIReader.hpp" #include "MIDIReader.hpp"
#include "MainWindow.hpp" #include "MainWindow.hpp"
MIDIReader::MIDIReader(amuse::Engine& engine, bool useLock) MIDIReader::MIDIReader(amuse::Engine& engine, bool useLock) : amuse::BooBackendMIDIReader(engine, useLock) {}
: amuse::BooBackendMIDIReader(engine, useLock) {}
void MIDIReader::noteOff(uint8_t chan, uint8_t key, uint8_t velocity) void MIDIReader::noteOff(uint8_t chan, uint8_t key, uint8_t velocity) {
{ if (g_MainWindow->m_interactiveSeq) {
if (g_MainWindow->m_interactiveSeq)
{
g_MainWindow->m_interactiveSeq->keyOff(chan, key, velocity); g_MainWindow->m_interactiveSeq->keyOff(chan, key, velocity);
return; return;
} }
@ -23,10 +20,8 @@ void MIDIReader::noteOff(uint8_t chan, uint8_t key, uint8_t velocity)
m_chanVoxs.erase(keySearch); m_chanVoxs.erase(keySearch);
} }
void MIDIReader::noteOn(uint8_t chan, uint8_t key, uint8_t velocity) void MIDIReader::noteOn(uint8_t chan, uint8_t key, uint8_t velocity) {
{ if (g_MainWindow->m_interactiveSeq) {
if (g_MainWindow->m_interactiveSeq)
{
g_MainWindow->m_interactiveSeq->keyOn(chan, key, velocity); g_MainWindow->m_interactiveSeq->keyOn(chan, key, velocity);
return; return;
} }
@ -35,11 +30,9 @@ void MIDIReader::noteOn(uint8_t chan, uint8_t key, uint8_t velocity)
m_lastVoice.reset(); m_lastVoice.reset();
/* If portamento is enabled for voice, pre-empt spawning new voices */ /* If portamento is enabled for voice, pre-empt spawning new voices */
if (amuse::ObjToken<amuse::Voice> lastVoice = m_lastVoice) if (amuse::ObjToken<amuse::Voice> lastVoice = m_lastVoice) {
{
uint8_t lastNote = lastVoice->getLastNote(); uint8_t lastNote = lastVoice->getLastNote();
if (lastVoice->doPortamento(key)) if (lastVoice->doPortamento(key)) {
{
m_chanVoxs.erase(lastNote); m_chanVoxs.erase(lastNote);
m_chanVoxs[key] = lastVoice; m_chanVoxs[key] = lastVoice;
return; return;
@ -48,8 +41,7 @@ void MIDIReader::noteOn(uint8_t chan, uint8_t key, uint8_t velocity)
/* Ensure keyoff sent first */ /* Ensure keyoff sent first */
auto keySearch = m_chanVoxs.find(key); auto keySearch = m_chanVoxs.find(key);
if (keySearch != m_chanVoxs.cend()) if (keySearch != m_chanVoxs.cend()) {
{
if (keySearch->second == m_lastVoice) if (keySearch->second == m_lastVoice)
m_lastVoice.reset(); m_lastVoice.reset();
keySearch->second->keyOff(); keySearch->second->keyOff();
@ -59,8 +51,7 @@ void MIDIReader::noteOn(uint8_t chan, uint8_t key, uint8_t velocity)
} }
amuse::ObjToken<amuse::Voice> newVox = g_MainWindow->startEditorVoice(key, velocity); amuse::ObjToken<amuse::Voice> newVox = g_MainWindow->startEditorVoice(key, velocity);
if (newVox) if (newVox) {
{
m_chanVoxs[key] = newVox; m_chanVoxs[key] = newVox;
m_lastVoice = newVox; m_lastVoice = newVox;
} }
@ -68,40 +59,31 @@ void MIDIReader::noteOn(uint8_t chan, uint8_t key, uint8_t velocity)
void MIDIReader::notePressure(uint8_t /*chan*/, uint8_t /*key*/, uint8_t /*pressure*/) {} void MIDIReader::notePressure(uint8_t /*chan*/, uint8_t /*key*/, uint8_t /*pressure*/) {}
void MIDIReader::controlChange(uint8_t chan, uint8_t control, uint8_t value) void MIDIReader::controlChange(uint8_t chan, uint8_t control, uint8_t value) {
{ if (g_MainWindow->m_interactiveSeq) {
if (g_MainWindow->m_interactiveSeq)
{
g_MainWindow->m_interactiveSeq->setCtrlValue(chan, control, value); g_MainWindow->m_interactiveSeq->setCtrlValue(chan, control, value);
return; return;
} }
if (control == 1) if (control == 1) {
{
g_MainWindow->m_ui.modulationSlider->setValue(int(value)); g_MainWindow->m_ui.modulationSlider->setValue(int(value));
} } else if (control == 64) {
else if (control == 64)
{
g_MainWindow->setSustain(value >= 0x40); g_MainWindow->setSustain(value >= 0x40);
} } else {
else
{
for (auto& v : m_engine.getActiveVoices()) for (auto& v : m_engine.getActiveVoices())
v->setCtrlValue(control, value); v->setCtrlValue(control, value);
} }
g_MainWindow->m_ctrlVals[control] = value; g_MainWindow->m_ctrlVals[control] = value;
} }
void MIDIReader::programChange(uint8_t chan, uint8_t program) void MIDIReader::programChange(uint8_t chan, uint8_t program) {
{
if (g_MainWindow->m_interactiveSeq) if (g_MainWindow->m_interactiveSeq)
g_MainWindow->m_interactiveSeq->setChanProgram(chan, program); g_MainWindow->m_interactiveSeq->setChanProgram(chan, program);
} }
void MIDIReader::channelPressure(uint8_t /*chan*/, uint8_t /*pressure*/) {} void MIDIReader::channelPressure(uint8_t /*chan*/, uint8_t /*pressure*/) {}
void MIDIReader::pitchBend(uint8_t chan, int16_t pitch) void MIDIReader::pitchBend(uint8_t chan, int16_t pitch) {
{
float pWheel = (pitch - 0x2000) / float(0x2000); float pWheel = (pitch - 0x2000) / float(0x2000);
if (g_MainWindow->m_interactiveSeq) if (g_MainWindow->m_interactiveSeq)
g_MainWindow->m_interactiveSeq->setPitchWheel(chan, pWheel); g_MainWindow->m_interactiveSeq->setPitchWheel(chan, pWheel);
@ -109,10 +91,8 @@ void MIDIReader::pitchBend(uint8_t chan, int16_t pitch)
g_MainWindow->m_ui.pitchSlider->setValue(int(pWheel * 2048.f)); g_MainWindow->m_ui.pitchSlider->setValue(int(pWheel * 2048.f));
} }
void MIDIReader::allSoundOff(uint8_t chan) void MIDIReader::allSoundOff(uint8_t chan) {
{ if (g_MainWindow->m_interactiveSeq) {
if (g_MainWindow->m_interactiveSeq)
{
g_MainWindow->m_interactiveSeq->kill(); g_MainWindow->m_interactiveSeq->kill();
return; return;
} }
@ -125,10 +105,8 @@ void MIDIReader::resetAllControllers(uint8_t /*chan*/) {}
void MIDIReader::localControl(uint8_t /*chan*/, bool /*on*/) {} void MIDIReader::localControl(uint8_t /*chan*/, bool /*on*/) {}
void MIDIReader::allNotesOff(uint8_t chan) void MIDIReader::allNotesOff(uint8_t chan) {
{ if (g_MainWindow->m_interactiveSeq) {
if (g_MainWindow->m_interactiveSeq)
{
g_MainWindow->m_interactiveSeq->kill(); g_MainWindow->m_interactiveSeq->kill();
return; return;
} }
@ -159,11 +137,8 @@ void MIDIReader::stopSeq() {}
void MIDIReader::reset() {} void MIDIReader::reset() {}
VoiceAllocator::VoiceAllocator(boo::IAudioVoiceEngine& booEngine) VoiceAllocator::VoiceAllocator(boo::IAudioVoiceEngine& booEngine) : amuse::BooBackendVoiceAllocator(booEngine) {}
: amuse::BooBackendVoiceAllocator(booEngine) {}
std::unique_ptr<amuse::IMIDIReader> std::unique_ptr<amuse::IMIDIReader> VoiceAllocator::allocateMIDIReader(amuse::Engine& engine) {
VoiceAllocator::allocateMIDIReader(amuse::Engine& engine)
{
return std::make_unique<MIDIReader>(engine, m_booEngine.useMIDILock()); return std::make_unique<MIDIReader>(engine, m_booEngine.useMIDILock());
} }

View File

@ -5,11 +5,11 @@
#include "amuse/Common.hpp" #include "amuse/Common.hpp"
#include <unordered_set> #include <unordered_set>
class MIDIReader : public amuse::BooBackendMIDIReader class MIDIReader : public amuse::BooBackendMIDIReader {
{
std::unordered_map<uint8_t, amuse::ObjToken<amuse::Voice>> m_chanVoxs; std::unordered_map<uint8_t, amuse::ObjToken<amuse::Voice>> m_chanVoxs;
std::unordered_set<amuse::ObjToken<amuse::Voice>> m_keyoffVoxs; std::unordered_set<amuse::ObjToken<amuse::Voice>> m_keyoffVoxs;
amuse::ObjToken<amuse::Voice> m_lastVoice; amuse::ObjToken<amuse::Voice> m_lastVoice;
public: public:
MIDIReader(amuse::Engine& engine, bool useLock); MIDIReader(amuse::Engine& engine, bool useLock);
@ -41,10 +41,8 @@ public:
void reset(); void reset();
}; };
class VoiceAllocator : public amuse::BooBackendVoiceAllocator class VoiceAllocator : public amuse::BooBackendVoiceAllocator {
{
public: public:
VoiceAllocator(boo::IAudioVoiceEngine& booEngine); VoiceAllocator(boo::IAudioVoiceEngine& booEngine);
std::unique_ptr<amuse::IMIDIReader> allocateMIDIReader(amuse::Engine& engine); std::unique_ptr<amuse::IMIDIReader> allocateMIDIReader(amuse::Engine& engine);
}; };

File diff suppressed because it is too large Load Diff

View File

@ -33,25 +33,22 @@ class KeymapEditor;
class LayersEditor; class LayersEditor;
class SampleEditor; class SampleEditor;
enum BackgroundTaskId enum BackgroundTaskId { TaskOpen, TaskImport, TaskExport, TaskReloadSamples };
{
TaskOpen,
TaskImport,
TaskExport,
TaskReloadSamples
};
class BackgroundTask : public QObject class BackgroundTask : public QObject {
{
Q_OBJECT Q_OBJECT
int m_id; int m_id;
std::function<void(BackgroundTask&)> m_task; std::function<void(BackgroundTask&)> m_task;
UIMessenger m_threadMessenger; UIMessenger m_threadMessenger;
bool m_cancelled = false; bool m_cancelled = false;
public: public:
explicit BackgroundTask(int id, std::function<void(BackgroundTask&)>&& task) explicit BackgroundTask(int id, std::function<void(BackgroundTask&)>&& task)
: m_id(id), m_task(std::move(task)), m_threadMessenger(this) {} : m_id(id), m_task(std::move(task)), m_threadMessenger(this) {}
bool isCanceled() const { QCoreApplication::processEvents(); return m_cancelled; } bool isCanceled() const {
QCoreApplication::processEvents();
return m_cancelled;
}
UIMessenger& uiMessenger() { return m_threadMessenger; } UIMessenger& uiMessenger() { return m_threadMessenger; }
signals: signals:
@ -62,22 +59,23 @@ signals:
void finished(int id); void finished(int id);
public slots: public slots:
void run() { m_task(*this); emit finished(m_id); } void run() {
m_task(*this);
emit finished(m_id);
}
void cancel() { m_cancelled = true; } void cancel() { m_cancelled = true; }
}; };
class TreeDelegate : public QStyledItemDelegate class TreeDelegate : public QStyledItemDelegate {
{
Q_OBJECT Q_OBJECT
MainWindow& m_window; MainWindow& m_window;
public: public:
explicit TreeDelegate(MainWindow& window, QObject* parent = Q_NULLPTR) explicit TreeDelegate(MainWindow& window, QObject* parent = Q_NULLPTR)
: QStyledItemDelegate(parent), m_window(window) {} : QStyledItemDelegate(parent), m_window(window) {}
bool editorEvent(QEvent *event, bool editorEvent(QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option,
QAbstractItemModel *model, const QModelIndex& index);
const QStyleOptionViewItem &option,
const QModelIndex &index);
public slots: public slots:
void doExportGroup(); void doExportGroup();
void doFindUsages(); void doFindUsages();
@ -89,8 +87,7 @@ public slots:
void doRename(); void doRename();
}; };
class MainWindow : public QMainWindow class MainWindow : public QMainWindow {
{
friend class MIDIReader; friend class MIDIReader;
friend class ProjectModel; friend class ProjectModel;
friend class GroupNodeUndoCommand; friend class GroupNodeUndoCommand;
@ -281,27 +278,20 @@ public slots:
void onBackgroundTaskFinished(int id); void onBackgroundTaskFinished(int id);
QMessageBox::StandardButton msgInformation(const QString &title, QMessageBox::StandardButton msgInformation(const QString& title, const QString& text,
const QString &text, QMessageBox::StandardButtons buttons = QMessageBox::Ok, QMessageBox::StandardButtons buttons = QMessageBox::Ok,
QMessageBox::StandardButton defaultButton = QMessageBox::NoButton); QMessageBox::StandardButton defaultButton = QMessageBox::NoButton);
int msgQuestion(const QString &title, int msgQuestion(const QString& title, const QString& text, const QString& button0Text,
const QString& text, const QString& button1Text = QString(), const QString& button2Text = QString(),
const QString& button0Text, int defaultButtonNumber = 0, int escapeButtonNumber = -1);
const QString& button1Text = QString(), QMessageBox::StandardButton
const QString& button2Text = QString(), msgQuestion(const QString& title, const QString& text,
int defaultButtonNumber = 0, QMessageBox::StandardButtons buttons = QMessageBox::StandardButtons(QMessageBox::Yes | QMessageBox::No),
int escapeButtonNumber = -1);
QMessageBox::StandardButton msgQuestion(const QString &title,
const QString &text, QMessageBox::StandardButtons buttons =
QMessageBox::StandardButtons(QMessageBox::Yes | QMessageBox::No),
QMessageBox::StandardButton defaultButton = QMessageBox::NoButton); QMessageBox::StandardButton defaultButton = QMessageBox::NoButton);
QMessageBox::StandardButton msgWarning(const QString &title, QMessageBox::StandardButton msgWarning(const QString& title, const QString& text,
const QString &text, QMessageBox::StandardButtons buttons = QMessageBox::Ok, QMessageBox::StandardButtons buttons = QMessageBox::Ok,
QMessageBox::StandardButton defaultButton = QMessageBox::NoButton); QMessageBox::StandardButton defaultButton = QMessageBox::NoButton);
QMessageBox::StandardButton msgCritical(const QString &title, QMessageBox::StandardButton msgCritical(const QString& title, const QString& text,
const QString &text, QMessageBox::StandardButtons buttons = QMessageBox::Ok, QMessageBox::StandardButtons buttons = QMessageBox::Ok,
QMessageBox::StandardButton defaultButton = QMessageBox::NoButton); QMessageBox::StandardButton defaultButton = QMessageBox::NoButton);
}; };

View File

@ -3,268 +3,138 @@
#include <QLabel> #include <QLabel>
#include "amuse/Common.hpp" #include "amuse/Common.hpp"
static const uint32_t BasicMacro[] = static const uint32_t BasicMacro[] = {
{ 0x38000000, 0xC07A1000, 0x10000000, 0x00000000, 0x07010001, 0x0000FFFF,
0x38000000, 0xC07A1000, 0x11000000, 0x00000000, 0x31000000, 0x00000000, 0x00000000, 0x00000000,
0x10000000, 0x00000000,
0x07010001, 0x0000FFFF,
0x11000000, 0x00000000,
0x31000000, 0x00000000,
0x00000000, 0x00000000,
}; };
static const uint32_t Looped[] = static const uint32_t Looped[] = {
{ 0x38000000, 0xC07A1000, 0x10000000, 0x00000000, 0x07010001, 0x0000FFFF, 0x3000D08A, 0x00000000, 0x38000000,
0x38000000, 0xC07A1000, 0xE8030000, 0x0F000000, 0x0001E803, 0x07000001, 0x0000E803, 0x11000000, 0x00000000, 0x00000000, 0x00000000,
0x10000000, 0x00000000,
0x07010001, 0x0000FFFF,
0x3000D08A, 0x00000000,
0x38000000, 0xE8030000,
0x0F000000, 0x0001E803,
0x07000001, 0x0000E803,
0x11000000, 0x00000000,
0x00000000, 0x00000000,
}; };
static const uint32_t LoopRelease[] = static const uint32_t LoopRelease[] = {
{ 0x38000000, 0xC07A1000, 0x10000000, 0x00000000, 0x1C000F01, 0x0001FA00, 0x07010000, 0x0000FFFF,
0x38000000, 0xC07A1000, 0x3000D08A, 0x00000000, 0x0F500000, 0x00013200, 0x07000000, 0x00003200, 0x38000000, 0xE8030000,
0x10000000, 0x00000000, 0x0F000000, 0x0001E803, 0x07000000, 0x0000E803, 0x11000000, 0x00000000, 0x00000000, 0x00000000,
0x1C000F01, 0x0001FA00,
0x07010000, 0x0000FFFF,
0x3000D08A, 0x00000000,
0x0F500000, 0x00013200,
0x07000000, 0x00003200,
0x38000000, 0xE8030000,
0x0F000000, 0x0001E803,
0x07000000, 0x0000E803,
0x11000000, 0x00000000,
0x00000000, 0x00000000,
}; };
static const uint32_t LoopSoftRelease[] = static const uint32_t LoopSoftRelease[] = {
{ 0x38000000, 0xC07A1000, 0x10000000, 0x00000000, 0x1C000F01, 0x0001C800, 0x07010000, 0x0000FFFF,
0x38000000, 0xC07A1000, 0x3000D08A, 0x00000000, 0x0F600000, 0x00016400, 0x07000000, 0x00006400, 0x38000000, 0xE8030000,
0x10000000, 0x00000000, 0x0F000000, 0x0001E803, 0x07000000, 0x0000E803, 0x11000000, 0x00000000, 0x00000000, 0x00000000,
0x1C000F01, 0x0001C800,
0x07010000, 0x0000FFFF,
0x3000D08A, 0x00000000,
0x0F600000, 0x00016400,
0x07000000, 0x00006400,
0x38000000, 0xE8030000,
0x0F000000, 0x0001E803,
0x07000000, 0x0000E803,
0x11000000, 0x00000000,
0x00000000, 0x00000000,
}; };
static const uint32_t LoopSoftReleaseNoClick[] = static const uint32_t LoopSoftReleaseNoClick[] = {
{ 0x38000000, 0xC07A1000, 0x147F0000, 0x00010100, 0x10000000, 0x00000000, 0x1C000F01, 0x0001C800, 0x07010000,
0x38000000, 0xC07A1000, 0x0000FFFF, 0x3000D08A, 0x00000000, 0x0F600000, 0x00016400, 0x07000000, 0x00006400, 0x38000000, 0xE8030000,
0x147F0000, 0x00010100, 0x0F000000, 0x0001E803, 0x07000000, 0x0000E803, 0x11000000, 0x00000000, 0x00000000, 0x00000000,
0x10000000, 0x00000000,
0x1C000F01, 0x0001C800,
0x07010000, 0x0000FFFF,
0x3000D08A, 0x00000000,
0x0F600000, 0x00016400,
0x07000000, 0x00006400,
0x38000000, 0xE8030000,
0x0F000000, 0x0001E803,
0x07000000, 0x0000E803,
0x11000000, 0x00000000,
0x00000000, 0x00000000,
}; };
static const uint32_t LoopADSR[] = static const uint32_t LoopADSR[] = {
{ 0x38000000, 0xC07A1000, 0x0C000000, 0x00000000, 0x10000000, 0x00000000, 0x1C000F01, 0x0001C800,
0x38000000, 0xC07A1000, 0x07010001, 0x0000FFFF, 0x3000D08A, 0x00000000, 0x12000000, 0x00000000, 0x07000001, 0x0000E803,
0x0C000000, 0x00000000, 0x38000000, 0xE8030000, 0x07000001, 0x0000E803, 0x00000000, 0x00000000,
0x10000000, 0x00000000,
0x1C000F01, 0x0001C800,
0x07010001, 0x0000FFFF,
0x3000D08A, 0x00000000,
0x12000000, 0x00000000,
0x07000001, 0x0000E803,
0x38000000, 0xE8030000,
0x07000001, 0x0000E803,
0x00000000, 0x00000000,
}; };
static const uint32_t LoopADSRSoftRelease[] = static const uint32_t LoopADSRSoftRelease[] = {
{ 0x38000000, 0xC07A1000, 0x0C000000, 0x00000000, 0x10000000, 0x00000000, 0x1C000F01, 0x0001C800,
0x38000000, 0xC07A1000, 0x07010001, 0x0000FFFF, 0x3000D08A, 0x00000000, 0x0F600000, 0x00017800, 0x07000001, 0x00007800,
0x0C000000, 0x00000000, 0x12000000, 0x00000000, 0x38000000, 0xE8030000, 0x07000001, 0x0000E803, 0x00000000, 0x00000000,
0x10000000, 0x00000000,
0x1C000F01, 0x0001C800,
0x07010001, 0x0000FFFF,
0x3000D08A, 0x00000000,
0x0F600000, 0x00017800,
0x07000001, 0x00007800,
0x12000000, 0x00000000,
0x38000000, 0xE8030000,
0x07000001, 0x0000E803,
0x00000000, 0x00000000,
}; };
static const uint32_t LoopHold[] = static const uint32_t LoopHold[] = {
{ 0x38000000, 0xC07A1000, 0x10000000, 0x00000000, 0x1C000F01, 0x0001C800, 0x07010001, 0x0000FFFF,
0x38000000, 0xC07A1000, 0x3000D08A, 0x00000000, 0x0F600000, 0x00016400, 0x07000001, 0x00006400, 0x38000000, 0xE8030000,
0x10000000, 0x00000000, 0x0F000000, 0x0001E803, 0x07000001, 0x0000E803, 0x11000000, 0x00000000, 0x00000000, 0x00000000,
0x1C000F01, 0x0001C800,
0x07010001, 0x0000FFFF,
0x3000D08A, 0x00000000,
0x0F600000, 0x00016400,
0x07000001, 0x00006400,
0x38000000, 0xE8030000,
0x0F000000, 0x0001E803,
0x07000001, 0x0000E803,
0x11000000, 0x00000000,
0x00000000, 0x00000000,
}; };
static const uint32_t OneShot[] = static const uint32_t OneShot[] = {
{ 0x38000000, 0xC07A1000, 0x10000000, 0x00000000, 0x07000001,
0x38000000, 0xC07A1000, 0x0000FFFF, 0x31000000, 0x00000000, 0x00000000, 0x00000000,
0x10000000, 0x00000000,
0x07000001, 0x0000FFFF,
0x31000000, 0x00000000,
0x00000000, 0x00000000,
}; };
static const uint32_t OneShotFixedNote[] = static const uint32_t OneShotFixedNote[] = {
{ 0x38000000, 0xC07A1000, 0x193C0000, 0x00010000, 0x10000000, 0x00000000,
0x38000000, 0xC07A1000, 0x07000001, 0x0000FFFF, 0x31000000, 0x00000000, 0x00000000, 0x00000000,
0x193C0000, 0x00010000,
0x10000000, 0x00000000,
0x07000001, 0x0000FFFF,
0x31000000, 0x00000000,
0x00000000, 0x00000000,
}; };
static const uint32_t OneShotNoClick[] = static const uint32_t OneShotNoClick[] = {
{ 0x38000000, 0xC07A1000, 0x147F0000, 0x00010100, 0x10000000, 0x00000000,
0x38000000, 0xC07A1000, 0x07000001, 0x0000FFFF, 0x31000000, 0x00000000, 0x00000000, 0x00000000,
0x147F0000, 0x00010100,
0x10000000, 0x00000000,
0x07000001, 0x0000FFFF,
0x31000000, 0x00000000,
0x00000000, 0x00000000,
}; };
static const uint32_t OneShotFixedNoClick[] = static const uint32_t OneShotFixedNoClick[] = {
{ 0x38000000, 0xC07A1000, 0x147F0000, 0x00010100, 0x193C0000, 0x00010000, 0x10000000,
0x38000000, 0xC07A1000, 0x00000000, 0x07000001, 0x0000FFFF, 0x31000000, 0x00000000, 0x00000000, 0x00000000,
0x147F0000, 0x00010100,
0x193C0000, 0x00010000,
0x10000000, 0x00000000,
0x07000001, 0x0000FFFF,
0x31000000, 0x00000000,
0x00000000, 0x00000000,
}; };
static const uint32_t Bubbles[] = static const uint32_t Bubbles[] = {
{ 0x38000000, 0xC07A1000, 0x0D600000, 0x00010000, 0x10000000, 0x00000000, 0x1D08E803,
0x38000000, 0xC07A1000, 0x00010000, 0x1E0544FD, 0x00010000, 0x0F000000, 0x0001F401, 0x07000000, 0x0000F401,
0x0D600000, 0x00010000, 0x11000000, 0x00000000, 0x31000000, 0x00000000, 0x00000000, 0x00000000,
0x10000000, 0x00000000,
0x1D08E803, 0x00010000,
0x1E0544FD, 0x00010000,
0x0F000000, 0x0001F401,
0x07000000, 0x0000F401,
0x11000000, 0x00000000,
0x31000000, 0x00000000,
0x00000000, 0x00000000,
}; };
static const uint32_t DownTrigger[] = static const uint32_t DownTrigger[] = {
{ 0x38000000, 0xC07A1000, 0x10000000, 0x00000000, 0x07000000, 0x00001200, 0x11000000, 0x00000000,
0x38000000, 0xC07A1000, 0x07000000, 0x00000100, 0x18FE0000, 0x00010000, 0x05000000, 0x01000C00, 0x0F000000, 0x00016400,
0x10000000, 0x00000000, 0x07000001, 0x00006400, 0x31000000, 0x00000000, 0x00000000, 0x00000000,
0x07000000, 0x00001200,
0x11000000, 0x00000000,
0x07000000, 0x00000100,
0x18FE0000, 0x00010000,
0x05000000, 0x01000C00,
0x0F000000, 0x00016400,
0x07000001, 0x00006400,
0x31000000, 0x00000000,
0x00000000, 0x00000000,
}; };
static const uint32_t LongFadeInAndStop[] = static const uint32_t LongFadeInAndStop[] = {
{ 0x38000000, 0xC07A1000, 0x147F0000, 0x0001E803, 0x10000000, 0x00000000, 0x07000001,
0x38000000, 0xC07A1000, 0x0000E803, 0x11000000, 0x00000000, 0x31000000, 0x00000000, 0x00000000, 0x00000000,
0x147F0000, 0x0001E803,
0x10000000, 0x00000000,
0x07000001, 0x0000E803,
0x11000000, 0x00000000,
0x31000000, 0x00000000,
0x00000000, 0x00000000,
}; };
static const uint32_t FadeInAndStop[] = static const uint32_t FadeInAndStop[] = {
{ 0x38000000, 0xC07A1000, 0x147F0000, 0x0001C800, 0x10000000, 0x00000000, 0x07000001,
0x38000000, 0xC07A1000, 0x0000C800, 0x11000000, 0x00000000, 0x31000000, 0x00000000, 0x00000000, 0x00000000,
0x147F0000, 0x0001C800,
0x10000000, 0x00000000,
0x07000001, 0x0000C800,
0x11000000, 0x00000000,
0x31000000, 0x00000000,
0x00000000, 0x00000000,
}; };
static const uint32_t RandomTrigger[] = static const uint32_t RandomTrigger[] = {
{ 0x38000000, 0xC07A1000, 0x0F000000, 0x0001F401, 0x195A0000, 0x00010000, 0x10000000,
0x38000000, 0xC07A1000, 0x00000000, 0x1750005A, 0x01000000, 0x07000001, 0x00002300, 0x05000000, 0x03001400,
0x0F000000, 0x0001F401, 0x11000000, 0x00000000, 0x31000000, 0x00000000, 0x00000000, 0x00000000,
0x195A0000, 0x00010000,
0x10000000, 0x00000000,
0x1750005A, 0x01000000,
0x07000001, 0x00002300,
0x05000000, 0x03001400,
0x11000000, 0x00000000,
0x31000000, 0x00000000,
0x00000000, 0x00000000,
}; };
static const uint32_t SimplePlaySample[] = static const uint32_t SimplePlaySample[] = {
{ 0x10000000,
0x10000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000,
0x00000000,
}; };
static const SoundMacroTemplateEntry Entries[] = static const SoundMacroTemplateEntry Entries[] = {
{
{QT_TRANSLATE_NOOP("NewSoundMacroDialog", "Basic Macro"), sizeof(BasicMacro), BasicMacro}, {QT_TRANSLATE_NOOP("NewSoundMacroDialog", "Basic Macro"), sizeof(BasicMacro), BasicMacro},
{QT_TRANSLATE_NOOP("NewSoundMacroDialog", "Looped"), sizeof(Looped), Looped}, {QT_TRANSLATE_NOOP("NewSoundMacroDialog", "Looped"), sizeof(Looped), Looped},
{QT_TRANSLATE_NOOP("NewSoundMacroDialog", "Loop Release"), sizeof(LoopRelease), LoopRelease}, {QT_TRANSLATE_NOOP("NewSoundMacroDialog", "Loop Release"), sizeof(LoopRelease), LoopRelease},
{QT_TRANSLATE_NOOP("NewSoundMacroDialog", "Loop Soft Release"), sizeof(LoopSoftRelease), LoopSoftRelease}, {QT_TRANSLATE_NOOP("NewSoundMacroDialog", "Loop Soft Release"), sizeof(LoopSoftRelease), LoopSoftRelease},
{QT_TRANSLATE_NOOP("NewSoundMacroDialog", "Loop Soft Release No Click"), sizeof(LoopSoftReleaseNoClick), LoopSoftReleaseNoClick}, {QT_TRANSLATE_NOOP("NewSoundMacroDialog", "Loop Soft Release No Click"), sizeof(LoopSoftReleaseNoClick),
LoopSoftReleaseNoClick},
{QT_TRANSLATE_NOOP("NewSoundMacroDialog", "Loop ADSR"), sizeof(LoopADSR), LoopADSR}, {QT_TRANSLATE_NOOP("NewSoundMacroDialog", "Loop ADSR"), sizeof(LoopADSR), LoopADSR},
{QT_TRANSLATE_NOOP("NewSoundMacroDialog", "Loop ADSR Soft Release"), sizeof(LoopADSRSoftRelease), LoopADSRSoftRelease}, {QT_TRANSLATE_NOOP("NewSoundMacroDialog", "Loop ADSR Soft Release"), sizeof(LoopADSRSoftRelease),
LoopADSRSoftRelease},
{QT_TRANSLATE_NOOP("NewSoundMacroDialog", "Loop Hold"), sizeof(LoopHold), LoopHold}, {QT_TRANSLATE_NOOP("NewSoundMacroDialog", "Loop Hold"), sizeof(LoopHold), LoopHold},
{QT_TRANSLATE_NOOP("NewSoundMacroDialog", "One-Shot"), sizeof(OneShot), OneShot}, {QT_TRANSLATE_NOOP("NewSoundMacroDialog", "One-Shot"), sizeof(OneShot), OneShot},
{QT_TRANSLATE_NOOP("NewSoundMacroDialog", "One-Shot Fixed Note"), sizeof(OneShotFixedNote), OneShotFixedNote}, {QT_TRANSLATE_NOOP("NewSoundMacroDialog", "One-Shot Fixed Note"), sizeof(OneShotFixedNote), OneShotFixedNote},
{QT_TRANSLATE_NOOP("NewSoundMacroDialog", "One-Shot No Click"), sizeof(OneShotNoClick), OneShotNoClick}, {QT_TRANSLATE_NOOP("NewSoundMacroDialog", "One-Shot No Click"), sizeof(OneShotNoClick), OneShotNoClick},
{QT_TRANSLATE_NOOP("NewSoundMacroDialog", "One-Shot Fixed No Click"), sizeof(OneShotFixedNoClick), OneShotFixedNoClick}, {QT_TRANSLATE_NOOP("NewSoundMacroDialog", "One-Shot Fixed No Click"), sizeof(OneShotFixedNoClick),
OneShotFixedNoClick},
{QT_TRANSLATE_NOOP("NewSoundMacroDialog", "Bubbles"), sizeof(Bubbles), Bubbles}, {QT_TRANSLATE_NOOP("NewSoundMacroDialog", "Bubbles"), sizeof(Bubbles), Bubbles},
{QT_TRANSLATE_NOOP("NewSoundMacroDialog", "Down Trigger"), sizeof(DownTrigger), DownTrigger}, {QT_TRANSLATE_NOOP("NewSoundMacroDialog", "Down Trigger"), sizeof(DownTrigger), DownTrigger},
{QT_TRANSLATE_NOOP("NewSoundMacroDialog", "Long Fade in and Stop"), sizeof(LongFadeInAndStop), LongFadeInAndStop}, {QT_TRANSLATE_NOOP("NewSoundMacroDialog", "Long Fade in and Stop"), sizeof(LongFadeInAndStop), LongFadeInAndStop},
{QT_TRANSLATE_NOOP("NewSoundMacroDialog", "Fade in and Stop"), sizeof(FadeInAndStop), FadeInAndStop}, {QT_TRANSLATE_NOOP("NewSoundMacroDialog", "Fade in and Stop"), sizeof(FadeInAndStop), FadeInAndStop},
{QT_TRANSLATE_NOOP("NewSoundMacroDialog", "Random Trigger"), sizeof(RandomTrigger), RandomTrigger}, {QT_TRANSLATE_NOOP("NewSoundMacroDialog", "Random Trigger"), sizeof(RandomTrigger), RandomTrigger},
{QT_TRANSLATE_NOOP("NewSoundMacroDialog", "Simple Play Sample"), sizeof(SimplePlaySample), SimplePlaySample} {QT_TRANSLATE_NOOP("NewSoundMacroDialog", "Simple Play Sample"), sizeof(SimplePlaySample), SimplePlaySample}};
};
const SoundMacroTemplateEntry* NewSoundMacroDialog::getSelectedTemplate() const const SoundMacroTemplateEntry* NewSoundMacroDialog::getSelectedTemplate() const {
{
return &Entries[m_combo.currentIndex()]; return &Entries[m_combo.currentIndex()];
} }
NewSoundMacroDialog::NewSoundMacroDialog(const QString& groupName, QWidget* parent) NewSoundMacroDialog::NewSoundMacroDialog(const QString& groupName, QWidget* parent)
: QDialog(parent), : QDialog(parent)
m_le(QString::fromStdString(amuse::SoundMacroId::CurNameDB->generateDefaultName(amuse::NameDB::Type::SoundMacro))), , m_le(QString::fromStdString(amuse::SoundMacroId::CurNameDB->generateDefaultName(amuse::NameDB::Type::SoundMacro)))
m_buttonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal) , m_buttonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal) {
{
setWindowTitle(tr("New Sound Macro")); setWindowTitle(tr("New Sound Macro"));
int idx = 0; int idx = 0;

View File

@ -5,22 +5,20 @@
#include <QComboBox> #include <QComboBox>
#include <QDialogButtonBox> #include <QDialogButtonBox>
struct SoundMacroTemplateEntry struct SoundMacroTemplateEntry {
{
const char* m_name; const char* m_name;
size_t m_length; size_t m_length;
const uint32_t* m_data; const uint32_t* m_data;
}; };
class NewSoundMacroDialog : public QDialog class NewSoundMacroDialog : public QDialog {
{
Q_OBJECT Q_OBJECT
QLineEdit m_le; QLineEdit m_le;
QComboBox m_combo; QComboBox m_combo;
QDialogButtonBox m_buttonBox; QDialogButtonBox m_buttonBox;
public: public:
explicit NewSoundMacroDialog(const QString& groupName, QWidget* parent = Q_NULLPTR); explicit NewSoundMacroDialog(const QString& groupName, QWidget* parent = Q_NULLPTR);
QString getName() const { return m_le.text(); } QString getName() const { return m_le.text(); }
const SoundMacroTemplateEntry* getSelectedTemplate() const; const SoundMacroTemplateEntry* getSelectedTemplate() const;
}; };

File diff suppressed because it is too large Load Diff

View File

@ -17,8 +17,7 @@
class ProjectModel; class ProjectModel;
class EditorUndoCommand; class EditorUndoCommand;
enum AmuseItemEditFlags enum AmuseItemEditFlags {
{
AmuseItemNone = 0, AmuseItemNone = 0,
AmuseItemCut = 1, AmuseItemCut = 1,
AmuseItemCopy = 2, AmuseItemCopy = 2,
@ -28,19 +27,18 @@ enum AmuseItemEditFlags
AmuseItemAll = (AmuseItemCut | AmuseItemCopy | AmuseItemPaste | AmuseItemDelete) AmuseItemAll = (AmuseItemCut | AmuseItemCopy | AmuseItemPaste | AmuseItemDelete)
}; };
class OutlineFilterProxyModel : public QSortFilterProxyModel class OutlineFilterProxyModel : public QSortFilterProxyModel {
{
Q_OBJECT Q_OBJECT
QRegExp m_usageKey; QRegExp m_usageKey;
public: public:
explicit OutlineFilterProxyModel(ProjectModel* source); explicit OutlineFilterProxyModel(ProjectModel* source);
public slots: public slots:
void setFilterRegExp(const QString &pattern); void setFilterRegExp(const QString& pattern);
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const; bool filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const;
}; };
class NullItemProxyModel : public QIdentityProxyModel class NullItemProxyModel : public QIdentityProxyModel {
{
Q_OBJECT Q_OBJECT
public: public:
explicit NullItemProxyModel(ProjectModel* source); explicit NullItemProxyModel(ProjectModel* source);
@ -51,8 +49,7 @@ public:
QVariant data(const QModelIndex& proxyIndex, int role) const; QVariant data(const QModelIndex& proxyIndex, int role) const;
}; };
class PageObjectProxyModel : public QIdentityProxyModel class PageObjectProxyModel : public QIdentityProxyModel {
{
Q_OBJECT Q_OBJECT
public: public:
explicit PageObjectProxyModel(ProjectModel* source); explicit PageObjectProxyModel(ProjectModel* source);
@ -65,27 +62,19 @@ public:
Qt::ItemFlags flags(const QModelIndex& proxyIndex) const; Qt::ItemFlags flags(const QModelIndex& proxyIndex) const;
}; };
class ProjectModel : public QAbstractItemModel class ProjectModel : public QAbstractItemModel {
{
Q_OBJECT Q_OBJECT
public: public:
enum class ImportMode enum class ImportMode { Original, WAVs, Both };
{
Original,
WAVs,
Both
};
struct NameUndoRegistry struct NameUndoRegistry {
{
std::unordered_map<amuse::SongId, std::string> m_songIDs; std::unordered_map<amuse::SongId, std::string> m_songIDs;
std::unordered_map<amuse::SFXId, std::string> m_sfxIDs; std::unordered_map<amuse::SFXId, std::string> m_sfxIDs;
void registerSongName(amuse::SongId id) const; void registerSongName(amuse::SongId id) const;
void unregisterSongName(amuse::SongId id); void unregisterSongName(amuse::SongId id);
void registerSFXName(amuse::SongId id) const; void registerSFXName(amuse::SongId id) const;
void unregisterSFXName(amuse::SongId id); void unregisterSFXName(amuse::SongId id);
void clear() void clear() {
{
m_songIDs.clear(); m_songIDs.clear();
m_sfxIDs.clear(); m_sfxIDs.clear();
} }
@ -100,21 +89,19 @@ private:
amuse::ProjectDatabase m_projectDatabase; amuse::ProjectDatabase m_projectDatabase;
std::unordered_map<QString, std::unique_ptr<amuse::AudioGroupDatabase>> m_groups; std::unordered_map<QString, std::unique_ptr<amuse::AudioGroupDatabase>> m_groups;
struct Song struct Song {
{
QString m_path; QString m_path;
int m_refCount = 0; int m_refCount = 0;
}; };
std::unordered_map<amuse::SongId, Song> m_midiFiles; std::unordered_map<amuse::SongId, Song> m_midiFiles;
public: public:
class INode : public amuse::IObj class INode : public amuse::IObj {
{
friend class ProjectModel; friend class ProjectModel;
virtual void _sortChildren(); virtual void _sortChildren();
public: public:
enum class Type enum class Type {
{
Null, Null,
Root, Root,
Group, // Top-level group Group, // Top-level group
@ -128,23 +115,22 @@ public:
Layer, Layer,
Sample Sample
}; };
protected: protected:
QString m_name; QString m_name;
INode* m_parent = nullptr; INode* m_parent = nullptr;
int m_row = -1; int m_row = -1;
std::vector<amuse::IObjToken<INode>> m_children; std::vector<amuse::IObjToken<INode>> m_children;
amuse::IObjToken<INode> m_nullChild; amuse::IObjToken<INode> m_nullChild;
public: public:
virtual ~INode() = default; virtual ~INode() = default;
INode(const QString& name); INode(const QString& name);
INode(INode* parent) : m_parent(parent), m_row(0) INode(INode* parent) : m_parent(parent), m_row(0) { /* ONLY USED BY NULL NODE! */
{
/* ONLY USED BY NULL NODE! */
} }
int childCount() const { return int(m_children.size()); } int childCount() const { return int(m_children.size()); }
INode* child(int row) const INode* child(int row) const {
{
if (row == m_children.size()) if (row == m_children.size())
return nullChild(); return nullChild();
return m_children[row].get(); return m_children[row].get();
@ -153,23 +139,20 @@ public:
INode* parent() const { return m_parent; } INode* parent() const { return m_parent; }
int row() const { return m_row; } int row() const { return m_row; }
void reindexRows(int row) void reindexRows(int row) {
{
for (auto it = m_children.begin() + row; it != m_children.end(); ++it) for (auto it = m_children.begin() + row; it != m_children.end(); ++it)
(*it)->m_row = row++; (*it)->m_row = row++;
m_nullChild->m_row = row; m_nullChild->m_row = row;
} }
void insertChild(amuse::ObjToken<INode> n) void insertChild(amuse::ObjToken<INode> n) {
{
assert(n->m_parent == nullptr && "Inserting already-parented node"); assert(n->m_parent == nullptr && "Inserting already-parented node");
n->m_parent = this; n->m_parent = this;
int row = hypotheticalIndex(n->name()); int row = hypotheticalIndex(n->name());
m_children.insert(m_children.begin() + row, n.get()); m_children.insert(m_children.begin() + row, n.get());
reindexRows(row); reindexRows(row);
} }
amuse::ObjToken<INode> removeChild(INode* n) amuse::ObjToken<INode> removeChild(INode* n) {
{
amuse::ObjToken<INode> ret = n; amuse::ObjToken<INode> ret = n;
int row = ret->row(); int row = ret->row();
assert(ret.get() == m_children.at(row).get() && "Removing non-child from node"); assert(ret.get() == m_children.at(row).get() && "Removing non-child from node");
@ -181,16 +164,14 @@ public:
} }
void reserve(size_t sz) { m_children.reserve(sz); } void reserve(size_t sz) { m_children.reserve(sz); }
template<class T, class... _Args> template <class T, class... _Args>
T& makeChild(_Args&&... args) T& makeChild(_Args&&... args) {
{
auto tok = amuse::MakeObj<T>(std::forward<_Args>(args)...); auto tok = amuse::MakeObj<T>(std::forward<_Args>(args)...);
insertChild(tok.get()); insertChild(tok.get());
return static_cast<T&>(*tok); return static_cast<T&>(*tok);
} }
template<class T, class... _Args> template <class T, class... _Args>
T& _appendChild(_Args&&... args) T& _appendChild(_Args&&... args) {
{
auto tok = amuse::MakeObj<T>(std::forward<_Args>(args)...); auto tok = amuse::MakeObj<T>(std::forward<_Args>(args)...);
tok->m_parent = this; tok->m_parent = this;
tok->m_row = m_children.size(); tok->m_row = m_children.size();
@ -199,8 +180,7 @@ public:
return static_cast<T&>(*tok); return static_cast<T&>(*tok);
} }
INode* findChild(const QString& name) const INode* findChild(const QString& name) const {
{
int idx = hypotheticalIndex(name); int idx = hypotheticalIndex(name);
if (idx >= m_children.size()) if (idx >= m_children.size())
return nullptr; return nullptr;
@ -210,16 +190,14 @@ public:
return nullptr; return nullptr;
} }
bool depthTraverse(const std::function<bool(INode* node)>& func) bool depthTraverse(const std::function<bool(INode* node)>& func) {
{
for (auto& n : m_children) for (auto& n : m_children)
if (!n->depthTraverse(func)) if (!n->depthTraverse(func))
break; break;
return func(this); return func(this);
} }
bool oneLevelTraverse(const std::function<bool(INode* node)>& func) bool oneLevelTraverse(const std::function<bool(INode* node)>& func) {
{
for (auto& n : m_children) for (auto& n : m_children)
if (!func(n.get())) if (!func(n.get()))
return false; return false;
@ -240,16 +218,14 @@ public:
virtual void registerNames(const NameUndoRegistry& registry) const {} virtual void registerNames(const NameUndoRegistry& registry) const {}
virtual void unregisterNames(NameUndoRegistry& registry) const {} virtual void unregisterNames(NameUndoRegistry& registry) const {}
}; };
struct NullNode final : INode struct NullNode final : INode {
{
NullNode(INode* parent) : INode(parent) {} NullNode(INode* parent) : INode(parent) {}
Type type() const { return Type::Null; } Type type() const { return Type::Null; }
QString text() const { return {}; } QString text() const { return {}; }
QIcon icon() const { return {}; } QIcon icon() const { return {}; }
}; };
struct RootNode final : INode struct RootNode final : INode {
{
RootNode() : INode(QStringLiteral("<root>")) {} RootNode() : INode(QStringLiteral("<root>")) {}
Type type() const { return Type::Root; } Type type() const { return Type::Root; }
@ -259,8 +235,7 @@ public:
}; };
struct CollectionNode; struct CollectionNode;
struct BasePoolObjectNode; struct BasePoolObjectNode;
struct GroupNode final : INode struct GroupNode final : INode {
{
std::unordered_map<QString, std::unique_ptr<amuse::AudioGroupDatabase>>::iterator m_it; std::unordered_map<QString, std::unique_ptr<amuse::AudioGroupDatabase>>::iterator m_it;
GroupNode(const QString& name) : INode(name) {} GroupNode(const QString& name) : INode(name) {}
GroupNode(std::unordered_map<QString, std::unique_ptr<amuse::AudioGroupDatabase>>::iterator it) GroupNode(std::unordered_map<QString, std::unique_ptr<amuse::AudioGroupDatabase>>::iterator it)
@ -279,12 +254,10 @@ public:
amuse::AudioGroupDatabase* getAudioGroup() const { return m_it->second.get(); } amuse::AudioGroupDatabase* getAudioGroup() const { return m_it->second.get(); }
BasePoolObjectNode* pageObjectNodeOfId(amuse::ObjectId id) const; BasePoolObjectNode* pageObjectNodeOfId(amuse::ObjectId id) const;
}; };
struct SongGroupNode final : INode struct SongGroupNode final : INode {
{
amuse::GroupId m_id; amuse::GroupId m_id;
amuse::ObjToken<amuse::SongGroupIndex> m_index; amuse::ObjToken<amuse::SongGroupIndex> m_index;
SongGroupNode(const QString& name, amuse::ObjToken<amuse::SongGroupIndex> index) SongGroupNode(const QString& name, amuse::ObjToken<amuse::SongGroupIndex> index) : INode(name), m_index(index) {}
: INode(name), m_index(index) {}
SongGroupNode(amuse::GroupId id, amuse::ObjToken<amuse::SongGroupIndex> index) SongGroupNode(amuse::GroupId id, amuse::ObjToken<amuse::SongGroupIndex> index)
: INode(amuse::GroupId::CurNameDB->resolveNameFromId(id).data()), m_id(id), m_index(index) {} : INode(amuse::GroupId::CurNameDB->resolveNameFromId(id).data()), m_id(id), m_index(index) {}
@ -296,25 +269,21 @@ public:
amuse::NameDB* getNameDb() const { return amuse::GroupId::CurNameDB; } amuse::NameDB* getNameDb() const { return amuse::GroupId::CurNameDB; }
void registerNames(const NameUndoRegistry& registry) const void registerNames(const NameUndoRegistry& registry) const {
{
amuse::GroupId::CurNameDB->registerPair(text().toUtf8().data(), m_id); amuse::GroupId::CurNameDB->registerPair(text().toUtf8().data(), m_id);
for (auto& p : m_index->m_midiSetups) for (auto& p : m_index->m_midiSetups)
registry.registerSongName(p.first); registry.registerSongName(p.first);
} }
void unregisterNames(NameUndoRegistry& registry) const void unregisterNames(NameUndoRegistry& registry) const {
{
amuse::GroupId::CurNameDB->remove(m_id); amuse::GroupId::CurNameDB->remove(m_id);
for (auto& p : m_index->m_midiSetups) for (auto& p : m_index->m_midiSetups)
registry.unregisterSongName(p.first); registry.unregisterSongName(p.first);
} }
}; };
struct SoundGroupNode final : INode struct SoundGroupNode final : INode {
{
amuse::GroupId m_id; amuse::GroupId m_id;
amuse::ObjToken<amuse::SFXGroupIndex> m_index; amuse::ObjToken<amuse::SFXGroupIndex> m_index;
SoundGroupNode(const QString& name, amuse::ObjToken<amuse::SFXGroupIndex> index) SoundGroupNode(const QString& name, amuse::ObjToken<amuse::SFXGroupIndex> index) : INode(name), m_index(index) {}
: INode(name), m_index(index) {}
SoundGroupNode(amuse::GroupId id, amuse::ObjToken<amuse::SFXGroupIndex> index) SoundGroupNode(amuse::GroupId id, amuse::ObjToken<amuse::SFXGroupIndex> index)
: INode(amuse::GroupId::CurNameDB->resolveNameFromId(id).data()), m_id(id), m_index(index) {} : INode(amuse::GroupId::CurNameDB->resolveNameFromId(id).data()), m_id(id), m_index(index) {}
@ -326,21 +295,18 @@ public:
amuse::NameDB* getNameDb() const { return amuse::GroupId::CurNameDB; } amuse::NameDB* getNameDb() const { return amuse::GroupId::CurNameDB; }
void registerNames(const NameUndoRegistry& registry) const void registerNames(const NameUndoRegistry& registry) const {
{
amuse::GroupId::CurNameDB->registerPair(text().toUtf8().data(), m_id); amuse::GroupId::CurNameDB->registerPair(text().toUtf8().data(), m_id);
for (auto& p : m_index->m_sfxEntries) for (auto& p : m_index->m_sfxEntries)
registry.registerSFXName(p.first); registry.registerSFXName(p.first);
} }
void unregisterNames(NameUndoRegistry& registry) const void unregisterNames(NameUndoRegistry& registry) const {
{
amuse::GroupId::CurNameDB->remove(m_id); amuse::GroupId::CurNameDB->remove(m_id);
for (auto& p : m_index->m_sfxEntries) for (auto& p : m_index->m_sfxEntries)
registry.unregisterSFXName(p.first); registry.unregisterSFXName(p.first);
} }
}; };
struct CollectionNode final : INode struct CollectionNode final : INode {
{
QIcon m_icon; QIcon m_icon;
Type m_collectionType; Type m_collectionType;
CollectionNode(const QString& name, const QIcon& icon, Type collectionType) CollectionNode(const QString& name, const QIcon& icon, Type collectionType)
@ -357,19 +323,16 @@ public:
BasePoolObjectNode* nodeOfIndex(int idx) const; BasePoolObjectNode* nodeOfIndex(int idx) const;
BasePoolObjectNode* nodeOfId(amuse::ObjectId id) const; BasePoolObjectNode* nodeOfId(amuse::ObjectId id) const;
}; };
struct BasePoolObjectNode : INode struct BasePoolObjectNode : INode {
{
amuse::ObjectId m_id; amuse::ObjectId m_id;
BasePoolObjectNode(const QString& name) : INode(name) {} BasePoolObjectNode(const QString& name) : INode(name) {}
BasePoolObjectNode(amuse::ObjectId id, const QString& name) BasePoolObjectNode(amuse::ObjectId id, const QString& name) : INode(name), m_id(id) {}
: INode(name), m_id(id) {}
amuse::ObjectId id() const { return m_id; } amuse::ObjectId id() const { return m_id; }
QString text() const { return m_name; } QString text() const { return m_name; }
QIcon icon() const { return {}; } QIcon icon() const { return {}; }
}; };
template <class ID, class T, INode::Type TP> template <class ID, class T, INode::Type TP>
struct PoolObjectNode final : BasePoolObjectNode struct PoolObjectNode final : BasePoolObjectNode {
{
amuse::ObjToken<T> m_obj; amuse::ObjToken<T> m_obj;
PoolObjectNode(const QString& name, amuse::ObjToken<T> obj) : BasePoolObjectNode(name), m_obj(obj) {} PoolObjectNode(const QString& name, amuse::ObjToken<T> obj) : BasePoolObjectNode(name), m_obj(obj) {}
PoolObjectNode(ID id, amuse::ObjToken<T> obj) PoolObjectNode(ID id, amuse::ObjToken<T> obj)
@ -378,18 +341,11 @@ public:
Type type() const { return TP; } Type type() const { return TP; }
AmuseItemEditFlags editFlags() const { return TP == INode::Type::Sample ? AmuseItemNoCut : AmuseItemAll; } AmuseItemEditFlags editFlags() const { return TP == INode::Type::Sample ? AmuseItemNoCut : AmuseItemAll; }
void registerNames(const NameUndoRegistry& registry) const void registerNames(const NameUndoRegistry& registry) const {
{
ID::CurNameDB->registerPair(text().toUtf8().data(), m_id); ID::CurNameDB->registerPair(text().toUtf8().data(), m_id);
} }
void unregisterNames(NameUndoRegistry& registry) const void unregisterNames(NameUndoRegistry& registry) const { ID::CurNameDB->remove(m_id); }
{ amuse::NameDB* getNameDb() const { return ID::CurNameDB; }
ID::CurNameDB->remove(m_id);
}
amuse::NameDB* getNameDb() const
{
return ID::CurNameDB;
}
}; };
using SoundMacroNode = PoolObjectNode<amuse::SoundMacroId, amuse::SoundMacro, INode::Type::SoundMacro>; using SoundMacroNode = PoolObjectNode<amuse::SoundMacroId, amuse::SoundMacro, INode::Type::SoundMacro>;
using ADSRNode = PoolObjectNode<amuse::TableId, std::unique_ptr<amuse::ITable>, INode::Type::ADSR>; using ADSRNode = PoolObjectNode<amuse::TableId, std::unique_ptr<amuse::ITable>, INode::Type::ADSR>;
@ -416,8 +372,8 @@ public:
void openSongsData(); void openSongsData();
void importSongsData(const QString& path); void importSongsData(const QString& path);
bool reloadSampleData(const QString& groupName, UIMessenger& messenger); bool reloadSampleData(const QString& groupName, UIMessenger& messenger);
bool importGroupData(const QString& groupName, const amuse::AudioGroupData& data, bool importGroupData(const QString& groupName, const amuse::AudioGroupData& data, ImportMode mode,
ImportMode mode, UIMessenger& messenger); UIMessenger& messenger);
void saveSongsIndex(); void saveSongsIndex();
bool saveToFile(UIMessenger& messenger); bool saveToFile(UIMessenger& messenger);
QStringList getGroupList() const; QStringList getGroupList() const;
@ -428,7 +384,7 @@ public:
void updateNodeNames(); void updateNodeNames();
bool ensureModelData(); bool ensureModelData();
QModelIndex proxyCreateIndex(int arow, int acolumn, void *adata) const; QModelIndex proxyCreateIndex(int arow, int acolumn, void* adata) const;
QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const; QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const;
QModelIndex index(INode* node) const; QModelIndex index(INode* node) const;
QModelIndex parent(const QModelIndex& child) const; QModelIndex parent(const QModelIndex& child) const;
@ -463,8 +419,7 @@ public:
void _delPoolNode(NT* node, GroupNode* parent, NameUndoRegistry& registry, T& container); void _delPoolNode(NT* node, GroupNode* parent, NameUndoRegistry& registry, T& container);
void _addNode(SoundMacroNode* node, GroupNode* parent, const NameUndoRegistry& registry); void _addNode(SoundMacroNode* node, GroupNode* parent, const NameUndoRegistry& registry);
void _delNode(SoundMacroNode* node, GroupNode* parent, NameUndoRegistry& registry); void _delNode(SoundMacroNode* node, GroupNode* parent, NameUndoRegistry& registry);
SoundMacroNode* newSoundMacro(GroupNode* group, const QString& name, SoundMacroNode* newSoundMacro(GroupNode* group, const QString& name, const SoundMacroTemplateEntry* templ = nullptr);
const SoundMacroTemplateEntry* templ = nullptr);
void _addNode(ADSRNode* node, GroupNode* parent, const NameUndoRegistry& registry); void _addNode(ADSRNode* node, GroupNode* parent, const NameUndoRegistry& registry);
void _delNode(ADSRNode* node, GroupNode* parent, NameUndoRegistry& registry); void _delNode(ADSRNode* node, GroupNode* parent, NameUndoRegistry& registry);
ADSRNode* newADSR(GroupNode* group, const QString& name); ADSRNode* newADSR(GroupNode* group, const QString& name);
@ -486,7 +441,7 @@ public:
QStringList mimeTypes() const; QStringList mimeTypes() const;
QMimeData* mimeData(const QModelIndexList& indexes) const; QMimeData* mimeData(const QModelIndexList& indexes) const;
bool dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex &parent); bool dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent);
void cut(const QModelIndex& index); void cut(const QModelIndex& index);
void copy(const QModelIndex& index); void copy(const QModelIndex& index);
@ -510,5 +465,3 @@ public:
void setIdDatabases(INode* context) const; void setIdDatabases(INode* context) const;
}; };

View File

@ -7,19 +7,15 @@
#include <QScrollBar> #include <QScrollBar>
#include <QCheckBox> #include <QCheckBox>
SampleEditor* SampleView::getEditor() const SampleEditor* SampleView::getEditor() const {
{
return qobject_cast<SampleEditor*>(parentWidget()->parentWidget()->parentWidget()); return qobject_cast<SampleEditor*>(parentWidget()->parentWidget()->parentWidget());
} }
void SampleView::seekToSample(qreal sample) void SampleView::seekToSample(qreal sample) {
{
sample = std::min(sample, qreal(m_sample->getNumSamples())); sample = std::min(sample, qreal(m_sample->getNumSamples()));
if (m_sample->isFormatDSP()) if (m_sample->isFormatDSP()) {
{ if (sample < m_curSamplePos) {
if (sample < m_curSamplePos)
{
m_prev1 = m_prev2 = 0; m_prev1 = m_prev2 = 0;
m_curSamplePos = 0.0; m_curSamplePos = 0.0;
} }
@ -29,45 +25,38 @@ void SampleView::seekToSample(qreal sample)
uint32_t endBlock = uint32_t(sample) / 14; uint32_t endBlock = uint32_t(sample) / 14;
uint32_t endRem = uint32_t(sample) % 14; uint32_t endRem = uint32_t(sample) % 14;
if (startRem) if (startRem) {
{
uint32_t end = 14; uint32_t end = 14;
if (startBlock == endBlock) if (startBlock == endBlock) {
{
end = endRem; end = endRem;
endRem = 0; endRem = 0;
} }
DSPDecompressFrameRangedStateOnly(m_sampleData + 8 * startBlock, m_sample->m_ADPCMParms.dsp.m_coefs, DSPDecompressFrameRangedStateOnly(m_sampleData + 8 * startBlock, m_sample->m_ADPCMParms.dsp.m_coefs, &m_prev1,
&m_prev1, &m_prev2, startRem, end); &m_prev2, startRem, end);
if (end == 14) if (end == 14)
++startBlock; ++startBlock;
} }
for (uint32_t b = startBlock; b < endBlock; ++b) for (uint32_t b = startBlock; b < endBlock; ++b) {
{ DSPDecompressFrameStateOnly(m_sampleData + 8 * b, m_sample->m_ADPCMParms.dsp.m_coefs, &m_prev1, &m_prev2, 14);
DSPDecompressFrameStateOnly(m_sampleData + 8 * b, m_sample->m_ADPCMParms.dsp.m_coefs,
&m_prev1, &m_prev2, 14);
} }
if (endRem) if (endRem) {
{ DSPDecompressFrameStateOnly(m_sampleData + 8 * endBlock, m_sample->m_ADPCMParms.dsp.m_coefs, &m_prev1, &m_prev2,
DSPDecompressFrameStateOnly(m_sampleData + 8 * endBlock, m_sample->m_ADPCMParms.dsp.m_coefs, endRem);
&m_prev1, &m_prev2, endRem);
} }
} }
m_curSamplePos = sample; m_curSamplePos = sample;
} }
std::pair<std::pair<qreal, qreal>, std::pair<qreal, qreal>> SampleView::iterateSampleInterval(qreal interval) std::pair<std::pair<qreal, qreal>, std::pair<qreal, qreal>> SampleView::iterateSampleInterval(qreal interval) {
{
std::pair<std::pair<qreal, qreal>, std::pair<qreal, qreal>> ret = {{0.0, 1.0}, {0.0, -1.0}}; // min,max avg,peak std::pair<std::pair<qreal, qreal>, std::pair<qreal, qreal>> ret = {{0.0, 1.0}, {0.0, -1.0}}; // min,max avg,peak
qreal avg = 0.0; qreal avg = 0.0;
qreal div = 0.0; qreal div = 0.0;
qreal endSample = std::min(m_curSamplePos + interval, qreal(m_sample->getNumSamples())); qreal endSample = std::min(m_curSamplePos + interval, qreal(m_sample->getNumSamples()));
auto accumulate = [&ret, &avg, &div](int16_t sample) auto accumulate = [&ret, &avg, &div](int16_t sample) {
{
qreal sampleF = sample / 32768.0; qreal sampleF = sample / 32768.0;
avg += sampleF; avg += sampleF;
div += 1.0; div += 1.0;
@ -75,8 +64,7 @@ std::pair<std::pair<qreal, qreal>, std::pair<qreal, qreal>> SampleView::iterateS
ret.second.second = std::max(ret.second.second, sampleF); ret.second.second = std::max(ret.second.second, sampleF);
}; };
if (m_sample->isFormatDSP()) if (m_sample->isFormatDSP()) {
{
uint32_t startBlock = uint32_t(m_curSamplePos) / 14; uint32_t startBlock = uint32_t(m_curSamplePos) / 14;
uint32_t startRem = uint32_t(m_curSamplePos) % 14; uint32_t startRem = uint32_t(m_curSamplePos) % 14;
uint32_t endBlock = uint32_t(endSample) / 14; uint32_t endBlock = uint32_t(endSample) / 14;
@ -84,40 +72,33 @@ std::pair<std::pair<qreal, qreal>, std::pair<qreal, qreal>> SampleView::iterateS
int16_t sampleBlock[14]; int16_t sampleBlock[14];
if (startRem) if (startRem) {
{
uint32_t end = 14; uint32_t end = 14;
if (startBlock == endBlock) if (startBlock == endBlock) {
{
end = endRem; end = endRem;
endRem = 0; endRem = 0;
} }
DSPDecompressFrameRanged(sampleBlock, m_sampleData + 8 * startBlock, m_sample->m_ADPCMParms.dsp.m_coefs, DSPDecompressFrameRanged(sampleBlock, m_sampleData + 8 * startBlock, m_sample->m_ADPCMParms.dsp.m_coefs, &m_prev1,
&m_prev1, &m_prev2, startRem, end); &m_prev2, startRem, end);
for (int s = 0; s < end - startRem; ++s) for (int s = 0; s < end - startRem; ++s)
accumulate(sampleBlock[s]); accumulate(sampleBlock[s]);
if (end == 14) if (end == 14)
++startBlock; ++startBlock;
} }
for (uint32_t b = startBlock; b < endBlock; ++b) for (uint32_t b = startBlock; b < endBlock; ++b) {
{ DSPDecompressFrame(sampleBlock, m_sampleData + 8 * b, m_sample->m_ADPCMParms.dsp.m_coefs, &m_prev1, &m_prev2, 14);
DSPDecompressFrame(sampleBlock, m_sampleData + 8 * b, m_sample->m_ADPCMParms.dsp.m_coefs,
&m_prev1, &m_prev2, 14);
for (int s = 0; s < 14; ++s) for (int s = 0; s < 14; ++s)
accumulate(sampleBlock[s]); accumulate(sampleBlock[s]);
} }
if (endRem) if (endRem) {
{ DSPDecompressFrame(sampleBlock, m_sampleData + 8 * endBlock, m_sample->m_ADPCMParms.dsp.m_coefs, &m_prev1,
DSPDecompressFrame(sampleBlock, m_sampleData + 8 * endBlock, m_sample->m_ADPCMParms.dsp.m_coefs, &m_prev2, endRem);
&m_prev1, &m_prev2, endRem);
for (int s = 0; s < endRem; ++s) for (int s = 0; s < endRem; ++s)
accumulate(sampleBlock[s]); accumulate(sampleBlock[s]);
} }
} } else if (m_sample->getSampleFormat() == amuse::SampleFormat::PCM_PC) {
else if (m_sample->getSampleFormat() == amuse::SampleFormat::PCM_PC)
{
for (uint32_t s = uint32_t(m_curSamplePos); s < uint32_t(endSample); ++s) for (uint32_t s = uint32_t(m_curSamplePos); s < uint32_t(endSample); ++s)
accumulate(reinterpret_cast<const int16_t*>(m_sampleData)[s]); accumulate(reinterpret_cast<const int16_t*>(m_sampleData)[s]);
} }
@ -129,13 +110,10 @@ std::pair<std::pair<qreal, qreal>, std::pair<qreal, qreal>> SampleView::iterateS
avg /= div; avg /= div;
if (avg > 0.0) if (avg > 0.0) {
{
ret.first.first = ret.first.second; ret.first.first = ret.first.second;
ret.second.first = avg; ret.second.first = avg;
} } else {
else
{
ret.first.first = avg; ret.first.first = avg;
ret.second.first = ret.second.second; ret.second.first = ret.second.second;
} }
@ -143,8 +121,7 @@ std::pair<std::pair<qreal, qreal>, std::pair<qreal, qreal>> SampleView::iterateS
return ret; return ret;
} }
void SampleView::paintEvent(QPaintEvent* ev) void SampleView::paintEvent(QPaintEvent* ev) {
{
QPainter painter(this); QPainter painter(this);
constexpr int rulerHeight = 28; constexpr int rulerHeight = 28;
@ -157,15 +134,13 @@ void SampleView::paintEvent(QPaintEvent* ev)
qreal deviceSamplesPerPx = m_samplesPerPx / deviceRatio; qreal deviceSamplesPerPx = m_samplesPerPx / deviceRatio;
qreal startSample = rectStart * m_samplesPerPx; qreal startSample = rectStart * m_samplesPerPx;
qreal startSampleRem = std::fmod(startSample, deviceSamplesPerPx); qreal startSampleRem = std::fmod(startSample, deviceSamplesPerPx);
if (startSampleRem > DBL_EPSILON) if (startSampleRem > DBL_EPSILON) {
{
startSample -= startSampleRem; startSample -= startSampleRem;
deviceWidth += startSampleRem; deviceWidth += startSampleRem;
rectStart = startSample / m_samplesPerPx; rectStart = startSample / m_samplesPerPx;
} }
if (m_sample) if (m_sample) {
{
QPen peakPen(QColor(255, 147, 41), increment); QPen peakPen(QColor(255, 147, 41), increment);
QPen avgPen(QColor(254, 177, 68), increment); QPen avgPen(QColor(254, 177, 68), increment);
@ -173,20 +148,16 @@ void SampleView::paintEvent(QPaintEvent* ev)
qreal trans = sampleHeight / 2.0; qreal trans = sampleHeight / 2.0;
std::pair<std::pair<qreal, qreal>, std::pair<qreal, qreal>> lastAvgPeak; std::pair<std::pair<qreal, qreal>, std::pair<qreal, qreal>> lastAvgPeak;
if (startSample >= deviceSamplesPerPx) if (startSample >= deviceSamplesPerPx) {
{
seekToSample(startSample - deviceSamplesPerPx); seekToSample(startSample - deviceSamplesPerPx);
lastAvgPeak = iterateSampleInterval(deviceSamplesPerPx); lastAvgPeak = iterateSampleInterval(deviceSamplesPerPx);
} } else {
else
{
seekToSample(startSample); seekToSample(startSample);
lastAvgPeak = std::pair<std::pair<qreal, qreal>, std::pair<qreal, qreal>>{}; lastAvgPeak = std::pair<std::pair<qreal, qreal>, std::pair<qreal, qreal>>{};
} }
std::pair<std::pair<qreal, qreal>, std::pair<qreal, qreal>> avgPeak; std::pair<std::pair<qreal, qreal>, std::pair<qreal, qreal>> avgPeak;
for (qreal i = 0.0; i < deviceWidth; i += increment) for (qreal i = 0.0; i < deviceWidth; i += increment) {
{
if (m_curSamplePos + deviceSamplesPerPx > m_sample->getNumSamples()) if (m_curSamplePos + deviceSamplesPerPx > m_sample->getNumSamples())
break; break;
if (i == 0.0 || std::floor(m_curSamplePos) != std::floor(m_curSamplePos + deviceSamplesPerPx)) if (i == 0.0 || std::floor(m_curSamplePos) != std::floor(m_curSamplePos + deviceSamplesPerPx))
@ -228,22 +199,18 @@ void SampleView::paintEvent(QPaintEvent* ev)
qreal samplePos = startX * m_samplesPerPx; qreal samplePos = startX * m_samplesPerPx;
painter.setFont(m_rulerFont); painter.setFont(m_rulerFont);
painter.setPen(QPen(QColor(127, 127, 127), increment)); painter.setPen(QPen(QColor(127, 127, 127), increment));
for (int i = startX; i < ev->rect().x() + ev->rect().width() + numSpacing; ++i) for (int i = startX; i < ev->rect().x() + ev->rect().width() + numSpacing; ++i) {
{
int thisNumDiv = int(i / numSpacing); int thisNumDiv = int(i / numSpacing);
int thisTickDiv = int(i / tickSpacing); int thisTickDiv = int(i / tickSpacing);
if (thisNumDiv != lastNumDiv) if (thisNumDiv != lastNumDiv) {
{
painter.drawLine(i, sampleHeight + 1, i, sampleHeight + 8); painter.drawLine(i, sampleHeight + 1, i, sampleHeight + 8);
lastNumDiv = thisNumDiv; lastNumDiv = thisNumDiv;
lastTickDiv = thisTickDiv; lastTickDiv = thisTickDiv;
painter.drawText(QRectF(i - numSpacing / 2.0, sampleHeight + 11.0, numSpacing, 12.0), painter.drawText(QRectF(i - numSpacing / 2.0, sampleHeight + 11.0, numSpacing, 12.0),
QString::number(int(samplePos)), QTextOption(Qt::AlignCenter)); QString::number(int(samplePos)), QTextOption(Qt::AlignCenter));
} } else if (thisTickDiv != lastTickDiv) {
else if (thisTickDiv != lastTickDiv)
{
painter.drawLine(i, sampleHeight + 1, i, sampleHeight + 5); painter.drawLine(i, sampleHeight + 1, i, sampleHeight + 5);
lastTickDiv = thisTickDiv; lastTickDiv = thisTickDiv;
} }
@ -251,10 +218,8 @@ void SampleView::paintEvent(QPaintEvent* ev)
samplePos += m_samplesPerPx; samplePos += m_samplesPerPx;
} }
if (m_sample) if (m_sample) {
{ if (m_sample->isLooped()) {
if (m_sample->isLooped())
{
int loopStart = m_sample->m_loopStartSample; int loopStart = m_sample->m_loopStartSample;
int loopEnd = loopStart + m_sample->m_loopLengthSamples - 1; int loopEnd = loopStart + m_sample->m_loopLengthSamples - 1;
QPointF points[4]; QPointF points[4];
@ -280,8 +245,7 @@ void SampleView::paintEvent(QPaintEvent* ev)
painter.drawPolygon(points, 4); painter.drawPolygon(points, 4);
} }
if (m_displaySamplePos >= 0) if (m_displaySamplePos >= 0) {
{
painter.setPen(QPen(Qt::white, increment)); painter.setPen(QPen(Qt::white, increment));
qreal pos = m_displaySamplePos / m_samplesPerPx; qreal pos = m_displaySamplePos / m_samplesPerPx;
painter.drawLine(QPointF(pos, 0.0), QPointF(pos, height())); painter.drawLine(QPointF(pos, 0.0), QPointF(pos, height()));
@ -289,15 +253,12 @@ void SampleView::paintEvent(QPaintEvent* ev)
} }
} }
void SampleView::calculateSamplesPerPx() void SampleView::calculateSamplesPerPx() {
{
m_samplesPerPx = (1.0 - m_zoomFactor) * m_baseSamplesPerPx + m_zoomFactor * 1.0; m_samplesPerPx = (1.0 - m_zoomFactor) * m_baseSamplesPerPx + m_zoomFactor * 1.0;
} }
void SampleView::resetZoom() void SampleView::resetZoom() {
{ if (QScrollArea* scroll = qobject_cast<QScrollArea*>(parentWidget()->parentWidget())) {
if (QScrollArea* scroll = qobject_cast<QScrollArea*>(parentWidget()->parentWidget()))
{
m_baseSamplesPerPx = m_sample->getNumSamples() / qreal(scroll->width() - 4); m_baseSamplesPerPx = m_sample->getNumSamples() / qreal(scroll->width() - 4);
calculateSamplesPerPx(); calculateSamplesPerPx();
setMinimumWidth(int(m_sample->getNumSamples() / m_samplesPerPx) + 1); setMinimumWidth(int(m_sample->getNumSamples() / m_samplesPerPx) + 1);
@ -305,23 +266,17 @@ void SampleView::resetZoom()
} }
} }
void SampleView::setZoom(int zVal) void SampleView::setZoom(int zVal) {
{
m_zoomFactor = zVal / 99.0; m_zoomFactor = zVal / 99.0;
calculateSamplesPerPx(); calculateSamplesPerPx();
setMinimumWidth(int(m_sample->getNumSamples() / m_samplesPerPx) + 1); setMinimumWidth(int(m_sample->getNumSamples() / m_samplesPerPx) + 1);
update(); update();
} }
void SampleView::showEvent(QShowEvent* ev) void SampleView::showEvent(QShowEvent* ev) { setZoom(0); }
{
setZoom(0);
}
void SampleView::mousePressEvent(QMouseEvent* ev) void SampleView::mousePressEvent(QMouseEvent* ev) {
{ if (m_sample && m_sample->isLooped()) {
if (m_sample && m_sample->isLooped())
{
int loopStart = m_sample->m_loopStartSample; int loopStart = m_sample->m_loopStartSample;
int startPos = int(loopStart / m_samplesPerPx); int startPos = int(loopStart / m_samplesPerPx);
int startDelta = std::abs(startPos - ev->pos().x()); int startDelta = std::abs(startPos - ev->pos().x());
@ -332,21 +287,17 @@ void SampleView::mousePressEvent(QMouseEvent* ev)
int endDelta = std::abs(endPos - ev->pos().x()); int endDelta = std::abs(endPos - ev->pos().x());
bool endPass = endDelta < 20; bool endPass = endDelta < 20;
if (startPass && endPass) if (startPass && endPass) {
{ if (startDelta == endDelta) {
if (startDelta == endDelta)
{
if (ev->pos().x() < startPos) if (ev->pos().x() < startPos)
m_dragState = DragState::Start; m_dragState = DragState::Start;
else else
m_dragState = DragState::End; m_dragState = DragState::End;
} } else if (startDelta < endDelta)
else if (startDelta < endDelta)
m_dragState = DragState::Start; m_dragState = DragState::Start;
else else
m_dragState = DragState::End; m_dragState = DragState::End;
} } else if (startPass)
else if (startPass)
m_dragState = DragState::Start; m_dragState = DragState::Start;
else if (endPass) else if (endPass)
m_dragState = DragState::End; m_dragState = DragState::End;
@ -357,31 +308,26 @@ void SampleView::mousePressEvent(QMouseEvent* ev)
} }
} }
void SampleView::mouseReleaseEvent(QMouseEvent* ev) void SampleView::mouseReleaseEvent(QMouseEvent* ev) {
{
m_dragState = DragState::None; m_dragState = DragState::None;
getEditor()->m_controls->setFileWrite(true); getEditor()->m_controls->setFileWrite(true);
} }
void SampleView::mouseMoveEvent(QMouseEvent* ev) void SampleView::mouseMoveEvent(QMouseEvent* ev) {
{
if (m_dragState == DragState::Start) if (m_dragState == DragState::Start)
getEditor()->m_controls->setLoopStartSample(int(ev->pos().x() * m_samplesPerPx)); getEditor()->m_controls->setLoopStartSample(int(ev->pos().x() * m_samplesPerPx));
else if (m_dragState == DragState::End) else if (m_dragState == DragState::End)
getEditor()->m_controls->setLoopEndSample(int(ev->pos().x() * m_samplesPerPx)); getEditor()->m_controls->setLoopEndSample(int(ev->pos().x() * m_samplesPerPx));
} }
void SampleView::wheelEvent(QWheelEvent* ev) void SampleView::wheelEvent(QWheelEvent* ev) {
{ if (QScrollArea* scroll = qobject_cast<QScrollArea*>(parentWidget()->parentWidget())) {
if (QScrollArea* scroll = qobject_cast<QScrollArea*>(parentWidget()->parentWidget()))
{
/* Send wheel event directly to the scroll bar */ /* Send wheel event directly to the scroll bar */
QApplication::sendEvent(scroll->horizontalScrollBar(), ev); QApplication::sendEvent(scroll->horizontalScrollBar(), ev);
} }
} }
bool SampleView::loadData(ProjectModel::SampleNode* node) bool SampleView::loadData(ProjectModel::SampleNode* node) {
{
bool reset = m_node.get() != node; bool reset = m_node.get() != node;
m_node = node; m_node = node;
@ -391,8 +337,7 @@ bool SampleView::loadData(ProjectModel::SampleNode* node)
resetZoom(); resetZoom();
m_playbackMacro = amuse::MakeObj<amuse::SoundMacro>(); m_playbackMacro = amuse::MakeObj<amuse::SoundMacro>();
amuse::SoundMacro::CmdStartSample* startSample = amuse::SoundMacro::CmdStartSample* startSample = static_cast<amuse::SoundMacro::CmdStartSample*>(
static_cast<amuse::SoundMacro::CmdStartSample*>(
m_playbackMacro->insertNewCmd(0, amuse::SoundMacro::CmdOp::StartSample)); m_playbackMacro->insertNewCmd(0, amuse::SoundMacro::CmdOp::StartSample));
startSample->sample.id = m_node->id(); startSample->sample.id = m_node->id();
m_playbackMacro->insertNewCmd(1, amuse::SoundMacro::CmdOp::End); m_playbackMacro->insertNewCmd(1, amuse::SoundMacro::CmdOp::End);
@ -402,80 +347,61 @@ bool SampleView::loadData(ProjectModel::SampleNode* node)
return reset; return reset;
} }
void SampleView::unloadData() void SampleView::unloadData() {
{
m_node.reset(); m_node.reset();
m_sample.reset(); m_sample.reset();
m_playbackMacro.reset(); m_playbackMacro.reset();
update(); update();
} }
ProjectModel::INode* SampleView::currentNode() const ProjectModel::INode* SampleView::currentNode() const { return m_node.get(); }
{
return m_node.get();
}
amuse::SampleEntryData* SampleView::entryData() const amuse::SampleEntryData* SampleView::entryData() const { return m_sample.get(); }
{
return m_sample.get();
}
const amuse::SoundMacro* SampleView::soundMacro() const const amuse::SoundMacro* SampleView::soundMacro() const { return m_playbackMacro.get(); }
{
return m_playbackMacro.get();
}
void SampleView::setSamplePos(int pos) void SampleView::setSamplePos(int pos) {
{ if (pos != m_displaySamplePos) {
if (pos != m_displaySamplePos) if (pos >= 0) {
{
if (pos >= 0)
{
int lastPos = m_displaySamplePos; int lastPos = m_displaySamplePos;
m_displaySamplePos = pos; m_displaySamplePos = pos;
updateSampleRange(lastPos, pos); updateSampleRange(lastPos, pos);
} } else {
else
{
m_displaySamplePos = pos; m_displaySamplePos = pos;
update(); update();
} }
} }
} }
void SampleView::updateSampleRange(int oldSamp, int newSamp) void SampleView::updateSampleRange(int oldSamp, int newSamp) {
{
qreal lastPos = oldSamp / m_samplesPerPx; qreal lastPos = oldSamp / m_samplesPerPx;
qreal newPos = newSamp / m_samplesPerPx; qreal newPos = newSamp / m_samplesPerPx;
update(int(std::min(lastPos, newPos)) - 10, 0, update(int(std::min(lastPos, newPos)) - 10, 0, int(std::fabs(newPos - lastPos)) + 20, height());
int(std::fabs(newPos - lastPos)) + 20, height());
} }
SampleView::SampleView(QWidget* parent) SampleView::SampleView(QWidget* parent) : QWidget(parent) {
: QWidget(parent)
{
setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred); setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred);
m_rulerFont.setPointSize(8); m_rulerFont.setPointSize(8);
} }
void SampleControls::zoomSliderChanged(int val) void SampleControls::zoomSliderChanged(int val) {
{
SampleEditor* editor = qobject_cast<SampleEditor*>(parentWidget()); SampleEditor* editor = qobject_cast<SampleEditor*>(parentWidget());
editor->m_sampleView->setZoom(val); editor->m_sampleView->setZoom(val);
} }
class SampLoopUndoCommand : public EditorUndoCommand class SampLoopUndoCommand : public EditorUndoCommand {
{
uint32_t m_redoStartVal, m_redoEndVal, m_undoStartVal, m_undoEndVal; uint32_t m_redoStartVal, m_redoEndVal, m_undoStartVal, m_undoEndVal;
int m_fieldIdx; int m_fieldIdx;
bool m_undid = false; bool m_undid = false;
public: public:
SampLoopUndoCommand(uint32_t redoStart, uint32_t redoEnd, const QString& fieldName, SampLoopUndoCommand(uint32_t redoStart, uint32_t redoEnd, const QString& fieldName, int fieldIdx,
int fieldIdx, amuse::ObjToken<ProjectModel::SampleNode> node) amuse::ObjToken<ProjectModel::SampleNode> node)
: EditorUndoCommand(node.get(), SampleControls::tr("Change %1").arg(fieldName)), : EditorUndoCommand(node.get(), SampleControls::tr("Change %1").arg(fieldName))
m_redoStartVal(redoStart), m_redoEndVal(redoEnd), m_fieldIdx(fieldIdx) {} , m_redoStartVal(redoStart)
void undo() , m_redoEndVal(redoEnd)
{ , m_fieldIdx(fieldIdx) {}
void undo() {
m_undid = true; m_undid = true;
amuse::SampleEntryData* data = m_node.cast<ProjectModel::SampleNode>()->m_obj->m_data.get(); amuse::SampleEntryData* data = m_node.cast<ProjectModel::SampleNode>()->m_obj->m_data.get();
data->setLoopStartSample(m_undoStartVal); data->setLoopStartSample(m_undoStartVal);
@ -484,24 +410,20 @@ public:
if (SampleEditor* e = static_cast<SampleEditor*>(g_MainWindow->getEditorWidget())) if (SampleEditor* e = static_cast<SampleEditor*>(g_MainWindow->getEditorWidget()))
e->m_controls->doFileWrite(); e->m_controls->doFileWrite();
} }
void redo() void redo() {
{
amuse::SampleEntryData* data = m_node.cast<ProjectModel::SampleNode>()->m_obj->m_data.get(); amuse::SampleEntryData* data = m_node.cast<ProjectModel::SampleNode>()->m_obj->m_data.get();
m_undoStartVal = data->getLoopStartSample(); m_undoStartVal = data->getLoopStartSample();
m_undoEndVal = data->getLoopEndSample(); m_undoEndVal = data->getLoopEndSample();
data->setLoopStartSample(m_redoStartVal); data->setLoopStartSample(m_redoStartVal);
data->setLoopEndSample(m_redoEndVal); data->setLoopEndSample(m_redoEndVal);
if (m_undid) if (m_undid) {
{
EditorUndoCommand::redo(); EditorUndoCommand::redo();
if (SampleEditor* e = static_cast<SampleEditor*>(g_MainWindow->getEditorWidget())) if (SampleEditor* e = static_cast<SampleEditor*>(g_MainWindow->getEditorWidget()))
e->m_controls->doFileWrite(); e->m_controls->doFileWrite();
} }
} }
bool mergeWith(const QUndoCommand* other) bool mergeWith(const QUndoCommand* other) {
{ if (other->id() == id() && static_cast<const SampLoopUndoCommand*>(other)->m_fieldIdx == m_fieldIdx) {
if (other->id() == id() && static_cast<const SampLoopUndoCommand*>(other)->m_fieldIdx == m_fieldIdx)
{
m_redoStartVal = static_cast<const SampLoopUndoCommand*>(other)->m_redoStartVal; m_redoStartVal = static_cast<const SampLoopUndoCommand*>(other)->m_redoStartVal;
m_redoEndVal = static_cast<const SampLoopUndoCommand*>(other)->m_redoEndVal; m_redoEndVal = static_cast<const SampLoopUndoCommand*>(other)->m_redoEndVal;
return true; return true;
@ -511,20 +433,16 @@ public:
int id() const { return int(Id::SampLoop); } int id() const { return int(Id::SampLoop); }
}; };
void SampleControls::loopStateChanged(int state) void SampleControls::loopStateChanged(int state) {
{ if (m_enableUpdate) {
if (m_enableUpdate)
{
SampleEditor* editor = qobject_cast<SampleEditor*>(parentWidget()); SampleEditor* editor = qobject_cast<SampleEditor*>(parentWidget());
amuse::SampleEntryData* data = editor->m_sampleView->entryData(); amuse::SampleEntryData* data = editor->m_sampleView->entryData();
if (state == Qt::Checked) if (state == Qt::Checked) {
{ g_MainWindow->pushUndoCommand(new SampLoopUndoCommand(
g_MainWindow->pushUndoCommand(new SampLoopUndoCommand(atUint32(m_loopStart->value()), atUint32(m_loopStart->value()), uint32_t(m_loopEnd->value()), tr("Loop"), 0, editor->m_sampleView->m_node));
uint32_t(m_loopEnd->value()), tr("Loop"), 0, editor->m_sampleView->m_node));
m_loopStart->setEnabled(true); m_loopStart->setEnabled(true);
m_loopEnd->setEnabled(true); m_loopEnd->setEnabled(true);
if (m_loopStart->value() == 0 && m_loopEnd->value() == 0) if (m_loopStart->value() == 0 && m_loopEnd->value() == 0) {
{
m_enableUpdate = false; m_enableUpdate = false;
m_loopEnd->setValue(data->getNumSamples() - 1); m_loopEnd->setValue(data->getNumSamples() - 1);
m_loopStart->setMaximum(m_loopEnd->value()); m_loopStart->setMaximum(m_loopEnd->value());
@ -532,9 +450,7 @@ void SampleControls::loopStateChanged(int state)
} }
data->m_loopStartSample = atUint32(m_loopStart->value()); data->m_loopStartSample = atUint32(m_loopStart->value());
data->m_loopLengthSamples = m_loopEnd->value() + 1 - data->m_loopStartSample; data->m_loopLengthSamples = m_loopEnd->value() + 1 - data->m_loopStartSample;
} } else {
else
{
g_MainWindow->pushUndoCommand(new SampLoopUndoCommand(0, 0, tr("Loop"), 0, editor->m_sampleView->m_node)); g_MainWindow->pushUndoCommand(new SampLoopUndoCommand(0, 0, tr("Loop"), 0, editor->m_sampleView->m_node));
m_loopStart->setEnabled(false); m_loopStart->setEnabled(false);
m_loopEnd->setEnabled(false); m_loopEnd->setEnabled(false);
@ -546,16 +462,14 @@ void SampleControls::loopStateChanged(int state)
} }
} }
void SampleControls::startValueChanged(int val) void SampleControls::startValueChanged(int val) {
{ if (m_enableUpdate) {
if (m_enableUpdate)
{
SampleEditor* editor = qobject_cast<SampleEditor*>(parentWidget()); SampleEditor* editor = qobject_cast<SampleEditor*>(parentWidget());
amuse::SampleEntryData* data = editor->m_sampleView->entryData(); amuse::SampleEntryData* data = editor->m_sampleView->entryData();
int oldPos = data->getLoopStartSample(); int oldPos = data->getLoopStartSample();
g_MainWindow->pushUndoCommand(new SampLoopUndoCommand(atUint32(val), data->getLoopEndSample(), tr("Loop Start"), g_MainWindow->pushUndoCommand(new SampLoopUndoCommand(atUint32(val), data->getLoopEndSample(), tr("Loop Start"), 1,
1, editor->m_sampleView->m_node)); editor->m_sampleView->m_node));
data->setLoopStartSample(atUint32(val)); data->setLoopStartSample(atUint32(val));
m_loopEnd->setMinimum(val); m_loopEnd->setMinimum(val);
@ -565,16 +479,14 @@ void SampleControls::startValueChanged(int val)
} }
} }
void SampleControls::endValueChanged(int val) void SampleControls::endValueChanged(int val) {
{ if (m_enableUpdate) {
if (m_enableUpdate)
{
SampleEditor* editor = qobject_cast<SampleEditor*>(parentWidget()); SampleEditor* editor = qobject_cast<SampleEditor*>(parentWidget());
amuse::SampleEntryData* data = editor->m_sampleView->entryData(); amuse::SampleEntryData* data = editor->m_sampleView->entryData();
int oldPos = data->getLoopEndSample(); int oldPos = data->getLoopEndSample();
g_MainWindow->pushUndoCommand(new SampLoopUndoCommand(data->getLoopStartSample(), atUint32(val), tr("Loop End"), g_MainWindow->pushUndoCommand(new SampLoopUndoCommand(data->getLoopStartSample(), atUint32(val), tr("Loop End"), 2,
2, editor->m_sampleView->m_node)); editor->m_sampleView->m_node));
data->setLoopEndSample(atUint32(val)); data->setLoopEndSample(atUint32(val));
m_loopStart->setMaximum(val); m_loopStart->setMaximum(val);
@ -584,16 +496,14 @@ void SampleControls::endValueChanged(int val)
} }
} }
class SampPitchUndoCommand : public EditorUndoCommand class SampPitchUndoCommand : public EditorUndoCommand {
{
uint8_t m_redoPitchVal, m_undoPitchVal; uint8_t m_redoPitchVal, m_undoPitchVal;
bool m_undid = false; bool m_undid = false;
public: public:
SampPitchUndoCommand(atUint8 redoPitch, amuse::ObjToken<ProjectModel::SampleNode> node) SampPitchUndoCommand(atUint8 redoPitch, amuse::ObjToken<ProjectModel::SampleNode> node)
: EditorUndoCommand(node.get(), SampleControls::tr("Change Base Pitch")), : EditorUndoCommand(node.get(), SampleControls::tr("Change Base Pitch")), m_redoPitchVal(redoPitch) {}
m_redoPitchVal(redoPitch) {} void undo() {
void undo()
{
m_undid = true; m_undid = true;
amuse::SampleEntryData* data = m_node.cast<ProjectModel::SampleNode>()->m_obj->m_data.get(); amuse::SampleEntryData* data = m_node.cast<ProjectModel::SampleNode>()->m_obj->m_data.get();
data->m_pitch = m_undoPitchVal; data->m_pitch = m_undoPitchVal;
@ -601,22 +511,18 @@ public:
if (SampleEditor* e = static_cast<SampleEditor*>(g_MainWindow->getEditorWidget())) if (SampleEditor* e = static_cast<SampleEditor*>(g_MainWindow->getEditorWidget()))
e->m_controls->doFileWrite(); e->m_controls->doFileWrite();
} }
void redo() void redo() {
{
amuse::SampleEntryData* data = m_node.cast<ProjectModel::SampleNode>()->m_obj->m_data.get(); amuse::SampleEntryData* data = m_node.cast<ProjectModel::SampleNode>()->m_obj->m_data.get();
m_undoPitchVal = data->m_pitch; m_undoPitchVal = data->m_pitch;
data->m_pitch = m_redoPitchVal; data->m_pitch = m_redoPitchVal;
if (m_undid) if (m_undid) {
{
EditorUndoCommand::redo(); EditorUndoCommand::redo();
if (SampleEditor* e = static_cast<SampleEditor*>(g_MainWindow->getEditorWidget())) if (SampleEditor* e = static_cast<SampleEditor*>(g_MainWindow->getEditorWidget()))
e->m_controls->doFileWrite(); e->m_controls->doFileWrite();
} }
} }
bool mergeWith(const QUndoCommand* other) bool mergeWith(const QUndoCommand* other) {
{ if (other->id() == id()) {
if (other->id() == id())
{
m_redoPitchVal = static_cast<const SampPitchUndoCommand*>(other)->m_redoPitchVal; m_redoPitchVal = static_cast<const SampPitchUndoCommand*>(other)->m_redoPitchVal;
return true; return true;
} }
@ -625,10 +531,8 @@ public:
int id() const { return int(Id::SampPitch); } int id() const { return int(Id::SampPitch); }
}; };
void SampleControls::pitchValueChanged(int val) void SampleControls::pitchValueChanged(int val) {
{ if (m_enableUpdate) {
if (m_enableUpdate)
{
SampleEditor* editor = qobject_cast<SampleEditor*>(parentWidget()); SampleEditor* editor = qobject_cast<SampleEditor*>(parentWidget());
amuse::SampleEntryData* data = editor->m_sampleView->entryData(); amuse::SampleEntryData* data = editor->m_sampleView->entryData();
@ -639,44 +543,35 @@ void SampleControls::pitchValueChanged(int val)
} }
} }
void SampleControls::makeWAVVersion() void SampleControls::makeWAVVersion() {
{
SampleEditor* editor = qobject_cast<SampleEditor*>(parentWidget()); SampleEditor* editor = qobject_cast<SampleEditor*>(parentWidget());
ProjectModel::SampleNode* node = static_cast<ProjectModel::SampleNode*>(editor->currentNode()); ProjectModel::SampleNode* node = static_cast<ProjectModel::SampleNode*>(editor->currentNode());
g_MainWindow->projectModel()->getGroupNode(node)->getAudioGroup()-> g_MainWindow->projectModel()->getGroupNode(node)->getAudioGroup()->makeWAVVersion(node->id(), node->m_obj.get());
makeWAVVersion(node->id(), node->m_obj.get());
updateFileState(); updateFileState();
} }
void SampleControls::makeCompressedVersion() void SampleControls::makeCompressedVersion() {
{
SampleEditor* editor = qobject_cast<SampleEditor*>(parentWidget()); SampleEditor* editor = qobject_cast<SampleEditor*>(parentWidget());
ProjectModel::SampleNode* node = static_cast<ProjectModel::SampleNode*>(editor->currentNode()); ProjectModel::SampleNode* node = static_cast<ProjectModel::SampleNode*>(editor->currentNode());
g_MainWindow->projectModel()->getGroupNode(node)->getAudioGroup()-> g_MainWindow->projectModel()->getGroupNode(node)->getAudioGroup()->makeCompressedVersion(node->id(),
makeCompressedVersion(node->id(), node->m_obj.get()); node->m_obj.get());
updateFileState(); updateFileState();
} }
void SampleControls::showInBrowser() void SampleControls::showInBrowser() { ShowInGraphicalShell(this, m_path); }
{
ShowInGraphicalShell(this, m_path);
}
void SampleControls::updateFileState() void SampleControls::updateFileState() {
{
m_enableUpdate = false; m_enableUpdate = false;
SampleEditor* editor = qobject_cast<SampleEditor*>(parentWidget()); SampleEditor* editor = qobject_cast<SampleEditor*>(parentWidget());
ProjectModel::SampleNode* node = static_cast<ProjectModel::SampleNode*>(editor->currentNode()); ProjectModel::SampleNode* node = static_cast<ProjectModel::SampleNode*>(editor->currentNode());
amuse::SystemString path; amuse::SystemString path;
amuse::SampleFileState state = amuse::SampleFileState state = g_MainWindow->projectModel()->getGroupNode(node)->getAudioGroup()->getSampleFileState(
g_MainWindow->projectModel()->getGroupNode(node)->getAudioGroup()-> node->id(), node->m_obj.get(), &path);
getSampleFileState(node->id(), node->m_obj.get(), &path);
disconnect(m_makeOtherConn); disconnect(m_makeOtherConn);
switch (state) switch (state) {
{
case amuse::SampleFileState::MemoryOnlyWAV: case amuse::SampleFileState::MemoryOnlyWAV:
case amuse::SampleFileState::CompressedNoWAV: case amuse::SampleFileState::CompressedNoWAV:
m_makeOtherVersion->setText(tr("Make WAV Version")); m_makeOtherVersion->setText(tr("Make WAV Version"));
@ -701,8 +596,7 @@ void SampleControls::updateFileState()
int loopStart = 0; int loopStart = 0;
int loopEnd = 0; int loopEnd = 0;
int loopMax = data->getNumSamples() - 1; int loopMax = data->getNumSamples() - 1;
if (data->isLooped()) if (data->isLooped()) {
{
loopStart = data->m_loopStartSample; loopStart = data->m_loopStartSample;
loopEnd = loopStart + data->m_loopLengthSamples - 1; loopEnd = loopStart + data->m_loopLengthSamples - 1;
} }
@ -715,13 +609,10 @@ void SampleControls::updateFileState()
m_loopStart->setEnabled(data->isLooped()); m_loopStart->setEnabled(data->isLooped());
m_loopEnd->setEnabled(data->isLooped()); m_loopEnd->setEnabled(data->isLooped());
if (!path.empty()) if (!path.empty()) {
{
m_path = SysStringToQString(path); m_path = SysStringToQString(path);
m_showInBrowser->setDisabled(false); m_showInBrowser->setDisabled(false);
} } else {
else
{
m_path = QString(); m_path = QString();
m_showInBrowser->setDisabled(true); m_showInBrowser->setDisabled(true);
} }
@ -729,25 +620,21 @@ void SampleControls::updateFileState()
m_enableUpdate = true; m_enableUpdate = true;
} }
void SampleControls::doFileWrite() void SampleControls::doFileWrite() {
{ if (m_enableFileWrite) {
if (m_enableFileWrite)
{
SampleEditor* editor = qobject_cast<SampleEditor*>(parentWidget()); SampleEditor* editor = qobject_cast<SampleEditor*>(parentWidget());
ProjectModel::SampleNode* node = static_cast<ProjectModel::SampleNode*>(editor->currentNode()); ProjectModel::SampleNode* node = static_cast<ProjectModel::SampleNode*>(editor->currentNode());
g_MainWindow->projectModel()->getGroupNode(node)->getAudioGroup()-> g_MainWindow->projectModel()->getGroupNode(node)->getAudioGroup()->patchSampleMetadata(node->id(),
patchSampleMetadata(node->id(), node->m_obj.get()); node->m_obj.get());
} }
} }
void SampleControls::setFileWrite(bool w) void SampleControls::setFileWrite(bool w) {
{
m_enableFileWrite = w; m_enableFileWrite = w;
doFileWrite(); doFileWrite();
} }
void SampleControls::loadData(bool reset) void SampleControls::loadData(bool reset) {
{
m_zoomSlider->setDisabled(false); m_zoomSlider->setDisabled(false);
m_loopCheck->setDisabled(false); m_loopCheck->setDisabled(false);
m_loopStart->setDisabled(false); m_loopStart->setDisabled(false);
@ -758,8 +645,7 @@ void SampleControls::loadData(bool reset)
updateFileState(); updateFileState();
} }
void SampleControls::unloadData() void SampleControls::unloadData() {
{
m_zoomSlider->setDisabled(true); m_zoomSlider->setDisabled(true);
m_loopCheck->setDisabled(true); m_loopCheck->setDisabled(true);
m_loopStart->setDisabled(true); m_loopStart->setDisabled(true);
@ -770,9 +656,7 @@ void SampleControls::unloadData()
m_showInBrowser->setDisabled(true); m_showInBrowser->setDisabled(true);
} }
SampleControls::SampleControls(QWidget* parent) SampleControls::SampleControls(QWidget* parent) : QFrame(parent) {
: QFrame(parent)
{
setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
setFixedHeight(100); setFixedHeight(100);
setFrameShape(QFrame::StyledPanel); setFrameShape(QFrame::StyledPanel);
@ -851,42 +735,26 @@ SampleControls::SampleControls(QWidget* parent)
setLayout(mainLayout); setLayout(mainLayout);
} }
bool SampleEditor::loadData(ProjectModel::SampleNode* node) bool SampleEditor::loadData(ProjectModel::SampleNode* node) {
{
m_controls->loadData(m_sampleView->loadData(node)); m_controls->loadData(m_sampleView->loadData(node));
return true; return true;
} }
void SampleEditor::unloadData() void SampleEditor::unloadData() {
{
m_sampleView->unloadData(); m_sampleView->unloadData();
m_controls->unloadData(); m_controls->unloadData();
} }
ProjectModel::INode* SampleEditor::currentNode() const ProjectModel::INode* SampleEditor::currentNode() const { return m_sampleView->currentNode(); }
{
return m_sampleView->currentNode();
}
const amuse::SoundMacro* SampleEditor::soundMacro() const const amuse::SoundMacro* SampleEditor::soundMacro() const { return m_sampleView->soundMacro(); }
{
return m_sampleView->soundMacro();
}
void SampleEditor::setSamplePos(int pos) void SampleEditor::setSamplePos(int pos) { m_sampleView->setSamplePos(pos); }
{
m_sampleView->setSamplePos(pos);
}
void SampleEditor::resizeEvent(QResizeEvent* ev) void SampleEditor::resizeEvent(QResizeEvent* ev) { m_sampleView->resetZoom(); }
{
m_sampleView->resetZoom();
}
SampleEditor::SampleEditor(QWidget* parent) SampleEditor::SampleEditor(QWidget* parent)
: EditorWidget(parent), m_scrollArea(new QScrollArea), : EditorWidget(parent), m_scrollArea(new QScrollArea), m_sampleView(new SampleView), m_controls(new SampleControls) {
m_sampleView(new SampleView), m_controls(new SampleControls)
{
m_scrollArea->setWidget(m_sampleView); m_scrollArea->setWidget(m_sampleView);
m_scrollArea->setWidgetResizable(true); m_scrollArea->setWidgetResizable(true);

View File

@ -9,8 +9,7 @@
class SampleEditor; class SampleEditor;
class SampleView : public QWidget class SampleView : public QWidget {
{
Q_OBJECT Q_OBJECT
friend class SampleControls; friend class SampleControls;
qreal m_baseSamplesPerPx = 100.0; qreal m_baseSamplesPerPx = 100.0;
@ -25,17 +24,13 @@ class SampleView : public QWidget
int16_t m_prev2 = 0; int16_t m_prev2 = 0;
QFont m_rulerFont; QFont m_rulerFont;
int m_displaySamplePos = -1; int m_displaySamplePos = -1;
enum class DragState enum class DragState { None, Start, End };
{
None,
Start,
End
};
DragState m_dragState = DragState::None; DragState m_dragState = DragState::None;
void seekToSample(qreal sample); void seekToSample(qreal sample);
std::pair<std::pair<qreal, qreal>, std::pair<qreal, qreal>> iterateSampleInterval(qreal interval); std::pair<std::pair<qreal, qreal>, std::pair<qreal, qreal>> iterateSampleInterval(qreal interval);
void calculateSamplesPerPx(); void calculateSamplesPerPx();
SampleEditor* getEditor() const; SampleEditor* getEditor() const;
public: public:
explicit SampleView(QWidget* parent = Q_NULLPTR); explicit SampleView(QWidget* parent = Q_NULLPTR);
bool loadData(ProjectModel::SampleNode* node); bool loadData(ProjectModel::SampleNode* node);
@ -56,8 +51,7 @@ public:
void wheelEvent(QWheelEvent* ev); void wheelEvent(QWheelEvent* ev);
}; };
class SampleControls : public QFrame class SampleControls : public QFrame {
{
Q_OBJECT Q_OBJECT
QString m_path; QString m_path;
QSlider* m_zoomSlider; QSlider* m_zoomSlider;
@ -70,6 +64,7 @@ class SampleControls : public QFrame
QPushButton* m_showInBrowser; QPushButton* m_showInBrowser;
bool m_enableUpdate = true; bool m_enableUpdate = true;
bool m_enableFileWrite = true; bool m_enableFileWrite = true;
public: public:
explicit SampleControls(QWidget* parent = Q_NULLPTR); explicit SampleControls(QWidget* parent = Q_NULLPTR);
void doFileWrite(); void doFileWrite();
@ -90,8 +85,7 @@ public slots:
void showInBrowser(); void showInBrowser();
}; };
class SampleEditor : public EditorWidget class SampleEditor : public EditorWidget {
{
Q_OBJECT Q_OBJECT
friend class SampleView; friend class SampleView;
friend class SampleControls; friend class SampleControls;
@ -100,6 +94,7 @@ class SampleEditor : public EditorWidget
QScrollArea* m_scrollArea; QScrollArea* m_scrollArea;
SampleView* m_sampleView; SampleView* m_sampleView;
SampleControls* m_controls; SampleControls* m_controls;
public: public:
explicit SampleEditor(QWidget* parent = Q_NULLPTR); explicit SampleEditor(QWidget* parent = Q_NULLPTR);
bool loadData(ProjectModel::SampleNode* node); bool loadData(ProjectModel::SampleNode* node);
@ -110,5 +105,3 @@ public:
void resizeEvent(QResizeEvent* ev); void resizeEvent(QResizeEvent* ev);
}; };

File diff suppressed because it is too large Load Diff

View File

@ -16,11 +16,11 @@
class SetupTableView; class SetupTableView;
class PageObjectDelegate : public BaseObjectDelegate class PageObjectDelegate : public BaseObjectDelegate {
{
Q_OBJECT Q_OBJECT
protected: protected:
ProjectModel::INode* getNode(const QAbstractItemModel* model, const QModelIndex& index) const; ProjectModel::INode* getNode(const QAbstractItemModel* model, const QModelIndex& index) const;
public: public:
explicit PageObjectDelegate(QObject* parent = Q_NULLPTR); explicit PageObjectDelegate(QObject* parent = Q_NULLPTR);
QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const; QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const;
@ -30,12 +30,12 @@ private slots:
void objIndexChanged(); void objIndexChanged();
}; };
class MIDIFileFieldWidget : public QWidget class MIDIFileFieldWidget : public QWidget {
{
Q_OBJECT Q_OBJECT
QLineEdit m_le; QLineEdit m_le;
QPushButton m_button; QPushButton m_button;
QFileDialog m_dialog; QFileDialog m_dialog;
public: public:
explicit MIDIFileFieldWidget(QWidget* parent = Q_NULLPTR); explicit MIDIFileFieldWidget(QWidget* parent = Q_NULLPTR);
QString path() const { return m_le.text(); } QString path() const { return m_le.text(); }
@ -47,19 +47,19 @@ signals:
void pathChanged(); void pathChanged();
}; };
class MIDIFileDelegate : public QStyledItemDelegate class MIDIFileDelegate : public QStyledItemDelegate {
{
Q_OBJECT Q_OBJECT
QFileDialog m_fileDialogMid, m_fileDialogSng; QFileDialog m_fileDialogMid, m_fileDialogSng;
std::vector<uint8_t> m_exportData; std::vector<uint8_t> m_exportData;
public: public:
explicit MIDIFileDelegate(SetupTableView* parent = Q_NULLPTR); explicit MIDIFileDelegate(SetupTableView* parent = Q_NULLPTR);
QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const; QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const;
void destroyEditor(QWidget *editor, const QModelIndex &index) const; void destroyEditor(QWidget* editor, const QModelIndex& index) const;
void setEditorData(QWidget* editor, const QModelIndex& index) const; void setEditorData(QWidget* editor, const QModelIndex& index) const;
void setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const; void setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const;
bool editorEvent(QEvent *event, QAbstractItemModel *model, bool editorEvent(QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option,
const QStyleOptionViewItem &option, const QModelIndex &index); const QModelIndex& index);
private slots: private slots:
void doExportMIDI(); void doExportMIDI();
void _doExportMIDI(const QString& path); void _doExportMIDI(const QString& path);
@ -69,15 +69,13 @@ public slots:
void pathChanged(); void pathChanged();
}; };
class PageModel : public QAbstractTableModel class PageModel : public QAbstractTableModel {
{
Q_OBJECT Q_OBJECT
friend class SongGroupEditor; friend class SongGroupEditor;
friend class PageObjectDelegate; friend class PageObjectDelegate;
friend class PageTableView; friend class PageTableView;
amuse::ObjToken<ProjectModel::SongGroupNode> m_node; amuse::ObjToken<ProjectModel::SongGroupNode> m_node;
struct Iterator struct Iterator {
{
using ItTp = std::unordered_map<uint8_t, amuse::SongGroupIndex::PageEntry>::iterator; using ItTp = std::unordered_map<uint8_t, amuse::SongGroupIndex::PageEntry>::iterator;
ItTp m_it; ItTp m_it;
Iterator(ItTp it) : m_it(it) {} Iterator(ItTp it) : m_it(it) {}
@ -91,6 +89,7 @@ class PageModel : public QAbstractTableModel
void _buildSortedList(); void _buildSortedList();
QModelIndex _indexOfProgram(uint8_t prog) const; QModelIndex _indexOfProgram(uint8_t prog) const;
int _hypotheticalIndexOfProgram(uint8_t prog) const; int _hypotheticalIndexOfProgram(uint8_t prog) const;
public: public:
explicit PageModel(bool drum, QObject* parent = Q_NULLPTR); explicit PageModel(bool drum, QObject* parent = Q_NULLPTR);
void loadData(ProjectModel::SongGroupNode* node); void loadData(ProjectModel::SongGroupNode* node);
@ -107,32 +106,27 @@ public:
std::pair<uint8_t, amuse::SongGroupIndex::PageEntry> _removeRow(uint8_t prog); std::pair<uint8_t, amuse::SongGroupIndex::PageEntry> _removeRow(uint8_t prog);
}; };
class SetupListModel : public QAbstractTableModel class SetupListModel : public QAbstractTableModel {
{
Q_OBJECT Q_OBJECT
friend class SongGroupEditor; friend class SongGroupEditor;
friend class MIDIFileDelegate; friend class MIDIFileDelegate;
friend class SetupTableView; friend class SetupTableView;
friend class SetupModel; friend class SetupModel;
amuse::ObjToken<ProjectModel::SongGroupNode> m_node; amuse::ObjToken<ProjectModel::SongGroupNode> m_node;
struct Iterator struct Iterator {
{
using ItTp = std::unordered_map<amuse::SongId, std::array<amuse::SongGroupIndex::MIDISetup, 16>>::iterator; using ItTp = std::unordered_map<amuse::SongId, std::array<amuse::SongGroupIndex::MIDISetup, 16>>::iterator;
ItTp m_it; ItTp m_it;
Iterator(ItTp it) : m_it(it) {} Iterator(ItTp it) : m_it(it) {}
ItTp::pointer operator->() { return m_it.operator->(); } ItTp::pointer operator->() { return m_it.operator->(); }
bool operator<(const Iterator& other) const bool operator<(const Iterator& other) const {
{
return amuse::SongId::CurNameDB->resolveNameFromId(m_it->first) < return amuse::SongId::CurNameDB->resolveNameFromId(m_it->first) <
amuse::SongId::CurNameDB->resolveNameFromId(other.m_it->first); amuse::SongId::CurNameDB->resolveNameFromId(other.m_it->first);
} }
bool operator<(amuse::SongId other) const bool operator<(amuse::SongId other) const {
{
return amuse::SongId::CurNameDB->resolveNameFromId(m_it->first) < return amuse::SongId::CurNameDB->resolveNameFromId(m_it->first) <
amuse::SongId::CurNameDB->resolveNameFromId(other); amuse::SongId::CurNameDB->resolveNameFromId(other);
} }
bool operator<(const std::string& name) const bool operator<(const std::string& name) const {
{
return amuse::SongId::CurNameDB->resolveNameFromId(m_it->first) < name; return amuse::SongId::CurNameDB->resolveNameFromId(m_it->first) < name;
} }
}; };
@ -141,6 +135,7 @@ class SetupListModel : public QAbstractTableModel
void _buildSortedList(); void _buildSortedList();
QModelIndex _indexOfSong(amuse::SongId id) const; QModelIndex _indexOfSong(amuse::SongId id) const;
int _hypotheticalIndexOfSong(const std::string& songName) const; int _hypotheticalIndexOfSong(const std::string& songName) const;
public: public:
explicit SetupListModel(QObject* parent = Q_NULLPTR); explicit SetupListModel(QObject* parent = Q_NULLPTR);
void loadData(ProjectModel::SongGroupNode* node); void loadData(ProjectModel::SongGroupNode* node);
@ -153,17 +148,15 @@ public:
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
Qt::ItemFlags flags(const QModelIndex& index) const; Qt::ItemFlags flags(const QModelIndex& index) const;
int _insertRow( int _insertRow(std::tuple<amuse::SongId, std::string, std::array<amuse::SongGroupIndex::MIDISetup, 16>>& data);
std::tuple<amuse::SongId, std::string, std::array<amuse::SongGroupIndex::MIDISetup, 16>>& data); std::tuple<amuse::SongId, std::string, std::array<amuse::SongGroupIndex::MIDISetup, 16>> _removeRow(amuse::SongId id);
std::tuple<amuse::SongId, std::string, std::array<amuse::SongGroupIndex::MIDISetup, 16>>
_removeRow(amuse::SongId id);
}; };
class SetupModel : public QAbstractTableModel class SetupModel : public QAbstractTableModel {
{
Q_OBJECT Q_OBJECT
friend class SongGroupEditor; friend class SongGroupEditor;
std::pair<const amuse::SongId, std::array<amuse::SongGroupIndex::MIDISetup, 16>>* m_data = nullptr; std::pair<const amuse::SongId, std::array<amuse::SongGroupIndex::MIDISetup, 16>>* m_data = nullptr;
public: public:
explicit SetupModel(QObject* parent = Q_NULLPTR); explicit SetupModel(QObject* parent = Q_NULLPTR);
void loadData(std::pair<const amuse::SongId, std::array<amuse::SongGroupIndex::MIDISetup, 16>>* data); void loadData(std::pair<const amuse::SongId, std::array<amuse::SongGroupIndex::MIDISetup, 16>>* data);
@ -177,22 +170,21 @@ public:
Qt::ItemFlags flags(const QModelIndex& index) const; Qt::ItemFlags flags(const QModelIndex& index) const;
}; };
class PageTableView : public QTableView class PageTableView : public QTableView {
{
Q_OBJECT Q_OBJECT
PageObjectDelegate m_poDelegate; PageObjectDelegate m_poDelegate;
RangedValueFactory<0, 127> m_127Factory; RangedValueFactory<0, 127> m_127Factory;
RangedValueFactory<1, 128> m_128Factory; RangedValueFactory<1, 128> m_128Factory;
RangedValueFactory<0, 255> m_255Factory; RangedValueFactory<0, 255> m_255Factory;
QStyledItemDelegate m_127Delegate, m_128Delegate, m_255Delegate; QStyledItemDelegate m_127Delegate, m_128Delegate, m_255Delegate;
public: public:
explicit PageTableView(QWidget* parent = Q_NULLPTR); explicit PageTableView(QWidget* parent = Q_NULLPTR);
void setModel(QAbstractItemModel* model); void setModel(QAbstractItemModel* model);
void deleteSelection(); void deleteSelection();
}; };
class SetupTableView : public QSplitter class SetupTableView : public QSplitter {
{
Q_OBJECT Q_OBJECT
friend class SongGroupEditor; friend class SongGroupEditor;
friend class SetupRowUndoCommand; friend class SetupRowUndoCommand;
@ -202,6 +194,7 @@ class SetupTableView : public QSplitter
RangedValueFactory<0, 127> m_127Factory; RangedValueFactory<0, 127> m_127Factory;
RangedValueFactory<1, 128> m_128Factory; RangedValueFactory<1, 128> m_128Factory;
QStyledItemDelegate m_127Delegate, m_128Delegate; QStyledItemDelegate m_127Delegate, m_128Delegate;
public: public:
explicit SetupTableView(QWidget* parent = Q_NULLPTR); explicit SetupTableView(QWidget* parent = Q_NULLPTR);
void setModel(QAbstractItemModel* list, QAbstractItemModel* table); void setModel(QAbstractItemModel* list, QAbstractItemModel* table);
@ -209,31 +202,28 @@ public:
void showEvent(QShowEvent* event); void showEvent(QShowEvent* event);
}; };
class ColoredTabBarStyle : public QProxyStyle class ColoredTabBarStyle : public QProxyStyle {
{
public: public:
using QProxyStyle::QProxyStyle; using QProxyStyle::QProxyStyle;
void drawControl(QStyle::ControlElement element, const QStyleOption *option, void drawControl(QStyle::ControlElement element, const QStyleOption* option, QPainter* painter,
QPainter *painter, const QWidget *widget = nullptr) const; const QWidget* widget = nullptr) const;
}; };
class ColoredTabBar : public QTabBar class ColoredTabBar : public QTabBar {
{
Q_OBJECT Q_OBJECT
public: public:
explicit ColoredTabBar(QWidget* parent = Q_NULLPTR); explicit ColoredTabBar(QWidget* parent = Q_NULLPTR);
}; };
class ColoredTabWidget : public QTabWidget class ColoredTabWidget : public QTabWidget {
{
Q_OBJECT Q_OBJECT
ColoredTabBar m_tabBar; ColoredTabBar m_tabBar;
public: public:
explicit ColoredTabWidget(QWidget* parent = Q_NULLPTR); explicit ColoredTabWidget(QWidget* parent = Q_NULLPTR);
}; };
class MIDIPlayerWidget : public QWidget class MIDIPlayerWidget : public QWidget {
{
Q_OBJECT Q_OBJECT
QAction m_playAction; QAction m_playAction;
QToolButton m_button; QToolButton m_button;
@ -243,9 +233,10 @@ class MIDIPlayerWidget : public QWidget
QString m_path; QString m_path;
std::vector<uint8_t> m_arrData; std::vector<uint8_t> m_arrData;
amuse::ObjToken<amuse::Sequencer> m_seq; amuse::ObjToken<amuse::Sequencer> m_seq;
public: public:
explicit MIDIPlayerWidget(QModelIndex index, amuse::GroupId gid, amuse::SongId id, explicit MIDIPlayerWidget(QModelIndex index, amuse::GroupId gid, amuse::SongId id, const QString& path,
const QString& path, QWidget* parent = Q_NULLPTR); QWidget* parent = Q_NULLPTR);
~MIDIPlayerWidget(); ~MIDIPlayerWidget();
amuse::SongId songId() const { return m_songId; } amuse::SongId songId() const { return m_songId; }
amuse::Sequencer* sequencer() const { return m_seq.get(); } amuse::Sequencer* sequencer() const { return m_seq.get(); }
@ -258,8 +249,7 @@ public slots:
void clicked(); void clicked();
}; };
class SongGroupEditor : public EditorWidget class SongGroupEditor : public EditorWidget {
{
Q_OBJECT Q_OBJECT
friend class SetupModel; friend class SetupModel;
PageModel m_normPages; PageModel m_normPages;
@ -271,6 +261,7 @@ class SongGroupEditor : public EditorWidget
SetupTableView* m_setupTable; SetupTableView* m_setupTable;
ColoredTabWidget m_tabs; ColoredTabWidget m_tabs;
AddRemoveButtons m_addRemoveButtons; AddRemoveButtons m_addRemoveButtons;
public: public:
explicit SongGroupEditor(QWidget* parent = Q_NULLPTR); explicit SongGroupEditor(QWidget* parent = Q_NULLPTR);
bool loadData(ProjectModel::SongGroupNode* node); bool loadData(ProjectModel::SongGroupNode* node);
@ -291,9 +282,8 @@ private slots:
void drumRowsMoved(const QModelIndex& parent, int start, int end, const QModelIndex& destination, int row); void drumRowsMoved(const QModelIndex& parent, int start, int end, const QModelIndex& destination, int row);
void setupRowsInserted(const QModelIndex& parent, int first, int last); void setupRowsInserted(const QModelIndex& parent, int first, int last);
void setupRowsMoved(const QModelIndex& parent, int start, int end, const QModelIndex& destination, int row); void setupRowsMoved(const QModelIndex& parent, int start, int end, const QModelIndex& destination, int row);
void setupRowsAboutToBeRemoved(const QModelIndex &parent, int first, int last); void setupRowsAboutToBeRemoved(const QModelIndex& parent, int first, int last);
void setupModelAboutToBeReset(); void setupModelAboutToBeReset();
void setupDataChanged(); void setupDataChanged();
void itemDeleteAction(); void itemDeleteAction();
}; };

View File

@ -1,25 +1,23 @@
#include "SoundGroupEditor.hpp" #include "SoundGroupEditor.hpp"
#include "MainWindow.hpp" #include "MainWindow.hpp"
class SFXDataChangeUndoCommand : public EditorUndoCommand class SFXDataChangeUndoCommand : public EditorUndoCommand {
{
amuse::SFXId m_sfx; amuse::SFXId m_sfx;
int m_column; int m_column;
int m_undoVal, m_redoVal; int m_undoVal, m_redoVal;
bool m_undid = false; bool m_undid = false;
public: public:
explicit SFXDataChangeUndoCommand(ProjectModel::SoundGroupNode* node, const QString& text, explicit SFXDataChangeUndoCommand(ProjectModel::SoundGroupNode* node, const QString& text, amuse::SFXId sfx,
amuse::SFXId sfx, int column, int redoVal) int column, int redoVal)
: EditorUndoCommand(node, text), m_sfx(sfx), m_column(column), m_redoVal(redoVal) {} : EditorUndoCommand(node, text), m_sfx(sfx), m_column(column), m_redoVal(redoVal) {}
void undo() void undo() {
{
m_undid = true; m_undid = true;
amuse::SFXGroupIndex& index = *static_cast<ProjectModel::SoundGroupNode*>(m_node.get())->m_index; amuse::SFXGroupIndex& index = *static_cast<ProjectModel::SoundGroupNode*>(m_node.get())->m_index;
auto& map = index.m_sfxEntries; auto& map = index.m_sfxEntries;
amuse::SFXGroupIndex::SFXEntry& entry = map[m_sfx]; amuse::SFXGroupIndex::SFXEntry& entry = map[m_sfx];
switch (m_column) switch (m_column) {
{
case 1: case 1:
entry.objId.id = m_undoVal; entry.objId.id = m_undoVal;
break; break;
@ -44,14 +42,12 @@ public:
EditorUndoCommand::undo(); EditorUndoCommand::undo();
} }
void redo() void redo() {
{
amuse::SFXGroupIndex& index = *static_cast<ProjectModel::SoundGroupNode*>(m_node.get())->m_index; amuse::SFXGroupIndex& index = *static_cast<ProjectModel::SoundGroupNode*>(m_node.get())->m_index;
auto& map = index.m_sfxEntries; auto& map = index.m_sfxEntries;
amuse::SFXGroupIndex::SFXEntry& entry = map[m_sfx]; amuse::SFXGroupIndex::SFXEntry& entry = map[m_sfx];
switch (m_column) switch (m_column) {
{
case 1: case 1:
m_undoVal = entry.objId.id; m_undoVal = entry.objId.id;
entry.objId.id = m_redoVal; entry.objId.id = m_redoVal;
@ -85,17 +81,16 @@ public:
} }
}; };
class SFXNameChangeUndoCommand : public EditorUndoCommand class SFXNameChangeUndoCommand : public EditorUndoCommand {
{
amuse::SFXId m_sfx; amuse::SFXId m_sfx;
std::string m_undoVal, m_redoVal; std::string m_undoVal, m_redoVal;
bool m_undid = false; bool m_undid = false;
public: public:
explicit SFXNameChangeUndoCommand(ProjectModel::SoundGroupNode* node, const QString& text, explicit SFXNameChangeUndoCommand(ProjectModel::SoundGroupNode* node, const QString& text, amuse::SFXId sfx,
amuse::SFXId sfx, std::string_view redoVal) std::string_view redoVal)
: EditorUndoCommand(node, text), m_sfx(sfx), m_redoVal(redoVal) {} : EditorUndoCommand(node, text), m_sfx(sfx), m_redoVal(redoVal) {}
void undo() void undo() {
{
m_undid = true; m_undid = true;
g_MainWindow->projectModel()->setIdDatabases(m_node.get()); g_MainWindow->projectModel()->setIdDatabases(m_node.get());
amuse::SFXGroupIndex& index = *static_cast<ProjectModel::SoundGroupNode*>(m_node.get())->m_index; amuse::SFXGroupIndex& index = *static_cast<ProjectModel::SoundGroupNode*>(m_node.get())->m_index;
@ -105,8 +100,7 @@ public:
EditorUndoCommand::undo(); EditorUndoCommand::undo();
} }
void redo() void redo() {
{
g_MainWindow->projectModel()->setIdDatabases(m_node.get()); g_MainWindow->projectModel()->setIdDatabases(m_node.get());
amuse::SFXGroupIndex& index = *static_cast<ProjectModel::SoundGroupNode*>(m_node.get())->m_index; amuse::SFXGroupIndex& index = *static_cast<ProjectModel::SoundGroupNode*>(m_node.get())->m_index;
auto& map = index.m_sfxEntries; auto& map = index.m_sfxEntries;
@ -119,11 +113,9 @@ public:
} }
}; };
SFXObjectDelegate::SFXObjectDelegate(QObject* parent) SFXObjectDelegate::SFXObjectDelegate(QObject* parent) : BaseObjectDelegate(parent) {}
: BaseObjectDelegate(parent) {}
ProjectModel::INode* SFXObjectDelegate::getNode(const QAbstractItemModel* __model, const QModelIndex& index) const ProjectModel::INode* SFXObjectDelegate::getNode(const QAbstractItemModel* __model, const QModelIndex& index) const {
{
const SFXModel* model = static_cast<const SFXModel*>(__model); const SFXModel* model = static_cast<const SFXModel*>(__model);
auto entry = model->m_sorted[index.row()]; auto entry = model->m_sorted[index.row()];
if (entry->second.objId.id.id == 0xffff) if (entry->second.objId.id.id == 0xffff)
@ -132,8 +124,8 @@ ProjectModel::INode* SFXObjectDelegate::getNode(const QAbstractItemModel* __mode
return group->pageObjectNodeOfId(entry->second.objId.id); return group->pageObjectNodeOfId(entry->second.objId.id);
} }
QWidget* SFXObjectDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const QWidget* SFXObjectDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& option,
{ const QModelIndex& index) const {
const SFXModel* model = static_cast<const SFXModel*>(index.model()); const SFXModel* model = static_cast<const SFXModel*>(index.model());
ProjectModel::GroupNode* group = g_MainWindow->projectModel()->getGroupNode(model->m_node.get()); ProjectModel::GroupNode* group = g_MainWindow->projectModel()->getGroupNode(model->m_node.get());
EditorFieldPageObjectNode* cb = new EditorFieldPageObjectNode(group, parent); EditorFieldPageObjectNode* cb = new EditorFieldPageObjectNode(group, parent);
@ -141,58 +133,53 @@ QWidget* SFXObjectDelegate::createEditor(QWidget* parent, const QStyleOptionView
return cb; return cb;
} }
void SFXObjectDelegate::setEditorData(QWidget* editor, const QModelIndex& index) const void SFXObjectDelegate::setEditorData(QWidget* editor, const QModelIndex& index) const {
{
int idx = 0; int idx = 0;
if (ProjectModel::BasePoolObjectNode* node = static_cast<ProjectModel::BasePoolObjectNode*>(getNode(index.model(), index))) if (ProjectModel::BasePoolObjectNode* node =
idx = g_MainWindow->projectModel()->getPageObjectProxy()->mapFromSource(g_MainWindow->projectModel()->index(node)).row(); static_cast<ProjectModel::BasePoolObjectNode*>(getNode(index.model(), index)))
idx = g_MainWindow->projectModel()
->getPageObjectProxy()
->mapFromSource(g_MainWindow->projectModel()->index(node))
.row();
static_cast<EditorFieldPageObjectNode*>(editor)->setCurrentIndex(idx); static_cast<EditorFieldPageObjectNode*>(editor)->setCurrentIndex(idx);
if (static_cast<EditorFieldPageObjectNode*>(editor)->shouldPopupOpen()) if (static_cast<EditorFieldPageObjectNode*>(editor)->shouldPopupOpen())
QApplication::postEvent(editor, new QEvent(QEvent::User)); QApplication::postEvent(editor, new QEvent(QEvent::User));
} }
void SFXObjectDelegate::setModelData(QWidget* editor, QAbstractItemModel* m, const QModelIndex& index) const void SFXObjectDelegate::setModelData(QWidget* editor, QAbstractItemModel* m, const QModelIndex& index) const {
{
const SFXModel* model = static_cast<const SFXModel*>(m); const SFXModel* model = static_cast<const SFXModel*>(m);
auto entry = model->m_sorted[index.row()]; auto entry = model->m_sorted[index.row()];
ProjectModel::BasePoolObjectNode* node = static_cast<EditorFieldPageObjectNode*>(editor)->currentNode(); ProjectModel::BasePoolObjectNode* node = static_cast<EditorFieldPageObjectNode*>(editor)->currentNode();
amuse::ObjectId id; amuse::ObjectId id;
if (node) if (node)
id = node->id(); id = node->id();
if (id == entry->second.objId.id) if (id == entry->second.objId.id) {
{
emit m->dataChanged(index, index); emit m->dataChanged(index, index);
return; return;
} }
g_MainWindow->pushUndoCommand(new SFXDataChangeUndoCommand(model->m_node.get(), g_MainWindow->pushUndoCommand(new SFXDataChangeUndoCommand(
tr("Change %1").arg(m->headerData(1, Qt::Horizontal).toString()), entry->first, 1, id.id)); model->m_node.get(), tr("Change %1").arg(m->headerData(1, Qt::Horizontal).toString()), entry->first, 1, id.id));
emit m->dataChanged(index, index); emit m->dataChanged(index, index);
} }
void SFXObjectDelegate::objIndexChanged() void SFXObjectDelegate::objIndexChanged() { emit commitData(static_cast<QWidget*>(sender())); }
{
emit commitData(static_cast<QWidget*>(sender()));
}
std::unordered_map<amuse::SFXId, amuse::SFXGroupIndex::SFXEntry>& SFXModel::_getMap() const std::unordered_map<amuse::SFXId, amuse::SFXGroupIndex::SFXEntry>& SFXModel::_getMap() const {
{
return m_node->m_index->m_sfxEntries; return m_node->m_index->m_sfxEntries;
} }
void SFXModel::_buildSortedList() void SFXModel::_buildSortedList() {
{
m_sorted.clear(); m_sorted.clear();
if (!m_node) if (!m_node)
return; return;
auto& map = _getMap(); auto& map = _getMap();
m_sorted.reserve(map.size()); m_sorted.reserve(map.size());
for (auto it = map.begin() ; it != map.end() ; ++it) for (auto it = map.begin(); it != map.end(); ++it)
m_sorted.emplace_back(it); m_sorted.emplace_back(it);
std::sort(m_sorted.begin(), m_sorted.end()); std::sort(m_sorted.begin(), m_sorted.end());
} }
QModelIndex SFXModel::_indexOfSFX(amuse::SFXId sfx) const QModelIndex SFXModel::_indexOfSFX(amuse::SFXId sfx) const {
{
auto search = std::lower_bound(m_sorted.cbegin(), m_sorted.cend(), sfx); auto search = std::lower_bound(m_sorted.cbegin(), m_sorted.cend(), sfx);
if (search == m_sorted.cend() || search->m_it->first != sfx) if (search == m_sorted.cend() || search->m_it->first != sfx)
return QModelIndex(); return QModelIndex();
@ -200,30 +187,26 @@ QModelIndex SFXModel::_indexOfSFX(amuse::SFXId sfx) const
return createIndex(search - m_sorted.begin(), 0); return createIndex(search - m_sorted.begin(), 0);
} }
int SFXModel::_hypotheticalIndexOfSFX(const std::string& sfxName) const int SFXModel::_hypotheticalIndexOfSFX(const std::string& sfxName) const {
{
auto search = std::lower_bound(m_sorted.cbegin(), m_sorted.cend(), sfxName); auto search = std::lower_bound(m_sorted.cbegin(), m_sorted.cend(), sfxName);
return search - m_sorted.begin(); return search - m_sorted.begin();
} }
void SFXModel::loadData(ProjectModel::SoundGroupNode* node) void SFXModel::loadData(ProjectModel::SoundGroupNode* node) {
{
beginResetModel(); beginResetModel();
m_node = node; m_node = node;
_buildSortedList(); _buildSortedList();
endResetModel(); endResetModel();
} }
void SFXModel::unloadData() void SFXModel::unloadData() {
{
beginResetModel(); beginResetModel();
m_node.reset(); m_node.reset();
m_sorted.clear(); m_sorted.clear();
endResetModel(); endResetModel();
} }
int SFXModel::rowCount(const QModelIndex& parent) const int SFXModel::rowCount(const QModelIndex& parent) const {
{
if (parent.isValid()) if (parent.isValid())
return 0; return 0;
if (!m_node) if (!m_node)
@ -231,15 +214,13 @@ int SFXModel::rowCount(const QModelIndex& parent) const
return int(m_sorted.size()) + 1; return int(m_sorted.size()) + 1;
} }
int SFXModel::columnCount(const QModelIndex& parent) const int SFXModel::columnCount(const QModelIndex& parent) const {
{
if (parent.isValid()) if (parent.isValid())
return 0; return 0;
return 7; return 7;
} }
QVariant SFXModel::data(const QModelIndex& index, int role) const QVariant SFXModel::data(const QModelIndex& index, int role) const {
{
if (!m_node) if (!m_node)
return QVariant(); return QVariant();
if (index.row() == m_sorted.size()) if (index.row() == m_sorted.size())
@ -247,17 +228,13 @@ QVariant SFXModel::data(const QModelIndex& index, int role) const
auto entry = m_sorted[index.row()]; auto entry = m_sorted[index.row()];
if (role == Qt::DisplayRole || role == Qt::EditRole) if (role == Qt::DisplayRole || role == Qt::EditRole) {
{ switch (index.column()) {
switch (index.column()) case 0: {
{
case 0:
{
g_MainWindow->projectModel()->setIdDatabases(m_node.get()); g_MainWindow->projectModel()->setIdDatabases(m_node.get());
return amuse::SFXId::CurNameDB->resolveNameFromId(entry->first.id).data(); return amuse::SFXId::CurNameDB->resolveNameFromId(entry->first.id).data();
} }
case 1: case 1: {
{
ProjectModel::GroupNode* group = g_MainWindow->projectModel()->getGroupNode(m_node.get()); ProjectModel::GroupNode* group = g_MainWindow->projectModel()->getGroupNode(m_node.get());
if (ProjectModel::BasePoolObjectNode* node = group->pageObjectNodeOfId(entry->second.objId.id)) if (ProjectModel::BasePoolObjectNode* node = group->pageObjectNodeOfId(entry->second.objId.id))
return node->text(); return node->text();
@ -281,23 +258,20 @@ QVariant SFXModel::data(const QModelIndex& index, int role) const
return QVariant(); return QVariant();
} }
bool SFXModel::setData(const QModelIndex& index, const QVariant& value, int role) bool SFXModel::setData(const QModelIndex& index, const QVariant& value, int role) {
{
if (!m_node || role != Qt::EditRole) if (!m_node || role != Qt::EditRole)
return false; return false;
auto& map = _getMap(); auto& map = _getMap();
auto entry = m_sorted[index.row()]; auto entry = m_sorted[index.row()];
switch (index.column()) switch (index.column()) {
{ case 0: {
case 0:
{
g_MainWindow->projectModel()->setIdDatabases(m_node.get()); g_MainWindow->projectModel()->setIdDatabases(m_node.get());
auto utf8key = value.toString().toUtf8(); auto utf8key = value.toString().toUtf8();
std::unordered_map<std::string, amuse::ObjectId>::iterator idIt; std::unordered_map<std::string, amuse::ObjectId>::iterator idIt;
if ((idIt = amuse::SFXId::CurNameDB->m_stringToId.find(utf8key.data())) != amuse::SFXId::CurNameDB->m_stringToId.cend()) if ((idIt = amuse::SFXId::CurNameDB->m_stringToId.find(utf8key.data())) !=
{ amuse::SFXId::CurNameDB->m_stringToId.cend()) {
if (idIt->second == entry->first) if (idIt->second == entry->first)
return false; return false;
g_MainWindow->uiMessenger().critical(tr("SFX Conflict"), g_MainWindow->uiMessenger().critical(tr("SFX Conflict"),
@ -306,8 +280,8 @@ bool SFXModel::setData(const QModelIndex& index, const QVariant& value, int role
} }
int newIdx = _hypotheticalIndexOfSFX(utf8key.data()); int newIdx = _hypotheticalIndexOfSFX(utf8key.data());
bool moving = beginMoveRows(index.parent(), index.row(), index.row(), index.parent(), newIdx); bool moving = beginMoveRows(index.parent(), index.row(), index.row(), index.parent(), newIdx);
g_MainWindow->pushUndoCommand(new SFXNameChangeUndoCommand(m_node.get(), g_MainWindow->pushUndoCommand(
tr("Change SFX Name"), entry->first, utf8key.data())); new SFXNameChangeUndoCommand(m_node.get(), tr("Change SFX Name"), entry->first, utf8key.data()));
_buildSortedList(); _buildSortedList();
if (moving) if (moving)
endMoveRows(); endMoveRows();
@ -339,20 +313,17 @@ bool SFXModel::setData(const QModelIndex& index, const QVariant& value, int role
return false; return false;
} }
g_MainWindow->pushUndoCommand(new SFXDataChangeUndoCommand(m_node.get(), g_MainWindow->pushUndoCommand(new SFXDataChangeUndoCommand(
tr("Change %1").arg(headerData(index.column(), Qt::Horizontal).toString()), m_node.get(), tr("Change %1").arg(headerData(index.column(), Qt::Horizontal).toString()), entry->first,
entry->first, index.column(), value.toInt())); index.column(), value.toInt()));
emit dataChanged(index, index, {Qt::DisplayRole, Qt::EditRole}); emit dataChanged(index, index, {Qt::DisplayRole, Qt::EditRole});
return true; return true;
} }
QVariant SFXModel::headerData(int section, Qt::Orientation orientation, int role) const QVariant SFXModel::headerData(int section, Qt::Orientation orientation, int role) const {
{ if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
if (orientation == Qt::Horizontal && role == Qt::DisplayRole) switch (section) {
{
switch (section)
{
case 0: case 0:
return tr("SFX"); return tr("SFX");
case 1: case 1:
@ -374,8 +345,7 @@ QVariant SFXModel::headerData(int section, Qt::Orientation orientation, int role
return QVariant(); return QVariant();
} }
Qt::ItemFlags SFXModel::flags(const QModelIndex& index) const Qt::ItemFlags SFXModel::flags(const QModelIndex& index) const {
{
if (!index.isValid()) if (!index.isValid())
return Qt::NoItemFlags; return Qt::NoItemFlags;
if (index.row() == m_sorted.size()) if (index.row() == m_sorted.size())
@ -383,68 +353,75 @@ Qt::ItemFlags SFXModel::flags(const QModelIndex& index) const
return Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable; return Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable;
} }
class SFXRowUndoCommand : public EditorUndoCommand class SFXRowUndoCommand : public EditorUndoCommand {
{
protected: protected:
SFXTableView* m_view; SFXTableView* m_view;
std::vector<std::tuple<amuse::SFXId, std::string, amuse::SFXGroupIndex::SFXEntry>> m_data; std::vector<std::tuple<amuse::SFXId, std::string, amuse::SFXGroupIndex::SFXEntry>> m_data;
bool m_undid = false; bool m_undid = false;
void add() void add() {
{
m_view->selectionModel()->clearSelection(); m_view->selectionModel()->clearSelection();
for (auto& p : m_data) for (auto& p : m_data) {
{
int row = static_cast<SFXModel*>(m_view->model())->_insertRow(p); int row = static_cast<SFXModel*>(m_view->model())->_insertRow(p);
m_view->setCurrentIndex(m_view->model()->index(row, 0)); m_view->setCurrentIndex(m_view->model()->index(row, 0));
} }
} }
void del() void del() {
{ for (auto it = m_data.rbegin(); it != m_data.rend(); ++it) {
for (auto it = m_data.rbegin(); it != m_data.rend(); ++it)
{
*it = static_cast<SFXModel*>(m_view->model())->_removeRow(std::get<0>(*it)); *it = static_cast<SFXModel*>(m_view->model())->_removeRow(std::get<0>(*it));
} }
} }
void undo() void undo() {
{
m_undid = true; m_undid = true;
EditorUndoCommand::undo(); EditorUndoCommand::undo();
} }
void redo() void redo() {
{
if (m_undid) if (m_undid)
EditorUndoCommand::redo(); EditorUndoCommand::redo();
} }
public: public:
explicit SFXRowUndoCommand(ProjectModel::SoundGroupNode* node, const QString& text, SFXTableView* view, explicit SFXRowUndoCommand(ProjectModel::SoundGroupNode* node, const QString& text, SFXTableView* view,
std::vector<std::tuple<amuse::SFXId, std::string, amuse::SFXGroupIndex::SFXEntry>>&& data) std::vector<std::tuple<amuse::SFXId, std::string, amuse::SFXGroupIndex::SFXEntry>>&& data)
: EditorUndoCommand(node, text), m_view(view), m_data(std::move(data)) {} : EditorUndoCommand(node, text), m_view(view), m_data(std::move(data)) {}
}; };
class SFXRowAddUndoCommand : public SFXRowUndoCommand class SFXRowAddUndoCommand : public SFXRowUndoCommand {
{
using base = SFXRowUndoCommand; using base = SFXRowUndoCommand;
public: public:
explicit SFXRowAddUndoCommand(ProjectModel::SoundGroupNode* node, const QString& text, SFXTableView* view, explicit SFXRowAddUndoCommand(
ProjectModel::SoundGroupNode* node, const QString& text, SFXTableView* view,
std::vector<std::tuple<amuse::SFXId, std::string, amuse::SFXGroupIndex::SFXEntry>>&& data) std::vector<std::tuple<amuse::SFXId, std::string, amuse::SFXGroupIndex::SFXEntry>>&& data)
: SFXRowUndoCommand(node, text, view, std::move(data)) {} : SFXRowUndoCommand(node, text, view, std::move(data)) {}
void undo() { base::undo(); base::del(); } void undo() {
void redo() { base::redo(); base::add(); } base::undo();
base::del();
}
void redo() {
base::redo();
base::add();
}
}; };
class SFXRowDelUndoCommand : public SFXRowUndoCommand class SFXRowDelUndoCommand : public SFXRowUndoCommand {
{
using base = SFXRowUndoCommand; using base = SFXRowUndoCommand;
public: public:
explicit SFXRowDelUndoCommand(ProjectModel::SoundGroupNode* node, const QString& text, SFXTableView* view, explicit SFXRowDelUndoCommand(
ProjectModel::SoundGroupNode* node, const QString& text, SFXTableView* view,
std::vector<std::tuple<amuse::SFXId, std::string, amuse::SFXGroupIndex::SFXEntry>>&& data) std::vector<std::tuple<amuse::SFXId, std::string, amuse::SFXGroupIndex::SFXEntry>>&& data)
: SFXRowUndoCommand(node, text, view, std::move(data)) {} : SFXRowUndoCommand(node, text, view, std::move(data)) {}
void undo() { base::undo(); base::add(); } void undo() {
void redo() { base::redo(); base::del(); } base::undo();
base::add();
}
void redo() {
base::redo();
base::del();
}
}; };
int SFXModel::_insertRow(const std::tuple<amuse::SFXId, std::string, amuse::SFXGroupIndex::SFXEntry>& data) int SFXModel::_insertRow(const std::tuple<amuse::SFXId, std::string, amuse::SFXGroupIndex::SFXEntry>& data) {
{
if (!m_node) if (!m_node)
return 0; return 0;
auto& map = _getMap(); auto& map = _getMap();
@ -458,8 +435,7 @@ int SFXModel::_insertRow(const std::tuple<amuse::SFXId, std::string, amuse::SFXG
return idx; return idx;
} }
std::tuple<amuse::SFXId, std::string, amuse::SFXGroupIndex::SFXEntry> SFXModel::_removeRow(amuse::SFXId sfx) std::tuple<amuse::SFXId, std::string, amuse::SFXGroupIndex::SFXEntry> SFXModel::_removeRow(amuse::SFXId sfx) {
{
std::tuple<amuse::SFXId, std::string, amuse::SFXGroupIndex::SFXEntry> ret; std::tuple<amuse::SFXId, std::string, amuse::SFXGroupIndex::SFXEntry> ret;
if (!m_node) if (!m_node)
return ret; return ret;
@ -470,8 +446,7 @@ std::tuple<amuse::SFXId, std::string, amuse::SFXGroupIndex::SFXEntry> SFXModel::
std::get<0>(ret) = sfx; std::get<0>(ret) = sfx;
std::get<1>(ret) = amuse::SFXId::CurNameDB->resolveNameFromId(sfx); std::get<1>(ret) = amuse::SFXId::CurNameDB->resolveNameFromId(sfx);
auto search = map.find(sfx); auto search = map.find(sfx);
if (search != map.cend()) if (search != map.cend()) {
{
std::get<2>(ret) = search->second; std::get<2>(ret) = search->second;
amuse::SFXId::CurNameDB->remove(sfx); amuse::SFXId::CurNameDB->remove(sfx);
map.erase(search); map.erase(search);
@ -481,30 +456,25 @@ std::tuple<amuse::SFXId, std::string, amuse::SFXGroupIndex::SFXEntry> SFXModel::
return ret; return ret;
} }
SFXModel::SFXModel(QObject* parent) SFXModel::SFXModel(QObject* parent) : QAbstractTableModel(parent) {}
: QAbstractTableModel(parent)
{}
void SFXTableView::deleteSelection() void SFXTableView::deleteSelection() {
{
QModelIndexList list = selectionModel()->selectedRows(); QModelIndexList list = selectionModel()->selectedRows();
if (list.isEmpty()) if (list.isEmpty())
return; return;
std::sort(list.begin(), list.end(), [](const auto& a, const auto& b) { return a.row() < b.row(); }); std::sort(list.begin(), list.end(), [](const auto& a, const auto& b) { return a.row() < b.row(); });
std::vector<std::tuple<amuse::SFXId, std::string, amuse::SFXGroupIndex::SFXEntry>> data; std::vector<std::tuple<amuse::SFXId, std::string, amuse::SFXGroupIndex::SFXEntry>> data;
data.reserve(list.size()); data.reserve(list.size());
for (QModelIndex idx : list) for (QModelIndex idx : list) {
{
auto& entry = *static_cast<SFXModel*>(model())->m_sorted[idx.row()].m_it; auto& entry = *static_cast<SFXModel*>(model())->m_sorted[idx.row()].m_it;
data.push_back({entry.first, {}, {}}); data.push_back({entry.first, {}, {}});
} }
g_MainWindow->pushUndoCommand( g_MainWindow->pushUndoCommand(new SFXRowDelUndoCommand(
new SFXRowDelUndoCommand(static_cast<SFXModel*>(model())->m_node.get(), static_cast<SFXModel*>(model())->m_node.get(),
data.size() > 1 ? tr("Delete SFX Entries") : tr("Delete SFX Entry"), this, std::move(data))); data.size() > 1 ? tr("Delete SFX Entries") : tr("Delete SFX Entry"), this, std::move(data)));
} }
void SFXTableView::setModel(QAbstractItemModel* model) void SFXTableView::setModel(QAbstractItemModel* model) {
{
QTableView::setModel(model); QTableView::setModel(model);
horizontalHeader()->setMinimumSectionSize(75); horizontalHeader()->setMinimumSectionSize(75);
horizontalHeader()->resizeSection(0, 200); horizontalHeader()->resizeSection(0, 200);
@ -521,9 +491,7 @@ void SFXTableView::setModel(QAbstractItemModel* model)
horizontalHeader()->resizeSection(6, 75); horizontalHeader()->resizeSection(6, 75);
} }
SFXTableView::SFXTableView(QWidget* parent) SFXTableView::SFXTableView(QWidget* parent) : QTableView(parent) {
: QTableView(parent)
{
setSelectionBehavior(QAbstractItemView::SelectRows); setSelectionBehavior(QAbstractItemView::SelectRows);
setSelectionMode(QAbstractItemView::ExtendedSelection); setSelectionMode(QAbstractItemView::ExtendedSelection);
setGridStyle(Qt::NoPen); setGridStyle(Qt::NoPen);
@ -539,47 +507,37 @@ SFXTableView::SFXTableView(QWidget* parent)
setItemDelegateForColumn(6, &m_127Delegate); setItemDelegateForColumn(6, &m_127Delegate);
} }
void SFXPlayerWidget::clicked() void SFXPlayerWidget::clicked() {
{ if (!m_vox) {
if (!m_vox)
{
m_vox = g_MainWindow->startSFX(m_groupId, m_sfxId); m_vox = g_MainWindow->startSFX(m_groupId, m_sfxId);
if (m_vox) if (m_vox) {
{
m_playAction.setText(tr("Stop")); m_playAction.setText(tr("Stop"));
m_playAction.setIcon(QIcon(QStringLiteral(":/icons/IconStop.svg"))); m_playAction.setIcon(QIcon(QStringLiteral(":/icons/IconStop.svg")));
} }
} } else {
else
{
stopped(); stopped();
} }
} }
void SFXPlayerWidget::stopped() void SFXPlayerWidget::stopped() {
{
m_vox->keyOff(); m_vox->keyOff();
m_vox.reset(); m_vox.reset();
m_playAction.setText(tr("Play")); m_playAction.setText(tr("Play"));
m_playAction.setIcon(QIcon(QStringLiteral(":/icons/IconSoundMacro.svg"))); m_playAction.setIcon(QIcon(QStringLiteral(":/icons/IconSoundMacro.svg")));
} }
void SFXPlayerWidget::resizeEvent(QResizeEvent* event) void SFXPlayerWidget::resizeEvent(QResizeEvent* event) {
{ m_button.setGeometry(event->size().width() - event->size().height(), 0, event->size().height(),
m_button.setGeometry(event->size().width() - event->size().height(), 0, event->size().height());
event->size().height(), event->size().height());
} }
void SFXPlayerWidget::mouseDoubleClickEvent(QMouseEvent* event) void SFXPlayerWidget::mouseDoubleClickEvent(QMouseEvent* event) {
{
qobject_cast<QTableView*>(parentWidget()->parentWidget())->setIndexWidget(m_index, nullptr); qobject_cast<QTableView*>(parentWidget()->parentWidget())->setIndexWidget(m_index, nullptr);
event->ignore(); event->ignore();
} }
void SFXPlayerWidget::mousePressEvent(QMouseEvent* event) void SFXPlayerWidget::mousePressEvent(QMouseEvent* event) {
{ if (event->button() == Qt::RightButton) {
if (event->button() == Qt::RightButton)
{
QTableView* view = qobject_cast<QTableView*>(parentWidget()->parentWidget()); QTableView* view = qobject_cast<QTableView*>(parentWidget()->parentWidget());
QAbstractItemDelegate* delegate = view->itemDelegateForColumn(1); QAbstractItemDelegate* delegate = view->itemDelegateForColumn(1);
delegate->editorEvent(event, view->model(), {}, m_index); delegate->editorEvent(event, view->model(), {}, m_index);
@ -587,50 +545,38 @@ void SFXPlayerWidget::mousePressEvent(QMouseEvent* event)
event->ignore(); event->ignore();
} }
SFXPlayerWidget::~SFXPlayerWidget() SFXPlayerWidget::~SFXPlayerWidget() {
{
if (m_vox) if (m_vox)
m_vox->keyOff(); m_vox->keyOff();
} }
SFXPlayerWidget::SFXPlayerWidget(QModelIndex index, amuse::GroupId gid, amuse::SFXId id, QWidget* parent) SFXPlayerWidget::SFXPlayerWidget(QModelIndex index, amuse::GroupId gid, amuse::SFXId id, QWidget* parent)
: QWidget(parent), m_button(this), m_playAction(tr("Play")), m_index(index), : QWidget(parent), m_button(this), m_playAction(tr("Play")), m_index(index), m_groupId(gid), m_sfxId(id) {
m_groupId(gid), m_sfxId(id)
{
m_playAction.setIcon(QIcon(QStringLiteral(":/icons/IconSoundMacro.svg"))); m_playAction.setIcon(QIcon(QStringLiteral(":/icons/IconSoundMacro.svg")));
m_button.setDefaultAction(&m_playAction); m_button.setDefaultAction(&m_playAction);
connect(&m_playAction, SIGNAL(triggered()), this, SLOT(clicked())); connect(&m_playAction, SIGNAL(triggered()), this, SLOT(clicked()));
} }
bool SoundGroupEditor::loadData(ProjectModel::SoundGroupNode* node) bool SoundGroupEditor::loadData(ProjectModel::SoundGroupNode* node) {
{
m_sfxs.loadData(node); m_sfxs.loadData(node);
return true; return true;
} }
void SoundGroupEditor::unloadData() void SoundGroupEditor::unloadData() { m_sfxs.unloadData(); }
{
m_sfxs.unloadData();
}
ProjectModel::INode* SoundGroupEditor::currentNode() const ProjectModel::INode* SoundGroupEditor::currentNode() const { return m_sfxs.m_node.get(); }
{
return m_sfxs.m_node.get();
}
void SoundGroupEditor::resizeEvent(QResizeEvent* ev) void SoundGroupEditor::resizeEvent(QResizeEvent* ev) {
{
m_sfxTable->setGeometry(QRect({}, ev->size())); m_sfxTable->setGeometry(QRect({}, ev->size()));
m_addRemoveButtons.move(0, ev->size().height() - 32); m_addRemoveButtons.move(0, ev->size().height() - 32);
} }
AmuseItemEditFlags SoundGroupEditor::itemEditFlags() const AmuseItemEditFlags SoundGroupEditor::itemEditFlags() const {
{ return (m_sfxTable->hasFocus() && !m_sfxTable->selectionModel()->selectedRows().isEmpty()) ? AmuseItemDelete
return (m_sfxTable->hasFocus() && !m_sfxTable->selectionModel()->selectedRows().isEmpty()) ? AmuseItemDelete : AmuseItemNone; : AmuseItemNone;
} }
void SoundGroupEditor::doAdd() void SoundGroupEditor::doAdd() {
{
g_MainWindow->projectModel()->setIdDatabases(m_sfxs.m_node.get()); g_MainWindow->projectModel()->setIdDatabases(m_sfxs.m_node.get());
std::vector<std::tuple<amuse::SFXId, std::string, amuse::SFXGroupIndex::SFXEntry>> data; std::vector<std::tuple<amuse::SFXId, std::string, amuse::SFXGroupIndex::SFXEntry>> data;
amuse::SFXId sfxId = amuse::SFXId::CurNameDB->generateId(amuse::NameDB::Type::SFX); amuse::SFXId sfxId = amuse::SFXId::CurNameDB->generateId(amuse::NameDB::Type::SFX);
@ -640,33 +586,28 @@ void SoundGroupEditor::doAdd()
new SFXRowAddUndoCommand(m_sfxs.m_node.get(), tr("Add SFX Entry"), m_sfxTable, std::move(data))); new SFXRowAddUndoCommand(m_sfxs.m_node.get(), tr("Add SFX Entry"), m_sfxTable, std::move(data)));
} }
void SoundGroupEditor::doSelectionChanged() void SoundGroupEditor::doSelectionChanged() {
{
m_addRemoveButtons.removeAction()->setDisabled(m_sfxTable->selectionModel()->selectedRows().isEmpty()); m_addRemoveButtons.removeAction()->setDisabled(m_sfxTable->selectionModel()->selectedRows().isEmpty());
g_MainWindow->updateFocus(); g_MainWindow->updateFocus();
} }
void SoundGroupEditor::rowsInserted(const QModelIndex &parent, int first, int last) void SoundGroupEditor::rowsInserted(const QModelIndex& parent, int first, int last) {
{
m_sfxTable->scrollTo(m_sfxTable->model()->index(first, 0)); m_sfxTable->scrollTo(m_sfxTable->model()->index(first, 0));
sfxDataChanged(); sfxDataChanged();
} }
void SoundGroupEditor::rowsMoved(const QModelIndex &parent, int start, int end, const QModelIndex &destination, int row) void SoundGroupEditor::rowsMoved(const QModelIndex& parent, int start, int end, const QModelIndex& destination,
{ int row) {
m_sfxTable->scrollTo(m_sfxTable->model()->index(row, 0)); m_sfxTable->scrollTo(m_sfxTable->model()->index(row, 0));
sfxDataChanged(); sfxDataChanged();
} }
void SoundGroupEditor::sfxDataChanged() void SoundGroupEditor::sfxDataChanged() {
{
int idx = 0; int idx = 0;
for (const auto& p : m_sfxs.m_sorted) for (const auto& p : m_sfxs.m_sorted) {
{
QModelIndex index = m_sfxs.index(idx, 1); QModelIndex index = m_sfxs.index(idx, 1);
SFXPlayerWidget* w = qobject_cast<SFXPlayerWidget*>(m_sfxTable->indexWidget(index)); SFXPlayerWidget* w = qobject_cast<SFXPlayerWidget*>(m_sfxTable->indexWidget(index));
if (!w || w->sfxId() != p->first) if (!w || w->sfxId() != p->first) {
{
SFXPlayerWidget* newW = new SFXPlayerWidget(index, m_sfxs.m_node->m_id, p->first, m_sfxTable->viewport()); SFXPlayerWidget* newW = new SFXPlayerWidget(index, m_sfxs.m_node->m_id, p->first, m_sfxTable->viewport());
m_sfxTable->setIndexWidget(index, newW); m_sfxTable->setIndexWidget(index, newW);
} }
@ -674,28 +615,22 @@ void SoundGroupEditor::sfxDataChanged()
} }
} }
void SoundGroupEditor::itemDeleteAction() void SoundGroupEditor::itemDeleteAction() { m_sfxTable->deleteSelection(); }
{
m_sfxTable->deleteSelection();
}
SoundGroupEditor::SoundGroupEditor(QWidget* parent) SoundGroupEditor::SoundGroupEditor(QWidget* parent)
: EditorWidget(parent), m_sfxs(this), m_sfxTable(new SFXTableView(this)), m_addRemoveButtons(this) : EditorWidget(parent), m_sfxs(this), m_sfxTable(new SFXTableView(this)), m_addRemoveButtons(this) {
{
m_sfxTable->setModel(&m_sfxs); m_sfxTable->setModel(&m_sfxs);
connect(m_sfxTable->selectionModel(), SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)), connect(m_sfxTable->selectionModel(), SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)), this,
this, SLOT(doSelectionChanged())); SLOT(doSelectionChanged()));
connect(&m_sfxs, SIGNAL(rowsInserted(const QModelIndex&, int, int)), connect(&m_sfxs, SIGNAL(rowsInserted(const QModelIndex&, int, int)), this,
this, SLOT(rowsInserted(const QModelIndex&, int, int))); SLOT(rowsInserted(const QModelIndex&, int, int)));
connect(&m_sfxs, SIGNAL(rowsRemoved(const QModelIndex&, int, int)), connect(&m_sfxs, SIGNAL(rowsRemoved(const QModelIndex&, int, int)), this, SLOT(sfxDataChanged()));
this, SLOT(sfxDataChanged())); connect(&m_sfxs, SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&, const QVector<int>&)), this,
connect(&m_sfxs, SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&, const QVector<int>&)), SLOT(sfxDataChanged()));
this, SLOT(sfxDataChanged())); connect(&m_sfxs, SIGNAL(rowsMoved(const QModelIndex&, int, int, const QModelIndex&, int)), this,
connect(&m_sfxs, SIGNAL(rowsMoved(const QModelIndex&, int, int, const QModelIndex&, int)), SLOT(rowsMoved(const QModelIndex&, int, int, const QModelIndex&, int)));
this, SLOT(rowsMoved(const QModelIndex&, int, int, const QModelIndex&, int))); connect(&m_sfxs, SIGNAL(modelReset()), this, SLOT(sfxDataChanged()));
connect(&m_sfxs, SIGNAL(modelReset()),
this, SLOT(sfxDataChanged()));
m_addRemoveButtons.addAction()->setToolTip(tr("Add new SFX entry")); m_addRemoveButtons.addAction()->setToolTip(tr("Add new SFX entry"));
connect(m_addRemoveButtons.addAction(), SIGNAL(triggered(bool)), this, SLOT(doAdd())); connect(m_addRemoveButtons.addAction(), SIGNAL(triggered(bool)), this, SLOT(doAdd()));

View File

@ -5,11 +5,11 @@
#include <QTableView> #include <QTableView>
#include "amuse/Voice.hpp" #include "amuse/Voice.hpp"
class SFXObjectDelegate : public BaseObjectDelegate class SFXObjectDelegate : public BaseObjectDelegate {
{
Q_OBJECT Q_OBJECT
protected: protected:
ProjectModel::INode* getNode(const QAbstractItemModel* model, const QModelIndex& index) const; ProjectModel::INode* getNode(const QAbstractItemModel* model, const QModelIndex& index) const;
public: public:
explicit SFXObjectDelegate(QObject* parent = Q_NULLPTR); explicit SFXObjectDelegate(QObject* parent = Q_NULLPTR);
QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const; QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const;
@ -19,31 +19,26 @@ private slots:
void objIndexChanged(); void objIndexChanged();
}; };
class SFXModel : public QAbstractTableModel class SFXModel : public QAbstractTableModel {
{
Q_OBJECT Q_OBJECT
friend class SoundGroupEditor; friend class SoundGroupEditor;
friend class SFXObjectDelegate; friend class SFXObjectDelegate;
friend class SFXTableView; friend class SFXTableView;
amuse::ObjToken<ProjectModel::SoundGroupNode> m_node; amuse::ObjToken<ProjectModel::SoundGroupNode> m_node;
struct Iterator struct Iterator {
{
using ItTp = std::unordered_map<amuse::SFXId, amuse::SFXGroupIndex::SFXEntry>::iterator; using ItTp = std::unordered_map<amuse::SFXId, amuse::SFXGroupIndex::SFXEntry>::iterator;
ItTp m_it; ItTp m_it;
Iterator(ItTp it) : m_it(it) {} Iterator(ItTp it) : m_it(it) {}
ItTp::pointer operator->() const { return m_it.operator->(); } ItTp::pointer operator->() const { return m_it.operator->(); }
bool operator<(const Iterator& other) const bool operator<(const Iterator& other) const {
{
return amuse::SFXId::CurNameDB->resolveNameFromId(m_it->first) < return amuse::SFXId::CurNameDB->resolveNameFromId(m_it->first) <
amuse::SFXId::CurNameDB->resolveNameFromId(other.m_it->first); amuse::SFXId::CurNameDB->resolveNameFromId(other.m_it->first);
} }
bool operator<(amuse::SongId other) const bool operator<(amuse::SongId other) const {
{
return amuse::SFXId::CurNameDB->resolveNameFromId(m_it->first) < return amuse::SFXId::CurNameDB->resolveNameFromId(m_it->first) <
amuse::SFXId::CurNameDB->resolveNameFromId(other); amuse::SFXId::CurNameDB->resolveNameFromId(other);
} }
bool operator<(const std::string& name) const bool operator<(const std::string& name) const {
{
return amuse::SFXId::CurNameDB->resolveNameFromId(m_it->first) < name; return amuse::SFXId::CurNameDB->resolveNameFromId(m_it->first) < name;
} }
}; };
@ -52,6 +47,7 @@ class SFXModel : public QAbstractTableModel
void _buildSortedList(); void _buildSortedList();
QModelIndex _indexOfSFX(amuse::SFXId sfx) const; QModelIndex _indexOfSFX(amuse::SFXId sfx) const;
int _hypotheticalIndexOfSFX(const std::string& sfxName) const; int _hypotheticalIndexOfSFX(const std::string& sfxName) const;
public: public:
explicit SFXModel(QObject* parent = Q_NULLPTR); explicit SFXModel(QObject* parent = Q_NULLPTR);
void loadData(ProjectModel::SoundGroupNode* node); void loadData(ProjectModel::SoundGroupNode* node);
@ -68,21 +64,20 @@ public:
std::tuple<amuse::SFXId, std::string, amuse::SFXGroupIndex::SFXEntry> _removeRow(amuse::SFXId sfx); std::tuple<amuse::SFXId, std::string, amuse::SFXGroupIndex::SFXEntry> _removeRow(amuse::SFXId sfx);
}; };
class SFXTableView : public QTableView class SFXTableView : public QTableView {
{
Q_OBJECT Q_OBJECT
SFXObjectDelegate m_sfxDelegate; SFXObjectDelegate m_sfxDelegate;
RangedValueFactory<0, 127> m_127Factory; RangedValueFactory<0, 127> m_127Factory;
RangedValueFactory<0, 255> m_255Factory; RangedValueFactory<0, 255> m_255Factory;
QStyledItemDelegate m_127Delegate, m_255Delegate; QStyledItemDelegate m_127Delegate, m_255Delegate;
public: public:
explicit SFXTableView(QWidget* parent = Q_NULLPTR); explicit SFXTableView(QWidget* parent = Q_NULLPTR);
void setModel(QAbstractItemModel* model); void setModel(QAbstractItemModel* model);
void deleteSelection(); void deleteSelection();
}; };
class SFXPlayerWidget : public QWidget class SFXPlayerWidget : public QWidget {
{
Q_OBJECT Q_OBJECT
QAction m_playAction; QAction m_playAction;
QToolButton m_button; QToolButton m_button;
@ -90,9 +85,9 @@ class SFXPlayerWidget : public QWidget
amuse::GroupId m_groupId; amuse::GroupId m_groupId;
amuse::SFXId m_sfxId; amuse::SFXId m_sfxId;
amuse::ObjToken<amuse::Voice> m_vox; amuse::ObjToken<amuse::Voice> m_vox;
public: public:
explicit SFXPlayerWidget(QModelIndex index, amuse::GroupId gid, amuse::SFXId id, explicit SFXPlayerWidget(QModelIndex index, amuse::GroupId gid, amuse::SFXId id, QWidget* parent = Q_NULLPTR);
QWidget* parent = Q_NULLPTR);
~SFXPlayerWidget(); ~SFXPlayerWidget();
amuse::SongId sfxId() const { return m_sfxId; } amuse::SongId sfxId() const { return m_sfxId; }
amuse::Voice* voice() const { return m_vox.get(); } amuse::Voice* voice() const { return m_vox.get(); }
@ -105,12 +100,12 @@ public slots:
void clicked(); void clicked();
}; };
class SoundGroupEditor : public EditorWidget class SoundGroupEditor : public EditorWidget {
{
Q_OBJECT Q_OBJECT
SFXModel m_sfxs; SFXModel m_sfxs;
SFXTableView* m_sfxTable; SFXTableView* m_sfxTable;
AddRemoveButtons m_addRemoveButtons; AddRemoveButtons m_addRemoveButtons;
public: public:
explicit SoundGroupEditor(QWidget* parent = Q_NULLPTR); explicit SoundGroupEditor(QWidget* parent = Q_NULLPTR);
bool loadData(ProjectModel::SoundGroupNode* node); bool loadData(ProjectModel::SoundGroupNode* node);
@ -121,11 +116,10 @@ public:
QTableView* getSFXListView() const { return m_sfxTable; } QTableView* getSFXListView() const { return m_sfxTable; }
AmuseItemEditFlags itemEditFlags() const; AmuseItemEditFlags itemEditFlags() const;
private slots: private slots:
void rowsInserted(const QModelIndex &parent, int first, int last); void rowsInserted(const QModelIndex& parent, int first, int last);
void rowsMoved(const QModelIndex &parent, int start, int end, const QModelIndex &destination, int row); void rowsMoved(const QModelIndex& parent, int start, int end, const QModelIndex& destination, int row);
void doAdd(); void doAdd();
void doSelectionChanged(); void doSelectionChanged();
void sfxDataChanged(); void sfxDataChanged();
void itemDeleteAction(); void itemDeleteAction();
}; };

File diff suppressed because it is too large Load Diff

View File

@ -16,8 +16,7 @@ class SoundMacroEditor;
class SoundMacroListing; class SoundMacroListing;
class CatalogueItem; class CatalogueItem;
class TargetButton : public QPushButton class TargetButton : public QPushButton {
{
Q_OBJECT Q_OBJECT
public: public:
explicit TargetButton(QWidget* parent = Q_NULLPTR); explicit TargetButton(QWidget* parent = Q_NULLPTR);
@ -27,8 +26,7 @@ public:
void keyPressEvent(QKeyEvent* event) { event->ignore(); } void keyPressEvent(QKeyEvent* event) { event->ignore(); }
}; };
class FieldSoundMacroStep : public QWidget class FieldSoundMacroStep : public QWidget {
{
friend class CommandWidget; friend class CommandWidget;
Q_OBJECT Q_OBJECT
FieldProjectNode* m_macroField; FieldProjectNode* m_macroField;
@ -41,6 +39,7 @@ signals:
public slots: public slots:
void targetPressed(); void targetPressed();
void updateMacroField(); void updateMacroField();
public: public:
explicit FieldSoundMacroStep(FieldProjectNode* macroField = Q_NULLPTR, QWidget* parent = Q_NULLPTR); explicit FieldSoundMacroStep(FieldProjectNode* macroField = Q_NULLPTR, QWidget* parent = Q_NULLPTR);
~FieldSoundMacroStep(); ~FieldSoundMacroStep();
@ -48,8 +47,7 @@ public:
void cancel(); void cancel();
}; };
class CommandWidget : public QWidget class CommandWidget : public QWidget {
{
Q_OBJECT Q_OBJECT
friend class SoundMacroListing; friend class SoundMacroListing;
QFont m_numberFont; QFont m_numberFont;
@ -67,8 +65,10 @@ private slots:
void numChanged(int); void numChanged(int);
void nodeChanged(int); void nodeChanged(int);
void deleteClicked(); void deleteClicked();
private: private:
CommandWidget(QWidget* parent, amuse::SoundMacro::ICmd* cmd, amuse::SoundMacro::CmdOp op, SoundMacroListing* listing); CommandWidget(QWidget* parent, amuse::SoundMacro::ICmd* cmd, amuse::SoundMacro::CmdOp op, SoundMacroListing* listing);
public: public:
CommandWidget(QWidget* parent, amuse::SoundMacro::ICmd* cmd, SoundMacroListing* listing); CommandWidget(QWidget* parent, amuse::SoundMacro::ICmd* cmd, SoundMacroListing* listing);
CommandWidget(QWidget* parent, amuse::SoundMacro::CmdOp op, SoundMacroListing* listing); CommandWidget(QWidget* parent, amuse::SoundMacro::CmdOp op, SoundMacroListing* listing);
@ -76,8 +76,7 @@ public:
QString getText() const { return m_titleLabel.text(); } QString getText() const { return m_titleLabel.text(); }
}; };
class CommandWidgetContainer : public QWidget class CommandWidgetContainer : public QWidget {
{
Q_OBJECT Q_OBJECT
friend class SoundMacroListing; friend class SoundMacroListing;
CommandWidget* m_commandWidget; CommandWidget* m_commandWidget;
@ -88,13 +87,13 @@ class CommandWidgetContainer : public QWidget
void snapClosed(); void snapClosed();
private slots: private slots:
void animationDestroyed(); void animationDestroyed();
public: public:
template <class..._Args> template <class... _Args>
CommandWidgetContainer(QWidget* parent, _Args&&... args); CommandWidgetContainer(QWidget* parent, _Args&&... args);
}; };
class SoundMacroListing : public QWidget class SoundMacroListing : public QWidget {
{
Q_OBJECT Q_OBJECT
friend class CommandWidget; friend class CommandWidget;
friend class SoundMacroEditor; friend class SoundMacroEditor;
@ -121,6 +120,7 @@ class SoundMacroListing : public QWidget
void deleteCommand(int index); void deleteCommand(int index);
void reindex(); void reindex();
void clear(); void clear();
public: public:
explicit SoundMacroListing(QWidget* parent = Q_NULLPTR); explicit SoundMacroListing(QWidget* parent = Q_NULLPTR);
bool loadData(ProjectModel::SoundMacroNode* node); bool loadData(ProjectModel::SoundMacroNode* node);
@ -129,22 +129,21 @@ public:
void timerEvent(QTimerEvent* event); void timerEvent(QTimerEvent* event);
}; };
class CatalogueItem : public QWidget class CatalogueItem : public QWidget {
{
Q_OBJECT Q_OBJECT
amuse::SoundMacro::CmdOp m_op; amuse::SoundMacro::CmdOp m_op;
QLabel m_iconLab; QLabel m_iconLab;
QLabel m_label; QLabel m_label;
public: public:
explicit CatalogueItem(amuse::SoundMacro::CmdOp op, const QString& name, explicit CatalogueItem(amuse::SoundMacro::CmdOp op, const QString& name, const QString& doc,
const QString& doc, QWidget* parent = Q_NULLPTR); QWidget* parent = Q_NULLPTR);
explicit CatalogueItem(const CatalogueItem& other, QWidget* parent = Q_NULLPTR); explicit CatalogueItem(const CatalogueItem& other, QWidget* parent = Q_NULLPTR);
amuse::SoundMacro::CmdOp getCmdOp() const { return m_op; } amuse::SoundMacro::CmdOp getCmdOp() const { return m_op; }
QString getText() const { return m_label.text(); } QString getText() const { return m_label.text(); }
}; };
class SoundMacroCatalogue : public QTreeWidget class SoundMacroCatalogue : public QTreeWidget {
{
Q_OBJECT Q_OBJECT
public: public:
explicit SoundMacroCatalogue(QWidget* parent = Q_NULLPTR); explicit SoundMacroCatalogue(QWidget* parent = Q_NULLPTR);
@ -153,8 +152,7 @@ public:
void mouseMoveEvent(QMouseEvent* event); void mouseMoveEvent(QMouseEvent* event);
}; };
class SoundMacroEditor : public EditorWidget class SoundMacroEditor : public EditorWidget {
{
Q_OBJECT Q_OBJECT
friend class SoundMacroCatalogue; friend class SoundMacroCatalogue;
friend class FieldSoundMacroStep; friend class FieldSoundMacroStep;
@ -170,6 +168,7 @@ class SoundMacroEditor : public EditorWidget
void beginCatalogueDrag(CatalogueItem* item, const QPoint& eventPt, const QPoint& pt); void beginCatalogueDrag(CatalogueItem* item, const QPoint& eventPt, const QPoint& pt);
void beginStepTarget(FieldSoundMacroStep* stepField); void beginStepTarget(FieldSoundMacroStep* stepField);
void endStepTarget(); void endStepTarget();
public: public:
explicit SoundMacroEditor(QWidget* parent = Q_NULLPTR); explicit SoundMacroEditor(QWidget* parent = Q_NULLPTR);
bool loadData(ProjectModel::SoundMacroNode* node); bool loadData(ProjectModel::SoundMacroNode* node);
@ -184,5 +183,3 @@ public:
public slots: public slots:
void catalogueDoubleClicked(QTreeWidgetItem* item, int column); void catalogueDoubleClicked(QTreeWidgetItem* item, int column);
}; };

View File

@ -1,16 +1,12 @@
#include "StatusBarWidget.hpp" #include "StatusBarWidget.hpp"
FXButton::FXButton(QWidget* parent) FXButton::FXButton(QWidget* parent) : QPushButton(parent) {
: QPushButton(parent)
{
setIcon(QIcon(QStringLiteral(":/icons/IconFX.svg"))); setIcon(QIcon(QStringLiteral(":/icons/IconFX.svg")));
setToolTip(tr("Access studio setup window for experimenting with audio effects")); setToolTip(tr("Access studio setup window for experimenting with audio effects"));
} }
StatusBarWidget::StatusBarWidget(QWidget* parent) StatusBarWidget::StatusBarWidget(QWidget* parent)
: QStatusBar(parent), m_volumeSlider(Qt::Horizontal), : QStatusBar(parent), m_volumeSlider(Qt::Horizontal), m_aSlider(Qt::Horizontal), m_bSlider(Qt::Horizontal) {
m_aSlider(Qt::Horizontal), m_bSlider(Qt::Horizontal)
{
addWidget(&m_normalMessage); addWidget(&m_normalMessage);
m_killButton.setIcon(QIcon(QStringLiteral(":/icons/IconKill.svg"))); m_killButton.setIcon(QIcon(QStringLiteral(":/icons/IconKill.svg")));
m_killButton.setVisible(false); m_killButton.setVisible(false);
@ -53,33 +49,26 @@ StatusBarWidget::StatusBarWidget(QWidget* parent)
addPermanentWidget(&m_volumeSlider); addPermanentWidget(&m_volumeSlider);
} }
void StatusBarWidget::setVoiceCount(int voices) void StatusBarWidget::setVoiceCount(int voices) {
{ if (voices != m_cachedVoiceCount) {
if (voices != m_cachedVoiceCount)
{
m_voiceCount.setText(QString::number(voices)); m_voiceCount.setText(QString::number(voices));
m_cachedVoiceCount = voices; m_cachedVoiceCount = voices;
setKillVisible(voices != 0); setKillVisible(voices != 0);
} }
} }
void StatusBarWidget::volumeChanged(int vol) void StatusBarWidget::volumeChanged(int vol) {
{
int idx = int(std::round(vol * (3.f / 100.f))); int idx = int(std::round(vol * (3.f / 100.f)));
if (idx != m_lastVolIdx) if (idx != m_lastVolIdx) {
{
m_lastVolIdx = idx; m_lastVolIdx = idx;
m_volumeIcon.setPixmap(m_volumeIcons[idx].pixmap(16, 16)); m_volumeIcon.setPixmap(m_volumeIcons[idx].pixmap(16, 16));
} }
} }
void StatusBarFocus::setMessage(const QString& message) void StatusBarFocus::setMessage(const QString& message) {
{
m_message = message; m_message = message;
if (StatusBarWidget* widget = qobject_cast<StatusBarWidget*>(parent())) if (StatusBarWidget* widget = qobject_cast<StatusBarWidget*>(parent())) {
{ if (widget->m_curFocus == this) {
if (widget->m_curFocus == this)
{
if (m_message.isEmpty()) if (m_message.isEmpty())
widget->clearMessage(); widget->clearMessage();
else else
@ -88,10 +77,8 @@ void StatusBarFocus::setMessage(const QString& message)
} }
} }
void StatusBarFocus::enter() void StatusBarFocus::enter() {
{ if (StatusBarWidget* widget = qobject_cast<StatusBarWidget*>(parent())) {
if (StatusBarWidget* widget = qobject_cast<StatusBarWidget*>(parent()))
{
widget->m_curFocus = this; widget->m_curFocus = this;
if (m_message.isEmpty()) if (m_message.isEmpty())
widget->clearMessage(); widget->clearMessage();
@ -100,12 +87,9 @@ void StatusBarFocus::enter()
} }
} }
void StatusBarFocus::exit() void StatusBarFocus::exit() {
{ if (StatusBarWidget* widget = qobject_cast<StatusBarWidget*>(parent())) {
if (StatusBarWidget* widget = qobject_cast<StatusBarWidget*>(parent())) if (widget->m_curFocus == this) {
{
if (widget->m_curFocus == this)
{
widget->clearMessage(); widget->clearMessage();
widget->m_curFocus = nullptr; widget->m_curFocus = nullptr;
} }

View File

@ -9,8 +9,7 @@
class StatusBarFocus; class StatusBarFocus;
class FXButton : public QPushButton class FXButton : public QPushButton {
{
Q_OBJECT Q_OBJECT
public: public:
explicit FXButton(QWidget* parent = Q_NULLPTR); explicit FXButton(QWidget* parent = Q_NULLPTR);
@ -20,8 +19,7 @@ public:
void keyPressEvent(QKeyEvent* event) { event->ignore(); } void keyPressEvent(QKeyEvent* event) { event->ignore(); }
}; };
class StatusBarWidget : public QStatusBar class StatusBarWidget : public QStatusBar {
{
friend class StatusBarFocus; friend class StatusBarFocus;
Q_OBJECT Q_OBJECT
QLabel m_normalMessage; QLabel m_normalMessage;
@ -38,38 +36,45 @@ class StatusBarWidget : public QStatusBar
QLabel m_voiceCount; QLabel m_voiceCount;
int m_cachedVoiceCount = -1; int m_cachedVoiceCount = -1;
StatusBarFocus* m_curFocus = nullptr; StatusBarFocus* m_curFocus = nullptr;
void setKillVisible(bool vis) { m_killButton.setVisible(vis); m_voiceCount.setVisible(vis); } void setKillVisible(bool vis) {
m_killButton.setVisible(vis);
m_voiceCount.setVisible(vis);
}
public: public:
explicit StatusBarWidget(QWidget* parent = Q_NULLPTR); explicit StatusBarWidget(QWidget* parent = Q_NULLPTR);
void setNormalMessage(const QString& message) { m_normalMessage.setText(message); } void setNormalMessage(const QString& message) { m_normalMessage.setText(message); }
void setVoiceCount(int voices); void setVoiceCount(int voices);
void connectKillClicked(const QObject* receiver, const char* method) void connectKillClicked(const QObject* receiver, const char* method) {
{ connect(&m_killButton, SIGNAL(clicked(bool)), receiver, method); } connect(&m_killButton, SIGNAL(clicked(bool)), receiver, method);
void connectFXPressed(const QObject* receiver, const char* method) }
{ connect(&m_fxButton, SIGNAL(pressed()), receiver, method); } void connectFXPressed(const QObject* receiver, const char* method) {
connect(&m_fxButton, SIGNAL(pressed()), receiver, method);
}
void setFXDown(bool down) { m_fxButton.setDown(down); } void setFXDown(bool down) { m_fxButton.setDown(down); }
void connectVolumeSlider(const QObject* receiver, const char* method) void connectVolumeSlider(const QObject* receiver, const char* method) {
{ connect(&m_volumeSlider, SIGNAL(valueChanged(int)), receiver, method); } connect(&m_volumeSlider, SIGNAL(valueChanged(int)), receiver, method);
void connectASlider(const QObject* receiver, const char* method) }
{ connect(&m_aSlider, SIGNAL(valueChanged(int)), receiver, method); } void connectASlider(const QObject* receiver, const char* method) {
void connectBSlider(const QObject* receiver, const char* method) connect(&m_aSlider, SIGNAL(valueChanged(int)), receiver, method);
{ connect(&m_bSlider, SIGNAL(valueChanged(int)), receiver, method); } }
void connectBSlider(const QObject* receiver, const char* method) {
connect(&m_bSlider, SIGNAL(valueChanged(int)), receiver, method);
}
void setVolumeValue(int vol) { m_volumeSlider.setValue(vol); } void setVolumeValue(int vol) { m_volumeSlider.setValue(vol); }
private slots: private slots:
void volumeChanged(int vol); void volumeChanged(int vol);
}; };
class StatusBarFocus : public QObject class StatusBarFocus : public QObject {
{ Q_OBJECT
Q_OBJECT
QString m_message; QString m_message;
public: public:
explicit StatusBarFocus(StatusBarWidget* statusWidget) explicit StatusBarFocus(StatusBarWidget* statusWidget) : QObject(statusWidget) {}
: QObject(statusWidget) {}
~StatusBarFocus() { exit(); } ~StatusBarFocus() { exit(); }
void setMessage(const QString& message); void setMessage(const QString& message);
void enter(); void enter();
void exit(); void exit();
}; };

File diff suppressed because it is too large Load Diff

View File

@ -14,17 +14,9 @@
class EffectListing; class EffectListing;
struct EffectIntrospection struct EffectIntrospection {
{ struct Field {
struct Field enum class Type { Invalid, UInt32, UInt32x8, Float };
{
enum class Type
{
Invalid,
UInt32,
UInt32x8,
Float
};
Type m_tp; Type m_tp;
std::string_view m_name; std::string_view m_name;
float m_min, m_max, m_default; float m_min, m_max, m_default;
@ -35,10 +27,10 @@ struct EffectIntrospection
Field m_fields[7]; Field m_fields[7];
}; };
class Uint32X8Popup : public QFrame class Uint32X8Popup : public QFrame {
{
Q_OBJECT Q_OBJECT
FieldSlider* m_sliders[8]; FieldSlider* m_sliders[8];
public: public:
explicit Uint32X8Popup(int min, int max, QWidget* parent = Q_NULLPTR); explicit Uint32X8Popup(int min, int max, QWidget* parent = Q_NULLPTR);
void setValue(int chanIdx, int val); void setValue(int chanIdx, int val);
@ -48,10 +40,10 @@ signals:
void valueChanged(int chanIdx, int val); void valueChanged(int chanIdx, int val);
}; };
class Uint32X8Button : public QPushButton class Uint32X8Button : public QPushButton {
{
Q_OBJECT Q_OBJECT
Uint32X8Popup* m_popup; Uint32X8Popup* m_popup;
public: public:
explicit Uint32X8Button(int min, int max, QWidget* parent = Q_NULLPTR); explicit Uint32X8Button(int min, int max, QWidget* parent = Q_NULLPTR);
void paintEvent(QPaintEvent* event); void paintEvent(QPaintEvent* event);
@ -61,8 +53,7 @@ private slots:
void onPressed(); void onPressed();
}; };
class EffectWidget : public QWidget class EffectWidget : public QWidget {
{
Q_OBJECT Q_OBJECT
friend class EffectListing; friend class EffectListing;
QFont m_numberFont; QFont m_numberFont;
@ -78,8 +69,10 @@ private slots:
void numChanged(double); void numChanged(double);
void chanNumChanged(int, int); void chanNumChanged(int, int);
void deleteClicked(); void deleteClicked();
private: private:
explicit EffectWidget(QWidget* parent, amuse::EffectBaseTypeless* effect, amuse::EffectType type); explicit EffectWidget(QWidget* parent, amuse::EffectBaseTypeless* effect, amuse::EffectType type);
public: public:
EffectListing* getParent() const; EffectListing* getParent() const;
explicit EffectWidget(QWidget* parent, amuse::EffectBaseTypeless* effect); explicit EffectWidget(QWidget* parent, amuse::EffectBaseTypeless* effect);
@ -88,8 +81,7 @@ public:
QString getText() const { return m_titleLabel.text(); } QString getText() const { return m_titleLabel.text(); }
}; };
class EffectWidgetContainer : public QWidget class EffectWidgetContainer : public QWidget {
{
Q_OBJECT Q_OBJECT
friend class EffectListing; friend class EffectListing;
EffectWidget* m_effectWidget; EffectWidget* m_effectWidget;
@ -100,13 +92,13 @@ class EffectWidgetContainer : public QWidget
void snapClosed(); void snapClosed();
private slots: private slots:
void animationDestroyed(); void animationDestroyed();
public: public:
template <class..._Args> template <class... _Args>
EffectWidgetContainer(QWidget* parent, _Args&&... args); EffectWidgetContainer(QWidget* parent, _Args&&... args);
}; };
class EffectListing : public QWidget class EffectListing : public QWidget {
{
Q_OBJECT Q_OBJECT
friend class EffectWidget; friend class EffectWidget;
friend class StudioSetupWidget; friend class StudioSetupWidget;
@ -133,6 +125,7 @@ class EffectListing : public QWidget
void deleteEffect(int index); void deleteEffect(int index);
void reindex(); void reindex();
void clear(); void clear();
public: public:
explicit EffectListing(QWidget* parent = Q_NULLPTR); explicit EffectListing(QWidget* parent = Q_NULLPTR);
bool loadData(amuse::Submix* submix); bool loadData(amuse::Submix* submix);
@ -140,22 +133,21 @@ public:
void timerEvent(QTimerEvent* event); void timerEvent(QTimerEvent* event);
}; };
class EffectCatalogueItem : public QWidget class EffectCatalogueItem : public QWidget {
{
Q_OBJECT Q_OBJECT
amuse::EffectType m_type; amuse::EffectType m_type;
QLabel m_iconLab; QLabel m_iconLab;
QLabel m_label; QLabel m_label;
public: public:
explicit EffectCatalogueItem(amuse::EffectType type, const QString& name, explicit EffectCatalogueItem(amuse::EffectType type, const QString& name, const QString& doc,
const QString& doc, QWidget* parent = Q_NULLPTR); QWidget* parent = Q_NULLPTR);
explicit EffectCatalogueItem(const EffectCatalogueItem& other, QWidget* parent = Q_NULLPTR); explicit EffectCatalogueItem(const EffectCatalogueItem& other, QWidget* parent = Q_NULLPTR);
amuse::EffectType getType() const { return m_type; } amuse::EffectType getType() const { return m_type; }
QString getText() const { return m_label.text(); } QString getText() const { return m_label.text(); }
}; };
class EffectCatalogue : public QTreeWidget class EffectCatalogue : public QTreeWidget {
{
Q_OBJECT Q_OBJECT
public: public:
explicit EffectCatalogue(QWidget* parent = Q_NULLPTR); explicit EffectCatalogue(QWidget* parent = Q_NULLPTR);
@ -164,8 +156,7 @@ public:
void mouseMoveEvent(QMouseEvent* event); void mouseMoveEvent(QMouseEvent* event);
}; };
class StudioSetupWidget : public QWidget class StudioSetupWidget : public QWidget {
{
Q_OBJECT Q_OBJECT
friend class EffectCatalogue; friend class EffectCatalogue;
QSplitter* m_splitter; QSplitter* m_splitter;
@ -179,6 +170,7 @@ class StudioSetupWidget : public QWidget
EffectListing* getCurrentListing() const; EffectListing* getCurrentListing() const;
void beginCommandDrag(EffectWidget* widget, const QPoint& eventPt, const QPoint& pt); void beginCommandDrag(EffectWidget* widget, const QPoint& eventPt, const QPoint& pt);
void beginCatalogueDrag(EffectCatalogueItem* item, const QPoint& eventPt, const QPoint& pt); void beginCatalogueDrag(EffectCatalogueItem* item, const QPoint& eventPt, const QPoint& pt);
public: public:
explicit StudioSetupWidget(QWidget* parent = Q_NULLPTR); explicit StudioSetupWidget(QWidget* parent = Q_NULLPTR);
bool loadData(amuse::Studio* studio); bool loadData(amuse::Studio* studio);
@ -200,4 +192,3 @@ signals:
void hidden(); void hidden();
void shown(); void shown();
}; };

View File

@ -17,13 +17,11 @@ void MacOSSetDarkAppearance();
extern "C" const uint8_t MAINICON_QT[]; extern "C" const uint8_t MAINICON_QT[];
static QIcon MakeAppIcon() static QIcon MakeAppIcon() {
{
QIcon ret; QIcon ret;
const uint8_t* ptr = MAINICON_QT; const uint8_t* ptr = MAINICON_QT;
for (int i = 0; i < 6; ++i) for (int i = 0; i < 6; ++i) {
{
uint32_t size = *reinterpret_cast<const uint32_t*>(ptr); uint32_t size = *reinterpret_cast<const uint32_t*>(ptr);
ptr += 4; ptr += 4;
@ -37,10 +35,10 @@ static QIcon MakeAppIcon()
} }
/* This is for adapting the get*Name methods */ /* This is for adapting the get*Name methods */
class BooInterface : public boo::IApplication class BooInterface : public boo::IApplication {
{
std::vector<boo::SystemString> m_args; std::vector<boo::SystemString> m_args;
void _deletedWindow(boo::IWindow* window) {} void _deletedWindow(boo::IWindow* window) {}
public: public:
EPlatformType getPlatformType() const { return EPlatformType::Qt; } EPlatformType getPlatformType() const { return EPlatformType::Qt; }
@ -56,8 +54,7 @@ public:
MainWindow* g_MainWindow = nullptr; MainWindow* g_MainWindow = nullptr;
int main(int argc, char* argv[]) int main(int argc, char* argv[]) {
{
QApplication::setAttribute(Qt::AA_Use96Dpi); QApplication::setAttribute(Qt::AA_Use96Dpi);
#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)) #if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0))
QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
@ -71,26 +68,26 @@ int main(int argc, char* argv[])
a.setApplicationName("Amuse"); a.setApplicationName("Amuse");
QPalette darkPalette; QPalette darkPalette;
darkPalette.setColor(QPalette::Window, QColor(53,53,53)); darkPalette.setColor(QPalette::Window, QColor(53, 53, 53));
darkPalette.setColor(QPalette::WindowText, Qt::white); darkPalette.setColor(QPalette::WindowText, Qt::white);
darkPalette.setColor(QPalette::Base, QColor(42,42,42)); darkPalette.setColor(QPalette::Base, QColor(42, 42, 42));
darkPalette.setColor(QPalette::Disabled, QPalette::Base, QColor(25,25,25,53)); darkPalette.setColor(QPalette::Disabled, QPalette::Base, QColor(25, 25, 25, 53));
darkPalette.setColor(QPalette::AlternateBase, QColor(53,53,53)); darkPalette.setColor(QPalette::AlternateBase, QColor(53, 53, 53));
darkPalette.setColor(QPalette::ToolTipBase, QColor(42,42,42)); darkPalette.setColor(QPalette::ToolTipBase, QColor(42, 42, 42));
darkPalette.setColor(QPalette::ToolTipText, Qt::white); darkPalette.setColor(QPalette::ToolTipText, Qt::white);
darkPalette.setColor(QPalette::Text, Qt::white); darkPalette.setColor(QPalette::Text, Qt::white);
darkPalette.setColor(QPalette::Disabled, QPalette::Text, QColor(255,255,255,120)); darkPalette.setColor(QPalette::Disabled, QPalette::Text, QColor(255, 255, 255, 120));
darkPalette.setColor(QPalette::Disabled, QPalette::Light, QColor(0,0,0,0)); darkPalette.setColor(QPalette::Disabled, QPalette::Light, QColor(0, 0, 0, 0));
darkPalette.setColor(QPalette::Button, QColor(53,53,53)); darkPalette.setColor(QPalette::Button, QColor(53, 53, 53));
darkPalette.setColor(QPalette::Disabled, QPalette::Button, QColor(53,53,53,53)); darkPalette.setColor(QPalette::Disabled, QPalette::Button, QColor(53, 53, 53, 53));
darkPalette.setColor(QPalette::ButtonText, Qt::white); darkPalette.setColor(QPalette::ButtonText, Qt::white);
darkPalette.setColor(QPalette::Disabled, QPalette::ButtonText, QColor(255,255,255,120)); darkPalette.setColor(QPalette::Disabled, QPalette::ButtonText, QColor(255, 255, 255, 120));
darkPalette.setColor(QPalette::BrightText, Qt::red); darkPalette.setColor(QPalette::BrightText, Qt::red);
darkPalette.setColor(QPalette::Link, QColor(42,130,218)); darkPalette.setColor(QPalette::Link, QColor(42, 130, 218));
darkPalette.setColor(QPalette::Highlight, QColor(42,130,218)); darkPalette.setColor(QPalette::Highlight, QColor(42, 130, 218));
darkPalette.setColor(QPalette::Disabled, QPalette::Highlight, QColor(42,130,218,53)); darkPalette.setColor(QPalette::Disabled, QPalette::Highlight, QColor(42, 130, 218, 53));
darkPalette.setColor(QPalette::HighlightedText, Qt::white); darkPalette.setColor(QPalette::HighlightedText, Qt::white);
darkPalette.setColor(QPalette::Disabled, QPalette::HighlightedText, QColor(255,255,255,120)); darkPalette.setColor(QPalette::Disabled, QPalette::HighlightedText, QColor(255, 255, 255, 120));
a.setPalette(darkPalette); a.setPalette(darkPalette);
#ifdef __APPLE__ #ifdef __APPLE__

File diff suppressed because it is too large Load Diff

View File

@ -3,8 +3,7 @@
#include <Shellapi.h> #include <Shellapi.h>
#include <Shlwapi.h> #include <Shlwapi.h>
namespace amuse namespace amuse {
{
static const wchar_t* const GMNames[128] = {L"Acoustic Grand Piano", static const wchar_t* const GMNames[128] = {L"Acoustic Grand Piano",
L"Bright Acoustic Piano", L"Bright Acoustic Piano",
@ -154,8 +153,7 @@ static const wchar_t* const GMPercNames[128] = {
L"Hi Wood Block", L"Low Wood Block", L"Mute Cuica", L"Open Cuica", L"Mute Triangle", L"Hi Wood Block", L"Low Wood Block", L"Mute Cuica", L"Open Cuica", L"Mute Triangle",
L"Open Triangle"}; L"Open Triangle"};
bool AudioGroupDataCollection::loadProj() bool AudioGroupDataCollection::loadProj() {
{
std::wstring path = m_path + L"\\proj"; std::wstring path = m_path + L"\\proj";
athena::io::FileReader r(path, 1024 * 32, false); athena::io::FileReader r(path, 1024 * 32, false);
if (r.hasError()) if (r.hasError())
@ -167,8 +165,7 @@ bool AudioGroupDataCollection::loadProj()
return ret.size() != 0; return ret.size() != 0;
} }
bool AudioGroupDataCollection::loadPool() bool AudioGroupDataCollection::loadPool() {
{
std::wstring path = m_path + L"\\pool"; std::wstring path = m_path + L"\\pool";
athena::io::FileReader r(path, 1024 * 32, false); athena::io::FileReader r(path, 1024 * 32, false);
if (r.hasError()) if (r.hasError())
@ -180,8 +177,7 @@ bool AudioGroupDataCollection::loadPool()
return ret.size() != 0; return ret.size() != 0;
} }
bool AudioGroupDataCollection::loadSdir() bool AudioGroupDataCollection::loadSdir() {
{
std::wstring path = m_path + L"\\sdir"; std::wstring path = m_path + L"\\sdir";
athena::io::FileReader r(path, 1024 * 32, false); athena::io::FileReader r(path, 1024 * 32, false);
if (r.hasError()) if (r.hasError())
@ -193,8 +189,7 @@ bool AudioGroupDataCollection::loadSdir()
return ret.size() != 0; return ret.size() != 0;
} }
bool AudioGroupDataCollection::loadSamp() bool AudioGroupDataCollection::loadSamp() {
{
std::wstring path = m_path + L"\\samp"; std::wstring path = m_path + L"\\samp";
athena::io::FileReader r(path, 1024 * 32, false); athena::io::FileReader r(path, 1024 * 32, false);
if (r.hasError()) if (r.hasError())
@ -206,8 +201,7 @@ bool AudioGroupDataCollection::loadSamp()
return ret.size() != 0; return ret.size() != 0;
} }
bool AudioGroupDataCollection::loadMeta() bool AudioGroupDataCollection::loadMeta() {
{
std::wstring path = m_path + L"\\meta"; std::wstring path = m_path + L"\\meta";
athena::io::FileReader r(path, 1024 * 32, false); athena::io::FileReader r(path, 1024 * 32, false);
if (r.hasError()) if (r.hasError())
@ -218,12 +212,9 @@ bool AudioGroupDataCollection::loadMeta()
} }
AudioGroupDataCollection::AudioGroupDataCollection(std::wstring_view path, std::wstring_view name) AudioGroupDataCollection::AudioGroupDataCollection(std::wstring_view path, std::wstring_view name)
: m_path(path), m_name(name) : m_path(path), m_name(name) {}
{
}
bool AudioGroupDataCollection::_attemptLoad() bool AudioGroupDataCollection::_attemptLoad() {
{
if (m_metaData && m_loadedData && m_loadedGroup) if (m_metaData && m_loadedData && m_loadedGroup)
return true; return true;
if (!loadProj()) if (!loadProj())
@ -240,39 +231,33 @@ bool AudioGroupDataCollection::_attemptLoad()
return _indexData(); return _indexData();
} }
bool AudioGroupDataCollection::_indexData() bool AudioGroupDataCollection::_indexData() {
{ switch (m_metaData->fmt) {
switch (m_metaData->fmt)
{
case amuse::DataFormat::GCN: case amuse::DataFormat::GCN:
default: default:
m_loadedData.emplace(m_projData.data(), m_projData.size(), m_poolData.data(), m_poolData.size(), m_loadedData.emplace(m_projData.data(), m_projData.size(), m_poolData.data(), m_poolData.size(), m_sdirData.data(),
m_sdirData.data(), m_sdirData.size(), m_sampData.data(), m_sampData.size(), m_sdirData.size(), m_sampData.data(), m_sampData.size(), amuse::GCNDataTag{});
amuse::GCNDataTag{});
break; break;
case amuse::DataFormat::N64: case amuse::DataFormat::N64:
m_loadedData.emplace(m_projData.data(), m_projData.size(), m_poolData.data(), m_poolData.size(), m_loadedData.emplace(m_projData.data(), m_projData.size(), m_poolData.data(), m_poolData.size(), m_sdirData.data(),
m_sdirData.data(), m_sdirData.size(), m_sampData.data(), m_sampData.size(), m_sdirData.size(), m_sampData.data(), m_sampData.size(), m_metaData->absOffs,
m_metaData->absOffs, amuse::N64DataTag{}); amuse::N64DataTag{});
break; break;
case amuse::DataFormat::PC: case amuse::DataFormat::PC:
m_loadedData.emplace(m_projData.data(), m_projData.size(), m_poolData.data(), m_poolData.size(), m_loadedData.emplace(m_projData.data(), m_projData.size(), m_poolData.data(), m_poolData.size(), m_sdirData.data(),
m_sdirData.data(), m_sdirData.size(), m_sampData.data(), m_sampData.size(), m_sdirData.size(), m_sampData.data(), m_sampData.size(), m_metaData->absOffs,
m_metaData->absOffs, amuse::PCDataTag{}); amuse::PCDataTag{});
break; break;
} }
return m_loadedData.operator bool(); return m_loadedData.operator bool();
} }
void AudioGroupDataCollection::addToEngine(amuse::Engine& engine) void AudioGroupDataCollection::addToEngine(amuse::Engine& engine) {
{
m_loadedGroup = engine.addAudioGroup(*m_loadedData); m_loadedGroup = engine.addAudioGroup(*m_loadedData);
m_groupTokens.clear(); m_groupTokens.clear();
if (m_loadedGroup) if (m_loadedGroup) {
{ m_groupTokens.reserve(m_loadedGroup->getProj().songGroups().size() + m_loadedGroup->getProj().sfxGroups().size());
m_groupTokens.reserve(m_loadedGroup->getProj().songGroups().size() +
m_loadedGroup->getProj().sfxGroups().size());
{ {
const auto& songGroups = m_loadedGroup->getProj().songGroups(); const auto& songGroups = m_loadedGroup->getProj().songGroups();
@ -296,24 +281,18 @@ void AudioGroupDataCollection::addToEngine(amuse::Engine& engine)
void AudioGroupDataCollection::removeFromEngine(amuse::Engine& engine) const { engine.removeAudioGroup(*m_loadedData); } void AudioGroupDataCollection::removeFromEngine(amuse::Engine& engine) const { engine.removeAudioGroup(*m_loadedData); }
AudioGroupCollection::AudioGroupCollection(std::wstring_view path, std::wstring_view name) AudioGroupCollection::AudioGroupCollection(std::wstring_view path, std::wstring_view name)
: m_path(path), m_name(name) : m_path(path), m_name(name) {}
{
}
void AudioGroupCollection::addCollection( void AudioGroupCollection::addCollection(
std::vector<std::pair<std::wstring, amuse::IntrusiveAudioGroupData>>&& collection) std::vector<std::pair<std::wstring, amuse::IntrusiveAudioGroupData>>&& collection) {
{ for (std::pair<std::wstring, amuse::IntrusiveAudioGroupData>& pair : collection) {
for (std::pair<std::wstring, amuse::IntrusiveAudioGroupData>& pair : collection)
{
std::wstring collectionPath = m_path + L'\\' + pair.first; std::wstring collectionPath = m_path + L'\\' + pair.first;
amuse::IntrusiveAudioGroupData& dataIn = pair.second; amuse::IntrusiveAudioGroupData& dataIn = pair.second;
auto search = m_groups.find(pair.first); auto search = m_groups.find(pair.first);
if (search == m_groups.end()) if (search == m_groups.end()) {
{
search = search =
m_groups.emplace(pair.first, std::make_unique<AudioGroupDataCollection>(collectionPath, pair.first)) m_groups.emplace(pair.first, std::make_unique<AudioGroupDataCollection>(collectionPath, pair.first)).first;
.first;
} }
AudioGroupDataCollection& dataCollection = *search->second; AudioGroupDataCollection& dataCollection = *search->second;
@ -334,28 +313,23 @@ void AudioGroupCollection::addCollection(
} }
} }
void AudioGroupCollection::update(AudioGroupFilePresenter& presenter) void AudioGroupCollection::update(AudioGroupFilePresenter& presenter) {
{
std::wstring path = m_path + L"\\*"; std::wstring path = m_path + L"\\*";
WIN32_FIND_DATAW d; WIN32_FIND_DATAW d;
HANDLE dir = FindFirstFileW(path.c_str(), &d); HANDLE dir = FindFirstFileW(path.c_str(), &d);
if (dir == INVALID_HANDLE_VALUE) if (dir == INVALID_HANDLE_VALUE)
return; return;
do do {
{
if (!wcscmp(d.cFileName, L".") || !wcscmp(d.cFileName, L"..")) if (!wcscmp(d.cFileName, L".") || !wcscmp(d.cFileName, L".."))
continue; continue;
if (d.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) if (d.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
{
std::wstring nameStr(d.cFileName); std::wstring nameStr(d.cFileName);
auto search = m_groups.find(nameStr); auto search = m_groups.find(nameStr);
if (search == m_groups.end()) if (search == m_groups.end()) {
{
search = search =
m_groups m_groups.emplace(nameStr, std::make_unique<AudioGroupDataCollection>(m_path + L'\\' + nameStr, nameStr))
.emplace(nameStr, std::make_unique<AudioGroupDataCollection>(m_path + L'\\' + nameStr, nameStr))
.first; .first;
search->second->_attemptLoad(); search->second->_attemptLoad();
} }
@ -365,8 +339,7 @@ void AudioGroupCollection::update(AudioGroupFilePresenter& presenter)
FindClose(dir); FindClose(dir);
} }
void AudioGroupFilePresenter::update() void AudioGroupFilePresenter::update() {
{
std::wstring path = m_backend.getUserDir() + L"\\*"; std::wstring path = m_backend.getUserDir() + L"\\*";
std::map<std::wstring, std::unique_ptr<AudioGroupCollection>>& theMap = m_audioGroupCollections; std::map<std::wstring, std::unique_ptr<AudioGroupCollection>>& theMap = m_audioGroupCollections;
@ -374,20 +347,17 @@ void AudioGroupFilePresenter::update()
HANDLE dir = FindFirstFileW(path.c_str(), &d); HANDLE dir = FindFirstFileW(path.c_str(), &d);
if (dir == INVALID_HANDLE_VALUE) if (dir == INVALID_HANDLE_VALUE)
return; return;
do do {
{
if (!wcscmp(d.cFileName, L".") || !wcscmp(d.cFileName, L"..")) if (!wcscmp(d.cFileName, L".") || !wcscmp(d.cFileName, L".."))
continue; continue;
if (d.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) if (d.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
{
std::wstring nameStr(d.cFileName); std::wstring nameStr(d.cFileName);
auto search = theMap.find(nameStr); auto search = theMap.find(nameStr);
if (search == theMap.end()) if (search == theMap.end()) {
{
search = theMap search = theMap
.emplace(nameStr, std::make_unique<AudioGroupCollection>( .emplace(nameStr,
m_backend.getUserDir() + L'\\' + nameStr, nameStr)) std::make_unique<AudioGroupCollection>(m_backend.getUserDir() + L'\\' + nameStr, nameStr))
.first; .first;
search->second->update(*this); search->second->update(*this);
} }
@ -398,60 +368,51 @@ void AudioGroupFilePresenter::update()
} }
void AudioGroupFilePresenter::addCollection( void AudioGroupFilePresenter::addCollection(
std::wstring_view name, std::vector<std::pair<std::wstring, amuse::IntrusiveAudioGroupData>>&& collection) std::wstring_view name, std::vector<std::pair<std::wstring, amuse::IntrusiveAudioGroupData>>&& collection) {
{
std::wstring path = m_backend.getUserDir() + L'\\' + name; std::wstring path = m_backend.getUserDir() + L'\\' + name;
AudioGroupCollection& insert = AudioGroupCollection& insert =
*m_audioGroupCollections.emplace(name, std::make_unique<AudioGroupCollection>(path, name)).first->second; *m_audioGroupCollections.emplace(name, std::make_unique<AudioGroupCollection>(path, name)).first->second;
CreateDirectory(insert.m_path.c_str(), nullptr); CreateDirectory(insert.m_path.c_str(), nullptr);
insert.addCollection(std::move(collection)); insert.addCollection(std::move(collection));
for (std::pair<const std::wstring, std::unique_ptr<AudioGroupDataCollection>>& pair : insert.m_groups) for (std::pair<const std::wstring, std::unique_ptr<AudioGroupDataCollection>>& pair : insert.m_groups) {
{
std::wstring collectionPath = insert.m_path + L'\\' + pair.first; std::wstring collectionPath = insert.m_path + L'\\' + pair.first;
CreateDirectory(collectionPath.c_str(), nullptr); CreateDirectory(collectionPath.c_str(), nullptr);
FILE* fp = _wfopen((collectionPath + L"\\proj").c_str(), L"wb"); FILE* fp = _wfopen((collectionPath + L"\\proj").c_str(), L"wb");
if (fp) if (fp) {
{
fwrite(pair.second->m_projData.data(), 1, pair.second->m_projData.size(), fp); fwrite(pair.second->m_projData.data(), 1, pair.second->m_projData.size(), fp);
fclose(fp); fclose(fp);
} }
fp = _wfopen((collectionPath + L"\\pool").c_str(), L"wb"); fp = _wfopen((collectionPath + L"\\pool").c_str(), L"wb");
if (fp) if (fp) {
{
fwrite(pair.second->m_poolData.data(), 1, pair.second->m_poolData.size(), fp); fwrite(pair.second->m_poolData.data(), 1, pair.second->m_poolData.size(), fp);
fclose(fp); fclose(fp);
} }
fp = _wfopen((collectionPath + L"\\sdir").c_str(), L"wb"); fp = _wfopen((collectionPath + L"\\sdir").c_str(), L"wb");
if (fp) if (fp) {
{
fwrite(pair.second->m_sdirData.data(), 1, pair.second->m_sdirData.size(), fp); fwrite(pair.second->m_sdirData.data(), 1, pair.second->m_sdirData.size(), fp);
fclose(fp); fclose(fp);
} }
fp = _wfopen((collectionPath + L"\\samp").c_str(), L"wb"); fp = _wfopen((collectionPath + L"\\samp").c_str(), L"wb");
if (fp) if (fp) {
{
fwrite(pair.second->m_sampData.data(), 1, pair.second->m_sampData.size(), fp); fwrite(pair.second->m_sampData.data(), 1, pair.second->m_sampData.size(), fp);
fclose(fp); fclose(fp);
} }
fp = _wfopen((collectionPath + L"\\meta").c_str(), L"wb"); fp = _wfopen((collectionPath + L"\\meta").c_str(), L"wb");
if (fp) if (fp) {
{
fwrite(&*pair.second->m_metaData, 1, sizeof(*pair.second->m_metaData), fp); fwrite(&*pair.second->m_metaData, 1, sizeof(*pair.second->m_metaData), fp);
fclose(fp); fclose(fp);
} }
} }
} }
void AudioGroupFilePresenter::removeCollection(unsigned idx) void AudioGroupFilePresenter::removeCollection(unsigned idx) {
{ if (idx < m_iteratorVec.size()) {
if (idx < m_iteratorVec.size())
{
CollectionIterator& it = m_iteratorVec[idx]; CollectionIterator& it = m_iteratorVec[idx];
std::wstring collectionPath = it->second->m_path + L'\0'; std::wstring collectionPath = it->second->m_path + L'\0';
SHFILEOPSTRUCT op = {}; SHFILEOPSTRUCT op = {};
@ -463,8 +424,7 @@ void AudioGroupFilePresenter::removeCollection(unsigned idx)
} }
} }
void AudioGroupCollection::populateFiles(VSTEditor& editor, HTREEITEM colHandle, size_t parentIdx) void AudioGroupCollection::populateFiles(VSTEditor& editor, HTREEITEM colHandle, size_t parentIdx) {
{
TVINSERTSTRUCT ins = {}; TVINSERTSTRUCT ins = {};
ins.item.mask = TVIF_TEXT | TVIF_PARAM; ins.item.mask = TVIF_TEXT | TVIF_PARAM;
ins.hParent = colHandle; ins.hParent = colHandle;
@ -472,8 +432,7 @@ void AudioGroupCollection::populateFiles(VSTEditor& editor, HTREEITEM colHandle,
m_iteratorVec.clear(); m_iteratorVec.clear();
m_iteratorVec.reserve(m_groups.size()); m_iteratorVec.reserve(m_groups.size());
for (auto it = m_groups.begin(); it != m_groups.end(); ++it) for (auto it = m_groups.begin(); it != m_groups.end(); ++it) {
{
ins.item.pszText = LPWSTR(it->first.c_str()); ins.item.pszText = LPWSTR(it->first.c_str());
ins.item.lParam = LPARAM(0x80000000 | (parentIdx << 16) | m_iteratorVec.size()); ins.item.lParam = LPARAM(0x80000000 | (parentIdx << 16) | m_iteratorVec.size());
HTREEITEM item = TreeView_InsertItem(editor.m_collectionTree, &ins); HTREEITEM item = TreeView_InsertItem(editor.m_collectionTree, &ins);
@ -483,8 +442,7 @@ void AudioGroupCollection::populateFiles(VSTEditor& editor, HTREEITEM colHandle,
} }
} }
void AudioGroupFilePresenter::populateCollectionColumn(VSTEditor& editor) void AudioGroupFilePresenter::populateCollectionColumn(VSTEditor& editor) {
{
TreeView_DeleteAllItems(editor.m_collectionTree); TreeView_DeleteAllItems(editor.m_collectionTree);
TVINSERTSTRUCT ins = {}; TVINSERTSTRUCT ins = {};
ins.hParent = TVI_ROOT; ins.hParent = TVI_ROOT;
@ -493,8 +451,7 @@ void AudioGroupFilePresenter::populateCollectionColumn(VSTEditor& editor)
m_iteratorVec.clear(); m_iteratorVec.clear();
m_iteratorVec.reserve(m_audioGroupCollections.size()); m_iteratorVec.reserve(m_audioGroupCollections.size());
for (auto it = m_audioGroupCollections.begin(); it != m_audioGroupCollections.end(); ++it) for (auto it = m_audioGroupCollections.begin(); it != m_audioGroupCollections.end(); ++it) {
{
ins.item.cChildren = it->second->m_groups.size() ? 1 : 0; ins.item.cChildren = it->second->m_groups.size() ? 1 : 0;
ins.item.pszText = LPWSTR(it->first.c_str()); ins.item.pszText = LPWSTR(it->first.c_str());
ins.item.lParam = LPARAM(m_iteratorVec.size() << 16); ins.item.lParam = LPARAM(m_iteratorVec.size() << 16);
@ -506,22 +463,18 @@ void AudioGroupFilePresenter::populateCollectionColumn(VSTEditor& editor)
} }
} }
void AudioGroupFilePresenter::populateGroupColumn(VSTEditor& editor, int collectionIdx, int fileIdx) void AudioGroupFilePresenter::populateGroupColumn(VSTEditor& editor, int collectionIdx, int fileIdx) {
{
LVITEM item = {}; LVITEM item = {};
item.mask = LVIF_TEXT; item.mask = LVIF_TEXT;
ListView_DeleteAllItems(editor.m_groupListView); ListView_DeleteAllItems(editor.m_groupListView);
ListView_DeleteAllItems(editor.m_pageListView); ListView_DeleteAllItems(editor.m_pageListView);
if (collectionIdx < m_iteratorVec.size()) if (collectionIdx < m_iteratorVec.size()) {
{
CollectionIterator& it = m_iteratorVec[collectionIdx]; CollectionIterator& it = m_iteratorVec[collectionIdx];
if (fileIdx < it->second->m_iteratorVec.size()) if (fileIdx < it->second->m_iteratorVec.size()) {
{
size_t idx = 0; size_t idx = 0;
AudioGroupCollection::GroupIterator& git = it->second->m_iteratorVec[fileIdx]; AudioGroupCollection::GroupIterator& git = it->second->m_iteratorVec[fileIdx];
for (AudioGroupDataCollection::GroupToken& gtok : git->second->m_groupTokens) for (AudioGroupDataCollection::GroupToken& gtok : git->second->m_groupTokens) {
{
wchar_t name[256]; wchar_t name[256];
wnsprintf(name, 256, L"%d (%s)", gtok.m_groupId, gtok.m_song ? L"Song" : L"SFX"); wnsprintf(name, 256, L"%d (%s)", gtok.m_groupId, gtok.m_song ? L"Song" : L"SFX");
item.pszText = name; item.pszText = name;
@ -532,33 +485,26 @@ void AudioGroupFilePresenter::populateGroupColumn(VSTEditor& editor, int collect
} }
} }
void AudioGroupFilePresenter::populatePageColumn(VSTEditor& editor, int collectionIdx, int fileIdx, int groupIdx) void AudioGroupFilePresenter::populatePageColumn(VSTEditor& editor, int collectionIdx, int fileIdx, int groupIdx) {
{
LVITEM item = {}; LVITEM item = {};
item.mask = LVIF_TEXT | LVIF_PARAM; item.mask = LVIF_TEXT | LVIF_PARAM;
ListView_DeleteAllItems(editor.m_pageListView); ListView_DeleteAllItems(editor.m_pageListView);
if (collectionIdx < m_iteratorVec.size()) if (collectionIdx < m_iteratorVec.size()) {
{
CollectionIterator& it = m_iteratorVec[collectionIdx]; CollectionIterator& it = m_iteratorVec[collectionIdx];
if (fileIdx < it->second->m_iteratorVec.size()) if (fileIdx < it->second->m_iteratorVec.size()) {
{
AudioGroupCollection::GroupIterator& git = it->second->m_iteratorVec[fileIdx]; AudioGroupCollection::GroupIterator& git = it->second->m_iteratorVec[fileIdx];
if (groupIdx < git->second->m_groupTokens.size()) if (groupIdx < git->second->m_groupTokens.size()) {
{
AudioGroupDataCollection::GroupToken& groupTok = git->second->m_groupTokens[groupIdx]; AudioGroupDataCollection::GroupToken& groupTok = git->second->m_groupTokens[groupIdx];
if (groupTok.m_song) if (groupTok.m_song) {
{
std::map<uint8_t, const amuse::SongGroupIndex::PageEntry*> sortPages; std::map<uint8_t, const amuse::SongGroupIndex::PageEntry*> sortPages;
for (auto& pair : groupTok.m_song->m_normPages) for (auto& pair : groupTok.m_song->m_normPages)
sortPages[pair.first] = pair.second; sortPages[pair.first] = pair.second;
size_t idx = 0; size_t idx = 0;
for (auto& pair : sortPages) for (auto& pair : sortPages) {
{
wchar_t name[256]; wchar_t name[256];
wnsprintf(name, 256, L"%d (%s)", pair.first, wnsprintf(name, 256, L"%d (%s)", pair.first, GMNames[pair.first] ? GMNames[pair.first] : L"???");
GMNames[pair.first] ? GMNames[pair.first] : L"???");
item.pszText = name; item.pszText = name;
item.iItem = idx++; item.iItem = idx++;
item.lParam = pair.first; item.lParam = pair.first;
@ -569,11 +515,9 @@ void AudioGroupFilePresenter::populatePageColumn(VSTEditor& editor, int collecti
for (auto& pair : groupTok.m_song->m_drumPages) for (auto& pair : groupTok.m_song->m_drumPages)
sortPages[pair.first] = pair.second; sortPages[pair.first] = pair.second;
for (auto& pair : sortPages) for (auto& pair : sortPages) {
{
wchar_t name[256]; wchar_t name[256];
wnsprintf(name, 256, L"%d (%s)", pair.first, wnsprintf(name, 256, L"%d (%s)", pair.first, GMPercNames[pair.first] ? GMPercNames[pair.first] : L"???");
GMPercNames[pair.first] ? GMPercNames[pair.first] : L"???");
item.pszText = name; item.pszText = name;
item.iItem = idx++; item.iItem = idx++;
item.lParam = 0x80000000 | pair.first; item.lParam = 0x80000000 | pair.first;
@ -584,4 +528,4 @@ void AudioGroupFilePresenter::populatePageColumn(VSTEditor& editor, int collecti
} }
} }
} }
} } // namespace amuse

View File

@ -10,14 +10,12 @@
#include <windows.h> #include <windows.h>
#include <CommCtrl.h> #include <CommCtrl.h>
namespace amuse namespace amuse {
{
class VSTBackend; class VSTBackend;
class VSTEditor; class VSTEditor;
class AudioGroupFilePresenter; class AudioGroupFilePresenter;
struct AudioGroupDataCollection struct AudioGroupDataCollection {
{
std::wstring m_path; std::wstring m_path;
std::wstring m_name; std::wstring m_name;
@ -26,26 +24,20 @@ struct AudioGroupDataCollection
std::vector<uint8_t> m_sdirData; std::vector<uint8_t> m_sdirData;
std::vector<uint8_t> m_sampData; std::vector<uint8_t> m_sampData;
struct MetaData struct MetaData {
{
amuse::DataFormat fmt; amuse::DataFormat fmt;
uint32_t absOffs; uint32_t absOffs;
uint32_t active; uint32_t active;
MetaData(amuse::DataFormat fmtIn, uint32_t absOffsIn, uint32_t activeIn) MetaData(amuse::DataFormat fmtIn, uint32_t absOffsIn, uint32_t activeIn)
: fmt(fmtIn), absOffs(absOffsIn), active(activeIn) : fmt(fmtIn), absOffs(absOffsIn), active(activeIn) {}
{
}
MetaData(athena::io::FileReader& r) MetaData(athena::io::FileReader& r)
: fmt(amuse::DataFormat(r.readUint32Little())), absOffs(r.readUint32Little()), active(r.readUint32Little()) : fmt(amuse::DataFormat(r.readUint32Little())), absOffs(r.readUint32Little()), active(r.readUint32Little()) {}
{
}
}; };
std::experimental::optional<MetaData> m_metaData; std::experimental::optional<MetaData> m_metaData;
std::experimental::optional<amuse::AudioGroupData> m_loadedData; std::experimental::optional<amuse::AudioGroupData> m_loadedData;
const amuse::AudioGroup* m_loadedGroup; const amuse::AudioGroup* m_loadedGroup;
struct GroupToken struct GroupToken {
{
int m_groupId; int m_groupId;
const amuse::SongGroupIndex* m_song = nullptr; const amuse::SongGroupIndex* m_song = nullptr;
const amuse::SFXGroupIndex* m_sfx = nullptr; const amuse::SFXGroupIndex* m_sfx = nullptr;
@ -61,8 +53,7 @@ struct AudioGroupDataCollection
bool loadMeta(); bool loadMeta();
AudioGroupDataCollection(std::wstring_view path, std::wstring_view name); AudioGroupDataCollection(std::wstring_view path, std::wstring_view name);
bool isDataComplete() const bool isDataComplete() const {
{
return m_projData.size() && m_poolData.size() && m_sdirData.size() && m_sampData.size() && m_metaData; return m_projData.size() && m_poolData.size() && m_sdirData.size() && m_sampData.size() && m_metaData;
} }
bool _attemptLoad(); bool _attemptLoad();
@ -72,8 +63,7 @@ struct AudioGroupDataCollection
void removeFromEngine(amuse::Engine& engine) const; void removeFromEngine(amuse::Engine& engine) const;
}; };
struct AudioGroupCollection struct AudioGroupCollection {
{
using GroupIterator = std::map<std::wstring, std::unique_ptr<AudioGroupDataCollection>>::iterator; using GroupIterator = std::map<std::wstring, std::unique_ptr<AudioGroupDataCollection>>::iterator;
std::wstring m_path; std::wstring m_path;
std::wstring m_name; std::wstring m_name;
@ -87,8 +77,7 @@ struct AudioGroupCollection
void populateFiles(VSTEditor& editor, HTREEITEM colHandle, size_t parentIdx); void populateFiles(VSTEditor& editor, HTREEITEM colHandle, size_t parentIdx);
}; };
class AudioGroupFilePresenter class AudioGroupFilePresenter {
{
friend class VSTBackend; friend class VSTBackend;
public: public:
@ -110,5 +99,4 @@ public:
void removeCollection(unsigned idx); void removeCollection(unsigned idx);
VSTBackend& getBackend() { return m_backend; } VSTBackend& getBackend() { return m_backend; }
}; };
} } // namespace amuse

View File

@ -18,7 +18,8 @@
#define CONTROL_GROUP 2000 #define CONTROL_GROUP 2000
#define CONTROL_RADIOBUTTONLIST 2 #define CONTROL_RADIOBUTTONLIST 2
#define CONTROL_RADIOBUTTON1 1 #define CONTROL_RADIOBUTTON1 1
#define CONTROL_RADIOBUTTON2 2 // It is OK for this to have the same IDas CONTROL_RADIOBUTTONLIST, #define CONTROL_RADIOBUTTON2 \
2 // It is OK for this to have the same IDas CONTROL_RADIOBUTTONLIST,
// because it is a child control under CONTROL_RADIOBUTTONLIST // because it is a child control under CONTROL_RADIOBUTTONLIST
// IDs for the Task Dialog Buttons // IDs for the Task Dialog Buttons
@ -33,12 +34,10 @@ HWND ghMainWnd = 0;
HINSTANCE ghAppInst = 0; HINSTANCE ghAppInst = 0;
RECT winRect; RECT winRect;
class CDialogEventHandler : public IFileDialogEvents, public IFileDialogControlEvents class CDialogEventHandler : public IFileDialogEvents, public IFileDialogControlEvents {
{
public: public:
// IUnknown methods // IUnknown methods
IFACEMETHODIMP QueryInterface(REFIID riid, void** ppv) IFACEMETHODIMP QueryInterface(REFIID riid, void** ppv) {
{
static const QITAB qit[] = { static const QITAB qit[] = {
QITABENT(CDialogEventHandler, IFileDialogEvents), QITABENT(CDialogEventHandler, IFileDialogEvents),
QITABENT(CDialogEventHandler, IFileDialogControlEvents), QITABENT(CDialogEventHandler, IFileDialogControlEvents),
@ -49,8 +48,7 @@ public:
IFACEMETHODIMP_(ULONG) AddRef() { return InterlockedIncrement(&_cRef); } IFACEMETHODIMP_(ULONG) AddRef() { return InterlockedIncrement(&_cRef); }
IFACEMETHODIMP_(ULONG) Release() IFACEMETHODIMP_(ULONG) Release() {
{
long cRef = InterlockedDecrement(&_cRef); long cRef = InterlockedDecrement(&_cRef);
if (!cRef) if (!cRef)
delete this; delete this;
@ -82,8 +80,7 @@ private:
HRESULT CDialogEventHandler_CreateInstance(REFIID riid, void** ppv); HRESULT CDialogEventHandler_CreateInstance(REFIID riid, void** ppv);
std::wstring openDB() std::wstring openDB() {
{
std::wstring ret; std::wstring ret;
CoInitializeEx(NULL, COINIT_MULTITHREADED | COINIT_DISABLE_OLE1DDE); CoInitializeEx(NULL, COINIT_MULTITHREADED | COINIT_DISABLE_OLE1DDE);
@ -92,8 +89,7 @@ std::wstring openDB()
HRESULT hr = CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pfd)); HRESULT hr = CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pfd));
if (SUCCEEDED(hr)) if (SUCCEEDED(hr)) {
{
// Stuff needed for later // Stuff needed for later
const COMDLG_FILTERSPEC rgFExt[] = {{L"Audio Group Archive (*.*)", L"*.*"}}; const COMDLG_FILTERSPEC rgFExt[] = {{L"Audio Group Archive (*.*)", L"*.*"}};
@ -101,33 +97,28 @@ std::wstring openDB()
IFileDialogEvents* pfde = NULL; IFileDialogEvents* pfde = NULL;
hr = CDialogEventHandler_CreateInstance(IID_PPV_ARGS(&pfde)); hr = CDialogEventHandler_CreateInstance(IID_PPV_ARGS(&pfde));
if (SUCCEEDED(hr)) if (SUCCEEDED(hr)) {
{
// Hook the event handler // Hook the event handler
DWORD dwCookie; DWORD dwCookie;
hr = pfd->Advise(pfde, &dwCookie); hr = pfd->Advise(pfde, &dwCookie);
if (SUCCEEDED(hr)) if (SUCCEEDED(hr)) {
{
// Set options for the dialog // Set options for the dialog
DWORD dwFlags; DWORD dwFlags;
// Get options first so we do not override // Get options first so we do not override
hr = pfd->GetOptions(&dwFlags); hr = pfd->GetOptions(&dwFlags);
if (SUCCEEDED(hr)) if (SUCCEEDED(hr)) {
{
// Get shell items only // Get shell items only
hr = pfd->SetOptions(dwFlags | FOS_FORCEFILESYSTEM); hr = pfd->SetOptions(dwFlags | FOS_FORCEFILESYSTEM);
if (SUCCEEDED(hr)) if (SUCCEEDED(hr)) {
{
// Types of files to display (not default) // Types of files to display (not default)
hr = pfd->SetFileTypes(ARRAYSIZE(rgFExt), rgFExt); hr = pfd->SetFileTypes(ARRAYSIZE(rgFExt), rgFExt);
if (SUCCEEDED(hr)) if (SUCCEEDED(hr)) {
{
// Set default file type to display // Set default file type to display
// hr = pfd->SetDefaultExtension(L"sqlite"); // hr = pfd->SetDefaultExtension(L"sqlite");
@ -136,22 +127,19 @@ std::wstring openDB()
// Show dialog // Show dialog
hr = pfd->Show(NULL); hr = pfd->Show(NULL);
if (SUCCEEDED(hr)) if (SUCCEEDED(hr)) {
{
// Get the result once the user clicks on open // Get the result once the user clicks on open
IShellItem* result; IShellItem* result;
hr = pfd->GetResult(&result); hr = pfd->GetResult(&result);
if (SUCCEEDED(hr)) if (SUCCEEDED(hr)) {
{
// Print out the file name // Print out the file name
PWSTR fName = NULL; PWSTR fName = NULL;
hr = result->GetDisplayName(SIGDN_FILESYSPATH, &fName); hr = result->GetDisplayName(SIGDN_FILESYSPATH, &fName);
if (SUCCEEDED(hr)) if (SUCCEEDED(hr)) {
{
ret.assign(fName); ret.assign(fName);
CoTaskMemFree(fName); CoTaskMemFree(fName);
} }
@ -175,29 +163,24 @@ std::wstring openDB()
return ret; return ret;
} }
HRESULT CDialogEventHandler_CreateInstance(REFIID riid, void** ppv) HRESULT CDialogEventHandler_CreateInstance(REFIID riid, void** ppv) {
{
*ppv = NULL; *ppv = NULL;
CDialogEventHandler* pDialogEventHandler = new (std::nothrow) CDialogEventHandler(); CDialogEventHandler* pDialogEventHandler = new (std::nothrow) CDialogEventHandler();
HRESULT hr = pDialogEventHandler ? S_OK : E_OUTOFMEMORY; HRESULT hr = pDialogEventHandler ? S_OK : E_OUTOFMEMORY;
if (SUCCEEDED(hr)) if (SUCCEEDED(hr)) {
{
hr = pDialogEventHandler->QueryInterface(riid, ppv); hr = pDialogEventHandler->QueryInterface(riid, ppv);
pDialogEventHandler->Release(); pDialogEventHandler->Release();
} }
return hr; return hr;
} }
HRESULT CDialogEventHandler::OnTypeChange(IFileDialog* pfd) HRESULT CDialogEventHandler::OnTypeChange(IFileDialog* pfd) {
{
IFileSaveDialog* pfsd; IFileSaveDialog* pfsd;
HRESULT hr = pfd->QueryInterface(&pfsd); HRESULT hr = pfd->QueryInterface(&pfsd);
if (SUCCEEDED(hr)) if (SUCCEEDED(hr)) {
{
UINT uIndex; UINT uIndex;
hr = pfsd->GetFileTypeIndex(&uIndex); // index of current file-type hr = pfsd->GetFileTypeIndex(&uIndex); // index of current file-type
if (SUCCEEDED(hr)) if (SUCCEEDED(hr)) {
{
IPropertyDescriptionList* pdl = NULL; IPropertyDescriptionList* pdl = NULL;
} }
pfsd->Release(); pfsd->Release();
@ -208,16 +191,12 @@ HRESULT CDialogEventHandler::OnTypeChange(IFileDialog* pfd)
// IFileDialogControlEvents // IFileDialogControlEvents
// This method gets called when an dialog control item selection happens (radio-button selection. etc). // This method gets called when an dialog control item selection happens (radio-button selection. etc).
// For sample sake, let's react to this event by changing the dialog title. // For sample sake, let's react to this event by changing the dialog title.
HRESULT CDialogEventHandler::OnItemSelected(IFileDialogCustomize* pfdc, DWORD dwIDCtl, DWORD dwIDItem) HRESULT CDialogEventHandler::OnItemSelected(IFileDialogCustomize* pfdc, DWORD dwIDCtl, DWORD dwIDItem) {
{
IFileDialog* pfd = NULL; IFileDialog* pfd = NULL;
HRESULT hr = pfdc->QueryInterface(&pfd); HRESULT hr = pfdc->QueryInterface(&pfd);
if (SUCCEEDED(hr)) if (SUCCEEDED(hr)) {
{ if (dwIDCtl == CONTROL_RADIOBUTTONLIST) {
if (dwIDCtl == CONTROL_RADIOBUTTONLIST) switch (dwIDItem) {
{
switch (dwIDItem)
{
case CONTROL_RADIOBUTTON1: case CONTROL_RADIOBUTTON1:
hr = pfd->SetTitle(L"Longhorn Dialog"); hr = pfd->SetTitle(L"Longhorn Dialog");
break; break;

View File

@ -3,4 +3,3 @@
#include <string> #include <string>
std::wstring openDB(); std::wstring openDB();

View File

@ -6,8 +6,7 @@
#undef min #undef min
#undef max #undef max
struct VSTVoiceEngine : boo::BaseAudioVoiceEngine struct VSTVoiceEngine : boo::BaseAudioVoiceEngine {
{
std::vector<float> m_interleavedBuf; std::vector<float> m_interleavedBuf;
float** m_outputData = nullptr; float** m_outputData = nullptr;
size_t m_renderFrames = 0; size_t m_renderFrames = 0;
@ -19,15 +18,13 @@ struct VSTVoiceEngine : boo::BaseAudioVoiceEngine
boo::ReceiveFunctor* m_midiReceiver = nullptr; boo::ReceiveFunctor* m_midiReceiver = nullptr;
struct MIDIIn : public boo::IMIDIIn struct MIDIIn : public boo::IMIDIIn {
{
MIDIIn(bool virt, boo::ReceiveFunctor&& receiver) : IMIDIIn(virt, std::move(receiver)) {} MIDIIn(bool virt, boo::ReceiveFunctor&& receiver) : IMIDIIn(virt, std::move(receiver)) {}
std::string description() const { return "VST MIDI"; } std::string description() const { return "VST MIDI"; }
}; };
std::unique_ptr<boo::IMIDIIn> newVirtualMIDIIn(boo::ReceiveFunctor&& receiver) std::unique_ptr<boo::IMIDIIn> newVirtualMIDIIn(boo::ReceiveFunctor&& receiver) {
{
std::unique_ptr<boo::IMIDIIn> ret = std::make_unique<MIDIIn>(true, std::move(receiver)); std::unique_ptr<boo::IMIDIIn> ret = std::make_unique<MIDIIn>(true, std::move(receiver));
m_midiReceiver = &ret->m_receiver; m_midiReceiver = &ret->m_receiver;
return ret; return ret;
@ -45,8 +42,7 @@ struct VSTVoiceEngine : boo::BaseAudioVoiceEngine
bool useMIDILock() const { return false; } bool useMIDILock() const { return false; }
VSTVoiceEngine() VSTVoiceEngine() {
{
m_mixInfo.m_periodFrames = 1024; m_mixInfo.m_periodFrames = 1024;
m_mixInfo.m_sampleRate = 44100.0; m_mixInfo.m_sampleRate = 44100.0;
m_mixInfo.m_sampleFormat = SOXR_FLOAT32_I; m_mixInfo.m_sampleFormat = SOXR_FLOAT32_I;
@ -54,8 +50,7 @@ struct VSTVoiceEngine : boo::BaseAudioVoiceEngine
_buildAudioRenderClient(); _buildAudioRenderClient();
} }
void _buildAudioRenderClient() void _buildAudioRenderClient() {
{
m_mixInfo.m_channels = _getAvailableSet(); m_mixInfo.m_channels = _getAvailableSet();
unsigned chCount = ChannelCount(m_mixInfo.m_channels); unsigned chCount = ChannelCount(m_mixInfo.m_channels);
@ -73,8 +68,7 @@ struct VSTVoiceEngine : boo::BaseAudioVoiceEngine
chMapOut.m_channels[chMapOut.m_channelCount++] = boo::AudioChannel::Unknown; chMapOut.m_channels[chMapOut.m_channelCount++] = boo::AudioChannel::Unknown;
} }
void _rebuildAudioRenderClient(double sampleRate, size_t periodFrames) void _rebuildAudioRenderClient(double sampleRate, size_t periodFrames) {
{
m_mixInfo.m_periodFrames = periodFrames; m_mixInfo.m_periodFrames = periodFrames;
m_mixInfo.m_sampleRate = sampleRate; m_mixInfo.m_sampleRate = sampleRate;
_buildAudioRenderClient(); _buildAudioRenderClient();
@ -85,21 +79,16 @@ struct VSTVoiceEngine : boo::BaseAudioVoiceEngine
smx->_resetOutputSampleRate(); smx->_resetOutputSampleRate();
} }
void pumpAndMixVoices() void pumpAndMixVoices() {
{ for (size_t f = 0; f < m_renderFrames;) {
for (size_t f = 0; f < m_renderFrames;) if (m_curBufFrame == m_5msFrames) {
{
if (m_curBufFrame == m_5msFrames)
{
_pumpAndMixVoices(m_5msFrames, m_interleavedBuf.data()); _pumpAndMixVoices(m_5msFrames, m_interleavedBuf.data());
m_curBufFrame = 0; m_curBufFrame = 0;
} }
size_t remRenderFrames = std::min(m_renderFrames - f, m_5msFrames - m_curBufFrame); size_t remRenderFrames = std::min(m_renderFrames - f, m_5msFrames - m_curBufFrame);
if (remRenderFrames) if (remRenderFrames) {
{ for (size_t i = 0; i < 2; ++i) {
for (size_t i = 0; i < 2; ++i)
{
float* bufOut = m_outputData[i]; float* bufOut = m_outputData[i];
for (size_t lf = 0; lf < remRenderFrames; ++lf) for (size_t lf = 0; lf < remRenderFrames; ++lf)
bufOut[f + lf] = m_interleavedBuf[(m_curBufFrame + lf) * 2 + i]; bufOut[f + lf] = m_interleavedBuf[(m_curBufFrame + lf) * 2 + i];
@ -113,15 +102,13 @@ struct VSTVoiceEngine : boo::BaseAudioVoiceEngine
double getCurrentSampleRate() const { return m_mixInfo.m_sampleRate; } double getCurrentSampleRate() const { return m_mixInfo.m_sampleRate; }
}; };
namespace amuse namespace amuse {
{
#define kBackendID CCONST('a', 'm', 'u', 's') #define kBackendID CCONST('a', 'm', 'u', 's')
static logvisor::Module Log("amuse::AudioUnitBackend"); static logvisor::Module Log("amuse::AudioUnitBackend");
VSTBackend::VSTBackend(audioMasterCallback cb) : AudioEffectX(cb, 0, 0), m_filePresenter(*this), m_editor(*this) VSTBackend::VSTBackend(audioMasterCallback cb) : AudioEffectX(cb, 0, 0), m_filePresenter(*this), m_editor(*this) {
{
isSynth(); isSynth();
setUniqueID(kBackendID); setUniqueID(kBackendID);
setNumInputs(0); setNumInputs(0);
@ -135,8 +122,7 @@ VSTBackend::VSTBackend(audioMasterCallback cb) : AudioEffectX(cb, 0, 0), m_fileP
m_engine.emplace(*m_voxAlloc); m_engine.emplace(*m_voxAlloc);
WCHAR path[MAX_PATH]; WCHAR path[MAX_PATH];
if (SUCCEEDED(SHGetFolderPathW(NULL, CSIDL_APPDATA, NULL, 0, path))) if (SUCCEEDED(SHGetFolderPathW(NULL, CSIDL_APPDATA, NULL, 0, path))) {
{
m_userDir = std::wstring(path) + L"\\Amuse"; m_userDir = std::wstring(path) + L"\\Amuse";
CreateDirectory(m_userDir.c_str(), nullptr); CreateDirectory(m_userDir.c_str(), nullptr);
} }
@ -148,14 +134,12 @@ VSTBackend::~VSTBackend() { editor = nullptr; }
AEffEditor* VSTBackend::getEditor() { return &m_editor; } AEffEditor* VSTBackend::getEditor() { return &m_editor; }
VstInt32 VSTBackend::processEvents(VstEvents* events) VstInt32 VSTBackend::processEvents(VstEvents* events) {
{
std::unique_lock<std::mutex> lk(m_lock); std::unique_lock<std::mutex> lk(m_lock);
VSTVoiceEngine& engine = static_cast<VSTVoiceEngine&>(*m_booBackend); VSTVoiceEngine& engine = static_cast<VSTVoiceEngine&>(*m_booBackend);
/* Handle group load request */ /* Handle group load request */
if (m_curGroup != m_reqGroup) if (m_curGroup != m_reqGroup) {
{
m_curGroup = m_reqGroup; m_curGroup = m_reqGroup;
if (m_curSeq) if (m_curSeq)
m_curSeq->kill(); m_curSeq->kill();
@ -163,15 +147,11 @@ VstInt32 VSTBackend::processEvents(VstEvents* events)
m_editor.reselectPage(); m_editor.reselectPage();
} }
if (engine.m_midiReceiver) if (engine.m_midiReceiver) {
{ for (VstInt32 i = 0; i < events->numEvents; ++i) {
for (VstInt32 i = 0; i < events->numEvents; ++i)
{
VstMidiEvent* evt = reinterpret_cast<VstMidiEvent*>(events->events[i]); VstMidiEvent* evt = reinterpret_cast<VstMidiEvent*>(events->events[i]);
if (evt->type == kVstMidiType) if (evt->type == kVstMidiType) {
{ if (m_routeChannel != -1) {
if (m_routeChannel != -1)
{
evt->midiData[0] &= ~0xf; evt->midiData[0] &= ~0xf;
evt->midiData[0] |= m_routeChannel & 0xf; evt->midiData[0] |= m_routeChannel & 0xf;
} }
@ -185,8 +165,7 @@ VstInt32 VSTBackend::processEvents(VstEvents* events)
return 1; return 1;
} }
void VSTBackend::processReplacing(float**, float** outputs, VstInt32 sampleFrames) void VSTBackend::processReplacing(float**, float** outputs, VstInt32 sampleFrames) {
{
std::unique_lock<std::mutex> lk(m_lock); std::unique_lock<std::mutex> lk(m_lock);
VSTVoiceEngine& engine = static_cast<VSTVoiceEngine&>(*m_booBackend); VSTVoiceEngine& engine = static_cast<VSTVoiceEngine&>(*m_booBackend);
@ -198,8 +177,7 @@ void VSTBackend::processReplacing(float**, float** outputs, VstInt32 sampleFrame
m_curFrame += sampleFrames; m_curFrame += sampleFrames;
} }
VstInt32 VSTBackend::canDo(char* text) VstInt32 VSTBackend::canDo(char* text) {
{
VstInt32 returnCode = 0; VstInt32 returnCode = 0;
if (!strcmp(text, "receiveVstEvents")) if (!strcmp(text, "receiveVstEvents"))
@ -212,35 +190,29 @@ VstInt32 VSTBackend::canDo(char* text)
VstPlugCategory VSTBackend::getPlugCategory() { return kPlugCategSynth; } VstPlugCategory VSTBackend::getPlugCategory() { return kPlugCategSynth; }
bool VSTBackend::getEffectName(char* text) bool VSTBackend::getEffectName(char* text) {
{
strcpy(text, "Amuse"); strcpy(text, "Amuse");
return true; return true;
} }
bool VSTBackend::getProductString(char* text) bool VSTBackend::getProductString(char* text) {
{
strcpy(text, "Amuse"); strcpy(text, "Amuse");
return true; return true;
} }
bool VSTBackend::getVendorString(char* text) bool VSTBackend::getVendorString(char* text) {
{
strcpy(text, "AxioDL"); strcpy(text, "AxioDL");
return true; return true;
} }
bool VSTBackend::getProgramNameIndexed(VstInt32 category, VstInt32 index, char* text) bool VSTBackend::getProgramNameIndexed(VstInt32 category, VstInt32 index, char* text) {
{
strcpy(text, "Sampler"); strcpy(text, "Sampler");
return true; return true;
} }
bool VSTBackend::getOutputProperties(VstInt32 index, VstPinProperties* properties) bool VSTBackend::getOutputProperties(VstInt32 index, VstPinProperties* properties) {
{
bool returnCode = false; bool returnCode = false;
if (index == 0) if (index == 0) {
{
strcpy(properties->label, "Amuse Out"); strcpy(properties->label, "Amuse Out");
properties->flags = kVstPinIsStereo | kVstPinIsActive; properties->flags = kVstPinIsStereo | kVstPinIsActive;
properties->arrangementType = kSpeakerArrStereo; properties->arrangementType = kSpeakerArrStereo;
@ -251,37 +223,31 @@ bool VSTBackend::getOutputProperties(VstInt32 index, VstPinProperties* propertie
VstInt32 VSTBackend::getNumMidiInputChannels() { return 1; } VstInt32 VSTBackend::getNumMidiInputChannels() { return 1; }
void VSTBackend::setSampleRate(float sampleRate) void VSTBackend::setSampleRate(float sampleRate) {
{
AudioEffectX::setSampleRate(sampleRate); AudioEffectX::setSampleRate(sampleRate);
VSTVoiceEngine& engine = static_cast<VSTVoiceEngine&>(*m_booBackend); VSTVoiceEngine& engine = static_cast<VSTVoiceEngine&>(*m_booBackend);
engine._rebuildAudioRenderClient(sampleRate, engine.mixInfo().m_periodFrames); engine._rebuildAudioRenderClient(sampleRate, engine.mixInfo().m_periodFrames);
} }
void VSTBackend::setBlockSize(VstInt32 blockSize) void VSTBackend::setBlockSize(VstInt32 blockSize) {
{
AudioEffectX::setBlockSize(blockSize); AudioEffectX::setBlockSize(blockSize);
VSTVoiceEngine& engine = static_cast<VSTVoiceEngine&>(*m_booBackend); VSTVoiceEngine& engine = static_cast<VSTVoiceEngine&>(*m_booBackend);
engine._rebuildAudioRenderClient(engine.mixInfo().m_sampleRate, blockSize); engine._rebuildAudioRenderClient(engine.mixInfo().m_sampleRate, blockSize);
} }
void VSTBackend::loadGroupFile(int collectionIdx, int fileIdx) void VSTBackend::loadGroupFile(int collectionIdx, int fileIdx) {
{
std::unique_lock<std::mutex> lk(m_lock); std::unique_lock<std::mutex> lk(m_lock);
if (m_curSeq) if (m_curSeq) {
{
m_curSeq->kill(); m_curSeq->kill();
m_curSeq.reset(); m_curSeq.reset();
m_curGroup = -1; m_curGroup = -1;
m_reqGroup = -1; m_reqGroup = -1;
} }
if (collectionIdx < m_filePresenter.m_iteratorVec.size()) if (collectionIdx < m_filePresenter.m_iteratorVec.size()) {
{
AudioGroupFilePresenter::CollectionIterator& it = m_filePresenter.m_iteratorVec[collectionIdx]; AudioGroupFilePresenter::CollectionIterator& it = m_filePresenter.m_iteratorVec[collectionIdx];
if (fileIdx < it->second->m_iteratorVec.size()) if (fileIdx < it->second->m_iteratorVec.size()) {
{
AudioGroupCollection::GroupIterator& git = it->second->m_iteratorVec[fileIdx]; AudioGroupCollection::GroupIterator& git = it->second->m_iteratorVec[fileIdx];
if (m_curData) if (m_curData)
m_curData->removeFromEngine(*m_engine); m_curData->removeFromEngine(*m_engine);
@ -291,19 +257,16 @@ void VSTBackend::loadGroupFile(int collectionIdx, int fileIdx)
} }
} }
void VSTBackend::setGroup(int groupIdx, bool immediate) void VSTBackend::setGroup(int groupIdx, bool immediate) {
{
std::unique_lock<std::mutex> lk(m_lock); std::unique_lock<std::mutex> lk(m_lock);
if (!m_curData) if (!m_curData)
return; return;
if (groupIdx < m_curData->m_groupTokens.size()) if (groupIdx < m_curData->m_groupTokens.size()) {
{
const AudioGroupDataCollection::GroupToken& groupTok = m_curData->m_groupTokens[groupIdx]; const AudioGroupDataCollection::GroupToken& groupTok = m_curData->m_groupTokens[groupIdx];
m_reqGroup = groupTok.m_groupId; m_reqGroup = groupTok.m_groupId;
if (immediate) if (immediate) {
{
if (m_curSeq) if (m_curSeq)
m_curSeq->kill(); m_curSeq->kill();
m_curSeq = m_engine->seqPlay(groupTok.m_groupId, -1, nullptr); m_curSeq = m_engine->seqPlay(groupTok.m_groupId, -1, nullptr);
@ -311,36 +274,31 @@ void VSTBackend::setGroup(int groupIdx, bool immediate)
} }
} }
void VSTBackend::_setNormalProgram(int programNo) void VSTBackend::_setNormalProgram(int programNo) {
{
if (!m_curSeq) if (!m_curSeq)
return; return;
m_curSeq->setChanProgram(0, programNo); m_curSeq->setChanProgram(0, programNo);
m_routeChannel = 0; m_routeChannel = 0;
} }
void VSTBackend::setNormalProgram(int programNo) void VSTBackend::setNormalProgram(int programNo) {
{
std::unique_lock<std::mutex> lk(m_lock); std::unique_lock<std::mutex> lk(m_lock);
_setNormalProgram(programNo); _setNormalProgram(programNo);
} }
void VSTBackend::_setDrumProgram(int programNo) void VSTBackend::_setDrumProgram(int programNo) {
{
if (!m_curSeq) if (!m_curSeq)
return; return;
m_curSeq->setChanProgram(9, programNo); m_curSeq->setChanProgram(9, programNo);
m_routeChannel = 9; m_routeChannel = 9;
} }
void VSTBackend::setDrumProgram(int programNo) void VSTBackend::setDrumProgram(int programNo) {
{
std::unique_lock<std::mutex> lk(m_lock); std::unique_lock<std::mutex> lk(m_lock);
_setDrumProgram(programNo); _setDrumProgram(programNo);
} }
VstInt32 VSTBackend::getChunk(void** data, bool) VstInt32 VSTBackend::getChunk(void** data, bool) {
{
size_t allocSz = 14; size_t allocSz = 14;
if (m_curData) if (m_curData)
allocSz += (m_curData->m_path.size() - m_userDir.size() - 1) * 2; allocSz += (m_curData->m_path.size() - m_userDir.size() - 1) * 2;
@ -358,8 +316,7 @@ VstInt32 VSTBackend::getChunk(void** data, bool)
return allocSz; return allocSz;
} }
VstInt32 VSTBackend::setChunk(void* data, VstInt32 byteSize, bool) VstInt32 VSTBackend::setChunk(void* data, VstInt32 byteSize, bool) {
{
if (byteSize < 14) if (byteSize < 14)
return 0; return 0;
@ -370,13 +327,10 @@ VstInt32 VSTBackend::setChunk(void* data, VstInt32 byteSize, bool)
uint32_t pageIdx = intVals[2]; uint32_t pageIdx = intVals[2];
size_t colIdx = 0; size_t colIdx = 0;
for (auto& collection : m_filePresenter.m_audioGroupCollections) for (auto& collection : m_filePresenter.m_audioGroupCollections) {
{
size_t fileIdx = 0; size_t fileIdx = 0;
for (auto& file : collection.second->m_groups) for (auto& file : collection.second->m_groups) {
{ if (!file.second->m_path.compare(targetPath)) {
if (!file.second->m_path.compare(targetPath))
{
m_editor.selectCollection(LPARAM(0x80000000 | (colIdx << 16) | fileIdx)); m_editor.selectCollection(LPARAM(0x80000000 | (colIdx << 16) | fileIdx));
m_editor.selectGroup(groupIdx); m_editor.selectGroup(groupIdx);
m_editor.selectPage(pageIdx); m_editor.selectPage(pageIdx);
@ -389,6 +343,6 @@ VstInt32 VSTBackend::setChunk(void* data, VstInt32 byteSize, bool)
return 1; return 1;
} }
} } // namespace amuse
AudioEffect* createEffectInstance(audioMasterCallback audioMaster) { return new amuse::VSTBackend(audioMaster); } AudioEffect* createEffectInstance(audioMasterCallback audioMaster) { return new amuse::VSTBackend(audioMaster); }

View File

@ -12,20 +12,17 @@
#include "amuse/IBackendVoiceAllocator.hpp" #include "amuse/IBackendVoiceAllocator.hpp"
#include "AudioGroupFilePresenter.hpp" #include "AudioGroupFilePresenter.hpp"
namespace amuse namespace amuse {
{
class VSTBackend; class VSTBackend;
/** Backend voice allocator implementation for AudioUnit mixer */ /** Backend voice allocator implementation for AudioUnit mixer */
class VSTBackendVoiceAllocator : public BooBackendVoiceAllocator class VSTBackendVoiceAllocator : public BooBackendVoiceAllocator {
{
public: public:
VSTBackendVoiceAllocator(boo::IAudioVoiceEngine& booEngine) : BooBackendVoiceAllocator(booEngine) {} VSTBackendVoiceAllocator(boo::IAudioVoiceEngine& booEngine) : BooBackendVoiceAllocator(booEngine) {}
}; };
/** Actual plugin implementation class */ /** Actual plugin implementation class */
class VSTBackend : public AudioEffectX class VSTBackend : public AudioEffectX {
{
std::mutex m_lock; std::mutex m_lock;
std::unique_ptr<boo::IAudioVoiceEngine> m_booBackend; std::unique_ptr<boo::IAudioVoiceEngine> m_booBackend;
std::experimental::optional<amuse::VSTBackendVoiceAllocator> m_voxAlloc; std::experimental::optional<amuse::VSTBackendVoiceAllocator> m_voxAlloc;
@ -71,5 +68,4 @@ public:
VstInt32 getChunk(void** data, bool isPreset); VstInt32 getChunk(void** data, bool isPreset);
VstInt32 setChunk(void* data, VstInt32 byteSize, bool isPreset); VstInt32 setChunk(void* data, VstInt32 byteSize, bool isPreset);
}; };
} } // namespace amuse

View File

@ -13,31 +13,24 @@ extern void* hInstance;
static WNDPROC OriginalListViewProc = 0; static WNDPROC OriginalListViewProc = 0;
static HBRUSH gGreyBorderBrush; static HBRUSH gGreyBorderBrush;
namespace amuse namespace amuse {
{
VSTEditor::VSTEditor(VSTBackend& backend) : AEffEditor(&backend), m_backend(backend) {} VSTEditor::VSTEditor(VSTBackend& backend) : AEffEditor(&backend), m_backend(backend) {}
bool VSTEditor::getRect(ERect** rect) bool VSTEditor::getRect(ERect** rect) {
{
*rect = &m_windowRect; *rect = &m_windowRect;
return true; return true;
} }
LRESULT CALLBACK VSTEditor::WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) LRESULT CALLBACK VSTEditor::WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
{
VSTEditor& editor = *reinterpret_cast<VSTEditor*>(GetWindowLongPtrW(hwnd, 0)); VSTEditor& editor = *reinterpret_cast<VSTEditor*>(GetWindowLongPtrW(hwnd, 0));
switch (uMsg) switch (uMsg) {
{ case WM_NOTIFY: {
case WM_NOTIFY:
{
NMHDR& itemAct = *reinterpret_cast<LPNMHDR>(lParam); NMHDR& itemAct = *reinterpret_cast<LPNMHDR>(lParam);
switch (itemAct.code) switch (itemAct.code) {
{
case HDN_BEGINTRACK: case HDN_BEGINTRACK:
return TRUE; return TRUE;
case NM_CLICK: case NM_CLICK: {
{
NMITEMACTIVATE& itemAct = *reinterpret_cast<LPNMITEMACTIVATE>(lParam); NMITEMACTIVATE& itemAct = *reinterpret_cast<LPNMITEMACTIVATE>(lParam);
if (itemAct.hdr.hwndFrom == editor.m_groupListView) if (itemAct.hdr.hwndFrom == editor.m_groupListView)
editor.selectGroup(itemAct.iItem); editor.selectGroup(itemAct.iItem);
@ -45,8 +38,7 @@ LRESULT CALLBACK VSTEditor::WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPAR
editor.selectPage(itemAct.iItem); editor.selectPage(itemAct.iItem);
return 0; return 0;
} }
case TVN_SELCHANGED: case TVN_SELCHANGED: {
{
if (editor.m_deferredCollectionSel) if (editor.m_deferredCollectionSel)
return 0; return 0;
NMTREEVIEW& itemAct = *reinterpret_cast<LPNMTREEVIEW>(lParam); NMTREEVIEW& itemAct = *reinterpret_cast<LPNMTREEVIEW>(lParam);
@ -54,24 +46,18 @@ LRESULT CALLBACK VSTEditor::WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPAR
editor.selectCollection(itemAct.itemNew.lParam); editor.selectCollection(itemAct.itemNew.lParam);
return 0; return 0;
} }
case TVN_GETDISPINFO: case TVN_GETDISPINFO: {
{
NMTVDISPINFO& treeDispInfo = *reinterpret_cast<LPNMTVDISPINFO>(lParam); NMTVDISPINFO& treeDispInfo = *reinterpret_cast<LPNMTVDISPINFO>(lParam);
if (treeDispInfo.item.mask & TVIF_CHILDREN) if (treeDispInfo.item.mask & TVIF_CHILDREN) {}
{
}
return 0; return 0;
} }
default: default:
return DefWindowProc(hwnd, uMsg, wParam, lParam); return DefWindowProc(hwnd, uMsg, wParam, lParam);
} }
} }
case WM_COMMAND: case WM_COMMAND: {
{ switch (HIWORD(wParam)) {
switch (HIWORD(wParam)) case BN_CLICKED: {
{
case BN_CLICKED:
{
HWND button = HWND(lParam); HWND button = HWND(lParam);
if (button == editor.m_collectionAdd) if (button == editor.m_collectionAdd)
editor.addAction(); editor.addAction();
@ -83,8 +69,7 @@ LRESULT CALLBACK VSTEditor::WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPAR
return DefWindowProc(hwnd, uMsg, wParam, lParam); return DefWindowProc(hwnd, uMsg, wParam, lParam);
} }
} }
case WM_ERASEBKGND: case WM_ERASEBKGND: {
{
RECT rect; RECT rect;
GetClientRect(hwnd, &rect); GetClientRect(hwnd, &rect);
FillRect(HDC(wParam), &rect, gGreyBorderBrush); FillRect(HDC(wParam), &rect, gGreyBorderBrush);
@ -95,16 +80,13 @@ LRESULT CALLBACK VSTEditor::WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPAR
} }
} }
LRESULT CALLBACK VSTEditor::ColHeaderWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) LRESULT CALLBACK VSTEditor::ColHeaderWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
{ switch (uMsg) {
switch (uMsg)
{
case WM_SETCURSOR: case WM_SETCURSOR:
return TRUE; return TRUE;
case WM_LBUTTONDBLCLK: case WM_LBUTTONDBLCLK:
return 0; return 0;
case WM_PAINT: case WM_PAINT: {
{
PAINTSTRUCT ps; PAINTSTRUCT ps;
HDC dc = BeginPaint(hwnd, &ps); HDC dc = BeginPaint(hwnd, &ps);
RECT rect; RECT rect;
@ -131,10 +113,8 @@ LRESULT CALLBACK VSTEditor::ColHeaderWindowProc(HWND hwnd, UINT uMsg, WPARAM wPa
return CallWindowProc(OriginalListViewProc, hwnd, uMsg, wParam, lParam); return CallWindowProc(OriginalListViewProc, hwnd, uMsg, wParam, lParam);
} }
void VSTEditor::_reselectColumns() void VSTEditor::_reselectColumns() {
{ if (m_deferredCollectionSel) {
if (m_deferredCollectionSel)
{
TreeView_SelectItem(m_collectionTree, m_deferredCollectionSel); TreeView_SelectItem(m_collectionTree, m_deferredCollectionSel);
m_deferredCollectionSel = 0; m_deferredCollectionSel = 0;
} }
@ -144,8 +124,7 @@ void VSTEditor::_reselectColumns()
ListView_SetItemState(m_pageListView, m_selPageIdx, LVIS_FOCUSED | LVIS_SELECTED, 0xf); ListView_SetItemState(m_pageListView, m_selPageIdx, LVIS_FOCUSED | LVIS_SELECTED, 0xf);
} }
bool VSTEditor::open(void* ptr) bool VSTEditor::open(void* ptr) {
{
AEffEditor::open(ptr); AEffEditor::open(ptr);
HWND hostView = HWND(ptr); HWND hostView = HWND(ptr);
gGreyBorderBrush = CreateSolidBrush(RGB(100, 100, 100)); gGreyBorderBrush = CreateSolidBrush(RGB(100, 100, 100));
@ -182,8 +161,8 @@ bool VSTEditor::open(void* ptr)
m_collectionTree = m_collectionTree =
CreateWindowW(WC_TREEVIEW, L"", CreateWindowW(WC_TREEVIEW, L"",
WS_CHILD | WS_CLIPSIBLINGS | TVS_SHOWSELALWAYS | TVS_HASLINES | TVS_LINESATROOT | TVS_HASBUTTONS, WS_CHILD | WS_CLIPSIBLINGS | TVS_SHOWSELALWAYS | TVS_HASLINES | TVS_LINESATROOT | TVS_HASBUTTONS, 1,
1, 25, 199, m_windowRect.bottom - m_windowRect.top - 26, m_rootView, nullptr, nullptr, nullptr); 25, 199, m_windowRect.bottom - m_windowRect.top - 26, m_rootView, nullptr, nullptr, nullptr);
TreeView_SetBkColor(m_collectionTree, RGB(64, 64, 64)); TreeView_SetBkColor(m_collectionTree, RGB(64, 64, 64));
TreeView_SetTextColor(m_collectionTree, RGB(255, 255, 255)); TreeView_SetTextColor(m_collectionTree, RGB(255, 255, 255));
HTREEITEM rootItemA = TreeView_InsertItem(m_collectionTree, &treeItem); HTREEITEM rootItemA = TreeView_InsertItem(m_collectionTree, &treeItem);
@ -264,14 +243,12 @@ bool VSTEditor::open(void* ptr)
return true; return true;
} }
void VSTEditor::close() void VSTEditor::close() {
{
AEffEditor::close(); AEffEditor::close();
UnregisterClassW(L"VSTNotify", HINSTANCE(hInstance)); UnregisterClassW(L"VSTNotify", HINSTANCE(hInstance));
} }
void VSTEditor::update() void VSTEditor::update() {
{
m_backend.getFilePresenter().populateCollectionColumn(*this); m_backend.getFilePresenter().populateCollectionColumn(*this);
m_backend.loadGroupFile(m_selCollectionIdx, m_selFileIdx); m_backend.loadGroupFile(m_selCollectionIdx, m_selFileIdx);
m_backend.getFilePresenter().populateGroupColumn(*this, m_selCollectionIdx, m_selFileIdx); m_backend.getFilePresenter().populateGroupColumn(*this, m_selCollectionIdx, m_selFileIdx);
@ -281,16 +258,13 @@ void VSTEditor::update()
_reselectColumns(); _reselectColumns();
} }
void VSTEditor::addAction() void VSTEditor::addAction() {
{
std::wstring path = openDB(); std::wstring path = openDB();
if (path.size()) if (path.size()) {
{
amuse::ContainerRegistry::Type containerType; amuse::ContainerRegistry::Type containerType;
std::vector<std::pair<std::wstring, amuse::IntrusiveAudioGroupData>> data = std::vector<std::pair<std::wstring, amuse::IntrusiveAudioGroupData>> data =
amuse::ContainerRegistry::LoadContainer(path.c_str(), containerType); amuse::ContainerRegistry::LoadContainer(path.c_str(), containerType);
if (data.empty()) if (data.empty()) {
{
wchar_t msg[512]; wchar_t msg[512];
SNPrintf(msg, 512, L"Unable to load Audio Groups from %s", path.c_str()); SNPrintf(msg, 512, L"Unable to load Audio Groups from %s", path.c_str());
MessageBoxW(nullptr, msg, L"Invalid Data File", MB_OK | MB_ICONERROR); MessageBoxW(nullptr, msg, L"Invalid Data File", MB_OK | MB_ICONERROR);
@ -298,8 +272,7 @@ void VSTEditor::addAction()
} }
SystemString name(amuse::ContainerRegistry::TypeToName(containerType)); SystemString name(amuse::ContainerRegistry::TypeToName(containerType));
if (containerType == amuse::ContainerRegistry::Type::Raw4) if (containerType == amuse::ContainerRegistry::Type::Raw4) {
{
size_t dotpos = path.rfind(L'.'); size_t dotpos = path.rfind(L'.');
if (dotpos != std::string::npos) if (dotpos != std::string::npos)
name.assign(path.cbegin(), path.cbegin() + dotpos); name.assign(path.cbegin(), path.cbegin() + dotpos);
@ -318,8 +291,7 @@ void VSTEditor::addAction()
} }
} }
void VSTEditor::removeAction() void VSTEditor::removeAction() {
{
if (m_selCollectionIdx == -1) if (m_selCollectionIdx == -1)
return; return;
m_backend.getFilePresenter().removeCollection(m_selCollectionIdx); m_backend.getFilePresenter().removeCollection(m_selCollectionIdx);
@ -332,10 +304,8 @@ void VSTEditor::removeAction()
Button_Enable(m_collectionRemove, FALSE); Button_Enable(m_collectionRemove, FALSE);
} }
void VSTEditor::selectCollection(LPARAM idx) void VSTEditor::selectCollection(LPARAM idx) {
{ if (0x80000000 & idx) {
if (0x80000000 & idx)
{
/* Sub-item */ /* Sub-item */
int rootIdx = (idx >> 16) & 0x7fff; int rootIdx = (idx >> 16) & 0x7fff;
int subIdx = idx & 0xffff; int subIdx = idx & 0xffff;
@ -344,9 +314,7 @@ void VSTEditor::selectCollection(LPARAM idx)
m_selFileIdx = subIdx; m_selFileIdx = subIdx;
m_backend.loadGroupFile(m_selCollectionIdx, m_selFileIdx); m_backend.loadGroupFile(m_selCollectionIdx, m_selFileIdx);
m_backend.getFilePresenter().populateGroupColumn(*this, rootIdx, subIdx); m_backend.getFilePresenter().populateGroupColumn(*this, rootIdx, subIdx);
} } else {
else
{
/* Root-item */ /* Root-item */
int rootIdx = (idx >> 16) & 0x7fff; int rootIdx = (idx >> 16) & 0x7fff;
m_selCollectionIdx = rootIdx; m_selCollectionIdx = rootIdx;
@ -354,16 +322,14 @@ void VSTEditor::selectCollection(LPARAM idx)
} }
} }
void VSTEditor::selectGroup(int idx) void VSTEditor::selectGroup(int idx) {
{
m_selGroupIdx = idx; m_selGroupIdx = idx;
m_backend.setGroup(m_selGroupIdx, false); m_backend.setGroup(m_selGroupIdx, false);
m_backend.getFilePresenter().populatePageColumn(*this, m_selCollectionIdx, m_selFileIdx, m_selGroupIdx); m_backend.getFilePresenter().populatePageColumn(*this, m_selCollectionIdx, m_selFileIdx, m_selGroupIdx);
m_lastLParam = -1; m_lastLParam = -1;
} }
void VSTEditor::selectPage(int idx) void VSTEditor::selectPage(int idx) {
{
m_selPageIdx = idx; m_selPageIdx = idx;
LV_ITEM item = {}; LV_ITEM item = {};
item.mask = LVIF_PARAM; item.mask = LVIF_PARAM;
@ -376,10 +342,8 @@ void VSTEditor::selectPage(int idx)
selectNormalPage(item.lParam & 0x7fffffff); selectNormalPage(item.lParam & 0x7fffffff);
} }
void VSTEditor::reselectPage() void VSTEditor::reselectPage() {
{ if (m_lastLParam != -1) {
if (m_lastLParam != -1)
{
if (m_lastLParam & 0x80000000) if (m_lastLParam & 0x80000000)
m_backend._setDrumProgram(m_lastLParam & 0x7fffffff); m_backend._setDrumProgram(m_lastLParam & 0x7fffffff);
else else
@ -390,4 +354,4 @@ void VSTEditor::reselectPage()
void VSTEditor::selectNormalPage(int idx) { m_backend.setNormalProgram(idx); } void VSTEditor::selectNormalPage(int idx) { m_backend.setNormalProgram(idx); }
void VSTEditor::selectDrumPage(int idx) { m_backend.setDrumProgram(idx); } void VSTEditor::selectDrumPage(int idx) { m_backend.setDrumProgram(idx); }
} } // namespace amuse

View File

@ -6,13 +6,11 @@
#include "aeffeditor.h" #include "aeffeditor.h"
namespace amuse namespace amuse {
{
class VSTBackend; class VSTBackend;
/** Editor UI class */ /** Editor UI class */
class VSTEditor : public AEffEditor class VSTEditor : public AEffEditor {
{
friend class VSTBackend; friend class VSTBackend;
friend class AudioGroupFilePresenter; friend class AudioGroupFilePresenter;
friend struct AudioGroupCollection; friend struct AudioGroupCollection;
@ -58,5 +56,4 @@ public:
void selectNormalPage(int idx); void selectNormalPage(int idx);
void selectDrumPage(int idx); void selectDrumPage(int idx);
}; };
} } // namespace amuse

View File

@ -7,17 +7,10 @@
static logvisor::Module Log("amuseconv"); static logvisor::Module Log("amuseconv");
enum ConvType enum ConvType { ConvN64, ConvGCN, ConvPC };
{
ConvN64,
ConvGCN,
ConvPC
};
static void ReportConvType(ConvType tp) static void ReportConvType(ConvType tp) {
{ switch (tp) {
switch (tp)
{
case ConvN64: case ConvN64:
Log.report(logvisor::Info, _SYS_STR("using N64 format")); Log.report(logvisor::Info, _SYS_STR("using N64 format"));
break; break;
@ -31,25 +24,19 @@ static void ReportConvType(ConvType tp)
} }
} }
static bool BuildAudioGroup(amuse::SystemStringView groupBase, amuse::SystemStringView targetPath) static bool BuildAudioGroup(amuse::SystemStringView groupBase, amuse::SystemStringView targetPath) { return true; }
{
return true;
}
static bool ExtractAudioGroup(amuse::SystemStringView inPath, amuse::SystemStringView targetPath) static bool ExtractAudioGroup(amuse::SystemStringView inPath, amuse::SystemStringView targetPath) {
{
amuse::ContainerRegistry::Type type; amuse::ContainerRegistry::Type type;
auto groups = amuse::ContainerRegistry::LoadContainer(inPath.data(), type); auto groups = amuse::ContainerRegistry::LoadContainer(inPath.data(), type);
if (groups.size()) if (groups.size()) {
{
Log.report(logvisor::Info, _SYS_STR("Found '%s'"), amuse::ContainerRegistry::TypeToName(type)); Log.report(logvisor::Info, _SYS_STR("Found '%s'"), amuse::ContainerRegistry::TypeToName(type));
amuse::Mkdir(targetPath.data(), 0755); amuse::Mkdir(targetPath.data(), 0755);
Log.report(logvisor::Info, _SYS_STR("Established directory at %s"), targetPath.data()); Log.report(logvisor::Info, _SYS_STR("Established directory at %s"), targetPath.data());
for (auto& group : groups) for (auto& group : groups) {
{
Log.report(logvisor::Info, _SYS_STR("Extracting %s"), group.first.c_str()); Log.report(logvisor::Info, _SYS_STR("Extracting %s"), group.first.c_str());
} }
} }
@ -57,10 +44,8 @@ static bool ExtractAudioGroup(amuse::SystemStringView inPath, amuse::SystemStrin
auto songs = amuse::ContainerRegistry::LoadSongs(inPath.data()); auto songs = amuse::ContainerRegistry::LoadSongs(inPath.data());
amuse::SystemString songsDir = amuse::SystemString(targetPath) + _SYS_STR("/midifiles"); amuse::SystemString songsDir = amuse::SystemString(targetPath) + _SYS_STR("/midifiles");
bool madeDir = false; bool madeDir = false;
for (auto& pair : songs) for (auto& pair : songs) {
{ if (!madeDir) {
if (!madeDir)
{
amuse::Mkdir(targetPath.data(), 0755); amuse::Mkdir(targetPath.data(), 0755);
amuse::Mkdir(songsDir.c_str(), 0755); amuse::Mkdir(songsDir.c_str(), 0755);
madeDir = true; madeDir = true;
@ -68,13 +53,11 @@ static bool ExtractAudioGroup(amuse::SystemStringView inPath, amuse::SystemStrin
amuse::SystemString songPath = songsDir + _SYS_STR('/') + pair.first + _SYS_STR(".mid"); amuse::SystemString songPath = songsDir + _SYS_STR('/') + pair.first + _SYS_STR(".mid");
FILE* fp = amuse::FOpen(songPath.c_str(), _SYS_STR("wb")); FILE* fp = amuse::FOpen(songPath.c_str(), _SYS_STR("wb"));
if (fp) if (fp) {
{
Log.report(logvisor::Info, _SYS_STR("Extracting %s"), pair.first.c_str()); Log.report(logvisor::Info, _SYS_STR("Extracting %s"), pair.first.c_str());
int extractedVersion; int extractedVersion;
bool isBig; bool isBig;
std::vector<uint8_t> mid = std::vector<uint8_t> mid = amuse::SongConverter::SongToMIDI(pair.second.m_data.get(), extractedVersion, isBig);
amuse::SongConverter::SongToMIDI(pair.second.m_data.get(), extractedVersion, isBig);
fwrite(mid.data(), 1, mid.size(), fp); fwrite(mid.data(), 1, mid.size(), fp);
fclose(fp); fclose(fp);
} }
@ -83,8 +66,7 @@ static bool ExtractAudioGroup(amuse::SystemStringView inPath, amuse::SystemStrin
return true; return true;
} }
static bool BuildSNG(amuse::SystemStringView inPath, amuse::SystemStringView targetPath, int version, bool big) static bool BuildSNG(amuse::SystemStringView inPath, amuse::SystemStringView targetPath, int version, bool big) {
{
FILE* fp = amuse::FOpen(inPath.data(), _SYS_STR("rb")); FILE* fp = amuse::FOpen(inPath.data(), _SYS_STR("rb"));
if (!fp) if (!fp)
return false; return false;
@ -107,8 +89,7 @@ static bool BuildSNG(amuse::SystemStringView inPath, amuse::SystemStringView tar
return true; return true;
} }
static bool ExtractSNG(amuse::SystemStringView inPath, amuse::SystemStringView targetPath) static bool ExtractSNG(amuse::SystemStringView inPath, amuse::SystemStringView targetPath) {
{
FILE* fp = amuse::FOpen(inPath.data(), _SYS_STR("rb")); FILE* fp = amuse::FOpen(inPath.data(), _SYS_STR("rb"));
if (!fp) if (!fp)
return false; return false;
@ -141,23 +122,20 @@ int main(int argc, const amuse::SystemChar** argv)
{ {
logvisor::RegisterConsoleLogger(); logvisor::RegisterConsoleLogger();
if (argc < 3) if (argc < 3) {
{
printf("Usage: amuseconv <in-file> <out-file> [n64|pc|gcn]\n"); printf("Usage: amuseconv <in-file> <out-file> [n64|pc|gcn]\n");
return 0; return 0;
} }
ConvType type = ConvGCN; ConvType type = ConvGCN;
if (argc >= 4) if (argc >= 4) {
{
if (!amuse::CompareCaseInsensitive(argv[3], _SYS_STR("n64"))) if (!amuse::CompareCaseInsensitive(argv[3], _SYS_STR("n64")))
type = ConvN64; type = ConvN64;
else if (!amuse::CompareCaseInsensitive(argv[3], _SYS_STR("gcn"))) else if (!amuse::CompareCaseInsensitive(argv[3], _SYS_STR("gcn")))
type = ConvGCN; type = ConvGCN;
else if (!amuse::CompareCaseInsensitive(argv[3], _SYS_STR("pc"))) else if (!amuse::CompareCaseInsensitive(argv[3], _SYS_STR("pc")))
type = ConvPC; type = ConvPC;
else else {
{
Log.report(logvisor::Error, _SYS_STR("unrecognized format: %s"), argv[3]); Log.report(logvisor::Error, _SYS_STR("unrecognized format: %s"), argv[3]);
return 1; return 1;
} }
@ -165,39 +143,30 @@ int main(int argc, const amuse::SystemChar** argv)
bool good = false; bool good = false;
FILE* fin = amuse::FOpen(argv[1], _SYS_STR("rb")); FILE* fin = amuse::FOpen(argv[1], _SYS_STR("rb"));
if (fin) if (fin) {
{
fclose(fin); fclose(fin);
amuse::SystemString barePath(argv[1]); amuse::SystemString barePath(argv[1]);
size_t dotPos = barePath.rfind(_SYS_STR('.')); size_t dotPos = barePath.rfind(_SYS_STR('.'));
const amuse::SystemChar* dot = barePath.c_str() + dotPos; const amuse::SystemChar* dot = barePath.c_str() + dotPos;
if (dotPos != amuse::SystemString::npos) if (dotPos != amuse::SystemString::npos) {
{ if (!amuse::CompareCaseInsensitive(dot, _SYS_STR(".mid")) ||
if (!amuse::CompareCaseInsensitive(dot, _SYS_STR(".mid")) || !amuse::CompareCaseInsensitive(dot, _SYS_STR(".midi"))) !amuse::CompareCaseInsensitive(dot, _SYS_STR(".midi"))) {
{
ReportConvType(type); ReportConvType(type);
good = BuildSNG(barePath, argv[2], 1, true); good = BuildSNG(barePath, argv[2], 1, true);
} } else if (!amuse::CompareCaseInsensitive(dot, _SYS_STR(".son")) ||
else if (!amuse::CompareCaseInsensitive(dot, _SYS_STR(".son")) || !amuse::CompareCaseInsensitive(dot, _SYS_STR(".sng"))) !amuse::CompareCaseInsensitive(dot, _SYS_STR(".sng"))) {
{
good = ExtractSNG(argv[1], argv[2]); good = ExtractSNG(argv[1], argv[2]);
} } else {
else
{
good = ExtractAudioGroup(argv[1], argv[2]); good = ExtractAudioGroup(argv[1], argv[2]);
} }
} }
} } else {
else
{
amuse::Sstat theStat; amuse::Sstat theStat;
if (!amuse::Stat(argv[1], &theStat) && S_ISDIR(theStat.st_mode)) if (!amuse::Stat(argv[1], &theStat) && S_ISDIR(theStat.st_mode)) {
{
amuse::SystemString projectPath(argv[1]); amuse::SystemString projectPath(argv[1]);
projectPath += _SYS_STR("/project.yaml"); projectPath += _SYS_STR("/project.yaml");
fin = amuse::FOpen(projectPath.c_str(), _SYS_STR("rb")); fin = amuse::FOpen(projectPath.c_str(), _SYS_STR("rb"));
if (fin) if (fin) {
{
fclose(fin); fclose(fin);
ReportConvType(type); ReportConvType(type);
good = BuildAudioGroup(argv[1], argv[2]); good = BuildAudioGroup(argv[1], argv[2]);
@ -205,8 +174,7 @@ int main(int argc, const amuse::SystemChar** argv)
} }
} }
if (!good) if (!good) {
{
Log.report(logvisor::Error, _SYS_STR("unable to convert %s to %s"), argv[1], argv[2]); Log.report(logvisor::Error, _SYS_STR("unable to convert %s to %s"), argv[1], argv[2]);
return 1; return 1;
} }

View File

@ -12,8 +12,7 @@ static logvisor::Module Log("amuseplay");
__attribute__((__format__(__printf__, 3, 4))) __attribute__((__format__(__printf__, 3, 4)))
#endif #endif
static inline void static inline void
SNPrintf(boo::SystemChar* str, size_t maxlen, const boo::SystemChar* format, ...) SNPrintf(boo::SystemChar* str, size_t maxlen, const boo::SystemChar* format, ...) {
{
va_list va; va_list va;
va_start(va, format); va_start(va, format);
#if _WIN32 #if _WIN32
@ -26,8 +25,7 @@ SNPrintf(boo::SystemChar* str, size_t maxlen, const boo::SystemChar* format, ...
struct AppCallback; struct AppCallback;
struct EventCallback : boo::IWindowCallback struct EventCallback : boo::IWindowCallback {
{
AppCallback& m_app; AppCallback& m_app;
bool m_tracking = false; bool m_tracking = false;
@ -45,8 +43,7 @@ public:
EventCallback(AppCallback& app) : m_app(app) {} EventCallback(AppCallback& app) : m_app(app) {}
}; };
struct AppCallback : boo::IApplicationCallback struct AppCallback : boo::IApplicationCallback {
{
int m_argc; int m_argc;
const boo::SystemChar** m_argv; const boo::SystemChar** m_argv;
@ -94,12 +91,10 @@ struct AppCallback : boo::IApplicationCallback
std::shared_ptr<amuse::Listener> m_listener; std::shared_ptr<amuse::Listener> m_listener;
#endif #endif
void UpdateSongDisplay() void UpdateSongDisplay() {
{
size_t voxCount = 0; size_t voxCount = 0;
int program = 0; int program = 0;
if (m_seq) if (m_seq) {
{
voxCount = m_seq->getVoiceCount(); voxCount = m_seq->getVoiceCount();
program = m_seq->getChanProgram(m_chanId); program = m_seq->getChanProgram(m_chanId);
} }
@ -110,11 +105,9 @@ struct AppCallback : boo::IApplicationCallback
fflush(stdout); fflush(stdout);
} }
void SelectSong(int setupId) void SelectSong(int setupId) {
{
m_setupId = setupId; m_setupId = setupId;
if (m_seq) if (m_seq) {
{
m_seq->stopSong(0.f, true); m_seq->stopSong(0.f, true);
m_seq->kill(); m_seq->kill();
} }
@ -127,8 +120,7 @@ struct AppCallback : boo::IApplicationCallback
UpdateSongDisplay(); UpdateSongDisplay();
} }
void SongLoop(const amuse::SongGroupIndex& index) void SongLoop(const amuse::SongGroupIndex& index) {
{
printf( printf(
"░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░\n" "░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░\n"
"░░░ ████ ████ ┃ ████ ████ ████ ┃ ████ ████ ░░░\n" "░░░ ████ ████ ┃ ████ ████ ████ ┃ ████ ████ ░░░\n"
@ -144,12 +136,10 @@ struct AppCallback : boo::IApplicationCallback
std::map<amuse::SongId, std::array<amuse::SongGroupIndex::MIDISetup, 16>> sortEntries(index.m_midiSetups.cbegin(), std::map<amuse::SongId, std::array<amuse::SongGroupIndex::MIDISetup, 16>> sortEntries(index.m_midiSetups.cbegin(),
index.m_midiSetups.cend()); index.m_midiSetups.cend());
auto setupIt = sortEntries.cbegin(); auto setupIt = sortEntries.cbegin();
if (setupIt != sortEntries.cend()) if (setupIt != sortEntries.cend()) {
{
if (m_setupId == -1) if (m_setupId == -1)
SelectSong(setupIt->first); SelectSong(setupIt->first);
else else {
{
while (setupIt != sortEntries.cend() && setupIt->first != m_setupId) while (setupIt != sortEntries.cend() && setupIt->first != m_setupId)
++setupIt; ++setupIt;
if (setupIt == sortEntries.cend()) if (setupIt == sortEntries.cend())
@ -158,48 +148,39 @@ struct AppCallback : boo::IApplicationCallback
} }
} }
while (m_running) while (m_running) {
{
m_events.dispatchEvents(); m_events.dispatchEvents();
if (m_wantsNext) if (m_wantsNext) {
{
m_wantsNext = false; m_wantsNext = false;
auto nextIt = setupIt; auto nextIt = setupIt;
++nextIt; ++nextIt;
if (nextIt != sortEntries.cend()) if (nextIt != sortEntries.cend()) {
{
++setupIt; ++setupIt;
SelectSong(setupIt->first); SelectSong(setupIt->first);
m_updateDisp = false; m_updateDisp = false;
} }
} }
if (m_wantsPrev) if (m_wantsPrev) {
{
m_wantsPrev = false; m_wantsPrev = false;
if (setupIt != sortEntries.cbegin()) if (setupIt != sortEntries.cbegin()) {
{
--setupIt; --setupIt;
SelectSong(setupIt->first); SelectSong(setupIt->first);
m_updateDisp = false; m_updateDisp = false;
} }
} }
if (m_seq && m_panicCount) if (m_seq && m_panicCount) {
{ if (m_panicCount > 1) {
if (m_panicCount > 1)
{
m_seq->allOff(true); m_seq->allOff(true);
m_panicCount = 0; m_panicCount = 0;
} } else
else
m_seq->allOff(false); m_seq->allOff(false);
m_updateDisp = true; m_updateDisp = true;
} }
if (m_updateDisp) if (m_updateDisp) {
{
m_updateDisp = false; m_updateDisp = false;
UpdateSongDisplay(); UpdateSongDisplay();
} }
@ -208,26 +189,21 @@ struct AppCallback : boo::IApplicationCallback
size_t voxCount; size_t voxCount;
int8_t progId; int8_t progId;
if (m_seq) if (m_seq) {
{
voxCount = m_seq->getVoiceCount(); voxCount = m_seq->getVoiceCount();
progId = m_seq->getChanProgram(m_chanId); progId = m_seq->getChanProgram(m_chanId);
} } else {
else
{
voxCount = 0; voxCount = 0;
progId = -1; progId = -1;
} }
if (m_lastVoxCount != voxCount || m_lastChanProg != progId) if (m_lastVoxCount != voxCount || m_lastChanProg != progId) {
{
m_lastVoxCount = voxCount; m_lastVoxCount = voxCount;
m_lastChanProg = progId; m_lastChanProg = progId;
UpdateSongDisplay(); UpdateSongDisplay();
} }
if (m_breakout) if (m_breakout) {
{
m_breakout = false; m_breakout = false;
m_seq->allOff(true); m_seq->allOff(true);
m_seq.reset(); m_seq.reset();
@ -236,8 +212,7 @@ struct AppCallback : boo::IApplicationCallback
} }
} }
void UpdateSFXDisplay() void UpdateSFXDisplay() {
{
bool playing = m_vox && m_vox->state() == amuse::VoiceState::Playing; bool playing = m_vox && m_vox->state() == amuse::VoiceState::Playing;
#if EMITTER_TEST #if EMITTER_TEST
printf( printf(
@ -253,13 +228,11 @@ struct AppCallback : boo::IApplicationCallback
fflush(stdout); fflush(stdout);
} }
void SelectSFX(int sfxId) void SelectSFX(int sfxId) {
{
m_sfxId = sfxId; m_sfxId = sfxId;
bool playing = m_vox && m_vox->state() == amuse::VoiceState::Playing; bool playing = m_vox && m_vox->state() == amuse::VoiceState::Playing;
if (playing) if (playing) {
{
#if EMITTER_TEST #if EMITTER_TEST
if (m_emitter) if (m_emitter)
m_emitter->getVoice()->keyOff(); m_emitter->getVoice()->keyOff();
@ -274,8 +247,7 @@ struct AppCallback : boo::IApplicationCallback
UpdateSFXDisplay(); UpdateSFXDisplay();
} }
void SFXLoop(const amuse::SFXGroupIndex& index) void SFXLoop(const amuse::SFXGroupIndex& index) {
{
printf("<space>: keyon/keyoff, <left/right>: cycle SFX, <up/down>: volume, <Q>: quit\n"); printf("<space>: keyon/keyoff, <left/right>: cycle SFX, <up/down>: volume, <Q>: quit\n");
m_seq = m_engine->seqPlay(m_groupId, 0, nullptr); m_seq = m_engine->seqPlay(m_groupId, 0, nullptr);
@ -294,10 +266,9 @@ struct AppCallback : boo::IApplicationCallback
m_listener = m_engine->addListener(zeroVec, m_listenerDir, heading, up, 5.f, 5.f, 1000.f, 1.f); m_listener = m_engine->addListener(zeroVec, m_listenerDir, heading, up, 5.f, 5.f, 1000.f, 1.f);
#endif #endif
while (m_running) while (m_running) {
{
#if EMITTER_TEST #if EMITTER_TEST
//float dist = std::sin(emitterTheta * 0.25f); // float dist = std::sin(emitterTheta * 0.25f);
m_pos[0] = std::cos(emitterTheta) * 5.f; m_pos[0] = std::cos(emitterTheta) * 5.f;
m_pos[1] = std::sin(emitterTheta) * 5.f; m_pos[1] = std::sin(emitterTheta) * 5.f;
if (m_emitter) if (m_emitter)
@ -308,40 +279,34 @@ struct AppCallback : boo::IApplicationCallback
m_events.dispatchEvents(); m_events.dispatchEvents();
if (m_wantsNext) if (m_wantsNext) {
{
m_wantsNext = false; m_wantsNext = false;
auto nextIt = sfxIt; auto nextIt = sfxIt;
++nextIt; ++nextIt;
if (nextIt != sortEntries.cend()) if (nextIt != sortEntries.cend()) {
{
++sfxIt; ++sfxIt;
SelectSFX(sfxIt->first); SelectSFX(sfxIt->first);
m_updateDisp = false; m_updateDisp = false;
} }
} }
if (m_wantsPrev) if (m_wantsPrev) {
{
m_wantsPrev = false; m_wantsPrev = false;
if (sfxIt != sortEntries.cbegin()) if (sfxIt != sortEntries.cbegin()) {
{
--sfxIt; --sfxIt;
SelectSFX(sfxIt->first); SelectSFX(sfxIt->first);
m_updateDisp = false; m_updateDisp = false;
} }
} }
if (m_updateDisp) if (m_updateDisp) {
{
m_updateDisp = false; m_updateDisp = false;
UpdateSFXDisplay(); UpdateSFXDisplay();
} }
m_win->waitForRetrace(); m_win->waitForRetrace();
if (m_vox && m_vox->state() == amuse::VoiceState::Dead) if (m_vox && m_vox->state() == amuse::VoiceState::Dead) {
{
m_vox.reset(); m_vox.reset();
#if EMITTER_TEST #if EMITTER_TEST
m_emitter.reset(); m_emitter.reset();
@ -349,8 +314,7 @@ struct AppCallback : boo::IApplicationCallback
UpdateSFXDisplay(); UpdateSFXDisplay();
} }
if (m_breakout) if (m_breakout) {
{
m_breakout = false; m_breakout = false;
m_vox.reset(); m_vox.reset();
#if EMITTER_TEST #if EMITTER_TEST
@ -368,14 +332,11 @@ struct AppCallback : boo::IApplicationCallback
#endif #endif
} }
void charKeyDownRepeat(unsigned long charCode) void charKeyDownRepeat(unsigned long charCode) {
{
charCode = tolower(charCode); charCode = tolower(charCode);
if (m_seq && m_chanId != -1) if (m_seq && m_chanId != -1) {
{ switch (charCode) {
switch (charCode)
{
case 'z': case 'z':
m_octave = amuse::clamp(-1, m_octave - 1, 8); m_octave = amuse::clamp(-1, m_octave - 1, 8);
m_updateDisp = true; m_updateDisp = true;
@ -414,26 +375,21 @@ struct AppCallback : boo::IApplicationCallback
} }
} }
void charKeyDown(unsigned long charCode) void charKeyDown(unsigned long charCode) {
{
charCode = tolower(charCode); charCode = tolower(charCode);
if (charCode == 'q') if (charCode == 'q') {
{
m_running = false; m_running = false;
return; return;
} }
if (m_sfxGroup) if (m_sfxGroup) {
{ switch (charCode) {
switch (charCode)
{
case ' ': case ' ':
if (m_seq) if (m_seq)
m_seq->allOff(true); m_seq->allOff(true);
if (m_vox && m_vox->state() == amuse::VoiceState::Playing) if (m_vox && m_vox->state() == amuse::VoiceState::Playing)
m_vox->keyOff(); m_vox->keyOff();
else if (m_sfxId != -1) else if (m_sfxId != -1) {
{
#if EMITTER_TEST #if EMITTER_TEST
m_emitter = m_engine->addEmitter(m_pos, m_dir, 100.f, 0.f, m_sfxId, 0.f, 1.f, true); m_emitter = m_engine->addEmitter(m_pos, m_dir, 100.f, 0.f, m_sfxId, 0.f, 1.f, true);
m_vox = m_emitter->getVoice(); m_vox = m_emitter->getVoice();
@ -445,13 +401,10 @@ struct AppCallback : boo::IApplicationCallback
default: default:
break; break;
} }
} } else if (m_seq && m_chanId != -1) {
else if (m_seq && m_chanId != -1)
{
bool setPanic = false; bool setPanic = false;
switch (charCode) switch (charCode) {
{
case ' ': case ' ':
++m_panicCount; ++m_panicCount;
setPanic = true; setPanic = true;
@ -552,14 +505,11 @@ struct AppCallback : boo::IApplicationCallback
} }
} }
void charKeyUp(unsigned long charCode) void charKeyUp(unsigned long charCode) {
{
charCode = tolower(charCode); charCode = tolower(charCode);
if (!m_sfxGroup && m_chanId != -1) if (!m_sfxGroup && m_chanId != -1) {
{ switch (charCode) {
switch (charCode)
{
case '\t': case '\t':
m_seq->setCtrlValue(m_chanId, 64, 0); m_seq->setCtrlValue(m_chanId, 64, 0);
break; break;
@ -621,8 +571,7 @@ struct AppCallback : boo::IApplicationCallback
} }
} }
int appMain(boo::IApplication* app) int appMain(boo::IApplication* app) {
{
/* Event window */ /* Event window */
m_win = app->newWindow(_SYS_STR("amuseplay")); m_win = app->newWindow(_SYS_STR("amuseplay"));
m_win->setCallback(&m_events); m_win->setCallback(&m_events);
@ -641,15 +590,13 @@ struct AppCallback : boo::IApplicationCallback
q->execute(); q->execute();
/* Load data */ /* Load data */
if (m_argc < 2) if (m_argc < 2) {
{
Log.report(logvisor::Error, "needs group path argument"); Log.report(logvisor::Error, "needs group path argument");
return 1; return 1;
} }
amuse::ContainerRegistry::Type cType = amuse::ContainerRegistry::DetectContainerType(m_argv[1]); amuse::ContainerRegistry::Type cType = amuse::ContainerRegistry::DetectContainerType(m_argv[1]);
if (cType == amuse::ContainerRegistry::Type::Invalid) if (cType == amuse::ContainerRegistry::Type::Invalid) {
{
Log.report(logvisor::Error, "invalid/no data at path argument"); Log.report(logvisor::Error, "invalid/no data at path argument");
return 1; return 1;
} }
@ -657,8 +604,7 @@ struct AppCallback : boo::IApplicationCallback
std::vector<std::pair<amuse::SystemString, amuse::IntrusiveAudioGroupData>> data = std::vector<std::pair<amuse::SystemString, amuse::IntrusiveAudioGroupData>> data =
amuse::ContainerRegistry::LoadContainer(m_argv[1]); amuse::ContainerRegistry::LoadContainer(m_argv[1]);
if (data.empty()) if (data.empty()) {
{
Log.report(logvisor::Error, "invalid/no data at path argument"); Log.report(logvisor::Error, "invalid/no data at path argument");
return 1; return 1;
} }
@ -672,8 +618,7 @@ struct AppCallback : boo::IApplicationCallback
allSFXGroups; allSFXGroups;
size_t totalGroups = 0; size_t totalGroups = 0;
for (auto& grp : data) for (auto& grp : data) {
{
/* Load project to assemble group list */ /* Load project to assemble group list */
m_projs.push_back(amuse::AudioGroupProject::CreateAudioGroupProject(grp.second)); m_projs.push_back(amuse::AudioGroupProject::CreateAudioGroupProject(grp.second));
amuse::AudioGroupProject& proj = m_projs.back(); amuse::AudioGroupProject& proj = m_projs.back();
@ -686,8 +631,7 @@ struct AppCallback : boo::IApplicationCallback
allSFXGroups[it->first] = std::make_pair(&grp, it->second); allSFXGroups[it->first] = std::make_pair(&grp, it->second);
} }
while (m_running) while (m_running) {
{
m_groupId = -1; m_groupId = -1;
m_setupId = -1; m_setupId = -1;
@ -698,16 +642,12 @@ struct AppCallback : boo::IApplicationCallback
else else
songs = amuse::ContainerRegistry::LoadSongs(m_argv[1]); songs = amuse::ContainerRegistry::LoadSongs(m_argv[1]);
if (songs.size()) if (songs.size()) {
{
bool play = true; bool play = true;
if (m_argc <= 2) if (m_argc <= 2) {
{
bool prompt = true; bool prompt = true;
while (true) while (true) {
{ if (prompt) {
if (prompt)
{
printf("Play Song? (Y/N): "); printf("Play Song? (Y/N): ");
prompt = false; prompt = false;
} }
@ -717,8 +657,7 @@ struct AppCallback : boo::IApplicationCallback
userSel = tolower(userSel); userSel = tolower(userSel);
if (userSel == 'n') if (userSel == 'n')
play = false; play = false;
else if (userSel != 'y') else if (userSel != 'y') {
{
prompt = true; prompt = true;
continue; continue;
} }
@ -726,27 +665,20 @@ struct AppCallback : boo::IApplicationCallback
} }
} }
if (play) if (play) {
{
/* Get song selection from user */ /* Get song selection from user */
if (songs.size() > 1) if (songs.size() > 1) {
{
/* Ask user to specify which song */ /* Ask user to specify which song */
printf("Multiple Songs discovered:\n"); printf("Multiple Songs discovered:\n");
int idx = 0; int idx = 0;
for (const auto& pair : songs) for (const auto& pair : songs) {
{
const amuse::ContainerRegistry::SongData& sngData = pair.second; const amuse::ContainerRegistry::SongData& sngData = pair.second;
int16_t grpId = sngData.m_groupId; int16_t grpId = sngData.m_groupId;
int16_t setupId = sngData.m_setupId; int16_t setupId = sngData.m_setupId;
if (sngData.m_groupId == -1 && sngData.m_setupId != -1) if (sngData.m_groupId == -1 && sngData.m_setupId != -1) {
{ for (const auto& pair : allSongGroups) {
for (const auto& pair : allSongGroups) for (const auto& setup : pair.second.second->m_midiSetups) {
{ if (setup.first == sngData.m_setupId) {
for (const auto& setup : pair.second.second->m_midiSetups)
{
if (setup.first == sngData.m_setupId)
{
grpId = pair.first; grpId = pair.first;
break; break;
} }
@ -755,32 +687,25 @@ struct AppCallback : boo::IApplicationCallback
break; break;
} }
} }
amuse::Printf(_SYS_STR(" %d %s (Group %d, Setup %d)\n"), idx++, pair.first.c_str(), grpId, amuse::Printf(_SYS_STR(" %d %s (Group %d, Setup %d)\n"), idx++, pair.first.c_str(), grpId, setupId);
setupId);
} }
int userSel = 0; int userSel = 0;
printf("Enter Song Number: "); printf("Enter Song Number: ");
if (scanf("%d", &userSel) <= 0) if (scanf("%d", &userSel) <= 0) {
{
Log.report(logvisor::Error, "unable to parse prompt"); Log.report(logvisor::Error, "unable to parse prompt");
return 1; return 1;
} }
if (userSel < songs.size()) if (userSel < songs.size()) {
{
m_arrData = &songs[userSel].second; m_arrData = &songs[userSel].second;
m_groupId = m_arrData->m_groupId; m_groupId = m_arrData->m_groupId;
m_setupId = m_arrData->m_setupId; m_setupId = m_arrData->m_setupId;
} } else {
else
{
Log.report(logvisor::Error, "unable to find Song %d", userSel); Log.report(logvisor::Error, "unable to find Song %d", userSel);
return 1; return 1;
} }
} } else if (songs.size() == 1) {
else if (songs.size() == 1)
{
m_arrData = &songs[0].second; m_arrData = &songs[0].second;
m_groupId = m_arrData->m_groupId; m_groupId = m_arrData->m_groupId;
m_setupId = m_arrData->m_setupId; m_setupId = m_arrData->m_setupId;
@ -789,14 +714,10 @@ struct AppCallback : boo::IApplicationCallback
} }
/* Get group selection via setup search */ /* Get group selection via setup search */
if (m_groupId == -1 && m_setupId != -1) if (m_groupId == -1 && m_setupId != -1) {
{ for (const auto& pair : allSongGroups) {
for (const auto& pair : allSongGroups) for (const auto& setup : pair.second.second->m_midiSetups) {
{ if (setup.first == m_setupId) {
for (const auto& setup : pair.second.second->m_midiSetups)
{
if (setup.first == m_setupId)
{
m_groupId = pair.first; m_groupId = pair.first;
break; break;
} }
@ -807,77 +728,58 @@ struct AppCallback : boo::IApplicationCallback
} }
/* Get group selection via user */ /* Get group selection via user */
if (m_groupId != -1) if (m_groupId != -1) {
{
if (allSongGroups.find(m_groupId) != allSongGroups.end()) if (allSongGroups.find(m_groupId) != allSongGroups.end())
m_sfxGroup = false; m_sfxGroup = false;
else if (allSFXGroups.find(m_groupId) != allSFXGroups.end()) else if (allSFXGroups.find(m_groupId) != allSFXGroups.end())
m_sfxGroup = true; m_sfxGroup = true;
else else {
{
Log.report(logvisor::Error, "unable to find Group %d", m_groupId); Log.report(logvisor::Error, "unable to find Group %d", m_groupId);
return 1; return 1;
} }
} } else if (totalGroups > 1) {
else if (totalGroups > 1)
{
/* Ask user to specify which group in project */ /* Ask user to specify which group in project */
printf("Multiple Audio Groups discovered:\n"); printf("Multiple Audio Groups discovered:\n");
for (const auto& pair : allSFXGroups) for (const auto& pair : allSFXGroups) {
{
amuse::Printf(_SYS_STR(" %d %s (SFXGroup) %" PRISize " sfx-entries\n"), pair.first.id, amuse::Printf(_SYS_STR(" %d %s (SFXGroup) %" PRISize " sfx-entries\n"), pair.first.id,
pair.second.first->first.c_str(), pair.second.second->m_sfxEntries.size()); pair.second.first->first.c_str(), pair.second.second->m_sfxEntries.size());
} }
for (const auto& pair : allSongGroups) for (const auto& pair : allSongGroups) {
{ amuse::Printf(_SYS_STR(" %d %s (SongGroup) %" PRISize " normal-pages, %" PRISize " drum-pages, %" PRISize
amuse::Printf(_SYS_STR(" %d %s (SongGroup) %" PRISize " normal-pages, %" PRISize " MIDI-setups\n"),
" drum-pages, %" PRISize " MIDI-setups\n"),
pair.first.id, pair.second.first->first.c_str(), pair.second.second->m_normPages.size(), pair.first.id, pair.second.first->first.c_str(), pair.second.second->m_normPages.size(),
pair.second.second->m_drumPages.size(), pair.second.second->m_midiSetups.size()); pair.second.second->m_drumPages.size(), pair.second.second->m_midiSetups.size());
} }
int userSel = 0; int userSel = 0;
printf("Enter Group Number: "); printf("Enter Group Number: ");
if (scanf("%d", &userSel) <= 0) if (scanf("%d", &userSel) <= 0) {
{
Log.report(logvisor::Error, "unable to parse prompt"); Log.report(logvisor::Error, "unable to parse prompt");
return 1; return 1;
} }
if (allSongGroups.find(userSel) != allSongGroups.end()) if (allSongGroups.find(userSel) != allSongGroups.end()) {
{
m_groupId = userSel; m_groupId = userSel;
m_sfxGroup = false; m_sfxGroup = false;
} } else if (allSFXGroups.find(userSel) != allSFXGroups.end()) {
else if (allSFXGroups.find(userSel) != allSFXGroups.end())
{
m_groupId = userSel; m_groupId = userSel;
m_sfxGroup = true; m_sfxGroup = true;
} } else {
else
{
Log.report(logvisor::Error, "unable to find Group %d", userSel); Log.report(logvisor::Error, "unable to find Group %d", userSel);
return 1; return 1;
} }
} } else if (totalGroups == 1) {
else if (totalGroups == 1)
{
/* Load one and only group */ /* Load one and only group */
if (allSongGroups.size()) if (allSongGroups.size()) {
{
const auto& pair = *allSongGroups.cbegin(); const auto& pair = *allSongGroups.cbegin();
m_groupId = pair.first; m_groupId = pair.first;
m_sfxGroup = false; m_sfxGroup = false;
} } else {
else
{
const auto& pair = *allSFXGroups.cbegin(); const auto& pair = *allSFXGroups.cbegin();
m_groupId = pair.first; m_groupId = pair.first;
m_sfxGroup = true; m_sfxGroup = true;
} }
} } else {
else
{
Log.report(logvisor::Error, "empty project"); Log.report(logvisor::Error, "empty project");
return 1; return 1;
} }
@ -887,23 +789,18 @@ struct AppCallback : boo::IApplicationCallback
amuse::ObjToken<amuse::SongGroupIndex> songIndex; amuse::ObjToken<amuse::SongGroupIndex> songIndex;
amuse::ObjToken<amuse::SFXGroupIndex> sfxIndex; amuse::ObjToken<amuse::SFXGroupIndex> sfxIndex;
auto songSearch = allSongGroups.find(m_groupId); auto songSearch = allSongGroups.find(m_groupId);
if (songSearch != allSongGroups.end()) if (songSearch != allSongGroups.end()) {
{
selData = &songSearch->second.first->second; selData = &songSearch->second.first->second;
songIndex = songSearch->second.second; songIndex = songSearch->second.second;
} } else {
else
{
auto sfxSearch = allSFXGroups.find(m_groupId); auto sfxSearch = allSFXGroups.find(m_groupId);
if (sfxSearch != allSFXGroups.end()) if (sfxSearch != allSFXGroups.end()) {
{
selData = &sfxSearch->second.first->second; selData = &sfxSearch->second.first->second;
sfxIndex = sfxSearch->second.second; sfxIndex = sfxSearch->second.second;
} }
} }
if (!selData) if (!selData) {
{
Log.report(logvisor::Error, "unable to select audio group data"); Log.report(logvisor::Error, "unable to select audio group data");
return 1; return 1;
} }
@ -915,8 +812,7 @@ struct AppCallback : boo::IApplicationCallback
/* Load group into engine */ /* Load group into engine */
const amuse::AudioGroup* group = m_engine->addAudioGroup(*selData); const amuse::AudioGroup* group = m_engine->addAudioGroup(*selData);
if (!group) if (!group) {
{
Log.report(logvisor::Error, "unable to add audio group"); Log.report(logvisor::Error, "unable to add audio group");
return 1; return 1;
} }
@ -940,13 +836,10 @@ struct AppCallback : boo::IApplicationCallback
void appQuitting(boo::IApplication*) { m_running = false; } void appQuitting(boo::IApplication*) { m_running = false; }
AppCallback(int argc, const boo::SystemChar** argv) AppCallback(int argc, const boo::SystemChar** argv)
: m_argc(argc), m_argv(argv), m_eventRec(*this), m_events(m_eventRec) : m_argc(argc), m_argv(argv), m_eventRec(*this), m_events(m_eventRec) {}
{
}
}; };
void EventCallback::charKeyDown(unsigned long charCode, boo::EModifierKey mods, bool isRepeat) void EventCallback::charKeyDown(unsigned long charCode, boo::EModifierKey mods, bool isRepeat) {
{
if (isRepeat) if (isRepeat)
m_app.charKeyDownRepeat(charCode); m_app.charKeyDownRepeat(charCode);
else else
@ -955,10 +848,8 @@ void EventCallback::charKeyDown(unsigned long charCode, boo::EModifierKey mods,
void EventCallback::charKeyUp(unsigned long charCode, boo::EModifierKey mods) { m_app.charKeyUp(charCode); } void EventCallback::charKeyUp(unsigned long charCode, boo::EModifierKey mods) { m_app.charKeyUp(charCode); }
void EventCallback::specialKeyDown(boo::ESpecialKey key, boo::EModifierKey mods, bool isRepeat) void EventCallback::specialKeyDown(boo::ESpecialKey key, boo::EModifierKey mods, bool isRepeat) {
{ switch (key) {
switch (key)
{
case boo::ESpecialKey::Left: case boo::ESpecialKey::Left:
m_app.m_wantsPrev = true; m_app.m_wantsPrev = true;
break; break;
@ -986,8 +877,7 @@ void EventCallback::specialKeyDown(boo::ESpecialKey key, boo::EModifierKey mods,
void EventCallback::specialKeyUp(boo::ESpecialKey key, boo::EModifierKey mods) {} void EventCallback::specialKeyUp(boo::ESpecialKey key, boo::EModifierKey mods) {}
void EventCallback::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton, boo::EModifierKey) void EventCallback::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton, boo::EModifierKey) {
{
m_tracking = true; m_tracking = true;
m_app.m_pitchBend = amuse::clamp(-1.f, coord.norm[1] * 2.f - 1.f, 1.f); m_app.m_pitchBend = amuse::clamp(-1.f, coord.norm[1] * 2.f - 1.f, 1.f);
if (m_app.m_vox) if (m_app.m_vox)
@ -996,8 +886,7 @@ void EventCallback::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton,
m_app.m_seq->setPitchWheel(m_app.m_chanId, m_app.m_pitchBend); m_app.m_seq->setPitchWheel(m_app.m_chanId, m_app.m_pitchBend);
} }
void EventCallback::mouseUp(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey) void EventCallback::mouseUp(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey) {
{
m_tracking = false; m_tracking = false;
m_app.m_pitchBend = 0.f; m_app.m_pitchBend = 0.f;
if (m_app.m_vox) if (m_app.m_vox)
@ -1006,10 +895,8 @@ void EventCallback::mouseUp(const boo::SWindowCoord&, boo::EMouseButton, boo::EM
m_app.m_seq->setPitchWheel(m_app.m_chanId, m_app.m_pitchBend); m_app.m_seq->setPitchWheel(m_app.m_chanId, m_app.m_pitchBend);
} }
void EventCallback::mouseMove(const boo::SWindowCoord& coord) void EventCallback::mouseMove(const boo::SWindowCoord& coord) {
{ if (m_tracking) {
if (m_tracking)
{
m_app.m_modulation = amuse::clamp(0.f, coord.norm[0], 1.f); m_app.m_modulation = amuse::clamp(0.f, coord.norm[0], 1.f);
if (m_app.m_vox) if (m_app.m_vox)
m_app.m_vox->setCtrlValue(1, m_app.m_modulation * 127.f); m_app.m_vox->setCtrlValue(1, m_app.m_modulation * 127.f);
@ -1033,17 +920,15 @@ int main(int argc, const boo::SystemChar** argv)
logvisor::RegisterConsoleLogger(); logvisor::RegisterConsoleLogger();
logvisor::RegisterStandardExceptions(); logvisor::RegisterStandardExceptions();
AppCallback app(argc, argv); AppCallback app(argc, argv);
int ret = boo::ApplicationRun(boo::IApplication::EPlatformType::Auto, app, int ret = boo::ApplicationRun(boo::IApplication::EPlatformType::Auto, app, _SYS_STR("amuseplay"),
_SYS_STR("amuseplay"), _SYS_STR("Amuse Player"), _SYS_STR("Amuse Player"), argc, argv, {}, 1, 1, false);
argc, argv, {}, 1, 1, false);
printf("IM DYING!!\n"); printf("IM DYING!!\n");
return ret; return ret;
} }
#if _WIN32 #if _WIN32
#include <shellapi.h> #include <shellapi.h>
int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE, LPWSTR lpCmdLine, int) int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE, LPWSTR lpCmdLine, int) {
{
int argc = 0; int argc = 0;
const boo::SystemChar** argv; const boo::SystemChar** argv;
if (lpCmdLine[0]) if (lpCmdLine[0])
@ -1052,8 +937,8 @@ int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE, LPWSTR lpCmdLine, int)
GetModuleFileNameW(nullptr, selfPath, 1024); GetModuleFileNameW(nullptr, selfPath, 1024);
static const boo::SystemChar* booArgv[32] = {}; static const boo::SystemChar* booArgv[32] = {};
booArgv[0] = selfPath; booArgv[0] = selfPath;
for (int i=0 ; i<argc ; ++i) for (int i = 0; i < argc; ++i)
booArgv[i+1] = argv[i]; booArgv[i + 1] = argv[i];
logvisor::CreateWin32Console(); logvisor::CreateWin32Console();
SetConsoleOutputCP(65001); SetConsoleOutputCP(65001);

View File

@ -21,8 +21,7 @@ static logvisor::Module Log("amuserender");
__attribute__((__format__(__printf__, 3, 4))) __attribute__((__format__(__printf__, 3, 4)))
#endif #endif
static inline void static inline void
SNPrintf(boo::SystemChar* str, size_t maxlen, const boo::SystemChar* format, ...) SNPrintf(boo::SystemChar* str, size_t maxlen, const boo::SystemChar* format, ...) {
{
va_list va; va_list va;
va_start(va, format); va_start(va, format);
#if _WIN32 #if _WIN32
@ -39,8 +38,7 @@ SNPrintf(boo::SystemChar* str, size_t maxlen, const boo::SystemChar* format, ...
#include <signal.h> #include <signal.h>
static void abortHandler(int signum) static void abortHandler(int signum) {
{
unsigned int i; unsigned int i;
void* stack[100]; void* stack[100];
unsigned short frames; unsigned short frames;
@ -54,8 +52,7 @@ static void abortHandler(int signum)
symbol->MaxNameLen = 255; symbol->MaxNameLen = 255;
symbol->SizeOfStruct = sizeof(SYMBOL_INFO); symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
for (i = 0; i < frames; i++) for (i = 0; i < frames; i++) {
{
SymFromAddr(process, (DWORD64)(stack[i]), 0, symbol); SymFromAddr(process, (DWORD64)(stack[i]), 0, symbol);
printf("%i: %s - 0x%0llX", frames - i - 1, symbol->Name, symbol->Address); printf("%i: %s - 0x%0llX", frames - i - 1, symbol->Name, symbol->Address);
@ -65,13 +62,10 @@ static void abortHandler(int signum)
SymSetOptions(SYMOPT_LOAD_LINES); SymSetOptions(SYMOPT_LOAD_LINES);
line.SizeOfStruct = sizeof(IMAGEHLP_LINE64); line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
if (SymGetLineFromAddr64(process, (DWORD64)(stack[i]), &dwDisplacement, &line)) if (SymGetLineFromAddr64(process, (DWORD64)(stack[i]), &dwDisplacement, &line)) {
{
// SymGetLineFromAddr64 returned success // SymGetLineFromAddr64 returned success
printf(" LINE %d\n", line.LineNumber); printf(" LINE %d\n", line.LineNumber);
} } else {
else
{
printf("\n"); printf("\n");
} }
} }
@ -102,87 +96,68 @@ int main(int argc, const boo::SystemChar** argv)
double rate = NativeSampleRate; double rate = NativeSampleRate;
int chCount = 2; int chCount = 2;
double volume = 1.0; double volume = 1.0;
for (int i = 1; i < argc; ++i) for (int i = 1; i < argc; ++i) {
{
#if _WIN32 #if _WIN32
if (!wcsncmp(argv[i], L"-r", 2)) if (!wcsncmp(argv[i], L"-r", 2)) {
{
if (argv[i][2]) if (argv[i][2])
rate = wcstod(&argv[i][2], nullptr); rate = wcstod(&argv[i][2], nullptr);
else if (argc > (i + 1)) else if (argc > (i + 1)) {
{
rate = wcstod(argv[i + 1], nullptr); rate = wcstod(argv[i + 1], nullptr);
++i; ++i;
} }
} } else if (!wcsncmp(argv[i], L"-c", 2)) {
else if (!wcsncmp(argv[i], L"-c", 2))
{
if (argv[i][2]) if (argv[i][2])
chCount = wcstoul(&argv[i][2], nullptr, 0); chCount = wcstoul(&argv[i][2], nullptr, 0);
else if (argc > (i + 1)) else if (argc > (i + 1)) {
{
chCount = wcstoul(argv[i + 1], nullptr, 0); chCount = wcstoul(argv[i + 1], nullptr, 0);
++i; ++i;
} }
} } else if (!wcsncmp(argv[i], L"-v", 2)) {
else if (!wcsncmp(argv[i], L"-v", 2))
{
if (argv[i][2]) if (argv[i][2])
volume = wcstod(&argv[i][2], nullptr); volume = wcstod(&argv[i][2], nullptr);
else if (argc > (i + 1)) else if (argc > (i + 1)) {
{
volume = wcstod(argv[i + 1], nullptr); volume = wcstod(argv[i + 1], nullptr);
++i; ++i;
} }
} } else
else
m_args.push_back(argv[i]); m_args.push_back(argv[i]);
#else #else
if (!strncmp(argv[i], "-r", 2)) if (!strncmp(argv[i], "-r", 2)) {
{
if (argv[i][2]) if (argv[i][2])
rate = strtod(&argv[i][2], nullptr); rate = strtod(&argv[i][2], nullptr);
else if (argc > (i + 1)) else if (argc > (i + 1)) {
{
rate = strtod(argv[i + 1], nullptr); rate = strtod(argv[i + 1], nullptr);
++i; ++i;
} }
} } else if (!strncmp(argv[i], "-c", 2)) {
else if (!strncmp(argv[i], "-c", 2))
{
if (argv[i][2]) if (argv[i][2])
chCount = strtoul(&argv[i][2], nullptr, 0); chCount = strtoul(&argv[i][2], nullptr, 0);
else if (argc > (i + 1)) else if (argc > (i + 1)) {
{
chCount = strtoul(argv[i + 1], nullptr, 0); chCount = strtoul(argv[i + 1], nullptr, 0);
++i; ++i;
} }
} } else if (!strncmp(argv[i], "-v", 2)) {
else if (!strncmp(argv[i], "-v", 2))
{
if (argv[i][2]) if (argv[i][2])
volume = strtod(&argv[i][2], nullptr); volume = strtod(&argv[i][2], nullptr);
else if (argc > (i + 1)) else if (argc > (i + 1)) {
{
volume = strtod(argv[i + 1], nullptr); volume = strtod(argv[i + 1], nullptr);
++i; ++i;
} }
} } else
else
m_args.push_back(argv[i]); m_args.push_back(argv[i]);
#endif #endif
} }
/* Load data */ /* Load data */
if (m_args.size() < 1) if (m_args.size() < 1) {
{ Log.report(logvisor::Error,
Log.report(logvisor::Error, "Usage: amuserender <group-file> [<songs-file>] [-r <sample-rate>] [-c <channel-count>] [-v <volume 0.0-1.0>]"); "Usage: amuserender <group-file> [<songs-file>] [-r <sample-rate>] [-c <channel-count>] [-v <volume "
"0.0-1.0>]");
return 1; return 1;
} }
amuse::ContainerRegistry::Type cType = amuse::ContainerRegistry::DetectContainerType(m_args[0].c_str()); amuse::ContainerRegistry::Type cType = amuse::ContainerRegistry::DetectContainerType(m_args[0].c_str());
if (cType == amuse::ContainerRegistry::Type::Invalid) if (cType == amuse::ContainerRegistry::Type::Invalid) {
{
Log.report(logvisor::Error, "invalid/no data at path argument"); Log.report(logvisor::Error, "invalid/no data at path argument");
return 1; return 1;
} }
@ -190,8 +165,7 @@ int main(int argc, const boo::SystemChar** argv)
std::vector<std::pair<amuse::SystemString, amuse::IntrusiveAudioGroupData>> data = std::vector<std::pair<amuse::SystemString, amuse::IntrusiveAudioGroupData>> data =
amuse::ContainerRegistry::LoadContainer(m_args[0].c_str()); amuse::ContainerRegistry::LoadContainer(m_args[0].c_str());
if (data.empty()) if (data.empty()) {
{
Log.report(logvisor::Error, "invalid/no data at path argument"); Log.report(logvisor::Error, "invalid/no data at path argument");
return 1; return 1;
} }
@ -204,16 +178,15 @@ int main(int argc, const boo::SystemChar** argv)
bool m_sfxGroup = false; bool m_sfxGroup = false;
std::list<amuse::AudioGroupProject> m_projs; std::list<amuse::AudioGroupProject> m_projs;
std::map<int, std::map<int, std::pair<std::pair<amuse::SystemString, amuse::IntrusiveAudioGroupData>*,
std::pair<std::pair<amuse::SystemString, amuse::IntrusiveAudioGroupData>*, amuse::ObjToken<amuse::SongGroupIndex>>> amuse::ObjToken<amuse::SongGroupIndex>>>
allSongGroups; allSongGroups;
std::map<int, std::map<int, std::pair<std::pair<amuse::SystemString, amuse::IntrusiveAudioGroupData>*,
std::pair<std::pair<amuse::SystemString, amuse::IntrusiveAudioGroupData>*, amuse::ObjToken<amuse::SFXGroupIndex>>> amuse::ObjToken<amuse::SFXGroupIndex>>>
allSFXGroups; allSFXGroups;
size_t totalGroups = 0; size_t totalGroups = 0;
for (auto& grp : data) for (auto& grp : data) {
{
/* Load project to assemble group list */ /* Load project to assemble group list */
m_projs.push_back(amuse::AudioGroupProject::CreateAudioGroupProject(grp.second)); m_projs.push_back(amuse::AudioGroupProject::CreateAudioGroupProject(grp.second));
amuse::AudioGroupProject& proj = m_projs.back(); amuse::AudioGroupProject& proj = m_projs.back();
@ -233,16 +206,12 @@ int main(int argc, const boo::SystemChar** argv)
else else
songs = amuse::ContainerRegistry::LoadSongs(m_args[0].c_str()); songs = amuse::ContainerRegistry::LoadSongs(m_args[0].c_str());
if (songs.size()) if (songs.size()) {
{
bool play = true; bool play = true;
if (m_args.size() <= 1) if (m_args.size() <= 1) {
{
bool prompt = true; bool prompt = true;
while (true) while (true) {
{ if (prompt) {
if (prompt)
{
printf("Render Song? (Y/N): "); printf("Render Song? (Y/N): ");
prompt = false; prompt = false;
} }
@ -252,8 +221,7 @@ int main(int argc, const boo::SystemChar** argv)
userSel = tolower(userSel); userSel = tolower(userSel);
if (userSel == 'n') if (userSel == 'n')
play = false; play = false;
else if (userSel != 'y') else if (userSel != 'y') {
{
prompt = true; prompt = true;
continue; continue;
} }
@ -261,27 +229,20 @@ int main(int argc, const boo::SystemChar** argv)
} }
} }
if (play) if (play) {
{
/* Get song selection from user */ /* Get song selection from user */
if (songs.size() > 1) if (songs.size() > 1) {
{
/* Ask user to specify which song */ /* Ask user to specify which song */
printf("Multiple Songs discovered:\n"); printf("Multiple Songs discovered:\n");
int idx = 0; int idx = 0;
for (const auto& pair : songs) for (const auto& pair : songs) {
{
const amuse::ContainerRegistry::SongData& sngData = pair.second; const amuse::ContainerRegistry::SongData& sngData = pair.second;
int16_t grpId = sngData.m_groupId; int16_t grpId = sngData.m_groupId;
int16_t setupId = sngData.m_setupId; int16_t setupId = sngData.m_setupId;
if (sngData.m_groupId == -1 && sngData.m_setupId != -1) if (sngData.m_groupId == -1 && sngData.m_setupId != -1) {
{ for (const auto& pair : allSongGroups) {
for (const auto& pair : allSongGroups) for (const auto& setup : pair.second.second->m_midiSetups) {
{ if (setup.first == sngData.m_setupId) {
for (const auto& setup : pair.second.second->m_midiSetups)
{
if (setup.first == sngData.m_setupId)
{
grpId = pair.first; grpId = pair.first;
break; break;
} }
@ -295,27 +256,21 @@ int main(int argc, const boo::SystemChar** argv)
int userSel = 0; int userSel = 0;
printf("Enter Song Number: "); printf("Enter Song Number: ");
if (scanf("%d", &userSel) <= 0) if (scanf("%d", &userSel) <= 0) {
{
Log.report(logvisor::Error, "unable to parse prompt"); Log.report(logvisor::Error, "unable to parse prompt");
return 1; return 1;
} }
if (userSel < songs.size()) if (userSel < songs.size()) {
{
m_arrData = &songs[userSel].second; m_arrData = &songs[userSel].second;
m_groupId = m_arrData->m_groupId; m_groupId = m_arrData->m_groupId;
m_setupId = m_arrData->m_setupId; m_setupId = m_arrData->m_setupId;
m_songName = &songs[userSel].first; m_songName = &songs[userSel].first;
} } else {
else
{
Log.report(logvisor::Error, "unable to find Song %d", userSel); Log.report(logvisor::Error, "unable to find Song %d", userSel);
return 1; return 1;
} }
} } else if (songs.size() == 1) {
else if (songs.size() == 1)
{
m_arrData = &songs[0].second; m_arrData = &songs[0].second;
m_groupId = m_arrData->m_groupId; m_groupId = m_arrData->m_groupId;
m_setupId = m_arrData->m_setupId; m_setupId = m_arrData->m_setupId;
@ -325,14 +280,10 @@ int main(int argc, const boo::SystemChar** argv)
} }
/* Get group selection via setup search */ /* Get group selection via setup search */
if (m_groupId == -1 && m_setupId != -1) if (m_groupId == -1 && m_setupId != -1) {
{ for (const auto& pair : allSongGroups) {
for (const auto& pair : allSongGroups) for (const auto& setup : pair.second.second->m_midiSetups) {
{ if (setup.first == m_setupId) {
for (const auto& setup : pair.second.second->m_midiSetups)
{
if (setup.first == m_setupId)
{
m_groupId = pair.first; m_groupId = pair.first;
m_groupName = &pair.second.first->first; m_groupName = &pair.second.first->first;
break; break;
@ -344,37 +295,27 @@ int main(int argc, const boo::SystemChar** argv)
} }
/* Get group selection via user */ /* Get group selection via user */
if (m_groupId != -1) if (m_groupId != -1) {
{
auto songSearch = allSongGroups.find(m_groupId); auto songSearch = allSongGroups.find(m_groupId);
auto sfxSearch = allSFXGroups.find(m_groupId); auto sfxSearch = allSFXGroups.find(m_groupId);
if (songSearch != allSongGroups.end()) if (songSearch != allSongGroups.end()) {
{
m_sfxGroup = false; m_sfxGroup = false;
m_groupName = &songSearch->second.first->first; m_groupName = &songSearch->second.first->first;
} } else if (sfxSearch != allSFXGroups.end()) {
else if (sfxSearch != allSFXGroups.end())
{
m_sfxGroup = true; m_sfxGroup = true;
m_groupName = &sfxSearch->second.first->first; m_groupName = &sfxSearch->second.first->first;
} } else {
else
{
Log.report(logvisor::Error, "unable to find Group %d", m_groupId); Log.report(logvisor::Error, "unable to find Group %d", m_groupId);
return 1; return 1;
} }
} } else if (totalGroups > 1) {
else if (totalGroups > 1)
{
/* Ask user to specify which group in project */ /* Ask user to specify which group in project */
printf("Multiple Audio Groups discovered:\n"); printf("Multiple Audio Groups discovered:\n");
for (const auto& pair : allSFXGroups) for (const auto& pair : allSFXGroups) {
{
amuse::Printf(_SYS_STR(" %d %s (SFXGroup) %" PRISize " sfx-entries\n"), pair.first, amuse::Printf(_SYS_STR(" %d %s (SFXGroup) %" PRISize " sfx-entries\n"), pair.first,
pair.second.first->first.c_str(), pair.second.second->m_sfxEntries.size()); pair.second.first->first.c_str(), pair.second.second->m_sfxEntries.size());
} }
for (const auto& pair : allSongGroups) for (const auto& pair : allSongGroups) {
{
amuse::Printf(_SYS_STR(" %d %s (SongGroup) %" PRISize " normal-pages, %" PRISize " drum-pages, %" PRISize amuse::Printf(_SYS_STR(" %d %s (SongGroup) %" PRISize " normal-pages, %" PRISize " drum-pages, %" PRISize
" MIDI-setups\n"), " MIDI-setups\n"),
pair.first, pair.second.first->first.c_str(), pair.second.second->m_normPages.size(), pair.first, pair.second.first->first.c_str(), pair.second.second->m_normPages.size(),
@ -383,52 +324,39 @@ int main(int argc, const boo::SystemChar** argv)
int userSel = 0; int userSel = 0;
printf("Enter Group Number: "); printf("Enter Group Number: ");
if (scanf("%d", &userSel) <= 0) if (scanf("%d", &userSel) <= 0) {
{
Log.report(logvisor::Error, "unable to parse prompt"); Log.report(logvisor::Error, "unable to parse prompt");
return 1; return 1;
} }
auto songSearch = allSongGroups.find(userSel); auto songSearch = allSongGroups.find(userSel);
auto sfxSearch = allSFXGroups.find(userSel); auto sfxSearch = allSFXGroups.find(userSel);
if (songSearch != allSongGroups.end()) if (songSearch != allSongGroups.end()) {
{
m_groupId = userSel; m_groupId = userSel;
m_groupName = &songSearch->second.first->first; m_groupName = &songSearch->second.first->first;
m_sfxGroup = false; m_sfxGroup = false;
} } else if (sfxSearch != allSFXGroups.end()) {
else if (sfxSearch != allSFXGroups.end())
{
m_groupId = userSel; m_groupId = userSel;
m_groupName = &sfxSearch->second.first->first; m_groupName = &sfxSearch->second.first->first;
m_sfxGroup = true; m_sfxGroup = true;
} } else {
else
{
Log.report(logvisor::Error, "unable to find Group %d", userSel); Log.report(logvisor::Error, "unable to find Group %d", userSel);
return 1; return 1;
} }
} } else if (totalGroups == 1) {
else if (totalGroups == 1)
{
/* Load one and only group */ /* Load one and only group */
if (allSongGroups.size()) if (allSongGroups.size()) {
{
const auto& pair = *allSongGroups.cbegin(); const auto& pair = *allSongGroups.cbegin();
m_groupId = pair.first; m_groupId = pair.first;
m_groupName = &pair.second.first->first; m_groupName = &pair.second.first->first;
m_sfxGroup = false; m_sfxGroup = false;
} } else {
else
{
const auto& pair = *allSFXGroups.cbegin(); const auto& pair = *allSFXGroups.cbegin();
m_groupId = pair.first; m_groupId = pair.first;
m_groupName = &pair.second.first->first; m_groupName = &pair.second.first->first;
m_sfxGroup = true; m_sfxGroup = true;
} }
} } else {
else
{
Log.report(logvisor::Error, "empty project"); Log.report(logvisor::Error, "empty project");
return 1; return 1;
} }
@ -438,52 +366,43 @@ int main(int argc, const boo::SystemChar** argv)
amuse::ObjToken<amuse::SongGroupIndex> songIndex; amuse::ObjToken<amuse::SongGroupIndex> songIndex;
amuse::ObjToken<amuse::SFXGroupIndex> sfxIndex; amuse::ObjToken<amuse::SFXGroupIndex> sfxIndex;
auto songSearch = allSongGroups.find(m_groupId); auto songSearch = allSongGroups.find(m_groupId);
if (songSearch != allSongGroups.end()) if (songSearch != allSongGroups.end()) {
{
selData = &songSearch->second.first->second; selData = &songSearch->second.first->second;
songIndex = songSearch->second.second; songIndex = songSearch->second.second;
std::set<int> sortSetups; std::set<int> sortSetups;
for (auto& pair : songIndex->m_midiSetups) for (auto& pair : songIndex->m_midiSetups)
sortSetups.insert(pair.first); sortSetups.insert(pair.first);
if (m_setupId == -1) if (m_setupId == -1) {
{
/* Ask user to specify which group in project */ /* Ask user to specify which group in project */
printf("Multiple MIDI Setups:\n"); printf("Multiple MIDI Setups:\n");
for (int setup : sortSetups) for (int setup : sortSetups)
printf(" %d\n", setup); printf(" %d\n", setup);
int userSel = 0; int userSel = 0;
printf("Enter Setup Number: "); printf("Enter Setup Number: ");
if (scanf("%d", &userSel) <= 0) if (scanf("%d", &userSel) <= 0) {
{
Log.report(logvisor::Error, "unable to parse prompt"); Log.report(logvisor::Error, "unable to parse prompt");
return 1; return 1;
} }
m_setupId = userSel; m_setupId = userSel;
} }
if (sortSetups.find(m_setupId) == sortSetups.cend()) if (sortSetups.find(m_setupId) == sortSetups.cend()) {
{
Log.report(logvisor::Error, "unable to find setup %d", m_setupId); Log.report(logvisor::Error, "unable to find setup %d", m_setupId);
return 1; return 1;
} }
} } else {
else
{
auto sfxSearch = allSFXGroups.find(m_groupId); auto sfxSearch = allSFXGroups.find(m_groupId);
if (sfxSearch != allSFXGroups.end()) if (sfxSearch != allSFXGroups.end()) {
{
selData = &sfxSearch->second.first->second; selData = &sfxSearch->second.first->second;
sfxIndex = sfxSearch->second.second; sfxIndex = sfxSearch->second.second;
} }
} }
if (!selData) if (!selData) {
{
Log.report(logvisor::Error, "unable to select audio group data"); Log.report(logvisor::Error, "unable to select audio group data");
return 1; return 1;
} }
if (m_sfxGroup) if (m_sfxGroup) {
{
Log.report(logvisor::Error, "amuserender is currently only able to render SongGroups"); Log.report(logvisor::Error, "amuserender is currently only able to render SongGroups");
return 1; return 1;
} }
@ -501,8 +420,7 @@ int main(int argc, const boo::SystemChar** argv)
/* Load group into engine */ /* Load group into engine */
const amuse::AudioGroup* group = engine.addAudioGroup(*selData); const amuse::AudioGroup* group = engine.addAudioGroup(*selData);
if (!group) if (!group) {
{
Log.report(logvisor::Error, "unable to add audio group"); Log.report(logvisor::Error, "unable to add audio group");
return 1; return 1;
} }
@ -511,8 +429,7 @@ int main(int argc, const boo::SystemChar** argv)
amuse::ObjToken<amuse::Sequencer> seq = engine.seqPlay(m_groupId, m_setupId, m_arrData->m_data.get(), false); amuse::ObjToken<amuse::Sequencer> seq = engine.seqPlay(m_groupId, m_setupId, m_arrData->m_data.get(), false);
size_t wroteFrames = 0; size_t wroteFrames = 0;
signal(SIGINT, SIGINTHandler); signal(SIGINT, SIGINTHandler);
do do {
{
voxEngine->pumpAndMixVoices(); voxEngine->pumpAndMixVoices();
wroteFrames += voxEngine->get5MsFrames(); wroteFrames += voxEngine->get5MsFrames();
printf("\rFrame %" PRISize, wroteFrames); printf("\rFrame %" PRISize, wroteFrames);
@ -525,8 +442,7 @@ int main(int argc, const boo::SystemChar** argv)
#if _WIN32 #if _WIN32
#include <shellapi.h> #include <shellapi.h>
int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE, LPWSTR lpCmdLine, int) int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE, LPWSTR lpCmdLine, int) {
{
signal(SIGABRT, abortHandler); signal(SIGABRT, abortHandler);
signal(SIGSEGV, abortHandler); signal(SIGSEGV, abortHandler);
signal(SIGILL, abortHandler); signal(SIGILL, abortHandler);
@ -540,8 +456,8 @@ int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE, LPWSTR lpCmdLine, int)
GetModuleFileNameW(nullptr, selfPath, 1024); GetModuleFileNameW(nullptr, selfPath, 1024);
static const boo::SystemChar* booArgv[32] = {}; static const boo::SystemChar* booArgv[32] = {};
booArgv[0] = selfPath; booArgv[0] = selfPath;
for (int i=0 ; i<argc ; ++i) for (int i = 0; i < argc; ++i)
booArgv[i+1] = argv[i]; booArgv[i + 1] = argv[i];
logvisor::CreateWin32Console(); logvisor::CreateWin32Console();
SetConsoleOutputCP(65001); SetConsoleOutputCP(65001);

View File

@ -5,15 +5,14 @@
#include "AudioGroupSampleDirectory.hpp" #include "AudioGroupSampleDirectory.hpp"
#include <unordered_set> #include <unordered_set>
namespace amuse namespace amuse {
{
class AudioGroupData; class AudioGroupData;
class ProjectDatabase; class ProjectDatabase;
/** Runtime audio group index container */ /** Runtime audio group index container */
class AudioGroup class AudioGroup {
{
friend class AudioGroupSampleDirectory; friend class AudioGroupSampleDirectory;
protected: protected:
AudioGroupProject m_proj; AudioGroupProject m_proj;
AudioGroupPool m_pool; AudioGroupPool m_pool;
@ -36,10 +35,9 @@ public:
void setGroupPath(SystemStringView groupPath) { m_groupPath = groupPath; } void setGroupPath(SystemStringView groupPath) { m_groupPath = groupPath; }
const SampleEntry* getSample(SampleId sfxId) const; const SampleEntry* getSample(SampleId sfxId) const;
std::pair<ObjToken<SampleEntryData>, const unsigned char*> std::pair<ObjToken<SampleEntryData>, const unsigned char*> getSampleData(SampleId sfxId,
getSampleData(SampleId sfxId, const SampleEntry* sample) const; const SampleEntry* sample) const;
SampleFileState getSampleFileState(SampleId sfxId, SampleFileState getSampleFileState(SampleId sfxId, const SampleEntry* sample, SystemString* pathOut = nullptr) const;
const SampleEntry* sample, SystemString* pathOut = nullptr) const;
void patchSampleMetadata(SampleId sfxId, const SampleEntry* sample) const; void patchSampleMetadata(SampleId sfxId, const SampleEntry* sample) const;
void makeWAVVersion(SampleId sfxId, const SampleEntry* sample) const; void makeWAVVersion(SampleId sfxId, const SampleEntry* sample) const;
void makeCompressedVersion(SampleId sfxId, const SampleEntry* sample) const; void makeCompressedVersion(SampleId sfxId, const SampleEntry* sample) const;
@ -53,8 +51,7 @@ public:
virtual void setIdDatabases() const {} virtual void setIdDatabases() const {}
}; };
class AudioGroupDatabase final : public AudioGroup class AudioGroupDatabase final : public AudioGroup {
{
NameDB m_soundMacroDb; NameDB m_soundMacroDb;
NameDB m_sampleDb; NameDB m_sampleDb;
NameDB m_tableDb; NameDB m_tableDb;
@ -66,24 +63,20 @@ class AudioGroupDatabase final : public AudioGroup
public: public:
AudioGroupDatabase() = default; AudioGroupDatabase() = default;
explicit AudioGroupDatabase(const AudioGroupData& data) explicit AudioGroupDatabase(const AudioGroupData& data) {
{
setIdDatabases(); setIdDatabases();
assign(data); assign(data);
} }
explicit AudioGroupDatabase(SystemStringView groupPath) explicit AudioGroupDatabase(SystemStringView groupPath) {
{
setIdDatabases(); setIdDatabases();
assign(groupPath); assign(groupPath);
} }
explicit AudioGroupDatabase(const AudioGroupDatabase& data, SystemStringView groupPath) explicit AudioGroupDatabase(const AudioGroupDatabase& data, SystemStringView groupPath) {
{
setIdDatabases(); setIdDatabases();
assign(data, groupPath); assign(data, groupPath);
} }
void setIdDatabases() const void setIdDatabases() const {
{
SoundMacroId::CurNameDB = const_cast<NameDB*>(&m_soundMacroDb); SoundMacroId::CurNameDB = const_cast<NameDB*>(&m_soundMacroDb);
SampleId::CurNameDB = const_cast<NameDB*>(&m_sampleDb); SampleId::CurNameDB = const_cast<NameDB*>(&m_sampleDb);
TableId::CurNameDB = const_cast<NameDB*>(&m_tableDb); TableId::CurNameDB = const_cast<NameDB*>(&m_tableDb);
@ -99,19 +92,16 @@ public:
std::string exportCHeader(std::string_view projectName, std::string_view groupName) const; std::string exportCHeader(std::string_view projectName, std::string_view groupName) const;
}; };
class ProjectDatabase class ProjectDatabase {
{
NameDB m_songDb; NameDB m_songDb;
NameDB m_sfxDb; NameDB m_sfxDb;
NameDB m_groupDb; NameDB m_groupDb;
public: public:
void setIdDatabases() const void setIdDatabases() const {
{
SongId::CurNameDB = const_cast<NameDB*>(&m_songDb); SongId::CurNameDB = const_cast<NameDB*>(&m_songDb);
SFXId::CurNameDB = const_cast<NameDB*>(&m_sfxDb); SFXId::CurNameDB = const_cast<NameDB*>(&m_sfxDb);
GroupId::CurNameDB = const_cast<NameDB*>(&m_groupDb); GroupId::CurNameDB = const_cast<NameDB*>(&m_groupDb);
} }
}; };
} } // namespace amuse

View File

@ -2,12 +2,10 @@
#include "Common.hpp" #include "Common.hpp"
namespace amuse namespace amuse {
{
/** Simple pointer-container of the four Audio Group chunks */ /** Simple pointer-container of the four Audio Group chunks */
class AudioGroupData class AudioGroupData {
{
friend class Engine; friend class Engine;
protected: protected:
@ -34,9 +32,7 @@ protected:
, m_samp(samp) , m_samp(samp)
, m_sampSz(sampSz) , m_sampSz(sampSz)
, m_fmt(fmt) , m_fmt(fmt)
, m_absOffs(absOffs) , m_absOffs(absOffs) {}
{
}
public: public:
AudioGroupData(unsigned char* proj, size_t projSz, unsigned char* pool, size_t poolSz, unsigned char* sdir, AudioGroupData(unsigned char* proj, size_t projSz, unsigned char* pool, size_t poolSz, unsigned char* sdir,
@ -50,9 +46,7 @@ public:
, m_samp(samp) , m_samp(samp)
, m_sampSz(sampSz) , m_sampSz(sampSz)
, m_fmt(DataFormat::GCN) , m_fmt(DataFormat::GCN)
, m_absOffs(true) , m_absOffs(true) {}
{
}
AudioGroupData(unsigned char* proj, size_t projSz, unsigned char* pool, size_t poolSz, unsigned char* sdir, AudioGroupData(unsigned char* proj, size_t projSz, unsigned char* pool, size_t poolSz, unsigned char* sdir,
size_t sdirSz, unsigned char* samp, size_t sampSz, bool absOffs, N64DataTag) size_t sdirSz, unsigned char* samp, size_t sampSz, bool absOffs, N64DataTag)
: m_proj(proj) : m_proj(proj)
@ -64,9 +58,7 @@ public:
, m_samp(samp) , m_samp(samp)
, m_sampSz(sampSz) , m_sampSz(sampSz)
, m_fmt(DataFormat::N64) , m_fmt(DataFormat::N64)
, m_absOffs(absOffs) , m_absOffs(absOffs) {}
{
}
AudioGroupData(unsigned char* proj, size_t projSz, unsigned char* pool, size_t poolSz, unsigned char* sdir, AudioGroupData(unsigned char* proj, size_t projSz, unsigned char* pool, size_t poolSz, unsigned char* sdir,
size_t sdirSz, unsigned char* samp, size_t sampSz, bool absOffs, PCDataTag) size_t sdirSz, unsigned char* samp, size_t sampSz, bool absOffs, PCDataTag)
: m_proj(proj) : m_proj(proj)
@ -78,9 +70,7 @@ public:
, m_samp(samp) , m_samp(samp)
, m_sampSz(sampSz) , m_sampSz(sampSz)
, m_fmt(DataFormat::PC) , m_fmt(DataFormat::PC)
, m_absOffs(absOffs) , m_absOffs(absOffs) {}
{
}
const unsigned char* getProj() const { return m_proj; } const unsigned char* getProj() const { return m_proj; }
const unsigned char* getPool() const { return m_pool; } const unsigned char* getPool() const { return m_pool; }
@ -104,8 +94,7 @@ public:
}; };
/** A buffer-owning version of AudioGroupData */ /** A buffer-owning version of AudioGroupData */
class IntrusiveAudioGroupData : public AudioGroupData class IntrusiveAudioGroupData : public AudioGroupData {
{
bool m_owns = true; bool m_owns = true;
public: public:
@ -120,5 +109,4 @@ public:
void dangleOwnership() { m_owns = false; } void dangleOwnership() { m_owns = false; }
}; };
} } // namespace amuse

File diff suppressed because it is too large Load Diff

View File

@ -7,23 +7,16 @@
#include <unordered_map> #include <unordered_map>
#include <memory> #include <memory>
namespace amuse namespace amuse {
{
class AudioGroupData; class AudioGroupData;
class AudioGroupPool; class AudioGroupPool;
class AudioGroupSampleDirectory; class AudioGroupSampleDirectory;
enum class GroupType : atUint16 enum class GroupType : atUint16 { Song, SFX };
{
Song,
SFX
};
/** Header at top of project file */ /** Header at top of project file */
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) GroupHeader : BigDNA {
GroupHeader : BigDNA
{
AT_DECL_DNA AT_DECL_DNA
Value<atUint32, DNAEn> groupEndOff; Value<atUint32, DNAEn> groupEndOff;
GroupIdDNA<DNAEn> groupId; GroupIdDNA<DNAEn> groupId;
@ -42,13 +35,10 @@ GroupHeader : BigDNA
struct AudioGroupIndex {}; struct AudioGroupIndex {};
/** Root index of SongGroup */ /** Root index of SongGroup */
struct SongGroupIndex : AudioGroupIndex struct SongGroupIndex : AudioGroupIndex {
{
/** Maps GM program numbers to sound entities */ /** Maps GM program numbers to sound entities */
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) PageEntryDNA : BigDNA {
PageEntryDNA : BigDNA
{
AT_DECL_DNA_YAML AT_DECL_DNA_YAML
PageObjectIdDNA<DNAEn> objId; PageObjectIdDNA<DNAEn> objId;
Value<atUint8> priority; Value<atUint8> priority;
@ -57,9 +47,7 @@ struct SongGroupIndex : AudioGroupIndex
Seek<1, athena::Current> pad; Seek<1, athena::Current> pad;
}; };
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) MusyX1PageEntryDNA : BigDNA {
MusyX1PageEntryDNA : BigDNA
{
AT_DECL_DNA AT_DECL_DNA
PageObjectIdDNA<DNAEn> objId; PageObjectIdDNA<DNAEn> objId;
Value<atUint8> priority; Value<atUint8> priority;
@ -68,8 +56,7 @@ struct SongGroupIndex : AudioGroupIndex
Value<atUint8> programNo; Value<atUint8> programNo;
Seek<2, athena::Current> pad; Seek<2, athena::Current> pad;
}; };
struct PageEntry : BigDNA struct PageEntry : BigDNA {
{
AT_DECL_DNA_YAML AT_DECL_DNA_YAML
PageObjectIdDNA<athena::Big> objId; PageObjectIdDNA<athena::Big> objId;
Value<atUint8> priority = 0; Value<atUint8> priority = 0;
@ -78,16 +65,14 @@ struct SongGroupIndex : AudioGroupIndex
PageEntry() = default; PageEntry() = default;
template <athena::Endian DNAE> template <athena::Endian DNAE>
PageEntry(const PageEntryDNA<DNAE>& in) PageEntry(const PageEntryDNA<DNAE>& in) : objId(in.objId.id), priority(in.priority), maxVoices(in.maxVoices) {}
: objId(in.objId.id), priority(in.priority), maxVoices(in.maxVoices) {}
template <athena::Endian DNAE> template <athena::Endian DNAE>
PageEntry(const MusyX1PageEntryDNA<DNAE>& in) PageEntry(const MusyX1PageEntryDNA<DNAE>& in)
: objId(in.objId.id), priority(in.priority), maxVoices(in.maxVoices) {} : objId(in.objId.id), priority(in.priority), maxVoices(in.maxVoices) {}
template <athena::Endian DNAEn> template <athena::Endian DNAEn>
PageEntryDNA<DNAEn> toDNA(uint8_t programNo) const PageEntryDNA<DNAEn> toDNA(uint8_t programNo) const {
{
PageEntryDNA<DNAEn> ret; PageEntryDNA<DNAEn> ret;
ret.objId = objId; ret.objId = objId;
ret.priority = priority; ret.priority = priority;
@ -100,8 +85,7 @@ struct SongGroupIndex : AudioGroupIndex
std::unordered_map<uint8_t, PageEntry> m_drumPages; std::unordered_map<uint8_t, PageEntry> m_drumPages;
/** Maps SongID to 16 MIDI channel numbers to GM program numbers and settings */ /** Maps SongID to 16 MIDI channel numbers to GM program numbers and settings */
struct MusyX1MIDISetup : BigDNA struct MusyX1MIDISetup : BigDNA {
{
AT_DECL_DNA_YAML AT_DECL_DNA_YAML
Value<atUint8> programNo; Value<atUint8> programNo;
Value<atUint8> volume; Value<atUint8> volume;
@ -110,8 +94,7 @@ struct SongGroupIndex : AudioGroupIndex
Value<atUint8> chorus; Value<atUint8> chorus;
Seek<3, athena::Current> pad; Seek<3, athena::Current> pad;
}; };
struct MIDISetup : BigDNA struct MIDISetup : BigDNA {
{
AT_DECL_DNA_YAML AT_DECL_DNA_YAML
Value<atUint8> programNo = 0; Value<atUint8> programNo = 0;
Value<atUint8> volume = 127; Value<atUint8> volume = 127;
@ -120,8 +103,11 @@ struct SongGroupIndex : AudioGroupIndex
Value<atUint8> chorus = 0; Value<atUint8> chorus = 0;
MIDISetup() = default; MIDISetup() = default;
MIDISetup(const MusyX1MIDISetup& setup) MIDISetup(const MusyX1MIDISetup& setup)
: programNo(setup.programNo), volume(setup.volume), panning(setup.panning), : programNo(setup.programNo)
reverb(setup.reverb), chorus(setup.chorus) {} , volume(setup.volume)
, panning(setup.panning)
, reverb(setup.reverb)
, chorus(setup.chorus) {}
}; };
std::unordered_map<SongId, std::array<MIDISetup, 16>> m_midiSetups; std::unordered_map<SongId, std::array<MIDISetup, 16>> m_midiSetups;
@ -130,13 +116,10 @@ struct SongGroupIndex : AudioGroupIndex
}; };
/** Root index of SFXGroup */ /** Root index of SFXGroup */
struct SFXGroupIndex : AudioGroupIndex struct SFXGroupIndex : AudioGroupIndex {
{
/** Maps game-side SFX define IDs to sound entities */ /** Maps game-side SFX define IDs to sound entities */
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) SFXEntryDNA : BigDNA {
SFXEntryDNA : BigDNA
{
AT_DECL_DNA AT_DECL_DNA
SFXIdDNA<DNAEn> sfxId; SFXIdDNA<DNAEn> sfxId;
PageObjectIdDNA<DNAEn> objId; PageObjectIdDNA<DNAEn> objId;
@ -147,8 +130,7 @@ struct SFXGroupIndex : AudioGroupIndex
Value<atUint8> defKey; Value<atUint8> defKey;
Seek<1, athena::Current> pad; Seek<1, athena::Current> pad;
}; };
struct SFXEntry : BigDNA struct SFXEntry : BigDNA {
{
AT_DECL_DNA_YAML AT_DECL_DNA_YAML
PageObjectIdDNA<athena::Big> objId; PageObjectIdDNA<athena::Big> objId;
Value<atUint8> priority = 0; Value<atUint8> priority = 0;
@ -161,12 +143,15 @@ struct SFXGroupIndex : AudioGroupIndex
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), : objId(in.objId.id)
defVel(in.defVel), panning(in.panning), defKey(in.defKey) {} , priority(in.priority)
, maxVoices(in.maxVoices)
, defVel(in.defVel)
, panning(in.panning)
, defKey(in.defKey) {}
template <athena::Endian DNAEn> template <athena::Endian DNAEn>
SFXEntryDNA<DNAEn> toDNA(SFXId id) const SFXEntryDNA<DNAEn> toDNA(SFXId id) const {
{
SFXEntryDNA<DNAEn> ret; SFXEntryDNA<DNAEn> ret;
ret.sfxId.id = id; ret.sfxId.id = id;
ret.objId = objId; ret.objId = objId;
@ -188,8 +173,7 @@ struct SFXGroupIndex : AudioGroupIndex
}; };
/** Collection of SongGroup and SFXGroup indexes */ /** Collection of SongGroup and SFXGroup indexes */
class AudioGroupProject class AudioGroupProject {
{
std::unordered_map<GroupId, ObjToken<SongGroupIndex>> m_songGroups; std::unordered_map<GroupId, ObjToken<SongGroupIndex>> m_songGroups;
std::unordered_map<GroupId, ObjToken<SFXGroupIndex>> m_sfxGroups; std::unordered_map<GroupId, ObjToken<SFXGroupIndex>> m_sfxGroups;
@ -200,6 +184,7 @@ class AudioGroupProject
static void BootstrapObjectIDs(athena::io::IStreamReader& r, GCNDataTag); static void BootstrapObjectIDs(athena::io::IStreamReader& r, GCNDataTag);
template <athena::Endian DNAE> template <athena::Endian DNAE>
static void BootstrapObjectIDs(athena::io::IStreamReader& r, bool absOffs); static void BootstrapObjectIDs(athena::io::IStreamReader& r, bool absOffs);
public: public:
AudioGroupProject() = default; AudioGroupProject() = default;
static AudioGroupProject CreateAudioGroupProject(const AudioGroupData& data); static AudioGroupProject CreateAudioGroupProject(const AudioGroupData& data);
@ -223,5 +208,4 @@ public:
AudioGroupProject(AudioGroupProject&&) = default; AudioGroupProject(AudioGroupProject&&) = default;
AudioGroupProject& operator=(AudioGroupProject&&) = default; AudioGroupProject& operator=(AudioGroupProject&&) = default;
}; };
} } // namespace amuse

View File

@ -4,13 +4,11 @@
#include <cstdint> #include <cstdint>
#include "Common.hpp" #include "Common.hpp"
namespace amuse namespace amuse {
{
class AudioGroupData; class AudioGroupData;
class AudioGroupDatabase; class AudioGroupDatabase;
struct DSPADPCMHeader : BigDNA struct DSPADPCMHeader : BigDNA {
{
AT_DECL_DNA AT_DECL_DNA
Value<atUint32> x0_num_samples; Value<atUint32> x0_num_samples;
Value<atUint32> x4_num_nibbles; Value<atUint32> x4_num_nibbles;
@ -32,8 +30,7 @@ struct DSPADPCMHeader : BigDNA
Seek<21, athena::Current> pad; Seek<21, athena::Current> pad;
}; };
struct VADPCMHeader : BigDNA struct VADPCMHeader : BigDNA {
{
AT_DECL_DNA AT_DECL_DNA
Value<uint32_t> m_pitchSampleRate; Value<uint32_t> m_pitchSampleRate;
Value<uint32_t> m_numSamples; Value<uint32_t> m_numSamples;
@ -41,8 +38,7 @@ struct VADPCMHeader : BigDNA
Value<uint32_t> m_loopLengthSamples; Value<uint32_t> m_loopLengthSamples;
}; };
struct WAVFormatChunk : LittleDNA struct WAVFormatChunk : LittleDNA {
{
AT_DECL_DNA AT_DECL_DNA
Value<atUint16> sampleFmt = 1; Value<atUint16> sampleFmt = 1;
Value<atUint16> numChannels = 1; Value<atUint16> numChannels = 1;
@ -52,8 +48,7 @@ struct WAVFormatChunk : LittleDNA
Value<atUint16> bitsPerSample = 16; Value<atUint16> bitsPerSample = 16;
}; };
struct WAVSampleChunk : LittleDNA struct WAVSampleChunk : LittleDNA {
{
AT_DECL_DNA AT_DECL_DNA
Value<atUint32> smplManufacturer = 0; Value<atUint32> smplManufacturer = 0;
Value<atUint32> smplProduct = 0; Value<atUint32> smplProduct = 0;
@ -66,8 +61,7 @@ struct WAVSampleChunk : LittleDNA
Value<atUint32> additionalDataSize = 0; Value<atUint32> additionalDataSize = 0;
}; };
struct WAVSampleLoop : LittleDNA struct WAVSampleLoop : LittleDNA {
{
AT_DECL_DNA AT_DECL_DNA
Value<atUint32> cuePointId = 0; Value<atUint32> cuePointId = 0;
Value<atUint32> loopType = 0; // 0: forward loop Value<atUint32> loopType = 0; // 0: forward loop
@ -77,8 +71,7 @@ struct WAVSampleLoop : LittleDNA
Value<atUint32> playCount = 0; Value<atUint32> playCount = 0;
}; };
struct WAVHeader : LittleDNA struct WAVHeader : LittleDNA {
{
AT_DECL_DNA AT_DECL_DNA
Value<atUint32> riffMagic = SBIG('RIFF'); Value<atUint32> riffMagic = SBIG('RIFF');
Value<atUint32> wavChuckSize; // everything - 8 Value<atUint32> wavChuckSize; // everything - 8
@ -96,8 +89,7 @@ struct WAVHeader : LittleDNA
Value<atUint32> dataChunkSize; // numSamples * numChannels * bitsPerSample/8 Value<atUint32> dataChunkSize; // numSamples * numChannels * bitsPerSample/8
}; };
struct WAVHeaderLoop : LittleDNA struct WAVHeaderLoop : LittleDNA {
{
AT_DECL_DNA AT_DECL_DNA
Value<atUint32> riffMagic = SBIG('RIFF'); Value<atUint32> riffMagic = SBIG('RIFF');
Value<atUint32> wavChuckSize; // everything - 8 Value<atUint32> wavChuckSize; // everything - 8
@ -116,17 +108,16 @@ struct WAVHeaderLoop : LittleDNA
Value<atUint32> dataChunkSize; // numSamples * numChannels * bitsPerSample/8 Value<atUint32> dataChunkSize; // numSamples * numChannels * bitsPerSample/8
}; };
enum class SampleFormat : uint8_t enum class SampleFormat : uint8_t {
{
DSP, /**< GCN DSP-ucode ADPCM (very common for GameCube games) */ DSP, /**< GCN DSP-ucode ADPCM (very common for GameCube games) */
DSP_DRUM, /**< GCN DSP-ucode ADPCM (seems to be set into drum samples for expanding their amplitude appropriately) */ DSP_DRUM, /**< GCN DSP-ucode ADPCM (seems to be set into drum samples for expanding their amplitude appropriately)
*/
PCM, /**< Big-endian PCM found in MusyX2 demo GM instruments */ PCM, /**< Big-endian PCM found in MusyX2 demo GM instruments */
N64, /**< 2-stage VADPCM coding with SAMP-embedded codebooks */ N64, /**< 2-stage VADPCM coding with SAMP-embedded codebooks */
PCM_PC /**< Little-endian PCM found in PC Rogue Squadron (actually enum 0 which conflicts with DSP-ADPCM) */ PCM_PC /**< Little-endian PCM found in PC Rogue Squadron (actually enum 0 which conflicts with DSP-ADPCM) */
}; };
enum class SampleFileState enum class SampleFileState {
{
NoData, NoData,
MemoryOnlyWAV, MemoryOnlyWAV,
MemoryOnlyCompressed, MemoryOnlyCompressed,
@ -137,14 +128,12 @@ enum class SampleFileState
}; };
/** Indexes individual samples in SAMP chunk */ /** Indexes individual samples in SAMP chunk */
class AudioGroupSampleDirectory class AudioGroupSampleDirectory {
{
friend class AudioGroup; friend class AudioGroup;
public: public:
union ADPCMParms { union ADPCMParms {
struct DSPParms struct DSPParms {
{
uint16_t m_bytesPerFrame; uint16_t m_bytesPerFrame;
uint8_t m_ps; uint8_t m_ps;
uint8_t m_lps; uint8_t m_lps;
@ -152,8 +141,7 @@ public:
int16_t m_hist1; int16_t m_hist1;
int16_t m_coefs[8][2]; int16_t m_coefs[8][2];
} dsp; } dsp;
struct VADPCMParms struct VADPCMParms {
{
int16_t m_coefs[8][2][8]; int16_t m_coefs[8][2][8];
} vadpcm; } vadpcm;
void swapBigDSP(); void swapBigDSP();
@ -161,9 +149,7 @@ public:
}; };
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) EntryDNA : BigDNA {
EntryDNA : BigDNA
{
AT_DECL_DNA AT_DECL_DNA
SampleIdDNA<DNAEn> m_sfxId; SampleIdDNA<DNAEn> m_sfxId;
Seek<2, athena::Current> pad; Seek<2, athena::Current> pad;
@ -177,20 +163,14 @@ public:
Value<atUint32, DNAEn> m_loopLengthSamples; Value<atUint32, DNAEn> m_loopLengthSamples;
Value<atUint32, DNAEn> m_adpcmParmOffset; Value<atUint32, DNAEn> m_adpcmParmOffset;
void _setLoopStartSample(atUint32 sample) void _setLoopStartSample(atUint32 sample) {
{
m_loopLengthSamples += m_loopStartSample - sample; m_loopLengthSamples += m_loopStartSample - sample;
m_loopStartSample = sample; m_loopStartSample = sample;
} }
void setLoopEndSample(atUint32 sample) void setLoopEndSample(atUint32 sample) { m_loopLengthSamples = sample + 1 - m_loopStartSample; }
{
m_loopLengthSamples = sample + 1 - m_loopStartSample;
}
}; };
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) MusyX1SdirEntry : BigDNA {
MusyX1SdirEntry : BigDNA
{
AT_DECL_DNA AT_DECL_DNA
SampleIdDNA<DNAEn> m_sfxId; SampleIdDNA<DNAEn> m_sfxId;
Seek<2, athena::Current> pad; Seek<2, athena::Current> pad;
@ -201,9 +181,7 @@ public:
Value<atUint32, DNAEn> m_loopLengthSamples; Value<atUint32, DNAEn> m_loopLengthSamples;
}; };
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) MusyX1AbsSdirEntry : BigDNA {
MusyX1AbsSdirEntry : BigDNA
{
AT_DECL_DNA AT_DECL_DNA
SampleIdDNA<DNAEn> m_sfxId; SampleIdDNA<DNAEn> m_sfxId;
Seek<2, athena::Current> pad; Seek<2, athena::Current> pad;
@ -214,8 +192,7 @@ public:
Value<uint32_t, DNAEn> m_loopStartSample; Value<uint32_t, DNAEn> m_loopStartSample;
Value<uint32_t, DNAEn> m_loopLengthSamples; Value<uint32_t, DNAEn> m_loopLengthSamples;
}; };
struct EntryData struct EntryData {
{
atUint32 m_sampleOff = 0; atUint32 m_sampleOff = 0;
atUint32 m_unk = 0; atUint32 m_unk = 0;
atUint8 m_pitch = 0; atUint8 m_pitch = 0;
@ -238,59 +215,59 @@ public:
atUint8 getPitch() const { return m_pitch == 0 ? atUint8(60) : m_pitch; } atUint8 getPitch() const { return m_pitch == 0 ? atUint8(60) : m_pitch; }
atUint32 getNumSamples() const { return m_numSamples & 0xffffff; } atUint32 getNumSamples() const { return m_numSamples & 0xffffff; }
SampleFormat getSampleFormat() const { return SampleFormat(m_numSamples >> 24); } SampleFormat getSampleFormat() const { return SampleFormat(m_numSamples >> 24); }
bool isFormatDSP() const bool isFormatDSP() const {
{
SampleFormat fmt = getSampleFormat(); SampleFormat fmt = getSampleFormat();
return fmt == SampleFormat::DSP || fmt == SampleFormat::DSP_DRUM; return fmt == SampleFormat::DSP || fmt == SampleFormat::DSP_DRUM;
} }
bool isLooped() const { return m_loopLengthSamples != 0 && m_loopStartSample != 0xffffffff; } bool isLooped() const { return m_loopLengthSamples != 0 && m_loopStartSample != 0xffffffff; }
void _setLoopStartSample(atUint32 sample) void _setLoopStartSample(atUint32 sample) {
{
m_loopLengthSamples += m_loopStartSample - sample; m_loopLengthSamples += m_loopStartSample - sample;
m_loopStartSample = sample; m_loopStartSample = sample;
} }
void setLoopStartSample(atUint32 sample); void setLoopStartSample(atUint32 sample);
atUint32 getLoopStartSample() const atUint32 getLoopStartSample() const { return m_loopStartSample; }
{ void setLoopEndSample(atUint32 sample) { m_loopLengthSamples = sample + 1 - m_loopStartSample; }
return m_loopStartSample; atUint32 getLoopEndSample() const { return m_loopStartSample + m_loopLengthSamples - 1; }
}
void setLoopEndSample(atUint32 sample)
{
m_loopLengthSamples = sample + 1 - m_loopStartSample;
}
atUint32 getLoopEndSample() const
{
return m_loopStartSample + m_loopLengthSamples - 1;
}
EntryData() = default; EntryData() = default;
template <athena::Endian DNAE> template <athena::Endian DNAE>
EntryData(const EntryDNA<DNAE>& in) EntryData(const EntryDNA<DNAE>& in)
: m_sampleOff(in.m_sampleOff), m_unk(in.m_unk), m_pitch(in.m_pitch), : m_sampleOff(in.m_sampleOff)
m_sampleRate(in.m_sampleRate), m_numSamples(in.m_numSamples), , m_unk(in.m_unk)
m_loopStartSample(in.m_loopStartSample), m_loopLengthSamples(in.m_loopLengthSamples), , m_pitch(in.m_pitch)
m_adpcmParmOffset(in.m_adpcmParmOffset) {} , 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> template <athena::Endian DNAE>
EntryData(const MusyX1SdirEntry<DNAE>& in) EntryData(const MusyX1SdirEntry<DNAE>& in)
: m_sampleOff(in.m_sampleOff), m_unk(0), m_pitch(in.m_pitchSampleRate >> 24), : m_sampleOff(in.m_sampleOff)
m_sampleRate(in.m_pitchSampleRate & 0xffff), m_numSamples(in.m_numSamples), , m_unk(0)
m_loopStartSample(in.m_loopStartSample), m_loopLengthSamples(in.m_loopLengthSamples), , m_pitch(in.m_pitchSampleRate >> 24)
m_adpcmParmOffset(0) {} , 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> template <athena::Endian DNAE>
EntryData(const MusyX1AbsSdirEntry<DNAE>& in) EntryData(const MusyX1AbsSdirEntry<DNAE>& in)
: m_sampleOff(in.m_sampleOff), m_unk(in.m_unk), m_pitch(in.m_pitchSampleRate >> 24), : m_sampleOff(in.m_sampleOff)
m_sampleRate(in.m_pitchSampleRate & 0xffff), m_numSamples(in.m_numSamples), , m_unk(in.m_unk)
m_loopStartSample(in.m_loopStartSample), m_loopLengthSamples(in.m_loopLengthSamples), , m_pitch(in.m_pitchSampleRate >> 24)
m_adpcmParmOffset(0) {} , 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> template <athena::Endian DNAEn>
EntryDNA<DNAEn> toDNA(SFXId id) const EntryDNA<DNAEn> toDNA(SFXId id) const {
{
EntryDNA<DNAEn> ret; EntryDNA<DNAEn> ret;
ret.m_sfxId.id = id; ret.m_sfxId.id = id;
ret.m_sampleOff = m_sampleOff; ret.m_sampleOff = m_sampleOff;
@ -315,28 +292,22 @@ public:
/* This double-wrapper allows Voices to keep a strong reference on /* This double-wrapper allows Voices to keep a strong reference on
* a single instance of loaded loose data without being unexpectedly * a single instance of loaded loose data without being unexpectedly
* clobbered */ * clobbered */
struct Entry struct Entry {
{
ObjToken<EntryData> m_data; ObjToken<EntryData> m_data;
Entry() Entry() : m_data(MakeObj<EntryData>()) {}
: m_data(MakeObj<EntryData>()) {}
template <athena::Endian DNAE> template <athena::Endian DNAE>
Entry(const EntryDNA<DNAE>& in) Entry(const EntryDNA<DNAE>& in) : m_data(MakeObj<EntryData>(in)) {}
: m_data(MakeObj<EntryData>(in)) {}
template <athena::Endian DNAE> template <athena::Endian DNAE>
Entry(const MusyX1SdirEntry<DNAE>& in) Entry(const MusyX1SdirEntry<DNAE>& in) : m_data(MakeObj<EntryData>(in)) {}
: m_data(MakeObj<EntryData>(in)) {}
template <athena::Endian DNAE> template <athena::Endian DNAE>
Entry(const MusyX1AbsSdirEntry<DNAE>& in) Entry(const MusyX1AbsSdirEntry<DNAE>& in) : m_data(MakeObj<EntryData>(in)) {}
: m_data(MakeObj<EntryData>(in)) {}
template <athena::Endian DNAEn> template <athena::Endian DNAEn>
EntryDNA<DNAEn> toDNA(SFXId id) const EntryDNA<DNAEn> toDNA(SFXId id) const {
{
return m_data->toDNA<DNAEn>(id); return m_data->toDNA<DNAEn>(id);
} }
@ -380,5 +351,4 @@ public:
using SampleEntry = AudioGroupSampleDirectory::Entry; using SampleEntry = AudioGroupSampleDirectory::Entry;
using SampleEntryData = AudioGroupSampleDirectory::EntryData; using SampleEntryData = AudioGroupSampleDirectory::EntryData;
} } // namespace amuse

View File

@ -10,16 +10,13 @@
#include <mutex> #include <mutex>
#include <list> #include <list>
namespace amuse namespace amuse {
{
/** Backend voice implementation for boo mixer */ /** Backend voice implementation for boo mixer */
class BooBackendVoice : public IBackendVoice class BooBackendVoice : public IBackendVoice {
{
friend class BooBackendVoiceAllocator; friend class BooBackendVoiceAllocator;
Voice& m_clientVox; Voice& m_clientVox;
struct VoiceCallback : boo::IAudioVoiceCallback struct VoiceCallback : boo::IAudioVoiceCallback {
{
BooBackendVoice& m_parent; BooBackendVoice& m_parent;
void preSupplyAudio(boo::IAudioVoice& voice, double dt); void preSupplyAudio(boo::IAudioVoice& voice, double dt);
size_t supplyAudio(boo::IAudioVoice& voice, size_t frames, int16_t* data); size_t supplyAudio(boo::IAudioVoice& voice, size_t frames, int16_t* data);
@ -42,13 +39,11 @@ public:
}; };
/** Backend submix implementation for boo mixer */ /** Backend submix implementation for boo mixer */
class BooBackendSubmix : public IBackendSubmix class BooBackendSubmix : public IBackendSubmix {
{
friend class BooBackendVoiceAllocator; friend class BooBackendVoiceAllocator;
friend class BooBackendVoice; friend class BooBackendVoice;
Submix& m_clientSmx; Submix& m_clientSmx;
struct SubmixCallback : boo::IAudioSubmixCallback struct SubmixCallback : boo::IAudioSubmixCallback {
{
BooBackendSubmix& m_parent; BooBackendSubmix& m_parent;
bool canApplyEffect() const; bool canApplyEffect() const;
void applyEffect(int16_t* audio, size_t frameCount, const boo::ChannelMap& chanMap, double sampleRate) const; void applyEffect(int16_t* audio, size_t frameCount, const boo::ChannelMap& chanMap, double sampleRate) const;
@ -67,9 +62,9 @@ public:
}; };
/** Backend MIDI event reader for controlling sequencer with external hardware / software */ /** Backend MIDI event reader for controlling sequencer with external hardware / software */
class BooBackendMIDIReader : public IMIDIReader, public boo::IMIDIReader class BooBackendMIDIReader : public IMIDIReader, public boo::IMIDIReader {
{
friend class BooBackendVoiceAllocator; friend class BooBackendVoiceAllocator;
protected: protected:
Engine& m_engine; Engine& m_engine;
std::unordered_map<std::string, std::unique_ptr<boo::IMIDIIn>> m_midiIns; std::unordered_map<std::string, std::unique_ptr<boo::IMIDIIn>> m_midiIns;
@ -122,9 +117,9 @@ public:
}; };
/** Backend voice allocator implementation for boo mixer */ /** Backend voice allocator implementation for boo mixer */
class BooBackendVoiceAllocator : public IBackendVoiceAllocator, public boo::IAudioVoiceEngineCallback class BooBackendVoiceAllocator : public IBackendVoiceAllocator, public boo::IAudioVoiceEngineCallback {
{
friend class BooBackendMIDIReader; friend class BooBackendMIDIReader;
protected: protected:
boo::IAudioVoiceEngine& m_booEngine; boo::IAudioVoiceEngine& m_booEngine;
Engine* m_cbInterface = nullptr; Engine* m_cbInterface = nullptr;
@ -141,5 +136,4 @@ public:
void on5MsInterval(boo::IAudioVoiceEngine& engine, double dt); void on5MsInterval(boo::IAudioVoiceEngine& engine, double dt);
void onPumpCycleComplete(boo::IAudioVoiceEngine& engine); void onPumpCycleComplete(boo::IAudioVoiceEngine& engine);
}; };
} } // namespace amuse

View File

@ -35,8 +35,7 @@
constexpr float NativeSampleRate = 32000.0f; constexpr float NativeSampleRate = 32000.0f;
namespace amuse namespace amuse {
{
struct NameDB; struct NameDB;
using BigDNA = athena::io::DNA<athena::Big>; using BigDNA = athena::io::DNA<athena::Big>;
@ -46,19 +45,19 @@ using LittleDNAV = athena::io::DNAVYaml<athena::Little>;
/** Common ID structure statically tagging /** Common ID structure statically tagging
* SoundMacros, Tables, Keymaps, Layers, Samples, SFX, Songs */ * SoundMacros, Tables, Keymaps, Layers, Samples, SFX, Songs */
struct ObjectId struct ObjectId {
{
uint16_t id = 0xffff; uint16_t id = 0xffff;
operator uint16_t() const { return id; } operator uint16_t() const { return id; }
ObjectId() = default; ObjectId() = default;
ObjectId(uint16_t idIn) : id(idIn) {} ObjectId(uint16_t idIn) : id(idIn) {}
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
{
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);
@ -69,17 +68,14 @@ ObjectIdDNA : BigDNA
}; };
#define DECL_ID_TYPE(type) \ #define DECL_ID_TYPE(type) \
struct type : ObjectId \ struct type : ObjectId { \
{ \
using ObjectId::ObjectId; \ using ObjectId::ObjectId; \
type() = default; \ type() = default; \
type(const ObjectId& id) : ObjectId(id) {} \ type(const ObjectId& id) : ObjectId(id) {} \
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) type##DNA : BigDNA { \
type##DNA : 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); \
@ -87,7 +83,7 @@ type##DNA : BigDNA \
type##DNA() = default; \ type##DNA() = default; \
type##DNA(type idIn) : id(idIn) {} \ type##DNA(type idIn) : id(idIn) {} \
operator type() const { return id; } \ operator type() const { return id; } \
}; };
DECL_ID_TYPE(SoundMacroId) DECL_ID_TYPE(SoundMacroId)
DECL_ID_TYPE(SampleId) DECL_ID_TYPE(SampleId)
DECL_ID_TYPE(TableId) DECL_ID_TYPE(TableId)
@ -101,9 +97,7 @@ DECL_ID_TYPE(GroupId)
* referenced by a song group's page object. When the upper bit is set, * referenced by a song group's page object. When the upper bit is set,
* this indicates a layer type. */ * 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) PageObjectIdDNA : 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);
@ -113,19 +107,19 @@ PageObjectIdDNA : BigDNA
operator ObjectId() const { return id; } operator ObjectId() const { return id; }
}; };
struct SoundMacroStep struct SoundMacroStep {
{
uint16_t step = 0; uint16_t step = 0;
operator uint16_t() const { return step; } operator uint16_t() const { return step; }
SoundMacroStep() = default; SoundMacroStep() = default;
SoundMacroStep(uint16_t idIn) : step(idIn) {} SoundMacroStep(uint16_t idIn) : step(idIn) {}
SoundMacroStep& operator=(uint16_t idIn) { step = idIn; return *this; } SoundMacroStep& operator=(uint16_t idIn) {
step = idIn;
return *this;
}
}; };
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) SoundMacroStepDNA : BigDNA {
SoundMacroStepDNA : BigDNA
{
AT_DECL_EXPLICIT_DNA_YAML AT_DECL_EXPLICIT_DNA_YAML
SoundMacroStep step; SoundMacroStep step;
SoundMacroStepDNA() = default; SoundMacroStepDNA() = default;
@ -133,34 +127,36 @@ SoundMacroStepDNA : BigDNA
operator SoundMacroStep() const { return step; } operator SoundMacroStep() const { return step; }
}; };
struct LittleUInt24 : LittleDNA struct LittleUInt24 : LittleDNA {
{
AT_DECL_EXPLICIT_DNA_YAML AT_DECL_EXPLICIT_DNA_YAML
atUint32 val; atUint32 val;
operator uint32_t() const { return val; } operator uint32_t() const { return val; }
LittleUInt24() = default; LittleUInt24() = default;
LittleUInt24(uint32_t valIn) : val(valIn) {} LittleUInt24(uint32_t valIn) : val(valIn) {}
LittleUInt24& operator=(uint32_t valIn) { val = valIn; return *this; } LittleUInt24& operator=(uint32_t valIn) {
val = valIn;
return *this;
}
}; };
class IObj class IObj {
{
std::atomic_int m_refCount = {0}; std::atomic_int m_refCount = {0};
protected: protected:
virtual ~IObj() = default; virtual ~IObj() = default;
public: public:
void increment() { m_refCount++; } void increment() { m_refCount++; }
void decrement() void decrement() {
{
if (m_refCount.fetch_sub(1) == 1) if (m_refCount.fetch_sub(1) == 1)
delete this; delete this;
} }
}; };
template<class SubCls> template <class SubCls>
class ObjWrapper : public IObj class ObjWrapper : public IObj {
{
SubCls m_obj; SubCls m_obj;
public: public:
template <class... _Args> template <class... _Args>
ObjWrapper(_Args&&... args) : m_obj(std::forward<_Args>(args)...) {} ObjWrapper(_Args&&... args) : m_obj(std::forward<_Args>(args)...) {}
@ -168,92 +164,136 @@ public:
const SubCls* get() const { return &m_obj; } const SubCls* get() const { return &m_obj; }
}; };
template<class SubCls> template <class SubCls>
class ObjTokenBase class ObjTokenBase {
{
protected: protected:
IObj* m_obj = nullptr; IObj* m_obj = nullptr;
ObjTokenBase(IObj* obj) : m_obj(obj) { if (m_obj) m_obj->increment(); } ObjTokenBase(IObj* obj) : m_obj(obj) {
if (m_obj)
m_obj->increment();
}
public: public:
ObjTokenBase() = default; ObjTokenBase() = default;
ObjTokenBase(const ObjTokenBase& other) : m_obj(other.m_obj) { if (m_obj) m_obj->increment(); } ObjTokenBase(const ObjTokenBase& other) : m_obj(other.m_obj) {
if (m_obj)
m_obj->increment();
}
ObjTokenBase(ObjTokenBase&& other) : m_obj(other.m_obj) { other.m_obj = nullptr; } ObjTokenBase(ObjTokenBase&& other) : m_obj(other.m_obj) { other.m_obj = nullptr; }
ObjTokenBase& operator=(const ObjTokenBase& other) ObjTokenBase& operator=(const ObjTokenBase& other) {
{ if (m_obj) m_obj->decrement(); m_obj = other.m_obj; if (m_obj) m_obj->increment(); return *this; } if (m_obj)
ObjTokenBase& operator=(ObjTokenBase&& other) m_obj->decrement();
{ if (m_obj) m_obj->decrement(); m_obj = other.m_obj; other.m_obj = nullptr; return *this; } m_obj = other.m_obj;
~ObjTokenBase() { if (m_obj) m_obj->decrement(); } if (m_obj)
m_obj->increment();
return *this;
}
ObjTokenBase& operator=(ObjTokenBase&& other) {
if (m_obj)
m_obj->decrement();
m_obj = other.m_obj;
other.m_obj = nullptr;
return *this;
}
~ObjTokenBase() {
if (m_obj)
m_obj->decrement();
}
bool operator==(const ObjTokenBase& other) const { return m_obj == other.m_obj; } bool operator==(const ObjTokenBase& other) const { return m_obj == other.m_obj; }
bool operator!=(const ObjTokenBase& other) const { return m_obj != other.m_obj; } bool operator!=(const ObjTokenBase& other) const { return m_obj != other.m_obj; }
bool operator<(const ObjTokenBase& other) const { return m_obj < other.m_obj; } bool operator<(const ObjTokenBase& other) const { return m_obj < other.m_obj; }
bool operator>(const ObjTokenBase& other) const { return m_obj > other.m_obj; } bool operator>(const ObjTokenBase& other) const { return m_obj > other.m_obj; }
operator bool() const { return m_obj != nullptr; } operator bool() const { return m_obj != nullptr; }
void reset() { if (m_obj) m_obj->decrement(); m_obj = nullptr; } void reset() {
if (m_obj)
m_obj->decrement();
m_obj = nullptr;
}
}; };
template<class SubCls, class Enable = void> template <class SubCls, class Enable = void>
class ObjToken : public ObjTokenBase<SubCls> class ObjToken : public ObjTokenBase<SubCls> {
{
IObj*& _obj() { return ObjTokenBase<SubCls>::m_obj; } IObj*& _obj() { return ObjTokenBase<SubCls>::m_obj; }
IObj*const& _obj() const { return ObjTokenBase<SubCls>::m_obj; } IObj* const& _obj() const { return ObjTokenBase<SubCls>::m_obj; }
public: public:
using ObjTokenBase<SubCls>::ObjTokenBase; using ObjTokenBase<SubCls>::ObjTokenBase;
ObjToken() = default; ObjToken() = default;
ObjToken(ObjWrapper<SubCls>* obj) : ObjTokenBase<SubCls>(obj) {} ObjToken(ObjWrapper<SubCls>* obj) : ObjTokenBase<SubCls>(obj) {}
ObjToken& operator=(ObjWrapper<SubCls>* obj) ObjToken& operator=(ObjWrapper<SubCls>* obj) {
{ if (_obj()) _obj()->decrement(); _obj() = obj; if (_obj()) _obj()->increment(); return *this; } if (_obj())
_obj()->decrement();
_obj() = obj;
if (_obj())
_obj()->increment();
return *this;
}
SubCls* get() const { return static_cast<ObjWrapper<SubCls>*>(_obj())->get(); } SubCls* get() const { return static_cast<ObjWrapper<SubCls>*>(_obj())->get(); }
SubCls* operator->() const { return get(); } SubCls* operator->() const { return get(); }
SubCls& operator*() const { return *get(); } SubCls& operator*() const { return *get(); }
}; };
template<class SubCls> template <class SubCls>
class ObjToken<SubCls, typename std::enable_if_t<std::is_base_of_v<IObj, SubCls>>> : public ObjTokenBase<SubCls> class ObjToken<SubCls, typename std::enable_if_t<std::is_base_of_v<IObj, SubCls>>> : public ObjTokenBase<SubCls> {
{
IObj*& _obj() { return ObjTokenBase<SubCls>::m_obj; } IObj*& _obj() { return ObjTokenBase<SubCls>::m_obj; }
IObj*const& _obj() const { return ObjTokenBase<SubCls>::m_obj; } IObj* const& _obj() const { return ObjTokenBase<SubCls>::m_obj; }
public: public:
using ObjTokenBase<SubCls>::ObjTokenBase; using ObjTokenBase<SubCls>::ObjTokenBase;
ObjToken() = default; ObjToken() = default;
ObjToken(IObj* obj) : ObjTokenBase<SubCls>(obj) {} ObjToken(IObj* obj) : ObjTokenBase<SubCls>(obj) {}
ObjToken& operator=(IObj* obj) ObjToken& operator=(IObj* obj) {
{ if (_obj()) _obj()->decrement(); _obj() = obj; if (_obj()) _obj()->increment(); return *this; } if (_obj())
_obj()->decrement();
_obj() = obj;
if (_obj())
_obj()->increment();
return *this;
}
SubCls* get() const { return static_cast<SubCls*>(_obj()); } SubCls* get() const { return static_cast<SubCls*>(_obj()); }
SubCls* operator->() const { return get(); } SubCls* operator->() const { return get(); }
SubCls& operator*() const { return *get(); } SubCls& operator*() const { return *get(); }
template <class T> template <class T>
T* cast() const { return static_cast<T*>(_obj()); } T* cast() const {
return static_cast<T*>(_obj());
}
}; };
/* ONLY USE WITH CLASSES DERIVED FROM IOBJ! /* ONLY USE WITH CLASSES DERIVED FROM IOBJ!
* Bypasses type_traits tests for incomplete type definitions. */ * Bypasses type_traits tests for incomplete type definitions. */
template<class SubCls> template <class SubCls>
class IObjToken : public ObjTokenBase<SubCls> class IObjToken : public ObjTokenBase<SubCls> {
{
IObj*& _obj() { return ObjTokenBase<SubCls>::m_obj; } IObj*& _obj() { return ObjTokenBase<SubCls>::m_obj; }
IObj*const& _obj() const { return ObjTokenBase<SubCls>::m_obj; } IObj* const& _obj() const { return ObjTokenBase<SubCls>::m_obj; }
public: public:
using ObjTokenBase<SubCls>::ObjTokenBase; using ObjTokenBase<SubCls>::ObjTokenBase;
IObjToken() = default; IObjToken() = default;
IObjToken(IObj* obj) : ObjTokenBase<SubCls>(obj) {} IObjToken(IObj* obj) : ObjTokenBase<SubCls>(obj) {}
IObjToken& operator=(IObj* obj) IObjToken& operator=(IObj* obj) {
{ if (_obj()) _obj()->decrement(); _obj() = obj; if (_obj()) _obj()->increment(); return *this; } if (_obj())
_obj()->decrement();
_obj() = obj;
if (_obj())
_obj()->increment();
return *this;
}
SubCls* get() const { return static_cast<SubCls*>(_obj()); } SubCls* get() const { return static_cast<SubCls*>(_obj()); }
SubCls* operator->() const { return get(); } SubCls* operator->() const { return get(); }
SubCls& operator*() const { return *get(); } SubCls& operator*() const { return *get(); }
template <class T> template <class T>
T* cast() const { return static_cast<T*>(_obj()); } T* cast() const {
return static_cast<T*>(_obj());
}
}; };
template <class Tp, class... _Args> template <class Tp, class... _Args>
inline typename std::enable_if_t<std::is_base_of_v<IObj, Tp>, ObjToken<Tp>> MakeObj(_Args&&... args) inline typename std::enable_if_t<std::is_base_of_v<IObj, Tp>, ObjToken<Tp>> MakeObj(_Args&&... args) {
{
return new Tp(std::forward<_Args>(args)...); return new Tp(std::forward<_Args>(args)...);
} }
template <class Tp, class... _Args> template <class Tp, class... _Args>
inline typename std::enable_if_t<!std::is_base_of_v<IObj, Tp>, ObjToken<Tp>> MakeObj(_Args&&... args) inline typename std::enable_if_t<!std::is_base_of_v<IObj, Tp>, ObjToken<Tp>> MakeObj(_Args&&... args) {
{
return new ObjWrapper<Tp>(std::forward<_Args>(args)...); return new ObjWrapper<Tp>(std::forward<_Args>(args)...);
} }
@ -287,10 +327,9 @@ static inline int Mkdir(const char* path, mode_t mode) { return mkdir(path, mode
static inline int Stat(const char* path, Sstat* statout) { return stat(path, statout); } static inline int Stat(const char* path, Sstat* statout) { return stat(path, statout); }
#endif #endif
static inline int Rename(const SystemChar* oldpath, const SystemChar* newpath) static inline int Rename(const SystemChar* oldpath, const SystemChar* newpath) {
{
#if _WIN32 #if _WIN32
//return _wrename(oldpath, newpath); // return _wrename(oldpath, newpath);
return MoveFileExW(oldpath, newpath, MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH) == 0; return MoveFileExW(oldpath, newpath, MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH) == 0;
#else #else
return rename(oldpath, newpath); return rename(oldpath, newpath);
@ -301,8 +340,7 @@ static inline int Rename(const SystemChar* oldpath, const SystemChar* newpath)
static inline int CompareCaseInsensitive(const char* a, const char* b) { return _stricmp(a, b); } static inline int CompareCaseInsensitive(const char* a, const char* b) { return _stricmp(a, b); }
#endif #endif
static inline int CompareCaseInsensitive(const SystemChar* a, const SystemChar* b) static inline int CompareCaseInsensitive(const SystemChar* a, const SystemChar* b) {
{
#if _WIN32 #if _WIN32
return _wcsicmp(a, b); return _wcsicmp(a, b);
#else #else
@ -311,20 +349,15 @@ static inline int CompareCaseInsensitive(const SystemChar* a, const SystemChar*
} }
template <typename T> template <typename T>
static inline T clamp(T a, T val, T b) static inline T clamp(T a, T val, T b) {
{
return std::max<T>(a, std::min<T>(b, val)); return std::max<T>(a, std::min<T>(b, val));
} }
template <typename T> template <typename T>
inline T ClampFull(float in) inline T ClampFull(float in) {
{ if (std::is_floating_point<T>()) {
if (std::is_floating_point<T>())
{
return in; return in;
} } else {
else
{
constexpr T MAX = std::numeric_limits<T>::max(); constexpr T MAX = std::numeric_limits<T>::max();
constexpr T MIN = std::numeric_limits<T>::min(); constexpr T MIN = std::numeric_limits<T>::min();
@ -345,8 +378,7 @@ inline T ClampFull(float in)
__attribute__((__format__(__printf__, 1, 2))) __attribute__((__format__(__printf__, 1, 2)))
#endif #endif
static inline void static inline void
Printf(const SystemChar* fmt, ...) Printf(const SystemChar* fmt, ...) {
{
va_list args; va_list args;
va_start(args, fmt); va_start(args, fmt);
#if _WIN32 #if _WIN32
@ -361,8 +393,7 @@ Printf(const SystemChar* fmt, ...)
__attribute__((__format__(__printf__, 3, 4))) __attribute__((__format__(__printf__, 3, 4)))
#endif #endif
static inline void static inline void
SNPrintf(SystemChar* str, size_t maxlen, const SystemChar* format, ...) SNPrintf(SystemChar* str, size_t maxlen, const SystemChar* format, ...) {
{
va_list va; va_list va;
va_start(va, format); va_start(va, format);
#if _WIN32 #if _WIN32
@ -373,8 +404,7 @@ SNPrintf(SystemChar* str, size_t maxlen, const SystemChar* format, ...)
va_end(va); va_end(va);
} }
static inline const SystemChar* StrRChr(const SystemChar* str, SystemChar ch) static inline const SystemChar* StrRChr(const SystemChar* str, SystemChar ch) {
{
#if _WIN32 #if _WIN32
return wcsrchr(str, ch); return wcsrchr(str, ch);
#else #else
@ -382,8 +412,7 @@ static inline const SystemChar* StrRChr(const SystemChar* str, SystemChar ch)
#endif #endif
} }
static inline SystemChar* StrRChr(SystemChar* str, SystemChar ch) static inline SystemChar* StrRChr(SystemChar* str, SystemChar ch) {
{
#if _WIN32 #if _WIN32
return wcsrchr(str, ch); return wcsrchr(str, ch);
#else #else
@ -391,8 +420,7 @@ static inline SystemChar* StrRChr(SystemChar* str, SystemChar ch)
#endif #endif
} }
static inline int FSeek(FILE* fp, int64_t offset, int whence) static inline int FSeek(FILE* fp, int64_t offset, int whence) {
{
#if _WIN32 #if _WIN32
return _fseeki64(fp, offset, whence); return _fseeki64(fp, offset, whence);
#elif __APPLE__ || __FreeBSD__ #elif __APPLE__ || __FreeBSD__
@ -402,8 +430,7 @@ static inline int FSeek(FILE* fp, int64_t offset, int whence)
#endif #endif
} }
static inline int64_t FTell(FILE* fp) static inline int64_t FTell(FILE* fp) {
{
#if _WIN32 #if _WIN32
return _ftelli64(fp); return _ftelli64(fp);
#elif __APPLE__ || __FreeBSD__ #elif __APPLE__ || __FreeBSD__
@ -413,8 +440,7 @@ static inline int64_t FTell(FILE* fp)
#endif #endif
} }
static inline FILE* FOpen(const SystemChar* path, const SystemChar* mode) static inline FILE* FOpen(const SystemChar* path, const SystemChar* mode) {
{
#if _WIN32 #if _WIN32
FILE* fp = _wfopen(path, mode); FILE* fp = _wfopen(path, mode);
if (!fp) if (!fp)
@ -427,8 +453,7 @@ static inline FILE* FOpen(const SystemChar* path, const SystemChar* mode)
return fp; return fp;
} }
static inline void Unlink(const SystemChar* file) static inline void Unlink(const SystemChar* file) {
{
#if _WIN32 #if _WIN32
_wunlink(file); _wunlink(file);
#else #else
@ -444,8 +469,7 @@ bool Copy(const SystemChar* from, const SystemChar* to);
/* Type-sensitive byte swappers */ /* Type-sensitive byte swappers */
template <typename T> template <typename T>
static inline T bswap16(T val) static inline T bswap16(T val) {
{
#if __GNUC__ #if __GNUC__
return __builtin_bswap16(val); return __builtin_bswap16(val);
#elif _WIN32 #elif _WIN32
@ -456,8 +480,7 @@ static inline T bswap16(T val)
} }
template <typename T> template <typename T>
static inline T bswap32(T val) static inline T bswap32(T val) {
{
#if __GNUC__ #if __GNUC__
return __builtin_bswap32(val); return __builtin_bswap32(val);
#elif _WIN32 #elif _WIN32
@ -470,8 +493,7 @@ static inline T bswap32(T val)
} }
template <typename T> template <typename T>
static inline T bswap64(T val) static inline T bswap64(T val) {
{
#if __GNUC__ #if __GNUC__
return __builtin_bswap64(val); return __builtin_bswap64(val);
#elif _WIN32 #elif _WIN32
@ -491,13 +513,11 @@ static inline int32_t SBig(int32_t val) { return bswap32(val); }
static inline uint32_t SBig(uint32_t val) { return bswap32(val); } static inline uint32_t SBig(uint32_t val) { return bswap32(val); }
static inline int64_t SBig(int64_t val) { return bswap64(val); } static inline int64_t SBig(int64_t val) { return bswap64(val); }
static inline uint64_t SBig(uint64_t val) { return bswap64(val); } static inline uint64_t SBig(uint64_t val) { return bswap64(val); }
static inline float SBig(float val) static inline float SBig(float val) {
{
int32_t ival = bswap32(*((int32_t*)(&val))); int32_t ival = bswap32(*((int32_t*)(&val)));
return *((float*)(&ival)); return *((float*)(&ival));
} }
static inline double SBig(double val) static inline double SBig(double val) {
{
int64_t ival = bswap64(*((int64_t*)(&val))); int64_t ival = bswap64(*((int64_t*)(&val)));
return *((double*)(&ival)); return *((double*)(&ival));
} }
@ -523,13 +543,11 @@ static inline int32_t SLittle(int32_t val) { return bswap32(val); }
static inline uint32_t SLittle(uint32_t val) { return bswap32(val); } static inline uint32_t SLittle(uint32_t val) { return bswap32(val); }
static inline int64_t SLittle(int64_t val) { return bswap64(val); } static inline int64_t SLittle(int64_t val) { return bswap64(val); }
static inline uint64_t SLittle(uint64_t val) { return bswap64(val); } static inline uint64_t SLittle(uint64_t val) { return bswap64(val); }
static inline float SLittle(float val) static inline float SLittle(float val) {
{
int32_t ival = bswap32(*((int32_t*)(&val))); int32_t ival = bswap32(*((int32_t*)(&val)));
return *((float*)(&ival)); return *((float*)(&ival));
} }
static inline double SLittle(double val) static inline double SLittle(double val) {
{
int64_t ival = bswap64(*((int64_t*)(&val))); int64_t ival = bswap64(*((int64_t*)(&val)));
return *((double*)(&ival)); return *((double*)(&ival));
} }
@ -551,32 +569,20 @@ static inline double SBig(double val) { return val; }
#endif #endif
/** Versioned data format to interpret */ /** Versioned data format to interpret */
enum class DataFormat enum class DataFormat { GCN, N64, PC };
{
GCN,
N64,
PC
};
/** Meta-type for selecting GameCube (MusyX 2.0) data formats */ /** Meta-type for selecting GameCube (MusyX 2.0) data formats */
struct GCNDataTag struct GCNDataTag {};
{
};
/** Meta-type for selecting N64 (MusyX 1.0) data formats */ /** Meta-type for selecting N64 (MusyX 1.0) data formats */
struct N64DataTag struct N64DataTag {};
{
};
/** Meta-type for selecting PC (MusyX 1.0) data formats */ /** Meta-type for selecting PC (MusyX 1.0) data formats */
struct PCDataTag struct PCDataTag {};
{
};
template <class T> template <class T>
static std::vector<std::pair<typename T::key_type, static std::vector<std::pair<typename T::key_type, std::reference_wrapper<typename T::mapped_type>>>
std::reference_wrapper<typename T::mapped_type>>> SortUnorderedMap(T& um) SortUnorderedMap(T& um) {
{
std::vector<std::pair<typename T::key_type, std::reference_wrapper<typename T::mapped_type>>> ret; std::vector<std::pair<typename T::key_type, std::reference_wrapper<typename T::mapped_type>>> ret;
ret.reserve(um.size()); ret.reserve(um.size());
for (auto& p : um) for (auto& p : um)
@ -586,9 +592,8 @@ static std::vector<std::pair<typename T::key_type,
} }
template <class T> template <class T>
static std::vector<std::pair<typename T::key_type, static std::vector<std::pair<typename T::key_type, std::reference_wrapper<const typename T::mapped_type>>>
std::reference_wrapper<const typename T::mapped_type>>> SortUnorderedMap(const T& um) SortUnorderedMap(const T& um) {
{
std::vector<std::pair<typename T::key_type, std::reference_wrapper<const typename T::mapped_type>>> ret; std::vector<std::pair<typename T::key_type, std::reference_wrapper<const typename T::mapped_type>>> ret;
ret.reserve(um.size()); ret.reserve(um.size());
for (const auto& p : um) for (const auto& p : um)
@ -598,8 +603,7 @@ static std::vector<std::pair<typename T::key_type,
} }
template <class T> template <class T>
static std::vector<typename T::key_type> SortUnorderedSet(T& us) static std::vector<typename T::key_type> SortUnorderedSet(T& us) {
{
std::vector<typename T::key_type> ret; std::vector<typename T::key_type> ret;
ret.reserve(us.size()); ret.reserve(us.size());
for (auto& p : us) for (auto& p : us)
@ -609,8 +613,7 @@ static std::vector<typename T::key_type> SortUnorderedSet(T& us)
} }
template <class T> template <class T>
static std::vector<typename T::key_type> SortUnorderedSet(const T& us) static std::vector<typename T::key_type> SortUnorderedSet(const T& us) {
{
std::vector<typename T::key_type> ret; std::vector<typename T::key_type> ret;
ret.reserve(us.size()); ret.reserve(us.size());
for (const auto& p : us) for (const auto& p : us)
@ -618,16 +621,14 @@ static std::vector<typename T::key_type> SortUnorderedSet(const T& us)
std::sort(ret.begin(), ret.end()); std::sort(ret.begin(), ret.end());
return ret; return ret;
} }
} } // namespace amuse
namespace std namespace std {
{
#define DECL_ID_HASH(type) \ #define DECL_ID_HASH(type) \
template<> \ template <> \
struct hash<amuse::type> \ struct hash<amuse::type> { \
{ \
size_t operator()(const amuse::type& val) const noexcept { return val.id; } \ size_t operator()(const amuse::type& val) const noexcept { return val.id; } \
}; };
DECL_ID_HASH(ObjectId) DECL_ID_HASH(ObjectId)
DECL_ID_HASH(SoundMacroId) DECL_ID_HASH(SoundMacroId)
DECL_ID_HASH(SampleId) DECL_ID_HASH(SampleId)
@ -638,28 +639,15 @@ DECL_ID_HASH(SongId)
DECL_ID_HASH(SFXId) DECL_ID_HASH(SFXId)
DECL_ID_HASH(GroupId) DECL_ID_HASH(GroupId)
template<class T> template <class T>
struct hash<amuse::ObjToken<T>> struct hash<amuse::ObjToken<T>> {
{
size_t operator()(const amuse::ObjToken<T>& val) const noexcept { return hash<T*>()(val.get()); } size_t operator()(const amuse::ObjToken<T>& val) const noexcept { return hash<T*>()(val.get()); }
}; };
} } // namespace std
namespace amuse namespace amuse {
{ struct NameDB {
struct NameDB enum class Type { SoundMacro, Table, Keymap, Layer, Song, SFX, Group, Sample };
{
enum class Type
{
SoundMacro,
Table,
Keymap,
Layer,
Song,
SFX,
Group,
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;
@ -673,5 +661,4 @@ struct NameDB
void remove(ObjectId id); void remove(ObjectId id);
void rename(ObjectId id, std::string_view str); void rename(ObjectId id, std::string_view str);
}; };
} } // namespace amuse

View File

@ -6,14 +6,11 @@
#include <vector> #include <vector>
#include <memory> #include <memory>
namespace amuse namespace amuse {
{
class ContainerRegistry class ContainerRegistry {
{
public: public:
enum class Type enum class Type {
{
Invalid = -1, Invalid = -1,
Raw4 = 0, Raw4 = 0,
MetroidPrime, MetroidPrime,
@ -24,16 +21,13 @@ public:
RogueSquadron2, RogueSquadron2,
RogueSquadron3 RogueSquadron3
}; };
struct SongData struct SongData {
{
std::unique_ptr<uint8_t[]> m_data; std::unique_ptr<uint8_t[]> m_data;
size_t m_size; size_t m_size;
int16_t m_groupId; int16_t m_groupId;
int16_t m_setupId; int16_t m_setupId;
SongData(std::unique_ptr<uint8_t[]>&& data, size_t size, int16_t groupId, int16_t setupId) SongData(std::unique_ptr<uint8_t[]>&& data, size_t size, int16_t groupId, int16_t setupId)
: m_data(std::move(data)), m_size(size), m_groupId(groupId), m_setupId(setupId) : m_data(std::move(data)), m_size(size), m_groupId(groupId), m_setupId(setupId) {}
{
}
}; };
static const SystemChar* TypeToName(Type tp); static const SystemChar* TypeToName(Type tp);
static Type DetectContainerType(const SystemChar* path); static Type DetectContainerType(const SystemChar* path);
@ -42,5 +36,4 @@ public:
Type& typeOut); Type& typeOut);
static std::vector<std::pair<SystemString, SongData>> LoadSongs(const SystemChar* path); static std::vector<std::pair<SystemString, SongData>> LoadSongs(const SystemChar* path);
}; };
} } // namespace amuse

View File

@ -3,36 +3,30 @@
#include <cstdint> #include <cstdint>
#include <cfloat> #include <cfloat>
static inline int16_t DSPSampClamp(int32_t val) static inline int16_t DSPSampClamp(int32_t val) {
{ if (val < -32768)
if (val < -32768) val = -32768; val = -32768;
else if (val > 32767) val = 32767; else if (val > 32767)
val = 32767;
return val; return val;
} }
unsigned DSPDecompressFrame(int16_t* out, const uint8_t* in, unsigned DSPDecompressFrame(int16_t* out, const uint8_t* in, const int16_t coefs[8][2], int16_t* prev1, int16_t* prev2,
const int16_t coefs[8][2], int16_t* prev1, int16_t* prev2,
unsigned lastSample); unsigned lastSample);
unsigned DSPDecompressFrameStereoStride(int16_t* out, const uint8_t* in, unsigned DSPDecompressFrameStereoStride(int16_t* out, const uint8_t* in, const int16_t coefs[8][2], int16_t* prev1,
const int16_t coefs[8][2], int16_t* prev1, int16_t* prev2, int16_t* prev2, unsigned lastSample);
unsigned lastSample); unsigned DSPDecompressFrameStereoDupe(int16_t* out, const uint8_t* in, const int16_t coefs[8][2], int16_t* prev1,
unsigned DSPDecompressFrameStereoDupe(int16_t* out, const uint8_t* in, int16_t* prev2, unsigned lastSample);
const int16_t coefs[8][2], int16_t* prev1, int16_t* prev2,
unsigned DSPDecompressFrameRanged(int16_t* out, const uint8_t* in, const int16_t coefs[8][2], int16_t* prev1,
int16_t* prev2, unsigned firstSample, unsigned lastSample);
unsigned DSPDecompressFrameStateOnly(const uint8_t* in, const int16_t coefs[8][2], int16_t* prev1, int16_t* prev2,
unsigned lastSample); unsigned lastSample);
unsigned DSPDecompressFrameRanged(int16_t* out, const uint8_t* in, unsigned DSPDecompressFrameRangedStateOnly(const uint8_t* in, const int16_t coefs[8][2], int16_t* prev1, int16_t* prev2,
const int16_t coefs[8][2], int16_t* prev1, int16_t* prev2,
unsigned firstSample, unsigned lastSample);
unsigned DSPDecompressFrameStateOnly(const uint8_t* in,
const int16_t coefs[8][2], int16_t* prev1, int16_t* prev2,
unsigned lastSample);
unsigned DSPDecompressFrameRangedStateOnly(const uint8_t* in,
const int16_t coefs[8][2], int16_t* prev1, int16_t* prev2,
unsigned firstSample, unsigned lastSample); unsigned firstSample, unsigned lastSample);
void DSPCorrelateCoefs(const short* source, int samples, short coefsOut[8][2]); void DSPCorrelateCoefs(const short* source, int samples, short coefsOut[8][2]);
void DSPEncodeFrame(short pcmInOut[16], int sampleCount, unsigned char adpcmOut[8], const short coefsIn[8][2]); void DSPEncodeFrame(short pcmInOut[16], int sampleCount, unsigned char adpcmOut[8], const short coefsIn[8][2]);

View File

@ -3,13 +3,10 @@
#include "Common.hpp" #include "Common.hpp"
#include <vector> #include <vector>
namespace amuse namespace amuse {
{
struct CaseInsensitiveCompare struct CaseInsensitiveCompare {
{ bool operator()(std::string_view lhs, std::string_view rhs) const {
bool operator()(std::string_view lhs, std::string_view rhs) const
{
#if _WIN32 #if _WIN32
if (_stricmp(lhs.data(), rhs.data()) < 0) if (_stricmp(lhs.data(), rhs.data()) < 0)
#else #else
@ -20,8 +17,7 @@ struct CaseInsensitiveCompare
} }
#if _WIN32 #if _WIN32
bool operator()(std::wstring_view lhs, std::wstring_view rhs) const bool operator()(std::wstring_view lhs, std::wstring_view rhs) const {
{
if (_wcsicmp(lhs.data(), rhs.data()) < 0) if (_wcsicmp(lhs.data(), rhs.data()) < 0)
return true; return true;
return false; return false;
@ -29,18 +25,10 @@ struct CaseInsensitiveCompare
#endif #endif
}; };
class DirectoryEnumerator class DirectoryEnumerator {
{
public: public:
enum class Mode enum class Mode { Native, DirsSorted, FilesSorted, DirsThenFilesSorted };
{ struct Entry {
Native,
DirsSorted,
FilesSorted,
DirsThenFilesSorted
};
struct Entry
{
SystemString m_path; SystemString m_path;
SystemString m_name; SystemString m_name;
size_t m_fileSz; size_t m_fileSz;
@ -62,5 +50,4 @@ public:
std::vector<Entry>::const_iterator begin() const { return m_entries.cbegin(); } std::vector<Entry>::const_iterator begin() const { return m_entries.cbegin(); }
std::vector<Entry>::const_iterator end() const { return m_entries.cend(); } std::vector<Entry>::const_iterator end() const { return m_entries.cend(); }
}; };
} } // namespace amuse

View File

@ -3,22 +3,12 @@
#include <cstdint> #include <cstdint>
#include <cstdlib> #include <cstdlib>
namespace amuse namespace amuse {
{
struct ChannelMap; struct ChannelMap;
enum class EffectType enum class EffectType { Invalid, ReverbStd, ReverbHi, Delay, Chorus, EffectTypeMAX };
{
Invalid,
ReverbStd,
ReverbHi,
Delay,
Chorus,
EffectTypeMAX
};
class EffectBaseTypeless class EffectBaseTypeless {
{
public: public:
virtual ~EffectBaseTypeless() = default; virtual ~EffectBaseTypeless() = default;
virtual void resetOutputSampleRate(double sampleRate) = 0; virtual void resetOutputSampleRate(double sampleRate) = 0;
@ -26,10 +16,8 @@ public:
}; };
template <typename T> template <typename T>
class EffectBase : public EffectBaseTypeless class EffectBase : public EffectBaseTypeless {
{
public: public:
virtual void applyEffect(T* audio, size_t frameCount, const ChannelMap& chanMap) = 0; virtual void applyEffect(T* audio, size_t frameCount, const ChannelMap& chanMap) = 0;
}; };
} } // namespace amuse

View File

@ -4,16 +4,14 @@
#include "Common.hpp" #include "Common.hpp"
#include <cstdint> #include <cstdint>
namespace amuse namespace amuse {
{
template <typename T> template <typename T>
class EffectChorusImp; class EffectChorusImp;
#define AMUSE_CHORUS_NUM_BLOCKS 3 #define AMUSE_CHORUS_NUM_BLOCKS 3
/** Parameters needed to create EffectChorus */ /** Parameters needed to create EffectChorus */
struct EffectChorusInfo struct EffectChorusInfo {
{
uint32_t baseDelay = 5; /**< [5, 15] minimum value (in ms) for computed delay */ uint32_t baseDelay = 5; /**< [5, 15] minimum value (in ms) for computed delay */
uint32_t variation = 0; /**< [0, 5] time error (in ms) to set delay within */ uint32_t variation = 0; /**< [0, 5] time error (in ms) to set delay within */
uint32_t period = 500; /**< [500, 10000] time (in ms) of one delay-shift cycle */ uint32_t period = 500; /**< [500, 10000] time (in ms) of one delay-shift cycle */
@ -24,8 +22,7 @@ struct EffectChorusInfo
}; };
/** Mixes the audio back into itself after continuously-varying delay */ /** Mixes the audio back into itself after continuously-varying delay */
class EffectChorus class EffectChorus {
{
uint32_t x90_baseDelay; /**< [5, 15] minimum value (in ms) for computed delay */ uint32_t x90_baseDelay; /**< [5, 15] minimum value (in ms) for computed delay */
uint32_t x94_variation; /**< [0, 5] time error (in ms) to set delay within */ uint32_t x94_variation; /**< [0, 5] time error (in ms) to set delay within */
uint32_t x98_period; /**< [500, 10000] time (in ms) of one delay-shift cycle */ uint32_t x98_period; /**< [500, 10000] time (in ms) of one delay-shift cycle */
@ -39,32 +36,28 @@ public:
template <typename T> template <typename T>
using ImpType = EffectChorusImp<T>; using ImpType = EffectChorusImp<T>;
void setBaseDelay(uint32_t baseDelay) void setBaseDelay(uint32_t baseDelay) {
{
baseDelay = clamp(5u, baseDelay, 15u); baseDelay = clamp(5u, baseDelay, 15u);
x90_baseDelay = baseDelay; x90_baseDelay = baseDelay;
m_dirty = true; m_dirty = true;
} }
uint32_t getBaseDelay() const { return x90_baseDelay; } uint32_t getBaseDelay() const { return x90_baseDelay; }
void setVariation(uint32_t variation) void setVariation(uint32_t variation) {
{
variation = clamp(0u, variation, 5u); variation = clamp(0u, variation, 5u);
x94_variation = variation; x94_variation = variation;
m_dirty = true; m_dirty = true;
} }
uint32_t getVariation() const { return x94_variation; } uint32_t getVariation() const { return x94_variation; }
void setPeriod(uint32_t period) void setPeriod(uint32_t period) {
{
period = clamp(500u, period, 10000u); period = clamp(500u, period, 10000u);
x98_period = period; x98_period = period;
m_dirty = true; m_dirty = true;
} }
uint32_t getPeriod() const { return x98_period; } uint32_t getPeriod() const { return x98_period; }
void updateParams(const EffectChorusInfo& info) void updateParams(const EffectChorusInfo& info) {
{
setBaseDelay(info.baseDelay); setBaseDelay(info.baseDelay);
setVariation(info.variation); setVariation(info.variation);
setPeriod(info.period); setPeriod(info.period);
@ -73,8 +66,7 @@ public:
/** Type-specific implementation of chorus effect */ /** Type-specific implementation of chorus effect */
template <typename T> template <typename T>
class EffectChorusImp : public EffectBase<T>, public EffectChorus class EffectChorusImp : public EffectBase<T>, public EffectChorus {
{
T* x0_lastChans[8][AMUSE_CHORUS_NUM_BLOCKS] = {}; /**< Evenly-allocated pointer-table for each channel's delay */ T* x0_lastChans[8][AMUSE_CHORUS_NUM_BLOCKS] = {}; /**< Evenly-allocated pointer-table for each channel's delay */
uint8_t x24_currentLast = 1; /**< Last 5ms block-idx to be processed */ uint8_t x24_currentLast = 1; /**< Last 5ms block-idx to be processed */
@ -87,8 +79,7 @@ class EffectChorusImp : public EffectBase<T>, public EffectChorus
uint32_t x64_pitchOffsetPeriodCount; /**< trigger value for flipping SRC state */ uint32_t x64_pitchOffsetPeriodCount; /**< trigger value for flipping SRC state */
uint32_t x68_pitchOffsetPeriod; /**< intermediate block window quantity for calculating SRC state */ uint32_t x68_pitchOffsetPeriod; /**< intermediate block window quantity for calculating SRC state */
struct SrcInfo struct SrcInfo {
{
T* x6c_dest; /**< selected channel's live buffer */ T* x6c_dest; /**< selected channel's live buffer */
T* x70_smpBase; /**< selected channel's delay buffer */ T* x70_smpBase; /**< selected channel's delay buffer */
T* x74_old; /**< selected channel's 4-sample history buffer */ T* x74_old; /**< selected channel's 4-sample history buffer */
@ -120,5 +111,4 @@ public:
EffectType Isa() const { return EffectType::Chorus; } EffectType Isa() const { return EffectType::Chorus; }
}; };
} } // namespace amuse

View File

@ -6,22 +6,19 @@
#include <cstdint> #include <cstdint>
#include <memory> #include <memory>
namespace amuse namespace amuse {
{
template <typename T> template <typename T>
class EffectDelayImp; class EffectDelayImp;
/** Parameters needed to create EffectDelay */ /** Parameters needed to create EffectDelay */
struct EffectDelayInfo struct EffectDelayInfo {
{
uint32_t delay[8]; /**< [10, 5000] time in ms of each channel's delay */ uint32_t delay[8]; /**< [10, 5000] time in ms of each channel's delay */
uint32_t feedback[8] = {}; /**< [0, 100] percent to mix delayed signal with input signal */ uint32_t feedback[8] = {}; /**< [0, 100] percent to mix delayed signal with input signal */
uint32_t output[8] = {}; /**< [0, 100] total output percent */ uint32_t output[8] = {}; /**< [0, 100] total output percent */
static uint32_t lerp(uint32_t v0, uint32_t v1, float t) { return (1.f - t) * v0 + t * v1; } static uint32_t lerp(uint32_t v0, uint32_t v1, float t) { return (1.f - t) * v0 + t * v1; }
static void Interp3To8(uint32_t arr[8], uint32_t L, uint32_t R, uint32_t S) static void Interp3To8(uint32_t arr[8], uint32_t L, uint32_t R, uint32_t S) {
{
arr[int(AudioChannel::FrontLeft)] = L; arr[int(AudioChannel::FrontLeft)] = L;
arr[int(AudioChannel::FrontRight)] = R; arr[int(AudioChannel::FrontRight)] = R;
arr[int(AudioChannel::RearLeft)] = lerp(L, S, 0.75f); arr[int(AudioChannel::RearLeft)] = lerp(L, S, 0.75f);
@ -33,10 +30,8 @@ struct EffectDelayInfo
} }
EffectDelayInfo() { std::fill_n(delay, 8, 10); } EffectDelayInfo() { std::fill_n(delay, 8, 10); }
EffectDelayInfo(uint32_t delayL, uint32_t delayR, uint32_t delayS, EffectDelayInfo(uint32_t delayL, uint32_t delayR, uint32_t delayS, uint32_t feedbackL, uint32_t feedbackR,
uint32_t feedbackL, uint32_t feedbackR, uint32_t feedbackS, uint32_t feedbackS, uint32_t outputL, uint32_t outputR, uint32_t outputS) {
uint32_t outputL, uint32_t outputR, uint32_t outputS)
{
Interp3To8(delay, delayL, delayR, delayS); Interp3To8(delay, delayL, delayR, delayS);
Interp3To8(feedback, feedbackL, feedbackR, feedbackS); Interp3To8(feedback, feedbackL, feedbackR, feedbackS);
Interp3To8(output, outputL, outputR, outputS); Interp3To8(output, outputL, outputR, outputS);
@ -44,8 +39,7 @@ struct EffectDelayInfo
}; };
/** Mixes the audio back into itself after specified delay */ /** Mixes the audio back into itself after specified delay */
class EffectDelay class EffectDelay {
{
protected: protected:
uint32_t x3c_delay[8]; /**< [10, 5000] time in ms of each channel's delay */ uint32_t x3c_delay[8]; /**< [10, 5000] time in ms of each channel's delay */
uint32_t x48_feedback[8]; /**< [0, 100] percent to mix delayed signal with input signal */ uint32_t x48_feedback[8]; /**< [0, 100] percent to mix delayed signal with input signal */
@ -55,57 +49,49 @@ public:
template <typename T> template <typename T>
using ImpType = EffectDelayImp<T>; using ImpType = EffectDelayImp<T>;
void setDelay(uint32_t delay) void setDelay(uint32_t delay) {
{
delay = clamp(10u, delay, 5000u); delay = clamp(10u, delay, 5000u);
for (int i = 0; i < 8; ++i) for (int i = 0; i < 8; ++i)
x3c_delay[i] = delay; x3c_delay[i] = delay;
m_dirty = true; m_dirty = true;
} }
void setChanDelay(int chanIdx, uint32_t delay) void setChanDelay(int chanIdx, uint32_t delay) {
{
delay = clamp(10u, delay, 5000u); delay = clamp(10u, delay, 5000u);
x3c_delay[chanIdx] = delay; x3c_delay[chanIdx] = delay;
m_dirty = true; m_dirty = true;
} }
uint32_t getChanDelay(int chanIdx) const { return x3c_delay[chanIdx]; } uint32_t getChanDelay(int chanIdx) const { return x3c_delay[chanIdx]; }
void setFeedback(uint32_t feedback) void setFeedback(uint32_t feedback) {
{
feedback = clamp(0u, feedback, 100u); feedback = clamp(0u, feedback, 100u);
for (int i = 0; i < 8; ++i) for (int i = 0; i < 8; ++i)
x48_feedback[i] = feedback; x48_feedback[i] = feedback;
m_dirty = true; m_dirty = true;
} }
void setChanFeedback(int chanIdx, uint32_t feedback) void setChanFeedback(int chanIdx, uint32_t feedback) {
{
feedback = clamp(0u, feedback, 100u); feedback = clamp(0u, feedback, 100u);
x48_feedback[chanIdx] = feedback; x48_feedback[chanIdx] = feedback;
m_dirty = true; m_dirty = true;
} }
uint32_t getChanFeedback(int chanIdx) const { return x48_feedback[chanIdx]; } uint32_t getChanFeedback(int chanIdx) const { return x48_feedback[chanIdx]; }
void setOutput(uint32_t output) void setOutput(uint32_t output) {
{
output = clamp(0u, output, 100u); output = clamp(0u, output, 100u);
for (int i = 0; i < 8; ++i) for (int i = 0; i < 8; ++i)
x54_output[i] = output; x54_output[i] = output;
m_dirty = true; m_dirty = true;
} }
void setChanOutput(int chanIdx, uint32_t output) void setChanOutput(int chanIdx, uint32_t output) {
{
output = clamp(0u, output, 100u); output = clamp(0u, output, 100u);
x54_output[chanIdx] = output; x54_output[chanIdx] = output;
m_dirty = true; m_dirty = true;
} }
uint32_t getChanOutput(int chanIdx) const { return x54_output[chanIdx]; } uint32_t getChanOutput(int chanIdx) const { return x54_output[chanIdx]; }
void setParams(const EffectDelayInfo& info) void setParams(const EffectDelayInfo& info) {
{ for (int i = 0; i < 8; ++i) {
for (int i = 0; i < 8; ++i)
{
x3c_delay[i] = clamp(10u, info.delay[i], 5000u); x3c_delay[i] = clamp(10u, info.delay[i], 5000u);
x48_feedback[i] = clamp(0u, info.feedback[i], 100u); x48_feedback[i] = clamp(0u, info.feedback[i], 100u);
x54_output[i] = clamp(0u, info.output[i], 100u); x54_output[i] = clamp(0u, info.output[i], 100u);
@ -116,8 +102,7 @@ public:
/** Type-specific implementation of delay effect */ /** Type-specific implementation of delay effect */
template <typename T> template <typename T>
class EffectDelayImp : public EffectBase<T>, public EffectDelay class EffectDelayImp : public EffectBase<T>, public EffectDelay {
{
uint32_t x0_currentSize[8]; /**< per-channel delay-line buffer sizes */ uint32_t x0_currentSize[8]; /**< per-channel delay-line buffer sizes */
uint32_t xc_currentPos[8]; /**< per-channel block-index */ uint32_t xc_currentPos[8]; /**< per-channel block-index */
uint32_t x18_currentFeedback[8]; /**< [0, 128] feedback attenuator */ uint32_t x18_currentFeedback[8]; /**< [0, 128] feedback attenuator */
@ -139,5 +124,4 @@ public:
EffectType Isa() const { return EffectType::Delay; } EffectType Isa() const { return EffectType::Delay; }
}; };
} } // namespace amuse

View File

@ -4,12 +4,10 @@
#include "amuse/Common.hpp" #include "amuse/Common.hpp"
#include <memory> #include <memory>
namespace amuse namespace amuse {
{
/** Parameters needed to create EffectReverbStd */ /** Parameters needed to create EffectReverbStd */
struct EffectReverbStdInfo struct EffectReverbStdInfo {
{
float coloration = 0.f; /**< [0.0, 1.0] influences filter coefficients to define surface characteristics of a room */ float coloration = 0.f; /**< [0.0, 1.0] influences filter coefficients to define surface characteristics of a room */
float mix = 0.f; /**< [0.0, 1.0] dry/wet mix factor of reverb effect */ float mix = 0.f; /**< [0.0, 1.0] dry/wet mix factor of reverb effect */
float time = 0.01f; /**< [0.01, 10.0] time in seconds for reflection decay */ float time = 0.01f; /**< [0.01, 10.0] time in seconds for reflection decay */
@ -22,8 +20,7 @@ struct EffectReverbStdInfo
}; };
/** Parameters needed to create EffectReverbHi */ /** Parameters needed to create EffectReverbHi */
struct EffectReverbHiInfo struct EffectReverbHiInfo {
{
float coloration = 0.f; /**< [0.0, 1.0] influences filter coefficients to define surface characteristics of a room */ float coloration = 0.f; /**< [0.0, 1.0] influences filter coefficients to define surface characteristics of a room */
float mix = 0.f; /**< [0.0, 1.0] dry/wet mix factor of reverb effect */ float mix = 0.f; /**< [0.0, 1.0] dry/wet mix factor of reverb effect */
float time = 0.01f; /**< [0.01, 10.0] time in seconds for reflection decay */ float time = 0.01f; /**< [0.01, 10.0] time in seconds for reflection decay */
@ -37,8 +34,7 @@ struct EffectReverbHiInfo
}; };
/** Delay state for one 'tap' of the reverb effect */ /** Delay state for one 'tap' of the reverb effect */
struct ReverbDelayLine struct ReverbDelayLine {
{
int32_t x0_inPoint = 0; int32_t x0_inPoint = 0;
int32_t x4_outPoint = 0; int32_t x4_outPoint = 0;
int32_t x8_length = 0; int32_t x8_length = 0;
@ -56,8 +52,7 @@ template <typename T>
class EffectReverbHiImp; class EffectReverbHiImp;
/** Reverb effect with configurable reflection filtering */ /** Reverb effect with configurable reflection filtering */
class EffectReverbStd class EffectReverbStd {
{
protected: protected:
float x140_x1c8_coloration; /**< [0.0, 1.0] influences filter coefficients to define surface characteristics of a float x140_x1c8_coloration; /**< [0.0, 1.0] influences filter coefficients to define surface characteristics of a
room */ room */
@ -77,43 +72,37 @@ public:
template <typename T> template <typename T>
using ImpType = EffectReverbStdImp<T>; using ImpType = EffectReverbStdImp<T>;
void setColoration(float coloration) void setColoration(float coloration) {
{
x140_x1c8_coloration = clamp(0.f, coloration, 1.f); x140_x1c8_coloration = clamp(0.f, coloration, 1.f);
m_dirty = true; m_dirty = true;
} }
float getColoration() const { return x140_x1c8_coloration; } float getColoration() const { return x140_x1c8_coloration; }
void setMix(float mix) void setMix(float mix) {
{
x144_x1cc_mix = clamp(0.f, mix, 1.f); x144_x1cc_mix = clamp(0.f, mix, 1.f);
m_dirty = true; m_dirty = true;
} }
float getMix() const { return x144_x1cc_mix; } float getMix() const { return x144_x1cc_mix; }
void setTime(float time) void setTime(float time) {
{
x148_x1d0_time = clamp(0.01f, time, 10.f); x148_x1d0_time = clamp(0.01f, time, 10.f);
m_dirty = true; m_dirty = true;
} }
float getTime() const { return x148_x1d0_time; } float getTime() const { return x148_x1d0_time; }
void setDamping(float damping) void setDamping(float damping) {
{
x14c_x1d4_damping = clamp(0.f, damping, 1.f); x14c_x1d4_damping = clamp(0.f, damping, 1.f);
m_dirty = true; m_dirty = true;
} }
float getDamping() const { return x14c_x1d4_damping; } float getDamping() const { return x14c_x1d4_damping; }
void setPreDelay(float preDelay) void setPreDelay(float preDelay) {
{
x150_x1d8_preDelay = clamp(0.f, preDelay, 0.1f); x150_x1d8_preDelay = clamp(0.f, preDelay, 0.1f);
m_dirty = true; m_dirty = true;
} }
float getPreDelay() const { return x150_x1d8_preDelay; } float getPreDelay() const { return x150_x1d8_preDelay; }
void setParams(const EffectReverbStdInfo& info) void setParams(const EffectReverbStdInfo& info) {
{
setColoration(info.coloration); setColoration(info.coloration);
setMix(info.mix); setMix(info.mix);
setTime(info.time); setTime(info.time);
@ -123,8 +112,7 @@ public:
}; };
/** Reverb effect with configurable reflection filtering, adds per-channel low-pass and crosstalk */ /** Reverb effect with configurable reflection filtering, adds per-channel low-pass and crosstalk */
class EffectReverbHi : public EffectReverbStd class EffectReverbHi : public EffectReverbStd {
{
float x1dc_crosstalk; /**< [0.0, 1.0] factor defining how much reflections are allowed to bleed to other channels */ float x1dc_crosstalk; /**< [0.0, 1.0] factor defining how much reflections are allowed to bleed to other channels */
template <typename T> template <typename T>
@ -135,15 +123,13 @@ public:
template <typename T> template <typename T>
using ImpType = EffectReverbHiImp<T>; using ImpType = EffectReverbHiImp<T>;
void setCrosstalk(float crosstalk) void setCrosstalk(float crosstalk) {
{
x1dc_crosstalk = clamp(0.f, crosstalk, 1.f); x1dc_crosstalk = clamp(0.f, crosstalk, 1.f);
m_dirty = true; m_dirty = true;
} }
float getCrosstalk() const { return x1dc_crosstalk; } float getCrosstalk() const { return x1dc_crosstalk; }
void setParams(const EffectReverbHiInfo& info) void setParams(const EffectReverbHiInfo& info) {
{
setColoration(info.coloration); setColoration(info.coloration);
setMix(info.mix); setMix(info.mix);
setTime(info.time); setTime(info.time);
@ -155,8 +141,7 @@ public:
/** Standard-quality 2-stage reverb */ /** Standard-quality 2-stage reverb */
template <typename T> template <typename T>
class EffectReverbStdImp : public EffectBase<T>, public EffectReverbStd class EffectReverbStdImp : public EffectBase<T>, public EffectReverbStd {
{
ReverbDelayLine x0_AP[8][2] = {}; /**< All-pass delay lines */ ReverbDelayLine x0_AP[8][2] = {}; /**< All-pass delay lines */
ReverbDelayLine x78_C[8][2] = {}; /**< Comb delay lines */ ReverbDelayLine x78_C[8][2] = {}; /**< Comb delay lines */
float xf0_allPassCoef = 0.f; /**< All-pass mix coefficient */ float xf0_allPassCoef = 0.f; /**< All-pass mix coefficient */
@ -185,8 +170,7 @@ public:
/** High-quality 3-stage reverb with per-channel low-pass and crosstalk */ /** High-quality 3-stage reverb with per-channel low-pass and crosstalk */
template <typename T> template <typename T>
class EffectReverbHiImp : public EffectBase<T>, public EffectReverbHi class EffectReverbHiImp : public EffectBase<T>, public EffectReverbHi {
{
ReverbDelayLine x0_AP[8][2] = {}; /**< All-pass delay lines */ ReverbDelayLine x0_AP[8][2] = {}; /**< All-pass delay lines */
ReverbDelayLine x78_LP[8] = {}; /**< Per-channel low-pass delay-lines */ ReverbDelayLine x78_LP[8] = {}; /**< Per-channel low-pass delay-lines */
ReverbDelayLine xb4_C[8][3] = {}; /**< Comb delay lines */ ReverbDelayLine xb4_C[8][3] = {}; /**< Comb delay lines */
@ -217,5 +201,4 @@ public:
EffectType Isa() const { return EffectType::ReverbHi; } EffectType Isa() const { return EffectType::ReverbHi; }
}; };
} } // namespace amuse

View File

@ -7,23 +7,20 @@
#include <cmath> #include <cmath>
#include <cfloat> #include <cfloat>
namespace amuse namespace amuse {
{
class Listener; class Listener;
using Vector3f = float[3]; using Vector3f = float[3];
static inline float Dot(const Vector3f& a, const Vector3f& b) { return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; } static inline float Dot(const Vector3f& a, const Vector3f& b) { return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; }
static inline float Length(const Vector3f& a) static inline float Length(const Vector3f& a) {
{
if (std::fabs(a[0]) <= FLT_EPSILON && std::fabs(a[1]) <= FLT_EPSILON && std::fabs(a[2]) <= FLT_EPSILON) if (std::fabs(a[0]) <= FLT_EPSILON && std::fabs(a[1]) <= FLT_EPSILON && std::fabs(a[2]) <= FLT_EPSILON)
return 0.f; return 0.f;
return std::sqrt(Dot(a, a)); return std::sqrt(Dot(a, a));
} }
static inline float Normalize(Vector3f& out) static inline float Normalize(Vector3f& out) {
{
float dist = Length(out); float dist = Length(out);
if (dist == 0.f) if (dist == 0.f)
return 0.f; return 0.f;
@ -34,8 +31,7 @@ static inline float Normalize(Vector3f& out)
} }
/** Voice wrapper with positional-3D level control */ /** Voice wrapper with positional-3D level control */
class Emitter : public Entity class Emitter : public Entity {
{
ObjToken<Voice> m_vox; ObjToken<Voice> m_vox;
Vector3f m_pos = {}; Vector3f m_pos = {};
Vector3f m_dir = {}; Vector3f m_dir = {};
@ -54,13 +50,15 @@ class Emitter : public Entity
public: public:
~Emitter(); ~Emitter();
Emitter(Engine& engine, const AudioGroup& group, ObjToken<Voice> vox, Emitter(Engine& engine, const AudioGroup& group, ObjToken<Voice> vox, float maxDist, float minVol, float falloff,
float maxDist, float minVol, float falloff, bool doppler); bool doppler);
void setVectors(const float* pos, const float* dir); void setVectors(const float* pos, const float* dir);
void setMaxVol(float maxVol) { m_maxVol = clamp(0.f, maxVol, 1.f); m_dirty = true; } void setMaxVol(float maxVol) {
m_maxVol = clamp(0.f, maxVol, 1.f);
m_dirty = true;
}
ObjToken<Voice> getVoice() const { return m_vox; } ObjToken<Voice> getVoice() const { return m_vox; }
}; };
} } // namespace amuse

View File

@ -12,8 +12,7 @@
#include "Studio.hpp" #include "Studio.hpp"
#include "IBackendVoiceAllocator.hpp" #include "IBackendVoiceAllocator.hpp"
namespace amuse namespace amuse {
{
class IBackendVoiceAllocator; class IBackendVoiceAllocator;
class Voice; class Voice;
class Submix; class Submix;
@ -22,15 +21,13 @@ class AudioGroup;
class AudioGroupData; class AudioGroupData;
class IMIDIReader; class IMIDIReader;
enum class AmplitudeMode enum class AmplitudeMode {
{
PerSample, /**< Per-sample amplitude evaluation (dt = 1.0 / sampleRate, rather CPU demanding) */ PerSample, /**< Per-sample amplitude evaluation (dt = 1.0 / sampleRate, rather CPU demanding) */
BlockLinearized /**< Per-block lerp amplitude evaluation (dt = 160.0 / sampleRate) */ BlockLinearized /**< Per-block lerp amplitude evaluation (dt = 160.0 / sampleRate) */
}; };
/** Main audio playback system for a single audio output */ /** Main audio playback system for a single audio output */
class Engine class Engine {
{
friend class Voice; friend class Voice;
friend class Emitter; friend class Emitter;
friend class Sequencer; friend class Sequencer;
@ -59,12 +56,11 @@ class Engine
std::list<ObjToken<Voice>>::iterator _allocateVoice(const AudioGroup& group, GroupId groupId, double sampleRate, std::list<ObjToken<Voice>>::iterator _allocateVoice(const AudioGroup& group, GroupId groupId, double sampleRate,
bool dynamicPitch, bool emitter, ObjToken<Studio> studio); bool dynamicPitch, bool emitter, ObjToken<Studio> studio);
std::list<ObjToken<Sequencer>>::iterator _allocateSequencer(const AudioGroup& group, GroupId groupId, std::list<ObjToken<Sequencer>>::iterator _allocateSequencer(const AudioGroup& group, GroupId groupId, SongId setupId,
SongId setupId, ObjToken<Studio> studio); ObjToken<Studio> studio);
ObjToken<Studio> _allocateStudio(bool mainOut); ObjToken<Studio> _allocateStudio(bool mainOut);
std::list<ObjToken<Voice>>::iterator _destroyVoice(std::list<ObjToken<Voice>>::iterator it); std::list<ObjToken<Voice>>::iterator _destroyVoice(std::list<ObjToken<Voice>>::iterator it);
std::list<ObjToken<Sequencer>>::iterator std::list<ObjToken<Sequencer>>::iterator _destroySequencer(std::list<ObjToken<Sequencer>>::iterator it);
_destroySequencer(std::list<ObjToken<Sequencer>>::iterator it);
void _bringOutYourDead(); void _bringOutYourDead();
public: public:
@ -91,51 +87,41 @@ public:
/** Start soundFX playing from loaded audio groups */ /** Start soundFX playing from loaded audio groups */
ObjToken<Voice> fxStart(SFXId sfxId, float vol, float pan, ObjToken<Studio> smx); ObjToken<Voice> fxStart(SFXId sfxId, float vol, float pan, ObjToken<Studio> smx);
ObjToken<Voice> fxStart(SFXId sfxId, float vol, float pan) ObjToken<Voice> fxStart(SFXId sfxId, float vol, float pan) { return fxStart(sfxId, vol, pan, m_defaultStudio); }
{
return fxStart(sfxId, vol, pan, m_defaultStudio);
}
/** Start soundFX playing from explicit group data (for editor use) */ /** Start soundFX playing from explicit group data (for editor use) */
ObjToken<Voice> fxStart(const AudioGroup* group, GroupId groupId, SFXId sfxId, float vol, float pan, ObjToken<Studio> smx); ObjToken<Voice> fxStart(const AudioGroup* group, GroupId groupId, SFXId sfxId, float vol, float pan,
ObjToken<Voice> fxStart(const AudioGroup* group, GroupId groupId, SFXId sfxId, float vol, float pan) ObjToken<Studio> smx);
{ ObjToken<Voice> fxStart(const AudioGroup* group, GroupId groupId, SFXId sfxId, float vol, float pan) {
return fxStart(group, groupId, sfxId, vol, pan, m_defaultStudio); return fxStart(group, groupId, sfxId, vol, pan, m_defaultStudio);
} }
/** Start SoundMacro node playing directly (for editor use) */ /** Start SoundMacro node playing directly (for editor use) */
ObjToken<Voice> macroStart(const AudioGroup* group, SoundMacroId id, uint8_t key, ObjToken<Voice> macroStart(const AudioGroup* group, SoundMacroId id, uint8_t key, uint8_t vel, uint8_t mod,
uint8_t vel, uint8_t mod, ObjToken<Studio> smx); ObjToken<Studio> smx);
ObjToken<Voice> macroStart(const AudioGroup* group, SoundMacroId id, uint8_t key, ObjToken<Voice> macroStart(const AudioGroup* group, SoundMacroId id, uint8_t key, uint8_t vel, uint8_t mod) {
uint8_t vel, uint8_t mod)
{
return macroStart(group, id, key, vel, mod, m_defaultStudio); return macroStart(group, id, key, vel, mod, m_defaultStudio);
} }
/** Start SoundMacro object playing directly (for editor use) */ /** Start SoundMacro object playing directly (for editor use) */
ObjToken<Voice> macroStart(const AudioGroup* group, const SoundMacro* macro, uint8_t key, ObjToken<Voice> macroStart(const AudioGroup* group, const SoundMacro* macro, uint8_t key, uint8_t vel, uint8_t mod,
uint8_t vel, uint8_t mod, ObjToken<Studio> smx); ObjToken<Studio> smx);
ObjToken<Voice> macroStart(const AudioGroup* group, const SoundMacro* macro, uint8_t key, ObjToken<Voice> macroStart(const AudioGroup* group, const SoundMacro* macro, uint8_t key, uint8_t vel, uint8_t mod) {
uint8_t vel, uint8_t mod)
{
return macroStart(group, macro, key, vel, mod, m_defaultStudio); return macroStart(group, macro, key, vel, mod, m_defaultStudio);
} }
/** Start PageObject node playing directly (for editor use) */ /** Start PageObject node playing directly (for editor use) */
ObjToken<Voice> pageObjectStart(const AudioGroup* group, ObjectId id, uint8_t key, ObjToken<Voice> pageObjectStart(const AudioGroup* group, ObjectId id, uint8_t key, uint8_t vel, uint8_t mod,
uint8_t vel, uint8_t mod, ObjToken<Studio> smx); ObjToken<Studio> smx);
ObjToken<Voice> pageObjectStart(const AudioGroup* group, ObjectId id, uint8_t key, ObjToken<Voice> pageObjectStart(const AudioGroup* group, ObjectId id, uint8_t key, uint8_t vel, uint8_t mod) {
uint8_t vel, uint8_t mod)
{
return pageObjectStart(group, id, key, vel, mod, m_defaultStudio); return pageObjectStart(group, id, key, vel, mod, m_defaultStudio);
} }
/** Start soundFX playing from loaded audio groups, attach to positional emitter */ /** Start soundFX playing from loaded audio groups, attach to positional emitter */
ObjToken<Emitter> addEmitter(const float* pos, const float* dir, float maxDist, float falloff, ObjToken<Emitter> addEmitter(const float* pos, const float* dir, float maxDist, float falloff, SFXId sfxId,
SFXId sfxId, float minVol, float maxVol, bool doppler, ObjToken<Studio> smx); float minVol, float maxVol, bool doppler, ObjToken<Studio> smx);
ObjToken<Emitter> addEmitter(const float* pos, const float* dir, float maxDist, float falloff, ObjToken<Emitter> addEmitter(const float* pos, const float* dir, float maxDist, float falloff, SFXId sfxId,
SFXId sfxId, float minVol, float maxVol, bool doppler) float minVol, float maxVol, bool doppler) {
{
return addEmitter(pos, dir, maxDist, falloff, sfxId, minVol, maxVol, doppler, m_defaultStudio); return addEmitter(pos, dir, maxDist, falloff, sfxId, minVol, maxVol, doppler, m_defaultStudio);
} }
@ -147,16 +133,17 @@ public:
void removeListener(Listener* listener); void removeListener(Listener* listener);
/** Start song playing from loaded audio groups */ /** Start song playing from loaded audio groups */
ObjToken<Sequencer> seqPlay(GroupId groupId, SongId songId, const unsigned char* arrData, bool loop, ObjToken<Studio> smx); ObjToken<Sequencer> seqPlay(GroupId groupId, SongId songId, const unsigned char* arrData, bool loop,
ObjToken<Sequencer> seqPlay(GroupId groupId, SongId songId, const unsigned char* arrData, bool loop = true) ObjToken<Studio> smx);
{ ObjToken<Sequencer> seqPlay(GroupId groupId, SongId songId, const unsigned char* arrData, bool loop = true) {
return seqPlay(groupId, songId, arrData, loop, m_defaultStudio); return seqPlay(groupId, songId, arrData, loop, m_defaultStudio);
} }
/** Start song playing from explicit group data (for editor use) */ /** Start song playing from explicit group data (for editor use) */
ObjToken<Sequencer> seqPlay(const AudioGroup* group, GroupId groupId, SongId songId, const unsigned char* arrData, bool loop, ObjToken<Studio> smx); ObjToken<Sequencer> seqPlay(const AudioGroup* group, GroupId groupId, SongId songId, const unsigned char* arrData,
ObjToken<Sequencer> seqPlay(const AudioGroup* group, GroupId groupId, SongId songId, const unsigned char* arrData, bool loop = true) bool loop, ObjToken<Studio> smx);
{ ObjToken<Sequencer> seqPlay(const AudioGroup* group, GroupId groupId, SongId songId, const unsigned char* arrData,
bool loop = true) {
return seqPlay(group, groupId, songId, arrData, loop, m_defaultStudio); return seqPlay(group, groupId, songId, arrData, loop, m_defaultStudio);
} }
@ -192,5 +179,4 @@ public:
* perform periodic cleanup tasks */ * perform periodic cleanup tasks */
void _onPumpCycleComplete(IBackendVoiceAllocator& engine); void _onPumpCycleComplete(IBackendVoiceAllocator& engine);
}; };
} } // namespace amuse

View File

@ -5,14 +5,12 @@
#include <cassert> #include <cassert>
#include "Common.hpp" #include "Common.hpp"
namespace amuse namespace amuse {
{
class Engine; class Engine;
class AudioGroup; class AudioGroup;
/** Common 'engine child' class */ /** Common 'engine child' class */
class Entity : public IObj class Entity : public IObj {
{
/* Only the Engine will manage Entity lifetimes, /* Only the Engine will manage Entity lifetimes,
* but shared_ptrs are issued to the client so it can safely track state */ * but shared_ptrs are issued to the client so it can safely track state */
friend class Engine; friend class Engine;
@ -20,8 +18,7 @@ class Entity : public IObj
protected: protected:
bool m_destroyed = false; bool m_destroyed = false;
void _destroy() void _destroy() {
{
assert(!m_destroyed); assert(!m_destroyed);
m_destroyed = true; m_destroyed = true;
} }
@ -31,11 +28,8 @@ protected:
ObjectId m_objectId; /* if applicable */ ObjectId m_objectId; /* if applicable */
public: public:
Entity(Engine& engine, const AudioGroup& group, GroupId groupId, ObjectId oid = ObjectId()) Entity(Engine& engine, const AudioGroup& group, GroupId groupId, ObjectId oid = ObjectId())
: m_engine(engine), m_audioGroup(group), m_groupId(groupId), m_objectId(oid) : m_engine(engine), m_audioGroup(group), m_groupId(groupId), m_objectId(oid) {}
{ ~Entity() {
}
~Entity()
{
/* Ensure proper destruction procedure followed */ /* Ensure proper destruction procedure followed */
assert(m_destroyed); assert(m_destroyed);
} }
@ -47,5 +41,4 @@ public:
bool isDestroyed() const { return m_destroyed; } bool isDestroyed() const { return m_destroyed; }
}; };
} } // namespace amuse

View File

@ -2,22 +2,13 @@
#include "AudioGroupPool.hpp" #include "AudioGroupPool.hpp"
namespace amuse namespace amuse {
{
class Voice; class Voice;
/** Per-sample state tracker for ADSR envelope data */ /** Per-sample state tracker for ADSR envelope data */
class Envelope class Envelope {
{
public: public:
enum class State enum class State { Attack, Decay, Sustain, Release, Complete };
{
Attack,
Decay,
Sustain,
Release,
Complete
};
private: private:
State m_phase = State::Attack; /**< Current envelope state */ State m_phase = State::Attack; /**< Current envelope state */
@ -39,5 +30,4 @@ public:
bool isComplete() const { return m_phase == State::Complete; } bool isComplete() const { return m_phase == State::Complete; }
bool isAdsrSet() const { return m_adsrSet; } bool isAdsrSet() const { return m_adsrSet; }
}; };
} } // namespace amuse

View File

@ -2,21 +2,14 @@
#include <memory> #include <memory>
namespace amuse namespace amuse {
{
class IBackendVoice; class IBackendVoice;
class Voice; class Voice;
enum class SubmixFormat enum class SubmixFormat { Int16, Int32, Float };
{
Int16,
Int32,
Float
};
/** Client-implemented submix instance */ /** Client-implemented submix instance */
class IBackendSubmix class IBackendSubmix {
{
public: public:
virtual ~IBackendSubmix() = default; virtual ~IBackendSubmix() = default;
@ -29,5 +22,4 @@ public:
/** Amuse gets fixed sample format of submix this way */ /** Amuse gets fixed sample format of submix this way */
virtual SubmixFormat getSampleFormat() const = 0; virtual SubmixFormat getSampleFormat() const = 0;
}; };
} } // namespace amuse

View File

@ -1,12 +1,10 @@
#pragma once #pragma once
namespace amuse namespace amuse {
{
class IBackendSubmix; class IBackendSubmix;
/** Same channel enums from boo, used for matrix coefficient table index */ /** Same channel enums from boo, used for matrix coefficient table index */
enum class AudioChannel enum class AudioChannel {
{
FrontLeft, FrontLeft,
FrontRight, FrontRight,
RearLeft, RearLeft,
@ -19,15 +17,13 @@ enum class AudioChannel
}; };
/** Same structure from boo, used to represent interleaved speaker layout */ /** Same structure from boo, used to represent interleaved speaker layout */
struct ChannelMap struct ChannelMap {
{
unsigned m_channelCount = 0; unsigned m_channelCount = 0;
AudioChannel m_channels[8] = {}; AudioChannel m_channels[8] = {};
}; };
/** Client-implemented voice instance */ /** Client-implemented voice instance */
class IBackendVoice class IBackendVoice {
{
public: public:
virtual ~IBackendVoice() = default; virtual ~IBackendVoice() = default;
@ -49,5 +45,4 @@ public:
/** Instructs platform to stop consuming sample data */ /** Instructs platform to stop consuming sample data */
virtual void stop() = 0; virtual void stop() = 0;
}; };
} } // namespace amuse

View File

@ -4,8 +4,7 @@
#include <functional> #include <functional>
#include <vector> #include <vector>
namespace amuse namespace amuse {
{
class IBackendVoice; class IBackendVoice;
class IBackendSubmix; class IBackendSubmix;
class Voice; class Voice;
@ -13,26 +12,17 @@ class Submix;
class Engine; class Engine;
/** Same enum as boo for describing speaker-configuration */ /** Same enum as boo for describing speaker-configuration */
enum class AudioChannelSet enum class AudioChannelSet { Stereo, Quad, Surround51, Surround71, Unknown = 0xff };
{
Stereo,
Quad,
Surround51,
Surround71,
Unknown = 0xff
};
/** Handle to MIDI-reader, implementation opaque */ /** Handle to MIDI-reader, implementation opaque */
class IMIDIReader class IMIDIReader {
{
public: public:
virtual ~IMIDIReader() = default; virtual ~IMIDIReader() = default;
virtual void pumpReader(double dt) = 0; virtual void pumpReader(double dt) = 0;
}; };
/** Client-implemented voice allocator */ /** Client-implemented voice allocator */
class IBackendVoiceAllocator class IBackendVoiceAllocator {
{
public: public:
virtual ~IBackendVoiceAllocator() = default; virtual ~IBackendVoiceAllocator() = default;
@ -57,5 +47,4 @@ public:
/** Amuse registers for key callback events from the mixing engine this way */ /** Amuse registers for key callback events from the mixing engine this way */
virtual void setCallbackInterface(Engine* engine) = 0; virtual void setCallbackInterface(Engine* engine) = 0;
}; };
} } // namespace amuse

View File

@ -2,10 +2,8 @@
#include "amuse/Emitter.hpp" #include "amuse/Emitter.hpp"
namespace amuse namespace amuse {
{ class Listener {
class Listener
{
friend class Emitter; friend class Emitter;
friend class Engine; friend class Engine;
Vector3f m_pos = {}; Vector3f m_pos = {};
@ -18,11 +16,14 @@ class Listener
float m_backDiff; float m_backDiff;
float m_soundSpeed; float m_soundSpeed;
bool m_dirty = true; bool m_dirty = true;
public: public:
Listener(float volume, float frontDiff, float backDiff, float soundSpeed) Listener(float volume, float frontDiff, float backDiff, float soundSpeed)
: m_volume(clamp(0.f, volume, 1.f)), m_frontDiff(frontDiff), m_backDiff(backDiff), m_soundSpeed(soundSpeed) {} : m_volume(clamp(0.f, volume, 1.f)), m_frontDiff(frontDiff), m_backDiff(backDiff), m_soundSpeed(soundSpeed) {}
void setVectors(const float* pos, const float* dir, const float* heading, const float* up); void setVectors(const float* pos, const float* dir, const float* heading, const float* up);
void setVolume(float vol) { m_volume = clamp(0.f, vol, 1.f); m_dirty = true; } void setVolume(float vol) {
m_volume = clamp(0.f, vol, 1.f);
m_dirty = true;
}
}; };
} } // namespace amuse

View File

@ -2,18 +2,15 @@
#include <cstdint> #include <cstdint>
static inline int16_t N64MusyXSampClamp(int32_t val) static inline int16_t N64MusyXSampClamp(int32_t val) {
{ if (val < -32768)
if (val < -32768) val = -32768; val = -32768;
else if (val > 32767) val = 32767; else if (val > 32767)
val = 32767;
return val; return val;
} }
unsigned N64MusyXDecompressFrame(int16_t* out, const uint8_t* in, unsigned N64MusyXDecompressFrame(int16_t* out, const uint8_t* in, const int16_t coefs[8][2][8], unsigned lastSample);
const int16_t coefs[8][2][8],
unsigned lastSample);
unsigned N64MusyXDecompressFrameRanged(int16_t* out, const uint8_t* in, unsigned N64MusyXDecompressFrameRanged(int16_t* out, const uint8_t* in, const int16_t coefs[8][2][8],
const int16_t coefs[8][2][8],
unsigned firstSample, unsigned lastSample); unsigned firstSample, unsigned lastSample);

View File

@ -10,20 +10,17 @@
#include <memory> #include <memory>
#include <list> #include <list>
namespace amuse namespace amuse {
{
/** State of sequencer over lifetime */ /** State of sequencer over lifetime */
enum class SequencerState enum class SequencerState {
{
Playing, /**< Sequencer actively playing arrangement */ Playing, /**< Sequencer actively playing arrangement */
Interactive, /**< Interactive sequencer for live MIDI message processing, will not automatically die */ Interactive, /**< Interactive sequencer for live MIDI message processing, will not automatically die */
Dead /**< Set when arrangement complete and `dieOnEnd` was set, or manually with die() */ Dead /**< Set when arrangement complete and `dieOnEnd` was set, or manually with die() */
}; };
/** Multi-voice lifetime manager and polyphonic parameter tracking */ /** Multi-voice lifetime manager and polyphonic parameter tracking */
class Sequencer : public Entity class Sequencer : public Entity {
{
friend class Engine; friend class Engine;
const SongGroupIndex* m_songGroup = nullptr; /**< Quick access to song group project index */ const SongGroupIndex* m_songGroup = nullptr; /**< Quick access to song group project index */
const SongGroupIndex::MIDISetup* m_midiSetup = nullptr; /**< Selected MIDI setup (may be null) */ const SongGroupIndex::MIDISetup* m_midiSetup = nullptr; /**< Selected MIDI setup (may be null) */
@ -44,8 +41,7 @@ class Sequencer : public Entity
float m_stopFadeBeginVol = 0.f; float m_stopFadeBeginVol = 0.f;
/** State of a single MIDI channel */ /** State of a single MIDI channel */
struct ChannelState struct ChannelState {
{
Sequencer* m_parent = nullptr; Sequencer* m_parent = nullptr;
uint8_t m_chanId; uint8_t m_chanId;
const SongGroupIndex::MIDISetup* m_setup = nullptr; /* Channel defaults to program 0 if null */ const SongGroupIndex::MIDISetup* m_setup = nullptr; /* Channel defaults to program 0 if null */
@ -163,5 +159,4 @@ public:
/** Manually kill sequencer for deferred release from engine */ /** Manually kill sequencer for deferred release from engine */
void kill() { m_state = SequencerState::Dead; } void kill() { m_state = SequencerState::Dead; }
}; };
} } // namespace amuse

View File

@ -3,14 +3,11 @@
#include <vector> #include <vector>
#include <cstdint> #include <cstdint>
namespace amuse namespace amuse {
{
class SongConverter class SongConverter {
{
public: public:
static std::vector<uint8_t> SongToMIDI(const unsigned char* data, int& versionOut, bool& isBig); static std::vector<uint8_t> SongToMIDI(const unsigned char* data, int& versionOut, bool& isBig);
static std::vector<uint8_t> MIDIToSong(const std::vector<uint8_t>& data, int version, bool big); static std::vector<uint8_t> MIDIToSong(const std::vector<uint8_t>& data, int version, bool big);
}; };
} } // namespace amuse

View File

@ -6,25 +6,18 @@
#include <list> #include <list>
#include "Entity.hpp" #include "Entity.hpp"
namespace amuse namespace amuse {
{
class Sequencer; class Sequencer;
enum class SongPlayState enum class SongPlayState { Stopped, Playing };
{
Stopped,
Playing
};
/** Real-time state of Song execution */ /** Real-time state of Song execution */
class SongState class SongState {
{
friend class Voice; friend class Voice;
friend class SongConverter; friend class SongConverter;
/** Song header */ /** Song header */
struct Header struct Header {
{
uint32_t m_trackIdxOff; uint32_t m_trackIdxOff;
uint32_t m_regionIdxOff; uint32_t m_regionIdxOff;
uint32_t m_chanMapOff; uint32_t m_chanMapOff;
@ -40,8 +33,7 @@ class SongState
} m_header; } m_header;
/** Track region ('clip' in an NLA representation) */ /** Track region ('clip' in an NLA representation) */
struct TrackRegion struct TrackRegion {
{
uint32_t m_startTick; uint32_t m_startTick;
uint8_t m_progNum; uint8_t m_progNum;
uint8_t m_unk1; uint8_t m_unk1;
@ -54,8 +46,7 @@ class SongState
}; };
/** Tempo change entry */ /** Tempo change entry */
struct TempoChange struct TempoChange {
{
uint32_t m_tick; /**< Relative song ticks from previous tempo change */ uint32_t m_tick; /**< Relative song ticks from previous tempo change */
uint32_t m_tempo; /**< Tempo value in beats-per-minute (at 384 ticks per quarter-note) */ uint32_t m_tempo; /**< Tempo value in beats-per-minute (at 384 ticks per quarter-note) */
void swapBig(); void swapBig();
@ -66,10 +57,8 @@ class SongState
bool m_bigEndian; /**< True if loaded song is big-endian data */ bool m_bigEndian; /**< True if loaded song is big-endian data */
/** State of a single track within arrangement */ /** State of a single track within arrangement */
struct Track struct Track {
{ struct Header {
struct Header
{
uint32_t m_type; uint32_t m_type;
uint32_t m_pitchOff; uint32_t m_pitchOff;
uint32_t m_modOff; uint32_t m_modOff;
@ -134,5 +123,4 @@ public:
*/ */
bool advance(Sequencer& seq, double dt); bool advance(Sequencer& seq, double dt);
}; };
} } // namespace amuse

View File

@ -11,19 +11,14 @@
#undef SendMessage #undef SendMessage
#undef GetMessage #undef GetMessage
namespace amuse namespace amuse {
{
class Voice; class Voice;
/** Real-time state of SoundMacro execution */ /** Real-time state of SoundMacro execution */
struct SoundMacroState struct SoundMacroState {
{
/** 'program counter' stack for the active SoundMacro */ /** 'program counter' stack for the active SoundMacro */
std::vector<std::tuple<ObjectId, const SoundMacro*, int>> m_pc; std::vector<std::tuple<ObjectId, const SoundMacro*, int>> m_pc;
void _setPC(int pc) void _setPC(int pc) { std::get<2>(m_pc.back()) = std::get<1>(m_pc.back())->assertPC(pc); }
{
std::get<2>(m_pc.back()) = std::get<1>(m_pc.back())->assertPC(pc);
}
double m_ticksPerSec; /**< ratio for resolving ticks in commands that use them */ double m_ticksPerSec; /**< ratio for resolving ticks in commands that use them */
uint8_t m_initVel; /**< Velocity played for this macro invocation */ uint8_t m_initVel; /**< Velocity played for this macro invocation */
@ -59,32 +54,19 @@ struct SoundMacroState
float m_portamentoTime = 0.5f; /**< portamento transition time, 0.f will perform legato */ float m_portamentoTime = 0.5f; /**< portamento transition time, 0.f will perform legato */
/** Used to build a multi-component formula for overriding controllers */ /** Used to build a multi-component formula for overriding controllers */
struct Evaluator struct Evaluator {
{ enum class Combine : uint8_t { Set, Add, Mult };
enum class Combine : uint8_t enum class VarType : uint8_t { Ctrl, Var };
{
Set,
Add,
Mult
};
enum class VarType : uint8_t
{
Ctrl,
Var
};
/** Represents one term of the formula assembled via *_SELECT commands */ /** Represents one term of the formula assembled via *_SELECT commands */
struct Component struct Component {
{
uint8_t m_midiCtrl; uint8_t m_midiCtrl;
float m_scale; float m_scale;
Combine m_combine; Combine m_combine;
VarType m_varType; VarType m_varType;
Component(uint8_t midiCtrl, float scale, Combine combine, VarType varType) Component(uint8_t midiCtrl, float scale, Combine combine, VarType varType)
: m_midiCtrl(midiCtrl), m_scale(scale), m_combine(combine), m_varType(varType) : m_midiCtrl(midiCtrl), m_scale(scale), m_combine(combine), m_varType(varType) {}
{
}
}; };
std::vector<Component> m_comps; /**< Components built up by the macro */ std::vector<Component> m_comps; /**< Components built up by the macro */
@ -117,8 +99,7 @@ struct SoundMacroState
int32_t m_variables[32]; /**< 32-bit variables set with relevant commands */ int32_t m_variables[32]; /**< 32-bit variables set with relevant commands */
/** Event registration data for TRAP_EVENT */ /** Event registration data for TRAP_EVENT */
struct EventTrap struct EventTrap {
{
ObjectId macroId = 0xffff; ObjectId macroId = 0xffff;
uint16_t macroStep; uint16_t macroStep;
}; };
@ -126,8 +107,8 @@ struct SoundMacroState
public: public:
/** initialize state for SoundMacro data at `ptr` */ /** initialize state for SoundMacro data at `ptr` */
void initialize(ObjectId id, const SoundMacro* macro, int step); void initialize(ObjectId id, const SoundMacro* macro, int step);
void initialize(ObjectId id, const SoundMacro* macro, int step, double ticksPerSec, void initialize(ObjectId id, const SoundMacro* macro, int step, double ticksPerSec, uint8_t midiKey, uint8_t midiVel,
uint8_t midiKey, uint8_t midiVel, uint8_t midiMod); uint8_t midiMod);
/** advances `dt` seconds worth of commands in the SoundMacro /** advances `dt` seconds worth of commands in the SoundMacro
* @return `true` if END reached * @return `true` if END reached
@ -140,5 +121,4 @@ public:
/** sample end event */ /** sample end event */
void sampleEndNotify(Voice& vox); void sampleEndNotify(Voice& vox);
}; };
} } // namespace amuse

View File

@ -6,12 +6,10 @@
#include "Submix.hpp" #include "Submix.hpp"
#include <type_traits> #include <type_traits>
namespace amuse namespace amuse {
{
struct StudioSend; struct StudioSend;
class Studio class Studio {
{
friend class Engine; friend class Engine;
Engine& m_engine; Engine& m_engine;
Submix m_master; Submix m_master;
@ -39,17 +37,13 @@ public:
Engine& getEngine() { return m_engine; } Engine& getEngine() { return m_engine; }
}; };
struct StudioSend struct StudioSend {
{
ObjToken<Studio> m_targetStudio; ObjToken<Studio> m_targetStudio;
float m_dryLevel; float m_dryLevel;
float m_auxALevel; float m_auxALevel;
float m_auxBLevel; float m_auxBLevel;
StudioSend(ObjToken<Studio> studio, float dry, float auxA, float auxB) StudioSend(ObjToken<Studio> studio, float dry, float auxA, float auxB)
: m_targetStudio(studio), m_dryLevel(dry), m_auxALevel(auxA), m_auxBLevel(auxB) : m_targetStudio(studio), m_dryLevel(dry), m_auxALevel(auxA), m_auxBLevel(auxB) {}
{
}
}; };
} } // namespace amuse

View File

@ -10,14 +10,12 @@
#include "EffectReverb.hpp" #include "EffectReverb.hpp"
#include <unordered_set> #include <unordered_set>
namespace amuse namespace amuse {
{
class IBackendSubmix; class IBackendSubmix;
class Sequencer; class Sequencer;
/** Intermediate mix of voices for applying auxiliary effects */ /** Intermediate mix of voices for applying auxiliary effects */
class Submix class Submix {
{
friend class Engine; friend class Engine;
friend class Voice; friend class Voice;
friend class Sequencer; friend class Sequencer;
@ -30,23 +28,18 @@ public:
/** Construct new effect */ /** Construct new effect */
template <class T, class... Args> template <class T, class... Args>
std::unique_ptr<EffectBaseTypeless> _makeEffect(Args... args) std::unique_ptr<EffectBaseTypeless> _makeEffect(Args... args) {
{ switch (m_backendSubmix->getSampleFormat()) {
switch (m_backendSubmix->getSampleFormat()) case SubmixFormat::Int16: {
{
case SubmixFormat::Int16:
{
using ImpType = typename T::template ImpType<int16_t>; using ImpType = typename T::template ImpType<int16_t>;
return std::make_unique<ImpType>(args..., m_backendSubmix->getSampleRate()); return std::make_unique<ImpType>(args..., m_backendSubmix->getSampleRate());
} }
case SubmixFormat::Int32: case SubmixFormat::Int32:
default: default: {
{
using ImpType = typename T::template ImpType<int32_t>; using ImpType = typename T::template ImpType<int32_t>;
return std::make_unique<ImpType>(args..., m_backendSubmix->getSampleRate()); return std::make_unique<ImpType>(args..., m_backendSubmix->getSampleRate());
} }
case SubmixFormat::Float: case SubmixFormat::Float: {
{
using ImpType = typename T::template ImpType<float>; using ImpType = typename T::template ImpType<float>;
return std::make_unique<ImpType>(args..., m_backendSubmix->getSampleRate()); return std::make_unique<ImpType>(args..., m_backendSubmix->getSampleRate());
} }
@ -55,8 +48,7 @@ public:
/** Add new effect to effect stack and assume ownership */ /** Add new effect to effect stack and assume ownership */
template <class T, class... Args> template <class T, class... Args>
T& makeEffect(Args... args) T& makeEffect(Args... args) {
{
m_effectStack.push_back(_makeEffect<T>(args...)); m_effectStack.push_back(_makeEffect<T>(args...));
return static_cast<typename T::template ImpType<float>&>(*m_effectStack.back()); return static_cast<typename T::template ImpType<float>&>(*m_effectStack.back());
} }
@ -80,8 +72,7 @@ public:
EffectReverbStd& makeReverbStd(const EffectReverbStdInfo& info); EffectReverbStd& makeReverbStd(const EffectReverbStdInfo& info);
/** Add new high-quality reverb effect to effect stack and assume ownership */ /** Add new high-quality reverb effect to effect stack and assume ownership */
EffectReverbHi& makeReverbHi(float coloration, float mix, float time, float damping, float preDelay, EffectReverbHi& makeReverbHi(float coloration, float mix, float time, float damping, float preDelay, float crosstalk);
float crosstalk);
/** Add new high-quality reverb effect to effect stack and assume ownership */ /** Add new high-quality reverb effect to effect stack and assume ownership */
EffectReverbHi& makeReverbHi(const EffectReverbHiInfo& info); EffectReverbHi& makeReverbHi(const EffectReverbHiInfo& info);
@ -108,5 +99,4 @@ public:
std::vector<std::unique_ptr<EffectBaseTypeless>>& getEffectStack() { return m_effectStack; } std::vector<std::unique_ptr<EffectBaseTypeless>>& getEffectStack() { return m_effectStack; }
}; };
} } // namespace amuse

View File

@ -12,23 +12,20 @@
#include "Envelope.hpp" #include "Envelope.hpp"
#include "Studio.hpp" #include "Studio.hpp"
namespace amuse namespace amuse {
{
class IBackendVoice; class IBackendVoice;
struct Keymap; struct Keymap;
struct LayerMapping; struct LayerMapping;
/** State of voice over lifetime */ /** State of voice over lifetime */
enum class VoiceState enum class VoiceState {
{
Playing, /**< SoundMacro actively executing, not in KeyOff */ Playing, /**< SoundMacro actively executing, not in KeyOff */
KeyOff, /**< KeyOff event issued, macro beginning fade-out */ KeyOff, /**< KeyOff event issued, macro beginning fade-out */
Dead /**< Default state, causes Engine to remove voice at end of pump cycle */ Dead /**< Default state, causes Engine to remove voice at end of pump cycle */
}; };
/** Individual source of audio */ /** Individual source of audio */
class Voice : public Entity class Voice : public Entity {
{
friend class Engine; friend class Engine;
friend class Sequencer; friend class Sequencer;
friend struct SoundMacroState; friend struct SoundMacroState;
@ -44,8 +41,7 @@ class Voice : public Entity
friend struct SoundMacro::CmdGetMessage; friend struct SoundMacro::CmdGetMessage;
friend struct SoundMacro::CmdModeSelect; friend struct SoundMacro::CmdModeSelect;
struct VolumeCache struct VolumeCache {
{
bool m_curDLS = false; /**< Current DLS status of cached lookup */ bool m_curDLS = false; /**< Current DLS status of cached lookup */
float m_curVolLUTKey = -1.f; /**< Current input level cached out of LUT */ float m_curVolLUTKey = -1.f; /**< Current input level cached out of LUT */
float m_curVolLUTVal = 0.f; /**< Current output level cached out of LUT */ float m_curVolLUTVal = 0.f; /**< Current output level cached out of LUT */
@ -53,8 +49,7 @@ class Voice : public Entity
float getCachedVolume() const { return m_curVolLUTVal; } float getCachedVolume() const { return m_curVolLUTVal; }
}; };
struct Panning struct Panning {
{
double m_time; /**< time of PANNING command */ double m_time; /**< time of PANNING command */
double m_dur; /**< requested duration of PANNING command */ double m_dur; /**< requested duration of PANNING command */
uint8_t m_pos; /**< initial pan value of PANNING command */ uint8_t m_pos; /**< initial pan value of PANNING command */
@ -180,12 +175,12 @@ class Voice : public Entity
std::list<ObjToken<Voice>>::iterator _allocateVoice(double sampleRate, bool dynamicPitch); std::list<ObjToken<Voice>>::iterator _allocateVoice(double sampleRate, bool dynamicPitch);
std::list<ObjToken<Voice>>::iterator _destroyVoice(std::list<ObjToken<Voice>>::iterator it); std::list<ObjToken<Voice>>::iterator _destroyVoice(std::list<ObjToken<Voice>>::iterator it);
bool _loadSoundMacro(SoundMacroId id, const SoundMacro* macroData, int macroStep, double ticksPerSec, bool _loadSoundMacro(SoundMacroId id, const SoundMacro* macroData, int macroStep, double ticksPerSec, uint8_t midiKey,
uint8_t midiKey, uint8_t midiVel, uint8_t midiMod, bool pushPc = false);
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(const std::vector<LayerMapping>& layer, double ticksPerSec, bool _loadKeymap(const Keymap* keymap, double ticksPerSec, uint8_t midiKey, uint8_t midiVel, uint8_t midiMod,
uint8_t midiKey, uint8_t midiVel, uint8_t midiMod, bool pushPc = false); bool pushPc = false);
bool _loadLayer(const std::vector<LayerMapping>& layer, double ticksPerSec, uint8_t midiKey, uint8_t midiVel,
uint8_t midiMod, bool pushPc = false);
ObjToken<Voice> _startChildMacro(ObjectId macroId, int macroStep, double ticksPerSec, uint8_t midiKey, ObjToken<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);
@ -342,10 +337,8 @@ public:
bool doPortamento(uint8_t newNote); bool doPortamento(uint8_t newNote);
/** Get MIDI Controller value on voice */ /** Get MIDI Controller value on voice */
int8_t getCtrlValue(uint8_t ctrl) const int8_t getCtrlValue(uint8_t ctrl) const {
{ if (!m_extCtrlVals) {
if (!m_extCtrlVals)
{
if (m_ctrlValsSelf) if (m_ctrlValsSelf)
return m_ctrlValsSelf[ctrl]; return m_ctrlValsSelf[ctrl];
return 0; return 0;
@ -354,21 +347,17 @@ public:
} }
/** Set MIDI Controller value on voice */ /** Set MIDI Controller value on voice */
void setCtrlValue(uint8_t ctrl, int8_t val) void setCtrlValue(uint8_t ctrl, int8_t val) {
{ if (!m_extCtrlVals) {
if (!m_extCtrlVals)
{
std::unique_ptr<int8_t[]>& vals = _ensureCtrlVals(); std::unique_ptr<int8_t[]>& vals = _ensureCtrlVals();
vals[ctrl] = val; vals[ctrl] = val;
} } else
else
m_extCtrlVals[ctrl] = val; m_extCtrlVals[ctrl] = val;
_notifyCtrlChange(ctrl, val); _notifyCtrlChange(ctrl, val);
} }
/** 'install' external MIDI controller storage */ /** 'install' external MIDI controller storage */
void installCtrlValues(int8_t* cvs) void installCtrlValues(int8_t* cvs) {
{
m_ctrlValsSelf.reset(); m_ctrlValsSelf.reset();
m_extCtrlVals = cvs; m_extCtrlVals = cvs;
for (ObjToken<Voice>& vox : m_childVoices) for (ObjToken<Voice>& vox : m_childVoices)
@ -390,5 +379,4 @@ public:
/** Recursively mark voice as dead for Engine to deallocate on next cycle */ /** Recursively mark voice as dead for Engine to deallocate on next cycle */
void kill(); void kill();
}; };
} } // namespace amuse

View File

@ -1,8 +1,6 @@
#pragma once #pragma once
namespace amuse namespace amuse {
{
float LookupVolume(float vol); float LookupVolume(float vol);
float LookupDLSVolume(float vol); float LookupDLSVolume(float vol);
} } // namespace amuse

View File

@ -1,6 +1,5 @@
#pragma once #pragma once
#include "AudioGroup.hpp" #include "AudioGroup.hpp"
#include "AudioGroupData.hpp" #include "AudioGroupData.hpp"
#include "AudioGroupPool.hpp" #include "AudioGroupPool.hpp"
@ -20,4 +19,3 @@
#include "SongState.hpp" #include "SongState.hpp"
#include "Submix.hpp" #include "Submix.hpp"
#include "Voice.hpp" #include "Voice.hpp"

View File

@ -10,11 +10,9 @@
#undef log2 #undef log2
#undef fabs #undef fabs
namespace std namespace std {
{ using ::exp2;
using ::exp2; using ::fabs;
using ::log2; using ::log2;
using ::fabs; } // namespace std
}
#endif #endif

View File

@ -5,18 +5,15 @@
using namespace std::literals; using namespace std::literals;
namespace amuse namespace amuse {
{
void AudioGroup::assign(const AudioGroupData& data) void AudioGroup::assign(const AudioGroupData& data) {
{
m_pool = AudioGroupPool::CreateAudioGroupPool(data); m_pool = AudioGroupPool::CreateAudioGroupPool(data);
m_proj = AudioGroupProject::CreateAudioGroupProject(data); m_proj = AudioGroupProject::CreateAudioGroupProject(data);
m_sdir = AudioGroupSampleDirectory::CreateAudioGroupSampleDirectory(data); m_sdir = AudioGroupSampleDirectory::CreateAudioGroupSampleDirectory(data);
m_samp = data.getSamp(); m_samp = data.getSamp();
} }
void AudioGroup::assign(SystemStringView groupPath) void AudioGroup::assign(SystemStringView groupPath) {
{
/* Reverse order when loading intermediates */ /* Reverse order when loading intermediates */
m_groupPath = groupPath; m_groupPath = groupPath;
m_sdir = AudioGroupSampleDirectory::CreateAudioGroupSampleDirectory(groupPath); m_sdir = AudioGroupSampleDirectory::CreateAudioGroupSampleDirectory(groupPath);
@ -24,8 +21,7 @@ void AudioGroup::assign(SystemStringView groupPath)
m_proj = AudioGroupProject::CreateAudioGroupProject(groupPath); m_proj = AudioGroupProject::CreateAudioGroupProject(groupPath);
m_samp = nullptr; m_samp = nullptr;
} }
void AudioGroup::assign(const AudioGroup& data, SystemStringView groupPath) void AudioGroup::assign(const AudioGroup& data, SystemStringView groupPath) {
{
/* Reverse order when loading intermediates */ /* Reverse order when loading intermediates */
m_groupPath = groupPath; m_groupPath = groupPath;
m_sdir = AudioGroupSampleDirectory::CreateAudioGroupSampleDirectory(groupPath); m_sdir = AudioGroupSampleDirectory::CreateAudioGroupSampleDirectory(groupPath);
@ -34,30 +30,24 @@ void AudioGroup::assign(const AudioGroup& data, SystemStringView groupPath)
m_samp = nullptr; m_samp = nullptr;
} }
const SampleEntry* AudioGroup::getSample(SampleId sfxId) const const SampleEntry* AudioGroup::getSample(SampleId sfxId) const {
{
auto search = m_sdir.m_entries.find(sfxId); auto search = m_sdir.m_entries.find(sfxId);
if (search == m_sdir.m_entries.cend()) if (search == m_sdir.m_entries.cend())
return nullptr; return nullptr;
return search->second.get(); return search->second.get();
} }
SystemString AudioGroup::getSampleBasePath(SampleId sfxId) const SystemString AudioGroup::getSampleBasePath(SampleId sfxId) const {
{
#if _WIN32 #if _WIN32
return m_groupPath + _SYS_STR('/') + return m_groupPath + _SYS_STR('/') + athena::utility::utf8ToWide(SampleId::CurNameDB->resolveNameFromId(sfxId));
athena::utility::utf8ToWide(SampleId::CurNameDB->resolveNameFromId(sfxId));
#else #else
return m_groupPath + _SYS_STR('/') + return m_groupPath + _SYS_STR('/') + SampleId::CurNameDB->resolveNameFromId(sfxId).data();
SampleId::CurNameDB->resolveNameFromId(sfxId).data();
#endif #endif
} }
std::pair<ObjToken<SampleEntryData>, const unsigned char*> std::pair<ObjToken<SampleEntryData>, const unsigned char*> AudioGroup::getSampleData(SampleId sfxId,
AudioGroup::getSampleData(SampleId sfxId, const SampleEntry* sample) const const SampleEntry* sample) const {
{ if (sample->m_data->m_looseData) {
if (sample->m_data->m_looseData)
{
setIdDatabases(); setIdDatabases();
SystemString basePath = getSampleBasePath(sfxId); SystemString basePath = getSampleBasePath(sfxId);
const_cast<SampleEntry*>(sample)->loadLooseData(basePath); const_cast<SampleEntry*>(sample)->loadLooseData(basePath);
@ -66,10 +56,8 @@ std::pair<ObjToken<SampleEntryData>, const unsigned char*>
return {sample->m_data, m_samp + sample->m_data->m_sampleOff}; return {sample->m_data, m_samp + sample->m_data->m_sampleOff};
} }
SampleFileState AudioGroup::getSampleFileState(SampleId sfxId, const SampleEntry* sample, SystemString* pathOut) const SampleFileState AudioGroup::getSampleFileState(SampleId sfxId, const SampleEntry* sample, SystemString* pathOut) const {
{ if (sample->m_data->m_looseData) {
if (sample->m_data->m_looseData)
{
setIdDatabases(); setIdDatabases();
SystemString basePath = getSampleBasePath(sfxId); SystemString basePath = getSampleBasePath(sfxId);
return sample->getFileState(basePath, pathOut); return sample->getFileState(basePath, pathOut);
@ -79,36 +67,29 @@ SampleFileState AudioGroup::getSampleFileState(SampleId sfxId, const SampleEntry
return SampleFileState::MemoryOnlyWAV; return SampleFileState::MemoryOnlyWAV;
} }
void AudioGroup::patchSampleMetadata(SampleId sfxId, const SampleEntry* sample) const void AudioGroup::patchSampleMetadata(SampleId sfxId, const SampleEntry* sample) const {
{ if (sample->m_data->m_looseData) {
if (sample->m_data->m_looseData)
{
setIdDatabases(); setIdDatabases();
SystemString basePath = getSampleBasePath(sfxId); SystemString basePath = getSampleBasePath(sfxId);
sample->patchSampleMetadata(basePath); sample->patchSampleMetadata(basePath);
} }
} }
void AudioGroup::makeWAVVersion(SampleId sfxId, const SampleEntry* sample) const void AudioGroup::makeWAVVersion(SampleId sfxId, const SampleEntry* sample) const {
{ if (sample->m_data->m_looseData) {
if (sample->m_data->m_looseData)
{
setIdDatabases(); setIdDatabases();
m_sdir._extractWAV(sfxId, *sample->m_data, m_groupPath, sample->m_data->m_looseData.get()); m_sdir._extractWAV(sfxId, *sample->m_data, m_groupPath, sample->m_data->m_looseData.get());
} }
} }
void AudioGroup::makeCompressedVersion(SampleId sfxId, const SampleEntry* sample) const void AudioGroup::makeCompressedVersion(SampleId sfxId, const SampleEntry* sample) const {
{ if (sample->m_data->m_looseData) {
if (sample->m_data->m_looseData)
{
setIdDatabases(); setIdDatabases();
m_sdir._extractCompressed(sfxId, *sample->m_data, m_groupPath, sample->m_data->m_looseData.get(), true); m_sdir._extractCompressed(sfxId, *sample->m_data, m_groupPath, sample->m_data->m_looseData.get(), true);
} }
} }
void AudioGroupDatabase::renameSample(SampleId id, std::string_view str) void AudioGroupDatabase::renameSample(SampleId id, std::string_view str) {
{
SystemString oldBasePath = getSampleBasePath(id); SystemString oldBasePath = getSampleBasePath(id);
SampleId::CurNameDB->rename(id, str); SampleId::CurNameDB->rename(id, str);
SystemString newBasePath = getSampleBasePath(id); SystemString newBasePath = getSampleBasePath(id);
@ -117,33 +98,27 @@ void AudioGroupDatabase::renameSample(SampleId id, std::string_view str)
Rename((oldBasePath + _SYS_STR(".vadpcm")).c_str(), (newBasePath + _SYS_STR(".vadpcm")).c_str()); Rename((oldBasePath + _SYS_STR(".vadpcm")).c_str(), (newBasePath + _SYS_STR(".vadpcm")).c_str());
} }
void AudioGroupDatabase::deleteSample(SampleId id) void AudioGroupDatabase::deleteSample(SampleId id) {
{
SystemString basePath = getSampleBasePath(id); SystemString basePath = getSampleBasePath(id);
Unlink((basePath + _SYS_STR(".wav")).c_str()); Unlink((basePath + _SYS_STR(".wav")).c_str());
Unlink((basePath + _SYS_STR(".dsp")).c_str()); Unlink((basePath + _SYS_STR(".dsp")).c_str());
Unlink((basePath + _SYS_STR(".vadpcm")).c_str()); Unlink((basePath + _SYS_STR(".vadpcm")).c_str());
} }
void AudioGroupDatabase::copySampleInto(const SystemString& basePath, const SystemString& newBasePath) void AudioGroupDatabase::copySampleInto(const SystemString& basePath, const SystemString& newBasePath) {
{
Copy((basePath + _SYS_STR(".wav")).c_str(), (newBasePath + _SYS_STR(".wav")).c_str()); Copy((basePath + _SYS_STR(".wav")).c_str(), (newBasePath + _SYS_STR(".wav")).c_str());
Copy((basePath + _SYS_STR(".dsp")).c_str(), (newBasePath + _SYS_STR(".dsp")).c_str()); Copy((basePath + _SYS_STR(".dsp")).c_str(), (newBasePath + _SYS_STR(".dsp")).c_str());
Copy((basePath + _SYS_STR(".vadpcm")).c_str(), (newBasePath + _SYS_STR(".vadpcm")).c_str()); Copy((basePath + _SYS_STR(".vadpcm")).c_str(), (newBasePath + _SYS_STR(".vadpcm")).c_str());
} }
void AudioGroupDatabase::_recursiveRenameMacro(SoundMacroId id, std::string_view str, int& macroIdx, void AudioGroupDatabase::_recursiveRenameMacro(SoundMacroId id, std::string_view str, int& macroIdx,
std::unordered_set<SoundMacroId>& renamedIds) std::unordered_set<SoundMacroId>& renamedIds) {
{
if (renamedIds.find(id) != renamedIds.cend()) if (renamedIds.find(id) != renamedIds.cend())
return; return;
if (const SoundMacro* macro = getPool().soundMacro(id)) if (const SoundMacro* macro = getPool().soundMacro(id)) {
{ if (!strncmp(SoundMacroId::CurNameDB->resolveNameFromId(id).data(), "macro", 5)) {
if (!strncmp(SoundMacroId::CurNameDB->resolveNameFromId(id).data(), "macro", 5))
{
std::string macroName("macro"sv); std::string macroName("macro"sv);
if (macroIdx) if (macroIdx) {
{
char num[16]; char num[16];
snprintf(num, 16, "%d", macroIdx); snprintf(num, 16, "%d", macroIdx);
macroName += num; macroName += num;
@ -154,18 +129,13 @@ void AudioGroupDatabase::_recursiveRenameMacro(SoundMacroId id, std::string_view
SoundMacroId::CurNameDB->rename(id, macroName); SoundMacroId::CurNameDB->rename(id, macroName);
renamedIds.insert(id); renamedIds.insert(id);
int sampleIdx = 0; int sampleIdx = 0;
for (const auto& cmd : macro->m_cmds) for (const auto& cmd : macro->m_cmds) {
{ switch (cmd->Isa()) {
switch (cmd->Isa()) case SoundMacro::CmdOp::StartSample: {
{
case SoundMacro::CmdOp::StartSample:
{
SoundMacro::CmdStartSample* ss = static_cast<SoundMacro::CmdStartSample*>(cmd.get()); SoundMacro::CmdStartSample* ss = static_cast<SoundMacro::CmdStartSample*>(cmd.get());
if (!strncmp(SampleId::CurNameDB->resolveNameFromId(ss->sample.id).data(), "sample", 6)) if (!strncmp(SampleId::CurNameDB->resolveNameFromId(ss->sample.id).data(), "sample", 6)) {
{
std::string sampleName("sample"sv); std::string sampleName("sample"sv);
if (sampleIdx) if (sampleIdx) {
{
char num[16]; char num[16];
snprintf(num, 16, "%d", sampleIdx); snprintf(num, 16, "%d", sampleIdx);
sampleName += num; sampleName += num;
@ -212,21 +182,16 @@ void AudioGroupDatabase::_recursiveRenameMacro(SoundMacroId id, std::string_view
} }
} }
static const std::regex DefineGRPEntry(R"(#define\s+GRP(\S+)\s+(\S+))", static const std::regex DefineGRPEntry(R"(#define\s+GRP(\S+)\s+(\S+))", std::regex::ECMAScript | std::regex::optimize);
std::regex::ECMAScript|std::regex::optimize); static const std::regex DefineSNGEntry(R"(#define\s+SNG(\S+)\s+(\S+))", std::regex::ECMAScript | std::regex::optimize);
static const std::regex DefineSNGEntry(R"(#define\s+SNG(\S+)\s+(\S+))", static const std::regex DefineSFXEntry(R"(#define\s+SFX(\S+)\s+(\S+))", std::regex::ECMAScript | std::regex::optimize);
std::regex::ECMAScript|std::regex::optimize);
static const std::regex DefineSFXEntry(R"(#define\s+SFX(\S+)\s+(\S+))",
std::regex::ECMAScript|std::regex::optimize);
void AudioGroupDatabase::importCHeader(std::string_view header) void AudioGroupDatabase::importCHeader(std::string_view header) {
{
setIdDatabases(); setIdDatabases();
std::match_results<std::string_view::const_iterator> dirMatch; std::match_results<std::string_view::const_iterator> dirMatch;
auto begin = header.cbegin(); auto begin = header.cbegin();
auto end = header.cend(); auto end = header.cend();
while (std::regex_search(begin, end, dirMatch, DefineGRPEntry)) while (std::regex_search(begin, end, dirMatch, DefineGRPEntry)) {
{
std::string key = dirMatch[1].str(); std::string key = dirMatch[1].str();
std::string value = dirMatch[2].str(); std::string value = dirMatch[2].str();
char* endPtr; char* endPtr;
@ -239,8 +204,7 @@ void AudioGroupDatabase::importCHeader(std::string_view header)
} }
begin = header.cbegin(); begin = header.cbegin();
end = header.cend(); end = header.cend();
while (std::regex_search(begin, end, dirMatch, DefineSNGEntry)) while (std::regex_search(begin, end, dirMatch, DefineSNGEntry)) {
{
std::string key = dirMatch[1].str(); std::string key = dirMatch[1].str();
std::string value = dirMatch[2].str(); std::string value = dirMatch[2].str();
char* endPtr; char* endPtr;
@ -254,8 +218,7 @@ void AudioGroupDatabase::importCHeader(std::string_view header)
begin = header.cbegin(); begin = header.cbegin();
end = header.cend(); end = header.cend();
std::unordered_set<SoundMacroId> renamedMacroIDs; std::unordered_set<SoundMacroId> renamedMacroIDs;
while (std::regex_search(begin, end, dirMatch, DefineSFXEntry)) while (std::regex_search(begin, end, dirMatch, DefineSFXEntry)) {
{
std::string key = dirMatch[1].str(); std::string key = dirMatch[1].str();
std::string value = dirMatch[2].str(); std::string value = dirMatch[2].str();
char* endPtr; char* endPtr;
@ -265,12 +228,9 @@ void AudioGroupDatabase::importCHeader(std::string_view header)
continue; continue;
SFXId::CurNameDB->rename(id, key); SFXId::CurNameDB->rename(id, key);
int macroIdx = 0; int macroIdx = 0;
for (auto& sfxGrp : getProj().sfxGroups()) for (auto& sfxGrp : getProj().sfxGroups()) {
{ for (auto& sfx : sfxGrp.second->m_sfxEntries) {
for (auto& sfx : sfxGrp.second->m_sfxEntries) if (sfx.first == id) {
{
if (sfx.first == id)
{
ObjectId sfxObjId = sfx.second.objId; ObjectId sfxObjId = sfx.second.objId;
if (sfxObjId == ObjectId() || sfxObjId.id & 0xc000) if (sfxObjId == ObjectId() || sfxObjId.id & 0xc000)
continue; continue;
@ -282,8 +242,7 @@ void AudioGroupDatabase::importCHeader(std::string_view header)
} }
} }
static void WriteDefineLine(std::string& ret, std::string_view typeStr, std::string_view name, ObjectId id) static void WriteDefineLine(std::string& ret, std::string_view typeStr, std::string_view name, ObjectId id) {
{
ret += "#define "sv; ret += "#define "sv;
ret += typeStr; ret += typeStr;
ret += name; ret += name;
@ -294,18 +253,20 @@ static void WriteDefineLine(std::string& ret, std::string_view typeStr, std::str
ret += '\n'; ret += '\n';
} }
std::string AudioGroupDatabase::exportCHeader(std::string_view projectName, std::string_view groupName) const std::string AudioGroupDatabase::exportCHeader(std::string_view projectName, std::string_view groupName) const {
{
setIdDatabases(); setIdDatabases();
std::string ret; std::string ret;
ret += "/* Auto-generated Amuse Defines\n" ret +=
"/* Auto-generated Amuse Defines\n"
" *\n" " *\n"
" * Project: "sv; " * Project: "sv;
ret += projectName; ret += projectName;
ret += "\n" ret +=
"\n"
" * Subproject: "sv; " * Subproject: "sv;
ret += groupName; ret += groupName;
ret += "\n" ret +=
"\n"
" * Date: "sv; " * Date: "sv;
time_t curTime = time(nullptr); time_t curTime = time(nullptr);
#ifndef _WIN32 #ifndef _WIN32
@ -322,18 +283,17 @@ std::string AudioGroupDatabase::exportCHeader(std::string_view projectName, std:
if (char* ch = strchr(curTmStr, '\n')) if (char* ch = strchr(curTmStr, '\n'))
*ch = '\0'; *ch = '\0';
ret += curTmStr; ret += curTmStr;
ret += "\n" ret +=
"\n"
" */\n\n\n"sv; " */\n\n\n"sv;
bool addLF = false; bool addLF = false;
for (const auto& sg : SortUnorderedMap(getProj().songGroups())) for (const auto& sg : SortUnorderedMap(getProj().songGroups())) {
{
auto name = amuse::GroupId::CurNameDB->resolveNameFromId(sg.first); auto name = amuse::GroupId::CurNameDB->resolveNameFromId(sg.first);
WriteDefineLine(ret, "GRP"sv, name, sg.first); WriteDefineLine(ret, "GRP"sv, name, sg.first);
addLF = true; addLF = true;
} }
for (const auto& sg : SortUnorderedMap(getProj().sfxGroups())) for (const auto& sg : SortUnorderedMap(getProj().sfxGroups())) {
{
auto name = amuse::GroupId::CurNameDB->resolveNameFromId(sg.first); auto name = amuse::GroupId::CurNameDB->resolveNameFromId(sg.first);
WriteDefineLine(ret, "GRP"sv, name, sg.first); WriteDefineLine(ret, "GRP"sv, name, sg.first);
addLF = true; addLF = true;
@ -347,8 +307,7 @@ std::string AudioGroupDatabase::exportCHeader(std::string_view projectName, std:
for (const auto& sg : getProj().songGroups()) for (const auto& sg : getProj().songGroups())
for (const auto& song : sg.second->m_midiSetups) for (const auto& song : sg.second->m_midiSetups)
songIds.insert(song.first); songIds.insert(song.first);
for (amuse::SongId id : SortUnorderedSet(songIds)) for (amuse::SongId id : SortUnorderedSet(songIds)) {
{
auto name = amuse::SongId::CurNameDB->resolveNameFromId(id); auto name = amuse::SongId::CurNameDB->resolveNameFromId(id);
WriteDefineLine(ret, "SNG"sv, name, id); WriteDefineLine(ret, "SNG"sv, name, id);
addLF = true; addLF = true;
@ -358,10 +317,8 @@ std::string AudioGroupDatabase::exportCHeader(std::string_view projectName, std:
ret += "\n\n"sv; ret += "\n\n"sv;
addLF = false; addLF = false;
for (const auto& sg : SortUnorderedMap(getProj().sfxGroups())) for (const auto& sg : SortUnorderedMap(getProj().sfxGroups())) {
{ for (const auto& sfx : SortUnorderedMap(sg.second.get()->m_sfxEntries)) {
for (const auto& sfx : SortUnorderedMap(sg.second.get()->m_sfxEntries))
{
auto name = amuse::SFXId::CurNameDB->resolveNameFromId(sfx.first); auto name = amuse::SFXId::CurNameDB->resolveNameFromId(sfx.first);
WriteDefineLine(ret, "SFX"sv, name, sfx.first.id); WriteDefineLine(ret, "SFX"sv, name, sfx.first.id);
addLF = true; addLF = true;
@ -373,4 +330,4 @@ std::string AudioGroupDatabase::exportCHeader(std::string_view projectName, std:
return ret; return ret;
} }
} } // namespace amuse

View File

@ -1,12 +1,9 @@
#include "amuse/AudioGroupData.hpp" #include "amuse/AudioGroupData.hpp"
namespace amuse namespace amuse {
{
IntrusiveAudioGroupData::~IntrusiveAudioGroupData() IntrusiveAudioGroupData::~IntrusiveAudioGroupData() {
{ if (m_owns) {
if (m_owns)
{
delete[] m_pool; delete[] m_pool;
delete[] m_proj; delete[] m_proj;
delete[] m_sdir; delete[] m_sdir;
@ -16,16 +13,13 @@ IntrusiveAudioGroupData::~IntrusiveAudioGroupData()
IntrusiveAudioGroupData::IntrusiveAudioGroupData(IntrusiveAudioGroupData&& other) noexcept IntrusiveAudioGroupData::IntrusiveAudioGroupData(IntrusiveAudioGroupData&& other) noexcept
: AudioGroupData(other.m_proj, other.m_projSz, other.m_pool, other.m_poolSz, other.m_sdir, other.m_sdirSz, other.m_samp, : AudioGroupData(other.m_proj, other.m_projSz, other.m_pool, other.m_poolSz, other.m_sdir, other.m_sdirSz, other.m_samp,
other.m_sampSz, other.m_fmt, other.m_absOffs) other.m_sampSz, other.m_fmt, other.m_absOffs) {
{
m_owns = other.m_owns; m_owns = other.m_owns;
other.m_owns = false; other.m_owns = false;
} }
IntrusiveAudioGroupData& IntrusiveAudioGroupData::operator=(IntrusiveAudioGroupData&& other) noexcept IntrusiveAudioGroupData& IntrusiveAudioGroupData::operator=(IntrusiveAudioGroupData&& other) noexcept {
{ if (m_owns) {
if (m_owns)
{
delete[] m_pool; delete[] m_pool;
delete[] m_proj; delete[] m_proj;
delete[] m_sdir; delete[] m_sdir;
@ -44,4 +38,4 @@ IntrusiveAudioGroupData& IntrusiveAudioGroupData::operator=(IntrusiveAudioGroupD
return *this; return *this;
} }
} } // namespace amuse

View File

@ -10,45 +10,34 @@
using namespace std::literals; using namespace std::literals;
namespace amuse namespace amuse {
{
static logvisor::Module Log("amuse::AudioGroupPool"); static logvisor::Module Log("amuse::AudioGroupPool");
struct MakeCmdOp struct MakeCmdOp {
{
template <class Tp, class R> template <class Tp, class R>
static std::unique_ptr<SoundMacro::ICmd> Do(R& r) static std::unique_ptr<SoundMacro::ICmd> Do(R& r) {
{
std::unique_ptr<SoundMacro::ICmd> ret = std::make_unique<Tp>(); std::unique_ptr<SoundMacro::ICmd> ret = std::make_unique<Tp>();
static_cast<Tp&>(*ret).read(r); static_cast<Tp&>(*ret).read(r);
return ret; return ret;
} }
}; };
struct MakeCopyCmdOp struct MakeCopyCmdOp {
{
template <class Tp, class R> template <class Tp, class R>
static std::unique_ptr<SoundMacro::ICmd> Do(R& r) static std::unique_ptr<SoundMacro::ICmd> Do(R& r) {
{
return std::make_unique<Tp>(static_cast<const Tp&>(r)); return std::make_unique<Tp>(static_cast<const Tp&>(r));
} }
}; };
struct MakeDefaultCmdOp struct MakeDefaultCmdOp {
{
template <class Tp, class R> template <class Tp, class R>
static std::unique_ptr<SoundMacro::ICmd> Do(R& r) static std::unique_ptr<SoundMacro::ICmd> Do(R& r) {
{
std::unique_ptr<SoundMacro::ICmd> ret = std::make_unique<Tp>(); std::unique_ptr<SoundMacro::ICmd> ret = std::make_unique<Tp>();
if (const SoundMacro::CmdIntrospection* introspection = SoundMacro::GetCmdIntrospection(r)) if (const SoundMacro::CmdIntrospection* introspection = SoundMacro::GetCmdIntrospection(r)) {
{ for (int f = 0; f < 7; ++f) {
for (int f = 0; f < 7; ++f)
{
const amuse::SoundMacro::CmdIntrospection::Field& field = introspection->m_fields[f]; const amuse::SoundMacro::CmdIntrospection::Field& field = introspection->m_fields[f];
if (!field.m_name.empty()) if (!field.m_name.empty()) {
{ switch (field.m_tp) {
switch (field.m_tp)
{
case amuse::SoundMacro::CmdIntrospection::Field::Type::Bool: case amuse::SoundMacro::CmdIntrospection::Field::Type::Bool:
AccessField<bool>(ret.get(), field) = bool(field.m_default); AccessField<bool>(ret.get(), field) = bool(field.m_default);
break; break;
@ -87,41 +76,35 @@ struct MakeDefaultCmdOp
} }
}; };
struct IntrospectCmdOp struct IntrospectCmdOp {
{
template <class Tp> template <class Tp>
static const SoundMacro::CmdIntrospection* Do(SoundMacro::CmdOp) static const SoundMacro::CmdIntrospection* Do(SoundMacro::CmdOp) {
{
return &Tp::Introspective; return &Tp::Introspective;
} }
}; };
static bool AtEnd(athena::io::IStreamReader& r) static bool AtEnd(athena::io::IStreamReader& r) {
{
uint32_t v = r.readUint32Big(); uint32_t v = r.readUint32Big();
r.seek(-4, athena::Current); r.seek(-4, athena::Current);
return v == 0xffffffff; return v == 0xffffffff;
} }
template <athena::Endian DNAE> template <athena::Endian DNAE>
AudioGroupPool AudioGroupPool::_AudioGroupPool(athena::io::IStreamReader& r) AudioGroupPool AudioGroupPool::_AudioGroupPool(athena::io::IStreamReader& r) {
{
AudioGroupPool ret; AudioGroupPool ret;
PoolHeader<DNAE> head; PoolHeader<DNAE> head;
head.read(r); head.read(r);
if (head.soundMacrosOffset) if (head.soundMacrosOffset) {
{
r.seek(head.soundMacrosOffset, athena::Begin); r.seek(head.soundMacrosOffset, athena::Begin);
while (!AtEnd(r)) while (!AtEnd(r)) {
{
ObjectHeader<DNAE> objHead; ObjectHeader<DNAE> objHead;
atInt64 startPos = r.position(); atInt64 startPos = r.position();
objHead.read(r); objHead.read(r);
if (SoundMacroId::CurNameDB) if (SoundMacroId::CurNameDB)
SoundMacroId::CurNameDB->registerPair( SoundMacroId::CurNameDB->registerPair(NameDB::generateName(objHead.objectId, NameDB::Type::SoundMacro),
NameDB::generateName(objHead.objectId, NameDB::Type::SoundMacro), objHead.objectId); objHead.objectId);
auto& macro = ret.m_soundMacros[objHead.objectId.id]; auto& macro = ret.m_soundMacros[objHead.objectId.id];
macro = MakeObj<SoundMacro>(); macro = MakeObj<SoundMacro>();
macro->template readCmds<DNAE>(r, objHead.size - 8); macro->template readCmds<DNAE>(r, objHead.size - 8);
@ -129,20 +112,16 @@ AudioGroupPool AudioGroupPool::_AudioGroupPool(athena::io::IStreamReader& r)
} }
} }
if (head.tablesOffset) if (head.tablesOffset) {
{
r.seek(head.tablesOffset, athena::Begin); r.seek(head.tablesOffset, athena::Begin);
while (!AtEnd(r)) while (!AtEnd(r)) {
{
ObjectHeader<DNAE> objHead; ObjectHeader<DNAE> objHead;
atInt64 startPos = r.position(); atInt64 startPos = r.position();
objHead.read(r); objHead.read(r);
if (TableId::CurNameDB) if (TableId::CurNameDB)
TableId::CurNameDB->registerPair( TableId::CurNameDB->registerPair(NameDB::generateName(objHead.objectId, NameDB::Type::Table), objHead.objectId);
NameDB::generateName(objHead.objectId, NameDB::Type::Table), objHead.objectId);
auto& ptr = ret.m_tables[objHead.objectId.id]; auto& ptr = ret.m_tables[objHead.objectId.id];
switch (objHead.size) switch (objHead.size) {
{
case 0x10: case 0x10:
ptr = MakeObj<std::unique_ptr<ITable>>(std::make_unique<ADSR>()); ptr = MakeObj<std::unique_ptr<ITable>>(std::make_unique<ADSR>());
static_cast<ADSR&>(**ptr).read(r); static_cast<ADSR&>(**ptr).read(r);
@ -161,21 +140,18 @@ AudioGroupPool AudioGroupPool::_AudioGroupPool(athena::io::IStreamReader& r)
} }
} }
if (head.keymapsOffset) if (head.keymapsOffset) {
{
r.seek(head.keymapsOffset, athena::Begin); r.seek(head.keymapsOffset, athena::Begin);
while (!AtEnd(r)) while (!AtEnd(r)) {
{
ObjectHeader<DNAE> objHead; ObjectHeader<DNAE> objHead;
atInt64 startPos = r.position(); atInt64 startPos = r.position();
objHead.read(r); objHead.read(r);
if (KeymapId::CurNameDB) if (KeymapId::CurNameDB)
KeymapId::CurNameDB->registerPair( KeymapId::CurNameDB->registerPair(NameDB::generateName(objHead.objectId, NameDB::Type::Keymap),
NameDB::generateName(objHead.objectId, NameDB::Type::Keymap), objHead.objectId); objHead.objectId);
auto& km = ret.m_keymaps[objHead.objectId.id]; auto& km = ret.m_keymaps[objHead.objectId.id];
km = MakeObj<std::array<Keymap, 128>>(); km = MakeObj<std::array<Keymap, 128>>();
for (int i = 0; i < 128; ++i) for (int i = 0; i < 128; ++i) {
{
KeymapDNA<DNAE> kmData; KeymapDNA<DNAE> kmData;
kmData.read(r); kmData.read(r);
(*km)[i] = kmData; (*km)[i] = kmData;
@ -184,24 +160,21 @@ AudioGroupPool AudioGroupPool::_AudioGroupPool(athena::io::IStreamReader& r)
} }
} }
if (head.layersOffset) if (head.layersOffset) {
{
r.seek(head.layersOffset, athena::Begin); r.seek(head.layersOffset, athena::Begin);
while (!AtEnd(r)) while (!AtEnd(r)) {
{
ObjectHeader<DNAE> objHead; ObjectHeader<DNAE> objHead;
atInt64 startPos = r.position(); atInt64 startPos = r.position();
objHead.read(r); objHead.read(r);
if (LayersId::CurNameDB) if (LayersId::CurNameDB)
LayersId::CurNameDB->registerPair( LayersId::CurNameDB->registerPair(NameDB::generateName(objHead.objectId, NameDB::Type::Layer),
NameDB::generateName(objHead.objectId, NameDB::Type::Layer), objHead.objectId); objHead.objectId);
auto& lm = ret.m_layers[objHead.objectId.id]; auto& lm = ret.m_layers[objHead.objectId.id];
lm = MakeObj<std::vector<LayerMapping>>(); lm = MakeObj<std::vector<LayerMapping>>();
uint32_t count; uint32_t count;
athena::io::Read<athena::io::PropType::None>::Do<decltype(count), DNAE>({}, count, r); athena::io::Read<athena::io::PropType::None>::Do<decltype(count), DNAE>({}, count, r);
lm->reserve(count); lm->reserve(count);
for (uint32_t i = 0; i < count; ++i) for (uint32_t i = 0; i < count; ++i) {
{
LayerMappingDNA<DNAE> lmData; LayerMappingDNA<DNAE> lmData;
lmData.read(r); lmData.read(r);
lm->push_back(lmData); lm->push_back(lmData);
@ -215,13 +188,11 @@ AudioGroupPool AudioGroupPool::_AudioGroupPool(athena::io::IStreamReader& r)
template AudioGroupPool AudioGroupPool::_AudioGroupPool<athena::Big>(athena::io::IStreamReader& r); template AudioGroupPool AudioGroupPool::_AudioGroupPool<athena::Big>(athena::io::IStreamReader& r);
template AudioGroupPool AudioGroupPool::_AudioGroupPool<athena::Little>(athena::io::IStreamReader& r); template AudioGroupPool AudioGroupPool::_AudioGroupPool<athena::Little>(athena::io::IStreamReader& r);
AudioGroupPool AudioGroupPool::CreateAudioGroupPool(const AudioGroupData& data) AudioGroupPool AudioGroupPool::CreateAudioGroupPool(const AudioGroupData& data) {
{
if (data.getPoolSize() < 16) if (data.getPoolSize() < 16)
return {}; return {};
athena::io::MemoryReader r(data.getPool(), data.getPoolSize()); athena::io::MemoryReader r(data.getPool(), data.getPoolSize());
switch (data.getDataFormat()) switch (data.getDataFormat()) {
{
case DataFormat::PC: case DataFormat::PC:
return _AudioGroupPool<athena::Little>(r); return _AudioGroupPool<athena::Little>(r);
default: default:
@ -229,67 +200,52 @@ AudioGroupPool AudioGroupPool::CreateAudioGroupPool(const AudioGroupData& data)
} }
} }
AudioGroupPool AudioGroupPool::CreateAudioGroupPool(SystemStringView groupPath) AudioGroupPool AudioGroupPool::CreateAudioGroupPool(SystemStringView groupPath) {
{
AudioGroupPool ret; AudioGroupPool ret;
SystemString poolPath(groupPath); SystemString poolPath(groupPath);
poolPath += _SYS_STR("/!pool.yaml"); poolPath += _SYS_STR("/!pool.yaml");
athena::io::FileReader fi(poolPath, 32 * 1024, false); athena::io::FileReader fi(poolPath, 32 * 1024, false);
if (!fi.hasError()) if (!fi.hasError()) {
{
athena::io::YAMLDocReader r; athena::io::YAMLDocReader r;
if (r.parse(&fi) && !r.readString("DNAType").compare("amuse::Pool")) if (r.parse(&fi) && !r.readString("DNAType").compare("amuse::Pool")) {
{ if (auto __r = r.enterSubRecord("soundMacros")) {
if (auto __r = r.enterSubRecord("soundMacros")) for (const auto& sm : r.getCurNode()->m_mapChildren) {
{
for (const auto& sm : r.getCurNode()->m_mapChildren)
{
ObjectId macroId = SoundMacroId::CurNameDB->generateId(NameDB::Type::SoundMacro); ObjectId macroId = SoundMacroId::CurNameDB->generateId(NameDB::Type::SoundMacro);
SoundMacroId::CurNameDB->registerPair(sm.first, macroId); SoundMacroId::CurNameDB->registerPair(sm.first, macroId);
} }
} }
if (auto __r = r.enterSubRecord("tables")) if (auto __r = r.enterSubRecord("tables")) {
{ for (const auto& t : r.getCurNode()->m_mapChildren) {
for (const auto& t : r.getCurNode()->m_mapChildren) if (auto __v = r.enterSubRecord(t.first.c_str())) {
{
if (auto __v = r.enterSubRecord(t.first.c_str()))
{
ObjectId tableId = TableId::CurNameDB->generateId(NameDB::Type::Table); ObjectId tableId = TableId::CurNameDB->generateId(NameDB::Type::Table);
TableId::CurNameDB->registerPair(t.first, tableId); TableId::CurNameDB->registerPair(t.first, tableId);
} }
} }
} }
if (auto __r = r.enterSubRecord("keymaps")) if (auto __r = r.enterSubRecord("keymaps")) {
{
for (const auto& k : r.getCurNode()->m_mapChildren) for (const auto& k : r.getCurNode()->m_mapChildren)
if (auto __v = r.enterSubRecord(k.first.c_str())) if (auto __v = r.enterSubRecord(k.first.c_str())) {
{
ObjectId keymapId = KeymapId::CurNameDB->generateId(NameDB::Type::Keymap); ObjectId keymapId = KeymapId::CurNameDB->generateId(NameDB::Type::Keymap);
KeymapId::CurNameDB->registerPair(k.first, keymapId); KeymapId::CurNameDB->registerPair(k.first, keymapId);
} }
} }
if (auto __r = r.enterSubRecord("layers")) if (auto __r = r.enterSubRecord("layers")) {
{ for (const auto& l : r.getCurNode()->m_mapChildren) {
for (const auto& l : r.getCurNode()->m_mapChildren)
{
size_t mappingCount; size_t mappingCount;
if (auto __v = r.enterSubVector(l.first.c_str(), mappingCount)) if (auto __v = r.enterSubVector(l.first.c_str(), mappingCount)) {
{
ObjectId layersId = LayersId::CurNameDB->generateId(NameDB::Type::Layer); ObjectId layersId = LayersId::CurNameDB->generateId(NameDB::Type::Layer);
LayersId::CurNameDB->registerPair(l.first, layersId); LayersId::CurNameDB->registerPair(l.first, layersId);
} }
} }
} }
if (auto __r = r.enterSubRecord("soundMacros")) if (auto __r = r.enterSubRecord("soundMacros")) {
{
ret.m_soundMacros.reserve(r.getCurNode()->m_mapChildren.size()); ret.m_soundMacros.reserve(r.getCurNode()->m_mapChildren.size());
for (const auto& sm : r.getCurNode()->m_mapChildren) for (const auto& sm : r.getCurNode()->m_mapChildren) {
{
auto& smOut = ret.m_soundMacros[SoundMacroId::CurNameDB->resolveIdFromName(sm.first)]; auto& smOut = ret.m_soundMacros[SoundMacroId::CurNameDB->resolveIdFromName(sm.first)];
smOut = MakeObj<SoundMacro>(); smOut = MakeObj<SoundMacro>();
size_t cmdCount; size_t cmdCount;
@ -298,31 +254,22 @@ AudioGroupPool AudioGroupPool::CreateAudioGroupPool(SystemStringView groupPath)
} }
} }
if (auto __r = r.enterSubRecord("tables")) if (auto __r = r.enterSubRecord("tables")) {
{
ret.m_tables.reserve(r.getCurNode()->m_mapChildren.size()); ret.m_tables.reserve(r.getCurNode()->m_mapChildren.size());
for (const auto& t : r.getCurNode()->m_mapChildren) for (const auto& t : r.getCurNode()->m_mapChildren) {
{ if (auto __v = r.enterSubRecord(t.first.c_str())) {
if (auto __v = r.enterSubRecord(t.first.c_str()))
{
auto& tableOut = ret.m_tables[TableId::CurNameDB->resolveIdFromName(t.first)]; auto& tableOut = ret.m_tables[TableId::CurNameDB->resolveIdFromName(t.first)];
if (auto __att = r.enterSubRecord("attack")) if (auto __att = r.enterSubRecord("attack")) {
{
__att.leave(); __att.leave();
if (auto __vta = r.enterSubRecord("velToAttack")) if (auto __vta = r.enterSubRecord("velToAttack")) {
{
__vta.leave(); __vta.leave();
tableOut = MakeObj<std::unique_ptr<ITable>>(std::make_unique<ADSRDLS>()); tableOut = MakeObj<std::unique_ptr<ITable>>(std::make_unique<ADSRDLS>());
static_cast<ADSRDLS&>(**tableOut).read(r); static_cast<ADSRDLS&>(**tableOut).read(r);
} } else {
else
{
tableOut = MakeObj<std::unique_ptr<ITable>>(std::make_unique<ADSR>()); tableOut = MakeObj<std::unique_ptr<ITable>>(std::make_unique<ADSR>());
static_cast<ADSR&>(**tableOut).read(r); static_cast<ADSR&>(**tableOut).read(r);
} }
} } else if (auto __dat = r.enterSubRecord("data")) {
else if (auto __dat = r.enterSubRecord("data"))
{
__dat.leave(); __dat.leave();
tableOut = MakeObj<std::unique_ptr<ITable>>(std::make_unique<Curve>()); tableOut = MakeObj<std::unique_ptr<ITable>>(std::make_unique<Curve>());
static_cast<Curve&>(**tableOut).read(r); static_cast<Curve&>(**tableOut).read(r);
@ -331,14 +278,11 @@ AudioGroupPool AudioGroupPool::CreateAudioGroupPool(SystemStringView groupPath)
} }
} }
if (auto __r = r.enterSubRecord("keymaps")) if (auto __r = r.enterSubRecord("keymaps")) {
{
ret.m_keymaps.reserve(r.getCurNode()->m_mapChildren.size()); ret.m_keymaps.reserve(r.getCurNode()->m_mapChildren.size());
for (const auto& k : r.getCurNode()->m_mapChildren) for (const auto& k : r.getCurNode()->m_mapChildren) {
{
size_t mappingCount; size_t mappingCount;
if (auto __v = r.enterSubVector(k.first.c_str(), mappingCount)) if (auto __v = r.enterSubVector(k.first.c_str(), mappingCount)) {
{
auto& kmOut = ret.m_keymaps[KeymapId::CurNameDB->resolveIdFromName(k.first)]; auto& kmOut = ret.m_keymaps[KeymapId::CurNameDB->resolveIdFromName(k.first)];
kmOut = MakeObj<std::array<Keymap, 128>>(); kmOut = MakeObj<std::array<Keymap, 128>>();
for (int i = 0; i < mappingCount && i < 128; ++i) for (int i = 0; i < mappingCount && i < 128; ++i)
@ -348,21 +292,16 @@ AudioGroupPool AudioGroupPool::CreateAudioGroupPool(SystemStringView groupPath)
} }
} }
if (auto __r = r.enterSubRecord("layers")) if (auto __r = r.enterSubRecord("layers")) {
{
ret.m_layers.reserve(r.getCurNode()->m_mapChildren.size()); ret.m_layers.reserve(r.getCurNode()->m_mapChildren.size());
for (const auto& l : r.getCurNode()->m_mapChildren) for (const auto& l : r.getCurNode()->m_mapChildren) {
{
size_t mappingCount; size_t mappingCount;
if (auto __v = r.enterSubVector(l.first.c_str(), mappingCount)) if (auto __v = r.enterSubVector(l.first.c_str(), mappingCount)) {
{
auto& layOut = ret.m_layers[LayersId::CurNameDB->resolveIdFromName(l.first)]; auto& layOut = ret.m_layers[LayersId::CurNameDB->resolveIdFromName(l.first)];
layOut = MakeObj<std::vector<LayerMapping>>(); layOut = MakeObj<std::vector<LayerMapping>>();
layOut->reserve(mappingCount); layOut->reserve(mappingCount);
for (int lm = 0; lm < mappingCount; ++lm) for (int lm = 0; lm < mappingCount; ++lm) {
{ if (auto __r2 = r.enterSubRecord(nullptr)) {
if (auto __r2 = r.enterSubRecord(nullptr))
{
layOut->emplace_back(); layOut->emplace_back();
layOut->back().read(r); layOut->back().read(r);
} }
@ -376,12 +315,10 @@ AudioGroupPool AudioGroupPool::CreateAudioGroupPool(SystemStringView groupPath)
return ret; return ret;
} }
int SoundMacro::assertPC(int pc) const int SoundMacro::assertPC(int pc) const {
{
if (pc == -1) if (pc == -1)
return -1; return -1;
if (pc >= m_cmds.size()) if (pc >= m_cmds.size()) {
{
fprintf(stderr, "SoundMacro PC bounds exceeded [%d/%d]\n", pc, int(m_cmds.size())); fprintf(stderr, "SoundMacro PC bounds exceeded [%d/%d]\n", pc, int(m_cmds.size()));
abort(); abort();
} }
@ -389,12 +326,10 @@ int SoundMacro::assertPC(int pc) const
} }
template <athena::Endian DNAE> template <athena::Endian DNAE>
void SoundMacro::readCmds(athena::io::IStreamReader& r, uint32_t size) void SoundMacro::readCmds(athena::io::IStreamReader& r, uint32_t size) {
{
uint32_t numCmds = size / 8; uint32_t numCmds = size / 8;
m_cmds.reserve(numCmds); m_cmds.reserve(numCmds);
for (int i = 0; i < numCmds; ++i) for (int i = 0; i < numCmds; ++i) {
{
uint32_t data[2]; uint32_t data[2];
athena::io::Read<athena::io::PropType::None>::Do<decltype(data), DNAE>({}, data, r); athena::io::Read<athena::io::PropType::None>::Do<decltype(data), DNAE>({}, data, r);
athena::io::MemoryReader r(data, 8); athena::io::MemoryReader r(data, 8);
@ -405,10 +340,8 @@ template void SoundMacro::readCmds<athena::Big>(athena::io::IStreamReader& r, ui
template void SoundMacro::readCmds<athena::Little>(athena::io::IStreamReader& r, uint32_t size); template void SoundMacro::readCmds<athena::Little>(athena::io::IStreamReader& r, uint32_t size);
template <athena::Endian DNAE> template <athena::Endian DNAE>
void SoundMacro::writeCmds(athena::io::IStreamWriter& w) const void SoundMacro::writeCmds(athena::io::IStreamWriter& w) const {
{ for (const auto& cmd : m_cmds) {
for (const auto& cmd : m_cmds)
{
uint32_t data[2]; uint32_t data[2];
athena::io::MemoryWriter mw((uint8_t*)data, 8); athena::io::MemoryWriter mw((uint8_t*)data, 8);
mw.writeUByte(uint8_t(cmd->Isa())); mw.writeUByte(uint8_t(cmd->Isa()));
@ -419,19 +352,15 @@ void SoundMacro::writeCmds(athena::io::IStreamWriter& w) const
template void SoundMacro::writeCmds<athena::Big>(athena::io::IStreamWriter& w) const; template void SoundMacro::writeCmds<athena::Big>(athena::io::IStreamWriter& w) const;
template void SoundMacro::writeCmds<athena::Little>(athena::io::IStreamWriter& w) const; template void SoundMacro::writeCmds<athena::Little>(athena::io::IStreamWriter& w) const;
void SoundMacro::buildFromPrototype(const SoundMacro& other) void SoundMacro::buildFromPrototype(const SoundMacro& other) {
{
m_cmds.reserve(other.m_cmds.size()); m_cmds.reserve(other.m_cmds.size());
for (auto& cmd : other.m_cmds) for (auto& cmd : other.m_cmds)
m_cmds.push_back(CmdDo<MakeCopyCmdOp, std::unique_ptr<SoundMacro::ICmd>>(*cmd)); m_cmds.push_back(CmdDo<MakeCopyCmdOp, std::unique_ptr<SoundMacro::ICmd>>(*cmd));
} }
void SoundMacro::toYAML(athena::io::YAMLDocWriter& w) const void SoundMacro::toYAML(athena::io::YAMLDocWriter& w) const {
{ for (const auto& c : m_cmds) {
for (const auto& c : m_cmds) if (auto __r2 = w.enterSubRecord(nullptr)) {
{
if (auto __r2 = w.enterSubRecord(nullptr))
{
w.setStyle(athena::io::YAMLNodeStyle::Flow); w.setStyle(athena::io::YAMLNodeStyle::Flow);
w.writeString("cmdOp", SoundMacro::CmdOpToStr(c->Isa())); w.writeString("cmdOp", SoundMacro::CmdOpToStr(c->Isa()));
c->write(w); c->write(w);
@ -439,88 +368,69 @@ void SoundMacro::toYAML(athena::io::YAMLDocWriter& w) const
} }
} }
void SoundMacro::fromYAML(athena::io::YAMLDocReader& r, size_t cmdCount) void SoundMacro::fromYAML(athena::io::YAMLDocReader& r, size_t cmdCount) {
{
m_cmds.reserve(cmdCount); m_cmds.reserve(cmdCount);
for (int c = 0; c < cmdCount; ++c) for (int c = 0; c < cmdCount; ++c)
if (auto __r2 = r.enterSubRecord(nullptr)) if (auto __r2 = r.enterSubRecord(nullptr))
m_cmds.push_back(SoundMacro::CmdDo<MakeCmdOp, std::unique_ptr<SoundMacro::ICmd>>(r)); m_cmds.push_back(SoundMacro::CmdDo<MakeCmdOp, std::unique_ptr<SoundMacro::ICmd>>(r));
} }
const SoundMacro* AudioGroupPool::soundMacro(ObjectId id) const const SoundMacro* AudioGroupPool::soundMacro(ObjectId id) const {
{
auto search = m_soundMacros.find(id); auto search = m_soundMacros.find(id);
if (search == m_soundMacros.cend()) if (search == m_soundMacros.cend())
return nullptr; return nullptr;
return search->second.get(); return search->second.get();
} }
const Keymap* AudioGroupPool::keymap(ObjectId id) const const Keymap* AudioGroupPool::keymap(ObjectId id) const {
{
auto search = m_keymaps.find(id); auto search = m_keymaps.find(id);
if (search == m_keymaps.cend()) if (search == m_keymaps.cend())
return nullptr; return nullptr;
return search->second.get()->data(); return search->second.get()->data();
} }
const std::vector<LayerMapping>* AudioGroupPool::layer(ObjectId id) const const std::vector<LayerMapping>* AudioGroupPool::layer(ObjectId id) const {
{
auto search = m_layers.find(id); auto search = m_layers.find(id);
if (search == m_layers.cend()) if (search == m_layers.cend())
return nullptr; return nullptr;
return search->second.get(); return search->second.get();
} }
const ADSR* AudioGroupPool::tableAsAdsr(ObjectId id) const const ADSR* AudioGroupPool::tableAsAdsr(ObjectId id) const {
{
auto search = m_tables.find(id); auto search = m_tables.find(id);
if (search == m_tables.cend() || (*search->second)->Isa() != ITable::Type::ADSR) if (search == m_tables.cend() || (*search->second)->Isa() != ITable::Type::ADSR)
return nullptr; return nullptr;
return static_cast<const ADSR*>((*search->second).get()); return static_cast<const ADSR*>((*search->second).get());
} }
const ADSRDLS* AudioGroupPool::tableAsAdsrDLS(ObjectId id) const const ADSRDLS* AudioGroupPool::tableAsAdsrDLS(ObjectId id) const {
{
auto search = m_tables.find(id); auto search = m_tables.find(id);
if (search == m_tables.cend() || (*search->second)->Isa() != ITable::Type::ADSRDLS) if (search == m_tables.cend() || (*search->second)->Isa() != ITable::Type::ADSRDLS)
return nullptr; return nullptr;
return static_cast<const ADSRDLS*>((*search->second).get()); return static_cast<const ADSRDLS*>((*search->second).get());
} }
const Curve* AudioGroupPool::tableAsCurves(ObjectId id) const const Curve* AudioGroupPool::tableAsCurves(ObjectId id) const {
{
auto search = m_tables.find(id); auto search = m_tables.find(id);
if (search == m_tables.cend() || (*search->second)->Isa() != ITable::Type::Curve) if (search == m_tables.cend() || (*search->second)->Isa() != ITable::Type::Curve)
return nullptr; return nullptr;
return static_cast<const Curve*>((*search->second).get()); return static_cast<const Curve*>((*search->second).get());
} }
static SoundMacro::CmdOp _ReadCmdOp(athena::io::MemoryReader& r) static SoundMacro::CmdOp _ReadCmdOp(athena::io::MemoryReader& r) { return SoundMacro::CmdOp(r.readUByte()); }
{
return SoundMacro::CmdOp(r.readUByte());
}
static SoundMacro::CmdOp _ReadCmdOp(athena::io::YAMLDocReader& r) static SoundMacro::CmdOp _ReadCmdOp(athena::io::YAMLDocReader& r) {
{
return SoundMacro::CmdStrToOp(r.readString("cmdOp")); return SoundMacro::CmdStrToOp(r.readString("cmdOp"));
} }
static SoundMacro::CmdOp _ReadCmdOp(SoundMacro::CmdOp& op) static SoundMacro::CmdOp _ReadCmdOp(SoundMacro::CmdOp& op) { return op; }
{
return op;
}
static SoundMacro::CmdOp _ReadCmdOp(const SoundMacro::ICmd& op) static SoundMacro::CmdOp _ReadCmdOp(const SoundMacro::ICmd& op) { return op.Isa(); }
{
return op.Isa();
}
template <class Op, class O, class... _Args> template <class Op, class O, class... _Args>
O SoundMacro::CmdDo(_Args&&... args) O SoundMacro::CmdDo(_Args&&... args) {
{
SoundMacro::CmdOp op = _ReadCmdOp(std::forward<_Args>(args)...); SoundMacro::CmdOp op = _ReadCmdOp(std::forward<_Args>(args)...);
switch (op) switch (op) {
{
case CmdOp::End: case CmdOp::End:
return Op::template Do<CmdEnd>(std::forward<_Args>(args)...); return Op::template Do<CmdEnd>(std::forward<_Args>(args)...);
case CmdOp::Stop: case CmdOp::Stop:
@ -690,20 +600,16 @@ template std::unique_ptr<SoundMacro::ICmd> SoundMacro::CmdDo<MakeCmdOp>(athena::
template std::unique_ptr<SoundMacro::ICmd> SoundMacro::CmdDo<MakeDefaultCmdOp>(SoundMacro::CmdOp& r); template std::unique_ptr<SoundMacro::ICmd> SoundMacro::CmdDo<MakeDefaultCmdOp>(SoundMacro::CmdOp& r);
template const SoundMacro::CmdIntrospection* SoundMacro::CmdDo<IntrospectCmdOp>(SoundMacro::CmdOp& op); template const SoundMacro::CmdIntrospection* SoundMacro::CmdDo<IntrospectCmdOp>(SoundMacro::CmdOp& op);
std::unique_ptr<SoundMacro::ICmd> SoundMacro::MakeCmd(CmdOp op) std::unique_ptr<SoundMacro::ICmd> SoundMacro::MakeCmd(CmdOp op) {
{
return CmdDo<MakeDefaultCmdOp, std::unique_ptr<SoundMacro::ICmd>>(op); return CmdDo<MakeDefaultCmdOp, std::unique_ptr<SoundMacro::ICmd>>(op);
} }
const SoundMacro::CmdIntrospection* SoundMacro::GetCmdIntrospection(CmdOp op) const SoundMacro::CmdIntrospection* SoundMacro::GetCmdIntrospection(CmdOp op) {
{
return CmdDo<IntrospectCmdOp, const SoundMacro::CmdIntrospection*>(op); return CmdDo<IntrospectCmdOp, const SoundMacro::CmdIntrospection*>(op);
} }
std::string_view SoundMacro::CmdOpToStr(CmdOp op) std::string_view SoundMacro::CmdOpToStr(CmdOp op) {
{ switch (op) {
switch (op)
{
case CmdOp::End: case CmdOp::End:
return "End"sv; return "End"sv;
case CmdOp::Stop: case CmdOp::Stop:
@ -869,8 +775,7 @@ std::string_view SoundMacro::CmdOpToStr(CmdOp op)
} }
} }
SoundMacro::CmdOp SoundMacro::CmdStrToOp(std::string_view op) SoundMacro::CmdOp SoundMacro::CmdStrToOp(std::string_view op) {
{
if (!CompareCaseInsensitive(op.data(), "End")) if (!CompareCaseInsensitive(op.data(), "End"))
return CmdOp::End; return CmdOp::End;
else if (!CompareCaseInsensitive(op.data(), "Stop")) else if (!CompareCaseInsensitive(op.data(), "Stop"))
@ -1034,32 +939,23 @@ SoundMacro::CmdOp SoundMacro::CmdStrToOp(std::string_view op)
return CmdOp::Invalid; return CmdOp::Invalid;
} }
std::vector<uint8_t> AudioGroupPool::toYAML() const std::vector<uint8_t> AudioGroupPool::toYAML() const {
{
athena::io::YAMLDocWriter w("amuse::Pool"); athena::io::YAMLDocWriter w("amuse::Pool");
if (!m_soundMacros.empty()) if (!m_soundMacros.empty()) {
{ if (auto __r = w.enterSubRecord("soundMacros")) {
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& p : SortUnorderedMap(m_soundMacros))
{
if (auto __v = w.enterSubVector(SoundMacroId::CurNameDB->resolveNameFromId(p.first).data()))
{
p.second.get()->toYAML(w); p.second.get()->toYAML(w);
} }
} }
} }
} }
if (!m_tables.empty()) if (!m_tables.empty()) {
{ if (auto __r = w.enterSubRecord("tables")) {
if (auto __r = w.enterSubRecord("tables")) for (const auto& p : SortUnorderedMap(m_tables)) {
{ if (auto __v = w.enterSubRecord(TableId::CurNameDB->resolveNameFromId(p.first).data())) {
for (const auto& p : SortUnorderedMap(m_tables))
{
if (auto __v = w.enterSubRecord(TableId::CurNameDB->resolveNameFromId(p.first).data()))
{
w.setStyle(athena::io::YAMLNodeStyle::Flow); w.setStyle(athena::io::YAMLNodeStyle::Flow);
(*p.second.get())->write(w); (*p.second.get())->write(w);
} }
@ -1067,18 +963,12 @@ std::vector<uint8_t> AudioGroupPool::toYAML() const
} }
} }
if (!m_keymaps.empty()) if (!m_keymaps.empty()) {
{ if (auto __r = w.enterSubRecord("keymaps")) {
if (auto __r = w.enterSubRecord("keymaps")) for (const auto& p : SortUnorderedMap(m_keymaps)) {
{ if (auto __v = w.enterSubVector(KeymapId::CurNameDB->resolveNameFromId(p.first).data())) {
for (const auto& p : SortUnorderedMap(m_keymaps)) for (const auto& km : *p.second.get()) {
{ if (auto __r2 = w.enterSubRecord(nullptr)) {
if (auto __v = w.enterSubVector(KeymapId::CurNameDB->resolveNameFromId(p.first).data()))
{
for (const auto& km : *p.second.get())
{
if (auto __r2 = w.enterSubRecord(nullptr))
{
w.setStyle(athena::io::YAMLNodeStyle::Flow); w.setStyle(athena::io::YAMLNodeStyle::Flow);
km.write(w); km.write(w);
} }
@ -1088,18 +978,12 @@ std::vector<uint8_t> AudioGroupPool::toYAML() const
} }
} }
if (!m_layers.empty()) if (!m_layers.empty()) {
{ if (auto __r = w.enterSubRecord("layers")) {
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& p : SortUnorderedMap(m_layers)) for (const auto& lm : *p.second.get()) {
{ if (auto __r2 = w.enterSubRecord(nullptr)) {
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); w.setStyle(athena::io::YAMLNodeStyle::Flow);
lm.write(w); lm.write(w);
} }
@ -1115,8 +999,7 @@ std::vector<uint8_t> AudioGroupPool::toYAML() const
} }
template <athena::Endian DNAE> template <athena::Endian DNAE>
std::vector<uint8_t> AudioGroupPool::toData() const std::vector<uint8_t> AudioGroupPool::toData() const {
{
athena::io::VectorWriter fo; athena::io::VectorWriter fo;
PoolHeader<DNAE> head = {}; PoolHeader<DNAE> head = {};
@ -1124,11 +1007,9 @@ std::vector<uint8_t> AudioGroupPool::toData() const
const uint32_t term = 0xffffffff; const uint32_t term = 0xffffffff;
if (!m_soundMacros.empty()) if (!m_soundMacros.empty()) {
{
head.soundMacrosOffset = fo.position(); head.soundMacrosOffset = fo.position();
for (const auto& p : m_soundMacros) for (const auto& p : m_soundMacros) {
{
auto startPos = fo.position(); auto startPos = fo.position();
ObjectHeader<DNAE> objHead = {}; ObjectHeader<DNAE> objHead = {};
objHead.write(fo); objHead.write(fo);
@ -1142,24 +1023,20 @@ std::vector<uint8_t> AudioGroupPool::toData() const
athena::io::Write<athena::io::PropType::None>::Do<decltype(term), DNAE>({}, term, fo); athena::io::Write<athena::io::PropType::None>::Do<decltype(term), DNAE>({}, term, fo);
} }
if (!m_tables.empty()) if (!m_tables.empty()) {
{
head.tablesOffset = fo.position(); head.tablesOffset = fo.position();
for (const auto& p : m_tables) for (const auto& p : m_tables) {
{
auto startPos = fo.position(); auto startPos = fo.position();
ObjectHeader<DNAE> objHead = {}; ObjectHeader<DNAE> objHead = {};
objHead.write(fo); objHead.write(fo);
switch ((*p.second)->Isa()) switch ((*p.second)->Isa()) {
{
case ITable::Type::ADSR: case ITable::Type::ADSR:
static_cast<ADSR*>(p.second->get())->write(fo); static_cast<ADSR*>(p.second->get())->write(fo);
break; break;
case ITable::Type::ADSRDLS: case ITable::Type::ADSRDLS:
static_cast<ADSRDLS*>(p.second->get())->write(fo); static_cast<ADSRDLS*>(p.second->get())->write(fo);
break; break;
case ITable::Type::Curve: case ITable::Type::Curve: {
{
const auto& data = static_cast<Curve*>(p.second->get())->data; const auto& data = static_cast<Curve*>(p.second->get())->data;
fo.writeUBytes(data.data(), data.size()); fo.writeUBytes(data.data(), data.size());
break; break;
@ -1176,16 +1053,13 @@ std::vector<uint8_t> AudioGroupPool::toData() const
athena::io::Write<athena::io::PropType::None>::Do<decltype(term), DNAE>({}, term, fo); athena::io::Write<athena::io::PropType::None>::Do<decltype(term), DNAE>({}, term, fo);
} }
if (!m_keymaps.empty()) if (!m_keymaps.empty()) {
{
head.keymapsOffset = fo.position(); head.keymapsOffset = fo.position();
for (const auto& p : m_keymaps) for (const auto& p : m_keymaps) {
{
auto startPos = fo.position(); auto startPos = fo.position();
ObjectHeader<DNAE> objHead = {}; ObjectHeader<DNAE> objHead = {};
objHead.write(fo); objHead.write(fo);
for (const auto& km : *p.second) for (const auto& km : *p.second) {
{
KeymapDNA<DNAE> kmData = km.toDNA<DNAE>(); KeymapDNA<DNAE> kmData = km.toDNA<DNAE>();
kmData.write(fo); kmData.write(fo);
} }
@ -1198,18 +1072,15 @@ std::vector<uint8_t> AudioGroupPool::toData() const
athena::io::Write<athena::io::PropType::None>::Do<decltype(term), DNAE>({}, term, fo); athena::io::Write<athena::io::PropType::None>::Do<decltype(term), DNAE>({}, term, fo);
} }
if (!m_layers.empty()) if (!m_layers.empty()) {
{
head.layersOffset = fo.position(); head.layersOffset = fo.position();
for (const auto& p : m_layers) for (const auto& p : m_layers) {
{
auto startPos = fo.position(); auto startPos = fo.position();
ObjectHeader<DNAE> objHead = {}; ObjectHeader<DNAE> objHead = {};
objHead.write(fo); objHead.write(fo);
uint32_t count = p.second->size(); uint32_t count = p.second->size();
athena::io::Write<athena::io::PropType::None>::Do<decltype(count), DNAE>({}, count, fo); athena::io::Write<athena::io::PropType::None>::Do<decltype(count), DNAE>({}, count, fo);
for (const auto& lm : *p.second) for (const auto& lm : *p.second) {
{
LayerMappingDNA<DNAE> lmData = lm.toDNA<DNAE>(); LayerMappingDNA<DNAE> lmData = lm.toDNA<DNAE>();
lmData.write(fo); lmData.write(fo);
} }
@ -1231,38 +1102,30 @@ template std::vector<uint8_t> AudioGroupPool::toData<athena::Big>() const;
template std::vector<uint8_t> AudioGroupPool::toData<athena::Little>() const; template std::vector<uint8_t> AudioGroupPool::toData<athena::Little>() const;
template <> template <>
void amuse::Curve::Enumerate<LittleDNA::Read>(athena::io::IStreamReader& r) void amuse::Curve::Enumerate<LittleDNA::Read>(athena::io::IStreamReader& r) {
{
Log.report(logvisor::Fatal, "Curve binary DNA read not supported"); Log.report(logvisor::Fatal, "Curve binary DNA read not supported");
} }
template <> template <>
void amuse::Curve::Enumerate<LittleDNA::Write>(athena::io::IStreamWriter& w) void amuse::Curve::Enumerate<LittleDNA::Write>(athena::io::IStreamWriter& w) {
{
Log.report(logvisor::Fatal, "Curve binary DNA write not supported"); Log.report(logvisor::Fatal, "Curve binary DNA write not supported");
} }
template <> template <>
void amuse::Curve::Enumerate<LittleDNA::BinarySize>(size_t& sz) void amuse::Curve::Enumerate<LittleDNA::BinarySize>(size_t& sz) {
{
Log.report(logvisor::Fatal, "Curve binary DNA size not supported"); Log.report(logvisor::Fatal, "Curve binary DNA size not supported");
} }
template <> template <>
void amuse::Curve::Enumerate<LittleDNA::ReadYaml>(athena::io::YAMLDocReader& r) void amuse::Curve::Enumerate<LittleDNA::ReadYaml>(athena::io::YAMLDocReader& r) {
{
r.enumerate("data", 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("data", data); w.enumerate("data", data);
} }
const char* amuse::Curve::DNAType() const char* amuse::Curve::DNAType() { return "amuse::Curve"; }
{
return "amuse::Curve";
}
} } // namespace amuse

View File

@ -7,41 +7,34 @@
#include "athena/FileWriter.hpp" #include "athena/FileWriter.hpp"
#include "athena/FileReader.hpp" #include "athena/FileReader.hpp"
namespace amuse namespace amuse {
{
static bool AtEnd64(athena::io::IStreamReader& r) static bool AtEnd64(athena::io::IStreamReader& r) {
{
uint64_t v = r.readUint64Big(); uint64_t v = r.readUint64Big();
r.seek(-8, athena::Current); r.seek(-8, athena::Current);
return v == 0xffffffffffffffff; return v == 0xffffffffffffffff;
} }
static bool AtEnd32(athena::io::IStreamReader& r) static bool AtEnd32(athena::io::IStreamReader& r) {
{
uint32_t v = r.readUint32Big(); uint32_t v = r.readUint32Big();
r.seek(-4, athena::Current); r.seek(-4, athena::Current);
return v == 0xffffffff; return v == 0xffffffff;
} }
static bool AtEnd16(athena::io::IStreamReader& r) static bool AtEnd16(athena::io::IStreamReader& r) {
{
uint16_t v = r.readUint16Big(); uint16_t v = r.readUint16Big();
r.seek(-2, athena::Current); r.seek(-2, athena::Current);
return v == 0xffff; return v == 0xffff;
} }
template <athena::Endian DNAE> template <athena::Endian DNAE>
static void ReadRangedObjectIds(NameDB* db, athena::io::IStreamReader& r, NameDB::Type tp) static void ReadRangedObjectIds(NameDB* db, athena::io::IStreamReader& r, NameDB::Type tp) {
{
uint16_t id; uint16_t id;
athena::io::Read<athena::io::PropType::None>::Do<decltype(id), DNAE>({}, id, r); athena::io::Read<athena::io::PropType::None>::Do<decltype(id), DNAE>({}, id, r);
if ((id & 0x8000) == 0x8000) if ((id & 0x8000) == 0x8000) {
{
uint16_t endId; uint16_t endId;
athena::io::Read<athena::io::PropType::None>::Do<decltype(endId), DNAE>({}, endId, r); 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) for (uint16_t i = uint16_t(id & 0x7fff); i <= uint16_t(endId & 0x7fff); ++i) {
{
ObjectId useId = i; ObjectId useId = i;
if (tp == NameDB::Type::Layer) if (tp == NameDB::Type::Layer)
useId.id |= 0x8000; useId.id |= 0x8000;
@ -50,9 +43,7 @@ static void ReadRangedObjectIds(NameDB* db, athena::io::IStreamReader& r, NameDB
if (db) if (db)
db->registerPair(NameDB::generateName(useId, tp), useId); db->registerPair(NameDB::generateName(useId, tp), useId);
} }
} } else {
else
{
if (tp == NameDB::Type::Layer) if (tp == NameDB::Type::Layer)
id |= 0x8000; id |= 0x8000;
else if (tp == NameDB::Type::Keymap) else if (tp == NameDB::Type::Keymap)
@ -63,26 +54,20 @@ static void ReadRangedObjectIds(NameDB* db, athena::io::IStreamReader& r, NameDB
} }
template <athena::Endian DNAE, class T> template <athena::Endian DNAE, class T>
static void WriteRangedObjectIds(athena::io::IStreamWriter& w, const T& list) static void WriteRangedObjectIds(athena::io::IStreamWriter& w, const T& list) {
{
if (list.cbegin() == list.cend()) if (list.cbegin() == list.cend())
return; return;
bool inRange = false; bool inRange = false;
uint16_t lastId = list.cbegin()->first & 0x3fff; uint16_t lastId = list.cbegin()->first & 0x3fff;
for (auto it = list.cbegin() + 1; it != list.cend(); ++it) for (auto it = list.cbegin() + 1; it != list.cend(); ++it) {
{
uint16_t thisId = it->first & 0x3fff; uint16_t thisId = it->first & 0x3fff;
if (thisId == lastId + 1) if (thisId == lastId + 1) {
{ if (!inRange) {
if (!inRange)
{
inRange = true; inRange = true;
lastId |= 0x8000; lastId |= 0x8000;
athena::io::Write<athena::io::PropType::None>::Do<decltype(lastId), DNAE>({}, lastId, w); athena::io::Write<athena::io::PropType::None>::Do<decltype(lastId), DNAE>({}, lastId, w);
} }
} } else {
else
{
inRange = false; inRange = false;
athena::io::Write<athena::io::PropType::None>::Do<decltype(lastId), DNAE>({}, lastId, w); athena::io::Write<athena::io::PropType::None>::Do<decltype(lastId), DNAE>({}, lastId, w);
} }
@ -93,10 +78,8 @@ static void WriteRangedObjectIds(athena::io::IStreamWriter& w, const T& list)
athena::io::Write<athena::io::PropType::None>::Do<decltype(term), DNAE>({}, term, w); athena::io::Write<athena::io::PropType::None>::Do<decltype(term), DNAE>({}, term, w);
} }
AudioGroupProject::AudioGroupProject(athena::io::IStreamReader& r, GCNDataTag) AudioGroupProject::AudioGroupProject(athena::io::IStreamReader& r, GCNDataTag) {
{ while (!AtEnd32(r)) {
while (!AtEnd32(r))
{
GroupHeader<athena::Big> header; GroupHeader<athena::Big> header;
header.read(r); header.read(r);
@ -130,15 +113,13 @@ AudioGroupProject::AudioGroupProject(athena::io::IStreamReader& r, GCNDataTag)
ReadRangedObjectIds<athena::Big>(LayersId::CurNameDB, r, NameDB::Type::Layer); ReadRangedObjectIds<athena::Big>(LayersId::CurNameDB, r, NameDB::Type::Layer);
#endif #endif
if (header.type == GroupType::Song) if (header.type == GroupType::Song) {
{
auto& idx = m_songGroups[header.groupId]; auto& idx = m_songGroups[header.groupId];
idx = MakeObj<SongGroupIndex>(); idx = MakeObj<SongGroupIndex>();
/* Normal pages */ /* Normal pages */
r.seek(header.pageTableOff, athena::Begin); r.seek(header.pageTableOff, athena::Begin);
while (!AtEnd64(r)) while (!AtEnd64(r)) {
{
SongGroupIndex::PageEntryDNA<athena::Big> entry; SongGroupIndex::PageEntryDNA<athena::Big> entry;
entry.read(r); entry.read(r);
idx->m_normPages[entry.programNo] = entry; idx->m_normPages[entry.programNo] = entry;
@ -146,8 +127,7 @@ AudioGroupProject::AudioGroupProject(athena::io::IStreamReader& r, GCNDataTag)
/* Drum pages */ /* Drum pages */
r.seek(header.drumTableOff, athena::Begin); r.seek(header.drumTableOff, athena::Begin);
while (!AtEnd64(r)) while (!AtEnd64(r)) {
{
SongGroupIndex::PageEntryDNA<athena::Big> entry; SongGroupIndex::PageEntryDNA<athena::Big> entry;
entry.read(r); entry.read(r);
idx->m_drumPages[entry.programNo] = entry; idx->m_drumPages[entry.programNo] = entry;
@ -155,19 +135,16 @@ AudioGroupProject::AudioGroupProject(athena::io::IStreamReader& r, GCNDataTag)
/* MIDI setups */ /* MIDI setups */
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 = r.readUint16Big();
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)
setup[i].read(r); setup[i].read(r);
if (SongId::CurNameDB) if (SongId::CurNameDB)
SongId::CurNameDB->registerPair(NameDB::generateName(songId, NameDB::Type::Song), songId); SongId::CurNameDB->registerPair(NameDB::generateName(songId, NameDB::Type::Song), songId);
} }
} } else if (header.type == GroupType::SFX) {
else if (header.type == GroupType::SFX)
{
auto& idx = m_sfxGroups[header.groupId]; auto& idx = m_sfxGroups[header.groupId];
idx = MakeObj<SFXGroupIndex>(); idx = MakeObj<SFXGroupIndex>();
@ -176,14 +153,12 @@ AudioGroupProject::AudioGroupProject(athena::io::IStreamReader& r, GCNDataTag)
uint16_t count = r.readUint16Big(); uint16_t count = r.readUint16Big();
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) {
{
SFXGroupIndex::SFXEntryDNA<athena::Big> entry; SFXGroupIndex::SFXEntryDNA<athena::Big> entry;
entry.read(r); entry.read(r);
idx->m_sfxEntries[entry.sfxId.id] = entry; idx->m_sfxEntries[entry.sfxId.id] = entry;
if (SFXId::CurNameDB) if (SFXId::CurNameDB)
SFXId::CurNameDB->registerPair( SFXId::CurNameDB->registerPair(NameDB::generateName(entry.sfxId.id, NameDB::Type::SFX), entry.sfxId.id);
NameDB::generateName(entry.sfxId.id, NameDB::Type::SFX), entry.sfxId.id);
} }
} }
@ -192,12 +167,10 @@ AudioGroupProject::AudioGroupProject(athena::io::IStreamReader& r, GCNDataTag)
} }
template <athena::Endian DNAE> template <athena::Endian DNAE>
AudioGroupProject AudioGroupProject::_AudioGroupProject(athena::io::IStreamReader& r, bool absOffs) AudioGroupProject AudioGroupProject::_AudioGroupProject(athena::io::IStreamReader& r, bool absOffs) {
{
AudioGroupProject ret; AudioGroupProject ret;
while (!AtEnd32(r)) while (!AtEnd32(r)) {
{
atInt64 groupBegin = r.position(); atInt64 groupBegin = r.position();
atInt64 subDataOff = absOffs ? 0 : groupBegin + 8; atInt64 subDataOff = absOffs ? 0 : groupBegin + 8;
GroupHeader<DNAE> header; GroupHeader<DNAE> header;
@ -232,17 +205,14 @@ AudioGroupProject AudioGroupProject::_AudioGroupProject(athena::io::IStreamReade
ReadRangedObjectIds<DNAE>(LayersId::CurNameDB, r, NameDB::Type::Layer); ReadRangedObjectIds<DNAE>(LayersId::CurNameDB, r, NameDB::Type::Layer);
#endif #endif
if (header.type == GroupType::Song) if (header.type == GroupType::Song) {
{
auto& idx = ret.m_songGroups[header.groupId]; auto& idx = ret.m_songGroups[header.groupId];
idx = MakeObj<SongGroupIndex>(); idx = MakeObj<SongGroupIndex>();
if (absOffs) if (absOffs) {
{
/* Normal pages */ /* Normal pages */
r.seek(header.pageTableOff, athena::Begin); r.seek(header.pageTableOff, athena::Begin);
while (!AtEnd16(r)) while (!AtEnd16(r)) {
{
SongGroupIndex::PageEntryDNA<DNAE> entry; SongGroupIndex::PageEntryDNA<DNAE> entry;
entry.read(r); entry.read(r);
idx->m_normPages[entry.programNo] = entry; idx->m_normPages[entry.programNo] = entry;
@ -250,8 +220,7 @@ AudioGroupProject AudioGroupProject::_AudioGroupProject(athena::io::IStreamReade
/* Drum pages */ /* Drum pages */
r.seek(header.drumTableOff, athena::Begin); r.seek(header.drumTableOff, athena::Begin);
while (!AtEnd16(r)) while (!AtEnd16(r)) {
{
SongGroupIndex::PageEntryDNA<DNAE> entry; SongGroupIndex::PageEntryDNA<DNAE> entry;
entry.read(r); entry.read(r);
idx->m_drumPages[entry.programNo] = entry; idx->m_drumPages[entry.programNo] = entry;
@ -259,23 +228,19 @@ AudioGroupProject AudioGroupProject::_AudioGroupProject(athena::io::IStreamReade
/* MIDI setups */ /* MIDI setups */
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; uint16_t songId;
athena::io::Read<athena::io::PropType::None>::Do<decltype(songId), DNAE>({}, songId, r); 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)
setup[i].read(r); setup[i].read(r);
SongId::CurNameDB->registerPair(NameDB::generateName(songId, NameDB::Type::Song), songId); SongId::CurNameDB->registerPair(NameDB::generateName(songId, NameDB::Type::Song), songId);
} }
} } else {
else
{
/* Normal pages */ /* Normal pages */
r.seek(subDataOff + header.pageTableOff, athena::Begin); r.seek(subDataOff + header.pageTableOff, athena::Begin);
while (!AtEnd16(r)) while (!AtEnd16(r)) {
{
SongGroupIndex::MusyX1PageEntryDNA<DNAE> entry; SongGroupIndex::MusyX1PageEntryDNA<DNAE> entry;
entry.read(r); entry.read(r);
idx->m_normPages[entry.programNo] = entry; idx->m_normPages[entry.programNo] = entry;
@ -283,8 +248,7 @@ AudioGroupProject AudioGroupProject::_AudioGroupProject(athena::io::IStreamReade
/* Drum pages */ /* Drum pages */
r.seek(subDataOff + header.drumTableOff, athena::Begin); r.seek(subDataOff + header.drumTableOff, athena::Begin);
while (!AtEnd16(r)) while (!AtEnd16(r)) {
{
SongGroupIndex::MusyX1PageEntryDNA<DNAE> entry; SongGroupIndex::MusyX1PageEntryDNA<DNAE> entry;
entry.read(r); entry.read(r);
idx->m_drumPages[entry.programNo] = entry; idx->m_drumPages[entry.programNo] = entry;
@ -292,14 +256,12 @@ AudioGroupProject AudioGroupProject::_AudioGroupProject(athena::io::IStreamReade
/* MIDI setups */ /* MIDI setups */
r.seek(subDataOff + header.midiSetupsOff, athena::Begin); r.seek(subDataOff + header.midiSetupsOff, athena::Begin);
while (r.position() + 4 < groupBegin + header.groupEndOff) while (r.position() + 4 < groupBegin + header.groupEndOff) {
{
uint16_t songId; uint16_t songId;
athena::io::Read<athena::io::PropType::None>::Do<decltype(songId), DNAE>({}, songId, r); 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) {
{
SongGroupIndex::MusyX1MIDISetup ent; SongGroupIndex::MusyX1MIDISetup ent;
ent.read(r); ent.read(r);
setup[i] = ent; setup[i] = ent;
@ -307,9 +269,7 @@ AudioGroupProject AudioGroupProject::_AudioGroupProject(athena::io::IStreamReade
SongId::CurNameDB->registerPair(NameDB::generateName(songId, NameDB::Type::Song), songId); SongId::CurNameDB->registerPair(NameDB::generateName(songId, NameDB::Type::Song), songId);
} }
} }
} } else if (header.type == GroupType::SFX) {
else if (header.type == GroupType::SFX)
{
auto& idx = ret.m_sfxGroups[header.groupId]; auto& idx = ret.m_sfxGroups[header.groupId];
idx = MakeObj<SFXGroupIndex>(); idx = MakeObj<SFXGroupIndex>();
@ -319,14 +279,12 @@ AudioGroupProject AudioGroupProject::_AudioGroupProject(athena::io::IStreamReade
athena::io::Read<athena::io::PropType::None>::Do<decltype(count), DNAE>({}, count, r); 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) {
{
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.sfxId.id] = entry; idx->m_sfxEntries[entry.sfxId.id] = entry;
SFXId::CurNameDB->registerPair( SFXId::CurNameDB->registerPair(NameDB::generateName(entry.sfxId.id, NameDB::Type::SFX), entry.sfxId.id);
NameDB::generateName(entry.sfxId.id, NameDB::Type::SFX), entry.sfxId.id);
} }
} }
@ -339,13 +297,11 @@ AudioGroupProject AudioGroupProject::_AudioGroupProject(athena::io::IStreamReade
return ret; return ret;
} }
AudioGroupProject AudioGroupProject::CreateAudioGroupProject(const AudioGroupData& data) AudioGroupProject AudioGroupProject::CreateAudioGroupProject(const AudioGroupData& data) {
{
if (data.getProjSize() < 4) if (data.getProjSize() < 4)
return {}; return {};
athena::io::MemoryReader r(data.getProj(), data.getProjSize()); athena::io::MemoryReader r(data.getProj(), data.getProjSize());
switch (data.getDataFormat()) switch (data.getDataFormat()) {
{
case DataFormat::GCN: case DataFormat::GCN:
default: default:
return AudioGroupProject(r, GCNDataTag{}); return AudioGroupProject(r, GCNDataTag{});
@ -356,8 +312,7 @@ AudioGroupProject AudioGroupProject::CreateAudioGroupProject(const AudioGroupDat
} }
} }
std::string ParseStringSlashId(const std::string& str, uint16_t& idOut) std::string ParseStringSlashId(const std::string& str, uint16_t& idOut) {
{
size_t slashPos = str.find('/'); size_t slashPos = str.find('/');
if (slashPos == std::string::npos) if (slashPos == std::string::npos)
return {}; return {};
@ -365,30 +320,24 @@ std::string ParseStringSlashId(const std::string& str, uint16_t& idOut)
return {str.begin(), str.begin() + slashPos}; return {str.begin(), str.begin() + slashPos};
} }
void SongGroupIndex::fromYAML(athena::io::YAMLDocReader& r) void SongGroupIndex::fromYAML(athena::io::YAMLDocReader& r) {
{ if (auto __v2 = r.enterSubRecord("normPages")) {
if (auto __v2 = r.enterSubRecord("normPages"))
{
m_normPages.reserve(r.getCurNode()->m_mapChildren.size()); m_normPages.reserve(r.getCurNode()->m_mapChildren.size());
for (const auto& pg : r.getCurNode()->m_mapChildren) for (const auto& pg : r.getCurNode()->m_mapChildren)
if (auto __r2 = r.enterSubRecord(pg.first.c_str())) if (auto __r2 = r.enterSubRecord(pg.first.c_str()))
m_normPages[strtoul(pg.first.c_str(), nullptr, 0)].read(r); m_normPages[strtoul(pg.first.c_str(), nullptr, 0)].read(r);
} }
if (auto __v2 = r.enterSubRecord("drumPages")) if (auto __v2 = r.enterSubRecord("drumPages")) {
{
m_drumPages.reserve(r.getCurNode()->m_mapChildren.size()); m_drumPages.reserve(r.getCurNode()->m_mapChildren.size());
for (const auto& pg : r.getCurNode()->m_mapChildren) for (const auto& pg : r.getCurNode()->m_mapChildren)
if (auto __r2 = r.enterSubRecord(pg.first.c_str())) if (auto __r2 = r.enterSubRecord(pg.first.c_str()))
m_drumPages[strtoul(pg.first.c_str(), nullptr, 0)].read(r); m_drumPages[strtoul(pg.first.c_str(), nullptr, 0)].read(r);
} }
if (auto __v2 = r.enterSubRecord("songs")) if (auto __v2 = r.enterSubRecord("songs")) {
{
m_midiSetups.reserve(r.getCurNode()->m_mapChildren.size()); m_midiSetups.reserve(r.getCurNode()->m_mapChildren.size());
for (const auto& song : r.getCurNode()->m_mapChildren) for (const auto& song : r.getCurNode()->m_mapChildren) {
{
size_t chanCount; size_t chanCount;
if (auto __v3 = r.enterSubVector(song.first.c_str(), chanCount)) if (auto __v3 = r.enterSubVector(song.first.c_str(), chanCount)) {
{
uint16_t songId; uint16_t songId;
std::string songName = ParseStringSlashId(song.first, songId); std::string songName = ParseStringSlashId(song.first, songId);
if (songName.empty() || songId == 0xffff) if (songName.empty() || songId == 0xffff)
@ -404,11 +353,9 @@ void SongGroupIndex::fromYAML(athena::io::YAMLDocReader& r)
} }
} }
void SFXGroupIndex::fromYAML(athena::io::YAMLDocReader& r) void SFXGroupIndex::fromYAML(athena::io::YAMLDocReader& r) {
{
for (const auto& sfx : r.getCurNode()->m_mapChildren) for (const auto& sfx : r.getCurNode()->m_mapChildren)
if (auto __r2 = r.enterSubRecord(sfx.first.c_str())) if (auto __r2 = r.enterSubRecord(sfx.first.c_str())) {
{
uint16_t sfxId; uint16_t sfxId;
std::string sfxName = ParseStringSlashId(sfx.first, sfxId); std::string sfxName = ParseStringSlashId(sfx.first, sfxId);
if (sfxName.empty() || sfxId == 0xffff) if (sfxName.empty() || sfxId == 0xffff)
@ -418,25 +365,19 @@ void SFXGroupIndex::fromYAML(athena::io::YAMLDocReader& r)
} }
} }
AudioGroupProject AudioGroupProject::CreateAudioGroupProject(SystemStringView groupPath) AudioGroupProject AudioGroupProject::CreateAudioGroupProject(SystemStringView groupPath) {
{
AudioGroupProject ret; AudioGroupProject ret;
SystemString projPath(groupPath); SystemString projPath(groupPath);
projPath += _SYS_STR("/!project.yaml"); projPath += _SYS_STR("/!project.yaml");
athena::io::FileReader fi(projPath, 32 * 1024, false); athena::io::FileReader fi(projPath, 32 * 1024, false);
if (!fi.hasError()) if (!fi.hasError()) {
{
athena::io::YAMLDocReader r; athena::io::YAMLDocReader r;
if (r.parse(&fi) && !r.readString("DNAType").compare("amuse::Project")) if (r.parse(&fi) && !r.readString("DNAType").compare("amuse::Project")) {
{ if (auto __v = r.enterSubRecord("songGroups")) {
if (auto __v = r.enterSubRecord("songGroups"))
{
ret.m_songGroups.reserve(r.getCurNode()->m_mapChildren.size()); ret.m_songGroups.reserve(r.getCurNode()->m_mapChildren.size());
for (const auto& grp : r.getCurNode()->m_mapChildren) for (const auto& grp : r.getCurNode()->m_mapChildren) {
{ if (auto __r = r.enterSubRecord(grp.first.c_str())) {
if (auto __r = r.enterSubRecord(grp.first.c_str()))
{
uint16_t groupId; uint16_t groupId;
std::string groupName = ParseStringSlashId(grp.first, groupId); std::string groupName = ParseStringSlashId(grp.first, groupId);
if (groupName.empty() || groupId == 0xffff) if (groupName.empty() || groupId == 0xffff)
@ -450,13 +391,10 @@ AudioGroupProject AudioGroupProject::CreateAudioGroupProject(SystemStringView gr
} }
} }
if (auto __v = r.enterSubRecord("sfxGroups")) if (auto __v = r.enterSubRecord("sfxGroups")) {
{
ret.m_sfxGroups.reserve(r.getCurNode()->m_mapChildren.size()); ret.m_sfxGroups.reserve(r.getCurNode()->m_mapChildren.size());
for (const auto& grp : r.getCurNode()->m_mapChildren) for (const auto& grp : r.getCurNode()->m_mapChildren) {
{ if (auto __r = r.enterSubRecord(grp.first.c_str())) {
if (auto __r = r.enterSubRecord(grp.first.c_str()))
{
uint16_t groupId; uint16_t groupId;
std::string groupName = ParseStringSlashId(grp.first, groupId); std::string groupName = ParseStringSlashId(grp.first, groupId);
if (groupName.empty() || groupId == 0xffff) if (groupName.empty() || groupId == 0xffff)
@ -475,13 +413,11 @@ AudioGroupProject AudioGroupProject::CreateAudioGroupProject(SystemStringView gr
return ret; return ret;
} }
static ObjectId RegisterDedupedName(ObjectId origId, amuse::NameDB* db, NameDB::Type tp) static ObjectId RegisterDedupedName(ObjectId origId, amuse::NameDB* db, NameDB::Type tp) {
{
std::string dupeName = std::string(db->resolveNameFromId(origId)) + "-copy"; std::string dupeName = std::string(db->resolveNameFromId(origId)) + "-copy";
std::string useName = dupeName; std::string useName = dupeName;
int dupeIdx = 1; int dupeIdx = 1;
while (db->m_stringToId.find(useName) != db->m_stringToId.cend()) while (db->m_stringToId.find(useName) != db->m_stringToId.cend()) {
{
char num[16]; char num[16];
snprintf(num, 16, "%d", dupeIdx++); snprintf(num, 16, "%d", dupeIdx++);
useName = dupeName + num; useName = dupeName + num;
@ -491,14 +427,12 @@ static ObjectId RegisterDedupedName(ObjectId origId, amuse::NameDB* db, NameDB::
return ret; return ret;
} }
SFXGroupIndex::SFXGroupIndex(const SFXGroupIndex& other) SFXGroupIndex::SFXGroupIndex(const SFXGroupIndex& other) {
{
for (const auto& sfx : other.m_sfxEntries) for (const auto& sfx : other.m_sfxEntries)
m_sfxEntries[RegisterDedupedName(sfx.first, SFXId::CurNameDB, NameDB::Type::SFX)] = sfx.second; m_sfxEntries[RegisterDedupedName(sfx.first, SFXId::CurNameDB, NameDB::Type::SFX)] = sfx.second;
} }
AudioGroupProject AudioGroupProject::CreateAudioGroupProject(const AudioGroupProject& oldProj) AudioGroupProject AudioGroupProject::CreateAudioGroupProject(const AudioGroupProject& oldProj) {
{
AudioGroupProject ret; AudioGroupProject ret;
for (const auto& grp : oldProj.songGroups()) for (const auto& grp : oldProj.songGroups())
@ -511,10 +445,8 @@ AudioGroupProject AudioGroupProject::CreateAudioGroupProject(const AudioGroupPro
return ret; return ret;
} }
void AudioGroupProject::BootstrapObjectIDs(athena::io::IStreamReader& r, GCNDataTag) void AudioGroupProject::BootstrapObjectIDs(athena::io::IStreamReader& r, GCNDataTag) {
{ while (!AtEnd32(r)) {
while (!AtEnd32(r))
{
GroupHeader<athena::Big> header; GroupHeader<athena::Big> header;
header.read(r); header.read(r);
@ -545,29 +477,23 @@ void AudioGroupProject::BootstrapObjectIDs(athena::io::IStreamReader& r, GCNData
while (!AtEnd16(r)) while (!AtEnd16(r))
ReadRangedObjectIds<athena::Big>(LayersId::CurNameDB, r, NameDB::Type::Layer); ReadRangedObjectIds<athena::Big>(LayersId::CurNameDB, r, NameDB::Type::Layer);
if (header.type == GroupType::Song) if (header.type == GroupType::Song) {
{
/* MIDI setups */ /* MIDI setups */
r.seek(header.midiSetupsOff, athena::Begin); r.seek(header.midiSetupsOff, athena::Begin);
while (r.position() < header.groupEndOff) while (r.position() < header.groupEndOff) {
{
uint16_t id = r.readUint16Big(); uint16_t id = r.readUint16Big();
SongId::CurNameDB->registerPair(NameDB::generateName(id, NameDB::Type::Song), id); SongId::CurNameDB->registerPair(NameDB::generateName(id, NameDB::Type::Song), id);
r.seek(2 + 5 * 16, athena::Current); r.seek(2 + 5 * 16, athena::Current);
} }
} } else if (header.type == GroupType::SFX) {
else if (header.type == GroupType::SFX)
{
/* SFX entries */ /* SFX entries */
r.seek(header.pageTableOff, athena::Begin); r.seek(header.pageTableOff, athena::Begin);
uint16_t count = r.readUint16Big(); uint16_t count = r.readUint16Big();
r.seek(2, athena::Current); r.seek(2, athena::Current);
for (int i = 0; i < count; ++i) for (int i = 0; i < count; ++i) {
{
SFXGroupIndex::SFXEntryDNA<athena::Big> entry; SFXGroupIndex::SFXEntryDNA<athena::Big> entry;
entry.read(r); entry.read(r);
SFXId::CurNameDB->registerPair( SFXId::CurNameDB->registerPair(NameDB::generateName(entry.sfxId.id, NameDB::Type::SFX), entry.sfxId.id);
NameDB::generateName(entry.sfxId.id, NameDB::Type::SFX), entry.sfxId.id);
} }
} }
@ -576,10 +502,8 @@ void AudioGroupProject::BootstrapObjectIDs(athena::io::IStreamReader& r, GCNData
} }
template <athena::Endian DNAE> template <athena::Endian DNAE>
void AudioGroupProject::BootstrapObjectIDs(athena::io::IStreamReader& r, bool absOffs) void AudioGroupProject::BootstrapObjectIDs(athena::io::IStreamReader& r, bool absOffs) {
{ while (!AtEnd32(r)) {
while (!AtEnd32(r))
{
atInt64 groupBegin = r.position(); atInt64 groupBegin = r.position();
atInt64 subDataOff = absOffs ? 0 : groupBegin + 8; atInt64 subDataOff = absOffs ? 0 : groupBegin + 8;
GroupHeader<DNAE> header; GroupHeader<DNAE> header;
@ -612,46 +536,36 @@ void AudioGroupProject::BootstrapObjectIDs(athena::io::IStreamReader& r, bool ab
while (!AtEnd16(r)) while (!AtEnd16(r))
ReadRangedObjectIds<DNAE>(LayersId::CurNameDB, r, NameDB::Type::Layer); ReadRangedObjectIds<DNAE>(LayersId::CurNameDB, r, NameDB::Type::Layer);
if (header.type == GroupType::Song) if (header.type == GroupType::Song) {
{
/* MIDI setups */ /* MIDI setups */
if (absOffs) if (absOffs) {
{
r.seek(header.midiSetupsOff, athena::Begin); r.seek(header.midiSetupsOff, athena::Begin);
while (r.position() < header.groupEndOff) while (r.position() < header.groupEndOff) {
{
uint16_t id; uint16_t id;
athena::io::Read<athena::io::PropType::None>::Do<decltype(id), DNAE>({}, id, r); athena::io::Read<athena::io::PropType::None>::Do<decltype(id), DNAE>({}, id, r);
SongId::CurNameDB->registerPair(NameDB::generateName(id, NameDB::Type::Song), id); SongId::CurNameDB->registerPair(NameDB::generateName(id, NameDB::Type::Song), id);
r.seek(2 + 5 * 16, athena::Current); r.seek(2 + 5 * 16, athena::Current);
} }
} } else {
else
{
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 id; uint16_t id;
athena::io::Read<athena::io::PropType::None>::Do<decltype(id), DNAE>({}, id, r); athena::io::Read<athena::io::PropType::None>::Do<decltype(id), DNAE>({}, id, r);
SongId::CurNameDB->registerPair(NameDB::generateName(id, NameDB::Type::Song), id); SongId::CurNameDB->registerPair(NameDB::generateName(id, NameDB::Type::Song), id);
r.seek(2 + 8 * 16, athena::Current); r.seek(2 + 8 * 16, athena::Current);
} }
} }
} } else if (header.type == GroupType::SFX) {
else if (header.type == GroupType::SFX)
{
/* SFX entries */ /* SFX entries */
r.seek(subDataOff + header.pageTableOff, athena::Begin); r.seek(subDataOff + header.pageTableOff, athena::Begin);
uint16_t count; uint16_t count;
athena::io::Read<athena::io::PropType::None>::Do<decltype(count), DNAE>({}, count, r); athena::io::Read<athena::io::PropType::None>::Do<decltype(count), DNAE>({}, count, r);
r.seek(2, athena::Current); r.seek(2, athena::Current);
for (int i = 0; i < count; ++i) for (int i = 0; i < count; ++i) {
{
SFXGroupIndex::SFXEntryDNA<DNAE> entry; SFXGroupIndex::SFXEntryDNA<DNAE> entry;
entry.read(r); entry.read(r);
r.seek(2, athena::Current); r.seek(2, athena::Current);
SFXId::CurNameDB->registerPair( SFXId::CurNameDB->registerPair(NameDB::generateName(entry.sfxId.id, NameDB::Type::SFX), entry.sfxId.id);
NameDB::generateName(entry.sfxId.id, NameDB::Type::SFX), entry.sfxId.id);
} }
} }
@ -662,11 +576,9 @@ void AudioGroupProject::BootstrapObjectIDs(athena::io::IStreamReader& r, bool ab
} }
} }
void AudioGroupProject::BootstrapObjectIDs(const AudioGroupData& data) void AudioGroupProject::BootstrapObjectIDs(const AudioGroupData& data) {
{
athena::io::MemoryReader r(data.getProj(), data.getProjSize()); athena::io::MemoryReader r(data.getProj(), data.getProjSize());
switch (data.getDataFormat()) switch (data.getDataFormat()) {
{
case DataFormat::GCN: case DataFormat::GCN:
default: default:
BootstrapObjectIDs(r, GCNDataTag{}); BootstrapObjectIDs(r, GCNDataTag{});
@ -680,69 +592,54 @@ void AudioGroupProject::BootstrapObjectIDs(const AudioGroupData& data)
} }
} }
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);
if (search != m_songGroups.cend()) if (search != m_songGroups.cend())
return search->second.get(); return search->second.get();
return nullptr; return nullptr;
} }
const SFXGroupIndex* AudioGroupProject::getSFXGroupIndex(int groupId) const const SFXGroupIndex* AudioGroupProject::getSFXGroupIndex(int groupId) const {
{
auto search = m_sfxGroups.find(groupId); auto search = m_sfxGroups.find(groupId);
if (search != m_sfxGroups.cend()) if (search != m_sfxGroups.cend())
return search->second.get(); return search->second.get();
return nullptr; return nullptr;
} }
void SongGroupIndex::toYAML(athena::io::YAMLDocWriter& w) const void SongGroupIndex::toYAML(athena::io::YAMLDocWriter& w) const {
{ if (!m_normPages.empty()) {
if (!m_normPages.empty()) if (auto __v2 = w.enterSubRecord("normPages")) {
{ for (const auto& pg : SortUnorderedMap(m_normPages)) {
if (auto __v2 = w.enterSubRecord("normPages"))
{
for (const auto& pg : SortUnorderedMap(m_normPages))
{
char name[16]; char name[16];
snprintf(name, 16, "%d", pg.first); snprintf(name, 16, "%d", pg.first);
if (auto __r2 = w.enterSubRecord(name)) if (auto __r2 = w.enterSubRecord(name)) {
{
w.setStyle(athena::io::YAMLNodeStyle::Flow); w.setStyle(athena::io::YAMLNodeStyle::Flow);
pg.second.get().write(w); pg.second.get().write(w);
} }
} }
} }
} }
if (!m_drumPages.empty()) if (!m_drumPages.empty()) {
{ if (auto __v2 = w.enterSubRecord("drumPages")) {
if (auto __v2 = w.enterSubRecord("drumPages")) for (const auto& pg : SortUnorderedMap(m_drumPages)) {
{
for (const auto& pg : SortUnorderedMap(m_drumPages))
{
char name[16]; char name[16];
snprintf(name, 16, "%d", pg.first); snprintf(name, 16, "%d", pg.first);
if (auto __r2 = w.enterSubRecord(name)) if (auto __r2 = w.enterSubRecord(name)) {
{
w.setStyle(athena::io::YAMLNodeStyle::Flow); w.setStyle(athena::io::YAMLNodeStyle::Flow);
pg.second.get().write(w); pg.second.get().write(w);
} }
} }
} }
} }
if (!m_midiSetups.empty()) if (!m_midiSetups.empty()) {
{ if (auto __v2 = w.enterSubRecord("songs")) {
if (auto __v2 = w.enterSubRecord("songs")) for (const auto& song : SortUnorderedMap(m_midiSetups)) {
{
for (const auto& song : SortUnorderedMap(m_midiSetups))
{
char songString[64]; char songString[64];
snprintf(songString, 64, "%s/0x%04X", snprintf(songString, 64, "%s/0x%04X", SongId::CurNameDB->resolveNameFromId(song.first).data(),
SongId::CurNameDB->resolveNameFromId(song.first).data(), int(song.first.id)); int(song.first.id));
if (auto __v3 = w.enterSubVector(songString)) if (auto __v3 = w.enterSubVector(songString))
for (int i = 0; i < 16; ++i) for (int i = 0; i < 16; ++i)
if (auto __r2 = w.enterSubRecord(nullptr)) if (auto __r2 = w.enterSubRecord(nullptr)) {
{
w.setStyle(athena::io::YAMLNodeStyle::Flow); w.setStyle(athena::io::YAMLNodeStyle::Flow);
song.second.get()[i].write(w); song.second.get()[i].write(w);
} }
@ -751,51 +648,38 @@ void SongGroupIndex::toYAML(athena::io::YAMLDocWriter& w) const
} }
} }
void SFXGroupIndex::toYAML(athena::io::YAMLDocWriter& w) const void SFXGroupIndex::toYAML(athena::io::YAMLDocWriter& w) const {
{ for (const auto& sfx : SortUnorderedMap(m_sfxEntries)) {
for (const auto& sfx : SortUnorderedMap(m_sfxEntries))
{
char sfxString[64]; char sfxString[64];
snprintf(sfxString, 64, "%s/0x%04X", snprintf(sfxString, 64, "%s/0x%04X", SFXId::CurNameDB->resolveNameFromId(sfx.first).data(), int(sfx.first.id));
SFXId::CurNameDB->resolveNameFromId(sfx.first).data(), int(sfx.first.id)); if (auto __r2 = w.enterSubRecord(sfxString)) {
if (auto __r2 = w.enterSubRecord(sfxString))
{
w.setStyle(athena::io::YAMLNodeStyle::Flow); w.setStyle(athena::io::YAMLNodeStyle::Flow);
sfx.second.get().write(w); sfx.second.get().write(w);
} }
} }
} }
std::vector<uint8_t> AudioGroupProject::toYAML() const std::vector<uint8_t> AudioGroupProject::toYAML() const {
{
athena::io::YAMLDocWriter w("amuse::Project"); athena::io::YAMLDocWriter w("amuse::Project");
if (!m_songGroups.empty()) if (!m_songGroups.empty()) {
{ if (auto __v = w.enterSubRecord("songGroups")) {
if (auto __v = w.enterSubRecord("songGroups")) for (const auto& p : SortUnorderedMap(m_songGroups)) {
{
for (const auto& p : SortUnorderedMap(m_songGroups))
{
char groupString[64]; char groupString[64];
snprintf(groupString, 64, "%s/0x%04X", GroupId::CurNameDB->resolveNameFromId(p.first).data(), int(p.first.id)); snprintf(groupString, 64, "%s/0x%04X", GroupId::CurNameDB->resolveNameFromId(p.first).data(), int(p.first.id));
if (auto __r = w.enterSubRecord(groupString)) if (auto __r = w.enterSubRecord(groupString)) {
{
p.second.get()->toYAML(w); p.second.get()->toYAML(w);
} }
} }
} }
} }
if (!m_sfxGroups.empty()) if (!m_sfxGroups.empty()) {
{ if (auto __v = w.enterSubRecord("sfxGroups")) {
if (auto __v = w.enterSubRecord("sfxGroups")) for (const auto& p : SortUnorderedMap(m_sfxGroups)) {
{
for (const auto& p : SortUnorderedMap(m_sfxGroups))
{
char groupString[64]; char groupString[64];
snprintf(groupString, 64, "%s/0x%04X", GroupId::CurNameDB->resolveNameFromId(p.first).data(), int(p.first.id)); snprintf(groupString, 64, "%s/0x%04X", GroupId::CurNameDB->resolveNameFromId(p.first).data(), int(p.first.id));
if (auto __r = w.enterSubRecord(groupString)) if (auto __r = w.enterSubRecord(groupString)) {
{
p.second.get()->toYAML(w); p.second.get()->toYAML(w);
} }
} }
@ -918,8 +802,7 @@ struct ObjectIdPool
#endif #endif
std::vector<uint8_t> AudioGroupProject::toGCNData(const AudioGroupPool& pool, std::vector<uint8_t> AudioGroupProject::toGCNData(const AudioGroupPool& pool,
const AudioGroupSampleDirectory& sdir) const const AudioGroupSampleDirectory& sdir) const {
{
constexpr athena::Endian DNAE = athena::Big; constexpr athena::Endian DNAE = athena::Big;
athena::io::VectorWriter fo; athena::io::VectorWriter fo;
@ -935,11 +818,9 @@ std::vector<uint8_t> AudioGroupProject::toGCNData(const AudioGroupPool& pool,
const uint64_t term64 = 0xffffffffffffffff; const uint64_t term64 = 0xffffffffffffffff;
const uint16_t padding = 0; const uint16_t padding = 0;
for (GroupId id : groupIds) for (GroupId id : groupIds) {
{
auto search = m_songGroups.find(id); auto search = m_songGroups.find(id);
if (search != m_songGroups.end()) if (search != m_songGroups.end()) {
{
const SongGroupIndex& index = *search->second; const SongGroupIndex& index = *search->second;
auto groupStart = fo.position(); auto groupStart = fo.position();
@ -961,30 +842,27 @@ std::vector<uint8_t> AudioGroupProject::toGCNData(const AudioGroupPool& pool,
WriteRangedObjectIds<DNAE>(fo, SortUnorderedMap(pool.layers())); WriteRangedObjectIds<DNAE>(fo, SortUnorderedMap(pool.layers()));
header.pageTableOff = fo.position(); header.pageTableOff = fo.position();
for (auto& p : SortUnorderedMap(index.m_normPages)) for (auto& p : SortUnorderedMap(index.m_normPages)) {
{
SongGroupIndex::PageEntryDNA<DNAE> entry = p.second.get().toDNA<DNAE>(p.first); SongGroupIndex::PageEntryDNA<DNAE> entry = p.second.get().toDNA<DNAE>(p.first);
entry.write(fo); entry.write(fo);
} }
athena::io::Write<athena::io::PropType::None>::Do<decltype(term64), DNAE>({}, term64, fo); athena::io::Write<athena::io::PropType::None>::Do<decltype(term64), DNAE>({}, term64, fo);
header.drumTableOff = fo.position(); header.drumTableOff = fo.position();
for (auto& p : SortUnorderedMap(index.m_drumPages)) for (auto& p : SortUnorderedMap(index.m_drumPages)) {
{
SongGroupIndex::PageEntryDNA<DNAE> entry = p.second.get().toDNA<DNAE>(p.first); SongGroupIndex::PageEntryDNA<DNAE> entry = p.second.get().toDNA<DNAE>(p.first);
entry.write(fo); entry.write(fo);
} }
athena::io::Write<athena::io::PropType::None>::Do<decltype(term64), DNAE>({}, term64, fo); athena::io::Write<athena::io::PropType::None>::Do<decltype(term64), DNAE>({}, term64, fo);
header.midiSetupsOff = fo.position(); header.midiSetupsOff = fo.position();
for (auto& p : SortUnorderedMap(index.m_midiSetups)) for (auto& p : SortUnorderedMap(index.m_midiSetups)) {
{
uint16_t songId = p.first.id; uint16_t songId = p.first.id;
athena::io::Write<athena::io::PropType::None>::Do<decltype(songId), DNAE>({}, songId, fo); athena::io::Write<athena::io::PropType::None>::Do<decltype(songId), DNAE>({}, songId, fo);
athena::io::Write<athena::io::PropType::None>::Do<decltype(padding), DNAE>({}, padding, fo); athena::io::Write<athena::io::PropType::None>::Do<decltype(padding), DNAE>({}, padding, fo);
const std::array<SongGroupIndex::MIDISetup, 16>& setup = p.second.get(); const std::array<SongGroupIndex::MIDISetup, 16>& setup = p.second.get();
for (int i = 0; i < 16 ; ++i) for (int i = 0; i < 16; ++i)
setup[i].write(fo); setup[i].write(fo);
} }
@ -992,12 +870,9 @@ std::vector<uint8_t> AudioGroupProject::toGCNData(const AudioGroupPool& pool,
fo.seek(groupStart, athena::Begin); fo.seek(groupStart, athena::Begin);
header.write(fo); header.write(fo);
fo.seek(header.groupEndOff, athena::Begin); fo.seek(header.groupEndOff, athena::Begin);
} } else {
else
{
auto search2 = m_sfxGroups.find(id); auto search2 = m_sfxGroups.find(id);
if (search2 != m_sfxGroups.end()) if (search2 != m_sfxGroups.end()) {
{
const SFXGroupIndex& index = *search2->second; const SFXGroupIndex& index = *search2->second;
auto groupStart = fo.position(); auto groupStart = fo.position();
@ -1022,8 +897,7 @@ std::vector<uint8_t> AudioGroupProject::toGCNData(const AudioGroupPool& pool,
uint16_t count = index.m_sfxEntries.size(); uint16_t count = index.m_sfxEntries.size();
athena::io::Write<athena::io::PropType::None>::Do<decltype(count), DNAE>({}, count, fo); athena::io::Write<athena::io::PropType::None>::Do<decltype(count), DNAE>({}, count, fo);
athena::io::Write<athena::io::PropType::None>::Do<decltype(padding), DNAE>({}, padding, fo); athena::io::Write<athena::io::PropType::None>::Do<decltype(padding), DNAE>({}, padding, fo);
for (auto& p : SortUnorderedMap(index.m_sfxEntries)) for (auto& p : SortUnorderedMap(index.m_sfxEntries)) {
{
SFXGroupIndex::SFXEntryDNA<DNAE> entry = p.second.get().toDNA<DNAE>(p.first); SFXGroupIndex::SFXEntryDNA<DNAE> entry = p.second.get().toDNA<DNAE>(p.first);
entry.write(fo); entry.write(fo);
} }
@ -1042,4 +916,4 @@ std::vector<uint8_t> AudioGroupProject::toGCNData(const AudioGroupPool& pool,
return fo.data(); return fo.data();
} }
} } // namespace amuse

File diff suppressed because it is too large Load Diff

View File

@ -3,45 +3,39 @@
#include "amuse/Submix.hpp" #include "amuse/Submix.hpp"
#include "amuse/Engine.hpp" #include "amuse/Engine.hpp"
namespace amuse namespace amuse {
{
void BooBackendVoice::VoiceCallback::preSupplyAudio(boo::IAudioVoice&, double dt) void BooBackendVoice::VoiceCallback::preSupplyAudio(boo::IAudioVoice&, double dt) {
{
m_parent.m_clientVox.preSupplyAudio(dt); m_parent.m_clientVox.preSupplyAudio(dt);
} }
size_t BooBackendVoice::VoiceCallback::supplyAudio(boo::IAudioVoice&, size_t frames, int16_t* data) size_t BooBackendVoice::VoiceCallback::supplyAudio(boo::IAudioVoice&, size_t frames, int16_t* data) {
{
return m_parent.m_clientVox.supplyAudio(frames, data); return m_parent.m_clientVox.supplyAudio(frames, data);
} }
void BooBackendVoice::VoiceCallback::routeAudio(size_t frames, size_t channels, double dt, int busId, int16_t* in, int16_t* out) void BooBackendVoice::VoiceCallback::routeAudio(size_t frames, size_t channels, double dt, int busId, int16_t* in,
{ int16_t* out) {
m_parent.m_clientVox.routeAudio(frames, dt, busId, in, out); m_parent.m_clientVox.routeAudio(frames, dt, busId, in, out);
} }
void BooBackendVoice::VoiceCallback::routeAudio(size_t frames, size_t channels, double dt, int busId, int32_t* in, int32_t* out) void BooBackendVoice::VoiceCallback::routeAudio(size_t frames, size_t channels, double dt, int busId, int32_t* in,
{ int32_t* out) {
m_parent.m_clientVox.routeAudio(frames, dt, busId, in, out); m_parent.m_clientVox.routeAudio(frames, dt, busId, in, out);
} }
void BooBackendVoice::VoiceCallback::routeAudio(size_t frames, size_t channels, double dt, int busId, float* in, float* out) void BooBackendVoice::VoiceCallback::routeAudio(size_t frames, size_t channels, double dt, int busId, float* in,
{ float* out) {
m_parent.m_clientVox.routeAudio(frames, dt, busId, in, out); m_parent.m_clientVox.routeAudio(frames, dt, busId, in, out);
} }
BooBackendVoice::BooBackendVoice(boo::IAudioVoiceEngine& engine, Voice& clientVox, double sampleRate, bool dynamicPitch) BooBackendVoice::BooBackendVoice(boo::IAudioVoiceEngine& engine, Voice& clientVox, double sampleRate, bool dynamicPitch)
: m_clientVox(clientVox), m_cb(*this), m_booVoice(engine.allocateNewMonoVoice(sampleRate, &m_cb, dynamicPitch)) : m_clientVox(clientVox), m_cb(*this), m_booVoice(engine.allocateNewMonoVoice(sampleRate, &m_cb, dynamicPitch)) {}
{
}
void BooBackendVoice::resetSampleRate(double sampleRate) { m_booVoice->resetSampleRate(sampleRate); } void BooBackendVoice::resetSampleRate(double sampleRate) { m_booVoice->resetSampleRate(sampleRate); }
void BooBackendVoice::resetChannelLevels() { m_booVoice->resetChannelLevels(); } void BooBackendVoice::resetChannelLevels() { m_booVoice->resetChannelLevels(); }
void BooBackendVoice::setChannelLevels(IBackendSubmix* submix, const float coefs[8], bool slew) void BooBackendVoice::setChannelLevels(IBackendSubmix* submix, const float coefs[8], bool slew) {
{
BooBackendSubmix& smx = *reinterpret_cast<BooBackendSubmix*>(submix); BooBackendSubmix& smx = *reinterpret_cast<BooBackendSubmix*>(submix);
m_booVoice->setMonoChannelLevels(smx.m_booSubmix.get(), coefs, slew); m_booVoice->setMonoChannelLevels(smx.m_booSubmix.get(), coefs, slew);
} }
@ -55,35 +49,28 @@ void BooBackendVoice::stop() { m_booVoice->stop(); }
bool BooBackendSubmix::SubmixCallback::canApplyEffect() const { return m_parent.m_clientSmx.canApplyEffect(); } bool BooBackendSubmix::SubmixCallback::canApplyEffect() const { return m_parent.m_clientSmx.canApplyEffect(); }
void BooBackendSubmix::SubmixCallback::applyEffect(int16_t* audio, size_t frameCount, const boo::ChannelMap& chanMap, void BooBackendSubmix::SubmixCallback::applyEffect(int16_t* audio, size_t frameCount, const boo::ChannelMap& chanMap,
double) const double) const {
{
return m_parent.m_clientSmx.applyEffect(audio, frameCount, reinterpret_cast<const ChannelMap&>(chanMap)); return m_parent.m_clientSmx.applyEffect(audio, frameCount, reinterpret_cast<const ChannelMap&>(chanMap));
} }
void BooBackendSubmix::SubmixCallback::applyEffect(int32_t* audio, size_t frameCount, const boo::ChannelMap& chanMap, void BooBackendSubmix::SubmixCallback::applyEffect(int32_t* audio, size_t frameCount, const boo::ChannelMap& chanMap,
double) const double) const {
{
return m_parent.m_clientSmx.applyEffect(audio, frameCount, reinterpret_cast<const ChannelMap&>(chanMap)); return m_parent.m_clientSmx.applyEffect(audio, frameCount, reinterpret_cast<const ChannelMap&>(chanMap));
} }
void BooBackendSubmix::SubmixCallback::applyEffect(float* audio, size_t frameCount, const boo::ChannelMap& chanMap, void BooBackendSubmix::SubmixCallback::applyEffect(float* audio, size_t frameCount, const boo::ChannelMap& chanMap,
double) const double) const {
{
return m_parent.m_clientSmx.applyEffect(audio, frameCount, reinterpret_cast<const ChannelMap&>(chanMap)); return m_parent.m_clientSmx.applyEffect(audio, frameCount, reinterpret_cast<const ChannelMap&>(chanMap));
} }
void BooBackendSubmix::SubmixCallback::resetOutputSampleRate(double sampleRate) void BooBackendSubmix::SubmixCallback::resetOutputSampleRate(double sampleRate) {
{
m_parent.m_clientSmx.resetOutputSampleRate(sampleRate); m_parent.m_clientSmx.resetOutputSampleRate(sampleRate);
} }
BooBackendSubmix::BooBackendSubmix(boo::IAudioVoiceEngine& engine, Submix& clientSmx, bool mainOut, int busId) BooBackendSubmix::BooBackendSubmix(boo::IAudioVoiceEngine& engine, Submix& clientSmx, bool mainOut, int busId)
: m_clientSmx(clientSmx), m_cb(*this), m_booSubmix(engine.allocateNewSubmix(mainOut, &m_cb, busId)) : m_clientSmx(clientSmx), m_cb(*this), m_booSubmix(engine.allocateNewSubmix(mainOut, &m_cb, busId)) {}
{
}
void BooBackendSubmix::setSendLevel(IBackendSubmix* submix, float level, bool slew) void BooBackendSubmix::setSendLevel(IBackendSubmix* submix, float level, bool slew) {
{
BooBackendSubmix& smx = *reinterpret_cast<BooBackendSubmix*>(submix); BooBackendSubmix& smx = *reinterpret_cast<BooBackendSubmix*>(submix);
m_booSubmix->setSendLevel(smx.m_booSubmix.get(), level, slew); m_booSubmix->setSendLevel(smx.m_booSubmix.get(), level, slew);
} }
@ -95,14 +82,13 @@ SubmixFormat BooBackendSubmix::getSampleFormat() const { return SubmixFormat(m_b
BooBackendMIDIReader::~BooBackendMIDIReader() {} BooBackendMIDIReader::~BooBackendMIDIReader() {}
BooBackendMIDIReader::BooBackendMIDIReader(Engine& engine, bool useLock) BooBackendMIDIReader::BooBackendMIDIReader(Engine& engine, bool useLock)
: m_engine(engine), m_decoder(*this), m_useLock(useLock) : m_engine(engine), m_decoder(*this), m_useLock(useLock) {
{
BooBackendVoiceAllocator& voxAlloc = static_cast<BooBackendVoiceAllocator&>(engine.getBackend()); BooBackendVoiceAllocator& voxAlloc = static_cast<BooBackendVoiceAllocator&>(engine.getBackend());
auto devices = voxAlloc.m_booEngine.enumerateMIDIInputs(); auto devices = voxAlloc.m_booEngine.enumerateMIDIInputs();
for (const auto& dev : devices) for (const auto& dev : devices) {
{ auto midiIn =
auto midiIn = voxAlloc.m_booEngine.newRealMIDIIn(dev.first.c_str(), voxAlloc.m_booEngine.newRealMIDIIn(dev.first.c_str(), std::bind(&BooBackendMIDIReader::_MIDIReceive, this,
std::bind(&BooBackendMIDIReader::_MIDIReceive, this, std::placeholders::_1, std::placeholders::_2)); std::placeholders::_1, std::placeholders::_2));
if (midiIn) if (midiIn)
m_midiIns[dev.first] = std::move(midiIn); m_midiIns[dev.first] = std::move(midiIn);
} }
@ -111,47 +97,32 @@ BooBackendMIDIReader::BooBackendMIDIReader(Engine& engine, bool useLock)
std::bind(&BooBackendMIDIReader::_MIDIReceive, this, std::placeholders::_1, std::placeholders::_2)); std::bind(&BooBackendMIDIReader::_MIDIReceive, this, std::placeholders::_1, std::placeholders::_2));
} }
void BooBackendMIDIReader::addMIDIIn(const char* name) void BooBackendMIDIReader::addMIDIIn(const char* name) {
{
BooBackendVoiceAllocator& voxAlloc = static_cast<BooBackendVoiceAllocator&>(m_engine.getBackend()); BooBackendVoiceAllocator& voxAlloc = static_cast<BooBackendVoiceAllocator&>(m_engine.getBackend());
auto midiIn = voxAlloc.m_booEngine.newRealMIDIIn(name, auto midiIn = voxAlloc.m_booEngine.newRealMIDIIn(
std::bind(&BooBackendMIDIReader::_MIDIReceive, this, std::placeholders::_1, std::placeholders::_2)); name, std::bind(&BooBackendMIDIReader::_MIDIReceive, this, std::placeholders::_1, std::placeholders::_2));
if (midiIn) if (midiIn)
m_midiIns[name] = std::move(midiIn); m_midiIns[name] = std::move(midiIn);
} }
void BooBackendMIDIReader::removeMIDIIn(const char* name) void BooBackendMIDIReader::removeMIDIIn(const char* name) { m_midiIns.erase(name); }
{
m_midiIns.erase(name);
}
bool BooBackendMIDIReader::hasMIDIIn(const char* name) const bool BooBackendMIDIReader::hasMIDIIn(const char* name) const { return m_midiIns.find(name) != m_midiIns.cend(); }
{
return m_midiIns.find(name) != m_midiIns.cend();
}
void BooBackendMIDIReader::setVirtualIn(bool v) void BooBackendMIDIReader::setVirtualIn(bool v) {
{ if (v) {
if (v)
{
BooBackendVoiceAllocator& voxAlloc = static_cast<BooBackendVoiceAllocator&>(m_engine.getBackend()); BooBackendVoiceAllocator& voxAlloc = static_cast<BooBackendVoiceAllocator&>(m_engine.getBackend());
if (voxAlloc.m_booEngine.supportsVirtualMIDIIn()) if (voxAlloc.m_booEngine.supportsVirtualMIDIIn())
m_virtualIn = voxAlloc.m_booEngine.newVirtualMIDIIn( m_virtualIn = voxAlloc.m_booEngine.newVirtualMIDIIn(
std::bind(&BooBackendMIDIReader::_MIDIReceive, this, std::placeholders::_1, std::placeholders::_2)); std::bind(&BooBackendMIDIReader::_MIDIReceive, this, std::placeholders::_1, std::placeholders::_2));
} } else {
else
{
m_virtualIn.reset(); m_virtualIn.reset();
} }
} }
bool BooBackendMIDIReader::hasVirtualIn() const bool BooBackendMIDIReader::hasVirtualIn() const { return m_virtualIn.operator bool(); }
{
return m_virtualIn.operator bool();
}
void BooBackendMIDIReader::_MIDIReceive(std::vector<uint8_t>&& bytes, double time) void BooBackendMIDIReader::_MIDIReceive(std::vector<uint8_t>&& bytes, double time) {
{
std::unique_lock<std::mutex> lk(m_midiMutex, std::defer_lock_t{}); std::unique_lock<std::mutex> lk(m_midiMutex, std::defer_lock_t{});
if (m_useLock) if (m_useLock)
lk.lock(); lk.lock();
@ -163,8 +134,7 @@ void BooBackendMIDIReader::_MIDIReceive(std::vector<uint8_t>&& bytes, double tim
#endif #endif
} }
void BooBackendMIDIReader::pumpReader(double dt) void BooBackendMIDIReader::pumpReader(double dt) {
{
dt += 0.001; /* Add 1ms to ensure consumer keeps up with producer */ dt += 0.001; /* Add 1ms to ensure consumer keeps up with producer */
std::unique_lock<std::mutex> lk(m_midiMutex, std::defer_lock_t{}); std::unique_lock<std::mutex> lk(m_midiMutex, std::defer_lock_t{});
@ -176,8 +146,7 @@ void BooBackendMIDIReader::pumpReader(double dt)
/* Determine range of buffer updates within this period */ /* Determine range of buffer updates within this period */
auto periodEnd = m_queue.cbegin(); auto periodEnd = m_queue.cbegin();
double startPt = m_queue.front().first; double startPt = m_queue.front().first;
for (; periodEnd != m_queue.cend(); ++periodEnd) for (; periodEnd != m_queue.cend(); ++periodEnd) {
{
double delta = periodEnd->first - startPt; double delta = periodEnd->first - startPt;
if (delta > dt) if (delta > dt)
break; break;
@ -187,8 +156,7 @@ void BooBackendMIDIReader::pumpReader(double dt)
return; return;
/* Dispatch buffers */ /* Dispatch buffers */
for (auto it = m_queue.begin(); it != periodEnd;) for (auto it = m_queue.begin(); it != periodEnd;) {
{
#if 0 #if 0
char str[64]; char str[64];
sprintf(str, "MIDI %zu %f ", it->second.size(), it->first); sprintf(str, "MIDI %zu %f ", it->second.size(), it->first);
@ -203,8 +171,7 @@ void BooBackendMIDIReader::pumpReader(double dt)
} }
} }
void BooBackendMIDIReader::noteOff(uint8_t chan, uint8_t key, uint8_t velocity) void BooBackendMIDIReader::noteOff(uint8_t chan, uint8_t key, uint8_t velocity) {
{
for (ObjToken<Sequencer>& seq : m_engine.getActiveSequencers()) for (ObjToken<Sequencer>& seq : m_engine.getActiveSequencers())
seq->keyOff(chan, key, velocity); seq->keyOff(chan, key, velocity);
#if 0 #if 0
@ -214,8 +181,7 @@ void BooBackendMIDIReader::noteOff(uint8_t chan, uint8_t key, uint8_t velocity)
#endif #endif
} }
void BooBackendMIDIReader::noteOn(uint8_t chan, uint8_t key, uint8_t velocity) void BooBackendMIDIReader::noteOn(uint8_t chan, uint8_t key, uint8_t velocity) {
{
for (ObjToken<Sequencer>& seq : m_engine.getActiveSequencers()) for (ObjToken<Sequencer>& seq : m_engine.getActiveSequencers())
seq->keyOn(chan, key, velocity); seq->keyOn(chan, key, velocity);
#if 0 #if 0
@ -227,28 +193,24 @@ void BooBackendMIDIReader::noteOn(uint8_t chan, uint8_t key, uint8_t velocity)
void BooBackendMIDIReader::notePressure(uint8_t /*chan*/, uint8_t /*key*/, uint8_t /*pressure*/) {} void BooBackendMIDIReader::notePressure(uint8_t /*chan*/, uint8_t /*key*/, uint8_t /*pressure*/) {}
void BooBackendMIDIReader::controlChange(uint8_t chan, uint8_t control, uint8_t value) void BooBackendMIDIReader::controlChange(uint8_t chan, uint8_t control, uint8_t value) {
{
for (ObjToken<Sequencer>& seq : m_engine.getActiveSequencers()) for (ObjToken<Sequencer>& seq : m_engine.getActiveSequencers())
seq->setCtrlValue(chan, control, value); seq->setCtrlValue(chan, control, value);
} }
void BooBackendMIDIReader::programChange(uint8_t chan, uint8_t program) void BooBackendMIDIReader::programChange(uint8_t chan, uint8_t program) {
{
for (ObjToken<Sequencer>& seq : m_engine.getActiveSequencers()) for (ObjToken<Sequencer>& seq : m_engine.getActiveSequencers())
seq->setChanProgram(chan, program); seq->setChanProgram(chan, program);
} }
void BooBackendMIDIReader::channelPressure(uint8_t /*chan*/, uint8_t /*pressure*/) {} void BooBackendMIDIReader::channelPressure(uint8_t /*chan*/, uint8_t /*pressure*/) {}
void BooBackendMIDIReader::pitchBend(uint8_t chan, int16_t pitch) void BooBackendMIDIReader::pitchBend(uint8_t chan, int16_t pitch) {
{
for (ObjToken<Sequencer>& seq : m_engine.getActiveSequencers()) for (ObjToken<Sequencer>& seq : m_engine.getActiveSequencers())
seq->setPitchWheel(chan, (pitch - 0x2000) / float(0x2000)); seq->setPitchWheel(chan, (pitch - 0x2000) / float(0x2000));
} }
void BooBackendMIDIReader::allSoundOff(uint8_t chan) void BooBackendMIDIReader::allSoundOff(uint8_t chan) {
{
for (ObjToken<Sequencer>& seq : m_engine.getActiveSequencers()) for (ObjToken<Sequencer>& seq : m_engine.getActiveSequencers())
seq->allOff(chan, true); seq->allOff(chan, true);
} }
@ -257,8 +219,7 @@ void BooBackendMIDIReader::resetAllControllers(uint8_t /*chan*/) {}
void BooBackendMIDIReader::localControl(uint8_t /*chan*/, bool /*on*/) {} void BooBackendMIDIReader::localControl(uint8_t /*chan*/, bool /*on*/) {}
void BooBackendMIDIReader::allNotesOff(uint8_t chan) void BooBackendMIDIReader::allNotesOff(uint8_t chan) {
{
for (ObjToken<Sequencer>& seq : m_engine.getActiveSequencers()) for (ObjToken<Sequencer>& seq : m_engine.getActiveSequencers())
seq->allOff(chan, false); seq->allOff(chan, false);
} }
@ -285,51 +246,40 @@ void BooBackendMIDIReader::stopSeq() {}
void BooBackendMIDIReader::reset() {} void BooBackendMIDIReader::reset() {}
BooBackendVoiceAllocator::BooBackendVoiceAllocator(boo::IAudioVoiceEngine& booEngine) BooBackendVoiceAllocator::BooBackendVoiceAllocator(boo::IAudioVoiceEngine& booEngine) : m_booEngine(booEngine) {
: m_booEngine(booEngine)
{
booEngine.setCallbackInterface(this); booEngine.setCallbackInterface(this);
} }
std::unique_ptr<IBackendVoice> BooBackendVoiceAllocator::allocateVoice(Voice& clientVox, double sampleRate, std::unique_ptr<IBackendVoice> BooBackendVoiceAllocator::allocateVoice(Voice& clientVox, double sampleRate,
bool dynamicPitch) bool dynamicPitch) {
{
return std::make_unique<BooBackendVoice>(m_booEngine, clientVox, sampleRate, dynamicPitch); return std::make_unique<BooBackendVoice>(m_booEngine, clientVox, sampleRate, dynamicPitch);
} }
std::unique_ptr<IBackendSubmix> BooBackendVoiceAllocator::allocateSubmix(Submix& clientSmx, bool mainOut, int busId) std::unique_ptr<IBackendSubmix> BooBackendVoiceAllocator::allocateSubmix(Submix& clientSmx, bool mainOut, int busId) {
{
return std::make_unique<BooBackendSubmix>(m_booEngine, clientSmx, mainOut, busId); return std::make_unique<BooBackendSubmix>(m_booEngine, clientSmx, mainOut, busId);
} }
std::vector<std::pair<std::string, std::string>> BooBackendVoiceAllocator::enumerateMIDIDevices() std::vector<std::pair<std::string, std::string>> BooBackendVoiceAllocator::enumerateMIDIDevices() {
{
return m_booEngine.enumerateMIDIInputs(); return m_booEngine.enumerateMIDIInputs();
} }
std::unique_ptr<IMIDIReader> BooBackendVoiceAllocator::allocateMIDIReader(Engine& engine) std::unique_ptr<IMIDIReader> BooBackendVoiceAllocator::allocateMIDIReader(Engine& engine) {
{
return std::make_unique<BooBackendMIDIReader>(engine, m_booEngine.useMIDILock()); return std::make_unique<BooBackendMIDIReader>(engine, m_booEngine.useMIDILock());
} }
void BooBackendVoiceAllocator::setCallbackInterface(Engine* engine) void BooBackendVoiceAllocator::setCallbackInterface(Engine* engine) { m_cbInterface = engine; }
{
m_cbInterface = engine;
}
AudioChannelSet BooBackendVoiceAllocator::getAvailableSet() { return AudioChannelSet(m_booEngine.getAvailableSet()); } AudioChannelSet BooBackendVoiceAllocator::getAvailableSet() { return AudioChannelSet(m_booEngine.getAvailableSet()); }
void BooBackendVoiceAllocator::setVolume(float vol) { m_booEngine.setVolume(vol); } void BooBackendVoiceAllocator::setVolume(float vol) { m_booEngine.setVolume(vol); }
void BooBackendVoiceAllocator::on5MsInterval(boo::IAudioVoiceEngine& engine, double dt) void BooBackendVoiceAllocator::on5MsInterval(boo::IAudioVoiceEngine& engine, double dt) {
{
if (m_cbInterface) if (m_cbInterface)
m_cbInterface->_on5MsInterval(*this, dt); m_cbInterface->_on5MsInterval(*this, dt);
} }
void BooBackendVoiceAllocator::onPumpCycleComplete(boo::IAudioVoiceEngine& engine) void BooBackendVoiceAllocator::onPumpCycleComplete(boo::IAudioVoiceEngine& engine) {
{
if (m_cbInterface) if (m_cbInterface)
m_cbInterface->_onPumpCycleComplete(*this); m_cbInterface->_onPumpCycleComplete(*this);
} }
} } // namespace amuse

View File

@ -3,12 +3,10 @@
using namespace std::literals; using namespace std::literals;
namespace amuse namespace amuse {
{
static logvisor::Module Log("amuse"); static logvisor::Module Log("amuse");
bool Copy(const SystemChar* from, const SystemChar* to) bool Copy(const SystemChar* from, const SystemChar* to) {
{
#if _WIN32 #if _WIN32
return CopyFileW(from, to, FALSE) != 0; return CopyFileW(from, to, FALSE) != 0;
#else #else
@ -16,8 +14,7 @@ bool Copy(const SystemChar* from, const SystemChar* to)
if (!fi) if (!fi)
return false; return false;
FILE* fo = fopen(to, "wb"); FILE* fo = fopen(to, "wb");
if (!fo) if (!fo) {
{
fclose(fi); fclose(fi);
return false; return false;
} }
@ -31,11 +28,11 @@ bool Copy(const SystemChar* from, const SystemChar* to)
if (::stat(from, &theStat)) if (::stat(from, &theStat))
return true; return true;
#if __APPLE__ #if __APPLE__
struct timespec times[] = { theStat.st_atimespec, theStat.st_mtimespec }; struct timespec times[] = {theStat.st_atimespec, theStat.st_mtimespec};
#elif __SWITCH__ #elif __SWITCH__
struct timespec times[] = { theStat.st_atime, theStat.st_mtime }; struct timespec times[] = {theStat.st_atime, theStat.st_mtime};
#else #else
struct timespec times[] = { theStat.st_atim, theStat.st_mtim }; struct timespec times[] = {theStat.st_atim, theStat.st_mtim};
#endif #endif
utimensat(AT_FDCWD, to, times, 0); utimensat(AT_FDCWD, to, times, 0);
return true; return true;
@ -43,73 +40,70 @@ bool Copy(const SystemChar* from, const SystemChar* to)
} }
#define DEFINE_ID_TYPE(type, typeName) \ #define DEFINE_ID_TYPE(type, typeName) \
thread_local NameDB* type::CurNameDB = nullptr; \ thread_local NameDB* type::CurNameDB = nullptr; \
template<> template<> \ template <> \
void type##DNA<athena::Little>::Enumerate<BigDNA::Read>(athena::io::IStreamReader& reader) \ template <> \
{ \ void type##DNA<athena::Little>::Enumerate<BigDNA::Read>(athena::io::IStreamReader & reader) { \
id = reader.readUint16Little(); \ id = reader.readUint16Little(); \
} \ } \
template<> template<> \ template <> \
void type##DNA<athena::Little>::Enumerate<BigDNA::Write>(athena::io::IStreamWriter& writer) \ template <> \
{ \ void type##DNA<athena::Little>::Enumerate<BigDNA::Write>(athena::io::IStreamWriter & writer) { \
writer.writeUint16Little(id); \ writer.writeUint16Little(id); \
} \ } \
template<> template<> \ template <> \
void type##DNA<athena::Little>::Enumerate<BigDNA::BinarySize>(size_t& sz) \ template <> \
{ \ void type##DNA<athena::Little>::Enumerate<BigDNA::BinarySize>(size_t & sz) { \
sz += 2; \ sz += 2; \
} \ } \
template<> template<> \ template <> \
void type##DNA<athena::Little>::Enumerate<BigDNA::ReadYaml>(athena::io::YAMLDocReader& reader) \ template <> \
{ \ void type##DNA<athena::Little>::Enumerate<BigDNA::ReadYaml>(athena::io::YAMLDocReader & reader) { \
_read(reader); \ _read(reader); \
} \ } \
template<> template<> \ template <> \
void type##DNA<athena::Little>::Enumerate<BigDNA::WriteYaml>(athena::io::YAMLDocWriter& writer) \ template <> \
{ \ void type##DNA<athena::Little>::Enumerate<BigDNA::WriteYaml>(athena::io::YAMLDocWriter & writer) { \
_write(writer); \ _write(writer); \
} \ } \
template<> template<> \ template <> \
void type##DNA<athena::Big>::Enumerate<BigDNA::Read>(athena::io::IStreamReader& reader) \ template <> \
{ \ void type##DNA<athena::Big>::Enumerate<BigDNA::Read>(athena::io::IStreamReader & reader) { \
id = reader.readUint16Big(); \ id = reader.readUint16Big(); \
} \ } \
template<> template<> \ template <> \
void type##DNA<athena::Big>::Enumerate<BigDNA::Write>(athena::io::IStreamWriter& writer) \ template <> \
{ \ void type##DNA<athena::Big>::Enumerate<BigDNA::Write>(athena::io::IStreamWriter & writer) { \
writer.writeUint16Big(id); \ writer.writeUint16Big(id); \
} \ } \
template<> template<> \ template <> \
void type##DNA<athena::Big>::Enumerate<BigDNA::BinarySize>(size_t& sz) \ template <> \
{ \ void type##DNA<athena::Big>::Enumerate<BigDNA::BinarySize>(size_t & sz) { \
sz += 2; \ sz += 2; \
} \ } \
template<> template<> \ template <> \
void type##DNA<athena::Big>::Enumerate<BigDNA::ReadYaml>(athena::io::YAMLDocReader& reader) \ template <> \
{ \ void type##DNA<athena::Big>::Enumerate<BigDNA::ReadYaml>(athena::io::YAMLDocReader & reader) { \
_read(reader); \ _read(reader); \
} \ } \
template<> template<> \ template <> \
void type##DNA<athena::Big>::Enumerate<BigDNA::WriteYaml>(athena::io::YAMLDocWriter& writer) \ template <> \
{ \ void type##DNA<athena::Big>::Enumerate<BigDNA::WriteYaml>(athena::io::YAMLDocWriter & writer) { \
_write(writer); \ _write(writer); \
} \ } \
template <athena::Endian DNAE> \ template <athena::Endian DNAE> \
void type##DNA<DNAE>::_read(athena::io::YAMLDocReader& r) \ void type##DNA<DNAE>::_read(athena::io::YAMLDocReader& r) { \
{ \
std::string name = r.readString(nullptr); \ std::string name = r.readString(nullptr); \
if (!type::CurNameDB) \ if (!type::CurNameDB) \
Log.report(logvisor::Fatal, "Unable to resolve " typeName " name %s, no database present", name.c_str()); \ Log.report(logvisor::Fatal, "Unable to resolve " typeName " name %s, no database present", name.c_str()); \
if (name.empty()) \ if (name.empty()) { \
{ \
id.id = 0xffff; \ id.id = 0xffff; \
return; \ return; \
} \ } \
id = type::CurNameDB->resolveIdFromName(name); \ id = type::CurNameDB->resolveIdFromName(name); \
} \ } \
template <athena::Endian DNAE> \ template <athena::Endian DNAE> \
void type##DNA<DNAE>::_write(athena::io::YAMLDocWriter& w) \ void type##DNA<DNAE>::_write(athena::io::YAMLDocWriter& w) { \
{ \
if (!type::CurNameDB) \ if (!type::CurNameDB) \
Log.report(logvisor::Fatal, "Unable to resolve " typeName " ID %d, no database present", id.id); \ Log.report(logvisor::Fatal, "Unable to resolve " typeName " ID %d, no database present", id.id); \
if (id.id == 0xffff) \ if (id.id == 0xffff) \
@ -117,14 +111,13 @@ void type##DNA<DNAE>::_write(athena::io::YAMLDocWriter& w) \
std::string_view name = type::CurNameDB->resolveNameFromId(id); \ std::string_view name = type::CurNameDB->resolveNameFromId(id); \
if (!name.empty()) \ if (!name.empty()) \
w.writeString(nullptr, name); \ w.writeString(nullptr, name); \
} \ } \
template <athena::Endian DNAE> \ template <athena::Endian DNAE> \
const char* type##DNA<DNAE>::DNAType() \ const char* type##DNA<DNAE>::DNAType() { \
{ \
return "amuse::" #type "DNA"; \ return "amuse::" #type "DNA"; \
} \ } \
template struct type##DNA<athena::Big>; \ template struct type##DNA<athena::Big>; \
template struct type##DNA<athena::Little>; template struct type##DNA<athena::Little>;
DEFINE_ID_TYPE(ObjectId, "object") DEFINE_ID_TYPE(ObjectId, "object")
DEFINE_ID_TYPE(SoundMacroId, "SoundMacro") DEFINE_ID_TYPE(SoundMacroId, "SoundMacro")
@ -136,76 +129,71 @@ DEFINE_ID_TYPE(SongId, "song")
DEFINE_ID_TYPE(SFXId, "sfx") DEFINE_ID_TYPE(SFXId, "sfx")
DEFINE_ID_TYPE(GroupId, "group") DEFINE_ID_TYPE(GroupId, "group")
template<> template<> template <>
void PageObjectIdDNA<athena::Little>::Enumerate<BigDNA::Read>(athena::io::IStreamReader& reader) template <>
{ void PageObjectIdDNA<athena::Little>::Enumerate<BigDNA::Read>(athena::io::IStreamReader& reader) {
id = reader.readUint16Little(); id = reader.readUint16Little();
} }
template<> template<> template <>
void PageObjectIdDNA<athena::Little>::Enumerate<BigDNA::Write>(athena::io::IStreamWriter& writer) template <>
{ void PageObjectIdDNA<athena::Little>::Enumerate<BigDNA::Write>(athena::io::IStreamWriter& writer) {
writer.writeUint16Little(id); writer.writeUint16Little(id);
} }
template<> template<> template <>
void PageObjectIdDNA<athena::Little>::Enumerate<BigDNA::BinarySize>(size_t& sz) template <>
{ void PageObjectIdDNA<athena::Little>::Enumerate<BigDNA::BinarySize>(size_t& sz) {
sz += 2; sz += 2;
} }
template<> template<> template <>
void PageObjectIdDNA<athena::Little>::Enumerate<BigDNA::ReadYaml>(athena::io::YAMLDocReader& reader) template <>
{ void PageObjectIdDNA<athena::Little>::Enumerate<BigDNA::ReadYaml>(athena::io::YAMLDocReader& reader) {
_read(reader); _read(reader);
} }
template<> template<> template <>
void PageObjectIdDNA<athena::Little>::Enumerate<BigDNA::WriteYaml>(athena::io::YAMLDocWriter& writer) template <>
{ void PageObjectIdDNA<athena::Little>::Enumerate<BigDNA::WriteYaml>(athena::io::YAMLDocWriter& writer) {
_write(writer); _write(writer);
} }
template<> template<> template <>
void PageObjectIdDNA<athena::Big>::Enumerate<BigDNA::Read>(athena::io::IStreamReader& reader) template <>
{ void PageObjectIdDNA<athena::Big>::Enumerate<BigDNA::Read>(athena::io::IStreamReader& reader) {
id = reader.readUint16Big(); id = reader.readUint16Big();
} }
template<> template<> template <>
void PageObjectIdDNA<athena::Big>::Enumerate<BigDNA::Write>(athena::io::IStreamWriter& writer) template <>
{ void PageObjectIdDNA<athena::Big>::Enumerate<BigDNA::Write>(athena::io::IStreamWriter& writer) {
writer.writeUint16Big(id); writer.writeUint16Big(id);
} }
template<> template<> template <>
void PageObjectIdDNA<athena::Big>::Enumerate<BigDNA::BinarySize>(size_t& sz) template <>
{ void PageObjectIdDNA<athena::Big>::Enumerate<BigDNA::BinarySize>(size_t& sz) {
sz += 2; sz += 2;
} }
template<> template<> template <>
void PageObjectIdDNA<athena::Big>::Enumerate<BigDNA::ReadYaml>(athena::io::YAMLDocReader& reader) template <>
{ void PageObjectIdDNA<athena::Big>::Enumerate<BigDNA::ReadYaml>(athena::io::YAMLDocReader& reader) {
_read(reader); _read(reader);
} }
template<> template<> template <>
void PageObjectIdDNA<athena::Big>::Enumerate<BigDNA::WriteYaml>(athena::io::YAMLDocWriter& writer) template <>
{ void PageObjectIdDNA<athena::Big>::Enumerate<BigDNA::WriteYaml>(athena::io::YAMLDocWriter& writer) {
_write(writer); _write(writer);
} }
template <athena::Endian DNAE> template <athena::Endian DNAE>
void PageObjectIdDNA<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 (!KeymapId::CurNameDB || !LayersId::CurNameDB) if (!KeymapId::CurNameDB || !LayersId::CurNameDB)
Log.report(logvisor::Fatal, "Unable to resolve keymap or layers 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());
if (name.empty()) if (name.empty()) {
{
id.id = 0xffff; id.id = 0xffff;
return; return;
} }
auto search = KeymapId::CurNameDB->m_stringToId.find(name); auto search = KeymapId::CurNameDB->m_stringToId.find(name);
if (search == KeymapId::CurNameDB->m_stringToId.cend()) if (search == KeymapId::CurNameDB->m_stringToId.cend()) {
{
search = LayersId::CurNameDB->m_stringToId.find(name); search = LayersId::CurNameDB->m_stringToId.find(name);
if (search == LayersId::CurNameDB->m_stringToId.cend()) if (search == LayersId::CurNameDB->m_stringToId.cend()) {
{
search = SoundMacroId::CurNameDB->m_stringToId.find(name); search = SoundMacroId::CurNameDB->m_stringToId.find(name);
if (search == SoundMacroId::CurNameDB->m_stringToId.cend()) if (search == SoundMacroId::CurNameDB->m_stringToId.cend()) {
{
Log.report(logvisor::Error, "Unable to resolve name %s", name.c_str()); Log.report(logvisor::Error, "Unable to resolve name %s", name.c_str());
id.id = 0xffff; id.id = 0xffff;
return; return;
@ -215,99 +203,90 @@ void PageObjectIdDNA<DNAE>::_read(athena::io::YAMLDocReader& r)
id = search->second; id = search->second;
} }
template <athena::Endian DNAE> template <athena::Endian DNAE>
void PageObjectIdDNA<DNAE>::_write(athena::io::YAMLDocWriter& w) void PageObjectIdDNA<DNAE>::_write(athena::io::YAMLDocWriter& w) {
{
if (!KeymapId::CurNameDB || !LayersId::CurNameDB) if (!KeymapId::CurNameDB || !LayersId::CurNameDB)
Log.report(logvisor::Fatal, "Unable to resolve keymap or layers ID %d, no database present", id.id); Log.report(logvisor::Fatal, "Unable to resolve keymap or layers ID %d, no database present", id.id);
if (id.id == 0xffff) if (id.id == 0xffff)
return; return;
if (id.id & 0x8000) if (id.id & 0x8000) {
{
std::string_view name = LayersId::CurNameDB->resolveNameFromId(id); std::string_view name = LayersId::CurNameDB->resolveNameFromId(id);
if (!name.empty()) if (!name.empty())
w.writeString(nullptr, name); w.writeString(nullptr, name);
} } else if (id.id & 0x4000) {
else if (id.id & 0x4000)
{
std::string_view name = KeymapId::CurNameDB->resolveNameFromId(id); std::string_view name = KeymapId::CurNameDB->resolveNameFromId(id);
if (!name.empty()) if (!name.empty())
w.writeString(nullptr, name); w.writeString(nullptr, name);
} } else {
else
{
std::string_view name = SoundMacroId::CurNameDB->resolveNameFromId(id); std::string_view name = SoundMacroId::CurNameDB->resolveNameFromId(id);
if (!name.empty()) if (!name.empty())
w.writeString(nullptr, name); w.writeString(nullptr, name);
} }
} }
template <athena::Endian DNAE> template <athena::Endian DNAE>
const char* PageObjectIdDNA<DNAE>::DNAType() const char* PageObjectIdDNA<DNAE>::DNAType() {
{
return "amuse::PageObjectIdDNA"; return "amuse::PageObjectIdDNA";
} }
template struct PageObjectIdDNA<athena::Big>; template struct PageObjectIdDNA<athena::Big>;
template struct PageObjectIdDNA<athena::Little>; template struct PageObjectIdDNA<athena::Little>;
template<> template<> template <>
void SoundMacroStepDNA<athena::Little>::Enumerate<BigDNA::Read>(athena::io::IStreamReader& reader) template <>
{ void SoundMacroStepDNA<athena::Little>::Enumerate<BigDNA::Read>(athena::io::IStreamReader& reader) {
step = reader.readUint16Little(); step = reader.readUint16Little();
} }
template<> template<> template <>
void SoundMacroStepDNA<athena::Little>::Enumerate<BigDNA::Write>(athena::io::IStreamWriter& writer) template <>
{ void SoundMacroStepDNA<athena::Little>::Enumerate<BigDNA::Write>(athena::io::IStreamWriter& writer) {
writer.writeUint16Little(step); writer.writeUint16Little(step);
} }
template<> template<> template <>
void SoundMacroStepDNA<athena::Little>::Enumerate<BigDNA::BinarySize>(size_t& sz) template <>
{ void SoundMacroStepDNA<athena::Little>::Enumerate<BigDNA::BinarySize>(size_t& sz) {
sz += 2; sz += 2;
} }
template<> template<> template <>
void SoundMacroStepDNA<athena::Little>::Enumerate<BigDNA::ReadYaml>(athena::io::YAMLDocReader& reader) template <>
{ void SoundMacroStepDNA<athena::Little>::Enumerate<BigDNA::ReadYaml>(athena::io::YAMLDocReader& reader) {
step = reader.readUint16(nullptr); step = reader.readUint16(nullptr);
} }
template<> template<> template <>
void SoundMacroStepDNA<athena::Little>::Enumerate<BigDNA::WriteYaml>(athena::io::YAMLDocWriter& writer) template <>
{ void SoundMacroStepDNA<athena::Little>::Enumerate<BigDNA::WriteYaml>(athena::io::YAMLDocWriter& writer) {
writer.writeUint16(nullptr, step); writer.writeUint16(nullptr, step);
} }
template<> template<> template <>
void SoundMacroStepDNA<athena::Big>::Enumerate<BigDNA::Read>(athena::io::IStreamReader& reader) template <>
{ void SoundMacroStepDNA<athena::Big>::Enumerate<BigDNA::Read>(athena::io::IStreamReader& reader) {
step = reader.readUint16Big(); step = reader.readUint16Big();
} }
template<> template<> template <>
void SoundMacroStepDNA<athena::Big>::Enumerate<BigDNA::Write>(athena::io::IStreamWriter& writer) template <>
{ void SoundMacroStepDNA<athena::Big>::Enumerate<BigDNA::Write>(athena::io::IStreamWriter& writer) {
writer.writeUint16Big(step); writer.writeUint16Big(step);
} }
template<> template<> template <>
void SoundMacroStepDNA<athena::Big>::Enumerate<BigDNA::BinarySize>(size_t& sz) template <>
{ void SoundMacroStepDNA<athena::Big>::Enumerate<BigDNA::BinarySize>(size_t& sz) {
sz += 2; sz += 2;
} }
template<> template<> template <>
void SoundMacroStepDNA<athena::Big>::Enumerate<BigDNA::ReadYaml>(athena::io::YAMLDocReader& reader) template <>
{ void SoundMacroStepDNA<athena::Big>::Enumerate<BigDNA::ReadYaml>(athena::io::YAMLDocReader& reader) {
step = reader.readUint16(nullptr); step = reader.readUint16(nullptr);
} }
template<> template<> template <>
void SoundMacroStepDNA<athena::Big>::Enumerate<BigDNA::WriteYaml>(athena::io::YAMLDocWriter& writer) template <>
{ void SoundMacroStepDNA<athena::Big>::Enumerate<BigDNA::WriteYaml>(athena::io::YAMLDocWriter& writer) {
writer.writeUint16(nullptr, step); writer.writeUint16(nullptr, step);
} }
template <athena::Endian DNAE> template <athena::Endian DNAE>
const char* SoundMacroStepDNA<DNAE>::DNAType() const char* SoundMacroStepDNA<DNAE>::DNAType() {
{
return "amuse::SoundMacroStepDNA"; return "amuse::SoundMacroStepDNA";
} }
template struct SoundMacroStepDNA<athena::Big>; template struct SoundMacroStepDNA<athena::Big>;
template struct SoundMacroStepDNA<athena::Little>; template struct SoundMacroStepDNA<athena::Little>;
ObjectId NameDB::generateId(Type tp) const ObjectId NameDB::generateId(Type tp) const {
{
uint16_t maxMatch = 0; uint16_t maxMatch = 0;
if (tp == Type::Layer) if (tp == Type::Layer)
maxMatch = 0x8000; maxMatch = 0x8000;
@ -319,11 +298,9 @@ ObjectId NameDB::generateId(Type tp) const
return maxMatch; return maxMatch;
} }
std::string NameDB::generateName(ObjectId id, Type tp) std::string NameDB::generateName(ObjectId id, Type tp) {
{
char name[32]; char name[32];
switch (tp) switch (tp) {
{
case Type::SoundMacro: case Type::SoundMacro:
snprintf(name, 32, "macro%04X", id.id); snprintf(name, 32, "macro%04X", id.id);
break; break;
@ -355,41 +332,32 @@ std::string NameDB::generateName(ObjectId id, Type tp)
return name; return name;
} }
std::string NameDB::generateDefaultName(Type tp) const std::string NameDB::generateDefaultName(Type tp) const { return generateName(generateId(tp), tp); }
{
return generateName(generateId(tp), tp);
}
std::string_view NameDB::registerPair(std::string_view str, ObjectId id) std::string_view NameDB::registerPair(std::string_view str, ObjectId id) {
{
m_stringToId[std::string(str)] = id; m_stringToId[std::string(str)] = id;
return m_idToString.insert(std::make_pair(id, str)).first->second; return m_idToString.insert(std::make_pair(id, str)).first->second;
} }
std::string_view NameDB::resolveNameFromId(ObjectId id) const 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::Error, "Unable to resolve ID 0x%04X", id.id); Log.report(logvisor::Error, "Unable to resolve ID 0x%04X", id.id);
return ""sv; return ""sv;
} }
return search->second; return search->second;
} }
ObjectId NameDB::resolveIdFromName(std::string_view str) const ObjectId NameDB::resolveIdFromName(std::string_view str) const {
{
auto search = m_stringToId.find(std::string(str)); auto search = m_stringToId.find(std::string(str));
if (search == m_stringToId.cend()) if (search == m_stringToId.cend()) {
{
Log.report(logvisor::Error, "Unable to resolve name %s", str.data()); Log.report(logvisor::Error, "Unable to resolve name %s", str.data());
return {}; return {};
} }
return search->second; return search->second;
} }
void NameDB::remove(ObjectId id) void NameDB::remove(ObjectId id) {
{
auto search = m_idToString.find(id); auto search = m_idToString.find(id);
if (search == m_idToString.cend()) if (search == m_idToString.cend())
return; return;
@ -400,8 +368,7 @@ void NameDB::remove(ObjectId id)
m_stringToId.erase(search2); m_stringToId.erase(search2);
} }
void NameDB::rename(ObjectId id, std::string_view str) void NameDB::rename(ObjectId id, std::string_view str) {
{
auto search = m_idToString.find(id); auto search = m_idToString.find(id);
if (search == m_idToString.cend()) if (search == m_idToString.cend())
return; return;
@ -421,11 +388,9 @@ void NameDB::rename(ObjectId id, std::string_view str)
search->second = str; search->second = str;
} }
template<> template <>
void LittleUInt24::Enumerate<LittleDNA::Read>(athena::io::IStreamReader& reader) void LittleUInt24::Enumerate<LittleDNA::Read>(athena::io::IStreamReader& reader) {
{ union {
union
{
atUint32 val; atUint32 val;
char bytes[4]; char bytes[4];
} data = {}; } data = {};
@ -433,11 +398,9 @@ void LittleUInt24::Enumerate<LittleDNA::Read>(athena::io::IStreamReader& reader)
val = SLittle(data.val); val = SLittle(data.val);
} }
template<> template <>
void LittleUInt24::Enumerate<LittleDNA::Write>(athena::io::IStreamWriter& writer) void LittleUInt24::Enumerate<LittleDNA::Write>(athena::io::IStreamWriter& writer) {
{ union {
union
{
atUint32 val; atUint32 val;
char bytes[4]; char bytes[4];
} data; } data;
@ -445,27 +408,21 @@ void LittleUInt24::Enumerate<LittleDNA::Write>(athena::io::IStreamWriter& writer
writer.writeBytes(data.bytes, 3); writer.writeBytes(data.bytes, 3);
} }
template<> template <>
void LittleUInt24::Enumerate<LittleDNA::BinarySize>(size_t& sz) void LittleUInt24::Enumerate<LittleDNA::BinarySize>(size_t& sz) {
{
sz += 3; sz += 3;
} }
template<> template <>
void LittleUInt24::Enumerate<LittleDNA::ReadYaml>(athena::io::YAMLDocReader& reader) void LittleUInt24::Enumerate<LittleDNA::ReadYaml>(athena::io::YAMLDocReader& reader) {
{
val = reader.readUint32(nullptr); val = reader.readUint32(nullptr);
} }
template<> template <>
void LittleUInt24::Enumerate<LittleDNA::WriteYaml>(athena::io::YAMLDocWriter& writer) void LittleUInt24::Enumerate<LittleDNA::WriteYaml>(athena::io::YAMLDocWriter& writer) {
{
writer.writeUint32(nullptr, val); writer.writeUint32(nullptr, val);
} }
const char* LittleUInt24::DNAType() const char* LittleUInt24::DNAType() { return "amuse::LittleUInt24"; }
{
return "amuse::LittleUInt24";
}
} } // namespace amuse

File diff suppressed because it is too large Load Diff

View File

@ -11,28 +11,21 @@
#pragma mark Decoder #pragma mark Decoder
static const int32_t NibbleToInt[16] = {0,1,2,3,4,5,6,7,-8,-7,-6,-5,-4,-3,-2,-1}; static const int32_t NibbleToInt[16] = {0, 1, 2, 3, 4, 5, 6, 7, -8, -7, -6, -5, -4, -3, -2, -1};
unsigned DSPDecompressFrame(int16_t* out, const uint8_t* in, unsigned DSPDecompressFrame(int16_t* out, const uint8_t* in, const int16_t coefs[8][2], int16_t* prev1, int16_t* prev2,
const int16_t coefs[8][2], int16_t* prev1, int16_t* prev2, unsigned lastSample) {
unsigned lastSample) uint8_t cIdx = (in[0] >> 4) & 0xf;
{
uint8_t cIdx = (in[0]>>4) & 0xf;
int32_t factor1 = coefs[cIdx][0]; int32_t factor1 = coefs[cIdx][0];
int32_t factor2 = coefs[cIdx][1]; int32_t factor2 = coefs[cIdx][1];
uint8_t exp = in[0] & 0xf; uint8_t exp = in[0] & 0xf;
unsigned ret = 0; unsigned ret = 0;
for (unsigned s=0 ; s<14 && s<lastSample ; ++s) for (unsigned s = 0; s < 14 && s < lastSample; ++s) {
{ int32_t sampleData = (s & 1) ? NibbleToInt[(in[s / 2 + 1]) & 0xf] : NibbleToInt[(in[s / 2 + 1] >> 4) & 0xf];
int32_t sampleData = (s&1)?
NibbleToInt[(in[s/2+1])&0xf]:
NibbleToInt[(in[s/2+1]>>4)&0xf];
sampleData <<= exp; sampleData <<= exp;
sampleData <<= 11; sampleData <<= 11;
sampleData += 1024; sampleData += 1024;
sampleData += sampleData += factor1 * ((int32_t)(*prev1)) + factor2 * ((int32_t)(*prev2));
factor1 * ((int32_t)(*prev1)) +
factor2 * ((int32_t)(*prev2));
sampleData >>= 11; sampleData >>= 11;
sampleData = DSPSampClamp(sampleData); sampleData = DSPSampClamp(sampleData);
out[s] = sampleData; out[s] = sampleData;
@ -43,29 +36,22 @@ unsigned DSPDecompressFrame(int16_t* out, const uint8_t* in,
return ret; return ret;
} }
unsigned DSPDecompressFrameStereoStride(int16_t* out, const uint8_t* in, unsigned DSPDecompressFrameStereoStride(int16_t* out, const uint8_t* in, const int16_t coefs[8][2], int16_t* prev1,
const int16_t coefs[8][2], int16_t* prev1, int16_t* prev2, int16_t* prev2, unsigned lastSample) {
unsigned lastSample) uint32_t cIdx = (in[0] >> 4) & 0xf;
{
uint32_t cIdx = (in[0]>>4) & 0xf;
int32_t factor1 = coefs[cIdx][0]; int32_t factor1 = coefs[cIdx][0];
int32_t factor2 = coefs[cIdx][1]; int32_t factor2 = coefs[cIdx][1];
uint32_t exp = in[0] & 0xf; uint32_t exp = in[0] & 0xf;
unsigned ret = 0; unsigned ret = 0;
for (unsigned s=0 ; s<14 && s<lastSample ; ++s) for (unsigned s = 0; s < 14 && s < lastSample; ++s) {
{ int32_t sampleData = (s & 1) ? NibbleToInt[(in[s / 2 + 1]) & 0xf] : NibbleToInt[(in[s / 2 + 1] >> 4) & 0xf];
int32_t sampleData = (s&1)?
NibbleToInt[(in[s/2+1])&0xf]:
NibbleToInt[(in[s/2+1]>>4)&0xf];
sampleData <<= exp; sampleData <<= exp;
sampleData <<= 11; sampleData <<= 11;
sampleData += 1024; sampleData += 1024;
sampleData += sampleData += factor1 * ((int32_t)(*prev1)) + factor2 * ((int32_t)(*prev2));
factor1 * ((int32_t)(*prev1)) +
factor2 * ((int32_t)(*prev2));
sampleData >>= 11; sampleData >>= 11;
sampleData = DSPSampClamp(sampleData); sampleData = DSPSampClamp(sampleData);
out[s*2] = sampleData; out[s * 2] = sampleData;
*prev2 = *prev1; *prev2 = *prev1;
*prev1 = sampleData; *prev1 = sampleData;
++ret; ++ret;
@ -73,30 +59,23 @@ unsigned DSPDecompressFrameStereoStride(int16_t* out, const uint8_t* in,
return ret; return ret;
} }
unsigned DSPDecompressFrameStereoDupe(int16_t* out, const uint8_t* in, unsigned DSPDecompressFrameStereoDupe(int16_t* out, const uint8_t* in, const int16_t coefs[8][2], int16_t* prev1,
const int16_t coefs[8][2], int16_t* prev1, int16_t* prev2, int16_t* prev2, unsigned lastSample) {
unsigned lastSample) uint8_t cIdx = (in[0] >> 4) & 0xf;
{
uint8_t cIdx = (in[0]>>4) & 0xf;
int32_t factor1 = coefs[cIdx][0]; int32_t factor1 = coefs[cIdx][0];
int32_t factor2 = coefs[cIdx][1]; int32_t factor2 = coefs[cIdx][1];
uint8_t exp = in[0] & 0xf; uint8_t exp = in[0] & 0xf;
unsigned ret = 0; unsigned ret = 0;
for (unsigned s=0 ; s<14 && s<lastSample ; ++s) for (unsigned s = 0; s < 14 && s < lastSample; ++s) {
{ int32_t sampleData = (s & 1) ? NibbleToInt[(in[s / 2 + 1]) & 0xf] : NibbleToInt[(in[s / 2 + 1] >> 4) & 0xf];
int32_t sampleData = (s&1)?
NibbleToInt[(in[s/2+1])&0xf]:
NibbleToInt[(in[s/2+1]>>4)&0xf];
sampleData <<= exp; sampleData <<= exp;
sampleData <<= 11; sampleData <<= 11;
sampleData += 1024; sampleData += 1024;
sampleData += sampleData += factor1 * ((int32_t)(*prev1)) + factor2 * ((int32_t)(*prev2));
factor1 * ((int32_t)(*prev1)) +
factor2 * ((int32_t)(*prev2));
sampleData >>= 11; sampleData >>= 11;
sampleData = DSPSampClamp(sampleData); sampleData = DSPSampClamp(sampleData);
out[s*2] = sampleData; out[s * 2] = sampleData;
out[s*2+1] = sampleData; out[s * 2 + 1] = sampleData;
*prev2 = *prev1; *prev2 = *prev1;
*prev1 = sampleData; *prev1 = sampleData;
++ret; ++ret;
@ -104,26 +83,19 @@ unsigned DSPDecompressFrameStereoDupe(int16_t* out, const uint8_t* in,
return ret; return ret;
} }
unsigned DSPDecompressFrameRanged(int16_t* out, const uint8_t* in, unsigned DSPDecompressFrameRanged(int16_t* out, const uint8_t* in, const int16_t coefs[8][2], int16_t* prev1,
const int16_t coefs[8][2], int16_t* prev1, int16_t* prev2, int16_t* prev2, unsigned firstSample, unsigned lastSample) {
unsigned firstSample, unsigned lastSample) uint8_t cIdx = (in[0] >> 4) & 0xf;
{
uint8_t cIdx = (in[0]>>4) & 0xf;
int32_t factor1 = coefs[cIdx][0]; int32_t factor1 = coefs[cIdx][0];
int32_t factor2 = coefs[cIdx][1]; int32_t factor2 = coefs[cIdx][1];
uint8_t exp = in[0] & 0xf; uint8_t exp = in[0] & 0xf;
unsigned ret = 0; unsigned ret = 0;
for (unsigned s=firstSample ; s<14 && s<lastSample ; ++s) for (unsigned s = firstSample; s < 14 && s < lastSample; ++s) {
{ int32_t sampleData = (s & 1) ? NibbleToInt[(in[s / 2 + 1]) & 0xf] : NibbleToInt[(in[s / 2 + 1] >> 4) & 0xf];
int32_t sampleData = (s&1)?
NibbleToInt[(in[s/2+1])&0xf]:
NibbleToInt[(in[s/2+1]>>4)&0xf];
sampleData <<= exp; sampleData <<= exp;
sampleData <<= 11; sampleData <<= 11;
sampleData += 1024; sampleData += 1024;
sampleData += sampleData += factor1 * ((int32_t)(*prev1)) + factor2 * ((int32_t)(*prev2));
factor1 * ((int32_t)(*prev1)) +
factor2 * ((int32_t)(*prev2));
sampleData >>= 11; sampleData >>= 11;
sampleData = DSPSampClamp(sampleData); sampleData = DSPSampClamp(sampleData);
*out++ = sampleData; *out++ = sampleData;
@ -134,26 +106,19 @@ unsigned DSPDecompressFrameRanged(int16_t* out, const uint8_t* in,
return ret; return ret;
} }
unsigned DSPDecompressFrameStateOnly(const uint8_t* in, unsigned DSPDecompressFrameStateOnly(const uint8_t* in, const int16_t coefs[8][2], int16_t* prev1, int16_t* prev2,
const int16_t coefs[8][2], int16_t* prev1, int16_t* prev2, unsigned lastSample) {
unsigned lastSample) uint8_t cIdx = (in[0] >> 4) & 0xf;
{
uint8_t cIdx = (in[0]>>4) & 0xf;
int32_t factor1 = coefs[cIdx][0]; int32_t factor1 = coefs[cIdx][0];
int32_t factor2 = coefs[cIdx][1]; int32_t factor2 = coefs[cIdx][1];
uint8_t exp = in[0] & 0xf; uint8_t exp = in[0] & 0xf;
unsigned ret = 0; unsigned ret = 0;
for (unsigned s=0 ; s<14 && s<lastSample ; ++s) for (unsigned s = 0; s < 14 && s < lastSample; ++s) {
{ int32_t sampleData = (s & 1) ? NibbleToInt[(in[s / 2 + 1]) & 0xf] : NibbleToInt[(in[s / 2 + 1] >> 4) & 0xf];
int32_t sampleData = (s&1)?
NibbleToInt[(in[s/2+1])&0xf]:
NibbleToInt[(in[s/2+1]>>4)&0xf];
sampleData <<= exp; sampleData <<= exp;
sampleData <<= 11; sampleData <<= 11;
sampleData += 1024; sampleData += 1024;
sampleData += sampleData += factor1 * ((int32_t)(*prev1)) + factor2 * ((int32_t)(*prev2));
factor1 * ((int32_t)(*prev1)) +
factor2 * ((int32_t)(*prev2));
sampleData >>= 11; sampleData >>= 11;
sampleData = DSPSampClamp(sampleData); sampleData = DSPSampClamp(sampleData);
*prev2 = *prev1; *prev2 = *prev1;
@ -163,26 +128,19 @@ unsigned DSPDecompressFrameStateOnly(const uint8_t* in,
return ret; return ret;
} }
unsigned DSPDecompressFrameRangedStateOnly(const uint8_t* in, unsigned DSPDecompressFrameRangedStateOnly(const uint8_t* in, const int16_t coefs[8][2], int16_t* prev1, int16_t* prev2,
const int16_t coefs[8][2], int16_t* prev1, int16_t* prev2, unsigned firstSample, unsigned lastSample) {
unsigned firstSample, unsigned lastSample) uint8_t cIdx = (in[0] >> 4) & 0xf;
{
uint8_t cIdx = (in[0]>>4) & 0xf;
int32_t factor1 = coefs[cIdx][0]; int32_t factor1 = coefs[cIdx][0];
int32_t factor2 = coefs[cIdx][1]; int32_t factor2 = coefs[cIdx][1];
uint8_t exp = in[0] & 0xf; uint8_t exp = in[0] & 0xf;
unsigned ret = 0; unsigned ret = 0;
for (unsigned s=firstSample ; s<14 && s<lastSample ; ++s) for (unsigned s = firstSample; s < 14 && s < lastSample; ++s) {
{ int32_t sampleData = (s & 1) ? NibbleToInt[(in[s / 2 + 1]) & 0xf] : NibbleToInt[(in[s / 2 + 1] >> 4) & 0xf];
int32_t sampleData = (s&1)?
NibbleToInt[(in[s/2+1])&0xf]:
NibbleToInt[(in[s/2+1]>>4)&0xf];
sampleData <<= exp; sampleData <<= exp;
sampleData <<= 11; sampleData <<= 11;
sampleData += 1024; sampleData += 1024;
sampleData += sampleData += factor1 * ((int32_t)(*prev1)) + factor2 * ((int32_t)(*prev2));
factor1 * ((int32_t)(*prev1)) +
factor2 * ((int32_t)(*prev2));
sampleData >>= 11; sampleData >>= 11;
sampleData = DSPSampClamp(sampleData); sampleData = DSPSampClamp(sampleData);
*prev2 = *prev1; *prev2 = *prev1;
@ -204,35 +162,29 @@ unsigned DSPDecompressFrameRangedStateOnly(const uint8_t* in,
*/ */
typedef double tvec[3]; typedef double tvec[3];
static inline void InnerProductMerge(tvec vecOut, short pcmBuf[14]) static inline void InnerProductMerge(tvec vecOut, short pcmBuf[14]) {
{ for (int i = 0; i <= 2; i++) {
for (int i=0 ; i<=2 ; i++)
{
vecOut[i] = 0.0f; vecOut[i] = 0.0f;
for (int x=0 ; x<14 ; x++) for (int x = 0; x < 14; x++)
vecOut[i] -= pcmBuf[x-i] * pcmBuf[x]; vecOut[i] -= pcmBuf[x - i] * pcmBuf[x];
} }
} }
static inline void OuterProductMerge(tvec mtxOut[3], short pcmBuf[14]) static inline void OuterProductMerge(tvec mtxOut[3], short pcmBuf[14]) {
{ for (int x = 1; x <= 2; x++)
for (int x=1 ; x<=2 ; x++) for (int y = 1; y <= 2; y++) {
for (int y=1 ; y<=2 ; y++)
{
mtxOut[x][y] = 0.0; mtxOut[x][y] = 0.0;
for (int z=0 ; z<14 ; z++) for (int z = 0; z < 14; z++)
mtxOut[x][y] += pcmBuf[z-x] * pcmBuf[z-y]; mtxOut[x][y] += pcmBuf[z - x] * pcmBuf[z - y];
} }
} }
static bool AnalyzeRanges(tvec mtx[3], int* vecIdxsOut) static bool AnalyzeRanges(tvec mtx[3], int* vecIdxsOut) {
{
double recips[3]; double recips[3];
double val, tmp, min, max; double val, tmp, min, max;
/* Get greatest distance from zero */ /* Get greatest distance from zero */
for (int x=1 ; x<=2 ; x++) for (int x = 1; x <= 2; x++) {
{
val = std::max(fabs(mtx[x][1]), fabs(mtx[x][2])); val = std::max(fabs(mtx[x][1]), fabs(mtx[x][2]));
if (val < DBL_EPSILON) if (val < DBL_EPSILON)
return true; return true;
@ -241,36 +193,30 @@ static bool AnalyzeRanges(tvec mtx[3], int* vecIdxsOut)
} }
int maxIndex = 0; int maxIndex = 0;
for (int i=1 ; i<=2 ; i++) for (int i = 1; i <= 2; i++) {
{ for (int x = 1; x < i; x++) {
for (int x=1 ; x<i ; x++)
{
tmp = mtx[x][i]; tmp = mtx[x][i];
for (int y=1 ; y<x ; y++) for (int y = 1; y < x; y++)
tmp -= mtx[x][y] * mtx[y][i]; tmp -= mtx[x][y] * mtx[y][i];
mtx[x][i] = tmp; mtx[x][i] = tmp;
} }
val = 0.0; val = 0.0;
for (int x=i ; x<=2 ; x++) for (int x = i; x <= 2; x++) {
{
tmp = mtx[x][i]; tmp = mtx[x][i];
for (int y=1 ; y<i ; y++) for (int y = 1; y < i; y++)
tmp -= mtx[x][y] * mtx[y][i]; tmp -= mtx[x][y] * mtx[y][i];
mtx[x][i] = tmp; mtx[x][i] = tmp;
tmp = fabs(tmp) * recips[x]; tmp = fabs(tmp) * recips[x];
if (tmp >= val) if (tmp >= val) {
{
val = tmp; val = tmp;
maxIndex = x; maxIndex = x;
} }
} }
if (maxIndex != i) if (maxIndex != i) {
{ for (int y = 1; y <= 2; y++) {
for (int y=1 ; y<=2 ; y++)
{
tmp = mtx[maxIndex][y]; tmp = mtx[maxIndex][y];
mtx[maxIndex][y] = mtx[i][y]; mtx[maxIndex][y] = mtx[i][y];
mtx[i][y] = tmp; mtx[i][y] = tmp;
@ -283,10 +229,9 @@ static bool AnalyzeRanges(tvec mtx[3], int* vecIdxsOut)
if (mtx[i][i] == 0.0) if (mtx[i][i] == 0.0)
return true; return true;
if (i != 2) if (i != 2) {
{
tmp = 1.0 / mtx[i][i]; tmp = 1.0 / mtx[i][i];
for (int x=i+1 ; x<=2 ; x++) for (int x = i + 1; x <= 2; x++)
mtx[x][i] *= tmp; mtx[x][i] *= tmp;
} }
} }
@ -294,8 +239,7 @@ static bool AnalyzeRanges(tvec mtx[3], int* vecIdxsOut)
/* Get range */ /* Get range */
min = 1.0e10; min = 1.0e10;
max = 0.0; max = 0.0;
for (int i=1 ; i<=2 ; i++) for (int i = 1; i <= 2; i++) {
{
tmp = fabs(mtx[i][i]); tmp = fabs(mtx[i][i]);
if (tmp < min) if (tmp < min)
min = tmp; min = tmp;
@ -309,27 +253,24 @@ static bool AnalyzeRanges(tvec mtx[3], int* vecIdxsOut)
return false; return false;
} }
static void BidirectionalFilter(tvec mtx[3], int* vecIdxs, tvec vecOut) static void BidirectionalFilter(tvec mtx[3], int* vecIdxs, tvec vecOut) {
{
double tmp; double tmp;
for (int i=1, x=0 ; i<=2 ; i++) for (int i = 1, x = 0; i <= 2; i++) {
{
int index = vecIdxs[i]; int index = vecIdxs[i];
tmp = vecOut[index]; tmp = vecOut[index];
vecOut[index] = vecOut[i]; vecOut[index] = vecOut[i];
if (x != 0) if (x != 0)
for (int y=x ; y<=i-1 ; y++) for (int y = x; y <= i - 1; y++)
tmp -= vecOut[y] * mtx[i][y]; tmp -= vecOut[y] * mtx[i][y];
else if (tmp != 0.0) else if (tmp != 0.0)
x = i; x = i;
vecOut[i] = tmp; vecOut[i] = tmp;
} }
for (int i=2 ; i>0 ; i--) for (int i = 2; i > 0; i--) {
{
tmp = vecOut[i]; tmp = vecOut[i];
for (int y=i+1 ; y<=2 ; y++) for (int y = i + 1; y <= 2; y++)
tmp -= vecOut[y] * mtx[i][y]; tmp -= vecOut[y] * mtx[i][y];
vecOut[i] = tmp / mtx[i][i]; vecOut[i] = tmp / mtx[i][i];
} }
@ -337,8 +278,7 @@ static void BidirectionalFilter(tvec mtx[3], int* vecIdxs, tvec vecOut)
vecOut[0] = 1.0; vecOut[0] = 1.0;
} }
static bool QuadraticMerge(tvec inOutVec) static bool QuadraticMerge(tvec inOutVec) {
{
double v0, v1, v2 = inOutVec[2]; double v0, v1, v2 = inOutVec[2];
double tmp = 1.0 - (v2 * v2); double tmp = 1.0 - (v2 * v2);
@ -354,10 +294,8 @@ static bool QuadraticMerge(tvec inOutVec)
return fabs(v1) > 1.0; return fabs(v1) > 1.0;
} }
static void FinishRecord(tvec in, tvec out) static void FinishRecord(tvec in, tvec out) {
{ for (int z = 1; z <= 2; z++) {
for (int z=1 ; z<=2 ; z++)
{
if (in[z] >= 1.0) if (in[z] >= 1.0)
in[z] = 0.9999999999; in[z] = 0.9999999999;
else if (in[z] <= -1.0) else if (in[z] <= -1.0)
@ -368,41 +306,36 @@ static void FinishRecord(tvec in, tvec out)
out[2] = in[2]; out[2] = in[2];
} }
static void MatrixFilter(tvec src, tvec dst) static void MatrixFilter(tvec src, tvec dst) {
{
tvec mtx[3]; tvec mtx[3];
mtx[2][0] = 1.0; mtx[2][0] = 1.0;
for (int i=1 ; i<=2 ; i++) for (int i = 1; i <= 2; i++)
mtx[2][i] = -src[i]; mtx[2][i] = -src[i];
for (int i=2 ; i>0 ; i--) for (int i = 2; i > 0; i--) {
{
double val = 1.0 - (mtx[i][i] * mtx[i][i]); double val = 1.0 - (mtx[i][i] * mtx[i][i]);
for (int y = 1; y <= i; y++) for (int y = 1; y <= i; y++)
mtx[i-1][y] = ((mtx[i][i] * mtx[i][y]) + mtx[i][y]) / val; mtx[i - 1][y] = ((mtx[i][i] * mtx[i][y]) + mtx[i][y]) / val;
} }
dst[0] = 1.0; dst[0] = 1.0;
for (int i=1 ; i<=2 ; i++) for (int i = 1; i <= 2; i++) {
{
dst[i] = 0.0; dst[i] = 0.0;
for (int y=1 ; y<=i ; y++) for (int y = 1; y <= i; y++)
dst[i] += mtx[i][y] * dst[i-y]; dst[i] += mtx[i][y] * dst[i - y];
} }
} }
static void MergeFinishRecord(tvec src, tvec dst) static void MergeFinishRecord(tvec src, tvec dst) {
{
tvec tmp; tvec tmp;
double val = src[0]; double val = src[0];
dst[0] = 1.0; dst[0] = 1.0;
for (int i=1 ; i<=2 ; i++) for (int i = 1; i <= 2; i++) {
{
double v2 = 0.0; double v2 = 0.0;
for (int y=1 ; y<i ; y++) for (int y = 1; y < i; y++)
v2 += dst[y] * src[i-y]; v2 += dst[y] * src[i - y];
if (val > 0.0) if (val > 0.0)
dst[i] = -(v2 + src[i]) / val; dst[i] = -(v2 + src[i]) / val;
@ -411,7 +344,7 @@ static void MergeFinishRecord(tvec src, tvec dst)
tmp[i] = dst[i]; tmp[i] = dst[i];
for (int y=1 ; y<i ; y++) for (int y = 1; y < i; y++)
dst[y] += dst[i] * dst[i - y]; dst[y] += dst[i] * dst[i - y];
val *= 1.0 - (dst[i] * dst[i]); val *= 1.0 - (dst[i] * dst[i]);
@ -420,8 +353,7 @@ static void MergeFinishRecord(tvec src, tvec dst)
FinishRecord(tmp, dst); FinishRecord(tmp, dst);
} }
static double ContrastVectors(tvec source1, tvec source2) static double ContrastVectors(tvec source1, tvec source2) {
{
double val = (-source2[2] * -source2[1] + -source2[1]) / (1.0 - source2[2] * source2[2]); double val = (-source2[2] * -source2[1] + -source2[1]) / (1.0 - source2[2] * source2[2]);
double val1 = (source1[0] * source1[0]) + (source1[1] * source1[1]) + (source1[2] * source1[2]); double val1 = (source1[0] * source1[0]) + (source1[1] * source1[1]) + (source1[2] * source1[2]);
double val2 = (source1[0] * source1[1]) + (source1[1] * source1[2]); double val2 = (source1[0] * source1[1]) + (source1[1] * source1[2]);
@ -429,8 +361,7 @@ static double ContrastVectors(tvec source1, tvec source2)
return val1 + (2.0 * val * val2) + (2.0 * (-source2[1] * val + -source2[2]) * val3); return val1 + (2.0 * val * val2) + (2.0 * (-source2[1] * val + -source2[2]) * val3);
} }
static void FilterRecords(tvec vecBest[8], int exp, tvec records[], int recordCount) static void FilterRecords(tvec vecBest[8], int exp, tvec records[], int recordCount) {
{
tvec bufferList[8]; tvec bufferList[8];
int buffer1[8]; int buffer1[8];
@ -439,45 +370,39 @@ static void FilterRecords(tvec vecBest[8], int exp, tvec records[], int recordCo
int index; int index;
double value, tempVal = 0; double value, tempVal = 0;
for (int x=0 ; x<2 ; x++) for (int x = 0; x < 2; x++) {
{ for (int y = 0; y < exp; y++) {
for (int y=0 ; y<exp ; y++)
{
buffer1[y] = 0; buffer1[y] = 0;
for (int i=0 ; i<=2 ; i++) for (int i = 0; i <= 2; i++)
bufferList[y][i] = 0.0; bufferList[y][i] = 0.0;
} }
for (int z=0 ; z<recordCount ; z++) for (int z = 0; z < recordCount; z++) {
{
index = 0; index = 0;
value= 1.0e30; value = 1.0e30;
for (int i=0 ; i<exp ; i++) for (int i = 0; i < exp; i++) {
{
tempVal = ContrastVectors(vecBest[i], records[z]); tempVal = ContrastVectors(vecBest[i], records[z]);
if (tempVal < value) if (tempVal < value) {
{
value = tempVal; value = tempVal;
index = i; index = i;
} }
} }
buffer1[index]++; buffer1[index]++;
MatrixFilter(records[z], buffer2); MatrixFilter(records[z], buffer2);
for (int i=0 ; i<=2 ; i++) for (int i = 0; i <= 2; i++)
bufferList[index][i] += buffer2[i]; bufferList[index][i] += buffer2[i];
} }
for (int i=0 ; i<exp ; i++) for (int i = 0; i < exp; i++)
if (buffer1[i] > 0) if (buffer1[i] > 0)
for (int y=0 ; y<=2 ; y++) for (int y = 0; y <= 2; y++)
bufferList[i][y] /= buffer1[i]; bufferList[i][y] /= buffer1[i];
for (int i=0 ; i<exp ; i++) for (int i = 0; i < exp; i++)
MergeFinishRecord(bufferList[i], vecBest[i]); MergeFinishRecord(bufferList[i], vecBest[i]);
} }
} }
void DSPCorrelateCoefs(const short* source, int samples, short coefsOut[8][2]) void DSPCorrelateCoefs(const short* source, int samples, short coefsOut[8][2]) {
{
int numFrames = (samples + 13) / 14; int numFrames = (samples + 13) / 14;
int frameSamples; int frameSamples;
@ -496,19 +421,17 @@ void DSPCorrelateCoefs(const short* source, int samples, short coefsOut[8][2])
tvec vecBest[8]; tvec vecBest[8];
/* Iterate though 1024-block frames */ /* Iterate though 1024-block frames */
for (int x=samples ; x>0 ;) for (int x = samples; x > 0;) {
{
if (x > 0x3800) /* Full 1024-block frame */ if (x > 0x3800) /* Full 1024-block frame */
{ {
frameSamples = 0x3800; frameSamples = 0x3800;
x -= 0x3800; x -= 0x3800;
} } else /* Partial frame */
else /* Partial frame */
{ {
/* Zero lingering block samples */ /* Zero lingering block samples */
frameSamples = x; frameSamples = x;
for (int z=0 ; z<14 && z+frameSamples<0x3800 ; z++) for (int z = 0; z < 14 && z + frameSamples < 0x3800; z++)
blockBuffer[frameSamples+z] = 0; blockBuffer[frameSamples + z] = 0;
x = 0; x = 0;
} }
@ -516,23 +439,18 @@ void DSPCorrelateCoefs(const short* source, int samples, short coefsOut[8][2])
memcpy(blockBuffer, source, frameSamples * sizeof(short)); memcpy(blockBuffer, source, frameSamples * sizeof(short));
source += frameSamples; source += frameSamples;
for (int i = 0; i < frameSamples;) {
for (int i=0 ; i<frameSamples ;) for (int z = 0; z < 14; z++)
{
for (int z=0 ; z<14 ; z++)
pcmHistBuffer[0][z] = pcmHistBuffer[1][z]; pcmHistBuffer[0][z] = pcmHistBuffer[1][z];
for (int z=0 ; z<14 ; z++) for (int z = 0; z < 14; z++)
pcmHistBuffer[1][z] = blockBuffer[i++]; pcmHistBuffer[1][z] = blockBuffer[i++];
InnerProductMerge(vec1, pcmHistBuffer[1]); InnerProductMerge(vec1, pcmHistBuffer[1]);
if (fabs(vec1[0]) > 10.0) if (fabs(vec1[0]) > 10.0) {
{
OuterProductMerge(mtx, pcmHistBuffer[1]); OuterProductMerge(mtx, pcmHistBuffer[1]);
if (!AnalyzeRanges(mtx, vecIdxs)) if (!AnalyzeRanges(mtx, vecIdxs)) {
{
BidirectionalFilter(mtx, vecIdxs, vec1); BidirectionalFilter(mtx, vecIdxs, vec1);
if (!QuadraticMerge(vec1)) if (!QuadraticMerge(vec1)) {
{
FinishRecord(vec1, records[recordCount]); FinishRecord(vec1, records[recordCount]);
recordCount++; recordCount++;
} }
@ -545,35 +463,31 @@ void DSPCorrelateCoefs(const short* source, int samples, short coefsOut[8][2])
vec1[1] = 0.0; vec1[1] = 0.0;
vec1[2] = 0.0; vec1[2] = 0.0;
for (int z=0 ; z<recordCount ; z++) for (int z = 0; z < recordCount; z++) {
{
MatrixFilter(records[z], vecBest[0]); MatrixFilter(records[z], vecBest[0]);
for (int y=1 ; y<=2 ; y++) for (int y = 1; y <= 2; y++)
vec1[y] += vecBest[0][y]; vec1[y] += vecBest[0][y];
} }
for (int y=1 ; y<=2 ; y++) for (int y = 1; y <= 2; y++)
vec1[y] /= recordCount; vec1[y] /= recordCount;
MergeFinishRecord(vec1, vecBest[0]); MergeFinishRecord(vec1, vecBest[0]);
int exp = 1; int exp = 1;
for (int w=0 ; w<3 ;) for (int w = 0; w < 3;) {
{
vec2[0] = 0.0; vec2[0] = 0.0;
vec2[1] = -1.0; vec2[1] = -1.0;
vec2[2] = 0.0; vec2[2] = 0.0;
for (int i=0 ; i<exp ; i++) for (int i = 0; i < exp; i++)
for (int y=0 ; y<=2 ; y++) for (int y = 0; y <= 2; y++)
vecBest[exp+i][y] = (0.01 * vec2[y]) + vecBest[i][y]; vecBest[exp + i][y] = (0.01 * vec2[y]) + vecBest[i][y];
++w; ++w;
exp = 1 << w; exp = 1 << w;
FilterRecords(vecBest, exp, records, recordCount); FilterRecords(vecBest, exp, records, recordCount);
} }
/* Write output */ /* Write output */
for (int z=0 ; z<8 ; z++) for (int z = 0; z < 8; z++) {
{
double d; double d;
d = -vecBest[z][1] * 2048.0; d = -vecBest[z][1] * 2048.0;
if (d > 0.0) if (d > 0.0)
@ -591,12 +505,10 @@ void DSPCorrelateCoefs(const short* source, int samples, short coefsOut[8][2])
/* Free memory */ /* Free memory */
free(records); free(records);
free(blockBuffer); free(blockBuffer);
} }
/* Make sure source includes the yn values (16 samples total) */ /* Make sure source includes the yn values (16 samples total) */
void DSPEncodeFrame(short pcmInOut[16], int sampleCount, unsigned char adpcmOut[8], const short coefsIn[8][2]) void DSPEncodeFrame(short pcmInOut[16], int sampleCount, unsigned char adpcmOut[8], const short coefsIn[8][2]) {
{
int inSamples[8][16]; int inSamples[8][16];
int outSamples[8][14]; int outSamples[8][14];
@ -606,8 +518,7 @@ void DSPEncodeFrame(short pcmInOut[16], int sampleCount, unsigned char adpcmOut[
double distAccum[8]; double distAccum[8];
/* Iterate through each coef set, finding the set with the smallest error */ /* Iterate through each coef set, finding the set with the smallest error */
for (int i=0 ; i<8 ; i++) for (int i = 0; i < 8; i++) {
{
int v1, v2, v3; int v1, v2, v3;
int distance, index; int distance, index;
@ -617,8 +528,7 @@ void DSPEncodeFrame(short pcmInOut[16], int sampleCount, unsigned char adpcmOut[
/* Round and clamp samples for this coef set */ /* Round and clamp samples for this coef set */
distance = 0; distance = 0;
for (int s=0 ; s<sampleCount ; s++) for (int s = 0; s < sampleCount; s++) {
{
/* Multiply previous samples by coefs */ /* Multiply previous samples by coefs */
inSamples[i][s + 2] = v1 = ((pcmInOut[s] * coefsIn[i][1]) + (pcmInOut[s + 1] * coefsIn[i][0])) / 2048; inSamples[i][s + 2] = v1 = ((pcmInOut[s] * coefsIn[i][1]) + (pcmInOut[s + 1] * coefsIn[i][0])) / 2048;
/* Subtract from current sample */ /* Subtract from current sample */
@ -631,33 +541,29 @@ void DSPEncodeFrame(short pcmInOut[16], int sampleCount, unsigned char adpcmOut[
} }
/* Set initial scale */ /* Set initial scale */
for (scale[i]=0; (scale[i]<=12) && ((distance>7) || (distance<-8)); scale[i]++, distance/=2) {} for (scale[i] = 0; (scale[i] <= 12) && ((distance > 7) || (distance < -8)); scale[i]++, distance /= 2) {}
scale[i] = (scale[i] <= 1) ? -1 : scale[i] - 2; scale[i] = (scale[i] <= 1) ? -1 : scale[i] - 2;
do do {
{
scale[i]++; scale[i]++;
distAccum[i] = 0; distAccum[i] = 0;
index = 0; index = 0;
for (int s=0 ; s<sampleCount ; s++) for (int s = 0; s < sampleCount; s++) {
{
/* Multiply previous */ /* Multiply previous */
v1 = ((inSamples[i][s] * coefsIn[i][1]) + (inSamples[i][s + 1] * coefsIn[i][0])); v1 = ((inSamples[i][s] * coefsIn[i][1]) + (inSamples[i][s + 1] * coefsIn[i][0]));
/* Evaluate from real sample */ /* Evaluate from real sample */
v2 = ((pcmInOut[s + 2] << 11) - v1) / 2048; v2 = ((pcmInOut[s + 2] << 11) - v1) / 2048;
/* Round to nearest sample */ /* Round to nearest sample */
v3 = (v2 > 0) ? (int)((double)v2 / (1 << scale[i]) + 0.4999999f) : (int)((double)v2 / (1 << scale[i]) - 0.4999999f); v3 = (v2 > 0) ? (int)((double)v2 / (1 << scale[i]) + 0.4999999f)
: (int)((double)v2 / (1 << scale[i]) - 0.4999999f);
/* Clamp sample and set index */ /* Clamp sample and set index */
if (v3 < -8) if (v3 < -8) {
{
if (index < (v3 = -8 - v3)) if (index < (v3 = -8 - v3))
index = v3; index = v3;
v3 = -8; v3 = -8;
} } else if (v3 > 7) {
else if (v3 > 7)
{
if (index < (v3 -= 7)) if (index < (v3 -= 7))
index = v3; index = v3;
v3 = 7; v3 = 7;
@ -675,7 +581,7 @@ void DSPEncodeFrame(short pcmInOut[16], int sampleCount, unsigned char adpcmOut[
distAccum[i] += v3 * (double)v3; distAccum[i] += v3 * (double)v3;
} }
for (int x=index+8 ; x>256 ; x>>=1) for (int x = index + 8; x > 256; x >>= 1)
if (++scale[i] >= 12) if (++scale[i] >= 12)
scale[i] = 11; scale[i] = 11;
@ -683,29 +589,26 @@ void DSPEncodeFrame(short pcmInOut[16], int sampleCount, unsigned char adpcmOut[
} }
double min = DBL_MAX; double min = DBL_MAX;
for (int i = 0; i < 8; i++) for (int i = 0; i < 8; i++) {
{ if (distAccum[i] < min) {
if (distAccum[i] < min)
{
min = distAccum[i]; min = distAccum[i];
bestIndex = i; bestIndex = i;
} }
} }
/* Write converted samples */ /* Write converted samples */
for (int s=0 ; s<sampleCount ; s++) for (int s = 0; s < sampleCount; s++)
pcmInOut[s + 2] = inSamples[bestIndex][s + 2]; pcmInOut[s + 2] = inSamples[bestIndex][s + 2];
/* Write ps */ /* Write ps */
adpcmOut[0] = (char)((bestIndex << 4) | (scale[bestIndex] & 0xF)); adpcmOut[0] = (char)((bestIndex << 4) | (scale[bestIndex] & 0xF));
/* Zero remaining samples */ /* Zero remaining samples */
for (int s=sampleCount ; s<14 ; s++) for (int s = sampleCount; s < 14; s++)
outSamples[bestIndex][s] = 0; outSamples[bestIndex][s] = 0;
/* Write output samples */ /* Write output samples */
for (int y=0; y<7; y++) for (int y = 0; y < 7; y++) {
{
adpcmOut[y + 1] = (char)((outSamples[bestIndex][y * 2] << 4) | (outSamples[bestIndex][y * 2 + 1] & 0xF)); adpcmOut[y + 1] = (char)((outSamples[bestIndex][y * 2] << 4) | (outSamples[bestIndex][y * 2 + 1] & 0xF));
} }
} }

View File

@ -19,11 +19,9 @@
#include "amuse/DirectoryEnumerator.hpp" #include "amuse/DirectoryEnumerator.hpp"
namespace amuse namespace amuse {
{
DirectoryEnumerator::DirectoryEnumerator(SystemStringView path, Mode mode, bool sizeSort, bool reverse, bool noHidden) DirectoryEnumerator::DirectoryEnumerator(SystemStringView path, Mode mode, bool sizeSort, bool reverse, bool noHidden) {
{
Sstat theStat; Sstat theStat;
if (Stat(path.data(), &theStat) || !S_ISDIR(theStat.st_mode)) if (Stat(path.data(), &theStat) || !S_ISDIR(theStat.st_mode))
return; return;
@ -35,11 +33,9 @@ DirectoryEnumerator::DirectoryEnumerator(SystemStringView path, Mode mode, bool
HANDLE dir = FindFirstFileW(wc.c_str(), &d); HANDLE dir = FindFirstFileW(wc.c_str(), &d);
if (dir == INVALID_HANDLE_VALUE) if (dir == INVALID_HANDLE_VALUE)
return; return;
switch (mode) switch (mode) {
{
case Mode::Native: case Mode::Native:
do do {
{
if (!wcscmp(d.cFileName, _SYS_STR(".")) || !wcscmp(d.cFileName, _SYS_STR(".."))) if (!wcscmp(d.cFileName, _SYS_STR(".")) || !wcscmp(d.cFileName, _SYS_STR("..")))
continue; continue;
if (noHidden && (d.cFileName[0] == L'.' || (d.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) != 0)) if (noHidden && (d.cFileName[0] == L'.' || (d.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) != 0))
@ -64,11 +60,9 @@ DirectoryEnumerator::DirectoryEnumerator(SystemStringView path, Mode mode, bool
} while (FindNextFileW(dir, &d)); } while (FindNextFileW(dir, &d));
break; break;
case Mode::DirsThenFilesSorted: case Mode::DirsThenFilesSorted:
case Mode::DirsSorted: case Mode::DirsSorted: {
{
std::map<SystemString, Entry, CaseInsensitiveCompare> sort; std::map<SystemString, Entry, CaseInsensitiveCompare> sort;
do do {
{
if (!wcscmp(d.cFileName, _SYS_STR(".")) || !wcscmp(d.cFileName, _SYS_STR(".."))) if (!wcscmp(d.cFileName, _SYS_STR(".")) || !wcscmp(d.cFileName, _SYS_STR("..")))
continue; continue;
if (noHidden && (d.cFileName[0] == L'.' || (d.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) != 0)) if (noHidden && (d.cFileName[0] == L'.' || (d.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) != 0))
@ -95,16 +89,13 @@ DirectoryEnumerator::DirectoryEnumerator(SystemStringView path, Mode mode, bool
FindClose(dir); FindClose(dir);
dir = FindFirstFileW(wc.c_str(), &d); dir = FindFirstFileW(wc.c_str(), &d);
} }
case Mode::FilesSorted: case Mode::FilesSorted: {
{
if (mode == Mode::FilesSorted) if (mode == Mode::FilesSorted)
m_entries.clear(); m_entries.clear();
if (sizeSort) if (sizeSort) {
{
std::multimap<size_t, Entry> sort; std::multimap<size_t, Entry> sort;
do do {
{
if (!wcscmp(d.cFileName, _SYS_STR(".")) || !wcscmp(d.cFileName, _SYS_STR(".."))) if (!wcscmp(d.cFileName, _SYS_STR(".")) || !wcscmp(d.cFileName, _SYS_STR("..")))
continue; continue;
if (noHidden && (d.cFileName[0] == L'.' || (d.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) != 0)) if (noHidden && (d.cFileName[0] == L'.' || (d.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) != 0))
@ -125,12 +116,9 @@ DirectoryEnumerator::DirectoryEnumerator(SystemStringView path, Mode mode, bool
else else
for (auto& e : sort) for (auto& e : sort)
m_entries.push_back(std::move(e.second)); m_entries.push_back(std::move(e.second));
} } else {
else
{
std::map<SystemString, Entry, CaseInsensitiveCompare> sort; std::map<SystemString, Entry, CaseInsensitiveCompare> sort;
do do {
{
if (!wcscmp(d.cFileName, _SYS_STR(".")) || !wcscmp(d.cFileName, _SYS_STR(".."))) if (!wcscmp(d.cFileName, _SYS_STR(".")) || !wcscmp(d.cFileName, _SYS_STR("..")))
continue; continue;
if (noHidden && (d.cFileName[0] == L'.' || (d.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) != 0)) if (noHidden && (d.cFileName[0] == L'.' || (d.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) != 0))
@ -164,11 +152,9 @@ DirectoryEnumerator::DirectoryEnumerator(SystemStringView path, Mode mode, bool
if (!dir) if (!dir)
return; return;
const dirent* d; const dirent* d;
switch (mode) switch (mode) {
{
case Mode::Native: case Mode::Native:
while ((d = readdir(dir))) while ((d = readdir(dir))) {
{
if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, "..")) if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
continue; continue;
if (noHidden && d->d_name[0] == '.') if (noHidden && d->d_name[0] == '.')
@ -193,11 +179,9 @@ DirectoryEnumerator::DirectoryEnumerator(SystemStringView path, Mode mode, bool
} }
break; break;
case Mode::DirsThenFilesSorted: case Mode::DirsThenFilesSorted:
case Mode::DirsSorted: case Mode::DirsSorted: {
{
std::map<SystemString, Entry, CaseInsensitiveCompare> sort; std::map<SystemString, Entry, CaseInsensitiveCompare> sort;
while ((d = readdir(dir))) while ((d = readdir(dir))) {
{
if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, "..")) if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
continue; continue;
if (noHidden && d->d_name[0] == '.') if (noHidden && d->d_name[0] == '.')
@ -223,16 +207,13 @@ DirectoryEnumerator::DirectoryEnumerator(SystemStringView path, Mode mode, bool
break; break;
rewinddir(dir); rewinddir(dir);
} }
case Mode::FilesSorted: case Mode::FilesSorted: {
{
if (mode == Mode::FilesSorted) if (mode == Mode::FilesSorted)
m_entries.clear(); m_entries.clear();
if (sizeSort) if (sizeSort) {
{
std::multimap<size_t, Entry> sort; std::multimap<size_t, Entry> sort;
while ((d = readdir(dir))) while ((d = readdir(dir))) {
{
if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, "..")) if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
continue; continue;
if (noHidden && d->d_name[0] == '.') if (noHidden && d->d_name[0] == '.')
@ -253,12 +234,9 @@ DirectoryEnumerator::DirectoryEnumerator(SystemStringView path, Mode mode, bool
else else
for (auto& e : sort) for (auto& e : sort)
m_entries.push_back(std::move(e.second)); m_entries.push_back(std::move(e.second));
} } else {
else
{
std::map<SystemString, Entry, CaseInsensitiveCompare> sort; std::map<SystemString, Entry, CaseInsensitiveCompare> sort;
while ((d = readdir(dir))) while ((d = readdir(dir))) {
{
if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, "..")) if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
continue; continue;
if (noHidden && d->d_name[0] == '.') if (noHidden && d->d_name[0] == '.')
@ -288,4 +266,4 @@ DirectoryEnumerator::DirectoryEnumerator(SystemStringView path, Mode mode, bool
#endif #endif
} }
} } // namespace amuse

View File

@ -4,8 +4,7 @@
#include <cstring> #include <cstring>
#include <cmath> #include <cmath>
namespace amuse namespace amuse {
{
/* clang-format off */ /* clang-format off */
static const float rsmpTab12khz[] = static const float rsmpTab12khz[] =
@ -144,20 +143,16 @@ static const float rsmpTab12khz[] =
EffectChorus::EffectChorus(uint32_t baseDelay, uint32_t variation, uint32_t period) EffectChorus::EffectChorus(uint32_t baseDelay, uint32_t variation, uint32_t period)
: x90_baseDelay(clamp(5u, baseDelay, 15u)) : x90_baseDelay(clamp(5u, baseDelay, 15u))
, x94_variation(clamp(0u, variation, 5u)) , x94_variation(clamp(0u, variation, 5u))
, x98_period(clamp(500u, period, 10000u)) , x98_period(clamp(500u, period, 10000u)) {}
{
}
template <typename T> template <typename T>
EffectChorusImp<T>::EffectChorusImp(uint32_t baseDelay, uint32_t variation, uint32_t period, double sampleRate) EffectChorusImp<T>::EffectChorusImp(uint32_t baseDelay, uint32_t variation, uint32_t period, double sampleRate)
: EffectChorus(baseDelay, variation, period) : EffectChorus(baseDelay, variation, period) {
{
_setup(sampleRate); _setup(sampleRate);
} }
template <typename T> template <typename T>
void EffectChorusImp<T>::_setup(double sampleRate) void EffectChorusImp<T>::_setup(double sampleRate) {
{
m_sampsPerMs = std::ceil(sampleRate / 1000.0); m_sampsPerMs = std::ceil(sampleRate / 1000.0);
m_blockSamples = m_sampsPerMs * 5; m_blockSamples = m_sampsPerMs * 5;
@ -177,8 +172,7 @@ void EffectChorusImp<T>::_setup(double sampleRate)
} }
template <typename T> template <typename T>
void EffectChorusImp<T>::_update() void EffectChorusImp<T>::_update() {
{
size_t chanPitch = m_blockSamples * AMUSE_CHORUS_NUM_BLOCKS; size_t chanPitch = m_blockSamples * AMUSE_CHORUS_NUM_BLOCKS;
size_t fifteenSamps = 15 * m_sampsPerMs; size_t fifteenSamps = 15 * m_sampsPerMs;
@ -195,27 +189,23 @@ void EffectChorusImp<T>::_update()
} }
template <typename T> template <typename T>
EffectChorusImp<T>::~EffectChorusImp() EffectChorusImp<T>::~EffectChorusImp() {
{
delete[] x0_lastChans[0][0]; delete[] x0_lastChans[0][0];
} }
template <typename T> template <typename T>
void EffectChorusImp<T>::SrcInfo::doSrc1(size_t blockSamples, size_t chanCount) void EffectChorusImp<T>::SrcInfo::doSrc1(size_t blockSamples, size_t chanCount) {
{
float old1 = x74_old[0]; float old1 = x74_old[0];
float old2 = x74_old[1]; float old2 = x74_old[1];
float old3 = x74_old[2]; float old3 = x74_old[2];
float cur = x70_smpBase[x7c_posHi]; float cur = x70_smpBase[x7c_posHi];
T* dest = x6c_dest; T* dest = x6c_dest;
for (size_t i = 0; i < blockSamples; ++i) for (size_t i = 0; i < blockSamples; ++i) {
{
const float* selTab = &rsmpTab12khz[x78_posLo >> 23 & 0x1fc]; const float* selTab = &rsmpTab12khz[x78_posLo >> 23 & 0x1fc];
uint64_t ovrTest = uint64_t(x78_posLo) + uint64_t(x80_pitchLo); uint64_t ovrTest = uint64_t(x78_posLo) + uint64_t(x80_pitchLo);
if (ovrTest > UINT32_MAX) if (ovrTest > UINT32_MAX) {
{
/* overflow */ /* overflow */
x78_posLo = ovrTest & 0xffffffff; x78_posLo = ovrTest & 0xffffffff;
++x7c_posHi; ++x7c_posHi;
@ -227,9 +217,7 @@ void EffectChorusImp<T>::SrcInfo::doSrc1(size_t blockSamples, size_t chanCount)
old2 = old3; old2 = old3;
old3 = cur; old3 = cur;
cur = x70_smpBase[x7c_posHi]; cur = x70_smpBase[x7c_posHi];
} } else {
else
{
x78_posLo = ovrTest; x78_posLo = ovrTest;
*dest = ClampFull<T>(selTab[0] * old1 + selTab[1] * old2 + selTab[2] * old3 + selTab[3] * cur); *dest = ClampFull<T>(selTab[0] * old1 + selTab[1] * old2 + selTab[2] * old3 + selTab[3] * cur);
dest += chanCount; dest += chanCount;
@ -242,22 +230,19 @@ void EffectChorusImp<T>::SrcInfo::doSrc1(size_t blockSamples, size_t chanCount)
} }
template <typename T> template <typename T>
void EffectChorusImp<T>::SrcInfo::doSrc2(size_t blockSamples, size_t chanCount) void EffectChorusImp<T>::SrcInfo::doSrc2(size_t blockSamples, size_t chanCount) {
{
float old1 = x74_old[0]; float old1 = x74_old[0];
float old2 = x74_old[1]; float old2 = x74_old[1];
float old3 = x74_old[2]; float old3 = x74_old[2];
float cur = x70_smpBase[x7c_posHi]; float cur = x70_smpBase[x7c_posHi];
T* dest = x6c_dest; T* dest = x6c_dest;
for (size_t i = 0; i < blockSamples; ++i) for (size_t i = 0; i < blockSamples; ++i) {
{
const float* selTab = &rsmpTab12khz[x78_posLo >> 23 & 0x1fc]; const float* selTab = &rsmpTab12khz[x78_posLo >> 23 & 0x1fc];
++x7c_posHi; ++x7c_posHi;
uint64_t ovrTest = uint64_t(x78_posLo) + uint64_t(x80_pitchLo); uint64_t ovrTest = uint64_t(x78_posLo) + uint64_t(x80_pitchLo);
if (ovrTest > UINT32_MAX) if (ovrTest > UINT32_MAX) {
{
/* overflow */ /* overflow */
x78_posLo = ovrTest & 0xffffffff; x78_posLo = ovrTest & 0xffffffff;
@ -276,9 +261,7 @@ void EffectChorusImp<T>::SrcInfo::doSrc2(size_t blockSamples, size_t chanCount)
dest += chanCount; dest += chanCount;
cur = x70_smpBase[x7c_posHi]; cur = x70_smpBase[x7c_posHi];
} } else {
else
{
x78_posLo = ovrTest; x78_posLo = ovrTest;
*dest = ClampFull<T>(selTab[0] * old1 + selTab[1] * old2 + selTab[2] * old3 + selTab[3] * cur); *dest = ClampFull<T>(selTab[0] * old1 + selTab[1] * old2 + selTab[2] * old3 + selTab[3] * cur);
@ -301,14 +284,12 @@ void EffectChorusImp<T>::SrcInfo::doSrc2(size_t blockSamples, size_t chanCount)
} }
template <typename T> template <typename T>
void EffectChorusImp<T>::applyEffect(T* audio, size_t frameCount, const ChannelMap& chanMap) void EffectChorusImp<T>::applyEffect(T* audio, size_t frameCount, const ChannelMap& chanMap) {
{
if (m_dirty) if (m_dirty)
_update(); _update();
size_t remFrames = frameCount; size_t remFrames = frameCount;
for (size_t f = 0; f < frameCount;) for (size_t f = 0; f < frameCount;) {
{
uint8_t next = x24_currentLast + 1; uint8_t next = x24_currentLast + 1;
uint8_t buf = next % 3; uint8_t buf = next % 3;
T* bufs[8] = { T* bufs[8] = {
@ -325,16 +306,14 @@ void EffectChorusImp<T>::applyEffect(T* audio, size_t frameCount, const ChannelM
x6c_src.x80_pitchLo = (x60_pitchOffset << 16); x6c_src.x80_pitchLo = (x60_pitchOffset << 16);
--x64_pitchOffsetPeriodCount; --x64_pitchOffsetPeriodCount;
if (x64_pitchOffsetPeriodCount == 0) if (x64_pitchOffsetPeriodCount == 0) {
{
x64_pitchOffsetPeriodCount = x68_pitchOffsetPeriod; x64_pitchOffsetPeriodCount = x68_pitchOffsetPeriod;
x60_pitchOffset = -x60_pitchOffset; x60_pitchOffset = -x60_pitchOffset;
} }
T* outBuf = audio; T* outBuf = audio;
size_t bs = std::min(remFrames, size_t(m_blockSamples)); size_t bs = std::min(remFrames, size_t(m_blockSamples));
for (size_t c = 0; c < chanMap.m_channelCount && c < 8; ++c) for (size_t c = 0; c < chanMap.m_channelCount && c < 8; ++c) {
{
x6c_src.x7c_posHi = x5c_currentPosHi; x6c_src.x7c_posHi = x5c_currentPosHi;
x6c_src.x78_posLo = x58_currentPosLo; x6c_src.x78_posLo = x58_currentPosLo;
@ -342,8 +321,7 @@ void EffectChorusImp<T>::applyEffect(T* audio, size_t frameCount, const ChannelM
x6c_src.x70_smpBase = x0_lastChans[c][0]; x6c_src.x70_smpBase = x0_lastChans[c][0];
x6c_src.x74_old = x28_oldChans[c]; x6c_src.x74_old = x28_oldChans[c];
switch (x6c_src.x84_pitchHi) switch (x6c_src.x84_pitchHi) {
{
case 0: case 0:
x6c_src.doSrc1(bs, chanMap.m_channelCount); x6c_src.doSrc1(bs, chanMap.m_channelCount);
break; break;
@ -370,4 +348,4 @@ void EffectChorusImp<T>::applyEffect(T* audio, size_t frameCount, const ChannelM
template class EffectChorusImp<int16_t>; template class EffectChorusImp<int16_t>;
template class EffectChorusImp<int32_t>; template class EffectChorusImp<int32_t>;
template class EffectChorusImp<float>; template class EffectChorusImp<float>;
} } // namespace amuse

View File

@ -4,18 +4,15 @@
#include <cstring> #include <cstring>
#include <cmath> #include <cmath>
namespace amuse namespace amuse {
{
template <typename T> template <typename T>
EffectDelayImp<T>::EffectDelayImp(uint32_t initDelay, uint32_t initFeedback, uint32_t initOutput, double sampleRate) EffectDelayImp<T>::EffectDelayImp(uint32_t initDelay, uint32_t initFeedback, uint32_t initOutput, double sampleRate) {
{
initDelay = clamp(10u, initDelay, 5000u); initDelay = clamp(10u, initDelay, 5000u);
initFeedback = clamp(0u, initFeedback, 100u); initFeedback = clamp(0u, initFeedback, 100u);
initOutput = clamp(0u, initOutput, 100u); initOutput = clamp(0u, initOutput, 100u);
for (int i = 0; i < 8; ++i) for (int i = 0; i < 8; ++i) {
{
x3c_delay[i] = initDelay; x3c_delay[i] = initDelay;
x48_feedback[i] = initFeedback; x48_feedback[i] = initFeedback;
x54_output[i] = initOutput; x54_output[i] = initOutput;
@ -25,10 +22,8 @@ EffectDelayImp<T>::EffectDelayImp(uint32_t initDelay, uint32_t initFeedback, uin
} }
template <typename T> template <typename T>
EffectDelayImp<T>::EffectDelayImp(const EffectDelayInfo& info, double sampleRate) EffectDelayImp<T>::EffectDelayImp(const EffectDelayInfo& info, double sampleRate) {
{ for (int i = 0; i < 8; ++i) {
for (int i = 0; i < 8; ++i)
{
x3c_delay[i] = clamp(10u, info.delay[i], 5000u); x3c_delay[i] = clamp(10u, info.delay[i], 5000u);
x48_feedback[i] = clamp(0u, info.feedback[i], 100u); x48_feedback[i] = clamp(0u, info.feedback[i], 100u);
x54_output[i] = clamp(0u, info.output[i], 100u); x54_output[i] = clamp(0u, info.output[i], 100u);
@ -38,8 +33,7 @@ EffectDelayImp<T>::EffectDelayImp(const EffectDelayInfo& info, double sampleRate
} }
template <typename T> template <typename T>
void EffectDelayImp<T>::_setup(double sampleRate) void EffectDelayImp<T>::_setup(double sampleRate) {
{
m_sampsPerMs = std::ceil(sampleRate / 1000.0); m_sampsPerMs = std::ceil(sampleRate / 1000.0);
m_blockSamples = m_sampsPerMs * 5; m_blockSamples = m_sampsPerMs * 5;
@ -47,10 +41,8 @@ void EffectDelayImp<T>::_setup(double sampleRate)
} }
template <typename T> template <typename T>
void EffectDelayImp<T>::_update() void EffectDelayImp<T>::_update() {
{ for (int i = 0; i < 8; ++i) {
for (int i = 0; i < 8; ++i)
{
x0_currentSize[i] = ((x3c_delay[i] - 5) * m_sampsPerMs + 159) / 160; x0_currentSize[i] = ((x3c_delay[i] - 5) * m_sampsPerMs + 159) / 160;
xc_currentPos[i] = 0; xc_currentPos[i] = 0;
x18_currentFeedback[i] = x48_feedback[i] * 128 / 100; x18_currentFeedback[i] = x48_feedback[i] * 128 / 100;
@ -64,18 +56,14 @@ void EffectDelayImp<T>::_update()
} }
template <typename T> template <typename T>
void EffectDelayImp<T>::applyEffect(T* audio, size_t frameCount, const ChannelMap& chanMap) void EffectDelayImp<T>::applyEffect(T* audio, size_t frameCount, const ChannelMap& chanMap) {
{
if (m_dirty) if (m_dirty)
_update(); _update();
for (size_t f = 0; f < frameCount;) for (size_t f = 0; f < frameCount;) {
{ for (unsigned c = 0; c < chanMap.m_channelCount; ++c) {
for (unsigned c = 0; c < chanMap.m_channelCount; ++c)
{
T* chanAud = audio + c; T* chanAud = audio + c;
for (unsigned i = 0; i < m_blockSamples && f < frameCount; ++i, ++f) for (unsigned i = 0; i < m_blockSamples && f < frameCount; ++i, ++f) {
{
T& liveSamp = chanAud[chanMap.m_channelCount * i]; T& liveSamp = chanAud[chanMap.m_channelCount * i];
T& samp = x30_chanLines[c][xc_currentPos[c] * m_blockSamples + i]; T& samp = x30_chanLines[c][xc_currentPos[c] * m_blockSamples + i];
samp = ClampFull<T>(samp * x18_currentFeedback[c] / 128 + liveSamp); samp = ClampFull<T>(samp * x18_currentFeedback[c] / 128 + liveSamp);
@ -90,4 +78,4 @@ void EffectDelayImp<T>::applyEffect(T* audio, size_t frameCount, const ChannelMa
template class EffectDelayImp<int16_t>; template class EffectDelayImp<int16_t>;
template class EffectDelayImp<int32_t>; template class EffectDelayImp<int32_t>;
template class EffectDelayImp<float>; template class EffectDelayImp<float>;
} } // namespace amuse

View File

@ -3,8 +3,7 @@
#include <cmath> #include <cmath>
#include <cstring> #include <cstring>
namespace amuse namespace amuse {
{
/* clang-format off */ /* clang-format off */
@ -38,8 +37,7 @@ static const size_t LPTapDelays[] =
/* clang-format on */ /* clang-format on */
void ReverbDelayLine::allocate(int32_t delay) void ReverbDelayLine::allocate(int32_t delay) {
{
delay += 2; delay += 2;
x8_length = delay; x8_length = delay;
xc_inputs.reset(new float[delay]); xc_inputs.reset(new float[delay]);
@ -50,8 +48,7 @@ void ReverbDelayLine::allocate(int32_t delay)
x4_outPoint = 0; x4_outPoint = 0;
} }
void ReverbDelayLine::setdelay(int32_t delay) void ReverbDelayLine::setdelay(int32_t delay) {
{
x4_outPoint = x0_inPoint - delay; x4_outPoint = x0_inPoint - delay;
while (x4_outPoint < 0) while (x4_outPoint < 0)
x4_outPoint += x8_length; x4_outPoint += x8_length;
@ -62,39 +59,30 @@ EffectReverbStd::EffectReverbStd(float coloration, float mix, float time, float
, x144_x1cc_mix(clamp(0.f, mix, 1.f)) , x144_x1cc_mix(clamp(0.f, mix, 1.f))
, x148_x1d0_time(clamp(0.01f, time, 10.f)) , x148_x1d0_time(clamp(0.01f, time, 10.f))
, x14c_x1d4_damping(clamp(0.f, damping, 1.f)) , x14c_x1d4_damping(clamp(0.f, damping, 1.f))
, x150_x1d8_preDelay(clamp(0.f, preDelay, 0.1f)) , x150_x1d8_preDelay(clamp(0.f, preDelay, 0.1f)) {}
{
}
EffectReverbHi::EffectReverbHi(float coloration, float mix, float time, float damping, float preDelay, float crosstalk) EffectReverbHi::EffectReverbHi(float coloration, float mix, float time, float damping, float preDelay, float crosstalk)
: EffectReverbStd(coloration, mix, time, damping, preDelay), x1dc_crosstalk(clamp(0.f, crosstalk, 1.0f)) : EffectReverbStd(coloration, mix, time, damping, preDelay), x1dc_crosstalk(clamp(0.f, crosstalk, 1.0f)) {}
{
}
template <typename T> template <typename T>
EffectReverbStdImp<T>::EffectReverbStdImp(float coloration, float mix, float time, float damping, float preDelay, EffectReverbStdImp<T>::EffectReverbStdImp(float coloration, float mix, float time, float damping, float preDelay,
double sampleRate) double sampleRate)
: EffectReverbStd(coloration, mix, time, damping, preDelay) : EffectReverbStd(coloration, mix, time, damping, preDelay) {
{
_setup(sampleRate); _setup(sampleRate);
} }
template <typename T> template <typename T>
void EffectReverbStdImp<T>::_setup(double sampleRate) void EffectReverbStdImp<T>::_setup(double sampleRate) {
{
m_sampleRate = sampleRate; m_sampleRate = sampleRate;
_update(); _update();
} }
template <typename T> template <typename T>
void EffectReverbStdImp<T>::_update() void EffectReverbStdImp<T>::_update() {
{
float timeSamples = x148_x1d0_time * m_sampleRate; float timeSamples = x148_x1d0_time * m_sampleRate;
double rateRatio = m_sampleRate / NativeSampleRate; double rateRatio = m_sampleRate / NativeSampleRate;
for (int c = 0; c < 8; ++c) for (int c = 0; c < 8; ++c) {
{ for (int t = 0; t < 2; ++t) {
for (int t = 0; t < 2; ++t)
{
ReverbDelayLine& combLine = x78_C[c][t]; ReverbDelayLine& combLine = x78_C[c][t];
size_t tapDelay = CTapDelays[t] * rateRatio; size_t tapDelay = CTapDelays[t] * rateRatio;
combLine.allocate(tapDelay); combLine.allocate(tapDelay);
@ -102,8 +90,7 @@ void EffectReverbStdImp<T>::_update()
xf4_combCoef[c][t] = std::pow(10.f, tapDelay * -3.f / timeSamples); xf4_combCoef[c][t] = std::pow(10.f, tapDelay * -3.f / timeSamples);
} }
for (int t = 0; t < 2; ++t) for (int t = 0; t < 2; ++t) {
{
ReverbDelayLine& allPassLine = x0_AP[c][t]; ReverbDelayLine& allPassLine = x0_AP[c][t];
size_t tapDelay = APTapDelays[t] * rateRatio; size_t tapDelay = APTapDelays[t] * rateRatio;
allPassLine.allocate(tapDelay); allPassLine.allocate(tapDelay);
@ -120,21 +107,16 @@ void EffectReverbStdImp<T>::_update()
x11c_damping = 1.f - (x11c_damping * 0.8f + 0.05); x11c_damping = 1.f - (x11c_damping * 0.8f + 0.05);
if (x150_x1d8_preDelay != 0.f) if (x150_x1d8_preDelay != 0.f) {
{
x120_preDelayTime = m_sampleRate * x150_x1d8_preDelay; x120_preDelayTime = m_sampleRate * x150_x1d8_preDelay;
for (int i = 0; i < 8; ++i) for (int i = 0; i < 8; ++i) {
{
x124_preDelayLine[i].reset(new float[x120_preDelayTime]); x124_preDelayLine[i].reset(new float[x120_preDelayTime]);
memset(x124_preDelayLine[i].get(), 0, x120_preDelayTime * sizeof(float)); memset(x124_preDelayLine[i].get(), 0, x120_preDelayTime * sizeof(float));
x130_preDelayPtr[i] = x124_preDelayLine[i].get(); x130_preDelayPtr[i] = x124_preDelayLine[i].get();
} }
} } else {
else
{
x120_preDelayTime = 0; x120_preDelayTime = 0;
for (int i = 0; i < 8; ++i) for (int i = 0; i < 8; ++i) {
{
x124_preDelayLine[i] = nullptr; x124_preDelayLine[i] = nullptr;
x130_preDelayPtr[i] = nullptr; x130_preDelayPtr[i] = nullptr;
} }
@ -144,18 +126,15 @@ void EffectReverbStdImp<T>::_update()
} }
template <typename T> template <typename T>
void EffectReverbStdImp<T>::applyEffect(T* audio, size_t frameCount, const ChannelMap& chanMap) void EffectReverbStdImp<T>::applyEffect(T* audio, size_t frameCount, const ChannelMap& chanMap) {
{
if (m_dirty) if (m_dirty)
_update(); _update();
float dampWet = x118_level * 0.6f; float dampWet = x118_level * 0.6f;
float dampDry = 0.6f - dampWet; float dampDry = 0.6f - dampWet;
for (size_t f = 0; f < frameCount; f += 160) for (size_t f = 0; f < frameCount; f += 160) {
{ for (unsigned c = 0; c < chanMap.m_channelCount; ++c) {
for (unsigned c = 0; c < chanMap.m_channelCount; ++c)
{
float* combCoefs = xf4_combCoef[c]; float* combCoefs = xf4_combCoef[c];
float& lpLastOut = x10c_lpLastout[c]; float& lpLastOut = x10c_lpLastout[c];
float* preDelayLine = x124_preDelayLine[c].get(); float* preDelayLine = x124_preDelayLine[c].get();
@ -166,14 +145,12 @@ void EffectReverbStdImp<T>::applyEffect(T* audio, size_t frameCount, const Chann
ReverbDelayLine* linesAP = x0_AP[c]; ReverbDelayLine* linesAP = x0_AP[c];
int procSamples = std::min(size_t(160), frameCount - f); int procSamples = std::min(size_t(160), frameCount - f);
for (int s = 0; s < procSamples; ++s) for (int s = 0; s < procSamples; ++s) {
{
float sample = audio[s * chanMap.m_channelCount + c]; float sample = audio[s * chanMap.m_channelCount + c];
/* Pre-delay stage */ /* Pre-delay stage */
float sample2 = sample; float sample2 = sample;
if (x120_preDelayTime != 0) if (x120_preDelayTime != 0) {
{
sample2 = *preDelayPtr; sample2 = *preDelayPtr;
*preDelayPtr = sample; *preDelayPtr = sample;
preDelayPtr += 1; preDelayPtr += 1;
@ -209,8 +186,7 @@ void EffectReverbStdImp<T>::applyEffect(T* audio, size_t frameCount, const Chann
/* All-pass filter stage */ /* All-pass filter stage */
linesAP[0].xc_inputs[linesAP[0].x0_inPoint] = linesAP[0].xc_inputs[linesAP[0].x0_inPoint] =
xf0_allPassCoef * linesAP[0].x10_lastInput + linesC[0].x10_lastInput + linesC[1].x10_lastInput; xf0_allPassCoef * linesAP[0].x10_lastInput + linesC[0].x10_lastInput + linesC[1].x10_lastInput;
float lowPass = float lowPass = -(xf0_allPassCoef * linesAP[0].xc_inputs[linesAP[0].x0_inPoint] - linesAP[0].x10_lastInput);
-(xf0_allPassCoef * linesAP[0].xc_inputs[linesAP[0].x0_inPoint] - linesAP[0].x10_lastInput);
linesAP[0].x0_inPoint += 1; linesAP[0].x0_inPoint += 1;
linesAP[0].x10_lastInput = linesAP[0].xc_inputs[linesAP[0].x4_outPoint]; linesAP[0].x10_lastInput = linesAP[0].xc_inputs[linesAP[0].x4_outPoint];
@ -224,8 +200,7 @@ void EffectReverbStdImp<T>::applyEffect(T* audio, size_t frameCount, const Chann
lpLastOut = x11c_damping * lpLastOut + lowPass * 0.3f; lpLastOut = x11c_damping * lpLastOut + lowPass * 0.3f;
linesAP[1].xc_inputs[linesAP[1].x0_inPoint] = xf0_allPassCoef * linesAP[1].x10_lastInput + lpLastOut; linesAP[1].xc_inputs[linesAP[1].x0_inPoint] = xf0_allPassCoef * linesAP[1].x10_lastInput + lpLastOut;
float allPass = float allPass = -(xf0_allPassCoef * linesAP[1].xc_inputs[linesAP[1].x0_inPoint] - linesAP[1].x10_lastInput);
-(xf0_allPassCoef * linesAP[1].xc_inputs[linesAP[1].x0_inPoint] - linesAP[1].x10_lastInput);
linesAP[1].x0_inPoint += 1; linesAP[1].x0_inPoint += 1;
linesAP[1].x10_lastInput = linesAP[1].xc_inputs[linesAP[1].x4_outPoint]; linesAP[1].x10_lastInput = linesAP[1].xc_inputs[linesAP[1].x4_outPoint];
@ -249,27 +224,22 @@ void EffectReverbStdImp<T>::applyEffect(T* audio, size_t frameCount, const Chann
template <typename T> template <typename T>
EffectReverbHiImp<T>::EffectReverbHiImp(float coloration, float mix, float time, float damping, float preDelay, EffectReverbHiImp<T>::EffectReverbHiImp(float coloration, float mix, float time, float damping, float preDelay,
float crosstalk, double sampleRate) float crosstalk, double sampleRate)
: EffectReverbHi(coloration, mix, time, damping, preDelay, crosstalk) : EffectReverbHi(coloration, mix, time, damping, preDelay, crosstalk) {
{
_setup(sampleRate); _setup(sampleRate);
} }
template <typename T> template <typename T>
void EffectReverbHiImp<T>::_setup(double sampleRate) void EffectReverbHiImp<T>::_setup(double sampleRate) {
{
m_sampleRate = sampleRate; m_sampleRate = sampleRate;
_update(); _update();
} }
template <typename T> template <typename T>
void EffectReverbHiImp<T>::_update() void EffectReverbHiImp<T>::_update() {
{
float timeSamples = x148_x1d0_time * m_sampleRate; float timeSamples = x148_x1d0_time * m_sampleRate;
double rateRatio = m_sampleRate / NativeSampleRate; double rateRatio = m_sampleRate / NativeSampleRate;
for (int c = 0; c < 8; ++c) for (int c = 0; c < 8; ++c) {
{ for (int t = 0; t < 3; ++t) {
for (int t = 0; t < 3; ++t)
{
ReverbDelayLine& combLine = xb4_C[c][t]; ReverbDelayLine& combLine = xb4_C[c][t];
size_t tapDelay = CTapDelays[t] * rateRatio; size_t tapDelay = CTapDelays[t] * rateRatio;
combLine.allocate(tapDelay); combLine.allocate(tapDelay);
@ -277,8 +247,7 @@ void EffectReverbHiImp<T>::_update()
x16c_combCoef[c][t] = std::pow(10.f, tapDelay * -3.f / timeSamples); x16c_combCoef[c][t] = std::pow(10.f, tapDelay * -3.f / timeSamples);
} }
for (int t = 0; t < 2; ++t) for (int t = 0; t < 2; ++t) {
{
ReverbDelayLine& allPassLine = x0_AP[c][t]; ReverbDelayLine& allPassLine = x0_AP[c][t];
size_t tapDelay = APTapDelays[t] * rateRatio; size_t tapDelay = APTapDelays[t] * rateRatio;
allPassLine.allocate(tapDelay); allPassLine.allocate(tapDelay);
@ -300,21 +269,16 @@ void EffectReverbHiImp<T>::_update()
x1a0_damping = 1.f - (x1a0_damping * 0.8f + 0.05); x1a0_damping = 1.f - (x1a0_damping * 0.8f + 0.05);
if (x150_x1d8_preDelay != 0.f) if (x150_x1d8_preDelay != 0.f) {
{
x1a4_preDelayTime = m_sampleRate * x150_x1d8_preDelay; x1a4_preDelayTime = m_sampleRate * x150_x1d8_preDelay;
for (int i = 0; i < 8; ++i) for (int i = 0; i < 8; ++i) {
{
x1ac_preDelayLine[i].reset(new float[x1a4_preDelayTime]); x1ac_preDelayLine[i].reset(new float[x1a4_preDelayTime]);
memset(x1ac_preDelayLine[i].get(), 0, x1a4_preDelayTime * sizeof(float)); memset(x1ac_preDelayLine[i].get(), 0, x1a4_preDelayTime * sizeof(float));
x1b8_preDelayPtr[i] = x1ac_preDelayLine[i].get(); x1b8_preDelayPtr[i] = x1ac_preDelayLine[i].get();
} }
} } else {
else
{
x1a4_preDelayTime = 0; x1a4_preDelayTime = 0;
for (int i = 0; i < 8; ++i) for (int i = 0; i < 8; ++i) {
{
x1ac_preDelayLine[i] = nullptr; x1ac_preDelayLine[i] = nullptr;
x1b8_preDelayPtr[i] = nullptr; x1b8_preDelayPtr[i] = nullptr;
} }
@ -325,8 +289,7 @@ void EffectReverbHiImp<T>::_update()
} }
template <typename T> template <typename T>
void EffectReverbHiImp<T>::_handleReverb(T* audio, int c, int chanCount, int sampleCount) void EffectReverbHiImp<T>::_handleReverb(T* audio, int c, int chanCount, int sampleCount) {
{
float dampWet = x19c_level * 0.6f; float dampWet = x19c_level * 0.6f;
float dampDry = 0.6f - dampWet; float dampDry = 0.6f - dampWet;
@ -344,14 +307,12 @@ void EffectReverbHiImp<T>::_handleReverb(T* audio, int c, int chanCount, int sam
float damping = x1a0_damping; float damping = x1a0_damping;
int32_t preDelayTime = x1a4_preDelayTime; int32_t preDelayTime = x1a4_preDelayTime;
for (int s = 0; s < sampleCount; ++s) for (int s = 0; s < sampleCount; ++s) {
{
float sample = audio[s * chanCount + c]; float sample = audio[s * chanCount + c];
/* Pre-delay stage */ /* Pre-delay stage */
float sample2 = sample; float sample2 = sample;
if (preDelayTime != 0) if (preDelayTime != 0) {
{
sample2 = *preDelayPtr; sample2 = *preDelayPtr;
*preDelayPtr = sample; *preDelayPtr = sample;
preDelayPtr += 1; preDelayPtr += 1;
@ -448,14 +409,11 @@ void EffectReverbHiImp<T>::_handleReverb(T* audio, int c, int chanCount, int sam
} }
template <typename T> template <typename T>
void EffectReverbHiImp<T>::_doCrosstalk(T* audio, float wet, float dry, int chanCount, int sampleCount) void EffectReverbHiImp<T>::_doCrosstalk(T* audio, float wet, float dry, int chanCount, int sampleCount) {
{ for (int i = 0; i < sampleCount; ++i) {
for (int i = 0; i < sampleCount; ++i)
{
T* base = &audio[chanCount * i]; T* base = &audio[chanCount * i];
float allWet = 0; float allWet = 0;
for (int c = 0; c < chanCount; ++c) for (int c = 0; c < chanCount; ++c) {
{
allWet += base[c] * wet; allWet += base[c] * wet;
base[c] *= dry; base[c] *= dry;
} }
@ -465,18 +423,14 @@ void EffectReverbHiImp<T>::_doCrosstalk(T* audio, float wet, float dry, int chan
} }
template <typename T> template <typename T>
void EffectReverbHiImp<T>::applyEffect(T* audio, size_t frameCount, const ChannelMap& chanMap) void EffectReverbHiImp<T>::applyEffect(T* audio, size_t frameCount, const ChannelMap& chanMap) {
{
if (m_dirty) if (m_dirty)
_update(); _update();
for (size_t f = 0; f < frameCount; f += 160) for (size_t f = 0; f < frameCount; f += 160) {
{
size_t blockSamples = std::min(size_t(160), frameCount - f); size_t blockSamples = std::min(size_t(160), frameCount - f);
for (unsigned i = 0; i < chanMap.m_channelCount; ++i) for (unsigned i = 0; i < chanMap.m_channelCount; ++i) {
{ if (i == 0 && x1a8_internalCrosstalk != 0.f) {
if (i == 0 && x1a8_internalCrosstalk != 0.f)
{
float crossWet = x1a8_internalCrosstalk * 0.5; float crossWet = x1a8_internalCrosstalk * 0.5;
_doCrosstalk(audio, crossWet, 1.f - crossWet, chanMap.m_channelCount, blockSamples); _doCrosstalk(audio, crossWet, 1.f - crossWet, chanMap.m_channelCount, blockSamples);
} }
@ -493,4 +447,4 @@ template class EffectReverbStdImp<float>;
template class EffectReverbHiImp<int16_t>; template class EffectReverbHiImp<int16_t>;
template class EffectReverbHiImp<int32_t>; template class EffectReverbHiImp<int32_t>;
template class EffectReverbHiImp<float>; template class EffectReverbHiImp<float>;
} } // namespace amuse

View File

@ -3,11 +3,9 @@
#include "amuse/Voice.hpp" #include "amuse/Voice.hpp"
#include "amuse/Engine.hpp" #include "amuse/Engine.hpp"
namespace amuse namespace amuse {
{
static void Delta(Vector3f& out, const Vector3f& a, const Vector3f& b) static void Delta(Vector3f& out, const Vector3f& a, const Vector3f& b) {
{
out[0] = a[0] - b[0]; out[0] = a[0] - b[0];
out[1] = a[1] - b[1]; out[1] = a[1] - b[1];
out[2] = a[2] - b[2]; out[2] = a[2] - b[2];
@ -15,45 +13,38 @@ static void Delta(Vector3f& out, const Vector3f& a, const Vector3f& b)
Emitter::~Emitter() {} Emitter::~Emitter() {}
Emitter::Emitter(Engine& engine, const AudioGroup& group, ObjToken<Voice> vox, Emitter::Emitter(Engine& engine, const AudioGroup& group, ObjToken<Voice> vox, float maxDist, float minVol,
float maxDist, float minVol, float falloff, bool doppler) float falloff, bool doppler)
: Entity(engine, group, vox->getGroupId(), vox->getObjectId()), m_vox(vox), m_maxDist(maxDist), : Entity(engine, group, vox->getGroupId(), vox->getObjectId())
m_minVol(clamp(0.f, minVol, 1.f)), m_falloff(clamp(-1.f, falloff, 1.f)), m_doppler(doppler) , m_vox(vox)
{ , m_maxDist(maxDist)
} , m_minVol(clamp(0.f, minVol, 1.f))
, m_falloff(clamp(-1.f, falloff, 1.f))
, m_doppler(doppler) {}
void Emitter::_destroy() void Emitter::_destroy() {
{
Entity::_destroy(); Entity::_destroy();
m_vox->kill(); m_vox->kill();
} }
float Emitter::_attenuationCurve(float dist) const float Emitter::_attenuationCurve(float dist) const {
{
if (dist > m_maxDist) if (dist > m_maxDist)
return 0.f; return 0.f;
float t = dist / m_maxDist; float t = dist / m_maxDist;
if (m_falloff >= 0.f) if (m_falloff >= 0.f) {
{
return 1.f - (m_falloff * t * t + (1.f - m_falloff) * t); return 1.f - (m_falloff * t * t + (1.f - m_falloff) * t);
} } else {
else
{
float omt = 1.f - t; float omt = 1.f - t;
return 1.f - ((1.f + m_falloff) * t - (1.f - omt * omt) * m_falloff); return 1.f - ((1.f + m_falloff) * t - (1.f - omt * omt) * m_falloff);
} }
} }
void Emitter::_update() void Emitter::_update() {
{ if (!m_dirty) {
if (!m_dirty)
{
/* Ensure that all listeners are also not dirty */ /* Ensure that all listeners are also not dirty */
bool dirty = false; bool dirty = false;
for (auto& listener : m_engine.m_activeListeners) for (auto& listener : m_engine.m_activeListeners) {
{ if (listener->m_dirty) {
if (listener->m_dirty)
{
dirty = true; dirty = true;
break; break;
} }
@ -65,8 +56,7 @@ void Emitter::_update()
float coefs[8] = {}; float coefs[8] = {};
double avgDopplerRatio = 0.0; double avgDopplerRatio = 0.0;
for (auto& listener : m_engine.m_activeListeners) for (auto& listener : m_engine.m_activeListeners) {
{
Vector3f listenerToEmitter; Vector3f listenerToEmitter;
Delta(listenerToEmitter, m_pos, listener->m_pos); Delta(listenerToEmitter, m_pos, listener->m_pos);
float dist = Length(listenerToEmitter); float dist = Length(listenerToEmitter);
@ -74,15 +64,13 @@ void Emitter::_update()
float frontPan = clamp(-1.f, panDist / listener->m_frontDiff, 1.f); float frontPan = clamp(-1.f, panDist / listener->m_frontDiff, 1.f);
float backPan = clamp(-1.f, panDist / listener->m_backDiff, 1.f); float backPan = clamp(-1.f, panDist / listener->m_backDiff, 1.f);
float spanDist = -Dot(listenerToEmitter, listener->m_heading); float spanDist = -Dot(listenerToEmitter, listener->m_heading);
float span = clamp(-1.f, spanDist > 0.f ? spanDist / listener->m_backDiff : float span = clamp(-1.f, spanDist > 0.f ? spanDist / listener->m_backDiff : spanDist / listener->m_frontDiff, 1.f);
spanDist / listener->m_frontDiff, 1.f);
/* Calculate attenuation */ /* Calculate attenuation */
float att = _attenuationCurve(dist); float att = _attenuationCurve(dist);
att = (m_maxVol - m_minVol) * att + m_minVol; att = (m_maxVol - m_minVol) * att + m_minVol;
att = m_attCache.getVolume(att, false); att = m_attCache.getVolume(att, false);
if (att > FLT_EPSILON) if (att > FLT_EPSILON) {
{
/* Apply pan law */ /* Apply pan law */
float thisCoefs[8] = {}; float thisCoefs[8] = {};
m_vox->_panLaw(thisCoefs, frontPan, backPan, span); m_vox->_panLaw(thisCoefs, frontPan, backPan, span);
@ -93,8 +81,7 @@ void Emitter::_update()
} }
/* Calculate doppler */ /* Calculate doppler */
if (m_doppler) if (m_doppler) {
{
/* Positive values indicate emitter and listener closing in */ /* Positive values indicate emitter and listener closing in */
Vector3f dirDelta; Vector3f dirDelta;
Delta(dirDelta, m_dir, listener->m_dir); Delta(dirDelta, m_dir, listener->m_dir);
@ -109,11 +96,9 @@ void Emitter::_update()
} }
} }
if (m_engine.m_activeListeners.size() != 0) if (m_engine.m_activeListeners.size() != 0) {
{
m_vox->setChannelCoefs(coefs); m_vox->setChannelCoefs(coefs);
if (m_doppler) if (m_doppler) {
{
m_vox->m_dopplerRatio = avgDopplerRatio / float(m_engine.m_activeListeners.size()); m_vox->m_dopplerRatio = avgDopplerRatio / float(m_engine.m_activeListeners.size());
m_vox->m_pitchDirty = true; m_vox->m_pitchDirty = true;
} }
@ -122,14 +107,12 @@ void Emitter::_update()
m_dirty = false; m_dirty = false;
} }
void Emitter::setVectors(const float* pos, const float* dir) void Emitter::setVectors(const float* pos, const float* dir) {
{ for (int i = 0; i < 3; ++i) {
for (int i=0 ; i<3 ; ++i)
{
m_pos[i] = pos[i]; m_pos[i] = pos[i];
m_dir[i] = dir[i]; m_dir[i] = dir[i];
} }
m_dirty = true; m_dirty = true;
} }
} } // namespace amuse

View File

@ -8,13 +8,11 @@
#include "amuse/AudioGroup.hpp" #include "amuse/AudioGroup.hpp"
#include "amuse/Common.hpp" #include "amuse/Common.hpp"
namespace amuse namespace amuse {
{
static const float FullLevels[8] = {1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f}; static const float FullLevels[8] = {1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f};
Engine::~Engine() Engine::~Engine() {
{
m_backend.setCallbackInterface(nullptr); m_backend.setCallbackInterface(nullptr);
for (ObjToken<Sequencer>& seq : m_activeSequencers) for (ObjToken<Sequencer>& seq : m_activeSequencers)
if (!seq->m_destroyed) if (!seq->m_destroyed)
@ -26,8 +24,7 @@ Engine::~Engine()
} }
Engine::Engine(IBackendVoiceAllocator& backend, AmplitudeMode ampMode) Engine::Engine(IBackendVoiceAllocator& backend, AmplitudeMode ampMode)
: m_backend(backend), m_ampMode(ampMode), m_defaultStudio(_allocateStudio(true)) : m_backend(backend), m_ampMode(ampMode), m_defaultStudio(_allocateStudio(true)) {
{
m_defaultStudio->getAuxA().makeReverbStd(0.5f, 0.8f, 3.0f, 0.5f, 0.1f); m_defaultStudio->getAuxA().makeReverbStd(0.5f, 0.8f, 3.0f, 0.5f, 0.1f);
m_defaultStudio->getAuxB().makeChorus(15, 0, 500); m_defaultStudio->getAuxB().makeChorus(15, 0, 500);
m_defaultStudioReady = true; m_defaultStudioReady = true;
@ -35,10 +32,8 @@ Engine::Engine(IBackendVoiceAllocator& backend, AmplitudeMode ampMode)
m_midiReader = backend.allocateMIDIReader(*this); m_midiReader = backend.allocateMIDIReader(*this);
} }
std::pair<AudioGroup*, const SongGroupIndex*> Engine::_findSongGroup(GroupId groupId) const std::pair<AudioGroup*, const SongGroupIndex*> Engine::_findSongGroup(GroupId groupId) const {
{ for (const auto& pair : m_audioGroups) {
for (const auto& pair : m_audioGroups)
{
const SongGroupIndex* ret = pair.second->getProj().getSongGroupIndex(groupId); const SongGroupIndex* ret = pair.second->getProj().getSongGroupIndex(groupId);
if (ret) if (ret)
return {pair.second.get(), ret}; return {pair.second.get(), ret};
@ -46,10 +41,8 @@ std::pair<AudioGroup*, const SongGroupIndex*> Engine::_findSongGroup(GroupId gro
return {}; return {};
} }
std::pair<AudioGroup*, const SFXGroupIndex*> Engine::_findSFXGroup(GroupId groupId) const std::pair<AudioGroup*, const SFXGroupIndex*> Engine::_findSFXGroup(GroupId groupId) const {
{ for (const auto& pair : m_audioGroups) {
for (const auto& pair : m_audioGroups)
{
const SFXGroupIndex* ret = pair.second->getProj().getSFXGroupIndex(groupId); const SFXGroupIndex* ret = pair.second->getProj().getSFXGroupIndex(groupId);
if (ret) if (ret)
return {pair.second.get(), ret}; return {pair.second.get(), ret};
@ -57,10 +50,8 @@ std::pair<AudioGroup*, const SFXGroupIndex*> Engine::_findSFXGroup(GroupId group
return {}; return {};
} }
std::list<ObjToken<Voice>>::iterator Engine::_allocateVoice(const AudioGroup& group, GroupId groupId, std::list<ObjToken<Voice>>::iterator Engine::_allocateVoice(const AudioGroup& group, GroupId groupId, double sampleRate,
double sampleRate, bool dynamicPitch, bool emitter, bool dynamicPitch, bool emitter, ObjToken<Studio> studio) {
ObjToken<Studio> studio)
{
auto it = auto it =
m_activeVoices.emplace(m_activeVoices.end(), MakeObj<Voice>(*this, group, groupId, m_nextVid++, emitter, studio)); m_activeVoices.emplace(m_activeVoices.end(), MakeObj<Voice>(*this, group, groupId, m_nextVid++, emitter, studio));
m_activeVoices.back()->m_backendVoice = m_backend.allocateVoice(*m_activeVoices.back(), sampleRate, dynamicPitch); m_activeVoices.back()->m_backendVoice = m_backend.allocateVoice(*m_activeVoices.back(), sampleRate, dynamicPitch);
@ -71,18 +62,15 @@ std::list<ObjToken<Voice>>::iterator Engine::_allocateVoice(const AudioGroup& gr
} }
std::list<ObjToken<Sequencer>>::iterator Engine::_allocateSequencer(const AudioGroup& group, GroupId groupId, std::list<ObjToken<Sequencer>>::iterator Engine::_allocateSequencer(const AudioGroup& group, GroupId groupId,
SongId setupId, ObjToken<Studio> studio) SongId setupId, ObjToken<Studio> studio) {
{
const SongGroupIndex* songGroup = group.getProj().getSongGroupIndex(groupId); const SongGroupIndex* songGroup = group.getProj().getSongGroupIndex(groupId);
if (songGroup) if (songGroup) {
{
amuse::ObjToken<Sequencer> tok = MakeObj<Sequencer>(*this, group, groupId, songGroup, setupId, studio); amuse::ObjToken<Sequencer> tok = MakeObj<Sequencer>(*this, group, groupId, songGroup, setupId, studio);
auto it = m_activeSequencers.emplace(m_activeSequencers.end(), tok); auto it = m_activeSequencers.emplace(m_activeSequencers.end(), tok);
return it; return it;
} }
const SFXGroupIndex* sfxGroup = group.getProj().getSFXGroupIndex(groupId); const SFXGroupIndex* sfxGroup = group.getProj().getSFXGroupIndex(groupId);
if (sfxGroup) if (sfxGroup) {
{
amuse::ObjToken<Sequencer> tok = MakeObj<Sequencer>(*this, group, groupId, sfxGroup, studio); amuse::ObjToken<Sequencer> tok = MakeObj<Sequencer>(*this, group, groupId, sfxGroup, studio);
auto it = m_activeSequencers.emplace(m_activeSequencers.end(), tok); auto it = m_activeSequencers.emplace(m_activeSequencers.end(), tok);
return it; return it;
@ -90,8 +78,7 @@ std::list<ObjToken<Sequencer>>::iterator Engine::_allocateSequencer(const AudioG
return {}; return {};
} }
ObjToken<Studio> Engine::_allocateStudio(bool mainOut) ObjToken<Studio> Engine::_allocateStudio(bool mainOut) {
{
ObjToken<Studio> ret = MakeObj<Studio>(*this, mainOut); ObjToken<Studio> ret = MakeObj<Studio>(*this, mainOut);
ret->m_master.m_backendSubmix = m_backend.allocateSubmix(ret->m_master, mainOut, 0); ret->m_master.m_backendSubmix = m_backend.allocateSubmix(ret->m_master, mainOut, 0);
ret->m_auxA.m_backendSubmix = m_backend.allocateSubmix(ret->m_auxA, mainOut, 1); ret->m_auxA.m_backendSubmix = m_backend.allocateSubmix(ret->m_auxA, mainOut, 1);
@ -99,8 +86,7 @@ ObjToken<Studio> Engine::_allocateStudio(bool mainOut)
return ret; return ret;
} }
std::list<ObjToken<Voice>>::iterator Engine::_destroyVoice(std::list<ObjToken<Voice>>::iterator it) std::list<ObjToken<Voice>>::iterator Engine::_destroyVoice(std::list<ObjToken<Voice>>::iterator it) {
{
assert(this == &(*it)->getEngine()); assert(this == &(*it)->getEngine());
if ((*it)->m_destroyed) if ((*it)->m_destroyed)
return m_activeVoices.begin(); return m_activeVoices.begin();
@ -108,9 +94,7 @@ std::list<ObjToken<Voice>>::iterator Engine::_destroyVoice(std::list<ObjToken<Vo
return m_activeVoices.erase(it); return m_activeVoices.erase(it);
} }
std::list<ObjToken<Sequencer>>::iterator std::list<ObjToken<Sequencer>>::iterator Engine::_destroySequencer(std::list<ObjToken<Sequencer>>::iterator it) {
Engine::_destroySequencer(std::list<ObjToken<Sequencer>>::iterator it)
{
assert(this == &(*it)->getEngine()); assert(this == &(*it)->getEngine());
if ((*it)->m_destroyed) if ((*it)->m_destroyed)
return m_activeSequencers.begin(); return m_activeSequencers.begin();
@ -118,13 +102,10 @@ Engine::_destroySequencer(std::list<ObjToken<Sequencer>>::iterator it)
return m_activeSequencers.erase(it); return m_activeSequencers.erase(it);
} }
void Engine::_bringOutYourDead() void Engine::_bringOutYourDead() {
{ for (auto it = m_activeEmitters.begin(); it != m_activeEmitters.end();) {
for (auto it = m_activeEmitters.begin(); it != m_activeEmitters.end();)
{
Emitter* emitter = it->get(); Emitter* emitter = it->get();
if (emitter->getVoice()->_isRecursivelyDead()) if (emitter->getVoice()->_isRecursivelyDead()) {
{
emitter->_destroy(); emitter->_destroy();
it = m_activeEmitters.erase(it); it = m_activeEmitters.erase(it);
continue; continue;
@ -132,24 +113,20 @@ void Engine::_bringOutYourDead()
++it; ++it;
} }
for (auto it = m_activeVoices.begin(); it != m_activeVoices.end();) for (auto it = m_activeVoices.begin(); it != m_activeVoices.end();) {
{
Voice* vox = it->get(); Voice* vox = it->get();
vox->_bringOutYourDead(); vox->_bringOutYourDead();
if (vox->_isRecursivelyDead()) if (vox->_isRecursivelyDead()) {
{
it = _destroyVoice(it); it = _destroyVoice(it);
continue; continue;
} }
++it; ++it;
} }
for (auto it = m_activeSequencers.begin(); it != m_activeSequencers.end();) for (auto it = m_activeSequencers.begin(); it != m_activeSequencers.end();) {
{
Sequencer* seq = it->get(); Sequencer* seq = it->get();
seq->_bringOutYourDead(); seq->_bringOutYourDead();
if (seq->m_state == SequencerState::Dead) if (seq->m_state == SequencerState::Dead) {
{
it = _destroySequencer(it); it = _destroySequencer(it);
continue; continue;
} }
@ -157,8 +134,7 @@ void Engine::_bringOutYourDead()
} }
} }
void Engine::_on5MsInterval(IBackendVoiceAllocator& engine, double dt) void Engine::_on5MsInterval(IBackendVoiceAllocator& engine, double dt) {
{
m_channelSet = engine.getAvailableSet(); m_channelSet = engine.getAvailableSet();
if (m_midiReader) if (m_midiReader)
m_midiReader->pumpReader(dt); m_midiReader->pumpReader(dt);
@ -170,8 +146,7 @@ void Engine::_on5MsInterval(IBackendVoiceAllocator& engine, double dt)
listener->m_dirty = false; listener->m_dirty = false;
} }
void Engine::_onPumpCycleComplete(IBackendVoiceAllocator& engine) void Engine::_onPumpCycleComplete(IBackendVoiceAllocator& engine) {
{
_bringOutYourDead(); _bringOutYourDead();
/* Determine lowest available free vid */ /* Determine lowest available free vid */
@ -181,14 +156,12 @@ void Engine::_onPumpCycleComplete(IBackendVoiceAllocator& engine)
m_nextVid = maxVid + 1; m_nextVid = maxVid + 1;
} }
AudioGroup* Engine::_addAudioGroup(const AudioGroupData& data, std::unique_ptr<AudioGroup>&& grp) AudioGroup* Engine::_addAudioGroup(const AudioGroupData& data, std::unique_ptr<AudioGroup>&& grp) {
{
AudioGroup* ret = grp.get(); AudioGroup* ret = grp.get();
m_audioGroups.emplace(std::make_pair(&data, std::move(grp))); m_audioGroups.emplace(std::make_pair(&data, std::move(grp)));
/* setup SFX index for contained objects */ /* setup SFX index for contained objects */
for (const auto& grp : ret->getProj().sfxGroups()) for (const auto& grp : ret->getProj().sfxGroups()) {
{
const SFXGroupIndex& sfxGroup = *grp.second; const SFXGroupIndex& sfxGroup = *grp.second;
m_sfxLookup.reserve(m_sfxLookup.size() + sfxGroup.m_sfxEntries.size()); m_sfxLookup.reserve(m_sfxLookup.size() + sfxGroup.m_sfxEntries.size());
for (const auto& ent : sfxGroup.m_sfxEntries) for (const auto& ent : sfxGroup.m_sfxEntries)
@ -199,26 +172,22 @@ AudioGroup* Engine::_addAudioGroup(const AudioGroupData& data, std::unique_ptr<A
} }
/** Add GameCube audio group data pointers to engine; must remain resident! */ /** Add GameCube audio group data pointers to engine; must remain resident! */
const AudioGroup* Engine::addAudioGroup(const AudioGroupData& data) const AudioGroup* Engine::addAudioGroup(const AudioGroupData& data) {
{
removeAudioGroup(data); removeAudioGroup(data);
return _addAudioGroup(data, std::make_unique<AudioGroup>(data)); return _addAudioGroup(data, std::make_unique<AudioGroup>(data));
} }
/** Remove audio group from engine */ /** Remove audio group from engine */
void Engine::removeAudioGroup(const AudioGroupData& data) void Engine::removeAudioGroup(const AudioGroupData& data) {
{
auto search = m_audioGroups.find(&data); auto search = m_audioGroups.find(&data);
if (search == m_audioGroups.cend()) if (search == m_audioGroups.cend())
return; return;
AudioGroup* grp = search->second.get(); AudioGroup* grp = search->second.get();
/* Destroy runtime entities within group */ /* Destroy runtime entities within group */
for (auto it = m_activeVoices.begin(); it != m_activeVoices.end();) for (auto it = m_activeVoices.begin(); it != m_activeVoices.end();) {
{
Voice* vox = it->get(); Voice* vox = it->get();
if (&vox->getAudioGroup() == grp) if (&vox->getAudioGroup() == grp) {
{
vox->_destroy(); vox->_destroy();
it = m_activeVoices.erase(it); it = m_activeVoices.erase(it);
continue; continue;
@ -226,11 +195,9 @@ void Engine::removeAudioGroup(const AudioGroupData& data)
++it; ++it;
} }
for (auto it = m_activeEmitters.begin(); it != m_activeEmitters.end();) for (auto it = m_activeEmitters.begin(); it != m_activeEmitters.end();) {
{
Emitter* emitter = it->get(); Emitter* emitter = it->get();
if (&emitter->getAudioGroup() == grp) if (&emitter->getAudioGroup() == grp) {
{
emitter->_destroy(); emitter->_destroy();
it = m_activeEmitters.erase(it); it = m_activeEmitters.erase(it);
continue; continue;
@ -238,11 +205,9 @@ void Engine::removeAudioGroup(const AudioGroupData& data)
++it; ++it;
} }
for (auto it = m_activeSequencers.begin(); it != m_activeSequencers.end();) for (auto it = m_activeSequencers.begin(); it != m_activeSequencers.end();) {
{
Sequencer* seq = it->get(); Sequencer* seq = it->get();
if (&seq->getAudioGroup() == grp) if (&seq->getAudioGroup() == grp) {
{
seq->_destroy(); seq->_destroy();
it = m_activeSequencers.erase(it); it = m_activeSequencers.erase(it);
continue; continue;
@ -251,8 +216,7 @@ void Engine::removeAudioGroup(const AudioGroupData& data)
} }
/* teardown SFX index for contained objects */ /* teardown SFX index for contained objects */
for (const auto& pair : grp->getProj().sfxGroups()) for (const auto& pair : grp->getProj().sfxGroups()) {
{
const SFXGroupIndex& sfxGroup = *pair.second; const SFXGroupIndex& sfxGroup = *pair.second;
for (const auto& pair : sfxGroup.m_sfxEntries) for (const auto& pair : sfxGroup.m_sfxEntries)
m_sfxLookup.erase(pair.first); m_sfxLookup.erase(pair.first);
@ -265,8 +229,7 @@ void Engine::removeAudioGroup(const AudioGroupData& data)
ObjToken<Studio> Engine::addStudio(bool mainOut) { return _allocateStudio(mainOut); } ObjToken<Studio> Engine::addStudio(bool mainOut) { return _allocateStudio(mainOut); }
/** Start soundFX playing from loaded audio groups */ /** Start soundFX playing from loaded audio groups */
ObjToken<Voice> Engine::fxStart(SFXId sfxId, float vol, float pan, ObjToken<Studio> smx) ObjToken<Voice> Engine::fxStart(SFXId sfxId, float vol, float pan, ObjToken<Studio> smx) {
{
auto search = m_sfxLookup.find(sfxId); auto search = m_sfxLookup.find(sfxId);
if (search == m_sfxLookup.end()) if (search == m_sfxLookup.end())
return {}; return {};
@ -279,8 +242,7 @@ ObjToken<Voice> Engine::fxStart(SFXId sfxId, float vol, float pan, ObjToken<Stud
std::list<ObjToken<Voice>>::iterator ret = std::list<ObjToken<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)->loadPageObject(entry->objId, 1000.f, entry->defKey, entry->defVel, 0)) if (!(*ret)->loadPageObject(entry->objId, 1000.f, entry->defKey, entry->defVel, 0)) {
{
_destroyVoice(ret); _destroyVoice(ret);
return {}; return {};
} }
@ -293,20 +255,16 @@ ObjToken<Voice> Engine::fxStart(SFXId sfxId, float vol, float pan, ObjToken<Stud
} }
/** Start soundFX playing from explicit group data (for editor use) */ /** Start soundFX playing from explicit group data (for editor use) */
ObjToken<Voice> Engine::fxStart(const AudioGroup* group, GroupId groupId, SFXId sfxId, float vol, float pan, ObjToken<Studio> smx) ObjToken<Voice> Engine::fxStart(const AudioGroup* group, GroupId groupId, SFXId sfxId, float vol, float pan,
{ ObjToken<Studio> smx) {
const SFXGroupIndex* sfxIdx = group->getProj().getSFXGroupIndex(groupId); const SFXGroupIndex* sfxIdx = group->getProj().getSFXGroupIndex(groupId);
if (sfxIdx) if (sfxIdx) {
{
auto search = sfxIdx->m_sfxEntries.find(sfxId); auto search = sfxIdx->m_sfxEntries.find(sfxId);
if (search != sfxIdx->m_sfxEntries.cend()) if (search != sfxIdx->m_sfxEntries.cend()) {
{ std::list<ObjToken<Voice>>::iterator ret = _allocateVoice(*group, groupId, NativeSampleRate, true, false, smx);
std::list<ObjToken<Voice>>::iterator ret =
_allocateVoice(*group, groupId, NativeSampleRate, true, false, smx);
auto& entry = search->second; auto& entry = search->second;
if (!(*ret)->loadPageObject(entry.objId, 1000.f, entry.defKey, entry.defVel, 0)) if (!(*ret)->loadPageObject(entry.objId, 1000.f, entry.defKey, entry.defVel, 0)) {
{
_destroyVoice(ret); _destroyVoice(ret);
return {}; return {};
} }
@ -323,17 +281,14 @@ ObjToken<Voice> Engine::fxStart(const AudioGroup* group, GroupId groupId, SFXId
} }
/** Start SoundMacro node playing directly (for editor use) */ /** Start SoundMacro node playing directly (for editor use) */
ObjToken<Voice> Engine::macroStart(const AudioGroup* group, SoundMacroId id, uint8_t key, uint8_t vel, ObjToken<Voice> Engine::macroStart(const AudioGroup* group, SoundMacroId id, uint8_t key, uint8_t vel, uint8_t mod,
uint8_t mod, ObjToken<Studio> smx) ObjToken<Studio> smx) {
{
if (!group) if (!group)
return {}; return {};
std::list<ObjToken<Voice>>::iterator ret = std::list<ObjToken<Voice>>::iterator ret = _allocateVoice(*group, {}, NativeSampleRate, true, false, smx);
_allocateVoice(*group, {}, NativeSampleRate, true, false, smx);
if (!(*ret)->loadMacroObject(id, 0, 1000.f, key, vel, mod)) if (!(*ret)->loadMacroObject(id, 0, 1000.f, key, vel, mod)) {
{
_destroyVoice(ret); _destroyVoice(ret);
return {}; return {};
} }
@ -344,17 +299,14 @@ ObjToken<Voice> Engine::macroStart(const AudioGroup* group, SoundMacroId id, uin
} }
/** Start SoundMacro object playing directly (for editor use) */ /** Start SoundMacro object playing directly (for editor use) */
ObjToken<Voice> Engine::macroStart(const AudioGroup* group, const SoundMacro* macro, uint8_t key, ObjToken<Voice> Engine::macroStart(const AudioGroup* group, const SoundMacro* macro, uint8_t key, uint8_t vel,
uint8_t vel, uint8_t mod, ObjToken<Studio> smx) uint8_t mod, ObjToken<Studio> smx) {
{
if (!group) if (!group)
return {}; return {};
std::list<ObjToken<Voice>>::iterator ret = std::list<ObjToken<Voice>>::iterator ret = _allocateVoice(*group, {}, NativeSampleRate, true, false, smx);
_allocateVoice(*group, {}, NativeSampleRate, true, false, smx);
if (!(*ret)->loadMacroObject(macro, 0, 1000.f, key, vel, mod)) if (!(*ret)->loadMacroObject(macro, 0, 1000.f, key, vel, mod)) {
{
_destroyVoice(ret); _destroyVoice(ret);
return {}; return {};
} }
@ -365,17 +317,14 @@ ObjToken<Voice> Engine::macroStart(const AudioGroup* group, const SoundMacro* ma
} }
/** Start PageObject node playing directly (for editor use) */ /** Start PageObject node playing directly (for editor use) */
ObjToken<Voice> Engine::pageObjectStart(const AudioGroup* group, ObjectId id, uint8_t key, ObjToken<Voice> Engine::pageObjectStart(const AudioGroup* group, ObjectId id, uint8_t key, uint8_t vel, uint8_t mod,
uint8_t vel, uint8_t mod, ObjToken<Studio> smx) ObjToken<Studio> smx) {
{
if (!group) if (!group)
return {}; return {};
std::list<ObjToken<Voice>>::iterator ret = std::list<ObjToken<Voice>>::iterator ret = _allocateVoice(*group, {}, NativeSampleRate, true, false, smx);
_allocateVoice(*group, {}, NativeSampleRate, true, false, smx);
if (!(*ret)->loadPageObject(id, 1000.f, key, vel, mod)) if (!(*ret)->loadPageObject(id, 1000.f, key, vel, mod)) {
{
_destroyVoice(ret); _destroyVoice(ret);
return {}; return {};
} }
@ -384,9 +333,8 @@ ObjToken<Voice> Engine::pageObjectStart(const AudioGroup* group, ObjectId id, ui
} }
/** Start soundFX playing from loaded audio groups, attach to positional emitter */ /** Start soundFX playing from loaded audio groups, attach to positional emitter */
ObjToken<Emitter> Engine::addEmitter(const float* pos, const float* dir, float maxDist, float falloff, ObjToken<Emitter> Engine::addEmitter(const float* pos, const float* dir, float maxDist, float falloff, SFXId sfxId,
SFXId sfxId, float minVol, float maxVol, bool doppler, ObjToken<Studio> smx) float minVol, float maxVol, bool doppler, ObjToken<Studio> smx) {
{
auto search = m_sfxLookup.find(sfxId); auto search = m_sfxLookup.find(sfxId);
if (search == m_sfxLookup.end()) if (search == m_sfxLookup.end())
return {}; return {};
@ -399,8 +347,7 @@ ObjToken<Emitter> Engine::addEmitter(const float* pos, const float* dir, float m
std::list<ObjToken<Voice>>::iterator vox = std::list<ObjToken<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)->loadPageObject(entry->objId, 1000.f, entry->defKey, entry->defVel, 0)) if (!(*vox)->loadPageObject(entry->objId, 1000.f, entry->defKey, entry->defVel, 0)) {
{
_destroyVoice(vox); _destroyVoice(vox);
return {}; return {};
} }
@ -418,22 +365,18 @@ ObjToken<Emitter> Engine::addEmitter(const float* pos, const float* dir, float m
/** Build listener and add to engine's listener list */ /** Build listener and add to engine's listener list */
ObjToken<Listener> Engine::addListener(const float* pos, const float* dir, const float* heading, const float* up, ObjToken<Listener> Engine::addListener(const float* pos, const float* dir, const float* heading, const float* up,
float frontDiff, float backDiff, float soundSpeed, float volume) float frontDiff, float backDiff, float soundSpeed, float volume) {
{ auto listenerIt =
auto listenerIt = m_activeListeners.emplace(m_activeListeners.end(), m_activeListeners.emplace(m_activeListeners.end(), MakeObj<Listener>(volume, frontDiff, backDiff, soundSpeed));
MakeObj<Listener>(volume, frontDiff, backDiff, soundSpeed));
Listener& ret = *(*listenerIt); Listener& ret = *(*listenerIt);
ret.setVectors(pos, dir, heading, up); ret.setVectors(pos, dir, heading, up);
return *listenerIt; return *listenerIt;
} }
/** Remove listener from engine's listener list */ /** Remove listener from engine's listener list */
void Engine::removeListener(Listener* listener) void Engine::removeListener(Listener* listener) {
{ for (auto it = m_activeListeners.begin(); it != m_activeListeners.end(); ++it) {
for (auto it = m_activeListeners.begin() ; it != m_activeListeners.end() ; ++it) if (it->get() == listener) {
{
if (it->get() == listener)
{
m_activeListeners.erase(it); m_activeListeners.erase(it);
return; return;
} }
@ -441,11 +384,10 @@ void Engine::removeListener(Listener* listener)
} }
/** Start song playing from loaded audio groups */ /** Start song playing from loaded audio groups */
ObjToken<Sequencer> Engine::seqPlay(GroupId groupId, SongId songId, const unsigned char* arrData, bool loop, ObjToken<Studio> smx) ObjToken<Sequencer> Engine::seqPlay(GroupId groupId, SongId songId, const unsigned char* arrData, bool loop,
{ ObjToken<Studio> smx) {
std::pair<AudioGroup*, const SongGroupIndex*> songGrp = _findSongGroup(groupId); std::pair<AudioGroup*, const SongGroupIndex*> songGrp = _findSongGroup(groupId);
if (songGrp.second) if (songGrp.second) {
{
std::list<ObjToken<Sequencer>>::iterator ret = _allocateSequencer(*songGrp.first, groupId, songId, smx); std::list<ObjToken<Sequencer>>::iterator ret = _allocateSequencer(*songGrp.first, groupId, songId, smx);
if (!*ret) if (!*ret)
return {}; return {};
@ -456,8 +398,7 @@ ObjToken<Sequencer> Engine::seqPlay(GroupId groupId, SongId songId, const unsign
} }
std::pair<AudioGroup*, const SFXGroupIndex*> sfxGrp = _findSFXGroup(groupId); std::pair<AudioGroup*, const SFXGroupIndex*> sfxGrp = _findSFXGroup(groupId);
if (sfxGrp.second) if (sfxGrp.second) {
{
std::list<ObjToken<Sequencer>>::iterator ret = _allocateSequencer(*sfxGrp.first, groupId, songId, smx); std::list<ObjToken<Sequencer>>::iterator ret = _allocateSequencer(*sfxGrp.first, groupId, songId, smx);
if (!*ret) if (!*ret)
return {}; return {};
@ -468,11 +409,9 @@ ObjToken<Sequencer> Engine::seqPlay(GroupId groupId, SongId songId, const unsign
} }
ObjToken<Sequencer> Engine::seqPlay(const AudioGroup* group, GroupId groupId, SongId songId, ObjToken<Sequencer> Engine::seqPlay(const AudioGroup* group, GroupId groupId, SongId songId,
const unsigned char* arrData, bool loop, ObjToken<Studio> smx) const unsigned char* arrData, bool loop, ObjToken<Studio> smx) {
{
const SongGroupIndex* sgIdx = group->getProj().getSongGroupIndex(groupId); const SongGroupIndex* sgIdx = group->getProj().getSongGroupIndex(groupId);
if (sgIdx) if (sgIdx) {
{
std::list<ObjToken<Sequencer>>::iterator ret = _allocateSequencer(*group, groupId, songId, smx); std::list<ObjToken<Sequencer>>::iterator ret = _allocateSequencer(*group, groupId, songId, smx);
if (!*ret) if (!*ret)
return {}; return {};
@ -483,8 +422,7 @@ ObjToken<Sequencer> Engine::seqPlay(const AudioGroup* group, GroupId groupId, So
} }
const SFXGroupIndex* sfxIdx = group->getProj().getSFXGroupIndex(groupId); const SFXGroupIndex* sfxIdx = group->getProj().getSFXGroupIndex(groupId);
if (sfxIdx) if (sfxIdx) {
{
std::list<ObjToken<Sequencer>>::iterator ret = _allocateSequencer(*group, groupId, songId, smx); std::list<ObjToken<Sequencer>>::iterator ret = _allocateSequencer(*group, groupId, songId, smx);
if (!*ret) if (!*ret)
return {}; return {};
@ -495,23 +433,17 @@ ObjToken<Sequencer> Engine::seqPlay(const AudioGroup* group, GroupId groupId, So
} }
/** Set total volume of engine */ /** Set total volume of engine */
void Engine::setVolume(float vol) void Engine::setVolume(float vol) { m_masterVolume = vol; }
{
m_masterVolume = vol;
}
/** Find voice from VoiceId */ /** Find voice from VoiceId */
ObjToken<Voice> Engine::findVoice(int vid) ObjToken<Voice> Engine::findVoice(int vid) {
{ for (ObjToken<Voice>& vox : m_activeVoices) {
for (ObjToken<Voice>& vox : m_activeVoices)
{
ObjToken<Voice> ret = vox->_findVoice(vid, vox); ObjToken<Voice> ret = vox->_findVoice(vid, vox);
if (ret) if (ret)
return ret; return ret;
} }
for (ObjToken<Sequencer>& seq : m_activeSequencers) for (ObjToken<Sequencer>& seq : m_activeSequencers) {
{
ObjToken<Voice> ret = seq->findVoice(vid); ObjToken<Voice> ret = seq->findVoice(vid);
if (ret) if (ret)
return ret; return ret;
@ -521,15 +453,11 @@ ObjToken<Voice> Engine::findVoice(int vid)
} }
/** Stop all voices in `kg`, stops immediately (no KeyOff) when `flag` set */ /** Stop all voices in `kg`, stops immediately (no KeyOff) when `flag` set */
void Engine::killKeygroup(uint8_t kg, bool now) void Engine::killKeygroup(uint8_t kg, bool now) {
{ for (auto it = m_activeVoices.begin(); it != m_activeVoices.end();) {
for (auto it = m_activeVoices.begin(); it != m_activeVoices.end();)
{
Voice* vox = it->get(); Voice* vox = it->get();
if (vox->m_keygroup == kg) if (vox->m_keygroup == kg) {
{ if (now) {
if (now)
{
it = _destroyVoice(it); it = _destroyVoice(it);
continue; continue;
} }
@ -543,10 +471,8 @@ void Engine::killKeygroup(uint8_t kg, bool now)
} }
/** Send all voices using `macroId` the message `val` */ /** Send all voices using `macroId` the message `val` */
void Engine::sendMacroMessage(ObjectId macroId, int32_t val) void Engine::sendMacroMessage(ObjectId macroId, int32_t val) {
{ for (auto it = m_activeVoices.begin(); it != m_activeVoices.end(); ++it) {
for (auto it = m_activeVoices.begin(); it != m_activeVoices.end(); ++it)
{
Voice* vox = it->get(); Voice* vox = it->get();
if (vox->getObjectId() == macroId) if (vox->getObjectId() == macroId)
vox->message(val); vox->message(val);
@ -556,11 +482,10 @@ void Engine::sendMacroMessage(ObjectId macroId, int32_t val)
seq->sendMacroMessage(macroId, val); seq->sendMacroMessage(macroId, val);
} }
size_t Engine::getNumTotalActiveVoices() const size_t Engine::getNumTotalActiveVoices() const {
{
size_t ret = 0; size_t ret = 0;
for (const auto& vox : m_activeVoices) for (const auto& vox : m_activeVoices)
ret += vox->getTotalVoices(); ret += vox->getTotalVoices();
return ret; return ret;
} }
} } // namespace amuse

Some files were not shown because too many files have changed in this diff Show More