001import processing.core.*; 
002import processing.data.*; 
003import processing.event.*; 
004import processing.opengl.*; 
005
006import java.util.Random; 
007import java.util.concurrent.Executors; 
008import java.util.concurrent.ScheduledExecutorService; 
009import java.util.concurrent.TimeUnit; 
010import java.util.concurrent.Executors; 
011import java.util.concurrent.ScheduledExecutorService; 
012import java.util.concurrent.TimeUnit; 
013import javax.sound.sampled.*; 
014import java.nio.ByteBuffer; 
015import processing.core.*; 
016import java.io.*; 
017
018import java.util.HashMap; 
019import java.util.ArrayList; 
020import java.io.File; 
021import java.io.BufferedReader; 
022import java.io.PrintWriter; 
023import java.io.InputStream; 
024import java.io.OutputStream; 
025import java.io.IOException; 
026
027public class MODULO_1003_STEREO extends PApplet {
028
029 /**
030 *  <h4>MODULO_1003_STEREO</h4>
031 *  <br/>
032 *  Copyright (C) 2019 Guido Kramann<br/>
033 *  kramann@th-brandenburg.de<br/>
034 *  http://www.kramann.info<br/>
035 *  <br/>
036 *  <p>  
037 *  This program is free software: you can redistribute it and/or modify
038 *  it under the terms of the GNU General Public License as published by
039 *  the Free Software Foundation, either version 3 of the License, or
040 *  (at your option) any later version.
041 *
042 *  </p>
043 *  <p>
044 *  This program is distributed in the hope that it will be useful,
045 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
046 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
047 *  GNU General Public License for more details.
048 *  </p>
049 *  <p>
050 *  You should have received a copy of the GNU General Public License
051 *  along with this program (gpl.html).  If not, see http://www.gnu.org/licenses/.
052 *  </p>
053 */
054
055Spieler spieler_schwarz,spieler_weiss;
056
057Rekorder rekorder = new Rekorder(86,1525);
058//Rekorder rekorder = new Rekorder(86,286);
059boolean RECORDING = false;
060
061boolean WARTUNG = false;
062
063//009: rhythmisierte Fassung:
064//Die Dauer eines Zuges wird festgelegt.
065//Der Wechsel erfolgt immer nach einer Periode, wenn gezogen wurde.
066//Wurde nicht gezogen, werden Strafpunkte abgezogen und erst wieder wenn eine weitere Periode voll ist gewechselt.
067long PULSMILLIS = 200;  //... so viele Millisekunden dauert Pulse
068long PULSEPROZUG = 12;  //... so viele Pulse dauert ein Zug (und auch eine gespielte Phrase)
069int STRAFPUNKTE = 50;
070
071
072
073//FEHLER: Das Entfernen von Steinen wird nicht richtig behandelt!!!!
074
075//Punkte: werden aktualisiert, wenn die Pfade aktualisiert werden!
076int PUNKTE_WEISS = 0;
077int PUNKTE_SCHWARZ = 0;
078
079//rot wenn schwarz dran ist,
080//gr\u00fcn wenn weiss dran ist
081
082//nur gerade Bewegungen auf Feld erlaubt
083//nur eigene Farbe darf bewegt werden, wenn man dran ist
084
085int[] ROT = {255,100,100};
086int[] GRUEN = {100,255,100};
087
088ArrayList<int[]> schwarzerpfad = null;
089ArrayList<int[]> weisserpfad = null;
090
091
092float LINIENDICKE;
093
094String[] kartentypen;
095Karte[] karte;
096Karte quelleweiss;
097Karte quelleschwarz;
098float kantex;
099float kantey;
100Spielfeld spielfeld;
101Spiel spiel;
102Spiel testspiel;  //Derzeit nur zum laden und speichern von Spielzust\u00e4nden
103Spiel testspiel2;  //Zwischenspeichern
104
105Zugkontrolle zugkontrolle;
106
107Karte dragged = null;
108int FELDBREITE = 101;
109int RANDBREITE = (6 + 3)*2;
110
111
112Mysoundplayer msp;
113Wav wav;
114
115public void setup()
116{
117   int[] MIDI = {33,35,37,38,40,42,44,  47,49,  52,54,56,  59,61,63,  66,68,  71,  75,  80,  87};  //Anzahl=21
118   //Sound
119   println("midi min = "+freq2mid(55));
120   println("midi max = "+freq2mid(1760));
121   
122//     msp = new Mysoundplayer(this,2);
123     msp = new Mysoundplayer(this,4);  //Jetzt 4 Kan\u00e4le
124     int midimin = 33;
125//     int midimax = 93;
126     int midimax = 87;
127     int[] skala = new int[midimax-midimin+1];
128     for(int i=midimin;i<=midimax;i++)
129         skala[i-midimin] = i;
130     float laute1 = 0.1f;
131     float laute2 = 0.2f;
132     float pan   = 0.5f;
133//     msp.ladeKanal(0, "/home/fhbstud/system/samples/89_marimbaneu/normal",skala,laute,pan-0.1);       
134//     msp.ladeKanal(0, "/home/fhbstud/system/samples/06_klavier_yamaha_c7/up106",MIDI,laute,pan-0.1);
135//     msp.ladeKanal(0, "data/t35",skala,laute,pan-0.1);
136     msp.ladeKanalStereo(0, "data/t35",MIDI,laute1,pan-0.1f);
137     msp.ladeKanalStereo(1, "data/t36",MIDI,laute1,pan-0.1f);     
138
139//     msp.saveKanal(int kanal, String pfad, int[] midiskala)     
140//     msp.ladeKanal(0, "/home/fhbstud/system/samples/06_klavier_yamaha_c7/up106",skala,5.0,pan);
141//     msp.saveKanal(0, "data/t35", skala);     
142     
143//     msp.ladeKanal(1, "/home/fhbstud/system/samples/06_klavier_yamaha_c7/up98",MIDI,laute,pan+0.1);     
144     msp.ladeKanalStereo(2, "data/t21",MIDI,laute2,pan+0.1f);     
145     msp.ladeKanalStereo(3, "data/t22",MIDI,laute2,pan+0.1f);     
146
147//     msp.ladeKanal(1, "/home/fhbstud/system/samples/06_klavier_yamaha_c7/up98",skala,5.0,pan);     
148//     msp.saveKanal(1, "data/t36", skala);     
149
150
151//     msp.ladeKanal(0, "/home/fhbstud/system/samples/89_marimbaneu/normal",skala,laute,pan-0.1);       
152//     msp.ladeKanal(1, "/home/fhbstud/system/samples/89_marimbaneu/normal",skala,laute,pan+0.1);
153   // ladeMonostimmen(int[] skala, String[] ordner, String prefix)
154   
155//   msp.ladeMonostimmen(MIDI, new String[] {"a7","a8"}, "ton");
156//   msp.ladeMonostimmen(MIDI, new String[] {"a7","t35"}, new float[] {1.0,0.2}, "ton");
157   
158   //Ende Sound
159  
160    float TEILER = 9.0f;
161//    size(1280,720);
162//    size(1100,720);
163//    size(1100,640);
164    //size(640,640);
165    
166//    fullScreen();
167    orientation(LANDSCAPE);
168    
169    LINIENDICKE = height/300.0f;
170    strokeWeight(LINIENDICKE);
171    
172    float bsoll = 1280.0f;
173    float hsoll = 720.0f;
174    float bist  = width;
175    float hist  = height;
176    
177    if(hist/bist > hsoll/bsoll)
178    {
179         float faktor = (hsoll/bsoll) / (hist/bist);
180         
181         float bb = width;
182//         float kx = (5.0f/13.0f)*(height*faktor)/(float)TEILER;                   
183         float kx = (5.0f/13.0f)*(height)/(float)TEILER;                   
184         while((int)floor(bb/kx) < FELDBREITE+RANDBREITE)
185             FELDBREITE-=2;
186                  
187         scale(1.0f,faktor);
188    }
189    else if(hist/bist < hsoll/bsoll)
190    {
191         float faktor = (hsoll/bsoll) / (hist/bist);
192         
193//         float bb = width/faktor;
194         float bb = width;
195         float kx = (5.0f/13.0f)*height/(float)TEILER;                   
196         while((int)floor(bb/kx) < FELDBREITE+RANDBREITE)
197             FELDBREITE-=2;
198
199         scale(1.0f/faktor,1.0f);
200         
201    }
202    
203println(FELDBREITE);    
204    
205    strokeWeight(height*0.002f);
206
207    kantex = (5.0f/13.0f)*height/TEILER;
208    kantey = height/TEILER;
209    kartentypen = loadStrings("kartentypen.txt");
210    frameRate(30);
211//    spielfeld = new Spielfeld(kantex,kantey,21,9);
212    spielfeld = new Spielfeld(kantex,kantey,FELDBREITE,9);
213    karte = new Karte[9*6*2];
214    for(int i=0;i<karte.length/2;i++)
215    {
216       float x = (i/9)*kantex;
217       float y = (i%9)*kantey;
218       karte[i] = new Karte(true,i%9,1+i/9,x,y,(5.0f/13.0f)*height/TEILER,height/TEILER);
219    }
220    
221    quelleweiss = new Karte(true,9,0,kantex*7,kantey*4,(5.0f/13.0f)*height/TEILER,height/TEILER);
222    quelleschwarz = new Karte(false,9,7,width-kantex*7-kantex,kantey*4,(5.0f/13.0f)*height/TEILER,height/TEILER);
223    
224    for(int i=0;i<karte.length/2;i++)
225    {
226       float x = (i/9)*kantex;
227       float y = (i%9)*kantey;
228       karte[i+karte.length/2] = new Karte(false,i%9,1+i/9,width-x-kantex,height-y-kantey,(5.0f/13.0f)*height/TEILER,height/TEILER);
229    }        
230    
231    spiel = new Spiel(spielfeld,karte,quelleweiss,quelleschwarz);
232    testspiel = new Spiel(spielfeld,karte,quelleweiss,quelleschwarz);
233    testspiel2 = new Spiel(spielfeld,karte,quelleweiss,quelleschwarz);
234    
235    zugkontrolle = new Zugkontrolle(PULSMILLIS,PULSEPROZUG,spielfeld,STRAFPUNKTE);
236    
237    //Automatische Spieler starten:
238    spieler_weiss = new Spieler(true,spielfeld,spiel,testspiel,testspiel2);
239    spieler_schwarz = new Spieler(false,spielfeld,spiel,testspiel,testspiel2);
240}
241
242public void draw()
243{
244    strokeWeight(LINIENDICKE);
245    background(70,70,70);
246    
247    
248    spielfeld.draw();
249    for(int i=0;i<karte.length;i++)
250       karte[i].draw(null);
251
252
253    if(spielfeld.WEISS_IST_DRAN && spielfeld.TIMER_WEISS_IST_DRAN)
254        quelleweiss.draw(GRUEN); //Korona
255    else    
256        quelleweiss.draw(null); //Korona
257        
258        
259    if(!spielfeld.WEISS_IST_DRAN && !spielfeld.TIMER_WEISS_IST_DRAN)
260        quelleschwarz.draw(ROT);
261    else
262        quelleschwarz.draw(null);
263    
264    
265    //Pfade zeigen:  (siehe mouseReleased() ganz unten!!!!)
266    //  schwarzerpfad = spiel.findeNaechstenpfadWeiss();
267    //  weisserpfad = spiel.findeNaechstenpfadWeiss();
268    stroke(GRUEN[0],GRUEN[1],GRUEN[2]);
269    if(weisserpfad!=null && weisserpfad.size()>1)
270    {
271         ArrayList<int[]> pfad = weisserpfad;
272         for(int i=0;i<pfad.size()-1;i++)
273         {
274               int ii1 = pfad.get(i)[0];
275               int kk1 = pfad.get(i)[1];
276               int ii2 = pfad.get(i+1)[0];
277               int kk2 = pfad.get(i+1)[1];
278               float x1 = spielfeld.kkoord[ii1][kk1];
279               float y1 = spielfeld.ikoord[ii1][kk1];
280               float x2 = spielfeld.kkoord[ii2][kk2];
281               float y2 = spielfeld.ikoord[ii2][kk2];
282               line(x1,y1,x2,y2);
283         }
284    }
285    
286    stroke(ROT[0],ROT[1],ROT[2]);
287    if(schwarzerpfad!=null && schwarzerpfad.size()>1)
288    {
289         ArrayList<int[]> pfad = schwarzerpfad;
290         for(int i=0;i<pfad.size()-1;i++)
291         {
292               int ii1 = pfad.get(i)[0];
293               int kk1 = pfad.get(i)[1];
294               int ii2 = pfad.get(i+1)[0];
295               int kk2 = pfad.get(i+1)[1];
296               float x1 = spielfeld.kkoord[ii1][kk1]+LINIENDICKE*0.5f;
297               float y1 = spielfeld.ikoord[ii1][kk1]+LINIENDICKE*0.5f;
298               float x2 = spielfeld.kkoord[ii2][kk2]+LINIENDICKE*0.5f;
299               float y2 = spielfeld.ikoord[ii2][kk2]+LINIENDICKE*0.5f;
300               line(x1,y1,x2,y2);
301         }
302    }
303    
304    
305    if(dragged!=null)
306    {
307          dragged.set(mouseX,mouseY);
308          dragged.draw(null);
309    }      
310}
311
312public void mousePressed()
313{
314     if(dragged==null)
315     {
316          //ABBRUCH, wenn falsche Farbe!
317          for(int i=0;i<karte.length;i++)
318              if(karte[i].mausHatEs(mouseX,mouseY) && (spielfeld.WEISS_IST_DRAN==spiel.istWeiss(karte[i].ID) && spielfeld.WEISS_IST_DRAN==spielfeld.TIMER_WEISS_IST_DRAN))
319                  dragged = karte[i];
320          if(quelleweiss.mausHatEs(mouseX,mouseY) && (spielfeld.WEISS_IST_DRAN==true && spielfeld.TIMER_WEISS_IST_DRAN==true))        
321                  dragged = quelleweiss;
322          if(quelleschwarz.mausHatEs(mouseX,mouseY) && (spielfeld.WEISS_IST_DRAN==false && spielfeld.TIMER_WEISS_IST_DRAN==false))        
323                  dragged = quelleschwarz;
324                  
325                  
326          if(dragged!=null)
327              dragged.war_auf_feld = false;
328              
329          if(dragged!=null && spielfeld.istInSpielfeld(dragged))
330          {
331               int kk = spielfeld.getNextXindex(dragged);
332               int ii = spielfeld.getNextYindex(dragged);
333               
334               if(spielfeld.istFrei(ii,kk)==false)
335               {
336                   spielfeld.matrix[ii][kk] = null;
337                   dragged.war_auf_feld = true;
338               }
339          }
340     }
341}
342
343public void updateSpielzustand()
344{
345      //Nur bei erfolgreicher Aktion n\u00f6tig:      
346      //Anzeige der aktuellen Belegung:
347      //*********** Das hier m\u00fc\u00dfte auch bei automatischen Z\u00fcgen ausgef\u00fchrt werden: *******
348      spiel.uebernehmeZustand();
349      if(WARTUNG == true)      
350          spiel.zeigeTestweiseDieEigenschaftenAllerKartenImSpielfeld();
351      schwarzerpfad = spiel.findeNaechstenpfadSchwarz();
352      weisserpfad = spiel.findeNaechstenpfadWeiss();
353      //****************      
354      
355      //Punkte aktualisieren:
356      if(spielfeld.WEISS_IST_DRAN)
357          PUNKTE_WEISS += spiel.berechnePunkte(weisserpfad);
358      if(!spielfeld.WEISS_IST_DRAN)
359          PUNKTE_SCHWARZ += spiel.berechnePunkte(schwarzerpfad);
360
361     if(WARTUNG)     
362      println("W:"+PUNKTE_WEISS+" S:"+PUNKTE_SCHWARZ);    
363}
364
365public void mouseReleased()
366{
367      float mx = mouseX;
368      float my = mouseY;
369      if(dragged!=null)
370      {
371          if(spielfeld.istInSpielfeld(dragged)) //wenn Figur auf Spielfeld gezogen wurde
372          {
373               float xx = spielfeld.getNextX(dragged);
374               float yy = spielfeld.getNextY(dragged);
375               int kk = spielfeld.getNextXindex(dragged);
376               int ii = spielfeld.getNextYindex(dragged);
377               
378               if(spielfeld.istFrei(ii,kk)) //Wenn Zielplatz auf Spielfeld frei ist
379               {
380                   //ERFOLGREICHER ZUG!
381                   dragged.setNeu(xx,yy);
382                   spielfeld.matrix[ii][kk] = dragged;
383                   dragged.xspielfeld=xx;
384                   dragged.yspielfeld=yy;
385                   
386                   updateSpielzustand(); //Nur bei erfolgreichen Z\u00fcgen Updtae n\u00f6tig!
387                   
388                   //JETZT IST DER ANDERE DRAN!
389                   spielfeld.WEISS_IST_DRAN = !spielfeld.WEISS_IST_DRAN;
390               }
391               else
392               {
393                  if(dragged.war_auf_feld == true)
394                  {
395                   dragged.x = dragged.xspielfeld;
396                   dragged.y = dragged.yspielfeld;
397                   kk = spielfeld.getNextXindex(dragged);
398                   ii = spielfeld.getNextYindex(dragged);
399                   spielfeld.matrix[ii][kk] = dragged;
400                   
401                   
402                  }
403                  else    //wenn Figur zuvor selbst schon auf Spielfeld war, dann auf alten Platz dort zur\u00fcck setzen
404                  {
405                     dragged.setHome();                     
406                  }  
407               }
408               
409          }
410          else //Spielfigut weg von Spielfeld ziehen
411          {
412                   dragged.setHome();
413                     //Das ist auch ein erfolgreicher Zug, darum hier auch update und Wechsel!!!!:
414                     updateSpielzustand(); //Nur bei erfolgreichen Z\u00fcgen Updtae n\u00f6tig!
415                   
416                     //JETZT IST DER ANDERE DRAN!
417                     spielfeld.WEISS_IST_DRAN = !spielfeld.WEISS_IST_DRAN;
418            
419          }
420          
421          dragged = null;
422      }
423
424      //Nur bei erfolgreicher Aktion n\u00f6tig (s. updateSpielzustand und erfolgreicher Zug!):      
425      //Anzeige der aktuellen Belegung:
426      //*********** Das hier m\u00fc\u00dfte auch bei automatischen Z\u00fcgen ausgef\u00fchrt werden: *******
427      //spiel.uebernehmeZustand();
428      //spiel.zeigeTestweiseDieEigenschaftenAllerKartenImSpielfeld();
429      //schwarzerpfad = spiel.findeNaechstenpfadSchwarz();
430      //weisserpfad = spiel.findeNaechstenpfadWeiss();
431      //****************      
432}
433
434public void keyPressed()
435{
436     if(key=='r')
437     {
438          spiel.alleHeimschicken(); //Testweise Zustand auf Start setzen
439          spiel.zeigeTestweiseDieEigenschaftenAllerKartenImSpielfeld();
440     }
441     else if(key=='s')  //Zustand in testspiel speichern
442     {
443          testspiel.uebernehmeZustand();
444          println("Spielzustand in Testspiel gemerkt");
445     }
446     else if(key=='l')  //Zustand VON testspiel LADEN
447     {
448          testspiel.schreibeZustand();
449          println("Spielzustand von Testspiel geholt");          
450     }
451     else if(key==' ')
452     {
453          if(RECORDING==false)
454          {
455              RECORDING = true;
456              println("\n\nAUFNAHME START\n");
457          }    
458          else
459          {
460              RECORDING = false;
461              rekorder.save("stueck_"+System.currentTimeMillis()+".txt");   
462              println("\n\nAUFNAHME ENDE\n");
463          }
464     }
465     
466     
467     
468}
469  public double midi2Frequency(double midi)
470  {
471        if(midi<1.0f)
472            return 0.0f; //Nullereignisse behandeln
473  
474        double freq69 = Math.pow(2.0f,69.0f/12.0f);
475        return Math.pow(2.0f,midi/12.0f)*440.0f/freq69;
476  }
477
478  public double frequency2Midi(double freq)
479  {
480        if(freq<1.0f)
481             return 0.0f; //Nullereignisse behandeln
482  
483        double freq69 = Math.pow(2.0f,69.0f/12.0f);
484        return 12.0f*Math.log(freq*freq69/440.0f)/Math.log(2.0f);
485  }
486
487  public int freq2mid(int freq)
488  {
489    if(freq==0)
490        return 0;
491    else
492        return (int)Math.round(frequency2Midi((double)freq));
493  }
494
495  public int mid2freq(int mid)
496  {
497      if(mid==0)
498          return 0;
499      else
500          return (int)Math.round(midi2Frequency((double)mid));
501  }
502 
503public class Karte
504{
505     public boolean war_auf_feld = false;
506  
507     int typ;
508     String[] pattern;
509     float kantex; 
510     float kantey;
511     public float h,b,x,y,xhome,yhome,xoff,yoff,xspielfeld,yspielfeld;
512     int farbe;
513     boolean WEISS;
514     
515     public int ID=0;
516     
517     //typ 9 ist Quelle, 0..8== .|..|...|-|--|---|+|++|+++
518     //                         0  1  2  3  4   5 6  7  8
519     public Karte(boolean WEISS,int typ,int farbe,float x, float y, float b, float h)
520     {
521          ID = 99000 + typ*100 + farbe*10;
522          if(WEISS)
523            ID++;
524       
525       
526          this.xoff = 0.0f;
527          this.yoff = 0.0f;
528          this.xspielfeld = 0.0f;
529          this.yspielfeld = 0.0f;
530       
531          this.WEISS = WEISS;
532          this.farbe = farbe;
533          this.typ = typ;
534          pattern = new String[13];
535          for(int i=0;i<pattern.length;i++)
536          {
537               pattern[i] = kartentypen[typ*20+i];
538          }
539          kantex = b/5.0f;
540          kantey = h/13.0f;
541          this.h = h;
542          this.b = b;
543          this.x = x;
544          this.y = y;
545          this.xhome = x;
546          this.yhome = y;
547     }
548     
549     public void draw(int[] randfarbe)
550     { 
551         if(randfarbe==null)
552            noStroke();
553         else
554            stroke(randfarbe[0],randfarbe[1],randfarbe[2]);
555         int r = ((7-farbe)/4)%2;
556         int g = ((7-farbe)/2)%2;
557         int b = ((7-farbe)/1)%2;
558         //&&&&
559         if(WEISS)
560         {
561             fill(127+64);
562         }    
563         else
564         {
565             fill(0);
566         }    
567         rect(x,y,this.b,this.h,60);
568         //&&&&
569         if(WEISS)
570         {
571             fill(r*127,g*127,b*127);
572             stroke(r*127,g*127,b*127);
573         }    
574         else
575         {
576             fill(r*127+64,g*127+64,b*127+64);
577             stroke(r*127+64,g*127+64,b*127+64);
578         }    
579         for(int i=0;i<pattern.length;i++)
580         {
581              for(int k=0;k<pattern[i].length();k++)
582              {
583                   if(pattern[i].charAt(k)=='*')
584                      rect(x+kantex*(k+1),y+kantey*(i-1),kantex,kantey,3);
585              }
586         }
587     }
588     
589     public boolean mausHatEs(float mx, float my)
590     {
591          if(mx>x && my>y && mx<x+b && my<y+h)
592          {
593              xoff = x-mx;
594              yoff = y-my;
595            
596              return true;
597          }    
598          else
599              return false;
600     }
601     
602     public void set(float mx, float my)
603     {
604          x = mx+xoff;
605          y = my+yoff;
606     }
607     public void setNeu(float mx, float my)
608     {
609          x = mx;
610          y = my;
611          xoff=0.0f;
612          yoff=0.0f;
613     }
614     
615     public void setHome()
616     {
617          this.x = xhome;
618          this.y = yhome;
619          xoff=0.0f;
620          yoff=0.0f;
621     }
622}
623//Spiel repr\u00e4sentiert den Spielstand / den Spielzustand
624//Mit einer Instanz testspiel, k\u00f6nnen auch nicht aktuelle Spielzust\u00e4nde \u00fcberpr\u00fcft werden (2. Instanz von spiel)
625
626public class Spiel
627{
628    //Nur die NEUEN Punkte, nicht die aku,ulierten.
629    //Die akumulierten stehen im Haupt-Sketch
630    //werden beim Bestimmen der Pfade mit aktualisiert!
631  
632  
633    //Die Parameter werden aus den \u00fcbergerbenen Objekten extrahiert und
634    //die \u00fcbergebenen Parameter hier registriert
635    Spielfeld spielfeld;
636    Karte[] karte;
637    Karte quelleweiss;
638    Karte quelleschwarz;
639    
640    public int[][] matrix;
641    public int[][] distmatrix;
642
643    public void kopiereAufAnderesSpiel(Spiel testspiel)
644    {
645         for(int i=0;i<matrix.length;i++)
646             for(int k=0;k<matrix[i].length;k++)
647                 testspiel.matrix[i][k] = matrix[i][k];
648         for(int i=0;i<matrix.length;i++)
649             for(int k=0;k<matrix[i].length;k++)
650                 testspiel.distmatrix[i][k] = distmatrix[i][k];
651    }
652    
653    public Spiel(Spielfeld spielfeld,Karte[] karte,Karte quelleweiss,Karte quelleschwarz)
654    {
655         this.spielfeld = spielfeld;
656         this.karte = karte;
657         this.quelleweiss = quelleweiss;
658         this.quelleschwarz = quelleschwarz;
659         
660         this.matrix = new int[spielfeld.matrix.length][spielfeld.matrix[0].length];
661         this.distmatrix = new int[spielfeld.matrix.length][spielfeld.matrix[0].length];
662    }
663    
664    public void uebernehmeZustand()
665    {
666         Karte[][] mat = spielfeld.matrix;
667         
668         for(int i=0;i<matrix.length;i++)
669             for(int k=0;k<matrix[i].length;k++)
670                 if(mat[i][k]!=null)
671                     matrix[i][k] = mat[i][k].ID;
672                 else    
673                     matrix[i][k] = 0;
674    }
675    
676    public void schreibeZustand() //in matrix gespeicherten Zustand auf das Spiel \u00fcbertragen!, praktisch f\u00fcr autom. Spiel!!!!
677    {
678        //1. Alle "heimschicken"
679        alleHeimschicken();
680        //2. aus matrix die IDs lesen und dort die Karten in Spielfeld positionieren.
681        for(int i=0;i<matrix.length;i++)
682        {
683            for(int k=0;k<matrix[i].length;k++)
684            {
685                float xxx = spielfeld.getNextXausK(k);
686                float yyy = spielfeld.getNextYausI(i);
687                int ID = matrix[i][k];
688                if(ID>0)
689                {
690                    if(quelleweiss.ID==ID)
691                    {
692                          spielfeld.matrix[i][k] = quelleweiss;
693                          quelleweiss.setNeu(xxx,yyy);
694                    }
695                    else if(quelleschwarz.ID==ID)
696                    {
697                          spielfeld.matrix[i][k] = quelleschwarz;
698                          quelleschwarz.setNeu(xxx,yyy);
699                    }
700                    else
701                    {
702                          for(int pp=0;pp<karte.length;pp++)
703                          {
704                               if(karte[pp].ID==ID)
705                               {
706                                   spielfeld.matrix[i][k] = karte[pp];
707                                   karte[pp].setNeu(xxx,yyy);
708                                   break;
709                               }
710                          }
711                    }
712                }    
713            }
714        }
715    }
716    
717    public void alleHeimschicken()
718    {
719        for(int i=0;i<karte.length;i++)
720            karte[i].setHome();
721        quelleweiss.setHome();
722        quelleschwarz.setHome();
723        for(int i=0;i<spielfeld.matrix.length;i++)
724            for(int k=0;k<spielfeld.matrix[0].length;k++)
725            spielfeld.matrix[i][k]=null;
726    }
727    
728    //Methoden zur Analyse der ID:
729    public boolean istWeiss(int ID)
730    {
731         if(ID%2==1)
732            return true;
733         else
734            return false;
735    }
736    
737    public int farbeVonID(int ID)
738    {
739         return (ID/10)%10;
740    }
741    
742    public int anzahlVonID(int ID)
743    {
744         return ((ID/100)%10)%3;
745    }
746    
747    public int formVonID(int ID)
748    {
749         return ((ID/100)%10)/3;
750    }
751    
752    public boolean istQuelle(int ID)
753    {
754         if( (ID/100)%10==9 )
755           return true;
756         else
757           return false;
758    }
759
760    public boolean istAufSpielfeld(int ID)
761    {
762          for(int i=0;i<matrix.length;i++)
763                for(int k=0;k<matrix[i].length;k++)
764                    if(ID==matrix[i][k])
765                        return true;
766          return false;              
767    }
768    
769    public void zeigeTestweiseDieEigenschaftenAllerKartenImSpielfeld()
770    {
771         println("//Angaben:"); 
772         println("[zeile|spalte]"); 
773         println("// S/W schwarz weiss");
774         println("// QQQ   Quelle");
775         println("// Farbe  1..6");
776         println("// Anzahl 1..3");
777         println("// Form   1..3");
778         for(int i=0;i<matrix.length;i++)
779         {
780               for(int k=0;k<matrix[i].length;k++)
781               {
782                 if(matrix[i][k]>0)
783                 {
784                   print("["+i+"|"+k+"] ");
785                   int ID = matrix[i][k];
786                   if(istWeiss(ID))
787                      print("W ");
788                   else   
789                      print("S ");
790                   if(istQuelle(ID))
791                   {
792                        print("QQQ");
793                   }
794                   else
795                   {
796                       int farbe = farbeVonID(ID);      //OHNE INKR schon richtig!!!
797                       int anzahl = anzahlVonID(ID)+1;  //PLUS 1 !!!
798                       int form   = formVonID(ID)+1;    //PLUS 1 !!!
799                       print(farbe+""+anzahl+""+form+"");
800                   }
801                   print(" # ");
802                 }
803                 else
804                 {
805                     print("["+i+"|"+k+"] ");
806                     print("     ");
807                     print(" # ");
808                 }
809               }
810               println();
811         }
812         println();
813    }
814    
815    
816    //Methoden bereitstellen, die es erlauben die G\u00fcltigkeit von Konstellationen zu untersuchen
817    //um schlie\u00dflich g\u00fcltige Z\u00fcge zu suchen und zu bewerten.
818    
819    //Verboten sind Zyklen.
820    //Wie erkennt man Zyklen?
821    //Es d\u00fcrfen keine Rechtecke auftreten! Reicht das???
822    
823    //Wenn man Kreuzungen verbietet reicht das.
824    //Aber wenn nicht g\u00e4be es z.B. 8-ten als M\u00f6glichkeit von Schleifen, die keine Rechtecke sind.
825    
826    //OBIGES VERWERFEN!!!
827    
828    //Statt dessen N\u00e4chstenpfad OHNE Zyklen/Wdh. bilden.
829    //So braucht es sonst keine Beschr\u00e4nkungen!!!!
830    
831    
832    public ArrayList<int[]> findeNaechstenpfadWeiss()
833    {
834        return findeNaechstenpfad(true);
835    }
836    
837    public ArrayList<int[]> findeNaechstenpfadSchwarz()
838    {
839        return findeNaechstenpfad(false);
840    }
841
842    //Nur die NEUEN Punkte, nicht die aku,ulierten.
843    //Die akumulierten stehen im Haupt-Sketch
844    //werden beim Bestimmen der Pfade mit aktualisiert!
845    
846    //Formel:  Anzahl_versch_farben * Anzahl_versch_formen * Anzahl_versch_Anzahlen * ANZAHLWEGSTATIONEN_OHNE_QUELLE
847    
848    public int berechnePunkte(ArrayList<int[]> sammel_ik)
849    {
850        if(sammel_ik==null || sammel_ik.size()<=1)
851            return 0; //Quelle z\u00e4hlt nicht mit!!!
852        int[][] merker = new int[4][matrix[0].length];  //Zeilen: Farbe, Form, Anzahl,distanzen || Spalten werden inkrementiert, wenn korrespondierende Farbe/Form/Anzahl auftaucht.
853        for(int i=0;i<sammel_ik.size();i++)
854        {
855            int ID = matrix[sammel_ik.get(i)[0]][sammel_ik.get(i)[1]];
856            if(ID>0 && !istQuelle(ID))
857            {
858                  int farbe = farbeVonID(ID);
859                  int form =  formVonID(ID);
860                  int anz  =  anzahlVonID(ID);
861                  int distanz = sammel_ik.get(i)[2];
862                  merker[0][farbe]++;
863                  merker[1][form]++;
864                  merker[2][anz]++;
865                  merker[3][distanz]++;
866            }
867        }
868        
869        int PUNKTE = sammel_ik.size()-1;
870        
871        for(int i=0;i<merker.length;i++)
872        {
873              int summe = 0;
874              for(int k=0;k<merker[i].length;k++)
875              {
876                   if(merker[i][k]>0)
877                      summe++;
878              }
879              PUNKTE*=summe;
880        }
881        return PUNKTE;
882    }
883
884    public boolean warschon(int i,int k,ArrayList<int[]> sammel_ik)
885    {
886        for(int p=0;p<sammel_ik.size();p++)
887             if(i==sammel_ik.get(p)[0] && k==sammel_ik.get(p)[1])
888                 return true;
889        return false;          
890    }
891    
892    public ArrayList<int[]> findeNaechstenpfad(boolean weiss)
893    {
894//if(weiss)      
895//println("Suche weiss");
896//else
897//println("Suche schwarz");
898
899
900        ArrayList<int[]> sammel_ik = new ArrayList<int[]>();
901        
902        //1. Startpunkt suchen:
903        println();
904        for(int i=0;i<matrix.length;i++)
905        {
906              for(int k=0;k<matrix[i].length;k++)
907              {
908                       
909                    int ID = matrix[i][k];
910                    if(WARTUNG)
911                    {
912                      if(ID==0)
913                        print(0);
914                      else if(istQuelle(ID) && istWeiss(ID))
915                        print("W");
916                      else if(istQuelle(ID) && !istWeiss(ID))
917                        print("S");
918                      else
919                        print("x");
920                    }    
921                    if(weiss)
922                    {
923                        if(ID>0 && istQuelle(ID) && istWeiss(ID))
924                        {
925                          sammel_ik.add(new int[] {i,k});
926                        }
927                    }
928                    else
929                    {                                              
930                        if(ID>0 && istQuelle(ID) && !istWeiss(ID))
931                        {
932                          sammel_ik.add(new int[] {i,k});
933                        }
934                    }
935              }
936              if(WARTUNG)
937              println();
938        }
939if(WARTUNG)        
940println("Quellanz="+sammel_ik.size());        
941        //2. Immer die k\u00fcrzeste Verbindung suchen.
942        while(sammel_ik.size()>0) //Abbruch, wenn kein neuer gefunden wird.
943        {
944            int i_start = sammel_ik.get(sammel_ik.size()-1)[0];
945            int k_start = sammel_ik.get(sammel_ik.size()-1)[1];
946            
947            int[][] merker = new int[4][4]; // i k ID dist, wenn ID 0 == nix gefunden
948            for(int p=k_start+1;p<matrix[0].length;p++)
949            {
950                 int ID = matrix[i_start][p]; 
951                 if(istQuelle(ID))
952                     break;  //andere Quelle blockiert weitergehen! 
953                 if(ID>0 && !istQuelle(ID)  && !warschon(i_start,p,sammel_ik)) //solche, die schon waren \u00fcbergehen!
954                 {
955                      merker[0][0] = i_start;
956                      merker[0][1] = p;
957                      merker[0][2] = matrix[i_start][p]; //ID
958                      merker[0][3] = p - k_start; //dist (>0)
959                      break;
960                 }
961                 else if(warschon(i_start,p,sammel_ik)) //auch abbrechen, wenn einer im Weg ist, der schon war!
962                 {
963                      break;
964                 }
965            }
966            //3 weitere...
967            for(int p=k_start-1;p>=0;p--)
968            {
969                 int ID = matrix[i_start][p]; 
970                 if(istQuelle(ID))
971                     break;  //andere Quelle blockiert weitergehen! 
972                 if(ID>0 && !istQuelle(ID)  && !warschon(i_start,p,sammel_ik)) //solche, die schon waren \u00fcbergehen!
973                 {
974                      merker[1][0] = i_start;
975                      merker[1][1] = p;
976                      merker[1][2] = matrix[i_start][p]; //ID
977                      merker[1][3] = k_start - p; //dist (>0)
978                      break;
979                 }
980                 else if(warschon(i_start,p,sammel_ik)) //auch abbrechen, wenn einer im Weg ist, der schon war!
981                 {
982                      break;
983                 }
984            }
985            for(int p=i_start+1;p<matrix.length;p++)
986            {
987                 int ID = matrix[p][k_start]; 
988                 if(istQuelle(ID))
989                     break;  //andere Quelle blockiert weitergehen! 
990                 if(ID>0 && !istQuelle(ID)  && !warschon(p,k_start,sammel_ik)) //solche, die schon waren \u00fcbergehen!
991                 {
992                      merker[2][0] = p; // i k ID dist, wenn ID 0 == nix gefunden
993                      merker[2][1] = k_start;
994                      merker[2][2] = matrix[p][k_start]; //ID
995                      merker[2][3] = p - i_start; //dist (>0)
996                      break;
997                 }
998                 else if(warschon(p,k_start,sammel_ik)) //auch abbrechen, wenn einer im Weg ist, der schon war!
999                 {
1000                      break;
1001                 }
1002            }
1003            for(int p=i_start-1;p>=0;p--)
1004            {
1005                 int ID = matrix[p][k_start]; 
1006                 if(istQuelle(ID))
1007                     break;  //andere Quelle blockiert weitergehen! 
1008                 if(ID>0 && !istQuelle(ID)  && !warschon(p,k_start,sammel_ik)) //solche, die schon waren \u00fcbergehen!
1009                 {
1010                      merker[3][0] = p; // i k ID dist, wenn ID 0 == nix gefunden
1011                      merker[3][1] = k_start;
1012                      merker[3][2] = matrix[p][k_start]; //ID
1013                      merker[3][3] = i_start - p; //dist (>0)
1014                      break;
1015                 }
1016                 else if(warschon(p,k_start,sammel_ik)) //auch abbrechen, wenn einer im Weg ist, der schon war!
1017                 {
1018                      break;
1019                 }
1020            }            
1021            
1022            //Pr\u00fcfen, ob Nachfolger dabei ist, oder Abbruch n\u00f6tig:
1023            int dist_best = Integer.MAX_VALUE;
1024            int dist_zweitbest = Integer.MAX_VALUE;
1025            int i_best    = -1;
1026            int k_best    = -1;
1027            
1028            for(int i=0;i<merker.length;i++)
1029            {
1030                 int i_test = merker[i][0];
1031                 int k_test = merker[i][1];
1032                 int id_test = merker[i][2];
1033                 int dist_test = merker[i][3];
1034                 
1035                 if(id_test>0 && dist_test<=dist_best)
1036                 {
1037                      dist_zweitbest = dist_best;
1038                      dist_best = dist_test;
1039                      i_best = i_test;
1040                      k_best = k_test;
1041                 }                                  
1042            }
1043            
1044            if(i_best>-1 && k_best>-1 && dist_best<dist_zweitbest && !warschon(i_best,k_best,sammel_ik)) //muss echt n\u00e4chster sein ohne Auswahlm\u00f6glichkeit
1045            {
1046                  sammel_ik.add(new int[] {i_best,k_best,dist_best});                                    
1047            }
1048            else
1049            {
1050                  break;  //wenn keiner mehr gefunden wird, der echt am n\u00e4chsten an dem zuletzt gefundenen liegt ohne wdh.
1051            }
1052        }
1053        
1054        return sammel_ik;
1055    }            
1056}
1057
1058
1059public class Spieler implements Runnable
1060{
1061//     Random zufall = new Random(System.currentTimeMillis());
1062     Random zufall = new Random(0);
1063  
1064     boolean WEISS;
1065     Spielfeld spielfeld;
1066     Spiel spiel;
1067     Spiel testspiel;
1068     Spiel testspiel2;
1069     public Spieler(boolean WEISS, Spielfeld spielfeld, Spiel spiel, Spiel testspiel, Spiel testspiel2)
1070     {
1071         this.WEISS = WEISS;
1072         this.spiel = spiel;
1073         this.testspiel = testspiel;
1074         this.testspiel2 = testspiel2;
1075         this.spielfeld = spielfeld;
1076         
1077         (new Thread(this)).start();         
1078     }
1079     
1080     public void run()
1081     {
1082        while(true)
1083        {
1084          if(spielfeld.WEISS_IST_DRAN == WEISS && spielfeld.TIMER_WEISS_IST_DRAN == WEISS ) //ist dran und darf loslegen
1085          {
1086               //Pr\u00fcfen, ob schon Quelle auf dem Feld ist, wenn nicht diese setzen
1087               Karte quelle = quelleweiss;
1088               if(!WEISS)
1089                   quelle = quelleschwarz;
1090               int ID = quelle.ID;
1091               if(!spiel.istAufSpielfeld(ID))
1092               {
1093//println("Nicht auf Feld");                 
1094                   int i = zufall.nextInt(spiel.matrix.length);
1095                   int k = zufall.nextInt(spiel.matrix[0].length);
1096                   while(spiel.matrix[i][k]>0)
1097                   {
1098                       i = zufall.nextInt(spiel.matrix.length);
1099                       k = zufall.nextInt(spiel.matrix[0].length);
1100                   }
1101//println("setze auf "+i+" "+k);                   
1102                   spiel.matrix[i][k] = ID;
1103               }
1104               else
1105               {
1106                    spiel.kopiereAufAnderesSpiel(testspiel);
1107                    spiel.kopiereAufAnderesSpiel(testspiel2);
1108                    int punkte_best = 0;
1109                    for(int i=0;i<3;i++)
1110                    {
1111                        spiel.kopiereAufAnderesSpiel(testspiel);
1112                        int punkte = zufallszug(testspiel);
1113                        if(punkte>=punkte_best)
1114                        {
1115                             punkte_best = punkte;
1116                             testspiel.kopiereAufAnderesSpiel(testspiel2);
1117                        }
1118                    }    
1119                    testspiel2.kopiereAufAnderesSpiel(spiel);
1120               }
1121               
1122               //abschliessen:
1123               //JETZT IST DER ANDERE DRAN!
1124               spiel.schreibeZustand();
1125               updateSpielzustand();
1126               spielfeld.WEISS_IST_DRAN = !spielfeld.WEISS_IST_DRAN;
1127          
1128               
1129          }
1130       
1131       
1132          try
1133          {
1134              Thread.sleep(1000);
1135          }
1136          catch(Exception e)
1137          {
1138          }
1139        }//while true  
1140     }//run
1141     
1142
1143     public boolean spielfeldVoll(Spiel spiel)
1144     {
1145           for(int i=0;i<spiel.matrix.length;i++)
1146               for(int k=0;k<spiel.matrix[0].length;k++)
1147                    if(spiel.matrix[i][k]==0)
1148                        return false;
1149           return true;             
1150     }
1151     
1152     public int spielfeldProzentVoll(Spiel spiel)
1153     {
1154           int anz = 0;
1155           int sum = spiel.matrix.length*spiel.matrix[0].length;
1156           for(int i=0;i<spiel.matrix.length;i++)
1157               for(int k=0;k<spiel.matrix[0].length;k++)
1158                    if(spiel.matrix[i][k]!=0)
1159                        anz++;
1160           return (anz*100)/sum;             
1161     }
1162     
1163     
1164     public int[] zufalls_ik(Spiel spiel)
1165     {
1166           int i = zufall.nextInt(spiel.matrix.length);
1167           int k = zufall.nextInt(spiel.matrix[0].length);
1168           while(spiel.matrix[i][k]>0)
1169           {
1170               i = zufall.nextInt(spiel.matrix.length);
1171               k = zufall.nextInt(spiel.matrix[0].length);
1172           }
1173           return new int[] {i,k};
1174     }
1175
1176     public int[] zufalls_ik_besetztEigeneFarbe(Spiel spiel) //liefert Platz, der besetrzt ist mit eigener Farbe und nicht Quelle
1177     {
1178           int i = zufall.nextInt(spiel.matrix.length);
1179           int k = zufall.nextInt(spiel.matrix[0].length);
1180           while(spiel.matrix[i][k]==0 || spiel.istWeiss(spiel.matrix[i][k])!=WEISS || spiel.istQuelle(spiel.matrix[i][k]))
1181           {
1182               i = zufall.nextInt(spiel.matrix.length);
1183               k = zufall.nextInt(spiel.matrix[0].length);
1184           }
1185           return new int[] {i,k};
1186     }
1187     
1188     
1189     public void entferneID(int ID,Spiel spiel)
1190     {
1191           for(int i=0;i<spiel.matrix.length;i++)
1192               for(int k=0;k<spiel.matrix[0].length;k++)
1193                    if(spiel.matrix[i][k]==ID)
1194                    {
1195                        spiel.matrix[i][k]=0;
1196                        return;
1197                    }    
1198     }
1199     
1200     public int bestimmePunkte(Spiel spiel, boolean WEISS)
1201     {
1202           if(WEISS)
1203           {
1204                return spiel.berechnePunkte(spiel.findeNaechstenpfadWeiss());
1205           }
1206           else
1207           {
1208                return spiel.berechnePunkte(spiel.findeNaechstenpfadSchwarz());
1209           }
1210     }
1211     
1212     public int zufallszug(Spiel spiel)  //Liefert auch mit dem Zug erreichbare Punkte
1213     {
1214          if(  spielfeldProzentVoll(spiel) > 30 )  //wenn zu 60% voll, dann in jedem Fall etwas entfernen
1215          {
1216              int[] ik = zufalls_ik_besetztEigeneFarbe(spiel); //sucht besetzten Platz eigener Farbe
1217              
1218              spiel.matrix[ik[0]][ik[1]] = 0; 
1219                                        
1220            
1221              //return bestimmePunkte(spiel,WEISS)-bestimmePunkte(spiel,!WEISS);
1222              return bestimmePunkte(spiel,WEISS);
1223          }
1224          else if(  spielfeldProzentVoll(spiel) > 10 && zufall.nextInt(100)<50)  //wenn zu 60% voll, dann in jedem Fall etwas entfernen
1225          {
1226              int[] ik = zufalls_ik_besetztEigeneFarbe(spiel); //sucht besetzten Platz
1227              
1228              spiel.matrix[ik[0]][ik[1]] = 0; 
1229            
1230              //return bestimmePunkte(spiel,WEISS)-bestimmePunkte(spiel,!WEISS);
1231              return bestimmePunkte(spiel,WEISS);
1232          }
1233       
1234          int inx = zufall.nextInt(karte.length);
1235          int ID = karte[inx].ID;
1236          while(spiel.istWeiss(ID)!=WEISS)
1237          {
1238              inx = zufall.nextInt(karte.length);
1239              ID = karte[inx].ID;
1240          }
1241          
1242          if(spiel.istAufSpielfeld(ID))  //dann verschieben
1243          {
1244               entferneID(ID,spiel);
1245               int[] ik = zufalls_ik(spiel);
1246               spiel.matrix[ik[0]][ik[1]] = ID;
1247          }
1248          else  //dann neu setzen
1249          {
1250               int[] ik = zufalls_ik(spiel);
1251               spiel.matrix[ik[0]][ik[1]] = ID;
1252          }
1253          
1254           //return bestimmePunkte(spiel,WEISS)-bestimmePunkte(spiel,!WEISS);
1255           return bestimmePunkte(spiel,WEISS);
1256     }
1257}
1258public class Spielfeld
1259{
1260     public boolean WEISS_IST_DRAN = true;
1261     public boolean TIMER_WEISS_IST_DRAN = true;
1262
1263     public float[][] ikoord; //Koordinaten des Spielfeldes  
1264     public float[][] kkoord; //Koordinaten des Spielfeldes  
1265  
1266     int anzx,anzy;
1267     float kantex,kantey;
1268     float mx;
1269     float my;
1270          
1271     float x;
1272     float y;
1273
1274     float b,h;
1275     
1276     public Karte[][] matrix; //mit belegten Feldern
1277     
1278     public Spielfeld(float kantex, float kantey,int anzx, int anzy)
1279     {
1280          this.anzx=anzx;
1281          this.anzy=anzy;
1282          this.kantex=kantex;
1283          this.kantey=kantey;
1284          this.matrix = new Karte[anzy][anzx+1]; //HACK. anzx mu\u00df ungerade sein, Breite wird dann komischerweise gerade wg. Darstellung
1285          this.mx = width/2.0f;
1286          this.my = height/2.0f;
1287          
1288          this.x = mx - kantex*(0.5f*(float)anzx);
1289          this.y = my - kantey*(0.5f*(float)anzy);
1290          this.b = anzx*kantex;
1291          this.h = anzy*kantey;
1292          
1293          ikoord = new float[matrix.length][matrix[0].length];
1294          kkoord = new float[matrix.length][matrix[0].length];
1295          for(int i=0;i<matrix.length;i++)
1296          {
1297                for(int k=0;k<matrix[i].length;k++)
1298                {
1299                    // rect(x+(k+i%2)*kantex-kantex*0.5f,y+i*kantey,kantex,kantey,60);
1300                    float xxx = x+k*kantex-kantex*0.5f;
1301                    float yyy = y+i*kantey;
1302                    ikoord[i][k] = yyy + kantey*0.5f;
1303                    kkoord[i][k] = xxx + kantex*0.5f;
1304                }
1305          }
1306     }
1307     
1308     public void draw()
1309     {
1310          //noFill();
1311          //stroke(95);
1312          noStroke();
1313          fill(127);
1314          for(int i=0;i<anzy;i++)
1315          {
1316                for(int k=0;k<anzx;k+=2)
1317                {
1318                     rect(x+(k+i%2)*kantex-kantex*0.5f,y+i*kantey,kantex,kantey,60);
1319                }
1320          }
1321          
1322          //fill(64);
1323          for(int i=0;i<anzy;i++)
1324          {
1325                for(int k=0;k<anzx;k+=2)
1326                {
1327                     rect(x+(k+(i+1)%2)*kantex-kantex*0.5f,y+i*kantey,kantex,kantey,60);
1328                }
1329          }
1330          
1331     }
1332     
1333     public boolean istInSpielfeld(Karte k)
1334     {
1335          float mausx = k.x - k.xoff;
1336          float mausy = k.y - k.yoff;
1337       
1338          if(mausx>x-kantex*0.4f && mausx<x+b+kantex*0.4f && mausy>y && mausy<y+h)
1339               return true;
1340          else
1341              return false;
1342     }
1343     
1344     public float getNextX(Karte k)
1345     {
1346           float mausx = k.x - k.xoff+kantex*0.5f;
1347           return x + kantex*floor((mausx-x)/kantex)-kantex*0.5f;
1348     }
1349
1350     public float getNextXausK(int kkk)
1351     {
1352           return x + kantex*kkk-kantex*0.5f;
1353     }     
1354     
1355     public float getNextY(Karte k)
1356     {
1357           float mausy = k.y - k.yoff;
1358           return y + kantey*floor((mausy-y)/kantey);
1359     }
1360
1361     public float getNextYausI(int iii)
1362     {
1363           return y + kantey*iii;
1364     }     
1365 
1366 
1367     public int getNextXindex(Karte k)
1368     {
1369           float mausx = k.x - k.xoff+kantex*0.5f;
1370           return (int)floor((mausx-x)/kantex);
1371     }
1372     
1373     public int getNextYindex(Karte k)
1374     {
1375           float mausy = k.y - k.yoff;
1376           return (int)floor((mausy-y)/kantey);
1377     }
1378     
1379     public boolean istFrei(int i, int k)
1380     {
1381          if(matrix[i][k]==null)
1382              return true;
1383          else
1384              return false;
1385     }
1386     
1387     public boolean istAufSpielfeld(Karte karte)
1388     {
1389          for(int i=0;i<matrix.length;i++)
1390              for(int k=0;k<matrix[i].length;k++)
1391                  if(matrix[i][k]!=null && karte!=null && matrix[i][k].ID==karte.ID)
1392                      return true;
1393          return false;            
1394     }
1395}
1396
1397
1398
1399
1400public class Zugkontrolle implements Runnable
1401{
1402     private long WERT_WEISS = 0;
1403     private long WERT_SCHWARZ = 0;
1404     private long FREQ_WEISS = 0;
1405     private long FREQ_SCHWARZ = 0;
1406     private long MIDI_WEISS = 0;
1407     private long MIDI_SCHWARZ = 0;
1408     
1409     private long FFREQ = 0;
1410     private long MMID = 0;
1411//Basiszahl: 2*2*2*3*3*5*7 == 2520 == 7*360
1412//Faktor:    1
1413//fmin:      55  == KA
1414//fmax:     1760 == a''' 
1415  
1416     private long BASISZAHL = 2520; 
1417     private long FAKTOR = 1; 
1418     private long FMIN = 55; 
1419     private long FMAX = 1760; 
1420  
1421     private ScheduledExecutorService schedExecService; //realtime process     
1422  
1423     private Spielfeld spielfeld;
1424     
1425  
1426     long PULSMILLIS;
1427     long PULSEPROZUG;
1428     long t;
1429     int STRAFPUNKTE;
1430     public Zugkontrolle(long PULSMILLIS, long PULSEPROZUG, Spielfeld spielfeld, int STRAFPUNKTE)
1431     {
1432         
1433         this.STRAFPUNKTE = STRAFPUNKTE;
1434         this.spielfeld = spielfeld;
1435         this.PULSMILLIS = PULSMILLIS;
1436         this.PULSEPROZUG = PULSEPROZUG;
1437         
1438         t=0;
1439         schedExecService = Executors.newSingleThreadScheduledExecutor();
1440         schedExecService.scheduleAtFixedRate(this, 0, PULSMILLIS, TimeUnit.MILLISECONDS);             
1441         
1442     }
1443  
1444     public long berechneWertAusPfad(long t,ArrayList<int[]> pfad, boolean WEISS)
1445     {
1446          long erg = t;
1447          try
1448          {
1449            for(int i=1;i<pfad.size();i++)
1450            {
1451               int ID = spiel.matrix[pfad.get(i)[0]][pfad.get(i)[1]];
1452               long operand = spiel.farbeVonID(ID); //==farbe 1,2,3,4,5,6
1453               
1454//NEU: dist ber\u00fccksichtigen
1455operand*=pfad.get(i)[2];
1456               
1457               //typ 9 ist Quelle, 0..8== .|..|...|-|--|---|+|++|+++ 
1458               //                         0  1  2  3  4  5  6  7  8
1459               //                         *  / gt  - =   %  +   
1460               int operator = 3*spiel.formVonID(ID) + spiel.anzahlVonID(ID);
1461               switch(operator)
1462               {
1463                   case 0:  // .
1464                      erg *= operand;
1465                   break;
1466                   case 1:  // ..
1467                      erg/=operand;
1468                   break;
1469                   case 2:  // ...  gemeinsame Teiler finden und durch ihre Gesamtprodukt teilen.
1470                      long teiler=1;
1471                      for(int p=2;p<=operand;p++)
1472                          if(operand%p==0 && erg%p==0)
1473                              teiler*=p;
1474                      erg/=teiler;        
1475                   break;
1476                   case 3:  // -
1477                      erg-=operand;
1478                      if(erg<0)
1479                         erg=0;
1480                   break;
1481                   case 4:  // --
1482                      if(erg==operand)
1483                          erg = operand;
1484                      else
1485                          erg = 0;
1486                   break;
1487                   case 5:  // --- Modulo
1488                      if(operand>0)
1489                          erg%=operand;
1490                      else
1491                          erg = erg;
1492                   break;
1493                   case 6:  // +
1494                      erg+=operand;
1495                   break;
1496                   case 7:  // ++ als UNGLEICH behandeln
1497                      if(erg!=operand)
1498                          erg = erg;
1499                      else
1500                          erg = 0;                   
1501                   break;
1502                   case 8:  // +++ , wie ..., aber multiplizieren statt dividieren
1503                      long faktor=1;
1504                      for(int p=2;p<=operand;p++)
1505                          if(operand%p==0 && erg%p==0)
1506                              faktor*=p;
1507                      erg*=faktor;        
1508                   break;
1509               }
1510               
1511               if(erg>0 && BASISZAHL%erg==0)
1512               {
1513             FREQ_WEISS = BASISZAHL/(erg*FAKTOR);
1514             if(FREQ_WEISS<FMIN)
1515                FREQ_WEISS=0;
1516             if(FREQ_WEISS>FMAX)
1517                FREQ_WEISS=0;
1518             if(FREQ_WEISS>0)
1519             {
1520                MIDI_WEISS = freq2mid((int)FREQ_WEISS);
1521                if(MIDI_WEISS>0 && WEISS)
1522                {
1523                    msp.play(0+i%2,(int)MIDI_WEISS);  //2 M\u00f6gl. je nach Pos. in Kette
1524//                    msp.playMono(0,(int)MIDI_WEISS);
1525                    if(RECORDING==true)
1526                    {
1527                         //add(int pulsnr, int spielernr, int steinnr, int zeile, int spalte, int midi)
1528                         rekorder.add((int)t,0,i,(int)pfad.get(i)[0],(int)pfad.get(i)[1],(int)MIDI_WEISS);
1529                         rekorder.addToScore(t,0,(int)MIDI_WEISS);
1530                    }
1531                }    
1532                else if(MIDI_WEISS>0 && !WEISS)
1533                {
1534                    msp.play(2+i%2,(int)MIDI_WEISS);
1535//                    msp.playMono(1,(int)MIDI_WEISS);
1536                    if(RECORDING==true)
1537                    {
1538                         //add(int pulsnr, int spielernr, int steinnr, int zeile, int spalte, int midi)
1539                         rekorder.add((int)t,1,i,(int)pfad.get(i)[0],(int)pfad.get(i)[1],(int)MIDI_WEISS);
1540                         rekorder.addToScore(t,1,(int)MIDI_WEISS);
1541                    }
1542                }    
1543             }  
1544                    
1545               }
1546            }
1547          }
1548          catch(Exception e)
1549          {
1550              println(e);
1551              return 0;
1552          }
1553          return erg;
1554     }
1555long ANZ=0;  
1556     public void run()
1557     {       
1558         if(t%PULSEPROZUG==0 && t>0)
1559         {
1560              if(spielfeld.WEISS_IST_DRAN != spielfeld.TIMER_WEISS_IST_DRAN)
1561              {
1562                  spielfeld.TIMER_WEISS_IST_DRAN = !spielfeld.TIMER_WEISS_IST_DRAN;
1563              }
1564              else
1565              {
1566                  if(spielfeld.WEISS_IST_DRAN && PUNKTE_WEISS>=STRAFPUNKTE)
1567                      PUNKTE_WEISS-=STRAFPUNKTE;
1568                  else if(spielfeld.WEISS_IST_DRAN && PUNKTE_WEISS<STRAFPUNKTE)
1569                      PUNKTE_WEISS=0;
1570                  else if(!spielfeld.WEISS_IST_DRAN && PUNKTE_SCHWARZ>=STRAFPUNKTE)
1571                      PUNKTE_SCHWARZ-=STRAFPUNKTE;
1572                  else if(!spielfeld.WEISS_IST_DRAN && PUNKTE_SCHWARZ<STRAFPUNKTE)
1573                      PUNKTE_SCHWARZ=0;
1574                  if(WARTUNG)    
1575                  println("Nach Strafpunkten: W:"+PUNKTE_WEISS+" S:"+PUNKTE_SCHWARZ);    
1576              }
1577         }
1578         //Werte aus Pfaden berechnen:
1579         if(weisserpfad!=null && weisserpfad.size()>1)
1580         {
1581             WERT_WEISS = berechneWertAusPfad(t,weisserpfad,true);
1582         }
1583         else
1584         {
1585             WERT_WEISS = 0;
1586         }
1587         if(schwarzerpfad!=null && schwarzerpfad.size()>1)
1588         {
1589             WERT_SCHWARZ = berechneWertAusPfad(t,schwarzerpfad,false);
1590         }
1591         else
1592         {
1593             WERT_SCHWARZ = 0;
1594         }
1595FFREQ=0;
1596         if(WERT_WEISS>0 && BASISZAHL%(WERT_WEISS*FAKTOR)==0)
1597         {
1598             FREQ_WEISS = BASISZAHL/(WERT_WEISS*FAKTOR);
1599             if(FREQ_WEISS<FMIN)
1600                FREQ_WEISS=0;
1601             if(FREQ_WEISS>FMAX)
1602                FREQ_WEISS=0;
1603             if(FREQ_WEISS>0)
1604             {
1605                MIDI_WEISS = freq2mid((int)FREQ_WEISS);
1606                FFREQ += FREQ_WEISS;
1607             }  
1608         }    
1609         else
1610         {
1611             FREQ_WEISS = 0;
1612         }
1613         
1614         if(WERT_SCHWARZ>0 && BASISZAHL%(WERT_SCHWARZ*FAKTOR)==0)
1615         {
1616             FREQ_SCHWARZ = BASISZAHL/(WERT_SCHWARZ*FAKTOR);
1617             if(FREQ_SCHWARZ<FMIN)
1618                FREQ_SCHWARZ=0;
1619             if(FREQ_SCHWARZ>FMAX)
1620                FREQ_SCHWARZ=0;
1621             if(FREQ_SCHWARZ>0)
1622             {
1623                MIDI_SCHWARZ = freq2mid((int)FREQ_SCHWARZ);
1624                FFREQ += FREQ_SCHWARZ;
1625             }  
1626                
1627         }    
1628         else
1629         {
1630             FREQ_WEISS = 0;
1631         }
1632
1633//             if(MIDI_SCHWARZ>0)
1634//                msp.play(1,(int)MIDI_SCHWARZ);
1635//             if(MIDI_WEISS>0)
1636//                msp.play(0,(int)MIDI_WEISS);
1637//         if(FFREQ>0)
1638//         {
1639//              MMID =  freq2mid((int)FFREQ);
1640//              if(MMID>0)
1641//                 msp.play(0,(int)MMID);
1642//         }
1643         
1644         //print(WERT_WEISS+"|"+WERT_SCHWARZ+" ");
1645         print(MIDI_WEISS+"|"+MIDI_SCHWARZ+" ");
1646       
1647         ANZ++;
1648         if(ANZ>=PULSEPROZUG)
1649         {
1650              println("###");
1651              ANZ=0;
1652         }
1653       
1654         t++;
1655       
1656     }
1657}
1658
1659
1660
1661
1662
1663
1664
1665 
1666
1667public class FastSoundplayer implements Runnable
1668{
1669     int MAXPOLY = 200; //Maximale Anzahl aktuell noch abzuarbeitender Samples
1670     float[][][] sample = new float[MAXPOLY][][]; 
1671     int[] index = new int[MAXPOLY];
1672     float[][] sampleMono = new float[MAXPOLY][]; 
1673     float[][] panMono = new float[MAXPOLY][2];  //wird mit \u00fcbernommen! 
1674     int[] indexMono = new int[MAXPOLY];
1675     //der play-Funktion wird ein Sample \u00fcbergeben und der korrespondierende Index wird auf Null gesetzt, alles, wenn noch
1676     //Platz im Array sample.
1677     //erreicht index die L\u00e4nge des samples wird dieses entfernt und damit der Platz f\u00fcr nachfolgende Samples frei gegeben.
1678     
1679     int sr = 44100;
1680     int buffsize = 512;
1681     int buffsize2 = buffsize*2;
1682     public float[] mikrofon_welle = new float[buffsize2];
1683     float dt = 1.0f/(float)sr;
1684     float dth = 0.5f*dt;
1685     protected ScheduledExecutorService schedExecService;  
1686     short[] puffer = new short[buffsize*2]; //4 Byte pro Sample == 16Bit Stereo  //2 * bei short
1687     float[] fpuffer = new float[buffsize*2]; //4 Byte pro Sample == 16Bit Stereo  //2 * bei short
1688     public float t=0.0f;
1689     
1690     private AudiotrackMic track;
1691     
1692     public void play(float[][] data)
1693     {
1694          for(int i=0;i<sample.length;i++)
1695          {
1696                if(sample[i]==null)
1697                {
1698                      sample[i]=data;
1699                      index[i]=0;
1700                      break;
1701                }
1702          }
1703     }
1704
1705     public void playMono(float[] data)
1706     {
1707          for(int i=0;i<sampleMono.length;i++)
1708          {
1709                if(sampleMono[i]==null)
1710                {
1711                      sampleMono[i]=data;
1712                      indexMono[i]=0;
1713                      panMono[i][0] = 0.1f;  //s\u00e4ter wird von au\u00dfen die Richtung berechnet und mit \u00fcbergeben
1714                      panMono[i][1] = 0.1f;
1715                      break;
1716                }
1717          }
1718     }
1719     
1720     
1721     public FastSoundplayer()
1722     {
1723         
1724         track = new AudiotrackMic(sr,buffsize);
1725         schedExecService = Executors.newSingleThreadScheduledExecutor();
1726         long period = (buffsize*1000)/sr; //Seconds per Beat==60/BPM, die H\u00e4lfte weil 8tel, mal 1000 weil Millisekunden.
1727         schedExecService.scheduleAtFixedRate(this, 0, period, TimeUnit.MILLISECONDS);                
1728     }
1729
1730     public void run()
1731     {
1732         runStereo();
1733//         runMono();
1734     }
1735     
1736     public void runStereo()
1737     {
1738         //Neues Vorgehen:
1739         for(int k=0;k<fpuffer.length;k++)
1740             fpuffer[k]=0.0f;
1741//STEREO:             
1742         for(int i=0;i<sample.length;i++)
1743         {
1744              float[][] data = sample[i]; //Threadsicher machen, indem Referenz erst einmal gemerkt / gesichert wird.
1745              if(data!=null)
1746              {
1747                  for(int k=0;k<puffer.length;k+=2)
1748                  {
1749                      if(index[i]>=data[0].length)
1750                      {
1751                          sample[i]=null;                          
1752                          break;
1753                      }    
1754                      fpuffer[k+0] += data[0][index[i]];
1755                      fpuffer[k+1] += data[1][index[i]];
1756                      index[i]++;
1757                  }
1758              }
1759         }
1760         for(int k=0;k<fpuffer.length;k++)
1761             puffer[k]=(short)(32767.0f*fpuffer[k]+0.5f);
1762                                       
1763         //audioTrack.write(puffer, 0,buffsize2);
1764         mikrofon_welle = track.write(puffer);
1765     }     
1766     
1767     public void runMono()
1768     {
1769         //Neues Vorgehen:
1770         for(int k=0;k<fpuffer.length;k++)
1771             fpuffer[k]=0.0f;
1772//MONO:             
1773         for(int i=0;i<sampleMono.length;i++)
1774         {
1775              float[] dataMono = sampleMono[i]; //Threadsicher machen, indem Referenz erst einmal gemerkt / gesichert wird.
1776              if(dataMono!=null)
1777              {
1778                  for(int k=0;k<puffer.length;k+=2)
1779                  {
1780                      if(indexMono[i]>=dataMono.length)
1781                      {
1782                          sampleMono[i]=null;                          
1783                          break;
1784                      }    
1785                      fpuffer[k+0] += dataMono[indexMono[i]] * panMono[i][0];
1786                      fpuffer[k+1] += dataMono[indexMono[i]] * panMono[i][1];
1787                      indexMono[i]++;
1788                  }
1789              }
1790         }
1791         for(int k=0;k<fpuffer.length;k++)
1792             puffer[k]=(short)(32767.0f*fpuffer[k]+0.5f);
1793                                       
1794         //audioTrack.write(puffer, 0,buffsize2);
1795         mikrofon_welle = track.write(puffer);
1796     }     
1797     
1798}
1799
1800/**
1801 * Interface f\u00fcr Audiostream mit zus\u00e4tzlichem Mikrofonkanal
1802 */
1803public interface iAudiotrackMic
1804{
1805    public abstract float[] write(short[] puffer);
1806}
1807
1808public class AudiotrackMic implements iAudiotrackMic
1809{
1810    // instance variables - replace the example below with your own
1811    private iAudiotrackMic track;
1812    public short[] shortpuffer;
1813    public float[] micpuffer;
1814    protected ScheduledExecutorService schedExecService;  
1815    
1816    public AudiotrackMic(int SAMPLING_RATE, int buffsize)
1817    {
1818          shortpuffer = new short[buffsize*2]; //2* weil Stereo
1819          micpuffer = new float[buffsize*2]; 
1820        
1821              track = new AudiotrackMicPC(SAMPLING_RATE, buffsize);
1822              
1823    }
1824
1825    public float[] write(short[] shortpuffer)
1826    {            
1827        return track.write(shortpuffer);
1828    }
1829
1830 
1831}
1832
1833public class AudiotrackMicPC implements iAudiotrackMic
1834{
1835    int BYTEPUFFERGROESSE;
1836    int SAMPLING_RATE;
1837    
1838    SourceDataLine line;
1839    TargetDataLine targetLine;  //Mikrofon
1840    DataLine.Info info;
1841    DataLine.Info targetInfo;  //Mikrofon
1842    
1843    AudioFormat format;
1844        
1845     //AudioTrack audioTrack;
1846     //int sr = 11025;
1847     //Versuchen die Qualit\u00e4t zu verbessern:
1848    
1849     //int buffsize = 512;
1850     int buffsize;
1851     int buffsize2;
1852    
1853     byte[] bytepuffer;
1854     byte[] targetData;
1855     float[] targetWelle;
1856    public AudiotrackMicPC(int SAMPLING_RATE, int buffsize)
1857    {
1858        this.SAMPLING_RATE = SAMPLING_RATE;
1859        this.buffsize = buffsize;
1860        this.buffsize2 = buffsize*2;
1861        this.BYTEPUFFERGROESSE = buffsize*4;
1862
1863        bytepuffer = new byte[BYTEPUFFERGROESSE];
1864        targetData = new byte[BYTEPUFFERGROESSE];
1865        targetWelle = new float[buffsize2];
1866        for(int i=0;i<bytepuffer.length;i++)
1867            bytepuffer[i]=0;
1868        
1869        this.format = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED,(float)SAMPLING_RATE, 16, 2, 4, (float)SAMPLING_RATE, false);
1870        this.info = new DataLine.Info(SourceDataLine.class, format);
1871        this.targetInfo = new DataLine.Info(TargetDataLine.class, format);
1872        if (!AudioSystem.isLineSupported(info))
1873        {
1874         System.out.println("Line matching " + info + " is not supported.");
1875         //throw new LineUnavailableException();
1876        }
1877        //format = new AudioFormat(SAMPLERATE, 16, 2, true, true);
1878        try
1879        {
1880            this.targetLine = (TargetDataLine) AudioSystem.getLine(targetInfo);
1881            this.targetLine.open(format);
1882            this.targetLine.start();            
1883            
1884            this.line = (SourceDataLine)AudioSystem.getLine(info);
1885            this.line.open(format,BYTEPUFFERGROESSE);  
1886            this.line.start();
1887        }
1888        catch(Exception ee)
1889        {
1890            System.out.println("FEHLER: "+ee);
1891        }              
1892        
1893    }
1894
1895    public float[] write(short[] shortpuffer)
1896    {
1897        for (int i=0; i < buffsize; i++) 
1898        {
1899            bytepuffer[i*4+1] = (byte)(shortpuffer[i*2+0]>>8);
1900            bytepuffer[i*4+0] = (byte)(shortpuffer[i*2+0] & 0xFF); 
1901            bytepuffer[i*4+3] = (byte)(shortpuffer[i*2+1]>>8);
1902            bytepuffer[i*4+2] = (byte)(shortpuffer[i*2+1] & 0xFF); 
1903        }            
1904        targetLine.read(targetData, 0, targetData.length);
1905        line.write(bytepuffer, 0, BYTEPUFFERGROESSE);
1906        
1907        for(int i=0;i<buffsize;i++) //Stereo!
1908        {
1909            //targetWelle[i*2+0] = (float)((targetData[i*4+0]<<8)+targetData[i*4+1])/32000.0f;
1910            //targetWelle[i*2+1] = (float)((targetData[i*4+2]<<8)+targetData[i*4+3])/32000.0f;
1911            targetWelle[i*2+0] = (float)((targetData[i*4+1]<<8)+targetData[i*4+0])/32000.0f;
1912            targetWelle[i*2+1] = (float)((targetData[i*4+3]<<8)+targetData[i*4+2])/32000.0f;
1913        }
1914        return targetWelle; //Mikrofondaten heraufreichen, um sie mit den anderen kan\u00e4len mischen zu k\u00f6nnen (ein paket verz\u00f6gert)
1915
1916    }
1917}
1918public class Mysoundplayer extends FastSoundplayer
1919{
1920      Wav wav;
1921      int anzahl_kanaele;
1922      float[][][][] ton;// = new float[anzahl_kanaele][128][][]; //jeder Kanal hat 128 Pl\u00e4tze f\u00fcr 44100kHz stereo wav-Sound, belegt abh. von Skalen.
1923
1924      float[][][] mono; //Stimme, Nr, Sample
1925
1926
1927      int[] skala;
1928      int[] skalamap;
1929
1930      public Mysoundplayer(PApplet pap, int anzahl_kanaele)
1931      {
1932          this.anzahl_kanaele = anzahl_kanaele;
1933          wav = new Wav(pap);
1934          ton = new float[anzahl_kanaele][128][][]; //jeder Kanal hat 128 Pl\u00e4tze f\u00fcr 44100kHz stereo wav-Sound, belegt abh. von Skalen.          
1935      }
1936      
1937      public void ladeMonostimmen(int[] skala, String[] ordner, String prefix)
1938      {
1939            this.skala = skala;
1940            skalamap = new int[128];
1941            for(int i=0;i<skala.length;i++)
1942                skalamap[skala[i]] = i;  //um schnell aus Midi den Index zu gewinnen!
1943            mono = new float[ordner.length][skala.length][];
1944            for(int i=0;i<mono.length;i++)
1945            {
1946                 for(int k=0;k<mono[i].length;k++)
1947                 {
1948                       mono[i][k] = wav.ladeWavMix("data/"+ordner[i]+"/"+prefix+skala[k]+".wav");
1949                 }
1950            }
1951      }
1952
1953      public void ladeMonostimmen(int[] skala, String[] ordner, float[] verst, String prefix)
1954      {
1955            this.skala = skala;
1956            skalamap = new int[128];
1957            for(int i=0;i<skala.length;i++)
1958                skalamap[skala[i]] = i;  //um schnell aus Midi den Index zu gewinnen!
1959            mono = new float[ordner.length][skala.length][];
1960            for(int i=0;i<mono.length;i++)
1961            {
1962                 for(int k=0;k<mono[i].length;k++)
1963                 {
1964                       mono[i][k] = wav.ladeWavMix("data/"+ordner[i]+"/"+prefix+skala[k]+".wav");
1965                 }
1966            }
1967            
1968            for(int i=0;i<mono.length;i++)
1969            {
1970                 for(int k=0;k<mono[i].length;k++)
1971                 {
1972                    for(int p=0;p<mono[i][k].length;p++)
1973                       mono[i][k][p] *= verst[i];
1974                 }
1975            }
1976            
1977      }
1978      
1979      
1980      public void ladeKanal(int kanal, String ordnerpfad, int[] midiskala, float laute, float pan)
1981      {
1982           float pan_left = cos(pan*HALF_PI);
1983           float pan_right = sin(pan*HALF_PI);
1984           for(int i=0;i<midiskala.length;i++)
1985           {
1986                 ton[kanal][midiskala[i]] = wav.ladeWavInterpolate(ordnerpfad,midiskala[i]);
1987                 for(int k=0;k<ton[kanal][midiskala[i]][0].length;k++)
1988                 {
1989                       ton[kanal][midiskala[i]][0][k]*=laute*pan_left;
1990                       ton[kanal][midiskala[i]][1][k]*=laute*pan_right;
1991                 }
1992           }
1993      }
1994
1995      public void ladeKanalStereo(int kanal, String ordnerpfad, int[] midiskala, float laute, float pan)
1996      {
1997           float pan_left = cos(pan*HALF_PI);
1998           float pan_right = sin(pan*HALF_PI);
1999           for(int i=0;i<midiskala.length;i++)
2000           {
2001                 ton[kanal][midiskala[i]] = wav.ladeWav(ordnerpfad+"/ton"+midiskala[i]+".wav");
2002                 for(int k=0;k<ton[kanal][midiskala[i]][0].length;k++)
2003                 {
2004                       ton[kanal][midiskala[i]][0][k]*=laute*pan_left;
2005                       ton[kanal][midiskala[i]][1][k]*=laute*pan_right;
2006                 }
2007           }
2008      }
2009      
2010      public void saveKanal(int kanal, String pfad, int[] midiskala)
2011      {
2012            for(int i=0;i<midiskala.length;i++)
2013            {
2014                 wav.saveWav(pfad+"/ton"+midiskala[i]+".wav",ton[kanal][midiskala[i]]);
2015            }
2016      }
2017      
2018      public void play(int kanal, int midihoehe)
2019      {
2020            play(ton[kanal][midihoehe]);
2021      }
2022
2023      public void playMono(int kanal, int midihoehe)
2024      {
2025            playMono(mono[kanal][skalamap[midihoehe]]);
2026      }
2027      
2028}
2029public class Rekorder
2030{
2031     ArrayList<int[]> merker = new ArrayList<int[]>();  //PulsNr, SpielerNr, SteinNr., Zeile, Spalte, Midi
2032     int[][] score1;
2033     int[][] score2;
2034     long startzeit;
2035     long endzeit;
2036     public Rekorder(long startzeit, long endzeit)
2037     {
2038         this.startzeit = startzeit;
2039         this.endzeit = endzeit;
2040         score1 = new int[(int)(endzeit-startzeit+1)][128];
2041         score2 = new int[(int)(endzeit-startzeit+1)][128];
2042     }
2043     
2044     public void saveMatrix(int[][] mat, String name)
2045     {
2046          String[] lines = new String[mat.length];
2047          for(int i=0;i<mat.length;i++)
2048          {
2049              StringBuffer sb = new StringBuffer();
2050              for(int k=0;k<mat[i].length;k++)
2051              {
2052                   if(k<mat[i].length-1)
2053                       sb.append(mat[i][k]+",");
2054                   else
2055                       sb.append(mat[i][k]);
2056              }
2057              lines[i] = sb.toString();
2058          }
2059          saveStrings(name,lines);
2060     }
2061     
2062     public void addToScore(long t, int spielernr, int midi)
2063     {
2064         if(t>endzeit)
2065         {
2066              return;
2067         }
2068       
2069         if(spielernr==0)
2070         {
2071              score1[(int)(t-startzeit)][midi]++;
2072         }
2073         else
2074         {
2075              score2[(int)(t-startzeit)][midi]++;
2076         }
2077         
2078         if(t==endzeit)
2079         {
2080              saveMatrix(score1,"score1.txt");
2081              saveMatrix(score2,"score2.txt");
2082              println("\n\n**** SCORE gespeichert **** \n");
2083              return;
2084         }
2085         
2086     }
2087     
2088     public void add(int pulsnr, int spielernr, int steinnr, int zeile, int spalte, int midi)
2089     {
2090          merker.add(new int[] {pulsnr, spielernr, steinnr, zeile, spalte, midi});
2091     }
2092     
2093     public void save(String name)
2094     {
2095          String[] s = new String[merker.size()];
2096          for(int i=0;i<s.length;i++)
2097          {
2098              int[] m = merker.get(i);
2099              String eintrag = "";
2100              for(int k=0;k<m.length;k++)
2101              {
2102                   if(k<m.length-1)
2103                      eintrag+=""+m[k]+",";
2104                   else   
2105                      eintrag+=""+m[k];
2106              }
2107              s[i] = eintrag;
2108          }
2109          saveStrings(name,s);
2110          merker.clear();
2111     }
2112     
2113     public int[][] load(String name)
2114     {
2115           String[] s = loadStrings(name);
2116           int[][] erg = new int[s.length][];
2117           for(int i=0;i<s.length;i++)
2118           {
2119                String[] spalten = PApplet.splitTokens(s[i], ",");
2120                int[] spal = new int[spalten.length];
2121                for(int k=0;k<spal.length;k++)
2122                   spal[k] = Integer.parseInt(spalten[k]);
2123                erg[i] = spal;   
2124           }
2125           return erg;
2126     }
2127}
2128
2129
2130public interface iWav
2131{
2132    public abstract void saveWav(String name, float[][] data);  
2133    //float-Array wieder zur\u00fcck in ein byte-Array umwandeln (Vorbereitung speichern eines Stereokanals)
2134    public abstract byte[] toByte(float[][] data);
2135    //L\u00e4dt eine Stereo-Wav-Datei in zwei getrennten float-Arrays, Wertebereich [-1,+1]:
2136    public abstract float[][] ladeWav(String name);
2137    public abstract float[][] ladeWav(String name, int sampleanzahl);
2138    //L\u00e4dt eine Stereo-Wav-Datei, die dann zu einem Kanal gemischt wird und als float-Array zur\u00fcck gegeben wird.
2139    //Gleich nur Mix aus linkem und rechtem Kanal laden (aus 44100 2x16Bit extrahieren)
2140    public abstract float[] ladeWavMix(String name); 
2141    /**
2142     * L\u00e4dt eine Stereo-Datei, mixt sie zu Mono und baut sie zu einer loop-baren Variante
2143     * zusammen:<br/>
2144     * [AB] a=A ausblenden, b=B einblenden<br/>
2145     * ab + ba<br/>
2146     */
2147    public abstract float[] ladeWavMixLoop(String name); //Gleich nur Mix aus linkem und rechtem Kanal laden (aus 44100 2x16Bit extrahieren)
2148    //Gleich nur Mix aus linkem und rechtem Kanal laden (aus 44100 2x16Bit extrahieren)    
2149    public abstract float[] ladeWavMix(String name, int sampleanzahl);
2150    //Gleich nur Mix aus linkem und rechtem Kanal laden (aus 44100 2x16Bit extrahieren)    
2151    public abstract float[] ladeWavMixLoop(String name, int sampleanzahl); 
2152    /**
2153    *  L\u00e4dt wav-Files, die als 16-Bit Mono-Files vorliegen
2154    */
2155    public abstract float[] ladeWavMono(String name); 
2156    /**
2157     * Shows wav-data as Java-short-Array
2158     */
2159    public abstract void showAsShortArray(float[] wav);    
2160}
2161public class Wav implements iWav
2162{
2163    private PApplet pap;
2164  
2165    public Wav(PApplet pap)
2166    {
2167        this.pap = pap;
2168    }
2169
2170
2171
2172    public void saveWav(String name, float[][] data)
2173    {
2174          double gross = 0.5f*(255.0f*256.0f + 255.0f);
2175          double gesamt_links,gesamt_rechts;
2176          byte[] dat = new byte[44+data[0].length*4];
2177          for(int i=0;i<data[0].length;i++)
2178          {
2179               float links = data[0][i];
2180               float rechts = data[1][i];
2181               
2182               gesamt_links = Math.round(  (links+gross)*gross  );
2183               gesamt_rechts = Math.round(  (rechts+gross)*gross  );
2184               
2185
2186               int lo_links = (int)gesamt_links%256;
2187               int lo_rechts = (int)gesamt_rechts%256;
2188               int hi_links = (int)gesamt_links/256;
2189               int hi_rechts = (int)gesamt_rechts/256;
2190
2191               hi_links-=128;
2192               hi_rechts-=128;
2193               
2194               byte left_lo = (byte)lo_links;
2195               byte left_hi = (byte)hi_links;
2196               byte right_lo = (byte)lo_rechts;
2197               byte right_hi = (byte)hi_rechts;
2198               
2199               dat[44+i*4+0] = left_lo;               
2200               dat[44+i*4+1] = left_hi;               
2201               dat[44+i*4+2] = right_lo;               
2202               dat[44+i*4+3] = right_hi;               
2203          }
2204          
2205          //Kopf f\u00fcr wav-Datei passend erzeugen:
2206          int[] kopf = {  82,   73,   70,   70,   52,  177,    2,    0,   87,   65, 
2207                                86,   69,  102,  109,  116,   32,   16,    0,    0,    0, 
2208                                 1,    0,    2,    0,   68,  172,    0,    0,   16,  177, 
2209                                 2,    0,    4,    0,   16,    0,  100,   97,  116,   97, 
2210                                16,  177,    2,    0  };
2211          int[] zahl1 = {0,0,0,0};
2212          int[] zahl2 = {0,0,0,0};
2213
2214          int  z1 = data[0].length*4+36;
2215          int  z2 = data[0].length*4;
2216          //KOPF bilden
2217          for(int i=0;i<4;i++)
2218          {  
2219              zahl1[i] = z1%256;
2220              z1/=256;
2221              kopf[4+i] = zahl1[i];
2222          }
2223          for(int i=0;i<4;i++)
2224          {
2225              zahl2[i] = z2%256;
2226              z2/=256;
2227              kopf[40+i] = zahl2[i];
2228          }
2229          
2230          for(int i=0;i<kopf.length;i++)
2231//              dat[i] = (byte)(kopf[i]-128);
2232              dat[i] = (byte)(kopf[i]);
2233              
2234          pap.saveBytes(name,dat);    
2235    }
2236
2237    public byte[] toByte(float[][] data)
2238    {
2239          double gross = 0.5f*(255.0f*256.0f + 255.0f);
2240          double gesamt_links,gesamt_rechts;
2241          byte[] dat = new byte[data[0].length*4];
2242          for(int i=0;i<data[0].length;i++)
2243          {
2244               float links = data[0][i];
2245               float rechts = data[1][i];
2246               
2247               gesamt_links = Math.round(  (links+gross)*gross  );
2248               gesamt_rechts = Math.round(  (rechts+gross)*gross  );
2249               
2250
2251               int lo_links = (int)gesamt_links%256;
2252               int lo_rechts = (int)gesamt_rechts%256;
2253               int hi_links = (int)gesamt_links/256;
2254               int hi_rechts = (int)gesamt_rechts/256;
2255
2256               hi_links-=128;
2257               hi_rechts-=128;
2258               
2259               byte left_lo = (byte)lo_links;
2260               byte left_hi = (byte)hi_links;
2261               byte right_lo = (byte)lo_rechts;
2262               byte right_hi = (byte)hi_rechts;
2263               
2264               dat[i*4+0] = left_lo;               
2265               dat[i*4+1] = left_hi;               
2266               dat[i*4+2] = right_lo;               
2267               dat[i*4+3] = right_hi;               
2268          }
2269          
2270          return dat;
2271    }
2272
2273    /**
2274     * L\u00e4dt eine Stereo-Wav-Datei in zwei getrennten float-Arrays, Wertebereich [-1,+1]
2275     */
2276    public float[][] ladeWav(String name)
2277    {
2278            int zl,zh,lo,gesamt;
2279            float gross = 0.5f*(255.0f*256.0f + 255.0f);
2280          
2281            byte[] dat = pap.loadBytes(name);
2282
2283            int anz = dat.length;
2284          
2285            float[][] y = new float[2][(anz-44)/4];                        
2286            //float[][] y = new float[2][sampleanzahl];                        
2287
2288            int inx=44;
2289            
2290            for(int i=0;i<y[0].length;i++)
2291            {
2292                 zl = dat[inx++];
2293                 zh = dat[inx++];
2294                 if(zl>127)
2295                     zl-=256;
2296            
2297                 if(zh>127)
2298                     zh-=256;
2299
2300                 lo     =  zl;
2301                 if(lo<0)
2302                     lo+=256;
2303                 gesamt = (zh+128)*256;                
2304                 gesamt+=lo;
2305                
2306                 y[0][i] = ((float)gesamt - gross)/gross;        
2307
2308                 zl = dat[inx++];
2309                 zh = dat[inx++];
2310                 if(zl>127)
2311                     zl-=256;
2312            
2313                 if(zh>127)
2314                     zh-=256;
2315
2316                 lo     =  zl;
2317                 if(lo<0)
2318                     lo+=256;
2319                 gesamt = (zh+128)*256;
2320                
2321                 gesamt+=lo;
2322                
2323                 y[1][i] = ((float)gesamt - gross)/gross;        
2324                 
2325            }    
2326            
2327            return y;
2328    }
2329  
2330    /**
2331    *   Pr\u00fcft, ob pfad+"/ton"+midi+".wav" im Original existiert, sucht andernfalls nach Nachbarn und interpoliert diese.    
2332    */
2333    int[] tests = {-1,1,-2,2,-3,3,-4,4,-5,5,-6,6,-7,7,-8,8,-9,9,-10,10,-11,11,-12,12};
2334    public float[][] ladeWavInterpolate(String pfad,int midi)
2335    {
2336        String name = pfad+"/ton"+midi+".wav";
2337        if(  (new File(name)).exists()  )
2338        {
2339             return ladeWav(name);    
2340        }
2341        else
2342        {
2343             for(int i=0;i<tests.length;i++)
2344             {
2345                 name = pfad+"/ton"+(midi+tests[i])+".wav";
2346                 if(  (new File(name)).exists()  )
2347                 {
2348                     float[][] data =  ladeWav(name);
2349                     
2350                     double ineu = Math.pow(2.0f,(1.0f/12.0f)*(double)(-tests[i]));
2351                     
2352                     float[][] data_neu = new float[2][(int)Math.round((double)data[0].length/ineu)+1];
2353                     
2354                     for(int k=0;k<data_neu[0].length;k++)
2355                     {
2356                           double inx = ineu*(double)k;
2357                           double inx1 = Math.floor(inx);
2358                           double inx2 = Math.ceil(inx);
2359                           int iinx1 = (int)inx1;
2360                           int iinx2 = (int)inx2;
2361                           
2362                           if(iinx1==iinx2 && iinx1>=0 && iinx1<data[0].length)
2363                           {
2364                                data_neu[0][k] = data[0][iinx1];
2365                                data_neu[1][k] = data[1][iinx1];
2366                           }
2367                           else if(iinx1!=iinx2 && iinx1>=0 && iinx1<data[0].length && iinx2>=0 && iinx2<data[0].length)
2368                           {
2369                                double anteil2 = inx - inx1;  
2370                                double anteil1 = 1.0f - anteil2;  
2371                                data_neu[0][k] = (float)anteil1*data[0][iinx1] + (float)anteil2*data[0][iinx2];
2372                                data_neu[1][k] = (float)anteil1*data[1][iinx1] + (float)anteil2*data[1][iinx2];
2373                           }
2374                           
2375                     }
2376                     
2377                     return data_neu;
2378                 }
2379             }
2380        }
2381        
2382        return null;
2383    }  
2384    
2385    /**
2386     * L\u00e4dt eine Stereo-Wav-Datei in zwei getrennten float-Arrays, Wertebereich [-1,+1]
2387     */
2388    public float[][] ladeWav(String name, int sampleanzahl)
2389    {
2390            int zl,zh,lo,gesamt;
2391            float gross = 0.5f*(255.0f*256.0f + 255.0f);
2392          
2393            byte[] dat = pap.loadBytes(name);
2394
2395            int anz = dat.length;
2396          
2397            //double[][] y = new double[2][(anz-44)/4];                        
2398            float[][] y = new float[2][sampleanzahl];                        
2399
2400            int inx=44;
2401            
2402            for(int i=0;i<y[0].length;i++)
2403            {
2404                 zl = dat[inx++];
2405                 zh = dat[inx++];
2406                 if(zl>127)
2407                     zl-=256;
2408            
2409                 if(zh>127)
2410                     zh-=256;
2411
2412                 lo     =  zl;
2413                 if(lo<0)
2414                     lo+=256;
2415                 gesamt = (zh+128)*256;
2416                
2417                 gesamt+=lo;
2418                
2419                 y[0][i] = ((float)gesamt - gross)/gross;        
2420
2421                 zl = dat[inx++];
2422                 zh = dat[inx++];
2423                 if(zl>127)
2424                     zl-=256;
2425            
2426                 if(zh>127)
2427                     zh-=256;
2428
2429                 lo     =  zl;
2430                 if(lo<0)
2431                     lo+=256;
2432                 gesamt = (zh+128)*256;
2433                
2434                 gesamt+=lo;
2435                
2436                 y[1][i] = ((float)gesamt - gross)/gross;        
2437                 
2438            }    
2439            
2440            return y;
2441    }
2442
2443    /**
2444     * L\u00e4dt eine Stereo-Wav-Datei, die dann zu einem Kanal gemischt wird und als float-Array zur\u00fcck gegeben wird.
2445     */
2446    public float[] ladeWavMix(String name) //Gleich nur Mix aus linkem und rechtem Kanal laden (aus 44100 2x16Bit extrahieren)
2447    {
2448            int zl,zh,lo,gesamt;
2449            float gross = 0.5f*(255.0f*256.0f + 255.0f);
2450          
2451            byte[] dat = pap.loadBytes(name);
2452
2453            int anz = dat.length;
2454          
2455            //double[][] y = new double[2][(anz-44)/4];                        
2456            //float[] y = new float[sampleanzahl];                        
2457            float[] y = new float[(anz-44)/4];                        
2458
2459            int inx=44;
2460            
2461            for(int i=0;i<y.length;i++)
2462            {
2463                 zl = dat[inx++];
2464                 zh = dat[inx++];
2465                 if(zl>127)
2466                     zl-=256;
2467            
2468                 if(zh>127)
2469                     zh-=256;
2470
2471                 lo     =  zl;
2472                 if(lo<0)
2473                     lo+=256;
2474                 gesamt = (zh+128)*256;
2475                
2476                 gesamt+=lo;
2477                
2478                 //y[0][i] = ((float)gesamt - gross)/gross;        
2479                 y[i] = 0.5f*((float)gesamt - gross)/gross;        
2480
2481                 zl = dat[inx++];
2482                 zh = dat[inx++];
2483                 if(zl>127)
2484                     zl-=256;
2485            
2486                 if(zh>127)
2487                     zh-=256;
2488
2489                 lo     =  zl;
2490                 if(lo<0)
2491                     lo+=256;
2492                 gesamt = (zh+128)*256;
2493                
2494                 gesamt+=lo;
2495                
2496                 //y[1][i] = ((float)gesamt - gross)/gross;        
2497                 y[i] += 0.5f*((float)gesamt - gross)/gross;        
2498                 
2499            }    
2500            
2501            return y;    
2502    }
2503    
2504    /**
2505     * L\u00e4dt eine Stereo-Datei, mixt sie zu Mono und baut sie zu einer loop-baren Variante
2506     * zusammen:<br/>
2507     * [AB] a=A ausblenden, b=B einblenden<br/>
2508     * ab + ba<br/>
2509     */
2510    public float[] ladeWavMixLoop(String name) //Gleich nur Mix aus linkem und rechtem Kanal laden (aus 44100 2x16Bit extrahieren)
2511    {
2512          float[] AB = ladeWavMix(name);   
2513          for(int i=0;i<AB.length/2;i++)
2514          {
2515              AB[i] = AB[i]*(1.0f - (float)i/(float)(AB.length/2)-1);
2516              int ii = AB.length-1-i;
2517              AB[ii] = AB[ii]*(1.0f - (float)i/(float)(AB.length/2)-1);
2518          }   
2519          
2520          for(int i=0;i<AB.length/2;i++)
2521          {
2522              int ii = AB.length/2+i;
2523              float a = AB[i];
2524              float b = AB[ii];
2525              AB[i] = a+b;
2526              AB[ii] = a+b;
2527          }   
2528          return AB;
2529    }
2530
2531    public float[] ladeWavMix(String name, int sampleanzahl) //Gleich nur Mix aus linkem und rechtem Kanal laden (aus 44100 2x16Bit extrahieren)
2532    {
2533         float[][] stereo = ladeWav(name,sampleanzahl);
2534         for(int i=0;i<stereo[0].length;i++)
2535             stereo[0][i] = 0.5f*(stereo[0][i]+stereo[1][i]);
2536         return stereo[0];    
2537    }
2538    
2539    public float[] ladeWavMixLoop(String name, int sampleanzahl) //Gleich nur Mix aus linkem und rechtem Kanal laden (aus 44100 2x16Bit extrahieren)
2540    {
2541         float[][] stereo = ladeWav(name,sampleanzahl);
2542         for(int i=0;i<stereo[0].length;i++)
2543             stereo[0][i] = 0.5f*(stereo[0][i]+stereo[1][i]);
2544         float[] AB = stereo[0];   
2545         for(int i=0;i<AB.length/2;i++)
2546         {
2547              AB[i] = AB[i]*(1.0f - (float)i/(float)(AB.length/2)-1);
2548              int ii = AB.length-1-i;
2549              AB[ii] = AB[ii]*(1.0f - (float)i/(float)(AB.length/2)-1);
2550         }   
2551          
2552         for(int i=0;i<AB.length/2;i++)
2553         {
2554              int ii = AB.length/2+i;
2555              float a = AB[i];
2556              float b = AB[ii];
2557              AB[i] = a+b;
2558              AB[ii] = a+b;
2559         }   
2560         return AB;
2561         
2562    }
2563    
2564    /**
2565    *  L\u00e4dt wav-Files, die als 16-Bit Mono-Files vorliegen
2566    */
2567    public float[] ladeWavMono(String name) 
2568    {
2569            int zl,zh,lo,gesamt;
2570            float gross = 0.5f*(255.0f*256.0f + 255.0f);
2571          
2572            byte[] dat = pap.loadBytes(name);
2573
2574            int anz = dat.length;
2575          
2576            //double[][] y = new double[2][(anz-44)/4];                        
2577            //float[] y = new float[sampleanzahl];                        
2578            //float[] y = new float[(anz-44)/4];                        
2579            float[] y = new float[(anz-44)/2];                        
2580
2581            int inx=44;
2582            
2583            for(int i=0;i<y.length;i++)
2584            {
2585                 zl = dat[inx++];
2586                 zh = dat[inx++];
2587                 if(zl>127)
2588                     zl-=256;
2589            
2590                 if(zh>127)
2591                     zh-=256;
2592
2593                 lo     =  zl;
2594                 if(lo<0)
2595                     lo+=256;
2596                 gesamt = (zh+128)*256;
2597                
2598                 gesamt+=lo;
2599                
2600                 //y[0][i] = ((float)gesamt - gross)/gross;        
2601                 y[i] = ((float)gesamt - gross)/gross;                         
2602            }    
2603            
2604            return y;
2605    }
2606    
2607    /**
2608     * Shows wav-data as Java-short-Array
2609     */
2610    public void showAsShortArray(float[] wav)
2611    {
2612         PApplet.println();
2613         PApplet.println("private short[] data = {");
2614         for(int i=0;i<wav.length;i++)
2615         {
2616              if(i<wav.length-1)
2617                 PApplet.print((int)PApplet.round((wav[i]*32000.0f))+",");
2618              else   
2619                 PApplet.print((int)PApplet.round((wav[i]*32000.0f)));
2620                 
2621              if(i%200==0 && i>0)   
2622                  PApplet.println();
2623         }
2624         PApplet.println();
2625         PApplet.println("};");
2626         
2627    }
2628    
2629    public void ueberlappendVerketten(String quelle1, String quelle2, String ziel, int samples_ueberlappung)
2630    {
2631         float[][] q1 = ladeWav(quelle1);
2632         float[][] q2 = ladeWav(quelle2);
2633         
2634         float[][] z = new float[2][q1[0].length+q2[0].length-samples_ueberlappung];
2635         
2636         for(int i=0;i<q1[0].length;i++)
2637         {
2638              z[0][i] = q1[0][i];
2639              z[1][i] = q1[1][i];
2640         }
2641         for(int i=0;i<q2[0].length;i++)
2642         {
2643              z[0][i+q1[0].length-samples_ueberlappung] += q2[0][i];
2644              z[1][i+q1[1].length-samples_ueberlappung] += q2[1][i];
2645         }
2646         
2647         saveWav(ziel,z);         
2648    }
2649    
2650}
2651  public void settings() {  size(1280,640); }
2652  static public void main(String[] passedArgs) {
2653    String[] appletArgs = new String[] { "MODULO_1003_STEREO" };
2654    if (passedArgs != null) {
2655      PApplet.main(concat(appletArgs, passedArgs));
2656    } else {
2657      PApplet.main(appletArgs);
2658    }
2659  }
2660}