8
8
9
9
#include < cstdint>
10
10
#include < cmath>
11
+ #include < algorithm>
11
12
#include < unistd.h>
12
13
13
14
#include " config.h"
20
21
constexpr int32_t AUDIO_SAMPLE_RATE = 44100 ;
21
22
constexpr float PI2 = 2 .0f * M_PI;
22
23
constexpr int SILENCE_BEFORE_STOP = kMillisPerSecond * 5 ;
23
- constexpr int MAX_RAMP = 350 ;
24
+ constexpr int MAX_RAMP = 450 ;
25
+ constexpr int RAMP_SCALE = 10 ;
24
26
int instances = 0 ;
25
27
26
28
struct Sound {
27
- Sound (int blockSize, int frequency, int millis, int volume);
29
+ Sound (int blockSize, bool fadeIn, int frequency, int millis, int volume);
28
30
~Sound ();
29
31
30
32
bool ready () const ;
31
33
float sample ();
32
- void sync (Sound *previous);
34
+ void sync (Sound *previous, bool lastSound, int blockSize );
33
35
34
36
private:
35
37
uint32_t _duration;
36
38
uint32_t _samples;
37
39
uint32_t _sampled;
38
- uint32_t _ramp;
40
+ uint32_t _rest;
41
+ uint32_t _fadeIn;
42
+ uint32_t _fadeOut;
39
43
float _amplitude;
40
44
float _increment;
41
45
float _phase;
42
46
};
43
47
44
- Sound::Sound (int blockSize, int frequency, int millis, int volume) :
48
+ Sound::Sound (int blockSize, bool fadeIn, int frequency, int millis, int volume) :
45
49
_duration(millis),
46
50
_samples(AUDIO_SAMPLE_RATE * millis / 1000 ),
47
51
_sampled(0 ),
48
- _ramp(_samples / 10 ),
52
+ _rest(0 ),
53
+ _fadeIn(0 ),
54
+ _fadeOut(0 ),
49
55
_amplitude((float )volume / 100.0f),
50
56
_increment(PI2 * (float )frequency / AUDIO_SAMPLE_RATE),
51
57
_phase(0 ) {
52
58
instances++;
53
59
54
- if (frequency != 0 ) {
55
- _ramp = 0 ;
56
- } else if (_ramp > MAX_RAMP) {
57
- _ramp = MAX_RAMP;
58
- }
59
-
60
- // align sample size with burst-size
61
- if (_ramp != 0 && _samples > blockSize) {
62
- _samples = (_samples / blockSize) * blockSize;
60
+ if (fadeIn) {
61
+ _fadeIn = std::min ((int )_samples / RAMP_SCALE, MAX_RAMP);
62
+ } else if (frequency == 0 ) {
63
+ _rest = std::min ((int )_samples / RAMP_SCALE, MAX_RAMP);
64
+ // align sample size with burst-size
65
+ if (_rest != 0 && _samples > blockSize) {
66
+ _samples = (_samples / blockSize) * blockSize;
67
+ }
63
68
}
64
69
}
65
70
@@ -82,29 +87,45 @@ float Sound::sample() {
82
87
_sampled++;
83
88
_phase = fmod (_phase + _increment, PI2);
84
89
85
- if (_ramp != 0 ) {
86
- if (_sampled < _ramp) {
90
+ if (_fadeIn != 0 && _sampled < _fadeIn) {
91
+ // fadeIn from silence
92
+ result *= (float )(_sampled) / (float )_fadeIn;
93
+ } else if (_rest != 0 ) {
94
+ if (_sampled < _rest) {
87
95
// fadeOut the previous sound
88
- result *= (float )(_ramp - _sampled) / (float )_ramp ;
89
- } else if (_samples - _sampled < _ramp ) {
90
- // fadeIn the next sound
91
- result *= (float )(_ramp - (_samples - _sampled)) / (float )_ramp ;
96
+ result *= (float )(_rest - _sampled) / (float )_rest ;
97
+ } else if (_samples - _sampled < _rest && _fadeOut == 0 ) {
98
+ // fadeIn the next sound, but not when the final sound
99
+ result *= (float )(_rest - (_samples - _sampled)) / (float )_rest ;
92
100
} else {
93
101
result = 0 ;
94
102
}
103
+ } else if (_fadeOut != 0 && _samples - _sampled < _fadeOut) {
104
+ // fadeOut to silence
105
+ result *= (float )(_samples - _sampled) / (float )_fadeOut;
95
106
}
96
107
return result;
97
108
}
98
109
99
110
//
100
111
// Continues the same phase for the previous sound
101
112
//
102
- void Sound::sync (Sound *previous) {
113
+ void Sound::sync (Sound *previous, bool lastSound, int blockSize ) {
103
114
_phase = previous->_phase ;
104
- if (_ramp != 0 ) {
105
- // for fadeOut/In
115
+ if (_rest != 0 ) {
116
+ // for fadeOut/In for adjoining silence
106
117
_increment = previous->_increment ;
107
118
}
119
+ if (lastSound) {
120
+ // fade out non-silent sound to silence
121
+ if (_samples > blockSize) {
122
+ _samples = (_samples / blockSize) * blockSize;
123
+ }
124
+ _fadeOut = _samples / RAMP_SCALE;
125
+ if (_fadeOut > MAX_RAMP) {
126
+ _fadeOut = MAX_RAMP;
127
+ }
128
+ }
108
129
}
109
130
110
131
Audio::Audio () {
@@ -195,7 +216,7 @@ DataCallbackResult Audio::onAudioReady(AudioStream *oboeStream, void *audioData,
195
216
//
196
217
void Audio::add (int frequency, int millis, int volume) {
197
218
std::lock_guard<std::mutex> lock (_lock);
198
- _queue.push (new Sound (_stream->getFramesPerBurst (), frequency, millis, volume));
219
+ _queue.push (new Sound (_stream->getFramesPerBurst (), _queue. empty (), frequency, millis, volume));
199
220
_startNoSound = 0 ;
200
221
}
201
222
@@ -215,7 +236,7 @@ Sound *Audio::front() {
215
236
_queue.pop ();
216
237
auto *next = _queue.front ();
217
238
if (next != nullptr ) {
218
- next->sync (result);
239
+ next->sync (result, _queue. size () == 1 , _stream-> getFramesPerBurst () );
219
240
}
220
241
result = nullptr ;
221
242
}
0 commit comments