mirror of https://github.com/AxioDL/amuse.git
Fix HQ reverb, better submix/sequencer allocation
This commit is contained in:
parent
c216f3d721
commit
d5b50e3633
|
@ -23,7 +23,7 @@ game archives or raw (`.proj`,`.pool`,`.sdir`,`.samp`) files is provided.
|
||||||
░░░ │ │ ┃ │ │ │ ┃ │ │ ░░░
|
░░░ │ │ ┃ │ │ │ ┃ │ │ ░░░
|
||||||
░░░ A │ S │ D ┃ F │ G │ H │ J ┃ K │ L │ ; ░░░
|
░░░ A │ S │ D ┃ F │ G │ H │ J ┃ K │ L │ ; ░░░
|
||||||
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
|
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
|
||||||
<left/right>: cycle MIDI setup / channel, <up/down>: volume, <space>: PANIC
|
<left/right>: cycle MIDI setup, <up/down>: volume, <space>: PANIC
|
||||||
<tab>: sustain pedal, <window-Y>: pitch wheel, <window-X>: mod wheel
|
<tab>: sustain pedal, <window-Y>: pitch wheel, <window-X>: mod wheel
|
||||||
<Z/X>: octave, <C/V>: velocity, <B/N>: channel, <,/.>: program, <Q>: quit
|
<Z/X>: octave, <C/V>: velocity, <B/N>: channel, <,/.>: program, <Q>: quit
|
||||||
0 Setup 0, Chan 0, Prog 0, Octave: 4, Vel: 64, VOL: 80%
|
0 Setup 0, Chan 0, Prog 0, Octave: 4, Vel: 64, VOL: 80%
|
||||||
|
|
|
@ -130,7 +130,7 @@ struct AppCallback : boo::IApplicationCallback
|
||||||
"░░░ │ │ ┃ │ │ │ ┃ │ │ ░░░\n"
|
"░░░ │ │ ┃ │ │ │ ┃ │ │ ░░░\n"
|
||||||
"░░░ A │ S │ D ┃ F │ G │ H │ J ┃ K │ L │ ; ░░░\n"
|
"░░░ A │ S │ D ┃ F │ G │ H │ J ┃ K │ L │ ; ░░░\n"
|
||||||
"░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░\n"
|
"░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░\n"
|
||||||
"<left/right>: cycle MIDI setup / channel, <up/down>: volume, <space>: PANIC\n"
|
"<left/right>: cycle MIDI setup, <up/down>: volume, <space>: PANIC\n"
|
||||||
"<tab>: sustain pedal, <window-Y>: pitch wheel, <window-X>: mod wheel\n"
|
"<tab>: sustain pedal, <window-Y>: pitch wheel, <window-X>: mod wheel\n"
|
||||||
"<Z/X>: octave, <C/V>: velocity, <B/N>: channel, <,/.>: program, <Q>: quit\n");
|
"<Z/X>: octave, <C/V>: velocity, <B/N>: channel, <,/.>: program, <Q>: quit\n");
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,7 @@ public:
|
||||||
double sampleRate, bool dynamicPitch);
|
double sampleRate, bool dynamicPitch);
|
||||||
void resetSampleRate(double sampleRate);
|
void resetSampleRate(double sampleRate);
|
||||||
void setMatrixCoefficients(const float coefs[8], bool slew);
|
void setMatrixCoefficients(const float coefs[8], bool slew);
|
||||||
|
void setSubmixMatrixCoefficients(const float coefs[8], bool slew);
|
||||||
void setPitchRatio(double ratio, bool slew);
|
void setPitchRatio(double ratio, bool slew);
|
||||||
void start();
|
void start();
|
||||||
void stop();
|
void stop();
|
||||||
|
|
|
@ -137,7 +137,7 @@ class EffectReverbHiImp : public EffectBase<T>, public EffectReverbHi
|
||||||
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;
|
float x1a8_internalCrosstalk = 0.f;
|
||||||
|
|
||||||
double m_sampleRate; /**< copy of sample rate */
|
double m_sampleRate; /**< copy of sample rate */
|
||||||
void _update();
|
void _update();
|
||||||
|
|
|
@ -37,6 +37,9 @@ public:
|
||||||
/** Set channel-gains for audio source (AudioChannel enum for array index) */
|
/** Set channel-gains for audio source (AudioChannel enum for array index) */
|
||||||
virtual void setMatrixCoefficients(const float coefs[8], bool slew)=0;
|
virtual void setMatrixCoefficients(const float coefs[8], bool slew)=0;
|
||||||
|
|
||||||
|
/** Set submix-channel-gains for audio source (AudioChannel enum for array index) */
|
||||||
|
virtual void setSubmixMatrixCoefficients(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;
|
||||||
|
|
||||||
|
|
|
@ -47,7 +47,6 @@ class Sequencer : public Entity
|
||||||
uint8_t m_chanId;
|
uint8_t m_chanId;
|
||||||
const SongGroupIndex::MIDISetup& m_setup;
|
const SongGroupIndex::MIDISetup& m_setup;
|
||||||
const SongGroupIndex::PageEntry* m_page = nullptr;
|
const SongGroupIndex::PageEntry* m_page = nullptr;
|
||||||
Submix* m_submix = nullptr;
|
|
||||||
~ChannelState();
|
~ChannelState();
|
||||||
ChannelState(Sequencer& parent, uint8_t chanId);
|
ChannelState(Sequencer& parent, uint8_t chanId);
|
||||||
|
|
||||||
|
|
|
@ -48,11 +48,11 @@ class Voice : public Entity
|
||||||
|
|
||||||
enum class SampleFormat : uint8_t
|
enum class SampleFormat : uint8_t
|
||||||
{
|
{
|
||||||
DSP, /**< GCN DSP-ucode ADPCM (very common for GameCube games) */
|
DSP, /**< GCN DSP-ucode ADPCM (very common for GameCube games) */
|
||||||
IMA, /**< IMA-ADPCM (rarely used within MusyX itself) */
|
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 */
|
||||||
|
|
|
@ -34,6 +34,11 @@ void BooBackendVoice::setMatrixCoefficients(const float coefs[8], bool slew)
|
||||||
m_booVoice->setMonoMatrixCoefficients(coefs, slew);
|
m_booVoice->setMonoMatrixCoefficients(coefs, slew);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BooBackendVoice::setSubmixMatrixCoefficients(const float coefs[8], bool slew)
|
||||||
|
{
|
||||||
|
m_booVoice->setMonoSubmixMatrixCoefficients(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);
|
||||||
|
|
|
@ -140,7 +140,7 @@ 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 ;)
|
for (size_t f=0 ; f<frameCount ; f+=160)
|
||||||
{
|
{
|
||||||
for (int c=0 ; c<chanMap.m_channelCount ; ++c)
|
for (int c=0 ; c<chanMap.m_channelCount ; ++c)
|
||||||
{
|
{
|
||||||
|
@ -153,7 +153,8 @@ void EffectReverbStdImp<T>::applyEffect(T* audio, size_t frameCount, const Chann
|
||||||
ReverbDelayLine* linesC = x78_C[c];
|
ReverbDelayLine* linesC = x78_C[c];
|
||||||
ReverbDelayLine* linesAP = x0_AP[c];
|
ReverbDelayLine* linesAP = x0_AP[c];
|
||||||
|
|
||||||
for (int s=0 ; s<160 && f<frameCount ; ++s, ++f)
|
int procSamples = std::min(160ul, frameCount - f);
|
||||||
|
for (int s=0 ; s<procSamples ; ++s)
|
||||||
{
|
{
|
||||||
float sample = audio[s * chanMap.m_channelCount + c];
|
float sample = audio[s * chanMap.m_channelCount + c];
|
||||||
|
|
||||||
|
@ -255,7 +256,7 @@ void EffectReverbHiImp<T>::_update()
|
||||||
size_t tapDelay = CTapDelays[t] * m_sampleRate / 32000.0;
|
size_t tapDelay = CTapDelays[t] * m_sampleRate / 32000.0;
|
||||||
combLine.allocate(tapDelay);
|
combLine.allocate(tapDelay);
|
||||||
combLine.setdelay(tapDelay);
|
combLine.setdelay(tapDelay);
|
||||||
x16c_combCoef[c][t] = std::pow(10.f, tapDelay * -3 / 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)
|
||||||
|
@ -301,6 +302,7 @@ void EffectReverbHiImp<T>::_update()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
x1a8_internalCrosstalk = x1dc_crosstalk;
|
||||||
m_dirty = false;
|
m_dirty = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -324,9 +326,10 @@ 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;
|
||||||
|
|
||||||
float sample = audio[c];
|
for (int s=0 ; s<sampleCount ; ++s)
|
||||||
for (int s=1 ; s<sampleCount ; ++s)
|
|
||||||
{
|
{
|
||||||
|
float sample = audio[s * chanCount + c];
|
||||||
|
|
||||||
/* Pre-delay stage */
|
/* Pre-delay stage */
|
||||||
float sample2 = sample;
|
float sample2 = sample;
|
||||||
if (preDelayTime != 0)
|
if (preDelayTime != 0)
|
||||||
|
@ -420,8 +423,7 @@ void EffectReverbHiImp<T>::_handleReverb(T* audio, int c, int chanCount, int sam
|
||||||
lineLP.x4_outPoint = 0;
|
lineLP.x4_outPoint = 0;
|
||||||
|
|
||||||
/* Mix out */
|
/* Mix out */
|
||||||
audio[(s-1) * chanCount + c] = ClampFull<T>(dampWet * allPass + dampDry * sample);
|
audio[s * chanCount + c] = ClampFull<T>(dampWet * allPass + dampDry * sample);
|
||||||
sample = audio[s * chanCount + c];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
x1b8_preDelayPtr[c] = preDelayPtr;
|
x1b8_preDelayPtr[c] = preDelayPtr;
|
||||||
|
|
|
@ -57,8 +57,12 @@ std::shared_ptr<Voice> Engine::_allocateVoice(const AudioGroup& group, int group
|
||||||
{
|
{
|
||||||
auto it = m_activeVoices.emplace(m_activeVoices.end(),
|
auto it = m_activeVoices.emplace(m_activeVoices.end(),
|
||||||
new Voice(*this, group, groupId, m_nextVid++, emitter, smx));
|
new Voice(*this, group, groupId, m_nextVid++, emitter, smx));
|
||||||
m_activeVoices.back()->m_backendVoice =
|
if (smx)
|
||||||
m_backend.allocateVoice(*m_activeVoices.back(), sampleRate, dynamicPitch);
|
m_activeVoices.back()->m_backendVoice =
|
||||||
|
smx->m_backendSubmix->allocateVoice(*m_activeVoices.back(), sampleRate, dynamicPitch);
|
||||||
|
else
|
||||||
|
m_activeVoices.back()->m_backendVoice =
|
||||||
|
m_backend.allocateVoice(*m_activeVoices.back(), sampleRate, dynamicPitch);
|
||||||
m_activeVoices.back()->m_engineIt = it;
|
m_activeVoices.back()->m_engineIt = it;
|
||||||
return m_activeVoices.back();
|
return m_activeVoices.back();
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,35 +51,28 @@ void Sequencer::_destroy()
|
||||||
m_engine.removeSubmix(m_submix);
|
m_engine.removeSubmix(m_submix);
|
||||||
m_submix = nullptr;
|
m_submix = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& chan : m_chanStates)
|
|
||||||
{
|
|
||||||
if (chan)
|
|
||||||
{
|
|
||||||
if (chan->m_submix)
|
|
||||||
{
|
|
||||||
m_engine.removeSubmix(chan->m_submix);
|
|
||||||
chan->m_submix = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Sequencer::~Sequencer() {}
|
Sequencer::~Sequencer()
|
||||||
|
{
|
||||||
|
if (m_submix)
|
||||||
|
m_engine.removeSubmix(m_submix);
|
||||||
|
}
|
||||||
|
|
||||||
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), m_submix(smx)
|
: 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->makeReverbHi(0.2f, 1.f, 1.f, 0.5f, 0.f, 0.f);
|
||||||
}
|
}
|
||||||
|
|
||||||
Sequencer::ChannelState::~ChannelState()
|
Sequencer::ChannelState::~ChannelState()
|
||||||
{
|
{
|
||||||
if (m_submix)
|
|
||||||
m_parent.m_engine.removeSubmix(m_submix);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Sequencer::ChannelState::ChannelState(Sequencer& parent, uint8_t chanId)
|
Sequencer::ChannelState::ChannelState(Sequencer& parent, uint8_t chanId)
|
||||||
|
@ -98,14 +91,10 @@ Sequencer::ChannelState::ChannelState(Sequencer& parent, uint8_t chanId)
|
||||||
m_page = it->second;
|
m_page = it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_submix = m_parent.m_engine.addSubmix(m_parent.m_submix);
|
|
||||||
if (m_setup.reverb)
|
|
||||||
m_submix->makeReverbStd(0.5f, m_setup.reverb / 127.f, 5.f, 0.5f, 0.f);
|
|
||||||
if (m_setup.chorus)
|
|
||||||
m_submix->makeChorus(15, m_setup.chorus * 5 / 127, 5000);
|
|
||||||
|
|
||||||
m_curVol = m_setup.volume / 127.f;
|
m_curVol = m_setup.volume / 127.f;
|
||||||
m_curPan = m_setup.panning / 64.f - 1.f;
|
m_curPan = m_setup.panning / 64.f - 1.f;
|
||||||
|
m_ctrlVals[0x5b] = m_setup.reverb;
|
||||||
|
m_ctrlVals[0x5d] = m_setup.chorus;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sequencer::advance(double dt)
|
void Sequencer::advance(double dt)
|
||||||
|
@ -155,7 +144,7 @@ std::shared_ptr<Voice> Sequencer::ChannelState::keyOn(uint8_t note, uint8_t velo
|
||||||
|
|
||||||
std::shared_ptr<Voice> ret = m_parent.m_engine._allocateVoice(m_parent.m_audioGroup,
|
std::shared_ptr<Voice> ret = m_parent.m_engine._allocateVoice(m_parent.m_audioGroup,
|
||||||
m_parent.m_groupId, 32000.0,
|
m_parent.m_groupId, 32000.0,
|
||||||
true, false, m_submix);
|
true, false, m_parent.m_submix);
|
||||||
if (ret)
|
if (ret)
|
||||||
{
|
{
|
||||||
m_chanVoxs[note] = ret;
|
m_chanVoxs[note] = ret;
|
||||||
|
@ -168,6 +157,7 @@ std::shared_ptr<Voice> Sequencer::ChannelState::keyOn(uint8_t note, uint8_t velo
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
ret->setVolume(m_parent.m_curVol * m_curVol);
|
ret->setVolume(m_parent.m_curVol * m_curVol);
|
||||||
|
ret->setReverbVol(m_ctrlVals[0x5b] / 127.f);
|
||||||
ret->setPan(m_curPan);
|
ret->setPan(m_curPan);
|
||||||
ret->setPitchWheel(m_curPitchWheel);
|
ret->setPitchWheel(m_curPitchWheel);
|
||||||
|
|
||||||
|
|
|
@ -190,8 +190,12 @@ std::shared_ptr<Voice> Voice::_allocateVoice(double sampleRate, bool dynamicPitc
|
||||||
{
|
{
|
||||||
auto it = m_childVoices.emplace(m_childVoices.end(), new Voice(m_engine, m_audioGroup,
|
auto it = m_childVoices.emplace(m_childVoices.end(), new Voice(m_engine, m_audioGroup,
|
||||||
m_groupId, m_engine.m_nextVid++, m_emitter, m_submix));
|
m_groupId, m_engine.m_nextVid++, m_emitter, m_submix));
|
||||||
m_childVoices.back()->m_backendVoice =
|
if (m_submix)
|
||||||
m_engine.getBackend().allocateVoice(*m_childVoices.back(), sampleRate, dynamicPitch);
|
m_childVoices.back()->m_backendVoice =
|
||||||
|
m_submix->m_backendSubmix->allocateVoice(*m_childVoices.back(), sampleRate, dynamicPitch);
|
||||||
|
else
|
||||||
|
m_childVoices.back()->m_backendVoice =
|
||||||
|
m_engine.getBackend().allocateVoice(*m_childVoices.back(), sampleRate, dynamicPitch);
|
||||||
m_childVoices.back()->m_engineIt = it;
|
m_childVoices.back()->m_engineIt = it;
|
||||||
return m_childVoices.back();
|
return m_childVoices.back();
|
||||||
}
|
}
|
||||||
|
@ -373,20 +377,9 @@ size_t Voice::supplyAudio(size_t samples, int16_t* data)
|
||||||
{
|
{
|
||||||
uint32_t samplesRem = samples;
|
uint32_t samplesRem = samples;
|
||||||
size_t samplesProc = 0;
|
size_t samplesProc = 0;
|
||||||
bool dead = true;
|
|
||||||
|
|
||||||
/* Attempt to load stopped sample for immediate decoding */
|
/* Process SoundMacro; bootstrapping sample if needed */
|
||||||
if (!m_curSample)
|
bool dead = m_state.advance(*this, samples / m_sampleRate);
|
||||||
{
|
|
||||||
dead = m_state.advance(*this, samples / m_sampleRate);
|
|
||||||
if (!dead)
|
|
||||||
{
|
|
||||||
memset(data, 0, sizeof(int16_t) * samples);
|
|
||||||
return samples;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
dead = m_state.advance(*this, samples / m_sampleRate);
|
|
||||||
|
|
||||||
if (m_curSample)
|
if (m_curSample)
|
||||||
{
|
{
|
||||||
|
@ -537,7 +530,7 @@ size_t Voice::supplyAudio(size_t samples, int16_t* data)
|
||||||
else
|
else
|
||||||
memset(data, 0, sizeof(int16_t) * samples);
|
memset(data, 0, sizeof(int16_t) * samples);
|
||||||
|
|
||||||
if (dead && 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_messageTrap.macroId == 0xffff &&
|
||||||
(!m_curSample || (m_curSample && m_volAdsr.isComplete())))
|
(!m_curSample || (m_curSample && m_volAdsr.isComplete())))
|
||||||
|
@ -744,22 +737,18 @@ void Voice::startSample(int16_t sampId, int32_t offset)
|
||||||
m_curSampleData = m_audioGroup.getSampleData(m_curSample->first.m_sampleOff);
|
m_curSampleData = m_audioGroup.getSampleData(m_curSample->first.m_sampleOff);
|
||||||
m_prev1 = 0;
|
m_prev1 = 0;
|
||||||
m_prev2 = 0;
|
m_prev2 = 0;
|
||||||
|
|
||||||
if (m_audioGroup.getDataFormat() == DataFormat::PC)
|
if (m_audioGroup.getDataFormat() == DataFormat::PC)
|
||||||
m_curFormat = SampleFormat::PCM_PC;
|
m_curFormat = SampleFormat::PCM_PC;
|
||||||
else
|
else
|
||||||
m_curFormat = SampleFormat(m_curSample->first.m_numSamples >> 24);
|
m_curFormat = SampleFormat(m_curSample->first.m_numSamples >> 24);
|
||||||
|
|
||||||
|
if (m_curFormat == SampleFormat::DSP_DRUM)
|
||||||
|
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;
|
||||||
|
|
||||||
if (m_curFormat != SampleFormat::DSP &&
|
|
||||||
m_curFormat != SampleFormat::PCM &&
|
|
||||||
m_curFormat != SampleFormat::N64 &&
|
|
||||||
m_curFormat != SampleFormat::PCM_PC)
|
|
||||||
{
|
|
||||||
m_curSample = nullptr;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool looped;
|
bool looped;
|
||||||
_checkSamplePos(looped);
|
_checkSamplePos(looped);
|
||||||
|
|
||||||
|
@ -829,6 +818,10 @@ void Voice::_setPan(float pan)
|
||||||
coefs[7] *= 1.f - std::fabs(totalSpan);
|
coefs[7] *= 1.f - std::fabs(totalSpan);
|
||||||
|
|
||||||
m_backendVoice->setMatrixCoefficients(coefs, true);
|
m_backendVoice->setMatrixCoefficients(coefs, true);
|
||||||
|
|
||||||
|
for (int i=0 ; i<8 ; ++i)
|
||||||
|
coefs[i] *= m_curReverbVol;
|
||||||
|
m_backendVoice->setSubmixMatrixCoefficients(coefs, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Voice::setPan(float pan)
|
void Voice::setPan(float pan)
|
||||||
|
@ -946,7 +939,10 @@ void Voice::setPitchSweep2(uint8_t times, int16_t add)
|
||||||
|
|
||||||
void Voice::setReverbVol(float rvol)
|
void Voice::setReverbVol(float rvol)
|
||||||
{
|
{
|
||||||
m_curReverbVol = rvol;
|
m_curReverbVol = clamp(0.f, rvol, 1.f);
|
||||||
|
_setPan(m_curPan);
|
||||||
|
for (std::shared_ptr<Voice>& vox : m_childVoices)
|
||||||
|
vox->setReverbVol(rvol);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Voice::setAdsr(ObjectId adsrId, bool dls)
|
void Voice::setAdsr(ObjectId adsrId, bool dls)
|
||||||
|
@ -1029,6 +1025,8 @@ void Voice::_notifyCtrlChange(uint8_t ctrl, int8_t val)
|
||||||
else
|
else
|
||||||
setPedal(false);
|
setPedal(false);
|
||||||
}
|
}
|
||||||
|
else if (ctrl == 0x5b)
|
||||||
|
setReverbVol(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);
|
||||||
|
|
Loading…
Reference in New Issue