150 lines
4.9 KiB
C#
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);
|
|
}
|
|
}
|
|
}
|
|
}
|