Skip to content

Commit

Permalink
fix drum panning
Browse files Browse the repository at this point in the history
The drum panning is now correctly added to the track's panning in order
to produce correct results.
  • Loading branch information
ipatix committed Jun 12, 2021
1 parent 0442cb3 commit 1788727
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 44 deletions.
22 changes: 12 additions & 10 deletions src/CGBChannel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
* public CGBChannel
*/

CGBChannel::CGBChannel(uint8_t owner, ADSR env, Note note, uint8_t vol, int8_t pan)
: env(env), note(note), owner(owner)
CGBChannel::CGBChannel(uint8_t owner, ADSR env, Note note, uint8_t vol, int8_t pan, int8_t instPan)
: env(env), note(note), owner(owner), instPan(instPan)
{
this->env.att &= 0x7;
this->env.dec &= 0x7;
Expand All @@ -30,11 +30,13 @@ uint8_t CGBChannel::GetOwner() const

void CGBChannel::SetVol(uint8_t vol, int8_t pan)
{
int combinedPan = std::clamp(pan + instPan, -64, +63);

if (eState < EnvState::REL) {
if (pan < -21) {
if (combinedPan < -21) {
// snap left
this->pan = Pan::LEFT;
} else if (pan > 20) {
} else if (combinedPan > 20) {
// snap right
this->pan = Pan::RIGHT;
} else {
Expand Down Expand Up @@ -310,8 +312,8 @@ void CGBChannel::updateVolFade()
* public SquareChannel
*/

SquareChannel::SquareChannel(uint8_t owner, WaveDuty wd, ADSR env, Note note, uint8_t vol, int8_t pan, int16_t pitch)
: CGBChannel(owner, env, note, vol, pan)
SquareChannel::SquareChannel(uint8_t owner, WaveDuty wd, ADSR env, Note note, uint8_t vol, int8_t pan, int8_t instPan, int16_t pitch)
: CGBChannel(owner, env, note, vol, pan, instPan)
{
SetPitch(pitch);

Expand Down Expand Up @@ -392,8 +394,8 @@ uint8_t WaveChannel::volLut[] = {
0, 0, 4, 4, 4, 4, 8, 8, 8, 8, 12, 12, 12, 12, 16, 16
};

WaveChannel::WaveChannel(uint8_t owner, const uint8_t *wavePtr, ADSR env, Note note, uint8_t vol, int8_t pan, int16_t pitch)
: CGBChannel(owner, env, note, vol, pan)
WaveChannel::WaveChannel(uint8_t owner, const uint8_t *wavePtr, ADSR env, Note note, uint8_t vol, int8_t pan, int8_t instPan, int16_t pitch)
: CGBChannel(owner, env, note, vol, pan, instPan)
{
SetPitch(pitch);

Expand Down Expand Up @@ -474,8 +476,8 @@ bool WaveChannel::sampleFetchCallback(std::vector<float>& fetchBuffer, size_t sa
* public NoiseChannel
*/

NoiseChannel::NoiseChannel(uint8_t owner, NoisePatt np, ADSR env, Note note, uint8_t vol, int8_t pan, int16_t pitch)
: CGBChannel(owner, env, note, vol, pan)
NoiseChannel::NoiseChannel(uint8_t owner, NoisePatt np, ADSR env, Note note, uint8_t vol, int8_t pan, int8_t instPan, int16_t pitch)
: CGBChannel(owner, env, note, vol, pan, instPan)
{
SetPitch(pitch);
this->rs = std::make_unique<NearestResampler>();
Expand Down
9 changes: 5 additions & 4 deletions src/CGBChannel.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
class CGBChannel
{
public:
CGBChannel(uint8_t owner, ADSR env, Note note, uint8_t vol, int8_t pan);
CGBChannel(uint8_t owner, ADSR env, Note note, uint8_t vol, int8_t pan, int8_t instPan);
CGBChannel(const CGBChannel&) = delete;
CGBChannel& operator=(const CGBChannel&) = delete;
virtual ~CGBChannel() = default;
Expand Down Expand Up @@ -46,6 +46,7 @@ class CGBChannel
uint8_t envPeak = 0;
uint8_t envSustain = 0;
uint8_t owner;
const int8_t instPan;
// these values are always 1 frame behind in order to provide a smooth transition
Pan fromPan = Pan::CENTER;
uint8_t fromEnvLevel = 0;
Expand All @@ -54,7 +55,7 @@ class CGBChannel
class SquareChannel : public CGBChannel
{
public:
SquareChannel(uint8_t owner, WaveDuty wd, ADSR env, Note note, uint8_t vol, int8_t pan, int16_t pitch);
SquareChannel(uint8_t owner, WaveDuty wd, ADSR env, Note note, uint8_t vol, int8_t pan, int8_t instPan, int16_t pitch);

void SetPitch(int16_t pitch) override;
void Process(sample *buffer, size_t numSamples, MixingArgs& args) override;
Expand All @@ -67,7 +68,7 @@ class SquareChannel : public CGBChannel
class WaveChannel : public CGBChannel
{
public:
WaveChannel(uint8_t owner, const uint8_t *wavePtr, ADSR env, Note note, uint8_t vol, int8_t pan, int16_t pitch);
WaveChannel(uint8_t owner, const uint8_t *wavePtr, ADSR env, Note note, uint8_t vol, int8_t pan, int8_t instPan, int16_t pitch);

void SetPitch(int16_t pitch) override;
void Process(sample *buffer, size_t numSamples, MixingArgs& args) override;
Expand All @@ -80,7 +81,7 @@ class WaveChannel : public CGBChannel
class NoiseChannel : public CGBChannel
{
public:
NoiseChannel(uint8_t owner, NoisePatt np, ADSR env, Note note, uint8_t vol, int8_t pan, int16_t pitch);
NoiseChannel(uint8_t owner, NoisePatt np, ADSR env, Note note, uint8_t vol, int8_t pan, int8_t instPan, int16_t pitch);

void SetPitch(int16_t pitch) override;
void Process(sample *buffer, size_t numSamples, MixingArgs& args) override;
Expand Down
51 changes: 26 additions & 25 deletions src/SequenceReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -442,37 +442,34 @@ void SequenceReader::playNote(Track& trk, Note note, uint8_t owner)

uint8_t oldKey = note.midiKey;
note.midiKey = ctx.bnk.GetMidiKey(trk.prog, oldKey);
uint8_t pan = ctx.bnk.GetPan(trk.prog, oldKey);

switch (ctx.bnk.GetInstrType(trk.prog, oldKey)) {
case InstrType::PCM:
{
uint8_t pan = ctx.bnk.GetPan(trk.prog, oldKey);
ctx.sndChannels.emplace_back(
owner,
ctx.bnk.GetSampInfo(trk.prog, oldKey),
ctx.bnk.GetADSR(trk.prog, oldKey),
note,
trk.GetVol(),
(pan & 0x80) ? int8_t(int(pan) - 0xC0) : trk.GetPan(),
trk.GetPitch(),
false);
}
ctx.sndChannels.emplace_back(
owner,
ctx.bnk.GetSampInfo(trk.prog, oldKey),
ctx.bnk.GetADSR(trk.prog, oldKey),
note,
trk.GetVol(),
trk.GetPan(),
(pan & 0x80) ? int8_t(int(pan) - 0xC0) : 0,
trk.GetPitch(),
false);
break;
case InstrType::PCM_FIXED:
{
uint8_t pan = ctx.bnk.GetPan(trk.prog, oldKey);
ctx.sndChannels.emplace_back(
owner,
ctx.bnk.GetSampInfo(trk.prog, oldKey),
ctx.bnk.GetADSR(trk.prog, oldKey),
note,
trk.GetVol(),
(pan & 0x80) ? int8_t(int(pan) - 0xC0) : trk.GetPan(),
trk.GetPitch(),
true);
}
ctx.sndChannels.emplace_back(
owner,
ctx.bnk.GetSampInfo(trk.prog, oldKey),
ctx.bnk.GetADSR(trk.prog, oldKey),
note,
trk.GetVol(),
trk.GetPan(),
(pan & 0x80) ? int8_t(int(pan) - 0xC0) : 0,
trk.GetPitch(),
true);
break;
case InstrType::SQ1:
// TODO Does pan of drum tables really only affect PCM channels?
cgbPolyphonySuppressFunc(ctx.sq1Channels);
ctx.sq1Channels.emplace_back(
owner,
Expand All @@ -481,6 +478,7 @@ void SequenceReader::playNote(Track& trk, Note note, uint8_t owner)
note,
trk.GetVol(),
trk.GetPan(),
(pan & 0x80) ? int8_t(int(pan) - 0xC0) : 0,
trk.GetPitch());
break;
case InstrType::SQ2:
Expand All @@ -492,6 +490,7 @@ void SequenceReader::playNote(Track& trk, Note note, uint8_t owner)
note,
trk.GetVol(),
trk.GetPan(),
(pan & 0x80) ? int8_t(int(pan) - 0xC0) : 0,
trk.GetPitch());
break;
case InstrType::WAVE:
Expand All @@ -503,6 +502,7 @@ void SequenceReader::playNote(Track& trk, Note note, uint8_t owner)
note,
trk.GetVol(),
trk.GetPan(),
(pan & 0x80) ? int8_t(int(pan) - 0xC0) : 0,
trk.GetPitch());
break;
case InstrType::NOISE:
Expand All @@ -514,6 +514,7 @@ void SequenceReader::playNote(Track& trk, Note note, uint8_t owner)
note,
trk.GetVol(),
trk.GetPan(),
(pan & 0x80) ? int8_t(int(pan) - 0xC0) : 0,
trk.GetPitch());
break;
case InstrType::INVALID:
Expand Down
9 changes: 5 additions & 4 deletions src/SoundChannel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
* public SoundChannel
*/

SoundChannel::SoundChannel(uint8_t owner, SampleInfo sInfo, ADSR env, Note note, uint8_t vol, int8_t pan, int16_t pitch, bool fixed)
: env(env), note(note), sInfo(sInfo), fixed(fixed), owner(owner)
SoundChannel::SoundChannel(uint8_t owner, SampleInfo sInfo, ADSR env, Note note, uint8_t vol, int8_t pan, int8_t instPan, int16_t pitch, bool fixed)
: env(env), note(note), sInfo(sInfo), fixed(fixed), owner(owner), instPan(instPan)
{
SetVol(vol, pan);

Expand Down Expand Up @@ -109,8 +109,9 @@ uint8_t SoundChannel::GetOwner() const
void SoundChannel::SetVol(uint8_t vol, int8_t pan)
{
if (eState < EnvState::REL) {
this->leftVol = uint8_t(note.velocity * vol * (-pan + 64) / 8192);
this->rightVol = uint8_t(note.velocity * vol * (pan + 64) / 8192);
int combinedPan = std::clamp(pan + instPan, -64, +63);
this->leftVol = uint8_t(note.velocity * vol * (-combinedPan + 64) / 8192);
this->rightVol = uint8_t(note.velocity * vol * (combinedPan + 64) / 8192);
}
}

Expand Down
3 changes: 2 additions & 1 deletion src/SoundChannel.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class SoundChannel
float interStep;
};
public:
SoundChannel(uint8_t owner, SampleInfo sInfo, ADSR env, Note note, uint8_t vol, int8_t pan, int16_t pitch, bool fixed);
SoundChannel(uint8_t owner, SampleInfo sInfo, ADSR env, Note note, uint8_t vol, int8_t pan, int8_t instPan, int16_t pitch, bool fixed);
SoundChannel(const SoundChannel&) = delete;
SoundChannel& operator=(const SoundChannel&) = delete;

Expand Down Expand Up @@ -58,6 +58,7 @@ class SoundChannel
int16_t levelMPTcompressed;
uint8_t shiftMPTcompressed;
uint8_t owner;
const int8_t instPan;
uint8_t envInterStep = 0;
uint8_t leftVol;
uint8_t rightVol;
Expand Down

0 comments on commit 1788727

Please sign in to comment.