OSDN Git Service

convert sjis to utf8 bom
[internetcity/prototype.git] / vc2010_server / vc2010_server / CServerModel.cpp
1 #include "../../common/Environment.h"\r
2 #include "CServerModel.h"\r
3 \r
4 #include <iostream>\r
5 \r
6 ////////////////////////////////////////////////////////////////////////////////\r
7 // constructor\r
8 ////////////////////////////////////////////////////////////////////////////////\r
9 CServerModel::CServerModel()\r
10 {\r
11         initializeSpeex(&m_SpeexData);\r
12 }\r
13 \r
14 ////////////////////////////////////////////////////////////////////////////////\r
15 // destructor\r
16 ////////////////////////////////////////////////////////////////////////////////\r
17 CServerModel::~CServerModel()\r
18 {\r
19         for(size_t i = 0; i < m_Connections.size(); i++){\r
20                 delete m_Connections[i].m_pConnection;\r
21         }\r
22         for(AvatarInformationList::iterator p = m_AvatarInformations.begin(); p != m_AvatarInformations.end(); p++){\r
23                 delete *p;\r
24         }\r
25         uninitializeSpeex(&m_SpeexData);\r
26 }\r
27 \r
28 ////////////////////////////////////////////////////////////////////////////////\r
29 // initialize\r
30 ////////////////////////////////////////////////////////////////////////////////\r
31 bool CServerModel::initialize()\r
32 {\r
33         m_ServerSocket.initialize();\r
34         m_ServerSocket.openPort();\r
35         std::cout << "PortNumber = " << m_ServerSocket.getPortNumber() << std::endl;\r
36 \r
37         m_Connections.resize(MAX_CONNECTION_NUMBER);\r
38         for(size_t i = 0; i < m_Connections.size(); i++){\r
39                 ConnectionTuple temp;\r
40                 temp.m_pConnection = new CServerConnection();\r
41                 temp.m_pConnection->initialize();\r
42                 m_ServerSocket.accept(temp.m_pConnection);\r
43                 temp.m_pAvatarInformation = NULL;\r
44                 m_Connections[i] = temp;\r
45         }\r
46         return true;\r
47 }\r
48 \r
49 ////////////////////////////////////////////////////////////////////////////////\r
50 // initialize of speex\r
51 ////////////////////////////////////////////////////////////////////////////////\r
52 bool CServerModel::initializeSpeex(SpeexData* io_pSpeexData)\r
53 {\r
54         io_pSpeexData->st = speex_encoder_init(speex_lib_get_mode(SPEEX_MODEID_NB));\r
55         io_pSpeexData->dec = speex_decoder_init(speex_lib_get_mode(SPEEX_MODEID_NB));\r
56 \r
57         /* BEGIN: You probably don't need the following in a real application */\r
58 #if 0\r
59         callback.callback_id = SPEEX_INBAND_CHAR;\r
60         callback.func = speex_std_char_handler;\r
61         callback.data = stderr;\r
62         speex_decoder_ctl(dec, SPEEX_SET_HANDLER, &callback);\r
63 \r
64         callback.callback_id = SPEEX_INBAND_MODE_REQUEST;\r
65         callback.func = speex_std_mode_request_handler;\r
66         callback.data = st;\r
67         speex_decoder_ctl(dec, SPEEX_SET_HANDLER, &callback);\r
68 #endif\r
69         /* END of unnecessary stuff */\r
70 \r
71         spx_int32_t tmp;\r
72         tmp=1;\r
73         speex_decoder_ctl(io_pSpeexData->dec, SPEEX_SET_ENH, &tmp);\r
74         tmp=0;\r
75         speex_encoder_ctl(io_pSpeexData->st, SPEEX_SET_VBR, &tmp);\r
76         tmp=8;\r
77         speex_encoder_ctl(io_pSpeexData->st, SPEEX_SET_QUALITY, &tmp);\r
78         /*\r
79         tmp=1;\r
80         speex_encoder_ctl(st, SPEEX_SET_COMPLEXITY, &tmp);\r
81         */\r
82         tmp = 8000;\r
83         //speex_encoder_ctl(st, SPEEX_SET_SAMPLING_RATE, &tmp);\r
84         //speex_decoder_ctl(dec, SPEEX_SET_SAMPLING_RATE, &tmp);\r
85         //tmp = 8000;\r
86         //speex_encoder_ctl(st, SPEEX_SET_BITRATE, &tmp);\r
87 \r
88         spx_int32_t frame_size;\r
89         speex_encoder_ctl(io_pSpeexData->st, SPEEX_GET_FRAME_SIZE, &frame_size);\r
90 \r
91         /* Turn this off if you want to measure SNR (on by default) */\r
92         /*\r
93         tmp=1;\r
94         speex_encoder_ctl(st, SPEEX_SET_HIGHPASS, &tmp);\r
95         speex_decoder_ctl(dec, SPEEX_SET_HIGHPASS, &tmp);\r
96         */\r
97 \r
98         speex_encoder_ctl(io_pSpeexData->st, SPEEX_GET_LOOKAHEAD, &io_pSpeexData->skip_group_delay);\r
99         speex_decoder_ctl(io_pSpeexData->dec, SPEEX_GET_LOOKAHEAD, &tmp);\r
100         io_pSpeexData->skip_group_delay += tmp;\r
101 \r
102         speex_bits_init(&io_pSpeexData->bits);\r
103 \r
104         return true;\r
105 }\r
106 \r
107 ////////////////////////////////////////////////////////////////////////////////\r
108 // uninitialize of speex\r
109 ////////////////////////////////////////////////////////////////////////////////\r
110 bool CServerModel::uninitializeSpeex(SpeexData* io_pSpeexData)\r
111 {\r
112         speex_encoder_destroy(io_pSpeexData->st);\r
113         speex_decoder_destroy(io_pSpeexData->dec);\r
114         speex_bits_destroy(&io_pSpeexData->bits);\r
115         return true;\r
116 }\r
117 \r
118 ////////////////////////////////////////////////////////////////////////////////\r
119 // 処理\r
120 ////////////////////////////////////////////////////////////////////////////////\r
121 bool CServerModel::process()\r
122 {\r
123         // 通信クラスからデータ取得\r
124         for(ConnectionVector::iterator p = m_Connections.begin(); p != m_Connections.end(); p++){\r
125                 CommunicationData* a_pData;\r
126                 if(p->m_pConnection->receive(&a_pData)){\r
127                         // ログイン処理(セッションとログインネームと(パスワード)を渡す)\r
128                         if(a_pData->m_DataType == 'i'){\r
129                                 if(login(p, a_pData->m_Data.m_LoginData.m_Name)){\r
130                                         std::cout << "login " << a_pData->m_Data.m_LoginData.m_Name << std::endl;\r
131                                 }\r
132                         }\r
133                         // ログアウト処理\r
134                         else if(a_pData->m_DataType == 'o'){\r
135                                 logout(p, p->m_pAvatarInformation->m_Name);\r
136                         }\r
137                         // 座標取得\r
138                         else if(a_pData->m_DataType == 'p'){\r
139                                 requestPosition(p);\r
140                         }\r
141                         // アクションコマンドを処理\r
142                         else if(a_pData->m_DataType == 'a'){\r
143                                 requestMove(p, a_pData->m_Data.m_ActionCommand.m_CommandType);\r
144                         }\r
145                         // 音声データを格納する\r
146                         else if(a_pData->m_DataType == 'v' && p->m_pAvatarInformation != NULL){\r
147                                 std::cout << "受信" << std::endl;\r
148                                 short out_short[FRAME_SIZE];\r
149 \r
150                                 // リセット\r
151                                 //speex_bits_reset(&m_SpeexData.bits);\r
152 \r
153                                 // 圧縮ビットストリームをセット(同時にリセットされる)\r
154                                 speex_bits_read_from(&m_SpeexData.bits, a_pData->m_Data.m_Voice.m_Stream, a_pData->m_Data.m_Voice.m_Length);\r
155 \r
156                                 // 解凍\r
157                                 speex_decode_int(m_SpeexData.dec, &m_SpeexData.bits, out_short);\r
158 \r
159                                 // Convert 16 -> 8 bits\r
160                                 for(int i = 0; i < FRAME_SIZE; i++){\r
161                                         p->m_pAvatarInformation->m_Stream[p->m_pAvatarInformation->m_Length] = (out_short[i] ^ 0x8000) >> 8;\r
162                                         p->m_pAvatarInformation->m_Length++;\r
163                                 }\r
164 \r
165                                 if(a_pData->m_Data.m_Voice.m_isEnd){\r
166                                         StructWaveBuffer* a_pOutputWaveData = p->m_pAvatarInformation->m_Voice.getWritePointer();\r
167                                         a_pOutputWaveData->m_pWaveBuffer = p->m_pAvatarInformation->m_Stream;\r
168                                         a_pOutputWaveData->m_BufferSize = p->m_pAvatarInformation->m_Length;\r
169                                         a_pOutputWaveData->m_RecorMilliSecond = 100;\r
170                                         p->m_pAvatarInformation->m_Length = 0;\r
171                                         p->m_pAvatarInformation->m_Voice.nextWriteBuffer();\r
172                                         //std::cout << "reset" << std::endl;\r
173                                 }\r
174                         }\r
175                 }\r
176         }\r
177         // 音声データがあれば送信する\r
178         sendVoice();\r
179 \r
180         // 音声を合成\r
181         // memo: 同時に受信した音声を、同時刻として合成する\r
182         // memo: 圧縮音声データは分割して送信されるため、しばらくためておく必要がある\r
183         // memo: ためた場合、最初が少し遅れるだけで、音がとぎれることはない\r
184         // memo: ただし、自分自信の声は遅れて聞こえるので、自分自身の音は送り返さない\r
185         // memo: また、音声の合成は各キャラクター(クライアント)ごとに生成しなければならない\r
186 \r
187         // 取得コマンドに対してデータ送信\r
188 \r
189 \r
190         // to do\r
191         // 音声を合成する場合、同じ音を何度も合成しないようにするため、\r
192         // 録音時刻や受信時刻を利用して、順番を間違えないようしなければならない\r
193 \r
194         // 音情報を簡単に扱うため、通信クラスをもう少しまとめなければならない\r
195 \r
196         // Modelクラスからは通信を行っていることを意識しないようにしたい\r
197 \r
198         return true;\r
199 }\r
200 \r
201 ////////////////////////////////////////////////////////////////////////////////\r
202 // login\r
203 ////////////////////////////////////////////////////////////////////////////////\r
204 bool CServerModel::login(ConnectionVector::iterator io_ConnectionIterator, const char* in_pLoginName)\r
205 {\r
206         AvatarInformation* temp = new AvatarInformation;\r
207         strcpy(temp->m_Name, in_pLoginName);\r
208         temp->m_Position[0] = 0;\r
209         temp->m_Position[1] = 0;\r
210         temp->m_Position[2] = 0;\r
211         temp->m_Direction[0] = 1;\r
212         temp->m_Direction[1] = 0;\r
213         temp->m_Direction[2] = 0;\r
214         temp->m_Radias = 0.3;\r
215         // あとで修正必須(マジックナンバー)\r
216         temp->m_Voice.allocate(10, 100, 2080);\r
217         temp->m_Length = 0;\r
218         m_AvatarInformations.push_back(temp);\r
219 \r
220         /*\r
221         // ログイン完了送信\r
222         CommunicationData a_SendData;\r
223         a_SendData.m_DataType = 'i';\r
224         strcpy(a_SendData.m_Data.m_LoginData.m_Name, in_pLoginName);\r
225         io_ConnectionIterator->m_pConnection->send(&a_SendData);\r
226         io_ConnectionIterator->m_pAvatarInformation = temp;\r
227         */\r
228         return true;\r
229 }\r
230 \r
231 ////////////////////////////////////////////////////////////////////////////////\r
232 // logout\r
233 ////////////////////////////////////////////////////////////////////////////////\r
234 bool CServerModel::logout(ConnectionVector::iterator io_ConnectionIterator, const char* in_pLoginName)\r
235 {\r
236         // 未ログイン\r
237         if(io_ConnectionIterator->m_pAvatarInformation == NULL){\r
238                 return false;\r
239         }\r
240 \r
241         CommunicationData a_SendData;\r
242         a_SendData.m_DataType = 'o';\r
243         strcpy(a_SendData.m_Data.m_LoginData.m_Name, in_pLoginName);\r
244         io_ConnectionIterator->m_pConnection->send(&a_SendData);\r
245 \r
246         std::cout << "logout " << io_ConnectionIterator->m_pAvatarInformation->m_Name << std::endl;\r
247 \r
248         // アバターを削除する\r
249         for(AvatarInformationList::iterator p = m_AvatarInformations.begin(); p != m_AvatarInformations.end(); p++){\r
250                 if(*p == io_ConnectionIterator->m_pAvatarInformation){\r
251                         delete *p;\r
252                 }\r
253                 m_AvatarInformations.erase(p);\r
254                 break;\r
255         }\r
256         io_ConnectionIterator->m_pAvatarInformation = NULL;\r
257         return true;\r
258 }\r
259 \r
260 ////////////////////////////////////////////////////////////////////////////////\r
261 // 送信処理\r
262 ////////////////////////////////////////////////////////////////////////////////\r
263 bool CServerModel::sendData()\r
264 {\r
265         return true;\r
266 }\r
267 \r
268 ////////////////////////////////////////////////////////////////////////////////\r
269 // position\r
270 ////////////////////////////////////////////////////////////////////////////////\r
271 bool CServerModel::requestPosition(ConnectionVector::iterator io_ConnectionIterator)\r
272 {\r
273         // 未ログイン\r
274         if(io_ConnectionIterator->m_pAvatarInformation == NULL){\r
275                 return false;\r
276         }\r
277 \r
278         if(!m_AvatarInformations.empty()){\r
279                 for(AvatarInformationList::iterator p = m_AvatarInformations.begin(); p != m_AvatarInformations.end(); p++){\r
280                         CommunicationData a_SendData;\r
281                         a_SendData.m_DataType = 'p';\r
282                         strcpy(a_SendData.m_Data.m_AvatarData.m_Name, (*p)->m_Name);\r
283                         a_SendData.m_Data.m_AvatarData.m_Position[0] = (*p)->m_Position[0];\r
284                         a_SendData.m_Data.m_AvatarData.m_Position[1] = (*p)->m_Position[1];\r
285                         a_SendData.m_Data.m_AvatarData.m_Position[2] = (*p)->m_Position[2];\r
286                         a_SendData.m_Data.m_AvatarData.m_Direction[0] = (*p)->m_Direction[0];\r
287                         a_SendData.m_Data.m_AvatarData.m_Direction[1] = (*p)->m_Direction[1];\r
288                         a_SendData.m_Data.m_AvatarData.m_Direction[2] = (*p)->m_Direction[2];\r
289                         a_SendData.m_Data.m_AvatarData.m_Radias = (*p)->m_Radias;\r
290 \r
291                         if(!io_ConnectionIterator->m_pConnection->send(&a_SendData)){\r
292                                 std::cout << "do not send position" << std::endl;\r
293                         }\r
294                 }\r
295         }\r
296         /*\r
297         else{\r
298                 CommunicationData a_SendData;\r
299                 a_SendBuffer.m_Length = sprintf(a_SendBuffer.m_Buffer, "p;");\r
300                 if(!io_pConnection->send(&a_SendBuffer)){\r
301                         std::cout << "do not send position" << std::endl;\r
302                 }\r
303         }\r
304         */\r
305         return true;\r
306 }\r
307 \r
308 ////////////////////////////////////////////////////////////////////////////////\r
309 // move\r
310 ////////////////////////////////////////////////////////////////////////////////\r
311 bool CServerModel::requestMove(ConnectionVector::iterator io_ConnectionIterator, char in_pMoveDirection)\r
312 {\r
313         const double M_PI = 3.14159265357989;\r
314         // 人の歩く速度を1秒間に1mとする\r
315         const double a_VelocityParTimes = 1.0 / 60;\r
316         // 2秒で振り返る(180度 = pi)とする。\r
317         const double a_RotateParTimes = M_PI / (2 * 60);\r
318 \r
319         // 未ログイン\r
320         if(io_ConnectionIterator->m_pAvatarInformation == NULL){\r
321                 return false;\r
322         }\r
323 \r
324         AvatarInformation* a_pAvatarInformation = io_ConnectionIterator->m_pAvatarInformation;\r
325 \r
326         if(in_pMoveDirection == 'f'){\r
327                 a_pAvatarInformation->m_Position[0] += a_pAvatarInformation->m_Direction[0] * a_VelocityParTimes;\r
328                 a_pAvatarInformation->m_Position[1] += a_pAvatarInformation->m_Direction[1] * a_VelocityParTimes;\r
329                 a_pAvatarInformation->m_Position[2] += a_pAvatarInformation->m_Direction[2] * a_VelocityParTimes;\r
330         }\r
331         // 後方へ移動\r
332         else if(in_pMoveDirection == 'b'){\r
333                 a_pAvatarInformation->m_Position[0] -= a_pAvatarInformation->m_Direction[0] * a_VelocityParTimes;\r
334                 a_pAvatarInformation->m_Position[1] -= a_pAvatarInformation->m_Direction[1] * a_VelocityParTimes;\r
335                 a_pAvatarInformation->m_Position[2] -= a_pAvatarInformation->m_Direction[2] * a_VelocityParTimes;\r
336         }\r
337         // 右旋回\r
338         else if(in_pMoveDirection == 'r'){\r
339                 double x = a_pAvatarInformation->m_Direction[0];\r
340                 double y = a_pAvatarInformation->m_Direction[1];\r
341                 a_pAvatarInformation->m_Direction[0] =  x * cos(a_RotateParTimes) + y * sin(a_RotateParTimes);\r
342                 a_pAvatarInformation->m_Direction[1] = -x * sin(a_RotateParTimes) + y * cos(a_RotateParTimes);\r
343         }\r
344         // 左旋回\r
345         else if(in_pMoveDirection == 'l'){\r
346                 double x = a_pAvatarInformation->m_Direction[0];\r
347                 double y = a_pAvatarInformation->m_Direction[1];\r
348                 a_pAvatarInformation->m_Direction[0] =  x * cos(a_RotateParTimes) - y * sin(a_RotateParTimes);\r
349                 a_pAvatarInformation->m_Direction[1] =  x * sin(a_RotateParTimes) + y * cos(a_RotateParTimes);\r
350         }\r
351         return true;\r
352 }\r
353 \r
354 ////////////////////////////////////////////////////////////////////////////////\r
355 // 音声送信\r
356 ////////////////////////////////////////////////////////////////////////////////\r
357 bool CServerModel::sendVoice()\r
358 {\r
359         bool check = false;\r
360         for(ConnectionVector::iterator p = m_Connections.begin(); p != m_Connections.end(); p++){\r
361                 if(p->m_pAvatarInformation != NULL){\r
362                         check = true;\r
363                         StructWaveBuffer* a_pWaveBuffer = p->m_pAvatarInformation->m_Voice.getReadPointer();\r
364                         if(a_pWaveBuffer == NULL){\r
365                                 // 一つでも音声データが存在しなければ送信しない\r
366                                 // 本来であれば時間で管理すべき\r
367                                 return false;\r
368                         }\r
369                 }\r
370         }\r
371         if(!check){\r
372                 return false;\r
373         }\r
374         // すべてのコネクションに送信する\r
375         for(ConnectionVector::iterator p = m_Connections.begin(); p != m_Connections.end(); p++){\r
376                 if(p->m_pAvatarInformation == NULL){\r
377                         continue;\r
378                 }\r
379                 // すべての音声データを集める\r
380                 unsigned char buffer[3000];\r
381                 int length = 0;\r
382                 for(int i = 0; i < 3000; i++){\r
383                         buffer[i] = 128;\r
384                 }\r
385                 for(ConnectionVector::iterator q = m_Connections.begin(); q != m_Connections.end(); q++){\r
386                         if(q->m_pAvatarInformation == NULL){\r
387                                 continue;\r
388                         }\r
389                         // 自分自身は合成しない(現在デバッグ中なので合成している)\r
390                         StructWaveBuffer* a_pInputWaveData = q->m_pAvatarInformation->m_Voice.getReadPointer();\r
391                         for(unsigned int i = 0; i < a_pInputWaveData->m_BufferSize; i++){\r
392                                 // 量子化ビット数が8ビットの場合は、0〜255 の範囲で振幅値を表現します。128 が中心(振幅なし)です。\r
393                                 // 16ビットの場合は、-32768〜32767 の範囲で振幅値を表現します。0 が中心(振幅なし)です。\r
394                                 buffer[i] = static_cast<unsigned char>(buffer[i]) + static_cast<unsigned char>(a_pInputWaveData->m_pWaveBuffer[i]) - 128;\r
395                                 length = a_pInputWaveData->m_BufferSize;\r
396                         }\r
397                 }\r
398                 unsigned char* p1 = buffer;\r
399                 while(true){\r
400                         short in_short[FRAME_SIZE];\r
401                         int bitCount = 0;\r
402                         // Convert 8 -> 16 bits\r
403                         for(int i = 0; i < FRAME_SIZE; i++){\r
404                                 // 量子化ビット数が8ビットの場合は、0〜255 の範囲で振幅値を表現します。128 が中心(振幅なし)です。\r
405                                 // 16ビットの場合は、-32768〜32767 の範囲で振幅値を表現します。0 が中心(振幅なし)です。\r
406                                 if(p1 < buffer + length){\r
407                                         in_short[i] = (*(p1 + i) << 8) ^ 0x8000;\r
408                                 }\r
409                                 else{\r
410                                         in_short[i] = (128 << 8) ^ 0x8000;\r
411                                 }\r
412                         }\r
413                         p1 += FRAME_SIZE;\r
414 \r
415                         // リセット\r
416                         speex_bits_reset(&m_SpeexData.bits);\r
417 \r
418                         // 圧縮\r
419                         speex_encode_int(m_SpeexData.st, in_short, &m_SpeexData.bits);\r
420 \r
421                         // 圧縮ビットストリーム取得\r
422                         char cbits[200];\r
423                         int nbBytes = speex_bits_write(&m_SpeexData.bits, cbits, 200);\r
424                         bitCount += m_SpeexData.bits.nbBits;\r
425 \r
426                         // 送信\r
427                         if(p1 >= buffer + length){\r
428                                 p->m_pConnection->sendVoice(cbits, nbBytes, 1);\r
429                                 break;\r
430                         }\r
431                         else{\r
432                                 p->m_pConnection->sendVoice(cbits, nbBytes, 0);\r
433                         }\r
434                         std::cout << "送信" << std::endl;\r
435                 }\r
436         }\r
437         for(ConnectionVector::iterator p = m_Connections.begin(); p != m_Connections.end(); p++){\r
438                 if(p->m_pAvatarInformation == NULL){\r
439                         continue;\r
440                 }\r
441                 p->m_pAvatarInformation->m_Voice.nextReadBuffer();\r
442         }\r
443         return true;\r
444 }\r