using UnityEngine; public enum WaveformType { Sine, Square, Triangle, Sawtooth, Noise, Composite, Spike, Pulse, } [RequireComponent(typeof(LineRenderer))] public class WaveformVisualizer : MonoBehaviour { private int samples = 1024; [HideInInspector] public float amplitude = 0.4f; public float spatialFrequency = 1f; public float temporalFrequency = 0.1f; private float targetWaveformNoiseAmplitude = 0.1f; public float noiseAmplitude = 0.5f; [Range(0f, 1f)] [HideInInspector] public float clarity = 0f; public Color noiseColor = Color.gray; public Color clearColor = Color.green; private LineRenderer lineRenderer; private SpriteRenderer spriteRenderer; private float spriteWidth; private float spriteHeight; [HideInInspector] public float[] waveformData; private float[] noiseData; [HideInInspector] public float[] displayData; private float[] antiWaveformData; //private float[] errorWaveformData; // 错误波形数据 [HideInInspector] public WaveformType waveformType = WaveformType.Sine; public float amplitudeModulationFrequency = 0.5f; public float amplitudeModulationDepth = 0.5f; public float phaseShift = 0f; // 相位偏移 private bool isCaptured = false; // 是否已拍照(冻结波形) void Start() { lineRenderer = GetComponent(); lineRenderer.positionCount = samples; lineRenderer.useWorldSpace = false; spriteRenderer = GetComponentInParent(); if (spriteRenderer != null) { spriteWidth = spriteRenderer.bounds.size.x; spriteHeight = spriteRenderer.bounds.size.y; lineRenderer.sortingLayerID = spriteRenderer.sortingLayerID; lineRenderer.sortingOrder = spriteRenderer.sortingOrder + 2; } else { Debug.LogError("Could not find SpriteRenderer in parent object."); } waveformData = new float[samples]; noiseData = new float[samples]; displayData = new float[samples]; antiWaveformData = new float[samples]; //errorWaveformData = new float[samples]; DrawWaveform(); // 初始化波形 } void Update() { if (!isCaptured) { GenerateNoiseData(); GenerateWaveformData(); if (phaseShift > 0) { GenerateAntiWaveformData(); } for (int i = 0; i < samples; i++) { displayData[i] = Mathf.Lerp(noiseData[i], waveformData[i], clarity); if (phaseShift > 0) { displayData[i] += antiWaveformData[i]; } //displayData[i] += errorWaveformData[i]; // 叠加错误波形 } DrawWaveform(); } } void GenerateNoiseData() { float adjustedNoiseAmplitude = Mathf.Lerp(noiseAmplitude, targetWaveformNoiseAmplitude, clarity); for (int i = 0; i < samples; i++) { noiseData[i] = Random.Range(-adjustedNoiseAmplitude, adjustedNoiseAmplitude); } } void GenerateWaveformData() { for (int i = 0; i < samples; i++) { float t = (float)i / samples; waveformData[i] = GetWaveformValue(t, 0) * clarity; } } float GetWaveformValue(float t, float phaseOffset) { float time = Time.time * temporalFrequency; float amplitudeModulation = 1f + amplitudeModulationDepth * Mathf.Sin(2f * Mathf.PI * amplitudeModulationFrequency * Time.time); float angle = t * Mathf.PI * 2f * spatialFrequency + phaseOffset; float value = 0f; switch (waveformType) { case WaveformType.Sine: value = Mathf.Sin(angle); break; case WaveformType.Square: value = Mathf.Sign(Mathf.Sin(angle)); break; case WaveformType.Triangle: value = Mathf.PingPong(angle / Mathf.PI, 2f) - 1f; break; case WaveformType.Sawtooth: value = ((angle / (Mathf.PI * 2f)) % 1f) * 2f - 1f; break; case WaveformType.Pulse: value = Mathf.PingPong(angle / Mathf.PI, 2f) > 1f ? 1f : -1f; break; case WaveformType.Noise: value = Mathf.PerlinNoise(angle / (Mathf.PI * 2f), Time.time * temporalFrequency) * 2f - 1f; break; case WaveformType.Composite: value = Mathf.Sin(angle) + Mathf.Sin(angle * 2f) * 0.5f; break; case WaveformType.Spike: value = Random.Range(0f, 1f) > 0.98f ? Random.Range(0.5f, 1f) : 0f; break; default: value = 0f; break; } return value * amplitude * amplitudeModulation; } void GenerateAntiWaveformData() { for (int i = 0; i < samples; i++) { float t = (float)i / samples; antiWaveformData[i] = -GetWaveformValue(t, phaseShift) * clarity; } } void DrawWaveform() { for (int i = 0; i < samples; i++) { float x = ((float)i / (samples - 1)) * spriteWidth - (spriteWidth / 2f); float amplitudeScale = Mathf.Lerp(0.2f, 1f, clarity); float y = displayData[i] * amplitudeScale * (spriteHeight / 2f); Vector3 position = new Vector3(x, y, 0); lineRenderer.SetPosition(i, position); } Color waveColor = Color.Lerp(noiseColor, clearColor, clarity); lineRenderer.startColor = waveColor; lineRenderer.endColor = waveColor; float startWidth = Mathf.Lerp(0.02f, 0.05f, clarity); lineRenderer.startWidth = startWidth; lineRenderer.endWidth = startWidth; } // 拍照功能 public void SetCaptured(bool captured) { isCaptured = captured; } // 应用相位偏移 public void SetPhaseShift(float phaseShiftValue) { phaseShift = phaseShiftValue; } // 重置波形 public void ResetWaveform() { isCaptured = false; phaseShift = 0f; } }