VST bug fixes, still having some odd discontinuity issues

This commit is contained in:
Jack Andersen 2016-06-14 14:36:25 -10:00
parent 7659371cb6
commit 3521d94d1c
10 changed files with 224 additions and 97 deletions

View File

@ -83,5 +83,5 @@ if(TARGET boo)
# Multi-platform CLI tool # Multi-platform CLI tool
add_executable(amuseplay WIN32 driver/main.cpp) add_executable(amuseplay WIN32 driver/main.cpp)
target_link_libraries(amuseplay amuse boo ${BOO_SYS_LIBS} logvisor athena-core ${ZLIB_LIBRARIES}) target_link_libraries(amuseplay amuse boo ${BOO_SYS_LIBS} Shlwapi logvisor athena-core ${ZLIB_LIBRARIES})
endif() endif()

View File

@ -413,9 +413,16 @@ void AudioGroupFilePresenter::populateGroupColumn(VSTEditor& editor, int collect
CollectionIterator& it = m_iteratorVec[collectionIdx]; CollectionIterator& it = m_iteratorVec[collectionIdx];
if (fileIdx < it->second->m_iteratorVec.size()) if (fileIdx < it->second->m_iteratorVec.size())
{ {
size_t idx = 0;
AudioGroupCollection::GroupIterator& git = it->second->m_iteratorVec[fileIdx]; AudioGroupCollection::GroupIterator& git = it->second->m_iteratorVec[fileIdx];
item.pszText = LPWSTR(git->first.c_str()); for (AudioGroupDataCollection::GroupToken& gtok : git->second->m_groupTokens)
ListView_InsertItem(editor.m_groupListView, &item); {
wchar_t name[256];
wnsprintf(name, 256, L"%d (%s)", gtok.m_groupId, gtok.m_song ? L"Song" : L"SFX");
item.pszText = name;
item.iItem = idx++;
ListView_InsertItem(editor.m_groupListView, &item);
}
} }
} }
} }

View File

@ -12,7 +12,7 @@ if (WIN32 AND (EXISTS ${VST3_SDK_ROOT}))
${VST2_DIR}/audioeffect.cpp ${VST2_DIR}/audioeffect.cpp
${VST2_DIR}/audioeffectx.cpp ${VST2_DIR}/audioeffectx.cpp
FileOpenDialog.hpp FileOpenDialog.cpp) FileOpenDialog.hpp FileOpenDialog.cpp)
target_link_libraries(amuse-vst amuse boo soxr ${ZLIB_LIBRARIES} ${BOO_SYS_LIBS} target_link_libraries(amuse-vst amuse boo soxr ${ZLIB_LIBRARIES} Winmm soxr
Msimg32 Shlwapi logvisor athena-core) Msimg32 Shlwapi logvisor athena-core)
set_target_properties(amuse-vst PROPERTIES LINK_FLAGS "/EXPORT:VSTPluginMain") set_target_properties(amuse-vst PROPERTIES LINK_FLAGS "/EXPORT:VSTPluginMain")
endif() endif()

View File

@ -3,15 +3,15 @@
#include <Shlobj.h> #include <Shlobj.h>
#include <logvisor/logvisor.hpp> #include <logvisor/logvisor.hpp>
#undef min
#undef max
struct VSTVoiceEngine : boo::BaseAudioVoiceEngine struct VSTVoiceEngine : boo::BaseAudioVoiceEngine
{ {
std::vector<float> m_interleavedBuf; std::vector<float> m_interleavedBuf;
float** m_outputData = nullptr; float** m_outputData = nullptr;
size_t m_renderFrames = 0; size_t m_renderFrames = 0;
size_t m_curBufFrame = 0;
int m_reqGroup = 0;
int m_curGroup = 0;
std::shared_ptr<amuse::Sequencer> m_curSeq;
boo::AudioChannelSet _getAvailableSet() boo::AudioChannelSet _getAvailableSet()
{ {
@ -85,6 +85,9 @@ struct VSTVoiceEngine : boo::BaseAudioVoiceEngine
unsigned chCount = ChannelCount(m_mixInfo.m_channels); unsigned chCount = ChannelCount(m_mixInfo.m_channels);
m_5msFrames = m_mixInfo.m_sampleRate * 5 / 1000; m_5msFrames = m_mixInfo.m_sampleRate * 5 / 1000;
m_curBufFrame = m_5msFrames;
m_mixInfo.m_periodFrames = m_5msFrames;
m_interleavedBuf.resize(m_5msFrames * 2);
boo::ChannelMap& chMapOut = m_mixInfo.m_channelMap; boo::ChannelMap& chMapOut = m_mixInfo.m_channelMap;
chMapOut.m_channelCount = 2; chMapOut.m_channelCount = 2;
@ -109,13 +112,32 @@ struct VSTVoiceEngine : boo::BaseAudioVoiceEngine
void pumpAndMixVoices() void pumpAndMixVoices()
{ {
_pumpAndMixVoices(m_renderFrames, m_interleavedBuf.data()); for (size_t f=0 ; f<m_renderFrames ;)
for (size_t i=0 ; i<2 ; ++i)
{ {
float* bufOut = m_outputData[i]; size_t remRenderFrames = std::min(m_renderFrames - f, m_5msFrames - m_curBufFrame);
for (size_t f=0 ; f<m_renderFrames ; ++f) for (size_t i=0 ; i<2 ; ++i)
bufOut[f] = m_interleavedBuf[f*2+i]; {
float* bufOut = m_outputData[i];
for (size_t lf=0 ; lf<remRenderFrames ; ++lf)
bufOut[f+lf] = m_interleavedBuf[(m_curBufFrame+lf)*2+i];
}
m_curBufFrame += remRenderFrames;
f += remRenderFrames;
if (m_curBufFrame == m_5msFrames)
{
_pumpAndMixVoices(m_5msFrames, m_interleavedBuf.data());
m_curBufFrame = 0;
remRenderFrames = std::min(m_renderFrames - f, m_5msFrames);
for (size_t i=0 ; i<2 ; ++i)
{
float* bufOut = m_outputData[i];
for (size_t lf=0 ; lf<remRenderFrames ; ++lf)
bufOut[f+lf] = m_interleavedBuf[lf*2+i];
}
f += remRenderFrames;
}
} }
} }
@ -166,16 +188,16 @@ AEffEditor* VSTBackend::getEditor()
VstInt32 VSTBackend::processEvents(VstEvents* events) VstInt32 VSTBackend::processEvents(VstEvents* events)
{ {
std::unique_lock<std::mutex> lk(m_lock);
VSTVoiceEngine& engine = static_cast<VSTVoiceEngine&>(*m_booBackend); VSTVoiceEngine& engine = static_cast<VSTVoiceEngine&>(*m_booBackend);
/* Handle group load request */ /* Handle group load request */
int reqGroup = engine.m_reqGroup; if (m_curGroup != m_reqGroup)
if (engine.m_curGroup != reqGroup)
{ {
engine.m_curGroup = reqGroup; m_curGroup = m_reqGroup;
if (engine.m_curSeq) if (m_curSeq)
engine.m_curSeq->kill(); m_curSeq->kill();
engine.m_curSeq = m_engine->seqPlay(reqGroup, -1, nullptr); m_curSeq = m_engine->seqPlay(m_reqGroup, -1, nullptr);
} }
if (engine.m_midiReceiver) if (engine.m_midiReceiver)
@ -197,6 +219,7 @@ VstInt32 VSTBackend::processEvents(VstEvents* events)
void VSTBackend::processReplacing(float**, float** outputs, VstInt32 sampleFrames) void VSTBackend::processReplacing(float**, float** outputs, VstInt32 sampleFrames)
{ {
std::unique_lock<std::mutex> lk(m_lock);
VSTVoiceEngine& engine = static_cast<VSTVoiceEngine&>(*m_booBackend); VSTVoiceEngine& engine = static_cast<VSTVoiceEngine&>(*m_booBackend);
/* Output buffers */ /* Output buffers */
@ -277,16 +300,19 @@ void VSTBackend::setBlockSize(VstInt32 blockSize)
{ {
AudioEffectX::setBlockSize(blockSize); AudioEffectX::setBlockSize(blockSize);
VSTVoiceEngine& engine = static_cast<VSTVoiceEngine&>(*m_booBackend); VSTVoiceEngine& engine = static_cast<VSTVoiceEngine&>(*m_booBackend);
engine.m_interleavedBuf.resize(blockSize * 2);
engine._rebuildAudioRenderClient(engine.mixInfo().m_sampleRate, blockSize); engine._rebuildAudioRenderClient(engine.mixInfo().m_sampleRate, blockSize);
} }
void VSTBackend::loadGroupSequencer(int collectionIdx, int fileIdx, int groupIdx) void VSTBackend::loadGroupFile(int collectionIdx, int fileIdx)
{ {
std::unique_lock<std::mutex> lk(m_lock);
if (m_curSeq) if (m_curSeq)
{ {
m_curSeq->kill(); m_curSeq->kill();
m_curSeq.reset(); m_curSeq.reset();
m_curGroup = -1;
m_reqGroup = -1;
} }
if (collectionIdx < m_filePresenter.m_iteratorVec.size()) if (collectionIdx < m_filePresenter.m_iteratorVec.size())
@ -299,19 +325,34 @@ void VSTBackend::loadGroupSequencer(int collectionIdx, int fileIdx, int groupIdx
m_curData->removeFromEngine(*m_engine); m_curData->removeFromEngine(*m_engine);
git->second->addToEngine(*m_engine); git->second->addToEngine(*m_engine);
m_curData = git->second.get(); m_curData = git->second.get();
}
}
}
if (groupIdx < git->second->m_groupTokens.size()) void VSTBackend::setGroup(int groupIdx, bool immediate)
{ {
AudioGroupDataCollection::GroupToken& groupTok = git->second->m_groupTokens[groupIdx]; std::unique_lock<std::mutex> lk(m_lock);
if (groupTok.m_song)
m_curSeq = m_engine->seqPlay(groupTok.m_groupId, -1, nullptr); if (!m_curData)
} return;
if (groupIdx < m_curData->m_groupTokens.size())
{
const AudioGroupDataCollection::GroupToken& groupTok = m_curData->m_groupTokens[groupIdx];
m_reqGroup = groupTok.m_groupId;
if (immediate)
{
if (m_curSeq)
m_curSeq->kill();
m_curSeq = m_engine->seqPlay(groupTok.m_groupId, -1, nullptr);
} }
} }
} }
void VSTBackend::setNormalProgram(int programNo) void VSTBackend::setNormalProgram(int programNo)
{ {
std::unique_lock<std::mutex> lk(m_lock);
if (!m_curSeq) if (!m_curSeq)
return; return;
m_curSeq->setChanProgram(0, programNo); m_curSeq->setChanProgram(0, programNo);
@ -319,6 +360,8 @@ void VSTBackend::setNormalProgram(int programNo)
void VSTBackend::setDrumProgram(int programNo) void VSTBackend::setDrumProgram(int programNo)
{ {
std::unique_lock<std::mutex> lk(m_lock);
if (!m_curSeq) if (!m_curSeq)
return; return;
m_curSeq->setChanProgram(9, programNo); m_curSeq->setChanProgram(9, programNo);

View File

@ -28,10 +28,13 @@ public:
/** Actual plugin implementation class */ /** Actual plugin implementation class */
class VSTBackend : public AudioEffectX class VSTBackend : public AudioEffectX
{ {
std::mutex m_lock;
std::unique_ptr<boo::IAudioVoiceEngine> m_booBackend; std::unique_ptr<boo::IAudioVoiceEngine> m_booBackend;
std::experimental::optional<amuse::VSTBackendVoiceAllocator> m_voxAlloc; std::experimental::optional<amuse::VSTBackendVoiceAllocator> m_voxAlloc;
std::experimental::optional<amuse::Engine> m_engine; std::experimental::optional<amuse::Engine> m_engine;
std::shared_ptr<amuse::Sequencer> m_curSeq; std::shared_ptr<amuse::Sequencer> m_curSeq;
int m_reqGroup = -1;
int m_curGroup = -1;
const AudioGroupDataCollection* m_curData = nullptr; const AudioGroupDataCollection* m_curData = nullptr;
size_t m_curFrame = 0; size_t m_curFrame = 0;
std::wstring m_userDir; std::wstring m_userDir;
@ -59,7 +62,8 @@ public:
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 loadGroupSequencer(int collectionIdx, int fileIdx, int groupIdx); void loadGroupFile(int collectionIdx, int fileIdx);
void setGroup(int groupIdx, bool immediate);
void setNormalProgram(int programNo); void setNormalProgram(int programNo);
void setDrumProgram(int programNo); void setDrumProgram(int programNo);

View File

@ -53,6 +53,8 @@ LRESULT CALLBACK VSTEditor::WindowProc(HWND hwnd,
} }
case TVN_SELCHANGED: case TVN_SELCHANGED:
{ {
if (editor.m_deferredCollectionSel)
return 0;
NMTREEVIEW& itemAct = *reinterpret_cast<LPNMTREEVIEW>(lParam); NMTREEVIEW& itemAct = *reinterpret_cast<LPNMTREEVIEW>(lParam);
if (itemAct.hdr.hwndFrom == editor.m_collectionTree) if (itemAct.hdr.hwndFrom == editor.m_collectionTree)
editor.selectCollection(itemAct.itemNew.lParam); editor.selectCollection(itemAct.itemNew.lParam);
@ -324,8 +326,9 @@ void VSTEditor::close()
void VSTEditor::update() void VSTEditor::update()
{ {
m_backend.getFilePresenter().populateCollectionColumn(*this); m_backend.getFilePresenter().populateCollectionColumn(*this);
m_backend.loadGroupFile(m_selCollectionIdx, m_selFileIdx);
m_backend.getFilePresenter().populateGroupColumn(*this, m_selCollectionIdx, m_selFileIdx); m_backend.getFilePresenter().populateGroupColumn(*this, m_selCollectionIdx, m_selFileIdx);
m_backend.loadGroupSequencer(m_selCollectionIdx, m_selFileIdx, m_selGroupIdx); m_backend.setGroup(m_selGroupIdx, true);
m_backend.getFilePresenter().populatePageColumn(*this, m_selCollectionIdx, m_selFileIdx, m_selGroupIdx); m_backend.getFilePresenter().populatePageColumn(*this, m_selCollectionIdx, m_selFileIdx, m_selGroupIdx);
selectPage(m_selPageIdx); selectPage(m_selPageIdx);
_reselectColumns(); _reselectColumns();
@ -394,6 +397,7 @@ void VSTEditor::selectCollection(LPARAM idx)
Button_Enable(m_collectionRemove, FALSE); Button_Enable(m_collectionRemove, FALSE);
m_selCollectionIdx = rootIdx; m_selCollectionIdx = rootIdx;
m_selFileIdx = subIdx; m_selFileIdx = subIdx;
m_backend.loadGroupFile(m_selCollectionIdx, m_selFileIdx);
m_backend.getFilePresenter().populateGroupColumn(*this, rootIdx, subIdx); m_backend.getFilePresenter().populateGroupColumn(*this, rootIdx, subIdx);
} }
else else
@ -408,7 +412,7 @@ void VSTEditor::selectCollection(LPARAM idx)
void VSTEditor::selectGroup(int idx) void VSTEditor::selectGroup(int idx)
{ {
m_selGroupIdx = idx; m_selGroupIdx = idx;
m_backend.loadGroupSequencer(m_selCollectionIdx, m_selFileIdx, m_selGroupIdx); m_backend.setGroup(m_selGroupIdx, false);
m_backend.getFilePresenter().populatePageColumn(*this, m_selCollectionIdx, m_selFileIdx, m_selGroupIdx); m_backend.getFilePresenter().populatePageColumn(*this, m_selCollectionIdx, m_selFileIdx, m_selGroupIdx);
} }

View File

@ -27,8 +27,10 @@ enum class SequencerState
class Sequencer : public Entity class Sequencer : public Entity
{ {
friend class Engine; friend class Engine;
const SongGroupIndex& m_songGroup; /**< 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 */
std::vector<const SFXGroupIndex::SFXEntry*> m_sfxMappings; /**< SFX entries are mapped to MIDI keys this via this */
Submix* m_submix = nullptr; /**< Submix this sequencer outputs to (or NULL for the main output mix) */ Submix* m_submix = nullptr; /**< Submix this sequencer outputs to (or NULL for the main output mix) */
const unsigned char* m_arrData = nullptr; /**< Current playing arrangement data */ const unsigned char* m_arrData = nullptr; /**< Current playing arrangement data */
@ -79,11 +81,13 @@ class Sequencer : public Entity
void _bringOutYourDead(); void _bringOutYourDead();
void _destroy(); void _destroy();
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, Submix* smx); const SongGroupIndex* songGroup, int setupId, Submix* smx);
Sequencer(Engine& engine, const AudioGroup& group, int groupId,
const SFXGroupIndex* sfxGroup, Submix* smx);
/** Advance current song data (if any) */ /** Advance current song data (if any) */
void advance(double dt); void advance(double dt);

View File

@ -73,11 +73,20 @@ Engine::_allocateSequencer(const AudioGroup& group, int groupId,
int setupId, Submix* smx) int setupId, Submix* smx)
{ {
const SongGroupIndex* songGroup = group.getProj().getSongGroupIndex(groupId); const SongGroupIndex* songGroup = group.getProj().getSongGroupIndex(groupId);
if (!songGroup) if (songGroup)
return {}; {
auto it = m_activeSequencers.emplace(m_activeSequencers.end(), auto it = m_activeSequencers.emplace(m_activeSequencers.end(),
new Sequencer(*this, group, groupId, *songGroup, setupId, smx)); new Sequencer(*this, group, groupId, songGroup, setupId, smx));
return it; return it;
}
const SFXGroupIndex* sfxGroup = group.getProj().getSFXGroupIndex(groupId);
if (sfxGroup)
{
auto it = m_activeSequencers.emplace(m_activeSequencers.end(),
new Sequencer(*this, group, groupId, sfxGroup, smx));
return it;
}
return {};
} }
std::list<Submix>::iterator Engine::_allocateSubmix(Submix* smx) std::list<Submix>::iterator Engine::_allocateSubmix(Submix* smx)
@ -407,16 +416,27 @@ std::shared_ptr<Sequencer> Engine::seqPlay(int groupId, int songId,
const unsigned char* arrData, Submix* smx) const unsigned char* arrData, Submix* smx)
{ {
std::pair<AudioGroup*, const SongGroupIndex*> songGrp = _findSongGroup(groupId); std::pair<AudioGroup*, const SongGroupIndex*> songGrp = _findSongGroup(groupId);
if (!songGrp.second) if (songGrp.second)
return {}; {
std::list<std::shared_ptr<Sequencer>>::iterator ret = _allocateSequencer(*songGrp.first, groupId, songId, smx);
if (!*ret)
return {};
std::list<std::shared_ptr<Sequencer>>::iterator ret = _allocateSequencer(*songGrp.first, groupId, songId, smx); if (arrData)
if (!*ret) (*ret)->playSong(arrData);
return {}; return *ret;
}
if (arrData) std::pair<AudioGroup*, const SFXGroupIndex*> sfxGrp = _findSFXGroup(groupId);
(*ret)->playSong(arrData); if (sfxGrp.second)
return *ret; {
std::list<std::shared_ptr<Sequencer>>::iterator ret = _allocateSequencer(*sfxGrp.first, groupId, songId, smx);
if (!*ret)
return {};
return *ret;
}
return {};
} }
/** Find voice from VoiceId */ /** Find voice from VoiceId */

View File

@ -2,6 +2,7 @@
#include "amuse/Submix.hpp" #include "amuse/Submix.hpp"
#include "amuse/Voice.hpp" #include "amuse/Voice.hpp"
#include "amuse/Engine.hpp" #include "amuse/Engine.hpp"
#include <map>
namespace amuse namespace amuse
{ {
@ -50,7 +51,7 @@ void Sequencer::_destroy()
{ {
m_engine.removeSubmix(m_submix); m_engine.removeSubmix(m_submix);
m_submix = nullptr; m_submix = nullptr;
} }
} }
Sequencer::~Sequencer() Sequencer::~Sequencer()
@ -63,17 +64,33 @@ Sequencer::~Sequencer()
} }
Sequencer::Sequencer(Engine& engine, const AudioGroup& group, int groupId, Sequencer::Sequencer(Engine& engine, const AudioGroup& group, int groupId,
const SongGroupIndex& songGroup, int setupId, Submix* smx) const SongGroupIndex* songGroup, int setupId, Submix* smx)
: Entity(engine, group, groupId), m_songGroup(songGroup) : Entity(engine, group, groupId), m_songGroup(songGroup)
{ {
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();
m_submix = m_engine.addSubmix(smx); m_submix = m_engine.addSubmix(smx);
m_submix->makeReverbHi(0.2f, 0.65f, 1.f, 0.5f, 0.f, 0.f); m_submix->makeReverbHi(0.2f, 0.65f, 1.f, 0.5f, 0.f, 0.f);
} }
Sequencer::Sequencer(Engine& engine, const AudioGroup& group, int groupId,
const SFXGroupIndex* sfxGroup, Submix* smx)
: Entity(engine, group, groupId), m_sfxGroup(sfxGroup)
{
m_submix = m_engine.addSubmix(smx);
m_submix->makeReverbHi(0.2f, 0.65f, 1.f, 0.5f, 0.f, 0.f);
std::map<uint16_t, const SFXGroupIndex::SFXEntry*> sortSFX;
for (const auto& sfx : sfxGroup->m_sfxEntries)
sortSFX[sfx.first] = sfx.second;
m_sfxMappings.reserve(sortSFX.size());
for (const auto& sfx : sortSFX)
m_sfxMappings.push_back(sfx.second);
}
Sequencer::ChannelState::~ChannelState() Sequencer::ChannelState::~ChannelState()
{ {
} }
@ -81,43 +98,53 @@ 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_midiSetup) if (m_parent.m_songGroup)
{ {
m_setup = &m_parent.m_midiSetup[chanId]; if (m_parent.m_midiSetup)
if (chanId == 9)
{ {
auto it = m_parent.m_songGroup.m_drumPages.find(m_setup->programNo); m_setup = &m_parent.m_midiSetup[chanId];
if (it != m_parent.m_songGroup.m_drumPages.cend())
m_page = it->second; if (chanId == 9)
{
auto it = m_parent.m_songGroup->m_drumPages.find(m_setup->programNo);
if (it != m_parent.m_songGroup->m_drumPages.cend())
m_page = it->second;
}
else
{
auto it = m_parent.m_songGroup->m_normPages.find(m_setup->programNo);
if (it != m_parent.m_songGroup->m_normPages.cend())
m_page = it->second;
}
m_curVol = m_setup->volume / 127.f;
m_curPan = m_setup->panning / 64.f - 1.f;
m_ctrlVals[0x5b] = m_setup->reverb;
m_ctrlVals[0x5d] = m_setup->chorus;
} }
else else
{ {
auto it = m_parent.m_songGroup.m_normPages.find(m_setup->programNo); if (chanId == 9)
if (it != m_parent.m_songGroup.m_normPages.cend()) {
m_page = it->second; auto it = m_parent.m_songGroup->m_drumPages.find(0);
} if (it != m_parent.m_songGroup->m_drumPages.cend())
m_page = it->second;
}
else
{
auto it = m_parent.m_songGroup->m_normPages.find(0);
if (it != m_parent.m_songGroup->m_normPages.cend())
m_page = it->second;
}
m_curVol = m_setup->volume / 127.f; m_curVol = 1.f;
m_curPan = m_setup->panning / 64.f - 1.f; m_curPan = 0.f;
m_ctrlVals[0x5b] = m_setup->reverb; m_ctrlVals[0x5b] = 0;
m_ctrlVals[0x5d] = m_setup->chorus; m_ctrlVals[0x5d] = 0;
}
} }
else else if (m_parent.m_sfxGroup)
{ {
if (chanId == 9)
{
auto it = m_parent.m_songGroup.m_drumPages.find(0);
if (it != m_parent.m_songGroup.m_drumPages.cend())
m_page = it->second;
}
else
{
auto it = m_parent.m_songGroup.m_normPages.find(0);
if (it != m_parent.m_songGroup.m_normPages.cend())
m_page = it->second;
}
m_curVol = 1.f; m_curVol = 1.f;
m_curPan = 0.f; m_curPan = 0.f;
m_ctrlVals[0x5b] = 0; m_ctrlVals[0x5b] = 0;
@ -160,7 +187,7 @@ size_t Sequencer::getVoiceCount() const
std::shared_ptr<Voice> Sequencer::ChannelState::keyOn(uint8_t note, uint8_t velocity) std::shared_ptr<Voice> Sequencer::ChannelState::keyOn(uint8_t note, uint8_t velocity)
{ {
if (!m_page) if (m_parent.m_songGroup && !m_page)
return {}; return {};
/* If portamento is enabled for voice, pre-empt spawning new voices */ /* If portamento is enabled for voice, pre-empt spawning new voices */
@ -196,7 +223,19 @@ std::shared_ptr<Voice> Sequencer::ChannelState::keyOn(uint8_t note, uint8_t velo
m_chanVoxs[note] = *ret; m_chanVoxs[note] = *ret;
(*ret)->installCtrlValues(m_ctrlVals); (*ret)->installCtrlValues(m_ctrlVals);
ObjectId oid = (m_parent.m_audioGroup.getDataFormat() == DataFormat::PC) ? m_page->objId : SBig(m_page->objId); ObjectId oid;
if (m_parent.m_songGroup)
oid = (m_parent.m_audioGroup.getDataFormat() == DataFormat::PC) ? m_page->objId : SBig(m_page->objId);
else if (m_parent.m_sfxMappings.size())
{
size_t lookupIdx = note % m_parent.m_sfxMappings.size();
const SFXGroupIndex::SFXEntry* sfxEntry = m_parent.m_sfxMappings[lookupIdx];
oid = (m_parent.m_audioGroup.getDataFormat() == DataFormat::PC) ? sfxEntry->objId : SBig(sfxEntry->objId);
note = sfxEntry->defKey;
}
else
return {};
if (!(*ret)->loadSoundObject(oid, 0, m_parent.m_ticksPerSec, note, velocity, m_ctrlVals[1])) if (!(*ret)->loadSoundObject(oid, 0, m_parent.m_ticksPerSec, note, velocity, m_ctrlVals[1]))
{ {
m_parent.m_engine._destroyVoice(ret); m_parent.m_engine._destroyVoice(ret);
@ -270,24 +309,27 @@ void Sequencer::ChannelState::setCtrlValue(uint8_t ctrl, int8_t val)
bool Sequencer::ChannelState::programChange(int8_t prog) bool Sequencer::ChannelState::programChange(int8_t prog)
{ {
if (m_chanId == 9) if (m_parent.m_songGroup)
{ {
auto it = m_parent.m_songGroup.m_drumPages.find(prog); if (m_chanId == 9)
if (it != m_parent.m_songGroup.m_drumPages.cend())
{ {
m_page = it->second; auto it = m_parent.m_songGroup->m_drumPages.find(prog);
m_curProgram = prog; if (it != m_parent.m_songGroup->m_drumPages.cend())
return true; {
m_page = it->second;
m_curProgram = prog;
return true;
}
} }
} else
else
{
auto it = m_parent.m_songGroup.m_normPages.find(prog);
if (it != m_parent.m_songGroup.m_normPages.cend())
{ {
m_page = it->second; auto it = m_parent.m_songGroup->m_normPages.find(prog);
m_curProgram = prog; if (it != m_parent.m_songGroup->m_normPages.cend())
return true; {
m_page = it->second;
m_curProgram = prog;
return true;
}
} }
} }
return false; return false;

View File

@ -6,6 +6,9 @@
#include "amuse/AudioGroupPool.hpp" #include "amuse/AudioGroupPool.hpp"
#include <string.h> #include <string.h>
#undef SendMessage
#undef GetMessage
namespace amuse namespace amuse
{ {
@ -346,7 +349,7 @@ bool SoundMacroState::advance(Voice& vox, double dt)
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)
m_lastPlayMacroVid = sibVox->vid(); m_lastPlayMacroVid = sibVox->vid();