Воспроизведение файлов WAV одновременно в режиме реального времени с использованием Java

У меня возникли трудности с использованием JSyn для одновременных WAV в реальном времени.

Я пытаюсь создать собственную клавиатуру с настроенными тонами, и я записал все мелодии в формате WAV.

Я сослался на файл PlaySample.java JSyn и попытался использовать тот же метод для клавиатуры, но проблема в том, что каждый семпл должен воспроизводиться сразу после нажатия клавиши из графического интерфейса, но VariableRateDataReader предоставляет dataQueue для воспроизведения семпла. Таким образом, если какой-либо сэмпл уже воспроизводится, и одновременно нажимается какая-то другая клавиша, другой файл сэмпла будет воспроизведен после первого, так что это приведет к задержке, и первый сэмпл должен продолжить воспроизведение даже после нажатия некоторых других клавиш.

Demo.java

public class Demo {
    private Synthesizer synth;
    private VariableRateDataReader samplePlayer;
    private LineOut lineOut;

    private void test() {
        synth = JSyn.createSynthesizer();
        FloatSample cSharpSample;
        FloatSample dSharpSample;
        FloatSample eSample;
        FloatSample dSample;
        FloatSample bSample;
        FloatSample fSharpSample;
        FloatSample gSharpSample;
        try {
            lineOut = new LineOut();

            synth.add(lineOut);
            SampleLoader.setJavaSoundPreferred(false);
            cSharpSample = SampleLoader.loadFloatSample(getClass().getResourceAsStream("/resources/wav/octapad/c#.wav"));
            dSharpSample = SampleLoader.loadFloatSample(getClass().getResourceAsStream("/resources/wav/octapad/d#.wav"));
            eSample = SampleLoader.loadFloatSample(getClass().getResourceAsStream("/resources/wav/octapad/e.wav"));
            bSample = SampleLoader.loadFloatSample(getClass().getResourceAsStream("/resources/wav/octapad/b.wav"));
            fSharpSample = SampleLoader.loadFloatSample(getClass().getResourceAsStream("/resources/wav/octapad/f#.wav"));
            gSharpSample = SampleLoader.loadFloatSample(getClass().getResourceAsStream("/resources/wav/octapad/g#.wav"));

            synth.add(samplePlayer = new VariableRateStereoReader());

            samplePlayer.output.connect(0, lineOut.input, 0);
            samplePlayer.output.connect(1, lineOut.input, 1);

            synth.start();

            samplePlayer.rate.set(cSharpSample.getFrameRate());

            lineOut.start();

            double gap = 100;

            // shouldplay e c# b g#, only g# is being played

            samplePlayer.dataQueue.queueOn(eSample);
            samplePlayer.dataQueue.queueOn(cSharpSample);
            samplePlayer.dataQueue.queueOn(bSample);
            samplePlayer.dataQueue.queueOn(gSharpSample);

            do {
                synth.sleepFor(20.0);
            } while (samplePlayer.dataQueue.hasMore());

            synth.sleepFor(0.5);

        } catch (IOException e1) {
            e1.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        synth.stop();
    }

    public static void main(String[] args) {
        new Demo().test();
    }
}

Так что вопрос в том; Есть ли какой-либо API, доступный через JSyn, с помощью которого я могу одновременно воспроизводить файлы WAV, не останавливая сэмпл, который в данный момент воспроизводится? И я не хочу использовать SOX или любой другой метод для воспроизведения файлов WAV, это должно быть сделано только с использованием Java.

1 ответ

Решение

Если вы хотите воспроизвести 8 сэмплов одновременно, вам нужно 8 блоков VariableRateDataReader. Подключите их все к LineOut, и они автоматически смешаются.

Вы можете иметь один VariableRateDataReader для каждого образца. Или вы можете иметь только несколько считывателей и динамически назначать считыватель для образца по мере необходимости.

Есть встроенные классы, которые могут помочь. JSyn VoiceAllocator назначит объекты UnitVoice. Каждый UnitVoice может содержать VariableRateDataReader.

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