OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libjava/] [classpath/] [gnu/] [javax/] [sound/] [midi/] [file/] [MidiFileReader.java] - Blame information for rev 769

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 769 jeremybenn
/* MidiFileReader.java -- Read MIDI files.
2
   Copyright (C) 2006 Free Software Foundation, Inc.
3
 
4
This file is part of GNU Classpath.
5
 
6
GNU Classpath is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2, or (at your option)
9
any later version.
10
 
11
GNU Classpath is distributed in the hope that it will be useful, but
12
WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
General Public License for more details.
15
 
16
You should have received a copy of the GNU General Public License
17
along with GNU Classpath; see the file COPYING.  If not, write to the
18
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19
02110-1301 USA.
20
 
21
Linking this library statically or dynamically with other modules is
22
making a combined work based on this library.  Thus, the terms and
23
conditions of the GNU General Public License cover the whole
24
combination.
25
 
26
As a special exception, the copyright holders of this library give you
27
permission to link this library with independent modules to produce an
28
executable, regardless of the license terms of these independent
29
modules, and to copy and distribute the resulting executable under
30
terms of your choice, provided that you also meet, for each linked
31
independent module, the terms and conditions of the license of that
32
module.  An independent module is a module which is not derived from
33
or based on this library.  If you modify this library, you may extend
34
this exception to your version of the library, but you are not
35
obligated to do so.  If you do not wish to do so, delete this
36
exception statement from your version. */
37
 
38
package gnu.javax.sound.midi.file;
39
 
40
import java.io.DataInputStream;
41
import java.io.File;
42
import java.io.FileInputStream;
43
import java.io.IOException;
44
import java.io.InputStream;
45
import java.net.URL;
46
 
47
import javax.sound.midi.InvalidMidiDataException;
48
import javax.sound.midi.MetaMessage;
49
import javax.sound.midi.MidiEvent;
50
import javax.sound.midi.MidiFileFormat;
51
import javax.sound.midi.MidiMessage;
52
import javax.sound.midi.Sequence;
53
import javax.sound.midi.ShortMessage;
54
import javax.sound.midi.SysexMessage;
55
import javax.sound.midi.Track;
56
 
57
/**
58
 * A MIDI file reader.
59
 *
60
 * This code reads MIDI file types 0 and 1.
61
 *
62
 * There are many decent documents on the web describing the MIDI file
63
 * format.  I didn't bother looking for the official document.  If it
64
 * exists, I'm not even sure if it is freely available.  We should
65
 * update this comment if we find out anything helpful here.
66
 *
67
 * @author Anthony Green (green@redhat.com)
68
 *
69
 */
70
public class MidiFileReader extends javax.sound.midi.spi.MidiFileReader
71
{
72
  /* Get the MidiFileFormat for the given input stream.
73
   * @see javax.sound.midi.spi.MidiFileReader#getMidiFileFormat(java.io.InputStream)
74
   */
75
  public MidiFileFormat getMidiFileFormat(InputStream in)
76
    throws InvalidMidiDataException, IOException
77
  {
78
    DataInputStream din;
79
    if (in instanceof DataInputStream)
80
      din = (DataInputStream) in;
81
    else
82
      din = new DataInputStream(in);
83
 
84
    int type, ntracks, division, resolution, bytes;
85
    float divisionType;
86
 
87
    if (din.readInt() != 0x4d546864) // "MThd"
88
      throw new InvalidMidiDataException("Invalid MIDI chunk header.");
89
 
90
    bytes = din.readInt();
91
    if (bytes < 6)
92
      throw new
93
        InvalidMidiDataException("Invalid MIDI chunk header length: " + bytes);
94
 
95
    type = din.readShort();
96
    if (type < 0 || type > 2)
97
      throw new
98
        InvalidMidiDataException("Invalid MIDI file type value: " + type);
99
 
100
    ntracks = din.readShort();
101
    if (ntracks <= 0)
102
      throw new
103
        InvalidMidiDataException("Invalid number of MIDI tracks: " + ntracks);
104
 
105
    division = din.readShort();
106
    if ((division & 0x8000) != 0)
107
      {
108
        division = -((division >>> 8) & 0xFF);
109
        switch (division)
110
          {
111
          case 24:
112
            divisionType = Sequence.SMPTE_24;
113
            break;
114
 
115
          case 25:
116
            divisionType = Sequence.SMPTE_25;
117
            break;
118
 
119
          case 29:
120
            divisionType = Sequence.SMPTE_30DROP;
121
            break;
122
 
123
          case 30:
124
            divisionType = Sequence.SMPTE_30;
125
            break;
126
 
127
          default:
128
            throw new
129
              InvalidMidiDataException("Invalid MIDI frame division type: "
130
                                       + division);
131
          }
132
        resolution = division & 0xff;
133
      }
134
    else
135
      {
136
        divisionType = Sequence.PPQ;
137
        resolution = division & 0x7fff;
138
      }
139
 
140
    // If we haven't read every byte in the header now, just skip the rest.
141
    din.skip(bytes - 6);
142
 
143
    return new ExtendedMidiFileFormat(type, divisionType, resolution,
144
                                      MidiFileFormat.UNKNOWN_LENGTH,
145
                                      MidiFileFormat.UNKNOWN_LENGTH, ntracks);
146
  }
147
 
148
  /* Get the MidiFileFormat from the given URL.
149
   * @see javax.sound.midi.spi.MidiFileReader#getMidiFileFormat(java.net.URL)
150
   */
151
  public MidiFileFormat getMidiFileFormat(URL url)
152
    throws InvalidMidiDataException, IOException
153
  {
154
    InputStream is = url.openStream();
155
    try
156
      {
157
        return getMidiFileFormat(is);
158
      }
159
    finally
160
      {
161
        is.close();
162
      }
163
  }
164
 
165
  /* Get the MidiFileFormat from the given file.
166
   * @see javax.sound.midi.spi.MidiFileReader#getMidiFileFormat(java.io.File)
167
   */
168
  public MidiFileFormat getMidiFileFormat(File file)
169
    throws InvalidMidiDataException, IOException
170
  {
171
    InputStream is = new FileInputStream(file);
172
    try
173
      {
174
        return getMidiFileFormat(is);
175
      }
176
    finally
177
      {
178
        is.close();
179
      }
180
  }
181
 
182
  /* Get the MIDI Sequence found in this input stream.
183
   * @see javax.sound.midi.spi.MidiFileReader#getSequence(java.io.InputStream)
184
   */
185
  public Sequence getSequence(InputStream is) throws InvalidMidiDataException,
186
    IOException
187
  {
188
    MidiDataInputStream din = new MidiDataInputStream(is);
189
    ExtendedMidiFileFormat mff = (ExtendedMidiFileFormat) getMidiFileFormat(din);
190
 
191
    Sequence seq = new Sequence(mff.getDivisionType(), mff.getResolution());
192
 
193
    int ntracks = mff.getNumberTracks();
194
 
195
    while (ntracks-- > 0)
196
      {
197
        Track track = seq.createTrack();
198
        int Mtrk = din.readInt();
199
        if (Mtrk != 0x4d54726b)
200
          throw new InvalidMidiDataException("Invalid MIDI track header.");
201
        int length = din.readInt();
202
 
203
        int runningStatus = -1;
204
        int click = 0;
205
 
206
        // Set this to true when we've hit an End of Track meta event.
207
        boolean done = false;
208
 
209
        // Read all events.
210
        while (! done)
211
          {
212
            MidiMessage mm;
213
            int dtime = din.readVariableLengthInt();
214
            click += dtime;
215
 
216
            int sbyte = din.readUnsignedByte();
217
 
218
            if (sbyte < 0xf0)
219
              {
220
                ShortMessage sm;
221
                switch (sbyte & 0xf0)
222
                  {
223
                  case ShortMessage.NOTE_OFF:
224
                  case ShortMessage.NOTE_ON:
225
                  case ShortMessage.POLY_PRESSURE:
226
                  case ShortMessage.CONTROL_CHANGE:
227
                  case ShortMessage.PITCH_BEND:
228
                  case ShortMessage.SONG_POSITION_POINTER:
229
                    sm = new ShortMessage();
230
                    sm.setMessage(sbyte, din.readByte(), din.readByte());
231
                    runningStatus = sbyte;
232
                    break;
233
 
234
                  case ShortMessage.PROGRAM_CHANGE:
235
                  case ShortMessage.CHANNEL_PRESSURE:
236
                  case ShortMessage.SONG_SELECT:
237
                  case 0xF5: // FIXME: unofficial bus select. Not in spec??
238
                    sm = new ShortMessage();
239
                    sm.setMessage(sbyte, din.readByte(), 0);
240
                    runningStatus = sbyte;
241
                    break;
242
 
243
                  case ShortMessage.TUNE_REQUEST:
244
                  case ShortMessage.END_OF_EXCLUSIVE:
245
                  case ShortMessage.TIMING_CLOCK:
246
                  case ShortMessage.START:
247
                  case ShortMessage.CONTINUE:
248
                  case ShortMessage.STOP:
249
                  case ShortMessage.ACTIVE_SENSING:
250
                  case ShortMessage.SYSTEM_RESET:
251
                    sm = new ShortMessage();
252
                    sm.setMessage(sbyte, 0, 0);
253
                    runningStatus = sbyte;
254
                    break;
255
 
256
                  default:
257
                    if (runningStatus != - 1)
258
                      {
259
                        switch (runningStatus & 0xf0)
260
                          {
261
                          case ShortMessage.NOTE_OFF:
262
                          case ShortMessage.NOTE_ON:
263
                          case ShortMessage.POLY_PRESSURE:
264
                          case ShortMessage.CONTROL_CHANGE:
265
                          case ShortMessage.PITCH_BEND:
266
                          case ShortMessage.SONG_POSITION_POINTER:
267
                            sm = new ShortMessage();
268
                            sm.setMessage(runningStatus, sbyte, din.readByte());
269
                            break;
270
 
271
                          case ShortMessage.PROGRAM_CHANGE:
272
                          case ShortMessage.CHANNEL_PRESSURE:
273
                          case ShortMessage.SONG_SELECT:
274
                          case 0xF5: // FIXME: unofficial bus select. Not in
275
                                     // spec??
276
                            sm = new ShortMessage();
277
                            sm.setMessage(runningStatus, sbyte, 0);
278
                            continue;
279
 
280
                          case ShortMessage.TUNE_REQUEST:
281
                          case ShortMessage.END_OF_EXCLUSIVE:
282
                          case ShortMessage.TIMING_CLOCK:
283
                          case ShortMessage.START:
284
                          case ShortMessage.CONTINUE:
285
                          case ShortMessage.STOP:
286
                          case ShortMessage.ACTIVE_SENSING:
287
                          case ShortMessage.SYSTEM_RESET:
288
                            sm = new ShortMessage();
289
                            sm.setMessage(runningStatus, 0, 0);
290
                            continue;
291
 
292
                          default:
293
                            throw new
294
                              InvalidMidiDataException("Invalid Short MIDI Event: "
295
                                                       + sbyte);
296
                          }
297
                      }
298
                    else
299
                      throw new
300
                        InvalidMidiDataException("Invalid Short MIDI Event: "
301
                                                 + sbyte);
302
                  }
303
                mm = sm;
304
              }
305
            else if (sbyte == 0xf0 || sbyte == 0xf7)
306
              {
307
                // System Exclusive event
308
                int slen = din.readVariableLengthInt();
309
                byte sysex[] = new byte[slen];
310
                din.readFully(sysex);
311
                SysexMessage sm = new SysexMessage();
312
                sm.setMessage(sbyte, sysex, slen);
313
                mm = sm;
314
                runningStatus = - 1;
315
              }
316
            else if (sbyte == 0xff)
317
              {
318
                // Meta Message
319
                byte mtype = din.readByte();
320
                int mlen = din.readVariableLengthInt();
321
                byte meta[] = new byte[mlen];
322
                din.readFully(meta);
323
                MetaMessage metam = new MetaMessage();
324
                metam.setMessage(mtype, meta, mlen);
325
                mm = metam;
326
 
327
                if (mtype == 0x2f) // End of Track
328
                  done = true;
329
 
330
                runningStatus = - 1;
331
              }
332
            else
333
              {
334
                throw new InvalidMidiDataException("Invalid status byte: "
335
                                                   + sbyte);
336
              }
337
 
338
            track.add(new MidiEvent(mm, click));
339
          }
340
      }
341
 
342
    return seq;
343
  }
344
 
345
  /* Get the MIDI Sequence found at the given URL.
346
   * @see javax.sound.midi.spi.MidiFileReader#getSequence(java.net.URL)
347
   */
348
  public Sequence getSequence(URL url) throws InvalidMidiDataException,
349
    IOException
350
  {
351
    InputStream is = url.openStream();
352
    try
353
      {
354
        return getSequence(is);
355
      }
356
    finally
357
      {
358
        is.close();
359
      }
360
  }
361
 
362
  /* Get the MIDI Sequence found in the given file.
363
   * @see javax.sound.midi.spi.MidiFileReader#getSequence(java.io.File)
364
   */
365
  public Sequence getSequence(File file) throws InvalidMidiDataException,
366
    IOException
367
  {
368
    InputStream is = new FileInputStream(file);
369
    try
370
      {
371
        return getSequence(is);
372
      }
373
    finally
374
      {
375
        is.close();
376
      }
377
  }
378
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.