/* Audio_Manager::run: main loop */ void Audio_Manager::run() { int i; Audio_Link *link; char *buff, *save; char *alias, *file; /* create initial threads */ for(i = 0; i < AUDIOMANAGER_INITIALNTHREAD; i++) { link = new Audio_Link; link->audio_thread.setupAndStart(m_mmdagent); link->next = m_list; m_list = link; } while(m_kill == false) { /* wait playing event */ glfwLockMutex(m_mutex); while(m_count <= 0) { glfwWaitCond(m_cond, m_mutex, GLFW_INFINITY); if(m_kill == true) return; } Audio_EventQueue_dequeue(&m_bufferQueue, &buff); m_count--; glfwUnlockMutex(m_mutex); if(buff != NULL) { alias = MMDAgent_strtok(buff, "|", &save); file = MMDAgent_strtok(NULL, "|", &save); if(alias != NULL && file != NULL) { /* check alias */ for(i = 0, link = m_list; link; link = link->next, i++) if(link->audio_thread.checkAlias(alias)) break; if(link) { link->audio_thread.stop(); /* if the same alias is playing, stop immediately */ } else { for(i = 0, link = m_list; link; link = link->next, i++) if(link->audio_thread.isRunning() && link->audio_thread.isPlaying() == false) break; if(link == NULL) { link = new Audio_Link; link->audio_thread.setupAndStart(m_mmdagent); link->next = m_list; m_list = link; } } /* set */ link->audio_thread.play(alias, file); } free(buff); /* free buffer */ } } }
/* MMDAgent_str2fvec: convert string to float vector */ bool MMDAgent_str2fvec(const char *str, float *vec, const int size) { int i = 0; char *buff, *p, *save = NULL; if(str == NULL) return false; buff = MMDAgent_strdup(str); for(p = MMDAgent_strtok(buff, ",", &save); p && i < size; p = MMDAgent_strtok(NULL, ",", &save)) vec[i++] = (float) atof(p); free(buff); if(i == size) return true; else return false; }
/* PMDObject::renderError: render model error */ void PMDObject::renderError(TextRenderer * text) { char buf[PMDOBJECT_MAXBUFLEN]; btVector3 pos; float w, h; float tpos[3]; char *p, *save; m_pmd.getErrorTextureList(buf, PMDOBJECT_MAXBUFLEN); if (MMDAgent_strlen(buf) <= 0) return; pos = m_pmd.getCenterBone()->getTransform()->getOrigin(); pos.setZ(pos.z() + 5.0f); glDisable(GL_LIGHTING); glPushMatrix(); glTranslatef(pos.x() - 0.3f, pos.y() - 0.3f, pos.z() - 0.01f); w = 10.0f; h = 6.0f; glNormal3f(0.0, 0.0, 1.0); glColor4f(0.0f, 0.0f, 0.0f, 0.7f); glBegin(GL_QUADS); glVertex3f(0, 0, 0); glVertex3f(w, 0, 0); glVertex3f(w, h, 0); glVertex3f(0, h, 0); glEnd(); glPopMatrix(); glColor4f(1.0f, 0.0f, 0.0f, 1.0f); tpos[0] = pos.x(); tpos[1] = pos.y() + 5.0f; tpos[2] = pos.z(); glPushMatrix(); glTranslatef(tpos[0], tpos[1], tpos[2]); text->drawString("[Texture Errors]"); glPopMatrix(); for (p = MMDAgent_strtok(buf, "\n", &save); p; p = MMDAgent_strtok(NULL, "\n", &save)) { tpos[1] -= 0.7f; glPushMatrix(); glTranslatef(tpos[0], tpos[1], tpos[2]); text->drawString(p); glPopMatrix(); } glEnable(GL_LIGHTING); }
/* PMDObject::renderCommand: render model comment */ void PMDObject::renderComment(TextRenderer * text) { char *buf, *p, *save; btVector3 pos; float w, h; float tpos[3]; if (m_displayCommentFrame <= 0.0) return; if(m_pmd.getComment() == NULL) return; buf = MMDAgent_strdup(m_pmd.getComment()); pos = m_pmd.getCenterBone()->getTransform()->getOrigin(); w = 13.0f; h = 5.0f; pos.setX(pos.x() - w * 0.5f); pos.setZ(pos.z() + 5.2f); glDisable(GL_LIGHTING); glPushMatrix(); glTranslatef(pos.x() - 0.3f, pos.y() - 0.3f, pos.z() - 0.01f); glNormal3f(0.0, 0.0, 1.0); glColor4f(0.0f, 0.0f, 0.0f, 0.4f); glBegin(GL_QUADS); glVertex3f(0, 0, 0); glVertex3f(w, 0, 0); glVertex3f(w, h, 0); glVertex3f(0, h, 0); glEnd(); glPopMatrix(); glColor4f(0.7f, 0.8f, 0.5f, 1.0f); tpos[0] = pos.x(); tpos[1] = pos.y() + 4.5f; tpos[2] = pos.z(); for (p = MMDAgent_strtok(buf, "\n", &save); p; p = MMDAgent_strtok(NULL, "\n", &save)) { tpos[1] -= 0.65f; glPushMatrix(); glTranslatef(tpos[0], tpos[1], tpos[2]); glScalef(0.8f, 0.8f, 0.8f); text->drawString(p); glPopMatrix(); } glEnable(GL_LIGHTING); free(buf); }
/* LogText::log: store log text */ void LogText::log(const char *format, ...) { char *p, *save; char buff[LOGTEXT_MAXBUFLEN]; va_list args; if (m_textList == NULL) return; va_start(args, format); vsprintf(buff, format, args); for (p = MMDAgent_strtok(buff, "\n", &save); p; p = MMDAgent_strtok(NULL, "\n", &save)) { strncpy(m_textList[m_textIndex], p, m_textWidth - 1); m_textList[m_textIndex][m_textWidth - 1] = '\0'; m_lengthList[m_textIndex] = -1; m_textIndex++; if (m_textIndex >= LOGTEXT_MAXNLINES) m_textIndex = 0; if(m_viewIndex != 0) scroll(1); } va_end(args); }
/* extProcEvent: process event message */ EXPORT void extProcEvent(MMDAgent *mmdagent, const char *type, const char *args) { int i, id; char *p, *buf, *save; PMDObject *objs; ControllerList *tmp1, *tmp2 = NULL; objs = mmdagent->getModelList(); if(MMDAgent_strequal(type, MMDAGENT_EVENT_KEY)) { if(MMDAgent_strequal(args, "l") || MMDAgent_strequal(args, "L")) { changeLookAt(objs, mmdagent->getNumModel(), mmdagent); } } else if(MMDAgent_strequal(type, MMDAGENT_EVENT_MODELCHANGE) || MMDAgent_strequal(type, MMDAGENT_EVENT_MODELADD)) { buf = MMDAgent_strdup(args); p = MMDAgent_strtok(buf, "|", &save); if(p) { id = mmdagent->findModelAlias(p); if(id != -1) { for(i = 0, tmp1 = controllerList; i <= id; i++) { if(tmp1 == NULL) { tmp1 = new ControllerList; tmp1->next = NULL; if(i == 0) controllerList = tmp1; else tmp2->next = tmp1; } if(i == id) { setHeadController(&tmp1->head, objs[id].getPMDModel()); setEyeController(&tmp1->eye, objs[id].getPMDModel()); tmp1->head.setEnableFlag(enable); tmp1->eye.setEnableFlag(enable); } tmp2 = tmp1; tmp1 = tmp1->next; } } } if(buf != NULL) free(buf); } }
/* LipSync::createMotion: create motion from phoneme sequence */ bool LipSync::createMotion(const char *str, unsigned char **rawData, unsigned long *rawSize) { int i, j, k; int len; char *buf, *p, *save; LipKeyFrame *head, *tail, *tmp1, *tmp2; float f, diff; int totalNumKey; unsigned long currentFrame; unsigned char *data; VMDFile_Header *header; unsigned long *numBoneKeyFrames; unsigned long *numFaceKeyFrames; VMDFile_FaceFrame *face; /* check */ if(str == NULL || m_numMotion <= 0 || m_numPhone <= 0) return false; /* initialize */ (*rawData) = NULL; (*rawSize) = 0; /* get phone index and duration */ buf = MMDAgent_strdup(str); head = NULL; tail = NULL; diff = 0.0f; for(i = 0, k = 0, p = MMDAgent_strtok(buf, LIPSYNC_SEPARATOR, &save); p; i++, p = MMDAgent_strtok(NULL, LIPSYNC_SEPARATOR, &save)) { if(i % 2 == 0) { for(j = 0; j < m_numPhone; j++) { if(MMDAgent_strequal(m_phone[j], p)) { k = j; break; } } if(m_numPhone <= j) k = 0; } else { tmp1 = (LipKeyFrame *) malloc(sizeof(LipKeyFrame)); tmp1->phone = k; f = 0.03f * MMDAgent_str2float(p) + diff; /* convert ms to frame */ tmp1->duration = (int) (f + 0.5); if(tmp1->duration < 1) tmp1->duration = 1; diff = f - tmp1->duration; tmp1->rate = 1.0f; tmp1->next = NULL; if(head == NULL) head = tmp1; else tail->next = tmp1; tail = tmp1; } } /* add final closed lip */ tmp1 = (LipKeyFrame *) malloc(sizeof(LipKeyFrame)); tmp1->phone = 0; tmp1->duration = 1; tmp1->rate = 0.0f; tmp1->next = NULL; if(head == NULL) head = tmp1; else tail->next = tmp1; tail = tmp1; /* insert interpolation lip motion */ for(tmp1 = head; tmp1; tmp1 = tmp1->next) { if(tmp1->next && tmp1->duration > LIPSYNC_INTERPOLATIONMARGIN) { tmp2 = (LipKeyFrame *) malloc(sizeof(LipKeyFrame)); tmp2->phone = tmp1->phone; tmp2->duration = LIPSYNC_INTERPOLATIONMARGIN; tmp2->rate = tmp1->rate * LIPSYNC_INTERPOLATIONRATE; tmp2->next = tmp1->next; tmp1->duration -= LIPSYNC_INTERPOLATIONMARGIN; tmp1->next = tmp2; tmp2 = tmp1; } } /* count length of key frame */ len = 0; for(tmp1 = head; tmp1; tmp1 = tmp1->next) len++; totalNumKey = m_numMotion * len; /* create memories */ (*rawSize) = sizeof(VMDFile_Header) + sizeof(unsigned long) + sizeof(unsigned long) + sizeof(VMDFile_FaceFrame) * totalNumKey; i = (*rawSize); i = sizeof(unsigned char) * (*rawSize); (*rawData) = (unsigned char *) malloc(i); data = (*rawData); /* header */ header = (VMDFile_Header *) data; strncpy(header->header, "Vocaloid Motion Data 0002", 30); data += sizeof(VMDFile_Header); /* number of key frame for bone */ numBoneKeyFrames = (unsigned long *) data; (*numBoneKeyFrames) = 0; data += sizeof(unsigned long); /* number of key frame for expression */ numFaceKeyFrames = (unsigned long *) data; (*numFaceKeyFrames) = totalNumKey; data += sizeof(unsigned long); /* set key frame */ for (i = 0; i < m_numMotion; i++) { currentFrame = 0; for(tmp1 = head; tmp1; tmp1 = tmp1->next) { face = (VMDFile_FaceFrame *) data; strncpy(face->name, m_motion[i], 15); face->keyFrame = currentFrame; face->weight = m_blendRate[tmp1->phone][i] * tmp1->rate; data += sizeof(VMDFile_FaceFrame); currentFrame += tmp1->duration; } } /* free */ free(buf); for(tmp1 = head; tmp1; tmp1 = tmp2) { tmp2 = tmp1->next; free(tmp1); } return true; }
/* Open_JTalk_Manager::run: main loop */ void Open_JTalk_Manager::run() { int i; Open_JTalk_Link *link; char *buff, *save; char *chara, *style, *text; bool ret = true; /* create initial threads */ for(i = 0; i < OPENJTALKMANAGER_INITIALNTHREAD; i++) { link = new Open_JTalk_Link; if(link->open_jtalk_thread.loadAndStart(m_mmdagent, m_dicDir, m_config) == false) ret = false; link->next = m_list; m_list = link; } if(ret == false) return; while(m_kill == false) { glfwLockMutex(m_mutex); while(m_count <= 0) { glfwWaitCond(m_cond, m_mutex, GLFW_INFINITY); if(m_kill == true) return; } Open_JTalk_EventQueue_dequeue(&m_bufferQueue, &buff); m_count--; glfwUnlockMutex(m_mutex); if(buff != NULL) { chara = MMDAgent_strtok(buff, "|", &save); style = MMDAgent_strtok(NULL, "|", &save); text = MMDAgent_strtok(NULL, "|", &save); if(chara != NULL && style != NULL && text != NULL) { /* check character */ for(i = 0, link = m_list; link; link = link->next, i++) if(link->open_jtalk_thread.checkCharacter(chara) == true) break; if(link) { if(link->open_jtalk_thread.isSpeaking() == true) link->open_jtalk_thread.stop(); /* if the same character is speaking, stop immediately */ } else { for(i = 0, link = m_list; link; link = link->next, i++) if(link->open_jtalk_thread.isRunning() == true && link->open_jtalk_thread.isSpeaking() == false) break; if(link == NULL) { link = new Open_JTalk_Link; link->open_jtalk_thread.loadAndStart(m_mmdagent, m_dicDir, m_config); link->next = m_list; m_list = link; } } /* set */ link->open_jtalk_thread.synthesis(chara, style, text); } free(buff); /* free buffer */ } } }
/* extProcEvent: process event message */ EXPORT void extProcEvent(MMDAgent *mmdagent, const char *type, const char *args) { int i; FILE *fp; char *buf, *p, *q; PMDObject *objs; MotionPlayer *motionPlayer; if(enable == true) { if(MMDAgent_strequal(type, MMDAGENT_EVENT_DRAGANDDROP)) { buf = MMDAgent_strdup(args); p = MMDAgent_strtok(buf, "|", &q); if(MMDAgent_strtailmatch(p, ".mp3") || MMDAgent_strtailmatch(p, ".MP3")) { /* if there is a motion file which have the same name, store it */ if(drop_motion != NULL) free(drop_motion); drop_motion = MMDAgent_strdup(p); i = MMDAgent_strlen(drop_motion); drop_motion[i-4] = '.'; drop_motion[i-3] = 'v'; drop_motion[i-2] = 'm'; drop_motion[i-1] = 'd'; fp = MMDAgent_fopen(drop_motion, "rb"); if(fp != NULL) { fclose(fp); } else { free(drop_motion); drop_motion = NULL; } /* start mp3 */ audio_manager.stop(PLUGINAUDIO_DEFAULTALIAS); q = (char *) malloc(sizeof(char) * (strlen(PLUGINAUDIO_DEFAULTALIAS) + 1 + strlen(p) + 1)); sprintf(q, "%s|%s", PLUGINAUDIO_DEFAULTALIAS, p); audio_manager.play(q); free(q); } if(buf) free(buf); } else if(MMDAgent_strequal(type, AUDIOTHREAD_EVENTSTART)) { if(drop_motion != NULL) { if(MMDAgent_strequal(args, PLUGINAUDIO_DEFAULTALIAS) == true) { objs = mmdagent->getModelList(); for (i = 0; i < mmdagent->getNumModel(); i++) { if (objs[i].isEnable() == true && objs[i].allowMotionFileDrop() == true) { for (motionPlayer = objs[i].getMotionManager()->getMotionPlayerList(); motionPlayer; motionPlayer = motionPlayer->next) { if (motionPlayer->active == true && MMDAgent_strequal(motionPlayer->name, "base") == true) { mmdagent->sendCommandMessage(MMDAGENT_COMMAND_MOTIONCHANGE, "%s|%s|%s", objs[i].getAlias(), "base", drop_motion); break; } } if (!motionPlayer) mmdagent->sendCommandMessage(MMDAGENT_COMMAND_MOTIONADD, "%s|%s|%s|FULL|ONCE|ON|ON", objs[i].getAlias(), "base", drop_motion); } } mmdagent->resetAdjustmentTimer(); } free(drop_motion); drop_motion = NULL; } } } }
/* postKeyMessage: post key message */ static void postKeyMessage(const char *args) { int i; char *buff, *param1, *param2, *param3, *param4, *param5, *save; HWND window; unsigned int id = 0; INPUT input[8]; int size; bool alt = false, ctrl = false, shift = false; LPARAM info; buff = MMDAgent_strdup(args); param1 = MMDAgent_strtok(buff, "|", &save); /* window name */ param2 = MMDAgent_strtok(NULL, "|", &save); /* key */ param3 = MMDAgent_strtok(NULL, "|", &save); /* shift-key */ param4 = MMDAgent_strtok(NULL, "|", &save); /* control-key */ param5 = MMDAgent_strtok(NULL, "|", &save); /* alt-key */ /* check */ if(buff == NULL || param1 == NULL || param2 == NULL) { free(buff); return; } /* get window handle */ window = FindWindowA(param1, NULL); if(window == 0) { free(buff); return; } /* get key ID */ if(MMDAgent_strlen(param2) == 1) { id = toupper(param2[0]); } else { for(i = 0; keys[i].name != NULL; i++) { if(MMDAgent_strequal(param2, keys[i].name) == true) { id = keys[i].id; break; } } } if(id == 0) { free(buff); return; } /* set forground window */ SetForegroundWindow(window); /* get options */ shift = MMDAgent_strequal(param3, "ON"); ctrl = MMDAgent_strequal(param4, "ON"); alt = MMDAgent_strequal(param5, "ON"); /* create key message */ size = 0; info = GetMessageExtraInfo(); if(shift == true && id != VK_SHIFT) { input[size].type = INPUT_KEYBOARD; input[size].ki.wVk = VK_SHIFT; input[size].ki.wScan = MapVirtualKey(VK_SHIFT, 0); input[size].ki.dwFlags = 0; input[size].ki.time = 0; input[size].ki.dwExtraInfo = info; size++; } if(ctrl == true && id != VK_CONTROL) { input[size].type = INPUT_KEYBOARD; input[size].ki.wVk = VK_CONTROL; input[size].ki.wScan = MapVirtualKey(VK_CONTROL, 0); input[size].ki.dwFlags = 0; input[size].ki.time = 0; input[size].ki.dwExtraInfo = info; size++; } if(alt == true && id != VK_MENU) { input[size].type = INPUT_KEYBOARD; input[size].ki.wVk = VK_MENU; input[size].ki.wScan = MapVirtualKey(VK_MENU, 0); input[size].ki.dwFlags = 0; input[size].ki.time = 0; input[size].ki.dwExtraInfo = info; size++; } input[size].type = INPUT_KEYBOARD; input[size].ki.wVk = id; input[size].ki.wScan = MapVirtualKey(id, 0); input[size].ki.dwFlags = 0; input[size].ki.time = 0; input[size].ki.dwExtraInfo = info; size++; input[size].type = INPUT_KEYBOARD; input[size].ki.wVk = id; input[size].ki.wScan = MapVirtualKey(id, 0); input[size].ki.dwFlags = KEYEVENTF_KEYUP; input[size].ki.time = 0; input[size].ki.dwExtraInfo = info; size++; if(alt == true && id != VK_MENU) { input[size].type = INPUT_KEYBOARD; input[size].ki.wVk = VK_MENU; input[size].ki.wScan = MapVirtualKey(VK_MENU, 0); input[size].ki.dwFlags = KEYEVENTF_KEYUP; input[size].ki.time = 0; input[size].ki.dwExtraInfo = info; size++; } if(ctrl == true && id != VK_CONTROL) { input[size].type = INPUT_KEYBOARD; input[size].ki.wVk = VK_CONTROL; input[size].ki.wScan = MapVirtualKey(VK_CONTROL, 0); input[size].ki.dwFlags = KEYEVENTF_KEYUP; input[size].ki.time = 0; input[size].ki.dwExtraInfo = info; size++; } if(shift == true && id != VK_SHIFT) { input[size].type = INPUT_KEYBOARD; input[size].ki.wVk = VK_SHIFT; input[size].ki.wScan = MapVirtualKey(VK_SHIFT, 0); input[size].ki.dwFlags = KEYEVENTF_KEYUP; input[size].ki.time = 0; input[size].ki.dwExtraInfo = info; size++; } /* send key message */ SendInput(size, input, sizeof(INPUT)); free(buff); }