• R/O
  • HTTP
  • SSH
  • HTTPS

cinnamon: Commit

Cinnamon audio library


Commit MetaInfo

Revisión097ceffeb1c2133af6e2d060b22e1457035be75a (tree)
Tiempo2020-01-05 08:27:38
AutorAlaskanEmily <emily@alas...>
CommiterAlaskanEmily

Log Message

Add per-sound volume on Cin_Sound

Cambiar Resumen

Diferencia incremental

--- a/src/cinnamon.h
+++ b/src/cinnamon.h
@@ -127,6 +127,31 @@ CIN_EXPORT(enum Cin_SoundError) Cin_SoundPlayLoop(struct Cin_Sound *snd,
127127
128128 CIN_EXPORT(enum Cin_SoundError) Cin_SoundStop(struct Cin_Sound *snd);
129129
130+/**
131+ * @brief Sets the volume of the sound.
132+ *
133+ * The range is from 0-255.
134+ *
135+ * @sa Cin_SoundGetVolume
136+ */
137+CIN_EXPORT(enum Cin_SoundError) Cin_SoundSetVolume(struct Cin_Sound *snd,
138+ unsigned char volume);
139+
140+/**
141+ * @brief Gets the volume of the sound.
142+ *
143+ * It is guaranteed that after a successful call to Cin_SoundSetVolume this
144+ * function will output the same value as was passed when setting the volume.
145+ *
146+ * On failure, this will not modify @p out_volume.
147+ *
148+ * The range is from 0-255.
149+ *
150+ * @sa Cin_SoundSetVolume
151+ */
152+CIN_EXPORT(enum Cin_SoundError) Cin_SoundGetVolume(const struct Cin_Sound *snd,
153+ unsigned char *out_volume);
154+
130155 CIN_EXPORT(void) Cin_DestroySound(struct Cin_Sound *snd);
131156
132157 /** @} */ /* End Sound group. */
--- a/src/dsound/cin_dsound.cpp
+++ b/src/dsound/cin_dsound.cpp
@@ -8,6 +8,7 @@
88 #include "cin_soft_loader.h"
99 #include "cinnamon.h"
1010
11+#include <assert.h>
1112 #include <new>
1213
1314 ///////////////////////////////////////////////////////////////////////////////
@@ -143,6 +144,36 @@ CIN_EXPORT(enum Cin_SoundError) Cin_SoundStop(Cin_Sound *snd){
143144
144145 ///////////////////////////////////////////////////////////////////////////////
145146
147+CIN_EXPORT(enum Cin_SoundError) Cin_SoundSetVolume(struct Cin_Sound *snd,
148+ unsigned char volume){
149+
150+ assert(snd != NULL);
151+ if(snd->setVolume(volume))
152+ return Cin_eSoundSuccess;
153+ else
154+ return Cin_eSoundFailure;
155+}
156+
157+///////////////////////////////////////////////////////////////////////////////
158+
159+CIN_EXPORT(enum Cin_SoundError) Cin_SoundGetVolume(const struct Cin_Sound *snd,
160+ unsigned char *out_volume){
161+
162+ assert(snd != NULL);
163+ assert(out_volume != NULL);
164+
165+ unsigned char volume;
166+ if(snd->getVolume(volume)){
167+ out_volume[0] = volume;
168+ return Cin_eSoundSuccess;
169+ }
170+ else{
171+ return Cin_eSoundFailure;
172+ }
173+}
174+
175+///////////////////////////////////////////////////////////////////////////////
176+
146177 CIN_EXPORT(void) Cin_DestroySound(Cin_Sound *snd){
147178 snd->~Cin_Sound();
148179 }
--- a/src/dsound/cin_dsound_sound.cpp
+++ b/src/dsound/cin_dsound_sound.cpp
@@ -87,6 +87,34 @@ void Cin_Sound::stop(){
8787 if(m_buffer != NULL)
8888 m_buffer->Stop();
8989 }
90+
91+///////////////////////////////////////////////////////////////////////////////
92+
93+bool Cin_Sound::setVolume(const unsigned char volume){
94+ const LONG vol = MulDiv(volume, DSBVOLUME_MAX - DSBVOLUME_MIN, 255);
95+ const LONG long_vol = vol + DSBVOLUME_MIN;
96+
97+ return m_buffer && SUCCEEDED(m_buffer->SetVolume(long_vol));
98+}
99+
100+///////////////////////////////////////////////////////////////////////////////
101+
102+bool Cin_Sound::getVolume(unsigned char &out_volume) const{
103+ LONG long_vol;
104+ if(m_buffer == NULL || FAILED(m_buffer->GetVolume(&long_vol)))
105+ return false;
106+
107+ long_vol -= DSBVOLUME_MIN;
108+ const LONG vol = MulDiv(long_vol, 255, DSBVOLUME_MAX - DSBVOLUME_MIN);
109+
110+ assert(vol > 0);
111+ assert(vol < 0x100);
112+
113+ out_volume = static_cast<unsigned char>(vol);
114+
115+ return true;
116+}
117+
90118 ///////////////////////////////////////////////////////////////////////////////
91119
92120 void Cin_Sound::CreateWaveFormat(unsigned sample_rate,
--- a/src/dsound/cin_dsound_sound.hpp
+++ b/src/dsound/cin_dsound_sound.hpp
@@ -38,6 +38,9 @@ public:
3838 void play(bool loop);
3939 void stop();
4040
41+ bool setVolume(unsigned char volume);
42+ bool getVolume(unsigned char &out_volume) const;
43+
4144 static void CreateWaveFormat(unsigned sample_rate,
4245 unsigned channels,
4346 enum Cin_Format format,
--- a/src/openal/cin_openal.c
+++ b/src/openal/cin_openal.c
@@ -12,6 +12,75 @@
1212 #include <assert.h>
1313
1414 /*****************************************************************************/
15+/* See gen_float_table.py for how this table was generated. */
16+static const float char_to_float_table[0x100] = {
17+ 0.0000000000f, 0.0000000000f, 0.0000000000f, 0.0000000000f,
18+ 0.0000000000f, 0.0000000000f, 0.0000000000f, 0.0000000000f,
19+ 0.0000000000f, 0.0000000000f, 0.0000000000f, 0.0000000000f,
20+ 0.0000000000f, 0.0000000000f, 0.0000000000f, 0.0000000000f,
21+ 0.0000000000f, 0.0094771457f, 0.0186795915f, 0.0276100044f,
22+ 0.0362710514f, 0.0446653996f, 0.0527957157f, 0.0606646670f,
23+ 0.0682749203f, 0.0756291427f, 0.0827300011f, 0.0895801626f,
24+ 0.0961822940f, 0.1025390625f, 0.1086531350f, 0.1145271784f,
25+ 0.1201638598f, 0.1255658462f, 0.1307358045f, 0.1356764018f,
26+ 0.1403903050f, 0.1448801811f, 0.1491486971f, 0.1531985200f,
27+ 0.1570323168f, 0.1606527545f, 0.1640625000f, 0.1672642204f,
28+ 0.1702605826f, 0.1730542537f, 0.1756479005f, 0.1780441902f,
29+ 0.1802457897f, 0.1822553660f, 0.1840755860f, 0.1857091168f,
30+ 0.1871586254f, 0.1884267787f, 0.1895162437f, 0.1904296875f,
31+ 0.1911697770f, 0.1917391791f, 0.1921405610f, 0.1923765895f,
32+ 0.1924499317f, 0.1923632546f, 0.1921192251f, 0.1917205102f,
33+ 0.1911697770f, 0.1904696923f, 0.1896229233f, 0.1886321369f,
34+ 0.1875000000f, 0.1862291797f, 0.1848223430f, 0.1832821568f,
35+ 0.1816112881f, 0.1798124040f, 0.1778881714f, 0.1758412573f,
36+ 0.1736743286f, 0.1713900525f, 0.1689910958f, 0.1664801256f,
37+ 0.1638598088f, 0.1611328125f, 0.1583018036f, 0.1553694491f,
38+ 0.1523384160f, 0.1492113713f, 0.1459909820f, 0.1426799151f,
39+ 0.1392808375f, 0.1357964163f, 0.1322293184f, 0.1285822108f,
40+ 0.1248577606f, 0.1210586346f, 0.1171875000f, 0.1132470236f,
41+ 0.1092398726f, 0.1051687137f, 0.1010362142f, 0.0968450408f,
42+ 0.0925978607f, 0.0882973408f, 0.0839461482f, 0.0795469497f,
43+ 0.0751024124f, 0.0706152033f, 0.0660879893f, 0.0615234375f,
44+ 0.0569242148f, 0.0522929883f, 0.0476324249f, 0.0429451916f,
45+ 0.0382339554f, 0.0335013833f, 0.0287501422f, 0.0239828993f,
46+ 0.0192023213f, 0.0144110755f, 0.0096118286f, 0.0048072478f,
47+ 0.5000000000f, 0.5000000000f, 0.5000000000f, 0.5000000000f,
48+ 0.5000000000f, 0.5000000000f, 0.5000000000f, 0.5000000000f,
49+ 0.5000000000f, 0.5000000000f, 0.5000000000f, 0.5000000000f,
50+ 0.5000000000f, 0.5000000000f, 0.5000000000f, 0.5000000000f,
51+ 0.5000000000f, 0.5094771457f, 0.5186795915f, 0.5276100044f,
52+ 0.5362710514f, 0.5446653996f, 0.5527957157f, 0.5606646670f,
53+ 0.5682749203f, 0.5756291427f, 0.5827300011f, 0.5895801626f,
54+ 0.5961822940f, 0.6025390625f, 0.6086531350f, 0.6145271784f,
55+ 0.6201638598f, 0.6255658462f, 0.6307358045f, 0.6356764018f,
56+ 0.6403903050f, 0.6448801811f, 0.6491486971f, 0.6531985200f,
57+ 0.6570323168f, 0.6606527545f, 0.6640625000f, 0.6672642204f,
58+ 0.6702605826f, 0.6730542537f, 0.6756479005f, 0.6780441902f,
59+ 0.6802457897f, 0.6822553660f, 0.6840755860f, 0.6857091168f,
60+ 0.6871586254f, 0.6884267787f, 0.6895162437f, 0.6904296875f,
61+ 0.6911697770f, 0.6917391791f, 0.6921405610f, 0.6923765895f,
62+ 0.6924499317f, 0.6923632546f, 0.6921192251f, 0.6917205102f,
63+ 0.6911697770f, 0.6904696923f, 0.6896229233f, 0.6886321369f,
64+ 0.6875000000f, 0.6862291797f, 0.6848223430f, 0.6832821568f,
65+ 0.6816112881f, 0.6798124040f, 0.6778881714f, 0.6758412573f,
66+ 0.6736743286f, 0.6713900525f, 0.6689910958f, 0.6664801256f,
67+ 0.6638598088f, 0.6611328125f, 0.6583018036f, 0.6553694491f,
68+ 0.6523384160f, 0.6492113713f, 0.6459909820f, 0.6426799151f,
69+ 0.6392808375f, 0.6357964163f, 0.6322293184f, 0.6285822108f,
70+ 0.6248577606f, 0.6210586346f, 0.6171875000f, 0.6132470236f,
71+ 0.6092398726f, 0.6051687137f, 0.6010362142f, 0.5968450408f,
72+ 0.5925978607f, 0.5882973408f, 0.5839461482f, 0.5795469497f,
73+ 0.5751024124f, 0.5706152033f, 0.5660879893f, 0.5615234375f,
74+ 0.5569242148f, 0.5522929883f, 0.5476324249f, 0.5429451916f,
75+ 0.5382339554f, 0.5335013833f, 0.5287501422f, 0.5239828993f,
76+ 0.5192023213f, 0.5144110755f, 0.5096118286f, 0.5048072478f,
77+ 1.0000000000f, 1.0000000000f, 1.0000000000f, 1.0000000000f,
78+ 1.0000000000f, 1.0000000000f, 1.0000000000f, 1.0000000000f,
79+ 1.0000000000f, 1.0000000000f, 1.0000000000f, 1.0000000000f,
80+ 1.0000000000f, 1.0000000000f, 1.0000000000f, 1.0000000000f
81+};
82+
83+/*****************************************************************************/
1584
1685 CIN_PRIVATE_PURE(ALuint)
1786 Cin_CinFormatToOpenALFormat(enum Cin_Format f, unsigned num_channels){
@@ -334,6 +403,7 @@ enum Cin_LoaderError Cin_LoaderFinalize(struct Cin_Loader *ld,
334403
335404 out->snd = ld->snd.snd;
336405 out->ctx = ld->snd.ctx;
406+ out->volume = 0xFF; /* Default volume is 100% */
337407
338408 ld->snd.snd = 0;
339409 return Cin_eLoaderSuccess;
@@ -374,6 +444,39 @@ enum Cin_SoundError Cin_SoundStop(struct Cin_Sound *snd){
374444
375445 /*****************************************************************************/
376446
447+CIN_EXPORT(enum Cin_SoundError) Cin_SoundSetVolume(struct Cin_Sound *snd,
448+ unsigned char volume){
449+
450+ const float gain = char_to_float_table[volume];
451+
452+ assert(snd != NULL);
453+
454+ /* Store the input volume as-is to be sure that calls to
455+ * Cin_SoundSetVolume/Cin_SoundGetVolume are round-trip safe.
456+ */
457+ snd->volume = volume;
458+
459+ alSourcef(snd->snd, AL_GAIN, gain);
460+ if(alGetError() != AL_NO_ERROR)
461+ return Cin_eSoundFailure;
462+ else
463+ return Cin_eSoundSuccess;
464+}
465+
466+/*****************************************************************************/
467+
468+CIN_EXPORT(enum Cin_SoundError) Cin_SoundGetVolume(const struct Cin_Sound *snd,
469+ unsigned char *out_volume){
470+
471+ assert(snd != NULL);
472+ assert(out_volume != NULL);
473+
474+ out_volume[0] = snd->volume;
475+ return Cin_eSoundSuccess;
476+}
477+
478+/*****************************************************************************/
479+
377480 void Cin_DestroySound(struct Cin_Sound *snd){
378481 alcMakeContextCurrent(snd->ctx);
379482 alDeleteSources(1, &(snd->snd));
--- a/src/openal/cin_openal.h
+++ b/src/openal/cin_openal.h
@@ -104,6 +104,13 @@ struct Cin_Driver{
104104 struct Cin_Sound {
105105 ALCcontext *ctx;
106106 ALuint snd;
107+ /* The volume as set is separately stored here, since we use a one-way
108+ * lookup table (of non-linear range no less!) for gain/volume setting.
109+ *
110+ * We want Cin_SoundSetVolume/Cin_SoundGetVolume to be round-trip
111+ * idempotent, so we just store the volume here.
112+ */
113+ unsigned char volume;
107114 };
108115
109116 /*****************************************************************************/
--- /dev/null
+++ b/src/openal/gen_float_table.py
@@ -0,0 +1,95 @@
1+# Generates the C table of floats used translate from 0u-255u to 0.0f to 1.0f
2+#
3+# Copyright (C) 2020 AlaskanEmily
4+#
5+# This software is provided 'as-is', without any express or implied
6+# warranty. In no event will the authors be held liable for any damages
7+# arising from the use of this software.
8+#
9+# Permission is granted to anyone to use this software for any purpose,
10+# including commercial applications, and to alter it and redistribute it
11+# freely, subject to the following restrictions:
12+#
13+# - The origin of this software must not be misrepresented; you must not
14+# claim that you wrote the original software. If you use this software
15+# in a product, an acknowledgment in the product documentation would be
16+# appreciated but is not required.
17+# - Altered source versions must be plainly marked as such, and must not be
18+# misrepresented as being the original software.
19+# - This notice may not be removed or altered from any source distribution.
20+#
21+
22+LOW_SNAP = 16
23+MID_SNAP0 = (128 - 8)
24+MID_SNAP1 = (128 + 8)
25+HI_SNAP = 240
26+
27+LOW_LERP_TANGENT = 0.0
28+MID_LERP_TANGENT = 1.0
29+HIGH_LERP_TANGENT = 0.5
30+
31+def CubicInterp(ValT, LoT, HiT, LoV, HiV):
32+ # Convert T to 0.0-1.0
33+ T = float(ValT - LoT) / float(HiT - LoT)
34+ A = (2.0 * pow(T, 3)) - (3.0 * pow(T, 2)) + 1.0
35+ B = pow(T, 3) - (2.0 * pow(T, 2)) + T
36+ C = (-2.0 * pow(T, 3)) + (3.0 * pow(T, 2)) + 0.0
37+ D = pow(T, 3) - (2.0 * pow(T, 2))
38+ if LoT < 0.5:
39+ Tan0 = LOW_LERP_TANGENT
40+ Tan1 = MID_LERP_TANGENT
41+ else:
42+ Tan0 = MID_LERP_TANGENT
43+ Tan1 = HIGH_LERP_TANGENT
44+
45+ return (A * LoV) + (B * Tan0) + (C * HiV) + (D * Tan1)
46+
47+def Lerp(T, LoT, HiT, LoV, HiV):
48+ return LoV + ((float(T - LoT) / float(HiT - LoT)) * (HiV - LoV))
49+
50+def DoAppend():
51+ Line = " "
52+ i = 0
53+ while True:
54+ Value = (yield)
55+ if Value == '\n':
56+ i = 0
57+ else:
58+ Str = "%1.10Ff, " % Value
59+ Line += Str
60+ i += 1
61+
62+ if i % 4 == 0:
63+ print(Line)
64+ Line = " "
65+
66+print("{")
67+
68+Append = DoAppend()
69+next(Append)
70+
71+e = 0
72+while e < LOW_SNAP:
73+ Append.send(0.0)
74+ e += 1
75+
76+while e < MID_SNAP0:
77+ Value = CubicInterp(e, LOW_SNAP, MID_SNAP0, 0.0, 0.5)
78+ Append.send(Value)
79+ e += 1
80+
81+while e < MID_SNAP1:
82+ Append.send(0.5)
83+ e += 1
84+
85+while e < HI_SNAP:
86+ Value = CubicInterp(e, MID_SNAP1, HI_SNAP, 0.5, 1.0)
87+ Append.send(Value)
88+ e += 1
89+
90+while e <= 255:
91+ Append.send(1.0)
92+ e += 1
93+
94+Append.send('\n')
95+print("};")
Show on old repository browser