1 #include "../../common/Environment.h"
\r
2 #include "CServerModel.h"
\r
6 ////////////////////////////////////////////////////////////////////////////////
\r
8 ////////////////////////////////////////////////////////////////////////////////
\r
9 CServerModel::CServerModel()
\r
11 initializeSpeex(&m_SpeexData);
\r
14 ////////////////////////////////////////////////////////////////////////////////
\r
16 ////////////////////////////////////////////////////////////////////////////////
\r
17 CServerModel::~CServerModel()
\r
19 for(size_t i = 0; i < m_Connections.size(); i++){
\r
20 delete m_Connections[i].m_pConnection;
\r
22 for(AvatarInformationList::iterator p = m_AvatarInformations.begin(); p != m_AvatarInformations.end(); p++){
\r
25 uninitializeSpeex(&m_SpeexData);
\r
28 ////////////////////////////////////////////////////////////////////////////////
\r
30 ////////////////////////////////////////////////////////////////////////////////
\r
31 bool CServerModel::initialize()
\r
33 m_ServerSocket.initialize();
\r
34 m_ServerSocket.openPort();
\r
35 std::cout << "PortNumber = " << m_ServerSocket.getPortNumber() << std::endl;
\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
49 ////////////////////////////////////////////////////////////////////////////////
\r
50 // initialize of speex
\r
51 ////////////////////////////////////////////////////////////////////////////////
\r
52 bool CServerModel::initializeSpeex(SpeexData* io_pSpeexData)
\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
57 /* BEGIN: You probably don't need the following in a real application */
\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
64 callback.callback_id = SPEEX_INBAND_MODE_REQUEST;
\r
65 callback.func = speex_std_mode_request_handler;
\r
67 speex_decoder_ctl(dec, SPEEX_SET_HANDLER, &callback);
\r
69 /* END of unnecessary stuff */
\r
73 speex_decoder_ctl(io_pSpeexData->dec, SPEEX_SET_ENH, &tmp);
\r
75 speex_encoder_ctl(io_pSpeexData->st, SPEEX_SET_VBR, &tmp);
\r
77 speex_encoder_ctl(io_pSpeexData->st, SPEEX_SET_QUALITY, &tmp);
\r
80 speex_encoder_ctl(st, SPEEX_SET_COMPLEXITY, &tmp);
\r
83 //speex_encoder_ctl(st, SPEEX_SET_SAMPLING_RATE, &tmp);
\r
84 //speex_decoder_ctl(dec, SPEEX_SET_SAMPLING_RATE, &tmp);
\r
86 //speex_encoder_ctl(st, SPEEX_SET_BITRATE, &tmp);
\r
88 spx_int32_t frame_size;
\r
89 speex_encoder_ctl(io_pSpeexData->st, SPEEX_GET_FRAME_SIZE, &frame_size);
\r
91 /* Turn this off if you want to measure SNR (on by default) */
\r
94 speex_encoder_ctl(st, SPEEX_SET_HIGHPASS, &tmp);
\r
95 speex_decoder_ctl(dec, SPEEX_SET_HIGHPASS, &tmp);
\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
102 speex_bits_init(&io_pSpeexData->bits);
\r
107 ////////////////////////////////////////////////////////////////////////////////
\r
108 // uninitialize of speex
\r
109 ////////////////////////////////////////////////////////////////////////////////
\r
110 bool CServerModel::uninitializeSpeex(SpeexData* io_pSpeexData)
\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
118 ////////////////////////////////////////////////////////////////////////////////
\r
120 ////////////////////////////////////////////////////////////////////////////////
\r
121 bool CServerModel::process()
\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
134 else if(a_pData->m_DataType == 'o'){
\r
135 logout(p, p->m_pAvatarInformation->m_Name);
\r
138 else if(a_pData->m_DataType == 'p'){
\r
139 requestPosition(p);
\r
142 else if(a_pData->m_DataType == 'a'){
\r
143 requestMove(p, a_pData->m_Data.m_ActionCommand.m_CommandType);
\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
151 //speex_bits_reset(&m_SpeexData.bits);
\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
157 speex_decode_int(m_SpeexData.dec, &m_SpeexData.bits, out_short);
\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
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
181 // memo: 同時に受信した音声を、同時刻として合成する
\r
182 // memo: 圧縮音声データは分割して送信されるため、しばらくためておく必要がある
\r
183 // memo: ためた場合、最初が少し遅れるだけで、音がとぎれることはない
\r
184 // memo: ただし、自分自信の声は遅れて聞こえるので、自分自身の音は送り返さない
\r
185 // memo: また、音声の合成は各キャラクター(クライアント)ごとに生成しなければならない
\r
191 // 音声を合成する場合、同じ音を何度も合成しないようにするため、
\r
192 // 録音時刻や受信時刻を利用して、順番を間違えないようしなければならない
\r
194 // 音情報を簡単に扱うため、通信クラスをもう少しまとめなければならない
\r
196 // Modelクラスからは通信を行っていることを意識しないようにしたい
\r
201 ////////////////////////////////////////////////////////////////////////////////
\r
203 ////////////////////////////////////////////////////////////////////////////////
\r
204 bool CServerModel::login(ConnectionVector::iterator io_ConnectionIterator, const char* in_pLoginName)
\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
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
231 ////////////////////////////////////////////////////////////////////////////////
\r
233 ////////////////////////////////////////////////////////////////////////////////
\r
234 bool CServerModel::logout(ConnectionVector::iterator io_ConnectionIterator, const char* in_pLoginName)
\r
237 if(io_ConnectionIterator->m_pAvatarInformation == NULL){
\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
246 std::cout << "logout " << io_ConnectionIterator->m_pAvatarInformation->m_Name << std::endl;
\r
249 for(AvatarInformationList::iterator p = m_AvatarInformations.begin(); p != m_AvatarInformations.end(); p++){
\r
250 if(*p == io_ConnectionIterator->m_pAvatarInformation){
\r
253 m_AvatarInformations.erase(p);
\r
256 io_ConnectionIterator->m_pAvatarInformation = NULL;
\r
260 ////////////////////////////////////////////////////////////////////////////////
\r
262 ////////////////////////////////////////////////////////////////////////////////
\r
263 bool CServerModel::sendData()
\r
268 ////////////////////////////////////////////////////////////////////////////////
\r
270 ////////////////////////////////////////////////////////////////////////////////
\r
271 bool CServerModel::requestPosition(ConnectionVector::iterator io_ConnectionIterator)
\r
274 if(io_ConnectionIterator->m_pAvatarInformation == NULL){
\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
291 if(!io_ConnectionIterator->m_pConnection->send(&a_SendData)){
\r
292 std::cout << "do not send position" << std::endl;
\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
308 ////////////////////////////////////////////////////////////////////////////////
\r
310 ////////////////////////////////////////////////////////////////////////////////
\r
311 bool CServerModel::requestMove(ConnectionVector::iterator io_ConnectionIterator, char in_pMoveDirection)
\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
320 if(io_ConnectionIterator->m_pAvatarInformation == NULL){
\r
324 AvatarInformation* a_pAvatarInformation = io_ConnectionIterator->m_pAvatarInformation;
\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
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
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
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
354 ////////////////////////////////////////////////////////////////////////////////
\r
356 ////////////////////////////////////////////////////////////////////////////////
\r
357 bool CServerModel::sendVoice()
\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
363 StructWaveBuffer* a_pWaveBuffer = p->m_pAvatarInformation->m_Voice.getReadPointer();
\r
364 if(a_pWaveBuffer == NULL){
\r
365 // 一つでも音声データが存在しなければ送信しない
\r
375 for(ConnectionVector::iterator p = m_Connections.begin(); p != m_Connections.end(); p++){
\r
376 if(p->m_pAvatarInformation == NULL){
\r
380 unsigned char buffer[3000];
\r
382 for(int i = 0; i < 3000; i++){
\r
385 for(ConnectionVector::iterator q = m_Connections.begin(); q != m_Connections.end(); q++){
\r
386 if(q->m_pAvatarInformation == NULL){
\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
398 unsigned char* p1 = buffer;
\r
400 short in_short[FRAME_SIZE];
\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
410 in_short[i] = (128 << 8) ^ 0x8000;
\r
416 speex_bits_reset(&m_SpeexData.bits);
\r
419 speex_encode_int(m_SpeexData.st, in_short, &m_SpeexData.bits);
\r
423 int nbBytes = speex_bits_write(&m_SpeexData.bits, cbits, 200);
\r
424 bitCount += m_SpeexData.bits.nbBits;
\r
427 if(p1 >= buffer + length){
\r
428 p->m_pConnection->sendVoice(cbits, nbBytes, 1);
\r
432 p->m_pConnection->sendVoice(cbits, nbBytes, 0);
\r
434 std::cout << "送信" << std::endl;
\r
437 for(ConnectionVector::iterator p = m_Connections.begin(); p != m_Connections.end(); p++){
\r
438 if(p->m_pAvatarInformation == NULL){
\r
441 p->m_pAvatarInformation->m_Voice.nextReadBuffer();
\r