1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586 |
- using BeatLyrics.Tool.RefLibs;
- using CSCore;
- using CSCore.Codecs.OGG;
- using System.Collections.Generic;
- using System.IO;
- using System.Linq;
- using System.Numerics;
- using System.Threading.Tasks;
- namespace BeatLyrics.Tool.Utils
- {
- internal static class SpectrumAnalyzer
- {
- public static SaResult[] RunOgg(string filePath, int blockSizeInMs, DSP.Window.Type windowType = DSP.Window.Type.Rectangular)
- {
- //extract samples from file
- using var ms = new MemoryStream(File.ReadAllBytes(filePath));
- using var ogg = new OggSource(ms);
- using var sampleSource = ogg.ToMono();
- var samples = new List<double[]>();
- var buffer = new float[(int)(sampleSource.WaveFormat.SampleRate * (blockSizeInMs / 1000f))];
- //Split by block size
- do
- {
- var read = sampleSource.Read(buffer, 0, buffer.Length);
- if (read == 0) break; // end of stream
- if (read < buffer.Length)
- {
- samples.Add(buffer.Take(read).Select(p => (double)p).ToArray());
- break;
- }
- samples.Add(buffer.Take(read).Select(p => (double)p).ToArray());
- } while (true);
- // calc each fft
- var results = new SaResult[samples.Count];
- Parallel.For(0, samples.Count, (i) =>
- {
- //feed samples to fft
- var timeSeries = samples[i];
- var N = (uint)timeSeries.Length;
- double[] wc = DSP.Window.Coefficients(windowType, N);
- double windowScaleFactor = DSP.Window.ScaleFactor.Signal(wc);
- double[] windowedTimeSeries = DSP.Math.Multiply(timeSeries, wc);
- FFT fft = new FFT();
- var pad = 0u;
- for (int pow = 1; pow <= 32; pow++)
- {
- var p = (uint)System.Math.Pow(2, pow);
- if (p >= N)
- {
- pad = p - N;
- break;
- }
- }
- fft.Initialize(N, pad);
- Complex[] cpxResult = fft.Execute(windowedTimeSeries);
- double[] mag = DSP.ConvertComplex.ToMagnitude(cpxResult);
- mag = DSP.Math.Multiply(mag, windowScaleFactor);
- double[] magLog = DSP.ConvertMagnitude.ToMagnitudeDBV(mag);
- double[] fSpan = fft.FrequencySpan(sampleSource.WaveFormat.SampleRate);
- var item = new SaResult { FreqAxis = fSpan, Values = magLog };
- results[i] = item;
- });
- return results;
- }
- public class SaResult
- {
- public double[] FreqAxis { get; set; }
- public double[] Values { get; set; }
- }
- }
- }
|