1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     snd_HardwareChannel.cpp
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: 31311 $
16  *---------------------------------------------------------------------------*/
17 
18 #include "precompiled.h"
19 #include <nw/snd/snd_HardwareChannel.h>
20 
21 #include <cstring>
22 #include <nw/snd/snd_HardwareManager.h>
23 #include <nw/snd/snd_HardwareChannelManager.h>
24 
25 #include NW_SND_ADAPTIVE_SOURCE( HardwareChannel )
26 
27 namespace nw {
28 namespace snd {
29 namespace internal {
30 namespace driver {
31 
32 /* ========================================================================
33         static function
34    ======================================================================== */
35 
CalcOffsetDspAdpcmParam(u16 * outPredScale,u16 * outYn1,u16 * outYn2,u32 offset,const void * dataAddr,const DspAdpcmParam & adpcmParam)36 void HardwareChannel::CalcOffsetDspAdpcmParam(
37     u16* outPredScale,
38     u16* outYn1,
39     u16* outYn2,
40     u32 offset,
41     const void* dataAddr,
42     const DspAdpcmParam& adpcmParam
43 )
44 {
45     DspAdpcmParameterBlock adpcm;
46     std::memcpy( adpcm.a, adpcmParam.coef, sizeof(u16)*16 );
47     adpcm.gain = 0; // adpcmParam.gain;
48     adpcm.predScale = adpcmParam.predScale;
49     adpcm.yn1 = adpcmParam.yn1;
50     adpcm.yn2 = adpcmParam.yn2;
51 
52     DspAddress currentPos = GetDspAddressBySample( dataAddr, 0, SAMPLE_FORMAT_DSP_ADPCM );
53     DspAddress endPos = GetDspAddressBySample( dataAddr, offset, SAMPLE_FORMAT_DSP_ADPCM );
54 
55     while ( currentPos < endPos )
56     {
57         // 8バイトごとのpred scaleを読み取る
58         if ( ! (currentPos & 0xf) )
59         {
60             u8 byte = *reinterpret_cast<u8*>( OS_PhysicalToCached( currentPos >> 1 ) );
61             adpcm.predScale = (u16)byte;
62 
63             currentPos += 2;
64         }
65 
66         u8 byte = *reinterpret_cast<u8*>( OS_PhysicalToCached( currentPos >> 1 ) );
67         u8 nibble;
68         if ( currentPos & 0x1 )
69         {
70             nibble = static_cast<u8>( byte & 0xf );
71         }
72         else
73         {
74             nibble = static_cast<u8>( byte >> 4 );
75         }
76 
77 #ifdef NW_PLATFORM_CTRWIN
78         AX_DecodeDspAdpcm( &adpcm, nibble );
79 #else
80         nn::dspsnd::CTR::Dspsnd::DecodeAdpcmNibble(
81                 reinterpret_cast<nn::dspsnd::CTR::DspsndAdpcmState*>(&adpcm),
82                 nibble );
83 #endif
84 
85         currentPos++;
86     }
87 
88     *outPredScale = adpcm.predScale;
89     *outYn1 = adpcm.yn1;
90     *outYn2 = adpcm.yn2;
91 }
92 
93 
94 
95 /* ========================================================================
96         member function
97    ======================================================================== */
HardwareChannel()98 HardwareChannel::HardwareChannel()
99 : m_pWaveData( NULL ),
100   m_IsReserveForFree( false ),
101   m_Callback( NULL ),
102   m_pCallbackData( NULL )
103 {
104     Initialize();
105 }
106 
~HardwareChannel()107 HardwareChannel::~HardwareChannel()
108 {
109 }
110 
111 
ClearParamBlock()112 void HardwareChannel::ClearParamBlock()
113 {
114     m_pVpb = NULL;
115     m_SyncFlag = 0;
116 }
117 
Initialize(const void * waveAddr,SampleFormat format,int sampleRate)118 void HardwareChannel::Initialize( const void* waveAddr, SampleFormat format, int sampleRate )
119 {
120     m_pWaveData = waveAddr;
121     m_Format = format;
122     m_SampleRate = sampleRate;
123 
124     OnInitialize();
125 }
126 
127 
128 
SetLoopStart(const void * baseAddress,u32 samples)129 void HardwareChannel::SetLoopStart( const void* baseAddress, u32 samples )
130 {
131     if ( ! IsAvailable() ) return;
132 
133     DspAddress dspAddress = GetDspAddressBySample(
134         baseAddress,
135         samples,
136         m_Format
137     );
138 
139     SetVoiceLoopAddr( dspAddress );
140 }
141 
SetLoopEnd(const void * baseAddress,u32 samples)142 void HardwareChannel::SetLoopEnd( const void* baseAddress, u32 samples )
143 {
144     if ( ! IsAvailable() ) return;
145 
146     DspAddress dspAddress = GetDspAddressBySample(
147         baseAddress,
148         samples-1,
149         m_Format
150     );
151 
152     SetVoiceEndAddr( dspAddress );
153 }
154 
IsDataAddressCovered(const void * begin,const void * end) const155 bool HardwareChannel::IsDataAddressCovered(
156         const void* begin, const void* end ) const
157 {
158     if ( ! IsAvailable() ) { return false; }
159 
160     if ( m_pWaveData == NULL ) { return false; }
161 
162     if ( begin <= m_pWaveData && m_pWaveData <= end )
163     {
164         return true;
165     }
166     else
167     {
168         return false;
169     }
170 }
171 
172 
SetLpf(u16)173 void HardwareChannel::SetLpf( u16 /*freq*/ ) {} // TODO:
SetBiquad(u8,f32)174 void HardwareChannel::SetBiquad( u8 /*filterType*/, f32 /*value*/ ) {} // TODO:
175 
SetPriority(u32)176 void HardwareChannel::SetPriority( u32 /*priority*/ ) {} // TODO:
177 
178 
ChannelCallback(void * callbackData)179 void HardwareChannel::ChannelCallback( void* callbackData )
180 {
181     ParameterBlock* dropVpb = reinterpret_cast<ParameterBlock*>( callbackData );
182     HardwareChannel* pChannel = reinterpret_cast<HardwareChannel*>( dropVpb->userContext );
183     NW_NULL_ASSERT( pChannel );
184 
185     pChannel->ClearParamBlock();
186 
187     // 解放処理に時間がかかるので、割り込み禁止期間が延びないように
188     // 後で処理を行うようにする。
189     HardwareChannelManager::GetInstance().ReserveForFreeHardwareChannel( pChannel );
190 }
191 
192 
193 
194 } // namespace nw::snd::internal::driver
195 } // namespace nw::snd::internal
196 } // namespace nw::snd
197 } // namespace nw
198