我正在寻找可用于在运行时生成声音的 Java 代码 - 而不是播放现有的声音文件。
例如,生成 440 Hz 持续时间为 2 毫秒的锯齿波的最佳代码是什么? 感谢源代码!
我记得我的 Commodore 128 有一个简单的 Sound 命令,它将声音、频率、波形和持续时间作为参数来定义声音。这在很多简单的情况下(快速和肮脏的游戏、声音实验等)都非常有效。
我专门寻找声音效果,而不是音乐或 MIDI(JFugue 库涵盖得很好)。
最佳答案
这是一个可能有用的示例。这会产生正弦波:
package notegenerator;
import java.io.IOException;
/**
* Tone generator and player.
*
* @author Cesar Vezga vcesar@yahoo.com
*/
public class Main {
public static void main(String[] args) throws IOException {
Player player = new Player();
player.play(BeachRock.getTack1(),BeachRock.getTack2());
}
}
package notegenerator;
public class BeachRock {
// GUITAR
static String gs1 = "T332 A4-E4 F#5-C6 E5-A5 T166 G5 A5 F#5 A5 F5 A5 E5-A5 E3 G3 G#3 ";
static String gs2 = "A3 A3 A3 G3 E3 E3 G3 G#3 ";
static String gs3 = "A3 A3 A3 G3 E3 A3 C4 C#4 ";
static String gs4 = gs2 + gs2 + gs2 + gs3;
static String gs5 = "D4 D4 D4 C4 A3 A3 C4 D#4 ";
static String gs6 = "D4 D4 D4 C4 A3 E3 G3 G#3 ";
static String gs7 = gs4 + gs5 + gs6 + gs2 + "A3 A3 A3 G3 E3 B3 D3 D#3 ";
static String gs8 = "E4 E4 E4 D4 B3 B3 E4 B3 " + gs6 + gs2;
static String gs9 = "x E3-B3 E3-B3 E3-B3 E3-B3 E3 G3 G#3 ";
static String gs10 = gs7 + gs8 + gs9;
static String gs11 = "A3-D4 X*7 X*16 X*5 E3 G3 G#3 ";
static String guitar = gs1 + gs10 + gs11 + gs10 + gs11 + "A3 A3 A3";
// DRUMS
static String ds1 = "D2 X D3 D3 X*2 D3 X ";
static String ds2 = "D2 X D3 D3 X D3 D3 D3 ";
static String ds3 = "D2 D3 D3 D3 D3 T83 D3 D3 T166 D3 ";
static String ds4 = ds1 + ds1 + ds1 + ds2;
static String ds5 = ds1 + ds1 + ds1 + ds3;
static String ds6 = "D2*2 D3 D3 X*2 D3*2 ";
static String ds7 = "D2*2 D3 D3 X D3 D3 D3 ";
static String ds8 = ds6 + ds6 + ds6 + ds7;
static String drums = "V25 T166 X*16 " + ds4 + ds4 + ds5 + ds8 + ds4 + ds4
+ ds5 + ds8;
public static String getTack1(){
return guitar;
}
public static String getTack2(){
return drums;
}
}
package notegenerator;
import java.util.HashMap;
/**
*
* Physics of Music - Notes
*
* Frequencies for equal-tempered scale
* This table created using A4 = 440 Hz
* Speed of sound = 345 m/s = 1130 ft/s = 770 miles/hr
*
* ("Middle C" is C4 )
*
* http://www.phy.mtu.edu/~suits/notefreqs.html
*
* @author Cesar Vezga <vcesar@yahoo.com>
*
*/
public class Notes {
private static final Object[] notes = {
"C0",16.35,
"C#0/Db0",17.32,
"D0",18.35,
"D#0/Eb0",19.45,
"E0",20.6,
"F0",21.83,
"F#0/Gb0",23.12,
"G0",24.5,
"G#0/Ab0",25.96,
"A0",27.5,
"A#0/Bb0",29.14,
"B0",30.87,
"C1",32.7,
"C#1/Db1",34.65,
"D1",36.71,
"D#1/Eb1",38.89,
"E1",41.2,
"F1",43.65,
"F#1/Gb1",46.25,
"G1",49.00,
"G#1/Ab1",51.91,
"A1",55.00,
"A#1/Bb1",58.27,
"B1",61.74,
"C2",65.41,
"C#2/Db2",69.3,
"D2",73.42,
"D#2/Eb2",77.78,
"E2",82.41,
"F2",87.31,
"F#2/Gb2",92.5,
"G2",98.00,
"G#2/Ab2",103.83,
"A2",110.00,
"A#2/Bb2",116.54,
"B2",123.47,
"C3",130.81,
"C#3/Db3",138.59,
"D3",146.83,
"D#3/Eb3",155.56,
"E3",164.81,
"F3",174.61,
"F#3/Gb3",185.00,
"G3",196.00,
"G#3/Ab3",207.65,
"A3",220.00,
"A#3/Bb3",233.08,
"B3",246.94,
"C4",261.63, // Middle C
"C#4/Db4",277.18,
"D4",293.66,
"D#4/Eb4",311.13,
"E4",329.63,
"F4",349.23,
"F#4/Gb4",369.99,
"G4",392.00,
"G#4/Ab4",415.3,
"A4",440.00,
"A#4/Bb4",466.16,
"B4",493.88,
"C5",523.25,
"C#5/Db5",554.37,
"D5",587.33,
"D#5/Eb5",622.25,
"E5",659.26,
"F5",698.46,
"F#5/Gb5",739.99,
"G5",783.99,
"G#5/Ab5",830.61,
"A5",880.00,
"A#5/Bb5",932.33,
"B5",987.77,
"C6",1046.5,
"C#6/Db6",1108.73,
"D6",1174.66,
"D#6/Eb6",1244.51,
"E6",1318.51,
"F6",1396.91,
"F#6/Gb6",1479.98,
"G6",1567.98,
"G#6/Ab6",1661.22,
"A6",1760.00,
"A#6/Bb6",1864.66,
"B6",1975.53,
"C7",2093.00,
"C#7/Db7",2217.46,
"D7",2349.32,
"D#7/Eb7",2489.02,
"E7",2637.02,
"F7",2793.83,
"F#7/Gb7",2959.96,
"G7",3135.96,
"G#7/Ab7",3322.44,
"A7",3520.00,
"A#7/Bb7",3729.31,
"B7",3951.07,
"C8",4186.01,
"C#8/Db8",4434.92,
"D8",4698.64,
"D#8/Eb8",4978.03
};
private HashMap<String,Double> noteMap;
public Notes(){
noteMap = new HashMap<String,Double>();
for(int i=0; i<notes.length; i=i+2){
String name = (String)notes[i];
double freq = (Double)notes[i+1];
String[] keys = name.split("/");
for(String key : keys){
noteMap.put(key, freq);
System.out.println(key);
}
}
}
public byte[] getCordData(String keys, double duration){
int N = (int) (8000 * duration/1000);
byte[] a = new byte[N+1];
String[] key = keys.split(" ");
int count=0;
for(String k : key){
double freq = getFrequency(k);
byte[] tone = tone(freq,duration);
if(count==0){
a = tone;
}else{
a = addWaves(a,tone);
}
count++;
}
return a;
}
public byte[] addWaves(byte[] a, byte[] b){
int len = Math.max(a.length, b.length);
byte[] c = new byte[len];
for(int i=0; i<c.length; i++){
byte aa = ( i < a.length ? a[i] : 0);
byte bb = ( i < b.length ? b[i] : 0);
c[i] = (byte) (( aa + bb ) / 2);
}
return c;
}
public double getFrequency(String key){
Double f = noteMap.get(key);
if(f==null){
System.out.println("Key not found. "+key);
f = 0D;
}
return f;
}
public byte[] tone(String key, double duration) {
double freq = getFrequency(key);
return tone(freq,duration);
}
public byte[] tone(double hz, double duration) {
int N = (int) (8000 * duration/1000);
byte[] a = new byte[N+1];
for (int i = 0; i <= N; i++) {
a[i] = (byte) ( Math.sin(2 * Math.PI * i * hz / 8000) * 127 );
}
return a;
}
}
package notegenerator;
import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;
public class Player {
private SourceDataLine line = null;
private Notes notes = new Notes();
private long time = 250;
private double volumen = 1;
public void play(String keys) {
byte[] data = parse(keys);
start();
line.write(data, 0, data.length);
stop();
}
public void play(String... track) {
byte[] data2 = parseAll(track);
if (data2 != null) {
start();
line.write(data2, 0, data2.length);
stop();
}
}
private byte[] parseAll(String... track) {
byte[] data2 = null;
for (String t : track) {
byte[] data1 = parse(t);
if (data2 == null) {
data2 = data1;
} else {
data2 = notes.addWaves(data1, data2);
}
}
return data2;
}
private byte[] parse(String song) {
time = 250;
volumen = 1;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
String[] key = song.split(" ");
byte[] data = null;
for (String k : key) {
int mult = 1;
if (k.indexOf("*") > -1) {
String keyAux = k.split("\\*")[0];
mult = Integer.parseInt(k.split("\\*")[1]);
k = keyAux;
} else if (k.startsWith("T")) {
time = Long.parseLong(k.substring(1));
continue;
} else if (k.startsWith("V")) {
volumen = Double.parseDouble(k.substring(1)) / 100;
if(volumen>1) volumen = 1;
if(volumen<0) volumen = 0;
continue;
}
if (k.indexOf("-") > -1) {
k = k.replaceAll("-", " ").trim();
data = notes.getCordData(k, time * mult);
} else {
data = notes.tone(k, time * mult);
}
volumen(data);
try {
baos.write(data);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return baos.toByteArray();
}
private void volumen(byte[] data) {
for(int i=0; i<data.length; i++){
data[i] = (byte) (data[i] * volumen);
}
}
private void stop() {
line.drain();
line.stop();
}
private void start() {
AudioFormat format = new AudioFormat(8000.0F, 8, 1, true, false);
SourceDataLine.Info info = new DataLine.Info(SourceDataLine.class,
format); // format
// is
// an
// AudioFormat
// object
if (!AudioSystem.isLineSupported(info)) {
System.out.println("Format not supported");
System.exit(1);
}
// Obtain and open the line.
try {
line = (SourceDataLine) AudioSystem.getLine(info);
line.open(format);
} catch (LineUnavailableException ex) {
ex.printStackTrace();
}
// Assume that the TargetDataLine, line, has already
// been obtained and opened.
int numBytesRead;
line.start();
}
public void save(String track, String fname) throws IOException {
byte[] data = parse(track);
FileOutputStream fos = new FileOutputStream(fname);
fos.write(data);
fos.flush();
fos.close();
}
}
关于java - 如何在Java中生成音效?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/297070/
出于纯粹的兴趣,我很好奇如何按顺序创建PI,而不是在过程结果之后生成数字,而是让数字在过程本身生成时显示。如果是这种情况,那么数字可以自行产生,我可以对以前看到的数字实现垃圾收集,从而创建一个无限系列。结果只是在Pi系列之后每秒生成一个数字。这是我通过互联网筛选的结果:这是流行的计算机友好算法,类机器算法:defarccot(x,unity)xpow=unity/xn=1sign=1sum=0loopdoterm=xpow/nbreakifterm==0sum+=sign*(xpow/n)xpow/=x*xn+=2sign=-signendsumenddefcalc_pi(digits
如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby
我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%
exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby中使用两个参数异步运行exe吗?我已经尝试过ruby命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何rubygems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除
鉴于我有以下迁移:Sequel.migrationdoupdoalter_table:usersdoadd_column:is_admin,:default=>falseend#SequelrunsaDESCRIBEtablestatement,whenthemodelisloaded.#Atthispoint,itdoesnotknowthatusershaveais_adminflag.#Soitfails.@user=User.find(:email=>"admin@fancy-startup.example")@user.is_admin=true@user.save!ende
我正在为一个项目制作一个简单的shell,我希望像在Bash中一样解析参数字符串。foobar"helloworld"fooz应该变成:["foo","bar","helloworld","fooz"]等等。到目前为止,我一直在使用CSV::parse_line,将列分隔符设置为""和.compact输出。问题是我现在必须选择是要支持单引号还是双引号。CSV不支持超过一个分隔符。Python有一个名为shlex的模块:>>>shlex.split("Test'helloworld'foo")['Test','helloworld','foo']>>>shlex.split('Test"
我实际上是在尝试使用RVM在我的OSX10.7.5上更新ruby,并在输入以下命令后:rvminstallruby我得到了以下回复:Searchingforbinaryrubies,thismighttakesometime.Checkingrequirementsforosx.Installingrequirementsforosx.Updatingsystem.......Errorrunning'requirements_osx_brew_update_systemruby-2.0.0-p247',pleaseread/Users/username/.rvm/log/138121
我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/
这可能是个愚蠢的问题。但是,我是一个新手......你怎么能在交互式rubyshell中有多行代码?好像你只能有一条长线。按回车键运行代码。无论如何我可以在不运行代码的情况下跳到下一行吗?再次抱歉,如果这是一个愚蠢的问题。谢谢。 最佳答案 这是一个例子:2.1.2:053>a=1=>12.1.2:054>b=2=>22.1.2:055>a+b=>32.1.2:056>ifa>b#Thecode‘if..."startsthedefinitionoftheconditionalstatement.2.1.2:057?>puts"f
我是一个Rails初学者,但我想从我的RailsView(html.haml文件)中查看Ruby变量的内容。我试图在ruby中打印出变量(认为它会在终端中出现),但没有得到任何结果。有什么建议吗?我知道Rails调试器,但更喜欢使用inspect来打印我的变量。 最佳答案 您可以在View中使用puts方法将信息输出到服务器控制台。您应该能够在View中的任何位置使用Haml执行以下操作:-puts@my_variable.inspect 关于ruby-on-rails-如何在我的R