We are about to switch to a new forum software. Until then we have removed the registration on this forum.
As the title says I'm trying to create an ArrayList of SinOsc objects. When I click the mouse I want it to add a new SinOsc object to the ArrayList which will play a sine wave. The sin wave will differ in frequency and amplitude based on its x and y location on the screen. When I remove the SinOsc object from the ArrayList I want the sound to stop as well. These sinOsc objects will also be dynamically moving around the screen based on Boids behaviours that are already defined in this code. So ideally when the mouse is clicked both a boid object (which will be displayed on the screen) and a SinOsc object will be created and the same ones removed when needed. I'm having trouble making this work. Any help is appreciated!
//importing sine sound and declaring array
import processing.sound.*;
ArrayList<SinOsc> sine;
ArrayList<Boid> boids;
float globalScale = .91;
float eraseRadius = 20;
String tool = "boids";
// boid control
float maxSpeed;
float friendRadius;
float crowdRadius;
float avoidRadius;
float coheseRadius;
boolean option_friend = true;
boolean option_crowd = true;
boolean option_avoid = true;
boolean option_noise = true;
boolean option_cohese = true;
// gui crap
int messageTimer = 0;
String messageText = "";
void setup () {
size(700, 700); //3508 pixels x 4961 1754x2480 877, 1240 , just some sizes
textSize(16);
recalculateConstants();
boids = new ArrayList<Boid>();
//sine is new Arraylist with SinOsc sounds in it
sine = new ArrayList<SinOsc>();
}
void recalculateConstants () {
maxSpeed = 2.1 * globalScale;
friendRadius = 60 * globalScale;
crowdRadius = (friendRadius / 1.3);
avoidRadius = 90 * globalScale;
coheseRadius = friendRadius;
}
void draw () {
noStroke();
colorMode(HSB);
fill(0, 100);
rect(0, 0, width, height);
if (tool == "erase") {
noFill();
stroke(0, 100, 260);
rect(mouseX - eraseRadius, mouseY - eraseRadius, eraseRadius * 2, eraseRadius *2);
if (mousePressed) {
erase();
}
} else if (tool == "avoids") {
noStroke();
fill(0, 200, 200);
ellipse(mouseX, mouseY, 15, 15);
}
for (int i = 0; i <boids.size(); i++) {
Boid current = boids.get(i);
current.go();
current.draw();
}
}
void keyPressed () {
if (key == 'q') {
tool = "boids";
} else if (key == 'e') {
tool = "erase";
} else if (key == '-') {
globalScale *= 0.8;
} else if (key == '=') {
globalScale /= 0.8;
} else if (key == '1') {
option_friend = option_friend ? false : true;
} else if (key == '2') {
option_crowd = option_crowd ? false : true;
} else if (key == '3') {
option_avoid = option_avoid ? false : true;
} else if (key == '4') {
option_cohese = option_cohese ? false : true;
} else if (key == '5') {
option_noise = option_noise ? false : true;
}
recalculateConstants();
// screen shot
// if (key == 'p') {
// saveFrame("boidsMaster-######.png");
// }
}
String s(int count) {
return (count != 1) ? "s" : "";
}
String on(boolean in) {
return in ? "on" : "off";
}
void mousePressed () {
switch (tool) {
case "boids":
boids.add(new Boid(mouseX, mouseY));
//adding new sine object/ particle to arraylist
//sine.add(new SinOsc());
//does not recognise play as a function
//sine.play();
break;
}
}
void erase () {
for (int i = boids.size()-1; i > -1; i--) {
Boid b = boids.get(i);
if (abs(b.pos.x - mouseX) < eraseRadius && abs(b.pos.y - mouseY) < eraseRadius) {
boids.remove(i);
//remove sin particle from array
sine.remove(i);
//does not recognise stop as a function
//sine.stop(i);
}
}
}
class Boid {
// main fields
PVector pos;
PVector move;
float shade;
ArrayList<Boid> friends;
// timers
int thinkTimer = 0;
Boid (float xx, float yy) {
move = new PVector(0, 0);
pos = new PVector(0, 0);
pos.x = xx;
pos.y = yy;
thinkTimer = int(random(10));
shade = random(255);
friends = new ArrayList<Boid>();
}
void go () {
increment();
wrap();
if (thinkTimer ==0 ) {
// update our friend array (lots of square roots)
getFriends();
}
flock();
pos.add(move);
}
void flock () {
PVector allign = getAverageDir();
PVector avoidDir = getAvoidDir();
PVector avoidObjects = getAvoidAvoids();
PVector noise = new PVector(random(2) - 1, random(2) -1);
PVector cohese = getCohesion();
allign.mult(1);
if (!option_friend) allign.mult(0);
avoidDir.mult(1);
if (!option_crowd) avoidDir.mult(0);
avoidObjects.mult(3);
if (!option_avoid) avoidObjects.mult(0);
noise.mult(0.1);
if (!option_noise) noise.mult(0);
cohese.mult(1);
if (!option_cohese) cohese.mult(0);
stroke(0, 255, 160);
move.add(allign);
move.add(avoidDir);
move.add(avoidObjects);
move.add(noise);
move.add(cohese);
move.limit(maxSpeed);
shade += (random(2) - 1) ;
shade = (shade + 255) % 255; //max(0, min(255, shade));
}
void getFriends () {
ArrayList<Boid> nearby = new ArrayList<Boid>();
for (int i =0; i < boids.size(); i++) {
Boid test = boids.get(i);
if (test == this) continue;
if (abs(test.pos.x - this.pos.x) < friendRadius &&
abs(test.pos.y - this.pos.y) < friendRadius) {
nearby.add(test);
}
}
friends = nearby;
}
PVector getAverageDir () {
PVector sum = new PVector(0, 0);
//int count = 0;
for (Boid other : friends) {
float d = PVector.dist(pos, other.pos);
// If the distance is greater than 0 and less than an arbitrary amount (0 when you are yourself)
if ((d > 0) && (d < friendRadius)) {
PVector copy = other.move.copy();
copy.normalize();
copy.div(d);
sum.add(copy);
//count++;
}
//if (count > 0) {
// sum.div((float)count);
//}
}
return sum;
}
PVector getAvoidDir() {
PVector steer = new PVector(0, 0);
int count = 0;
for (Boid other : friends) {
float d = PVector.dist(pos, other.pos);
// If the distance is greater than 0 and less than an arbitrary amount (0 when you are yourself)
if ((d > 0) && (d < crowdRadius)) {
// Calculate vector pointing away from neighbor
PVector diff = PVector.sub(pos, other.pos);
diff.normalize();
diff.div(d); // Weight by distance
steer.add(diff);
count++; // Keep track of how many
}
}
if (count > 0) {
//steer.div((float) count);
}
return steer;
}
PVector getAvoidAvoids() {
PVector steer = new PVector(0, 0);
//int count = 0;
return steer;
}
PVector getCohesion () {
PVector sum = new PVector(0, 0); // Start with empty vector to accumulate all locations
int count = 0;
for (Boid other : friends) {
float d = PVector.dist(pos, other.pos);
if ((d > 0) && (d < coheseRadius)) {
sum.add(other.pos); // Add location
count++;
}
}
if (count > 0) {
sum.div(count);
PVector desired = PVector.sub(sum, pos);
return desired.setMag(0.05);
} else {
return new PVector(0, 0);
}
}
void draw () {
noStroke();
fill(255);
pushMatrix();
translate(pos.x, pos.y);
ellipse(0, 0, 5, 5);
popMatrix();
float freqMy = map(pos.y,height,0,0,500);
float ampMy = map(pos.y,0,height,0,1);
float panMx = map(pos.x,0,width,-1,1);
float add= 0;
//sine.set(freqMy,ampMy,add,panMx);
}
// update all those timers!
void increment () {
thinkTimer = (thinkTimer + 1) % 5;
}
void wrap () {
pos.x = (pos.x + width) % width;
pos.y = (pos.y + height) % height;
}
}
class SinOsc {
SinOsc(){
}
}
Doing something like this requires to know about the nature of your data, and exactly how you envision your trigger to work. Here I have implemented the concept based on leading edge crossing. White line is based line. Blue line is the current threshold definition. The data from minim is in a range of -1..+1. When displaying, I multiply this data by a normalization factor which I defined as height/2. I set my threshold to 0.4 based on observations from the printInfo()
function in my code below. Green line shows the data points.
The concept is this. If the wave crosses the threshold, capture this crossing point. Set this crossing point as the center of the display (across the sketch width) which means all the data is shifted either to the left or to the right. Because the display width is 512 and the data buffer is 512, if the data is shifted with respect to the leading edge crossing, then it is natural that either the left end or right end will have no data... these data bins were set to zero (Notice this is because I copy the original data to a temporal array before I reset those containers to zero).
I removed the hsb color definition, added an inversion on the y axis, and instead of calling background()
, I am using a fill with alpha to slowly erased my sketch content. So this creates an effect of memory on the display where you can see that previous waves are attenuated and removed after few iterations, and not immediately in the case you call background()
function.
As in an oscilloscope, I work with the time-amplitude domain. However, the examples of the minim is based on a buffer that provides amplitude only, no time information. Then What I do is that I take the index of the array and I set them to be my time. The amplitude from minim is used as my amplitude data, so I get two internal arrays: time and amplitude which store the data to display.
Kf
//REFERENCE: https://forum.processing.org/two/discussion/28074/how-to-add-a-trigger-to-an-oscilloscope-program#latest // //Title: Oscilloscope trigger based on the leading edge. //Author: Kfrajer, July 15, 2018
import ddf.minim.*;
Minim minim;
AudioInput in;
color white;
WavePacket wp;
void setup()
{
size(512, 200, P2D);
white = color(255);
minim = new Minim(this);
minim.debugOn();
in = minim.getLineIn(Minim.STEREO, 512);
wp=new WavePacket(in.bufferSize());
background(0);
}
void draw()
{
//clone wafeform
wp.loadData(in);
wp.printInfo();
wp.searchHThresholdCrossing();
wp.shiftWaveBasedOnHThreshold();
//This next enables drawing only of those signals above the threshold
//Remove or comment out if you want to see all the signals
if (!wp.thresholdFound()) {
return;
}
fill(0, 60);
rect(0, 0, width, height);
translate(0, height/2);
scale(1, -1);
wp.drawBaseLine();
wp.display();
wp.drawThresold();
}
void stop()
{
in.close();
minim.stop();
super.stop();
}
class WavePacket {
final float NORMFACTOR=height/2;
int len;
FloatList time;
FloatList amp;
float highThreshold;
float idxTimeFirstCrossing;
WavePacket(int n) {
len=n;
time=new FloatList(len);
amp=new FloatList(len);
highThreshold=0.4; //Chosen based on initial observations from printInfo()
println("Size set to ", len);
}
void loadData(AudioInput in) {
for (int i = 0; i < in.bufferSize(); i++) {
time.set(i, i);
amp.set(i, in.left.get(i));
}
}
//It finds index when the curve crosses the threshold for the first time
void searchHThresholdCrossing() {
idxTimeFirstCrossing = -1; //Resets
for (int i = 0; i < in.bufferSize(); i++) {
if (amp.get(i)>=highThreshold) {
idxTimeFirstCrossing=i;
return;
}
}
}
boolean thresholdFound() {
return idxTimeFirstCrossing>=0;
}
void shiftWaveBasedOnHThreshold() {
int middlePoint=(len/2);
//If wave did not cross threshold, then define delta time correction as zero
int deltaTime = thresholdFound() ? int(middlePoint-idxTimeFirstCrossing) : 0;
FloatList tempX=new FloatList();
FloatList tempY=new FloatList();
//Create temporal containers with shifted tinme data
for (int i = 0; i < in.bufferSize(); i++) {
tempX.set(i, time.get(i)+deltaTime);
tempY.set(i, amp.get(i));
}
//Zero original containers
for (int i = 0; i < in.bufferSize() - 1; i++) {
time.set(i, 0);
amp.set(i, 0);
}
//Search for first index
int idx=0;
for (; idx < in.bufferSize(); idx++) {
if (tempX.get(idx)<0)
continue;
break;
}
//println("Threshold:", highThreshold, "idxTimeFirstCrossing", idxTimeFirstCrossing, "idx:", idx);
//Populate arrays with shifted data using temporal holders
for (int j=idx; j<len; j++) {
//println(idx);
//println(int(tempX.get(j)), tempY.get(j));
time.set(int(tempX.get(j)), tempX.get(j));
amp.set(int(tempX.get(j)), tempY.get(j));
}
}
void display() {
// draw the waveforms
stroke(0, 250, 10); //Green
strokeWeight(2);
for (int i = 0; i < in.bufferSize(); i++) {
point(i, amp.get(i)*NORMFACTOR);
}
}
void drawThresold() {
stroke(0, 0, 200); //Blue
strokeWeight(1);
int step=2;
for (int k=0; k<len-step*2; k+=step*2)
line(k, highThreshold*NORMFACTOR, k+step, highThreshold*NORMFACTOR);
}
void drawBaseLine() {
stroke(250); //White
strokeWeight(1);
line(0, 0, width, 0);
}
void printInfo() {
println("Report range: ", amp.min(), amp.max());
println("Report Norm Factor", NORMFACTOR);
}
}
You need to manage your in.bufferSize()
as it has the current data to display. You could create a container made of time-amplitude pair values. Then, one way is to trigger on the leading edge or falling edge of a signal. This can be easily accomplish using a threshold applied to your values. When you find a signal going above the threshold, then you display that position at the center of the screen and the other values should be shifted up or down accordingly.
There is an oscilloscope library in case you don't know about it.
Kf
I was able to learn (with the strategical use of "println") that the code is slowing down when this loop is running:
for ( int i = 0; i< 20; i++) {
aliens.add(new Worker(width/2, height/2, elites.get(j).net));
j++;
if (j >= elites.size()) {
j = 0;
}
}
So somehow adding a new "Worker" is slow. Here is what the constructor looks like:
public Worker(float _x, float _y, NeuralNetwork _net) {
directionsPI = new float [] {0,QUARTER_PI, PI/2, PI/2 + QUARTER_PI, PI, PI + QUARTER_PI, PI + PI/2, PI*2 - QUARTER_PI, PI};
directionalValues = new float [directionsPI.length];
for ( int i = 0; i < directionalValues.length; i++){
directionalValues [i] = 0;
}
_layers = new int[] {16, 30, 16, directionalValues.length};
net = new NeuralNetwork ( _layers, _net);
type = "Worker";
diameter = worker_size;
pos = new PVector (_x, _y);
speed = worker_speed;
cor = workerColor;
hearing_distance = 100;
controls = new String[] {"Evolve Fighter"};
out = minim.getLineOut();
// create a sine wave Oscil, set to 440 Hz, at 0.5 amplitude
wave = new Oscil( 200, 0.5f, Waves.SINE );
fftLinA = new FFT (out.bufferSize(), out.sampleRate());
fftLinA.linAverages(30);
this.registerObserver(tutorial);
collidable = true;
selectable = true;
soundInterval = 10;
fitness = 0;
float ran = random(1);
if ( ran > mutation_chance){
net.Mutate();
}
}
As you can see that it contains a constructor for the other class which is NeuralNetwork which is the constructor that creates a copy of an existing net which is one of the arguments for the Worker. It also runs a "Mutate()" command which makes random changes to the neural network.
anyone know why this is crashing right when it should loop?
import processing.sound.*;
// Declare the processing sound variables
SoundFile sample;
Amplitude rms;
// Declare a scaling factor
float scale=1;
// Declare a smooth factor
float smooth_factor=0.25;
// Used for smoothing
float sum;
PImage img; // The source image
int cellsize = 2; // Dimensions of each cell in the grid
int columns, rows; // Number of columns and rows in our system
public void setup() {
size(800, 1000, P3D);
//fullScreen(P3D);
img = loadImage("..."); // Load the image
columns = img.width / cellsize; // Calculate # of columns
rows = img.height / cellsize; // Calculate # of rows
//Load and play a soundfile and loop it
sample = new SoundFile(this, "...");
sample.loop();
// Create and patch the rms tracker
rms = new Amplitude(this);
rms.input(sample);
}
void draw() {
background(255,0,255);
// Begin loop for columns
for ( int i = 0; i < columns; i++) {
// Begin loop for rows
for ( int j = 0; j < rows; j++) {
int x = i*cellsize + cellsize/2; // x position
int y = j*cellsize + cellsize/2; // y position
int loc = x + y*img.width; // Pixel array location
color c = img.pixels[loc]; // Grab the color
// Calculate a z position as a function of mouseX and pixel brightness
//float z = width/2 * brightness(img.pixels[loc]) - 20.0;
float rms_scaled=sum*width/10 * brightness(img.pixels[loc]) - 20.0;
// smooth the rms data by smoothing factor
sum += (rms.analyze() - sum) * smooth_factor;
// rms.analyze() return a value between 0 and 1. It's
// scaled to height/2 and then multiplied by a scale factor
// Translate to the location, set fill and stroke, and draw the rect
pushMatrix();
//translate(x + 300, y + 250, rms_scaled);
translate(x + 200, y + 200, rms_scaled);
fill(c, 204);
noStroke();
rectMode(CENTER);
rect(0, 0, cellsize, cellsize);
popMatrix();
}
}
}
I have been playing with the Leap Motion for the last couple of days ever since I discovered the "Leap Motion for Processing" library.
The biggest problem that you have is that sometimes the Leap Motion library does not immediately provide data. To demonstrate this I modified example sketch "LM_1_Basics". It can take up to 99 msecs for the Leap Motion to connect, that's a really long time from the sketches point of view.
In your original code you were assuming the the right-hand's position data was available from the very first iteration of the draw(). Unfortunately, initially it isn't, I modified your code to illustrate this problem:
import de.voidplus.leapmotion.*;
import processing.sound.*;
import punktiert.math.Vec;
import punktiert.physics.*;
LeapMotion leap;
SinOsc sine;
Hand leftHand;
Hand rightHand;
float freq;
float amp;
float pos;
PVector hL;
PVector hR;
int teller = 0;
int amount = 100;
// world object
VPhysics physics;
// attractor
BAttraction attr;
void setup() {
//size(displayWidth, 700);
size(1280, 720); // HD 720P
leap = new LeapMotion(this);
sine = new SinOsc(this);
//Start the Sine Oscillator.
sine.play();
sine.amp(amp);
noStroke();
background(#57385c);
//frameRate(30);
smooth();
//set up physics
physics = new VPhysics();
physics.setfriction(0.4f);
// new AttractionForce: (Vec pos, radius, strength)
attr = new BAttraction(new Vec(width * .5f, height * .5f), 400, .01f);
physics.addBehavior(attr);
//
// val for arbitrary radius
float rad = attr.getRadius()/4;
// vector for position
Vec pos = new Vec (random(rad, width/2 - rad), random(rad, height/2 - rad));
// create particle (Vec pos, mass, radius)
VParticle particle = new VParticle(pos, 9, rad);
// add Collision Behavior
particle.addBehavior(new BCollision());
// add particle to world
physics.addParticle(particle);
for (int i = 1; i < amount; i++) {
// val for arbitrary radius
float rad2 = random(2, 20);
// vector for position
Vec pos2 = new Vec(random(rad2, width - rad2), random(rad2, height - rad2));
// create particle (Vec pos, mass, radius)
VParticle particle2 = new VParticle(pos2, 8, rad2);
// add Collision Behavior
particle2.addBehavior(new BCollision());
// add particle to world
physics.addParticle(particle2);
}
}
void draw() {
background(255);
smooth();
for (Hand hand : leap.getHands()) {
boolean handIsLeft = hand.isLeft();
boolean handIsRight = hand.isRight();
leftHand = leap.getLeftHand();
hL = leftHand.getPosition();
if (hL == null) println("No LH data!");
rightHand = leap.getRightHand();
hR = rightHand.getPosition();
if (hR == null) println("No RH data!");
//----------------------- LEFT HAND ----------------------------------
if (handIsLeft) {
text("leftHand-X=" + hL.x, 10, 15); //shows hL.x in sketch
text("leftHand-Y=" + hL.y, 10, 30); //shows hL.y in sketch
text("leftHand-Z=" + hL.z, 10, 45); //shows hL.z in sketch
text("volume(in %)= " + nf(amp*100, 1, -3), 10, 60);
leftHand.draw();
// Map leftHandY van 0.0 to 1.0 voor amplitude (volume)
amp = map(hL.y, 0, height, 1.0, 0.0);
}
sine.amp(amp);
//----------------------- RIGHT HAND ----------------------------------
if (handIsRight) {
text("rightHand-X= " + hR.x, width-160, 15); // shows hL.x in sketch
text("rightHand-Y= " + hR.y, width-160, 30); // shows hL.y in sketch
text("rightHand-Z= " + hR.z, width-160, 45); // shows hL.z in sketch
text("freq(in Hz)= " + nf(freq, 3, -3), width-160, 60);
rightHand.draw();
// Map rightHandX van 100Hz to 800Hz voor frequency
freq = map(hR.x, 0, width, 100.0, 800.0);
}
if (!handIsLeft && handIsRight) {
amp = 0;
}
sine.freq(freq);
} // end for - hand
physics.update();
noFill();
stroke(200, 0, 0);
// set pos to mousePosition
Vec mousePos;
// Deal with right-hand position not yet ready?
// Note: The Leap Motion can take a fraction of a second to start providing data and
// this code is outside the "for (Hand hand : leap.getHands())" for-loop ;-)
if (hR == null) {
println("hR is null!");
mousePos = new Vec(mouseX, mouseY); // Added by Niels
} else {
println("hand x,y = " + hR.x + "," + hR.y);
mousePos = new Vec(hR.x, hR.y); // Added by Niels
}
attr.setAttractor(mousePos);
//ellipse(attr.getAttractor().x, attr.getAttractor().y, attr.getRadius(), attr.getRadius());
noStroke();
fill(0, 125);
teller = 0;
for (VParticle p : physics.particles) {
//println("teller= " + teller);
if (teller == 0) {
p.set(mouseX, mouseY);
ellipse(p.x, p.y, p.getRadius() * 2, p.getRadius() * 2);
teller++;
}
if (teller == 1); {
ellipse(p.x, p.y, p.getRadius() * 2, p.getRadius() * 2);
}
} // end for - p
}
With no call to frameRate() specified Processing will call draw() as quickly as it can. When I run the modified sketch I see the following in the console window:
# Leap Motion Library v2.3.1.6 - Leap Motion SDK v2.3.1+31549 - https://github.com/nok/leap-motion-processing
hR is null!
hR is null!
hR is null!
hR is null!
hR is null!
hR is null!
hR is null!
hR is null!
hR is null!
hR is null!
hR is null!
hR is null!
hR is null!
hR is null!
hR is null!
hR is null!
hR is null!
hR is null!
hR is null!
hR is null!
hR is null!
hR is null!
translate(), or this particular variation of it, is not available with this renderer.
hand x,y = 647.9134,592.4121
hand x,y = 786.3234,530.3577
hand x,y = 767.5345,525.84015
hand x,y = 745.8991,519.5922
So you see you need to handle the situation where you don't immediately get data from the Leap Motion.
The sin line is wrapping the points around the sphere, the contents inside the sin() function kind of like a longitude line. This becomes clear if you play with the contents, like changing the line to float sine = sin((6 * PI * x)/period + 1);
The animation part comes from the x variable which is increased every frame.
The abs() isn't really needed, if you remove it, the effect is still the same. If you remove the sq() wrapping it, the sphere turns into a cylinder.
The third line is multiplying the amplitude(kinda like the lattitude) by the sine(kinda like the longitude) to make it spherical.
Hello Processing Community,I have used this particle case, but there are a few sentences about abs(), sqrt() can't read, can you help me understand this?
float circleSize = 400;
float radius = circleSize/2;
int period = 5; //speed
float x = 0;
float particleY;
float amplitude;
float sineEl;
int randomPart[] = new int[100];
int partSize[] = new int[100];
void setup() {
size(600, 600);
for (int i = 0; i < randomPart.length; i++) {
randomPart[i] = int(random(100, 500));
partSize[i] = int(random(2, 11));
}
}
void draw() {
background(0);
x += 0.01;
for (int yRand = 0; yRand < randomPart.length; yRand++) {
particleY = randomPart[yRand];
float sine = sin((3*PI*x)/period + randomPart[yRand]);//this
amplitude = sqrt(sq(radius) - sq(abs(height/2 - particleY))); // and this
sineEl = width/2 + sine * amplitude;//and this i don't konw
float particleSize = partSize[yRand];
//rotation
pushMatrix();
translate(width/2, height/2);
translate(-width/2, -height/2);
stroke(255);
noStroke();
fill(255);
ellipse(sineEl, particleY, particleSize, particleSize);
println(sineEl, particleY, particleSize, particleSize);
popMatrix();
}
noFill();
stroke(0);
}
@plux -- I believe you want: (untested)
if( player.right.level() > myThreshold ){
doLoudEvent();
}
For related older discussion, see:
Hello, i'm sorry if i'm not posting in the right Category, i'm new to the forum.
I'm working on a project for hiking help for android, and i thought about a functionnality that can be fun, recognizing a bird's singing. The idea is to record a bird that you pass by and the database tells you which species it is.
I'm not a pro of sound processing, but i though that implementing an FFT could help. I was planing on using the FFT to get the max-min amplitude and compare it with the database's pre-processed information, of course i don't plan on using only the min-max indicators.
I inspired my code from this: https://github.com/blanche/shayam/blob/master/java/at.lw.shayam/src/at/lw/shayam/AudioAnalysis.java and as much as i undestand the maths behind the fourrier transform, i don't get everything in that code.
So here are my questions:
The chunks are used to accelerate the computing time of the FFT ? if we have a 2^n chunks, we'll have 2^n smaller FT processed ?
The results[][] 2d Complex Array contains... complexs. But i don't understant what is x and y in results[x][y], how can you find the frequency and the amplitude. (of course i'll have to convert the complexs to doubles)
Do you think this approach is enough ? the projet is not professional so i'm not trying to get a recogntion rate of 100% !
Thank you for your answers.
Hi there, I was wondering if there's a way to detect amplitude peaks in a sound file while being played. I don't need anything fancy really, I just need to find when the "volume" is above a certain level.
import ddf.minim.*;
Minim minim;
AudioPlayer player;
void setup()
{
minim = new Minim(this);
player = minim.loadFile("/data/samples/sample02.mp3");
player.play();
}
void draw()
{
println("Gain: " + player.getGain()); //always prints 0.0 but I guess it's because it's not what I'm looking for
println("Volume: " + player.getVolume()); //Minim error: Volume is not supported
}
Thank you!
each line has two ends. You use xspeed and yspeed for BOTH. I changed that by using xspeed2 and yspeed2 for the 2nd end now.
import processing.sound.*;
// Bouncer a;
Bouncer []c= new Bouncer [150];
AudioIn in;
Amplitude amp;
void setup() {
size( 1500, 1000);
for (int i=0; i<c.length; i++) {
c[i] = new Bouncer(random(-8, 8), random (-8, 8), random(255));
}
background(0, .000005);
}
void draw() {
// if (random(100)>96)
background(0, .000005);
for (int i=0; i<c.length; i++) {
c[i].display();
c[i].bounce();
}
}
// ======================================================
class Bouncer {
float r, g, b, // color !!
s,
xpos, ypos,
xpos2, ypos2,
xspeed, yspeed,
xspeed2=random(-8, 8), yspeed2=random(-8, 8); // !!!!!!!!!!
Bouncer(float tempxspeed, float tempyspeed,
float tempr) {
xspeed = tempxspeed;
yspeed = tempyspeed;
xpos = width/2;
ypos = height/2;
xpos2 = width/4;
ypos2 = height/4;
r = tempr;
g = random(255);
b = 255;
s = 15;
}
void display() {
stroke(r, g, b);
//fill(255);
line(xpos, ypos,
xpos2, ypos2);
}
void bounce() {
if ( xpos > width - s/2 || xpos < s/2 ) {
xspeed = xspeed * -1;
}
if ( ypos > height - s/2 || ypos < s/2 ) {
yspeed = yspeed * -1;
}
if ( xpos2 > width - s/2 || xpos2 < s/2 ) {
xspeed2 = xspeed2 * -1;
}
if ( ypos2 > height - s/2 || ypos2 < s/2 ) {
yspeed2 = yspeed2 * -1;
}
xpos = xpos + xspeed;
ypos = ypos + yspeed;
xpos2 = xpos2 + xspeed2;
ypos2 = ypos2 + yspeed2;
}
}//class
//
Hi Processing World!
I'm still a newbie here, and never have coded something substantial in my life. I'm wondering if I can get some help in figuring out how to make my lines move independently from each other and go off of different angles, instead of just bouncing back off the screen in the same direction. Either I need to have them rotate as they hit the side of the screen, or I need point X to follow point Y. Not sure what my solution would be but I hope someone here can help.
Thank you,
Clinton
Bouncer a; Bouncer []c= new Bouncer [150]; import processing.sound.*; AudioIn in; Amplitude amp; void setup(){
size( 1500,1500); for (int i=0; i<c.length;i++){ c[i] = new Bouncer(random(-8,8), random (-8,8), random(255)); }
}
void draw(){
background(0,.000005);
for (int i=0; i<c.length;i++){ c[i].display(); c[i].bounce(); }
}
class Bouncer {
float r, g, b, s, xpos, ypos, xpos2, ypos2, xspeed, yspeed; Bouncer(float tempxspeed, float tempyspeed, float tempr) {
xspeed = tempxspeed;
yspeed = tempyspeed;
xpos = width/2;
ypos = height/2;
xpos2 = width/4;
ypos2 = height/4;
r = tempr;
g = random(255);
b = 255;
s = 5;
}
void display() {
stroke(255);
fill(255);
line(xpos, ypos, xpos2, ypos2);
}
void bounce() {
if ( xpos > width - s/2 || xpos < s/2 ) {
xspeed = xspeed * -1;
}
if ( ypos > height - s/2 || ypos < s/2 ) {
yspeed = yspeed * -1;
}
if ( xpos2 > width - s/2 || xpos2 < s/2 ) {
xspeed = xspeed * -1;
}
if ( ypos2 > height - s/2 || ypos2 < s/2 ) {
yspeed = yspeed * -1;
}
xpos = xpos + xspeed;
ypos = ypos + yspeed;
xpos2 = xpos2 + xspeed;
ypos2 = ypos2 + yspeed;
} }
Hiya
In case its any use to anyone I thought I'd share some performance testing code and data I made while optimising a music visualizer.
I wondered what impact calling amp.analyze multiple times might have so performed 3 tests to see
test 1 - drawing a 400x400 green screen via loop - average frame rate 18.63485
test 2 - same but call amp.analyze each iteration - average frame rate 8.72345
test 3- pass amp.analyze value into variable once per draw - average frame rate 18.66579
test code:
import processing.sound.*;
Amplitude amp;
SoundFile file;
float analyzed;
void setup() {
size(400, 400);
background(255);
noSmooth();
file = new SoundFile(this, "Crickets.mp3");
amp = new Amplitude(this);
file.play();
amp.input(file);
}
void draw(){
//test one: just drawing points - average frame rate 18.63485
for ( int iy=0; iy < height; iy++){
for ( int ix=0; ix < width; ix++){
stroke(0,255,0);
point(ix, iy);
}
}
//test 2: call amp value each iteration - average frame rate 8.72345
//for ( int iy=0; iy < height; iy++){
// for ( int ix=0; ix < width; ix++){
// stroke(0,amp.analyze()*200,0);
// point(ix, iy);
// }
//}
//test 3 call amp value once per draw - average frame rate 18.66579
//analyzed = amp.analyze();
//for ( int iy=0; iy < height; iy++){
// for ( int ix=0; ix < width; ix++){
// stroke(0,analyzed*200,0);
// point(ix, iy);
// }
//}
println(frameRate);
}
Hey everyone,
I would like to use different wave forms as "parent" frequencies for their "child" oscillators. Something like this:
MASTER SINE: 0.1hz child sine one:0.2 hz ( x2 of 0.1hz from master) child sine two: 0.3 hz (x 3 of 0.1hz from master)
Can you use scale() or mult() to mulitply the frequency of an oscillator? Its seems like scale() or mult() will multiply the amplitude and not increase the frequency. Not even sure if this is possible ha. I'd like to keep the child oscillators "in sync" to the master to create a series of rhythmically pulsing oscillations at even divisions.
Let me know if you this isn't clear enough. Any light that can be shed on this technique would be greatly appreciated!
Please format your code. Edit your post (gear on top right side of any of your posts), select your code and hit ctrl+o. Leave an empty line above and below your block of code. Details here: https://forum.processing.org/two/discussion/15473/readme-how-to-format-code-and-text
Demo below.
Kf
import processing.sound.*;
final int STEPX=4;
final int STEPY=30;
AudioIn in;
Amplitude amp;
float x=50;
float y=STEPY;
float c;
PVector prevPoint;
void setup() {
size (displayWidth, 500);
amp=new Amplitude(this);
in=new AudioIn(this, 0);
in.start();
amp.input(in);
background(255);
prevPoint=new PVector(0, y);
}
void draw() {
c=amp.analyze()*50;
beginShape();
stroke(25);
line(prevPoint.x,prevPoint.y, x+STEPX, y+c);
if (x>width) {
y=y+STEPY;
x=0;
}
prevPoint.set( x=x+STEPX, y+c);
}
P.S. The code for the line() function above could be replace with:
beginShape();
vertex(prevPoint.x, prevPoint.y);
vertex( x+STEPX, y+c);
endShape();
Hello!
I have a problem. I am a newbie with processing and I'm trying to make a sound meter similar to one that you would see on a lie detecter test/or a Joy Division album cover. I've only been using processing for a month now, and the problem I'm running into is that every time I make a sound my image jumps and looks like squares instead of curved lines.
Hoping I could get some help....
-Clinton
import processing.sound.*; AudioIn in; Amplitude amp; float x=50; float y=10; float c; void setup() { frameRate (300); size (1500, 500); amp=new Amplitude(this); in=new AudioIn(this, 0); in.start(); amp.input(in); background(255); }
void draw() { c=amp.analyze()*50; beginShape(); stroke(25);
line(x, y, x, y-c); line(x, y, x, y+c); x++; if (x>width) { y=y+10; x=0; } }
@solub --
If the example you found on the internet is indeed using perlin noise then the two issues are:
I would demonstrate on your provided sketch, but it fails on
from particle import Particle
ImportError: no module named particle
(also, for some reason the forum inserted emoticon HTML into your line 15).
At first glance it looks like you are approaching things in the right way but your base radius is much larger than the reference example, and your output amplitude is way smaller, and you need the highest facet resolution shown in your demo (high resolution is required for sharp peaks). The regularity / irregularity on the surface is extremely sensitive to the scale of input.
To read more about the scale of input coordinates, see past discussions of "perlin" on this forum:
Or is it bad idea to try it on processing?
As a matter of fact, P3 would be a good tool to do this. You just need to design the algorithm... the fun part.
Can you generate your own demonstration of a sine function in Processing? Are you familiar with the concept of frequency, amplitude and phase for --this-- waveform?
This is a good start: https://processing.org/examples/sinewave.html
Few tasks you need to do:
1. Increase the number of peaks shown: What parameter do you need to adjust for this?
2. Adjust the amplitude so the center sees the maximum amplitude and the edges sees zero amplitude.
3. Can you draw a second wave on top of the first one?
4. Finally, apply a phase to the second phase
The net stage is to move from a line into a circle. This means that you need to map your X axis into an angle. The X axis' range is from 0 to width, where width is the width of your sketch. The angle ranges from 0 to TWO_PI. There is not better function for this operation than using map(). So using map, you can project a line into the perimeter of a circle. If the line is described by a sine function, then it follows that the perimeter of the circle is described by this same function.
Check the reference for (really all what you need): sin, map, vertex/curvevertex,point/strokeWeight
Kf
Hi seamiki. Thanks for the tip. I have implemented the code. No matter what I set the threshold at it seems to act in a jerky fashion. Some time not firing at all or like before firing by too many rotations. I think this might actually be just the nature of minims beat detection. Even when you view a simple expanding circle that is growing with the amplitude of each beat, the circle does not grow to a consistent size at the loudest part of each beat... even with a simple looping 909 kick pattern with no variations in amplitude and no other layered sounds to confuse it.