gpt4 book ai didi

java - 如何使用 javax.sound.sampled 包同时播放一组频率(和弦)

转载 作者:行者123 更新时间:2023-11-29 03:43:58 24 4
gpt4 key购买 nike

我正在尝试实现一个系统,在该系统中我可以同时播放一组频率,目前可以单独播放每个频率。下面我有一个代码,它播放给定的频率,一次播放一个。

    import java.applet.*;
import java.io.*;
import java.net.*;
import javax.sound.sampled.*;

public final class StdAudio {

public static final int SAMPLE_RATE = 44100;

private static final int BYTES_PER_SAMPLE = 2; // 16-bit audio
private static final int BITS_PER_SAMPLE = 16; // 16-bit audio
private static final double MAX_16_BIT = Short.MAX_VALUE; // 32,767
private static final int SAMPLE_BUFFER_SIZE = 4096;


private static SourceDataLine line; // to play the sound
private static byte[] buffer; // our internal buffer
private static int bufferSize = 0;

// not-instantiable
private StdAudio() { }


// static initializer
static { init(); }

// open up an audio stream
private static void init() {
try {
// 44,100 samples per second, 16-bit audio, mono, signed PCM, little Endian
AudioFormat format = new AudioFormat((float) SAMPLE_RATE, BITS_PER_SAMPLE, 1, true, false);
DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);

line = (SourceDataLine) AudioSystem.getLine(info);
line.open(format, SAMPLE_BUFFER_SIZE * BYTES_PER_SAMPLE);

buffer = new byte[SAMPLE_BUFFER_SIZE * BYTES_PER_SAMPLE/3];
} catch (Exception e) {
System.out.println(e.getMessage());
System.exit(1);
}

// no sound gets made before this call
line.start();
}


/**
* Close standard audio.
*/
public static void close() {
line.drain();
line.stop();
}

/**
* Write one sample (between -1.0 and +1.0) to standard audio. If the sample
* is outside the range, it will be clipped.
*/
public static void play(double in) {

// clip if outside [-1, +1]
if (in < -1.0) in = -1.0;
if (in > +1.0) in = +1.0;

// convert to bytes
short s = (short) (MAX_16_BIT * in);
buffer[bufferSize++] = (byte) s;
buffer[bufferSize++] = (byte) (s >> 8); // little Endian

// send to sound card if buffer is full
if (bufferSize >= buffer.length) {
line.write(buffer, 0, buffer.length);
bufferSize = 0;
}
}

/**
* Write an array of samples (between -1.0 and +1.0) to standard audio. If a sample
* is outside the range, it will be clipped.
*/
public static void play(double[] input) {
for (int i = 0; i < input.length; i++) {
play(input[i]);
}
}

private static double[] tone(double hz, double duration) {
int N = (int) (StdAudio.SAMPLE_RATE * duration);
double[] a = new double[N+1];
for (int i = 0; i <= N; i++)
a[i] = amplitude * Math.sin(2 * Math.PI * i * hz / StdAudio.SAMPLE_RATE);
return a;
}

/**
* Test client - play an A major scale to standard audio.
*/
public static void main(String[] args) {


double hz = 440.4// 440.4 Hz for 1 sec
double duration = 1.0;

double[] a = tone(hz,duration);
StdAudio.play(a);

}

最佳答案

只需将每个时间点的样本值相加,然后除以适当的比例因子即可使您的值保持在范围内。例如,同时播放 A 440 和 C 523.25:

double[] a = tone(440,1.0);
double[] b = tone(523.25,1.0);
for( int i=0; i<a.length; ++ i )
a[i] = ( a[i] + b[i] ) / 2;
StdAudio.play(a);

关于java - 如何使用 javax.sound.sampled 包同时播放一组频率(和弦),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11881595/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com