All Downloads are FREE. Search and download functionalities are using the official Maven repository.

META-INF.modules.java.desktop.classes.com.sun.media.sound.StandardMidiFileWriter Maven / Gradle / Ivy

/*
 * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package com.sun.media.sound;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.io.SequenceInputStream;
import java.util.Objects;

import javax.sound.midi.InvalidMidiDataException;
import javax.sound.midi.MetaMessage;
import javax.sound.midi.MidiEvent;
import javax.sound.midi.Sequence;
import javax.sound.midi.ShortMessage;
import javax.sound.midi.SysexMessage;
import javax.sound.midi.Track;
import javax.sound.midi.spi.MidiFileWriter;

/**
 * MIDI file writer.
 *
 * @author Kara Kytle
 * @author Jan Borgersen
 */
public final class StandardMidiFileWriter extends MidiFileWriter {

    private static final int MThd_MAGIC = 0x4d546864;  // 'MThd'
    private static final int MTrk_MAGIC = 0x4d54726b;  // 'MTrk'

    private static final int ONE_BYTE   = 1;
    private static final int TWO_BYTE   = 2;
    private static final int SYSEX      = 3;
    private static final int META       = 4;
    private static final int ERROR      = 5;
    private static final int IGNORE     = 6;

    private static final int MIDI_TYPE_0 = 0;
    private static final int MIDI_TYPE_1 = 1;

    private static final int bufferSize = 16384;  // buffersize for write
    private DataOutputStream tddos;               // data output stream for track writing

    /**
     * MIDI parser types.
     */
    private static final int[] types = {
        MIDI_TYPE_0,
        MIDI_TYPE_1
    };

    @Override
    public int[] getMidiFileTypes() {
        int[] localArray = new int[types.length];
        System.arraycopy(types, 0, localArray, 0, types.length);
        return localArray;
    }

    /**
     * Obtains the file types that this provider can write from the
     * sequence specified.
     * @param sequence the sequence for which midi file type support
     * is queried
     * @return array of file types.  If no file types are supported,
     * returns an array of length 0.
     */
    @Override
    public int[] getMidiFileTypes(Sequence sequence){
        int[] typesArray;
        Track[] tracks = sequence.getTracks();

        if( tracks.length==1 ) {
            typesArray = new int[2];
            typesArray[0] = MIDI_TYPE_0;
            typesArray[1] = MIDI_TYPE_1;
        } else {
            typesArray = new int[1];
            typesArray[0] = MIDI_TYPE_1;
        }

        return typesArray;
    }

    @Override
    public int write(Sequence in, int type, OutputStream out) throws IOException {
        Objects.requireNonNull(out);
        if (!isFileTypeSupported(type, in)) {
            throw new IllegalArgumentException("Could not write MIDI file");
        }
        byte [] buffer = null;

        int bytesRead = 0;
        long bytesWritten = 0;

        // First get the fileStream from this sequence
        InputStream fileStream = getFileStream(type,in);
        if (fileStream == null) {
            throw new IllegalArgumentException("Could not write MIDI file");
        }
        buffer = new byte[bufferSize];

        while( (bytesRead = fileStream.read( buffer )) >= 0 ) {
            out.write( buffer, 0, bytesRead );
            bytesWritten += bytesRead;
        }
        // Done....return bytesWritten
        return (int) bytesWritten;
    }

    @Override
    public int write(Sequence in, int type, File out) throws IOException {
        Objects.requireNonNull(in);
        FileOutputStream fos = new FileOutputStream(out); // throws IOException
        int bytesWritten = write( in, type, fos );
        fos.close();
        return bytesWritten;
    }

    //=================================================================================

    private InputStream getFileStream(int type, Sequence sequence) throws IOException {
        Track[] tracks = sequence.getTracks();
        int bytesBuilt = 0;
        int headerLength = 14;
        int length = 0;
        int timeFormat;
        float divtype;

        PipedOutputStream   hpos = null;
        DataOutputStream    hdos = null;
        PipedInputStream    headerStream = null;

        InputStream[]         trackStreams  = null;
        InputStream         trackStream = null;
        InputStream fStream = null;

        // Determine the filetype to write
        if( type==MIDI_TYPE_0 ) {
            if (tracks.length != 1) {
                return null;
            }
        } else if( type==MIDI_TYPE_1 ) {
            if (tracks.length < 1) { // $$jb: 05.31.99: we _can_ write TYPE_1 if tracks.length==1
                return null;
            }
        } else {
            if(tracks.length==1) {
                type = MIDI_TYPE_0;
            } else if(tracks.length>1) {
                type = MIDI_TYPE_1;
            } else {
                return null;
            }
        }

        // Now build the file one track at a time
        // Note that above we made sure that MIDI_TYPE_0 only happens
        // if tracks.length==1

        trackStreams = new InputStream[tracks.length];
        int trackCount = 0;
        for(int i=0; i 1 ){
            trackStream = trackStreams[0];
            for(int i=1; i 0) && ((value & (mask << shift)) == 0)) shift-=7;
        // then write actual values
        while (shift > 0) {
            tddos.writeByte((int) (((value & (mask << shift)) >> shift) | 0x80));
            shift-=7;
            len++;
        }
        tddos.writeByte((int) (value & mask));
        return len;
    }

    private InputStream writeTrack( Track track, int type ) throws IOException, InvalidMidiDataException {
        int bytesWritten = 0;
        int lastBytesWritten = 0;
        int size = track.size();
        PipedOutputStream thpos = new PipedOutputStream();
        DataOutputStream  thdos = new DataOutputStream(thpos);
        PipedInputStream  thpis = new PipedInputStream(thpos);

        ByteArrayOutputStream tdbos = new ByteArrayOutputStream();
        tddos = new DataOutputStream(tdbos);
        ByteArrayInputStream tdbis = null;

        SequenceInputStream  fStream = null;

        long currentTick = 0;
        long deltaTick = 0;
        long eventTick = 0;
        int runningStatus = -1;

        // -----------------------------
        // Write each event in the track
        // -----------------------------
        for(int i=0; i




© 2015 - 2025 Weber Informatics LLC | Privacy Policy