_multivc.h
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 #include "libasync_config.h" 36 37 #define VOC_8BIT 0x0 38 #define VOC_16BIT 0x4 39 40 #define T_SIXTEENBIT_STEREO 0 41 #define T_MONO 1 42 #define T_16BITSOURCE 2 43 #define T_STEREOSOURCE 4 44 #define T_DEFAULT T_SIXTEENBIT_STEREO 45 46 #define MV_MAXPANPOSITION 127 /* formerly 31 */ 47 #define MV_NUMPANPOSITIONS ( MV_MAXPANPOSITION + 1 ) 48 #define MV_MAXTOTALVOLUME 255 49 #define MV_MAXVOLUME 127 /* formerly 63 */ 50 51 // mirrors FX_MUSIC_PRIORITY from fx_man.h 52 #define MV_MUSIC_PRIORITY INT_MAX 53 54 #define MIX_VOLUME(volume) ((max(0, min((volume), 255)) * (MV_MAXVOLUME + 1)) >> 8) 55 56 extern struct VoiceNode *MV_Voices; 57 extern struct VoiceNode VoiceList; 58 extern struct VoiceNode VoicePool; 59 60 extern fix16_t MV_GlobalVolume; 61 extern fix16_t MV_VolumeSmoothFactor; 62 63 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); } 64 65 template <typename T> static inline conditional_t<is_signed<T>::value, make_unsigned_t<T>, make_signed_t<T>> FLIP_SIGN(T src) 66 { 67 static constexpr make_unsigned_t<T> msb = ((make_unsigned_t<T>)1) << (sizeof(T) * CHAR_BIT - 1u); 68 return src ^ msb; 69 } 70 71 template <typename T> static inline enable_if_t<is_signed<T>::value, T> SCALE_SAMPLE(T src, fix16_t volume) 72 { 73 return (T)fix16_fast_trunc_mul_int_by_fix16(src, volume); 74 } 75 76 template <typename T> static inline T CONVERT_SAMPLE_FROM_SIGNED(int src); 77 template <> inline int16_t CONVERT_SAMPLE_FROM_SIGNED<int16_t>(int src) { return src; } 78 79 template <typename T> static inline int CONVERT_SAMPLE_TO_SIGNED(T src); 80 template <> inline int CONVERT_SAMPLE_TO_SIGNED<int16_t>(int16_t src) { return src; } 81 82 template <typename S, typename D> static inline int CONVERT_LE_SAMPLE_TO_SIGNED(S src); 83 template <> inline int CONVERT_LE_SAMPLE_TO_SIGNED<uint8_t, int16_t>(uint8_t src) { return FLIP_SIGN(src) << 8; } 84 template <> inline int CONVERT_LE_SAMPLE_TO_SIGNED<int16_t, int16_t>(int16_t src) { return B_LITTLE16(src); } 85 86 template <typename T> static int CLAMP_SAMPLE(int src); 87 template <> inline int CLAMP_SAMPLE<int16_t>(int src) { return clamp(src, INT16_MIN, INT16_MAX); } 88 89 template <typename T> static T MIX_SAMPLES(int signed_sample, T untouched_sample) 90 { 91 return CONVERT_SAMPLE_FROM_SIGNED<T>(CLAMP_SAMPLE<T>(signed_sample + CONVERT_SAMPLE_TO_SIGNED<T>(untouched_sample))); 92 } 93 94 struct split16_t 95 { 96 explicit split16_t(uint16_t x) : v{x} {} 97 98 uint8_t l() const 99 { 100 return (v & 0x00FFu); 101 } 102 uint8_t h() const 103 { 104 return (v & 0xFF00u) >> CHAR_BIT; 105 } 106 107 private: 108 uint16_t v; 109 }; 110 111 #define MV_MIXBUFFERSIZE 256 112 #define MV_NUMBEROFBUFFERS 32 113 #define MV_TOTALBUFFERSIZE ( MV_MIXBUFFERSIZE * MV_NUMBEROFBUFFERS ) 114 115 #define MV_MAXVOICES 256 116 117 typedef enum : bool 118 { 119 NoMoreData, 120 KeepPlaying 121 } playbackstatus; 122 123 124 typedef struct VoiceNode 125 { 126 struct VoiceNode *next; 127 struct VoiceNode *prev; 128 129 playbackstatus (*GetSound)(struct VoiceNode *); 130 131 uint32_t (*mix)(struct VoiceNode *, uint32_t); 132 133 const char *sound; 134 void *rawdataptr; 135 136 union 137 { 138 const char *NextBlock; 139 void (*DemandFeed)(const char** ptr, uint32_t* length, void* userdata); 140 }; 141 142 struct 143 { 144 const char *Start; 145 const char *End; 146 int Count; 147 uint32_t Size; 148 } Loop; 149 150 intptr_t callbackval; 151 152 struct 153 { 154 fix16_t Left; 155 fix16_t Right; 156 } PannedVolume, GoalVolume; 157 158 wavefmt_t wavetype; 159 160 int bits; 161 int channels; 162 163 fix16_t volume; 164 165 uint32_t BlockLength; 166 167 uint32_t rawdatasiz; // rawdatasiz-1 is the max permissible index for rawdataptr 168 169 uint32_t PitchScale; 170 uint32_t FixedPointBufferSize; 171 172 uint32_t length; 173 uint32_t SamplingRate; 174 uint32_t RateScale; 175 uint32_t position; 176 std::atomic<int> Paused; 177 178 int handle; 179 int priority; 180 181 async::task<int> task; 182 } VoiceNode; 183 184 typedef struct 185 { 186 uint8_t left; 187 uint8_t right; 188 } Pan; 189 190 typedef struct 191 { 192 char RIFF[4]; 193 uint32_t file_size; 194 char WAVE[4]; 195 char fmt[4]; 196 uint32_t format_size; 197 } riff_header; 198 199 typedef struct 200 { 201 uint16_t wFormatTag; 202 uint16_t nChannels; 203 uint32_t nSamplesPerSec; 204 uint32_t nAvgBytesPerSec; 205 uint16_t nBlockAlign; 206 uint16_t nBitsPerSample; 207 } format_header; 208 209 typedef struct 210 { 211 uint8_t DATA[4]; 212 uint32_t size; 213 } data_header; 214 215 extern Pan MV_PanTable[MV_NUMPANPOSITIONS][MV_MAXVOLUME + 1]; 216 extern int MV_ErrorCode; 217 extern int MV_Installed; 218 extern int MV_MixRate; 219 extern char *MV_MusicBuffer; 220 extern int MV_BufferSize; 221 extern int MV_LazyAlloc; 222 223 extern int MV_MaxVoices; 224 extern int MV_Channels; 225 extern int MV_MixRate; 226 extern void *MV_InitDataPtr; 227 228 extern int MV_MIDIRenderTempo; 229 extern int MV_MIDIRenderTimer; 230 231 static FORCE_INLINE int MV_SetErrorCode(int status) 232 { 233 MV_ErrorCode = status; 234 return MV_Error; 235 } 236 237 void MV_PlayVoice(VoiceNode *voice); 238 239 VoiceNode *MV_AllocVoice(int priority, uint32_t allocsize = 0); 240 241 void MV_SetVoiceMixMode(VoiceNode *voice); 242 void MV_SetVoiceVolume(VoiceNode *voice, int vol, int left, int right, fix16_t volume); 243 void MV_SetVoicePitch(VoiceNode *voice, uint32_t rate, int pitchoffset); 244 245 int MV_GetVorbisPosition(VoiceNode *voice); 246 void MV_SetVorbisPosition(VoiceNode *voice, int position); 247 int MV_GetFLACPosition(VoiceNode *voice); 248 void MV_SetFLACPosition(VoiceNode *voice, int position); 249 int MV_GetXAPosition(VoiceNode *voice); 250 void MV_SetXAPosition(VoiceNode *voice, int position); 251 int MV_GetXMPPosition(VoiceNode *voice); 252 void MV_SetXMPPosition(VoiceNode *voice, int position); 253 254 void MV_ReleaseVorbisVoice(VoiceNode *voice); 255 void MV_ReleaseFLACVoice(VoiceNode *voice); 256 void MV_ReleaseXAVoice(VoiceNode *voice); 257 void MV_ReleaseXMPVoice(VoiceNode *voice); 258 259 #ifdef HAVE_XMP 260 extern int MV_XMPInterpolation; 261 #endif 262 263 // implemented in mix.c 264 template <typename S, typename D> uint32_t MV_MixMono(struct VoiceNode * const voice, uint32_t length); 265 template <typename S, typename D> uint32_t MV_MixStereo(struct VoiceNode * const voice, uint32_t length); 266 template <typename T> void MV_Reverb(char const *src, char * const dest, const fix16_t volume, int count); 267 268 // implemented in mixst.c 269 template <typename S, typename D> uint32_t MV_MixMonoStereo(struct VoiceNode * const voice, uint32_t length); 270 template <typename S, typename D> uint32_t MV_MixStereoStereo(struct VoiceNode * const voice, uint32_t length); 271 272 extern char *MV_MixDestination; // pointer to the next output sample 273 extern int MV_SampleSize; 274 extern int MV_RightChannelOffset; 275 276 #define loopStartTagCount 3 277 extern const char *loopStartTags[loopStartTagCount]; 278 #define loopEndTagCount 2 279 extern const char *loopEndTags[loopEndTagCount]; 280 #define loopLengthTagCount 2 281 extern const char *loopLengthTags[loopLengthTagCount]; 282 283 #if defined __POWERPC__ || defined GEKKO 284 # define BIGENDIAN 285 #endif 286 287 #endif