- Home /
How exactly does AudioClip.Create() work?
I'm using AudioClip.Create() to create procedural tones. Using the example provided it is functional and I've been able to implement my own tones, but I want to take it further and I'm not understanding what the callback functions are doing or why I should be using this function at all!
My first question is in regards to the 'frequency' argument within Create(). Why does it accept a frequency if you make the frequency yourself inside the OnAudioRead() callback function? What baffles me further is that even though I'm overriding the frequency (or so I thought) within the OnAudioRead() using a standard sine wave input for the audio data, the frequency argument seems to affect the pitch.
OnAudioRead() appears to be called 12 times when using AudioClip.Create() with the following parameters: ("Sine Tone", 44100, 1, 44100, false, false, OnAudioRead, OnAudioSetPosition) Is there any reason that it needs to be called 12 times? I think there's something I don't understand about the callbacks in general. The 'position' integer also makes little sense to me. What is this meant to be doing!?
Here's the code for reference:
using UnityEngine;
using System.Collections;
public class ToneGenerator : MonoBehaviour {
private AudioClip[] tones;
private AudioSource audioSource;
private int position = 0;
private int sampleRate = 0;
private float frequency = 0;
void Start ()
{
//Audio properties
audioSource = gameObject.AddComponent<AudioSource>();
audio.volume = 0;
audio.loop = true;
GenerateTones();
}
void GenerateTones ()
{
tones = new AudioClip[4];
//Generate the tones
sampleRate = 44100;
frequency = 440f;
tones[0] = AudioClip.Create("Saw Tone", 44100, 1, 44100, false, false, OnAudioRead, OnAudioSetPosition);
frequency = 300f;
tones[1] = AudioClip.Create("Saw Tone", 44100, 2, 44100, false, false, OnAudioRead, OnAudioSetPosition);
frequency = 200f;
tones[2] = AudioClip.Create("Saw Tone", 44100, 2, 44100, false, false, OnAudioRead, OnAudioSetPosition);
frequency = 500f;
tones[3] = AudioClip.Create("Saw Tone", 44100, 2, 44100, false, false, OnAudioRead, OnAudioSetPosition);
}
void OnAudioRead(float[] data)
{
for(int i = 0; i < data.Length; i++)
{
switch (wave)
{
case waveType.Sine:
data[i] = Mathf.Sin(2 * Mathf.PI * frequency * position / sampleRate);
break;
case waveType.Sawtooth:
data[i] = (Mathf.PingPong(frequency * position / sampleRate, 0.5f));
break;
case waveType.Square:
data[i] = Mathf.Sign(Mathf.Sin(2 * Mathf.PI * frequency * position / sampleRate)) * 0.5f;
break;
case waveType.Noise:
data[i] = Mathf.PerlinNoise(frequency * position / sampleRate, 0);
break;
}
position++;
}
}
void OnAudioSetPosition(int newPosition)
{
position = newPosition;
}
}
Thanks for any advice or resources!
Answer by drudiverse · Nov 12, 2014 at 12:03 PM
Sorry i didnt see this earlier. If you change the sample rate, it is like changing the pitch, because, the audio playback rate of audio files is normally set to 44k or 22k or whatever, so if you cram more sine dots into the same space, it will be higher.
Question1 why does it make a frequency...
the freq in audioclip.create is the number of dots per second recorded onto the audio file, in other words, it tells the audio files that it's supposed to have 44k dots/samples per second. it's standard audio technology.
The freq of the sine wave, is the number of wobbles per second multiploed onto the sine wave, i.e. the freq of the sine wave encoded into the 44k dots, each dot is a value of sin on a graph at 44k
i dunno why it is called 12 times, i found if i make the sample longer in seconds, it's called more times, i get this printout from the example file: 9 reads from create function, 9 reads from play() function, and 8 reads from some other print whose line isnt declared.
perhaps its processing audio blocks.
actually i just ran the reference code with sample length 200 i.e. 20ms, and it printed 300 times.
well noticed! very bizarre.
i figure it's something to do with audio memory blocks
i just tried a 10 second file, it did 9, 18, and 45 prints on seperate lines, but he 45 printed slowly over the course of playback.
dunny why the create stuff runs in playback! weird.
i want to use the stream option anyways.
if you print the data length of elements called in the function, you will see that each data[] is 4096, so if you make 4096 samples, it calls the maths fct once, plus 8 times for some other... it may vary on different platforms, 4096, 2048 etc.
Answer by Graham-Dunnett · Apr 28, 2013 at 03:33 PM
Just use the first documented AudioClip.Create
function, then the AudioClip.SetData
one to populate the clip.
Is there any reason why there's a more complex constructor with the callbacks? Is it more efficient in any way? I'm not having so much trouble getting it working, I'm more just curious as to what it's doing behind the magic!
Answer by astracat111 · Oct 28, 2016 at 07:51 AM
Here's what I used to create an empty clip (the method I mean):
public static AudioClip AudioClipCreateEmpty(string ClipName, int Length) {
AudioClip AudioClipToReturn = AudioClip.Create (ClipName, Length, 1, 44100*2,false);
return AudioClipToReturn;
}
Your answer
Follow this Question
Related Questions
Audio on object plays low in unity 5 1 Answer
Array of AudioClips not playing, please help 3 Answers
Best way to transfer audio clips? 0 Answers