Mercurial > hg > camir-aes2014
diff toolboxes/MIRtoolbox1.3.2/MIRToolbox/@miremotion/miremotion.m @ 0:e9a9cd732c1e tip
first hg version after svn
author | wolffd |
---|---|
date | Tue, 10 Feb 2015 15:05:51 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/toolboxes/MIRtoolbox1.3.2/MIRToolbox/@miremotion/miremotion.m Tue Feb 10 15:05:51 2015 +0000 @@ -0,0 +1,470 @@ +function varargout = miremotion(orig,varargin) +% Predicts emotion along three dimensions and five basic concepts. +% Optional parameters: +% miremotion(...,'Dimensions',0) excludes all three dimensions. +% miremotion(...,'Dimensions',3) includes all three dimensions (default). +% miremotion(...,'Activity') includes the 'Activity' dimension. +% miremotion(...,'Valence') includes the 'Valence' dimension. +% miremotion(...,'Tension') includes the 'Tension' dimension. +% miremotion(...,'Dimensions',2) includes 'Activity' and 'Valence'. +% miremotion(...,'Arousal') includes 'Activity' and 'Tension'. +% miremotion(...,'Concepts',0) excludes all five concepts. +% miremotion(...,'Concepts') includes all five concepts (default). +% miremotion(...,'Happy') includes the 'Happy' concept. +% miremotion(...,'Sad') includes the 'Sad' concept. +% miremotion(...,'Tender') includes the 'Tender' concept. +% miremotion(...,'Anger') includes the 'Anger' concept. +% miremotion(...,'Fear') includes the 'Fear' concept. +% miremotion(...,'Frame',...) predict emotion frame by frame. +% +% Selection of features and coefficients are taken from a study: +% Eerola, T., Lartillot, O., and Toiviainen, P. +% (2009). Prediction of multidimensional emotional ratings in +% music from audio using multivariate regression models. +% In Proceedings of 10th International Conference on Music Information Retrieval +% (ISMIR 2009), pages 621-626. +% +% The implemented models are based on multiple linear regression with 5 best +% predictors (MLR option in the paper). The box-cox transformations have now been +% removed until the normalization values have been established with a large sample of music. +% +% TODO: Revision of coefficients to (a) force the output range between 0 - 1 and +% (b) to be based on alternative models and materials (training sets). +% +% Updated 03.05.2010 TE +% + frame.key = 'Frame'; + frame.type = 'Integer'; + frame.number = 2; + frame.default = [0 0]; + frame.keydefault = [1 1]; + option.frame = frame; + + dim.key = 'Dimensions'; + dim.type = 'Integer'; + dim.default = NaN; + dim.keydefault = 3; + option.dim = dim; + + activity.key = 'Activity'; + activity.type = 'Boolean'; + activity.default = NaN; + option.activity = activity; + + valence.key = 'Valence'; + valence.type = 'Boolean'; + valence.default = NaN; + option.valence = valence; + + tension.key = 'Tension'; + tension.type = 'Boolean'; + tension.default = NaN; + option.tension = tension; + + arousal.key = 'Arousal'; + arousal.type = 'Boolean'; + arousal.default = NaN; + option.arousal = arousal; + + concepts.key = 'Concepts'; + concepts.type = 'Boolean'; + concepts.default = NaN; + option.concepts = concepts; + + happy.key = 'Happy'; + happy.type = 'Boolean'; + happy.default = NaN; + option.happy = happy; + + sad.key = 'Sad'; + sad.type = 'Boolean'; + sad.default = NaN; + option.sad = sad; + + tender.key = 'Tender'; + tender.type = 'Boolean'; + tender.default = NaN; + option.tender = tender; + + anger.key = 'Anger'; + anger.type = 'Boolean'; + anger.default = NaN; + option.anger = anger; + + fear.key = 'Fear'; + fear.type = 'Boolean'; + fear.default = NaN; + option.fear = fear; + +specif.option = option; +specif.defaultframelength = 1; +%specif.defaultframehop = .5; + +specif.combinechunk = {'Average',@nothing}; +specif.extensive = 1; + +varargout = mirfunction(@miremotion,orig,varargin,nargout,specif,@init,@main); + + +%% +function [x type] = init(x,option) + +option = process(option); + +if option.frame.length.val + hop = option.frame.hop.val; + if strcmpi(option.frame.hop.unit,'Hz') + hop = 1/hop; + option.frame.hop.unit = 's'; + end + if strcmpi(option.frame.hop.unit,'s') + hop = hop*get(x,'Sampling'); + end + if strcmpi(option.frame.hop.unit,'%') + hop = hop/100; + option.frame.hop.unit = '/1'; + end + if strcmpi(option.frame.hop.unit,'/1') + hop = hop*option.frame.length.val; + end + frames = 0:hop:1000000; + x = mirsegment(x,[frames;frames+option.frame.length.val]); +elseif isa(x,'mirdesign') + x = set(x,'NoChunk',1); +end +rm = mirrms(x,'Frame',.046,.5); + +le = 0; %mirlowenergy(rm,'ASR'); + +o = mironsets(x,'Filterbank',15,'Contrast',0.1); +at = mirattacktime(o); +as = 0; %mirattackslope(o); +ed = 0; %mireventdensity(o,'Option1'); + +fl = mirfluctuation(x,'Summary'); +fp = mirpeaks(fl,'Total',1); +fc = 0; %mircentroid(fl); + +tp = 0; %mirtempo(x,'Frame',2,.5,'Autocor','Spectrum'); +pc = mirpulseclarity(x,'Frame',2,.5); %%%%%%%%%%% Why 'Frame'?? + +s = mirspectrum(x,'Frame',.046,.5); +sc = mircentroid(s); +ss = mirspread(s); +sr = mirroughness(s); + +%ps = mirpitch(x,'Frame',.046,.5,'Tolonen'); + +c = mirchromagram(x,'Frame','Wrap',0,'Pitch',0); %%%%%%%%%%%%%%%%%%%% Previous frame size was too small. +cp = mirpeaks(c,'Total',1); +ps = 0;%cp; +ks = mirkeystrength(c); +[k kc] = mirkey(ks); +mo = mirmode(ks); +hc = mirhcdf(c); + +se = mirentropy(mirspectrum(x,'Collapsed','Min',40,'Smooth',70,'Frame',1.5,.5)); %%%%%%%%% Why 'Frame'?? + +ns = mirnovelty(mirspectrum(x,'Frame',.1,.5,'Max',5000),'Normal',0); +nt = mirnovelty(mirchromagram(x,'Frame',.2,.25),'Normal',0); %%%%%%%%%%%%%%%%%%%% Previous frame size was too small. +nr = mirnovelty(mirchromagram(x,'Frame',.2,.25,'Wrap',0),'Normal',0); %%%%%%%%%%%%%%%%%%%% Previous frame size was too small. + + + +x = {rm,le, at,as,ed, fp,fc, tp,pc, sc,ss,sr, ps, cp,kc,mo,hc, se, ns,nt,nr}; + +type = {'miremotion','mirscalar','mirscalar',... + 'mirscalar','mirscalar','mirscalar',... + 'mirspectrum','mirscalar',... + 'mirscalar','mirscalar',... + 'mirscalar','mirscalar','mirscalar',... + 'mirscalar',... + 'mirchromagram','mirscalar','mirscalar','mirscalar',... + 'mirscalar',... + 'mirscalar','mirscalar','mirscalar'}; + + +%% +function e = main(x,option,postoption) + +warning('WARNING IN MIRENOTION: The current model of miremotion is not correctly calibrated with this version of MIRtoolbox (but with version 1.3 only).'); + +option = process(option); +rm = get(x{1},'Data'); +%le = get(x{2},'Data'); +at = get(x{3},'Data'); +%as = get(x{4},'Data'); +%ed = get(x{5},'Data'); +%fpp = get(x{6},'PeakPosUnit'); +fpv = get(x{6},'PeakVal'); +%fc = get(x{7},'Data'); +%tp = get(x{8},'Data'); +pc = get(x{9},'Data'); +sc = get(x{10},'Data'); +ss = get(x{11},'Data'); +rg = get(x{12},'Data'); +%ps = get(x{13},'PeakPosUnit'); +cp = get(x{14},'PeakPosUnit'); +kc = get(x{15},'Data'); +mo = get(x{16},'Data'); +hc = get(x{17},'Data'); +se = get(x{18},'Data'); +ns = get(x{19},'Data'); +nt = get(x{20},'Data'); +nr = get(x{21},'Data'); + + +e.dim = {}; +e.dimdata = mircompute(@initialise,rm); +if option.activity == 1 + [e.dimdata e.activity_fact] = mircompute(@activity,e.dimdata,rm,fpv,sc,ss,se); + e.dim = [e.dim,'Activity']; +else + e.activity_fact = NaN; +end +if option.valence == 1 + [e.dimdata e.valence_fact] = mircompute(@valence,e.dimdata,rm,fpv,kc,mo,ns); + e.dim = [e.dim,'Valence']; +else + e.valence_fact = NaN; +end +if option.tension == 1 + [e.dimdata e.tension_fact] = mircompute(@tension,e.dimdata,rm,fpv,kc,hc,nr); + e.dim = [e.dim,'Tension']; +else + e.tension_fact = NaN; +end + +e.class = {}; +e.classdata = mircompute(@initialise,rm); +if option.happy == 1 + [e.classdata e.happy_fact] = mircompute(@happy,e.classdata,fpv,ss,cp,kc,mo); + e.class = [e.class,'Happy']; +else + e.happy_fact = NaN; +end +if option.sad == 1 + [e.classdata e.sad_fact] = mircompute(@sad,e.classdata,ss,cp,mo,hc,nt); + e.class = [e.class,'Sad']; +else + e.sad_fact = NaN; +end +if option.tender == 1 + [e.classdata e.tender_fact] = mircompute(@tender,e.classdata,sc,rg,kc,hc,ns); + e.class = [e.class,'Tender']; +else + e.tender_fact = NaN; +end +if option.anger == 1 + [e.classdata e.anger_fact] = mircompute(@anger,e.classdata,rg,kc,se,nr); + e.class = [e.class,'Anger']; +else + e.anger_fact = NaN; +end +if option.fear == 1 + [e.classdata e.fear_fact] = mircompute(@fear,e.classdata,rm,at,fpv,kc,mo); + e.class = [e.class,'Fear']; +else + e.fear_fact = NaN; +end + +e = class(e,'miremotion',mirdata(x{1})); +e = purgedata(e); +fp = mircompute(@noframe,get(x{1},'FramePos')); +e = set(e,'Title','Emotion','Abs','emotions','Ord','magnitude','FramePos',fp); + +%% +function option = process(option) +if option.arousal==1 + option.activity = 1; + option.tension = 1; + if isnan(option.dim) + option.dim = 0; + end +end +if option.activity==1 || option.valence==1 || option.tension==1 + if isnan(option.activity) + option.activity = 0; + end + if isnan(option.valence) + option.valence = 0; + end + if isnan(option.tension) + option.tension = 0; + end + if isnan(option.concepts) + option.concepts = 0; + end +end +if not(isnan(option.dim)) && option.dim + if isnan(option.concepts) + option.concepts = 0; + end +end +if not(isnan(option.concepts)) && option.concepts + if isnan(option.dim) + option.dim = 0; + end +end +if not(isnan(option.dim)) + switch option.dim + case 0 + if isnan(option.activity) + option.activity = 0; + end + if isnan(option.valence) + option.valence = 0; + end + if isnan(option.tension) + option.tension = 0; + end + case 2 + option.activity = 1; + option.valence = 1; + if isnan(option.tension) + option.tension = 0; + end + case 3 + option.activity = 1; + option.valence = 1; + option.tension = 1; + end +end +if isnan(option.activity) + option.activity = 1; +end +if isnan(option.valence) + option.valence = 1; +end +if isnan(option.tension) + option.tension = 1; +end +if isnan(option.concepts) + option.concepts = 1; +end +if option.concepts + option.happy = 1; + option.sad = 1; + option.tender = 1; + option.anger = 1; + option.fear = 1; +end +if option.happy==1 || option.sad==1 || option.tender==1 ... + || option.anger==1 || option.fear==1 + if isnan(option.happy) + option.happy = 0; + end + if isnan(option.sad) + option.sad = 0; + end + if isnan(option.tender) + option.tender = 0; + end + if isnan(option.anger) + option.anger = 0; + end + if isnan(option.fear) + option.fear = 0; + end +end + + +%% +function e = initialise(rm) +e = []; + + +function e = activity(e,rm,fpv,sc,ss,se) % without the box-cox transformation, revised coefficients +af = zeros(5,1); +af(1) = 0.6664* ((mean(rm) - 0.0559)/0.0337); % +af(2) = 0.6099 * ((mean(fpv{1}) - 13270.1836)/10790.655); +af(3) = 0.4486*((mean(cell2mat(sc)) - 1677.7)./570.34); +af(4) = -0.4639*((mean(cell2mat(ss)) - 250.5574)./205.3147); +af(5) = 0.7056*((mean(se) - 0.954)./0.0258); +af(isnan(af)) = []; +e(end+1,:) = sum(af)+5.4861; +e = {e af}; + +function e = valence(e,rm,fpv,kc,mo,ns) % without the box-cox transformation, revised coefficients +vf = zeros(5,1); +vf(1) = -0.3161 * ((std(rm) - 0.024254)./0.015667); +vf(2) = 0.6099 * ((mean(fpv{1}) - 13270.1836)/10790.655); +vf(3) = 0.8802 * ((mean(kc) - 0.5123)./0.091953); +vf(4) = 0.4565 * ((mean(mo) - -0.0019958)./0.048664); +ns(isnan(ns)) = []; +vf(5) = 0.4015 * ((mean(ns) - 131.9503)./47.6463); +vf(isnan(vf)) = []; +e(end+1,:) = sum(vf)+5.2749; +e = {e vf}; + +function e = tension(e,rm,fpv,kc,hc,nr) +tf = zeros(5,1); +tf(1) = 0.5382 * ((std(rm) - 0.024254)./0.015667); +tf(2) = -0.5406 * ((mean(fpv{1}) - 13270.1836)/10790.655); +tf(3) = -0.6808 * ((mean(kc) - 0.5124)./0.092); +tf(4) = 0.8629 * ((mean(hc) - 0.2962)./0.0459); +tf(5) = -0.5958 * ((mean(nr) - 71.8426)./46.9246); +tf(isnan(tf)) = []; +e(end+1,:) = sum(tf)+5.4679; +e = {e tf}; + + +% BASIC EMOTION PREDICTORS + +function e = happy(e,fpv,ss,cp,kc,mo) +ha_f = zeros(5,1); +ha_f(1) = 0.7438*((mean(cell2mat(fpv)) - 13270.1836)./10790.655); +ha_f(2) = -0.3965*((mean(cell2mat(ss)) - 250.5574)./205.3147); +ha_f(3) = 0.4047*((std(cell2mat(cp)) - 8.5321)./2.5899); +ha_f(4) = 0.7780*((mean(kc) - 0.5124)./0.092); +ha_f(5) = 0.6220*((mean(mo) - -0.002)./0.0487); +ha_f(isnan(ha_f)) = []; +e(end+1,:) = sum(ha_f)+2.6166; +e = {e ha_f}; + +function e = sad(e,ss,cp,mo,hc,nt) +sa_f = zeros(5,1); +sa_f(1) = 0.4324*((mean(cell2mat(ss)) - 250.5574)./205.3147); +sa_f(2) = -0.3137*((std(cell2mat(cp)) - 8.5321)./2.5899); +sa_f(3) = -0.5201*((mean(mo) - -0.0020)./0.0487); +sa_f(4) = -0.6017*((mean(hc) - 0.2962)./0.0459); +sa_f(5) = 0.4493*((mean(nt) - 42.2022)./36.7782); +sa_f(isnan(sa_f)) = []; +e(end+1,:) = sum(sa_f)+2.9756; +e = {e sa_f}; + +function e = tender(e,sc,rg,kc,hc,ns) +te_f = zeros(5,1); +te_f(1) = -0.2709*((mean(cell2mat(sc)) - 1677.7106)./570.3432); +te_f(2) = -0.4904*((std(rg) - 85.9387)./106.0767); +te_f(3) = 0.5192*((mean(kc) - 0.5124)./0.0920); +te_f(4) = -0.3995*((mean(hc) - 0.2962)./0.0459); +te_f(5) = 0.3391*((mean(ns) - 131.9503)./47.6463); +te_f(isnan(te_f)) = []; +e(end+1,:) = sum(te_f)+2.9756; +e = {e te_f}; + +function e = anger(e,rg,kc,se,nr) % +an_f = zeros(5,1); +%an_f(1) = -0.2353*((mean(pc) - 0.1462)./.1113); +an_f(2) = 0.5517*((mean(rg) - 85.9387)./106.0767); +an_f(3) = -.5802*((mean(kc) - 0.5124)./0.092); +an_f(4) = .2821*((mean(se) - 0.954)./0.0258); +an_f(5) = -.2971*((mean(nr) - 71.8426)./46.9246); +an_f(isnan(an_f)) = []; +e(end+1,:) = sum(an_f)+1.9767; +e = {e an_f}; + +function e = fear(e,rm,at,fpv,kc,mo) +fe_f = zeros(5,1); +fe_f(1) = 0.4069*((std(rm) - 0.0243)./0.0157); +fe_f(2) = -0.6388*((mean(at) - 0.0707)./0.015689218536423); +fe_f(3) = -0.2538*((mean(cell2mat(fpv)) - 13270.1836)./10790.655); +fe_f(4) = -0.9860*((mean(kc) - 0.5124)./0.0920); +fe_f(5) = -0.3144*((mean(mo) - -0.0019958)./0.048663550639094); +fe_f(isnan(fe_f)) = []; +e(end+1,:) = sum(fe_f)+2.7847; +e = {e fe_f}; + +function fp = noframe(fp) +fp = [fp(1);fp(end)]; \ No newline at end of file