import processing.sound.*; import soundtrack.optical.*; SoundtrackOptical soundtrack; SoundFile playback; String soundtrackFile = "PS1.wav"; // make sure this is in your sketch's data folder int exportFPS = 24; // desired frames per second float volume = 1.0; int dpi = 2400; String type = "variable area"; String pitch = "short"; boolean positive = false; float audioDuration; int totalFramesToExport; boolean exporting = true; void setup() { size(213, 620, P2D); // match your optical size frameRate(exportFPS); soundtrack = new SoundtrackOptical(this, soundtrackFile, dpi, volume, type, pitch, positive); playback = new SoundFile(this, soundtrackFile); audioDuration = playback.duration(); // in seconds totalFramesToExport = floor(audioDuration * exportFPS); // e.g. 20.2s * 24 = 484 frames println("Audio duration: " + audioDuration + " seconds"); println("Total frames to export: " + totalFramesToExport); playback.play(); // for reference only } void draw() { int frameToRender = frameCount - 1; if (exporting && frameToRender < totalFramesToExport) { // Generate optical frame soundtrack.frame(0, 0, frameToRender); // Add white frame number on black box in bottom-left String frameText = str(frameToRender); textSize(16); textAlign(LEFT, BOTTOM); // Measure text width and height float padding = 4; float textW = textWidth(frameText) + padding * 2; float textH = textAscent() + textDescent() + padding * 2; float x = 5; float y = height - 5; // Draw black box noStroke(); fill(0); // black rect(x - padding, y - textH + padding, textW, textH); // Draw white number fill(255); // white text(frameText, x, y); // Save the frame as a PNG String filename = "frame_" + nf(frameToRender, 4) + ".png"; saveFrame(filename); println("Saved: " + filename); } else { println("Export complete."); noLoop(); // stop draw() after last frame } }