improved the MIDI component

This commit is contained in:
hneemann 2019-02-10 20:20:18 +01:00
parent 39c0c921ee
commit 9bc188d69e
5 changed files with 64 additions and 36 deletions

View File

@ -22,30 +22,34 @@ import static de.neemann.digital.core.element.PinInfo.input;
/**
* The speaker.
*/
public class Speaker extends Node implements Element {
public class MIDI extends Node implements Element {
/**
* The Speakers description
*/
public static final ElementTypeDescription DESCRIPTION
= new ElementTypeDescription(Speaker.class, input("N"), input("V"), input("en")) {}
= new ElementTypeDescription(MIDI.class,
input("N"),
input("V"),
input("OnOff"),
input("C").setClock())
.addAttribute(Keys.MIDICHANNEL)
.addAttribute(Keys.ROTATE);
private final int chanNum;
private ObservableValue note;
private ObservableValue volume;
private ObservableValue enable;
private ObservableValue clock;
private ObservableValue onOff;
private MidiChannel channel;
private boolean lastEn = false;
private int notePlaying;
private boolean lastCl = false;
/**
* Creates a new instance
*
* @param attributes the elements attributes
*/
public Speaker(ElementAttributes attributes) {
public MIDI(ElementAttributes attributes) {
chanNum = attributes.get(Keys.MIDICHANNEL);
}
@ -53,7 +57,8 @@ public class Speaker extends Node implements Element {
public void setInputs(ObservableValues inputs) throws NodeException {
note = inputs.get(0).checkBits(7, this, 0);
volume = inputs.get(1).checkBits(7, this, 1);
enable = inputs.get(2).checkBits(1, this, 2).addObserverToValue(this);
onOff = inputs.get(2).checkBits(1, this, 2);
clock = inputs.get(3).checkBits(1, this, 3).addObserverToValue(this);
}
@Override
@ -63,17 +68,16 @@ public class Speaker extends Node implements Element {
@Override
public void readInputs() throws NodeException {
boolean en = enable.getBool();
if (channel != null) {
if (!lastEn && en) {
notePlaying = (int) note.getValue();
boolean cl = clock.getBool();
if (!lastCl && cl) {
int note = (int) this.note.getValue();
if (onOff.getBool()) {
int v = (int) volume.getValue();
channel.noteOn(notePlaying, v);
} else if (lastEn && !en) {
channel.noteOff(notePlaying);
}
channel.noteOn(note, v);
} else
channel.noteOff(note);
}
lastEn = en;
lastCl = cl;
}
@Override
@ -86,10 +90,16 @@ public class Speaker extends Node implements Element {
Synthesizer synth = MidiSystem.getSynthesizer();
synth.open();
MidiChannel[] channels = synth.getChannels();
if (chanNum >= channels.length)
channel = channels[0];
else
channel = channels[chanNum];
if (chanNum >= channels.length) {
synth.close();
throw new NodeException(Lang.get("err_midiChannel_N_NotAvailable", chanNum));
}
channel = channels[chanNum];
if (channel == null) {
synth.close();
throw new NodeException(Lang.get("err_midiChannel_N_NotAvailable", chanNum));
}
model.addObserver(event -> {
if (event.equals(ModelEvent.STOPPED))

View File

@ -141,7 +141,7 @@ public class ElementLibrary implements Iterable<ElementLibrary.ElementContainer>
.add(RotEncoder.DESCRIPTION)
.add(Keyboard.DESCRIPTION)
.add(Terminal.DESCRIPTION)
.add(Speaker.DESCRIPTION)))
.add(MIDI.DESCRIPTION)))
.add(new LibraryNode(Lang.get("lib_wires"))
.add(Ground.DESCRIPTION)
.add(VDD.DESCRIPTION)

View File

@ -258,11 +258,13 @@
<string name="elem_Terminal_pin_D">Über diesen Eingang werden die anzuzeigenden Daten an das Terminal weitergegeben.</string>
<string name="elem_Terminal_pin_en">Ein High an diesem Eingang aktiviert den Takteingang.</string>
<string name="elem_Speaker">Lautsprecher</string>
<string name="elem_Speaker_tt">Nutzt das MIDI-System, um Noten abzuspielen.</string>
<string name="elem_Speaker_pin_N">Note</string>
<string name="elem_Speaker_pin_V">Lautstärke</string>
<string name="elem_Speaker_pin_en">Wenn gesetzt, wird der Ton ausgegeben.</string>
<string name="elem_MIDI">MIDI</string>
<string name="elem_MIDI_tt">Nutzt das MIDI-System, um Noten abzuspielen.</string>
<string name="elem_MIDI_pin_N">Note</string>
<string name="elem_MIDI_pin_V">Lautstärke</string>
<string name="elem_MIDI_pin_OnOff">Wenn gesetzt, enspricht das dem Drücken eine Keyboard-Taste (key down).
Wenn nicht gesetzt, entspricht das einem Loslassen der Taste (key up).</string>
<string name="elem_MIDI_pin_C">Takteingang</string>
<!-- Leitungen -->
@ -999,6 +1001,7 @@ Sind evtl. die Namen der Variablen nicht eindeutig?</string>
<string name="err_ProgMemLabelsNotDifferent">Wenn Programme in mehrere RAMs geladen werden sollen, müssen alle RAMs
unterschiedliche Bezeichnungen haben. Die lexikalische Ordnung legt dann die Reihenfolge der RAMs fest.</string>
<string name="err_midiSystemNotAvailable">Das MIDI-System ist nicht verfügbar.</string>
<string name="err_midiChannel_N_NotAvailable">Der MIDI-Kanal {0} ist nicht verfügbar.</string>
<string name="key_AddrBits">Adress-Bits</string><!-- ROM, RAMDualPort, RAMSinglePort, RAMSinglePortSel, EEPROM -->
<string name="key_AddrBits_tt">Anzahl der Adress-Bits, die verwendet werden.</string>

View File

@ -263,11 +263,13 @@
<string name="elem_Terminal_pin_D">The data to write to the terminal</string>
<string name="elem_Terminal_pin_en">A high at this input enables the clock input.</string>
<string name="elem_Speaker">Speaker</string>
<string name="elem_Speaker_tt">Uses the MIDI system to play notes.</string>
<string name="elem_Speaker_pin_N">Note</string>
<string name="elem_Speaker_pin_V">Valume</string>
<string name="elem_Speaker_pin_en">When set, the note is played.</string>
<string name="elem_MIDI">MIDI</string>
<string name="elem_MIDI_tt">Uses the MIDI system to play notes.</string>
<string name="elem_MIDI_pin_N">Note</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),
if not set, this translates to releasing the key (key up event).</string>
<string name="elem_MIDI_pin_C">Clock</string>
<!-- Wires -->
@ -992,6 +994,7 @@
<string name="err_ProgMemLabelsNotDifferent">If programs are to be loaded into several RAMs, all RAMs must have
different names. The lexical order then determines the order of the RAMs.</string>
<string name="err_midiSystemNotAvailable">The MIDI-System is not available.</string>
<string name="err_midiChannel_N_NotAvailable">The MIDI channel {0} is not available.</string>
<string name="key_AddrBits">Address Bits</string><!-- ROM, RAMDualPort, RAMSinglePort, RAMSinglePortSel, EEPROM -->
<string name="key_AddrBits_tt">Number of address bits used.</string>

View File

@ -579,11 +579,6 @@
<elementAttributes/>
<pos x="120" y="900"/>
</visualElement>
<visualElement>
<elementName>Speaker</elementName>
<elementAttributes/>
<pos x="300" y="940"/>
</visualElement>
<visualElement>
<elementName>Const</elementName>
<elementAttributes>
@ -604,6 +599,11 @@
</elementAttributes>
<pos x="280" y="960"/>
</visualElement>
<visualElement>
<elementName>MIDI</elementName>
<elementAttributes/>
<pos x="300" y="940"/>
</visualElement>
</visualElements>
<wires>
<wire>
@ -836,6 +836,10 @@
</wire>
<wire>
<p1 x="240" y="980"/>
<p2 x="280" y="980"/>
</wire>
<wire>
<p1 x="280" y="980"/>
<p2 x="300" y="980"/>
</wire>
<wire>
@ -1006,6 +1010,10 @@
<p1 x="1140" y="360"/>
<p2 x="1160" y="360"/>
</wire>
<wire>
<p1 x="280" y="1000"/>
<p2 x="300" y="1000"/>
</wire>
<wire>
<p1 x="1080" y="940"/>
<p2 x="1100" y="940"/>
@ -1498,6 +1506,10 @@
<p1 x="920" y="100"/>
<p2 x="920" y="620"/>
</wire>
<wire>
<p1 x="280" y="980"/>
<p2 x="280" y="1000"/>
</wire>
<wire>
<p1 x="220" y="220"/>
<p2 x="220" y="300"/>