Working Studio implementation

This commit is contained in:
Jack Andersen 2016-07-13 18:54:46 -10:00
parent d3d5595422
commit 2dcb9dd1c7
68 changed files with 1981 additions and 2098 deletions

31
.clang-format Normal file
View File

@ -0,0 +1,31 @@
---
IndentWidth: 4
ColumnLimit: 120
UseTab: Never
---
Language: Cpp
DerivePointerAlignment: false
PointerAlignment: Left
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false
BreakBeforeBraces: Allman
IndentCaseLabels: false
AllowShortBlocksOnASingleLine: true
AlignOperands: true
AlignTrailingComments: true
AlwaysBreakBeforeMultilineStrings: true
AlwaysBreakTemplateDeclarations: true
BreakConstructorInitializersBeforeComma: true
BreakStringLiterals: true
AlwaysBreakAfterReturnType: None
AlwaysBreakAfterDefinitionReturnType: None
AllowShortFunctionsOnASingleLine: All
Cpp11BracedListStyle: true
NamespaceIndentation: None
ReflowComments: true
BinPackArguments: true
BinPackParameters: true
SortIncludes: false
AccessModifierOffset: -4
ConstructorInitializerIndentWidth: 0
ConstructorInitializerAllOnOneLineOrOnePerLine: true

View File

@ -42,9 +42,13 @@ struct AudioGroupDataCollection
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;
@ -61,7 +65,10 @@ struct AudioGroupDataCollection
bool loadMeta(AudioGroupFilePresenter* presenter); bool loadMeta(AudioGroupFilePresenter* presenter);
AudioGroupDataCollection(const std::string& name, NSURL* proj, NSURL* pool, NSURL* sdir, NSURL* samp, NSURL* meta); AudioGroupDataCollection(const std::string& name, NSURL* proj, NSURL* pool, NSURL* sdir, NSURL* samp, NSURL* meta);
bool isDataComplete() const {return m_projData.size() && m_poolData.size() && m_sdirData.size() && m_sampData.size() && m_metaData;} bool isDataComplete() const
{
return m_projData.size() && m_poolData.size() && m_sdirData.size() && m_sampData.size() && m_metaData;
}
bool _attemptLoad(AudioGroupFilePresenter* presenter); bool _attemptLoad(AudioGroupFilePresenter* presenter);
bool _indexData(AudioGroupFilePresenter* presenter); bool _indexData(AudioGroupFilePresenter* presenter);
@ -119,8 +126,10 @@ struct AudioGroupCollection
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)initWithName:(NSAttributedString*)name samp:(const std::pair<amuse::AudioGroupSampleDirectory::Entry, - (id)
amuse::AudioGroupSampleDirectory::ADPCMParms>*)sample; initWithName:(NSAttributedString*)name
samp:(const std::pair<amuse::AudioGroupSampleDirectory::Entry, amuse::AudioGroupSampleDirectory::ADPCMParms>*)
sample;
@end @end
@interface AudioGroupToken : NSObject @interface AudioGroupToken : NSObject
@ -149,7 +158,8 @@ struct AudioGroupCollection
std::vector<AudioGroupSampleToken*> m_sampleTableData; std::vector<AudioGroupSampleToken*> m_sampleTableData;
} }
- (id)initWithAudioGroupClient:(id<AudioGroupClient>)client; - (id)initWithAudioGroupClient:(id<AudioGroupClient>)client;
- (BOOL)addCollectionName:(std::string&&)name items:(std::vector<std::pair<std::string, amuse::IntrusiveAudioGroupData>>&&)collection; - (BOOL)addCollectionName:(std::string&&)name
items:(std::vector<std::pair<std::string, amuse::IntrusiveAudioGroupData>>&&)collection;
- (void)update; - (void)update;
- (void)resetIterators; - (void)resetIterators;
- (void)setSearchFilter:(NSString*)str; - (void)setSearchFilter:(NSString*)str;

View File

@ -27,12 +27,10 @@ namespace amuse
class AudioUnitBackendVoiceAllocator : public BooBackendVoiceAllocator class AudioUnitBackendVoiceAllocator : public BooBackendVoiceAllocator
{ {
public: public:
AudioUnitBackendVoiceAllocator(boo::IAudioVoiceEngine& booEngine) AudioUnitBackendVoiceAllocator(boo::IAudioVoiceEngine& booEngine) : BooBackendVoiceAllocator(booEngine) {}
: BooBackendVoiceAllocator(booEngine) {}
}; };
void RegisterAudioUnit(); void RegisterAudioUnit();
} }
@interface AmuseAudioUnit : AUAudioUnit <AudioGroupClient> @interface AmuseAudioUnit : AUAudioUnit <AudioGroupClient>

View File

@ -20,10 +20,9 @@ set(SOURCES
lib/SongConverter.cpp lib/SongConverter.cpp
lib/SongState.cpp lib/SongState.cpp
lib/Voice.cpp lib/Voice.cpp
lib/VolumeLUT.cpp lib/VolumeLUT.c
lib/Submix.cpp lib/Submix.cpp
lib/Studio.cpp lib/Studio.cpp
lib/EffectBase.cpp
lib/EffectReverb.cpp lib/EffectReverb.cpp
lib/EffectChorus.cpp lib/EffectChorus.cpp
lib/EffectDelay.cpp lib/EffectDelay.cpp

View File

@ -6,42 +6,153 @@
namespace amuse namespace amuse
{ {
static const wchar_t *const GMNames[128] = static const wchar_t* const GMNames[128] = {L"Acoustic Grand Piano",
{ L"Bright Acoustic Piano",
L"Acoustic Grand Piano", L"Bright Acoustic Piano", L"Electric Grand Piano", L"Honky-tonk Piano", L"Rhodes Piano", L"Chorused Piano", L"Electric Grand Piano",
L"Harpsichord", L"Clavinet", L"Celesta", L"Glockenspiel", L"Music Box", L"Vibraphone", L"Marimba", L"Xylophone", L"Tubular Bells", L"Dulcimer", L"Honky-tonk Piano",
L"Drawbar Organ", L"Percussive Organ", L"Rock Organ", L"Church Organ", L"Reed Organ", L"Accordion", L"Harmonica", L"Tango Accordion", L"Rhodes Piano",
L"Acoustic Guitar (nylon)", L"Acoustic Guitar (steel)", L"Electric Guitar (jazz)", L"Electric Guitar (clean)", L"Electric Guitar (muted)", L"Chorused Piano",
L"Overdriven Guitar", L"Distortion Guitar", L"Guitar Harmonics", L"Acoustic Bass", L"Electric Bass (finger)", L"Electric Bass (pick)", L"Harpsichord",
L"Fretless Bass", L"Slap Bass 1", L"Slap Bass 2", L"Synth Bass 1", L"Synth Bass 2", L"Violin", L"Viola", L"Cello", L"Contrabass", L"Clavinet",
L"Tremelo Strings", L"Pizzicato Strings", L"Orchestral Harp", L"Timpani", L"String Ensemble 1", L"String Ensemble 2", L"SynthStrings 1", L"Celesta",
L"SynthStrings 2", L"Choir Aahs", L"Voice Oohs", L"Synth Voice", L"Orchestra Hit", L"Trumpet", L"Trombone", L"Tuba", L"Muted Trumpet", L"Glockenspiel",
L"French Horn", L"Brass Section", L"Synth Brass 1", L"Synth Brass 2", L"Soprano Sax", L"Alto Sax", L"Tenor Sax", L"Baritone Sax", L"Music Box",
L"Oboe", L"English Horn", L"Bassoon", L"Clarinet", L"Piccolo", L"Flute", L"Recorder", L"Pan Flute", L"Bottle Blow", L"Shakuhachi", L"Whistle", L"Vibraphone",
L"Ocarina", L"Lead 1 (square)", L"Lead 2 (sawtooth)", L"Lead 3 (calliope lead)", L"Lead 4 (chiff lead)", L"Lead 5 (charang)", L"Marimba",
L"Lead 6 (voice)", L"Lead 7 (fifths)", L"Lead 8 (bass + lead)", L"Pad 1 (new age)", L"Pad 2 (warm)", L"Pad 3 (polysynth)", L"Pad 4 (choir)", L"Xylophone",
L"Pad 5 (bowed)", L"Pad 6 (metallic)", L"Pad 7 (halo)", L"Pad 8 (sweep)", L"FX 1 (rain)", L"FX 2 (soundtrack)", L"FX 3 (crystal)", L"Tubular Bells",
L"FX 4 (atmosphere)", L"FX 5 (brightness)", L"FX 6 (goblins)", L"FX 7 (echoes)", L"FX 8 (sci-fi)", L"Sitar", L"Banjo", L"Shamisen", L"Koto", L"Dulcimer",
L"Kalimba", L"Bagpipe", L"Fiddle", L"Shanai", L"Tinkle Bell", L"Agogo", L"Steel Drums", L"Woodblock", L"Taiko Drum", L"Melodic Tom", L"Drawbar Organ",
L"Synth Drum", L"Reverse Cymbal", L"Guitar Fret Noise", L"Breath Noise", L"Seashore", L"Bird Tweet", L"Telephone Ring", L"Helicopter", L"Percussive Organ",
L"Applause", L"Gunshot" L"Rock Organ",
}; L"Church Organ",
L"Reed Organ",
L"Accordion",
L"Harmonica",
L"Tango Accordion",
L"Acoustic Guitar (nylon)",
L"Acoustic Guitar (steel)",
L"Electric Guitar (jazz)",
L"Electric Guitar (clean)",
L"Electric Guitar (muted)",
L"Overdriven Guitar",
L"Distortion Guitar",
L"Guitar Harmonics",
L"Acoustic Bass",
L"Electric Bass (finger)",
L"Electric Bass (pick)",
L"Fretless Bass",
L"Slap Bass 1",
L"Slap Bass 2",
L"Synth Bass 1",
L"Synth Bass 2",
L"Violin",
L"Viola",
L"Cello",
L"Contrabass",
L"Tremelo Strings",
L"Pizzicato Strings",
L"Orchestral Harp",
L"Timpani",
L"String Ensemble 1",
L"String Ensemble 2",
L"SynthStrings 1",
L"SynthStrings 2",
L"Choir Aahs",
L"Voice Oohs",
L"Synth Voice",
L"Orchestra Hit",
L"Trumpet",
L"Trombone",
L"Tuba",
L"Muted Trumpet",
L"French Horn",
L"Brass Section",
L"Synth Brass 1",
L"Synth Brass 2",
L"Soprano Sax",
L"Alto Sax",
L"Tenor Sax",
L"Baritone Sax",
L"Oboe",
L"English Horn",
L"Bassoon",
L"Clarinet",
L"Piccolo",
L"Flute",
L"Recorder",
L"Pan Flute",
L"Bottle Blow",
L"Shakuhachi",
L"Whistle",
L"Ocarina",
L"Lead 1 (square)",
L"Lead 2 (sawtooth)",
L"Lead 3 (calliope lead)",
L"Lead 4 (chiff lead)",
L"Lead 5 (charang)",
L"Lead 6 (voice)",
L"Lead 7 (fifths)",
L"Lead 8 (bass + lead)",
L"Pad 1 (new age)",
L"Pad 2 (warm)",
L"Pad 3 (polysynth)",
L"Pad 4 (choir)",
L"Pad 5 (bowed)",
L"Pad 6 (metallic)",
L"Pad 7 (halo)",
L"Pad 8 (sweep)",
L"FX 1 (rain)",
L"FX 2 (soundtrack)",
L"FX 3 (crystal)",
L"FX 4 (atmosphere)",
L"FX 5 (brightness)",
L"FX 6 (goblins)",
L"FX 7 (echoes)",
L"FX 8 (sci-fi)",
L"Sitar",
L"Banjo",
L"Shamisen",
L"Koto",
L"Kalimba",
L"Bagpipe",
L"Fiddle",
L"Shanai",
L"Tinkle Bell",
L"Agogo",
L"Steel Drums",
L"Woodblock",
L"Taiko Drum",
L"Melodic Tom",
L"Synth Drum",
L"Reverse Cymbal",
L"Guitar Fret Noise",
L"Breath Noise",
L"Seashore",
L"Bird Tweet",
L"Telephone Ring",
L"Helicopter",
L"Applause",
L"Gunshot"};
static const wchar_t *const GMPercNames[128] = static const wchar_t* const GMPercNames[128] = {
{ nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr, L"Acoustic Bass Drum", L"Bass Drum 1", L"Side Stick", nullptr, nullptr, nullptr, nullptr, nullptr,
L"Acoustic Snare", L"Hand Clap", L"Electric Snare", L"Low Floor Tom", L"Closed Hi-Hat", nullptr, nullptr, nullptr, nullptr, nullptr,
L"High Floor Tom", L"Pedal Hi-Hat", L"Low Tom", L"Open Hi-Hat", L"Low-Mid Tom", L"Hi-Mid Tom", nullptr, nullptr, nullptr, nullptr, L"Acoustic Bass Drum",
L"Crash Cymbal 1", L"High Tom", L"Ride Cymbal 1", L"Chinese Cymbal", L"Ride Bell", L"Tambourine", L"Bass Drum 1", L"Side Stick", L"Acoustic Snare", L"Hand Clap", L"Electric Snare",
L"Splash Cymbal", L"Cowbell", L"Crash Cymbal 2", L"Vibraslap", L"Ride Cymbal 2", L"Hi Bongo", L"Low Floor Tom", L"Closed Hi-Hat", L"High Floor Tom", L"Pedal Hi-Hat", L"Low Tom",
L"Low Bongo", L"Mute Hi Conga", L"Open Hi Conga", L"Low Conga", L"High Timbale", L"Low Timbale", L"Open Hi-Hat", L"Low-Mid Tom", L"Hi-Mid Tom", L"Crash Cymbal 1", L"High Tom",
L"High Agogo", L"Low Agogo", L"Cabasa", L"Maracas", L"Short Whistle", L"Long Whistle", L"Short Guiro", L"Ride Cymbal 1", L"Chinese Cymbal", L"Ride Bell", L"Tambourine", L"Splash Cymbal",
L"Long Guiro", L"Claves", L"Hi Wood Block", L"Low Wood Block", L"Mute Cuica", L"Open Cuica", L"Cowbell", L"Crash Cymbal 2", L"Vibraslap", L"Ride Cymbal 2", L"Hi Bongo",
L"Mute Triangle", L"Open Triangle" L"Low Bongo", L"Mute Hi Conga", L"Open Hi Conga", L"Low Conga", L"High Timbale",
}; L"Low Timbale", L"High Agogo", L"Low Agogo", L"Cabasa", L"Maracas",
L"Short Whistle", L"Long Whistle", L"Short Guiro", L"Long Guiro", L"Claves",
L"Hi Wood Block", L"Low Wood Block", L"Mute Cuica", L"Open Cuica", L"Mute Triangle",
L"Open Triangle"};
bool AudioGroupDataCollection::loadProj() bool AudioGroupDataCollection::loadProj()
{ {
@ -109,7 +220,6 @@ bool AudioGroupDataCollection::loadMeta()
AudioGroupDataCollection::AudioGroupDataCollection(const std::wstring& path, const std::wstring& name) AudioGroupDataCollection::AudioGroupDataCollection(const std::wstring& path, const std::wstring& name)
: m_path(path), m_name(name) : m_path(path), m_name(name)
{ {
} }
bool AudioGroupDataCollection::_attemptLoad() bool AudioGroupDataCollection::_attemptLoad()
@ -136,24 +246,18 @@ bool AudioGroupDataCollection::_indexData()
{ {
case amuse::DataFormat::GCN: case amuse::DataFormat::GCN:
default: default:
m_loadedData.emplace(m_projData.data(), m_projData.size(), m_loadedData.emplace(m_projData.data(), m_projData.size(), m_poolData.data(), m_poolData.size(),
m_poolData.data(), m_poolData.size(), m_sdirData.data(), m_sdirData.size(), m_sampData.data(), m_sampData.size(),
m_sdirData.data(), 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_loadedData.emplace(m_projData.data(), m_projData.size(), m_poolData.data(), m_poolData.size(),
m_poolData.data(), m_poolData.size(), m_sdirData.data(), m_sdirData.size(), m_sampData.data(), m_sampData.size(),
m_sdirData.data(), m_sdirData.size(),
m_sampData.data(), m_sampData.size(),
m_metaData->absOffs, amuse::N64DataTag{}); m_metaData->absOffs, amuse::N64DataTag{});
break; break;
case amuse::DataFormat::PC: case amuse::DataFormat::PC:
m_loadedData.emplace(m_projData.data(), m_projData.size(), m_loadedData.emplace(m_projData.data(), m_projData.size(), m_poolData.data(), m_poolData.size(),
m_poolData.data(), m_poolData.size(), m_sdirData.data(), m_sdirData.size(), m_sampData.data(), m_sampData.size(),
m_sdirData.data(), m_sdirData.size(),
m_sampData.data(), m_sampData.size(),
m_metaData->absOffs, amuse::PCDataTag{}); m_metaData->absOffs, amuse::PCDataTag{});
break; break;
} }
@ -189,18 +293,15 @@ void AudioGroupDataCollection::addToEngine(amuse::Engine& engine)
} }
} }
void AudioGroupDataCollection::removeFromEngine(amuse::Engine& engine) const void AudioGroupDataCollection::removeFromEngine(amuse::Engine& engine) const { engine.removeAudioGroup(*m_loadedData); }
{
engine.removeAudioGroup(*m_loadedData);
}
AudioGroupCollection::AudioGroupCollection(const std::wstring& path, const std::wstring& name) AudioGroupCollection::AudioGroupCollection(const std::wstring& path, const std::wstring& name)
: m_path(path), m_name(name) : m_path(path), m_name(name)
{ {
} }
void AudioGroupCollection::addCollection(std::vector<std::pair<std::wstring, amuse::IntrusiveAudioGroupData>>&& collection) void AudioGroupCollection::addCollection(
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)
{ {
@ -210,9 +311,9 @@ void AudioGroupCollection::addCollection(std::vector<std::pair<std::wstring, amu
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 = m_groups.emplace(pair.first, search =
std::make_unique<AudioGroupDataCollection>(collectionPath, m_groups.emplace(pair.first, std::make_unique<AudioGroupDataCollection>(collectionPath, pair.first))
pair.first)).first; .first;
} }
AudioGroupDataCollection& dataCollection = *search->second; AudioGroupDataCollection& dataCollection = *search->second;
@ -253,9 +354,9 @@ void AudioGroupCollection::update(AudioGroupFilePresenter& presenter)
if (search == m_groups.end()) if (search == m_groups.end())
{ {
search = search =
m_groups.emplace(nameStr, m_groups
std::make_unique<AudioGroupDataCollection>(m_path + L'\\' + nameStr, .emplace(nameStr, std::make_unique<AudioGroupDataCollection>(m_path + L'\\' + nameStr, nameStr))
nameStr)).first; .first;
search->second->_attemptLoad(); search->second->_attemptLoad();
} }
} }
@ -284,8 +385,10 @@ void AudioGroupFilePresenter::update()
auto search = theMap.find(nameStr); auto search = theMap.find(nameStr);
if (search == theMap.end()) if (search == theMap.end())
{ {
search = theMap.emplace(nameStr, search = theMap
std::make_unique<AudioGroupCollection>(m_backend.getUserDir() + L'\\' + nameStr, nameStr)).first; .emplace(nameStr, std::make_unique<AudioGroupCollection>(
m_backend.getUserDir() + L'\\' + nameStr, nameStr))
.first;
search->second->update(*this); search->second->update(*this);
} }
} }
@ -294,11 +397,12 @@ void AudioGroupFilePresenter::update()
FindClose(dir); FindClose(dir);
} }
void AudioGroupFilePresenter::addCollection(const std::wstring& name, void AudioGroupFilePresenter::addCollection(
std::vector<std::pair<std::wstring, amuse::IntrusiveAudioGroupData>>&& collection) const std::wstring& 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 = *m_audioGroupCollections.emplace(name, std::make_unique<AudioGroupCollection>(path, name)).first->second; AudioGroupCollection& insert =
*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));
@ -453,7 +557,8 @@ void AudioGroupFilePresenter::populatePageColumn(VSTEditor& editor, int collecti
for (auto& pair : sortPages) for (auto& pair : sortPages)
{ {
wchar_t name[256]; wchar_t name[256];
wnsprintf(name, 256, L"%d (%s)", pair.first, GMNames[pair.first] ? GMNames[pair.first] : L"???"); wnsprintf(name, 256, L"%d (%s)", pair.first,
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;
@ -467,7 +572,8 @@ void AudioGroupFilePresenter::populatePageColumn(VSTEditor& editor, int collecti
for (auto& pair : sortPages) for (auto& pair : sortPages)
{ {
wchar_t name[256]; wchar_t name[256];
wnsprintf(name, 256, L"%d (%s)", pair.first, GMPercNames[pair.first] ? GMPercNames[pair.first] : L"???"); wnsprintf(name, 256, L"%d (%s)", pair.first,
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;
@ -478,5 +584,4 @@ void AudioGroupFilePresenter::populatePageColumn(VSTEditor& editor, int collecti
} }
} }
} }
} }

View File

@ -33,9 +33,13 @@ struct AudioGroupDataCollection
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;
@ -58,7 +62,10 @@ struct AudioGroupDataCollection
bool loadMeta(); bool loadMeta();
AudioGroupDataCollection(const std::wstring& path, const std::wstring& name); AudioGroupDataCollection(const std::wstring& path, const std::wstring& name);
bool isDataComplete() const {return m_projData.size() && m_poolData.size() && m_sdirData.size() && m_sampData.size() && m_metaData;} bool isDataComplete() const
{
return m_projData.size() && m_poolData.size() && m_sdirData.size() && m_sampData.size() && m_metaData;
}
bool _attemptLoad(); bool _attemptLoad();
bool _indexData(); bool _indexData();
@ -84,12 +91,15 @@ struct AudioGroupCollection
class AudioGroupFilePresenter class AudioGroupFilePresenter
{ {
friend class VSTBackend; friend class VSTBackend;
public: public:
using CollectionIterator = std::map<std::wstring, std::unique_ptr<AudioGroupCollection>>::iterator; using CollectionIterator = std::map<std::wstring, std::unique_ptr<AudioGroupCollection>>::iterator;
private: private:
VSTBackend& m_backend; VSTBackend& m_backend;
std::map<std::wstring, std::unique_ptr<AudioGroupCollection>> m_audioGroupCollections; std::map<std::wstring, std::unique_ptr<AudioGroupCollection>> m_audioGroupCollections;
std::vector<CollectionIterator> m_iteratorVec; std::vector<CollectionIterator> m_iteratorVec;
public: public:
AudioGroupFilePresenter(VSTBackend& backend) : m_backend(backend) {} AudioGroupFilePresenter(VSTBackend& backend) : m_backend(backend) {}
void update(); void update();
@ -101,7 +111,6 @@ public:
void removeCollection(unsigned idx); void removeCollection(unsigned idx);
VSTBackend& getBackend() { return m_backend; } VSTBackend& getBackend() { return m_backend; }
}; };
} }
#endif // __AMUSE_AUDIOGROUPFILEPRESENTER_HPP__ #endif // __AMUSE_AUDIOGROUPFILEPRESENTER_HPP__

View File

@ -33,8 +33,7 @@ HWND ghMainWnd = 0;
HINSTANCE ghAppInst = 0; HINSTANCE ghAppInst = 0;
RECT winRect; RECT winRect;
class CDialogEventHandler : public IFileDialogEvents, class CDialogEventHandler : public IFileDialogEvents, public IFileDialogControlEvents
public IFileDialogControlEvents
{ {
public: public:
// IUnknown methods // IUnknown methods
@ -48,10 +47,7 @@ public:
return QISearch(this, qit, riid, ppv); return QISearch(this, qit, riid, ppv);
} }
IFACEMETHODIMP_(ULONG) AddRef() IFACEMETHODIMP_(ULONG) AddRef() { return InterlockedIncrement(&_cRef); }
{
return InterlockedIncrement(&_cRef);
}
IFACEMETHODIMP_(ULONG) Release() IFACEMETHODIMP_(ULONG) Release()
{ {
@ -78,6 +74,7 @@ public:
IFACEMETHODIMP OnControlActivating(IFileDialogCustomize*, DWORD) { return S_OK; }; IFACEMETHODIMP OnControlActivating(IFileDialogCustomize*, DWORD) { return S_OK; };
CDialogEventHandler() : _cRef(1){}; CDialogEventHandler() : _cRef(1){};
private: private:
~CDialogEventHandler(){}; ~CDialogEventHandler(){};
long _cRef; long _cRef;
@ -178,7 +175,6 @@ 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;
@ -203,8 +199,6 @@ HRESULT CDialogEventHandler::OnTypeChange(IFileDialog *pfd)
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
IPropertyDescriptionList* pdl = NULL; IPropertyDescriptionList* pdl = NULL;
} }
pfsd->Release(); pfsd->Release();
} }

View File

@ -13,27 +13,17 @@ struct VSTVoiceEngine : boo::BaseAudioVoiceEngine
size_t m_renderFrames = 0; size_t m_renderFrames = 0;
size_t m_curBufFrame = 0; size_t m_curBufFrame = 0;
boo::AudioChannelSet _getAvailableSet() boo::AudioChannelSet _getAvailableSet() { return boo::AudioChannelSet::Stereo; }
{
return boo::AudioChannelSet::Stereo;
}
std::vector<std::pair<std::string, std::string>> enumerateMIDIDevices() const std::vector<std::pair<std::string, std::string>> enumerateMIDIDevices() const { return {}; }
{
return {};
}
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) MIDIIn(bool virt, boo::ReceiveFunctor&& receiver) : IMIDIIn(virt, std::move(receiver)) {}
: IMIDIIn(virt, std::move(receiver)) {}
std::string description() const std::string description() const { return "VST MIDI"; }
{
return "VST MIDI";
}
}; };
std::unique_ptr<boo::IMIDIIn> newVirtualMIDIIn(boo::ReceiveFunctor&& receiver) std::unique_ptr<boo::IMIDIIn> newVirtualMIDIIn(boo::ReceiveFunctor&& receiver)
@ -43,30 +33,15 @@ struct VSTVoiceEngine : boo::BaseAudioVoiceEngine
return ret; return ret;
} }
std::unique_ptr<boo::IMIDIOut> newVirtualMIDIOut() std::unique_ptr<boo::IMIDIOut> newVirtualMIDIOut() { return {}; }
{
return {};
}
std::unique_ptr<boo::IMIDIInOut> newVirtualMIDIInOut(boo::ReceiveFunctor&& receiver) std::unique_ptr<boo::IMIDIInOut> newVirtualMIDIInOut(boo::ReceiveFunctor&& receiver) { return {}; }
{
return {};
}
std::unique_ptr<boo::IMIDIIn> newRealMIDIIn(const char* name, boo::ReceiveFunctor&& receiver) std::unique_ptr<boo::IMIDIIn> newRealMIDIIn(const char* name, boo::ReceiveFunctor&& receiver) { return {}; }
{
return {};
}
std::unique_ptr<boo::IMIDIOut> newRealMIDIOut(const char* name) std::unique_ptr<boo::IMIDIOut> newRealMIDIOut(const char* name) { return {}; }
{
return {};
}
std::unique_ptr<boo::IMIDIInOut> newRealMIDIInOut(const char* name, boo::ReceiveFunctor&& receiver) std::unique_ptr<boo::IMIDIInOut> newRealMIDIInOut(const char* name, boo::ReceiveFunctor&& receiver) { return {}; }
{
return {};
}
bool useMIDILock() const { return false; } bool useMIDILock() const { return false; }
@ -145,8 +120,7 @@ namespace amuse
static logvisor::Module Log("amuse::AudioUnitBackend"); static logvisor::Module Log("amuse::AudioUnitBackend");
VSTBackend::VSTBackend(audioMasterCallback cb) VSTBackend::VSTBackend(audioMasterCallback cb) : AudioEffectX(cb, 0, 0), m_filePresenter(*this), m_editor(*this)
: AudioEffectX(cb, 0, 0), m_filePresenter(*this), m_editor(*this)
{ {
isSynth(); isSynth();
setUniqueID(kBackendID); setUniqueID(kBackendID);
@ -170,15 +144,9 @@ VSTBackend::VSTBackend(audioMasterCallback cb)
m_filePresenter.update(); m_filePresenter.update();
} }
VSTBackend::~VSTBackend() VSTBackend::~VSTBackend() { editor = nullptr; }
{
editor = nullptr;
}
AEffEditor* VSTBackend::getEditor() AEffEditor* VSTBackend::getEditor() { return &m_editor; }
{
return &m_editor;
}
VstInt32 VSTBackend::processEvents(VstEvents* events) VstInt32 VSTBackend::processEvents(VstEvents* events)
{ {
@ -207,8 +175,8 @@ VstInt32 VSTBackend::processEvents(VstEvents* events)
evt->midiData[0] &= ~0xf; evt->midiData[0] &= ~0xf;
evt->midiData[0] |= m_routeChannel & 0xf; evt->midiData[0] |= m_routeChannel & 0xf;
} }
(*engine.m_midiReceiver)(std::vector<uint8_t>(std::cbegin(evt->midiData), (*engine.m_midiReceiver)(
std::cbegin(evt->midiData) + evt->byteSize), std::vector<uint8_t>(std::cbegin(evt->midiData), std::cbegin(evt->midiData) + evt->byteSize),
(m_curFrame + evt->deltaFrames) / sampleRate); (m_curFrame + evt->deltaFrames) / sampleRate);
} }
} }
@ -242,10 +210,7 @@ VstInt32 VSTBackend::canDo(char* text)
return returnCode; return returnCode;
} }
VstPlugCategory VSTBackend::getPlugCategory() VstPlugCategory VSTBackend::getPlugCategory() { return kPlugCategSynth; }
{
return kPlugCategSynth;
}
bool VSTBackend::getEffectName(char* text) bool VSTBackend::getEffectName(char* text)
{ {
@ -284,10 +249,7 @@ bool VSTBackend::getOutputProperties(VstInt32 index, VstPinProperties* propertie
return returnCode; return returnCode;
} }
VstInt32 VSTBackend::getNumMidiInputChannels() VstInt32 VSTBackend::getNumMidiInputChannels() { return 1; }
{
return 1;
}
void VSTBackend::setSampleRate(float sampleRate) void VSTBackend::setSampleRate(float sampleRate)
{ {
@ -427,10 +389,6 @@ VstInt32 VSTBackend::setChunk(void* data, VstInt32 byteSize, bool)
return 1; return 1;
} }
} }
AudioEffect* createEffectInstance(audioMasterCallback audioMaster) AudioEffect* createEffectInstance(audioMasterCallback audioMaster) { return new amuse::VSTBackend(audioMaster); }
{
return new amuse::VSTBackend(audioMaster);
}

View File

@ -21,8 +21,7 @@ class VSTBackend;
class VSTBackendVoiceAllocator : public BooBackendVoiceAllocator class VSTBackendVoiceAllocator : public BooBackendVoiceAllocator
{ {
public: public:
VSTBackendVoiceAllocator(boo::IAudioVoiceEngine& booEngine) VSTBackendVoiceAllocator(boo::IAudioVoiceEngine& booEngine) : BooBackendVoiceAllocator(booEngine) {}
: BooBackendVoiceAllocator(booEngine) {}
}; };
/** Actual plugin implementation class */ /** Actual plugin implementation class */
@ -41,6 +40,7 @@ class VSTBackend : public AudioEffectX
int m_routeChannel = -1; int m_routeChannel = -1;
AudioGroupFilePresenter m_filePresenter; AudioGroupFilePresenter m_filePresenter;
VSTEditor m_editor; VSTEditor m_editor;
public: public:
VSTBackend(audioMasterCallback cb); VSTBackend(audioMasterCallback cb);
~VSTBackend(); ~VSTBackend();
@ -72,7 +72,6 @@ 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);
}; };
} }
#endif // __AMUSE_VSTBACKEND_HPP__ #endif // __AMUSE_VSTBACKEND_HPP__

View File

@ -16,10 +16,7 @@ static HBRUSH gGreyBorderBrush;
namespace amuse namespace amuse
{ {
VSTEditor::VSTEditor(VSTBackend& backend) VSTEditor::VSTEditor(VSTBackend& backend) : AEffEditor(&backend), m_backend(backend) {}
: AEffEditor(&backend), m_backend(backend)
{
}
bool VSTEditor::getRect(ERect** rect) bool VSTEditor::getRect(ERect** rect)
{ {
@ -27,10 +24,7 @@ bool VSTEditor::getRect(ERect** rect)
return true; return true;
} }
LRESULT CALLBACK VSTEditor::WindowProc(HWND hwnd, LRESULT CALLBACK VSTEditor::WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
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)
@ -101,10 +95,7 @@ LRESULT CALLBACK VSTEditor::WindowProc(HWND hwnd,
} }
} }
LRESULT CALLBACK VSTEditor::ColHeaderWindowProc(HWND hwnd, LRESULT CALLBACK VSTEditor::ColHeaderWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{ {
switch (uMsg) switch (uMsg)
{ {
@ -119,11 +110,8 @@ LRESULT CALLBACK VSTEditor::ColHeaderWindowProc(HWND hwnd,
RECT rect; RECT rect;
GetClientRect(hwnd, &rect); GetClientRect(hwnd, &rect);
TRIVERTEX verts[] = TRIVERTEX verts[] = {{rect.left, rect.top, 0x6000, 0x6000, 0x7000, 0xff00},
{ {rect.right, rect.bottom, 0x2000, 0x2000, 0x2800, 0xff00}};
{rect.left, rect.top, 0x6000, 0x6000, 0x7000, 0xff00},
{rect.right, rect.bottom, 0x2000, 0x2000, 0x2800, 0xff00}
};
GRADIENT_RECT grect = {0, 1}; GRADIENT_RECT grect = {0, 1};
GradientFill(dc, verts, 2, &grect, 1, GRADIENT_FILL_RECT_V); GradientFill(dc, verts, 2, &grect, 1, GRADIENT_FILL_RECT_V);
@ -162,9 +150,7 @@ bool VSTEditor::open(void* ptr)
HWND hostView = HWND(ptr); HWND hostView = HWND(ptr);
gGreyBorderBrush = CreateSolidBrush(RGB(100, 100, 100)); gGreyBorderBrush = CreateSolidBrush(RGB(100, 100, 100));
WNDCLASSW notifyCls = WNDCLASSW notifyCls = {CS_HREDRAW | CS_VREDRAW,
{
CS_HREDRAW | CS_VREDRAW,
WindowProc, WindowProc,
0, 0,
8, 8,
@ -173,20 +159,11 @@ bool VSTEditor::open(void* ptr)
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
L"VSTNotify" L"VSTNotify"};
};
RegisterClassW(&notifyCls); RegisterClassW(&notifyCls);
m_rootView = CreateWindowW(L"VSTNotify", m_rootView = CreateWindowW(L"VSTNotify", L"", WS_CHILD, 0, 0, m_windowRect.right, m_windowRect.bottom, hostView,
L"", nullptr, HINSTANCE(hInstance), nullptr);
WS_CHILD,
0, 0,
m_windowRect.right,
m_windowRect.bottom,
hostView,
nullptr,
HINSTANCE(hInstance),
nullptr);
SetWindowLongPtrW(m_rootView, 0, LONG_PTR(this)); SetWindowLongPtrW(m_rootView, 0, LONG_PTR(this));
ShowWindow(m_rootView, SW_SHOW); ShowWindow(m_rootView, SW_SHOW);
@ -203,16 +180,10 @@ bool VSTEditor::open(void* ptr)
column.fmt = LVCFMT_LEFT | LVCFMT_FIXED_WIDTH; column.fmt = LVCFMT_LEFT | LVCFMT_FIXED_WIDTH;
column.cx = 199; column.cx = 199;
m_collectionTree = CreateWindowW(WC_TREEVIEW, m_collectionTree =
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, 25, 1, 25, 199, m_windowRect.bottom - m_windowRect.top - 26, m_rootView, nullptr, nullptr, nullptr);
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);
@ -231,85 +202,39 @@ bool VSTEditor::open(void* ptr)
TreeView_InsertItem(m_collectionTree, &treeItem); TreeView_InsertItem(m_collectionTree, &treeItem);
ShowWindow(m_collectionTree, SW_SHOW); ShowWindow(m_collectionTree, SW_SHOW);
HWND cHeader = CreateWindowW(WC_HEADER, HWND cHeader = CreateWindowW(WC_HEADER, L"", WS_CHILD, 1, 1, 199, 24, m_rootView, nullptr, nullptr, nullptr);
L"",
WS_CHILD,
1, 1,
199,
24,
m_rootView,
nullptr,
nullptr,
nullptr);
SetWindowLongPtrW(cHeader, GWLP_USERDATA, LONG_PTR(L"Collection")); SetWindowLongPtrW(cHeader, GWLP_USERDATA, LONG_PTR(L"Collection"));
OriginalListViewProc = WNDPROC(SetWindowLongPtr(cHeader, GWLP_WNDPROC, LONG_PTR(ColHeaderWindowProc))); OriginalListViewProc = WNDPROC(SetWindowLongPtr(cHeader, GWLP_WNDPROC, LONG_PTR(ColHeaderWindowProc)));
ShowWindow(cHeader, SW_SHOW); ShowWindow(cHeader, SW_SHOW);
HWND gHeader = CreateWindowW(WC_HEADER, HWND gHeader = CreateWindowW(WC_HEADER, L"", WS_CHILD, 201, 1, 199, 24, m_rootView, nullptr, nullptr, nullptr);
L"",
WS_CHILD,
201, 1,
199,
24,
m_rootView,
nullptr,
nullptr,
nullptr);
SetWindowLongPtrW(gHeader, GWLP_USERDATA, LONG_PTR(L"Group")); SetWindowLongPtrW(gHeader, GWLP_USERDATA, LONG_PTR(L"Group"));
OriginalListViewProc = WNDPROC(SetWindowLongPtr(gHeader, GWLP_WNDPROC, LONG_PTR(ColHeaderWindowProc))); OriginalListViewProc = WNDPROC(SetWindowLongPtr(gHeader, GWLP_WNDPROC, LONG_PTR(ColHeaderWindowProc)));
ShowWindow(gHeader, SW_SHOW); ShowWindow(gHeader, SW_SHOW);
HWND pHeader = CreateWindowW(WC_HEADER, HWND pHeader = CreateWindowW(WC_HEADER, L"", WS_CHILD, 401, 1, 198, 24, m_rootView, nullptr, nullptr, nullptr);
L"",
WS_CHILD,
401, 1,
198,
24,
m_rootView,
nullptr,
nullptr,
nullptr);
SetWindowLongPtrW(pHeader, GWLP_USERDATA, LONG_PTR(L"Page")); SetWindowLongPtrW(pHeader, GWLP_USERDATA, LONG_PTR(L"Page"));
OriginalListViewProc = WNDPROC(SetWindowLongPtr(pHeader, GWLP_WNDPROC, LONG_PTR(ColHeaderWindowProc))); OriginalListViewProc = WNDPROC(SetWindowLongPtr(pHeader, GWLP_WNDPROC, LONG_PTR(ColHeaderWindowProc)));
ShowWindow(pHeader, SW_SHOW); ShowWindow(pHeader, SW_SHOW);
m_collectionAdd = CreateWindowW(WC_BUTTON, m_collectionAdd =
L"+", CreateWindowW(WC_BUTTON, L"+", WS_CHILD | WS_CLIPSIBLINGS | BS_PUSHBUTTON, 1,
WS_CHILD | WS_CLIPSIBLINGS | BS_PUSHBUTTON, m_windowRect.bottom - m_windowRect.top - 25, 25, 24, m_rootView, nullptr, nullptr, nullptr);
1, m_windowRect.bottom - m_windowRect.top - 25,
25, 24,
m_rootView,
nullptr,
nullptr,
nullptr);
SetWindowFont(m_collectionAdd, GetStockObject(ANSI_FIXED_FONT), FALSE); SetWindowFont(m_collectionAdd, GetStockObject(ANSI_FIXED_FONT), FALSE);
Button_Enable(m_collectionAdd, TRUE); Button_Enable(m_collectionAdd, TRUE);
SetWindowPos(m_collectionAdd, HWND_TOP, 1, m_windowRect.bottom - m_windowRect.top - 25, 25, 24, SWP_SHOWWINDOW); SetWindowPos(m_collectionAdd, HWND_TOP, 1, m_windowRect.bottom - m_windowRect.top - 25, 25, 24, SWP_SHOWWINDOW);
m_collectionRemove = CreateWindowW(WC_BUTTON, m_collectionRemove =
L"-", CreateWindowW(WC_BUTTON, L"-", WS_CHILD | WS_CLIPSIBLINGS | BS_PUSHBUTTON, 26,
WS_CHILD | WS_CLIPSIBLINGS | BS_PUSHBUTTON, m_windowRect.bottom - m_windowRect.top - 25, 25, 24, m_rootView, nullptr, nullptr, nullptr);
26, m_windowRect.bottom - m_windowRect.top - 25,
25, 24,
m_rootView,
nullptr,
nullptr,
nullptr);
SetWindowFont(m_collectionRemove, GetStockObject(ANSI_FIXED_FONT), FALSE); SetWindowFont(m_collectionRemove, GetStockObject(ANSI_FIXED_FONT), FALSE);
Button_Enable(m_collectionRemove, FALSE); Button_Enable(m_collectionRemove, FALSE);
SetWindowPos(m_collectionRemove, HWND_TOP, 26, m_windowRect.bottom - m_windowRect.top - 25, 25, 24, SWP_SHOWWINDOW); SetWindowPos(m_collectionRemove, HWND_TOP, 26, m_windowRect.bottom - m_windowRect.top - 25, 25, 24, SWP_SHOWWINDOW);
m_groupListView =
m_groupListView = CreateWindowW(WC_LISTVIEW, CreateWindowW(WC_LISTVIEW, L"",
L"",
WS_CHILD | LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_NOCOLUMNHEADER | LVS_NOSORTHEADER, WS_CHILD | LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_NOCOLUMNHEADER | LVS_NOSORTHEADER,
201, 25, 201, 25, 199, m_windowRect.bottom - m_windowRect.top - 26, m_rootView, nullptr, nullptr, nullptr);
199,
m_windowRect.bottom - m_windowRect.top - 26,
m_rootView,
nullptr,
nullptr,
nullptr);
column.pszText = L"Group"; column.pszText = L"Group";
HWND header = ListView_GetHeader(m_groupListView); HWND header = ListView_GetHeader(m_groupListView);
SetWindowLongPtrW(header, GWLP_USERDATA, LONG_PTR(column.pszText)); SetWindowLongPtrW(header, GWLP_USERDATA, LONG_PTR(column.pszText));
@ -320,16 +245,10 @@ bool VSTEditor::open(void* ptr)
ListView_InsertColumn(m_groupListView, 0, &column); ListView_InsertColumn(m_groupListView, 0, &column);
ShowWindow(m_groupListView, SW_SHOW); ShowWindow(m_groupListView, SW_SHOW);
m_pageListView = CreateWindowW(WC_LISTVIEW, m_pageListView =
L"", CreateWindowW(WC_LISTVIEW, L"",
WS_CHILD | LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_NOCOLUMNHEADER | LVS_NOSORTHEADER, WS_CHILD | LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_NOCOLUMNHEADER | LVS_NOSORTHEADER,
401, 25, 401, 25, 198, m_windowRect.bottom - m_windowRect.top - 26, m_rootView, nullptr, nullptr, nullptr);
198,
m_windowRect.bottom - m_windowRect.top - 26,
m_rootView,
nullptr,
nullptr,
nullptr);
column.pszText = L"Page"; column.pszText = L"Page";
column.cx = 198 - GetSystemMetrics(SM_CXVSCROLL); column.cx = 198 - GetSystemMetrics(SM_CXVSCROLL);
header = ListView_GetHeader(m_pageListView); header = ListView_GetHeader(m_pageListView);
@ -468,14 +387,7 @@ void VSTEditor::reselectPage()
} }
} }
void VSTEditor::selectNormalPage(int idx) void VSTEditor::selectNormalPage(int idx) { m_backend.setNormalProgram(idx); }
{
m_backend.setNormalProgram(idx);
}
void VSTEditor::selectDrumPage(int idx)
{
m_backend.setDrumProgram(idx);
}
void VSTEditor::selectDrumPage(int idx) { m_backend.setDrumProgram(idx); }
} }

View File

@ -36,20 +36,11 @@ class VSTEditor : public AEffEditor
HTREEITEM m_deferredCollectionSel = 0; HTREEITEM m_deferredCollectionSel = 0;
static LRESULT CALLBACK WindowProc( static LRESULT CALLBACK WindowProc(_In_ HWND hwnd, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam);
_In_ HWND hwnd, static LRESULT CALLBACK ColHeaderWindowProc(_In_ HWND hwnd, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam);
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
);
static LRESULT CALLBACK ColHeaderWindowProc(
_In_ HWND hwnd,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
);
void _reselectColumns(); void _reselectColumns();
public: public:
VSTEditor(VSTBackend& backend); VSTEditor(VSTBackend& backend);
@ -68,7 +59,6 @@ public:
void selectNormalPage(int idx); void selectNormalPage(int idx);
void selectDrumPage(int idx); void selectDrumPage(int idx);
}; };
} }
#endif // __AMUSE_VSTEDITOR_HPP__ #endif // __AMUSE_VSTEDITOR_HPP__

View File

@ -52,7 +52,6 @@ static bool ExtractAudioGroup(const amuse::SystemString& inPath, const amuse::Sy
{ {
Log.report(logvisor::Info, _S("Extracting %s"), group.first.c_str()); Log.report(logvisor::Info, _S("Extracting %s"), group.first.c_str());
} }
} }
auto songs = amuse::ContainerRegistry::LoadSongs(inPath.c_str()); auto songs = amuse::ContainerRegistry::LoadSongs(inPath.c_str());
@ -74,7 +73,8 @@ static bool ExtractAudioGroup(const amuse::SystemString& inPath, const amuse::Sy
Log.report(logvisor::Info, _S("Extracting %s"), pair.first.c_str()); Log.report(logvisor::Info, _S("Extracting %s"), pair.first.c_str());
int extractedVersion; int extractedVersion;
bool isBig; bool isBig;
std::vector<uint8_t> mid = amuse::SongConverter::SongToMIDI(pair.second.m_data.get(), extractedVersion, isBig); std::vector<uint8_t> mid =
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);
} }
@ -173,14 +173,12 @@ int main(int argc, const amuse::SystemChar** argv)
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, _S(".mid")) || if (!amuse::CompareCaseInsensitive(dot, _S(".mid")) || !amuse::CompareCaseInsensitive(dot, _S(".midi")))
!amuse::CompareCaseInsensitive(dot, _S(".midi")))
{ {
ReportConvType(type); ReportConvType(type);
good = BuildSNG(barePath, argv[2], 1, true); good = BuildSNG(barePath, argv[2], 1, true);
} }
else if (!amuse::CompareCaseInsensitive(dot, _S(".son")) || else if (!amuse::CompareCaseInsensitive(dot, _S(".son")) || !amuse::CompareCaseInsensitive(dot, _S(".sng")))
!amuse::CompareCaseInsensitive(dot, _S(".sng")))
{ {
good = ExtractSNG(argv[1], argv[2]); good = ExtractSNG(argv[1], argv[2]);
} }

View File

@ -18,7 +18,8 @@ static logvisor::Module Log("amuseplay");
#if __GNUC__ #if __GNUC__
__attribute__((__format__(__printf__, 3, 4))) __attribute__((__format__(__printf__, 3, 4)))
#endif #endif
static inline void SNPrintf(boo::SystemChar* str, size_t maxlen, const boo::SystemChar* format, ...) static inline void
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);
@ -88,6 +89,7 @@ struct EventCallback : boo::IWindowCallback
{ {
AppCallback& m_app; AppCallback& m_app;
bool m_tracking = false; bool m_tracking = false;
public: public:
void charKeyDown(unsigned long charCode, boo::EModifierKey mods, bool isRepeat); void charKeyDown(unsigned long charCode, boo::EModifierKey mods, bool isRepeat);
void charKeyUp(unsigned long charCode, boo::EModifierKey mods); void charKeyUp(unsigned long charCode, boo::EModifierKey mods);
@ -151,9 +153,10 @@ struct AppCallback : boo::IApplicationCallback
voxCount = m_seq->getVoiceCount(); voxCount = m_seq->getVoiceCount();
program = m_seq->getChanProgram(m_chanId); program = m_seq->getChanProgram(m_chanId);
} }
printf("\r " printf(
"\r %" PRISize " Setup %d, Chan %d, Prog %d, Octave: %d, Vel: %d, VOL: %d%%\r", voxCount, "\r "
m_setupId, m_chanId, program, m_octave, m_velocity, int(std::rint(m_volume * 100))); "\r %" PRISize " Setup %d, Chan %d, Prog %d, Octave: %d, Vel: %d, VOL: %d%%\r",
voxCount, m_setupId, m_chanId, program, m_octave, m_velocity, int(std::rint(m_volume * 100)));
fflush(stdout); fflush(stdout);
} }
@ -176,7 +179,8 @@ struct AppCallback : boo::IApplicationCallback
void SongLoop(const amuse::SongGroupIndex& index) void SongLoop(const amuse::SongGroupIndex& index)
{ {
printf("░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░\n" printf(
"░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░\n"
"░░░ ████ ████ ┃ ████ ████ ████ ┃ ████ ████ ░░░\n" "░░░ ████ ████ ┃ ████ ████ ████ ┃ ████ ████ ░░░\n"
"░░░ ████ ████ ┃ ████ ████ ████ ┃ ████ ████ ░░░\n" "░░░ ████ ████ ┃ ████ ████ ████ ┃ ████ ████ ░░░\n"
"░░░ ▌W▐█ ▌E▐█ ┃ ▌T▐█ ▌Y▐█ ▌U▐█ ┃ ▌O▐█ ▌P▐█ ░░░\n" "░░░ ▌W▐█ ▌E▐█ ┃ ▌T▐█ ▌Y▐█ ▌U▐█ ┃ ▌O▐█ ▌P▐█ ░░░\n"
@ -187,8 +191,8 @@ struct AppCallback : boo::IApplicationCallback
"<tab>: sustain pedal, <window-Y>: pitch wheel, <window-X>: mod wheel\n" "<tab>: sustain pedal, <window-Y>: pitch wheel, <window-X>: mod wheel\n"
"<Z/X>: octave, <C/V>: velocity, <B/N>: channel, <,/.>: program, <Q>: quit\n"); "<Z/X>: octave, <C/V>: velocity, <B/N>: channel, <,/.>: program, <Q>: quit\n");
std::map<int, const std::array<amuse::SongGroupIndex::MIDISetup, 16>*> sortEntries std::map<int, const std::array<amuse::SongGroupIndex::MIDISetup, 16>*> sortEntries(index.m_midiSetups.cbegin(),
(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())
{ {
@ -287,9 +291,10 @@ 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;
printf("\r " printf(
"\r %c SFX %d, VOL: %d%%\r", playing ? '>' : ' ', "\r "
m_sfxId, int(std::rint(m_volume * 100))); "\r %c SFX %d, VOL: %d%%\r",
playing ? '>' : ' ', m_sfxId, int(std::rint(m_volume * 100)));
fflush(stdout); fflush(stdout);
} }
@ -311,8 +316,8 @@ struct AppCallback : boo::IApplicationCallback
{ {
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");
std::map<uint16_t, const amuse::SFXGroupIndex::SFXEntry*> sortEntries std::map<uint16_t, const amuse::SFXGroupIndex::SFXEntry*> sortEntries(index.m_sfxEntries.cbegin(),
(index.m_sfxEntries.cbegin(), index.m_sfxEntries.cend()); index.m_sfxEntries.cend());
auto sfxIt = sortEntries.cbegin(); auto sfxIt = sortEntries.cbegin();
if (sfxIt != sortEntries.cend()) if (sfxIt != sortEntries.cend())
SelectSFX(sfxIt->first); SelectSFX(sfxIt->first);
@ -410,7 +415,8 @@ struct AppCallback : boo::IApplicationCallback
m_seq->nextChanProgram(m_chanId); m_seq->nextChanProgram(m_chanId);
m_updateDisp = true; m_updateDisp = true;
break; break;
default: break; default:
break;
} }
} }
} }
@ -434,7 +440,8 @@ struct AppCallback : boo::IApplicationCallback
else if (m_sfxId != -1) else if (m_sfxId != -1)
m_vox = m_engine->fxStart(m_sfxId, m_volume, 0.f); m_vox = m_engine->fxStart(m_sfxId, m_volume, 0.f);
m_updateDisp = true; m_updateDisp = true;
default: break; default:
break;
} }
} }
else if (m_seq && m_chanId != -1) else if (m_seq && m_chanId != -1)
@ -534,7 +541,8 @@ struct AppCallback : boo::IApplicationCallback
case ':': case ':':
m_seq->keyOn(m_chanId, (m_octave + 1) * 12 + 16, m_velocity); m_seq->keyOn(m_chanId, (m_octave + 1) * 12 + 16, m_velocity);
break; break;
default: break; default:
break;
} }
if (!setPanic) if (!setPanic)
@ -605,7 +613,8 @@ struct AppCallback : boo::IApplicationCallback
case ':': case ':':
m_seq->keyOff(m_chanId, (m_octave + 1) * 12 + 16, m_velocity); m_seq->keyOff(m_chanId, (m_octave + 1) * 12 + 16, m_velocity);
break; break;
default: break; default:
break;
} }
} }
} }
@ -620,9 +629,7 @@ struct AppCallback : boo::IApplicationCallback
m_win->showWindow(); m_win->showWindow();
boo::ITextureR* tex = nullptr; boo::ITextureR* tex = nullptr;
boo::GraphicsDataToken gfxToken = boo::GraphicsDataToken gfxToken =
m_win->getMainContextDataFactory()->commitTransaction( m_win->getMainContextDataFactory()->commitTransaction([&](boo::IGraphicsDataFactory::Context& ctx) -> bool {
[&](boo::IGraphicsDataFactory::Context& ctx) -> bool
{
tex = ctx.newRenderTexture(100, 100, false, false); tex = ctx.newRenderTexture(100, 100, false, false);
return true; return true;
}); });
@ -656,8 +663,12 @@ struct AppCallback : boo::IApplicationCallback
} }
std::list<amuse::AudioGroupProject> m_projs; std::list<amuse::AudioGroupProject> m_projs;
std::map<int, std::pair<std::pair<amuse::SystemString, amuse::IntrusiveAudioGroupData>*, const amuse::SongGroupIndex*>> allSongGroups; std::map<int, std::pair<std::pair<amuse::SystemString, amuse::IntrusiveAudioGroupData>*,
std::map<int, std::pair<std::pair<amuse::SystemString, amuse::IntrusiveAudioGroupData>*, const amuse::SFXGroupIndex*>> allSFXGroups; const amuse::SongGroupIndex*>>
allSongGroups;
std::map<int, std::pair<std::pair<amuse::SystemString, amuse::IntrusiveAudioGroupData>*,
const amuse::SFXGroupIndex*>>
allSFXGroups;
size_t totalGroups = 0; size_t totalGroups = 0;
for (auto& grp : data) for (auto& grp : data)
@ -743,8 +754,8 @@ struct AppCallback : boo::IApplicationCallback
break; break;
} }
} }
amuse::Printf(_S(" %d %s (Group %d, Setup %d)\n"), idx++, amuse::Printf(_S(" %d %s (Group %d, Setup %d)\n"), idx++, pair.first.c_str(), grpId,
pair.first.c_str(), grpId, setupId); setupId);
} }
int userSel = 0; int userSel = 0;
@ -813,17 +824,15 @@ struct AppCallback : boo::IApplicationCallback
printf("Multiple Audio Groups discovered:\n"); printf("Multiple Audio Groups discovered:\n");
for (const auto& pair : allSFXGroups) for (const auto& pair : allSFXGroups)
{ {
amuse::Printf(_S(" %d %s (SFXGroup) %" PRISize " sfx-entries\n"), amuse::Printf(_S(" %d %s (SFXGroup) %" PRISize " sfx-entries\n"), pair.first,
pair.first, pair.second.first->first.c_str(), pair.second.first->first.c_str(), pair.second.second->m_sfxEntries.size());
pair.second.second->m_sfxEntries.size());
} }
for (const auto& pair : allSongGroups) for (const auto& pair : allSongGroups)
{ {
amuse::Printf(_S(" %d %s (SongGroup) %" PRISize " normal-pages, %" PRISize " drum-pages, %" PRISize " MIDI-setups\n"), amuse::Printf(_S(" %d %s (SongGroup) %" PRISize " normal-pages, %" PRISize
pair.first, pair.second.first->first.c_str(), " drum-pages, %" PRISize " MIDI-setups\n"),
pair.second.second->m_normPages.size(), pair.first, pair.second.first->first.c_str(), pair.second.second->m_normPages.size(),
pair.second.second->m_drumPages.size(), pair.second.second->m_drumPages.size(), pair.second.second->m_midiSetups.size());
pair.second.second->m_midiSetups.size());
} }
int userSel = 0; int userSel = 0;
@ -923,13 +932,12 @@ struct AppCallback : boo::IApplicationCallback
return 0; return 0;
} }
void appQuitting(boo::IApplication*) void appQuitting(boo::IApplication*) { m_running = false; }
{
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)
@ -940,10 +948,7 @@ void EventCallback::charKeyDown(unsigned long charCode, boo::EModifierKey mods,
m_app.charKeyDown(charCode); m_app.charKeyDown(charCode);
} }
void EventCallback::charKeyUp(unsigned long charCode, boo::EModifierKey mods) void EventCallback::charKeyUp(unsigned long charCode, boo::EModifierKey mods) { m_app.charKeyUp(charCode); }
{
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)
{ {
@ -975,13 +980,12 @@ void EventCallback::specialKeyDown(boo::ESpecialKey key, boo::EModifierKey mods,
break; break;
case boo::ESpecialKey::Esc: case boo::ESpecialKey::Esc:
m_app.m_breakout = true; m_app.m_breakout = true;
default: break; default:
break;
} }
} }
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)
{ {
@ -1029,8 +1033,8 @@ int main(int argc, const boo::SystemChar** argv)
{ {
logvisor::RegisterConsoleLogger(); logvisor::RegisterConsoleLogger();
AppCallback app(argc, argv); AppCallback app(argc, argv);
int ret = boo::ApplicationRun(boo::IApplication::EPlatformType::Auto, int ret = boo::ApplicationRun(boo::IApplication::EPlatformType::Auto, app, _S("amuseplay"), _S("Amuse Player"),
app, _S("amuseplay"), _S("Amuse Player"), argc, argv, false); argc, argv, false);
printf("IM DYING!!\n"); printf("IM DYING!!\n");
return ret; return ret;
} }

View File

@ -20,7 +20,8 @@ static logvisor::Module Log("amuserender");
#if __GNUC__ #if __GNUC__
__attribute__((__format__(__printf__, 3, 4))) __attribute__((__format__(__printf__, 3, 4)))
#endif #endif
static inline void SNPrintf(boo::SystemChar* str, size_t maxlen, const boo::SystemChar* format, ...) static inline void
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);
@ -86,10 +87,7 @@ static void abortHandler( int signum )
/* SIGINT will gracefully break write loop */ /* SIGINT will gracefully break write loop */
static bool g_BreakLoop = false; static bool g_BreakLoop = false;
static void SIGINTHandler(int sig) static void SIGINTHandler(int sig) { g_BreakLoop = true; }
{
g_BreakLoop = true;
}
#if _WIN32 #if _WIN32
int wmain(int argc, const boo::SystemChar** argv) int wmain(int argc, const boo::SystemChar** argv)
@ -164,8 +162,12 @@ 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::pair<std::pair<amuse::SystemString, amuse::IntrusiveAudioGroupData>*, const amuse::SongGroupIndex*>> allSongGroups; std::map<int,
std::map<int, std::pair<std::pair<amuse::SystemString, amuse::IntrusiveAudioGroupData>*, const amuse::SFXGroupIndex*>> allSFXGroups; std::pair<std::pair<amuse::SystemString, amuse::IntrusiveAudioGroupData>*, const amuse::SongGroupIndex*>>
allSongGroups;
std::map<int,
std::pair<std::pair<amuse::SystemString, amuse::IntrusiveAudioGroupData>*, const amuse::SFXGroupIndex*>>
allSFXGroups;
size_t totalGroups = 0; size_t totalGroups = 0;
for (auto& grp : data) for (auto& grp : data)
@ -246,8 +248,7 @@ int main(int argc, const boo::SystemChar** argv)
break; break;
} }
} }
amuse::Printf(_S(" %d %s (Group %d, Setup %d)\n"), idx++, amuse::Printf(_S(" %d %s (Group %d, Setup %d)\n"), idx++, pair.first.c_str(), grpId, setupId);
pair.first.c_str(), grpId, setupId);
} }
int userSel = 0; int userSel = 0;
@ -319,17 +320,15 @@ int main(int argc, const boo::SystemChar** argv)
printf("Multiple Audio Groups discovered:\n"); printf("Multiple Audio Groups discovered:\n");
for (const auto& pair : allSFXGroups) for (const auto& pair : allSFXGroups)
{ {
amuse::Printf(_S(" %d %s (SFXGroup) %" PRISize " sfx-entries\n"), amuse::Printf(_S(" %d %s (SFXGroup) %" PRISize " sfx-entries\n"), pair.first,
pair.first, pair.second.first->first.c_str(), pair.second.first->first.c_str(), pair.second.second->m_sfxEntries.size());
pair.second.second->m_sfxEntries.size());
} }
for (const auto& pair : allSongGroups) for (const auto& pair : allSongGroups)
{ {
amuse::Printf(_S(" %d %s (SongGroup) %" PRISize " normal-pages, %" PRISize " drum-pages, %" PRISize " MIDI-setups\n"), amuse::Printf(_S(" %d %s (SongGroup) %" PRISize " normal-pages, %" PRISize " drum-pages, %" PRISize
pair.first, pair.second.first->first.c_str(), " MIDI-setups\n"),
pair.second.second->m_normPages.size(), pair.first, pair.second.first->first.c_str(), pair.second.second->m_normPages.size(),
pair.second.second->m_drumPages.size(), pair.second.second->m_drumPages.size(), pair.second.second->m_midiSetups.size());
pair.second.second->m_midiSetups.size());
} }
int userSel = 0; int userSel = 0;

View File

@ -9,8 +9,7 @@ namespace amuse
{ {
class AudioGroupData; class AudioGroupData;
using Sample = std::pair<AudioGroupSampleDirectory::Entry, using Sample = std::pair<AudioGroupSampleDirectory::Entry, AudioGroupSampleDirectory::ADPCMParms>;
AudioGroupSampleDirectory::ADPCMParms>;
/** Runtime audio group index container */ /** Runtime audio group index container */
class AudioGroup class AudioGroup
@ -21,6 +20,7 @@ class AudioGroup
const unsigned char* m_samp; const unsigned char* m_samp;
DataFormat m_fmt; DataFormat m_fmt;
bool m_valid; bool m_valid;
public: public:
operator bool() const { return m_valid; } operator bool() const { return m_valid; }
AudioGroup(const AudioGroupData& data, GCNDataTag); AudioGroup(const AudioGroupData& data, GCNDataTag);
@ -34,7 +34,6 @@ public:
const AudioGroupSampleDirectory& getSdir() const { return m_sdir; } const AudioGroupSampleDirectory& getSdir() const { return m_sdir; }
DataFormat getDataFormat() const { return m_fmt; } DataFormat getDataFormat() const { return m_fmt; }
}; };
} }
#endif // __AMUSE_AUDIOGROUP_HPP__ #endif // __AMUSE_AUDIOGROUP_HPP__

View File

@ -10,6 +10,7 @@ namespace amuse
class AudioGroupData class AudioGroupData
{ {
friend class Engine; friend class Engine;
protected: protected:
unsigned char* m_proj; unsigned char* m_proj;
size_t m_projSz; size_t m_projSz;
@ -23,44 +24,64 @@ protected:
DataFormat m_fmt; DataFormat m_fmt;
bool m_absOffs; bool m_absOffs;
AudioGroupData(unsigned char* proj, size_t projSz, AudioGroupData(unsigned char* proj, size_t projSz, unsigned char* pool, size_t poolSz, unsigned char* sdir,
unsigned char* pool, size_t poolSz, size_t sdirSz, unsigned char* samp, size_t sampSz, DataFormat fmt, bool absOffs)
unsigned char* sdir, size_t sdirSz, : m_proj(proj)
unsigned char* samp, size_t sampSz, , m_projSz(projSz)
DataFormat fmt, bool absOffs) , m_pool(pool)
: m_proj(proj), m_projSz(projSz), , m_poolSz(poolSz)
m_pool(pool), m_poolSz(poolSz), , m_sdir(sdir)
m_sdir(sdir), m_sdirSz(sdirSz), , m_sdirSz(sdirSz)
m_samp(samp), m_sampSz(sampSz), , m_samp(samp)
m_fmt(fmt), m_absOffs(absOffs) {} , m_sampSz(sampSz)
, m_fmt(fmt)
, m_absOffs(absOffs)
{
}
public: public:
AudioGroupData(unsigned char* proj, size_t projSz, AudioGroupData(unsigned char* proj, size_t projSz, unsigned char* pool, size_t poolSz, unsigned char* sdir,
unsigned char* pool, size_t poolSz, size_t sdirSz, unsigned char* samp, size_t sampSz, GCNDataTag)
unsigned char* sdir, size_t sdirSz, : m_proj(proj)
unsigned char* samp, size_t sampSz, GCNDataTag) , m_projSz(projSz)
: m_proj(proj), m_projSz(projSz), , m_pool(pool)
m_pool(pool), m_poolSz(poolSz), , m_poolSz(poolSz)
m_sdir(sdir), m_sdirSz(sdirSz), , m_sdir(sdir)
m_samp(samp), m_sampSz(sampSz), , m_sdirSz(sdirSz)
m_fmt(DataFormat::GCN), m_absOffs(true) {} , m_samp(samp)
AudioGroupData(unsigned char* proj, size_t projSz, , m_sampSz(sampSz)
unsigned char* pool, size_t poolSz, , m_fmt(DataFormat::GCN)
unsigned char* sdir, size_t sdirSz, , m_absOffs(true)
unsigned char* samp, size_t sampSz, bool absOffs, N64DataTag) {
: m_proj(proj), m_projSz(projSz), }
m_pool(pool), m_poolSz(poolSz), AudioGroupData(unsigned char* proj, size_t projSz, unsigned char* pool, size_t poolSz, unsigned char* sdir,
m_sdir(sdir), m_sdirSz(sdirSz), size_t sdirSz, unsigned char* samp, size_t sampSz, bool absOffs, N64DataTag)
m_samp(samp), m_sampSz(sampSz), : m_proj(proj)
m_fmt(DataFormat::N64), m_absOffs(absOffs) {} , m_projSz(projSz)
AudioGroupData(unsigned char* proj, size_t projSz, , m_pool(pool)
unsigned char* pool, size_t poolSz, , m_poolSz(poolSz)
unsigned char* sdir, size_t sdirSz, , m_sdir(sdir)
unsigned char* samp, size_t sampSz, bool absOffs, PCDataTag) , m_sdirSz(sdirSz)
: m_proj(proj), m_projSz(projSz), , m_samp(samp)
m_pool(pool), m_poolSz(poolSz), , m_sampSz(sampSz)
m_sdir(sdir), m_sdirSz(sdirSz), , m_fmt(DataFormat::N64)
m_samp(samp), m_sampSz(sampSz), , m_absOffs(absOffs)
m_fmt(DataFormat::PC), m_absOffs(absOffs) {} {
}
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)
: m_proj(proj)
, m_projSz(projSz)
, m_pool(pool)
, m_poolSz(poolSz)
, m_sdir(sdir)
, m_sdirSz(sdirSz)
, m_samp(samp)
, m_sampSz(sampSz)
, m_fmt(DataFormat::PC)
, 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; }
@ -77,10 +98,7 @@ public:
size_t getSdirSize() const { return m_sdirSz; } size_t getSdirSize() const { return m_sdirSz; }
size_t getSampSize() const { return m_sampSz; } size_t getSampSize() const { return m_sampSz; }
operator bool() const operator bool() const { return m_proj != nullptr && m_pool != nullptr && m_sdir != nullptr && m_samp != nullptr; }
{
return m_proj != nullptr && m_pool != nullptr && m_sdir != nullptr && m_samp != nullptr;
}
DataFormat getDataFormat() const { return m_fmt; } DataFormat getDataFormat() const { return m_fmt; }
bool getAbsoluteProjOffsets() const { return m_absOffs; } bool getAbsoluteProjOffsets() const { return m_absOffs; }
@ -90,6 +108,7 @@ public:
class IntrusiveAudioGroupData : public AudioGroupData class IntrusiveAudioGroupData : public AudioGroupData
{ {
bool m_owns = true; bool m_owns = true;
public: public:
using AudioGroupData::AudioGroupData; using AudioGroupData::AudioGroupData;
~IntrusiveAudioGroupData(); ~IntrusiveAudioGroupData();
@ -102,7 +121,6 @@ public:
void dangleOwnership() { m_owns = false; } void dangleOwnership() { m_owns = false; }
}; };
} }
#endif // __AMUSE_AUDIOGROUPDATA_HPP__ #endif // __AMUSE_AUDIOGROUPDATA_HPP__

View File

@ -33,7 +33,10 @@ struct ADSR
double getAttack() const { return (attackCoarse * 255 + attackFine) / 1000.0; } double getAttack() const { return (attackCoarse * 255 + attackFine) / 1000.0; }
double getDecay() const { return decayCoarse == 128 ? 0.0 : ((decayCoarse * 255 + decayFine) / 1000.0); } double getDecay() const { return decayCoarse == 128 ? 0.0 : ((decayCoarse * 255 + decayFine) / 1000.0); }
double getSustain() const {return decayCoarse == 128 ? 1.0 : ((sustainCoarse * 6.25 + sustainFine * 0.0244) / 100.0);} double getSustain() const
{
return decayCoarse == 128 ? 1.0 : ((sustainCoarse * 6.25 + sustainFine * 0.0244) / 100.0);
}
double getRelease() const { return (releaseCoarse * 255 + releaseFine) / 1000.0; } double getRelease() const { return (releaseCoarse * 255 + releaseFine) / 1000.0; }
}; };
@ -96,6 +99,7 @@ class AudioGroupPool
std::unordered_map<ObjectId, const unsigned char*> m_tables; std::unordered_map<ObjectId, const unsigned char*> m_tables;
std::unordered_map<ObjectId, const Keymap*> m_keymaps; std::unordered_map<ObjectId, const Keymap*> m_keymaps;
std::unordered_map<ObjectId, std::vector<const LayerMapping*>> m_layers; std::unordered_map<ObjectId, std::vector<const LayerMapping*>> m_layers;
public: public:
AudioGroupPool(const unsigned char* data); AudioGroupPool(const unsigned char* data);
AudioGroupPool(const unsigned char* data, PCDataTag); AudioGroupPool(const unsigned char* data, PCDataTag);
@ -103,12 +107,9 @@ public:
const Keymap* keymap(ObjectId id) const; const Keymap* keymap(ObjectId id) const;
const std::vector<const LayerMapping*>* layer(ObjectId id) const; const std::vector<const LayerMapping*>* layer(ObjectId id) const;
const ADSR* tableAsAdsr(ObjectId id) const; const ADSR* tableAsAdsr(ObjectId id) const;
const ADSRDLS* tableAsAdsrDLS(ObjectId id) const const ADSRDLS* tableAsAdsrDLS(ObjectId id) const { return reinterpret_cast<const ADSRDLS*>(tableAsAdsr(id)); }
{return reinterpret_cast<const ADSRDLS*>(tableAsAdsr(id));} const Curve* tableAsCurves(ObjectId id) const { return reinterpret_cast<const Curve*>(tableAsAdsr(id)); }
const Curve* tableAsCurves(ObjectId id) const
{return reinterpret_cast<const Curve*>(tableAsAdsr(id));}
}; };
} }
#endif // __AMUSE_AUDIOGROUPPOOL_HPP__ #endif // __AMUSE_AUDIOGROUPPOOL_HPP__

View File

@ -91,7 +91,6 @@ public:
const std::unordered_map<int, SongGroupIndex>& songGroups() const { return m_songGroups; } const std::unordered_map<int, SongGroupIndex>& songGroups() const { return m_songGroups; }
const std::unordered_map<int, SFXGroupIndex>& sfxGroups() const { return m_sfxGroups; } const std::unordered_map<int, SFXGroupIndex>& sfxGroups() const { return m_sfxGroups; }
}; };
} }
#endif // __AMUSE_AUDIOGROUPPROJECT_HPP__ #endif // __AMUSE_AUDIOGROUPPROJECT_HPP__

View File

@ -12,6 +12,7 @@ namespace amuse
class AudioGroupSampleDirectory class AudioGroupSampleDirectory
{ {
friend class AudioGroup; friend class AudioGroup;
public: public:
struct Entry struct Entry
{ {
@ -26,8 +27,7 @@ public:
uint32_t m_adpcmParmOffset; uint32_t m_adpcmParmOffset;
void swapBig(); void swapBig();
}; };
union ADPCMParms union ADPCMParms {
{
struct DSPParms struct DSPParms
{ {
uint16_t m_bytesPerFrame; uint16_t m_bytesPerFrame;
@ -44,17 +44,17 @@ public:
void swapBigDSP(); void swapBigDSP();
void swapBigVADPCM(); void swapBigVADPCM();
}; };
private: private:
std::unordered_map<uint16_t, std::pair<Entry, ADPCMParms>> m_entries; std::unordered_map<uint16_t, std::pair<Entry, ADPCMParms>> m_entries;
public: public:
AudioGroupSampleDirectory(const unsigned char* data, GCNDataTag); AudioGroupSampleDirectory(const unsigned char* data, GCNDataTag);
AudioGroupSampleDirectory(const unsigned char* data, const unsigned char* sampData, AudioGroupSampleDirectory(const unsigned char* data, const unsigned char* sampData, bool absOffs, N64DataTag);
bool absOffs, N64DataTag);
AudioGroupSampleDirectory(const unsigned char* data, bool absOffs, PCDataTag); AudioGroupSampleDirectory(const unsigned char* data, bool absOffs, PCDataTag);
const std::unordered_map<uint16_t, std::pair<Entry, ADPCMParms>>& sampleEntries() const { return m_entries; } const std::unordered_map<uint16_t, std::pair<Entry, ADPCMParms>>& sampleEntries() const { return m_entries; }
}; };
} }
#endif // __AMUSE_AUDIOGROUPSAMPLEDIR_HPP__ #endif // __AMUSE_AUDIOGROUPSAMPLEDIR_HPP__

View File

@ -24,12 +24,15 @@ class BooBackendVoice : public IBackendVoice
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);
void routeAudio(size_t frames, double dt, int busId, int16_t* in, int16_t* out);
void routeAudio(size_t frames, double dt, int busId, int32_t* in, int32_t* out);
void routeAudio(size_t frames, double dt, int busId, float* in, float* out);
VoiceCallback(BooBackendVoice& parent) : m_parent(parent) {} VoiceCallback(BooBackendVoice& parent) : m_parent(parent) {}
} m_cb; } m_cb;
std::unique_ptr<boo::IAudioVoice> m_booVoice; std::unique_ptr<boo::IAudioVoice> m_booVoice;
public: public:
BooBackendVoice(boo::IAudioVoiceEngine& engine, Voice& clientVox, BooBackendVoice(boo::IAudioVoiceEngine& engine, Voice& clientVox, double sampleRate, bool dynamicPitch);
double sampleRate, bool dynamicPitch);
void resetSampleRate(double sampleRate); void resetSampleRate(double sampleRate);
void resetChannelLevels(); void resetChannelLevels();
@ -49,18 +52,16 @@ class BooBackendSubmix : public IBackendSubmix
{ {
BooBackendSubmix& m_parent; BooBackendSubmix& m_parent;
bool canApplyEffect() const; bool canApplyEffect() const;
void applyEffect(int16_t* audio, size_t frameCount, void applyEffect(int16_t* audio, size_t frameCount, const boo::ChannelMap& chanMap, double sampleRate) const;
const boo::ChannelMap& chanMap, double sampleRate) const; void applyEffect(int32_t* audio, size_t frameCount, const boo::ChannelMap& chanMap, double sampleRate) const;
void applyEffect(int32_t* audio, size_t frameCount, void applyEffect(float* audio, size_t frameCount, const boo::ChannelMap& chanMap, double sampleRate) const;
const boo::ChannelMap& chanMap, double sampleRate) const;
void applyEffect(float* audio, size_t frameCount,
const boo::ChannelMap& chanMap, double sampleRate) const;
void resetOutputSampleRate(double sampleRate); void resetOutputSampleRate(double sampleRate);
SubmixCallback(BooBackendSubmix& parent) : m_parent(parent) {} SubmixCallback(BooBackendSubmix& parent) : m_parent(parent) {}
} m_cb; } m_cb;
std::unique_ptr<boo::IAudioSubmix> m_booSubmix; std::unique_ptr<boo::IAudioSubmix> m_booSubmix;
public: public:
BooBackendSubmix(boo::IAudioVoiceEngine& engine, Submix& clientSmx, bool mainOut); BooBackendSubmix(boo::IAudioVoiceEngine& engine, Submix& clientSmx, bool mainOut, int busId);
void setSendLevel(IBackendSubmix* submix, float level, bool slew); void setSendLevel(IBackendSubmix* submix, float level, bool slew);
double getSampleRate() const; double getSampleRate() const;
SubmixFormat getSampleFormat() const; SubmixFormat getSampleFormat() const;
@ -119,17 +120,17 @@ class BooBackendVoiceAllocator : public IBackendVoiceAllocator
{ {
friend class BooBackendMIDIReader; friend class BooBackendMIDIReader;
boo::IAudioVoiceEngine& m_booEngine; boo::IAudioVoiceEngine& m_booEngine;
public: public:
BooBackendVoiceAllocator(boo::IAudioVoiceEngine& booEngine); BooBackendVoiceAllocator(boo::IAudioVoiceEngine& booEngine);
std::unique_ptr<IBackendVoice> allocateVoice(Voice& clientVox, double sampleRate, bool dynamicPitch); std::unique_ptr<IBackendVoice> allocateVoice(Voice& clientVox, double sampleRate, bool dynamicPitch);
std::unique_ptr<IBackendSubmix> allocateSubmix(Submix& clientSmx, bool mainOut); std::unique_ptr<IBackendSubmix> allocateSubmix(Submix& clientSmx, bool mainOut, int busId);
std::vector<std::pair<std::string, std::string>> enumerateMIDIDevices(); std::vector<std::pair<std::string, std::string>> enumerateMIDIDevices();
std::unique_ptr<IMIDIReader> allocateMIDIReader(Engine& engine, const char* name = nullptr); std::unique_ptr<IMIDIReader> allocateMIDIReader(Engine& engine, const char* name = nullptr);
void register5MsCallback(std::function<void(double)>&& callback); void register5MsCallback(std::function<void(double)>&& callback);
AudioChannelSet getAvailableSet(); AudioChannelSet getAvailableSet();
void pumpAndMixVoices(); void pumpAndMixVoices();
}; };
} }
#endif // __AMUSE_BOO_BACKEND_HPP__ #endif // __AMUSE_BOO_BACKEND_HPP__

View File

@ -46,10 +46,7 @@ namespace amuse
#endif #endif
#if _WIN32 #if _WIN32
static inline int CompareCaseInsensitive(const char* a, const char* b) static inline int CompareCaseInsensitive(const char* a, const char* b) { return _stricmp(a, 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)
@ -62,10 +59,16 @@ 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) {return std::max<T>(a, std::min<T>(b, val));} static inline T clamp(T a, T val, T b)
{
return std::max<T>(a, std::min<T>(b, val));
}
template <typename T> template <typename T>
static inline T ClampFull(float in) {return in;} static inline T ClampFull(float in)
{
return in;
}
template <> template <>
inline int16_t ClampFull<int16_t>(float in) inline int16_t ClampFull<int16_t>(float in)
@ -100,7 +103,8 @@ inline float ClampFull<float>(float in)
#if __GNUC__ #if __GNUC__
__attribute__((__format__(__printf__, 1, 2))) __attribute__((__format__(__printf__, 1, 2)))
#endif #endif
static inline void Printf(const SystemChar* fmt, ...) static inline void
Printf(const SystemChar* fmt, ...)
{ {
va_list args; va_list args;
va_start(args, fmt); va_start(args, fmt);
@ -115,7 +119,8 @@ static inline void Printf(const SystemChar* fmt, ...)
#if __GNUC__ #if __GNUC__
__attribute__((__format__(__printf__, 3, 4))) __attribute__((__format__(__printf__, 3, 4)))
#endif #endif
static inline void SNPrintf(SystemChar* str, size_t maxlen, const SystemChar* format, ...) static inline void
SNPrintf(SystemChar* str, size_t maxlen, const SystemChar* format, ...)
{ {
va_list va; va_list va;
va_start(va, format); va_start(va, format);
@ -220,14 +225,10 @@ static inline T bswap64(T val)
#elif _WIN32 #elif _WIN32
return _byteswap_uint64(val); return _byteswap_uint64(val);
#else #else
return ((val & 0xFF00000000000000ULL) >> 56) | return ((val & 0xFF00000000000000ULL) >> 56) | ((val & 0x00FF000000000000ULL) >> 40) |
((val & 0x00FF000000000000ULL) >> 40) | ((val & 0x0000FF0000000000ULL) >> 24) | ((val & 0x000000FF00000000ULL) >> 8) |
((val & 0x0000FF0000000000ULL) >> 24) | ((val & 0x00000000FF000000ULL) << 8) | ((val & 0x0000000000FF0000ULL) << 24) |
((val & 0x000000FF00000000ULL) >> 8) | ((val & 0x000000000000FF00ULL) << 40) | ((val & 0x00000000000000FFULL) << 56);
((val & 0x00000000FF000000ULL) << 8) |
((val & 0x0000000000FF0000ULL) << 24) |
((val & 0x000000000000FF00ULL) << 40) |
((val & 0x00000000000000FFULL) << 56);
#endif #endif
} }
@ -249,8 +250,7 @@ static inline double SBig(double val)
return *((double*)(&ival)); return *((double*)(&ival));
} }
#ifndef SBIG #ifndef SBIG
#define SBIG(q) ( ( (q) & 0x000000FF ) << 24 | ( (q) & 0x0000FF00 ) << 8 \ #define SBIG(q) (((q)&0x000000FF) << 24 | ((q)&0x0000FF00) << 8 | ((q)&0x00FF0000) >> 8 | ((q)&0xFF000000) >> 24)
| ( (q) & 0x00FF0000 ) >> 8 | ( (q) & 0xFF000000 ) >> 24 )
#endif #endif
static inline int16_t SLittle(int16_t val) { return val; } static inline int16_t SLittle(int16_t val) { return val; }
@ -282,8 +282,7 @@ static inline double SLittle(double val)
return *((double*)(&ival)); return *((double*)(&ival));
} }
#ifndef SLITTLE #ifndef SLITTLE
#define SLITTLE(q) ( ( (q) & 0x000000FF ) << 24 | ( (q) & 0x0000FF00 ) << 8 \ #define SLITTLE(q) (((q)&0x000000FF) << 24 | ((q)&0x0000FF00) << 8 | ((q)&0x00FF0000) >> 8 | ((q)&0xFF000000) >> 24)
| ( (q) & 0x00FF0000 ) >> 8 | ( (q) & 0xFF000000 ) >> 24 )
#endif #endif
static inline int16_t SBig(int16_t val) { return val; } static inline int16_t SBig(int16_t val) { return val; }
@ -308,14 +307,19 @@ enum class DataFormat
}; };
/** 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
{
};
} }
#endif // __AMUSE_COMMON_HPP__ #endif // __AMUSE_COMMON_HPP__

View File

@ -33,15 +33,17 @@ public:
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);
static std::vector<std::pair<SystemString, IntrusiveAudioGroupData>> LoadContainer(const SystemChar* path); static std::vector<std::pair<SystemString, IntrusiveAudioGroupData>> LoadContainer(const SystemChar* path);
static std::vector<std::pair<SystemString, IntrusiveAudioGroupData>> LoadContainer(const SystemChar* path, Type& typeOut); static std::vector<std::pair<SystemString, IntrusiveAudioGroupData>> LoadContainer(const SystemChar* path,
Type& typeOut);
static std::vector<std::pair<SystemString, SongData>> LoadSongs(const SystemChar* path); static std::vector<std::pair<SystemString, SongData>> LoadSongs(const SystemChar* path);
}; };
} }
#endif // __AMUSE_CONTAINERREGISTRY_HPP__ #endif // __AMUSE_CONTAINERREGISTRY_HPP__

View File

@ -50,25 +50,28 @@ public:
private: private:
friend class DirectoryEnumerator; friend class DirectoryEnumerator;
Entry(SystemString&& path, const SystemChar* name, size_t sz, bool isDir) Entry(SystemString&& path, const SystemChar* name, size_t sz, bool isDir)
: m_path(std::move(path)), m_name(name), m_fileSz(sz), m_isDir(isDir) {} : m_path(std::move(path)), m_name(name), m_fileSz(sz), m_isDir(isDir)
{
}
}; };
private: private:
std::vector<Entry> m_entries; std::vector<Entry> m_entries;
public: public:
DirectoryEnumerator(const SystemString& path, Mode mode=Mode::DirsThenFilesSorted, DirectoryEnumerator(const SystemString& path, Mode mode = Mode::DirsThenFilesSorted, bool sizeSort = false,
bool sizeSort=false, bool reverse=false, bool noHidden=false) bool reverse = false, bool noHidden = false)
: DirectoryEnumerator(path.c_str(), mode, sizeSort, reverse, noHidden) {} : DirectoryEnumerator(path.c_str(), mode, sizeSort, reverse, noHidden)
DirectoryEnumerator(const SystemChar* path, Mode mode=Mode::DirsThenFilesSorted, {
bool sizeSort=false, bool reverse=false, bool noHidden=false); }
DirectoryEnumerator(const SystemChar* path, Mode mode = Mode::DirsThenFilesSorted, bool sizeSort = false,
bool reverse = false, bool noHidden = false);
operator bool() const { return m_entries.size() != 0; } operator bool() const { return m_entries.size() != 0; }
size_t size() const { return m_entries.size(); } size_t size() const { return m_entries.size(); }
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(); }
}; };
} }
#endif // __AMUSE_DIRECTORY_ENUMERATOR__ #endif // __AMUSE_DIRECTORY_ENUMERATOR__

View File

@ -21,7 +21,6 @@ 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;
}; };
} }
#endif // __AMUSE_EFFECTBASE_HPP__ #endif // __AMUSE_EFFECTBASE_HPP__

View File

@ -23,6 +23,7 @@ class EffectChorus
template <typename T> template <typename T>
friend class EffectChorusImp; friend class EffectChorusImp;
EffectChorus(uint32_t baseDelay, uint32_t variation, uint32_t period); EffectChorus(uint32_t baseDelay, uint32_t variation, uint32_t period);
public: public:
template <typename T> template <typename T>
using ImpType = EffectChorusImp<T>; using ImpType = EffectChorusImp<T>;
@ -93,7 +94,6 @@ public:
void applyEffect(T* audio, size_t frameCount, const ChannelMap& chanMap); void applyEffect(T* audio, size_t frameCount, const ChannelMap& chanMap);
void resetOutputSampleRate(double sampleRate) { _setup(sampleRate); } void resetOutputSampleRate(double sampleRate) { _setup(sampleRate); }
}; };
} }
#endif // __AMUSE_EFFECTCHORUS_HPP__ #endif // __AMUSE_EFFECTCHORUS_HPP__

View File

@ -82,12 +82,12 @@ class EffectDelayImp : public EffectBase<T>, public EffectDelay
uint32_t m_blockSamples; /**< count of samples in a 5ms block */ uint32_t m_blockSamples; /**< count of samples in a 5ms block */
void _setup(double sampleRate); void _setup(double sampleRate);
void _update(); void _update();
public: public:
EffectDelayImp(uint32_t initDelay, uint32_t initFeedback, uint32_t initOutput, double sampleRate); EffectDelayImp(uint32_t initDelay, uint32_t initFeedback, uint32_t initOutput, double sampleRate);
void applyEffect(T* audio, size_t frameCount, const ChannelMap& chanMap); void applyEffect(T* audio, size_t frameCount, const ChannelMap& chanMap);
void resetOutputSampleRate(double sampleRate) { _setup(sampleRate); } void resetOutputSampleRate(double sampleRate) { _setup(sampleRate); }
}; };
} }
#endif // __AMUSE_EFFECTDELAY_HPP__ #endif // __AMUSE_EFFECTDELAY_HPP__

View File

@ -31,7 +31,8 @@ class EffectReverbHiImp;
class EffectReverbStd class EffectReverbStd
{ {
protected: protected:
float x140_x1c8_coloration; /**< [0.0, 1.0] influences filter coefficients to define surface characteristics of a room */ float x140_x1c8_coloration; /**< [0.0, 1.0] influences filter coefficients to define surface characteristics of a
room */
float x144_x1cc_mix; /**< [0.0, 1.0] dry/wet mix factor of reverb effect */ float x144_x1cc_mix; /**< [0.0, 1.0] dry/wet mix factor of reverb effect */
float x148_x1d0_time; /**< [0.01, 10.0] time in seconds for reflection decay */ float x148_x1d0_time; /**< [0.01, 10.0] time in seconds for reflection decay */
float x14c_x1d4_damping; /**< [0.0, 1.0] damping factor influencing low-pass filter of reflections */ float x14c_x1d4_damping; /**< [0.0, 1.0] damping factor influencing low-pass filter of reflections */
@ -42,8 +43,8 @@ protected:
friend class EffectReverbStdImp; friend class EffectReverbStdImp;
template <typename T> template <typename T>
friend class EffectReverbHiImp; friend class EffectReverbHiImp;
EffectReverbStd(float coloration, float mix, float time, EffectReverbStd(float coloration, float mix, float time, float damping, float preDelay);
float damping, float preDelay);
public: public:
template <typename T> template <typename T>
using ImpType = EffectReverbStdImp<T>; using ImpType = EffectReverbStdImp<T>;
@ -86,8 +87,8 @@ class EffectReverbHi : public EffectReverbStd
template <typename T> template <typename T>
friend class EffectReverbHiImp; friend class EffectReverbHiImp;
EffectReverbHi(float coloration, float mix, float time, EffectReverbHi(float coloration, float mix, float time, float damping, float preDelay, float crosstalk);
float damping, float preDelay, float crosstalk);
public: public:
template <typename T> template <typename T>
using ImpType = EffectReverbHiImp<T>; using ImpType = EffectReverbHiImp<T>;
@ -117,9 +118,9 @@ class EffectReverbStdImp : public EffectBase<T>, public EffectReverbStd
double m_sampleRate; /**< copy of sample rate */ double m_sampleRate; /**< copy of sample rate */
void _setup(double sampleRate); void _setup(double sampleRate);
void _update(); void _update();
public: public:
EffectReverbStdImp(float coloration, float mix, float time, EffectReverbStdImp(float coloration, float mix, float time, float damping, float preDelay, double sampleRate);
float damping, float preDelay, double sampleRate);
void applyEffect(T* audio, size_t frameCount, const ChannelMap& chanMap); void applyEffect(T* audio, size_t frameCount, const ChannelMap& chanMap);
void resetOutputSampleRate(double sampleRate) { _setup(sampleRate); } void resetOutputSampleRate(double sampleRate) { _setup(sampleRate); }
}; };
@ -146,13 +147,13 @@ class EffectReverbHiImp : public EffectBase<T>, public EffectReverbHi
void _update(); void _update();
void _handleReverb(T* audio, int chanIdx, int chanCount, int sampleCount); void _handleReverb(T* audio, int chanIdx, int chanCount, int sampleCount);
void _doCrosstalk(T* audio, float wet, float dry, int chanCount, int sampleCount); void _doCrosstalk(T* audio, float wet, float dry, int chanCount, int sampleCount);
public: public:
EffectReverbHiImp(float coloration, float mix, float time, EffectReverbHiImp(float coloration, float mix, float time, float damping, float preDelay, float crosstalk,
float damping, float preDelay, float crosstalk, double sampleRate); double sampleRate);
void applyEffect(T* audio, size_t frameCount, const ChannelMap& chanMap); void applyEffect(T* audio, size_t frameCount, const ChannelMap& chanMap);
void resetOutputSampleRate(double sampleRate) { _setup(sampleRate); } void resetOutputSampleRate(double sampleRate) { _setup(sampleRate); }
}; };
} }
#endif // __AMUSE_EFFECTREVERB_HPP__ #endif // __AMUSE_EFFECTREVERB_HPP__

View File

@ -17,6 +17,7 @@ class Emitter : public Entity
friend class Engine; friend class Engine;
void _destroy(); void _destroy();
public: public:
~Emitter(); ~Emitter();
Emitter(Engine& engine, const AudioGroup& group, std::shared_ptr<Voice>&& vox); Emitter(Engine& engine, const AudioGroup& group, std::shared_ptr<Voice>&& vox);
@ -30,7 +31,6 @@ public:
std::shared_ptr<Voice>& getVoice() { return m_vox; } std::shared_ptr<Voice>& getVoice() { return m_vox; }
}; };
} }
#endif // __AMUSE_EMITTER_HPP__ #endif // __AMUSE_EMITTER_HPP__

View File

@ -33,17 +33,19 @@ class Engine
friend class Voice; friend class Voice;
friend class Emitter; friend class Emitter;
friend class Sequencer; friend class Sequencer;
friend class Studio;
friend struct Sequencer::ChannelState; friend struct Sequencer::ChannelState;
IBackendVoiceAllocator& m_backend; IBackendVoiceAllocator& m_backend;
AmplitudeMode m_ampMode; AmplitudeMode m_ampMode;
std::unique_ptr<IMIDIReader> m_midiReader; std::unique_ptr<IMIDIReader> m_midiReader;
std::shared_ptr<Studio> m_defaultStudio;
std::unordered_map<const AudioGroupData*, std::unique_ptr<AudioGroup>> m_audioGroups; std::unordered_map<const AudioGroupData*, std::unique_ptr<AudioGroup>> m_audioGroups;
std::list<std::shared_ptr<Voice>> m_activeVoices; std::list<std::shared_ptr<Voice>> m_activeVoices;
std::list<std::shared_ptr<Emitter>> m_activeEmitters; std::list<std::shared_ptr<Emitter>> m_activeEmitters;
std::list<std::shared_ptr<Sequencer>> m_activeSequencers; std::list<std::shared_ptr<Sequencer>> m_activeSequencers;
std::list<std::shared_ptr<Studio>> m_activeStudios; std::list<std::weak_ptr<Studio>> m_activeStudios; /* lifetime dependent on contributing audio entities */
bool m_defaultStudioReady = false;
std::shared_ptr<Studio> m_defaultStudio;
std::unordered_map<uint16_t, std::tuple<AudioGroup*, int, const SFXGroupIndex::SFXEntry*>> m_sfxLookup; std::unordered_map<uint16_t, std::tuple<AudioGroup*, int, const SFXGroupIndex::SFXEntry*>> m_sfxLookup;
std::linear_congruential_engine<uint32_t, 0x41c64e6d, 0x3039, UINT32_MAX> m_random; std::linear_congruential_engine<uint32_t, 0x41c64e6d, 0x3039, UINT32_MAX> m_random;
int m_nextVid = 0; int m_nextVid = 0;
@ -52,19 +54,18 @@ class Engine
std::pair<AudioGroup*, const SongGroupIndex*> _findSongGroup(int groupId) const; std::pair<AudioGroup*, const SongGroupIndex*> _findSongGroup(int groupId) const;
std::pair<AudioGroup*, const SFXGroupIndex*> _findSFXGroup(int groupId) const; std::pair<AudioGroup*, const SFXGroupIndex*> _findSFXGroup(int groupId) const;
std::list<std::shared_ptr<Voice>>::iterator std::list<std::shared_ptr<Voice>>::iterator _allocateVoice(const AudioGroup& group, int groupId, double sampleRate,
_allocateVoice(const AudioGroup& group, int groupId, double sampleRate, bool dynamicPitch, bool emitter,
bool dynamicPitch, bool emitter, std::weak_ptr<Studio> studio); std::weak_ptr<Studio> studio);
std::list<std::shared_ptr<Sequencer>>::iterator std::list<std::shared_ptr<Sequencer>>::iterator _allocateSequencer(const AudioGroup& group, int groupId,
_allocateSequencer(const AudioGroup& group, int groupId,
int setupId, std::weak_ptr<Studio> studio); int setupId, std::weak_ptr<Studio> studio);
std::list<std::shared_ptr<Studio>>::iterator _allocateStudio(bool mainOut); std::shared_ptr<Studio> _allocateStudio(bool mainOut);
std::list<std::shared_ptr<Voice>>::iterator _destroyVoice(std::list<std::shared_ptr<Voice>>::iterator it); std::list<std::shared_ptr<Voice>>::iterator _destroyVoice(std::list<std::shared_ptr<Voice>>::iterator it);
std::list<std::shared_ptr<Sequencer>>::iterator _destroySequencer(std::list<std::shared_ptr<Sequencer>>::iterator it); std::list<std::shared_ptr<Sequencer>>::iterator
std::list<std::shared_ptr<Studio>>::iterator _destroyStudio(std::list<std::shared_ptr<Studio>>::iterator it); _destroySequencer(std::list<std::shared_ptr<Sequencer>>::iterator it);
std::list<std::shared_ptr<Studio>>::iterator _removeStudio(std::list<std::shared_ptr<Studio>>::iterator it);
void _bringOutYourDead(); void _bringOutYourDead();
void _5MsCallback(double dt); void _5MsCallback(double dt);
public: public:
~Engine(); ~Engine();
Engine(IBackendVoiceAllocator& backend, AmplitudeMode ampMode = AmplitudeMode::PerSample); Engine(IBackendVoiceAllocator& backend, AmplitudeMode ampMode = AmplitudeMode::PerSample);
@ -87,9 +88,6 @@ public:
/** Create new Studio within engine */ /** Create new Studio within engine */
std::shared_ptr<Studio> addStudio(bool mainOut); std::shared_ptr<Studio> addStudio(bool mainOut);
/** Remove Studio from engine */
void removeStudio(std::weak_ptr<Studio> studio);
/** Start soundFX playing from loaded audio groups */ /** Start soundFX playing from loaded audio groups */
std::shared_ptr<Voice> fxStart(int sfxId, float vol, float pan, std::weak_ptr<Studio> smx); std::shared_ptr<Voice> fxStart(int sfxId, float vol, float pan, std::weak_ptr<Studio> smx);
std::shared_ptr<Voice> fxStart(int sfxId, float vol, float pan) std::shared_ptr<Voice> fxStart(int sfxId, float vol, float pan)
@ -98,9 +96,8 @@ public:
} }
/** Start soundFX playing from loaded audio groups, attach to positional emitter */ /** Start soundFX playing from loaded audio groups, attach to positional emitter */
std::shared_ptr<Emitter> addEmitter(const Vector3f& pos, const Vector3f& dir, float maxDist, std::shared_ptr<Emitter> addEmitter(const Vector3f& pos, const Vector3f& dir, float maxDist, float falloff,
float falloff, int sfxId, float minVol, float maxVol, int sfxId, float minVol, float maxVol, std::weak_ptr<Studio> smx);
std::weak_ptr<Studio> smx);
/** Start song playing from loaded audio groups */ /** Start song playing from loaded audio groups */
std::shared_ptr<Sequencer> seqPlay(int groupId, int songId, const unsigned char* arrData, std::shared_ptr<Sequencer> seqPlay(int groupId, int songId, const unsigned char* arrData,
@ -125,7 +122,6 @@ public:
/** Obtain list of active sequencers */ /** Obtain list of active sequencers */
std::list<std::shared_ptr<Sequencer>>& getActiveSequencers() { return m_activeSequencers; } std::list<std::shared_ptr<Sequencer>>& getActiveSequencers() { return m_activeSequencers; }
}; };
} }
#endif // __AMUSE_ENGINE_HPP__ #endif // __AMUSE_ENGINE_HPP__

View File

@ -21,6 +21,7 @@ class Entity
* 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;
friend class SoundMacroState; friend class SoundMacroState;
protected: protected:
bool m_destroyed = false; bool m_destroyed = false;
void _destroy() void _destroy()
@ -36,7 +37,9 @@ protected:
ObjectId m_objectId = 0xffff; /* if applicable */ ObjectId m_objectId = 0xffff; /* if applicable */
public: public:
Entity(Engine& engine, const AudioGroup& group, int groupId, ObjectId oid = ObjectId()) Entity(Engine& engine, const AudioGroup& group, int 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()
{ {
#ifndef NDEBUG #ifndef NDEBUG
@ -54,7 +57,6 @@ public:
/** Curves for mapping velocity to volume and other functional mappings /** Curves for mapping velocity to volume and other functional mappings
* (defined here for visibility)*/ * (defined here for visibility)*/
using Curve = uint8_t[128]; using Curve = uint8_t[128];
} }
#endif // __AMUSE_ENTITY_HPP__ #endif // __AMUSE_ENTITY_HPP__

View File

@ -19,6 +19,7 @@ public:
Release, Release,
Complete Complete
}; };
private: private:
State m_phase = State::Attack; /**< Current envelope state */ State m_phase = State::Attack; /**< Current envelope state */
double m_attackTime = 0.0; /**< Time of attack in seconds */ double m_attackTime = 0.0; /**< Time of attack in seconds */
@ -28,6 +29,7 @@ private:
double m_releaseStartFactor = 0.0; /**< Level at whenever release event occurs */ double m_releaseStartFactor = 0.0; /**< Level at whenever release event occurs */
double m_curTime = 0.0; /**< Current time of envelope stage in seconds */ double m_curTime = 0.0; /**< Current time of envelope stage in seconds */
bool m_adsrSet = false; bool m_adsrSet = false;
public: public:
void reset(const ADSR* adsr); void reset(const ADSR* adsr);
void reset(const ADSRDLS* adsr, int8_t note, int8_t vel); void reset(const ADSRDLS* adsr, int8_t note, int8_t vel);
@ -38,7 +40,6 @@ 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; }
}; };
} }
#endif // __AMUSE_ENVELOPE_HPP__ #endif // __AMUSE_ENVELOPE_HPP__

View File

@ -30,7 +30,6 @@ 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;
}; };
} }
#endif // __AMUSE_IBACKENDSUBMIX_HPP__ #endif // __AMUSE_IBACKENDSUBMIX_HPP__

View File

@ -50,7 +50,6 @@ public:
/** Instructs platform to stop consuming sample data */ /** Instructs platform to stop consuming sample data */
virtual void stop() = 0; virtual void stop() = 0;
}; };
} }
#endif // __AMUSE_IBACKENDVOICE_HPP__ #endif // __AMUSE_IBACKENDVOICE_HPP__

View File

@ -39,12 +39,10 @@ public:
virtual ~IBackendVoiceAllocator() = default; virtual ~IBackendVoiceAllocator() = default;
/** Amuse obtains a new voice from the platform this way */ /** Amuse obtains a new voice from the platform this way */
virtual std::unique_ptr<IBackendVoice> allocateVoice(Voice& clientVox, virtual std::unique_ptr<IBackendVoice> allocateVoice(Voice& clientVox, double sampleRate, bool dynamicPitch) = 0;
double sampleRate,
bool dynamicPitch)=0;
/** Amuse obtains a new submix from the platform this way */ /** Amuse obtains a new submix from the platform this way */
virtual std::unique_ptr<IBackendSubmix> allocateSubmix(Submix& clientSmx, bool mainOut)=0; virtual std::unique_ptr<IBackendSubmix> allocateSubmix(Submix& clientSmx, bool mainOut, int busId) = 0;
/** Amuse obtains a list of all MIDI devices this way */ /** Amuse obtains a list of all MIDI devices this way */
virtual std::vector<std::pair<std::string, std::string>> enumerateMIDIDevices() = 0; virtual std::vector<std::pair<std::string, std::string>> enumerateMIDIDevices() = 0;
@ -61,7 +59,6 @@ public:
/** Amuse may request callbacks 200-updates-per-second virtually */ /** Amuse may request callbacks 200-updates-per-second virtually */
virtual void register5MsCallback(std::function<void(double dt)>&& callback) = 0; virtual void register5MsCallback(std::function<void(double dt)>&& callback) = 0;
}; };
} }
#endif // __AMUSE_IBACKENDVOICEALLOCATOR_HPP__ #endif // __AMUSE_IBACKENDVOICEALLOCATOR_HPP__

View File

@ -9,7 +9,6 @@ namespace amuse
class Listener : public Entity class Listener : public Entity
{ {
}; };
} }
#endif // __AMUSE_LISTENER_HPP__ #endif // __AMUSE_LISTENER_HPP__

View File

@ -84,10 +84,10 @@ class Sequencer : public Entity
public: public:
~Sequencer(); ~Sequencer();
Sequencer(Engine& engine, const AudioGroup& group, int groupId, Sequencer(Engine& engine, const AudioGroup& group, int groupId, const SongGroupIndex* songGroup, int setupId,
const SongGroupIndex* songGroup, int setupId, std::weak_ptr<Studio> studio); std::weak_ptr<Studio> studio);
Sequencer(Engine& engine, const AudioGroup& group, int groupId, Sequencer(Engine& engine, const AudioGroup& group, int groupId, const SFXGroupIndex* sfxGroup,
const SFXGroupIndex* sfxGroup, std::weak_ptr<Studio> studio); std::weak_ptr<Studio> studio);
/** Advance current song data (if any) */ /** Advance current song data (if any) */
void advance(double dt); void advance(double dt);
@ -155,7 +155,6 @@ 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; }
}; };
} }
#endif // __AMUSE_SEQUENCER_HPP__ #endif // __AMUSE_SEQUENCER_HPP__

View File

@ -13,7 +13,6 @@ 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);
}; };
} }
#endif // __AMUSE_SONGCONVERTER_HPP__ #endif // __AMUSE_SONGCONVERTER_HPP__

View File

@ -86,7 +86,8 @@ class SongState
std::array<int, 128> m_remNoteLengths; /**< Remaining ticks per note */ std::array<int, 128> m_remNoteLengths; /**< Remaining ticks per note */
int32_t m_eventWaitCountdown = 0; /**< Current wait in ticks */ int32_t m_eventWaitCountdown = 0; /**< Current wait in ticks */
int32_t m_lastN64EventTick = 0; /**< Last command time on this channel (for computing delta times from absolute times in N64 songs) */ int32_t m_lastN64EventTick =
0; /**< Last command time on this channel (for computing delta times from absolute times in N64 songs) */
Track(SongState& parent, uint8_t midiChan, const TrackRegion* regions); Track(SongState& parent, uint8_t midiChan, const TrackRegion* regions);
void setRegion(Sequencer* seq, const TrackRegion* region); void setRegion(Sequencer* seq, const TrackRegion* region);
@ -121,7 +122,6 @@ public:
/** Get current song tempo in BPM */ /** Get current song tempo in BPM */
uint32_t getTempo() const { return m_tempo; } uint32_t getTempo() const { return m_tempo; }
}; };
} }
#endif // __AMUSE_SONGSTATE_HPP__ #endif // __AMUSE_SONGSTATE_HPP__

View File

@ -72,33 +72,33 @@ class SoundMacroState
SendMessage, SendMessage,
GetMessage, GetMessage,
GetVid, GetVid,
AddAgeCount = 0x30, AddAgeCount = 0x30, /* unimplemented */
SetAgeCount, SetAgeCount, /* unimplemented */
SendFlag, SendFlag, /* unimplemented */
PitchWheelR, PitchWheelR,
SetPriority, SetPriority, /* unimplemented */
AddPriority, AddPriority, /* unimplemented */
AgeCntSpeed, AgeCntSpeed, /* unimplemented */
AgeCntVel, AgeCntVel, /* unimplemented */
VolSelect = 0x40, VolSelect = 0x40,
PanSelect, PanSelect,
PitchWheelSelect, PitchWheelSelect,
ModWheelSelect, ModWheelSelect,
PedalSelect, PedalSelect,
PortamentoSelect, PortamentoSelect,
ReverbSelect, ReverbSelect, /* serves as PostASelect */
SpanSelect, SpanSelect,
DopplerSelect, DopplerSelect,
TremoloSelect, TremoloSelect,
PreASelect, PreASelect,
PreBSelect, PreBSelect,
PostBSelect, PostBSelect,
AuxAFXSelect, AuxAFXSelect, /* unimplemented */
AuxBFXSelect, AuxBFXSelect, /* unimplemented */
SetupLFO = 0x50, SetupLFO = 0x50,
ModeSelect = 0x58, ModeSelect = 0x58,
SetKeygroup, SetKeygroup,
SRCmodeSelect, SRCmodeSelect, /* unimplemented */
AddVars = 0x60, AddVars = 0x60,
SubVars, SubVars,
MulVars, MulVars,
@ -174,16 +174,17 @@ class SoundMacroState
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 */
/** Combine additional component(s) to formula */ /** Combine additional component(s) to formula */
void addComponent(uint8_t midiCtrl, float scale, void addComponent(uint8_t midiCtrl, float scale, Combine combine, VarType varType);
Combine combine, VarType varType);
/** Calculate value */ /** Calculate value */
float evaluate(const Voice& vox, const SoundMacroState& st) const; float evaluate(double time, const Voice& vox, const SoundMacroState& st) const;
/** Determine if able to use */ /** Determine if able to use */
operator bool() const { return m_comps.size() != 0; } operator bool() const { return m_comps.size() != 0; }
@ -217,8 +218,8 @@ class SoundMacroState
public: public:
/** initialize state for SoundMacro data at `ptr` */ /** initialize state for SoundMacro data at `ptr` */
void initialize(const unsigned char* ptr, int step, bool swapData); void initialize(const unsigned char* ptr, int step, bool swapData);
void initialize(const unsigned char* ptr, int step, double ticksPerSec, void initialize(const unsigned char* ptr, int step, double ticksPerSec, uint8_t midiKey, uint8_t midiVel,
uint8_t midiKey, uint8_t midiVel, uint8_t midiMod, bool swapData); uint8_t midiMod, bool swapData);
/** 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
@ -231,7 +232,6 @@ public:
/** sample end event */ /** sample end event */
void sampleEndNotify(Voice& vox); void sampleEndNotify(Voice& vox);
}; };
} }
#endif // __AMUSE_SOUNDMACROSTATE_HPP__ #endif // __AMUSE_SOUNDMACROSTATE_HPP__

View File

@ -15,21 +15,21 @@ class Studio
{ {
friend class Engine; friend class Engine;
Engine& m_engine; Engine& m_engine;
Submix m_master;
Submix m_auxA; Submix m_auxA;
Submix m_auxB; Submix m_auxB;
struct StudioSend struct StudioSend
{ {
std::weak_ptr<Studio> m_targetStudio; std::shared_ptr<Studio> m_targetStudio;
float m_dryLevel; float m_dryLevel;
float m_auxALevel; float m_auxALevel;
float m_auxBLevel; float m_auxBLevel;
StudioSend(std::weak_ptr<Studio> studio, float dry, float auxA, float auxB) StudioSend(std::weak_ptr<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)
{
}
}; };
std::list<StudioSend> m_studiosOut; std::list<StudioSend> m_studiosOut;
bool m_destroyed = false;
void _destroy();
void _bringOutYourDead();
#ifndef NDEBUG #ifndef NDEBUG
bool _cyclicCheck(Studio* leaf); bool _cyclicCheck(Studio* leaf);
#endif #endif
@ -40,23 +40,15 @@ public:
/** Register a target Studio to send this Studio's mixing busses */ /** Register a target Studio to send this Studio's mixing busses */
void addStudioSend(std::weak_ptr<Studio> studio, float dry, float auxA, float auxB); void addStudioSend(std::weak_ptr<Studio> studio, float dry, float auxA, float auxB);
~Studio() /** Advise submixes of changing sample rate */
{
#ifndef NDEBUG
/* Ensure proper destruction procedure followed */
assert(m_destroyed);
#endif
}
/** advice submixes of changing sample rate */
void resetOutputSampleRate(double sampleRate); void resetOutputSampleRate(double sampleRate);
Submix& getMaster() { return m_master; }
Submix& getAuxA() { return m_auxA; } Submix& getAuxA() { return m_auxA; }
Submix& getAuxB() { return m_auxB; } Submix& getAuxB() { return m_auxB; }
Engine& getEngine() { return m_engine; } Engine& getEngine() { return m_engine; }
}; };
} }
#endif // __AMUSE_STUDIO_HPP__ #endif // __AMUSE_STUDIO_HPP__

View File

@ -25,18 +25,9 @@ class Submix
Engine& m_root; Engine& m_root;
std::unique_ptr<IBackendSubmix> m_backendSubmix; /**< Handle to client-implemented backend submix */ std::unique_ptr<IBackendSubmix> m_backendSubmix; /**< Handle to client-implemented backend submix */
std::vector<std::unique_ptr<EffectBaseTypeless>> m_effectStack; /**< Ordered list of effects to apply to submix */ std::vector<std::unique_ptr<EffectBaseTypeless>> m_effectStack; /**< Ordered list of effects to apply to submix */
bool m_destroyed = false;
void _destroy();
public: public:
Submix(Engine& engine); Submix(Engine& engine);
~Submix()
{
#ifndef NDEBUG
/* Ensure proper destruction procedure followed */
assert(m_destroyed);
#endif
}
/** 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>
@ -73,12 +64,11 @@ public:
EffectDelay& makeDelay(uint32_t initDelay, uint32_t initFeedback, uint32_t initOutput); EffectDelay& makeDelay(uint32_t initDelay, uint32_t initFeedback, uint32_t initOutput);
/** Add new standard-quality reverb effect to effect stack and assume ownership */ /** Add new standard-quality reverb effect to effect stack and assume ownership */
EffectReverbStd& makeReverbStd(float coloration, float mix, float time, EffectReverbStd& makeReverbStd(float coloration, float mix, float time, float damping, float preDelay);
float damping, float preDelay);
/** 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, EffectReverbHi& makeReverbHi(float coloration, float mix, float time, float damping, float preDelay,
float damping, float preDelay, float crosstalk); float crosstalk);
/** Remove and deallocate all effects from effect stack */ /** Remove and deallocate all effects from effect stack */
void clearEffects() { m_effectStack.clear(); } void clearEffects() { m_effectStack.clear(); }
@ -100,7 +90,6 @@ public:
Engine& getEngine() { return m_root; } Engine& getEngine() { return m_root; }
}; };
} }
#endif // __AMUSE_SUBMIX_HPP__ #endif // __AMUSE_SUBMIX_HPP__

View File

@ -12,14 +12,13 @@ struct ReferenceVector;
/** Support class for attenuating channel audio based on speaker 'positions' */ /** Support class for attenuating channel audio based on speaker 'positions' */
class SurroundProfiles class SurroundProfiles
{ {
static void SetupRefs(float matOut[8], const ChannelMap& map, static void SetupRefs(float matOut[8], const ChannelMap& map, const Vector3f& listenEmit,
const Vector3f& listenEmit, const ReferenceVector refs[]); const ReferenceVector refs[]);
public:
static void SetupMatrix(float matOut[8], const ChannelMap& map, AudioChannelSet set,
const Vector3f& emitPos, const Vector3f& listenPos,
const Vector3f& listenDir, const Vector3f& listenUp);
};
public:
static void SetupMatrix(float matOut[8], const ChannelMap& map, AudioChannelSet set, const Vector3f& emitPos,
const Vector3f& listenPos, const Vector3f& listenDir, const Vector3f& listenUp);
};
} }
#endif // __AMUSE_SURROUNDPROFILES_HPP__ #endif // __AMUSE_SURROUNDPROFILES_HPP__

View File

@ -49,7 +49,8 @@ class Voice : public Entity
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) */
@ -76,6 +77,7 @@ class Voice : public Entity
float m_curUserVol = 1.f; /**< Current user volume of voice */ float m_curUserVol = 1.f; /**< Current user volume of voice */
float m_curVol = 1.f; /**< Current volume of voice */ float m_curVol = 1.f; /**< Current volume of voice */
float m_curReverbVol = 0.f; /**< Current reverb volume of voice */ float m_curReverbVol = 0.f; /**< Current reverb volume of voice */
float m_curAuxBVol = 0.f; /**< Current AuxB volume of voice */
float m_userPan = 0.f; /**< User pan of voice */ float m_userPan = 0.f; /**< User pan of voice */
float m_curPan = 0.f; /**< Current pan of voice */ float m_curPan = 0.f; /**< Current pan of voice */
float m_userSpan = 0.f; /**< User span of voice */ float m_userSpan = 0.f; /**< User span of voice */
@ -138,7 +140,13 @@ class Voice : public Entity
void _doKeyOff(); void _doKeyOff();
void _macroKeyOff(); void _macroKeyOff();
void _macroSampleEnd(); void _macroSampleEnd();
void _advanceSample(int16_t& samp); void _procSamplePre(int16_t& samp);
template <typename T>
T _procSampleMaster(double time, T samp);
template <typename T>
T _procSampleAuxA(double time, T samp);
template <typename T>
T _procSampleAuxB(double time, T samp);
void _setTotalPitch(int32_t cents, bool slew); void _setTotalPitch(int32_t cents, bool slew);
bool _isRecursivelyDead(); bool _isRecursivelyDead();
void _bringOutYourDead(); void _bringOutYourDead();
@ -149,23 +157,25 @@ class Voice : public Entity
std::list<std::shared_ptr<Voice>>::iterator _allocateVoice(double sampleRate, bool dynamicPitch); std::list<std::shared_ptr<Voice>>::iterator _allocateVoice(double sampleRate, bool dynamicPitch);
std::list<std::shared_ptr<Voice>>::iterator _destroyVoice(std::list<std::shared_ptr<Voice>>::iterator it); std::list<std::shared_ptr<Voice>>::iterator _destroyVoice(std::list<std::shared_ptr<Voice>>::iterator it);
bool _loadSoundMacro(const unsigned char* macroData, int macroStep, double ticksPerSec, bool _loadSoundMacro(const unsigned char* macroData, int macroStep, double ticksPerSec, uint8_t midiKey,
uint8_t midiKey, uint8_t midiVel, uint8_t midiMod, bool pushPc=false); uint8_t midiVel, uint8_t midiMod, bool pushPc = false);
bool _loadKeymap(const Keymap* keymap, int macroStep, double ticksPerSec, bool _loadKeymap(const Keymap* keymap, int macroStep, double ticksPerSec, uint8_t midiKey, uint8_t midiVel,
uint8_t midiKey, uint8_t midiVel, uint8_t midiMod, bool pushPc=false); uint8_t midiMod, bool pushPc = false);
bool _loadLayer(const std::vector<const LayerMapping*>& layer, int macroStep, double ticksPerSec, bool _loadLayer(const std::vector<const LayerMapping*>& layer, int macroStep, double ticksPerSec, uint8_t midiKey,
uint8_t midiKey, uint8_t midiVel, uint8_t midiMod, bool pushPc=false); uint8_t midiVel, uint8_t midiMod, bool pushPc = false);
std::shared_ptr<Voice> _startChildMacro(ObjectId macroId, int macroStep, double ticksPerSec, std::shared_ptr<Voice> _startChildMacro(ObjectId macroId, int macroStep, double ticksPerSec, uint8_t midiKey,
uint8_t midiKey, uint8_t midiVel, uint8_t midiMod, bool pushPc=false); uint8_t midiVel, uint8_t midiMod, bool pushPc = false);
void _setPan(float pan); void _setPan(float pan);
void _setSurroundPan(float span); void _setSurroundPan(float span);
void _setPitchWheel(float pitchWheel); void _setPitchWheel(float pitchWheel);
void _notifyCtrlChange(uint8_t ctrl, int8_t val); void _notifyCtrlChange(uint8_t ctrl, int8_t val);
public: public:
~Voice(); ~Voice();
Voice(Engine& engine, const AudioGroup& group, int groupId, int vid, bool emitter, std::weak_ptr<Studio> studio); Voice(Engine& engine, const AudioGroup& group, int groupId, int vid, bool emitter, std::weak_ptr<Studio> studio);
Voice(Engine& engine, const AudioGroup& group, int groupId, ObjectId oid, int vid, bool emitter, std::weak_ptr<Studio> studio); Voice(Engine& engine, const AudioGroup& group, int groupId, ObjectId oid, int vid, bool emitter,
std::weak_ptr<Studio> studio);
/** Called before each supplyAudio invocation to prepare voice /** Called before each supplyAudio invocation to prepare voice
* backend for possible parameter updates */ * backend for possible parameter updates */
@ -175,6 +185,12 @@ public:
* internally advancing the voice stream */ * internally advancing the voice stream */
size_t supplyAudio(size_t frames, int16_t* data); size_t supplyAudio(size_t frames, int16_t* data);
/** Called three times after resampling supplyAudio output, voice should
* perform volume processing / send routing for each aux bus and master */
void routeAudio(size_t frames, double dt, int busId, int16_t* in, int16_t* out);
void routeAudio(size_t frames, double dt, int busId, int32_t* in, int32_t* out);
void routeAudio(size_t frames, double dt, int busId, float* in, float* out);
/** Obtain pointer to Voice's Studio */ /** Obtain pointer to Voice's Studio */
std::shared_ptr<Studio> getStudio() { return m_studio; } std::shared_ptr<Studio> getStudio() { return m_studio; }
@ -191,9 +207,8 @@ public:
std::shared_ptr<Voice> startChildMacro(int8_t addNote, ObjectId macroId, int macroStep); std::shared_ptr<Voice> startChildMacro(int8_t addNote, ObjectId macroId, int macroStep);
/** Load specified Sound Object from within group into voice */ /** Load specified Sound Object from within group into voice */
bool loadSoundObject(ObjectId objectId, int macroStep, double ticksPerSec, bool loadSoundObject(ObjectId objectId, int macroStep, double ticksPerSec, uint8_t midiKey, uint8_t midiVel,
uint8_t midiKey, uint8_t midiVel, uint8_t midiMod, uint8_t midiMod, bool pushPc = false);
bool pushPc=false);
/** Signals voice to begin fade-out (or defer if sustained), eventually reaching silence */ /** Signals voice to begin fade-out (or defer if sustained), eventually reaching silence */
void keyOff(); void keyOff();
@ -261,6 +276,9 @@ public:
/** Set reverb mix for voice */ /** Set reverb mix for voice */
void setReverbVol(float rvol); void setReverbVol(float rvol);
/** Set AuxB volume for voice */
void setAuxBVol(float bvol);
/** Set envelope for voice */ /** Set envelope for voice */
void setAdsr(ObjectId adsrId, bool dls); void setAdsr(ObjectId adsrId, bool dls);
@ -331,9 +349,7 @@ 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();
}; };
} }
#endif // __AMUSE_VOICE_HPP__ #endif // __AMUSE_VOICE_HPP__

View File

@ -5,28 +5,31 @@ namespace amuse
{ {
AudioGroup::AudioGroup(const AudioGroupData& data, GCNDataTag) AudioGroup::AudioGroup(const AudioGroupData& data, GCNDataTag)
: m_proj(data.getProj(), GCNDataTag{}), : m_proj(data.getProj(), GCNDataTag{})
m_pool(data.getPool()), , m_pool(data.getPool())
m_sdir(data.getSdir(), GCNDataTag{}), , m_sdir(data.getSdir(), GCNDataTag{})
m_samp(data.getSamp()), , m_samp(data.getSamp())
m_fmt(DataFormat::GCN) , m_fmt(DataFormat::GCN)
{} {
}
AudioGroup::AudioGroup(const AudioGroupData& data, bool absOffs, N64DataTag) AudioGroup::AudioGroup(const AudioGroupData& data, bool absOffs, N64DataTag)
: m_proj(data.getProj(), absOffs, N64DataTag{}), : m_proj(data.getProj(), absOffs, N64DataTag{})
m_pool(data.getPool()), , m_pool(data.getPool())
m_sdir(data.getSdir(), data.getSamp(), absOffs, N64DataTag{}), , m_sdir(data.getSdir(), data.getSamp(), absOffs, N64DataTag{})
m_samp(data.getSamp()), , m_samp(data.getSamp())
m_fmt(DataFormat::N64) , m_fmt(DataFormat::N64)
{} {
}
AudioGroup::AudioGroup(const AudioGroupData& data, bool absOffs, PCDataTag) AudioGroup::AudioGroup(const AudioGroupData& data, bool absOffs, PCDataTag)
: m_proj(data.getProj(), absOffs, PCDataTag{}), : m_proj(data.getProj(), absOffs, PCDataTag{})
m_pool(data.getPool(), PCDataTag{}), , m_pool(data.getPool(), PCDataTag{})
m_sdir(data.getSdir(), absOffs, PCDataTag{}), , m_sdir(data.getSdir(), absOffs, PCDataTag{})
m_samp(data.getSamp()), , m_samp(data.getSamp())
m_fmt(DataFormat::PC) , m_fmt(DataFormat::PC)
{} {
}
const Sample* AudioGroup::getSample(int sfxId) const const Sample* AudioGroup::getSample(int sfxId) const
{ {
@ -36,9 +39,5 @@ const Sample* AudioGroup::getSample(int sfxId) const
return &search->second; return &search->second;
} }
const unsigned char* AudioGroup::getSampleData(uint32_t offset) const const unsigned char* AudioGroup::getSampleData(uint32_t offset) const { return m_samp + offset; }
{
return m_samp + offset;
}
} }

View File

@ -15,9 +15,8 @@ IntrusiveAudioGroupData::~IntrusiveAudioGroupData()
} }
IntrusiveAudioGroupData::IntrusiveAudioGroupData(IntrusiveAudioGroupData&& other) IntrusiveAudioGroupData::IntrusiveAudioGroupData(IntrusiveAudioGroupData&& other)
: AudioGroupData(other.m_proj, other.m_projSz, other.m_pool, other.m_poolSz, : AudioGroupData(other.m_proj, other.m_projSz, other.m_pool, other.m_poolSz, other.m_sdir, other.m_sdirSz, other.m_samp,
other.m_sdir, other.m_sdirSz, other.m_samp, other.m_sampSz, other.m_sampSz, other.m_fmt, other.m_absOffs)
other.m_fmt, other.m_absOffs)
{ {
m_owns = other.m_owns; m_owns = other.m_owns;
other.m_owns = false; other.m_owns = false;
@ -45,5 +44,4 @@ IntrusiveAudioGroupData& IntrusiveAudioGroupData::operator=(IntrusiveAudioGroupD
return *this; return *this;
} }
} }

View File

@ -172,5 +172,4 @@ const ADSR* AudioGroupPool::tableAsAdsr(ObjectId id) const
return nullptr; return nullptr;
return reinterpret_cast<const ADSR*>(search->second); return reinterpret_cast<const ADSR*>(search->second);
} }
} }

View File

@ -481,5 +481,4 @@ const SFXGroupIndex* AudioGroupProject::getSFXGroupIndex(int groupId) const
return nullptr; return nullptr;
return &search->second; return &search->second;
} }
} }

View File

@ -41,8 +41,7 @@ AudioGroupSampleDirectory::AudioGroupSampleDirectory(const unsigned char* data,
const unsigned char* cur = data; const unsigned char* cur = data;
while (*reinterpret_cast<const uint32_t*>(cur) != 0xffffffff) while (*reinterpret_cast<const uint32_t*>(cur) != 0xffffffff)
{ {
const AudioGroupSampleDirectory::Entry* ent = const AudioGroupSampleDirectory::Entry* ent = reinterpret_cast<const AudioGroupSampleDirectory::Entry*>(cur);
reinterpret_cast<const AudioGroupSampleDirectory::Entry*>(cur);
std::pair<Entry, ADPCMParms>& store = m_entries[SBig(ent->m_sfxId)]; std::pair<Entry, ADPCMParms>& store = m_entries[SBig(ent->m_sfxId)];
store.first = *ent; store.first = *ent;
@ -51,8 +50,7 @@ AudioGroupSampleDirectory::AudioGroupSampleDirectory(const unsigned char* data,
if (store.first.m_adpcmParmOffset) if (store.first.m_adpcmParmOffset)
{ {
const AudioGroupSampleDirectory::ADPCMParms* adpcm = const AudioGroupSampleDirectory::ADPCMParms* adpcm =
reinterpret_cast<const AudioGroupSampleDirectory::ADPCMParms*>(data + reinterpret_cast<const AudioGroupSampleDirectory::ADPCMParms*>(data + store.first.m_adpcmParmOffset);
store.first.m_adpcmParmOffset);
store.second.dsp = adpcm->dsp; store.second.dsp = adpcm->dsp;
store.second.swapBigDSP(); store.second.swapBigDSP();
} }
@ -129,8 +127,7 @@ struct MusyX1AbsSdirEntry
} }
}; };
AudioGroupSampleDirectory::AudioGroupSampleDirectory(const unsigned char* data, AudioGroupSampleDirectory::AudioGroupSampleDirectory(const unsigned char* data, const unsigned char* sampData,
const unsigned char* sampData,
bool absOffs, N64DataTag) bool absOffs, N64DataTag)
{ {
const unsigned char* cur = data; const unsigned char* cur = data;
@ -169,8 +166,7 @@ AudioGroupSampleDirectory::AudioGroupSampleDirectory(const unsigned char* data,
} }
} }
AudioGroupSampleDirectory::AudioGroupSampleDirectory(const unsigned char* data, AudioGroupSampleDirectory::AudioGroupSampleDirectory(const unsigned char* data, bool absOffs, PCDataTag)
bool absOffs, PCDataTag)
{ {
const unsigned char* cur = data; const unsigned char* cur = data;
@ -199,5 +195,4 @@ AudioGroupSampleDirectory::AudioGroupSampleDirectory(const unsigned char* data,
} }
} }
} }
} }

View File

@ -6,74 +6,68 @@
namespace amuse namespace amuse
{ {
void BooBackendVoice::VoiceCallback::preSupplyAudio(boo::IAudioVoice&, void BooBackendVoice::VoiceCallback::preSupplyAudio(boo::IAudioVoice&, double dt)
double dt)
{ {
m_parent.m_clientVox.preSupplyAudio(dt); m_parent.m_clientVox.preSupplyAudio(dt);
} }
size_t BooBackendVoice::VoiceCallback::supplyAudio(boo::IAudioVoice&, size_t BooBackendVoice::VoiceCallback::supplyAudio(boo::IAudioVoice&, size_t frames, int16_t* data)
size_t frames, int16_t* data)
{ {
return m_parent.m_clientVox.supplyAudio(frames, data); return m_parent.m_clientVox.supplyAudio(frames, data);
} }
BooBackendVoice::BooBackendVoice(boo::IAudioVoiceEngine& engine, Voice& clientVox, void BooBackendVoice::VoiceCallback::routeAudio(size_t frames, double dt, int busId, int16_t* in, int16_t* out)
double sampleRate, bool dynamicPitch)
: m_clientVox(clientVox), m_cb(*this),
m_booVoice(engine.allocateNewMonoVoice(sampleRate, &m_cb, dynamicPitch))
{}
void BooBackendVoice::resetSampleRate(double sampleRate)
{ {
m_booVoice->resetSampleRate(sampleRate); m_parent.m_clientVox.routeAudio(frames, dt, busId, in, out);
} }
void BooBackendVoice::resetChannelLevels() void BooBackendVoice::VoiceCallback::routeAudio(size_t frames, double dt, int busId, int32_t* in, int32_t* out)
{ {
m_booVoice->resetChannelLevels(); m_parent.m_clientVox.routeAudio(frames, dt, busId, in, out);
} }
void BooBackendVoice::VoiceCallback::routeAudio(size_t frames, double dt, int busId, float* in, float* out)
{
m_parent.m_clientVox.routeAudio(frames, dt, busId, in, out);
}
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))
{
}
void BooBackendVoice::resetSampleRate(double sampleRate) { m_booVoice->resetSampleRate(sampleRate); }
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);
} }
void BooBackendVoice::setPitchRatio(double ratio, bool slew) void BooBackendVoice::setPitchRatio(double ratio, bool slew) { m_booVoice->setPitchRatio(ratio, slew); }
{
m_booVoice->setPitchRatio(ratio, slew);
}
void BooBackendVoice::start() void BooBackendVoice::start() { m_booVoice->start(); }
{
m_booVoice->start();
}
void BooBackendVoice::stop() void BooBackendVoice::stop() { m_booVoice->stop(); }
{
m_booVoice->stop();
}
bool BooBackendSubmix::SubmixCallback::canApplyEffect() const bool BooBackendSubmix::SubmixCallback::canApplyEffect() const { return m_parent.m_clientSmx.canApplyEffect(); }
{
return m_parent.m_clientSmx.canApplyEffect();
}
void BooBackendSubmix::SubmixCallback::applyEffect(int16_t* audio, size_t frameCount, void BooBackendSubmix::SubmixCallback::applyEffect(int16_t* audio, size_t frameCount, const boo::ChannelMap& chanMap,
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, void BooBackendSubmix::SubmixCallback::applyEffect(int32_t* audio, size_t frameCount, const boo::ChannelMap& chanMap,
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, void BooBackendSubmix::SubmixCallback::applyEffect(float* audio, size_t frameCount, const boo::ChannelMap& chanMap,
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));
} }
@ -83,9 +77,10 @@ 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) BooBackendSubmix::BooBackendSubmix(boo::IAudioVoiceEngine& engine, Submix& clientSmx, bool mainOut, int busId)
: m_clientSmx(clientSmx), m_cb(*this), m_booSubmix(engine.allocateNewSubmix(mainOut, &m_cb)) : 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)
{ {
@ -93,21 +88,11 @@ void BooBackendSubmix::setSendLevel(IBackendSubmix* submix, float level, bool sl
m_booSubmix->setSendLevel(smx.m_booSubmix.get(), level, slew); m_booSubmix->setSendLevel(smx.m_booSubmix.get(), level, slew);
} }
double BooBackendSubmix::getSampleRate() const double BooBackendSubmix::getSampleRate() const { return m_booSubmix->getSampleRate(); }
{
return m_booSubmix->getSampleRate();
}
SubmixFormat BooBackendSubmix::getSampleFormat() const SubmixFormat BooBackendSubmix::getSampleFormat() const { return SubmixFormat(m_booSubmix->getSampleFormat()); }
{
return SubmixFormat(m_booSubmix->getSampleFormat());
}
std::string BooBackendMIDIReader::description() { return m_midiIn->description(); }
std::string BooBackendMIDIReader::description()
{
return m_midiIn->description();
}
BooBackendMIDIReader::~BooBackendMIDIReader() {} BooBackendMIDIReader::~BooBackendMIDIReader() {}
@ -120,25 +105,25 @@ BooBackendMIDIReader::BooBackendMIDIReader(Engine& engine, const char* name, boo
auto devices = voxAlloc.m_booEngine.enumerateMIDIDevices(); auto devices = voxAlloc.m_booEngine.enumerateMIDIDevices();
for (const auto& dev : devices) for (const auto& dev : devices)
{ {
m_midiIn = voxAlloc.m_booEngine.newRealMIDIIn(dev.first.c_str(), m_midiIn = voxAlloc.m_booEngine.newRealMIDIIn(
std::bind(&BooBackendMIDIReader::_MIDIReceive, this, dev.first.c_str(),
std::placeholders::_1, std::placeholders::_2)); std::bind(&BooBackendMIDIReader::_MIDIReceive, this, std::placeholders::_1, std::placeholders::_2));
if (m_midiIn) if (m_midiIn)
return; return;
} }
m_midiIn = voxAlloc.m_booEngine.newVirtualMIDIIn(std::bind(&BooBackendMIDIReader::_MIDIReceive, this, m_midiIn = voxAlloc.m_booEngine.newVirtualMIDIIn(
std::placeholders::_1, std::placeholders::_2)); std::bind(&BooBackendMIDIReader::_MIDIReceive, this, std::placeholders::_1, std::placeholders::_2));
} }
else else
m_midiIn = voxAlloc.m_booEngine.newRealMIDIIn(name, m_midiIn = voxAlloc.m_booEngine.newRealMIDIIn(
std::bind(&BooBackendMIDIReader::_MIDIReceive, this, name, std::bind(&BooBackendMIDIReader::_MIDIReceive, this, std::placeholders::_1, std::placeholders::_2));
std::placeholders::_1, std::placeholders::_2));
} }
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) lk.lock(); if (m_useLock)
lk.lock();
m_queue.emplace_back(time, std::move(bytes)); m_queue.emplace_back(time, std::move(bytes));
#if 0 #if 0
openlog("LogIt", (LOG_CONS|LOG_PERROR|LOG_PID), LOG_DAEMON); openlog("LogIt", (LOG_CONS|LOG_PERROR|LOG_PID), LOG_DAEMON);
@ -152,7 +137,8 @@ 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{});
if (m_useLock) lk.lock(); if (m_useLock)
lk.lock();
if (m_queue.empty()) if (m_queue.empty())
return; return;
@ -208,9 +194,7 @@ void BooBackendMIDIReader::noteOn(uint8_t chan, uint8_t key, uint8_t velocity)
#endif #endif
} }
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)
{ {
@ -224,9 +208,7 @@ void BooBackendMIDIReader::programChange(uint8_t chan, uint8_t program)
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)
{ {
@ -234,20 +216,15 @@ void BooBackendMIDIReader::pitchBend(uint8_t chan, int16_t pitch)
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 (std::shared_ptr<Sequencer>& seq : m_engine.getActiveSequencers()) for (std::shared_ptr<Sequencer>& seq : m_engine.getActiveSequencers())
seq->allOff(chan, true); seq->allOff(chan, true);
} }
void BooBackendMIDIReader::resetAllControllers(uint8_t /*chan*/) 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)
{ {
@ -255,67 +232,39 @@ void BooBackendMIDIReader::allNotesOff(uint8_t chan)
seq->allOff(chan, false); seq->allOff(chan, false);
} }
void BooBackendMIDIReader::omniMode(uint8_t /*chan*/, bool /*on*/) void BooBackendMIDIReader::omniMode(uint8_t /*chan*/, bool /*on*/) {}
{
}
void BooBackendMIDIReader::polyMode(uint8_t /*chan*/, bool /*on*/) void BooBackendMIDIReader::polyMode(uint8_t /*chan*/, bool /*on*/) {}
{
}
void BooBackendMIDIReader::sysex(const void* /*data*/, size_t /*len*/) {}
void BooBackendMIDIReader::sysex(const void* /*data*/, size_t /*len*/) void BooBackendMIDIReader::timeCodeQuarterFrame(uint8_t /*message*/, uint8_t /*value*/) {}
{
}
void BooBackendMIDIReader::timeCodeQuarterFrame(uint8_t /*message*/, uint8_t /*value*/) void BooBackendMIDIReader::songPositionPointer(uint16_t /*pointer*/) {}
{
}
void BooBackendMIDIReader::songPositionPointer(uint16_t /*pointer*/) void BooBackendMIDIReader::songSelect(uint8_t /*song*/) {}
{
}
void BooBackendMIDIReader::songSelect(uint8_t /*song*/) void BooBackendMIDIReader::tuneRequest() {}
{
}
void BooBackendMIDIReader::tuneRequest() void BooBackendMIDIReader::startSeq() {}
{
}
void BooBackendMIDIReader::continueSeq() {}
void BooBackendMIDIReader::startSeq() void BooBackendMIDIReader::stopSeq() {}
{
}
void BooBackendMIDIReader::continueSeq() void BooBackendMIDIReader::reset() {}
{
}
void BooBackendMIDIReader::stopSeq() BooBackendVoiceAllocator::BooBackendVoiceAllocator(boo::IAudioVoiceEngine& booEngine) : m_booEngine(booEngine) {}
{
}
std::unique_ptr<IBackendVoice> BooBackendVoiceAllocator::allocateVoice(Voice& clientVox, double sampleRate,
void BooBackendMIDIReader::reset() bool dynamicPitch)
{
}
BooBackendVoiceAllocator::BooBackendVoiceAllocator(boo::IAudioVoiceEngine& booEngine)
: m_booEngine(booEngine)
{}
std::unique_ptr<IBackendVoice>
BooBackendVoiceAllocator::allocateVoice(Voice& clientVox, double sampleRate, 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) std::unique_ptr<IBackendSubmix> BooBackendVoiceAllocator::allocateSubmix(Submix& clientSmx, bool mainOut, int busId)
{ {
return std::make_unique<BooBackendSubmix>(m_booEngine, clientSmx, mainOut); 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()
@ -336,14 +285,7 @@ void BooBackendVoiceAllocator::register5MsCallback(std::function<void(double)>&&
m_booEngine.register5MsCallback(std::move(callback)); m_booEngine.register5MsCallback(std::move(callback));
} }
AudioChannelSet BooBackendVoiceAllocator::getAvailableSet() AudioChannelSet BooBackendVoiceAllocator::getAvailableSet() { return AudioChannelSet(m_booEngine.getAvailableSet()); }
{
return AudioChannelSet(m_booEngine.getAvailableSet());
}
void BooBackendVoiceAllocator::pumpAndMixVoices()
{
m_booEngine.pumpAndMixVoices();
}
void BooBackendVoiceAllocator::pumpAndMixVoices() { m_booEngine.pumpAndMixVoices(); }
} }

View File

@ -45,10 +45,7 @@ static amuse::SystemString StrToSys(const std::string& str)
} }
#else #else
static amuse::SystemString StrToSys(const std::string& str) static amuse::SystemString StrToSys(const std::string& str) { return str; }
{
return str;
}
#endif #endif
@ -105,14 +102,10 @@ static bool IsChunkExtension(const SystemChar* path, const SystemChar*& dotOut)
const SystemChar* ext = StrRChr(path, _S('.')); const SystemChar* ext = StrRChr(path, _S('.'));
if (ext) if (ext)
{ {
if (!CompareCaseInsensitive(ext, _S(".poo")) || if (!CompareCaseInsensitive(ext, _S(".poo")) || !CompareCaseInsensitive(ext, _S(".pool")) ||
!CompareCaseInsensitive(ext, _S(".pool")) || !CompareCaseInsensitive(ext, _S(".pro")) || !CompareCaseInsensitive(ext, _S(".proj")) ||
!CompareCaseInsensitive(ext, _S(".pro")) || !CompareCaseInsensitive(ext, _S(".sdi")) || !CompareCaseInsensitive(ext, _S(".sdir")) ||
!CompareCaseInsensitive(ext, _S(".proj")) || !CompareCaseInsensitive(ext, _S(".sam")) || !CompareCaseInsensitive(ext, _S(".samp")))
!CompareCaseInsensitive(ext, _S(".sdi")) ||
!CompareCaseInsensitive(ext, _S(".sdir")) ||
!CompareCaseInsensitive(ext, _S(".sam")) ||
!CompareCaseInsensitive(ext, _S(".samp")))
{ {
dotOut = ext; dotOut = ext;
return true; return true;
@ -126,8 +119,7 @@ static bool IsSongExtension(const SystemChar* path, const SystemChar*& dotOut)
const SystemChar* ext = StrRChr(path, _S('.')); const SystemChar* ext = StrRChr(path, _S('.'));
if (ext) if (ext)
{ {
if (!CompareCaseInsensitive(ext, _S(".son")) || if (!CompareCaseInsensitive(ext, _S(".son")) || !CompareCaseInsensitive(ext, _S(".sng")) ||
!CompareCaseInsensitive(ext, _S(".sng")) ||
!CompareCaseInsensitive(ext, _S(".song"))) !CompareCaseInsensitive(ext, _S(".song")))
{ {
dotOut = ext; dotOut = ext;
@ -273,10 +265,10 @@ static std::vector<std::pair<SystemString, IntrusiveAudioGroupData>> LoadMP1(FIL
std::unique_ptr<uint8_t[]> sdir(new uint8_t[sdirLen]); std::unique_ptr<uint8_t[]> sdir(new uint8_t[sdirLen]);
fread(sdir.get(), 1, sdirLen, fp); fread(sdir.get(), 1, sdirLen, fp);
ret.emplace_back(std::move(name), IntrusiveAudioGroupData{proj.release(), projLen, ret.emplace_back(std::move(name),
pool.release(), poolLen, IntrusiveAudioGroupData{proj.release(), projLen, pool.release(), poolLen,
sdir.release(), sdirLen, sdir.release(), sdirLen, samp.release(), sampLen,
samp.release(), sampLen, GCNDataTag{}}); GCNDataTag{}});
} }
} }
FSeek(fp, origPos, SEEK_SET); FSeek(fp, origPos, SEEK_SET);
@ -420,7 +412,6 @@ static std::vector<std::pair<SystemString, ContainerRegistry::SongData>> LoadMP1
ret.emplace_back(name, ContainerRegistry::SongData(std::move(song), sonLength, groupId, midiSetup)); ret.emplace_back(name, ContainerRegistry::SongData(std::move(song), sonLength, groupId, midiSetup));
} }
FSeek(fp, origPos, SEEK_SET); FSeek(fp, origPos, SEEK_SET);
} }
} }
@ -571,10 +562,10 @@ static std::vector<std::pair<SystemString, IntrusiveAudioGroupData>> LoadMP2(FIL
std::unique_ptr<uint8_t[]> samp(new uint8_t[sampSz]); std::unique_ptr<uint8_t[]> samp(new uint8_t[sampSz]);
fread(samp.get(), 1, sampSz, fp); fread(samp.get(), 1, sampSz, fp);
ret.emplace_back(std::move(name), IntrusiveAudioGroupData{proj.release(), projSz, ret.emplace_back(std::move(name),
pool.release(), poolSz, IntrusiveAudioGroupData{proj.release(), projSz, pool.release(), poolSz,
sdir.release(), sdirSz, sdir.release(), sdirSz, samp.release(), sampSz,
samp.release(), sampSz, GCNDataTag{}}); GCNDataTag{}});
} }
} }
} }
@ -716,9 +707,9 @@ static std::vector<std::pair<SystemString, IntrusiveAudioGroupData>> LoadRS1PC(F
} }
} }
ret.emplace_back(_S("Group"), IntrusiveAudioGroupData{proj.release(), projSz, pool.release(), poolSz, ret.emplace_back(_S("Group"),
sdir.release(), sdirSz, samp.release(), sampSz, IntrusiveAudioGroupData{proj.release(), projSz, pool.release(), poolSz, sdir.release(),
false, PCDataTag{}}); sdirSz, samp.release(), sampSz, false, PCDataTag{}});
} }
} }
@ -780,8 +771,8 @@ static bool ValidateRS1N64(FILE* fp)
return false; /* GameId not 'NRSE', 'NRSJ', or 'NRSP' */ return false; /* GameId not 'NRSE', 'NRSJ', or 'NRSP' */
#endif #endif
const uint8_t* dataSeg = reinterpret_cast<const uint8_t*>(memmem(data.get(), endPos, const uint8_t* dataSeg =
"dbg_data\0\0\0\0\0\0\0\0", 16)); reinterpret_cast<const uint8_t*>(memmem(data.get(), endPos, "dbg_data\0\0\0\0\0\0\0\0", 16));
if (dataSeg) if (dataSeg)
{ {
dataSeg += 28; dataSeg += 28;
@ -827,8 +818,8 @@ static std::vector<std::pair<SystemString, IntrusiveAudioGroupData>> LoadRS1N64(
else if ((data[0] & 0x80) != 0x80 && (data[1] & 0x80) == 0x80) else if ((data[0] & 0x80) != 0x80 && (data[1] & 0x80) == 0x80)
SwapN64Rom16(data.get(), endPos); SwapN64Rom16(data.get(), endPos);
const uint8_t* dataSeg = reinterpret_cast<const uint8_t*>(memmem(data.get(), endPos, const uint8_t* dataSeg =
"dbg_data\0\0\0\0\0\0\0\0", 16)); reinterpret_cast<const uint8_t*>(memmem(data.get(), endPos, "dbg_data\0\0\0\0\0\0\0\0", 16));
if (dataSeg) if (dataSeg)
{ {
dataSeg += 28; dataSeg += 28;
@ -917,9 +908,9 @@ static std::vector<std::pair<SystemString, IntrusiveAudioGroupData>> LoadRS1N64(
} }
} }
ret.emplace_back(_S("Group"), IntrusiveAudioGroupData{proj.release(), projSz, pool.release(), poolSz, ret.emplace_back(_S("Group"),
sdir.release(), sdirSz, samp.release(), sampSz, IntrusiveAudioGroupData{proj.release(), projSz, pool.release(), poolSz, sdir.release(), sdirSz,
false, N64DataTag{}}); samp.release(), sampSz, false, N64DataTag{}});
} }
return ret; return ret;
@ -938,8 +929,8 @@ static std::vector<std::pair<SystemString, ContainerRegistry::SongData>> LoadRS1
else if ((data[0] & 0x80) != 0x80 && (data[1] & 0x80) == 0x80) else if ((data[0] & 0x80) != 0x80 && (data[1] & 0x80) == 0x80)
SwapN64Rom16(data.get(), endPos); SwapN64Rom16(data.get(), endPos);
const uint8_t* dataSeg = reinterpret_cast<const uint8_t*>(memmem(data.get(), endPos, const uint8_t* dataSeg =
"dbg_data\0\0\0\0\0\0\0\0", 16)); reinterpret_cast<const uint8_t*>(memmem(data.get(), endPos, "dbg_data\0\0\0\0\0\0\0\0", 16));
if (dataSeg) if (dataSeg)
{ {
dataSeg += 28; dataSeg += 28;
@ -1077,9 +1068,9 @@ static std::vector<std::pair<SystemString, IntrusiveAudioGroupData>> LoadBFNPC(F
} }
} }
ret.emplace_back(_S("Group"), IntrusiveAudioGroupData{proj.release(), projSz, pool.release(), poolSz, ret.emplace_back(_S("Group"),
sdir.release(), sdirSz, samp.release(), sampSz, IntrusiveAudioGroupData{proj.release(), projSz, pool.release(), poolSz, sdir.release(),
true, PCDataTag{}}); sdirSz, samp.release(), sampSz, true, PCDataTag{}});
} }
} }
@ -1141,8 +1132,8 @@ static bool ValidateBFNN64(FILE* fp)
return false; /* GameId not 'NRSE', 'NRSJ', or 'NRSP' */ return false; /* GameId not 'NRSE', 'NRSJ', or 'NRSP' */
#endif #endif
const uint8_t* dataSeg = reinterpret_cast<const uint8_t*>(memmem(data.get(), endPos, const uint8_t* dataSeg =
"dbg_data\0\0\0\0\0\0\0\0", 16)); reinterpret_cast<const uint8_t*>(memmem(data.get(), endPos, "dbg_data\0\0\0\0\0\0\0\0", 16));
if (dataSeg) if (dataSeg)
{ {
dataSeg += 28; dataSeg += 28;
@ -1188,8 +1179,8 @@ static std::vector<std::pair<SystemString, IntrusiveAudioGroupData>> LoadBFNN64(
else if ((data[0] & 0x80) != 0x80 && (data[1] & 0x80) == 0x80) else if ((data[0] & 0x80) != 0x80 && (data[1] & 0x80) == 0x80)
SwapN64Rom16(data.get(), endPos); SwapN64Rom16(data.get(), endPos);
const uint8_t* dataSeg = reinterpret_cast<const uint8_t*>(memmem(data.get(), endPos, const uint8_t* dataSeg =
"dbg_data\0\0\0\0\0\0\0\0", 16)); reinterpret_cast<const uint8_t*>(memmem(data.get(), endPos, "dbg_data\0\0\0\0\0\0\0\0", 16));
if (dataSeg) if (dataSeg)
{ {
dataSeg += 28; dataSeg += 28;
@ -1278,9 +1269,9 @@ static std::vector<std::pair<SystemString, IntrusiveAudioGroupData>> LoadBFNN64(
} }
} }
ret.emplace_back(_S("Group"), IntrusiveAudioGroupData{proj.release(), projSz, pool.release(), poolSz, ret.emplace_back(_S("Group"),
sdir.release(), sdirSz, samp.release(), sampSz, IntrusiveAudioGroupData{proj.release(), projSz, pool.release(), poolSz, sdir.release(), sdirSz,
true, N64DataTag{}}); samp.release(), sampSz, true, N64DataTag{}});
} }
return ret; return ret;
@ -1299,8 +1290,8 @@ static std::vector<std::pair<SystemString, ContainerRegistry::SongData>> LoadBFN
else if ((data[0] & 0x80) != 0x80 && (data[1] & 0x80) == 0x80) else if ((data[0] & 0x80) != 0x80 && (data[1] & 0x80) == 0x80)
SwapN64Rom16(data.get(), endPos); SwapN64Rom16(data.get(), endPos);
const uint8_t* dataSeg = reinterpret_cast<const uint8_t*>(memmem(data.get(), endPos, const uint8_t* dataSeg =
"dbg_data\0\0\0\0\0\0\0\0", 16)); reinterpret_cast<const uint8_t*>(memmem(data.get(), endPos, "dbg_data\0\0\0\0\0\0\0\0", 16));
if (dataSeg) if (dataSeg)
{ {
dataSeg += 28; dataSeg += 28;
@ -1494,8 +1485,9 @@ static std::vector<std::pair<SystemString, IntrusiveAudioGroupData>> LoadRS2(FIL
{ {
SystemChar name[128]; SystemChar name[128];
SNPrintf(name, 128, _S("GroupFile%02u"), j); SNPrintf(name, 128, _S("GroupFile%02u"), j);
ret.emplace_back(name, IntrusiveAudioGroupData{proj.release(), head.projLen, pool.release(), head.poolLen, ret.emplace_back(name, IntrusiveAudioGroupData{proj.release(), head.projLen, pool.release(),
sdir.release(), head.sdirLen, samp.release(), head.sampLen, GCNDataTag{}}); head.poolLen, sdir.release(), head.sdirLen,
samp.release(), head.sampLen, GCNDataTag{}});
} }
} }
@ -1556,8 +1548,8 @@ static std::vector<std::pair<SystemString, ContainerRegistry::SongData>> LoadRS2
SNPrintf(name, 128, _S("GroupFile%02u-%u"), j, s); SNPrintf(name, 128, _S("GroupFile%02u-%u"), j, s);
std::unique_ptr<uint8_t[]> song(new uint8_t[sonHead.length]); std::unique_ptr<uint8_t[]> song(new uint8_t[sonHead.length]);
memmove(song.get(), audData.get() + sonHead.offset, sonHead.length); memmove(song.get(), audData.get() + sonHead.offset, sonHead.length);
ret.emplace_back(name, ContainerRegistry::SongData(std::move(song), sonHead.length, ret.emplace_back(name, ContainerRegistry::SongData(std::move(song), sonHead.length, sonHead.groupId,
sonHead.groupId, sonHead.setupId)); sonHead.setupId));
} }
} }
@ -1667,8 +1659,9 @@ static std::vector<std::pair<SystemString, IntrusiveAudioGroupData>> LoadRS3(FIL
{ {
SystemChar name[128]; SystemChar name[128];
SNPrintf(name, 128, _S("GroupFile%02u"), j); SNPrintf(name, 128, _S("GroupFile%02u"), j);
ret.emplace_back(name, IntrusiveAudioGroupData{proj.release(), head.projLen, pool.release(), head.poolLen, ret.emplace_back(name, IntrusiveAudioGroupData{proj.release(), head.projLen, pool.release(),
sdir.release(), head.sdirLen, samp.release(), head.sampLen, GCNDataTag{}}); head.poolLen, sdir.release(), head.sdirLen,
samp.release(), head.sampLen, GCNDataTag{}});
} }
} }
@ -1768,7 +1761,8 @@ struct TTYDSongDesc
uint8_t setup; uint8_t setup;
}; };
static std::vector<std::pair<SystemString, ContainerRegistry::SongData>> LoadPaperMarioTTYDSongs(FILE* midifp, FILE* descFp) static std::vector<std::pair<SystemString, ContainerRegistry::SongData>> LoadPaperMarioTTYDSongs(FILE* midifp,
FILE* descFp)
{ {
if (!descFp) if (!descFp)
return {}; return {};
@ -1802,9 +1796,9 @@ static std::vector<std::pair<SystemString, ContainerRegistry::SongData>> LoadPap
std::unique_ptr<uint8_t[]> songData(new uint8_t[len - 32]); std::unique_ptr<uint8_t[]> songData(new uint8_t[len - 32]);
memcpy(songData.get(), (data.get() + off + 32), len - 32); memcpy(songData.get(), (data.get() + off + 32), len - 32);
ret.emplace_back(StrToSys(std::string(songDescs[song].name, 30)), ret.emplace_back(
ContainerRegistry::SongData(std::move(songData), len - 32, StrToSys(std::string(songDescs[song].name, 30)),
songDescs[song].group, songDescs[song].setup)); ContainerRegistry::SongData(std::move(songData), len - 32, songDescs[song].group, songDescs[song].setup));
off += len; off += len;
song++; song++;
} }
@ -1931,15 +1925,14 @@ ContainerRegistry::Type ContainerRegistry::DetectContainerType(const SystemChar*
return Type::Invalid; return Type::Invalid;
} }
std::vector<std::pair<SystemString, IntrusiveAudioGroupData>> std::vector<std::pair<SystemString, IntrusiveAudioGroupData>> ContainerRegistry::LoadContainer(const SystemChar* path)
ContainerRegistry::LoadContainer(const SystemChar* path)
{ {
Type typeOut; Type typeOut;
return LoadContainer(path, typeOut); return LoadContainer(path, typeOut);
}; };
std::vector<std::pair<SystemString, IntrusiveAudioGroupData>> std::vector<std::pair<SystemString, IntrusiveAudioGroupData>> ContainerRegistry::LoadContainer(const SystemChar* path,
ContainerRegistry::LoadContainer(const SystemChar* path, Type& typeOut) Type& typeOut)
{ {
FILE* fp; FILE* fp;
typeOut = Type::Invalid; typeOut = Type::Invalid;
@ -2034,17 +2027,17 @@ ContainerRegistry::LoadContainer(const SystemChar* path, Type& typeOut)
/* SDIR-based format detection */ /* SDIR-based format detection */
if (*reinterpret_cast<uint32_t*>(sdir.get() + 8) == 0x0) if (*reinterpret_cast<uint32_t*>(sdir.get() + 8) == 0x0)
ret.emplace_back(_S("Group"), IntrusiveAudioGroupData{proj.release(), projLen, pool.release(), poolLen, ret.emplace_back(_S("Group"),
sdir.release(), sdirLen, samp.release(), sampLen, IntrusiveAudioGroupData{proj.release(), projLen, pool.release(), poolLen, sdir.release(),
GCNDataTag{}}); sdirLen, samp.release(), sampLen, GCNDataTag{}});
else if (sdir[9] == 0x0) else if (sdir[9] == 0x0)
ret.emplace_back(_S("Group"), IntrusiveAudioGroupData{proj.release(), projLen, pool.release(), poolLen, ret.emplace_back(_S("Group"),
sdir.release(), sdirLen, samp.release(), sampLen, IntrusiveAudioGroupData{proj.release(), projLen, pool.release(), poolLen, sdir.release(),
false, N64DataTag{}}); sdirLen, samp.release(), sampLen, false, N64DataTag{}});
else else
ret.emplace_back(_S("Group"), IntrusiveAudioGroupData{proj.release(), projLen, pool.release(), poolLen, ret.emplace_back(_S("Group"),
sdir.release(), sdirLen, samp.release(), sampLen, IntrusiveAudioGroupData{proj.release(), projLen, pool.release(), poolLen, sdir.release(),
false, PCDataTag{}}); sdirLen, samp.release(), sampLen, false, PCDataTag{}});
typeOut = Type::Raw4; typeOut = Type::Raw4;
return ret; return ret;
@ -2124,8 +2117,7 @@ ContainerRegistry::LoadContainer(const SystemChar* path, Type& typeOut)
return {}; return {};
} }
std::vector<std::pair<SystemString, ContainerRegistry::SongData>> std::vector<std::pair<SystemString, ContainerRegistry::SongData>> ContainerRegistry::LoadSongs(const SystemChar* path)
ContainerRegistry::LoadSongs(const SystemChar* path)
{ {
FILE* fp; FILE* fp;
@ -2223,5 +2215,4 @@ ContainerRegistry::LoadSongs(const SystemChar* path)
return {}; return {};
} }
} }

View File

@ -22,8 +22,7 @@
namespace amuse namespace amuse
{ {
DirectoryEnumerator::DirectoryEnumerator(const SystemChar* path, Mode mode, DirectoryEnumerator::DirectoryEnumerator(const SystemChar* path, Mode mode, bool sizeSort, bool reverse, bool noHidden)
bool sizeSort, bool reverse, bool noHidden)
{ {
Sstat theStat; Sstat theStat;
if (Stat(path, &theStat) || !S_ISDIR(theStat.st_mode)) if (Stat(path, &theStat) || !S_ISDIR(theStat.st_mode))
@ -283,5 +282,4 @@ DirectoryEnumerator::DirectoryEnumerator(const SystemChar* path, Mode mode,
#endif #endif
} }
} }

View File

View File

@ -7,6 +7,7 @@
namespace amuse namespace amuse
{ {
/* clang-format off */
static const float rsmpTab12khz[] = static const float rsmpTab12khz[] =
{ {
0.097504, 0.802216, 0.101593, -0.000977, 0.097504, 0.802216, 0.101593, -0.000977,
@ -138,16 +139,17 @@ static const float rsmpTab12khz[] =
-0.001038, 0.105804, 0.802032, 0.093506, -0.001038, 0.105804, 0.802032, 0.093506,
-0.000977, 0.101593, 0.802216, 0.097504, -0.000977, 0.101593, 0.802216, 0.097504,
}; };
/* clang-format on */
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, EffectChorusImp<T>::EffectChorusImp(uint32_t baseDelay, uint32_t variation, uint32_t period, double sampleRate)
uint32_t period, double sampleRate)
: EffectChorus(baseDelay, variation, period) : EffectChorus(baseDelay, variation, period)
{ {
_setup(sampleRate); _setup(sampleRate);
@ -309,16 +311,9 @@ void EffectChorusImp<T>::applyEffect(T* audio, size_t frameCount, const ChannelM
{ {
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] = {
{ x0_lastChans[0][buf], x0_lastChans[1][buf], x0_lastChans[2][buf], x0_lastChans[3][buf],
x0_lastChans[0][buf], x0_lastChans[4][buf], x0_lastChans[5][buf], x0_lastChans[6][buf], x0_lastChans[7][buf],
x0_lastChans[1][buf],
x0_lastChans[2][buf],
x0_lastChans[3][buf],
x0_lastChans[4][buf],
x0_lastChans[5][buf],
x0_lastChans[6][buf],
x0_lastChans[7][buf],
}; };
T* inBuf = audio; T* inBuf = audio;
@ -355,7 +350,8 @@ void EffectChorusImp<T>::applyEffect(T* audio, size_t frameCount, const ChannelM
case 1: case 1:
x6c_src.doSrc2(bs, chanMap.m_channelCount); x6c_src.doSrc2(bs, chanMap.m_channelCount);
break; break;
default: break; default:
break;
} }
} }
@ -374,5 +370,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>;
} }

View File

@ -8,8 +8,7 @@ namespace amuse
{ {
template <typename T> template <typename T>
EffectDelayImp<T>::EffectDelayImp(uint32_t initDelay, uint32_t initFeedback, EffectDelayImp<T>::EffectDelayImp(uint32_t initDelay, uint32_t initFeedback, uint32_t initOutput, double sampleRate)
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);
@ -78,5 +77,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>;
} }

View File

@ -6,6 +6,8 @@
namespace amuse namespace amuse
{ {
/* clang-format off */
/* Comb-filter delays */ /* Comb-filter delays */
static const size_t CTapDelays[] = static const size_t CTapDelays[] =
{ {
@ -34,6 +36,8 @@ static const size_t LPTapDelays[] =
73 73
}; };
/* clang-format on */
void ReverbDelayLine::allocate(int32_t delay) void ReverbDelayLine::allocate(int32_t delay)
{ {
delay += 2; delay += 2;
@ -53,24 +57,23 @@ void ReverbDelayLine::setdelay(int32_t delay)
x4_outPoint += x8_length; x4_outPoint += x8_length;
} }
EffectReverbStd::EffectReverbStd(float coloration, float mix, float time, EffectReverbStd::EffectReverbStd(float coloration, float mix, float time, float damping, float preDelay)
float damping, float preDelay) : x140_x1c8_coloration(clamp(0.f, coloration, 1.f))
: x140_x1c8_coloration(clamp(0.f, coloration, 1.f)), , 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, EffectReverbHi::EffectReverbHi(float coloration, float mix, float time, float damping, float preDelay, float crosstalk)
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, EffectReverbStdImp<T>::EffectReverbStdImp(float coloration, float mix, float time, float damping, float preDelay,
float damping, float preDelay, double sampleRate) double sampleRate)
: EffectReverbStd(coloration, mix, time, damping, preDelay) : EffectReverbStd(coloration, mix, time, damping, preDelay)
{ {
_setup(sampleRate); _setup(sampleRate);
@ -87,12 +90,13 @@ 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 / 32000.0;
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] * m_sampleRate / 32000.0; size_t tapDelay = CTapDelays[t] * rateRatio;
combLine.allocate(tapDelay); combLine.allocate(tapDelay);
combLine.setdelay(tapDelay); combLine.setdelay(tapDelay);
xf4_combCoef[c][t] = std::pow(10.f, tapDelay * -3.f / timeSamples); xf4_combCoef[c][t] = std::pow(10.f, tapDelay * -3.f / timeSamples);
@ -101,7 +105,7 @@ void EffectReverbStdImp<T>::_update()
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] * m_sampleRate / 32000.0; size_t tapDelay = APTapDelays[t] * rateRatio;
allPassLine.allocate(tapDelay); allPassLine.allocate(tapDelay);
allPassLine.setdelay(tapDelay); allPassLine.setdelay(tapDelay);
} }
@ -205,8 +209,8 @@ 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 = -(xf0_allPassCoef * linesAP[0].xc_inputs[linesAP[0].x0_inPoint] - float lowPass =
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];
@ -220,8 +224,8 @@ 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 = -(xf0_allPassCoef * linesAP[1].xc_inputs[linesAP[1].x0_inPoint] - float allPass =
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];
@ -243,9 +247,8 @@ 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, EffectReverbHiImp<T>::EffectReverbHiImp(float coloration, float mix, float time, float damping, float preDelay,
float damping, float preDelay, float crosstalk, float crosstalk, double sampleRate)
double sampleRate)
: EffectReverbHi(coloration, mix, time, damping, preDelay, crosstalk) : EffectReverbHi(coloration, mix, time, damping, preDelay, crosstalk)
{ {
_setup(sampleRate); _setup(sampleRate);
@ -262,12 +265,13 @@ 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 / 32000.0;
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] * m_sampleRate / 32000.0; size_t tapDelay = CTapDelays[t] * rateRatio;
combLine.allocate(tapDelay); combLine.allocate(tapDelay);
combLine.setdelay(tapDelay); combLine.setdelay(tapDelay);
x16c_combCoef[c][t] = std::pow(10.f, tapDelay * -3.f / timeSamples); x16c_combCoef[c][t] = std::pow(10.f, tapDelay * -3.f / timeSamples);
@ -276,13 +280,13 @@ void EffectReverbHiImp<T>::_update()
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] * m_sampleRate / 32000.0; size_t tapDelay = APTapDelays[t] * rateRatio;
allPassLine.allocate(tapDelay); allPassLine.allocate(tapDelay);
allPassLine.setdelay(tapDelay); allPassLine.setdelay(tapDelay);
} }
ReverbDelayLine& lpLine = x78_LP[c]; ReverbDelayLine& lpLine = x78_LP[c];
size_t tapDelay = LPTapDelays[c] * m_sampleRate / 32000.0; size_t tapDelay = LPTapDelays[c] * rateRatio;
lpLine.allocate(tapDelay); lpLine.allocate(tapDelay);
lpLine.setdelay(tapDelay); lpLine.setdelay(tapDelay);
} }
@ -393,8 +397,8 @@ void EffectReverbHiImp<T>::_handleReverb(T* audio, int c, int chanCount, int sam
linesC[2].x4_outPoint = 0; linesC[2].x4_outPoint = 0;
/* All-pass filter stage */ /* All-pass filter stage */
linesAP[0].xc_inputs[linesAP[0].x0_inPoint] = linesAP[0].xc_inputs[linesAP[0].x0_inPoint] = allPassCoef * linesAP[0].x10_lastInput + linesC[0].x10_lastInput +
allPassCoef * linesAP[0].x10_lastInput + linesC[0].x10_lastInput + linesC[1].x10_lastInput + linesC[2].x10_lastInput; linesC[1].x10_lastInput + linesC[2].x10_lastInput;
linesAP[1].xc_inputs[linesAP[1].x0_inPoint] = linesAP[1].xc_inputs[linesAP[1].x0_inPoint] =
allPassCoef * linesAP[1].x10_lastInput - allPassCoef * linesAP[1].x10_lastInput -
@ -489,5 +493,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>;
} }

View File

@ -18,28 +18,15 @@ void Emitter::_destroy()
m_vox->kill(); m_vox->kill();
} }
void Emitter::setPos(const Vector3f& pos) void Emitter::setPos(const Vector3f& pos) {}
{
}
void Emitter::setDir(const Vector3f& dir) void Emitter::setDir(const Vector3f& dir) {}
{
}
void Emitter::setMaxDist(float maxDist) void Emitter::setMaxDist(float maxDist) {}
{
}
void Emitter::setMaxVol(float maxVol) void Emitter::setMaxVol(float maxVol) {}
{
}
void Emitter::setMinVol(float minVol) void Emitter::setMinVol(float minVol) {}
{
}
void Emitter::setFalloff(float falloff)
{
}
void Emitter::setFalloff(float falloff) {}
} }

View File

@ -11,13 +11,13 @@
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};
Engine::~Engine() Engine::~Engine()
{ {
for (std::shared_ptr<Sequencer>& seq : m_activeSequencers) for (std::shared_ptr<Sequencer>& seq : m_activeSequencers)
if (!seq->m_destroyed) if (!seq->m_destroyed)
seq->_destroy(); seq->_destroy();
while (m_activeStudios.size())
removeStudio(m_activeStudios.front());
for (std::shared_ptr<Emitter>& emitter : m_activeEmitters) for (std::shared_ptr<Emitter>& emitter : m_activeEmitters)
emitter->_destroy(); emitter->_destroy();
for (std::shared_ptr<Voice>& vox : m_activeVoices) for (std::shared_ptr<Voice>& vox : m_activeVoices)
@ -25,8 +25,11 @@ Engine::~Engine()
} }
Engine::Engine(IBackendVoiceAllocator& backend, AmplitudeMode ampMode) Engine::Engine(IBackendVoiceAllocator& backend, AmplitudeMode ampMode)
: m_backend(backend), m_ampMode(ampMode), m_defaultStudio(std::make_shared<Studio>(*this, 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->getAuxB().makeChorus(15, 0, 500);
m_defaultStudioReady = true;
backend.register5MsCallback(std::bind(&Engine::_5MsCallback, this, std::placeholders::_1)); backend.register5MsCallback(std::bind(&Engine::_5MsCallback, this, std::placeholders::_1));
m_midiReader = backend.allocateMIDIReader(*this); m_midiReader = backend.allocateMIDIReader(*this);
} }
@ -53,19 +56,21 @@ std::pair<AudioGroup*, const SFXGroupIndex*> Engine::_findSFXGroup(int groupId)
return {}; return {};
} }
std::list<std::shared_ptr<Voice>>::iterator std::list<std::shared_ptr<Voice>>::iterator Engine::_allocateVoice(const AudioGroup& group, int groupId,
Engine::_allocateVoice(const AudioGroup& group, int groupId, double sampleRate, double sampleRate, bool dynamicPitch, bool emitter,
bool dynamicPitch, bool emitter, std::weak_ptr<Studio> studio) std::weak_ptr<Studio> studio)
{ {
auto it = m_activeVoices.emplace(m_activeVoices.end(), std::shared_ptr<Studio> st = studio.lock();
new Voice(*this, group, groupId, m_nextVid++, emitter, studio)); auto it =
m_activeVoices.back()->m_backendVoice = m_activeVoices.emplace(m_activeVoices.end(), new Voice(*this, group, groupId, m_nextVid++, emitter, studio));
m_backend.allocateVoice(*m_activeVoices.back(), sampleRate, dynamicPitch); m_activeVoices.back()->m_backendVoice = m_backend.allocateVoice(*m_activeVoices.back(), sampleRate, dynamicPitch);
m_activeVoices.back()->m_backendVoice->setChannelLevels(st->getMaster().m_backendSubmix.get(), FullLevels, false);
m_activeVoices.back()->m_backendVoice->setChannelLevels(st->getAuxA().m_backendSubmix.get(), FullLevels, false);
m_activeVoices.back()->m_backendVoice->setChannelLevels(st->getAuxB().m_backendSubmix.get(), FullLevels, false);
return it; return it;
} }
std::list<std::shared_ptr<Sequencer>>::iterator std::list<std::shared_ptr<Sequencer>>::iterator Engine::_allocateSequencer(const AudioGroup& group, int groupId,
Engine::_allocateSequencer(const AudioGroup& group, int groupId,
int setupId, std::weak_ptr<Studio> studio) int setupId, std::weak_ptr<Studio> studio)
{ {
const SongGroupIndex* songGroup = group.getProj().getSongGroupIndex(groupId); const SongGroupIndex* songGroup = group.getProj().getSongGroupIndex(groupId);
@ -85,12 +90,14 @@ Engine::_allocateSequencer(const AudioGroup& group, int groupId,
return {}; return {};
} }
std::list<std::shared_ptr<Studio>>::iterator Engine::_allocateStudio(bool mainOut) std::shared_ptr<Studio> Engine::_allocateStudio(bool mainOut)
{ {
auto it = m_activeStudios.emplace(m_activeStudios.end(), std::make_shared<Studio>(*this, mainOut)); std::shared_ptr<Studio> ret = std::make_shared<Studio>(*this, mainOut);
m_activeStudios.back()->m_auxA.m_backendSubmix = m_backend.allocateSubmix(m_activeStudios.back()->m_auxA, mainOut); m_activeStudios.emplace(m_activeStudios.end(), ret);
m_activeStudios.back()->m_auxB.m_backendSubmix = m_backend.allocateSubmix(m_activeStudios.back()->m_auxB, mainOut); ret->m_master.m_backendSubmix = m_backend.allocateSubmix(ret->m_master, mainOut, 0);
return it; ret->m_auxA.m_backendSubmix = m_backend.allocateSubmix(ret->m_auxA, mainOut, 1);
ret->m_auxB.m_backendSubmix = m_backend.allocateSubmix(ret->m_auxB, mainOut, 2);
return ret;
} }
std::list<std::shared_ptr<Voice>>::iterator Engine::_destroyVoice(std::list<std::shared_ptr<Voice>>::iterator it) std::list<std::shared_ptr<Voice>>::iterator Engine::_destroyVoice(std::list<std::shared_ptr<Voice>>::iterator it)
@ -104,7 +111,8 @@ std::list<std::shared_ptr<Voice>>::iterator Engine::_destroyVoice(std::list<std:
return m_activeVoices.erase(it); return m_activeVoices.erase(it);
} }
std::list<std::shared_ptr<Sequencer>>::iterator Engine::_destroySequencer(std::list<std::shared_ptr<Sequencer>>::iterator it) std::list<std::shared_ptr<Sequencer>>::iterator
Engine::_destroySequencer(std::list<std::shared_ptr<Sequencer>>::iterator it)
{ {
#ifndef NDEBUG #ifndef NDEBUG
assert(this == &(*it)->getEngine()); assert(this == &(*it)->getEngine());
@ -115,17 +123,6 @@ std::list<std::shared_ptr<Sequencer>>::iterator Engine::_destroySequencer(std::l
return m_activeSequencers.erase(it); return m_activeSequencers.erase(it);
} }
std::list<std::shared_ptr<Studio>>::iterator Engine::_destroyStudio(std::list<std::shared_ptr<Studio>>::iterator it)
{
#ifndef NDEBUG
assert(this == &(*it)->getEngine());
#endif
if ((*it)->m_destroyed)
return m_activeStudios.begin();
(*it)->_destroy();
return m_activeStudios.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();)
@ -163,6 +160,15 @@ void Engine::_bringOutYourDead()
} }
++it; ++it;
} }
for (auto it = m_activeStudios.begin(); it != m_activeStudios.end();)
{
std::shared_ptr<Studio> st = it->lock();
if (!st)
it = m_activeStudios.erase(it);
else
++it;
}
} }
void Engine::_5MsCallback(double dt) void Engine::_5MsCallback(double dt)
@ -284,51 +290,7 @@ void Engine::removeAudioGroup(const AudioGroupData& data)
} }
/** Create new Studio within engine */ /** Create new Studio within engine */
std::shared_ptr<Studio> Engine::addStudio(bool mainOut) std::shared_ptr<Studio> Engine::addStudio(bool mainOut) { return _allocateStudio(mainOut); }
{
return *_allocateStudio(mainOut);
}
std::list<std::shared_ptr<Studio>>::iterator Engine::_removeStudio(std::list<std::shared_ptr<Studio>>::iterator smx)
{
/* Delete all voices bound to studio */
for (auto it = m_activeVoices.begin() ; it != m_activeVoices.end() ; ++it)
{
Voice* vox = it->get();
std::shared_ptr<Studio> vsmx = vox->getStudio();
if (vsmx == *smx)
vox->kill();
}
/* Delete all sequencers bound to studio */
for (auto it = m_activeSequencers.begin() ; it != m_activeSequencers.end() ; ++it)
{
Sequencer* seq = it->get();
std::shared_ptr<Studio> ssmx = seq->getStudio();
if (ssmx == *smx)
seq->kill();
}
/* Delete studio */
return _destroyStudio(smx);
}
/** Remove Submix and deallocate */
void Engine::removeStudio(std::weak_ptr<Studio> smx)
{
std::shared_ptr<Studio> sm = smx.lock();
if (sm == m_defaultStudio)
return;
for (auto it = m_activeStudios.begin() ; it != m_activeStudios.end() ;)
{
if (*it == sm)
{
it = _removeStudio(it);
break;
}
++it;
}
}
/** Start soundFX playing from loaded audio groups */ /** Start soundFX playing from loaded audio groups */
std::shared_ptr<Voice> Engine::fxStart(int sfxId, float vol, float pan, std::weak_ptr<Studio> smx) std::shared_ptr<Voice> Engine::fxStart(int sfxId, float vol, float pan, std::weak_ptr<Studio> smx)
@ -343,8 +305,7 @@ std::shared_ptr<Voice> Engine::fxStart(int sfxId, float vol, float pan, std::wea
return nullptr; return nullptr;
std::list<std::shared_ptr<Voice>>::iterator ret = std::list<std::shared_ptr<Voice>>::iterator ret =
_allocateVoice(*grp, std::get<1>(search->second), _allocateVoice(*grp, std::get<1>(search->second), 32000.0, true, false, smx);
32000.0, true, false, smx);
ObjectId oid = (grp->getDataFormat() == DataFormat::PC) ? entry->objId : SBig(entry->objId); ObjectId oid = (grp->getDataFormat() == DataFormat::PC) ? entry->objId : SBig(entry->objId);
if (!(*ret)->loadSoundObject(oid, 0, 1000.f, entry->defKey, entry->defVel, 0)) if (!(*ret)->loadSoundObject(oid, 0, 1000.f, entry->defKey, entry->defVel, 0))
@ -359,9 +320,8 @@ std::shared_ptr<Voice> Engine::fxStart(int sfxId, float vol, float pan, std::wea
} }
/** Start soundFX playing from loaded audio groups, attach to positional emitter */ /** Start soundFX playing from loaded audio groups, attach to positional emitter */
std::shared_ptr<Emitter> Engine::addEmitter(const Vector3f& pos, const Vector3f& dir, float maxDist, std::shared_ptr<Emitter> Engine::addEmitter(const Vector3f& pos, const Vector3f& dir, float maxDist, float falloff,
float falloff, int sfxId, float minVol, float maxVol, int sfxId, float minVol, float maxVol, std::weak_ptr<Studio> smx)
std::weak_ptr<Studio> smx)
{ {
auto search = m_sfxLookup.find(sfxId); auto search = m_sfxLookup.find(sfxId);
if (search == m_sfxLookup.end()) if (search == m_sfxLookup.end())
@ -373,8 +333,7 @@ std::shared_ptr<Emitter> Engine::addEmitter(const Vector3f& pos, const Vector3f&
return nullptr; return nullptr;
std::list<std::shared_ptr<Voice>>::iterator vox = std::list<std::shared_ptr<Voice>>::iterator vox =
_allocateVoice(*grp, std::get<1>(search->second), _allocateVoice(*grp, std::get<1>(search->second), 32000.0, true, true, smx);
32000.0, true, true, smx);
auto emitIt = m_activeEmitters.emplace(m_activeEmitters.end(), new Emitter(*this, *grp, std::move(*vox))); auto emitIt = m_activeEmitters.emplace(m_activeEmitters.end(), new Emitter(*this, *grp, std::move(*vox)));
Emitter& ret = *(*emitIt); Emitter& ret = *(*emitIt);
@ -398,8 +357,8 @@ std::shared_ptr<Emitter> Engine::addEmitter(const Vector3f& pos, const Vector3f&
} }
/** Start song playing from loaded audio groups */ /** Start song playing from loaded audio groups */
std::shared_ptr<Sequencer> Engine::seqPlay(int groupId, int songId, std::shared_ptr<Sequencer> Engine::seqPlay(int groupId, int songId, const unsigned char* arrData,
const unsigned char* arrData, std::weak_ptr<Studio> smx) std::weak_ptr<Studio> smx)
{ {
std::pair<AudioGroup*, const SongGroupIndex*> songGrp = _findSongGroup(groupId); std::pair<AudioGroup*, const SongGroupIndex*> songGrp = _findSongGroup(groupId);
if (songGrp.second) if (songGrp.second)
@ -480,5 +439,4 @@ void Engine::sendMacroMessage(ObjectId macroId, int32_t val)
for (std::shared_ptr<Sequencer>& seq : m_activeSequencers) for (std::shared_ptr<Sequencer>& seq : m_activeSequencers)
seq->sendMacroMessage(macroId, val); seq->sendMacroMessage(macroId, val);
} }
} }

View File

@ -4,22 +4,16 @@
namespace amuse namespace amuse
{ {
static int32_t MIDItoTIME[104] = static int32_t MIDItoTIME[104] = {/* [0..103] -> milliseconds */
{ /* [0..103] -> milliseconds */ 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110,
0, 10, 20, 30, 40, 50, 60, 70, 110, 120, 130, 140, 150, 160, 170, 190, 200, 220, 230, 250,
80, 90, 100, 110, 110, 120, 130, 140, 270, 290, 310, 330, 350, 380, 410, 440, 470, 500, 540, 580,
150, 160, 170, 190, 200, 220, 230, 250, 620, 660, 710, 760, 820, 880, 940, 1000, 1000, 1100, 1200, 1300,
270, 290, 310, 330, 350, 380, 410, 440, 1400, 1500, 1600, 1700, 1800, 2000, 2100, 2300, 2400, 2600, 2800, 3000,
470, 500, 540, 580, 620, 660, 710, 760, 3200, 3500, 3700, 4000, 4300, 4600, 4900, 5300, 5700, 6100, 6500, 7000,
820, 880, 940, 1000, 1000, 1100, 1200, 1300, 7500, 8100, 8600, 9300, 9900, 10000, 11000, 12000, 13000, 14000, 15000, 16000,
1400, 1500, 1600, 1700, 1800, 2000, 2100, 2300, 17000, 18000, 19000, 21000, 22000, 24000, 26000, 28000, 30000, 32000, 34000, 37000,
2400, 2600, 2800, 3000, 3200, 3500, 3700, 4000, 39000, 42000, 45000, 49000, 50000, 55000, 60000, 65000};
4300, 4600, 4900, 5300, 5700, 6100, 6500, 7000,
7500, 8100, 8600, 9300, 9900, 10000, 11000, 12000,
13000, 14000, 15000, 16000, 17000, 18000, 19000, 21000,
22000, 24000, 26000, 28000, 30000, 32000, 34000, 37000,
39000, 42000, 45000, 49000, 50000, 55000, 60000, 65000
};
void Envelope::reset(const ADSR* adsr) void Envelope::reset(const ADSR* adsr)
{ {
@ -231,5 +225,4 @@ float Envelope::advance(double dt)
return 0.f; return 0.f;
} }
} }
} }

View File

@ -48,44 +48,28 @@ void Sequencer::_destroy()
{ {
Entity::_destroy(); Entity::_destroy();
if (m_studio) if (m_studio)
{
m_engine.removeStudio(m_studio);
m_studio.reset(); m_studio.reset();
} }
}
Sequencer::~Sequencer() Sequencer::~Sequencer()
{ {
if (m_studio) if (m_studio)
{
m_engine.removeStudio(m_studio);
m_studio.reset(); m_studio.reset();
} }
}
Sequencer::Sequencer(Engine& engine, const AudioGroup& group, int groupId, Sequencer::Sequencer(Engine& engine, const AudioGroup& group, int groupId, const SongGroupIndex* songGroup, int setupId,
const SongGroupIndex* songGroup, int setupId, std::weak_ptr<Studio> studio) std::weak_ptr<Studio> studio)
: Entity(engine, group, groupId), m_songGroup(songGroup) : Entity(engine, group, groupId), m_songGroup(songGroup), m_studio(studio)
{ {
auto it = m_songGroup->m_midiSetups.find(setupId); auto it = m_songGroup->m_midiSetups.find(setupId);
if (it != m_songGroup->m_midiSetups.cend()) if (it != m_songGroup->m_midiSetups.cend())
m_midiSetup = it->second->data(); m_midiSetup = it->second->data();
std::shared_ptr<Studio> st = studio.lock();
m_studio = m_engine.addStudio(st ? false : true);
if (st)
m_studio->addStudioSend(studio, 1.f, 0.f, 0.f);
m_studio->getAuxA().makeReverbHi(0.2f, 0.3f, 1.f, 0.5f, 0.f, 0.f);
m_studio->getAuxB().makeChorus(10, 5, 1000);
} }
Sequencer::Sequencer(Engine& engine, const AudioGroup& group, int groupId, Sequencer::Sequencer(Engine& engine, const AudioGroup& group, int groupId, const SFXGroupIndex* sfxGroup,
const SFXGroupIndex* sfxGroup, std::weak_ptr<Studio> studio) std::weak_ptr<Studio> studio)
: Entity(engine, group, groupId), m_sfxGroup(sfxGroup) : Entity(engine, group, groupId), m_sfxGroup(sfxGroup), m_studio(studio)
{ {
//m_submix = m_engine.addSubmix(smx);
//m_submix->makeReverbHi(0.2f, 0.3f, 1.f, 0.5f, 0.f, 0.f);
std::map<uint16_t, const SFXGroupIndex::SFXEntry*> sortSFX; std::map<uint16_t, const SFXGroupIndex::SFXEntry*> sortSFX;
for (const auto& sfx : sfxGroup->m_sfxEntries) for (const auto& sfx : sfxGroup->m_sfxEntries)
sortSFX[sfx.first] = sfx.second; sortSFX[sfx.first] = sfx.second;
@ -95,12 +79,9 @@ Sequencer::Sequencer(Engine& engine, const AudioGroup& group, int groupId,
m_sfxMappings.push_back(sfx.second); m_sfxMappings.push_back(sfx.second);
} }
Sequencer::ChannelState::~ChannelState() Sequencer::ChannelState::~ChannelState() {}
{
}
Sequencer::ChannelState::ChannelState(Sequencer& parent, uint8_t chanId) Sequencer::ChannelState::ChannelState(Sequencer& parent, uint8_t chanId) : m_parent(parent), m_chanId(chanId)
: m_parent(parent), m_chanId(chanId)
{ {
if (m_parent.m_songGroup) if (m_parent.m_songGroup)
{ {
@ -218,10 +199,8 @@ std::shared_ptr<Voice> Sequencer::ChannelState::keyOn(uint8_t note, uint8_t velo
m_chanVoxs.erase(keySearch); m_chanVoxs.erase(keySearch);
} }
std::list<std::shared_ptr<Voice>>::iterator ret = std::list<std::shared_ptr<Voice>>::iterator ret = m_parent.m_engine._allocateVoice(
m_parent.m_engine._allocateVoice(m_parent.m_audioGroup, m_parent.m_audioGroup, m_parent.m_groupId, 32000.0, true, false, m_parent.m_studio);
m_parent.m_groupId, 32000.0,
true, false, m_parent.m_studio);
if (*ret) if (*ret)
{ {
m_chanVoxs[note] = *ret; m_chanVoxs[note] = *ret;
@ -247,6 +226,7 @@ std::shared_ptr<Voice> Sequencer::ChannelState::keyOn(uint8_t note, uint8_t velo
} }
(*ret)->setVolume(m_parent.m_curVol * m_curVol); (*ret)->setVolume(m_parent.m_curVol * m_curVol);
(*ret)->setReverbVol(m_ctrlVals[0x5b] / 127.f); (*ret)->setReverbVol(m_ctrlVals[0x5b] / 127.f);
(*ret)->setAuxBVol(m_ctrlVals[0x5d] / 127.f);
(*ret)->setPan(m_curPan); (*ret)->setPan(m_curPan);
(*ret)->setPitchWheel(m_curPitchWheel); (*ret)->setPitchWheel(m_curPitchWheel);
@ -307,7 +287,8 @@ void Sequencer::ChannelState::setCtrlValue(uint8_t ctrl, int8_t val)
case 10: case 10:
setPan(val / 64.f - 1.f); setPan(val / 64.f - 1.f);
break; break;
default: break; default:
break;
} }
} }
@ -395,10 +376,7 @@ void Sequencer::setPitchWheel(uint8_t chan, float pitchWheel)
m_chanStates[chan]->setPitchWheel(pitchWheel); m_chanStates[chan]->setPitchWheel(pitchWheel);
} }
void Sequencer::setTempo(double ticksPerSec) void Sequencer::setTempo(double ticksPerSec) { m_ticksPerSec = ticksPerSec; }
{
m_ticksPerSec = ticksPerSec;
}
void Sequencer::ChannelState::allOff() void Sequencer::ChannelState::allOff()
{ {
@ -638,5 +616,4 @@ void Sequencer::prevChanProgram(int8_t chanId)
return m_chanStates[chanId]->prevProgram(); return m_chanStates[chanId]->prevProgram();
} }
} }

View File

@ -33,10 +33,18 @@ enum class Status
}; };
/* Event tags */ /* Event tags */
struct NoteEvent {}; struct NoteEvent
struct CtrlEvent {}; {
struct ProgEvent {}; };
struct PitchEvent {}; struct CtrlEvent
{
};
struct ProgEvent
{
};
struct PitchEvent
{
};
/* Intermediate event */ /* Intermediate event */
struct Event struct Event
@ -55,16 +63,18 @@ struct Event
int pitchBend; int pitchBend;
Event(NoteEvent, uint8_t chan, uint8_t note, uint8_t vel, uint16_t len) Event(NoteEvent, uint8_t chan, uint8_t note, uint8_t vel, uint16_t len)
: isNote(true), channel(chan), noteOrCtrl(note), velOrVal(vel), length(len) {} : isNote(true), channel(chan), noteOrCtrl(note), velOrVal(vel), length(len)
{
}
Event(CtrlEvent, uint8_t chan, uint8_t note, uint8_t vel, uint16_t len) Event(CtrlEvent, uint8_t chan, uint8_t note, uint8_t vel, uint16_t len)
: isControlChange(true), channel(chan), noteOrCtrl(note), velOrVal(vel), length(len) {} : isControlChange(true), channel(chan), noteOrCtrl(note), velOrVal(vel), length(len)
{
}
Event(ProgEvent, uint8_t chan, uint8_t prog) Event(ProgEvent, uint8_t chan, uint8_t prog) : isProgChange(true), channel(chan), program(prog) {}
: isProgChange(true), channel(chan), program(prog) {}
Event(PitchEvent, uint8_t chan, int pBend) Event(PitchEvent, uint8_t chan, int pBend) : isPitchBend(true), channel(chan), pitchBend(pBend) {}
: isPitchBend(true), channel(chan), pitchBend(pBend) {}
}; };
class MIDIDecoder class MIDIDecoder
@ -83,8 +93,7 @@ class MIDIDecoder
} }
uint8_t m_status = 0; uint8_t m_status = 0;
bool _readContinuedValue(std::vector<uint8_t>::const_iterator& it, bool _readContinuedValue(std::vector<uint8_t>::const_iterator& it, std::vector<uint8_t>::const_iterator end,
std::vector<uint8_t>::const_iterator end,
uint32_t& valOut) uint32_t& valOut)
{ {
uint8_t a = *it++; uint8_t a = *it++;
@ -112,8 +121,7 @@ class MIDIDecoder
} }
public: public:
std::vector<uint8_t>::const_iterator std::vector<uint8_t>::const_iterator receiveBytes(std::vector<uint8_t>::const_iterator begin,
receiveBytes(std::vector<uint8_t>::const_iterator begin,
std::vector<uint8_t>::const_iterator end) std::vector<uint8_t>::const_iterator end)
{ {
std::vector<uint8_t>::const_iterator it = begin; std::vector<uint8_t>::const_iterator it = begin;
@ -289,11 +297,13 @@ public:
case Status::SysExTerm: case Status::SysExTerm:
case Status::TimingClock: case Status::TimingClock:
case Status::ActiveSensing: case Status::ActiveSensing:
default: break; default:
break;
} }
break; break;
} }
default: break; default:
break;
} }
} }
@ -357,97 +367,85 @@ class MIDIEncoder
public: public:
void noteOff(uint8_t chan, uint8_t key, uint8_t velocity) void noteOff(uint8_t chan, uint8_t key, uint8_t velocity)
{ {
uint8_t cmd[3] = {uint8_t(int(Status::NoteOff) | (chan & 0xf)), uint8_t cmd[3] = {uint8_t(int(Status::NoteOff) | (chan & 0xf)), uint8_t(key & 0x7f), uint8_t(velocity & 0x7f)};
uint8_t(key & 0x7f), uint8_t(velocity & 0x7f)};
_sendMessage(cmd, 3); _sendMessage(cmd, 3);
} }
void noteOn(uint8_t chan, uint8_t key, uint8_t velocity) void noteOn(uint8_t chan, uint8_t key, uint8_t velocity)
{ {
uint8_t cmd[3] = {uint8_t(int(Status::NoteOn) | (chan & 0xf)), uint8_t cmd[3] = {uint8_t(int(Status::NoteOn) | (chan & 0xf)), uint8_t(key & 0x7f), uint8_t(velocity & 0x7f)};
uint8_t(key & 0x7f), uint8_t(velocity & 0x7f)};
_sendMessage(cmd, 3); _sendMessage(cmd, 3);
} }
void notePressure(uint8_t chan, uint8_t key, uint8_t pressure) void notePressure(uint8_t chan, uint8_t key, uint8_t pressure)
{ {
uint8_t cmd[3] = {uint8_t(int(Status::NotePressure) | (chan & 0xf)), uint8_t cmd[3] = {uint8_t(int(Status::NotePressure) | (chan & 0xf)), uint8_t(key & 0x7f),
uint8_t(key & 0x7f), uint8_t(pressure & 0x7f)}; uint8_t(pressure & 0x7f)};
_sendMessage(cmd, 3); _sendMessage(cmd, 3);
} }
void controlChange(uint8_t chan, uint8_t control, uint8_t value) void controlChange(uint8_t chan, uint8_t control, uint8_t value)
{ {
uint8_t cmd[3] = {uint8_t(int(Status::ControlChange) | (chan & 0xf)), uint8_t cmd[3] = {uint8_t(int(Status::ControlChange) | (chan & 0xf)), uint8_t(control & 0x7f),
uint8_t(control & 0x7f), uint8_t(value & 0x7f)}; uint8_t(value & 0x7f)};
_sendMessage(cmd, 3); _sendMessage(cmd, 3);
} }
void programChange(uint8_t chan, uint8_t program) void programChange(uint8_t chan, uint8_t program)
{ {
uint8_t cmd[2] = {uint8_t(int(Status::ProgramChange) | (chan & 0xf)), uint8_t cmd[2] = {uint8_t(int(Status::ProgramChange) | (chan & 0xf)), uint8_t(program & 0x7f)};
uint8_t(program & 0x7f)};
_sendMessage(cmd, 2); _sendMessage(cmd, 2);
} }
void channelPressure(uint8_t chan, uint8_t pressure) void channelPressure(uint8_t chan, uint8_t pressure)
{ {
uint8_t cmd[2] = {uint8_t(int(Status::ChannelPressure) | (chan & 0xf)), uint8_t cmd[2] = {uint8_t(int(Status::ChannelPressure) | (chan & 0xf)), uint8_t(pressure & 0x7f)};
uint8_t(pressure & 0x7f)};
_sendMessage(cmd, 2); _sendMessage(cmd, 2);
} }
void pitchBend(uint8_t chan, int16_t pitch) void pitchBend(uint8_t chan, int16_t pitch)
{ {
uint8_t cmd[3] = {uint8_t(int(Status::PitchBend) | (chan & 0xf)), uint8_t cmd[3] = {uint8_t(int(Status::PitchBend) | (chan & 0xf)), uint8_t((pitch % 128) & 0x7f),
uint8_t((pitch % 128) & 0x7f), uint8_t((pitch / 128) & 0x7f)}; uint8_t((pitch / 128) & 0x7f)};
_sendMessage(cmd, 3); _sendMessage(cmd, 3);
} }
void allSoundOff(uint8_t chan) void allSoundOff(uint8_t chan)
{ {
uint8_t cmd[3] = {uint8_t(int(Status::ControlChange) | (chan & 0xf)), uint8_t cmd[3] = {uint8_t(int(Status::ControlChange) | (chan & 0xf)), 120, 0};
120, 0};
_sendMessage(cmd, 3); _sendMessage(cmd, 3);
} }
void resetAllControllers(uint8_t chan) void resetAllControllers(uint8_t chan)
{ {
uint8_t cmd[3] = {uint8_t(int(Status::ControlChange) | (chan & 0xf)), uint8_t cmd[3] = {uint8_t(int(Status::ControlChange) | (chan & 0xf)), 121, 0};
121, 0};
_sendMessage(cmd, 3); _sendMessage(cmd, 3);
} }
void localControl(uint8_t chan, bool on) void localControl(uint8_t chan, bool on)
{ {
uint8_t cmd[3] = {uint8_t(int(Status::ControlChange) | (chan & 0xf)), uint8_t cmd[3] = {uint8_t(int(Status::ControlChange) | (chan & 0xf)), 122, uint8_t(on ? 127 : 0)};
122, uint8_t(on ? 127 : 0)};
_sendMessage(cmd, 3); _sendMessage(cmd, 3);
} }
void allNotesOff(uint8_t chan) void allNotesOff(uint8_t chan)
{ {
uint8_t cmd[3] = {uint8_t(int(Status::ControlChange) | (chan & 0xf)), uint8_t cmd[3] = {uint8_t(int(Status::ControlChange) | (chan & 0xf)), 123, 0};
123, 0};
_sendMessage(cmd, 3); _sendMessage(cmd, 3);
} }
void omniMode(uint8_t chan, bool on) void omniMode(uint8_t chan, bool on)
{ {
uint8_t cmd[3] = {uint8_t(int(Status::ControlChange) | (chan & 0xf)), uint8_t cmd[3] = {uint8_t(int(Status::ControlChange) | (chan & 0xf)), uint8_t(on ? 125 : 124), 0};
uint8_t(on ? 125 : 124), 0};
_sendMessage(cmd, 3); _sendMessage(cmd, 3);
} }
void polyMode(uint8_t chan, bool on) void polyMode(uint8_t chan, bool on)
{ {
uint8_t cmd[3] = {uint8_t(int(Status::ControlChange) | (chan & 0xf)), uint8_t cmd[3] = {uint8_t(int(Status::ControlChange) | (chan & 0xf)), uint8_t(on ? 127 : 126), 0};
uint8_t(on ? 127 : 126), 0};
_sendMessage(cmd, 3); _sendMessage(cmd, 3);
} }
void sysex(const void* data, size_t len) void sysex(const void* data, size_t len)
{ {
uint8_t cmd = uint8_t(Status::SysEx); uint8_t cmd = uint8_t(Status::SysEx);
@ -461,22 +459,20 @@ public:
void timeCodeQuarterFrame(uint8_t message, uint8_t value) void timeCodeQuarterFrame(uint8_t message, uint8_t value)
{ {
uint8_t cmd[2] = {uint8_t(int(Status::TimecodeQuarterFrame)), uint8_t cmd[2] = {uint8_t(int(Status::TimecodeQuarterFrame)), uint8_t((message & 0x7 << 4) | (value & 0xf))};
uint8_t((message & 0x7 << 4) | (value & 0xf))};
_sendMessage(cmd, 2); _sendMessage(cmd, 2);
} }
void songPositionPointer(uint16_t pointer) void songPositionPointer(uint16_t pointer)
{ {
uint8_t cmd[3] = {uint8_t(int(Status::SongPositionPointer)), uint8_t cmd[3] = {uint8_t(int(Status::SongPositionPointer)), uint8_t((pointer % 128) & 0x7f),
uint8_t((pointer % 128) & 0x7f), uint8_t((pointer / 128) & 0x7f)}; uint8_t((pointer / 128) & 0x7f)};
_sendMessage(cmd, 3); _sendMessage(cmd, 3);
} }
void songSelect(uint8_t song) void songSelect(uint8_t song)
{ {
uint8_t cmd[2] = {uint8_t(int(Status::TimecodeQuarterFrame)), uint8_t cmd[2] = {uint8_t(int(Status::TimecodeQuarterFrame)), uint8_t(song & 0x7f)};
uint8_t(song & 0x7f)};
_sendMessage(cmd, 2); _sendMessage(cmd, 2);
} }
@ -486,7 +482,6 @@ public:
_sendMessage(&cmd, 1); _sendMessage(&cmd, 1);
} }
void startSeq() void startSeq()
{ {
uint8_t cmd = uint8_t(Status::Start); uint8_t cmd = uint8_t(Status::Start);
@ -505,7 +500,6 @@ public:
_sendMessage(&cmd, 1); _sendMessage(&cmd, 1);
} }
void reset() void reset()
{ {
uint8_t cmd = uint8_t(Status::Reset); uint8_t cmd = uint8_t(Status::Reset);
@ -710,7 +704,8 @@ std::vector<uint8_t> SongConverter::SongToMIDI(const unsigned char* data, int& v
{ {
std::multimap<int, Event> events; std::multimap<int, Event> events;
trk->advanceRegion(nullptr); trk->advanceRegion(nullptr);
uint32_t regStart = song.m_bigEndian ? SBig(trk->m_curRegion->m_startTick) : trk->m_curRegion->m_startTick; uint32_t regStart =
song.m_bigEndian ? SBig(trk->m_curRegion->m_startTick) : trk->m_curRegion->m_startTick;
/* Initial program change */ /* Initial program change */
if (trk->m_curRegion->m_progNum != 0xff) if (trk->m_curRegion->m_progNum != 0xff)
@ -731,7 +726,9 @@ std::vector<uint8_t> SongConverter::SongToMIDI(const unsigned char* data, int& v
trk->m_lastPitchVal += pitchDelta; trk->m_lastPitchVal += pitchDelta;
trk->m_pitchWheelData = ptr; trk->m_pitchWheelData = ptr;
trk->m_lastPitchTick = nextTick; trk->m_lastPitchTick = nextTick;
events.emplace(regStart + nextTick, Event{PitchEvent{}, trk->m_midiChan, clamp(0, trk->m_lastPitchVal / 2 + 0x2000, 0x4000)}); events.emplace(regStart + nextTick,
Event{PitchEvent{}, trk->m_midiChan,
clamp(0, trk->m_lastPitchVal / 2 + 0x2000, 0x4000)});
} }
else else
break; break;
@ -753,7 +750,9 @@ std::vector<uint8_t> SongConverter::SongToMIDI(const unsigned char* data, int& v
trk->m_lastModVal += modDelta; trk->m_lastModVal += modDelta;
trk->m_modWheelData = ptr; trk->m_modWheelData = ptr;
trk->m_lastModTick = nextTick; trk->m_lastModTick = nextTick;
events.emplace(regStart + nextTick, Event{CtrlEvent{}, trk->m_midiChan, 1, uint8_t(clamp(0, trk->m_lastModVal * 128 / 16384, 127)), 0}); events.emplace(regStart + nextTick,
Event{CtrlEvent{}, trk->m_midiChan, 1,
uint8_t(clamp(0, trk->m_lastModVal * 128 / 16384, 127)), 0});
} }
else else
break; break;
@ -778,14 +777,16 @@ std::vector<uint8_t> SongConverter::SongToMIDI(const unsigned char* data, int& v
/* Control change */ /* Control change */
uint8_t val = trk->m_data[0] & 0x7f; uint8_t val = trk->m_data[0] & 0x7f;
uint8_t ctrl = trk->m_data[1] & 0x7f; uint8_t ctrl = trk->m_data[1] & 0x7f;
events.emplace(regStart + trk->m_eventWaitCountdown, Event{CtrlEvent{}, trk->m_midiChan, ctrl, val, 0}); events.emplace(regStart + trk->m_eventWaitCountdown,
Event{CtrlEvent{}, trk->m_midiChan, ctrl, val, 0});
trk->m_data += 2; trk->m_data += 2;
} }
else if (trk->m_data[0] & 0x80) else if (trk->m_data[0] & 0x80)
{ {
/* Program change */ /* Program change */
uint8_t prog = trk->m_data[0] & 0x7f; uint8_t prog = trk->m_data[0] & 0x7f;
events.emplace(regStart + trk->m_eventWaitCountdown, Event{ProgEvent{}, trk->m_midiChan, prog}); events.emplace(regStart + trk->m_eventWaitCountdown,
Event{ProgEvent{}, trk->m_midiChan, prog});
trk->m_data += 2; trk->m_data += 2;
} }
else else
@ -793,9 +794,11 @@ std::vector<uint8_t> SongConverter::SongToMIDI(const unsigned char* data, int& v
/* Note */ /* Note */
uint8_t note = trk->m_data[0] & 0x7f; uint8_t note = trk->m_data[0] & 0x7f;
uint8_t vel = trk->m_data[1] & 0x7f; uint8_t vel = trk->m_data[1] & 0x7f;
uint16_t length = (song.m_bigEndian ? SBig(*reinterpret_cast<const uint16_t*>(trk->m_data + 2)) : uint16_t length =
*reinterpret_cast<const uint16_t*>(trk->m_data + 2)); (song.m_bigEndian ? SBig(*reinterpret_cast<const uint16_t*>(trk->m_data + 2))
events.emplace(regStart + trk->m_eventWaitCountdown, Event{NoteEvent{}, trk->m_midiChan, note, vel, length}); : *reinterpret_cast<const uint16_t*>(trk->m_data + 2));
events.emplace(regStart + trk->m_eventWaitCountdown,
Event{NoteEvent{}, trk->m_midiChan, note, vel, length});
trk->m_data += 4; trk->m_data += 4;
} }
@ -820,31 +823,35 @@ std::vector<uint8_t> SongConverter::SongToMIDI(const unsigned char* data, int& v
if ((trk->m_data[2] & 0x80) != 0x80) if ((trk->m_data[2] & 0x80) != 0x80)
{ {
/* Note */ /* Note */
uint16_t length = (song.m_bigEndian ? SBig(*reinterpret_cast<const uint16_t*>(trk->m_data)) : uint16_t length =
*reinterpret_cast<const uint16_t*>(trk->m_data)); (song.m_bigEndian ? SBig(*reinterpret_cast<const uint16_t*>(trk->m_data))
: *reinterpret_cast<const uint16_t*>(trk->m_data));
uint8_t note = trk->m_data[2] & 0x7f; uint8_t note = trk->m_data[2] & 0x7f;
uint8_t vel = trk->m_data[3] & 0x7f; uint8_t vel = trk->m_data[3] & 0x7f;
events.emplace(regStart + trk->m_eventWaitCountdown, Event{NoteEvent{}, trk->m_midiChan, note, vel, length}); events.emplace(regStart + trk->m_eventWaitCountdown,
Event{NoteEvent{}, trk->m_midiChan, note, vel, length});
} }
else if (trk->m_data[2] & 0x80 && trk->m_data[3] & 0x80) else if (trk->m_data[2] & 0x80 && trk->m_data[3] & 0x80)
{ {
/* Control change */ /* Control change */
uint8_t val = trk->m_data[2] & 0x7f; uint8_t val = trk->m_data[2] & 0x7f;
uint8_t ctrl = trk->m_data[3] & 0x7f; uint8_t ctrl = trk->m_data[3] & 0x7f;
events.emplace(regStart + trk->m_eventWaitCountdown, Event{CtrlEvent{}, trk->m_midiChan, ctrl, val, 0}); events.emplace(regStart + trk->m_eventWaitCountdown,
Event{CtrlEvent{}, trk->m_midiChan, ctrl, val, 0});
} }
else if (trk->m_data[2] & 0x80) else if (trk->m_data[2] & 0x80)
{ {
/* Program change */ /* Program change */
uint8_t prog = trk->m_data[2] & 0x7f; uint8_t prog = trk->m_data[2] & 0x7f;
events.emplace(regStart + trk->m_eventWaitCountdown, Event{ProgEvent{}, trk->m_midiChan, prog}); events.emplace(regStart + trk->m_eventWaitCountdown,
Event{ProgEvent{}, trk->m_midiChan, prog});
} }
trk->m_data += 4; trk->m_data += 4;
} }
/* Set next delta-time */ /* Set next delta-time */
int32_t absTick = (song.m_bigEndian ? SBig(*reinterpret_cast<const int32_t*>(trk->m_data)) : int32_t absTick = (song.m_bigEndian ? SBig(*reinterpret_cast<const int32_t*>(trk->m_data))
*reinterpret_cast<const int32_t*>(trk->m_data)); : *reinterpret_cast<const int32_t*>(trk->m_data));
trk->m_eventWaitCountdown += absTick - trk->m_lastN64EventTick; trk->m_eventWaitCountdown += absTick - trk->m_lastN64EventTick;
trk->m_lastN64EventTick = absTick; trk->m_lastN64EventTick = absTick;
trk->m_data += 4; trk->m_data += 4;
@ -1016,7 +1023,8 @@ std::vector<uint8_t> SongConverter::MIDIToSong(const std::vector<uint8_t>& data,
for (auto& pair : tempos) for (auto& pair : tempos)
{ {
if (big) if (big)
tempoBuf.emplace_back(SBig(uint32_t(pair.first * 384 / header.div)), SBig(uint32_t(pair.second))); tempoBuf.emplace_back(SBig(uint32_t(pair.first * 384 / header.div)),
SBig(uint32_t(pair.second)));
else else
tempoBuf.emplace_back(pair.first * 384 / header.div, pair.second); tempoBuf.emplace_back(pair.first * 384 / header.div, pair.second);
} }
@ -1219,8 +1227,7 @@ std::vector<uint8_t> SongConverter::MIDIToSong(const std::vector<uint8_t>& data,
{ {
if (big) if (big)
{ {
uint32_t selTick = std::max(std::max(lastEventTick - startTick, uint32_t selTick = std::max(std::max(lastEventTick - startTick, lastPitchTick - startTick),
lastPitchTick - startTick),
lastModTick - startTick); lastModTick - startTick);
uint32_t tickBig = SBig(uint32_t(selTick)); uint32_t tickBig = SBig(uint32_t(selTick));
for (int i = 0; i < 4; ++i) for (int i = 0; i < 4; ++i)
@ -1232,8 +1239,7 @@ std::vector<uint8_t> SongConverter::MIDIToSong(const std::vector<uint8_t>& data,
} }
else else
{ {
uint32_t selTick = std::max(std::max(lastEventTick - startTick, uint32_t selTick = std::max(std::max(lastEventTick - startTick, lastPitchTick - startTick),
lastPitchTick - startTick),
lastModTick - startTick); lastModTick - startTick);
uint32_t tick = uint32_t(selTick); uint32_t tick = uint32_t(selTick);
for (int i = 0; i < 4; ++i) for (int i = 0; i < 4; ++i)
@ -1349,8 +1355,8 @@ std::vector<uint8_t> SongConverter::MIDIToSong(const std::vector<uint8_t>& data,
} }
uint32_t idx = trackRegionIdxArr[i]; uint32_t idx = trackRegionIdxArr[i];
*reinterpret_cast<uint32_t*>(&*ret.insert(ret.cend(), 4, 0)) = big ? SBig(uint32_t(0x18 + 4 * 64 + idx * 12)) : *reinterpret_cast<uint32_t*>(&*ret.insert(ret.cend(), 4, 0)) =
uint32_t(0x18 + 4 * 64 + idx * 12); big ? SBig(uint32_t(0x18 + 4 * 64 + idx * 12)) : uint32_t(0x18 + 4 * 64 + idx * 12);
} }
for (SongState::TrackRegion& reg : regionBuf) for (SongState::TrackRegion& reg : regionBuf)
@ -1358,8 +1364,8 @@ std::vector<uint8_t> SongConverter::MIDIToSong(const std::vector<uint8_t>& data,
uint32_t regBase = regIdxOff + 4 * regionDataIdxArr.size(); uint32_t regBase = regIdxOff + 4 * regionDataIdxArr.size();
for (uint32_t regOff : regionDataIdxArr) for (uint32_t regOff : regionDataIdxArr)
*reinterpret_cast<uint32_t*>(&*ret.insert(ret.cend(), 4, 0)) = big ? SBig(uint32_t(regBase + regOff)) : *reinterpret_cast<uint32_t*>(&*ret.insert(ret.cend(), 4, 0)) =
uint32_t(regBase + regOff); big ? SBig(uint32_t(regBase + regOff)) : uint32_t(regBase + regOff);
uint32_t curOffset = regBase; uint32_t curOffset = regBase;
for (Region& reg : regions) for (Region& reg : regions)
@ -1368,15 +1374,15 @@ std::vector<uint8_t> SongConverter::MIDIToSong(const std::vector<uint8_t>& data,
if (reg.pitchBuf.size()) if (reg.pitchBuf.size())
*reinterpret_cast<uint32_t*>(&*ret.insert(ret.cend(), 4, 0)) = *reinterpret_cast<uint32_t*>(&*ret.insert(ret.cend(), 4, 0)) =
big ? SBig(uint32_t(curOffset + 12 + reg.eventBuf.size())) : big ? SBig(uint32_t(curOffset + 12 + reg.eventBuf.size()))
uint32_t(curOffset + 12 + reg.eventBuf.size()); : uint32_t(curOffset + 12 + reg.eventBuf.size());
else else
ret.insert(ret.cend(), 4, 0); ret.insert(ret.cend(), 4, 0);
if (reg.modBuf.size()) if (reg.modBuf.size())
*reinterpret_cast<uint32_t*>(&*ret.insert(ret.cend(), 4, 0)) = *reinterpret_cast<uint32_t*>(&*ret.insert(ret.cend(), 4, 0)) =
big ? SBig(uint32_t(curOffset + 12 + reg.eventBuf.size() + reg.pitchBuf.size())) : big ? SBig(uint32_t(curOffset + 12 + reg.eventBuf.size() + reg.pitchBuf.size()))
uint32_t(curOffset + 12 + reg.eventBuf.size() + reg.pitchBuf.size()); : uint32_t(curOffset + 12 + reg.eventBuf.size() + reg.pitchBuf.size());
else else
ret.insert(ret.cend(), 4, 0); ret.insert(ret.cend(), 4, 0);
@ -1428,8 +1434,8 @@ std::vector<uint8_t> SongConverter::MIDIToSong(const std::vector<uint8_t>& data,
} }
uint32_t idx = trackRegionIdxArr[i]; uint32_t idx = trackRegionIdxArr[i];
*reinterpret_cast<uint32_t*>(&*ret.insert(ret.cend(), 4, 0)) = big ? SBig(uint32_t(0x18 + 4 * 64 + idx * 12)) : *reinterpret_cast<uint32_t*>(&*ret.insert(ret.cend(), 4, 0)) =
uint32_t(0x18 + 4 * 64 + idx * 12); big ? SBig(uint32_t(0x18 + 4 * 64 + idx * 12)) : uint32_t(0x18 + 4 * 64 + idx * 12);
} }
memmove(&*ret.insert(ret.cend(), 64, 0), chanMap.data(), 64); memmove(&*ret.insert(ret.cend(), 64, 0), chanMap.data(), 64);
@ -1442,15 +1448,15 @@ std::vector<uint8_t> SongConverter::MIDIToSong(const std::vector<uint8_t>& data,
if (reg.pitchBuf.size()) if (reg.pitchBuf.size())
*reinterpret_cast<uint32_t*>(&*ret.insert(ret.cend(), 4, 0)) = *reinterpret_cast<uint32_t*>(&*ret.insert(ret.cend(), 4, 0)) =
big ? SBig(uint32_t(curOffset + 12 + reg.eventBuf.size())) : big ? SBig(uint32_t(curOffset + 12 + reg.eventBuf.size()))
uint32_t(curOffset + 12 + reg.eventBuf.size()); : uint32_t(curOffset + 12 + reg.eventBuf.size());
else else
ret.insert(ret.cend(), 4, 0); ret.insert(ret.cend(), 4, 0);
if (reg.modBuf.size()) if (reg.modBuf.size())
*reinterpret_cast<uint32_t*>(&*ret.insert(ret.cend(), 4, 0)) = *reinterpret_cast<uint32_t*>(&*ret.insert(ret.cend(), 4, 0)) =
big ? SBig(uint32_t(curOffset + 12 + reg.eventBuf.size() + reg.pitchBuf.size())) : big ? SBig(uint32_t(curOffset + 12 + reg.eventBuf.size() + reg.pitchBuf.size()))
uint32_t(curOffset + 12 + reg.eventBuf.size() + reg.pitchBuf.size()); : uint32_t(curOffset + 12 + reg.eventBuf.size() + reg.pitchBuf.size());
else else
ret.insert(ret.cend(), 4, 0); ret.insert(ret.cend(), 4, 0);
@ -1469,8 +1475,8 @@ std::vector<uint8_t> SongConverter::MIDIToSong(const std::vector<uint8_t>& data,
} }
for (uint32_t regOff : regionDataIdxArr) for (uint32_t regOff : regionDataIdxArr)
*reinterpret_cast<uint32_t*>(&*ret.insert(ret.cend(), 4, 0)) = big ? SBig(uint32_t(regBase + regOff)) : *reinterpret_cast<uint32_t*>(&*ret.insert(ret.cend(), 4, 0)) =
uint32_t(regBase + regOff); big ? SBig(uint32_t(regBase + regOff)) : uint32_t(regBase + regOff);
if (tempoBuf.size()) if (tempoBuf.size())
memmove(&*ret.insert(ret.cend(), tempoBuf.size() * 8, 0), tempoBuf.data(), tempoBuf.size() * 8); memmove(&*ret.insert(ret.cend(), tempoBuf.size() * 8, 0), tempoBuf.data(), tempoBuf.size() * 8);
@ -1480,5 +1486,4 @@ std::vector<uint8_t> SongConverter::MIDIToSong(const std::vector<uint8_t>& data,
return ret; return ret;
} }
} }

View File

@ -107,12 +107,11 @@ SongState::Track::Track(SongState& parent, uint8_t midiChan, const TrackRegion*
void SongState::Track::setRegion(Sequencer* seq, const TrackRegion* region) void SongState::Track::setRegion(Sequencer* seq, const TrackRegion* region)
{ {
m_curRegion = region; m_curRegion = region;
uint32_t regionIdx = (m_parent.m_bigEndian ? SBig(m_curRegion->m_regionIndex) : uint32_t regionIdx = (m_parent.m_bigEndian ? SBig(m_curRegion->m_regionIndex) : m_curRegion->m_regionIndex);
m_curRegion->m_regionIndex);
m_nextRegion = &m_curRegion[1]; m_nextRegion = &m_curRegion[1];
m_data = m_parent.m_songData + (m_parent.m_bigEndian ? SBig(m_parent.m_regionIdx[regionIdx]) : m_data = m_parent.m_songData +
m_parent.m_regionIdx[regionIdx]); (m_parent.m_bigEndian ? SBig(m_parent.m_regionIdx[regionIdx]) : m_parent.m_regionIdx[regionIdx]);
Header header = *reinterpret_cast<const Header*>(m_data); Header header = *reinterpret_cast<const Header*>(m_data);
if (m_parent.m_bigEndian) if (m_parent.m_bigEndian)
@ -138,18 +137,15 @@ void SongState::Track::setRegion(Sequencer* seq, const TrackRegion* region)
m_eventWaitCountdown = int32_t(DecodeTimeRLE(m_data)); m_eventWaitCountdown = int32_t(DecodeTimeRLE(m_data));
else else
{ {
int32_t absTick = (m_parent.m_bigEndian ? SBig(*reinterpret_cast<const int32_t*>(m_data)) : int32_t absTick = (m_parent.m_bigEndian ? SBig(*reinterpret_cast<const int32_t*>(m_data))
*reinterpret_cast<const int32_t*>(m_data)); : *reinterpret_cast<const int32_t*>(m_data));
m_eventWaitCountdown = absTick; m_eventWaitCountdown = absTick;
m_lastN64EventTick = absTick; m_lastN64EventTick = absTick;
m_data += 4; m_data += 4;
} }
} }
void SongState::Track::advanceRegion(Sequencer* seq) void SongState::Track::advanceRegion(Sequencer* seq) { setRegion(seq, m_nextRegion); }
{
setRegion(seq, m_nextRegion);
}
int SongState::DetectVersion(const unsigned char* ptr, bool& isBig) int SongState::DetectVersion(const unsigned char* ptr, bool& isBig)
{ {
@ -167,14 +163,14 @@ int SongState::DetectVersion(const unsigned char* ptr, bool& isBig)
if (trackIdx[i]) if (trackIdx[i])
{ {
const TrackRegion* region = nullptr; const TrackRegion* region = nullptr;
const TrackRegion* nextRegion = reinterpret_cast<const TrackRegion*>(ptr + (isBig ? SBig(trackIdx[i]) : trackIdx[i])); const TrackRegion* nextRegion =
reinterpret_cast<const TrackRegion*>(ptr + (isBig ? SBig(trackIdx[i]) : trackIdx[i]));
/* Iterate all regions */ /* Iterate all regions */
while (nextRegion->indexValid(isBig)) while (nextRegion->indexValid(isBig))
{ {
region = nextRegion; region = nextRegion;
uint32_t regionIdx = (isBig ? SBig(region->m_regionIndex) : uint32_t regionIdx = (isBig ? SBig(region->m_regionIndex) : region->m_regionIndex);
region->m_regionIndex);
maxRegionIdx = std::max(maxRegionIdx, regionIdx); maxRegionIdx = std::max(maxRegionIdx, regionIdx);
nextRegion = &region[1]; nextRegion = &region[1];
} }
@ -193,26 +189,26 @@ int SongState::DetectVersion(const unsigned char* ptr, bool& isBig)
if (trackIdx[i]) if (trackIdx[i])
{ {
const TrackRegion* region = nullptr; const TrackRegion* region = nullptr;
const TrackRegion* nextRegion = reinterpret_cast<const TrackRegion*>(ptr + (isBig ? SBig(trackIdx[i]) : trackIdx[i])); const TrackRegion* nextRegion =
reinterpret_cast<const TrackRegion*>(ptr + (isBig ? SBig(trackIdx[i]) : trackIdx[i]));
/* Iterate all regions */ /* Iterate all regions */
while (nextRegion->indexValid(isBig)) while (nextRegion->indexValid(isBig))
{ {
region = nextRegion; region = nextRegion;
uint32_t regionIdx = (isBig ? SBig(region->m_regionIndex) : uint32_t regionIdx = (isBig ? SBig(region->m_regionIndex) : region->m_regionIndex);
region->m_regionIndex);
nextRegion = &region[1]; nextRegion = &region[1];
const unsigned char* data = ptr + (isBig ? SBig(regionIdxTable[regionIdx]) : const unsigned char* data =
regionIdxTable[regionIdx]); ptr + (isBig ? SBig(regionIdxTable[regionIdx]) : regionIdxTable[regionIdx]);
/* Can't reliably validate final region */ /* Can't reliably validate final region */
if (regionIdx == maxRegionIdx) if (regionIdx == maxRegionIdx)
continue; continue;
/* Expected end pointer (next region) */ /* Expected end pointer (next region) */
const unsigned char* expectedEnd = ptr + (isBig ? SBig(regionIdxTable[regionIdx+1]) : const unsigned char* expectedEnd =
regionIdxTable[regionIdx+1]); ptr + (isBig ? SBig(regionIdxTable[regionIdx + 1]) : regionIdxTable[regionIdx + 1]);
Track::Header header = *reinterpret_cast<const Track::Header*>(data); Track::Header header = *reinterpret_cast<const Track::Header*>(data);
if (isBig) if (isBig)
@ -223,7 +219,10 @@ int SongState::DetectVersion(const unsigned char* ptr, bool& isBig)
if (header.m_pitchOff) if (header.m_pitchOff)
{ {
const unsigned char* dptr = ptr + header.m_pitchOff; const unsigned char* dptr = ptr + header.m_pitchOff;
while (DecodeRLE(dptr) != 0xffffffff) {DecodeContinuousRLE(dptr);} while (DecodeRLE(dptr) != 0xffffffff)
{
DecodeContinuousRLE(dptr);
}
if (dptr >= (expectedEnd - 4) && (dptr <= expectedEnd)) if (dptr >= (expectedEnd - 4) && (dptr <= expectedEnd))
continue; continue;
} }
@ -232,7 +231,10 @@ int SongState::DetectVersion(const unsigned char* ptr, bool& isBig)
if (header.m_modOff) if (header.m_modOff)
{ {
const unsigned char* dptr = ptr + header.m_modOff; const unsigned char* dptr = ptr + header.m_modOff;
while (DecodeRLE(dptr) != 0xffffffff) {DecodeContinuousRLE(dptr);} while (DecodeRLE(dptr) != 0xffffffff)
{
DecodeContinuousRLE(dptr);
}
if (dptr >= (expectedEnd - 4) && (dptr <= expectedEnd)) if (dptr >= (expectedEnd - 4) && (dptr <= expectedEnd))
continue; continue;
} }
@ -341,7 +343,8 @@ bool SongState::initialize(const unsigned char* ptr)
{ {
if (trackIdx[i]) if (trackIdx[i])
{ {
const TrackRegion* region = reinterpret_cast<const TrackRegion*>(ptr + (m_bigEndian ? SBig(trackIdx[i]) : trackIdx[i])); const TrackRegion* region =
reinterpret_cast<const TrackRegion*>(ptr + (m_bigEndian ? SBig(trackIdx[i]) : trackIdx[i]));
m_tracks[i].emplace(*this, chanMap[i], region); m_tracks[i].emplace(*this, chanMap[i], region);
} }
else else
@ -368,8 +371,7 @@ bool SongState::Track::advance(Sequencer& seq, int32_t ticks)
/* Advance region if needed */ /* Advance region if needed */
while (m_nextRegion->indexValid(m_parent.m_bigEndian)) while (m_nextRegion->indexValid(m_parent.m_bigEndian))
{ {
uint32_t nextRegTick = (m_parent.m_bigEndian ? SBig(m_nextRegion->m_startTick) : uint32_t nextRegTick = (m_parent.m_bigEndian ? SBig(m_nextRegion->m_startTick) : m_nextRegion->m_startTick);
m_nextRegion->m_startTick);
if (endTick > nextRegTick) if (endTick > nextRegTick)
advanceRegion(&seq); advanceRegion(&seq);
else else
@ -501,8 +503,8 @@ bool SongState::Track::advance(Sequencer& seq, int32_t ticks)
/* Note */ /* Note */
uint8_t note = m_data[0] & 0x7f; uint8_t note = m_data[0] & 0x7f;
uint8_t vel = m_data[1] & 0x7f; uint8_t vel = m_data[1] & 0x7f;
uint16_t length = (m_parent.m_bigEndian ? SBig(*reinterpret_cast<const uint16_t*>(m_data + 2)) : uint16_t length = (m_parent.m_bigEndian ? SBig(*reinterpret_cast<const uint16_t*>(m_data + 2))
*reinterpret_cast<const uint16_t*>(m_data + 2)); : *reinterpret_cast<const uint16_t*>(m_data + 2));
seq.keyOn(m_midiChan, note, vel); seq.keyOn(m_midiChan, note, vel);
m_remNoteLengths[note] = length; m_remNoteLengths[note] = length;
m_data += 4; m_data += 4;
@ -538,8 +540,8 @@ bool SongState::Track::advance(Sequencer& seq, int32_t ticks)
if ((m_data[2] & 0x80) != 0x80) if ((m_data[2] & 0x80) != 0x80)
{ {
/* Note */ /* Note */
uint16_t length = (m_parent.m_bigEndian ? SBig(*reinterpret_cast<const uint16_t*>(m_data)) : uint16_t length = (m_parent.m_bigEndian ? SBig(*reinterpret_cast<const uint16_t*>(m_data))
*reinterpret_cast<const uint16_t*>(m_data)); : *reinterpret_cast<const uint16_t*>(m_data));
uint8_t note = m_data[2] & 0x7f; uint8_t note = m_data[2] & 0x7f;
uint8_t vel = m_data[3] & 0x7f; uint8_t vel = m_data[3] & 0x7f;
seq.keyOn(m_midiChan, note, vel); seq.keyOn(m_midiChan, note, vel);
@ -562,8 +564,8 @@ bool SongState::Track::advance(Sequencer& seq, int32_t ticks)
} }
/* Set next delta-time */ /* Set next delta-time */
int32_t absTick = (m_parent.m_bigEndian ? SBig(*reinterpret_cast<const int32_t*>(m_data)) : int32_t absTick = (m_parent.m_bigEndian ? SBig(*reinterpret_cast<const int32_t*>(m_data))
*reinterpret_cast<const int32_t*>(m_data)); : *reinterpret_cast<const int32_t*>(m_data));
m_eventWaitCountdown += absTick - m_lastN64EventTick; m_eventWaitCountdown += absTick - m_lastN64EventTick;
m_lastN64EventTick = absTick; m_lastN64EventTick = absTick;
m_data += 4; m_data += 4;
@ -628,5 +630,4 @@ bool SongState::advance(Sequencer& seq, double dt)
m_songState = SongPlayState::Stopped; m_songState = SongPlayState::Stopped;
return done; return done;
} }
} }

View File

@ -6,6 +6,7 @@
#include "amuse/AudioGroupPool.hpp" #include "amuse/AudioGroupPool.hpp"
#include <string.h> #include <string.h>
/* Squelch Win32 macro pollution >.< */
#undef SendMessage #undef SendMessage
#undef GetMessage #undef GetMessage
@ -25,13 +26,12 @@ void SoundMacroState::Command::swapBig()
words[1] = SBig(words[1]); words[1] = SBig(words[1]);
} }
void SoundMacroState::Evaluator::addComponent(uint8_t midiCtrl, float scale, void SoundMacroState::Evaluator::addComponent(uint8_t midiCtrl, float scale, Combine combine, VarType varType)
Combine combine, VarType varType)
{ {
m_comps.push_back({midiCtrl, scale, combine, varType}); m_comps.push_back({midiCtrl, scale, combine, varType});
} }
float SoundMacroState::Evaluator::evaluate(const Voice& vox, const SoundMacroState& st) const float SoundMacroState::Evaluator::evaluate(double time, const Voice& vox, const SoundMacroState& st) const
{ {
float value = 0.f; float value = 0.f;
@ -57,12 +57,12 @@ float SoundMacroState::Evaluator::evaluate(const Voice& vox, const SoundMacroSta
case 130: case 130:
/* LFO1 */ /* LFO1 */
if (vox.m_lfoPeriods[0]) if (vox.m_lfoPeriods[0])
thisValue = std::sin(vox.m_voiceTime / vox.m_lfoPeriods[0] * 2.f * M_PIF); thisValue = std::sin(time / vox.m_lfoPeriods[0] * 2.f * M_PIF);
break; break;
case 131: case 131:
/* LFO2 */ /* LFO2 */
if (vox.m_lfoPeriods[1]) if (vox.m_lfoPeriods[1])
thisValue = std::sin(vox.m_voiceTime / vox.m_lfoPeriods[1] * 2.f * M_PIF); thisValue = std::sin(time / vox.m_lfoPeriods[1] * 2.f * M_PIF);
break; break;
case 132: case 132:
/* Surround panning */ /* Surround panning */
@ -89,7 +89,7 @@ float SoundMacroState::Evaluator::evaluate(const Voice& vox, const SoundMacroSta
} }
} }
else if (comp.m_varType == VarType::Var) else if (comp.m_varType == VarType::Var)
thisValue = st.m_variables[std::max(0, std::min(255, int(comp.m_midiCtrl)))]; thisValue = st.m_variables[clamp(0, int(comp.m_midiCtrl), 255)];
/* Apply scale */ /* Apply scale */
thisValue *= comp.m_scale; thisValue *= comp.m_scale;
@ -122,8 +122,8 @@ void SoundMacroState::initialize(const unsigned char* ptr, int step, bool swapDa
initialize(ptr, step, 1000.f, 0, 0, 0, swapData); initialize(ptr, step, 1000.f, 0, 0, 0, swapData);
} }
void SoundMacroState::initialize(const unsigned char* ptr, int step, double ticksPerSec, void SoundMacroState::initialize(const unsigned char* ptr, int step, double ticksPerSec, uint8_t midiKey,
uint8_t midiKey, uint8_t midiVel, uint8_t midiMod, bool swapData) uint8_t midiVel, uint8_t midiMod, bool swapData)
{ {
m_ticksPerSec = ticksPerSec; m_ticksPerSec = ticksPerSec;
m_initKey = midiKey; m_initKey = midiKey;
@ -203,8 +203,7 @@ bool SoundMacroState::advance(Voice& vox, double dt)
if (macroId == m_header.m_macroId) if (macroId == m_header.m_macroId)
m_pc.back().second = macroStep; m_pc.back().second = macroStep;
else else
vox.loadSoundObject(macroId, macroStep, m_ticksPerSec, vox.loadSoundObject(macroId, macroStep, m_ticksPerSec, m_initKey, m_initVel, m_initMod);
m_initKey, m_initVel, m_initMod);
} }
break; break;
@ -221,8 +220,7 @@ bool SoundMacroState::advance(Voice& vox, double dt)
if (macroId == m_header.m_macroId) if (macroId == m_header.m_macroId)
m_pc.back().second = macroStep; m_pc.back().second = macroStep;
else else
vox.loadSoundObject(macroId, macroStep, m_ticksPerSec, vox.loadSoundObject(macroId, macroStep, m_ticksPerSec, m_initKey, m_initVel, m_initMod);
m_initKey, m_initVel, m_initMod);
} }
break; break;
@ -305,8 +303,7 @@ bool SoundMacroState::advance(Voice& vox, double dt)
if (macroId == m_header.m_macroId) if (macroId == m_header.m_macroId)
m_pc.back().second = macroStep; m_pc.back().second = macroStep;
else else
vox.loadSoundObject(macroId, macroStep, m_ticksPerSec, vox.loadSoundObject(macroId, macroStep, m_ticksPerSec, m_initKey, m_initVel, m_initMod);
m_initKey, m_initVel, m_initMod);
break; break;
} }
@ -394,8 +391,7 @@ bool SoundMacroState::advance(Voice& vox, double dt)
if (macroId == m_header.m_macroId) if (macroId == m_header.m_macroId)
m_pc.back().second = macroStep; m_pc.back().second = macroStep;
else else
vox.loadSoundObject(macroId, macroStep, m_ticksPerSec, vox.loadSoundObject(macroId, macroStep, m_ticksPerSec, m_initKey, m_initVel, m_initMod);
m_initKey, m_initVel, m_initMod);
} }
break; break;
@ -426,7 +422,7 @@ bool SoundMacroState::advance(Voice& vox, double dt)
bool orgVel = cmd.m_data[4]; bool orgVel = cmd.m_data[4];
int32_t eval = int32_t(orgVel ? m_initVel : m_curVel) * scale / 127 + add; int32_t eval = int32_t(orgVel ? m_initVel : m_curVel) * scale / 127 + add;
eval = std::max(0, std::min(127, eval)); eval = clamp(0, eval, 127);
if (curve != 0) if (curve != 0)
{ {
@ -462,7 +458,7 @@ bool SoundMacroState::advance(Voice& vox, double dt)
double secTime = fadeTime / q; double secTime = fadeTime / q;
int32_t eval = int32_t(m_curVel) * scale / 127 + add; int32_t eval = int32_t(m_curVel) * scale / 127 + add;
eval = std::max(0, std::min(127, eval)); eval = clamp(0, eval, 127);
const Curve* curveData; const Curve* curveData;
if (curve != 0) if (curve != 0)
@ -517,8 +513,7 @@ bool SoundMacroState::advance(Voice& vox, double dt)
if (macroId == m_header.m_macroId) if (macroId == m_header.m_macroId)
m_pc.back().second = macroStep; m_pc.back().second = macroStep;
else else
vox.loadSoundObject(macroId, macroStep, m_ticksPerSec, vox.loadSoundObject(macroId, macroStep, m_ticksPerSec, m_initKey, m_initVel, m_initMod);
m_initKey, m_initVel, m_initMod);
} }
break; break;
@ -535,7 +530,7 @@ bool SoundMacroState::advance(Voice& vox, double dt)
float secTime = fadeTime / q; float secTime = fadeTime / q;
int32_t eval = int32_t(m_curVel) * scale / 127 + add; int32_t eval = int32_t(m_curVel) * scale / 127 + add;
eval = std::max(0, std::min(127, eval)); eval = clamp(0, eval, 127);
const Curve* curveData; const Curve* curveData;
if (curve != 0) if (curve != 0)
@ -774,8 +769,7 @@ bool SoundMacroState::advance(Voice& vox, double dt)
if (macroId == m_header.m_macroId) if (macroId == m_header.m_macroId)
m_pc.push_back({m_pc.back().first, macroStep}); m_pc.push_back({m_pc.back().first, macroStep});
else else
vox.loadSoundObject(macroId, macroStep, m_ticksPerSec, vox.loadSoundObject(macroId, macroStep, m_ticksPerSec, m_initKey, m_initVel, m_initMod, true);
m_initKey, m_initVel, m_initMod, true);
m_header = *reinterpret_cast<const Header*>(m_pc.back().first); m_header = *reinterpret_cast<const Header*>(m_pc.back().first);
if (vox.getAudioGroup().getDataFormat() != DataFormat::PC) if (vox.getAudioGroup().getDataFormat() != DataFormat::PC)
@ -804,7 +798,8 @@ bool SoundMacroState::advance(Voice& vox, double dt)
vox.m_messageTrap.macroId = macroId; vox.m_messageTrap.macroId = macroId;
vox.m_messageTrap.macroStep = macroStep; vox.m_messageTrap.macroStep = macroStep;
break; break;
default: break; default:
break;
} }
break; break;
@ -827,7 +822,8 @@ bool SoundMacroState::advance(Voice& vox, double dt)
vox.m_messageTrap.macroId = 0xffff; vox.m_messageTrap.macroId = 0xffff;
vox.m_messageTrap.macroStep = -1; vox.m_messageTrap.macroStep = -1;
break; break;
default: break; default:
break;
} }
break; break;
@ -1237,14 +1233,7 @@ bool SoundMacroState::advance(Voice& vox, double dt)
return false; return false;
} }
void SoundMacroState::keyoffNotify(Voice& vox) void SoundMacroState::keyoffNotify(Voice& vox) { m_keyoff = true; }
{
m_keyoff = true;
}
void SoundMacroState::sampleEndNotify(Voice& vox)
{
m_sampleEnd = true;
}
void SoundMacroState::sampleEndNotify(Voice& vox) { m_sampleEnd = true; }
} }

View File

@ -4,62 +4,39 @@
namespace amuse namespace amuse
{ {
void Studio::_destroy()
{
m_destroyed = true;
}
void Studio::_bringOutYourDead()
{
for (auto it = m_studiosOut.begin() ; it != m_studiosOut.end() ;)
{
std::shared_ptr<Studio> studio = it->m_targetStudio.lock();
if (!studio)
it = m_studiosOut.erase(it);
else
++it;
}
}
#ifndef NDEBUG #ifndef NDEBUG
bool Studio::_cyclicCheck(Studio* leaf) bool Studio::_cyclicCheck(Studio* leaf)
{ {
for (auto it = m_studiosOut.begin(); it != m_studiosOut.end();) for (auto it = m_studiosOut.begin(); it != m_studiosOut.end();)
{ {
if (std::shared_ptr<Studio> studio = it->m_targetStudio.lock()) if (leaf == it->m_targetStudio.get() || it->m_targetStudio->_cyclicCheck(leaf))
{
if (leaf == studio.get() || studio->_cyclicCheck(leaf))
return true; return true;
++it; ++it;
} }
else
it = m_studiosOut.erase(it);
}
return false; return false;
} }
#endif #endif
Studio::Studio(Engine& engine, bool mainOut) Studio::Studio(Engine& engine, bool mainOut) : m_engine(engine), m_master(engine), m_auxA(engine), m_auxB(engine)
: m_engine(engine), m_auxA(engine), m_auxB(engine)
{ {
if (mainOut) if (mainOut && engine.m_defaultStudioReady)
addStudioSend(engine.getDefaultStudio(), 1.f, 1.f, 1.f); addStudioSend(engine.getDefaultStudio(), 1.f, 1.f, 1.f);
} }
void Studio::addStudioSend(std::weak_ptr<Studio> studio, float dry, float auxA, float auxB) void Studio::addStudioSend(std::weak_ptr<Studio> studio, float dry, float auxA, float auxB)
{ {
m_studiosOut.emplace_back(studio, dry, auxA, auxB);
#ifndef NDEBUG #ifndef NDEBUG
/* Cyclic check */ /* Cyclic check */
assert(!_cyclicCheck(this)); assert(!_cyclicCheck(this));
#endif #endif
m_studiosOut.emplace_back(studio, dry, auxA, auxB);
} }
void Studio::resetOutputSampleRate(double sampleRate) void Studio::resetOutputSampleRate(double sampleRate)
{ {
m_master.resetOutputSampleRate(sampleRate);
m_auxA.resetOutputSampleRate(sampleRate); m_auxA.resetOutputSampleRate(sampleRate);
m_auxB.resetOutputSampleRate(sampleRate); m_auxB.resetOutputSampleRate(sampleRate);
} }
} }

View File

@ -3,14 +3,7 @@
namespace amuse namespace amuse
{ {
void Submix::_destroy() Submix::Submix(Engine& engine) : m_root(engine) {}
{
m_destroyed = true;
}
Submix::Submix(Engine& engine)
: m_root(engine)
{}
EffectChorus& Submix::makeChorus(uint32_t baseDelay, uint32_t variation, uint32_t period) EffectChorus& Submix::makeChorus(uint32_t baseDelay, uint32_t variation, uint32_t period)
{ {
@ -22,14 +15,13 @@ EffectDelay& Submix::makeDelay(uint32_t initDelay, uint32_t initFeedback, uint32
return makeEffect<EffectDelay>(initDelay, initFeedback, initOutput); return makeEffect<EffectDelay>(initDelay, initFeedback, initOutput);
} }
EffectReverbStd& Submix::makeReverbStd(float coloration, float mix, float time, EffectReverbStd& Submix::makeReverbStd(float coloration, float mix, float time, float damping, float preDelay)
float damping, float preDelay)
{ {
return makeEffect<EffectReverbStd>(coloration, mix, time, damping, preDelay); return makeEffect<EffectReverbStd>(coloration, mix, time, damping, preDelay);
} }
EffectReverbHi& Submix::makeReverbHi(float coloration, float mix, float time, EffectReverbHi& Submix::makeReverbHi(float coloration, float mix, float time, float damping, float preDelay,
float damping, float preDelay, float crosstalk) float crosstalk)
{ {
return makeEffect<EffectReverbHi>(coloration, mix, time, damping, preDelay, crosstalk); return makeEffect<EffectReverbHi>(coloration, mix, time, damping, preDelay, crosstalk);
} }
@ -57,5 +49,4 @@ void Submix::resetOutputSampleRate(double sampleRate)
for (const std::unique_ptr<EffectBaseTypeless>& effect : m_effectStack) for (const std::unique_ptr<EffectBaseTypeless>& effect : m_effectStack)
effect->resetOutputSampleRate(sampleRate); effect->resetOutputSampleRate(sampleRate);
} }
} }

View File

@ -6,16 +6,11 @@
namespace amuse namespace amuse
{ {
static float Dot(const Vector3f& a, const Vector3f& b) static float Dot(const Vector3f& a, const Vector3f& b) { return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; }
{
return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
}
static float Length(const Vector3f& a) static float Length(const Vector3f& a)
{ {
if (std::fabs(a[0]) <= FLT_EPSILON && if (std::fabs(a[0]) <= FLT_EPSILON && std::fabs(a[1]) <= FLT_EPSILON && std::fabs(a[2]) <= 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));
} }
@ -42,6 +37,7 @@ static void Cross(Vector3f& out, const Vector3f& a, const Vector3f& b)
class SimpleMatrix class SimpleMatrix
{ {
Vector3f m_mat[3]; Vector3f m_mat[3];
public: public:
SimpleMatrix(const Vector3f& dir, const Vector3f& up) SimpleMatrix(const Vector3f& dir, const Vector3f& up)
{ {
@ -86,44 +82,30 @@ struct ReferenceVector
} }
}; };
static const ReferenceVector StereoVectors[8] = static const ReferenceVector StereoVectors[8] = {
{ {-0.80901f, 0.58778f, 0.f, 0.3f}, {0.80901f, 0.58778f, 0.f, 0.3f},
{-0.80901f, 0.58778f, 0.f, 0.3f},
{ 0.80901f, 0.58778f, 0.f, 0.3f},
}; };
static const ReferenceVector QuadVectors[8] = static const ReferenceVector QuadVectors[8] = {
{
{-0.70710f, 0.70710f, 0.f, 0.1f}, {-0.70710f, 0.70710f, 0.f, 0.1f},
{0.70710f, 0.70710f, 0.f, 0.1f}, {0.70710f, 0.70710f, 0.f, 0.1f},
{-0.70710f, -0.70710f, 0.f, 0.1f}, {-0.70710f, -0.70710f, 0.f, 0.1f},
{0.70710f, -0.70710f, 0.f, 0.1f}, {0.70710f, -0.70710f, 0.f, 0.1f},
}; };
static const ReferenceVector Sur51Vectors[8] = static const ReferenceVector Sur51Vectors[8] = {
{ {-0.70710f, 0.70710f, 0.f, 0.1f}, {0.70710f, 0.70710f, 0.f, 0.1f}, {-0.70710f, -0.70710f, 0.f, 0.1f},
{-0.70710f, 0.70710f, 0.f, 0.1f}, {0.70710f, -0.70710f, 0.f, 0.1f}, {0.0f, 1.0f, 0.f, 0.1f}, {0.0f, 1.0f, 0.f, 1.0f},
{ 0.70710f, 0.70710f, 0.f, 0.1f},
{-0.70710f, -0.70710f, 0.f, 0.1f},
{ 0.70710f, -0.70710f, 0.f, 0.1f},
{ 0.0f, 1.0f, 0.f, 0.1f},
{ 0.0f, 1.0f, 0.f, 1.0f},
}; };
static const ReferenceVector Sur71Vectors[8] = static const ReferenceVector Sur71Vectors[8] = {
{ {-0.70710f, 0.70710f, 0.f, 0.1f}, {0.70710f, 0.70710f, 0.f, 0.1f}, {-0.70710f, -0.70710f, 0.f, 0.1f},
{-0.70710f, 0.70710f, 0.f, 0.1f}, {0.70710f, -0.70710f, 0.f, 0.1f}, {0.0f, 1.0f, 0.f, 0.1f}, {0.0f, 1.0f, 0.f, 1.0f},
{ 0.70710f, 0.70710f, 0.f, 0.1f}, {-1.f, 0.0f, 0.f, 0.1f}, {1.f, 0.0f, 0.f, 0.1f},
{-0.70710f, -0.70710f, 0.f, 0.1f},
{ 0.70710f, -0.70710f, 0.f, 0.1f},
{ 0.0f, 1.0f, 0.f, 0.1f},
{ 0.0f, 1.0f, 0.f, 1.0f},
{-1.f, 0.0f, 0.f, 0.1f},
{ 1.f, 0.0f, 0.f, 0.1f},
}; };
void SurroundProfiles::SetupRefs(float matOut[8], const ChannelMap& map, void SurroundProfiles::SetupRefs(float matOut[8], const ChannelMap& map, const Vector3f& listenEmit,
const Vector3f& listenEmit, const ReferenceVector refs[]) const ReferenceVector refs[])
{ {
for (unsigned i = 0; i < map.m_channelCount && i < 8; ++i) for (unsigned i = 0; i < map.m_channelCount && i < 8; ++i)
{ {
@ -137,9 +119,8 @@ void SurroundProfiles::SetupRefs(float matOut[8], const ChannelMap& map,
} }
} }
void SurroundProfiles::SetupMatrix(float matOut[8], const ChannelMap& map, AudioChannelSet set, void SurroundProfiles::SetupMatrix(float matOut[8], const ChannelMap& map, AudioChannelSet set, const Vector3f& emitPos,
const Vector3f& emitPos, const Vector3f& listenPos, const Vector3f& listenPos, const Vector3f& listenHeading, const Vector3f& listenUp)
const Vector3f& listenHeading, const Vector3f& listenUp)
{ {
Vector3f listenDelta; Vector3f listenDelta;
listenDelta[0] = emitPos[0] - listenPos[0]; listenDelta[0] = emitPos[0] - listenPos[0];
@ -171,5 +152,4 @@ void SurroundProfiles::SetupMatrix(float matOut[8], const ChannelMap& map, Audio
break; break;
} }
} }
} }

View File

@ -33,7 +33,8 @@ Voice::Voice(Engine& engine, const AudioGroup& group, int groupId, int vid, bool
// fprintf(stderr, "ALLOC %d\n", m_vid); // fprintf(stderr, "ALLOC %d\n", m_vid);
} }
Voice::Voice(Engine& engine, const AudioGroup& group, int groupId, ObjectId oid, int vid, bool emitter, std::weak_ptr<Studio> studio) Voice::Voice(Engine& engine, const AudioGroup& group, int groupId, ObjectId oid, int vid, bool emitter,
std::weak_ptr<Studio> studio)
: Entity(engine, group, groupId, oid), m_vid(vid), m_emitter(emitter), m_studio(studio) : Entity(engine, group, groupId, oid), m_vid(vid), m_emitter(emitter), m_studio(studio)
{ {
// fprintf(stderr, "ALLOC %d\n", m_vid); // fprintf(stderr, "ALLOC %d\n", m_vid);
@ -49,9 +50,8 @@ void Voice::_macroSampleEnd()
m_state.m_inWait = false; m_state.m_inWait = false;
} }
else else
loadSoundObject(m_sampleEndTrap.macroId, m_sampleEndTrap.macroStep, loadSoundObject(m_sampleEndTrap.macroId, m_sampleEndTrap.macroStep, m_state.m_ticksPerSec,
m_state.m_ticksPerSec, m_state.m_initKey, m_state.m_initKey, m_state.m_initVel, m_state.m_initMod);
m_state.m_initVel, m_state.m_initMod);
} }
else else
m_state.sampleEndNotify(*this); m_state.sampleEndNotify(*this);
@ -173,8 +173,8 @@ std::unique_ptr<int8_t[]>& Voice::_ensureCtrlVals()
std::list<std::shared_ptr<Voice>>::iterator Voice::_allocateVoice(double sampleRate, bool dynamicPitch) std::list<std::shared_ptr<Voice>>::iterator Voice::_allocateVoice(double sampleRate, bool dynamicPitch)
{ {
auto it = m_childVoices.emplace(m_childVoices.end(), new Voice(m_engine, m_audioGroup, auto it = m_childVoices.emplace(
m_groupId, m_engine.m_nextVid++, m_emitter, m_studio)); m_childVoices.end(), new Voice(m_engine, m_audioGroup, m_groupId, m_engine.m_nextVid++, m_emitter, m_studio));
m_childVoices.back()->m_backendVoice = m_childVoices.back()->m_backendVoice =
m_engine.getBackend().allocateVoice(*m_childVoices.back(), sampleRate, dynamicPitch); m_engine.getBackend().allocateVoice(*m_childVoices.back(), sampleRate, dynamicPitch);
return it; return it;
@ -189,13 +189,14 @@ std::list<std::shared_ptr<Voice>>::iterator Voice::_destroyVoice(std::list<std::
return m_childVoices.erase(it); return m_childVoices.erase(it);
} }
static void ApplyVolume(float vol, int16_t& samp) template <typename T>
static T ApplyVolume(float vol, T samp)
{ {
/* -10dB to 0dB mapped to full volume range */ /* -10dB to 0dB mapped to full volume range */
samp *= VolumeLUT[int(vol * 65536)]; return samp * VolumeLUT[int(vol * 65536)];
} }
void Voice::_advanceSample(int16_t& samp) void Voice::_procSamplePre(int16_t& samp)
{ {
double dt; double dt;
@ -211,6 +212,7 @@ void Voice::_advanceSample(int16_t& samp)
{ {
uint32_t rem = m_voiceSamples % 160; uint32_t rem = m_voiceSamples % 160;
m_voiceSamples += 1; m_voiceSamples += 1;
dt = m_sampleRate * 160;
if (rem != 0) if (rem != 0)
{ {
/* Lerp within 160-sample block */ /* Lerp within 160-sample block */
@ -218,7 +220,7 @@ void Voice::_advanceSample(int16_t& samp)
float l = clamp(0.f, m_lastLevel * (1.f - t) + m_nextLevel * t, 1.f); float l = clamp(0.f, m_lastLevel * (1.f - t) + m_nextLevel * t, 1.f);
/* Apply total volume to sample using decibel scale */ /* Apply total volume to sample using decibel scale */
ApplyVolume(l, samp); samp = ApplyVolume(l, samp);
return; return;
} }
@ -235,7 +237,7 @@ void Voice::_advanceSample(int16_t& samp)
m_envelopeTime += dt; m_envelopeTime += dt;
float start = m_envelopeStart; float start = m_envelopeStart;
float end = m_envelopeEnd; float end = m_envelopeEnd;
float t = std::max(0.f, std::min(1.f, float(m_envelopeTime / m_envelopeDur))); float t = clamp(0.f, float(m_envelopeTime / m_envelopeDur), 1.f);
if (m_envelopeCurve) if (m_envelopeCurve)
t = (*m_envelopeCurve)[int(t * 127.f)] / 127.f; t = (*m_envelopeCurve)[int(t * 127.f)] / 127.f;
m_curVol = clamp(0.f, (start * (1.0f - t)) + (end * t), 1.f); m_curVol = clamp(0.f, (start * (1.0f - t)) + (end * t), 1.f);
@ -248,7 +250,6 @@ void Voice::_advanceSample(int16_t& samp)
} }
/* Dynamically evaluate per-sample SoundMacro parameters */ /* Dynamically evaluate per-sample SoundMacro parameters */
float evalVol = m_state.m_volumeSel ? (m_state.m_volumeSel.evaluate(*this, m_state) / 2.f * m_curVol) : m_curVol;
/* Process user volume slew */ /* Process user volume slew */
if (m_engine.m_ampMode == AmplitudeMode::PerSample) if (m_engine.m_ampMode == AmplitudeMode::PerSample)
@ -282,16 +283,17 @@ void Voice::_advanceSample(int16_t& samp)
/* Factor in ADSR envelope state */ /* Factor in ADSR envelope state */
float adsr = m_volAdsr.advance(dt, *this); float adsr = m_volAdsr.advance(dt, *this);
m_lastLevel = m_nextLevel; m_lastLevel = m_nextLevel;
m_nextLevel = m_curUserVol * evalVol * adsr * (m_state.m_curVel / 127.f); m_nextLevel = m_curUserVol * m_curVol * adsr * (m_state.m_curVel / 127.f);
/* Apply tremolo */ /* Apply tremolo */
if (m_state.m_tremoloSel && (m_tremoloScale || m_tremoloModScale)) if (m_state.m_tremoloSel && (m_tremoloScale || m_tremoloModScale))
{ {
float t = m_state.m_tremoloSel.evaluate(*this, m_state) / 2.f; float t = m_state.m_tremoloSel.evaluate(m_voiceTime, *this, m_state) / 2.f;
if (m_tremoloScale && m_tremoloModScale) if (m_tremoloScale && m_tremoloModScale)
{ {
float fac = (1.0f - t) + (m_tremoloScale * t); float fac = (1.0f - t) + (m_tremoloScale * t);
float modT = m_state.m_modWheelSel ? (m_state.m_modWheelSel.evaluate(*this, m_state) / 2.f) : (getCtrlValue(1) / 127.f); float modT = m_state.m_modWheelSel ? (m_state.m_modWheelSel.evaluate(m_voiceTime, *this, m_state) / 2.f)
: (getCtrlValue(1) / 127.f);
float modFac = (1.0f - modT) + (m_tremoloModScale * modT); float modFac = (1.0f - modT) + (m_tremoloModScale * modT);
m_nextLevel *= fac * modFac; m_nextLevel *= fac * modFac;
} }
@ -302,7 +304,8 @@ void Voice::_advanceSample(int16_t& samp)
} }
else if (m_tremoloModScale) else if (m_tremoloModScale)
{ {
float modT = m_state.m_modWheelSel ? (m_state.m_modWheelSel.evaluate(*this, m_state) / 2.f) : (getCtrlValue(1) / 127.f); float modT = m_state.m_modWheelSel ? (m_state.m_modWheelSel.evaluate(m_voiceTime, *this, m_state) / 2.f)
: (getCtrlValue(1) / 127.f);
float modFac = (1.0f - modT) + (m_tremoloModScale * modT); float modFac = (1.0f - modT) + (m_tremoloModScale * modT);
m_nextLevel *= modFac; m_nextLevel *= modFac;
} }
@ -311,7 +314,32 @@ void Voice::_advanceSample(int16_t& samp)
m_nextLevel = clamp(0.f, m_nextLevel, 1.f); m_nextLevel = clamp(0.f, m_nextLevel, 1.f);
/* Apply total volume to sample using decibel scale */ /* Apply total volume to sample using decibel scale */
ApplyVolume(m_nextLevel, samp); samp = ApplyVolume(m_nextLevel, samp);
}
template <typename T>
T Voice::_procSampleMaster(double time, T samp)
{
float evalVol = m_state.m_volumeSel ? (m_state.m_volumeSel.evaluate(time, *this, m_state) / 2.f) : 1.f;
return ApplyVolume(clamp(0.f, evalVol, 1.f), samp);
}
template <typename T>
T Voice::_procSampleAuxA(double time, T samp)
{
float evalVol = m_state.m_volumeSel ? (m_state.m_volumeSel.evaluate(time, *this, m_state) / 2.f) : 1.f;
evalVol *= m_state.m_reverbSel ? (m_state.m_reverbSel.evaluate(time, *this, m_state) / 2.f) : m_curReverbVol;
evalVol += m_state.m_preAuxASel ? (m_state.m_preAuxASel.evaluate(time, *this, m_state) / 2.f) : 0.f;
return ApplyVolume(clamp(0.f, evalVol, 1.f), samp);
}
template <typename T>
T Voice::_procSampleAuxB(double time, T samp)
{
float evalVol = m_state.m_volumeSel ? (m_state.m_volumeSel.evaluate(time, *this, m_state) / 2.f) : 1.f;
evalVol *= m_state.m_postAuxB ? (m_state.m_postAuxB.evaluate(time, *this, m_state) / 2.f) : m_curAuxBVol;
evalVol += m_state.m_preAuxBSel ? (m_state.m_preAuxBSel.evaluate(time, *this, m_state) / 2.f) : 0.f;
return ApplyVolume(clamp(0.f, evalVol, 1.f), samp);
} }
uint32_t Voice::_GetBlockSampleCount(SampleFormat fmt) uint32_t Voice::_GetBlockSampleCount(SampleFormat fmt)
@ -335,7 +363,7 @@ void Voice::preSupplyAudio(double dt)
/* Process per-block evaluators here */ /* Process per-block evaluators here */
if (m_state.m_pedalSel) if (m_state.m_pedalSel)
{ {
bool pedal = m_state.m_pedalSel.evaluate(*this, m_state) >= 1.f; bool pedal = m_state.m_pedalSel.evaluate(m_voiceTime, *this, m_state) >= 1.f;
if (pedal != m_sustained) if (pedal != m_sustained)
setPedal(pedal); setPedal(pedal);
} }
@ -343,7 +371,7 @@ void Voice::preSupplyAudio(double dt)
bool panDirty = false; bool panDirty = false;
if (m_state.m_panSel) if (m_state.m_panSel)
{ {
float evalPan = m_state.m_panSel.evaluate(*this, m_state); float evalPan = m_state.m_panSel.evaluate(m_voiceTime, *this, m_state);
if (evalPan != m_curPan) if (evalPan != m_curPan)
{ {
m_curPan = evalPan; m_curPan = evalPan;
@ -352,27 +380,18 @@ void Voice::preSupplyAudio(double dt)
} }
if (m_state.m_spanSel) if (m_state.m_spanSel)
{ {
float evalSpan = m_state.m_spanSel.evaluate(*this, m_state); float evalSpan = m_state.m_spanSel.evaluate(m_voiceTime, *this, m_state);
if (evalSpan != m_curSpan) if (evalSpan != m_curSpan)
{ {
m_curSpan = evalSpan; m_curSpan = evalSpan;
panDirty = true; panDirty = true;
} }
} }
if (m_state.m_reverbSel)
{
float evalRev = m_state.m_reverbSel.evaluate(*this, m_state) / 2.f;
if (evalRev != m_curReverbVol)
{
m_curReverbVol = evalRev;
panDirty = true;
}
}
if (panDirty) if (panDirty)
_setPan(m_curPan); _setPan(m_curPan);
if (m_state.m_pitchWheelSel) if (m_state.m_pitchWheelSel)
_setPitchWheel(m_state.m_pitchWheelSel.evaluate(*this, m_state)); _setPitchWheel(m_state.m_pitchWheelSel.evaluate(m_voiceTime, *this, m_state));
/* Process active pan-sweep */ /* Process active pan-sweep */
bool refresh = false; bool refresh = false;
@ -381,7 +400,7 @@ void Voice::preSupplyAudio(double dt)
m_panningTime += dt; m_panningTime += dt;
float start = (m_panPos - 64) / 64.f; float start = (m_panPos - 64) / 64.f;
float end = (m_panPos + m_panWidth - 64) / 64.f; float end = (m_panPos + m_panWidth - 64) / 64.f;
float t = std::max(0.f, std::min(1.f, m_panningTime / m_panningDur)); float t = clamp(0.f, m_panningTime / m_panningDur, 1.f);
_setPan((start * (1.0f - t)) + (end * t)); _setPan((start * (1.0f - t)) + (end * t));
refresh = true; refresh = true;
@ -396,7 +415,7 @@ void Voice::preSupplyAudio(double dt)
m_spanningTime += dt; m_spanningTime += dt;
float start = (m_spanPos - 64) / 64.f; float start = (m_spanPos - 64) / 64.f;
float end = (m_spanPos + m_spanWidth - 64) / 64.f; float end = (m_spanPos + m_spanWidth - 64) / 64.f;
float t = std::max(0.f, std::min(1.f, m_spanningTime / m_spanningDur)); float t = clamp(0.f, m_spanningTime / m_spanningDur, 1.f);
_setSurroundPan((start * (1.0f - t)) + (end * t)); _setSurroundPan((start * (1.0f - t)) + (end * t));
refresh = true; refresh = true;
@ -412,7 +431,7 @@ void Voice::preSupplyAudio(double dt)
if (m_portamentoTime >= 0.f) if (m_portamentoTime >= 0.f)
{ {
m_portamentoTime += dt; m_portamentoTime += dt;
float t = std::max(0.f, std::min(1.f, m_portamentoTime / m_state.m_portamentoTime)); float t = clamp(0.f, m_portamentoTime / m_state.m_portamentoTime, 1.f);
newPitch = (m_curPitch * (1.0f - t)) + (m_portamentoTarget * t); newPitch = (m_curPitch * (1.0f - t)) + (m_portamentoTarget * t);
refresh = true; refresh = true;
@ -452,10 +471,8 @@ void Voice::preSupplyAudio(double dt)
m_needsSlew = true; m_needsSlew = true;
} }
if (dead && (!m_curSample || m_voxState == VoiceState::KeyOff) && if (dead && (!m_curSample || m_voxState == VoiceState::KeyOff) && m_sampleEndTrap.macroId == 0xffff &&
m_sampleEndTrap.macroId == 0xffff && m_messageTrap.macroId == 0xffff && (!m_curSample || (m_curSample && m_volAdsr.isComplete())))
m_messageTrap.macroId == 0xffff &&
(!m_curSample || (m_curSample && m_volAdsr.isComplete())))
{ {
m_voxState = VoiceState::Dead; m_voxState = VoiceState::Dead;
m_backendVoice->stop(); m_backendVoice->stop();
@ -465,7 +482,6 @@ void Voice::preSupplyAudio(double dt)
size_t Voice::supplyAudio(size_t samples, int16_t* data) size_t Voice::supplyAudio(size_t samples, int16_t* data)
{ {
uint32_t samplesRem = samples; uint32_t samplesRem = samples;
size_t samplesProc = 0;
if (m_curSample) if (m_curSample)
{ {
@ -487,16 +503,15 @@ size_t Voice::supplyAudio(size_t samples, int16_t* data)
{ {
case SampleFormat::DSP: case SampleFormat::DSP:
{ {
decSamples = DSPDecompressFrameRanged(data, m_curSampleData + 8 * block, decSamples =
m_curSample->second.dsp.m_coefs, DSPDecompressFrameRanged(data, m_curSampleData + 8 * block, m_curSample->second.dsp.m_coefs,
&m_prev1, &m_prev2, rem, remCount); &m_prev1, &m_prev2, rem, remCount);
break; break;
} }
case SampleFormat::N64: case SampleFormat::N64:
{ {
decSamples = N64MusyXDecompressFrameRanged(data, m_curSampleData + 256 + 40 * block, decSamples = N64MusyXDecompressFrameRanged(data, m_curSampleData + 256 + 40 * block,
m_curSample->second.vadpcm.m_coefs, m_curSample->second.vadpcm.m_coefs, rem, remCount);
rem, remCount);
break; break;
} }
case SampleFormat::PCM: case SampleFormat::PCM:
@ -524,9 +539,8 @@ size_t Voice::supplyAudio(size_t samples, int16_t* data)
/* Per-sample processing */ /* Per-sample processing */
for (uint32_t i = 0; i < decSamples; ++i) for (uint32_t i = 0; i < decSamples; ++i)
{ {
++samplesProc;
++m_curSamplePos; ++m_curSamplePos;
_advanceSample(data[i]); _procSamplePre(data[i]);
} }
samplesRem -= decSamples; samplesRem -= decSamples;
@ -552,16 +566,14 @@ size_t Voice::supplyAudio(size_t samples, int16_t* data)
{ {
case SampleFormat::DSP: case SampleFormat::DSP:
{ {
decSamples = DSPDecompressFrame(data, m_curSampleData + 8 * block, decSamples = DSPDecompressFrame(data, m_curSampleData + 8 * block, m_curSample->second.dsp.m_coefs,
m_curSample->second.dsp.m_coefs,
&m_prev1, &m_prev2, remCount); &m_prev1, &m_prev2, remCount);
break; break;
} }
case SampleFormat::N64: case SampleFormat::N64:
{ {
decSamples = N64MusyXDecompressFrame(data, m_curSampleData + 256 + 40 * block, decSamples = N64MusyXDecompressFrame(data, m_curSampleData + 256 + 40 * block,
m_curSample->second.vadpcm.m_coefs, m_curSample->second.vadpcm.m_coefs, remCount);
remCount);
break; break;
} }
case SampleFormat::PCM: case SampleFormat::PCM:
@ -589,9 +601,8 @@ size_t Voice::supplyAudio(size_t samples, int16_t* data)
/* Per-sample processing */ /* Per-sample processing */
for (uint32_t i = 0; i < decSamples; ++i) for (uint32_t i = 0; i < decSamples; ++i)
{ {
++samplesProc;
++m_curSamplePos; ++m_curSamplePos;
_advanceSample(data[i]); _procSamplePre(data[i]);
} }
samplesRem -= decSamples; samplesRem -= decSamples;
@ -617,6 +628,90 @@ size_t Voice::supplyAudio(size_t samples, int16_t* data)
return samples; return samples;
} }
void Voice::routeAudio(size_t frames, double dt, int busId, int16_t* in, int16_t* out)
{
dt /= double(frames);
switch (busId)
{
case 0:
default:
{
for (uint32_t i = 0; i < frames; ++i)
out[i] = _procSampleMaster(dt * i + m_voiceTime, in[i]);
break;
}
case 1:
{
for (uint32_t i = 0; i < frames; ++i)
out[i] = _procSampleAuxA(dt * i + m_voiceTime, in[i]);
break;
}
case 2:
{
for (uint32_t i = 0; i < frames; ++i)
out[i] = _procSampleAuxB(dt * i + m_voiceTime, in[i]);
break;
}
}
}
void Voice::routeAudio(size_t frames, double dt, int busId, int32_t* in, int32_t* out)
{
dt /= double(frames);
switch (busId)
{
case 0:
default:
{
for (uint32_t i = 0; i < frames; ++i)
out[i] = _procSampleMaster(dt * i + m_voiceTime, in[i]);
break;
}
case 1:
{
for (uint32_t i = 0; i < frames; ++i)
out[i] = _procSampleAuxA(dt * i + m_voiceTime, in[i]);
break;
}
case 2:
{
for (uint32_t i = 0; i < frames; ++i)
out[i] = _procSampleAuxB(dt * i + m_voiceTime, in[i]);
break;
}
}
}
void Voice::routeAudio(size_t frames, double dt, int busId, float* in, float* out)
{
dt /= double(frames);
switch (busId)
{
case 0:
default:
{
for (uint32_t i = 0; i < frames; ++i)
out[i] = _procSampleMaster(dt * i + m_voiceTime, in[i]);
break;
}
case 1:
{
for (uint32_t i = 0; i < frames; ++i)
out[i] = _procSampleAuxA(dt * i + m_voiceTime, in[i]);
break;
}
case 2:
{
for (uint32_t i = 0; i < frames; ++i)
out[i] = _procSampleAuxB(dt * i + m_voiceTime, in[i]);
break;
}
}
}
int Voice::maxVid() const int Voice::maxVid() const
{ {
int maxVid = m_vid; int maxVid = m_vid;
@ -625,12 +720,11 @@ int Voice::maxVid() const
return maxVid; return maxVid;
} }
std::shared_ptr<Voice> Voice::_startChildMacro(ObjectId macroId, int macroStep, double ticksPerSec, std::shared_ptr<Voice> Voice::_startChildMacro(ObjectId macroId, int macroStep, double ticksPerSec, uint8_t midiKey,
uint8_t midiKey, uint8_t midiVel, uint8_t midiMod, bool pushPc) uint8_t midiVel, uint8_t midiMod, bool pushPc)
{ {
std::list<std::shared_ptr<Voice>>::iterator vox = _allocateVoice(32000.0, true); std::list<std::shared_ptr<Voice>>::iterator vox = _allocateVoice(32000.0, true);
if (!(*vox)->loadSoundObject(macroId, macroStep, ticksPerSec, midiKey, if (!(*vox)->loadSoundObject(macroId, macroStep, ticksPerSec, midiKey, midiVel, midiMod, pushPc))
midiVel, midiMod, pushPc))
{ {
_destroyVoice(vox); _destroyVoice(vox);
return {}; return {};
@ -643,12 +737,12 @@ std::shared_ptr<Voice> Voice::_startChildMacro(ObjectId macroId, int macroStep,
std::shared_ptr<Voice> Voice::startChildMacro(int8_t addNote, ObjectId macroId, int macroStep) std::shared_ptr<Voice> Voice::startChildMacro(int8_t addNote, ObjectId macroId, int macroStep)
{ {
return _startChildMacro(macroId, macroStep, 1000.0, m_state.m_initKey + addNote, return _startChildMacro(macroId, macroStep, 1000.0, m_state.m_initKey + addNote, m_state.m_initVel,
m_state.m_initVel, m_state.m_initMod); m_state.m_initMod);
} }
bool Voice::_loadSoundMacro(const unsigned char* macroData, int macroStep, double ticksPerSec, bool Voice::_loadSoundMacro(const unsigned char* macroData, int macroStep, double ticksPerSec, uint8_t midiKey,
uint8_t midiKey, uint8_t midiVel, uint8_t midiMod, bool pushPc) uint8_t midiVel, uint8_t midiMod, bool pushPc)
{ {
if (m_state.m_pc.empty()) if (m_state.m_pc.empty())
m_state.initialize(macroData, macroStep, ticksPerSec, midiKey, midiVel, midiMod, m_state.initialize(macroData, macroStep, ticksPerSec, midiKey, midiVel, midiMod,
@ -668,8 +762,8 @@ bool Voice::_loadSoundMacro(const unsigned char* macroData, int macroStep, doubl
return true; return true;
} }
bool Voice::_loadKeymap(const Keymap* keymap, int macroStep, double ticksPerSec, bool Voice::_loadKeymap(const Keymap* keymap, int macroStep, double ticksPerSec, uint8_t midiKey, uint8_t midiVel,
uint8_t midiKey, uint8_t midiVel, uint8_t midiMod, bool pushPc) uint8_t midiMod, bool pushPc)
{ {
const Keymap& km = keymap[midiKey]; const Keymap& km = keymap[midiKey];
ObjectId oid = (m_audioGroup.getDataFormat() == DataFormat::PC) ? km.objectId : SBig(km.objectId); ObjectId oid = (m_audioGroup.getDataFormat() == DataFormat::PC) ? km.objectId : SBig(km.objectId);
@ -689,12 +783,12 @@ bool Voice::_loadLayer(const std::vector<const LayerMapping*>& layer, int macroS
{ {
if (midiKey >= mapping->keyLo && midiKey <= mapping->keyHi) if (midiKey >= mapping->keyLo && midiKey <= mapping->keyHi)
{ {
ObjectId oid = (m_audioGroup.getDataFormat() == DataFormat::PC) ? mapping->objectId : SBig(mapping->objectId); ObjectId oid =
(m_audioGroup.getDataFormat() == DataFormat::PC) ? mapping->objectId : SBig(mapping->objectId);
uint8_t mappingKey = midiKey + mapping->transpose; uint8_t mappingKey = midiKey + mapping->transpose;
if (m_voxState != VoiceState::Playing) if (m_voxState != VoiceState::Playing)
{ {
ret |= loadSoundObject(oid, macroStep, ticksPerSec, ret |= loadSoundObject(oid, macroStep, ticksPerSec, mappingKey, midiVel, midiMod, pushPc);
mappingKey, midiVel, midiMod, pushPc);
m_curVol = mapping->volume / 127.f; m_curVol = mapping->volume / 127.f;
_setPan((mapping->pan - 64) / 64.f); _setPan((mapping->pan - 64) / 64.f);
_setSurroundPan((mapping->span - 64) / 64.f); _setSurroundPan((mapping->span - 64) / 64.f);
@ -702,8 +796,7 @@ bool Voice::_loadLayer(const std::vector<const LayerMapping*>& layer, int macroS
else else
{ {
std::shared_ptr<Voice> vox = std::shared_ptr<Voice> vox =
_startChildMacro(oid, macroStep, ticksPerSec, _startChildMacro(oid, macroStep, ticksPerSec, mappingKey, midiVel, midiMod, pushPc);
mappingKey, midiVel, midiMod, pushPc);
if (vox) if (vox)
{ {
vox->m_curVol = mapping->volume / 127.f; vox->m_curVol = mapping->volume / 127.f;
@ -717,9 +810,8 @@ bool Voice::_loadLayer(const std::vector<const LayerMapping*>& layer, int macroS
return ret; return ret;
} }
bool Voice::loadSoundObject(ObjectId objectId, int macroStep, double ticksPerSec, bool Voice::loadSoundObject(ObjectId objectId, int macroStep, double ticksPerSec, uint8_t midiKey, uint8_t midiVel,
uint8_t midiKey, uint8_t midiVel, uint8_t midiMod, uint8_t midiMod, bool pushPc)
bool pushPc)
{ {
const unsigned char* macroData = m_audioGroup.getPool().soundMacro(objectId); const unsigned char* macroData = m_audioGroup.getPool().soundMacro(objectId);
if (macroData) if (macroData)
@ -758,8 +850,7 @@ void Voice::keyOff()
m_state.m_inWait = false; m_state.m_inWait = false;
} }
else else
loadSoundObject(m_keyoffTrap.macroId, m_keyoffTrap.macroStep, loadSoundObject(m_keyoffTrap.macroId, m_keyoffTrap.macroStep, m_state.m_ticksPerSec, m_state.m_initKey,
m_state.m_ticksPerSec, m_state.m_initKey,
m_state.m_initVel, m_state.m_initMod); m_state.m_initVel, m_state.m_initMod);
} }
else else
@ -778,8 +869,7 @@ void Voice::message(int32_t val)
if (m_messageTrap.macroId == m_state.m_header.m_macroId) if (m_messageTrap.macroId == m_state.m_header.m_macroId)
m_state.m_pc.back().second = m_messageTrap.macroStep; m_state.m_pc.back().second = m_messageTrap.macroStep;
else else
loadSoundObject(m_messageTrap.macroId, m_messageTrap.macroStep, loadSoundObject(m_messageTrap.macroId, m_messageTrap.macroStep, m_state.m_ticksPerSec, m_state.m_initKey,
m_state.m_ticksPerSec, m_state.m_initKey,
m_state.m_initVel, m_state.m_initMod); m_state.m_initVel, m_state.m_initMod);
} }
} }
@ -802,8 +892,8 @@ void Voice::startSample(int16_t sampId, int32_t offset)
if (m_curSample->first.m_loopLengthSamples) if (m_curSample->first.m_loopLengthSamples)
{ {
if (offset > int32_t(m_curSample->first.m_loopStartSample)) if (offset > int32_t(m_curSample->first.m_loopStartSample))
offset = ((offset - m_curSample->first.m_loopStartSample) % offset =
m_curSample->first.m_loopLengthSamples) + ((offset - m_curSample->first.m_loopStartSample) % m_curSample->first.m_loopLengthSamples) +
m_curSample->first.m_loopStartSample; m_curSample->first.m_loopStartSample;
} }
else else
@ -822,8 +912,9 @@ void Voice::startSample(int16_t sampId, int32_t offset)
if (m_curFormat == SampleFormat::DSP_DRUM) if (m_curFormat == SampleFormat::DSP_DRUM)
m_curFormat = SampleFormat::DSP; m_curFormat = SampleFormat::DSP;
m_lastSamplePos = m_curSample->first.m_loopLengthSamples ? m_lastSamplePos = m_curSample->first.m_loopLengthSamples
(m_curSample->first.m_loopStartSample + m_curSample->first.m_loopLengthSamples) : numSamples; ? (m_curSample->first.m_loopStartSample + m_curSample->first.m_loopLengthSamples)
: numSamples;
bool looped; bool looped;
_checkSamplePos(looped); _checkSamplePos(looped);
@ -834,20 +925,17 @@ void Voice::startSample(int16_t sampId, int32_t offset)
uint32_t block = m_curSamplePos / 14; uint32_t block = m_curSamplePos / 14;
uint32_t rem = m_curSamplePos % 14; uint32_t rem = m_curSamplePos % 14;
for (uint32_t b = 0; b < block; ++b) for (uint32_t b = 0; b < block; ++b)
DSPDecompressFrameStateOnly(m_curSampleData + 8 * b, m_curSample->second.dsp.m_coefs, DSPDecompressFrameStateOnly(m_curSampleData + 8 * b, m_curSample->second.dsp.m_coefs, &m_prev1,
&m_prev1, &m_prev2, 14); &m_prev2, 14);
if (rem) if (rem)
DSPDecompressFrameStateOnly(m_curSampleData + 8 * block, m_curSample->second.dsp.m_coefs, DSPDecompressFrameStateOnly(m_curSampleData + 8 * block, m_curSample->second.dsp.m_coefs, &m_prev1,
&m_prev1, &m_prev2, rem); &m_prev2, rem);
} }
} }
} }
void Voice::stopSample() void Voice::stopSample() { m_curSample = nullptr; }
{
m_curSample = nullptr;
}
void Voice::setVolume(float vol) void Voice::setVolume(float vol)
{ {
@ -893,12 +981,9 @@ void Voice::_setPan(float pan)
coefs[7] = (totalPan >= 0.f) ? 1.f : (1.f + totalPan); coefs[7] = (totalPan >= 0.f) ? 1.f : (1.f + totalPan);
coefs[7] *= 1.f - std::fabs(totalSpan); coefs[7] *= 1.f - std::fabs(totalSpan);
m_backendVoice->setChannelLevels(nullptr, coefs, true); m_backendVoice->setChannelLevels(m_studio->getMaster().m_backendSubmix.get(), coefs, true);
m_backendVoice->setChannelLevels(m_studio->getAuxA().m_backendSubmix.get(), coefs, true);
float revCoefs[8]; m_backendVoice->setChannelLevels(m_studio->getAuxB().m_backendSubmix.get(), coefs, true);
for (int i=0 ; i<8 ; ++i)
revCoefs[i] = coefs[i] * m_curReverbVol;
m_backendVoice->setChannelLevels(m_studio->getAuxA().m_backendSubmix.get(), revCoefs, true);
} }
void Voice::setPan(float pan) void Voice::setPan(float pan)
@ -976,9 +1061,7 @@ void Voice::setPedal(bool pedal)
vox->setPedal(pedal); vox->setPedal(pedal);
} }
void Voice::setDoppler(float) void Voice::setDoppler(float) {}
{
}
void Voice::setVibrato(int32_t level, int32_t modLevel, float period) void Voice::setVibrato(int32_t level, int32_t modLevel, float period)
{ {
@ -987,10 +1070,7 @@ void Voice::setVibrato(int32_t level, int32_t modLevel, float period)
m_vibratoPeriod = period; m_vibratoPeriod = period;
} }
void Voice::setMod2VibratoRange(int32_t modLevel) void Voice::setMod2VibratoRange(int32_t modLevel) { m_vibratoModLevel = modLevel; }
{
m_vibratoModLevel = modLevel;
}
void Voice::setTremolo(float tremoloScale, float tremoloModScale) void Voice::setTremolo(float tremoloScale, float tremoloModScale)
{ {
@ -1017,11 +1097,17 @@ void Voice::setPitchSweep2(uint8_t times, int16_t add)
void Voice::setReverbVol(float rvol) void Voice::setReverbVol(float rvol)
{ {
m_curReverbVol = clamp(0.f, rvol, 1.f); m_curReverbVol = clamp(0.f, rvol, 1.f);
_setPan(m_curPan);
for (std::shared_ptr<Voice>& vox : m_childVoices) for (std::shared_ptr<Voice>& vox : m_childVoices)
vox->setReverbVol(rvol); vox->setReverbVol(rvol);
} }
void Voice::setAuxBVol(float bvol)
{
m_curAuxBVol = clamp(0.f, bvol, 1.f);
for (std::shared_ptr<Voice>& vox : m_childVoices)
vox->setAuxBVol(bvol);
}
void Voice::setAdsr(ObjectId adsrId, bool dls) void Voice::setAdsr(ObjectId adsrId, bool dls)
{ {
if (dls) if (dls)
@ -1111,7 +1197,8 @@ bool Voice::doPortamento(uint8_t newNote)
pState = true; pState = true;
break; break;
case 2: case 2:
pState = m_state.m_portamentoSel ? (m_state.m_portamentoSel.evaluate(*this, m_state) >= 1.f) : (getCtrlValue(65) >= 64); pState = m_state.m_portamentoSel ? (m_state.m_portamentoSel.evaluate(m_voiceTime, *this, m_state) >= 1.f)
: (getCtrlValue(65) >= 64);
break; break;
} }
@ -1137,6 +1224,10 @@ void Voice::_notifyCtrlChange(uint8_t ctrl, int8_t val)
{ {
setReverbVol(val / 127.f); setReverbVol(val / 127.f);
} }
else if (ctrl == 0x5d)
{
setAuxBVol(val / 127.f);
}
for (std::shared_ptr<Voice>& vox : m_childVoices) for (std::shared_ptr<Voice>& vox : m_childVoices)
vox->_notifyCtrlChange(ctrl, val); vox->_notifyCtrlChange(ctrl, val);
@ -1156,5 +1247,4 @@ void Voice::kill()
for (const std::shared_ptr<Voice>& vox : m_childVoices) for (const std::shared_ptr<Voice>& vox : m_childVoices)
vox->kill(); vox->kill();
} }
} }

View File

@ -1,14 +1,13 @@
namespace amuse /* clang-format off */
{
/* /* # [-10,0] dB RMS volume scale generator
* import math * import math
* print(" %.10ff," % 0.0) * print(" %.10ff," % 0.0)
* for i in range(65536): * for i in range(65536):
* print(" %.10ff," % (math.sqrt(10 ** (i/65536 - 1)) - 0.31622)) * print(" %.10ff," % (math.sqrt(10 ** (i/65536 - 1)) - 0.31622))
*/ */
extern "C" const float VolumeLUT[] = const float VolumeLUT[] =
{ {
0.f, 0.f,
0.0000077660f, 0.0000077660f,
@ -65548,5 +65547,4 @@ extern "C" const float VolumeLUT[] =
0.6837448660f, 0.6837448660f,
0.6837624328f 0.6837624328f
}; };
/* clang-format on */
}