d2867810ee
- Add editor tool to batch apply audio import settings based on configuration files - Standardize sample rates: SFX/Voice to 22050 Hz, Music to 44100 Hz - Set quality: SFX/Voice to 0.5, Music to 0.13 - Adjust load types based on audio duration - Set project sample rate to 48000 Hz - Update preload settings for voice and music files
192 lines
7.5 KiB
C#
192 lines
7.5 KiB
C#
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using UnityEditor;
|
|
using UnityEngine;
|
|
|
|
namespace OCES.Audio
|
|
{
|
|
|
|
public static class AudioImportTool
|
|
{
|
|
const string k_audioResourcePath = "Audios";
|
|
const string k_audioConfigPath = "AudioData";
|
|
|
|
static string AudioAbsolutePath
|
|
{
|
|
get { return Path.Combine(Application.dataPath, "Resources", k_audioResourcePath); }
|
|
}
|
|
static string ConfigAbsolutePath
|
|
{
|
|
get { return Path.Combine(Application.dataPath, "Resources", k_audioConfigPath); }
|
|
}
|
|
|
|
[MenuItem("Tools/Audio/Apply Audio Import Settings")]
|
|
public static void RunFromMenu()
|
|
{
|
|
if (EditorUtility.DisplayDialog(
|
|
"Apply Audio Import Settings",
|
|
$"将对 {k_audioResourcePath} 下所有文件重新应用导入设置,确认继续?",
|
|
"确认", "取消"))
|
|
{
|
|
Run();
|
|
}
|
|
}
|
|
|
|
// Unity -batchmode -executeMethod OCES.Audio.Editor.AudioImportTool.RunCLI
|
|
public static void RunCli()
|
|
{
|
|
Debug.Log("[AudioImportTool] CLI 模式启动");
|
|
Run();
|
|
}
|
|
|
|
public static void Run()
|
|
{
|
|
// 1. 加载配置表
|
|
var audioObjectConfig = AudioConfigLoader.Load<AudioObjectConfig>(ConfigAbsolutePath, "AudioObject.bytes");
|
|
var musicSegmentConfig = AudioConfigLoader.Load<MusicSegmentConfig>(ConfigAbsolutePath, "MusicSegment.bytes");
|
|
if (audioObjectConfig == null || musicSegmentConfig == null)
|
|
{
|
|
Debug.LogError("[AudioImportTool] 配置表加载失败,终止");
|
|
return;
|
|
}
|
|
|
|
// 2. 扫描文件
|
|
List<string> supportedExtensions = new() { ".wav", ".ogg" };
|
|
DirectoryInfo dir = new(AudioAbsolutePath);
|
|
FileInfo[] files = dir.GetFiles().Where(f => supportedExtensions.Contains(f.Extension.ToLower())).ToArray();
|
|
int total = files.Length, processed = 0, failed = 0;
|
|
|
|
AssetDatabase.StartAssetEditing(); // 批量操作,暂停自动刷新
|
|
try
|
|
{
|
|
foreach (FileInfo file in files)
|
|
{
|
|
// 转成 Assets/... 相对路径供 AssetDatabase 使用
|
|
string assetPath = "Assets" + file.FullName
|
|
.Replace(Application.dataPath, "")
|
|
.Replace("\\", "/");
|
|
|
|
EditorUtility.DisplayProgressBar(
|
|
"Audio Import Tool",
|
|
$"处理: {file.Name} ({processed}/{total})",
|
|
(float)processed / total);
|
|
|
|
bool ok = ProcessFile(assetPath, file.Name, audioObjectConfig, musicSegmentConfig);
|
|
if (ok) processed++;
|
|
else failed++;
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
EditorUtility.ClearProgressBar();
|
|
AssetDatabase.StopAssetEditing();
|
|
AssetDatabase.SaveAssets();
|
|
}
|
|
|
|
Debug.Log($"[AudioImportTool] 完成:{processed} 成功,{failed} 失败,共 {total} 个文件");
|
|
}
|
|
|
|
static bool ProcessFile(
|
|
string assetPath, string fileName,
|
|
AudioObjectConfig audioObjectConfig, MusicSegmentConfig musicSegmentConfig)
|
|
{
|
|
AudioImporter importer = AssetImporter.GetAtPath(assetPath) as AudioImporter;
|
|
if (!importer)
|
|
{
|
|
Debug.LogWarning($"[AudioImportTool] 无法获取 AudioImporter: {assetPath}");
|
|
return false;
|
|
}
|
|
|
|
AudioClip clip = AssetDatabase.LoadAssetAtPath<AudioClip>(assetPath);
|
|
if (!clip)
|
|
{
|
|
Debug.LogWarning($"[AudioImportTool] 无法加载 AudioClip: {assetPath}");
|
|
return false;
|
|
}
|
|
|
|
float duration = clip.length;
|
|
string fileNameNoExt = Path.GetFileNameWithoutExtension(fileName);
|
|
AudioCategory category = ClassifyAudio(fileNameNoExt, audioObjectConfig, musicSegmentConfig, out AudioObject audioObject);
|
|
|
|
importer.ClearSampleSettingOverride("Android");
|
|
importer.ClearSampleSettingOverride("iOS");
|
|
|
|
AudioImporterSampleSettings settings = importer.defaultSampleSettings;
|
|
settings.compressionFormat = AudioCompressionFormat.Vorbis;
|
|
|
|
settings.sampleRateSetting = AudioSampleRateSetting.OverrideSampleRate;
|
|
settings.preloadAudioData = audioObject?.Haptic != 0;
|
|
switch (category)
|
|
{
|
|
case AudioCategory.Music:
|
|
settings.sampleRateOverride = 44100;
|
|
settings.quality = 0.13f;
|
|
settings.loadType = duration switch
|
|
{
|
|
<= 5 => AudioClipLoadType.DecompressOnLoad,
|
|
>= 15 => AudioClipLoadType.Streaming,
|
|
_ => AudioClipLoadType.CompressedInMemory,
|
|
};
|
|
break;
|
|
case AudioCategory.Voice:
|
|
case AudioCategory.SFX:
|
|
default:
|
|
settings.sampleRateOverride = 22050; // 音效2022.3.62f3没有32kHz这一档,要是有的话这一档其实最合适
|
|
settings.quality = 0.5f;
|
|
settings.loadType = duration switch
|
|
{
|
|
>= 15 => AudioClipLoadType.Streaming,
|
|
_ => AudioClipLoadType.DecompressOnLoad,
|
|
};
|
|
break;
|
|
}
|
|
|
|
importer.defaultSampleSettings = settings;
|
|
importer.forceToMono = false;
|
|
importer.SaveAndReimport();
|
|
return true;
|
|
}
|
|
|
|
enum AudioCategory {Music, SFX, Voice }
|
|
|
|
static AudioCategory ClassifyAudio(
|
|
string fileName, // 不含扩展名
|
|
AudioObjectConfig audioObjectConfig,
|
|
MusicSegmentConfig musicSegmentConfig,
|
|
out AudioObject matchedObject)
|
|
{
|
|
matchedObject = null;
|
|
|
|
// 1. MusicSegment 表命中 → Music
|
|
MusicSegment segment = musicSegmentConfig.MusicSegmentList()
|
|
.FirstOrDefault(musicSegment => musicSegment.Name == fileName);
|
|
if (segment != null)
|
|
return AudioCategory.Music;
|
|
|
|
// 2. AudioObject 表命中 → 按 MixingType
|
|
AudioObject audioObject = audioObjectConfig.AudioObjectList()
|
|
.FirstOrDefault(audioObject => audioObject.Name != null && audioObject.Name.Contains(fileName));
|
|
if (audioObject != null)
|
|
{
|
|
matchedObject = audioObject;
|
|
return audioObject.MixingType == MixingType.Voice
|
|
? AudioCategory.Voice
|
|
: AudioCategory.SFX; // SFX + Accent 都走 SFX 分支
|
|
}
|
|
|
|
// 3. 文件名 fallback
|
|
string lower = fileName.ToLowerInvariant();
|
|
if (lower.Contains("music") || lower.Contains("bgm"))
|
|
return AudioCategory.Music;
|
|
if (lower.Contains("sfx"))
|
|
return AudioCategory.SFX;
|
|
if (lower.Contains("voice"))
|
|
return AudioCategory.Voice;
|
|
|
|
// 4. 完全兜底
|
|
Debug.LogWarning($"[AudioImportTool] 无法分类: {fileName},默认当作 SFX 处理");
|
|
return AudioCategory.SFX;
|
|
}
|
|
}
|
|
} |