作者 主题: [ 作业提交 ] P5 Workshop (2nd) @ xinchejian DAY2  (阅读 15807 次)

muddy

  • Newbie
  • *
  • 帖子: 11
Re: [ 作业提交 ] P5 Workshop (2nd) @ xinchejian DAY2
« 回复 #15 于: 一月 04, 2012, 10:28:59 下午 »
请问有没有办法让声音参数抖动的频率低一些,现在曲线抖动得非常快,效果不是很理想啊。

RavenKwok

  • Sr. Member
  • ****
  • 帖子: 277
  • Artist/ Animator/ Coder/ Cynical Asshole
Re: [ 作业提交 ] P5 Workshop (2nd) @ xinchejian DAY2
« 回复 #16 于: 一月 05, 2012, 10:28:49 上午 »
@muddy

研究下这条命令。

http://processing.org/reference/lerp_.html

muddy

  • Newbie
  • *
  • 帖子: 11
Re: [ 作业提交 ] P5 Workshop (2nd) @ xinchejian DAY2
« 回复 #17 于: 一月 05, 2012, 03:24:34 下午 »
这条命令似乎只是一种映射方法?不知道怎么用它解决我的问题。。
我不知道你有没有理解我的意思,我意思是声音变量的更新频率太快了,每秒钟可能上百次,导致图像在剧烈的晃动,出现近似random的效果而并非我想要的像noise函数的柔和变化的效果。
我在想是不是可以改变采集声音变量的间隔时间,比如每隔1/10秒或者半秒采集一次,不知道能否做到。
« 最后编辑时间: 一月 05, 2012, 03:30:11 下午 作者 muddy »

RavenKwok

  • Sr. Member
  • ****
  • 帖子: 277
  • Artist/ Animator/ Coder/ Cynical Asshole
Re: [ 作业提交 ] P5 Workshop (2nd) @ xinchejian DAY2
« 回复 #18 于: 一月 07, 2012, 10:24:55 下午 »
@muddy

每秒的更新次数和frameRate 一致的。改变采集的时间间隔能让点能在一个特定的位置维持较长的时间,但不能让它平滑地在两个位置间运动。
所以可以用lerp() 函数让当前点向目标位置做平滑的缓冲运动。而我们只需要将get 值写入目标数值的参数位置即可。 ::)

muddy

  • Newbie
  • *
  • 帖子: 11
Re: [ 作业提交 ] P5 Workshop (2nd) @ xinchejian DAY2
« 回复 #19 于: 一月 09, 2012, 03:05:09 上午 »
研究了两个晚上终于有了比较理想的效果- -b

代码写得比较复杂,因为思路比较复杂
我觉得应该有简单的写法,目前我就这点水平啦,老师帮看看 ;)

我的思路是在圆周上均匀选取18个点,然后对这18个点的坐标值采集20组数据
然后在每个点的20组数据中选取离圆心最近最远两组峰值坐标,用lerp函数让每个点在峰值间滑动

以下是代码,重要行都有注释:
程序代码
//导入类库
import ddf.minim.*;

int counter, degree, incre;
int i, j;
float baseRadius;
float[]xPos = new float[360];
float[]yPos = new float[360];
float[]xPos20 = new float[20];
float[]yPos20 = new float[20];
float[]xPosMinMax = new float[36];
float[]yPosMinMax = new float[36];
float[]xPosLerp = new float[18];
float[]yPosLerp = new float[18];
boolean shutterStartDraw, shutterMinMax;

//声明minim 与in 对象
Minim minim;
AudioInput in;

void setup()

  frameRate(100);
  size(600, 600);
  strokeWeight(3);
  smooth();

  //初始化minim 以及in
  minim = new Minim(this);
  in = minim.getLineIn(Minim.STEREO, 360);

  //初始化计数器,原始半径,开关
  counter = 1;
  baseRadius = 150;
  shutterStartDraw = false;
  shutterMinMax = false;
}

void draw()
{
  //残影效果
  noStroke();
  fill(0, 20);
  rect(0, 0, width, height);

  //移动坐标原点
  translate(width/2, height/2);
  stroke(255);

  //将声音输入变量与圆弧上的点相关联,每一次draw循环给圆弧上的18个点赋予坐标值
  for (int degree = 0; degree < 360; degree += 20) {
    xPos[degree+counter-1] = cos(radians(degree))*(baseRadius+(in.left.get(degree)+in.right.get(degree))*40);
    yPos[degree+counter-1] = sin(radians(degree))*(baseRadius+(in.left.get(degree)+in.right.get(degree))*40);
  }
  counter ++;

  //判断draw循环执行20次,每个点有了20组候选坐标值,准备开始画圆
  if (counter > 20) { 
    shutterStartDraw = true;
   
    //重置计数器
    counter = 1;
   
    //在每个点的20组候选坐标值中,选取最大最小两个峰值,给lerp函数使用
    for (int i = 0; i < 36; i += 2) {
     
      //在新的一轮20组赋值开始后,将后面lerp函数末值赋给首值,保证每个点移动的连续性
      xPosMinMax[i] = xPosMinMax[i+1];
      yPosMinMax[i] = yPosMinMax[i+1];

      //将每个点的20组候选坐标值存入数组待选
      for (int j = 0; j < 20; j++) {
        xPos20[j] = xPos[10*i+j];
        yPos20[j] = yPos[10*i+j];
      }

      //为后面lerp函数里的末值选取一个峰值,用shutterMinMax逻辑开关实现在不同轮中交替选取Min值与Max值
      //需分象限讨论
      //第一象限(右下),xy值皆为正
      if (i < 9) {
        if (shutterMinMax) {     
          xPosMinMax[i+1] = max(xPos20);
          yPosMinMax[i+1] = max(yPos20);
        }
        else {
          xPosMinMax[i+1] = min(xPos20);
          yPosMinMax[i+1] = min(yPos20);
        }
      }
      //第二象限(左下),x为负,y为正
      else if (i > 9 && i < 19) {
        if (shutterMinMax) {     
          xPosMinMax[i+1] = min(xPos20);
          yPosMinMax[i+1] = max(yPos20);
        }
        else {
          xPosMinMax[i+1] = max(xPos20);
          yPosMinMax[i+1] = min(yPos20);
        }
      }
      //第三象限(左上),xy值皆为负
      else if (i > 19 && i < 27) {
        if (shutterMinMax) {     
          xPosMinMax[i+1] = min(xPos20);
          yPosMinMax[i+1] = min(yPos20);
        }
        else {
          xPosMinMax[i+1] = max(xPos20);
          yPosMinMax[i+1] = max(yPos20);
        }
      }
      //第四象限(右上),x为正,y为负
      else {
        if (shutterMinMax) {     
          xPosMinMax[i+1] = max(xPos20);
          yPosMinMax[i+1] = min(yPos20);
        }
        else {
          xPosMinMax[i+1] = min(xPos20);
          yPosMinMax[i+1] = max(yPos20);
        }
      }
    }
    //最大值最小值逻辑开关进行运算
    shutterMinMax = !shutterMinMax;
  }

  //开始画圆
  if (shutterStartDraw) {
   
    //让每一点在最大值与最小值之间平移 
    for (int i = 0; i < 36; i += 2) {
      xPosLerp[i/2] = lerp(xPosMinMax[i], xPosMinMax[i+1], incre/100.0);
      yPosLerp[i/2] = lerp(yPosMinMax[i], yPosMinMax[i+1], incre/100.0);
    }

    //各点连线
    beginShape();
    curveVertex(xPosLerp[0], yPosLerp[0]);
    for (int i = 0; i < 18; i++) {
      curveVertex(xPosLerp[i], yPosLerp[i]);
    }
    curveVertex(xPosLerp[0], yPosLerp[0]);
    curveVertex(xPosLerp[0], yPosLerp[0]);
    endShape();

    //平移增量累加
    incre += 5;
  }
 
  //每一轮结束后,重置平移增量
  if (incre > 95) incre = 0;
}

void stop()
{
  in.close();
  minim.stop();
  super.stop();
}

还有两个小问题
1. processing有没有二维数组?我这个sketch用二维数组貌似容易些
2. 各点连线的时候,起点两侧总是折线,有没有办法平滑它?

竟然3点了。。 :o
« 最后编辑时间: 一月 09, 2012, 03:11:37 上午 作者 muddy »

RavenKwok

  • Sr. Member
  • ****
  • 帖子: 277
  • Artist/ Animator/ Coder/ Cynical Asshole
Re: [ 作业提交 ] P5 Workshop (2nd) @ xinchejian DAY2
« 回复 #20 于: 一月 12, 2012, 12:14:43 下午 »
@muddy

 :-[ 不好意思,最近有些小忙,回晚了。

貌似有延时嘛,这是你刻意追求的效果吗? :)

其实不必这么复杂拉,只要定义点位置的目标值(get值赋值给目标值),再定义点位置的当前值(当前值到目标值之间做lerp)就可以了。

另外,Processing 当然可以声明使用二维数组的,如下(譬如一个10x10的矩阵):

程序代码
float [][] xpos = new float[10][10];

for(int i=0;i<10;i++){
  for(int j=0;j<10;j++){
    xpos[i][j] = random(10);
  }
}

再另外,关于curveVertex() 的起始直线问题:

有一个小技巧,定义完最后一个curveVertex() 后,如果需要圆滑的首位相接的话,再在后面跟上首三个curveVertex(),即
程序代码
beginShape();
for(int i=0;i<xpos.length;i++){
  for(int j=0;j<ypos.length;j++){
    curveVertex(xpos[i],ypos[j]);
  }
}
curveVertex(xpos[0],ypos[0]);
curveVertex(xpos[1],ypos[1]);
curveVertex(xpos[2],ypos[2]);
endShape(CLOSE);

muddy

  • Newbie
  • *
  • 帖子: 11
Re: [ 作业提交 ] P5 Workshop (2nd) @ xinchejian DAY2
« 回复 #21 于: 一月 25, 2012, 10:32:21 下午 »
@RavenKwok

一段时间没来了,拜个晚年!

你说的"只要定义点位置的目标值(get值赋值给目标值),再定义点位置的当前值(当前值到目标值之间做lerp)就可以了"还是没有闹明白。

我想不通的是,每一次draw循环就会更新一次目标值和当前值,那么在每次循环里怎么表现点的平移过程呢?draw的里绘制过程都是瞬间完成啊。

应该用什么样的结构来写呢,老师能不能给一小段示范呀 :)

另外两个tips很受用,多谢 ;D

RavenKwok

  • Sr. Member
  • ****
  • 帖子: 277
  • Artist/ Animator/ Coder/ Cynical Asshole
Re: [ 作业提交 ] P5 Workshop (2nd) @ xinchejian DAY2
« 回复 #22 于: 一月 25, 2012, 11:23:57 下午 »
@muddy

哈哈,新年好。

直接上代码咯。 ::)

程序代码

import ddf.minim.*;

float degree;
float [] xPos,yPos;
float baseRadius;
int complexity;
float mapping;

AudioPlayer player;
Minim minim;
float x;

void setup()
{
  size(600, 600);
  background(0);
  complexity = 360;
  mapping = float(360/complexity);
 
  minim = new Minim(this);
  player = minim.loadFile("groove.mp3",complexity);
  player.loop();
 
  baseRadius = 150;
  xPos = new float[complexity];
  yPos = new float[complexity];
  rectMode(CENTER);
  for(int degree = 0; degree < complexity; degree++){
    xPos[degree] = cos(radians(degree))*baseRadius;
    yPos[degree] = sin(radians(degree))*baseRadius;
  }
  smooth();
}

void draw()
{
  background(0);
  translate(width/2,height/2);
  rotate(radians(x));
  strokeWeight(1);
  stroke(255);
  noFill();
  beginShape();
  for(int degree = 0; degree < complexity; degree++){
    float radiusT = (baseRadius+(player.left.get(degree)+player.right.get(degree))*500);
   
    float xPosT = cos(radians(degree*mapping))*radiusT;
    float yPosT = sin(radians(degree*mapping))*radiusT;
   
    xPos[degree] = lerp(xPos[degree],xPosT,0.2);
    yPos[degree] = lerp(yPos[degree],yPosT,0.2);
   
    curveVertex(xPos[degree],yPos[degree]);
  }
  curveVertex(xPos[0],yPos[0]);
  curveVertex(xPos[1],yPos[1]);
  curveVertex(xPos[2],yPos[2]);
  endShape(CLOSE);
  x+=0.5;
}

void stop()
{
  player.close();
  minim.stop();
  super.stop();
}


muddy

  • Newbie
  • *
  • 帖子: 11
Re: [ 作业提交 ] P5 Workshop (2nd) @ xinchejian DAY2
« 回复 #23 于: 一月 27, 2012, 12:17:37 下午 »
@RavenKwok

非常感谢 :)

yuanyuan

  • Newbie
  • *
  • 帖子: 12
Re: [ 作业提交 ] P5 Workshop (2nd) @ xinchejian DAY2
« 回复 #24 于: 二月 14, 2012, 12:14:25 上午 »
我想问问,有没有可能是设定在一个范围内的频率是形成一种形态,在另一个频率范围内是变成另外一种形态?

RavenKwok

  • Sr. Member
  • ****
  • 帖子: 277
  • Artist/ Animator/ Coder/ Cynical Asshole
Re: [ 作业提交 ] P5 Workshop (2nd) @ xinchejian DAY2
« 回复 #25 于: 二月 14, 2012, 01:26:07 下午 »
@yuanyuan

木有听懂你的意思。

yuanyuan

  • Newbie
  • *
  • 帖子: 12
Re: [ 作业提交 ] P5 Workshop (2nd) @ xinchejian DAY2
« 回复 #26 于: 二月 14, 2012, 08:54:08 下午 »
是想分音频的高低,当有比较柔和的声音的时候是圆滑的形态,有节奏特别强烈的时候图形就变的复杂有棱角。这样的话是不是要划分音频的一个数据范围?比如说1-。。。是一个范围,这样。不知道我有没有说清楚。。

yuanyuan

  • Newbie
  • *
  • 帖子: 12
Re: [ 作业提交 ] P5 Workshop (2nd) @ xinchejian DAY2
« 回复 #27 于: 二月 14, 2012, 09:09:08 下午 »
import ddf.minim.*;

//Minim minim;
AudioInput in;
//import processing.pdf.*;

float degree;
float [] xPos,yPos;
float baseRadius;
int complexity;
float mapping;
boolean recordOrNot = false;


AudioPlayer player;
Minim minim;
float x;

void setup()
{
  size(600, 600,P2D);
  background(255);
  complexity = 360;
  mapping = float(360/complexity);
 
  minim = new Minim(this);
  minim.debugOn();
  in = minim.getLineIn(Minim.STEREO, 512);
 // player = minim.loadFile("music.mp3",complexity);
  //player.loop();
 
  baseRadius = 150;
  xPos = new float[complexity];
  yPos = new float[complexity];
  rectMode(CENTER);
  for(int degree = 0; degree < complexity; degree++){
    xPos[degree] = cos(radians(degree))*baseRadius;
    yPos[degree] = sin(radians(degree))*baseRadius;
  }
  smooth();
}

void draw()
{
 /* if(recordOrNot) {
    beginRecord(PDF, "Output.pdf");
  }*/
  background(255);
  translate(width/2,height/2);
  rotate(radians(x));
  strokeWeight(2);
  stroke(0);
  noFill();
  beginShape();
  for(int degree = 0; degree < complexity; degree++){
    float radiusT = (baseRadius+(player.left.get(degree)+player.right.get(degree))*500);
   
    float xPosT = cos(radians(degree*mapping))*radiusT;
    float yPosT = sin(radians(degree*mapping))*radiusT;
   
    xPos[degree] = lerp(xPos[degree],xPosT,0.2);
    yPos[degree] = lerp(yPos[degree],yPosT,0.2);
   
    curveVertex(xPos[degree],yPos[degree]);
  }
  curveVertex(xPos[0],yPos[0]);
  curveVertex(xPos[1],yPos[1]);
  curveVertex(xPos[2],yPos[2]);
  endShape(CLOSE);
  x+=0.5;
 
}

void stop()
{
  player.close();
  minim.stop();
  super.stop();
}
 前面的sketch 想改成实时的声音输入情况,可是显示的错误提示是nullpointerexception。。。。

RavenKwok

  • Sr. Member
  • ****
  • 帖子: 277
  • Artist/ Animator/ Coder/ Cynical Asshole
Re: [ 作业提交 ] P5 Workshop (2nd) @ xinchejian DAY2
« 回复 #28 于: 二月 15, 2012, 03:57:29 下午 »
@yuanyuan

因为你的player 对象在setup 结构内已经被你注释掉了,但你在draw() 结构内又调用了它。

程序代码
float radiusT = (baseRadius+(player.left.get(degree)+player.right.get(degree))*500);

yuanyuan

  • Newbie
  • *
  • 帖子: 12
Re: [ 作业提交 ] P5 Workshop (2nd) @ xinchejian DAY2
« 回复 #29 于: 二月 15, 2012, 11:13:08 下午 »
哦。。好的,我再试试看。。多谢啦。。 :)

Tags: