Search Unity

Audio Generating a Simple Sinewave

Discussion in 'Audio & Video' started by zeekee, May 18, 2017.

  1. zeekee

    zeekee

    Joined:
    May 18, 2017
    Posts:
    5
    I've been racking my brain for a while trying to figure out how to do this, but... Essentially, I'd like to create a script that generates two sinewave tones that are panned both hard left and right. Ideally, I'd like to be able to change the frequency of each tone with a slider. Anyone have any ideas? I'm at a loss...
     
  2. MD_Reptile

    MD_Reptile

    Joined:
    Jan 19, 2012
    Posts:
    2,664
    Research AudioClip.SetData(), which should allow you to "create" audio, or modify existing audio.
     
    davidafrederick likes this.
  3. willemsenzo

    willemsenzo

    Joined:
    Nov 15, 2012
    Posts:
    585
    Hi zeekee. Here is an example you can try out. The script generates 2 sinewaves and sends each of them to their respective channel. I must add that I didn't test if it compiles rightaway, although it shouldn't be too hard to fix the errors (if any). If you have any questions or problems let me know.

    Code (csharp):
    1.  
    2. public class SinewaveExample : MonoBehaviour
    3. {
    4.     [Range(1,20000)]  //Creates a slider in the inspector
    5.     public float frequency1;
    6.  
    7.     [Range(1,20000)]  //Creates a slider in the inspector
    8.     public float frequency2;
    9.  
    10.     public float sampleRate = 44100;
    11.     public float waveLengthInSeconds = 2.0f;
    12.  
    13.     AudioSource audioSource;
    14.     int timeIndex = 0;
    15.  
    16.     void Start()
    17.     {
    18.         audioSource = gameObject.AddComponent<AudioSource>();
    19.         audioSource.playOnAwake = false;
    20.         audioSource.spatialBlend = 0; //force 2D sound
    21.         audioSource.Stop(); //avoids audiosource from starting to play automatically
    22.     }
    23.    
    24.     void Update()
    25.     {
    26.         if(Input.GetKeyDown(KeyCode.Space))
    27.         {
    28.             if(!audioSource.isPlaying)
    29.             {
    30.                 timeIndex = 0;  //resets timer before playing sound
    31.                 audioSource.Play();
    32.             }
    33.             else
    34.             {
    35.                 audioSource.Stop();
    36.             }
    37.         }
    38.     }
    39.    
    40.     void OnAudioFilterRead(float[] data, int channels)
    41.     {
    42.         for(int i = 0; i < data.Length; i+= channels)
    43.         {          
    44.             data[i] = CreateSine(timeIndex, frequency1, sampleRate);
    45.            
    46.             if(channels == 2)
    47.                 data[i+1] = CreateSine(timeIndex, frequency2, sampleRate);
    48.            
    49.             timeIndex++;
    50.            
    51.             //if timeIndex gets too big, reset it to 0
    52.             if(timeIndex >= (sampleRate * waveLengthInSeconds))
    53.             {
    54.                 timeIndex = 0;
    55.             }
    56.         }
    57.     }
    58.    
    59.     //Creates a sinewave
    60.     public float CreateSine(int timeIndex, float frequency, float sampleRate)
    61.     {
    62.         return Mathf.Sin(2 * Mathf.PI * timeIndex * frequency / sampleRate);
    63.     }
    64. }
    65.  
     
    toonsend, Adria0965, Cedebo and 13 others like this.
  4. zeekee

    zeekee

    Joined:
    May 18, 2017
    Posts:
    5
    Willemsenzo, that works great! This may sound like a stupid question, but how would I get the sinewave to play on a loop? Also, I tried associating the frequencies of each tone with slider objects in the hierarchy view, but I can't seem to get it to work.
     
  5. zeekee

    zeekee

    Joined:
    May 18, 2017
    Posts:
    5
    Actually, disregard the loop question, I just figured it out!
     
  6. zeekee

    zeekee

    Joined:
    May 18, 2017
    Posts:
    5
    I'm essentially looking to associate a Slider object in the Scene view to the frequency value in the script. I've tried adding the game object with the script attached to it in the hierarchy view to the "On value changed" submenu, but I can't seem to find the function that changes the value of the frequencies.

    On a side note, the script you made works really well, but it seems to be producing a monaural beat as opposed to a binaural beat. Would I use AudioSource.panStereo to remedy this? If so, how would I implement it? The reference page doesn't include an example.

    Also, thanks for bearing with me. I realize I have a lot to learn about Unity and am really appreciative of all the help :)
     
  7. mitchellson97

    mitchellson97

    Joined:
    Jan 12, 2016
    Posts:
    9
    Is anyone else experiencing a lot of background noise with this? a lot of popping, is there a way to get rid of this?
     
    yy404 likes this.
  8. seyeste

    seyeste

    Joined:
    Sep 29, 2018
    Posts:
    1
    thank !!
     
  9. jason416

    jason416

    Joined:
    Nov 8, 2018
    Posts:
    31
    yeah, I'm getting a clicking, popping if I'm updating the frequency (to create different notes). Have you found a solution?
     
    yy404 likes this.
  10. thieberson

    thieberson

    Joined:
    Mar 6, 2015
    Posts:
    5
    It Works great, but the volume is too low.
    There is a way to turn crate a wave in a higher volume?

    Thank you

     
  11. willemsenzo

    willemsenzo

    Joined:
    Nov 15, 2012
    Posts:
    585
    If you need higher volume, multiply the output of the GetSine function with some number. However you might want to check your audiosettings first because if it's low volume now then something probably isn't right on your end.
     
    thieberson likes this.
  12. levitate03

    levitate03

    Joined:
    Jan 11, 2016
    Posts:
    1
    @willemsenzo how would I go about playing custom waves? For instance, I have an animationCurve in my inspector that I've shaped like a square wave. What code should go inside the OnAudioFilterRead() method to play this curve like a sound wave?

    I thought I understood what I was doing and tried to write my wave to the data[] array, but this doesn't sound like I want it to.
    Code (CSharp):
    1. void OnAudioFilterRead(float[] data, int channels)
    2. {
    3.         for (int i = 0; i < data.Length; i += channels) {
    4.         float waveData = wave.Evaluate(i / 2048);
    5.         data[i] = waveData;
    6.         data[i + 1] = waveData;
    7.     }
    8. }
    Any idea how to do this?
     
  13. willemsenzo

    willemsenzo

    Joined:
    Nov 15, 2012
    Posts:
    585
    How do you want it to sound? If you set the time of the animation curve to 1, and you would divide by 44100 (or whatever your sampling rate may be) you end up with a 1 hertz sound which probably sounds like a low click or something. If you want more control on the frequency I suggest to use a function like this which would generate a square wave.

    Code (csharp):
    1.  
    2. float waveData = Mathf.Sign(Mathf.Sin(2 * Mathf.PI * timeCount * frequency / samplingRate));
    3.  
     
  14. yy404

    yy404

    Joined:
    Apr 19, 2020
    Posts:
    2
  15. crcdng

    crcdng

    Joined:
    Dec 22, 2017
    Posts:
    2
     
  16. JohanAR

    JohanAR

    Joined:
    Dec 26, 2016
    Posts:
    6
    It's probably caused by setting timeIndex to 0, but this example algorithm is also not suitable for changing frequency while the sound is playing. I've updated it to fix both things, but also made other changes for what I needed but it ought to be easy enough to add back the second channel if you want it.

    Code (CSharp):
    1.  
    2. public class SineTest : MonoBehaviour
    3. {
    4.     [Range(1,20000)]  //Creates a slider in the inspector
    5.     public float frequency = 100;
    6.  
    7.     public float sampleRate = 44100;
    8.  
    9.     float phase = 0;
    10.  
    11.     // ...I cut the rest of the functions because they are mostly unchanged...
    12.  
    13.     void OnAudioFilterRead(float[] data, int channels)
    14.     {
    15.         for(int i = 0 ; i < data.Length ; i += channels)
    16.         {  
    17.             phase += 2 * Mathf.PI * frequency / sampleRate;
    18.  
    19.             data[i] = Mathf.Sin(phase);
    20.  
    21.             if (phase >= 2 * Mathf.PI)
    22.             {
    23.                 phase -= 2 * Mathf.PI;
    24.             }
    25.         }
    26.     }
    27.  
    28. }
    29.  
     
  17. vlakdo

    vlakdo

    Joined:
    Jun 23, 2014
    Posts:
    2
    Hello, is this supported by WebGL?
     
  18. yy404

    yy404

    Joined:
    Apr 19, 2020
    Posts:
    2
  19. FMmutingMode

    FMmutingMode

    Joined:
    Feb 4, 2019
    Posts:
    5
    Hey guys,
    I'm currently working on a synth component to my drum machine for Android. I have basic Sine, Square, and Triangle waves set. I need help putting in variables that will modify the sound using sliders. Can anyone help with this?
     
    Strunden likes this.
  20. BachmannT

    BachmannT

    Joined:
    Nov 20, 2016
    Posts:
    388
    Hi, the free version of Maestro is able to play samples of drum ;-)
     
  21. fercmann

    fercmann

    Joined:
    Aug 21, 2019
    Posts:
    1
  22. Adria0965

    Adria0965

    Joined:
    Feb 2, 2024
    Posts:
    1