2

我在使用 JFugue 5.0.7 时遇到了问题:我正在编写一个无限期播放音乐的实时应用程序,但是 jfugue 库提供的 RealtimePlayer 将乐器相互混合。

我有以下代码

public class HelloJFugue {

    public static int BPM = 150;
    public static int SIGNATURE = 3;
    public static boolean RANDOM = false;

    public static void main(String[] args) throws MidiUnavailableException {
        RealtimePlayer player = new RealtimePlayer();
        BlockingQueue<Pattern> queue = new SynchronousQueue<>();

        List<PatternProducer> pProducers = createPatternProducers();

        Thread pConsumer = new Thread(new PatternConsumer(player, queue));
        Thread pProducer = new Thread(new PatternMediator(queue, pProducers));

        pConsumer.start();
        pProducer.start();
    }

    private static List<PatternProducer> createPatternProducers() {
        Random rand = new Random();

        PatternProducer rightHand = new PatternProducer() {
            int counter = 0;
            String[] patterns = {
                "Rq Rq E6i D#6i",
                "E6i D#6i E6i B5i D6i C6i",
                "A5q Ri C5i E5i A5i",
                "B5q Ri E5i G#5i B5i",
                "C6q Ri E5i E6i D#6i",
                "E6i D#6i E6i B5i D6i C6i",
                "A5q Ri C5i E5i A5i",
                "B5q Ri E5i C6i B5i",
                "A5q Ri E5i E6i D#6i"
            };

            @Override
            public Pattern getPattern() {
                Pattern p = new Pattern(patterns[RANDOM ? rand.nextInt(patterns.length - 1) + 1 : counter])
                        .setVoice(0)
                        .setInstrument("Piano");
                counter++;
                if (counter >= patterns.length) {
                    counter = 1;
                }
                return p;
            }
        };

        PatternProducer leftHand = new PatternProducer() {
            int counter = 0;
            String[] patterns = {
                "Rq Rq Rq",
                "Rq Rq Rq",
                "A3i E4i A4i Ri Rq",
                "E3i E4i G#4i Ri Rq",
                "A3i E4i A4i Ri Rq",
                "Rq Rq Rq",
                "A3i E4i A4i Ri Rq",
                "E3i E4i G#4i Ri Rq",
                "A3i E4i A4i Ri Rq"
            };

            @Override
            public Pattern getPattern() {
                Pattern p = new Pattern(patterns[RANDOM ? rand.nextInt(patterns.length - 1) + 1 : counter])
                        .setVoice(1)
                        .setInstrument("Guitar");
                counter++;
                if (counter >= patterns.length) {
                    counter = 1;
                }
                return p;
            }
        };

        return new ArrayList<PatternProducer>() {
            {
                add(rightHand);
                add(leftHand);
            }
        };
    }
}

public class PatternMediator implements Runnable {

    private BlockingQueue<Pattern> queue;
    private List<PatternProducer> producers;

    public PatternMediator(BlockingQueue<Pattern> queue, List<PatternProducer> producers) {
        this.queue = queue;
        this.producers = producers;
    }

    private void fillQueue() throws InterruptedException {
        Pattern p = new Pattern();
        for (PatternProducer producer : producers) {
            p.add(producer.getPattern().setTempo(HelloJFugue.BPM));
        }
        this.queue.put(p);
    }

    @Override
    public void run() {
        while (true) {
            try {
                fillQueue();
            } catch (InterruptedException ex) {
                Logger.getLogger(PatternMediator.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }
}

public class PatternConsumer implements Runnable {

    private RealtimePlayer player;
    private BlockingQueue<Pattern> queue;

    public PatternConsumer(RealtimePlayer player, BlockingQueue<Pattern> queue) {
        this.player = player;
        this.queue = queue;
    }

    private void playFromQueue() throws InterruptedException {
        player.play(queue.take());
    }

    @Override
    public void run() {
        while (true) {
            try {
                playFromQueue();
                Thread.sleep(HelloJFugue.SIGNATURE * 60000 / HelloJFugue.BPM);
            } catch (InterruptedException ex) {
                Logger.getLogger(PatternConsumer.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }
}

问题是,在演奏两种乐器(吉他和钢琴)时会混合在一起,并且两者不能同时演奏。相反,演奏者在两种乐器之间随意切换,因此一次只能听到一种演奏两种模式的乐器。

4

1 回答 1

2

这已通过Atom在 JFugue 5.0.8 中的引入解决。Atom 在一个原子单元中包含语音、乐器和音符信息,因此乐器不会与它们用来演奏的音符断开连接。

我在这里更全面地描述了这个更新:https ://medium.com/@dmkoelle/whats-new-in-jfugue-5-0-8-7479abca3be4

于 2017-04-21T04:48:28.543 回答