MIDI Java генерирует беспорядочный звук

Я работаю над проектом, в котором мне нужно манипулировать каждым инструментом в файле MIDI в java. Затем я решил получить каждое MIDI-событие с каждой дорожки из последовательности и отправить его на приемник. После этого поток ждет, пока длится каждый тик, а затем делает это снова со следующим тиком. Проблема в том, что звучание инструментов сильно путается, как и их порядок. Я тоже пытался исполнять каждую дорожку по отдельности, но все равно беспорядок! Код:

    Sequence    sequence        = MidiSystem.getSequence(new File(source));
    Synthesizer synth           = MidiSystem.getSynthesizer();

    //Gets a MidiMessage and send it to Synthesizer
    Receiver    rcv             = synth.getReceiver();

    //Contains all tracks and events from MIDI file
    Track[]     tracks          = sequence.getTracks();
    synth.open();

    //If there are tracks
    if(tracks != null)
    {
        //Verify the division type of the sequence (PPQ, SMPT)
        if(sequence.getDivisionType() == Sequence.PPQ)
        {
            int     ppq         = sequence.getResolution();
            //Do the math to get the time (in miliseconds) each tick takes 
            long    tickTime    = TicksToMiliseconds(BPM,ppq);
            //Returns the number of ticks from the longest track
            int     longestTrackTicks   = LongestTrackTicks(tracks);

            //Each iteration sends a new message to 'receiver'
            for(int tick = 0; tick < maiorTick ; tick++)
            {   
                //Iteration of each track
                for(int trackNumber = 0; trackNumber < tracks.length; trackNumber++)
                {
                    //If the number of ticks from a track isn't already finished
                    //continue
                    if(tick < tracks[trackNumber].size())
                    {
                        MidiEvent ev = tracks[trackNumber].get(tick);
                        rcv.send(ev.getMessage(),-1);
                    }
                }
                Thread.sleep(tickTime);
            }

        }
    }
    synth.close();

person Carlos Braile    schedule 16.09.2014    source источник


Ответы (3)


Как сказал ntabee, Track.get(n) возвращает nth событие в дорожке; чтобы получить события по времени, вы должны сравнить время событий вручную.

Кроме того, Thread.sleep() не очень точен и может ждать дольше, чем хотелось бы. Эти ошибки суммируются.


Чтобы изменить MIDI-сообщения в реальном времени, скажите секвенсеру, чтобы он воспроизводил ваш собственный Receiver, затем делайте все, что хотите, с событиями и передайте их «настоящему» Receiver.

person CL.    schedule 16.09.2014

По крайней мере, ваш код выглядит так, будто что-то включается/выключается каждые tickTime мс. период. track.get(tick) просто возвращает tick-е событие в дорожке, не событие(я) на данный момент из tick. Если вашей целью является просто воспроизведение звука, Java предоставляет для этого высокоуровневый API, см., например, http://www.jsresources.org/examples/midi_playback_and_recording.html

person ntabee    schedule 16.09.2014
comment
Проблема в том, что мне нужно манипулировать инструментами во время воспроизведения музыки. Вот почему я не использовал секвенсор раньше. Идея состоит в том, чтобы изменить громкость некоторых инструментов во время игры. Кроме того, track.get(tick) возвращает MIDI-событие. В документации Java говорится, что MIDI-событие имеет MIDI-сообщение, и оно содержит всю информацию о звуке в этот тик. - person Carlos Braile; 16.09.2014

Я решил использовать секвенсор. Я не знал, но метод «старт» запускается в новом потоке, и пока он все еще работает, я могу заглушить любой инструмент, который захочу, и это именно то, что я хотел. Спасибо за ответы!

person Carlos Braile    schedule 16.09.2014