Allow MIDI program change

This commit is contained in:
hneemann 2019-02-11 23:13:48 +01:00
parent 57593c1f6a
commit dbdb6f79a0
9 changed files with 2800 additions and 38 deletions

File diff suppressed because it is too large Load Diff

View File

@ -37,7 +37,7 @@
<int>15</int> <int>15</int>
</entry> </entry>
</elementAttributes> </elementAttributes>
<pos x="100" y="240"/> <pos x="100" y="260"/>
</visualElement> </visualElement>
<visualElement> <visualElement>
<elementName>Counter</elementName> <elementName>Counter</elementName>
@ -113,7 +113,12 @@
</visualElement> </visualElement>
<visualElement> <visualElement>
<elementName>MIDI</elementName> <elementName>MIDI</elementName>
<elementAttributes/> <elementAttributes>
<entry>
<string>midiInstrument</string>
<string>Accordion</string>
</entry>
</elementAttributes>
<pos x="580" y="180"/> <pos x="580" y="180"/>
</visualElement> </visualElement>
<visualElement> <visualElement>
@ -121,6 +126,11 @@
<elementAttributes/> <elementAttributes/>
<pos x="140" y="120"/> <pos x="140" y="120"/>
</visualElement> </visualElement>
<visualElement>
<elementName>Const</elementName>
<elementAttributes/>
<pos x="560" y="240"/>
</visualElement>
</visualElements> </visualElements>
<wires> <wires>
<wire> <wire>
@ -132,16 +142,20 @@
<p2 x="480" y="160"/> <p2 x="480" y="160"/>
</wire> </wire>
<wire> <wire>
<p1 x="100" y="240"/> <p1 x="560" y="240"/>
<p2 x="120" y="240"/>
</wire>
<wire>
<p1 x="240" y="240"/>
<p2 x="580" y="240"/> <p2 x="580" y="240"/>
</wire> </wire>
<wire> <wire>
<p1 x="120" y="240"/> <p1 x="100" y="260"/>
<p2 x="240" y="240"/> <p2 x="120" y="260"/>
</wire>
<wire>
<p1 x="120" y="260"/>
<p2 x="240" y="260"/>
</wire>
<wire>
<p1 x="240" y="260"/>
<p2 x="580" y="260"/>
</wire> </wire>
<wire> <wire>
<p1 x="560" y="180"/> <p1 x="560" y="180"/>
@ -205,7 +219,7 @@
</wire> </wire>
<wire> <wire>
<p1 x="240" y="140"/> <p1 x="240" y="140"/>
<p2 x="240" y="240"/> <p2 x="240" y="260"/>
</wire> </wire>
<wire> <wire>
<p1 x="260" y="160"/> <p1 x="260" y="160"/>
@ -213,7 +227,7 @@
</wire> </wire>
<wire> <wire>
<p1 x="120" y="140"/> <p1 x="120" y="140"/>
<p2 x="120" y="240"/> <p2 x="120" y="260"/>
</wire> </wire>
<wire> <wire>
<p1 x="120" y="100"/> <p1 x="120" y="100"/>

View File

@ -739,14 +739,20 @@ public final class Keys {
/** /**
* Selects the midi channel * Selects the midi channel
*/ */
public static final Key.KeyInteger MIDICHANNEL = public static final Key.KeyInteger MIDI_CHANNEL =
new Key.KeyInteger("midiChannel", 0) new Key.KeyInteger("midiChannel", 1)
.setMin(0) .setMin(1)
.setMax(15); .setMax(16);
/** /**
* Selects the midi channel * Selects the midi channel
*/ */
public static final Key<String> MIDIINSTRUMENT = public static final Key<String> MIDI_INSTRUMENT =
new Key<>("midiInstrument", ""); new Key<>("midiInstrument", "");
/**
* Enables Program change
*/
public static final Key<Boolean> MIDI_PROG_CHANGE =
new Key<>("midiProgChange", false);
} }

View File

@ -6,10 +6,7 @@
package de.neemann.digital.core.io; package de.neemann.digital.core.io;
import de.neemann.digital.core.*; import de.neemann.digital.core.*;
import de.neemann.digital.core.element.Element; import de.neemann.digital.core.element.*;
import de.neemann.digital.core.element.ElementAttributes;
import de.neemann.digital.core.element.ElementTypeDescription;
import de.neemann.digital.core.element.Keys;
import javax.sound.midi.MidiChannel; import javax.sound.midi.MidiChannel;
@ -24,21 +21,38 @@ public class MIDI extends Node implements Element {
* The Speakers description * The Speakers description
*/ */
public static final ElementTypeDescription DESCRIPTION public static final ElementTypeDescription DESCRIPTION
= new ElementTypeDescription(MIDI.class, = new ElementTypeDescription(MIDI.class) {
input("N"), public PinDescriptions getInputDescription(ElementAttributes elementAttributes) throws NodeException {
if (elementAttributes.get(Keys.MIDI_PROG_CHANGE))
return new PinDescriptions(input("N"),
input("V"), input("V"),
input("OnOff"), input("OnOff"),
input("C").setClock()) input("PC"),
input("en"),
input("C").setClock()).setLangKey(getPinLangKey());
else
return new PinDescriptions(input("N"),
input("V"),
input("OnOff"),
input("en"),
input("C").setClock()).setLangKey(getPinLangKey());
}
}
.addAttribute(Keys.ROTATE) .addAttribute(Keys.ROTATE)
.addAttribute(Keys.MIDICHANNEL) .addAttribute(Keys.LABEL)
.addAttribute(Keys.MIDIINSTRUMENT); .addAttribute(Keys.MIDI_CHANNEL)
.addAttribute(Keys.MIDI_INSTRUMENT)
.addAttribute(Keys.MIDI_PROG_CHANGE);
private final int chanNum; private final int chanNum;
private final String instrument; private final String instrument;
private final boolean progChangeEnable;
private ObservableValue note; private ObservableValue note;
private ObservableValue volume; private ObservableValue volume;
private ObservableValue clock; private ObservableValue clock;
private ObservableValue onOff; private ObservableValue onOff;
private ObservableValue en;
private ObservableValue progChange;
private MidiChannel channel; private MidiChannel channel;
private boolean lastCl = false; private boolean lastCl = false;
@ -48,8 +62,9 @@ public class MIDI extends Node implements Element {
* @param attributes the elements attributes * @param attributes the elements attributes
*/ */
public MIDI(ElementAttributes attributes) { public MIDI(ElementAttributes attributes) {
chanNum = attributes.get(Keys.MIDICHANNEL); chanNum = attributes.get(Keys.MIDI_CHANNEL)-1;
instrument = attributes.get(Keys.MIDIINSTRUMENT); instrument = attributes.get(Keys.MIDI_INSTRUMENT);
progChangeEnable = attributes.get(Keys.MIDI_PROG_CHANGE);
} }
@Override @Override
@ -57,7 +72,14 @@ public class MIDI extends Node implements Element {
note = inputs.get(0).checkBits(7, this, 0); note = inputs.get(0).checkBits(7, this, 0);
volume = inputs.get(1).checkBits(7, this, 1); volume = inputs.get(1).checkBits(7, this, 1);
onOff = inputs.get(2).checkBits(1, this, 2); onOff = inputs.get(2).checkBits(1, this, 2);
clock = inputs.get(3).checkBits(1, this, 3).addObserverToValue(this); if (progChangeEnable) {
progChange = inputs.get(3).checkBits(1, this, 3);
en = inputs.get(4).checkBits(1, this, 4);
clock = inputs.get(5).checkBits(1, this, 5).addObserverToValue(this);
} else {
en = inputs.get(3).checkBits(1, this, 3);
clock = inputs.get(4).checkBits(1, this, 4).addObserverToValue(this);
}
} }
@Override @Override
@ -68,14 +90,18 @@ public class MIDI extends Node implements Element {
@Override @Override
public void readInputs() throws NodeException { public void readInputs() throws NodeException {
boolean cl = clock.getBool(); boolean cl = clock.getBool();
if (!lastCl && cl) { if (!lastCl && cl && en.getBool()) {
int note = (int) this.note.getValue(); int note = (int) this.note.getValue();
if (progChange != null && progChange.getBool()) {
channel.programChange(note);
} else {
if (onOff.getBool()) { if (onOff.getBool()) {
int v = (int) volume.getValue(); int v = (int) volume.getValue();
channel.noteOn(note, v); channel.noteOn(note, v);
} else } else
channel.noteOff(note); channel.noteOff(note);
} }
}
lastCl = cl; lastCl = cl;
} }

View File

@ -95,7 +95,7 @@ public final class EditorFactory {
* @return the editor * @return the editor
*/ */
public <T> Editor<T> create(Key<T> key, T value) { public <T> Editor<T> create(Key<T> key, T value) {
if (key == Keys.MIDIINSTRUMENT) if (key == Keys.MIDI_INSTRUMENT)
return (Editor<T>) new MidiInstrumentEditor(value.toString()); return (Editor<T>) new MidiInstrumentEditor(value.toString());
Class<? extends Editor> fac = map.get(key.getValueClass()); Class<? extends Editor> fac = map.get(key.getValueClass());

View File

@ -264,6 +264,8 @@
<string name="elem_MIDI_pin_V">Lautstärke</string> <string name="elem_MIDI_pin_V">Lautstärke</string>
<string name="elem_MIDI_pin_OnOff">Wenn gesetzt, enspricht das dem Drücken einer Keyboard-Taste (key down). <string name="elem_MIDI_pin_OnOff">Wenn gesetzt, enspricht das dem Drücken einer Keyboard-Taste (key down).
Wenn nicht gesetzt, entspricht das einem Loslassen der Taste (key up).</string> Wenn nicht gesetzt, entspricht das einem Loslassen der Taste (key up).</string>
<string name="elem_MIDI_pin_en">Wenn dieser eingang high ist, kann der Baustein angesprochen werden.</string>
<string name="elem_MIDI_pin_PC">Wenn gesetzt, wird mit dem Wert an Eingang N das Programm (Instrument) gewechselt.</string>
<string name="elem_MIDI_pin_C">Takteingang</string> <string name="elem_MIDI_pin_C">Takteingang</string>
<!-- Leitungen --> <!-- Leitungen -->
@ -1305,6 +1307,9 @@ Sind evtl. die Namen der Variablen nicht eindeutig?</string>
<string name="key_midiChannel_tt">Legt den MIDI-Kanal fest.</string> <string name="key_midiChannel_tt">Legt den MIDI-Kanal fest.</string>
<string name="key_midiInstrument">MIDI-Instrument</string> <string name="key_midiInstrument">MIDI-Instrument</string>
<string name="key_midiInstrument_tt">Das MIDI-Instrument, welches verwendet werden soll.</string> <string name="key_midiInstrument_tt">Das MIDI-Instrument, welches verwendet werden soll.</string>
<string name="key_midiProgChange">Programmwechsel erlauben</string>
<string name="key_midiProgChange_tt">Fügt einen weiteren Eingang PC hinzu. Wird dieser Eingang auf High gesetzt,
wird mit dem Wert am Eingang N das Programm (Intrument) gewechselt.</string>
<string name="mod_insertWire">Leitung eingefügt.</string> <string name="mod_insertWire">Leitung eingefügt.</string>
<string name="mod_insertCopied">Aus Zwischenablage eingefügt.</string> <string name="mod_insertCopied">Aus Zwischenablage eingefügt.</string>

View File

@ -269,6 +269,8 @@
<string name="elem_MIDI_pin_V">Volume</string> <string name="elem_MIDI_pin_V">Volume</string>
<string name="elem_MIDI_pin_OnOff">If set, this translates to pressing a keyboard key (key down event), <string name="elem_MIDI_pin_OnOff">If set, this translates to pressing a keyboard key (key down event),
if not set, this translates to releasing the key (key up event).</string> if not set, this translates to releasing the key (key up event).</string>
<string name="elem_MIDI_pin_en">Enables the component</string>
<string name="elem_MIDI_pin_PC">If high, the value at N is used to change the program (instrument).</string>
<string name="elem_MIDI_pin_C">Clock</string> <string name="elem_MIDI_pin_C">Clock</string>
<!-- Wires --> <!-- Wires -->
@ -1293,6 +1295,9 @@
<string name="key_midiChannel_tt">Selects the MIDI channel to use.</string> <string name="key_midiChannel_tt">Selects the MIDI channel to use.</string>
<string name="key_midiInstrument">MIDI instrument</string> <string name="key_midiInstrument">MIDI instrument</string>
<string name="key_midiInstrument_tt">The MIDI instrument to use.</string> <string name="key_midiInstrument_tt">The MIDI instrument to use.</string>
<string name="key_midiProgChange">Allow program change</string>
<string name="key_midiProgChange_tt">Adds a new input PC. If this input is set to high,
the value at input N is used to change te program (instrument).</string>
<string name="mod_insertWire">Inserted wire.</string> <string name="mod_insertWire">Inserted wire.</string>
<string name="mod_insertCopied">Insert from clipboard.</string> <string name="mod_insertCopied">Insert from clipboard.</string>

View File

@ -32,7 +32,7 @@ public class TestExamples extends TestCase {
*/ */
public void testDistExamples() throws Exception { public void testDistExamples() throws Exception {
File examples = new File(Resources.getRoot().getParentFile().getParentFile(), "/main/dig"); File examples = new File(Resources.getRoot().getParentFile().getParentFile(), "/main/dig");
assertEquals(249, new FileScanner(this::check).scan(examples)); assertEquals(250, new FileScanner(this::check).scan(examples));
assertEquals(170, testCasesInFiles); assertEquals(170, testCasesInFiles);
} }

View File

@ -1238,6 +1238,10 @@
<p1 x="940" y="380"/> <p1 x="940" y="380"/>
<p2 x="960" y="380"/> <p2 x="960" y="380"/>
</wire> </wire>
<wire>
<p1 x="280" y="1020"/>
<p2 x="300" y="1020"/>
</wire>
<wire> <wire>
<p1 x="640" y="500"/> <p1 x="640" y="500"/>
<p2 x="640" y="520"/> <p2 x="640" y="520"/>
@ -1510,6 +1514,10 @@
<p1 x="280" y="980"/> <p1 x="280" y="980"/>
<p2 x="280" y="1000"/> <p2 x="280" y="1000"/>
</wire> </wire>
<wire>
<p1 x="280" y="1000"/>
<p2 x="280" y="1020"/>
</wire>
<wire> <wire>
<p1 x="220" y="220"/> <p1 x="220" y="220"/>
<p2 x="220" y="300"/> <p2 x="220" y="300"/>