使用 Intel® 工具优化 PhonoPaper





5.00/5 (1投票)
得益于 Intel 借给我的用于测试的 x86 安卓平板电脑,PhonoPaper 得到了改进和优化。
Intel® Developer Zone 提供跨平台应用开发工具和指南、平台和技术信息、代码示例以及同行专业知识,帮助开发者创新并取得成功。加入我们的社区,了解 Android、物联网、Intel® RealSense™ 技术和 Windows,下载工具,访问开发套件,与志同道合的开发者分享想法,并参与黑客松、竞赛、路演和本地活动。
PhonoPaper 是一种技术和应用,它允许你将音频转换为一种特殊格式的图像(称为声谱图)在纸张或任何其他表面上播放。过程大致如下:10 秒的音频(语音、歌曲片段等)被转换为一种特殊格式的图像。打印出的图像可以贴在墙上。路过的人看到这个代码,在他们的手机上启动 PhonoPaper 扫描器,将摄像头对准图像,瞬间就能听到其中编码的声音。用户完全参与到这个过程中——播放的方向和速度取决于用户手部运动(当然也有自动模式)。所有必要的信息都存储在图像中,不需要互联网访问。
Phonopaper 实际应用示例
PhonoPaper 引起了音乐家、艺术家和新奇实验爱好者的浓厚兴趣。在 2014 年第三季度,该应用在 Apps4All.ru 网站上的 Intel Developer Rating 项目中 荣获第一名。得益于 Intel 借给我的用于测试的 x86 安卓* 平板电脑,该应用得到了改进和优化。在这里,我将展示我是如何优化 PhonoPaper 的。
视频捕获
我做的第一件事是集成 Intel® INDE Media for Mobile 库集,特别是 GLCapture 类,它可以实时捕获 OpenGL ES* 曲面的视频(高清音质)。这有什么必要呢?首先,捕获和播放 PhonoPaper 代码的过程就像演奏一种不寻常的乐器一样,是一个有趣、引人入胜的景象。其次,PhonoPaper 可以处于自由模式,当声音被随意转换为任意图像时,例如与地毯和猫。这两种情况都非常适合录制并上传到 YouTube*。
GLCapture 的集成过程在几篇文章中已有描述(1,2)。我只提及一些在开始之前了解清楚的点。
你应该使用 Android 4.3 或更高版本。对于较旧的设备,我创建了一个跨平台的 MJPEG 录像器,其速度和质量当然远不如硬件加速的 GLCapture(它以 mp4 格式写入)。但它仍然能够完成工作。
应用程序必须基于 OpenGL ES 2.0 构建。我的程序历史上使用的是 1.1 版本,所以我不得不重写代码。但转向 OpenGL ES 2.0 最终对生产力产生了积极影响,因为它提供了手动调整着色器的机会。
GLCapture 可以从麦克风录制声音。如果你想要伴随你评论的视频,这很有用。如果你需要应用程序中的高质量声音,你应该将它录制到单独的文件中,然后将其与 mp4 合并。要合并它们,你可以使用 MediaComposer 和 Media for Mobile 集中的 SubstituteAudioEffect 效果。另一种方法是录制 WAV,将 WAV 编码为 AAC,然后使用 mp4parser 库将 AAC 音轨添加到 mp4 文件中。
由于 PhonoPaper 是用 Pixilang 编程语言编写的,视频捕获功能以后可以与其他的基于 Pixilang 的应用程序(PixiTracker、PixiVisor、Nature - Oscillator、Virtual ANS)一起使用,最重要的是,它将对所有使用 Pixilang 的开发者可用。同时,访问非常简单(只有几个选项:开始捕获、停止和保存)。
Pixilang 是一种开源的跨平台编程语言,经过定制,可用于处理声音和图形。该语言的语法非常简洁,是 BASIC 和 C 的混合体,再加上其他特性(无需函数即可编写代码以及用于存储任何数据的通用容器),降低了入门门槛。
Intel® C++ 编译器和优化
下一步是使用 Intel® C Compiler 构建 PhonoPaper 的 x86 安卓版本,并将其结果与 GCC 4.8 进行比较。我使用 Debian Linux*,而且是一个相当旧的版本。因此,第一个问题是找到合适版本的 Intel C++ 编译器。幸运的是,找到了正确的安装包——Intel® System Studio 2015。尽管安装过程中有警告,但一切运行良好,第一次编译成功。
编译使用以下参数进行:-xATOM_SSSE3 -ipo -fomit-frame-pointer -fstrict-aliasing -finline-limit=300 -ffunction-sections -restrict。为了测试 Pixilang 虚拟机(它是我所有应用程序的基础)的性能,编写了一些小型测试,其源代码和结果可以在 此存档(zip)中查看。结果是,即使没有进行准备,一些代码片段也加速了 5 倍(!)。这令人印象深刻!
在 PhonoPaper 中,大部分负载在频谱合成器函数(表波,非 FFT)——wavetable_generator()。为此,写了一个单独的测试,在四秒内渲染一个具有随机频谱的音频流。测试结束时,产生最高可能的采样频率。不幸的是,Intel C 编译器在这里表现不佳:105 kHz,而 GCC 为 100 kHz。通过在编译时添加 -qopt-report=2 参数,报告中会显示此消息
循环未向量化:向量依赖阻止了向量化。
我们函数中的主循环无法向量化,因为输入数据指针可以指向重叠的内存区域。
int* amp = (int*)amp_cont->data int* amp_delta = (int*)amp_delta_cont->data;
查看代码,我发现此时重叠已经消除,我只需要告诉编译器。在 C/C++ 中有一个特殊的关键字 `restrict`,表示声明的指针指向一个内存块,而该内存块不被任何其他指针指向。因此,我将上述代码替换为
int* restrict amp = (int*)amp_cont->data; int* restrict amp_delta = (int*)amp_delta_cont->data;
然后,我编译应用程序,看到循环被成功向量化。通过一些额外的更改(在此过程中,证明可以消除几个位运算),结果现在是 190 kHz。考虑到这些修改,GCC 提供了 130 kHz——性能提高了 1.46 倍!
接下来是什么?
正如你所见,结果非常积极。PhonoPaper 现在运行速度更快(这很大程度上得益于 Intel C++ 编译器),并且增加了视频捕获功能。此外,视频录制功能将在下一个 Pixilang 3.6 更新中通过几个简单的函数提供。
这项优化甚至有助于完成录音、打印然后播放语音代码等任务。
PhonoPaper 还有很多值得探索的地方!
关于作者
Alexander Zolotov 是一名软件开发者、demoscene 艺术家、作曲家以及声音和图形设计师。他是 WarmPlace.ru 网站的所有者。他开发了多款视听应用:SunVox(模块化合成器和 tracker)、Virtual ANS、PhonoPaper、PixiTracker 和 Pixilang 编程语言。