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.codec;
33 
34 import derelict.util.system;
35 
36 import derelict.fmod.common;
37 
38 align(1):
39 
40 alias FMOD_CODEC_OPEN_CALLBACK = FMOD_RESULT function(FMOD_CODEC_STATE *codec_state, FMOD_MODE usermode, FMOD_CREATESOUNDEXINFO *userexinfo);
41 alias FMOD_CODEC_CLOSE_CALLBACK = FMOD_RESULT function(FMOD_CODEC_STATE *codec_state);
42 alias FMOD_CODEC_READ_CALLBACK = FMOD_RESULT function(FMOD_CODEC_STATE *codec_state, void *buffer, uint samples_in, uint *samples_out);
43 alias FMOD_CODEC_GETLENGTH_CALLBACK = FMOD_RESULT function(FMOD_CODEC_STATE *codec_state, uint *length, FMOD_TIMEUNIT lengthtype);
44 alias FMOD_CODEC_SETPOSITION_CALLBACK = FMOD_RESULT function(FMOD_CODEC_STATE *codec_state, int subsound, uint position, FMOD_TIMEUNIT postype);
45 alias FMOD_CODEC_GETPOSITION_CALLBACK = FMOD_RESULT function(FMOD_CODEC_STATE *codec_state, uint *position, FMOD_TIMEUNIT postype);
46 alias FMOD_CODEC_SOUNDCREATE_CALLBACK = FMOD_RESULT function(FMOD_CODEC_STATE *codec_state, int subsound, FMOD_SOUND *sound);
47 alias FMOD_CODEC_METADATA_CALLBACK = FMOD_RESULT function(FMOD_CODEC_STATE *codec_state, FMOD_TAGTYPE tagtype, char *name, void *data, uint datalen, FMOD_TAGDATATYPE datatype, int unique);
48 alias FMOD_CODEC_GETWAVEFORMAT_CALLBACK = FMOD_RESULT function(FMOD_CODEC_STATE *codec_state, int index, FMOD_CODEC_WAVEFORMAT *waveformat);
49 
50 struct FMOD_CODEC_DESCRIPTION
51 {
52 	const(char)                       *name;            /* [w] Name of the codec. */
53 	uint                              version_;         /* [w] Plugin writer's version number. */
54 	int                               defaultasstream; /* [w] Tells FMOD to open the file as a stream when calling System::createSound, and not a static sample.  Should normally be 0 (FALSE), because generally the user wants to decode the file into memory when using System::createSound.   Mainly used for formats that decode for a very long time, or could use large amounts of memory when decoded.  Usually sequenced formats such as mod/s3m/xm/it/midi fall into this category.   It is mainly to stop users that don't know what they're doing from getting FMOD_ERR_MEMORY returned from createSound when they should have in fact called System::createStream or used FMOD_CREATESTREAM in System::createSound. */
55 	FMOD_TIMEUNIT                     timeunits;       /* [w] When setposition codec is called, only these time formats will be passed to the codec. Use bitwise OR to accumulate different types. */
56 	FMOD_CODEC_OPEN_CALLBACK          open;            /* [w] Open callback for the codec for when FMOD tries to open a sound using this codec. */
57 	FMOD_CODEC_CLOSE_CALLBACK         close;           /* [w] Close callback for the codec for when FMOD tries to close a sound using this codec.  */
58 	FMOD_CODEC_READ_CALLBACK          read;            /* [w] Read callback for the codec for when FMOD tries to read some data from the file to the destination format (specified in the open callback). */
59 	FMOD_CODEC_GETLENGTH_CALLBACK     getlength;       /* [w] Callback to return the length of the song in whatever format required when Sound::getLength is called. */
60 	FMOD_CODEC_SETPOSITION_CALLBACK   setposition;     /* [w] Seek callback for the codec for when FMOD tries to seek within the file with Channel::setPosition. */
61 	FMOD_CODEC_GETPOSITION_CALLBACK   getposition;     /* [w] Tell callback for the codec for when FMOD tries to get the current position within the with Channel::getPosition. */
62 	FMOD_CODEC_SOUNDCREATE_CALLBACK   soundcreate;     /* [w] Sound creation callback for the codec when FMOD finishes creating the sound.  (So the codec can set more parameters for the related created sound, ie loop points/mode or 3D attributes etc). */
63 	FMOD_CODEC_GETWAVEFORMAT_CALLBACK getwaveformat;   /* [w] Callback to tell FMOD about the waveformat of a particular subsound.  This is to save memory, rather than saving 1000 FMOD_CODEC_WAVEFORMAT structures in the codec, the codec might have a more optimal way of storing this information. */
64 }
65 
66 struct FMOD_CODEC_WAVEFORMAT
67 {
68 	const(char)*       name;     /* [w] Name of sound.  Optional. */
69 	FMOD_SOUND_FORMAT  format;        /* [w] Format for (decompressed) codec output, ie FMOD_SOUND_FORMAT_PCM8, FMOD_SOUND_FORMAT_PCM16.  Mandantory - Must be supplied. */
70 	int                channels;      /* [w] Number of channels used by codec, ie mono = 1, stereo = 2.  Mandantory - Must be supplied.  */
71 	int                frequency;     /* [w] Default frequency in hz of the codec, ie 44100.  Mandantory - Must be supplied.  */
72 	uint               lengthbytes;   /* [w] Length in bytes of the source data.  Used for FMOD_TIMEUNIT_RAWBYTES.  Optional. Default = 0. */
73 	uint               lengthpcm;     /* [w] Length in decompressed, PCM samples of the file, ie length in seconds * frequency.  Used for Sound::getLength and for memory allocation of static decompressed sample data.  Mandantory - Must be supplied. */
74 	uint               pcmblocksize;  /* [w] Minimum, optimal number of decompressed PCM samples codec can handle.  0 or 1 = no buffering.  Anything higher means FMOD will allocate a PCM buffer of this size to read in chunks.  The codec read callback will be called in multiples of this value.  Optional.  */
75 	int                loopstart;     /* [w] Loopstart in decompressed, PCM samples of file. Optional. Default = 0. */
76 	int                loopend;       /* [w] Loopend in decompressed, PCM samples of file. Optional. Default = 0. */
77 	FMOD_MODE          mode;          /* [w] Mode to determine whether the sound should by default load as looping, non looping, 2d or 3d.  Optional. Default = FMOD_DEFAULT. */
78 	FMOD_CHANNELMASK   channelmask;   /* [w] Defined channel bitmask to describe which speakers the channels in the codec map to, in order of channel count.  See fmod_common.h.  Optional. Leave at 0 to map to the speaker layout defined in FMOD_SPEAKER. */
79 	FMOD_CHANNELORDER  channelorder;  /* [w] Defined channel order type, to describe where each sound channel should pan for the number of channels specified.  See fmod_common.h.  Optional.  Leave at 0 to play in default speaker order. */
80 	float              peakvolume;    /* [w] Peak volume of sound. Optional. Default = 0 if not used. */
81 }
82 
83 static immutable FMOD_CODEC_WAVEFORMAT_VERSION = 3;
84 
85 struct FMOD_CODEC_STATE
86 {
87 	int                          numsubsounds;      /* [w] Number of 'subsounds' in this sound.  Anything other than 0 makes it a 'container' format (ie DLS/FSB etc which contain 1 or more subsounds).  For most normal, single sound codec such as WAV/AIFF/MP3, this should be 0 as they are not a container for subsounds, they are the sound by itself. */
88 	FMOD_CODEC_WAVEFORMAT       *waveformat;        /* [w] Pointer to an array of format structures containing information about each sample.  Can be 0 or NULL if FMOD_CODEC_GETWAVEFORMAT_CALLBACK callback is preferred.  The number of entries here must equal the number of subsounds defined in the subsound parameter. If numsubsounds = 0 then there should be 1 instance of this structure. */
89 	void                        *plugindata;        /* [w] Plugin writer created data the codec author wants to attach to this object. */
90 	
91 	void                        *filehandle;        /* [r] This will return an internal FMOD file handle to use with the callbacks provided.  */
92 	uint                         filesize;          /* [r] This will contain the size of the file in bytes. */
93 	FMOD_FILE_READ_CALLBACK      fileread;          /* [r] This will return a callable FMOD file function to use from codec. */
94 	FMOD_FILE_SEEK_CALLBACK      fileseek;          /* [r] This will return a callable FMOD file function to use from codec.  */
95 	FMOD_CODEC_METADATA_CALLBACK metadata;          /* [r] This will return a callable FMOD metadata function to use from codec.  */
96 	
97 	int                          waveformatversion; /* [w] Must be set to FMOD_CODEC_WAVEFORMAT_VERSION in the FMOD_CODEC_OPEN_CALLBACK. */
98 }