除非我弄错了,否则扬声器由一张有许多位置的软盘片组成。在Java中,有没有办法手动设置扬声器的位置?我正在寻找这些方面的东西:
...
Speaker.setPosition(byte position);
// or
setSpeakerPosition(byte position);
...
提前致谢!
答案 0 :(得分:2)
你错了。大多数扬声器不是金属片。 (如果您想了解典型演讲者的工作原理,请尝试:http://electronics.howstuffworks.com/speaker.htm)
在Java中没有办法(将#34;板块#34;移动到特定位置)。我怀疑它甚至可能在硬件级别......除非扬声器是以一种相当奇怪的方式/昂贵/低效的方式实现的。最重要的是,在典型的计算机音频系统中,程序和扬声器板之间有许多硬件和软件组件,其中没有一个设计用于这种方式。
答案 1 :(得分:1)
扬声器板从其静止点相对于其端子上施加的电压移动。正电压使电路板远离线圈,负电压使电池靠近。您可以连接电池并保持恒定的直流电压,电路板将移出并保持在那里(直到扬声器烧坏),因为扬声器在这一点上表现得像一个电阻器。正常的音频信号本质上是AC。
计算机系统驱动扬声器的方式是将一系列时间序列的数值发送到称为D / A转换器的芯片,该芯片将每个特定数值转换为模拟电压。接下来,模拟电压通过放大器发送,最后发送到扬声器。有各种API用于创建数字信号并将它们路由到扬声器。
您可能认为可以创建一个恒定值的数字信号,作为将DC应用于扬声器的一种方式。它不会工作,因为放大器输出端有一个交流耦合滤波器,专门用于保护扬声器免受直流电压影响。它基本上是与扬声器串联的电容器。
您要求做的事情不会像您在PC中找到的那样使用音频放大器。
您可以连接连接到外部扬声器的SW可编程直流电源。
答案 2 :(得分:0)
实际上java中的某些东西很像这样。你只需要了解声音本身不会。如果您只是将扬声器位置设置为一个值并离开它,您最多只会听到一个短暂的脉冲,然后什么都没有。
如果你想让它产生噪音,它必须移动。所以你不要只设置一个位置。你设置了一堆,随着时间的推移改变了价值。这是一个例子:
/** Generates a tone.
@param hz Base frequency (neglecting harmonic) of the tone in cycles per second
@param msecs The number of milliseconds to play the tone.
@param volume Volume, form 0 (mute) to 100 (max).
@param addHarmonic Whether to add an harmonic, one octave up. */
public static void generateTone(int hz,int msecs, int volume, boolean addHarmonic)
throws LineUnavailableException {
float frequency = 44100;
byte[] buf;
AudioFormat af;
if (addHarmonic) {
buf = new byte[2];
af = new AudioFormat(frequency,8,2,true,false);
} else {
buf = new byte[1];
af = new AudioFormat(frequency,8,1,true,false);
}
SourceDataLine sdl = AudioSystem.getSourceDataLine(af);
sdl = AudioSystem.getSourceDataLine(af);
sdl.open(af);
sdl.start();
for(int i=0; i<msecs*frequency/1000; i++){
double angle = i/(frequency/hz)*2.0*Math.PI;
buf[0]=(byte)(Math.sin(angle)*volume);
if(addHarmonic) {
double angle2 = (i)/(frequency/hz)*2.0*Math.PI;
buf[1]=(byte)(Math.sin(2*angle2)*volume*0.6);
sdl.write(buf,0,2);
} else {
sdl.write(buf,0,1);
}
}
sdl.drain();
sdl.stop();
sdl.close();
}
来自https://community.oracle.com/thread/1273219
此处使用的SourceDataLine.write()
与您想象的Speaker.setPosition()
差别不大。每次循环时,将一个字节数组(或谐波关闭时只有一个字节)写入SourceDataLine。字节的值是幅度。在这种情况下,其范围从-100到100。扬声器所处的位置将与理想扬声器中的该值成正比。在真实的扬声器中,它受物理扬声器频率响应的影响:
理想扬声器的频率响应是从0Hz到无穷大的水平线。如果你为狗或座头鲸演奏音乐,这可能是一个问题。对于大多数人来说,虽然这足够接近我们能够听到的理想。特别是如果你添加一点基础和高音来平整它。但是,这意味着您精确控制扬声器位置的能力仅限于一系列频率。
在上面的列表中,他们使用数学来构造一个非常简单的音频。特别是正弦波。听起来不会太棒。事实上,这听起来就像你在听力测试中听到的那样。不管你信不信,你所听过的一切都是很多简单的声音,就像这样加在一起。这就是http://en.wikipedia.org/wiki/Fourier_transform教给我们的东西。
上面列表中的generateTone()
方法将在傅立叶分析中调用Frequency Domain。这里,音频信号是基于频率定义的。 generateTone()
内的数学运算正在将该定义转换为Time Domain。这里,音频信号基于任何一个时间的位置来定义。 SourceDataLine.write()
要求将发言人的职位带到一个特定的位置。
因此,构建问题的方法是:什么java方法控制来自时域的音频? SourceDataLine.write()
只是众多以这种方式工作的人之一。任何可以重现sampled audio(用麦克风录制)的方法都可以在时域中使用。在任何时候,它都具有扬声器位置的期望值。
其他音频API(例如MIDI)在频域中运行更多。当你敲击钢琴上的特定键时,你会要求一个频率。有些细节使这一点复杂化(谐波,攻击,维持等),但这是基本的想法。尝试从如上所示的数学构建有趣的声音是合成器的作用。
还有其他音频格式,其中字节不直接表示特定时间的扬声器位置。有人做压缩。有些是有损的。但肯定有很多音频格式,其中一个字节直接代表扬声器的位置。他们的采样率就是衡量头寸的频率。
在任何情况下,这一切都必须最终转化为在特定时间将扬声器振膜放入特定位置。