mirror of https://github.com/AxioDL/amuse.git
Working Studio implementation
This commit is contained in:
parent
d3d5595422
commit
2dcb9dd1c7
|
@ -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
|
|
@ -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;
|
||||||
|
|
|
@ -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>
|
||||||
|
@ -47,7 +45,7 @@ void RegisterAudioUnit();
|
||||||
AUAudioUnitBusArray* m_outs;
|
AUAudioUnitBusArray* m_outs;
|
||||||
}
|
}
|
||||||
- (nullable id)initWithComponentDescription:(AudioComponentDescription)componentDescription
|
- (nullable id)initWithComponentDescription:(AudioComponentDescription)componentDescription
|
||||||
error:(NSError * __nullable * __nonnull)outError
|
error:(NSError* __nullable* __nonnull)outError
|
||||||
viewController:(AudioUnitViewController* __nonnull)vc;
|
viewController:(AudioUnitViewController* __nonnull)vc;
|
||||||
- (void)requestAudioGroup:(AudioGroupToken* _Nonnull)group;
|
- (void)requestAudioGroup:(AudioGroupToken* _Nonnull)group;
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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()
|
||||||
|
@ -134,28 +244,22 @@ bool AudioGroupDataCollection::_indexData()
|
||||||
{
|
{
|
||||||
switch (m_metaData->fmt)
|
switch (m_metaData->fmt)
|
||||||
{
|
{
|
||||||
case amuse::DataFormat::GCN:
|
case amuse::DataFormat::GCN:
|
||||||
default:
|
default:
|
||||||
m_loadedData.emplace(m_projData.data(), m_projData.size(),
|
m_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(),
|
amuse::GCNDataTag{});
|
||||||
m_sampData.data(), m_sampData.size(),
|
break;
|
||||||
amuse::GCNDataTag{});
|
case amuse::DataFormat::N64:
|
||||||
break;
|
m_loadedData.emplace(m_projData.data(), m_projData.size(), m_poolData.data(), m_poolData.size(),
|
||||||
case amuse::DataFormat::N64:
|
m_sdirData.data(), m_sdirData.size(), m_sampData.data(), m_sampData.size(),
|
||||||
m_loadedData.emplace(m_projData.data(), m_projData.size(),
|
m_metaData->absOffs, amuse::N64DataTag{});
|
||||||
m_poolData.data(), m_poolData.size(),
|
break;
|
||||||
m_sdirData.data(), m_sdirData.size(),
|
case amuse::DataFormat::PC:
|
||||||
m_sampData.data(), m_sampData.size(),
|
m_loadedData.emplace(m_projData.data(), m_projData.size(), m_poolData.data(), m_poolData.size(),
|
||||||
m_metaData->absOffs, amuse::N64DataTag{});
|
m_sdirData.data(), m_sdirData.size(), m_sampData.data(), m_sampData.size(),
|
||||||
break;
|
m_metaData->absOffs, amuse::PCDataTag{});
|
||||||
case amuse::DataFormat::PC:
|
break;
|
||||||
m_loadedData.emplace(m_projData.data(), m_projData.size(),
|
|
||||||
m_poolData.data(), m_poolData.size(),
|
|
||||||
m_sdirData.data(), m_sdirData.size(),
|
|
||||||
m_sampData.data(), m_sampData.size(),
|
|
||||||
m_metaData->absOffs, amuse::PCDataTag{});
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return m_loadedData.operator bool();
|
return m_loadedData.operator bool();
|
||||||
|
@ -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));
|
||||||
|
|
||||||
|
@ -368,7 +472,7 @@ void AudioGroupCollection::populateFiles(VSTEditor& editor, HTREEITEM colHandle,
|
||||||
|
|
||||||
m_iteratorVec.clear();
|
m_iteratorVec.clear();
|
||||||
m_iteratorVec.reserve(m_groups.size());
|
m_iteratorVec.reserve(m_groups.size());
|
||||||
for (auto it = m_groups.begin() ; it != m_groups.end() ; ++it)
|
for (auto it = m_groups.begin(); it != m_groups.end(); ++it)
|
||||||
{
|
{
|
||||||
ins.item.pszText = LPWSTR(it->first.c_str());
|
ins.item.pszText = LPWSTR(it->first.c_str());
|
||||||
ins.item.lParam = LPARAM(0x80000000 | (parentIdx << 16) | m_iteratorVec.size());
|
ins.item.lParam = LPARAM(0x80000000 | (parentIdx << 16) | m_iteratorVec.size());
|
||||||
|
@ -389,7 +493,7 @@ void AudioGroupFilePresenter::populateCollectionColumn(VSTEditor& editor)
|
||||||
|
|
||||||
m_iteratorVec.clear();
|
m_iteratorVec.clear();
|
||||||
m_iteratorVec.reserve(m_audioGroupCollections.size());
|
m_iteratorVec.reserve(m_audioGroupCollections.size());
|
||||||
for (auto it = m_audioGroupCollections.begin() ; it != m_audioGroupCollections.end() ; ++it)
|
for (auto it = m_audioGroupCollections.begin(); it != m_audioGroupCollections.end(); ++it)
|
||||||
{
|
{
|
||||||
ins.item.cChildren = it->second->m_groups.size() ? 1 : 0;
|
ins.item.cChildren = it->second->m_groups.size() ? 1 : 0;
|
||||||
ins.item.pszText = LPWSTR(it->first.c_str());
|
ins.item.pszText = LPWSTR(it->first.c_str());
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
@ -99,9 +109,8 @@ public:
|
||||||
void addCollection(const std::wstring& name,
|
void addCollection(const std::wstring& name,
|
||||||
std::vector<std::pair<std::wstring, amuse::IntrusiveAudioGroupData>>&& collection);
|
std::vector<std::pair<std::wstring, amuse::IntrusiveAudioGroupData>>&& collection);
|
||||||
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__
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
#include "FileOpenDialog.hpp"
|
#include "FileOpenDialog.hpp"
|
||||||
|
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
#include <windows.h> // For common windows data types and function headers
|
#include <windows.h> // For common windows data types and function headers
|
||||||
#define STRICT_TYPED_ITEMIDS
|
#define STRICT_TYPED_ITEMIDS
|
||||||
#include <objbase.h> // For COM headers
|
#include <objbase.h> // For COM headers
|
||||||
#include <shobjidl.h> // for IFileDialogEvents and IFileDialogControlEvents
|
#include <shobjidl.h> // for IFileDialogEvents and IFileDialogControlEvents
|
||||||
#include <shlwapi.h>
|
#include <shlwapi.h>
|
||||||
#include <knownfolders.h> // for KnownFolder APIs/datatypes/function headers
|
#include <knownfolders.h> // for KnownFolder APIs/datatypes/function headers
|
||||||
#include <propvarutil.h> // for PROPVAR-related functions
|
#include <propvarutil.h> // for PROPVAR-related functions
|
||||||
|
@ -15,26 +15,25 @@
|
||||||
#include <new>
|
#include <new>
|
||||||
|
|
||||||
// Controls
|
// Controls
|
||||||
#define CONTROL_GROUP 2000
|
#define CONTROL_GROUP 2000
|
||||||
#define CONTROL_RADIOBUTTONLIST 2
|
#define CONTROL_RADIOBUTTONLIST 2
|
||||||
#define CONTROL_RADIOBUTTON1 1
|
#define CONTROL_RADIOBUTTON1 1
|
||||||
#define CONTROL_RADIOBUTTON2 2 // It is OK for this to have the same IDas CONTROL_RADIOBUTTONLIST,
|
#define CONTROL_RADIOBUTTON2 2 // It is OK for this to have the same IDas CONTROL_RADIOBUTTONLIST,
|
||||||
// because it is a child control under CONTROL_RADIOBUTTONLIST
|
// because it is a child control under CONTROL_RADIOBUTTONLIST
|
||||||
|
|
||||||
// IDs for the Task Dialog Buttons
|
// IDs for the Task Dialog Buttons
|
||||||
#define IDC_BASICFILEOPEN 100
|
#define IDC_BASICFILEOPEN 100
|
||||||
#define IDC_ADDITEMSTOCUSTOMPLACES 101
|
#define IDC_ADDITEMSTOCUSTOMPLACES 101
|
||||||
#define IDC_ADDCUSTOMCONTROLS 102
|
#define IDC_ADDCUSTOMCONTROLS 102
|
||||||
#define IDC_SETDEFAULTVALUESFORPROPERTIES 103
|
#define IDC_SETDEFAULTVALUESFORPROPERTIES 103
|
||||||
#define IDC_WRITEPROPERTIESUSINGHANDLERS 104
|
#define IDC_WRITEPROPERTIESUSINGHANDLERS 104
|
||||||
#define IDC_WRITEPROPERTIESWITHOUTUSINGHANDLERS 105
|
#define IDC_WRITEPROPERTIESWITHOUTUSINGHANDLERS 105
|
||||||
|
|
||||||
HWND ghMainWnd = 0;
|
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
|
||||||
|
@ -43,15 +42,12 @@ public:
|
||||||
static const QITAB qit[] = {
|
static const QITAB qit[] = {
|
||||||
QITABENT(CDialogEventHandler, IFileDialogEvents),
|
QITABENT(CDialogEventHandler, IFileDialogEvents),
|
||||||
QITABENT(CDialogEventHandler, IFileDialogControlEvents),
|
QITABENT(CDialogEventHandler, IFileDialogControlEvents),
|
||||||
{ 0 },
|
{0},
|
||||||
};
|
};
|
||||||
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()
|
||||||
{
|
{
|
||||||
|
@ -62,106 +58,107 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
// IFileDialogEvents methods
|
// IFileDialogEvents methods
|
||||||
IFACEMETHODIMP OnFileOk(IFileDialog *) { return S_OK; };
|
IFACEMETHODIMP OnFileOk(IFileDialog*) { return S_OK; };
|
||||||
IFACEMETHODIMP OnFolderChange(IFileDialog *) { return S_OK; };
|
IFACEMETHODIMP OnFolderChange(IFileDialog*) { return S_OK; };
|
||||||
IFACEMETHODIMP OnFolderChanging(IFileDialog *, IShellItem *) { return S_OK; };
|
IFACEMETHODIMP OnFolderChanging(IFileDialog*, IShellItem*) { return S_OK; };
|
||||||
IFACEMETHODIMP OnHelp(IFileDialog *) { return S_OK; };
|
IFACEMETHODIMP OnHelp(IFileDialog*) { return S_OK; };
|
||||||
IFACEMETHODIMP OnSelectionChange(IFileDialog *) { return S_OK; };
|
IFACEMETHODIMP OnSelectionChange(IFileDialog*) { return S_OK; };
|
||||||
IFACEMETHODIMP OnShareViolation(IFileDialog *, IShellItem *, FDE_SHAREVIOLATION_RESPONSE *) { return S_OK; };
|
IFACEMETHODIMP OnShareViolation(IFileDialog*, IShellItem*, FDE_SHAREVIOLATION_RESPONSE*) { return S_OK; };
|
||||||
IFACEMETHODIMP OnTypeChange(IFileDialog *pfd);
|
IFACEMETHODIMP OnTypeChange(IFileDialog* pfd);
|
||||||
IFACEMETHODIMP OnOverwrite(IFileDialog *, IShellItem *, FDE_OVERWRITE_RESPONSE *) { return S_OK; };
|
IFACEMETHODIMP OnOverwrite(IFileDialog*, IShellItem*, FDE_OVERWRITE_RESPONSE*) { return S_OK; };
|
||||||
|
|
||||||
// IFileDialogControlEvents methods
|
// IFileDialogControlEvents methods
|
||||||
IFACEMETHODIMP OnItemSelected(IFileDialogCustomize *pfdc, DWORD dwIDCtl, DWORD dwIDItem);
|
IFACEMETHODIMP OnItemSelected(IFileDialogCustomize* pfdc, DWORD dwIDCtl, DWORD dwIDItem);
|
||||||
IFACEMETHODIMP OnButtonClicked(IFileDialogCustomize *, DWORD) { return S_OK; };
|
IFACEMETHODIMP OnButtonClicked(IFileDialogCustomize*, DWORD) { return S_OK; };
|
||||||
IFACEMETHODIMP OnCheckButtonToggled(IFileDialogCustomize *, DWORD, BOOL) { return S_OK; };
|
IFACEMETHODIMP OnCheckButtonToggled(IFileDialogCustomize*, DWORD, BOOL) { return S_OK; };
|
||||||
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;
|
||||||
};
|
};
|
||||||
|
|
||||||
HRESULT CDialogEventHandler_CreateInstance(REFIID riid, void **ppv);
|
HRESULT CDialogEventHandler_CreateInstance(REFIID riid, void** ppv);
|
||||||
|
|
||||||
std::wstring openDB()
|
std::wstring openDB()
|
||||||
{
|
{
|
||||||
std::wstring ret;
|
std::wstring ret;
|
||||||
CoInitializeEx(NULL, COINIT_MULTITHREADED | COINIT_DISABLE_OLE1DDE);
|
CoInitializeEx(NULL, COINIT_MULTITHREADED | COINIT_DISABLE_OLE1DDE);
|
||||||
|
|
||||||
//Cocreate the file open dialog object
|
// Cocreate the file open dialog object
|
||||||
IFileDialog *pfd = NULL;
|
IFileDialog* pfd = NULL;
|
||||||
|
|
||||||
HRESULT hr = CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pfd));
|
HRESULT hr = CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pfd));
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
//Stuff needed for later
|
// Stuff needed for later
|
||||||
const COMDLG_FILTERSPEC rgFExt[] = {{L"Audio Group Archive (*.*)", L"*.*"}};
|
const COMDLG_FILTERSPEC rgFExt[] = {{L"Audio Group Archive (*.*)", L"*.*"}};
|
||||||
|
|
||||||
//Create event handling
|
// Create event handling
|
||||||
IFileDialogEvents *pfde = NULL;
|
IFileDialogEvents* pfde = NULL;
|
||||||
hr = CDialogEventHandler_CreateInstance(IID_PPV_ARGS(&pfde));
|
hr = CDialogEventHandler_CreateInstance(IID_PPV_ARGS(&pfde));
|
||||||
|
|
||||||
if(SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
//Hook the event handler
|
// Hook the event handler
|
||||||
DWORD dwCookie;
|
DWORD dwCookie;
|
||||||
|
|
||||||
hr = pfd->Advise(pfde, &dwCookie);
|
hr = pfd->Advise(pfde, &dwCookie);
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
//Set options for the dialog
|
// Set options for the dialog
|
||||||
DWORD dwFlags;
|
DWORD dwFlags;
|
||||||
|
|
||||||
//Get options first so we do not override
|
// Get options first so we do not override
|
||||||
hr = pfd->GetOptions(&dwFlags);
|
hr = pfd->GetOptions(&dwFlags);
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
//Get shell items only
|
// Get shell items only
|
||||||
hr = pfd->SetOptions(dwFlags | FOS_FORCEFILESYSTEM);
|
hr = pfd->SetOptions(dwFlags | FOS_FORCEFILESYSTEM);
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
//Types of files to display (not default)
|
// Types of files to display (not default)
|
||||||
hr = pfd->SetFileTypes(ARRAYSIZE(rgFExt), rgFExt);
|
hr = pfd->SetFileTypes(ARRAYSIZE(rgFExt), rgFExt);
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
//Set default file type to display
|
// Set default file type to display
|
||||||
//hr = pfd->SetDefaultExtension(L"sqlite");
|
// hr = pfd->SetDefaultExtension(L"sqlite");
|
||||||
|
|
||||||
//if (SUCCEEDED(hr))
|
// if (SUCCEEDED(hr))
|
||||||
//{
|
//{
|
||||||
//Show dialog
|
// Show dialog
|
||||||
hr = pfd->Show(NULL);
|
hr = pfd->Show(NULL);
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
// Get the result once the user clicks on open
|
||||||
|
IShellItem* result;
|
||||||
|
|
||||||
|
hr = pfd->GetResult(&result);
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
//Get the result once the user clicks on open
|
// Print out the file name
|
||||||
IShellItem *result;
|
PWSTR fName = NULL;
|
||||||
|
|
||||||
hr = pfd->GetResult(&result);
|
hr = result->GetDisplayName(SIGDN_FILESYSPATH, &fName);
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
//Print out the file name
|
ret.assign(fName);
|
||||||
PWSTR fName = NULL;
|
CoTaskMemFree(fName);
|
||||||
|
|
||||||
hr = result->GetDisplayName(SIGDN_FILESYSPATH, &fName);
|
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
{
|
|
||||||
ret.assign(fName);
|
|
||||||
CoTaskMemFree(fName);
|
|
||||||
}
|
|
||||||
|
|
||||||
result->Release();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
result->Release();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
//}
|
//}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -178,11 +175,10 @@ std::wstring openDB()
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HRESULT CDialogEventHandler_CreateInstance(REFIID riid, void** ppv)
|
||||||
HRESULT CDialogEventHandler_CreateInstance(REFIID riid, void **ppv)
|
|
||||||
{
|
{
|
||||||
*ppv = NULL;
|
*ppv = NULL;
|
||||||
CDialogEventHandler *pDialogEventHandler = new (std::nothrow) CDialogEventHandler();
|
CDialogEventHandler* pDialogEventHandler = new (std::nothrow) CDialogEventHandler();
|
||||||
HRESULT hr = pDialogEventHandler ? S_OK : E_OUTOFMEMORY;
|
HRESULT hr = pDialogEventHandler ? S_OK : E_OUTOFMEMORY;
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
|
@ -192,19 +188,17 @@ HRESULT CDialogEventHandler_CreateInstance(REFIID riid, void **ppv)
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT CDialogEventHandler::OnTypeChange(IFileDialog *pfd)
|
HRESULT CDialogEventHandler::OnTypeChange(IFileDialog* pfd)
|
||||||
{
|
{
|
||||||
IFileSaveDialog *pfsd;
|
IFileSaveDialog* pfsd;
|
||||||
HRESULT hr = pfd->QueryInterface(&pfsd);
|
HRESULT hr = pfd->QueryInterface(&pfsd);
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
UINT uIndex;
|
UINT uIndex;
|
||||||
hr = pfsd->GetFileTypeIndex(&uIndex); // index of current file-type
|
hr = pfsd->GetFileTypeIndex(&uIndex); // index of current file-type
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
IPropertyDescriptionList *pdl = NULL;
|
IPropertyDescriptionList* pdl = NULL;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
pfsd->Release();
|
pfsd->Release();
|
||||||
}
|
}
|
||||||
|
@ -214,9 +208,9 @@ HRESULT CDialogEventHandler::OnTypeChange(IFileDialog *pfd)
|
||||||
// IFileDialogControlEvents
|
// IFileDialogControlEvents
|
||||||
// This method gets called when an dialog control item selection happens (radio-button selection. etc).
|
// This method gets called when an dialog control item selection happens (radio-button selection. etc).
|
||||||
// For sample sake, let's react to this event by changing the dialog title.
|
// For sample sake, let's react to this event by changing the dialog title.
|
||||||
HRESULT CDialogEventHandler::OnItemSelected(IFileDialogCustomize *pfdc, DWORD dwIDCtl, DWORD dwIDItem)
|
HRESULT CDialogEventHandler::OnItemSelected(IFileDialogCustomize* pfdc, DWORD dwIDCtl, DWORD dwIDItem)
|
||||||
{
|
{
|
||||||
IFileDialog *pfd = NULL;
|
IFileDialog* pfd = NULL;
|
||||||
HRESULT hr = pfdc->QueryInterface(&pfd);
|
HRESULT hr = pfdc->QueryInterface(&pfd);
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
|
|
|
@ -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,32 +33,17 @@ 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; }
|
||||||
|
|
||||||
VSTVoiceEngine()
|
VSTVoiceEngine()
|
||||||
{
|
{
|
||||||
|
@ -112,7 +87,7 @@ struct VSTVoiceEngine : boo::BaseAudioVoiceEngine
|
||||||
|
|
||||||
void pumpAndMixVoices()
|
void pumpAndMixVoices()
|
||||||
{
|
{
|
||||||
for (size_t f=0 ; f<m_renderFrames ;)
|
for (size_t f = 0; f < m_renderFrames;)
|
||||||
{
|
{
|
||||||
if (m_curBufFrame == m_5msFrames)
|
if (m_curBufFrame == m_5msFrames)
|
||||||
{
|
{
|
||||||
|
@ -123,11 +98,11 @@ struct VSTVoiceEngine : boo::BaseAudioVoiceEngine
|
||||||
size_t remRenderFrames = std::min(m_renderFrames - f, m_5msFrames - m_curBufFrame);
|
size_t remRenderFrames = std::min(m_renderFrames - f, m_5msFrames - m_curBufFrame);
|
||||||
if (remRenderFrames)
|
if (remRenderFrames)
|
||||||
{
|
{
|
||||||
for (size_t i=0 ; i<2 ; ++i)
|
for (size_t i = 0; i < 2; ++i)
|
||||||
{
|
{
|
||||||
float* bufOut = m_outputData[i];
|
float* bufOut = m_outputData[i];
|
||||||
for (size_t lf=0 ; lf<remRenderFrames ; ++lf)
|
for (size_t lf = 0; lf < remRenderFrames; ++lf)
|
||||||
bufOut[f+lf] = m_interleavedBuf[(m_curBufFrame+lf)*2+i];
|
bufOut[f + lf] = m_interleavedBuf[(m_curBufFrame + lf) * 2 + i];
|
||||||
}
|
}
|
||||||
m_curBufFrame += remRenderFrames;
|
m_curBufFrame += remRenderFrames;
|
||||||
f += remRenderFrames;
|
f += remRenderFrames;
|
||||||
|
@ -135,18 +110,17 @@ struct VSTVoiceEngine : boo::BaseAudioVoiceEngine
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
double getCurrentSampleRate() const {return m_mixInfo.m_sampleRate;}
|
double getCurrentSampleRate() const { return m_mixInfo.m_sampleRate; }
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace amuse
|
namespace amuse
|
||||||
{
|
{
|
||||||
|
|
||||||
#define kBackendID CCONST ('a','m','u','s')
|
#define kBackendID CCONST('a', 'm', 'u', 's')
|
||||||
|
|
||||||
static logvisor::Module Log("amuse::AudioUnitBackend");
|
static logvisor::Module Log("amuse::AudioUnitBackend");
|
||||||
|
|
||||||
VSTBackend::VSTBackend(audioMasterCallback cb)
|
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)
|
||||||
{
|
{
|
||||||
|
@ -197,7 +165,7 @@ VstInt32 VSTBackend::processEvents(VstEvents* events)
|
||||||
|
|
||||||
if (engine.m_midiReceiver)
|
if (engine.m_midiReceiver)
|
||||||
{
|
{
|
||||||
for (VstInt32 i=0 ; i<events->numEvents ; ++i)
|
for (VstInt32 i = 0; i < events->numEvents; ++i)
|
||||||
{
|
{
|
||||||
VstMidiEvent* evt = reinterpret_cast<VstMidiEvent*>(events->events[i]);
|
VstMidiEvent* evt = reinterpret_cast<VstMidiEvent*>(events->events[i]);
|
||||||
if (evt->type == kVstMidiType)
|
if (evt->type == kVstMidiType)
|
||||||
|
@ -207,9 +175,9 @@ 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);
|
|
||||||
}
|
|
||||||
|
|
|
@ -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();
|
||||||
|
@ -58,9 +58,9 @@ public:
|
||||||
void setSampleRate(float sampleRate);
|
void setSampleRate(float sampleRate);
|
||||||
void setBlockSize(VstInt32 blockSize);
|
void setBlockSize(VstInt32 blockSize);
|
||||||
|
|
||||||
amuse::Engine& getAmuseEngine() {return *m_engine;}
|
amuse::Engine& getAmuseEngine() { return *m_engine; }
|
||||||
const std::wstring& getUserDir() const {return m_userDir;}
|
const std::wstring& getUserDir() const { return m_userDir; }
|
||||||
AudioGroupFilePresenter& getFilePresenter() {return m_filePresenter;}
|
AudioGroupFilePresenter& getFilePresenter() { return m_filePresenter; }
|
||||||
|
|
||||||
void loadGroupFile(int collectionIdx, int fileIdx);
|
void loadGroupFile(int collectionIdx, int fileIdx);
|
||||||
void setGroup(int groupIdx, bool immediate);
|
void setGroup(int groupIdx, bool immediate);
|
||||||
|
@ -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__
|
||||||
|
|
|
@ -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,15 +110,12 @@ 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);
|
||||||
|
|
||||||
SetTextColor(dc, RGB(255,255,255));
|
SetTextColor(dc, RGB(255, 255, 255));
|
||||||
SetBkMode(dc, TRANSPARENT);
|
SetBkMode(dc, TRANSPARENT);
|
||||||
SelectObject(dc, GetStockObject(ANSI_VAR_FONT));
|
SelectObject(dc, GetStockObject(ANSI_VAR_FONT));
|
||||||
rect.left += 6;
|
rect.left += 6;
|
||||||
|
@ -160,33 +148,22 @@ bool VSTEditor::open(void* ptr)
|
||||||
{
|
{
|
||||||
AEffEditor::open(ptr);
|
AEffEditor::open(ptr);
|
||||||
HWND hostView = HWND(ptr);
|
HWND hostView = HWND(ptr);
|
||||||
gGreyBorderBrush = CreateSolidBrush(RGB(100,100,100));
|
gGreyBorderBrush = CreateSolidBrush(RGB(100, 100, 100));
|
||||||
|
|
||||||
WNDCLASSW notifyCls =
|
WNDCLASSW notifyCls = {CS_HREDRAW | CS_VREDRAW,
|
||||||
{
|
WindowProc,
|
||||||
CS_HREDRAW | CS_VREDRAW,
|
0,
|
||||||
WindowProc,
|
8,
|
||||||
0,
|
HINSTANCE(hInstance),
|
||||||
8,
|
nullptr,
|
||||||
HINSTANCE(hInstance),
|
nullptr,
|
||||||
nullptr,
|
nullptr,
|
||||||
nullptr,
|
nullptr,
|
||||||
nullptr,
|
L"VSTNotify"};
|
||||||
nullptr,
|
|
||||||
L"VSTNotify"
|
|
||||||
};
|
|
||||||
RegisterClassW(¬ifyCls);
|
RegisterClassW(¬ifyCls);
|
||||||
|
|
||||||
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,18 +180,12 @@ 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,
|
TreeView_SetBkColor(m_collectionTree, RGB(64, 64, 64));
|
||||||
m_windowRect.bottom - m_windowRect.top - 26,
|
TreeView_SetTextColor(m_collectionTree, RGB(255, 255, 255));
|
||||||
m_rootView,
|
|
||||||
nullptr,
|
|
||||||
nullptr,
|
|
||||||
nullptr);
|
|
||||||
TreeView_SetBkColor(m_collectionTree, RGB(64,64,64));
|
|
||||||
TreeView_SetTextColor(m_collectionTree, RGB(255,255,255));
|
|
||||||
HTREEITEM rootItemA = TreeView_InsertItem(m_collectionTree, &treeItem);
|
HTREEITEM rootItemA = TreeView_InsertItem(m_collectionTree, &treeItem);
|
||||||
treeItem.item.pszText = L"Root B";
|
treeItem.item.pszText = L"Root B";
|
||||||
HTREEITEM rootItemB = TreeView_InsertItem(m_collectionTree, &treeItem);
|
HTREEITEM rootItemB = TreeView_InsertItem(m_collectionTree, &treeItem);
|
||||||
|
@ -231,113 +202,61 @@ 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, 199, m_windowRect.bottom - m_windowRect.top - 26, m_rootView, nullptr, nullptr, nullptr);
|
||||||
201, 25,
|
|
||||||
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));
|
||||||
SetWindowLongPtr(header, GWLP_WNDPROC, LONG_PTR(ColHeaderWindowProc));
|
SetWindowLongPtr(header, GWLP_WNDPROC, LONG_PTR(ColHeaderWindowProc));
|
||||||
ListView_SetBkColor(m_groupListView, RGB(64,64,64));
|
ListView_SetBkColor(m_groupListView, RGB(64, 64, 64));
|
||||||
ListView_SetTextBkColor(m_groupListView, CLR_NONE);
|
ListView_SetTextBkColor(m_groupListView, CLR_NONE);
|
||||||
ListView_SetTextColor(m_groupListView, RGB(255,255,255));
|
ListView_SetTextColor(m_groupListView, RGB(255, 255, 255));
|
||||||
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);
|
||||||
SetWindowLongPtrW(header, GWLP_USERDATA, LONG_PTR(column.pszText));
|
SetWindowLongPtrW(header, GWLP_USERDATA, LONG_PTR(column.pszText));
|
||||||
SetWindowLongPtr(header, GWLP_WNDPROC, LONG_PTR(ColHeaderWindowProc));
|
SetWindowLongPtr(header, GWLP_WNDPROC, LONG_PTR(ColHeaderWindowProc));
|
||||||
ListView_SetBkColor(m_pageListView, RGB(64,64,64));
|
ListView_SetBkColor(m_pageListView, RGB(64, 64, 64));
|
||||||
ListView_SetTextBkColor(m_pageListView, CLR_NONE);
|
ListView_SetTextBkColor(m_pageListView, CLR_NONE);
|
||||||
ListView_SetTextColor(m_pageListView, RGB(255,255,255));
|
ListView_SetTextColor(m_pageListView, RGB(255, 255, 255));
|
||||||
ListView_InsertColumn(m_pageListView, 0, &column);
|
ListView_InsertColumn(m_pageListView, 0, &column);
|
||||||
ShowWindow(m_pageListView, SW_SHOW);
|
ShowWindow(m_pageListView, SW_SHOW);
|
||||||
|
|
||||||
|
@ -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); }
|
||||||
}
|
}
|
||||||
|
|
|
@ -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__
|
||||||
|
|
|
@ -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]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,9 +16,10 @@
|
||||||
static logvisor::Module Log("amuseplay");
|
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);
|
||||||
|
@ -36,33 +37,33 @@ static inline void SNPrintf(boo::SystemChar* str, size_t maxlen, const boo::Syst
|
||||||
|
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
|
||||||
static void abortHandler( int signum )
|
static void abortHandler(int signum)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
void * stack[ 100 ];
|
void* stack[100];
|
||||||
unsigned short frames;
|
unsigned short frames;
|
||||||
SYMBOL_INFO * symbol;
|
SYMBOL_INFO* symbol;
|
||||||
HANDLE process;
|
HANDLE process;
|
||||||
|
|
||||||
process = GetCurrentProcess();
|
process = GetCurrentProcess();
|
||||||
SymInitialize( process, NULL, TRUE );
|
SymInitialize(process, NULL, TRUE);
|
||||||
frames = CaptureStackBackTrace( 0, 100, stack, NULL );
|
frames = CaptureStackBackTrace(0, 100, stack, NULL);
|
||||||
symbol = ( SYMBOL_INFO * )calloc( sizeof( SYMBOL_INFO ) + 256 * sizeof( char ), 1 );
|
symbol = (SYMBOL_INFO*)calloc(sizeof(SYMBOL_INFO) + 256 * sizeof(char), 1);
|
||||||
symbol->MaxNameLen = 255;
|
symbol->MaxNameLen = 255;
|
||||||
symbol->SizeOfStruct = sizeof( SYMBOL_INFO );
|
symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
|
||||||
|
|
||||||
for( i = 0; i < frames; i++ )
|
for (i = 0; i < frames; i++)
|
||||||
{
|
{
|
||||||
SymFromAddr( process, ( DWORD64 )( stack[ i ] ), 0, symbol );
|
SymFromAddr(process, (DWORD64)(stack[i]), 0, symbol);
|
||||||
|
|
||||||
printf( "%i: %s - 0x%0llX", frames - i - 1, symbol->Name, symbol->Address );
|
printf("%i: %s - 0x%0llX", frames - i - 1, symbol->Name, symbol->Address);
|
||||||
|
|
||||||
DWORD dwDisplacement;
|
DWORD dwDisplacement;
|
||||||
IMAGEHLP_LINE64 line;
|
IMAGEHLP_LINE64 line;
|
||||||
SymSetOptions(SYMOPT_LOAD_LINES);
|
SymSetOptions(SYMOPT_LOAD_LINES);
|
||||||
|
|
||||||
line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
|
line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
|
||||||
if (SymGetLineFromAddr64(process, ( DWORD64 )( stack[ i ] ), &dwDisplacement, &line))
|
if (SymGetLineFromAddr64(process, (DWORD64)(stack[i]), &dwDisplacement, &line))
|
||||||
{
|
{
|
||||||
// SymGetLineFromAddr64 returned success
|
// SymGetLineFromAddr64 returned success
|
||||||
printf(" LINE %d\n", line.LineNumber);
|
printf(" LINE %d\n", line.LineNumber);
|
||||||
|
@ -73,12 +74,12 @@ static void abortHandler( int signum )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
free( symbol );
|
free(symbol);
|
||||||
|
|
||||||
// If you caught one of the above signals, it is likely you just
|
// If you caught one of the above signals, it is likely you just
|
||||||
// want to quit your program right now.
|
// want to quit your program right now.
|
||||||
system("PAUSE");
|
system("PAUSE");
|
||||||
exit( signum );
|
exit(signum);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -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,19 +179,20 @@ struct AppCallback : boo::IApplicationCallback
|
||||||
|
|
||||||
void SongLoop(const amuse::SongGroupIndex& index)
|
void SongLoop(const amuse::SongGroupIndex& index)
|
||||||
{
|
{
|
||||||
printf("░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░\n"
|
printf(
|
||||||
"░░░ ████ ████ ┃ ████ ████ ████ ┃ ████ ████ ░░░\n"
|
"░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░\n"
|
||||||
"░░░ ████ ████ ┃ ████ ████ ████ ┃ ████ ████ ░░░\n"
|
"░░░ ████ ████ ┃ ████ ████ ████ ┃ ████ ████ ░░░\n"
|
||||||
"░░░ ▌W▐█ ▌E▐█ ┃ ▌T▐█ ▌Y▐█ ▌U▐█ ┃ ▌O▐█ ▌P▐█ ░░░\n"
|
"░░░ ████ ████ ┃ ████ ████ ████ ┃ ████ ████ ░░░\n"
|
||||||
"░░░ │ │ ┃ │ │ │ ┃ │ │ ░░░\n"
|
"░░░ ▌W▐█ ▌E▐█ ┃ ▌T▐█ ▌Y▐█ ▌U▐█ ┃ ▌O▐█ ▌P▐█ ░░░\n"
|
||||||
"░░░ A │ S │ D ┃ F │ G │ H │ J ┃ K │ L │ ; ░░░\n"
|
"░░░ │ │ ┃ │ │ │ ┃ │ │ ░░░\n"
|
||||||
"░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░\n"
|
"░░░ A │ S │ D ┃ F │ G │ H │ J ┃ K │ L │ ; ░░░\n"
|
||||||
"<left/right>: cycle MIDI setup, <up/down>: volume, <space>: PANIC\n"
|
"░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░\n"
|
||||||
"<tab>: sustain pedal, <window-Y>: pitch wheel, <window-X>: mod wheel\n"
|
"<left/right>: cycle MIDI setup, <up/down>: volume, <space>: PANIC\n"
|
||||||
"<Z/X>: octave, <C/V>: velocity, <B/N>: channel, <,/.>: program, <Q>: quit\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");
|
||||||
|
|
||||||
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,12 +629,10 @@ 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);
|
||||||
{
|
return true;
|
||||||
tex = ctx.newRenderTexture(100, 100, false, false);
|
});
|
||||||
return true;
|
|
||||||
});
|
|
||||||
boo::IGraphicsCommandQueue* q = m_win->getCommandQueue();
|
boo::IGraphicsCommandQueue* q = m_win->getCommandQueue();
|
||||||
q->setRenderTarget(tex);
|
q->setRenderTarget(tex);
|
||||||
q->clearTarget();
|
q->clearTarget();
|
||||||
|
@ -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)
|
||||||
|
@ -667,10 +678,10 @@ struct AppCallback : boo::IApplicationCallback
|
||||||
amuse::AudioGroupProject& proj = m_projs.back();
|
amuse::AudioGroupProject& proj = m_projs.back();
|
||||||
totalGroups += proj.sfxGroups().size() + proj.songGroups().size();
|
totalGroups += proj.sfxGroups().size() + proj.songGroups().size();
|
||||||
|
|
||||||
for (auto it = proj.songGroups().begin() ; it != proj.songGroups().end() ; ++it)
|
for (auto it = proj.songGroups().begin(); it != proj.songGroups().end(); ++it)
|
||||||
allSongGroups[it->first] = std::make_pair(&grp, &it->second);
|
allSongGroups[it->first] = std::make_pair(&grp, &it->second);
|
||||||
|
|
||||||
for (auto it = proj.sfxGroups().begin() ; it != proj.sfxGroups().end() ; ++it)
|
for (auto it = proj.sfxGroups().begin(); it != proj.sfxGroups().end(); ++it)
|
||||||
allSFXGroups[it->first] = std::make_pair(&grp, &it->second);
|
allSFXGroups[it->first] = std::make_pair(&grp, &it->second);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -1038,10 +1042,10 @@ int main(int argc, const boo::SystemChar** argv)
|
||||||
#if _WIN32
|
#if _WIN32
|
||||||
int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE, LPWSTR lpCmdLine, int)
|
int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE, LPWSTR lpCmdLine, int)
|
||||||
{
|
{
|
||||||
signal( SIGABRT, abortHandler );
|
signal(SIGABRT, abortHandler);
|
||||||
signal( SIGSEGV, abortHandler );
|
signal(SIGSEGV, abortHandler);
|
||||||
signal( SIGILL, abortHandler );
|
signal(SIGILL, abortHandler);
|
||||||
signal( SIGFPE, abortHandler );
|
signal(SIGFPE, abortHandler);
|
||||||
|
|
||||||
int argc = 0;
|
int argc = 0;
|
||||||
const boo::SystemChar** argv = (const wchar_t**)(CommandLineToArgvW(lpCmdLine, &argc));
|
const boo::SystemChar** argv = (const wchar_t**)(CommandLineToArgvW(lpCmdLine, &argc));
|
||||||
|
@ -1049,11 +1053,11 @@ int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE, LPWSTR lpCmdLine, int)
|
||||||
GetModuleFileNameW(nullptr, selfPath, 1024);
|
GetModuleFileNameW(nullptr, selfPath, 1024);
|
||||||
static const boo::SystemChar* booArgv[32] = {};
|
static const boo::SystemChar* booArgv[32] = {};
|
||||||
booArgv[0] = selfPath;
|
booArgv[0] = selfPath;
|
||||||
for (int i=0 ; i<argc ; ++i)
|
for (int i = 0; i < argc; ++i)
|
||||||
booArgv[i+1] = argv[i];
|
booArgv[i + 1] = argv[i];
|
||||||
|
|
||||||
logvisor::CreateWin32Console();
|
logvisor::CreateWin32Console();
|
||||||
SetConsoleOutputCP(65001);
|
SetConsoleOutputCP(65001);
|
||||||
return wmain(argc+1, booArgv);
|
return wmain(argc + 1, booArgv);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -18,9 +18,10 @@
|
||||||
static logvisor::Module Log("amuserender");
|
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);
|
||||||
|
@ -38,33 +39,33 @@ static inline void SNPrintf(boo::SystemChar* str, size_t maxlen, const boo::Syst
|
||||||
|
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
|
||||||
static void abortHandler( int signum )
|
static void abortHandler(int signum)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
void * stack[ 100 ];
|
void* stack[100];
|
||||||
unsigned short frames;
|
unsigned short frames;
|
||||||
SYMBOL_INFO * symbol;
|
SYMBOL_INFO* symbol;
|
||||||
HANDLE process;
|
HANDLE process;
|
||||||
|
|
||||||
process = GetCurrentProcess();
|
process = GetCurrentProcess();
|
||||||
SymInitialize( process, NULL, TRUE );
|
SymInitialize(process, NULL, TRUE);
|
||||||
frames = CaptureStackBackTrace( 0, 100, stack, NULL );
|
frames = CaptureStackBackTrace(0, 100, stack, NULL);
|
||||||
symbol = ( SYMBOL_INFO * )calloc( sizeof( SYMBOL_INFO ) + 256 * sizeof( char ), 1 );
|
symbol = (SYMBOL_INFO*)calloc(sizeof(SYMBOL_INFO) + 256 * sizeof(char), 1);
|
||||||
symbol->MaxNameLen = 255;
|
symbol->MaxNameLen = 255;
|
||||||
symbol->SizeOfStruct = sizeof( SYMBOL_INFO );
|
symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
|
||||||
|
|
||||||
for( i = 0; i < frames; i++ )
|
for (i = 0; i < frames; i++)
|
||||||
{
|
{
|
||||||
SymFromAddr( process, ( DWORD64 )( stack[ i ] ), 0, symbol );
|
SymFromAddr(process, (DWORD64)(stack[i]), 0, symbol);
|
||||||
|
|
||||||
printf( "%i: %s - 0x%0llX", frames - i - 1, symbol->Name, symbol->Address );
|
printf("%i: %s - 0x%0llX", frames - i - 1, symbol->Name, symbol->Address);
|
||||||
|
|
||||||
DWORD dwDisplacement;
|
DWORD dwDisplacement;
|
||||||
IMAGEHLP_LINE64 line;
|
IMAGEHLP_LINE64 line;
|
||||||
SymSetOptions(SYMOPT_LOAD_LINES);
|
SymSetOptions(SYMOPT_LOAD_LINES);
|
||||||
|
|
||||||
line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
|
line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
|
||||||
if (SymGetLineFromAddr64(process, ( DWORD64 )( stack[ i ] ), &dwDisplacement, &line))
|
if (SymGetLineFromAddr64(process, (DWORD64)(stack[i]), &dwDisplacement, &line))
|
||||||
{
|
{
|
||||||
// SymGetLineFromAddr64 returned success
|
// SymGetLineFromAddr64 returned success
|
||||||
printf(" LINE %d\n", line.LineNumber);
|
printf(" LINE %d\n", line.LineNumber);
|
||||||
|
@ -75,21 +76,18 @@ static void abortHandler( int signum )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
free( symbol );
|
free(symbol);
|
||||||
|
|
||||||
// If you caught one of the above signals, it is likely you just
|
// If you caught one of the above signals, it is likely you just
|
||||||
// want to quit your program right now.
|
// want to quit your program right now.
|
||||||
system("PAUSE");
|
system("PAUSE");
|
||||||
exit( signum );
|
exit(signum);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* 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)
|
||||||
|
@ -102,16 +100,16 @@ int main(int argc, const boo::SystemChar** argv)
|
||||||
std::vector<boo::SystemString> m_args;
|
std::vector<boo::SystemString> m_args;
|
||||||
m_args.reserve(argc);
|
m_args.reserve(argc);
|
||||||
double rate = 32000.0;
|
double rate = 32000.0;
|
||||||
for (int i=1 ; i<argc ; ++i)
|
for (int i = 1; i < argc; ++i)
|
||||||
{
|
{
|
||||||
#if _WIN32
|
#if _WIN32
|
||||||
if (!wcsncmp(argv[i], L"-r", 2))
|
if (!wcsncmp(argv[i], L"-r", 2))
|
||||||
{
|
{
|
||||||
if (argv[i][2])
|
if (argv[i][2])
|
||||||
rate = wcstod(&argv[i][2], nullptr);
|
rate = wcstod(&argv[i][2], nullptr);
|
||||||
else if (argc > (i+1))
|
else if (argc > (i + 1))
|
||||||
{
|
{
|
||||||
rate = wcstod(argv[i+1], nullptr);
|
rate = wcstod(argv[i + 1], nullptr);
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -122,9 +120,9 @@ int main(int argc, const boo::SystemChar** argv)
|
||||||
{
|
{
|
||||||
if (argv[i][2])
|
if (argv[i][2])
|
||||||
rate = strtod(&argv[i][2], nullptr);
|
rate = strtod(&argv[i][2], nullptr);
|
||||||
else if (argc > (i+1))
|
else if (argc > (i + 1))
|
||||||
{
|
{
|
||||||
rate = strtod(argv[i+1], nullptr);
|
rate = strtod(argv[i + 1], nullptr);
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
@ -175,10 +177,10 @@ int main(int argc, const boo::SystemChar** argv)
|
||||||
amuse::AudioGroupProject& proj = m_projs.back();
|
amuse::AudioGroupProject& proj = m_projs.back();
|
||||||
totalGroups += proj.sfxGroups().size() + proj.songGroups().size();
|
totalGroups += proj.sfxGroups().size() + proj.songGroups().size();
|
||||||
|
|
||||||
for (auto it = proj.songGroups().begin() ; it != proj.songGroups().end() ; ++it)
|
for (auto it = proj.songGroups().begin(); it != proj.songGroups().end(); ++it)
|
||||||
allSongGroups[it->first] = std::make_pair(&grp, &it->second);
|
allSongGroups[it->first] = std::make_pair(&grp, &it->second);
|
||||||
|
|
||||||
for (auto it = proj.sfxGroups().begin() ; it != proj.sfxGroups().end() ; ++it)
|
for (auto it = proj.sfxGroups().begin(); it != proj.sfxGroups().end(); ++it)
|
||||||
allSFXGroups[it->first] = std::make_pair(&grp, &it->second);
|
allSFXGroups[it->first] = std::make_pair(&grp, &it->second);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -476,10 +475,10 @@ int main(int argc, const boo::SystemChar** argv)
|
||||||
#if _WIN32
|
#if _WIN32
|
||||||
int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE, LPWSTR lpCmdLine, int)
|
int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE, LPWSTR lpCmdLine, int)
|
||||||
{
|
{
|
||||||
signal( SIGABRT, abortHandler );
|
signal(SIGABRT, abortHandler);
|
||||||
signal( SIGSEGV, abortHandler );
|
signal(SIGSEGV, abortHandler);
|
||||||
signal( SIGILL, abortHandler );
|
signal(SIGILL, abortHandler);
|
||||||
signal( SIGFPE, abortHandler );
|
signal(SIGFPE, abortHandler);
|
||||||
|
|
||||||
int argc = 0;
|
int argc = 0;
|
||||||
const boo::SystemChar** argv = (const wchar_t**)(CommandLineToArgvW(lpCmdLine, &argc));
|
const boo::SystemChar** argv = (const wchar_t**)(CommandLineToArgvW(lpCmdLine, &argc));
|
||||||
|
@ -487,11 +486,11 @@ int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE, LPWSTR lpCmdLine, int)
|
||||||
GetModuleFileNameW(nullptr, selfPath, 1024);
|
GetModuleFileNameW(nullptr, selfPath, 1024);
|
||||||
static const boo::SystemChar* booArgv[32] = {};
|
static const boo::SystemChar* booArgv[32] = {};
|
||||||
booArgv[0] = selfPath;
|
booArgv[0] = selfPath;
|
||||||
for (int i=0 ; i<argc ; ++i)
|
for (int i = 0; i < argc; ++i)
|
||||||
booArgv[i+1] = argv[i];
|
booArgv[i + 1] = argv[i];
|
||||||
|
|
||||||
logvisor::CreateWin32Console();
|
logvisor::CreateWin32Console();
|
||||||
SetConsoleOutputCP(65001);
|
SetConsoleOutputCP(65001);
|
||||||
return wmain(argc+1, booArgv);
|
return wmain(argc + 1, booArgv);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -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,20 +20,20 @@ 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);
|
||||||
AudioGroup(const AudioGroupData& data, bool absOffs, N64DataTag);
|
AudioGroup(const AudioGroupData& data, bool absOffs, N64DataTag);
|
||||||
AudioGroup(const AudioGroupData& data, bool absOffs, PCDataTag);
|
AudioGroup(const AudioGroupData& data, bool absOffs, PCDataTag);
|
||||||
|
|
||||||
const Sample* getSample(int sfxId) const;
|
const Sample* getSample(int sfxId) const;
|
||||||
const unsigned char* getSampleData(uint32_t offset) const;
|
const unsigned char* getSampleData(uint32_t offset) const;
|
||||||
const AudioGroupProject& getProj() const {return m_proj;}
|
const AudioGroupProject& getProj() const { return m_proj; }
|
||||||
const AudioGroupPool& getPool() const {return m_pool;}
|
const AudioGroupPool& getPool() const { return m_pool; }
|
||||||
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__
|
||||||
|
|
|
@ -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,86 +24,103 @@ 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)
|
||||||
public:
|
, m_fmt(fmt)
|
||||||
AudioGroupData(unsigned char* proj, size_t projSz,
|
, m_absOffs(absOffs)
|
||||||
unsigned char* pool, size_t poolSz,
|
|
||||||
unsigned char* sdir, size_t sdirSz,
|
|
||||||
unsigned char* samp, size_t sampSz, GCNDataTag)
|
|
||||||
: 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::GCN), m_absOffs(true) {}
|
|
||||||
AudioGroupData(unsigned char* proj, size_t projSz,
|
|
||||||
unsigned char* pool, size_t poolSz,
|
|
||||||
unsigned char* sdir, size_t sdirSz,
|
|
||||||
unsigned char* samp, size_t sampSz, bool absOffs, N64DataTag)
|
|
||||||
: 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::N64), 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* getPool() const {return m_pool;}
|
|
||||||
const unsigned char* getSdir() const {return m_sdir;}
|
|
||||||
const unsigned char* getSamp() const {return m_samp;}
|
|
||||||
|
|
||||||
unsigned char* getProj() {return m_proj;}
|
|
||||||
unsigned char* getPool() {return m_pool;}
|
|
||||||
unsigned char* getSdir() {return m_sdir;}
|
|
||||||
unsigned char* getSamp() {return m_samp;}
|
|
||||||
|
|
||||||
size_t getProjSize() const {return m_projSz;}
|
|
||||||
size_t getPoolSize() const {return m_poolSz;}
|
|
||||||
size_t getSdirSize() const {return m_sdirSz;}
|
|
||||||
size_t getSampSize() const {return m_sampSz;}
|
|
||||||
|
|
||||||
operator bool() const
|
|
||||||
{
|
{
|
||||||
return m_proj != nullptr && m_pool != nullptr && m_sdir != nullptr && m_samp != nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DataFormat getDataFormat() const {return m_fmt;}
|
public:
|
||||||
bool getAbsoluteProjOffsets() const {return m_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, GCNDataTag)
|
||||||
|
: 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::GCN)
|
||||||
|
, m_absOffs(true)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
AudioGroupData(unsigned char* proj, size_t projSz, unsigned char* pool, size_t poolSz, unsigned char* sdir,
|
||||||
|
size_t sdirSz, unsigned char* samp, size_t sampSz, bool absOffs, N64DataTag)
|
||||||
|
: 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::N64)
|
||||||
|
, 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* getPool() const { return m_pool; }
|
||||||
|
const unsigned char* getSdir() const { return m_sdir; }
|
||||||
|
const unsigned char* getSamp() const { return m_samp; }
|
||||||
|
|
||||||
|
unsigned char* getProj() { return m_proj; }
|
||||||
|
unsigned char* getPool() { return m_pool; }
|
||||||
|
unsigned char* getSdir() { return m_sdir; }
|
||||||
|
unsigned char* getSamp() { return m_samp; }
|
||||||
|
|
||||||
|
size_t getProjSize() const { return m_projSz; }
|
||||||
|
size_t getPoolSize() const { return m_poolSz; }
|
||||||
|
size_t getSdirSize() const { return m_sdirSz; }
|
||||||
|
size_t getSampSize() const { return m_sampSz; }
|
||||||
|
|
||||||
|
operator bool() const { return m_proj != nullptr && m_pool != nullptr && m_sdir != nullptr && m_samp != nullptr; }
|
||||||
|
|
||||||
|
DataFormat getDataFormat() const { return m_fmt; }
|
||||||
|
bool getAbsoluteProjOffsets() const { return m_absOffs; }
|
||||||
};
|
};
|
||||||
|
|
||||||
/** A buffer-owning version of AudioGroupData */
|
/** A buffer-owning version of AudioGroupData */
|
||||||
class IntrusiveAudioGroupData : public AudioGroupData
|
class IntrusiveAudioGroupData : public AudioGroupData
|
||||||
{
|
{
|
||||||
bool m_owns = true;
|
bool m_owns = true;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using AudioGroupData::AudioGroupData;
|
using AudioGroupData::AudioGroupData;
|
||||||
~IntrusiveAudioGroupData();
|
~IntrusiveAudioGroupData();
|
||||||
|
|
||||||
IntrusiveAudioGroupData(const IntrusiveAudioGroupData&)=delete;
|
IntrusiveAudioGroupData(const IntrusiveAudioGroupData&) = delete;
|
||||||
IntrusiveAudioGroupData& operator=(const IntrusiveAudioGroupData&)=delete;
|
IntrusiveAudioGroupData& operator=(const IntrusiveAudioGroupData&) = delete;
|
||||||
|
|
||||||
IntrusiveAudioGroupData(IntrusiveAudioGroupData&& other);
|
IntrusiveAudioGroupData(IntrusiveAudioGroupData&& other);
|
||||||
IntrusiveAudioGroupData& operator=(IntrusiveAudioGroupData&& other);
|
IntrusiveAudioGroupData& operator=(IntrusiveAudioGroupData&& other);
|
||||||
|
|
||||||
void dangleOwnership() {m_owns = false;}
|
void dangleOwnership() { m_owns = false; }
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // __AMUSE_AUDIOGROUPDATA_HPP__
|
#endif // __AMUSE_AUDIOGROUPDATA_HPP__
|
||||||
|
|
|
@ -22,35 +22,38 @@ static inline double TimeCentsToSeconds(int32_t tc)
|
||||||
/** Defines phase-based volume curve for macro volume control */
|
/** Defines phase-based volume curve for macro volume control */
|
||||||
struct ADSR
|
struct ADSR
|
||||||
{
|
{
|
||||||
uint8_t attackFine; /* 0-255ms */
|
uint8_t attackFine; /* 0-255ms */
|
||||||
uint8_t attackCoarse; /* 0-65280ms */
|
uint8_t attackCoarse; /* 0-65280ms */
|
||||||
uint8_t decayFine; /* 0-255ms */
|
uint8_t decayFine; /* 0-255ms */
|
||||||
uint8_t decayCoarse; /* 0-65280ms */
|
uint8_t decayCoarse; /* 0-65280ms */
|
||||||
uint8_t sustainFine; /* multiply by 0.0244 for percentage */
|
uint8_t sustainFine; /* multiply by 0.0244 for percentage */
|
||||||
uint8_t sustainCoarse; /* multiply by 6.25 for percentage */
|
uint8_t sustainCoarse; /* multiply by 6.25 for percentage */
|
||||||
uint8_t releaseFine; /* 0-255ms */
|
uint8_t releaseFine; /* 0-255ms */
|
||||||
uint8_t releaseCoarse; /* 0-65280ms */
|
uint8_t releaseCoarse; /* 0-65280ms */
|
||||||
|
|
||||||
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
|
||||||
double getRelease() const {return (releaseCoarse * 255 + releaseFine) / 1000.0;}
|
{
|
||||||
|
return decayCoarse == 128 ? 1.0 : ((sustainCoarse * 6.25 + sustainFine * 0.0244) / 100.0);
|
||||||
|
}
|
||||||
|
double getRelease() const { return (releaseCoarse * 255 + releaseFine) / 1000.0; }
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Defines phase-based volume curve for macro volume control (modified DLS standard) */
|
/** Defines phase-based volume curve for macro volume control (modified DLS standard) */
|
||||||
struct ADSRDLS
|
struct ADSRDLS
|
||||||
{
|
{
|
||||||
uint32_t attack; /* 16.16 Time-cents */
|
uint32_t attack; /* 16.16 Time-cents */
|
||||||
uint32_t decay; /* 16.16 Time-cents */
|
uint32_t decay; /* 16.16 Time-cents */
|
||||||
uint16_t sustain; /* 0x1000 == 100% */
|
uint16_t sustain; /* 0x1000 == 100% */
|
||||||
uint16_t release; /* milliseconds */
|
uint16_t release; /* milliseconds */
|
||||||
uint32_t velToAttack; /* 16.16, 1000.0 == 100%; attack = <attack> + (vel/128) * <velToAttack> */
|
uint32_t velToAttack; /* 16.16, 1000.0 == 100%; attack = <attack> + (vel/128) * <velToAttack> */
|
||||||
uint32_t keyToDecay; /* 16.16, 1000.0 == 100%; decay = <decay> + (note/128) * <keyToDecay> */
|
uint32_t keyToDecay; /* 16.16, 1000.0 == 100%; decay = <decay> + (note/128) * <keyToDecay> */
|
||||||
|
|
||||||
double getAttack() const {return TimeCentsToSeconds(attack);}
|
double getAttack() const { return TimeCentsToSeconds(attack); }
|
||||||
double getDecay() const {return TimeCentsToSeconds(decay);}
|
double getDecay() const { return TimeCentsToSeconds(decay); }
|
||||||
double getSustain() const {return sustain / double(0x1000);}
|
double getSustain() const { return sustain / double(0x1000); }
|
||||||
double getRelease() const {return release / double(1000);}
|
double getRelease() const { return release / double(1000); }
|
||||||
double getVelToAttack(int8_t vel) const
|
double getVelToAttack(int8_t vel) const
|
||||||
{
|
{
|
||||||
if (velToAttack == 0x80000000)
|
if (velToAttack == 0x80000000)
|
||||||
|
@ -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__
|
||||||
|
|
|
@ -88,10 +88,9 @@ public:
|
||||||
const SongGroupIndex* getSongGroupIndex(int groupId) const;
|
const SongGroupIndex* getSongGroupIndex(int groupId) const;
|
||||||
const SFXGroupIndex* getSFXGroupIndex(int groupId) const;
|
const SFXGroupIndex* getSFXGroupIndex(int groupId) const;
|
||||||
|
|
||||||
const std::unordered_map<int, SongGroupIndex>& songGroups() const {return m_songGroups;}
|
const std::unordered_map<int, SongGroupIndex>& songGroups() const { return m_songGroups; }
|
||||||
const std::unordered_map<int, SFXGroupIndex>& sfxGroups() const {return m_sfxGroups;}
|
const std::unordered_map<int, SFXGroupIndex>& sfxGroups() const { return m_sfxGroups; }
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // __AMUSE_AUDIOGROUPPROJECT_HPP__
|
#endif // __AMUSE_AUDIOGROUPPROJECT_HPP__
|
||||||
|
|
|
@ -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__
|
||||||
|
|
|
@ -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__
|
||||||
|
|
|
@ -26,30 +26,27 @@ namespace amuse
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
using SystemString = std::wstring;
|
using SystemString = std::wstring;
|
||||||
using SystemChar = wchar_t;
|
using SystemChar = wchar_t;
|
||||||
# ifndef _S
|
#ifndef _S
|
||||||
# define _S(val) L ## val
|
#define _S(val) L##val
|
||||||
# endif
|
#endif
|
||||||
typedef struct _stat Sstat;
|
typedef struct _stat Sstat;
|
||||||
static inline int Mkdir(const wchar_t* path, int) {return _wmkdir(path);}
|
static inline int Mkdir(const wchar_t* path, int) { return _wmkdir(path); }
|
||||||
static inline int Stat(const wchar_t* path, Sstat* statout) {return _wstat(path, statout);}
|
static inline int Stat(const wchar_t* path, Sstat* statout) { return _wstat(path, statout); }
|
||||||
#else
|
#else
|
||||||
using SystemString = std::string;
|
using SystemString = std::string;
|
||||||
using SystemChar = char;
|
using SystemChar = char;
|
||||||
# ifndef _S
|
#ifndef _S
|
||||||
# define _S(val) val
|
#define _S(val) val
|
||||||
# endif
|
#endif
|
||||||
typedef struct stat Sstat;
|
typedef struct stat Sstat;
|
||||||
static inline int Mkdir(const char* path, mode_t mode) {return mkdir(path, mode);}
|
static inline int Mkdir(const char* path, mode_t mode) { return mkdir(path, mode); }
|
||||||
static inline int Stat(const char* path, Sstat* statout) {return stat(path, statout);}
|
static inline int Stat(const char* path, Sstat* statout) { return stat(path, statout); }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#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)
|
||||||
|
@ -98,9 +101,10 @@ inline float ClampFull<float>(float in)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#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);
|
||||||
|
@ -113,9 +117,10 @@ 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,24 +225,20 @@ 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
|
||||||
}
|
}
|
||||||
|
|
||||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||||
static inline int16_t SBig(int16_t val) {return bswap16(val);}
|
static inline int16_t SBig(int16_t val) { return bswap16(val); }
|
||||||
static inline uint16_t SBig(uint16_t val) {return bswap16(val);}
|
static inline uint16_t SBig(uint16_t val) { return bswap16(val); }
|
||||||
static inline int32_t SBig(int32_t val) {return bswap32(val);}
|
static inline int32_t SBig(int32_t val) { return bswap32(val); }
|
||||||
static inline uint32_t SBig(uint32_t val) {return bswap32(val);}
|
static inline uint32_t SBig(uint32_t val) { return bswap32(val); }
|
||||||
static inline int64_t SBig(int64_t val) {return bswap64(val);}
|
static inline int64_t SBig(int64_t val) { return bswap64(val); }
|
||||||
static inline uint64_t SBig(uint64_t val) {return bswap64(val);}
|
static inline uint64_t SBig(uint64_t val) { return bswap64(val); }
|
||||||
static inline float SBig(float val)
|
static inline float SBig(float val)
|
||||||
{
|
{
|
||||||
int32_t ival = bswap32(*((int32_t*)(&val)));
|
int32_t ival = bswap32(*((int32_t*)(&val)));
|
||||||
|
@ -249,28 +250,27 @@ 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; }
|
||||||
static inline uint16_t SLittle(uint16_t val) {return val;}
|
static inline uint16_t SLittle(uint16_t val) { return val; }
|
||||||
static inline int32_t SLittle(int32_t val) {return val;}
|
static inline int32_t SLittle(int32_t val) { return val; }
|
||||||
static inline uint32_t SLittle(uint32_t val) {return val;}
|
static inline uint32_t SLittle(uint32_t val) { return val; }
|
||||||
static inline int64_t SLittle(int64_t val) {return val;}
|
static inline int64_t SLittle(int64_t val) { return val; }
|
||||||
static inline uint64_t SLittle(uint64_t val) {return val;}
|
static inline uint64_t SLittle(uint64_t val) { return val; }
|
||||||
static inline float SLittle(float val) {return val;}
|
static inline float SLittle(float val) { return val; }
|
||||||
static inline double SLittle(double val) {return val;}
|
static inline double SLittle(double val) { return val; }
|
||||||
#ifndef SLITTLE
|
#ifndef SLITTLE
|
||||||
#define SLITTLE(q) (q)
|
#define SLITTLE(q) (q)
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
static inline int16_t SLittle(int16_t val) {return bswap16(val);}
|
static inline int16_t SLittle(int16_t val) { return bswap16(val); }
|
||||||
static inline uint16_t SLittle(uint16_t val) {return bswap16(val);}
|
static inline uint16_t SLittle(uint16_t val) { return bswap16(val); }
|
||||||
static inline int32_t SLittle(int32_t val) {return bswap32(val);}
|
static inline int32_t SLittle(int32_t val) { return bswap32(val); }
|
||||||
static inline uint32_t SLittle(uint32_t val) {return bswap32(val);}
|
static inline uint32_t SLittle(uint32_t val) { return bswap32(val); }
|
||||||
static inline int64_t SLittle(int64_t val) {return bswap64(val);}
|
static inline int64_t SLittle(int64_t val) { return bswap64(val); }
|
||||||
static inline uint64_t SLittle(uint64_t val) {return bswap64(val);}
|
static inline uint64_t SLittle(uint64_t val) { return bswap64(val); }
|
||||||
static inline float SLittle(float val)
|
static inline float SLittle(float val)
|
||||||
{
|
{
|
||||||
int32_t ival = bswap32(*((int32_t*)(&val)));
|
int32_t ival = bswap32(*((int32_t*)(&val)));
|
||||||
|
@ -282,18 +282,17 @@ 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; }
|
||||||
static inline uint16_t SBig(uint16_t val) {return val;}
|
static inline uint16_t SBig(uint16_t val) { return val; }
|
||||||
static inline int32_t SBig(int32_t val) {return val;}
|
static inline int32_t SBig(int32_t val) { return val; }
|
||||||
static inline uint32_t SBig(uint32_t val) {return val;}
|
static inline uint32_t SBig(uint32_t val) { return val; }
|
||||||
static inline int64_t SBig(int64_t val) {return val;}
|
static inline int64_t SBig(int64_t val) { return val; }
|
||||||
static inline uint64_t SBig(uint64_t val) {return val;}
|
static inline uint64_t SBig(uint64_t val) { return val; }
|
||||||
static inline float SBig(float val) {return val;}
|
static inline float SBig(float val) { return val; }
|
||||||
static inline double SBig(double val) {return val;}
|
static inline double SBig(double val) { return val; }
|
||||||
#ifndef SBIG
|
#ifndef SBIG
|
||||||
#define SBIG(q) (q)
|
#define SBIG(q) (q)
|
||||||
#endif
|
#endif
|
||||||
|
@ -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__
|
||||||
|
|
|
@ -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__
|
||||||
|
|
|
@ -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__
|
||||||
|
|
|
@ -12,16 +12,15 @@ class EffectBaseTypeless
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~EffectBaseTypeless() = default;
|
virtual ~EffectBaseTypeless() = default;
|
||||||
virtual void resetOutputSampleRate(double sampleRate)=0;
|
virtual void resetOutputSampleRate(double sampleRate) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class EffectBase : public EffectBaseTypeless
|
class EffectBase : public EffectBaseTypeless
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void applyEffect(T* audio, size_t frameCount, const ChannelMap& chanMap)=0;
|
virtual void applyEffect(T* audio, size_t frameCount, const ChannelMap& chanMap) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // __AMUSE_EFFECTBASE_HPP__
|
#endif // __AMUSE_EFFECTBASE_HPP__
|
||||||
|
|
|
@ -17,12 +17,13 @@ class EffectChorus
|
||||||
{
|
{
|
||||||
uint32_t x90_baseDelay; /**< [5, 15] minimum value (in ms) for computed delay */
|
uint32_t x90_baseDelay; /**< [5, 15] minimum value (in ms) for computed delay */
|
||||||
uint32_t x94_variation; /**< [0, 5] time error (in ms) to set delay within */
|
uint32_t x94_variation; /**< [0, 5] time error (in ms) to set delay within */
|
||||||
uint32_t x98_period; /**< [500, 10000] time (in ms) of one delay-shift cycle */
|
uint32_t x98_period; /**< [500, 10000] time (in ms) of one delay-shift cycle */
|
||||||
bool m_dirty = true; /**< needs update of internal parameter data */
|
bool m_dirty = true; /**< needs update of internal parameter data */
|
||||||
|
|
||||||
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>;
|
||||||
|
@ -56,32 +57,32 @@ class EffectChorusImp : public EffectBase<T>, public EffectChorus
|
||||||
T* x0_lastChans[8][AMUSE_CHORUS_NUM_BLOCKS] = {}; /**< Evenly-allocated pointer-table for each channel's delay */
|
T* x0_lastChans[8][AMUSE_CHORUS_NUM_BLOCKS] = {}; /**< Evenly-allocated pointer-table for each channel's delay */
|
||||||
|
|
||||||
uint8_t x24_currentLast = 1; /**< Last 5ms block-idx to be processed */
|
uint8_t x24_currentLast = 1; /**< Last 5ms block-idx to be processed */
|
||||||
T x28_oldChans[8][4] = {}; /**< Unprocessed history of previous 4 samples */
|
T x28_oldChans[8][4] = {}; /**< Unprocessed history of previous 4 samples */
|
||||||
|
|
||||||
uint32_t x58_currentPosLo = 0; /**< 16.7 fixed-point low-part of sample index */
|
uint32_t x58_currentPosLo = 0; /**< 16.7 fixed-point low-part of sample index */
|
||||||
uint32_t x5c_currentPosHi = 0; /**< 16.7 fixed-point high-part of sample index */
|
uint32_t x5c_currentPosHi = 0; /**< 16.7 fixed-point high-part of sample index */
|
||||||
|
|
||||||
int32_t x60_pitchOffset; /**< packed 16.16 fixed-point value of pitchHi and pitchLo quantities */
|
int32_t x60_pitchOffset; /**< packed 16.16 fixed-point value of pitchHi and pitchLo quantities */
|
||||||
uint32_t x64_pitchOffsetPeriodCount; /**< trigger value for flipping SRC state */
|
uint32_t x64_pitchOffsetPeriodCount; /**< trigger value for flipping SRC state */
|
||||||
uint32_t x68_pitchOffsetPeriod; /**< intermediate block window quantity for calculating SRC state */
|
uint32_t x68_pitchOffsetPeriod; /**< intermediate block window quantity for calculating SRC state */
|
||||||
|
|
||||||
struct SrcInfo
|
struct SrcInfo
|
||||||
{
|
{
|
||||||
T* x6c_dest; /**< selected channel's live buffer */
|
T* x6c_dest; /**< selected channel's live buffer */
|
||||||
T* x70_smpBase; /**< selected channel's delay buffer */
|
T* x70_smpBase; /**< selected channel's delay buffer */
|
||||||
T* x74_old; /**< selected channel's 4-sample history buffer */
|
T* x74_old; /**< selected channel's 4-sample history buffer */
|
||||||
uint32_t x78_posLo; /**< 16.7 fixed-point low-part of sample index */
|
uint32_t x78_posLo; /**< 16.7 fixed-point low-part of sample index */
|
||||||
uint32_t x7c_posHi; /**< 16.7 fixed-point high-part of sample index */
|
uint32_t x7c_posHi; /**< 16.7 fixed-point high-part of sample index */
|
||||||
uint32_t x80_pitchLo; /**< 16.7 fixed-point low-part of sample-rate conversion differential */
|
uint32_t x80_pitchLo; /**< 16.7 fixed-point low-part of sample-rate conversion differential */
|
||||||
uint32_t x84_pitchHi; /**< 16.7 fixed-point low-part of sample-rate conversion differential */
|
uint32_t x84_pitchHi; /**< 16.7 fixed-point low-part of sample-rate conversion differential */
|
||||||
uint32_t x88_trigger; /**< total count of samples per channel across all blocks */
|
uint32_t x88_trigger; /**< total count of samples per channel across all blocks */
|
||||||
uint32_t x8c_target = 0; /**< value to reset to when trigger hit */
|
uint32_t x8c_target = 0; /**< value to reset to when trigger hit */
|
||||||
|
|
||||||
void doSrc1(size_t blockSamples, size_t chanCount);
|
void doSrc1(size_t blockSamples, size_t chanCount);
|
||||||
void doSrc2(size_t blockSamples, size_t chanCount);
|
void doSrc2(size_t blockSamples, size_t chanCount);
|
||||||
} x6c_src;
|
} x6c_src;
|
||||||
|
|
||||||
uint32_t m_sampsPerMs; /**< canonical count of samples per ms for the current backend */
|
uint32_t m_sampsPerMs; /**< canonical count of samples per ms for the current backend */
|
||||||
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);
|
||||||
|
@ -91,9 +92,8 @@ public:
|
||||||
~EffectChorusImp();
|
~EffectChorusImp();
|
||||||
EffectChorusImp(uint32_t baseDelay, uint32_t variation, uint32_t period, double sampleRate);
|
EffectChorusImp(uint32_t baseDelay, uint32_t variation, uint32_t period, 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_EFFECTCHORUS_HPP__
|
#endif // __AMUSE_EFFECTCHORUS_HPP__
|
||||||
|
|
|
@ -15,10 +15,10 @@ class EffectDelayImp;
|
||||||
class EffectDelay
|
class EffectDelay
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
uint32_t x3c_delay[8]; /**< [10, 5000] time in ms of each channel's delay */
|
uint32_t x3c_delay[8]; /**< [10, 5000] time in ms of each channel's delay */
|
||||||
uint32_t x48_feedback[8]; /**< [0, 100] percent to mix delayed signal with input signal */
|
uint32_t x48_feedback[8]; /**< [0, 100] percent to mix delayed signal with input signal */
|
||||||
uint32_t x54_output[8]; /**< [0, 100] total output percent */
|
uint32_t x54_output[8]; /**< [0, 100] total output percent */
|
||||||
bool m_dirty = true; /**< needs update of internal parameter data */
|
bool m_dirty = true; /**< needs update of internal parameter data */
|
||||||
public:
|
public:
|
||||||
template <typename T>
|
template <typename T>
|
||||||
using ImpType = EffectDelayImp<T>;
|
using ImpType = EffectDelayImp<T>;
|
||||||
|
@ -26,7 +26,7 @@ public:
|
||||||
void setDelay(uint32_t delay)
|
void setDelay(uint32_t delay)
|
||||||
{
|
{
|
||||||
delay = clamp(10u, delay, 5000u);
|
delay = clamp(10u, delay, 5000u);
|
||||||
for (int i=0 ; i<8 ; ++i)
|
for (int i = 0; i < 8; ++i)
|
||||||
x3c_delay[i] = delay;
|
x3c_delay[i] = delay;
|
||||||
m_dirty = true;
|
m_dirty = true;
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,7 @@ public:
|
||||||
void setFeedback(uint32_t feedback)
|
void setFeedback(uint32_t feedback)
|
||||||
{
|
{
|
||||||
feedback = clamp(0u, feedback, 100u);
|
feedback = clamp(0u, feedback, 100u);
|
||||||
for (int i=0 ; i<8 ; ++i)
|
for (int i = 0; i < 8; ++i)
|
||||||
x48_feedback[i] = feedback;
|
x48_feedback[i] = feedback;
|
||||||
m_dirty = true;
|
m_dirty = true;
|
||||||
}
|
}
|
||||||
|
@ -55,7 +55,7 @@ public:
|
||||||
void setOutput(uint32_t output)
|
void setOutput(uint32_t output)
|
||||||
{
|
{
|
||||||
output = clamp(0u, output, 100u);
|
output = clamp(0u, output, 100u);
|
||||||
for (int i=0 ; i<8 ; ++i)
|
for (int i = 0; i < 8; ++i)
|
||||||
x54_output[i] = output;
|
x54_output[i] = output;
|
||||||
m_dirty = true;
|
m_dirty = true;
|
||||||
}
|
}
|
||||||
|
@ -71,23 +71,23 @@ public:
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class EffectDelayImp : public EffectBase<T>, public EffectDelay
|
class EffectDelayImp : public EffectBase<T>, public EffectDelay
|
||||||
{
|
{
|
||||||
uint32_t x0_currentSize[8]; /**< per-channel delay-line buffer sizes */
|
uint32_t x0_currentSize[8]; /**< per-channel delay-line buffer sizes */
|
||||||
uint32_t xc_currentPos[8]; /**< per-channel block-index */
|
uint32_t xc_currentPos[8]; /**< per-channel block-index */
|
||||||
uint32_t x18_currentFeedback[8]; /**< [0, 128] feedback attenuator */
|
uint32_t x18_currentFeedback[8]; /**< [0, 128] feedback attenuator */
|
||||||
uint32_t x24_currentOutput[8]; /**< [0, 128] total attenuator */
|
uint32_t x24_currentOutput[8]; /**< [0, 128] total attenuator */
|
||||||
|
|
||||||
std::unique_ptr<T[]> x30_chanLines[8]; /**< delay-line buffers for each channel */
|
std::unique_ptr<T[]> x30_chanLines[8]; /**< delay-line buffers for each channel */
|
||||||
|
|
||||||
uint32_t m_sampsPerMs; /**< canonical count of samples per ms for the current backend */
|
uint32_t m_sampsPerMs; /**< canonical count of samples per ms for the current backend */
|
||||||
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__
|
||||||
|
|
|
@ -31,19 +31,20 @@ 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
|
||||||
float x144_x1cc_mix; /**< [0.0, 1.0] dry/wet mix factor of reverb effect */
|
room */
|
||||||
float x148_x1d0_time; /**< [0.01, 10.0] time in seconds for reflection decay */
|
float x144_x1cc_mix; /**< [0.0, 1.0] dry/wet mix factor of reverb effect */
|
||||||
float x14c_x1d4_damping; /**< [0.0, 1.0] damping factor influencing low-pass filter of reflections */
|
float x148_x1d0_time; /**< [0.01, 10.0] time in seconds for reflection decay */
|
||||||
float x150_x1d8_preDelay; /**< [0.0, 0.1] time in seconds before initial reflection heard */
|
float x14c_x1d4_damping; /**< [0.0, 1.0] damping factor influencing low-pass filter of reflections */
|
||||||
bool m_dirty = true; /**< needs update of internal parameter data */
|
float x150_x1d8_preDelay; /**< [0.0, 0.1] time in seconds before initial reflection heard */
|
||||||
|
bool m_dirty = true; /**< needs update of internal parameter data */
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
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>;
|
||||||
|
@ -103,42 +104,42 @@ public:
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class EffectReverbStdImp : public EffectBase<T>, public EffectReverbStd
|
class EffectReverbStdImp : public EffectBase<T>, public EffectReverbStd
|
||||||
{
|
{
|
||||||
ReverbDelayLine x0_AP[8][2] = {}; /**< All-pass delay lines */
|
ReverbDelayLine x0_AP[8][2] = {}; /**< All-pass delay lines */
|
||||||
ReverbDelayLine x78_C[8][2] = {}; /**< Comb delay lines */
|
ReverbDelayLine x78_C[8][2] = {}; /**< Comb delay lines */
|
||||||
float xf0_allPassCoef = 0.f; /**< All-pass mix coefficient */
|
float xf0_allPassCoef = 0.f; /**< All-pass mix coefficient */
|
||||||
float xf4_combCoef[8][2] = {}; /**< Comb mix coefficients */
|
float xf4_combCoef[8][2] = {}; /**< Comb mix coefficients */
|
||||||
float x10c_lpLastout[8] = {}; /**< Last low-pass results */
|
float x10c_lpLastout[8] = {}; /**< Last low-pass results */
|
||||||
float x118_level = 0.f; /**< Internal wet/dry mix factor */
|
float x118_level = 0.f; /**< Internal wet/dry mix factor */
|
||||||
float x11c_damping = 0.f; /**< Low-pass damping */
|
float x11c_damping = 0.f; /**< Low-pass damping */
|
||||||
int32_t x120_preDelayTime = 0; /**< Sample count of pre-delay */
|
int32_t x120_preDelayTime = 0; /**< Sample count of pre-delay */
|
||||||
std::unique_ptr<float[]> x124_preDelayLine[8]; /**< Dedicated pre-delay buffers */
|
std::unique_ptr<float[]> x124_preDelayLine[8]; /**< Dedicated pre-delay buffers */
|
||||||
float* x130_preDelayPtr[8] = {}; /**< Current pre-delay pointers */
|
float* x130_preDelayPtr[8] = {}; /**< Current pre-delay pointers */
|
||||||
|
|
||||||
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); }
|
||||||
};
|
};
|
||||||
|
|
||||||
/** High-quality 3-stage reverb with per-channel low-pass and crosstalk */
|
/** High-quality 3-stage reverb with per-channel low-pass and crosstalk */
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class EffectReverbHiImp : public EffectBase<T>, public EffectReverbHi
|
class EffectReverbHiImp : public EffectBase<T>, public EffectReverbHi
|
||||||
{
|
{
|
||||||
ReverbDelayLine x0_AP[8][2] = {}; /**< All-pass delay lines */
|
ReverbDelayLine x0_AP[8][2] = {}; /**< All-pass delay lines */
|
||||||
ReverbDelayLine x78_LP[8] = {}; /**< Per-channel low-pass delay-lines */
|
ReverbDelayLine x78_LP[8] = {}; /**< Per-channel low-pass delay-lines */
|
||||||
ReverbDelayLine xb4_C[8][3] = {}; /**< Comb delay lines */
|
ReverbDelayLine xb4_C[8][3] = {}; /**< Comb delay lines */
|
||||||
float x168_allPassCoef = 0.f; /**< All-pass mix coefficient */
|
float x168_allPassCoef = 0.f; /**< All-pass mix coefficient */
|
||||||
float x16c_combCoef[8][3] = {}; /**< Comb mix coefficients */
|
float x16c_combCoef[8][3] = {}; /**< Comb mix coefficients */
|
||||||
float x190_lpLastout[8] = {}; /**< Last low-pass results */
|
float x190_lpLastout[8] = {}; /**< Last low-pass results */
|
||||||
float x19c_level = 0.f; /**< Internal wet/dry mix factor */
|
float x19c_level = 0.f; /**< Internal wet/dry mix factor */
|
||||||
float x1a0_damping = 0.f; /**< Low-pass damping */
|
float x1a0_damping = 0.f; /**< Low-pass damping */
|
||||||
int32_t x1a4_preDelayTime = 0; /**< Sample count of pre-delay */
|
int32_t x1a4_preDelayTime = 0; /**< Sample count of pre-delay */
|
||||||
std::unique_ptr<float[]> x1ac_preDelayLine[8]; /**< Dedicated pre-delay buffers */
|
std::unique_ptr<float[]> x1ac_preDelayLine[8]; /**< Dedicated pre-delay buffers */
|
||||||
float* x1b8_preDelayPtr[8] = {}; /**< Current pre-delay pointers */
|
float* x1b8_preDelayPtr[8] = {}; /**< Current pre-delay pointers */
|
||||||
float x1a8_internalCrosstalk = 0.f;
|
float x1a8_internalCrosstalk = 0.f;
|
||||||
|
|
||||||
double m_sampleRate; /**< copy of sample rate */
|
double m_sampleRate; /**< copy of sample rate */
|
||||||
|
@ -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:
|
|
||||||
EffectReverbHiImp(float coloration, float mix, float time,
|
|
||||||
float damping, float preDelay, float crosstalk, double sampleRate);
|
|
||||||
void applyEffect(T* audio, size_t frameCount, const ChannelMap& chanMap);
|
|
||||||
void resetOutputSampleRate(double sampleRate) {_setup(sampleRate);}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
EffectReverbHiImp(float coloration, float mix, float time, float damping, float preDelay, float crosstalk,
|
||||||
|
double sampleRate);
|
||||||
|
void applyEffect(T* audio, size_t frameCount, const ChannelMap& chanMap);
|
||||||
|
void resetOutputSampleRate(double sampleRate) { _setup(sampleRate); }
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // __AMUSE_EFFECTREVERB_HPP__
|
#endif // __AMUSE_EFFECTREVERB_HPP__
|
||||||
|
|
|
@ -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);
|
||||||
|
@ -28,9 +29,8 @@ public:
|
||||||
void setMinVol(float minVol);
|
void setMinVol(float minVol);
|
||||||
void setFalloff(float falloff);
|
void setFalloff(float falloff);
|
||||||
|
|
||||||
std::shared_ptr<Voice>& getVoice() {return m_vox;}
|
std::shared_ptr<Voice>& getVoice() { return m_vox; }
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // __AMUSE_EMITTER_HPP__
|
#endif // __AMUSE_EMITTER_HPP__
|
||||||
|
|
|
@ -23,7 +23,7 @@ class IMIDIReader;
|
||||||
|
|
||||||
enum class AmplitudeMode
|
enum class AmplitudeMode
|
||||||
{
|
{
|
||||||
PerSample, /**< Per-sample amplitude evaluation (dt = 1.0 / sampleRate, rather CPU demanding) */
|
PerSample, /**< Per-sample amplitude evaluation (dt = 1.0 / sampleRate, rather CPU demanding) */
|
||||||
BlockLinearized /**< Per-block lerp amplitude evaluation (dt = 160.0 / sampleRate) */
|
BlockLinearized /**< Per-block lerp amplitude evaluation (dt = 160.0 / sampleRate) */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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,25 +54,24 @@ 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::shared_ptr<Studio> _allocateStudio(bool mainOut);
|
||||||
std::list<std::shared_ptr<Studio>>::iterator _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);
|
||||||
|
|
||||||
/** Access voice backend of engine */
|
/** Access voice backend of engine */
|
||||||
IBackendVoiceAllocator& getBackend() {return m_backend;}
|
IBackendVoiceAllocator& getBackend() { return m_backend; }
|
||||||
|
|
||||||
/** Update all active audio entities and fill OS audio buffers as needed */
|
/** Update all active audio entities and fill OS audio buffers as needed */
|
||||||
void pumpEngine();
|
void pumpEngine();
|
||||||
|
@ -82,14 +83,11 @@ public:
|
||||||
void removeAudioGroup(const AudioGroupData& data);
|
void removeAudioGroup(const AudioGroupData& data);
|
||||||
|
|
||||||
/** Access engine's default studio */
|
/** Access engine's default studio */
|
||||||
std::shared_ptr<Studio> getDefaultStudio() {return m_defaultStudio;}
|
std::shared_ptr<Studio> getDefaultStudio() { return m_defaultStudio; }
|
||||||
|
|
||||||
/** 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,
|
||||||
|
@ -120,12 +117,11 @@ public:
|
||||||
void sendMacroMessage(ObjectId macroId, int32_t val);
|
void sendMacroMessage(ObjectId macroId, int32_t val);
|
||||||
|
|
||||||
/** Obtain next random number from engine's PRNG */
|
/** Obtain next random number from engine's PRNG */
|
||||||
uint32_t nextRandom() {return m_random();}
|
uint32_t nextRandom() { return m_random(); }
|
||||||
|
|
||||||
/** 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__
|
||||||
|
|
|
@ -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()
|
||||||
|
@ -35,8 +36,10 @@ protected:
|
||||||
int m_groupId;
|
int m_groupId;
|
||||||
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
|
||||||
|
@ -45,16 +48,15 @@ public:
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
Engine& getEngine() {return m_engine;}
|
Engine& getEngine() { return m_engine; }
|
||||||
const AudioGroup& getAudioGroup() const {return m_audioGroup;}
|
const AudioGroup& getAudioGroup() const { return m_audioGroup; }
|
||||||
int getGroupId() const {return m_groupId;}
|
int getGroupId() const { return m_groupId; }
|
||||||
ObjectId getObjectId() const {return m_objectId;}
|
ObjectId getObjectId() const { return m_objectId; }
|
||||||
};
|
};
|
||||||
|
|
||||||
/** 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__
|
||||||
|
|
|
@ -19,15 +19,17 @@ 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 */
|
||||||
double m_decayTime = 0.0; /**< Time of decay in seconds */
|
double m_decayTime = 0.0; /**< Time of decay in seconds */
|
||||||
double m_sustainFactor = 1.0; /**< Evaluated sustain percentage */
|
double m_sustainFactor = 1.0; /**< Evaluated sustain percentage */
|
||||||
double m_releaseTime = 0.0; /**< Time of release in seconds */
|
double m_releaseTime = 0.0; /**< Time of release in seconds */
|
||||||
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);
|
||||||
|
@ -35,10 +37,9 @@ public:
|
||||||
void keyOff();
|
void keyOff();
|
||||||
float advance(double dt, const Voice& vox);
|
float advance(double dt, const Voice& vox);
|
||||||
float advance(double dt);
|
float advance(double dt);
|
||||||
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__
|
||||||
|
|
|
@ -22,15 +22,14 @@ public:
|
||||||
virtual ~IBackendSubmix() = default;
|
virtual ~IBackendSubmix() = default;
|
||||||
|
|
||||||
/** Set send level for submix (AudioChannel enum for array index) */
|
/** Set send level for submix (AudioChannel enum for array index) */
|
||||||
virtual void setSendLevel(IBackendSubmix* submix, float level, bool slew)=0;
|
virtual void setSendLevel(IBackendSubmix* submix, float level, bool slew) = 0;
|
||||||
|
|
||||||
/** Amuse gets fixed sample rate of submix this way */
|
/** Amuse gets fixed sample rate of submix this way */
|
||||||
virtual double getSampleRate() const=0;
|
virtual double getSampleRate() const = 0;
|
||||||
|
|
||||||
/** 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__
|
||||||
|
|
|
@ -33,24 +33,23 @@ public:
|
||||||
virtual ~IBackendVoice() = default;
|
virtual ~IBackendVoice() = default;
|
||||||
|
|
||||||
/** Set new sample rate into platform voice (may result in artifacts while playing) */
|
/** Set new sample rate into platform voice (may result in artifacts while playing) */
|
||||||
virtual void resetSampleRate(double sampleRate)=0;
|
virtual void resetSampleRate(double sampleRate) = 0;
|
||||||
|
|
||||||
/** Reset channel-gains to silence and unbind all submixes */
|
/** Reset channel-gains to silence and unbind all submixes */
|
||||||
virtual void resetChannelLevels()=0;
|
virtual void resetChannelLevels() = 0;
|
||||||
|
|
||||||
/** Set channel-gains for audio source (AudioChannel enum for array index) */
|
/** Set channel-gains for audio source (AudioChannel enum for array index) */
|
||||||
virtual void setChannelLevels(IBackendSubmix* submix, const float coefs[8], bool slew)=0;
|
virtual void setChannelLevels(IBackendSubmix* submix, const float coefs[8], bool slew) = 0;
|
||||||
|
|
||||||
/** Called by client to dynamically adjust the pitch of voices with dynamic pitch enabled */
|
/** Called by client to dynamically adjust the pitch of voices with dynamic pitch enabled */
|
||||||
virtual void setPitchRatio(double ratio, bool slew)=0;
|
virtual void setPitchRatio(double ratio, bool slew) = 0;
|
||||||
|
|
||||||
/** Instructs platform to begin consuming sample data; invoking callback as needed */
|
/** Instructs platform to begin consuming sample data; invoking callback as needed */
|
||||||
virtual void start()=0;
|
virtual void start() = 0;
|
||||||
|
|
||||||
/** 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__
|
||||||
|
|
|
@ -27,9 +27,9 @@ enum class AudioChannelSet
|
||||||
class IMIDIReader
|
class IMIDIReader
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~IMIDIReader()=default;
|
virtual ~IMIDIReader() = default;
|
||||||
virtual std::string description()=0;
|
virtual std::string description() = 0;
|
||||||
virtual void pumpReader(double dt)=0;
|
virtual void pumpReader(double dt) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Client-implemented voice allocator */
|
/** Client-implemented voice allocator */
|
||||||
|
@ -39,29 +39,26 @@ 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;
|
||||||
|
|
||||||
/** Amuse obtains an interactive MIDI-in connection from the OS this way */
|
/** Amuse obtains an interactive MIDI-in connection from the OS this way */
|
||||||
virtual std::unique_ptr<IMIDIReader> allocateMIDIReader(Engine& engine, const char* name=nullptr)=0;
|
virtual std::unique_ptr<IMIDIReader> allocateMIDIReader(Engine& engine, const char* name = nullptr) = 0;
|
||||||
|
|
||||||
/** Amuse obtains speaker-configuration from the platform this way */
|
/** Amuse obtains speaker-configuration from the platform this way */
|
||||||
virtual AudioChannelSet getAvailableSet()=0;
|
virtual AudioChannelSet getAvailableSet() = 0;
|
||||||
|
|
||||||
/** Amuse flushes voice samples to the backend this way */
|
/** Amuse flushes voice samples to the backend this way */
|
||||||
virtual void pumpAndMixVoices()=0;
|
virtual void pumpAndMixVoices() = 0;
|
||||||
|
|
||||||
/** 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__
|
||||||
|
|
|
@ -9,7 +9,6 @@ namespace amuse
|
||||||
class Listener : public Entity
|
class Listener : public Entity
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // __AMUSE_LISTENER_HPP__
|
#endif // __AMUSE_LISTENER_HPP__
|
||||||
|
|
|
@ -18,24 +18,24 @@ class Voice;
|
||||||
/** State of sequencer over lifetime */
|
/** State of sequencer over lifetime */
|
||||||
enum class SequencerState
|
enum class SequencerState
|
||||||
{
|
{
|
||||||
Playing, /**< Sequencer actively playing arrangement */
|
Playing, /**< Sequencer actively playing arrangement */
|
||||||
Interactive, /**< Interactive sequencer for live MIDI message processing, will not automatically die */
|
Interactive, /**< Interactive sequencer for live MIDI message processing, will not automatically die */
|
||||||
Dead /**< Set when arrangement complete and `dieOnEnd` was set, or manually with die() */
|
Dead /**< Set when arrangement complete and `dieOnEnd` was set, or manually with die() */
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Multi-voice lifetime manager and polyphonic parameter tracking */
|
/** Multi-voice lifetime manager and polyphonic parameter tracking */
|
||||||
class Sequencer : public Entity
|
class Sequencer : public Entity
|
||||||
{
|
{
|
||||||
friend class Engine;
|
friend class Engine;
|
||||||
const SongGroupIndex* m_songGroup = nullptr; /**< Quick access to song group project index */
|
const SongGroupIndex* m_songGroup = nullptr; /**< Quick access to song group project index */
|
||||||
const SongGroupIndex::MIDISetup* m_midiSetup = nullptr; /**< Selected MIDI setup (may be null) */
|
const SongGroupIndex::MIDISetup* m_midiSetup = nullptr; /**< Selected MIDI setup (may be null) */
|
||||||
const SFXGroupIndex* m_sfxGroup = nullptr; /**< SFX Groups are alternatively referenced here */
|
const SFXGroupIndex* m_sfxGroup = nullptr; /**< SFX Groups are alternatively referenced here */
|
||||||
std::vector<const SFXGroupIndex::SFXEntry*> m_sfxMappings; /**< SFX entries are mapped to MIDI keys this via this */
|
std::vector<const SFXGroupIndex::SFXEntry*> m_sfxMappings; /**< SFX entries are mapped to MIDI keys this via this */
|
||||||
std::shared_ptr<Studio> m_studio; /**< Studio this sequencer outputs to */
|
std::shared_ptr<Studio> m_studio; /**< Studio this sequencer outputs to */
|
||||||
|
|
||||||
const unsigned char* m_arrData = nullptr; /**< Current playing arrangement data */
|
const unsigned char* m_arrData = nullptr; /**< Current playing arrangement data */
|
||||||
SongState m_songState; /**< State of current arrangement playback */
|
SongState m_songState; /**< State of current arrangement playback */
|
||||||
double m_ticksPerSec = 1000.0; /**< Current ticks per second (tempo) for arrangement data */
|
double m_ticksPerSec = 1000.0; /**< Current ticks per second (tempo) for arrangement data */
|
||||||
SequencerState m_state = SequencerState::Interactive; /**< Current high-level state of sequencer */
|
SequencerState m_state = SequencerState::Interactive; /**< Current high-level state of sequencer */
|
||||||
bool m_dieOnEnd = false; /**< Sequencer will be killed when current arrangement completes */
|
bool m_dieOnEnd = false; /**< Sequencer will be killed when current arrangement completes */
|
||||||
|
|
||||||
|
@ -57,9 +57,9 @@ class Sequencer : public Entity
|
||||||
std::weak_ptr<Voice> m_lastVoice;
|
std::weak_ptr<Voice> m_lastVoice;
|
||||||
int8_t m_ctrlVals[128] = {}; /**< MIDI controller values */
|
int8_t m_ctrlVals[128] = {}; /**< MIDI controller values */
|
||||||
float m_curPitchWheel = 0.f; /**< MIDI pitch-wheel */
|
float m_curPitchWheel = 0.f; /**< MIDI pitch-wheel */
|
||||||
int8_t m_curProgram = 0; /**< MIDI program number */
|
int8_t m_curProgram = 0; /**< MIDI program number */
|
||||||
float m_curVol = 1.f; /**< Current volume of channel */
|
float m_curVol = 1.f; /**< Current volume of channel */
|
||||||
float m_curPan = 0.f; /**< Current panning of channel */
|
float m_curPan = 0.f; /**< Current panning of channel */
|
||||||
|
|
||||||
void _bringOutYourDead();
|
void _bringOutYourDead();
|
||||||
size_t getVoiceCount() const;
|
size_t getVoiceCount() const;
|
||||||
|
@ -84,19 +84,19 @@ 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);
|
||||||
|
|
||||||
/** Obtain pointer to Sequencer's Submix */
|
/** Obtain pointer to Sequencer's Submix */
|
||||||
std::shared_ptr<Studio> getStudio() {return m_studio;}
|
std::shared_ptr<Studio> getStudio() { return m_studio; }
|
||||||
|
|
||||||
/** Get current state of sequencer */
|
/** Get current state of sequencer */
|
||||||
SequencerState state() const {return m_state;}
|
SequencerState state() const { return m_state; }
|
||||||
|
|
||||||
/** Get number of active voices */
|
/** Get number of active voices */
|
||||||
size_t getVoiceCount() const;
|
size_t getVoiceCount() const;
|
||||||
|
@ -114,10 +114,10 @@ public:
|
||||||
void setPitchWheel(uint8_t chan, float pitchWheel);
|
void setPitchWheel(uint8_t chan, float pitchWheel);
|
||||||
|
|
||||||
/** Send keyoffs to all active notes, silence immediately if `now` set */
|
/** Send keyoffs to all active notes, silence immediately if `now` set */
|
||||||
void allOff(bool now=false);
|
void allOff(bool now = false);
|
||||||
|
|
||||||
/** Send keyoffs to all active notes on specified channel, silence immediately if `now` set */
|
/** Send keyoffs to all active notes on specified channel, silence immediately if `now` set */
|
||||||
void allOff(uint8_t chan, bool now=false);
|
void allOff(uint8_t chan, bool now = false);
|
||||||
|
|
||||||
/** Stop all voices in `kg`, stops immediately (no KeyOff) when `now` set */
|
/** Stop all voices in `kg`, stops immediately (no KeyOff) when `now` set */
|
||||||
void killKeygroup(uint8_t kg, bool now);
|
void killKeygroup(uint8_t kg, bool now);
|
||||||
|
@ -132,10 +132,10 @@ public:
|
||||||
void setTempo(double ticksPerSec);
|
void setTempo(double ticksPerSec);
|
||||||
|
|
||||||
/** Play MIDI arrangement */
|
/** Play MIDI arrangement */
|
||||||
void playSong(const unsigned char* arrData, bool dieOnEnd=true);
|
void playSong(const unsigned char* arrData, bool dieOnEnd = true);
|
||||||
|
|
||||||
/** Stop current MIDI arrangement */
|
/** Stop current MIDI arrangement */
|
||||||
void stopSong(bool now=false);
|
void stopSong(bool now = false);
|
||||||
|
|
||||||
/** Set total volume of sequencer */
|
/** Set total volume of sequencer */
|
||||||
void setVolume(float vol);
|
void setVolume(float vol);
|
||||||
|
@ -153,9 +153,8 @@ public:
|
||||||
void prevChanProgram(int8_t chanId);
|
void prevChanProgram(int8_t chanId);
|
||||||
|
|
||||||
/** 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__
|
||||||
|
|
|
@ -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__
|
||||||
|
|
|
@ -51,14 +51,14 @@ class SongState
|
||||||
/** Tempo change entry */
|
/** Tempo change entry */
|
||||||
struct TempoChange
|
struct TempoChange
|
||||||
{
|
{
|
||||||
uint32_t m_tick; /**< Relative song ticks from previous tempo change */
|
uint32_t m_tick; /**< Relative song ticks from previous tempo change */
|
||||||
uint32_t m_tempo; /**< Tempo value in beats-per-minute (at 384 ticks per quarter-note) */
|
uint32_t m_tempo; /**< Tempo value in beats-per-minute (at 384 ticks per quarter-note) */
|
||||||
void swapBig();
|
void swapBig();
|
||||||
};
|
};
|
||||||
|
|
||||||
const unsigned char* m_songData = nullptr; /**< Base pointer to active song */
|
const unsigned char* m_songData = nullptr; /**< Base pointer to active song */
|
||||||
int m_sngVersion; /**< Detected song revision, 1 has RLE-compressed delta-times */
|
int m_sngVersion; /**< Detected song revision, 1 has RLE-compressed delta-times */
|
||||||
bool m_bigEndian; /**< True if loaded song is big-endian data */
|
bool m_bigEndian; /**< True if loaded song is big-endian data */
|
||||||
|
|
||||||
/** State of a single track within arrangement */
|
/** State of a single track within arrangement */
|
||||||
struct Track
|
struct Track
|
||||||
|
@ -72,21 +72,22 @@ class SongState
|
||||||
};
|
};
|
||||||
|
|
||||||
SongState& m_parent;
|
SongState& m_parent;
|
||||||
uint8_t m_midiChan; /**< MIDI channel number of song channel */
|
uint8_t m_midiChan; /**< MIDI channel number of song channel */
|
||||||
const TrackRegion* m_curRegion; /**< Pointer to currently-playing track region */
|
const TrackRegion* m_curRegion; /**< Pointer to currently-playing track region */
|
||||||
const TrackRegion* m_nextRegion; /**< Pointer to next-queued track region */
|
const TrackRegion* m_nextRegion; /**< Pointer to next-queued track region */
|
||||||
|
|
||||||
const unsigned char* m_data = nullptr; /**< Pointer to upcoming command data */
|
const unsigned char* m_data = nullptr; /**< Pointer to upcoming command data */
|
||||||
const unsigned char* m_pitchWheelData = nullptr; /**< Pointer to upcoming pitch data */
|
const unsigned char* m_pitchWheelData = nullptr; /**< Pointer to upcoming pitch data */
|
||||||
const unsigned char* m_modWheelData = nullptr; /**< Pointer to upcoming modulation data */
|
const unsigned char* m_modWheelData = nullptr; /**< Pointer to upcoming modulation data */
|
||||||
uint32_t m_lastPitchTick = 0; /**< Last position of pitch wheel change */
|
uint32_t m_lastPitchTick = 0; /**< Last position of pitch wheel change */
|
||||||
int32_t m_lastPitchVal = 0; /**< Last value of pitch */
|
int32_t m_lastPitchVal = 0; /**< Last value of pitch */
|
||||||
uint32_t m_lastModTick = 0; /**< Last position of mod wheel change */
|
uint32_t m_lastModTick = 0; /**< Last position of mod wheel change */
|
||||||
int32_t m_lastModVal = 0; /**< Last value of mod */
|
int32_t m_lastModVal = 0; /**< Last value of mod */
|
||||||
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);
|
||||||
|
@ -100,9 +101,9 @@ class SongState
|
||||||
const TempoChange* m_tempoPtr = nullptr;
|
const TempoChange* m_tempoPtr = nullptr;
|
||||||
uint32_t m_tempo = 120; /**< Current tempo (beats per minute) */
|
uint32_t m_tempo = 120; /**< Current tempo (beats per minute) */
|
||||||
|
|
||||||
uint32_t m_curTick = 0; /**< Current playback position for all channels */
|
uint32_t m_curTick = 0; /**< Current playback position for all channels */
|
||||||
SongPlayState m_songState = SongPlayState::Playing; /**< High-level state of Song playback */
|
SongPlayState m_songState = SongPlayState::Playing; /**< High-level state of Song playback */
|
||||||
double m_curDt = 0.f; /**< Cumulative dt value for time-remainder tracking */
|
double m_curDt = 0.f; /**< Cumulative dt value for time-remainder tracking */
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/** Determine SNG version
|
/** Determine SNG version
|
||||||
|
@ -119,9 +120,8 @@ public:
|
||||||
bool advance(Sequencer& seq, double dt);
|
bool advance(Sequencer& seq, double dt);
|
||||||
|
|
||||||
/** 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__
|
||||||
|
|
|
@ -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,
|
||||||
|
@ -120,34 +120,34 @@ class SoundMacroState
|
||||||
std::vector<std::pair<const unsigned char*, int>> m_pc;
|
std::vector<std::pair<const unsigned char*, int>> m_pc;
|
||||||
|
|
||||||
double m_ticksPerSec; /**< ratio for resolving ticks in commands that use them */
|
double m_ticksPerSec; /**< ratio for resolving ticks in commands that use them */
|
||||||
uint8_t m_initVel; /**< Velocity played for this macro invocation */
|
uint8_t m_initVel; /**< Velocity played for this macro invocation */
|
||||||
uint8_t m_initMod; /**< Modulation played for this macro invocation */
|
uint8_t m_initMod; /**< Modulation played for this macro invocation */
|
||||||
uint8_t m_initKey; /**< Key played for this macro invocation */
|
uint8_t m_initKey; /**< Key played for this macro invocation */
|
||||||
uint8_t m_curVel; /**< Current velocity played for this macro invocation */
|
uint8_t m_curVel; /**< Current velocity played for this macro invocation */
|
||||||
uint8_t m_curMod; /**< Current modulation played for this macro invocation */
|
uint8_t m_curMod; /**< Current modulation played for this macro invocation */
|
||||||
uint32_t m_curPitch; /**< Current key played for this macro invocation (in cents) */
|
uint32_t m_curPitch; /**< Current key played for this macro invocation (in cents) */
|
||||||
|
|
||||||
double m_execTime; /**< time in seconds of SoundMacro execution (per-update resolution) */
|
double m_execTime; /**< time in seconds of SoundMacro execution (per-update resolution) */
|
||||||
bool m_keyoff; /**< keyoff message has been received */
|
bool m_keyoff; /**< keyoff message has been received */
|
||||||
bool m_sampleEnd; /**< sample has finished playback */
|
bool m_sampleEnd; /**< sample has finished playback */
|
||||||
|
|
||||||
bool m_inWait = false; /**< set when timer/keyoff/sampleend wait active */
|
bool m_inWait = false; /**< set when timer/keyoff/sampleend wait active */
|
||||||
bool m_indefiniteWait = false; /**< set when timer wait is indefinite (keyoff/sampleend only) */
|
bool m_indefiniteWait = false; /**< set when timer wait is indefinite (keyoff/sampleend only) */
|
||||||
bool m_keyoffWait = false; /**< set when active wait is a keyoff wait */
|
bool m_keyoffWait = false; /**< set when active wait is a keyoff wait */
|
||||||
bool m_sampleEndWait = false; /**< set when active wait is a sampleend wait */
|
bool m_sampleEndWait = false; /**< set when active wait is a sampleend wait */
|
||||||
double m_waitCountdown; /**< countdown timer for active wait */
|
double m_waitCountdown; /**< countdown timer for active wait */
|
||||||
|
|
||||||
int m_loopCountdown = -1; /**< countdown for current loop */
|
int m_loopCountdown = -1; /**< countdown for current loop */
|
||||||
int m_lastPlayMacroVid = -1; /**< VoiceId from last PlayMacro command */
|
int m_lastPlayMacroVid = -1; /**< VoiceId from last PlayMacro command */
|
||||||
|
|
||||||
bool m_useAdsrControllers; /**< when set, use the following controllers for envelope times */
|
bool m_useAdsrControllers; /**< when set, use the following controllers for envelope times */
|
||||||
uint8_t m_midiAttack; /**< Attack MIDI controller */
|
uint8_t m_midiAttack; /**< Attack MIDI controller */
|
||||||
uint8_t m_midiDecay; /**< Decay MIDI controller */
|
uint8_t m_midiDecay; /**< Decay MIDI controller */
|
||||||
uint8_t m_midiSustain; /**< Sustain MIDI controller */
|
uint8_t m_midiSustain; /**< Sustain MIDI controller */
|
||||||
uint8_t m_midiRelease; /**< Release MIDI controller */
|
uint8_t m_midiRelease; /**< Release MIDI controller */
|
||||||
|
|
||||||
uint8_t m_portamentoMode = 2; /**< (0: Off, 1: On, 2: MIDI specified) */
|
uint8_t m_portamentoMode = 2; /**< (0: Off, 1: On, 2: MIDI specified) */
|
||||||
uint8_t m_portamentoType = 0; /**< (0: New key pressed while old key pressed, 1: Always) */
|
uint8_t m_portamentoType = 0; /**< (0: New key pressed while old key pressed, 1: Always) */
|
||||||
float m_portamentoTime = 0.5f; /**< portamento transition time, 0.f will perform legato */
|
float m_portamentoTime = 0.5f; /**< portamento transition time, 0.f will perform legato */
|
||||||
|
|
||||||
/** Used to build a multi-component formula for overriding controllers */
|
/** Used to build a multi-component formula for overriding controllers */
|
||||||
|
@ -174,19 +174,20 @@ 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; }
|
||||||
};
|
};
|
||||||
|
|
||||||
Evaluator m_volumeSel;
|
Evaluator m_volumeSel;
|
||||||
|
@ -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__
|
||||||
|
|
|
@ -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& getAuxA() {return m_auxA;}
|
Submix& getMaster() { return m_master; }
|
||||||
Submix& getAuxB() {return m_auxB;}
|
Submix& getAuxA() { return m_auxA; }
|
||||||
|
Submix& getAuxB() { return m_auxB; }
|
||||||
|
|
||||||
Engine& getEngine() {return m_engine;}
|
Engine& getEngine() { return m_engine; }
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // __AMUSE_STUDIO_HPP__
|
#endif // __AMUSE_STUDIO_HPP__
|
||||||
|
|
|
@ -23,23 +23,14 @@ class Submix
|
||||||
friend class Voice;
|
friend class Voice;
|
||||||
friend class Sequencer;
|
friend class Sequencer;
|
||||||
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>
|
||||||
T& makeEffect(Args... args)
|
T& makeEffect(Args... args)
|
||||||
{
|
{
|
||||||
switch (m_backendSubmix->getSampleFormat())
|
switch (m_backendSubmix->getSampleFormat())
|
||||||
|
@ -73,18 +64,17 @@ 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(); }
|
||||||
|
|
||||||
/** Returns true when an effect callback is bound */
|
/** Returns true when an effect callback is bound */
|
||||||
bool canApplyEffect() const {return m_effectStack.size() != 0;}
|
bool canApplyEffect() const { return m_effectStack.size() != 0; }
|
||||||
|
|
||||||
/** in/out transformation entry for audio effect */
|
/** in/out transformation entry for audio effect */
|
||||||
void applyEffect(int16_t* audio, size_t frameCount, const ChannelMap& chanMap) const;
|
void applyEffect(int16_t* audio, size_t frameCount, const ChannelMap& chanMap) const;
|
||||||
|
@ -98,9 +88,8 @@ public:
|
||||||
/** advice effects of changing sample rate */
|
/** advice effects of changing sample rate */
|
||||||
void resetOutputSampleRate(double sampleRate);
|
void resetOutputSampleRate(double sampleRate);
|
||||||
|
|
||||||
Engine& getEngine() {return m_root;}
|
Engine& getEngine() { return m_root; }
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // __AMUSE_SUBMIX_HPP__
|
#endif // __AMUSE_SUBMIX_HPP__
|
||||||
|
|
|
@ -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__
|
||||||
|
|
|
@ -22,8 +22,8 @@ struct LayerMapping;
|
||||||
enum class VoiceState
|
enum class VoiceState
|
||||||
{
|
{
|
||||||
Playing, /**< SoundMacro actively executing, not in KeyOff */
|
Playing, /**< SoundMacro actively executing, not in KeyOff */
|
||||||
KeyOff, /**< KeyOff event issued, macro beginning fade-out */
|
KeyOff, /**< KeyOff event issued, macro beginning fade-out */
|
||||||
Dead /**< Default state, causes Engine to remove voice at end of pump cycle */
|
Dead /**< Default state, causes Engine to remove voice at end of pump cycle */
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Individual source of audio */
|
/** Individual source of audio */
|
||||||
|
@ -33,112 +33,120 @@ class Voice : public Entity
|
||||||
friend class Sequencer;
|
friend class Sequencer;
|
||||||
friend class SoundMacroState;
|
friend class SoundMacroState;
|
||||||
friend class Envelope;
|
friend class Envelope;
|
||||||
int m_vid; /**< VoiceID of this voice instance */
|
int m_vid; /**< VoiceID of this voice instance */
|
||||||
bool m_emitter; /**< Voice is part of an Emitter */
|
bool m_emitter; /**< Voice is part of an Emitter */
|
||||||
std::shared_ptr<Studio> m_studio; /**< Studio this voice outputs to */
|
std::shared_ptr<Studio> m_studio; /**< Studio this voice outputs to */
|
||||||
|
|
||||||
std::unique_ptr<IBackendVoice> m_backendVoice; /**< Handle to client-implemented backend voice */
|
std::unique_ptr<IBackendVoice> m_backendVoice; /**< Handle to client-implemented backend voice */
|
||||||
SoundMacroState m_state; /**< State container for SoundMacro playback */
|
SoundMacroState m_state; /**< State container for SoundMacro playback */
|
||||||
SoundMacroState::EventTrap m_keyoffTrap; /**< Trap for keyoff (SoundMacro overrides default envelope behavior) */
|
SoundMacroState::EventTrap m_keyoffTrap; /**< Trap for keyoff (SoundMacro overrides default envelope behavior) */
|
||||||
SoundMacroState::EventTrap m_sampleEndTrap; /**< Trap for sampleend (SoundMacro overrides voice removal) */
|
SoundMacroState::EventTrap m_sampleEndTrap; /**< Trap for sampleend (SoundMacro overrides voice removal) */
|
||||||
SoundMacroState::EventTrap m_messageTrap; /**< Trap for messages sent from other SoundMacros */
|
SoundMacroState::EventTrap m_messageTrap; /**< Trap for messages sent from other SoundMacros */
|
||||||
std::list<int32_t> m_messageQueue; /**< Messages pending processing for SoundMacros in this voice */
|
std::list<int32_t> m_messageQueue; /**< Messages pending processing for SoundMacros in this voice */
|
||||||
std::list<std::shared_ptr<Voice>> m_childVoices; /**< Child voices for PLAYMACRO usage */
|
std::list<std::shared_ptr<Voice>> m_childVoices; /**< Child voices for PLAYMACRO usage */
|
||||||
uint8_t m_keygroup = 0; /**< Keygroup voice is a member of */
|
uint8_t m_keygroup = 0; /**< Keygroup voice is a member of */
|
||||||
|
|
||||||
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) */
|
||||||
};
|
};
|
||||||
const Sample* m_curSample = nullptr; /**< Current sample entry playing */
|
const Sample* m_curSample = nullptr; /**< Current sample entry playing */
|
||||||
const unsigned char* m_curSampleData = nullptr; /**< Current sample data playing */
|
const unsigned char* m_curSampleData = nullptr; /**< Current sample data playing */
|
||||||
SampleFormat m_curFormat; /**< Current sample format playing */
|
SampleFormat m_curFormat; /**< Current sample format playing */
|
||||||
uint32_t m_curSamplePos = 0; /**< Current sample position */
|
uint32_t m_curSamplePos = 0; /**< Current sample position */
|
||||||
uint32_t m_lastSamplePos = 0; /**< Last sample position (or last loop sample) */
|
uint32_t m_lastSamplePos = 0; /**< Last sample position (or last loop sample) */
|
||||||
int16_t m_prev1 = 0; /**< DSPADPCM prev sample */
|
int16_t m_prev1 = 0; /**< DSPADPCM prev sample */
|
||||||
int16_t m_prev2 = 0; /**< DSPADPCM prev-prev sample */
|
int16_t m_prev2 = 0; /**< DSPADPCM prev-prev sample */
|
||||||
double m_sampleRate = 32000.0; /**< Current sample rate computed from relative sample key or SETPITCH */
|
double m_sampleRate = 32000.0; /**< Current sample rate computed from relative sample key or SETPITCH */
|
||||||
double m_voiceTime = 0.0; /**< Current seconds of voice playback (per-sample resolution) */
|
double m_voiceTime = 0.0; /**< Current seconds of voice playback (per-sample resolution) */
|
||||||
uint64_t m_voiceSamples = 0; /**< Count of samples processed over voice's lifetime */
|
uint64_t m_voiceSamples = 0; /**< Count of samples processed over voice's lifetime */
|
||||||
float m_lastLevel = 0.f; /**< Last computed level ([0,1] mapped to [-10,0] clamped decibels) */
|
float m_lastLevel = 0.f; /**< Last computed level ([0,1] mapped to [-10,0] clamped decibels) */
|
||||||
float m_nextLevel = 0.f; /**< Next computed level used for lerp-mode amplitude */
|
float m_nextLevel = 0.f; /**< Next computed level used for lerp-mode amplitude */
|
||||||
|
|
||||||
VoiceState m_voxState = VoiceState::Dead; /**< Current high-level state of voice */
|
VoiceState m_voxState = VoiceState::Dead; /**< Current high-level state of voice */
|
||||||
bool m_sustained = false; /**< Sustain pedal pressed for this voice */
|
bool m_sustained = false; /**< Sustain pedal pressed for this voice */
|
||||||
bool m_sustainKeyOff = false; /**< Keyoff event occured while sustained */
|
bool m_sustainKeyOff = false; /**< Keyoff event occured while sustained */
|
||||||
uint8_t m_curAftertouch = 0; /**< Aftertouch value (key pressure when 'bottoming out') */
|
uint8_t m_curAftertouch = 0; /**< Aftertouch value (key pressure when 'bottoming out') */
|
||||||
|
|
||||||
float m_targetUserVol = 1.f; /**< Target user volume of voice (slewed to prevent audible aliasing) */
|
float m_targetUserVol = 1.f; /**< Target user volume of voice (slewed to prevent audible aliasing) */
|
||||||
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_userPan = 0.f; /**< User pan of voice */
|
float m_curAuxBVol = 0.f; /**< Current AuxB volume of voice */
|
||||||
float m_curPan = 0.f; /**< Current pan of voice */
|
float m_userPan = 0.f; /**< User pan of voice */
|
||||||
float m_userSpan = 0.f; /**< User span of voice */
|
float m_curPan = 0.f; /**< Current pan of voice */
|
||||||
float m_curSpan = 0.f; /**< Current surround pan of voice */
|
float m_userSpan = 0.f; /**< User span of voice */
|
||||||
float m_curPitchWheel = 0.f; /**< Current normalized wheel value for control */
|
float m_curSpan = 0.f; /**< Current surround pan of voice */
|
||||||
int32_t m_pitchWheelUp = 600; /**< Up range for pitchwheel control in cents */
|
float m_curPitchWheel = 0.f; /**< Current normalized wheel value for control */
|
||||||
|
int32_t m_pitchWheelUp = 600; /**< Up range for pitchwheel control in cents */
|
||||||
int32_t m_pitchWheelDown = 600; /**< Down range for pitchwheel control in cents */
|
int32_t m_pitchWheelDown = 600; /**< Down range for pitchwheel control in cents */
|
||||||
int32_t m_pitchWheelVal = 0; /**< Current resolved pitchwheel delta for control */
|
int32_t m_pitchWheelVal = 0; /**< Current resolved pitchwheel delta for control */
|
||||||
int32_t m_curPitch; /**< Current base pitch in cents */
|
int32_t m_curPitch; /**< Current base pitch in cents */
|
||||||
bool m_pitchDirty = true; /**< m_curPitch has been updated and needs sending to voice */
|
bool m_pitchDirty = true; /**< m_curPitch has been updated and needs sending to voice */
|
||||||
bool m_needsSlew = false; /**< next _setTotalPitch will be slewed */
|
bool m_needsSlew = false; /**< next _setTotalPitch will be slewed */
|
||||||
|
|
||||||
Envelope m_volAdsr; /**< Volume envelope */
|
Envelope m_volAdsr; /**< Volume envelope */
|
||||||
double m_envelopeTime = -1.f; /**< time since last ENVELOPE command, -1 for no active volume-sweep */
|
double m_envelopeTime = -1.f; /**< time since last ENVELOPE command, -1 for no active volume-sweep */
|
||||||
double m_envelopeDur; /**< requested duration of last ENVELOPE command */
|
double m_envelopeDur; /**< requested duration of last ENVELOPE command */
|
||||||
float m_envelopeStart; /**< initial value for last ENVELOPE command */
|
float m_envelopeStart; /**< initial value for last ENVELOPE command */
|
||||||
float m_envelopeEnd; /**< final value for last ENVELOPE command */
|
float m_envelopeEnd; /**< final value for last ENVELOPE command */
|
||||||
const Curve* m_envelopeCurve; /**< curve to use for ENVELOPE command */
|
const Curve* m_envelopeCurve; /**< curve to use for ENVELOPE command */
|
||||||
|
|
||||||
bool m_pitchEnv = false; /**< Pitch envelope activated */
|
bool m_pitchEnv = false; /**< Pitch envelope activated */
|
||||||
Envelope m_pitchAdsr; /**< Pitch envelope for SETPITCHADSR */
|
Envelope m_pitchAdsr; /**< Pitch envelope for SETPITCHADSR */
|
||||||
int32_t m_pitchEnvRange; /**< Pitch delta for SETPITCHADSR (in cents) */
|
int32_t m_pitchEnvRange; /**< Pitch delta for SETPITCHADSR (in cents) */
|
||||||
|
|
||||||
float m_portamentoTime = -1.f; /**< time since last portamento invocation, -1 for no active portamento-glide */
|
float m_portamentoTime = -1.f; /**< time since last portamento invocation, -1 for no active portamento-glide */
|
||||||
int32_t m_portamentoTarget; /**< destination pitch for latest portamento invocation */
|
int32_t m_portamentoTarget; /**< destination pitch for latest portamento invocation */
|
||||||
|
|
||||||
uint32_t m_pitchSweep1 = 0; /**< Current value of PITCHSWEEP1 controller (in cents) */
|
uint32_t m_pitchSweep1 = 0; /**< Current value of PITCHSWEEP1 controller (in cents) */
|
||||||
uint32_t m_pitchSweep2 = 0; /**< Current value of PITCHSWEEP2 controller (in cents) */
|
uint32_t m_pitchSweep2 = 0; /**< Current value of PITCHSWEEP2 controller (in cents) */
|
||||||
int16_t m_pitchSweep1Add = 0; /**< Value to add to PITCHSWEEP1 controller each cycle */
|
int16_t m_pitchSweep1Add = 0; /**< Value to add to PITCHSWEEP1 controller each cycle */
|
||||||
int16_t m_pitchSweep2Add = 0; /**< Value to add to PITCHSWEEP2 controller each cycle */
|
int16_t m_pitchSweep2Add = 0; /**< Value to add to PITCHSWEEP2 controller each cycle */
|
||||||
uint8_t m_pitchSweep1Times = 0; /**< Remaining times to advance PITCHSWEEP1 controller */
|
uint8_t m_pitchSweep1Times = 0; /**< Remaining times to advance PITCHSWEEP1 controller */
|
||||||
uint8_t m_pitchSweep2Times = 0; /**< Remaining times to advance PITCHSWEEP2 controller */
|
uint8_t m_pitchSweep2Times = 0; /**< Remaining times to advance PITCHSWEEP2 controller */
|
||||||
uint8_t m_pitchSweep1It = 0; /**< Current iteration of PITCHSWEEP1 controller */
|
uint8_t m_pitchSweep1It = 0; /**< Current iteration of PITCHSWEEP1 controller */
|
||||||
uint8_t m_pitchSweep2It = 0; /**< Current iteration of PITCHSWEEP2 controller */
|
uint8_t m_pitchSweep2It = 0; /**< Current iteration of PITCHSWEEP2 controller */
|
||||||
|
|
||||||
float m_panningTime = -1.f; /**< time since last PANNING command, -1 for no active pan-sweep */
|
float m_panningTime = -1.f; /**< time since last PANNING command, -1 for no active pan-sweep */
|
||||||
float m_panningDur; /**< requested duration of last PANNING command */
|
float m_panningDur; /**< requested duration of last PANNING command */
|
||||||
uint8_t m_panPos; /**< initial pan value of last PANNING command */
|
uint8_t m_panPos; /**< initial pan value of last PANNING command */
|
||||||
int8_t m_panWidth; /**< delta pan value to target of last PANNING command */
|
int8_t m_panWidth; /**< delta pan value to target of last PANNING command */
|
||||||
|
|
||||||
float m_spanningTime = -1.f; /**< time since last SPANNING command, -1 for no active span-sweep */
|
float m_spanningTime = -1.f; /**< time since last SPANNING command, -1 for no active span-sweep */
|
||||||
float m_spanningDur; /**< requested duration of last SPANNING command */
|
float m_spanningDur; /**< requested duration of last SPANNING command */
|
||||||
uint8_t m_spanPos; /**< initial pan value of last SPANNING command */
|
uint8_t m_spanPos; /**< initial pan value of last SPANNING command */
|
||||||
int8_t m_spanWidth; /**< delta pan value to target of last SPANNING command */
|
int8_t m_spanWidth; /**< delta pan value to target of last SPANNING command */
|
||||||
|
|
||||||
int32_t m_vibratoLevel = 0; /**< scale of vibrato effect (in cents) */
|
int32_t m_vibratoLevel = 0; /**< scale of vibrato effect (in cents) */
|
||||||
int32_t m_vibratoModLevel = 0; /**< scale of vibrato mod-wheel influence (in cents) */
|
int32_t m_vibratoModLevel = 0; /**< scale of vibrato mod-wheel influence (in cents) */
|
||||||
float m_vibratoPeriod = 0.f; /**< vibrato wave period-time, 0.f will disable vibrato */
|
float m_vibratoPeriod = 0.f; /**< vibrato wave period-time, 0.f will disable vibrato */
|
||||||
bool m_vibratoModWheel = false; /**< vibrato scaled with mod-wheel if set */
|
bool m_vibratoModWheel = false; /**< vibrato scaled with mod-wheel if set */
|
||||||
|
|
||||||
float m_tremoloScale = 0.f; /**< minimum volume factor produced via LFO */
|
float m_tremoloScale = 0.f; /**< minimum volume factor produced via LFO */
|
||||||
float m_tremoloModScale = 0.f; /**< minimum volume factor produced via LFO, scaled via mod wheel */
|
float m_tremoloModScale = 0.f; /**< minimum volume factor produced via LFO, scaled via mod wheel */
|
||||||
|
|
||||||
float m_lfoPeriods[2] = {}; /**< time-periods for LFO1 and LFO2 */
|
float m_lfoPeriods[2] = {}; /**< time-periods for LFO1 and LFO2 */
|
||||||
std::unique_ptr<int8_t[]> m_ctrlValsSelf; /**< Self-owned MIDI Controller values */
|
std::unique_ptr<int8_t[]> m_ctrlValsSelf; /**< Self-owned MIDI Controller values */
|
||||||
int8_t* m_extCtrlVals = nullptr; /**< MIDI Controller values (external storage) */
|
int8_t* m_extCtrlVals = nullptr; /**< MIDI Controller values (external storage) */
|
||||||
|
|
||||||
void _destroy();
|
void _destroy();
|
||||||
bool _checkSamplePos(bool& looped);
|
bool _checkSamplePos(bool& looped);
|
||||||
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,14 +185,20 @@ 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; }
|
||||||
|
|
||||||
/** Get current state of voice */
|
/** Get current state of voice */
|
||||||
VoiceState state() const {return m_voxState;}
|
VoiceState state() const { return m_voxState; }
|
||||||
|
|
||||||
/** Get VoiceId of this voice (unique to all currently-playing voices) */
|
/** Get VoiceId of this voice (unique to all currently-playing voices) */
|
||||||
int vid() const {return m_vid;}
|
int vid() const { return m_vid; }
|
||||||
|
|
||||||
/** Get max VoiceId of this voice and any contained children */
|
/** Get max VoiceId of this voice and any contained children */
|
||||||
int maxVid() const;
|
int maxVid() const;
|
||||||
|
@ -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();
|
||||||
|
@ -247,10 +262,10 @@ public:
|
||||||
void setTremolo(float tremoloScale, float tremoloModScale);
|
void setTremolo(float tremoloScale, float tremoloModScale);
|
||||||
|
|
||||||
/** Setup LFO1 for voice */
|
/** Setup LFO1 for voice */
|
||||||
void setLFO1Period(float period) {m_lfoPeriods[0] = period;}
|
void setLFO1Period(float period) { m_lfoPeriods[0] = period; }
|
||||||
|
|
||||||
/** Setup LFO2 for voice */
|
/** Setup LFO2 for voice */
|
||||||
void setLFO2Period(float period) {m_lfoPeriods[1] = period;}
|
void setLFO2Period(float period) { m_lfoPeriods[1] = period; }
|
||||||
|
|
||||||
/** Setup pitch sweep controller 1 */
|
/** Setup pitch sweep controller 1 */
|
||||||
void setPitchSweep1(uint8_t times, int16_t add);
|
void setPitchSweep1(uint8_t times, int16_t add);
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -280,10 +298,10 @@ public:
|
||||||
void setAftertouch(uint8_t aftertouch);
|
void setAftertouch(uint8_t aftertouch);
|
||||||
|
|
||||||
/** Assign voice to keygroup for coordinated mass-silencing */
|
/** Assign voice to keygroup for coordinated mass-silencing */
|
||||||
void setKeygroup(uint8_t kg) {m_keygroup = kg;}
|
void setKeygroup(uint8_t kg) { m_keygroup = kg; }
|
||||||
|
|
||||||
/** Get note played on voice */
|
/** Get note played on voice */
|
||||||
uint8_t getLastNote() const {return m_state.m_initKey;}
|
uint8_t getLastNote() const { return m_state.m_initKey; }
|
||||||
|
|
||||||
/** Do portamento glide; returns `false` if portamento disabled */
|
/** Do portamento glide; returns `false` if portamento disabled */
|
||||||
bool doPortamento(uint8_t newNote);
|
bool doPortamento(uint8_t newNote);
|
||||||
|
@ -321,19 +339,17 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Get MIDI pitch wheel value on voice */
|
/** Get MIDI pitch wheel value on voice */
|
||||||
float getPitchWheel() const {return m_curPitchWheel;}
|
float getPitchWheel() const { return m_curPitchWheel; }
|
||||||
|
|
||||||
/** Get MIDI aftertouch value on voice */
|
/** Get MIDI aftertouch value on voice */
|
||||||
int8_t getAftertouch() const {return m_curAftertouch;}
|
int8_t getAftertouch() const { return m_curAftertouch; }
|
||||||
|
|
||||||
/** Get count of all voices in hierarchy, including this one */
|
/** Get count of all voices in hierarchy, including this one */
|
||||||
size_t getTotalVoices() const;
|
size_t getTotalVoices() const;
|
||||||
|
|
||||||
/** 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__
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,10 +70,10 @@ AudioGroupPool::AudioGroupPool(const unsigned char* data)
|
||||||
ObjectId id = SBig(*reinterpret_cast<const ObjectId*>(cur + 4));
|
ObjectId id = SBig(*reinterpret_cast<const ObjectId*>(cur + 4));
|
||||||
std::vector<const LayerMapping*>& mappingsOut = m_layers[id];
|
std::vector<const LayerMapping*>& mappingsOut = m_layers[id];
|
||||||
|
|
||||||
uint32_t count = SBig(*reinterpret_cast<const uint32_t*>(cur+8));
|
uint32_t count = SBig(*reinterpret_cast<const uint32_t*>(cur + 8));
|
||||||
mappingsOut.reserve(count);
|
mappingsOut.reserve(count);
|
||||||
const unsigned char* subcur = cur + 12;
|
const unsigned char* subcur = cur + 12;
|
||||||
for (int i=0 ; i<count ; ++i)
|
for (int i = 0; i < count; ++i)
|
||||||
mappingsOut.push_back(reinterpret_cast<const LayerMapping*>(subcur + i * 12));
|
mappingsOut.push_back(reinterpret_cast<const LayerMapping*>(subcur + i * 12));
|
||||||
|
|
||||||
cur += size;
|
cur += size;
|
||||||
|
@ -130,10 +130,10 @@ AudioGroupPool::AudioGroupPool(const unsigned char* data, PCDataTag)
|
||||||
ObjectId id = *reinterpret_cast<const ObjectId*>(cur + 4);
|
ObjectId id = *reinterpret_cast<const ObjectId*>(cur + 4);
|
||||||
std::vector<const LayerMapping*>& mappingsOut = m_layers[id];
|
std::vector<const LayerMapping*>& mappingsOut = m_layers[id];
|
||||||
|
|
||||||
uint32_t count = *reinterpret_cast<const uint32_t*>(cur+8);
|
uint32_t count = *reinterpret_cast<const uint32_t*>(cur + 8);
|
||||||
mappingsOut.reserve(count);
|
mappingsOut.reserve(count);
|
||||||
const unsigned char* subcur = cur + 12;
|
const unsigned char* subcur = cur + 12;
|
||||||
for (int i=0 ; i<count ; ++i)
|
for (int i = 0; i < count; ++i)
|
||||||
mappingsOut.push_back(reinterpret_cast<const LayerMapping*>(subcur + i * 12));
|
mappingsOut.push_back(reinterpret_cast<const LayerMapping*>(subcur + i * 12));
|
||||||
|
|
||||||
cur += size;
|
cur += size;
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,7 +96,7 @@ AudioGroupProject::AudioGroupProject(const unsigned char* data, GCNDataTag)
|
||||||
idx.m_sfxEntries.reserve(count);
|
idx.m_sfxEntries.reserve(count);
|
||||||
const SFXGroupIndex::SFXEntry* entries =
|
const SFXGroupIndex::SFXEntry* entries =
|
||||||
reinterpret_cast<const SFXGroupIndex::SFXEntry*>(data + header.pageTableOff + 4);
|
reinterpret_cast<const SFXGroupIndex::SFXEntry*>(data + header.pageTableOff + 4);
|
||||||
for (int i=0 ; i<count ; ++i)
|
for (int i = 0; i < count; ++i)
|
||||||
{
|
{
|
||||||
idx.m_sfxEntries[SBig(entries->defineId)] = entries;
|
idx.m_sfxEntries[SBig(entries->defineId)] = entries;
|
||||||
++entries;
|
++entries;
|
||||||
|
@ -208,7 +208,7 @@ void AudioGroupProject::_allocateConvBuffers(const unsigned char* data, bool abs
|
||||||
if (drumPageCount)
|
if (drumPageCount)
|
||||||
m_convDrumPages.reset(new SongGroupIndex::PageEntry[drumPageCount]);
|
m_convDrumPages.reset(new SongGroupIndex::PageEntry[drumPageCount]);
|
||||||
if (midiSetupCount)
|
if (midiSetupCount)
|
||||||
m_convMidiSetups.reset(new std::array<SongGroupIndex::MIDISetup, 16>[midiSetupCount]);
|
m_convMidiSetups.reset(new std::array<SongGroupIndex::MIDISetup, 16>[ midiSetupCount ]);
|
||||||
}
|
}
|
||||||
|
|
||||||
AudioGroupProject::AudioGroupProject(const unsigned char* data, bool absOffs, N64DataTag)
|
AudioGroupProject::AudioGroupProject(const unsigned char* data, bool absOffs, N64DataTag)
|
||||||
|
@ -262,7 +262,7 @@ AudioGroupProject::AudioGroupProject(const unsigned char* data, bool absOffs, N6
|
||||||
const std::array<MusyX1MIDISetup, 16>* midiSetups =
|
const std::array<MusyX1MIDISetup, 16>* midiSetups =
|
||||||
reinterpret_cast<const std::array<MusyX1MIDISetup, 16>*>(setupData + 4);
|
reinterpret_cast<const std::array<MusyX1MIDISetup, 16>*>(setupData + 4);
|
||||||
|
|
||||||
for (int i=0 ; i<16 ; ++i)
|
for (int i = 0; i < 16; ++i)
|
||||||
(*midiSetups)[i].setIntoMusyX2((*midiSetupsBuf)[i]);
|
(*midiSetups)[i].setIntoMusyX2((*midiSetupsBuf)[i]);
|
||||||
|
|
||||||
idx.m_midiSetups[songId] = midiSetupsBuf;
|
idx.m_midiSetups[songId] = midiSetupsBuf;
|
||||||
|
@ -278,7 +278,7 @@ AudioGroupProject::AudioGroupProject(const unsigned char* data, bool absOffs, N6
|
||||||
/* SFX entries */
|
/* SFX entries */
|
||||||
uint16_t count = SBig(*reinterpret_cast<const uint16_t*>(subData + header.pageTableOff));
|
uint16_t count = SBig(*reinterpret_cast<const uint16_t*>(subData + header.pageTableOff));
|
||||||
idx.m_sfxEntries.reserve(count);
|
idx.m_sfxEntries.reserve(count);
|
||||||
for (int i=0 ; i<count ; ++i)
|
for (int i = 0; i < count; ++i)
|
||||||
{
|
{
|
||||||
const SFXGroupIndex::SFXEntry* entries =
|
const SFXGroupIndex::SFXEntry* entries =
|
||||||
reinterpret_cast<const SFXGroupIndex::SFXEntry*>(subData + header.pageTableOff + 4 + i * 12);
|
reinterpret_cast<const SFXGroupIndex::SFXEntry*>(subData + header.pageTableOff + 4 + i * 12);
|
||||||
|
@ -319,7 +319,7 @@ void AudioGroupProject::_allocateConvBuffers(const unsigned char* data, bool abs
|
||||||
{
|
{
|
||||||
/* Normal pages */
|
/* Normal pages */
|
||||||
const MusyX1PageEntry* normEntries =
|
const MusyX1PageEntry* normEntries =
|
||||||
reinterpret_cast<const MusyX1PageEntry*>(subData + group->pageTableOff);
|
reinterpret_cast<const MusyX1PageEntry*>(subData + group->pageTableOff);
|
||||||
while (normEntries->objId != 0xffff)
|
while (normEntries->objId != 0xffff)
|
||||||
{
|
{
|
||||||
++normPageCount;
|
++normPageCount;
|
||||||
|
@ -328,7 +328,7 @@ void AudioGroupProject::_allocateConvBuffers(const unsigned char* data, bool abs
|
||||||
|
|
||||||
/* Drum pages */
|
/* Drum pages */
|
||||||
const MusyX1PageEntry* drumEntries =
|
const MusyX1PageEntry* drumEntries =
|
||||||
reinterpret_cast<const MusyX1PageEntry*>(subData + group->drumTableOff);
|
reinterpret_cast<const MusyX1PageEntry*>(subData + group->drumTableOff);
|
||||||
while (drumEntries->objId != 0xffff)
|
while (drumEntries->objId != 0xffff)
|
||||||
{
|
{
|
||||||
++drumPageCount;
|
++drumPageCount;
|
||||||
|
@ -358,7 +358,7 @@ void AudioGroupProject::_allocateConvBuffers(const unsigned char* data, bool abs
|
||||||
if (drumPageCount)
|
if (drumPageCount)
|
||||||
m_convDrumPages.reset(new SongGroupIndex::PageEntry[drumPageCount]);
|
m_convDrumPages.reset(new SongGroupIndex::PageEntry[drumPageCount]);
|
||||||
if (midiSetupCount)
|
if (midiSetupCount)
|
||||||
m_convMidiSetups.reset(new std::array<SongGroupIndex::MIDISetup, 16>[midiSetupCount]);
|
m_convMidiSetups.reset(new std::array<SongGroupIndex::MIDISetup, 16>[ midiSetupCount ]);
|
||||||
}
|
}
|
||||||
|
|
||||||
AudioGroupProject::AudioGroupProject(const unsigned char* data, bool absOffs, PCDataTag)
|
AudioGroupProject::AudioGroupProject(const unsigned char* data, bool absOffs, PCDataTag)
|
||||||
|
@ -410,7 +410,7 @@ AudioGroupProject::AudioGroupProject(const unsigned char* data, bool absOffs, PC
|
||||||
const std::array<MusyX1MIDISetup, 16>* midiSetups =
|
const std::array<MusyX1MIDISetup, 16>* midiSetups =
|
||||||
reinterpret_cast<const std::array<MusyX1MIDISetup, 16>*>(setupData + 4);
|
reinterpret_cast<const std::array<MusyX1MIDISetup, 16>*>(setupData + 4);
|
||||||
|
|
||||||
for (int i=0 ; i<16 ; ++i)
|
for (int i = 0; i < 16; ++i)
|
||||||
(*midiSetups)[i].setIntoMusyX2((*midiSetupsBuf)[i]);
|
(*midiSetups)[i].setIntoMusyX2((*midiSetupsBuf)[i]);
|
||||||
|
|
||||||
idx.m_midiSetups[songId] = midiSetupsBuf;
|
idx.m_midiSetups[songId] = midiSetupsBuf;
|
||||||
|
@ -426,10 +426,10 @@ AudioGroupProject::AudioGroupProject(const unsigned char* data, bool absOffs, PC
|
||||||
/* SFX entries */
|
/* SFX entries */
|
||||||
uint16_t count = *reinterpret_cast<const uint16_t*>(subData + group->pageTableOff);
|
uint16_t count = *reinterpret_cast<const uint16_t*>(subData + group->pageTableOff);
|
||||||
idx.m_sfxEntries.reserve(count);
|
idx.m_sfxEntries.reserve(count);
|
||||||
for (int i=0 ; i<count ; ++i)
|
for (int i = 0; i < count; ++i)
|
||||||
{
|
{
|
||||||
const SFXGroupIndex::SFXEntry* entries =
|
const SFXGroupIndex::SFXEntry* entries =
|
||||||
reinterpret_cast<const SFXGroupIndex::SFXEntry*>(subData + group->pageTableOff + 4 + i * 12);
|
reinterpret_cast<const SFXGroupIndex::SFXEntry*>(subData + group->pageTableOff + 4 + i * 12);
|
||||||
idx.m_sfxEntries[entries->defineId] = entries;
|
idx.m_sfxEntries[entries->defineId] = entries;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -481,5 +481,4 @@ const SFXGroupIndex* AudioGroupProject::getSFXGroupIndex(int groupId) const
|
||||||
return nullptr;
|
return nullptr;
|
||||||
return &search->second;
|
return &search->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ void AudioGroupSampleDirectory::ADPCMParms::swapBigDSP()
|
||||||
dsp.m_bytesPerFrame = SBig(dsp.m_bytesPerFrame);
|
dsp.m_bytesPerFrame = SBig(dsp.m_bytesPerFrame);
|
||||||
dsp.m_hist2 = SBig(dsp.m_hist2);
|
dsp.m_hist2 = SBig(dsp.m_hist2);
|
||||||
dsp.m_hist1 = SBig(dsp.m_hist1);
|
dsp.m_hist1 = SBig(dsp.m_hist1);
|
||||||
for (int i=0 ; i<8 ; ++i)
|
for (int i = 0; i < 8; ++i)
|
||||||
{
|
{
|
||||||
dsp.m_coefs[i][0] = SBig(dsp.m_coefs[i][0]);
|
dsp.m_coefs[i][0] = SBig(dsp.m_coefs[i][0]);
|
||||||
dsp.m_coefs[i][1] = SBig(dsp.m_coefs[i][1]);
|
dsp.m_coefs[i][1] = SBig(dsp.m_coefs[i][1]);
|
||||||
|
@ -32,7 +32,7 @@ void AudioGroupSampleDirectory::ADPCMParms::swapBigDSP()
|
||||||
void AudioGroupSampleDirectory::ADPCMParms::swapBigVADPCM()
|
void AudioGroupSampleDirectory::ADPCMParms::swapBigVADPCM()
|
||||||
{
|
{
|
||||||
int16_t* allCoefs = reinterpret_cast<int16_t*>(vadpcm.m_coefs[0][0]);
|
int16_t* allCoefs = reinterpret_cast<int16_t*>(vadpcm.m_coefs[0][0]);
|
||||||
for (int i=0 ; i<128 ; ++i)
|
for (int i = 0; i < 128; ++i)
|
||||||
allCoefs[i] = SBig(allCoefs[i]);
|
allCoefs[i] = SBig(allCoefs[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,14 +137,15 @@ 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;
|
||||||
|
|
||||||
/* Determine range of buffer updates within this period */
|
/* Determine range of buffer updates within this period */
|
||||||
auto periodEnd = m_queue.cbegin();
|
auto periodEnd = m_queue.cbegin();
|
||||||
double startPt = m_queue.front().first;
|
double startPt = m_queue.front().first;
|
||||||
for (; periodEnd != m_queue.cend() ; ++periodEnd)
|
for (; periodEnd != m_queue.cend(); ++periodEnd)
|
||||||
{
|
{
|
||||||
double delta = periodEnd->first - startPt;
|
double delta = periodEnd->first - startPt;
|
||||||
if (delta > dt)
|
if (delta > dt)
|
||||||
|
@ -170,7 +156,7 @@ void BooBackendMIDIReader::pumpReader(double dt)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Dispatch buffers */
|
/* Dispatch buffers */
|
||||||
for (auto it = m_queue.begin() ; it != periodEnd ;)
|
for (auto it = m_queue.begin(); it != periodEnd;)
|
||||||
{
|
{
|
||||||
#if 0
|
#if 0
|
||||||
char str[64];
|
char str[64];
|
||||||
|
@ -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(); }
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,21 +12,21 @@
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <Stringapiset.h>
|
#include <Stringapiset.h>
|
||||||
|
|
||||||
static void *memmem(const void *haystack, size_t hlen, const void *needle, size_t nlen)
|
static void* memmem(const void* haystack, size_t hlen, const void* needle, size_t nlen)
|
||||||
{
|
{
|
||||||
int needle_first;
|
int needle_first;
|
||||||
const uint8_t *p = static_cast<const uint8_t*>(haystack);
|
const uint8_t* p = static_cast<const uint8_t*>(haystack);
|
||||||
size_t plen = hlen;
|
size_t plen = hlen;
|
||||||
|
|
||||||
if (!nlen)
|
if (!nlen)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
needle_first = *(unsigned char *)needle;
|
needle_first = *(unsigned char*)needle;
|
||||||
|
|
||||||
while (plen >= nlen && (p = static_cast<const uint8_t*>(memchr(p, needle_first, plen - nlen + 1))))
|
while (plen >= nlen && (p = static_cast<const uint8_t*>(memchr(p, needle_first, plen - nlen + 1))))
|
||||||
{
|
{
|
||||||
if (!memcmp(p, needle, nlen))
|
if (!memcmp(p, needle, nlen))
|
||||||
return (void *)p;
|
return (void*)p;
|
||||||
|
|
||||||
p++;
|
p++;
|
||||||
plen = hlen - (p - static_cast<const uint8_t*>(haystack));
|
plen = hlen - (p - static_cast<const uint8_t*>(haystack));
|
||||||
|
@ -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;
|
||||||
|
@ -153,7 +145,7 @@ static bool ValidateMP1(FILE* fp)
|
||||||
uint32_t nameCount;
|
uint32_t nameCount;
|
||||||
fread(&nameCount, 1, 4, fp);
|
fread(&nameCount, 1, 4, fp);
|
||||||
nameCount = SBig(nameCount);
|
nameCount = SBig(nameCount);
|
||||||
for (uint32_t i=0 ; i<nameCount ; ++i)
|
for (uint32_t i = 0; i < nameCount; ++i)
|
||||||
{
|
{
|
||||||
FSeek(fp, 8, SEEK_CUR);
|
FSeek(fp, 8, SEEK_CUR);
|
||||||
uint32_t nameLen;
|
uint32_t nameLen;
|
||||||
|
@ -165,7 +157,7 @@ static bool ValidateMP1(FILE* fp)
|
||||||
uint32_t resCount;
|
uint32_t resCount;
|
||||||
fread(&resCount, 1, 4, fp);
|
fread(&resCount, 1, 4, fp);
|
||||||
resCount = SBig(resCount);
|
resCount = SBig(resCount);
|
||||||
for (uint32_t i=0 ; i<resCount ; ++i)
|
for (uint32_t i = 0; i < resCount; ++i)
|
||||||
{
|
{
|
||||||
FSeek(fp, 4, SEEK_CUR);
|
FSeek(fp, 4, SEEK_CUR);
|
||||||
uint32_t type;
|
uint32_t type;
|
||||||
|
@ -212,7 +204,7 @@ static std::vector<std::pair<SystemString, IntrusiveAudioGroupData>> LoadMP1(FIL
|
||||||
uint32_t nameCount;
|
uint32_t nameCount;
|
||||||
fread(&nameCount, 1, 4, fp);
|
fread(&nameCount, 1, 4, fp);
|
||||||
nameCount = SBig(nameCount);
|
nameCount = SBig(nameCount);
|
||||||
for (uint32_t i=0 ; i<nameCount ; ++i)
|
for (uint32_t i = 0; i < nameCount; ++i)
|
||||||
{
|
{
|
||||||
FSeek(fp, 8, SEEK_CUR);
|
FSeek(fp, 8, SEEK_CUR);
|
||||||
uint32_t nameLen;
|
uint32_t nameLen;
|
||||||
|
@ -225,7 +217,7 @@ static std::vector<std::pair<SystemString, IntrusiveAudioGroupData>> LoadMP1(FIL
|
||||||
fread(&resCount, 1, 4, fp);
|
fread(&resCount, 1, 4, fp);
|
||||||
resCount = SBig(resCount);
|
resCount = SBig(resCount);
|
||||||
ret.reserve(resCount);
|
ret.reserve(resCount);
|
||||||
for (uint32_t i=0 ; i<resCount ; ++i)
|
for (uint32_t i = 0; i < resCount; ++i)
|
||||||
{
|
{
|
||||||
FSeek(fp, 4, SEEK_CUR);
|
FSeek(fp, 4, SEEK_CUR);
|
||||||
uint32_t type;
|
uint32_t type;
|
||||||
|
@ -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);
|
||||||
|
@ -303,7 +295,7 @@ static bool ValidateMP1Songs(FILE* fp)
|
||||||
uint32_t nameCount;
|
uint32_t nameCount;
|
||||||
fread(&nameCount, 1, 4, fp);
|
fread(&nameCount, 1, 4, fp);
|
||||||
nameCount = SBig(nameCount);
|
nameCount = SBig(nameCount);
|
||||||
for (uint32_t i=0 ; i<nameCount ; ++i)
|
for (uint32_t i = 0; i < nameCount; ++i)
|
||||||
{
|
{
|
||||||
FSeek(fp, 8, SEEK_CUR);
|
FSeek(fp, 8, SEEK_CUR);
|
||||||
uint32_t nameLen;
|
uint32_t nameLen;
|
||||||
|
@ -315,7 +307,7 @@ static bool ValidateMP1Songs(FILE* fp)
|
||||||
uint32_t resCount;
|
uint32_t resCount;
|
||||||
fread(&resCount, 1, 4, fp);
|
fread(&resCount, 1, 4, fp);
|
||||||
resCount = SBig(resCount);
|
resCount = SBig(resCount);
|
||||||
for (uint32_t i=0 ; i<resCount ; ++i)
|
for (uint32_t i = 0; i < resCount; ++i)
|
||||||
{
|
{
|
||||||
FSeek(fp, 4, SEEK_CUR);
|
FSeek(fp, 4, SEEK_CUR);
|
||||||
uint32_t type;
|
uint32_t type;
|
||||||
|
@ -353,7 +345,7 @@ static std::vector<std::pair<SystemString, ContainerRegistry::SongData>> LoadMP1
|
||||||
|
|
||||||
std::unordered_map<uint32_t, SystemString> names;
|
std::unordered_map<uint32_t, SystemString> names;
|
||||||
names.reserve(nameCount);
|
names.reserve(nameCount);
|
||||||
for (uint32_t i=0 ; i<nameCount ; ++i)
|
for (uint32_t i = 0; i < nameCount; ++i)
|
||||||
{
|
{
|
||||||
FSeek(fp, 4, SEEK_CUR);
|
FSeek(fp, 4, SEEK_CUR);
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
|
@ -371,7 +363,7 @@ static std::vector<std::pair<SystemString, ContainerRegistry::SongData>> LoadMP1
|
||||||
fread(&resCount, 1, 4, fp);
|
fread(&resCount, 1, 4, fp);
|
||||||
resCount = SBig(resCount);
|
resCount = SBig(resCount);
|
||||||
ret.reserve(resCount);
|
ret.reserve(resCount);
|
||||||
for (uint32_t i=0 ; i<resCount ; ++i)
|
for (uint32_t i = 0; i < resCount; ++i)
|
||||||
{
|
{
|
||||||
FSeek(fp, 4, SEEK_CUR);
|
FSeek(fp, 4, SEEK_CUR);
|
||||||
uint32_t type;
|
uint32_t type;
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -445,7 +436,7 @@ static bool ValidateMP2(FILE* fp)
|
||||||
uint32_t nameCount;
|
uint32_t nameCount;
|
||||||
fread(&nameCount, 1, 4, fp);
|
fread(&nameCount, 1, 4, fp);
|
||||||
nameCount = SBig(nameCount);
|
nameCount = SBig(nameCount);
|
||||||
for (uint32_t i=0 ; i<nameCount ; ++i)
|
for (uint32_t i = 0; i < nameCount; ++i)
|
||||||
{
|
{
|
||||||
FSeek(fp, 8, SEEK_CUR);
|
FSeek(fp, 8, SEEK_CUR);
|
||||||
uint32_t nameLen;
|
uint32_t nameLen;
|
||||||
|
@ -457,7 +448,7 @@ static bool ValidateMP2(FILE* fp)
|
||||||
uint32_t resCount;
|
uint32_t resCount;
|
||||||
fread(&resCount, 1, 4, fp);
|
fread(&resCount, 1, 4, fp);
|
||||||
resCount = SBig(resCount);
|
resCount = SBig(resCount);
|
||||||
for (uint32_t i=0 ; i<resCount ; ++i)
|
for (uint32_t i = 0; i < resCount; ++i)
|
||||||
{
|
{
|
||||||
FSeek(fp, 4, SEEK_CUR);
|
FSeek(fp, 4, SEEK_CUR);
|
||||||
uint32_t type;
|
uint32_t type;
|
||||||
|
@ -504,7 +495,7 @@ static std::vector<std::pair<SystemString, IntrusiveAudioGroupData>> LoadMP2(FIL
|
||||||
uint32_t nameCount;
|
uint32_t nameCount;
|
||||||
fread(&nameCount, 1, 4, fp);
|
fread(&nameCount, 1, 4, fp);
|
||||||
nameCount = SBig(nameCount);
|
nameCount = SBig(nameCount);
|
||||||
for (uint32_t i=0 ; i<nameCount ; ++i)
|
for (uint32_t i = 0; i < nameCount; ++i)
|
||||||
{
|
{
|
||||||
FSeek(fp, 8, SEEK_CUR);
|
FSeek(fp, 8, SEEK_CUR);
|
||||||
uint32_t nameLen;
|
uint32_t nameLen;
|
||||||
|
@ -517,7 +508,7 @@ static std::vector<std::pair<SystemString, IntrusiveAudioGroupData>> LoadMP2(FIL
|
||||||
fread(&resCount, 1, 4, fp);
|
fread(&resCount, 1, 4, fp);
|
||||||
resCount = SBig(resCount);
|
resCount = SBig(resCount);
|
||||||
ret.reserve(resCount);
|
ret.reserve(resCount);
|
||||||
for (uint32_t i=0 ; i<resCount ; ++i)
|
for (uint32_t i = 0; i < resCount; ++i)
|
||||||
{
|
{
|
||||||
FSeek(fp, 4, SEEK_CUR);
|
FSeek(fp, 4, SEEK_CUR);
|
||||||
uint32_t type;
|
uint32_t type;
|
||||||
|
@ -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{}});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -608,14 +599,14 @@ struct RS1FSTEntry
|
||||||
static void SwapN64Rom16(void* data, size_t size)
|
static void SwapN64Rom16(void* data, size_t size)
|
||||||
{
|
{
|
||||||
uint16_t* words = reinterpret_cast<uint16_t*>(data);
|
uint16_t* words = reinterpret_cast<uint16_t*>(data);
|
||||||
for (size_t i=0 ; i<size/2 ; ++i)
|
for (size_t i = 0; i < size / 2; ++i)
|
||||||
words[i] = SBig(words[i]);
|
words[i] = SBig(words[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SwapN64Rom32(void* data, size_t size)
|
static void SwapN64Rom32(void* data, size_t size)
|
||||||
{
|
{
|
||||||
uint32_t* words = reinterpret_cast<uint32_t*>(data);
|
uint32_t* words = reinterpret_cast<uint32_t*>(data);
|
||||||
for (size_t i=0 ; i<size/4 ; ++i)
|
for (size_t i = 0; i < size / 4; ++i)
|
||||||
words[i] = SBig(words[i]);
|
words[i] = SBig(words[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -637,7 +628,7 @@ static bool ValidateRS1PC(FILE* fp)
|
||||||
fread(entries.get(), fstSz, 1, fp);
|
fread(entries.get(), fstSz, 1, fp);
|
||||||
|
|
||||||
uint8_t foundComps = 0;
|
uint8_t foundComps = 0;
|
||||||
for (uint32_t i=0 ; i<elemCount ; ++i)
|
for (uint32_t i = 0; i < elemCount; ++i)
|
||||||
{
|
{
|
||||||
RS1FSTEntry& entry = entries[i];
|
RS1FSTEntry& entry = entries[i];
|
||||||
if (!strncmp("proj_SND", entry.name, 16))
|
if (!strncmp("proj_SND", entry.name, 16))
|
||||||
|
@ -683,7 +674,7 @@ static std::vector<std::pair<SystemString, IntrusiveAudioGroupData>> LoadRS1PC(F
|
||||||
std::unique_ptr<uint8_t[]> samp;
|
std::unique_ptr<uint8_t[]> samp;
|
||||||
size_t sampSz = 0;
|
size_t sampSz = 0;
|
||||||
|
|
||||||
for (uint32_t i=0 ; i<elemCount ; ++i)
|
for (uint32_t i = 0; i < elemCount; ++i)
|
||||||
{
|
{
|
||||||
RS1FSTEntry& entry = entries[i];
|
RS1FSTEntry& entry = entries[i];
|
||||||
if (!strncmp("proj_SND", entry.name, 16))
|
if (!strncmp("proj_SND", entry.name, 16))
|
||||||
|
@ -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{}});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -741,7 +732,7 @@ static std::vector<std::pair<SystemString, ContainerRegistry::SongData>> LoadRS1
|
||||||
std::unique_ptr<RS1FSTEntry[]> entries(new RS1FSTEntry[elemCount]);
|
std::unique_ptr<RS1FSTEntry[]> entries(new RS1FSTEntry[elemCount]);
|
||||||
fread(entries.get(), fstSz, 1, fp);
|
fread(entries.get(), fstSz, 1, fp);
|
||||||
|
|
||||||
for (uint32_t i=0 ; i<elemCount ; ++i)
|
for (uint32_t i = 0; i < elemCount; ++i)
|
||||||
{
|
{
|
||||||
RS1FSTEntry& entry = entries[i];
|
RS1FSTEntry& entry = entries[i];
|
||||||
if (strstr(entry.name, "SNG"))
|
if (strstr(entry.name, "SNG"))
|
||||||
|
@ -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;
|
||||||
|
@ -795,7 +786,7 @@ static bool ValidateRS1N64(FILE* fp)
|
||||||
const RS1FSTEntry* lastEnt = reinterpret_cast<const RS1FSTEntry*>(dataSeg + fstEnd);
|
const RS1FSTEntry* lastEnt = reinterpret_cast<const RS1FSTEntry*>(dataSeg + fstEnd);
|
||||||
|
|
||||||
uint8_t foundComps = 0;
|
uint8_t foundComps = 0;
|
||||||
for (; entry != lastEnt ; ++entry)
|
for (; entry != lastEnt; ++entry)
|
||||||
{
|
{
|
||||||
if (!strncmp("proj_SND", entry->name, 16))
|
if (!strncmp("proj_SND", entry->name, 16))
|
||||||
foundComps |= 1;
|
foundComps |= 1;
|
||||||
|
@ -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;
|
||||||
|
@ -850,7 +841,7 @@ static std::vector<std::pair<SystemString, IntrusiveAudioGroupData>> LoadRS1N64(
|
||||||
std::unique_ptr<uint8_t[]> samp;
|
std::unique_ptr<uint8_t[]> samp;
|
||||||
size_t sampSz = 0;
|
size_t sampSz = 0;
|
||||||
|
|
||||||
for (; entry != lastEnt ; ++entry)
|
for (; entry != lastEnt; ++entry)
|
||||||
{
|
{
|
||||||
RS1FSTEntry ent = *entry;
|
RS1FSTEntry ent = *entry;
|
||||||
ent.swapBig();
|
ent.swapBig();
|
||||||
|
@ -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;
|
||||||
|
@ -952,7 +943,7 @@ static std::vector<std::pair<SystemString, ContainerRegistry::SongData>> LoadRS1
|
||||||
const RS1FSTEntry* entry = reinterpret_cast<const RS1FSTEntry*>(dataSeg + fstOff);
|
const RS1FSTEntry* entry = reinterpret_cast<const RS1FSTEntry*>(dataSeg + fstOff);
|
||||||
const RS1FSTEntry* lastEnt = reinterpret_cast<const RS1FSTEntry*>(dataSeg + fstEnd);
|
const RS1FSTEntry* lastEnt = reinterpret_cast<const RS1FSTEntry*>(dataSeg + fstEnd);
|
||||||
|
|
||||||
for (; entry != lastEnt ; ++entry)
|
for (; entry != lastEnt; ++entry)
|
||||||
{
|
{
|
||||||
RS1FSTEntry ent = *entry;
|
RS1FSTEntry ent = *entry;
|
||||||
ent.swapBig();
|
ent.swapBig();
|
||||||
|
@ -998,7 +989,7 @@ static bool ValidateBFNPC(FILE* fp)
|
||||||
fread(entries.get(), fstSz, 1, fp);
|
fread(entries.get(), fstSz, 1, fp);
|
||||||
|
|
||||||
uint8_t foundComps = 0;
|
uint8_t foundComps = 0;
|
||||||
for (uint32_t i=0 ; i<elemCount ; ++i)
|
for (uint32_t i = 0; i < elemCount; ++i)
|
||||||
{
|
{
|
||||||
RS1FSTEntry& entry = entries[i];
|
RS1FSTEntry& entry = entries[i];
|
||||||
if (!strncmp("proj", entry.name, 16))
|
if (!strncmp("proj", entry.name, 16))
|
||||||
|
@ -1044,7 +1035,7 @@ static std::vector<std::pair<SystemString, IntrusiveAudioGroupData>> LoadBFNPC(F
|
||||||
std::unique_ptr<uint8_t[]> samp;
|
std::unique_ptr<uint8_t[]> samp;
|
||||||
size_t sampSz = 0;
|
size_t sampSz = 0;
|
||||||
|
|
||||||
for (uint32_t i=0 ; i<elemCount ; ++i)
|
for (uint32_t i = 0; i < elemCount; ++i)
|
||||||
{
|
{
|
||||||
RS1FSTEntry& entry = entries[i];
|
RS1FSTEntry& entry = entries[i];
|
||||||
if (!strncmp("proj", entry.name, 16))
|
if (!strncmp("proj", entry.name, 16))
|
||||||
|
@ -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{}});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1102,7 +1093,7 @@ static std::vector<std::pair<SystemString, ContainerRegistry::SongData>> LoadBFN
|
||||||
std::unique_ptr<RS1FSTEntry[]> entries(new RS1FSTEntry[elemCount]);
|
std::unique_ptr<RS1FSTEntry[]> entries(new RS1FSTEntry[elemCount]);
|
||||||
fread(entries.get(), fstSz, 1, fp);
|
fread(entries.get(), fstSz, 1, fp);
|
||||||
|
|
||||||
for (uint32_t i=0 ; i<elemCount ; ++i)
|
for (uint32_t i = 0; i < elemCount; ++i)
|
||||||
{
|
{
|
||||||
RS1FSTEntry& entry = entries[i];
|
RS1FSTEntry& entry = entries[i];
|
||||||
if (!strncmp(entry.name, "s_", 2))
|
if (!strncmp(entry.name, "s_", 2))
|
||||||
|
@ -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;
|
||||||
|
@ -1156,7 +1147,7 @@ static bool ValidateBFNN64(FILE* fp)
|
||||||
const RS1FSTEntry* lastEnt = reinterpret_cast<const RS1FSTEntry*>(dataSeg + fstEnd);
|
const RS1FSTEntry* lastEnt = reinterpret_cast<const RS1FSTEntry*>(dataSeg + fstEnd);
|
||||||
|
|
||||||
uint8_t foundComps = 0;
|
uint8_t foundComps = 0;
|
||||||
for (; entry != lastEnt ; ++entry)
|
for (; entry != lastEnt; ++entry)
|
||||||
{
|
{
|
||||||
if (!strncmp("proj", entry->name, 16))
|
if (!strncmp("proj", entry->name, 16))
|
||||||
foundComps |= 1;
|
foundComps |= 1;
|
||||||
|
@ -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;
|
||||||
|
@ -1211,7 +1202,7 @@ static std::vector<std::pair<SystemString, IntrusiveAudioGroupData>> LoadBFNN64(
|
||||||
std::unique_ptr<uint8_t[]> samp;
|
std::unique_ptr<uint8_t[]> samp;
|
||||||
size_t sampSz = 0;
|
size_t sampSz = 0;
|
||||||
|
|
||||||
for (; entry != lastEnt ; ++entry)
|
for (; entry != lastEnt; ++entry)
|
||||||
{
|
{
|
||||||
RS1FSTEntry ent = *entry;
|
RS1FSTEntry ent = *entry;
|
||||||
ent.swapBig();
|
ent.swapBig();
|
||||||
|
@ -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;
|
||||||
|
@ -1313,7 +1304,7 @@ static std::vector<std::pair<SystemString, ContainerRegistry::SongData>> LoadBFN
|
||||||
const RS1FSTEntry* entry = reinterpret_cast<const RS1FSTEntry*>(dataSeg + fstOff);
|
const RS1FSTEntry* entry = reinterpret_cast<const RS1FSTEntry*>(dataSeg + fstOff);
|
||||||
const RS1FSTEntry* lastEnt = reinterpret_cast<const RS1FSTEntry*>(dataSeg + fstEnd);
|
const RS1FSTEntry* lastEnt = reinterpret_cast<const RS1FSTEntry*>(dataSeg + fstEnd);
|
||||||
|
|
||||||
for (; entry != lastEnt ; ++entry)
|
for (; entry != lastEnt; ++entry)
|
||||||
{
|
{
|
||||||
RS1FSTEntry ent = *entry;
|
RS1FSTEntry ent = *entry;
|
||||||
ent.swapBig();
|
ent.swapBig();
|
||||||
|
@ -1427,7 +1418,7 @@ static bool ValidateRS2(FILE* fp)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
FSeek(fp, int64_t(fstOff), SEEK_SET);
|
FSeek(fp, int64_t(fstOff), SEEK_SET);
|
||||||
for (size_t i=0 ; i<fstSz/64 ; ++i)
|
for (size_t i = 0; i < fstSz / 64; ++i)
|
||||||
{
|
{
|
||||||
RS2FSTEntry entry;
|
RS2FSTEntry entry;
|
||||||
fread(&entry, 1, 64, fp);
|
fread(&entry, 1, 64, fp);
|
||||||
|
@ -1457,7 +1448,7 @@ static std::vector<std::pair<SystemString, IntrusiveAudioGroupData>> LoadRS2(FIL
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
FSeek(fp, int64_t(fstOff), SEEK_SET);
|
FSeek(fp, int64_t(fstOff), SEEK_SET);
|
||||||
for (size_t i=0 ; i<fstSz/64 ; ++i)
|
for (size_t i = 0; i < fstSz / 64; ++i)
|
||||||
{
|
{
|
||||||
RS2FSTEntry entry;
|
RS2FSTEntry entry;
|
||||||
fread(&entry, 1, 64, fp);
|
fread(&entry, 1, 64, fp);
|
||||||
|
@ -1472,7 +1463,7 @@ static std::vector<std::pair<SystemString, IntrusiveAudioGroupData>> LoadRS2(FIL
|
||||||
uint32_t groupCount = SBig(*reinterpret_cast<uint32_t*>(audData.get() + indexOff));
|
uint32_t groupCount = SBig(*reinterpret_cast<uint32_t*>(audData.get() + indexOff));
|
||||||
const uint32_t* groupOffs = reinterpret_cast<const uint32_t*>(audData.get() + indexOff + 4);
|
const uint32_t* groupOffs = reinterpret_cast<const uint32_t*>(audData.get() + indexOff + 4);
|
||||||
|
|
||||||
for (uint32_t j=0 ; j<groupCount ; ++j)
|
for (uint32_t j = 0; j < groupCount; ++j)
|
||||||
{
|
{
|
||||||
const uint8_t* groupData = audData.get() + SBig(groupOffs[j]);
|
const uint8_t* groupData = audData.get() + SBig(groupOffs[j]);
|
||||||
RS23GroupHead head = *reinterpret_cast<const RS23GroupHead*>(groupData);
|
RS23GroupHead head = *reinterpret_cast<const RS23GroupHead*>(groupData);
|
||||||
|
@ -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{}});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1522,7 +1514,7 @@ static std::vector<std::pair<SystemString, ContainerRegistry::SongData>> LoadRS2
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
FSeek(fp, int64_t(fstOff), SEEK_SET);
|
FSeek(fp, int64_t(fstOff), SEEK_SET);
|
||||||
for (size_t i=0 ; i<fstSz/64 ; ++i)
|
for (size_t i = 0; i < fstSz / 64; ++i)
|
||||||
{
|
{
|
||||||
RS2FSTEntry entry;
|
RS2FSTEntry entry;
|
||||||
fread(&entry, 1, 64, fp);
|
fread(&entry, 1, 64, fp);
|
||||||
|
@ -1537,7 +1529,7 @@ static std::vector<std::pair<SystemString, ContainerRegistry::SongData>> LoadRS2
|
||||||
uint32_t groupCount = SBig(*reinterpret_cast<uint32_t*>(audData.get() + indexOff));
|
uint32_t groupCount = SBig(*reinterpret_cast<uint32_t*>(audData.get() + indexOff));
|
||||||
const uint32_t* groupOffs = reinterpret_cast<const uint32_t*>(audData.get() + indexOff + 4);
|
const uint32_t* groupOffs = reinterpret_cast<const uint32_t*>(audData.get() + indexOff + 4);
|
||||||
|
|
||||||
for (uint32_t j=0 ; j<groupCount ; ++j)
|
for (uint32_t j = 0; j < groupCount; ++j)
|
||||||
{
|
{
|
||||||
const uint8_t* groupData = audData.get() + SBig(groupOffs[j]);
|
const uint8_t* groupData = audData.get() + SBig(groupOffs[j]);
|
||||||
RS23GroupHead head = *reinterpret_cast<const RS23GroupHead*>(groupData);
|
RS23GroupHead head = *reinterpret_cast<const RS23GroupHead*>(groupData);
|
||||||
|
@ -1547,7 +1539,7 @@ static std::vector<std::pair<SystemString, ContainerRegistry::SongData>> LoadRS2
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const RS23SONHead* sonData = reinterpret_cast<const RS23SONHead*>(audData.get() + head.sonIdxBeginOff);
|
const RS23SONHead* sonData = reinterpret_cast<const RS23SONHead*>(audData.get() + head.sonIdxBeginOff);
|
||||||
for (uint32_t s=0 ; s<head.sonCount ; ++s)
|
for (uint32_t s = 0; s < head.sonCount; ++s)
|
||||||
{
|
{
|
||||||
RS23SONHead sonHead = sonData[s];
|
RS23SONHead sonHead = sonData[s];
|
||||||
sonHead.swapBig();
|
sonHead.swapBig();
|
||||||
|
@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1602,7 +1594,7 @@ static bool ValidateRS3(FILE* fp)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
FSeek(fp, int64_t(fstOff), SEEK_SET);
|
FSeek(fp, int64_t(fstOff), SEEK_SET);
|
||||||
for (size_t i=0 ; i<fstSz/160 ; ++i)
|
for (size_t i = 0; i < fstSz / 160; ++i)
|
||||||
{
|
{
|
||||||
RS3FSTEntry entry;
|
RS3FSTEntry entry;
|
||||||
fread(&entry, 1, 160, fp);
|
fread(&entry, 1, 160, fp);
|
||||||
|
@ -1630,7 +1622,7 @@ static std::vector<std::pair<SystemString, IntrusiveAudioGroupData>> LoadRS3(FIL
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
FSeek(fp, int64_t(fstOff), SEEK_SET);
|
FSeek(fp, int64_t(fstOff), SEEK_SET);
|
||||||
for (size_t i=0 ; i<fstSz/160 ; ++i)
|
for (size_t i = 0; i < fstSz / 160; ++i)
|
||||||
{
|
{
|
||||||
RS3FSTEntry entry;
|
RS3FSTEntry entry;
|
||||||
fread(&entry, 1, 160, fp);
|
fread(&entry, 1, 160, fp);
|
||||||
|
@ -1645,7 +1637,7 @@ static std::vector<std::pair<SystemString, IntrusiveAudioGroupData>> LoadRS3(FIL
|
||||||
uint32_t groupCount = SBig(*reinterpret_cast<uint32_t*>(audData.get() + indexOff));
|
uint32_t groupCount = SBig(*reinterpret_cast<uint32_t*>(audData.get() + indexOff));
|
||||||
const uint32_t* groupOffs = reinterpret_cast<const uint32_t*>(audData.get() + indexOff + 4);
|
const uint32_t* groupOffs = reinterpret_cast<const uint32_t*>(audData.get() + indexOff + 4);
|
||||||
|
|
||||||
for (uint32_t j=0 ; j<groupCount ; ++j)
|
for (uint32_t j = 0; j < groupCount; ++j)
|
||||||
{
|
{
|
||||||
const uint8_t* groupData = audData.get() + SBig(groupOffs[j]);
|
const uint8_t* groupData = audData.get() + SBig(groupOffs[j]);
|
||||||
RS23GroupHead head = *reinterpret_cast<const RS23GroupHead*>(groupData);
|
RS23GroupHead head = *reinterpret_cast<const RS23GroupHead*>(groupData);
|
||||||
|
@ -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{}});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1690,8 +1683,8 @@ static bool ValidateStarFoxAdvSongs(FILE* fp)
|
||||||
|
|
||||||
const uint32_t* lengths = reinterpret_cast<const uint32_t*>(data.get());
|
const uint32_t* lengths = reinterpret_cast<const uint32_t*>(data.get());
|
||||||
size_t totalLen = 0;
|
size_t totalLen = 0;
|
||||||
int i=0;
|
int i = 0;
|
||||||
for (; i<128 ; ++i)
|
for (; i < 128; ++i)
|
||||||
{
|
{
|
||||||
uint32_t len = SBig(lengths[i]);
|
uint32_t len = SBig(lengths[i]);
|
||||||
if (len == 0)
|
if (len == 0)
|
||||||
|
@ -1699,7 +1692,7 @@ static bool ValidateStarFoxAdvSongs(FILE* fp)
|
||||||
totalLen += len;
|
totalLen += len;
|
||||||
totalLen = ((totalLen + 31) & ~31);
|
totalLen = ((totalLen + 31) & ~31);
|
||||||
}
|
}
|
||||||
totalLen += (((i*4) + 31) & ~31);
|
totalLen += (((i * 4) + 31) & ~31);
|
||||||
|
|
||||||
return totalLen == endPos;
|
return totalLen == endPos;
|
||||||
}
|
}
|
||||||
|
@ -1716,8 +1709,8 @@ static std::vector<std::pair<SystemString, ContainerRegistry::SongData>> LoadSta
|
||||||
fread(data.get(), 1, endPos, midifp);
|
fread(data.get(), 1, endPos, midifp);
|
||||||
|
|
||||||
const uint32_t* lengths = reinterpret_cast<const uint32_t*>(data.get());
|
const uint32_t* lengths = reinterpret_cast<const uint32_t*>(data.get());
|
||||||
int i=0;
|
int i = 0;
|
||||||
for (; i<128 ; ++i)
|
for (; i < 128; ++i)
|
||||||
{
|
{
|
||||||
uint32_t len = SBig(lengths[i]);
|
uint32_t len = SBig(lengths[i]);
|
||||||
if (len == 0)
|
if (len == 0)
|
||||||
|
@ -1725,8 +1718,8 @@ static std::vector<std::pair<SystemString, ContainerRegistry::SongData>> LoadSta
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t sngCount = i;
|
size_t sngCount = i;
|
||||||
size_t cur = (((sngCount*4) + 31) & ~31);
|
size_t cur = (((sngCount * 4) + 31) & ~31);
|
||||||
for (i=0; i<sngCount ; ++i)
|
for (i = 0; i < sngCount; ++i)
|
||||||
{
|
{
|
||||||
uint32_t len = SBig(lengths[i]);
|
uint32_t len = SBig(lengths[i]);
|
||||||
if (len == 0)
|
if (len == 0)
|
||||||
|
@ -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 {};
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,11 +8,11 @@
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
#if !defined(S_ISREG) && defined(S_IFMT) && defined(S_IFREG)
|
#if !defined(S_ISREG) && defined(S_IFMT) && defined(S_IFREG)
|
||||||
#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
|
#define S_ISREG(m) (((m)&S_IFMT) == S_IFREG)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined(S_ISDIR) && defined(S_IFMT) && defined(S_IFDIR)
|
#if !defined(S_ISDIR) && defined(S_IFMT) && defined(S_IFDIR)
|
||||||
#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
|
#define S_ISDIR(m) (((m)&S_IFMT) == S_IFDIR)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
@ -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))
|
||||||
|
@ -75,7 +74,7 @@ DirectoryEnumerator::DirectoryEnumerator(const SystemChar* path, Mode mode,
|
||||||
if (noHidden && (d.cFileName[0] == L'.' || (d.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) != 0))
|
if (noHidden && (d.cFileName[0] == L'.' || (d.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) != 0))
|
||||||
continue;
|
continue;
|
||||||
SystemString fp(path);
|
SystemString fp(path);
|
||||||
fp +=_S('/');
|
fp += _S('/');
|
||||||
fp += d.cFileName;
|
fp += d.cFileName;
|
||||||
Sstat st;
|
Sstat st;
|
||||||
if (Stat(fp.c_str(), &st) || !S_ISDIR(st.st_mode))
|
if (Stat(fp.c_str(), &st) || !S_ISDIR(st.st_mode))
|
||||||
|
@ -84,7 +83,7 @@ DirectoryEnumerator::DirectoryEnumerator(const SystemChar* path, Mode mode,
|
||||||
} while (FindNextFileW(dir, &d));
|
} while (FindNextFileW(dir, &d));
|
||||||
|
|
||||||
if (reverse)
|
if (reverse)
|
||||||
for (auto it=sort.crbegin() ; it != sort.crend() ; ++it)
|
for (auto it = sort.crbegin(); it != sort.crend(); ++it)
|
||||||
m_entries.push_back(std::move(it->second));
|
m_entries.push_back(std::move(it->second));
|
||||||
else
|
else
|
||||||
for (auto& e : sort)
|
for (auto& e : sort)
|
||||||
|
@ -119,7 +118,7 @@ DirectoryEnumerator::DirectoryEnumerator(const SystemChar* path, Mode mode,
|
||||||
} while (FindNextFileW(dir, &d));
|
} while (FindNextFileW(dir, &d));
|
||||||
|
|
||||||
if (reverse)
|
if (reverse)
|
||||||
for (auto it=sort.crbegin() ; it != sort.crend() ; ++it)
|
for (auto it = sort.crbegin(); it != sort.crend(); ++it)
|
||||||
m_entries.push_back(std::move(it->second));
|
m_entries.push_back(std::move(it->second));
|
||||||
else
|
else
|
||||||
for (auto& e : sort)
|
for (auto& e : sort)
|
||||||
|
@ -144,7 +143,7 @@ DirectoryEnumerator::DirectoryEnumerator(const SystemChar* path, Mode mode,
|
||||||
} while (FindNextFileW(dir, &d));
|
} while (FindNextFileW(dir, &d));
|
||||||
|
|
||||||
if (reverse)
|
if (reverse)
|
||||||
for (auto it=sort.crbegin() ; it != sort.crend() ; ++it)
|
for (auto it = sort.crbegin(); it != sort.crend(); ++it)
|
||||||
m_entries.push_back(std::move(it->second));
|
m_entries.push_back(std::move(it->second));
|
||||||
else
|
else
|
||||||
for (auto& e : sort)
|
for (auto& e : sort)
|
||||||
|
@ -210,7 +209,7 @@ DirectoryEnumerator::DirectoryEnumerator(const SystemChar* path, Mode mode,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reverse)
|
if (reverse)
|
||||||
for (auto it=sort.crbegin() ; it != sort.crend() ; ++it)
|
for (auto it = sort.crbegin(); it != sort.crend(); ++it)
|
||||||
m_entries.push_back(std::move(it->second));
|
m_entries.push_back(std::move(it->second));
|
||||||
else
|
else
|
||||||
for (auto& e : sort)
|
for (auto& e : sort)
|
||||||
|
@ -244,7 +243,7 @@ DirectoryEnumerator::DirectoryEnumerator(const SystemChar* path, Mode mode,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reverse)
|
if (reverse)
|
||||||
for (auto it=sort.crbegin() ; it != sort.crend() ; ++it)
|
for (auto it = sort.crbegin(); it != sort.crend(); ++it)
|
||||||
m_entries.push_back(std::move(it->second));
|
m_entries.push_back(std::move(it->second));
|
||||||
else
|
else
|
||||||
for (auto& e : sort)
|
for (auto& e : sort)
|
||||||
|
@ -269,7 +268,7 @@ DirectoryEnumerator::DirectoryEnumerator(const SystemChar* path, Mode mode,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reverse)
|
if (reverse)
|
||||||
for (auto it=sort.crbegin() ; it != sort.crend() ; ++it)
|
for (auto it = sort.crbegin(); it != sort.crend(); ++it)
|
||||||
m_entries.push_back(std::move(it->second));
|
m_entries.push_back(std::move(it->second));
|
||||||
else
|
else
|
||||||
for (auto& e : sort)
|
for (auto& e : sort)
|
||||||
|
@ -283,5 +282,4 @@ DirectoryEnumerator::DirectoryEnumerator(const SystemChar* path, Mode mode,
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
@ -165,8 +167,8 @@ void EffectChorusImp<T>::_setup(double sampleRate)
|
||||||
memset(buf, 0, m_blockSamples * AMUSE_CHORUS_NUM_BLOCKS * 8 * sizeof(T));
|
memset(buf, 0, m_blockSamples * AMUSE_CHORUS_NUM_BLOCKS * 8 * sizeof(T));
|
||||||
size_t chanPitch = m_blockSamples * AMUSE_CHORUS_NUM_BLOCKS;
|
size_t chanPitch = m_blockSamples * AMUSE_CHORUS_NUM_BLOCKS;
|
||||||
|
|
||||||
for (int c=0 ; c<8 ; ++c)
|
for (int c = 0; c < 8; ++c)
|
||||||
for (int i=0 ; i<AMUSE_CHORUS_NUM_BLOCKS ; ++i)
|
for (int i = 0; i < AMUSE_CHORUS_NUM_BLOCKS; ++i)
|
||||||
x0_lastChans[c][i] = buf + chanPitch * c + m_blockSamples * i;
|
x0_lastChans[c][i] = buf + chanPitch * c + m_blockSamples * i;
|
||||||
|
|
||||||
x6c_src.x88_trigger = chanPitch;
|
x6c_src.x88_trigger = chanPitch;
|
||||||
|
@ -207,7 +209,7 @@ void EffectChorusImp<T>::SrcInfo::doSrc1(size_t blockSamples, size_t chanCount)
|
||||||
float cur = x70_smpBase[x7c_posHi];
|
float cur = x70_smpBase[x7c_posHi];
|
||||||
|
|
||||||
T* dest = x6c_dest;
|
T* dest = x6c_dest;
|
||||||
for (size_t i=0 ; i<blockSamples ; ++i)
|
for (size_t i = 0; i < blockSamples; ++i)
|
||||||
{
|
{
|
||||||
const float* selTab = &rsmpTab12khz[x78_posLo >> 23 & 0x1fc];
|
const float* selTab = &rsmpTab12khz[x78_posLo >> 23 & 0x1fc];
|
||||||
|
|
||||||
|
@ -248,7 +250,7 @@ void EffectChorusImp<T>::SrcInfo::doSrc2(size_t blockSamples, size_t chanCount)
|
||||||
float cur = x70_smpBase[x7c_posHi];
|
float cur = x70_smpBase[x7c_posHi];
|
||||||
|
|
||||||
T* dest = x6c_dest;
|
T* dest = x6c_dest;
|
||||||
for (size_t i=0 ; i<blockSamples ; ++i)
|
for (size_t i = 0; i < blockSamples; ++i)
|
||||||
{
|
{
|
||||||
const float* selTab = &rsmpTab12khz[x78_posLo >> 23 & 0x1fc];
|
const float* selTab = &rsmpTab12khz[x78_posLo >> 23 & 0x1fc];
|
||||||
++x7c_posHi;
|
++x7c_posHi;
|
||||||
|
@ -305,25 +307,18 @@ void EffectChorusImp<T>::applyEffect(T* audio, size_t frameCount, const ChannelM
|
||||||
_update();
|
_update();
|
||||||
|
|
||||||
size_t remFrames = frameCount;
|
size_t remFrames = frameCount;
|
||||||
for (size_t f=0 ; f<frameCount ;)
|
for (size_t f = 0; f < frameCount;)
|
||||||
{
|
{
|
||||||
uint8_t next = x24_currentLast + 1;
|
uint8_t next = x24_currentLast + 1;
|
||||||
uint8_t buf = next % 3;
|
uint8_t buf = next % 3;
|
||||||
T* bufs[8] =
|
T* bufs[8] = {
|
||||||
{
|
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;
|
||||||
for (size_t s=0 ; f<frameCount && s<m_blockSamples ; ++s, ++f)
|
for (size_t s = 0; f < frameCount && s < m_blockSamples; ++s, ++f)
|
||||||
for (size_t c=0 ; c<chanMap.m_channelCount && c<8 ; ++c)
|
for (size_t c = 0; c < chanMap.m_channelCount && c < 8; ++c)
|
||||||
*bufs[c]++ = *inBuf++;
|
*bufs[c]++ = *inBuf++;
|
||||||
|
|
||||||
x6c_src.x84_pitchHi = (x60_pitchOffset >> 16) + 1;
|
x6c_src.x84_pitchHi = (x60_pitchOffset >> 16) + 1;
|
||||||
|
@ -338,7 +333,7 @@ void EffectChorusImp<T>::applyEffect(T* audio, size_t frameCount, const ChannelM
|
||||||
|
|
||||||
T* outBuf = audio;
|
T* outBuf = audio;
|
||||||
size_t bs = std::min(remFrames, size_t(m_blockSamples));
|
size_t bs = std::min(remFrames, size_t(m_blockSamples));
|
||||||
for (size_t c=0 ; c<chanMap.m_channelCount && c<8 ; ++c)
|
for (size_t c = 0; c < chanMap.m_channelCount && c < 8; ++c)
|
||||||
{
|
{
|
||||||
x6c_src.x7c_posHi = x5c_currentPosHi;
|
x6c_src.x7c_posHi = x5c_currentPosHi;
|
||||||
x6c_src.x78_posLo = x58_currentPosLo;
|
x6c_src.x78_posLo = x58_currentPosLo;
|
||||||
|
@ -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>;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,14 +8,13 @@ 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);
|
||||||
initOutput = clamp(0u, initOutput, 100u);
|
initOutput = clamp(0u, initOutput, 100u);
|
||||||
|
|
||||||
for (int i=0 ; i<8 ; ++i)
|
for (int i = 0; i < 8; ++i)
|
||||||
{
|
{
|
||||||
x3c_delay[i] = initDelay;
|
x3c_delay[i] = initDelay;
|
||||||
x48_feedback[i] = initFeedback;
|
x48_feedback[i] = initFeedback;
|
||||||
|
@ -37,7 +36,7 @@ void EffectDelayImp<T>::_setup(double sampleRate)
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void EffectDelayImp<T>::_update()
|
void EffectDelayImp<T>::_update()
|
||||||
{
|
{
|
||||||
for (int i=0 ; i<8 ; ++i)
|
for (int i = 0; i < 8; ++i)
|
||||||
{
|
{
|
||||||
x0_currentSize[i] = ((x3c_delay[i] - 5) * m_sampsPerMs + 159) / 160;
|
x0_currentSize[i] = ((x3c_delay[i] - 5) * m_sampsPerMs + 159) / 160;
|
||||||
xc_currentPos[i] = 0;
|
xc_currentPos[i] = 0;
|
||||||
|
@ -57,12 +56,12 @@ void EffectDelayImp<T>::applyEffect(T* audio, size_t frameCount, const ChannelMa
|
||||||
if (m_dirty)
|
if (m_dirty)
|
||||||
_update();
|
_update();
|
||||||
|
|
||||||
for (size_t f=0 ; f<frameCount ;)
|
for (size_t f = 0; f < frameCount;)
|
||||||
{
|
{
|
||||||
for (int c=0 ; c<chanMap.m_channelCount ; ++c)
|
for (int c = 0; c < chanMap.m_channelCount; ++c)
|
||||||
{
|
{
|
||||||
T* chanAud = audio + c;
|
T* chanAud = audio + c;
|
||||||
for (int i=0 ; i<m_blockSamples && f<frameCount ; ++i, ++f)
|
for (int i = 0; i < m_blockSamples && f < frameCount; ++i, ++f)
|
||||||
{
|
{
|
||||||
T& liveSamp = chanAud[chanMap.m_channelCount * i];
|
T& liveSamp = chanAud[chanMap.m_channelCount * i];
|
||||||
T& samp = x30_chanLines[c][xc_currentPos[c] * m_blockSamples + i];
|
T& samp = x30_chanLines[c][xc_currentPos[c] * m_blockSamples + i];
|
||||||
|
@ -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>;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,21 +90,22 @@ 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;
|
||||||
for (int c=0 ; c<8 ; ++c)
|
double rateRatio = m_sampleRate / 32000.0;
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
@ -119,7 +123,7 @@ void EffectReverbStdImp<T>::_update()
|
||||||
if (x150_x1d8_preDelay != 0.f)
|
if (x150_x1d8_preDelay != 0.f)
|
||||||
{
|
{
|
||||||
x120_preDelayTime = m_sampleRate * x150_x1d8_preDelay;
|
x120_preDelayTime = m_sampleRate * x150_x1d8_preDelay;
|
||||||
for (int i=0 ; i<8 ; ++i)
|
for (int i = 0; i < 8; ++i)
|
||||||
{
|
{
|
||||||
x124_preDelayLine[i].reset(new float[x120_preDelayTime]);
|
x124_preDelayLine[i].reset(new float[x120_preDelayTime]);
|
||||||
memset(x124_preDelayLine[i].get(), 0, x120_preDelayTime * sizeof(float));
|
memset(x124_preDelayLine[i].get(), 0, x120_preDelayTime * sizeof(float));
|
||||||
|
@ -129,7 +133,7 @@ void EffectReverbStdImp<T>::_update()
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
x120_preDelayTime = 0;
|
x120_preDelayTime = 0;
|
||||||
for (int i=0 ; i<8 ; ++i)
|
for (int i = 0; i < 8; ++i)
|
||||||
{
|
{
|
||||||
x124_preDelayLine[i] = nullptr;
|
x124_preDelayLine[i] = nullptr;
|
||||||
x130_preDelayPtr[i] = nullptr;
|
x130_preDelayPtr[i] = nullptr;
|
||||||
|
@ -148,9 +152,9 @@ void EffectReverbStdImp<T>::applyEffect(T* audio, size_t frameCount, const Chann
|
||||||
float dampWet = x118_level * 0.6f;
|
float dampWet = x118_level * 0.6f;
|
||||||
float dampDry = 0.6f - dampWet;
|
float dampDry = 0.6f - dampWet;
|
||||||
|
|
||||||
for (size_t f=0 ; f<frameCount ; f+=160)
|
for (size_t f = 0; f < frameCount; f += 160)
|
||||||
{
|
{
|
||||||
for (unsigned c=0 ; c<chanMap.m_channelCount ; ++c)
|
for (unsigned c = 0; c < chanMap.m_channelCount; ++c)
|
||||||
{
|
{
|
||||||
float* combCoefs = xf4_combCoef[c];
|
float* combCoefs = xf4_combCoef[c];
|
||||||
float& lpLastOut = x10c_lpLastout[c];
|
float& lpLastOut = x10c_lpLastout[c];
|
||||||
|
@ -162,7 +166,7 @@ void EffectReverbStdImp<T>::applyEffect(T* audio, size_t frameCount, const Chann
|
||||||
ReverbDelayLine* linesAP = x0_AP[c];
|
ReverbDelayLine* linesAP = x0_AP[c];
|
||||||
|
|
||||||
int procSamples = std::min(size_t(160), frameCount - f);
|
int procSamples = std::min(size_t(160), frameCount - f);
|
||||||
for (int s=0 ; s<procSamples ; ++s)
|
for (int s = 0; s < procSamples; ++s)
|
||||||
{
|
{
|
||||||
float sample = audio[s * chanMap.m_channelCount + c];
|
float sample = audio[s * chanMap.m_channelCount + c];
|
||||||
|
|
||||||
|
@ -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,27 +265,28 @@ 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;
|
||||||
for (int c=0 ; c<8 ; ++c)
|
double rateRatio = m_sampleRate / 32000.0;
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
@ -299,7 +303,7 @@ void EffectReverbHiImp<T>::_update()
|
||||||
if (x150_x1d8_preDelay != 0.f)
|
if (x150_x1d8_preDelay != 0.f)
|
||||||
{
|
{
|
||||||
x1a4_preDelayTime = m_sampleRate * x150_x1d8_preDelay;
|
x1a4_preDelayTime = m_sampleRate * x150_x1d8_preDelay;
|
||||||
for (int i=0 ; i<8 ; ++i)
|
for (int i = 0; i < 8; ++i)
|
||||||
{
|
{
|
||||||
x1ac_preDelayLine[i].reset(new float[x1a4_preDelayTime]);
|
x1ac_preDelayLine[i].reset(new float[x1a4_preDelayTime]);
|
||||||
memset(x1ac_preDelayLine[i].get(), 0, x1a4_preDelayTime * sizeof(float));
|
memset(x1ac_preDelayLine[i].get(), 0, x1a4_preDelayTime * sizeof(float));
|
||||||
|
@ -309,7 +313,7 @@ void EffectReverbHiImp<T>::_update()
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
x1a4_preDelayTime = 0;
|
x1a4_preDelayTime = 0;
|
||||||
for (int i=0 ; i<8 ; ++i)
|
for (int i = 0; i < 8; ++i)
|
||||||
{
|
{
|
||||||
x1ac_preDelayLine[i] = nullptr;
|
x1ac_preDelayLine[i] = nullptr;
|
||||||
x1b8_preDelayPtr[i] = nullptr;
|
x1b8_preDelayPtr[i] = nullptr;
|
||||||
|
@ -340,7 +344,7 @@ void EffectReverbHiImp<T>::_handleReverb(T* audio, int c, int chanCount, int sam
|
||||||
float damping = x1a0_damping;
|
float damping = x1a0_damping;
|
||||||
int32_t preDelayTime = x1a4_preDelayTime;
|
int32_t preDelayTime = x1a4_preDelayTime;
|
||||||
|
|
||||||
for (int s=0 ; s<sampleCount ; ++s)
|
for (int s = 0; s < sampleCount; ++s)
|
||||||
{
|
{
|
||||||
float sample = audio[s * chanCount + c];
|
float sample = audio[s * chanCount + c];
|
||||||
|
|
||||||
|
@ -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 -
|
||||||
|
@ -446,16 +450,16 @@ void EffectReverbHiImp<T>::_handleReverb(T* audio, int c, int chanCount, int sam
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void EffectReverbHiImp<T>::_doCrosstalk(T* audio, float wet, float dry, int chanCount, int sampleCount)
|
void EffectReverbHiImp<T>::_doCrosstalk(T* audio, float wet, float dry, int chanCount, int sampleCount)
|
||||||
{
|
{
|
||||||
for (int i=0 ; i<sampleCount ; ++i)
|
for (int i = 0; i < sampleCount; ++i)
|
||||||
{
|
{
|
||||||
T* base = &audio[chanCount*i];
|
T* base = &audio[chanCount * i];
|
||||||
float allWet = 0;
|
float allWet = 0;
|
||||||
for (int c=0 ; c<chanCount ; ++c)
|
for (int c = 0; c < chanCount; ++c)
|
||||||
{
|
{
|
||||||
allWet += base[c] * wet;
|
allWet += base[c] * wet;
|
||||||
base[c] *= dry;
|
base[c] *= dry;
|
||||||
}
|
}
|
||||||
for (int c=0 ; c<chanCount ; ++c)
|
for (int c = 0; c < chanCount; ++c)
|
||||||
base[c] = ClampFull<T>(base[c] + allWet);
|
base[c] = ClampFull<T>(base[c] + allWet);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -466,10 +470,10 @@ void EffectReverbHiImp<T>::applyEffect(T* audio, size_t frameCount, const Channe
|
||||||
if (m_dirty)
|
if (m_dirty)
|
||||||
_update();
|
_update();
|
||||||
|
|
||||||
for (size_t f=0 ; f<frameCount ; f+=160)
|
for (size_t f = 0; f < frameCount; f += 160)
|
||||||
{
|
{
|
||||||
size_t blockSamples = std::min(size_t(160), frameCount - f);
|
size_t blockSamples = std::min(size_t(160), frameCount - f);
|
||||||
for (unsigned i=0 ; i<chanMap.m_channelCount ; ++i)
|
for (unsigned i = 0; i < chanMap.m_channelCount; ++i)
|
||||||
{
|
{
|
||||||
if (i == 0 && x1a8_internalCrosstalk != 0.f)
|
if (i == 0 && x1a8_internalCrosstalk != 0.f)
|
||||||
{
|
{
|
||||||
|
@ -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>;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) {}
|
||||||
}
|
}
|
||||||
|
|
148
lib/Engine.cpp
148
lib/Engine.cpp
|
@ -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,44 +56,48 @@ 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);
|
||||||
if (songGroup)
|
if (songGroup)
|
||||||
{
|
{
|
||||||
auto it = m_activeSequencers.emplace(m_activeSequencers.end(),
|
auto it = m_activeSequencers.emplace(m_activeSequencers.end(),
|
||||||
new Sequencer(*this, group, groupId, songGroup, setupId, studio));
|
new Sequencer(*this, group, groupId, songGroup, setupId, studio));
|
||||||
return it;
|
return it;
|
||||||
}
|
}
|
||||||
const SFXGroupIndex* sfxGroup = group.getProj().getSFXGroupIndex(groupId);
|
const SFXGroupIndex* sfxGroup = group.getProj().getSFXGroupIndex(groupId);
|
||||||
if (sfxGroup)
|
if (sfxGroup)
|
||||||
{
|
{
|
||||||
auto it = m_activeSequencers.emplace(m_activeSequencers.end(),
|
auto it = m_activeSequencers.emplace(m_activeSequencers.end(),
|
||||||
new Sequencer(*this, group, groupId, sfxGroup, studio));
|
new Sequencer(*this, group, groupId, sfxGroup, studio));
|
||||||
return it;
|
return it;
|
||||||
}
|
}
|
||||||
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,20 +123,9 @@ 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();)
|
||||||
{
|
{
|
||||||
Emitter* emitter = it->get();
|
Emitter* emitter = it->get();
|
||||||
if (emitter->getVoice()->_isRecursivelyDead())
|
if (emitter->getVoice()->_isRecursivelyDead())
|
||||||
|
@ -140,7 +137,7 @@ void Engine::_bringOutYourDead()
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto it = m_activeVoices.begin() ; it != m_activeVoices.end() ;)
|
for (auto it = m_activeVoices.begin(); it != m_activeVoices.end();)
|
||||||
{
|
{
|
||||||
Voice* vox = it->get();
|
Voice* vox = it->get();
|
||||||
vox->_bringOutYourDead();
|
vox->_bringOutYourDead();
|
||||||
|
@ -152,7 +149,7 @@ void Engine::_bringOutYourDead()
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto it = m_activeSequencers.begin() ; it != m_activeSequencers.end() ;)
|
for (auto it = m_activeSequencers.begin(); it != m_activeSequencers.end();)
|
||||||
{
|
{
|
||||||
Sequencer* seq = it->get();
|
Sequencer* seq = it->get();
|
||||||
seq->_bringOutYourDead();
|
seq->_bringOutYourDead();
|
||||||
|
@ -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)
|
||||||
|
@ -236,7 +242,7 @@ void Engine::removeAudioGroup(const AudioGroupData& data)
|
||||||
AudioGroup* grp = search->second.get();
|
AudioGroup* grp = search->second.get();
|
||||||
|
|
||||||
/* Destroy runtime entities within group */
|
/* Destroy runtime entities within group */
|
||||||
for (auto it = m_activeVoices.begin() ; it != m_activeVoices.end() ;)
|
for (auto it = m_activeVoices.begin(); it != m_activeVoices.end();)
|
||||||
{
|
{
|
||||||
Voice* vox = it->get();
|
Voice* vox = it->get();
|
||||||
if (&vox->getAudioGroup() == grp)
|
if (&vox->getAudioGroup() == grp)
|
||||||
|
@ -248,7 +254,7 @@ void Engine::removeAudioGroup(const AudioGroupData& data)
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto it = m_activeEmitters.begin() ; it != m_activeEmitters.end() ;)
|
for (auto it = m_activeEmitters.begin(); it != m_activeEmitters.end();)
|
||||||
{
|
{
|
||||||
Emitter* emitter = it->get();
|
Emitter* emitter = it->get();
|
||||||
if (&emitter->getAudioGroup() == grp)
|
if (&emitter->getAudioGroup() == grp)
|
||||||
|
@ -260,7 +266,7 @@ void Engine::removeAudioGroup(const AudioGroupData& data)
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto it = m_activeSequencers.begin() ; it != m_activeSequencers.end() ;)
|
for (auto it = m_activeSequencers.begin(); it != m_activeSequencers.end();)
|
||||||
{
|
{
|
||||||
Sequencer* seq = it->get();
|
Sequencer* seq = it->get();
|
||||||
if (&seq->getAudioGroup() == grp)
|
if (&seq->getAudioGroup() == grp)
|
||||||
|
@ -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)
|
||||||
|
@ -448,7 +407,7 @@ std::shared_ptr<Voice> Engine::findVoice(int vid)
|
||||||
/** Stop all voices in `kg`, stops immediately (no KeyOff) when `flag` set */
|
/** Stop all voices in `kg`, stops immediately (no KeyOff) when `flag` set */
|
||||||
void Engine::killKeygroup(uint8_t kg, bool now)
|
void Engine::killKeygroup(uint8_t kg, bool now)
|
||||||
{
|
{
|
||||||
for (auto it = m_activeVoices.begin() ; it != m_activeVoices.end() ;)
|
for (auto it = m_activeVoices.begin(); it != m_activeVoices.end();)
|
||||||
{
|
{
|
||||||
Voice* vox = it->get();
|
Voice* vox = it->get();
|
||||||
if (vox->m_keygroup == kg)
|
if (vox->m_keygroup == kg)
|
||||||
|
@ -470,7 +429,7 @@ void Engine::killKeygroup(uint8_t kg, bool now)
|
||||||
/** Send all voices using `macroId` the message `val` */
|
/** Send all voices using `macroId` the message `val` */
|
||||||
void Engine::sendMacroMessage(ObjectId macroId, int32_t val)
|
void Engine::sendMacroMessage(ObjectId macroId, int32_t val)
|
||||||
{
|
{
|
||||||
for (auto it = m_activeVoices.begin() ; it != m_activeVoices.end() ; ++it)
|
for (auto it = m_activeVoices.begin(); it != m_activeVoices.end(); ++it)
|
||||||
{
|
{
|
||||||
Voice* vox = it->get();
|
Voice* vox = it->get();
|
||||||
if (vox->getObjectId() == macroId)
|
if (vox->getObjectId() == macroId)
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ namespace amuse
|
||||||
|
|
||||||
void Sequencer::ChannelState::_bringOutYourDead()
|
void Sequencer::ChannelState::_bringOutYourDead()
|
||||||
{
|
{
|
||||||
for (auto it = m_chanVoxs.begin() ; it != m_chanVoxs.end() ;)
|
for (auto it = m_chanVoxs.begin(); it != m_chanVoxs.end();)
|
||||||
{
|
{
|
||||||
Voice* vox = it->second.get();
|
Voice* vox = it->second.get();
|
||||||
vox->_bringOutYourDead();
|
vox->_bringOutYourDead();
|
||||||
|
@ -21,7 +21,7 @@ void Sequencer::ChannelState::_bringOutYourDead()
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto it = m_keyoffVoxs.begin() ; it != m_keyoffVoxs.end() ;)
|
for (auto it = m_keyoffVoxs.begin(); it != m_keyoffVoxs.end();)
|
||||||
{
|
{
|
||||||
Voice* vox = it->get();
|
Voice* vox = it->get();
|
||||||
vox->_bringOutYourDead();
|
vox->_bringOutYourDead();
|
||||||
|
@ -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,14 +376,11 @@ 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()
|
||||||
{
|
{
|
||||||
for (auto it = m_chanVoxs.begin() ; it != m_chanVoxs.end() ;)
|
for (auto it = m_chanVoxs.begin(); it != m_chanVoxs.end();)
|
||||||
{
|
{
|
||||||
if (it->second == m_lastVoice.lock())
|
if (it->second == m_lastVoice.lock())
|
||||||
m_lastVoice.reset();
|
m_lastVoice.reset();
|
||||||
|
@ -453,7 +431,7 @@ void Sequencer::allOff(uint8_t chan, bool now)
|
||||||
|
|
||||||
void Sequencer::ChannelState::killKeygroup(uint8_t kg, bool now)
|
void Sequencer::ChannelState::killKeygroup(uint8_t kg, bool now)
|
||||||
{
|
{
|
||||||
for (auto it = m_chanVoxs.begin() ; it != m_chanVoxs.end() ;)
|
for (auto it = m_chanVoxs.begin(); it != m_chanVoxs.end();)
|
||||||
{
|
{
|
||||||
Voice* vox = it->second.get();
|
Voice* vox = it->second.get();
|
||||||
if (vox->m_keygroup == kg)
|
if (vox->m_keygroup == kg)
|
||||||
|
@ -475,7 +453,7 @@ void Sequencer::ChannelState::killKeygroup(uint8_t kg, bool now)
|
||||||
|
|
||||||
if (now)
|
if (now)
|
||||||
{
|
{
|
||||||
for (auto it = m_keyoffVoxs.begin() ; it != m_keyoffVoxs.end() ;)
|
for (auto it = m_keyoffVoxs.begin(); it != m_keyoffVoxs.end();)
|
||||||
{
|
{
|
||||||
Voice* vox = it->get();
|
Voice* vox = it->get();
|
||||||
if (vox->m_keygroup == kg)
|
if (vox->m_keygroup == kg)
|
||||||
|
@ -638,5 +616,4 @@ void Sequencer::prevChanProgram(int8_t chanId)
|
||||||
|
|
||||||
return m_chanStates[chanId]->prevProgram();
|
return m_chanStates[chanId]->prevProgram();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
namespace amuse
|
namespace amuse
|
||||||
{
|
{
|
||||||
|
|
||||||
static inline uint8_t clamp7(uint8_t val) {return std::max(0, std::min(127, int(val)));}
|
static inline uint8_t clamp7(uint8_t val) { return std::max(0, std::min(127, int(val))); }
|
||||||
|
|
||||||
enum class Status
|
enum class Status
|
||||||
{
|
{
|
||||||
|
@ -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
|
||||||
|
@ -78,13 +88,12 @@ class MIDIDecoder
|
||||||
{
|
{
|
||||||
m_results.emplace_back();
|
m_results.emplace_back();
|
||||||
m_results.back().first = prog;
|
m_results.back().first = prog;
|
||||||
for (size_t i=0 ; i<128 ; ++i)
|
for (size_t i = 0; i < 128; ++i)
|
||||||
m_notes[i] = m_results.back().second.end();
|
m_notes[i] = m_results.back().second.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
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,9 +121,8 @@ 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;
|
||||||
if (it == end)
|
if (it == end)
|
||||||
|
@ -289,19 +297,21 @@ 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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return it;
|
return it;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::pair<int, std::multimap<int, Event>>>& getResults() {return m_results;}
|
std::vector<std::pair<int, std::multimap<int, Event>>>& getResults() { return m_results; }
|
||||||
std::multimap<int, int>& getTempos() {return m_tempos;}
|
std::multimap<int, int>& getTempos() { return m_tempos; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class MIDIEncoder
|
class MIDIEncoder
|
||||||
|
@ -314,14 +324,14 @@ class MIDIEncoder
|
||||||
{
|
{
|
||||||
if (data[0] == m_status)
|
if (data[0] == m_status)
|
||||||
{
|
{
|
||||||
for (size_t i=1 ; i<len ; ++i)
|
for (size_t i = 1; i < len; ++i)
|
||||||
m_result.push_back(data[i]);
|
m_result.push_back(data[i]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (data[0] & 0x80)
|
if (data[0] & 0x80)
|
||||||
m_status = data[0];
|
m_status = data[0];
|
||||||
for (size_t i=0 ; i<len ; ++i)
|
for (size_t i = 0; i < len; ++i)
|
||||||
m_result.push_back(data[i]);
|
m_result.push_back(data[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -350,110 +360,98 @@ class MIDIEncoder
|
||||||
send[2] = val & 0x7f;
|
send[2] = val & 0x7f;
|
||||||
|
|
||||||
size_t len = 3 - (ptr - send);
|
size_t len = 3 - (ptr - send);
|
||||||
for (size_t i=0 ; i<len ; ++i)
|
for (size_t i = 0; i < len; ++i)
|
||||||
m_result.push_back(ptr[i]);
|
m_result.push_back(ptr[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
||||||
_sendMessage(&cmd, 1);
|
_sendMessage(&cmd, 1);
|
||||||
_sendContinuedValue(len);
|
_sendContinuedValue(len);
|
||||||
for (size_t i=0 ; i<len ; ++i)
|
for (size_t i = 0; i < len; ++i)
|
||||||
m_result.push_back(reinterpret_cast<const uint8_t*>(data)[i]);
|
m_result.push_back(reinterpret_cast<const uint8_t*>(data)[i]);
|
||||||
cmd = uint8_t(Status::SysExTerm);
|
cmd = uint8_t(Status::SysExTerm);
|
||||||
_sendMessage(&cmd, 1);
|
_sendMessage(&cmd, 1);
|
||||||
|
@ -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,15 +500,14 @@ 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);
|
||||||
_sendMessage(&cmd, 1);
|
_sendMessage(&cmd, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<uint8_t>& getResult() const {return m_result;}
|
const std::vector<uint8_t>& getResult() const { return m_result; }
|
||||||
std::vector<uint8_t>& getResult() {return m_result;}
|
std::vector<uint8_t>& getResult() { return m_result; }
|
||||||
};
|
};
|
||||||
|
|
||||||
static uint32_t DecodeRLE(const unsigned char*& data)
|
static uint32_t DecodeRLE(const unsigned char*& data)
|
||||||
|
@ -622,7 +616,7 @@ std::vector<uint8_t> SongConverter::SongToMIDI(const unsigned char* data, int& v
|
||||||
{
|
{
|
||||||
std::vector<uint8_t> ret = {'M', 'T', 'h', 'd'};
|
std::vector<uint8_t> ret = {'M', 'T', 'h', 'd'};
|
||||||
uint32_t six32 = SBig(uint32_t(6));
|
uint32_t six32 = SBig(uint32_t(6));
|
||||||
for (int i=0 ; i<4 ; ++i)
|
for (int i = 0; i < 4; ++i)
|
||||||
ret.push_back(reinterpret_cast<uint8_t*>(&six32)[i]);
|
ret.push_back(reinterpret_cast<uint8_t*>(&six32)[i]);
|
||||||
|
|
||||||
ret.push_back(0);
|
ret.push_back(0);
|
||||||
|
@ -658,7 +652,7 @@ std::vector<uint8_t> SongConverter::SongToMIDI(const unsigned char* data, int& v
|
||||||
encoder.getResult().push_back(3);
|
encoder.getResult().push_back(3);
|
||||||
|
|
||||||
uint32_t tempo24 = SBig(60000000 / song.m_tempo);
|
uint32_t tempo24 = SBig(60000000 / song.m_tempo);
|
||||||
for (int i=1 ; i<4 ; ++i)
|
for (int i = 1; i < 4; ++i)
|
||||||
encoder.getResult().push_back(reinterpret_cast<uint8_t*>(&tempo24)[i]);
|
encoder.getResult().push_back(reinterpret_cast<uint8_t*>(&tempo24)[i]);
|
||||||
|
|
||||||
/* Write out tempo changes */
|
/* Write out tempo changes */
|
||||||
|
@ -676,7 +670,7 @@ std::vector<uint8_t> SongConverter::SongToMIDI(const unsigned char* data, int& v
|
||||||
encoder.getResult().push_back(3);
|
encoder.getResult().push_back(3);
|
||||||
|
|
||||||
uint32_t tempo24 = SBig(60000000 / (change.m_tempo & 0x7fffffff));
|
uint32_t tempo24 = SBig(60000000 / (change.m_tempo & 0x7fffffff));
|
||||||
for (int i=1 ; i<4 ; ++i)
|
for (int i = 1; i < 4; ++i)
|
||||||
encoder.getResult().push_back(reinterpret_cast<uint8_t*>(&tempo24)[i]);
|
encoder.getResult().push_back(reinterpret_cast<uint8_t*>(&tempo24)[i]);
|
||||||
|
|
||||||
++song.m_tempoPtr;
|
++song.m_tempoPtr;
|
||||||
|
@ -692,7 +686,7 @@ std::vector<uint8_t> SongConverter::SongToMIDI(const unsigned char* data, int& v
|
||||||
ret.push_back('r');
|
ret.push_back('r');
|
||||||
ret.push_back('k');
|
ret.push_back('k');
|
||||||
uint32_t trkSz = SBig(uint32_t(encoder.getResult().size()));
|
uint32_t trkSz = SBig(uint32_t(encoder.getResult().size()));
|
||||||
for (int i=0 ; i<4 ; ++i)
|
for (int i = 0; i < 4; ++i)
|
||||||
ret.push_back(reinterpret_cast<uint8_t*>(&trkSz)[i]);
|
ret.push_back(reinterpret_cast<uint8_t*>(&trkSz)[i]);
|
||||||
ret.insert(ret.cend(), encoder.getResult().begin(), encoder.getResult().end());
|
ret.insert(ret.cend(), encoder.getResult().begin(), encoder.getResult().end());
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -904,7 +911,7 @@ std::vector<uint8_t> SongConverter::SongToMIDI(const unsigned char* data, int& v
|
||||||
ret.push_back('r');
|
ret.push_back('r');
|
||||||
ret.push_back('k');
|
ret.push_back('k');
|
||||||
uint32_t trkSz = SBig(uint32_t(encoder.getResult().size()));
|
uint32_t trkSz = SBig(uint32_t(encoder.getResult().size()));
|
||||||
for (int i=0 ; i<4 ; ++i)
|
for (int i = 0; i < 4; ++i)
|
||||||
ret.push_back(reinterpret_cast<uint8_t*>(&trkSz)[i]);
|
ret.push_back(reinterpret_cast<uint8_t*>(&trkSz)[i]);
|
||||||
ret.insert(ret.cend(), encoder.getResult().begin(), encoder.getResult().end());
|
ret.insert(ret.cend(), encoder.getResult().begin(), encoder.getResult().end());
|
||||||
}
|
}
|
||||||
|
@ -955,7 +962,7 @@ std::vector<uint8_t> SongConverter::MIDIToSong(const std::vector<uint8_t>& data,
|
||||||
std::vector<std::pair<uint32_t, uint32_t>> tempoBuf;
|
std::vector<std::pair<uint32_t, uint32_t>> tempoBuf;
|
||||||
|
|
||||||
std::array<uint8_t, 64> chanMap;
|
std::array<uint8_t, 64> chanMap;
|
||||||
for (int i=0 ; i<64 ; ++i)
|
for (int i = 0; i < 64; ++i)
|
||||||
chanMap[i] = 0xff;
|
chanMap[i] = 0xff;
|
||||||
|
|
||||||
struct Region
|
struct Region
|
||||||
|
@ -987,7 +994,7 @@ std::vector<uint8_t> SongConverter::MIDIToSong(const std::vector<uint8_t>& data,
|
||||||
std::vector<Region> regions;
|
std::vector<Region> regions;
|
||||||
int curRegionOff = 0;
|
int curRegionOff = 0;
|
||||||
|
|
||||||
for (int i=0 ; i<header.count ; ++i)
|
for (int i = 0; i < header.count; ++i)
|
||||||
{
|
{
|
||||||
if (memcmp(&*it, "MTrk", 4))
|
if (memcmp(&*it, "MTrk", 4))
|
||||||
return {};
|
return {};
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -1039,7 +1047,7 @@ std::vector<uint8_t> SongConverter::MIDIToSong(const std::vector<uint8_t>& data,
|
||||||
begin = dec.receiveBytes(begin, end);
|
begin = dec.receiveBytes(begin, end);
|
||||||
|
|
||||||
std::vector<std::pair<int, std::multimap<int, Event>>>& results = dec.getResults();
|
std::vector<std::pair<int, std::multimap<int, Event>>>& results = dec.getResults();
|
||||||
for (int c=0 ; c<16 ; ++c)
|
for (int c = 0; c < 16; ++c)
|
||||||
{
|
{
|
||||||
int lastTrackStartTick = 0;
|
int lastTrackStartTick = 0;
|
||||||
bool didChanInit = false;
|
bool didChanInit = false;
|
||||||
|
@ -1096,7 +1104,7 @@ std::vector<uint8_t> SongConverter::MIDIToSong(const std::vector<uint8_t>& data,
|
||||||
if (big)
|
if (big)
|
||||||
{
|
{
|
||||||
uint32_t tickBig = SBig(uint32_t(eventTick - startTick));
|
uint32_t tickBig = SBig(uint32_t(eventTick - startTick));
|
||||||
for (int i=0 ; i<4 ; ++i)
|
for (int i = 0; i < 4; ++i)
|
||||||
region.eventBuf.push_back(reinterpret_cast<const uint8_t*>(&tickBig)[i]);
|
region.eventBuf.push_back(reinterpret_cast<const uint8_t*>(&tickBig)[i]);
|
||||||
region.eventBuf.push_back(0x80 | event.second.velOrVal);
|
region.eventBuf.push_back(0x80 | event.second.velOrVal);
|
||||||
region.eventBuf.push_back(0x80 | event.second.noteOrCtrl);
|
region.eventBuf.push_back(0x80 | event.second.noteOrCtrl);
|
||||||
|
@ -1104,7 +1112,7 @@ std::vector<uint8_t> SongConverter::MIDIToSong(const std::vector<uint8_t>& data,
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
uint32_t tick = uint32_t(eventTick - startTick);
|
uint32_t tick = uint32_t(eventTick - startTick);
|
||||||
for (int i=0 ; i<4 ; ++i)
|
for (int i = 0; i < 4; ++i)
|
||||||
region.eventBuf.push_back(reinterpret_cast<const uint8_t*>(&tick)[i]);
|
region.eventBuf.push_back(reinterpret_cast<const uint8_t*>(&tick)[i]);
|
||||||
region.eventBuf.push_back(0x80 | event.second.velOrVal);
|
region.eventBuf.push_back(0x80 | event.second.velOrVal);
|
||||||
region.eventBuf.push_back(0x80 | event.second.noteOrCtrl);
|
region.eventBuf.push_back(0x80 | event.second.noteOrCtrl);
|
||||||
|
@ -1126,7 +1134,7 @@ std::vector<uint8_t> SongConverter::MIDIToSong(const std::vector<uint8_t>& data,
|
||||||
if (big)
|
if (big)
|
||||||
{
|
{
|
||||||
uint32_t tickBig = SBig(uint32_t(eventTick - startTick));
|
uint32_t tickBig = SBig(uint32_t(eventTick - startTick));
|
||||||
for (int i=0 ; i<4 ; ++i)
|
for (int i = 0; i < 4; ++i)
|
||||||
region.eventBuf.push_back(reinterpret_cast<const uint8_t*>(&tickBig)[i]);
|
region.eventBuf.push_back(reinterpret_cast<const uint8_t*>(&tickBig)[i]);
|
||||||
region.eventBuf.push_back(0x80 | event.second.program);
|
region.eventBuf.push_back(0x80 | event.second.program);
|
||||||
region.eventBuf.push_back(0);
|
region.eventBuf.push_back(0);
|
||||||
|
@ -1134,7 +1142,7 @@ std::vector<uint8_t> SongConverter::MIDIToSong(const std::vector<uint8_t>& data,
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
uint32_t tick = uint32_t(eventTick - startTick);
|
uint32_t tick = uint32_t(eventTick - startTick);
|
||||||
for (int i=0 ; i<4 ; ++i)
|
for (int i = 0; i < 4; ++i)
|
||||||
region.eventBuf.push_back(reinterpret_cast<const uint8_t*>(&tick)[i]);
|
region.eventBuf.push_back(reinterpret_cast<const uint8_t*>(&tick)[i]);
|
||||||
region.eventBuf.push_back(0x80 | event.second.program);
|
region.eventBuf.push_back(0x80 | event.second.program);
|
||||||
region.eventBuf.push_back(0);
|
region.eventBuf.push_back(0);
|
||||||
|
@ -1166,7 +1174,7 @@ std::vector<uint8_t> SongConverter::MIDIToSong(const std::vector<uint8_t>& data,
|
||||||
if (big)
|
if (big)
|
||||||
{
|
{
|
||||||
uint32_t tickBig = SBig(uint32_t(eventTick - startTick));
|
uint32_t tickBig = SBig(uint32_t(eventTick - startTick));
|
||||||
for (int i=0 ; i<4 ; ++i)
|
for (int i = 0; i < 4; ++i)
|
||||||
region.eventBuf.push_back(reinterpret_cast<const uint8_t*>(&tickBig)[i]);
|
region.eventBuf.push_back(reinterpret_cast<const uint8_t*>(&tickBig)[i]);
|
||||||
uint16_t lenBig = SBig(uint16_t(event.second.length));
|
uint16_t lenBig = SBig(uint16_t(event.second.length));
|
||||||
region.eventBuf.push_back(reinterpret_cast<const uint8_t*>(&lenBig)[0]);
|
region.eventBuf.push_back(reinterpret_cast<const uint8_t*>(&lenBig)[0]);
|
||||||
|
@ -1177,7 +1185,7 @@ std::vector<uint8_t> SongConverter::MIDIToSong(const std::vector<uint8_t>& data,
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
uint32_t tick = uint32_t(eventTick - startTick);
|
uint32_t tick = uint32_t(eventTick - startTick);
|
||||||
for (int i=0 ; i<4 ; ++i)
|
for (int i = 0; i < 4; ++i)
|
||||||
region.eventBuf.push_back(reinterpret_cast<const uint8_t*>(&tick)[i]);
|
region.eventBuf.push_back(reinterpret_cast<const uint8_t*>(&tick)[i]);
|
||||||
uint16_t len = uint16_t(event.second.length);
|
uint16_t len = uint16_t(event.second.length);
|
||||||
region.eventBuf.push_back(reinterpret_cast<const uint8_t*>(&len)[0]);
|
region.eventBuf.push_back(reinterpret_cast<const uint8_t*>(&len)[0]);
|
||||||
|
@ -1219,11 +1227,10 @@ 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)
|
||||||
region.eventBuf.push_back(reinterpret_cast<const uint8_t*>(&tickBig)[i]);
|
region.eventBuf.push_back(reinterpret_cast<const uint8_t*>(&tickBig)[i]);
|
||||||
region.eventBuf.push_back(0);
|
region.eventBuf.push_back(0);
|
||||||
region.eventBuf.push_back(0);
|
region.eventBuf.push_back(0);
|
||||||
|
@ -1232,11 +1239,10 @@ 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)
|
||||||
region.eventBuf.push_back(reinterpret_cast<const uint8_t*>(&tick)[i]);
|
region.eventBuf.push_back(reinterpret_cast<const uint8_t*>(&tick)[i]);
|
||||||
region.eventBuf.push_back(0);
|
region.eventBuf.push_back(0);
|
||||||
region.eventBuf.push_back(0);
|
region.eventBuf.push_back(0);
|
||||||
|
@ -1340,7 +1346,7 @@ std::vector<uint8_t> SongConverter::MIDIToSong(const std::vector<uint8_t>& data,
|
||||||
head.swapBig();
|
head.swapBig();
|
||||||
*reinterpret_cast<SongState::Header*>(&*ret.insert(ret.cend(), 0x18, 0)) = head;
|
*reinterpret_cast<SongState::Header*>(&*ret.insert(ret.cend(), 0x18, 0)) = head;
|
||||||
|
|
||||||
for (int i=0 ; i<64 ; ++i)
|
for (int i = 0; i < 64; ++i)
|
||||||
{
|
{
|
||||||
if (i >= trackRegionIdxArr.size())
|
if (i >= trackRegionIdxArr.size())
|
||||||
{
|
{
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -1419,7 +1425,7 @@ std::vector<uint8_t> SongConverter::MIDIToSong(const std::vector<uint8_t>& data,
|
||||||
for (SongState::TrackRegion& reg : regionBuf)
|
for (SongState::TrackRegion& reg : regionBuf)
|
||||||
*reinterpret_cast<SongState::TrackRegion*>(&*ret.insert(ret.cend(), 12, 0)) = reg;
|
*reinterpret_cast<SongState::TrackRegion*>(&*ret.insert(ret.cend(), 12, 0)) = reg;
|
||||||
|
|
||||||
for (int i=0 ; i<64 ; ++i)
|
for (int i = 0; i < 64; ++i)
|
||||||
{
|
{
|
||||||
if (i >= trackRegionIdxArr.size())
|
if (i >= trackRegionIdxArr.size())
|
||||||
{
|
{
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,19 +100,18 @@ void SongState::Track::Header::swapBig()
|
||||||
SongState::Track::Track(SongState& parent, uint8_t midiChan, const TrackRegion* regions)
|
SongState::Track::Track(SongState& parent, uint8_t midiChan, const TrackRegion* regions)
|
||||||
: m_parent(parent), m_midiChan(midiChan), m_curRegion(nullptr), m_nextRegion(regions)
|
: m_parent(parent), m_midiChan(midiChan), m_curRegion(nullptr), m_nextRegion(regions)
|
||||||
{
|
{
|
||||||
for (int i=0 ; i<128 ; ++i)
|
for (int i = 0; i < 128; ++i)
|
||||||
m_remNoteLengths[i] = INT_MIN;
|
m_remNoteLengths[i] = INT_MIN;
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
|
@ -162,19 +158,19 @@ int SongState::DetectVersion(const unsigned char* ptr, bool& isBig)
|
||||||
|
|
||||||
/* First determine maximum index of MIDI regions across all tracks */
|
/* First determine maximum index of MIDI regions across all tracks */
|
||||||
uint32_t maxRegionIdx = 0;
|
uint32_t maxRegionIdx = 0;
|
||||||
for (int i=0 ; i<64 ; ++i)
|
for (int i = 0; i < 64; ++i)
|
||||||
{
|
{
|
||||||
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 = ®ion[1];
|
nextRegion = ®ion[1];
|
||||||
}
|
}
|
||||||
|
@ -182,37 +178,37 @@ int SongState::DetectVersion(const unsigned char* ptr, bool& isBig)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Perform 2 trials, first assuming revised format (more likely) */
|
/* Perform 2 trials, first assuming revised format (more likely) */
|
||||||
int v=1;
|
int v = 1;
|
||||||
for (; v>=0 ; --v)
|
for (; v >= 0; --v)
|
||||||
{
|
{
|
||||||
bool bad = false;
|
bool bad = false;
|
||||||
|
|
||||||
/* Validate all tracks */
|
/* Validate all tracks */
|
||||||
for (int i=0 ; i<64 ; ++i)
|
for (int i = 0; i < 64; ++i)
|
||||||
{
|
{
|
||||||
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 = ®ion[1];
|
nextRegion = ®ion[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;
|
||||||
}
|
}
|
||||||
|
@ -337,11 +339,12 @@ bool SongState::initialize(const unsigned char* ptr)
|
||||||
const uint8_t* chanMap = reinterpret_cast<const uint8_t*>(ptr + m_header.m_chanMapOff);
|
const uint8_t* chanMap = reinterpret_cast<const uint8_t*>(ptr + m_header.m_chanMapOff);
|
||||||
|
|
||||||
/* Initialize all tracks */
|
/* Initialize all tracks */
|
||||||
for (int i=0 ; i<64 ; ++i)
|
for (int i = 0; i < 64; ++i)
|
||||||
{
|
{
|
||||||
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
|
||||||
|
@ -377,7 +379,7 @@ bool SongState::Track::advance(Sequencer& seq, int32_t ticks)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Stop finished notes */
|
/* Stop finished notes */
|
||||||
for (int i=0 ; i<128 ; ++i)
|
for (int i = 0; i < 128; ++i)
|
||||||
{
|
{
|
||||||
if (m_remNoteLengths[i] != INT_MIN)
|
if (m_remNoteLengths[i] != INT_MIN)
|
||||||
{
|
{
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,18 +26,17 @@ 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;
|
||||||
|
|
||||||
/* Iterate each component */
|
/* Iterate each component */
|
||||||
for (auto it=m_comps.cbegin() ; it != m_comps.cend() ; ++it)
|
for (auto it = m_comps.cbegin(); it != m_comps.cend(); ++it)
|
||||||
{
|
{
|
||||||
const Component& comp = *it;
|
const Component& comp = *it;
|
||||||
float thisValue = 0.f;
|
float thisValue = 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;
|
||||||
}
|
}
|
||||||
|
@ -350,8 +347,8 @@ bool SoundMacroState::advance(Voice& vox, double dt)
|
||||||
int8_t addNote = cmd.m_data[0];
|
int8_t addNote = cmd.m_data[0];
|
||||||
ObjectId macroId = *reinterpret_cast<ObjectId*>(&cmd.m_data[1]);
|
ObjectId macroId = *reinterpret_cast<ObjectId*>(&cmd.m_data[1]);
|
||||||
int16_t macroStep = *reinterpret_cast<int16_t*>(&cmd.m_data[3]);
|
int16_t macroStep = *reinterpret_cast<int16_t*>(&cmd.m_data[3]);
|
||||||
//int8_t priority = cmd.m_data[5];
|
// int8_t priority = cmd.m_data[5];
|
||||||
//int8_t maxVoices = cmd.m_data[6];
|
// int8_t maxVoices = cmd.m_data[6];
|
||||||
|
|
||||||
std::shared_ptr<Voice> sibVox = vox.startChildMacro(addNote, macroId, macroStep);
|
std::shared_ptr<Voice> sibVox = vox.startChildMacro(addNote, macroId, macroStep);
|
||||||
if (sibVox)
|
if (sibVox)
|
||||||
|
@ -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; }
|
||||||
}
|
}
|
||||||
|
|
|
@ -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))
|
||||||
{
|
return true;
|
||||||
if (leaf == studio.get() || studio->_cyclicCheck(leaf))
|
++it;
|
||||||
return true;
|
|
||||||
++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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,46 +82,32 @@ 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)
|
||||||
{
|
{
|
||||||
matOut[i] = 0.f;
|
matOut[i] = 0.f;
|
||||||
if (map.m_channels[i] == AudioChannel::Unknown)
|
if (map.m_channels[i] == AudioChannel::Unknown)
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
378
lib/Voice.cpp
378
lib/Voice.cpp
|
@ -24,19 +24,20 @@ void Voice::_destroy()
|
||||||
|
|
||||||
Voice::~Voice()
|
Voice::~Voice()
|
||||||
{
|
{
|
||||||
//fprintf(stderr, "DEALLOC %d\n", m_vid);
|
// fprintf(stderr, "DEALLOC %d\n", m_vid);
|
||||||
}
|
}
|
||||||
|
|
||||||
Voice::Voice(Engine& engine, const AudioGroup& group, int groupId, int vid, bool emitter, std::weak_ptr<Studio> studio)
|
Voice::Voice(Engine& engine, const AudioGroup& group, int groupId, int vid, bool emitter, std::weak_ptr<Studio> studio)
|
||||||
: Entity(engine, group, groupId), m_vid(vid), m_emitter(emitter), m_studio(studio)
|
: Entity(engine, group, groupId), m_vid(vid), m_emitter(emitter), m_studio(studio)
|
||||||
{
|
{
|
||||||
//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);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Voice::_macroSampleEnd()
|
void Voice::_macroSampleEnd()
|
||||||
|
@ -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);
|
||||||
|
@ -115,7 +115,7 @@ void Voice::_doKeyOff()
|
||||||
|
|
||||||
void Voice::_setTotalPitch(int32_t cents, bool slew)
|
void Voice::_setTotalPitch(int32_t cents, bool slew)
|
||||||
{
|
{
|
||||||
//fprintf(stderr, "PITCH %d %d \n", cents, slew);
|
// fprintf(stderr, "PITCH %d %d \n", cents, slew);
|
||||||
int32_t interval = cents - m_curSample->first.m_pitch * 100;
|
int32_t interval = cents - m_curSample->first.m_pitch * 100;
|
||||||
double ratio = std::exp2(interval / 1200.0);
|
double ratio = std::exp2(interval / 1200.0);
|
||||||
m_sampleRate = m_curSample->first.m_sampleRate * ratio;
|
m_sampleRate = m_curSample->first.m_sampleRate * ratio;
|
||||||
|
@ -134,7 +134,7 @@ bool Voice::_isRecursivelyDead()
|
||||||
|
|
||||||
void Voice::_bringOutYourDead()
|
void Voice::_bringOutYourDead()
|
||||||
{
|
{
|
||||||
for (auto it = m_childVoices.begin() ; it != m_childVoices.end() ;)
|
for (auto it = m_childVoices.begin(); it != m_childVoices.end();)
|
||||||
{
|
{
|
||||||
Voice* vox = it->get();
|
Voice* vox = it->get();
|
||||||
vox->_bringOutYourDead();
|
vox->_bringOutYourDead();
|
||||||
|
@ -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,12 +237,12 @@ 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);
|
||||||
|
|
||||||
//printf("%d %f\n", m_vid, m_curVol);
|
// printf("%d %f\n", m_vid, m_curVol);
|
||||||
|
|
||||||
/* Done with envelope */
|
/* Done with envelope */
|
||||||
if (m_envelopeTime > m_envelopeDur)
|
if (m_envelopeTime > m_envelopeDur)
|
||||||
|
@ -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,24 +503,23 @@ 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:
|
||||||
{
|
{
|
||||||
const int16_t* pcm = reinterpret_cast<const int16_t*>(m_curSampleData);
|
const int16_t* pcm = reinterpret_cast<const int16_t*>(m_curSampleData);
|
||||||
remCount = std::min(samplesRem, m_lastSamplePos - m_curSamplePos);
|
remCount = std::min(samplesRem, m_lastSamplePos - m_curSamplePos);
|
||||||
for (uint32_t i=0 ; i<remCount ; ++i)
|
for (uint32_t i = 0; i < remCount; ++i)
|
||||||
data[i] = SBig(pcm[m_curSamplePos+i]);
|
data[i] = SBig(pcm[m_curSamplePos + i]);
|
||||||
decSamples = remCount;
|
decSamples = remCount;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -522,11 +537,10 @@ 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;
|
||||||
|
@ -550,48 +564,45 @@ size_t Voice::supplyAudio(size_t samples, int16_t* data)
|
||||||
|
|
||||||
switch (m_curFormat)
|
switch (m_curFormat)
|
||||||
{
|
{
|
||||||
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, remCount);
|
||||||
m_curSample->second.vadpcm.m_coefs,
|
break;
|
||||||
remCount);
|
}
|
||||||
break;
|
case SampleFormat::PCM:
|
||||||
}
|
{
|
||||||
case SampleFormat::PCM:
|
const int16_t* pcm = reinterpret_cast<const int16_t*>(m_curSampleData);
|
||||||
{
|
remCount = std::min(samplesRem, m_lastSamplePos - m_curSamplePos);
|
||||||
const int16_t* pcm = reinterpret_cast<const int16_t*>(m_curSampleData);
|
for (uint32_t i = 0; i < remCount; ++i)
|
||||||
remCount = std::min(samplesRem, m_lastSamplePos - m_curSamplePos);
|
data[i] = SBig(pcm[m_curSamplePos + i]);
|
||||||
for (uint32_t i=0 ; i<remCount ; ++i)
|
decSamples = remCount;
|
||||||
data[i] = SBig(pcm[m_curSamplePos+i]);
|
break;
|
||||||
decSamples = remCount;
|
}
|
||||||
break;
|
case SampleFormat::PCM_PC:
|
||||||
}
|
{
|
||||||
case SampleFormat::PCM_PC:
|
const int16_t* pcm = reinterpret_cast<const int16_t*>(m_curSampleData);
|
||||||
{
|
remCount = std::min(samplesRem, m_lastSamplePos - m_curSamplePos);
|
||||||
const int16_t* pcm = reinterpret_cast<const int16_t*>(m_curSampleData);
|
memmove(data, pcm + m_curSamplePos, remCount * sizeof(int16_t));
|
||||||
remCount = std::min(samplesRem, m_lastSamplePos - m_curSamplePos);
|
decSamples = remCount;
|
||||||
memmove(data, pcm + m_curSamplePos, remCount * sizeof(int16_t));
|
break;
|
||||||
decSamples = remCount;
|
}
|
||||||
break;
|
default:
|
||||||
}
|
memset(data, 0, sizeof(int16_t) * samples);
|
||||||
default:
|
return samples;
|
||||||
memset(data, 0, sizeof(int16_t) * samples);
|
|
||||||
return samples;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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,9 +892,9 @@ 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
|
||||||
offset = clamp(0, offset, numSamples);
|
offset = clamp(0, offset, numSamples);
|
||||||
|
@ -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);
|
||||||
|
@ -833,21 +924,18 @@ 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();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 */
|
||||||
}
|
|
Loading…
Reference in New Issue