首先鸣谢:溪夜大佬的博客:https://blog.audiokinetic.com/zh/everyone-can-use-waapi-overview/

本文环境:

Wwise 2019.1.9.7221

python 3.6.2(Anaconda3)

UE4 4.24.3

防伪刮刮乐:原文地址:https://www.cnblogs.com/lingchuL/p/14364085.html

一、配置环境

自己平时都是python 3.6.3裸奔,这次想试试Anaconda3,不得不说,有一个管理环境的工具确实要方便一些。

不要使用python 3.8!因为目前(2021.2),WAAPI的源码无法完全兼容python3.8。虽然pypl上写着自己支持3.8和3.9,但就是会因为time.block这个方法被3.8舍弃而没法import waapi-client。

1. Anaconda3的安装:https://segmentfault.com/a/1190000022797661

2. 配置 Anaconda 并在本地环境中通过 pip 添加 waapi-client:

https://zhuanlan.zhihu.com/p/25198543

https://conda.io/projects/conda/en/latest/user-guide/tasks/manage-pkgs.html#installing-non-conda-packages

3. 更新pip

默认的pip应该都是9.0.1的,但就安装不了waapi-client。要先更新一下pip。

但是最tm离谱的是,用pip install --upgrade pip来更新的话,很有可能因为网络原因反而继续提示你用--upgrade来更新pip。十足的鸡生蛋。根据这篇文章,使用如下命令:

python -m pip install --upgrade pip -i https://pypi.douban.com/simple

大概是镜像吧。

二、使用中的记录

1. pprint的作用

https://blog.csdn.net/qq_24185239/article/details/80977556

总的来说,pprint打印json的排版比print的更好看。通过 from pprint import pprint 来使用pprint。

2. WAAPI是什么?

如果你有阅读一点Wwise中对于WAAPI的介绍,你应该知道AK官方提供了几种方式来连接到Wwise:WAMP、HTTP POST和Wwise插件。

我这就只会记录WAMP,毕竟它最nb。

你可能很想知道Wwise的WAMP到底是什么,总之,先记住WAMP就类似于一种网络连接,理论上它可以连通你的程序和另一台电脑的Wwise,但它默认情况下只负责连接你的电脑和你自己电脑里的Wwise。如果你有使用过Unity/Unreal和Wwise进行实时调试,应该也会对上述过程有所理解(这一切就类似于,在Profiler视图中点击的Connect)。可以粗暴地想象为Wwise是个网站,而这个网站默认情况下就建在你的电脑里。总之,WAMP就是这样一个和Wwise通信的方式,而WAAPI就是Wwise官方推出的、钦定的,和Wwise通信使用的一系列方法、语法和规则。

2.1 连接建立

先来看下和Wwise通信的代码在python中大致模样。感觉首先知道代码大概长什么样,每部分在干什么,然后再去学WAAPI里那些细节的规则会更高效。

这部分大概说来我就是翻译了一下waapi-client库在其github页面中readme的部分内容,其余部分可以通过原文学习:https://github.com/audiokinetic/waapi-client-python

总的来说,先要引入WaapiClient。记忆角度而言的话:刚才说了,WAMP就相当于你的电脑/你自己编写的程序去连接Wwise。所以你现在在写的python代码/程序相当于就是Client(客户端)。Wwise就是那个服务器。

from waapi import WaapiClient

然后,有两种方法进行“客户端”的建立。

(1)

with WaapiClient() as client:

然后,就可以使用client进行后续的和Wwise的通信。但官方表示,这种方式会导致,client在with程序块之后会自动关闭。所以如果你希望,只是定义一个client,并且随时进行通信,可以使用第二种建立方式。

(2)

client=WaapiClient()

然后你就可以随时使用client进行通信了。

如果你有一定python基础,建议你看看WwapiClient()类的源码,还是比较清晰的:https://github.com/audiokinetic/waapi-client-python/blob/0d746223f56be6749dfaf0d78a6f10ffd2904c23/waapi/client/client.py#L30

如果你没有基础,那就继续看我的记录吧。

2.2 有了Client后要做什么

首先默认你拥有最基本的“面向对象”的编程知识,如果你是一名纯音效设计师没有学过编程,你可以考虑去廖雪峰的python教程中学习一下面向对象的基本知识。

client有一些方法,如果你没有基础,但又跳过了上面这段话的建议。我稍微说下,client就相当于游戏里一个角色,这对游戏音效设计师的你来说应该很熟悉吧?然后这个角色可能有很多技能,在面向对象的编程世界里,我们就把“角色、角色的技能”称为“对象、对象的方法”。

大致方法列举如下,再次推荐浏览源码,注释非常清晰。

2.2.1  call(self, _uri, *args, **kwargs)

  这个方法,用来进行远程程序调用(Remote Procedure Call, RPC),这六个字在Wwise官网也能见到。

  self,*args,**kwargs都是很多方法都会有的东西。而_uri则是远程程序的URI,它的所需类型为str。不用太在意URI原意是什么,因为其实这个位置上我们只需要指定WAAPI为我们提供的远程程序就行了。比如如果要获取wwise的基本信息,我们会使用名为ak.wwise.core.getInfo的这个远程程序!你可能还是一脸懵逼,但这部分暂时还不用太过在意!后文会详细地介绍它。总之你就记住,官方WAAPI已经提供了一大堆诸如刚才提到的getInfo的远程程序,然后这些程序都有各自的功能!

  虽然说*args,**kwargs是所有程序都会有的东西,但WAAPI里有的远程程序可能需要额外的参数,这些参数在编写代码时候也有着各自的规定!具体的规定对每个远程程序而言都是不一样的。比如刚才的getInfo,就不需要任何参数。这部分也会在之后介绍!现在只需要记住后面这两个东西之后还有一出戏份就好了!因为我们现在还是在介绍client的方法本身。

2.2.2  subscribe(self, _uri, callback_or_handler=None, *args, **kwargs)

  没骗你吧?self,*args,**kwargs都是很多方法都会有的东西。而_uri也和刚才的意思一样。

  这个方法,用来进行订阅主题(Subscribe to a topic)。是不是很不明所以,但官方就是这么叫它的,可能这就是程序员的浪漫吧(不是)。

  这个方法配合它的远程程序会比较好懂,所以在这里先举个例子吧:比如,这个方法有一个配套远程程序叫做ak.wwise.core.audio.imported,看这串名字都看出来了吧,它是一个,会在你在wwise导入文件后通知你的程序。也就是说,你使用subscribe连接到这个audio.imported的远程程序。然后远程程序会开始持续检测你是否导入文件,并且会在检测到导入操作后,以回传的方式通知你。而回传的接口,就是你在callback_or_handler中给它的一个函数句柄。

  源码中明确提醒,callback会从另一个线程返回,所以需要你的程序自行处理线程之间的冲突/竞争条件问题。所以再次建议强行读到这里的人,通过上文提到的廖雪峰的python教程,了解下面向对象和多线程编程,再来学习WAAPI。否则光是多线程的冲突就可能有麻烦的坑。

  值得一记的是所谓的callback_or_handler,总之只要是可以调用的东西就可以了。比如,函数,对象方法,甚至是实现了__call__方法的类实例,特别地,还有lambda函式。lambda的用法可以粗暴地如下记忆:函数名=lambda 参数列表:函数表达式。比如,test=lambda a,b:print(a+b),这样,就可以用test(1,2)之类的函数表达了。是不是超没用?反正我觉得挺装杯的,知道就行了。

  还值得一提的是,subscribe的返回值类型是一个Wwise官方自己定义的抽象类,叫做EventHandler,有基础的话也可以去看看它的源码。但是我们只要知道几点这个类有用的方法就行了。

    unsubscribe:用于随时取消订阅。

    bind:用于绑定一个新的接受返回通知的callback_or_handler。其实,官方源码也写了,之所以写了这个抽象类,就是为了方便我们随时切换绑定的接受返回通知函数。

以上可能有一点杂乱了,但是比对着下面这段代码应该就会立刻思路清晰!

from waapi import WaapiClient

# 连接Wwise (使用默认URL,也就是说会连接到自己电脑上的Wwise)
client = WaapiClient() # 使用client的call方法,进行远程程序调用,调用的是叫做getInfo的远程程序,然后远程程序会把它运行的结果返回给result。
result = client.call("ak.wwise.core.getInfo") # 使用client的subscribe方法,进行订阅主题,订阅的是object.created的远程程序,这个程序会在有wwise对象被创建时返回通知。handler用于持续地控制这个订阅。
handler = client.subscribe(
"ak.wwise.core.object.created",
lambda object: print("Object created: " + str(object))
) # 随时都可以切换接收通知的函数
def my_callback(object):
print("Different callback: " + str(object)) handler.bind(my_callback) # 使用handler的方法unsubscribe取消订阅
handler.unsubscribe() # 使用client的方法disconnect断开和Wwise的连接
client.disconnect()

 2.3  远程程序详细介绍

首先,其实Wwise自身提供的文档介绍非常详细:https://www.audiokinetic.com/zh/library/edge/?source=SDK&id=waapi_index.html

用一个结构相对比较简单且有特殊结构的远程程序来举例,它就是ak.wwise.core.object.get。

调用这个程序,需要给予Wwise两大类参数:Arguments和Options。首先,前者的Wwise文档如图。

根据表格最下方的标注,带星号的项目都是必要的参数。对这里的get而言,就是from参数必须。(因为transform本身不是必须的,所以虽然它下面有一些transform.select是必须的,但总的来说并不是必须的。)

还有就是,中间的Type列中,会有一些行内容为 one of、any of,其实这就是在说,下面几行的都可以。比如from,既可以用id指定,也可以用path指定,你会发现每一个都对应了下面带星号的Name。

一定要注意中间Type为每个参数指定的类型,按照类型来书写参数才不会出错。

而对于Options,则没有什么必须提供的参数。并且其书写规则与上面Arguments表的书写规则一致。

虽然熟悉了之后这表看着也挺快的,但这种书写格式对你可能不够亲切。如果那样的话,你可以使用json格式转换器,把上面Arguments那张图最底下的Arguments Schema里的内容,转换换为较易阅读的格式,转换后如图:

首先是这个样子,最大类别中有一个required的参数,为from。符合我们上面直接读表的结论。接下来,是全部properties的内容如图。

所有的参数,共有from和transform两大类。这也与我们上面直接读表的结论一致。最后,再象征性地展开properties里的from和transform看看。

可以发现,分别显示了六个和四个可选参数类型,其实如果再点开,就会发现它们分别对应于上面我们在表里from和transform对应的Type里看见的几个参数名了。这可能会适合一些人的思维习惯吧。

2.4  把至此为止的知识结合起来

然后,在写代码的时候,需要注意,call方法只能调用Functions的远程函数,而subscribe只能调用Topics的远程函数!

而2.3中提到的这一大堆参数,在书写时,官方有几种格式可供选择。但推荐使用类似于以下的格式。

args={
"from": {
"id": [ "{A076AA65-B71A-45BB-8841-5A20C52CE727}", "{2028C899-8300-4667-ADD0-ED10467BD91E}", "{24979032-B170-43E3-A2E4-469E0193E2C3}" ] }
}

总之就是类似于python中的字典的形式。细心的话会发现这里只有args,那说好的kwargs呢,其实官方实现了一个能将输入参数合并的内部方法,刚才说的“几种格式可供选择”也是得益于此。

然后,调用call的时候,就是形如以下代码:

client.call("ak.wwise.core.object.get",args)

(持续补充)

WAAPI+Python使用中的相关问题和学习记录的更多相关文章

  1. Python全栈工程师系列学习之学习记录

    @ 目录 前言 Day 01 一.python的历史和种类 二.安装python解释器以及配置环境变量 三.变量.常量和注释 Day 02 Day 03 Day 04 Day 05 Day 06 一. ...

  2. python 加密算法及其相关模块的学习(hashlib,random,string,math)

    加密算法介绍 一,HASH Hash,一般翻译做“散列”,也有直接音译为”哈希”的,就是把任意长度的输入(又叫做预映射,pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值.这种 ...

  3. python加密算法及其相关模块的学习(hashlib,RSA,random,string,math)

    加密算法介绍 一,HASH Hash,一般翻译做“散列”,也有直接音译为”哈希”的,就是把任意长度的输入(又叫做预映射,pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值.这种 ...

  4. Python标准库之核心模块学习记录

    内建函数和异常 包括__builtin__模块和exceptions模块 操作系统接口模块 包括提供文件和进程处理功能的os模块,提供平台独立的文件名处理(分拆目录名,文件名,后缀等)的os.path ...

  5. 流畅的python第二十章属性描述符学习记录

    描述符是对多个属性运用相同存取逻辑的一种方式.例如,Django ORM 和 SQL Alchemy等 ORM 中的字段类型是描述符,把数据库记录中字段里的数据与 Python 对象的属性对应起来.描 ...

  6. 流畅的python第五章一等函数学习记录

    在python中,函数是一等对象,一等对象是满足以下条件的程序实体 1在运行时创建 2能复制给变量或数据结构的元素 3能作为参数传给函数 4能作为函数的返回结果 高阶函数(接受函数作为参数或者把函数作 ...

  7. Python学习记录day6

    title: Python学习记录day6 tags: python author: Chinge Yang date: 2016-12-03 --- Python学习记录day6 @(学习)[pyt ...

  8. Python学习记录day5

    title: Python学习记录day5 tags: python author: Chinge Yang date: 2016-11-26 --- 1.多层装饰器 多层装饰器的原理是,装饰器装饰函 ...

  9. Python之路,Day21 - 常用算法学习

    Python之路,Day21 - 常用算法学习   本节内容 算法定义 时间复杂度 空间复杂度 常用算法实例 1.算法定义 算法(Algorithm)是指解题方案的准确而完整的描述,是一系列解决问题的 ...

随机推荐

  1. Beta冲刺——汇总随笔

    一.代码规范与计划随笔 Beta冲刺--代码规范与计划 二.凡事预则立随笔 Beta冲刺--凡事预则立 三.10篇冲刺随笔 Beta冲刺--第一天 Beta冲刺--第二天 Beta冲刺--第三天 Be ...

  2. 【剑指 Offer】10-II.青蛙跳台阶问题

    题目描述 一只青蛙一次可以跳上1级台阶,也可以跳上2级台阶.求该青蛙跳上一个 n 级的台阶总共有多少种跳法. 答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008, ...

  3. 肌肤管家SkinRun V3S智能皮肤检测仪,用AI探索肌肤问题

    继肌肤管家SkinRun V3皮肤检测仪之后,肌肤管家SkinRun近期又一重磅推出的肌肤管家SkinRun V3S 智能肌肤测试仪引起了美业人的广泛关注.据了解它汇集百万皮肤数据,利用五光谱原理和人 ...

  4. python学习笔记 | selenium各浏览器驱动下载地址

    Chrome http://chromedriver.storage.googleapis.com/index.html 不同的Chrome的版本对应的chromedriver.exe 版本也不一样, ...

  5. 解决Tengine健康检查引起的TIME_WAIT堆积问题

    简介: 解决Tengine健康检查引起的TIME_WAIT堆积问题 一. 问题背景 "服务上云后,我们的TCP端口基本上都处于TIME_WAIT的状态"."这个问题在线下 ...

  6. three.js 之cannon.js物理引擎

    今天郭先生说的是一个物理引擎,它十分小巧并且操作简单,没错他就是cannon.js.这些优点都源自于他是基于js编写的,对于js使用者来说cannon.js拥有其他物理引擎没有的纯粹性.从学习成本来看 ...

  7. LRU(Least Recently Used)最近未使用置换算法--c实现

    在OS中,一些程序的大小超过内存的大小(比如好几十G的游戏要在16G的内存上跑),便产生了虚拟内存的概念 我们通过给每个进程适当的物理块(内存),只让经常被调用的页面常驻在物理块上,不常用的页面就放在 ...

  8. CSAPP:Lab1 -DataLab 超详解

    写在前面 之前考研的时候csapp的书有刷过5,6遍,所以对书本知识还算比较了解.恰逢最近在学c++的时候,顺带刷一下大名鼎鼎的csapp实验. 0. 环境准备 最好准备一个纯净的Linux系统这里建 ...

  9. 三节锂电池充电管理芯片,IC电路图如何设计

    关于三节锂电池供电的产品,在三节锂电池上,需要三个电路系统: 1,三节锂电池保护电路, 2,三节锂电池充电电路, 3,三节锂电池输出电路. 1.三节锂电池保护电路,芯片电路图 控制三节锂电池池的充电电 ...

  10. CentOS系统内核升级(在线 离线)

    为什么要升级内核? Docker 在CentOS系统中需要安装在 CentOS 7 64 位的平台,并且内核版本不低于 3.10:CentOS 7.× 满足要求的最低内核版本要求,但由于 CentOS ...