Derek Leidemann
Derek Leidemann

Reputation: 41

Pre-processing Audio Spectrum Data in Unity

I'm trying to pre-process a song and implement some beat detection before playing the song (not in real-time as the song plays). My basic idea is to sample the spectrum data at about 90 times per second and I'm trying to do that by incrementing AudioSource.timeSamples by a value and making calls to AudioSource.GetSpectrumData(). But the array I supply always seems to be filled with the same values.

It seems like setting timeSamples isn't actually updating the sample being used by the AudioSource. However, if I play the song normally and make calls to GetSpectrumData() my array is filled with the correct data as I would expect.

Is there something I can do to make AudioSource use the sample that is set in timeSamples when I make the call to GetSpectrumData(), or some other way I should be parsing through the song to get this data?

Thanks

Here's a code sample (song is an AudioSource), the 2nd for loop is the area of interest:

float[][] get_spectrum_data()
{
    int samples = song.clip.samples;
    int sample_rate = song.clip.frequency / parse_rate;
    int arr_siz = samples / sample_rate;
    FFTWindow win = FFTWindow.Rectangular;  //which type do we want?

    float[][] spectrum = new float[arr_siz][];
    for (int i = 0; i < arr_siz; i++)
    {
        spectrum[i] = new float[spec_res];
    }

    for (int i = 1, j = 0; j < arr_siz; i += sample_rate, j++)
    {
        song.timeSamples = i;
        song.GetSpectrumData(spectrum[j], 0, win);
    }

    return spectrum;
}

Upvotes: 4

Views: 2230

Answers (1)

Daniel Rothmann
Daniel Rothmann

Reputation: 46

I think AudioSource.GetSpectrumData relies on the AudioSource currently being engaged in playback. My guess is that it is sampling from the audio thread instead of the clip itself, since a user might also have added subsequent audio filters. Try explicitly playing the clip in your loop:

for (int i = 1, j = 0; j < arr_siz; i += sample_rate, j++)
{
    song.Play();
    song.timeSamples = i;
    song.GetSpectrumData(spectrum[j], 0, win);
}

Upvotes: 1

Related Questions