首页 > 解决方案 > JAVA MIDI 按顺序消除静音

问题描述

不久前我买了一个带有 MIDI 输出的 VDRUM 套件。我以前的项目中有一个树莓派,我想用那台小型计算机作为记录器。

所以我编写了一个在 PI 上运行并监听 VDRUM 套件的 MIDI 输出端口的无头应用程序。在收到除静音以外的输入后,我开始通过 jdk 库进行录制,并将其放在带有时间戳的 samba 服务器上。

这样我就可以保存我玩过的所有东西。现在我已经设置我的音频工作站从 samba 共享中接收这些 MIDI 文件,我注意到,它们通常在 MIDI 文件的开头有一个很长的“静音”部分。

有没有办法以编程方式消除 midi 序列开头的静音?我是这个 MIDI 的新手,还在学习。

这是开始和停止录制的代码:

    public void send(MidiMessage message, long timeStamp) {
        if (message.getStatus() == 254) {
            if (isRecording && timestampOfLastAction.isBefore(LocalTime.now().minus(5, ChronoUnit.SECONDS))) {
                String userDirectory = "/home/pi/";
                DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH-mm-ss");
                LocalDateTime now = LocalDateTime.now();
                String fileName = dtf.format(now) + ".mid";
                sequencer.stopRecording();
                File midiFile = new File(userDirectory + "/MidiRecorder/" + fileName);
                try {
                    Sequence sequence = sequencer.getSequence();
                    MidiSystem.write(sequence, 0, midiFile);
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                Logger.getGlobal().info("STOPPED RECORDING: " + LocalTime.now().toString());
                isRecording = false;
            }

        } else {
            timestampOfLastAction = LocalTime.now();
            if (!isRecording) {
                isRecording = true;
                sequencer = null;
                try {
                    sequencer = MidiSystem.getSequencer();

                    Transmitter transmitter1;
                    Receiver receiver;
                    // Open a connection to the default sequencer (as specified by MidiSystem)
                    sequencer.open();
                    // Get the transmitter class from your input device
                    transmitter1 = this.midiDevice.getTransmitter();
                    // Get the receiver class from your sequencer
                    receiver = sequencer.getReceiver();
                    transmitter1.setReceiver(receiver);
                    Sequence seq = new Sequence(Sequence.PPQ, 24);
                    // And of course a track to record the input on
                    Track currentTrack = seq.createTrack();
                    // Do some sequencer settings
                    sequencer.setSequence(seq);
                    sequencer.setTickPosition(0);
                    sequencer.recordEnable(currentTrack, -1);

                    // And start recording
                    sequencer.startRecording();
                    Logger.getGlobal().info("STARTED RECORDING: " + LocalTime.now().toString());
                } catch (Exception e) {
                    // TODO: handle exception
                } finally {

                }
            }
        }
    }

标签: javamidirecording

解决方案


您需要移动所有MidiEventsSequence以消除领先的沉默。

private void removeLeadingSilence(Sequence sequence)
{
    // Find first event
    long firstEventTick = Long.MAX_VALUE;
    for (Track track : sequence.getTracks())
    {
        if (track.size() > 0)
        {
            firstEventTick = Math.min(firstEventTick, track.get(0).getTick());
        }
    }

    // Shift all events
    for (Track track : sequence.getTracks())
    {
        for (int i = 0; i < track.size(); i++)
        {
            MidiEvent me = track.get(i);
            me.setTick(me.getTick() - firstEventTick);
        }
    }
}

推荐阅读