mirror of
https://github.com/DarthAffe/CUE.NET.git
synced 2026-11-11 13:06:24 +00:00
Added AudioAnalyzer-Example
This commit is contained in:
1 parent
0c862fc6de
commit
6ed251a484
16 files changed
+731
No files matched your search
@@ -0,0 +1,46 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Un4seen.Bass;
|
||||
using Un4seen.BassWasapi;
|
||||
|
||||
namespace Example_AudioAnalyzer_full.TakeAsIs
|
||||
{
|
||||
public static class BassHelper
|
||||
{
|
||||
public static void InitializeBass()
|
||||
{
|
||||
BassNet.Registration("trial@trial.com", "2X1837515183722");
|
||||
BassNet.OmitCheckVersion = true;
|
||||
if (!Bass.LoadMe())
|
||||
throw new WASAPIInitializationException("Unable to load bass.dll!");
|
||||
|
||||
if (!Bass.BASS_Init(0, 48000, 0, IntPtr.Zero))
|
||||
throw new WASAPIInitializationException("Unable to initialize the BASS library!");
|
||||
|
||||
if (!BassWasapi.LoadMe())
|
||||
throw new WASAPIInitializationException("Unable to load BassWasapi.dll!");
|
||||
|
||||
Bass.BASS_SetConfig(BASSConfig.BASS_CONFIG_UPDATEPERIOD, 0);
|
||||
}
|
||||
|
||||
public static List<Tuple<string, int>> GetBassDevices()
|
||||
{
|
||||
List<Tuple<string, int>> deviceList = new List<Tuple<string, int>>();
|
||||
|
||||
BASS_WASAPI_DEVICEINFO[] devices = BassWasapi.BASS_WASAPI_GetDeviceInfos();
|
||||
for (int i = 0; i < devices.Length; i++)
|
||||
{
|
||||
BASS_WASAPI_DEVICEINFO device = devices[i];
|
||||
if (!device.IsEnabled || !device.SupportsRecording) continue;
|
||||
|
||||
string deviceName = device.name;
|
||||
if (device.IsLoopback)
|
||||
deviceName += " (Loopback)";
|
||||
|
||||
deviceList.Add(new Tuple<string, int>(deviceName, i));
|
||||
}
|
||||
|
||||
return deviceList;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
/*
|
||||
* ###################################################################################################################
|
||||
* # Thanks to AterialDawn #
|
||||
* # #
|
||||
* # Source: https://github.com/AterialDawn/CUEAudioVisualizer/blob/master/CUEAudioVisualizer/SoundDataProcessor.cs #
|
||||
* # Date: 23.10.2015 #
|
||||
* # Commit: 9106ab777d70a23254872455c6f3cefbe9bef6ca #
|
||||
* # #
|
||||
* ###################################################################################################################
|
||||
*
|
||||
* > Note < This code is refactored and all parts not used inb this tutorial are removed.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using Un4seen.Bass;
|
||||
using Un4seen.BassWasapi;
|
||||
|
||||
namespace Example_AudioAnalyzer_full.TakeAsIs
|
||||
{
|
||||
public class SoundDataProcessor
|
||||
{
|
||||
private const int BAR_COUNT = 1000;
|
||||
|
||||
public float[] BarValues = new float[BAR_COUNT];
|
||||
public float VolumeScalar = 1f;
|
||||
public float SongBeat = 0;
|
||||
|
||||
private float _averagedVolume = 0;
|
||||
private int _wasapiDeviceIndex = -1;
|
||||
private BASSData _maxFft = (BASSData.BASS_DATA_FFT8192);
|
||||
private float[] _fftData = new float[4096];
|
||||
private float[] _freqVolScalar = new float[BAR_COUNT];
|
||||
private float[] _barValues = new float[BAR_COUNT];
|
||||
private int _sampleFrequency = 48000;
|
||||
private int _maximumFrequency = 21000;
|
||||
private int _minimumFrequency = 0;
|
||||
private int _maximumFrequencyIndex;
|
||||
private int _minimumFrequencyIndex;
|
||||
private int _deviceNumber;
|
||||
private int[] _logIndex = new int[BAR_COUNT];
|
||||
private bool _deviceInitialized = false;
|
||||
private WASAPIPROC _wasapiProc;
|
||||
|
||||
public SoundDataProcessor(int deviceIndex)
|
||||
{
|
||||
this._wasapiDeviceIndex = deviceIndex;
|
||||
|
||||
BuildLookupTables();
|
||||
_wasapiProc = IgnoreDataProc;
|
||||
}
|
||||
|
||||
public void Process()
|
||||
{
|
||||
if (_deviceNumber != _wasapiDeviceIndex || !_deviceInitialized)
|
||||
{
|
||||
UpdateDevice();
|
||||
_deviceNumber = BassWasapi.BASS_WASAPI_GetDevice();
|
||||
}
|
||||
|
||||
if (!_deviceInitialized) return;
|
||||
|
||||
GetBarData();
|
||||
float curVol = BassWasapi.BASS_WASAPI_GetDeviceLevel(_deviceNumber, -1) * VolumeScalar;
|
||||
_averagedVolume = Utility.Clamp(Utility.LinearInterpolate(_averagedVolume, curVol, 0.02f), 0f, 1f);
|
||||
}
|
||||
|
||||
private void UpdateDevice()
|
||||
{
|
||||
if (_wasapiDeviceIndex == -1) return;
|
||||
if (_deviceInitialized)
|
||||
{
|
||||
Console.WriteLine("Deinitializing WASAPI device");
|
||||
BassWasapi.BASS_WASAPI_Stop(true);
|
||||
BassWasapi.BASS_WASAPI_Free();
|
||||
_deviceInitialized = false;
|
||||
}
|
||||
BASS_WASAPI_DEVICEINFO devInfo = BassWasapi.BASS_WASAPI_GetDeviceInfo(_wasapiDeviceIndex);
|
||||
if (devInfo == null)
|
||||
throw new WASAPIInitializationException("Device " + _wasapiDeviceIndex + " is invalid!");
|
||||
|
||||
if (!BassWasapi.BASS_WASAPI_Init(_wasapiDeviceIndex, devInfo.mixfreq, 2, BASSWASAPIInit.BASS_WASAPI_AUTOFORMAT | BASSWASAPIInit.BASS_WASAPI_BUFFER, 0f, 0f, _wasapiProc, IntPtr.Zero))
|
||||
{
|
||||
BASSError error = Bass.BASS_ErrorGetCode();
|
||||
throw new WASAPIInitializationException("Unable to initialize WASAPI device " + _wasapiDeviceIndex, error);
|
||||
}
|
||||
|
||||
if (!BassWasapi.BASS_WASAPI_Start())
|
||||
{
|
||||
BASSError error = Bass.BASS_ErrorGetCode();
|
||||
throw new WASAPIInitializationException("Unable to start WASAPI!", error);
|
||||
}
|
||||
|
||||
Console.WriteLine("WASAPI device initialized");
|
||||
_deviceNumber = _wasapiDeviceIndex;
|
||||
_sampleFrequency = devInfo.mixfreq;
|
||||
BuildLookupTables();
|
||||
_deviceInitialized = true;
|
||||
}
|
||||
|
||||
private void BuildLookupTables()
|
||||
{
|
||||
_maximumFrequencyIndex = Math.Min(Utils.FFTFrequency2Index(_maximumFrequency, 8192, _sampleFrequency) + 1, 4095);
|
||||
_minimumFrequencyIndex = Math.Min(Utils.FFTFrequency2Index(_minimumFrequency, 8192, _sampleFrequency), 4095);
|
||||
_freqVolScalar[0] = 1f;
|
||||
for (int i = 1; i < BAR_COUNT; i++)
|
||||
{
|
||||
_logIndex[i] = (int)((Math.Log(BAR_COUNT, BAR_COUNT) - Math.Log(BAR_COUNT - i, BAR_COUNT)) * (_maximumFrequencyIndex - _minimumFrequencyIndex) + _minimumFrequencyIndex);
|
||||
_freqVolScalar[i] = 1 + (float)Math.Sqrt((double)i / (double)BAR_COUNT) * 1.25f;
|
||||
}
|
||||
}
|
||||
|
||||
private void GetBarData()
|
||||
{
|
||||
//Get FFT data
|
||||
BassWasapi.BASS_WASAPI_GetData(_fftData, (int)_maxFft);
|
||||
int barIndex = 0;
|
||||
//Calculate bar values by squaring fftData from log(x) fft bin, and multiply by a few magic values to end up with a somewhat reasonable graphical representation of the sound
|
||||
for (barIndex = 0; barIndex < BAR_COUNT; barIndex++)
|
||||
{
|
||||
_barValues[barIndex] = ((float)Math.Sqrt(_fftData[_logIndex[barIndex]]) * 15f * VolumeScalar) * _freqVolScalar[barIndex];
|
||||
}
|
||||
barIndex = 0;
|
||||
|
||||
//This chunk of code is supposed to do a rolling average to smooth out the lower values to look cleaner for another visualizer i'm working on
|
||||
float preScaled;
|
||||
|
||||
float preScaled1 = _barValues[barIndex];
|
||||
preScaled1 += _barValues[barIndex + 1];
|
||||
preScaled1 /= 2f;
|
||||
BarValues[barIndex] = Utility.Clamp(preScaled1, 0f, 1f);
|
||||
|
||||
barIndex++;
|
||||
|
||||
preScaled1 = _barValues[barIndex - 1] * 0.75f;
|
||||
preScaled1 += _barValues[barIndex];
|
||||
preScaled1 += _barValues[barIndex + 1] * 0.75f;
|
||||
preScaled1 /= 2.5f;
|
||||
BarValues[barIndex] = Utility.Clamp(preScaled1, 0f, 1f);
|
||||
|
||||
for (barIndex = 2; barIndex < 50; barIndex++)
|
||||
{
|
||||
preScaled = _barValues[barIndex - 2] * 0.5f;
|
||||
preScaled += _barValues[barIndex - 1] * 0.75f;
|
||||
preScaled += _barValues[barIndex];
|
||||
preScaled += _barValues[barIndex + 1] * 0.75f;
|
||||
preScaled += _barValues[barIndex + 2] * 0.5f;
|
||||
preScaled /= 3.5f;
|
||||
BarValues[barIndex] = Utility.Clamp(preScaled, 0f, 1f);
|
||||
}
|
||||
for (barIndex = 50; barIndex < 999; barIndex++)
|
||||
{
|
||||
preScaled = _barValues[barIndex - 1] * 0.75f;
|
||||
preScaled += _barValues[barIndex];
|
||||
preScaled += _barValues[barIndex + 1] * 0.75f;
|
||||
preScaled /= 2.5f;
|
||||
BarValues[barIndex] = Utility.Clamp(preScaled, 0f, 1f);
|
||||
}
|
||||
preScaled = _barValues[barIndex - 1];
|
||||
preScaled += _barValues[barIndex];
|
||||
preScaled /= 2f;
|
||||
BarValues[barIndex] = Utility.Clamp(preScaled, 0f, 1f);
|
||||
|
||||
//Calculate the song beat
|
||||
float sum = 0f;
|
||||
for (int i = 2; i < 28; i++)
|
||||
sum += (float)Math.Sqrt(_barValues[i]); //Prettier scaling > Accurate scaling
|
||||
|
||||
SongBeat = (sum / 25f);
|
||||
}
|
||||
|
||||
private static int IgnoreDataProc(IntPtr buffer, int length, IntPtr user)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* ###################################################################################################################
|
||||
* # Thanks to AterialDawn #
|
||||
* # #
|
||||
* # Source: https://github.com/AterialDawn/CUEAudioVisualizer/blob/master/CUEAudioVisualizer/Utility.cs #
|
||||
* # Date: 23.10.2015 #
|
||||
* # Commit: d415fd1dda2e7fd98391ac83c000d7e4a781558e #
|
||||
* # #
|
||||
* ###################################################################################################################
|
||||
*
|
||||
* > Note < This code is refactored and all parts not used inb this tutorial are removed.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
namespace Example_AudioAnalyzer_full.TakeAsIs
|
||||
{
|
||||
public static class Utility
|
||||
{
|
||||
public static float Clamp(float value, float min, float max)
|
||||
{
|
||||
return Math.Min(Math.Max(value, min), max);
|
||||
}
|
||||
|
||||
public static float LinearInterpolate(float absMin, float absMax, float value)
|
||||
{
|
||||
return (value / (1f / (absMax - absMin))) + absMin;
|
||||
}
|
||||
}
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* ###################################################################################################################
|
||||
* # Thanks to AterialDawn #
|
||||
* # #
|
||||
* # Source: https://github.com/AterialDawn/CUEAudioVisualizer/blob/master/CUEAudioVisualizer/Exceptions/WASAPIInitializationException.cs #
|
||||
* # Date: 23.10.2015 #
|
||||
* # Commit: d415fd1dda2e7fd98391ac83c000d7e4a781558e #
|
||||
* # #
|
||||
* ###################################################################################################################
|
||||
*
|
||||
* > Note < This code is refactored and all parts not used inb this tutorial are removed.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using Un4seen.Bass;
|
||||
|
||||
namespace Example_AudioAnalyzer_full.TakeAsIs
|
||||
{
|
||||
public class WASAPIInitializationException : Exception
|
||||
{
|
||||
public BASSError? OptionalError { get; private set; }
|
||||
|
||||
public WASAPIInitializationException(string message) : base(message) { OptionalError = null; }
|
||||
public WASAPIInitializationException(string message, BASSError error) : base(message) { OptionalError = error; }
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user