1 /*---------------------------------------------------------------------------*
2 Project: NintendoWare
3 File: snd_CurveAdshr.cpp
4
5 Copyright (C)2009-2010 Nintendo Co., Ltd./HAL Laboratory, Inc. All rights reserved.
6
7 These coded instructions, statements, and computer programs contain
8 proprietary information of Nintendo of America Inc. and/or Nintendo
9 Company Ltd., and are protected by Federal copyright law. They may
10 not be disclosed to third parties or copied or duplicated in any form,
11 in whole or in part, without the prior written consent of Nintendo.
12
13 $Revision: 13145 $
14 *---------------------------------------------------------------------------*/
15
16 #include "precompiled.h"
17
18 #include <nw/snd/snd_CurveAdshr.h>
19 #include <nw/assert.h>
20
21 namespace nw {
22 namespace snd {
23 namespace internal {
24
25 const float CurveAdshr::VOLUME_INIT = -90.4f;
26
27 // squareスケール -> デシベル 変換テーブル
28
29 const s16 CurveAdshr::DecibelSquareTable[ DECIBEL_SQUARE_TABLE_SIZE ] =
30 {
31 -723, -722, -721, -651, -601, -562, -530, -503,
32 -480, -460, -442, -425, -410, -396, -383, -371,
33 -360, -349, -339, -330, -321, -313, -305, -297,
34 -289, -282, -276, -269, -263, -257, -251, -245,
35 -239, -234, -229, -224, -219, -214, -210, -205,
36 -201, -196, -192, -188, -184, -180, -176, -173,
37 -169, -165, -162, -158, -155, -152, -149, -145,
38 -142, -139, -136, -133, -130, -127, -125, -122,
39 -119, -116, -114, -111, -109, -106, -103, -101,
40 -99, -96, -94, -91, -89, -87, -85, -82,
41 -80, -78, -76, -74, -72, -70, -68, -66,
42 -64, -62, -60, -58, -56, -54, -52, -50,
43 -49, -47, -45, -43, -42, -40, -38, -36,
44 -35, -33, -31, -30, -28, -27, -25, -23,
45 -22, -20, -19, -17, -16, -14, -13, -11,
46 -10, -8, -7, -6, -4, -3, -1, 0
47 };
48
49
50 /* ========================================================================
51 public function
52 ======================================================================== */
53
54 /*---------------------------------------------------------------------------*
55 Name: CurveAdshr
56
57 Description: コンストラクタ
58
59 Arguments: なし
60
61 Returns: なし
62 *---------------------------------------------------------------------------*/
CurveAdshr()63 CurveAdshr::CurveAdshr()
64 {
65 Initialize();
66 }
67
68 /*---------------------------------------------------------------------------*
69 Name: Init
70
71 Description: エンベロープジェネレータのパラメータを初期化します
72
73 Arguments: なし
74
75 Returns: なし
76 *---------------------------------------------------------------------------*/
Initialize(float initDecibel)77 void CurveAdshr::Initialize( float initDecibel )
78 {
79 SetAttack( ATTACK_INIT );
80 SetHold( HOLD_INIT );
81 SetDecay( DECAY_INIT );
82 SetSustain( SUSTAIN_INIT );
83 SetRelease( RELEASE_INIT );
84
85 Reset( initDecibel );
86 }
87
88 /*---------------------------------------------------------------------------*
89 Name: Reset
90
91 Description: エンベロープジェネレータをリセットします
92
93 Arguments: なし
94
95 Returns: なし
96 *---------------------------------------------------------------------------*/
Reset(float initDecibel)97 void CurveAdshr::Reset( float initDecibel )
98 {
99 m_Value = initDecibel * 10.0f;
100 m_Status = STATUS_ATTACK;
101 }
102
103 /*---------------------------------------------------------------------------*
104 Name: GetValue
105
106 Description: 現在値を取得します
107
108 Arguments: なし
109
110 Returns: 現在値
111 *---------------------------------------------------------------------------*/
GetValue() const112 f32 CurveAdshr::GetValue() const
113 {
114 // アタックの速度が最大の時は、音量0から始まらず最大の音量を返す
115 if ( ( m_Status == STATUS_ATTACK ) && ( m_Attack == 0.0f ) )
116 {
117 return 0.0f;
118 }
119
120 return m_Value/10.0f;
121 }
122
123 /*---------------------------------------------------------------------------*
124 Name: Update
125
126 Description: エンベロープを更新します
127
128 Arguments: msec - 更新時間
129
130 Returns: なし
131 *---------------------------------------------------------------------------*/
Update(int msec)132 void CurveAdshr::Update( int msec )
133 {
134 switch ( m_Status )
135 {
136 case STATUS_ATTACK:
137 {
138 while( msec > 0 )
139 {
140 m_Value *= m_Attack;
141 msec--;
142
143 if ( m_Value > - 1.0f / 32.0f )
144 {
145 m_Value = 0.0f;
146 m_Status = STATUS_HOLD;
147 m_HoldCounter = m_Hold;
148 break;
149 }
150 }
151 break;
152 }
153
154 case STATUS_HOLD:
155 {
156 if ( msec < m_HoldCounter )
157 {
158 m_HoldCounter -= msec;
159 }
160 else
161 {
162 msec -= m_HoldCounter;
163 m_HoldCounter = 0;
164 m_Status = STATUS_DECAY;
165 }
166 if ( m_Status != STATUS_DECAY ) break;
167 // continue;
168 }
169
170 case STATUS_DECAY:
171 {
172 const f32 sustainDecay =
173 CalcDecibelSquare( m_Sustain );
174
175 m_Value -= m_Decay * msec;
176 if ( m_Value < sustainDecay )
177 {
178 m_Value = sustainDecay;
179 m_Status = STATUS_SUSTAIN;
180 }
181 break;
182 }
183
184 case STATUS_SUSTAIN:
185 // do Nothing
186 break;
187
188 case STATUS_RELEASE:
189 m_Value -= m_Release * msec;
190 break;
191 }
192 }
193
194 /*---------------------------------------------------------------------------*
195 Name: SetChannelAttack
196
197 Description: エンベロープのアタックを設定します
198
199 Arguments: attack - アタック値
200
201 Returns: None.
202 *---------------------------------------------------------------------------*/
SetAttack(int attack)203 void CurveAdshr::SetAttack( int attack )
204 {
205 /*----------------------------------------------------------
206 以下の計算式をテーブルにして最適化
207
208 static const u8 attackTable[ 127 - 109 + 1 ] = {
209 0, 1, 5, 14, 26, 38, 51, 63, 73, 84,
210 92, 100, 109, 116, 123, 127, 132, 137, 143
211 };
212
213 NW_MINMAX_ASSERT( attack, 0, 127 );
214
215 double x;
216 if ( attack < 109 ) {
217 x = 255 - attack;
218 }
219 else {
220 x = attackTable[ 127 - attack ];
221 }
222 x /= 256.0f;
223 x = std::pow( x, 1.0/5 );
224
225 m_Attack = static_cast<f32>(x);
226 ----------------------------------------------------------*/
227
228 static const float attackTable[ 128 ] = {
229 0.9992175f, 0.9984326f, 0.9976452f, 0.9968553f,
230 0.9960629f, 0.9952679f, 0.9944704f, 0.9936704f,
231 0.9928677f, 0.9920625f, 0.9912546f, 0.9904441f,
232 0.9896309f, 0.9888151f, 0.9879965f, 0.9871752f,
233 0.9863512f, 0.9855244f, 0.9846949f, 0.9838625f,
234 0.9830273f, 0.9821893f, 0.9813483f, 0.9805045f,
235 0.9796578f, 0.9788081f, 0.9779555f, 0.9770999f,
236 0.9762413f, 0.9753797f, 0.9745150f, 0.9736472f,
237 0.9727763f, 0.9719023f, 0.9710251f, 0.9701448f,
238 0.9692612f, 0.9683744f, 0.9674844f, 0.9665910f,
239 0.9656944f, 0.9647944f, 0.9638910f, 0.9629842f,
240 0.9620740f, 0.9611604f, 0.9602433f, 0.9593226f,
241 0.9583984f, 0.9574706f, 0.9565392f, 0.9556042f,
242 0.9546655f, 0.9537231f, 0.9527769f, 0.9518270f,
243 0.9508732f, 0.9499157f, 0.9489542f, 0.9479888f,
244 0.9470195f, 0.9460462f, 0.9450689f, 0.9440875f,
245 0.9431020f, 0.9421124f, 0.9411186f, 0.9401206f,
246 0.9391184f, 0.9381118f, 0.9371009f, 0.9360856f,
247 0.9350659f, 0.9340417f, 0.9330131f, 0.9319798f,
248 0.9309420f, 0.9298995f, 0.9288523f, 0.9278004f,
249 0.9267436f, 0.9256821f, 0.9246156f, 0.9235442f,
250 0.9224678f, 0.9213864f, 0.9202998f, 0.9192081f,
251 0.9181112f, 0.9170091f, 0.9159016f, 0.9147887f,
252 0.9136703f, 0.9125465f, 0.9114171f, 0.9102821f,
253 0.9091414f, 0.9079949f, 0.9068427f, 0.9056845f,
254 0.9045204f, 0.9033502f, 0.9021740f, 0.9009916f,
255 0.8998029f, 0.8986080f, 0.8974066f, 0.8961988f,
256 0.8949844f, 0.8900599f, 0.8824622f, 0.8759247f,
257 0.8691861f, 0.8636406f, 0.8535788f, 0.8430189f,
258 0.8286135f, 0.8149099f, 0.8002172f, 0.7780663f,
259 0.7554750f, 0.7242125f, 0.6828239f, 0.6329169f,
260 0.5592135f, 0.4551411f, 0.3298770f, 0.0000000f
261 };
262
263 NW_MINMAX_ASSERT( attack, 0, 127 );
264 m_Attack = attackTable[ attack ];
265 }
266
267 /*---------------------------------------------------------------------------*
268 Name: SetSustain
269
270 Description: エンベロープのサステインを設定します
271
272 Arguments: hold - ホールド値
273
274 Returns: None.
275 *---------------------------------------------------------------------------*/
SetHold(int hold)276 void CurveAdshr::SetHold( int hold )
277 {
278 NW_MINMAX_ASSERT( hold, 0, 127 );
279
280 m_Hold = static_cast<u16>( (hold+1)*(hold+1)/4 );
281 }
282
283 /*---------------------------------------------------------------------------*
284 Name: SetDecay
285
286 Description: エンベロープのディケイを設定します
287
288 Arguments: decay - ディケイ値
289
290 Returns: None.
291 *---------------------------------------------------------------------------*/
SetDecay(int decay)292 void CurveAdshr::SetDecay( int decay )
293 {
294 NW_MINMAX_ASSERT( decay, 0, 127 );
295
296 m_Decay = CalcRelease( decay );
297 }
298
299 /*---------------------------------------------------------------------------*
300 Name: SetSustain
301
302 Description: エンベロープのサステインを設定します
303
304 Arguments: sustain - サステイン値
305
306 Returns: None.
307 *---------------------------------------------------------------------------*/
SetSustain(int sustain)308 void CurveAdshr::SetSustain( int sustain )
309 {
310 NW_MINMAX_ASSERT( sustain, 0, 127 );
311
312 m_Sustain = static_cast<u8>( sustain );
313 }
314
315 /*---------------------------------------------------------------------------*
316 Name: SetRelease
317
318 Description: エンベロープのリリースを設定します
319
320 Arguments: release - リリース値
321
322 Returns: None.
323 *---------------------------------------------------------------------------*/
SetRelease(int release)324 void CurveAdshr::SetRelease( int release )
325 {
326 NW_MINMAX_ASSERT( release, 0, 127 );
327
328 m_Release = CalcRelease( release );
329 }
330
331 /* ========================================================================
332 private function
333 ======================================================================== */
334
CalcRelease(int release)335 f32 CurveAdshr::CalcRelease( int release )
336 {
337 NW_MINMAX_ASSERT( release, 0, 127 );
338
339 if ( release == 127 ) return 65535.0f;
340 if ( release == 126 ) return 120 / 5.0f;
341
342 if ( release < 50 ) {
343 return ( ( release << 1 ) + 1 ) / 128.0f / 5.0f;
344 }
345 else {
346 return ( 60.0f / ( 126 - release ) ) / 5.0f;
347 }
348 }
349
CalcDecibelSquare(int scale)350 s16 CurveAdshr::CalcDecibelSquare( int scale )
351 {
352 NW_MINMAX_ASSERT( scale, 0, CALC_DECIBEL_SCALE_MAX );
353 return DecibelSquareTable[ scale ];
354 }
355
356
357 } // namespace nw::snd::internal
358 } // namespace nw::snd
359 } // namespace nw
360
361