diff --git a/UnityProject/Assembly-CSharp.csproj b/UnityProject/Assembly-CSharp.csproj
index dfd7428..ced6be8 100644
--- a/UnityProject/Assembly-CSharp.csproj
+++ b/UnityProject/Assembly-CSharp.csproj
@@ -71,6 +71,7 @@
+
diff --git a/UnityProject/Assets/Editor/PdBackendEditor.cs b/UnityProject/Assets/Editor/PdBackendEditor.cs
index 8b90ff9..c7cd88f 100644
--- a/UnityProject/Assets/Editor/PdBackendEditor.cs
+++ b/UnityProject/Assets/Editor/PdBackendEditor.cs
@@ -8,6 +8,7 @@ namespace cylvester
{
private PdBackend pdBackend_;
private SerializedProperty midiMessageReceivedProperty_;
+ private SerializedProperty midiClockReceivedProperty_;
private readonly string[] samples_ =
{
@@ -36,6 +37,9 @@ namespace cylvester
midiMessageReceivedProperty_ = serializedObject.FindProperty("midiMessageReceived");
EditorGUILayout.PropertyField(midiMessageReceivedProperty_);
+ midiClockReceivedProperty_ = serializedObject.FindProperty("midiClockReceived");
+ EditorGUILayout.PropertyField(midiClockReceivedProperty_);
+
if (Application.isPlaying)
{
RenderSamplePlayback();
diff --git a/UnityProject/Assets/Scenes/Examples/MIDI/MIDI.unity b/UnityProject/Assets/Scenes/Examples/MIDI/MIDI.unity
index 4f0745f..74b3e5b 100644
--- a/UnityProject/Assets/Scenes/Examples/MIDI/MIDI.unity
+++ b/UnityProject/Assets/Scenes/Examples/MIDI/MIDI.unity
@@ -212,6 +212,171 @@ Transform:
m_Father: {fileID: 0}
m_RootOrder: 3
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!1 &560516510
+GameObject:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ serializedVersion: 6
+ m_Component:
+ - component: {fileID: 560516514}
+ - component: {fileID: 560516513}
+ - component: {fileID: 560516512}
+ - component: {fileID: 560516511}
+ m_Layer: 5
+ m_Name: Canvas
+ m_TagString: Untagged
+ m_Icon: {fileID: 0}
+ m_NavMeshLayer: 0
+ m_StaticEditorFlags: 0
+ m_IsActive: 1
+--- !u!114 &560516511
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 560516510}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: dc42784cf147c0c48a680349fa168899, type: 3}
+ m_Name:
+ m_EditorClassIdentifier:
+ m_IgnoreReversedGraphics: 1
+ m_BlockingObjects: 0
+ m_BlockingMask:
+ serializedVersion: 2
+ m_Bits: 4294967295
+--- !u!114 &560516512
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 560516510}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: 0cd44c1031e13a943bb63640046fad76, type: 3}
+ m_Name:
+ m_EditorClassIdentifier:
+ m_UiScaleMode: 0
+ m_ReferencePixelsPerUnit: 100
+ m_ScaleFactor: 1
+ m_ReferenceResolution: {x: 800, y: 600}
+ m_ScreenMatchMode: 0
+ m_MatchWidthOrHeight: 0
+ m_PhysicalUnit: 3
+ m_FallbackScreenDPI: 96
+ m_DefaultSpriteDPI: 96
+ m_DynamicPixelsPerUnit: 1
+--- !u!223 &560516513
+Canvas:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 560516510}
+ m_Enabled: 1
+ serializedVersion: 3
+ m_RenderMode: 0
+ m_Camera: {fileID: 0}
+ m_PlaneDistance: 100
+ m_PixelPerfect: 0
+ m_ReceivesEvents: 1
+ m_OverrideSorting: 0
+ m_OverridePixelPerfect: 0
+ m_SortingBucketNormalizedSize: 0
+ m_AdditionalShaderChannelsFlag: 0
+ m_SortingLayerID: 0
+ m_SortingOrder: 0
+ m_TargetDisplay: 0
+--- !u!224 &560516514
+RectTransform:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 560516510}
+ m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+ m_LocalPosition: {x: 0, y: 0, z: 0}
+ m_LocalScale: {x: 0, y: 0, z: 0}
+ m_Children:
+ - {fileID: 1790437804}
+ m_Father: {fileID: 0}
+ m_RootOrder: 4
+ m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+ m_AnchorMin: {x: 0, y: 0}
+ m_AnchorMax: {x: 0, y: 0}
+ m_AnchoredPosition: {x: 0, y: 0}
+ m_SizeDelta: {x: 0, y: 0}
+ m_Pivot: {x: 0, y: 0}
+--- !u!1 &700239840
+GameObject:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ serializedVersion: 6
+ m_Component:
+ - component: {fileID: 700239843}
+ - component: {fileID: 700239842}
+ - component: {fileID: 700239841}
+ m_Layer: 0
+ m_Name: EventSystem
+ m_TagString: Untagged
+ m_Icon: {fileID: 0}
+ m_NavMeshLayer: 0
+ m_StaticEditorFlags: 0
+ m_IsActive: 1
+--- !u!114 &700239841
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 700239840}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: 4f231c4fb786f3946a6b90b886c48677, type: 3}
+ m_Name:
+ m_EditorClassIdentifier:
+ m_HorizontalAxis: Horizontal
+ m_VerticalAxis: Vertical
+ m_SubmitButton: Submit
+ m_CancelButton: Cancel
+ m_InputActionsPerSecond: 10
+ m_RepeatDelay: 0.5
+ m_ForceModuleActive: 0
+--- !u!114 &700239842
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 700239840}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: 76c392e42b5098c458856cdf6ecaaaa1, type: 3}
+ m_Name:
+ m_EditorClassIdentifier:
+ m_FirstSelected: {fileID: 0}
+ m_sendNavigationEvents: 1
+ m_DragThreshold: 10
+--- !u!4 &700239843
+Transform:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 700239840}
+ m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+ m_LocalPosition: {x: 0, y: 0, z: 0}
+ m_LocalScale: {x: 1, y: 1, z: 1}
+ m_Children: []
+ m_Father: {fileID: 0}
+ m_RootOrder: 5
+ m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &1261823479
GameObject:
m_ObjectHideFlags: 0
@@ -223,6 +388,7 @@ GameObject:
- component: {fileID: 1261823481}
- component: {fileID: 1261823480}
- component: {fileID: 1261823482}
+ - component: {fileID: 1261823483}
m_Layer: 0
m_Name: PdBackend
m_TagString: Untagged
@@ -267,6 +433,20 @@ MonoBehaviour:
m_StringArgument:
m_BoolArgument: 0
m_CallState: 2
+ midiClockReceived:
+ m_PersistentCalls:
+ m_Calls:
+ - m_Target: {fileID: 1261823483}
+ m_MethodName: onClockReceived
+ m_Mode: 1
+ m_Arguments:
+ m_ObjectArgument: {fileID: 0}
+ m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine
+ m_IntArgument: 0
+ m_FloatArgument: 0
+ m_StringArgument:
+ m_BoolArgument: 0
+ m_CallState: 2
samplePlayback: 0
--- !u!4 &1261823481
Transform:
@@ -297,6 +477,19 @@ MonoBehaviour:
logAll: 0
logFiltered: 0
filterStatusByte: 176
+--- !u!114 &1261823483
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 1261823479}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: 10a68b6f417f08e428a5e9c5e21c485a, type: 3}
+ m_Name:
+ m_EditorClassIdentifier:
+ counter: {fileID: 1790437805}
--- !u!1 &1461024797
GameObject:
m_ObjectHideFlags: 0
@@ -480,6 +673,83 @@ MonoBehaviour:
enableFptlForForwardOpaque: 0
enableBigTilePrepass: 0
isFptlEnabled: 0
+--- !u!1 &1790437803
+GameObject:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ serializedVersion: 6
+ m_Component:
+ - component: {fileID: 1790437804}
+ - component: {fileID: 1790437806}
+ - component: {fileID: 1790437805}
+ m_Layer: 5
+ m_Name: Text
+ m_TagString: Untagged
+ m_Icon: {fileID: 0}
+ m_NavMeshLayer: 0
+ m_StaticEditorFlags: 0
+ m_IsActive: 1
+--- !u!224 &1790437804
+RectTransform:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 1790437803}
+ m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+ m_LocalPosition: {x: 0, y: 0, z: 0}
+ m_LocalScale: {x: 1, y: 1, z: 1}
+ m_Children: []
+ m_Father: {fileID: 560516514}
+ m_RootOrder: 0
+ m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+ m_AnchorMin: {x: 0.5, y: 0.5}
+ m_AnchorMax: {x: 0.5, y: 0.5}
+ m_AnchoredPosition: {x: 0, y: -31.3}
+ m_SizeDelta: {x: 300, y: 90}
+ m_Pivot: {x: 0.5, y: 0.5}
+--- !u!114 &1790437805
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 1790437803}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3}
+ m_Name:
+ m_EditorClassIdentifier:
+ m_Material: {fileID: 0}
+ m_Color: {r: 1, g: 1, b: 1, a: 1}
+ m_RaycastTarget: 1
+ m_OnCullStateChanged:
+ m_PersistentCalls:
+ m_Calls: []
+ m_FontData:
+ m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
+ m_FontSize: 32
+ m_FontStyle: 1
+ m_BestFit: 0
+ m_MinSize: 3
+ m_MaxSize: 40
+ m_Alignment: 4
+ m_AlignByGeometry: 0
+ m_RichText: 1
+ m_HorizontalOverflow: 0
+ m_VerticalOverflow: 0
+ m_LineSpacing: 1
+ m_Text: 1:1:0
+--- !u!222 &1790437806
+CanvasRenderer:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 1790437803}
+ m_CullTransparentMesh: 0
--- !u!1 &2049244779
GameObject:
m_ObjectHideFlags: 0
diff --git a/UnityProject/Assets/Scripts/PdConnection/MidiClockCounter.cs b/UnityProject/Assets/Scripts/PdConnection/MidiClockCounter.cs
new file mode 100644
index 0000000..0a1f37d
--- /dev/null
+++ b/UnityProject/Assets/Scripts/PdConnection/MidiClockCounter.cs
@@ -0,0 +1,21 @@
+
+using UnityEngine;
+using UnityEngine.UI;
+
+public class MidiClockCounter : MonoBehaviour
+{
+
+ [SerializeField] private Text counter;
+
+ private int count_ = 0;
+
+ public void onClockReceived()
+ {
+ count_++;
+ var tick = count_ % 24;
+ var beat = count_ / 24;
+ var measure = beat / 4;
+
+ counter.text = (measure+1) + ":" + (beat%4+1) + ":" + tick;
+ }
+}
diff --git a/UnityProject/Assets/Scripts/PdConnection/MidiClockCounter.cs.meta b/UnityProject/Assets/Scripts/PdConnection/MidiClockCounter.cs.meta
new file mode 100644
index 0000000..455d81c
--- /dev/null
+++ b/UnityProject/Assets/Scripts/PdConnection/MidiClockCounter.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 10a68b6f417f08e428a5e9c5e21c485a
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/UnityProject/Assets/Scripts/PdConnection/MidiLogger.cs b/UnityProject/Assets/Scripts/PdConnection/MidiLogger.cs
index 942b23f..a5ec4ab 100644
--- a/UnityProject/Assets/Scripts/PdConnection/MidiLogger.cs
+++ b/UnityProject/Assets/Scripts/PdConnection/MidiLogger.cs
@@ -10,6 +10,7 @@ namespace cylvester
public void OnMidiMessageReceived(MidiMessage mes)
{
+
if(logAll)
Debug.Log("MIDI Received: " + mes);
diff --git a/UnityProject/Assets/Scripts/PdConnection/MidiParser.cs b/UnityProject/Assets/Scripts/PdConnection/MidiParser.cs
index eba3f2d..395c315 100644
--- a/UnityProject/Assets/Scripts/PdConnection/MidiParser.cs
+++ b/UnityProject/Assets/Scripts/PdConnection/MidiParser.cs
@@ -4,7 +4,7 @@ using UnityEngine.Events;
namespace cylvester
{
[Serializable]
- public class UnityControlEvent : UnityEvent
+ public class UnityMidiEvent : UnityEvent
{}
public struct MidiMessage
@@ -24,6 +24,8 @@ namespace cylvester
public interface IMidiParser : IDisposable
{
event Action MidiMessageReceived;
+ event Action MidiClockReceived;
+
}
public class MidiParser : IMidiParser
@@ -39,6 +41,7 @@ namespace cylvester
private Accept accept_ = Accept.StatusByte;
private readonly IPdReceiver pdReceiver_;
private readonly Action onDataReceived_;
+ private static byte MIDI_CLOCK = 248;
public MidiParser(IPdReceiver pdReceiver)
{
@@ -48,6 +51,9 @@ namespace cylvester
{
foreach (var element in bytes)
{
+ if (element == MIDI_CLOCK)
+ MidiClockReceived?.Invoke();
+
if (element >= 128)
{
message_ = new MidiMessage {Status = element};
@@ -63,7 +69,7 @@ namespace cylvester
else if (accept_ == Accept.DataByte2 && element <= 128)
{
message_.Data2 = element;
- Invoke();
+ MidiMessageReceived?.Invoke(message_);
accept_ = Accept.StatusByte;
}
}
@@ -72,17 +78,12 @@ namespace cylvester
pdReceiver_.DataReceived += onDataReceived_;
}
- private void Invoke()
- {
- MidiMessageReceived?.Invoke(message_);
- }
-
public void Dispose()
{
pdReceiver_.DataReceived -= onDataReceived_;
}
public event Action MidiMessageReceived;
-
+ public event Action MidiClockReceived;
}
}
\ No newline at end of file
diff --git a/UnityProject/Assets/Scripts/PdConnection/PdBackend.cs b/UnityProject/Assets/Scripts/PdConnection/PdBackend.cs
index 030f9ca..d83886a 100644
--- a/UnityProject/Assets/Scripts/PdConnection/PdBackend.cs
+++ b/UnityProject/Assets/Scripts/PdConnection/PdBackend.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using UnityEngine;
+using UnityEngine.Events;
namespace cylvester
{
@@ -14,8 +15,10 @@ namespace cylvester
public class PdBackend : MonoBehaviour, IPdBackend
{
- [SerializeField] UnityControlEvent midiMessageReceived = null;
-
+ [SerializeField] UnityMidiEvent midiMessageReceived = null;
+ [SerializeField] UnityEvent midiClockReceived = null;
+
+
public int samplePlayback;
private IChangeObserver samplePlaybackObserver_;
@@ -33,6 +36,7 @@ namespace cylvester
private Action onSamplePlaybackChanged_;
private Action onMidiMessageReceived_;
+ private Action onMidiClockReceived_;
private void Awake()
{
@@ -53,13 +57,12 @@ namespace cylvester
onSamplePlaybackChanged_ = () => { pdSender_.Send(new[]{(byte)PdMessage.SampleSound, (byte)samplePlayback}); };
- onMidiMessageReceived_ = (message) => {
- midiMessageReceived.Invoke(message);
- };
+ onMidiMessageReceived_ = (message) => { midiMessageReceived.Invoke(message); };
+ onMidiClockReceived_ = () => { midiClockReceived.Invoke(); };
samplePlaybackObserver_.ValueChanged += onSamplePlaybackChanged_;
midiParser_.MidiMessageReceived += onMidiMessageReceived_;
-
+ midiParser_.MidiClockReceived += onMidiClockReceived_;
dspController_.State = true;
}
@@ -69,6 +72,8 @@ namespace cylvester
pdSender_?.Dispose();
samplePlaybackObserver_.ValueChanged -= onSamplePlaybackChanged_;
midiParser_.MidiMessageReceived -= onMidiMessageReceived_;
+ midiParser_.MidiClockReceived -= onMidiClockReceived_;
+
}
public void Update()
diff --git a/UnityProject/Assets/StreamingAssets/pd/patch/analyzer.pd b/UnityProject/Assets/StreamingAssets/pd/patch/analyzer.pd
index c492cd9..a36eeb6 100644
--- a/UnityProject/Assets/StreamingAssets/pd/patch/analyzer.pd
+++ b/UnityProject/Assets/StreamingAssets/pd/patch/analyzer.pd
@@ -1,6 +1,6 @@
-#N canvas 216 302 670 468 10;
-#X obj 125 345 adc~ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16;
-#X obj 55 386 dac~, f 6;
+#N canvas 758 125 670 468 10;
+#X obj 142 343 adc~ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16;
+#X obj 72 384 dac~, f 6;
#N canvas 215 619 730 390 analyzers_______________________________
0;
#X obj 95 44 inlet~;
@@ -51,11 +51,11 @@
#X connect 13 0 29 0;
#X connect 14 0 30 0;
#X connect 15 0 31 0;
-#X restore 126 385 pd analyzers_______________________________;
-#X obj 46 26 bang~;
-#X obj 46 49 count 16;
-#X obj 46 76 sel 0;
-#X obj 46 102 s shmemupdate;
+#X restore 143 383 pd analyzers_______________________________;
+#X obj 63 24 bang~;
+#X obj 63 47 count 16;
+#X obj 63 74 sel 0;
+#X obj 63 100 s shmemupdate;
#N canvas 763 290 408 235 window 0;
#N canvas 0 0 450 300 (subpatch) 0;
#X array hann 1024 float 1;
@@ -194,7 +194,7 @@
0.000244498 0.000150442 9.39965e-005 3.75807e-005 1.87755e-005;
#X coords 0 1 1023 0 300 100 1 0 0;
#X restore 39 32 graph;
-#X restore 533 23 pd window;
+#X restore 550 21 pd window;
#N canvas 2182 728 332 292 commands_from_unity 0;
#X obj 66 31 inlet;
#X obj 130 130 s sample_playback;
@@ -209,7 +209,7 @@
#X connect 4 0 6 0;
#X connect 4 1 1 0;
#X connect 6 0 7 0;
-#X restore 231 60 pd commands_from_unity;
+#X restore 248 58 pd commands_from_unity;
#N canvas 667 603 480 371 sample_playback 0;
#X obj 86 166 readsf~;
#X obj 95 6 r sample_playback;
@@ -235,29 +235,30 @@
#X connect 9 0 7 0;
#X connect 10 0 0 0;
#X connect 11 0 0 0;
-#X restore 55 306 pd sample_playback;
-#X obj 231 22 netreceive -u -b 54345;
-#X obj 45 140 text define -k samplefiles;
+#X restore 72 304 pd sample_playback;
+#X obj 248 20 netreceive -u -b 54345;
+#X obj 62 138 text define -k samplefiles;
#A set Back_Back.wav \; Brutal_Synth.wav \; Dialog.wav \; Drums.wav
\; Fox_Melo.wav \; Kick.wav \; Pads+Strings.wav \; Rose_Sax.wav \;
Roses_Front.wav;
-#X obj 231 245 netsend -u -b;
-#X msg 231 144 connect localhost 56765;
-#X obj 253 114 loadbang;
-#X obj 86 199 list prepend send;
-#X obj 86 223 list trim;
-#X obj 86 175 midiin;
-#X msg 410 115 23 31;
-#X msg 457 115 80 84, f 10;
-#X text 422 89 sample CC;
-#X msg 424 161 send 176 \$1 \$2;
-#X text 423 183 176... control channel 1;
-#N canvas 695 332 450 300 level 1;
+#X obj 248 243 netsend -u -b;
+#X msg 248 142 connect localhost 56765;
+#X obj 270 112 loadbang;
+#X obj 103 197 list prepend send;
+#X obj 103 221 list trim;
+#X obj 103 173 midiin;
+#X msg 427 113 23 31;
+#X msg 474 113 80 84, f 10;
+#X text 439 87 sample CC;
+#X msg 441 159 send 176 \$1 \$2;
+#X text 440 181 176... control channel 1;
+#N canvas 695 332 450 300 level 0;
#X obj 90 182 table level 16;
#X obj 89 152 shmem level 16;
#X obj 89 127 r shmemupdate;
#X connect 2 0 1 0;
-#X restore 532 55 pd level;
+#X restore 549 53 pd level;
+#X obj 12 173 midirealtimein;
#X connect 0 0 2 0;
#X connect 0 1 2 1;
#X connect 0 2 2 2;
@@ -290,3 +291,4 @@ Roses_Front.wav;
#X connect 18 0 21 0;
#X connect 19 0 21 0;
#X connect 21 0 12 0;
+#X connect 24 0 15 0;