Audio Visualization - Unity/C# Tutorial [Part 4 - Eight Frequency Bands]

Поділитися
Вставка
  • Опубліковано 20 вер 2024

КОМЕНТАРІ • 123

  • @rickloyd8208
    @rickloyd8208 4 роки тому +26

    10:06 It's unclear why we should multiply samples by the index of the sample... that's for sure not a calculation of simple average of list of values.

  • @eliweston1857
    @eliweston1857 5 років тому +25

    In the middle of going through these videos and I just wanted to say I really appreciate what you've done here. I know it's been a few years, but this is still really helpful and honestly just really fun.

  • @NeilDonkin
    @NeilDonkin Рік тому +3

    Still getting value from these tutorials in 2023! Thanks for your hard work.

  • @guywitha-lotofcheese329
    @guywitha-lotofcheese329 7 місяців тому +3

    For anyone confused about the part when he multiplies _samples[count] * (count + 1) I can answer that. In Unity higher frequencies have exponentially smaller values, by multiplying by count, it offsets the smaller numbers that come with high frequencies. Making the output for the _freqBand more normal.

    • @PeerPlay
      @PeerPlay  7 місяців тому +2

      this answer! I may have left some parts of the code out in enough detail. Thanks.

  • @GeeCeeAte
    @GeeCeeAte Рік тому

    *edit!* - Disregard all of this, i paused and typed it halfway (about 8mins) because I thought you were about to assign them all manually according to the comments, but you did almost exactly this but way more elegant. Again thank you!
    public GameObject[] bars;
    private float[] frequencies;
    public float minFrequency = 20f;
    public float maxFrequency = 20000f;
    START
    float nyquistFrequency = AudioSettings.outputSampleRate / 2f;
    float frequencyStep = nyquistFrequency / (float)(bufferSize / 2);
    for (int i = 0; i < bars.Length; i++)
    {
    float barCenterFrequency = Mathf.Lerp(minFrequency, maxFrequency, (float)i / (float)(bars.Length - 1));
    frequencies[i] = Mathf.Round(barCenterFrequency / frequencyStep) * frequencyStep;
    }
    UPDATE
    for (int i = 0; i < bars.Length; i++)
    {
    int spectrumIndex = Mathf.RoundToInt(frequencies[i] / (AudioSettings.outputSampleRate / bufferSize));
    }
    This should give you an array of game objects. Then you drag whatever you want in there, and it will divide the frequencies up according to how many you have in there. if you debug log frequencies[i], it posts all the correct frequencies from min-max depending on the size of your array. Makes it easier instead of manually assigning freqs. I got this down over two or three days. but I needed your tutorial to help me to ACTUALLY understand how its sampling everything. Thank you so much for your tutorial and you have eased my headache! haha. Wish I would have thought to search youtube 3 days ago for a tutorial instead of trying to figure it out from scratch. Also, If you can figure out a better way to run this feel free to update it. I honestly have no idea what im really doing haha. So this code definitely isnt perfect or probably not even the right way to do it. its just what i came up with over a few days trying to assign freqs depending on the number if items in the array

  • @SpencerSaxey
    @SpencerSaxey 5 років тому

    Dividing the frequency bands like you did with 2^(n+1) is very elegant, and i appreciate that you did it this way instead of just making arbitrary manual separations as i probably would have done.

  • @virtuellgestalten3d
    @virtuellgestalten3d 2 роки тому

    Thank you for saying it took you some time to come up with this, I was worried for a second.
    Great tutorial series.

  • @stove777
    @stove777 7 років тому +6

    7:46 instead of multiplying by two, you can change the for loop declaration to (int i = 1; i

    • @V_2077
      @V_2077 6 років тому +4

      HEADS UP: If you follow this advice (like I have) be sure to change "if(i == 7)" to "if(i - 1 == 7)" and "_freqBand[i]" to "_freqBand[i - 1]"

  • @zhiyuanli9196
    @zhiyuanli9196 3 роки тому +6

    I am also confused about the multiply samples by the index of the sample. I change the code into this :
    int count = 0;
    for (int i = 0; i < 8; i++)
    {
    float average = 0;
    int sampleCount = (int)Mathf.Pow(2, i) * 2;
    if (i == 7)
    {
    sampleCount += 2;
    }
    for (int j = 0; j < sampleCount; j++)
    {
    average += _samples[count];
    count++;
    }
    average /= sampleCount;
    _freqBand[i] = average * 10;
    Is it also work? Can we discuss about that, I have no idea why you need to multiply the (count+1)

  • @hm8909
    @hm8909 3 роки тому

    Just wanted to thank you a lot for sharing your knowledge and making this tutorial! Very inspiring and empowering. I've subscribed and looking forward to following your other tutorials!

  • @muzboz
    @muzboz 6 років тому +6

    Awesome. :) [And yes, I was also wondering, why does one need to multiply by (count + 1) at 10:00 ???]

  • @jeremyfoo1107
    @jeremyfoo1107 7 років тому +2

    Thanks a lot! It helps a lot for my uni project!

  • @ZacharyAghaizu
    @ZacharyAghaizu 4 роки тому

    So so amazing to have found your tutorials!!!

  • @Mooooov0815
    @Mooooov0815 7 років тому +5

    This tutorial series is so unbelievable helpful, you saved my life! Your explanations are really good to understand, but I still have on question. I don't want to set the color of my objects according to the music rather than the transformation. My approach was to create a gradient object with a range from 0f-1f with 10 colors. But would it make sense to create 10 bands, so each channel has a gradient value range of 0.1? Or would a completely different approach work out better? Would appreciate your help!

    • @King-mj2bn
      @King-mj2bn 5 років тому

      I know this is an old comment, but for those that come across this with the same question, just normalize the range. To normalize an arbitrary range in unity, use Mathf.InverseLerp. (Or if using a simple range like 0-10, just divide by the max value of 10 to normalize it to the 0-1 range.)

  • @sleep0
    @sleep0 Рік тому

    Thanks you so much for this incredible tutorial series!!

  • @Tyler-ur2ig
    @Tyler-ur2ig 6 років тому +24

    Why does he multiply each sample by (Count+1)

    • @KoltronZer0
      @KoltronZer0 4 роки тому +2

      Came to the comments to find the answer to this, glad i'm not alone. I have no idea can someone please answer this?

    • @artemix1351
      @artemix1351 4 роки тому +6

      I think this increases the values of high frequencies. If you delete this, it will be too low (as in the 3rd part of the tutorial)

    • @KoltronZer0
      @KoltronZer0 4 роки тому +1

      @@artemix1351 thanks

    • @JamesBowling
      @JamesBowling 4 роки тому +2

      I’d like to know too, I don’t understand why you’d scale values differently in a band.
      As a simple example
      [1,0,0] = 1 / 3 = 0.33
      [0,1,0] = 2 / 3 = 0.66
      [0,0,1] = 3 / 3 = 1
      [1,1,1] = 6 / 3 = 2
      Unless I’m missing something here?
      If it is a case of needing to scale higher frequencies, then that's the kind of thing that should be mentioned, preferably commented. Just saying "average" is very confusing if you're looking to understand it, not just copy-paste it. Also, if it is scaling, it's not going to work very well. It's only scaling within the band, not the overall frequency range.

  • @张毅-d8h
    @张毅-d8h 4 роки тому

    Thanks a lot. Your project is really incredible.

  • @Applzor
    @Applzor 7 років тому +3

    I'm a little confused how the samples -> hertz works.
    If you write them out you get the following:
    0 - 43Hz
    1 - 86Hz
    2 - 129Hz
    3 - 172Hz
    4 - 215Hz
    5 - 258Hz
    ...
    12 - 516Hz
    Which would suggest having the bands as:
    0-1 - 43Hz-86Hz
    1-5 - 86Hz-258Hz
    5-12 258Hz-516Hz
    ... and so on

    • @Applzor
      @Applzor 7 років тому +2

      Okay I feel dumb, the first number on the left is just the band number...

    • @PeerPlay
      @PeerPlay  7 років тому +1

      Nicholas Z its ok, haha! I always ask questions too and figure it out myself a little later xD

  • @muzboz
    @muzboz 6 років тому +2

    re: the confusion about " * (count + 1)" ... I think the naming of a few variables here has caused some confusion, and it's actually a bit wrong.
    I renamed some of my variables:
    I renamed "count" to be "sampleID"
    I renamed "sampleCount" to be "samplesInThisBand"
    ...and things became clearer! I think that in the original code in the video, (count + 1) should have been (sampleCount + 1) ???
    Going off my renaming, the code would feature these lines:
    int sampleID =0 // at the top, instead of "count"
    int samplesInThisBand = (int)Mathf.Pow(2,i) * 2;
    for (int j = 0; j < samplesInThisBand; j++)
    {
    average += _samples[samplesInThisBand] * (sampleID + 1);
    sampleID++;
    }
    average /= samplesInThisBand;
    But then, I might be crazy! I'm a bit confused by the way the second array works.
    But it seems to be working pretty nicely for me that way.

    • @Despair1992
      @Despair1992 6 років тому +2

      _samples[samplesInThisBand] * (sampleID + 1); is wrong, cause for every j value you will always take same value from samples, and how then it can be average, if it analize only 1 value?) The idea is to take average from first 2 samples, then for next 4 samples etc, i mean average for [1-2], for [3-6], [7-14], [15-30]...

    • @JamesBowling
      @JamesBowling 4 роки тому

      @@Despair1992No, I'm fairly sure he's right. If we're working off the premise that the value needs to be scaled depending on how high it is, resetting that scale depending on the band index is going to ignore the overall position in the range (sample 0 will be scaled as 1, sample 255 will be scaled as 1).
      Honestly, the whole thing looks like a hack to me anyway because the average is dropping as the range gets bigger, but then I'm pretty new to this spectrum analysis thing.

  • @Despair1992
    @Despair1992 6 років тому +8

    average /= count ? It should be average /= sampleCount

    • @DoisKoh
      @DoisKoh 4 роки тому

      This is what I'm thinking exactly - so are we right or what? I'm trying to properly understand this instead of just getting results and all the weird stuff like adding count + 1 is confusing me.

  • @roarlisfang2860
    @roarlisfang2860 3 роки тому +1

    Don't quite understand the calculation of average for a band amplitude. For the average shouldn't we divide the total amplitude by sampleCount?

  • @nand3kudasai
    @nand3kudasai 2 роки тому

    alternatively
    readonly int[] samplesXBand = {2, 4, 8, 16, 32, 64, 128, 258}; (at the class level)
    for (int i = 0; i

  • @risingdeathx
    @risingdeathx 4 роки тому +1

    For those who want to be able to change the size of the frequency band, I made this very generic solution using linq. I think it's also easier to read:
    var chunk = sampleSize / bandSize;
    for (int i = 0; i < bandSize; i++)
    {
    bands[i] = samples.Skip(i * chunk).Take(chunk).Average();
    }

  • @Crisisdarkness
    @Crisisdarkness 6 років тому +3

    I'm curious about your studies, did you study a career related to sound engineering?

    • @PeerPlay
      @PeerPlay  6 років тому +17

      nope, never studied anything related to sound. All this is just me searching the internet for information, and trying things out, until they work. Self educated ;)

  • @Merlok_3_0
    @Merlok_3_0 2 роки тому +1

    can i get those numbers before the music even go to them?

  • @AtrociousGameDev
    @AtrociousGameDev Рік тому

    Is there a way to do this but get the average of the frequency bands in the start function instead of in realtime?

  • @trnogger
    @trnogger 7 років тому +1

    I guess you multiply by (count +1) in >> average += _samples [count] + (count+1);

    • @trnogger
      @trnogger 7 років тому

      EDIT: >> average += _samples [count] * (count+1);

    • @PeerPlay
      @PeerPlay  7 років тому +1

      Yes, that little part is actually still from earlier scripting before I figured out how to do the ranged values in part 6 of the tutorial. By multiplying the result of the values totals are all about in eachother ranges (the total of the average amounts).
      You could actually leave it out, and it should work too ;)

    • @trnogger
      @trnogger 7 років тому

      Yes, I thought so. I decided to only work with 0 to 1 values, in this case it probably makes sense to first convert the frequencies into the 0 to 1 range and then buffer them?

    • @jnzou9488
      @jnzou9488 7 років тому

      average /= count; Is the line a problem?every loop you set average = 0, but the count is bigger and bigger, so the value of higher frequency is lower.

    • @porureru2667
      @porureru2667 6 років тому

      I suppose it's too late, and you realized it already. But inside void MakeFrequencyBands(){} you have a "int count = 0;" before de first loop. I made the same mistake :P

  • @darkkevinkilleur25
    @darkkevinkilleur25 5 років тому +2

    Hey, my transform position y never changes so whenever the beat's upscaling a cube, it also upscales downwards and I don't want that. Any fix ?

  • @frikstobal
    @frikstobal 4 роки тому

    Dudeeeeeeee thank you so much!!!!

  • @alexseevideo
    @alexseevideo 7 років тому +4

    why can't i do it with 16 bands instead of 8 ?

    • @LabGecko
      @LabGecko 5 років тому +5

      You could. You would just need to modify the math to accommodate.

  • @danielwatson5547
    @danielwatson5547 3 роки тому

    How would this work with musical note detection? Tried making a banding for each distinct note on the keyboard but not sure it's working. I think my issue is that I'm using Mic detection as the audio clip with a frequency of 4096 with 8192 cubes giving 0.5Hz range per cube but high notes are not on the end of the spectrum - any ideas?

  • @Magick420
    @Magick420 6 років тому +1

    i love you man!))

  • @joeplukken1187
    @joeplukken1187 2 роки тому

    I f I wanted to make 16 frequency bands then I'd have to just change all 8's to a 16?

  • @taylorking7750
    @taylorking7750 6 років тому +1

    I have one issue with the parametric cube. It scales both up and down. How do I fix it to only scale up like it is suppose to?

    • @Lyoshiiro
      @Lyoshiiro 6 років тому +2

      parametric cube.transform.position = new vector3(0f, scaling value / 2, 0f);

  •  3 роки тому

    Am I correct that those bands could be caulculated onece, not in update?

  • @Nbanator
    @Nbanator 6 років тому

    I'm not sure if you still check comments over here, but I seem to have 2 issues which may, possibly, be related. 1) only about 3/4 of my circle seems to be doing anything. 2) I was getting array index errors in the "MakeFrequencyBands" function with the high end frequencies going beyond 512. Thoughts?

    • @Lyoshiiro
      @Lyoshiiro 6 років тому +1

      somewhere u follow the array size or smt, and for the 3/4 is natural cause songs dont make use of all frequencies. he mention it in the previous videos

  • @xmkmx1
    @xmkmx1 6 років тому

    Hi , since you are using a 22.05khz sample rate for your track, I am wondering why you are making bands for +10khz. I thought the maximum frequency output of a 22.05 khz audio file is 10khz. Wouldn't the last band be obsolete unless you are using a 44.1khz sample rate?

    • @LabGecko
      @LabGecko 5 років тому

      Yes, but it's at such a high sample rate that won't get hit often that it doesn't matter. But this is just for a visualization (pretty graphics). If you are using some of this code to actually modify sound files or something you probably want to work with the math & logic to get the numbers perfect.

  • @SaisBlade
    @SaisBlade 5 років тому

    Couldn't you have passed a sample array of length 8 to the GetSpectrumData function instead of averaging yourself? Or would that have grouped frequencies together differently?

    • @brandond193
      @brandond193 5 років тому

      If you do that, you get 8 bands of equal frequency width, which you don't want.

    • @SaisBlade
      @SaisBlade 5 років тому

      @@brandond193 you could scale the result after though. But I think Unity only lets you pick powers of two >=64 as array sizes, so you would have to average yourself anyway

  • @jerxvan1
    @jerxvan1 7 років тому +4

    question sir,
    how u know your song is 22050 hz ??
    or every song is 22050hz ?

    • @jerxvan1
      @jerxvan1 7 років тому +4

      oo nevermind, unity actually give information about your fsong frequency

    • @StarOnCheek
      @StarOnCheek 5 років тому +4

      @@jerxvan1 also all music is 22050hz and as a music producer I'll tell you something, usually, we cut everything above 18000hz because most people can't hear it and it only adds extra weight to the audio file so you shouldn't visualize above 18khz. Yes, there is some audio information up there but it is most likely compression noise.

    • @StarOnCheek
      @StarOnCheek 5 років тому +4

      oh and the same applies to the low end. You'll hardly ever find songs that go below 40hz, this time not because people can't hear it. but because most speakers can't play lower than 40hz.

    • @jerxvan1
      @jerxvan1 5 років тому

      @@StarOnCheek thanks you for the nice information sir 👍

    • @IDontReadReplies42069
      @IDontReadReplies42069 Рік тому

      @@StarOnCheek wrong, sub bases are in 20hz

  • @bryanmartinez19
    @bryanmartinez19 7 років тому

    What if the audio is came from a microphone ? I set my audio source : audio clip to the microphone input. Thanks for any response

    • @PeerPlay
      @PeerPlay  7 років тому +1

      ua-cam.com/video/rnZ52SlVJj8/v-deo.html Watch this new series I'm creating, after finishing this tutorial ;)

    • @bryanmartinez19
      @bryanmartinez19 7 років тому

      Thanks for quick reply :)
      btw, i use 2d cube. Nothin happen to the cube when I start speaking in microphone. Any suggestion ? thanks in advance

  • @Fire321Star
    @Fire321Star 5 років тому

    Can anyone here help me? I have followed this tutorial series and there is a very big possibility that I've just typed something wrong, idk I'm re-watching it anyways, but my problem is that everytime I press play, I get "IndexOutOfRangeException" errors. The error message says that this is being caused by something in the "MakeFrequencyBands" function. I've gone over the code and so far ha ent found any typos on my end. Any help would be greatly appreciated.

    • @PeerPlay
      @PeerPlay  5 років тому

      IndexOutOfRangeException is always about either a loop that is too long, or an array that hasn't been set to the correct length. You should be getting a line number as error aswell. You can then look at that line, and see which arrays it is talking to, so you know what arraysize the problem is.

    • @Fire321Star
      @Fire321Star 5 років тому

      @@PeerPlay is there a way I can pm you or email you a photo? I know what line is causing it, but I cant figure out why. I'm still fairly new to coding.

    • @Fire321Star
      @Fire321Star 5 років тому

      @@PeerPlay as far as I can tell, it's talking to the left and right sample arrays.

  • @davidjelinek7821
    @davidjelinek7821 5 років тому

    HI, I am missing the Parametric Cube avatar for the animator can someone help me please?

    • @huk25ph
      @huk25ph 5 років тому

      It is stored in _Mesh folder and loads up automatically when you put folder in the unity project assets.

  • @alishafique421
    @alishafique421 6 років тому

    Hi, the Audio files that I am using have a frequency of 44.1 khz. What changes will I have to make to my code for this?
    ...pls help

    • @Despair1992
      @Despair1992 6 років тому

      your file is 44.1, so its 22050 hz per channel (left right), just like in this video, no changes! (we analize only 1 channel for visualization here)

    • @Despair1992
      @Despair1992 6 років тому

      Oops, I guess I said bullshit, but that’s not for sure. As I understand now, 44.1 khz is 44100 samples per second for ONE channel, so if song is stereo, file actually contains 2 times more samples, 44100 for left and 44100 for right. But that 44100 samples per second describe frequency's up to 22050 hz, cause one clever man proved that it's enough 2 times more samples for describing some frequency. I am not sure about anything i said, I'm trying to figure it out myself now :D

    • @alishafique421
      @alishafique421 6 років тому

      Despair1992 Thanks, let me know if you figure something out

    • @Despair1992
      @Despair1992 6 років тому +1

      medium.com/giant-scam/algorithmic-beat-mapping-in-unity-preprocessed-audio-analysis-d41c339c135a

  • @utsabdas6331
    @utsabdas6331 7 років тому

    The music I'm loading shows a frequency of 44100. Is there a reason for this? Have I missed something?

    • @PeerPlay
      @PeerPlay  7 років тому

      No, i haven't covered this, 44.1k is an industry standard based on the Nyquist-Shannon sampling theorem.
      The human hearing is still between 20 - 20000hz. Here's some more info:
      en.wikipedia.org/wiki/44,100_Hz

    • @utsabdas6331
      @utsabdas6331 7 років тому +1

      Thanks Peter! As a follow up, since the music shows a frequency of 44100, should I still split it into Frequency Bands in the same way done in this video?

    • @xmkmx1
      @xmkmx1 6 років тому +1

      Hi, if you are still interested regarding the code for 44.1khz files let me know.
      Cheers

    • @Luigi1996ish
      @Luigi1996ish 6 років тому

      I'm still confused, using AudioSettings.outputSampleRate I'm getting a value of 48000?!
      But what I'd like is to band the frequencies to the 7 bands there are instead of 8 bands so that each band shows its specific frequency. I'd like to take 1024 samples for both left and right channels.
      My uni final year project is to make beat detection software which can create a basic step file for StepMania and then I'll make my own simpler version of StepMania. I need there to be only the 7 bands so I can apply a basic beat detection algorithm to each band.
      Your tutorials are really good by the way :)

  • @Acrozi
    @Acrozi 5 років тому

    I cant get it to work, I copied the code line for line it just wont go to the music in Unity

    • @TheTca211
      @TheTca211 5 років тому +1

      I am having the same problem. Did you solve it?

    • @brain_apostrophe_t
      @brain_apostrophe_t 3 роки тому

      same here, and Ive triple checked my code as well

    • @brain_apostrophe_t
      @brain_apostrophe_t 3 роки тому

      ok, I fixed mine. nothing amazing, I had jsut mixed up my 0 with 8 cause of poor eyesight. I doubt this will help you but hey, maybe its worth a double check

  • @dominikkomar9170
    @dominikkomar9170 3 роки тому

    My cubes all act the same... for the line of 8 cubes, they all jump at the exact same time xd

  • @tango6x192
    @tango6x192 7 років тому

    I have done all the scripts and my cubes are not doing anything help would be appreciated thank you :)

    • @aurorarose9727
      @aurorarose9727 6 років тому

      TheBlitzingFerret Gaming did you add the main script “AudioPeer” to the audiosource

    • @FirahFabe
      @FirahFabe 6 років тому

      I'm having this same problem, yes to the "AudioPeer" in audiosource as well

    • @FirahFabe
      @FirahFabe 6 років тому +1

      Never mind, I found it. I missed one part of the code in "AudioPeer" of calling "MakeFrequencyBands();" in the Update() function.

    • @JustGotHeated
      @JustGotHeated 5 років тому

      FirahFabe I missed the same thing, thanks for calling that out

  • @ale-hl8pg
    @ale-hl8pg 4 роки тому

    Is 22050 the peak frequency or..?

  • @hyungtaecf
    @hyungtaecf 4 роки тому

    Firstly, thanks for the tutorial!
    I didn't understand why the samples need to be 512. Why can't it be 510 already?

    • @tobiasseubert3511
      @tobiasseubert3511 4 роки тому +2

      The sample array needs to be a power of 2
      (docs.unity3d.com/ScriptReference/AudioSource.GetSpectrumData.html)

  • @themannyzaur
    @themannyzaur 6 років тому

    What song is that at the end??

  • @НикитаМордвинцев-у6ю

    OOOUE I will did my MusicPlayer