| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729 |
- /*
- * Copyright (c) 1983-2023 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 = 0.0;
- 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);
- }
|