/ source / audiolib / src / mixst.cpp
mixst.cpp
 1  /*
 2   Copyright (C) 2009 Jonathon Fowler <jf@jonof.id.au>
 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  #include "_multivc.h"
22  
23  template uint32_t MV_MixMonoStereo<uint8_t, int16_t>(struct VoiceNode * const voice, uint32_t length);
24  template uint32_t MV_MixStereoStereo<uint8_t, int16_t>(struct VoiceNode * const voice, uint32_t length);
25  template uint32_t MV_MixMonoStereo<int16_t, int16_t>(struct VoiceNode * const voice, uint32_t length);
26  template uint32_t MV_MixStereoStereo<int16_t, int16_t>(struct VoiceNode * const voice, uint32_t length);
27  
28  /*
29   length = count of samples to mix
30   position = offset of starting sample in source
31   rate = resampling increment
32   volume = direct volume adjustment, 1.0 = no change
33   */
34  
35  // stereo source, mono output
36  template <typename S, typename D>
37  uint32_t MV_MixMonoStereo(struct VoiceNode * const voice, uint32_t length)
38  {
39      auto const * __restrict source = (S const *)voice->sound;
40      auto       * __restrict dest   = (D *)MV_MixDestination;
41  
42      uint32_t       position = voice->position;
43      uint32_t const rate     = voice->RateScale;
44      fix16_t const  volume   = fix16_fast_trunc_mul(voice->volume, MV_GlobalVolume);
45  
46      do
47      {
48          auto const isample0 = CONVERT_LE_SAMPLE_TO_SIGNED<S, D>(source[(position >> 16) << 1]);
49          auto const isample1 = CONVERT_LE_SAMPLE_TO_SIGNED<S, D>(source[((position >> 16) << 1) + 1]);
50  
51          position += rate;
52  
53          *dest = MIX_SAMPLES<D>((SCALE_SAMPLE((isample0 + isample1) >> 1, fix16_fast_trunc_mul(volume, voice->PannedVolume.Left))), *dest);
54          dest++;
55  
56          voice->PannedVolume.Left = SMOOTH_VOLUME(voice->PannedVolume.Left, voice->GoalVolume.Left);
57      }
58      while (--length);
59  
60      MV_MixDestination = (char *)dest;
61  
62      return position;
63  }
64  
65  // stereo source, stereo output
66  template <typename S, typename D>
67  uint32_t MV_MixStereoStereo(struct VoiceNode * const voice, uint32_t length)
68  {
69      auto const * __restrict source = (S const *)voice->sound;
70      auto       * __restrict dest   = (D *)MV_MixDestination;
71  
72      uint32_t       position = voice->position;
73      uint32_t const rate     = voice->RateScale;
74      fix16_t const  volume   = fix16_fast_trunc_mul(voice->volume, MV_GlobalVolume);
75  
76      do
77      {
78          auto const isample0 = CONVERT_LE_SAMPLE_TO_SIGNED<S, D>(source[(position >> 16) << 1]);
79          auto const isample1 = CONVERT_LE_SAMPLE_TO_SIGNED<S, D>(source[((position >> 16) << 1) + 1]);
80  
81          position += rate;
82  
83          *dest = MIX_SAMPLES<D>(SCALE_SAMPLE(isample0, fix16_fast_trunc_mul(volume, voice->PannedVolume.Left)), *dest);
84          *(dest + (MV_RightChannelOffset / sizeof(*dest)))
85              = MIX_SAMPLES<D>(SCALE_SAMPLE(isample1, fix16_fast_trunc_mul(volume, voice->PannedVolume.Right)), *(dest + (MV_RightChannelOffset / sizeof(*dest))));
86          dest += 2;
87  
88          voice->PannedVolume = { SMOOTH_VOLUME(voice->PannedVolume.Left, voice->GoalVolume.Left), SMOOTH_VOLUME(voice->PannedVolume.Right, voice->GoalVolume.Right) };
89      }
90      while (--length);
91  
92      MV_MixDestination = (char *)dest;
93  
94      return position;
95  }