CRIWARE Unity Plugin Manual  Last Updated: 2024-07-12
Converting the spectrum analysis results to log frequency scale
The spectrum analysis results from CriWare.CriAtomExPlayerOutputAnalyzer are stored in linearly-spaced frequency bands (from 0 to half the output's sample rate). The number of bands is defined in the config.
For example, on a platform with an output sample rate of 48 kHz, if an analysis is performed on 8 bands (which is the default value), the first band will contain information about all frequencies from 0 to about 3 kHz. This means that a detailed understanding of the sound spectrum may be hard to achieve due to the lack of precision in the lower frequencies.
We explain below how to get analysis results with frequency bands on a logarithmic scale, like in most commercially available spectrum analyzers.

1.Create a CriAtomExPlayerOutputAnalyzer with the maximum accuracy available
Create a CriWare.CriAtomExPlayerOutputAnalyzer with the maximum number of bands you can specify(512).
This value is defined by CriWare.CriAtomExPlayerOutputAnalyzer::MaximumSpectrumBands .

2. Get the analysis results and rearrange them on a logarithmic scale
Call CriWare.CriAtomExPlayerOutputAnalyzer::GetSpectrumLevels to get the analysis results in linearly-spaced frequency bands. Then redistribute them in logarithmically-spaced frequency bands.

The sample code below demonstrates how to rearrange the results into 16 logarithmically-spaced frequency bands.
It also converts the amplitude of each band in dB.
public class ExampleScript : MonoBehaviour {
/* CriAtomSource to be analyzed */
public CriAtomSource atomSource;
/* Number of bands in the output spectrum after analysis */
public int outputSpectrumBands = 8;
private CriAtomExPlayerOutputAnalyzer analyzer;
private float[] linearSpectrumLevels;
private float[] logSpectrumLevels;
void Start ()
{
CriAtomExPlayerOutputAnalyzer.Type[] analyzerType = new CriAtomExPlayerOutputAnalyzer.Type[1];
CriAtomExPlayerOutputAnalyzer.Config[] analyzerConfig = new CriAtomExPlayerOutputAnalyzer.Config[1];
/* Create a spectrum analyzer with the maximum number of bands */
analyzerType[0] = CriAtomExPlayerOutputAnalyzer.Type.SpectrumAnalyzer;
analyzerConfig[0] = new CriAtomExPlayerOutputAnalyzer.Config(CriAtomExPlayerOutputAnalyzer.MaximumSpectrumBands);
this.analyzer = new CriAtomExPlayerOutputAnalyzer(analyzerType, analyzerConfig);
/* Attach the analyzer to the CriAtomSource */
this.atomSource.AttachToAnalyzer(analyzer);
/* Allocate an array to store the results of the CriAtomExPlayerOutputAnalyzer */
linearSpectrumLevels = new float[CriAtomExPlayerOutputAnalyzer.MaximumSpectrumBands];
/* Allocate an array to store the results in a logarithmic scale */
logSpectrumLevels = new float[outputSpectrumBands];
}
void OnDestroy()
{
this.analyzer.DetachExPlayer();
this.analyzer.Dispose();
}
void Update ()
{
/* Get the spectrum analysis result */
analyzer.GetSpectrumLevels(ref linearSpectrumLevels);
/* Re-arrange the results on a logarithmic scale */
SplitBandsOnLogScale(ref linearSpectrumLevels, ref logSpectrumLevels);
/* Convert from amplitude values to decibel values */
for (int i = 0; i < logSpectrumLevels.Length; i++) {
logSpectrumLevels[i] = 20.0f * Mathf.Log10(logSpectrumLevels[i]);
}
}
/* Rearrange the linearly-spaced bands on a logarithmic scale */
private bool SplitBandsOnLogScale(ref float[] iLinearLvs, ref float[] oLogLvs)
{
if (iLinearLvs == null || oLogLvs == null )
return false;
float lowBand, highBand, tmpVal;
int lowBandIdx, highBandIdx, i, j;
int iBandCnt = iLinearLvs.Length;
int oBandCnt = oLogLvs.Length;
for (i = 0; i < oBandCnt; ++i)
{
/* Find the range of this band (min and max frequencies) on the logarithmic scale */
lowBand = Mathf.Pow((float)iBandCnt, (float)i / (float)oBandCnt);
highBand = Mathf.Pow((float)iBandCnt, (float)(i + 1) / (float)oBandCnt);
/* Round both ends */
lowBandIdx = Mathf.FloorToInt(lowBand) - 1;
highBandIdx = Mathf.FloorToInt(highBand) - 1;
/* Add the levels from the relevant linear bands to this band and calculate the average*/
tmpVal = 0;
for (j = lowBandIdx; j <= highBandIdx; ++j) {
tmpVal += iLinearLvs[j];
}
tmpVal = tmpVal / (float)(highBandIdx - lowBandIdx + 1);
/* Output logarithmic level value */
oLogLvs[i] = tmpVal;
}
return true;
}
/* Get the amplitudes in dB of the logarithmically-spaced bands */
public void GetSpectrumLevels(out float[] result)
{
result = this.logSpectrumLevels;
}
}