mirror of
https://github.com/Stone-Red-Code/BeatDetector.git
synced 2026-09-04 00:46:06 +02:00
Multiple improvments
This commit is contained in:
@@ -6,7 +6,7 @@ using System.Linq;
|
||||
|
||||
namespace BeatDetector.AudioProcessing;
|
||||
|
||||
internal class AudioBeatDetector
|
||||
internal class AudioBeatDetector : IDisposable
|
||||
{
|
||||
public event EventHandler<BeatDetectorEventArgs>? OnBeat;
|
||||
|
||||
@@ -20,8 +20,9 @@ internal class AudioBeatDetector
|
||||
private readonly int chunkCount;
|
||||
private readonly BeatChunk[] beatChunks;
|
||||
|
||||
public AudioBeatDetector(TimeSpan beatDetectionDelay, int fftLength, int chunkCount)
|
||||
public AudioBeatDetector(IWaveIn waveIn, TimeSpan beatDetectionDelay, int fftLength, int chunkCount)
|
||||
{
|
||||
this.waveIn = waveIn;
|
||||
this.beatDetectionDelay = beatDetectionDelay;
|
||||
this.chunkCount = chunkCount;
|
||||
this.fftLength = fftLength;
|
||||
@@ -38,10 +39,12 @@ internal class AudioBeatDetector
|
||||
sampleAggregator.FftCalculated += new EventHandler<FftEventArgs>(FftCalculated);
|
||||
sampleAggregator.PerformFFT = true;
|
||||
|
||||
waveIn = new WasapiLoopbackCapture();
|
||||
waveIn.DataAvailable += OnDataAvailable;
|
||||
}
|
||||
|
||||
waveIn.StartRecording();
|
||||
public void Dispose()
|
||||
{
|
||||
waveIn.DataAvailable -= OnDataAvailable;
|
||||
}
|
||||
|
||||
private void OnDataAvailable(object? sender, WaveInEventArgs e)
|
||||
@@ -77,7 +80,7 @@ internal class AudioBeatDetector
|
||||
|
||||
double averageEnergyLevel = beatChunk.EnergyHistory.Count > 0 ? beatChunk.EnergyHistory.Average() : double.MaxValue;
|
||||
|
||||
if (beatChunk.StopWatch.Elapsed >= beatDetectionDelay)
|
||||
if (beatChunk.StopWatch.Elapsed >= beatDetectionDelay || beatDetectionDelay <= TimeSpan.Zero)
|
||||
{
|
||||
double difference = energyLevel - averageEnergyLevel;
|
||||
|
||||
@@ -88,6 +91,11 @@ internal class AudioBeatDetector
|
||||
}
|
||||
else
|
||||
{
|
||||
//if (difference > 0)
|
||||
//{
|
||||
// beatChunk.AverageDifference = (difference + beatChunk.AverageDifference) / 2.00001;
|
||||
//}
|
||||
|
||||
OnNoBeat?.Invoke(this, new BeatDetectorEventArgs(chunkIndex, 0));
|
||||
}
|
||||
beatChunk.StopWatch.Restart();
|
||||
|
||||
@@ -8,4 +8,6 @@ internal class BeatChunk
|
||||
public Stopwatch StopWatch { get; } = new Stopwatch();
|
||||
public List<double> EnergyHistory { get; } = new List<double>();
|
||||
public double AverageDifference { get; set; }
|
||||
|
||||
public int NoBeatCount { get; set; }
|
||||
}
|
||||
+3
-3
@@ -5,12 +5,12 @@
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:local="clr-namespace:BeatDetector" d:DataContext="{d:DesignInstance Type=local:MainWindow}"
|
||||
mc:Ignorable="d"
|
||||
Title="MainWindow" Height="450" Width="800">
|
||||
Title="MainWindow" Height="450" Width="800" KeyUp="Window_KeyUp" ResizeMode="NoResize">
|
||||
<Grid Name="MainGrid">
|
||||
<ItemsControl ItemsSource="{Binding BeatLights}" Background="Green">
|
||||
<ItemsControl ItemsSource="{Binding BeatLights}" Background="Black">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Grid Background="{Binding Color}" Margin="10" Width="100" Height="100"></Grid>
|
||||
<Grid Background="{Binding Color}" Margin="5" Width="100" Height="100"></Grid>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
<ItemsControl.ItemsPanel>
|
||||
|
||||
+65
-9
@@ -1,8 +1,11 @@
|
||||
using BeatDetector.AudioProcessing;
|
||||
|
||||
using NAudio.Wave;
|
||||
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Windows;
|
||||
using System.Windows.Media;
|
||||
@@ -15,6 +18,19 @@ namespace BeatDetector;
|
||||
/// </summary>
|
||||
public partial class MainWindow : Window
|
||||
{
|
||||
private readonly Brush[] brushes = new Brush[]
|
||||
{
|
||||
Brushes.Red,
|
||||
Brushes.Orange,
|
||||
Brushes.Plum,
|
||||
Brushes.Purple,
|
||||
Brushes.Blue,
|
||||
Brushes.Green,
|
||||
};
|
||||
|
||||
private readonly IWaveIn audioStream;
|
||||
private int lightAmountFactor = 3;
|
||||
private AudioBeatDetector? audioBeatDetector;
|
||||
public ObservableCollection<BeatLight> BeatLights { get; } = new ObservableCollection<BeatLight>();
|
||||
|
||||
public MainWindow()
|
||||
@@ -22,24 +38,64 @@ public partial class MainWindow : Window
|
||||
DataContext = this;
|
||||
InitializeComponent();
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
BeatLights.Add(new BeatLight());
|
||||
}
|
||||
audioStream = new WasapiLoopbackCapture();
|
||||
audioStream.StartRecording();
|
||||
|
||||
AudioBeatDetector audioBeatDetector = new AudioBeatDetector(new TimeSpan(0, 0, 0, 0, 100), 1024 * 2, BeatLights.Count);
|
||||
audioBeatDetector.OnBeat += AudioBeatDetector_OnBeat;
|
||||
audioBeatDetector.OnNoBeat += AudioBeatDetector_OnNoBeat;
|
||||
SetupAudioBeatDetector();
|
||||
}
|
||||
|
||||
private void AudioBeatDetector_OnBeat(object? sender, BeatDetectorEventArgs e)
|
||||
{
|
||||
Dispatcher.Invoke(() => BeatLights[e.ChunkIndex].Color = Brushes.Red);
|
||||
Dispatcher.Invoke(() =>
|
||||
{
|
||||
double index = (brushes.Length - 1) / (double)BeatLights.Count * BeatLights.Count(x => x.Color != Brushes.White);
|
||||
BeatLights[e.ChunkIndex].Color = brushes[(int)index];
|
||||
});
|
||||
}
|
||||
|
||||
private void AudioBeatDetector_OnNoBeat(object? sender, BeatDetectorEventArgs e)
|
||||
{
|
||||
Dispatcher.Invoke(() => BeatLights[e.ChunkIndex].Color = Brushes.White);
|
||||
_ = Dispatcher.Invoke(() => BeatLights[e.ChunkIndex].Color = Brushes.White);
|
||||
}
|
||||
|
||||
private void Window_KeyUp(object sender, System.Windows.Input.KeyEventArgs e)
|
||||
{
|
||||
if (e.Key == System.Windows.Input.Key.Add && lightAmountFactor < 10)
|
||||
{
|
||||
lightAmountFactor++;
|
||||
audioBeatDetector?.Dispose();
|
||||
SetupAudioBeatDetector();
|
||||
}
|
||||
else if (e.Key == System.Windows.Input.Key.Subtract && lightAmountFactor > 1)
|
||||
{
|
||||
lightAmountFactor--;
|
||||
audioBeatDetector?.Dispose();
|
||||
SetupAudioBeatDetector();
|
||||
}
|
||||
}
|
||||
|
||||
private void SetupAudioBeatDetector()
|
||||
{
|
||||
BeatLights.Clear();
|
||||
|
||||
for (int i = 0; i < Math.Pow(lightAmountFactor, 2); i++)
|
||||
{
|
||||
BeatLights.Add(new BeatLight());
|
||||
}
|
||||
|
||||
if (audioBeatDetector is not null)
|
||||
{
|
||||
audioBeatDetector.OnBeat -= AudioBeatDetector_OnBeat;
|
||||
audioBeatDetector.OnNoBeat -= AudioBeatDetector_OnNoBeat;
|
||||
}
|
||||
|
||||
audioBeatDetector = new AudioBeatDetector(audioStream, TimeSpan.FromMilliseconds(0), 1024 * 2, BeatLights.Count);
|
||||
|
||||
audioBeatDetector.OnBeat += AudioBeatDetector_OnBeat;
|
||||
audioBeatDetector.OnNoBeat += AudioBeatDetector_OnNoBeat;
|
||||
|
||||
Width = (Math.Sqrt(BeatLights.Count) * 110) + 15;
|
||||
Height = (Math.Sqrt(BeatLights.Count) * 110) + 40;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user