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