1 /*---------------------------------------------------------------------------*
2 Project: NintendoWare
3 File: snd_HardwareChannelManager.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: 19566 $
14 *---------------------------------------------------------------------------*/
15
16 #include "precompiled.h"
17 #include <nw/snd/snd_HardwareChannelManager.h>
18 #include <nw/snd/snd_HardwareChannel.h>
19
20 #include <new>
21
22 #include NW_SND_ADAPTIVE_SOURCE( HardwareChannelManager )
23
24 namespace nw {
25 namespace snd {
26 namespace internal {
27 namespace driver {
28
GetInstance()29 HardwareChannelManager& HardwareChannelManager::GetInstance()
30 {
31 static HardwareChannelManager instance;
32 return instance;
33 }
34
HardwareChannelManager()35 HardwareChannelManager::HardwareChannelManager()
36 : m_IsInitialized( false )
37 {
38 }
39
GetRequiredMemSize(int hardwareChannelCount)40 unsigned long HardwareChannelManager::GetRequiredMemSize( int hardwareChannelCount )
41 {
42 return sizeof( HardwareChannel )
43 * ( hardwareChannelCount + CHANNEL_COUNT_MARGIN );
44 }
45
Initialize(void * mem,unsigned long memSize)46 void HardwareChannelManager::Initialize( void* mem, unsigned long memSize )
47 {
48 if ( m_IsInitialized ) return;
49
50 OnInitialize();
51
52 m_HardwareChannelCount = static_cast<int>( memSize / sizeof( HardwareChannel ) );
53
54 u8* ptr = reinterpret_cast<u8*>( mem );
55
56 for ( int i = 0; i < m_HardwareChannelCount; i++ )
57 {
58 m_FreeList.PushBack( new( ptr ) HardwareChannel() );
59 ptr += sizeof( HardwareChannel );
60 }
61 NW_ASSERT( ptr <= reinterpret_cast<u8*>( mem ) + memSize );
62 m_IsInitialized = true;
63
64 return;
65 }
66
Finalize()67 void HardwareChannelManager::Finalize()
68 {
69 if ( ! m_IsInitialized ) return;
70
71 // 全てのボイスを止める
72 while ( ! m_ActiveList.IsEmpty() )
73 {
74 HardwareChannel& channel = m_ActiveList.GetFront();
75 m_ActiveList.PopFront();
76 if ( channel.IsAvailable() )
77 {
78 channel.Stop();
79 if ( channel.m_Callback != NULL )
80 {
81 channel.m_Callback(
82 &channel,
83 HardwareChannel::CALLBACK_STATUS_CANCEL,
84 channel.m_pCallbackData
85 );
86 }
87 FreeHardwareChannel( &channel );
88 }
89 }
90
91 // TODO: コード整理(コードの重複)
92 while ( ! m_FreeReservedList.IsEmpty() )
93 {
94 HardwareChannel& channel = m_FreeReservedList.GetFront();
95 m_ActiveList.PopFront();
96 if ( channel.IsAvailable() )
97 {
98 channel.Stop();
99 if ( channel.m_Callback != NULL )
100 {
101 channel.m_Callback(
102 &channel,
103 HardwareChannel::CALLBACK_STATUS_CANCEL,
104 channel.m_pCallbackData
105 );
106 }
107 FreeHardwareChannel( &channel );
108 }
109 }
110
111 // ボイスをリストから削除
112 while ( ! m_FreeList.IsEmpty() )
113 {
114 HardwareChannel& voice = m_FreeList.GetFront();
115 m_FreeList.PopFront();
116 voice.~HardwareChannel(); // デストラクタ呼び出し
117 }
118
119 m_IsInitialized = false;
120 }
121
ReserveForFreeHardwareChannel(HardwareChannel * pChannel)122 void HardwareChannelManager::ReserveForFreeHardwareChannel( HardwareChannel* pChannel )
123 {
124 NW_NULL_ASSERT( pChannel );
125 pChannel->m_IsReserveForFree = true;
126 ReserveForFree( pChannel );
127 }
128
FreeAllReservedHardwareChannel()129 void HardwareChannelManager::FreeAllReservedHardwareChannel()
130 {
131 while ( !m_FreeReservedList.IsEmpty() )
132 {
133 HardwareChannel& channel = m_FreeReservedList.GetFront();
134
135 if ( channel.m_Callback != NULL )
136 {
137 channel.m_Callback(
138 &channel,
139 HardwareChannel::CALLBACK_STATUS_DROP_DSP,
140 channel.m_pCallbackData
141 );
142 }
143
144 HardwareChannelManager::GetInstance().FreeHardwareChannel( &channel );
145 }
146 }
147
148 // TODO-continue: アロックできない
Alloc()149 HardwareChannel* HardwareChannelManager::Alloc()
150 {
151 // HardwareChannel インスタンスの枯渇をさけるため、
152 // 解放予約ボイスの解放処理を行う
153 // 割り込み禁止期間が長くなるが、やむを得ない
154 FreeAllReservedHardwareChannel();
155
156 if ( m_FreeList.IsEmpty() )
157 {
158 return NULL;
159 }
160
161 HardwareChannel* ptr = &m_FreeList.GetFront();
162 m_FreeList.PopFront();
163
164 // コンストラクタ呼び出し
165 HardwareChannel* pChannel = new( ptr )HardwareChannel();
166 m_ActiveList.PushBack( ptr );
167
168 return pChannel;
169 }
170
Free(HardwareChannel * pChannel)171 void HardwareChannelManager::Free( HardwareChannel* pChannel )
172 {
173 NW_NULL_ASSERT( pChannel );
174
175 pChannel->~HardwareChannel();
176
177 {
178 if ( pChannel->m_IsReserveForFree )
179 {
180 m_FreeReservedList.Erase( pChannel );
181 }
182 else
183 {
184 m_ActiveList.Erase( pChannel );
185 }
186 m_FreeList.PushBack( pChannel );
187 }
188 }
189
ReserveForFree(HardwareChannel * pChannel)190 void HardwareChannelManager::ReserveForFree( HardwareChannel* pChannel )
191 {
192 NW_ASSERT( pChannel );
193
194 m_ActiveList.Erase( pChannel );
195 m_FreeReservedList.PushBack( pChannel );
196 }
197
198 } // namespace nw::snd::internal::driver
199 } // namespace nw::snd::internal
200 } // namespace nw::snd
201 } // namespace nw
202