4 XCSoar Glide Computer - http://www.xcsoar.org/
5 Copyright (C) 2000-2013 The XCSoar Project
6 A detailed list of copyright holders can be found in the file "AUTHORS".
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; either version 2
11 of the License, or (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 #include "VarioSynthesiser.hpp"
25 #include "Math/FastMath.h"
26 #include "Util/Clamp.hpp"
31 * The minimum and maximum vario range for the constants below [cm/s].
33 static constexpr int min_vario
= -500, max_vario
= 500;
36 VarioSynthesiser::VarioToFrequency(int ivario
)
39 ? (zero_frequency
+ (unsigned)ivario
* (max_frequency
- zero_frequency
)
40 / (unsigned)max_vario
)
41 : (zero_frequency
- (unsigned)(ivario
* (int)(zero_frequency
- min_frequency
) / min_vario
));
45 VarioSynthesiser::SetVario(unsigned sample_rate
, fixed vario
)
47 const ScopeLock
protect(mutex
);
49 const int ivario
= Clamp((int)(vario
* 100), min_vario
, max_vario
);
51 if (dead_band_enabled
&& InDeadBand(ivario
)) {
52 /* inside the "dead band" */
57 /* update the ToneSynthesiser base class */
58 SetTone(sample_rate
, VarioToFrequency(ivario
));
61 /* while climbing, the vario sound gets interrupted by silence
64 const unsigned period_ms
= sample_rate
65 * (min_period_ms
+ (max_vario
- ivario
)
66 * (max_period_ms
- min_period_ms
) / max_vario
)
69 silence_count
= period_ms
/ 3;
70 audible_count
= period_ms
- silence_count
;
72 /* preserve the old "_remaining" values as much as possible, to
73 avoid chopping off the previous tone */
75 if (audible_remaining
> audible_count
)
76 audible_remaining
= audible_count
;
78 if (silence_remaining
> silence_count
)
79 silence_remaining
= silence_count
;
81 /* continuous tone while sinking */
88 VarioSynthesiser::SetSilence()
90 const ScopeLock
protect(mutex
);
95 VarioSynthesiser::UnsafeSetSilence()
100 if (audible_remaining
> 0)
101 /* quit the current period as early as possible; the method
102 Synthesise() will take care for finishing the current sine
103 wave to avoid clicking noise */
104 audible_remaining
= 1;
106 silence_remaining
= 0;
111 VarioSynthesiser::Synthesise(int16_t *buffer
, size_t n
)
113 const ScopeLock
protect(mutex
);
115 assert(audible_count
> 0 || silence_count
> 0);
117 if (silence_count
== 0) {
118 /* magic value for "continuous tone" */
119 ToneSynthesiser::Synthesise(buffer
, n
);
124 if (audible_remaining
> 0) {
125 /* generate a period of audible tone */
127 unsigned o
= silence_count
> 0
128 ? std::min(n
, audible_remaining
)
130 ToneSynthesiser::Synthesise(buffer
, o
);
133 audible_remaining
-= o
;
135 if (audible_remaining
== 0 && silence_remaining
> 0) {
136 /* finish the current sine wave to avoid clicking noise */
137 audible_remaining
= ToZero();
138 if (audible_remaining
== 0)
139 /* finished, we can now emit a period of silence */
142 } else if (silence_remaining
> 0) {
143 /* generate a period of silence (climbing) */
145 unsigned o
= audible_count
> 0
146 ? std::min(n
, silence_remaining
)
148 /* the "silence" PCM sample value is zero */
149 std::fill(buffer
, buffer
+ o
, 0);
152 silence_remaining
-= o
;
154 /* period finished, begin next one */
156 audible_remaining
= audible_count
;
157 silence_remaining
= silence_count
;