AudioSource定义了三个AudioBuffer成员,同时也可执行Recordable和Effectable界面。你无法直接创建一个AudioSource,它仅仅是为AudioPlayer, AudioSample, AudioOuput和AudioInput提供普通功能而存在。
采样缓冲器
三个采样缓冲器被命名为left, right和mix。它们持续更新左通道,右通道及左右混合声道的音源。即使在播放单声道音频时,三个通道都是可用的并且包含同样的采样。每个采样缓冲器都是一个AudioBuffer对象。
AudioBuffer: Get和Size
两个你在AudioBuffer中使用最频繁的方法是get(int i)和size()。方法size返回缓冲器的长度。方法get返回采样缓冲器第i个采样的浮点值,这个值将会在-1~1的范围内。因此,这常被认为是一个标准化的浮点采样。一个采样即对一个音源在某一时刻的振幅测量值。要听见一个声音,振幅必须时刻处于变化。最简单的变化辨识方波(square wave)。方法get并不做任何范围检查。因此,如果你询问一个位置小于零或大等于size返回值的采样,你将会得到一个ArrayOutOfBounds的错误。下例示范了如何使用get和size来为一个音频信号绘制波形。
范例(在线看)
import ddf.minim.*; Minim minim; AudioPlayer groove; void setup() { size(512, 200, P3D); minim = new Minim(this); groove = minim.loadFile("groove.mp3"); groove.loop(); } void draw() { background(0); stroke(255); // 我们用50乘以值才能看到波形 for ( int i = 0; i < groove.bufferSize() - 1; i++ ) { float x1 = map(i, 0, groove.bufferSize(), 0, width); float x2 = map(i+1, 0, groove.bufferSize(), 0, width); line(x1, height/4 - groove.left.get(i)*50, x2, height/4 - groove.left.get(i+1)*50); line(x1, 3*height/4 - groove.right.get(i)*50, x2, 3*height/4 - groove.right.get(i+1)*50); } } void stop() { // 记得关闭音频类 groove.close(); // 记得停止Minim minim.stop(); super.stop(); }
AudioBuffer:Level(水平)
AudioBuffer的方法level返回当前缓冲器的音量水平。这个值将始终处于0~1之间,但你可能会发现返回的值常比你的预期要小。
范例(在线看)
import ddf.minim.*; import ddf.minim.signals.*; Minim minim; AudioPlayer groove; void setup() { size(200, 200, P3D); minim = new Minim(this); groove = minim.loadFile("groove.mp3"); groove.loop(); rectMode(CORNERS); } void draw() { background(0); fill(255); // 绘制当前左右采样缓冲器的音量水平 // level()返回一个0~1之间的值, 因此我们将它放大 rect(0, height, width/2, height - groove.left.level()*1000); rect(width/2, height, width, height - groove.right.level()*1000); } void stop() { // 记得关闭音频类 groove.close(); // 记得停止Minim minim.stop(); super.stop(); }
AudioBuffer: toArray(到数组)
第四个也是最后一个AudioBuffer可用的方法是toArray()。这个方法以一个浮动数组的形式返回一个缓冲器内值的副本。toArray返回的浮动数组长度将一直与缓冲器的大小相同。数组内的值也将一直在-1~1的范围内变化,除非你使用了AudioOutput的信号混合产生一个超过这个范围的采样值。如果那样的话你必须注意,因为这会产生声音的失真。你可以用toArray为在AudioBuffer内的音频绘制波形,并且这是这么做的首选方法。这是由于线路方面的原因。当有一个新的采样缓冲时,实际的音频输入输出发生在他自己的线路上并最后返回总线(你的sketch)。因此,当使用get来绘制波形的时候,在绘制波形的途中,在缓冲器中的采样很有可能已经改变了,这将造成一个看起来并不连续的波形。而当你使用toArray的时候,你给的是当前缓冲器里内容的副本并且是有保障的,因此在整个过程中不会出现采样的改变。
范例(在线看)
import ddf.minim.*; Minim minim; AudioPlayer groove; void setup() { size(512, 200, P3D); minim = new Minim(this); groove = minim.loadFile("groove.mp3"); groove.loop(); } void draw() { background(0); stroke(255); float[] left = groove.left.toArray(); float[] right = groove.right.toArray(); // 我们仅循环至left.length - 1 因为我们正进入循环内i+1的目录 for ( int i = 0; i < left.length - 1; i++ ) { float x1 = map(i, 0, groove.bufferSize(), 0, width); float x2 = map(i+1, 0, groove.bufferSize(), 0, width); // 我们将这些值乘以50以更好的看到波形 line(x1, height/4 - left[i]*50, x2, height/4 - left[i+1]*50); line(x1, 3*height/4 - right[i]*50, x2, 3*height/4 - right[i+1]*50); } } void stop() { // 记得关闭音频类 groove.close(); // 记得停掉Minim minim.stop(); super.stop(); }
关闭一个AudioSource
当你用完一个对象后,你应到呼叫close来关闭Minim里的全部音频输入输出。这使得用来回放/监听的线路完全的停止并释放那个线路占用的资源。你可以在除方法stop以外的其他地方停止一个音源,就像你在为groove配置一个新的播放器之前你必须呼叫close。如果你不这么做,上一个播放器的线路仍将继续执行而且你没有办法使其停止。
哦!这个好!感谢!