Files
aibis-dream/Assets/Editor/GlitchNoiseAudioGenerator.cs
T
2026-03-13 22:07:36 +08:00

150 lines
4.9 KiB
C#

using UnityEngine;
using UnityEditor;
using System.IO;
/// <summary>
/// 生成与 SpriteNoiseGlitch shader 三阶段对应的程序化音效。
/// 菜单: Tools > Generate Glitch Noise Audio
/// </summary>
public static class GlitchNoiseAudioGenerator
{
private const int SampleRate = 44100;
private const float Duration = 4f; // 每段音效时长(秒),便于循环使用
private const string OutputFolder = "Assets/RawResources/Audio/GlitchNoise";
[MenuItem("Tools/Generate Glitch Noise Audio")]
public static void Generate()
{
string dir = Path.Combine(Application.dataPath, "RawResources", "Audio", "GlitchNoise");
Directory.CreateDirectory(dir);
GenerateStage1(dir);
GenerateStage2(dir);
GenerateStage3(dir);
AssetDatabase.Refresh();
Debug.Log($"[GlitchNoise] 已生成三阶段音效至 Assets/RawResources/Audio/GlitchNoise");
}
/// <summary>Stage 1: 轻微静态噪点 - 柔和白噪声</summary>
private static void GenerateStage1(string dir)
{
int samples = (int)(SampleRate * Duration);
float[] data = new float[samples];
var rnd = new System.Random(12345);
float gain = 0.12f;
for (int i = 0; i < samples; i++)
{
data[i] = ((float)rnd.NextDouble() * 2f - 1f) * gain;
}
SaveWav(dir, "GlitchNoise_Stage1_Light.wav", data);
}
/// <summary>Stage 2: 中等 - 更多噪点 + 偶尔 glitch 爆音</summary>
private static void GenerateStage2(string dir)
{
int samples = (int)(SampleRate * Duration);
float[] data = new float[samples];
var rnd = new System.Random(23456);
float noiseGain = 0.22f;
int glitchInterval = SampleRate / 4; // 约每 0.25 秒一次 glitch 爆音
for (int i = 0; i < samples; i++)
{
float n = ((float)rnd.NextDouble() * 2f - 1f) * noiseGain;
// 随机 glitch 爆音
if (i > 0 && i % glitchInterval < 120)
{
float burst = ((float)rnd.NextDouble() * 2f - 1f) * 0.5f;
n += burst * (1f - (i % glitchInterval) / 120f);
}
data[i] = Mathf.Clamp(n, -1f, 1f);
}
SaveWav(dir, "GlitchNoise_Stage2_Medium.wav", data);
}
/// <summary>Stage 3: 严重 - 强烈噪点 + 频繁 glitch + 数字故障感</summary>
private static void GenerateStage3(string dir)
{
int samples = (int)(SampleRate * Duration);
float[] data = new float[samples];
var rnd = new System.Random(34567);
float noiseGain = 0.4f;
int blockSize = 2205; // 约 0.05 秒一块
int glitchBlockEvery = 4;
for (int i = 0; i < samples; i++)
{
int block = i / blockSize;
float n = ((float)rnd.NextDouble() * 2f - 1f) * noiseGain;
// 块状 glitch:整块随机反转/爆音
if (block % glitchBlockEvery == 0)
{
int posInBlock = i % blockSize;
float t = (float)posInBlock / blockSize;
n += ((float)rnd.NextDouble() * 2f - 1f) * 0.6f * (1f - t);
}
// 随机“卡顿”短静音后爆音
if (rnd.NextDouble() < 0.0003)
{
int silenceLen = 100 + rnd.Next(300);
int end = Mathf.Min(i + silenceLen, samples);
for (int j = i; j < end; j++)
{
data[j] = j == end - 1 ? ((float)rnd.NextDouble() * 2f - 1f) * 0.8f : 0f;
}
i = end - 1;
}
else
{
data[i] = Mathf.Clamp(n, -1f, 1f);
}
}
SaveWav(dir, "GlitchNoise_Stage3_Heavy.wav", data);
}
private static void SaveWav(string dir, string filename, float[] samples)
{
string path = Path.Combine(dir, filename);
using (var fs = new FileStream(path, FileMode.Create))
using (var bw = new BinaryWriter(fs))
{
// RIFF header
bw.Write(new[] { 'R', 'I', 'F', 'F' });
int dataSize = samples.Length * 2; // 16-bit
bw.Write(36 + dataSize);
bw.Write(new[] { 'W', 'A', 'V', 'E' });
// fmt chunk
bw.Write(new[] { 'f', 'm', 't', ' ' });
bw.Write(16); // chunk size
bw.Write((short)1); // PCM
bw.Write((short)1); // mono
bw.Write(SampleRate);
bw.Write(SampleRate * 2);
bw.Write((short)2);
bw.Write((short)16);
// data chunk
bw.Write(new[] { 'd', 'a', 't', 'a' });
bw.Write(dataSize);
foreach (float s in samples)
{
short sample = (short)Mathf.Clamp((int)(s * 32767), -32768, 32767);
bw.Write(sample);
}
}
}
}