
HarmonyOS项目实战:调频声波App(三)播放声音 原创
作者:大李子
团队:坚果派
十年iOS,All in转鸿蒙
调频声波App(一)概述
调频声波App(二)UI
调频声波App(三)播放声音
生成声波
思路(可以跳过)
形成声波并播放是这个App的核心功能,如何实现这个功能,属实走了很多弯路。起初认为这是一个计算密集任务,在网上查到了一个生成正弦波并输出wav文件的C语言实现,并开了一个C工程来验证功能。可以成功调整声波频率,并生成wav文件。
可以看到这段代码里面依赖三方库sndfile。所以起初为了把这段C代码放进App里,在native包上面研究了很久。包括怎么处理三方库sndfile的依赖,以及sndfile对其他库的依赖。尝试过直接集成源码,也尝试过编译不同处理器架构的so文件。但发现工作量太大,另外涉及到的技术栈不熟悉,花太多精力搞这个功能。之后换了个思路,找了一份不依赖三方库生成正弦波的C代码。
这段代码可以直接放到native子工程里,并在js端调用。之后又花了很多精力研究了一下App文件沙盒的访问,使C语言生成的wav文件能被js访问到。然后通过AVPlayer播放wav文件。
然而,根据App的功能,需要在主界面拖动并连续调整声波频率。考虑到每次调整频率都要删除旧的wav,生成新的wav,效率可能不够。实际的验证下拉也发现频率调节会有延迟和杂音的问题。
于是,继续研究,深入阅读源码,发现整个代码的核心功能在for循环里。在// Write WAV file header注释段中,写入的是wav文件头,这段数据可以舍弃,舍弃以后的文件只有纯声波数据(pcm文件)。所以是否可以直接把声波数据播放出来呢?
最终方案(正文开始)
最终我在文档里找到了AudioRenderer,这个组件可以把声波数据直接播放出来。
创建一个AudioRendererPlayer类来控制音频的播放,以下是该类中的核心代码。本代码示例省略了很多细节,包括AudioRenderer的创建过程和写入声波数据的异步操作,为的是展示最核心的实现思路。完整源码请参考AudioRendererPlayer.ets
除了正弦波之外,我们还可以生成其他的波形,把data[i]的赋值提取一个方法,判断当前类中设置的波形类型,生成相应的声波数据。
至此,本App的核心代码就讲解完成了。完整工程请参考这个链接
