Skip to content

Commit

Permalink
Initialize.
Browse files Browse the repository at this point in the history
  • Loading branch information
rodgers-r committed Mar 15, 2019
0 parents commit 53ec877
Show file tree
Hide file tree
Showing 19 changed files with 1,095 additions and 0 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.vs
*.suo
bin/
obj/
91 changes: 91 additions & 0 deletions DssiDescriptor.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;

namespace LADSPA.NET
{
public class DssiDescriptor
{
public readonly LadspaLibraryContext Library;
public readonly LadspaDescriptor LadspaDescriptor;
public readonly bool IsSynth;

internal readonly IntPtr DataHandle;
internal readonly DssiDescriptorConfigureCallback Configure;
internal readonly DssiDescriptorGetProgramCallback GetProgram;
internal readonly DssiDescriptorSelectProgramCallback SelectProgram;
internal readonly DssiDescriptorGetMidiControllerForPortCallback GetMidiControllerForPort;
internal readonly DssiDescriptorRunSynthCallback RunSynth;
internal readonly DssiDescriptorRunSynthCallback RunSynthAdding;
internal readonly DssiDescriptorRunMultiSynthCallback RunMultiSynth;
internal readonly DssiDescriptorRunMultiSynthCallback RunMultiSynthAdding;

private DssiProgramDescriptor[] _programs;
public DssiProgramDescriptor[] Programs
{
get
{
lock (this)
{
if (_programs == null)
{
if (LadspaDescriptor.Instantiate != null && LadspaDescriptor.Cleanup != null)
{
IntPtr handle = LadspaDescriptor.Instantiate(LadspaDescriptor.DataHandle, 44100);
if (handle != IntPtr.Zero)
{
try { _programs = LoadProgramsFromHandle(handle); }
finally { LadspaDescriptor.Cleanup(handle); }
}
}
if (_programs == null) { _programs = new DssiProgramDescriptor[0]; }
}
return (_programs);
}
}
}

internal DssiDescriptor(LadspaLibraryContext library, uint index, IntPtr dataPtr)
{
DssiDescriptorStruct data = (DssiDescriptorStruct)Marshal.PtrToStructure(dataPtr, typeof(DssiDescriptorStruct));
Library = library;
DataHandle = dataPtr;
LadspaDescriptor = new LadspaDescriptor(library, index, data.LadspaDescriptor);
if (data.Configure != IntPtr.Zero) { Configure = (DssiDescriptorConfigureCallback)Marshal.GetDelegateForFunctionPointer(data.Configure, typeof(DssiDescriptorConfigureCallback)); }
if (data.GetProgram != IntPtr.Zero) { GetProgram = (DssiDescriptorGetProgramCallback)Marshal.GetDelegateForFunctionPointer(data.GetProgram, typeof(DssiDescriptorGetProgramCallback)); }
if (data.SelectProgram != IntPtr.Zero) { SelectProgram = (DssiDescriptorSelectProgramCallback)Marshal.GetDelegateForFunctionPointer(data.SelectProgram, typeof(DssiDescriptorSelectProgramCallback)); }
if (data.GetMidiControllerForPort != IntPtr.Zero) { GetMidiControllerForPort = (DssiDescriptorGetMidiControllerForPortCallback)Marshal.GetDelegateForFunctionPointer(data.GetMidiControllerForPort, typeof(DssiDescriptorGetMidiControllerForPortCallback)); }
if (data.RunSynth != IntPtr.Zero) { RunSynth = (DssiDescriptorRunSynthCallback)Marshal.GetDelegateForFunctionPointer(data.RunSynth, typeof(DssiDescriptorRunSynthCallback)); }
if (data.RunSynthAdding != IntPtr.Zero) { RunSynthAdding = (DssiDescriptorRunSynthCallback)Marshal.GetDelegateForFunctionPointer(data.RunSynthAdding, typeof(DssiDescriptorRunSynthCallback)); }
if (data.RunMultiSynth != IntPtr.Zero) { RunMultiSynth = (DssiDescriptorRunMultiSynthCallback)Marshal.GetDelegateForFunctionPointer(data.RunMultiSynth, typeof(DssiDescriptorRunMultiSynthCallback)); }
if (data.RunMultiSynthAdding != IntPtr.Zero) { RunMultiSynthAdding = (DssiDescriptorRunMultiSynthCallback)Marshal.GetDelegateForFunctionPointer(data.RunMultiSynthAdding, typeof(DssiDescriptorRunMultiSynthCallback)); }
IsSynth = data.RunSynth != null;
}

public DssiInstance CreateInstance(int sampleRate, int bufferSize = 1024)
{
IntPtr handle = LadspaDescriptor.Instantiate != null ? LadspaDescriptor.Instantiate(LadspaDescriptor.DataHandle, (uint)sampleRate) : IntPtr.Zero;
if (handle == IntPtr.Zero) { throw new Exception("Failed to create instance."); }
lock (this) { if (_programs == null) { _programs = LoadProgramsFromHandle(handle); } }
return (new DssiInstance(this, handle, sampleRate, bufferSize));
}

private DssiProgramDescriptor[] LoadProgramsFromHandle(IntPtr handle)
{
List<DssiProgramDescriptor> programs = new List<DssiProgramDescriptor>();
if (GetProgram != null)
{
for (uint index = 0; true; index++)
{
IntPtr programPtr = GetProgram(handle, index);
if (programPtr == IntPtr.Zero) { break; }
programs.Add((DssiProgramDescriptor)Marshal.PtrToStructure(programPtr, typeof(DssiProgramDescriptor)));
}
}
return (programs.ToArray());
}
}
}
37 changes: 37 additions & 0 deletions DssiDescriptorStruct.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;

namespace LADSPA.NET
{
[StructLayout(LayoutKind.Sequential)]
internal struct DssiDescriptorStruct
{
public uint APIVersion;
public IntPtr LadspaDescriptor; // LadspaDescriptorStruct
public IntPtr Configure; // string (IntPtr handle, string key, string value)
public IntPtr GetProgram; // IntPtr (IntPtr handle, uint index)
public IntPtr SelectProgram; // void (IntPtr handle, uint bank, uint program)
public IntPtr GetMidiControllerForPort; // int (IntPtr handle, uint port)
public IntPtr RunSynth; // void (IntPtr thisPtr, uint sampleCount, IntPtr events, uint eventCount)
public IntPtr RunSynthAdding; // void (IntPtr thisPtr, uint sampleCount, IntPtr events, uint eventCount)
public IntPtr RunMultiSynth; // void (uint thisCount, IntPtr thisPtrs, uint sampleCount, IntPtr events, IntPtr eventCounts)
public IntPtr RunMultiSynthAdding; // void (uint thisCount, IntPtr thisPtrs, uint sampleCount, IntPtr events, IntPtr eventCounts)
}

[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate string DssiDescriptorConfigureCallback(IntPtr thisPtr, string key, string value);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate IntPtr DssiDescriptorGetProgramCallback(IntPtr thisPtr, uint index);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate void DssiDescriptorSelectProgramCallback(IntPtr thisPtr, uint bank, uint program);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate int DssiDescriptorGetMidiControllerForPortCallback(IntPtr thisPtr, uint port);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate void DssiDescriptorRunSynthCallback(IntPtr thisPtr, uint sampleCount, IntPtr events, uint eventCount);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate void DssiDescriptorRunMultiSynthCallback(uint thisCount, IntPtr thisPtrs, uint sampleCount, IntPtr events, IntPtr eventCounts);
}
194 changes: 194 additions & 0 deletions DssiInstance.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;

namespace LADSPA.NET
{
public class DssiInstance : LadspaInstance
{
public readonly DssiDescriptor DssiDescriptor;

protected readonly List<DssiMidiEvent> eventList = new List<DssiMidiEvent>();
protected IntPtr eventBuffer;
protected int eventBufferSize;
protected int eventBufferCount;

internal DssiInstance(DssiDescriptor descriptor, IntPtr handle, int sampleRate, int bufferSize)
: base(descriptor.LadspaDescriptor, handle, sampleRate, bufferSize)
{
DssiDescriptor = descriptor;
}

protected void PrepareEvents()
{
int i, offset, count = eventList.Count;
int size = count * 28;
if (eventBuffer == IntPtr.Zero || eventBufferSize < size)
{
if (eventBuffer != IntPtr.Zero) { Marshal.FreeHGlobal(eventBuffer); eventBuffer = IntPtr.Zero; }
eventBuffer = Marshal.AllocHGlobal(eventBufferSize = size + 140);
}
for (i = 0, offset = 0, eventBufferCount = 0; i < count; i++)
{
DssiMidiEvent e = eventList[i];
int command = e.MidiCommand & 0xf0;
switch (command)
{
case 0x80: // Note Off
case 0x90: // Note On
case 0xA0: // Aftertouch
int code = (command == 0x80 || (e.MidiData1 == 0 && command == 0x90)) ? 7 : command == 0x90 ? 6 : 8;
Marshal.WriteInt32(eventBuffer, offset, code); offset += 4; // Type code
Marshal.WriteInt32(eventBuffer, offset, e.SampleIndex); offset += 4; // Ticks
Marshal.WriteInt64(eventBuffer, offset, 0); offset += 8; // Realtime timestamp + addresses (not used)
Marshal.WriteByte(eventBuffer, offset, (byte)(e.MidiCommand & 0x0f)); offset++; // Channel
Marshal.WriteByte(eventBuffer, offset, e.MidiData0); offset++; // Pitch
Marshal.WriteByte(eventBuffer, offset, e.MidiData1 == 0 ? (byte)64 : e.MidiData1); offset++; // Velocity
Marshal.WriteByte(eventBuffer, offset, 0); offset++; // Off Velocity (not used)
Marshal.WriteInt64(eventBuffer, offset, 0); offset += 8; // Duration (not used)
eventBufferCount++;
break;

case 0xB0: // Controller
Marshal.WriteInt32(eventBuffer, offset, 10); offset += 4; // Type code
Marshal.WriteInt32(eventBuffer, offset, e.SampleIndex); offset += 4; // Ticks
Marshal.WriteInt64(eventBuffer, offset, 0); offset += 8; // Realtime timestamp + addresses (not used)
Marshal.WriteInt32(eventBuffer, offset, e.MidiCommand & 0x0f); offset += 4; // Channel + Unused
Marshal.WriteInt32(eventBuffer, offset, e.MidiData0); offset += 4; // Control parameter
Marshal.WriteInt32(eventBuffer, offset, e.MidiData1); offset += 4; // Value
eventBufferCount++;
break;

case 0xC0: // Change program
SelectProgram((uint)(e.MidiCommand & 0x0f), e.MidiData0);
break;

case 0xD0: // Channel pressure
Marshal.WriteInt32(eventBuffer, offset, 12); offset += 4; // Type code
Marshal.WriteInt32(eventBuffer, offset, e.SampleIndex); offset += 4; // Ticks
Marshal.WriteInt64(eventBuffer, offset, 0); offset += 8; // Realtime timestamp + addresses (not used)
Marshal.WriteInt32(eventBuffer, offset, e.MidiCommand & 0x0f); offset += 4; // Channel + Unused
Marshal.WriteInt32(eventBuffer, offset, 0); offset += 4; // Control parameter
Marshal.WriteInt32(eventBuffer, offset, e.MidiData0); offset += 4; // Value
eventBufferCount++;
break;

case 0xE0: // Pitchbend
Marshal.WriteInt32(eventBuffer, offset, 13); offset += 4; // Type code
Marshal.WriteInt32(eventBuffer, offset, e.SampleIndex); offset += 4; // Ticks
Marshal.WriteInt64(eventBuffer, offset, 0); offset += 8; // Realtime timestamp + addresses (not used)
Marshal.WriteInt32(eventBuffer, offset, e.MidiCommand & 0x0f); offset += 4; // Channel + Unused
Marshal.WriteInt32(eventBuffer, offset, 0); offset += 4; // Control parameter
Marshal.WriteInt32(eventBuffer, offset, (short)(((int)e.MidiData0 << 2) + ((int)e.MidiData1 << 9)) >> 2); offset += 4; // Value
eventBufferCount++;
break;
}
}
eventList.Clear();
}

public string Configure(string key, string value)
{
if (handle == IntPtr.Zero || DssiDescriptor.Configure == null) { return (null); }
return (DssiDescriptor.Configure(handle, key, value));
}

public void SelectProgram(uint bank, uint program)
{
if (handle == IntPtr.Zero || DssiDescriptor.SelectProgram == null) { return; }
DssiDescriptor.SelectProgram(handle, bank, program);
}

public int GetMidiControllerForPort(uint port)
{
if (handle == IntPtr.Zero || DssiDescriptor.GetMidiControllerForPort == null) { return (0); }
return (DssiDescriptor.GetMidiControllerForPort(handle, port));
}

public void AddSynthEvents(params DssiMidiEvent[] events)
{
if (events != null && events.Length > 0)
{
eventList.AddRange(events);
}
}

public bool Run(float[][] outputs)
{
if (handle != IntPtr.Zero)
{
if (DssiDescriptor.RunSynth != null)
{
PrepareEvents();
DssiDescriptor.RunSynth(handle, (uint)bufferSize, eventBuffer, (uint)eventBufferCount);
CopyOutputs(outputs);
return (true);
}
else if (LadspaDescriptor.Run != null)
{
LadspaDescriptor.Run(handle, (uint)bufferSize);
CopyOutputs(outputs);
return (true);
}
}
if (eventList.Count > 0) { eventList.Clear(); }
return (false);
}

public bool RunAdding(float[][] outputs)
{
if (handle != IntPtr.Zero)
{
if (DssiDescriptor.RunSynthAdding != null)
{
PrepareEvents();
DssiDescriptor.RunSynthAdding(handle, (uint)bufferSize, eventBuffer, (uint)eventBufferCount);
CopyOutputs(outputs);
return (true);
}
else if (LadspaDescriptor.RunAdding != null)
{
LadspaDescriptor.RunAdding(handle, (uint)bufferSize);
CopyOutputs(outputs);
return (true);
}
}
if (eventList.Count > 0) { eventList.Clear(); }
return (false);
}

public override bool Run(float[][] inputs, float[][] outputs)
{
if (handle != IntPtr.Zero) { CopyInputs(inputs); }
return (Run(outputs));
}

public override bool RunAdding(float[][] inputs, float[][] outputs)
{
if (handle != IntPtr.Zero) { CopyInputs(inputs); }
return (RunAdding(outputs));
}

public override LadspaInstance Clone(int sampleRate = 0, int bufferSize = 0)
{
if (sampleRate == 0) { sampleRate = this.sampleRate; }
if (bufferSize == 0) { bufferSize = this.bufferSize; }
DssiInstance instance = DssiDescriptor.CreateInstance(sampleRate, bufferSize);
for (int i = 0; i < LadspaDescriptor.Ports.Length; i++) { instance.SetParameter(i, GetParameter(i)); }
return (instance);
}

public override void Dispose()
{
base.Dispose();
if (eventBuffer != IntPtr.Zero)
{
Marshal.FreeHGlobal(eventBuffer);
eventBuffer = IntPtr.Zero;
}
}
}
}
18 changes: 18 additions & 0 deletions DssiMidiEvent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;

namespace LADSPA.NET
{
public struct DssiMidiEvent
{
public int SampleIndex;
public byte MidiCommand;
public byte MidiData0;
public byte MidiData1;
public byte MidiData2;
}
}
17 changes: 17 additions & 0 deletions DssiProgramDescriptorStruct.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;

namespace LADSPA.NET
{
[StructLayout(LayoutKind.Sequential)]
public struct DssiProgramDescriptor
{
public uint Bank;
public uint Program;
public string Name;
}
}
Loading

0 comments on commit 53ec877

Please sign in to comment.