1 /*---------------------------------------------------------------------------*
2   Project:  Horizon
3   File:     snd_Voice.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: 25765 $
14  *---------------------------------------------------------------------------*/
15 
16 #ifndef NN_SND_VOICE_H_
17 #define NN_SND_VOICE_H_
18 
19 #include <nn/os.h>
20 #include <nn/Result.h>
21 
22 #include <nn/snd/CTR/Common/snd_Types.h>
23 
24 #ifdef __cplusplus
25 
26 /*! @file
27     @brief      Voice に関する関数、およびクラス定義
28 */
29 
30 namespace nn  { namespace snd { namespace CTR {
31 
32 /*!
33     @brief      ライブラリがボイスを解放する際に呼び出すコールバック関数の型定義です。
34     @param[in]  pVoice          解放したボイスオブジェクトへの参照
35     @param[in]  userArg         ユーザーパラメータ
36 */
37 typedef void (*VoiceDropCallbackFunc)(class Voice *, uptr userArg);
38 
39 class VoiceManager;
40 
41 /*!
42     @brief      Voice を操作するクラスです。
43  */
44 class Voice
45 {
46     friend class VoiceManager;
47 
48 public:
49 
50     /*!
51         @brief      ボイスの状態を表す列挙型です。
52      */
53     enum State
54     {
55         STATE_PLAY,  //!< 再生指令状態を表します。
56         STATE_STOP,  //!< 停止状態を表します。
57         STATE_PAUSE  //!< 一時停止状態を表します。再生を再開する際は、SetState により再生状態を設定して下さい。
58     };
59 
60 private:
61     const s32                m_Id;                  // ボイス番号(管理用)
62     s16                      m_SyncCount;           // DSP との同期カウンタ(管理用)
63     u16                      m_bufferId;
64     s32                      m_PlayPosition;        // 再生位置
65 
66     bool                     m_Playing;             // 実際に再生されてるかどうか
67     State                    m_State;               // 状態
68     InterpolationType        m_InterpolationType;   // 補間方法
69 
70     FilterType               m_iirType;             // フィルタタイプ
71     MonoFilterCoefficients   m_monoFilterCoeffs;    // 単極フィルタ係数
72     BiquadFilterCoefficients m_biquadFilterCoeffs;  // 双極フィルタ係数
73 
74     u16                      m_SampleInfo;          // ChannelCount と SampleFormat をまとめた情報
75 
76     s32                      m_SampleRate;          // 標本化周波数
77     f32                      m_Pitch;               // ピッチ(SampleRate に対する比)
78 
79     u32                      m_DspCycles;           // DSP で消費されるサイクル数
80     s32                      m_Priority;            // 優先度
81     Voice *                  m_PriorVoice;          // 優先度が高い Voice へのポインタ
82     Voice *                  m_InferiorVoice;       // 優先度が低い Voice へのポインタ
83 
84     VoiceDropCallbackFunc    m_Callback;            // Voice がシステムにより解放された場合に呼び出されるコールバック関数
85     uptr                     m_UserArg;             // 上記コールバック呼び出し時のユーザ引数
86 
87     WaveBuffer *             m_pWaveBuffer;         // 音源データ情報の先頭
88 
89     WaveBuffer *             m_pNextBuffer[NN_SND_NEXT_BUFFER_NUM];
90 
91     s32                      m_SentBufferCount;     // 登録されているバッファの数
92     s32                      m_NextBufferIndex;     // NextBuffer のインデクス
93 
94     MixParam                 m_MixParam;            // 各チャンネルへのゲイン
95     f32                      m_Volume;              // ボリューム
96 
97     bit16                    m_ModifiedParamFlag;   // 変更があったパラメータを表すフラグ
98 
99     bool                     m_IsFirstWaveBufferForAdpcm;  // ADPCM 係数がセットされたかどうか
100     NN_PADDING1;
101 
102     /*! :private
103         @brief      Voice の初期化を行います。
104      */
105     void Initialize(void);
106 
107     /*! :private
108         @brief      バッファの状態を更新します。
109         @param[in]  bufferId    再生中のバッファ ID
110      */
111     void UpdateWaveBufferStatus( const u16 bufferId );
112 
113     /*! :private
114         @brief      バッファの登録を行います。
115      */
116     void SendWaveBuffer( void );
117 
118     /*! :private
119         @brief      バッファの解放を行います。
120      */
121     void ReleaseWaveBuffer( void ) ;
122 
123     /*! :private
124         @brief      再生します。
125      */
126     void Start      ( void );
127 
128     /*! :private
129         @brief      停止し、バッファの解放を行います。
130      */
131     void Stop      ( void ) ;
132 
133     /*! :private
134         @brief      停止します。
135      */
136     void Pause      ( void ) const ;
137 
138     /*! :private
139         @brief      サイクルを取得します。
140         @return     サイクル数を返します。
141      */
142     s32 GetCycle( void ) const ;
143 
144     /*! :private
145         @brief      DSP でのサイクル数を計算します。
146         @return     なし。
147      */
148     void CalculateDspCycle( void ) ;
149 
150     /*! :private
151         @brief      タイマー値を設定します。アプリからは直接呼び出すことはできません。
152      */
153     void SetTimer( void );
154 
155     /*! :private
156         @brief      ボリューム値を設定します。アプリからは直接呼び出すことはできません。
157      */
158     void SetMixVolume( void );
159 
160     /*! :private
161         @brief      同期カウントを設定します。
162      */
163     void SetSyncCount ( void ) ;
164 
165     /*! :private
166         @brief      ハードウェアのサンプリング周波数に対する比を計算する。
167         @return     ハードウェアの周波数に対する比。
168      */
169     f32 CalcFsRatio ( void ) const;
170 
171     /*! :private
172         @brief      タイマー値を計算。
173         @return     タイマー値。
174      */
175     u32 CalcTimer( void ) const;
176 
177     /*! :private
178         @brief      ポリフェイズフィルタの係数を選択する。
179         @return     係数値を返します。
180      */
181     u16 SelectCoefficient( void );
182 
183     void UpdateInterpolationType(void);
184 
185 public:
186     /*!
187         @brief      コンストラクタです。
188         @param[in]  id          ボイスの ID
189     */
190     Voice(s32 id);
191 
192     /*!
193         @brief      デストラクタです。
194      */
195     ~Voice();
196 
197     /*!
198         @brief      ボイスのチャンネル数を設定します。
199         @param[in]  channelCount    チャンネル数
200      */
201     void SetChannelCount( s32 channelCount );
202 
203     /*!
204         @brief      ボイスにリンクされるサンプルの形式を設定します。
205         @param[in]  format      サンプルの形式
206      */
207     void SetSampleFormat( SampleFormat format );
208 
209     /*!
210         @brief      3D サラウンドが有効な場合に、フロントチャンネルをバイパスするかを設定します。
211         @param[in]  flag        true ならフロントバイパス、false ならフロントにも 3D サラウンドを適用
212      */
213     void SetFrontBypassFlag(bool flag);
214 
215     /*!
216         @brief      再生開始時にボリューム 0 からの短いフェードインを用いるかどうかを指定します。
217         @param[in]  flag        On/Off フラグ
218      */
219     void SetStartFrameFadeInFlag(bool flag);
220 
221     /*!
222         @brief      ボイスのサンプリングレートを設定します。
223         @param[in]  sampleRate  サンプリングレート
224     */
225     void SetSampleRate  ( s32 sampleRate );
226 
227     /*!
228         @brief      ボイスのピッチを設定します。
229         @param[in]  pitch       サンプリングレートに対する再生速度比
230      */
231     void SetPitch   ( f32 pitch );
232 
233     /*!
234         @brief      ボイスのピッチを取得します。
235         @return     ピッチを返します。
236      */
237     f32 GetPitch ( void ) const ;
238 
239     /*!
240         @brief      Adpcm の係数を設定します。
241         @param[in]  param Adpcm 係数構造体への参照
242      */
243     void SetAdpcmParam  ( const AdpcmParam& param );
244 
245     /*!
246         @brief      ボイスの優先度を設定します。
247         @param[in]  priority    優先度
248      */
249     void SetPriority    ( s32 priority );
250 
251     /*!
252         @brief      ボイスの優先度を取得します。
253         @return     優先度を返します。
254      */
255     s32 GetPriority( void ) const ;
256 
257     /*!
258         @brief      ボイスに対してサンプルデータ情報を追加します。
259         @param[in]  buffer      バッファ情報構造体のポインタ
260      */
261     void AppendWaveBuffer ( WaveBuffer * buffer);
262 
263     /*! :private
264         @brief      DSP からの戻り値に基づき、Voice の状態を更新します。
265         @param[in]  pVars       ステータス構造体のポインタ
266      */
267     void UpdateStatus( const void * pVars );
268 
269     /*! :private
270         @brief      バッファリストを更新します。
271      */
272     void UpdateWaveBufferList ( void );
273 
274     /*!
275         @brief      ボイスの状態を設定します。
276         @param[in]  state       状態
277      */
278     void SetState( State state );
279 
280     /*!
281         @brief      ボイスの状態を取得します。
282         @return     状態を返します。
283      */
284     Voice::State GetState( void ) const ;
285 
286     /*!
287         @brief      ボイスの各チャンネルのゲインを設定します。
288         @param[in]  mixParam    ゲイン構造体への参照
289      */
290     void SetMixParam( const MixParam& mixParam );
291 
292     /*!
293         @brief      ボイスの各チャンネルのゲインを取得します。
294         @return     ゲイン構造体への参照を返します。
295      */
296     const MixParam & GetMixParam( void ) const ;
297 
298     /*!
299         @brief      ボイスのボリュームを設定します。
300         @param[in]  volume      ボリューム値
301      */
302     void SetVolume( f32 volume );
303 
304     /*!
305         @brief      ボイスのボリュームを取得します。
306         @return     ボリューム値を返します。
307      */
308     f32 GetVolume( void ) const ;
309 
310     /*!
311         @brief      使用中のバッファ内での再生位置を取得します。
312         @return     再生位置をサンプル数で返します。
313      */
314     s32 GetPlayPosition( void ) const ;
315 
316     /*! :private
317         @brief      ボイスの ID を取得します。
318         @return     ボイスの ID を返します。
319      */
320     s32  GetId    ( void ) const ;
321 
322     /*!
323         @brief      ボイスの再生状態を取得します。
324         @return     ボイスの再生状態を返します。
325      */
326     bool  IsPlaying ( void ) const ;
327 
328     /*!
329         @brief      ボイスの補間方法を設定します。
330         @param[in]  type        補間方法
331      */
332     void SetInterpolationType( InterpolationType type );
333 
334     /*!
335         @brief      ボイスの補間方法を取得します。
336         @return     現在の補間方法を返します。
337      */
338     InterpolationType GetInterpolationType() const;
339 
340     /*!
341         @brief      フィルタタイプを設定します。
342         @param[in]  type        フィルタタイプ
343      */
344     void SetFilterType(FilterType type);
345 
346     /*!
347         @brief      フィルタの使用状況を取得します。
348         @return     フィルタタイプ。
349      */
350     FilterType GetFilterType(void) const;
351 
352     /*! :overload   coef
353         @brief      単極フィルタの係数を設定します。
354         @param[in]  pCoeff      係数バッファ
355      */
356     void SetMonoFilterCoefficients(MonoFilterCoefficients* pCoeff);
357 
358     /*! :overload   freq
359         @brief      指定したカットオフ周波数を持つ、単極ローパスフィルタを設定します。
360         @param[in]  cutoff      カットオフ周波数 (0 <= cutoff <= 16000)
361      */
362     void SetMonoFilterCoefficients(u16 cutoff);
363 
364     /*!
365         @brief      単極フィルタの係数を取得します。
366         @param[out] pCoeff      係数バッファ
367      */
368     void GetMonoFilterCoefficients(MonoFilterCoefficients* pCoeff);
369 
370     /*!
371         @brief      双極フィルタの係数を設定します。
372         @param[in]  pCoeff      係数バッファ
373      */
374     void SetBiquadFilterCoefficients(BiquadFilterCoefficients* pCoeff);
375 
376     /*!
377         @brief      双極フィルタの係数を取得します。
378         @param[out] pCoeff      係数バッファ
379      */
380     void GetBiquadFilterCoefficients(BiquadFilterCoefficients* pCoeff);
381 
382     /*! :private
383         @brief      パラメータを DSP に反映します。
384      */
385     void UpdateParams(void);
386 
387     /*! :private
388         @brief      パラメータを強制的に DSP に反映します。
389      */
390     void ForceUpdateParams(void);
391 
392     /*!
393         @brief      Bcwav ファイルを解釈し、再生準備を行います。
394         @param[in]  addrBcwav      Bcwav ファイルの先頭アドレス
395         @param[in]  pWaveBuffer0   初回再生時に使用する nn::snd::WaveBuffer へのポインタ
396         @param[in]  pWaveBuffer1   ループ再生時に使用する nn::snd::WaveBuffer へのポインタ
397         @param[in]  channelIndex   使用するチャンネル
398         @return     成功なら true, 失敗なら false を返します。
399      */
400     bool SetupBcwav(uptr addrBcwav, WaveBuffer* pWaveBuffer0, WaveBuffer* pWaveBuffer1, Bcwav::ChannelIndex channelIndex = Bcwav::CHANNEL_INDEX_L);
401 
402 }; // class Voice
403 
404 //--------------------------------
405 // inline 関数
406 //--------------------------------
407 // 優先度を取得。
GetPriority(void)408 inline s32 Voice::GetPriority( void ) const
409 {
410     return m_Priority;
411 }
412 // 状態を取得。
GetState(void)413 inline Voice::State Voice::GetState( void ) const
414 {
415     return m_State;
416 }
417 // ピッチを取得。
GetPitch(void)418 inline f32 Voice::GetPitch( void ) const
419 {
420     return m_Pitch;
421 }
422 // ゲインへの参照を取得。
GetMixParam(void)423 inline const MixParam& Voice::GetMixParam( void ) const
424 {
425     return m_MixParam;
426 }
427 // ボリュームを取得。
GetVolume(void)428 inline f32 Voice::GetVolume (void ) const
429 {
430     return m_Volume;
431 }
432 // 優先度を取得。
GetId(void)433 inline s32 Voice::GetId ( void ) const
434 {
435     return m_Id;
436 }
437 // 再生状態を取得。
IsPlaying(void)438 inline bool Voice::IsPlaying ( void ) const
439 {
440     return m_Playing;
441 }
442 // 補間方法を取得。
GetInterpolationType(void)443 inline InterpolationType Voice::GetInterpolationType ( void ) const
444 {
445     return m_InterpolationType;
446 }
447 // ベース周波数に対する再生周波数の比を計算する。
CalcFsRatio(void)448 inline f32 Voice::CalcFsRatio( void ) const
449 {
450     return (m_SampleRate * m_Pitch) / NN_SND_HW_I2S_CLOCK_32KHZ_F32;
451 }
452 // タイマー値を計算。
CalcTimer(void)453 inline u32 Voice::CalcTimer( void ) const
454 {
455     return static_cast<u32>(CalcFsRatio() * NN_SND_TIMER_EQUIV);
456 }
457 
458 /*!
459     @brief      ボイスを取得します。
460     @param[in]  priority 優先順位
461     @param[in]  callback コールバック関数のアドレス
462     @param[in]  userArg ユーザ引数
463     @return     成功した場合、Voice オブジェクトのアドレスを返します。失敗した場合、NULL を返します。
464  */
465 Voice* AllocVoice( s32 priority, VoiceDropCallbackFunc callback, uptr userArg );
466 
467 /*!
468     @brief      ボイスを解放します。
469     @param[in]  pVoice ボイスオブジェクトのアドレス。
470  */
471 void   FreeVoice ( Voice * pVoice );
472 
473 }}} // namespace nn::snd::CTR
474 
475 #endif // __cplusplus
476 
477 #endif //NN_SND_VOICE_H_
478