fmod音频bank打包加载以及热更方案

https://blog.csdn.net/UWA4D/article/details/106091666

fmod的音频有两种引入的模式,一个是streaming的方式,另外一个是assetbundle的方式。
第一种方式:Streaming Assets形式
我们将制作好的bank,导入到unity之后,在设置中:
在这里插入图片描述
选择:streaming assets
这是最通常的做法,fmod在运行的时候或者是Refresh bank的时候,会将bank拷贝到streaming文件夹下:
在这里插入图片描述
在这里插入图片描述

那么unity在何时加载呢?
在这里插入图片描述
代码在:
RuntimeManager——>FMOD.RESULT Initialize()——>LoadBanks
在这里插入图片描述
这样就将所有的bank加载到内存了。

第二种方式:Asset Bundle
在这里插入图片描述
当选择Asset Bundle的时候,fmod会自动将我们的Build Path下的bank,重新拷贝一份到当前的项目中,但是每个bank的后缀都更改为.bytes了。
这是因为unity打包的时候,对unity之外的一些文件后缀是不识别的,比如这里.bank。我记得lua也是要改为.txt才能进行打包。

ok,我们有了bytes文件,就好打包了。我们准备将其中的一个bytes文件,进行打包:
在这里插入图片描述
打包代码:

public class BuildBundle
{

    [MenuItem("ArtTool/Build Single Bank")]
    public static void BuildSingleBank()
    {
        AssetBundleBuild[] abs = new AssetBundleBuild[1];
        abs[0].assetBundleName = "Tone.bundle";
        abs[0].assetNames = new string[1];
        abs[0].assetNames[0] = @"Assets/Desktop/bytes/Tone.bytes";
        string outpath = Application.streamingAssetsPath + "/Desktop/bytes";
        if(!Directory.Exists(outpath))
        {
            Directory.CreateDirectory(outpath);
        }
        BuildPipeline.BuildAssetBundles(outpath, abs, BuildAssetBundleOptions.ChunkBasedCompression, BuildTarget.Android);
        AssetDatabase.Refresh();
    }
}

打包之后的位置:
在这里插入图片描述

我们将其拷贝到persistentDataPath路径下:
在这里插入图片描述

下面就是加载:

public void LoadBank()
{
    //RuntimeManager.LoadBank();
    AssetBundle ab = AssetBundle.LoadFromFile(Application.persistentDataPath + "/tone.bundle");
    UnityEngine.Object obj = ab.LoadAsset("Tone"); // 无类型&无后缀加载,能加载到
    UnityEngine.Object[] objs = ab.LoadAllAssets(); // 加载所有资源,能加载到
    TextAsset txtAsset = ab.LoadAsset<TextAsset>("Tone"); // 有类型&无后缀,能加载到
    TextAsset txtAsset2 = ab.LoadAsset<TextAsset>("Tone.bytes"); //有类型&有后缀,能加载到

    RuntimeManager.LoadBank(txtAsset);
    string[] names = ab.GetAllAssetNames();
    for (int i = 0; i < names.Length; ++i)
    {
        Debug.LogError("name = " + names[i]);
    }

    TextAsset txtAsset3 = ab.LoadAsset<TextAsset>(names[0]); //这个names[0]=Assets/Desktop/bytes/Tone.bytes,其在tone.bundle.manifest中能找到
    if (txtAsset3 != null) //经实验,能加载到
    {
        Debug.LogError("well done!");
    }
}

其中:LoadBank(TextAsset asset, bool loadSamples = false)在RuntimeManager中:

public static void LoadBank(TextAsset asset, bool loadSamples = false)
{
	……
}

ok,在pc上测试成功;如果是手机上,我们如果不是下载的bundle文件的话,也好模拟(android手机),只要打包之后,找到包路径,将其bundle文件拷贝到持久化目录下,然后加载,经过测试也是成功的。成功的判断标准是,在未加载之前,播放Tone包里面的一个音频,是听不到声音的,并且报错事件找不到;但是在加载Tone之后,再次进行播放,则播放出声音了。

这是我拷贝手动拷贝到手机安装包里的bundle文件:
在这里插入图片描述
pc上和手机上加载的代码是不变的,路径都是Application.persistentDataPath。

第三种,如果是以原生的bank的方式,直接拷贝到Application.persistentDataPath,下如何加载呢?
就是我们不打包,直接进行bank的加载,只是此时bank在持久化的目录下而已。
我同样做了实验,将一个原始Tone.bank直接拷贝到Application.persistentDataPath下,然后用下面的函数加载:

public static void LoadBank()
{
    LoadedBank loadedBank = new LoadedBank();
    string bankPath = Application.persistentDataPath + "/Tone.bank";
    FMOD.RESULT loadResult = Instance.studioSystem.loadBankFile(bankPath, FMOD.Studio.LOAD_BANK_FLAGS.NORMAL, out loadedBank.Bank);
}

经过测试,加载争取。

综上,无论是Streaming Assets还是Asset Bundle,还是原生的bank只是拷贝到Application.persistentDataPath之后,都是可以正常加载的。

如果是考虑热更新的话,我是这样想的:
1、同名的bank,优先加载Application.persistentDataPath下的bank
2、音频制作方面,需要制作两份Master Bank,一个是在Streaming下的,一个是在Application.persistentDataPath下,如果是同名的bank,遵循规则1,这样就只加载一份的bank了。
3、也可是Streaming的不改,如果是新添加的音频,那么则直接在新的bank中,此bank热更到Application.persistentDataPath下。程序一运行,就直接读取两个目录下的所有的bank即可。
4、如果bank过大,考虑使用loadSampleData?这个没怎么研究,后面再补充下。结合profie分析下fmod的内存占用情况。还可以进一步的优化,进行bank的卸载:UnloadBank方法。

public static void UnloadBank(string bankName)
  {
      LoadedBank loadedBank;
      if (Instance.loadedBanks.TryGetValue(bankName, out loadedBank))
      {
          loadedBank.RefCount--;
          if (loadedBank.RefCount == 0)
          {
              loadedBank.Bank.unload();
              Instance.loadedBanks.Remove(bankName);
              return;
          }
          Instance.loadedBanks[bankName] = loadedBank;
      }
  }

5、判断以事件是否在bank中:


public static bool CheckEventInBank(string bankName, string eventName)
{
	  if (Instance.loadedBanks.ContainsKey(bankName))
	  {
	      LoadedBank bank = Instance.loadedBanks[bankName];
	      FMOD.Studio.EventDescription[] eventList;
	      var result = bank.Bank.getEventList(out eventList);
	      if (result == FMOD.RESULT.OK)
	      {
	          foreach (var eventDesc in eventList)
	          {
	              string path;
	              eventDesc.getPath(out path);
	              if (path.Equals(eventName)) return true;
	          }
	      }
	  }
	  return false;
}

ok,至此,fmod的音频打包,加载介绍完毕,后续在补充实际项目中遇到的问题。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
fmod是一个用于音频处理的库,它提供了许多函数和接口来获取和处理音频数据。要使用fmod获取音频数据并绘制图形,可以按照以下步骤进行: 1. 初始化fmod:首先,我们需要初始化fmod库。这可以通过调用fmod提供的初始化函数来完成。在初始化过程中,我们需要指定音频设备的一些参数,例如采样率、声道数等。 2. 创建fmod系统对象:一旦fmod初始化完成,我们可以创建一个fmod系统对象。系统对象可以用来管理和控制音频资源,包括加载音频文件、播放音频、获取音频数据等。 3. 打开音频文件:使用系统对象提供的函数,我们可以打开一个音频文件。打开音频文件后,我们可以通过fmod提供的函数来获取音频数据。例如,使用fmod系统对象的"getWaveData"函数可以获取当前播放位置的音频数据。 4. 绘制图形:获取到音频数据后,我们可以使用各种图形库或绘图工具来绘制图形。例如,我们可以使用Python中的matplotlib库或者其他绘图库来创建音频波形图。通过将获取到的音频数据作为输入,我们可以将其与时间轴进行绘制,以呈现音频信号的波形形状。 5. 音频数据:如果需要实时新绘图,我们可以使用一个循环来不断获取音频数据并新图形。在每次循环中,我们可以调用fmod的函数来获取新的音频数据,并使用绘图库来新图形。 总结:使用fmod获取音频数据并绘制图形的过程包括初始化fmod、创建系统对象、打开音频文件、获取音频数据和绘制图形。这些步骤可以帮助我们实现音频数据的可视化,以便好地理解和分析音频信号。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值