BGC Tools
Static Public Member Functions
BGC.Audio.Visualization.Spectrogram Class Reference

Static Public Member Functions

static SpectralDecomp Decompose (IBGCStream stream, int windowCount=400, int windowOrder=12, int targetChannel=0, double minFreq=0.0, double maxFreq=double.PositiveInfinity)
 

Detailed Description

Definition at line 8 of file Spectrogram.cs.

Member Function Documentation

◆ Decompose()

static SpectralDecomp BGC.Audio.Visualization.Spectrogram.Decompose ( IBGCStream  stream,
int  windowCount = 400,
int  windowOrder = 12,
int  targetChannel = 0,
double  minFreq = 0.0,
double  maxFreq = double.PositiveInfinity 
)
inlinestatic

Definition at line 10 of file Spectrogram.cs.

References BGC.Audio.Visualization.SpectralDecomp.Add(), BGC.Audio.IBGCStream.Channels, BGC.Mathematics.Fourier.Forward(), BGC.Audio.FrequencyDomain.GetComplexSampleFrequency(), BGC.Audio.Envelopes.CosineEnvelope.HammingWindow(), BGC.Audio.Envelopes.IBGCEnvelopeStream.ReadNextSample(), and BGC.Audio.Envelopes.IBGCEnvelopeStream.Reset().

17  {
18  //WindowSize is 2 ^ windowOrder
19  int windowSize = 1 << windowOrder;
20 
21  if (stream.Channels <= targetChannel)
22  {
23  throw new ArgumentException(
24  $"TargetChannel ({targetChannel}) exceeded stream channels ({stream.Channels})",
25  nameof(targetChannel));
26  }
27 
28  float[] samples = stream.IsolateChannel(targetChannel).Cache().Samples;
29 
30  int sampleOffset = (int)((samples.Length - windowSize) / (double)(windowCount - 1));
31 
32  //Adjust windowSize to conform to sample size and requirements
33  while (sampleOffset <= 0 && windowOrder > 4)
34  {
35  --windowOrder;
36  windowSize = 1 << windowOrder;
37  windowCount /= 2;
38  sampleOffset = (int)((samples.Length - windowSize) / (double)(windowCount - 1));
39  }
40 
41  if (windowOrder == 4)
42  {
43  throw new ArgumentException("Clip too short to evaluate");
44  }
45 
46  if (maxFreq == double.PositiveInfinity)
47  {
48  //Default MaxFrequency to be determined by the size of the window
49  maxFreq = FrequencyDomain.GetComplexSampleFrequency(windowSize, windowSize / 2);
50  }
51 
52  //Limit Max Frquency by the size of the window
53  maxFreq = Math.Min(maxFreq, FrequencyDomain.GetComplexSampleFrequency(windowSize, windowSize / 2));
54 
55  //Limit Min Frequency by the
56  minFreq = Math.Max(minFreq, FrequencyDomain.GetComplexSampleFrequency(windowSize, 1));
57 
58  //Our output will be just the real-valued amplitudes
59  SpectralDecomp decomp = new SpectralDecomp(minFreq, maxFreq, windowSize, windowCount);
60 
61  Complex64[] fftBuffer = new Complex64[windowSize];
62 
63  IBGCEnvelopeStream hammingWindow = new EnvelopeConcatenator(
64  CosineEnvelope.HammingWindow(windowSize / 2, true),
65  CosineEnvelope.HammingWindow(windowSize / 2, false));
66 
67  for (int window = 0; window < windowCount; window++)
68  {
69  int specificOffset = sampleOffset * window;
70  hammingWindow.Reset();
71 
72  //Copy samples into buffer
73  for (int i = 0; i < windowSize; i++)
74  {
75  //Set real value
76  fftBuffer[i] = samples[specificOffset + i] * hammingWindow.ReadNextSample();
77  }
78 
79  Fourier.Forward(fftBuffer);
80 
81  decomp.Add(window, fftBuffer);
82  }
83 
84  return decomp;
85  }
void Reset()
Sets this internal state of this stream to the initial state
float ReadNextSample()
Returns the next sample in the BGCEnvelopeStream
Represents a complex number with double-precision floating point components
Definition: Complex64.cs:39
Support for Fourier Transforms. Borrows heavily from Mathnet.Numerics.
Definition: Fourier.cs:41
static void Forward(Complex32[] samples)
Definition: Fourier.cs:43
static CosineEnvelope HammingWindow(double duration, bool open)
Here is the call graph for this function:

The documentation for this class was generated from the following file: