Here is the full code for wave generation!
A few things to consider:
./frames. Then, consider mounting a tmpfs file system so it resides in RAM.
#include <stdio.h>
#define ROW 128
#define COL 128
#define SIZE ROW*COL
#define EXP 12
#define ONE 0x1000 //one with 12 binary places
#define FRAMES 200 //we're gonna do 200 frames
int mulf(int a, int b) {
int res = a * b;
//for a right bit shift, you have to handle the cases where result is negative
if (res < 0) return -(-res >> EXP);
return res >> EXP;
}
const int c2 = 0x400; //This is 1/4 in this fixed point system, so c^2 = 0.25
void compute_next(int *next, int *curr, int *prev) {
for (int x=ROW; x<SIZE-ROW; x+=ROW) {
for (int y=1; y<ROW-1; y++) {
int index = x+y; // no need to recompute x+y everywhere!
int dt = (curr[index]<<1) - prev[index];
int ds = (curr[index]<<2) - curr[index+1] - curr[index-1] - curr[index+ROW] - curr[index-ROW];
next[index] = dt - mulf(ds, c2);
}
}
//edge along y=0
for (int x=0; x<SIZE; x+=ROW) next[x] = 0;
//edge along y=ROW-1
for (int x=ROW-1; x<SIZE; x+=ROW) next[x] = 0;
//edge along x=0
for (int y=0; y<ROW; y++) next[y] = 0;
//edge along x=SIZE-ROW
for (int y=SIZE-ROW; y<SIZE; y++) next[y] = 0;
}
void generate_pgm(int *array, int *pgmidx) {
char filename[64];
sprintf(filename, "./frames/frame%03d.pgm", *pgmidx);
FILE *fd = fopen(filename, "wb+");
fprintf(fd, "P5\n%d %d\n255\n", ROW, COL);
for (int i=0; i<SIZE; i++) {
int temp = 0x7f + mulf(0x7f,array[i]); //Normalize with zero being middle grey
if(temp > 0xff) temp = 0xff;
else if(temp < 0) temp = 0;
fputc(temp, fd);
}
*pgmidx = *pgmidx + 1;
fclose(fd);
}
int main(int argc, char **argv) {
int buf0[SIZE];
int buf1[SIZE];
int buf2[SIZE];
//Now have pointers point to these buffers, so it's possible to switch between them
int *next = buf0;
int *curr = buf1;
int *prev = buf2;
//initialise arrays
for (int i=0; i<SIZE; i++) next[i] = curr[i] = prev[i] = 0;
//Trigger one wave in the middle
int MIDX = ROW>>1;
int MIDY = COL>>1;
curr[MIDX+MIDY*ROW] = ONE<<2; //Let's trigger a wave with amplitude 4
int pgmidx = 0; //frame name index
int framecount = 0; //This is used to render only every 8th frame!
for (int i=0; i<FRAMES<<3; i++) { // important to multiply FRAME with 8
compute_next(next, curr, prev);
framecount++;
if(framecount&0b1000) {
framecount = 0;
generate_pgm(next, &pgmidx);
}
// swap the buffers!
int *ptr = prev;
prev = curr;
curr = next;
next = ptr;
}
return 0;
}