Skip to content

Instantly share code, notes, and snippets.

@shiena
Last active June 6, 2018 14:09
Show Gist options
  • Save shiena/78ce11495d0e4ef8e9d9371660ca9ec7 to your computer and use it in GitHub Desktop.
Save shiena/78ce11495d0e4ef8e9d9371660ca9ec7 to your computer and use it in GitHub Desktop.
UnityでProcedual Audio
/*
* refs
* http://tips.hecomi.com/entry/2014/11/11/021147
* http://d.hatena.ne.jp/nakamura001/20120724/1343148980
* https://gist.github.com/keijiro/3806478
* https://codepen.io/DavidSabine/pen/kyAlJ
* https://femurdesign.com/theremin/
*/
using UnityEngine;
using UnityEngine.UI;
[RequireComponent(typeof(AudioSource))]
public class Sinus : MonoBehaviour
{
const float PI2 = Mathf.PI * 2;
const float PI_2 = Mathf.PI / 2.0f;
public Text toggle;
[Range(55, 1760)]
public float frequency = 440;
public float gain = 0.4f;
private float increment;
private float phase;
private float sampling_frequency = 44100;
private bool playing = false;
private AudioSource audio_;
void Awake()
{
// オーディオ出力設定、44100 Hz がデフォルト
sampling_frequency = AudioSettings.outputSampleRate;
audio_ = GetComponent<AudioSource>();
audio_.clip = AudioClip.Create("(null)", 44100, 1, 44100, true, (data) => { });
audio_.loop = true;
}
/// <summary>
/// If OnAudioFilterRead is implemented, Unity will insert a custom filter into the
/// audio DSP chain.
/// </summary>
/// <param name="data">An array of floats comprising the audio data.</param>
/// <param name="channels">An int that stores the number of channels
/// of audio data passed to this delegate.</param>
void SineWave(float[] data, int channels)
{
// update increment in case frequency has changed
increment = frequency * 2 * Mathf.PI / sampling_frequency;
for (var i = 0; i < data.Length; i += channels)
{
phase += increment;
data[i] = gain * Mathf.Sin(phase);
// if we have stereo, we copy the mono data to each channel
if (channels == 2)
{
data[i + 1] = data[i];
}
if (phase > 2 * Mathf.PI)
{
phase = 0;
}
}
}
void SquareWave(float[] data, int channels)
{
increment = frequency * 2 * Mathf.PI / sampling_frequency;
for (var i = 0; i < data.Length; i = i + channels)
{
phase += increment;
data[i] = (float)(gain * ((phase % PI2) < PI2 * 0.5 ? 1.0 : -1.0));
if (channels == 2)
{
data[i + 1] = data[i];
}
if (phase > 2 * Mathf.PI)
{
phase = 0;
}
}
}
void OnAudioFilterRead(float[] data, int channels)
{
if (!playing)
{
return;
}
SineWave(data, channels);
}
public void TogglePlay()
{
if (playing)
{
audio_.Stop();
toggle.text = "Play";
}
else
{
audio_.Play();
toggle.text = "Stop";
}
playing = !playing;
}
public void SetFrequency(float f)
{
frequency = f;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment