JDK-4427890 : Sequencer.getTickLength() and Sequence.getTickLength() report the wrong length
  • Type: Bug
  • Component: client-libs
  • Sub-Component: javax.sound
  • Affected Version: 2.1,1.3.0,1.4.0
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • OS: generic,windows_xp
  • CPU: generic,x86
  • Submitted: 2001-03-20
  • Updated: 2004-04-20
  • Resolved: 2002-11-20
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other
1.4.2 mantisFixed
Related Reports
Duplicate :  
Duplicate :  
Relates :  
Description

Name: yyT116575			Date: 03/20/2001


legion:source> java -version
java version "1.3.0"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.0)
Java HotSpot(TM) Client VM (build 1.3.0, mixed mode)


Sequencer.getTickLength() and Sequence.getTickLength() report a wrong total tick
length.

When checking the actual tick position (Sequencer.getTickPosition()) and
comparing it with Sequencer.getTickLength() near the end of a track, the total
tick length reported by Sequencer.getTickLength() has to be divided by 64 in
order to correspond with the tick length reported by
Sequencer.getTickPosition().

I attached a little program demonstrating the problem as well as the work around. The
program creates a simple MIDI sequence and plays is. It implements MetaEventListener, so one
can track the actual tick position of the sequence played. It also supplies the total length
in ticks (according to the sequencer (wrong)) and the corrected one (original divided by
64).  This problem is machine and operating system independent (I tried it on a Ultra 1
running Solaris and on a PIII with Windows 2000).

source code:

import javax.sound.midi.*;

public class TickLengthTester implements MetaEventListener {
  private Sequence          theSequence;
  private Sequencer         theSequencer;
  private Synthesizer       theSynthesizer;

  public TickLengthTester() {
    this.initMidiCompoments();
    theSequence = this.generateSequence();
    try {
      theSequencer.setSequence(theSequence);
    }
    catch(Exception e) {
      System.out.println(this.getClass()+"\tCannot set sequence to sequencer ("+e+")");
      return;
    }
  }

  public  void start() {
    theSequencer.start();
  }

  /* 
    instantiate the necessary midi components
   */

  private void initMidiCompoments() {

    try {
      theSynthesizer = MidiSystem.getSynthesizer();
    }
    catch(Exception e) {
      System.out.println(this.getClass()+"\tSynthesizer Device not supported ("+e+")");
      System.exit(1);
    }

    try {
      theSynthesizer.open();
    }
    catch(Exception e) {
      System.out.println(this.getClass()+"\tCannot open Synthesizer Device ("+e+")");
      System.exit(1);
    }
    
    try {
      theSequencer = MidiSystem.getSequencer();
    }
    catch(Exception e) {
      System.out.println(this.getClass()+"\tSequencer Device not supported"+e+")");
      System.exit(1);
    }

    try {
      theSequencer.open();
    }
    catch(Exception e) {
      System.out.println(this.getClass()+"Cannot open Sequencer Device");
      System.exit(1);
    }
    if(!theSequencer.addMetaEventListener(this)) {
      System.out.println(this.getClass()+"\tCould not register MetaEventListener - there will be problems with scrolling! ");
    }
  }

  private Sequence generateSequence() {      
    MidiEvent dummyMidiEvent;
    ShortMessage dummyShortMessage;
    Sequence dummySequence        = null;
    Track[] allTracks ;
    Track theTrack;       

    try {
      dummySequence = new Sequence(Sequence.PPQ,1500);
    }
    catch(InvalidMidiDataException e) {
      System.out.println("O o "+e);
    }
    
    dummySequence.createTrack(); 
    allTracks = dummySequence.getTracks();
    theTrack = allTracks[0];

    for(int i=0;i<20;i++) {
      theTrack.add(this.createShortMidiEvent(ShortMessage.NOTE_ON, 2, 30+i, 100,100+1000*i));
      theTrack.add(this.createMetaMidiEvent(1,"start",100+1000*i));
      theTrack.add(this.createShortMidiEvent(ShortMessage.NOTE_OFF, 2, 30+i, 100,(1000*i)+600));
      theTrack.add(this.createMetaMidiEvent(1,"end",(1000*i)+600));
    }

    return dummySequence;
  }

  /*
    A method to create a short midi event (sound)
  */

  public MidiEvent createShortMidiEvent(int theCommand, int theChannel, int theData1, int theData2, long theTime) {
    ShortMessage dummyShortMessage;
    MidiEvent    dummyMidiEvent;
      
    try {
      dummyShortMessage = new ShortMessage();
      dummyShortMessage.setMessage(theCommand, theChannel, theData1, theData2);
      dummyMidiEvent    = new MidiEvent(dummyShortMessage,theTime);
    }
    catch (Exception e) {
      System.out.println(this.getClass()+"\t"+e);
      return null;
    }
      
    return dummyMidiEvent;
  }

  /*
    A method to create a meta midi event (used in  meta() method)
  */
  public MidiEvent createMetaMidiEvent(int theType, String theData1, long theTime) {
    MetaMessage  dummyMetaMessage;
    MidiEvent    dummyMidiEvent;
      
    try {
      dummyMetaMessage = new MetaMessage();
      dummyMetaMessage.setMessage(theType, theData1.getBytes(), theData1.length());
      dummyMidiEvent    = new MidiEvent(dummyMetaMessage,theTime);
    }
    catch (Exception e) {
      System.out.println(e);
      return null;
    }
      
    return dummyMidiEvent;
  }

  /*
    the method is activated by each meta midi event
    it puts out the actual tick position, as well as the WRONG total tick length and the RIGHT 
    tick length using the work around by dividing the total length by 64
  */

  public void meta(MetaMessage p1) {
    if(p1.getType() ==47) {
      System.exit(0);
    }
    System.out.println("Actual:\t"+theSequencer.getTickPosition()+"\tWrong Length:\t"
        +theSequencer.getTickLength()+"\tRight Length:\t"+(theSequencer.getTickLength()/64));
  }

  public static void main(String[] args) {
    TickLengthTester tlt = new TickLengthTester();
    tlt.start();
  }
}
(Review ID: 118879) 
======================================================================

Name: vtR10009			Date: 07/31/2002


This bug causes failure of new JCK test:
  api/javax_sound/midi/Sequencer/index.html#Sequencer




======================================================================

Comments
CONVERTED DATA BugTraq+ Release Management Values COMMIT TO FIX: mantis FIXED IN: mantis INTEGRATED IN: mantis mantis-b08
2004-06-14

EVALUATION ###@###.### 2002-06-25 Should be an easy fix and fixed for Mantis. ###@###.### 2002-10-30 Actually, only Sequencer.getTickLength() reports wrong length. This has been fixed for mantis.
2002-06-25