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