digital signal processing_一天一点Processing|11网易云音乐动效并不难1——动感音阶

35cd6d7f8596d0d88d31169523191947.png

最近在学习声音可视化的内容,所以就试图用processing做了一下超爱的网易云音乐的动效,没想到还真的实现啦,就放上来大家一同学习学习~~。教程中借用了王菲演唱的《我和我的祖国》专辑封面作为素材,歌超好听,欢迎大家去收听呀。

e68ea375c2973ddfff73612fa989edd5.png

我们先从看起来最简单的动感音阶这个动效进行尝试吧,未来可能还会出后续动效的小教程,欢迎关注呀。

序: 圆形唱片

首先我们要在画布中央导入专辑图片,并将专辑图片变为圆形。用过PS的同学,在此时可能很快就浮现出一个词:蒙版。我们这次用的方式就是蒙版。

首先要准备一张蒙版图片。然后将唱片图片和蒙版图片放入工程文件中,再导入程序之中。

0173a8dfd4c0a9ad4b4725c777c49f88.png
蒙版
PImage album, masking;   //初始化两个图片变量,album和masking
int r = 200;  //唱片圆形半径

void setup() {
  size(800, 800); //设置画布
  background(0);  //设置背景颜色

  imageMode(CENTER);  //图片导入模式为中点
  album = loadImage("album.jpg");      //导入album.jpg图片
  masking = loadImage("masking.jpg");  //导入masking.jpg图片
  album.resize(2*r, 2*r);   //将图片长宽放缩为两倍半径
  masking.resize(2*r, 2*r);
  masking.filter(INVERT);   //将蒙版反相,黑色蒙住,白色漏出
  album.mask(masking);      //唱片为底图,加上蒙版
}

void draw() {
  translate(width/2, height/2);    //将坐标原点放在画布中心
  image(album, 0, 0);  //绘制圆形图片
}

e38caec0e6b8da0d84f497722417a361.png

现在我们需要将唱片旋转起来啦。原理是将坐标轴转动起来。设定一个theta变量,每次循环增加一点。

float theta = 0.0;  //唱片旋转角度

void draw() {
  translate(width/2, height/2);    //将坐标原点放在画布中心
  rotate(theta);
  image(album, 0, 0);
  theta += 0.02;
}

0ca2eddde287040c72a8fac5e49d2d1c.gif

渐变背景

旋转唱片已经实现了,我们可以再对比一下网易云音乐的效果,可以发现背景是透明渐变的。我们可以从唱片中提取颜色来实现渐变效果。

首先我们设置两个颜色变量。一个变量从唱片图片中提取颜色,另一个设置为白色,来制造渐变效果。

color c1, c2; //动效颜色
  c1 = album.get(0, 0);  //提取唱片中的颜色
  c2 = color(360, 1, 100, 1);  //白色透明

颜色从上到下为:唱片颜色 - 白 - 唱片颜色,所以我们将底图分为上下两部分。先绘制上半部分。

  for (int y = -height/2; y < 0; y++) {  //循环
    float n = map(y, -height/2, 0, 0, 1);  //0-1间取值,根据y得到映射值n
    color newc = lerpColor(c1, c2, n);  //渐变颜色提取,n取值为0-1
    stroke(newc);                       //设置线的颜色
    line(-width/2, y, width/2, y);      //画线
  }

c47784c888d085c1f440fb7ecc584c5d.png

绘制下半部分后,再得加一个透明白色正方形。

//设置渐变背景
void backGround() {
  for (int y = -height/2; y < 0; y++) {  //循环
    float n = map(y, -height/2, 0, 0, 1);  //0-1间取值,根据y得到映射值n
    color newc = lerpColor(c1, c2, n);  //渐变颜色提取,n取值为0-1
    stroke(newc);                       //设置线的颜色
    line(-width/2, y, width/2, y);      //画线
  }
  for (int y = height/2; y >= 0; y--) {
    float n = map(y, height/2, 0, 0, 1);
    color newc = lerpColor(c1, c2, n);
    stroke(newc);
    line(-width/2, y, width/2, y);
  }
  //设置透明白色正方形
  noStroke();
  fill(360, 40);
  rect(-width/2, -height/2, width, height);
}

4d9292a9e3f915ef6bc9227c467b3e84.png

音乐可视化动效:动感音阶

在绘制动效之前,我们需要导入Minim音频库。通过建立Minim对象,载入音频文件或者建立声音输入与输出。首先我们需要在“速写本 - 引用库文件 - 添加库文件”中搜索Minim点击Install。

点击“速写本 - 引用库文件 - 添加库文件 - 第三方贡献库 - Minim”我们可以得到以下几行代码。我们这次只需要最开始的一行代码。

import ddf.minim.*;           //这次只用得到这行代码
import ddf.minim.analysis.*;
import ddf.minim.effects.*;
import ddf.minim.signals.*;
import ddf.minim.spi.*;
import ddf.minim.ugens.*;

一般编写音频相关的代码,需要参考下面的范例。

import ddf.minim.*;

AudioPlayer player;  //建立音频播放器
Minim minim;   //定义音频对象

void setup() {
  minim = new Minim(this); 
  player = minim.loadFile("music.mp3", 1024);  //调取音频文件,指定缓存的采样频率为1024
  player.play();  //播放文件
}

void draw(){
}

//需要注意的是,在推出程序钱,必须关闭Minim获得的所有I/O类,然后关闭Minim范本。
void stop(){
  player.close(); //关闭播放器
  minim.stop();   //停止音频
  super.stop();
}

e68ea375c2973ddfff73612fa989edd5.png

我们可以通过上图看动态音效的效果,围绕圆形唱片根据音乐绘制线。这里也要用到循环。每画一条线就旋转一个角度继续画。我们旋转角度后每次都要将坐标轴重置为没有旋转的位置,所以要运用到pushMatrix();和popMatrix();

  translate(width/2, height/2);   //原始点到画布中央
  for (int i=0; i<player.left.size(); i+=15) {
    float rTheta = map(i, 0, player.left.size()-1, 0, 2*PI);  //动态音效绘制线旋转的角度
    pushMatrix();    //把原点数据和旋转数据放入矩阵堆栈中
    rotate(rTheta);  //旋转一个角度
    line(0, r, 0, r + player.left.get(i)*100);  //player.left.get(i)为-1 - 1,所以要乘以一个数放大
    popMatrix();     //释放堆栈
 }

07710bf5c70baa0a98c15c04377f3df9.png

这里我们可以看到线会往内部,会影响视觉效果,所以我们将player.left.get(i)加上绝对值,保证它能够大于0。

再将线条设置为提取的颜色就可以啦!!

c2b790ddd3ef369df2c336c2990b6f7f.png

其实绘制圆形图片应当有更简单高效的方法,但是奈何我试不出来/(ㄒoㄒ)/~~,希望有厉害的同学能够和我分享分享方法,十分感谢~~~。

最后附上所有的代码~~~

主代码

import ddf.minim.*;

AudioPlayer player;  //建立音频播放器
Minim minim;   //定义音频对象

PImage album, masking;
int r = 200;  //唱片圆形半径
float albumTheta = 0.0;  坐标轴旋转角度
color c1, c2; //动效颜色


void setup() {
  size(800, 800);   //设置画布
  colorMode(HSB, 360, 100, 100, 100);
  myAlbum();  //***导入圆形唱片图片

  minim = new Minim(this); 
  player = minim.loadFile("yunian.mp3", 1024);  //调取音频文件,指定缓存的采样频率为1024
  player.play(); //播放文件
}

void draw() {
  translate(width/2, height/2);    //将坐标原点放在画布中心
  background(360);   //设置背景颜色
  backGround();    //***设置渐变背景
  rotate(albumTheta);       //坐标轴旋转
  image(album, 0, 0);  //绘制圆形图片

  //绘制动态音效
  stroke(c1);        //线颜色
  strokeWeight(4);   //线粗
  for (int i=0; i<player.left.size(); i+=6) {
    float rTheta = map(i, 0, player.left.size()-1, 0, 2*PI);  //旋转角度
    pushMatrix();   //把原点数据和旋转数据放入矩阵堆栈中
    rotate(rTheta);
    line(0, r+10, 0, r + 10 + abs(player.left.get(i))*200);
    popMatrix();    //释放堆栈
  }

  albumTheta += 0.02;       //坐标轴旋转角度增加
}

void stop() {
  player.close(); //关闭播放器
  minim.stop();   //停止音频
  super.stop();
}

myAlbum();导入圆形专辑图片

//导入圆形唱片图片
void myAlbum() {
  imageMode(CENTER);  //图片导入模式为中点
  album = loadImage("album.jpg");      //导入album.jpg图片
  masking = loadImage("masking.jpg");  //导入masking.jpg图片
  album.resize(2*r, 2*r);   //将图片长宽放缩为两倍半径
  masking.resize(2*r, 2*r);

  c1 = album.get(0, 0);  //提取唱片中的颜色
  c2 = color(360, 1, 100, 1);  //白色透明

  masking.filter(INVERT);   //将蒙版反相,黑色蒙住,白色漏出
  album.mask(masking);      //唱片为底图,加上蒙版
}

backGround();设置渐变背景

//设置渐变背景
void backGround() {
  for (int y = -height/2; y < 0; y++) {  //循环
    float n = map(y, -height/2, 0, 0, 1);  //0-1间取值,根据y得到映射值n
    color newc = lerpColor(c1, c2, n);  //渐变颜色提取,n取值为0-1
    stroke(newc);                       //设置线的颜色
    line(-width/2, y, width/2, y);      //画线
  }
  for (int y = height/2; y >= 0; y--) {
    float n = map(y, height/2, 0, 0, 1);
    color newc = lerpColor(c1, c2, n);
    stroke(newc);
    line(-width/2, y, width/2, y);
  }
  noStroke();
  fill(360, 40);
  rect(-width/2, -height/2, width, height);
}
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值