/* Sphinx_Thread::loadAndStart: load models and start thread */ void Sphinx_Thread::loadAndStart(MMDAgent *mmdagent, const char *languageModel, const char *dictionary, const char *acousticModel, const char *configFile, const char *logFolder) { /* reset */ clear(); m_mmdagent = mmdagent; m_languageModel = MMDAgent_strdup(languageModel); m_dictionary = MMDAgent_strdup(dictionary); m_acousticModel = MMDAgent_strdup(acousticModel); m_configFile = MMDAgent_strdup(configFile); m_logFolder = MMDAgent_strdup(logFolder); if(m_mmdagent == NULL || m_languageModel == NULL || m_dictionary == NULL || m_acousticModel == NULL || m_configFile == NULL || m_logFolder == NULL) { clear(); return; } /* create recognition thread */ glfwInit(); m_thread = glfwCreateThread(mainThread, this); if(m_thread < 0) { clear(); return; } }
/* Audio_Thread::play: start playing */ void Audio_Thread::play(const char *alias, const char *file) { /* check */ if(isRunning() == false) return; if(MMDAgent_strlen(alias) <= 0 || MMDAgent_strlen(file) <= 0) return; /* wait buffer mutex */ glfwLockMutex(m_mutex); /* save character name, speaking style, and text */ if(m_alias) free(m_alias); if(m_file) free(m_file); m_alias = MMDAgent_strdup(alias); m_file = MMDAgent_strdup(file); m_count++; /* start playing thread */ if(m_count <= 1) glfwSignalCond(m_cond); /* release buffer mutex */ glfwUnlockMutex(m_mutex); }
/* VIManager_Arc_initialize: initialize arc */ static void VIManager_Arc_initialize(VIManager_Arc *a, char *input_event_type, char *input_event_args, char *output_command_type, char *output_command_args, VIManager_State *next_state) { a->input_event_type = MMDAgent_strdup(input_event_type); InputArguments_initialize(&a->input_event_args, input_event_args); a->output_command_type = MMDAgent_strdup(output_command_type); a->output_command_args = MMDAgent_strdup(output_command_args); a->next_state = next_state; a->next = NULL; }
/* Variables::set: set value */ void Variables::set(const char *alias, const char *str1, const char *str2) { Value *val; float max, min, tmp; if(MMDAgent_strlen(alias) <= 0) return; /* check the same alias */ for(val = m_head; val; val = val->next) { if(MMDAgent_strequal(val->name, alias)) break; } /* push */ if(val == NULL) { val = (Value *) malloc(sizeof(Value)); val->name = MMDAgent_strdup(alias); val->next = NULL; if(m_tail == NULL) { m_head = val; val->prev = NULL; } else { m_tail->next = val; val->prev = m_tail; } m_tail = val; } else { free(val->sval); } /* set string */ if(str2 == NULL) { val->sval = MMDAgent_strdup(str1); } else { val->sval = (char *) malloc(sizeof(char) * (MMDAgent_strlen(str1) + 1 + MMDAgent_strlen(str2) + 1)); sprintf(val->sval, "%s|%s", str1, str2); } /* set float */ if(str2 == NULL) { val->fval = MMDAgent_str2float(str1); } else { min = MMDAgent_str2float(str1); max = MMDAgent_str2float(str2); if(max < min) { tmp = max; max = min; min = tmp; } val->fval = min + (max - min) * (rand() - 0.0f) * (1.0f / (RAND_MAX - 0.0f)); /* 0.0f is RAND_MIN */ } m_mmdagent->sendEventMessage(VARIABLES_VALUESETEVENT, alias); /* send message */ }
/* Audio_Thread::run: main thread loop for audio */ void Audio_Thread::run() { Audio audio; char *alias, *file; bool lipsync; while (m_kill == false) { /* wait event */ glfwLockMutex(m_mutex); while(m_count <= 0) { glfwWaitCond(m_cond, m_mutex, GLFW_INFINITY); if(m_kill == true) return; } alias = MMDAgent_strdup(m_alias); file = MMDAgent_strdup(m_file); m_count--; glfwUnlockMutex(m_mutex); m_playing = true; /* open and start audio */ Audio_initialize(&audio); if(Audio_openAndStart(&audio, alias, file) == true) { lipsync = startLipsync(file); /* send SOUND_EVENT_START */ m_mmdagent->sendMessage(AUDIOTHREAD_EVENTSTART, "%s", alias); /* wait to stop audio */ Audio_waitToStop(&audio, alias, &m_playing); if(lipsync) stopLipsync(); /* send SOUND_EVENT_STOP */ m_mmdagent->sendMessage(AUDIOTHREAD_EVENTSTOP, "%s", alias); /* close audio file */ Audio_close(&audio, alias); } if(alias) free(alias); if(file) free(file); Audio_clear(&audio); m_playing = false; } }
/* DLLibrary_load: load dynamic link library */ bool DLLibrary_load(DLLibrary *d, const char *dir, const char *file) { char *buf; if(d == NULL || dir == NULL || file == NULL) return false; DLLibrary_clear(d); /* open */ buf = (char *) malloc(sizeof(char) * (MMDAgent_strlen(dir) + 1 + MMDAgent_strlen(file) + 1)); sprintf(buf, "%s%c%s", dir, MMDAGENT_DIRSEPARATOR, file); d->handle = MMDAgent_dlopen(buf); free(buf); if (!d->handle) return false; /* set function pointers */ d->appStart = (void (*)(MMDAgent *)) MMDAgent_dlsym(d->handle, "extAppStart"); d->appEnd = (void (*)(MMDAgent *)) MMDAgent_dlsym(d->handle, "extAppEnd"); d->procCommand = (void (*)(MMDAgent *, const char *, const char *)) MMDAgent_dlsym(d->handle, "extProcCommand"); d->procEvent = (void (*)(MMDAgent *, const char *, const char *)) MMDAgent_dlsym(d->handle, "extProcEvent"); d->update = (void (*)(MMDAgent *, double)) MMDAgent_dlsym(d->handle, "extUpdate"); d->render = (void (*)(MMDAgent *)) MMDAgent_dlsym(d->handle, "extRender"); if (d->appStart || d->appEnd || d->procCommand || d->procEvent || d->update || d->render) { /* save file name */ d->name = MMDAgent_strdup(file); return true; } else { /* if none, exit */ DLLibrary_clear(d); return false; } }
/* extAppStart: load amodels and start thread */ EXPORT void extAppStart(MMDAgent *mmdagent) { int len; char dic[MMDAGENT_MAXBUFLEN]; char *config; /* get dictionary directory name */ sprintf(dic, "%s%c%s", mmdagent->getConfigDirName(), MMDAGENT_DIRSEPARATOR, PLUGININTERFACE_NAME); /* get config file */ config = MMDAgent_strdup(mmdagent->getConfigFileName()); len = MMDAgent_strlen(config); /* load */ if (len > 4) { config[len - 4] = '.'; config[len - 3] = 'x'; config[len - 2] = 'x'; config[len - 1] = 'x'; interface_manager.loadAndStart(mmdagent, dic, config); } if(config) free(config); enable = true; mmdagent->sendMessage(MMDAGENT_EVENT_PLUGINENABLE, "%s", PLUGININTERFACE_NAME); }
/* PMDObject::setAlias: set alias name */ void PMDObject::setAlias(const char *alias) { if(MMDAgent_strlen(alias) > 0 && m_alias != alias) { if(m_alias) free(m_alias); m_alias = MMDAgent_strdup(alias); } }
/* Open_JTalk_Event_initialize: initialize input message buffer */ static void Open_JTalk_Event_initialize(Open_JTalk_Event *e, const char *str) { if (str != NULL) e->event = MMDAgent_strdup(str); else e->event = NULL; e->next = NULL; }
/* Audio_Thread::startLipsync: start lipsync if HTK label file is existing */ bool Audio_Thread::startLipsync(const char *file) { bool result = false; int i; char *label; size_t len; FILE *fp; char buff[MMDAGENT_MAXBUFLEN]; char message[MMDAGENT_MAXBUFLEN]; int startLen, startTime, endLen, endTime, phonemeLen; bool first = true; PMDObject *objs; len = MMDAgent_strlen(file); if(len > 4) { label = MMDAgent_strdup(file); label[len - 4] = '.'; label[len - 3] = 'l'; label[len - 2] = 'a'; label[len - 1] = 'b'; fp = MMDAgent_fopen(label, "r"); if(fp != NULL) { /* load HTK label */ strcpy(message, ""); while(1) { startLen = MMDAgent_fgettoken(fp, buff); startTime = MMDAgent_str2int(buff); endLen = MMDAgent_fgettoken(fp, buff); endTime = MMDAgent_str2int(buff); phonemeLen = MMDAgent_fgettoken(fp, buff); if(startLen > 0 && endLen > 0 && phonemeLen > 0 && startTime < endTime) { if(first) sprintf(message, "%s,%d", buff, (int) ((double) (endTime - startTime) * 1.0E-04 + 0.5)); else sprintf(message, "%s,%s,%d", message, buff, (int) ((double) (endTime - startTime) * 1.0E-04 + 0.5)); first = false; } else { break; } } fclose(fp); /* send lipsync message */ if(first == false) { objs = m_mmdagent->getModelList(); for (i = 0; i < m_mmdagent->getNumModel(); i++) { if (objs[i].isEnable() == true && objs[i].allowMotionFileDrop() == true) { m_mmdagent->sendMessage(MMDAGENT_COMMAND_LIPSYNCSTART, "%s|%s", objs[i].getAlias(), message); result = true; } } } } free(label); } return result; }
/* VIManager_Arc_initialize: initialize arc */ static void VIManager_Arc_initialize(VIManager_Arc *a, char *input_event_type, char **input_event_args, int input_event_argc, char *output_command_type, char *output_command_args, VIManager_State *next_state) { int i; a->input_event_type = MMDAgent_strdup(input_event_type); if (input_event_argc <= 0) { a->input_event_args = NULL; a->input_event_argc = 0; } else { a->input_event_args = (char **) calloc(input_event_argc, sizeof(char *)); for (i = 0; i < input_event_argc; i++) a->input_event_args[i] = MMDAgent_strdup(input_event_args[i]); a->input_event_argc = input_event_argc; } a->output_command_type = MMDAgent_strdup(output_command_type); a->output_command_args = MMDAgent_strdup(output_command_args); a->next_state = next_state; a->next = NULL; }
/* Julius_Thread::loadAndStart: load models and start thread */ void Julius_Thread::loadAndStart(MMDAgent *mmdagent, const char *languageModel, const char *dictionary, const char *acousticModel, const char *triphoneList, const char *configFile, const char *userDictionary) { /* reset */ clear(); m_mmdagent = mmdagent; m_languageModel = MMDAgent_strdup(languageModel); m_dictionary = MMDAgent_strdup(dictionary); m_acousticModel = MMDAgent_strdup(acousticModel); m_triphoneList = MMDAgent_strdup(triphoneList); m_configFile = MMDAgent_strdup(configFile); m_userDictionary = MMDAgent_strdup(userDictionary); if(m_mmdagent == NULL || m_languageModel == NULL || m_dictionary == NULL || m_acousticModel == NULL || m_triphoneList == NULL || m_configFile == NULL) { clear(); return; } /* create recognition thread */ glfwInit(); m_thread = glfwCreateThread(mainThread, this); if(m_thread < 0) { clear(); return; } }
/* Open_JTalk_Manager::loadAndStart: load and start thread */ void Open_JTalk_Manager::loadAndStart(MMDAgent *mmdagent, const char *dicDir, const char *config) { clear(); m_mmdagent = mmdagent; m_dicDir = MMDAgent_strdup(dicDir); m_config = MMDAgent_strdup(config); if(m_mmdagent == NULL || m_dicDir == NULL || m_config == NULL) { clear(); return; } glfwInit(); m_mutex = glfwCreateMutex(); m_cond = glfwCreateCond(); m_thread = glfwCreateThread(mainThread, this); if(m_mutex == NULL || m_cond == NULL || m_thread < 0) { clear(); return; } }
/* 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::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); }
/* Open_JTalk_EventQueue_dequeue: dequeue */ static void Open_JTalk_EventQueue_dequeue(Open_JTalk_EventQueue *q, char **str) { Open_JTalk_Event *tmp; if (q->head == NULL) { *str = NULL; return; } *str = MMDAgent_strdup(q->head->event); tmp = q->head->next; Open_JTalk_Event_clear(q->head); free(q->head); q->head = tmp; if (tmp == NULL) q->tail = NULL; }
/* 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); } }
/* extAppStart: load FST and start thread */ EXPORT void extAppStart(MMDAgent *mmdagent) { char *buf; int len; setlocale(LC_CTYPE, "japanese"); buf = MMDAgent_strdup(mmdagent->getConfigFileName()); len = MMDAgent_strlen(buf); if (len > 4) { buf[len - 4] = '.'; buf[len - 3] = 'f'; buf[len - 2] = 's'; buf[len - 1] = 't'; vimanager_thread.loadAndStart(mmdagent, buf); } if(buf) free(buf); enable = true; enable_log = false; mmdagent->sendMessage(MMDAGENT_EVENT_PLUGINENABLE, "%s", PLUGINVIMANAGER_NAME); }
/* InputArguments_initialize: initialize input arguments */ void InputArguments_initialize(InputArguments *ia, const char *str) { int i, j, idx1, idx2; char buff1[MMDAGENT_MAXBUFLEN]; char buff2[MMDAGENT_MAXBUFLEN]; /* get number of arguments */ ia->size = countArgs(str, VIMANAGER_SEPARATOR1); if(ia->size <= 0) { ia->size = 0; ia->args = NULL; ia->argc = NULL; return; } ia->argc = (int *) malloc(ia->size * sizeof(int)); ia->args = (char ***) malloc(ia->size * sizeof(char **)); /* get event arguments */ idx1 = 0; for(i = 0; i < ia->size; i++) { getArgFromString(str, &idx1, buff1, VIMANAGER_SEPARATOR1); ia->argc[i] = countArgs(buff1, VIMANAGER_SEPARATOR2); if(ia->argc[i] <= 0) { ia->args[i] = NULL; } else { ia->args[i] = (char **) malloc(ia->argc[i] * sizeof(char *)); idx2 = 0; for(j = 0; j < ia->argc[i]; j++) { getArgFromString(buff1, &idx2, buff2, VIMANAGER_SEPARATOR2); ia->args[i][j] = MMDAgent_strdup(buff2); } } } }
/* PMDObject::load: load model */ bool PMDObject::load(const char *fileName, const char *alias, btVector3 *offsetPos, btQuaternion *offsetRot, bool forcedPosition, PMDBone *assignBone, PMDObject *assignObject, BulletPhysics *bullet, SystemTexture *systex, LipSync *sysLipSync, bool useCartoonRendering, float cartoonEdgeWidth, btVector3 *light, float commentFrame) { int i; int len; char *buf; LipSync *lip; if (fileName == NULL || alias == NULL) return false; /* apply given parameters */ m_assignTo = assignObject; m_baseBone = assignBone; if (forcedPosition) { /* set offset by given parameters */ if (offsetPos) m_offsetPos = (*offsetPos); if (offsetRot) m_offsetRot = (*offsetRot); m_pmd.getRootBone()->setOffset(&m_offsetPos); m_pmd.getRootBone()->update(); } else { /* set offset by root bone */ m_pmd.getRootBone()->getOffset(&m_offsetPos); } /* copy absolute position flag */ for (i = 0; i < 3; i++) m_absPosFlag[i] = false; /* copy toon rendering flag */ m_useCartoonRendering = useCartoonRendering; /* copy flag for motion file drop or all motion */ if(assignBone || assignObject) m_allowMotionFileDrop = false; else m_allowMotionFileDrop = true; /* save position when position is fixed */ if (m_baseBone) m_origBasePos = m_baseBone->getTransform()->getOrigin(); /* set alpha frame */ m_alphaAppearFrame = PMDOBJECT_ALPHAFRAME; m_alphaDisappearFrame = 0.0; /* set comment frame */ m_displayCommentFrame = commentFrame; /* load model */ if (m_pmd.load(fileName, bullet, systex) == false) { clear(); return false; } /* set toon rendering flag */ m_pmd.setToonFlag(useCartoonRendering); /* set edge width */ m_pmd.setEdgeThin(cartoonEdgeWidth); /* load lip sync */ m_globalLipSync = sysLipSync; if(m_localLipSync != NULL) delete m_localLipSync; m_localLipSync = NULL; lip = new LipSync(); len = MMDAgent_strlen(fileName); if(len < 5) { delete lip; } else { buf = MMDAgent_strdup(fileName); buf[len - 4] = '.'; buf[len - 3] = 'l'; buf[len - 2] = 'i'; buf[len - 1] = 'p'; if(lip->load(buf) == true) { m_localLipSync = lip; } else delete lip; if(buf) free(buf); } /* set alias */ setAlias(alias); /* reset */ setLightForToon(light); m_moveSpeed = -1.0f; m_spinSpeed = -1.0f; /* set temporarily all body to Kinematic */ /* this is fixed at first simulation */ skipNextSimulation(); /* enable */ m_isEnable = true; return true; }
/* 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); }
/* LipSync::load: initialize and load lip setting */ bool LipSync::load(const char *file) { int i, j; FILE *fp; int len; char buff[LIPSYNC_MAXBUFLEN]; bool err = false; fp = MMDAgent_fopen(file, "r"); if(fp == NULL) return false; /* number of expression */ len = MMDAgent_fgettoken(fp, buff); if(len <= 0) { fclose(fp); return false; } m_numMotion = MMDAgent_str2int(buff); if(m_numMotion <= 0) { fclose(fp); clear(); return false; } /* motion name */ m_motion = (char **) malloc(sizeof(char *) * m_numMotion); for(i = 0; i < m_numMotion; i++) { len = MMDAgent_fgettoken(fp, buff); if(len <= 0) err = true; m_motion[i] = MMDAgent_strdup(buff); } if(err == true) { fclose(fp); clear(); return false; } /* number of phone */ len = MMDAgent_fgettoken(fp, buff); if(len <= 0) { fclose(fp); clear(); return false; } m_numPhone = MMDAgent_str2int(buff); if(m_numPhone <= 0) { fclose(fp); clear(); return false; } /* phone name, type, and blend rate */ m_phone = (char **) malloc(sizeof(char *) * m_numPhone); m_blendRate = (float **) malloc(sizeof(float *) * m_numPhone); for(i = 0; i < m_numPhone; i++) { len = MMDAgent_fgettoken(fp, buff); if(len <= 0) err = true; m_phone[i] = MMDAgent_strdup(buff); m_blendRate[i] = (float *) malloc(sizeof(float) * m_numMotion); for(j = 0; j < m_numMotion; j++) { len = MMDAgent_fgettoken(fp, buff); if(len <= 0) err = true; m_blendRate[i][j] = MMDAgent_str2float(buff); if(m_blendRate[i][j] < 0.0f) err = true; } } if(err == true) { fclose(fp); clear(); return false; } fclose(fp); return true; }
/* 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; }
/* MessageLink_initialize: initialize message */ static void MessageLink_initialize(MessageLink *l, const char *type, const char *value) { l->type = MMDAgent_strdup(type); l->value = MMDAgent_strdup(value); l->next = NULL; }
/* 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; } } } }