using Sandbox.Audio;
namespace Editor.Audio;
///
/// Shows left and right volume bars, with a peak indicator.
///
public class AudioMeterWidget : Widget
{
public float Left { get; private set; }
public float Right { get; private set; }
public AudioMeterWidget()
{
HorizontalSizeMode = SizeMode.Expand;
}
protected override Vector2 SizeHint() => new( 32, 200 );
float TopDb = 10;
float BottomDb = -80;
float DecibelsToWidget( float db ) => db.Remap( TopDb, BottomDb, 0, Height );
protected override void OnPaint()
{
var bg = Theme.Green.Darken( 0.85f );
bg = Theme.ControlBackground;
var ll = Left;
var lr = Right;
ll = Helper.LinearToDecibels( ll );
lr = Helper.LinearToDecibels( lr );
Paint.Antialiasing = true;
Paint.SetBrushAndPen( bg.WithAlpha( 0.35f ) );
Paint.DrawRect( LocalRect.Shrink( 1 ), 4 );
var inner = LocalRect.Shrink( 1 );
var gap = 2;
var w = (inner.Width / 2.0f) - gap / 2.0f;
float danger = DecibelsToWidget( -20 );
{
var h = inner.Height - DecibelsToWidget( ll );
if ( h > 0 )
{
var r = new Rect( inner.Left, inner.Top + inner.Height - h, w, h );
Paint.ClearPen();
Paint.SetBrushLinear( new Vector2( 0, 0 ), new Vector2( 0, danger ), Theme.Red, Theme.Green );
Paint.DrawRect( r, 0 );
}
if ( historyFrames.Count > 0 )
{
var peak = historyFrames.Max( x => x.MaxLevelLeft );
if ( peak > 0 )
{
float zero = DecibelsToWidget( Helper.LinearToDecibels( peak ) );
Paint.SetBrushAndPen( Color.Transparent, Color.Yellow.WithAlpha( 0.7f ), 1 );
Paint.DrawLine( new Vector2( inner.Left, zero ), new Vector2( inner.Left + w, zero ) );
}
}
}
{
var h = inner.Height - DecibelsToWidget( lr );
if ( h > 0 )
{
var r = new Rect( inner.Left + w + gap, inner.Top + inner.Height - h, w, h );
Paint.ClearPen();
Paint.SetBrushLinear( new Vector2( 0, 0 ), new Vector2( 0, danger ), Theme.Red, Theme.Green );
Paint.DrawRect( r, 0 );
}
if ( historyFrames.Count > 0 )
{
var peak = historyFrames.Max( x => x.MaxLevelRight );
if ( peak > 0 )
{
float zero = DecibelsToWidget( Helper.LinearToDecibels( peak ) );
Paint.SetBrushAndPen( Color.Transparent, Color.Yellow.WithAlpha( 0.7f ), 1 );
Paint.DrawLine( new Vector2( inner.Left + w + gap, zero ), new Vector2( inner.Left + w + gap + w, zero ) );
}
}
}
for ( float i = BottomDb; i <= TopDb; i += 2 )
{
bool sig = i % 10 == 0;
float zero = DecibelsToWidget( i );
Paint.SetBrushAndPen( Color.Transparent, bg.WithAlpha( sig ? 0.3f : 0.1f ), 1 );
if ( i == 0 ) Paint.Pen = bg;
Paint.DrawLine( new Vector2( 0, zero ), new Vector2( Width, zero ) );
}
Paint.SetBrushAndPen( Color.Transparent, bg, 1 );
Paint.DrawRect( LocalRect.Shrink( 1 ), 2 );
Paint.DrawLine( new Vector2( Width * 0.5f, 0 ), new Vector2( Width * 0.5f, Height ) );
}
RealTimeSince timeSinceUpdate = 0;
List historyFrames = new List();
internal void UpdateValues( AudioMeter meter )
{
if ( timeSinceUpdate < 1 / 60.0f )
return;
timeSinceUpdate = 0;
Left = meter.Current.MaxLevelLeft;
Right = meter.Current.MaxLevelRight;
historyFrames.Add( meter.Current );
if ( historyFrames.Count > 60 )
historyFrames.RemoveAt( 0 );
Update();
}
}