mirror of
https://mirror.ghproxy.com/https://github.com/dexyfex/CodeWalker
synced 2025-01-10 07:42:56 +08:00
Synthesizer progress
This commit is contained in:
parent
1371c0390e
commit
4a00d67658
@ -748,13 +748,17 @@ namespace CodeWalker.Forms
|
|||||||
{
|
{
|
||||||
//for (int i = 0; i < buffersCopy.Length; i++)
|
//for (int i = 0; i < buffersCopy.Length; i++)
|
||||||
int i = synthesizer.Synth.OutputsIndices[0];
|
int i = synthesizer.Synth.OutputsIndices[0];
|
||||||
if (i < SynthBufferChart.Series.Count)
|
try
|
||||||
{
|
{
|
||||||
var series = SynthBufferChart.Series[$"B{i}"];
|
var series = SynthBufferChart.Series.FindByName($"B{i}");
|
||||||
series.Points.Clear();
|
if (series != null)
|
||||||
foreach (var v in buffersCopy[i])
|
{
|
||||||
series.Points.AddY(v);
|
series.Points.Clear();
|
||||||
|
foreach (var v in buffersCopy[i])
|
||||||
|
series.Points.AddY(Math.Max(Math.Min(v, 2.0f), -2.0f));//make sure crazy accidental values don't crash it later
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
catch { }
|
||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,7 @@ namespace CodeWalker.Utils
|
|||||||
public Dat10Synth Synth { get; private set; }
|
public Dat10Synth Synth { get; private set; }
|
||||||
public float[] Registers { get; private set; }
|
public float[] Registers { get; private set; }
|
||||||
public float[][] Buffers { get; private set; }
|
public float[][] Buffers { get; private set; }
|
||||||
public Vector4[] StateBlocks { get; private set; }
|
public StateBlock[] StateBlocks { get; private set; }
|
||||||
|
|
||||||
private Dat10Synth.Instruction[] instructions;
|
private Dat10Synth.Instruction[] instructions;
|
||||||
private bool stop;
|
private bool stop;
|
||||||
@ -63,7 +63,7 @@ namespace CodeWalker.Utils
|
|||||||
instructions = Dat10Synth.DisassembleGetInstructions(synth.Bytecode, synth.Constants, synth.Variables);
|
instructions = Dat10Synth.DisassembleGetInstructions(synth.Bytecode, synth.Constants, synth.Variables);
|
||||||
Registers = new float[synth.RegistersCount];
|
Registers = new float[synth.RegistersCount];
|
||||||
Buffers = new float[synth.BuffersCount][];
|
Buffers = new float[synth.BuffersCount][];
|
||||||
StateBlocks = new Vector4[synth.StateBlocksCount];
|
StateBlocks = new StateBlock[synth.StateBlocksCount];
|
||||||
stop = false;
|
stop = false;
|
||||||
|
|
||||||
for (int i = 0; i < synth.BuffersCount; i++)
|
for (int i = 0; i < synth.BuffersCount; i++)
|
||||||
@ -115,8 +115,9 @@ namespace CodeWalker.Utils
|
|||||||
Buffers[i][k] = 0.0f;
|
Buffers[i][k] = 0.0f;
|
||||||
|
|
||||||
bool frameFinished = false;
|
bool frameFinished = false;
|
||||||
foreach (var inst in instructions)
|
for (int insti = 0; insti < instructions.Length; insti++)
|
||||||
{
|
{
|
||||||
|
var inst = instructions[insti];
|
||||||
if (frameFinished)
|
if (frameFinished)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -772,14 +773,18 @@ namespace CodeWalker.Utils
|
|||||||
case Dat10Synth.Opcode.GATE_SCALAR_SCALAR:
|
case Dat10Synth.Opcode.GATE_SCALAR_SCALAR:
|
||||||
SetRegister(param[0], Gate(GetScalar(param[1]), GetScalar(param[2])));
|
SetRegister(param[0], Gate(GetScalar(param[1]), GetScalar(param[2])));
|
||||||
break;
|
break;
|
||||||
//case Dat10Synth.Opcode.SMALL_DELAY_FRAC:
|
case Dat10Synth.Opcode.SMALL_DELAY_FRAC:
|
||||||
// break;
|
SmallDelay(GetBuffer(param[0]), GetScalar(param[1]), 0.0f, ref StateBlocks[param[inst.NumberOfInputs].Value], true);
|
||||||
//case Dat10Synth.Opcode.SMALL_DELAY_NON_INTERP:
|
break;
|
||||||
// break;
|
case Dat10Synth.Opcode.SMALL_DELAY_NON_INTERP:
|
||||||
//case Dat10Synth.Opcode.SMALL_DELAY_FRAC_FEEDBACK:
|
SmallDelay(GetBuffer(param[0]), GetScalar(param[1]), 0.0f, ref StateBlocks[param[inst.NumberOfInputs].Value], false);
|
||||||
// break;
|
break;
|
||||||
//case Dat10Synth.Opcode.SMALL_DELAY_NON_INTERP_FEEDBACK:
|
case Dat10Synth.Opcode.SMALL_DELAY_FRAC_FEEDBACK:
|
||||||
// break;
|
SmallDelay(GetBuffer(param[0]), GetScalar(param[1]), GetScalar(param[2]), ref StateBlocks[param[3].Value], true);
|
||||||
|
break;
|
||||||
|
case Dat10Synth.Opcode.SMALL_DELAY_NON_INTERP_FEEDBACK:
|
||||||
|
SmallDelay(GetBuffer(param[0]), GetScalar(param[1]), GetScalar(param[2]), ref StateBlocks[param[3].Value], false);
|
||||||
|
break;
|
||||||
case Dat10Synth.Opcode.TRIGGER_DIFF:
|
case Dat10Synth.Opcode.TRIGGER_DIFF:
|
||||||
SetRegister(param[0], TriggerDiff(GetScalar(param[1]), GetScalar(param[2]), ref StateBlocks[param[3].Value]));
|
SetRegister(param[0], TriggerDiff(GetScalar(param[1]), GetScalar(param[2]), ref StateBlocks[param[3].Value]));
|
||||||
break;
|
break;
|
||||||
@ -913,7 +918,7 @@ namespace CodeWalker.Utils
|
|||||||
frameFinished = true;
|
frameFinished = true;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new NotImplementedException(inst.Opcode.ToString());
|
throw new NotImplementedException(inst.Opcode.ToString() + " (line " + (insti + 1).ToString() + ")");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1049,7 +1054,7 @@ FINISH =>
|
|||||||
return (float)Math.Pow(2.0f, (note + 36.376301f) / 12.0f);
|
return (float)Math.Pow(2.0f, (note + 36.376301f) / 12.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Decimate(float[] buffer, float scalar1, float deltaPerSample, ref Vector4 stateBlock)
|
private void Decimate(float[] buffer, float scalar1, float deltaPerSample, ref StateBlock stateBlock)
|
||||||
{
|
{
|
||||||
// State block:
|
// State block:
|
||||||
// X -> t: samples counter, each sample adds deltaPerSample, once it reaches 1.0 the lastSample value is updated
|
// X -> t: samples counter, each sample adds deltaPerSample, once it reaches 1.0 the lastSample value is updated
|
||||||
@ -1082,7 +1087,7 @@ FINISH =>
|
|||||||
stateBlock.Y = lastSample;
|
stateBlock.Y = lastSample;
|
||||||
}
|
}
|
||||||
|
|
||||||
private float Counter(bool returnCounter, float setToZeroTrigger, float incrementTrigger, float decrementTrigger, float maxCounter, ref Vector4 stateBlock)
|
private float Counter(bool returnCounter, float setToZeroTrigger, float incrementTrigger, float decrementTrigger, float maxCounter, ref StateBlock stateBlock)
|
||||||
{
|
{
|
||||||
// State block:
|
// State block:
|
||||||
// X -> counter value
|
// X -> counter value
|
||||||
@ -1128,7 +1133,7 @@ FINISH =>
|
|||||||
return valuePercent * threshold * Math.Sign(value);
|
return valuePercent * threshold * Math.Sign(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Compress(float[] buffer, float scalar1_threshold, float scalar2_ratio, float scalar3_time1, float scalar4_time2, ref Vector4 stateBlock)
|
private void Compress(float[] buffer, float scalar1_threshold, float scalar2_ratio, float scalar3_time1, float scalar4_time2, ref StateBlock stateBlock)
|
||||||
{
|
{
|
||||||
// State block:
|
// State block:
|
||||||
// X -> ...
|
// X -> ...
|
||||||
@ -1331,7 +1336,7 @@ FINISH =>
|
|||||||
a1 /= a0; a2 /= a0;
|
a1 /= a0; a2 /= a0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void BiquadFilter2Pole(float[] buffer, float b0, float b1, float b2, float a1, float a2, ref Vector4 stateBlock)
|
private void BiquadFilter2Pole(float[] buffer, float b0, float b1, float b2, float a1, float a2, ref StateBlock stateBlock)
|
||||||
{
|
{
|
||||||
// State block:
|
// State block:
|
||||||
// X -> ...
|
// X -> ...
|
||||||
@ -1352,7 +1357,7 @@ FINISH =>
|
|||||||
stateBlock.Y = stateY;
|
stateBlock.Y = stateY;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void BiquadFilter4Pole(float[] buffer, float b0, float b1, float b2, float a1, float a2, ref Vector4 stateBlock)
|
private void BiquadFilter4Pole(float[] buffer, float b0, float b1, float b2, float a1, float a2, ref StateBlock stateBlock)
|
||||||
{
|
{
|
||||||
// State block:
|
// State block:
|
||||||
// X -> ...
|
// X -> ...
|
||||||
@ -1382,7 +1387,7 @@ FINISH =>
|
|||||||
stateBlock.W = stateW;
|
stateBlock.W = stateW;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void EnvelopeFollower(float[] buffer, float a2, float a3, ref Vector4 stateBlock)
|
private void EnvelopeFollower(float[] buffer, float a2, float a3, ref StateBlock stateBlock)
|
||||||
{
|
{
|
||||||
// State block:
|
// State block:
|
||||||
// X -> previous follower value
|
// X -> previous follower value
|
||||||
@ -1411,7 +1416,7 @@ FINISH =>
|
|||||||
stateBlock.X = prevFollower;
|
stateBlock.X = prevFollower;
|
||||||
}
|
}
|
||||||
|
|
||||||
private float EnvelopeFollower(float scalar, float a2, float a3, ref Vector4 stateBlock)
|
private float EnvelopeFollower(float scalar, float a2, float a3, ref StateBlock stateBlock)
|
||||||
{
|
{
|
||||||
// State block:
|
// State block:
|
||||||
// X -> previous follower value
|
// X -> previous follower value
|
||||||
@ -1434,12 +1439,12 @@ FINISH =>
|
|||||||
return follower;
|
return follower;
|
||||||
}
|
}
|
||||||
|
|
||||||
private float TriggerLatch(float value, float triggerLimit, ref Vector4 stateBlock)
|
private float TriggerLatch(float value, float triggerLimit, ref StateBlock stateBlock)
|
||||||
{
|
{
|
||||||
return TriggerLatch(value >= (triggerLimit - 0.000001f), ref stateBlock);
|
return TriggerLatch(value >= (triggerLimit - 0.000001f), ref stateBlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
private float TriggerLatch(float[] buffer, float triggerLimit, ref Vector4 stateBlock)
|
private float TriggerLatch(float[] buffer, float triggerLimit, ref StateBlock stateBlock)
|
||||||
{
|
{
|
||||||
bool triggered = false;
|
bool triggered = false;
|
||||||
for (int i = 0; !triggered && i < BufferSize; i++)
|
for (int i = 0; !triggered && i < BufferSize; i++)
|
||||||
@ -1449,7 +1454,7 @@ FINISH =>
|
|||||||
return TriggerLatch(triggered, ref stateBlock);
|
return TriggerLatch(triggered, ref stateBlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
private float TriggerLatch(float[] buffer, float[] triggerLimitBuffer, ref Vector4 stateBlock)
|
private float TriggerLatch(float[] buffer, float[] triggerLimitBuffer, ref StateBlock stateBlock)
|
||||||
{
|
{
|
||||||
bool triggered = false;
|
bool triggered = false;
|
||||||
for (int i = 0; !triggered && i < BufferSize; i++)
|
for (int i = 0; !triggered && i < BufferSize; i++)
|
||||||
@ -1459,7 +1464,7 @@ FINISH =>
|
|||||||
return TriggerLatch(triggered, ref stateBlock);
|
return TriggerLatch(triggered, ref stateBlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
private float TriggerLatch(bool triggered, ref Vector4 stateBlock)
|
private float TriggerLatch(bool triggered, ref StateBlock stateBlock)
|
||||||
{
|
{
|
||||||
// State block:
|
// State block:
|
||||||
// X -> latch SET
|
// X -> latch SET
|
||||||
@ -1477,7 +1482,7 @@ FINISH =>
|
|||||||
return latch;
|
return latch;
|
||||||
}
|
}
|
||||||
|
|
||||||
private float TriggerDiff(float value, float triggerLimit, ref Vector4 stateBlock)
|
private float TriggerDiff(float value, float triggerLimit, ref StateBlock stateBlock)
|
||||||
{
|
{
|
||||||
// State block:
|
// State block:
|
||||||
// X -> previous value
|
// X -> previous value
|
||||||
@ -1488,7 +1493,7 @@ FINISH =>
|
|||||||
return triggered ? 1.0f : 0.0f;
|
return triggered ? 1.0f : 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OscillatorRamp(float[] buffer, ref Vector4 stateBlock)
|
private void OscillatorRamp(float[] buffer, ref StateBlock stateBlock)
|
||||||
{
|
{
|
||||||
// TODO(alexguirre): better names in OSC_RAMP_BUFFER_BUFFER
|
// TODO(alexguirre): better names in OSC_RAMP_BUFFER_BUFFER
|
||||||
var stateX = stateBlock.X;
|
var stateX = stateBlock.X;
|
||||||
@ -1503,7 +1508,7 @@ FINISH =>
|
|||||||
stateBlock.X = stateX;
|
stateBlock.X = stateX;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OscillatorRamp(float[] buffer, float frequency, ref Vector4 stateBlock)
|
private void OscillatorRamp(float[] buffer, float frequency, ref StateBlock stateBlock)
|
||||||
{
|
{
|
||||||
// TODO(alexguirre): better names in OSC_RAMP_BUFFER_SCALAR
|
// TODO(alexguirre): better names in OSC_RAMP_BUFFER_SCALAR
|
||||||
var v1 = frequency / SampleRate;
|
var v1 = frequency / SampleRate;
|
||||||
@ -1518,7 +1523,7 @@ FINISH =>
|
|||||||
stateBlock.X = v3;
|
stateBlock.X = v3;
|
||||||
}
|
}
|
||||||
|
|
||||||
private float OscillatorRamp(float frequency, ref Vector4 stateBlock)
|
private float OscillatorRamp(float frequency, ref StateBlock stateBlock)
|
||||||
{
|
{
|
||||||
// TODO(alexguirre): better names in OSC_RAMP_SCALAR
|
// TODO(alexguirre): better names in OSC_RAMP_SCALAR
|
||||||
var v2 = Math.Max(1.0f, frequency / 187.5f);
|
var v2 = Math.Max(1.0f, frequency / 187.5f);
|
||||||
@ -1535,7 +1540,7 @@ FINISH =>
|
|||||||
private enum EnvelopeReleaseType { Linear, Exponential }
|
private enum EnvelopeReleaseType { Linear, Exponential }
|
||||||
private enum EnvelopeTriggerMode { OneShot, Retrigger, Interruptible }
|
private enum EnvelopeTriggerMode { OneShot, Retrigger, Interruptible }
|
||||||
|
|
||||||
private float EnvelopeGen(Dat10Synth.Opcode envelopeGenOpcode, float[] buffer, ref Vector4 stateBlock, float predelay, float attack, float decay, float sustain, float hold, float release, float trigger)
|
private float EnvelopeGen(Dat10Synth.Opcode envelopeGenOpcode, float[] buffer, ref StateBlock stateBlock, float predelay, float attack, float decay, float sustain, float hold, float release, float trigger)
|
||||||
{
|
{
|
||||||
EnvelopeReleaseType releaseType;
|
EnvelopeReleaseType releaseType;
|
||||||
switch (envelopeGenOpcode)
|
switch (envelopeGenOpcode)
|
||||||
@ -1576,7 +1581,7 @@ FINISH =>
|
|||||||
return EnvelopeGen(releaseType, triggerMode, buffer, ref stateBlock, predelay, attack, decay, sustain, hold, release, trigger);
|
return EnvelopeGen(releaseType, triggerMode, buffer, ref stateBlock, predelay, attack, decay, sustain, hold, release, trigger);
|
||||||
}
|
}
|
||||||
|
|
||||||
private float EnvelopeGen(EnvelopeReleaseType releaseType, EnvelopeTriggerMode triggerMode, float[] buffer, ref Vector4 stateBlock, float predelay, float attack, float decay, float sustain, float hold, float release, float trigger)
|
private float EnvelopeGen(EnvelopeReleaseType releaseType, EnvelopeTriggerMode triggerMode, float[] buffer, ref StateBlock stateBlock, float predelay, float attack, float decay, float sustain, float hold, float release, float trigger)
|
||||||
{
|
{
|
||||||
// State block:
|
// State block:
|
||||||
// X -> envelope state : 8 bits | envelope state remaining samples : 24 bits
|
// X -> envelope state : 8 bits | envelope state remaining samples : 24 bits
|
||||||
@ -1783,7 +1788,7 @@ FINISH =>
|
|||||||
public float ReleaseActive;
|
public float ReleaseActive;
|
||||||
}
|
}
|
||||||
|
|
||||||
private TimedTriggerResult TimedTrigger(Dat10Synth.Opcode envelopeGenOpcode, ref Vector4 stateBlock, float trigger, float predelay, float attack, float decay, float hold, float release)
|
private TimedTriggerResult TimedTrigger(Dat10Synth.Opcode envelopeGenOpcode, ref StateBlock stateBlock, float trigger, float predelay, float attack, float decay, float hold, float release)
|
||||||
{
|
{
|
||||||
EnvelopeTriggerMode triggerMode;
|
EnvelopeTriggerMode triggerMode;
|
||||||
switch (envelopeGenOpcode)
|
switch (envelopeGenOpcode)
|
||||||
@ -1821,7 +1826,7 @@ FILL_BUFFER R1 => B1 ; timed trigger finished
|
|||||||
FILL_BUFFER 0 => B7
|
FILL_BUFFER 0 => B7
|
||||||
FINISH =>
|
FINISH =>
|
||||||
*/
|
*/
|
||||||
private TimedTriggerResult TimedTrigger(EnvelopeTriggerMode triggerMode, ref Vector4 stateBlock, float trigger, float predelay, float attack, float decay, float hold, float release)
|
private TimedTriggerResult TimedTrigger(EnvelopeTriggerMode triggerMode, ref StateBlock stateBlock, float trigger, float predelay, float attack, float decay, float hold, float release)
|
||||||
{
|
{
|
||||||
// State block:
|
// State block:
|
||||||
// X -> envelope state : 8 bits | envelope state remaining samples : 24 bits
|
// X -> envelope state : 8 bits | envelope state remaining samples : 24 bits
|
||||||
@ -2038,6 +2043,89 @@ FINISH =>
|
|||||||
outputBuffer[i] = cos * a[i] + sin * b[i];
|
outputBuffer[i] = cos * a[i] + sin * b[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void SmallDelay(float[] buffer, float delaySamples, float feedback, ref StateBlock stateBlock, bool interpolate)
|
||||||
|
{
|
||||||
|
feedback = Math.Max(Math.Min(feedback, 1.0f), -1.0f);//just to stop things getting accidentally out of control...
|
||||||
|
delaySamples = Math.Abs(delaySamples);//should this be clamped to max 8..?
|
||||||
|
int delaySamplesInt = (int)delaySamples;
|
||||||
|
float frac = delaySamples - (float)Math.Floor(delaySamples);
|
||||||
|
for (int i = 0; i < BufferSize; i++)
|
||||||
|
{
|
||||||
|
float currSample = buffer[i];
|
||||||
|
float delayedSample;
|
||||||
|
int delayed = i + delaySamplesInt;
|
||||||
|
float s0 = stateBlock[delayed & 7];
|
||||||
|
if (interpolate)
|
||||||
|
{
|
||||||
|
float s1 = stateBlock[(delayed + 1) & 7];
|
||||||
|
delayedSample = (s1 - s0) * frac + s0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
delayedSample = s0;
|
||||||
|
}
|
||||||
|
buffer[i] = delayedSample;
|
||||||
|
stateBlock[i & 7] = delayedSample * feedback + currSample;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public struct StateBlock
|
||||||
|
{
|
||||||
|
public float X { get; set; }
|
||||||
|
public float Y { get; set; }
|
||||||
|
public float Z { get; set; }
|
||||||
|
public float W { get; set; }
|
||||||
|
public float A { get; set; }
|
||||||
|
public float B { get; set; }
|
||||||
|
public float C { get; set; }
|
||||||
|
public float D { get; set; }
|
||||||
|
|
||||||
|
public float this[int index]
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
switch (index)
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
case 0: return X;
|
||||||
|
case 1: return Y;
|
||||||
|
case 2: return Z;
|
||||||
|
case 3: return W;
|
||||||
|
case 4: return A;
|
||||||
|
case 5: return B;
|
||||||
|
case 6: return C;
|
||||||
|
case 7: return D;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
switch (index)
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
case 0: X = value; break;
|
||||||
|
case 1: Y = value; break;
|
||||||
|
case 2: Z = value; break;
|
||||||
|
case 3: W = value; break;
|
||||||
|
case 4: A = value; break;
|
||||||
|
case 5: B = value; break;
|
||||||
|
case 6: C = value; break;
|
||||||
|
case 7: D = value; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public float[] Values
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return new[] { X, Y, Z, W, A, B, C, D };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user