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吧,我知道大家都很忙,直接用一个工具挺好的~

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

相关推荐
左 岸 ღ °5 小时前
window11 通过cmd命令行安装 oh my zsh 的教程
编辑器
MonkeyKing_sunyuhua6 小时前
Visual Studio Code 进行汉化
ide·vscode·编辑器
空中湖6 小时前
墨笔 在线Markdown 编辑器
编辑器
有趣的我9 小时前
vim的操作
编辑器·vim·excel
牙膏上的小苏打233314 小时前
Unity Surround开关后导致获取主显示器分辨率错误
unity·主屏幕
『六哥』14 小时前
Windows 10 如何设置右击鼠标快速进行“关机”
windows·经验分享·编辑器
Unity大海16 小时前
诠视科技Unity SDK开发环境配置、项目设置、apk打包。
科技·unity·游戏引擎
浅陌sss21 小时前
Unity中 粒子系统使用整理(一)
unity·游戏引擎
维度攻城狮1 天前
实现在Unity3D中仿真汽车,而且还能使用ros2控制
python·unity·docker·汽车·ros2·rviz2
为你写首诗ge1 天前
【Unity网络编程知识】FTP学习
网络·unity