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

Unity音频剪辑工具的实现

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

效果

在这里插入图片描述

工具功能

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

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

代码解析

1. 显示工具窗口

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

2. 初始化音频资源

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

3. 用户界面

工具通过OnGUI方法绘制用户界面,用户可以选择音频文件并进行编辑操作。
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方法显示音频的基本信息。
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方法进行预览播放。
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方法允许用户将剪辑后的音频片段保存到文件。
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方法生成音频波形图像。
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。
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吧,我知道大家都很忙,直接用一个工具挺好的~

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/31312.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux 一键部署 Nginx1.26.1 + ModSecurity3

前言 ModSecurity 是 Apache 基金会的一个开源、高性能的 Web 应用程序防火墙(WAF),它提供了强大的安全规则引擎,用于检测和阻止各种攻击行为,如 SQL 注入、XSS 跨站点脚本攻击等。而 nginx 是一个高性能的 Web 服务器,常用于处理大量的并发请求,具有很高的负载均衡能力…

k8s及etcd的每日自动备份及故障时的还原脚本

#!/bin/bash# 定义备份目录 BACKUP_DIR"/data/backupdata/k8s" K8S_CONFIG_BACKUP"${BACKUP_DIR}/k8s_config_backup_$(date %Y%m%d%H%M%S).tar.gz" ETCD_BACKUP"${BACKUP_DIR}/etcd_backup_$(date %Y%m%d%H%M%S).db" TEMP_DIR"${BACKUP_DI…

<component>标签的介绍和使用

目录 基本使用&#xff1a; 使用组件对象&#xff1a; 使用动态组件与 keep-alive keep-alive简单介绍及使用&#xff1a; 属性&#xff1a; 生命周期钩子&#xff1a; 举例&#xff1a; 缓存单个组件&#xff1a; 缓存多个组件&#xff08;通过路由动态&#xff09;&…

如何修炼个人影响力,怎样有效地影响他人

一、教程描述 影响力是用一种别人所乐于接受的方式&#xff0c;改变他人的思想和行动的能力。影响力又被解释为战略影响、印象管理、善于表现的能力、目标的说服力以及合作促成的影响力等。影响力表明了一种试图支配与统帅他人的倾向&#xff0c;从而才使一个人采取各种劝说、…

iOS封装FrameWork

我们是整个项目封装给客户app用&#xff0c;项目里面有资源文件&#xff1a;xib和图片文件。有第三方&#xff0c;也有.a文件和第三方给我们的frameWork。下面记录下大体遇到的问题及遇到的冲突解决办法。 第一部分&#xff1a;封装frameWork 1.首先准备好&#xff0c;要封装的…

在阿里云服务器Linux系统上从头到尾实现Webapp的部署(安装卸载JDK、安装Tomcat、安装配置MySQL)

输入yum list | grep jdk 选择 devel是软件包中的典型命名格式 devel表示这个包是开发工具相关的 里面包含内容是最完整的 x86表示cpu架构是x86_64 还有openjdk表示开源版本 输入yum install java-1.8.0-openjdk-devel.x86_64 开始下载 遇到问你 is this ok? 输入y表示ok 输…

C#中的枚举类-自定义属性

在实际开发过程中&#xff0c;我们常常会用到枚举类&#xff0c;使用枚举的时候往往有着各种使用条件&#xff0c;如何给枚举加入使用条件呢&#xff1f; 答案就是我们的——自定义属性 废话不多说&#xff0c;上代码 枚举类 首先我们要有一个枚举类 public enum XXXX枚举…

0621# C++八股 1.成员初始化列表的概念?以及为什么使用它会快一点?2.重写Override和重载Overload区别

成员初始化列表的概念&#xff1f;以及为什么使用它会快一点&#xff1f; 成员初始化列表的概念 在C中&#xff0c;成员初始化列表是构造函数的一部分&#xff0c;它用于在构造函数体执行之前初始化类的成员变量。成员初始化列表在构造函数参数列表之后&#xff0c;以冒号 : …

Unity与Android交互通信系列(6)

本节主要讲述广播订阅。 使用AndroidJavaProxy代理接口&#xff0c;我们可以很方便的实现对Android端事件的订阅&#xff0c;灵活的进行Android端与Unity端的代码交互。通过AndroidJavaProxy代理&#xff0c;我们也可以在安卓端使用 BroadcastReceiver 接收广播&#xff0c;然后…

物联网APP设计艺术:技巧与未来科技的融合

从早期的智能家居&#xff0c;到今天的服装制造、医疗保健、物流运输、汽车工业...越来越多的行业开始使用物联网。物联网技术跨度大&#xff0c;适用范围广&#xff0c;设计师在面对物联网产品的UI设计项目时往往会感到受阻。这是什么原因呢&#xff1f;物联网应用程序界面设计…

基于国产飞腾2000制作的paddleocr hubserving服务docker镜像文件

paddleocr hubserving国产化飞腾、鲲鹏armv8 api服务镜像制作 一、编译paddle paddle官网说明在处理器飞腾2000和鲲鹏需要自行编译&#xff08;FT2000/Kunpeng 920 2426SK&#xff09; 如果自己编译可以参考官网飞腾/鲲鹏下从源码编译-使用文档-PaddlePaddle深度学习平台 二…

干货满满!亚信安慧亮相PostgreSQL峰会,分享AntDB数据库国产化运维之路

6月15日&#xff0c;PostgreSQL数据库技术峰会广州站圆满落幕。峰会上&#xff0c;亚信安慧数据库智能运维产品负责人李志龙带来了《AntDB数据库运维之路》的主题演讲。如何用好数据是企业数智化转型的重点&#xff0c;更智能的数据管理&#xff0c;在促进数据要素流转&#xf…

哪些医疗器械需要注意网络安全问题?医疗器械网络安全测试方法有哪些?

随着医疗设备的网络化程度不断提高&#xff0c;网络安全问题变得越来越突出。以下是一些需要特别注意网络安全的医疗器械类别&#xff1a;1. 医学影像类设备&#xff1a;包括CT、DR、医用X射线系统、超声诊断仪、磁共振设备、肿瘤治疗机、医用胶片及处理系统、医用3D打印设备等…

WindTerm软件的本地模式和远程模式

WindTerm作为一个多功能的远程终端控制软件&#xff0c;支持本地模式和远程模式两种键盘输入处理方式&#xff0c;这两种模式的主要区别在于键盘输入的处理逻辑和目标&#xff1a; 本地模式&#xff08;Local Mode&#xff09; 在本地模式下&#xff0c;WindTerm不对键盘输入…

怎么使用Consul当配置中心和动态刷新配置

一、背景 由于Eureka官方已经正式宣布&#xff0c;自2.0起不再维护该项目&#xff0c;如果需要使用2.x&#xff0c;自行承担风险。 项目之前使用的Eureka&#xff0c;现在不维护了则需要寻找替代方案。现在Spring Cloud官方推荐Spring Cloud Consul替换Eureka作为注册中心&…

IDEA 学习之 热加载问题(Hot Swap)

目录 1. IDEA 自带热加载1.1. 热加载快捷键1.2. 热加载范围 1. IDEA 自带热加载 1.1. 热加载快捷键 系统快捷键WINCtrl F9MACOPTIOIN F9 1.2. 热加载范围 资源类型是否影响影响范围Java部分方法签名内

常见的spark mllib分类算法详解

构建一个中文博客&#xff1a;常见的分类算法详解 在机器学习和数据科学领域&#xff0c;分类算法是解决分类问题的重要工具。本文将介绍几种常见的分类算法&#xff0c;包括线性支持向量机&#xff08;LinearSVC&#xff09;、逻辑回归&#xff08;Logistic Regression&#…

VUE面试题汇总(九)

之间联系&#xff08;Model 和 ViewModel 的双向数据绑定&#xff09; 解析&#xff1a; MVVM 是 Model-View-ViewModel 的缩写。MVVM 是一种设计思想。Model 层代表数据模型&#xff0c;也可以在 Model 中定义数据修改和操作的业务逻辑&#xff1b;View 代表 UI 组件&#xf…

推荐5个AI辅助生成论文、降低查重率的网站【2024最新】

一、引言 对于忙碌的学生来说&#xff0c;毕业论文通常是一项艰巨的任务。幸运的是&#xff0c;随着人工智能技术的发展&#xff0c;现在有一些工具可以帮助学生轻松完成论文。本文将介绍五个免费的AI工具&#xff0c;它们能够一键帮助你生成毕业论文&#xff0c;让你的学术生…

实验一:Ubuntu系统中的USB设备绑定实验

实验一&#xff1a;Ubuntu系统中的USB设备绑定实验 一、实验目的二、实验原理三、实验环境四、实验步骤任务 1&#xff1a;绑定不同USB设备任务 2&#xff1a;绑定多个相同设ID的串口设备 五、注意事项六、拓展练习 一、实验目的 学习Ubuntu中USB设备命名方法&#xff1b;掌握…