1 //-----------------------------------------------------------------------------
2 // Copyright (c) 2015-2018 Marcelo Fernandez
3 //
4 // Permission is hereby granted, free of charge, to any person obtaining a copy
5 // of this software and associated documentation files (the "Software"), to
6 // deal in the Software without restriction, including without limitation the
7 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8 // sell copies of the Software, and to permit persons to whom the Software is
9 // furnished to do so, subject to the following conditions:
10 //
11 // The above copyright notice and this permission notice shall be included in
12 // all copies or substantial portions of the Software.
13 //
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20 // IN THE SOFTWARE.
21 //-----------------------------------------------------------------------------
22 
23 #ifndef __OAML_H__
24 #define __OAML_H__
25 
26 #include <stddef.h>
27 
28 //
29 // Definitions
30 //
31 
32 #define OAML_VOLUME_MIN		0.f
33 #define OAML_VOLUME_MAX		1.f
34 
35 #define OAML_VOLUME_DEFAULT	0.5f
36 
37 //
38 typedef enum {
39 	OAML_CONDTYPE_EQUAL	= 0, // x == value
40 	OAML_CONDTYPE_GREATER	= 1, // x > value
41 	OAML_CONDTYPE_LESS	= 2, // x < value
42 	OAML_CONDTYPE_RANGE	= 3  // x >= value AND x <= value2
43 } oamlCondType;
44 
45 // Condition id's 1-9 are reserved for oaml core
46 typedef enum {
47 	OAML_CONDID_TENSION	= 1,
48 	OAML_CONDID_MAIN_LOOP	= 2,
49 	OAML_CONDID_USER	= 10
50 } oamlCondId;
51 
52 // Return codes
53 typedef enum {
54 	OAML_OK			= 0,
55 	OAML_ERROR		= -1,
56 	OAML_NOT_FOUND		= -2
57 } oamlRC;
58 
59 typedef struct {
60 	void*  (*open)  (const char *filename);
61 	size_t (*read)  (void *ptr, size_t size, size_t nitems, void *fd);
62 	int    (*seek)  (void *fd, long offset, int whence);
63 	long   (*tell)  (void *fd);
64 	int    (*close) (void *fd);
65 } oamlFileCallbacks;
66 
67 
68 #ifndef __cplusplus
69 
70 #ifdef _MSC_VER
71 typedef int bool;
72 #define false 0
73 #define true 1
74 #else
75 #include <stdbool.h>
76 #endif
77 
78 const char* oamlGetVersion();
79 oamlRC oamlInitAudioDevice(int sampleRate, int channels);
80 oamlRC oamlInit(const char *defsFilename);
81 oamlRC oamlReadDefsFile(const char *defsFilename);
82 oamlRC oamlInitString(const char *defs);
83 void oamlSetAudioFormat(int sampleRate, int channels, int bytesPerSample, bool floatBuffer);
84 oamlRC oamlPlayTrack(const char *name);
85 oamlRC oamlPlayTrackWithStringRandom(const char *str);
86 oamlRC oamlPlayTrackByGroupRandom(const char *group);
87 oamlRC oamlPlayTrackByGroupAndSubgroupRandom(const char *group, const char *subgroup);
88 oamlRC oamlPlaySfx(const char *name);
89 oamlRC oamlPlaySfxEx(const char *name, float vol, float pan);
90 oamlRC oamlPlaySfx2d(const char *name, int x, int y, int width, int height);
91 bool oamlIsTrackPlaying(const char *name);
92 bool oamlIsPlaying();
93 void oamlStopPlaying();
94 void oamlPause();
95 void oamlResume();
96 void oamlPauseToggle();
97 bool oamlIsPaused();
98 void oamlMixToBuffer(void *buffer, int size);
99 void oamlSetCondition(int id, int value);
100 void oamlSetVolume(float vol);
101 float oamlGetVolume();
102 void oamlAddTension(int value);
103 void oamlSetTension(int value);
104 void oamlSetMainLoopCondition(int value);
105 void oamlUpdate();
106 void SetDebugClipping(bool option);
107 void SetWriteAudioAtShutdown(bool option);
108 void oamlSetFileCallbacks(oamlFileCallbacks *cbs);
109 void oamlEnableDynamicCompressor(bool enable, double threshold, double ratio);
110 const char* oamlGetDefsFile();
111 const char* oamlGetPlayingInfo();
112 void oamlShutdown();
113 
114 #else
115 
116 #include <algorithm>
117 #include <string>
118 #include <vector>
119 
120 typedef struct {
121 	std::string filename;
122 	std::string layer;
123 	int randomChance;
124 } oamlAudioFileInfo;
125 
126 typedef struct {
127 	std::string name;
128 	int type;
129 	float volume;
130 	float bpm;
131 	int beatsPerBar;
132 	int bars;
133 	int minMovementBars;
134 	int randomChance;
135 	int playOrder;
136 	int fadeIn;
137 	int fadeOut;
138 	int xfadeIn;
139 	int xfadeOut;
140 	int condId;
141 	int condType;
142 	int condValue;
143 	int condValue2;
144 	std::vector<oamlAudioFileInfo> files;
145 } oamlAudioInfo;
146 
147 typedef struct {
148 	std::string name;
149 	std::vector<std::string> groups;
150 	std::vector<std::string> subgroups;
151 	bool musicTrack;
152 	bool sfxTrack;
153 	int fadeIn;
154 	int fadeOut;
155 	int xfadeIn;
156 	int xfadeOut;
157 	float volume;
158 	std::vector<oamlAudioInfo> audios;
159 } oamlTrackInfo;
160 
161 typedef struct {
162 	float bpm;
163 	int beatsPerBar;
164 	std::vector<oamlTrackInfo> tracks;
165 } oamlTracksInfo;
166 
167 
168 //
169 // Internal declarations
170 //
171 
172 class oamlBase;
173 class oamlStudioApi;
174 
175 //
176 // Main class
177 //
178 
179 #if defined(oaml_shared_EXPORTS) || defined(OAML_EXPORTS)
180 class DLLEXPORT oamlApi {
181 #else
182 class oamlApi {
183 #endif
184 private:
185 	oamlBase *oaml;
186 	oamlStudioApi *oamlStudio;
187 
188 public:
189 	oamlApi();
190 	~oamlApi();
191 
192 	const char* GetVersion();
193 
194 	/** Initilize the Open Adaptive Music Library with the path to 'oaml.defs'
195 	 *  @return returns OAML_OK on success
196 	 */
197 	oamlRC Init(const char *defsFilename);
198 
199 	/** Read Open Adaptive Music Library definition file
200 	 *  @return returns OAML_OK on success
201 	 */
202 	oamlRC ReadDefsFile(const char *defsFilename);
203 
204 	/** Initilize the Open Adaptive Music Library with xml definitions on value defs
205 	 *  @return returns OAML_OK on success
206 	 */
207 	oamlRC InitString(const char *defs);
208 
209 	/** Initialize the audio device through RtAudio
210 	 *  @return returns OAML_OK on success
211 	 */
212 	oamlRC InitAudioDevice(int sampleRate = 44100, int channels = 2);
213 
214 	/** Shutdown the library */
215 	void Shutdown();
216 
217 	/** Set the audio format to be used by MixToBuffer */
218 	void SetAudioFormat(int sampleRate, int channels, int bytesPerSample, bool floatBuffer = false);
219 	void SetVolume(float vol);
220 	float GetVolume();
221 
222 	/** Play a music track by name (recommended) or id
223 	 *  @return returns OAML_OK on success
224 	 */
225 	oamlRC PlayTrack(const char *name);
226 
227 	/** Play a random music track that contains str in the name
228 	 *  @return returns OAML_OK on success
229 	 */
230 	oamlRC PlayTrackWithStringRandom(const char *str);
231 
232 	/** Play a random music track that belongs to a certain group
233 	 *  @return returns OAML_OK on success
234 	 */
235 	oamlRC PlayTrackByGroupRandom(const char *group);
236 
237 	/** Play a random music track that belongs to a certain group and subgroup
238 	 *  @return returns OAML_OK on success
239 	 */
240 	oamlRC PlayTrackByGroupAndSubgroupRandom(const char *group, const char *subgroup);
241 
242 	/** Play a sound fx
243 	 *  @return returns OAML_OK on success
244 	 */
245 	oamlRC PlaySfx(const char *name);
246 	oamlRC PlaySfxEx(const char *name, float vol, float pan);
247 	oamlRC PlaySfx2d(const char *name, int x, int y, int width, int height);
248 
249 	/** Load a track into memory cache (blocking)
250 	 */
251 	oamlRC LoadTrack(const char *name);
252 
253 	/** Load a track into memory cache (non-blocking)
254 	 *  @return returns 0.f to 1.f or -1.f on error
255 	 */
256 	float LoadTrackProgress(const char *name);
257 
258 	/** Stop playing any track currently playing */
259 	void StopPlaying();
260 
261 	/** Pause playback */
262 	void Pause();
263 
264 	/** Resume playback */
265 	void Resume();
266 
267 	/** Pause/resume playback */
268 	void PauseToggle();
269 
270 	/** Are we in pause state? */
271 	bool IsPaused();
272 
273 	/** Check if a track is playing */
274 	bool IsTrackPlaying(const char *name);
275 
276 	/** Check if any track is playing */
277 	bool IsPlaying();
278 
279 	/** Add tension that triggers different aspects of the music */
280 	void AddTension(int value);
281 
282 	/** Set tension that triggers different aspects of the music */
283 	void SetTension(int value);
284 
285 	/** Get the current tension value */
286 	int GetTension();
287 
288 	/** Sets a condition that affects the main loop */
289 	void SetMainLoopCondition(int value);
290 
291 	/** Set a condition */
292 	void SetCondition(int id, int value);
293 
294 	/** Clears current conditions */
295 	void ClearConditions();
296 
297 	/** Set gain (0.f - 1.f) of a layer */
298 	void SetLayerGain(const char *layer, float gain);
299 
300 	/** Get gain (0.f - 1.f) of a layer */
301 	float GetLayerGain(const char *layer);
302 
303 	/** Set random chance (0 - 100) of a layer */
304 	void SetLayerRandomChance(const char *layer, int rhandomChance);
305 
306 	/** Get random chance (0 - 100) of a layer */
307 	int GetLayerRandomChance(const char *layer);
308 
309 	/** Main function to call form the internal game audio manager */
310 	void MixToBuffer(void *buffer, int size);
311 
312 	/** Update */
313 	void Update();
314 
315 	/** Debugging functions */
316 	void SetDebugClipping(bool option);
317 	void SetWriteAudioAtShutdown(bool option);
318 
319 	/** Enable dynamic compressor for music */
320 	void EnableDynamicCompressor(bool enable = true, double thresholdDb = -3, double ratio = 4.0);
321 
322 	/** Set file handling callbacks */
323 	void SetFileCallbacks(oamlFileCallbacks *cbs);
324 
325 	/** Returns the 'oaml.defs' filename that was used for initialization */
326 	const char* GetDefsFile();
327 
328 	/** Returns a simple text showing the track and audios being played */
329 	const char* GetPlayingInfo();
330 
331 	/** Returns a pointer to the tracks information */
332 	oamlTracksInfo *GetTracksInfo();
333 
334 	/** Returns the current playing state as a string, this can be used to resume the exact music state with LoadState */
335 	std::string SaveState();
336 
337 	/** Resume the exact music state that was saved using SaveState */
338 	void LoadState(std::string state);
339 
340 	/** Returns a pointer to the oamlStudioApi class */
341 	oamlStudioApi *GetStudioApi();
342 };
343 
344 
345 //
346 // oamlStudioApi, this api is used by the oamlStudio app
347 //
348 
349 #if defined(oaml_shared_EXPORTS) || defined(OAML_EXPORTS)
350 class DLLEXPORT oamlStudioApi {
351 #else
352 class oamlStudioApi {
353 #endif
354 private:
355 	oamlBase *oaml;
356 
357 public:
358 	oamlStudioApi(oamlBase *_oaml);
359 	~oamlStudioApi();
360 
361 	void ProjectNew();
362 	void ProjectSetBPM(float bpm);
363 	void ProjectSetBeatsPerBar(int beatsPerBar);
364 
365 	float ProjectGetBPM();
366 	int ProjectGetBeatsPerBar();
367 
368 	oamlRC TrackNew(std::string name, bool sfxTrack = false);
369 	oamlRC TrackRemove(std::string name);
370 	void TrackRename(std::string name, std::string newName);
371 	void TrackSetVolume(std::string name, float volume);
372 	void TrackSetFadeIn(std::string name, int fadeIn);
373 	void TrackSetFadeOut(std::string name, int fadeOut);
374 	void TrackSetXFadeIn(std::string name, int xFadeIn);
375 	void TrackSetXFadeOut(std::string name, int xFadeOut);
376 
377 	bool TrackExists(std::string name);
378 	bool TrackIsSfxTrack(std::string name);
379 	bool TrackIsMusicTrack(std::string name);
380 	void TrackGetAudioList(std::string name, std::vector<std::string>& list);
381 	float TrackGetVolume(std::string name);
382 	int TrackGetFadeIn(std::string name);
383 	int TrackGetFadeOut(std::string name);
384 	int TrackGetXFadeIn(std::string name);
385 	int TrackGetXFadeOut(std::string name);
386 
387 	oamlRC AudioNew(std::string trackName, std::string audioName, int type);
388 	oamlRC AudioRemove(std::string trackName, std::string audioName);
389 	void AudioAddAudioFile(std::string trackName, std::string audioName, std::string filename);
390 	void AudioSetName(std::string trackName, std::string audioName, std::string name);
391 	void AudioSetVolume(std::string trackName, std::string audioName, float volume);
392 	void AudioSetBPM(std::string trackName, std::string audioName, float bpm);
393 	void AudioSetBeatsPerBar(std::string trackName, std::string audioName, int beatsPerBar);
394 	void AudioSetBars(std::string trackName, std::string audioName, int bars);
395 	void AudioSetMinMovementBars(std::string trackName, std::string audioName, int minMovementBars);
396 	void AudioSetRandomChance(std::string trackName, std::string audioName, int randomChance);
397 	void AudioSetFadeIn(std::string trackName, std::string audioName, int fadeIn);
398 	void AudioSetFadeOut(std::string trackName, std::string audioName, int fadeOut);
399 	void AudioSetXFadeIn(std::string trackName, std::string audioName, int xFadeIn);
400 	void AudioSetXFadeOut(std::string trackName, std::string audioName, int xFadeOut);
401 	void AudioSetCondId(std::string trackName, std::string audioName, int condId);
402 	void AudioSetCondType(std::string trackName, std::string audioName, int condType);
403 	void AudioSetCondValue(std::string trackName, std::string audioName, int condValue);
404 	void AudioSetCondValue2(std::string trackName, std::string audioName, int condValue2);
405 
406 	bool AudioExists(std::string trackName, std::string audioName);
407 	void AudioGetAudioFileList(std::string trackName, std::string audioName, std::vector<std::string>& list);
408 	int AudioGetType(std::string trackName, std::string audioName);
409 	float AudioGetVolume(std::string trackName, std::string audioName);
410 	float AudioGetBPM(std::string trackName, std::string audioName);
411 	int AudioGetBeatsPerBar(std::string trackName, std::string audioName);
412 	int AudioGetBars(std::string trackName, std::string audioName);
413 	int AudioGetMinMovementBars(std::string trackName, std::string audioName);
414 	int AudioGetRandomChance(std::string trackName, std::string audioName);
415 	int AudioGetFadeIn(std::string trackName, std::string audioName);
416 	int AudioGetFadeOut(std::string trackName, std::string audioName);
417 	int AudioGetXFadeIn(std::string trackName, std::string audioName);
418 	int AudioGetXFadeOut(std::string trackName, std::string audioName);
419 	int AudioGetCondId(std::string trackName, std::string audioName);
420 	int AudioGetCondType(std::string trackName, std::string audioName);
421 	int AudioGetCondValue(std::string trackName, std::string audioName);
422 	int AudioGetCondValue2(std::string trackName, std::string audioName);
423 
424 	void AudioFileRemove(std::string trackName, std::string audioName, std::string filename);
425 	void AudioFileSetLayer(std::string trackName, std::string audioName, std::string filename, std::string layer);
426 	void AudioFileSetRandomChance(std::string trackName, std::string audioName, std::string filename, int randomChance);
427 
428 	std::string AudioFileGetLayer(std::string trackName, std::string audioName, std::string filename);
429 	int AudioFileGetRandomChance(std::string trackName, std::string audioName, std::string filename);
430 
431 	oamlRC LayerNew(std::string name);
432 	void LayerList(std::vector<std::string>& list);
433 	void LayerRename(std::string layerName, std::string name);
434 	int LayerGetId(std::string layerName);
435 	int LayerGetRandomChance(std::string layerName);
436 	float LayerGetGain(std::string layerName);
437 };
438 
439 #endif
440 
441 #endif /* __OAML_H__ */
442