Skip to content

Commit

Permalink
[MP2K] Combine pan properly
Browse files Browse the repository at this point in the history
  • Loading branch information
Kermalis committed Jun 13, 2021
1 parent ac31d62 commit 3a628c5
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 24 deletions.
43 changes: 32 additions & 11 deletions VG Music Studio/Core/GBA/MP2K/Channel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ internal abstract class Channel

public Note Note; // Must be a struct & field
protected ADSR _adsr;
protected int _instPan;

protected byte _velocity;
protected int _pos;
Expand Down Expand Up @@ -83,7 +84,7 @@ internal class PCM8Channel : Channel
private sbyte[] _decompressedSample;

public PCM8Channel(Mixer mixer) : base(mixer) { }
public void Init(Track owner, Note note, ADSR adsr, int sampleOffset, byte vol, sbyte pan, int pitch, bool bFixed, bool bCompressed)
public void Init(Track owner, Note note, ADSR adsr, int sampleOffset, byte vol, sbyte pan, int instPan, int pitch, bool bFixed, bool bCompressed)
{
State = EnvelopeState.Initializing;
_pos = 0; _interPos = 0;
Expand All @@ -95,6 +96,7 @@ public void Init(Track owner, Note note, ADSR adsr, int sampleOffset, byte vol,
Owner.Channels.Add(this);
Note = note;
_adsr = adsr;
_instPan = instPan;
_sampleHeader = _mixer.Config.Reader.ReadObject<SampleHeader>(sampleOffset);
_sampleOffset = sampleOffset + 0x10;
_bFixed = bFixed;
Expand All @@ -120,12 +122,21 @@ public override ChannelVolume GetVolume()
}
public override void SetVolume(byte vol, sbyte pan)
{
int combinedPan = pan + _instPan;
if (combinedPan > 63)
{
combinedPan = 63;
}
else if (combinedPan < -64)
{
combinedPan = -64;
}
const int fix = 0x2000;
if (State < EnvelopeState.Releasing)
{
int a = Note.Velocity * vol;
_leftVol = (byte)(a * (-pan + 0x40) / fix);
_rightVol = (byte)(a * (pan + 0x40) / fix);
_leftVol = (byte)(a * (-combinedPan + 0x40) / fix);
_rightVol = (byte)(a * (combinedPan + 0x40) / fix);
}
}
public override void SetPitch(int pitch)
Expand Down Expand Up @@ -346,7 +357,7 @@ protected enum GBPan : byte
protected GBPan _panpot = GBPan.Center;

public PSGChannel(Mixer mixer) : base(mixer) { }
protected void Init(Track owner, Note note, ADSR env)
protected void Init(Track owner, Note note, ADSR env, int instPan)
{
State = EnvelopeState.Initializing;
if (Owner != null)
Expand All @@ -360,6 +371,7 @@ protected void Init(Track owner, Note note, ADSR env)
_adsr.D = (byte)(env.D & 0x7);
_adsr.S = (byte)(env.S & 0xF);
_adsr.R = (byte)(env.R & 0x7);
_instPan = instPan;
}

public override void Release()
Expand Down Expand Up @@ -424,9 +436,18 @@ public override ChannelVolume GetVolume()
}
public override void SetVolume(byte vol, sbyte pan)
{
int combinedPan = pan + _instPan;
if (combinedPan > 63)
{
combinedPan = 63;
}
else if (combinedPan < -64)
{
combinedPan = -64;
}
if (State < EnvelopeState.Releasing)
{
_panpot = pan < -21 ? GBPan.Left : pan > 20 ? GBPan.Right : GBPan.Center;
_panpot = combinedPan < -21 ? GBPan.Left : combinedPan > 20 ? GBPan.Right : GBPan.Center;
_peakVelocity = (byte)((Note.Velocity * vol) >> 10);
_sustainVelocity = (byte)(((_peakVelocity * _adsr.S) + 0xF) >> 4); // TODO
if (State == EnvelopeState.Playing)
Expand Down Expand Up @@ -609,9 +630,9 @@ internal class SquareChannel : PSGChannel
private float[] _pat;

public SquareChannel(Mixer mixer) : base(mixer) { }
public void Init(Track owner, Note note, ADSR env, SquarePattern pattern)
public void Init(Track owner, Note note, ADSR env, int instPan, SquarePattern pattern)
{
Init(owner, note, env);
Init(owner, note, env, instPan);
switch (pattern)
{
default: _pat = Utils.SquareD12; break;
Expand Down Expand Up @@ -657,9 +678,9 @@ internal class PCM4Channel : PSGChannel
private float[] _sample;

public PCM4Channel(Mixer mixer) : base(mixer) { }
public void Init(Track owner, Note note, ADSR env, int sampleOffset)
public void Init(Track owner, Note note, ADSR env, int instPan, int sampleOffset)
{
Init(owner, note, env);
Init(owner, note, env, instPan);
_sample = Utils.PCM4ToFloat(sampleOffset);
}

Expand Down Expand Up @@ -699,9 +720,9 @@ internal class NoiseChannel : PSGChannel
private BitArray _pat;

public NoiseChannel(Mixer mixer) : base(mixer) { }
public void Init(Track owner, Note note, ADSR env, NoisePattern pattern)
public void Init(Track owner, Note note, ADSR env, int instPan, NoisePattern pattern)
{
Init(owner, note, env);
Init(owner, note, env, instPan);
_pat = pattern == NoisePattern.Fine ? Utils.NoiseFine : Utils.NoiseRough;
}

Expand Down
14 changes: 7 additions & 7 deletions VG Music Studio/Core/GBA/MP2K/Mixer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public override void Dispose()
CloseWaveWriter();
}

public PCM8Channel AllocPCM8Channel(Track owner, ADSR env, Note note, byte vol, sbyte pan, int pitch, bool bFixed, bool bCompressed, int sampleOffset)
public PCM8Channel AllocPCM8Channel(Track owner, ADSR env, Note note, byte vol, sbyte pan, int instPan, int pitch, bool bFixed, bool bCompressed, int sampleOffset)
{
PCM8Channel nChn = null;
IOrderedEnumerable<PCM8Channel> byOwner = _pcm8Channels.OrderByDescending(c => c.Owner == null ? 0xFF : c.Owner.Index);
Expand Down Expand Up @@ -106,11 +106,11 @@ public PCM8Channel AllocPCM8Channel(Track owner, ADSR env, Note note, byte vol,
}
if (nChn != null) // Could still be null from the above if
{
nChn.Init(owner, note, env, sampleOffset, vol, pan, pitch, bFixed, bCompressed);
nChn.Init(owner, note, env, sampleOffset, vol, pan, instPan, pitch, bFixed, bCompressed);
}
return nChn;
}
public PSGChannel AllocPSGChannel(Track owner, ADSR env, Note note, byte vol, sbyte pan, int pitch, VoiceType type, object arg)
public PSGChannel AllocPSGChannel(Track owner, ADSR env, Note note, byte vol, sbyte pan, int instPan, int pitch, VoiceType type, object arg)
{
PSGChannel nChn;
switch (type)
Expand All @@ -122,7 +122,7 @@ public PSGChannel AllocPSGChannel(Track owner, ADSR env, Note note, byte vol, sb
{
return null;
}
_sq1.Init(owner, note, env, (SquarePattern)arg);
_sq1.Init(owner, note, env, instPan, (SquarePattern)arg);
break;
}
case VoiceType.Square2:
Expand All @@ -132,7 +132,7 @@ public PSGChannel AllocPSGChannel(Track owner, ADSR env, Note note, byte vol, sb
{
return null;
}
_sq2.Init(owner, note, env, (SquarePattern)arg);
_sq2.Init(owner, note, env, instPan, (SquarePattern)arg);
break;
}
case VoiceType.PCM4:
Expand All @@ -142,7 +142,7 @@ public PSGChannel AllocPSGChannel(Track owner, ADSR env, Note note, byte vol, sb
{
return null;
}
_pcm4.Init(owner, note, env, (int)arg);
_pcm4.Init(owner, note, env, instPan, (int)arg);
break;
}
case VoiceType.Noise:
Expand All @@ -152,7 +152,7 @@ public PSGChannel AllocPSGChannel(Track owner, ADSR env, Note note, byte vol, sb
{
return null;
}
_noise.Init(owner, note, env, (NoisePattern)arg);
_noise.Init(owner, note, env, instPan, (NoisePattern)arg);
break;
}
default: return null;
Expand Down
10 changes: 6 additions & 4 deletions VG Music Studio/Core/GBA/MP2K/Player.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1043,36 +1043,38 @@ private void PlayNote(Track track, byte key, byte velocity, byte addedDuration)
Key = fromDrum ? v.RootKey : key
};
var type = (VoiceType)(v.Type & 0x7);
int instPan = v.Pan;
instPan = (instPan & 0x80) != 0 ? instPan - 0xC0 : 0;
switch (type)
{
case VoiceType.PCM8:
{
bool bFixed = (v.Type & (int)VoiceFlags.Fixed) != 0;
bool bCompressed = _config.HasPokemonCompression && ((v.Type & (int)VoiceFlags.Compressed) != 0);
_mixer.AllocPCM8Channel(track, v.ADSR, note,
track.GetVolume(), track.GetPanpot(), track.GetPitch(),
track.GetVolume(), track.GetPanpot(), instPan, track.GetPitch(),
bFixed, bCompressed, v.Int4 - GBA.Utils.CartridgeOffset);
return;
}
case VoiceType.Square1:
case VoiceType.Square2:
{
_mixer.AllocPSGChannel(track, v.ADSR, note,
track.GetVolume(), track.GetPanpot(), track.GetPitch(),
track.GetVolume(), track.GetPanpot(), instPan, track.GetPitch(),
type, (SquarePattern)v.Int4);
return;
}
case VoiceType.PCM4:
{
_mixer.AllocPSGChannel(track, v.ADSR, note,
track.GetVolume(), track.GetPanpot(), track.GetPitch(),
track.GetVolume(), track.GetPanpot(), instPan, track.GetPitch(),
type, v.Int4 - GBA.Utils.CartridgeOffset);
return;
}
case VoiceType.Noise:
{
_mixer.AllocPSGChannel(track, v.ADSR, note,
track.GetVolume(), track.GetPanpot(), track.GetPitch(),
track.GetVolume(), track.GetPanpot(), instPan, track.GetPitch(),
type, (NoisePattern)v.Int4);
return;
}
Expand Down
3 changes: 1 addition & 2 deletions VG Music Studio/Core/GBA/MP2K/Structs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,7 @@ internal class VoiceEntry
public byte Type { get; set; } // 0
public byte RootKey { get; set; } // 1
public byte Unknown { get; set; } // 2
/// <summary>Panpot for PCM8/Noise, Sweep for Square1</summary>
public byte Byte3 { get; set; } // 3
public byte Pan { get; set; } // 3
/// <summary>SquarePattern for Square1/Square2, NoisePattern for Noise, Address for PCM8/PCM4/KeySplit/Drum</summary>
public int Int4 { get; set; } // 4
/// <summary>ADSR for PCM8/Square1/Square2/PCM4/Noise, KeysAddress for KeySplit</summary>
Expand Down

0 comments on commit 3a628c5

Please sign in to comment.