像之前的章节里提到的,JavaSound使用Line在你的系统和程序间传递音频。每条线路都可以通过它进行声相、平衡、增益和音量调节。优点是你无须在你的合成类里执行以上的控制,但缺点是在回放音频时,只有当你的软件接到采样后这些控制才会起作用。这意味着你在播放一个立体声音频时,即使将平衡调至极右,你也不会在你的采样中看到任何差别。换句话说,当你以为左声道的值为0的时候,它仍将保存原始音频文件左声道内的一起实际存在的东西。另外,在监听音频输入的时候,设置一个控制将被反映入采样缓冲器中,因为它将在你的软件收到音频之前起效。
打印控制
并非所有控制在所有线路上都可用。你可以使用方法printControls打印出一个控制器上可用的控制,同时包括那些控制的范围。
示范代码(在线范例)
import ddf.minim.*; Minim minim; AudioOutput out; void setup() { size(512, 200); minim = new Minim(this); out = minim.getLineOut(); out.printControls(); } void draw() { background(0); } void stop() { // 日完记得关闭Minim音频类 out.close(); minim.stop(); super.stop(); }
询问控制
Controller提供方法hasControl,这样你可以在尝试使用一个控制前测定它是否存在。hasControl的引数为Control.Type。控制器包括三个静态成员(member),他们是BALANCE, GAIN, PAN, MUTE, SAMPLE_RATE和VOLUME。
示范代码(在线范例)
import ddf.minim.*; Minim minim; AudioOutput out; void setup() { size(512, 200); minim = new Minim(this); out = minim.getLineOut(); textFont(createFont("Arial", 12)); } void draw() { background(0); if ( out.hasControl(Controller.PAN) ) { text("The output has a pan control.", 5, 15); } else { text("The output doesn't have a pan control.", 5, 15); } if ( out.hasControl(Controller.VOLUME) ) { text("The output has a volume control.", 5, 30); } else { text("The output doesn't have a volume control.", 5, 30); } if ( out.hasControl(Controller.SAMPLE_RATE) ) { text("The output has a sample rate control.", 5, 45); } else { text("The output doesn't have a sample rate control.", 5, 45); } if ( out.hasControl(Controller.BALANCE) ) { text("The output has a balance control.", 5, 60); } else { text("The output doesn't have a balance control.", 5, 60); } if ( out.hasControl(Controller.MUTE) ) { text("The output has a mute control.", 5, 75); } else { text("The output doesn't have a mute control.", 5, 75); } if ( out.hasControl(Controller.GAIN) ) { text("The output has a gain control.", 5, 90); } else { text("The output doesn't have a gain control.", 5, 105); } } void stop() { // 日完记得XXXXXX out.close(); minim.stop(); super.stop(); }
获取和设置控制器
当你知道了你可以使用什么控制后,你可以使用适当的方法get(获取)和set(设置)操作它们。
setBalance(float value) getBalance() setGain(float value) getGain() setPan(float value) getPan() setVolume(float value) getVolume()
平衡的范围是-1~1,增益常从-80~6,声相也是从-1~1,音量的范围作者说他自己也不知道。。。从所有的使用上,增益基本上等同于音量。以下是操作一个输出的增益的例子。其他控制的例子可以在这里找到。
示范代码(在线范例)
import ddf.minim.*; import ddf.minim.signals.*; Minim minim; AudioOutput out; Oscillator osc; WaveformRenderer waveform; void setup() { size(512, 200); minim = new Minim(this); out = minim.getLineOut(); // see the example AudioOutput >> SawWaveSignal for more about this class osc = new SawWave(100, 0.2, out.sampleRate()); // see the example Polyphonic >> addSignal for more about this out.addSignal(osc); waveform = new WaveformRenderer(); // see the example Recordable >> addListener for more about this out.addListener(waveform); textFont(createFont("Arial", 12)); } void draw() { background(0); // see waveform.pde for more about this waveform.draw(); if ( out.hasControl(Controller.GAIN) ) { // 将鼠标位置映射到可听到的增益范围内 float val = map(mouseX, 0, width, 6, -48); // 如果一个增益控制不可用,这里将什么都不做 out.setGain(val); // 如果一个增益控制不可用,这里将输出0 text("The current gain is " + out.getGain() + ".", 5, 15); } else { text("The output doesn't have a gain control.", 5, 15); } } void stop() { // 日完记得XXXXX out.close(); minim.stop(); super.stop(); }
变化控制
因为反映的是一系列连续值的范围,所以所有这些控制都被称为浮点控制。Controller为持续改变这些控制之一的值提供方法。这被称为变化(shifting)。shifting的方法如下:
shiftBalance(float from, float to, int ms) shiftGain(float from, float to, int ms) shiftPan(float from, float to, int ms) shiftVolume(float from, float to, int ms)
很明显的,from是一个值开始的点,to是目标值,ms是以毫秒计的shift作用时间。
示范代码(在线范例)
import ddf.minim.*; import ddf.minim.signals.*; Minim minim; AudioOutput out; WaveformRenderer waveform; SawWave saw; void setup() { size(512, 200); minim = new Minim(this); out = minim.getLineOut(); waveform = new WaveformRenderer(); // see the example Recordable >> addListener for more about this out.addListener(waveform); // see the example AudioOutput >> SawWaveSignal for more about this saw = new SawWave(100, 0.2, out.sampleRate()); // see the example Polyphonic >> addSignal for more about this out.addSignal(saw); textFont(createFont("Arial", 12)); } void draw() { background(0); // see waveform.pde for more about this waveform.draw(); if ( out.hasControl(Controller.PAN) ) { text("The current pan value is " + out.getPan() + ".", 5, 15); } else { text("The output doesn't have a pan control.", 5, 15); } if ( out.hasControl(Controller.VOLUME) ) { text("The current volume value is " + out.getVolume() + ".", 5, 30); } else { text("The output doesn't have a volume control.", 5, 30); } if ( out.hasControl(Controller.BALANCE) ) { text("The current balance value is " + out.getBalance() + ".", 5, 45); } else { text("The output doesn't have a balance control.", 5, 45); } if ( out.hasControl(Controller.GAIN) ) { text("The current gain value is " + out.getGain() + ".", 5, 60); } else { text("The output doesn't have a gain control.", 5, 60); } } void keyReleased() { if ( key == 'v' ) out.shiftVolume(0, 1, 2000); if ( key == 'g' ) out.shiftGain(-40, 0, 2000); if ( key == 'b' ) out.shiftBalance(-1, 1, 2000); if ( key == 'p' ) out.shiftPan(1, -1, 2000); } void stop() { // always close Minim audio classes when you are finished with them out.close(); minim.stop(); super.stop(); }
静音
如下
isMuted() mute() unmute()
再次,如果静音不是一个可用的控制,静音和非静音将不起任何作用,并会在PDE控制台输出错误信息。
示范代码(在线范例)
import ddf.minim.*; import ddf.minim.signals.*; Minim minim; AudioOutput out; WaveformRenderer waveform; SawWave saw; void setup() { size(512, 200); minim = new Minim(this); out = minim.getLineOut(); waveform = new WaveformRenderer(); // see the example Recordable >> addListener for more about this out.addListener(waveform); // see the example AudioOutput >> SawWaveSignal for more about this saw = new SawWave(100, 0.2, out.sampleRate()); // see the example Polyphonic >> addSignal for more about this out.addSignal(saw); textFont(createFont("Arial", 12)); } void draw() { background(0); // see waveform.pde for more about this waveform.draw(); if ( out.hasControl(Controller.MUTE) ) { if (mousePressed) { out.mute(); } else { out.unmute(); } if ( out.isMuted() ) { text("The output is muted.", 5, 15); } else { text("The output is not muted.", 5, 15); } } else { text("The output doesn't have a mute control.", 5, 15); } } void stop() { // always close Minim audio classes when you are finished with them out.close(); minim.stop(); super.stop(); }
直接使用一个控制
使用控制更直接的方式是使用Controller的方法getControls。这个方法返回Control对象的数组,你可以使用方法getType测定一个控制的类型。
示范代码(在线范例)
import ddf.minim.*; import ddf.minim.signals.*; import javax.sound.sampled.Control; Minim minim; AudioOutput out; Control[] controls; void setup() { size(512, 200); minim = new Minim(this); out = minim.getLineOut(); controls = out.getControls(); textFont(createFont("Arial", 12)); } void draw() { background(0); for ( int i = 0; i < controls.length; i++ ) { text("Control " + (i+1) + " is a " + controls[i].toString() + ".", 5, 15 + i*15); } } void stop() { // always close Minim audio classes when you are finished with them out.close(); minim.stop(); super.stop(); }
所有这些方法都返回适当的FloatControl。以下是使用pan()而不是setPan进入声相控制的例子:
示范代码(在线范例)
import ddf.minim.*; import ddf.minim.signals.*; Minim minim; AudioOutput out; Oscillator osc; WaveformRenderer waveform; void setup() { size(512, 200); minim = new Minim(this); out = minim.getLineOut(); // see the example AudioOutput >> SawWaveSignal for more about this class osc = new SawWave(100, 0.2, out.sampleRate()); // see the example Polyphonic >> addSignal for more about this out.addSignal(osc); waveform = new WaveformRenderer(); // see the example Recordable >> addListener for more about this out.addListener(waveform); textFont(createFont("Arial", 12)); } void draw() { background(0); // see waveform.pde for more about this waveform.draw(); if ( out.hasControl(Controller.PAN) ) { // map the mouse position to the range of the pan float val = map(mouseX, 0, width, out.pan().getMinimum(), out.pan().getMaximum()); out.pan().setValue(val); text("The current pan is " + out.pan().getValue() + ".", 5, 15); } else { text("There is no pan control for this output.", 5, 15); } } void stop() { // always close Minim audio classes when you are finished with them out.close(); minim.stop(); super.stop(); }
要细讲FloatControl的所有方法实在太多,所以还是仔细读读javadoc或者研究一下在线范例们吧。
FloatControl
感谢你的文章^^