Vorversuche zur Ermittlung sinnvoller Parameter und Anspieltechniken
(EN google-translate)
(PL google-translate)
Zusammenfassung der Ergebnisse
|
Alle mechanischen Aktionen benötigen Zeit. Dies muss bei der Entwicklung der Ansteuerung berücksichtigt werden.
|
Vorbereiten des Laptops
|
client 14: 'Midi Through' [type=Kernel] 0 'Midi Through Port-0' client 28: 'Virtual Raw MIDI 3-0' [type=Kernel,card=3] 0 'VirMIDI 3-0 ' client 29: 'Virtual Raw MIDI 3-1' [type=Kernel,card=3] zukünftig Senden an das Klavier 0 'VirMIDI 3-1 ' client 30: 'Virtual Raw MIDI 3-2' [type=Kernel,card=3] zukünftig Empfangen von Klavier 0 'VirMIDI 3-2 ' client 31: 'Virtual Raw MIDI 3-3' [type=Kernel,card=3] zukünftig TWISTER 0 'VirMIDI 3-3 ' client 32: 'USB MIDI Interface' [type=Kernel,card=4] 0 'USB MIDI Interface MIDI 1' client 36: 'Midi Fighter Twister' [type=Kernel,card=5] 0 'Midi Fighter Twister MIDI 1'
Code 0-1: Ausgabe von aconnect-o
Bild 0-1: Aufbau Laptop-seitig.
|
Versuch #1 -- Vom Laptop repetitiv einen Ton an das Klavier senden
Einfacher Funktionstest zur Überprüfung der Datenleitungen.
|
import themidibus.*; //contributed library themidibus needed! MidiBus[] bus; public void setup() { bus = new MidiBus[4]; bus[0] = new MidiBus(this, -1, "VirMIDI [hw:3,0,0]"); //später ev. Moddart Klavier U1 bus[1] = new MidiBus(this, "VirMIDI [hw:3,1,0]", -1); //VOM Disklavier empfangen bus[2] = new MidiBus(this, -1, "VirMIDI [hw:3,2,0]"); //AN das DISKLAVIER senden bus[3] = new MidiBus(this, "VirMIDI [hw:3,3,0]", "VirMIDI [hw:3,3,0]"); //MIDITWISTER frameRate(1); } int index=0; public void draw() { int u = index%2; if(PLAYING) { if(index%2==0) { //Kanal Höhe Lautstärke bus[2].sendNoteOn(0,60,40); } else { bus[2].sendNoteOff(0,60,40); } } index++; } void noteOn(int channel, int pitch, int velocity) { // Receive a noteOn println(); println("Note On:"); println("--------"); println("Channel:"+channel); println("Pitch:"+pitch); println("Velocity:"+velocity); } void noteOff(int channel, int pitch, int velocity) { // Receive a noteOff println(); println("Note Off:"); println("--------"); println("Channel:"+channel); println("Pitch:"+pitch); println("Velocity:"+velocity); } void controllerChange(int channel, int number, int value) { // Receive a controllerChange println(); println("Controller Change:"); println("--------"); println("Channel:"+channel); println("Number:"+number); println("Value:"+value); }
Code 0-2: Quelltext des Processing-Sketches Disklavier001
Versuch #2 -- Disklavier spielt vermindertes Arpeggio über einem angeschlagenen Ton
Bild 0-2: Disklavier spielt Arpeggien über einem einzelnen angeschlagenen Ton.
import themidibus.*; //contributed library themidibus needed! import processchains.simple.SimplePiano; boolean PLAYING = false; SimplePiano piano; MidiBus[] bus; /* .. am Twister muss Start- und Endlautstärke eingestellt werden. */ int LAUT1 = 0; int LAUT2 = 0; int[] laut = new int[19]; public void setup() { piano = new SimplePiano(this); // piano sound bus = new MidiBus[4]; bus[0] = new MidiBus(this, -1, "VirMIDI [hw:3,0,0]"); //Moddart Klavier U1 bus[1] = new MidiBus(this, "VirMIDI [hw:3,1,0]", -1); //VOM Disklavier empfangen bus[2] = new MidiBus(this, -1, "VirMIDI [hw:3,2,0]"); //AN das DISKLAVIER senden bus[3] = new MidiBus(this, "VirMIDI [hw:3,3,0]", "VirMIDI [hw:3,3,0]"); //MIDITWISTER size(200,200); frameRate(20); } int index=0; int GRUNDTON = 48; int GRUNDTON_NEU = 48; public void draw() { background(0); text(LAUT1+" "+LAUT2,20,20); int u = index%20; if(PLAYING) { if(u==19) { for(int m=1;m<20;m++) { int midi = GRUNDTON+m*3; bus[2].sendNoteOff(0,midi,laut[m-1]); } PLAYING=false; } else { int laute = LAUT1 + (int)((float)(LAUT2 - LAUT1)/(float)19.0f); laut[u]=laute; int midi = GRUNDTON+u*3; bus[2].sendNoteOn(0,midi,laute); } } index++; } public void keyPressed() { if(key==' ') { PLAYING=false; for(int m=21;m<=108;m++) bus[2].sendNoteOff(0,m,80); } else if(key=='r') { for(int m=21;m<=108;m++) bus[2].sendNoteOff(0,m,80); index=0; PLAYING=true; } } void noteOn(int channel, int pitch, int velocity) { // Receive a noteOn println(); println("Note On:"); println("--------"); println("Channel:"+channel); println("Pitch:"+pitch); println("Velocity:"+velocity); //piano.play(pitch); GRUNDTON=pitch; index=0; PLAYING=true; //GRUNDTON_NEU = GRUNDTON; //weg, wenn erst komplett sein soll. } void noteOff(int channel, int pitch, int velocity) { // Receive a noteOff println(); println("Note Off:"); println("--------"); println("Channel:"+channel); println("Pitch:"+pitch); println("Velocity:"+velocity); } void controllerChange(int channel, int number, int value) { // Receive a controllerChange println(); println("Controller Change:"); println("--------"); println("Channel:"+channel); println("Number:"+number); println("Value:"+value); if(channel==0 && number==0) LAUT1 = value; if(channel==0 && number==1) LAUT2 = value; }
Code 0-3: Disklavier002
Versuch #3 -- Sext-Akkord-Parallelbewegungen
Sketch: Disklavier003.zipYoutube-Video Sext-Akkord-Parallelbewegungen
Bild 0-3: Sext-Akkord-Parallelbewegungen
Versuch #4 -- Pedale
Sketch Disklavier004_PEDALE.zipSustain-Pedal in Kombination mit verschiedenen Anschlagstärken
|
Nachfolgend wird das Softpedal verwendet. Wenn die Hämmer nahe an die Saiten gebracht werden, wird der Klang weicher.
Versuch #5 -- Anschlag
Sketch Disklavier005_Anschlag.zipBei diesem Versuch wird untersucht, bis zu welcher Anaschlagstärke ein Ton noch anspricht. Dabei kommt heraus, dass bei genügend langsamem Tempo auch die allerleisesten durchkommen. Das Problem ist nicht das Ansprechen, sondern wie lange es bei einem leisen Ton dauert, ihn anzuspielen:
Versuch #6 -- Aufzeichnen
Nachfolgend wurde aufgezeichnet und in vierfachem Tempo abgespielt:
Interessanter Effekt: Bei einer sehr schnellen Tonrepetition mit schwachem Anschlag, erklingt nur sporadisch ein Ton:
|
public class Disklavier implements Runnable { // 0 1 2 3 4 ArrayList<int[]> rec = new ArrayList<int[]>(); // t-Tsrat, 1=on 0=off, midi, laute Durchgang int DAUER_MILLIS=0; int[][] arr; int durchgang = 0; int TEILUNG=4; long Tstart = 0; //Zeit beim ersten angeschlagenen Ton int INDEX = 0; MidiBus[] bus; int MODE = 0; int MODEalt = 0; int[] onetime = new int[100]; long tickmillis = 1000; public Disklavier() { initMidi(); (new Thread(this)).start(); } public void init() { INDEX = 0; allNotesOff(); rec.clear(); } public void setMode(int MODE) { this.MODE = MODE; } public void allNotesOff() { for(int m=21;m<=108;m++) { bus[2].sendNoteOff(0,m,40); } } public void initMidi() { bus = new MidiBus[4]; bus[0] = new MidiBus(this, -1, "VirMIDI [hw:3,0,0]"); //Moddart Klavier U1 bus[1] = new MidiBus(this, "VirMIDI [hw:3,1,0]", -1); //VOM Disklavier empfangen bus[2] = new MidiBus(this, -1, "VirMIDI [hw:3,2,0]"); //AN das DISKLAVIER senden bus[3] = new MidiBus(this, "VirMIDI [hw:3,3,0]", "VirMIDI [hw:3,3,0]"); //MIDITWISTER } public void setTickMillis(int tickmillis) { this.tickmillis = (long)tickmillis; } int[] diaton = {0,2,4,5,7,9,11}; public void selbsttest() { if(tickmillis!=500) setTickMillis(500); int inx = INDEX%15; int okt = inx/diaton.length; int dia = diaton[inx%diaton.length]; int mid = okt*12 + dia + 60; if(INDEX%2==0) { bus[2].sendNoteOff(0,mid,70); bus[2].sendNoteOn(0,mid,70); } else { bus[2].sendNoteOff(0,mid,1); bus[2].sendNoteOn(0,mid,1); } } public void run() { long t = System.currentTimeMillis(); while(true) { if(MODE!=MODEalt) { MODEalt = MODE; zeros(onetime); } switch(MODE) { case 0: if(onetime[0]==0) { init(); onetime[0]=1; } break; case 1: //Selbsttest if(onetime[1]==0) { setTickMillis(500); onetime[1]=1; } selbsttest(); break; case 2: //siehe noteOn break; case 3: abspielen(); break; } if(MODE!=3) { while(System.currentTimeMillis()<t+tickmillis); t = System.currentTimeMillis(); INDEX++; } } } public void abspielen() { int t = (int)(System.currentTimeMillis() - Tstart); int tz = t%DAUER_MILLIS; int durchgang = t/DAUER_MILLIS; for(int i=0;i<arr.length;i++) { if(arr[i][0]<tz && arr[i][4]<=durchgang && arr[i][2]>=21 && arr[i][2]<=108) { if(arr[i][1]==1) bus[2].sendNoteOn(0,arr[i][2],arr[i][3]); else if(arr[i][1]==0) bus[2].sendNoteOff(0,arr[i][2],arr[i][3]); arr[i][4]++; } } } void noteOn(int channel, int pitch, int velocity) { // Receive a noteOn println(); println("Note On:"); println("--------"); println("Channel:"+channel); println("Pitch:"+pitch); println("Velocity:"+velocity); //GRUNDTON_NEU = GRUNDTON; //weg, wenn erst komplett sein soll. if(MODE==2) { if(rec.size()==0) { Tstart = System.currentTimeMillis(); } rec.add(new int[] {(int)(System.currentTimeMillis()-Tstart)/TEILUNG, // t-tStart 1, // 1==on 0==off pitch, velocity, 0 //Zähler für später }); } } void noteOff(int channel, int pitch, int velocity) { // Receive a noteOff println(); println("Note Off:"); println("--------"); println("Channel:"+channel); println("Pitch:"+pitch); println("Velocity:"+velocity); if(MODE==2) { if(rec.size()==0) Tstart = System.currentTimeMillis(); rec.add(new int[] {(int)(System.currentTimeMillis()-Tstart)/TEILUNG, // t-tStart 0, // 1==on 0==off pitch, velocity, 0 //Zähler für später! }); } } void controllerChange(int channel, int number, int value) { // Receive a controllerChange println(); println("Controller Change:"); println("--------"); println("Channel:"+channel); println("Number:"+number); println("Value:"+value); if(MODE==2 && rec.size()>0 && number==67) //Linkes Pedal (Dämpfung) zum Starten des Abspielens { rec.add(new int[] {(int)(System.currentTimeMillis()-Tstart)/TEILUNG, // t-tStart 0, // 1==on 0==off 0, 0, 0 //Zähler für später! }); DAUER_MILLIS = rec.get(rec.size()-1)[0] - rec.get(0)[0]; Tstart = System.currentTimeMillis(); //neue Bedeutung: Startzeit beim zyklischen Abspielen arr = new int[rec.size()][]; for(int i=0;i<arr.length;i++) arr[i] = rec.get(i); durchgang = 0; MODE=3; } } }
Code 0-4: Klasse Disklavier