SoundtrackOptical/src/soundtrack/optical/SoundtrackOptical.java

183 lines
5.1 KiB
Java
Executable File

package soundtrack.optical;
import processing.core.*;
import processing.sound.*;
public class SoundtrackOptical {
String TYPE = "dual variable area";
int DPI = 2880;
boolean POSITIVE = true;
float VOLUME = (float) 1.0;
String pitch = "long";
String FILEPATH;
float IN = (float) 25.4;
float FRAME_H = (float) 7.62;
float FRAME_W = (float) (12.52 - 10.26);
float DPMM = (float) (DPI / IN);
int FRAME_H_PIXELS = (int) Math.round(DPMM * FRAME_H);
int SAMPLE_RATE = FRAME_H_PIXELS * 24;
int DEPTH = (int) Math.round(DPMM * FRAME_W);
int RAW_RATE = 0;
int RAW_FRAME_H = 0;
int RAW_FRAME_W = 0;
int LINE_W = 0;
float DENSITY = 0;
int LEFT = 0;
int FRAMES = 0;
int i = 0;
float max = 0;
float min = 0;
float compare;
float[] frameSample;
SoundFile soundfile;
PGraphics raw;
PApplet parent;
/**
* @constructor
*
*
* @param parent {PApplet} Parent process (usually this)
* @param soundtrackFile {String} Path to soundtrackFile
* @param dpi {Integer} Target DPI of printer
* @param volume {Float} Volume of output soundtrack, 0 to 1.0
* @param type {String} Type of soundtrack either "unilateral", "variable area", "dual variable area", "multiple variable area", "variable density"
* @param pitch {String} Pitch of the film, either "long" for projection or "short" for camera stock
* @param positive {Boolean} Whether or not soundtrack is positive or negative
*/
@SuppressWarnings("static-access")
public SoundtrackOptical (PApplet parent, String soundtrackFile, int dpi, float volume, String type, String pitch, boolean positive ) {
this.parent = parent;
FILEPATH = soundtrackFile;
TYPE = type;
DPI = dpi;
VOLUME = volume;
POSITIVE = positive;
FRAME_H = (float) ((pitch == "long") ? 7.62 : 7.605);
DPMM = DPI / IN;
FRAME_H_PIXELS = (int) Math.round(DPMM * FRAME_H);
SAMPLE_RATE = FRAME_H_PIXELS * 24;
DEPTH = (int) Math.floor(DPMM * FRAME_W);
soundfile = new SoundFile(parent, FILEPATH);
RAW_RATE = soundfile.sampleRate();
RAW_FRAME_H = Math.round(RAW_RATE / 24);
RAW_FRAME_W = Math.round(((RAW_RATE / 24) / FRAME_H ) * FRAME_W);
FRAMES = (int) Math.ceil(soundfile.frames() / RAW_FRAME_H);
frameSample = new float[RAW_FRAME_H];
raw = parent.createGraphics(RAW_FRAME_W, RAW_FRAME_H);//mode option?
for (int x = 0; x < soundfile.frames(); x++) {
compare = soundfile.read(x);
if (compare > max) {
max = compare;
}
if (compare < min) {
min = compare;
}
}
}
public void draw (int X, int Y) {
frame(X, Y, parent.frameCount);
}
@SuppressWarnings("static-access")
public void frame(int X, int Y, int frameNumber) {
if (frameNumber != -1) {
i = frameNumber;
}
if (i >= FRAMES) {
return;
}
raw.beginDraw();
//draw bg
raw.noStroke();
if (POSITIVE) {
raw.fill(0);
} else {
raw.fill(255);
}
if (TYPE != "variable density") {
raw.rect(0, 0, RAW_FRAME_W, RAW_FRAME_H);
}
//draw top
if (POSITIVE) {
raw.stroke(255);
} else {
raw.stroke(0);
}
soundfile.read(i * RAW_FRAME_H, frameSample, 0, RAW_FRAME_H);
for (int y = 0; y < RAW_FRAME_H; y++) {
if (TYPE != "variable density") {
LINE_W = Math.round(parent.map(frameSample[y], min, max, (float) 0, RAW_FRAME_W * VOLUME));
}
if (TYPE == "unilateral") {
unilateral(y, LINE_W);
} else if (TYPE == "dual unilateral") {
/* TODO!!!! */
} else if (TYPE == "single variable area" || TYPE == "variable area") {
variableArea(y, LINE_W);
} else if (TYPE == "dual variable area") {
dualVariableArea(y, LINE_W);
} else if (TYPE == "multiple variable area" || TYPE == "maurer") {
multipleVariableArea(y, LINE_W);
} else if (TYPE == "variable density") {
variableDensity(y);
}
}
raw.endDraw();
parent.image(raw, X, Y, DEPTH, FRAME_H_PIXELS);
if (frameNumber == -1) {
i++;
}
}
private void unilateral (int y, int LINE_W) {
raw.line(0, y, LINE_W, y);
}
private void variableArea (int y, int LINE_W) {
LEFT = Math.round((RAW_FRAME_W - LINE_W) / 2);
raw.line(LEFT, y, LEFT + LINE_W, y);
}
private void dualVariableArea (int y, int LINE_W) {
LEFT = Math.round((RAW_FRAME_W / 4) - (LINE_W / 4));
raw.line(LEFT, y, LEFT + (LINE_W / 2), y);
raw.line(LEFT + (RAW_FRAME_W / 2), y, LEFT + (RAW_FRAME_W / 2) + (LINE_W / 2), y);
}
private void multipleVariableArea (int y, int LINE_W) {
LEFT = Math.round((RAW_FRAME_W / 16) - (LINE_W / 16));
for (int x = 1; x < 7; x++) {
raw.line(LEFT + ((x * RAW_FRAME_W) / 8), y, LEFT + ((x * RAW_FRAME_W) / 8) + (LINE_W / 8), y);
}
}
@SuppressWarnings("static-access")
private void variableDensity(int y) {
DENSITY = parent.map(frameSample[y], min, max, (float) 0, 255 * VOLUME);
if (POSITIVE) {
raw.stroke(DENSITY);
} else {
raw.stroke(255 - DENSITY);
}
raw.line(0, y, RAW_FRAME_W, y);
}
}