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