2009-07-27 05:47:50 +00:00
|
|
|
/*
|
|
|
|
Copyright (C) 2009 Jonathon Fowler <jf@jonof.id.au>
|
2016-06-05 04:46:28 +00:00
|
|
|
|
2009-07-27 05:47:50 +00:00
|
|
|
This program is free software; you can redistribute it and/or
|
|
|
|
modify it under the terms of the GNU General Public License
|
|
|
|
as published by the Free Software Foundation; either version 2
|
|
|
|
of the License, or (at your option) any later version.
|
2016-06-05 04:46:28 +00:00
|
|
|
|
2009-07-27 05:47:50 +00:00
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
2016-06-05 04:46:28 +00:00
|
|
|
|
2009-07-27 05:47:50 +00:00
|
|
|
See the GNU General Public License for more details.
|
2016-06-05 04:46:28 +00:00
|
|
|
|
2009-07-27 05:47:50 +00:00
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program; if not, write to the Free Software
|
2014-07-20 08:55:56 +00:00
|
|
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
2016-06-05 04:46:28 +00:00
|
|
|
|
2009-07-27 05:47:50 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "_multivc.h"
|
|
|
|
|
2019-10-19 23:44:53 +00:00
|
|
|
template uint32_t MV_MixMonoStereo<uint8_t, int16_t>(struct VoiceNode * const voice, uint32_t length);
|
|
|
|
template uint32_t MV_MixStereoStereo<uint8_t, int16_t>(struct VoiceNode * const voice, uint32_t length);
|
|
|
|
template uint32_t MV_MixMonoStereo<int16_t, int16_t>(struct VoiceNode * const voice, uint32_t length);
|
|
|
|
template uint32_t MV_MixStereoStereo<int16_t, int16_t>(struct VoiceNode * const voice, uint32_t length);
|
|
|
|
|
2009-07-27 05:47:50 +00:00
|
|
|
/*
|
|
|
|
length = count of samples to mix
|
2018-10-25 23:32:41 +00:00
|
|
|
position = offset of starting sample in source
|
|
|
|
rate = resampling increment
|
2018-10-25 23:32:14 +00:00
|
|
|
volume = direct volume adjustment, 1.0 = no change
|
2009-07-27 05:47:50 +00:00
|
|
|
*/
|
|
|
|
|
2019-10-19 23:44:53 +00:00
|
|
|
// stereo source, mono output
|
|
|
|
template <typename S, typename D>
|
|
|
|
uint32_t MV_MixMonoStereo(struct VoiceNode * const voice, uint32_t length)
|
2009-07-27 05:47:50 +00:00
|
|
|
{
|
2019-10-19 23:44:53 +00:00
|
|
|
auto const source = (S const *)voice->sound;
|
|
|
|
auto dest = (D *)MV_MixDestination;
|
2018-10-25 23:33:21 +00:00
|
|
|
|
2018-10-25 23:32:41 +00:00
|
|
|
uint32_t position = voice->position;
|
|
|
|
uint32_t const rate = voice->RateScale;
|
2019-07-09 05:42:23 +00:00
|
|
|
float const volume = voice->volume*MV_GlobalVolume;
|
2018-10-25 23:32:14 +00:00
|
|
|
|
2018-12-15 01:40:03 +00:00
|
|
|
do
|
2018-10-25 23:32:14 +00:00
|
|
|
{
|
2019-10-19 23:44:53 +00:00
|
|
|
auto const isample0 = CONVERT_LE_SAMPLE_TO_SIGNED<S, D>(source[(position >> 16) << 1]);
|
|
|
|
auto const isample1 = CONVERT_LE_SAMPLE_TO_SIGNED<S, D>(source[((position >> 16) << 1) + 1]);
|
2018-10-25 23:32:14 +00:00
|
|
|
|
2018-10-25 23:32:35 +00:00
|
|
|
position += rate;
|
2016-06-05 04:46:28 +00:00
|
|
|
|
2019-10-19 23:44:53 +00:00
|
|
|
*dest = MIX_SAMPLES<D>((SCALE_SAMPLE((isample0 + isample1) >> 1, volume*voice->LeftVolume)), *dest);
|
|
|
|
dest++;
|
2019-07-08 00:41:08 +00:00
|
|
|
|
|
|
|
voice->LeftVolume = SMOOTH_VOLUME(voice->LeftVolume, voice->LeftVolumeDest);
|
2009-07-27 05:47:50 +00:00
|
|
|
}
|
2018-12-15 01:40:03 +00:00
|
|
|
while (--length);
|
2016-06-05 04:46:28 +00:00
|
|
|
|
2018-10-25 23:32:14 +00:00
|
|
|
MV_MixDestination = (char *)dest;
|
2018-12-15 01:40:03 +00:00
|
|
|
|
|
|
|
return position;
|
2009-07-27 05:47:50 +00:00
|
|
|
}
|
|
|
|
|
2019-10-19 23:44:53 +00:00
|
|
|
// stereo source, stereo output
|
|
|
|
template <typename S, typename D>
|
|
|
|
uint32_t MV_MixStereoStereo(struct VoiceNode * const voice, uint32_t length)
|
2009-07-27 05:47:50 +00:00
|
|
|
{
|
2019-10-19 23:44:53 +00:00
|
|
|
auto const source = (S const *)voice->sound;
|
|
|
|
auto dest = (D *)MV_MixDestination;
|
2018-10-25 23:33:21 +00:00
|
|
|
|
2018-10-25 23:32:41 +00:00
|
|
|
uint32_t position = voice->position;
|
|
|
|
uint32_t const rate = voice->RateScale;
|
2019-07-09 05:42:23 +00:00
|
|
|
float const volume = voice->volume*MV_GlobalVolume;
|
2018-10-25 23:32:14 +00:00
|
|
|
|
2018-12-15 01:40:03 +00:00
|
|
|
do
|
2018-10-25 23:32:14 +00:00
|
|
|
{
|
2019-10-19 23:44:53 +00:00
|
|
|
auto const isample0 = CONVERT_LE_SAMPLE_TO_SIGNED<S, D>(source[(position >> 16) << 1]);
|
|
|
|
auto const isample1 = CONVERT_LE_SAMPLE_TO_SIGNED<S, D>(source[((position >> 16) << 1) + 1]);
|
2018-10-25 23:32:14 +00:00
|
|
|
|
2018-10-25 23:32:35 +00:00
|
|
|
position += rate;
|
2016-06-05 04:46:28 +00:00
|
|
|
|
2019-10-19 23:44:53 +00:00
|
|
|
*dest = MIX_SAMPLES<D>(SCALE_SAMPLE(isample0, volume*voice->LeftVolume), *dest);
|
|
|
|
*(dest + (MV_RightChannelOffset / sizeof(*dest)))
|
|
|
|
= MIX_SAMPLES<D>(SCALE_SAMPLE(isample1, volume*voice->RightVolume), *(dest + (MV_RightChannelOffset / sizeof(*dest))));
|
|
|
|
dest += 2;
|
2019-07-08 00:41:08 +00:00
|
|
|
|
|
|
|
voice->LeftVolume = SMOOTH_VOLUME(voice->LeftVolume, voice->LeftVolumeDest);
|
|
|
|
voice->RightVolume = SMOOTH_VOLUME(voice->RightVolume, voice->RightVolumeDest);
|
2009-07-27 05:47:50 +00:00
|
|
|
}
|
2018-12-15 01:40:03 +00:00
|
|
|
while (--length);
|
2016-06-05 04:46:28 +00:00
|
|
|
|
2018-10-25 23:32:14 +00:00
|
|
|
MV_MixDestination = (char *)dest;
|
2018-12-15 01:40:03 +00:00
|
|
|
|
|
|
|
return position;
|
2009-07-27 05:47:50 +00:00
|
|
|
}
|