Indicator.cs
//**********************************************************
//* Direct X Sound Recorder *
//* Author: D. Zouchinski *
//* http://zouchinski.co.uk *
//* Copyright @ 2009-2011 *
//**********************************************************
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
namespace DZouch
{
public partial class Indicator : UserControl
{
private double period = 0.3 * 44100;
private double mean;
private double meanPower;
private double peakPower;
private static short threshold = 30000;
private double powerLimit = 2.0 * Math.Log10((double)threshold);
public Indicator()
{
InitializeComponent();
SetStyle(ControlStyles.ResizeRedraw, true);
UpdateStyles();
}
protected override void OnPaint(PaintEventArgs e)
{
Rectangle rect = ClientRectangle;
rect.Width -= 1;
rect.Height -= 1;
if (peakPower > powerLimit)
{
using (Brush brush = new SolidBrush(Color.Red))
e.Graphics.FillRectangle(brush, rect);
}
using (Pen pen = new Pen(Color.Blue))
e.Graphics.DrawRectangle(pen, rect);
rect.Inflate(-2, -2);
int pos = ScalePower(rect, meanPower);
using (Pen pen = new Pen(Color.Green))
{
for (int line = rect.Bottom; line >= pos; line -= 2)
e.Graphics.DrawLine(pen, rect.Left, line, rect.Right, line);
}
pos = ScalePower(rect, peakPower);
using (Pen pen = new Pen(Color.Red))
e.Graphics.DrawLine(pen, rect.Left, pos, rect.Right, pos);
base.OnPaint(e);
}
private int ScalePower(Rectangle rect, double power)
{
// We will ignore noise of up to level of 100
return ScalePosition(rect, Math.Max(0, power - 4), MaxPower - 4);
}
private int ScalePosition(Rectangle rect, double value, double max)
{
int pos = (int)(rect.Height * (value / max));
if (pos > rect.Height)
pos = rect.Height;
if (pos < 0)
pos = 0;
pos = rect.Top + rect.Height - pos;
return pos;
}
public void Update(short[] data)
{
if (data == null)
return;
if (data.Length == 0)
return;
double max = 0, square = 0;
foreach (short sample in data)
{
if (Math.Abs((double)sample) > max)
max = Math.Abs((double)sample);
double deviation = sample - mean;
square += (deviation * deviation);
mean += deviation / period;
}
square /= data.Length;
meanPower += (Math.Log10(square + 1) - meanPower) * Math.Min(data.Length / period, 1);
peakPower += (Math.Log10(max * max + 1) - peakPower) * Math.Min(data.Length / period, 1);
Invalidate();
}
public double MeanPower { get { return meanPower; } }
public double PeakPower { get { return peakPower; } }
public double MaxPower { get { return Math.Log10(32768.0 * 32768.0 + 1); } }
public void Reset()
{
mean = 0;
meanPower = 0;
peakPower = 0;
}
}
}