2016-05-19 06:13:01 +00:00
|
|
|
### Amuse
|
2016-05-02 21:52:27 +00:00
|
|
|
|
|
|
|
**Amuse** is a real-time MIDI and SFX sequencer, with basic effects,
|
|
|
|
3D positional audio and surround-output capabilities.
|
|
|
|
|
|
|
|
The project is designed for compatibility with Audio Groups and Song data
|
2016-05-08 07:33:47 +00:00
|
|
|
found in PC/N64/GCN/GBA games using the *MusyX* audio engine; providing an
|
2016-05-02 21:52:27 +00:00
|
|
|
alternate runtime library to use for sequencing these games' audio libraries.
|
|
|
|
|
|
|
|
#### Library
|
|
|
|
|
|
|
|
The Amuse API exposes full interactivity between a client application
|
|
|
|
(game engine) and the sequencer engine. Unlike the interrupt-driven nature
|
|
|
|
of the original console implementations (where the audio chip 'requests' more
|
|
|
|
audio as needed), Amuse is entirely synchronous. This means the client must
|
|
|
|
periodically *pump* the audio engine (typically once per video frame) to keep
|
|
|
|
the OS' audio system fed.
|
|
|
|
|
|
|
|
The client must provide the implementation for allocating and mixing audio
|
|
|
|
voices, since this may drastically differ from target to target.
|
2016-05-03 06:38:14 +00:00
|
|
|
`amuse::IBackendVoiceAllocator` is the pure-virtual interface to implement
|
2016-05-08 07:33:47 +00:00
|
|
|
for this. Alternatively, if [Boo](https://github.com/AxioDL/boo) is present
|
|
|
|
in the CMake project tree, Amuse will be compiled with a backend supporting
|
|
|
|
multiple popular low-level audio APIs. Windows, OS X, and Linux all have
|
|
|
|
excellent support this way.
|
2016-05-02 21:52:27 +00:00
|
|
|
|
|
|
|
Here's an example usage:
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
#include <amuse/amuse.hpp>
|
|
|
|
#include "MyVoiceAllocator.hpp"
|
2016-05-02 21:54:23 +00:00
|
|
|
#include "MyAudioGroupLoader.hpp"
|
2016-05-02 21:52:27 +00:00
|
|
|
|
|
|
|
int main(int argc, char* argv[])
|
|
|
|
{
|
|
|
|
/* Up to the client to implement voice allocation and mixing */
|
2016-05-03 01:16:26 +00:00
|
|
|
std::unique_ptr<amuse::IBackendVoiceAllocator> voxAlloc = MakeMyVoiceAllocator();
|
2016-05-02 21:52:27 +00:00
|
|
|
|
|
|
|
/* Application just needs one per audio output (not per channel) */
|
|
|
|
amuse::Engine snd(*voxAlloc);
|
|
|
|
|
|
|
|
/* An 'AudioGroup' is an atomically-loadable unit within Amuse.
|
|
|
|
* A client-assigned integer serves as the handle to the group once loaded
|
|
|
|
*/
|
2016-05-15 21:56:23 +00:00
|
|
|
amuse::IntrusiveAudioGroupData data = LoadMyAudioGroup();
|
|
|
|
snd.addAudioGroup(data);
|
2016-05-02 21:52:27 +00:00
|
|
|
|
|
|
|
/* Starting a SoundMacro playing is accomplished like so: */
|
|
|
|
int sfxId = 0x1337;
|
|
|
|
float vol = 1.0f;
|
|
|
|
float pan = 0.0f;
|
2016-05-14 05:19:57 +00:00
|
|
|
std::shared_ptr<Voice> voice = snd.fxStart(sfxId, vol, pan);
|
2016-05-02 21:52:27 +00:00
|
|
|
|
|
|
|
/* Play for ~5 sec */
|
|
|
|
int passedFrames = 0;
|
|
|
|
while (passedFrames < 300)
|
|
|
|
{
|
|
|
|
snd.pumpEngine();
|
|
|
|
++passedFrames;
|
|
|
|
WaitForVSync();
|
|
|
|
}
|
|
|
|
|
2016-05-03 05:16:37 +00:00
|
|
|
/* Stopping a SoundMacro is accomplished by sending a
|
2016-05-02 21:52:27 +00:00
|
|
|
* MIDI-style 'KeyOff' message for the voice
|
|
|
|
*/
|
2016-05-03 06:40:17 +00:00
|
|
|
voice->keyOff();
|
2016-05-02 21:52:27 +00:00
|
|
|
|
|
|
|
/* Play for 2 more seconds to allow the macro to gracefully fade-out */
|
|
|
|
passedFrames = 0;
|
|
|
|
while (passedFrames < 120)
|
|
|
|
{
|
|
|
|
snd.pumpEngine();
|
|
|
|
++passedFrames;
|
|
|
|
WaitForVSync();
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Clean up and exit */
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
```
|
2016-05-02 22:02:50 +00:00
|
|
|
|
|
|
|
#### Tool
|
|
|
|
|
|
|
|
In addition to the library, a command-line tool for performing various pipeline
|
|
|
|
tasks is provided. Compilers for audio groups and song data, as well as basic
|
|
|
|
playback functionality is available via the tool.
|