Sine wave visualisation phasing issue / digital distortion?
in
Contributed Library Questions
•
6 months ago
Hello all, sorry about the length of this message.
In
my code though, I am encountering a strange effect that I am unsure of the cause of - though I think it might be a phasing issue, or a type of digital distortion? Here is my project, which would require you to set up midiBus and have midi input in order to run. I've also put a video on youtube incase you'd rather not run the project, although the affect isn't really represented fully at all in the video:
I am working on a patch that receives midi messages (using midiBus) and visualises their pitch + length as sine wave objects that float around (using Traer Physics) being attracted towards mass points. Weird I know, but there's an eventual reason for this that I'll explain if anybody is interested.
I'm not much of a programmer, this project is very much at the limits of my capabilities so I'm certain I'm making mistakes all over the place. Here's my issue, I'd like each sine wave to progress along with its movement and respective frequency, as shown in this code:
- Wave w1;
- void setup() {
- size(500, 500);
- smooth();
- w1 = new Wave(20, 80, 0, 0);
- }
- void draw() {
- background(255);
- translate(width/2, height/2);
- w1.draw();
- noFill();
- }
- class Wave {
- float amp, p;
- float ax, ay;
- float x1 = 0;
- public Wave(float amplitude, float pitch, float angX, float angY) {
- amp = amplitude;
- p = pitch;
- ax = angX;
- ay = angY;
- }
- public void draw() {
- pushMatrix();
- for (float i = x1; i < x1+50; i += 2/amp) {
- point(i, sin(TWO_PI * i/p)*amp);
- }
- x1++;
- popMatrix();
- }
- }
- import traer.physics.*;
- import themidibus.*;
- // Declarations
- ParticleSystem physics;
- Particle f, c, woof, tweet;
- MidiBus myBus;
- ArrayList Ons = null;
- ArrayList Waves = null;
- float a;
- int circleRad, wooferPosX, wooferPosY, tweeterPosX, tweeterPosY, tweeterRad, wooferRad;
- void setup() {
- size(1000, 750, P2D);
- frameRate(120);
- smooth(4);
- //Default style settings
- stroke(255);
- strokeWeight(1);
- ellipseMode(CENTER);
- noFill();
- // Initializations
- myBus = new MidiBus(this, 0, 7);
- Ons = new ArrayList();
- Waves = new ArrayList();
- wooferPosX = 3*width/4;
- wooferPosY = height/2;
- tweeterPosX = width/4;
- tweeterPosY = height/2;
- tweeterRad = 100;
- wooferRad = 200;
- circleRad = 350;
- // creating system setup
- physics = new ParticleSystem(0, 0);
- f = physics.makeParticle(1, sin(a%TWO_PI)*circleRad+width/2, cos(a%TWO_PI)*circleRad+height/2, 0);
- c = physics.makeParticle(1, sin(a-PI%TWO_PI)*circleRad+width/2, cos(a-PI%TWO_PI)*circleRad+height/2, 0);
- woof = physics.makeParticle(1, wooferPosX, wooferPosY, 0);
- tweet = physics.makeParticle(1, tweeterPosX, tweeterPosY, 0);
- woof.position().set(wooferPosX, wooferPosY, 0);
- tweet.position().set(tweeterPosX, tweeterPosY, 0);
- f.makeFixed();
- c.makeFixed();
- woof.makeFixed();
- tweet.makeFixed();
- }
- void draw() {
- physics.tick();
- // Scene Settings
- background(0);
- strokeWeight(1);
- //drawing speaker cone circles
- //tweeter
- ellipse(tweet.position().x(),tweet.position().y(), tweeterRad, tweeterRad);
- //woofer
- ellipse(woof.position().x(),woof.position().y(), wooferRad, wooferRad);
- //Updating creation + force point positions
- f.position().set(sin(a%TWO_PI)*circleRad+width/2, cos(a%TWO_PI)*circleRad+height/2, 0);
- c.position().set(sin(a-PI%TWO_PI)*circleRad+width/2, cos(a-PI%TWO_PI)*circleRad+height/2, 0);
- //Drawing creation and force point
- strokeWeight(5);
- point(f.position().x(), f.position().y());
- point(c.position().x(), c.position().y());
- //update and draw all waves
- for (int i = 0; i < Waves.size(); i++) {
- Wave w = (Wave)Waves.get(i);
- w.updateTailPointPosition();
- w.updateDirections();
- w.drawWave();
- }
- a+=0.01;
- }
- //midibus noteOn class for when a note on message is received.
- void noteOn(int channel, int pitch, int velocity) {
- int midiChannel = channel;
- int midiPitch = pitch;
- int midiVel = velocity;
- int pointInTime = millis();
- Ons.add(new On(midiPitch, midiVel, midiChannel, pointInTime));
- }
- //midibus noteOff class for when a note off message is received.
- void noteOff(int channel, int pitch, int velocity) {
- int midiChannel = channel;
- int midiPitch = pitch;
- int midiVel = velocity;
- int pointInTime = millis();
- new Off(midiPitch, midiChannel, pointInTime);
- //println(Ons.size());
- }
- class Off{
- public int channel = -1;
- public float pitch = -1;
- public int velocity = -1;
- public int whenThisHappened = -1;
- public int timeDifference = -1;
- Off(int midiPitch, int midiChannel, int pointInTime){
- pitch = midiPitch;
- channel = midiChannel;
- whenThisHappened = pointInTime;
- // checking for the corresponding note on to this off (i.e. same pitch, waiting for an off)
- for(int i = 0; i < Ons.size(); i++){
- On o = (On)Ons.get(i);
- //getting the note on in question
- if(o.retrievePitch() == pitch && o.retrieveWaiting() == true){
- //getting this ons velocity
- velocity = o.retrieveVelocity();
- //finding time difference between note off and note on
- timeDifference = whenThisHappened - o.retrieveWhenThisHappened();
- //println("this is the time difference: " + timeDifference);
- o.setWaitingToFalse();
- Ons.remove(o);
- Waves.add(new Wave(pitch, velocity, channel, timeDifference));
- }
- }
- }
- }
- class On{
- public int channel = -1;
- public int pitch = -1;
- public int velocity = -1;
- public int whenThisHappened = -1;
- public boolean waitingForOff = false;
- On(int midiPitch, int midiVel, int midiChannel, int pointInTime){
- pitch = midiPitch;
- velocity = midiVel;
- channel = midiChannel;
- whenThisHappened = pointInTime;
- waitingForOff = true;
- }
- public int retrievePitch(){
- return pitch;
- }
- public int retrieveVelocity(){
- return velocity;
- }
- public int retrieveWhenThisHappened(){
- return whenThisHappened;
- }
- public boolean retrieveWaiting(){
- return waitingForOff;
- }
- public void setWaitingToFalse(){
- waitingForOff = false;
- }
- }
- class Wave{
- public Particle p1, p2;
- public PVector directionOfTailPoint, directionOfMovement, unitVector;
- public float x1;
- public int channel = -1;
- public float pitch = -1;
- public float velocity = -1;
- public float waveLength = -1;
- public int distanceBetweenPoints = -1;
- public int pan = -1;
- public float waveAngle;
- Wave(float midiPitch, int midiVel, int midiChannel, int timeDifference){
- //println(midiPitch);
- pitch = (pow(2, ((midiPitch-69)/12)))*440.0 ; //converting from midi note to frequency
- //println(pitch);
- velocity = map(midiVel, 0, 127, 1, 50);
- channel = midiChannel;
- waveLength = timeDifference;
- x1 = 0.0;
- unitVector = new PVector(0,-1,0);
- //println(waveLength);
- //initialize point position, velocity and attractions
- p1 = physics.makeParticle(waveLength/25, c.position().x(), c.position().y(), 0);
- physics.makeAttraction( p1, woof, wooferRad*2, wooferRad);
- physics.makeAttraction( p1, tweet, tweeterRad*2, tweeterRad);
- physics.makeAttraction( p1, f, 1000, 30);
- directionOfTailPoint = new PVector(-1*p1.velocity().x(),-1*p1.velocity().y(),0);
- directionOfTailPoint.normalize();
- p2 = physics.makeParticle(waveLength/25, p1.position().x()+(directionOfTailPoint.x*waveLength), p1.position().y()+(directionOfTailPoint.y*waveLength), 0);
- physics.makeAttraction( p2, woof, wooferRad, wooferRad);
- physics.makeAttraction( p2, tweet, tweeterRad, tweeterRad);
- physics.makeAttraction( p2, f, 250, 30);
- distanceBetweenPoints = (int)dist(p1.position().x(),p1.position().y(),p2.position().x(),p2.position().y());
- directionOfMovement = new PVector(p1.velocity().x(),p1.velocity().y(),0);
- waveAngle = PVector.angleBetween(directionOfMovement, unitVector);
- }
- void updateDirections(){
- directionOfTailPoint.set(-1*p1.velocity().x(),-1*p1.velocity().y(),0);
- directionOfTailPoint.normalize();
- directionOfMovement.set(p1.velocity().x(),p1.velocity().y(),0);
- waveAngle = atan2(p1.velocity().y(),p1.velocity().x());
- //println(waveAngle);
- }
- void updateTailPointPosition(){
- p2.position().set(p1.position().x()+(directionOfTailPoint.x*waveLength), p1.position().y()+(directionOfTailPoint.y*waveLength), 0);
- }
- void drawWave(){
- //guidelines
- /*
- stroke(100);
- strokeWeight(1);
- line(p1.position().x(),p1.position().y(),p2.position().x(),p2.position().y());
- stroke(255);
- strokeWeight(5);
- point(p1.position().x(),p1.position().y());
- stroke(255);
- strokeWeight(3);
- point(p2.position().x(),p2.position().y());
- */
- //wave itself
- pushMatrix();
- strokeWeight(2);
- stroke(255);
- translate(p1.position().x(),p1.position().y());
- rotate(waveAngle);
- for (float i = x1; i < x1+waveLength; i++) {
- point(i-x1-waveLength, sin(i*pitch)*velocity);
- }
- popMatrix();
- x1+=0.1;
- println(x1);
- }
- }
I'd be really grateful for some help, you can probably tell from the code that this has been a real struggle!
Thanks,
Adam
Edit: I stumbled upon this, which I'm certain holds the solution somewhere
http://subversion.assembla.com/svn/portaudio/portaudio/branches/alsa_hw_endian_subdevice/qa/loopback/src/audio_analyzer.c
1