Unity做一个剪辑声音的工具 在编辑器模式实时剪辑声音

Unity音频剪辑工具的实现

在游戏开发中,音频是一个至关重要的元素。音频剪辑工具能够帮助开发者高效地编辑和管理音频文件。本文将解析一个基于Unity编辑器的音频剪辑工具的实现方法

效果

工具功能

该音频剪辑工具允许用户在Unity编辑器中加载音频片段,并通过图形化界面进行剪辑、预览和保存操作。以下是该工具的主要功能:

  • 加载音频片段:用户可以通过工具界面选择并加载音频文件。
  • 波形显示:工具会生成音频的波形图,以帮助用户可视化音频数据。
  • 剪辑操作:用户可以通过滑动条调整音频的起始和结束时间,以便进行剪辑。
  • 音量控制:提供音量滑块,用户可以调整音频播放的音量。
  • 预览播放:用户可以播放剪辑后的音频片段进行预览。
  • 保存剪辑结果:工具支持将剪辑后的音频片段保存为新的音频文件。

代码解析

1. 显示工具窗口

首先,工具通过[MenuItem("Tools/音频剪辑工具")]创建一个菜单项,点击该菜单项可以显示音频编辑器窗口。
javascript 复制代码
[MenuItem("Tools/音频剪辑工具")]
public static void ShowWindow()
{
    GetWindow<AudioClipEditor>("音频编辑器");
}

2. 初始化音频资源

在OnEnable方法中,工具创建了一个隐藏的AudioSource用于播放音频。
javascript 复制代码
private void OnEnable()
{
    audioSource = EditorUtility.CreateGameObjectWithHideFlags("AudioSource" , HideFlags.HideAndDontSave , typeof(AudioSource)).GetComponent<AudioSource>();
}

3. 用户界面

工具通过OnGUI方法绘制用户界面,用户可以选择音频文件并进行编辑操作。
javascript 复制代码
private void OnGUI()
{
    EditorGUILayout.BeginVertical();

    audioClip = EditorGUILayout.ObjectField("声音片段" , audioClip , typeof(AudioClip) , false) as AudioClip;
    if (audioClipTemp != audioClip)
    {
        audioClipTemp = audioClip;
        Init();
    }

    if (audioClip)
    {
        DisplayAudioClipInfo();
        AdjustClipSection();
        DisplayVolumeControl();

        GUILayout.Space(10);

        if (GUILayout.Button("听" , GUILayout.Height(40)))
        {
            PlayTestAudio();
        }

        GUILayout.Space(10);

        if (GUILayout.Button("保存片段" , GUILayout.Height(40)))
        {
            ClipAndSave();
        }
    }

    EditorGUILayout.EndVertical();
}

4. 初始化和显示音频信息

Init方法负责加载音频数据并生成波形图,DisplayAudioClipInfo方法显示音频的基本信息。
javascript 复制代码
private void Init()
{
    if (audioClip != null)
    {
        endTime = audioClip.length;
        samples = new float[audioClip.samples * audioClip.channels];
        audioClip.GetData(samples , 0);
        UpdateWaveformTexture();
    }
}

private void DisplayAudioClipInfo()
{
    EditorGUILayout.LabelField($"开始时间: {startTime:F2}s");
    EditorGUILayout.LabelField($"结束时间: {endTime:F2}s");

    GUILayout.Space(10);
}

5. 剪辑和预览功能

工具通过AdjustClipSection方法调整剪辑区间,通过PlayTestAudio方法进行预览播放。
javascript 复制代码
private void AdjustClipSection()
{
    GUILayout.Label("调整剪辑片段");

    Rect waveformRect = GUILayoutUtility.GetRect(position.width , 64);
    if (waveformTexture == null || waveformTexture.width != (int)waveformRect.width)
    {
        UpdateWaveformTexture();
    }

    if (waveformTexture != null)
    {
        EditorGUI.DrawPreviewTexture(waveformRect , waveformTexture);
    }

    EditorGUILayout.MinMaxSlider("" , ref startTime , ref endTime , 0f , audioClip != null ? audioClip.length : 10f);
}

private void PlayTestAudio()
{
    if (audioClip != null)
    {
        AudioClip clippedAudioClip = ClipAudio(audioClip , startTime , endTime);
        audioSource.clip = clippedAudioClip;
        audioSource.volume = volume;
        audioSource.Play();
    }
    else
    {
        Debug.LogError("请指定一段音频");
    }
}

6. 保存剪辑后的音频

ClipAndSave方法允许用户将剪辑后的音频片段保存到文件。
javascript 复制代码
private void ClipAndSave()
{
    if (audioClip != null)
    {
        AudioClip clippedAudioClip = ClipAudio(audioClip , startTime , endTime);
        string savePath = EditorUtility.SaveFilePanel("保存剪辑的音频" , "Assets" , audioClipTemp.name + "_New" , "wav");

        if (!string.IsNullOrEmpty(savePath))
        {
            SaveAudioClipToFile(clippedAudioClip , savePath);
        }
    }
    else
    {
        Debug.LogError("请指定一段音频");
    }
}

7. 波形图生成

UpdateWaveformTexture方法更新波形图,GenerateWaveformTexture方法生成音频波形图像。
javascript 复制代码
private void UpdateWaveformTexture()
{
    if (samples != null)
    {
        waveformTexture = GenerateWaveformTexture(samples , audioClip.channels , (int)position.width , 64);
    }
}

private Texture2D GenerateWaveformTexture(float[] samples , int channels , int width , int height)
{
    Texture2D texture = new Texture2D(width , height , TextureFormat.RGBA32 , false);
    Color[] colors = new Color[width * height];
    for (int i = 0; i < colors.Length; i++)
    {
        colors[i] = Color.black;
    }
    texture.SetPixels(colors);

    int packSize = ( samples.Length / channels ) / width;
    for (int x = 0; x < width; x++)
    {
        float max = 0;
        for (int i = 0; i < packSize; i++)
        {
            float sampleValue = samples[( x * packSize + i ) * channels] * volume;
            if (sampleValue > max) max = sampleValue;
        }
        int heightValue = (int)( max * height );
        for (int y = 0; y < heightValue; y++)
        {
            texture.SetPixel(x , y , Color.yellow);
        }
    }
    texture.Apply();
    return texture;
}

8. 剪辑音频片段

ClipAudio方法根据用户指定的起始和结束时间剪辑音频片段,并返回新的AudioClip。
javascript 复制代码
private AudioClip ClipAudio(AudioClip originalClip , float start , float end)
{
    float[] data = new float[originalClip.samples * originalClip.channels];
    originalClip.GetData(data , 0);

    int newSampleCount = (int)( ( end - start ) * originalClip.frequency );
    float[] newData = new float[newSampleCount * originalClip.channels];

    int startIndex = (int)( start * originalClip.frequency * originalClip.channels );
    for (int i = 0; i < newSampleCount * originalClip.channels; i++)
    {
        newData[i] = data[startIndex + i] * volume;
    }

    AudioClip clippedAudioClip = AudioClip.Create("ClippedAudio" , newSampleCount , originalClip.channels , originalClip.frequency , false);
    clippedAudioClip.SetData(newData , 0);

    return clippedAudioClip;
}

我为什么要使用?

  • 用户友好:工具通过图形化界面,使得音频剪辑操作直观易用,即使对非程序员用户也非常友好。
  • 实时预览:用户可以即时预览剪辑后的音频片段,方便进行调整。
  • 高效:工具内嵌于Unity编辑器中,无需切换应用程序,提升了开发效率。
  • 灵活性:提供音量控制功能,用户可以根据需求调整音量,确保最终效果符合预期。
  • 便捷保存:工具支持将剪辑后的音频片段保存为文件,便于后续使用和管理。
通过实现这个音频剪辑工具,我们可以看到在Unity中集成自定义工具的强大功能。它不仅提升了工作效率,也为开发者提供了更多的创作自由。希望本文对你理解和实现类似的工具有所帮助。

虽然文章写的已经够详细了,但是还是放出来 Demo吧,我知道大家都很忙,直接用一个工具挺好的~

有时间一定回来看看具体实现,学会写一些小工具来提升自己的开发效率,一起加油!

相关推荐
程序猿小D4 小时前
第12节 Node.js 函数
开发语言·ide·人工智能·vscode·node.js·c#·编辑器
装大炮的自行车9 小时前
【Unity】R3 CSharp 响应式编程 - 使用篇(集合)(三)
windows·unity·游戏引擎
阿松爱学习13 小时前
【Unity开发】控制手机移动端的震动
unity·游戏引擎·unity开发
快乐觉主吖14 小时前
Unity安卓平台开发,启动app并传参
android·unity·游戏引擎
海尔辛18 小时前
Unity Mac 笔记本操作入门
macos·unity·游戏引擎
清晨朝暮21 小时前
vscode不满足先决条件问题的解决——vscode的老版本安装与禁止更新(附安装包)
ide·vscode·编辑器
扮作大侠21 小时前
VScode自动添加指定内容
ide·vscode·编辑器
Eric.Lee202121 小时前
vscode实时预览编辑markdown
ide·vscode·编辑器·markdown
海尔辛21 小时前
UGUI Text/TextMeshPro字体组件
ui·unity·性能优化
程序猿小D1 天前
第11节 Node.js 模块系统
服务器·前端·node.js·编辑器·vim