/*--------------------------------------------------------------------------
  Project:  Manual 2D Library - m2d
  File:     soundManager.h

  Copyright (C)2007-2009 Nintendo  All Rights Reserved.

  These coded instructions, statements, and computer programs contain
  proprietary information of Nintendo of America Inc. and/or Nintendo
  Company Ltd., and are protected by Federal copyright law. They may
  not be disclosed to third parties or copied or duplicated in any form,
  in whole or in part, without the prior written consent of Nintendo.

  $Revision: 1758 $
 *-------------------------------------------------------------------------*/

#ifndef NTMV_M2D_SOUNDMANAGER_H_
#define NTMV_M2D_SOUNDMANAGER_H_

#if defined(__CWCC__)
#pragma once
#endif

#include <nnsys/snd.h>

/*!
  Macros
 */
#define Assigned(i) ( (static_cast<void *>(i)) != 0 )
#define Tr(i)       ( 1 << i )  /* track bit */
    
namespace ntmv
{
namespace m2d
{

/*!
  Structure typedef
 */
typedef struct tagSSeInfo
{
        NNSSndHandle sndHandle;
        int          seNo;
        BOOL         holdSeFlag; /* Is the sound effect held? */
        BOOL         holdSeUpdateFlag; /* Is the held sound effect called every frame? */
        s32          posX;
        s32          posY;
}SSeInfo;

typedef struct tagSBgmInfo
{
        NNSSndHandle sndHandle;
        int          bgmNo;
        int          pitch;
}SBgmInfo;


// Callback base class
class SoundManager;
class CallbackBase
{
  public:
    virtual ~CallbackBase();
    // Methods that contain callbacks
    virtual void update();
    virtual void startSe( int seNo );
    virtual void setScrollSpec( SoundManager* sndmgr_p, int speed, u32 objId );
};


// Sound manager class
class SoundManager
{
  protected:
    const static u32 MAXCT_SE          = 16; /* Number of sound effects that can play at once */
    const static u32 MAXCT_BGM         = 1;  /* Number of background music tracks that can play at once */
    const static u32 CTFRAME_SE_STOP   = 0; /* Frames until a sound effect is stopped */
    const static u32 CTFRAME_BGM_STOP  = 30; /* Frames until the background music is stopped */
    const static u32 SEQ_ARC_NO        = 0; /* Sequence archive number (fixed at 0) */
    const static int WAVE_OUT_CH       = 7; /* Channel for wave playback */

  public:
    SoundManager();
    ~SoundManager();

    void init( u8* p_arg );
    void update();
    void setCallback( CallbackBase* p_cb ) { mpCallback = p_cb; }

    // Starting and stopping sound effects
    NNSSndHandle* startSe( int seNo, int posX = 128 );
    NNSSndHandle* startSeWithPitch( int seNo, int posX = 128 );
    NNSSndHandle* startSeWithVol( int seNo, int vol = 127 );
    NNSSndHandle* startMultiSe( int seNo, int posX = 128 );
    NNSSndHandle* startScrollSe( int seNo, int speed, u32 objId = 0 );
    NNSSndHandle* holdSe( int seNo, int posX = 128 );
    NNSSndHandle* holdSeWithPos( int seNo, int posX, int posY );
    NNSSndHandle* holdSeWithDis( int seNo, int distance, int posX = 128 );
    NNSSndHandle* holdSeWithDot( int seNo, int dot, int posX = 128 );
    NNSSndHandle* holdSeWithSweep( int seNo, int percent = 0, int posX = 128 );
    void stopSe( NNSSndHandle* sndHandle, int fadeFrame = CTFRAME_SE_STOP );
    void stopSe( int seNo, int fadeFrame = CTFRAME_SE_STOP );

    // Starting and stopping background music
    BOOL startBgm( int bgmNo );
    void stopBgm( int fadeFrame = CTFRAME_BGM_STOP );

    // Waveform playback
    void playWave( const void* waveBuf, int sampleNum );

    NNSSndArc getSndArc() { return mArc; }

    BOOL isSeActive( int seNo );
    BOOL isBgmActive();

    s32 abs_S32( s32 aa );                         /* Gets the absolute value */
    s32 cutGELE_S32( s32 val, s32 from, s32 to );  /* Truncates a value */

  private:
    BOOL mInitialized;
    CallbackBase* mpCallback;

    u32 mMaxSeNum;
    u32 mMaxBgmNum;

    NNSSndArc mArc;
    NNSSndWaveOutHandle mWaveOutHandle;

    SSeInfo  mSeInfo[ MAXCT_SE ];
    SBgmInfo mBgmInfo;

    struct SSeInfo* FIsSeActive( int seNo );
    struct SSeInfo* FGetFreeSeBlock( BOOL isForce );

    void FChangeBgmTrackPitch( u16 trackBit, int pitch );

    s32 mSeBlk;
    s32 clipGELT_S32( s32 val, s32 from, s32 to ); /* Rotates numbers between "from" and "to" */
    BOOL checkRangeGELT_S32( s32 val, s32 min, s32 max ); /* Checks whether a value is confined to a range */
};


}   // namespace m2d
}   // namespace ntmv

/* NTMV_M2D_SOUNDMANAGER_H_ */
#endif
