/* ----------------------------------------------------------------------------- This source file is part of OpenSpace3D For the latest info, see http://www.openspace3d.com Copyright (c) 2012 I-maginer This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA, or go to http://www.gnu.org/copyleft/lesser.txt ----------------------------------------------------------------------------- */ struct PlugMoho = [ MOHO_inst : PInstance, MOHO_sDirpath : S, MOHO_source : SO3_OBJECT, MOHO_fAttenuation : F, MOHO_iVolume : I, MOHO_fPitch : F, MOHO_tCone : [I I I], MOHO_lVisemes : [[I S] r1], // Time / viseme for the moho file that is currently played MOHO_sCurrentFile : S, MOHO_currentSound : ObjAudio, MOHO_fTotalFrameTime : F, MOHO_fLastFrameTime : F, MOHO_iCurrentPos : I ]mkPlugMoho;; fun stopTimer(mohostr, forcesoundstop)= SendPluginEvent mohostr.MOHO_inst "Viseme" "rest" nil; setPluginInstanceCbScenePreRender mohostr.MOHO_inst nil; set mohostr.MOHO_fTotalFrameTime = 0.0; set mohostr.MOHO_fLastFrameTime = 0.0; set mohostr.MOHO_iCurrentPos = 0; set mohostr.MOHO_lVisemes = nil; if forcesoundstop == 0 then nil else { _DSAudio mohostr.MOHO_currentSound; set mohostr.MOHO_currentSound = nil; SendPluginEvent mohostr.MOHO_inst "End" nil nil; }; 0;; fun cbUpdateVisems(inst, viewstr, etime, mohostr)= // Compute frame time let if etime <= 1000 then 1000 else etime -> etime in set mohostr.MOHO_fTotalFrameTime = mohostr.MOHO_fTotalFrameTime +. ((itof (etime / 1000)) *. 24.0 /. 1000.0 *. mohostr.MOHO_fPitch); // New moho frame? if mohostr.MOHO_fTotalFrameTime -. mohostr.MOHO_fLastFrameTime <. 1.0 then nil else { let (ftoi (absf mohostr.MOHO_fTotalFrameTime)) -> currentPos in let nth_list mohostr.MOHO_lVisemes ((sizelist mohostr.MOHO_lVisemes) - 1) -> [lastVisemPos _] in if (currentPos <= lastVisemPos) then { let switch mohostr.MOHO_lVisemes currentPos -> viseme in if (viseme == nil) then nil else { SendPluginEvent mohostr.MOHO_inst "Viseme" viseme nil; set mohostr.MOHO_iCurrentPos = currentPos; set mohostr.MOHO_fLastFrameTime = mohostr.MOHO_fTotalFrameTime; }; 0; } else { stopTimer mohostr 0; // Let the sound finish! 0; }; }; // Update 3D sound position if mohostr.MOHO_source == nil then nil else { let SO3ObjectGetGlobalPosition mohostr.MOHO_source -> pos in let SO3ObjectGetDerivedDirectionAxis mohostr.MOHO_source [0.0 0.0 1.0] -> dir in _AudioSetPosition mohostr.MOHO_currentSound pos dir; }; 0;; fun startTimer(mohostr)= setPluginInstanceCbScenePreRender mohostr.MOHO_inst mkfun4 @cbUpdateVisems mohostr; set mohostr.MOHO_fTotalFrameTime = 0.0; set mohostr.MOHO_fLastFrameTime = 0.0; set mohostr.MOHO_iCurrentPos = 0; 0;; fun initializeFile(mohostr, file)= if !strcmp file mohostr.MOHO_sCurrentFile then nil else { let _getpack _checkpack strcatn mohostr.MOHO_sDirpath::"/"::file::".dat"::nil -> cont in let strextr cont -> lcont in let sizelist lcont -> size in { set mohostr.MOHO_lVisemes = nil; let size -> i in while (i > 0) do { let nth_list lcont i -> [t [visem _]] in let atoi t -> timeframe in if (timeframe == nil) || (visem == nil) then nil else set mohostr.MOHO_lVisemes = [timeframe visem]::mohostr.MOHO_lVisemes; set i = i - 1; }; }; }; 0;; fun cbEndSound(snd, mohostr)= stopTimer mohostr 1; 0;; fun cbPlay(inst, from, action, param, reply, mohostr)= if param == nil then nil else { stopTimer mohostr 1; initializeFile mohostr param; if (mohostr.MOHO_lVisemes == nil) then { setPluginInstanceCbScenePreRender inst nil; 0; } else { // Load sound file let strcatn mohostr.MOHO_sDirpath::"/"::param::nil -> basename in let _checkpack strcat basename ".mp3" -> soundpath in let if (soundpath == nil) then _checkpack strcat basename ".wav" else soundpath -> soundpath in let if (soundpath == nil) then _checkpack strcat basename ".ogg" else soundpath -> soundpath in { set mohostr.MOHO_currentSound = _CRAudio _channel (strcat (getPluginInstanceName inst) "_sound") soundpath 1; _CBAudioEnd mohostr.MOHO_currentSound @cbEndSound mohostr; _AudioSetVolume mohostr.MOHO_currentSound mohostr.MOHO_iVolume; _AudioSetPitch mohostr.MOHO_currentSound mohostr.MOHO_fPitch; // 2D sound or 3D sound? if mohostr.MOHO_source == nil then { _AudioPlay mohostr.MOHO_currentSound 0; } else { let SO3ObjectGetGlobalPosition mohostr.MOHO_source -> pos in let SO3ObjectGetDerivedDirectionAxis mohostr.MOHO_source [0.0 0.0 1.0] -> dir in let mohostr.MOHO_tCone -> [innerangle outerangle outervol] in { _AudioSetCone mohostr.MOHO_currentSound innerangle outerangle outervol; _AudioSetPosition mohostr.MOHO_currentSound pos dir; _AudioPlay3d mohostr.MOHO_currentSound mohostr.MOHO_fAttenuation 0; }; }; }; startTimer mohostr; 0; }; }; 0;; fun cbStop(inst, from, action, param, reply, mohostr)= stopTimer mohostr 1; 0;; fun deleteOb(inst, mohostr)= stopTimer mohostr 1; 0;; fun newOb(inst)= let (getPluginInstanceParam inst "path") -> path in let if path == nil then "" else path -> path in let (getPluginInstanceParam inst "source") -> objname in let atof (getPluginInstanceParam inst "attenuation") -> attenuation in let if attenuation == nil then 1.0 else attenuation -> attenuation in let atoi (getPluginInstanceParam inst "volume") -> ivolume in let if ivolume == nil then 100 else ivolume -> ivolume in let atof (getPluginInstanceParam inst "pitch") -> pitch in let if pitch == nil then 1.0 else pitch -> pitch in let atoi (getPluginInstanceParam inst "innerangle") -> innerangle in let if innerangle == nil then 360 else innerangle -> innerangle in let atoi (getPluginInstanceParam inst "outerangle") -> outerangle in let if outerangle == nil then 360 else outerangle -> outerangle in let atoi (getPluginInstanceParam inst "outervol") -> outervol in let if outervol == nil then 0 else outervol -> outervol in let V3DgetObjectByName c3dXsession objname -> object in let mkPlugMoho [inst path object attenuation ivolume pitch [innerangle outerangle outervol] nil nil nil nil nil nil] -> mohostr in { PluginRegisterAction inst "Play" mkfun6 @cbPlay mohostr; PluginRegisterAction inst "Stop" mkfun6 @cbStop mohostr; setPluginInstanceCbDel inst mkfun2 @deleteOb mohostr; }; 0;; fun IniPlug(file)= PlugRegister @newOb nil; setPluginEditor @dynamicedit; 0;;