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