OPMLog.java
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13: package xeij;
14:
15: import java.awt.*;
16: import java.awt.event.*;
17: import java.awt.geom.*;
18: import java.awt.image.*;
19: import java.io.*;
20: import java.util.*;
21: import javax.sound.sampled.*;
22: import javax.swing.*;
23: import javax.swing.border.*;
24: import javax.swing.event.*;
25:
26: public class OPMLog {
27:
28: public static final boolean OLG_ON = true;
29:
30:
31: public static final double LOG2_358_400 = -0.16004041251046827164899520744140640962;
32:
33: public static final int OLG_BUFFER_SIZE = 1024 * 1024;
34: public static final long OLG_UNIT = 1000000L;
35: public static final int[] olgBuffer = new int[OLG_BUFFER_SIZE];
36:
37:
38: public static final int OLG_LIMIT_S = 900;
39: public static boolean olgRecording;
40: public static int olgLength;
41: public static long olgStartTimePS;
42: public static int olgCounter;
43:
44:
45: public static final int[] OLG_US_PER_PX = new int[] {
46: 1,
47: 2,
48: 5,
49: 10,
50: 20,
51: 50,
52: 100,
53: 200,
54: 500,
55: 1000,
56: 2000,
57: 5000,
58: 10000,
59: 20000,
60: 50000,
61: 100000,
62: };
63: public static final int OLG_RANGE_COUNT = OLG_US_PER_PX.length;
64: public static int olgRangeIndex;
65: public static int olgUsPerPx;
66: public static int olgRangeUs;
67: public static int olgStartUs;
68: public static int olgEndUs;
69: public static int olgPxToUs (int px) {
70: return olgStartUs + olgUsPerPx * px;
71: }
72: public static int olgUsToPx (int us) {
73: return (us - olgStartUs) / olgUsPerPx;
74: }
75: public static final boolean[] olgChannelMask = new boolean[8];
76:
77:
78: public static int olgCaretPx;
79: public static int olgCaretUs;
80:
81:
82: public static int olgMaskLeftUs;
83: public static int olgMaskRightUs;
84:
85: public static java.util.Timer olgTimer;
86: public static TimerTask olgForcedTerminationTask;
87:
88: public static File olgLastMMLFile;
89: public static javax.swing.filechooser.FileFilter olgMMLFilter;
90: public static File olgLastFile;
91: public static javax.swing.filechooser.FileFilter olgFilter;
92:
93:
94: public static BasicStroke olgSolidStroke;
95: public static BasicStroke olgDashStroke;
96: public static BasicStroke olgWaveStroke;
97:
98:
99: public static TexturePaint olgMaskPaint;
100:
101:
102: public static final int OLG_SCORE_WIDTH = 1200;
103: public static final int OLG_SCORE_HEIGHT = 388;
104: public static final int OLG_SCORE_H_MARGIN = 10;
105: public static final int OLG_SCORE_V_MARGIN = 6;
106: public static final int OLG_SCORE_IMAGE_WIDTH = OLG_SCORE_H_MARGIN + OLG_SCORE_WIDTH + OLG_SCORE_H_MARGIN;
107: public static final int OLG_WAVE_RADIUS = 48;
108: public static final int OLG_WAVE_Y1 = OLG_SCORE_V_MARGIN + OLG_SCORE_HEIGHT;
109: public static final int OLG_WAVE_Y0 = OLG_WAVE_Y1 + OLG_WAVE_RADIUS;
110: public static final int OLG_WAVE_YM1 = OLG_WAVE_Y0 + OLG_WAVE_RADIUS;
111: public static final int OLG_SCORE_IMAGE_HEIGHT = OLG_WAVE_YM1 + OLG_SCORE_V_MARGIN;
112: public static final int OLG_KON1ST_HEIGHT = 9;
113: public static final int OLG_KON2ND_HEIGHT = 7;
114: public static final int OLG_BAR_HEIGHT = 3;
115: public static final Color[] OLG_KON_COLOR = new Color[] {
116: Color.getHSBColor (0.000F, 0.5F, 1.0F),
117: Color.getHSBColor (0.125F, 0.5F, 1.0F),
118: Color.getHSBColor (0.250F, 0.5F, 1.0F),
119: Color.getHSBColor (0.375F, 0.5F, 1.0F),
120: Color.getHSBColor (0.500F, 0.5F, 1.0F),
121: Color.getHSBColor (0.625F, 0.5F, 1.0F),
122: Color.getHSBColor (0.750F, 0.5F, 1.0F),
123: Color.getHSBColor (0.875F, 0.5F, 1.0F),
124: };
125: public static final Color[] OLG_BAR_COLOR = new Color[] {
126: Color.getHSBColor (0.000F, 0.5F, 0.5F),
127: Color.getHSBColor (0.125F, 0.5F, 0.5F),
128: Color.getHSBColor (0.250F, 0.5F, 0.5F),
129: Color.getHSBColor (0.375F, 0.5F, 0.5F),
130: Color.getHSBColor (0.500F, 0.5F, 0.5F),
131: Color.getHSBColor (0.625F, 0.5F, 0.5F),
132: Color.getHSBColor (0.750F, 0.5F, 0.5F),
133: Color.getHSBColor (0.875F, 0.5F, 0.5F),
134: };
135: public static BufferedImage olgCanvasImage;
136: public static int[] olgCanvasBitmap;
137: public static ScrollCanvas olgCanvas;
138: public static int olgScaleShift;
139:
140:
141: public static final char[] OLG_TONE_BASE = (
142:
143:
144: " FC SL WA SY SP PD AD PS AS PN " +
145: " -- -- -- -- -- -- -- -- -- -- --" +
146: " AR 1R 2R RR 1L TL KS ML T1 T2 AE" +
147: "M1 -- -- -- -- -- -- -- -- -- -- --" +
148: "C1 -- -- -- -- -- -- -- -- -- -- --" +
149: "M2 -- -- -- -- -- -- -- -- -- -- --" +
150: "C2 -- -- -- -- -- -- -- -- -- -- --" +
151: " KC KF " +
152: " -- -- ").toCharArray ();
153: public static final int OLG_TONE_CHAR_WIDTH = 6;
154: public static final int OLG_TONE_LINE_HEIGHT = 10;
155: public static final int OLG_TONE_COLS = 35;
156: public static final int OLG_TONE_ROWS = 9;
157: public static final int OLG_TONE_H_SPACE = 6;
158: public static final int OLG_TONE_V_SPACE = 10;
159: public static final int OLG_TONE_WIDTH = (OLG_TONE_CHAR_WIDTH * OLG_TONE_COLS + OLG_TONE_H_SPACE) * 4 - OLG_TONE_H_SPACE;
160: public static final int OLG_TONE_HEIGHT = (OLG_TONE_LINE_HEIGHT * OLG_TONE_ROWS + OLG_TONE_V_SPACE) * 2 - OLG_TONE_V_SPACE;
161: public static final int OLG_TONE_H_MARGIN = 6;
162: public static final int OLG_TONE_V_MARGIN = 10;
163: public static final int OLG_TONE_IMAGE_WIDTH = OLG_TONE_H_MARGIN + OLG_TONE_WIDTH + OLG_TONE_H_MARGIN;
164: public static final int OLG_TONE_IMAGE_HEIGHT = OLG_TONE_V_MARGIN + OLG_TONE_HEIGHT + OLG_TONE_V_MARGIN;
165: public static BufferedImage olgToneImage;
166: public static int[] olgToneBitmap;
167: public static JPanel olgTonePanel;
168:
169:
170:
171:
172:
173:
174: public static final int OLG_DUMP_TEXT_AREA_WIDTH = 340;
175: public static final int OLG_DUMP_TEXT_AREA_HEIGHT = 180;
176: public static ScrollTextArea olgDumpTextArea;
177:
178:
179: public static JRadioButtonMenuItem[] olgScaleMenuItem;
180:
181:
182: public static JFrame olgFrame;
183:
184: public static JButton olgStartButton;
185: public static JButton olgEndButton;
186:
187: public static JButton olgPlusButton;
188: public static JButton olgMinusButton;
189:
190:
191: public static final int OPM_CHANNELS = 2;
192: public static YM2151 olgYM2151;
193: public static int[] opmBuffer;
194:
195:
196: public static void olgInit () {
197:
198:
199: olgRecording = false;
200: olgBuffer[0] = 0;
201: olgBuffer[1] = -1;
202: olgLength = 2;
203: olgStartTimePS = 0L;
204: olgCounter = 0;
205:
206: olgRangeIndex = OLG_RANGE_COUNT - 1;
207: olgUsPerPx = OLG_US_PER_PX[olgRangeIndex];
208: olgRangeUs = olgUsPerPx * OLG_SCORE_WIDTH;
209: olgStartUs = 0;
210: olgEndUs = olgRangeUs;
211:
212: Arrays.fill (olgChannelMask, true);
213:
214: olgCaretPx = 0;
215: olgCaretUs = 0;
216:
217: olgMaskLeftUs = -1;
218: olgMaskRightUs = -1;
219:
220: olgTimer = new java.util.Timer ();
221: olgForcedTerminationTask = null;
222:
223: olgLastFile = new File (System.getProperty ("user.dir") + File.separator + "opmlog.dat");
224: olgFilter = new javax.swing.filechooser.FileFilter () {
225: @Override public boolean accept (File file) {
226: String name = file.getName ();
227: String lowerName = name.toLowerCase ();
228: return (file.isDirectory () ||
229: (file.isFile () &&
230: lowerName.endsWith (".dat")));
231: }
232: @Override public String getDescription () {
233: return (Multilingual.mlnJapanese ?
234: "データファイル (*.dat)" :
235: "Data files (*.dat)");
236: }
237: };
238:
239: olgLastMMLFile = new File (System.getProperty ("user.dir") + File.separator + "a.opm");
240: olgMMLFilter = new javax.swing.filechooser.FileFilter () {
241: @Override public boolean accept (File file) {
242: String name = file.getName ();
243: String lowerName = name.toLowerCase ();
244: return (file.isDirectory () ||
245: (file.isFile () &&
246: (lowerName.endsWith (".opm") ||
247: lowerName.endsWith (".zms"))));
248: }
249: @Override public String getDescription () {
250: return (Multilingual.mlnJapanese ?
251: "MML ファイル (*.opm *.zms)" :
252: "MML files (*.opm *.zms)");
253: }
254: };
255:
256: olgYM2151 = new YM2151 ();
257: opmBuffer = null;
258: olgYM2151.setListener (new YM2151.Listener () {
259: @Override public void timerA (int clocks) {
260: }
261: @Override public void timerB (int clocks) {
262: }
263: @Override public void busy (int clocks) {
264: }
265: @Override public boolean isBusy () {
266: return false;
267: }
268: @Override public void irq (boolean asserted) {
269: }
270: @Override public void control (int data) {
271: }
272: @Override public void written (int pointer, int address, int data) {
273: }
274: });
275: olgYM2151.reset ();
276:
277: }
278:
279:
280: public static void olgTini () {
281: olgTimer.cancel ();
282: }
283:
284: public static void olgStart () {
285: if (RestorableFrame.rfmGetOpened (Settings.SGS_OLG_FRAME_KEY)) {
286: olgOpen ();
287: }
288: }
289:
290: public static void olgOpen () {
291: if (olgFrame == null) {
292: olgMakeFrame ();
293: }
294: XEiJ.pnlExitFullScreen (false);
295: olgFrame.setVisible (true);
296: }
297:
298: public static void olgMakeFrame () {
299:
300:
301: olgSolidStroke = new BasicStroke (1.0F, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 10.0F);
302: olgDashStroke = new BasicStroke (1.0F, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 10.0F, new float[] { 1.0F, 1.0F }, 0.0F);
303: olgWaveStroke = new BasicStroke (1.0F, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, 10.0F);
304:
305:
306: {
307: BufferedImage image = new BufferedImage (4, 4, BufferedImage.TYPE_INT_ARGB);
308: int[] bitmap = ((DataBufferInt) image.getRaster ().getDataBuffer ()).getData ();
309: Arrays.fill (bitmap, 0x00000000);
310: bitmap[3] = 0x80808080;
311: bitmap[6] = 0x80808080;
312: bitmap[9] = 0x80808080;
313: bitmap[12] = 0x80808080;
314: olgMaskPaint = new TexturePaint (image, new Rectangle2D.Float (0.0F, 0.0F, 4.0F, 4.0F));
315: }
316:
317:
318: olgCanvasImage = new BufferedImage (OLG_SCORE_IMAGE_WIDTH, OLG_SCORE_IMAGE_HEIGHT, BufferedImage.TYPE_INT_RGB);
319: olgCanvasBitmap = ((DataBufferInt) olgCanvasImage.getRaster ().getDataBuffer ()).getData ();
320: olgCanvas = new ScrollCanvas (olgCanvasImage);
321: olgCanvas.setMargin (10, 10);
322: olgCanvas.setMatColor (new Color (LnF.lnfRGB[4]));
323: olgScaleShift = 0;
324: ComponentFactory.setPreferredSize (olgCanvas,
325: OLG_SCORE_IMAGE_WIDTH + 10 + 20 + 20,
326: OLG_SCORE_IMAGE_HEIGHT + 10 + 20 + 30);
327:
328:
329: ActionListener listener = new ActionListener () {
330: @Override public void actionPerformed (ActionEvent ae) {
331: Object source = ae.getSource ();
332: String command = ae.getActionCommand ();
333: switch (command) {
334: case "Load MML":
335: olgLoadMML ();
336: break;
337: case "Load Log":
338: olgLoadLog ();
339: break;
340: case "Save Log":
341: olgSaveLog ();
342: break;
343: case "Quit":
344: olgFrame.setVisible (false);
345: break;
346:
347: case "Adjust":
348: olgAdjust ();
349: break;
350:
351: case "6.25%":
352: if (olgScaleShift != -4) {
353: olgCanvas.setScaleShift (-4);
354: }
355: break;
356: case "12.5%":
357: if (olgScaleShift != -3) {
358: olgCanvas.setScaleShift (-3);
359: }
360: break;
361: case "25%":
362: if (olgScaleShift != -2) {
363: olgCanvas.setScaleShift (-2);
364: }
365: break;
366: case "50%":
367: if (olgScaleShift != -1) {
368: olgCanvas.setScaleShift (-1);
369: }
370: break;
371: case "100%":
372: if (olgScaleShift != 0) {
373: olgCanvas.setScaleShift (0);
374: }
375: break;
376: case "200%":
377: if (olgScaleShift != 1) {
378: olgCanvas.setScaleShift (1);
379: }
380: break;
381: case "400%":
382: if (olgScaleShift != 2) {
383: olgCanvas.setScaleShift (2);
384: }
385: break;
386: case "800%":
387: if (olgScaleShift != 3) {
388: olgCanvas.setScaleShift (3);
389: }
390: break;
391: case "1600%":
392: if (olgScaleShift != 4) {
393: olgCanvas.setScaleShift (4);
394: }
395: break;
396:
397: case "●":
398: olgRecordStart ();
399: break;
400: case "■":
401: olgRecordEnd ();
402: break;
403:
404: case "+":
405: olgRangeIndex = Math.max (0, olgRangeIndex - 1);
406: ComponentFactory.setEnabled (olgPlusButton, 0 < olgRangeIndex);
407: ComponentFactory.setEnabled (olgMinusButton, olgRangeIndex < OLG_RANGE_COUNT - 1);
408: olgUsPerPx = OLG_US_PER_PX[olgRangeIndex];
409: olgRangeUs = olgUsPerPx * OLG_SCORE_WIDTH;
410: olgCaretUs = (olgCaretUs / olgUsPerPx) * olgUsPerPx;
411: olgStartUs = Math.max (0, olgCaretUs - olgUsPerPx * olgCaretPx);
412: olgCaretPx = (olgCaretUs - olgStartUs) / olgUsPerPx;
413: olgEndUs = olgStartUs + olgRangeUs;
414: olgPaint ();
415: break;
416: case "-":
417: olgRangeIndex = Math.min (OLG_RANGE_COUNT - 1, olgRangeIndex + 1);
418: ComponentFactory.setEnabled (olgPlusButton, 0 < olgRangeIndex);
419: ComponentFactory.setEnabled (olgMinusButton, olgRangeIndex < OLG_RANGE_COUNT - 1);
420: olgUsPerPx = OLG_US_PER_PX[olgRangeIndex];
421: olgRangeUs = olgUsPerPx * OLG_SCORE_WIDTH;
422: olgCaretUs = (olgCaretUs / olgUsPerPx) * olgUsPerPx;
423: olgStartUs = Math.max (0, olgCaretUs - olgUsPerPx * olgCaretPx);
424: olgCaretPx = (olgCaretUs - olgStartUs) / olgUsPerPx;
425: olgEndUs = olgStartUs + olgRangeUs;
426: olgPaint ();
427: break;
428: case "丨<":
429: olgCaretUs = 0;
430: olgStartUs = 0;
431: olgCaretPx = 0;
432: olgEndUs = olgStartUs + olgRangeUs;
433: olgPaint ();
434: break;
435: case "≪≪":
436: olgMoveCaret (-400);
437: break;
438: case "≪":
439: olgMoveCaret (-20);
440: break;
441: case "<":
442: olgMoveCaret (-1);
443: break;
444: case ">":
445: olgMoveCaret (1);
446: break;
447: case "≫":
448: olgMoveCaret (20);
449: break;
450: case "≫≫":
451: olgMoveCaret (400);
452: break;
453: case ">丨":
454: olgCaretUs = (Math.max (0, olgBuffer[olgLength - 2] - 1) / olgUsPerPx) * olgUsPerPx;
455: olgStartUs = Math.max (0, olgCaretUs - olgUsPerPx * olgCaretPx);
456: olgCaretPx = (olgCaretUs - olgStartUs) / olgUsPerPx;
457: olgEndUs = olgStartUs + olgRangeUs;
458: olgPaint ();
459: break;
460:
461: case "0":
462: olgChannelMask[0] = ((JCheckBox) source).isSelected ();
463: olgMakeWaveData ();
464: olgPaint ();
465: break;
466: case "1":
467: olgChannelMask[1] = ((JCheckBox) source).isSelected ();
468: olgMakeWaveData ();
469: olgPaint ();
470: break;
471: case "2":
472: olgChannelMask[2] = ((JCheckBox) source).isSelected ();
473: olgMakeWaveData ();
474: olgPaint ();
475: break;
476: case "3":
477: olgChannelMask[3] = ((JCheckBox) source).isSelected ();
478: olgMakeWaveData ();
479: olgPaint ();
480: break;
481: case "4":
482: olgChannelMask[4] = ((JCheckBox) source).isSelected ();
483: olgMakeWaveData ();
484: olgPaint ();
485: break;
486: case "5":
487: olgChannelMask[5] = ((JCheckBox) source).isSelected ();
488: olgMakeWaveData ();
489: olgPaint ();
490: break;
491: case "6":
492: olgChannelMask[6] = ((JCheckBox) source).isSelected ();
493: olgMakeWaveData ();
494: olgPaint ();
495: break;
496: case "7":
497: olgChannelMask[7] = ((JCheckBox) source).isSelected ();
498: olgMakeWaveData ();
499: olgPaint ();
500: break;
501:
502: case "From":
503: if (olgMaskRightUs == -1 || olgCaretUs < olgMaskRightUs) {
504: olgMaskLeftUs = olgCaretUs;
505: olgPaint ();
506: }
507: break;
508: case "To":
509: if (olgMaskLeftUs == -1 || olgMaskLeftUs < olgCaretUs) {
510: olgMaskRightUs = olgCaretUs;
511: olgPaint ();
512: }
513: break;
514: case "All":
515: olgMaskLeftUs = -1;
516: olgMaskRightUs = -1;
517: olgPaint ();
518: break;
519:
520: case "\u25b7":
521: olgPlayStart ();
522: break;
523: case "□":
524: olgPlayEnd ();
525: break;
526: }
527: }
528: };
529:
530:
531: ButtonGroup zoomGroup = new ButtonGroup ();
532: olgScaleMenuItem = new JRadioButtonMenuItem[9];
533: JMenuBar menuBar = ComponentFactory.createMenuBar (
534:
535: Multilingual.mlnText (
536: ComponentFactory.createMenu (
537: "File", 'F',
538: Multilingual.mlnText (ComponentFactory.createMenuItem ("Load MML", 'M', listener), "ja", "ロード MML"),
539: ComponentFactory.createHorizontalSeparator (),
540: Multilingual.mlnText (ComponentFactory.createMenuItem ("Load Log", 'L', listener), "ja", "ロード ログ"),
541: Multilingual.mlnText (ComponentFactory.createMenuItem ("Save Log", 'S', listener), "ja", "セーブ ログ"),
542: ComponentFactory.createHorizontalSeparator (),
543: Multilingual.mlnText (ComponentFactory.createMenuItem ("Quit", 'Q', listener), "ja", "終了")
544: ),
545: "ja", "ファイル"),
546:
547: Multilingual.mlnText (
548: ComponentFactory.createMenu (
549: "Edit", 'E',
550: Multilingual.mlnText (ComponentFactory.createMenuItem ("Adjust", 'A', listener), "ja", "アジャスト")
551: ),
552: "ja", "編集"),
553:
554: Multilingual.mlnText (
555: ComponentFactory.createMenu (
556: "Display", 'D',
557: olgScaleMenuItem[0] = ComponentFactory.createRadioButtonMenuItem (zoomGroup, olgScaleShift == -4, "6.25%", '1', listener),
558: olgScaleMenuItem[1] = ComponentFactory.createRadioButtonMenuItem (zoomGroup, olgScaleShift == -3, "12.5%", '2', listener),
559: olgScaleMenuItem[2] = ComponentFactory.createRadioButtonMenuItem (zoomGroup, olgScaleShift == -2, "25%", '3', listener),
560: olgScaleMenuItem[3] = ComponentFactory.createRadioButtonMenuItem (zoomGroup, olgScaleShift == -1, "50%", '4', listener),
561: olgScaleMenuItem[4] = ComponentFactory.createRadioButtonMenuItem (zoomGroup, olgScaleShift == 0, "100%", '5', listener),
562: olgScaleMenuItem[5] = ComponentFactory.createRadioButtonMenuItem (zoomGroup, olgScaleShift == 1, "200%", '6', listener),
563: olgScaleMenuItem[6] = ComponentFactory.createRadioButtonMenuItem (zoomGroup, olgScaleShift == 2, "400%", '7', listener),
564: olgScaleMenuItem[7] = ComponentFactory.createRadioButtonMenuItem (zoomGroup, olgScaleShift == 3, "800%", '8', listener),
565: olgScaleMenuItem[8] = ComponentFactory.createRadioButtonMenuItem (zoomGroup, olgScaleShift == 4, "1600%", '9', listener)
566: ),
567: "ja", "表示")
568: );
569:
570:
571: olgCanvas.addScaleShiftListener (new ScrollCanvas.ScaleShiftListener () {
572: @Override public void scaleShiftChanged (int scaleShift) {
573: if (-4 <= scaleShift && scaleShift <= 4) {
574: olgScaleShift = scaleShift;
575: olgScaleMenuItem[4 + scaleShift].setSelected (true);
576: }
577: }
578: });
579:
580:
581: olgCanvas.addMouseListener (new MouseAdapter () {
582: @Override public void mouseClicked (MouseEvent me) {
583: MouseEvent2D me2D = (MouseEvent2D) me;
584: int x = (int) me2D.getX2D ();
585: int y = (int) me2D.getY2D ();
586: if (OLG_SCORE_H_MARGIN <= x && x < OLG_SCORE_H_MARGIN + OLG_SCORE_WIDTH &&
587: OLG_SCORE_V_MARGIN <= y && y < OLG_WAVE_YM1) {
588: x -= OLG_SCORE_H_MARGIN;
589: y -= OLG_SCORE_V_MARGIN;
590:
591: olgCaretUs = Math.min ((Math.max (0, olgBuffer[olgLength - 2] - 1) / olgUsPerPx) * olgUsPerPx,
592: olgPxToUs (x));
593: olgCaretPx = olgUsToPx (olgCaretUs);
594: if (me.getClickCount () == 2) {
595:
596: olgStartUs = Math.max (0, olgStartUs + olgUsPerPx * (olgCaretPx - (OLG_SCORE_WIDTH >> 1)));
597: olgCaretPx = (olgCaretUs - olgStartUs) / olgUsPerPx;
598: olgEndUs = olgStartUs + olgRangeUs;
599: }
600: olgPaint ();
601: }
602: }
603: });
604:
605:
606: olgCanvas.setFocusable (true);
607: olgCanvas.addKeyListener (new KeyAdapter () {
608: @Override public void keyPressed (KeyEvent ke) {
609: int keyCode = ke.getKeyCode ();
610: int modifierEx = ke.getModifiersEx ();
611: boolean shift = (modifierEx & InputEvent.SHIFT_DOWN_MASK) == InputEvent.SHIFT_DOWN_MASK;
612: boolean ctrl = (modifierEx & InputEvent.CTRL_DOWN_MASK) == InputEvent.CTRL_DOWN_MASK;
613: int dxPx = 0;
614: switch (keyCode) {
615: case KeyEvent.VK_LEFT:
616: dxPx = ctrl ? -100 : shift ? -10 : -1;
617: break;
618: case KeyEvent.VK_RIGHT:
619: dxPx = ctrl ? 100 : shift ? 10 : 1;
620: break;
621: }
622: if (dxPx != 0) {
623: olgMoveCaret (dxPx);
624: ke.consume ();
625: }
626: }
627: });
628:
629:
630: Box recordBox = Multilingual.mlnTitledBorder (
631: ComponentFactory.setTitledLineBorder (
632: ComponentFactory.createHorizontalBox (
633: olgStartButton = ComponentFactory.setEnabled (
634: ComponentFactory.createButton ("●", listener),
635: true),
636: olgEndButton = ComponentFactory.setEnabled (
637: ComponentFactory.createButton ("■", listener),
638: false)),
639: "Record"),
640: "ja", "録音");
641:
642:
643: Box zoomBox = Multilingual.mlnTitledBorder (
644: ComponentFactory.setTitledLineBorder (
645: ComponentFactory.createHorizontalBox (
646: olgPlusButton =
647: ComponentFactory.setEnabled (
648: ComponentFactory.createButton ("+", listener),
649: 0 < olgRangeIndex),
650: olgMinusButton =
651: ComponentFactory.setEnabled (
652: ComponentFactory.createButton ("-", listener),
653: olgRangeIndex < OLG_RANGE_COUNT - 1)),
654: "Zoom"),
655: "ja", "拡大");
656:
657:
658: Box moveBox = Multilingual.mlnTitledBorder (
659: ComponentFactory.setTitledLineBorder (
660: ComponentFactory.createHorizontalBox (
661: ComponentFactory.createButton ("丨<", listener),
662: ComponentFactory.createButton ("≪≪", listener),
663: ComponentFactory.createButton ("≪", listener),
664: ComponentFactory.createButton ("<", listener),
665: ComponentFactory.createButton (">", listener),
666: ComponentFactory.createButton ("≫", listener),
667: ComponentFactory.createButton ("≫≫", listener),
668: ComponentFactory.createButton (">丨", listener)),
669: "Move"),
670: "ja", "移動");
671:
672:
673: Box channelBox = Multilingual.mlnTitledBorder (
674: ComponentFactory.setTitledLineBorder (
675: ComponentFactory.createHorizontalBox (
676: ComponentFactory.setEmptyBorder (
677: ComponentFactory.setColor (ComponentFactory.createCheckBox (olgChannelMask[0], "0", listener), Color.black, OLG_KON_COLOR[0]),
678: 4, 4, 4, 4),
679: ComponentFactory.setEmptyBorder (
680: ComponentFactory.setColor (ComponentFactory.createCheckBox (olgChannelMask[1], "1", listener), Color.black, OLG_KON_COLOR[1]),
681: 4, 4, 4, 4),
682: ComponentFactory.setEmptyBorder (
683: ComponentFactory.setColor (ComponentFactory.createCheckBox (olgChannelMask[2], "2", listener), Color.black, OLG_KON_COLOR[2]),
684: 4, 4, 4, 4),
685: ComponentFactory.setEmptyBorder (
686: ComponentFactory.setColor (ComponentFactory.createCheckBox (olgChannelMask[3], "3", listener), Color.black, OLG_KON_COLOR[3]),
687: 4, 4, 4, 4),
688: ComponentFactory.setEmptyBorder (
689: ComponentFactory.setColor (ComponentFactory.createCheckBox (olgChannelMask[4], "4", listener), Color.black, OLG_KON_COLOR[4]),
690: 4, 4, 4, 4),
691: ComponentFactory.setEmptyBorder (
692: ComponentFactory.setColor (ComponentFactory.createCheckBox (olgChannelMask[5], "5", listener), Color.black, OLG_KON_COLOR[5]),
693: 4, 4, 4, 4),
694: ComponentFactory.setEmptyBorder (
695: ComponentFactory.setColor (ComponentFactory.createCheckBox (olgChannelMask[6], "6", listener), Color.black, OLG_KON_COLOR[6]),
696: 4, 4, 4, 4),
697: ComponentFactory.setEmptyBorder (
698: ComponentFactory.setColor (ComponentFactory.createCheckBox (olgChannelMask[7], "7", listener), Color.black, OLG_KON_COLOR[7]),
699: 4, 4, 4, 4)
700: ),
701: "Channel"),
702: "ja", "チャンネル");
703:
704:
705: Box rangeBox = Multilingual.mlnTitledBorder (
706: ComponentFactory.setTitledLineBorder (
707: ComponentFactory.createHorizontalBox (
708: Multilingual.mlnText (ComponentFactory.createButton ("From", listener), "ja", "ここから"),
709: Multilingual.mlnText (ComponentFactory.createButton ("To", listener), "ja", "ここまで"),
710: Multilingual.mlnText (ComponentFactory.createButton ("All", listener), "ja", "全部")),
711: "Range"),
712: "ja", "範囲");
713:
714:
715: Box playBox = Multilingual.mlnTitledBorder (
716: ComponentFactory.setTitledLineBorder (
717: ComponentFactory.createHorizontalBox (
718: ComponentFactory.createButton ("\u25b7", listener),
719: ComponentFactory.createButton ("□", listener)),
720: "Play"),
721: "ja", "再生");
722:
723:
724: Box toolBox = ComponentFactory.createHorizontalBox (
725: recordBox,
726: zoomBox,
727: moveBox,
728: channelBox,
729: rangeBox,
730: playBox,
731: Box.createHorizontalGlue ());
732:
733:
734: olgToneImage = new BufferedImage (OLG_TONE_IMAGE_WIDTH, OLG_TONE_IMAGE_HEIGHT, BufferedImage.TYPE_INT_RGB);
735: olgToneBitmap = ((DataBufferInt) olgToneImage.getRaster ().getDataBuffer ()).getData ();
736: olgTonePanel = ComponentFactory.setPreferredSize (
737: new JPanel () {
738: @Override public void paintComponent (Graphics g) {
739: super.paintComponent (g);
740: g.drawImage (olgToneImage, 0, 0, null);
741: }
742: },
743: OLG_TONE_IMAGE_WIDTH,
744: OLG_TONE_IMAGE_HEIGHT);
745:
746:
747: olgDumpTextArea = ComponentFactory.createScrollTextArea ("",
748: OLG_DUMP_TEXT_AREA_WIDTH,
749: OLG_DUMP_TEXT_AREA_HEIGHT);
750: olgDumpTextArea.setLineWrap (true);
751:
752:
753: olgFrame = Multilingual.mlnTitle (
754: ComponentFactory.createRestorableSubFrame (
755: Settings.SGS_OLG_FRAME_KEY,
756: "OPM log",
757: menuBar,
758: ComponentFactory.createVerticalBox (
759: toolBox,
760: Multilingual.mlnTitledBorder (
761: ComponentFactory.setTitledLineBorder (olgCanvas, "Score and wave"),
762: "ja", "楽譜と波形"),
763: ComponentFactory.createHorizontalBox (
764: Multilingual.mlnTitledBorder (
765: ComponentFactory.setTitledLineBorder (olgDumpTextArea, "Log"),
766: "ja", "ログ"),
767: Multilingual.mlnTitledBorder (
768: ComponentFactory.setTitledLineBorder (
769: ComponentFactory.createHorizontalBox (olgTonePanel), "Tone"),
770: "ja", "音色")))),
771: "ja", "OPM ログ");
772:
773: olgPaint ();
774:
775: }
776:
777: public static void olgMoveCaret (int dxPx) {
778: olgCaretUs = Math.max (0,
779: Math.min ((Math.max (0, olgBuffer[olgLength - 2] - 1) / olgUsPerPx) * olgUsPerPx,
780: olgCaretUs + olgUsPerPx * dxPx));
781: olgCaretPx = (olgCaretUs - olgStartUs) / olgUsPerPx;
782: if (olgCaretPx < 0) {
783: olgStartUs = Math.max (0, olgStartUs - olgRangeUs);
784: olgCaretPx = (olgCaretUs - olgStartUs) / olgUsPerPx;
785: olgEndUs = olgStartUs + olgRangeUs;
786: } else if (OLG_SCORE_WIDTH <= olgCaretPx) {
787: olgStartUs = olgStartUs + olgRangeUs;
788: olgCaretPx = (olgCaretUs - olgStartUs) / olgUsPerPx;
789: olgEndUs = olgStartUs + olgRangeUs;
790: }
791: olgPaint ();
792: }
793:
794:
795: public static void olgRecordStart () {
796: if (olgRecording) {
797: return;
798: }
799: olgRecording = true;
800: olgLength = 0;
801: olgStartTimePS = XEiJ.mpuClockTime;
802: olgCounter = 0;
803:
804: olgStartButton.setEnabled (false);
805: olgEndButton.setEnabled (true);
806:
807: olgForcedTerminationTask = new TimerTask () {
808: @Override public void run () {
809: olgRecordEnd ();
810: }
811: };
812: olgTimer.schedule (olgForcedTerminationTask, 1000L * 900);
813:
814: for (int a = 0x00; a <= 0xff; a++) {
815: if (a == 0x08) {
816: } else if (a == 0x19) {
817: for (int i = 0; i < 2; i++) {
818: olgBuffer[olgCounter++] = 0;
819: olgBuffer[olgCounter++] = a << 8 | (i << 7 | OPM.opmRegister[264 + i]);
820: }
821: } else {
822: olgBuffer[olgCounter++] = 0;
823: olgBuffer[olgCounter++] = a << 8 | OPM.opmRegister[a];
824: }
825: }
826:
827: for (int ch = 0; ch < 8; ch++) {
828: olgBuffer[olgCounter++] = 0;
829: olgBuffer[olgCounter++] = 0x08 << 8 | (OPM.opmRegister[256 + ch] << 3 | ch);
830: }
831: }
832:
833:
834: public static void olgRecordEnd () {
835: if (!olgRecording) {
836: return;
837: }
838:
839: olgBuffer[olgCounter++] = (int) ((XEiJ.mpuClockTime - olgStartTimePS) / (XEiJ.TMR_FREQ / OLG_UNIT));
840: olgBuffer[olgCounter++] = -1;
841:
842: olgRecording = false;
843: olgLength = olgCounter;
844: olgStartTimePS = 0L;
845: olgCounter = 0;
846:
847: if (olgForcedTerminationTask != null) {
848: olgForcedTerminationTask.cancel ();
849: olgForcedTerminationTask = null;
850: }
851:
852:
853: olgEndButton.setEnabled (false);
854:
855: olgTimer.schedule (new TimerTask () {
856: @Override public void run () {
857: olgMakeWaveData ();
858: olgPaint ();
859: olgStartButton.setEnabled (true);
860:
861: }
862: }, 0L);
863: }
864:
865:
866: public static void olgSetData (int a, int d) {
867: if (olgRecording) {
868: if (OLG_BUFFER_SIZE - 2 <= olgCounter) {
869: olgRecordEnd ();
870: } else {
871: olgBuffer[olgCounter++] = (int) ((XEiJ.mpuClockTime - olgStartTimePS) / (XEiJ.TMR_FREQ / OLG_UNIT));
872: olgBuffer[olgCounter++] = a << 8 | d;
873: }
874: }
875: }
876:
877:
878: public static void olgSetCSMKON () {
879: if (olgRecording) {
880: if (OLG_BUFFER_SIZE - 2 <= olgCounter) {
881: olgRecordEnd ();
882: } else {
883: olgBuffer[olgCounter++] = (int) ((XEiJ.mpuClockTime - olgStartTimePS) / (XEiJ.TMR_FREQ / OLG_UNIT));
884: olgBuffer[olgCounter++] = 0x10000;
885: }
886: }
887: }
888:
889: private static final int[] addressToData = new int[266];
890: private static final int[] addressToUs = new int[266];
891: private static final int[] channelToKindex = new int[8];
892: private static final int[] channelToKonUs = new int[8];
893: private static final int[] caretAddressToData = new int[266];
894: private static final int[] caretAddressToUs = new int[266];
895: private static final int[] lastCaretAddressToUs = new int[266];
896: private static final boolean[] strong = new boolean[OLG_TONE_BASE.length];
897:
898:
899:
900:
901:
902:
903:
904:
905:
906:
907:
908:
909:
910: private static final int[] TONE_MAP = new int[] {
911:
912: 0x20, 1, 0b11000000, 30, 0b00111111, 3,
913: 0x28, 8, 0b01111111, 3, 0, 0,
914: 0x30, 8, 0b11111100, 6, 0, 0,
915: 0x38, 1, 0b01110000, 24, 0b00000011, 27,
916:
917: 0x40, 3, 0b01110000, 27, 0b00001111, 24,
918: 0x48, 5, 0b01110000, 27, 0b00001111, 24,
919: 0x50, 4, 0b01110000, 27, 0b00001111, 24,
920: 0x58, 6, 0b01110000, 27, 0b00001111, 24,
921:
922: 0x60, 3, 0b01111111, 18, 0, 0,
923: 0x68, 5, 0b01111111, 18, 0, 0,
924: 0x70, 4, 0b01111111, 18, 0, 0,
925: 0x78, 6, 0b01111111, 18, 0, 0,
926:
927: 0x80, 3, 0b11000000, 21, 0b00011111, 3,
928: 0x88, 5, 0b11000000, 21, 0b00011111, 3,
929: 0x90, 4, 0b11000000, 21, 0b00011111, 3,
930: 0x98, 6, 0b11000000, 21, 0b00011111, 3,
931:
932: 0xa0, 3, 0b10000000, 33, 0b00011111, 6,
933: 0xa8, 5, 0b10000000, 33, 0b00011111, 6,
934: 0xb0, 4, 0b10000000, 33, 0b00011111, 6,
935: 0xb8, 6, 0b10000000, 33, 0b00011111, 6,
936:
937: 0xc0, 3, 0b11000000, 30, 0b00011111, 9,
938: 0xc8, 5, 0b11000000, 30, 0b00011111, 9,
939: 0xd0, 4, 0b11000000, 30, 0b00011111, 9,
940: 0xd8, 6, 0b11000000, 30, 0b00011111, 9,
941:
942: 0xe0, 3, 0b11110000, 15, 0b00001111, 12,
943: 0xe8, 5, 0b11110000, 15, 0b00001111, 12,
944: 0xf0, 4, 0b11110000, 15, 0b00001111, 12,
945: 0xf8, 6, 0b11110000, 15, 0b00001111, 12,
946:
947: 256, 1, 0b00001111, 6, 0, 0,
948: };
949:
950:
951: public static void olgPaint () {
952: Graphics2D g2 = olgCanvasImage.createGraphics ();
953:
954: g2.setColor (Color.black);
955: g2.fillRect (0, 0, OLG_SCORE_IMAGE_WIDTH, OLG_SCORE_IMAGE_HEIGHT);
956:
957: {
958: g2.setColor (Color.darkGray);
959: g2.setStroke (olgSolidStroke);
960: int stepPx = 10;
961: int stepUs = olgUsPerPx * stepPx;
962: int us0 = ((olgStartUs + (stepUs - 1)) / stepUs) * stepUs;
963: int px0 = olgUsToPx (us0);
964: for (int px = px0; px < OLG_SCORE_WIDTH; px += stepPx) {
965: int us = olgPxToUs (px);
966: if (us % (stepUs * 10) != 0) {
967: g2.drawLine (OLG_SCORE_H_MARGIN + px, OLG_SCORE_V_MARGIN,
968:
969: OLG_SCORE_H_MARGIN + px, OLG_WAVE_YM1);
970: }
971: }
972: }
973:
974: g2.setColor (Color.darkGray);
975: g2.setStroke (olgSolidStroke);
976:
977:
978: for (int oct12 = -6; oct12 < 12 * 8 - 6; oct12++) {
979: if ((1 << ((oct12 + 12) % 12) & (1 << 2 | 1 << 3 | 1 << 5 | 1 << 7 | 1 << 8 | 1 << 10)) != 0) {
980: double oct = oct12 / 12.0;
981: int kindex = (int) Math.floor (0.5 + 3584.0 + 64.0 * 12.0 * (oct - 4.0 + LOG2_358_400));
982: int y = OLG_SCORE_HEIGHT * (6208 - 1 - kindex) / 6208;
983: g2.drawLine (OLG_SCORE_H_MARGIN, OLG_SCORE_V_MARGIN + y,
984: OLG_SCORE_H_MARGIN + OLG_SCORE_WIDTH - 1, OLG_SCORE_V_MARGIN + y);
985: }
986: }
987:
988: g2.setFont (LnF.lnfMonospacedFont12);
989: g2.setStroke (olgSolidStroke);
990: {
991: int stepPx = 100;
992: int stepUs = olgUsPerPx * stepPx;
993: int us0 = ((olgStartUs + (stepUs - 1)) / stepUs) * stepUs;
994: int px0 = olgUsToPx (us0);
995: for (int px = px0; px < OLG_SCORE_WIDTH; px += stepPx) {
996: int us = olgPxToUs (px);
997: g2.setColor (Color.gray);
998: g2.drawLine (OLG_SCORE_H_MARGIN + px, OLG_SCORE_V_MARGIN,
999:
1000: OLG_SCORE_H_MARGIN + px, OLG_WAVE_YM1);
1001: g2.setColor (Color.white);
1002: g2.drawString (String.valueOf ((double) us / 1000000.0) + "s",
1003: OLG_SCORE_H_MARGIN + px + 3, OLG_SCORE_V_MARGIN + OLG_SCORE_HEIGHT - 2);
1004: }
1005: }
1006:
1007:
1008:
1009:
1010:
1011:
1012:
1013:
1014:
1015:
1016:
1017:
1018: g2.setFont (LnF.lnfMonospacedFont12);
1019: g2.setStroke (olgSolidStroke);
1020: for (int oct = 0; oct < 8; oct++) {
1021: int kindex = (int) Math.floor (0.5 + 3584.0 + 64.0 * 12.0 * ((double) (oct - 4) + LOG2_358_400));
1022: int y = OLG_SCORE_HEIGHT * (6208 - 1 - kindex) / 6208;
1023: g2.setColor (Color.gray);
1024: g2.drawLine (OLG_SCORE_H_MARGIN, OLG_SCORE_V_MARGIN + y,
1025: OLG_SCORE_H_MARGIN + OLG_SCORE_WIDTH - 1, OLG_SCORE_V_MARGIN + y);
1026: g2.setColor (Color.white);
1027: g2.drawString ("o" + oct + "a", OLG_SCORE_H_MARGIN + 3, OLG_SCORE_V_MARGIN + y - 2);
1028: }
1029:
1030: g2.setColor (Color.darkGray);
1031: g2.drawLine (OLG_SCORE_H_MARGIN, OLG_WAVE_Y1,
1032: OLG_SCORE_H_MARGIN + OLG_SCORE_WIDTH - 1, OLG_WAVE_Y1);
1033: g2.setColor (Color.gray);
1034: g2.drawLine (OLG_SCORE_H_MARGIN, OLG_WAVE_Y0,
1035: OLG_SCORE_H_MARGIN + OLG_SCORE_WIDTH - 1, OLG_WAVE_Y0);
1036: g2.setColor (Color.darkGray);
1037: g2.drawLine (OLG_SCORE_H_MARGIN, OLG_WAVE_YM1,
1038: OLG_SCORE_H_MARGIN + OLG_SCORE_WIDTH - 1, OLG_WAVE_YM1);
1039: if (opmBuffer != null) {
1040: Path2D pathL = new Path2D.Float ();
1041: Path2D pathR = new Path2D.Float ();
1042: for (int x = 0; x < OLG_SCORE_WIDTH; x++) {
1043: int us = olgPxToUs (x);
1044: int i = OPM_CHANNELS * (us >> 4);
1045: if (opmBuffer.length <= i) {
1046: break;
1047: }
1048: int yL = (OLG_WAVE_RADIUS * opmBuffer[i ]) >> 15;
1049: int yR = (OLG_WAVE_RADIUS * opmBuffer[i + 1]) >> 15;
1050: if (x == 0) {
1051: pathL.moveTo ((float) (OLG_SCORE_H_MARGIN + x), (float) (OLG_WAVE_Y0 - yL));
1052: pathR.moveTo ((float) (OLG_SCORE_H_MARGIN + x), (float) (OLG_WAVE_Y0 - yR));
1053: } else {
1054: pathL.lineTo ((float) (OLG_SCORE_H_MARGIN + x), (float) (OLG_WAVE_Y0 - yL));
1055: pathR.lineTo ((float) (OLG_SCORE_H_MARGIN + x), (float) (OLG_WAVE_Y0 - yR));
1056: }
1057: }
1058: g2.setStroke (olgWaveStroke);
1059: g2.setColor (Color.yellow);
1060: g2.draw (pathL);
1061: g2.setColor (Color.cyan);
1062: g2.draw (pathR);
1063: }
1064:
1065: Arrays.fill (addressToData, 0);
1066: Arrays.fill (addressToUs, -1);
1067: Arrays.fill (channelToKindex, 0);
1068: Arrays.fill (channelToKonUs, -1);
1069: Arrays.fill (caretAddressToData, 0);
1070: Arrays.fill (caretAddressToUs, -1);
1071:
1072: int caretIndex = -1;
1073: g2.setStroke (olgSolidStroke);
1074: for (int index = 0; index < olgLength; index += 2) {
1075: int us = olgBuffer[index];
1076: int ad = olgBuffer[index + 1];
1077: if (olgEndUs <= us || ad == -1) {
1078: break;
1079: }
1080: if (ad == 0x10000) {
1081: continue;
1082: }
1083: if (caretIndex == -1 && olgCaretUs <= us) {
1084: caretIndex = index;
1085: System.arraycopy (addressToData, 0,
1086: caretAddressToData, 0,
1087: addressToData.length);
1088: System.arraycopy (addressToUs, 0,
1089: caretAddressToUs, 0,
1090: addressToUs.length);
1091: }
1092: int a = ad >> 8;
1093: int d = ad & 255;
1094: addressToData[a] = d;
1095: addressToUs[a] = us;
1096: if (!((a == 0x08 && !olgChannelMask[d & 7]) ||
1097: (0x10 <= a && a <= 0x12) ||
1098: (0x20 <= a && !olgChannelMask[a & 7]))) {
1099: g2.setColor (a == 0x08 ? OLG_KON_COLOR[d & 7] :
1100: 0x20 <= a ? OLG_KON_COLOR[a & 7] :
1101: Color.white);
1102: int px = olgUsToPx (us);
1103: g2.drawLine (OLG_SCORE_H_MARGIN + px, OLG_SCORE_V_MARGIN + OLG_SCORE_HEIGHT - 14 - (OLG_KON1ST_HEIGHT - 1),
1104: OLG_SCORE_H_MARGIN + px, OLG_SCORE_V_MARGIN + OLG_SCORE_HEIGHT - 14);
1105: }
1106: if (a == 0x08) {
1107: int channel = d & 7;
1108: if (channelToKonUs[channel] != -1) {
1109: olgDrawKoff (g2, channel, channelToKindex[channel], channelToKonUs[channel], us);
1110: channelToKonUs[channel] = -1;
1111: }
1112: int slotMask = (d >> 3) & 15;
1113: addressToData[256 + channel] = slotMask;
1114: addressToUs[256 + channel] = us;
1115: if (slotMask != 0) {
1116: olgDrawKon1st (g2, channel, channelToKindex[channel], us);
1117: channelToKonUs[channel] = us;
1118: }
1119: } else if (a == 0x19) {
1120: int aa = (d & 128) == 0 ? 264 : 265;
1121: addressToData[aa] = d & 127;
1122: addressToUs[aa] = us;
1123: } else if (0x28 <= a && a < 0x30) {
1124: int channel = a & 7;
1125: int kc = d & 127;
1126: int kf = (addressToData[0x30 + channel] >> 2) & 63;
1127: int kindex = ((kc - (kc >> 2)) << 6) | kf;
1128: if (channelToKonUs[channel] != -1) {
1129: olgDrawKoff (g2, channel, channelToKindex[channel], channelToKonUs[channel], us);
1130: olgDrawKon2nd (g2, channel, kindex, us);
1131: channelToKonUs[channel] = us;
1132: }
1133: channelToKindex[channel] = kindex;
1134: } else if (0x30 <= a && a < 0x38) {
1135: int channel = a & 7;
1136: int kc = addressToData[0x28 + channel] & 127;
1137: int kf = (d >> 2) & 63;
1138: int kindex = ((kc - (kc >> 2)) << 6) | kf;
1139: if (channelToKonUs[channel] != -1) {
1140: olgDrawKoff (g2, channel, channelToKindex[channel], channelToKonUs[channel], us);
1141: olgDrawKon2nd (g2, channel, kindex, us);
1142: channelToKonUs[channel] = us;
1143: }
1144: channelToKindex[channel] = kindex;
1145: }
1146: }
1147: for (int channel = 0; channel < 8; channel++) {
1148: if (channelToKonUs[channel] != -1) {
1149: olgDrawKoff (g2, channel, channelToKindex[channel], channelToKonUs[channel], Math.min (olgBuffer[olgLength - 2], olgEndUs));
1150: channelToKonUs[channel] = -1;
1151: }
1152: }
1153:
1154: if (olgMaskLeftUs != -1 &&
1155: olgStartUs < olgMaskLeftUs) {
1156: int px0 = 0;
1157: int px1 = olgUsToPx (Math.min (olgEndUs, olgMaskLeftUs));
1158: g2.setPaint (olgMaskPaint);
1159: g2.fillRect (OLG_SCORE_H_MARGIN + px0, OLG_SCORE_V_MARGIN, px1 - px0, OLG_SCORE_HEIGHT);
1160: }
1161:
1162: if (olgMaskRightUs != -1 &&
1163: olgMaskRightUs < olgEndUs) {
1164: int px0 = olgUsToPx (Math.max (olgStartUs, olgMaskRightUs));
1165: int px1 = OLG_SCORE_WIDTH;
1166: g2.setPaint (olgMaskPaint);
1167: g2.fillRect (OLG_SCORE_H_MARGIN + px0, OLG_SCORE_V_MARGIN, px1 - px0, OLG_SCORE_HEIGHT);
1168: }
1169:
1170: g2.setColor (Color.green);
1171: g2.setStroke (olgDashStroke);
1172: g2.drawLine (OLG_SCORE_H_MARGIN + olgCaretPx, OLG_SCORE_V_MARGIN,
1173:
1174: OLG_SCORE_H_MARGIN + olgCaretPx, OLG_WAVE_YM1);
1175: olgCanvas.repaint ();
1176:
1177:
1178: Arrays.fill (olgToneBitmap, 0xff000000);
1179: for (int ch = 0; ch < 8; ch++) {
1180: Arrays.fill (strong, false);
1181: for (int j = 0; j < TONE_MAP.length; j += 6) {
1182: int address = TONE_MAP[j ];
1183: int row = TONE_MAP[j + 1];
1184: int mask1 = TONE_MAP[j + 2];
1185: int col1 = TONE_MAP[j + 3];
1186: int mask2 = TONE_MAP[j + 4];
1187: int col2 = TONE_MAP[j + 5];
1188: int a = address + ch;
1189: XEiJ.fmtHex2 (OLG_TONE_BASE, OLG_TONE_COLS * row + col1, (caretAddressToData[a] & mask1) >> Integer.numberOfTrailingZeros (mask1));
1190: if (mask2 != 0) {
1191: XEiJ.fmtHex2 (OLG_TONE_BASE, OLG_TONE_COLS * row + col2, (caretAddressToData[a] & mask2) >> Integer.numberOfTrailingZeros (mask2));
1192: }
1193: if (lastCaretAddressToUs[a] != caretAddressToUs[a]) {
1194: strong[OLG_TONE_COLS * row + col1 ] = true;
1195: strong[OLG_TONE_COLS * row + col1 + 1] = true;
1196: if (mask2 != 0) {
1197: strong[OLG_TONE_COLS * row + col2 ] = true;
1198: strong[OLG_TONE_COLS * row + col2 + 1] = true;
1199: }
1200: }
1201: }
1202: {
1203: int a = 0x18;
1204: int d = caretAddressToData[a];
1205: int row = 1;
1206: int col = 15;
1207: XEiJ.fmtHex2 (OLG_TONE_BASE, OLG_TONE_COLS * row + col, d & 255);
1208: if (lastCaretAddressToUs[a] != caretAddressToUs[a]) {
1209: strong[OLG_TONE_COLS * row + col ] = true;
1210: strong[OLG_TONE_COLS * row + col + 1] = true;
1211: }
1212: }
1213: {
1214: int a = 0x1b;
1215: int d = caretAddressToData[a];
1216: int row = 1;
1217: int col = 9;
1218: XEiJ.fmtHex2 (OLG_TONE_BASE, OLG_TONE_COLS * row + col, d & 3);
1219: if (lastCaretAddressToUs[a] != caretAddressToUs[a]) {
1220: strong[OLG_TONE_COLS * row + col ] = true;
1221: strong[OLG_TONE_COLS * row + col + 1] = true;
1222: }
1223: }
1224: {
1225: int a = 264;
1226: int d = caretAddressToData[a];
1227: int row = 1;
1228: int col = 21;
1229: XEiJ.fmtHex2 (OLG_TONE_BASE, OLG_TONE_COLS * row + col, d);
1230: if (lastCaretAddressToUs[a] != caretAddressToUs[a]) {
1231: strong[OLG_TONE_COLS * row + col ] = true;
1232: strong[OLG_TONE_COLS * row + col + 1] = true;
1233: }
1234: }
1235: {
1236: int a = 265;
1237: int d = caretAddressToData[a];
1238: int row = 1;
1239: int col = 18;
1240: XEiJ.fmtHex2 (OLG_TONE_BASE, OLG_TONE_COLS * row + col, d);
1241: if (lastCaretAddressToUs[a] != caretAddressToUs[a]) {
1242: strong[OLG_TONE_COLS * row + col ] = true;
1243: strong[OLG_TONE_COLS * row + col + 1] = true;
1244: }
1245: }
1246: int chCol = ch & 3;
1247: int chRow = ch >> 2;
1248: int chX = OLG_TONE_H_MARGIN + (OLG_TONE_CHAR_WIDTH * OLG_TONE_COLS + OLG_TONE_H_SPACE) * chCol;
1249: int chY = OLG_TONE_V_MARGIN + (OLG_TONE_LINE_HEIGHT * OLG_TONE_ROWS + OLG_TONE_V_SPACE) * chRow;
1250: int rgb = (olgChannelMask[ch] ? (caretAddressToData[256 + ch] != 0 ? OLG_KON_COLOR : OLG_BAR_COLOR)[ch] : Color.darkGray).getRGB ();
1251: for (int row = 0; row < OLG_TONE_ROWS; row++) {
1252: for (int col = 0; col < OLG_TONE_COLS; col++) {
1253: int c = OLG_TONE_BASE[col + OLG_TONE_COLS * row];
1254: for (int v = 0; v < 8; v++) {
1255: int t = FontPage.Lcd.LCD6X8_FONT[8 * c + v] << 24;
1256: for (int u = 0; u < 6; u++) {
1257: olgToneBitmap[chX + OLG_TONE_CHAR_WIDTH * col + u +
1258: OLG_TONE_IMAGE_WIDTH * (chY + OLG_TONE_LINE_HEIGHT * row + v)] = t < 0 ? rgb : 0xff000000;
1259: t <<= 1;
1260: }
1261: }
1262: if (strong[col + OLG_TONE_COLS * row]) {
1263: for (int u = 0; u < 6; u++) {
1264: olgToneBitmap[chX + OLG_TONE_CHAR_WIDTH * col + u +
1265: OLG_TONE_IMAGE_WIDTH * (chY + OLG_TONE_LINE_HEIGHT * row + 8)] = rgb;
1266: }
1267: }
1268: }
1269: }
1270: }
1271: System.arraycopy (caretAddressToUs, 0,
1272: lastCaretAddressToUs, 0,
1273: caretAddressToUs.length);
1274: olgTonePanel.repaint ();
1275:
1276:
1277: if (caretIndex == -1) {
1278: caretIndex = Math.max (0, olgLength - 2);
1279: }
1280: {
1281:
1282:
1283: int leftUs = olgCaretUs;
1284: int leftIndex = caretIndex;
1285: while (Math.max (0, caretIndex - 2 * 10) < leftIndex) {
1286: leftUs = Math.max (0, leftUs - olgUsPerPx);
1287: while (0 < leftIndex && leftUs <= olgBuffer[leftIndex - 2]) {
1288: leftIndex -= 2;
1289: }
1290: }
1291:
1292: int rightUs = olgCaretUs;
1293: int rightIndex = caretIndex;
1294: while (rightIndex < Math.min (olgLength - 2, caretIndex + 2 * 10)) {
1295: rightUs = Math.min (olgBuffer[olgLength - 2], rightUs + olgUsPerPx);
1296: while (rightIndex < olgLength - 2 && olgBuffer[rightIndex + 2] <= rightUs) {
1297: rightIndex += 2;
1298: }
1299: }
1300:
1301: StringBuilder sb = new StringBuilder ();
1302: for (int index = leftIndex; index <= rightIndex; index += 2) {
1303: if (index == caretIndex) {
1304: sb.append ("--------------------\n");
1305: }
1306: int us = olgBuffer[index];
1307: int ad = olgBuffer[index + 1];
1308: sb.append (String.valueOf ((double) us / 1000000.0)).append ("s");
1309: if (ad == -1) {
1310: sb.append (" -1 END\n");
1311: break;
1312: }
1313: sb.append (" 0x");
1314: XEiJ.fmtHex4 (sb, ad);
1315: if (ad == 0x10000) {
1316: sb.append (" CSMKON\n");
1317: continue;
1318: }
1319: int a = (ad >> 8) & 255;
1320: int d = ad & 255;
1321: if (a < 0x20) {
1322: switch (a) {
1323: case 0x01:
1324: sb.append (" LFORESET=").append ((d >> 1) & 1);
1325: break;
1326: case 0x08:
1327: sb.append (" KON[").append (d & 7).append ("]=").append ((d >> 3) & 15);
1328: break;
1329: case 0x0f:
1330: sb.append (" NE=").append ((d >> 7) & 1);
1331: sb.append (" NFRQ=").append (d & 31);
1332: break;
1333: case 0x10:
1334: sb.append (" CLKA1=").append (d & 255);
1335: break;
1336: case 0x11:
1337: sb.append (" CLKA2=").append (d & 3);
1338: break;
1339: case 0x12:
1340: sb.append (" CLKB=").append (d & 255);
1341: break;
1342: case 0x14:
1343: sb.append (" CSM=").append ((d >> 7) & 1);
1344: sb.append (" RESETB=").append ((d >> 5) & 1);
1345: sb.append (" RESETA=").append ((d >> 4) & 1);
1346: sb.append (" IRQENB=").append ((d >> 3) & 1);
1347: sb.append (" IRQENA=").append ((d >> 2) & 1);
1348: sb.append (" LOADB=").append ((d >> 1) & 1);
1349: sb.append (" LOADA=").append (d & 1);
1350: break;
1351: case 0x18:
1352: sb.append (" LFRQ=").append (d & 255);
1353: break;
1354: case 0x19:
1355: if (((d >> 7) & 1) == 0) {
1356: sb.append (" AMD=").append (d & 127);
1357: } else {
1358: sb.append (" PMD=").append (d & 127);
1359: }
1360: break;
1361: case 0x1b:
1362: sb.append (" CT1=").append ((d >> 7) & 1);
1363: sb.append (" CT2=").append ((d >> 6) & 1);
1364: sb.append (" W=").append (d & 3);
1365: break;
1366: }
1367: } else if (a < 0x40) {
1368: sb.append (" CH").append (a & 7);
1369: switch (a >> 3) {
1370: case 0x20 >> 3:
1371: sb.append (" R=").append ((d >> 7) & 1);
1372: sb.append (" L=").append ((d >> 6) & 1);
1373: sb.append (" FL=").append ((d >> 3) & 7);
1374: sb.append (" CON=").append (d & 7);
1375: break;
1376: case 0x28 >> 3:
1377: sb.append (" KC=").append (d & 127);
1378: break;
1379: case 0x30 >> 3:
1380: sb.append (" KF=").append ((d >> 2) & 63);
1381: break;
1382: case 0x38 >> 3:
1383: sb.append (" PMS=").append ((d >> 4) & 7);
1384: sb.append (" AMS=").append (d & 3);
1385: break;
1386: }
1387: } else {
1388: sb.append (" CH").append (a & 7);
1389: sb.append (((a >> 3) & 3) == 0 ? " M1" :
1390: ((a >> 3) & 3) == 1 ? " M2" :
1391: ((a >> 3) & 3) == 2 ? " C1" : " C2");
1392: switch (a >> 5) {
1393: case 0x40 >> 5:
1394: sb.append (" DT1=").append ((d >> 4) & 7);
1395: sb.append (" MUL=").append (d & 15);
1396: break;
1397: case 0x60 >> 5:
1398: sb.append (" TL=").append (d & 127);
1399: break;
1400: case 0x80 >> 5:
1401: sb.append (" KS=").append ((d >> 6) & 3);
1402: sb.append (" AR=").append (d & 31);
1403: break;
1404: case 0xa0 >> 5:
1405: sb.append (" AMSEN=").append ((d >> 7) & 1);
1406: sb.append (" D1R=").append (d & 31);
1407: break;
1408: case 0xc0 >> 5:
1409: sb.append (" DT2=").append ((d >> 6) & 3);
1410: sb.append (" D2R=").append (d & 31);
1411: break;
1412: case 0xe0 >> 5:
1413: sb.append (" D1L=").append ((d >> 4) & 15);
1414: sb.append (" RR=").append (d & 15);
1415: break;
1416: }
1417: }
1418: sb.append ("\n");
1419: }
1420: String text = sb.toString ();
1421: olgDumpTextArea.setText (text);
1422: olgDumpTextArea.setCaretPosition (text.length ());
1423: olgDumpTextArea.setCaretPosition (text.indexOf ("----"));
1424: }
1425: }
1426:
1427:
1428: public static void olgDrawKon1st (Graphics2D g2, int channel, int kindex, int us) {
1429: if (olgStartUs <= us && us < olgEndUs &&
1430: olgChannelMask[channel]) {
1431: int py = OLG_SCORE_HEIGHT * (6208 - 1 - kindex) / 6208;
1432: int px = Math.max (0, us - olgStartUs) / olgUsPerPx;
1433: g2.setColor (OLG_KON_COLOR[channel]);
1434: g2.drawLine (OLG_SCORE_H_MARGIN + px, OLG_SCORE_V_MARGIN + py - (OLG_KON1ST_HEIGHT >> 1),
1435: OLG_SCORE_H_MARGIN + px, OLG_SCORE_V_MARGIN + py + (OLG_KON1ST_HEIGHT >> 1));
1436: }
1437: }
1438: public static void olgDrawKon2nd (Graphics2D g2, int channel, int kindex, int us) {
1439: if (olgStartUs <= us && us < olgEndUs &&
1440: olgChannelMask[channel]) {
1441: int py = OLG_SCORE_HEIGHT * (6208 - 1 - kindex) / 6208;
1442: int px = Math.max (0, us - olgStartUs) / olgUsPerPx;
1443: g2.setColor (OLG_BAR_COLOR[channel]);
1444: g2.drawLine (OLG_SCORE_H_MARGIN + px, OLG_SCORE_V_MARGIN + py - (OLG_KON2ND_HEIGHT >> 1),
1445: OLG_SCORE_H_MARGIN + px, OLG_SCORE_V_MARGIN + py + (OLG_KON2ND_HEIGHT >> 1));
1446: }
1447: }
1448: public static void olgDrawKoff (Graphics2D g2, int channel, int kindex, int leftUs, int rightUs) {
1449: if (olgStartUs < rightUs && leftUs < olgEndUs &&
1450: olgChannelMask[channel]) {
1451: int py = OLG_SCORE_HEIGHT * (6208 - 1 - kindex) / 6208;
1452: int px0 = Math.max (0, leftUs - olgStartUs) / olgUsPerPx;
1453: int px1 = (rightUs - olgStartUs) / olgUsPerPx;
1454: if (px0 + 1 < px1) {
1455: g2.setColor (OLG_BAR_COLOR[channel]);
1456: g2.fillRect (OLG_SCORE_H_MARGIN + px0 + 1, OLG_SCORE_V_MARGIN + py - (OLG_BAR_HEIGHT >> 1),
1457: px1 - (px0 + 1), OLG_BAR_HEIGHT);
1458: }
1459: }
1460: }
1461:
1462:
1463: public static void olgLoadMML () {
1464: JFileChooser2 fileChooser = new JFileChooser2 (olgLastMMLFile);
1465: fileChooser.setFileFilter (olgMMLFilter);
1466: if (fileChooser.showOpenDialog (null) != JFileChooser.APPROVE_OPTION) {
1467: return;
1468: }
1469: File file = fileChooser.getSelectedFile ();
1470: String program = XEiJ.rscGetTextFile (file.getPath ());
1471: MMLCompiler compiler = new MMLCompiler ();
1472: int[] array = compiler.compile (program);
1473: if (array == null) {
1474: JOptionPane.showMessageDialog (null, compiler.getError ());
1475: return;
1476: }
1477: olgLastMMLFile = file;
1478: System.arraycopy (array, 0, olgBuffer, 0, array.length);
1479: olgLength = array.length;
1480: olgMakeWaveData ();
1481: olgPaint ();
1482: }
1483:
1484:
1485: public static void olgLoadLog () {
1486: JFileChooser2 fileChooser = new JFileChooser2 (olgLastFile);
1487: fileChooser.setFileFilter (olgFilter);
1488: if (fileChooser.showOpenDialog (null) != JFileChooser.APPROVE_OPTION) {
1489: return;
1490: }
1491: File file = fileChooser.getSelectedFile ();
1492: byte[] b = XEiJ.rscGetFile (file.getPath ());
1493:
1494: boolean error = !(8 <= b.length && b.length <= 4 * OLG_BUFFER_SIZE && b.length % 8 == 0);
1495: if (!error) {
1496: olgLength = b.length >> 2;
1497: for (int i = 0; i < olgLength; i++) {
1498: olgBuffer[i] = ((b[4 * i ] ) << 24 |
1499: (b[4 * i + 1] & 255) << 16 |
1500: (b[4 * i + 2] & 255) << 8 |
1501: (b[4 * i + 3] & 255));
1502: }
1503: int lastUs = 0;
1504: for (int i = 0; i < olgLength; i += 2) {
1505: int us = olgBuffer[i];
1506: int ad = olgBuffer[i + 1];
1507:
1508:
1509: if (!(0 <= us && us <= 999999999 && lastUs <= us &&
1510: (i < olgLength - 2 ? 0 <= ad && ad <= 0x10000 : ad == -1))) {
1511: error = true;
1512: break;
1513: }
1514: lastUs = us;
1515: }
1516: if (!error) {
1517: olgLastFile = file;
1518: }
1519: }
1520: if (error) {
1521: olgBuffer[0] = 0;
1522: olgBuffer[1] = -1;
1523: olgLength = 2;
1524: }
1525: olgMakeWaveData ();
1526: olgPaint ();
1527: }
1528:
1529:
1530: public static void olgSaveLog () {
1531: byte[] b = new byte[4 * olgLength];
1532: for (int i = 0; i < olgLength; i++) {
1533: int t = olgBuffer[i];
1534: b[4 * i ] = (byte) (t >> 24);
1535: b[4 * i + 1] = (byte) (t >> 16);
1536: b[4 * i + 2] = (byte) (t >> 8);
1537: b[4 * i + 3] = (byte) t;
1538: }
1539: JFileChooser2 fileChooser = new JFileChooser2 (olgLastFile);
1540: fileChooser.setFileFilter (olgFilter);
1541: if (fileChooser.showSaveDialog (null) != JFileChooser.APPROVE_OPTION) {
1542: return;
1543: }
1544: File file = fileChooser.getSelectedFile ();
1545: if (XEiJ.rscPutFile (file.getPath (), b, 0, 4 * olgLength)) {
1546: olgLastFile = file;
1547: }
1548: }
1549:
1550:
1551:
1552:
1553:
1554:
1555:
1556:
1557:
1558: public static void olgAdjust () {
1559: int us1 = 0;
1560: int us2 = 0;
1561: for (int i = 0; i < olgLength; i += 2) {
1562: int us = olgBuffer[i];
1563: if (us == 0) {
1564: continue;
1565: }
1566: int ad = olgBuffer[i + 1];
1567: if (us1 == 0) {
1568: us1 = us;
1569: }
1570: if (ad == 0x10000) {
1571: us2 = us;
1572: break;
1573: }
1574: if (ad != -1) {
1575: int a = ad >> 8;
1576: int d = ad & 255;
1577: if (a == 0x08) {
1578: int mask = (d >> 3) & 15;
1579: if (mask != 0) {
1580: us2 = us;
1581: break;
1582: }
1583: }
1584: }
1585: }
1586: if (us2 == 0) {
1587: return;
1588: }
1589: int us3 = ((us2 - us1 + 1 + (1000000 - 1)) / 1000000) * 1000000;
1590: for (int i = 0; i < olgLength; i += 2) {
1591: int us = olgBuffer[i];
1592: if (us == 0) {
1593: continue;
1594: }
1595: olgBuffer[i] += us3 - us2;
1596: }
1597: olgPaint ();
1598: }
1599:
1600: private static final int VOLUME = 1024;
1601: private static int samples62500;
1602: private static int samples48000;
1603: private static byte[] sampleBuffer;
1604: private static SourceDataLine sourceDataLine;
1605: private static int totalBytes;
1606: private static int writtenBytes;
1607: private static TimerTask playTask;
1608:
1609:
1610: public static void olgMakeWaveData () {
1611: olgYM2151.reset ();
1612: olgYM2151.setChannelMask ((olgChannelMask[0] ? 1 << 0 : 0) |
1613: (olgChannelMask[1] ? 1 << 1 : 0) |
1614: (olgChannelMask[2] ? 1 << 2 : 0) |
1615: (olgChannelMask[3] ? 1 << 3 : 0) |
1616: (olgChannelMask[4] ? 1 << 4 : 0) |
1617: (olgChannelMask[5] ? 1 << 5 : 0) |
1618: (olgChannelMask[6] ? 1 << 6 : 0) |
1619: (olgChannelMask[7] ? 1 << 7 : 0));
1620: samples62500 = 0;
1621: samples48000 = 0;
1622: int totalUs = olgBuffer[olgLength - 2];
1623: if (totalUs == 0) {
1624: return;
1625: }
1626:
1627: samples62500 = totalUs >> 4;
1628: olgYM2151.allocate (OPM_CHANNELS * samples62500);
1629: opmBuffer = olgYM2151.getBuffer ();
1630: int minUS = 0;
1631: for (int index = 0; index < olgLength; index += 2) {
1632: int us = olgBuffer[index];
1633: int ad = olgBuffer[index + 1];
1634: if (ad == -1) {
1635: break;
1636: }
1637: us = Math.max (minUS, us);
1638: int pointer = OPM_CHANNELS * (us >> 4);
1639: if (OPM_CHANNELS * samples62500 <= pointer) {
1640: break;
1641: }
1642: minUS = us + 16;
1643: olgYM2151.generate (pointer);
1644: if (ad == 0x10000) {
1645: olgYM2151.timerAExpired ();
1646: } else {
1647: olgYM2151.writeAddress (ad >> 8);
1648: olgYM2151.writeData (ad);
1649: }
1650: }
1651: olgYM2151.fill ();
1652:
1653: samples48000 = (int) (((long) samples62500 * 48000L) / 62500L);
1654: sampleBuffer = new byte[2 * OPM_CHANNELS * samples48000];
1655: for (int i48000 = 0; i48000 < samples48000; i48000++) {
1656: int i62500 = (int) (((long) i48000 * 62500L) / 48000L);
1657: if (OPM_CHANNELS == 1) {
1658: int m = (opmBuffer[i62500] * VOLUME) >> 10;
1659: m = Math.max (-32768, Math.min (32767, m));
1660: sampleBuffer[2 * i48000 ] = (byte) m;
1661: sampleBuffer[2 * i48000 + 1] = (byte) (m >> 8);
1662: } else {
1663: int l = (opmBuffer[2 * i62500 ] * VOLUME) >> 10;
1664: int r = (opmBuffer[2 * i62500 + 1] * VOLUME) >> 10;
1665: l = Math.max (-32768, Math.min (32767, l));
1666: r = Math.max (-32768, Math.min (32767, r));
1667: sampleBuffer[4 * i48000 ] = (byte) l;
1668: sampleBuffer[4 * i48000 + 1] = (byte) (l >> 8);
1669: sampleBuffer[4 * i48000 + 2] = (byte) r;
1670: sampleBuffer[4 * i48000 + 3] = (byte) (r >> 8);
1671: }
1672: }
1673: }
1674:
1675:
1676:
1677:
1678:
1679:
1680:
1681:
1682:
1683:
1684:
1685: public static void olgPlayStart () {
1686: int fromUs = olgMaskLeftUs != -1 ? olgMaskLeftUs : 0;
1687: int toUs = olgMaskRightUs != -1 ? olgMaskRightUs : olgBuffer[olgLength - 2];
1688: int from62500 = fromUs >> 4;
1689: int to62500 = toUs >> 4;
1690: int from48000 = (int) (((long) from62500 * 48000L) / 62500L);
1691: int to48000 = (int) (((long) to62500 * 48000L) / 62500L);
1692: int fromBytes = 2 * OPM_CHANNELS * from48000;
1693: int toBytes = 2 * OPM_CHANNELS * to48000;
1694: totalBytes = toBytes;
1695: writtenBytes = fromBytes;
1696: playTask = null;
1697:
1698: try {
1699: AudioFormat audioFormat = new AudioFormat (48000.0F,
1700: 16,
1701: OPM_CHANNELS,
1702: true,
1703: false);
1704: sourceDataLine = AudioSystem.getSourceDataLine (audioFormat);
1705: sourceDataLine.open (audioFormat, 2 * OPM_CHANNELS * 48000 * 500 / 1000);
1706: sourceDataLine.start ();
1707: } catch (Exception e) {
1708: e.printStackTrace ();
1709: return;
1710: }
1711:
1712: playTask = new TimerTask () {
1713: @Override public void run () {
1714: if (writtenBytes < totalBytes) {
1715:
1716: int thisTimeBytes = Math.min (2 * OPM_CHANNELS * 48000 * 200 / 1000, totalBytes - writtenBytes);
1717: if (thisTimeBytes <= sourceDataLine.available ()) {
1718:
1719: try {
1720: sourceDataLine.write (sampleBuffer, writtenBytes, thisTimeBytes);
1721: writtenBytes += thisTimeBytes;
1722: } catch (Exception e) {
1723: e.printStackTrace ();
1724: writtenBytes = totalBytes;
1725: }
1726: }
1727: } else {
1728: if (!sourceDataLine.isRunning ()) {
1729:
1730: playTask.cancel ();
1731: playTask = null;
1732: try {
1733: sourceDataLine.stop ();
1734: sourceDataLine.close ();
1735: } catch (Exception e) {
1736: e.printStackTrace ();
1737: }
1738: }
1739: }
1740: }
1741: };
1742: olgTimer.scheduleAtFixedRate (playTask, 0L, 100L);
1743: }
1744:
1745:
1746:
1747: public static void olgPlayEnd () {
1748: writtenBytes = totalBytes;
1749: }
1750:
1751: }