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