├── src ├── worldHandlerSetting.txt ├── worldManipulatorBase.txt ├── hz2kHzWH.m ├── setting.jpg ├── hz2erbWH.m ├── worldHandler.mlapp ├── morphContinuumGen.mlapp ├── morphingAligner.mlapp ├── worldManipulator.mlapp ├── morphingSoundGenerator.mlapp ├── pitchWrapper.m ├── threeItemMorpherGeneralUI.mlapp ├── worldSynthMod20231127T161253d.mat ├── worldSynthMod20231127T161253d.wav ├── worldHandlerBase.txt ├── kHz2hzWH.m ├── erb2hzWH.m ├── lineButtonUpFcn.m ├── pitchPlginHarvest.m ├── testPrime.m ├── lineCallback.m ├── twoWayMultiAttributeMorphing.m ├── wordTV2WmorphingEngineRev.m └── generalizedTCmorphing.m ├── .gitattributes ├── README.md └── LICENSE /src/worldHandlerSetting.txt: -------------------------------------------------------------------------------- 1 | f0_floor 40 2 | f0_ceil 800 3 | -------------------------------------------------------------------------------- /src/worldManipulatorBase.txt: -------------------------------------------------------------------------------- 1 | Position 153 273 1273 736 2 | -------------------------------------------------------------------------------- /src/hz2kHzWH.m: -------------------------------------------------------------------------------- 1 | function kHz = hz2kHzWH(hz) 2 | %erb = hz; 3 | kHz = hz/1000; 4 | end -------------------------------------------------------------------------------- /src/setting.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HidekiKawahara/worldGUItools/HEAD/src/setting.jpg -------------------------------------------------------------------------------- /src/hz2erbWH.m: -------------------------------------------------------------------------------- 1 | function erb = hz2erbWH(hz) 2 | %erb = hz; 3 | erb = 21.4*log10(0.00437*hz+1); 4 | end -------------------------------------------------------------------------------- /src/worldHandler.mlapp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HidekiKawahara/worldGUItools/HEAD/src/worldHandler.mlapp -------------------------------------------------------------------------------- /src/morphContinuumGen.mlapp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HidekiKawahara/worldGUItools/HEAD/src/morphContinuumGen.mlapp -------------------------------------------------------------------------------- /src/morphingAligner.mlapp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HidekiKawahara/worldGUItools/HEAD/src/morphingAligner.mlapp -------------------------------------------------------------------------------- /src/worldManipulator.mlapp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HidekiKawahara/worldGUItools/HEAD/src/worldManipulator.mlapp -------------------------------------------------------------------------------- /src/morphingSoundGenerator.mlapp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HidekiKawahara/worldGUItools/HEAD/src/morphingSoundGenerator.mlapp -------------------------------------------------------------------------------- /src/pitchWrapper.m: -------------------------------------------------------------------------------- 1 | function output = pitchWrapper(x, fs, options, pitchExtractor) 2 | output = pitchExtractor(x, fs, options); 3 | end -------------------------------------------------------------------------------- /src/threeItemMorpherGeneralUI.mlapp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HidekiKawahara/worldGUItools/HEAD/src/threeItemMorpherGeneralUI.mlapp -------------------------------------------------------------------------------- /src/worldSynthMod20231127T161253d.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HidekiKawahara/worldGUItools/HEAD/src/worldSynthMod20231127T161253d.mat -------------------------------------------------------------------------------- /src/worldSynthMod20231127T161253d.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HidekiKawahara/worldGUItools/HEAD/src/worldSynthMod20231127T161253d.wav -------------------------------------------------------------------------------- /src/worldHandlerBase.txt: -------------------------------------------------------------------------------- 1 | SettingFilePath /Users/kawahara/m-file/miraikanf/samples/morphedSound 2 | Position 184 277 1360 700 3 | Extension off 4 | -------------------------------------------------------------------------------- /src/kHz2hzWH.m: -------------------------------------------------------------------------------- 1 | function hz = kHz2hzWH(kHz) 2 | %erb = 21.4*log10(0.00437*hz+1); 3 | %erb/21.4 = log10(0.00437*hz+1); 4 | %10^(erb/21.4) = 0.00437*hz+1; 5 | %10^(erb/21.4)-1 = 0.00437*hz; 6 | hz = kHz*1000; 7 | %hz = erb; 8 | end -------------------------------------------------------------------------------- /src/erb2hzWH.m: -------------------------------------------------------------------------------- 1 | function hz = erb2hzWH(erb) 2 | %erb = 21.4*log10(0.00437*hz+1); 3 | %erb/21.4 = log10(0.00437*hz+1); 4 | %10^(erb/21.4) = 0.00437*hz+1; 5 | %10^(erb/21.4)-1 = 0.00437*hz; 6 | hz = (10.^(erb/21.4)-1)/0.00437; 7 | %hz = erb; 8 | end -------------------------------------------------------------------------------- /src/lineButtonUpFcn.m: -------------------------------------------------------------------------------- 1 | function lineButtonUpFcn(src, ~) 2 | %get(src) 3 | set(src, 'WindowButtonUpFcn', '', 'WindowButtonMotionFcn', ''); 4 | lineHandle = get(src, 'UserData'); 5 | lineHandle.LineWidth = 0.5; 6 | lineStatus = get(lineHandle,'UserData'); 7 | lineStatus.replayHandle.Enable = 'off'; 8 | end -------------------------------------------------------------------------------- /src/pitchPlginHarvest.m: -------------------------------------------------------------------------------- 1 | function output = pitchPlginHarvest(x, fs, options) 2 | %Plugin_Role fundamental_frequency 3 | %Plugin_Name Harvest 4 | output = Harvest(x, fs, options); 5 | [~, nTime] = size(output.f0_candidates); 6 | output.candidatePositions = (0:nTime-1)'/1000; 7 | output.foExtractor = "Harvest"; 8 | end -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.fig binary 2 | *.mat binary 3 | *.mdl binary diff merge=mlAutoMerge 4 | *.mdlp binary 5 | *.mexa64 binary 6 | *.mexw64 binary 7 | *.mexmaci64 binary 8 | *.mlapp binary 9 | *.mldatx binary 10 | *.mlproj binary 11 | *.mlx binary 12 | *.p binary 13 | *.sfx binary 14 | *.sldd binary 15 | *.slreqx binary merge=mlAutoMerge 16 | *.slmx binary merge=mlAutoMerge 17 | *.sltx binary 18 | *.slxc binary 19 | *.slx binary merge=mlAutoMerge 20 | *.slxp binary 21 | 22 | ## Other common binary file types 23 | *.docx binary 24 | *.exe binary 25 | *.jpg binary 26 | *.pdf binary 27 | *.png binary 28 | *.xlsx binary 29 | -------------------------------------------------------------------------------- /src/testPrime.m: -------------------------------------------------------------------------------- 1 | %% test prime 2 | tic 3 | upperLimit = 10^5; 4 | n = upperLimit; 5 | buff = ones(n,1); 6 | buff(1) = 0; 7 | testLim = ceil(sqrt(n)); 8 | for ii = 2:testLim 9 | if buff(ii) == 1 10 | buff(ii * (2:n/ii)) = 0; 11 | end 12 | end 13 | idx = 1:n; 14 | xPrimes = idx(buff==1); 15 | toc 16 | sum(abs(xPrimes - primes(10^5))) 17 | %% 18 | ntest = 100; 19 | eTime = zeros(ntest,1); 20 | for ii = 1:ntest 21 | stmp = sum(1:rand(1,1)*1000000); 22 | stTic = tic; 23 | stmp = primes(10^5); 24 | eTime(ii) = toc(stTic); 25 | end 26 | figure; 27 | bar(sort(eTime));grid on 28 | ylabel("elapsed time (s)") -------------------------------------------------------------------------------- /src/lineCallback.m: -------------------------------------------------------------------------------- 1 | function lineCallback(src, ~) 2 | lineStatus = get(src,'UserData'); 3 | currentAxisToolBar = lineStatus.axisToolbar; 4 | onCount = 0; 5 | for ii = 1:length(currentAxisToolBar.Children)-1 6 | onCount = onCount + currentAxisToolBar.Children(ii).Value; 7 | end 8 | if onCount == 0 9 | src.LineWidth = 3; 10 | axisHandle = src.Parent; 11 | tmp = axisHandle.Parent; 12 | switch tmp.Type 13 | case 'figure' 14 | figureHandle = tmp; 15 | otherwise 16 | tmp1 = tmp.Parent; 17 | figureHandle = tmp1.Parent; 18 | end 19 | set(figureHandle, 'WindowButtonUpFcn', @lineButtonUpFcn, ... 20 | 'WindowButtonMotionFcn', @lineMotionFunction); 21 | set(figureHandle, 'UserData', src); 22 | lineStatus.InitialYData = src.YData; 23 | lineStatus.lastPoint = axisHandle.CurrentPoint; 24 | figureHandle.Tag = 'modified'; 25 | set(src,'UserData', lineStatus); 26 | end 27 | end -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # WORLD GUI tools for explorational research/education of speech science and technology 2 | GUI tools for WORLD vocoder. This tool uses MATLAB version of WORLD. You can get it from below. 3 | [Link to WORLD matlab version dwonload page](http://www.isc.meiji.ac.jp/~mmorise/world/english/index.html) 4 | 5 | ## References 6 | 7 | ### GUI tools: worldHandler, and worldManipulator 8 | 9 | Kawahara, H., & Morise, M. (2024). Interactive tools for making vocoder-based signal processing accessible: Flexible manipulation of speech attributes for explorational research and education. Acoustical Science and Technology, 45(1), 48-51. 10 | [DOI: 10.1250/ast.e23.52](https://doi.org/10.1250/ast.e23.52) 11 | 12 | ### GUI tools: morphingAligner, morphingSoundGenerator, threeItemMorpherGeneralUI, and morphContinuumGen 13 | 14 | Kawahara, H., & Morise, M. (2024). Interactive tools for making temporally variable, multiple-attributes, and multiple-instances morphing accessible: Flexible manipulation of divergent speech instances for explorational research and education. arXiv preprint arXiv:2404.13418. 15 | [Link to arXiV](https://arxiv.org/abs/2404.13418) (Accepted for Acoustical Science and Technology) 16 | 17 | ### World GUI tools on YouTube channel 18 | 19 | [Link to YouTube channel on World GUI tools playlist](https://www.youtube.com/playlist?list=PLqr7NXdG4BylcF9QIqkT7zGgEUh_vdhq_) 20 | 21 | ## MATLAB application 22 | ### Analysis ans basic synthesis 23 | worldHandler.mlx provide interactive control of basic copy-synth workflow. Type 24 | worldHandler 25 | in the MATLAB command window 26 | 27 | 28 | 29 | https://github.com/HidekiKawahara/worldGUItools/assets/6383109/a6ed9687-d264-46f0-81cd-98b8a13084f9 30 | 31 | 32 | 33 | 34 | 35 | [worldHandler link to longer version](https://youtu.be/Wmesva37nZs) 36 | 37 | ### Parameter modification and synthesis 38 | worldManipulator.mlx provide interactive parameter manipulation and synthesis. Type 39 | worldManipulator 40 | in the MATLAB command window 41 | 42 | 43 | 44 | https://github.com/HidekiKawahara/worldGUItools/assets/6383109/a8985652-3225-4cd8-8260-602fea100331 45 | 46 | 47 | 48 | ### Preparation for morphing and interactive check 49 | wordTV2WmorphingEngineRev.mlx provides interactive preparation for extended morphing and check. Type 50 | wordTV2WmorphingEngineRev 51 | in the MATLAB command window 52 | 53 | 54 | 55 | https://github.com/HidekiKawahara/worldGUItools/assets/6383109/5d57194a-563b-4485-8140-696878f032db 56 | 57 | [wordTV2WmorphingEngineRev longer version with Japanese caption](https://youtu.be/QMAmoNbLlCQ) 58 | 59 | 60 | ### Stimulus continuum generation using generation tool 61 | morphingSoundGenerator.mlx assists stimulus continuum generation.. Type 62 | morphingSoundGenerator 63 | in the MATLAB command window 64 | 65 | 66 | 67 | https://github.com/HidekiKawahara/worldGUItools/assets/6383109/808a5cda-8913-466a-895a-d8d3ab533a1c 68 | 69 | [morphingSoundGenerator longer version with Japanese caption](https://youtu.be/5hHatrPrjuY) 70 | ### note 71 | Added numerical input for time stretching factor in worldManipulator. 72 | 73 | Fixed minor error in wordTV2WmorphingEngineRev 74 | 75 | Updated function, "generalizedTCmorphing" for compatibility. 76 | 77 | Added missing function, "generalizedTCmorphing" 78 | 79 | Tentatively updated using 25/May/2024 version. We will review and update code and usability by the end of May 2024. 80 | 81 | -------------------------------------------------------------------------------- /src/twoWayMultiAttributeMorphing.m: -------------------------------------------------------------------------------- 1 | function output = twoWayMultiAttributeMorphing(mObjectEntity1, mObjectEntity2, morphRate) 2 | % output = twoWayMultiAttributeMorphing(mObjectEntity1, mObjectEntity2, morphRate) 3 | % Two way multi attribute morphing function 4 | % 5 | % Arguments 6 | % mObjectEntity1 : morphing object identifier (structure or string) 7 | % mObjectEntity2 : morphing object identifier (structure or string) 8 | % morphRate : morphing rate definition (scalar or structure) 9 | % note: 10 | % morphing object structure consists of following fields 11 | % worldParameter : structure consisting of WORLD parameter 12 | % timeAnchor : vector defining time anchor position 13 | % timeFreqAnchor : matrix defining time-frequency position 14 | % morphing object identifier string is the fullpath to the .mat file 15 | % consisting of a morphing object 16 | % When morphRate is a structure, it consists of following fields 17 | % tx : time axis morphing rate 18 | % fx : frequency axis morphing rate 19 | % fo : fundamental frequency morphing rate 20 | % sl : spectrum level morphing rate 21 | % ap : aperiodicity morphing rate 22 | % morphing rate defines contributions of two entities. 23 | % morphing rate 0 uses parameters in mObjectEntity1 only 24 | % morphing rate 1 uses parameters in mObjectEntity2 only 25 | % 26 | % Output 27 | % output : structure consitsing of following fields 28 | % elapsedTime : elapsed time 29 | % morphOutStr : morphed WORLD parameter 30 | % xSynth : vector consisting of the morphed sound 31 | % samplingFrequency : in Hz 32 | 33 | %-- Check first and second input arguments 34 | if isstruct(mObjectEntity1) 35 | mObject1 = mObjectEntity1; 36 | elseif isstring(mObjectEntity1) 37 | try 38 | mObject1 = load(mObjectEntity1); 39 | if ~isstruct(mObject1) 40 | disp("Input file should consist of morphing object structure.") 41 | help("twoWayMultiAttributeMorphing"); 42 | output = []; 43 | return; 44 | end 45 | catch 46 | disp("file " + mObjectEntity1 + " does not exist") 47 | help("twoWayMultiAttributeMorphing"); 48 | output = []; 49 | return; 50 | end 51 | else 52 | help("twoWayMultiAttributeMorphing"); 53 | output = []; 54 | return; 55 | end 56 | if isstruct(mObjectEntity2) 57 | mObject2 = mObjectEntity2; 58 | elseif isstring(mObjectEntity2) 59 | try 60 | mObject2 = load(mObjectEntity2); 61 | if ~isstruct(mObject2) 62 | disp("Input file should consist of morphing object structure.") 63 | help("twoWayMultiAttributeMorphing"); 64 | output = []; 65 | return; 66 | end 67 | catch 68 | disp("file " + mObjectEntity2 + " does not exist") 69 | help("twoWayMultiAttributeMorphing"); 70 | output = []; 71 | return; 72 | end 73 | else 74 | help("twoWayMultiAttributeMorphing"); 75 | output = []; 76 | return; 77 | end 78 | %-- Initialize parameters 79 | startTic = tic; 80 | displayOn = 0; 81 | vtl_ratio = 1; 82 | worldPRef = mObject1.worldParameter; 83 | worldPTgt = mObject2.worldParameter; 84 | 85 | anchStr = struct; 86 | anchStr.timeAnchorReference = mObject1.timeAnchor; 87 | anchStr.timeAnchorTarget = mObject2.timeAnchor; 88 | anchStr.timeFreqAnchorReference = mObject1.timeFreqAnchor; 89 | anchStr.timeFreqAnchorTarget = mObject2.timeFreqAnchor; 90 | %-- Check morphing object compatibility 91 | 92 | %-- Morphing parameters and synthesize morphed sound 93 | morphOutStr = ... 94 | wordTV2WmorphingEngineRev(worldPRef, worldPTgt, anchStr, morphRate, vtl_ratio, displayOn); 95 | xSynth = Synthesis(morphOutStr.source_parameter, morphOutStr.spectrum_parameter); 96 | 97 | %-- Copy to output structure 98 | output.elapsedTime = toc(startTic); 99 | output.morphOutStr = morphOutStr; 100 | output.xSynth = xSynth; 101 | output.samplingFrequency = worldPRef.samplingFrequency; -------------------------------------------------------------------------------- /src/wordTV2WmorphingEngineRev.m: -------------------------------------------------------------------------------- 1 | function output = wordTV2WmorphingEngineRev(worldPRef, worldPTgt, anchStr, mRate, vtl_ratio, displayOn) 2 | strtTic = tic; 3 | if isstruct(mRate) 4 | mStr = mRate; 5 | else 6 | mStr.tx = mRate; 7 | mStr.fx = mRate; 8 | mStr.fo = mRate; 9 | mStr.sl = mRate; 10 | mStr.ap = mRate; 11 | end 12 | %% 13 | tFrameRef = worldPRef.source_parameter.temporal_positions; 14 | tFrameTgt = worldPTgt.source_parameter.temporal_positions; 15 | tAnchRef = [0 anchStr.timeAnchorReference' tFrameRef(end)]; 16 | tAnchTgt = [0 anchStr.timeAnchorTarget' tFrameTgt(end)]; 17 | ftAnchorRef = anchStr.timeFreqAnchorReference; 18 | ftAnchorTgt = anchStr.timeFreqAnchorTarget; 19 | % 20 | tAnchMrph = [0 cumsum(real(exp((1-mStr.tx)*log(diff(tAnchRef))+mStr.tx*log(diff(tAnchTgt)))))]; 21 | deltaT = tFrameRef(2)-tFrameRef(1); 22 | tFrameMorph = 0:deltaT:tAnchMrph(end); 23 | tFrameMorphOnRef = interp1(tAnchMrph,tAnchRef,tFrameMorph,"linear","extrap"); 24 | tFrameMorphOnTgt = interp1(tAnchMrph,tAnchTgt,tFrameMorph,"linear","extrap"); 25 | 26 | if displayOn 27 | figure; 28 | plot(tFrameMorph,tFrameMorphOnRef);grid on 29 | hold all 30 | plot(tFrameMorph,tFrameMorphOnTgt); 31 | end 32 | % fo 33 | f0Ref = worldPRef.f0_original; 34 | f0Tgt = worldPTgt.f0_original; 35 | f0RefOnMrh = interp1(tFrameRef,f0Ref,tFrameMorphOnRef,"linear","extrap"); 36 | f0TgtOnMrh = interp1(tFrameTgt,f0Tgt,tFrameMorphOnTgt,"linear","extrap"); 37 | f0_original = exp((1-mStr.fo)*log(f0RefOnMrh) + mStr.fo*log(f0TgtOnMrh)); 38 | % vuv 39 | vuvRef = worldPRef.source_parameter.vuv; 40 | vuvTgt = worldPTgt.source_parameter.vuv; 41 | vuvRefOnMrh = interp1(tFrameRef,vuvRef,tFrameMorphOnRef,"linear","extrap"); 42 | vuvTgtOnMrh = interp1(tFrameTgt,vuvTgt,tFrameMorphOnTgt,"linear","extrap"); 43 | vuv = (1-mStr.fo)*vuvRefOnMrh + mStr.fo*vuvTgtOnMrh; 44 | vuv = double(vuv > 0.3); 45 | vuv = vuv*0 + 1; % all voiced 46 | % 47 | if displayOn 48 | figure; 49 | plot(tFrameRef,f0Ref);grid on 50 | hold all 51 | plot(tFrameTgt,f0Tgt);grid on 52 | plot(tFrameMorph,f0RefOnMrh,"LineWidth",3) 53 | plot(tFrameMorph,f0TgtOnMrh,"LineWidth",3) 54 | plot(tFrameMorph,f0_original,"k","LineWidth",3) 55 | end 56 | % spectrum 57 | fs = worldPRef.spectrum_parameter.fs; 58 | spectrogramRef = real(10*log10(worldPRef.spectrum_parameter.spectrogram)); 59 | spectrogramTgt = real(10*log10(worldPTgt.spectrum_parameter.spectrogram)); 60 | fxRef = (0:size(spectrogramRef,1)-1)'/size(spectrogramRef,1)*fs/2; 61 | fxTgT = (0:size(spectrogramRef,1)-1)'/size(spectrogramRef,1)*fs/2; 62 | fxMorphR = fxRef/((1-mStr.fx) + mStr.fx*vtl_ratio); 63 | fxMorphT = fxTgT/((1-mStr.fx) + mStr.fx/vtl_ratio); 64 | % 65 | nAnch = size(ftAnchorRef,2); 66 | fxMorphMapRef = zeros(size(spectrogramRef,1),nAnch+2); 67 | fxMorphMapRef(:,1) = fxMorphR; 68 | fxMorphMapRef(:,end) = fxMorphR; 69 | fxMorphMapTgt = zeros(size(spectrogramRef,1),nAnch+2); 70 | fxMorphMapTgt(:,1) = fxMorphT; 71 | fxMorphMapTgt(:,end) = fxMorphT; 72 | for ii = 1:nAnch 73 | nfC = sum(ftAnchorRef(:,ii)>0); 74 | if nfC > 0 75 | tmpLogFanchRef = log([1 ftAnchorRef(1:nfC, ii)' fs/2]); 76 | tmpLogFanchTgt = log([1 ftAnchorTgt(1:nfC, ii)' fs/2/vtl_ratio]); 77 | fAncMrph = exp(cumsum([log(1) real(exp((1-mStr.fx)*log(diff(tmpLogFanchRef)) ... 78 | +mStr.fx*log(diff(tmpLogFanchTgt))))])); 79 | %fxLinOnMrph = (0:size(spectrogramRef,1)-1)'/size(spectrogramRef,1)*fAncMrph(end); 80 | fxMrphOnTgt = interp1(exp(tmpLogFanchTgt),fAncMrph,fxRef, ... 81 | "linear","extrap"); 82 | fxMrphOnRef = interp1(exp(tmpLogFanchRef),fAncMrph,fxRef, ... 83 | "linear","extrap"); 84 | %[~, tRefIdx] = min(abs(anchStr.timeAnchorReference(ii)-tFrameRef)); 85 | fxMorphMapRef(:,ii+1) = fxMrphOnRef; 86 | %[~, tTgtIdx] = min(abs(anchStr.timeAnchorTarget(ii)-tFrameTgt)); 87 | fxMorphMapTgt(:,ii+1) = fxMrphOnTgt; 88 | else 89 | fxMorphMapRef(:,ii+1) = fxMorphR; 90 | fxMorphMapTgt(:,ii+1) = fxMorphT; 91 | end 92 | end 93 | % 94 | nFrameMorph = length(tFrameMorph); 95 | %specgramMorph = zeros(length(fxRef), nFrameMorph); 96 | %apMroph = zeros(length(fxRef), nFrameMorph); 97 | prevInd = 1; 98 | segHead = zeros(nAnch,1); 99 | segHead(1) = 1; 100 | for ii = 1:nFrameMorph 101 | if tFrameMorph(ii) > tAnchMrph(prevInd) 102 | prevInd = prevInd + 1; 103 | segHead(prevInd) = ii; 104 | end 105 | end 106 | % 107 | idxOnMorph = floor(tAnchMrph/deltaT)+1; 108 | %idxOnRef = floor(tAnchRef/deltaT)+1; 109 | %idxOnTgt = floor(tAnchTgt/deltaT)+1; 110 | % 111 | fxMorphMapRefIntrp = zeros(length(fxRef), nFrameMorph); 112 | fxMorphMapTgtIntrp = zeros(length(fxRef), nFrameMorph); 113 | fxMorphMapMixIntrp = zeros(length(fxRef), nFrameMorph); 114 | spectrogramRefOnTFMrh = zeros(length(fxRef), nFrameMorph); 115 | spectrogramTgtOnTFMrh = zeros(length(fxRef), nFrameMorph); 116 | spectrogramTgt(end,:) = spectrogramTgt(end-1,:); 117 | spectrogramRef(end,:) = spectrogramRef(end-1,:); 118 | spectrogramRefOnMrh = interp1(tFrameRef',spectrogramRef',tFrameMorphOnRef',"linear","extrap")'; 119 | spectrogramTgtOnMrh = interp1(tFrameTgt',spectrogramTgt',tFrameMorphOnTgt',"linear","extrap")'; 120 | spectrogramMixOnTFMrh = spectrogramTgtOnTFMrh * 0; 121 | aperiodicityRef = real(log(worldPRef.source_parameter.aperiodicity)); 122 | aperiodicityTgt = real(log(worldPTgt.source_parameter.aperiodicity)); 123 | aperiodicityRefOnMrh = interp1(tFrameRef',aperiodicityRef',tFrameMorphOnRef',"linear","extrap")'; 124 | aperiodicityTgtOnMrh = interp1(tFrameTgt',aperiodicityTgt',tFrameMorphOnTgt',"linear","extrap")'; 125 | aperiodicityRefOnTFMrh = zeros(length(fxRef), nFrameMorph); 126 | aperiodicityTgtOnTFMrh = zeros(length(fxRef), nFrameMorph); 127 | aperiodicityMixOnTFMrh = spectrogramTgtOnTFMrh * 0; 128 | for ii = 1:nAnch+1 129 | strtP = idxOnMorph(ii); 130 | if ii == nAnch 131 | endP = nFrameMorph; 132 | else 133 | endP = idxOnMorph(ii+1); 134 | end 135 | safeguard = cumsum(ones(length(fxMorphMapRefIntrp(:, 1)),1)*0.0001); 136 | % This is a quick and dirty fix. Practicall, OK. 137 | for jj = strtP:endP 138 | fractionV = (tFrameMorph(jj) - tFrameMorph(strtP)) ... 139 | /(tFrameMorph(endP)-tFrameMorph(strtP)); 140 | fxMorphMapRefIntrp(:, jj) = (1-fractionV) * fxMorphMapRef(:,ii) ... 141 | + fractionV * fxMorphMapRef(:,ii+1); 142 | fxMorphMapTgtIntrp(:, jj) = (1-fractionV) * fxMorphMapTgt(:,ii) ... 143 | + fractionV * fxMorphMapTgt(:,ii+1); 144 | fxMorphMapMixIntrp(:, jj) = (1-mStr.fx) * fxMorphMapRefIntrp(:, jj) ... 145 | + mStr.fx * fxMorphMapTgtIntrp(:, jj); 146 | %safeguard = ones(length(fxMorphMapRefIntrp(:, jj)),1); 147 | try 148 | spectrogramRefOnTFMrh(:, jj) = interp1(fxMorphMapRefIntrp(:, jj)+safeguard, ... 149 | spectrogramRefOnMrh(:, jj), fxRef, "linear","extrap"); 150 | spectrogramTgtOnTFMrh(:, jj) = interp1(fxMorphMapTgtIntrp(:, jj)+safeguard, ... 151 | spectrogramTgtOnMrh(:, jj), fxRef, "linear","extrap"); 152 | spectrogramMixOnTFMrh(:, jj) = (1-mStr.sl) * spectrogramRefOnTFMrh(:, jj) ... 153 | + mStr.sl * spectrogramTgtOnTFMrh(:, jj); 154 | aperiodicityRefOnTFMrh(:, jj) = interp1(fxMorphMapRefIntrp(:, jj)+safeguard, ... 155 | aperiodicityRefOnMrh(:, jj), fxRef, "linear","extrap"); 156 | aperiodicityTgtOnTFMrh(:, jj) = interp1(fxMorphMapTgtIntrp(:, jj)++safeguard, ... 157 | aperiodicityTgtOnMrh(:, jj), fxRef, "linear","extrap"); 158 | aperiodicityMixOnTFMrh(:, jj) = (1-mStr.ap) * aperiodicityRefOnTFMrh(:, jj) ... 159 | + mStr.ap * aperiodicityTgtOnTFMrh(:, jj); 160 | catch 161 | %keyboard; 162 | end 163 | end 164 | end 165 | %% 166 | spectrogram = 10.0 .^ (spectrogramMixOnTFMrh/10); 167 | %% aperiodicity 168 | aperiodicity = exp(aperiodicityMixOnTFMrh); 169 | %% modify aperiodicity 170 | originalAperiodicity = aperiodicity; 171 | f0_original(f0_original <= 0) = min(f0_original(f0_original > 30)); 172 | f0_original(isnan(f0_original)) = min(f0_original(f0_original > 30)); 173 | averageFo = mean(f0_original); 174 | fxTmp = fxRef(fxRef<3*averageFo); 175 | apShaper = ones(length(fxTmp),1); 176 | apShaper(1:length(fxTmp)) = 0.5*cos((fxTmp-averageFo)/averageFo/2*pi)+0.5; 177 | apShaper(fxTmp<=averageFo) = 1; 178 | apShaper = 10 .^ (-60*apShaper/10); 179 | for ii = 1:size(aperiodicity,2) 180 | aperiodicity(1:length(fxTmp),ii) = aperiodicity(1:length(fxTmp),ii) .* apShaper; 181 | end 182 | %% 183 | output.samplingFrequency = worldPRef.samplingFrequency; 184 | output.f0_original = f0_original; 185 | output.source_parameter.temporal_positions = tFrameMorph; 186 | output.source_parameter.f0 = f0_original .* vuv; 187 | output.spectrum_parameter.temporal_positions = tFrameMorph; 188 | output.spectrum_parameter.fs = worldPRef.samplingFrequency; 189 | output.source_parameter.vuv = vuv; 190 | output.spectrum_parameter.spectrogram = spectrogram; 191 | output.source_parameter.aperiodicity = aperiodicity; 192 | output.morphingRateStructure = mStr; 193 | %% 194 | output.elapsedTime = toc(strtTic); 195 | end -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /src/generalizedTCmorphing.m: -------------------------------------------------------------------------------- 1 | function output = generalizedTCmorphing(morphdBase,weightStr,dispOn) 2 | % output = generalizedTCmorphing(morphdBase,weightStr,dispOn) 3 | % generalized morphing function with temporally constant weights 4 | % 5 | % Argument 6 | % morphdBase: Structure variable with the following fields 7 | % morphStr : Structure variable consists of morphing objects 8 | % worldParameter : WORLD vocoder analysis results *note-1 9 | % timeAnchor : vector consisting of time anchring points 10 | % timeFreqAnchor : martix sonsisting of time-frequency points 11 | % weightStr: Structure variable with the following fields 12 | % tx: vector of morphing weight of time axis for each instance 13 | % fx: vector of morphing weight of frequency axis for each instance 14 | % fo: vector of morphing weight of fun. freq. for each instance 15 | % sl: vector of morphing weight of spectrum level for each instance 16 | % ap: vector of morphing weight of aperiodicity for each instance 17 | % dispOn: switch for debug, 1:plot graphs, 0:no plots 18 | % 19 | % Output 20 | % output: Structure variable with the following fields 21 | % source_parameter : source parameters for vocoder with fields: 22 | % temporal_positions : vector of frame locations 23 | % f0 : fundamental frequency of each frame 24 | % vuv : 1: voiced, 0: unvoiced 25 | % aperiodicity : aperiodicity matrix 26 | % spectrum_parameter : spectrum prameters for vocoder 27 | % temporal_positions : vector of frame locations 28 | % spectrogram : smoothed power spectrum matrix 29 | % fs : sampling frequency 30 | % elapsedTime : elapsed time for processing 31 | % * There are other fields for debug use 32 | % 33 | % *note-1 : use "worldHandler" tool to get worldParameter 34 | 35 | % Copyright 2024 Hideki Kawahara 36 | % 37 | % Licensed under the Apache License, Version 2.0 (the "License"); 38 | % you may not use this file except in compliance with the License. 39 | % You may obtain a copy of the License at 40 | % 41 | % http://www.apache.org/licenses/LICENSE-2.0 42 | % 43 | % Unless required by applicable law or agreed to in writing, software 44 | % distributed under the License is distributed on an "AS IS" BASIS, 45 | % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 46 | % See the License for the specific language governing permissions and 47 | % limitations under the License. 48 | 49 | startTic = tic; 50 | nObj = length(morphdBase.morphStr); 51 | 52 | %Morph time axis 53 | nTanchor = length(morphdBase.morphStr(1).timeAnchor); 54 | segLengthMtx = zeros(nTanchor+1,nObj); 55 | for ii = 1:nObj 56 | timeAnchor = morphdBase.morphStr(ii).timeAnchor; 57 | worldParameter = morphdBase.morphStr(ii).worldParameter; 58 | fs = worldParameter.samplingFrequency; 59 | span = worldParameter.span; 60 | endTime = length(span)/fs; 61 | lastPoint = 0; 62 | for jj = 1:nTanchor 63 | segLengthMtx(jj,ii) = timeAnchor(jj) - lastPoint; 64 | lastPoint = timeAnchor(jj); 65 | end 66 | segLengthMtx(nTanchor+1,ii) = endTime - lastPoint; 67 | end 68 | logSlopeMtx = log(segLengthMtx); 69 | morphedLogSlope = logSlopeMtx*weightStr.tx; 70 | morphedSlope = exp(morphedLogSlope); 71 | morphedTanchor = cumsum(morphedSlope); 72 | if dispOn 73 | figure; 74 | plot(cumsum(segLengthMtx),'o-');grid on; 75 | hold all 76 | plot(morphedTanchor,'ko-','LineWidth',2); 77 | xlabel("anchor index") 78 | ylabel("time (s)") 79 | hold off 80 | drawnow 81 | end 82 | 83 | %Morph fundamental frequency 84 | morphedTemporalPosition = 0:0.005:morphedTanchor(end); 85 | morphedFo = morphedTemporalPosition*0; 86 | extendedTanchorMtx = cumsum(segLengthMtx); 87 | morphedVUV = morphedTemporalPosition*0; 88 | tmpAxisOnObjMtx = zeros(nObj,length(morphedTemporalPosition)); 89 | for ii = 1:nObj 90 | worldParameter = morphdBase.morphStr(ii).worldParameter; 91 | temporalPositions = worldParameter.source_parameter.temporal_positions; 92 | fo = worldParameter.source_parameter.f0; 93 | vuv = worldParameter.source_parameter.vuv; 94 | tmpAxisOnObj = ... 95 | interp1(morphedTanchor,extendedTanchorMtx(:,ii),morphedTemporalPosition,"linear","extrap"); 96 | tmp = interp1(temporalPositions,log(fo),tmpAxisOnObj,"linear","extrap"); 97 | tmp = exp(tmp); 98 | tmpVUV = interp1(temporalPositions,vuv,tmpAxisOnObj,"linear","extrap"); 99 | tmp(isnan(tmp)) = 0; 100 | morphedFo = morphedFo + tmp*weightStr.fo(ii); 101 | morphedVUV = morphedVUV + tmpVUV*weightStr.fo(ii); 102 | tmpAxisOnObjMtx(ii,:) = tmpAxisOnObj; 103 | end 104 | morphedFo(morphedVUV<0.99) = 0; 105 | 106 | %Display morphed fundamental frequency 107 | if dispOn 108 | figure; 109 | semilogy(morphedTemporalPosition,morphedFo,"k","LineWidth",2);grid on; 110 | hold on 111 | for ii = 1:nObj 112 | worldParameter = morphdBase.morphStr(ii).worldParameter; 113 | temporalPositions = worldParameter.source_parameter.temporal_positions; 114 | fo = worldParameter.source_parameter.f0; 115 | semilogy(temporalPositions,fo); 116 | drawnow; 117 | end 118 | hold off 119 | end 120 | 121 | %morph frequency axis 122 | spGram = worldParameter(1).spectrum_parameter.spectrogram; 123 | [nFbin, ~] = size(spGram); 124 | freqAxisOnMorph = (0:nFbin-1)'/nFbin*fs/2; 125 | freqAxisOnMorph(1)=freqAxisOnMorph(2)/2; 126 | logFx = log(freqAxisOnMorph); 127 | timeFreqAnchor = morphdBase.morphStr(1).timeFreqAnchor; 128 | maxNfreqAnchor = length(timeFreqAnchor(:,1)); 129 | freqMapStr = struct; 130 | endLogFqPoint = log(fs/2); 131 | segLengthMtx = zeros(maxNfreqAnchor+1,1); 132 | weightedLogSlope = zeros(maxNfreqAnchor+1,nTanchor); 133 | nFreqVector = zeros(nTanchor,1); 134 | for ii = 1:nObj 135 | timeFreqAnchor = morphdBase.morphStr(ii).timeFreqAnchor; 136 | segLengthMtx = segLengthMtx*0; 137 | weightedLogSlope = weightedLogSlope*0; 138 | nFreqVector = nFreqVector*0; 139 | for jj = 1:nTanchor 140 | nFreq = nnz(timeFreqAnchor(:,jj)); 141 | nFreqVector(jj) = nFreq; 142 | if nFreq == 0 143 | segLengthMtx(1) = endLogFqPoint; 144 | else 145 | lastPoint = 0; 146 | for kk = 1:nFreq 147 | segLengthMtx(kk) = log(timeFreqAnchor(kk,jj)) - lastPoint; 148 | lastPoint = log(timeFreqAnchor(kk,jj)); 149 | end 150 | segLengthMtx(nFreq+1) = endLogFqPoint - lastPoint; 151 | end 152 | logSlopeMtx = segLengthMtx(1:nFreq+1); 153 | weightedLogSlope(1:nFreq+1,jj) = logSlopeMtx*weightStr.fx(ii); 154 | end 155 | freqMapStr.mapStr(ii).weightedLogSlope = weightedLogSlope; 156 | freqMapStr.mapStr(ii).nFreqVector = nFreqVector; 157 | end 158 | morphedLogSlope = zeros(maxNfreqAnchor+1,1); 159 | morphedTLogFanchor = timeFreqAnchor*0; 160 | freqAxisOnObj = zeros(nFbin,nTanchor); 161 | for ii = 1:nObj 162 | freqMapStr.mapStr(ii).freqAxisOnObj = freqAxisOnObj; 163 | end 164 | for jj = 1:nTanchor 165 | nFreq = nFreqVector(jj); 166 | if nFreq == 0 167 | morphedTLogFanchor(1,jj) = log(fs/2); 168 | else 169 | morphedLogSlope = morphedLogSlope*0; 170 | for ii = 1:nObj 171 | morphedLogSlope(1:nFreq+1) = morphedLogSlope(1:nFreq+1) ... 172 | +freqMapStr.mapStr(ii).weightedLogSlope(1:nFreq+1,jj); 173 | end 174 | morphedLogFanchor = cumsum(morphedLogSlope); 175 | morphedLogFanchor(nFreq+1) = log(fs/2); 176 | morphedTLogFanchor(1:nFreq+1,jj) = morphedLogFanchor(1:nFreq+1); 177 | end 178 | for ii = 1:nObj 179 | nFreq = nFreqVector(jj); 180 | if nFreq == 0 181 | freqMapStr.mapStr(ii).freqAxisOnObj(:,jj) = freqAxisOnMorph; 182 | else 183 | logFreqAnchor = log(morphdBase.morphStr(ii).timeFreqAnchor(1:nFreq,jj)); 184 | tmp = interp1([0;morphedTLogFanchor(1:nFreq+1,jj)],[0;logFreqAnchor;endLogFqPoint], ... 185 | logFx,"linear","extrap"); 186 | freqMapStr.mapStr(ii).freqAxisOnObj(:,jj) = exp(tmp); 187 | end 188 | end 189 | end 190 | morphedTFanchor = exp(morphedTLogFanchor); 191 | 192 | %Check TF anchor morping 193 | if dispOn 194 | figure; 195 | colorList = {"ro","go","bo","mo"}; 196 | for ii = 1:nObj 197 | semilogy(morphdBase.morphStr(ii).timeAnchor,morphdBase.morphStr(ii).timeFreqAnchor, ... 198 | colorList{ii},"LineWidth",1.5); 199 | grid on 200 | hold on 201 | end 202 | hold on; 203 | semilogy(morphedTanchor(1:nTanchor),morphedTFanchor,'ko',"linewidth",3); 204 | end 205 | 206 | %Morph spectrogram 207 | alignedLogSgram = struct; 208 | nFrameMorph = length(morphedTemporalPosition); 209 | morphedSgram = zeros(nFbin,nFrameMorph); 210 | tmpSgramBase = zeros(nFbin,nFrameMorph); 211 | morphedSgramWoFmod = zeros(nFbin,nFrameMorph); 212 | morphedAp = zeros(nFbin,nFrameMorph); 213 | for ii = 1:nObj 214 | %logAp = log(clip(morphdBase.morphStr(ii).worldParameter.source_parameter.aperiodicity,0.00001,1)); 215 | logAp = log(max(0.00001,min(1,morphdBase.morphStr(ii).worldParameter.source_parameter.aperiodicity))); 216 | logSgram = log(morphdBase.morphStr(ii).worldParameter.spectrum_parameter.spectrogram); 217 | temporalPositions = morphdBase.morphStr(ii).worldParameter.spectrum_parameter.temporal_positions; 218 | alignedLogSgram(ii).sgram = interp1(temporalPositions,logSgram', ... 219 | tmpAxisOnObjMtx(ii,:),"linear","extrap")'; 220 | alignedLogSgram(ii).ap = interp1(temporalPositions,logAp', ... 221 | tmpAxisOnObjMtx(ii,:),"linear","extrap")'; 222 | lastTime = 0; 223 | currentFrame = 1; 224 | lastFreqAxOnObj = freqAxisOnMorph; 225 | tmpSgram = tmpSgramBase; 226 | tmpAp = tmpSgramBase; 227 | for jj = 1:nTanchor+1 228 | segLength = morphedTanchor(jj)-lastTime; 229 | if jj <= nTanchor 230 | nextFreqAxOnObj = freqMapStr.mapStr(ii).freqAxisOnObj(:,jj); 231 | else 232 | nextFreqAxOnObj = freqAxisOnMorph; 233 | end 234 | while currentFrame <= nFrameMorph ... 235 | && morphedTemporalPosition(currentFrame) < morphedTanchor(jj) 236 | currentTime = morphedTemporalPosition(currentFrame); 237 | lambda = (currentTime - lastTime)/segLength; 238 | currentFreqAxOnObj = ... 239 | (1-lambda)*lastFreqAxOnObj + lambda*nextFreqAxOnObj; 240 | tmpSgram(:,currentFrame) = ... 241 | interp1(freqAxisOnMorph,alignedLogSgram(ii).sgram(:,currentFrame), ... 242 | currentFreqAxOnObj,"linear","extrap"); 243 | tmpAp(:,currentFrame) = ... 244 | interp1(freqAxisOnMorph,alignedLogSgram(ii).ap(:,currentFrame), ... 245 | currentFreqAxOnObj,"linear","extrap"); 246 | currentFrame = currentFrame + 1; 247 | end 248 | lastFreqAxOnObj = nextFreqAxOnObj; 249 | if jj <= nTanchor 250 | lastTime = morphedTanchor(jj); 251 | end 252 | end 253 | morphedSgram = morphedSgram + tmpSgram*weightStr.sl(ii); 254 | morphedAp = morphedAp + tmpAp*weightStr.ap(ii); 255 | morphedSgramWoFmod = morphedSgramWoFmod ... 256 | +alignedLogSgram(ii).sgram*weightStr.sl(ii); 257 | end 258 | morphedSgram = exp(morphedSgram); 259 | morphedSgramWoFmod = exp(morphedSgramWoFmod); 260 | morphedAp = exp(morphedAp); 261 | if dispOn 262 | figure; 263 | imagesc([0 morphedTemporalPosition(end)],[0 fs/2],10*log10(morphedSgram)); 264 | axis('xy') 265 | end 266 | output.morphedSgram = morphedSgram; 267 | output.morphedAp = morphedAp; 268 | output.morphedSgramWoFmod = morphedSgramWoFmod; 269 | output.morphedTemporalPosition = morphedTemporalPosition; 270 | output.morphedFo = morphedFo; 271 | morphedVUV(morphedVUV<0.995) = 0; 272 | morphedVUV(morphedVUV>0) = 1; 273 | output.morphedVUV = morphedVUV; 274 | output.freqMapStr = freqMapStr; 275 | %--------- 276 | source_parameter = struct; 277 | spectrum_parameter = struct; 278 | source_parameter.temporal_positions = morphedTemporalPosition; 279 | source_parameter.f0 = morphedFo; 280 | source_parameter.vuv = morphedVUV; 281 | source_parameter.aperiodicity = morphedAp; 282 | spectrum_parameter.temporal_positions = morphedTemporalPosition; 283 | spectrum_parameter.spectrogram = morphedSgram; 284 | spectrum_parameter.fs = fs; 285 | output.source_parameter = source_parameter; 286 | output.spectrum_parameter = spectrum_parameter; 287 | output.elapsedTime = toc(startTic); 288 | end 289 | --------------------------------------------------------------------------------