/ source / audiolib / src / _multivc.h
_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