1 /*
2  * Copyright (c) 2017 Derelict Developers
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  * * Redistributions of source code must retain the above copyright
10  *   notice, this list of conditions and the following disclaimer.
11  *
12  * * Redistributions in binary form must reproduce the above copyright
13  *   notice, this list of conditions and the following disclaimer in the
14  *   documentation and/or other materials provided with the distribution.
15  *
16  * * Neither the names 'Derelict', 'DerelictFmod', nor the names of its contributors
17  *   may be used to endorse or promote products derived from this software
18  *   without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 module derelict.fmod.output;
33 
34 import derelict.fmod.common;
35 
36 align(1):
37 
38 static immutable FMOD_OUTPUT_PLUGIN_VERSION = 2;
39 
40 alias FMOD_OUTPUT_GETNUMDRIVERS_CALLBACK = FMOD_RESULT  function(FMOD_OUTPUT_STATE *output_state, int *numdrivers);
41 alias FMOD_OUTPUT_GETDRIVERINFO_CALLBACK = FMOD_RESULT  function(FMOD_OUTPUT_STATE *output, int id, char *name, int namelen, FMOD_GUID *guid, int *systemrate, FMOD_SPEAKERMODE *speakermode, int *speakermodechannels);
42 alias FMOD_OUTPUT_INIT_CALLBACK = FMOD_RESULT           function(FMOD_OUTPUT_STATE *output_state, int selecteddriver, FMOD_INITFLAGS flags, int *outputrate, FMOD_SPEAKERMODE *speakermode, int *speakermodechannels, FMOD_SOUND_FORMAT *outputformat, int dspbufferlength, int dspnumbuffers, void *extradriverdata);
43 alias FMOD_OUTPUT_START_CALLBACK = FMOD_RESULT          function(FMOD_OUTPUT_STATE *output_state);
44 alias FMOD_OUTPUT_STOP_CALLBACK = FMOD_RESULT           function(FMOD_OUTPUT_STATE *output_state);
45 alias FMOD_OUTPUT_CLOSE_CALLBACK = FMOD_RESULT          function(FMOD_OUTPUT_STATE *output_state);
46 alias FMOD_OUTPUT_UPDATE_CALLBACK = FMOD_RESULT         function(FMOD_OUTPUT_STATE *output_state);
47 alias FMOD_OUTPUT_GETHANDLE_CALLBACK = FMOD_RESULT       function(FMOD_OUTPUT_STATE *output_state, void **handle);
48 alias FMOD_OUTPUT_GETPOSITION_CALLBACK = FMOD_RESULT     function(FMOD_OUTPUT_STATE *output_state, uint *pcm);
49 alias FMOD_OUTPUT_LOCK_CALLBACK = FMOD_RESULT            function(FMOD_OUTPUT_STATE *output_state, uint offset, uint length, void **ptr1, void **ptr2, uint *len1, uint *len2);
50 alias FMOD_OUTPUT_UNLOCK_CALLBACK = FMOD_RESULT          function(FMOD_OUTPUT_STATE *output_state, void *ptr1, void *ptr2, uint len1, uint len2);
51 alias FMOD_OUTPUT_MIXER_CALLBACK = FMOD_RESULT           function(FMOD_OUTPUT_STATE *output_state);
52 
53 alias FMOD_OUTPUT_OBJECT3DGETINFO_CALLBACK = FMOD_RESULT    function(FMOD_OUTPUT_STATE *output_state, int *maxhardwareobjects);
54 alias FMOD_OUTPUT_OBJECT3DALLOC_CALLBACK = FMOD_RESULT      function(FMOD_OUTPUT_STATE *output_state, void **object3d);
55 alias FMOD_OUTPUT_OBJECT3DFREE_CALLBACK = FMOD_RESULT       function(FMOD_OUTPUT_STATE *output_state, void *object3d);
56 alias FMOD_OUTPUT_OBJECT3DUPDATE_CALLBACK = FMOD_RESULT     function(FMOD_OUTPUT_STATE *output_state, void *object3d, const FMOD_OUTPUT_OBJECT3DINFO *info);
57 
58 alias FMOD_OUTPUT_OPENPORT_CALLBACK = FMOD_RESULT         function(FMOD_OUTPUT_STATE *output, FMOD_PORT_TYPE portType, FMOD_PORT_INDEX portIndex, int *portId, int *portRate, int *portChannels, FMOD_SOUND_FORMAT *portFormat);
59 alias FMOD_OUTPUT_CLOSEPORT_CALLBACK = FMOD_RESULT        function(FMOD_OUTPUT_STATE *output, int portId);
60 
61 alias FMOD_OUTPUT_READFROMMIXER = FMOD_RESULT           function(FMOD_OUTPUT_STATE *output_state, void *buffer, uint length);  /* This one is called by plugin through FMOD_OUTPUT_STATE, not set by user as a callback. */
62 alias FMOD_OUTPUT_COPYPORT = FMOD_RESULT                function(FMOD_OUTPUT_STATE *output, int portId, void *buffer, uint length);
63 alias FMOD_OUTPUT_ALLOC = void*                         function(uint size, uint align_, const(char) *file, int line);
64 alias FMOD_OUTPUT_FREE = void                           function(void *ptr, const(char) *file, int line);
65 alias FMOD_OUTPUT_LOG = void                            function(FMOD_DEBUG_FLAGS level, const(char) *file, int line, const(char) *function_, const(char) *string, ...);
66  
67 
68 struct FMOD_OUTPUT_DESCRIPTION
69 {
70 	uint                            apiversion;         /* [w] The output plugin API version this plugin is built for. Set to this to FMOD_OUTPUT_PLUGIN_VERSION defined above. */
71 	const(char)                         *name;                  /* [in] Name of the output. */
72 	uint                                version_;               /* [in] Plugin writer's version number. */
73 	int                                 polling;               /* [in] If TRUE (non zero), this tells FMOD to start a thread and call getposition / lock / unlock for feeding data.  If 0, the output is probably callback based, so all the plugin needs to do is call readfrommixer to the appropriate pointer. */ 
74 	FMOD_OUTPUT_GETNUMDRIVERS_CALLBACK  getnumdrivers;         /* [in] For sound device enumeration.  This callback is to give System::getNumDrivers somthing to return. */
75 	FMOD_OUTPUT_GETDRIVERINFO_CALLBACK  getdriverinfo;         /* [in] For sound device enumeration.  This callback is to give System::getDriverName somthing to return. */
76 	FMOD_OUTPUT_INIT_CALLBACK           init;                  /* [in] Initialization function for the output device.  This is called from System::init. */
77 	FMOD_OUTPUT_START_CALLBACK          start;                 /* [in] Initialization function for the output device to start accepting audio data from the FMOD software mixer.  This is called from System::init. */
78 	FMOD_OUTPUT_STOP_CALLBACK           stop;                  /* [in] Initialization function for the output device to stop accepting audio data from FMOD the software mixer.  This is called from System::close. */
79 	FMOD_OUTPUT_CLOSE_CALLBACK          close;                 /* [in] Cleanup / close down function for the output device.  This is called from System::close. */
80 	FMOD_OUTPUT_UPDATE_CALLBACK         update;                /* [in] Update function that is called once a frame by the user.  This is called from System::update. */
81 	FMOD_OUTPUT_GETHANDLE_CALLBACK      gethandle;             /* [in] This is called from System::getOutputHandle.  This is just to return a pointer to the internal system device object that the system may be using.*/
82 	FMOD_OUTPUT_GETPOSITION_CALLBACK    getposition;           /* [in] This is called from the FMOD software mixer thread if 'polling' = true.  This returns a position value in samples so that FMOD knows where and when to fill its buffer. */
83 	FMOD_OUTPUT_LOCK_CALLBACK           lock;                  /* [in] This is called from the FMOD software mixer thread if 'polling' = true.  This function provides a pointer to data that FMOD can write to when software mixing. */
84 	FMOD_OUTPUT_UNLOCK_CALLBACK         unlock;                /* [in] This is called from the FMOD software mixer thread if 'polling' = true.  This optional function accepts the data that has been mixed and copies it or does whatever it needs to before sending it to the hardware. */
85 	FMOD_OUTPUT_MIXER_CALLBACK              mixer;              /* [w] ('polling' == FALSE) Mixer thread that will continually retrigger. Wait on a synchronization primitive until ready, then call FMOD_OUTPUT_READFROMMIXER, then leave the callback (will retrigger immediately if mixer is still running). Called continually after FMOD_OUTPUT_START_CALLBACK and before FMOD_OUTPUT_STOP_CALLBACK. */
86 	FMOD_OUTPUT_OBJECT3DGETINFO_CALLBACK    object3dgetinfo;    /* [w] Provide information about the capabilities of the 3D object hardware. Called during a mix. */
87 	FMOD_OUTPUT_OBJECT3DALLOC_CALLBACK      object3dalloc;      /* [w] Reserve a hardware resources for a single 3D object. Called during a mix. */
88 	FMOD_OUTPUT_OBJECT3DFREE_CALLBACK       object3dfree;       /* [w] Release a hardware resource previously acquired with FMOD_OUTPUT_OBJECT3DALLOC_CALLBACK. Called during a mix. */
89 	FMOD_OUTPUT_OBJECT3DUPDATE_CALLBACK     object3dupdate;     /* [w] Called once for every acquired 3D object every mix to provide 3D information and buffered audio. Called during a mix. */
90 	FMOD_OUTPUT_OPENPORT_CALLBACK           openport;           /* [w] Optional main thread callback to open an auxiliary output port on the device. */
91 	FMOD_OUTPUT_CLOSEPORT_CALLBACK          closeport;          /* [w] Optional main thread callback to close an auxiliary output port on the device. */
92 }
93 
94 struct FMOD_OUTPUT_STATE
95 {
96 	void                      *plugindata;      /* [in] Plugin writer created data the output author wants to attach to this object. */
97 	FMOD_OUTPUT_READFROMMIXER   readfrommixer;  /* [r] Function to execute the mixer producing a buffer of audio. Used to control when the mix occurs manually as an alternative to FMOD_OUTPUT_DESCRIPTION::polling == TRUE. */
98 	FMOD_OUTPUT_ALLOC           alloc;          /* [r] Function to allocate memory using the FMOD memory system. */
99 	FMOD_OUTPUT_FREE            free;           /* [r] Function to free memory allocated with FMOD_OUTPUT_ALLOC. */
100 	FMOD_OUTPUT_LOG             log;            /* [r] Function to write to the FMOD logging system. */
101 	FMOD_OUTPUT_COPYPORT        copyport;       /* [r] Function to copy the output from the mixer for the given auxiliary port */
102 }
103 
104 struct FMOD_OUTPUT_OBJECT3DINFO
105 {
106 	float          *buffer;         /* [r] Mono PCM floating point buffer. This buffer needs to be scaled by the gain value to get distance attenuation.  */
107 	uint            bufferlength;   /* [r] Length in PCM samples of buffer. */
108 	FMOD_VECTOR     position;       /* [r] Vector relative between object and listener. */
109 	float           gain;           /* [r] 0.0 to 1.0 - 1 = 'buffer' is not attenuated, 0 = 'buffer' is fully attenuated. */
110 	float           spread;         /* [r] 0 - 360 degrees.  0 = point source, 360 = sound is spread around all speakers */
111 	float           priority;       /* [r] 0.0 to 1.0 - 0 = most important, 1 = least important. Based on height and distance (height is more important). */
112 }