%% EPS 109 Project  - Day and Night (Cellular Automaton) Soundboard
% Ryan O'Bannon 
% 12/2/15 
% Much of the code used to produce sound comes from Mark Belbin and Athan Bourganos' Matlab Juke Box 
% This code plays Beat It by Michael Jackson using three P-3 spaceships from the Day and Night cellular automaton and
%   a custom soundboard
% Day and Night cellular automaton: B3678/S34678
% Use periodic boundary conditions

clear
close all
clc

%% Set initial conditions
maxX = 50; % board size
maxY = 50;
A = zeros(maxX,maxY);
startX1 = 10;
startY1 = 45;
startX2 = 25;
startY2 = 45;
startX3 = 40;
startY3 = 45;

% DIAGONAL SPACESHIP Stage 1 (DAY/NIGHT)
B = [0 1 1 1 0;
     1 0 1 1 1;
     1 1 0 0 0;
     1 1 0 0 0;
     0 1 0 0 0];

Bdim = size(B);
A(startY1 - 2:startY1 + 2,startX1 - 2:startX1 + 2) = B; % add diagonal spaceship to A at specified location

% DIAGONAL SPACESHIP Stage 2 (DAY/NIGHT)
C = [0 0 0 1 0 0;
     0 0 1 1 1 1;
     0 1 1 0 1 0;
     1 1 0 0 1 0;
     0 1 1 1 0 0;
     0 1 0 0 0 0];

Cdim = size(C);
A(startY2 - 3:startY2 + 2,startX2 - 3:startX2 + 2) = C; % add diagonal spaceship to A at specified location

% DIAGONAL SPACESHIP Stage 3 (DAY/NIGHT)
D = [0 0 1 1 0;
     0 1 1 0 1;
     1 1 1 1 1;
     1 0 1 0 0;
     0 1 1 0 0];

Ddim = size(D);
A(startY3 - 2:startY3 + 2,startX3 - 2:startX3 + 2) = D; % add diagonal spaceship to A at specified location

% display initial pattern in colored grid
pcolor(A)
suptitle('''Day and Night'' Soundboard - "Beat It" by Michael Jackson')
set(gca,'Xtick',1,'XTickLabel',{})
set(gca,'Ytick',1,'YTickLabel',{})
colormap('default')

%% Generate sound based on board condition

% Sound frequency
Fs = 2000;

% Note frequencies
G88 = 97.9989;
Ab88 = 103.826;
D8 = 146.832;
Gb8 = 184.997;
Ab8 = 207.652;
A8 = 220.000;
Bb8 = 233.082;
B8 = 246.942;
C = 261.626;
Db = 277.183;
D = 293.665;
Eb = 311.127;
Enote = 329.628;
F = 349.228;
Gb = 369.994;
G = 391.995;
Ab = 415.305;
Anote = 440.000;
Bb = 466.164;
B = 493.883;
c = 523.251;
db = 554.365;
d = 587.330;
eb = 622.254;
e = 659.255;
f = 698.456;
gb = 739.989;
g = 783.991;
ab = 830.609;
a = 880.000;
bb = 932.328;
b = 987.767;
c8 = 1046.50;
db8 = 1108.73;
d8 = 1174.66;
eb8 = 1244.51;
e8 = 1318.51;

Notes = [G88; Ab88; D8; Gb8; Ab8;
        A8; Bb8; B8; C; Db;
        D; Eb; Enote; F; Gb;
        G; Ab; Anote; Bb; B;
        c; db; d; eb; e;
        f; gb; g; ab; a;
        bb; b; c8; db8; d8;
        eb8; e8];
    
t = 1/Fs:1/Fs:(.1); % time vec for sound
        
% Initialize "soundboard" with notes corresponding to each cell
% Numbers at the end of each line correspond to initial spaceship stage.
% For example, all lines that end with 1 are the same spaceship that
% started at stage 1 (see above section)

% Beat It by Michael Jackson (divided by measure):

Soundboard = zeros(maxX,maxY);
Soundboard(8,47) = B; % 1
Soundboard(22,46) = B; % 2
Soundboard(7,46) = B; % 1
Soundboard(37,46) = Anote; % 3
Soundboard(21,45) = B; % 2
Soundboard(6,45) = Anote; % 1
Soundboard(36,45) = B; % 3

Soundboard(20,44) = d; % 2
Soundboard(5,44) = B; % 1
Soundboard(35,44) = Anote; % 3
Soundboard(4,43) = B; % 1
Soundboard(3,42) = B; % 1

Soundboard(33,42) = B; % 3
Soundboard(17,41) = B; % 2
Soundboard(2,41) = B; % 1
Soundboard(32,41) = B; % 3
Soundboard(16,40) = B; % 2
Soundboard(1,40) = B; % 1
Soundboard(31,40) = Anote; % 3
Soundboard(15,39) = G; % 2

Soundboard(50,39) = Anote; % 1
Soundboard(30,39) = G; % 3
Soundboard(14,38) = B; % 2
Soundboard(48,37) = B; % 1

Soundboard(12,36) = Anote; % 2
Soundboard(47,36) = G; % 1
Soundboard(27,36) = Enote; % 3
Soundboard(11,35) = D; % 2
Soundboard(46,35) = Enote; % 1
Soundboard(10,34) = Enote; % 2
Soundboard(45,34) = Enote; % 1

Soundboard(25,34) = Gb; % 3
Soundboard(9,33) = Enote; % 2
Soundboard(44,33) = D; % 1
Soundboard(24,33) = B8; % 3
Soundboard(8,32) = D; % 2
Soundboard(23,32) = Enote; % 3

Soundboard(42,31) = G; % 1
Soundboard(22,31) = Enote; % 3
Soundboard(40,29) = Enote; % 1

Soundboard(4,28) = Gb; % 2
Soundboard(39,28) = D; % 1

Soundboard(17,26) = B; % 3
Soundboard(36,25) = B; % 1
Soundboard(16,25) = B; % 3
Soundboard(50,24) = Anote; % 2
Soundboard(35,24) = B; % 1
Soundboard(15,24) = Anote; % 3
Soundboard(49,23) = B; % 2

Soundboard(34,23) = d; % 1
Soundboard(14,23) = B; % 3
Soundboard(48,22) = Anote; % 2
Soundboard(13,22) = B; % 3
Soundboard(12,21) = B; % 3

Soundboard(46,20) = B; % 2
Soundboard(31,20) = B; % 1
Soundboard(11,20) = B; % 3
Soundboard(45,19) = B; % 2
Soundboard(30,19) = B; % 1
Soundboard(10,19) = B; % 3
Soundboard(44,18) = Anote; % 2
Soundboard(29,18) = G; % 1

Soundboard(9,18) = Anote; % 3
Soundboard(43,17) = G; % 2
Soundboard(28,17) = B; % 1
Soundboard(7,16) = B; % 3

Soundboard(26,15) = Anote; % 1
Soundboard(6,15) = G; % 3
Soundboard(40,14) = Enote; % 2
Soundboard(25,14) = D; % 1
Soundboard(5,14) = Enote; % 3
Soundboard(24,13) = Enote; % 1
Soundboard(4,13) = Enote; % 3

Soundboard(38,12) = Gb; % 2
Soundboard(23,12) = Enote; % 1
Soundboard(3,12) = D; % 3
Soundboard(37,11) = B8; % 2
Soundboard(22,11) = D; % 1
Soundboard(36,10) = Enote; % 2

Soundboard(1,10) = G; % 3
Soundboard(35,9) = Enote; % 2
Soundboard(49,8) = B; % 3
Soundboard(33,7) = B; % 2

Soundboard(18,7) = d; % 1
Soundboard(48,7) = B; % 3
Soundboard(32,6) = Anote; % 2
Soundboard(47,6) = B; % 3
Soundboard(16,5) = Anote; % 1

Soundboard(30,4) = B; % 2
Soundboard(15,4) = B; % 1
Soundboard(14,3) = G; % 1
Soundboard(44,3) = G; % 3

Soundboard(43,2) = B; % 3
Soundboard(27,1) = B; % 2
Soundboard(25,49) = B; % 2

Soundboard(40,49) = B; % 3
Soundboard(24,48) = B; % 2
Soundboard(9,48) = B; % 1
Soundboard(39,48) = d; % 3
Soundboard(8,47) = B; % 1
Soundboard(38,47) = B; % 3

Soundboard(7,46) = B; %1

Soundboard = Soundboard';

%% Run Simulation
% Lifespan conditions
iterations = 153;
soundvec = []; % initialize sound vector to be exported as .wav file 
counter = 0; % counter used to name PNG files
tic % start timer 

for n = 1:iterations
    Anew = A;
    for x = 1:maxX % iterate over every cell
        for y = 1:maxX
            
            xR = x+1;
            xL = x-1;
            yU = y+1;
            yD = y-1;
            
            % apply periodic boundary conditions
            if x == maxX
                xR = 1;
            elseif x == 1
                xL = maxX;
            end

            if y == maxY
                yU = 1;
            elseif y == 1
                yD = maxY;
            end

            % count neighbors
            nb = 0;
            for i = [xL, x, xR]
                for j = [yD, y, yU]
                    if A(i,j) == 1;
                        nb = nb + 1;
                    end
                end
            end
            if A(x,y) == 1
                nb = nb - 1; % because we counted the cell itself
            end
            
            % implement birth/survival conditions
            if A(x,y) == 0
                if nb == 3 || nb == 6 || nb == 7 || nb == 8 % cell becomes alive if 3,6,7, or 8 neighbors
                    Anew(x,y) = 1;
                end
            else % if == 1
                if nb == 0 ||nb == 1 || nb == 2 || nb == 5 %|| nb == 6 || nb == 7 || nb == 8
                        Anew(x,y) = 0; % cell dies if only 0, 1, 2, or 5 neighbors
                end
                
            end
        end
    end
    A = Anew;
    
    % display pattern in colored grid
    suptitle('''Day and Night'' Soundboard - "Beat It" by Michael Jackson')
    pcolor(A)
    set(gca,'Xtick',1,'XTickLabel',{})
    set(gca,'Ytick',1,'YTickLabel',{})   
    
%   save current figure as PNG file (comment out for faster simulation)
%   saveas(gcf, ['Soundboard_MJ_',sprintf('%03d',counter),'.png'])
%   counter = counter+1;
    
    % check soundboard
    cells = find(A == 1); % all cells where soundboard is 'activated' by Day and Night automaton
    soundsum = 0;
    for i = 1:numel(cells) 
        soundsum = soundsum + sin(Soundboard(cells(i))*2*pi*t); % create sinewave at current note frequency and add all sine waves
    end
    if soundsum ~= 0 
        soundsum = soundsum/max(abs(soundsum)); % normalize note frequencies
    end
    sound(soundsum,Fs) % play sound
    
    time = toc; % end timer
    tic % restart timer 
    waitvec = zeros(1,round(time*Fs)); % this vector adds silence to the saved .wav file so that there is proper spacing between the notes
    soundvec = [soundvec,waitvec,soundsum]; % create final sound vector to be exported as .wav file
  
    pause(.15)
    
end

% save soundvec as a .wav file (comment out when not needed)
%audiowrite('Soundboard_MJ.wav',soundvec,Fs) 