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 }