Madwin74

Audio VU meter

May 15th, 2023
742
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 12.42 KB | Source Code | 0 0
  1. /***********************************************************
  2.  **                                                       **
  3.  **   Codesnippets written by Madwin for MMP 2023         **
  4.  **                                                       **
  5.  **   Not to be used freely. the code still has errors    **
  6.  **   It's intended to be used as starting point.         **
  7.  **   Code has not been checked and might still need      **
  8.  **   (a lot of) work.                                    **
  9.  **                                                       **
  10.  **   © MadMedia Productions 2023                         **
  11.  **                                                       **
  12.  ***********************************************************/
  13.  
  14.  
  15. using System;
  16. using System.Drawing;
  17. using System.Windows.Forms;
  18. using NAudio.Wave;
  19.  
  20. namespace AudioVUMeter
  21. {
  22.     public partial class MainForm : Form
  23.     {
  24.         private const int NumChannels = 2; // Stereo
  25.         private const int NumBars = 20; // Number of LED bars
  26.         private const int BarSpacing = 2; // Spacing between LED bars
  27.  
  28.         private BufferedWaveProvider bufferedWaveProvider;
  29.         private readonly Timer timer;
  30.         private float[] peakValues;
  31.  
  32.         public MainForm()
  33.         {
  34.             InitializeComponent();
  35.  
  36.             // Create the buffered wave provider
  37.             bufferedWaveProvider = new BufferedWaveProvider(new WaveFormat());
  38.  
  39.             // Initialize the peak values array
  40.             peakValues = new float[NumBars];
  41.  
  42.             // Set up the timer
  43.             timer = new Timer();
  44.             timer.Interval = 20; // Update every 20 milliseconds
  45.             timer.Tick += Timer_Tick;
  46.  
  47.             // Populate audio source options
  48.             foreach (var waveInDevice in WaveIn.DeviceCount)
  49.             {
  50.                 comboBoxAudioSources.Items.Add(waveInDevice);
  51.             }
  52.  
  53.             // Select the first audio source by default
  54.             if (comboBoxAudioSources.Items.Count > 0)
  55.             {
  56.                 comboBoxAudioSources.SelectedIndex = 0;
  57.             }
  58.         }
  59.  
  60.         private void MainForm_Load(object sender, EventArgs e)
  61.         {
  62.             // Start the timer
  63.             timer.Start();
  64.         }
  65.  
  66.         private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
  67.         {
  68.             // Stop and dispose the timer
  69.             timer.Stop();
  70.             timer.Dispose();
  71.         }
  72.  
  73.         private void Timer_Tick(object sender, EventArgs e)
  74.         {
  75.             // Check if there is available data in the buffered wave provider
  76.             if (bufferedWaveProvider.BufferedBytes >= bufferedWaveProvider.WaveFormat.AverageBytesPerSecond / 10)
  77.             {
  78.                 // Read the available data from the buffered wave provider
  79.                 byte[] buffer = new byte[bufferedWaveProvider.WaveFormat.AverageBytesPerSecond / 10];
  80.                 int bytesRead = bufferedWaveProvider.Read(buffer, 0, buffer.Length);
  81.  
  82.                 // Calculate the peak values for each channel
  83.                 for (int i = 0; i < bytesRead / sizeof(float); i += NumChannels)
  84.                 {
  85.                     for (int channel = 0; channel < NumChannels; channel++)
  86.                     {
  87.                         float value = BitConverter.ToSingle(buffer, i + channel * sizeof(float));
  88.                         peakValues[i / NumChannels] = Math.Max(peakValues[i / NumChannels], value);
  89.                     }
  90.                 }
  91.             }
  92.  
  93.             // Refresh the display
  94.             vuMeterDisplay.Refresh();
  95.         }
  96.  
  97.         private void vuMeterDisplay_Paint(object sender, PaintEventArgs e)
  98.         {
  99.             Graphics graphics = e.Graphics;
  100.             Rectangle displayArea = vuMeterDisplay.ClientRectangle;
  101.  
  102.             // Calculate the width and height of each LED bar
  103.             int barWidth = (displayArea.Width - (NumBars - 1) * BarSpacing) / NumBars;
  104.             int barHeight = displayArea.Height;
  105.  
  106.             // Draw each LED bar
  107.             for (int i = 0; i < NumBars; i++)
  108.             {
  109.                 // Calculate the rectangle for the current LED bar
  110.                 Rectangle barRect = new Rectangle(i * (barWidth + BarSpacing), displayArea.Top, barWidth, barHeight);
  111.  
  112.                 // Calculate the fill percentage based on the peak value
  113.                 float fillPercentage = peakValues[i];
  114.  
  115.                 // Calculate the height of the filled portion of the LED bar
  116.                 int fillHeight = (int)(fillPercentage * barHeight);
  117.  
  118.                 // Calculate the color for the filled portion
  119.                 Color fillColor = Color.FromArgb((int)(
  120.                     fillPercentage * 255), Color.Red);
  121.  
  122.             // Fill the LED bar
  123.             graphics.FillRectangle(new SolidBrush(fillColor), barRect);
  124.  
  125.             // Draw the border of the LED bar
  126.             graphics.DrawRectangle(Pens.Black, barRect);
  127.         }
  128.     }
  129.  
  130.     private void comboBoxAudioSources_SelectedIndexChanged(object sender, EventArgs e)
  131.     {
  132.         // Stop the current audio source, if any
  133.         if (bufferedWaveProvider != null)
  134.         {
  135.             bufferedWaveProvider.ClearBuffer();
  136.             bufferedWaveProvider = null;
  137.         }
  138.  
  139.         // Create a new audio source based on the selected index
  140.         int selectedDeviceIndex = comboBoxAudioSources.SelectedIndex;
  141.         if (selectedDeviceIndex >= 0 && selectedDeviceIndex < WaveIn.DeviceCount)
  142.         {
  143.             WaveIn waveIn = new WaveIn();
  144.             waveIn.DeviceNumber = selectedDeviceIndex;
  145.             waveIn.WaveFormat = new WaveFormat();
  146.  
  147.             bufferedWaveProvider = new BufferedWaveProvider(waveIn.WaveFormat);
  148.             bufferedWaveProvider.BufferDuration = TimeSpan.FromSeconds(1); // Set buffer duration to 1 second
  149.             bufferedWaveProvider.DiscardOnBufferOverflow = true;
  150.  
  151.             waveIn.DataAvailable += WaveIn_DataAvailable;
  152.             waveIn.StartRecording();
  153.         }
  154.     }
  155.  
  156.     private void WaveIn_DataAvailable(object sender, WaveInEventArgs e)
  157.     {
  158.         if (bufferedWaveProvider != null)
  159.         {
  160.             bufferedWaveProvider.AddSamples(e.Buffer, 0, e.BytesRecorded);
  161.         }
  162.     }
  163. }
  164.  
  165. }
  166.  
  167.  
  168.  
  169. /*
  170. There's a `comboBoxAudioSources` control, which allows the user to select
  171. the audio source for display. We populate the combo box with the available
  172. audio input devices using the `WaveIn.DeviceCount` property.
  173.  
  174. When the user selects a different audio source, the `comboBoxAudioSources_SelectedIndexChanged` event handler is triggered.
  175. It stops the current audio source (if any), clears the buffer, and creates a
  176. new audio source based on the selected index. The `WaveIn` class is used to
  177. capture audio data from the selected device, and the `WaveIn_DataAvailable` event
  178. handler is responsible for adding the available samples to the `bufferedWaveProvider`
  179.  for processing.
  180.  
  181. Remember to wire up the `comboBoxAudioSources_SelectedIndexChanged` event handler
  182. to the `SelectedIndexChanged` event of the combo box in the form designer or
  183. programmatically.
  184. */
  185.  
  186. using System;
  187. using System.Drawing;
  188. using System.Windows.Forms;
  189. using CSCore;
  190. using CSCore.CoreAudioAPI;
  191. using CSCore.SoundIn;
  192.  
  193. namespace AudioVUMeter
  194. {
  195.     public partial class MainForm : Form
  196.     {
  197.         private const int NumChannels = 2; // Stereo
  198.         private const int NumBars = 20; // Number of LED bars
  199.         private const int BarSpacing = 2; // Spacing between LED bars
  200.  
  201.         private WasapiCapture capture;
  202.         private float[] peakValues;
  203.  
  204.         public MainForm()
  205.         {
  206.             InitializeComponent();
  207.  
  208.             // Initialize the peak values array
  209.             peakValues = new float[NumBars];
  210.         }
  211.  
  212.         private void MainForm_Load(object sender, EventArgs e)
  213.         {
  214.             // Populate audio source options
  215.             foreach (var device in MMDeviceEnumerator.EnumerateDevices(DataFlow.Capture, DeviceState.Active))
  216.             {
  217.                 comboBoxAudioSources.Items.Add(device);
  218.             }
  219.  
  220.             // Select the first audio source by default
  221.             if (comboBoxAudioSources.Items.Count > 0)
  222.             {
  223.                 comboBoxAudioSources.SelectedIndex = 0;
  224.             }
  225.         }
  226.  
  227.         private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
  228.         {
  229.             // Stop and dispose the capture
  230.             if (capture != null)
  231.             {
  232.                 capture.Stop();
  233.                 capture.Dispose();
  234.             }
  235.         }
  236.  
  237.         private void comboBoxAudioSources_SelectedIndexChanged(object sender, EventArgs e)
  238.         {
  239.             // Stop the current capture, if any
  240.             if (capture != null)
  241.             {
  242.                 capture.Stop();
  243.                 capture.Dispose();
  244.                 capture = null;
  245.             }
  246.  
  247.             // Create a new capture based on the selected audio source
  248.             int selectedDeviceIndex = comboBoxAudioSources.SelectedIndex;
  249.             if (selectedDeviceIndex >= 0 && selectedDeviceIndex < comboBoxAudioSources.Items.Count)
  250.             {
  251.                 MMDevice selectedDevice = (MMDevice)comboBoxAudioSources.SelectedItem;
  252.                 capture = new WasapiCapture(selectedDevice);
  253.  
  254.                 // Set up event handlers
  255.                 capture.DataAvailable += Capture_DataAvailable;
  256.                 capture.Initialize();
  257.  
  258.                 // Start the capture
  259.                 capture.Start();
  260.             }
  261.         }
  262.  
  263.         private void Capture_DataAvailable(object sender, WaveInEventArgs e)
  264.         {
  265.             // Calculate the peak values for each channel
  266.             for (int i = 0; i < e.BytesRecorded / sizeof(float); i += NumChannels)
  267.             {
  268.                 for (int channel = 0; channel < NumChannels; channel++)
  269.                 {
  270.                     float value = BitConverter.ToSingle(e.Buffer, i + channel * sizeof(float));
  271.                     peakValues[i / NumChannels] = Math.Max(peakValues[i / NumChannels], value);
  272.                 }
  273.             }
  274.  
  275.             // Refresh the display
  276.             vuMeterDisplay.Refresh();
  277.         }
  278.  
  279.         private void vuMeterDisplay_Paint(object sender, PaintEventArgs e)
  280.         {
  281.             Graphics graphics = e.Graphics;
  282.             Rectangle displayArea = vuMeterDisplay.ClientRectangle;
  283.  
  284.             // Calculate the width and height of each LED bar
  285.             int barWidth = (displayArea.Width - (NumBars - 1) * BarSpacing) / NumBars;
  286.             int barHeight = displayArea.Height;
  287.  
  288.             // Draw each LED bar
  289.             for (int i = 0; i < NumBars; i++)
  290.             {
  291.                 // Calculate the rectangle for the current LED bar
  292.                 Rectangle barRect = new Rectangle(i * (barWidth + BarSpacing), displayArea.Top, barWidth, barHeight);
  293.  
  294.                 // Calculate the fill percentage based on the peak value
  295.                 float fillPercentage = peakValues[i];
  296.  
  297.                 // Calculate the height of the filled portion of the LED bar
  298.                 int fillHeight = (int)(fillPercentage * barHeight);
  299.  
  300.                 // Calculate the color for the filled portion
  301.                 Color fillColor = Color.FromArgb((int)(fillPercentage * 255), Color.Red);
  302.  
  303.                 // Fill the LED bar
  304.                 graphics.FillRectangle(new SolidBrush(fillColor), barRect);
  305.  
  306.                 // Draw the border of the LED bar
  307.                 graphics.DrawRectangle(Pens.Black, barRect);
  308.             }
  309.         }
  310.     }
  311. }
  312.  
  313. /*
  314. In this updated version, we use the CSCore library to capture audio data from
  315. the selected audio source. We populate the comboBoxAudioSources combo box with
  316. the active audio capture devices using the MMDeviceEnumerator.EnumerateDevices
  317. method.
  318.  
  319. When the user selects a different audio source, the
  320. comboBoxAudioSources_SelectedIndexChanged event handler is triggered. It stops
  321. the current capture (if any), disposes of the resources, and creates a new capture
  322. based on the selected audio source using the WasapiCapture class. We set up the
  323. DataAvailable event handler to calculate the peak values for each channel and
  324. update the VU meter display.
  325.  
  326. Remember to wire up the comboBoxAudioSources_SelectedIndexChanged event handler
  327. to the SelectedIndexChanged event of the combo box in the form designer or
  328. programmatically.
  329.  
  330. This updated code should allow you to choose the audio source you want to
  331. isplay in the VU meter using the CSCore library.
  332. */
Advertisement
Add Comment
Please, Sign In to add comment