如何使用javax.sound.sampled包同时播放一组频率(和弦) [英] How to play a set of frequencies (Chords) at the same time with javax.sound.sampled package

查看:151
本文介绍了如何使用javax.sound.sampled包同时播放一组频率(和弦)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am trying to implement a system where I give a set of frequencies to be played at once, currently can play each frequency individually. Below I have a code, that plays the given frequency, one at a time.

    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);

}

}

推荐答案

在此示例中, Tone 为每个 Note 打开一个 SourceDataLine ,但你可以打开尽可能多的行你的和弦中的音符。然后只需 write()每个注意的和弦到一个单独的行。您可以使用 Note.REST 创建琶音效果。

In this example, Tone opens a single SourceDataLine for each Note, but you can open as many lines as there are notes in your chord. Then simply write() each Note of the chord to a separate line. You can create an arpeggio effect by using Note.REST.

这篇关于如何使用javax.sound.sampled包同时播放一组频率(和弦)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆