Skip to content

Commit a75c498

Browse files
authored
Fixed not releasing a pipe after fast switching between vave-based tremulant samples and regular pipe samples #2004 (#2041)
1 parent 8f8d350 commit a75c498

File tree

3 files changed

+63
-19
lines changed

3 files changed

+63
-19
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
- Fixed not releasing a pipe after fast switching between vave-based tremulant samples and regular pipe samples https://github.com/GrandOrgue/grandorgue/issues/2004
12
- Removed support of MacOs 12
23
- Fixed hang if there were lots of unused ODF entries https://github.com/GrandOrgue/grandorgue/issues/1918
34
# 3.15.3 (2024-11-23)

src/grandorgue/sound/GOSoundFader.cpp

+46-18
Original file line numberDiff line numberDiff line change
@@ -32,39 +32,67 @@ void GOSoundFader::Process(
3232
unsigned nFrames, float *buffer, float externalVolume) {
3333
// setup process
3434

35-
// Consider the velocity volume as part of the external volume
36-
externalVolume *= m_VelocityVolume;
37-
3835
float startTargetVolumePoint = m_LastTargetVolumePoint;
36+
3937
// Calculate new m_LastTargetVolumePoint
4038
// the target volume will be changed from startTargetVolumePoint to
4139
// m_LastTargetVolumePoint during the nFrames
42-
float targetVolumeDeltaPerFrame
43-
= m_IncreasingDeltaPerFrame + m_DecreasingDeltaPerFrame;
4440

45-
if (targetVolumeDeltaPerFrame != 0.0f) {
46-
m_LastTargetVolumePoint = std::clamp(
47-
startTargetVolumePoint + targetVolumeDeltaPerFrame * nFrames,
48-
0.0f,
49-
m_TargetVolume);
41+
unsigned framesLeftAfterIncreasing = nFrames;
42+
43+
// increasing section
44+
if (m_IncreasingDeltaPerFrame > 0.0f) {
45+
// we are increasing now
46+
float newTargetVolumePoint
47+
= m_LastTargetVolumePoint + m_IncreasingDeltaPerFrame * nFrames;
48+
49+
if (newTargetVolumePoint < m_TargetVolume) {
50+
framesLeftAfterIncreasing = 0; // we are increase during the whole period
51+
m_LastTargetVolumePoint = newTargetVolumePoint;
52+
} else {
53+
// we reach m_TargetVolume inside this nFrames period
5054

51-
if (m_LastTargetVolumePoint >= m_TargetVolume)
52-
// target volume is reached. Stop increasing
55+
// stop increasing
5356
m_IncreasingDeltaPerFrame = 0.0f;
54-
else if (m_LastTargetVolumePoint <= 0.0f)
55-
// Decreasing is finished. Stop it.
57+
58+
// calculate how many frames left after increasing
59+
framesLeftAfterIncreasing = nFrames
60+
- unsigned((m_TargetVolume - m_LastTargetVolumePoint)
61+
/ m_IncreasingDeltaPerFrame);
62+
63+
m_LastTargetVolumePoint = m_TargetVolume;
64+
}
65+
}
66+
67+
// decreasing section
68+
if (framesLeftAfterIncreasing && m_DecreasingDeltaPerFrame > 0.0f) {
69+
// decrease the volume
70+
float newTargetVolumePoint = m_LastTargetVolumePoint
71+
- m_DecreasingDeltaPerFrame * framesLeftAfterIncreasing;
72+
73+
if (newTargetVolumePoint > 0.0f) {
74+
m_LastTargetVolumePoint = newTargetVolumePoint;
75+
} else {
76+
// stop decreasing
5677
m_DecreasingDeltaPerFrame = 0.0f;
78+
m_LastTargetVolumePoint = 0.0f;
79+
}
5780
}
5881

59-
if (m_LastExternalVolumePoint < 0.0f) // The first Process() call
60-
m_LastExternalVolumePoint = externalVolume;
82+
// Calculate the external volume
83+
float targetExternalVolume = m_VelocityVolume * externalVolume;
84+
85+
if (m_LastExternalVolumePoint < 0.0f)
86+
m_LastExternalVolumePoint = targetExternalVolume;
6187

6288
float startExternalVolumePoint = m_LastExternalVolumePoint;
89+
6390
// Calculate new m_LastExternalVolumePoint
6491
// the target volume will be changed from startExternalVolumePoint to
6592
// m_LastExternalVolumePoint during the nFrames period
66-
if (externalVolume != startExternalVolumePoint)
67-
m_LastExternalVolumePoint += (externalVolume - startExternalVolumePoint)
93+
if (targetExternalVolume != startExternalVolumePoint)
94+
m_LastExternalVolumePoint
95+
+= (targetExternalVolume - startExternalVolumePoint)
6896
// Assume that external volume is to be reached in MAX_FRAME_SIZE frames
6997
* std::max(nFrames, EXTERNAL_VOLUME_CHANGE_FRAMES)
7098
/ EXTERNAL_VOLUME_CHANGE_FRAMES;

src/grandorgue/sound/GOSoundFader.h

+16-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
#ifndef GOSOUNDFADER_H_
99
#define GOSOUNDFADER_H_
1010

11+
#include <assert.h>
12+
1113
/**
1214
* This class is responsible for smoothly changing a volume of samples.
1315
*
@@ -71,7 +73,20 @@ class GOSoundFader {
7173
inline void StartDecreasingVolume(unsigned nFrames) {
7274
// maybe m_TargetVolume has not yet been reached, but the velocity of
7375
// decreasing should be the same as it has reached
74-
m_DecreasingDeltaPerFrame = -(m_TargetVolume / nFrames);
76+
m_DecreasingDeltaPerFrame = m_TargetVolume / nFrames;
77+
if (m_IncreasingDeltaPerFrame > 0.0f) {
78+
/*
79+
The increasing has not yet finished. We are starting a "virtual"
80+
decreasing from m_TargetVolume to 0.
81+
The increasing processus will continue until it meet the "virtual"
82+
decreasing one at the new m_TargetVolume. Let's calculate it
83+
*/
84+
assert(m_LastTargetVolumePoint < m_TargetVolume);
85+
m_TargetVolume = (m_TargetVolume - m_LastTargetVolumePoint)
86+
* m_IncreasingDeltaPerFrame
87+
/ (m_IncreasingDeltaPerFrame + m_DecreasingDeltaPerFrame)
88+
+ m_LastTargetVolumePoint;
89+
}
7590
}
7691

7792
inline float GetVelocityVolume() const { return m_VelocityVolume; }

0 commit comments

Comments
 (0)