sfsys.c 253 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129
  1. /*
  2. * Copyright (c) 1983-2013 Martin Atkins, Richard Dobson and Composers Desktop Project Ltd
  3. * http://people.bath.ac.uk/masrwd
  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. /* sfsys 64bit (sfsys2010): handle files up to 4GB : fpos_t/fread/POS64 version */
  22. /* PC requires FILE64_WIN defined at compiler level */
  23. /*
  24. * portable sfsys replacement
  25. */
  26. /*RWD.6.5.99 test version for PEAK chunk, etc...
  27. *RWD.7.99 delete created file on error in format, etc
  28. *RWD Jan 2004: fixed WAVE_EX GUID reading on big-endian
  29. */
  30. /* Nov 2005: allow any channel count for B-Format files */
  31. /* April 2006: correct bug recoignising .ambi extension in gettypefrom name98() */
  32. /* but we don't really need to preserve this anyway...could just remove */
  33. /*April 2006: revise rdwavhdr to scan all chunks, so can pick up PEAK chunk after data chunk,
  34. as done by SoundForge! */
  35. /* Oct 2006: changed defs of WORD and DWORD to unsigned, can we support 4GB files???? */
  36. /* RWD 2009: first version of 64bit file handling for 4GB files.*/
  37. /* RWD May 2011: hacked rdwavhdr to accept dastardly Wavelab files with 20byte fmt chunk */
  38. /* PS: and also even more dastardly PT plain wave files with 40byte fmt chunk! */
  39. /* RWD Jan 2013 fixed bug in getsfsysadtl, return correct padded size */
  40. /* RWD Nov 2013 RELEASE 7: added MC_SURR_6_1 */
  41. /* still TODO: replace tmpnam with mkstemp for CDP temporary files for GUI progs (see below)
  42. * Or: leave it to the GUI progs to sort out! */
  43. /* RWD Feb 2014: converted to ints for x64 building */
  44. /* RWD MAR 2015 finished (?) adoption of default value for CDP_SOUND_EXT, eliminated various compiler warnings */
  45. #ifdef __GNUC__
  46. # if (defined(__LP64__) || defined(_LP64))
  47. # define CDPLONG64
  48. # endif
  49. #endif
  50. #ifdef CDPLONG64
  51. # define CDPLONG int
  52. #else
  53. # define CDPLONG long
  54. #endif
  55. //static char *rcsid = "$Id: sfsys.c%v 4.0 1998/17/02 00:47:05 martin Exp $";
  56. /*pstring for AIFC - includes the pad byte*/
  57. static const char aifc_floatstring[10] = { 0x08,'F','l','o','a','t',0x20,'3','2',0x00};
  58. static const char aifc_notcompressed[16] = {0x0e,'n','o','t',0x20,'c','o','m','p','r','e','s','s','e','d',0x00};
  59. /*
  60. * global state
  61. */
  62. int _sfverno = 0x0710; //RWD: remember to update this!
  63. /* NB: private flag! */
  64. #define SFILE_ANAL (3) /* RWD Nov 2009: no PEAK,CLUE chunk for analysis files */
  65. #ifdef DEBUG_MAC
  66. #include <errno.h>
  67. static void parse_errno(int err)
  68. {
  69. switch(err){
  70. case(EBADF):
  71. printf("fd is not valid descriptor\n");
  72. break;
  73. case(EINVAL):
  74. printf("fd is socket, not a file\n");
  75. printf("or: file not open for writing\n");
  76. break;
  77. default:
  78. printf("unrecognised value for err: %d\n",err);
  79. break;
  80. }
  81. }
  82. #endif
  83. /*
  84. * $Log: sfsys.c%v $
  85. * Revision 2.2 1994/12/13 00:47:05 martin
  86. * Add declaration for Unix
  87. *
  88. * Revision 2.1 1994/10/31 15:49:10 martin
  89. * New version number to differentiate from versions already shipped
  90. *
  91. * Revision 1.1 1994/10/31 15:41:38 martin
  92. * Initial revision
  93. *
  94. */
  95. /* RWD July 1997: Revision 2.3: add support for new WAV float format
  96. RWD OCT 97: IMPORTANT FIX: DEAL WITH EXTRA 2 BYTES IN NEW WAVEFORMATEX CHUNK
  97. We MUST READ wave files correctly; it is not wrong, as such, to continue to write them
  98. the old way, (at least, for straight PCM format), but it is nevertheless inconsistent
  99. with modern practice.
  100. also: completed support for 8bit infiles (read,seek,dirsf)
  101. added initial support of minimal 'fact' chunk in WAVE files for non-PCM formats
  102. to use: #define CDP97
  103. to use Win32 file functions, define CDP99
  104. */
  105. #include <stdio.h>
  106. #ifdef unix
  107. #include <unistd.h>
  108. # ifdef __MAC__
  109. # include <sys/syslimits.h>
  110. # endif
  111. #endif
  112. #include <stdlib.h>
  113. #include <math.h>
  114. #include <string.h>
  115. #if /* defined CDP99 && */ defined _WIN32
  116. #include <windows.h>
  117. #endif
  118. #include <fcntl.h>
  119. #include <sys/types.h>
  120. #include <sys/stat.h>
  121. #if defined(_WIN32) || defined(__SC__) || defined (__GNUWIN32__)
  122. #include <io.h>
  123. extern char* _fullpath (char*, const char*, size_t);
  124. #endif
  125. #include <errno.h>
  126. #include <stdio.h>
  127. #include <time.h>
  128. #ifdef _DEBUG
  129. #include <assert.h>
  130. #endif
  131. #include <sfsys.h> /*RWD: don't want local copies of this!*/
  132. /*RWD April 2005 */
  133. #include "sffuncs.h"
  134. #include <osbind.h>
  135. #ifdef _WIN32
  136. #include "alias.h"
  137. #endif
  138. int CDP_COM_READY = 0; /*global flag, ah well...(define in alias.h will access func??)*/
  139. #include <chanmask.h>
  140. /* RWD oct 2022 to eliminate pointer aliasing in AIFF srate handling */
  141. #include "ieee80.h"
  142. //static char *sfsys_h_rcsid = SFSYS_H_RCSID;
  143. /*
  144. * The portability definitions come first
  145. */
  146. #ifdef unix
  147. #define _O_BINARY (0)
  148. #define _O_RDWR O_RDWR
  149. #define _O_RDONLY O_RDONLY
  150. #define _O_CREAT O_CREAT
  151. #define _O_TRUNC O_TRUNC
  152. #define _O_EXCL O_EXCL
  153. #define _S_IWRITE S_IWRITE
  154. #define _S_IREAD S_IREAD
  155. #define chsize ftruncate
  156. #endif
  157. #if !defined(_WIN32) && !defined(__GNUC__)
  158. #define __inline /**/
  159. #endif
  160. #if defined __MAC__
  161. #define _MAX_PATH (PATH_MAX)
  162. #endif
  163. #if defined MAC || defined __MAC__ || defined linux
  164. int getAliasName(char *filename,char *newpath)
  165. {
  166. return 1;
  167. }
  168. #endif
  169. #ifndef min
  170. #define min(a,b) (((a) < (b)) ? (a) : (b) )
  171. #endif
  172. #ifndef WORD
  173. typedef unsigned short WORD;
  174. #endif
  175. #ifndef DWORD
  176. # ifdef CDPLONG64
  177. typedef unsigned int DWORD;
  178. # else
  179. typedef unsigned long DWORD;
  180. # endif
  181. #endif
  182. #ifdef NOTDEF
  183. // moved to sffuncs.h
  184. #define MSBFIRST (1)
  185. #define LSBFIRST (1)
  186. /*RWD May 2007: revise defines to recognise both forms of MAC (__PPC__) */
  187. #if defined(__I86__) || defined(_X86_) || defined(__i386__) || defined(__i486__) || defined(_IBMR2) || defined(__LITTLE_ENDIAN__)
  188. #undef MSBFIRST
  189. #elif defined(M68000) || defined(__sgi) || defined (__ppc__) || defined(__BIG_ENDIAN__)
  190. #undef LSBFIRST
  191. #else
  192. #error "Unknown byte order for this processor"
  193. #endif
  194. #if defined(MSBFIRST) && defined(LSBFIRST)
  195. #error "Internal: can't be both MSB and LSB"
  196. #endif
  197. #define REVDWBYTES(t) ( (((t)&0xff) << 24) | (((t)&0xff00) << 8) | (((t)&0xff0000) >> 8) | (((t)>>24) & 0xff) )
  198. #define REVWBYTES(t) ( (((t)&0xff) << 8) | (((t)>>8) &0xff) )
  199. /*RWD.6.99 REV3BYTES is a function*/
  200. static char * REV3BYTES(char *samp_24);
  201. extern int sampsize[];
  202. #ifdef MSBFIRST
  203. #define REVDATAINFILE(f) ((f)->filetype == riffwav || (f)->filetype == wave_ex)
  204. #else
  205. #define REVDATAINFILE(f) (((f)->filetype == eaaiff) || ((f)->filetype==aiffc))
  206. #endif
  207. #endif
  208. /*
  209. * Sfsys-related definitions
  210. */
  211. #define SFDBASE (1000)
  212. #define ALLOC(s) ((s *)malloc(sizeof(s)))
  213. #define TAG(a,b,c,d) ( ((a)<<24) | ((b)<<16) | ((c)<<8) | (d) )
  214. /*
  215. * Wave format-specific stuff
  216. */
  217. #ifndef WAVE_FORMAT_PCM
  218. #define WAVE_FORMAT_PCM (0x0001)
  219. #endif
  220. #ifndef WAVE_FORMAT_IEEE_FLOAT
  221. #define WAVE_FORMAT_IEEE_FLOAT (0x0003)
  222. #endif
  223. #ifndef WAVE_FORMAT_EXTENSIBLE
  224. #define WAVE_FORMAT_EXTENSIBLE (65534)
  225. #endif
  226. #define CURRENT_PEAK_VERSION (1)
  227. #define sizeof_WFMTEX (40)
  228. #ifdef linux
  229. #define POS64(x) (x.__pos)
  230. #else
  231. #define POS64(x) (x)
  232. #endif
  233. typedef union {
  234. DWORD lsamp;
  235. float fsamp;
  236. unsigned char bytes[4];
  237. } SND_SAMP;
  238. struct fmtchunk {
  239. WORD formattag;
  240. WORD channels;
  241. DWORD samplespersec;
  242. DWORD avgbytespersec;
  243. WORD blockalign;
  244. };
  245. #ifndef _WIN32
  246. typedef struct _GUID
  247. {
  248. DWORD Data1;
  249. unsigned short Data2;
  250. unsigned short Data3;
  251. unsigned char Data4[8];
  252. } GUID;
  253. typedef struct {
  254. WORD wFormatTag;
  255. WORD nChannels;
  256. DWORD nSamplesPerSec;
  257. DWORD nAvgBytesPerSec;
  258. WORD nBlockAlign;
  259. WORD wBitsPerSample;
  260. WORD cbSize;
  261. } WAVEFORMATEX;
  262. #endif
  263. typedef struct {
  264. WAVEFORMATEX Format;
  265. union {
  266. WORD wValidBitsPerSample; /* bits of precision */
  267. WORD wSamplesPerBlock; /* valid if wBitsPerSample==0 */
  268. WORD wReserved; /* If neither applies, set to */
  269. /* zero. */
  270. } Samples;
  271. DWORD dwChannelMask; /* which channels are */
  272. /* present in stream */
  273. GUID SubFormat;
  274. } WAVEFORMATEXTENSIBLE, *PWAVEFORMATEXTENSIBLE;
  275. const static GUID KSDATAFORMAT_SUBTYPE_PCM = {0x00000001,0x0000,0x0010,
  276. {0x80,
  277. 0x00,
  278. 0x00,
  279. 0xaa,
  280. 0x00,
  281. 0x38,
  282. 0x9b,
  283. 0x71}};
  284. const static GUID KSDATAFORMAT_SUBTYPE_IEEE_FLOAT = {0x00000003,0x0000,0x0010,
  285. {0x80,
  286. 0x00,
  287. 0x00,
  288. 0xaa,
  289. 0x00,
  290. 0x38,
  291. 0x9b,
  292. 0x71}};
  293. //B-FORMAT!
  294. // {00000001-0721-11d3-8644-C8C1CA000000}
  295. static const GUID SUBTYPE_AMBISONIC_B_FORMAT_PCM = { 0x00000001, 0x0721, 0x11d3,
  296. { 0x86,
  297. 0x44,
  298. 0xc8,
  299. 0xc1,
  300. 0xca,
  301. 0x0,
  302. 0x0,
  303. 0x0 } };
  304. static const GUID SUBTYPE_AMBISONIC_B_FORMAT_IEEE_FLOAT = { 0x00000003, 0x0721, 0x11d3,
  305. { 0x86,
  306. 0x44,
  307. 0xc8,
  308. 0xc1,
  309. 0xca,
  310. 0x0,
  311. 0x0,
  312. 0x0 } };
  313. struct cuepoint {
  314. DWORD name;
  315. DWORD position;
  316. DWORD incchunkid;
  317. DWORD chunkoffset;
  318. DWORD blockstart;
  319. DWORD sampleoffset;
  320. };
  321. /*
  322. * aiff format-specific stuff
  323. */
  324. struct aiffchunk {
  325. DWORD tag;
  326. DWORD size;
  327. fpos_t offset;
  328. char *buf;
  329. struct aiffchunk *next;
  330. };
  331. /*
  332. * Property storage structures
  333. */
  334. #define PROPCNKSIZE (2000)
  335. struct property {
  336. char *name;
  337. char *data;
  338. int size;
  339. struct property *next;
  340. };
  341. /*
  342. * Common declarations
  343. */
  344. enum sndfiletype {
  345. unknown_wave,
  346. riffwav,
  347. eaaiff,
  348. aiffc, //RWD sfsys98
  349. wave_ex, //RWD.5.99
  350. cdpfile //RWD sfsys98
  351. };
  352. //typedef struct chpeak {
  353. // float value;
  354. // unsigned long position;
  355. //} CHPEAK;
  356. //RWD.6.99 NOTE: because of the slight possibility of 32bit int formats, from both file formats,
  357. // we need an explicit indicator of sample type. We choose to use the fmtchunk.formattag WAVE-style
  358. //for this, even for AIFF formats. Eventually, AIF-C will be used for all float AIFF files
  359. struct sf_file {
  360. char *filename;
  361. enum sndfiletype filetype;
  362. int refcnt;
  363. #if defined CDP99 && defined _WIN32
  364. HANDLE fileno;
  365. #else
  366. FILE* fileno;
  367. #endif
  368. int infochanged;
  369. int todelete;
  370. int readonly;
  371. DWORD mainchunksize;
  372. fpos_t fmtchunkoffset;
  373. WAVEFORMATEXTENSIBLE fmtchunkEx;
  374. int bitmask;
  375. fpos_t datachunkoffset;
  376. #ifdef FILE64_WIN
  377. __int64 datachunksize;
  378. __int64 sizerequested;
  379. #else
  380. /* typedef from long long */
  381. __int64 datachunksize;
  382. __int64 sizerequested;
  383. #endif
  384. int extrachunksizes;
  385. struct aiffchunk *aiffchunks;
  386. int proplim;
  387. fpos_t propoffset;
  388. int propschanged;
  389. int curpropsize;
  390. struct property *props;
  391. DWORD curpos;
  392. fpos_t factchunkoffset;
  393. int header_set; //streaming: disallow header updates
  394. int is_shortcut;
  395. //RWD.6.5.99
  396. time_t peaktime;
  397. fpos_t peakchunkoffset;
  398. CHPEAK *peaks;
  399. channelformat chformat;
  400. int min_header;
  401. };
  402. /*
  403. * for later!!
  404. * I think all we have to do is keep an fd open for each file open, and share
  405. * the other information - we don't have to worry about being thread-safe, etc!!!
  406. */
  407. struct sf_openfile {
  408. struct sf_file *file;
  409. #if defined CDP99 && defined _WIN32
  410. HANDLE fileno;
  411. #else
  412. FILE* fileno;
  413. #endif
  414. DWORD curpos;
  415. };
  416. /*
  417. * Values for sizerequested
  418. */
  419. #define ES_EXIST (-2)
  420. #define LEAVESPACE (10*1024) /* file space that must be left */ //RWD? align to cluster size?
  421. /*
  422. * internal state
  423. */
  424. int rsferrno = 0;
  425. char *rsferrstr = "no previous error";
  426. static struct sf_file *sf_files[SF_MAXFILES];
  427. //static enum sndfiletype gettypefromname(const char *path); //RWD98: lets declare this here
  428. static enum sndfiletype gettypefromname98(const char *path);
  429. static enum sndfiletype gettypefromfile(struct sf_file *f);
  430. static int wrwavhdr98(struct sf_file *f, int channels, int srate, int stype);
  431. static int wraiffhdr98(struct sf_file *f, int channels, int srate, int stype);
  432. static int wavupdate98(time_t thistime,struct sf_file *f);
  433. static int aiffupdate(time_t thistime,struct sf_file *f);
  434. static int aiffupdate98(time_t thistime,struct sf_file *f);
  435. //private, but used by snd routines
  436. unsigned int _rsf_getmaxpeak(int sfd,float *peak);
  437. /*RWD 3:2000 to add analysis properties internally */
  438. static int addprop(struct sf_file *f, char *propname, char *src, int size);
  439. static int compare_guids(const GUID *gleft, const GUID *gright)
  440. {
  441. const char *left = (const char *) gleft, *right = (const char *) gright;
  442. return !memcmp(left,right,sizeof(GUID));
  443. }
  444. static int check_guid(struct sf_file *f)
  445. {
  446. //expects a GUID to be loaded already,
  447. //at present, we only need to know if this is b-format or not.
  448. //but might as well validate floatsam format against nBits , jic
  449. if(f->filetype != wave_ex) //should be an assert, but this is NOT a console lib!
  450. return 1;
  451. f->chformat = MC_STD;
  452. //we elabotate on possible std assignments later...
  453. if(compare_guids(&(f->fmtchunkEx.SubFormat),&(KSDATAFORMAT_SUBTYPE_PCM)))
  454. return 0;
  455. if(compare_guids(&(f->fmtchunkEx.SubFormat),&(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)))
  456. if(f->fmtchunkEx.Format.wBitsPerSample == 32)
  457. return 0;
  458. if(compare_guids(&(f->fmtchunkEx.SubFormat),&(SUBTYPE_AMBISONIC_B_FORMAT_PCM))) {
  459. f->chformat = MC_BFMT;
  460. return 0;
  461. }
  462. if(compare_guids(&(f->fmtchunkEx.SubFormat),&(SUBTYPE_AMBISONIC_B_FORMAT_IEEE_FLOAT))) {
  463. if(f->fmtchunkEx.Format.wBitsPerSample == 32){
  464. f->chformat = MC_BFMT;
  465. return 0;
  466. }
  467. }
  468. return 1;
  469. }
  470. #if defined CDP99 && defined _WIN32
  471. #ifdef FILE64_WIN
  472. static int w_ch_size(HANDLE fh,__int64 size)
  473. #else
  474. static int w_ch_size(HANDLE fh,DWORD size)
  475. #endif
  476. {
  477. #ifdef FILE64_WIN
  478. LARGE_INTEGER li;
  479. li.QuadPart = size;
  480. li.LowPart = SetFilePointer(fh,li.LowPart,&li.HighPart,FILE_BEGIN);
  481. if(li.LowPart != 0xFFFFFFFF && GetLastError() == NO_ERROR){
  482. if (!SetEndOfFile(fh))
  483. return -1;
  484. }
  485. else
  486. return -1;
  487. #else
  488. if(SetFilePointer(fh,(long) size,NULL,FILE_BEGIN)== 0xFFFFFFFF
  489. || !SetEndOfFile(fh))
  490. return -1;
  491. #endif
  492. return 0;
  493. }
  494. #endif
  495. /*
  496. * read/write routines
  497. */
  498. /* RWD 2007 executive decision not to allow cnt >= 2GB! */
  499. #if defined CDP99 && defined _WIN32
  500. static __inline int
  501. doread(struct sf_file *f, char *buf, int cnt)
  502. {
  503. DWORD done = 0, count = (DWORD) cnt;
  504. if(f->fileno == INVALID_HANDLE_VALUE)
  505. return 1;
  506. if(!ReadFile(f->fileno, buf, count,&done,NULL)){
  507. # ifdef _DEBUG
  508. LPVOID lpMsgBuf;
  509. FormatMessage(
  510. FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
  511. NULL,
  512. GetLastError(),
  513. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
  514. (LPTSTR) &lpMsgBuf,
  515. 0,
  516. NULL
  517. );
  518. # ifndef WINDOWS
  519. fprintf(stderr,(const char *)lpMsgBuf);
  520. # else
  521. MessageBox( NULL, lpMsgBuf, "GetLastError", MB_OK|MB_ICONINFORMATION );
  522. # endif
  523. LocalFree( lpMsgBuf );
  524. # endif
  525. return 1;
  526. }
  527. return done != count;
  528. }
  529. #else
  530. //RWD NB returns ERROR if requested byte-count not read
  531. static __inline int
  532. doread(struct sf_file *f, char *buf, int cnt)
  533. {
  534. int done = fread(buf,sizeof(char),cnt,f->fileno);
  535. return done != cnt;
  536. }
  537. #endif
  538. static int
  539. read_w_lsf(WORD *wp, struct sf_file *f)
  540. {
  541. WORD w;
  542. if(doread(f, (char *)&w, sizeof(WORD)))
  543. return 1;
  544. #ifdef MSBFIRST
  545. *wp = REVWBYTES(w);
  546. #else
  547. *wp = w;
  548. #endif
  549. return 0;
  550. }
  551. static int
  552. read_w_msf(WORD *wp, struct sf_file *f)
  553. {
  554. WORD w;
  555. if(doread(f, (char *)&w, sizeof(WORD)))
  556. return 1;
  557. #ifdef LSBFIRST
  558. *wp = REVWBYTES(w);
  559. #else
  560. *wp = w;
  561. #endif
  562. return 0;
  563. }
  564. static int
  565. read_dw_lsf(DWORD *dwp, struct sf_file *f)
  566. {
  567. DWORD dw;
  568. if(doread(f, (char *)&dw, sizeof(DWORD)))
  569. return 1;
  570. #ifdef MSBFIRST
  571. *dwp = REVDWBYTES(dw);
  572. #else
  573. *dwp = dw;
  574. #endif
  575. return 0;
  576. }
  577. static int
  578. read_dw_msf(DWORD *dwp, struct sf_file *f)
  579. {
  580. DWORD dw;
  581. if(doread(f, (char *)&dw, sizeof(DWORD)))
  582. return 1;
  583. #ifdef LSBFIRST
  584. *dwp = REVDWBYTES(dw);
  585. #else
  586. *dwp = dw;
  587. #endif
  588. return 0;
  589. }
  590. #if defined CDP99 && defined _WIN32
  591. static __inline int
  592. dowrite(struct sf_file *f, char *buf, int cnt)
  593. {
  594. DWORD done = 0, count = (DWORD)cnt;
  595. if(!WriteFile(f->fileno, buf, count,&done,NULL))
  596. return 1;
  597. return done != count;
  598. }
  599. #else
  600. static __inline int
  601. dowrite(struct sf_file *f, char *buf, int cnt)
  602. {
  603. int done = fwrite(buf,sizeof(char),cnt,f->fileno);
  604. return done != cnt;
  605. }
  606. #endif
  607. static int
  608. write_w_lsf(WORD w, struct sf_file *f)
  609. {
  610. #ifdef MSBFIRST
  611. w = REVWBYTES(w);
  612. #endif
  613. return dowrite(f, (char *)&w, sizeof(WORD));
  614. }
  615. static int
  616. write_w_msf(WORD w, struct sf_file *f)
  617. {
  618. #ifdef LSBFIRST
  619. w = REVWBYTES(w);
  620. #endif
  621. return dowrite(f, (char *)&w, sizeof(WORD));
  622. }
  623. static int
  624. write_dw_lsf(DWORD dw, struct sf_file *f)
  625. {
  626. #ifdef MSBFIRST
  627. dw = REVDWBYTES(dw);
  628. #endif
  629. return dowrite(f, (char *)&dw, sizeof(DWORD));
  630. }
  631. static int
  632. write_dw_msf(DWORD dw, struct sf_file *f)
  633. {
  634. #ifdef LSBFIRST
  635. dw = REVDWBYTES(dw);
  636. #endif
  637. return dowrite(f, (char *)&dw, sizeof(DWORD));
  638. }
  639. //RWD.6.5.99 write peak data
  640. /* NB position values are of frames, so int good for 2GB anyway */
  641. static int write_peak_lsf(int channels, struct sf_file *f)
  642. {
  643. int i;
  644. DWORD peak[2];
  645. SND_SAMP ssamp;
  646. #ifdef _DEBUG
  647. if(f->peaks==NULL){
  648. printf("\nerror: attempt to write uninitialized peak data");
  649. return 1;
  650. }
  651. #endif
  652. for(i=0; i < channels; i++){
  653. // /*long*/ DWORD *pdw;
  654. // pdw = (/*long*/DWORD *) &(f->peaks[i].value); /* RWD replaced with union */
  655. ssamp.fsamp = f->peaks[i].value;
  656. //peak[0] = *pdw;
  657. peak[0] = ssamp.lsamp;
  658. peak[1] = f->peaks[i].position;
  659. #ifdef MSBFIRST
  660. peak[0] = REVDWBYTES(peak[0]);
  661. peak[1] = REVDWBYTES(peak[1]);
  662. #endif
  663. if(dowrite(f,(char *) peak, 2 * sizeof(DWORD)))
  664. return 1;
  665. }
  666. return 0;
  667. }
  668. static int read_peak_lsf(int channels, struct sf_file *f)
  669. {
  670. int i;
  671. DWORD peak[2];
  672. SND_SAMP ssamp;
  673. #ifdef _DEBUG
  674. if(f->peaks==NULL){
  675. printf("\nerror: attempt to write uninitialized peak data");
  676. return 1;
  677. }
  678. #endif
  679. for(i=0;i < channels; i++){
  680. if(doread(f,(char *)peak,2 * sizeof(DWORD)))
  681. return 1;
  682. #ifdef MSBFIRST
  683. peak[0] = REVDWBYTES(peak[0]);
  684. peak[1] = REVDWBYTES(peak[1]);
  685. #endif
  686. ssamp.lsamp = peak[0];
  687. //f->peaks[i].value = *(float *) &(peak[0]); /* RWD TODO: replaced with union */
  688. f->peaks[i].value = ssamp.fsamp;
  689. f->peaks[i].position = peak[1];
  690. }
  691. return 0;
  692. }
  693. static int write_peak_msf(int channels, struct sf_file *f)
  694. {
  695. int i;
  696. DWORD peak[2];
  697. SND_SAMP ssamp;
  698. for(i=0; i < channels; i++){
  699. // /*long*/DWORD *pdw;
  700. //pdw = (/*long*/DWORD *) &(f->peaks[i].value); /* RWD replaced with union */
  701. ssamp.fsamp = f->peaks[i].value;
  702. // peak[0] = *pdw;
  703. peak[0] = ssamp.lsamp;
  704. peak[1] = f->peaks[i].position;
  705. #ifdef LSBFIRST
  706. peak[0] = REVDWBYTES(peak[0]);
  707. peak[1] = REVDWBYTES(peak[1]);
  708. #endif
  709. if(dowrite(f,(char *) peak, 2 * sizeof(DWORD)))
  710. return 1;
  711. }
  712. return 0;
  713. }
  714. static int read_peak_msf(int channels, struct sf_file *f)
  715. {
  716. int i;
  717. DWORD peak[2];
  718. SND_SAMP ssamp;
  719. for(i=0;i < channels; i++){
  720. if(doread(f,(char *)peak,2 * sizeof(DWORD)))
  721. return 1;
  722. #ifdef LSBFIRST
  723. peak[0] = REVDWBYTES(peak[0]);
  724. peak[1] = REVDWBYTES(peak[1]);
  725. #endif
  726. ssamp.lsamp = peak[0];
  727. //f->peaks[i].value = *(float *) &(peak[0]); /* RWD replaced with union */
  728. f->peaks[i].value = ssamp.fsamp;
  729. f->peaks[i].position = peak[1];
  730. }
  731. return 0;
  732. }
  733. /*
  734. * Fudge Apple extended format, for sample rates
  735. */
  736. /* RWD Oct 2022 removed old "TABLE_IEEE754" code */
  737. /* now using compact Csound code */
  738. #ifdef DW_EX_OLDCODE
  739. static int
  740. read_ex_todw(DWORD *dwp, struct sf_file *f)
  741. {
  742. double neg = 1.0;
  743. WORD exp;
  744. /*unsigned long*/DWORD ms_sig;
  745. double res;
  746. char buf[10]; /* for 80-bit extended float */
  747. if(doread(f, buf, 10))
  748. return 1;
  749. # ifdef LSBFIRST
  750. exp = REVWBYTES(*(WORD *)&buf[0]);
  751. ms_sig = (/*unsigned long*/DWORD)REVDWBYTES(*(DWORD *)&buf[2]); /* RWD TODO replace with union */
  752. # else
  753. exp = *(WORD *)&buf[0];
  754. ms_sig = (/*unsigned long*/DWORD)*(DWORD *)&buf[2]; /* RWD TODO replace with union */
  755. # endif
  756. if(exp & 0x8000) {
  757. exp &= ~0x8000;
  758. neg = -1.0;
  759. }
  760. exp -= 16382;
  761. res = (double)ms_sig/TWOPOW32;
  762. res = neg*ldexp(res, exp);
  763. *dwp = (DWORD)(res+0.5);
  764. return 0;
  765. }
  766. static int
  767. write_dw_toex(DWORD dw, struct sf_file *f)
  768. {
  769. double val = (double)dw;
  770. int neg = 0;
  771. /*unsigned long*/DWORD mant;
  772. int exp;
  773. char buf[10];
  774. if(val < 0.0) {
  775. val = -val;
  776. neg++;
  777. }
  778. mant = (/*unsigned long*/DWORD)(frexp(val, &exp) * TWOPOW32 + 0.5);
  779. exp += 16382;
  780. if(neg)
  781. exp |= 0x8000;
  782. # ifdef LSBFIRST
  783. *(WORD *)&buf[0] = REVWBYTES(exp); /* RWD TODO replace all with union? */
  784. *(DWORD *)&buf[2] = REVDWBYTES((DWORD)mant);
  785. # else
  786. *(WORD *)&buf[0] = exp;
  787. *(DWORD *)&buf[2] = mant;
  788. # endif
  789. *(DWORD *)&buf[6] = 0;
  790. return dowrite(f, buf, 10);
  791. }
  792. #else
  793. /* use Csound funcs */
  794. static int
  795. read_ex_todw(DWORD *dwp, struct sf_file *f)
  796. {
  797. double Csound_res = 0.0;
  798. char buf[10]; /* for 80-bit extended float */
  799. if(doread(f, buf, 10))
  800. return 1;
  801. Csound_res = ieee_80_to_double((unsigned char *) buf);
  802. *dwp = (DWORD) Csound_res;
  803. return 0;
  804. }
  805. static int
  806. write_dw_toex(DWORD dw, struct sf_file *f)
  807. {
  808. double val = (double)dw;
  809. char buf[10];
  810. double_to_ieee_80(val,(unsigned char *) buf);
  811. return dowrite(f,buf,10);
  812. }
  813. #endif // DW_EX_OLDCODE
  814. /*
  815. * wave file-format specific routines
  816. */
  817. static int
  818. getsfsyscue(struct sf_file *f)
  819. {
  820. DWORD cnt;
  821. int rc = 0;
  822. struct cuepoint cue;
  823. if(read_dw_lsf(&cnt, f))
  824. return -1;
  825. while(cnt-- > 0) {
  826. if(read_dw_msf(&cue.name, f)
  827. ||read_dw_lsf(&cue.position, f)
  828. ||read_dw_msf(&cue.incchunkid, f)
  829. ||read_dw_lsf(&cue.chunkoffset, f)
  830. ||read_dw_lsf(&cue.blockstart, f)
  831. ||read_dw_lsf(&cue.sampleoffset, f))
  832. return -1;
  833. if(cue.name == TAG('s','f','i','f'))
  834. rc = 1;
  835. }
  836. return rc;
  837. }
  838. /*
  839. * extended properties are as follows:
  840. *
  841. * property name '\n'
  842. * property value '\n'
  843. * ...
  844. * '\n'
  845. */
  846. static int
  847. xtoi(int ch)
  848. {
  849. if(ch >= '0' && ch <= '9')
  850. return ch - '0';
  851. if(ch >= 'A' && ch <= 'F')
  852. return ch - 'A' + 10;
  853. if(ch >= 'a' && ch <= 'f')
  854. return ch - 'a' + 10;
  855. return 0;
  856. }
  857. static int
  858. itox(int i)
  859. {
  860. static char trans[] = "0123456789ABCDEF";
  861. return trans[i&0x0f];
  862. }
  863. static void
  864. parseprops(struct sf_file *f, char *data)
  865. {
  866. char *cp = data;
  867. char *ep, *evp;
  868. int cnt;
  869. struct property **ppp = &f->props;
  870. struct property *np;
  871. f->curpropsize = 0;
  872. while(cp-data < f->proplim && *cp != '\n') {
  873. if((ep = strchr(cp, '\n')) == 0
  874. ||(evp = strchr(ep+1, '\n')) == 0
  875. ||((evp-ep-1)&1))
  876. return;
  877. if((np = ALLOC(struct property)) == 0
  878. ||(np->name = (char *) malloc(ep-cp+1)) == 0
  879. ||(np->data = (char *) malloc((evp-ep-1)/2)) == 0)
  880. return;
  881. np->size = (evp-ep-1)/2;
  882. np->next = 0;
  883. memcpy(np->name, cp, ep-cp);
  884. np->name[ep-cp] = '\0';
  885. for(cnt = 0; cnt < np->size; cnt++)
  886. np->data[cnt] = (xtoi((ep+1)[2*cnt])<<4) + xtoi((ep+1)[2*cnt+1]);
  887. *ppp = np;
  888. ppp = &np->next;
  889. f->curpropsize += strlen(np->name) + 1 + np->size + 1;
  890. cp = evp+1;
  891. }
  892. }
  893. static int
  894. writeprops(struct sf_file *f)
  895. {
  896. char *obuf, *op;
  897. int cnt;
  898. struct property *p = f->props;
  899. if((obuf = (char *) malloc(f->proplim)) == 0) {
  900. rsferrno = ESFNOMEM;
  901. rsferrstr = "No memory to write properties with";
  902. return -1;
  903. }
  904. op = obuf;
  905. while(p != 0) {
  906. strcpy(op, p->name);
  907. op += strlen(p->name);
  908. *op++ = '\n';
  909. for(cnt = 0; cnt < p->size; cnt++) {
  910. *op++ = itox(p->data[cnt]>>4);
  911. *op++ = itox(p->data[cnt]);
  912. }
  913. *op++ = '\n';
  914. if(op-obuf >= f->proplim) //RWD.1.99 this is really an assert test...
  915. abort();
  916. p = p->next;
  917. }
  918. while(op < &obuf[f->proplim])
  919. *op++ = '\n';
  920. /*RWD 2007: we rely on all props being within first 2GB of file! */
  921. #if defined CDP99 && defined _WIN32
  922. if (SetFilePointer(f->fileno,(LONG)f->propoffset,NULL,FILE_BEGIN) == 0xFFFFFFFF
  923. #else
  924. if(fseeko(f->fileno, POS64(f->propoffset), SEEK_SET)
  925. #endif
  926. ||dowrite(f, obuf, f->proplim)) {
  927. rsferrno = ESFWRERR;
  928. rsferrstr = "Write error writing new property values";
  929. return -1;
  930. }
  931. free(obuf);
  932. return 0;
  933. }
  934. static int
  935. getsfsysadtl(struct sf_file *f, int adtllen)
  936. {
  937. DWORD tag, size;
  938. DWORD name;
  939. fpos_t bytepos;
  940. char *propspace;
  941. char buf[1];
  942. while(adtllen > 0) {
  943. if(read_dw_msf(&tag, f)
  944. ||read_dw_lsf(&size, f))
  945. return -1;
  946. switch(tag) {
  947. case TAG('n','o','t','e'):
  948. if(read_dw_msf(&name, f))
  949. return -1;
  950. if(name != TAG('s','f','i','f')
  951. ||(int)(POS64(f->propoffset)) >= 0
  952. ||(propspace = (char *) malloc(size-sizeof(DWORD))) == 0) {
  953. #if defined CDP99 && defined _WIN32
  954. if(SetFilePointer(f->fileno,(LONG)((size-sizeof(DWORD)+1)&~1),NULL,FILE_CURRENT)== 0xFFFFFFFF)
  955. #else
  956. if(fseek(f->fileno, (size-sizeof(DWORD)+1)&~1, SEEK_CUR))
  957. #endif
  958. return -1;
  959. break;
  960. }
  961. f->proplim = size-sizeof(DWORD);
  962. #if defined CDP99 && defined _WIN32
  963. if((f->propoffset = SetFilePointer(f->fileno, 0L, NULL, FILE_CURRENT)) == 0xFFFFFFFF
  964. ||doread(f, propspace, size-sizeof(DWORD)))
  965. return -1;
  966. #else
  967. if(fgetpos(f->fileno,&bytepos)
  968. ||doread(f, propspace, size-sizeof(DWORD)))
  969. return -1;
  970. f->propoffset = bytepos;
  971. #endif
  972. parseprops(f, propspace);
  973. free(propspace);
  974. if(size&1)
  975. doread(f, buf, 1);
  976. break;
  977. default:
  978. #if defined CDP99 && defined _WIN32
  979. if(SetFilePointer(f->fileno, (size+1)&~1,NULL,FILE_CURRENT) == 0xFFFFFFFF)
  980. return -1;
  981. #else
  982. if(fseek(f->fileno, (size+1)&~1, SEEK_CUR) < 0)
  983. return -1;
  984. #endif
  985. break;
  986. }
  987. adtllen -= 2*sizeof(DWORD) + ((size+1)&~1); /* RWD Jan 2013 */
  988. }
  989. return 0;
  990. }
  991. //RWD.7.99 TODO: set f->min_header here?
  992. /*RWD 2007: MUST use DWORD to enure we get sizes up to 4GB */
  993. /* BUT: if we seek to end of data chunk, need 64bit seek */
  994. static int
  995. rdwavhdr(struct sf_file *f)
  996. {
  997. DWORD tag, size;
  998. int fmtseen = 0;
  999. int dataseen = 0; /*RWD April 2006: try to read PEAK chunk after data (boo hiss Sony! )*/
  1000. int err = 0; /* "" */
  1001. int gotsfsyscue = 0;
  1002. DWORD factsize = 0;
  1003. DWORD peak_version;
  1004. #ifdef FILE64_WIN
  1005. LARGE_INTEGER pos64; /* pos64.QuadPart is __int64 */
  1006. #endif
  1007. fpos_t bytepos;
  1008. //WAVEFORMATEXTENSIBLE *pFmtEx;
  1009. if(read_dw_msf(&tag, f)
  1010. ||read_dw_lsf(&size, f)
  1011. ||tag != TAG('R','I','F','F')) {
  1012. rsferrno = ESFNOTFOUND;
  1013. rsferrstr = "File is not a RIFF file";
  1014. return 1;
  1015. }
  1016. if(size < 4) {
  1017. rsferrno = ESFNOTFOUND;
  1018. rsferrstr = "File data size is too small";
  1019. return 1;
  1020. }
  1021. if(read_dw_msf(&tag, f)
  1022. ||tag != TAG('W','A','V','E')) {
  1023. rsferrno = ESFNOTFOUND;
  1024. rsferrstr = "File is not a wave RIFF file";
  1025. return 1;
  1026. }
  1027. f->filetype = riffwav; //might be wave_ex
  1028. f->mainchunksize = size;
  1029. f->extrachunksizes = 0;
  1030. f->proplim = 0;
  1031. f->props = 0;
  1032. POS64(f->propoffset) = (unsigned) -1;
  1033. POS64(f->factchunkoffset) = (unsigned) -1;
  1034. //datachunkoffset now initialized in allocsffile
  1035. //RWD.6.99 do I need to do the AIFF getout for bad sizes here too?
  1036. for(;;) {
  1037. if(read_dw_msf(&tag, f)
  1038. ||read_dw_lsf(&size,f)){
  1039. /*RWD April 2006 TODO: detect EOF! */
  1040. err++;
  1041. goto ioerror;
  1042. }
  1043. switch(tag) {
  1044. case TAG('f','m','t',' '):
  1045. //RWD: must deal with possibility of WAVEFORMATEX extra cbSize word
  1046. #if defined CDP99 && defined _WIN32
  1047. if((f->fmtchunkoffset = SetFilePointer(f->fileno, 0L,NULL, FILE_CURRENT))== 0xFFFFFFFF
  1048. ||read_w_lsf(&f->fmtchunkEx.Format.wFormatTag, f)
  1049. ||read_w_lsf(&f->fmtchunkEx.Format.nChannels, f)
  1050. ||read_dw_lsf(&f->fmtchunkEx.Format.nSamplesPerSec, f)
  1051. ||read_dw_lsf(&f->fmtchunkEx.Format.nAvgBytesPerSec, f)
  1052. ||read_w_lsf(&f->fmtchunkEx.Format.nBlockAlign, f) ) {
  1053. err++;
  1054. goto ioerror;
  1055. }
  1056. #else
  1057. if(fgetpos(f->fileno, &bytepos)
  1058. ||read_w_lsf(&f->fmtchunkEx.Format.wFormatTag, f)
  1059. ||read_w_lsf(&f->fmtchunkEx.Format.nChannels, f)
  1060. ||read_dw_lsf(&f->fmtchunkEx.Format.nSamplesPerSec, f)
  1061. ||read_dw_lsf(&f->fmtchunkEx.Format.nAvgBytesPerSec, f)
  1062. ||read_w_lsf(&f->fmtchunkEx.Format.nBlockAlign, f) ) {
  1063. err++;
  1064. goto ioerror;
  1065. }
  1066. f->fmtchunkoffset = bytepos;
  1067. #endif
  1068. switch(f->fmtchunkEx.Format.wFormatTag) {
  1069. case WAVE_FORMAT_PCM:
  1070. case WAVE_FORMAT_IEEE_FLOAT: //RWD 07:97
  1071. case WAVE_FORMAT_EXTENSIBLE: //RWD.5.99
  1072. if(read_w_lsf(&f->fmtchunkEx.Format.wBitsPerSample, f)) {
  1073. err++;
  1074. goto ioerror;
  1075. }
  1076. //RWD.6.99 set f->fmtchunkEx.Samples.wValidBitsPerSample to this as default
  1077. // will only be changed by a WAVE_EX header
  1078. f->fmtchunkEx.Samples.wValidBitsPerSample = f->fmtchunkEx.Format.wBitsPerSample;
  1079. //deal with things such as 20bits per sample...
  1080. //this covers standard WAVE, WAVE-EX may adjust again
  1081. if(f->fmtchunkEx.Format.wBitsPerSample !=
  1082. ((f->fmtchunkEx.Format.nBlockAlign / f->fmtchunkEx.Format.nChannels) * 8)){
  1083. //deduce the container size
  1084. f->fmtchunkEx.Format.wBitsPerSample =
  1085. ((f->fmtchunkEx.Format.nBlockAlign / f->fmtchunkEx.Format.nChannels) * 8);
  1086. }
  1087. switch(f->fmtchunkEx.Format.wBitsPerSample) {
  1088. case 32: /* floats or longs*/
  1089. break;
  1090. case(24):
  1091. case 16: /* shorts */
  1092. case 8: /* byte -> short mappping */
  1093. /*RWD 07:97*/ if(!(f->fmtchunkEx.Format.wFormatTag == WAVE_FORMAT_PCM ||
  1094. f->fmtchunkEx.Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE)){
  1095. rsferrno = ESFNOTFOUND;
  1096. rsferrstr = "can't open Sfile : Format mismatch";
  1097. return 1;
  1098. }
  1099. break;
  1100. default:
  1101. rsferrno = ESFNOTFOUND;
  1102. rsferrstr = "can't open Sfile - unsupported format";
  1103. return 1;
  1104. }
  1105. //now catch any extra bytes, and parse WAVE_EX if we have it...
  1106. if(size > 16){
  1107. unsigned short cbSize;
  1108. if(read_w_lsf(&cbSize,f))
  1109. goto ioerror;
  1110. /* RWD May 2011. Effing Steinberg Wavelab writes a 20byte fmt chunk! */
  1111. /* Feb 2012: AND Pro Tools writes a 40byte fmt chunk! */
  1112. if(cbSize==0){
  1113. int wordstoskip = (size-18) / sizeof(WORD);
  1114. int skip;
  1115. unsigned short dummy;
  1116. for(skip = 0; skip < wordstoskip; skip++){
  1117. if(read_w_lsf(&dummy,f))
  1118. goto ioerror;
  1119. }
  1120. }
  1121. else{
  1122. if(f->fmtchunkEx.Format.wFormatTag != WAVE_FORMAT_EXTENSIBLE){
  1123. rsferrno = ESFNOTFOUND;
  1124. rsferrstr = "unexpected extra format information - not a wave file";
  1125. return 1;
  1126. }
  1127. if(cbSize != 22){
  1128. rsferrno = ESFNOTFOUND;
  1129. rsferrstr = "unexpected extra format information in WAVE_EX file!";
  1130. return 1;
  1131. }
  1132. f->filetype = wave_ex;
  1133. if(read_w_lsf(&(f->fmtchunkEx.Samples.wValidBitsPerSample),f)
  1134. ||
  1135. read_dw_lsf(&(f->fmtchunkEx.dwChannelMask),f)){
  1136. err++;
  1137. goto ioerror;
  1138. }
  1139. //get the GUID
  1140. /*RWD TODO: need byte-reverse code in hers! */
  1141. if(doread(f,(char *) &(f->fmtchunkEx.SubFormat),sizeof(GUID))) {
  1142. err++;
  1143. goto ioerror;
  1144. }
  1145. #ifdef MSBFIRST
  1146. f->fmtchunkEx.SubFormat.Data1 = REVDWBYTES(f->fmtchunkEx.SubFormat.Data1);
  1147. f->fmtchunkEx.SubFormat.Data2 = REVWBYTES(f->fmtchunkEx.SubFormat.Data2);
  1148. f->fmtchunkEx.SubFormat.Data3 = REVWBYTES(f->fmtchunkEx.SubFormat.Data3);
  1149. #endif
  1150. if(check_guid(f)){
  1151. rsferrno = ESFNOTFOUND;
  1152. rsferrstr = "unrecognized WAV_EX subformat";
  1153. return 1;
  1154. }
  1155. //we don't try to ID the spkr-config here: do that in the sf/snd open fucntions
  1156. }
  1157. }
  1158. break;
  1159. default:
  1160. rsferrno = ESFNOTFOUND;
  1161. rsferrstr = "can't open Sfile - unsupported format";
  1162. return 1;
  1163. }
  1164. //set the bitmask here - covers plain WAVE too
  1165. if(f->fmtchunkEx.Samples.wValidBitsPerSample
  1166. < f->fmtchunkEx.Format.wBitsPerSample){
  1167. /*long*/ int mask = 0xffffffff;
  1168. /*long*/ int shift = 32 - f->fmtchunkEx.Format.wBitsPerSample;
  1169. f->bitmask = mask << (shift + (f->fmtchunkEx.Format.wBitsPerSample
  1170. - f->fmtchunkEx.Samples.wValidBitsPerSample));
  1171. }
  1172. fmtseen++;
  1173. break;
  1174. case TAG('L','I','S','T'):
  1175. if(read_dw_msf(&tag, f))
  1176. goto ioerror;
  1177. switch(tag) {
  1178. case TAG('w','a','v','l'):
  1179. rsferrno = ESFNOTFOUND;
  1180. rsferrstr = "Can't open SFfile - no support for list chunks yet!";
  1181. return 1;
  1182. case TAG('a','d','t','l'):
  1183. if(getsfsysadtl(f, size-sizeof(DWORD)) < 0) {
  1184. err++;
  1185. goto ioerror;
  1186. }
  1187. break;
  1188. default:
  1189. #if defined CDP99 && defined _WIN32
  1190. if(SetFilePointer(f->fileno, size-sizeof(DWORD),NULL, FILE_CURRENT) == 0xFFFFFFFF)
  1191. #else
  1192. POS64(bytepos) = size-sizeof(DWORD);
  1193. if(fseeko(f->fileno, /*size-sizeof(DWORD)*/POS64(bytepos), SEEK_CUR) < 0)
  1194. #endif
  1195. {
  1196. err++;
  1197. goto ioerror;
  1198. }
  1199. break;
  1200. }
  1201. break;
  1202. //read fact chunk (not needed for std PCM files...but we use it anyway in sfsys97!
  1203. case TAG('f','a','c','t'):
  1204. #if defined CDP99 && defined _WIN32
  1205. if((f->factchunkoffset = SetFilePointer(f->fileno, 0L, NULL, FILE_CURRENT)) == 0xFFFFFFFF)
  1206. #else
  1207. if(fgetpos(f->fileno,&f->factchunkoffset))
  1208. #endif
  1209. {
  1210. err++;
  1211. goto ioerror;
  1212. }
  1213. if(read_dw_lsf(&factsize,f)) {
  1214. err++;
  1215. goto ioerror;
  1216. }
  1217. break; //RWD: need to update extrachunksizes?
  1218. //RWD.5.99 read PEAK chunk
  1219. case TAG('P','E','A','K'):
  1220. f->peaks = (CHPEAK *) calloc(f->fmtchunkEx.Format.nChannels,sizeof(CHPEAK));
  1221. if(f->peaks == NULL){
  1222. rsferrno = ESFNOMEM;
  1223. rsferrstr = "No memory for peak data";
  1224. return 1;
  1225. }
  1226. if(read_dw_lsf(&peak_version,f)) {
  1227. err++;
  1228. goto ioerror;
  1229. }
  1230. switch(peak_version){
  1231. case(CURRENT_PEAK_VERSION):
  1232. if(read_dw_lsf((DWORD*) &(f->peaktime),f)){
  1233. err++;
  1234. goto ioerror;
  1235. }
  1236. /* RWD 2007: PEAK chunk is after data chunk in some naff but otherwise legal files,
  1237. so ordinary lseek no good */
  1238. #if defined CDP99 && defined _WIN32
  1239. # ifdef FILE64_WIN
  1240. pos64.QuadPart = 0;
  1241. pos64.LowPart = SetFilePointer(f->fileno, 0L, &pos64.HighPart, FILE_CURRENT);
  1242. if(pos64.LowPart == 0xFFFFFFFF && GetLastError() != NO_ERROR){
  1243. err++;
  1244. goto ioerror;
  1245. }
  1246. else {
  1247. /* WAVE and AIFF have to fit inside unsigned int */
  1248. f->peakchunkoffset = (unsigned int) pos64.QuadPart;
  1249. if(read_peak_lsf(f->fmtchunkEx.Format.nChannels,f)) {
  1250. err++;
  1251. goto ioerror;
  1252. }
  1253. }
  1254. # else
  1255. if((f->peakchunkoffset = SetFilePointer(f->fileno, 0L, NULL, FILE_CURRENT)) == 0xFFFFFFFF
  1256. || read_peak_lsf(f->fmtchunkEx.Format.nChannels,f)) {
  1257. err++;
  1258. goto ioerror;
  1259. }
  1260. # endif
  1261. #else
  1262. if(fgetpos(f->fileno,&f->peakchunkoffset)
  1263. || read_peak_lsf(f->fmtchunkEx.Format.nChannels,f)) {
  1264. err++;
  1265. goto ioerror;
  1266. }
  1267. #endif
  1268. break;
  1269. default:
  1270. #ifdef _DEBUG
  1271. fprintf(stderr,"\nunknown PEAK version!");
  1272. #endif
  1273. free(f->peaks);
  1274. f->peaks = NULL;
  1275. break;
  1276. }
  1277. break;
  1278. case TAG('d','a','t','a'):
  1279. #if defined CDP99 && defined _WIN32
  1280. /* datachunk MUST be within 2GB! */
  1281. if((f->datachunkoffset = SetFilePointer(f->fileno, 0L, NULL, FILE_CURRENT)) == 0xFFFFFFFF)
  1282. {
  1283. err++;
  1284. goto ioerror;
  1285. }
  1286. f->datachunksize = size;
  1287. if(f->fmtchunkEx.Format.wBitsPerSample == 8)
  1288. f->datachunksize *= 2;
  1289. #else
  1290. if(fgetpos(f->fileno,&f->datachunkoffset) )
  1291. {
  1292. err++;
  1293. goto ioerror;
  1294. }
  1295. f->datachunksize = size;
  1296. if(f->fmtchunkEx.Format.wBitsPerSample == 8)
  1297. f->datachunksize *= 2;
  1298. #endif
  1299. /* skip over data chunk; to try to read later chunks */
  1300. size = (size+1)&~1;
  1301. #if defined CDP99 && defined _WIN32
  1302. # ifdef FILE64_WIN
  1303. pos64.QuadPart = (__int64) size;
  1304. pos64.LowPart = SetFilePointer(f->fileno, pos64.LowPart,&pos64.HighPart,FILE_CURRENT);
  1305. if(pos64.LowPart == 0xFFFFFFFF && GetLastError() != NO_ERROR){
  1306. err++;
  1307. goto ioerror;
  1308. }
  1309. # else
  1310. if(SetFilePointer(f->fileno, size, NULL,FILE_CURRENT) == 0xFFFFFFFF)
  1311. {
  1312. err++;
  1313. goto ioerror;
  1314. }
  1315. # endif
  1316. #else
  1317. /* expect >2GB data chunk, so must use fseeko etc */
  1318. POS64(bytepos) = POS64(f->datachunkoffset) + size;
  1319. if(fsetpos(f->fileno, &bytepos))
  1320. {
  1321. err++;
  1322. goto ioerror;
  1323. }
  1324. #endif
  1325. dataseen++;
  1326. break;
  1327. case TAG('c','u','e',' '):
  1328. if((gotsfsyscue = getsfsyscue(f)) < 0) {
  1329. err++;
  1330. goto ioerror;
  1331. }
  1332. break;
  1333. default:
  1334. size = (size+1)&~1;
  1335. /* we trust that only the data chunk will be huge! */
  1336. #if defined CDP99 && defined _WIN32
  1337. if(SetFilePointer(f->fileno, size, NULL,FILE_CURRENT) == 0xFFFFFFFF)
  1338. {
  1339. err++;
  1340. goto ioerror;
  1341. }
  1342. #else
  1343. if(fseek(f->fileno, size, SEEK_CUR) < 0)
  1344. {
  1345. err++;
  1346. goto ioerror;
  1347. }
  1348. #endif
  1349. f->extrachunksizes += size + 2*sizeof(DWORD); //RWD: anonymous chunks - we will copy these one day...
  1350. break;
  1351. }
  1352. }
  1353. /* NOTREACHED */
  1354. ioerror:
  1355. if(fmtseen && dataseen)
  1356. return 0;
  1357. rsferrno = ESFRDERR;
  1358. rsferrstr = "read error (or file too short) reading wav header";
  1359. return 1;
  1360. }
  1361. #if 0
  1362. static int
  1363. wrwavhdr(struct sf_file *f)
  1364. {
  1365. struct cuepoint cue;
  1366. int extra = 0; //RWD CDP97
  1367. #ifdef linux
  1368. fpos_t bytepos = {0};
  1369. #else
  1370. fpos_t bytepos = 0;
  1371. #endif
  1372. WORD cbSize = 0x0000; //RWD for WAVEFORMATEX
  1373. f->mainchunksize = 0; /* we don't know the full size yet! */
  1374. f->extrachunksizes = 0;
  1375. extra = sizeof(WORD);
  1376. if(write_dw_msf(TAG('R','I','F','F'), f)
  1377. ||write_dw_lsf(0, f)
  1378. ||write_dw_msf(TAG('W','A','V','E'), f))
  1379. goto ioerror;
  1380. f->fmtchunkEx.Format.wFormatTag = WAVE_FORMAT_PCM;
  1381. f->fmtchunkEx.Format.nChannels = 1;
  1382. f->fmtchunkEx.Format.nSamplesPerSec = 44100;
  1383. f->fmtchunkEx.Format.nAvgBytesPerSec = 4*44100;
  1384. f->fmtchunkEx.Format.nBlockAlign = 2;
  1385. f->fmtchunkEx.Format.wBitsPerSample = 16;
  1386. if(write_dw_msf(TAG('f','m','t',' '), f)
  1387. ||write_dw_lsf(16 + extra, f) //RWD CDP97: size = 18 to include cbSize field
  1388. #if defined CDP99 && defined _WIN32
  1389. ||((f->fmtchunkoffset = SetFilePointer(f->fileno, 0L, NULL, FILE_CURRENT)) == 0xFFFFFFFF)
  1390. ||write_w_lsf(f->fmtchunkEx.Format.wFormatTag, f)
  1391. ||write_w_lsf(f->fmtchunkEx.Format.nChannels, f)
  1392. ||write_dw_lsf(f->fmtchunkEx.Format.nSamplesPerSec, f)
  1393. ||write_dw_lsf(f->fmtchunkEx.Format.nAvgBytesPerSec, f)
  1394. ||write_w_lsf(f->fmtchunkEx.Format.nBlockAlign, f)
  1395. ||write_w_lsf(f->fmtchunkEx.Format.wBitsPerSample, f)
  1396. ||write_w_lsf(cbSize,f) //RWD , sorry, HAVE to allow for this!
  1397. )
  1398. goto ioerror;
  1399. #else
  1400. ||(fgetpos(f->fileno, &bytepos))
  1401. ||write_w_lsf(f->fmtchunkEx.Format.wFormatTag, f)
  1402. ||write_w_lsf(f->fmtchunkEx.Format.nChannels, f)
  1403. ||write_dw_lsf(f->fmtchunkEx.Format.nSamplesPerSec, f)
  1404. ||write_dw_lsf(f->fmtchunkEx.Format.nAvgBytesPerSec, f)
  1405. ||write_w_lsf(f->fmtchunkEx.Format.nBlockAlign, f)
  1406. ||write_w_lsf(f->fmtchunkEx.Format.wBitsPerSample, f)
  1407. ||write_w_lsf(cbSize,f) //RWD , sorry, HAVE to allow for this!
  1408. )
  1409. goto ioerror;
  1410. f->fmtchunkoffset = bytepos;
  1411. #endif
  1412. /* don't need to put a fact chunk */
  1413. /*
  1414. * add the cue point/note chunk for properties
  1415. */
  1416. //RWD TODO: add switch to skip writing this extra stuff!
  1417. if(write_dw_msf(TAG('c','u','e',' '), f)
  1418. ||write_dw_lsf(sizeof(struct cuepoint) + sizeof(DWORD), f) )
  1419. goto ioerror;
  1420. cue.name = TAG('s','f','i','f');
  1421. cue.position = 0;
  1422. cue.incchunkid = TAG('d','a','t','a');
  1423. cue.chunkoffset = 0;
  1424. cue.blockstart = 0;
  1425. cue.sampleoffset = 0;
  1426. if(write_dw_lsf(1, f) /* one cue point */
  1427. ||write_dw_msf(cue.name, f)
  1428. ||write_dw_lsf(cue.position, f)
  1429. ||write_dw_msf(cue.incchunkid, f)
  1430. ||write_dw_lsf(cue.chunkoffset, f)
  1431. ||write_dw_lsf(cue.blockstart, f)
  1432. ||write_dw_lsf(cue.sampleoffset, f) )
  1433. goto ioerror;
  1434. /*... add a LIST chunk of type 'adtl'... */
  1435. if(write_dw_msf(TAG('L','I','S','T'), f)
  1436. ||write_dw_lsf(sizeof(DWORD) + 3*sizeof(DWORD) + PROPCNKSIZE, f)
  1437. ||write_dw_msf(TAG('a','d','t','l'), f) )
  1438. goto ioerror;
  1439. /* add the property-space note chunk */
  1440. if(write_dw_msf(TAG('n','o','t','e'), f)
  1441. ||write_dw_lsf(sizeof(DWORD) + PROPCNKSIZE, f)
  1442. ||write_dw_msf(TAG('s','f','i','f'), f)
  1443. #if defined CDP99 && defined _WIN32
  1444. ||((f->propoffset = SetFilePointer(f->fileno, 0L, NULL, FILE_CURRENT)) == 0xFFFFFFFF)
  1445. ||SetFilePointer(f->fileno, (long)PROPCNKSIZE,NULL, FILE_CURRENT) == 0xFFFFFFFF )
  1446. goto ioerror;
  1447. #else
  1448. ||fgetpos(f->fileno, &bytepos)
  1449. ||fseek(f->fileno, PROPCNKSIZE, SEEK_CUR) )
  1450. goto ioerror;
  1451. f->propoffset = bytepos;
  1452. #endif
  1453. f->propschanged = 1;
  1454. f->proplim = PROPCNKSIZE;
  1455. /*
  1456. * and add the data chunk
  1457. */
  1458. f->datachunksize = 0;
  1459. if( write_dw_msf(TAG('d','a','t','a'), f)
  1460. ||write_dw_lsf(0, f)
  1461. #if defined CDP99 && defined _WIN32
  1462. ||((f->datachunkoffset = SetFilePointer(f->fileno, 0L, NULL, FILE_CURRENT)) == 0xFFFFFFFF))
  1463. goto ioerror;
  1464. #else
  1465. ||(fgetpos(f->fileno, &bytepos)) )
  1466. goto ioerror;
  1467. # ifndef linux
  1468. f->datachunkoffset = (__int64) POS64(bytepos);
  1469. # else
  1470. POS64(f->datachunkoffset) = POS64(bytepos);
  1471. # endif
  1472. #endif
  1473. return 0;
  1474. /* NOTREACHED */
  1475. ioerror:
  1476. rsferrno = ESFWRERR;
  1477. rsferrstr = "write error writing wav header";
  1478. return 1;
  1479. }
  1480. #endif
  1481. /********** SFSYS98 version ****************
  1482. * this RECEIVES format data from calling function,
  1483. * to create the required header
  1484. */
  1485. static int
  1486. wrwavhdr98(struct sf_file *f, int channels, int srate, int stype)
  1487. {
  1488. struct cuepoint cue;
  1489. int extra = 0;
  1490. int wordsize;
  1491. #ifdef linux
  1492. fpos_t bytepos = {0};
  1493. #else
  1494. fpos_t bytepos = 0;
  1495. #endif
  1496. WORD cbSize = 0x0000; //RWD for WAVEFORMATEX, FLOAT FORMAT ONLY
  1497. f->mainchunksize = 0; /* we don't know the full size yet! */
  1498. f->extrachunksizes = 0;
  1499. //we will not use sffuncs for 24bit files!
  1500. if(stype >= SAMP_MASKED){
  1501. rsferrstr = "this verson cannot write files in requested format";
  1502. return 1;
  1503. }
  1504. //wordsize = (stype == SAMP_FLOAT ? sizeof(float) : sizeof(short));
  1505. wordsize = sampsize[stype];
  1506. if(stype== SAMP_FLOAT)
  1507. extra = sizeof(WORD);
  1508. if(write_dw_msf(TAG('R','I','F','F'), f)
  1509. ||write_dw_lsf(0, f)
  1510. ||write_dw_msf(TAG('W','A','V','E'), f))
  1511. goto ioerror;
  1512. f->fmtchunkEx.Format.wFormatTag = stype == SAMP_FLOAT ? WAVE_FORMAT_IEEE_FLOAT : WAVE_FORMAT_PCM;
  1513. f->fmtchunkEx.Format.nChannels = (unsigned short)channels;
  1514. f->fmtchunkEx.Format.nSamplesPerSec = srate;
  1515. f->fmtchunkEx.Format.nAvgBytesPerSec = wordsize * channels * srate;
  1516. f->fmtchunkEx.Format.nBlockAlign = (unsigned short) ( wordsize * channels);
  1517. //for standard WAVE, we set wBitsPerSample to = validbits
  1518. if(stype==SAMP_2024)
  1519. f->fmtchunkEx.Format.wBitsPerSample = 20;
  1520. else if(stype==SAMP_2432)
  1521. f->fmtchunkEx.Format.wBitsPerSample = 24;
  1522. else
  1523. f->fmtchunkEx.Format.wBitsPerSample = (short)(8 * wordsize);
  1524. //need this for wavupdate98()
  1525. f->fmtchunkEx.Samples.wValidBitsPerSample = f->fmtchunkEx.Format.wBitsPerSample;
  1526. if(write_dw_msf(TAG('f','m','t',' '), f)
  1527. ||write_dw_lsf(16 + extra, f) //RWD CDP97: size = 18 to include cbSize field
  1528. #if defined CDP99 && defined _WIN32
  1529. ||((f->fmtchunkoffset = SetFilePointer(f->fileno, 0L, NULL, FILE_CURRENT)) == 0xFFFFFFFF)
  1530. ||write_w_lsf(f->fmtchunkEx.Format.wFormatTag, f)
  1531. ||write_w_lsf(f->fmtchunkEx.Format.nChannels, f)
  1532. ||write_dw_lsf(f->fmtchunkEx.Format.nSamplesPerSec, f)
  1533. ||write_dw_lsf(f->fmtchunkEx.Format.nAvgBytesPerSec, f)
  1534. ||write_w_lsf(f->fmtchunkEx.Format.nBlockAlign, f)
  1535. ||write_w_lsf(f->fmtchunkEx.Format.wBitsPerSample, f)
  1536. )
  1537. goto ioerror;
  1538. #else
  1539. ||fgetpos(f->fileno,&bytepos)
  1540. ||write_w_lsf(f->fmtchunkEx.Format.wFormatTag, f)
  1541. ||write_w_lsf(f->fmtchunkEx.Format.nChannels, f)
  1542. ||write_dw_lsf(f->fmtchunkEx.Format.nSamplesPerSec, f)
  1543. ||write_dw_lsf(f->fmtchunkEx.Format.nAvgBytesPerSec, f)
  1544. ||write_w_lsf(f->fmtchunkEx.Format.nBlockAlign, f)
  1545. ||write_w_lsf(f->fmtchunkEx.Format.wBitsPerSample, f)
  1546. )
  1547. goto ioerror;
  1548. f->fmtchunkoffset = bytepos;
  1549. #endif
  1550. if(stype == SAMP_FLOAT) {
  1551. if(write_w_lsf(cbSize,f))
  1552. goto ioerror;
  1553. }
  1554. //RWD.6.5.99 ADD the PEAK chunk
  1555. if((f->min_header >= SFILE_PEAKONLY) && f->peaks){
  1556. int i,size;
  1557. DWORD now = 0;
  1558. for(i=0;i < channels; i++){
  1559. f->peaks[i].value = 0.0f;
  1560. f->peaks[i].position = 0;
  1561. }
  1562. size = 2 * sizeof(DWORD) + channels * sizeof(CHPEAK);
  1563. if(write_dw_msf(TAG('P','E','A','K'),f)
  1564. || write_dw_lsf(size,f)
  1565. #if defined CDP99 && defined _WIN32
  1566. || ((f->peakchunkoffset = SetFilePointer(f->fileno,0L,NULL, FILE_CURRENT))== 0xFFFFFFFF)
  1567. || write_dw_lsf(CURRENT_PEAK_VERSION,f)
  1568. || write_dw_lsf(now,f)
  1569. || write_peak_lsf(channels,f))
  1570. goto ioerror;
  1571. #else
  1572. || fgetpos(f->fileno,&bytepos)
  1573. || write_dw_lsf(CURRENT_PEAK_VERSION,f)
  1574. || write_dw_lsf(now,f)
  1575. || write_peak_lsf(channels,f))
  1576. goto ioerror;
  1577. f->peakchunkoffset = bytepos;
  1578. #endif
  1579. }
  1580. if(f->min_header >= SFILE_CDP){
  1581. /*
  1582. * add the cue point/note chunk for properties
  1583. */
  1584. /* RWD Nov 2009: don't need cue for analysis files */
  1585. if(f->min_header==SFILE_CDP){
  1586. //RWD TODO: add switch to skip writing this extra stuff!
  1587. if(write_dw_msf(TAG('c','u','e',' '), f)
  1588. ||write_dw_lsf(sizeof(struct cuepoint) + sizeof(DWORD), f) )
  1589. goto ioerror;
  1590. cue.name = TAG('s','f','i','f');
  1591. cue.position = 0;
  1592. cue.incchunkid = TAG('d','a','t','a');
  1593. cue.chunkoffset = 0;
  1594. cue.blockstart = 0;
  1595. cue.sampleoffset = 0;
  1596. if(write_dw_lsf(1, f) /* one cue point */
  1597. ||write_dw_msf(cue.name, f)
  1598. ||write_dw_lsf(cue.position, f)
  1599. ||write_dw_msf(cue.incchunkid, f)
  1600. ||write_dw_lsf(cue.chunkoffset, f)
  1601. ||write_dw_lsf(cue.blockstart, f)
  1602. ||write_dw_lsf(cue.sampleoffset, f) )
  1603. goto ioerror;
  1604. }
  1605. /*... add a LIST chunk of type 'adtl'... */
  1606. if(write_dw_msf(TAG('L','I','S','T'), f)
  1607. ||write_dw_lsf(sizeof(DWORD) + 3*sizeof(DWORD) + PROPCNKSIZE, f)
  1608. ||write_dw_msf(TAG('a','d','t','l'), f) )
  1609. goto ioerror;
  1610. /* add the property-space note chunk */
  1611. if(write_dw_msf(TAG('n','o','t','e'), f)
  1612. ||write_dw_lsf(sizeof(DWORD) + PROPCNKSIZE, f)
  1613. ||write_dw_msf(TAG('s','f','i','f'), f)
  1614. #if defined CDP99 && defined _WIN32
  1615. ||((f->propoffset = SetFilePointer(f->fileno, 0L, NULL, FILE_CURRENT)) == 0xFFFFFFFF)
  1616. ||SetFilePointer(f->fileno, (long)PROPCNKSIZE,NULL, FILE_CURRENT) == 0xFFFFFFFF )
  1617. goto ioerror;
  1618. #else
  1619. ||fgetpos(f->fileno, &bytepos)
  1620. ||fseek(f->fileno, (long)PROPCNKSIZE, SEEK_CUR) < 0)
  1621. goto ioerror;
  1622. f->propoffset = bytepos;
  1623. #endif
  1624. f->propschanged = 1;
  1625. f->proplim = PROPCNKSIZE;
  1626. }
  1627. /*
  1628. * and add the data chunk
  1629. */
  1630. f->datachunksize = 0;
  1631. if(write_dw_msf(TAG('d','a','t','a'), f)
  1632. ||write_dw_lsf(0, f)
  1633. #if defined CDP99 && defined _WIN32
  1634. ||((f->datachunkoffset = SetFilePointer(f->fileno, 0L, NULL, FILE_CURRENT)) == 0xFFFFFFFF))
  1635. goto ioerror;
  1636. #else
  1637. ||fgetpos(f->fileno, &bytepos))
  1638. goto ioerror;
  1639. f->datachunkoffset = bytepos;
  1640. #endif
  1641. f->header_set = 1; //later, may allow update prior to first write ?
  1642. return 0;
  1643. /* NOTREACHED */
  1644. ioerror:
  1645. rsferrno = ESFWRERR;
  1646. rsferrstr = "write error writing formatted wav header";
  1647. return 1;
  1648. }
  1649. //wave-ex special
  1650. static int
  1651. wrwavex(struct sf_file *f, SFPROPS *props)
  1652. {
  1653. struct cuepoint cue;
  1654. //int extra = 0;
  1655. int wordsize;
  1656. WORD validbits,cbSize = 22;
  1657. GUID guid;
  1658. GUID *pGuid = NULL;
  1659. //int fmtsize = sizeof_WFMTEX;
  1660. fpos_t bytepos;
  1661. POS64(bytepos) = 0;
  1662. f->mainchunksize = 0; /* we don't know the full size yet! */
  1663. f->extrachunksizes = 0;
  1664. POS64(f->propoffset) = 0;
  1665. if(props->chformat==STDWAVE){
  1666. rsferrno = ESFBADPARAM;
  1667. rsferrstr = "std wave format requested for WAVE-EX file!";
  1668. return 1;
  1669. }
  1670. if(props->samptype == FLOAT32){
  1671. pGuid = (GUID *) &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
  1672. }
  1673. else{
  1674. pGuid =(GUID *) &KSDATAFORMAT_SUBTYPE_PCM;
  1675. }
  1676. //NB AIFF and AIFF-C don't support masked formats - just write the required larger container size
  1677. switch(props->samptype){
  1678. case(INT_32):
  1679. case(FLOAT32):
  1680. case(INT2432):
  1681. wordsize = sizeof(/*long*/int);
  1682. break;
  1683. case(INT2424):
  1684. case(INT2024):
  1685. wordsize = 3;
  1686. break;
  1687. case(SHORT16):
  1688. wordsize= sizeof(short);
  1689. break;
  1690. default:
  1691. //don't accept SHORT8, can't deal with INT_MASKED yet - no info in SFPROPS yet!
  1692. rsferrno = ESFBADPARAM;
  1693. rsferrstr = "unsupported sample format requested for WAVE-EX file";
  1694. return 1;
  1695. }
  1696. if(props->samptype==INT2432)
  1697. validbits = (WORD)24;
  1698. else if(props->samptype==INT2024)
  1699. validbits = (WORD)20;
  1700. else
  1701. validbits = (WORD)( 8 * wordsize); //deal with more masks in due course...
  1702. if(write_dw_msf(TAG('R','I','F','F'), f)
  1703. ||write_dw_lsf(0, f)
  1704. ||write_dw_msf(TAG('W','A','V','E'), f))
  1705. goto ioerror;
  1706. /* MC_STD,MC_GENERIC,MC_LCRS,MC_BFMT,MC_DOLBY_5_1,
  1707. MC_SURR_5_0,MC_SURR_7_1,MC_CUBE,MC_WAVE_EX
  1708. */
  1709. f->fmtchunkEx.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
  1710. f->fmtchunkEx.Format.nChannels = (unsigned short) props->chans;
  1711. f->fmtchunkEx.Format.nSamplesPerSec = props->srate;
  1712. f->fmtchunkEx.Format.nAvgBytesPerSec = wordsize * props->chans * props->srate;
  1713. f->fmtchunkEx.Format.nBlockAlign = (unsigned short) ( wordsize * props->chans);
  1714. f->fmtchunkEx.Format.wBitsPerSample = (WORD)(wordsize * 8);
  1715. f->fmtchunkEx.Samples.wValidBitsPerSample = validbits;
  1716. /*RWD Jan 30 2007: permit mask bits < nChans */
  1717. switch(props->chformat){
  1718. case(MC_STD):
  1719. f->fmtchunkEx.dwChannelMask = SPKRS_UNASSIGNED;
  1720. break;
  1721. case(MC_MONO):
  1722. if(props->chans /*!=*/ < 1){ /*RWD Jan 30 2007 */
  1723. rsferrno = ESFBADPARAM;
  1724. rsferrstr = "conflicting channel configuration for WAVE-EX file";
  1725. return 1;
  1726. }
  1727. f->fmtchunkEx.dwChannelMask = SPKRS_MONO;
  1728. break;
  1729. case(MC_STEREO):
  1730. if(props->chans /*!=*/ < 2){
  1731. rsferrno = ESFBADPARAM;
  1732. rsferrstr = "conflicting channel configuration for WAVE-EX file";
  1733. return 1;
  1734. }
  1735. f->fmtchunkEx.dwChannelMask = SPKRS_STEREO;
  1736. break;
  1737. case(MC_QUAD):
  1738. if(props->chans /*!=*/ < 4){
  1739. rsferrno = ESFBADPARAM;
  1740. rsferrstr = "conflicting channel configuration for WAVE-EX file";
  1741. return 1;
  1742. }
  1743. f->fmtchunkEx.dwChannelMask = SPKRS_GENERIC_QUAD;
  1744. break;
  1745. case(MC_BFMT):
  1746. // Nov 2005: now supporting many channel counts for B-Format!
  1747. #ifdef NOTDEF
  1748. if(props->chans != 4){
  1749. rsferrno = ESFBADPARAM;
  1750. rsferrstr = "conflicting channel configuration for WAVE-EX file";
  1751. return 1;
  1752. }
  1753. #endif
  1754. f->fmtchunkEx.dwChannelMask = SPKRS_UNASSIGNED;
  1755. pGuid = props->samptype==FLOAT32 ?(GUID *) &SUBTYPE_AMBISONIC_B_FORMAT_IEEE_FLOAT :(GUID *) &SUBTYPE_AMBISONIC_B_FORMAT_PCM;
  1756. break;
  1757. case(MC_LCRS):
  1758. if(props->chans /*!=*/< 4){
  1759. rsferrno = ESFBADPARAM;
  1760. rsferrstr = "conflicting channel configuration for WAVE-EX file";
  1761. return 1;
  1762. }
  1763. f->fmtchunkEx.dwChannelMask = SPKRS_SURROUND_LCRS;
  1764. break;
  1765. case(MC_DOLBY_5_1):
  1766. if(props->chans /*!=*/ < 6){
  1767. rsferrno = ESFBADPARAM;
  1768. rsferrstr = "conflicting channel configuration for WAVE-EX file";
  1769. return 1;
  1770. }
  1771. f->fmtchunkEx.dwChannelMask = SPKRS_DOLBY5_1;
  1772. break;
  1773. /*March 2008 */
  1774. case(MC_SURR_5_0):
  1775. if(props->chans /*!=*/ < 5){
  1776. rsferrno = ESFBADPARAM;
  1777. rsferrstr = "conflicting channel configuration for WAVE-EX file";
  1778. return 1;
  1779. }
  1780. f->fmtchunkEx.dwChannelMask = SPKRS_SURR_5_0;
  1781. break;
  1782. /* Nov 2013 */
  1783. case(MC_SURR_6_1):
  1784. if(props->chans < 7){
  1785. rsferrno = ESFBADPARAM;
  1786. rsferrstr = "conflicting channel configuration for WAVE-EX file";
  1787. return 1;
  1788. }
  1789. f->fmtchunkEx.dwChannelMask = SPKRS_SURR_6_1;
  1790. break;
  1791. /* OCT 2009 */
  1792. case(MC_SURR_7_1):
  1793. if(props->chans /*!=*/ < 8){
  1794. rsferrno = ESFBADPARAM;
  1795. rsferrstr = "conflicting channel configuration for WAVE-EX file";
  1796. return 1;
  1797. }
  1798. f->fmtchunkEx.dwChannelMask = SPKRS_SURR_7_1;
  1799. break;
  1800. case(MC_CUBE):
  1801. if(props->chans /*!=*/ < 8){
  1802. rsferrno = ESFBADPARAM;
  1803. rsferrstr = "conflicting channel configuration for WAVE-EX file";
  1804. return 1;
  1805. }
  1806. f->fmtchunkEx.dwChannelMask = SPKRS_CUBE;
  1807. break;
  1808. default:
  1809. rsferrno = ESFBADPARAM;
  1810. rsferrstr = "unsupported channel configuration for WAVE-EX file";
  1811. return 1;
  1812. break;
  1813. }
  1814. if(write_dw_msf(TAG('f','m','t',' '), f)
  1815. ||write_dw_lsf(sizeof_WFMTEX, f) //RWD CDP97: size = 18 to include cbSize field
  1816. #if defined CDP99 && defined _WIN32
  1817. ||((f->fmtchunkoffset = SetFilePointer(f->fileno, 0L, NULL, FILE_CURRENT)) == 0xFFFFFFFF)
  1818. ||write_w_lsf(f->fmtchunkEx.Format.wFormatTag, f)
  1819. ||write_w_lsf(f->fmtchunkEx.Format.nChannels, f)
  1820. ||write_dw_lsf(f->fmtchunkEx.Format.nSamplesPerSec, f)
  1821. ||write_dw_lsf(f->fmtchunkEx.Format.nAvgBytesPerSec, f)
  1822. ||write_w_lsf(f->fmtchunkEx.Format.nBlockAlign, f)
  1823. ||write_w_lsf(f->fmtchunkEx.Format.wBitsPerSample, f)
  1824. ||write_w_lsf(cbSize,f)
  1825. )
  1826. goto ioerror;
  1827. #else
  1828. ||fgetpos(f->fileno, &bytepos)
  1829. ||write_w_lsf(f->fmtchunkEx.Format.wFormatTag, f)
  1830. ||write_w_lsf(f->fmtchunkEx.Format.nChannels, f)
  1831. ||write_dw_lsf(f->fmtchunkEx.Format.nSamplesPerSec, f)
  1832. ||write_dw_lsf(f->fmtchunkEx.Format.nAvgBytesPerSec, f)
  1833. ||write_w_lsf(f->fmtchunkEx.Format.nBlockAlign, f)
  1834. ||write_w_lsf(f->fmtchunkEx.Format.wBitsPerSample, f)
  1835. ||write_w_lsf(cbSize,f)
  1836. )
  1837. goto ioerror;
  1838. f->fmtchunkoffset = bytepos;
  1839. #endif
  1840. //don't need fact chunk unless actually a compressed format...
  1841. guid = *pGuid;
  1842. #ifdef MSBFIRST
  1843. guid.Data1 = REVDWBYTES(guid.Data1);
  1844. guid.Data2 = REVWBYTES(guid.Data2);
  1845. guid.Data3 = REVWBYTES(guid.Data3);
  1846. #endif
  1847. if(write_w_lsf(f->fmtchunkEx.Samples.wValidBitsPerSample,f)
  1848. || write_dw_lsf(f->fmtchunkEx.dwChannelMask,f)
  1849. || dowrite(f,(char *) &guid,sizeof(GUID)) /* RWD NB deal with byte-reversal sometime! */
  1850. )
  1851. goto ioerror;
  1852. // ADD the PEAK chunk
  1853. if((f->min_header>=SFILE_PEAKONLY) && f->peaks){
  1854. int i,size;
  1855. DWORD now = 0;
  1856. for(i=0;i < props->chans; i++){
  1857. f->peaks[i].value = 0.0f;
  1858. f->peaks[i].position = 0;
  1859. }
  1860. size = 2 * sizeof(DWORD) + props->chans * sizeof(CHPEAK);
  1861. if(write_dw_msf(TAG('P','E','A','K'),f)
  1862. || write_dw_lsf(size,f)
  1863. #if defined CDP99 && defined _WIN32
  1864. || ((f->peakchunkoffset = SetFilePointer(f->fileno,0L,NULL, FILE_CURRENT))== 0xFFFFFFFF)
  1865. || write_dw_lsf(CURRENT_PEAK_VERSION,f)
  1866. || write_dw_lsf(now,f)
  1867. || write_peak_lsf(props->chans,f))
  1868. goto ioerror;
  1869. #else
  1870. || fgetpos(f->fileno, &bytepos)
  1871. || write_dw_lsf(CURRENT_PEAK_VERSION,f)
  1872. || write_dw_lsf(now,f)
  1873. || write_peak_lsf(props->chans,f))
  1874. goto ioerror;
  1875. f->peakchunkoffset = bytepos;
  1876. #endif
  1877. }
  1878. if(f->min_header>=SFILE_CDP){
  1879. /*
  1880. * add the cue point/note chunk for properties
  1881. */
  1882. //RWD TODO: add switch to skip writing this extra stuff!
  1883. if(write_dw_msf(TAG('c','u','e',' '), f)
  1884. ||write_dw_lsf(sizeof(struct cuepoint) + sizeof(DWORD), f) )
  1885. goto ioerror;
  1886. cue.name = TAG('s','f','i','f');
  1887. cue.position = 0;
  1888. cue.incchunkid = TAG('d','a','t','a');
  1889. cue.chunkoffset = 0;
  1890. cue.blockstart = 0;
  1891. cue.sampleoffset = 0;
  1892. if(write_dw_lsf(1, f) /* one cue point */
  1893. ||write_dw_msf(cue.name, f)
  1894. ||write_dw_lsf(cue.position, f)
  1895. ||write_dw_msf(cue.incchunkid, f)
  1896. ||write_dw_lsf(cue.chunkoffset, f)
  1897. ||write_dw_lsf(cue.blockstart, f)
  1898. ||write_dw_lsf(cue.sampleoffset, f) )
  1899. goto ioerror;
  1900. /*... add a LIST chunk of type 'adtl'... */
  1901. if(write_dw_msf(TAG('L','I','S','T'), f)
  1902. ||write_dw_lsf(sizeof(DWORD) + 3*sizeof(DWORD) + PROPCNKSIZE, f)
  1903. ||write_dw_msf(TAG('a','d','t','l'), f) )
  1904. goto ioerror;
  1905. /* add the property-space note chunk */
  1906. if(write_dw_msf(TAG('n','o','t','e'), f)
  1907. ||write_dw_lsf(sizeof(DWORD) + PROPCNKSIZE, f)
  1908. ||write_dw_msf(TAG('s','f','i','f'), f)
  1909. #if defined CDP99 && defined _WIN32
  1910. ||((f->propoffset = SetFilePointer(f->fileno, 0L, NULL, FILE_CURRENT)) == 0xFFFFFFFF)
  1911. ||SetFilePointer(f->fileno, (long)PROPCNKSIZE,NULL, FILE_CURRENT) == 0xFFFFFFFF )
  1912. goto ioerror;
  1913. #else
  1914. ||fgetpos(f->fileno, &bytepos)
  1915. ||fseek(f->fileno, (long)PROPCNKSIZE, SEEK_CUR) < 0)
  1916. goto ioerror;
  1917. f->propoffset = bytepos;
  1918. #endif
  1919. f->propschanged = 1;
  1920. f->proplim = PROPCNKSIZE;
  1921. }
  1922. /*
  1923. * and add the data chunk
  1924. */
  1925. f->datachunksize = 0;
  1926. if(write_dw_msf(TAG('d','a','t','a'), f)
  1927. ||write_dw_lsf(0, f)
  1928. #if defined CDP99 && defined _WIN32
  1929. ||((f->datachunkoffset = SetFilePointer(f->fileno, 0L, NULL, FILE_CURRENT)) == 0xFFFFFFFF))
  1930. goto ioerror;
  1931. #else
  1932. ||fgetpos(f->fileno, &bytepos))
  1933. goto ioerror;
  1934. f->datachunkoffset = bytepos;
  1935. #endif
  1936. f->header_set = 1; //later, may allow update prior to first write ?
  1937. return 0;
  1938. /* NOTREACHED */
  1939. ioerror:
  1940. rsferrno = ESFWRERR;
  1941. rsferrstr = "error writing wav_ex header";
  1942. return 1;
  1943. }
  1944. /*
  1945. * aiff routines
  1946. */
  1947. //RWD98 BUG, SOMEWHERE: THIS READS THE SSND CHUNK, AND GETS SIZE = REMAIN; BUT REMAIN SHOULD BE SIZE + 8
  1948. // SO, EITHER BUG IN THIS CODE, OR IN WRAIFFHDR... SO CANNOT USE WINDOWS DWORD 'COS UNSIGNED....
  1949. //RWD.6.99 NOTE: some tests require the Fomat field to be set, even though this is aiff
  1950. //RWD.7.99: accept masked AIFF formats: container size is always next intergral number of bytes
  1951. static int
  1952. rdaiffhdr(struct sf_file *f)
  1953. {
  1954. DWORD /*long */ tag, size = 0, remain = 0, appltag; //RWD.04.98 can't be unsigned until the size anomalies are resolved
  1955. DWORD peaktime; /* RWD Jan 2005 */
  1956. int commseen = 0, ssndseen = 0;
  1957. DWORD numsampleframes;
  1958. DWORD ssnd_offset, ssnd_blocksize;
  1959. fpos_t bytepos;
  1960. POS64(bytepos) = 0;
  1961. char *propspace;
  1962. DWORD peak_version;
  1963. // WARNING! The file can have the wrong size (e.g. from sox)
  1964. if(read_dw_msf(&tag, f)
  1965. ||read_dw_msf(&remain, f)
  1966. ||tag != TAG('F','O','R','M')) {
  1967. rsferrno = ESFNOTFOUND;
  1968. rsferrstr = "File is not an AIFF file";
  1969. return 1;
  1970. }
  1971. if(remain < 3*sizeof(DWORD)) {
  1972. rsferrno = ESFNOTFOUND;
  1973. rsferrstr = "File data size is too small";
  1974. return 1;
  1975. }
  1976. if(read_dw_msf(&tag, f)
  1977. ||tag != TAG('A','I','F','F')) {
  1978. rsferrno = ESFNOTFOUND;
  1979. rsferrstr = "File does not include an AIFF form";
  1980. return 1;
  1981. }
  1982. f->mainchunksize = remain;
  1983. f->extrachunksizes = 0;
  1984. POS64(f->propoffset) = -1;
  1985. f->aiffchunks = 0;
  1986. remain -= sizeof(DWORD);
  1987. while(remain > 0) {
  1988. if(read_dw_msf(&tag, f)
  1989. ||read_dw_msf(&size,f)){
  1990. if(ssndseen && commseen){ //RWD accept the file anyway if we have enough
  1991. remain = 0;
  1992. break;
  1993. }
  1994. else
  1995. goto ioerror;
  1996. }
  1997. remain -= 2*sizeof(DWORD);
  1998. switch(tag) {
  1999. case TAG('C','O','M','M'):
  2000. if(size != 18) {
  2001. rsferrno = ESFNOTFOUND;
  2002. rsferrstr = "AIFF COMM chunk of incorrect size";
  2003. return 1;
  2004. }
  2005. #if defined CDP99 && defined _WIN32
  2006. if((f->fmtchunkoffset = SetFilePointer(f->fileno, 0L, NULL, FILE_CURRENT)) == 0xFFFFFFFF
  2007. ||read_w_msf(&f->fmtchunkEx.Format.nChannels, f)
  2008. ||read_dw_msf(&numsampleframes, f)
  2009. ||read_w_msf(&f->fmtchunkEx.Format.wBitsPerSample, f)
  2010. ||read_ex_todw(&f->fmtchunkEx.Format.nSamplesPerSec, f) )
  2011. goto ioerror;
  2012. #else
  2013. if(fgetpos(f->fileno, &bytepos)
  2014. ||read_w_msf(&f->fmtchunkEx.Format.nChannels, f)
  2015. ||read_dw_msf(&numsampleframes, f)
  2016. ||read_w_msf(&f->fmtchunkEx.Format.wBitsPerSample, f)
  2017. ||read_ex_todw(&f->fmtchunkEx.Format.nSamplesPerSec, f) )
  2018. goto ioerror;
  2019. f->fmtchunkoffset = bytepos;
  2020. #endif
  2021. /*RWD Trevor uses srate of zero for envel files! */
  2022. /* nSamples... is unsigned anyway, so dont bother with this one any more... */
  2023. #ifdef NOTDEF
  2024. if(f->fmtchunkEx.Format.nSamplesPerSec < 0) {
  2025. rsferrno = ESFNOTFOUND;
  2026. rsferrstr = "Unknown AIFF sample rate";
  2027. return 1;
  2028. }
  2029. #endif
  2030. /*RWD.7.99 we now read 32bit in standard AIFF as LONGS
  2031. * we rely on the extra properties to tell if it's an analysis file */
  2032. f->fmtchunkEx.Format.wFormatTag = WAVE_FORMAT_PCM;
  2033. //fill in other info
  2034. f->fmtchunkEx.Samples.wValidBitsPerSample = f->fmtchunkEx.Format.wBitsPerSample;
  2035. //we have to deduce blockalign, and hence containersize
  2036. switch(f->fmtchunkEx.Samples.wValidBitsPerSample){
  2037. case(32):
  2038. f->fmtchunkEx.Format.nBlockAlign = sizeof(/*long*/int);
  2039. break;
  2040. case(20):
  2041. case(24):
  2042. f->fmtchunkEx.Format.nBlockAlign = 3;
  2043. break;
  2044. case(16):
  2045. f->fmtchunkEx.Format.nBlockAlign = sizeof(short);
  2046. break;
  2047. case(8):
  2048. f->fmtchunkEx.Format.nBlockAlign = sizeof(char);
  2049. break;
  2050. default:
  2051. rsferrno = ESFNOTFOUND;
  2052. rsferrstr = "unsupported sample size in aiff file";
  2053. return 1;
  2054. }
  2055. f->fmtchunkEx.Format.nBlockAlign *= f->fmtchunkEx.Format.nChannels;
  2056. //should do avgBytesPerSec too...
  2057. f->fmtchunkEx.dwChannelMask = 0;
  2058. remain -= 18;
  2059. commseen++;
  2060. break;
  2061. //RWD.5.99 read PEAK chunk
  2062. case TAG('P','E','A','K'):
  2063. f->peaks = (CHPEAK *) calloc(f->fmtchunkEx.Format.nChannels,sizeof(CHPEAK));
  2064. if(f->peaks == NULL){
  2065. rsferrno = ESFNOMEM;
  2066. rsferrstr = "No memory for peak data";
  2067. return 1;
  2068. }
  2069. if(read_dw_msf(&peak_version,f))
  2070. goto ioerror;
  2071. switch(peak_version){
  2072. case(CURRENT_PEAK_VERSION):
  2073. if(read_dw_msf(&peaktime,f)) /* RWD Jan 2005 for DevCPP */
  2074. goto ioerror;
  2075. f->peaktime = (time_t) peaktime;
  2076. #if defined CDP99 && defined _WIN32
  2077. if((f->peakchunkoffset = SetFilePointer(f->fileno, 0L, NULL, FILE_CURRENT)) == 0xFFFFFFFF
  2078. || read_peak_msf(f->fmtchunkEx.Format.nChannels,f))
  2079. goto ioerror;
  2080. #else
  2081. if(fgetpos(f->fileno, &bytepos)
  2082. || read_peak_msf(f->fmtchunkEx.Format.nChannels,f))
  2083. goto ioerror;
  2084. f->peakchunkoffset = bytepos;
  2085. #endif
  2086. break;
  2087. default:
  2088. #ifdef _DEBUG
  2089. fprintf(stderr,"\nunknown PEAK version!");
  2090. #endif
  2091. free(f->peaks);
  2092. f->peaks = NULL;
  2093. break;
  2094. }
  2095. remain -= 2 * sizeof(DWORD) + (sizeof(CHPEAK) * f->fmtchunkEx.Format.nChannels);
  2096. break;
  2097. case TAG('S','S','N','D'):
  2098. if(read_dw_msf(&ssnd_offset, f)
  2099. ||read_dw_msf(&ssnd_blocksize, f)
  2100. #if defined CDP99 && defined _WIN32
  2101. ||(f->datachunkoffset = SetFilePointer(f->fileno, 0L,NULL,FILE_CURRENT)) ==0xFFFFFFFF
  2102. || SetFilePointer(f->fileno, ((size+1)&~1) - 2 *sizeof(DWORD),NULL,FILE_CURRENT) ==0xFFFFFFFF)
  2103. goto ioerror;
  2104. #else
  2105. || fgetpos(f->fileno, &bytepos))
  2106. goto ioerror;
  2107. f->datachunkoffset = bytepos;
  2108. POS64(bytepos) += ((size+1)&~1) - 2 *sizeof(DWORD);
  2109. /*fseek(f->fileno, ((size+1)&~1) - 2 *sizeof(DWORD), SEEK_CUR) < 0) */
  2110. if(fsetpos(f->fileno,&bytepos))
  2111. goto ioerror;
  2112. #endif
  2113. remain -= 2 * sizeof(DWORD); /* RWD Apr 2011 need this */
  2114. /* RWD MAR 2015 eliminate warning, ssnd_offset is unsigned */
  2115. if(/* ssnd_offset < 0 || */ ssnd_offset > ssnd_blocksize) {
  2116. rsferrno = ESFNOTFOUND;
  2117. rsferrstr = "Funny offset in AIFF SSND chunk";
  2118. return 1;
  2119. }
  2120. POS64(f->datachunkoffset) += ssnd_offset;
  2121. ssndseen++;
  2122. remain -= (size+1)&~1; //RWD98 BUG!!! remain can get less than size...
  2123. break;
  2124. case 0:
  2125. rsferrno = ESFNOTFOUND;
  2126. rsferrstr = "Illegal zero tag in aiff chunk";
  2127. return 1;
  2128. case TAG('A','P','P','L'):
  2129. if(size < sizeof(DWORD)
  2130. ||read_dw_msf(&appltag,f) )
  2131. goto ioerror;
  2132. if(appltag == TAG('s','f','i','f')) {
  2133. if(POS64(f->propoffset) >= 0
  2134. ||(propspace = (char *) malloc(size - sizeof(DWORD))) == 0
  2135. #if defined CDP99 && defined _WIN32
  2136. ||(f->propoffset = SetFilePointer(f->fileno, 0L,NULL,FILE_CURRENT))==0xFFFFFFFF
  2137. ||doread(f, propspace, size-sizeof(DWORD)) )
  2138. goto ioerror;
  2139. #else
  2140. ||fgetpos(f->fileno, &bytepos)
  2141. ||doread(f, propspace, size-sizeof(DWORD)) )
  2142. goto ioerror;
  2143. POS64(f->propoffset) = POS64(bytepos);
  2144. #endif
  2145. f->proplim = size - sizeof(DWORD);
  2146. parseprops(f, propspace);
  2147. if(size&1)
  2148. doread(f, propspace, 1);
  2149. free(propspace);
  2150. break;
  2151. } else {
  2152. #if defined CDP99 && defined _WIN32
  2153. if(SetFilePointer(f->fileno,-4L,NULL,FILE_CURRENT) == 0xFFFFFFFF)
  2154. #else
  2155. if(fseek(f->fileno, -4L, SEEK_CUR) < 0)
  2156. #endif
  2157. goto ioerror;
  2158. }
  2159. /* FALLTHROUGH */
  2160. default:
  2161. /* RWD MAR 2015: size is unsigned, eliminate warning! */
  2162. #ifdef NOTDEF
  2163. if(size < 0 /* || size > 100*1024 */) { /* RWD Apr 2011 */
  2164. rsferrno = ESFNOTFOUND;
  2165. rsferrstr = "Silly size for unknown AIFF chunk";
  2166. return 1;
  2167. }
  2168. #endif
  2169. if(ssndseen) {
  2170. struct aiffchunk **cpp, *cp;
  2171. for(cpp = &f->aiffchunks; *cpp != 0; cpp = &(*cpp)->next)
  2172. ;
  2173. if((*cpp = cp = ALLOC(struct aiffchunk)) == 0
  2174. ||(cp->buf = (char *) malloc((size+1)&~1)) == 0) {
  2175. rsferrno = ESFNOMEM;
  2176. rsferrstr = "No memory for aiff chunk storage";
  2177. return 1;
  2178. }
  2179. cp->tag = tag;
  2180. cp->size = size;
  2181. cp->next = 0;
  2182. #if defined CDP99 && defined _WIN32
  2183. if((cp->offset = SetFilePointer(f->fileno,0L,NULL,FILE_CURRENT)) == 0xFFFFFFFF
  2184. ||doread(f, cp->buf, (size+1)&~1))
  2185. goto ioerror;
  2186. #else
  2187. if(fgetpos(f->fileno,&bytepos)
  2188. ||doread(f, cp->buf, (size+1)&~1))
  2189. goto ioerror;
  2190. cp->offset = bytepos;
  2191. #endif
  2192. } else {
  2193. #if defined CDP99 && defined _WIN32
  2194. if(SetFilePointer(f->fileno,(long)((size+1)&~1),NULL,FILE_CURRENT) == 0xFFFFFFFF)
  2195. #else
  2196. if(fseeko(f->fileno, (size+1)&~1, SEEK_CUR) < 0)
  2197. #endif
  2198. goto ioerror;
  2199. }
  2200. f->extrachunksizes += ((size+1)&~1) + 2*sizeof(DWORD);
  2201. remain -= (size+1)&~1;
  2202. break;
  2203. }
  2204. }
  2205. if(!commseen) {
  2206. rsferrno = ESFNOTFOUND;
  2207. rsferrstr = "AIFF format error: no COMM chunk found";
  2208. return 1;
  2209. }
  2210. if(!ssndseen) {
  2211. rsferrno = ESFNOTFOUND;
  2212. rsferrstr = "AIFF format error: no SSND chunk found";
  2213. return 1;
  2214. }
  2215. f->datachunksize = numsampleframes * f->fmtchunkEx.Format.nChannels;
  2216. switch(f->fmtchunkEx.Format.wBitsPerSample) {
  2217. case 32: /* floats */
  2218. f->datachunksize *= 4;
  2219. break;
  2220. case 20:
  2221. case 24:
  2222. f->datachunksize *= 3;
  2223. break;
  2224. case 16: /* shorts */
  2225. f->datachunksize *= 2;
  2226. break;
  2227. case 8: /* byte -> short mappping */
  2228. f->datachunksize *= 2; /* looks like short samples! */
  2229. break;
  2230. default:
  2231. rsferrno = ESFNOTFOUND;
  2232. rsferrstr = "can't open aiff file - unsupported wordsize";
  2233. return 1;
  2234. }
  2235. #if defined CDP99 && defined _WIN32
  2236. if(SetFilePointer(f->fileno,f->datachunkoffset,NULL,FILE_BEGIN)==0xFFFFFFFF)
  2237. #else
  2238. bytepos = f->datachunkoffset;
  2239. if(fsetpos(f->fileno, &bytepos) < 0)
  2240. #endif
  2241. goto ioerror;
  2242. return 0;
  2243. /* NOTREACHED */
  2244. ioerror:
  2245. rsferrno = ESFRDERR;
  2246. rsferrstr = "read error (or file too short) reading AIFF header";
  2247. return 1;
  2248. }
  2249. /*AIF-C*/
  2250. #define AIFC_VERSION_1 (0xA2805140)
  2251. static int
  2252. rdaifchdr(struct sf_file *f)
  2253. {
  2254. DWORD tag, size = 0, remain = 0, appltag;
  2255. int commseen = 0, ssndseen = 0,fmtverseen = 0;
  2256. DWORD numsampleframes, aifcver,ID_compression;
  2257. DWORD ssnd_offset, ssnd_blocksize;
  2258. char *propspace;
  2259. DWORD peak_version;
  2260. DWORD peaktime;
  2261. fpos_t bytepos;
  2262. if(read_dw_msf(&tag, f)
  2263. ||read_dw_msf(&remain, f)
  2264. ||tag != TAG('F','O','R','M')) {
  2265. rsferrno = ESFNOTFOUND;
  2266. rsferrstr = "File is not an AIFF file";
  2267. return 1;
  2268. }
  2269. if(remain < 3*sizeof(DWORD)) {
  2270. rsferrno = ESFNOTFOUND;
  2271. rsferrstr = "File data size is too small";
  2272. return 1;
  2273. }
  2274. if(read_dw_msf(&tag, f)
  2275. ||tag != TAG('A','I','F','C')) {
  2276. rsferrno = ESFNOTFOUND;
  2277. rsferrstr = "File does not include an AIFC form";
  2278. return 1;
  2279. }
  2280. f->mainchunksize = remain;
  2281. f->extrachunksizes = 0;
  2282. POS64(f->propoffset) = -1;
  2283. f->aiffchunks = 0;
  2284. //start by assuming integer format:
  2285. f->fmtchunkEx.Format.wFormatTag = WAVE_FORMAT_PCM;
  2286. remain -= sizeof(DWORD);
  2287. while(remain > 0) {
  2288. if(read_dw_msf(&tag, f)
  2289. ||read_dw_msf(&size,f)){
  2290. if(ssndseen && commseen){ //RWD accept the file anyway if we have enough
  2291. remain = 0;
  2292. break;
  2293. }
  2294. else
  2295. goto ioerror;
  2296. }
  2297. remain -= 2*sizeof(DWORD);
  2298. switch(tag) {
  2299. case TAG('F','V','E','R'):
  2300. if(size != 4){
  2301. rsferrno = ESFNOTFOUND;
  2302. rsferrstr = "bad aif-c FVER chunk";
  2303. return 1;
  2304. }
  2305. if(read_dw_msf(&aifcver,f) || aifcver != AIFC_VERSION_1){
  2306. rsferrno = ESFNOTFOUND;
  2307. rsferrstr = "bad aif-c Version";
  2308. return 1;
  2309. }
  2310. remain -= sizeof(DWORD);
  2311. fmtverseen++;
  2312. break;
  2313. case TAG('C','O','M','M'):
  2314. if(size < 22) {
  2315. rsferrno = ESFNOTFOUND;
  2316. rsferrstr = "AIFC COMM chunk of incorrect size";
  2317. return 1;
  2318. }
  2319. #if defined CDP99 && defined _WIN32
  2320. if((f->fmtchunkoffset = SetFilePointer(f->fileno, 0L, NULL, FILE_CURRENT)) == 0xFFFFFFFF
  2321. ||read_w_msf(&f->fmtchunkEx.Format.nChannels, f)
  2322. ||read_dw_msf(&numsampleframes, f)
  2323. ||read_w_msf(&f->fmtchunkEx.Format.wBitsPerSample, f)
  2324. ||read_ex_todw(&f->fmtchunkEx.Format.nSamplesPerSec, f) )
  2325. goto ioerror;
  2326. #else
  2327. if(fgetpos(f->fileno, &bytepos)
  2328. ||read_w_msf(&f->fmtchunkEx.Format.nChannels, f)
  2329. ||read_dw_msf(&numsampleframes, f)
  2330. ||read_w_msf(&f->fmtchunkEx.Format.wBitsPerSample, f)
  2331. ||read_ex_todw(&f->fmtchunkEx.Format.nSamplesPerSec, f) )
  2332. goto ioerror;
  2333. f->fmtchunkoffset = bytepos;
  2334. #endif
  2335. /*RWD: Trevor uses srate of zero for envel files! */
  2336. /* RWD MAR 2015: so elimianet code to avoid warning, as above */
  2337. #ifdef NOTDEF
  2338. if(f->fmtchunkEx.Format.nSamplesPerSec < 0) {
  2339. rsferrno = ESFNOTFOUND;
  2340. rsferrstr = "Unknown AIFC sample rate";
  2341. return 1;
  2342. }
  2343. #endif
  2344. if(read_dw_msf(&ID_compression,f))
  2345. goto ioerror;
  2346. if( !(
  2347. (ID_compression == TAG('N','O','N','E'))
  2348. || (ID_compression == TAG('F','L','3','2')) //Csound
  2349. || (ID_compression == TAG('f','l','3','2')) //Apple
  2350. /* used in Steinberg 24bit SDIR files */
  2351. || (ID_compression == TAG('i','n','2','4'))
  2352. )){
  2353. rsferrno = ESFNOTFOUND;
  2354. rsferrstr = "Unknown AIFC compression type";
  2355. return 1;
  2356. }
  2357. //set sample type in sfinfo
  2358. if((ID_compression== TAG('F','L','3','2'))
  2359. || ID_compression == TAG('f','l','3','2')){
  2360. /*Nov 2001: F***** Quicktime writes size = 16, for floats! */
  2361. if(f->fmtchunkEx.Format.wBitsPerSample != 32){
  2362. if(f->fmtchunkEx.Format.wBitsPerSample != 16){
  2363. rsferrno = ESFNOTFOUND;
  2364. rsferrstr = "error in AIFC header: samples not 32bit in floats file ";
  2365. return 1;
  2366. }
  2367. else
  2368. f->fmtchunkEx.Format.wBitsPerSample = 32;
  2369. }
  2370. f->fmtchunkEx.Format.wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
  2371. }
  2372. /* RWD 06/01/09 precautionary, to validate 'in24' 24bit files */
  2373. if(ID_compression == TAG('i','n','2','4')) {
  2374. if(f->fmtchunkEx.Format.wBitsPerSample != 24){
  2375. rsferrstr = "error in AIFC header: sample size not 24bit in <in24> file ";
  2376. return 1;
  2377. }
  2378. }
  2379. //no ambiguity here with 32bit format.
  2380. //fill in other info
  2381. f->fmtchunkEx.Samples.wValidBitsPerSample = f->fmtchunkEx.Format.wBitsPerSample;
  2382. f->fmtchunkEx.dwChannelMask = 0;
  2383. //we have to deduce blockalign, and hence containersize
  2384. switch(f->fmtchunkEx.Samples.wValidBitsPerSample){
  2385. case(32):
  2386. f->fmtchunkEx.Format.nBlockAlign = sizeof(/*long*/int);
  2387. break;
  2388. case(20):
  2389. case(24):
  2390. f->fmtchunkEx.Format.nBlockAlign = 3;
  2391. break;
  2392. case(16):
  2393. f->fmtchunkEx.Format.nBlockAlign = sizeof(short);
  2394. break;
  2395. case(8):
  2396. f->fmtchunkEx.Format.nBlockAlign = sizeof(char);
  2397. break;
  2398. default:
  2399. rsferrno = ESFNOTFOUND;
  2400. rsferrstr = "unsupported sample size in aiff file";
  2401. return 1;
  2402. }
  2403. f->fmtchunkEx.Format.nBlockAlign *= f->fmtchunkEx.Format.nChannels;
  2404. //should do avgBytesPerSec too...
  2405. /*RWD 23:10:2000 can get odd sizes... */
  2406. //skip past pascal string
  2407. #if defined CDP99 && defined _WIN32
  2408. if(SetFilePointer(f->fileno, ((size+1)&~1) - 22,NULL,FILE_CURRENT) ==0xFFFFFFFF)
  2409. #else
  2410. if(fseek(f->fileno,((size+1)&~1) - 22,SEEK_CUR) < 0)
  2411. #endif
  2412. goto ioerror;
  2413. remain -= (size+1)&~1;
  2414. commseen++;
  2415. break;
  2416. //RWD.5.99 read PEAK chunk
  2417. case TAG('P','E','A','K'):
  2418. f->peaks = (CHPEAK *) calloc(f->fmtchunkEx.Format.nChannels,sizeof(CHPEAK));
  2419. if(f->peaks == NULL){
  2420. rsferrno = ESFNOMEM;
  2421. rsferrstr = "No memory for peak data";
  2422. return 1;
  2423. }
  2424. if(read_dw_msf(&peak_version,f))
  2425. goto ioerror;
  2426. switch(peak_version){
  2427. case(CURRENT_PEAK_VERSION):
  2428. if(read_dw_msf(&peaktime,f))
  2429. goto ioerror;
  2430. f->peaktime = (time_t) peaktime;
  2431. #if defined CDP99 && defined _WIN32
  2432. if((f->peakchunkoffset = SetFilePointer(f->fileno, 0L, NULL, FILE_CURRENT)) == 0xFFFFFFFF
  2433. || read_peak_msf(f->fmtchunkEx.Format.nChannels,f))
  2434. goto ioerror;
  2435. #else
  2436. if(fgetpos(f->fileno, &bytepos)
  2437. || read_peak_msf(f->fmtchunkEx.Format.nChannels,f))
  2438. goto ioerror;
  2439. f->peakchunkoffset = bytepos;
  2440. #endif
  2441. break;
  2442. default:
  2443. #ifdef _DEBUG
  2444. fprintf(stderr,"\nunknown PEAK version!");
  2445. #endif
  2446. free(f->peaks);
  2447. f->peaks = NULL;
  2448. break;
  2449. }
  2450. remain -= 2 * sizeof(DWORD) + (sizeof(CHPEAK) * f->fmtchunkEx.Format.nChannels);
  2451. break;
  2452. case TAG('S','S','N','D'):
  2453. if(read_dw_msf(&ssnd_offset, f)
  2454. ||read_dw_msf(&ssnd_blocksize, f)
  2455. #if defined CDP99 && defined _WIN32
  2456. ||(f->datachunkoffset = SetFilePointer(f->fileno, 0L,NULL,FILE_CURRENT)) ==0xFFFFFFFF
  2457. || SetFilePointer(f->fileno, ((size+1)&~1) - 2 *sizeof(DWORD),NULL,FILE_CURRENT) ==0xFFFFFFFF)
  2458. goto ioerror;
  2459. if(ssnd_offset < 0 || ssnd_offset > ssnd_blocksize) {
  2460. rsferrno = ESFNOTFOUND;
  2461. rsferrstr = "Funny offset in AIFC SSND chunk";
  2462. return 1;
  2463. }
  2464. f->datachunkoffset += ssnd_offset;
  2465. #else
  2466. ||fgetpos(f->fileno, &bytepos) )
  2467. goto ioerror;
  2468. f->datachunkoffset = bytepos;
  2469. POS64(bytepos) = ((size+1)&~1) - 2 *sizeof(DWORD);
  2470. if(fseeko(f->fileno,POS64(bytepos), SEEK_CUR) < 0)
  2471. goto ioerror;
  2472. /* RWD MAR 2015 ssnd_offset unsigned, eliminate compiler warning */
  2473. if(/* ssnd_offset < 0 || */ ssnd_offset > ssnd_blocksize) {
  2474. rsferrno = ESFNOTFOUND;
  2475. rsferrstr = "Funny offset in AIFC SSND chunk";
  2476. return 1;
  2477. }
  2478. POS64(f->datachunkoffset) += ssnd_offset;
  2479. #endif
  2480. ssndseen++;
  2481. remain -= (size+1)&~1; //RWD98 BUG!!! remain can get less than size...
  2482. break;
  2483. case 0:
  2484. rsferrno = ESFNOTFOUND;
  2485. rsferrstr = "Illegal zero tag in aifc chunk";
  2486. return 1;
  2487. case TAG('A','P','P','L'):
  2488. if(size < sizeof(DWORD)
  2489. ||read_dw_msf(&appltag,f) )
  2490. goto ioerror;
  2491. if(appltag == TAG('s','f','i','f')) {
  2492. if(POS64(f->propoffset) >= 0
  2493. ||(propspace = (char *) malloc(size - sizeof(DWORD))) == 0
  2494. #if defined CDP99 && defined _WIN32
  2495. ||(f->propoffset = SetFilePointer(f->fileno, 0L,NULL,FILE_CURRENT))==0xFFFFFFFF
  2496. ||doread(f, propspace, size-sizeof(DWORD)) )
  2497. goto ioerror;
  2498. #else
  2499. ||fgetpos(f->fileno, &bytepos)
  2500. ||doread(f, propspace, size-sizeof(DWORD)) )
  2501. goto ioerror;
  2502. f->propoffset = bytepos;
  2503. #endif
  2504. f->proplim = size - sizeof(DWORD);
  2505. parseprops(f, propspace);
  2506. if(size&1)
  2507. doread(f, propspace, 1);
  2508. free(propspace);
  2509. break;
  2510. } else {
  2511. #if defined CDP99 && defined _WIN32
  2512. if(SetFilePointer(f->fileno,-4L,NULL,FILE_CURRENT) == 0xFFFFFFFF)
  2513. #else
  2514. if(fseek(f->fileno, -4L, SEEK_CUR) < 0)
  2515. #endif
  2516. goto ioerror;
  2517. }
  2518. /* FALLTHROUGH */
  2519. default:
  2520. /* RWD MAR 2015 eliminate compiler warning; bit of an arbitrary exclusion anyway? */
  2521. if(/* size < 0 || */ size > 100*1024) {
  2522. rsferrno = ESFNOTFOUND;
  2523. rsferrstr = "Silly size for unknown AIFC chunk";
  2524. return 1;
  2525. }
  2526. if(ssndseen) {
  2527. struct aiffchunk **cpp, *cp;
  2528. for(cpp = &f->aiffchunks; *cpp != 0; cpp = &(*cpp)->next)
  2529. ;
  2530. if((*cpp = cp = ALLOC(struct aiffchunk)) == 0
  2531. ||(cp->buf = (char *) malloc((size+1)&~1)) == 0) {
  2532. rsferrno = ESFNOMEM;
  2533. rsferrstr = "No memory for aifc chunk storage";
  2534. return 1;
  2535. }
  2536. cp->tag = tag;
  2537. cp->size = size;
  2538. cp->next = 0;
  2539. #if defined CDP99 && defined _WIN32
  2540. if((cp->offset = SetFilePointer(f->fileno,0L,NULL,FILE_CURRENT)) == 0xFFFFFFFF
  2541. ||doread(f, cp->buf, (size+1)&~1))
  2542. goto ioerror;
  2543. #else
  2544. if(fgetpos(f->fileno, &bytepos)
  2545. ||doread(f, cp->buf, (size+1)&~1))
  2546. goto ioerror;
  2547. cp->offset = bytepos;
  2548. #endif
  2549. } else {
  2550. #if defined CDP99 && defined _WIN32
  2551. if(SetFilePointer(f->fileno,(long)((size+1)&~1),NULL,FILE_CURRENT) == 0xFFFFFFFF)
  2552. goto ioerror;
  2553. #else
  2554. if(fgetpos(f->fileno, &bytepos))
  2555. goto ioerror;
  2556. POS64(bytepos) += (size+1)&~1;
  2557. if(fsetpos(f->fileno, &bytepos))
  2558. goto ioerror;
  2559. #endif
  2560. }
  2561. f->extrachunksizes += ((size+1)&~1) + 2*sizeof(DWORD);
  2562. remain -= (size+1)&~1;
  2563. break;
  2564. }
  2565. }
  2566. if(!commseen) {
  2567. rsferrno = ESFNOTFOUND;
  2568. rsferrstr = "AIFC format error: no COMM chunk found";
  2569. return 1;
  2570. }
  2571. if(!ssndseen) {
  2572. rsferrno = ESFNOTFOUND;
  2573. rsferrstr = "AIFC format error: no SSND chunk found";
  2574. return 1;
  2575. }
  2576. if(!fmtverseen) {
  2577. rsferrno = ESFNOTFOUND;
  2578. rsferrstr = "AIFC format error: no FVER chunk found";
  2579. return 1;
  2580. }
  2581. f->datachunksize = numsampleframes * f->fmtchunkEx.Format.nChannels;
  2582. switch(f->fmtchunkEx.Format.wBitsPerSample) {
  2583. case 32: /* floats */
  2584. f->datachunksize *= 4;
  2585. break;
  2586. case 16: /* shorts */
  2587. f->datachunksize *= 2;
  2588. break;
  2589. case 20:
  2590. case 24:
  2591. f->datachunksize *= 3;
  2592. break;
  2593. case 8: /* byte -> short mappping */
  2594. f->datachunksize *= 2; /* looks like short samples! */
  2595. break;
  2596. default:
  2597. rsferrno = ESFNOTFOUND;
  2598. rsferrstr = "can't open Sfile - unsupported wordsize";
  2599. return 1;
  2600. }
  2601. #if defined CDP99 && defined _WIN32
  2602. if(SetFilePointer(f->fileno,f->datachunkoffset,NULL,FILE_BEGIN)==0xFFFFFFFF)
  2603. #else
  2604. POS64(bytepos) = POS64(f->datachunkoffset);
  2605. if(fsetpos(f->fileno, &bytepos) < 0)
  2606. #endif
  2607. goto ioerror;
  2608. return 0;
  2609. /* NOTREACHED */
  2610. ioerror:
  2611. rsferrno = ESFRDERR;
  2612. rsferrstr = "read error (or file too short) reading AIFC header";
  2613. return 1;
  2614. }
  2615. #if 0
  2616. static int
  2617. wraiffhdr(struct sf_file *f)
  2618. {
  2619. fpos_t bytepos;
  2620. f->mainchunksize = 0;
  2621. if(write_dw_msf(TAG('F','O','R','M'), f)
  2622. ||write_dw_msf(0, f)
  2623. ||write_dw_msf(TAG('A','I','F','F'), f) )
  2624. goto ioerror;
  2625. f->fmtchunkEx.Format.nChannels = 1;
  2626. f->fmtchunkEx.Format.nSamplesPerSec = 44100;
  2627. f->fmtchunkEx.Format.wBitsPerSample = 16;
  2628. f->aiffchunks = 0;
  2629. if(write_dw_msf(TAG('C','O','M','M'), f)
  2630. || write_dw_msf(18, f)
  2631. #if defined CDP99 && defined _WIN32
  2632. || (f->fmtchunkoffset = SetFilePointer(f->fileno,0L,NULL,FILE_CURRENT))==0xFFFFFFFF
  2633. || write_w_msf(f->fmtchunkEx.Format.nChannels, f)
  2634. || write_dw_msf(0, f) /* num sample frames */
  2635. || write_w_msf(f->fmtchunkEx.Format.wBitsPerSample, f)
  2636. || write_dw_toex(f->fmtchunkEx.Format.nSamplesPerSec, f) )
  2637. goto ioerror;
  2638. #else
  2639. ||fgetpos(f->fileno, &bytepos)
  2640. || write_w_msf(f->fmtchunkEx.Format.nChannels, f)
  2641. || write_dw_msf(0, f) /* num sample frames */
  2642. || write_w_msf(f->fmtchunkEx.Format.wBitsPerSample, f)
  2643. || write_dw_toex(f->fmtchunkEx.Format.nSamplesPerSec, f) )
  2644. goto ioerror;
  2645. f->fmtchunkoffset = bytepos;
  2646. #endif
  2647. if(write_dw_msf(TAG('A','P','P','L'), f)
  2648. || write_dw_msf(sizeof(DWORD) + PROPCNKSIZE, f)
  2649. || write_dw_msf(TAG('s','f','i','f'), f)
  2650. #if defined CDP99 && defined _WIN32
  2651. || (f->propoffset = SetFilePointer(f->fileno, 0L,NULL,FILE_CURRENT))==0xFFFFFFFF
  2652. || SetFilePointer(f->fileno,(long)PROPCNKSIZE,NULL,FILE_CURRENT) == 0xFFFFFFFF)
  2653. goto ioerror;
  2654. #else
  2655. || fgetpos(f->fileno, &bytepos)
  2656. || fseek(f->fileno, (long)PROPCNKSIZE, SEEK_CUR) < 0)
  2657. goto ioerror;
  2658. f->propoffset = bytepos;
  2659. #endif
  2660. if(write_dw_msf(TAG('S','S','N','D'), f)
  2661. || write_dw_msf(0, f)
  2662. || write_dw_msf(0, f) /* offset */
  2663. || write_dw_msf(0, f) /* blocksize */
  2664. #if defined CDP99 && defined _WIN32
  2665. || (f->datachunkoffset = SetFilePointer(f->fileno,0L,NULL,FILE_CURRENT)) == 0xFFFFFFFF)
  2666. goto ioerror;
  2667. #else
  2668. || fgetpos(f->fileno, &bytepos) )
  2669. goto ioerror;
  2670. f->datachunkoffset = bytepos;
  2671. #endif
  2672. f->propschanged = 1;
  2673. f->proplim = PROPCNKSIZE;
  2674. f->datachunksize = 0;
  2675. f->extrachunksizes = 0;
  2676. return 0;
  2677. /* NOTREACHED */
  2678. ioerror:
  2679. rsferrno = ESFWRERR;
  2680. rsferrstr = "write error writing aiff header";
  2681. return 1;
  2682. }
  2683. #endif
  2684. /*********** sfsys98 extension **********/
  2685. static int
  2686. wraiffhdr98(struct sf_file *f,int channels,int srate,int stype)
  2687. {
  2688. fpos_t bytepos;
  2689. if(stype >= SAMP_MASKED)
  2690. return 1;
  2691. rsferrstr = NULL;
  2692. f->mainchunksize = 0;
  2693. if(write_dw_msf(TAG('F','O','R','M'), f)
  2694. || write_dw_msf(0, f)
  2695. || write_dw_msf(TAG('A','I','F','F'), f) )
  2696. goto ioerror;
  2697. f->fmtchunkEx.Format.nChannels = (short)channels;
  2698. f->fmtchunkEx.Format.nSamplesPerSec = srate;
  2699. switch(stype){
  2700. case(SAMP_SHORT):
  2701. f->fmtchunkEx.Format.wBitsPerSample = 16;
  2702. f->fmtchunkEx.Format.nBlockAlign = sizeof(short) * f->fmtchunkEx.Format.nChannels;
  2703. break;
  2704. case(SAMP_FLOAT): //need to keep this for now...
  2705. case(SAMP_LONG):
  2706. f->fmtchunkEx.Format.wBitsPerSample = 32;
  2707. f->fmtchunkEx.Format.nBlockAlign = sizeof(/*long*/int) * f->fmtchunkEx.Format.nChannels;
  2708. break;
  2709. case(SAMP_2024):
  2710. f->fmtchunkEx.Format.wBitsPerSample = 20;
  2711. f->fmtchunkEx.Format.nBlockAlign = 3 * f->fmtchunkEx.Format.nChannels;
  2712. break;
  2713. case(SAMP_2424):
  2714. f->fmtchunkEx.Format.wBitsPerSample = 24;
  2715. f->fmtchunkEx.Format.nBlockAlign = 3 * f->fmtchunkEx.Format.nChannels;
  2716. break;
  2717. //NB 24/32 not allowed in AIFF
  2718. //case SAMP_MASKED: supported by AIFF, inside nearest integral byte-size
  2719. default:
  2720. rsferrstr = "sample format not supported in AIFF files";
  2721. goto ioerror; //something we don't know about!
  2722. }
  2723. f->aiffchunks = 0;
  2724. if(write_dw_msf(TAG('C','O','M','M'), f)
  2725. || write_dw_msf(18, f)
  2726. #if defined CDP99 && defined _WIN32
  2727. || (f->fmtchunkoffset = SetFilePointer(f->fileno,0L,NULL,FILE_CURRENT))==0xFFFFFFFF
  2728. || write_w_msf(f->fmtchunkEx.Format.nChannels, f)
  2729. || write_dw_msf(0, f) /* num sample frames */
  2730. || write_w_msf(f->fmtchunkEx.Format.wBitsPerSample, f)
  2731. || write_dw_toex(f->fmtchunkEx.Format.nSamplesPerSec, f) )
  2732. goto ioerror;
  2733. #else
  2734. || fgetpos(f->fileno, &bytepos)
  2735. || write_w_msf(f->fmtchunkEx.Format.nChannels, f)
  2736. || write_dw_msf(0, f) /* num sample frames */
  2737. || write_w_msf(f->fmtchunkEx.Format.wBitsPerSample, f)
  2738. || write_dw_toex(f->fmtchunkEx.Format.nSamplesPerSec, f) )
  2739. goto ioerror;
  2740. f->fmtchunkoffset = bytepos;
  2741. #endif
  2742. //RWD.6.5.99 ADD the PEAK chunk
  2743. if((f->min_header >= SFILE_PEAKONLY) && f->peaks){
  2744. int i,size;
  2745. DWORD now = 0;
  2746. for(i=0;i < channels; i++){
  2747. f->peaks[i].value = 0.0f;
  2748. f->peaks[i].position = 0;
  2749. }
  2750. size = 2 * sizeof(DWORD) + channels * sizeof(CHPEAK);
  2751. if(write_dw_msf(TAG('P','E','A','K'),f)
  2752. || write_dw_msf(size,f)
  2753. #if defined CDP99 && defined _WIN32
  2754. || ((f->peakchunkoffset = SetFilePointer(f->fileno,0L,NULL, FILE_CURRENT))== 0xFFFFFFFF)
  2755. || write_dw_msf(CURRENT_PEAK_VERSION,f)
  2756. || write_dw_msf(now,f)
  2757. || write_peak_msf(channels,f))
  2758. goto ioerror;
  2759. #else
  2760. || fgetpos(f->fileno, &bytepos)
  2761. || write_dw_msf(CURRENT_PEAK_VERSION,f)
  2762. || write_dw_msf(now,f)
  2763. || write_peak_msf(channels,f))
  2764. goto ioerror;
  2765. f->peakchunkoffset = bytepos;
  2766. #endif
  2767. }
  2768. if(f->min_header >= SFILE_CDP){
  2769. if(write_dw_msf(TAG('A','P','P','L'), f)
  2770. || write_dw_msf(sizeof(DWORD) + PROPCNKSIZE, f)
  2771. || write_dw_msf(TAG('s','f','i','f'), f)
  2772. #if defined CDP99 && defined _WIN32
  2773. || (f->propoffset = SetFilePointer(f->fileno, 0L,NULL,FILE_CURRENT))==0xFFFFFFFF
  2774. || SetFilePointer(f->fileno,(long)PROPCNKSIZE,NULL,FILE_CURRENT) == 0xFFFFFFFF)
  2775. goto ioerror;
  2776. #else
  2777. || fgetpos(f->fileno, &bytepos)
  2778. || fseek(f->fileno, (long)PROPCNKSIZE, SEEK_CUR) < 0)
  2779. goto ioerror;
  2780. f->propoffset = bytepos;
  2781. #endif
  2782. }
  2783. if(write_dw_msf(TAG('S','S','N','D'), f)
  2784. || write_dw_msf(0, f)
  2785. || write_dw_msf(0, f) /* offset */
  2786. || write_dw_msf(0, f) /* blocksize */
  2787. #if defined CDP99 && defined _WIN32
  2788. || (f->datachunkoffset = SetFilePointer(f->fileno,0L,NULL,FILE_CURRENT)) == 0xFFFFFFFF)
  2789. goto ioerror;
  2790. #else
  2791. || fgetpos(f->fileno, &bytepos) )
  2792. goto ioerror;
  2793. f->datachunkoffset = bytepos;
  2794. #endif
  2795. if(f->min_header >= SFILE_CDP){
  2796. f->propschanged = 1;
  2797. f->proplim = PROPCNKSIZE;
  2798. }
  2799. f->datachunksize = 0;
  2800. f->extrachunksizes = 0;
  2801. f->header_set = 1;
  2802. return 0;
  2803. /* NOTREACHED */
  2804. ioerror:
  2805. rsferrno = ESFWRERR;
  2806. if(rsferrstr == NULL)
  2807. rsferrstr = "error writing aiff header";
  2808. return 1;
  2809. }
  2810. /*RWD 22:6:2000 now use 'fl32', so the new Cubase will read it!*/
  2811. static int
  2812. wraifchdr(struct sf_file *f,int channels,int srate,int stype)
  2813. {
  2814. DWORD aifcver = AIFC_VERSION_1;
  2815. DWORD ID_compression;
  2816. fpos_t bytepos;
  2817. //assume 32bit floats, but we may be asked to use aifc for integer formats too
  2818. char *str_compressed = (char *) aifc_floatstring;
  2819. int pstring_size = 10;
  2820. rsferrstr = NULL;
  2821. if(stype >= SAMP_MASKED)
  2822. return 1;
  2823. /*RWD Sept 2000: was "ff32!" .*/
  2824. if(stype==SAMP_FLOAT)
  2825. ID_compression = TAG('f','l','3','2');
  2826. /* RWD 06-01-09 TODO: add "in24" type? */
  2827. else {
  2828. ID_compression = TAG('N','O','N','E');
  2829. pstring_size = 16;
  2830. str_compressed = (char *) aifc_notcompressed;
  2831. }
  2832. f->mainchunksize = 0;
  2833. if(write_dw_msf(TAG('F','O','R','M'), f)
  2834. ||write_dw_msf(0, f)
  2835. ||write_dw_msf(TAG('A','I','F','C'), f) )
  2836. goto ioerror;
  2837. f->fmtchunkEx.Format.nChannels = (short)channels;
  2838. f->fmtchunkEx.Format.nSamplesPerSec = srate;
  2839. switch(stype){
  2840. case(SAMP_SHORT):
  2841. f->fmtchunkEx.Format.wBitsPerSample = 16;
  2842. f->fmtchunkEx.Format.nBlockAlign = sizeof(short) * f->fmtchunkEx.Format.nChannels;
  2843. break;
  2844. case(SAMP_FLOAT):
  2845. case(SAMP_LONG):
  2846. f->fmtchunkEx.Format.wBitsPerSample = 32;
  2847. f->fmtchunkEx.Format.nBlockAlign = sizeof(/*long*/int) * f->fmtchunkEx.Format.nChannels;
  2848. break;
  2849. case(SAMP_2024):
  2850. f->fmtchunkEx.Format.wBitsPerSample = 20;
  2851. f->fmtchunkEx.Format.nBlockAlign = 3 * f->fmtchunkEx.Format.nChannels;
  2852. case(SAMP_2424):
  2853. f->fmtchunkEx.Format.wBitsPerSample = 24;
  2854. f->fmtchunkEx.Format.nBlockAlign = 3 * f->fmtchunkEx.Format.nChannels;
  2855. break;
  2856. //NB 2432 format not allowed in AIF file!
  2857. default:
  2858. rsferrstr = "requested sample format not supported by AIFF-C";
  2859. goto ioerror; //something we don't know about!
  2860. }
  2861. f->aiffchunks = 0;
  2862. //write FVER chunk
  2863. if(write_dw_msf(TAG('F','V','E','R'),f)
  2864. || write_dw_msf(4,f)
  2865. || write_dw_msf(aifcver,f))
  2866. goto ioerror;
  2867. //extended COMM chunk...22 bytes plus size of pascal string, rounded
  2868. if(write_dw_msf(TAG('C','O','M','M'), f)
  2869. || write_dw_msf(22 + pstring_size, f)
  2870. #if defined CDP99 && defined _WIN32
  2871. || (f->fmtchunkoffset = SetFilePointer(f->fileno,0L,NULL,FILE_CURRENT))==0xFFFFFFFF
  2872. || write_w_msf(f->fmtchunkEx.Format.nChannels, f)
  2873. || write_dw_msf(0, f) /* num sample frames */
  2874. || write_w_msf(f->fmtchunkEx.Format.wBitsPerSample, f)
  2875. || write_dw_toex(f->fmtchunkEx.Format.nSamplesPerSec, f) )
  2876. goto ioerror;
  2877. #else
  2878. || fgetpos(f->fileno, &bytepos)
  2879. || write_w_msf(f->fmtchunkEx.Format.nChannels, f)
  2880. || write_dw_msf(0, f) /* num sample frames */
  2881. || write_w_msf(f->fmtchunkEx.Format.wBitsPerSample, f)
  2882. || write_dw_toex(f->fmtchunkEx.Format.nSamplesPerSec, f) )
  2883. goto ioerror;
  2884. f->fmtchunkoffset = bytepos;
  2885. #endif
  2886. //now the special bits...
  2887. if(write_dw_msf(ID_compression,f))
  2888. goto ioerror;
  2889. //the dreaded pascal string...
  2890. if(dowrite(f,str_compressed,pstring_size))
  2891. goto ioerror;
  2892. //RWD.6.5.99 ADD the PEAK chunk
  2893. if((f->min_header >= SFILE_PEAKONLY) && f->peaks){
  2894. int i,size;
  2895. DWORD now = 0;
  2896. for(i=0;i < channels; i++){
  2897. f->peaks[i].value = 0.0f;
  2898. f->peaks[i].position = 0;
  2899. }
  2900. size = 2 * sizeof(DWORD) + channels * sizeof(CHPEAK);
  2901. if(write_dw_msf(TAG('P','E','A','K'),f)
  2902. || write_dw_msf(size,f)
  2903. #if defined CDP99 && defined _WIN32
  2904. || ((f->peakchunkoffset = SetFilePointer(f->fileno,0L,NULL, FILE_CURRENT))== 0xFFFFFFFF)
  2905. || write_dw_msf(CURRENT_PEAK_VERSION,f)
  2906. || write_dw_msf(now,f)
  2907. || write_peak_msf(channels,f))
  2908. goto ioerror;
  2909. #else
  2910. || fgetpos(f->fileno, &bytepos)
  2911. || write_dw_msf(CURRENT_PEAK_VERSION,f)
  2912. || write_dw_msf(now,f)
  2913. || write_peak_msf(channels,f))
  2914. goto ioerror;
  2915. f->peakchunkoffset = bytepos;
  2916. #endif
  2917. }
  2918. if(f->min_header >= SFILE_CDP){
  2919. if(write_dw_msf(TAG('A','P','P','L'), f)
  2920. || write_dw_msf(sizeof(DWORD) + PROPCNKSIZE, f)
  2921. || write_dw_msf(TAG('s','f','i','f'), f)
  2922. #if defined CDP99 && defined _WIN32
  2923. || (f->propoffset = SetFilePointer(f->fileno, 0L,NULL,FILE_CURRENT))==0xFFFFFFFF
  2924. || SetFilePointer(f->fileno,(long)PROPCNKSIZE,NULL,FILE_CURRENT) == 0xFFFFFFFF)
  2925. goto ioerror;
  2926. #else
  2927. || fgetpos(f->fileno, &bytepos)
  2928. || fseek(f->fileno, (long)PROPCNKSIZE, SEEK_CUR) < 0)
  2929. goto ioerror;
  2930. f->propoffset = bytepos;
  2931. #endif
  2932. }
  2933. if(write_dw_msf(TAG('S','S','N','D'), f)
  2934. ||write_dw_msf(0, f)
  2935. ||write_dw_msf(0, f) /* offset */
  2936. ||write_dw_msf(0, f) /* blocksize */
  2937. #if defined CDP99 && defined _WIN32
  2938. ||(f->datachunkoffset = SetFilePointer(f->fileno,0L,NULL,FILE_CURRENT)) == 0xFFFFFFFF)
  2939. goto ioerror;
  2940. #else
  2941. ||fgetpos(f->fileno, &bytepos) )
  2942. goto ioerror;
  2943. f->datachunkoffset = bytepos;
  2944. #endif
  2945. if(f->min_header >= SFILE_CDP){
  2946. f->propschanged = 1;
  2947. f->proplim = PROPCNKSIZE;
  2948. }
  2949. f->datachunksize = 0;
  2950. f->extrachunksizes = 0;
  2951. f->header_set = 1;
  2952. return 0;
  2953. /* NOTREACHED */
  2954. ioerror:
  2955. rsferrno = ESFWRERR;
  2956. if(rsferrstr==NULL)
  2957. rsferrstr = "error writing aiff-c header";
  2958. return 1;
  2959. }
  2960. /*
  2961. * Initialization routines
  2962. */
  2963. #if 0
  2964. int
  2965. sfinit()
  2966. {
  2967. return sflinit("%no name app%");
  2968. }
  2969. #endif
  2970. static void
  2971. rsffinish(void)
  2972. {
  2973. int i;
  2974. for(i = 0; i < SF_MAXFILES; i++)
  2975. if(sf_files[i] != 0)
  2976. sfclose(i+SFDBASE);
  2977. #ifdef _WIN32
  2978. if(CDP_COM_READY){
  2979. COMclose();
  2980. CDP_COM_READY = 0;
  2981. }
  2982. #endif
  2983. }
  2984. int
  2985. sflinit(const char *name)
  2986. {
  2987. int i;
  2988. for(i = 0; i < SF_MAXFILES; i++)
  2989. sf_files[i] = 0;
  2990. atexit(rsffinish);
  2991. if(sizeof(DWORD) != 4 || sizeof(WORD) != 2) {
  2992. rsferrno = ESFBADPARAM;
  2993. rsferrstr = "internal: sizeof(WORD) != 2 or sizeof(DWORD) != 4";
  2994. return -1;
  2995. }
  2996. #ifdef _WIN32
  2997. //alternative is to set CDP_COM_READY entirely in shortcuts.c
  2998. #ifdef _DEBUG
  2999. assert(!CDP_COM_READY);
  3000. #endif
  3001. CDP_COM_READY = COMinit(); //need COM to read shortcuts
  3002. #endif
  3003. return 0;
  3004. }
  3005. /*
  3006. * Misc other stuff
  3007. */
  3008. #if 0
  3009. void
  3010. sffinish()
  3011. {
  3012. /* leave everything to atexit! */
  3013. }
  3014. #endif
  3015. char *
  3016. sfgetbigbuf(int *secsize)
  3017. {
  3018. char *mem = (char *) malloc(100*SECSIZE);
  3019. *secsize = (mem == 0) ? 0 : 100;
  3020. return mem;
  3021. }
  3022. void
  3023. sfperror(const char *s)
  3024. {
  3025. if(s == 0)
  3026. s = "sound filing system";
  3027. if(*s != '\0')
  3028. fprintf(stderr, "%s: %s\n", s, rsferrstr);
  3029. else
  3030. fprintf(stderr, "%s\n", rsferrstr);
  3031. }
  3032. char *
  3033. sferrstr(void)
  3034. {
  3035. return rsferrstr;
  3036. }
  3037. int
  3038. sferrno(void)
  3039. {
  3040. return rsferrno;
  3041. }
  3042. int
  3043. sfsetprefix(char *path)
  3044. {
  3045. /* the set prefix call is simply ignored - for now */
  3046. return 0;
  3047. }
  3048. void
  3049. sfgetprefix(char *path)
  3050. {
  3051. path[0] = '\0'; /* signal that no prefix is set */
  3052. }
  3053. /*
  3054. * allocate/de-allocate file numbers
  3055. */
  3056. static int
  3057. allocsffile(char *filename)
  3058. {
  3059. int i;
  3060. int first_i = -1;
  3061. /*#if defined CDP97 && defined _WIN32*/
  3062. int refcnt98 = 1; //RWD incr refcnt for THIS file, if we have previously opened it
  3063. /*#endif*/
  3064. for(i = 0; i < SF_MAXFILES; i++)
  3065. if(sf_files[i] == 0) {
  3066. if(first_i < 0)
  3067. first_i = i;
  3068. }
  3069. //RWD98 excluding the return ~seems~ to be all thats needed to get multiple opens!
  3070. else if(_stricmp(sf_files[i]->filename, filename) == 0) {/* not quite right! */
  3071. sf_files[i]->refcnt++;
  3072. refcnt98++; //for THIS file
  3073. //return i;
  3074. }
  3075. if(first_i < 0) {
  3076. rsferrno = ESFNOSFD;
  3077. rsferrstr = "Too many Sfiles are open";
  3078. free(filename);
  3079. return -1;
  3080. }
  3081. if((sf_files[first_i] = ALLOC(struct sf_file)) == 0) {
  3082. rsferrno = ESFNOMEM;
  3083. rsferrstr = "No memory for open SFfile";
  3084. free(filename);
  3085. return -1;
  3086. }
  3087. sf_files[first_i]->refcnt = refcnt98;
  3088. //sf_files[first_i]->refcnt = 1; //RWD.6.98 restore this to restore old behaviour
  3089. sf_files[first_i]->filename = filename;
  3090. sf_files[first_i]->props = 0;
  3091. sf_files[first_i]->proplim = 0;
  3092. sf_files[first_i]->curpropsize = 0;
  3093. sf_files[first_i]->propschanged = 0;
  3094. sf_files[first_i]->aiffchunks = 0;
  3095. sf_files[first_i]->peaktime = 0;
  3096. POS64(sf_files[first_i]->peakchunkoffset) = 0;
  3097. POS64(sf_files[first_i]->factchunkoffset) = 0;
  3098. POS64(sf_files[first_i]->datachunkoffset) = 0;
  3099. sf_files[first_i]->peaks = NULL;
  3100. sf_files[first_i]->bitmask = 0xffffffff;
  3101. sf_files[first_i]->fmtchunkEx.dwChannelMask = 0;
  3102. sf_files[first_i]->chformat = STDWAVE;
  3103. sf_files[first_i]->min_header = SFILE_CDP;
  3104. return first_i;
  3105. }
  3106. static void
  3107. freesffile(int i)
  3108. {
  3109. struct property *pp = sf_files[i]->props;
  3110. struct aiffchunk *ap = sf_files[i]->aiffchunks;
  3111. while(pp != /* 0 */ NULL) {
  3112. struct property *pnext = pp->next;
  3113. free(pp->name);
  3114. free(pp->data);
  3115. free(pp);
  3116. pp = pnext;
  3117. }
  3118. while(ap != /* 0 */ NULL) {
  3119. struct aiffchunk *anext = ap->next;
  3120. free(ap->buf);
  3121. free(ap);
  3122. ap = anext;
  3123. }
  3124. free(sf_files[i]->filename);
  3125. //RWD.6.5.99
  3126. if(sf_files[i]->peaks != NULL)
  3127. free(sf_files[i]->peaks);
  3128. free(sf_files[i]);
  3129. sf_files[i] = /* 0 */ NULL;
  3130. }
  3131. #ifdef unix
  3132. #define PATH_SEP '/'
  3133. #else
  3134. #define PATH_SEP '\\'
  3135. #endif
  3136. //RWD: the environment var code prevents use of a defined analysis file extension
  3137. //in addition to CDP_SOUND_EXT ...
  3138. //RWD98 now declared static at top of file
  3139. /*RWD for DevCPp*/
  3140. #ifndef _MAX_PATH
  3141. #define _MAX_PATH (255)
  3142. #endif
  3143. #if 0
  3144. static enum sndfiletype
  3145. gettypefromname(const char *path)
  3146. {
  3147. #ifdef NOTDEF
  3148. char *eos = &path[strlen(path)]; /* points to the null byte */
  3149. char *lastsl = strrchr(path, PATH_SEP);
  3150. #else
  3151. //RWD98: use hackable local copy of path, to check for WIN32 shortcut
  3152. //this bit general, though
  3153. char *eos, *lastsl;
  3154. char copypath[_MAX_PATH];
  3155. int len;
  3156. copypath[0] = '\0';
  3157. strcpy(copypath,path);
  3158. len = strlen(copypath);
  3159. eos = &copypath[len];
  3160. lastsl = strrchr(copypath,PATH_SEP);
  3161. #endif
  3162. if(lastsl == 0)
  3163. //abort();
  3164. return unknown_wave; //RWD.1.99
  3165. #ifdef _WIN32
  3166. //it it a shortcut?
  3167. if(_stricmp(eos-4, ".lnk")==0) {
  3168. copypath[len-4] = '\0'; //cut away link extension
  3169. eos -= 4; //step past the ext, we should be left with a kosher sfilename
  3170. }
  3171. #endif
  3172. #ifdef NOTDEF
  3173. if(eos-4 > lastsl && _stricmp(eos-4, ".wav") == 0)
  3174. #endif
  3175. //CDP97: recognise .ana as signifying analysis file
  3176. if(eos-4 > lastsl && (_stricmp(eos-4, ".wav") == 0 || _stricmp(eos-4, ".ana") == 0))
  3177. return riffwav;
  3178. else if(eos-4 > lastsl && _stricmp(eos-4, ".aif") == 0 )
  3179. return eaaiff;
  3180. else if(eos-5 > lastsl && _stricmp(eos-5, ".aiff") == 0)
  3181. return eaaiff;
  3182. else if(eos-4 > lastsl && _stricmp(eos-4, ".afc") == 0) //RWD.1.99 for AIF-C
  3183. return aiffc;
  3184. else if(eos-4 > lastsl && _stricmp(eos-4, ".aic") == 0 )
  3185. return aiffc;
  3186. else if(eos-5 > lastsl && _stricmp(eos-5, ".aifc") == 0) //anyone using this?
  3187. return aiffc;
  3188. return unknown_wave;
  3189. }
  3190. #endif
  3191. /********* sfsy98 alternative... ********/
  3192. static enum sndfiletype
  3193. gettypefromname98(const char *path)
  3194. {
  3195. #ifdef NOTDEF
  3196. char *eos = &path[strlen(path)]; /* points to the null byte */
  3197. char *lastsl = strrchr(path, PATH_SEP);
  3198. #else
  3199. //RWD98: use hackable local copy of path, to check for WIN32 shortcut
  3200. //this bit general, though
  3201. char *eos, *lastsl;
  3202. char copypath[_MAX_PATH];
  3203. int len;
  3204. copypath[0] = '\0';
  3205. strcpy(copypath,path);
  3206. len = strlen(copypath);
  3207. eos = &copypath[len];
  3208. lastsl = strrchr(copypath,PATH_SEP);
  3209. #endif
  3210. if(lastsl == 0)
  3211. //abort();
  3212. return unknown_wave; //RWD.1.99
  3213. #ifdef _WIN32
  3214. //it it a shortcut?
  3215. if(_stricmp(eos-4, ".lnk")==0) {
  3216. copypath[len-4] = '\0'; //cut away link extension
  3217. eos -= 4; //step past the ext, we should be left with a kosher sfilename
  3218. }
  3219. #endif
  3220. if(eos-4 > lastsl && _stricmp(eos-4, ".wav") == 0)
  3221. return riffwav;
  3222. else if(eos-4 > lastsl && _stricmp(eos-4, ".aif") == 0)
  3223. return eaaiff;
  3224. else if(eos-5 > lastsl && _stricmp(eos-5, ".aiff") == 0)
  3225. return eaaiff;
  3226. //Recognize AIF-C files: use separate sndfiletype for this?
  3227. else if(eos-4 > lastsl && _stricmp(eos-4,".afc") == 0)
  3228. return aiffc;
  3229. else if(eos-4 > lastsl && _stricmp(eos-4,".aic") == 0)
  3230. return aiffc;
  3231. else if(eos-5 > lastsl && _stricmp(eos-5,".aifc") == 0)
  3232. return aiffc;
  3233. /* FILE_AMB_SUPPORT */
  3234. else if(eos-4 > lastsl && _stricmp(eos-4, ".amb") == 0)
  3235. return riffwav;
  3236. else if(eos-5 > lastsl && _stricmp(eos-5, ".ambi") == 0) //RWD April 2006 was -4 !
  3237. return riffwav;
  3238. else if(eos-5 > lastsl && _stricmp(eos-5, ".wxyz") == 0)
  3239. return riffwav;
  3240. //CDP97: recognise .ana as signifying analysis file - find out later whether wav or aiff
  3241. /* 4:2001 added revised extensions for and evl; lose fmt and env in time */
  3242. else if(_stricmp(eos-4, ".ana") == 0 //analysis file
  3243. || _stricmp(eos-4,".fmt") == 0 //formant file
  3244. || _stricmp(eos-4,".for") == 0
  3245. || _stricmp(eos-4,".frq") == 0 // pitch file
  3246. || _stricmp(eos-4,".env") == 0 // binary envelope
  3247. || _stricmp(eos-4,".evl") == 0
  3248. || _stricmp(eos-4,".trn") == 0 ) // transposition file
  3249. return cdpfile;
  3250. return unknown_wave;
  3251. }
  3252. //if a cdpfile - what format is it?
  3253. //RWD TODO: rewrite this with error retval
  3254. static enum sndfiletype
  3255. gettypefromfile(struct sf_file *f)
  3256. {
  3257. DWORD tag1,tag2,size;
  3258. enum sndfiletype type = unknown_wave;
  3259. if(read_dw_msf(&tag1, f) || read_dw_lsf(&size, f) || read_dw_msf(&tag2,f)) {
  3260. #if defined CDP99 && defined _WIN32
  3261. if(SetFilePointer(f->fileno,0,NULL,FILE_BEGIN)==0xFFFFFFFF)
  3262. #else
  3263. if(fseek(f->fileno,0,SEEK_SET) < 0)
  3264. #endif
  3265. return unknown_wave;
  3266. }
  3267. else if(tag1 == TAG('R','I','F','F') && tag2 == TAG('W','A','V','E')){
  3268. type = riffwav;
  3269. }
  3270. else if(tag1 == TAG('F','O','R','M') && tag2 == TAG('A','I','F','F')){
  3271. type = eaaiff;
  3272. }
  3273. //RWD.1.99 support aifc files as well
  3274. else if(tag1 == TAG('F','O','R','M') && tag2 == TAG('A','I','F','C')){
  3275. type = aiffc;
  3276. }
  3277. #if defined CDP99 && defined _WIN32
  3278. if(SetFilePointer(f->fileno,0,NULL,FILE_BEGIN)==0xFFFFFFFF)
  3279. #else
  3280. if(fseek(f->fileno,0,SEEK_SET) < 0)
  3281. #endif
  3282. return unknown_wave;
  3283. return type;
  3284. }
  3285. //RWD.6.98 when tested, add shortcuts code...
  3286. static char *
  3287. mksfpath(const char *name)
  3288. {
  3289. char *errormsg;
  3290. char *path = _fullpath(NULL, name, 0);
  3291. enum sndfiletype filetype = unknown_wave; //RWD 2015
  3292. if(path == NULL) {
  3293. rsferrno = ESFBADPARAM;
  3294. rsferrstr = "can't find full path for soundfile - bad drive?";
  3295. //#ifdef unix
  3296. // printf("realpath failed:errno = %d:%s\n",errno,strerror(errno));
  3297. //#endif
  3298. return NULL;
  3299. }
  3300. #ifdef _WIN32
  3301. //if its a shortcut, strip off the link extension: sfopen will try normal open first
  3302. {
  3303. int len;
  3304. char *eos;
  3305. len = strlen(path);
  3306. eos = &path[len-4];
  3307. if(_stricmp(eos,".lnk")==0)
  3308. path[len-4] = '\0';
  3309. }
  3310. #endif
  3311. /* RWD March 2014 make this optional! */
  3312. filetype = gettypefromname98(path);
  3313. if( filetype == unknown_wave) {
  3314. char *newpath;
  3315. char *ext;
  3316. char *ext_default = "wav";
  3317. // RWD MAR 2015 we may have unset CDP_SOUND_EXT, but not removed it completely!
  3318. if((ext = getenv("CDP_SOUND_EXT")) == NULL || strlen(ext) == 0 ) {
  3319. //rsferrno = ESFBADPARAM;
  3320. //rsferrstr = "unknown sound file type - extension not set";
  3321. //free(path);
  3322. //return NULL;
  3323. ext = ext_default;
  3324. }
  3325. if(_stricmp(ext, "wav") != 0
  3326. &&_stricmp(ext, "aif") != 0
  3327. &&_stricmp(ext, "aiff") != 0
  3328. &&_stricmp(ext,"afc") != 0 //Apple...
  3329. &&_stricmp(ext,"aic") != 0 //Csound uses this form
  3330. &&_stricmp(ext,"aifc") !=0) {
  3331. rsferrno = ESFBADPARAM;
  3332. rsferrstr = "unknown sound file type - bad CDP_SOUND_EXT setting";
  3333. free(path);
  3334. return NULL;
  3335. }
  3336. if((newpath = (char *) malloc(strlen(path) + strlen(ext) + 2)) == 0) {
  3337. rsferrno = ESFNOMEM;
  3338. rsferrstr = "can't get memory for full path of soundfile";
  3339. free(path);
  3340. return NULL;
  3341. }
  3342. strcpy(newpath, path);
  3343. strcat(newpath, ".");
  3344. strcat(newpath, ext);
  3345. free(path);
  3346. path = newpath;
  3347. }
  3348. if((errormsg = legalfilename(path)) != 0) {
  3349. rsferrno = ESFBADPARAM;
  3350. rsferrstr = errormsg;
  3351. free(path);
  3352. return NULL;
  3353. }
  3354. return path;
  3355. }
  3356. /*
  3357. * public sf routines
  3358. */
  3359. //RWD.6.98 TODO when tested, add all the file-sharing code
  3360. // best to #ifdef the revised function in as a block...
  3361. int
  3362. sfopen(const char *name)
  3363. {
  3364. int i, rc;
  3365. struct sf_file *f;
  3366. char *sfpath;
  3367. #if defined CDP99 && defined _WIN32
  3368. DWORD access = GENERIC_WRITE | GENERIC_READ; //assumeed for first open (eg for maxsamp...)
  3369. //seems I need to set write sharing so some other process can write...
  3370. DWORD sharing = FILE_SHARE_READ; //for first open
  3371. #else
  3372. char *faccess = "r+";
  3373. #endif
  3374. #ifdef _WIN32
  3375. char newpath[_MAX_PATH];
  3376. newpath[0] = '\0';
  3377. #endif
  3378. if((sfpath = mksfpath(name)) == NULL)
  3379. return -1;
  3380. if((i = allocsffile(sfpath)) < 0)
  3381. return -1;
  3382. f = sf_files[i];
  3383. //#ifdef NOTDEF
  3384. //this may not be needed after all: can't really display a file while is is being written to...
  3385. if(f->refcnt > 1) {
  3386. # if defined CDP99 && defined _WIN32
  3387. access = GENERIC_READ;
  3388. sharing = FILE_SHARE_WRITE | FILE_SHARE_READ; //repeat opens MUST allow first open to write!
  3389. # else
  3390. //faccess = "r"; /*RWD 2010 allow this ?? */
  3391. rsferrno = ESFNOTOPEN;
  3392. rsferrstr = "Can't open file more than once - yet!";
  3393. freesffile(i);
  3394. return -1;
  3395. # endif
  3396. }
  3397. //#endif
  3398. f->readonly = 0;
  3399. #ifdef _WIN32
  3400. f->is_shortcut = 0;
  3401. #endif
  3402. //first, try normal open as rd/wr
  3403. #if defined CDP99 && defined _WIN32
  3404. if((f->fileno = CreateFile(f->filename,access,sharing,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL)) == INVALID_HANDLE_VALUE)
  3405. #else
  3406. if((f->fileno = fopen(f->filename, faccess)) == NULL)
  3407. #endif
  3408. {
  3409. #if defined CDP99 && defined _WIN32
  3410. DWORD w_errno = GetLastError();
  3411. #endif
  3412. rsferrno = ESFNOTFOUND;
  3413. #if defined CDP99 && defined _WIN32
  3414. if(w_errno != ERROR_FILE_NOT_FOUND){
  3415. #else
  3416. if(errno != ENOENT){ //won't exist if its actually a shortcut
  3417. #endif
  3418. #if defined CDP99 && defined _WIN32
  3419. if(w_errno == ERROR_INVALID_NAME) {
  3420. #else
  3421. if(errno == EINVAL) {
  3422. #endif
  3423. rsferrstr = "Illegal filename";
  3424. freesffile(i);
  3425. return -1;
  3426. }
  3427. #if defined CDP99 && defined _WIN32
  3428. if(w_errno != ERROR_ACCESS_DENIED) {
  3429. #else
  3430. if(errno != EACCES) {
  3431. #endif
  3432. rsferrstr = "SFile not found";
  3433. freesffile(i);
  3434. return -1;
  3435. }
  3436. }
  3437. }
  3438. /* block bnelow is ONLY for Windows */
  3439. #ifdef _WIN32
  3440. //try a shortcut to rd/wr file...
  3441. # ifdef CDP99
  3442. if(f->fileno == INVALID_HANDLE_VALUE){
  3443. # else
  3444. if(f->fileno == NULL){
  3445. # endif
  3446. if(
  3447. (CDP_COM_READY) &&
  3448. (getAliasName(f->filename,newpath)) &&
  3449. # ifdef CDP99
  3450. ((f->fileno = CreateFile(newpath,access,sharing,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL)) == INVALID_HANDLE_VALUE)
  3451. # else
  3452. ((f->fileno = open(newpath, _O_BINARY|_O_RDWR) ) < 0)
  3453. # endif
  3454. ) {
  3455. //good link, but still no open...
  3456. # ifdef CDP99
  3457. DWORD w_errno = GetLastError();
  3458. rsferrno = ESFNOTFOUND;
  3459. if(w_errno == ERROR_INVALID_NAME) {
  3460. # else
  3461. rsferrno = ESFNOTFOUND;
  3462. if(errno == EINVAL) {
  3463. # endif
  3464. rsferrstr = "Illegal filename";
  3465. freesffile(i);
  3466. return -1;
  3467. }
  3468. # ifdef CDP99
  3469. if(w_errno != ERROR_ACCESS_DENIED) {
  3470. # else
  3471. if(errno != EACCES) {
  3472. # endif
  3473. rsferrstr = "SFile not found";
  3474. freesffile(i);
  3475. return -1;
  3476. }
  3477. }
  3478. }
  3479. #endif
  3480. /* "normal" file open code here */
  3481. //must be rdonly, try normal open or shortcut
  3482. #if defined CDP99 && defined _WIN32
  3483. if(f->fileno== INVALID_HANDLE_VALUE){
  3484. #else
  3485. if(f->fileno==NULL){
  3486. #endif
  3487. if(
  3488. #ifdef CDP99
  3489. ((f->fileno = CreateFile(f->filename, GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_READONLY,NULL)) == INVALID_HANDLE_VALUE)
  3490. #else
  3491. ((f->fileno = fopen(f->filename, "r")) == NULL)
  3492. #endif
  3493. #ifdef _WIN32
  3494. && (!((CDP_COM_READY) || (getAliasName(f->filename,newpath)))
  3495. # ifdef CDP99
  3496. || ((f->fileno = CreateFile(newpath, GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_READONLY,NULL)) == INVALID_HANDLE_VALUE)
  3497. # else
  3498. || ((f->fileno = open(newpath, _O_BINARY|_O_RDONLY) ) < 0)
  3499. # endif
  3500. )
  3501. #endif
  3502. ){
  3503. rsferrstr = "SFile not found";
  3504. freesffile(i);
  3505. return -1;
  3506. }
  3507. f->readonly = 1;
  3508. }
  3509. #ifdef _WIN32
  3510. if(strlen(newpath) >0) {
  3511. f->filename[0] = '\0';
  3512. f->is_shortcut = 1;
  3513. strcpy(f->filename,newpath); //filename will be freed eventually; don't copy pointers
  3514. }
  3515. #endif
  3516. switch(f->filetype = gettypefromfile(f)) {
  3517. case riffwav:
  3518. rc = rdwavhdr(f);
  3519. break;
  3520. case eaaiff:
  3521. rc = rdaiffhdr(f);
  3522. break;
  3523. case aiffc:
  3524. rc = rdaifchdr(f);
  3525. break;
  3526. default:
  3527. rsferrno = ESFNOSTYPE;
  3528. rsferrstr = "Internal error: can't find file type";
  3529. rc = 1;
  3530. }
  3531. if(rc) {
  3532. freesffile(i);
  3533. return -1;
  3534. }
  3535. f->infochanged = 0;
  3536. f->todelete = 0;
  3537. f->sizerequested = ES_EXIST;
  3538. f->curpos = 0;
  3539. return i+SFDBASE;
  3540. }
  3541. //RWD.9.98 new version to control access
  3542. int
  3543. sfopenEx(const char *name, unsigned int access)
  3544. {
  3545. int i, rc;
  3546. struct sf_file *f;
  3547. char *sfpath;
  3548. char newpath[_MAX_PATH];
  3549. newpath[0] = '\0';
  3550. if((sfpath = mksfpath(name)) == NULL)
  3551. return -1;
  3552. if((i = allocsffile(sfpath)) < 0)
  3553. return -1;
  3554. f = sf_files[i];
  3555. f->readonly = 0;
  3556. f->is_shortcut = 0;
  3557. if(access== CDP_OPEN_RDONLY){
  3558. #if defined CDP99 && defined _WIN32
  3559. if(((f->fileno = CreateFile(f->filename, GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_READONLY,NULL)) == INVALID_HANDLE_VALUE)
  3560. #else
  3561. if(((f->fileno = fopen(f->filename, "r")) == NULL)
  3562. #endif
  3563. && ((!CDP_COM_READY)
  3564. || (!getAliasName(f->filename,newpath))
  3565. #if defined CDP99 && defined _WIN32
  3566. || ((f->fileno = CreateFile(newpath, GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_READONLY,NULL)) == INVALID_HANDLE_VALUE)
  3567. #else
  3568. || ((f->fileno = fopen(newpath, "r") ) == NULL)
  3569. #endif
  3570. )){
  3571. rsferrstr = "SFile not found";
  3572. freesffile(i);
  3573. return -1;
  3574. }
  3575. f->readonly = 1;
  3576. }
  3577. else{
  3578. // normal open as rd/wr
  3579. #if defined CDP99 && defined _WIN32
  3580. DWORD w_errno;
  3581. if((f->fileno = CreateFile(f->filename, GENERIC_READ | GENERIC_WRITE,
  3582. FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_READONLY,NULL)) == INVALID_HANDLE_VALUE) {
  3583. #else
  3584. if((f->fileno = fopen(f->filename, "r+")) == NULL ) {
  3585. #endif
  3586. rsferrno = ESFNOTFOUND;
  3587. #if defined CDP99 && defined _WIN32
  3588. w_errno= GetLastError();
  3589. if(w_errno != ERROR_FILE_NOT_FOUND){
  3590. #else
  3591. if(errno != ENOENT){ //won't exist if its actually a shortcut
  3592. #endif
  3593. #if defined CDP99 && defined _WIN32
  3594. if(w_errno == ERROR_INVALID_NAME) {
  3595. #else
  3596. if(errno == EINVAL) {
  3597. #endif
  3598. rsferrstr = "Illegal filename";
  3599. freesffile(i);
  3600. return -1;
  3601. }
  3602. #if defined CDP99 && defined _WIN32
  3603. if(w_errno != ERROR_ACCESS_DENIED) {
  3604. #else
  3605. if(errno != EACCES) {
  3606. #endif
  3607. rsferrstr = "SFile not found";
  3608. freesffile(i);
  3609. return -1;
  3610. }
  3611. }
  3612. }
  3613. //try a shortcut to rd/wr file...
  3614. # ifdef CDP99
  3615. if(f->fileno == INVALID_HANDLE_VALUE){
  3616. # else
  3617. if(f->fileno == NULL){
  3618. # endif
  3619. if(
  3620. (CDP_COM_READY) &&
  3621. (getAliasName(f->filename,newpath)) &&
  3622. #if defined CDP99 && defined _WIN32
  3623. ((f->fileno = CreateFile(newpath, GENERIC_READ | GENERIC_WRITE,
  3624. FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_READONLY,NULL)) == INVALID_HANDLE_VALUE)
  3625. #else
  3626. ((f->fileno = fopen(newpath, "r+") ) == NULL)
  3627. #endif
  3628. ) {
  3629. //good link, but still no open...
  3630. rsferrno = ESFNOTFOUND;
  3631. #if defined CDP99 && defined _WIN32
  3632. if(w_errno == ERROR_INVALID_NAME) {
  3633. #else
  3634. if(errno == EINVAL) {
  3635. #endif
  3636. rsferrstr = "Illegal filename";
  3637. freesffile(i);
  3638. return -1;
  3639. }
  3640. #if defined CDP99 && defined _WIN32
  3641. if(w_errno != ERROR_ACCESS_DENIED) {
  3642. #else
  3643. if(errno != EACCES) {
  3644. #endif
  3645. rsferrstr = "SFile not found";
  3646. freesffile(i);
  3647. return -1;
  3648. }
  3649. }
  3650. }
  3651. #if defined CDP99 && defined _WIN32
  3652. if(f->fileno== INVALID_HANDLE_VALUE){
  3653. #else
  3654. if(f->fileno == NULL){
  3655. #endif
  3656. rsferrstr = "SFile not found";
  3657. freesffile(i);
  3658. return -1;
  3659. }
  3660. }
  3661. #ifdef _WIN32
  3662. if(strlen(newpath) >0) {
  3663. f->filename[0] = '\0';
  3664. f->is_shortcut = 1;
  3665. strcpy(f->filename,newpath); //filename will be freed eventually; don't copy pointers
  3666. }
  3667. #endif
  3668. switch(f->filetype = gettypefromfile(f)) {
  3669. case riffwav:
  3670. rc = rdwavhdr(f);
  3671. break;
  3672. case eaaiff:
  3673. rc = rdaiffhdr(f);
  3674. break;
  3675. case aiffc:
  3676. rc = rdaifchdr(f);
  3677. break;
  3678. default:
  3679. rsferrno = ESFNOSTYPE;
  3680. rsferrstr = "Internal error: can't find file type";
  3681. rc = 1;
  3682. }
  3683. if(rc) {
  3684. freesffile(i);
  3685. return -1;
  3686. }
  3687. f->infochanged = 0;
  3688. f->todelete = 0;
  3689. f->sizerequested = ES_EXIST;
  3690. f->curpos = 0;
  3691. return i+SFDBASE;
  3692. }
  3693. static struct sf_file *
  3694. findfile(int sfd)
  3695. {
  3696. sfd -= SFDBASE;
  3697. if(sfd < 0 || sfd >= SF_MAXFILES || sf_files[sfd] == 0) {
  3698. rsferrno = ESFNOTOPEN;
  3699. rsferrstr = "soundfile descriptor does not refer to an open soundfile";
  3700. return 0;
  3701. }
  3702. return sf_files[sfd];
  3703. }
  3704. static int
  3705. comparewithlist(const char *list, const char *name)
  3706. {
  3707. size_t len = strlen(name);
  3708. for(;;) {
  3709. if(_strnicmp(list, name, len) == 0
  3710. &&(list[len] == '\0' || list[len] == ','))
  3711. return 1;
  3712. if((list = strchr(list, ',')) == 0)
  3713. break;
  3714. list++;
  3715. }
  3716. return 0;
  3717. }
  3718. #if defined CDP99 && defined _WIN32
  3719. static HANDLE doopen(const char *name, const char *origname,cdp_create_mode mode)
  3720. {
  3721. char *ovrflg;
  3722. HANDLE rc;
  3723. DWORD access,sharing,attrib,w_errno;
  3724. access = GENERIC_READ | GENERIC_WRITE;
  3725. sharing = FILE_SHARE_READ;
  3726. attrib = FILE_ATTRIBUTE_NORMAL;
  3727. if(mode==CDP_CREATE_TEMPORARY){
  3728. sharing = 0;
  3729. attrib = FILE_ATTRIBUTE_TEMPORARY
  3730. | FILE_ATTRIBUTE_HIDDEN
  3731. | FILE_FLAG_DELETE_ON_CLOSE;
  3732. }
  3733. if(mode==CDP_CREATE_RDONLY)
  3734. attrib = FILE_ATTRIBUTE_READONLY;
  3735. if((rc = CreateFile(name, access,sharing,NULL,CREATE_NEW,attrib,NULL)) != INVALID_HANDLE_VALUE)
  3736. return rc;
  3737. w_errno = GetLastError();
  3738. if(!(w_errno == ERROR_FILE_EXISTS || w_errno==ERROR_ALREADY_EXISTS))
  3739. return rc;
  3740. if(mode==CDP_CREATE_NORMAL){
  3741. if((ovrflg = getenv("CDP_OVERWRITE_FILE")) == 0)
  3742. return rc;
  3743. if(strcmp(ovrflg, "*") != 0
  3744. &&!comparewithlist(ovrflg, origname))
  3745. return rc;
  3746. return CreateFile(name, access,sharing,NULL,CREATE_ALWAYS,attrib,NULL);
  3747. }
  3748. else
  3749. return rc;
  3750. }
  3751. #else
  3752. static FILE* doopen(const char *name, const char *origname,cdp_create_mode mode)
  3753. {
  3754. char *ovrflg;
  3755. FILE* fp = NULL;
  3756. //RWD set modeflags here to allow setting a temporary file in CDP97
  3757. //int exclmode,truncmode;
  3758. //exclmode = (_O_BINARY|_O_RDWR|_O_CREAT|_O_EXCL );
  3759. //truncmode = (_O_BINARY|_O_RDWR|_O_TRUNC);
  3760. char *fmode = "w+x";
  3761. #ifdef _WIN32
  3762. if(mode==CDP_CREATE_TEMPORARY){
  3763. exclmode |= /*_O_SHORT_LIVED*/_O_TEMPORARY; //create as temporary, if poss no flush to disk
  3764. }
  3765. #else
  3766. /* TODO: replace with mkstemp, maybe use origname as part of template? */
  3767. /* RWD MAR 2015, need to eliminate call to tmpnam,
  3768. * without having to alloc new memory for modifiable name for mkstemp() */
  3769. /* only the old GUI programs (GrainMill) ask for a temporary filename, anyway... */
  3770. //if(mode==CDP_CREATE_TEMPORARY)
  3771. // name = tmpnam(NULL);
  3772. #endif
  3773. if(mode==CDP_CREATE_RDONLY){
  3774. //exclmode = (_O_BINARY|_O_RDONLY|_O_CREAT|_O_EXCL );
  3775. //truncmode = (_O_BINARY|_O_RDONLY|_O_TRUNC);
  3776. fmode = "r+x";
  3777. }
  3778. if((fp = fopen(name,fmode ))!= NULL)
  3779. return fp;
  3780. if(errno != EEXIST)
  3781. return fp;
  3782. if((ovrflg = getenv("CDP_OVERWRITE_FILE")) == 0)
  3783. return fp;
  3784. if(strcmp(ovrflg, "*") != 0
  3785. &&!comparewithlist(ovrflg, origname))
  3786. return fp;
  3787. // allow overwriting (I hope...) */
  3788. return fopen(name,"w+");
  3789. }
  3790. #endif
  3791. //RWD98 BIG TODO: new function sfcreateEx(const char *name, long size, long *outsize, SFPROPS *pProps,int min_header)
  3792. //RWD.5.99 NB of course, we CANNOT write a peak chunk here, as we have no format information
  3793. //RWD.6.99 also, just to be consistent with old programs, we reject any aifc formats
  3794. /* RWD Aug 2010 hope we can eliminate this altogether! */
  3795. #ifdef NOTDEF
  3796. int
  3797. sfcreat(const char *name, int size, int *outsize)
  3798. {
  3799. int i, rc;
  3800. struct sf_file *f;
  3801. char *sfpath;
  3802. char *ext_default = "wav";
  3803. #if defined CDP99 && defined _WIN32
  3804. DWORD w_errno;
  3805. #endif
  3806. unsigned long freespace = getdrivefreespace(name) - LEAVESPACE;
  3807. if((sfpath = mksfpath(name)) == NULL)
  3808. return -1;
  3809. //RWD.5.99 we rely on f->peaks being NULL
  3810. if((i = allocsffile(sfpath)) < 0)
  3811. return -1;
  3812. f = sf_files[i];
  3813. //RWD: this is OK, as it tells us we cannot CREATE more than one file of the same name, or one already opened
  3814. if(f->refcnt > 1) {
  3815. rsferrno = ESFNOTOPEN;
  3816. rsferrstr = "Can't open file more than once - yet!";
  3817. freesffile(i);
  3818. return -1;
  3819. }
  3820. #ifdef NOTDEF
  3821. if((f->fileno = doopen(f->filename, name)) < 0) {
  3822. #endif
  3823. #ifdef CDP99
  3824. if((f->fileno = doopen(f->filename, name,CDP_CREATE_NORMAL)) == INVALID_HANDLE_VALUE) {
  3825. #else
  3826. if((f->fileno = doopen(f->filename, name,CDP_CREATE_NORMAL)) < 0) {
  3827. #endif
  3828. #if defined CDP99 && defined _WIN32
  3829. w_errno = GetLastError();
  3830. switch(w_errno){
  3831. case ERROR_INVALID_NAME:
  3832. rsferrno = ESFNOTOPEN;
  3833. rsferrstr = "Can't create SFile, Illegal filename";
  3834. break;
  3835. case ERROR_FILE_EXISTS:
  3836. case ERROR_ALREADY_EXISTS:
  3837. rsferrno = ESFDUPFNAME;
  3838. rsferrstr = "Can't create SFile, already exists";
  3839. break;
  3840. case ERROR_ACCESS_DENIED:
  3841. rsferrno = ESFNOTOPEN;
  3842. rsferrstr = "Can't create SFile, permission denied";
  3843. break;
  3844. default:
  3845. rsferrno = ESFNOTOPEN;
  3846. rsferrstr = "Can't create SFile, Internal error";
  3847. }
  3848. #else
  3849. switch(errno) {
  3850. case EINVAL:
  3851. rsferrno = ESFNOTOPEN;
  3852. rsferrstr = "Can't create SFile, Illegal filename";
  3853. break;
  3854. case EEXIST:
  3855. rsferrno = ESFDUPFNAME;
  3856. rsferrstr = "Can't create SFile, already exists";
  3857. break;
  3858. case EACCES:
  3859. rsferrno = ESFNOTOPEN;
  3860. rsferrstr = "Can't create SFile, permission denied";
  3861. break;
  3862. default:
  3863. rsferrno = ESFNOTOPEN;
  3864. rsferrstr = "Can't create SFile, Internal error";
  3865. }
  3866. #endif
  3867. freesffile(i);
  3868. return -1;
  3869. }
  3870. if(size < 0)
  3871. f->sizerequested = freespace;
  3872. else if((unsigned int)size >= freespace) {
  3873. rsferrno = ESFNOSPACE;
  3874. rsferrstr = "Not enough space on Disk to create sound file";
  3875. freesffile(i);
  3876. return -1;
  3877. } else
  3878. f->sizerequested = size&~1; /*RWD Nov 2001 No 24bit support in this func, so keep ~1 */
  3879. f->readonly = 0;
  3880. f->header_set = 0;
  3881. //RWD.5.99 HOPE WE WE DON'T TRY TO CREATE FROM A SHORTCUT!
  3882. //#ifdef NOTDEF
  3883. // switch(f->filetype = gettypefromname(f->filename)) {
  3884. //#endif
  3885. switch(f->filetype = gettypefromname98(f->filename)) {
  3886. /******* RWD.7.98 all we have to do to write a requested format is to fill in the data in f->fmtchunk
  3887. ******* and get wrwavhdr() to read this in! *****/
  3888. char *ext;
  3889. case riffwav:
  3890. rc = wrwavhdr(f);
  3891. break;
  3892. case eaaiff:
  3893. rc = wraiffhdr(f);
  3894. break;
  3895. //RWD temporary
  3896. case aiffc:
  3897. rsferrno = ESFNOSTYPE;
  3898. rsferrstr = "This version canot write AIF-C soundfiles";
  3899. return -1;
  3900. break;
  3901. case cdpfile:
  3902. /* RWD MAR 2015 added test for empty string */
  3903. if((ext = getenv("CDP_SOUND_EXT")) == NULL || strlen(ext) == 0) {
  3904. //rsferrno = ESFBADPARAM;
  3905. //rsferrstr = "unknown sound file type - extension not set";
  3906. //return -1;
  3907. ext = ext_default;
  3908. }
  3909. if(_stricmp(ext, "wav") == 0){
  3910. rc=wrwavhdr(f);
  3911. f->filetype = riffwav;
  3912. }
  3913. else if(_stricmp(ext, "aif") == 0 || _stricmp(ext, "aiff") == 0){
  3914. rc=wraiffhdr(f);
  3915. f->filetype= eaaiff;
  3916. }
  3917. else {
  3918. rsferrno = ESFBADPARAM;
  3919. rsferrstr = "unknown sound file type - bad CDP_SOUND_EXT setting";
  3920. return -1;
  3921. }
  3922. break;
  3923. default:
  3924. rsferrno = ESFNOSTYPE;
  3925. rsferrstr = "Internal error: can't find filetype";
  3926. rc = 1;
  3927. }
  3928. if(rc) {
  3929. freesffile(i);
  3930. return -1;
  3931. }
  3932. f->datachunksize = 0;
  3933. f->infochanged = 0;
  3934. f->todelete = 0;
  3935. if(outsize != 0)
  3936. *outsize = (int) f->sizerequested;
  3937. f->curpos = 0;
  3938. return i+SFDBASE;
  3939. }
  3940. #endif
  3941. /********* SFSY98 extension: supply format info for streaming, etc *******/
  3942. //RWD.6.99 supports all new legal formats, except WAVE_EX (use sfcreat_ex)
  3943. //RWD.1.99 added mode arg to create temporary file in Current Directory
  3944. /*RWD 2007: change size params to __int64 */
  3945. #ifdef FILE64_WIN
  3946. int
  3947. sfcreat_formatted(const char *name, __int64 size, __int64 *outsize,int channels,
  3948. int srate, int stype,cdp_create_mode mode)
  3949. #else
  3950. int sfcreat_formatted(const char *name, __int64 size, __int64 *outsize,int channels,
  3951. int srate, int stype,cdp_create_mode mode)
  3952. #endif
  3953. {
  3954. int i, rc;
  3955. struct sf_file *f;
  3956. char *sfpath;
  3957. /* RWD March 2014 */
  3958. char *ext_default = "wav";
  3959. /*RWD 2007 */
  3960. #ifdef FILE64_WIN
  3961. /*unsigned long*/__int64 freespace = getdrivefreespace(name) - LEAVESPACE;
  3962. #else
  3963. __int64 freespace = getdrivefreespace(name) - LEAVESPACE;
  3964. #endif
  3965. if((sfpath = mksfpath(name)) == NULL)
  3966. return -1;
  3967. if((i = allocsffile(sfpath)) < 0)
  3968. return -1;
  3969. f = sf_files[i];
  3970. //RWD: this is OK, as it tells us we cannot CREATE more than one file of the same name, or one already opened
  3971. if(f->refcnt > 1) {
  3972. rsferrno = ESFNOTOPEN;
  3973. rsferrstr = "Can't open file more than once - yet!";
  3974. freesffile(i);
  3975. return -1;
  3976. }
  3977. #if defined CDP99 && defined _WIN32
  3978. if((f->fileno = doopen(f->filename, name,mode)) == INVALID_HANDLE_VALUE) {
  3979. DWORD w_errno = GetLastError();
  3980. #else
  3981. if((f->fileno = doopen(f->filename, name,mode)) == NULL) {
  3982. #endif
  3983. #if defined CDP99 && defined _WIN32
  3984. switch(w_errno) {
  3985. case ERROR_INVALID_NAME:
  3986. rsferrno = ESFNOTOPEN;
  3987. rsferrstr = "Can't create SFile, Illegal filename";
  3988. break;
  3989. case ERROR_FILE_EXISTS:
  3990. case ERROR_ALREADY_EXISTS:
  3991. rsferrno = ESFDUPFNAME;
  3992. rsferrstr = "Can't create SFile, already exists";
  3993. break;
  3994. case ERROR_ACCESS_DENIED:
  3995. rsferrno = ESFNOTOPEN;
  3996. rsferrstr = "Can't create SFile, permission denied";
  3997. break;
  3998. default:
  3999. rsferrno = ESFNOTOPEN;
  4000. rsferrstr = "Can't create SFile, Internal error";
  4001. }
  4002. #else
  4003. switch(errno) {
  4004. case EINVAL:
  4005. rsferrno = ESFNOTOPEN;
  4006. rsferrstr = "Can't create SFile, Illegal filename";
  4007. break;
  4008. case EEXIST:
  4009. rsferrno = ESFDUPFNAME;
  4010. rsferrstr = "Can't create SFile, already exists";
  4011. break;
  4012. case EACCES:
  4013. rsferrno = ESFNOTOPEN;
  4014. rsferrstr = "Can't create SFile, permission denied";
  4015. break;
  4016. default:
  4017. rsferrno = ESFNOTOPEN;
  4018. rsferrstr = "Can't create SFile, Internal error";
  4019. }
  4020. #endif
  4021. freesffile(i);
  4022. return -1;
  4023. }
  4024. if(size < 0)
  4025. f->sizerequested = freespace;
  4026. else if(size >= freespace) {
  4027. rsferrno = ESFNOSPACE;
  4028. rsferrstr = "Not enough space on Disk to create sound file";
  4029. //RWD.7.99
  4030. #if defined CDP99 && defined _WIN32
  4031. CloseHandle(f->fileno);
  4032. DeleteFile(f->filename);
  4033. #else
  4034. fclose(f->fileno);
  4035. remove(f->filename);
  4036. #endif
  4037. freesffile(i);
  4038. return -1;
  4039. } else
  4040. f->sizerequested = /*size&~1*/ size; /* RWD NOV 2001 NO ROUNDING! We have 24bit samples now! */
  4041. f->readonly = 0;
  4042. f->header_set = 0;
  4043. ///RWD.6.5.99 prepare peak storage
  4044. f->peaks = (CHPEAK *) calloc(channels, sizeof(CHPEAK));
  4045. if(f->peaks==NULL){
  4046. rsferrno = ESFNOMEM;
  4047. rsferrstr = "No memory to create peak data storage";
  4048. //RWD.7.99
  4049. #if defined CDP99 && defined _WIN32
  4050. CloseHandle(f->fileno);
  4051. DeleteFile(f->filename);
  4052. #else
  4053. fclose(f->fileno);
  4054. remove(f->filename);
  4055. #endif
  4056. freesffile(i);
  4057. return -1;
  4058. }
  4059. switch(f->filetype = gettypefromname98(f->filename)) {
  4060. char *ext;
  4061. /******* RWD.7.98 all we have to do to write a requested format is to fill in the data in f->fmtchunk
  4062. ******* and get wrwavhdr() to read this in! *****/
  4063. case riffwav:
  4064. rc = wrwavhdr98(f,channels,srate,stype);
  4065. break;
  4066. case eaaiff:
  4067. //make sure AIFF format is legal!
  4068. if(stype==SAMP_2432){
  4069. //reject here, as can't tell caller
  4070. rsferrno = ESFBADPARAM;
  4071. rsferrstr = "requested sample type illegal for AIFF files";
  4072. return -1;
  4073. }
  4074. if(stype==SAMP_FLOAT){
  4075. //we now require AIFC for float formats
  4076. f->filetype = aiffc;
  4077. rc = wraifchdr(f,channels,srate,stype);
  4078. }
  4079. else
  4080. rc = wraiffhdr98(f,channels,srate,stype);
  4081. break;
  4082. //RWD temporary
  4083. case aiffc:
  4084. //make sure AIFF format is legal!
  4085. if(stype==SAMP_2432){
  4086. //reject here, as can't tell caller
  4087. rsferrno = ESFBADPARAM;
  4088. rsferrstr = "requested sample type illegal for AIFF files";
  4089. return -1;
  4090. }
  4091. rc = wraifchdr(f,channels,srate,stype);
  4092. break;
  4093. case cdpfile:
  4094. /* RWD MAR 2015 as above */
  4095. if((ext = getenv("CDP_SOUND_EXT")) == NULL || strlen(ext) == 0) {
  4096. //rsferrno = ESFBADPARAM;
  4097. //rsferrstr = "unknown sound file type - extension not set";
  4098. //RWD.7.99
  4099. //#if defined CD/P99 && defined _WIN32
  4100. // CloseHandle(f->fileno);
  4101. // DeleteFile(f->filename);
  4102. //#else
  4103. // fclose(f->fileno);
  4104. // remove(f->filename);
  4105. //#endif
  4106. // return -1;
  4107. ext = ext_default;
  4108. }
  4109. f->min_header = SFILE_ANAL; /*RWD Nov 2009: but we don't want PEAK, CUE for analysis files! */
  4110. if(f->peaks){
  4111. free(f->peaks);
  4112. f->peaks = NULL;
  4113. }
  4114. if(_stricmp(ext, "wav") == 0){
  4115. rc = wrwavhdr98(f,channels,srate,stype); /*RWD 5:2003*/
  4116. f->filetype = riffwav;
  4117. }
  4118. else if(_stricmp(ext, "aif") == 0 || _stricmp(ext, "aiff") == 0){
  4119. if(stype==SAMP_FLOAT){
  4120. //we now require AIFC for float formats
  4121. f->filetype = aiffc;
  4122. rc = wraifchdr(f,channels,srate,stype);
  4123. }
  4124. else{
  4125. rc=wraiffhdr98(f,channels,srate,stype);
  4126. f->filetype= eaaiff;
  4127. }
  4128. }
  4129. //RWD.1.99 temporary
  4130. else if(_stricmp(ext, "aic") == 0
  4131. || _stricmp(ext, "afc") == 0
  4132. || _stricmp(ext, "aifc") == 0){
  4133. rc=wraifchdr(f,channels,srate,stype);
  4134. f->filetype= aiffc;
  4135. }
  4136. else {
  4137. rsferrno = ESFBADPARAM;
  4138. rsferrstr = "unknown sound file type - bad CDP_SOUND_EXT setting";
  4139. //RWD.7.99
  4140. #if defined CDP99 && defined _WIN32
  4141. CloseHandle(f->fileno);
  4142. DeleteFile(f->filename);
  4143. #else
  4144. fclose(f->fileno);
  4145. remove(f->filename);
  4146. #endif
  4147. return -1;
  4148. }
  4149. break;
  4150. default:
  4151. rsferrno = ESFNOSTYPE;
  4152. rsferrstr = "Internal error: can't find filetype";
  4153. rc = 1;
  4154. }
  4155. if(rc) {
  4156. //RWD.7.99
  4157. #if defined CDP99 && defined _WIN32
  4158. CloseHandle(f->fileno);
  4159. DeleteFile(f->filename);
  4160. #else
  4161. fclose(f->fileno);
  4162. remove(f->filename);
  4163. #endif
  4164. freesffile(i);
  4165. return -1;
  4166. }
  4167. f->datachunksize = 0;
  4168. f->infochanged = 0;
  4169. f->todelete = 0;
  4170. if(outsize != 0)
  4171. *outsize = (unsigned int) f->sizerequested;
  4172. f->curpos = 0;
  4173. return i+SFDBASE;
  4174. }
  4175. //special version for wave-ex
  4176. //props is both in and out
  4177. #ifdef FILE64_WIN
  4178. int
  4179. sfcreat_ex(const char *name, __int64 size, __int64 *outsize,SFPROPS *props,int min_header,cdp_create_mode mode)
  4180. #else
  4181. int
  4182. sfcreat_ex(const char *name, __int64 size, __int64 *outsize,SFPROPS *props,int min_header,cdp_create_mode mode)
  4183. #endif
  4184. {
  4185. int i, rc;
  4186. int stype = -1;
  4187. struct sf_file *f;
  4188. char *sfpath;
  4189. char *ext_default = "wav"; /* RWD March 2014 */
  4190. unsigned long freespace = getdrivefreespace(name) - LEAVESPACE;
  4191. if((sfpath = mksfpath(name)) == NULL)
  4192. return -1;
  4193. if(min_header < SFILE_MINIMUM || min_header > SFILE_CDP){
  4194. rsferrno = ESFBADPARAM;
  4195. rsferrstr = "bad min_header spec";
  4196. return -1;
  4197. }
  4198. if((i = allocsffile(sfpath)) < 0)
  4199. return -1;
  4200. f = sf_files[i];
  4201. //RWD: this is OK, as it tells us we cannot CREATE more than one file of the same name, or one already opened
  4202. if(f->refcnt > 1) {
  4203. rsferrno = ESFNOTOPEN;
  4204. rsferrstr = "Can't open file more than once - yet!";
  4205. freesffile(i);
  4206. return -1;
  4207. }
  4208. //can only minimise header for wavefile!
  4209. if(props->type == wt_wave)
  4210. f->min_header = min_header;
  4211. //reject analysis formats if not floatsams
  4212. else{
  4213. if(props->samptype != FLOAT32){
  4214. rsferrno = ESFBADPARAM;
  4215. rsferrstr = "Analysis data must be floats";
  4216. freesffile(i);
  4217. return -1;
  4218. }
  4219. }
  4220. switch(props->samptype){
  4221. case (SHORT16):
  4222. stype = SAMP_SHORT;
  4223. break;
  4224. case(FLOAT32):
  4225. stype = SAMP_FLOAT;
  4226. break;
  4227. case(INT_32):
  4228. stype = SAMP_LONG;
  4229. break;
  4230. case(INT2424):
  4231. stype = SAMP_2424;
  4232. break;
  4233. case(INT2024):
  4234. stype = SAMP_2024;
  4235. break;
  4236. case(INT2432):
  4237. stype = SAMP_2432;
  4238. break;
  4239. default:
  4240. rsferrno = ESFBADPARAM;
  4241. rsferrstr = "unsupported sample type"; //add speaker mask stuff ere long, if WAVE_EX
  4242. freesffile(i);
  4243. return -1;
  4244. break;
  4245. }
  4246. #if defined CDP99 && defined _WIN32
  4247. if((f->fileno = doopen(f->filename, name,mode)) == INVALID_HANDLE_VALUE) {
  4248. DWORD w_errno = GetLastError();
  4249. #else
  4250. if((f->fileno = doopen(f->filename, name,mode)) == NULL) {
  4251. #endif
  4252. #if defined CDP99 && defined _WIN32
  4253. switch(w_errno) {
  4254. case ERROR_INVALID_NAME:
  4255. rsferrno = ESFNOTOPEN;
  4256. rsferrstr = "Can't create SFile, Illegal filename";
  4257. break;
  4258. case ERROR_FILE_EXISTS:
  4259. case ERROR_ALREADY_EXISTS:
  4260. rsferrno = ESFDUPFNAME;
  4261. rsferrstr = "Can't create SFile, already exists";
  4262. break;
  4263. case ERROR_ACCESS_DENIED:
  4264. rsferrno = ESFNOTOPEN;
  4265. rsferrstr = "Can't create SFile, permission denied";
  4266. break;
  4267. default:
  4268. rsferrno = ESFNOTOPEN;
  4269. rsferrstr = "Can't create SFile, Internal error";
  4270. }
  4271. #else
  4272. switch(errno) {
  4273. case EINVAL:
  4274. rsferrno = ESFNOTOPEN;
  4275. rsferrstr = "Can't create SFile, Illegal filename";
  4276. break;
  4277. case EEXIST:
  4278. rsferrno = ESFDUPFNAME;
  4279. rsferrstr = "Can't create SFile, already exists";
  4280. break;
  4281. case EACCES:
  4282. rsferrno = ESFNOTOPEN;
  4283. rsferrstr = "Can't create SFile, permission denied";
  4284. break;
  4285. default:
  4286. rsferrno = ESFNOTOPEN;
  4287. rsferrstr = "Can't create SFile, Internal error";
  4288. }
  4289. #endif
  4290. freesffile(i);
  4291. return -1;
  4292. }
  4293. if(size < 0)
  4294. f->sizerequested = freespace;
  4295. else if(size >= freespace) {
  4296. rsferrno = ESFNOSPACE;
  4297. rsferrstr = "Not enough space on Disk to create sound file";
  4298. //RWD.7.99
  4299. #if defined CDP99 && defined _WIN32
  4300. CloseHandle(f->fileno);
  4301. DeleteFile(f->filename);
  4302. #else
  4303. fclose(f->fileno);
  4304. remove(f->filename);
  4305. #endif
  4306. freesffile(i);
  4307. return -1;
  4308. } else
  4309. f->sizerequested = (size/* + 1*/)/* &~1*/; /*RWD use size+1) to get 16bit pad for 24bit files */
  4310. f->readonly = 0;
  4311. f->header_set = 0;
  4312. ///RWD.6.5.99 prepare peak storage: wave and binary envelope are OK
  4313. if(props->type == wt_wave || props->type== wt_binenv){
  4314. f->peaks = (CHPEAK *) calloc(props->chans, sizeof(CHPEAK));
  4315. if(f->peaks==NULL){
  4316. rsferrno = ESFNOMEM;
  4317. rsferrstr = "No memory to create peak data storage";
  4318. //RWD.7.99
  4319. #if defined CDP99 && defined _WIN32
  4320. CloseHandle(f->fileno);
  4321. DeleteFile(f->filename);
  4322. #else
  4323. fclose(f->fileno);
  4324. remove(f->filename);
  4325. #endif
  4326. freesffile(i);
  4327. return -1;
  4328. }
  4329. }
  4330. switch(f->filetype = gettypefromname98(f->filename)) {
  4331. char *ext;
  4332. /******* RWD.7.98 all we have to do to write a requested format is to fill in the data in f->fmtchunk
  4333. ******* and get wrwavhdr() to read this in! *****/
  4334. case riffwav:
  4335. if(props->chformat >= MC_STD){
  4336. f->filetype = wave_ex;
  4337. props->format = WAVE_EX;
  4338. rc = wrwavex(f, props);
  4339. }
  4340. else {
  4341. props->chformat = STDWAVE;
  4342. props->format = WAVE;
  4343. rc = wrwavhdr98(f,props->chans,props->srate,stype);
  4344. }
  4345. break;
  4346. //TODO: get the aiff extended formats sorted!
  4347. case eaaiff:
  4348. //for now, we have to IGNORE chformat requests
  4349. props->chformat = STDWAVE;
  4350. props->format = AIFF;
  4351. //make sure AIFF format is legal!
  4352. if(stype==SAMP_2432){
  4353. stype = SAMP_2424;
  4354. props->samptype = INT2424;
  4355. }
  4356. if(stype==SAMP_FLOAT){
  4357. //we now require AIFC for float formats
  4358. props->format = AIFC;
  4359. f->filetype = aiffc;
  4360. rc = wraifchdr(f,props->chans,props->srate,stype);
  4361. }
  4362. else
  4363. rc = wraiffhdr98(f,props->chans,props->srate,stype);
  4364. break;
  4365. case aiffc:
  4366. props->format = AIFC;
  4367. //make sure AIFF format is legal!
  4368. if(stype==SAMP_2432){
  4369. stype = SAMP_2424;
  4370. props->samptype = INT2424;
  4371. }
  4372. rc = wraifchdr(f,props->chans,props->srate,stype);
  4373. break;
  4374. case cdpfile:
  4375. /* RWD MAR 2015 as above */
  4376. if((ext = getenv("CDP_SOUND_EXT")) == NULL || strlen(ext) == 0) {
  4377. // rsferrno = ESFBADPARAM;
  4378. // rsferrstr = "unknown sound file type - extension not set";
  4379. //RWD.7.99
  4380. //#if defined CDP99 && defined _WIN32
  4381. // CloseHandle(f->fileno);
  4382. // DeleteFile(f->filename);
  4383. //#else
  4384. // fclose(f->fileno);
  4385. // remove(f->filename);
  4386. //#endif
  4387. // return -1;
  4388. ext = ext_default;
  4389. }
  4390. if(_stricmp(ext, "wav") == 0){
  4391. if(props->chformat > MC_STD){
  4392. f->filetype = wave_ex;
  4393. props->format = WAVE_EX;
  4394. rc = wrwavex(f, props);
  4395. }
  4396. else {
  4397. props->chformat = STDWAVE;
  4398. props->format = WAVE;
  4399. rc = wrwavhdr98(f,props->chans,props->srate,stype);
  4400. f->filetype = riffwav;
  4401. }
  4402. }
  4403. else if(_stricmp(ext, "aif") == 0 || _stricmp(ext, "aiff") == 0){
  4404. props->chformat = STDWAVE;
  4405. props->format = AIFF;
  4406. if(stype==SAMP_FLOAT){
  4407. //we now require AIFC for float formats
  4408. props->format = AIFC;
  4409. f->filetype = aiffc;
  4410. rc = wraifchdr(f,props->chans,props->srate,stype);
  4411. }
  4412. else {
  4413. rc = wraiffhdr98(f,props->chans,props->srate,stype);
  4414. f->filetype= eaaiff;
  4415. }
  4416. }
  4417. //RWD.1.99 temporary
  4418. else if(_stricmp(ext, "aic") == 0
  4419. || _stricmp(ext, "afc") == 0
  4420. || _stricmp(ext, "aifc") == 0){
  4421. props->format = AIFC;
  4422. f->filetype = aiffc;
  4423. rc = wraifchdr(f,props->chans,props->srate,stype);
  4424. }
  4425. else {
  4426. rsferrno = ESFBADPARAM;
  4427. rsferrstr = "unknown sound file type - bad CDP_SOUND_EXT setting";
  4428. //RWD.7.99
  4429. #if defined CDP99 && defined _WIN32
  4430. CloseHandle(f->fileno);
  4431. DeleteFile(f->filename);
  4432. #else
  4433. fclose(f->fileno);
  4434. remove(f->filename);
  4435. #endif
  4436. return -1;
  4437. }
  4438. break;
  4439. default:
  4440. rsferrno = ESFNOSTYPE;
  4441. rsferrstr = "Internal error: can't find filetype";
  4442. rc = 1;
  4443. }
  4444. if(rc) {
  4445. //RWD.7.99
  4446. #if defined CDP99 && defined _WIN32
  4447. CloseHandle(f->fileno);
  4448. DeleteFile(f->filename);
  4449. #else
  4450. fclose(f->fileno);
  4451. remove(f->filename);
  4452. #endif
  4453. freesffile(i);
  4454. return -1;
  4455. }
  4456. f->datachunksize = 0;
  4457. f->infochanged = 0;
  4458. f->todelete = 0;
  4459. if(outsize != 0)
  4460. *outsize = f->sizerequested;
  4461. f->curpos = 0;
  4462. if(props->type==wt_analysis){
  4463. /*Write all pvoc properties*/
  4464. if(addprop(f,"original sampsize",(char *)&(props->origsize), sizeof(/*long*/int))<0){
  4465. rsferrstr = "Failure to write original sample size";
  4466. return -1;
  4467. }
  4468. if(addprop(f,"original sample rate",(char *)&(props->origrate),sizeof(/*long*/int))<0){
  4469. rsferrstr = "Failure to write original sample rate";
  4470. }
  4471. if(addprop(f,"arate",(char *)&(props->arate),sizeof(float)) < 0){
  4472. rsferrstr = "Failure to write analysis sample rate";
  4473. }
  4474. if(addprop(f,"analwinlen",(char *)&(props->winlen),sizeof(int)) < 0){
  4475. rsferrstr = "Failure to write analysis window length";
  4476. }
  4477. if(addprop(f,"decfactor",(char *)&(props->decfac),sizeof(int)) < 0){
  4478. rsferrstr = "Failure to write decimation factor";
  4479. }
  4480. }
  4481. return i+SFDBASE;
  4482. }
  4483. //RWD.1.99 new func to enable current sfile (e.g temporary) to be reopened for writing
  4484. //return 1 for success, 0 for error
  4485. //new channel/sample formats are accepted, but the cdp_create_mode cannot be changed, nor the file format
  4486. //(without alot mre jiggery-pokery...)
  4487. //BIG QUESTION: ALLOW THIS ONLY FOR TEMPORARY FILES?
  4488. //note we do not call freesfile[] here, as the file is owned externally
  4489. //current dependency: GRAINMILL
  4490. //will need sndrecreat_formatted eventually, NB set buffer size for 24bit formats!
  4491. #ifdef FILE64_WIN
  4492. int
  4493. sfrecreat_formatted(int sfd, __int64 size, __int64 *outsize,int channels,
  4494. int srate, int stype)
  4495. #else
  4496. int
  4497. sfrecreat_formatted(int sfd, __int64 size, __int64 *outsize,int channels,
  4498. int srate, int stype)
  4499. #endif
  4500. {
  4501. int rc;
  4502. struct sf_file *f;
  4503. char *ext_default = "wav";
  4504. __int64 freespace;
  4505. //might as well validate the params
  4506. if(channels < 1 || srate <= 0)
  4507. return 0;
  4508. //ho hum, need stype as a typedef...
  4509. // we're not interested in 8-bit stuff!
  4510. if((stype >= SAMP_MASKED) || stype == SAMP_BYTE)
  4511. return 0;
  4512. if((f = findfile(sfd)) == 0)
  4513. return 0;
  4514. //RWD: this is OK, as it tells us we cannot CREATE more than one file of the same name, or one already opened
  4515. if(f->refcnt > 1) {
  4516. rsferrno = ESFNOTOPEN;
  4517. rsferrstr = "Can't (re)create file more than once!";
  4518. return 0;
  4519. }
  4520. if(f->readonly == 1)
  4521. return 0;
  4522. #if defined CDP99 && defined _WIN32
  4523. if(w_ch_size(f->fileno, 0L) < 0) {
  4524. #else
  4525. if(ftruncate(fileno(f->fileno), 0) < 0) {
  4526. #endif
  4527. rsferrno = ESFWRERR;
  4528. rsferrstr = "write error resetting file";
  4529. return 0;
  4530. }
  4531. freespace = getdrivefreespace(f->filename) - LEAVESPACE;
  4532. if(size < 0)
  4533. f->sizerequested = freespace;
  4534. else if((unsigned long)size >= freespace) {
  4535. rsferrno = ESFNOSPACE;
  4536. rsferrstr = "Not enough space on Disk to create sound file";
  4537. return 0;
  4538. } else
  4539. f->sizerequested = /*size&~1*/ size; /*RWD Nov 2001: accept 24bit samples */
  4540. f->readonly = 0;
  4541. f->header_set = 0;
  4542. //RWD.6.5.99 : accept PEAKS for now, but may need to forbid unless wave or binenv, as above
  4543. if(f->peaks){
  4544. free(f->peaks);
  4545. f->peaks = (CHPEAK *) calloc(channels,sizeof(CHPEAK));
  4546. if(f->peaks==NULL){
  4547. rsferrno = ESFNOMEM;
  4548. rsferrstr = "No memory for peak data";
  4549. return 0;
  4550. }
  4551. }
  4552. //we don't change f->min_header...
  4553. switch(f->filetype) {
  4554. char *ext;
  4555. case riffwav:
  4556. rc = wrwavhdr98(f,channels,srate,stype);
  4557. break;
  4558. case eaaiff:
  4559. //make sure AIFF format is legal!
  4560. if(stype==SAMP_2432){
  4561. //reject here, as can't tell caller
  4562. rsferrno = ESFBADPARAM;
  4563. rsferrstr = "requested sample type illegal for AIFF files";
  4564. return -1;
  4565. }
  4566. if(stype==SAMP_FLOAT){
  4567. //we now require AIFC for float formats
  4568. f->filetype = aiffc;
  4569. rc = wraifchdr(f,channels,srate,stype);
  4570. }
  4571. else
  4572. rc = wraiffhdr98(f,channels,srate,stype);
  4573. break;
  4574. case aiffc:
  4575. //make sure AIFF format is legal!
  4576. if(stype==SAMP_2432){
  4577. //reject here, as can't tell caller
  4578. rsferrno = ESFBADPARAM;
  4579. rsferrstr = "requested sample type illegal for AIFF files";
  4580. return -1;
  4581. }
  4582. rc = wraifchdr(f,channels,srate,stype);
  4583. break;
  4584. case cdpfile:
  4585. /* RWD MAR 2015 as above */
  4586. if((ext = getenv("CDP_SOUND_EXT")) == NULL || strlen(ext) == 0) {
  4587. // rsferrno = ESFBADPARAM;
  4588. // rsferrstr = "unknown sound file type - extension not set";
  4589. // rc = 1;
  4590. ext = ext_default;
  4591. }
  4592. if(_stricmp(ext, "wav") == 0){
  4593. rc = wrwavhdr98(f,channels,srate,stype);
  4594. f->filetype = riffwav;
  4595. }
  4596. else if(_stricmp(ext, "aif") == 0 || _stricmp(ext, "aiff") == 0){
  4597. if(stype==SAMP_FLOAT){
  4598. //we now require AIFC for float formats
  4599. f->filetype = aiffc;
  4600. rc = wraifchdr(f,channels,srate,stype);
  4601. }
  4602. else {
  4603. rc = wraiffhdr98(f,channels,srate,stype);
  4604. f->filetype= eaaiff;
  4605. }
  4606. }
  4607. //RWD.1.99 temporary
  4608. else if(_stricmp(ext, "aic") == 0
  4609. || _stricmp(ext, "afc") == 0
  4610. || _stricmp(ext, "aifc") == 0){
  4611. f->filetype = aiffc;
  4612. rc = wraifchdr(f,channels,srate,stype);
  4613. }
  4614. else {
  4615. rsferrno = ESFBADPARAM;
  4616. rsferrstr = "unknown sound file type - bad CDP_SOUND_EXT setting";
  4617. rc = 1;
  4618. }
  4619. break;
  4620. default:
  4621. rsferrno = ESFNOSTYPE;
  4622. rsferrstr = "Internal error: can't find filetype";
  4623. rc = 1;
  4624. }
  4625. if(rc) {
  4626. return 0;
  4627. }
  4628. f->datachunksize = 0;
  4629. f->infochanged = 0;
  4630. f->todelete = 0;
  4631. if(outsize != 0)
  4632. *outsize = f->sizerequested;
  4633. f->curpos = 0;
  4634. return 1;
  4635. }
  4636. //RWD OCT97
  4637. int
  4638. sfgetwordsize(int sfd)
  4639. {
  4640. struct sf_file *f;
  4641. if((f = findfile(sfd)) == 0)
  4642. return -1;
  4643. return f->fmtchunkEx.Format.wBitsPerSample;
  4644. }
  4645. #ifdef FILE64_WIN
  4646. __int64 sfgetdatasize(int sfd)
  4647. #else
  4648. __int64
  4649. sfgetdatasize(int sfd)
  4650. #endif
  4651. {
  4652. struct sf_file *f;
  4653. if((f = findfile(sfd)) == 0)
  4654. return -1;
  4655. return f->datachunksize;
  4656. }
  4657. #if defined CDP97 && defined _WIN32
  4658. int sf_is_shortcut(int sfd,char *name)
  4659. {
  4660. struct sf_file *f;
  4661. if((f = findfile(sfd)) == 0)
  4662. return -1;
  4663. if(f->is_shortcut){
  4664. if(name != NULL)
  4665. strcpy(name,f->filename);
  4666. }
  4667. return f->is_shortcut;
  4668. }
  4669. #endif
  4670. /*RWD: nb cnt arg is seen as count of BYTES to fill (expecting cnt/sizeof(sample) words);
  4671. f->curpos expected to contain bytes of SHORTS or FLOATS
  4672. */
  4673. int
  4674. sfread(int sfd, char *buf, int cnt)
  4675. {
  4676. struct sf_file *f;
  4677. short *sp;
  4678. DWORD *dp;
  4679. __int64 remain;
  4680. int i;
  4681. //int got = 0;
  4682. if((f = findfile(sfd)) == 0)
  4683. return -1;
  4684. cnt = cnt & ~(SECSIZE-1);
  4685. /*RWD OCT97: here, remain IS size-specific, so curpos must be, too*/
  4686. if((remain = (int)(f->datachunksize - f->curpos)) < 0)
  4687. remain = 0;
  4688. if(cnt > remain)
  4689. cnt = remain;
  4690. if(cnt == 0)
  4691. return 0;
  4692. if(f->fmtchunkEx.Format.wBitsPerSample == 8)
  4693. cnt /= 2; /*see below...*/
  4694. if(doread(f, buf, cnt)) { /*bytes, bytecnt*/
  4695. rsferrno = ESFRDERR;
  4696. rsferrstr = "Read error";
  4697. return -1;
  4698. }
  4699. switch(f->fmtchunkEx.Format.wBitsPerSample) {
  4700. case 8:
  4701. if(f->filetype == riffwav || f->filetype ==wave_ex) {
  4702. for(i = cnt-1; i >= 0; i--)
  4703. ((short *)buf)[i] = (buf[i]-128)<<8;
  4704. } else if((f->filetype == eaaiff) || (f->filetype==aiffc)) { //RWD.1.99
  4705. for(i = cnt-1; i >= 0; i--)
  4706. ((short *)buf)[i] = ((signed char *)buf)[i];
  4707. } else
  4708. abort(); //RWD ouch!
  4709. cnt *= 2; // restored from above
  4710. break;
  4711. case 16:
  4712. if(REVDATAINFILE(f)) {
  4713. sp = (short *)buf;
  4714. for(i = cnt/sizeof(short); i > 0; i--) {
  4715. *sp = REVWBYTES(*sp);
  4716. sp++;
  4717. }
  4718. }
  4719. break;
  4720. case 32:
  4721. if(REVDATAINFILE(f)) {
  4722. dp = (DWORD *)buf;
  4723. for(i = cnt/sizeof(DWORD); i > 0; i--) {
  4724. *dp = REVDWBYTES(*dp);
  4725. dp++;
  4726. }
  4727. }
  4728. break;
  4729. default:
  4730. // abort(); // ouch again!
  4731. //RW.6.99
  4732. rsferrno = ESFBADPARAM;
  4733. rsferrstr = "cannot read unsupported sample type";
  4734. return -1;
  4735. }
  4736. f->curpos += cnt; //assumes pos in SHORTS or FLOATS buffer
  4737. return cnt;
  4738. }
  4739. //RWD: the original func - no support for new formats, but must eliminate abort() call!
  4740. /* RWD 2007 NB : these funcs all return -1 for error, so are forced to handle only signed longs */
  4741. /* therefore: NOT ready for 4GB files ! */
  4742. int
  4743. sfwrite(int sfd, char *outbuf, int cnt)
  4744. {
  4745. struct sf_file *f;
  4746. int i;
  4747. __int64 remain;
  4748. short *ssp, *sdp;
  4749. DWORD *dsp, *ddp;
  4750. char *buf = outbuf;
  4751. if((f = findfile(sfd)) == 0)
  4752. return -1;
  4753. if(f->readonly) {
  4754. rsferrno = ESFREADONLY;
  4755. rsferrstr = "Can't write to read only file";
  4756. return -1;
  4757. }
  4758. if(f->fmtchunkEx.Format.wBitsPerSample == 8) {
  4759. rsferrno = ESFREADONLY;
  4760. rsferrstr = "Can't write to 8bits/sample files";
  4761. return -1;
  4762. }
  4763. cnt = cnt & ~(SECSIZE-1);
  4764. if(f->sizerequested >= 0) { /* creating file - explicit size */
  4765. if((remain = f->sizerequested - f->curpos) < 0)
  4766. remain = 0;
  4767. if(cnt > (int) remain)
  4768. cnt = (int) remain;
  4769. } else if(f->sizerequested == ES_EXIST) { /* existing file - can't change size */
  4770. if((remain = f->datachunksize - f->curpos) < 0)
  4771. remain = 0;
  4772. if(cnt > (int) remain)
  4773. cnt = (int) remain;
  4774. }
  4775. if(cnt == 0)
  4776. return 0;
  4777. if(REVDATAINFILE(f)) {
  4778. if((buf = (char *) malloc(cnt)) == 0) {
  4779. rsferrno = ESFWRERR;
  4780. rsferrstr = "Write error: can't allocate byte swap buffer";
  4781. return -1;
  4782. }
  4783. switch(f->fmtchunkEx.Format.wBitsPerSample) {
  4784. case 16:
  4785. ssp = (short *)outbuf;
  4786. sdp = (short *)buf;
  4787. for(i = cnt/sizeof(short); i > 0; i--) {
  4788. *sdp = REVWBYTES(*ssp);
  4789. ssp++;
  4790. sdp++;
  4791. }
  4792. break;
  4793. case 32:
  4794. dsp = (DWORD *)outbuf;
  4795. ddp = (DWORD *)buf;
  4796. for(i = cnt/sizeof(DWORD); i > 0; i--) {
  4797. *ddp = REVDWBYTES(*dsp);
  4798. dsp++;
  4799. ddp++;
  4800. }
  4801. break;
  4802. default:
  4803. #ifdef NOTDEF
  4804. abort();
  4805. #endif
  4806. rsferrno = ESFBADPARAM;
  4807. rsferrstr = "cannot write unsupported sample format";
  4808. return -1;
  4809. }
  4810. }
  4811. /* else creating file - max size */
  4812. if(dowrite(f, buf, cnt)) {
  4813. rsferrno = ESFWRERR;
  4814. rsferrstr = "Write error";
  4815. if(buf != outbuf)
  4816. free(buf);
  4817. return -1;
  4818. }
  4819. f->curpos += cnt;
  4820. if(f->curpos > f->datachunksize) {
  4821. f->datachunksize = f->curpos;
  4822. f->infochanged = 1;
  4823. }
  4824. if(buf != outbuf)
  4825. free(buf);
  4826. return cnt;
  4827. }
  4828. /* RWD: OBSOLETE - NOT IN USE NOW! */
  4829. int
  4830. sfseek(int sfd, int dist, int whence)
  4831. {
  4832. struct sf_file *f;
  4833. unsigned int newpos = 0u;
  4834. unsigned int size;
  4835. fpos_t bytepos;
  4836. if((f = findfile(sfd)) == 0)
  4837. return -1;
  4838. /*RWD 2007 added casts to silence compiler! */
  4839. size = (unsigned int) sfsize(sfd); /* NB Can't fail! */ //RWD OCT97: NB: assumes file of SHORTS or FLOATS
  4840. switch(whence) {
  4841. case 0:
  4842. newpos = dist;
  4843. break;
  4844. case 1:
  4845. newpos = f->curpos + dist;
  4846. break;
  4847. case 2:
  4848. newpos = size + dist;
  4849. break;
  4850. default:
  4851. rsferrno = ESFBADPARAM;
  4852. rsferrstr = "illegal whence value in sfseek";
  4853. break;
  4854. }
  4855. /* RWD MAR 2015 just to eliminate compiler warning */
  4856. //if(newpos < 0)
  4857. // newpos = 0;
  4858. if(newpos > size)
  4859. newpos = size;
  4860. newpos &= ~(SECSIZE-1);
  4861. f->curpos = newpos; //still size-specific here...
  4862. //RWD OCT97 must seek correctly in 8bit files
  4863. if(f->fmtchunkEx.Format.wBitsPerSample==8)
  4864. newpos /= 2;
  4865. #if defined _WIN32
  4866. newpos += f->datachunkoffset;
  4867. if(SetFilePointer(f->fileno, newpos,NULL, FILE_BEGIN) != newpos) {
  4868. #else
  4869. POS64(bytepos) = newpos + POS64(f->datachunkoffset);
  4870. if(fsetpos(f->fileno, &bytepos) ) {
  4871. #endif
  4872. rsferrno = ESFRDERR; //RWD CDP97
  4873. rsferrstr = "Seek error";
  4874. return -1;
  4875. }
  4876. return f->curpos;
  4877. }
  4878. static char * REV3BYTES(char *samp_24){
  4879. //trick here: just exchange the outer bytes!
  4880. char temp = samp_24[0];
  4881. *samp_24 = samp_24[2];
  4882. samp_24[2] = temp;
  4883. return samp_24;
  4884. }
  4885. /* special buffered sf_routines for new sample sizes */
  4886. int
  4887. sfread_buffered(int sfd, char *buf, int lcnt)
  4888. {
  4889. struct sf_file *f;
  4890. short *sp;
  4891. DWORD *dp;
  4892. #ifdef FILE64_WIN
  4893. __int64 remain,i;
  4894. __int64 cnt = lcnt; /*RWD 2007: lcnt used some places below */
  4895. long containersize;
  4896. #else
  4897. __int64 remain;
  4898. __int64 cnt = lcnt;
  4899. int i,containersize;
  4900. #endif
  4901. //int got = 0;
  4902. if((f = findfile(sfd)) == 0)
  4903. return -1;
  4904. //RWD OCT97: here, remain IS size-specific, so curpos must be, too
  4905. if((remain = (__int64) (f->datachunksize - f->curpos)) < 0)
  4906. remain = 0;
  4907. #ifdef FILE64_WIN
  4908. if((__int64) cnt > remain)
  4909. cnt = (unsigned int) remain;
  4910. #else
  4911. if(cnt > remain)
  4912. cnt = remain;
  4913. #endif
  4914. if(cnt == 0)
  4915. return 0;
  4916. if(f->fmtchunkEx.Format.wBitsPerSample == 8)
  4917. cnt /= 2; //see below...
  4918. if(doread(f, buf, (int) cnt)) { //bytes, bytecnt
  4919. rsferrno = ESFRDERR;
  4920. rsferrstr = "Read error";
  4921. return -1;
  4922. }
  4923. containersize = 8 * (f->fmtchunkEx.Format.nBlockAlign / f->fmtchunkEx.Format.nChannels);
  4924. switch(containersize) {
  4925. case 8:
  4926. if(f->filetype == riffwav || f->filetype ==wave_ex) {
  4927. for(i = cnt-1; i >= 0; i--)
  4928. ((short *)buf)[i] = (buf[i]-128)<<8;
  4929. } else if((f->filetype == eaaiff) || (f->filetype==aiffc)) { //RWD.1.99
  4930. for(i = cnt-1; i >= 0; i--)
  4931. ((short *)buf)[i] = ((signed char *)buf)[i];
  4932. } else
  4933. abort(); //RWD ouch!
  4934. cnt *= 2; // restored from above
  4935. break;
  4936. case 16:
  4937. if(REVDATAINFILE(f)) {
  4938. sp = (short *)buf;
  4939. for(i = cnt/sizeof(short); i > 0; i--) {
  4940. *sp = REVWBYTES(*sp);
  4941. sp++;
  4942. }
  4943. }
  4944. break;
  4945. case(24):
  4946. if(REVDATAINFILE(f)) {
  4947. char *p_byte = buf;
  4948. for(i = cnt/3; i > 0; i--) {
  4949. p_byte = REV3BYTES(p_byte);
  4950. p_byte += 3;
  4951. }
  4952. }
  4953. break;
  4954. case 32:
  4955. if(REVDATAINFILE(f)) {
  4956. dp = (DWORD *)buf;
  4957. for(i = cnt/sizeof(DWORD); i > 0; i--) {
  4958. *dp = REVDWBYTES(*dp);
  4959. dp++;
  4960. }
  4961. }
  4962. break;
  4963. default:
  4964. #ifdef NOTDEF
  4965. abort(); // ouch again!
  4966. #endif
  4967. rsferrno = ESFBADPARAM;
  4968. rsferrstr = "unsupported sample format";
  4969. return -1;
  4970. }
  4971. f->curpos += (DWORD) cnt; //assumes pos in SHORTS or FLOATS buffer
  4972. return (int) cnt;
  4973. }
  4974. //RWD.7.99 TODO: use blockalign to decide what size word to write
  4975. int
  4976. sfwrite_buffered(int sfd, char *outbuf, int lcnt)
  4977. {
  4978. struct sf_file *f;
  4979. //unsigned int remain, cnt = lcnt; /* RWD Feb 2010 */
  4980. __int64 remain;
  4981. __int64 cnt = lcnt;
  4982. short *ssp, *sdp;
  4983. DWORD *dsp, *ddp;
  4984. char *buf = outbuf;
  4985. int containersize;
  4986. if((f = findfile(sfd)) == 0)
  4987. return -1;
  4988. if(f->readonly) {
  4989. rsferrno = ESFREADONLY;
  4990. rsferrstr = "Can't write to read only file";
  4991. return -1;
  4992. }
  4993. if(f->fmtchunkEx.Format.wBitsPerSample == 8) {
  4994. rsferrno = ESFREADONLY;
  4995. rsferrstr = "Can't write to 8bits/sample files";
  4996. return -1;
  4997. }
  4998. //cnt = cnt & ~(SECSIZE-1);
  4999. if(f->sizerequested >= 0) { /* creating file - explicit size */
  5000. if((remain = f->sizerequested - f->curpos) < 0)
  5001. remain = 0;
  5002. if(cnt > remain)
  5003. cnt = remain;
  5004. } else if(f->sizerequested == ES_EXIST) { /* existing file - can't change size */
  5005. if((remain = f->datachunksize - f->curpos) < 0)
  5006. remain = 0;
  5007. if(cnt > remain)
  5008. cnt = remain;
  5009. }
  5010. if(cnt == 0)
  5011. return 0;
  5012. containersize = 8 * (f->fmtchunkEx.Format.nBlockAlign / f->fmtchunkEx.Format.nChannels);
  5013. if(REVDATAINFILE(f)) {
  5014. int i; /* RWD Feb 2010: should be OK as signed; too risky unsigned in a loop! */
  5015. if((buf = (char *) malloc((size_t) cnt)) == 0) { /*RWD 2007 */
  5016. rsferrno = ESFWRERR;
  5017. rsferrstr = "Write error: can't allocate byte swap buffer";
  5018. return -1;
  5019. }
  5020. switch(containersize) {
  5021. char *p_byte;
  5022. char *p_buf;
  5023. case 16:
  5024. ssp = (short *)outbuf;
  5025. sdp = (short *)buf;
  5026. for(i = cnt/sizeof(short); i > 0; i--) {
  5027. *sdp = REVWBYTES(*ssp);
  5028. ssp++;
  5029. sdp++;
  5030. }
  5031. break;
  5032. case 32:
  5033. dsp = (DWORD *)outbuf;
  5034. ddp = (DWORD *)buf;
  5035. for(i = cnt/sizeof(DWORD); i > 0; i--) {
  5036. *ddp = REVDWBYTES(*dsp);
  5037. dsp++;
  5038. ddp++;
  5039. }
  5040. break;
  5041. //case 20:
  5042. case 24:
  5043. p_byte = outbuf;
  5044. p_buf = buf;
  5045. for(i= cnt/3; i > 0; i--){
  5046. p_buf[0] = p_byte[2];
  5047. p_buf[1] = p_byte[1];
  5048. p_buf[2] = p_byte[0];
  5049. p_byte += 3;
  5050. p_buf += 3;
  5051. }
  5052. break;
  5053. default:
  5054. //abort();
  5055. rsferrno = ESFBADPARAM;
  5056. rsferrstr = "unsupported sample format";
  5057. if(buf != outbuf)
  5058. free(buf);
  5059. return -1;
  5060. break;
  5061. }
  5062. }
  5063. /* else creating file - max size */
  5064. if(dowrite(f, buf, (int) cnt)) {
  5065. rsferrno = ESFWRERR;
  5066. rsferrstr = "Write error";
  5067. if(buf != outbuf)
  5068. free(buf);
  5069. return -1;
  5070. }
  5071. f->curpos += (DWORD) cnt;
  5072. if(f->curpos > (DWORD) f->datachunksize) {
  5073. f->datachunksize = f->curpos;
  5074. f->infochanged = 1;
  5075. }
  5076. if(buf != outbuf)
  5077. free(buf);
  5078. return (int) cnt;
  5079. }
  5080. #ifdef FILE64_WIN
  5081. /* RWD 2007 remember dist can be negative... */
  5082. __int64
  5083. sfseek_buffered(int sfd, __int64 dist, int whence)
  5084. {
  5085. struct sf_file *f;
  5086. /*unsigned long*/__int64 newpos = 0;
  5087. __int64 i64size;
  5088. LARGE_INTEGER pos64;
  5089. if((f = findfile(sfd)) == 0)
  5090. return -1;
  5091. i64size = sfsize(sfd); /* NB Can't fail! */ //RWD OCT97: NB: assumes file of SHORTS or FLOATS
  5092. switch(whence) {
  5093. case 0:
  5094. newpos = dist;
  5095. break;
  5096. case 1:
  5097. newpos = (__int64) f->curpos + dist;
  5098. break;
  5099. case 2:
  5100. newpos = i64size + dist;
  5101. break;
  5102. default:
  5103. rsferrno = ESFBADPARAM;
  5104. rsferrstr = "illegal whence value in sfseek";
  5105. break;
  5106. }
  5107. if(newpos < 0)
  5108. newpos = 0;
  5109. if(newpos > i64size)
  5110. newpos = i64size;
  5111. f->curpos = (unsigned int) newpos; //still size-specific here...
  5112. //RWD OCT97 must seek correctly in 8bit files
  5113. if(f->fmtchunkEx.Format.wBitsPerSample==8)
  5114. newpos /= 2;
  5115. newpos += f->datachunkoffset;
  5116. //#endif
  5117. #if defined _WIN32
  5118. pos64.QuadPart = newpos;
  5119. pos64.LowPart = SetFilePointer(f->fileno, pos64.LowPart,&pos64.HighPart, FILE_BEGIN);
  5120. if(pos64.LowPart==0xFFFFFFFF && GetLastError() != NO_ERROR){
  5121. /* != newpos) { */
  5122. rsferrno = ESFRDERR; //RWD CDP97
  5123. rsferrstr = "Seek error";
  5124. return -1;
  5125. }
  5126. if(pos64.QuadPart != newpos){
  5127. rsferrno = ESFRDERR;
  5128. rsferrstr = "Seek error";
  5129. return -1;
  5130. }
  5131. #else
  5132. if(lseek(f->fileno, newpos, SEEK_SET) != newpos) {
  5133. rsferrno = ESFRDERR; //RWD CDP97
  5134. rsferrstr = "Seek error";
  5135. return -1;
  5136. }
  5137. #endif
  5138. return f->curpos;
  5139. }
  5140. #else
  5141. __int64
  5142. sfseek_buffered(int sfd, __int64 dist, int whence)
  5143. {
  5144. struct sf_file *f;
  5145. __int64 newpos = 0; // allow max seek distance 2GB
  5146. __int64 size;
  5147. fpos_t bytepos;
  5148. if((f = findfile(sfd)) == 0)
  5149. //return -1;
  5150. return 0xFFFFFFFF;
  5151. size = sfsize(sfd); /* NB Can't fail! */ //RWD OCT97: NB: assumes file of SHORTS or FLOATS
  5152. switch(whence) {
  5153. case 0:
  5154. newpos = dist;
  5155. break;
  5156. case 1:
  5157. newpos = f->curpos + dist;
  5158. break;
  5159. case 2:
  5160. newpos = size + dist;
  5161. break;
  5162. default:
  5163. rsferrno = ESFBADPARAM;
  5164. rsferrstr = "illegal whence value in sfseek";
  5165. break;
  5166. }
  5167. if(newpos < 0)
  5168. newpos = 0;
  5169. if(newpos > size)
  5170. newpos = size;
  5171. f->curpos = (DWORD) newpos; //still size-specific here...
  5172. //RWD OCT97 must seek correctly in 8bit files
  5173. if(f->fmtchunkEx.Format.wBitsPerSample==8)
  5174. newpos /= 2;
  5175. //
  5176. //#endif
  5177. #if defined _WIN32
  5178. newpos += f->datachunkoffset;
  5179. if(SetFilePointer(f->fileno, newpos,NULL, FILE_BEGIN) != newpos) {
  5180. #else
  5181. POS64(bytepos) = (DWORD) newpos + POS64(f->datachunkoffset);
  5182. if(fsetpos(f->fileno, &bytepos)) {
  5183. #endif
  5184. rsferrno = ESFRDERR; //RWD CDP97
  5185. rsferrstr = "Seek error";
  5186. return -1;
  5187. }
  5188. return (__int64) f->curpos;
  5189. }
  5190. #endif
  5191. //RWD: this may not be sufficient: we may want to distinguish betweeen
  5192. // float sfiles and analfiles....
  5193. static int
  5194. wavupdate(struct sf_file *f)
  5195. {
  5196. unsigned long seekdist;
  5197. fpos_t bytepos;
  5198. switch(f->fmtchunkEx.Format.wBitsPerSample) {
  5199. case 8:
  5200. f->fmtchunkEx.Format.nAvgBytesPerSec = f->fmtchunkEx.Format.nBlockAlign = f->fmtchunkEx.Format.nChannels;
  5201. f->datachunksize /= 2;
  5202. break;
  5203. case 16:
  5204. f->fmtchunkEx.Format.nAvgBytesPerSec = f->fmtchunkEx.Format.nBlockAlign = f->fmtchunkEx.Format.nChannels * 2;
  5205. break;
  5206. case 32:
  5207. f->fmtchunkEx.Format.nAvgBytesPerSec = f->fmtchunkEx.Format.nBlockAlign = f->fmtchunkEx.Format.nChannels * 4;
  5208. f->fmtchunkEx.Format.wFormatTag = WAVE_FORMAT_IEEE_FLOAT; //RWD 07:97
  5209. //RWD TODO: update 'fact' chunk with num-samples
  5210. break;
  5211. default:
  5212. abort();
  5213. }
  5214. f->fmtchunkEx.Format.nAvgBytesPerSec *= f->fmtchunkEx.Format.nSamplesPerSec;
  5215. //add space for fact chunk ?
  5216. //WARNING: THIS HAS NOT BEEN FULLY TESTED!
  5217. // maxsamp needed this...writes directly to existing header on disk
  5218. //f->extrachunksizes = 3*sizeof(DWORD);
  5219. f->mainchunksize = POS64(f->datachunkoffset) + (DWORD) f->datachunksize - 2*sizeof(DWORD) + f->extrachunksizes;
  5220. #if defined _WIN32
  5221. if(SetFilePointer(f->fileno, 4L,NULL, FILE_BEGIN)== 0xFFFFFFFF
  5222. #else
  5223. if(fseek(f->fileno, 4L, SEEK_SET) < 0
  5224. #endif
  5225. || write_dw_lsf(f->mainchunksize, f)
  5226. #if defined _WIN32
  5227. || SetFilePointer(f->fileno, f->fmtchunkoffset,NULL, FILE_BEGIN)== 0xFFFFFFFF
  5228. || write_w_lsf(f->fmtchunkEx.Format.wFormatTag, f)
  5229. || write_w_lsf(f->fmtchunkEx.Format.nChannels, f)
  5230. || write_dw_lsf(f->fmtchunkEx.Format.nSamplesPerSec, f)
  5231. || write_dw_lsf(f->fmtchunkEx.Format.nAvgBytesPerSec, f)
  5232. || write_w_lsf(f->fmtchunkEx.Format.nBlockAlign, f)
  5233. || write_w_lsf(f->fmtchunkEx.Format.wBitsPerSample, f)){
  5234. rsferrno = ESFWRERR;
  5235. rsferrstr = "Write error: Can't update format data";
  5236. return -1;
  5237. }
  5238. #else
  5239. || fsetpos(f->fileno, &f->fmtchunkoffset)
  5240. || write_w_lsf(f->fmtchunkEx.Format.wFormatTag, f)
  5241. || write_w_lsf(f->fmtchunkEx.Format.nChannels, f)
  5242. || write_dw_lsf(f->fmtchunkEx.Format.nSamplesPerSec, f)
  5243. || write_dw_lsf(f->fmtchunkEx.Format.nAvgBytesPerSec, f)
  5244. || write_w_lsf(f->fmtchunkEx.Format.nBlockAlign, f)
  5245. || write_w_lsf(f->fmtchunkEx.Format.wBitsPerSample, f)){
  5246. rsferrno = ESFWRERR;
  5247. rsferrstr = "Write error: Can't update format data";
  5248. return -1;
  5249. }
  5250. #endif
  5251. //RWD OCT97: the extra cbSize field SHOULD be there, = 0
  5252. //fact chunk contains size in samples
  5253. if(f->fmtchunkEx.Format.wFormatTag == WAVE_FORMAT_IEEE_FLOAT){
  5254. if(POS64(f->factchunkoffset) > 0){ /*RWD 01:2004 */
  5255. #if defined _WIN32
  5256. if(SetFilePointer(f->fileno,f->factchunkoffset,NULL,FILE_BEGIN)== 0xFFFFFFFF
  5257. #else
  5258. if(fsetpos(f->fileno,&f->factchunkoffset)
  5259. #endif
  5260. ||write_dw_lsf((DWORD)(f->datachunksize / (f->fmtchunkEx.Format.wBitsPerSample / sizeof(char))),f)){ /*RWD 2007 */
  5261. rsferrno = ESFWRERR;
  5262. rsferrstr = "Write error: Can't update fact chunk for floatsam data";
  5263. return -1;
  5264. }
  5265. }
  5266. }
  5267. #if defined _WIN32
  5268. if(SetFilePointer(f->fileno, f->datachunkoffset - sizeof(DWORD),NULL, FILE_BEGIN)== 0xFFFFFFFF
  5269. #else
  5270. seekdist = POS64(f->datachunkoffset) - sizeof(DWORD);
  5271. POS64(bytepos) = seekdist;
  5272. if(fsetpos(f->fileno, &bytepos)
  5273. #endif
  5274. ||write_dw_lsf((DWORD) f->datachunksize, f) ) { /*RWD 2007 */
  5275. rsferrno = ESFWRERR;
  5276. rsferrstr = "Write error: Can't update data size";
  5277. return -1;
  5278. }
  5279. return 0;
  5280. }
  5281. /******* SFSY98 VERSION*******
  5282. ******* main format data already there - just update durations
  5283. */
  5284. //RWD.5.99 TODO: need to be more clever with extended formats:
  5285. //must distinguish 32bit int and float
  5286. //this is used when header has already been set
  5287. static int
  5288. wavupdate98(time_t thistime, struct sf_file *f)
  5289. {
  5290. fpos_t bytepos;
  5291. if(! f->header_set)
  5292. return -1;
  5293. if(f->fmtchunkEx.Format.wBitsPerSample == 8)
  5294. f->datachunksize /= 2;
  5295. f->mainchunksize = POS64(f->datachunkoffset) + (DWORD) f->datachunksize - 2*sizeof(DWORD) + f->extrachunksizes;
  5296. #if defined _WIN32
  5297. if(SetFilePointer(f->fileno, 4L,NULL, FILE_BEGIN)== 0xFFFFFFFF
  5298. #else
  5299. if(fseek(f->fileno, 4L, SEEK_SET) < 0
  5300. #endif
  5301. ||write_dw_lsf(f->mainchunksize, f)){
  5302. rsferrno = ESFWRERR;
  5303. rsferrstr = "SFSY98: Write error: Can't update datachunk size";
  5304. return -1;
  5305. }
  5306. #ifdef NOTDEF
  5307. if(f->infochanged){
  5308. #ifdef _WIN32
  5309. if(SetFilePointer(f->fileno, f->fmtchunkoffset,NULL, FILE_BEGIN)== 0xFFFFFFFF
  5310. #else
  5311. if(fsetpos(f->fileno, &f->fmtchunkoffset)
  5312. #endif
  5313. ||write_w_lsf(f->fmtchunkEx.Format.wFormatTag, f)
  5314. ||write_w_lsf(f->fmtchunkEx.Format.nChannels, f)
  5315. ||write_dw_lsf(f->fmtchunkEx.Format.nSamplesPerSec, f)
  5316. ||write_dw_lsf(f->fmtchunkEx.Format.nAvgBytesPerSec, f)
  5317. ||write_w_lsf(f->fmtchunkEx.Format.nBlockAlign, f)
  5318. ||write_w_lsf(f->fmtchunkEx.Format.wBitsPerSample, f)){
  5319. rsferrno = ESFWRERR;
  5320. rsferrstr = "SFSYS98: Write error: Can't update chunk sizes or info chunk";
  5321. return -1;
  5322. }
  5323. }
  5324. #endif
  5325. if(f->fmtchunkEx.Format.wFormatTag == WAVE_FORMAT_IEEE_FLOAT){
  5326. //fact chunk contains size in samples
  5327. //RWD.5.99 may not be using it...
  5328. if(POS64(f->factchunkoffset) > 0){
  5329. #if defined _WIN32
  5330. if(SetFilePointer(f->fileno,f->factchunkoffset,NULL,FILE_BEGIN)== 0xFFFFFFFF
  5331. #else
  5332. if(fsetpos(f->fileno,&f->factchunkoffset)
  5333. #endif
  5334. || write_dw_lsf((DWORD)(f->datachunksize / (f->fmtchunkEx.Format.wBitsPerSample / sizeof(char))),f)) {
  5335. rsferrno = ESFWRERR;
  5336. rsferrstr = "SFSYS98: Write error: Can't update fact chunk for floatsam file";
  5337. return -1;
  5338. }
  5339. }
  5340. }
  5341. //RWD.6.5.99 update peak chunk
  5342. if((f->min_header >= SFILE_PEAKONLY) && f->peaks){
  5343. #if defined _WIN32
  5344. if(SetFilePointer(f->fileno,f->peakchunkoffset + sizeof(DWORD),NULL,FILE_BEGIN)== 0xFFFFFFFF
  5345. #else
  5346. fpos_t target = f->peakchunkoffset;
  5347. POS64(target) += sizeof(DWORD);
  5348. //if(lseek(f->fileno,f->peakchunkoffset + sizeof(DWORD),SEEK_SET) < 0
  5349. if(fsetpos(f->fileno,&target)
  5350. #endif
  5351. || write_dw_lsf((DWORD) thistime,f)
  5352. || write_peak_lsf(f->fmtchunkEx.Format.nChannels,f)) {
  5353. rsferrno = ESFWRERR;
  5354. rsferrstr = "SFSYS98: Write error: Can't update peak chunk";
  5355. return -1;
  5356. }
  5357. }
  5358. #if defined _WIN32
  5359. if(SetFilePointer(f->fileno, f->datachunkoffset - sizeof(DWORD),NULL, FILE_BEGIN)== 0xFFFFFFFF
  5360. ||write_dw_lsf((DWORD) f->datachunksize, f) ) {
  5361. #else
  5362. bytepos = f->datachunkoffset;
  5363. POS64(bytepos) -= sizeof(DWORD);
  5364. //if(lseek(f->fileno, f->datachunkoffset - sizeof(DWORD), SEEK_SET) < 0
  5365. // ||write_dw_lsf((DWORD) f->datachunksize, f) ) {
  5366. if(fsetpos(f->fileno, &bytepos)
  5367. ||write_dw_lsf((DWORD) f->datachunksize, f) ) {
  5368. #endif
  5369. rsferrno = ESFWRERR;
  5370. rsferrstr = "SFSYS98: Write error: Can't update chunk sizes or info chunk";
  5371. return -1;
  5372. }
  5373. return 0;
  5374. }
  5375. static int
  5376. aiffupdate(time_t thistime,struct sf_file *f)
  5377. {
  5378. DWORD numsampleframes;
  5379. fpos_t bytepos;
  5380. struct aiffchunk *ap = f->aiffchunks;
  5381. int commafterdata = 0;
  5382. switch(f->fmtchunkEx.Format.wBitsPerSample) {
  5383. case 8:
  5384. f->datachunksize /= 2;
  5385. numsampleframes = (DWORD) f->datachunksize; /* RWD 2007 added DWORD casts */
  5386. break;
  5387. case 16:
  5388. numsampleframes = (DWORD) f->datachunksize / 2;
  5389. break;
  5390. case 32:
  5391. numsampleframes = (DWORD) f->datachunksize / 4;
  5392. break;
  5393. default:
  5394. abort();
  5395. }
  5396. numsampleframes /= f->fmtchunkEx.Format.nChannels;
  5397. f->mainchunksize = sizeof(DWORD) + 2*sizeof(DWORD) + 26 + 2*sizeof(DWORD) + (DWORD)(f->datachunksize + f->extrachunksizes);
  5398. #if defined _WIN32
  5399. if(SetFilePointer(f->fileno,4L,NULL,FILE_BEGIN) == 0xFFFFFFFF
  5400. ||write_dw_msf((DWORD) POS64(f->mainchunksize), f)
  5401. ||SetFilePointer(f->fileno,(long)(POS64(f->datachunkoffset) - 3*sizeof(DWORD)),NULL,FILE_BEGIN) == 0xFFFFFFFF
  5402. ||write_dw_msf((DWORD)(f->datachunksize + 2*sizeof(DWORD)), f) ) {
  5403. rsferrno = ESFWRERR;
  5404. rsferrstr = "Write error: Can't update main or data chunk size";
  5405. return -1;
  5406. }
  5407. #else
  5408. bytepos = f->datachunkoffset;
  5409. POS64(bytepos) -= 3 * sizeof(DWORD);
  5410. if(fseek(f->fileno, 4L, SEEK_SET)
  5411. ||write_dw_msf((DWORD) f->mainchunksize, f)
  5412. ||fsetpos(f->fileno, &bytepos)
  5413. ||write_dw_msf((DWORD)(f->datachunksize + 2*sizeof(DWORD)), f) ) {
  5414. rsferrno = ESFWRERR;
  5415. rsferrstr = "Write error: Can't update main or data chunk size";
  5416. return -1;
  5417. }
  5418. #endif
  5419. if(POS64(f->fmtchunkoffset) > POS64(f->datachunkoffset)) {
  5420. commafterdata++;
  5421. POS64(f->fmtchunkoffset) = POS64(f->datachunkoffset) + (DWORD)( (f->datachunksize+1)&~1);
  5422. }
  5423. //RWD NB no support for AIFC here...
  5424. #ifdef NOTDEF
  5425. else
  5426. f->fmtchunkoffset -= 2*sizeof(DWORD);
  5427. #endif
  5428. #if defined _WIN32
  5429. if(SetFilePointer(f->fileno,f->fmtchunkoffset,NULL,FILE_BEGIN) == 0xFFFFFFFF){
  5430. #else
  5431. if(fsetpos(f->fileno, &f->fmtchunkoffset) ) {
  5432. #endif
  5433. rsferrno = ESFWRERR;
  5434. rsferrstr = "Write error: Can't seek to COMM chunk";
  5435. return -1;
  5436. }
  5437. if(
  5438. #ifdef NOTDEF
  5439. write_dw_msf(TAG('C','O','M','M'), f)
  5440. ||write_dw_msf(18, f)
  5441. ||
  5442. #endif
  5443. write_w_msf(f->fmtchunkEx.Format.nChannels, f)
  5444. ||write_dw_msf(numsampleframes, f)
  5445. ||write_w_msf(f->fmtchunkEx.Format.wBitsPerSample, f)
  5446. ||write_dw_toex(f->fmtchunkEx.Format.nSamplesPerSec, f) ) {
  5447. rsferrno = ESFWRERR;
  5448. rsferrstr = "Write error: Can't update COMM chunk";
  5449. return -1;
  5450. }
  5451. //RWD.6.5.99 update peak chunk
  5452. if((f->min_header >= SFILE_PEAKONLY) && f->peaks){
  5453. #if defined _WIN32
  5454. if(SetFilePointer(f->fileno,f->peakchunkoffset + sizeof(DWORD),NULL,FILE_BEGIN)== 0xFFFFFFFF
  5455. #else
  5456. bytepos = f->peakchunkoffset;
  5457. POS64(bytepos) += sizeof(DWORD);
  5458. if(fsetpos(f->fileno,&bytepos)
  5459. #endif
  5460. || write_dw_msf((DWORD) thistime,f)
  5461. || write_peak_msf(f->fmtchunkEx.Format.nChannels,f)) {
  5462. rsferrno = ESFWRERR;
  5463. rsferrstr = "SFSYS98: Write error: Can't update peak chunk";
  5464. return -1;
  5465. }
  5466. }
  5467. if(!commafterdata) {
  5468. #if defined _WIN32
  5469. if(SetFilePointer(f->fileno,(long)(f->datachunkoffset + (f->datachunksize+1)&~1),NULL,FILE_BEGIN)==0xFFFFFFFF) {
  5470. #else
  5471. bytepos = f->datachunkoffset;
  5472. POS64(bytepos) += (f->datachunksize+1)&~1;
  5473. if(fsetpos(f->fileno, &bytepos) ) {
  5474. #endif
  5475. rsferrno = ESFWRERR;
  5476. rsferrstr = "Can't seek to end, to update extra chunks";
  5477. return -1;
  5478. }
  5479. }
  5480. for(; ap != 0; ap = ap->next) {
  5481. if(POS64(ap->offset) < POS64(f->datachunkoffset))
  5482. continue;
  5483. if(write_dw_msf(ap->tag, f)
  5484. ||write_dw_msf(ap->size, f)
  5485. ||dowrite(f, ap->buf, (ap->size+1)&~1) ) {
  5486. rsferrno = ESFWRERR;
  5487. rsferrstr = "Can't update extra chunk";
  5488. return -1;
  5489. }
  5490. }
  5491. return 0;
  5492. }
  5493. static int
  5494. aiffupdate98(time_t thistime,struct sf_file *f)
  5495. {
  5496. DWORD numsampleframes = 0;
  5497. #ifdef linux
  5498. fpos_t bytepos = {0};
  5499. #else
  5500. fpos_t bytepos = 0;
  5501. #endif
  5502. struct aiffchunk *ap = f->aiffchunks;
  5503. int commafterdata = 0;
  5504. if(! f->header_set)
  5505. return -1;
  5506. if(f->infochanged){
  5507. switch(f->fmtchunkEx.Format.wBitsPerSample) {
  5508. case 8:
  5509. f->datachunksize /= 2;
  5510. numsampleframes = (DWORD) f->datachunksize;
  5511. break;
  5512. case 16:
  5513. numsampleframes = (DWORD) f->datachunksize/2;
  5514. break;
  5515. case 20: //NB not allowed by AIFF - no header field for masked sizes
  5516. case 24:
  5517. numsampleframes = (DWORD) f->datachunksize / 3;
  5518. break;
  5519. case 32:
  5520. numsampleframes = (DWORD) f->datachunksize/4;
  5521. break;
  5522. default:
  5523. rsferrno = ESFBADPARAM;
  5524. rsferrstr = "cannot update with unknown sample format";
  5525. return -1;
  5526. break;
  5527. }
  5528. }
  5529. // else if bitspersample== 8.... ?
  5530. numsampleframes /= f->fmtchunkEx.Format.nChannels;
  5531. /* RWD 8.99 this may be wrong...*/
  5532. /*f->mainchunksize = sizeof(DWORD) + 2*sizeof(DWORD) + 26 + 2*sizeof(DWORD) + f->datachunksize + f->extrachunksizes;
  5533. */
  5534. f->mainchunksize = POS64(f->datachunkoffset) + (DWORD) f->datachunksize - 2 * sizeof(DWORD);
  5535. #if defined defined _WIN32
  5536. if(SetFilePointer(f->fileno,4L,NULL,FILE_BEGIN) == 0xFFFFFFFF
  5537. #else
  5538. bytepos = f->datachunkoffset;
  5539. POS64(bytepos) -= 3*sizeof(DWORD);
  5540. if(fseek(f->fileno, 4L, SEEK_SET) < 0
  5541. #endif
  5542. ||write_dw_msf(f->mainchunksize, f)
  5543. #if defined defined _WIN32
  5544. ||SetFilePointer(f->fileno,(long)(f->datachunkoffset - 3*sizeof(DWORD)),NULL,FILE_BEGIN) == 0xFFFFFFFF
  5545. #else
  5546. // ||lseek(f->fileno, f->datachunkoffset - 3*sizeof(DWORD), SEEK_SET) < 0
  5547. ||fsetpos(f->fileno, &bytepos)
  5548. #endif
  5549. ||write_dw_msf((DWORD) f->datachunksize + 2*sizeof(DWORD), f) ) {
  5550. rsferrno = ESFWRERR;
  5551. rsferrstr = "Write error: Can't update main or data chunk size";
  5552. return -1;
  5553. }
  5554. if(POS64(f->fmtchunkoffset) > POS64(f->datachunkoffset)) {
  5555. commafterdata++;
  5556. POS64(f->fmtchunkoffset) = POS64(f->datachunkoffset) + (DWORD)((f->datachunksize+1)&~1); /*RWD 2007 */
  5557. }
  5558. //RWD don't want to do this - might be AIFC - don't need to anyway!
  5559. #ifdef NOTDEF
  5560. else
  5561. f->fmtchunkoffset -= 2*sizeof(DWORD);
  5562. #endif
  5563. #if defined defined _WIN32
  5564. if(SetFilePointer(f->fileno,f->fmtchunkoffset,NULL,FILE_BEGIN) == 0xFFFFFFFF){
  5565. #else
  5566. if(fsetpos(f->fileno, &f->fmtchunkoffset) ) {
  5567. #endif
  5568. rsferrno = ESFWRERR;
  5569. rsferrstr = "Write error: Can't seek to COMM chunk";
  5570. return -1;
  5571. }
  5572. //strictly, we should check the new format and redo the AIFC stuff,
  5573. //OR reject if infochanged
  5574. //at least, disallow format conversion in AIFC!
  5575. if(
  5576. #ifdef NOTDEF
  5577. write_dw_msf(TAG('C','O','M','M'), f)
  5578. ||write_dw_msf(18, f)
  5579. ||
  5580. #endif
  5581. write_w_msf(f->fmtchunkEx.Format.nChannels, f)
  5582. ||write_dw_msf(numsampleframes, f)
  5583. ||write_w_msf(f->fmtchunkEx.Format.wBitsPerSample, f)
  5584. ||write_dw_toex(f->fmtchunkEx.Format.nSamplesPerSec, f) ) {
  5585. rsferrno = ESFWRERR;
  5586. rsferrstr = "Write error: Can't update COMM chunk";
  5587. return -1;
  5588. }
  5589. // update peak chunk
  5590. if((f->min_header >= SFILE_PEAKONLY) && f->peaks){
  5591. #if defined defined _WIN32
  5592. if(SetFilePointer(f->fileno,f->peakchunkoffset + sizeof(DWORD),NULL,FILE_BEGIN)== 0xFFFFFFFF
  5593. #else
  5594. bytepos = f->peakchunkoffset;
  5595. POS64(bytepos) += sizeof(DWORD);
  5596. if(fsetpos(f->fileno,&bytepos)
  5597. #endif
  5598. || write_dw_msf((DWORD) thistime,f)
  5599. || write_peak_msf(f->fmtchunkEx.Format.nChannels,f)) {
  5600. rsferrno = ESFWRERR;
  5601. rsferrstr = "SFSYS98: Write error: Can't update peak chunk";
  5602. return -1;
  5603. }
  5604. }
  5605. if(!commafterdata) {
  5606. #if defined CDP99 && defined _WIN32
  5607. if(SetFilePointer(f->fileno,(long)(f->datachunkoffset + (f->datachunksize+1)&~1),NULL,FILE_BEGIN)==0xFFFFFFFF) {
  5608. #else
  5609. bytepos = f->datachunkoffset;
  5610. POS64(bytepos) += (f->datachunksize+1)&~1;
  5611. // if(lseek(f->fileno, f->datachunkoffset + (f->datachunksize+1)&~1, SEEK_SET) < 0) {
  5612. if(fsetpos(f->fileno, &bytepos) ) {
  5613. #endif
  5614. rsferrno = ESFWRERR;
  5615. rsferrstr = "Can't seek to end, to update extra chunks";
  5616. return -1;
  5617. }
  5618. }
  5619. /* RWD: NB if we have these, they will start correctly after a pad byte,
  5620. * and we will just trust that these chunks are kosher!*/
  5621. if(ap){
  5622. for(; ap != 0; ap = ap->next) {
  5623. if(POS64(ap->offset) < POS64(f->datachunkoffset))
  5624. continue;
  5625. if(write_dw_msf(ap->tag, f)
  5626. ||write_dw_msf(ap->size, f)
  5627. ||dowrite(f, ap->buf, (ap->size+1)&~1) ) {
  5628. rsferrno = ESFWRERR;
  5629. rsferrstr = "Can't update extra chunk";
  5630. return -1;
  5631. }
  5632. }
  5633. }
  5634. /*RWD AIFF requires pad byte at end, for 8bit and 24bit sample types*/
  5635. else {
  5636. #ifdef FILE64_WIN
  5637. __int64 size = f->datachunkoffset + (f->datachunksize+1)&~1;
  5638. #else
  5639. DWORD size = POS64(f->datachunkoffset) + ((f->datachunksize+1)&~1);
  5640. #endif
  5641. #if defined CDP99 && defined _WIN32
  5642. if(w_ch_size(f->fileno, size) < 0) {
  5643. #else
  5644. if(ftruncate(fileno(f->fileno), (off_t) size) < 0) {
  5645. #endif
  5646. rsferrno = ESFWRERR;
  5647. rsferrstr = "write error truncating file";
  5648. return -1;
  5649. }
  5650. }
  5651. return 0;
  5652. }
  5653. int
  5654. sfclose(int sfd)
  5655. {
  5656. struct sf_file *f;
  5657. int rc = 0;
  5658. if((f = findfile(sfd)) == 0){ //RWD: may already have been closed... see errrmsg
  5659. rsferrstr = "SFSYS: close: bad file ID (already closed?)";
  5660. return -1;
  5661. }
  5662. if((f->infochanged || f->propschanged) && !f->todelete && !f->readonly) {
  5663. unsigned int cdptime;
  5664. time_t now = time(0);
  5665. cdptime = (unsigned int) now;
  5666. //RWD.5.99
  5667. if((f->min_header >= SFILE_CDP) && POS64(f->propoffset) > 0)
  5668. sfputprop(sfd, "DATE", /* (char *)&now */ (char *) &cdptime, sizeof(/*long*/int));
  5669. switch(f->filetype) {
  5670. case riffwav:
  5671. case wave_ex:
  5672. if(f->header_set)
  5673. rc = wavupdate98(now,f); //RWD.6.5.99
  5674. else
  5675. rc = wavupdate(f);
  5676. break;
  5677. case eaaiff:
  5678. case aiffc:
  5679. if(f->header_set)
  5680. rc = aiffupdate98(now,f);
  5681. else
  5682. rc = aiffupdate(now,f); //RWD.6.5.99
  5683. break;
  5684. default:
  5685. //abort();
  5686. rsferrno = ESFBADPARAM;
  5687. rsferrstr = "SFSYS98: aif-c files not supported";
  5688. return -1;
  5689. break;
  5690. }
  5691. f->propschanged = 1;
  5692. }
  5693. if(f->min_header >= SFILE_CDP && POS64(f->propoffset) >= 0 && f->propschanged && !f->todelete && !f->readonly)
  5694. if(writeprops(f) < 0)
  5695. rc = -1;
  5696. #if defined _WIN32
  5697. if(!CloseHandle(f->fileno)) {
  5698. #else
  5699. if(fclose(f->fileno) < 0) {
  5700. #endif
  5701. rsferrno = ESFWRERR;
  5702. rsferrstr = "write error: system had trouble closing file";
  5703. rc = -1;
  5704. }
  5705. if(f->todelete
  5706. && f->filename != NULL
  5707. #if defined _WIN32
  5708. && !DeleteFile(f->filename)){
  5709. #else
  5710. && remove(f->filename) < 0) {
  5711. #endif
  5712. rsferrno = ESFWRERR;
  5713. rsferrstr = "can't remove soundfile";
  5714. rc = -1;
  5715. }
  5716. freesffile(sfd-SFDBASE);
  5717. return rc;
  5718. }
  5719. //return true size in bytes: of SHORTS or FLOATS file
  5720. __int64
  5721. sfsize(int sfd)
  5722. {
  5723. struct sf_file *f;
  5724. if((f = findfile(sfd)) == 0)
  5725. return -1;
  5726. return (__int64)(f->sizerequested == ES_EXIST ? f->datachunksize : f->sizerequested);
  5727. }
  5728. #ifdef FILE64_WIN
  5729. int
  5730. sfadjust(int sfd, __int64 delta)
  5731. {
  5732. struct sf_file *f;
  5733. __int64 newsize;
  5734. if(delta > 0) {
  5735. rsferrno = ESFBADPARAM;
  5736. rsferrstr = "Can't extend a soundfile";
  5737. return -1;
  5738. }
  5739. if((f = findfile(sfd)) == 0)
  5740. return -1;
  5741. if(f->readonly) {
  5742. rsferrno = ESFREADONLY;
  5743. rsferrstr = "can't adjust size of read-only file";
  5744. return -1;
  5745. }
  5746. f->infochanged = 1;
  5747. switch(f->sizerequested) {
  5748. case ES_EXIST:
  5749. if(f->datachunksize + delta < 0) {
  5750. rsferrno = ESFBADPARAM;
  5751. rsferrstr = "can't make soundfile with negative size";
  5752. return -1;
  5753. }
  5754. f->datachunksize += delta;
  5755. break;
  5756. default:
  5757. if(f->sizerequested + delta < 0) {
  5758. rsferrno = ESFBADPARAM;
  5759. rsferrstr = "can't make soundfile with negative size";
  5760. return -1;
  5761. }
  5762. if(f->sizerequested + delta >= f->datachunksize)
  5763. return 0;
  5764. f->sizerequested += delta;
  5765. f->datachunksize = f->sizerequested;
  5766. break;
  5767. }
  5768. newsize = f->datachunkoffset;
  5769. if(f->fmtchunkEx.Format.wBitsPerSample == 8)
  5770. newsize += f->datachunksize/2;
  5771. else
  5772. newsize += f->datachunksize;
  5773. #if defined defined _WIN32
  5774. if(w_ch_size(f->fileno, newsize) < 0) {
  5775. #else
  5776. if(chsize(f->fileno, newsize) < 0) {
  5777. #endif
  5778. rsferrno = ESFWRERR;
  5779. rsferrstr = "write error truncating file";
  5780. return -1;
  5781. }
  5782. return 0; /* is this right? */
  5783. }
  5784. #else
  5785. int
  5786. sfadjust(int sfd, __int64 delta)
  5787. {
  5788. struct sf_file *f;
  5789. __int64 newsize;
  5790. #ifdef _DEBUG
  5791. fprintf(stder,"in sfadjust()\n");
  5792. #endif
  5793. if(delta > 0) {
  5794. rsferrno = ESFBADPARAM;
  5795. rsferrstr = "Can't extend a soundfile";
  5796. return -1;
  5797. }
  5798. if((f = findfile(sfd)) == 0)
  5799. return -1;
  5800. if(f->readonly) {
  5801. rsferrno = ESFREADONLY;
  5802. rsferrstr = "can't adjust size of read-only file";
  5803. return -1;
  5804. }
  5805. f->infochanged = 1;
  5806. switch(f->sizerequested) {
  5807. case ES_EXIST:
  5808. if( f->datachunksize + delta < 0) {
  5809. rsferrno = ESFBADPARAM;
  5810. rsferrstr = "can't make soundfile with negative size";
  5811. return -1;
  5812. }
  5813. f->datachunksize += delta;
  5814. break;
  5815. default:
  5816. if(f->sizerequested + delta < 0) {
  5817. rsferrno = ESFBADPARAM;
  5818. rsferrstr = "can't make soundfile with negative size";
  5819. return -1;
  5820. }
  5821. if(f->sizerequested + delta >= f->datachunksize)
  5822. return 0;
  5823. f->sizerequested += delta;
  5824. f->datachunksize = f->sizerequested;
  5825. break;
  5826. }
  5827. newsize = (__int64) POS64(f->datachunkoffset);
  5828. if(f->fmtchunkEx.Format.wBitsPerSample == 8)
  5829. newsize += f->datachunksize/2;
  5830. else
  5831. newsize += f->datachunksize;
  5832. #if defined _WIN32
  5833. if(w_ch_size(f->fileno, newsize) < 0) {
  5834. #else
  5835. if(chsize(fileno(f->fileno), newsize) < 0) {
  5836. #endif
  5837. rsferrno = ESFWRERR;
  5838. rsferrstr = "write error truncating file";
  5839. return -1;
  5840. }
  5841. return 0; /* is this right? */
  5842. }
  5843. #endif
  5844. int
  5845. sfunlink(int sfd)
  5846. {
  5847. struct sf_file *f;
  5848. if((f = findfile(sfd)) == 0)
  5849. return -1;
  5850. if(f->readonly) {
  5851. rsferrno = ESFREADONLY;
  5852. rsferrstr = "can't delete read-only file";
  5853. return -1;
  5854. }
  5855. f->todelete = 1;
  5856. return 0;
  5857. }
  5858. int
  5859. sfrename(int sfd, const char *newname)
  5860. {
  5861. struct sf_file *f;
  5862. char *path = NULL;
  5863. if((f = findfile(sfd)) == 0)
  5864. return -1;
  5865. if(f->readonly) {
  5866. rsferrno = ESFREADONLY;
  5867. rsferrstr = "can't rename read-only file";
  5868. return -1;
  5869. }
  5870. if(f->filename == 0) {
  5871. rsferrno = ESFNOMEM;
  5872. rsferrstr = "Couldn't remember name of file";
  5873. return -1;
  5874. }
  5875. path = mksfpath(newname);
  5876. if(path==NULL){
  5877. rsferrno = ESFBADPARAM;
  5878. rsferrstr = "can't rename file changing its type";
  5879. return -1;
  5880. }
  5881. if(f->filetype != gettypefromname98(path)) {
  5882. rsferrno = ESFBADPARAM;
  5883. rsferrstr = "can't rename file changing its type";
  5884. return -1;
  5885. }
  5886. if(rename(f->filename, path) != 0) {
  5887. rsferrno = ESFDUPFNAME;
  5888. rsferrstr = "file already exists, or can't rename across devices";
  5889. return -1;
  5890. }
  5891. free(f->filename);
  5892. f->filename = _fullpath(NULL, path, 0);
  5893. return 0;
  5894. }
  5895. /*
  5896. * Property access routines
  5897. */
  5898. //RWD.6.99 mega-special case for sample type now!
  5899. int
  5900. sfgetprop(int sfd, const char *propname, char *dest, int lim)
  5901. {
  5902. int lret = SAMP_MASKED; //RWD.6.99
  5903. int res,containersize;
  5904. struct sf_file *f;
  5905. struct property *pp;
  5906. if((f = findfile(sfd)) == 0)
  5907. return -1;
  5908. if(strcmp(propname, "channels") == 0)
  5909. lret = f->fmtchunkEx.Format.nChannels;
  5910. else if(strcmp(propname, "sample rate") == 0)
  5911. lret = f->fmtchunkEx.Format.nSamplesPerSec;
  5912. else if(strcmp(propname, "sample type") == 0) {
  5913. //RWD.6.99 lets accept all formats!
  5914. //is this good for AIFF?
  5915. containersize = 8 * (f->fmtchunkEx.Format.nBlockAlign / f->fmtchunkEx.Format.nChannels);
  5916. switch(containersize){
  5917. case(32):
  5918. if(f->fmtchunkEx.Format.wFormatTag== WAVE_FORMAT_IEEE_FLOAT
  5919. || (f->fmtchunkEx.Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE
  5920. && (
  5921. (compare_guids(&(f->fmtchunkEx.SubFormat),&(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)))
  5922. ||
  5923. (compare_guids(&(f->fmtchunkEx.SubFormat),&(SUBTYPE_AMBISONIC_B_FORMAT_IEEE_FLOAT)))
  5924. )
  5925. )
  5926. ) {
  5927. lret = SAMP_FLOAT;
  5928. break;
  5929. }
  5930. else{
  5931. //int format: may be masked
  5932. switch(f->fmtchunkEx.Samples.wValidBitsPerSample){
  5933. case(32):
  5934. lret = SAMP_LONG;
  5935. break;
  5936. case(24):
  5937. lret = SAMP_2432;
  5938. break;
  5939. default:
  5940. lret = SAMP_MASKED;
  5941. break;
  5942. }
  5943. }
  5944. break;
  5945. case(24):
  5946. switch(f->fmtchunkEx.Samples.wValidBitsPerSample){
  5947. case(24):
  5948. lret = SAMP_2424;
  5949. break;
  5950. case(20):
  5951. lret = SAMP_2024;
  5952. break;
  5953. default:
  5954. lret = SAMP_MASKED;
  5955. break;
  5956. }
  5957. break;
  5958. case(16):
  5959. case(8):
  5960. lret = SAMP_SHORT;
  5961. break;
  5962. default:
  5963. break;
  5964. }
  5965. } else {
  5966. if(f->min_header < SFILE_CDP){
  5967. rsferrno = ESFNOTFOUND;
  5968. rsferrstr = "no CDP properties in minimum header";
  5969. return -1;
  5970. }
  5971. if(POS64(f->propoffset) >= 0)
  5972. for(pp = f->props; pp != 0; pp = pp->next) {
  5973. if(strcmp(propname, pp->name) == 0) {
  5974. res = min(pp->size, lim);
  5975. memcpy(dest, pp->data, res);
  5976. return res;
  5977. }
  5978. }
  5979. rsferrno = ESFNOTFOUND;
  5980. rsferrstr = "Property not defined in file";
  5981. return -1;
  5982. }
  5983. /*
  5984. * return a standard property as a long
  5985. */
  5986. res = min(lim, sizeof(/*long*/int));
  5987. memcpy(dest, &lret, res);
  5988. return res;
  5989. }
  5990. static int
  5991. getlong(int *dest, char *src, int size, int error)
  5992. {
  5993. if(size != sizeof(/*long*/int)) {
  5994. rsferrno = error;
  5995. rsferrstr = "Bad size for standard property";
  5996. return -1;
  5997. }
  5998. memcpy(dest, src, sizeof(/*long*/int));
  5999. return 0;
  6000. }
  6001. //RWD.6.99 trap attempts to update primary properties of streamable file
  6002. // ATARI trapped, but ATARI ~could~ support 32bit longs, but who cares?
  6003. int
  6004. sfputprop(int sfd, char *propname, char *src, int size)
  6005. {
  6006. int data;
  6007. struct sf_file *f;
  6008. struct property *pp, **ppp;
  6009. char *np;
  6010. if((f = findfile(sfd)) == 0)
  6011. return -1;
  6012. if(f->readonly) {
  6013. rsferrno = ESFREADONLY;
  6014. rsferrstr = "can't set property in a read-only file";
  6015. return -1;
  6016. }
  6017. if(strcmp(propname, "channels") == 0) {
  6018. if(getlong(&data, src, size, ESFBADNCHANS) < 0)
  6019. return -1;
  6020. //RWD.6.99
  6021. if(f->header_set && (data != (int)f->fmtchunkEx.Format.nChannels)){
  6022. rsferrno = ESFBADPARAM;
  6023. rsferrstr = "not allowed to alter existing property";
  6024. return -1;
  6025. }
  6026. f->fmtchunkEx.Format.nChannels = (short)data;
  6027. f->infochanged = 1;
  6028. return 0;
  6029. } else if(strcmp(propname, "sample rate") == 0) {
  6030. if(getlong(&data, src, size, ESFBADRATE) < 0)
  6031. return -1;
  6032. //RWD.6.99
  6033. if(f->header_set && (data != (int) f->fmtchunkEx.Format.nSamplesPerSec)){
  6034. rsferrno = ESFBADPARAM;
  6035. rsferrstr = "not allowed to alter existing property";
  6036. return -1;
  6037. }
  6038. f->fmtchunkEx.Format.nSamplesPerSec = data;
  6039. f->infochanged = 1;
  6040. return 0;
  6041. } else if(strcmp(propname, "sample type") == 0) {
  6042. if(f->header_set){
  6043. rsferrno = ESFBADPARAM;
  6044. rsferrstr = "not allowed to alter existing property";
  6045. return -1;
  6046. }
  6047. if(getlong(&data, src, size, ESFBADPARAM) < 0)
  6048. return -1;
  6049. #ifdef SFSYS_UNBUFFERED
  6050. if(data != SAMP_SHORT && data != SAMP_FLOAT) {
  6051. rsferrno = ESFBADPARAM;
  6052. rsferrstr = "Only short samples supported, as yet!";
  6053. return -1;
  6054. }
  6055. #else
  6056. if(data < SAMP_SHORT && data >= SAMP_MASKED) {
  6057. rsferrno = ESFBADPARAM;
  6058. rsferrstr = "cannot change to unsupported sample type";
  6059. return -1;
  6060. }
  6061. #endif
  6062. if(f->fmtchunkEx.Format.wBitsPerSample == 8) {
  6063. rsferrno = ESFBADPARAM;
  6064. rsferrstr = "Can't change sample type when accessing 8 bits/sample file";
  6065. return -1;
  6066. }
  6067. #ifdef SFSYS_UNBUFFERED
  6068. f->fmtchunkEx.Format.wBitsPerSample = (data == SAMP_SHORT) ? 16 : 32;
  6069. #else
  6070. switch(data){
  6071. case(SAMP_LONG):
  6072. case(SAMP_FLOAT):
  6073. case(SAMP_2432):
  6074. f->fmtchunkEx.Format.wBitsPerSample = 32;
  6075. break;
  6076. case(SAMP_2424):
  6077. case(SAMP_2024):
  6078. f->fmtchunkEx.Format.wBitsPerSample = 24;
  6079. break;
  6080. case(SAMP_SHORT):
  6081. f->fmtchunkEx.Format.wBitsPerSample = 16;
  6082. break;
  6083. case(SAMP_BYTE):
  6084. rsferrno = ESFBADPARAM;
  6085. rsferrstr = "8-bit files not supportewd for writing";
  6086. return -1;
  6087. default:
  6088. rsferrno = ESFBADPARAM;
  6089. rsferrstr = "cannot set unsupported sample type";
  6090. return -1;
  6091. break;
  6092. }
  6093. #endif
  6094. f->infochanged = 1;
  6095. return 0;
  6096. }
  6097. /*
  6098. * now deal with extended attributes
  6099. */
  6100. if((f->min_header < SFILE_CDP) || POS64(f->propoffset) < 0) {
  6101. rsferrno = ESFNOSPACE;
  6102. rsferrstr = "No property chunk in this .wav file";
  6103. return -1;
  6104. }
  6105. for(pp = f->props; pp != 0; pp = pp->next) {
  6106. if(strcmp(propname, pp->name) == 0) {
  6107. if(f->curpropsize + 2*(size - pp->size) > f->proplim) {
  6108. rsferrno = ESFNOSPACE;
  6109. rsferrstr = "No space in extended properties for bigger property data";
  6110. return -1;
  6111. }
  6112. if((np = (char *) malloc(size)) == 0) {
  6113. rsferrno = ESFNOMEM;
  6114. rsferrstr = "No memory for bigger property data";
  6115. return -1;
  6116. }
  6117. memcpy(np, src, size);
  6118. free(pp->data);
  6119. pp->data = np;
  6120. pp->size = size;
  6121. f->curpropsize -= 2*(size - pp->size);
  6122. f->propschanged = 1;
  6123. return 0;
  6124. }
  6125. }
  6126. /* adding new property */
  6127. if(f->curpropsize + (signed int)strlen(propname) + 2 + 2*size > f->proplim) {
  6128. rsferrno = ESFNOSPACE;
  6129. rsferrstr = "No space in extended properties for new property data";
  6130. return -1;
  6131. }
  6132. for(ppp = &f->props; *ppp != 0; ppp = &(*ppp)->next)
  6133. ;
  6134. if((*ppp = ALLOC(struct property)) == 0
  6135. ||((*ppp)->name = (char *) malloc(strlen(propname)+1)) == 0
  6136. ||((*ppp)->data = (char *) malloc(size)) == 0) {
  6137. rsferrno = ESFNOMEM;
  6138. rsferrstr = "No memory for bigger property data";
  6139. return -1;
  6140. }
  6141. strcpy((*ppp)->name, propname);
  6142. memcpy((*ppp)->data, src, size);
  6143. (*ppp)->size = size;
  6144. (*ppp)->next = 0;
  6145. f->curpropsize += strlen(propname) + 2 + 2*size;
  6146. f->propschanged = 1;
  6147. return 0;
  6148. }
  6149. //RWD.6.5.99 not used internally by header routines, return 0 for true
  6150. int sfputpeaks(int sfd,int channels,const CHPEAK peakdata[])
  6151. {
  6152. int i;
  6153. struct sf_file *f;
  6154. if((f = findfile(sfd)) == 0)
  6155. return -1;
  6156. if(f->readonly) {
  6157. rsferrno = ESFREADONLY;
  6158. rsferrstr = "can't set property in a read-only file";
  6159. return -1;
  6160. }
  6161. if(f->min_header < SFILE_PEAKONLY){
  6162. rsferrno = ESFNOSPACE;
  6163. rsferrstr = "no space for peak data in minimum header";
  6164. return -1;
  6165. }
  6166. if(f->peaks==NULL){
  6167. rsferrno = ESFREADONLY;
  6168. rsferrstr = "peak data not initialized";
  6169. return -1;
  6170. }
  6171. for(i=0;i < channels; i++){
  6172. f->peaks[i].value = peakdata[i].value;
  6173. f->peaks[i].position = peakdata[i].position;
  6174. }
  6175. return 0;
  6176. }
  6177. //NB this one not used internally by header routines, return 1 for true
  6178. int sfreadpeaks(int sfd,int channels,CHPEAK peakdata[],int *peaktime)
  6179. {
  6180. int i;
  6181. struct sf_file *f;
  6182. if((f = findfile(sfd)) == 0)
  6183. return -1;
  6184. if(f->peaks==NULL){ //NOT an error: just don't have the chunk
  6185. *peaktime = 0;
  6186. return 0;
  6187. }
  6188. *peaktime = (int) f->peaktime;
  6189. for(i=0;i < channels; i++){
  6190. peakdata[i].value = f->peaks[i].value;
  6191. peakdata[i].position = f->peaks[i].position;
  6192. }
  6193. return 1;
  6194. }
  6195. int
  6196. sfrmprop(int sfd, char *propname)
  6197. {
  6198. struct sf_file *f;
  6199. struct property **ppp;
  6200. if((f = findfile(sfd)) == 0)
  6201. return -1;
  6202. if(f->readonly) {
  6203. rsferrno = ESFREADONLY;
  6204. rsferrstr = "can't remove property from a read-only file";
  6205. return -1;
  6206. }
  6207. if(strcmp(propname, "channels") == 0
  6208. ||strcmp(propname, "sample rate") == 0
  6209. ||strcmp(propname, "sample type") == 0) {
  6210. rsferrno = ESFBADPARAM;
  6211. rsferrstr = "Cannot remove standard property";
  6212. return -1;
  6213. }
  6214. if(f->min_header < SFILE_CDP){
  6215. rsferrno = ESFNOTFOUND;
  6216. rsferrstr = "minimum header - no CDP properties present";
  6217. return -1;
  6218. }
  6219. if(POS64(f->propoffset) >= 0)
  6220. for(ppp = &f->props; *ppp != 0; ppp = &(*ppp)->next)
  6221. if(strcmp((*ppp)->name, propname) == 0) {
  6222. struct property *p = *ppp;
  6223. f->curpropsize -= strlen(propname) + 2 + p->size;
  6224. f->propschanged = 1;
  6225. free(p->name);
  6226. free(p->data);
  6227. *ppp = p->next;
  6228. free(p);
  6229. return 0;
  6230. }
  6231. rsferrno = ESFNOTFOUND;
  6232. rsferrstr = "Property not found";
  6233. return -1;
  6234. }
  6235. int
  6236. sfdirprop(int sfd, int (*func)(char *propname, int propsize))
  6237. {
  6238. struct sf_file *f;
  6239. struct property *pp;
  6240. if((f = findfile(sfd)) == 0)
  6241. return -1;
  6242. if(func("channels", sizeof(/*long*/ int)) != 0
  6243. ||func("sample type", sizeof(/*long*/ int)) != 0
  6244. ||func("sample rate", sizeof(/*long*/ int)) != 0)
  6245. return SFDIR_FOUND;
  6246. for(pp = f->props; pp != 0; pp = pp->next)
  6247. if(func(pp->name, pp->size) != 0)
  6248. return SFDIR_FOUND;
  6249. return SFDIR_NOTFOUND;
  6250. }
  6251. //CDP98
  6252. #if defined _WIN32 && defined _MSC_VER
  6253. long cdp_round(double fval)
  6254. {
  6255. int result;
  6256. _asm{
  6257. fld fval
  6258. fistp result
  6259. mov eax,result
  6260. }
  6261. return (long) result;
  6262. }
  6263. #else
  6264. # if defined __GNUWIN32__
  6265. // TODO: learn and use gcc asm syntax!
  6266. long cdp_round(double fval)
  6267. {
  6268. int k;
  6269. k = (int)(fabs(fval)+0.5);
  6270. if(fval < 0.0)
  6271. k = -k;
  6272. return (long) k;
  6273. }
  6274. # endif
  6275. #endif
  6276. int sfformat(int sfd, fileformat *pfmt)
  6277. {
  6278. struct sf_file *f;
  6279. if(pfmt==NULL)
  6280. return 0;
  6281. if((f = findfile(sfd)) == 0)
  6282. return -1;
  6283. if(f->filetype == riffwav)
  6284. *pfmt = WAVE;
  6285. else if(f->filetype == wave_ex)
  6286. *pfmt = WAVE_EX;
  6287. else if(f->filetype== eaaiff)
  6288. *pfmt = AIFF;
  6289. else if(f->filetype ==aiffc)
  6290. *pfmt = AIFC;
  6291. else
  6292. return -1;
  6293. return 0;
  6294. }
  6295. int sfgetchanmask(int sfd)
  6296. {
  6297. struct sf_file *f;
  6298. //int mask = 0; //default is generic (unassigned)
  6299. if((f = findfile(sfd)) ==NULL)
  6300. return -1;
  6301. if(f->filetype==wave_ex)
  6302. return f->fmtchunkEx.dwChannelMask;
  6303. return 0;
  6304. }
  6305. //private, but used by sndsystem
  6306. int _rsf_getbitmask(int sfd)
  6307. {
  6308. struct sf_file *f;
  6309. if((f = findfile(sfd)) ==NULL)
  6310. return 0;
  6311. return f->bitmask;
  6312. }
  6313. int sf_getchanformat(int sfd, channelformat *chformat)
  6314. {
  6315. struct sf_file *f;
  6316. if((f = findfile(sfd)) ==NULL)
  6317. return -1;
  6318. if(chformat==NULL)
  6319. return -1;
  6320. *chformat = f->chformat;
  6321. return 0;
  6322. }
  6323. const char* sf_getfilename(int sfd)
  6324. {
  6325. struct sf_file *f;
  6326. if((f = findfile(sfd)) ==NULL)
  6327. return NULL;
  6328. return (const char *) f->filename;
  6329. }
  6330. int sf_getcontainersize(int sfd)
  6331. {
  6332. struct sf_file *f;
  6333. if((f = findfile(sfd)) ==NULL)
  6334. return -1;
  6335. return (int) f->fmtchunkEx.Format.wBitsPerSample;
  6336. }
  6337. int sf_getvalidbits(int sfd)
  6338. {
  6339. struct sf_file *f;
  6340. if((f = findfile(sfd)) ==NULL)
  6341. return -1;
  6342. return (int) f->fmtchunkEx.Samples.wValidBitsPerSample;
  6343. }
  6344. //keep this as private func for now, but used by snd routines
  6345. // may have pos >2GB so need unsigned retval
  6346. unsigned int _rsf_getmaxpeak(int sfd,float *peak)
  6347. {
  6348. struct sf_file *f;
  6349. int i;
  6350. double peakval = 0.0;
  6351. if((f = findfile(sfd)) ==NULL)
  6352. return 0xFFFFFFFF;
  6353. if(f->peaks == NULL)
  6354. return 0;
  6355. for(i=0; i < f->fmtchunkEx.Format.nChannels; i++)
  6356. peakval = max(peakval,(double)(f->peaks[i].value));
  6357. *peak = (float) peakval;
  6358. return 1;
  6359. }
  6360. /*RWD */
  6361. int addprop(struct sf_file *f, char *propname, char *src, int size)
  6362. {
  6363. struct property /* *pp,*/ **ppp;
  6364. /*char *np;*/
  6365. if(f->curpropsize + (signed int)strlen(propname) + 2 + 2*size > f->proplim) {
  6366. rsferrno = ESFNOSPACE;
  6367. rsferrstr = "No space in extended properties for new property data";
  6368. return -1;
  6369. }
  6370. for(ppp = &f->props; *ppp != 0; ppp = &(*ppp)->next)
  6371. ;
  6372. if((*ppp = ALLOC(struct property)) == 0
  6373. ||((*ppp)->name = (char *) malloc(strlen(propname)+1)) == 0
  6374. ||((*ppp)->data = (char *) malloc(size)) == 0) {
  6375. rsferrno = ESFNOMEM;
  6376. rsferrstr = "No memory for bigger property data";
  6377. return -1;
  6378. }
  6379. strcpy((*ppp)->name, propname);
  6380. memcpy((*ppp)->data, src, size);
  6381. (*ppp)->size = size;
  6382. (*ppp)->next = 0;
  6383. f->curpropsize += strlen(propname) + 2 + 2*size;
  6384. f->propschanged = 1;
  6385. return 0;
  6386. }
  6387. int sf_makepath(char path[], const char* sfname)
  6388. {
  6389. char* fullname = mksfpath(sfname);
  6390. if(fullname==NULL)
  6391. return -1;
  6392. strcpy(path,fullname);
  6393. return 0;
  6394. }