/* * Keep our waveform in bounds */ void WrapPhaseIfNeeded(int index, bsgbryan.ConfigieMcWaveface configie) { if (configie.Phases[index] > (2 * Mathf.PI)) { configie.Phases[index] -= 2 * Mathf.PI; } }
private static void NewWaveform() { string path = EditorUtility.SaveFilePanelInProject( "New Waveform", "Waveforms", "asset", "What do you want to name this new Waveform?"); if (path != "") { ConfigieMcWaveface configie = (ConfigieMcWaveface)ScriptableObject.CreateInstance <ConfigieMcWaveface>(); configie.Volume.Level = 0.5f; configie.WaveVolumes.Selected[0] = 1f; configie.PlayControls.LowOctave = 2; configie.PlayControls.HighOctave = 7; configie.PlayControls.CurrentOctave = 4; configie.PlayControls.NoteIndex = 9; configie.Envelope.Attack.Curve = AnimationCurve.EaseInOut(0f, 0f, 1f, 1f); configie.Envelope.Attack.Time = 200; configie.Envelope.Decay.Curve = AnimationCurve.EaseInOut(0f, 1f, 1f, 0f); configie.Envelope.Decay.Time = 1000; configie.Harmonics.Enabled = true; configie.Harmonics.LowerCurve = AnimationCurve.EaseInOut(0f, 0.5f, 1f, 1f); configie.Harmonics.UpperCurve = AnimationCurve.EaseInOut(0f, 0.5f, 1f, 0f); configie.FrequencyLimit.Curve = AnimationCurve.EaseInOut(0f, 1f, 1f, 1f); configie.WibbleWobble.Curve = AnimationCurve.EaseInOut(0f, 0.5f, 1f, 0.5f); configie.Noise.Variance.Min = 0.25f; configie.Noise.Variance.Max = 0.75f; configie.Noise.Level = 0.5f; configie.Noise.Curve = AnimationCurve.EaseInOut(0f, 0.5f, 1f, 0.5f); AssetDatabase.CreateAsset(configie, path); AssetDatabase.Refresh(); AssetDatabase.SaveAssets(); char[] path_delimiters = { '/' }; char[] name_delimiters = { '.' }; string[] path_tokens = path.Split(path_delimiters); string[] name_tokens = path_tokens[path_tokens.Length - 1].Split(name_delimiters); GameObject new_waveform = new GameObject(name_tokens[0]); new_waveform.AddComponent <AudioSource>(); bsgbryan.WavyMcFormface wavy = new_waveform.AddComponent <bsgbryan.WavyMcFormface>() as bsgbryan.WavyMcFormface; wavy.Configie = configie; } }
/* * Set each of our four available WaveVolumes as Selected */ float ProcessWaveVolumes(int octave, float amp, bsgbryan.ConfigieMcWaveface configie) { float output = 0f; for (int w = 0; w < waves.Length; w++) { float vol = configie.WaveVolumes.CurrentSelected[w]; output += waves[w].Generate(configie.Phases[octave], amp * vol); } return(output); }
float ApplyNoise(float pass, bsgbryan.ConfigieMcWaveface configie) { float noise = (float)rand.NextDouble(); if (noise >= configie.Noise.Variance.CurrentMin && noise <= configie.Noise.Variance.CurrentMax) { noise = noise - (noise * 0.5f); float curve = configie.Noise.CurrentCurve.Evaluate(pass); return((noise + curve) * configie.Noise.CurrentLevel); } else { return(0f); } }
/* * Modify our core note tone by applying any Enabled processors, taking the * range of rendered octaves into consideration */ float ProcessNote(int note_index, float octave, float rise, float position, float volume_adjust, float pass, bsgbryan.ConfigieMcWaveface configie) { float limit = 1f; float note = configie.Notes[note_index] * DetermineOctave(octave); if (configie.WibbleWobble.Enabled == true && configie.WibbleWobble.Time.Value > 0) { note *= ApplyWibbleWobble(configie, position); } if (configie.Noise.Enabled == true) { note += note * ApplyNoise(pass, configie); } configie.Phases[(int)octave] += DetermineIncrement(note, configie); float high = configie.PlayControls.HighOctave + 1; float low = configie.PlayControls.LowOctave; float range = high - low; float vol = configie.Volume.CurrentLevel; // Debug.Log("volume " + vol); if (configie.FrequencyLimit.Enabled == true) { limit = configie.FrequencyLimit.CurrentCurve.Evaluate((octave - low) / range); } float amp = Amplitude(vol, volume_adjust) * rise; float mod = 1f / range; WrapPhaseIfNeeded((int)octave, configie); return(ProcessWaveVolumes((int)octave, amp, configie) * limit * vol * mod); }
/* * This is where the magic happens! * * This method uses the input provided to generate and return the amplitude * value for the current data slice being processed (from WavyMcFormface.OnAudioFilterRead). * * This method is called once for each iteration through the OnAudioFilterRead's * data array. The value returned from this method is assigned to the appropriate * element of the data array. */ public float Evaluate(int note_index, float octave, float rise, float position, float pass, bsgbryan.ConfigieMcWaveface configie) { float generated_amplitude = 0f; if (configie.Harmonics.Enabled == true) { float low = (float)configie.PlayControls.LowOctave; float high = (float)configie.PlayControls.HighOctave; float upper_limit = configie.PlayControls.HighOctave + 1f; for (float current = low; current < upper_limit; current++) { float volume_adjust = 1f; if (current < octave) { volume_adjust = configie.Harmonics.CurrentLowerCurve.Evaluate(current / octave); } else if (current > octave) { volume_adjust = configie.Harmonics.CurrentUpperCurve.Evaluate(current / high); } generated_amplitude += ProcessNote(note_index, current, rise, position, volume_adjust, pass, configie); } } else { generated_amplitude = ProcessNote(note_index, octave, rise, position, 1f, pass, configie); } return(generated_amplitude); }
/* * Keep track of where we are in our waveform */ float DetermineIncrement(float note, bsgbryan.ConfigieMcWaveface configie) { return((note * 2.0f * Mathf.PI) / (float)configie.SampleRate); }
float ApplyWibbleWobble(bsgbryan.ConfigieMcWaveface configie, float position) { return(configie.WibbleWobble.CurrentCurve.Evaluate(position) * 2f); }
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { float width = position.width * 0.5f; GUIStyle foldout_style = new GUIStyle(EditorStyles.foldout); foldout_style.fontStyle = FontStyle.Bold; Rect properties_pos = new Rect(position.x, position.y, 20, row_height); Rect enabled_pos = new Rect(position.x + 68, position.y, 20, row_height); GUIContent property_name = new GUIContent(property.displayName); property_name.tooltip = "Harmonics are the octaves above and below the current one. They provide a fuller, richer sound."; show_properties.boolValue = EditorGUI.Foldout(properties_pos, show_properties.boolValue, property_name, foldout_style); SerializedProperty enabled = property.FindPropertyRelative("Enabled"); enabled.boolValue = EditorGUI.Toggle(enabled_pos, enabled.boolValue); using (new EditorGUI.DisabledScope(enabled.boolValue == false)) { if (show_properties.boolValue == true) { float row_one = position.y + row_height; float curve_height = row_height * 5; Rect lower_pos = new Rect(position.x, row_one, width, curve_height); Rect upper_pos = new Rect(position.x + width, row_one, width, curve_height); SerializedProperty lower = property.FindPropertyRelative("LowerCurve"); SerializedProperty upper = property.FindPropertyRelative("UpperCurve"); Rect limit = new Rect(0, 0, 1, 1); EditorGUI.CurveField(lower_pos, lower, Color.white, limit, GUIContent.none); EditorGUI.CurveField(upper_pos, upper, Color.white, limit, GUIContent.none); Rect details_pos = new Rect(position.x + 10, position.y + (row_height * 6), 20, row_height); show_details.boolValue = EditorGUI.Foldout(details_pos, show_details.boolValue, "Details", foldout_style); ConfigieMcWaveface configie = (ConfigieMcWaveface)property.serializedObject.targetObject; int low_octave = configie.PlayControls.LowOctave; int high_octave = configie.PlayControls.HighOctave; int current_octave = configie.PlayControls.CurrentOctave; float low_diff = (float)current_octave - low_octave; float high_diff = (float)high_octave - current_octave; float y_offset = lower_pos.y + 2f; float bar_height = lower_pos.height - 4f; Color white = Color.white * (enabled.boolValue ? 0.5f : 0.5f); for (float i = 0; i < low_diff; i++) { float left = i / low_diff; Rect pos = new Rect(lower_pos.x + (lower_pos.width * left), y_offset, 1f, bar_height); EditorGUI.DrawRect(pos, white); } for (float i = 1; i <= high_diff; i++) { float left = i / high_diff; Rect pos = new Rect(upper_pos.x + (upper_pos.width * left), y_offset, 1f, bar_height); EditorGUI.DrawRect(pos, white); } if (show_details.boolValue == true) { AnimationCurve lower_curve = lower.animationCurveValue; AnimationCurve upper_curve = upper.animationCurveValue; float rows_needed = low_diff < high_diff ? high_diff : low_diff; detail_rows = (int)rows_needed; float base_width = position.width * 0.5f; float octave_width = base_width * 0.4f; float strength_width = base_width * 0.6f; float x_offset = position.x + base_width; float x_octave_offset = position.x + octave_width; float x_third_offset = x_offset + octave_width; float row_eight = position.y + (row_height * 7); Rect lower_octave_text_pos = new Rect(position.x, row_eight, octave_width, row_height); Rect lower_strength_text_pos = new Rect(x_octave_offset, row_eight, strength_width, row_height); Rect upper_octave_text_pos = new Rect(x_offset, row_eight, octave_width, row_height); Rect upper_strength_text_pos = new Rect(x_third_offset, row_eight, strength_width, row_height); GUIContent lower_octave_text = new GUIContent("octave"); GUIContent upper_octave_text = new GUIContent("octave"); GUIContent strength_text = new GUIContent("strength"); GUIStyle left_style = new GUIStyle(GUI.skin.label); GUIStyle right_style = new GUIStyle(GUI.skin.label); left_style.alignment = TextAnchor.MiddleCenter; right_style.alignment = TextAnchor.MiddleLeft; lower_octave_text.tooltip = "The octaves below the current one (" + current_octave + ")"; upper_octave_text.tooltip = "The octaves above the current one (" + current_octave + ")"; strength_text.tooltip = "The intensity each octave will be played at"; EditorGUI.LabelField(lower_octave_text_pos, lower_octave_text, left_style); EditorGUI.LabelField(lower_strength_text_pos, strength_text, right_style); EditorGUI.LabelField(upper_octave_text_pos, upper_octave_text, left_style); EditorGUI.LabelField(upper_strength_text_pos, strength_text, right_style); float row_nine = position.y + (row_height * 8); for (float i = 0; i < low_diff; i++) { float strength = lower_curve.Evaluate(i / low_diff); float row_y = row_nine + (row_height * i); Rect lower_octave_pos = new Rect(position.x, row_y, octave_width, row_height); Rect lower_strength_pos = new Rect(x_octave_offset, row_y, strength_width, row_height); GUIContent octave_text = new GUIContent(i.ToString()); GUIContent lower_strength_text = new GUIContent(strength.ToString()); octave_text.tooltip = (Mathf.Abs(i - current_octave)) + " octaves below the current one (" + current_octave + ")"; lower_strength_text.tooltip = (Mathf.Round((1f - strength) * 100f)) + "% quieter than the current octave (" + current_octave + ")"; EditorGUI.LabelField(lower_octave_pos, octave_text, left_style); EditorGUI.LabelField(lower_strength_pos, lower_strength_text, right_style); } for (float i = 1; i <= high_diff; i++) { float strength = upper_curve.Evaluate(i / high_diff); float row_y = row_nine + (row_height * (i - 1)); Rect lower_octave_pos = new Rect(x_offset, row_y, octave_width, row_height); Rect lower_strength_pos = new Rect(x_third_offset, row_y, strength_width, row_height); GUIContent octave_text = new GUIContent((i + current_octave).ToString()); GUIContent upper_strength_text = new GUIContent(strength.ToString()); octave_text.tooltip = (Mathf.Abs(current_octave - (current_octave + i))) + " octaves above the current one (" + current_octave + ")"; upper_strength_text.tooltip = (Mathf.Round((1f - strength) * 100f)) + "% quieter than the current octave (" + current_octave + ")"; EditorGUI.LabelField(lower_octave_pos, octave_text, left_style); EditorGUI.LabelField(lower_strength_pos, upper_strength_text, right_style); } } } else { show_details.boolValue = false; } } }
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { GUIStyle foldout_style = new GUIStyle(EditorStyles.foldout); foldout_style.fontStyle = FontStyle.Bold; Rect properties_pos = new Rect(position.x, position.y, 20, row_height); Rect enabled_pos = new Rect(position.x + 95, position.y, 20, row_height); GUIContent property_name = new GUIContent(property.displayName); property_name.tooltip = "Use this curve to limit the volume for frequencies across the entire rendered spectrum"; show_properties.boolValue = EditorGUI.Foldout(properties_pos, show_properties.boolValue, property_name, foldout_style); SerializedProperty enabled = property.FindPropertyRelative("Enabled"); enabled.boolValue = EditorGUI.Toggle(enabled_pos, enabled.boolValue); using (new EditorGUI.DisabledScope(enabled.boolValue == false)) { if (show_properties.boolValue == true) { Rect curve_pos = new Rect(position.x, position.y + row_height, position.width, row_height * 5); SerializedProperty curve = property.FindPropertyRelative("Curve"); EditorGUI.CurveField(curve_pos, curve, Color.white, new Rect(0, 0, 1, 1), GUIContent.none); ConfigieMcWaveface configie = (ConfigieMcWaveface)property.serializedObject.targetObject; int low_octave = configie.PlayControls.LowOctave; int high_octave = configie.PlayControls.HighOctave; int current_octave = configie.PlayControls.CurrentOctave; float note = configie.Notes[configie.PlayControls.NoteIndex]; Color white = Color.white * (enabled.boolValue ? 0.5f : 0.375f); for (int i = low_octave; i <= high_octave; i++) { float left = ((float)(i - low_octave) / (high_octave - low_octave)); if (i == current_octave) { white = Color.white * (enabled.boolValue ? 0.75f : 0.5f); } else if (i == current_octave + 1) { white = Color.white * (enabled.boolValue ? 0.5f : 0.375f); } Rect pos = new Rect(curve_pos.x + (curve_pos.width * left), curve_pos.y + 2f, 1f, curve_pos.height - 4f); EditorGUI.DrawRect(pos, white); } Rect details_pos = new Rect(position.x + 10, position.y + (row_height * 6), 20, row_height); show_details.boolValue = EditorGUI.Foldout(details_pos, show_details.boolValue, "Details", foldout_style); if (show_details.boolValue == true) { AnimationCurve anim_curve = curve.animationCurveValue; int rows_needed = high_octave - low_octave + 1; detail_rows = rows_needed; float base_width = position.width * 0.5f; float half_base_width = base_width * 0.5f; float octave_width = base_width * 0.4f; float strength_width = base_width * 0.6f; float row_eight = position.y + (row_height * 7); float x_offset = position.x + base_width; float x_octave_offset = position.x + octave_width; float x_third_offset = x_offset + half_base_width; float row_nine = position.y + (row_height * 8); Rect octave_text_pos = new Rect(position.x, row_eight, octave_width, row_height); Rect strength_text_pos = new Rect(x_octave_offset, row_eight, strength_width, row_height); Rect frequency_text_pos = new Rect(x_offset, row_eight, half_base_width, row_height); Rect position_text_pos = new Rect(x_third_offset, row_eight, half_base_width, row_height); GUIContent octave_text = new GUIContent("octave"); GUIContent frequency_text = new GUIContent("frequency"); GUIContent strength_text = new GUIContent("strength"); GUIContent position_text = new GUIContent("position"); GUIStyle left_style = new GUIStyle(GUI.skin.label); GUIStyle right_style = new GUIStyle(GUI.skin.label); left_style.alignment = TextAnchor.MiddleCenter; right_style.alignment = TextAnchor.MiddleLeft; octave_text.tooltip = "All octaves currently being rendered"; frequency_text.tooltip = "The frequency for [note] in the octave listed"; strength_text.tooltip = "The intensity each note will be played at for the given octave"; position_text.tooltip = "The position on the curve for [note] at the given octave"; EditorGUI.LabelField(octave_text_pos, octave_text, left_style); EditorGUI.LabelField(strength_text_pos, strength_text, right_style); EditorGUI.LabelField(frequency_text_pos, frequency_text, right_style); EditorGUI.LabelField(position_text_pos, position_text, right_style); for (int i = low_octave; i <= high_octave; i++) { float pos = (float)(i - low_octave) / (high_octave - low_octave); float strength = anim_curve.Evaluate(pos); float row_y = row_nine + (row_height * (i - low_octave)); Rect octave_pos = new Rect(position.x, row_y, octave_width, row_height); Rect strength_pos = new Rect(x_octave_offset, row_y, strength_width, row_height); Rect frequency_pos = new Rect(x_offset, row_y, half_base_width, row_height); Rect position_pos = new Rect(x_third_offset, row_y, half_base_width, row_height); float freq = note * DetermineOctave(i); GUIContent i_octave_text = new GUIContent(i.ToString()); GUIContent i_strength_text = new GUIContent(strength.ToString()); GUIContent i_frequency_text = new GUIContent(freq.ToString()); GUIContent i_position_text = new GUIContent(pos.ToString()); if (i < current_octave) { i_octave_text.tooltip = (Mathf.Abs(i - current_octave)) + " octaves below the current one (" + current_octave + ")"; left_style.fontStyle = FontStyle.Normal; right_style.fontStyle = FontStyle.Normal; } else if (i == current_octave) { i_octave_text.tooltip = "The current octave"; left_style.fontStyle = FontStyle.Italic; right_style.fontStyle = FontStyle.Italic; } else { i_octave_text.tooltip = (Mathf.Abs(current_octave - i)) + " octaves above the current one (" + current_octave + ")"; left_style.fontStyle = FontStyle.Normal; right_style.fontStyle = FontStyle.Normal; } i_strength_text.tooltip = Mathf.Round(strength * 100f) + "% of the max volume level"; i_frequency_text.tooltip = "[Frequency tooltp goes here]"; i_position_text.tooltip = Mathf.Round(pos * 100f) + "% to the right on the curve"; EditorGUI.LabelField(octave_pos, i_octave_text, left_style); EditorGUI.LabelField(strength_pos, i_strength_text, right_style); EditorGUI.LabelField(frequency_pos, i_frequency_text, right_style); EditorGUI.LabelField(position_pos, i_position_text, right_style); } } } else { show_details.boolValue = false; } } }