spectune.c 133 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412
  1. /*
  2. * Copyright (c) 1983-2023 Trevor Wishart and Composers Desktop Project Ltd
  3. * http://www.trevorwishart.co.uk
  4. * http://www.composersdesktop.com
  5. *
  6. This file is part of the CDP System.
  7. The CDP System is free software; you can redistribute it
  8. and/or modify it under the terms of the GNU Lesser General Public
  9. License as published by the Free Software Foundation; either
  10. version 2.1 of the License, or (at your option) any later version.
  11. The CDP System is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. GNU Lesser General Public License for more details.
  15. You should have received a copy of the GNU Lesser General Public
  16. License along with the CDP System; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
  18. 02111-1307 USA
  19. *
  20. */
  21. // This algorithm finds the pitch (if any) in each window,
  22. // marking no-pitch-found with a -1 value.
  23. // It discards any windows falling below a threshold amplitude.
  24. // (It can ,optionally, smooth the output data, and remove "blips"
  25. // i.e. "pitches lasting for no more than 1 window".
  26. // but this is not essential, as the statistical survey to follow
  27. // should normally eliminate these anomalies.
  28. //
  29. // It then allots the found pitches to 1/8th semitone bins,
  30. // and finds the bin with the most entries.
  31. // This can be done by counting the windows that fall into the bin,
  32. // or by summing the total-loudnesses of the windows that fall into the bin.
  33. // The bin with the highest score/weight is taken to be the most prominent pitch.
  34. //
  35. // Note that, if the pitch is wrong but falls on a prominent harmonic,
  36. // and the tuning is to a harmonic field with a large number of pitches to tune to,
  37. // such an error may still lead to an appropriate transposition,
  38. // as the real root with be transposed along with the prominent harmonic.
  39. #include <stdio.h>
  40. #include <stdlib.h>
  41. #include <structures.h>
  42. #include <tkglobals.h>
  43. #include <pnames.h>
  44. #include <filetype.h>
  45. #include <processno.h>
  46. #include <modeno.h>
  47. #include <arrays.h>
  48. #include <flags.h>
  49. #include <logic.h>
  50. #include <fmnts.h>
  51. #include <formants.h>
  52. #include <globcon.h>
  53. #include <cdpmain.h>
  54. #include <math.h>
  55. #include <mixxcon.h>
  56. #include <osbind.h>
  57. #include <standalone.h>
  58. #include <speccon.h>
  59. #include <ctype.h>
  60. #include <sfsys.h>
  61. #include <string.h>
  62. #include <srates.h>
  63. //#ifdef unix
  64. #define round(x) lround((x))
  65. //#endif
  66. #ifndef HUGE
  67. #define HUGE 3.40282347e+38F
  68. #endif
  69. #define searchsize rampbrksize
  70. #define TUNING_ARRAY 0
  71. #define TIMING_ARRAY 0
  72. #define FOUND_PITCHES 1
  73. #define TOTALAMPS 2
  74. #define PITCHWEIGHT 3
  75. #define WEIGHTEDSCORE 4
  76. #define AMPBINSCNT 32
  77. #define MINSEGLEN (0.03 + FLTERR) // 2 * 15mS splices and margin-of-error for segments in Loom VBOX
  78. static double st_intun, st_noise;
  79. static int st_wndws;
  80. char errstr[2400];
  81. int anal_infiles = 1;
  82. int sloom = 0;
  83. int sloombatch = 0;
  84. const char* cdp_version = "7.1.0";
  85. /* CDP LIBRARY FUNCTIONS TRANSFERRED HERE */
  86. static int set_param_data(aplptr ap, int special_data,int maxparamcnt,int paramcnt,char *paramlist);
  87. static int set_vflgs(aplptr ap,char *optflags,int optcnt,char *optlist,
  88. char *varflags,int vflagcnt, int vparamcnt,char *varlist);
  89. static int setup_parameter_storage_and_constants(int storage_cnt,dataptr dz);
  90. static int initialise_is_int_and_no_brk_constants(int storage_cnt,dataptr dz);
  91. static int mark_parameter_types(dataptr dz,aplptr ap);
  92. static int establish_application(dataptr dz);
  93. static int application_init(dataptr dz);
  94. static int initialise_vflags(dataptr dz);
  95. static int setup_input_param_defaultval_stores(int tipc,aplptr ap);
  96. static int setup_and_init_input_param_activity(dataptr dz,int tipc);
  97. static int get_tk_cmdline_word(int *cmdlinecnt,char ***cmdline,char *q);
  98. static int assign_file_data_storage(int infilecnt,dataptr dz);
  99. /* CDP LIB FUNCTION MODIFIED TO AVOID CALLING setup_particular_application() */
  100. static int parse_sloom_data(int argc,char *argv[],char ***cmdline,int *cmdlinecnt,dataptr dz);
  101. /* SIMPLIFICATION OF LIB FUNC TO APPLY TO JUST THIS FUNCTION */
  102. static int parse_infile_and_check_type(char **cmdline,dataptr dz);
  103. static int handle_the_outfile(int *cmdlinecnt,char ***cmdline,int is_launched,dataptr dz);
  104. static int setup_the_application(dataptr dz);
  105. static int setup_the_param_ranges_and_defaults(dataptr dz);
  106. static int check_the_param_validity_and_consistency(dataptr dz);
  107. static int get_the_process_no(char *prog_identifier_from_cmdline,dataptr dz);
  108. static int setup_and_init_input_brktable_constants(dataptr dz,int brkcnt);
  109. static int get_the_mode_no(char *str, dataptr dz);
  110. /* BYPASS LIBRARY GLOBAL FUNCTION TO GO DIRECTLY TO SPECIFIC APPLIC FUNCTIONS */
  111. static int handle_tuning_data(int *cmdlinecnt,char ***cmdline,dataptr dz);
  112. static int handle_segmentation_data(int *cmdlinecnt,char ***cmdline,dataptr dz);
  113. static int fill_tuning_array(dataptr dz);
  114. static int do_spectune(dataptr dz);
  115. static int do_specpedal(dataptr dz);
  116. static int specget(double *pitch,chvptr *partials,dataptr dz);
  117. static int close_to_frq_already_in_ring(chvptr *there,double frq1,dataptr dz);
  118. static int substitute_in_ring(int vc,chvptr here,chvptr there,dataptr dz);
  119. static int insert_in_ring(int vc, chvptr here, dataptr dz);
  120. static int put_ring_frqs_in_ascending_order(chvptr **partials,float *minamp,dataptr dz);
  121. //static void find_pitch(double *pitch,chvptr *partials,double lo_loud_partial,double hi_loud_partial,float minamp,dataptr dz);
  122. static int equivalent_pitches(double frq1, double frq2, dataptr dz);
  123. //static int is_peak_at(double frq,int window_offset,float minamp,dataptr dz);
  124. //static int enough_partials_are_harmonics(chvptr *partials,double pich_pich,dataptr dz);
  125. //static int is_a_harmonic(double frq1,double frq2,dataptr dz);
  126. //static int local_peak(int thiscc,double frq, float *thisbuf, dataptr dz);
  127. static int spectrnsf(double transpos,dataptr dz);
  128. static int spectrnsp(double transpos,dataptr dz);
  129. static int tranpose_within_formant_envelope(double transpos,int vc,dataptr dz);
  130. static int reposition_partials_in_appropriate_channels(double transpos, dataptr dz);
  131. static int tidy_up_the_pitch_data(double *pitches,int pitchcnt,dataptr dz);
  132. static int test_glitch_backwards(int gltchstart,int gltchend,char *smooth,double max_pglide,int wlength,double *pitches);
  133. static int test_glitch_forwards(int gltchstart,int gltchend,char *smooth,double max_pglide,double *pitches);
  134. static void remove_unsmooth_pitches(char *smooth,int wlength,double *pitches);
  135. static int test_glitch_sets(char *smooth,double max_pglide,int wlength,double *pitches);
  136. static int is_smooth_from_after(int n,char *smooth,double max_pglide,double *pitches);
  137. static int is_smooth_from_before(int n,char *smooth,double max_pglide,double *pitches);
  138. static int is_finalpitch_smooth(char *smooth,double max_pglide,int wlength,double *pitches);
  139. static int is_initialpitch_smooth(char *smooth,double max_pglide,double *pitches);
  140. static int is_smooth_from_both_sides(int n,double max_pglide,double *pitches);
  141. static int anti_noise_smoothing(int wlength,double *pitches,float frametime);
  142. static int pitch_found(double *pitches,int pitchcnt);
  143. static int mark_zeros_in_pitchdata(double *pitches,int pitchcnt,dataptr dz);
  144. static int eliminate_blips_in_pitch_data(double *pitches,int pitchcnt,dataptr dz);
  145. static int alternative_find_pitch(double *pitch,chvptr *partials,dataptr dz);
  146. static int setup_formants(dataptr dz);
  147. static int set_specenv_frqs(int arraycnt,dataptr dz);
  148. static int setup_octaveband_steps(double **interval,dataptr dz);
  149. static int setup_low_octave_bands(int arraycnt,dataptr dz);
  150. extern int special_operation_on_window_zero(dataptr dz);
  151. extern int allocate_single_buffer_plus_peakarray(dataptr dz);
  152. extern int get_totalamp_and_maxamp(double *totalamp,float *maxamp,float *sbuf,int wanted);
  153. extern int get_peaks(dataptr dz) ;
  154. extern int tunepeaks(int *tuned,dataptr dz);
  155. /**************************************** MAIN *********************************************/
  156. int main(int argc,char *argv[])
  157. {
  158. int exit_status;
  159. dataptr dz = NULL;
  160. char **cmdline;
  161. int cmdlinecnt;
  162. // aplptr ap;
  163. int is_launched = FALSE;
  164. if(argc==2 && (strcmp(argv[1],"--version") == 0)) {
  165. fprintf(stdout,"%s\n",cdp_version);
  166. fflush(stdout);
  167. return 0;
  168. }
  169. /* CHECK FOR SOUNDLOOM */
  170. if((sloom = sound_loom_in_use(&argc,&argv)) > 1) {
  171. sloom = 0;
  172. sloombatch = 1;
  173. }
  174. if(sflinit("cdp")){
  175. sfperror("cdp: initialisation\n");
  176. return(FAILED);
  177. }
  178. /* SET UP THE PRINCIPLE DATASTRUCTURE */
  179. if((exit_status = establish_datastructure(&dz))<0) { // CDP LIB
  180. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  181. return(FAILED);
  182. }
  183. if(!sloom) {
  184. if(argc == 1) {
  185. usage1();
  186. return(FAILED);
  187. } else if(argc == 2) {
  188. usage2(argv[1]);
  189. return(FAILED);
  190. }
  191. if((exit_status = make_initial_cmdline_check(&argc,&argv))<0) { // CDP LIB
  192. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  193. return(FAILED);
  194. }
  195. cmdline = argv;
  196. cmdlinecnt = argc;
  197. if((get_the_process_no(argv[0],dz))<0)
  198. return(FAILED);
  199. cmdline++;
  200. cmdlinecnt--;
  201. dz->maxmode = 6;
  202. if((get_the_mode_no(cmdline[0],dz))<0)
  203. return(FAILED);
  204. cmdline++;
  205. cmdlinecnt--;
  206. if((exit_status = setup_the_application(dz))<0) {
  207. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  208. return(FAILED);
  209. }
  210. if((exit_status = count_and_allocate_for_infiles(cmdlinecnt,cmdline,dz))<0) { // CDP LIB
  211. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  212. return(FAILED);
  213. }
  214. } else {
  215. //parse_TK_data() =
  216. if((exit_status = parse_sloom_data(argc,argv,&cmdline,&cmdlinecnt,dz))<0) {
  217. exit_status = print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  218. return(exit_status);
  219. }
  220. }
  221. // ap = dz->application;
  222. // parse_infile_and_hone_type() =
  223. if((exit_status = parse_infile_and_check_type(cmdline,dz))<0) {
  224. exit_status = print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  225. return(FAILED);
  226. }
  227. // setup_param_ranges_and_defaults() =
  228. if((exit_status = setup_the_param_ranges_and_defaults(dz))<0) {
  229. exit_status = print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  230. return(FAILED);
  231. }
  232. // open_first_infile CDP LIB
  233. if((exit_status = open_first_infile(cmdline[0],dz))<0) {
  234. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  235. return(FAILED);
  236. }
  237. cmdlinecnt--;
  238. cmdline++;
  239. if(dz->mode == 3) { // No output file
  240. if(sloom) {
  241. cmdlinecnt--;
  242. cmdline++;
  243. }
  244. } else {
  245. if((exit_status = handle_the_outfile(&cmdlinecnt,&cmdline,is_launched,dz))<0) {
  246. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  247. return(FAILED);
  248. }
  249. if(dz->mode != 4 && dz->mode != 5) {
  250. if(!dz->vflag[2]) {
  251. // handle_formants() formants for pitchshift-with-fixed-formants
  252. if((exit_status = setup_formants(dz))<0) {
  253. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  254. return(FAILED);
  255. }
  256. }
  257. }
  258. }
  259. // handle_formant_quiksearch() redundant
  260. // handle_special_data() redundant except
  261. if(dz->mode != 3) {
  262. if(dz->mode > 0) {
  263. if(dz->mode == 5) {
  264. if((exit_status = handle_segmentation_data(&cmdlinecnt,&cmdline,dz))<0) {
  265. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  266. return(FAILED);
  267. }
  268. } else {
  269. if((exit_status = handle_tuning_data(&cmdlinecnt,&cmdline,dz))<0) {
  270. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  271. return(FAILED);
  272. }
  273. }
  274. } else {
  275. if((exit_status = fill_tuning_array(dz))<0) {
  276. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  277. return(FAILED);
  278. }
  279. }
  280. }
  281. if((exit_status = read_parameters_and_flags(&cmdline,&cmdlinecnt,dz))<0) { // CDP LIB
  282. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  283. return(FAILED);
  284. }
  285. //check_param_validity_and_consistency .....
  286. if((exit_status = check_the_param_validity_and_consistency(dz))<0) {
  287. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  288. return(FAILED);
  289. }
  290. is_launched = TRUE;
  291. //allocate_large_buffers() ... replaced by CDP LIB
  292. dz->extra_bufcnt = 1;
  293. if(dz->mode == 4)
  294. dz->bptrcnt = 4;
  295. else
  296. dz->bptrcnt = 1;
  297. if((exit_status = establish_spec_bufptrs_and_extra_buffers(dz))<0) {
  298. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  299. return(FAILED);
  300. }
  301. if(dz->mode == 4) {
  302. if((exit_status = allocate_single_buffer_plus_peakarray(dz))< 0) {
  303. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  304. return(FAILED);
  305. }
  306. } else {
  307. if((exit_status = allocate_single_buffer(dz))< 0) {
  308. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  309. return(FAILED);
  310. }
  311. if((dz->windowbuf[0] = (float *)malloc(dz->wanted * sizeof(float)))==NULL) {
  312. sprintf(errstr,"Insufficient memory for extra channel-shuffling buffer.\n");
  313. return(MEMORY_ERROR);
  314. }
  315. if(dz->mode == 5)
  316. dz->searchsize = dz->wlength;
  317. else
  318. dz->searchsize = dz->iparam[ST_ETIME] - dz->iparam[ST_STIME] + 1;
  319. if ((dz->parray[FOUND_PITCHES] = (double *)malloc((dz->searchsize + 4) * sizeof(double)))==NULL) {
  320. sprintf(errstr,"Insufficient memory to store found pitches.\n");
  321. return(MEMORY_ERROR);
  322. }
  323. if ((dz->parray[TOTALAMPS] = (double *)malloc((dz->searchsize + 4) * sizeof(double)))==NULL) {
  324. sprintf(errstr,"Insufficient memory to store window amplitudes.\n");
  325. return(MEMORY_ERROR);
  326. }
  327. if ((dz->parray[PITCHWEIGHT] = (double *)malloc((dz->searchsize + 4) * sizeof(double)))==NULL) {
  328. sprintf(errstr,"Insufficient memory to store pitched-window amplitudes.\n");
  329. return(MEMORY_ERROR);
  330. }
  331. if ((dz->parray[WEIGHTEDSCORE] = (double *)malloc((dz->searchsize + 4) * sizeof(double)))==NULL) {
  332. sprintf(errstr,"Insufficient memory to store pitches amplitude weightings.\n");
  333. return(MEMORY_ERROR);
  334. }
  335. if ((dz->iparray[0] = (int *)malloc((dz->searchsize + 4) * sizeof(int)))==NULL) {
  336. sprintf(errstr,"Insufficient memory for pitch bins.\n");
  337. return(MEMORY_ERROR);
  338. }
  339. if ((dz->iparray[1] = (int *)malloc((dz->searchsize + 4) * sizeof(int)))==NULL) {
  340. sprintf(errstr,"Insufficient memory for pitch bin counters.\n");
  341. return(MEMORY_ERROR);
  342. }
  343. //param_preprocess() redundant
  344. if((exit_status = setup_ring(dz) )<0) { // CDP LIB
  345. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  346. return(FAILED);
  347. }
  348. }
  349. //spec_process_file =
  350. if(dz->mode==4)
  351. exit_status = do_specpedal(dz);
  352. else
  353. exit_status = do_spectune(dz);
  354. if(exit_status < 0) {
  355. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  356. return(FAILED);
  357. }
  358. if((exit_status = complete_output(dz))<0) { // CDP LIB
  359. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  360. return(FAILED);
  361. }
  362. exit_status = print_messages_and_close_sndfiles(FINISHED,is_launched,dz); // CDP LIB
  363. free(dz);
  364. return(SUCCEEDED);
  365. }
  366. /**********************************************
  367. REPLACED CDP LIB FUNCTIONS
  368. **********************************************/
  369. /****************************** SET_PARAM_DATA *********************************/
  370. int set_param_data(aplptr ap, int special_data,int maxparamcnt,int paramcnt,char *paramlist)
  371. {
  372. ap->special_data = (char)special_data;
  373. ap->param_cnt = (char)paramcnt;
  374. ap->max_param_cnt = (char)maxparamcnt;
  375. if(ap->max_param_cnt>0) {
  376. if((ap->param_list = (char *)malloc((size_t)(ap->max_param_cnt+1)))==NULL) {
  377. sprintf(errstr,"INSUFFICIENT MEMORY: for param_list\n");
  378. return(MEMORY_ERROR);
  379. }
  380. strcpy(ap->param_list,paramlist);
  381. }
  382. return(FINISHED);
  383. }
  384. /****************************** SET_VFLGS *********************************/
  385. int set_vflgs
  386. (aplptr ap,char *optflags,int optcnt,char *optlist,char *varflags,int vflagcnt, int vparamcnt,char *varlist)
  387. {
  388. ap->option_cnt = (char) optcnt; /*RWD added cast */
  389. if(optcnt) {
  390. if((ap->option_list = (char *)malloc((size_t)(optcnt+1)))==NULL) {
  391. sprintf(errstr,"INSUFFICIENT MEMORY: for option_list\n");
  392. return(MEMORY_ERROR);
  393. }
  394. strcpy(ap->option_list,optlist);
  395. if((ap->option_flags = (char *)malloc((size_t)(optcnt+1)))==NULL) {
  396. sprintf(errstr,"INSUFFICIENT MEMORY: for option_flags\n");
  397. return(MEMORY_ERROR);
  398. }
  399. strcpy(ap->option_flags,optflags);
  400. }
  401. ap->vflag_cnt = (char) vflagcnt;
  402. ap->variant_param_cnt = (char) vparamcnt;
  403. if(vflagcnt) {
  404. if((ap->variant_list = (char *)malloc((size_t)(vflagcnt+1)))==NULL) {
  405. sprintf(errstr,"INSUFFICIENT MEMORY: for variant_list\n");
  406. return(MEMORY_ERROR);
  407. }
  408. strcpy(ap->variant_list,varlist);
  409. if((ap->variant_flags = (char *)malloc((size_t)(vflagcnt+1)))==NULL) {
  410. sprintf(errstr,"INSUFFICIENT MEMORY: for variant_flags\n");
  411. return(MEMORY_ERROR);
  412. }
  413. strcpy(ap->variant_flags,varflags);
  414. }
  415. return(FINISHED);
  416. }
  417. /***************************** APPLICATION_INIT **************************/
  418. int application_init(dataptr dz)
  419. {
  420. int exit_status;
  421. int storage_cnt;
  422. int tipc, brkcnt;
  423. aplptr ap = dz->application;
  424. if(ap->vflag_cnt>0)
  425. initialise_vflags(dz);
  426. tipc = ap->max_param_cnt + ap->option_cnt + ap->variant_param_cnt;
  427. ap->total_input_param_cnt = (char)tipc;
  428. if(tipc>0) {
  429. if((exit_status = setup_input_param_range_stores(tipc,ap))<0)
  430. return(exit_status);
  431. if((exit_status = setup_input_param_defaultval_stores(tipc,ap))<0)
  432. return(exit_status);
  433. if((exit_status = setup_and_init_input_param_activity(dz,tipc))<0)
  434. return(exit_status);
  435. }
  436. brkcnt = tipc;
  437. if(brkcnt>0) {
  438. if((exit_status = setup_and_init_input_brktable_constants(dz,brkcnt))<0)
  439. return(exit_status);
  440. }
  441. if((storage_cnt = tipc + ap->internal_param_cnt)>0) {
  442. if((exit_status = setup_parameter_storage_and_constants(storage_cnt,dz))<0)
  443. return(exit_status);
  444. if((exit_status = initialise_is_int_and_no_brk_constants(storage_cnt,dz))<0)
  445. return(exit_status);
  446. }
  447. if((exit_status = mark_parameter_types(dz,ap))<0)
  448. return(exit_status);
  449. // establish_infile_constants() replaced by
  450. dz->infilecnt = 1;
  451. //establish_bufptrs_and_extra_buffers():
  452. dz->array_cnt=5;
  453. if((dz->parray = (double **)malloc(dz->array_cnt * sizeof(double *)))==NULL) {
  454. sprintf(errstr,"INSUFFICIENT MEMORY for internal double arrays.\n");
  455. return(MEMORY_ERROR);
  456. }
  457. dz->iarray_cnt=2;
  458. if((dz->iparray = (int **)malloc(dz->iarray_cnt * sizeof(int *)))==NULL) {
  459. sprintf(errstr,"INSUFFICIENT MEMORY for internal integer arrays.\n");
  460. return(MEMORY_ERROR);
  461. }
  462. dz->parray[TUNING_ARRAY] = NULL;
  463. dz->parray[FOUND_PITCHES] = NULL;
  464. dz->parray[2] = NULL;
  465. dz->iparray[0] = NULL;
  466. dz->iparray[1] = NULL;
  467. return(FINISHED);
  468. }
  469. /******************************** SETUP_AND_INIT_INPUT_BRKTABLE_CONSTANTS ********************************/
  470. int setup_and_init_input_brktable_constants(dataptr dz,int brkcnt)
  471. {
  472. int n;
  473. if((dz->brk = (double **)malloc(brkcnt * sizeof(double *)))==NULL) {
  474. sprintf(errstr,"setup_and_init_input_brktable_constants(): 1\n");
  475. return(MEMORY_ERROR);
  476. }
  477. if((dz->brkptr = (double **)malloc(brkcnt * sizeof(double *)))==NULL) {
  478. sprintf(errstr,"setup_and_init_input_brktable_constants(): 6\n");
  479. return(MEMORY_ERROR);
  480. }
  481. if((dz->brksize = (int *)malloc(brkcnt * sizeof(int)))==NULL) {
  482. sprintf(errstr,"setup_and_init_input_brktable_constants(): 2\n");
  483. return(MEMORY_ERROR);
  484. }
  485. if((dz->firstval = (double *)malloc(brkcnt * sizeof(double)))==NULL) {
  486. sprintf(errstr,"setup_and_init_input_brktable_constants(): 3\n");
  487. return(MEMORY_ERROR);
  488. }
  489. if((dz->lastind = (double *)malloc(brkcnt * sizeof(double)))==NULL) {
  490. sprintf(errstr,"setup_and_init_input_brktable_constants(): 4\n");
  491. return(MEMORY_ERROR);
  492. }
  493. if((dz->lastval = (double *)malloc(brkcnt * sizeof(double)))==NULL) {
  494. sprintf(errstr,"setup_and_init_input_brktable_constants(): 5\n");
  495. return(MEMORY_ERROR);
  496. }
  497. if((dz->brkinit = (int *)malloc(brkcnt * sizeof(int)))==NULL) {
  498. sprintf(errstr,"setup_and_init_input_brktable_constants(): 7\n");
  499. return(MEMORY_ERROR);
  500. }
  501. for(n=0;n<brkcnt;n++) {
  502. dz->brk[n] = NULL;
  503. dz->brkptr[n] = NULL;
  504. dz->brkinit[n] = 0;
  505. dz->brksize[n] = 0;
  506. }
  507. return(FINISHED);
  508. }
  509. /********************** SETUP_PARAMETER_STORAGE_AND_CONSTANTS ********************/
  510. /* RWD mallo changed to calloc; helps debug verison run as release! */
  511. int setup_parameter_storage_and_constants(int storage_cnt,dataptr dz)
  512. {
  513. if((dz->param = (double *)calloc(storage_cnt, sizeof(double)))==NULL) {
  514. sprintf(errstr,"setup_parameter_storage_and_constants(): 1\n");
  515. return(MEMORY_ERROR);
  516. }
  517. if((dz->iparam = (int *)calloc(storage_cnt, sizeof(int) ))==NULL) {
  518. sprintf(errstr,"setup_parameter_storage_and_constants(): 2\n");
  519. return(MEMORY_ERROR);
  520. }
  521. if((dz->is_int = (char *)calloc(storage_cnt, sizeof(char)))==NULL) {
  522. sprintf(errstr,"setup_parameter_storage_and_constants(): 3\n");
  523. return(MEMORY_ERROR);
  524. }
  525. if((dz->no_brk = (char *)calloc(storage_cnt, sizeof(char)))==NULL) {
  526. sprintf(errstr,"setup_parameter_storage_and_constants(): 5\n");
  527. return(MEMORY_ERROR);
  528. }
  529. return(FINISHED);
  530. }
  531. /************** INITIALISE_IS_INT_AND_NO_BRK_CONSTANTS *****************/
  532. int initialise_is_int_and_no_brk_constants(int storage_cnt,dataptr dz)
  533. {
  534. int n;
  535. for(n=0;n<storage_cnt;n++) {
  536. dz->is_int[n] = (char)0;
  537. dz->no_brk[n] = (char)0;
  538. }
  539. return(FINISHED);
  540. }
  541. /***************************** MARK_PARAMETER_TYPES **************************/
  542. int mark_parameter_types(dataptr dz,aplptr ap)
  543. {
  544. int n, m; /* PARAMS */
  545. for(n=0;n<ap->max_param_cnt;n++) {
  546. switch(ap->param_list[n]) {
  547. case('0'): break; /* dz->is_active[n] = 0 is default */
  548. case('i'): dz->is_active[n] = (char)1; dz->is_int[n] = (char)1;dz->no_brk[n] = (char)1; break;
  549. case('I'): dz->is_active[n] = (char)1; dz->is_int[n] = (char)1; break;
  550. case('d'): dz->is_active[n] = (char)1; dz->no_brk[n] = (char)1; break;
  551. case('D'): dz->is_active[n] = (char)1; /* normal case: double val or brkpnt file */ break;
  552. default:
  553. sprintf(errstr,"Programming error: invalid parameter type in mark_parameter_types()\n");
  554. return(PROGRAM_ERROR);
  555. }
  556. } /* OPTIONS */
  557. for(n=0,m=ap->max_param_cnt;n<ap->option_cnt;n++,m++) {
  558. switch(ap->option_list[n]) {
  559. case('i'): dz->is_active[m] = (char)1; dz->is_int[m] = (char)1; dz->no_brk[m] = (char)1; break;
  560. case('I'): dz->is_active[m] = (char)1; dz->is_int[m] = (char)1; break;
  561. case('d'): dz->is_active[m] = (char)1; dz->no_brk[m] = (char)1; break;
  562. case('D'): dz->is_active[m] = (char)1; /* normal case: double val or brkpnt file */ break;
  563. default:
  564. sprintf(errstr,"Programming error: invalid option type in mark_parameter_types()\n");
  565. return(PROGRAM_ERROR);
  566. }
  567. } /* VARIANTS */
  568. for(n=0,m=ap->max_param_cnt + ap->option_cnt;n < ap->variant_param_cnt; n++, m++) {
  569. switch(ap->variant_list[n]) {
  570. case('0'): break;
  571. case('i'): dz->is_active[m] = (char)1; dz->is_int[m] = (char)1; dz->no_brk[m] = (char)1; break;
  572. case('I'): dz->is_active[m] = (char)1; dz->is_int[m] = (char)1; break;
  573. case('d'): dz->is_active[m] = (char)1; dz->no_brk[m] = (char)1; break;
  574. case('D'): dz->is_active[m] = (char)1; /* normal case: double val or brkpnt file */ break;
  575. default:
  576. sprintf(errstr,"Programming error: invalid variant type in mark_parameter_types()\n");
  577. return(PROGRAM_ERROR);
  578. }
  579. } /* INTERNAL */
  580. for(n=0,
  581. m=ap->max_param_cnt + ap->option_cnt + ap->variant_param_cnt; n<ap->internal_param_cnt; n++,m++) {
  582. switch(ap->internal_param_list[n]) {
  583. case('0'): break; /* dummy variables: variables not used: but important for internal paream numbering!! */
  584. case('i'): dz->is_int[m] = (char)1; dz->no_brk[m] = (char)1; break;
  585. case('d'): dz->no_brk[m] = (char)1; break;
  586. default:
  587. sprintf(errstr,"Programming error: invalid internal param type in mark_parameter_types()\n");
  588. return(PROGRAM_ERROR);
  589. }
  590. }
  591. return(FINISHED);
  592. }
  593. /***************************** HANDLE_THE_OUTFILE **************************/
  594. int handle_the_outfile(int *cmdlinecnt,char ***cmdline,int is_launched,dataptr dz)
  595. {
  596. int exit_status;
  597. char *filename = NULL;
  598. filename = (*cmdline)[0];
  599. strcpy(dz->outfilename,filename);
  600. if((exit_status = create_sized_outfile(filename,dz))<0)
  601. return(exit_status);
  602. (*cmdline)++;
  603. (*cmdlinecnt)--;
  604. return(FINISHED);
  605. }
  606. /***************************** ESTABLISH_APPLICATION **************************/
  607. int establish_application(dataptr dz)
  608. {
  609. aplptr ap;
  610. if((dz->application = (aplptr)malloc(sizeof (struct applic)))==NULL) {
  611. sprintf(errstr,"establish_application()\n");
  612. return(MEMORY_ERROR);
  613. }
  614. ap = dz->application;
  615. memset((char *)ap,0,sizeof(struct applic));
  616. return(FINISHED);
  617. }
  618. /************************* INITIALISE_VFLAGS *************************/
  619. int initialise_vflags(dataptr dz)
  620. {
  621. int n;
  622. if((dz->vflag = (char *)malloc(dz->application->vflag_cnt * sizeof(char)))==NULL) {
  623. sprintf(errstr,"INSUFFICIENT MEMORY: vflag store,\n");
  624. return(MEMORY_ERROR);
  625. }
  626. for(n=0;n<dz->application->vflag_cnt;n++)
  627. dz->vflag[n] = FALSE;
  628. return FINISHED;
  629. }
  630. /************************* SETUP_INPUT_PARAM_DEFAULTVALS *************************/
  631. int setup_input_param_defaultval_stores(int tipc,aplptr ap)
  632. {
  633. int n;
  634. if((ap->default_val = (double *)malloc(tipc * sizeof(double)))==NULL) {
  635. sprintf(errstr,"INSUFFICIENT MEMORY for application default values store\n");
  636. return(MEMORY_ERROR);
  637. }
  638. for(n=0;n<tipc;n++)
  639. ap->default_val[n] = 0.0;
  640. return(FINISHED);
  641. }
  642. /***************************** SETUP_AND_INIT_INPUT_PARAM_ACTIVITY **************************/
  643. int setup_and_init_input_param_activity(dataptr dz,int tipc)
  644. {
  645. int n;
  646. if((dz->is_active = (char *)malloc((size_t)tipc))==NULL) {
  647. sprintf(errstr,"setup_and_init_input_param_activity()\n");
  648. return(MEMORY_ERROR);
  649. }
  650. for(n=0;n<tipc;n++)
  651. dz->is_active[n] = (char)0;
  652. return(FINISHED);
  653. }
  654. /************************* SETUP_THE_APPLICATION *******************/
  655. int setup_the_application(dataptr dz)
  656. {
  657. int exit_status;
  658. aplptr ap;
  659. if((exit_status = establish_application(dz))<0) // GLOBAL
  660. return(FAILED);
  661. ap = dz->application;
  662. // SEE parstruct FOR EXPLANATION of next 2 functions
  663. switch(dz->mode) {
  664. case(5): exit_status = set_param_data(ap,SEGMENTLIST,0,0,""); break;
  665. case(4): exit_status = set_param_data(ap,TUNINGLIST,1,1,"i"); break;
  666. case(3): // fall thro
  667. case(0): exit_status = set_param_data(ap,0 ,0,0,""); break;
  668. case(1): exit_status = set_param_data(ap,TUNINGLIST,0,0,""); break;
  669. case(2): exit_status = set_param_data(ap,TUNINGLIST,0,0,""); break;
  670. }
  671. if(exit_status < 0)
  672. return(FAILED);
  673. switch(dz->mode) {
  674. case(5): exit_status = set_vflgs(ap,"mlhiwn",6,"idddid","rb" ,2,0,"00"); break;
  675. case(4): exit_status = set_vflgs(ap,"",0,"","" ,0,0,""); break;
  676. case(3): exit_status = set_vflgs(ap,"mlhseiwn",8,"idddddid","rb" ,2,0,"00"); break;
  677. default: exit_status = set_vflgs(ap,"mlhseiwn",8,"idddddid","rbf",3,0,"000"); break;
  678. }
  679. if(exit_status < 0)
  680. return(FAILED);
  681. // set_legal_infile_structure -->
  682. dz->has_otherfile = FALSE;
  683. // assign_process_logic -->
  684. dz->input_data_type = ANALFILE_ONLY;
  685. if(dz->mode == 3) {
  686. dz->process_type = OTHER_PROCESS;
  687. dz->outfiletype = NO_OUTPUTFILE;
  688. } else if(dz->mode == 5) {
  689. dz->process_type = TO_TEXTFILE;
  690. dz->outfiletype = TEXTFILE_OUT;
  691. } else {
  692. dz->process_type = EQUAL_ANALFILE;
  693. dz->outfiletype = ANALFILE_OUT;
  694. }
  695. return application_init(dz); //GLOBAL
  696. }
  697. /************************* PARSE_INFILE_AND_CHECK_TYPE *******************/
  698. int parse_infile_and_check_type(char **cmdline,dataptr dz)
  699. {
  700. int exit_status;
  701. infileptr infile_info;
  702. if(!sloom) {
  703. if((infile_info = (infileptr)malloc(sizeof(struct filedata)))==NULL) {
  704. sprintf(errstr,"INSUFFICIENT MEMORY for infile structure to test file data.");
  705. return(MEMORY_ERROR);
  706. } else if((exit_status = cdparse(cmdline[0],infile_info))<0) {
  707. sprintf(errstr,"Failed tp parse input file %s\n",cmdline[0]);
  708. return(PROGRAM_ERROR);
  709. } else if(infile_info->filetype != ANALFILE) {
  710. sprintf(errstr,"File %s is not of correct type\n",cmdline[0]);
  711. return(DATA_ERROR);
  712. } else if((exit_status = copy_parse_info_to_main_structure(infile_info,dz))<0) {
  713. sprintf(errstr,"Failed to copy file parsing information\n");
  714. return(PROGRAM_ERROR);
  715. }
  716. free(infile_info);
  717. }
  718. dz->clength = dz->wanted / 2;
  719. dz->chwidth = dz->nyquist/(double)(dz->clength-1);
  720. dz->halfchwidth = dz->chwidth/2.0;
  721. return(FINISHED);
  722. }
  723. /************************* SETUP_THE_PARAM_RANGES_AND_DEFAULTS *******************/
  724. int setup_the_param_ranges_and_defaults(dataptr dz)
  725. {
  726. int exit_status;
  727. aplptr ap = dz->application;
  728. // set_param_ranges()
  729. ap->total_input_param_cnt = (char)(ap->max_param_cnt + ap->option_cnt + ap->variant_param_cnt);
  730. // NB total_input_param_cnt is > 0 !!!s
  731. if((exit_status = setup_input_param_range_stores(ap->total_input_param_cnt,ap))<0)
  732. return(FAILED);
  733. // get_param_ranges()
  734. if(dz->mode == 4) {
  735. ap->lo[ST_CNT] = 1;
  736. ap->hi[ST_CNT] = 128;
  737. ap->default_val[ST_CNT] = 32;
  738. } else {
  739. ap->lo[ST_MATCH] = 1;
  740. ap->hi[ST_MATCH] = 8;
  741. ap->default_val[ST_MATCH] = ST_ACCEPTABLE_MATCH;
  742. ap->lo[ST_LOPCH] = 4;
  743. ap->hi[ST_LOPCH] = 127;
  744. ap->default_val[ST_LOPCH] = 4;
  745. ap->lo[ST_HIPCH] = 4;
  746. ap->hi[ST_HIPCH] = 127;
  747. ap->default_val[ST_HIPCH] = 127;
  748. if (dz->mode == 5) {
  749. ap->lo[ST_INTUN5] = 0;
  750. ap->hi[ST_INTUN5] = 6;
  751. ap->default_val[ST_INTUN5] = 1;
  752. ap->lo[ST_WNDWS5] = 0;
  753. ap->hi[ST_WNDWS5] = dz->wlength;
  754. ap->default_val[ST_WNDWS5] = BLIPLEN;
  755. ap->lo[ST_NOISE5] = 0.0;
  756. ap->hi[ST_NOISE5] = SIGNOIS_MAX;
  757. ap->default_val[ST_NOISE5] = SILENCE_RATIO;
  758. } else {
  759. ap->lo[ST_STIME] = 0;
  760. ap->hi[ST_STIME] = dz->duration;
  761. ap->default_val[ST_STIME] = 0;
  762. ap->lo[ST_ETIME] = 0;
  763. ap->hi[ST_ETIME] = dz->duration;
  764. ap->default_val[ST_ETIME] = dz->duration;
  765. ap->lo[ST_INTUN] = 0;
  766. ap->hi[ST_INTUN] = 6;
  767. ap->default_val[ST_INTUN] = 1;
  768. ap->lo[ST_WNDWS] = 0;
  769. ap->hi[ST_WNDWS] = dz->wlength;
  770. ap->default_val[ST_WNDWS] = BLIPLEN;
  771. ap->lo[ST_NOISE] = 0.0;
  772. ap->hi[ST_NOISE] = SIGNOIS_MAX;
  773. ap->default_val[ST_NOISE] = SILENCE_RATIO;
  774. }
  775. }
  776. dz->maxmode = 6;
  777. if(!sloom)
  778. put_default_vals_in_all_params(dz);
  779. return(FINISHED);
  780. }
  781. /********************************* PARSE_SLOOM_DATA *********************************/
  782. int parse_sloom_data(int argc,char *argv[],char ***cmdline,int *cmdlinecnt,dataptr dz)
  783. {
  784. int exit_status;
  785. int cnt = 1, infilecnt;
  786. int filesize, insams, inbrksize;
  787. double dummy;
  788. int true_cnt = 0;
  789. // aplptr ap;
  790. while(cnt<=PRE_CMDLINE_DATACNT) {
  791. if(cnt > argc) {
  792. sprintf(errstr,"Insufficient data sent from TK\n");
  793. return(DATA_ERROR);
  794. }
  795. switch(cnt) {
  796. case(1):
  797. if(sscanf(argv[cnt],"%d",&dz->process)!=1) {
  798. sprintf(errstr,"Cannot read process no. sent from TK\n");
  799. return(DATA_ERROR);
  800. }
  801. break;
  802. case(2):
  803. if(sscanf(argv[cnt],"%d",&dz->mode)!=1) {
  804. sprintf(errstr,"Cannot read mode no. sent from TK\n");
  805. return(DATA_ERROR);
  806. }
  807. if(dz->mode > 0)
  808. dz->mode--;
  809. //setup_particular_application() =
  810. if((exit_status = setup_the_application(dz))<0)
  811. return(exit_status);
  812. // ap = dz->application;
  813. break;
  814. case(3):
  815. if(sscanf(argv[cnt],"%d",&infilecnt)!=1) {
  816. sprintf(errstr,"Cannot read infilecnt sent from TK\n");
  817. return(DATA_ERROR);
  818. }
  819. if(infilecnt < 1) {
  820. true_cnt = cnt + 1;
  821. cnt = PRE_CMDLINE_DATACNT; /* force exit from loop after assign_file_data_storage */
  822. }
  823. if((exit_status = assign_file_data_storage(infilecnt,dz))<0)
  824. return(exit_status);
  825. break;
  826. case(INPUT_FILETYPE+4):
  827. if(sscanf(argv[cnt],"%d",&dz->infile->filetype)!=1) {
  828. sprintf(errstr,"Cannot read filetype sent from TK (%s)\n",argv[cnt]);
  829. return(DATA_ERROR);
  830. }
  831. break;
  832. case(INPUT_FILESIZE+4):
  833. if(sscanf(argv[cnt],"%d",&filesize)!=1) {
  834. sprintf(errstr,"Cannot read infilesize sent from TK\n");
  835. return(DATA_ERROR);
  836. }
  837. dz->insams[0] = filesize;
  838. break;
  839. case(INPUT_INSAMS+4):
  840. if(sscanf(argv[cnt],"%d",&insams)!=1) {
  841. sprintf(errstr,"Cannot read insams sent from TK\n");
  842. return(DATA_ERROR);
  843. }
  844. dz->insams[0] = insams;
  845. break;
  846. case(INPUT_SRATE+4):
  847. if(sscanf(argv[cnt],"%d",&dz->infile->srate)!=1) {
  848. sprintf(errstr,"Cannot read srate sent from TK\n");
  849. return(DATA_ERROR);
  850. }
  851. break;
  852. case(INPUT_CHANNELS+4):
  853. if(sscanf(argv[cnt],"%d",&dz->infile->channels)!=1) {
  854. sprintf(errstr,"Cannot read channels sent from TK\n");
  855. return(DATA_ERROR);
  856. }
  857. break;
  858. case(INPUT_STYPE+4):
  859. if(sscanf(argv[cnt],"%d",&dz->infile->stype)!=1) {
  860. sprintf(errstr,"Cannot read stype sent from TK\n");
  861. return(DATA_ERROR);
  862. }
  863. break;
  864. case(INPUT_ORIGSTYPE+4):
  865. if(sscanf(argv[cnt],"%d",&dz->infile->origstype)!=1) {
  866. sprintf(errstr,"Cannot read origstype sent from TK\n");
  867. return(DATA_ERROR);
  868. }
  869. break;
  870. case(INPUT_ORIGRATE+4):
  871. if(sscanf(argv[cnt],"%d",&dz->infile->origrate)!=1) {
  872. sprintf(errstr,"Cannot read origrate sent from TK\n");
  873. return(DATA_ERROR);
  874. }
  875. break;
  876. case(INPUT_MLEN+4):
  877. if(sscanf(argv[cnt],"%d",&dz->infile->Mlen)!=1) {
  878. sprintf(errstr,"Cannot read Mlen sent from TK\n");
  879. return(DATA_ERROR);
  880. }
  881. break;
  882. case(INPUT_DFAC+4):
  883. if(sscanf(argv[cnt],"%d",&dz->infile->Dfac)!=1) {
  884. sprintf(errstr,"Cannot read Dfac sent from TK\n");
  885. return(DATA_ERROR);
  886. }
  887. break;
  888. case(INPUT_ORIGCHANS+4):
  889. if(sscanf(argv[cnt],"%d",&dz->infile->origchans)!=1) {
  890. sprintf(errstr,"Cannot read origchans sent from TK\n");
  891. return(DATA_ERROR);
  892. }
  893. break;
  894. case(INPUT_SPECENVCNT+4):
  895. if(sscanf(argv[cnt],"%d",&dz->infile->specenvcnt)!=1) {
  896. sprintf(errstr,"Cannot read specenvcnt sent from TK\n");
  897. return(DATA_ERROR);
  898. }
  899. dz->specenvcnt = dz->infile->specenvcnt;
  900. break;
  901. case(INPUT_WANTED+4):
  902. if(sscanf(argv[cnt],"%d",&dz->wanted)!=1) {
  903. sprintf(errstr,"Cannot read wanted sent from TK\n");
  904. return(DATA_ERROR);
  905. }
  906. break;
  907. case(INPUT_WLENGTH+4):
  908. if(sscanf(argv[cnt],"%d",&dz->wlength)!=1) {
  909. sprintf(errstr,"Cannot read wlength sent from TK\n");
  910. return(DATA_ERROR);
  911. }
  912. break;
  913. case(INPUT_OUT_CHANS+4):
  914. if(sscanf(argv[cnt],"%d",&dz->out_chans)!=1) {
  915. sprintf(errstr,"Cannot read out_chans sent from TK\n");
  916. return(DATA_ERROR);
  917. }
  918. break;
  919. /* RWD these chanegs to samps - tk will have to deal with that! */
  920. case(INPUT_DESCRIPTOR_BYTES+4):
  921. if(sscanf(argv[cnt],"%d",&dz->descriptor_samps)!=1) {
  922. sprintf(errstr,"Cannot read descriptor_samps sent from TK\n");
  923. return(DATA_ERROR);
  924. }
  925. break;
  926. case(INPUT_IS_TRANSPOS+4):
  927. if(sscanf(argv[cnt],"%d",&dz->is_transpos)!=1) {
  928. sprintf(errstr,"Cannot read is_transpos sent from TK\n");
  929. return(DATA_ERROR);
  930. }
  931. break;
  932. case(INPUT_COULD_BE_TRANSPOS+4):
  933. if(sscanf(argv[cnt],"%d",&dz->could_be_transpos)!=1) {
  934. sprintf(errstr,"Cannot read could_be_transpos sent from TK\n");
  935. return(DATA_ERROR);
  936. }
  937. break;
  938. case(INPUT_COULD_BE_PITCH+4):
  939. if(sscanf(argv[cnt],"%d",&dz->could_be_pitch)!=1) {
  940. sprintf(errstr,"Cannot read could_be_pitch sent from TK\n");
  941. return(DATA_ERROR);
  942. }
  943. break;
  944. case(INPUT_DIFFERENT_SRATES+4):
  945. if(sscanf(argv[cnt],"%d",&dz->different_srates)!=1) {
  946. sprintf(errstr,"Cannot read different_srates sent from TK\n");
  947. return(DATA_ERROR);
  948. }
  949. break;
  950. case(INPUT_DUPLICATE_SNDS+4):
  951. if(sscanf(argv[cnt],"%d",&dz->duplicate_snds)!=1) {
  952. sprintf(errstr,"Cannot read duplicate_snds sent from TK\n");
  953. return(DATA_ERROR);
  954. }
  955. break;
  956. case(INPUT_BRKSIZE+4):
  957. if(sscanf(argv[cnt],"%d",&inbrksize)!=1) {
  958. sprintf(errstr,"Cannot read brksize sent from TK\n");
  959. return(DATA_ERROR);
  960. }
  961. if(inbrksize > 0) {
  962. switch(dz->input_data_type) {
  963. case(WORDLIST_ONLY):
  964. break;
  965. case(PITCH_AND_PITCH):
  966. case(PITCH_AND_TRANSPOS):
  967. case(TRANSPOS_AND_TRANSPOS):
  968. dz->tempsize = inbrksize;
  969. break;
  970. case(BRKFILES_ONLY):
  971. case(UNRANGED_BRKFILE_ONLY):
  972. case(DB_BRKFILES_ONLY):
  973. case(ALL_FILES):
  974. case(ANY_NUMBER_OF_ANY_FILES):
  975. if(dz->extrabrkno < 0) {
  976. sprintf(errstr,"Storage location number for brktable not established by CDP.\n");
  977. return(DATA_ERROR);
  978. }
  979. if(dz->brksize == NULL) {
  980. sprintf(errstr,"CDP has not established storage space for input brktable.\n");
  981. return(PROGRAM_ERROR);
  982. }
  983. dz->brksize[dz->extrabrkno] = inbrksize;
  984. break;
  985. default:
  986. sprintf(errstr,"TK sent brktablesize > 0 for input_data_type [%d] not using brktables.\n",
  987. dz->input_data_type);
  988. return(PROGRAM_ERROR);
  989. }
  990. break;
  991. }
  992. break;
  993. case(INPUT_NUMSIZE+4):
  994. if(sscanf(argv[cnt],"%d",&dz->numsize)!=1) {
  995. sprintf(errstr,"Cannot read numsize sent from TK\n");
  996. return(DATA_ERROR);
  997. }
  998. break;
  999. case(INPUT_LINECNT+4):
  1000. if(sscanf(argv[cnt],"%d",&dz->linecnt)!=1) {
  1001. sprintf(errstr,"Cannot read linecnt sent from TK\n");
  1002. return(DATA_ERROR);
  1003. }
  1004. break;
  1005. case(INPUT_ALL_WORDS+4):
  1006. if(sscanf(argv[cnt],"%d",&dz->all_words)!=1) {
  1007. sprintf(errstr,"Cannot read all_words sent from TK\n");
  1008. return(DATA_ERROR);
  1009. }
  1010. break;
  1011. case(INPUT_ARATE+4):
  1012. if(sscanf(argv[cnt],"%f",&dz->infile->arate)!=1) {
  1013. sprintf(errstr,"Cannot read arate sent from TK\n");
  1014. return(DATA_ERROR);
  1015. }
  1016. break;
  1017. case(INPUT_FRAMETIME+4):
  1018. if(sscanf(argv[cnt],"%lf",&dummy)!=1) {
  1019. sprintf(errstr,"Cannot read frametime sent from TK\n");
  1020. return(DATA_ERROR);
  1021. }
  1022. dz->frametime = (float)dummy;
  1023. break;
  1024. case(INPUT_WINDOW_SIZE+4):
  1025. if(sscanf(argv[cnt],"%f",&dz->infile->window_size)!=1) {
  1026. sprintf(errstr,"Cannot read window_size sent from TK\n");
  1027. return(DATA_ERROR);
  1028. }
  1029. break;
  1030. case(INPUT_NYQUIST+4):
  1031. if(sscanf(argv[cnt],"%lf",&dz->nyquist)!=1) {
  1032. sprintf(errstr,"Cannot read nyquist sent from TK\n");
  1033. return(DATA_ERROR);
  1034. }
  1035. break;
  1036. case(INPUT_DURATION+4):
  1037. if(sscanf(argv[cnt],"%lf",&dz->duration)!=1) {
  1038. sprintf(errstr,"Cannot read duration sent from TK\n");
  1039. return(DATA_ERROR);
  1040. }
  1041. break;
  1042. case(INPUT_MINBRK+4):
  1043. if(sscanf(argv[cnt],"%lf",&dz->minbrk)!=1) {
  1044. sprintf(errstr,"Cannot read minbrk sent from TK\n");
  1045. return(DATA_ERROR);
  1046. }
  1047. break;
  1048. case(INPUT_MAXBRK+4):
  1049. if(sscanf(argv[cnt],"%lf",&dz->maxbrk)!=1) {
  1050. sprintf(errstr,"Cannot read maxbrk sent from TK\n");
  1051. return(DATA_ERROR);
  1052. }
  1053. break;
  1054. case(INPUT_MINNUM+4):
  1055. if(sscanf(argv[cnt],"%lf",&dz->minnum)!=1) {
  1056. sprintf(errstr,"Cannot read minnum sent from TK\n");
  1057. return(DATA_ERROR);
  1058. }
  1059. break;
  1060. case(INPUT_MAXNUM+4):
  1061. if(sscanf(argv[cnt],"%lf",&dz->maxnum)!=1) {
  1062. sprintf(errstr,"Cannot read maxnum sent from TK\n");
  1063. return(DATA_ERROR);
  1064. }
  1065. break;
  1066. default:
  1067. sprintf(errstr,"case switch item missing: parse_sloom_data()\n");
  1068. return(PROGRAM_ERROR);
  1069. }
  1070. cnt++;
  1071. }
  1072. if(cnt!=PRE_CMDLINE_DATACNT+1) {
  1073. sprintf(errstr,"Insufficient pre-cmdline params sent from TK\n");
  1074. return(DATA_ERROR);
  1075. }
  1076. if(true_cnt)
  1077. cnt = true_cnt;
  1078. *cmdlinecnt = 0;
  1079. while(cnt < argc) {
  1080. if((exit_status = get_tk_cmdline_word(cmdlinecnt,cmdline,argv[cnt]))<0)
  1081. return(exit_status);
  1082. cnt++;
  1083. }
  1084. return(FINISHED);
  1085. }
  1086. /********************************* GET_TK_CMDLINE_WORD *********************************/
  1087. int get_tk_cmdline_word(int *cmdlinecnt,char ***cmdline,char *q)
  1088. {
  1089. if(*cmdlinecnt==0) {
  1090. if((*cmdline = (char **)malloc(sizeof(char *)))==NULL) {
  1091. sprintf(errstr,"INSUFFICIENT MEMORY for TK cmdline array.\n");
  1092. return(MEMORY_ERROR);
  1093. }
  1094. } else {
  1095. if((*cmdline = (char **)realloc(*cmdline,((*cmdlinecnt)+1) * sizeof(char *)))==NULL) {
  1096. sprintf(errstr,"INSUFFICIENT MEMORY for TK cmdline array.\n");
  1097. return(MEMORY_ERROR);
  1098. }
  1099. }
  1100. if(((*cmdline)[*cmdlinecnt] = (char *)malloc((strlen(q) + 1) * sizeof(char)))==NULL) {
  1101. sprintf(errstr,"INSUFFICIENT MEMORY for TK cmdline item %d.\n",(*cmdlinecnt)+1);
  1102. return(MEMORY_ERROR);
  1103. }
  1104. strcpy((*cmdline)[*cmdlinecnt],q);
  1105. (*cmdlinecnt)++;
  1106. return(FINISHED);
  1107. }
  1108. /****************************** ASSIGN_FILE_DATA_STORAGE *********************************/
  1109. int assign_file_data_storage(int infilecnt,dataptr dz)
  1110. {
  1111. int exit_status;
  1112. int no_sndfile_system_files = FALSE;
  1113. dz->infilecnt = infilecnt;
  1114. if((exit_status = allocate_filespace(dz))<0)
  1115. return(exit_status);
  1116. if(no_sndfile_system_files)
  1117. dz->infilecnt = 0;
  1118. return(FINISHED);
  1119. }
  1120. /*********************** CHECK_THE_PARAM_VALIDITY_AND_CONSISTENCY *********************/
  1121. int check_the_param_validity_and_consistency(dataptr dz)
  1122. {
  1123. int n, m, lolim;
  1124. int warning_given = 0;
  1125. if(dz->mode == 4)
  1126. return FINISHED;
  1127. if(dz->param[ST_LOPCH] >= dz->param[ST_HIPCH]) {
  1128. sprintf(errstr,"Upper and lower pitch limits are not compatible.\n");
  1129. return(DATA_ERROR);
  1130. }
  1131. if(dz->mode != 3 && dz->mode != 5) {
  1132. if(dz->mode == 1) {
  1133. // FOR HARMONIC SET CASE
  1134. for(n = 0;n < dz->itemcnt; n++) {
  1135. if(dz->parray[TUNING_ARRAY][n] < dz->param[ST_LOPCH] || dz->parray[TUNING_ARRAY][n] > dz->param[ST_HIPCH]) {
  1136. if(!warning_given) {
  1137. fprintf(stdout,"WARNING: TUNING PITCH %lf IS OUTSIDE THE SPECIFIED RANGE (%lf to %lf)\n",
  1138. dz->parray[TUNING_ARRAY][n],dz->param[ST_LOPCH],dz->param[ST_HIPCH]);
  1139. fflush(stdout);
  1140. warning_given = 1;
  1141. }
  1142. }
  1143. }
  1144. } else {
  1145. // FOR HARMONIC FIELD AND TEMPERED SCALE CASES : RESTRICT TUNING-PITCHES INSIDE SPECIFIED RANGE
  1146. for(n = 0;n < dz->itemcnt; n++) {
  1147. if(dz->parray[TUNING_ARRAY][n] >= dz->param[ST_LOPCH])
  1148. break;
  1149. }
  1150. lolim = n;
  1151. for(n = lolim;n < dz->itemcnt; n++) {
  1152. if(dz->parray[TUNING_ARRAY][n] > dz->param[ST_HIPCH])
  1153. break;
  1154. }
  1155. dz->itemcnt = n; // COnstrict MIDI search array from top (if ness)
  1156. if(lolim > 0) { // Shuffle array down
  1157. for(n = lolim, m = 0; n < dz->itemcnt; n++,m++)
  1158. dz->parray[TUNING_ARRAY][m] = dz->parray[TUNING_ARRAY][n];
  1159. dz->itemcnt -= lolim; // Constrict MIDI search array from bottom
  1160. }
  1161. }
  1162. }
  1163. if (dz->mode != 5) {
  1164. if(dz->param[ST_STIME] >= dz->param[ST_ETIME]) {
  1165. sprintf(errstr,"Upper and lower searchtime limits are not compatible.\n");
  1166. return(DATA_ERROR);
  1167. }
  1168. dz->iparam[ST_STIME] = (int)(round(dz->param[ST_STIME]/dz->frametime)); // Convert search limits from seconds to windowcount
  1169. dz->iparam[ST_ETIME] = (int)(round(dz->param[ST_ETIME]/dz->frametime));
  1170. }
  1171. if (dz->mode == 5) {
  1172. st_intun = pow(SEMITONE_INTERVAL,fabs(dz->param[ST_INTUN5])); // Convert in-tune semitones to frq ratio
  1173. st_noise = dz->param[ST_NOISE5];
  1174. st_wndws = dz->iparam[ST_WNDWS];
  1175. } else {
  1176. st_intun = pow(SEMITONE_INTERVAL,fabs(dz->param[ST_INTUN])); // Convert in-tune semitones to frq ratio
  1177. st_noise = dz->param[ST_NOISE];
  1178. st_wndws = dz->iparam[ST_WNDWS];
  1179. }
  1180. st_noise /= 20.0; // convert sig-to-nois ratio from dB to gain
  1181. st_noise = pow(10.0,st_noise);
  1182. st_noise = 1.0/st_noise;
  1183. return FINISHED;
  1184. }
  1185. /************************* redundant functions: to ensure libs compile OK *******************/
  1186. int assign_process_logic(dataptr dz)
  1187. {
  1188. return(FINISHED);
  1189. }
  1190. void set_legal_infile_structure(dataptr dz)
  1191. {}
  1192. int set_legal_internalparam_structure(int process,int mode,aplptr ap)
  1193. {
  1194. return(FINISHED);
  1195. }
  1196. int setup_internal_arrays_and_array_pointers(dataptr dz)
  1197. {
  1198. return(FINISHED);
  1199. }
  1200. int establish_bufptrs_and_extra_buffers(dataptr dz)
  1201. {
  1202. return(FINISHED);
  1203. }
  1204. int get_process_no(char *prog_identifier_from_cmdline,dataptr dz)
  1205. {
  1206. return(FINISHED);
  1207. }
  1208. int read_special_data(char *str,dataptr dz)
  1209. {
  1210. return(FINISHED);
  1211. }
  1212. int inner_loop
  1213. (int *peakscore,int *descnt,int *in_start_portion,int *least,int *pitchcnt,int windows_in_buf,dataptr dz)
  1214. {
  1215. return(FINISHED);
  1216. }
  1217. /********************************************************************************************/
  1218. int get_the_process_no(char *prog_identifier_from_cmdline,dataptr dz)
  1219. {
  1220. if (!strcmp(prog_identifier_from_cmdline,"tune")) dz->process = SPECTUNE;
  1221. else {
  1222. fprintf(stderr,"Unknown program identification string '%s'\n",prog_identifier_from_cmdline);
  1223. return(USAGE_ONLY);
  1224. }
  1225. return(FINISHED);
  1226. }
  1227. /******************************** USAGE1 ********************************/
  1228. int usage1(void)
  1229. {
  1230. fprintf(stderr,
  1231. "\nFURTHER OPERATIONS ON ANALYSIS FILES\n\n"
  1232. "USAGE: spectune tune mode infile (outfile) parameters: \n"
  1233. "\n"
  1234. "Type 'spectune tune' for more info.\n");
  1235. return(USAGE_ONLY);
  1236. }
  1237. /******************************** USAGE2 ********************************/
  1238. int usage2(char *str)
  1239. {
  1240. if(!strcmp(str,"tune")) {
  1241. fprintf(stdout,
  1242. "USAGE: spectune tune 1 infile outfile\n"
  1243. "[-mmatch] [-llop] [-hhip] [-stim] [-etim] [-iintune] [-wwins] [-nnois] [-r][-b][-f]\n"
  1244. "OR: spectune tune 2-3 infile outfile tuning\n"
  1245. "[-mmatch] [-llop] [-hhip] [-stim] [-etim] [-iintune] [-wwins] [-nnois] [-r][-b][-f]\n"
  1246. "OR: spectune tune 4 infile outfile\n"
  1247. "[-mmatch] [-llop] [-hhip] [-stim] [-etim] [-iintune] [-wwins] [-nnois] [-r][-b]\n"
  1248. "OR: spectune tune 5 infile outfile tuning peakcnt\n"
  1249. "OR: spectune tune 6 infile outfile segmentation\n"
  1250. "[-mmatch] [-llop] [-hhip] [-iintune] [-wwins] [-nnois] [-r][-b]\n"
  1251. "\n"
  1252. "Find (most prominent) pitch in input file\n"
  1253. "then transpose input file to ....\n"
  1254. "MODE 1: nearest tempered pitch.\n"
  1255. "MODE 2: nearest of pitches listed in \"tuning\" file.\n"
  1256. "MODE 3: nearest pitch, or its octave equivalents, listed in \"tuning\" file.\n"
  1257. "MODE 4: Report the pitch found : no sound output.\n"
  1258. "MODE 5: Tune sound to a given (possibly time-varying) pedal pitch and its harmonics.\n"
  1259. "MODE 6: Report median pitch in all segments indicated.\n"
  1260. "\n"
  1261. "MATCH No of partials lying on harmonic series, to affirm pitch (Default %d).\n"
  1262. "LOP Minimum (MIDI) pitch to accept (default : 4 = c 10Hz).\n"
  1263. "HIP Maximum (MIDI) pitch to accept (default : 127).\n"
  1264. "STIM Time in file where pitch search begins (default : 0.0).\n"
  1265. "ETIM Time in file where pitch search ends (default : end-of-file).\n"
  1266. "INTUNE How closely tuned must harmonics be (in semitones) (Default 1).\n"
  1267. "WINS Minimum no consective pitched windows, to confirm pitch found (Default %d).\n"
  1268. "NOIS Sig-to-noise ratio (dB). (Default %.0lf db).\n"
  1269. " Windows more than \"NOIS\" dB below loudest window are ignored.\n"
  1270. "PEAKCNT How many spectral peaks to tune (1 - 128 max).\n"
  1271. "\n"
  1272. "-r Ignore relative loudness of pitched windows when assessing most prominent pitch.\n"
  1273. "-b Smooth pitch data & eliminate blips, before searching for most prominent pitch.\n"
  1274. "-f Ignore the formant envelope, when transposing.\n"
  1275. "\n"
  1276. "TUNING Textfile list of (possibly fractional) MIDI pitches.\n"
  1277. "\n"
  1278. "SEGMENTATION Times of starts/ends of segments in input sound.\n"
  1279. "\n"
  1280. "Input (and output sound) files are analysis files.\n",ST_ACCEPTABLE_MATCH,BLIPLEN,SILENCE_RATIO);
  1281. } else
  1282. fprintf(stdout,"Unknown option '%s'\n",str);
  1283. return(USAGE_ONLY);
  1284. }
  1285. int usage3(char *str1,char *str2)
  1286. {
  1287. fprintf(stderr,"Insufficient parameters on command line.\n");
  1288. return(USAGE_ONLY);
  1289. }
  1290. /**************************** DO_SPECTUNE ****************************/
  1291. int do_spectune(dataptr dz)
  1292. {
  1293. int exit_status, wc, done, windows_in_buf, median;
  1294. int n,m, medianscore, medianpos, sumcnt, samps_read, pitchcnt = 0, startwin, endwin, j, k, mediancnt, tdiff;
  1295. double *tunings = dz->parray[TUNING_ARRAY], *pitches = dz->parray[FOUND_PITCHES], medianweight, *timings = NULL;
  1296. double *pitchweight = dz->parray[PITCHWEIGHT], *weightedscore = dz->parray[WEIGHTEDSCORE], *windowamp = dz->parray[TOTALAMPS],*medianpitches = NULL;
  1297. int *pitchbin = dz->iparray[0], *pitchscore = dz->iparray[1];
  1298. double pitch, sum, medianpitch, diff, nudiff, transpos, totalamp = 0.0, pitchstep;
  1299. chvptr *partials;
  1300. int st_stime, st_etime;
  1301. if(dz->mode == 5) {
  1302. st_stime = 0;
  1303. st_etime = dz->wlength;
  1304. } else {
  1305. st_stime = dz->iparam[ST_STIME];
  1306. st_etime = dz->iparam[ST_ETIME];
  1307. }
  1308. done = 0;
  1309. if((partials = (chvptr *)malloc(MAXIMI * sizeof(chvptr)))==NULL) {
  1310. sprintf(errstr,"INSUFFICIENT MEMORY for partials array.\n");
  1311. return(MEMORY_ERROR);
  1312. }
  1313. while((samps_read = fgetfbufEx(dz->bigfbuf, dz->buflen,dz->ifd[0],0)) > 0) {
  1314. if(samps_read < 0) {
  1315. sprintf(errstr,"Failed to read data from input file.\n");
  1316. return(SYSTEM_ERROR);
  1317. }
  1318. dz->flbufptr[0] = dz->bigfbuf;
  1319. windows_in_buf = samps_read/dz->wanted;
  1320. for(wc=0; wc<windows_in_buf; wc++, dz->total_windows++) {
  1321. if(dz->total_windows < st_stime) {
  1322. dz->flbufptr[0] += dz->wanted;
  1323. continue;
  1324. }
  1325. if(dz->total_windows > st_etime) {
  1326. done = 1;
  1327. break;
  1328. }
  1329. if((exit_status = get_totalamp(&totalamp,dz->flbufptr[0],dz->wanted))<0)
  1330. return(exit_status);
  1331. dz->parray[TOTALAMPS][pitchcnt] = totalamp;
  1332. if(dz->total_windows==0)
  1333. pitches[pitchcnt++] = 0.0; // First window has no pitch
  1334. else {
  1335. if((exit_status = specget(&pitch,partials,dz))<0)
  1336. return(exit_status);
  1337. pitches[pitchcnt++] = pitch;
  1338. }
  1339. dz->flbufptr[0] += dz->wanted;
  1340. }
  1341. if(done)
  1342. break;
  1343. }
  1344. // CLEAN UP PITCH DATA
  1345. if((exit_status = tidy_up_the_pitch_data(pitches,pitchcnt,dz))<0)
  1346. return exit_status;
  1347. // ASSIGN FOUND PITCHES TO 1/8-TONE BANDS
  1348. for(n=0;n<pitchcnt;n++) {
  1349. if(pitches[n] > 0) {
  1350. if(hztomidi(&pitch,pitches[n]) < 0) {
  1351. pitch = -1.0;
  1352. }
  1353. } else
  1354. pitch = -1.0;
  1355. pitches[n] = pitch;
  1356. }
  1357. if(dz->mode == 5) {
  1358. timings = dz->parray[TIMING_ARRAY];
  1359. if ((medianpitches = (double *)malloc(dz->itemcnt * sizeof(double)))==NULL) {
  1360. sprintf(errstr,"Insufficient memory to store tunings data.\n");
  1361. return(MEMORY_ERROR);
  1362. }
  1363. startwin = 0;
  1364. for(k=1;k<dz->itemcnt;k++) {
  1365. endwin = (int)round(timings[k]/dz->frametime);
  1366. for(n = startwin;n<endwin;n++) {
  1367. // IF pitch is out of range (or marked as no-pitch-found i.e. <= 0.0) set bin to zero
  1368. if(pitches[n] < dz->param[ST_LOPCH] || pitches[n] > dz->param[ST_HIPCH]) {
  1369. pitchbin[n] = 0;
  1370. pitchweight[n] = -1;
  1371. }
  1372. else { // ELSE assign pitch to nearest 8th-tone bin : NB values are stored as an integer count of 1/8th tones
  1373. pitchbin[n] = (int)(round(pitches[n] * 8.0));
  1374. pitchweight[n] = windowamp[n];
  1375. }
  1376. pitchscore[n] = 0; // Flag all bins as not counted
  1377. weightedscore[n] = 0.0;
  1378. }
  1379. if(dz->vflag[0]) {
  1380. // COUNT THE PITCH CLASSES
  1381. for(n=startwin;n<endwin;n++) {
  1382. if(pitchscore[n]) // If pitchbin marked as already counted (non-zero), go to next item
  1383. continue;
  1384. if(pitchbin[n] == 0) {
  1385. pitchscore[n] = -1; // If pitchbin is not pitched (or not in range) mark as already counted
  1386. continue;
  1387. }
  1388. pitchscore[n] = 1; // Start counting
  1389. for(m=n+1;m<endwin;m++) {
  1390. if(pitchscore[m]) // Marked as already counted, go to next item
  1391. continue;
  1392. if(pitchbin[m] == 0) {
  1393. pitchscore[m] = -1; // If pitchbin is not pitched (or not in range) mark as already counted
  1394. continue;
  1395. }
  1396. if(pitchbin[n] == pitchbin[m]) {
  1397. pitchscore[n]++; // Count recurrences of value in bin[n]
  1398. pitchscore[m] = -1; // Flag other occurence as already counted
  1399. }
  1400. }
  1401. }
  1402. // FIND THE MEDIAN PITCHBIN
  1403. medianscore = -1;
  1404. medianpos = -1;
  1405. for(n=startwin;n<endwin;n++) {
  1406. if(pitchscore[n] > medianscore) {
  1407. medianscore = pitchscore[n];
  1408. medianpos = n;
  1409. }
  1410. }
  1411. if(medianpos < 0)
  1412. medianpitches[k-1] = -1;
  1413. else
  1414. medianpitches[k-1] = pitchbin[medianpos];
  1415. } else {
  1416. // WEIGH THE PITCH CLASSES
  1417. for(n=startwin;n<endwin;n++) {
  1418. if(weightedscore[n] > 0.0) // If pitchbin marked as already weighed (non-negative), go to next item
  1419. continue;
  1420. if(pitchbin[n] == 0) {
  1421. weightedscore[n] = -1; // If pitchbin is not pitched (or not in range) mark as not-to-be-weighed
  1422. continue;
  1423. }
  1424. weightedscore[n] = pitchweight[n]; // Start weighing
  1425. for(m=n+1;m<endwin;m++) {
  1426. if(weightedscore[m] > 0.0) // Marked as already weighed, go to next item
  1427. continue;
  1428. if(pitchbin[m] == 0) {
  1429. weightedscore[m] = -1; // If pitchbin is not pitched (or not in range) mark as not-to-be-weighed
  1430. continue;
  1431. }
  1432. if(pitchbin[n] == pitchbin[m]) {
  1433. weightedscore[n] += pitchweight[m]; // Add weight of recurrencing pitch value to bin[n]
  1434. weightedscore[m] = -1; // Flag other occurence as already weighed
  1435. }
  1436. }
  1437. }
  1438. // FIND THE MEDIAN PITCHWEIGHT
  1439. medianweight = -1;
  1440. medianpos = -1;
  1441. for(n=startwin;n<endwin;n++) {
  1442. if(weightedscore[n] > medianweight) {
  1443. medianweight = weightedscore[n];
  1444. medianpos = n;
  1445. }
  1446. }
  1447. }
  1448. if(medianpos < 0)
  1449. median = -1; // No median pitch found
  1450. else
  1451. median = pitchbin[medianpos];
  1452. // AVERAGE ALL PITCHES FALLING IN THE MEDIAN PITCHBIN
  1453. if(median < 0)
  1454. medianpitches[k-1] = -1;
  1455. else {
  1456. sum = 0.0;
  1457. sumcnt = 0;
  1458. for(n=startwin;n<endwin;n++) {
  1459. if(pitchbin[n] == median) {
  1460. sum += pitches[n];
  1461. sumcnt++;
  1462. }
  1463. }
  1464. medianpitches[k-1] = sum/(double)sumcnt;
  1465. }
  1466. startwin = endwin;
  1467. }
  1468. j = 0;
  1469. mediancnt = dz->itemcnt - 1; // 1 less segment than segment boundaries
  1470. for(k = 0; k < mediancnt;k++) {
  1471. if(medianpitches[k] < 0.0)
  1472. j++;
  1473. }
  1474. if(j == mediancnt) {
  1475. sprintf(errstr,"NO MEDIAN PITCHES FOUND.\n");
  1476. return DATA_ERROR;
  1477. }
  1478. if(medianpitches[0] < 0.0) { // If initial pitch null
  1479. k = 1;
  1480. while(k < mediancnt) { // Find first valid pitch
  1481. if(medianpitches[k] >= 0) {
  1482. j = 0; // Copy this to all prior segments
  1483. while(j < k) {
  1484. medianpitches[j] = medianpitches[k];
  1485. j++;
  1486. }
  1487. break;
  1488. }
  1489. k++;
  1490. }
  1491. }
  1492. if(medianpitches[mediancnt - 1] < 0.0) { // If last pitch null
  1493. k = mediancnt - 2;
  1494. while(k >= 0) { // Find last valid pitch
  1495. if(medianpitches[k] >= 0) {
  1496. j = k+1; // Copy this to all later segments
  1497. while(j < mediancnt) {
  1498. medianpitches[j] = medianpitches[k];
  1499. j++;
  1500. }
  1501. break;
  1502. }
  1503. k--;
  1504. }
  1505. }
  1506. for(k = 0; k < mediancnt;k++) {
  1507. if(medianpitches[k] < 0.0) { // Find any internal null pitches, and interp across
  1508. j = k + 1;
  1509. while(medianpitches[j] < 0.0)
  1510. j++;
  1511. pitchstep = medianpitches[j] - medianpitches[k-1]; // P1 x P2 -> P1 + 1/2diff
  1512. tdiff = j - (k-1); // P1 x x P2 -> P1 + 1/3diff
  1513. pitchstep *= 1.0/(double)tdiff; // P1 x x x P2 -> P1 + 1/4diffETC
  1514. medianpitches[k] = medianpitches[k-1] + pitchstep;
  1515. }
  1516. }
  1517. for(k = 0; k < mediancnt;k++)
  1518. fprintf(dz->fp,"%lf\n",medianpitches[k]);
  1519. return FINISHED;
  1520. } else {
  1521. for(n=0;n<pitchcnt;n++) {
  1522. // IF pitch is out of range (or marked as no-pitch-found i.e. <= 0.0) set bin to zero
  1523. if(pitches[n] < dz->param[ST_LOPCH] || pitches[n] > dz->param[ST_HIPCH]) {
  1524. pitchbin[n] = 0;
  1525. pitchweight[n] = -1;
  1526. }
  1527. else { // ELSE assign pitch to nearest 8th-tone bin : NB values are stored as an integer count of 1/8th tones
  1528. pitchbin[n] = (int)(round(pitches[n] * 8.0));
  1529. pitchweight[n] = windowamp[n];
  1530. }
  1531. pitchscore[n] = 0; // Flag all bins as not counted
  1532. weightedscore[n] = 0.0;
  1533. }
  1534. if(dz->vflag[0]) {
  1535. for(n=0;n<pitchcnt;n++) {
  1536. // IF pitch is out of range (or marked as no-pitch-found i.e. <= 0.0) set bin to zero
  1537. if(pitches[n] < dz->param[ST_LOPCH] || pitches[n] > dz->param[ST_HIPCH]) {
  1538. pitchbin[n] = 0;
  1539. pitchweight[n] = -1;
  1540. }
  1541. else { // ELSE assign pitch to nearest 8th-tone bin : NB values are stored as an integer count of 1/8th tones
  1542. pitchbin[n] = (int)(round(pitches[n] * 8.0));
  1543. pitchweight[n] = windowamp[n];
  1544. }
  1545. pitchscore[n] = 0; // Flag all bins as not counted
  1546. weightedscore[n] = 0.0;
  1547. }
  1548. // COUNT THE PITCH CLASSES
  1549. for(n=0;n<pitchcnt;n++) {
  1550. if(pitchscore[n]) // If pitchbin marked as already counted (non-zero), go to next item
  1551. continue;
  1552. if(pitchbin[n] == 0) {
  1553. pitchscore[n] = -1; // If pitchbin is not pitched (or not in range) mark as already counted
  1554. continue;
  1555. }
  1556. pitchscore[n] = 1; // Start counting
  1557. for(m=n+1;m<pitchcnt;m++) {
  1558. if(pitchscore[m]) // Marked as already counted, go to next item
  1559. continue;
  1560. if(pitchbin[m] == 0) {
  1561. pitchscore[m] = -1; // If pitchbin is not pitched (or not in range) mark as already counted
  1562. continue;
  1563. }
  1564. if(pitchbin[n] == pitchbin[m]) {
  1565. pitchscore[n]++; // Count recurrences of value in bin[n]
  1566. pitchscore[m] = -1; // Flag other occurence as already counted
  1567. }
  1568. }
  1569. }
  1570. // FIND THE MEDIAN PITCHBIN
  1571. medianscore = -1;
  1572. medianpos = -1;
  1573. for(n=0;n<pitchcnt;n++) {
  1574. if(pitchscore[n] > medianscore) {
  1575. medianscore = pitchscore[n];
  1576. medianpos = n;
  1577. }
  1578. }
  1579. if(medianpos < 0) {
  1580. sprintf(errstr,"NO MEDIAN PITCH FOUND.\n");
  1581. return(DATA_ERROR);
  1582. }
  1583. median = pitchbin[medianpos];
  1584. } else {
  1585. // WEIGH THE PITCH CLASSES
  1586. for(n=0;n<pitchcnt;n++) {
  1587. // IF pitch is out of range (or marked as no-pitch-found i.e. <= 0.0) set bin to zero
  1588. if(pitches[n] < dz->param[ST_LOPCH] || pitches[n] > dz->param[ST_HIPCH]) {
  1589. pitchweight[n] = -1;
  1590. }
  1591. else { // ELSE assign pitch to nearest 8th-tone bin : NB values are stored as an integer count of 1/8th tones
  1592. pitchbin[n] = (int)(round(pitches[n] * 8.0));
  1593. pitchweight[n] = windowamp[n];
  1594. }
  1595. weightedscore[n] = 0.0; // Reset all weights to zero
  1596. }
  1597. for(n=0;n<pitchcnt;n++) {
  1598. if(weightedscore[n] > 0.0) // If pitchbin marked as already weighed (non-negative), go to next item
  1599. continue;
  1600. if(pitchbin[n] == 0) {
  1601. weightedscore[n] = -1; // If pitchbin is not pitched (or not in range) mark as not-to-be-weighed
  1602. continue;
  1603. }
  1604. weightedscore[n] = pitchweight[n]; // Start weighing
  1605. for(m=n+1;m<pitchcnt;m++) {
  1606. if(weightedscore[m] > 0.0) // Marked as already weighed, go to next item
  1607. continue;
  1608. if(pitchbin[m] == 0) {
  1609. weightedscore[m] = -1; // If pitchbin is not pitched (or not in range) mark as not-to-be-weighed
  1610. continue;
  1611. }
  1612. if(pitchbin[n] == pitchbin[m]) {
  1613. weightedscore[n] += pitchweight[m]; // Add weight of recurrencing pitch value to bin[n]
  1614. weightedscore[m] = -1; // Flag other occurence as already weighed
  1615. }
  1616. }
  1617. }
  1618. // FIND THE MEDIAN PITCHWEIGHT
  1619. medianweight = -1;
  1620. medianpos = -1;
  1621. for(n=0;n<pitchcnt;n++) {
  1622. if(weightedscore[n] > medianweight) {
  1623. medianweight = weightedscore[n];
  1624. medianpos = n;
  1625. }
  1626. }
  1627. if(medianpos < 0) {
  1628. sprintf(errstr,"NO MEDIAN PITCH FOUND.\n");
  1629. return(DATA_ERROR);
  1630. }
  1631. median = pitchbin[medianpos];
  1632. }
  1633. // AVERAGE ALL PITCHES FALLING IN THE MEDIAN PITCHBIN
  1634. sum = 0.0;
  1635. sumcnt = 0;
  1636. for(n=0;n<pitchcnt;n++) {
  1637. if(pitchbin[n] == median) {
  1638. sum += pitches[n];
  1639. sumcnt++;
  1640. }
  1641. }
  1642. medianpitch = sum/(double)sumcnt;
  1643. }
  1644. if(dz->mode == 3) {
  1645. fprintf(stdout,"INFO: %lf\n",medianpitch);
  1646. fflush(stdout);
  1647. return FINISHED;
  1648. }
  1649. // FIND CLOSEST PITCH IN TUNING SET
  1650. diff = fabs(medianpitch - tunings[0]);
  1651. for(n = 1;n < dz->itemcnt;n++) {
  1652. nudiff = fabs(medianpitch - tunings[n]);
  1653. if(nudiff > diff)
  1654. break;
  1655. diff = nudiff;
  1656. }
  1657. n--;
  1658. transpos = miditohz(tunings[n])/miditohz(medianpitch);
  1659. fprintf(stdout,"INFO: Transposing from MIDI %.2lf to %lf : by ratio %lf\n",medianpitch,tunings[n],transpos);
  1660. fflush(stdout);
  1661. // TRANSPOSE THE DATA
  1662. if(sndseekEx(dz->ifd[0],0,0)<0) {
  1663. sprintf(errstr,"SEEK FAILED BEFORE TRANSPOSITION STARTED.\n");
  1664. return(DATA_ERROR);
  1665. }
  1666. dz->total_windows = 0;
  1667. while((samps_read = fgetfbufEx(dz->bigfbuf, dz->buflen,dz->ifd[0],0)) > 0) {
  1668. if(samps_read < 0) {
  1669. sprintf(errstr,"Failed to re-read data from input file, to do transposition.\n");
  1670. return(SYSTEM_ERROR);
  1671. }
  1672. dz->flbufptr[0] = dz->bigfbuf;
  1673. windows_in_buf = samps_read/dz->wanted;
  1674. for(wc=0; wc<windows_in_buf; wc++, dz->total_windows++) {
  1675. if(dz->total_windows==0) // First window has no pitch
  1676. special_operation_on_window_zero(dz);
  1677. else {
  1678. if(dz->vflag[2]) {
  1679. if((exit_status = spectrnsp(transpos,dz))<0)
  1680. return(exit_status);
  1681. } else {
  1682. if((exit_status = spectrnsf(transpos,dz))<0)
  1683. return(exit_status);
  1684. }
  1685. }
  1686. if((exit_status = write_samps(dz->flbufptr[0],dz->wanted,dz))<0)
  1687. return(exit_status);
  1688. dz->flbufptr[0] += dz->wanted;
  1689. }
  1690. }
  1691. return FINISHED;
  1692. }
  1693. /************************ GET_THE_MODE_NO *********************/
  1694. int get_the_mode_no(char *str, dataptr dz)
  1695. {
  1696. if(sscanf(str,"%d",&dz->mode)!=1) {
  1697. fprintf(stderr,"Cannot read mode of program.\n");
  1698. return(USAGE_ONLY);
  1699. }
  1700. if(dz->mode <= 0 || dz->mode > dz->maxmode) {
  1701. fprintf(stderr,"Program mode value [%d] is out of range [1 - %d].\n",dz->mode,dz->maxmode);
  1702. return(USAGE_ONLY);
  1703. }
  1704. dz->mode--; /* CHANGE TO INTERNAL REPRESENTATION OF MODE NO */
  1705. return(FINISHED);
  1706. }
  1707. /************************ HANDLE_TUNING_DATA *********************/
  1708. int handle_tuning_data(int *cmdlinecnt,char ***cmdline,dataptr dz)
  1709. {
  1710. int oct;
  1711. aplptr ap = dz->application;
  1712. int n, m, total;
  1713. char temp[200], *q, *filename = (*cmdline)[0];
  1714. double *p, tempval, midival;
  1715. if(!sloom) {
  1716. if(*cmdlinecnt <= 0) {
  1717. sprintf(errstr,"Insufficient parameters on command line.\n");
  1718. return(USAGE_ONLY);
  1719. }
  1720. }
  1721. ap->data_in_file_only = TRUE;
  1722. ap->special_range = TRUE;
  1723. ap->min_special = 4;
  1724. ap->max_special = 127;
  1725. if((dz->fp = fopen(filename,"r"))==NULL) {
  1726. sprintf(errstr,"Cannot open datafile %s\n",filename);
  1727. return(DATA_ERROR);
  1728. }
  1729. n = 0;
  1730. while(fgets(temp,200,dz->fp)!=NULL) {
  1731. q = temp;
  1732. if(is_an_empty_line_or_a_comment(q))
  1733. continue;
  1734. n++;
  1735. }
  1736. if(n==0) {
  1737. sprintf(errstr,"No data in file %s\n",filename);
  1738. return(DATA_ERROR);
  1739. }
  1740. dz->itemcnt = n;
  1741. if(dz->mode == 2)
  1742. dz->itemcnt *= 12; // Only need 11 octaves (12 for safety)
  1743. if ((dz->parray[TUNING_ARRAY] = (double *)malloc(dz->itemcnt * sizeof(double)))==NULL) {
  1744. sprintf(errstr,"Insufficient memory to store tuning data\n");
  1745. return(MEMORY_ERROR);
  1746. }
  1747. p = dz->parray[TUNING_ARRAY];
  1748. if(fseek(dz->fp,0,0)<0) {
  1749. sprintf(errstr,"fseek() failed in handle_pitchdata()\n");
  1750. return(SYSTEM_ERROR);
  1751. }
  1752. n = 0;
  1753. while(fgets(temp,200,dz->fp)!=NULL) {
  1754. q = temp;
  1755. if(is_an_empty_line_or_a_comment(temp))
  1756. continue;
  1757. if(n >= dz->itemcnt) {
  1758. sprintf(errstr,"Accounting problem reading pitchdata\n");
  1759. return(PROGRAM_ERROR);
  1760. }
  1761. while(get_float_from_within_string(&q,p)) {
  1762. if(*p <= ap->min_special || *p >= ap->max_special) {
  1763. sprintf(errstr,"Pitch out of range (%lf - %lf) : line %d: file %s\n",ap->min_special,ap->max_special,n+1,filename);
  1764. return(DATA_ERROR);
  1765. }
  1766. p++;
  1767. }
  1768. n++;
  1769. }
  1770. if(fclose(dz->fp)<0) {
  1771. fprintf(stdout,"WARNING: Failed to close input textfile %s.\n",filename);
  1772. fflush(stdout);
  1773. }
  1774. total = n;
  1775. if(dz->mode == 2) {
  1776. // FOR HARMONIC-FIELD CASE : TRANSPOSE ALL PITCHES INTO LOWEST OCTAVE
  1777. for(n = 0; n < total; n++) {
  1778. while(dz->parray[TUNING_ARRAY][n] > ap->min_special)
  1779. dz->parray[TUNING_ARRAY][n] -= 12;
  1780. dz->parray[TUNING_ARRAY][n] += 12;
  1781. }
  1782. }
  1783. // SORT PITCHES INTO ASCENDING ORDER
  1784. for(n = 0; n < total-1; n++) {
  1785. for(m = n; m < total; m++) {
  1786. if(dz->parray[TUNING_ARRAY][m] < dz->parray[TUNING_ARRAY][n]) {
  1787. tempval = dz->parray[TUNING_ARRAY][m];
  1788. dz->parray[TUNING_ARRAY][m] = dz->parray[TUNING_ARRAY][n];
  1789. dz->parray[TUNING_ARRAY][n] = tempval;
  1790. }
  1791. }
  1792. }
  1793. if(dz->mode == 2) {
  1794. // FOR HARMONIC-FIELD CASE : FILL THE MIDI SPACE
  1795. m = total;
  1796. oct = 1;
  1797. midival = 0.0;
  1798. while(midival <= 127.0) {
  1799. for(n = 0; n < total; n++) {
  1800. midival = dz->parray[TUNING_ARRAY][n] + (12.0 * oct);
  1801. if(midival > 127.0)
  1802. break;
  1803. if(m >= dz->itemcnt) {
  1804. sprintf(errstr,"Tuning array overran when expanded.\n");
  1805. return(DATA_ERROR);
  1806. }
  1807. dz->parray[TUNING_ARRAY][m++] = midival;
  1808. }
  1809. oct++;
  1810. }
  1811. dz->itemcnt = m; // Remember size of tuning-space
  1812. }
  1813. (*cmdline)++;
  1814. (*cmdlinecnt)--;
  1815. return(FINISHED);
  1816. }
  1817. /************************ FILL_TUNING_ARRAY *********************/
  1818. int fill_tuning_array(dataptr dz)
  1819. {
  1820. int n, m;
  1821. dz->itemcnt = 124; // Only need 11 octaves
  1822. if ((dz->parray[TUNING_ARRAY] = (double *)malloc(dz->itemcnt * sizeof(double)))==NULL) {
  1823. sprintf(errstr,"Insufficient memory to store tuning data\n");
  1824. return(MEMORY_ERROR);
  1825. }
  1826. for(n = 0,m = 4;m <= 127;n++,m++)
  1827. dz->parray[TUNING_ARRAY][n] = (double)m;
  1828. dz->itemcnt = n; // Remember size of tuning-space
  1829. return(FINISHED);
  1830. }
  1831. /****************************** SPECGET *******************************
  1832. *
  1833. * (1) Ignore partials below low limit of pitch.
  1834. * (2) If this channel data is louder than any existing piece of data in ring.
  1835. * (Ring data is ordered loudness-wise)...
  1836. * (3) If this freq is too close to an existing frequency..
  1837. * (4) and if it is louder than that existing frequency data..
  1838. * (5) Substitute in in the ring.
  1839. * (6) Otherwise, (its a new frq) insert it into the ring.
  1840. */
  1841. int specget(double *pitch,chvptr *partials,dataptr dz)
  1842. {
  1843. int exit_status = FINISHED;
  1844. int vc;
  1845. chvptr here, there;
  1846. float minamp;
  1847. /* double loudest_partial_frq, nextloudest_partial_frq, lo_loud_partial, hi_loud_partial, sum; */
  1848. if((exit_status = initialise_ring_vals(MAXIMI,-1.0,dz))<0)
  1849. return(exit_status);
  1850. if((exit_status = rectify_frqs(dz->flbufptr[0],dz))<0)
  1851. return(exit_status);
  1852. // sum = 0.0;
  1853. for(vc=0;vc<dz->wanted;vc+=2) {
  1854. // sum += dz->flbufptr[0][AMPP];
  1855. here = dz->ringhead;
  1856. if(dz->flbufptr[0][FREQ] > SPEC_MINFRQ) { /* 1 */
  1857. do {
  1858. if(dz->flbufptr[0][AMPP] > here->val) { /* 2 */
  1859. if((exit_status = close_to_frq_already_in_ring(&there,(double)dz->flbufptr[0][FREQ],dz))<0)
  1860. return(exit_status);
  1861. if(exit_status==TRUE) {
  1862. if(dz->flbufptr[0][AMPP] > there->val) { /* 4 */
  1863. if((exit_status = substitute_in_ring(vc,here,there,dz))<0) /* 5 */
  1864. return(exit_status);
  1865. }
  1866. } else { /* 6 */
  1867. if((exit_status = insert_in_ring(vc,here,dz))<0)
  1868. return(exit_status);
  1869. }
  1870. break;
  1871. }
  1872. } while((here = here->next)!=dz->ringhead);
  1873. }
  1874. }
  1875. // loudest_partial_frq = dz->flbufptr[0][dz->ringhead->loc + 1];
  1876. // nextloudest_partial_frq = dz->flbufptr[0][dz->ringhead->next->loc + 1];
  1877. /*
  1878. if(loudest_partial_frq < nextloudest_partial_frq) {
  1879. lo_loud_partial = loudest_partial_frq;
  1880. hi_loud_partial = nextloudest_partial_frq;
  1881. } else {
  1882. lo_loud_partial = nextloudest_partial_frq;
  1883. hi_loud_partial = loudest_partial_frq;
  1884. }
  1885. */
  1886. if((exit_status = put_ring_frqs_in_ascending_order(&partials,&minamp,dz))<0)
  1887. return(exit_status);
  1888. if((exit_status = alternative_find_pitch(pitch,partials,dz))<0)
  1889. return(exit_status);
  1890. // find_pitch(pitch,partials,lo_loud_partial,hi_loud_partial,minamp,dz);
  1891. return exit_status;
  1892. }
  1893. /**************************** CLOSE_TO_FRQ_ALREADY_IN_RING *******************************/
  1894. int close_to_frq_already_in_ring(chvptr *there,double frq1,dataptr dz)
  1895. {
  1896. #define EIGHT_OVER_SEVEN (1.142857143)
  1897. double frq2, frqratio;
  1898. *there = dz->ringhead;
  1899. do {
  1900. if((*there)->val > 0.0) {
  1901. frq2 = dz->flbufptr[0][(*there)->loc + 1];
  1902. if(frq1 > frq2)
  1903. frqratio = frq1/frq2;
  1904. else
  1905. frqratio = frq2/frq1;
  1906. if(frqratio < EIGHT_OVER_SEVEN)
  1907. return(TRUE);
  1908. }
  1909. } while((*there = (*there)->next) != dz->ringhead);
  1910. return(FALSE);
  1911. }
  1912. /******************************* SUBSITUTE_IN_RING **********************/
  1913. int substitute_in_ring(int vc,chvptr here,chvptr there,dataptr dz)
  1914. {
  1915. chvptr spare, previous;
  1916. if(here!=there) {
  1917. if(there==dz->ringhead) {
  1918. sprintf(errstr,"IMPOSSIBLE! in substitute_in_ring()\n");
  1919. return(PROGRAM_ERROR);
  1920. }
  1921. spare = there;
  1922. there->next->last = there->last; /* SPLICE REDUNDANT STRUCT FROM RING */
  1923. there->last->next = there->next;
  1924. previous = here->last;
  1925. previous->next = spare; /* SPLICE ITS ADDRESS-SPACE BACK INTO RING */
  1926. spare->last = previous; /* IMMEDIATELY BEFORE HERE */
  1927. here->last = spare;
  1928. spare->next = here;
  1929. if(here==dz->ringhead) /* IF HERE IS RINGHEAD, MOVE RINGHEAD */
  1930. dz->ringhead = spare;
  1931. here = spare; /* POINT TO INSERT LOCATION */
  1932. }
  1933. here->val = dz->flbufptr[0][AMPP]; /* IF here==there */
  1934. here->loc = vc; /* THIS WRITES OVER VAL IN EXISTING RING LOCATION */
  1935. return(FINISHED);
  1936. }
  1937. /*************************** INSERT_IN_RING ***************************/
  1938. int insert_in_ring(int vc, chvptr here, dataptr dz)
  1939. {
  1940. chvptr previous, newend, spare;
  1941. if(here==dz->ringhead) {
  1942. dz->ringhead = dz->ringhead->last;
  1943. spare = dz->ringhead;
  1944. } else {
  1945. if(here==dz->ringhead->last)
  1946. spare = here;
  1947. else {
  1948. spare = dz->ringhead->last;
  1949. newend = dz->ringhead->last->last; /* cut ENDADR (spare) out of ring */
  1950. dz->ringhead->last = newend;
  1951. newend->next = dz->ringhead;
  1952. previous = here->last;
  1953. here->last = spare; /* reuse spare address at new loc by */
  1954. spare->next = here; /* inserting it back into ring before HERE */
  1955. previous->next = spare;
  1956. spare->last = previous;
  1957. }
  1958. }
  1959. spare->val = dz->flbufptr[0][vc]; /* Store new val in spare ring location */
  1960. spare->loc = vc;
  1961. return(FINISHED);
  1962. }
  1963. /************************** PUT_RING_FRQS_IN_ASCENDING_ORDER **********************/
  1964. int put_ring_frqs_in_ascending_order(chvptr **partials,float *minamp,dataptr dz)
  1965. {
  1966. int k;
  1967. chvptr start, ggot, here = dz->ringhead;
  1968. float minpitch;
  1969. *minamp = (float)MAXFLOAT;
  1970. for(k=0;k<MAXIMI;k++) {
  1971. if((*minamp = min(dz->flbufptr[0][here->loc],*minamp))>=(float)MAXFLOAT) {
  1972. sprintf(errstr,"Problem with amplitude out of range: put_ring_frqs_in_ascending_order()\n");
  1973. return(PROGRAM_ERROR);
  1974. }
  1975. (here->loc)++; /* CHANGE RING TO POINT TO FRQS, not AMPS */
  1976. here->val = dz->flbufptr[0][here->loc];
  1977. here = here->next;
  1978. }
  1979. here = dz->ringhead;
  1980. minpitch = dz->flbufptr[0][here->loc];
  1981. for(k=1;k<MAXIMI;k++) {
  1982. start = ggot = here;
  1983. while((here = here->next)!=start) { /* Find lowest frq */
  1984. if(dz->flbufptr[0][here->loc] < minpitch) {
  1985. minpitch = dz->flbufptr[0][here->loc];
  1986. ggot = here;
  1987. }
  1988. }
  1989. (*partials)[k-1] = ggot; /* Save its address */
  1990. here = ggot->next; /* Move to next ring site */
  1991. minpitch = dz->flbufptr[0][here->loc]; /* Preset minfrq to val there */
  1992. ggot->last->next = here; /* Unlink ringsite ggot */
  1993. here->last = ggot->last;
  1994. }
  1995. (*partials)[k-1] = here; /* Remaining ringsite is maximum */
  1996. here = dz->ringhead = (*partials)[0]; /* Reconstruct ring */
  1997. for(k=1;k<MAXIMI;k++) {
  1998. here->next = (*partials)[k];
  1999. (*partials)[k]->last = here;
  2000. here = here->next;
  2001. }
  2002. here->next = dz->ringhead; /* Close up ring */
  2003. dz->ringhead->last = here;
  2004. return(FINISHED);
  2005. }
  2006. /****************************** FIND_PITCH **************************/
  2007. #define MAXIMUM_PARTIAL (64)
  2008. //
  2009. //void find_pitch(double *pitch,chvptr *partials,double lo_loud_partial,double hi_loud_partial,float minamp,dataptr dz)
  2010. //{
  2011. // static int firsttime = 1;
  2012. // int n, m, mm, k, kk, maximi_less_one = MAXIMUM_PARTIAL - 1, endd = 0;
  2013. // double whole_number_ratio, comparison_frq, thisfrq, thisamp, pich_pich = -1.0;
  2014. // for(n=1;n<maximi_less_one;n++) {
  2015. // for(m=n+1;m<MAXIMUM_PARTIAL;m++) { /* NOV 7 */
  2016. // whole_number_ratio = (double)m/(double)n;
  2017. // comparison_frq = lo_loud_partial * whole_number_ratio;
  2018. // if(equivalent_pitches(comparison_frq,hi_loud_partial,dz))
  2019. // endd = (MAXIMUM_PARTIAL/m) * n; /* explanation at foot of file */
  2020. // else if(comparison_frq > hi_loud_partial)
  2021. // break;
  2022. //
  2023. // for(k=n;k<=endd;k+=n) {
  2024. // pich_pich = lo_loud_partial/(double)k;
  2025. // if(pich_pich>dz->nyquist/MAXIMI)
  2026. // continue;
  2027. // if(pich_pich<SPEC_MINFRQ)
  2028. // break;
  2029. // if(is_peak_at(pich_pich,0,minamp,dz)){
  2030. // if(enough_partials_are_harmonics(partials,pich_pich,dz)) {
  2031. // for(mm=0;mm<MAXIMI;mm++) {
  2032. // kk = partials[mm]->loc;
  2033. // if((thisfrq = dz->flbufptr[0][kk]) < pich_pich)
  2034. // continue;
  2035. // if(is_a_harmonic(thisfrq,pich_pich,dz)) { /* for this algo, lowest partial must be within pitchrange specified */
  2036. // if(thisfrq > dz->nyquist/MAXIMI)
  2037. // return;
  2038. // else
  2039. // break;
  2040. // }
  2041. // }
  2042. // for(mm=0;mm<MAXIMI;mm++) {
  2043. // kk = partials[mm]->loc;
  2044. // if((thisfrq = dz->flbufptr[0][kk]) < pich_pich)
  2045. // continue;
  2046. // if(is_a_harmonic(thisfrq,pich_pich,dz)) {
  2047. // thisamp = dz->flbufptr[0][kk-1];
  2048. // }
  2049. // }
  2050. //
  2051. // }
  2052. // }
  2053. // }
  2054. // }
  2055. // }
  2056. // if(pich_pich < miditohz(dz->param[ST_LOPCH]) || pich_pich > miditohz(dz->param[ST_HIPCH]))
  2057. // pich_pich = 0.0;
  2058. // if(pich_pich > 0) {
  2059. // if(hztomidi(pitch,pich_pich) < 0) {
  2060. // *pitch = -1.0;
  2061. // } else
  2062. // *pitch = pich_pich;
  2063. // } else
  2064. // *pitch = -1.0;
  2065. //}
  2066. //
  2067. /**************************** EQUIVALENT_PITCHES *************************/
  2068. int equivalent_pitches(double frq1, double frq2, dataptr dz)
  2069. {
  2070. double ratio;
  2071. int iratio;
  2072. double intvl;
  2073. ratio = frq1/frq2;
  2074. iratio = round(ratio);
  2075. if(iratio!=1)
  2076. return(FALSE);
  2077. if(ratio > iratio)
  2078. intvl = ratio/(double)iratio;
  2079. else
  2080. intvl = (double)iratio/ratio;
  2081. if(intvl > st_intun)
  2082. return FALSE;
  2083. return TRUE;
  2084. }
  2085. /*************************** IS_PEAK_AT ***************************/
  2086. //
  2087. //#define PEAK_LIMIT (.05)
  2088. //
  2089. //int is_peak_at(double frq,int window_offset,float minamp,dataptr dz)
  2090. //{
  2091. // float *thisbuf;
  2092. // int cc, vc, searchtop, searchbot;
  2093. // if(window_offset) { /* BAKTRAK ALONG BIGBUF, IF NESS */
  2094. // thisbuf = dz->flbufptr[0] - (window_offset * dz->wanted);
  2095. // if((int)thisbuf < 0 || thisbuf < dz->bigfbuf || thisbuf >= dz->flbufptr[1])
  2096. // return(FALSE);
  2097. // } else
  2098. // thisbuf = dz->flbufptr[0];
  2099. // cc = (int)((frq + dz->halfchwidth)/dz->chwidth); /* TRUNCATE */
  2100. // searchtop = min(dz->clength,cc + CHANSCAN + 1);
  2101. // searchbot = max(0,cc - CHANSCAN);
  2102. // for(cc = searchbot ,vc = searchbot*2; cc < searchtop; cc++, vc += 2) {
  2103. // if(!equivalent_pitches((double)thisbuf[vc+1],frq,dz)) {
  2104. // continue;
  2105. // }
  2106. // if(thisbuf[vc] < minamp * PEAK_LIMIT)
  2107. // continue;
  2108. // if(local_peak(cc,frq,thisbuf,dz))
  2109. // return TRUE;
  2110. // }
  2111. // return FALSE;
  2112. //}
  2113. //
  2114. /**************************** ENOUGH_PARTIALS_ARE_HARMONICS *************************/
  2115. //
  2116. //int enough_partials_are_harmonics(chvptr *partials,double pich_pich,dataptr dz)
  2117. //{
  2118. // int n, good_match = 0;
  2119. // double thisfrq;
  2120. // for(n=0;n<MAXIMI;n++) {
  2121. // if((thisfrq = dz->flbufptr[0][partials[n]->loc]) < pich_pich)
  2122. // continue;
  2123. // if(is_a_harmonic(thisfrq,pich_pich,dz)){
  2124. // if(++good_match >= dz->iparam[ST_MATCH])
  2125. // return TRUE;
  2126. // }
  2127. // }
  2128. // return FALSE;
  2129. //}
  2130. //
  2131. /**************************** IS_A_HARMONIC *************************/
  2132. //
  2133. //int is_a_harmonic(double frq1,double frq2,dataptr dz)
  2134. //{
  2135. // double ratio = frq1/frq2;
  2136. // int iratio = round(ratio);
  2137. // double intvl;
  2138. //
  2139. // ratio = frq1/frq2;
  2140. // iratio = round(ratio);
  2141. //
  2142. // if(ratio > iratio)
  2143. // intvl = ratio/(double)iratio;
  2144. // else
  2145. // intvl = (double)iratio/ratio;
  2146. // if(intvl > dz->param[ST_INTUN])
  2147. // return(FALSE);
  2148. // return(TRUE);
  2149. //}
  2150. //
  2151. /***************************** LOCAL_PEAK **************************/
  2152. //
  2153. //int local_peak(int thiscc,double frq, float *thisbuf, dataptr dz)
  2154. //{
  2155. // int thisvc = thiscc * 2;
  2156. // int cc, vc, searchtop, searchbot;
  2157. // double frqtop = frq * SEMITONE_INTERVAL;
  2158. // double frqbot = frq / SEMITONE_INTERVAL;
  2159. // searchtop = (int)((frqtop + dz->halfchwidth)/dz->chwidth); /* TRUNCATE */
  2160. // searchtop = min(dz->clength,searchtop + PEAKSCAN + 1);
  2161. // searchbot = (int)((frqbot + dz->halfchwidth)/dz->chwidth); /* TRUNCATE */
  2162. // searchbot = max(0,searchbot - PEAKSCAN);
  2163. // for(cc = searchbot ,vc = searchbot*2; cc < searchtop; cc++, vc += 2) {
  2164. // if(thisbuf[thisvc] < thisbuf[vc])
  2165. // return(FALSE);
  2166. // }
  2167. // return(TRUE);
  2168. //}
  2169. //
  2170. /********************************** SPECTRNSF **********************************
  2171. *
  2172. * transpose spectrum, but retain original spectral envelope.
  2173. */
  2174. int spectrnsf(double transpos,dataptr dz)
  2175. {
  2176. int exit_status;
  2177. double pre_totalamp, post_totalamp;
  2178. int cc, vc;
  2179. rectify_window(dz->flbufptr[0],dz);
  2180. if((exit_status = extract_specenv(0,0,dz))<0)
  2181. return(exit_status);
  2182. if((exit_status = get_totalamp(&pre_totalamp,dz->flbufptr[0],dz->wanted))<0)
  2183. return(exit_status);
  2184. for(cc = 0, vc = 0; cc < dz->clength; cc++, vc += 2) {
  2185. if((exit_status = tranpose_within_formant_envelope(transpos,vc,dz))<0)
  2186. return(exit_status);
  2187. }
  2188. if((exit_status = reposition_partials_in_appropriate_channels(transpos,dz))<0)
  2189. return(exit_status);
  2190. if((exit_status = get_totalamp(&post_totalamp,dz->flbufptr[0],dz->wanted))<0)
  2191. return(exit_status);
  2192. return normalise(pre_totalamp,post_totalamp,dz);
  2193. }
  2194. /********************************** SPECTRNSP **********************************
  2195. *
  2196. * transpose spectrum, (spectral envelope also moves).
  2197. */
  2198. int spectrnsp(double transpos,dataptr dz)
  2199. {
  2200. int exit_status;
  2201. double pre_totalamp, post_totalamp;
  2202. int cc, vc;
  2203. rectify_window(dz->flbufptr[0],dz);
  2204. if((exit_status = get_totalamp(&pre_totalamp,dz->flbufptr[0],dz->wanted))<0)
  2205. return(exit_status);
  2206. for(cc = 0, vc = 0; cc < dz->clength; cc++, vc += 2)
  2207. dz->flbufptr[0][FREQ] = (float)(dz->flbufptr[0][FREQ]*transpos);
  2208. if((exit_status = reposition_partials_in_appropriate_channels(transpos,dz))<0)
  2209. return(exit_status);
  2210. if((exit_status = get_totalamp(&post_totalamp,dz->flbufptr[0],dz->wanted))<0)
  2211. return(exit_status);
  2212. return normalise(pre_totalamp,post_totalamp,dz);
  2213. }
  2214. /************************** TRANPOSE_WITHIN_FORMANT_ENVELOPE *****************************/
  2215. int tranpose_within_formant_envelope(double transpos,int vc,dataptr dz)
  2216. {
  2217. int exit_status;
  2218. double thisspecamp, newspecamp, thisamp, formantamp_ratio;
  2219. if((exit_status = getspecenvamp(&thisspecamp,(double)dz->flbufptr[0][FREQ],0,dz))<0)
  2220. return(exit_status);
  2221. dz->flbufptr[0][FREQ] = (float)(fabs(dz->flbufptr[0][FREQ])*transpos);
  2222. if(dz->flbufptr[0][FREQ] < dz->nyquist) {
  2223. if(thisspecamp < VERY_TINY_VAL)
  2224. dz->flbufptr[0][AMPP] = 0.0f;
  2225. else {
  2226. if((exit_status = getspecenvamp(&newspecamp,(double)dz->flbufptr[0][FREQ],0,dz))<0)
  2227. return(exit_status);
  2228. if(newspecamp < VERY_TINY_VAL)
  2229. dz->flbufptr[0][AMPP] = 0.0f;
  2230. else {
  2231. formantamp_ratio = newspecamp/thisspecamp;
  2232. if((thisamp = dz->flbufptr[0][AMPP] * formantamp_ratio) < VERY_TINY_VAL)
  2233. dz->flbufptr[0][AMPP] = 0.0f;
  2234. else
  2235. dz->flbufptr[0][AMPP] = (float)thisamp;
  2236. }
  2237. }
  2238. }
  2239. return(FINISHED);
  2240. }
  2241. /************************ REPOSITION_PARTIALS_IN_APPROPRIATE_CHANNELS *************************
  2242. *
  2243. * (1) At each pass, preset store-buffer channel amps to zero.
  2244. * (2) Move frq data into appropriate channels, carrying the
  2245. * amplitude information along with them.
  2246. * Work down spectrum for upward transposition, and
  2247. * (3) up spectrum for downward transposition,
  2248. * so that we do not overwrite transposed data before we move it.
  2249. * (4) Put new frqs back into src buff.
  2250. */
  2251. int reposition_partials_in_appropriate_channels(double transpos,dataptr dz)
  2252. {
  2253. int exit_status;
  2254. int truecc,truevc;
  2255. int cc, vc;
  2256. for(vc = 0; vc < dz->wanted; vc+=2) /* 1 */
  2257. dz->windowbuf[0][vc] = 0.0f;
  2258. if(transpos > 1.0f) { /* 2 */
  2259. for(cc=dz->clength-1,vc = dz->wanted-2; cc>=0; cc--, vc-=2) {
  2260. if(dz->flbufptr[0][FREQ] < dz->nyquist && dz->flbufptr[0][AMPP] > 0.0f) {
  2261. if((exit_status = get_channel_corresponding_to_frq(&truecc,(double)dz->flbufptr[0][FREQ],dz))<0)
  2262. return(exit_status);
  2263. truevc = truecc * 2;
  2264. if((exit_status = move_data_into_appropriate_channel(vc,truevc,dz->flbufptr[0][AMPP],dz->flbufptr[0][FREQ],dz))<0)
  2265. return(exit_status);
  2266. /* upward transpos, chandata tends to thin */
  2267. } /* case(TRUE) tries for fuller spectrum */
  2268. }
  2269. for(vc = 0; vc < dz->wanted; vc++)
  2270. dz->flbufptr[0][vc] = dz->windowbuf[0][vc];
  2271. } else if(transpos < 1.0f){ /* 3 */
  2272. for(cc=0,vc = 0; cc < dz->clength; cc++, vc+=2) {
  2273. if(dz->flbufptr[0][FREQ] < dz->nyquist && dz->flbufptr[0][FREQ]>0.0) {
  2274. if((exit_status = get_channel_corresponding_to_frq(&truecc,(double)dz->flbufptr[0][FREQ],dz))<0)
  2275. return(exit_status);
  2276. truevc = truecc * 2;
  2277. if((exit_status = move_data_into_appropriate_channel(vc,truevc,dz->flbufptr[0][AMPP],dz->flbufptr[0][FREQ],dz))<0)
  2278. return(exit_status);
  2279. }
  2280. }
  2281. for(vc = 0; vc < dz->wanted; vc++)
  2282. dz->flbufptr[0][vc] = dz->windowbuf[0][vc]; /* 4 */
  2283. }
  2284. return(FINISHED);
  2285. }
  2286. /***************************** TIDY_UP_PITCH_DATA ***********************/
  2287. int tidy_up_the_pitch_data(double *pitches,int pitchcnt,dataptr dz)
  2288. {
  2289. int exit_status;
  2290. if(dz->vflag[1]) {
  2291. if((exit_status = anti_noise_smoothing(pitchcnt,pitches,dz->frametime))<0)
  2292. return(exit_status);
  2293. }
  2294. if((exit_status = mark_zeros_in_pitchdata(pitches,pitchcnt,dz))<0)
  2295. return(exit_status);
  2296. if(dz->vflag[1]) {
  2297. if((exit_status = eliminate_blips_in_pitch_data(pitches,pitchcnt,dz))<0)
  2298. return(exit_status);
  2299. }
  2300. return pitch_found(pitches,pitchcnt);
  2301. }
  2302. /********************** ANTI_NOISE_SMOOTHING *********************/
  2303. /*RWD used in conditional test, so better as a real var:*/
  2304. static const int MIN_SMOOTH_SET = 3;
  2305. #define MAX_GLISRATE (16.0) /* Assumptions: pitch can't move faster than 16 octaves per sec: MAX_GLISRATE */
  2306. /* Possible movement from window-to-window = MAX_GLISRATE * dz->frametime */
  2307. int anti_noise_smoothing(int wlength,double *pitches,float frametime)
  2308. {
  2309. char *smooth;
  2310. double max_pglide;
  2311. int n;
  2312. if(wlength < MIN_SMOOTH_SET + 1)
  2313. return(FINISHED);
  2314. max_pglide = pow(2.0,MAX_GLISRATE * frametime);
  2315. if((smooth = (char *)malloc((size_t)wlength))==NULL) {
  2316. sprintf(errstr,"INSUFFICIENT MEMORY for smoothing array.\n");
  2317. return(MEMORY_ERROR);
  2318. }
  2319. for(n=1;n<wlength-1;n++)
  2320. smooth[n] = (char)is_smooth_from_both_sides(n,max_pglide,pitches);
  2321. smooth[0] = (char)is_initialpitch_smooth(smooth,max_pglide,pitches);
  2322. smooth[wlength-1] = (char)is_finalpitch_smooth(smooth,max_pglide,wlength,pitches);
  2323. for(n=MIN_SMOOTH_SET-1;n<wlength;n++) {
  2324. if(!smooth[n])
  2325. smooth[n] = (char)is_smooth_from_before(n,smooth,max_pglide,pitches);
  2326. }
  2327. for(n=0;n<=wlength-MIN_SMOOTH_SET;n++) {
  2328. if(!smooth[n])
  2329. smooth[n] = (char)is_smooth_from_after(n,smooth,max_pglide,pitches);
  2330. }
  2331. test_glitch_sets(smooth,max_pglide,wlength,pitches);
  2332. remove_unsmooth_pitches(smooth,wlength,pitches);
  2333. free(smooth);
  2334. return(FINISHED);
  2335. }
  2336. /********************** IS_SMOOTH_FROM_BOTH_SIDES *********************
  2337. *
  2338. * verify a pitch if it has continuity with the pitches on either side.
  2339. */
  2340. int is_smooth_from_both_sides(int n,double max_pglide,double *pitches)
  2341. {
  2342. double thispitch, pitch_before, pitch_after;
  2343. double pre_interval, post_interval;
  2344. if((thispitch = pitches[n]) < FLTERR)
  2345. return FALSE;
  2346. if((pitch_before = pitches[n-1]) < FLTERR)
  2347. return FALSE;
  2348. if((pitch_after = pitches[n+1]) < FLTERR)
  2349. return FALSE;
  2350. pre_interval = pitch_before/thispitch;
  2351. if(pre_interval < 1.0)
  2352. pre_interval = 1.0/pre_interval;
  2353. post_interval = pitch_after/thispitch;
  2354. if(post_interval < 1.0)
  2355. post_interval = 1.0/post_interval;
  2356. if(pre_interval > max_pglide
  2357. || post_interval > max_pglide)
  2358. return FALSE;
  2359. return TRUE;
  2360. }
  2361. /********************** IS_INITIALPITCH_SMOOTH *********************
  2362. *
  2363. * verify first pitch if it has continuity with an ensuing verified pitch.
  2364. */
  2365. int is_initialpitch_smooth(char *smooth,double max_pglide,double *pitches)
  2366. {
  2367. int n;
  2368. double thispitch, post_interval;
  2369. if((thispitch = pitches[0]) < FLTERR)
  2370. return FALSE;
  2371. for(n=1;n < MIN_SMOOTH_SET;n++) {
  2372. if(smooth[n]) {
  2373. post_interval = pitches[n]/pitches[0];
  2374. if(post_interval < 1.0)
  2375. post_interval = 1.0/post_interval;
  2376. if(post_interval <= pow(max_pglide,(double)n))
  2377. return TRUE;
  2378. }
  2379. }
  2380. return(FALSE);
  2381. }
  2382. /********************** IS_FINALPITCH_SMOOTH *********************
  2383. *
  2384. * verify final pitch if it has continuity with a preceding verified pitch.
  2385. */
  2386. int is_finalpitch_smooth(char *smooth,double max_pglide,int wlength,double *pitches)
  2387. {
  2388. double pre_interval, thispitch;
  2389. int n;
  2390. int last = wlength - 1;
  2391. if((thispitch = pitches[last]) < FLTERR)
  2392. return FALSE;
  2393. for(n=1;n < MIN_SMOOTH_SET;n++) {
  2394. if(smooth[last-n]) {
  2395. pre_interval = pitches[last-n]/pitches[last];
  2396. if(pre_interval < 1.0)
  2397. pre_interval = 1.0/pre_interval;
  2398. if(pre_interval <= pow(max_pglide,(double)n))
  2399. return TRUE;
  2400. }
  2401. }
  2402. return(FALSE);
  2403. }
  2404. /********************** IS_SMOOTH_FROM_BEFORE *********************
  2405. *
  2406. * verify a pitch which has continuity with a preceding set of verified pitches.
  2407. */
  2408. int is_smooth_from_before(int n,char *smooth,double max_pglide,double *pitches)
  2409. {
  2410. double thispitch, pitch_before, pre_interval;
  2411. int m;
  2412. if((thispitch = pitches[n]) < FLTERR)
  2413. return FALSE;
  2414. for(m=1;m<MIN_SMOOTH_SET;m++) { /* If there are (MIN_SMOOTH_SET-1) smooth pitches before */
  2415. if(!smooth[n-m])
  2416. return(FALSE);
  2417. }
  2418. pitch_before = pitches[n-1]; /* Test the interval with the previous pitch */
  2419. pre_interval = pitch_before/thispitch;
  2420. if(pre_interval < 1.0)
  2421. pre_interval = 1.0/pre_interval;
  2422. if(pre_interval > max_pglide)
  2423. return FALSE; /* And if it's acceptably smooth */
  2424. return TRUE; /* mark this pitch as smooth also */
  2425. }
  2426. /********************** IS_SMOOTH_FROM_AFTER *********************
  2427. *
  2428. * verify a pitch which has continuity with a following set of verified pitches.
  2429. */
  2430. int is_smooth_from_after(int n,char *smooth,double max_pglide,double *pitches)
  2431. {
  2432. double thispitch, pitch_after, post_interval;
  2433. int m;
  2434. if((thispitch = pitches[n]) < FLTERR)
  2435. return FALSE;
  2436. for(m=1;m<MIN_SMOOTH_SET;m++) { /* If there are (MIN_SMOOTH_SET-1) smooth pitches after */
  2437. if(!smooth[n+m])
  2438. return(FALSE);
  2439. }
  2440. pitch_after = pitches[n+1]; /* Test the interval with the next pitch */
  2441. post_interval = pitch_after/thispitch;
  2442. if(post_interval < 1.0)
  2443. post_interval = 1.0/post_interval;
  2444. if(post_interval > max_pglide)
  2445. return FALSE; /* And if it's acceptably smooth */
  2446. return TRUE; /* mark this pitch as smooth also */
  2447. }
  2448. /********************** TEST_GLITCH_SETS *********************
  2449. *
  2450. * This function looks for any sets of values that appear to be glitches
  2451. * amongst the real pitch data.
  2452. * It is possible some items are REAL pitch data isolated BETWEEN short glitches.
  2453. * This function checks for these cases.
  2454. */
  2455. int test_glitch_sets(char *smooth,double max_pglide,int wlength,double *pitches)
  2456. {
  2457. int exit_status;
  2458. int gotglitch = FALSE;
  2459. int n, gltchend, gltchstart = 0;
  2460. for(n=0;n<wlength;n++) {
  2461. if(gotglitch) { /* if inside a glitch */
  2462. if(smooth[n]) { /* if reached its end, mark the end, then process the glitch */
  2463. gltchend = n;
  2464. if((exit_status = test_glitch_forwards(gltchstart,gltchend,smooth,max_pglide,pitches))<0)
  2465. return(exit_status);
  2466. if((exit_status = test_glitch_backwards(gltchstart,gltchend,smooth,max_pglide,wlength,pitches))<0)
  2467. return(exit_status);
  2468. gotglitch = 0;
  2469. }
  2470. } else { /* look for a glitch and mark its start */
  2471. if(!smooth[n]) {
  2472. gotglitch = 1;
  2473. gltchstart = n;
  2474. }
  2475. }
  2476. }
  2477. if(gotglitch) { /* if inside a glitch at end of data, process glitch */
  2478. gltchend = n;
  2479. test_glitch_forwards(gltchstart,gltchend,smooth,max_pglide,pitches);
  2480. }
  2481. return(FINISHED);
  2482. }
  2483. /********************* REMOVE_UNSMOOTH_PITCHES ***********************
  2484. *
  2485. * delete all pitches which have no verified continuity with surrounding pitches.
  2486. */
  2487. void remove_unsmooth_pitches(char *smooth,int wlength,double *pitches)
  2488. {
  2489. int n;
  2490. for(n=0;n<wlength;n++) {
  2491. if(!smooth[n])
  2492. pitches[n] = (float)NOT_PITCH;
  2493. }
  2494. }
  2495. /********************** TEST_GLITCH_FORWARDS *********************
  2496. *
  2497. * searching from start of glitch, look for isolated true pitches
  2498. * amongst glitch data.
  2499. */
  2500. #define LAST_SMOOTH_NOT_SET (-1)
  2501. int test_glitch_forwards(int gltchstart,int gltchend,char *smooth,double max_pglide,double *pitches)
  2502. {
  2503. int n, glcnt;
  2504. int last_smooth, previous;
  2505. double pre_interval;
  2506. if((previous = gltchstart - 1) < 0)
  2507. return FINISHED;
  2508. if(pitches[previous] < FLTERR) {
  2509. sprintf(errstr,"Error in previous smoothing logic: test_glitch_forwards()\n");
  2510. return(PROGRAM_ERROR);
  2511. }
  2512. last_smooth = previous;
  2513. n = gltchstart+1; /* setup params for local search of glitch */
  2514. glcnt = 1;
  2515. while(n < gltchend) { /* look through the glitch */
  2516. if(pitches[n] > FLTERR) { /* if glitch location holds a true pitch */
  2517. pre_interval = pitches[n]/pitches[previous];
  2518. if(pre_interval < 1.0)
  2519. pre_interval = 1.0/pre_interval; /* compare against previous verified pitch */
  2520. if(pre_interval <= pow(max_pglide,(double)(n-previous))) {
  2521. smooth[n] = TRUE; /* if comparable: mark this pitch as verified */
  2522. last_smooth = n;
  2523. }
  2524. }
  2525. n++; /* Once more than a max-glitch-set has been scanned */
  2526. /* or the end of the entire glitch is reached */
  2527. if(++glcnt >= MIN_SMOOTH_SET || n >= gltchend) {
  2528. if(last_smooth == previous)
  2529. break; /* If no new verifiable pitch found, give up */
  2530. previous = last_smooth;
  2531. n = last_smooth + 1; /* Otherwise start a new local search from newly verified pitch */
  2532. glcnt = 1;
  2533. }
  2534. }
  2535. return(FINISHED);
  2536. }
  2537. /********************** TEST_GLITCH_BACKWARDS *********************
  2538. *
  2539. * searching from end of glitch, look for isolated true pitches
  2540. * amongst glitch data.
  2541. */
  2542. int test_glitch_backwards(int gltchstart,int gltchend,char *smooth,double max_pglide,int wlength,double *pitches)
  2543. {
  2544. int n, glcnt, next, next_smooth;
  2545. double post_interval;
  2546. if((next = gltchend) >= wlength)
  2547. return FINISHED;
  2548. if(pitches[next] < FLTERR) {
  2549. sprintf(errstr,"Error in previous smoothing logic: test_glitch_backwards()\n");
  2550. return(PROGRAM_ERROR);
  2551. }
  2552. next_smooth = next;
  2553. n = gltchend-2; /* setup params for local search of glitch */
  2554. glcnt = 1;
  2555. while(n >= gltchstart) { /* look through the glitch */
  2556. if(pitches[n] > FLTERR) { /* if glitch location holds a true pitch */
  2557. post_interval = pitches[n]/pitches[next];
  2558. if(post_interval < 1.0)
  2559. post_interval = 1.0/post_interval; /* compare against previous verified pitch */
  2560. if(post_interval <= pow(max_pglide,(double)(next - n))) {
  2561. smooth[n] = TRUE; /* if comparable: mark this pitch as verified */
  2562. next_smooth = n;
  2563. }
  2564. }
  2565. n--; /* Once more than a max-glitch-set has been scanned */
  2566. /* or the start of the entire glitch is reached */
  2567. if(++glcnt >= MIN_SMOOTH_SET || n < gltchstart) {
  2568. if(next_smooth == next)
  2569. break; /* If no new verifiable pitch found, give up */
  2570. next = next_smooth;
  2571. n = next_smooth - 1;
  2572. glcnt = 1; /* Otherwise start a new local search */
  2573. }
  2574. }
  2575. return(FINISHED);
  2576. }
  2577. /**************************** PITCH_FOUND ****************************/
  2578. int pitch_found(double *pitches,int pitchcnt)
  2579. {
  2580. int n;
  2581. for(n=0;n<pitchcnt;n++) {
  2582. if(pitches[n] > NOT_PITCH)
  2583. return(FINISHED);
  2584. }
  2585. sprintf(errstr,"No valid pitch found.\n");
  2586. return(GOAL_FAILED);
  2587. }
  2588. /********************************** MARK_ZEROS_IN_PITCHDATA ************************
  2589. *
  2590. * Disregard data on windows which are SILENCE_RATIO below maximum level.
  2591. */
  2592. int mark_zeros_in_pitchdata(double *pitches,int pitchcnt,dataptr dz)
  2593. {
  2594. int n;
  2595. double maxlevel = 0.0, minlevel;
  2596. for(n=0;n<pitchcnt;n++) {
  2597. if(dz->parray[TOTALAMPS][n] > maxlevel)
  2598. maxlevel = dz->parray[TOTALAMPS][n];
  2599. }
  2600. minlevel = maxlevel * st_noise;
  2601. for(n=0;n<pitchcnt;n++) {
  2602. if(dz->parray[TOTALAMPS][n] < minlevel)
  2603. pitches[n] = (float)NOT_SOUND;
  2604. }
  2605. return(FINISHED);
  2606. }
  2607. /************************** ELIMINATE_BLIPS_IN_PITCH_DATA ****************************
  2608. *
  2609. * (1) Eliminate any group of 'dz->param[PICH_VALID]' pitched windows, bracketed by
  2610. * unpitched windows, as unreliable data.
  2611. */
  2612. int eliminate_blips_in_pitch_data(double *pitches,int pitchcnt,dataptr dz)
  2613. {
  2614. int n, m, k, wlength_less_bliplen;
  2615. int OK = 1;
  2616. if(st_wndws<=0)
  2617. return(FINISHED);
  2618. wlength_less_bliplen = pitchcnt - st_wndws;
  2619. for(n=1;n<wlength_less_bliplen;n++) {
  2620. if(pitches[n] > 0.0) {
  2621. if(pitches[n-1] < 0.0) {
  2622. for(k = 1; k <= st_wndws; k++) {
  2623. if(pitches[n+k] < 0.0) {
  2624. for(m=0;m<k;m++)
  2625. pitches[n+m] = (float)NOT_PITCH;
  2626. n += k;
  2627. continue;
  2628. }
  2629. }
  2630. }
  2631. }
  2632. }
  2633. n = wlength_less_bliplen;
  2634. if((pitches[n] > 0.0) && (pitches[n-1] < 0.0)) {
  2635. /* UNREACHABLE at level4 ??? */
  2636. for(k = 1; k < st_wndws; k++) {
  2637. if(pitches[n+k] < 0.0)
  2638. OK = 0;
  2639. break;
  2640. }
  2641. }
  2642. if(!OK) {
  2643. for(n=wlength_less_bliplen;n<pitchcnt;n++)
  2644. pitches[n] = (float)NOT_PITCH;
  2645. }
  2646. return(FINISHED);
  2647. }
  2648. /****************************** ALTERNATIVE_FIND_PITCH **************************/
  2649. #define MAXIMUM_ROOT_DIVISION (2)
  2650. int alternative_find_pitch(double *pitch,chvptr *partials,dataptr dz)
  2651. {
  2652. int n, m, kk, mx = MAXIMI * MAXIMUM_ROOT_DIVISION, *matches, match, matchcnt = 0, maxcnt;
  2653. double whole_number_ratio, comparison_frq, thisfrq, pich_pich = -1.0, *posspich;
  2654. chvptr thispartial, thatpartial;
  2655. if ((posspich = (double *)malloc(mx * sizeof(double)))==NULL) {
  2656. sprintf(errstr,"Insufficient memory to store possible pitches.\n");
  2657. return(MEMORY_ERROR);
  2658. }
  2659. if ((matches = (int *)malloc(mx * sizeof(int)))==NULL) {
  2660. sprintf(errstr,"Insufficient memory to store tuning matches.\n");
  2661. return(MEMORY_ERROR);
  2662. }
  2663. for(m=1;m<MAXIMUM_ROOT_DIVISION;m++) {
  2664. whole_number_ratio = 1.0/(double)m; // Consider each partial as a root OR 2 * root
  2665. thispartial = dz->ringhead;
  2666. do { // For every partial (thispartial)
  2667. match = 0; // Use it (or its divisor) as the comparison frq
  2668. thisfrq = thispartial->val * whole_number_ratio;
  2669. thatpartial = dz->ringhead; // For every partial (thatpartial)
  2670. do {
  2671. kk = 1;
  2672. comparison_frq = thisfrq * kk; // Consider all harmonics of thispartial
  2673. while(comparison_frq < thatpartial->val + thisfrq) { // until we exceed the freq of thatpartial
  2674. if(equivalent_pitches(comparison_frq,thatpartial->val,dz))
  2675. match++; // If thatpartial is a harmonic of thispartial, Count the match
  2676. kk++;
  2677. comparison_frq = thisfrq * kk;
  2678. }
  2679. thatpartial = thatpartial->next;
  2680. } while(thatpartial != dz->ringhead);
  2681. if(match >= dz->iparam[ST_MATCH]) { // If sufficient matches found
  2682. posspich[matchcnt] = thisfrq; // Store fundamental pitch
  2683. matches[matchcnt] = match; // And store count of harmonics-matches
  2684. matchcnt++;
  2685. }
  2686. thispartial = thispartial->next;
  2687. } while(thispartial != dz->ringhead);
  2688. }
  2689. pich_pich = 0.0; // Default : no pitch
  2690. if(matchcnt) { // If possible pitches found
  2691. maxcnt = 0; // Find the highest number of harmonics-matches
  2692. for(n=0;n<matchcnt;n++) {
  2693. if(matches[n] > maxcnt)
  2694. maxcnt = matches[n];
  2695. } // If more than one most-matched-pitch, take the highest frequency
  2696. for(n=0;n<matchcnt;n++) {
  2697. if((matches[n] == maxcnt) && (posspich[n] > pich_pich))
  2698. pich_pich = posspich[n];
  2699. }
  2700. }
  2701. if(pich_pich < miditohz(dz->param[ST_LOPCH]) || pich_pich > miditohz(dz->param[ST_HIPCH]))
  2702. pich_pich = 0.0;
  2703. if(pich_pich <= 0)
  2704. *pitch = -1.0;
  2705. else
  2706. *pitch = pich_pich;
  2707. return FINISHED;
  2708. }
  2709. /************************** READ_FORMANTBAND_DATA_AND_SETUP_FORMANTS *********************/
  2710. int setup_formants(dataptr dz)
  2711. {
  2712. int exit_status;
  2713. int /* max_fbands = 0,*/ arraycnt;
  2714. aplptr ap = dz->application;
  2715. if((exit_status = establish_formant_band_ranges(dz->infile->channels,ap))<0)
  2716. return(exit_status);
  2717. dz->specenv_type = PICHWISE_FORMANTS;
  2718. if(dz->specenv_type==PICHWISE_FORMANTS && ap->no_pitchwise_formants) {
  2719. sprintf(errstr,"-p flag can't be used: Too few analysis data channels.\n");
  2720. return(DATA_ERROR);
  2721. }
  2722. dz->formant_bands = 4;
  2723. // max_fbands = ap->max_pichwise_fbands;
  2724. if((exit_status = initialise_specenv(&arraycnt,dz))<0)
  2725. return(exit_status);
  2726. if((exit_status = set_specenv_frqs(arraycnt,dz))<0)
  2727. return(exit_status);
  2728. dz->descriptor_samps = dz->infile->specenvcnt * DESCRIPTOR_DATA_BLOKS;
  2729. return(FINISHED);
  2730. }
  2731. /************************ SET_SPECENV_FRQS ************************
  2732. *
  2733. * FREQWISE BANDS = number of channels for each specenv point
  2734. * PICHWISE BANDS = number of points per octave
  2735. */
  2736. int set_specenv_frqs(int arraycnt,dataptr dz)
  2737. {
  2738. int exit_status;
  2739. double bandbot;
  2740. double *interval;
  2741. int m, n, k = 0, cc;
  2742. if((exit_status = setup_octaveband_steps(&interval,dz))<0)
  2743. return(exit_status);
  2744. if((exit_status = setup_low_octave_bands(arraycnt,dz))<0)
  2745. return(exit_status);
  2746. k = TOP_OF_LOW_OCTAVE_BANDS;
  2747. cc = CHAN_ABOVE_LOW_OCTAVES;
  2748. while(cc <= dz->clength) {
  2749. m = 0;
  2750. if((bandbot = dz->chwidth * (double)cc) >= dz->nyquist)
  2751. break;
  2752. for(n=0;n<dz->formant_bands;n++) {
  2753. if(k >= arraycnt) {
  2754. sprintf(errstr,"Formant array too small: set_specenv_frqs()\n");
  2755. return(PROGRAM_ERROR);
  2756. }
  2757. dz->specenvfrq[k] = (float)(bandbot * interval[m++]);
  2758. dz->specenvpch[k] = (float)log10(dz->specenvfrq[k]);
  2759. dz->specenvtop[k++] = (float)(bandbot * interval[m++]);
  2760. }
  2761. cc *= 2; /* 8-16: 16-32: 32-64 etc as 8vas, then split into bands */
  2762. }
  2763. dz->specenvfrq[k] = (float)dz->nyquist;
  2764. dz->specenvpch[k] = (float)log10(dz->nyquist);
  2765. dz->specenvtop[k] = (float)dz->nyquist;
  2766. dz->specenvamp[k] = (float)0.0;
  2767. k++;
  2768. dz->infile->specenvcnt = k;
  2769. return(FINISHED);
  2770. }
  2771. /************************* SETUP_OCTAVEBAND_STEPS ************************/
  2772. int setup_octaveband_steps(double **interval,dataptr dz)
  2773. {
  2774. double octave_step;
  2775. int n = 1, m = 0, halfbands_per_octave = dz->formant_bands * 2;
  2776. if((*interval = (double *)malloc(halfbands_per_octave * sizeof(double)))==NULL) {
  2777. sprintf(errstr,"INSUFFICIENT MEMORY establishing interval array for formants.\n");
  2778. return(MEMORY_ERROR);
  2779. }
  2780. while(n < halfbands_per_octave) {
  2781. octave_step = (double)n++/(double)halfbands_per_octave;
  2782. (*interval)[m++] = pow(2.0,octave_step);
  2783. }
  2784. (*interval)[m] = 2.0;
  2785. return(FINISHED);
  2786. }
  2787. /************************ SETUP_LOW_OCTAVE_BANDS ***********************
  2788. *
  2789. * Lowest PVOC channels span larger freq steps and therefore we must
  2790. * group them in octave bands, rather than in anything smaller.
  2791. */
  2792. int setup_low_octave_bands(int arraycnt,dataptr dz)
  2793. {
  2794. int n;
  2795. if(arraycnt < LOW_OCTAVE_BANDS) {
  2796. sprintf(errstr,"Insufficient array space for low_octave_bands\n");
  2797. return(PROGRAM_ERROR);
  2798. }
  2799. for(n=0;n<LOW_OCTAVE_BANDS;n++) {
  2800. switch(n) {
  2801. case(0):
  2802. dz->specenvfrq[0] = (float)1.0; /* frq whose log is 0 */
  2803. dz->specenvpch[0] = (float)0.0;
  2804. dz->specenvtop[0] = (float)dz->chwidth; /* 8VA wide bands */
  2805. break;
  2806. case(1):
  2807. dz->specenvfrq[1] = (float)(dz->chwidth * 1.5); /* Centre Chs 1-2 */
  2808. dz->specenvpch[1] = (float)log10(dz->specenvfrq[1]);
  2809. dz->specenvtop[1] = (float)(dz->chwidth * 2.0);
  2810. break;
  2811. case(2):
  2812. dz->specenvfrq[2] = (float)(dz->chwidth * 3.0); /* Centre Chs 2-4 */
  2813. dz->specenvpch[2] = (float)log10(dz->specenvfrq[2]);
  2814. dz->specenvtop[2] = (float)(dz->chwidth * 4.0);
  2815. break;
  2816. case(3):
  2817. dz->specenvfrq[3] = (float)(dz->chwidth * 6.0); /* Centre Chs 4-8 */
  2818. dz->specenvpch[3] = (float)log10(dz->specenvfrq[3]);
  2819. dz->specenvtop[3] = (float)(dz->chwidth * 8.0);
  2820. break;
  2821. default:
  2822. sprintf(errstr,"Insufficient low octave band setups in setup_low_octave_bands()\n");
  2823. return(PROGRAM_ERROR);
  2824. }
  2825. }
  2826. return(FINISHED);
  2827. }
  2828. /***************** SPECIAL_OPERATION_ON_WINDOW_ZERO ************/
  2829. int special_operation_on_window_zero(dataptr dz)
  2830. {
  2831. int vc;
  2832. for(vc = 0; vc < dz->wanted; vc += 2)
  2833. dz->windowbuf[0][FREQ] = dz->flbufptr[0][FREQ];
  2834. return(TRUE);
  2835. }
  2836. /**************************** DO_SPECPEDAL ****************************/
  2837. int do_specpedal(dataptr dz)
  2838. {
  2839. int exit_status, wc, /*done,*/ windows_in_buf, wastuned = 0, tuned = 0;
  2840. int samps_read;
  2841. double /* time = 0.0,*/ totalamp = 0.0;
  2842. float maxamp;
  2843. chvptr *partials;
  2844. // done = 0;
  2845. if((partials = (chvptr *)malloc(MAXIMI * sizeof(chvptr)))==NULL) {
  2846. sprintf(errstr,"INSUFFICIENT MEMORY for partials array.\n");
  2847. return(MEMORY_ERROR);
  2848. }
  2849. while((samps_read = fgetfbufEx(dz->bigfbuf, dz->buflen,dz->ifd[0],0)) > 0) {
  2850. if(samps_read < 0) {
  2851. sprintf(errstr,"Failed to read data from input file.\n");
  2852. return(SYSTEM_ERROR);
  2853. }
  2854. dz->flbufptr[0] = dz->bigfbuf;
  2855. windows_in_buf = samps_read/dz->wanted;
  2856. for(wc=0; wc<windows_in_buf; wc++, dz->total_windows++) {
  2857. if(dz->total_windows == 0) {
  2858. dz->flbufptr[0] += dz->wanted;
  2859. // time += dz->frametime;
  2860. continue;
  2861. }
  2862. if((exit_status = get_totalamp_and_maxamp(&totalamp,&maxamp,dz->flbufptr[0],dz->wanted))<0)
  2863. return(exit_status);
  2864. if(totalamp <= 0.0) {
  2865. dz->flbufptr[0] += dz->wanted;
  2866. // time += dz->frametime;
  2867. continue;
  2868. }
  2869. if((exit_status = get_peaks(dz))<0)
  2870. return(exit_status);
  2871. if((exit_status = tunepeaks(&tuned,dz))<0)
  2872. return(exit_status);
  2873. wastuned += tuned;
  2874. dz->flbufptr[0] += dz->wanted;
  2875. // time += dz->frametime;
  2876. }
  2877. if((exit_status = write_samps(dz->bigfbuf,samps_read,dz))<0)
  2878. return(exit_status);
  2879. }
  2880. fprintf(stdout,"INFO: Tuned %d of %d windows\n",wastuned,dz->total_windows);
  2881. fflush(stdout);
  2882. return FINISHED;
  2883. }
  2884. /****************************************** ALLOCATE_SINGLE_BUFFER_PLUS_PEAKARRAY *****************************/
  2885. int allocate_single_buffer_plus_peakarray(dataptr dz)
  2886. {
  2887. unsigned int buffersize;
  2888. if(dz->bptrcnt < 4) {
  2889. sprintf(errstr,"bufptr not established in allocate_single_buffer_plus_peakarray()\n");
  2890. return(PROGRAM_ERROR);
  2891. }
  2892. buffersize = dz->wanted * BUF_MULTIPLIER;
  2893. dz->buflen = buffersize;
  2894. buffersize += dz->wanted; // Extra space for peak assessment
  2895. buffersize += 1; // Safety
  2896. if((dz->bigfbuf = (float*) malloc(buffersize * sizeof(float)))==NULL) {
  2897. sprintf(errstr,"INSUFFICIENT MEMORY for sound buffers.\n");
  2898. return(MEMORY_ERROR);
  2899. }
  2900. dz->big_fsize = dz->buflen;
  2901. dz->bigfbuf[dz->big_fsize] = 0.0f; /* safety value */
  2902. dz->flbufptr[2] = dz->bigfbuf + dz->buflen + 1;
  2903. return(FINISHED);
  2904. }
  2905. /******************************** GET_PEAKS **********************************/
  2906. int get_peaks(dataptr dz)
  2907. {
  2908. float *inbuf = dz->flbufptr[0];
  2909. float *pkbuf = dz->flbufptr[2];
  2910. float lastamp;
  2911. double maxamp;
  2912. int cc, vc, lastvc, kk, thismax;
  2913. memset((char *)pkbuf,0,dz->wanted * sizeof(float)); // Preset all peak amplitudes to zeros
  2914. if(inbuf[2] < inbuf[0]) // Peak at start
  2915. pkbuf[0] = inbuf[0]; // set peak level to input amp
  2916. else if (inbuf[0] > 0.0) {
  2917. if(flteq(inbuf[2],inbuf[0])) // Possible peak-plateau at start
  2918. pkbuf[0] = inbuf[0]; // ditto
  2919. }
  2920. for(cc = 1, vc = 2, lastvc = 0; cc < dz->clength - 1; cc++, vc+=2, lastvc+=2) {
  2921. if(inbuf[vc] > inbuf[lastvc]) { // If current amp louder than last
  2922. pkbuf[vc] = inbuf[vc]; // This amp possibly a peak, so assign it the input amp value
  2923. lastamp = pkbuf[lastvc];
  2924. pkbuf[lastvc] = 0; // last amp could not be a peak, so set to zero
  2925. if(lastamp > 0.0) {
  2926. kk = vc - 4; // Check preceeding peaks, in case level plateaued
  2927. while(kk >= 0) { // and remove plateau-peak values, as they are NOT a peak
  2928. if(flteq(pkbuf[kk],lastamp))
  2929. pkbuf[kk] = 0.0;
  2930. kk-=2;
  2931. }
  2932. }
  2933. } else if(flteq(inbuf[vc],inbuf[lastvc])) // peak-plateau, each plateau channel gets input amp val
  2934. pkbuf[vc] = inbuf[vc];
  2935. // else, not a peak, remains zero-valued
  2936. }
  2937. if(inbuf[vc] > inbuf[lastvc]) { // Peak AT END
  2938. pkbuf[vc] = inbuf[vc]; // This amp a peak, so assign it the input amp value
  2939. lastamp = pkbuf[lastvc];
  2940. pkbuf[lastvc] = 0; // last amp could not be a peak, so set to zero
  2941. if(lastamp > 0.0) {
  2942. kk = vc - 4; // Check preceeding peaks, in case level plateaued
  2943. while(kk >= 0) { // and remove plateau-peak values, as they are NOT a peak
  2944. if(flteq(pkbuf[kk],lastamp))
  2945. pkbuf[kk] = 0.0;
  2946. kk-=2;
  2947. }
  2948. }
  2949. } else if(pkbuf[lastvc] > 0.0) {
  2950. if(flteq(inbuf[vc],inbuf[lastvc])) // Possible peak-plateau at end
  2951. pkbuf[vc] = inbuf[vc];
  2952. }
  2953. // GET THE PEAKCNT LOUDEST PEAKS
  2954. for(kk = 0; kk < dz->iparam[ST_CNT];kk++) {
  2955. maxamp = -10000;
  2956. thismax = 0;
  2957. for(vc = 0; vc < dz->wanted; vc += 2) {
  2958. if(pkbuf[vc] > maxamp) {
  2959. maxamp = pkbuf[vc];
  2960. thismax = vc;
  2961. }
  2962. }
  2963. if(maxamp <= 0)
  2964. break;
  2965. pkbuf[thismax+1] = pkbuf[thismax]; // Move loudest value out of array (to adjacent odd-numbered array position)
  2966. pkbuf[thismax] = 0.0; // so next pass gets next-loudest peak
  2967. }
  2968. for(vc = 0; vc < dz->wanted; vc += 2) {
  2969. if(pkbuf[vc+1] > 0.0) { // Where peak level has been stored in odd-vals of array
  2970. pkbuf[vc] = 1.0; // Mark as peak (in even array-vals)
  2971. pkbuf[vc+1] = inbuf[vc+1]; // Remember frqs of peaks (in odd-array vals)
  2972. }
  2973. } // Look for duplication of peak freqs
  2974. for(kk = 0; kk < dz->wanted; kk += 2) { // For all input freqs
  2975. if(pkbuf[kk] == 0.0) { // If not marked as peak
  2976. for(vc = 0; vc < dz->wanted; vc += 2) {
  2977. if(pkbuf[vc] > 0.0) { // Test against all frqs of peaks
  2978. // and if equal to a peak frq,
  2979. if(equivalent_pitches((double)inbuf[kk+1],pkbuf[vc+1],dz))
  2980. pkbuf[kk] = 1.0; // mark as another peak
  2981. else if(inbuf[kk+1] > pkbuf[vc+1])
  2982. break;
  2983. }
  2984. }
  2985. }
  2986. }
  2987. return FINISHED;
  2988. }
  2989. /************************** GET_TOTALAMP_AND_MAXAMP ***********************/
  2990. int get_totalamp_and_maxamp(double *totalamp,float *maxamp,float *sbuf,int wanted)
  2991. {
  2992. int vc;
  2993. *totalamp = 0.0;
  2994. *maxamp = -MAXFLOAT;
  2995. for(vc = 0; vc < wanted; vc += 2) {
  2996. *totalamp += sbuf[AMPP];
  2997. if(sbuf[AMPP] > *maxamp)
  2998. *maxamp = sbuf[AMPP];
  2999. }
  3000. return(FINISHED);
  3001. }
  3002. /************************** TUNEPEAKS ***********************/
  3003. int tunepeaks(int *tuned,dataptr dz)
  3004. {
  3005. float *pkbuf = dz->flbufptr[2];
  3006. float *inbuf = dz->flbufptr[0];
  3007. double *tunings = dz->parray[TUNING_ARRAY];
  3008. double actualfrq, centrefrq, topfrq, botfrq, newfrq, newfrqbas, lastnewfrq, botgap, topgap;
  3009. float temp;
  3010. int cc, vc, kk, octcnt, peakchan, peakvc;
  3011. double closest, close, closestfrq = 0.0;
  3012. *tuned = 0;
  3013. for(cc = 0, vc = 0;cc < dz->clength; cc++, vc+=2) {
  3014. if(pkbuf[vc] > 0.0) { // At each peak
  3015. actualfrq = inbuf[vc+1];
  3016. centrefrq = cc * dz->chwidth; // Find frq range of associated channel
  3017. botfrq = max(centrefrq - dz->halfchwidth,0.0);
  3018. topfrq = min(centrefrq + dz->halfchwidth,dz->nyquist);
  3019. closest = HUGE;
  3020. for(kk=0;kk<dz->itemcnt;kk++) {
  3021. octcnt = 1;
  3022. newfrqbas = tunings[kk];
  3023. newfrq = miditohz(newfrqbas);
  3024. lastnewfrq = 0.0;
  3025. while(newfrq < actualfrq) { // Find nearest harmonic of tuning-set actual-freq in peak channel
  3026. lastnewfrq = newfrq;
  3027. octcnt++;
  3028. newfrq = miditohz(newfrqbas + (octcnt * SEMITONES_PER_OCTAVE));
  3029. }
  3030. if(lastnewfrq > 0.0) {
  3031. botgap = actualfrq - lastnewfrq;
  3032. topgap = newfrq - actualfrq;
  3033. if(botgap < topgap)
  3034. newfrq = lastnewfrq;
  3035. }
  3036. close = fabs(newfrq - actualfrq);
  3037. if(close < closest) {
  3038. closest = close;
  3039. closestfrq = newfrq;
  3040. }
  3041. }
  3042. newfrq = closestfrq;
  3043. if(newfrq <= topfrq && newfrq >= botfrq) { // If newfrq lies within channel,
  3044. inbuf[vc+1] = (float)newfrq; // retune it
  3045. *tuned = 1;
  3046. } else { // Otherwise
  3047. peakchan = (int)round(newfrq/dz->chwidth); // find channel where that frq could sit
  3048. peakvc = peakchan*2;
  3049. if(pkbuf[peakvc] == 0.0) { // If new channel is not already a peak
  3050. pkbuf[peakvc+1] = (float)newfrq; // Insert new freq into selected channel
  3051. *tuned = 1;
  3052. temp = inbuf[peakvc]; // Swap level of new channel for level of peak
  3053. inbuf[peakvc] = inbuf[vc];
  3054. inbuf[vc] = temp;
  3055. pkbuf[peakvc] = 1.0; // Swap peak and non-peak markers of channels
  3056. pkbuf[vc] = 0.0;
  3057. } else { // BUT if it is already a peak
  3058. if(cc == 0) // reduce level of channel that is NOT being retuned
  3059. inbuf[vc] = inbuf[vc+2]; // so its no longer a peak
  3060. else if(cc == dz->clength - 1)
  3061. inbuf[vc] = inbuf[vc-2];
  3062. else
  3063. inbuf[vc] = min(inbuf[vc-2],inbuf[vc+2]);
  3064. pkbuf[vc] = 0.0;
  3065. }
  3066. }
  3067. }
  3068. }
  3069. return FINISHED;
  3070. }
  3071. /************************ HANDLE_SEGMENTATION_DATA *********************/
  3072. int handle_segmentation_data(int *cmdlinecnt,char ***cmdline,dataptr dz)
  3073. {
  3074. aplptr ap = dz->application;
  3075. int n;
  3076. char temp[200], *q, *filename = (*cmdline)[0];
  3077. double *p, lasttime;
  3078. FILE *sfp;
  3079. if(!sloom) {
  3080. if(*cmdlinecnt <= 0) {
  3081. sprintf(errstr,"Insufficient parameters on command line.\n");
  3082. return(USAGE_ONLY);
  3083. }
  3084. }
  3085. ap->data_in_file_only = TRUE;
  3086. ap->special_range = FALSE;
  3087. if((sfp = fopen(filename,"r"))==NULL) {
  3088. sprintf(errstr,"Cannot open datafile %s\n",filename);
  3089. return(DATA_ERROR);
  3090. }
  3091. n = 0;
  3092. while(fgets(temp,200,sfp)!=NULL) {
  3093. q = temp;
  3094. if(is_an_empty_line_or_a_comment(q))
  3095. continue;
  3096. n++;
  3097. }
  3098. if(n==0) {
  3099. sprintf(errstr,"No data in file %s\n",filename);
  3100. return(DATA_ERROR);
  3101. }
  3102. dz->itemcnt = n;
  3103. if ((dz->parray[TIMING_ARRAY] = (double *)malloc(dz->itemcnt * sizeof(double)))==NULL) {
  3104. sprintf(errstr,"Insufficient memory to store slice times\n");
  3105. return(MEMORY_ERROR);
  3106. }
  3107. p = dz->parray[TIMING_ARRAY];
  3108. if(fseek(sfp,0,0)<0) {
  3109. sprintf(errstr,"fseek() failed in handle_segmentation_data()\n");
  3110. return(SYSTEM_ERROR);
  3111. }
  3112. n = 0;
  3113. lasttime = -1.0;
  3114. while(fgets(temp,200,sfp)!=NULL) {
  3115. q = temp;
  3116. if(is_an_empty_line_or_a_comment(temp))
  3117. continue;
  3118. if(n >= dz->itemcnt) {
  3119. sprintf(errstr,"Accounting problem reading timedata.\n");
  3120. return(PROGRAM_ERROR);
  3121. }
  3122. while(get_float_from_within_string(&q,p)) {
  3123. if(n == 0 && *p != 0.0) {
  3124. sprintf(errstr,"Segmentation times must begin at zero (First time in file %s is %lf)\n",filename,*p);
  3125. return(DATA_ERROR);
  3126. }
  3127. if(*p < 0.0) {
  3128. sprintf(errstr,"Time (%lf) less than zero on line %d: file %s\n",*p,n+1,filename);
  3129. return(DATA_ERROR);
  3130. }
  3131. if(*p <= lasttime) {
  3132. sprintf(errstr,"Time (%lf) out of order (last time %lf) on lines %d & %d: file %s\n",*p,lasttime,n,n+1,filename);
  3133. return(DATA_ERROR);
  3134. }
  3135. if(n == dz->itemcnt-1)
  3136. *p = dz->duration;
  3137. else if(*p >= dz->duration) {
  3138. sprintf(errstr,"Time out of range (0 to sound duration %lf) : line %d: file %s\n",dz->duration,n+1,filename);
  3139. return(DATA_ERROR);
  3140. }
  3141. if(*p - lasttime < 0.03 + FLTERR) {
  3142. sprintf(errstr,"Segment length (%lf between %lf to %lf) too short (min %lf) : line %d: file %s\n",*p - lasttime,lasttime,*p,MINSEGLEN,n+1,filename);
  3143. return(DATA_ERROR);
  3144. }
  3145. lasttime = *p;
  3146. p++;
  3147. n++;
  3148. }
  3149. }
  3150. if(fclose(sfp)<0) {
  3151. fprintf(stdout,"WARNING: Failed to close input textfile %s.\n",filename);
  3152. fflush(stdout);
  3153. }
  3154. (*cmdline)++;
  3155. (*cmdlinecnt)--;
  3156. return(FINISHED);
  3157. }