package org.herac.tuxguitar.midiinput; import org.herac.tuxguitar.song.models.TGDuration; class MiStaffNote { static final int EIGHTH = (int) TGDuration.QUARTER_TIME / 2; static final int EIGHTH_d = EIGHTH + EIGHTH / 2; static final int EIGHTH_dd = EIGHTH_d + EIGHTH / 4; static final int HALF = (int) TGDuration.QUARTER_TIME * 2; static final int HALF_d = HALF + HALF / 2; static final int HALF_dd = HALF_d + HALF / 4; static final int QUARTER = (int) TGDuration.QUARTER_TIME; static final int QUARTER_d = QUARTER + QUARTER / 2; static final int QUARTER_dd = QUARTER_d + QUARTER / 4; static final int SIXTEENTH = (int) TGDuration.QUARTER_TIME / 4; static final int SIXTEENTH_d = SIXTEENTH + SIXTEENTH / 2; static final int SIXTEENTH_dd = SIXTEENTH_d + SIXTEENTH / 4; static final int SIXTY_FOURTH = (int) TGDuration.QUARTER_TIME / 16; static final int SIXTY_FOURTH_d = SIXTY_FOURTH + SIXTY_FOURTH / 2; static final int SIXTY_FOURTH_dd = SIXTY_FOURTH_d + SIXTY_FOURTH / 4; static final int THIRTY_SECOND = (int) TGDuration.QUARTER_TIME / 8; static final int THIRTY_SECOND_d = THIRTY_SECOND + THIRTY_SECOND / 2; static final int THIRTY_SECOND_dd = THIRTY_SECOND_d + THIRTY_SECOND / 4; static final int WHOLE = (int) TGDuration.QUARTER_TIME * 4; static int durationToNoteType(long inDuration) { // converts duration [ticks] into note type if (inDuration >= noteToTicks(TGDuration.WHOLE)) return (TGDuration.WHOLE); else if (inDuration >= noteToTicks(TGDuration.HALF)) return (TGDuration.HALF); else if (inDuration >= noteToTicks(TGDuration.QUARTER)) return (TGDuration.QUARTER); else if (inDuration >= noteToTicks(TGDuration.EIGHTH)) return (TGDuration.EIGHTH); else if (inDuration >= noteToTicks(TGDuration.SIXTEENTH)) return (TGDuration.SIXTEENTH); else if (inDuration >= noteToTicks(TGDuration.THIRTY_SECOND)) return (TGDuration.THIRTY_SECOND); else return (TGDuration.SIXTY_FOURTH); } static long noteToTicks(int inNoteType) { switch (inNoteType) { case TGDuration.WHOLE: return (TGDuration.QUARTER_TIME * 4); case TGDuration.HALF: return (TGDuration.QUARTER_TIME * 2); case TGDuration.QUARTER: return (TGDuration.QUARTER_TIME); case TGDuration.EIGHTH: return (TGDuration.QUARTER_TIME / 2); case TGDuration.SIXTEENTH: return (TGDuration.QUARTER_TIME / 4); case TGDuration.THIRTY_SECOND: return (TGDuration.QUARTER_TIME / 8); case TGDuration.SIXTY_FOURTH: return (TGDuration.QUARTER_TIME / 16); default: return (1L); } } private byte f_DotCount; // number of dots private long f_Duration; // nominal duration [ticks] private byte f_Fret; // 0-based fret index private boolean f_IsTied; // true if this is a tied note private byte f_Pitch; // MIDI note pitch private byte f_String; // 1-based string index private byte f_Velocity; // MIDI note velocity public MiStaffNote(MiNote inNote) { f_String = inNote.getString(); f_Fret = inNote.getFret(); f_Pitch = inNote.getPitch(); f_Velocity = inNote.getVelocity(); f_Duration = inNote.getDuration(); f_DotCount = 0; f_IsTied = false; } public MiStaffNote(MiStaffNote inNote) { f_String = inNote.f_String; f_Fret = inNote.f_Fret; f_Pitch = inNote.f_Pitch; f_Velocity = inNote.f_Velocity; f_Duration = inNote.f_Duration; f_DotCount = inNote.f_DotCount; f_IsTied = inNote.f_IsTied; } byte getDotCount() { return f_DotCount; } byte getFret() { return f_Fret; } long getNominalDuration() { return f_Duration; } long getOverallDuration() { long time = f_Duration; if (f_DotCount == 1) time += time / 2; else if (f_DotCount == 2) time += ((time / 4) * 3); return (time); } byte getPitch() { return f_Pitch; } byte getString() { return f_String; } byte getVelocity() { return f_Velocity; } boolean isTied() { return f_IsTied; } private long nd2(long inDuration) { if (inDuration < SIXTY_FOURTH) return (SIXTY_FOURTH); else if (inDuration < SIXTY_FOURTH_d) return (nd3(SIXTY_FOURTH, SIXTY_FOURTH_d, inDuration)); else if (inDuration < SIXTY_FOURTH_dd) return (nd3(SIXTY_FOURTH_d, SIXTY_FOURTH_dd, inDuration)); else if (inDuration < THIRTY_SECOND) return (nd3(SIXTY_FOURTH_dd, THIRTY_SECOND, inDuration)); else if (inDuration < THIRTY_SECOND_d) return (nd3(THIRTY_SECOND, THIRTY_SECOND_d, inDuration)); else if (inDuration < THIRTY_SECOND_dd) return (nd3(THIRTY_SECOND_d, THIRTY_SECOND_dd, inDuration)); else if (inDuration < SIXTEENTH) return (nd3(THIRTY_SECOND_dd, SIXTEENTH, inDuration)); else if (inDuration < SIXTEENTH_d) return (nd3(SIXTEENTH, SIXTEENTH_d, inDuration)); else if (inDuration < SIXTEENTH_dd) return (nd3(SIXTEENTH_d, SIXTEENTH_dd, inDuration)); else if (inDuration < EIGHTH) return (nd3(SIXTEENTH_dd, EIGHTH, inDuration)); else if (inDuration < EIGHTH_d) return (nd3(EIGHTH, EIGHTH_d, inDuration)); else if (inDuration < EIGHTH_dd) return (nd3(EIGHTH_d, EIGHTH_dd, inDuration)); else if (inDuration < QUARTER) return (nd3(EIGHTH_dd, QUARTER, inDuration)); else if (inDuration < QUARTER_d) return (nd3(QUARTER, QUARTER_d, inDuration)); else if (inDuration < QUARTER_dd) return (nd3(QUARTER_d, QUARTER_dd, inDuration)); else if (inDuration < HALF) return (nd3(QUARTER_dd, HALF, inDuration)); else if (inDuration < HALF_d) return (nd3(HALF, HALF_d, inDuration)); else if (inDuration < HALF_dd) return (nd3(HALF_d, HALF_dd, inDuration)); else if (inDuration < WHOLE) return (nd3(HALF_dd, WHOLE, inDuration)); else return (WHOLE); } private long nd3(long inBottom, long inTop, long inTime) { long mid = inBottom + (inTop - inBottom) / 2; return (inTime <= mid ? inBottom : inTop); } void normalizeDuration() { switch ((int) nd2(getOverallDuration())) { case SIXTY_FOURTH: f_Duration = SIXTY_FOURTH; f_DotCount = 0; break; case SIXTY_FOURTH_d: f_Duration = SIXTY_FOURTH; f_DotCount = 1; break; case SIXTY_FOURTH_dd: f_Duration = SIXTY_FOURTH; f_DotCount = 2; break; case THIRTY_SECOND: f_Duration = THIRTY_SECOND; f_DotCount = 0; break; case THIRTY_SECOND_d: f_Duration = THIRTY_SECOND; f_DotCount = 1; break; case THIRTY_SECOND_dd: f_Duration = THIRTY_SECOND; f_DotCount = 2; break; case SIXTEENTH: f_Duration = SIXTEENTH; f_DotCount = 0; break; case SIXTEENTH_d: f_Duration = SIXTEENTH; f_DotCount = 1; break; case SIXTEENTH_dd: f_Duration = SIXTEENTH; f_DotCount = 2; break; case EIGHTH: f_Duration = EIGHTH; f_DotCount = 0; break; case EIGHTH_d: f_Duration = EIGHTH; f_DotCount = 1; break; case EIGHTH_dd: f_Duration = EIGHTH; f_DotCount = 2; break; case QUARTER: f_Duration = QUARTER; f_DotCount = 0; break; case QUARTER_d: f_Duration = QUARTER; f_DotCount = 1; break; case QUARTER_dd: f_Duration = QUARTER; f_DotCount = 2; break; case HALF: f_Duration = HALF; f_DotCount = 0; break; case HALF_d: f_Duration = HALF; f_DotCount = 1; break; case HALF_dd: f_Duration = HALF; f_DotCount = 2; break; case WHOLE: f_Duration = WHOLE; f_DotCount = 0; break; } } void setDuration(long inDuration) { f_Duration = inDuration; f_DotCount = 0; } void setTied(boolean inTied) { f_IsTied = inTied; } public String toString() { String out = "(" + f_String + "," + f_Fret + ") " + "(" + f_Pitch + "," + f_Velocity + ") " + "d " + getOverallDuration(); if (f_DotCount == 1) out += " (" + f_Duration + "*)"; else if (f_DotCount == 2) out += " (" + f_Duration + "**)"; return (out); } }