aboutsummaryrefslogtreecommitdiffstats
path: root/Game/Code/Screens/UScreenOptionsRecord.pas
diff options
context:
space:
mode:
authortobigun <tobigun@b956fd51-792f-4845-bead-9b4dfca2ff2c>2008-03-03 03:16:57 +0000
committertobigun <tobigun@b956fd51-792f-4845-bead-9b4dfca2ff2c>2008-03-03 03:16:57 +0000
commit6880109d9d38abfed6dececf863fdb7430fbb837 (patch)
tree4c04d9645071121185e69ebca50143b9b33cb46e /Game/Code/Screens/UScreenOptionsRecord.pas
parenta022cbec1cb1245ab81bf008dd8835a860f38999 (diff)
downloadusdx-6880109d9d38abfed6dececf863fdb7430fbb837.tar.gz
usdx-6880109d9d38abfed6dececf863fdb7430fbb837.tar.xz
usdx-6880109d9d38abfed6dececf863fdb7430fbb837.zip
- Input now supports multiple SampleRates (not fixed to 44100Hz anymore)
- Input is not restricted to stereo input-devices anymore (mono and multi-channel devices work too) - Some improvements on the input-device detection - Retrieves native capture sample-rate on Vista and MacOSX with BASS (maybe this solves some problems with wrong sample-rates) - Capture-volume preview: a little modification to jay's approach. Now there are volume bars and pitch-displays. It needs some fine-tuning, maybe mog can do this if he likes. - Some indentation/clean-up/translations git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/trunk@900 b956fd51-792f-4845-bead-9b4dfca2ff2c
Diffstat (limited to '')
-rw-r--r--Game/Code/Screens/UScreenOptionsRecord.pas492
1 files changed, 386 insertions, 106 deletions
diff --git a/Game/Code/Screens/UScreenOptionsRecord.pas b/Game/Code/Screens/UScreenOptionsRecord.pas
index b6fb588e..3da29f43 100644
--- a/Game/Code/Screens/UScreenOptionsRecord.pas
+++ b/Game/Code/Screens/UScreenOptionsRecord.pas
@@ -2,36 +2,75 @@ unit UScreenOptionsRecord;
interface
+{$IFDEF FPC}
+ {$MODE Delphi}
+{$ENDIF}
+
{$I switches.inc}
uses
- UMenu, SDL, UDisplay, UMusic, UFiles, UIni, UThemes;
+ UThemes,
+ UMusic,
+ URecord,
+ UMenu;
type
TScreenOptionsRecord = class(TMenu)
private
- Card: integer; // current input device
+ // max. count of input-channels determined for all devices
+ MaxChannelCount: integer;
+
+ // current input device
+ CurrentDeviceIndex: integer;
+ PreviewDeviceIndex: integer;
+
+ // string arrays for select-slide options
+ InputSourceNames: array of string;
+ InputDeviceNames: array of string;
+
+ // dynamic generated themes for channel select-sliders
+ SelectSlideChannelTheme: array of TThemeSelectSlide;
+
+ // indices for widget-updates
+ SelectSlideInputID: integer;
+ SelectSlideChannelID: array of integer;
+ TextPitchID: array of integer;
- SelectSlideInput: integer;
- SelectSlideChannelL: integer;
- SelectSlideChannelR: integer;
+ // interaction IDs
+ ExitButtonIID: integer;
+
+ // dummy data for non-available channels
+ ChannelToPlayerMapDummy: integer;
+
+ // preview channel-buffers
+ PreviewChannel: array of TCaptureBuffer;
+
+ procedure StartPreview;
+ procedure StopPreview;
+ procedure UpdateCard;
public
constructor Create; override;
function Draw: boolean; override;
function ParseInput(PressedKey: Cardinal; ScanCode: byte; PressedDown: Boolean): Boolean; override;
procedure onShow; override;
procedure onHide; override;
- procedure UpdateCard;
end;
implementation
-uses SysUtils,
- UGraphic,
- URecord,
- UDraw,
- UMain,
- ULog;
+uses
+ SysUtils,
+ SDL,
+ OpenGL12,
+ UGraphic,
+ UDraw,
+ UMain,
+ UMenuSelectSlide,
+ UMenuText,
+ UFiles,
+ UDisplay,
+ UIni,
+ ULog;
function TScreenOptionsRecord.ParseInput(PressedKey: Cardinal; ScanCode: byte; PressedDown: Boolean): Boolean;
begin
@@ -52,7 +91,8 @@ begin
end;
SDLK_RETURN:
begin
- if SelInteraction = 5 then begin
+ if (SelInteraction = ExitButtonIID) then
+ begin
Ini.Save;
AudioPlayback.PlaySound(SoundLib.Back);
FadeTo(@ScreenOptions);
@@ -64,21 +104,21 @@ begin
InteractPrev;
SDLK_RIGHT:
begin
- if (SelInteraction >= 0) and (SelInteraction <= 4) then begin
+ if (SelInteraction >= 0) and (SelInteraction < ExitButtonIID) then
+ begin
AudioPlayback.PlaySound(SoundLib.Option);
InteractInc;
end;
-// if SelInteraction = 0 then UpdateCard;
UpdateCard;
end;
SDLK_LEFT:
begin
- if (SelInteraction >= 0) and (SelInteraction <= 4) then begin
+ if (SelInteraction >= 0) and (SelInteraction < ExitButtonIID) then
+ begin
AudioPlayback.PlaySound(SoundLib.Option);
InteractDec;
end;
- UpdateCard;
-// if SelInteraction = 0 then UpdateCard;
+ UpdateCard;
end;
end;
end;
@@ -86,146 +126,386 @@ end;
constructor TScreenOptionsRecord.Create;
var
- SC: integer;
- SCI: integer;
+ DeviceIndex: integer;
+ SourceIndex: integer;
+ ChannelIndex: integer;
InputDevice: TAudioInputDevice;
InputDeviceCfg: PInputDeviceConfig;
+ ChannelTheme: ^TThemeSelectSlide;
+ ButtonTheme: TThemeButton;
begin
inherited Create;
- Card := 0;
-
LoadFromTheme(Theme.OptionsRecord);
- SetLength(ICard, Length(AudioInputProcessor.Device));
- for SC := 0 to High(AudioInputProcessor.Device) do
- ICard[SC] := AudioInputProcessor.Device[SC].Description;
+ // set CurrentDeviceIndex to a valid device
+ if (Length(AudioInputProcessor.Device) > 0) then
+ CurrentDeviceIndex := 0
+ else
+ CurrentDeviceIndex := -1;
- if (Card > High(AudioInputProcessor.Device)) then
- Card := 0;
+ PreviewDeviceIndex := -1;
+ // init sliders if at least one device was detected
if (Length(AudioInputProcessor.Device) > 0) then
begin
- InputDevice := AudioInputProcessor.Device[Card];
+ InputDevice := AudioInputProcessor.Device[CurrentDeviceIndex];
InputDeviceCfg := @Ini.InputDeviceConfig[InputDevice.CfgIndex];
-
- SetLength(IInput, Length(InputDevice.Source));
- for SCI := 0 to High(InputDevice.Source) do
- IInput[SCI] := InputDevice.Source[SCI].Name;
- AddSelectSlide(Theme.OptionsRecord.SelectSlideCard, Card, ICard);
+ // init device-selection slider
+ SetLength(InputDeviceNames, Length(AudioInputProcessor.Device));
+ for DeviceIndex := 0 to High(AudioInputProcessor.Device) do
+ begin
+ InputDeviceNames[DeviceIndex] := AudioInputProcessor.Device[DeviceIndex].Description;
+ end;
+ // add device-selection slider (InteractionID: 0)
+ AddSelectSlide(Theme.OptionsRecord.SelectSlideCard, CurrentDeviceIndex, InputDeviceNames);
+
+ // init source-selection slider
+ SetLength(InputSourceNames, Length(InputDevice.Source));
+ for SourceIndex := 0 to High(InputDevice.Source) do
+ begin
+ InputSourceNames[SourceIndex] := InputDevice.Source[SourceIndex].Name;
+ end;
+ // add source-selection slider (InteractionID: 1)
+ SelectSlideInputID := AddSelectSlide(Theme.OptionsRecord.SelectSlideInput,
+ InputDeviceCfg.Input, InputSourceNames);
+
+ // find max. channel count of all devices
+ MaxChannelCount := 0;
+ for DeviceIndex := 0 to High(AudioInputProcessor.Device) do
+ begin
+ if (AudioInputProcessor.Device[DeviceIndex].AudioFormat.Channels > MaxChannelCount) then
+ MaxChannelCount := AudioInputProcessor.Device[DeviceIndex].AudioFormat.Channels;
+ end;
- SelectSlideInput := AddSelectSlide(Theme.OptionsRecord.SelectSlideInput,
- InputDeviceCfg^.Input, IInput);
- SelectSlideChannelL := AddSelectSlide(Theme.OptionsRecord.SelectSlideChannelL,
- InputDeviceCfg^.ChannelToPlayerMap[0], IChannel);
- SelectSlideChannelR := AddSelectSlide(Theme.OptionsRecord.SelectSlideChannelR,
- InputDeviceCfg^.ChannelToPlayerMap[1], IChannel);
+ // init channel-to-player mapping sliders
+ SetLength(SelectSlideChannelID, MaxChannelCount);
+ SetLength(SelectSlideChannelTheme, MaxChannelCount);
+ SetLength(TextPitchID, MaxChannelCount);
+
+ for ChannelIndex := 0 to MaxChannelCount-1 do
+ begin
+ // copy reference slide
+ SelectSlideChannelTheme[ChannelIndex] :=
+ Theme.OptionsRecord.SelectSlideChannel;
+ // set current channel-theme
+ ChannelTheme := @SelectSlideChannelTheme[ChannelIndex];
+ // adjust vertical position
+ ChannelTheme.Y := ChannelTheme.Y + ChannelIndex * ChannelTheme.H;
+ // append channel index to name
+ ChannelTheme.Text := ChannelTheme.Text + IntToStr(ChannelIndex+1);
+
+ // add tone-pitch label
+ TextPitchID[ChannelIndex] := AddText(
+ ChannelTheme.X + ChannelTheme.W,
+ ChannelTheme.Y + ChannelTheme.H/2,
+ '-');
+
+ // show/hide widgets depending on whether the channel exists
+ if (ChannelIndex < Length(InputDeviceCfg.ChannelToPlayerMap)) then
+ begin
+ // current device has this channel
+
+ // add slider
+ SelectSlideChannelID[ChannelIndex] := AddSelectSlide(ChannelTheme^,
+ InputDeviceCfg.ChannelToPlayerMap[ChannelIndex], IChannel);
+ end
+ else
+ begin
+ // current device does not have that many channels
+
+ // add slider but hide it and assign a dummy variable to it
+ SelectSlideChannelID[ChannelIndex] := AddSelectSlide(ChannelTheme^,
+ ChannelToPlayerMapDummy, IChannel);
+ SelectsS[SelectSlideChannelID[ChannelIndex]].Visible := false;
+
+ // hide pitch label
+ Text[TextPitchID[ChannelIndex]].Visible := false;
+ end;
+ end;
- AddSelect(Theme.OptionsSound.SelectMicBoost, Ini.MicBoost, IMicBoost);
+ // TODO: move from sound-options to record-options (Themes must be changed first)
+ //AddSelect(Theme.OptionsSound.SelectMicBoost, Ini.MicBoost, IMicBoost);
end;
- AddButton(Theme.OptionsRecord.ButtonExit);
- if (Length(Button[0].Text)=0) then
+ // add Exit-button
+ ButtonTheme := Theme.OptionsRecord.ButtonExit;
+ ButtonTheme.Y := Theme.OptionsRecord.SelectSlideChannel.Y +
+ MaxChannelCount *
+ Theme.OptionsRecord.SelectSlideChannel.H;
+ AddButton(ButtonTheme);
+ if (Length(Button[0].Text) = 0) then
AddButtonText(14, 20, Theme.Options.Description[7]);
+ // store InteractionID
+ ExitButtonIID := MaxChannelCount + 2;
+ // set focus
Interaction := 0;
end;
+procedure TScreenOptionsRecord.UpdateCard;
+var
+ SourceIndex: integer;
+ InputDevice: TAudioInputDevice;
+ InputDeviceCfg: PInputDeviceConfig;
+ ChannelIndex: integer;
+begin
+ Log.LogStatus('Update input-device', 'TScreenOptionsRecord.UpdateCard') ;
+
+ StopPreview();
+
+ // set CurrentDeviceIndex to a valid device
+ if (CurrentDeviceIndex > High(AudioInputProcessor.Device)) then
+ CurrentDeviceIndex := 0;
+
+ // update sliders if at least one device was detected
+ if (Length(AudioInputProcessor.Device) > 0) then
+ begin
+ InputDevice := AudioInputProcessor.Device[CurrentDeviceIndex];
+ InputDeviceCfg := @Ini.InputDeviceConfig[InputDevice.CfgIndex];
+
+ // update source-selection slider
+ SetLength(InputSourceNames, Length(InputDevice.Source));
+ for SourceIndex := 0 to High(InputDevice.Source) do
+ begin
+ InputSourceNames[SourceIndex] := InputDevice.Source[SourceIndex].Name;
+ end;
+ UpdateSelectSlideOptions(Theme.OptionsRecord.SelectSlideInput, SelectSlideInputID,
+ InputSourceNames, InputDeviceCfg.Input);
+
+ // update channel-to-player mapping sliders
+ for ChannelIndex := 0 to MaxChannelCount-1 do
+ begin
+ // show/hide widgets depending on whether the channel exists
+ if (ChannelIndex < Length(InputDeviceCfg.ChannelToPlayerMap)) then
+ begin
+ // current device has this channel
+
+ // show slider
+ UpdateSelectSlideOptions(SelectSlideChannelTheme[ChannelIndex],
+ SelectSlideChannelID[ChannelIndex], IChannel,
+ InputDeviceCfg.ChannelToPlayerMap[ChannelIndex]);
+ SelectsS[SelectSlideChannelID[ChannelIndex]].Visible := true;
+
+ // show pitch label
+ Text[TextPitchID[ChannelIndex]].Visible := true;
+ end
+ else
+ begin
+ // current device does not have that many channels
+
+ // hide slider and assign a dummy variable to it
+ UpdateSelectSlideOptions(SelectSlideChannelTheme[ChannelIndex],
+ SelectSlideChannelID[ChannelIndex], IChannel,
+ ChannelToPlayerMapDummy);
+ SelectsS[SelectSlideChannelID[ChannelIndex]].Visible := false;
+
+ // hide pitch label
+ Text[TextPitchID[ChannelIndex]].Visible := false;
+ end;
+ end;
+ end;
+
+ StartPreview();
+end;
+
procedure TScreenOptionsRecord.onShow;
+var
+ ChannelIndex: integer;
begin
inherited;
Interaction := 0;
- writeln( 'AudioInput.CaptureStart') ;
- PlayersPlay := 2; // TODO : This needs fixing
- AudioInput.CaptureStart;
+ // create preview sound-buffers
+ SetLength(PreviewChannel, MaxChannelCount);
+ for ChannelIndex := 0 to High(PreviewChannel) do
+ PreviewChannel[ChannelIndex] := TCaptureBuffer.Create();
+ StartPreview();
end;
procedure TScreenOptionsRecord.onHide;
+var
+ ChannelIndex: integer;
begin
- AudioInput.CaptureStop;
+ StopPreview();
+
+ // free preview buffers
+ for ChannelIndex := 0 to High(PreviewChannel) do
+ PreviewChannel[ChannelIndex].Free;
+ SetLength(PreviewChannel, 0);
end;
-procedure TScreenOptionsRecord.UpdateCard;
+procedure TScreenOptionsRecord.StartPreview;
var
- SourceIndex: integer;
- InputDevice: TAudioInputDevice;
- InputDeviceCfg: PInputDeviceConfig;
+ ChannelIndex: integer;
+ Device: TAudioInputDevice;
begin
- Log.LogStatus('Update input-device', 'TScreenOptionsRecord.UpdateCard') ;
-
- AudioInput.CaptureStop;
-
- if (Card > High(AudioInputProcessor.Device)) then
- Card := 0;
-
- if (Length(AudioInputProcessor.Device) > 0) then
+ if ((CurrentDeviceIndex >= 0) and
+ (CurrentDeviceIndex <= High(AudioInputProcessor.Device))) then
begin
- InputDevice := AudioInputProcessor.Device[Card];
- InputDeviceCfg := @Ini.InputDeviceConfig[InputDevice.CfgIndex];
-
- SetLength(IInput, Length(InputDevice.Source));
- for SourceIndex := 0 to High(InputDevice.Source) do begin
- IInput[SourceIndex] := InputDevice.Source[SourceIndex].Name;
+ Device := AudioInputProcessor.Device[CurrentDeviceIndex];
+ // set preview channel as active capture channel
+ for ChannelIndex := 0 to High(Device.CaptureChannel) do
+ begin
+ PreviewChannel[ChannelIndex].Clear();
+ Device.LinkCaptureBuffer(ChannelIndex, PreviewChannel[ChannelIndex]);
end;
-
- UpdateSelectSlideOptions(Theme.OptionsRecord.SelectSlideInput, SelectSlideInput, IInput,
- InputDeviceCfg^.Input);
- UpdateSelectSlideOptions(Theme.OptionsRecord.SelectSlideChannelL, SelectSlideChannelL, IChannel,
- InputDeviceCfg^.ChannelToPlayerMap[0]);
- UpdateSelectSlideOptions(Theme.OptionsRecord.SelectSlideChannelR, SelectSlideChannelR, IChannel,
- InputDeviceCfg^.ChannelToPlayerMap[1]);
+ Device.Start();
+ PreviewDeviceIndex := CurrentDeviceIndex;
end;
+end;
- AudioInput.CaptureStart;
+procedure TScreenOptionsRecord.StopPreview;
+var
+ ChannelIndex: integer;
+ Device: TAudioInputDevice;
+begin
+ if ((PreviewDeviceIndex >= 0) and
+ (PreviewDeviceIndex <= High(AudioInputProcessor.Device))) then
+ begin
+ Device := AudioInputProcessor.Device[PreviewDeviceIndex];
+ Device.Stop;
+ for ChannelIndex := 0 to High(Device.CaptureChannel) do
+ Device.CaptureChannel[ChannelIndex] := nil;
+ end;
+ PreviewDeviceIndex := -1;
end;
function TScreenOptionsRecord.Draw: boolean;
+var
+ i: integer;
+ x1, x2, y1, y2: real;
+ R, G, B, RD, GD, BD: real;
+ ChannelIndex: integer;
+ Device: TAudioInputDevice;
+ DeviceCfg: PInputDeviceConfig;
+ SelectSlide: TSelectSlide;
+ ToneBoxWidth: real;
begin
DrawBG;
DrawFG;
- // TODO : this needs to be positioned correctly
- if PlayersPlay = 1 then
- SingDrawOscilloscope(190 + 10*ScreenX, 55, 180, 40, 0);
-
- if PlayersPlay = 2 then begin
- SingDrawOscilloscope(190 + 10*ScreenX, 55, 180, 40, 0);
- SingDrawOscilloscope(425 + 10*ScreenX, 55, 180, 40, 1);
- end;
+ if ((PreviewDeviceIndex >= 0) and
+ (PreviewDeviceIndex <= High(AudioInputProcessor.Device))) then
+ begin
+ Device := AudioInputProcessor.Device[PreviewDeviceIndex];
+ DeviceCfg := @Ini.InputDeviceConfig[Device.CfgIndex];
+
+ glBegin(GL_QUADS);
+ for ChannelIndex := 0 to High(Device.CaptureChannel) do
+ begin
+ // load player color mapped to current input channel
+ if (DeviceCfg.ChannelToPlayerMap[ChannelIndex] > 0) then
+ begin
+ // set mapped channel to corresponding player-color
+ LoadColor(R, G, B, 'P'+ IntToStr(DeviceCfg.ChannelToPlayerMap[ChannelIndex]) + 'Dark');
+ end
+ else
+ begin
+ // set non-mapped channel to white
+ R := 1; G := 1; B := 1;
+ end;
- if PlayersPlay = 4 then begin
- if ScreenAct = 1 then begin
- SingDrawOscilloscope(190 + 10*ScreenX, 55, 180, 40, 0);
- SingDrawOscilloscope(425 + 10*ScreenX, 55, 180, 40, 1);
- end;
- if ScreenAct = 2 then begin
- SingDrawOscilloscope(190 + 10*ScreenX, 55, 180, 40, 2);
- SingDrawOscilloscope(425 + 10*ScreenX, 55, 180, 40, 3);
- end;
- end;
+ // dark player colors
+ RD := 0.2 * R;
+ GD := 0.2 * G;
+ BD := 0.2 * B;
+
+ // channel select slide
+ SelectSlide := SelectsS[SelectSlideChannelID[ChannelIndex]];
+
+ //////////
+ // draw Volume
+ //
+
+ // coordinates for black rect
+ x1 := SelectSlide.TextureSBG.X;
+ x2 := x1 + SelectSlide.TextureSBG.W;
+ y2 := SelectSlide.TextureSBG.Y + SelectSlide.TextureSBG.H;
+ y1 := y2 - 11;
+
+ // draw black background-rect
+ glColor3f(0, 0, 0);
+ glVertex2f(x1, y1);
+ glVertex2f(x2, y1);
+ glVertex2f(x2, y2);
+ glVertex2f(x1, y2);
+
+ // coordinates for volume bar
+ x1 := x1 + 1;
+ x2 := x1 + Trunc((SelectSlide.TextureSBG.W-4) *
+ PreviewChannel[ChannelIndex].MaxSampleVolume()) + 1;
+ y1 := y1 + 1;
+ y2 := y2 - 1;
+
+ // draw volume bar
+ glColor3f(RD, GD, BD);
+ glVertex2f(x1, y1);
+ glColor3f(R, G, B);
+ glVertex2f(x2, y1);
+ glColor3f(R, G, B);
+ glVertex2f(x2, y2);
+ glColor3f(RD, GD, BD);
+ glVertex2f(x1, y2);
+
+ //////////
+ // draw Pitch
+ //
+
+ // calc tone pitch
+ PreviewChannel[ChannelIndex].AnalyzeBuffer();
+
+ // coordinates for black rect
+ x1 := SelectSlide.TextureSBG.X;
+ x2 := x1 + SelectSlide.TextureSBG.W;
+ y1 := SelectSlide.TextureSBG.Y + SelectSlide.TextureSBG.H;
+ y2 := y1 + 11;
+
+ // draw black background-rect
+ glColor3f(0, 0, 0);
+ glVertex2f(x1, y1);
+ glVertex2f(x2, y1);
+ glVertex2f(x2, y2);
+ glVertex2f(x1, y2);
+
+ // coordinates for tone boxes
+ ToneBoxWidth := SelectSlide.TextureSBG.W / NumHalftones;
+ y1 := y1 + 1;
+ y2 := y2 - 1;
+
+ // draw tone boxes
+ for i := 0 to NumHalftones-1 do
+ begin
+ x1 := SelectSlide.TextureSBG.X + i * ToneBoxWidth + 2;
+ x2 := x1 + ToneBoxWidth - 4;
+
+ if ((PreviewChannel[ChannelIndex].ToneValid) and
+ (PreviewChannel[ChannelIndex].ToneAbs = i)) then
+ begin
+ // highlight current tone-pitch
+ glColor3f(1, i / (NumHalftones-1), 0)
+ end
+ else
+ begin
+ // grey other tone-pitches
+ glColor3f(0.3, i / (NumHalftones-1) * 0.3, 0);
+ end;
- if PlayersPlay = 3 then begin
- SingDrawOscilloscope(75 + 10*ScreenX, 95, 100, 20, 0);
- SingDrawOscilloscope(370 + 10*ScreenX, 95, 100, 20, 1);
- SingDrawOscilloscope(670 + 10*ScreenX, 95, 100, 20, 2);
- end;
+ glVertex2f(x1, y1);
+ glVertex2f(x2, y1);
+ glVertex2f(x2, y2);
+ glVertex2f(x1, y2);
+ end;
- if PlayersPlay = 6 then begin
- if ScreenAct = 1 then begin
- SingDrawOscilloscope( 75 + 10*ScreenX, 95, 100, 20, 0);
- SingDrawOscilloscope(370 + 10*ScreenX, 95, 100, 20, 1);
- SingDrawOscilloscope(670 + 10*ScreenX, 95, 100, 20, 2);
- end;
- if ScreenAct = 2 then begin
- SingDrawOscilloscope( 75 + 10*ScreenX, 95, 100, 20, 3);
- SingDrawOscilloscope(370 + 10*ScreenX, 95, 100, 20, 4);
- SingDrawOscilloscope(670 + 10*ScreenX, 95, 100, 20, 5);
+ // update tone-pitch label
+ Text[TextPitchID[ChannelIndex]].Text :=
+ PreviewChannel[ChannelIndex].ToneString;
end;
- end;
+ glEnd;
+ end;
Result := True;
end;