Created
May 7, 2022 08:06
-
-
Save Starpelly/7f14e9ed31f773991b529fb28fe42610 to your computer and use it in GitHub Desktop.
Oscillioscope in Unity using the Shapes plugin. (Can also be used with the default Line Renderer)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Created by Starpelly, based on the FL STUDIO oscillator | |
using UnityEngine; | |
using Shapes; | |
public class Oscillator : MonoBehaviour | |
{ | |
public int lengthOfLineRenderer = 16384; | |
public float thickness; | |
public float strength; | |
private Polyline polyline; | |
public AudioSource source; | |
[Header("Testing")] | |
public bool testing; | |
public double frequency = 400.0; | |
private double increment; | |
private double phase; | |
private readonly double sampleRate = 48000.0; | |
[Range(0, 32)] | |
public double gain = 0.5; | |
[Range(0, 32)] | |
public double c = 32; | |
[Range(-32, 32)] | |
public double ind = 1; | |
public double z = 5; | |
[Range(0, 8)] | |
public byte choice = 0; | |
void Start() | |
{ | |
polyline = transform.GetChild(0).GetComponent<Polyline>(); | |
polyline.Closed = false; | |
for (int i = 0; i < lengthOfLineRenderer; i++) | |
{ | |
PolylinePoint polylinePoint = new PolylinePoint(); | |
polylinePoint.color = Color.white; | |
polylinePoint.thickness = thickness; | |
polyline.points.Add(polylinePoint); | |
} | |
} | |
void LateUpdate() | |
{ | |
float[] samples = new float[lengthOfLineRenderer]; | |
source.GetOutputData(samples, 0); | |
for (int i = 0; i < lengthOfLineRenderer; i++) | |
{ | |
polyline.SetPointPosition(i, new Vector3(i * 0.5f, samples[i] * strength, 0.0f)); | |
} | |
} | |
private void OnAudioFilterRead(float[] data, int channels) | |
{ | |
if (!testing) return; | |
increment = frequency * 2.0 * Mathf.PI / sampleRate; | |
for (int i = 0; i < data.Length - 1; i += channels) | |
{ | |
switch (choice) | |
{ | |
case 0: //sawtooth | |
for (float j = Mathf.Floor((float)ind); j < c; j++) | |
{ | |
data[i] += (float)(gain * (Mathf.Sin((float)(phase * j)) / j)); | |
} | |
break; | |
case 1: //square | |
for (float j = Mathf.Floor((float)ind); j < c; j++) | |
{ | |
data[i] += (float)(gain * (Mathf.Sin((float)(phase * (2 * j - 1))) / (2 * j - 1))); | |
} | |
break; | |
case 2: //triangle | |
for (float j = Mathf.Floor((float)ind); j < c; j++) | |
{ | |
data[i] += (float)(gain * (Mathf.Sin((float)(phase * (2 * j - 1) + Mathf.PI * ((j + 1) % 2)))) / Mathf.Pow((2 * j - 1), 2)); | |
} | |
break; | |
case 3: //harmonics | |
for (int j = (int)Mathf.Floor((float)ind); j < c; j++) | |
{ | |
data[i] += (float)(gain * (Mathf.Cos((float)(j * phase + z)))); | |
} | |
break; | |
default: //sine | |
data[i] = (float)(gain * Mathf.Sin((float)phase)); | |
break; | |
} | |
phase += increment; | |
if (channels == 2) | |
{ | |
data[i + 1] = data[i]; | |
// ring mod: Mathf.Sin((float)((Mathf.Pow((float)(phase * j), 3)) * frequency / sampleRate)); data[i] += (float)(gain * (Mathf.Sin((float)((Mathf.Pow((float)(phase * j), 3)))))); | |
// sawtooth: data[i] += (float)(gain * (Mathf.Sin((float)(phase * j)) / j)); | |
// square: data[i] += (float)(gain * (Mathf.Sin((float)(phase * (2 * j - 1))) / (2* j - 1))); | |
// triangle: data[i] += (float)(gain * (Mathf.Sin((float)(phase * (2 * j - 1) + Mathf.PI * ((j + 1) % 2)))) / Mathf.Pow((2 * j - 1), 2)); | |
// accidental bitcrushed sine: data[i] += (float)(gain * (Mathf.Cos((float)(2 * Mathf.PI * frequency * phase + Mathf.Pow((float)1.618034, j - 1))))); | |
// harsh squares depending on frequency: data[i] += (float)(gain * (Mathf.Cos((float)(2 * Mathf.PI * frequency * phase + z)))); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment