Commit 7b67c9c1 by PLN (Algolia)

viz: v2

parent 9a16f5db
/**
* Background class
* Background class - Improved version
*
* Creates a dynamic cyberpunk background with subtle animations
* Reduced visual noise for better event visibility
*/
class Background {
// Background properties
......@@ -10,19 +11,19 @@ class Background {
color accentColor2;
// Movement properties
float noiseScale = 0.02;
float noiseScale = 0.01; // Reduced from 0.02 for subtler pattern
float noiseOffset = 0;
float noiseSpeed = 0.005;
float noiseSpeed = 0.003; // Reduced from 0.005 for slower movement
// Timing
float cps = 0.5;
float lastCycleTime = 0;
Background() {
// Dark cyberpunk colors
bgColor = color(10, 12, 18);
accentColor1 = color(0, 70, 100);
accentColor2 = color(60, 0, 80);
// Darker cyberpunk colors for better contrast with events
bgColor = color(5, 7, 12); // Darker than original
accentColor1 = color(0, 50, 80); // More subtle
accentColor2 = color(40, 0, 60); // More subtle
}
void update() {
......@@ -39,58 +40,60 @@ class Background {
void display() {
// Create gradient background
noiseDetail(8, 0.5);
noiseDetail(4, 0.4); // Simplified noise
// Fill with base color
// Fill with base color - more transparent for more visible motion trails
noStroke();
fill(bgColor, 40); // Semi-transparent for motion blur effect
fill(bgColor, 30); // Reduced from 40
rect(0, 0, width, height);
// Add subtle noise pattern
float motionFactor = sin(millis() * 0.001) * 0.5 + 0.5;
float motionFactor = sin(millis() * 0.0005) * 0.5 + 0.5; // Slowed from 0.001
loadPixels();
for (int y = 0; y < height; y += 4) {
for (int x = 0; x < width; x += 4) {
// Reduced noise pattern density - iterate every 8 pixels instead of 4
for (int y = 0; y < height; y += 8) {
for (int x = 0; x < width; x += 8) {
float noiseVal = noise(x * noiseScale, y * noiseScale, noiseOffset);
if (noiseVal > 0.7) {
// Only draw higher noise values (reduced density)
if (noiseVal > 0.8) { // Increased from 0.7
color pixelColor;
// Create different zones
if (noiseVal > 0.85) {
if (noiseVal > 0.9) { // Increased from 0.85
// Highlight areas
pixelColor = lerpColor(accentColor1, accentColor2,
sin(x * 0.01 + millis() * 0.0005) * 0.5 + 0.5);
sin(x * 0.005 + millis() * 0.0002) * 0.5 + 0.5);
pixelColor = color(red(pixelColor), green(pixelColor), blue(pixelColor),
20 + 20 * motionFactor);
15 + 10 * motionFactor); // Reduced from 20+20
} else {
// Subtle accent
pixelColor = lerpColor(bgColor, accentColor1, 0.3);
pixelColor = color(red(pixelColor), green(pixelColor), blue(pixelColor), 10);
pixelColor = lerpColor(bgColor, accentColor1, 0.2); // Reduced from 0.3
pixelColor = color(red(pixelColor), green(pixelColor), blue(pixelColor), 8); // Reduced from 10
}
// Draw 4x4 pixel block for better performance
// Draw 8x8 pixel block for better performance and subtler texture
fill(pixelColor);
rect(x, y, 4, 4);
rect(x, y, 8, 8);
}
}
}
// Draw horizontal scan lines
// Draw horizontal scan lines - fewer and more subtle
drawScanlines();
}
void drawScanlines() {
stroke(255, 8);
// Fewer scan lines (every 8 pixels instead of 4)
stroke(255, 5); // Reduced from 8
strokeWeight(1);
for (int y = 0; y < height; y += 4) {
for (int y = 0; y < height; y += 8) {
line(0, y, width, y);
}
// Draw brighter scanline that moves
float movingScanline = (millis() % 5000) / 5000.0 * height;
stroke(255, 15);
float movingScanline = (millis() % 8000) / 8000.0 * height; // Slower movement (5000 to 8000)
stroke(255, 10); // Reduced from 15
strokeWeight(2);
line(0, movingScanline, width, movingScanline);
}
......
/**
* Grid class
* Grid class - Improved version
*
* Creates a cyberpunk grid with pulse effects that react to the music
* Reduced number of lines for cleaner visuals
*/
class Grid {
// Grid properties
......@@ -17,9 +17,18 @@ class Grid {
color gridColor;
color accentColor;
// Reduced line counts for cleaner visuals
int verticalLines = 10; // reduced from 20
int horizontalLines = 8; // reduced from 15
int polarCircles = 5; // reduced from 10
int polarRadials = 8; // reduced from 16
// Alpha values for better visibility
int defaultAlpha = 30; // reduced from 50
Grid() {
gridColor = color(0, 150, 180, 50);
accentColor = color(0, 255, 255, 100);
gridColor = color(0, 150, 180, defaultAlpha);
accentColor = color(0, 255, 255, 80);
}
void update() {
......@@ -44,25 +53,31 @@ class Grid {
void drawStandardGrid() {
strokeWeight(1);
// Draw vertical lines
float verticalSpacing = width / 20.0;
for (int i = 0; i <= 20; i++) {
// Draw vertical lines (reduced count)
float verticalSpacing = width / (float)verticalLines;
for (int i = 0; i <= verticalLines; i++) {
float x = i * verticalSpacing;
float intensity = pulseIntensity * (1 - abs((x / width) - 0.5) * 2);
// Only draw lines with enough visibility
if (intensity > 0.05 || i % 2 == 0) {
stroke(lerpColor(gridColor, accentColor, intensity));
line(x, 0, x, height);
}
}
// Draw horizontal lines
float horizontalSpacing = height / 15.0;
for (int i = 0; i <= 15; i++) {
// Draw horizontal lines (reduced count)
float horizontalSpacing = height / (float)horizontalLines;
for (int i = 0; i <= horizontalLines; i++) {
float y = i * horizontalSpacing;
float intensity = pulseIntensity * (1 - abs((y / height) - 0.5) * 2);
// Only draw lines with enough visibility
if (intensity > 0.05 || i % 2 == 0) {
stroke(lerpColor(gridColor, accentColor, intensity));
line(0, y, width, y);
}
}
// Draw horizon line with stronger pulse
stroke(lerpColor(gridColor, accentColor, pulseIntensity));
......@@ -74,21 +89,20 @@ class Grid {
pushMatrix();
translate(width / 2, height / 2);
// Draw circular grid
// Draw circular grid (reduced count)
noFill();
for (int i = 1; i <= 10; i++) {
float radius = i * (min(width, height) / 20.0);
float intensity = pulseIntensity * (1 - (i / 10.0) * 0.8);
for (int i = 1; i <= polarCircles; i++) {
float radius = i * (min(width, height) / (polarCircles * 2.0));
float intensity = pulseIntensity * (1 - (i / (float)polarCircles) * 0.8);
stroke(lerpColor(gridColor, accentColor, intensity));
strokeWeight(1 + intensity * 2);
ellipse(0, 0, radius * 2, radius * 2);
}
// Draw radial lines
int numRadials = 16;
for (int i = 0; i < numRadials; i++) {
float angle = i * TWO_PI / numRadials;
// Draw radial lines (reduced count)
for (int i = 0; i < polarRadials; i++) {
float angle = i * TWO_PI / polarRadials;
float intensity = pulseIntensity * 0.8;
stroke(lerpColor(gridColor, accentColor, intensity));
......@@ -102,7 +116,7 @@ class Grid {
}
void drawHexGrid() {
float hexSize = 40;
float hexSize = 60; // Increased from 40 for fewer hexagons
float horizontalSpacing = hexSize * 1.5;
float verticalSpacing = hexSize * sqrt(3);
......@@ -110,8 +124,8 @@ class Grid {
strokeWeight(1 + pulseIntensity * 2);
noFill();
for (int row = -1; row < height / verticalSpacing + 1; row++) {
for (int col = -1; col < width / horizontalSpacing + 1; col++) {
for (int row = -1; row < height / verticalSpacing + 1; row += 2) { // Skip rows
for (int col = -1; col < width / horizontalSpacing + 1; col += 2) { // Skip columns
float xCenter = col * horizontalSpacing + ((row % 2 == 0) ? 0 : horizontalSpacing / 2);
float yCenter = row * verticalSpacing;
......@@ -119,7 +133,7 @@ class Grid {
float distFromCenter = dist(xCenter, yCenter, width/2, height/2) / (width/2);
float intensity = pulseIntensity * (1 - distFromCenter * 0.7);
if (intensity > 0.05) {
if (intensity > 0.05 || (row % 4 == 0 && col % 4 == 0)) {
stroke(lerpColor(gridColor, accentColor, intensity));
drawHexagon(xCenter, yCenter, hexSize);
}
......
/**
* ParVaguesViz - Cyberpunk TidalCycles Visualizer
* ParVaguesViz - Cyberpunk TidalCycles Visualizer (Improved)
*
* A Processing-based visualizer that works with SuperDirt OSC messages
* to create cyberpunk-style visualizations for TidalCycles performances.
......@@ -37,9 +37,9 @@ MetadataSystem metadataSystem;
SampleAnalyzer sampleAnalyzer;
// UI settings
boolean debug = false;
boolean debug = true; // Start with debug ON to troubleshoot
boolean showHelp = false;
boolean showMetadata = false;
boolean showMetadata = true; // Show metadata by default for better visibility
PFont debugFont;
PFont titleFont;
PFont metadataFont;
......@@ -51,7 +51,10 @@ float currentCycle = 0;
float elapsedTime = 0;
float lastBeatTime = 0;
// Colors (cyberpunk palette)
// Settings for improved visibility
float fadeAmount = 20; // Lower = more motion blur, higher = clearer screen
// Colors (enhanced cyberpunk palette) - Increased brightness
color[] orbitColors = {
#00FFFF, // Cyan (d1 - kick)
#FF00FF, // Magenta (d2 - snare)
......@@ -71,6 +74,10 @@ color[] orbitColors = {
#FFFFFF
};
// OSC message receive counter and timestamp for debugging
int oscMessageCount = 0;
float lastOscTime = 0;
void setup() {
// Apply Processing 4.x compatibility fixes
checkProcessingVersion();
......@@ -80,9 +87,15 @@ void setup() {
frameRate(60);
smooth(8);
// Initialize OSC
// Initialize OSC with enhanced error handling
try {
oscP5 = new OscP5(this, listenPort);
superdirtAddress = new NetAddress("127.0.0.1", listenPort);
println("OSC initialized on port " + listenPort);
} catch (Exception e) {
println("ERROR initializing OSC: " + e.getMessage());
println("Try restarting SuperDirt and this visualizer");
}
// Initialize components
trackManager = new TrackManager();
......@@ -105,13 +118,17 @@ void setup() {
// Print startup message
println("ParVaguesViz started");
println("Listening for SuperDirt OSC messages on port " + listenPort);
println("CONTROLS: D=Debug, H=Help, G=GridStyle, F=Fullscreen, R=Reset, M=Metadata");
// Generate a test pattern to verify visualization is working
generateTestPattern();
}
void draw() {
// Update timing
elapsedTime = millis() / 1000.0;
// Clear background with fade effect
// Clear background with fade effect (lower alpha for more motion trails)
background.update();
background.display();
......@@ -144,10 +161,29 @@ void draw() {
if (showHelp) {
drawHelp();
}
// Check for OSC timeout (no messages received in the last 5 seconds)
if (oscMessageCount > 0 && millis() - lastOscTime > 5000) {
// Draw OSC timeout warning
fill(255, 0, 0, 200);
textAlign(CENTER);
textSize(18);
text("WARNING: No OSC messages received in the last 5 seconds", width/2, 50);
text("Check that SuperDirt is running and sending to port " + listenPort, width/2, 75);
}
}
// Handle OSC messages
void oscEvent(OscMessage msg) {
// Update OSC stats
oscMessageCount++;
lastOscTime = millis();
// Detailed debug logging for OSC messages
if (debug) {
println("OSC message received: " + msg.addrPattern());
}
// Check for metadata messages
if (msg.addrPattern().equals("/parvagues/metadata")) {
metadataSystem.processMetadataMessage(msg);
......@@ -172,32 +208,46 @@ void handleDirtMessage(OscMessage msg) {
float gain = 1.0;
float pan = 0.5;
// Debug output
if (debug) {
println("Processing dirt/play message: " + msg.typetag());
}
// Extract all parameters from the message
try {
for (int i = 0; i < msg.typetag().length(); i++) {
String paramName = msg.get(i).stringValue();
if (paramName.equals("orbit")) {
if (paramName.equals("orbit") && i+1 < msg.typetag().length()) {
orbit = msg.get(i+1).intValue();
}
else if (paramName.equals("s")) {
else if (paramName.equals("s") && i+1 < msg.typetag().length()) {
sound = msg.get(i+1).stringValue();
}
else if (paramName.equals("cycle")) {
else if (paramName.equals("cycle") && i+1 < msg.typetag().length()) {
cycle = msg.get(i+1).floatValue();
}
else if (paramName.equals("delta")) {
else if (paramName.equals("delta") && i+1 < msg.typetag().length()) {
delta = msg.get(i+1).floatValue();
}
else if (paramName.equals("gain")) {
else if (paramName.equals("gain") && i+1 < msg.typetag().length()) {
gain = msg.get(i+1).floatValue();
}
else if (paramName.equals("pan")) {
else if (paramName.equals("pan") && i+1 < msg.typetag().length()) {
pan = msg.get(i+1).floatValue();
}
}
} catch (Exception e) {
println("Error processing OSC message: " + e.getMessage());
}
// Only process valid messages with an orbit
if (orbit >= 0) {
// Debug output
if (debug) {
println("Event: orbit=" + orbit + ", sound=" + sound + ", gain=" + gain + ", pan=" + pan);
}
// Update metadata system with sample information
metadataSystem.updateFromSample(orbit, sound);
......@@ -230,6 +280,10 @@ void updateCPS(OscMessage msg) {
// Update components with new timing
grid.setCPS(cps);
background.setCPS(cps);
if (debug) {
println("CPS updated: " + cps + " (BPM: " + bpm + ")");
}
}
}
......@@ -237,25 +291,40 @@ void updateCPS(OscMessage msg) {
void keyPressed() {
if (key == 'd' || key == 'D') {
debug = !debug;
println("Debug mode: " + (debug ? "ON" : "OFF"));
} else if (key == 'h' || key == 'H') {
showHelp = !showHelp;
} else if (key == 'g' || key == 'G') {
grid.toggleStyle();
println("Grid style changed");
} else if (key == 'f' || key == 'F') {
// Use the compatible fullscreen toggle
handleFullscreenToggle();
println("Toggled fullscreen");
} else if (key == 'r' || key == 'R') {
// Reset all visuals
trackManager.reset();
particleSystem.reset();
println("Visualization reset");
// Generate test pattern after reset
generateTestPattern();
} else if (key == 'm' || key == 'M') {
// Toggle metadata display
showMetadata = !showMetadata;
println("Metadata display: " + (showMetadata ? "ON" : "OFF"));
} else if (key == 't' || key == 'T') {
// Generate test pattern
generateTestPattern();
println("Test pattern generated");
}
}
// Debug information display
void drawDebugInfo() {
fill(0, 180);
noStroke();
rect(5, 5, 300, 150, 5);
fill(255);
textFont(debugFont);
textAlign(LEFT);
......@@ -265,11 +334,12 @@ void drawDebugInfo() {
text("Cycle: " + nf(currentCycle, 0, 2), 10, 50);
text("Active Tracks: " + trackManager.getActiveTrackCount(), 10, 65);
text("Particles: " + particleSystem.getParticleCount(), 10, 80);
text("Tracked Samples: " + sampleAnalyzer.getSampleCount(), 10, 95);
text("OSC Messages: " + oscMessageCount, 10, 95);
text("Last OSC: " + nf((millis() - lastOscTime)/1000, 0, 1) + "s ago", 10, 110);
// Add hint about metadata
// Add hints
fill(200);
text("Press 'M' to toggle metadata display", 10, 125);
text("T = Test Pattern, M = Metadata, H = Help", 10, 140);
}
// Draw metadata overlay
......@@ -295,6 +365,7 @@ void drawMetadataOverlay() {
if (activeOrbits.size() == 0) {
text("No active tracks", width - 300, y);
text("Try pressing T to generate a test pattern", width - 300, y + 25);
} else {
for (Integer orbit : activeOrbits) {
TrackMetadata metadata = metadataSystem.getMetadata(orbit);
......@@ -307,7 +378,8 @@ void drawMetadataOverlay() {
// Draw most recent sample
fill(200);
if (metadata.recentSamples.size() > 0) {
text("Sample: " + metadata.recentSamples.get(metadata.recentSamples.size() - 1), width - 300, y + 40);
text("Sample: " + metadata.recentSamples.get(metadata.recentSamples.size() - 1),
width - 300, y + 40);
}
// Add analyzed features if available
......@@ -334,15 +406,16 @@ void drawMetadataOverlay() {
// Help information display
void drawHelp() {
fill(0, 180);
// Semi-transparent background
fill(0, 220);
noStroke();
rect(width/2 - 200, height/2 - 150, 400, 300);
rect(width/2 - 200, height/2 - 170, 400, 340, 10);
fill(255);
textFont(titleFont);
textAlign(CENTER);
text("ParVaguesViz Controls", width/2, height/2 - 120);
text("ParVaguesViz Controls", width/2, height/2 - 140);
textFont(debugFont);
textAlign(LEFT);
......@@ -354,22 +427,63 @@ void drawHelp() {
"F - Toggle fullscreen",
"R - Reset visuals",
"M - Toggle metadata display",
"T - Generate test pattern",
"",
"Automatically visualizes tracks d1-d16",
"Special visualization for d8 breakbeats",
"No TidalCycles configuration needed"
"No TidalCycles configuration needed",
"",
"If no events are visible, check that:",
"1. SuperDirt is running on port 57120",
"2. Your TidalCycles pattern is active",
"3. Press T to generate a test pattern"
};
for (int i = 0; i < helpText.length; i++) {
text(helpText[i], width/2 - 180, height/2 - 80 + i * 20);
text(helpText[i], width/2 - 180, height/2 - 100 + i * 20);
}
}
// Check if currently fullscreen
boolean isFullScreen() {
if (isProcessing4) {
return width == displayWidth && height == displayHeight;
} else {
return width == displayWidth && height == displayHeight;
// Generate a test pattern to verify visualization is working
void generateTestPattern() {
// Create events for different tracks to check visualization
for (int orbit = 0; orbit < 12; orbit++) {
String sound = "";
float gain = 0.8;
float pan = 0.5;
float delta = 0.25;
// Create appropriate sample names for each orbit
switch(orbit) {
case 0:
sound = "kick";
break;
case 1:
sound = "snare";
break;
case 2:
sound = "hihat";
break;
case 3:
sound = "bass";
break;
case 7:
sound = "jungle_breaks";
break;
default:
sound = "sample" + orbit;
}
// Create test event
trackManager.addEvent(orbit, sound, gain, pan, delta);
metadataSystem.updateFromSample(orbit, sound);
// Add test metadata
TrackMetadata metadata = metadataSystem.getMetadata(orbit);
metadata.name = "Test d" + (orbit + 1);
}
// Trigger effects
grid.trigger(0.5);
glitchEffect.trigger(0.2);
}
/**
* TrackManager class
* TrackManager class - Improved version
*
* Handles the management and visualization of TidalCycles tracks (d1-d16)
* Each track has its own visual representation and effects
* Enhanced visibility for events and track visualization
*/
class TrackManager {
ArrayList<Track> tracks;
......@@ -36,15 +36,15 @@ class TrackManager {
}
void display() {
// Display active events first (behind tracks)
for (SoundEvent event : activeEvents) {
event.display();
}
// Display all tracks
for (Track track : tracks) {
track.display();
}
// Display all active events
for (SoundEvent event : activeEvents) {
event.display();
}
}
void addEvent(int orbit, String sound, float gain, float pan, float delta) {
......@@ -57,30 +57,41 @@ class TrackManager {
// Create new event with appropriate visualization style based on orbit and sound
SoundEvent event = createEvent(orbit, sound, gain, pan, delta);
activeEvents.add(event);
// Debug output to help identify events
if (debug) {
println("Added event: orbit=" + orbit + ", sound=" + sound + ", gain=" + gain);
}
}
SoundEvent createEvent(int orbit, String sound, float gain, float pan, float delta) {
// Different visualization based on orbit (track number)
// ENHANCED: Increased default size and visibility for all event types
if (sound.contains("break") || sound.contains("jungle")) {
return new BreakbeatEvent(orbit, sound, gain, pan, delta);
}
switch(orbit) {
case 0: // d1 - typically kick
return new KickEvent(orbit, sound, gain, pan, delta);
return new KickEvent(orbit, sound, gain * 1.5, pan, delta);
case 1: // d2 - typically snare
return new SnareEvent(orbit, sound, gain, pan, delta);
return new SnareEvent(orbit, sound, gain * 1.5, pan, delta);
case 2: // d3 - typically hats or percussion
return new HihatEvent(orbit, sound, gain, pan, delta);
return new HihatEvent(orbit, sound, gain * 1.3, pan, delta);
case 3: // d4 - typically bass
return new BassEvent(orbit, sound, gain, pan, delta);
return new BassEvent(orbit, sound, gain * 1.5, pan, delta);
case 7: // d8 - typically breaks
return new BreakbeatEvent(orbit, sound, gain * 1.2, pan, delta);
default: // Other instruments
if (sound.contains("suns") || sound.contains("key")) {
return new MelodicEvent(orbit, sound, gain, pan, delta);
} else if (sound.contains("break") || sound.contains("jungle")) {
return new BreakEvent(orbit, sound, gain, pan, delta);
return new MelodicEvent(orbit, sound, gain * 1.4, pan, delta);
} else if (sound.contains("voice") || sound.contains("voc")) {
return new VoiceEvent(orbit, sound, gain, pan, delta);
return new VoiceEvent(orbit, sound, gain * 1.3, pan, delta);
} else if (sound.contains("riser") || sound.contains("fx")) {
return new FXEvent(orbit, sound, gain, pan, delta);
return new FXEvent(orbit, sound, gain * 1.5, pan, delta);
} else {
return new SoundEvent(orbit, sound, gain, pan, delta);
return new SoundEvent(orbit, sound, gain * 1.4, pan, delta);
}
}
}
......@@ -119,10 +130,10 @@ class TrackManager {
}
/**
* Track class
* Track class - Improved version
*
* Represents a single TidalCycles track (d1-d16)
* Maintains state and provides visual representation
* Enhanced visibility and layout
*/
class Track {
int orbit;
......@@ -148,41 +159,42 @@ class Track {
this.historyGain = new ArrayList<Float>();
// Visual initialization
this.baseHeight = height / 32.0;
// Visual initialization - INCREASED heights for better visibility
this.baseHeight = height / 24.0; // Changed from 32.0
this.targetHeight = baseHeight;
this.currentHeight = baseHeight;
}
void update() {
// Decay activity over time
activity *= 0.95;
// Slower decay for better visibility
activity *= 0.97; // Changed from 0.95
// Update height with smooth animation
currentHeight = lerp(currentHeight, targetHeight, 0.2);
// Reset target height if activity is low
if (activity < 0.1) {
if (activity < 0.05) { // Changed from 0.1
targetHeight = baseHeight;
active = false;
}
}
void display() {
if (activity < 0.05) return; // Don't display inactive tracks
if (activity < 0.02) return; // Lower threshold for visibility - Changed from 0.05
float yPos = map(orbit, 0, 15, height * 0.1, height * 0.9);
float trackWidth = width * 0.8;
float xOffset = width * 0.1;
// Better vertical distribution - Changed from 0.1 and 0.9 to 0.05 and 0.95
float yPos = map(orbit, 0, 15, height * 0.05, height * 0.95);
float trackWidth = width * 0.9; // Wider tracks - Changed from 0.8
float xOffset = width * 0.05; // Changed from 0.1
// Draw track background with trail effect
noStroke();
fill(red(trackColor), green(trackColor), blue(trackColor), activity * 150);
fill(red(trackColor), green(trackColor), blue(trackColor), activity * 180); // Increased from 150
rect(xOffset, yPos - currentHeight/2, trackWidth, currentHeight, 5);
// Draw glowing edge
stroke(trackColor, activity * 255);
strokeWeight(2);
strokeWeight(2 + activity); // Increased from 2
noFill();
rect(xOffset, yPos - currentHeight/2, trackWidth, currentHeight, 5);
......@@ -192,16 +204,24 @@ class Track {
// Draw activity meter
float meterWidth = map(activity, 0, 1, 0, trackWidth);
noStroke();
fill(trackColor, activity * 200);
fill(trackColor, activity * 220); // Increased from 200
rect(xOffset, yPos - currentHeight/3, meterWidth, currentHeight/3, 5);
// Add label for active tracks
if (activity > 0.5) {
fill(255, activity * 255);
textAlign(LEFT, CENTER);
textSize(12);
text("d" + (orbit + 1), xOffset + 10, yPos);
}
}
void drawGlow(float x, float y, float w, float h) {
// Create glow effect using multiple transparent strokes
// Enhanced glow effect
for (int i = 0; i < 5; i++) {
float alpha = map(i, 0, 4, activity * 100, 0);
float alpha = map(i, 0, 4, activity * 150, 0); // Increased from 100
stroke(red(trackColor), green(trackColor), blue(trackColor), alpha);
strokeWeight(i * 2 + 2);
strokeWeight(i * 2 + 3); // Increased from i*2+2
noFill();
rect(x, y - currentHeight/2, w, currentHeight, 5);
}
......@@ -220,8 +240,8 @@ class Track {
historyGain.remove(0);
}
// Update visual properties
targetHeight = baseHeight + (gain * baseHeight * 2);
// Update visual properties - MORE DRAMATIC HEIGHT CHANGE
targetHeight = baseHeight + (gain * baseHeight * 4); // Changed from 2
}
boolean isActive() {
......@@ -238,7 +258,7 @@ class Track {
}
/**
* SoundEvent class
* SoundEvent class - Improved version
*
* Base class for visualizing individual sound events
*/
......@@ -264,16 +284,16 @@ class SoundEvent {
this.pan = pan;
this.delta = delta;
this.birthTime = millis();
this.lifespan = 500 + (gain * 500); // Duration based on gain
this.lifespan = 800 + (gain * 700); // Longer duration - Changed from 500
// Initialize visuals
this.eventColor = orbitColors[orbit];
this.size = 20 + (gain * 60);
this.size = 30 + (gain * 80); // Larger size - Changed from 20+(gain*60)
this.alpha = 255;
// Position based on pan value
float xPos = map(pan, 0, 1, width * 0.3, width * 0.7);
float yPos = map(orbit, 0, 15, height * 0.2, height * 0.8);
// Better spread across the screen - Changed from width*0.3/0.7 to 0.2/0.8
float xPos = map(pan, 0, 1, width * 0.2, width * 0.8);
float yPos = map(orbit, 0, 15, height * 0.1, height * 0.9);
this.position = new PVector(xPos, yPos);
}
......@@ -281,11 +301,11 @@ class SoundEvent {
// Calculate age
float age = millis() - birthTime;
// Fade out as the event ages
// Slower fade out
alpha = map(age, 0, lifespan, 255, 0);
// Grow size slightly over time
size = 20 + (gain * 60) * (1 + (age / lifespan) * 0.5);
size = 30 + (gain * 80) * (1 + (age / lifespan) * 0.6); // Changed from 20+(gain*60)*(1+(age/lifespan)*0.5)
}
void display() {
......@@ -302,10 +322,10 @@ class SoundEvent {
void drawGlow(float x, float y, float s) {
for (int i = 0; i < 5; i++) {
float glowAlpha = map(i, 0, 4, alpha * 0.5, 0);
float glowAlpha = map(i, 0, 4, alpha * 0.7, 0); // Increased from 0.5
fill(red(eventColor), green(eventColor), blue(eventColor), glowAlpha);
noStroke();
ellipse(x, y, s + (i * 10), s + (i * 10));
ellipse(x, y, s + (i * 12), s + (i * 12)); // Increased from i*10
}
}
......
# ParVagues Visualization Metadata
# Format: orbit:name:type:prop1=value1,prop2=value2,...
0:Test d1:kick
1:Test d2:snare
2:Drums:hihat
#!/bin/bash
# Direct launcher script for ParVaguesViz
# This uses what we've learned works on your system
# Get the full path to the sketch directory
SKETCH_DIR=$(cd "$(dirname "$0")" && pwd)
# Simple launcher script for ParVaguesViz
# Colors for terminal output
GREEN='\033[0;32m'
BLUE='\033[0;34m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
NC='\033[0m' # No Color
# Print banner
......@@ -22,20 +19,61 @@ echo "██║ ██║ ██║██║ ██║ ╚████╔
echo "╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═══╝ ╚═╝ ╚═╝ ╚═════╝ ╚═════╝ ╚══════╝╚══════╝"
echo -e " TIDALCYCLES VISUALIZER\n${NC}"
# Set Java options to fix module restrictions
export _JAVA_OPTIONS="--add-opens=java.desktop/sun.awt.X11=ALL-UNNAMED --add-opens=java.desktop/java.awt=ALL-UNNAMED -Djava.awt.headless=false -Dawt.useSystemAAFontSettings=on -Dswing.aatext=true"
# Get the full path to the sketch directory
SKETCH_DIR=$(cd "$(dirname "$0")" && pwd)
# Check if Processing is installed
if ! command -v processing &> /dev/null && ! command -v processing-java &> /dev/null; then
echo -e "${RED}Error: Processing not found!${NC}"
echo "Please make sure Processing is installed and in your PATH."
echo "You can download it from: https://processing.org/download"
exit 1
fi
echo -e "${YELLOW}Starting ParVaguesViz...${NC}"
echo -e "${BLUE}Controls:${NC}"
# Check if SuperDirt might be running
if ! command -v lsof &> /dev/null || ! lsof -i :57120 &> /dev/null; then
echo -e "${YELLOW}Warning: No process seems to be listening on port 57120.${NC}"
echo "Make sure SuperDirt is running in SuperCollider before starting TidalCycles."
echo -e "Typical SuperCollider startup: ${GREEN}SuperDirt.start${NC}"
echo ""
fi
# Print troubleshooting tips
echo -e "${YELLOW}Troubleshooting tips:${NC}"
echo "1. If no visualization appears, press 'T' to generate a test pattern"
echo "2. Debug mode is ON by default, press 'D' to toggle it"
echo "3. Make sure SuperDirt is running on port 57120"
echo -e "\n${BLUE}Controls:${NC}"
echo " D - Toggle debug info"
echo " H - Toggle help screen"
echo " G - Change grid style"
echo " F - Toggle fullscreen"
echo " R - Reset visualization"
echo " M - Toggle metadata display"
echo
echo " T - Generate test pattern"
echo ""
# Set Java options to fix module restrictions (important for Processing 4.x)
export _JAVA_OPTIONS="--add-opens=java.desktop/sun.awt.X11=ALL-UNNAMED --add-opens=java.desktop/java.awt=ALL-UNNAMED -Djava.awt.headless=false -Dawt.useSystemAAFontSettings=on -Dswing.aatext=true"
# Launch Processing with the full path to the main sketch
# Launch Processing sketch
echo -e "${GREEN}Launching visualizer...${NC}"
cd "$SKETCH_DIR"
processing "$SKETCH_DIR/ParVaguesViz.pde"
echo "Sketch directory: $SKETCH_DIR"
# Try different launch methods
if command -v processing &> /dev/null; then
# Preferred method: Use the Processing GUI
cd "$SKETCH_DIR"
processing "$SKETCH_DIR/ParVaguesViz.pde"
elif command -v processing-java &> /dev/null; then
# Alternative: Use processing-java command line
processing-java --sketch="$SKETCH_DIR" --run
else
# Last resort: Try direct Java execution
echo -e "${RED}Could not find Processing launcher. Trying direct execution...${NC}"
cd "$SKETCH_DIR"
java -jar "$SKETCH_DIR/ParVaguesViz.jar"
fi
echo -e "${GREEN}Visualizer closed.${NC}"
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment