Вопрос относительно жесткого кодирования и создания MIDI-событий

#midi

#midi

Вопрос:

В настоящее время я работаю над проектом по изменению MIDI-песни и ее удлинению, а также изменению некоторых инструментов и скорости. Одно из требований к проекту заключается в следующем:

«Не составляйте длинный список жестко запрограммированных Midi-событий. Вам необходимо изменить метод setMidiEvents, чтобы программно добавлять дополнительные группы Midi-событий «.

Я не понимаю этого требования. Жесткое кодирование — это когда код не меняется и остается неизменным на протяжении всей программы, и в нем говорится, что не нужно составлять длинный список, поэтому я предположил, что это означает не добавлять в длинный список промежуточных событий. Однако в требовании также указано, что мне нужно изменить метод setMidiEvents, чтобы добавить больше групп Midi-событий, то есть метод с включенным длинным списком. Итак, я должен создать совершенно новое Midi-событие с помощью private void addMidiEvent? Или просто добавить в список setMidiEvents? Извините за глупый вопрос, но я просто хочу прояснить это, прежде чем начать кодирование.

Ниже приведен пример, который был дан нам для изменения.

Код, используемый в качестве примера: https://github.com/ksnortum/midi-examples/blob/master/src/main/java/net/snortum/play/midi/PlaySequencer.java

 /**
 * Plays "Mary Had a Little Lamb" on the default software sequencer by
 * constructing each MIDI event by hand.
 * 
 * @author Knute Snortum
 * @version 2017-06-27
 */
public class PlaySequencer {

    /** 
     * To use a specific sequencer, you can run {@link MidiDeviceDisplay} to
     * discover the names of other sequencers on your system.
     * 
     * @see KeyboardToSynth
     */
    private static final String SEQ_DEV_NAME = "default";
    private static final String SEQ_PROP_KEY = "javax.sound.midi.Sequence";

    public static void main(String[] args) {
        new PlaySequencer().run();
    }

    private void run() {
        
        // Get default sequencer, if it exists
        Sequencer sequencer = getSequencer();

        if (sequencer == null) {
            return;
        }

        try {
            sequencer.open();
        } catch (MidiUnavailableException e1) {
            e1.printStackTrace();
            return;
        }
        
        sequencer.setTempoInBPM(144.0f);

        // Input MIDI data
        try {
            sequencer.setSequence(getMidiInputData());
        } catch (InvalidMidiDataException e1) {
            e1.printStackTrace();
            return;
        }

        // Play sequence
        // Sleep, or first note is too long
        sleep(200);
        sequencer.start();

        while (sequencer.isRunning()) {
            sleep(1000);
        }

        // Sleep or last note is clipped
        sleep(200);
        sequencer.close();
    }

    // Create a sequence and set all MIDI events
    private Sequence getMidiInputData() {
        int ticksPerQuarterNote = 4;
        Sequence seq;
        try {
            seq = new Sequence(Sequence.PPQ, ticksPerQuarterNote);
            setMidiEvents(seq.createTrack());
        } catch (InvalidMidiDataException e) {
            e.printStackTrace();
            return null;
        }
        return seq;
    }

    // Set MIDI events to play "Mary Had a Little Lamb"
    private void setMidiEvents(Track track) {
        int channel = 0;
        int velocity = 64;
        int note = 61;
        int tick = 0;
        addMidiEvent(track, ShortMessage.NOTE_ON, channel, note, velocity, tick);
        addMidiEvent(track, ShortMessage.NOTE_OFF, channel, note, 0, tick   3);
        addMidiEvent(track, ShortMessage.NOTE_ON, channel, note - 2, velocity, tick   4);
        addMidiEvent(track, ShortMessage.NOTE_OFF, channel, note - 2, 0, tick   7);
        addMidiEvent(track, ShortMessage.NOTE_ON, channel, note - 4, velocity, tick   8);
        addMidiEvent(track, ShortMessage.NOTE_OFF, channel, note - 4, 0, tick   11);
        addMidiEvent(track, ShortMessage.NOTE_ON, channel, note - 2, velocity, tick   12);
        addMidiEvent(track, ShortMessage.NOTE_OFF, channel, note - 2, 0, tick   15);
        addMidiEvent(track, ShortMessage.NOTE_ON, channel, note, velocity, tick   16);
        addMidiEvent(track, ShortMessage.NOTE_OFF, channel, note, 0, tick   19);
        addMidiEvent(track, ShortMessage.NOTE_ON, channel, note, velocity, tick   20);
        addMidiEvent(track, ShortMessage.NOTE_OFF, channel, note, 0, tick   23);
        addMidiEvent(track, ShortMessage.NOTE_ON, channel, note, velocity, tick   24);
        addMidiEvent(track, ShortMessage.NOTE_OFF, channel, note, 0, tick   31);
    }

    // Create a MIDI event and add it to the track
    private void addMidiEvent(Track track, int command, int channel, int data1,
            int data2, int tick) {
        ShortMessage message = new ShortMessage();
        try {
            message.setMessage(command, channel, data1, data2);
        } catch (InvalidMidiDataException e) {
            e.printStackTrace();
        }
        track.add(new MidiEvent(message, tick));
    }

    /**
     * @return a specific sequencer object by setting the system property,
     *         otherwise the default
     */
    private Sequencer getSequencer() {
        if (!SEQ_DEV_NAME.isEmpty()
                || !"default".equalsIgnoreCase(SEQ_DEV_NAME)) {
            System.setProperty(SEQ_PROP_KEY, SEQ_DEV_NAME);
        }

        try {
            return MidiSystem.getSequencer();
        } catch (MidiUnavailableException e) {
            System.err.println("Error getting sequencer");
            e.printStackTrace();
            return null;
        }
    }

    private void sleep(long millis) {
        try {
            Thread.sleep(millis);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}
 

Ответ №1:

Один из простых способов сделать песню длиннее — setMidiEvents() это ввести в метод параметр scale, который изменяет фактическую позицию тика каждой ноты.

 addMidiEvent(track, ShortMessage.NOTE_OFF, channel, note, 0, scale * (tick   3));
 

Если масштаб равен 1, вы получаете свою оригинальную песню. Если масштаб равен 2, песня будет в два раза длиннее (или темп будет ощущаться в два раза медленнее).