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