1 /*
2 Copyright (C) 1994-1995 Apogee Software, Ltd.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18
19 */
20 /**********************************************************************
21 file: _MULTIVC.H
22
23 author: James R. Dose
24 date: December 20, 1993
25
26 Private header for MULTIVOC.C
27
28 (c) Copyright 1993 James R. Dose. All Rights Reserved.
29 **********************************************************************/
30
31 #ifndef MULTIVC_H_
32 #define MULTIVC_H_
33
34 #include "multivoc.h"
35
36 #define VOC_8BIT 0x0
37 #define VOC_16BIT 0x4
38
39 #define T_SIXTEENBIT_STEREO 0
40 #define T_MONO 1
41 #define T_16BITSOURCE 2
42 #define T_STEREOSOURCE 4
43 #define T_DEFAULT T_SIXTEENBIT_STEREO
44
45 #define MV_MAXPANPOSITION 127 /* formerly 31 */
46 #define MV_NUMPANPOSITIONS ( MV_MAXPANPOSITION + 1 )
47 #define MV_MAXTOTALVOLUME 255
48 #define MV_MAXVOLUME 127 /* formerly 63 */
49
50 // mirrors FX_MUSIC_PRIORITY from fx_man.h
51 #define MV_MUSIC_PRIORITY INT_MAX
52
53 #define MIX_VOLUME(volume) ((max(0, min((volume), 255)) * (MV_MAXVOLUME + 1)) >> 8)
54
55 extern struct VoiceNode *MV_Voices;
56 extern struct VoiceNode VoiceList;
57 extern struct VoiceNode VoicePool;
58
59 extern fix16_t MV_GlobalVolume;
60 extern fix16_t MV_VolumeSmoothFactor;
61
SMOOTH_VOLUME(fix16_t const volume,fix16_t const dest)62 static FORCE_INLINE fix16_t SMOOTH_VOLUME(fix16_t const volume, fix16_t const dest) { return volume + fix16_fast_trunc_mul(dest - volume, MV_VolumeSmoothFactor); }
63
FLIP_SIGN(T src)64 template <typename T> static inline conditional_t<is_signed<T>::value, make_unsigned_t<T>, make_signed_t<T>> FLIP_SIGN(T src)
65 {
66 static constexpr make_unsigned_t<T> msb = ((make_unsigned_t<T>)1) << (sizeof(T) * CHAR_BIT - 1u);
67 return src ^ msb;
68 }
69
SCALE_SAMPLE(T src,fix16_t volume)70 template <typename T> static inline enable_if_t<is_signed<T>::value, T> SCALE_SAMPLE(T src, fix16_t volume)
71 {
72 return (T)fix16_fast_trunc_mul_int_by_fix16(src, volume);
73 }
74
75 template <typename T> static inline T CONVERT_SAMPLE_FROM_SIGNED(int src);
76 template <> inline int16_t CONVERT_SAMPLE_FROM_SIGNED<int16_t>(int src) { return src; }
77
78 template <typename T> static inline int CONVERT_SAMPLE_TO_SIGNED(T src);
79 template <> inline int CONVERT_SAMPLE_TO_SIGNED<int16_t>(int16_t src) { return src; }
80
81 template <typename S, typename D> static inline int CONVERT_LE_SAMPLE_TO_SIGNED(S src);
82 template <> inline int CONVERT_LE_SAMPLE_TO_SIGNED<uint8_t, int16_t>(uint8_t src) { return FLIP_SIGN(src) << 8; }
83 template <> inline int CONVERT_LE_SAMPLE_TO_SIGNED<int16_t, int16_t>(int16_t src) { return B_LITTLE16(src); }
84
85 template <typename T> static int CLAMP_SAMPLE(int src);
86 template <> inline int CLAMP_SAMPLE<int16_t>(int src) { return clamp(src, INT16_MIN, INT16_MAX); }
87
MIX_SAMPLES(int signed_sample,T untouched_sample)88 template <typename T> static T MIX_SAMPLES(int signed_sample, T untouched_sample)
89 {
90 return CONVERT_SAMPLE_FROM_SIGNED<T>(CLAMP_SAMPLE<T>(signed_sample + CONVERT_SAMPLE_TO_SIGNED<T>(untouched_sample)));
91 }
92
93 struct split16_t
94 {
split16_tsplit16_t95 explicit split16_t(uint16_t x) : v{x} {}
96
lsplit16_t97 uint8_t l() const
98 {
99 return (v & 0x00FFu);
100 }
hsplit16_t101 uint8_t h() const
102 {
103 return (v & 0xFF00u) >> CHAR_BIT;
104 }
105
106 private:
107 uint16_t v;
108 };
109
110 #define MV_MIXBUFFERSIZE 256
111 #define MV_NUMBEROFBUFFERS 32
112 #define MV_TOTALBUFFERSIZE ( MV_MIXBUFFERSIZE * MV_NUMBEROFBUFFERS )
113
114 typedef enum : bool
115 {
116 NoMoreData,
117 KeepPlaying
118 } playbackstatus;
119
120
121 typedef struct VoiceNode
122 {
123 struct VoiceNode *next;
124 struct VoiceNode *prev;
125
126 playbackstatus (*GetSound)(struct VoiceNode *);
127
128 uint32_t (*mix)(struct VoiceNode *, uint32_t);
129
130 const char *sound;
131 void *rawdataptr;
132
133 union
134 {
135 const char *NextBlock;
136 void (*DemandFeed)(const char** ptr, uint32_t* length, void* userdata);
137 };
138
139 struct
140 {
141 const char *Start;
142 const char *End;
143 int Count;
144 uint32_t Size;
145 } Loop;
146
147 intptr_t callbackval;
148
149 struct
150 {
151 fix16_t Left;
152 fix16_t Right;
153 } PannedVolume, GoalVolume;
154
155 wavefmt_t wavetype;
156
157 int bits;
158 int channels;
159
160 fix16_t volume;
161
162 uint32_t BlockLength;
163
164 uint32_t rawdatasiz; // rawdatasiz-1 is the max permissible index for rawdataptr
165
166 uint32_t PitchScale;
167 uint32_t FixedPointBufferSize;
168
169 uint32_t length;
170 uint32_t SamplingRate;
171 uint32_t RateScale;
172 uint32_t position;
173 int Paused;
174
175 int handle;
176 int priority;
177
178 } VoiceNode;
179
180 typedef struct
181 {
182 uint8_t left;
183 uint8_t right;
184 } Pan;
185
186 typedef struct
187 {
188 char RIFF[4];
189 uint32_t file_size;
190 char WAVE[4];
191 char fmt[4];
192 uint32_t format_size;
193 } riff_header;
194
195 typedef struct
196 {
197 uint16_t wFormatTag;
198 uint16_t nChannels;
199 uint32_t nSamplesPerSec;
200 uint32_t nAvgBytesPerSec;
201 uint16_t nBlockAlign;
202 uint16_t nBitsPerSample;
203 } format_header;
204
205 typedef struct
206 {
207 uint8_t DATA[4];
208 uint32_t size;
209 } data_header;
210
211 extern Pan MV_PanTable[ MV_NUMPANPOSITIONS ][ MV_MAXVOLUME + 1 ];
212 extern int MV_ErrorCode;
213 extern int MV_Installed;
214 extern int MV_MixRate;
215 extern char *MV_MusicBuffer;
216 extern int MV_BufferSize;
217 extern int MV_LazyAlloc;
218
219 extern int MV_MaxVoices;
220 extern int MV_Channels;
221 extern int MV_MixRate;
222 extern void *MV_InitDataPtr;
223
224 extern int MV_MIDIRenderTempo;
225 extern int MV_MIDIRenderTimer;
226
MV_SetErrorCode(int status)227 static FORCE_INLINE int MV_SetErrorCode(int status)
228 {
229 MV_ErrorCode = status;
230 return MV_Error;
231 }
232
233 void MV_PlayVoice(VoiceNode *voice);
234
235 VoiceNode *MV_AllocVoice(int priority, uint32_t allocsize = 0);
236
237 void MV_SetVoiceMixMode(VoiceNode *voice);
238 void MV_SetVoiceVolume(VoiceNode *voice, int vol, int left, int right, fix16_t volume);
239 void MV_SetVoicePitch(VoiceNode *voice, uint32_t rate, int pitchoffset);
240
241 int MV_GetVorbisPosition(VoiceNode *voice);
242 void MV_SetVorbisPosition(VoiceNode *voice, int position);
243 int MV_GetFLACPosition(VoiceNode *voice);
244 void MV_SetFLACPosition(VoiceNode *voice, int position);
245 int MV_GetXAPosition(VoiceNode *voice);
246 void MV_SetXAPosition(VoiceNode *voice, int position);
247 int MV_GetXMPPosition(VoiceNode *voice);
248 void MV_SetXMPPosition(VoiceNode *voice, int position);
249
250 void MV_ReleaseVorbisVoice(VoiceNode *voice);
251 void MV_ReleaseFLACVoice(VoiceNode *voice);
252 void MV_ReleaseXAVoice(VoiceNode *voice);
253 void MV_ReleaseXMPVoice(VoiceNode *voice);
254
255 #ifdef HAVE_XMP
256 extern int MV_XMPInterpolation;
257 #endif
258
259 // implemented in mix.c
260 template <typename S, typename D> uint32_t MV_MixMono(struct VoiceNode * const voice, uint32_t length);
261 template <typename S, typename D> uint32_t MV_MixStereo(struct VoiceNode * const voice, uint32_t length);
262 template <typename T> void MV_Reverb(char const *src, char * const dest, const fix16_t volume, int count);
263
264 // implemented in mixst.c
265 template <typename S, typename D> uint32_t MV_MixMonoStereo(struct VoiceNode * const voice, uint32_t length);
266 template <typename S, typename D> uint32_t MV_MixStereoStereo(struct VoiceNode * const voice, uint32_t length);
267
268 extern char *MV_MixDestination; // pointer to the next output sample
269 extern int MV_SampleSize;
270 extern int MV_RightChannelOffset;
271
272 #define loopStartTagCount 3
273 extern const char *loopStartTags[loopStartTagCount];
274 #define loopEndTagCount 2
275 extern const char *loopEndTags[loopEndTagCount];
276 #define loopLengthTagCount 2
277 extern const char *loopLengthTags[loopLengthTagCount];
278
279 #if defined __POWERPC__ || defined GEKKO
280 # define BIGENDIAN
281 #endif
282
283 #endif
284