像之前的章节里提到的,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
感谢你的文章^^