目录
sf::SoundSource and audio in 3D
Preface
● 从SFML开始,我们已经走了很长的路,在到达终点之前,我们还有一段路要走。 本章介绍了SFML在音频模块内部的声音特征。这包括声音、音乐和3D声音环境。本章的最后一部分介绍了如何在屏幕上呈现文本。
在本章中,我们将介绍以下主题:
- Audio module—an overview
- Sound versus music
- Audio in action
- sf::SoundSource and sound in 3D
- Getting started with sf::Text
Audio module – overview
● 到目前为止,我们只使用了SFML的 window, graphics, and system modules. window module 处理本地的操作系统窗口以及与其相关联的功能。graphics module 使我们可以容易地在屏幕上绘制对象。系统模块保存vector classes ,并将操作系统的特性封装在处理时间的常见类(如时钟和时间类)之后(系统模块保存向量类,并将操作系统的功能特性在常用类之后,例如时钟和时间类,它们处理时间)。
SFML中还有两个模块—— audio and network. 我们将在本书的最后一章讨论network module。本章主要介绍audio module 及其功能. 这个module中最重要的类是 sf :: Sound和sf :: Music。 它们为我们提供了播放 sounds and music的方法。还有一个功能可以让你播放3D声音,这意味着可以根据听众的位置和方向从不同方向播放声音。我们将在本章深入探讨这些功能。还有一些模块包含的内容超出了本书的范围,例如SoundRecorder类,它可以记录来自输入设备(例如麦克风)的声音 。
话虽如此,我们现在准备开始使用audio module 。 我们需要讨论的第一件事是,有两个不同的classes 可以通过它来播放audio , Sound 和Music 类。从外面看,他们似乎在做同样的事情,都是在播放audio 文件; 然而,俗话说“不要以貌取人”。
Sound versus music
● 乍一看,这两个类的存在可能看起来很奇怪, 但它们最终的用途不同,而这一切都归功于它们的实现方式有所不同。
Sound类将其所有数据加载到系统内存中,这使得播放音频样本变得非常快。另一方面,Music类将流打开到随机访问内存(或RAM)上的文件,并加载一小块数据,这些数据一个接一个地播放。根据它的设计, Music类会因为在慢的地方传输数据导致播放有延迟.
这两个类提供了不同的好处,Sound 类几乎可以立即播放,但需要大量的系统内存,而Music 类播放速度较慢,但根本不需要太多内存。因此,这两个类在不同的情况下都是有用的。例如,如果audio 文件足够小,可以存储在系统内存中,我们应该使用Sound类加载它。这适用于在调用其play()方法后立即播放声音的情况。有时,当文件太大时,我们必须牺牲内存,而且必须立即播放,这就是为什么资源管理很重要(删除未使用资源注并加载新资源)。另一方面,Music类主要用于audio 音频文件,在这些文件中,即使在开始时播放延迟了一点,也不重要。这个类主要用于游戏的背景音乐。
Sound和Music在它们的继承树SoundSource中有相同的类,SoundSource提供一种常见的audio 功能,例如改变pitch and 3D positioning. Sound类直接派生自它,而Music派生自SoundStream。最后,SoundStream派生自SoundSource。下图展示了它们之间的关系:
我们将在本章后面详细介绍SoundSource和SoundStream。
这一节可以总结为: 利用Sound来播放声音效果(枪声、脚步声等),利用music来播放背景音乐。现在您已经了解了这两者之间的区别,让我们继续学习一些代码。
Audio in action
我们先讨论Music 效果然后在讨论Music .
The sf::Sound class
● Sound由两个类组成,Sound 和SoundBuffer。SoundBuffer类是内存中的资源,而Sound是播放资源的包装器。因为它使用与Sprite相同的结构,而Texture-Sprite使用Texture作为资源。通过以这种方式设计,多个Sound实例可以使用同一个SoundBuffer实例,显著减少了所需的内存量。
这些解释已经足够了,下面是我们如创建Sound:
#include<SFML/Audio.hpp>
int main()
{
sf::Window window(sf::VideoMode(640, 480), "Audio");
sf::SoundBuffer sBuffer;
if (!sBuffer.loadFromFile("mySound.ogg"))
return -1;
sf::Sound sound(sBuffer);
while (window.isOpen())
{
// Game loop
}
return 0;
}
我们使用与SoundBuffer相同的格式加载Texture —— 检查加载是否失败,并相应地执行一些操作。在这种情况下,没有SoundBuffer,继续执行程序是没有意义的,所以我们将终止它。一些常见的支持音频格式是:OGG,WAV,FLAC等。 请注意,由于许可问题,不支持MP3。
类似于sf::Texture,sound buffers有从内存加载( SoundBuffer::loadFromMemory ( ) )和从流加载( SoundBuffer::loadFromStream ( ) )的方法。Texture也可以从像素数组中加载,但是,就声音缓冲区而言,这没有什么意义。相反,SoundBuffer类具有从样本数组中加载的方法(SoundBuffer::loadFromSamples())。
一旦我们通过调用sf::Sound的构造函数并传递 sound buffer来创建它,我们就可以使用Sound::play()来播放它。该方法根据Sound的当前状态执行不同的操作。 该方法在另一个线程中播放声音,因此不会 阻塞当前线程。
每个SoundSource对象都有与之关联的SoundSource::Status (enum)。它可以是三种状态之一:Stopped, Paused, or Playing. 此状态系统在SoundSource类内部使用,以控制其方法的行为。 可以通过调用其getState()方法来获取Sound或Music对象的状态。
返回到Sound::play ( ),在stopped or paused 的状态下,该方法从其当前播放位置开始播放声音。如果它处于播放状态,它会重启sound。 这意味着当我们想要多次播放相同的sound 时我们必须要小心。对此最好的解决方案是每次需要播放声音时创建多个Sound实例。 由于所有这些实例都使用相同的SoundBuffer实例,因此创建声音非常快速和轻松的,因此我们不必担心性能或内存
Sound类也有stopping and pausing&nbs