Commit 30549c6

Nick committed on
Oscilloscopes, VU meters, rendering optimizations, file format changes
commit 30549c6f7b1b08da4bf62463a715bb58d8bf10ac parent 556f79b
10 changed files +199−119
ModifiedSound/sound.pas +44−18
@@ -126,6 +126,15 @@ Bit0 Sound 1 on[1]/off[0]
126 126
127 *) 127 *)
128 128
129 const
130 SAMPLE_BUFFER_SIZE = 1024;
131
132 type
133 TSampleBuffer = record
134 BufferL, BufferR: array[0..SAMPLE_BUFFER_SIZE] of Integer;
135 Cursor: Integer;
136 end;
137
129 procedure EnableSound; 138 procedure EnableSound;
130 procedure DisableSound; 139 procedure DisableSound;
131 procedure ResetSound; 140 procedure ResetSound;
@@ -151,6 +160,7 @@ var
151 bit: byte; 160 bit: byte;
152 cnt: integer; 161 cnt: integer;
153 end; 162 end;
163 SampleBuffers: array[0..4] of TSampleBuffer;
154 164
155 implementation 165 implementation
156 166
@@ -267,14 +277,20 @@ const
267 277
268 var 278 var
269 swpClk, envClk, lenClk, freqClk, freq4Clk: longint; 279 swpClk, envClk, lenClk, freqClk, freq4Clk: longint;
270 l, r: integer;
271 280
272 procedure SoundUpdate(cycles: integer); 281 procedure SoundUpdate(cycles: integer);
273 var 282 var
274 n, stage: integer; 283 n, stage: integer;
284 ls: array[1..4] of Integer = (0, 0, 0, 0);
285 rs: array[1..4] of Integer = (0, 0, 0, 0);
286 l, r: Integer;
287 I: Integer;
275 begin 288 begin
276 if (not soundEnable) then 289 if (not soundEnable) then
277 exit; 290 exit;
291
292 l := 0;
293 r := 0;
278 if sndRegChange then 294 if sndRegChange then
279 begin 295 begin
280 snd[1].Freq := m_iram[$FF13] or ((m_iram[$FF14] and 7) shl 8); 296 snd[1].Freq := m_iram[$FF13] or ((m_iram[$FF14] and 7) shl 8);
@@ -496,15 +512,15 @@ begin
496 end; 512 end;
497 if m_iram[$FF25] and 1 > 0 then 513 if m_iram[$FF25] and 1 > 0 then
498 if snd[1].Bit > 0 then 514 if snd[1].Bit > 0 then
499 Inc(l, vol[snd[1].Vol]) 515 Inc(ls[1], vol[snd[1].Vol])
500 else 516 else
501 Dec(l, vol[snd[1].Vol]); 517 Dec(ls[1], vol[snd[1].Vol]);
502 518
503 if m_iram[$FF25] and $10 > 0 then 519 if m_iram[$FF25] and $10 > 0 then
504 if snd[1].bit > 0 then 520 if snd[1].bit > 0 then
505 Inc(r, vol[snd[1].Vol]) 521 Inc(rs[1], vol[snd[1].Vol])
506 else 522 else
507 Dec(r, vol[snd[1].Vol]); 523 Dec(rs[1], vol[snd[1].Vol]);
508 end; 524 end;
509 525
510 if not snd[2].channelOFF then 526 if not snd[2].channelOFF then
@@ -519,15 +535,15 @@ begin
519 end; 535 end;
520 if m_iram[$FF25] and 2 > 0 then 536 if m_iram[$FF25] and 2 > 0 then
521 if snd[2].bit > 0 then 537 if snd[2].bit > 0 then
522 Inc(l, vol[snd[2].Vol]) 538 Inc(ls[2], vol[snd[2].Vol])
523 else 539 else
524 Dec(l, vol[snd[2].Vol]); 540 Dec(ls[2], vol[snd[2].Vol]);
525 541
526 if m_iram[$FF25] and $20 > 0 then 542 if m_iram[$FF25] and $20 > 0 then
527 if snd[2].Bit > 0 then 543 if snd[2].Bit > 0 then
528 Inc(r, vol[snd[2].Vol]) 544 Inc(rs[2], vol[snd[2].Vol])
529 else 545 else
530 Dec(r, vol[snd[2].Vol]); 546 Dec(rs[2], vol[snd[2].Vol]);
531 end; 547 end;
532 548
533 if not snd[3].channelOFF then 549 if not snd[3].channelOFF then
@@ -552,9 +568,9 @@ begin
552 end; 568 end;
553 end; 569 end;
554 if m_iram[$FF25] and 4 > 0 then 570 if m_iram[$FF25] and 4 > 0 then
555 Inc(l, (snd[3].Bit shl 4) - $80); 571 Inc(ls[3], (snd[3].Bit shl 4) - $80);
556 if m_iram[$FF25] and $40 > 0 then 572 if m_iram[$FF25] and $40 > 0 then
557 Inc(r, (snd[3].Bit shl 4) - $80); 573 Inc(rs[3], (snd[3].Bit shl 4) - $80);
558 end; 574 end;
559 if not snd[4].channelOFF then 575 if not snd[4].channelOFF then
560 begin 576 begin
@@ -571,20 +587,30 @@ begin
571 end; 587 end;
572 if (m_iram[$FF25] and 8) > 0 then 588 if (m_iram[$FF25] and 8) > 0 then
573 if snd[4].Bit > 0 then 589 if snd[4].Bit > 0 then
574 Inc(l, vol[snd[4].Vol]) 590 Inc(ls[4], vol[snd[4].Vol])
575 else 591 else
576 Dec(l, vol[snd[4].Vol]); 592 Dec(ls[4], vol[snd[4].Vol]);
577 if (m_iram[$FF25] and $80) > 0 then 593 if (m_iram[$FF25] and $80) > 0 then
578 if snd[4].Bit > 0 then 594 if snd[4].Bit > 0 then
579 Inc(r, vol[snd[4].Vol]) 595 Inc(rs[4], vol[snd[4].Vol])
580 else 596 else
581 Dec(r, vol[snd[4].Vol]); 597 Dec(rs[4], vol[snd[4].Vol]);
582 end; 598 end;
583 599
584 SoundOutBits(l, r, cycles); 600 for I := 1 to 4 do begin
601 SampleBuffers[I].BufferL[SampleBuffers[I].Cursor] := ls[I];
602 SampleBuffers[I].BufferR[SampleBuffers[I].Cursor] := rs[I];
603 SampleBuffers[I].Cursor := (SampleBuffers[I].Cursor + 1) mod SAMPLE_BUFFER_SIZE;
604 end;
585 605
586 l := 0; 606 l := ls[1] + ls[2] + ls[3] + ls[4];
587 r := 0 607 r := rs[1] + rs[2] + rs[3] + rs[4];
608
609 SampleBuffers[0].BufferL[SampleBuffers[0].Cursor] := l;
610 SampleBuffers[0].BufferR[SampleBuffers[0].Cursor] := r;
611 SampleBuffers[0].Cursor := (SampleBuffers[0].Cursor + 1) mod SAMPLE_BUFFER_SIZE;
612
613 SoundOutBits(l, r, cycles);
588 end; 614 end;
589 615
590 procedure SoundSetCycles(n: integer); 616 procedure SoundSetCycles(n: integer);
Modifiedconstants.pas +3−1
@@ -5,7 +5,7 @@ unit Constants;
5 interface 5 interface
6 6
7 uses 7 uses
8 fgl; 8 fgl, LMessages;
9 9
10 type 10 type
11 TNoteMap = specialize TFPGMap<Integer, String>; 11 TNoteMap = specialize TFPGMap<Integer, String>;
@@ -14,6 +14,8 @@ type
14 TNoteToFreqMap = specialize TFPGMap<Integer, Integer>; 14 TNoteToFreqMap = specialize TFPGMap<Integer, Integer>;
15 15
16 const 16 const
17 LM_FD = LM_USER + 0;
18
17 SYM_ROW = 'row'; 19 SYM_ROW = 'row';
18 SYM_CURRENT_ORDER = 'current_order'; 20 SYM_CURRENT_ORDER = 'current_order';
19 SYM_TICKS_PER_ROW = 'ticks_per_row'; 21 SYM_TICKS_PER_ROW = 'ticks_per_row';
Modifiedemulationthread.pas +9−1
@@ -13,13 +13,14 @@ type
13 TEmulationThread = class(TThread) 13 TEmulationThread = class(TThread)
14 protected 14 protected
15 procedure Execute; override; 15 procedure Execute; override;
16 procedure OnFD;
16 public 17 public
17 Constructor Create(ROM: String); 18 Constructor Create(ROM: String);
18 end; 19 end;
19 20
20 implementation 21 implementation
21 22
22 uses sound, mainloop, vars, machine; 23 uses sound, mainloop, vars, machine, LCLIntf, constants, Tracker;
23 24
24 var 25 var
25 ET: TEpikTimer; 26 ET: TEpikTimer;
@@ -61,6 +62,11 @@ begin
61 until Terminated; 62 until Terminated;
62 end; 63 end;
63 64
65 procedure TEmulationThread.OnFD;
66 begin
67 PostMessage(frmTracker.Handle, LM_FD, 0, 0);
68 end;
69
64 constructor TEmulationThread.Create(ROM: String); 70 constructor TEmulationThread.Create(ROM: String);
65 begin 71 begin
66 inherited Create(True); 72 inherited Create(True);
@@ -68,6 +74,8 @@ begin
68 ResetSound; 74 ResetSound;
69 enablesound; 75 enablesound;
70 76
77 FDCallback := OnFD;
78
71 load(ROM); 79 load(ROM);
72 end; 80 end;
73 81
Modifiedhugedatatypes.pas +5−5
@@ -10,8 +10,8 @@ uses
10 type 10 type
11 Nibble = $0..$F; 11 Nibble = $0..$F;
12 12
13 TInstrumentBank = array[1..15] of TInstrument; 13 TInstrumentBank = packed array[1..15] of TInstrument;
14 TWaveBank = array[0..15] of TWave; 14 TWaveBank = packed array[0..15] of TWave;
15 15
16 TEffectParams = bitpacked record 16 TEffectParams = bitpacked record
17 case Boolean of 17 case Boolean of
@@ -19,18 +19,18 @@ type
19 False: (Value: Byte); 19 False: (Value: Byte);
20 end; 20 end;
21 21
22 TCell = record 22 TCell = packed record
23 Note: Integer; 23 Note: Integer;
24 Instrument: Integer; 24 Instrument: Integer;
25 EffectCode: Integer; 25 EffectCode: Integer;
26 EffectParams: TEffectParams; 26 EffectParams: TEffectParams;
27 end; 27 end;
28 28
29 TPattern = array[0..63] of TCell; 29 TPattern = packed array[0..63] of TCell;
30 PPattern = ^TPattern; 30 PPattern = ^TPattern;
31 31
32 TPatternMap = specialize TFPGMap<Integer, PPattern>; 32 TPatternMap = specialize TFPGMap<Integer, PPattern>;
33 TOrderMatrix = array[0..3] of array of Integer; 33 TOrderMatrix = packed array[0..3] of array of Integer;
34 34
35 TCellPart = ( 35 TCellPart = (
36 cpNote = 0, 36 cpNote = 0,
Modifiedinstruments.pas +3−3
@@ -15,10 +15,10 @@ type
15 TEnvelopeVolume = 0..63; 15 TEnvelopeVolume = 0..63;
16 TEnvelopeSweepAmount = 0..7; 16 TEnvelopeSweepAmount = 0..7;
17 17
18 TInstrument = record 18 TInstrument = packed record
19 Type_: TInstrumentType; 19 Type_: TInstrumentType;
20 20
21 Name: String; 21 Name: ShortString;
22 Length: Integer; 22 Length: Integer;
23 // Highmask 23 // Highmask
24 LengthEnabled: Boolean; 24 LengthEnabled: Boolean;
@@ -52,7 +52,7 @@ type
52 52
53 TAsmInstrument = array[0..3] of Byte; 53 TAsmInstrument = array[0..3] of Byte;
54 54
55 TRegisters = record 55 TRegisters = record
56 case Type_: TInstrumentType of 56 case Type_: TInstrumentType of
57 Square: (NR10, NR11, NR12, NR13, NR14: Byte); 57 Square: (NR10, NR11, NR12, NR13, NR14: Byte);
58 Wave: (NR30, NR31, NR32, NR33, NR34: Byte); 58 Wave: (NR30, NR31, NR32, NR33, NR34: Byte);
Modifiedsong.pas +1−1
@@ -9,7 +9,7 @@ uses Classes, HugeDatatypes;
9 type 9 type
10 { TSong } 10 { TSong }
11 11
12 TSong = record 12 TSong = packed record
13 Name: ShortString; 13 Name: ShortString;
14 Artist: ShortString; 14 Artist: ShortString;
15 Comment: ShortString; 15 Comment: ShortString;
Modifiedtracker.lfm +22−63
@@ -1,13 +1,14 @@
1 object frmTracker: TfrmTracker 1 object frmTracker: TfrmTracker
2 Left = 801 2 Left = 793
3 Height = 1376 3 Height = 1376
4 Top = 186 4 Top = 197
5 Width = 2212 5 Width = 2212
6 Caption = 'hUGETracker' 6 Caption = 'hUGETracker'
7 ClientHeight = 1342 7 ClientHeight = 1342
8 ClientWidth = 2212 8 ClientWidth = 2212
9 DesignTimePPI = 168 9 DesignTimePPI = 168
10 Menu = MainMenu1 10 Menu = MainMenu1
11 OnClose = FormClose
11 OnCreate = FormCreate 12 OnCreate = FormCreate
12 OnKeyDown = FormKeyDown 13 OnKeyDown = FormKeyDown
13 OnKeyUp = FormKeyUp 14 OnKeyUp = FormKeyUp
@@ -53,10 +54,10 @@ object frmTracker: TfrmTracker
53 Height = 946 54 Height = 946
54 Top = 0 55 Top = 0
55 Width = 1865 56 Width = 1865
56 ActivePage = GeneralTabSheet 57 ActivePage = InstrumentTabSheet
57 Align = alClient 58 Align = alClient
58 ParentFont = False 59 ParentFont = False
59 TabIndex = 0 60 TabIndex = 2
60 TabOrder = 0 61 TabOrder = 0
61 object GeneralTabSheet: TTabSheet 62 object GeneralTabSheet: TTabSheet
62 Caption = 'General' 63 Caption = 'General'
@@ -127,7 +128,7 @@ object frmTracker: TfrmTracker
127 Top = 128 128 Top = 128
128 Width = 88 129 Width = 88
129 MaxValue = 20 130 MaxValue = 20
130 MinValue = 7 131 MinValue = 1
131 OnChange = TicksPerRowSpinEditChange 132 OnChange = TicksPerRowSpinEditChange
132 ParentFont = False 133 ParentFont = False
133 TabOrder = 2 134 TabOrder = 2
@@ -1784,8 +1785,8 @@ object frmTracker: TfrmTracker
1784 PeakHoldTime = 0 1785 PeakHoldTime = 0
1785 Position = 0 1786 Position = 0
1786 SingleLED = False 1787 SingleLED = False
1787 Section2Value = 70 1788 Section2Value = 60
1788 Section3Value = 90 1789 Section3Value = 80
1789 end 1790 end
1790 object LEDMeter2: TLEDMeter 1791 object LEDMeter2: TLEDMeter
1791 AnchorSideRight.Side = asrBottom 1792 AnchorSideRight.Side = asrBottom
@@ -1808,56 +1809,8 @@ object frmTracker: TfrmTracker
1808 PeakHoldTime = 0 1809 PeakHoldTime = 0
1809 Position = 0 1810 Position = 0
1810 SingleLED = False 1811 SingleLED = False
1811 Section2Value = 70 1812 Section2Value = 60
1812 Section3Value = 90 1813 Section3Value = 80
1813 end
1814 object LEDMeter3: TLEDMeter
1815 AnchorSideRight.Side = asrBottom
1816 Left = 1256
1817 Height = 312
1818 Top = 0
1819 Width = 88
1820 Anchors = [akTop, akRight]
1821 BevelStyle = bvLowered
1822 Colors.Border = clBlack
1823 Colors.Section1 = clLime
1824 Colors.Section2 = clYellow
1825 Colors.Section3 = clRed
1826 Direction = mdUp
1827 FallbackDelay = 0
1828 LEDContrast = 9
1829 Max = 100
1830 Min = 0
1831 NumDigits = 50
1832 PeakHoldTime = 0
1833 Position = 0
1834 SingleLED = False
1835 Section2Value = 70
1836 Section3Value = 90
1837 end
1838 object LEDMeter4: TLEDMeter
1839 AnchorSideRight.Side = asrBottom
1840 Left = 1168
1841 Height = 312
1842 Top = 0
1843 Width = 88
1844 Anchors = [akTop, akRight]
1845 BevelStyle = bvLowered
1846 Colors.Border = clBlack
1847 Colors.Section1 = clLime
1848 Colors.Section2 = clYellow
1849 Colors.Section3 = clRed
1850 Direction = mdUp
1851 FallbackDelay = 0
1852 LEDContrast = 9
1853 Max = 100
1854 Min = 0
1855 NumDigits = 50
1856 PeakHoldTime = 0
1857 Position = 0
1858 SingleLED = False
1859 Section2Value = 70
1860 Section3Value = 90
1861 end 1814 end
1862 end 1815 end
1863 object StatusBar1: TStatusBar 1816 object StatusBar1: TStatusBar
@@ -1955,13 +1908,13 @@ object frmTracker: TfrmTracker
1955 Caption = 'ToolButton7' 1908 Caption = 'ToolButton7'
1956 Style = tbsSeparator 1909 Style = tbsSeparator
1957 end 1910 end
1958 object SpinEdit1: TSpinEdit 1911 object OctaveSpinEdit: TSpinEdit
1959 Left = 589 1912 Left = 589
1960 Height = 38 1913 Height = 38
1961 Top = 0 1914 Top = 0
1962 Width = 158 1915 Width = 158
1963 MaxValue = 5 1916 MaxValue = 5
1964 OnChange = SpinEdit1Change 1917 OnChange = OctaveSpinEditChange
1965 TabOrder = 0 1918 TabOrder = 0
1966 end 1919 end
1967 object ToolButton9: TToolButton 1920 object ToolButton9: TToolButton
@@ -1987,7 +1940,7 @@ object frmTracker: TfrmTracker
1987 Caption = ' Instrument ' 1940 Caption = ' Instrument '
1988 ParentColor = False 1941 ParentColor = False
1989 end 1942 end
1990 object ComboBox1: TComboBox 1943 object InstrumentComboBox: TComboBox
1991 Left = 872 1944 Left = 872
1992 Height = 38 1945 Height = 38
1993 Top = 0 1946 Top = 0
@@ -2012,7 +1965,7 @@ object frmTracker: TfrmTracker
2012 '14:' 1965 '14:'
2013 '15:' 1966 '15:'
2014 ) 1967 )
2015 OnChange = ComboBox1Change 1968 OnChange = InstrumentComboBoxChange
2016 Style = csDropDownList 1969 Style = csDropDownList
2017 TabOrder = 1 1970 TabOrder = 1
2018 Text = '(no instrument)' 1971 Text = '(no instrument)'
@@ -2025,13 +1978,13 @@ object frmTracker: TfrmTracker
2025 Caption = ' Step ' 1978 Caption = ' Step '
2026 ParentColor = False 1979 ParentColor = False
2027 end 1980 end
2028 object SpinEdit2: TSpinEdit 1981 object StepSpinEdit: TSpinEdit
2029 Left = 1311 1982 Left = 1311
2030 Height = 38 1983 Height = 38
2031 Top = 0 1984 Top = 0
2032 Width = 88 1985 Width = 88
2033 MaxValue = 63 1986 MaxValue = 63
2034 OnChange = SpinEdit2Change 1987 OnChange = StepSpinEditChange
2035 TabOrder = 2 1988 TabOrder = 2
2036 end 1989 end
2037 object ToolButton3: TToolButton 1990 object ToolButton3: TToolButton
@@ -4973,4 +4926,10 @@ object frmTracker: TfrmTracker
4973 0000000000000000000000000000 4926 0000000000000000000000000000
4974 } 4927 }
4975 end 4928 end
4929 object Timer1: TTimer
4930 Interval = 10
4931 OnTimer = Timer1Timer
4932 left = 504
4933 top = 80
4934 end
4976 end 4935 end
Modifiedtracker.pas +90−24
@@ -16,7 +16,7 @@ type
16 { TfrmTracker } 16 { TfrmTracker }
17 17
18 TfrmTracker = class(TForm) 18 TfrmTracker = class(TForm)
19 ComboBox1: TComboBox; 19 InstrumentComboBox: TComboBox;
20 CutAction: TAction; 20 CutAction: TAction;
21 ImageList2: TImageList; 21 ImageList2: TImageList;
22 Label22: TLabel; 22 Label22: TLabel;
@@ -24,8 +24,6 @@ type
24 Label24: TLabel; 24 Label24: TLabel;
25 LEDMeter1: TLEDMeter; 25 LEDMeter1: TLEDMeter;
26 LEDMeter2: TLEDMeter; 26 LEDMeter2: TLEDMeter;
27 LEDMeter3: TLEDMeter;
28 LEDMeter4: TLEDMeter;
29 OrderEditStringGrid: TStringGrid; 27 OrderEditStringGrid: TStringGrid;
30 EditCut1: TEditCut; 28 EditCut1: TEditCut;
31 HeaderControl1: THeaderControl; 29 HeaderControl1: THeaderControl;
@@ -34,8 +32,9 @@ type
34 MenuItem19: TMenuItem; 32 MenuItem19: TMenuItem;
35 MenuItem20: TMenuItem; 33 MenuItem20: TMenuItem;
36 Duty1Visualizer: TPaintBox; 34 Duty1Visualizer: TPaintBox;
37 SpinEdit1: TSpinEdit; 35 OctaveSpinEdit: TSpinEdit;
38 SpinEdit2: TSpinEdit; 36 StepSpinEdit: TSpinEdit;
37 Timer1: TTimer;
39 ToolButton3: TToolButton; 38 ToolButton3: TToolButton;
40 ToolButton9: TToolButton; 39 ToolButton9: TToolButton;
41 WaveVisualizer: TPaintBox; 40 WaveVisualizer: TPaintBox;
@@ -165,13 +164,14 @@ type
165 DivRatioSpinner: TECSpinPosition; 164 DivRatioSpinner: TECSpinPosition;
166 TreeView1: TTreeView; 165 TreeView1: TTreeView;
167 TrackerGrid: TTrackerGrid; 166 TrackerGrid: TTrackerGrid;
168 procedure ComboBox1Change(Sender: TObject); 167 procedure InstrumentComboBoxChange(Sender: TObject);
169 procedure CopyActionExecute(Sender: TObject); 168 procedure CopyActionExecute(Sender: TObject);
170 procedure CutActionExecute(Sender: TObject); 169 procedure CutActionExecute(Sender: TObject);
171 procedure Duty1VisualizerPaint(Sender: TObject); 170 procedure Duty1VisualizerPaint(Sender: TObject);
172 procedure Duty2VisualizerPaint(Sender: TObject); 171 procedure Duty2VisualizerPaint(Sender: TObject);
173 procedure FileOpen1Accept(Sender: TObject); 172 procedure FileOpen1Accept(Sender: TObject);
174 procedure FileSaveAs1Accept(Sender: TObject); 173 procedure FileSaveAs1Accept(Sender: TObject);
174 procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
175 procedure HeaderControl1MouseDown(Sender: TObject; Button: TMouseButton; 175 procedure HeaderControl1MouseDown(Sender: TObject; Button: TMouseButton;
176 Shift: TShiftState; X, Y: Integer); 176 Shift: TShiftState; X, Y: Integer);
177 procedure HeaderControl1SectionClick(HeaderControl: TCustomHeaderControl; 177 procedure HeaderControl1SectionClick(HeaderControl: TCustomHeaderControl;
@@ -218,9 +218,10 @@ type
218 Shift: TShiftState); 218 Shift: TShiftState);
219 procedure PanicToolButtonClick(Sender: TObject); 219 procedure PanicToolButtonClick(Sender: TObject);
220 procedure PasteActionExecute(Sender: TObject); 220 procedure PasteActionExecute(Sender: TObject);
221 procedure SpinEdit1Change(Sender: TObject); 221 procedure OctaveSpinEditChange(Sender: TObject);
222 procedure SpinEdit2Change(Sender: TObject); 222 procedure StepSpinEditChange(Sender: TObject);
223 procedure TicksPerRowSpinEditChange(Sender: TObject); 223 procedure TicksPerRowSpinEditChange(Sender: TObject);
224 procedure Timer1Timer(Sender: TObject);
224 procedure ToolButton2Click(Sender: TObject); 225 procedure ToolButton2Click(Sender: TObject);
225 procedure ToolButton3Click(Sender: TObject); 226 procedure ToolButton3Click(Sender: TObject);
226 procedure ToolButton4Click(Sender: TObject); 227 procedure ToolButton4Click(Sender: TObject);
@@ -278,7 +279,7 @@ type
278 procedure WordPokeSymbol(Symbol: String; Value: Word); 279 procedure WordPokeSymbol(Symbol: String; Value: Word);
279 function PeekSymbol(Symbol: String): Integer; 280 function PeekSymbol(Symbol: String): Integer;
280 procedure PokeSymbol(Symbol: String; Value: Byte); 281 procedure PokeSymbol(Symbol: String; Value: Byte);
281 procedure OnFD; 282 procedure OnFD(var msg: TLMessage); message LM_FD;
282 283
283 procedure RecreateTrackerGrid; 284 procedure RecreateTrackerGrid;
284 procedure UpdateUIAfterLoad; 285 procedure UpdateUIAfterLoad;
@@ -301,6 +302,8 @@ implementation
301 { TfrmTracker } 302 { TfrmTracker }
302 303
303 procedure TfrmTracker.UpdateUIAfterLoad; 304 procedure TfrmTracker.UpdateUIAfterLoad;
305 var
306 I: Integer;
304 begin 307 begin
305 LoadingFile := True; // HACK!!!!! 308 LoadingFile := True; // HACK!!!!!
306 LoadInstrument(1); 309 LoadInstrument(1);
@@ -315,6 +318,9 @@ begin
315 RecreateTrackerGrid; 318 RecreateTrackerGrid;
316 CopyOrderMatrixToOrderGrid; 319 CopyOrderMatrixToOrderGrid;
317 320
321 for I := Low(Song.Instruments) to High(song.Instruments) do
322 InstrumentComboBox.Items[I] := IntToStr(I)+': '+Song.Instruments[I].Name;
323
318 LoadingFile := False; // HACK!!!! 324 LoadingFile := False; // HACK!!!!
319 325
320 OrderEditStringGrid.Row := 1; 326 OrderEditStringGrid.Row := 1;
@@ -357,8 +363,34 @@ begin
357 end; 363 end;
358 364
359 procedure TfrmTracker.DrawVizualizer(PB: TPaintBox; Channel: Integer); 365 procedure TfrmTracker.DrawVizualizer(PB: TPaintBox; Channel: Integer);
366 var
367 I, J, X: Integer;
360 begin 368 begin
369 with PB.Canvas do begin
370 MoveTo(0, PB.Height div 2);
371
372 Brush.Color := clBlack;
373 Clear;
374
375 Pen.Color := clGray;
376 Rectangle(0, 0, PB.Width, PB.Height);
361 377
378 Pen.Color := clLime;
379 Pen.Width := 2;
380
381 X := 0;
382 I := 0;
383 J := SampleBuffers[Channel].Cursor;
384 while I < SAMPLE_BUFFER_SIZE-1 do begin
385 LineTo(X, (PB.Height div 2) +
386 Trunc((SampleBuffers[Channel].BufferL[J]/512)*PB.Height) +
387 Trunc((SampleBuffers[Channel].BufferR[J]/512)*PB.Height));
388 J := (J+1) mod SAMPLE_BUFFER_SIZE;
389
390 X := Trunc((I/SAMPLE_BUFFER_SIZE)*PB.Width);
391 Inc(I, 2);
392 end;
393 end;
362 end; 394 end;
363 395
364 procedure TfrmTracker.PreviewInstrument(Freq: Integer; Instr: Integer); 396 procedure TfrmTracker.PreviewInstrument(Freq: Integer; Instr: Integer);
@@ -542,9 +574,9 @@ begin
542 EmulationThread.Start; 574 EmulationThread.Start;
543 end; 575 end;
544 576
545 procedure TfrmTracker.OnFD; 577 procedure TfrmTracker.OnFD(var Msg: TLMessage);
546 begin 578 begin
547 TrackerGrid.HighlightedRow:=PeekSymbol(SYM_ROW); 579 TrackerGrid.HighlightedRow := PeekSymbol(SYM_ROW);
548 OrderEditStringGrid.Row := (PeekSymbol(SYM_CURRENT_ORDER) div 2) + 1; 580 OrderEditStringGrid.Row := (PeekSymbol(SYM_CURRENT_ORDER) div 2) + 1;
549 end; 581 end;
550 582
@@ -562,7 +594,7 @@ begin
562 CI := CurrentInstrument; 594 CI := CurrentInstrument;
563 595
564 InstrumentNumberSpinner.Value := Instr; 596 InstrumentNumberSpinner.Value := Instr;
565 InstrumentNameEdit.Text := CI^.Name; 597 //InstrumentNameEdit.Text := CI^.Name;
566 LengthEnabledCheckbox.Checked := CI^.LengthEnabled; 598 LengthEnabledCheckbox.Checked := CI^.LengthEnabled;
567 LengthSpinner.Position := CI^.Length; 599 LengthSpinner.Position := CI^.Length;
568 600
@@ -656,7 +688,7 @@ end;
656 688
657 procedure TfrmTracker.WaveVisualizerPaint(Sender: TObject); 689 procedure TfrmTracker.WaveVisualizerPaint(Sender: TObject);
658 begin 690 begin
659 691 DrawVizualizer(WaveVisualizer, 3);
660 end; 692 end;
661 693
662 procedure TfrmTracker.WaveVolumeComboboxChange(Sender: TObject); 694 procedure TfrmTracker.WaveVolumeComboboxChange(Sender: TObject);
@@ -761,8 +793,6 @@ begin
761 for Section in HeaderControl1.Sections do 793 for Section in HeaderControl1.Sections do
762 (Section as THeaderSection).Width := TrackerGrid.ColumnWidth; 794 (Section as THeaderSection).Width := TrackerGrid.ColumnWidth;
763 795
764 FDCallback := @Self.OnFD;
765
766 for I := Low(Song.Instruments) to High(Song.Instruments) do 796 for I := Low(Song.Instruments) to High(Song.Instruments) do
767 with Song.Instruments[I] do begin 797 with Song.Instruments[I] do begin
768 Type_ := Square; 798 Type_ := Square;
@@ -884,6 +914,11 @@ begin
884 end; 914 end;
885 end; 915 end;
886 916
917 procedure TfrmTracker.FormClose(Sender: TObject; var CloseAction: TCloseAction);
918 begin
919
920 end;
921
887 procedure TfrmTracker.FileOpen1Accept(Sender: TObject); 922 procedure TfrmTracker.FileOpen1Accept(Sender: TObject);
888 var 923 var
889 Stream: TStream; 924 Stream: TStream;
@@ -945,12 +980,12 @@ end;
945 980
946 procedure TfrmTracker.Duty1VisualizerPaint(Sender: TObject); 981 procedure TfrmTracker.Duty1VisualizerPaint(Sender: TObject);
947 begin 982 begin
948 983 DrawVizualizer(Duty1Visualizer, 1);
949 end; 984 end;
950 985
951 procedure TfrmTracker.Duty2VisualizerPaint(Sender: TObject); 986 procedure TfrmTracker.Duty2VisualizerPaint(Sender: TObject);
952 begin 987 begin
953 988 DrawVizualizer(Duty2Visualizer, 2);
954 end; 989 end;
955 990
956 procedure TfrmTracker.CopyActionExecute(Sender: TObject); 991 procedure TfrmTracker.CopyActionExecute(Sender: TObject);
@@ -958,9 +993,9 @@ begin
958 PostMessage(Screen.ActiveControl.Handle, LM_COPY, 0, 0); 993 PostMessage(Screen.ActiveControl.Handle, LM_COPY, 0, 0);
959 end; 994 end;
960 995
961 procedure TfrmTracker.ComboBox1Change(Sender: TObject); 996 procedure TfrmTracker.InstrumentComboBoxChange(Sender: TObject);
962 begin 997 begin
963 TrackerGrid.SelectedInstrument := ComboBox1.ItemIndex; 998 TrackerGrid.SelectedInstrument := InstrumentComboBox.ItemIndex;
964 end; 999 end;
965 1000
966 procedure TfrmTracker.PasteActionExecute(Sender: TObject); 1001 procedure TfrmTracker.PasteActionExecute(Sender: TObject);
@@ -968,14 +1003,14 @@ begin
968 PostMessage(Screen.ActiveControl.Handle, LM_PASTE, 0, 0); 1003 PostMessage(Screen.ActiveControl.Handle, LM_PASTE, 0, 0);
969 end; 1004 end;
970 1005
971 procedure TfrmTracker.SpinEdit1Change(Sender: TObject); 1006 procedure TfrmTracker.OctaveSpinEditChange(Sender: TObject);
972 begin 1007 begin
973 TrackerGrid.SelectedOctave := SpinEdit1.Value; 1008 TrackerGrid.SelectedOctave := OctaveSpinEdit.Value;
974 end; 1009 end;
975 1010
976 procedure TfrmTracker.SpinEdit2Change(Sender: TObject); 1011 procedure TfrmTracker.StepSpinEditChange(Sender: TObject);
977 begin 1012 begin
978 TrackerGrid.Step := SpinEdit2.Value; 1013 TrackerGrid.Step := StepSpinEdit.Value;
979 end; 1014 end;
980 1015
981 procedure TfrmTracker.DivRatioSpinnerChange(Sender: TObject); 1016 procedure TfrmTracker.DivRatioSpinnerChange(Sender: TObject);
@@ -1015,6 +1050,8 @@ end;
1015 procedure TfrmTracker.InstrumentNameEditChange(Sender: TObject); 1050 procedure TfrmTracker.InstrumentNameEditChange(Sender: TObject);
1016 begin 1051 begin
1017 CurrentInstrument^.Name := InstrumentNameEdit.Text; 1052 CurrentInstrument^.Name := InstrumentNameEdit.Text;
1053 InstrumentComboBox.Items[InstrumentNumberSpinner.Value] :=
1054 IntToStr(InstrumentNumberSpinner.Value) + ': ' + InstrumentNameEdit.Text;
1018 end; 1055 end;
1019 1056
1020 procedure TfrmTracker.InstrumentNumberSpinnerChange(Sender: TObject); 1057 procedure TfrmTracker.InstrumentNumberSpinnerChange(Sender: TObject);
@@ -1084,7 +1121,7 @@ end;
1084 1121
1085 procedure TfrmTracker.NoiseVisualizerPaint(Sender: TObject); 1122 procedure TfrmTracker.NoiseVisualizerPaint(Sender: TObject);
1086 begin 1123 begin
1087 1124 DrawVizualizer(NoiseVisualizer, 4);
1088 end; 1125 end;
1089 1126
1090 procedure TfrmTracker.OrderEditStringGridAfterSelection(Sender: TObject; aCol, 1127 procedure TfrmTracker.OrderEditStringGridAfterSelection(Sender: TObject; aCol,
@@ -1176,6 +1213,35 @@ begin
1176 Song.TicksPerRow := TicksPerRowSpinEdit.Value; 1213 Song.TicksPerRow := TicksPerRowSpinEdit.Value;
1177 end; 1214 end;
1178 1215
1216 procedure TfrmTracker.Timer1Timer(Sender: TObject);
1217 var
1218 Max1, Max2: Integer;
1219 I: Integer;
1220 Samp: Integer;
1221 begin
1222 Max1 := -1;
1223 Max2 := -1;
1224 for I := 0 to SAMPLE_BUFFER_SIZE do begin
1225 Samp := Abs(SampleBuffers[0].BufferL[I] div 2);
1226 if Samp > Max1 then Max1 := Samp;
1227 Samp := Abs(SampleBuffers[0].BufferR[I] div 2);
1228 if Samp > Max2 then Max2 := Samp;
1229 end;
1230
1231 Duty1Visualizer.Invalidate;
1232 Duty2Visualizer.Invalidate;
1233 NoiseVisualizer.Invalidate;
1234 WaveVisualizer.Invalidate;
1235
1236 LEDMeter1.Position := LEDMeter1.Position-2;
1237 LEDMeter2.Position := LEDMeter2.Position-2;
1238
1239 Max1 := Trunc((Max1/512)*100);
1240 Max2 := Trunc((Max2/512)*100);
1241 if Max1 > LEDMeter1.Position then LEDMeter1.Position := Max1;
1242 if Max2 > LEDMeter2.Position then LEDMeter2.Position := Max2;
1243 end;
1244
1179 procedure TfrmTracker.ToolButton2Click(Sender: TObject); 1245 procedure TfrmTracker.ToolButton2Click(Sender: TObject);
1180 begin 1246 begin
1181 if Playing then ResetEmulationThread; 1247 if Playing then ResetEmulationThread;
Modifiedtrackergrid.pas +20−1
@@ -786,9 +786,28 @@ begin
786 end; 786 end;
787 787
788 procedure TTrackerGrid.SetHighlightedRow(Row: Integer); 788 procedure TTrackerGrid.SetHighlightedRow(Row: Integer);
789 var
790 R: TRect;
791 OldRow: Integer;
789 begin 792 begin
793 OldRow := FHighlightedRow;
790 FHighlightedRow := Row; 794 FHighlightedRow := Row;
791 if FHighlightedRow >= 0 then Invalidate; 795
796 // An optimization to redraw the pattern faster. This function gets called
797 // a lot (every time the FD callback happens) so it needs to be fast. It can
798 // sort of lag out the main thread if it just does a full invalidate.
799
800 RenderRow(OldRow);
801 RenderRow(Row);
802
803 R.Left:=0;
804 R.Width:=ColumnWidth*4;
805 R.Height:=RowHeight*2;
806
807 R.Top:=(Row-1)*RowHeight;
808 InvalidateRect(Self.Handle, @R, True);
809 R.Top:=(OldRow-1)*RowHeight;
810 InvalidateRect(Self.Handle, @R, True);
792 end; 811 end;
793 812
794 procedure TTrackerGrid.SetSelectionGridRect(R: TRect); 813 procedure TTrackerGrid.SetSelectionGridRect(R: TRect);
Modifiedwaves.pas +2−2
@@ -8,8 +8,8 @@ uses
8 Classes, SysUtils; 8 Classes, SysUtils;
9 9
10 type 10 type
11 TWave = array[0..32] of Byte; 11 TWave = packed array[0..32] of Byte;
12 T4bitWave = array[0..15] of Byte; 12 T4bitWave = packed array[0..15] of Byte;
13 13
14 implementation 14 implementation
15 15