Java声音生成会产生噪音
发布时间:2020-12-15 04:44:23 所属栏目:Java 来源:网络整理
导读:我正在使用 javax.sound来制作声音,但是当你演奏时它们会在背景中产生某种噪音,如果你一次演奏几个音符,它甚至会克服声音.这是代码: public final static double notes[] = new double[] {130.81,138.59,146.83,155.56,164.81,174.61,185,196,207.65,220,23
我正在使用
javax.sound来制作声音,但是当你演奏时它们会在背景中产生某种噪音,如果你一次演奏几个音符,它甚至会克服声音.这是代码:
public final static double notes[] = new double[] {130.81,138.59,146.83,155.56,164.81,174.61,185,196,207.65,220,233.08,246.94,261.63,277.18,293.66,311.13,329.63,349.23,369.99,392,415.3,440,466.16,493.88,523.25,554.37}; public static void playSound(int note,int type) throws LineUnavailableException { //type 0 = sin,type 1 = square Thread t = new Thread() { public void run() { try { int sound = (int) (notes[note] * 100); byte[] buf = new byte[1]; AudioFormat af = new AudioFormat((float) sound,8,1,true,false); SourceDataLine sdl; sdl = AudioSystem.getSourceDataLine(af); sdl = AudioSystem.getSourceDataLine(af); sdl.open(af); sdl.start(); int maxi = (int) (1000 * (float) sound / 1000); for (int i = 0; i < maxi; i++) { double angle = i / ((float) 44100 / 440) * 2.0 * Math.PI; double val = 0; if (type == 0) val = Math.sin(angle)*100; if (type == 1) val = square(angle)*50; buf[0] = (byte) (val * (maxi - i) / maxi); sdl.write(buf,1); } sdl.drain(); sdl.stop(); sdl.close(); } catch (LineUnavailableException e) { // TODO Auto-generated catch block e.printStackTrace(); } }; }; t.start(); } public static double square (double angle){ angle = angle % (Math.PI*2); if (angle > Math.PI) return 1; else return 0; } 此代码来自:https://stackoverflow.com/a/1932537/3787777 解决方法
在这个答案中,我将参考1)你的代码,2)更好的方法(恕我直言:)和3)在同一时间播放两个音符.
你的代码 首先,采样率不应取决于音符频率.因此尝试: AudioFormat(44100,... 接下来,使用16位采样(听起来更好!).这是你的代码,在没有噪音的情况下播放简单的音调 – 但我会稍微使用它(见后面).请查看评论: Thread t = new Thread() { public void run() { try { int sound = (440 * 100); // play A AudioFormat af = new AudioFormat(44100,16,false); SourceDataLine sdl; sdl = AudioSystem.getSourceDataLine(af); sdl.open(af,4096 * 2); sdl.start(); int maxi = (int) (1000 * (float) sound / 1000); // should not depend on notes frequency! byte[] buf = new byte[maxi * 2]; // try to find better len! int i = 0; while (i < maxi * 2) { // formula is changed to be simple sine!! double val = Math.sin(Math.PI * i * 440 / 44100); short s = (short) (Short.MAX_VALUE * val); buf[i++] = (byte) s; buf[i++] = (byte) (s >> 8); // little endian } sdl.write(buf,maxi); sdl.drain(); sdl.stop(); sdl.close(); } catch (LineUnavailableException e) { e.printStackTrace(); } } }; t.start(); 建议更好的代码 以下是代码的简化版本,可以播放一些没有噪音的音符(频率).我更喜欢它,因为我们首先创建双打数组,这是通用值.这些值可以组合在一起,或者存储或进一步修改.然后我们将它们转换为(8位或16位)样本值. private static byte[] buffer = new byte[4096 * 2 / 3]; private static int bufferSize = 0; // plays a sample in range (-1,+1). public static void play(SourceDataLine line,double in) { if (in < -1.0) in = -1.0; // just sanity checks if (in > +1.0) in = +1.0; // convert to bytes - need 2 bytes for 16 bit sample short s = (short) (Short.MAX_VALUE * in); buffer[bufferSize++] = (byte) s; buffer[bufferSize++] = (byte) (s >> 8); // little Endian // send to line when buffer is full if (bufferSize >= buffer.length) { line.write(buffer,buffer.length); bufferSize = 0; } // todo: be sure that whole buffer is sent to line! } // prepares array of doubles,not related with the sampling value! private static double[] tone(double hz,double duration) { double amplitude = 1.0; int N = (int) (44100 * duration); double[] a = new double[N + 1]; for (int i = 0; i <= N; i++) { a[i] = amplitude * Math.sin(2 * Math.PI * i * hz / 44100); } return a; } // finally: public static void main(String[] args) throws LineUnavailableException { AudioFormat af = new AudioFormat(44100,false); SourceDataLine sdl = AudioSystem.getSourceDataLine(af); sdl.open(af,4096 * 2); sdl.start(); double[] tones = tone(440,2.0); // play A for 2 seconds for (double t : tones) { play(sdl,t); } sdl.drain(); sdl.stop(); sdl.close(); } 听起来不错 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |