JFugue RealtimePlayer не может играть на нескольких инструментах одновременно

У меня возникла проблема с JFugue 5.0.7: я кодирую приложение реального времени, которое играет музыку бесконечно, но RealtimePlayer, предоставляемый библиотекой jfugue, смешивает инструменты друг с другом.

У меня есть следующий код

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

Проблема заключается в том, что при игре на двух инструментах (гитаре и пианино) они смешиваются, и на них нельзя играть одновременно. Вместо этого игрок случайно переключается между двумя инструментами, так что только один инструмент, играющий на обоих паттернах, может быть услышан одновременно.

1 ответ

Это было решено с введением Atom в JFugue 5.0.8. Атом содержит информацию о голосе, инструментах и ​​нотах в одном атомном блоке, поэтому инструменты не будут отключены от нот, которые они используют для воспроизведения.

Я опишу это обновление более подробно здесь: https://medium.com/@dmkoelle/whats-new-in-jfugue-5-0-8-7479abca3be4

Другие вопросы по тегам