Thursday, June 9, 2011

aLife cellular automata with sound output

Warning: a typo creating a bug in this, needs repair.

import javax.sound.sampled.*;
import java.util.Random;
/**
 * 
 */
public class Alife
   {

    private double frequency = 1000.0;
    private double rad = 0.5 * Math.PI;
    private double volume = 256.0; 
    private int byteSize = 10000;
    
    
    public Alife(int myByteSize, double myFrequency, double myRad, double myVolume ) {
     byteSize =myByteSize;
     frequency = myFrequency;
     rad = myRad;
     volume = myVolume;
    }
    
    
   
    public void aByte() {
      Random r = new Random();
     try
     {
      AudioFormat af = new
      AudioFormat( (float)byteSize, 8, 1, true, true );
  
      
      DataLine.Info info = new
      DataLine.Info ( SourceDataLine.class, af );
      SourceDataLine source =
      (SourceDataLine) AudioSystem.getLine( info );
      source.open( af );
      source.start();
      byte[] buf = new byte[byteSize];
      int bufLess = buf.length - 10;
      int localPop = 0;
      int deaths = 0;
      int births = 0;
      int currentPop = 0;
      int iterations = 0;
     //  RULE 1 Any live cell with fewer than two live neighbours dies, as if caused by under-population.
     //  RULE 2 Any live cell with two or three live neighbours lives on to the next generation.
     //  RULE 3 Any live cell with more than three live neighbours dies, as if by overcrowding.
     //  RULE 4 Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction.
      boolean firstRun = true;
      while (true) {     
        iterations++; 
 localPop = 0;
        deaths = 0;
        births = 0;
        currentPop = 0;
        rad = rad + 0.1;
        if (rad>1.0) {rad=0.0;}
        for ( int i=0; i<buf.length; i++ ) {
    
        if (volume>512) {volume=0;}
        if (firstRun == false) {       
        if (i > 10) {
          if (i < bufLess) {
           if (buf[i-1]>0.0) {localPop++;} 
    if (buf[i+1]>0.0) {localPop++;} 
    if (buf[i-2]>0.0) {localPop++;} 
    if (buf[i+2]>0.0) {localPop++;} 
           // GOT A LOCAL POPULATION COUNT ABOVE     
                     if ((buf[i]<0.1) && (localPop==3))  { rad=r.nextGaussian();frequency++;volume++;  } // RULE 4
        else { if ( (buf[i]>0.0) && (localPop>3) ) {rad=0.0; frequency--; } // RULE 3
                    else { if ( (buf[i]>0.0) && (localPop<2) ) {rad=0.0;frequency--;volume--; } // RULE 1
                  else { rad=rad+0.1 ; volume++;frequency++; } // RULE 2
                        }
        }
                  } 
          }      
   }
        if (buf[i]>0) {currentPop++;} else {deaths++;} 
       buf[i] = (byte)( Math.sin( rad * frequency / byteSize  ) * volume  );
           }
  
      source.write( buf, 0, buf.length );
      source.write( buf, buf.length, 0 );
      source.write( buf, 0, currentPop );
      source.write( buf, deaths, 0 );
      firstRun = false;    
      System.out.println( "current pop:" + currentPop );
      System.out.println( "deaths:" + deaths );
      System.out.println( "iterations:" + iterations );

      }

      // source.drain();
      // source.stop();
      // source.close(); 
      
      
      
     }
     catch ( Exception e )
     {
      System.out.println( e );
     }

    }

 public static void main(String[] args) {
  int byteSize = 10000;
  double frequency = 500.0;
  double myRad = 0.2 * Math.PI;
  double volume = 256.0;
  Alife line1 = new Alife(byteSize, frequency, myRad, volume);
  line1.aByte();
 }


 
   }



No comments: