using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using RecrownedAthenaeum.Camera; using RecrownedAthenaeum.Render; using RecrownedAthenaeum.UI.Modular; using System; namespace RecrownedAthenaeum.Audio.Visualizer { internal class HorizontalVisualizer : UIModule { private RectangleRenderer renderer; private const int BAR_COUNT = 70; private const int SMOOTH_RANGE = 3; private readonly int binsPerBar; private readonly int spaceBetweenBars; private Rectangle bar; private TransparentSampleProvider tsp; private int[] barValue; internal HorizontalVisualizer(TransparentSampleProvider transparentSampleProvider, GraphicsDevice graphicsDevice, Camera2D camera2D) { tsp = transparentSampleProvider; bar.Width = (int)(graphicsDevice.Viewport.Width / 70f); spaceBetweenBars = (int)(0.25f * bar.Width); bar.Width -= spaceBetweenBars; binsPerBar = tsp.GetCurrentSpectrum().Length / BAR_COUNT; barValue = new int[BAR_COUNT]; renderer = new RectangleRenderer(graphicsDevice, camera2D); } public override void Update(GameTime gameTime) { UpdateBars((float)gameTime.ElapsedGameTime.TotalSeconds); AverageBars(); base.Update(gameTime); } public override void Draw(SpriteBatch batch) { for (int i = 0; i < BAR_COUNT; i++) { bar.X = (i * (bar.Width + spaceBetweenBars)) + bounds.X; bar.Y = bounds.Y; renderer.Begin(true); bar.Height = barValue[i]; renderer.DrawRectangle(bar.X, bar.Y, bar.Width, bar.Height, color); bar.Height = -barValue[BAR_COUNT - i - 1]; renderer.DrawRectangle(bar.X, bar.Y, bar.Width, bar.Height, color); } base.Draw(batch); } private void UpdateBars(float delta) { const float ALPHA = 0.5f; float[] spectrum = tsp.GetCurrentSpectrum(); for (int barID = 0; barID < BAR_COUNT; barID++) { int targetBarHeight = 0; for (int bin = barID * binsPerBar; bin < (barID + 1) * (binsPerBar); bin++) { targetBarHeight += (int)spectrum[bin]; } targetBarHeight /= binsPerBar; int distance = targetBarHeight - barValue[barID]; distance *= (int)Math.Round((1.0f - Math.Pow(1 - ALPHA, delta / 0.02f))); barValue[barID] += distance; } } private void AverageBars() { for (int barID = 0; barID < BAR_COUNT; barID++) { int terms = 0; for (int pos = 0; pos < SMOOTH_RANGE; pos++) { if (barID + pos < BAR_COUNT) { barValue[barID] += barValue[barID + pos]; terms++; } if (barID - pos > 0) { barValue[barID] += barValue[barID - pos]; terms++; } } barValue[barID] /= terms; } } ~HorizontalVisualizer() { renderer.Dispose(); } } }