1 /*---------------------------------------------------------------------------*
2   Project:  Horizon
3   File:     snd_FxReverb.h
4 
5   Copyright (C)2009 Nintendo Co., Ltd.  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   $Rev: $
14  *---------------------------------------------------------------------------*/
15 
16 #ifndef NN_SND_FX_REVERB_H_
17 #define NN_SND_FX_REVERB_H_
18 
19 #ifdef __cplusplus
20 
21 namespace nn  { namespace snd { namespace CTR {
22 
23 //---------------------------------------------------------------------------
24 //! @brief  リバーブエフェクトクラスです。
25 //!
26 //!         エフェクトを実行するには、@ref SetEffect 関数を呼び出してください。
27 //!
28 //!         エフェクトは CPU で処理されます (DSP では処理されません)。
29 //!
30 //!         @ref FxDelay と異なり、前方の 2ch にしかエフェクト処理されません。
31 //!
32 //! @see FxDelay クラス
33 //!
34 //! @date 2010/10/20 初版
35 //---------------------------------------------------------------------------
36 class FxReverb
37 {
38 public:
39     //---------------------------------------------------------------------------
40     //! @brief  フィルタサイズを表現する構造体です。
41     //!
42     //!         m_Comb0 および m_Comb1 は、後置残響音
43     //!         (詳しくは @ref Param の説明をご覧ください) にかかる
44     //!         「くし型フィルタ」のサイズを表します。
45     //!         この値を小さくすると、特定の周波数だけ際立った金属的な音になります。
46     //!         m_Comb0 の初期値は 19 * 160、
47     //!         m_Comb1 の初期値は 23 * 160 です。
48     //!
49     //!         m_AllPass は、後置残響音にかかる全域通過フィルタのサイズ (ディレイ長) を表します。
50     //!         この値を大きくすると、後置残響音をきめ細かくすることができます。
51     //!         初期値は 13 * 160 です。
52     //!
53     //!         160 は 1 オーディオフレーム (約 5 msec) で処理するサンプル数に由来します。
54     //!         初期値で設定されているように 19, 23, 13 など、
55     //!         「互いに素」な値を設定することが望ましいです。
56     //!         互いに素な値に設定しないと、リバーブ音に周期性が出やすくなります。
57     //!
58     //!         エフェクト実行中にこれらの値を変更すると、
59     //!         ノイズがのる可能性があります。
60     //!
61     //! @date 2010/10/20 初版
62     //---------------------------------------------------------------------------
63     struct FilterSize
64     {
65         u32  m_Comb0;    //!< くし型フィルタ 0 のサイズです。
66         u32  m_Comb1;    //!< くし型フィルタ 1 のサイズです。
67         u32  m_AllPass;  //!< 全域通過フィルタのサイズです。
68 
69         //---------------------------------------------------------------------------
70         //! @brief    コンストラクタです。
71         //!
72         //! @date 2010/10/20 初版
73         //---------------------------------------------------------------------------
FilterSizeFilterSize74         FilterSize()
75         : m_Comb0( 19 * NN_SND_SAMPLES_PER_FRAME ),
76           m_Comb1( 23 * NN_SND_SAMPLES_PER_FRAME ),
77           m_AllPass( 13 * NN_SND_SAMPLES_PER_FRAME )
78         {}
79     };
80 
81     //---------------------------------------------------------------------------
82     //! @brief  リバーブパラメータの構造体です。
83     //!
84     //!         リバーブは大きく「初期反射音」と「後置残響音」とに分けて考えられます。
85     //!
86     //!         「初期反射音」は m_EarlyReflectionTime および m_EarlyGain で
87     //!         調整することができます。
88     //!
89     //!         m_EarlyReflectionTime は初期反射音が返ってくるまでの時間を表します。
90     //!         この値が大きければ大きいほど、音が反射して返ってくるまでの時間が長くなります。
91     //!         単位は msec で、5 以上かつ 5 の倍数を設定する必要があります。
92     //!         初期値は 60 に設定されています。
93     //!
94     //!         m_EarlyGain は初期反射音の出力ゲインを表します。
95     //!         0.0f ~ 1.0f で設定します。
96     //!         0.0f にすると初期反射音が聞こえなくなります。
97     //!         初期値は 0.6f に設定されています。
98     //!
99     //!         「後置残響音」は m_FusedTime, m_FusedGain, m_PreDelayTime,
100     //!         m_Coloration, m_Damping, m_pFilterSize で調整することができます。
101     //!
102     //!         m_FusedTime は後置残響音が鳴り続ける時間を表します。
103     //!         この値を大きくすると、音が反射しやすい空間を表現することができます。
104     //!         単位は msec で、初期値は 4000 に設定されています。
105     //!
106     //!         m_FusedGain は後置残響音の出力ゲインを表します。
107     //!         0.0f ~ 1.0f で設定します。
108     //!         0.0f にすると後置残響音が聞こえなくなります。
109     //!         初期値は 0.4f に設定されています。
110     //!
111     //!         m_PreDelayTime は、後置残響音の前に置かれる遅延時間を表します。
112     //!         この値が大きければ大きいほど、後置残響音が遅れて聞こえるようになります。
113     //!         単位は msec で、5 以上かつ 5 の倍数で設定する必要があります。
114     //!         初期値は 100 です。
115     //!
116     //!         m_Coloration は後置残響音の全域通過フィルタの係数を表します。
117     //!         この値を大きくすると後置残響音がきめ細かくなり、
118     //!         より複雑な残響が混じるようなります。
119     //!         0.0f ~ 1.0f で設定します。
120     //!         0.0f にすると全域通過フィルタはスルーされます。
121     //!         初期値は 0.5f です。
122     //!
123     //!         m_Damping は後置残響音に対する LPF (ローパスフィルタ) のかかり具合を表します。
124     //!         0.0f ~ 1.0f で設定します。
125     //!         この値を大きくすればするほど、カットオフ周波数が下がっていきます。
126     //!         0.0f にすると、LPF はかかりません。
127     //!         初期値は 0.4f です。
128     //!
129     //!         m_pFilterSize の各メンバ変数については、@ref FilterSize の説明をご覧ください。
130     //!
131     //!         @ref GetRequiredMemSize で取得できる必要メモリサイズは、@n
132     //!         ・m_EarlyReflectionTime @n
133     //!         ・m_PreDelayTime @n
134     //!         ・m_pFilterSize @n
135     //!         に依存します。
136     //!
137     //!         エフェクト実行中に次の値を変更すると、ノイズがのる可能性があります。@n
138     //!         ・m_EarlyReflectionTime @n
139     //!         ・m_PreDelayTime
140     //!
141     //!         また、次の値はエフェクト実行中であっても、「連続的に」変化させる場合は、
142     //!         ノイズはのりません。@n
143     //!         ・m_FusedTime @n
144     //!         ・m_Coloration @n
145     //!         ・m_Damping @n
146     //!         ・m_EarlyGain @n
147     //!         ・m_FusedGain
148     //!
149     //!         エフェクト実行中にパラメータを変更する場合は、@ref SetParam を呼び出してください。
150     //!
151     //! @date 2010/10/20 初版
152     //---------------------------------------------------------------------------
153     struct Param
154     {
155         u32 m_EarlyReflectionTime;  //!< 初期反射時間 (msec) です。
156         u32 m_FusedTime;            //!< 後置残響音の減衰時間 (msec) です。
157         u32 m_PreDelayTime;         //!< 後置残響音のプリディレイ時間 (msec) です。
158         f32 m_Coloration;           //!< 後置残響音の全域通過フィルタの係数です。
159         f32 m_Damping;              //!< 後置残響音の LPF のかかり具合です。
160 
161         //! フィルタサイズです。NULL を指定すると、FilterSize 構造体の初期値値が設定されます。
162         FilterSize* m_pFilterSize;
163 
164         f32 m_EarlyGain;            //!< 初期反射音の出力ゲインです。
165         f32 m_FusedGain;            //!< 後置残響音の出力ゲインです。
166 
167         //---------------------------------------------------------------------------
168         //! @brief    コンストラクタです。
169         //!
170         //! @date 2010/10/20 初版
171         //---------------------------------------------------------------------------
ParamParam172         Param()
173         : m_EarlyReflectionTime( 60 ),  // msec
174           m_FusedTime( 4000 ),          // msec
175           m_PreDelayTime( 100 ),        // msec
176           m_Coloration( 0.5f ),
177           m_Damping( 0.4f ),
178           m_pFilterSize( &s_DefaultFilterSize ),
179           m_EarlyGain( 0.6f ),
180           m_FusedGain( 0.4f )
181         {}
182     };
183 
184     //----------------------------------------
185     //! @name コンストラクタ / デストラクタ
186     //@{
187     //---------------------------------------------------------------------------
188     //! @brief    コンストラクタです。
189     //!
190     //! @date 2010/10/20 初版
191     //---------------------------------------------------------------------------
192     FxReverb();
193 
194     //---------------------------------------------------------------------------
195     //! @brief    デストラクタです。
196     //!
197     //! @date 2010/10/20 初版
198     //---------------------------------------------------------------------------
199     virtual ~FxReverb();
200     //@}
201 
202     //----------------------------------------------------------------
203     /// @name   パラメータ設定/取得
204     //----------------------------------------------------------------
205     //@{
206     //---------------------------------------------------------------------------
207     //! @brief  リバーブパラメータを設定します。
208     //!
209     //!         @ref GetRequiredMemSize 関数は、
210     //!         ここで設定されたリバーブパラメータを元に必要なメモリサイズを計算します。
211     //!
212     //!         設定された @ref Param 構造体は、内部でコピーされます。
213     //!
214     //!         @ref SetEffect を呼び出して
215     //!         FxReverb インスタンスを渡す前と後で挙動が変わります。
216     //!
217     //!         @ref SetEffect 呼び出し前は、
218     //!         @ref Param 構造体のうち、m_Coloration, m_Damping, m_EarlyGain,
219     //!         m_FusedGain の範囲チェックが行われます。
220     //!         範囲外の場合は、Debug / Development 版ではアサートで停止し、
221     //!         Release 版では false を返します。
222     //!
223     //!         @ref SetEffect 呼び出し後は、
224     //!         呼び出し前に行われる範囲チェックに加え、
225     //!         必要メモリサイズが増えるかどうかのチェックが行われます。
226     //!         すなわち、@n
227     //!         ・m_EarlyReflection に @ref SetEffect が呼び出された時より大きな値を設定する @n
228     //!         ・m_PreDelay に @ref SetEffect が呼び出された時より大きな値を設定する @n
229     //!         ・m_pFilterSize の各メンバには
230     //!           @ref SetEffect が呼び出された時より大きな値を設定する @n
231     //!         のような操作をした場合、本関数は失敗し false を返します。
232     //!         上記の条件を満たさない場合は、
233     //!         @ref SetEffect 以降でもパラメータの変更が可能です。
234     //!
235     //! @param[in] param  リバーブパラメータです。
236     //!
237     //! @return   設定に成功すると true を、失敗 (範囲外の値を設定するなど) した場合は
238     //!           false を返します。
239     //!
240     //! @see GetRequiredMemSize
241     //! @see GetParam
242     //!
243     //! @date 2010/11/04 関数名誤記修正 (Initialize → SetEffect)
244     //! @date 2010/10/20 初版
245     //---------------------------------------------------------------------------
246     bool SetParam( const Param& param );
247 
248     //---------------------------------------------------------------------------
249     //! @brief  リバーブパラメータを取得します。
250     //!
251     //! @return   現在のリバーブパラメータを返します。
252     //!
253     //! @see SetParam
254     //!
255     //! @date 2010/10/20 初版
256     //---------------------------------------------------------------------------
GetParam()257     const Param& GetParam() const
258     {
259         return m_Param;
260     }
261     //@}
262 
263     //----------------------------------------
264     //! @name メモリ割り当て
265     //@{
266 
267     //---------------------------------------------------------------------------
268     //! @brief    エフェクトに必要なメモリサイズを取得します。
269     //!
270     //!           あらかじめ @ref SetParam 関数で、
271     //!           リバーブパラメータを設定しておく必要があります。
272     //!
273     //! @return   リバーブエフェクトに必要なメモリサイズを返します。
274     //!
275     //! @see AssignWorkBuffer
276     //!
277     //! @date 2010/10/20 初版
278     //---------------------------------------------------------------------------
279     size_t GetRequiredMemSize();
280 
281     //---------------------------------------------------------------------------
282     //! @brief    エフェクトで使用するメモリ領域を割り当てます。
283     //!
284     //!           メモリ領域の割り当ては、エフェクトを
285     //!           @ref SetEffect 関数で追加する前に行う必要があります。
286     //!
287     //!           エフェクトが必要とするバッファサイズは、パラメータの値によって変化しますので、
288     //!           @ref GetRequiredMemSize を呼び出して、必要なメモリサイズを取得してください。
289     //!
290     //! @param[in] buffer 割り当てるメモリの先頭アドレスです。
291     //! @param[in] size   割り当てるメモリのサイズです。
292     //!
293     //! @return   メモリ領域の割り当てに成功すると true を、
294     //!           失敗すると false を返します。
295     //!
296     //! @see GetRequiredMemSize
297     //! @see ReleaseWorkBuffer
298     //! @see SetEffect
299     //!
300     //! @date 2010/10/20 初版
301     //---------------------------------------------------------------------------
302     bool AssignWorkBuffer( uptr buffer, size_t size );
303 
304     //---------------------------------------------------------------------------
305     //! @brief    エフェクトで使用していたメモリ領域を解放します。
306     //!
307     //!           この関数で解放を行う前に、@ref SoundSystem::ClearEffect
308     //!           関数でエフェクトを削除しておく必要があります。
309     //!
310     //! @see AssignWorkBuffer
311     //! @see SoundSystem::ClearEffect
312     //!
313     //! @date 2010/11/04 誤植修正 (開放→解放)
314     //! @date 2010/10/20 初版
315     //---------------------------------------------------------------------------
316     void ReleaseWorkBuffer();
317     //@}
318 
319     /*! :private */
320     bool Initialize();
321 
322     /*! :private */
323     void Finalize();
324 
325     /*! :private */
326     void UpdateBuffer( uptr data );
327 
328 private:
329     struct WorkBuffer
330     {
331         s32*  m_EarlyReflection[4]; // 初期反射用
332         s32*  m_PreDelay[4];        // プリディレイ用
333         s32*  m_CombFilter[4][2];   // くし型フィルタ用(2段)
334         s32*  m_AllPassFilter[4];   // 全域通過フィルタ用(1段)
335         s32   m_Lpf[4];             // LPF用
336     };
337 
338     static FilterSize s_DefaultFilterSize;
339 
340     void AllocBuffer();
341     void FreeBuffer();
342 
343     void InitializeParam();
344 
345     Param           m_Param;
346     uptr            m_pBuffer;
347     size_t          m_BufferSize;
348     FilterSize      m_FilterSize;
349     WorkBuffer      m_WorkBuffer;
350 
351     s32  m_EarlyLength;
352     s32  m_EarlyPos;
353 
354     s32  m_PreDelayLength;
355     s32  m_PreDelayPos;
356 
357     s32  m_CombFilterLength[2];
358     s32  m_CombFilterPos[2];
359     s32  m_CombFilterCoef[2];
360 
361     s32  m_AllPassFilterLength;
362     s32  m_AllPassFilterPos;
363     s32  m_AllPassFilterCoef;
364 
365     s32  m_LastLpfOut[4];
366 
367 
368     // 以下のパラメータは、InitializeParam() で算出されるように変更
369     s32 m_EarlyGain;
370     s32 m_FusedGain;
371     s32 m_LpfCoef1;
372     s32 m_LpfCoef2;
373 
374     u32 m_EarlyReflectionTimeAtInitialize;
375     u32 m_PreDelayTimeAtInitialize;
376     FilterSize m_FilterSizeAtInitialize;
377 
378     bool m_IsActive;
379 
380     NN_PADDING3;
381 };
382 
383 }}} // namespace nn::snd::CTR
384 
385 #endif // __cplusplus
386 
387 #endif /* NN_SND_FX_REVERB_H_ */
388 
389