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