| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730 |
- /*
- * Copyright (c) 1983-2013 Trevor Wishart and Composers Desktop Project Ltd
- * http://www.trevorwishart.co.uk
- * http://www.composersdesktop.com
- *
- This file is part of the CDP System.
- The CDP System 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.1 of the License, or (at your option) any later version.
- The CDP System 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 the CDP System; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- 02111-1307 USA
- *
- */
- /* flotsam version */
- #include <stdio.h>
- #include <stdlib.h>
- #include <structures.h>
- #include <tkglobals.h>
- #include <pnames.h>
- #include <globcon.h>
- #include <processno.h>
- #include <modeno.h>
- #include <special.h>
- #include <logic.h>
- #include <arrays.h>
- #include <flags.h>
- #include <repitch.h>
- #include <cdpmain.h>
- #include <formants.h>
- #include <speccon.h>
- #include <sfsys.h>
- #include <osbind.h>
- #include <repitch.h>
- #include <pvoc.h>
- #include <vowels.h>
- #include <vowels2.h>
- #if defined unix || defined __GNUC__
- #define round(x) lround((x))
- #endif
- #define GLARG (0.1) /* 2nd-derivative maximum, for smoothing */
- #define SLOPE_FUDGE (0.2)
- static int specpitch(dataptr dz);
- static int spectrack(dataptr dz);
- static int tranpose_within_formant_envelope(int vc,dataptr dz);
- static int reposition_partials_in_appropriate_channels(int with_body,dataptr dz);
- static int zero_outofrange_channels(double *totalamp,double lofrq_limit,double hifrq_limit,dataptr dz);
- static int close_to_frq_already_in_ring(chvptr *there,double frq1,dataptr dz);
- static int substitute_in_ring(int vc,chvptr here,chvptr there,dataptr dz);
- static int insert_in_ring(int vc, chvptr here, dataptr dz);
- static int put_ring_frqs_in_ascending_order(chvptr **partials,float *minamp,dataptr dz);
- static int found_pitch(chvptr *partials,double lo_loud_partial,double hi_loud_partial,float minamp,dataptr dz);
- static int found_pitch_1(chvptr *partials,double lo_loud_partial,double hi_loud_partial,float minamp,dataptr dz);
- static int found_pitch_2(chvptr *partials,dataptr dz);
- static int smooth_spurious_octave_leaps(int pitchno,float minamp,dataptr dz);
- static int equivalent_pitches(double frq1, double frq2, dataptr dz);
- static int is_peak_at(double frq,int window_offset,float minamp,dataptr dz);
- static int enough_partials_are_harmonics(chvptr *partials,dataptr dz);
- static int is_a_harmonic(double frq1,double frq2,dataptr dz);
- static int do_pitch_cut(dataptr dz);
- static int do_pitch_filter(dataptr dz);
- static int do_pitch_smoothing(dataptr dz);
- static int skip_to_first_pitch(int *first_pitch,dataptr dz);
- static int calc_slopechanges(int m, double *slopechange,dataptr dz);
- static int is_start_of_glitch(int n,double *slopechange,dataptr dz);
- static int do_onset_smooth(int n, double *slopechange,dataptr dz);
- static int do_double_onset_smooth(int n, double *slopechange,dataptr dz);
- static int do_smooth(int n, double *slopechange,dataptr dz);
- static int get_max_and_min_pitches(double *maxpitch,double *minpitch,dataptr dz);
- static int write_remaining_pitch_or_transpos_data(int final_length_in_windows,dataptr dz);
- static int specpapprox(int *,double *,dataptr dz);
- static int specpcut(int *,dataptr dz);
- static int specpexag(dataptr dz);
- static int specpinvert(dataptr dz);
- static int specpquantise(dataptr dz);
- static int specprand(dataptr dz);
- static int specpsmooth(dataptr dz);
- static int specptranspose(dataptr dz);
- static int specpvib(dataptr dz);
- static int get_midimean(double *midimean,dataptr dz);
- static int set_pval(double midivalue,int n,dataptr dz);
- static int do_tail(int n, double lastmidi,dataptr dz);
- static int get_pitchapprox_averages(int *avcnt,dataptr dz);
- static int get_rand_interval(double *thisintv,dataptr dz);
- static int approx_func1(int *,int *,double *,int *,int n,dataptr dz);
- static int approx_func2(int *newlength_of_data,double lastmidi,int lastpos,int avcnt,dataptr dz);
- static int interval_mapping(double *thisint,double thismidi,dataptr dz);
- static int peak_interp(int pitchno,int last_validpitch_no,int *lastmaxpos,double meanpich,
- double minint,double maxint,double *lastmidi,dataptr dz);
- static int tidy_up_pitch_data(dataptr dz);
- static int generate_tone(dataptr dz);
- static int anti_noise_smoothing(int wlength,float *pitches,float frametime);
- static int is_smooth_from_both_sides(int n,double max_pglide,float *pitches);
- static int is_initialpitch_smooth(char *smooth,double max_pglide,float *pitches);
- static int is_finalpitch_smooth(char *smooth,double max_pglide,int wlength,float *pitches);
- static int is_smooth_from_before(int n,char *smooth,double max_pglide,float *pitches);
- static int is_smooth_from_after(int n,char *smooth,double max_pglide,float *pitches);
- static int test_glitch_sets(char *smooth,double max_pglide,int wlength,float *pitches);
- static void remove_unsmooth_pitches(char *smooth,int wlength,float *pitches);
- static int test_glitch_forwards(int gltchstart,int gltchend,char *smooth,double max_pglide,float *pitches);
- static int test_glitch_backwards(int gltchstart,int gltchend,char *smooth,
- double max_pglide,int wlength,float *pitches);
- /* RWD NB: changes outfile header properties - rejigging required! */
- static int write_pitch_outheader_from_analysis_inheader_to_second_outfile(int ofd,dataptr dz);
- static int local_peak(int thiscc,double frq, float *thisbuf, dataptr dz);
- static int interpolate_pitch(float *floatbuf,int skip_silence,dataptr dz);
- static double hz_to_pitchheight(double frqq);
- static double pitchheight_to_hz(double pitch_height);
- static int eliminate_blips_in_pitch_data(dataptr dz);
- static int mark_zeros_in_pitchdata(dataptr dz);
- static int pitch_found(dataptr dz);
- static int do_interpolating(int *pitchno,float *floatbuf,int skip_silence,dataptr dz);
- static void check_transpos(float *t,dataptr dz);
- static void check_pitch(float *t,dataptr dz);
- static int trap_junk(int final_length_in_windows,dataptr dz);
- static int write_pitch_or_transpos_data(int final_length_in_windows,dataptr dz);
- static int pitch_insert(int is_sil,dataptr dz);
- static int pitch_to_silence(dataptr dz);
- static int unpitch_to_silence(dataptr dz);
- static int generate_vowels(dataptr dz);
- static int generate_vowel_spectrum(double frq,double formant1,double formant2,double formant3,
- double f2atten,double f3atten,double *sensitivity,int senslen,int is_offset,dataptr dz);
- static int get_formant_frqs(int vowel,double *formant1,double *formant2,double *formant3,
- double *f2atten,double *f3atten);
- static int define_sensitivity_curve(double **sensitivity,int *senslen);
- static int adjust_for_sensitivity(double *amp,double frq,double *sensitivity,int senslen);
- static int remove_pitch_zeros(dataptr dz);
- static int convert_single_window_pch_or_transpos_data_to_brkpnttable
- (int *brksize,float *floatbuf,float frametime,int array_no,dataptr dz);
- int are_pitch_zeros = 0;
- /********************************** SPECTRNSF **********************************
- *
- * transpose spectrum, but retain original spectral envelope.
- */
- int spectrnsf(dataptr dz)
- {
- int exit_status;
- double pre_totalamp, post_totalamp;
- double lofrq_limit, hifrq_limit;
- int cc, vc;
- rectify_window(dz->flbufptr[0],dz);
- if((exit_status = extract_specenv(0,0,dz))<0)
- return(exit_status);
- if((exit_status = get_totalamp(&pre_totalamp,dz->flbufptr[0],dz->wanted))<0)
- return(exit_status);
- for(cc = 0, vc = 0; cc < dz->clength; cc++, vc += 2) {
- if((exit_status = tranpose_within_formant_envelope(vc,dz))<0)
- return(exit_status);
- }
- if((exit_status = reposition_partials_in_appropriate_channels(TRNSF_BODY,dz))<0)
- return(exit_status);
- if(dz->vflag[TRNSF_FBOT] || dz->vflag[TRNSF_FTOP]) {
- lofrq_limit = dz->param[TRNSF_LOFRQ];
- hifrq_limit = dz->param[TRNSF_HIFRQ];
- if(hifrq_limit < lofrq_limit)
- swap(&hifrq_limit,&lofrq_limit);
- if((exit_status = zero_outofrange_channels(&post_totalamp,lofrq_limit,hifrq_limit,dz))<0)
- return(exit_status);
- } else {
- if((exit_status = get_totalamp(&post_totalamp,dz->flbufptr[0],dz->wanted))<0)
- return(exit_status);
- }
- return normalise(pre_totalamp,post_totalamp,dz);
- }
- /********************************** SPECTRNSP **********************************
- *
- * transpose spectrum, (spectral envelope also moves).
- */
- int spectrnsp(dataptr dz)
- {
- int exit_status;
- double pre_totalamp, post_totalamp;
- double lofrq_limit, hifrq_limit;
- int cc, vc;
- rectify_window(dz->flbufptr[0],dz);
- if((exit_status = get_totalamp(&pre_totalamp,dz->flbufptr[0],dz->wanted))<0)
- return(exit_status);
- for(cc = 0, vc = 0; cc < dz->clength; cc++, vc += 2)
- dz->flbufptr[0][FREQ] = (float)(dz->flbufptr[0][FREQ]*dz->transpos[dz->total_windows]);
- if((exit_status = reposition_partials_in_appropriate_channels(TRNSP_BODY,dz))<0)
- return(exit_status);
- if(dz->vflag[TRNSP_FBOT] || dz->vflag[TRNSP_FTOP]) {
- lofrq_limit = dz->param[TRNSP_LOFRQ];
- hifrq_limit = dz->param[TRNSP_HIFRQ];
- if(hifrq_limit < lofrq_limit)
- swap(&hifrq_limit,&lofrq_limit);
- if((exit_status = zero_outofrange_channels(&post_totalamp,lofrq_limit,hifrq_limit,dz))<0)
- return(exit_status);
- } else {
- if((exit_status = get_totalamp(&post_totalamp,dz->flbufptr[0],dz->wanted))<0)
- return(exit_status);
- }
- return normalise(pre_totalamp,post_totalamp,dz);
- }
- /************************** TRANPOSE_WITHIN_FORMANT_ENVELOPE *****************************/
- int tranpose_within_formant_envelope(int vc,dataptr dz)
- {
- int exit_status;
- double thisspecamp, newspecamp, thisamp, formantamp_ratio;
- if((exit_status = getspecenvamp(&thisspecamp,(double)dz->flbufptr[0][FREQ],0,dz))<0)
- return(exit_status);
- dz->flbufptr[0][FREQ] = (float)(fabs(dz->flbufptr[0][FREQ])*dz->transpos[dz->total_windows]);
- if(dz->flbufptr[0][FREQ] < dz->nyquist) {
- if(thisspecamp < VERY_TINY_VAL)
- dz->flbufptr[0][AMPP] = 0.0f;
- else {
- if((exit_status = getspecenvamp(&newspecamp,(double)dz->flbufptr[0][FREQ],0,dz))<0)
- return(exit_status);
- if(newspecamp < VERY_TINY_VAL)
- dz->flbufptr[0][AMPP] = 0.0f;
- else {
- formantamp_ratio = newspecamp/thisspecamp;
- if((thisamp = dz->flbufptr[0][AMPP] * formantamp_ratio) < VERY_TINY_VAL)
- dz->flbufptr[0][AMPP] = 0.0f;
- else
- dz->flbufptr[0][AMPP] = (float)thisamp;
- }
- }
- }
- return(FINISHED);
- }
- /************************ REPOSITION_PARTIALS_IN_APPROPRIATE_CHANNELS *************************
- *
- * (1) At each pass, preset store-buffer channel amps to zero.
- * (2) Move frq data into appropriate channels, carrying the
- * amplitude information along with them.
- * Work down spectrum for upward transposition, and
- * (3) up spectrum for downward transposition,
- * so that we do not overwrite transposed data before we move it.
- * (4) Put new frqs back into src buff.
- */
- int reposition_partials_in_appropriate_channels(int with_body,dataptr dz)
- {
- int exit_status;
- int truecc,truevc;
- int cc, vc;
- for(vc = 0; vc < dz->wanted; vc+=2) /* 1 */
- dz->windowbuf[0][vc] = 0.0f;
- if(dz->transpos[dz->total_windows] > 1.0f) { /* 2 */
- for(cc=dz->clength-1,vc = dz->wanted-2; cc>=0; cc--, vc-=2) {
- if(dz->flbufptr[0][FREQ] < dz->nyquist && dz->flbufptr[0][AMPP] > 0.0f) {
- if((exit_status = get_channel_corresponding_to_frq(&truecc,(double)dz->flbufptr[0][FREQ],dz))<0)
- return(exit_status);
- truevc = truecc * 2;
- switch(dz->vflag[with_body]) {
- case(FALSE):
- if((exit_status = move_data_into_appropriate_channel(vc,truevc,dz->flbufptr[0][AMPP],dz->flbufptr[0][FREQ],dz))<0)
- return(exit_status);
- break;
- case(TRUE):
- if((exit_status = move_data_into_some_appropriate_channel(truevc,dz->flbufptr[0][AMPP],dz->flbufptr[0][FREQ],dz))<0)
- return(exit_status);
- break;
- default:
- sprintf(errstr,"Unknown case for vflag[with_body]: reposition_partials_in_appropriate_channels()\n");
- return(PROGRAM_ERROR);
- } /* upward transpos, chandata tends to thin */
- } /* case(TRUE) tries for fuller spectrum */
- }
- for(vc = 0; vc < dz->wanted; vc++)
- dz->flbufptr[0][vc] = dz->windowbuf[0][vc];
- } else if(dz->transpos[dz->total_windows] < 1.0f){ /* 3 */
- for(cc=0,vc = 0; cc < dz->clength; cc++, vc+=2) {
- if(dz->flbufptr[0][FREQ] < dz->nyquist && dz->flbufptr[0][FREQ]>0.0) {
- if((exit_status = get_channel_corresponding_to_frq(&truecc,(double)dz->flbufptr[0][FREQ],dz))<0)
- return(exit_status);
- truevc = truecc * 2;
- if((exit_status = move_data_into_appropriate_channel(vc,truevc,dz->flbufptr[0][AMPP],dz->flbufptr[0][FREQ],dz))<0)
- return(exit_status);
- }
- }
- for(vc = 0; vc < dz->wanted; vc++)
- dz->flbufptr[0][vc] = dz->windowbuf[0][vc]; /* 4 */
- }
- return(FINISHED);
- }
- /******************* ZERO_OUTOFRANGE_CHANNELS *****************/
- int zero_outofrange_channels(double *totalamp,double lofrq_limit,double hifrq_limit,dataptr dz)
- {
- int cc, vc;
- *totalamp = 0.0;
- for(cc = 0,vc = 0; cc < dz->clength; cc++, vc += 2) {
- if(dz->flbufptr[0][FREQ] < lofrq_limit || dz->flbufptr[0][FREQ] > hifrq_limit)
- dz->flbufptr[0][AMPP] = 0.0f;
- else
- *totalamp += dz->flbufptr[0][AMPP];
- }
- return(FINISHED);
- }
- /***************************** OUTER_PITCH_LOOP ***********************/
- int outer_pitch_loop(dataptr dz)
- {
- int exit_status;
- int samps_read, wc, windows_in_buf, brklen;
- double totalamp;
- int thismode = 0;
- while((samps_read = fgetfbufEx(dz->bigfbuf,dz->big_fsize,dz->ifd[0],0)) > 0) {
- dz->flbufptr[0] = dz->bigfbuf;
- windows_in_buf = samps_read/dz->wanted;
- for(wc=0; wc<windows_in_buf; wc++, dz->total_windows++) {
- if(dz->total_windows==0 && dz->wlength > 1) {
- dz->pitches[0] = (float)NOT_PITCH;
- dz->flbufptr[0] += dz->wanted;
- continue;
- }
- if((exit_status = get_totalamp(&totalamp,dz->flbufptr[0],dz->wanted))<0)
- return(exit_status);
- dz->parray[PICH_PRETOTAMP][dz->total_windows] = totalamp;
- switch(dz->process) {
- case(PITCH):
- if((exit_status = specpitch(dz))<0)
- return(exit_status);
- break;
- case(TRACK):
- if((exit_status = spectrack(dz))<0)
- return(exit_status);
- break;
- default:
- sprintf(errstr,"Unknown case in outer_pitch_loop()\n");
- return(PROGRAM_ERROR);
- }
- dz->flbufptr[0] += dz->wanted;
- }
- }
- if(samps_read<0) {
- sprintf(errstr,"Sound read error.\n");
- return(SYSTEM_ERROR);
- }
- if((exit_status = tidy_up_pitch_data(dz))<0)
- return(exit_status);
- if((exit_status = generate_tone(dz))<0)
- return(exit_status);
- dz->total_samps_written = 0;
- switch(dz->process) {
- case(PITCH): if(dz->mode == PICH_TO_BRK) thismode = 1; break;
- case(TRACK): if(dz->mode == TRK_TO_BRK) thismode = 1; break;
- default:
- sprintf(errstr,"Unknown mode in outer_pitch_loop().\n");
- return(PROGRAM_ERROR);
- }
- switch(thismode) {
- case(0):
- if((exit_status = write_samps_to_elsewhere(dz->other_file,dz->pitches,dz->wlength,dz))<0)
- return(exit_status);
- if((exit_status = write_pitch_outheader_from_analysis_inheader_to_second_outfile
- (dz->other_file,dz))<0)
- return(exit_status);
- break;
- case(1):
- /* MAY 2001 BRKPNT OUTPUT ELIMINATES PITCH ZEROS */
- if((exit_status = interpolate_pitch(dz->pitches,0,dz))<0)
- return(exit_status);
- if(dz->wlength == 1) {
- if((exit_status = convert_single_window_pch_or_transpos_data_to_brkpnttable
- (&brklen,dz->pitches,dz->frametime,PICH_PBRK,dz))<0)
- return(exit_status);
- } else {
- if((exit_status = convert_pch_or_transpos_data_to_brkpnttable
- (&brklen,dz->pitches,dz->frametime,PICH_PBRK,dz))<0)
- return(exit_status);
- }
- if((exit_status = write_brkfile(dz->fp,brklen,PICH_PBRK,dz))<0)
- return(exit_status);
- if(fclose(dz->fp)<0) {
- fprintf(stdout, "WARNING: Failed to close output brkpntfile.\n");
- fflush(stdout);
- }
- break;
- default:
- sprintf(errstr,"unknown output case in outer_pitch_loop()\n");
- return(PROGRAM_ERROR);
- }
- return(FINISHED);
- }
- /****************************** SPECPITCH *******************************
- *
- * (1) Ignore partials below low limit of pitch.
- * (2) If this channel data is louder than any existing piece of data in ring.
- * (Ring data is ordered loudness-wise)...
- * (3) If this freq is too close to an existing frequency..
- * (4) and if it is louder than that existing frequency data..
- * (5) Substitute in in the ring.
- * (6) Otherwise, (its a new frq) insert it into the ring.
- */
-
- int specpitch(dataptr dz)
- {
- int exit_status;
- int vc;
- chvptr here, there, *partials;
- float minamp;
- double loudest_partial_frq, nextloudest_partial_frq, lo_loud_partial, hi_loud_partial;
- if((partials = (chvptr *)malloc(MAXIMI * sizeof(chvptr)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for partials array.\n");
- return(MEMORY_ERROR);
- }
- if((exit_status = initialise_ring_vals(MAXIMI,-1.0,dz))<0)
- return(exit_status);
- if((exit_status = rectify_frqs(dz->flbufptr[0],dz))<0)
- return(exit_status);
- for(vc=0;vc<dz->wanted;vc+=2) {
- here = dz->ringhead;
- if(dz->flbufptr[0][FREQ] > dz->param[PICH_LOLM]) { /* 1 */
- do {
- if(dz->flbufptr[0][AMPP] > here->val) { /* 2 */
- if((exit_status = close_to_frq_already_in_ring(&there,(double)dz->flbufptr[0][FREQ],dz))<0)
- return(exit_status);
- if(exit_status==TRUE) {
- if(dz->flbufptr[0][AMPP] > there->val) { /* 4 */
- if((exit_status = substitute_in_ring(vc,here,there,dz))<0) /* 5 */
- return(exit_status);
- }
- } else { /* 6 */
- if((exit_status = insert_in_ring(vc,here,dz))<0)
- return(exit_status);
- }
- break;
- }
- } while((here = here->next)!=dz->ringhead);
- }
- }
- loudest_partial_frq = dz->flbufptr[0][dz->ringhead->loc + 1];
- nextloudest_partial_frq = dz->flbufptr[0][dz->ringhead->next->loc + 1];
- if(loudest_partial_frq < nextloudest_partial_frq) {
- lo_loud_partial = loudest_partial_frq;
- hi_loud_partial = nextloudest_partial_frq;
- } else {
- lo_loud_partial = nextloudest_partial_frq;
- hi_loud_partial = loudest_partial_frq;
- }
- if((exit_status = put_ring_frqs_in_ascending_order(&partials,&minamp,dz))<0)
- return(exit_status);
- if((exit_status = found_pitch(partials,lo_loud_partial,hi_loud_partial,minamp,dz))<0)
- return(exit_status);
- if(exit_status==TRUE && dz->param[PICH_PICH]>=MINPITCH)
- dz->pitches[dz->total_windows] = (float)dz->param[PICH_PICH];
- else
- dz->pitches[dz->total_windows] = (float)NOT_PITCH;
- return smooth_spurious_octave_leaps(dz->total_windows,minamp,dz);
- }
- /**************************** CLOSE_TO_FRQ_ALREADY_IN_RING *******************************/
- int close_to_frq_already_in_ring(chvptr *there,double frq1,dataptr dz)
- {
- #define EIGHT_OVER_SEVEN (1.142857143)
- double frq2, frqratio;
- *there = dz->ringhead;
- do {
- if((*there)->val > 0.0) {
- frq2 = dz->flbufptr[0][(*there)->loc + 1];
- if(frq1 > frq2)
- frqratio = frq1/frq2;
- else
- frqratio = frq2/frq1;
- if(frqratio < EIGHT_OVER_SEVEN)
- return(TRUE);
- }
- } while((*there = (*there)->next) != dz->ringhead);
- return(FALSE);
- }
- /******************************* SUBSITUTE_IN_RING **********************/
- int substitute_in_ring(int vc,chvptr here,chvptr there,dataptr dz)
- {
- chvptr spare, previous;
- if(here!=there) {
- if(there==dz->ringhead) {
- sprintf(errstr,"IMPOSSIBLE! in substitute_in_ring()\n");
- return(PROGRAM_ERROR);
- }
- spare = there;
- there->next->last = there->last; /* SPLICE REDUNDANT STRUCT FROM RING */
- there->last->next = there->next;
- previous = here->last;
- previous->next = spare; /* SPLICE ITS ADDRESS-SPACE BACK INTO RING */
- spare->last = previous; /* IMMEDIATELY BEFORE HERE */
- here->last = spare;
- spare->next = here;
- if(here==dz->ringhead) /* IF HERE IS RINGHEAD, MOVE RINGHEAD */
- dz->ringhead = spare;
- here = spare; /* POINT TO INSERT LOCATION */
- }
- here->val = dz->flbufptr[0][AMPP]; /* IF here==there */
- here->loc = vc; /* THIS WRITES OVER VAL IN EXISTING RING LOCATION */
- return(FINISHED);
- }
- /*************************** INSERT_IN_RING ***************************/
- int insert_in_ring(int vc, chvptr here, dataptr dz)
- {
- chvptr previous, newend, spare;
- if(here==dz->ringhead) {
- dz->ringhead = dz->ringhead->last;
- spare = dz->ringhead;
- } else {
- if(here==dz->ringhead->last)
- spare = here;
- else {
- spare = dz->ringhead->last;
- newend = dz->ringhead->last->last; /* cut ENDADR (spare) out of ring */
- dz->ringhead->last = newend;
- newend->next = dz->ringhead;
- previous = here->last;
- here->last = spare; /* reuse spare address at new loc by */
- spare->next = here; /* inserting it back into ring before HERE */
- previous->next = spare;
- spare->last = previous;
- }
- }
- spare->val = dz->flbufptr[0][vc]; /* Store new val in spare ring location */
- spare->loc = vc;
- return(FINISHED);
- }
- /************************** PUT_RING_FRQS_IN_ASCENDING_ORDER **********************/
- int put_ring_frqs_in_ascending_order(chvptr **partials,float *minamp,dataptr dz)
- {
- int k;
- chvptr start, ggot, here = dz->ringhead;
- float minpitch;
- *minamp = (float)MAXFLOAT;
- for(k=0;k<MAXIMI;k++) {
- if((*minamp = min(dz->flbufptr[0][here->loc],*minamp))>=(float)MAXFLOAT) {
- sprintf(errstr,"Problem with amplitude out of range: put_ring_frqs_in_ascending_order()\n");
- return(PROGRAM_ERROR);
- }
- (here->loc)++; /* CHANGE RING TO POINT TO FRQS, not AMPS */
- here->val = dz->flbufptr[0][here->loc];
- here = here->next;
- }
- here = dz->ringhead;
- minpitch = dz->flbufptr[0][here->loc];
- for(k=1;k<MAXIMI;k++) {
- start = ggot = here;
- while((here = here->next)!=start) { /* Find lowest frq */
- if(dz->flbufptr[0][here->loc] < minpitch) {
- minpitch = dz->flbufptr[0][here->loc];
- ggot = here;
- }
- }
- (*partials)[k-1] = ggot; /* Save its address */
- here = ggot->next; /* Move to next ring site */
- minpitch = dz->flbufptr[0][here->loc]; /* Preset minfrq to val there */
- ggot->last->next = here; /* Unlink ringsite ggot */
- here->last = ggot->last;
- }
- (*partials)[k-1] = here; /* Remaining ringsite is maximum */
- here = dz->ringhead = (*partials)[0]; /* Reconstruct ring */
- for(k=1;k<MAXIMI;k++) {
- here->next = (*partials)[k];
- (*partials)[k]->last = here;
- here = here->next;
- }
- here->next = dz->ringhead; /* Close up ring */
- dz->ringhead->last = here;
- return(FINISHED);
- }
- /****************************** FIND_PITCH **************************/
- int found_pitch(chvptr *partials,double lo_loud_partial,double hi_loud_partial,float minamp,dataptr dz)
- {
- switch(dz->vflag[PICH_ALTERNATIVE_METHOD]) {
- case(FALSE): return(found_pitch_1(partials,lo_loud_partial,hi_loud_partial,minamp,dz));
- case(TRUE): return(found_pitch_2(partials,dz));
- default:
- sprintf(errstr,"Unknown case in found_pitch()\n");
- return(PROGRAM_ERROR);
- }
- }
- /****************************** FIND_PITCH_1 **************************/
- #define MAXIMUM_PARTIAL (64)
- int found_pitch_1(chvptr *partials,double lo_loud_partial,double hi_loud_partial,float minamp,dataptr dz)
- {
- int n, m, k, maximi_less_one = MAXIMUM_PARTIAL - 1, endd = 0;
- double whole_number_ratio, comparison_frq;
- for(n=1;n<maximi_less_one;n++) {
- for(m=n+1;m<MAXIMUM_PARTIAL;m++) { /* NOV 7 */
- whole_number_ratio = (double)m/(double)n;
- comparison_frq = lo_loud_partial * whole_number_ratio;
- if(equivalent_pitches(comparison_frq,hi_loud_partial,dz))
- endd = (MAXIMUM_PARTIAL/m) * n; /* explanation at foot of file */
- else if(comparison_frq > hi_loud_partial)
- break;
- for(k=n;k<=endd;k+=n) {
- dz->param[PICH_PICH] = lo_loud_partial/(double)k;
- if(dz->param[PICH_PICH]>dz->param[PICH_HILM])
- continue;
- if(dz->param[PICH_PICH]<dz->param[PICH_LOLM])
- break;
- if(is_peak_at(dz->param[PICH_PICH],0,minamp,dz)){
- if(dz->iparam[PICH_MATCH] <= 2)
- return TRUE;
- else if(enough_partials_are_harmonics(partials,dz))
- return TRUE;
- }
- }
- }
- }
- return(FALSE);
- }
- /********************** FIND_PITCH_2 *****************************/
- int found_pitch_2(chvptr *partials,dataptr dz)
- {
- int m, n, k, good_match;
- int top_of_test = MAXIMI - dz->iparam[PICH_MATCH] + 1;
- double resolved_pitch, prevpitch,pitchdiff = 0.0;
- int diffcount = 0;
- for(n=0;n<top_of_test;n++) {
- for(m=1;m<=MAXHARM;m++) {
- dz->param[PICH_PICH] = (partials[n]->val)/(double)m;
- if(dz->param[PICH_PICH] > dz->param[PICH_HILM])
- continue;
- if(dz->param[PICH_PICH] < dz->param[PICH_LOLM])
- break;
- good_match = 1;
- prevpitch = dz->param[PICH_PICH];
- if(dz->iparam[PICH_MATCH] > 1) {
- for(k=n+1;k<MAXIMI;k++) {
- if(is_a_harmonic((double)(partials[k]->val),dz->param[PICH_PICH],dz)) {
- pitchdiff += (double)(partials[k]->val - prevpitch);
- prevpitch = (double)(partials[k]->val);
- diffcount++;
- if(++good_match >= dz->iparam[PICH_MATCH]) {
- resolved_pitch = pitchdiff / (double)diffcount;
- if(equivalent_pitches(resolved_pitch,dz->param[PICH_PICH],dz)){
- partials[0]->val = (float) resolved_pitch;
- dz->param[PICH_PICH] = resolved_pitch;
- }
- return TRUE;
- }
- }
- }
- }
- }
- }
- return(FALSE);
- }
- /************************ SMOOTH_SPURIOUS_OCTAVE_LEAPS ***************************/
- int smooth_spurious_octave_leaps(int pitchno,float minamp,dataptr dz)
- {
- #define ALMOST_TWO (1.75)
- double thispitch = dz->pitches[pitchno];
- double startpitch, lastpitch;
- int k = 0;
- if(pitchno<=0)
- return(FINISHED);
- lastpitch = dz->pitches[pitchno-1];
- if(lastpitch > dz->param[PICH_LOLM] && thispitch > dz->param[PICH_LOLM]) { /* OCTAVE ADJ HERE */
- if(thispitch > lastpitch) { /* OCTAVE ADJ FORWARDS */
- startpitch = thispitch;
- while(thispitch/lastpitch > ALMOST_TWO)
- thispitch /= 2.0;
- if(thispitch!=startpitch) {
- if(thispitch < dz->param[PICH_LOLM])
- return(FINISHED);
- if(is_peak_at(thispitch,0L,minamp,dz))
- dz->pitches[pitchno] = (float)thispitch;
- else
- dz->pitches[pitchno] = (float)startpitch;
- }
- return(FINISHED);
- } else {
- while(pitchno>=1) { /* OCTAVE ADJ BCKWARDS */
- k++;
- if((thispitch = dz->pitches[pitchno--])<dz->param[PICH_LOLM])
- return(FINISHED);
-
- if((lastpitch = dz->pitches[pitchno])<dz->param[PICH_LOLM])
- return(FINISHED);
-
- startpitch = lastpitch;
- while(lastpitch/thispitch > ALMOST_TWO)
- lastpitch /= 2.0;
-
- if(lastpitch!=startpitch) {
- if(lastpitch < dz->param[PICH_LOLM])
- return(FINISHED);
- if(is_peak_at(lastpitch,k,minamp,dz))
- dz->pitches[pitchno] = (float)lastpitch;
- else
- dz->pitches[pitchno] = (float)startpitch;
- }
- }
- }
- }
- return(FINISHED);
- }
- /**************************** EQUIVALENT_PITCHES *************************/
- int equivalent_pitches(double frq1, double frq2, dataptr dz)
- {
- double ratio;
- int iratio;
- double intvl;
- ratio = frq1/frq2;
- iratio = round(ratio);
- if(iratio!=1)
- return(FALSE);
- if(ratio > iratio)
- intvl = ratio/(double)iratio;
- else
- intvl = (double)iratio/ratio;
- if(intvl > dz->param[PICH_RNGE])
- return FALSE;
- return TRUE;
- }
- /*************************** IS_PEAK_AT ***************************/
- #define PEAK_LIMIT (.05)
- int is_peak_at(double frq,int window_offset,float minamp,dataptr dz)
- {
- float *thisbuf;
- int cc, vc, searchtop, searchbot;
- if(window_offset) { /* BAKTRAK ALONG BIGBUF, IF NESS */
- thisbuf = dz->flbufptr[0] - (window_offset * dz->wanted);
- if((int)thisbuf < 0 || thisbuf < dz->bigfbuf || thisbuf >= dz->flbufptr[1])
- return(FALSE);
- } else
- thisbuf = dz->flbufptr[0];
- cc = (int)((frq + dz->halfchwidth)/dz->chwidth); /* TRUNCATE */
- searchtop = min(dz->clength,cc + CHANSCAN + 1);
- searchbot = max(0,cc - CHANSCAN);
- for(cc = searchbot ,vc = searchbot*2; cc < searchtop; cc++, vc += 2) {
- if(!equivalent_pitches((double)thisbuf[vc+1],frq,dz)) {
- continue;
- }
- if(thisbuf[vc] < minamp * PEAK_LIMIT)
- continue;
- if(local_peak(cc,frq,thisbuf,dz))
- return TRUE;
- }
- return FALSE;
- }
- /**************************** ENOUGH_PARTIALS_ARE_HARMONICS *************************/
- int enough_partials_are_harmonics(chvptr *partials,dataptr dz)
- {
- int n, good_match = 0;
- double thisfrq;
- for(n=0;n<MAXIMI;n++) {
- if((thisfrq = dz->flbufptr[0][partials[n]->loc]) < dz->param[PICH_PICH])
- continue;
- if(is_a_harmonic(thisfrq,dz->param[PICH_PICH],dz)){
- if(++good_match >= dz->iparam[PICH_MATCH])
- return TRUE;
- }
- }
- return FALSE;
- }
- /**************************** IS_A_HARMONIC *************************/
- int is_a_harmonic(double frq1,double frq2,dataptr dz)
- {
- double ratio = frq1/frq2;
- int iratio = round(ratio);
- double intvl;
- ratio = frq1/frq2;
- iratio = round(ratio);
- if(ratio > iratio)
- intvl = ratio/(double)iratio;
- else
- intvl = (double)iratio/ratio;
- if(intvl > dz->param[PICH_RNGE])
- return(FALSE);
- return(TRUE);
- }
- /***************************** SPECTRACK *********************************/
- int spectrack(dataptr dz)
- {
- int exit_status;
- double thisfrq = dz->param[TRAK_PICH], frqtop, frqbot, maxamp;
- double outfrq = 0.0;
- int n = 0, vc = 0, passed_limit = 0, maxloc;
- while((thisfrq = dz->param[TRAK_PICH] * (double)++n) < dz->param[TRAK_HILM]) {
- frqtop = thisfrq * dz->param[TRAK_RNGE];
- frqbot = thisfrq / dz->param[TRAK_RNGE];
- if((exit_status = rectify_frqs(dz->flbufptr[0],dz))<0)
- return(exit_status);
- while(dz->flbufptr[0][FREQ] < frqbot) { /* JUMP OVER CHANNELS */
- if((vc+=2) >=dz->wanted) {
- outfrq = -1.0;
- passed_limit = 1;
- break;
- }
- }
- if(passed_limit) /* IF GONE PAST LIMIT */
- break; /* BREAK OUT OF LOOP */
- if(dz->flbufptr[0][FREQ]>frqtop) { /* IF OUTSIDE RANGE */
- outfrq = -1.0; /* BREAK OUT OF LOOP */
- break;
- }
- maxamp = dz->flbufptr[0][AMPP]; /* SET MAXAMP TO 1ST IN-RANGE CH */
- maxloc = vc; /* NOTE NO. OF CH THUS MARKED */
- while((vc+=2) < dz->wanted) {
- if(dz->flbufptr[0][FREQ]>frqtop) /* IF BEYOND CURRENT RANGE, STOP */
- break;
- if(dz->flbufptr[0][AMPP]>maxamp) { /* IF LOUDER THAN MAX, RESET MAX */
- maxamp = dz->flbufptr[0][AMPP]; /* AND RESET MAXAMP CHANNEL NO. */
- maxloc = vc;
- }
- }
- outfrq = dz->flbufptr[0][maxloc+1];
- }
- if(outfrq>MINPITCH) /* If pitch has been found */
- dz->param[TRAK_PICH] = outfrq; /* reset goal pitch to this */
- dz->pitches[dz->total_windows] = (float)outfrq;
- return(FINISHED);
- }
- /**************************** OUTER_PICHPICH_LOOP *********************/
- int outer_pichpich_loop(dataptr dz)
- {
- int exit_status, valid_pitch_data = FALSE;
- int final_length_in_windows = dz->wlength, n;
- double lastmidi;
- if(dz->is_transpos) {
- if((dz->transpos = (float *)malloc(dz->wlength * sizeof(float)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for transpositions array.\n");
- return(MEMORY_ERROR);
- }
- for(n=0;n<dz->wlength;n++)
- dz->transpos[n] = 1.0f; /* DEFAULT: no transposition */
- }
- for(n=0;n<dz->wlength;n++) {
- if(dz->pitches[n] > FLTERR) {
- valid_pitch_data = 1;
- break;
- }
- }
- if(!valid_pitch_data) {
- sprintf(errstr,"No valid pitches found in input data.\n");
- return(DATA_ERROR);
- }
- switch(dz->process) {
- case(P_APPROX):
- if((exit_status = specpapprox(&final_length_in_windows,&lastmidi,dz))<0)
- return(exit_status);
- if((exit_status = trap_junk(final_length_in_windows,dz))<0)
- return(exit_status);
- return write_remaining_pitch_or_transpos_data(final_length_in_windows,dz);
- case(P_CUT):
- if((exit_status = specpcut(&final_length_in_windows,dz))<0)
- return(exit_status);
- return write_remaining_pitch_or_transpos_data(final_length_in_windows,dz);
- case(P_EXAG):
- if((exit_status = specpexag(dz))<0)
- return(exit_status);
- break;
- case(P_INVERT):
- if((exit_status = specpinvert(dz))<0)
- return(exit_status);
- break;
- case(P_QUANTISE):
- if((exit_status = specpquantise(dz))<0)
- return(exit_status);
- break;
- case(P_RANDOMISE):
- if((exit_status = specprand(dz))<0)
- return(exit_status);
- break;
- case(P_SMOOTH):
- if((exit_status = specpsmooth(dz))<0)
- return(exit_status);
- break;
- case(P_TRANSPOSE):
- if((exit_status = specptranspose(dz))<0)
- return(exit_status);
- break;
- case(P_VIBRATO):
- if((exit_status = specpvib(dz))<0)
- return(exit_status);
- break;
- case(P_SYNTH):
- return generate_tone(dz);
- break;
- case(P_VOWELS):
- return generate_vowels(dz);
- break;
- case(P_INSERT):
- if((exit_status = pitch_insert(0,dz)) < 0)
- return(exit_status);
- return write_pitch_or_transpos_data(final_length_in_windows,dz);
- break;
- case(P_SINSERT):
- if((exit_status = pitch_insert(1,dz)) < 0)
- return(exit_status);
- return write_pitch_or_transpos_data(final_length_in_windows,dz);
- break;
- case(P_PTOSIL):
- if((exit_status = pitch_to_silence(dz)) < 0)
- return(exit_status);
- return write_pitch_or_transpos_data(final_length_in_windows,dz);
- break;
- case(P_NTOSIL):
- if((exit_status = unpitch_to_silence(dz)) < 0)
- return(exit_status);
- return write_pitch_or_transpos_data(final_length_in_windows,dz);
- break;
- case(P_INTERP):
- if((exit_status = remove_pitch_zeros(dz)) < 0)
- return(exit_status);
- return write_pitch_or_transpos_data(dz->wlength,dz);
- break;
- default:
- sprintf(errstr,"Unknown process in outer_pichpich_loop()\n");
- return(PROGRAM_ERROR);
- }
- if((exit_status = trap_junk(final_length_in_windows,dz))<0)
- return(exit_status);
- return write_pitch_or_transpos_data(final_length_in_windows,dz);
- }
- /************************** SPECPAPPROX ************************/
- int specpapprox(int *newlength_of_data,double *lastmidi,dataptr dz)
- {
- int exit_status;
- int avcnt;
- int n = 0, diff;
- int is_firstime = TRUE;
- int lastpos = 0;
- *newlength_of_data = dz->wlength;
- initrand48();
- if((exit_status = get_pitchapprox_averages(&avcnt,dz))<0)
- return(exit_status);
- if((dz->iparray[PA_CHANGE] = (int *)malloc(avcnt * sizeof(int)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for pitch approximation array.\n");
- return(MEMORY_ERROR);
- }
- if((exit_status = get_statechanges(avcnt,PA_SRANG,PA_AVPICH,PA_CHANGE,SEMITONE_INTERVAL,SEMITONE_DOWN,IS_FRQ,dz))<0)
- return(exit_status);
- while(dz->parray[PA_AVPICH][n]<0.0) {
- if(++n>=avcnt) {
- sprintf(errstr,"No valid pitch-average data found.\n");
- return(DATA_ERROR); /* ??? */
- }
- }
- dz->iparray[PA_CHANGE][n] = 1;
- for(;n<avcnt;n++) {
- if(dz->iparray[PA_CHANGE][n]) {
- if((exit_status = approx_func1(newlength_of_data,&is_firstime,lastmidi,&lastpos,n,dz))<0)
- return(exit_status);
- if(exit_status==FINISHED)
- break;
- }
- }
- if((diff = (dz->wlength-1) - lastpos) > 0
- && (exit_status = approx_func2(newlength_of_data,*lastmidi,lastpos,avcnt,dz))<0)
- return(exit_status);
- return(FINISHED);
- }
- /***************************** SPECPCUT ***************************/
- int specpcut(int *final_length_in_windows,dataptr dz)
- {
- int m, n;
- int startcut = 0;
- int endcut = dz->wlength;
- if(dz->mode != PCUT_START_ONLY) /* is_endtime */
- endcut = round(dz->param[PC_END]/dz->frametime);
- if(dz->mode != PCUT_END_ONLY) /* is_starttime */
- startcut = round(dz->param[PC_STT]/dz->frametime);
- for(m = 0, n = startcut; n < endcut; n++, m++)
- dz->pitches[m] = dz->pitches[n];
- *final_length_in_windows = endcut - startcut;
- return(FINISHED);
- }
- /************************************* SPECPEXAG ******************************/
- int specpexag(dataptr dz)
- {
- int exit_status;
- int n;
- double thismidi, maxmidi, minmidi, variance, thispich;
- double maxpitch = FLTERR, minpitch = dz->nyquist, meanpich, maxint, minint;
- dz->time = 0.0f;
- if((exit_status = get_max_and_min_pitches(&maxpitch,&minpitch,dz))<0)
- return(exit_status);
- if((exit_status = hztomidi(&maxmidi,maxpitch))<0)
- return(exit_status);
- if((exit_status = hztomidi(&minmidi,minpitch))<0)
- return(exit_status);
- for(n=0;n<dz->wlength;n++) {
- if(dz->pitches[n]<MINPITCH)
- continue;
- if((exit_status = read_values_from_all_existing_brktables((double)dz->time,dz))<0)
- return(exit_status);
- meanpich = miditohz(dz->param[PEX_MEAN]);
- thispich = dz->pitches[n];
- /* contour variable specified */
- if(dz->mode != RANGE_ONLY_TO_P && dz->mode != RANGE_ONLY_TO_T) {
- if((exit_status = hztomidi(&thismidi,thispich))<0)
- return(exit_status);
- maxint = maxmidi - dz->param[PEX_MEAN];
- minint = dz->param[PEX_MEAN] - minmidi;
- if(thismidi >= dz->param[PEX_MEAN])
- variance = ((thismidi - dz->param[PEX_MEAN])/12.0)/maxint;
- else
- variance = ((dz->param[PEX_MEAN] - thismidi)/12.0)/minint;
- if(!flteq(variance,0.0))
- variance = pow(variance,dz->param[PEX_CNTR]);
- if(thismidi>=dz->param[PEX_MEAN])
- thispich = (float)(pow(maxpitch,variance) * pow(meanpich,(1.0-variance)));
- else
- thispich = (float)(pow(minpitch,variance) * pow(meanpich,(1.0-variance)));
- }
- if(dz->mode != CONTOUR_ONLY_TO_P && dz->mode != CONTOUR_ONLY_TO_T) {
- /* range variable specified */
- if((exit_status = hztomidi(&thismidi,thispich))<0)
- return(exit_status);
- thismidi = dz->param[PEX_MEAN] + ((thismidi - dz->param[PEX_MEAN])
- * dz->param[PEX_RANG]);
- thispich = (float)miditohz(thismidi);
- }
- if(dz->is_transpos) { /* transpos output */
- dz->transpos[n] = (float)(thispich/dz->pitches[n]);
- check_transpos(&(dz->transpos[n]),dz);
- } else {
- dz->pitches[n] = (float)thispich;
- check_pitch(&(dz->pitches[n]),dz);
- }
- dz->time = (float)(dz->time + dz->frametime);
- }
- return(FINISHED);
- }
- /****************************** SPECPFIX ********************************/
-
- int specpfix(dataptr dz)
- {
- int exit_status;
- if(dz->iparam[PF_ISCUT] && (exit_status = do_pitch_cut(dz))<0)
- return(exit_status);
- if(dz->iparam[PF_ISFILTER] && (exit_status = do_pitch_filter(dz))<0)
- return(exit_status);
- if(dz->vflag[PF_IS_SMOOTH] && (exit_status = do_pitch_smoothing(dz))<0)
- return(exit_status);
- if(dz->vflag[PF_IS_SMARK])
- dz->pitches[0] = (float)dz->param[PF_SMARK];
- if(dz->vflag[PF_IS_EMARK])
- dz->pitches[dz->wlength-1] = (float)dz->param[PF_EMARK];
- if(dz->vflag[PF_INTERP] && (exit_status = interpolate_pitch(dz->pitches,1,dz))<0)
- return(exit_status);
- return write_exact_samps(dz->pitches,dz->wlength,dz);
- }
- /************************** SPECPINVERT ************************/
- int specpinvert(dataptr dz)
- {
- int exit_status;
- int n;
- double midimean = 0.0, thismidi, thisint;
- dz->time = 0.0f;
- if(!dz->vflag[PI_IS_MEAN]) {
- if((exit_status = get_midimean(&midimean,dz))<0)
- return(exit_status);
- } else
- midimean = dz->param[PI_MEAN];
- for(n=0;n<dz->wlength;n++) {
- if(dz->pitches[n]<MINPITCH)
- continue;
- if((exit_status = read_values_from_all_existing_brktables((double)dz->time,dz))<0)
- return(exit_status);
- if((exit_status = hztomidi(&thismidi,dz->pitches[n]))<0)
- return(exit_status);
- if(dz->is_mapping) {
- if((exit_status = interval_mapping(&thisint,thismidi - midimean,dz))<0)
- return(exit_status);
- thismidi = max(dz->param[PI_BOT],min(dz->param[PI_TOP],midimean + thisint));
- } else
- thismidi = min(dz->param[PI_TOP],max(dz->param[PI_BOT],((2.0 * midimean) - thismidi)));
- if(dz->is_transpos) {
- dz->transpos[n] = (float)(miditohz(thismidi)/dz->pitches[n]);
- check_transpos(&(dz->transpos[n]),dz);
- } else {
- dz->pitches[n] = (float)miditohz(thismidi);
- check_pitch(&(dz->pitches[n]),dz);
- }
- dz->time = (float)(dz->time + dz->frametime);
- }
- return(FINISHED);
- }
- /************************************** SPECPQUANTISE **************************/
- int specpquantise(dataptr dz)
- {
- int exit_status;
- int n;
- int got;
- double *p, thismidi;
- double *pend = dz->parray[PQ_QSET] + dz->itemcnt;
- for(n=0;n<dz->wlength;n++) {
- if(dz->pitches[n]<MINPITCH)
- continue;
- got = 0;
- p = dz->parray[PQ_QSET];
- if((exit_status = hztomidi(&thismidi,dz->pitches[n]))<0)
- return(exit_status);
- if(*p >= thismidi) {
- if((exit_status = set_pval(*p,n,dz))<0)
- return(exit_status);
- continue;
- }
- while(*p < thismidi) {
- if(++p >= pend) {
- p--;
- if((exit_status = set_pval(*p,n,dz))<0)
- return(exit_status);
- got = 1;
- break;
- }
- }
- if(got)
- continue;
- if((*p - thismidi) > (thismidi - *(p-1))) {
- if((exit_status = set_pval(*(p-1),n,dz))<0)
- return(exit_status);
- } else {
- if((exit_status = set_pval(*p,n,dz))<0)
- return(exit_status);
- }
- }
- return(FINISHED);
- }
- /***************************************** SPECPRAND *********************/
- int specprand(dataptr dz)
- {
- int exit_status;
- int n = 0, lastn, m, thiswstep, diff, z;
- double thisintv, ttime = 0.0, lastmidi, thismidi, mididiff, midistep;
- initrand48();
- while(dz->pitches[n]<MINPITCH) {
- if(++n>=dz->wlength) {
- sprintf(errstr,"No valid pitchdata found in pitch file.\n");
- return(DATA_ERROR);
- }
- }
- if((exit_status = hztomidi(&lastmidi,dz->pitches[n]))<0)
- return(exit_status);
- ttime = dz->frametime * (double)n;
- if((exit_status = read_values_from_all_existing_brktables(ttime,dz))<0)
- return(exit_status);
- if((exit_status = get_rand_interval(&thisintv,dz))<0)
- return(exit_status);
- lastmidi += thisintv;
- if((exit_status = set_pval(lastmidi,n,dz))<0)
- return(exit_status);
- lastn = n;
- do {
- thiswstep = round(max(dz->frametime,drand48() * dz->param[PR_TSTEP])/dz->frametime);
- if((n += thiswstep) >= dz->wlength) {
- sprintf(errstr,"Too much unpitched data in file to proceed this time. But try again.\n");
- return(DATA_ERROR);
- }
- ttime = dz->frametime * (double)n;
- if(dz->brksize[PR_TSTEP]) {
- if((exit_status = read_value_from_brktable(ttime,PR_TSTEP,dz))<0)
- return(exit_status);
- }
- } while(dz->pitches[n]<MINPITCH);
- while(n<dz->wlength) {
- if(dz->brksize[PR_MXINT]) {
- if((exit_status = read_value_from_brktable(ttime,PR_MXINT,dz))<0)
- return(exit_status);
- }
- if((exit_status = get_rand_interval(&thisintv,dz))<0)
- return(exit_status);
- if((exit_status = hztomidi(&thismidi,dz->pitches[n]))<0)
- return(exit_status);
- thismidi += thisintv;
- mididiff = thismidi - lastmidi;
- diff = n - lastn;
- midistep = mididiff/(double)diff;
- for(m = lastn+1;m<=n;m++) { /* Interp pitch between randomised points */
- if(dz->pitches[m] < MINPITCH)
- continue;
- lastmidi += midistep;
- if((exit_status = set_pval(lastmidi,m,dz))<0)
- return(exit_status);
- }
- lastmidi = thismidi;
- lastn = n;
- do {
- if(dz->brksize[PR_TSTEP]) {
- if((exit_status = read_value_from_brktable(ttime,PR_TSTEP,dz))<0)
- return(exit_status);
- }
- thiswstep = round(max(dz->frametime,drand48() * dz->param[PR_TSTEP])/dz->frametime);
- if((n+=thiswstep) > dz->wlength)
- break;
- ttime = dz->frametime * (double)n;
- } while(dz->pitches[n]<MINPITCH);
- }
- if(lastn < dz->wlength-1) {
- z = dz->wlength - 1;
- while(dz->pitches[z]<MINPITCH) {
- if(--z<=lastn)
- return(FINISHED);
- }
- n = z;
- thisintv = ((drand48() * 2.0) - 1.0) * dz->param[PR_MXINT];
- if((exit_status = hztomidi(&thismidi,dz->pitches[n]))<0)
- return(exit_status);
- thismidi += thisintv;
- mididiff = thismidi - lastmidi;
- if((diff = n - lastn)<2)
- return(FINISHED);
- midistep = mididiff/(double)diff;
- for(m = lastn+1;m<=n;m++) {
- if(dz->pitches[n]<MINPITCH)
- continue;
- lastmidi += midistep;
- if((exit_status = set_pval(lastmidi,m,dz))<0)
- return(exit_status);
- }
- }
- return(FINISHED);
- }
- /*************************************** SPECPSMOOTH ***********************************/
- int specpsmooth(dataptr dz)
- {
- int exit_status;
- double ttime = 0.0, maxpitch = FLTERR, minpitch = dz->nyquist,
- maxmidi, minmidi, lastmidi;
- double meanpich, maxint, minint, startmidi, endmidi, thismidi, mdiff, step;
- int lastmaxpos = 0, n=0, m, z, interpfact, lastn;
- if((exit_status = get_max_and_min_pitches(&maxpitch,&minpitch,dz))<0)
- return(exit_status);
- if((exit_status = hztomidi(&maxmidi,maxpitch))<0)
- return(exit_status);
- if((exit_status = hztomidi(&minmidi,minpitch))<0)
- return(exit_status);
- n = 0;
- while(dz->pitches[n]<MINPITCH) {
- if(++n >= dz->wlength) {
- sprintf(errstr,"No valid data in pitchfile\n");
- return(DATA_ERROR);
- }
- }
- if(dz->is_transpos)
- dz->transpos[n] = 1.0f;
- if((exit_status = hztomidi(&lastmidi,dz->pitches[n]))<0)
- return(exit_status);
- ttime = (double)n * dz->frametime;
- if((exit_status = read_values_from_all_existing_brktables(ttime,dz))<0)
- return(exit_status);
- interpfact = round(dz->param[PS_TFRAME]/dz->frametime);
- lastn = n;
- do {
- if((n += interpfact) >=dz->wlength) {
- sprintf(errstr,"Too much unpitched data in file: cannot proceed. Try different interpfact(s).\n");
- return(DATA_ERROR);
- }
- ttime = (double)n * dz->frametime;
- if(dz->brksize[PS_TFRAME]) {
- if((exit_status = read_value_from_brktable(ttime,PS_TFRAME,dz))<0)
- return(exit_status);
- interpfact = round(dz->param[PS_TFRAME]/dz->frametime);
- }
- } while(dz->pitches[n]<MINPITCH);
- if(dz->vflag[PS_MEANP]) {
- meanpich = miditohz(dz->param[PS_MEAN]);
- maxint = maxmidi - dz->param[PS_MEAN];
- minint = dz->param[PS_MEAN] - minmidi;
- while(n<dz->wlength) {
- if((exit_status = peak_interp(n,lastn,&lastmaxpos,meanpich,minint,maxint,&lastmidi,dz))<0)
- return(exit_status);
- if(dz->brksize[PS_TFRAME]) {
- if((exit_status = read_value_from_brktable(ttime,PS_TFRAME,dz))<0)
- return(exit_status);
- interpfact = round(dz->param[PS_TFRAME]/dz->frametime);
- }
- if(dz->brksize[PS_MEAN]) {
- if((exit_status = read_value_from_brktable(ttime,PS_MEAN,dz))<0)
- return(exit_status);
- meanpich = miditohz(dz->param[PS_MEAN]);
- maxint = maxmidi - dz->param[PS_MEAN];
- minint = dz->param[PS_MEAN] - minmidi;
- }
- lastn = n;
- do{
- if((n += interpfact) >= dz->wlength)
- break;
- ttime = (double)n * dz->frametime;
- if(dz->brksize[PS_TFRAME]) {
- if((exit_status = read_value_from_brktable(ttime,PS_TFRAME,dz))<0)
- return(exit_status);
- interpfact = round(dz->param[PS_TFRAME]/dz->frametime);
- }
- } while(dz->pitches[n]<MINPITCH);
- }
- n = lastmaxpos;
- } else {
- while(n<dz->wlength) {
- z = n - lastn;
- if((exit_status = hztomidi(&startmidi,dz->pitches[lastn]))<0)
- return(exit_status);
- if((exit_status = hztomidi(&endmidi,dz->pitches[n]))<0)
- return(exit_status);
- mdiff = endmidi - startmidi;
- step = mdiff/(double)z;
- for(m=1;m<=z;m++) {
- if(dz->pitches[m+lastn]<MINPITCH)
- continue;
- thismidi = startmidi + (step * (double)m);
- if((exit_status = set_pval(thismidi,m+lastn,dz))<0)
- return(exit_status);
- }
- lastn = n;
- do{
- if((n += interpfact) >=dz->wlength)
- break;
- ttime = (float)((double)n * dz->frametime);
- if(dz->brksize[PS_TFRAME]) {
- if((exit_status = read_value_from_brktable(ttime,PS_TFRAME,dz))<0)
- return(exit_status);
- interpfact = round(dz->param[PS_TFRAME]/dz->frametime);
- }
- } while(dz->pitches[n]<MINPITCH);
- }
- n = lastn;
- if((exit_status = hztomidi(&lastmidi,dz->pitches[n]))<0)
- return(exit_status);
- }
- if(n < dz->wlength-1)
- if((exit_status = do_tail(n,lastmidi,dz))<0)
- return(exit_status);
- return(FINISHED);
- }
- /***************************** SPECPTRANSPOSE *****************/
- int specptranspose(dataptr dz)
- {
- int n;
- for(n=0;n<dz->wlength;n++) {
- if(dz->pitches[n]<MINPITCH)
- continue;
- dz->pitches[n] = (float)(dz->pitches[n] * dz->param[PT_TVAL]);
- check_pitch(&(dz->pitches[n]),dz);
- }
- return(FINISHED);
- }
- /***************************** SPECPVIB *****************/
- int specpvib(dataptr dz)
- {
- int exit_status;
- double indexf = 0.0, intvl, indexstep;
- int index = 0;
- int n;
- dz->time = 0.0f;
- if((exit_status = read_values_from_all_existing_brktables((double)dz->time,dz))<0)
- return(exit_status);
- indexstep = dz->param[PV_FRQ] * dz->frametime * (double)P_TABSIZE;
- for(n=0;n<dz->wlength;n++) {
- if(dz->pitches[n]<MINPITCH)
- continue;
- intvl = dz->parray[PV_SIN][index] * dz->param[PV_RANG];
- intvl = pow(SEMITONE_INTERVAL,intvl);
- if(dz->is_transpos) {
- dz->transpos[n] = (float)intvl;
- check_transpos(&(dz->transpos[n]),dz);
- } else {
- dz->pitches[n] = (float)(dz->pitches[n] * intvl);
- check_pitch(&(dz->pitches[n]),dz);
- }
- indexf += indexstep;
- index = round(indexf) % P_TABSIZE;
- dz->time = (float)(dz->time + dz->frametime);
- if(dz->brksize[PV_FRQ]) {
- if((exit_status = read_value_from_brktable((double)dz->time,PV_FRQ,dz))<0)
- return(exit_status);
- indexstep = dz->param[PV_FRQ] * dz->frametime * (double)P_TABSIZE;
- }
- if(dz->brksize[PV_RANG]) {
- if((exit_status = read_value_from_brktable((double)dz->time,PV_RANG,dz))<0)
- return(exit_status);
- }
- }
- return(FINISHED);
- }
- /*************************** SPECREPITCH ********************/
- int specrepitch(dataptr dz)
- {
- int exit_status;
- int n, brklen;
- float frametime;
- if(dz->wlength == 0) { /* brkpnt only data entered */
- dz->wlength = round(dz->duration/DEFAULT_FRAMETIME);
- frametime = DEFAULT_FRAMETIME;
- } else
- frametime = dz->frametime;
- switch(dz->mode) {
- case(PPT): case(PPT_TO_BRK): /* PPT */
- if((dz->transpos = (float *)malloc(dz->wlength * sizeof(float)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for transpositions array.\n");
- return(MEMORY_ERROR);
- }
- for(n=0;n<dz->wlength;n++) {
- if(dz->pitches[n]<MINPITCH || dz->pitches2[n]<MINPITCH)
- dz->transpos[n] = 1.0f;
- else
- dz->transpos[n] = (float)(dz->pitches2[n]/dz->pitches[n]);
- check_transpos(&(dz->transpos[n]),dz);
- }
- break;
- case(PTP): case(PTP_TO_BRK): /* PTP */
- for(n=0;n<dz->wlength;n++) {
- if(dz->pitches[n] < MINPITCH)
- continue;
- dz->pitches[n] = (float)(dz->pitches[n] * dz->transpos[n]);
- check_pitch(&(dz->pitches[n]),dz);
- }
- break;
- case(TTT): case(TTT_TO_BRK): /* TTT */
- for(n=0;n<dz->wlength;n++) {
- dz->transpos[n] = (float)(dz->transpos[n] * dz->transpos2[n]);
- check_transpos(&(dz->transpos[n]),dz);
- }
- break;
- default:
- sprintf(errstr,"unknown case in specrepitch()\n");
- return(PROGRAM_ERROR);
- }
- switch(dz->mode) {
- case(PTP): /* out P-bin */
- if((exit_status = write_samps(dz->pitches,dz->wlength,dz))<0)
- return(exit_status);
- break;
- case(PPT):
- case(TTT): /* out T-bin */
- dz->outfiletype = TRANSPOS_OUT;
- if((exit_status = write_samps(dz->transpos,dz->wlength,dz))<0)
- return(exit_status);
- dz->is_transpos = TRUE;
- break;
- case(PTP_TO_BRK): /* P-brk out */
- if((dz->parray[RP_TBRK]
- = (double *)malloc(dz->wlength * sizeof(double) * 2))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for pitch brkpnt array.\n");
- return(MEMORY_ERROR);
- }
- if((exit_status = interpolate_pitch(dz->pitches,0,dz))<0)
- return(exit_status);
- if((exit_status = convert_pch_or_transpos_data_to_brkpnttable(
- &brklen,dz->pitches,frametime,RP_TBRK,dz))<0)
- return(exit_status);
- if((exit_status = write_brkfile(dz->fp,brklen,RP_TBRK,dz))<0)
- return(exit_status);
- break;
- case(PPT_TO_BRK):
- case(TTT_TO_BRK): /* T_brk out */
- if((dz->parray[RP_TBRK]
- = (double *)malloc(dz->wlength * sizeof(double) * 2))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for transposition brkpnt array.\n");
- return(MEMORY_ERROR);
- }
- if((exit_status = convert_pch_or_transpos_data_to_brkpnttable(&brklen,dz->transpos,frametime,RP_TBRK,dz))<0)
- return(exit_status);
- if((exit_status = write_brkfile(dz->fp,brklen,RP_TBRK,dz))<0)
- return(exit_status);
- break;
- }
- return(FINISHED);
- }
- /******************************* DO_PITCH_CUT ******************************/
- int do_pitch_cut(dataptr dz)
- { int n;
- for(n=dz->iparam[PF_SCUTW];n<dz->iparam[PF_ECUTW];n++)
- dz->pitches[n] = (float)NOT_PITCH;
- return(FINISHED);
- }
- /************************* DO_PITCH_SMOOTHING ***************************/
- int do_pitch_smoothing(dataptr dz)
- {
- int exit_status;
- int z;
- int first_valid_pitch, n, wlength_less_2 = dz->wlength - 2;
- double *slopechange;
- if((slopechange = (double *)malloc(dz->wlength * sizeof(double)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for slopechange array.\n");
- return(MEMORY_ERROR);
- }
- for(z=0;z<dz->iparam[PF_SMOOTH];z++) {
- if((exit_status = skip_to_first_pitch(&first_valid_pitch,dz))<0)
- return(exit_status);
- if((exit_status = calc_slopechanges(first_valid_pitch,slopechange,dz))<0)
- return(exit_status);
- for(n=1;n<wlength_less_2;n++) {
- if(fabs(slopechange[n]) > GLARG) {
- if(dz->pitches[n+1]<0.0)
- continue;
- if((exit_status = is_start_of_glitch(n,slopechange,dz))<0)
- return(exit_status);
- if(exit_status==TRUE)
- continue; /* WILL BE SMOOTHED OUT AT NEXTSTEP */
- if(dz->pitches[n-1]<MINPITCH) { /* ONSET SMOOTH */
- if((exit_status = do_onset_smooth(n,slopechange,dz))<0)
- return(exit_status);
- continue;
- }
- if(n>=2 && dz->pitches[n-2]<MINPITCH) { /* DOUBLE ONSET SMOOTH */
- if((exit_status = do_double_onset_smooth(n,slopechange,dz))<0)
- return(exit_status);
- continue;
- } /* NORMAL SMOOTH */
- if((exit_status = do_smooth(n,slopechange,dz))<0)
- return(exit_status);
- }
- }
- }
- free(slopechange);
- return(FINISHED);
- }
- /****************************** DO_SMOOTH **************************
- *
- * Including checking for end of a pitched segment.
- */
- int do_smooth(int pitchno,double *slopechange,dataptr dz)
- {
- double val, val0, val1;
- if(slopechange[pitchno+1] > GLARG && pitchno>=1) {
- if(pitchno+2 < dz->wlength && dz->pitches[pitchno+2] < 0.0) {
- val0 = log10(dz->pitches[pitchno-1]); /* TAIL */
- val1 = log10(dz->pitches[pitchno]);
- val = val1 - val0;
- dz->pitches[pitchno+1] = (float)pow((double)10,(val1 + val));
- slopechange[pitchno] = 0.0; /* CORRECT SLOPECHANGE APPROPRIATELY */
- slopechange[pitchno+1] = 0.0; /* AVOID SPURIOUS SMOOTH AT END_OF_TAIL PITCH */
- return(FINISHED);
- } else {
- if(pitchno+3 < dz->wlength && dz->pitches[pitchno+3] < MINPITCH) {
- val0 = log10(dz->pitches[pitchno-1]); /* DOUBLE TAIL */
- val1 = log10(dz->pitches[pitchno]);
- val = val1 - val0;
- dz->pitches[pitchno+1] = (float)pow((double)10,(val1 + val));
- val += val;
- dz->pitches[pitchno+2] = (float)pow((double)10,(val1 + val));
- slopechange[pitchno] = 0.0; /* CORRECT SLOPECHANGES APPROPRIATELY */
- slopechange[pitchno+1] = 0.0;
- slopechange[pitchno+2] = 0.0; /* AVOID SPURIOUS SMOOTH AT END_OF_TAIL PITCH */
- return(FINISHED);
- }
- }
- } /* NORMAL */
- val0 = log10(dz->pitches[pitchno-1]);
- val1 = log10(dz->pitches[pitchno+1]);
- val = (val0 + val1)/2.0;
- dz->pitches[pitchno] = (float)pow((double)10,val);
- slopechange[pitchno] = 0.0; /* CORRECT SLOPECHANGE APPROPRIATELY */
- return(FINISHED);
- }
- /************************ SKIP_TO_FIRST_PITCH ***********************/
- int skip_to_first_pitch(int *first_pitch,dataptr dz)
- {
- *first_pitch = 0;
- while(dz->pitches[*first_pitch] < MINPITCH) {
- if(++(*first_pitch) >= dz->wlength) {
- sprintf(errstr,"No pitch data found.\n");
- return(DATA_ERROR);
- }
- }
- if(++(*first_pitch) >= dz->wlength) {
- sprintf(errstr,"No pitch data found.\n");
- return(DATA_ERROR);
- }
- return(FINISHED);
- }
- /************************* CALC_SLOPECHANGES ***********************/
- int calc_slopechanges(int first_valid_pitch,double *slopechange,dataptr dz)
- {
- int n, k, wlength_less_1 = dz->wlength - 1;
- int OK = 1;
- double preslope = 0.0, postslope;
- for(n=0;n<dz->wlength;n++)
- slopechange[n] = 0.0;
- for(n = first_valid_pitch;n<wlength_less_1;n++) {
- k = 1;
- while(dz->pitches[n+k] < 0.0) {
- k++;
- if(k+n >= dz->wlength) {
- OK = 0;
- break;
- }
- if(!OK)
- break;
- }
- if(!OK)
- break;
- postslope = (log10(dz->pitches[n+k]) - log10(dz->pitches[n]))/(double)k;
- slopechange[n] = postslope - preslope;
- n += k - 1;
- preslope = postslope;
- }
- return(FINISHED);
- }
- /********************** IS_START_OF_GLITCH **********************
- *
- * WITHOUT THOROUGH CHECK worried that logs may get 0 or -ve vals..
- */
- int is_start_of_glitch(int pitchno,double *slopechange,dataptr dz)
- {
- double val, val0, val1;
- if(dz->vflag[PF_TWOW]) {
- if(pitchno+3 < dz->wlength-1
- && fabs(slopechange[pitchno+1]) > GLARG
- && fabs(slopechange[pitchno+2]) > GLARG
- && fabs(slopechange[pitchno+3]) > GLARG
- && ((slopechange[pitchno] > 0.0
- && slopechange[pitchno+1] < 0.0
- && slopechange[pitchno+2] < 0.0
- && slopechange[pitchno+3] > 0.0) /* +--+ */
- || (slopechange[pitchno] < 0.0
- && slopechange[pitchno+1] > 0.0
- && slopechange[pitchno+2] < 0.0
- && slopechange[pitchno+3] > 0.0) /* -++- */
- )
- ){
- val0 = log10(dz->pitches[pitchno]);
- val1 = log10(dz->pitches[pitchno+3]);
- val = (val1 - val0)/3.0; /* 2 WINDOW GLITCH */
- val0 = log10(dz->pitches[pitchno] + val);
- dz->pitches[pitchno+1] = (float)pow((double)10,val0);
- val += val;
- val1 = log10(dz->pitches[pitchno] + val);
- dz->pitches[pitchno+2] = (float)pow((double)10,val1);
- slopechange[pitchno+1] = 0.0;
- slopechange[pitchno+2] = 0.0;
- return(TRUE);
- }
- }
- if(fabs(slopechange[pitchno+1]) > GLARG
- && fabs(slopechange[pitchno+2]) > GLARG
- && ((slopechange[pitchno] > 0.0
- && slopechange[pitchno+1] < 0.0
- && slopechange[pitchno+2] > 0.0) /* +-+ */
- || (slopechange[pitchno] < 0.0
- && slopechange[pitchno+1] > 0.0
- && slopechange[pitchno+2] < 0.0) /* -+- */
- )
- )
- return(TRUE);
- return(FALSE);
- }
- /*********************** DO_ONSET_SMOOTH ********************/
- int do_onset_smooth(int pitchno, double *slopechange,dataptr dz)
- {
- double val, val0, val1;
- if(dz->pitches[pitchno+2] < MINPITCH)
- return(FINISHED);
- val0 = log10(dz->pitches[pitchno+1]);
- val1 = log10(dz->pitches[pitchno+2]);
- val = (2.0 * val0) - val1;
- dz->pitches[pitchno] = (float)pow((double)10,val);
- slopechange[pitchno+1] = 0.0; /* CHANGE OF SLOPE HENCE BECOMES ZERO AT NEXT PITCH */
- return(FINISHED);
- } /* THIS ALSO PREVENTS double_onset BEING CALLED SPURIOUSLY */
- /************************ DO_DOUBLE_ONSET_SMOOTH ********************
- *
- * NORMAL DOUBLE ONSET GLITCH SITUATION TO BE AVOIDED
- * .
- * .
- * .
- * postslope .
- * ...... X---X---X X
- * / / \postslope
- * / / \
- * X---X X---X X---X
- * | |
- * | |
- * 0...| 0...|
- *
- * X
- * |\
- * reverse predict from postslope, OK | \reverse predict from postslope
- * X---X---X---X---X | \ gives spurious glitch
- * | | X
- * | | \
- * | | \
- * | | \
- * | | X
- * 0...| | \
- * | \
- * | X---X
- * |
- * |
- * 0...|
- * ,X
- * / \
- * interp instead ,X \
- * / \
- * X X---X
- * |
- * |
- * 0...|
- *
- * and at next pass, there'll probably be a 2nd interp thus..
- *
- * ,X.
- * / 'X.
- * X ' X---X
- * |
- * |
- * 0...|
- *
- *
- */
- int do_double_onset_smooth(int pitchno,double *slopechange,dataptr dz)
- {
- double val, val0, val1, preslope, postslope, pn0 ,pn1, pn2;
- if(dz->pitches[pitchno+2] < MINPITCH)
- return(FINISHED);
- pn0 = log10(dz->pitches[pitchno]);
- pn1 = log10(dz->pitches[pitchno+1]);
- pn2 = log10(dz->pitches[pitchno+2]);
- preslope = fabs(pn1 - pn0);
- postslope = fabs(pn2 - pn1);
- if(postslope > preslope * SLOPE_FUDGE) { /* 1 */
- val0 = log10(dz->pitches[pitchno-1]); /* IF SLOPE AHEAD LOOKS TOO BIG */
- val1 = pn1; /* DON'T RISK USING IT TO GET VALS HERE. */
- val = (val0 + val1)/2.0; /* INTERP INSTEAD */
- dz->pitches[pitchno] = (float)pow((double)10,val);
- slopechange[pitchno] = 0.0; /* CORRECT SLOPECHANGE APPROPRIATELY */
- } else {
- val0 = pn1; /* OTHERWISE BASE VALS ON SLOPE AHEAD */
- val1 = pn2;
- val = (2.0 * val0) - val1;
- dz->pitches[pitchno] = (float)pow((double)10,val);
- val = (3.0 * val0) - (2.0 * val1);
- dz->pitches[pitchno-1] = (float)pow((double)10,val);
- slopechange[pitchno] = 0.0;
- slopechange[pitchno+1] = 0.0; /* CORRECT SLOPECHANGES APPROPRIATELY */
- }
- return(FINISHED);
- }
- /********************** GET_MAX_AND_MIN_PITCHES **********************/
- int get_max_and_min_pitches(double *maxpitch,double *minpitch,dataptr dz)
- {
- int n;
- for(n=0;n<dz->wlength;n++) {
- if(dz->pitches[n] > MINPITCH) {
- if(dz->pitches[n] > *maxpitch)
- *maxpitch = dz->pitches[n];
- if(dz->pitches[n] < *minpitch)
- *minpitch = dz->pitches[n];
- }
- }
- return(FINISHED);
- }
- /***************************** WRITE_REMAINING_PITCH_OR_TRANSPOS_DATA ******************************/
- int write_remaining_pitch_or_transpos_data(int final_length_in_windows,dataptr dz)
- {
- int exit_status;
- if(final_length_in_windows > 0) {
- if(dz->is_transpos) {
- if((exit_status = write_samps(dz->transpos,final_length_in_windows,dz))<0)
- return(exit_status);
- }else {
- if((exit_status = write_samps(dz->pitches,final_length_in_windows,dz))<0)
- return(exit_status);
- }
- }
- return(FINISHED);
- }
- /***************************** GET_MIDIMEAN ******************************/
- int get_midimean(double *midimean,dataptr dz)
- {
- int exit_status;
- int n;
- double val;
- *midimean = 0.0;
- for(n=0;n<dz->wlength;n++) {
- if(dz->pitches[n]<MINPITCH)
- continue;
- if((exit_status = hztomidi(&val,dz->pitches[n]))<0)
- return(exit_status);
- *midimean += val;
- }
- *midimean /= (double)dz->wlength;
- return(FINISHED);
- }
- /***************************** SET_PVAL ******************************/
- int set_pval(double midivalue,int n,dataptr dz)
- {
- if(dz->is_transpos) {
- dz->transpos[n] = (float)(miditohz(midivalue)/dz->pitches[n]);
- check_transpos(&(dz->transpos[n]),dz);
- } else {
- dz->pitches[n] = (float)miditohz(midivalue);
- check_pitch(&(dz->pitches[n]),dz);
- }
- return(FINISHED);
- }
- /***************************************** DO_TAIL ************************/
- int do_tail(int n,double lastmidi,dataptr dz)
- {
- int exit_status;
- double thispich, thismidi, endmidi, mdiff, step;
- int diff, m, z;
- if(dz->vflag[PS_HOLD]) {
- thispich = dz->pitches[n];
- n++;
- while(n < dz->wlength) {
- if(dz->pitches[n]<MINPITCH) {
- n++;
- continue;
- }
- if(dz->is_transpos) {
- dz->transpos[n] = (float)(thispich/dz->pitches[n]);
- check_transpos(&(dz->transpos[n]),dz);
- } else {
- dz->pitches[n] = (float)thispich;
- check_pitch(&(dz->pitches[n]),dz);
- }
- n++;
- }
- } else {
- z = dz->wlength-1;
- while(dz->pitches[z]<MINPITCH) {
- if(--z==n)
- return(FINISHED);
- }
- if((exit_status = hztomidi(&endmidi,dz->pitches[z]))<0)
- return(exit_status);
- mdiff = endmidi - lastmidi;
- if((diff = z - n)<2)
- return(FINISHED);
- step = mdiff/(double)diff;
- n++;
- for(m=1;n <= z;n++,m++) {
- if(dz->pitches[n]<MINPITCH)
- continue;
- thismidi = lastmidi + (step * (double)m);
- if((exit_status = set_pval(thismidi,n,dz))<0)
- return(exit_status);
- }
- }
- return(FINISHED);
- }
- /************************** GET_PITCHAPPROX_AVERAGES ************************/
- int get_pitchapprox_averages(int *avcnt,dataptr dz)
- {
- int exit_status;
- int OK = 1, n = 0, m, cnt;
- double val;
- *avcnt = 0;
- if((dz->parray[PA_AVPICH] = (double *)malloc(dz->wlength * sizeof(double)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for averaging array.\n");
- return(MEMORY_ERROR);
- }
- while(OK) {
- dz->parray[PA_AVPICH][*avcnt] = 0.0;
- m = 0;
- cnt = 0;
- while(m < BLOKCNT) {
- if(dz->pitches[n]<MINPITCH) {
- m++;
- if(++n >= dz->wlength) {
- OK = 0;
- break;
- }
- continue;
- }
- if((exit_status = hztomidi(&val,dz->pitches[n]))<0)
- return(exit_status);
- dz->parray[PA_AVPICH][*avcnt] += val;
- cnt++;
- m++;
- if(++n >= dz->wlength) {
- OK = 0;
- break;
- }
- }
- if(cnt==0)
- dz->parray[PA_AVPICH][*avcnt] = -1.0f;
- else {
- dz->parray[PA_AVPICH][*avcnt] /= (double)cnt;
- dz->parray[PA_AVPICH][*avcnt] = miditohz(dz->parray[PA_AVPICH][*avcnt]);
- }
- (*avcnt)++;
- }
- return(FINISHED);
- }
- /********************************** APPROX_FUNC1 **********************************/
- int approx_func1(int *newlength_of_data,int *is_firsttime,
- double *lastmidi,int *lastpos,int n,dataptr dz)
- {
- int q, m, thispos, diff;
- int exit_status = CONTINUE;
- double ttime, thismidi, wiggle, this_prange, this_trange, mididiff, midistep;
- int here = min(dz->wlength-1,n * BLOKCNT); /* just being ultra careful !! */
- for(q=here;q<here+BLOKCNT;q++) {
- if(q>=dz->wlength)
- break;
- if(dz->pitches[q] > MINPITCH)
- break;
- }
- if(q>=here+BLOKCNT || q>=dz->wlength) /* No valid pitchdata here !! */
- return(CONTINUE);
- here = q;
- ttime = dz->frametime * (double)here;
- if((exit_status = hztomidi(&thismidi,dz->pitches[here]))<0)
- return(exit_status);
- if(dz->brksize[PA_PRANG]) { /* RWD need curly */
- if((exit_status = read_value_from_brktable(ttime,PA_PRANG,dz))<0)
- return(exit_status);
- }
- wiggle = (drand48() * 2.0) -1.0; /* random +- */
- this_prange = wiggle * dz->param[PA_PRANG];
- thismidi += this_prange;
- if(*is_firsttime) {
- if((exit_status = set_pval(thismidi,q,dz))<0)
- return(exit_status);
- *lastpos = q;
- *lastmidi = thismidi;
- *is_firsttime = FALSE;
- } else {
- wiggle = (drand48() * 2.0) -1.0;
- if(dz->brksize[PA_TRANG]) { /* RWD need curly */
- if((exit_status = read_value_from_brktable(ttime,PA_TRANG,dz))<0)
- return(exit_status);
- }
- this_trange = dz->param[PA_TRANG] * wiggle;
- ttime += this_trange;
- thispos = round(ttime/dz->frametime);
- thispos = max(0L,thispos);
- if((diff = thispos - *lastpos)>0) {
- if(thispos > (*newlength_of_data)-1) {
- if(dz->is_transpos) {
- thispos = (*newlength_of_data)-1;
- exit_status = FINISHED;
- } else {
- *newlength_of_data = thispos + 1;
- if((dz->pitches = (float *)realloc((char *)dz->pitches,
- (*newlength_of_data) * sizeof(float)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY to reallocate pitch array.\n");
- return(MEMORY_ERROR);
- }
- }
- }
- mididiff = thismidi - *lastmidi;
- midistep = mididiff/(double)diff;
- for(m=1,q= *lastpos + 1;m<=diff;m++,q++) {
- if(q < dz->wlength && dz->pitches[q]<MINPITCH)
- continue;
- thismidi = *lastmidi + (midistep * (double)m);
- if((exit_status = set_pval(thismidi,q,dz))<0)
- return(exit_status);
- }
- *lastmidi = thismidi;
- *lastpos = thispos;
- }
- }
- return(exit_status);
- }
- /********************************** APPROX_FUNC2 **********************************/
- int approx_func2(int *newlength_of_data,double lastmidi,int lastpos,int avcnt,dataptr dz)
- {
- int exit_status;
- int q, n, thispos, diff = 0;
- double thismidi,ttime, wiggle, this_prange, this_trange;
- double mididiff, midistep;
- q = avcnt-1;
- while(dz->parray[PA_AVPICH][q]<0.0) {
- if(--q<=lastpos)
- return(FINISHED);
- }
- if((exit_status = hztomidi(&thismidi,dz->parray[PA_AVPICH][q]))<0)
- return(exit_status);
- ttime = (q * BLOKCNT) * dz->frametime;
- if(dz->brksize[PA_PRANG]) { //RWD need curly
- if((exit_status = read_value_from_brktable(ttime,PA_PRANG,dz))<0)
- return(exit_status);
- }
- wiggle = (drand48() * 2.0) -1.0; /* random +- */
- this_prange = wiggle * dz->param[PA_PRANG];
- thismidi += this_prange;
- if(dz->is_transpos)
- thispos = dz->wlength-1;
- else {
- wiggle = (drand48() * 2.0) -1.0; /* random +- */
- if(dz->brksize[PA_TRANG]) { /* RWD need curly */
- if((exit_status = read_value_from_brktable(ttime,PA_TRANG,dz))<0)
- return(exit_status);
- }
- this_trange = dz->param[PA_TRANG] * wiggle;
- ttime += this_trange;
- thispos = round(ttime/dz->frametime);
- thispos = max(0L,thispos);
- if((diff = thispos - lastpos)>0 && thispos > *newlength_of_data-1) {
- *newlength_of_data = thispos + 1;
- if((dz->pitches =
- (float *)realloc((char *)dz->pitches,*newlength_of_data * sizeof(float)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY to reallocate pitch array.\n");
- return(MEMORY_ERROR);
- }
- }
- }
- if(diff>0) {
- mididiff = thismidi - lastmidi;
- midistep = mididiff/(double)diff;
- for(n=1,q=lastpos+1;n<=diff;n++,q++) {
- if(q < dz->wlength && dz->pitches[q]<MINPITCH)
- continue;
- thismidi = lastmidi + (midistep * (double)n);
- if((exit_status = set_pval(thismidi,q,dz))<0)
- return(exit_status);
- }
- } else
- *newlength_of_data = lastpos + 1;
- return(FINISHED);
- }
- /************************** GET_RAND_INTERVAL ************************/
- int get_rand_interval(double *thisintv,dataptr dz)
- {
- double wiggle = ((drand48() * 2.0) - 1.0);
- if(dz->vflag[PR_IS_SLEW]) {
- if(wiggle < dz->param[PR_SLEW]
- || (dz->iparam[PR_NEGATIV_SLEW]==TRUE
- && (wiggle > dz->param[PR_SLEW])))
- wiggle = -wiggle;
- }
- *thisintv = dz->param[PR_MXINT] * wiggle;
- return(FINISHED);
- }
-
- /************************** INTERVAL_MAPPING ************************
- *
- * Approximate input interval to nearest value in LHS column of input map.
- * Find variance from that value.
- * Return corresponding value in RHS column of map, with the variance correction added.
- */
- int interval_mapping(double *thisint,double thismidi,dataptr dz)
- {
- double *p = dz->parray[PI_INTMAP];
- double *pend = dz->parray[PI_INTMAP] + (dz->itemcnt * 2);
- double variance, v1, v2;
- if(thismidi <= *p) { /* intvl is below all entries in mapping table */
- variance = thismidi - *p;
- *thisint = *(p+1) - variance; /* return map of bottom val (-variance) */
- return(FINISHED);
- }
- while(thismidi > *p) {
- p += 2;
- if(p >= pend) { /* intvl is above all entries in mapping table */
- p -= 2;
- variance = thismidi - *p;
- *thisint = *(p+1) - variance;/* return map of top val (-variance) */
- return(FINISHED);
- }
- }
- v1 = *p - thismidi; /* intvl is between 2 entries in mapping table */
- v2 = thismidi - *(p-2);
- if(v1 > v2) { /* Compare variances, to find which intvl closer */
- variance = v2;
- *thisint = *(p-1) - variance;
- } else {
- variance = v1;
- *thisint = *(p+1) + variance; /* return appropriate mapped pitch (+/-variance) */
- }
- return(FINISHED);
- }
- /************************************** PEAK_INTERP ****************/
- int peak_interp
- (int pitchno,int last_validpitch_no,int *lastmaxpos,double meanpich,
- double minint,double maxint,double *lastmidi,dataptr dz)
- {
- int exit_status;
- double thispitch, thismidi, variance, mdiff,step;
- int m, k, maxpos = 0, minpos = 0, diff;
- double maxvar = 0.0, minvar = 0.0;
- k = pitchno - last_validpitch_no;
- for(m=0;m<k;m++) {
- if((thispitch = dz->pitches[k+m])<MINPITCH)
- continue;
- if(thispitch >= meanpich) {
- if((variance = thispitch/meanpich)>maxvar) {
- maxvar = variance;
- maxpos = k+m;
- }
- } else {
- if((variance = meanpich/thispitch)>minvar) {
- minvar = variance;
- minpos = k+m;
- }
- }
- //TW avoid log(0)
- if(minvar > 0.0)
- minvar = LOG2(minvar) * 12.0;
- //TW avoid log(0)
- if(maxvar > 0.0)
- maxvar = LOG2(maxvar) * 12.0;
- minvar /= minint;
- maxvar /= maxint; /* NORMALISE */
- if(maxvar < minvar)
- maxpos = minpos;
- }
- diff = maxpos - *lastmaxpos;
- if((exit_status = hztomidi(&thismidi,dz->pitches[maxpos]))<0)
- return(exit_status);
- mdiff = thismidi - *lastmidi;
- step = mdiff/(double)diff;
- for(m=1;m<=diff;m++) {
- thismidi = *lastmidi + (step * (double)m);
- if(dz->pitches[(*lastmaxpos)+m]<MINPITCH)
- continue;
- if((exit_status = set_pval(thismidi,(*lastmaxpos)+m,dz))<0)
- return(exit_status);
- }
- *lastmidi = thismidi;
- *lastmaxpos = maxpos;
- return(FINISHED);
- }
- /*************************** DO_PITCH_FILTER *************************/
- int do_pitch_filter(dataptr dz)
- {
- int n;
- switch(dz->iparam[PF_ISFILTER]) {
- case(IS_HIPASS):
- for(n=0;n<dz->wlength;n++) {
- if(dz->pitches[n] < dz->param[PF_LOF])
- dz->pitches[n] = (float)NOT_PITCH;
- }
- break;
- case(IS_LOPASS):
- for(n=0;n<dz->wlength;n++) {
- if(dz->pitches[n] > dz->param[PF_HIF])
- dz->pitches[n] = (float)NOT_PITCH;
- }
- break;
- case(IS_BANDPASS):
- for(n=0;n<dz->wlength;n++) {
- if(dz->pitches[n] < dz->param[PF_LOF] || dz->pitches[n] > dz->param[PF_HIF])
- dz->pitches[n] = (float)NOT_PITCH;
- }
- break;
- }
- return(FINISHED);
- }
- /***************************** TIDY_UP_PITCH_DATA ***********************/
- int tidy_up_pitch_data(dataptr dz)
- {
- int exit_status;
- if((exit_status = anti_noise_smoothing(dz->wlength,dz->pitches,dz->frametime))<0)
- return(exit_status);
- if((exit_status = mark_zeros_in_pitchdata(dz))<0)
- return(exit_status);
- if((exit_status = eliminate_blips_in_pitch_data(dz))<0)
- return(exit_status);
- if(dz->vflag[KEEP_PITCH_ZEROS]==FALSE)
- return interpolate_pitch(dz->pitches,1,dz);
- return pitch_found(dz);
- }
- /************************* GENERATE_TONE *************************/
- int generate_tone(dataptr dz)
- {
- #define VOLUME_PAD (0.3)
- #define NOISEBASE (0.2)
- int exit_status;
- int m, done, cc, vc, partials_in_test_tone;
- float thisamp;
- double thisfrq, basefrq;
- int n = 0, last_partial;
- double noisrange = 1.0 - NOISEBASE;
- double level, totamp = 0.0;
- dz->flbufptr[0] = dz->bigfbuf;
- thisamp = (float)(VOLUME_PAD/(double)dz->clength);
- if(dz->process==P_SYNTH) {
- dz->wanted = dz->clength * 2;
- partials_in_test_tone = dz->itemcnt;
- } else
- partials_in_test_tone = PARTIALS_IN_TEST_TONE;
- while(n < dz->wlength) {
- done = FALSE;
- thisfrq = dz->pitches[n];
- if(thisfrq < 0.0){ /* NO PITCH FOUND : GENERATE NOISE */
- if(thisfrq > NOT_SOUND) {
- if(dz->process!=P_SYNTH)
- thisamp = (float)((dz->parray[PICH_PRETOTAMP][n]/(double)dz->clength) * VOLUME_PAD);
- basefrq = 0.0;
- dz->flbufptr[0][1] = (float)(drand48() * dz->halfchwidth);
- basefrq += dz->halfchwidth;
- for(cc = 1, vc = 2; cc < dz->clength - 1; cc++, vc += 2) {
- dz->flbufptr[0][FREQ] = (float)((drand48() * dz->chwidth) + basefrq);
- dz->flbufptr[0][AMPP] = (float)(thisamp * ((drand48() * noisrange) + NOISEBASE));
- basefrq += dz->chwidth;
- }
- dz->flbufptr[0][FREQ] = (float)(dz->nyquist - (drand48() * dz->halfchwidth));
- dz->flbufptr[0][AMPP] = (float)(thisamp * ((drand48() * noisrange) + NOISEBASE));
- done = TRUE;
- } else {
- basefrq = 0.0;
- for(cc = 0, vc = 0; cc < dz->clength-1; cc++, vc += 2) {
- dz->flbufptr[0][FREQ] = (float)basefrq;
- dz->flbufptr[0][AMPP] = 0.0f;
- basefrq += dz->chwidth;
- }
- dz->flbufptr[0][FREQ] = (float)dz->nyquist;
- dz->flbufptr[0][AMPP] = 0.0f;
- done = TRUE;
- }
- } else { /* GENERATE TESTTONE AT FOUND PITCH */
- if(dz->process==P_SYNTH) {
- for(cc = 0, vc = 0; cc < dz->clength; cc++, vc += 2)
- dz->flbufptr[0][AMPP] = 0.0f;
- basefrq = thisfrq;
- totamp = 0.0;
- for(m=0;m<partials_in_test_tone;m++) {
- cc = (int)((thisfrq + dz->halfchwidth)/dz->chwidth);
- vc = cc * 2;
- if((level = dz->parray[PICH_SPEC][m]) > 0.0) {
- dz->flbufptr[0][AMPP] = (float)level;
- dz->flbufptr[0][FREQ] = (float)thisfrq;
- totamp += dz->flbufptr[0][AMPP];
- }
- if((thisfrq += basefrq) > dz->nyquist) {
- if((exit_status = normalise(VOLUME_PAD,totamp,dz))<0)
- return(exit_status);
- done = TRUE;
- break;
- }
- }
- } else {
- for(cc = 0, vc = 0; cc < dz->clength; cc++, vc += 2)
- dz->flbufptr[0][AMPP] = 0.0f;
- for(m=0;m<partials_in_test_tone;m++) {
- cc = (int)((thisfrq + dz->halfchwidth)/dz->chwidth); /* TRUNCATE */
- vc = cc * 2;
- dz->flbufptr[0][AMPP] = dz->windowbuf[TESTPAMP][m];
- dz->flbufptr[0][FREQ] = (float)thisfrq;
- if((thisfrq = thisfrq * 2.0) > dz->nyquist) {
- if((exit_status = normalise(dz->parray[PICH_PRETOTAMP][n] * VOLUME_PAD,
- dz->windowbuf[TOTPAMP][m],dz))<0)
- return(exit_status);
- done = TRUE;
- break;
- }
- }
- }
- }
- if(!done) {
- last_partial = partials_in_test_tone-1;
- if(dz->process==P_SYNTH) {
- if((level = dz->parray[PICH_SPEC][last_partial]) > 0.0) {
- if((exit_status = normalise(VOLUME_PAD,totamp,dz))<0)
- return(exit_status);
- }
- } else {
- if((exit_status = normalise(dz->parray[PICH_PRETOTAMP][n],
- dz->windowbuf[TOTPAMP][last_partial],dz))<0)
- return(exit_status);
- }
- }
- if((dz->flbufptr[0] += dz->wanted) >= dz->flbufptr[1]) {
- if((exit_status = write_samps(dz->bigfbuf,dz->big_fsize,dz))<0)
- return(exit_status);
- dz->flbufptr[0] = dz->bigfbuf;
- }
- n++;
- }
- if(dz->flbufptr[0] != dz->bigfbuf) {
- if((exit_status = write_samps(dz->bigfbuf,dz->flbufptr[0] - dz->bigfbuf,dz))<0)
- return(exit_status);
- }
- return(FINISHED);
- }
- /********************** ANTI_NOISE_SMOOTHING *********************/
- /*RWD used in conditional test, so better as a real var:*/
- static const int MIN_SMOOTH_SET = 3;
- /*#define MIN_SMOOTH_SET (3)*/ /* minimum number of adjacent smooth pitches to imply true pitch present */
- #define MAX_GLISRATE (16.0) /* Assumptions: pitch can't move faster than 16 octaves per sec: MAX_GLISRATE */
- /* Possible movement from window-to-window = MAX_GLISRATE * dz->frametime */
- int anti_noise_smoothing(int wlength,float *pitches,float frametime)
- {
- char *smooth;
- double max_pglide;
- int n;
- if(MIN_SMOOTH_SET<3) {
- sprintf(errstr,"Bad constant: MIN_SMOOTH_SET: anti_noise_smoothing()\n");
- return(PROGRAM_ERROR);
- }
- if(wlength < MIN_SMOOTH_SET + 1)
- return(FINISHED);
- max_pglide = pow(2.0,MAX_GLISRATE * frametime);
- if((smooth = (char *)malloc((size_t)wlength))==NULL) {
- sprintf(errstr,"aINSUFFICIENT MEMORY for smoothing array.\n");
- return(MEMORY_ERROR);
- }
- for(n=1;n<wlength-1;n++)
- smooth[n] = (char)is_smooth_from_both_sides(n,max_pglide,pitches);
- smooth[0] = (char)is_initialpitch_smooth(smooth,max_pglide,pitches);
- smooth[wlength-1] = (char)is_finalpitch_smooth(smooth,max_pglide,wlength,pitches);
- for(n=MIN_SMOOTH_SET-1;n<wlength;n++) {
- if(!smooth[n])
- smooth[n] = (char)is_smooth_from_before(n,smooth,max_pglide,pitches);
- }
- for(n=0;n<=wlength-MIN_SMOOTH_SET;n++) {
- if(!smooth[n])
- smooth[n] = (char)is_smooth_from_after(n,smooth,max_pglide,pitches);
- }
- test_glitch_sets(smooth,max_pglide,wlength,pitches);
- remove_unsmooth_pitches(smooth,wlength,pitches);
- free(smooth);
- return(FINISHED);
- }
- /********************** IS_SMOOTH_FROM_BOTH_SIDES *********************
- *
- * verify a pitch if it has continuity with the pitches on either side.
- */
- int is_smooth_from_both_sides(int n,double max_pglide,float *pitches)
- {
- float thispitch, pitch_before, pitch_after;
- double pre_interval, post_interval;
- if((thispitch = pitches[n]) < FLTERR)
- return FALSE;
- if((pitch_before = pitches[n-1]) < FLTERR)
- return FALSE;
- if((pitch_after = pitches[n+1]) < FLTERR)
- return FALSE;
- pre_interval = pitch_before/thispitch;
- if(pre_interval < 1.0)
- pre_interval = 1.0/pre_interval;
- post_interval = pitch_after/thispitch;
- if(post_interval < 1.0)
- post_interval = 1.0/post_interval;
- if(pre_interval > max_pglide
- || post_interval > max_pglide)
- return FALSE;
- return TRUE;
- }
- /********************** IS_INITIALPITCH_SMOOTH *********************
- *
- * verify first pitch if it has continuity with an ensuing verified pitch.
- */
- int is_initialpitch_smooth(char *smooth,double max_pglide,float *pitches)
- {
- float thispitch;
- int n;
- double post_interval;
- if((thispitch = pitches[0]) < FLTERR)
- return FALSE;
- for(n=1;n < MIN_SMOOTH_SET;n++) {
- if(smooth[n]) {
- post_interval = pitches[n]/pitches[0];
- if(post_interval < 1.0)
- post_interval = 1.0/post_interval;
- if(post_interval <= pow(max_pglide,(double)n))
- return TRUE;
- }
- }
- return(FALSE);
- }
-
- /********************** IS_FINALPITCH_SMOOTH *********************
- *
- * verify final pitch if it has continuity with a preceding verified pitch.
- */
- int is_finalpitch_smooth(char *smooth,double max_pglide,int wlength,float *pitches)
- {
- float thispitch;
- double pre_interval;
- int n;
- int last = wlength - 1;
- if((thispitch = pitches[last]) < FLTERR)
- return FALSE;
- for(n=1;n < MIN_SMOOTH_SET;n++) {
- if(smooth[last-n]) {
- pre_interval = pitches[last-n]/pitches[last];
- if(pre_interval < 1.0)
- pre_interval = 1.0/pre_interval;
- if(pre_interval <= pow(max_pglide,(double)n))
- return TRUE;
- }
- }
- return(FALSE);
- }
-
- /********************** IS_SMOOTH_FROM_BEFORE *********************
- *
- * verify a pitch which has continuity with a preceding set of verified pitches.
- */
- int is_smooth_from_before(int n,char *smooth,double max_pglide,float *pitches)
- {
- float thispitch, pitch_before;
- double pre_interval;
- int m;
- if((thispitch = pitches[n]) < FLTERR)
- return FALSE;
- for(m=1;m<MIN_SMOOTH_SET;m++) { /* If there are (MIN_SMOOTH_SET-1) smooth pitches before */
- if(!smooth[n-m])
- return(FALSE);
- }
- pitch_before = pitches[n-1]; /* Test the interval with the previous pitch */
- pre_interval = pitch_before/thispitch;
- if(pre_interval < 1.0)
- pre_interval = 1.0/pre_interval;
- if(pre_interval > max_pglide)
- return FALSE; /* And if it's acceptably smooth */
- return TRUE; /* mark this pitch as smooth also */
- }
- /********************** IS_SMOOTH_FROM_AFTER *********************
- *
- * verify a pitch which has continuity with a following set of verified pitches.
- */
- int is_smooth_from_after(int n,char *smooth,double max_pglide,float *pitches)
- {
- float thispitch, pitch_after;
- double post_interval;
- int m;
- if((thispitch = pitches[n]) < FLTERR)
- return FALSE;
- for(m=1;m<MIN_SMOOTH_SET;m++) { /* If there are (MIN_SMOOTH_SET-1) smooth pitches after */
- if(!smooth[n+m])
- return(FALSE);
- }
- pitch_after = pitches[n+1]; /* Test the interval with the next pitch */
- post_interval = pitch_after/thispitch;
- if(post_interval < 1.0)
- post_interval = 1.0/post_interval;
- if(post_interval > max_pglide)
- return FALSE; /* And if it's acceptably smooth */
- return TRUE; /* mark this pitch as smooth also */
- }
- /********************** TEST_GLITCH_SETS *********************
- *
- * This function looks for any sets of values that appear to be glitches
- * amongst the real pitch data.
- * It is possible some items are REAL pitch data isolated BETWEEN short glitches.
- * This function checks for these cases.
- */
- int test_glitch_sets(char *smooth,double max_pglide,int wlength,float *pitches)
- {
- int exit_status;
- int gotglitch = FALSE;
- int n, gltchend, gltchstart = 0;
- for(n=0;n<wlength;n++) {
- if(gotglitch) { /* if inside a glitch */
- if(smooth[n]) { /* if reached its end, mark the end, then process the glitch */
- gltchend = n;
- if((exit_status = test_glitch_forwards(gltchstart,gltchend,smooth,max_pglide,pitches))<0)
- return(exit_status);
- if((exit_status = test_glitch_backwards(gltchstart,gltchend,smooth,max_pglide,wlength,pitches))<0)
- return(exit_status);
- gotglitch = 0;
- }
- } else { /* look for a glitch and mark its start */
- if(!smooth[n]) {
- gotglitch = 1;
- gltchstart = n;
- }
- }
- }
- if(gotglitch) { /* if inside a glitch at end of data, process glitch */
- gltchend = n;
- test_glitch_forwards(gltchstart,gltchend,smooth,max_pglide,pitches);
- }
- return(FINISHED);
- }
- /********************* REMOVE_UNSMOOTH_PITCHES ***********************
- *
- * delete all pitches which have no verified continuity with surrounding pitches.
- */
- void remove_unsmooth_pitches(char *smooth,int wlength,float *pitches)
- {
- int n;
- for(n=0;n<wlength;n++) {
- if(!smooth[n])
- pitches[n] = (float)NOT_PITCH;
- }
- }
- /********************** TEST_GLITCH_FORWARDS *********************
- *
- * searching from start of glitch, look for isolated true pitches
- * amongst glitch data.
- */
- #define LAST_SMOOTH_NOT_SET (-1)
- int test_glitch_forwards(int gltchstart,int gltchend,char *smooth,double max_pglide,float *pitches)
- {
- int n, glcnt;
- int last_smooth, previous;
- double pre_interval;
- if((previous = gltchstart - 1) < 0)
- return FINISHED;
- if(pitches[previous] < FLTERR) {
- sprintf(errstr,"Error in previous smoothing logic: test_glitch_forwards()\n");
- return(PROGRAM_ERROR);
- }
- last_smooth = previous;
- n = gltchstart+1; /* setup params for local search of glitch */
- glcnt = 1;
- while(n < gltchend) { /* look through the glitch */
- if(pitches[n] > FLTERR) { /* if glitch location holds a true pitch */
- pre_interval = pitches[n]/pitches[previous];
- if(pre_interval < 1.0)
- pre_interval = 1.0/pre_interval; /* compare against previous verified pitch */
- if(pre_interval <= pow(max_pglide,(double)(n-previous))) {
- smooth[n] = TRUE; /* if comparable: mark this pitch as verified */
- last_smooth = n;
- }
- }
- n++; /* Once more than a max-glitch-set has been scanned */
- /* or the end of the entire glitch is reached */
- if(++glcnt >= MIN_SMOOTH_SET || n >= gltchend) {
- if(last_smooth == previous)
- break; /* If no new verifiable pitch found, give up */
- previous = last_smooth;
- n = last_smooth + 1; /* Otherwise start a new local search from newly verified pitch */
- glcnt = 1;
- }
- }
- return(FINISHED);
- }
- /********************** TEST_GLITCH_BACKWARDS *********************
- *
- * searching from end of glitch, look for isolated true pitches
- * amongst glitch data.
- */
- int test_glitch_backwards(int gltchstart,int gltchend,char *smooth,double max_pglide,int wlength,float *pitches)
- {
- int n, glcnt, next, next_smooth;
- double post_interval;
- if((next = gltchend) >= wlength)
- return FINISHED;
- if(pitches[next] < FLTERR) {
- sprintf(errstr,"Error in previous smoothing logic: test_glitch_backwards()\n");
- return(PROGRAM_ERROR);
- }
- next_smooth = next;
- n = gltchend-2; /* setup params for local search of glitch */
- glcnt = 1;
- while(n >= gltchstart) { /* look through the glitch */
- if(pitches[n] > FLTERR) { /* if glitch location holds a true pitch */
- post_interval = pitches[n]/pitches[next];
- if(post_interval < 1.0)
- post_interval = 1.0/post_interval; /* compare against previous verified pitch */
- if(post_interval <= pow(max_pglide,(double)(next - n))) {
- smooth[n] = TRUE; /* if comparable: mark this pitch as verified */
- next_smooth = n;
- }
- }
- n--; /* Once more than a max-glitch-set has been scanned */
- /* or the start of the entire glitch is reached */
- if(++glcnt >= MIN_SMOOTH_SET || n < gltchstart) {
- if(next_smooth == next)
- break; /* If no new verifiable pitch found, give up */
- next = next_smooth;
- n = next_smooth - 1;
- glcnt = 1; /* Otherwise start a new local search */
- }
- }
- return(FINISHED);
- }
- /*********** WRITE_PITCH_OUTHEADER_FROM_ANALYSIS_INHEADER_TO_SECOND_OUTFILE **************
- *
- * Works for specpitch and spectrack: which write to 2nd datafile!!!
- */
- int write_pitch_outheader_from_analysis_inheader_to_second_outfile(int ofd,dataptr dz)
- {
- int exit_status;
- int orig_process = dz->process_type;
- int orig_outfiletype = dz->outfiletype;
- int orig_chans = dz->infile->channels;
- int orig_origchans = dz->infile->origchans;
- dz->process_type = ANAL_TO_PITCH;
- dz->outfiletype = PITCH_OUT;
- dz->outfile->origchans = dz->infile->channels;
- dz->outfile->channels = 1;
- if((exit_status = headwrite(ofd,dz))<0)
- return(exit_status);
- /* restore orig values */
- dz->process_type = orig_process;
- dz->outfiletype = orig_outfiletype;
- dz->outfile->origchans = orig_origchans;
- dz->outfile->channels = orig_chans;
- return(FINISHED);
- }
- /***************************** LOCAL_PEAK **************************/
- int local_peak(int thiscc,double frq, float *thisbuf, dataptr dz)
- {
- int thisvc = thiscc * 2;
- int cc, vc, searchtop, searchbot;
- double frqtop = frq * SEMITONE_INTERVAL;
- double frqbot = frq / SEMITONE_INTERVAL;
- searchtop = (int)((frqtop + dz->halfchwidth)/dz->chwidth); /* TRUNCATE */
- searchtop = min(dz->clength,searchtop + PEAKSCAN + 1);
- searchbot = (int)((frqbot + dz->halfchwidth)/dz->chwidth); /* TRUNCATE */
- searchbot = max(0,searchbot - PEAKSCAN);
- for(cc = searchbot ,vc = searchbot*2; cc < searchtop; cc++, vc += 2) {
- if(thisbuf[thisvc] < thisbuf[vc])
- return(FALSE);
- }
- return(TRUE);
- }
- /**************************** INTERPOLATE_PITCH ***************************/
- int interpolate_pitch(float *floatbuf,int skip_silence,dataptr dz)
- {
- int exit_status;
- int pitchno;
- for(pitchno=0;pitchno<dz->wlength;pitchno++) {
- if(floatbuf[pitchno] < MINPITCH) {
- if(skip_silence && flteq((double)floatbuf[pitchno],NOT_SOUND))
- continue;
- if((exit_status = do_interpolating(&pitchno,floatbuf,skip_silence,dz))<0)
- return(exit_status);
- }
- }
- return(FINISHED);
- }
- /****************************** DO_INTERPOLATING ************************
- *
- * WITHOUT THOROUGH CHECK, worried about logs getting <= 0.0.
- */
- int do_interpolating(int *pitchno,float *floatbuf,int skip_silence,dataptr dz)
- {
- #define MID_PITCH (0)
- #define FIRST_PITCH (1)
- #define END_PITCH (2)
- #define NO_PITCH (3)
- int act_type = MID_PITCH;
- int start = *pitchno, m;
- double startpitch, endpitch, thispitch, lastpitch, pstep;
- if(*pitchno==0L)
- act_type = FIRST_PITCH;
- while(floatbuf[*pitchno] < MINPITCH) {
- if(++(*pitchno)>=dz->wlength) {
- if(act_type == FIRST_PITCH)
- act_type = NO_PITCH;
- else
- act_type = END_PITCH;
- break;
- }
- }
- if(act_type==MID_PITCH) {
- m = start-1;
- while(floatbuf[m] < MINPITCH) {
- if(--m <= 0) {
- act_type = FIRST_PITCH;
- break;
- }
- }
- start = m;
- }
- switch(act_type) {
- case(MID_PITCH):
- startpitch = hz_to_pitchheight((double)floatbuf[start-1]);
- endpitch = hz_to_pitchheight((double)floatbuf[*pitchno]);
- pstep = (endpitch - startpitch)/(double)((*pitchno) - (start - 1));
- lastpitch = startpitch;
- for(m=start;m<*pitchno;m++) { /* INTERP PITCH ACROSS UNPITCHED SEG */
- thispitch = lastpitch + pstep;
- if(!(skip_silence && flteq(floatbuf[m],NOT_SOUND)))
- floatbuf[m] = (float)pitchheight_to_hz(thispitch);
- lastpitch = thispitch;
- }
- break;
- case(FIRST_PITCH):
- for(m=0;m<*pitchno;m++) { /* EXTEND FIRST CLEAR PITCH BACK TO START */
- if(!(skip_silence && flteq(floatbuf[m],NOT_SOUND)))
- floatbuf[m] = floatbuf[*pitchno];
- }
- break;
- case(END_PITCH): /* EXTEND LAST CLEAR PITCH ON TO END */
- for(m=start;m<*pitchno;m++) {
- if(!(skip_silence && flteq(floatbuf[m],NOT_SOUND)))
- floatbuf[m] = floatbuf[start-1];
- }
- break;
- case(NO_PITCH):
- sprintf(errstr,"No valid pitch found.\n");
- return(GOAL_FAILED);
- }
- (*pitchno)--;
- return(FINISHED);
- }
- /***************************** HZ_TO_PITCHHEIGHT *******************************
- *
- * Real pitch is 12 * log2(frq/basis_frq).
- *
- * BUT (with a little help from the Feynman lectures!!)
- * (1) The basis_frq is arbitrary, and cancels out, so let it be 1.0.
- i.e. pitch1 = 12 * log2(frq1/basis_frq) = 12 * (log2(frq1) - log2(basis_frq));
- pitch2 = 12 * log2(frq2/basis_frq) = 12 * (log2(frq2) - log2(basis_frq));
- pitch1 - pitch2 = 12 * (log2(frq1) - log2(frq2)) = 12 * log2(frq1/frq2);
- * (2) Finding the difference of 2 log2() numbers, interpolating and
- * reconverting to pow(2.0,...) is no different to doing same
- * calculation to base e.
- * (3) The (12 *) is also a cancellable factor in all this.
- * So pitch_height serves the same function as pitch in these calculations!!
- */
- double hz_to_pitchheight(double frqq)
- {
- return log(frqq);
- }
- /***************************** PITCHHEIGHT_TO_HZ *******************************/
- double pitchheight_to_hz(double pitch_height)
- {
- return exp(pitch_height);
- }
- /************************** ELIMINATE_BLIPS_IN_PITCH_DATA ****************************
- *
- * (1) Eliminate any group of 'dz->param[PICH_VALID]' pitched windows, bracketed by
- * unpitched windows, as unreliable data.
- */
- int eliminate_blips_in_pitch_data(dataptr dz)
- {
- int q;
- int n, m, k, wlength_less_bliplen;
- int OK = 1;
- switch(dz->process) {
- case(PITCH): q = PICH_VALID; break;
- case(TRACK): q = TRAK_VALID; break;
- default:
- sprintf(errstr,"unknown case in eliminate_blips_in_pitch_data()\n");
- return(PROGRAM_ERROR);
- }
- if(dz->iparam[q]<=0)
- return(FINISHED);
- wlength_less_bliplen = dz->wlength - dz->iparam[q];
- for(n=1;n<wlength_less_bliplen;n++) {
- if(dz->pitches[n] > 0.0) {
- if(dz->pitches[n-1] < 0.0) {
- for(k = 1; k <= dz->iparam[q]; k++) {
- if(dz->pitches[n+k] < 0.0) {
- for(m=0;m<k;m++)
- dz->pitches[n+m] = (float)NOT_PITCH;
- n += k;
- continue;
- }
- }
- }
- }
- }
- n = wlength_less_bliplen;
- if((dz->pitches[n] > 0.0) && (dz->pitches[n-1] < 0.0)) {
- /* UNREACHABLE at level4 ??? */
- for(k = 1; k < dz->iparam[q]; k++) {
- if(dz->pitches[n+k] < 0.0)
- OK = 0;
- break;
- }
- }
- if(!OK) {
- for(n=wlength_less_bliplen;n<dz->wlength;n++)
- dz->pitches[n] = (float)NOT_PITCH;
- }
- return(FINISHED);
- }
- /********************************** MARK_ZEROS_IN_PITCHDATA ************************
- *
- * Disregard data on windows which are SILENCE_RATIO below maximum level.
- */
- int mark_zeros_in_pitchdata(dataptr dz)
- {
- int k;
- int n;
- double maxlevel = 0.0, minlevel;
- switch(dz->process) {
- case(PITCH): k = PICH_SRATIO; break;
- case(TRACK): k = TRAK_SRATIO; break;
- default:
- sprintf(errstr,"unknown case in mark_zeros_in_pitchdata()\n");
- return(PROGRAM_ERROR);
- }
- for(n=0;n<dz->wlength;n++) {
- if(dz->parray[PICH_PRETOTAMP][n] > maxlevel)
- maxlevel = dz->parray[PICH_PRETOTAMP][n];
- }
- minlevel = maxlevel * dz->param[k];
- for(n=0;n<dz->wlength;n++) {
- if(dz->parray[PICH_PRETOTAMP][n] < minlevel)
- dz->pitches[n] = (float)NOT_SOUND;
- }
- return(FINISHED);
- }
- /**************************** PITCH_FOUND ****************************/
- int pitch_found(dataptr dz)
- {
- int n;
- for(n=0;n<dz->wlength;n++) {
- if(dz->pitches[n] > NOT_PITCH)
- return(FINISHED);
- }
- sprintf(errstr,"No valid pitch found.\n");
- return(GOAL_FAILED);
- }
-
- /**************************** CHECK_TRANSPOS ****************************/
- void check_transpos(float *t,dataptr dz)
- {
- if(*t <= MIN_TRANSPOS) {
- if(!dz->fzeroset) {
- fprintf(stdout,"WARNING: Transposition(s) by > max permitted: adjusted.\n");
- fflush(stdout);
- dz->fzeroset = TRUE;
- }
- *t = (float)(MIN_TRANSPOS + FLTERR);
- }
- if(*t >= MAX_TRANSPOS) {
- if(!dz->fzeroset) {
- fprintf(stdout,"WARNING: Transposition(s) by > max permitted: adjusted.\n");
- fflush(stdout);
- dz->fzeroset = TRUE;
- }
- *t = (float)(MAX_TRANSPOS - 1.0);
- }
- }
- /**************************** CHECK_PITCH ****************************/
- void check_pitch(float *t,dataptr dz)
- {
- if(*t <= SPEC_MINFRQ) {
- if(!dz->fzeroset) {
- fprintf(stdout,"WARNING: Pitch(es) out of permitted range: adjusted.\n");
- fflush(stdout);
- dz->fzeroset = TRUE;
- }
- *t = (float)(SPEC_MINFRQ + FLTERR);
- }
- if(*t >= DEFAULT_NYQUIST) {
- if(!dz->fzeroset) {
- fprintf(stdout,"WARNING: Pitch(es) out of permitted range: adjusted.\n");
- fflush(stdout);
- dz->fzeroset = TRUE;
- }
- *t = (float)(DEFAULT_NYQUIST-1.0);
- }
- }
- /***************************** WRITE_PITCH_OR_TRANSPOS_DATA ******************************/
- int write_pitch_or_transpos_data(int final_length_in_windows,dataptr dz)
- {
- int exit_status;
- if(final_length_in_windows > 0) {
- if(dz->is_transpos) {
- if((exit_status = write_exact_samps(dz->transpos,final_length_in_windows,dz))<0)
- return(exit_status);
- } else {
- if((exit_status = write_exact_samps(dz->pitches,final_length_in_windows,dz))<0)
- return(exit_status);
- }
- }
- return(FINISHED);
- }
- /***************************** TRAP_JUNK ******************************/
- int trap_junk(int final_length_in_windows,dataptr dz)
- {
- int n;
- int caught_zero = 0, caught_skrch = 0;
- double mintrans, maxtrans;
- if((dz->process==P_EXAG && ODD(dz->mode)) || dz->mode==TRANSP_OUT) {
- /* Transposition file output */
- maxtrans = dz->nyquist/MINPITCH;
- mintrans = 1.0/maxtrans;
- for(n=0;n<final_length_in_windows;n++) {
- //if(!caught_zero && (dz->pitches[n] < mintrans && !flteq((double)dz->pitches[n],NOT_PITCH)))
- // caught_zero = 1;
- /*RWD 6:2001 */
- if(!caught_zero && (dz->transpos[n] < mintrans && !
- (flteq((double)dz->transpos[n],NOT_PITCH) || flteq((double)dz->transpos[n],NOT_SOUND))))
- caught_zero = 1;
- if(!caught_skrch && (dz->transpos[n] > maxtrans))
- caught_skrch = 1;
- if(caught_zero && caught_skrch)
- break;
- }
- if(caught_zero || caught_skrch) {
- if(caught_zero)
- sprintf(errstr,"You have generated transposition data < the minimum possible.\n");
- if(caught_skrch)
- sprintf(errstr,"You have generated transposition data > the maximum possible.\n");
- return(GOAL_FAILED);
- }
- } else { /* Pitch file output */
- for(n=0;n<final_length_in_windows;n++) {
- //if(!caught_zero && (dz->pitches[n] < MINPITCH && !flteq((double)dz->pitches[n],NOT_PITCH)))
- // caught_zero = 1;
- /* RWD 6:2001 trap zero windows too? */
- if(!caught_zero && (dz->pitches[n] < MINPITCH && !
- (flteq((double)dz->pitches[n],NOT_PITCH) || flteq((double)dz->pitches[n],NOT_SOUND))))
- caught_zero = 1;
- if(!caught_skrch && (dz->pitches[n] > dz->nyquist))
- caught_skrch = 1;
- if(caught_zero && caught_skrch)
- break;
- }
- if(caught_zero || caught_skrch) {
- if(caught_zero)
- sprintf(errstr,"You have generated pitch data below %.0lfHz.\n",MINPITCH);
- if(caught_skrch)
- sprintf(errstr,"You have generated pitch data above the nyquist frq.\n");
- return(GOAL_FAILED);
- }
- }
- return(FINISHED);
- }
- int pitch_insert(int is_sil,dataptr dz)
- {
- int n, m, start, end;
- int last_window = dz->wlength - 1;
- int cnt = 0;
- for(n=0;n<dz->itemcnt;n++) {
- start = dz->lparray[0][n];
- end = dz->lparray[1][n];
- if(start > last_window)
- break;
- end = min(end,last_window);
- if(is_sil) {
- for(m=start;m<=end;m++) {
- dz->pitches[m] = (float)NOT_SOUND;
- cnt++;
- }
- } else {
- for(m=start;m<=end;m++) {
- dz->pitches[m] = (float)NOT_PITCH;
- cnt++;
- }
- }
- }
- if(cnt==0) {
- sprintf(errstr,"No insertions made.\n");
- return(GOAL_FAILED);
- }
- return(FINISHED);
- }
- int pitch_to_silence(dataptr dz)
- {
- int n, cnt = 0;
- for(n=0;n < dz->wlength;n++) {
- if(!flteq((double)dz->pitches[n],NOT_PITCH)) {
- dz->pitches[n] = (float)NOT_SOUND;
- cnt++;
- }
- }
- if(cnt==0) {
- sprintf(errstr,"No silence inserted.\n");
- return(GOAL_FAILED);
- }
- return(FINISHED);
- }
- int unpitch_to_silence(dataptr dz)
- {
- int n, cnt = 0;
- for(n=0;n<dz->wlength;n++) {
- if(flteq((double)dz->pitches[n],NOT_PITCH)) {
- dz->pitches[n] = (float)NOT_SOUND;
- cnt++;
- }
- }
- if(cnt==0) {
- sprintf(errstr,"No silence inserted.\n");
- return(GOAL_FAILED);
- }
- return(FINISHED);
- }
- /***************************** GET_ANAL_ENVELOPE ***********************/
- int get_anal_envelope(dataptr dz)
- {
- int exit_status;
- int samps_read, wc, windows_in_buf, samps_left;
- double totalamp;
- dz->flbufptr[1] = dz->flbufptr[2];
- while((samps_read = fgetfbufEx(dz->bigfbuf,dz->big_fsize,dz->ifd[0],0)) > 0) {
- dz->flbufptr[0] = dz->bigfbuf;
- windows_in_buf = samps_read/dz->wanted;
- for(wc=0; wc<windows_in_buf; wc++) {
- if((exit_status = get_totalamp(&totalamp,dz->flbufptr[0],dz->wanted))<0)
- return(exit_status);
- *(dz->flbufptr[1]) = (float)totalamp;
- if(++dz->flbufptr[1] >= dz->flbufptr[3]) {
- dz->flbufptr[1] = dz->flbufptr[2];
- if((exit_status = write_samps(dz->flbufptr[2],dz->big_fsize,dz))<0)
- return(exit_status);
- }
- dz->flbufptr[0] += dz->wanted;
- }
- }
- if((samps_left = dz->flbufptr[1] - dz->flbufptr[2]) > 0) {
- if((exit_status = write_samps(dz->flbufptr[2],samps_left,dz))<0)
- return(exit_status);
- }
- dz->outfile->window_size = (float)(dz->frametime * SECS_TO_MS);
- return(FINISHED);
- }
- /************************************ GENERATE_VOWELS ************************************/
- int generate_vowels(dataptr dz)
- {
- int *vowels = dz->iparray[0];
- double *times = dz->parray[0];
- double startformant1, startformant2, startformant3, endformant1, endformant2, endformant3;
- double formant1, formant2, formant3;
- double form1step, form2step, form3step;
- double starttime, endtime, time, timefrac, timestep, *sensitivity;
- double thisfrq, basefrq;
- double f3startatten, f3endatten, f3attenstep, f3atten;
- double f2startatten, f2endatten, f2attenstep, f2atten;
- float thisamp = (float)(VOLUME_PAD/(double)dz->clength);
- double noisrange = 1.0 - NOISEBASE;
- int cc, vc, exit_status, senslen, is_offset = 0;
- int n = 0, t = 0;
- if((exit_status = define_sensitivity_curve(&sensitivity,&senslen))<0)
- return(exit_status);
- if(dz->param[PV_OFFSET] > 0.0)
- is_offset = 1;
- dz->flbufptr[0] = dz->bigfbuf;
- dz->wanted = dz->infile->origchans;
- if((exit_status = get_formant_frqs
- (vowels[t],&startformant1,&startformant2,&startformant3,&f2startatten,&f3startatten))<0)
- return(exit_status);
- starttime = times[t++];
- if((exit_status = get_formant_frqs(vowels[t],&endformant1,&endformant2,&endformant3,&f2endatten,&f3endatten))<0)
- return(exit_status);
- endtime = times[t++];
- form1step = endformant1 - startformant1;
- form2step = endformant2 - startformant2;
- form3step = endformant3 - startformant3;
- f2attenstep = f2endatten - f2startatten;
- f3attenstep = f3endatten - f3startatten;
- timestep = endtime-starttime;
- formant1 = startformant1; /* works if only one vowel is entered (for time zero) */
- formant2 = startformant2;
- formant3 = startformant3;
- f2atten = f2startatten;
- f3atten = f3startatten;
- while(n < dz->wlength) {
- thisfrq = dz->pitches[n];
- if(thisfrq < 0.0){ /* NO PITCH FOUND : GENERATE NOISE */
- if(thisfrq > NOT_SOUND) {
- basefrq = 0.0;
- dz->flbufptr[0][1] = (float)(drand48() * dz->halfchwidth);
- basefrq += dz->halfchwidth;
- for(cc = 1, vc = 2; cc < dz->clength - 1; cc++, vc += 2) {
- dz->flbufptr[0][FREQ] = (float)((drand48() * dz->chwidth) + basefrq);
- dz->flbufptr[0][AMPP] = (float)(thisamp * ((drand48() * noisrange) + NOISEBASE));
- basefrq += dz->chwidth;
- }
- dz->flbufptr[0][FREQ] = (float)(dz->nyquist - (drand48() * dz->halfchwidth));
- dz->flbufptr[0][AMPP] = (float)(thisamp * ((drand48() * noisrange) + NOISEBASE));
- } else { /* NO SOUND FOUND, GENERATE SILENCE */
- basefrq = 0.0;
- for(cc = 0, vc = 0; cc < dz->clength-1; cc++, vc += 2) {
- dz->flbufptr[0][FREQ] = (float)basefrq;
- dz->flbufptr[0][AMPP] = 0.0f;
- basefrq += dz->chwidth;
- }
- dz->flbufptr[0][FREQ] = (float)dz->nyquist;
- dz->flbufptr[0][AMPP] = 0.0f;
- }
- } else { /* GENERATE VOWEL */
- basefrq = 0.0;
- for(cc = 0, vc = 0; cc < dz->clength-1; cc++, vc += 2) {
- dz->flbufptr[0][AMPP] = 0.0f;
- dz->flbufptr[0][FREQ] = (float)basefrq; /* default frq, overwritten by vowel partials */
- basefrq += dz->chwidth;
- }
- dz->flbufptr[0][AMPP] = 0.0f;
- dz->flbufptr[0][FREQ] = (float)dz->nyquist;
- if(dz->itemcnt) {
- time = n * dz->frametime;
- while(time >= endtime) { /* advance along vowels */
- startformant1 = endformant1;
- startformant2 = endformant2;
- startformant3 = endformant3;
- f2startatten = f2endatten;
- f3startatten = f3endatten;
- starttime = endtime;
- if(t < dz->itemcnt) {
- if((exit_status = get_formant_frqs(vowels[t],&endformant1,&endformant2,&endformant3,&f2endatten,&f3endatten))<0)
- return(exit_status);
- endtime = times[t++];
- } else
- break;
- form1step = endformant1 - startformant1;
- form2step = endformant2 - startformant2;
- form3step = endformant3 - startformant3;
- f2attenstep = f2endatten - f2startatten;
- f3attenstep = f3endatten - f3startatten;
- timestep = endtime-starttime;
- }
- if(!flteq(starttime,endtime)) { /* interpolate between vowels : or retain last vowel */
- timefrac = (time - starttime)/timestep;
- formant1 = startformant1 + (form1step * timefrac);
- formant2 = startformant2 + (form2step * timefrac);
- formant3 = startformant3 + (form3step * timefrac);
- f2atten = f2startatten + (f2attenstep * timefrac);
- f3atten = f3startatten + (f3attenstep * timefrac);
- }
- }
- if((exit_status = generate_vowel_spectrum
- (thisfrq,formant1,formant2,formant3,f2atten,f3atten,sensitivity,senslen,is_offset,dz)) <0)
- return(exit_status);
- }
- if((dz->flbufptr[0] += dz->wanted) >= dz->flbufptr[1]) {
- if((exit_status = write_samps(dz->bigfbuf,dz->big_fsize,dz))<0)
- return(exit_status);
- dz->flbufptr[0] = dz->bigfbuf;
- }
- n++;
- }
- if(dz->flbufptr[0] != dz->bigfbuf) {
- if((exit_status = write_samps(dz->bigfbuf,dz->flbufptr[0] - dz->bigfbuf,dz))<0)
- return(exit_status);
- }
- return(FINISHED);
- }
-
- /************************************ DEFINE_SENSITIVITY_CURVE ************************************
- *
- * approximate compensation for aural sensitivity
- */
- #define LOFRQ_BOOST (2.511) /* 8dB */
- #define HIFRQ_LOSS (0.4) /* -8dB */
- #define LOFRQ_FOOT (250.0)
- #define MIDFRQSHELF_BOT (2000.0)
- #define MIDFRQSHELF_TOP (3000.0)
- #define HIFRQ_FOOT (4000.0)
- #define TOP_OF_SPECTRUM (96000.0) /* double maximum nyquist (i.e. >nyquist: for safety margin) */
- int define_sensitivity_curve(double **sensitivity,int *senslen)
- {
- int arraysize = BIGARRAY;
- double *p;
- int n = 0;
- if((*sensitivity = (double *)malloc(arraysize * sizeof(double)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for time data.\n");
- return(MEMORY_ERROR);
- }
- p = *sensitivity;
- *p++ = 0.0; *p++ = 1.0; n+= 2; /* everything must be in 0-1 range */
- *p++ = LOFRQ_FOOT; *p++ = 1.0; n+= 2; /* for pow() calculations to work, later */
- *p++ = MIDFRQSHELF_BOT; *p++ = 1.0/LOFRQ_BOOST; n+= 2;
- *p++ = MIDFRQSHELF_TOP; *p++ = 1.0/LOFRQ_BOOST; n+= 2;
- *p++ = HIFRQ_FOOT; *p++ = HIFRQ_LOSS/LOFRQ_BOOST; n+= 2;
- *p++ = TOP_OF_SPECTRUM; *p++ = HIFRQ_LOSS/LOFRQ_BOOST; n+= 2;
- if((*sensitivity = (double *)realloc((char *)(*sensitivity),n * sizeof(double)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for sensitivity curve.\n");
- return(MEMORY_ERROR);
- }
- *senslen = n;
- return(FINISHED);
- }
- /************************************ GET_FORMANT_FRQS ************************************/
- int get_formant_frqs
- (int vowel,double *formant1, double *formant2, double *formant3, double *f2atten, double *f3atten)
- {
- switch(vowel) {
- case(VOWEL_EE): *formant1= EE_FORMANT1; *formant2= EE_FORMANT2; *formant3= EE_FORMANT3;
- /* heed */ *f2atten = EE_F2ATTEN; *f3atten = EE_F3ATTEN;
- break;
- case(VOWEL_I): *formant1= I_FORMANT1; *formant2= I_FORMANT2; *formant3= I_FORMANT3;
- /* hid */ *f2atten = I_F2ATTEN; *f3atten = I_F3ATTEN;
- break;
- case(VOWEL_AI): *formant1= AI_FORMANT1; *formant2= AI_FORMANT2; *formant3= AI_FORMANT3;
- /* maid */ *f2atten = AI_F2ATTEN; *f3atten = AI_F3ATTEN;
- break;
- case(VOWEL_AII): *formant1= AII_FORMANT1; *formant2= AII_FORMANT2; *formant3= AII_FORMANT3;
- /* scottish educAted */ *f2atten = AII_F2ATTEN; *f3atten = AII_F3ATTEN;
- break;
- case(VOWEL_E): *formant1= E_FORMANT1; *formant2= E_FORMANT2; *formant3= E_FORMANT3;
- /* head */ *f2atten = E_F2ATTEN; *f3atten = E_F3ATTEN;
- break;
- case(VOWEL_A): *formant1= A_FORMANT1; *formant2= A_FORMANT2; *formant3= A_FORMANT3;
- /* had */ *f2atten = A_F2ATTEN; *f3atten = A_F3ATTEN;
- break;
- case(VOWEL_AR): *formant1= AR_FORMANT1; *formant2= AR_FORMANT2; *formant3= AR_FORMANT3;
- /* hard */ *f2atten = AR_F2ATTEN; *f3atten = AR_F3ATTEN;
- break;
- case(VOWEL_O): *formant1= O_FORMANT1; *formant2= O_FORMANT2; *formant3= O_FORMANT3;
- /* hod */ *f2atten = O_F2ATTEN; *f3atten = O_F3ATTEN;
- break;
- case(VOWEL_OR): *formant1= OR_FORMANT1; *formant2= OR_FORMANT2; *formant3= OR_FORMANT3;
- /* hoard */ *f2atten = OR_F2ATTEN; *f3atten = OR_F3ATTEN;
- break;
- case(VOWEL_OA): *formant1= OA_FORMANT1; *formant2= OA_FORMANT2; *formant3= OA_FORMANT3;
- /* load (North of England) */ *f2atten = OA_F2ATTEN; *f3atten = OA_F3ATTEN;
- break;
- case(VOWEL_U): *formant1= U_FORMANT1; *formant2= U_FORMANT2; *formant3= U_FORMANT3;
- /* hood, mud (Norht of England) */ *f2atten = U_F2ATTEN; *f3atten = U_F3ATTEN;
- break;
- case(VOWEL_UU): *formant1= UU_FORMANT1; *formant2= UU_FORMANT2; *formant3= UU_FORMANT3;
- /* Scottish edUcated */ *f2atten = UU_F2ATTEN; *f3atten = UU_F3ATTEN;
- break;
- case(VOWEL_UI): *formant1= UI_FORMANT1; *formant2= UI_FORMANT2; *formant3= UI_FORMANT3;
- /* Scottish 'could' */ *f2atten = UI_F2ATTEN; *f3atten = UI_F3ATTEN;
- break;
- case(VOWEL_OO): *formant1= OO_FORMANT1; *formant2= OO_FORMANT2; *formant3= OO_FORMANT3;
- /* mood */ *f2atten = OO_F2ATTEN; *f3atten = OO_F3ATTEN;
- break;
- case(VOWEL_XX): *formant1= XX_FORMANT1; *formant2= XX_FORMANT2; *formant3= XX_FORMANT3;
- /* mud (South of England) */ *f2atten = XX_F2ATTEN; *f3atten = XX_F3ATTEN;
- break;
- case(VOWEL_X): *formant1= X_FORMANT1; *formant2= X_FORMANT2; *formant3 = X_FORMANT3;
- /* the, herd */ *f2atten = X_F2ATTEN; *f3atten = X_F3ATTEN;
- break;
- case(VOWEL_N): *formant1= N_FORMANT1; *formant2= N_FORMANT2; *formant3 = N_FORMANT3;
- /* 'n' */ *f2atten = N_F2ATTEN; *f3atten = N_F3ATTEN;
- break;
- case(VOWEL_M): *formant1= M_FORMANT1; *formant2= M_FORMANT2; *formant3 = M_FORMANT3;
- /* 'm' */ *f2atten = M_F2ATTEN; *f3atten = M_F3ATTEN;
- break;
- case(VOWEL_R): *formant1= R_FORMANT1; *formant2= R_FORMANT2; *formant3 = R_FORMANT3;
- /* dRaws */ *f2atten = R_F2ATTEN; *f3atten = R_F3ATTEN;
- break;
- case(VOWEL_TH): *formant1= TH_FORMANT1; *formant2= TH_FORMANT2; *formant3 = TH_FORMANT3;
- /* dRaws */ *f2atten = TH_F2ATTEN; *f3atten = TH_F3ATTEN;
- break;
- default:
- sprintf(errstr,"Unknown vowel\n");
- return(PROGRAM_ERROR);
- }
- return(FINISHED);
- }
- /************************************ GENERATE_VOWEL_SPECTRUM ************************************
- *
- * "sensitivity" compensates for frq sensitivity of ear at low end, and attenuates
- * formant bamds above c3500.
- */
- int generate_vowel_spectrum(double frq,double formant1,double formant2,double formant3,double f2atten,double f3atten,
- double *sensitivity,int senslen,int is_offset,dataptr dz)
- {
- double hfwidth1, hfwidth2, hfwidth3 = 0.0, lolim1, lolim2, lolim3 = 0.0, hilim1, hilim2, hilim3 = 0.0;
- double basefrq = frq, harmfrq = basefrq, thisfrq = basefrq, frq_offset;
- double amp, amp2 = 0.0, amp3 = 0.0, totamp = 0.0;
- int exit_status, cc, vc;
- int overlapped_formants12 = 0, overlapped_formants23 = 0, overlapped_formants13 = 0;
- int is_overlap12, is_overlap23, is_overlap13;
- double toplim;
- int is_third_formant = 0;
- double signal_base = 1.0 - dz->param[PV_PKRANG];
- if(formant3 > 0.0)
- is_third_formant = 1;
- hfwidth1 = formant1 * dz->param[PV_HWIDTH]; /* set limits of formant bands */
- lolim1 = formant1 - hfwidth1;
- hilim1 = formant1 + hfwidth1;
- hfwidth2 = formant2 * dz->param[PV_HWIDTH];
- lolim2 = formant2 - hfwidth2;
- hilim2 = formant2 + hfwidth2;
- if(is_third_formant) {
- hfwidth3 = formant3 * dz->param[PV_HWIDTH];
- lolim3 = formant3 - hfwidth3;
- hilim3 = formant3 + hfwidth3;
- }
- if(hilim1 > lolim2) /* deal with overlapping formants */
- overlapped_formants12 = 1;
- if(is_third_formant) {
- if(hilim2 > lolim3)
- overlapped_formants23 = 1;
- if(hilim1 > lolim3)
- overlapped_formants13 = 1;
- }
- if(is_third_formant)
- toplim = hilim3;
- else
- toplim = hilim2;
- while(thisfrq < toplim) {
- amp = 0.0; /* amplitude will get signal_base * sensitivity */
- is_overlap12 = 0;
- is_overlap23 = 0;
- is_overlap13 = 0;
- if(thisfrq < lolim1) {
- if(flteq(thisfrq,basefrq))
- amp = dz->param[PV_FUNBAS];
- } else if((thisfrq > lolim1) && (thisfrq < hilim1)) {
- if(overlapped_formants12 && (thisfrq > lolim2)) {
- is_overlap12 = 1;
- if(thisfrq >= formant2)
- amp2 = (hilim2 - thisfrq)/hfwidth2;
- else
- amp2 = (thisfrq - lolim2)/hfwidth2;
- amp2 *= f2atten;
- }
- if(is_third_formant) {
- if(overlapped_formants13 && (thisfrq > lolim3)) {
- is_overlap13 = 1;
- if(thisfrq >= formant3)
- amp3 = (hilim3 - thisfrq)/hfwidth3;
- else
- amp3 = (thisfrq - lolim3)/hfwidth3;
- amp3 *= f3atten;
- }
- }
- if(thisfrq >= formant1)
- amp = (hilim1 - thisfrq)/hfwidth1;
- else
- amp = (thisfrq - lolim1)/hfwidth1;
- if(is_overlap12)
- amp = max(amp,amp2);
- if(is_third_formant && is_overlap13)
- amp = max(amp,amp3);
- } else if((thisfrq > lolim2) && (thisfrq < hilim2)) {
- if(is_third_formant && overlapped_formants23 && (thisfrq > lolim3)) {
- is_overlap23 = 1;
- if(thisfrq >= formant3)
- amp3 = (hilim3 - thisfrq)/hfwidth3;
- else
- amp3 = (thisfrq - lolim3)/hfwidth3;
- amp3 *= f3atten;
- }
- if(thisfrq >= formant2)
- amp = (hilim2 - thisfrq)/hfwidth2;
- else
- amp = (thisfrq - lolim2)/hfwidth2;
- amp *= f2atten;
- if(is_third_formant && is_overlap23)
- amp = max(amp,amp3);
- } else if(is_third_formant && (thisfrq > lolim3)) {
- if(thisfrq >= formant3)
- amp = (hilim3 - thisfrq)/hfwidth3;
- else
- amp = (thisfrq - lolim3)/hfwidth3;
- amp *= f3atten;
- }
- amp = pow(amp,dz->param[PV_CURVIT]);
- amp *= dz->param[PV_PKRANG];
- amp += signal_base;
- if((exit_status = adjust_for_sensitivity(&,(double)thisfrq,sensitivity,senslen))<0)
- return(exit_status);
- cc = (int)((thisfrq + dz->halfchwidth)/dz->chwidth);
- vc = cc * 2;
- dz->flbufptr[0][AMPP] = (float)amp;
- dz->flbufptr[0][FREQ] = (float)thisfrq;
- totamp += amp;
- if(is_offset) {
- harmfrq += basefrq;
- frq_offset = (drand48() - .5) * dz->param[PV_OFFSET] * basefrq;
- if(harmfrq + frq_offset > dz->nyquist)
- thisfrq = harmfrq - frq_offset;
- else
- thisfrq = harmfrq + frq_offset;
- } else
- thisfrq += basefrq;
- if(thisfrq > dz->nyquist) {
- sprintf(errstr,"Error in setting formant: overran nyquist\n");
- return(PROGRAM_ERROR);
- }
- }
- if((exit_status = normalise(VOLUME_PAD,totamp,dz))<0)
- return(exit_status);
- return(FINISHED);
- }
- /************************************ ADJUST_FOR_SENSITIVITY ************************************/
- int adjust_for_sensitivity(double *amp,double frq,double *sensitivity,int senslen)
- {
- int n = 0;
- double multiplier, losensfrq, hisensfrq, losens, hisens, frqfrac, sensstep;
- while(frq > sensitivity[n]) {
- n += 2;
- if(n > senslen) {
- sprintf(errstr,"Failed to find sensitivity value (1)\n");
- return(PROGRAM_ERROR);
- }
- }
- hisensfrq = sensitivity[n];
- n -= 2;
- if(n < 0) {
- sprintf(errstr,"Failed to find sensitivity value (2)\n");
- return(PROGRAM_ERROR);
- }
- losensfrq = sensitivity[n];
- frqfrac = (frq - losensfrq)/(hisensfrq - losensfrq);
- n++;
- losens = sensitivity[n];
- n += 2;
- if(n >= senslen) {
- sprintf(errstr,"Failed to find sensitivity value (3)\n");
- return(PROGRAM_ERROR);
- }
- hisens = sensitivity[n];
- sensstep = hisens - losens;
- multiplier = losens + (sensstep * frqfrac);
- * amp *= multiplier;
- return(FINISHED);
- }
- /************************************ GENERATE_PITCH ************************************/
- int generate_pitch(dataptr dz)
- {
- double *times = dz->parray[0];
- double *pitch = dz->parray[1];
- double startpitch, endpitch, pitchstep, thispitch;
- double starttime, endtime, time, timefrac, timestep;
- int n = 0, m = 0, samps_written;
- if((dz->pitches = (float *)malloc(dz->wlength * sizeof(float)))==NULL) {
- sprintf(errstr,"Insufficient memory to store pitch data\n");
- return(MEMORY_ERROR);
- }
- starttime = times[m];
- startpitch = pitch[m];
- m++;
- endtime = times[m];
- endpitch = pitch[m];
- m++;
- pitchstep = endpitch - startpitch;
- timestep = endtime - starttime;
- while(n < dz->wlength) {
- time = n * dz->frametime;
- while(time >= endtime) { /* advance along (MIDI) pitches */
- startpitch = endpitch;
- starttime = endtime;
- if(m < dz->itemcnt) {
- endtime = times[m];
- endpitch = pitch[m];
- m++;
- } else
- break;
- }
- if(!flteq(starttime,endtime)) { /* interpolate between pitches : or retain last pitches */
- pitchstep = endpitch - startpitch;
- timestep = endtime - starttime;
- timefrac = (time - starttime)/timestep;
- thispitch = (pitchstep * timefrac) + startpitch;
- } else
- thispitch = startpitch;
- dz->pitches[n++] = (float)miditohz(thispitch);
- }
- dz->is_transpos = 0;
- return write_samps_no_report(dz->pitches,dz->wlength,&samps_written,dz);
- }
- /********************** REMOVE_PITCH_ZEROS *********************
- *
- * This function removes pitch zeroes (and si;ences) by interpolation.
- */
- int remove_pitch_zeros(dataptr dz)
- {
- int gotglitch = FALSE, gstart = -1;
- double pstep, pstartval = 0.0;
- int n, m;
- for(n=0;n<dz->wlength;n++) {
- if(gotglitch) {
- if(dz->pitches[n] < MINPITCH)
- continue;
- if(gstart<0) {
- for(m=0; m < n; m++) /* Interp to start if ness */
- dz->pitches[m] = dz->pitches[n];
- } else { /* Interp between good vals */
- switch(dz->mode) {
- case(PI_GLIDE):
- pstep = (dz->pitches[n] - pstartval)/(double)(n - gstart);
- for(m=gstart+1; m < n; m++) {
- pstartval += pstep;
- dz->pitches[m] = (float)pstartval;
- }
- break;
- case(PI_SUSTAIN):
- for(m=gstart+1; m < n; m++)
- dz->pitches[m] = (float)pstartval;
- break;
- }
- }
- gotglitch = 0;
- } else {
- if(dz->pitches[n] >= MINPITCH)
- continue;
- gstart = n-1;
- if(gstart >= 0)
- pstartval = (double)dz->pitches[gstart];
- gotglitch = 1;
- }
- }
- if(gotglitch) {
- if(gstart < 0) {
- sprintf(errstr,"No pitched data found.");
- return(GOAL_FAILED);
- }
- for(m=gstart+1; m < n; m++) /* Interp to end if ness */
- dz->pitches[m] = (float)pstartval;
- }
- return(FINISHED);
- }
- /*************************** CONVERT_PITCH_FROM_BINARY_TO_TEXT **************************/
- int convert_pitch_from_binary_to_text(dataptr dz)
- {
- int exit_status;
- int brklen, n, m;
- if((dz->parray[0] = malloc(((dz->wlength + 1) * 2) * sizeof(double)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY FOR TEXT DATA\n");
- return MEMORY_ERROR;
- }
- if((exit_status = interpolate_pitch(dz->pitches,0,dz))<0)
- return(exit_status);
- if(dz->wlength == 1) {
- if((exit_status = convert_single_window_pch_or_transpos_data_to_brkpnttable(&brklen,dz->pitches,dz->frametime,0,dz))<0)
- return(exit_status);
- } else {
- if((exit_status = convert_pch_or_transpos_data_to_brkpnttable(&brklen,dz->pitches,dz->frametime,0,dz))<0)
- return(exit_status);
- }
- for(n=0,m=0;n<brklen;n++,m+=2)
- fprintf(dz->fp,"%lf\t%lf\n",dz->parray[0][m],dz->parray[0][m+1]);
- return(FINISHED);
- }
- /***************** CONVERT_SINGLE_WINDOW_PCH_OR_TRANSPOS_DATA_TO_BRKPNTTABLE ***********************/
- int convert_single_window_pch_or_transpos_data_to_brkpnttable(int *brksize,float *floatbuf,float frametime,int array_no,dataptr dz)
- {
- double *q;
- float *p = floatbuf;
- int bsize;
- q = dz->parray[array_no];
- *q++ = 0.0;
- *q++ = (double)*p++;
- bsize = q - dz->parray[array_no];
- if((dz->parray[array_no] = (double *)realloc((char *)dz->parray[array_no],bsize*sizeof(double)))==NULL) {
- sprintf(errstr,"convert_single_window_pch_or_transpos_data_to_brkpnttable()\n");
- return(MEMORY_ERROR);
- }
- *brksize = bsize/2;
- return(FINISHED);
- }
-
|