1
0

RtAudio.cpp 376 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852785378547855785678577858785978607861786278637864786578667867786878697870787178727873787478757876787778787879788078817882788378847885788678877888788978907891789278937894789578967897789878997900790179027903790479057906790779087909791079117912791379147915791679177918791979207921792279237924792579267927792879297930793179327933793479357936793779387939794079417942794379447945794679477948794979507951795279537954795579567957795879597960796179627963796479657966796779687969797079717972797379747975797679777978797979807981798279837984798579867987798879897990799179927993799479957996799779987999800080018002800380048005800680078008800980108011801280138014801580168017801880198020802180228023802480258026802780288029803080318032803380348035803680378038803980408041804280438044804580468047804880498050805180528053805480558056805780588059806080618062806380648065806680678068806980708071807280738074807580768077807880798080808180828083808480858086808780888089809080918092809380948095809680978098809981008101810281038104810581068107810881098110811181128113811481158116811781188119812081218122812381248125812681278128812981308131813281338134813581368137813881398140814181428143814481458146814781488149815081518152815381548155815681578158815981608161816281638164816581668167816881698170817181728173817481758176817781788179818081818182818381848185818681878188818981908191819281938194819581968197819881998200820182028203820482058206820782088209821082118212821382148215821682178218821982208221822282238224822582268227822882298230823182328233823482358236823782388239824082418242824382448245824682478248824982508251825282538254825582568257825882598260826182628263826482658266826782688269827082718272827382748275827682778278827982808281828282838284828582868287828882898290829182928293829482958296829782988299830083018302830383048305830683078308830983108311831283138314831583168317831883198320832183228323832483258326832783288329833083318332833383348335833683378338833983408341834283438344834583468347834883498350835183528353835483558356835783588359836083618362836383648365836683678368836983708371837283738374837583768377837883798380838183828383838483858386838783888389839083918392839383948395839683978398839984008401840284038404840584068407840884098410841184128413841484158416841784188419842084218422842384248425842684278428842984308431843284338434843584368437843884398440844184428443844484458446844784488449845084518452845384548455845684578458845984608461846284638464846584668467846884698470847184728473847484758476847784788479848084818482848384848485848684878488848984908491849284938494849584968497849884998500850185028503850485058506850785088509851085118512851385148515851685178518851985208521852285238524852585268527852885298530853185328533853485358536853785388539854085418542854385448545854685478548854985508551855285538554855585568557855885598560856185628563856485658566856785688569857085718572857385748575857685778578857985808581858285838584858585868587858885898590859185928593859485958596859785988599860086018602860386048605860686078608860986108611861286138614861586168617861886198620862186228623862486258626862786288629863086318632863386348635863686378638863986408641864286438644864586468647864886498650865186528653865486558656865786588659866086618662866386648665866686678668866986708671867286738674867586768677867886798680868186828683868486858686868786888689869086918692869386948695869686978698869987008701870287038704870587068707870887098710871187128713871487158716871787188719872087218722872387248725872687278728872987308731873287338734873587368737873887398740874187428743874487458746874787488749875087518752875387548755875687578758875987608761876287638764876587668767876887698770877187728773877487758776877787788779878087818782878387848785878687878788878987908791879287938794879587968797879887998800880188028803880488058806880788088809881088118812881388148815881688178818881988208821882288238824882588268827882888298830883188328833883488358836883788388839884088418842884388448845884688478848884988508851885288538854885588568857885888598860886188628863886488658866886788688869887088718872887388748875887688778878887988808881888288838884888588868887888888898890889188928893889488958896889788988899890089018902890389048905890689078908890989108911891289138914891589168917891889198920892189228923892489258926892789288929893089318932893389348935893689378938893989408941894289438944894589468947894889498950895189528953895489558956895789588959896089618962896389648965896689678968896989708971897289738974897589768977897889798980898189828983898489858986898789888989899089918992899389948995899689978998899990009001900290039004900590069007900890099010901190129013901490159016901790189019902090219022902390249025902690279028902990309031903290339034903590369037903890399040904190429043904490459046904790489049905090519052905390549055905690579058905990609061906290639064906590669067906890699070907190729073907490759076907790789079908090819082908390849085908690879088908990909091909290939094909590969097909890999100910191029103910491059106910791089109911091119112911391149115911691179118911991209121912291239124912591269127912891299130913191329133913491359136913791389139914091419142914391449145914691479148914991509151915291539154915591569157915891599160916191629163916491659166916791689169917091719172917391749175917691779178917991809181918291839184918591869187918891899190919191929193919491959196919791989199920092019202920392049205920692079208920992109211921292139214921592169217921892199220922192229223922492259226922792289229923092319232923392349235923692379238923992409241924292439244924592469247924892499250925192529253925492559256925792589259926092619262926392649265926692679268926992709271927292739274927592769277927892799280928192829283928492859286928792889289929092919292929392949295929692979298929993009301930293039304930593069307930893099310931193129313931493159316931793189319932093219322932393249325932693279328932993309331933293339334933593369337933893399340934193429343934493459346934793489349935093519352935393549355935693579358935993609361936293639364936593669367936893699370937193729373937493759376937793789379938093819382938393849385938693879388938993909391939293939394939593969397939893999400940194029403940494059406940794089409941094119412941394149415941694179418941994209421942294239424942594269427942894299430943194329433943494359436943794389439944094419442944394449445944694479448944994509451945294539454945594569457945894599460946194629463946494659466946794689469947094719472947394749475947694779478947994809481948294839484948594869487948894899490949194929493949494959496949794989499950095019502950395049505950695079508950995109511951295139514951595169517951895199520952195229523952495259526952795289529953095319532953395349535953695379538953995409541954295439544954595469547954895499550955195529553955495559556955795589559956095619562956395649565956695679568956995709571957295739574957595769577957895799580958195829583958495859586958795889589959095919592959395949595959695979598959996009601960296039604960596069607960896099610961196129613961496159616961796189619962096219622962396249625962696279628962996309631963296339634963596369637963896399640964196429643964496459646964796489649965096519652965396549655965696579658965996609661966296639664966596669667966896699670967196729673967496759676967796789679968096819682968396849685968696879688968996909691969296939694969596969697969896999700970197029703970497059706970797089709971097119712971397149715971697179718971997209721972297239724972597269727972897299730973197329733973497359736973797389739974097419742974397449745974697479748974997509751975297539754975597569757975897599760976197629763976497659766976797689769977097719772977397749775977697779778977997809781978297839784978597869787978897899790979197929793979497959796979797989799980098019802980398049805980698079808980998109811981298139814981598169817981898199820982198229823982498259826982798289829983098319832983398349835983698379838983998409841984298439844984598469847984898499850985198529853985498559856985798589859986098619862986398649865986698679868986998709871987298739874987598769877987898799880988198829883988498859886988798889889989098919892989398949895989698979898989999009901990299039904990599069907990899099910991199129913991499159916991799189919992099219922992399249925992699279928992999309931993299339934993599369937993899399940994199429943994499459946994799489949995099519952995399549955995699579958995999609961996299639964996599669967996899699970997199729973997499759976997799789979998099819982998399849985998699879988998999909991999299939994999599969997999899991000010001100021000310004100051000610007100081000910010100111001210013100141001510016100171001810019100201002110022100231002410025100261002710028100291003010031100321003310034100351003610037100381003910040100411004210043100441004510046100471004810049100501005110052100531005410055100561005710058100591006010061100621006310064100651006610067100681006910070100711007210073100741007510076100771007810079100801008110082100831008410085100861008710088100891009010091100921009310094100951009610097100981009910100101011010210103101041010510106101071010810109101101011110112101131011410115101161011710118101191012010121101221012310124101251012610127101281012910130101311013210133101341013510136101371013810139101401014110142101431014410145101461014710148101491015010151101521015310154101551015610157101581015910160101611016210163101641016510166101671016810169101701017110172101731017410175101761017710178101791018010181101821018310184101851018610187101881018910190101911019210193101941019510196101971019810199102001020110202102031020410205102061020710208102091021010211102121021310214102151021610217102181021910220102211022210223102241022510226102271022810229102301023110232102331023410235102361023710238102391024010241102421024310244102451024610247102481024910250102511025210253102541025510256102571025810259102601026110262102631026410265102661026710268102691027010271102721027310274102751027610277102781027910280102811028210283102841028510286102871028810289102901029110292102931029410295102961029710298102991030010301103021030310304103051030610307103081030910310103111031210313103141031510316103171031810319103201032110322103231032410325103261032710328103291033010331103321033310334103351033610337103381033910340103411034210343103441034510346103471034810349103501035110352103531035410355103561035710358103591036010361103621036310364103651036610367103681036910370103711037210373103741037510376103771037810379103801038110382103831038410385103861038710388103891039010391103921039310394103951039610397103981039910400104011040210403104041040510406104071040810409104101041110412104131041410415104161041710418104191042010421104221042310424104251042610427104281042910430104311043210433104341043510436104371043810439104401044110442104431044410445104461044710448104491045010451104521045310454104551045610457104581045910460104611046210463104641046510466104671046810469104701047110472104731047410475104761047710478104791048010481104821048310484104851048610487104881048910490104911049210493104941049510496104971049810499105001050110502105031050410505105061050710508105091051010511105121051310514105151051610517105181051910520105211052210523105241052510526105271052810529105301053110532105331053410535105361053710538105391054010541105421054310544105451054610547105481054910550105511055210553105541055510556105571055810559105601056110562105631056410565105661056710568105691057010571105721057310574105751057610577105781057910580105811058210583105841058510586105871058810589105901059110592105931059410595105961059710598105991060010601106021060310604106051060610607106081060910610106111061210613106141061510616106171061810619106201062110622106231062410625106261062710628106291063010631106321063310634106351063610637106381063910640106411064210643106441064510646106471064810649106501065110652106531065410655106561065710658106591066010661106621066310664106651066610667106681066910670106711067210673106741067510676106771067810679106801068110682106831068410685106861068710688106891069010691106921069310694106951069610697106981069910700107011070210703107041070510706107071070810709107101071110712107131071410715107161071710718107191072010721107221072310724107251072610727107281072910730107311073210733107341073510736107371073810739107401074110742107431074410745107461074710748107491075010751107521075310754107551075610757107581075910760107611076210763107641076510766107671076810769107701077110772107731077410775107761077710778107791078010781107821078310784107851078610787107881078910790107911079210793107941079510796107971079810799108001080110802108031080410805108061080710808108091081010811108121081310814108151081610817108181081910820108211082210823108241082510826108271082810829108301083110832108331083410835108361083710838108391084010841108421084310844108451084610847108481084910850108511085210853108541085510856108571085810859108601086110862108631086410865108661086710868108691087010871108721087310874108751087610877108781087910880108811088210883108841088510886108871088810889108901089110892108931089410895108961089710898108991090010901109021090310904109051090610907109081090910910109111091210913109141091510916109171091810919109201092110922109231092410925109261092710928109291093010931109321093310934109351093610937109381093910940109411094210943109441094510946109471094810949109501095110952109531095410955109561095710958109591096010961109621096310964109651096610967109681096910970109711097210973109741097510976109771097810979
  1. /************************************************************************/
  2. /*! \class RtAudio
  3. \brief Realtime audio i/o C++ classes.
  4. RtAudio provides a common API (Application Programming Interface)
  5. for realtime audio input/output across Linux (native ALSA, Jack,
  6. and OSS), Macintosh OS X (CoreAudio and Jack), and Windows
  7. (DirectSound, ASIO and WASAPI) operating systems.
  8. RtAudio GitHub site: https://github.com/thestk/rtaudio
  9. RtAudio WWW site: http://www.music.mcgill.ca/~gary/rtaudio/
  10. RtAudio: realtime audio i/o C++ classes
  11. Copyright (c) 2001-2021 Gary P. Scavone
  12. Permission is hereby granted, free of charge, to any person
  13. obtaining a copy of this software and associated documentation files
  14. (the "Software"), to deal in the Software without restriction,
  15. including without limitation the rights to use, copy, modify, merge,
  16. publish, distribute, sublicense, and/or sell copies of the Software,
  17. and to permit persons to whom the Software is furnished to do so,
  18. subject to the following conditions:
  19. The above copyright notice and this permission notice shall be
  20. included in all copies or substantial portions of the Software.
  21. Any person wishing to distribute modifications to the Software is
  22. asked to send the modifications to the original developer so that
  23. they can be incorporated into the canonical version. This is,
  24. however, not a binding provision of this license.
  25. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  26. EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  27. MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  28. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
  29. ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
  30. CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  31. WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  32. */
  33. /************************************************************************/
  34. // RtAudio: Version 5.2.0
  35. #include "RtAudio.h"
  36. #include <iostream>
  37. #include <cstdlib>
  38. #include <cstring>
  39. #include <climits>
  40. #include <cmath>
  41. #include <algorithm>
  42. // Static variable definitions.
  43. const unsigned int RtApi::MAX_SAMPLE_RATES = 14;
  44. const unsigned int RtApi::SAMPLE_RATES[] = {
  45. 4000, 5512, 8000, 9600, 11025, 16000, 22050,
  46. 32000, 44100, 48000, 88200, 96000, 176400, 192000
  47. };
  48. #if defined(_WIN32) || defined(__CYGWIN__)
  49. #define MUTEX_INITIALIZE(A) InitializeCriticalSection(A)
  50. #define MUTEX_DESTROY(A) DeleteCriticalSection(A)
  51. #define MUTEX_LOCK(A) EnterCriticalSection(A)
  52. #define MUTEX_UNLOCK(A) LeaveCriticalSection(A)
  53. #include "tchar.h"
  54. template<typename T> inline
  55. std::string convertCharPointerToStdString(const T *text);
  56. template<> inline
  57. std::string convertCharPointerToStdString(const char *text)
  58. {
  59. return std::string(text);
  60. }
  61. template<> inline
  62. std::string convertCharPointerToStdString(const wchar_t *text)
  63. {
  64. int length = WideCharToMultiByte(CP_UTF8, 0, text, -1, NULL, 0, NULL, NULL);
  65. std::string s( length-1, '\0' );
  66. WideCharToMultiByte(CP_UTF8, 0, text, -1, &s[0], length, NULL, NULL);
  67. return s;
  68. }
  69. #elif defined(__unix__) || defined(__APPLE__)
  70. // pthread API
  71. #define MUTEX_INITIALIZE(A) pthread_mutex_init(A, NULL)
  72. #define MUTEX_DESTROY(A) pthread_mutex_destroy(A)
  73. #define MUTEX_LOCK(A) pthread_mutex_lock(A)
  74. #define MUTEX_UNLOCK(A) pthread_mutex_unlock(A)
  75. #endif
  76. // *************************************************** //
  77. //
  78. // RtAudio definitions.
  79. //
  80. // *************************************************** //
  81. std::string RtAudio :: getVersion( void )
  82. {
  83. return RTAUDIO_VERSION;
  84. }
  85. // Define API names and display names.
  86. // Must be in same order as API enum.
  87. extern "C" {
  88. const char* rtaudio_api_names[][2] = {
  89. { "unspecified" , "Unknown" },
  90. { "alsa" , "ALSA" },
  91. { "pulse" , "Pulse" },
  92. { "oss" , "OpenSoundSystem" },
  93. { "jack" , "Jack" },
  94. { "core" , "CoreAudio" },
  95. { "wasapi" , "WASAPI" },
  96. { "asio" , "ASIO" },
  97. { "ds" , "DirectSound" },
  98. { "dummy" , "Dummy" },
  99. };
  100. const unsigned int rtaudio_num_api_names =
  101. sizeof(rtaudio_api_names)/sizeof(rtaudio_api_names[0]);
  102. // The order here will control the order of RtAudio's API search in
  103. // the constructor.
  104. extern "C" const RtAudio::Api rtaudio_compiled_apis[] = {
  105. #if defined(__UNIX_JACK__)
  106. RtAudio::UNIX_JACK,
  107. #endif
  108. #if defined(__LINUX_PULSE__)
  109. RtAudio::LINUX_PULSE,
  110. #endif
  111. #if defined(__LINUX_ALSA__)
  112. RtAudio::LINUX_ALSA,
  113. #endif
  114. #if defined(__LINUX_OSS__)
  115. RtAudio::LINUX_OSS,
  116. #endif
  117. #if defined(__WINDOWS_ASIO__)
  118. RtAudio::WINDOWS_ASIO,
  119. #endif
  120. #if defined(__WINDOWS_WASAPI__)
  121. RtAudio::WINDOWS_WASAPI,
  122. #endif
  123. #if defined(__WINDOWS_DS__)
  124. RtAudio::WINDOWS_DS,
  125. #endif
  126. #if defined(__MACOSX_CORE__)
  127. RtAudio::MACOSX_CORE,
  128. #endif
  129. #if defined(__RTAUDIO_DUMMY__)
  130. RtAudio::RTAUDIO_DUMMY,
  131. #endif
  132. RtAudio::UNSPECIFIED,
  133. };
  134. extern "C" const unsigned int rtaudio_num_compiled_apis =
  135. sizeof(rtaudio_compiled_apis)/sizeof(rtaudio_compiled_apis[0])-1;
  136. }
  137. // This is a compile-time check that rtaudio_num_api_names == RtAudio::NUM_APIS.
  138. // If the build breaks here, check that they match.
  139. template<bool b> class StaticAssert { private: StaticAssert() {} };
  140. template<> class StaticAssert<true>{ public: StaticAssert() {} };
  141. class StaticAssertions { StaticAssertions() {
  142. StaticAssert<rtaudio_num_api_names == RtAudio::NUM_APIS>();
  143. }};
  144. void RtAudio :: getCompiledApi( std::vector<RtAudio::Api> &apis )
  145. {
  146. apis = std::vector<RtAudio::Api>(rtaudio_compiled_apis,
  147. rtaudio_compiled_apis + rtaudio_num_compiled_apis);
  148. }
  149. std::string RtAudio :: getApiName( RtAudio::Api api )
  150. {
  151. if (api < 0 || api >= RtAudio::NUM_APIS)
  152. return "";
  153. return rtaudio_api_names[api][0];
  154. }
  155. std::string RtAudio :: getApiDisplayName( RtAudio::Api api )
  156. {
  157. if (api < 0 || api >= RtAudio::NUM_APIS)
  158. return "Unknown";
  159. return rtaudio_api_names[api][1];
  160. }
  161. RtAudio::Api RtAudio :: getCompiledApiByName( const std::string &name )
  162. {
  163. unsigned int i=0;
  164. for (i = 0; i < rtaudio_num_compiled_apis; ++i)
  165. if (name == rtaudio_api_names[rtaudio_compiled_apis[i]][0])
  166. return rtaudio_compiled_apis[i];
  167. return RtAudio::UNSPECIFIED;
  168. }
  169. void RtAudio :: openRtApi( RtAudio::Api api )
  170. {
  171. if ( rtapi_ )
  172. delete rtapi_;
  173. rtapi_ = 0;
  174. #if defined(__UNIX_JACK__)
  175. if ( api == UNIX_JACK )
  176. rtapi_ = new RtApiJack();
  177. #endif
  178. #if defined(__LINUX_ALSA__)
  179. if ( api == LINUX_ALSA )
  180. rtapi_ = new RtApiAlsa();
  181. #endif
  182. #if defined(__LINUX_PULSE__)
  183. if ( api == LINUX_PULSE )
  184. rtapi_ = new RtApiPulse();
  185. #endif
  186. #if defined(__LINUX_OSS__)
  187. if ( api == LINUX_OSS )
  188. rtapi_ = new RtApiOss();
  189. #endif
  190. #if defined(__WINDOWS_ASIO__)
  191. if ( api == WINDOWS_ASIO )
  192. rtapi_ = new RtApiAsio();
  193. #endif
  194. #if defined(__WINDOWS_WASAPI__)
  195. if ( api == WINDOWS_WASAPI )
  196. rtapi_ = new RtApiWasapi();
  197. #endif
  198. #if defined(__WINDOWS_DS__)
  199. if ( api == WINDOWS_DS )
  200. rtapi_ = new RtApiDs();
  201. #endif
  202. #if defined(__MACOSX_CORE__)
  203. if ( api == MACOSX_CORE )
  204. rtapi_ = new RtApiCore();
  205. #endif
  206. #if defined(__RTAUDIO_DUMMY__)
  207. if ( api == RTAUDIO_DUMMY )
  208. rtapi_ = new RtApiDummy();
  209. #endif
  210. }
  211. RtAudio :: RtAudio( RtAudio::Api api )
  212. {
  213. rtapi_ = 0;
  214. if ( api != UNSPECIFIED ) {
  215. // Attempt to open the specified API.
  216. openRtApi( api );
  217. if ( rtapi_ ) return;
  218. // No compiled support for specified API value. Issue a debug
  219. // warning and continue as if no API was specified.
  220. std::cerr << "\nRtAudio: no compiled support for specified API argument!\n" << std::endl;
  221. }
  222. // Iterate through the compiled APIs and return as soon as we find
  223. // one with at least one device or we reach the end of the list.
  224. std::vector< RtAudio::Api > apis;
  225. getCompiledApi( apis );
  226. for ( unsigned int i=0; i<apis.size(); i++ ) {
  227. openRtApi( apis[i] );
  228. if ( rtapi_ && rtapi_->getDeviceCount() ) break;
  229. }
  230. if ( rtapi_ ) return;
  231. // It should not be possible to get here because the preprocessor
  232. // definition __RTAUDIO_DUMMY__ is automatically defined if no
  233. // API-specific definitions are passed to the compiler. But just in
  234. // case something weird happens, we'll throw an error.
  235. std::string errorText = "\nRtAudio: no compiled API support found ... critical error!!\n\n";
  236. throw( RtAudioError( errorText, RtAudioError::UNSPECIFIED ) );
  237. }
  238. RtAudio :: ~RtAudio()
  239. {
  240. if ( rtapi_ )
  241. delete rtapi_;
  242. }
  243. void RtAudio :: openStream( RtAudio::StreamParameters *outputParameters,
  244. RtAudio::StreamParameters *inputParameters,
  245. RtAudioFormat format, unsigned int sampleRate,
  246. unsigned int *bufferFrames,
  247. RtAudioCallback callback, void *userData,
  248. RtAudio::StreamOptions *options,
  249. RtAudioErrorCallback errorCallback )
  250. {
  251. return rtapi_->openStream( outputParameters, inputParameters, format,
  252. sampleRate, bufferFrames, callback,
  253. userData, options, errorCallback );
  254. }
  255. // *************************************************** //
  256. //
  257. // Public RtApi definitions (see end of file for
  258. // private or protected utility functions).
  259. //
  260. // *************************************************** //
  261. RtApi :: RtApi()
  262. {
  263. stream_.state = STREAM_CLOSED;
  264. stream_.mode = UNINITIALIZED;
  265. stream_.apiHandle = 0;
  266. stream_.userBuffer[0] = 0;
  267. stream_.userBuffer[1] = 0;
  268. MUTEX_INITIALIZE( &stream_.mutex );
  269. showWarnings_ = true;
  270. firstErrorOccurred_ = false;
  271. }
  272. RtApi :: ~RtApi()
  273. {
  274. MUTEX_DESTROY( &stream_.mutex );
  275. }
  276. void RtApi :: openStream( RtAudio::StreamParameters *oParams,
  277. RtAudio::StreamParameters *iParams,
  278. RtAudioFormat format, unsigned int sampleRate,
  279. unsigned int *bufferFrames,
  280. RtAudioCallback callback, void *userData,
  281. RtAudio::StreamOptions *options,
  282. RtAudioErrorCallback errorCallback )
  283. {
  284. if ( stream_.state != STREAM_CLOSED ) {
  285. errorText_ = "RtApi::openStream: a stream is already open!";
  286. error( RtAudioError::INVALID_USE );
  287. return;
  288. }
  289. // Clear stream information potentially left from a previously open stream.
  290. clearStreamInfo();
  291. if ( oParams && oParams->nChannels < 1 ) {
  292. errorText_ = "RtApi::openStream: a non-NULL output StreamParameters structure cannot have an nChannels value less than one.";
  293. error( RtAudioError::INVALID_USE );
  294. return;
  295. }
  296. if ( iParams && iParams->nChannels < 1 ) {
  297. errorText_ = "RtApi::openStream: a non-NULL input StreamParameters structure cannot have an nChannels value less than one.";
  298. error( RtAudioError::INVALID_USE );
  299. return;
  300. }
  301. if ( oParams == NULL && iParams == NULL ) {
  302. errorText_ = "RtApi::openStream: input and output StreamParameters structures are both NULL!";
  303. error( RtAudioError::INVALID_USE );
  304. return;
  305. }
  306. if ( formatBytes(format) == 0 ) {
  307. errorText_ = "RtApi::openStream: 'format' parameter value is undefined.";
  308. error( RtAudioError::INVALID_USE );
  309. return;
  310. }
  311. unsigned int nDevices = getDeviceCount();
  312. unsigned int oChannels = 0;
  313. if ( oParams ) {
  314. oChannels = oParams->nChannels;
  315. if ( oParams->deviceId >= nDevices ) {
  316. errorText_ = "RtApi::openStream: output device parameter value is invalid.";
  317. error( RtAudioError::INVALID_USE );
  318. return;
  319. }
  320. }
  321. unsigned int iChannels = 0;
  322. if ( iParams ) {
  323. iChannels = iParams->nChannels;
  324. if ( iParams->deviceId >= nDevices ) {
  325. errorText_ = "RtApi::openStream: input device parameter value is invalid.";
  326. error( RtAudioError::INVALID_USE );
  327. return;
  328. }
  329. }
  330. bool result;
  331. if ( oChannels > 0 ) {
  332. result = probeDeviceOpen( oParams->deviceId, OUTPUT, oChannels, oParams->firstChannel,
  333. sampleRate, format, bufferFrames, options );
  334. if ( result == false ) {
  335. error( RtAudioError::SYSTEM_ERROR );
  336. return;
  337. }
  338. }
  339. if ( iChannels > 0 ) {
  340. result = probeDeviceOpen( iParams->deviceId, INPUT, iChannels, iParams->firstChannel,
  341. sampleRate, format, bufferFrames, options );
  342. if ( result == false ) {
  343. if ( oChannels > 0 ) closeStream();
  344. error( RtAudioError::SYSTEM_ERROR );
  345. return;
  346. }
  347. }
  348. stream_.callbackInfo.callback = (void *) callback;
  349. stream_.callbackInfo.userData = userData;
  350. stream_.callbackInfo.errorCallback = (void *) errorCallback;
  351. if ( options ) options->numberOfBuffers = stream_.nBuffers;
  352. stream_.state = STREAM_STOPPED;
  353. }
  354. unsigned int RtApi :: getDefaultInputDevice( void )
  355. {
  356. // Should be reimplemented in subclasses if necessary.
  357. unsigned int nDevices = getDeviceCount();
  358. for ( unsigned int i = 0; i < nDevices; i++ ) {
  359. if ( getDeviceInfo( i ).isDefaultInput ) {
  360. return i;
  361. }
  362. }
  363. return 0;
  364. }
  365. unsigned int RtApi :: getDefaultOutputDevice( void )
  366. {
  367. // Should be reimplemented in subclasses if necessary.
  368. unsigned int nDevices = getDeviceCount();
  369. for ( unsigned int i = 0; i < nDevices; i++ ) {
  370. if ( getDeviceInfo( i ).isDefaultOutput ) {
  371. return i;
  372. }
  373. }
  374. return 0;
  375. }
  376. void RtApi :: closeStream( void )
  377. {
  378. // MUST be implemented in subclasses!
  379. return;
  380. }
  381. bool RtApi :: probeDeviceOpen( unsigned int /*device*/, StreamMode /*mode*/, unsigned int /*channels*/,
  382. unsigned int /*firstChannel*/, unsigned int /*sampleRate*/,
  383. RtAudioFormat /*format*/, unsigned int * /*bufferSize*/,
  384. RtAudio::StreamOptions * /*options*/ )
  385. {
  386. // MUST be implemented in subclasses!
  387. return FAILURE;
  388. }
  389. void RtApi :: tickStreamTime( void )
  390. {
  391. // Subclasses that do not provide their own implementation of
  392. // getStreamTime should call this function once per buffer I/O to
  393. // provide basic stream time support.
  394. stream_.streamTime += ( stream_.bufferSize * 1.0 / stream_.sampleRate );
  395. #if defined( HAVE_GETTIMEOFDAY )
  396. gettimeofday( &stream_.lastTickTimestamp, NULL );
  397. #endif
  398. }
  399. long RtApi :: getStreamLatency( void )
  400. {
  401. verifyStream();
  402. long totalLatency = 0;
  403. if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX )
  404. totalLatency = stream_.latency[0];
  405. if ( stream_.mode == INPUT || stream_.mode == DUPLEX )
  406. totalLatency += stream_.latency[1];
  407. return totalLatency;
  408. }
  409. double RtApi :: getStreamTime( void )
  410. {
  411. verifyStream();
  412. #if defined( HAVE_GETTIMEOFDAY )
  413. // Return a very accurate estimate of the stream time by
  414. // adding in the elapsed time since the last tick.
  415. struct timeval then;
  416. struct timeval now;
  417. if ( stream_.state != STREAM_RUNNING || stream_.streamTime == 0.0 )
  418. return stream_.streamTime;
  419. gettimeofday( &now, NULL );
  420. then = stream_.lastTickTimestamp;
  421. return stream_.streamTime +
  422. ((now.tv_sec + 0.000001 * now.tv_usec) -
  423. (then.tv_sec + 0.000001 * then.tv_usec));
  424. #else
  425. return stream_.streamTime;
  426. #endif
  427. }
  428. void RtApi :: setStreamTime( double time )
  429. {
  430. verifyStream();
  431. if ( time >= 0.0 )
  432. stream_.streamTime = time;
  433. #if defined( HAVE_GETTIMEOFDAY )
  434. gettimeofday( &stream_.lastTickTimestamp, NULL );
  435. #endif
  436. }
  437. unsigned int RtApi :: getStreamSampleRate( void )
  438. {
  439. verifyStream();
  440. return stream_.sampleRate;
  441. }
  442. // *************************************************** //
  443. //
  444. // OS/API-specific methods.
  445. //
  446. // *************************************************** //
  447. #if defined(__MACOSX_CORE__)
  448. #include <unistd.h>
  449. // The OS X CoreAudio API is designed to use a separate callback
  450. // procedure for each of its audio devices. A single RtAudio duplex
  451. // stream using two different devices is supported here, though it
  452. // cannot be guaranteed to always behave correctly because we cannot
  453. // synchronize these two callbacks.
  454. //
  455. // A property listener is installed for over/underrun information.
  456. // However, no functionality is currently provided to allow property
  457. // listeners to trigger user handlers because it is unclear what could
  458. // be done if a critical stream parameter (buffer size, sample rate,
  459. // device disconnect) notification arrived. The listeners entail
  460. // quite a bit of extra code and most likely, a user program wouldn't
  461. // be prepared for the result anyway. However, we do provide a flag
  462. // to the client callback function to inform of an over/underrun.
  463. // A structure to hold various information related to the CoreAudio API
  464. // implementation.
  465. struct CoreHandle {
  466. AudioDeviceID id[2]; // device ids
  467. #if defined( MAC_OS_X_VERSION_10_5 ) && ( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 )
  468. AudioDeviceIOProcID procId[2];
  469. #endif
  470. UInt32 iStream[2]; // device stream index (or first if using multiple)
  471. UInt32 nStreams[2]; // number of streams to use
  472. bool xrun[2];
  473. char *deviceBuffer;
  474. pthread_cond_t condition;
  475. int drainCounter; // Tracks callback counts when draining
  476. bool internalDrain; // Indicates if stop is initiated from callback or not.
  477. CoreHandle()
  478. :deviceBuffer(0), drainCounter(0), internalDrain(false) { nStreams[0] = 1; nStreams[1] = 1; id[0] = 0; id[1] = 0; xrun[0] = false; xrun[1] = false; }
  479. };
  480. RtApiCore:: RtApiCore()
  481. {
  482. #if defined( AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER )
  483. // This is a largely undocumented but absolutely necessary
  484. // requirement starting with OS-X 10.6. If not called, queries and
  485. // updates to various audio device properties are not handled
  486. // correctly.
  487. CFRunLoopRef theRunLoop = NULL;
  488. AudioObjectPropertyAddress property = { kAudioHardwarePropertyRunLoop,
  489. kAudioObjectPropertyScopeGlobal,
  490. kAudioObjectPropertyElementMaster };
  491. OSStatus result = AudioObjectSetPropertyData( kAudioObjectSystemObject, &property, 0, NULL, sizeof(CFRunLoopRef), &theRunLoop);
  492. if ( result != noErr ) {
  493. errorText_ = "RtApiCore::RtApiCore: error setting run loop property!";
  494. error( RtAudioError::WARNING );
  495. }
  496. #endif
  497. }
  498. RtApiCore :: ~RtApiCore()
  499. {
  500. // The subclass destructor gets called before the base class
  501. // destructor, so close an existing stream before deallocating
  502. // apiDeviceId memory.
  503. if ( stream_.state != STREAM_CLOSED ) closeStream();
  504. }
  505. unsigned int RtApiCore :: getDeviceCount( void )
  506. {
  507. // Find out how many audio devices there are, if any.
  508. UInt32 dataSize;
  509. AudioObjectPropertyAddress propertyAddress = { kAudioHardwarePropertyDevices, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster };
  510. OSStatus result = AudioObjectGetPropertyDataSize( kAudioObjectSystemObject, &propertyAddress, 0, NULL, &dataSize );
  511. if ( result != noErr ) {
  512. errorText_ = "RtApiCore::getDeviceCount: OS-X error getting device info!";
  513. error( RtAudioError::WARNING );
  514. return 0;
  515. }
  516. return dataSize / sizeof( AudioDeviceID );
  517. }
  518. unsigned int RtApiCore :: getDefaultInputDevice( void )
  519. {
  520. unsigned int nDevices = getDeviceCount();
  521. if ( nDevices <= 1 ) return 0;
  522. AudioDeviceID id;
  523. UInt32 dataSize = sizeof( AudioDeviceID );
  524. AudioObjectPropertyAddress property = { kAudioHardwarePropertyDefaultInputDevice, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster };
  525. OSStatus result = AudioObjectGetPropertyData( kAudioObjectSystemObject, &property, 0, NULL, &dataSize, &id );
  526. if ( result != noErr ) {
  527. errorText_ = "RtApiCore::getDefaultInputDevice: OS-X system error getting device.";
  528. error( RtAudioError::WARNING );
  529. return 0;
  530. }
  531. dataSize *= nDevices;
  532. AudioDeviceID deviceList[ nDevices ];
  533. property.mSelector = kAudioHardwarePropertyDevices;
  534. result = AudioObjectGetPropertyData( kAudioObjectSystemObject, &property, 0, NULL, &dataSize, (void *) &deviceList );
  535. if ( result != noErr ) {
  536. errorText_ = "RtApiCore::getDefaultInputDevice: OS-X system error getting device IDs.";
  537. error( RtAudioError::WARNING );
  538. return 0;
  539. }
  540. for ( unsigned int i=0; i<nDevices; i++ )
  541. if ( id == deviceList[i] ) return i;
  542. errorText_ = "RtApiCore::getDefaultInputDevice: No default device found!";
  543. error( RtAudioError::WARNING );
  544. return 0;
  545. }
  546. unsigned int RtApiCore :: getDefaultOutputDevice( void )
  547. {
  548. unsigned int nDevices = getDeviceCount();
  549. if ( nDevices <= 1 ) return 0;
  550. AudioDeviceID id;
  551. UInt32 dataSize = sizeof( AudioDeviceID );
  552. AudioObjectPropertyAddress property = { kAudioHardwarePropertyDefaultOutputDevice, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster };
  553. OSStatus result = AudioObjectGetPropertyData( kAudioObjectSystemObject, &property, 0, NULL, &dataSize, &id );
  554. if ( result != noErr ) {
  555. errorText_ = "RtApiCore::getDefaultOutputDevice: OS-X system error getting device.";
  556. error( RtAudioError::WARNING );
  557. return 0;
  558. }
  559. dataSize = sizeof( AudioDeviceID ) * nDevices;
  560. AudioDeviceID deviceList[ nDevices ];
  561. property.mSelector = kAudioHardwarePropertyDevices;
  562. result = AudioObjectGetPropertyData( kAudioObjectSystemObject, &property, 0, NULL, &dataSize, (void *) &deviceList );
  563. if ( result != noErr ) {
  564. errorText_ = "RtApiCore::getDefaultOutputDevice: OS-X system error getting device IDs.";
  565. error( RtAudioError::WARNING );
  566. return 0;
  567. }
  568. for ( unsigned int i=0; i<nDevices; i++ )
  569. if ( id == deviceList[i] ) return i;
  570. errorText_ = "RtApiCore::getDefaultOutputDevice: No default device found!";
  571. error( RtAudioError::WARNING );
  572. return 0;
  573. }
  574. RtAudio::DeviceInfo RtApiCore :: getDeviceInfo( unsigned int device )
  575. {
  576. RtAudio::DeviceInfo info;
  577. info.probed = false;
  578. // Get device ID
  579. unsigned int nDevices = getDeviceCount();
  580. if ( nDevices == 0 ) {
  581. errorText_ = "RtApiCore::getDeviceInfo: no devices found!";
  582. error( RtAudioError::INVALID_USE );
  583. return info;
  584. }
  585. if ( device >= nDevices ) {
  586. errorText_ = "RtApiCore::getDeviceInfo: device ID is invalid!";
  587. error( RtAudioError::INVALID_USE );
  588. return info;
  589. }
  590. AudioDeviceID deviceList[ nDevices ];
  591. UInt32 dataSize = sizeof( AudioDeviceID ) * nDevices;
  592. AudioObjectPropertyAddress property = { kAudioHardwarePropertyDevices,
  593. kAudioObjectPropertyScopeGlobal,
  594. kAudioObjectPropertyElementMaster };
  595. OSStatus result = AudioObjectGetPropertyData( kAudioObjectSystemObject, &property,
  596. 0, NULL, &dataSize, (void *) &deviceList );
  597. if ( result != noErr ) {
  598. errorText_ = "RtApiCore::getDeviceInfo: OS-X system error getting device IDs.";
  599. error( RtAudioError::WARNING );
  600. return info;
  601. }
  602. AudioDeviceID id = deviceList[ device ];
  603. // Get the device name.
  604. info.name.erase();
  605. CFStringRef cfname;
  606. dataSize = sizeof( CFStringRef );
  607. property.mSelector = kAudioObjectPropertyManufacturer;
  608. result = AudioObjectGetPropertyData( id, &property, 0, NULL, &dataSize, &cfname );
  609. if ( result != noErr ) {
  610. errorStream_ << "RtApiCore::probeDeviceInfo: system error (" << getErrorCode( result ) << ") getting device manufacturer.";
  611. errorText_ = errorStream_.str();
  612. error( RtAudioError::WARNING );
  613. return info;
  614. }
  615. //const char *mname = CFStringGetCStringPtr( cfname, CFStringGetSystemEncoding() );
  616. int length = CFStringGetLength(cfname);
  617. char *mname = (char *)malloc(length * 3 + 1);
  618. #if defined( UNICODE ) || defined( _UNICODE )
  619. CFStringGetCString(cfname, mname, length * 3 + 1, kCFStringEncodingUTF8);
  620. #else
  621. CFStringGetCString(cfname, mname, length * 3 + 1, CFStringGetSystemEncoding());
  622. #endif
  623. info.name.append( (const char *)mname, strlen(mname) );
  624. info.name.append( ": " );
  625. CFRelease( cfname );
  626. free(mname);
  627. property.mSelector = kAudioObjectPropertyName;
  628. result = AudioObjectGetPropertyData( id, &property, 0, NULL, &dataSize, &cfname );
  629. if ( result != noErr ) {
  630. errorStream_ << "RtApiCore::probeDeviceInfo: system error (" << getErrorCode( result ) << ") getting device name.";
  631. errorText_ = errorStream_.str();
  632. error( RtAudioError::WARNING );
  633. return info;
  634. }
  635. //const char *name = CFStringGetCStringPtr( cfname, CFStringGetSystemEncoding() );
  636. length = CFStringGetLength(cfname);
  637. char *name = (char *)malloc(length * 3 + 1);
  638. #if defined( UNICODE ) || defined( _UNICODE )
  639. CFStringGetCString(cfname, name, length * 3 + 1, kCFStringEncodingUTF8);
  640. #else
  641. CFStringGetCString(cfname, name, length * 3 + 1, CFStringGetSystemEncoding());
  642. #endif
  643. info.name.append( (const char *)name, strlen(name) );
  644. CFRelease( cfname );
  645. free(name);
  646. // Get the output stream "configuration".
  647. AudioBufferList *bufferList = nil;
  648. property.mSelector = kAudioDevicePropertyStreamConfiguration;
  649. property.mScope = kAudioDevicePropertyScopeOutput;
  650. // property.mElement = kAudioObjectPropertyElementWildcard;
  651. dataSize = 0;
  652. result = AudioObjectGetPropertyDataSize( id, &property, 0, NULL, &dataSize );
  653. if ( result != noErr || dataSize == 0 ) {
  654. errorStream_ << "RtApiCore::getDeviceInfo: system error (" << getErrorCode( result ) << ") getting output stream configuration info for device (" << device << ").";
  655. errorText_ = errorStream_.str();
  656. error( RtAudioError::WARNING );
  657. return info;
  658. }
  659. // Allocate the AudioBufferList.
  660. bufferList = (AudioBufferList *) malloc( dataSize );
  661. if ( bufferList == NULL ) {
  662. errorText_ = "RtApiCore::getDeviceInfo: memory error allocating output AudioBufferList.";
  663. error( RtAudioError::WARNING );
  664. return info;
  665. }
  666. result = AudioObjectGetPropertyData( id, &property, 0, NULL, &dataSize, bufferList );
  667. if ( result != noErr || dataSize == 0 ) {
  668. free( bufferList );
  669. errorStream_ << "RtApiCore::getDeviceInfo: system error (" << getErrorCode( result ) << ") getting output stream configuration for device (" << device << ").";
  670. errorText_ = errorStream_.str();
  671. error( RtAudioError::WARNING );
  672. return info;
  673. }
  674. // Get output channel information.
  675. unsigned int i, nStreams = bufferList->mNumberBuffers;
  676. for ( i=0; i<nStreams; i++ )
  677. info.outputChannels += bufferList->mBuffers[i].mNumberChannels;
  678. free( bufferList );
  679. // Get the input stream "configuration".
  680. property.mScope = kAudioDevicePropertyScopeInput;
  681. result = AudioObjectGetPropertyDataSize( id, &property, 0, NULL, &dataSize );
  682. if ( result != noErr || dataSize == 0 ) {
  683. errorStream_ << "RtApiCore::getDeviceInfo: system error (" << getErrorCode( result ) << ") getting input stream configuration info for device (" << device << ").";
  684. errorText_ = errorStream_.str();
  685. error( RtAudioError::WARNING );
  686. return info;
  687. }
  688. // Allocate the AudioBufferList.
  689. bufferList = (AudioBufferList *) malloc( dataSize );
  690. if ( bufferList == NULL ) {
  691. errorText_ = "RtApiCore::getDeviceInfo: memory error allocating input AudioBufferList.";
  692. error( RtAudioError::WARNING );
  693. return info;
  694. }
  695. result = AudioObjectGetPropertyData( id, &property, 0, NULL, &dataSize, bufferList );
  696. if (result != noErr || dataSize == 0) {
  697. free( bufferList );
  698. errorStream_ << "RtApiCore::getDeviceInfo: system error (" << getErrorCode( result ) << ") getting input stream configuration for device (" << device << ").";
  699. errorText_ = errorStream_.str();
  700. error( RtAudioError::WARNING );
  701. return info;
  702. }
  703. // Get input channel information.
  704. nStreams = bufferList->mNumberBuffers;
  705. for ( i=0; i<nStreams; i++ )
  706. info.inputChannels += bufferList->mBuffers[i].mNumberChannels;
  707. free( bufferList );
  708. // If device opens for both playback and capture, we determine the channels.
  709. if ( info.outputChannels > 0 && info.inputChannels > 0 )
  710. info.duplexChannels = (info.outputChannels > info.inputChannels) ? info.inputChannels : info.outputChannels;
  711. // Probe the device sample rates.
  712. bool isInput = false;
  713. if ( info.outputChannels == 0 ) isInput = true;
  714. // Determine the supported sample rates.
  715. property.mSelector = kAudioDevicePropertyAvailableNominalSampleRates;
  716. if ( isInput == false ) property.mScope = kAudioDevicePropertyScopeOutput;
  717. result = AudioObjectGetPropertyDataSize( id, &property, 0, NULL, &dataSize );
  718. if ( result != kAudioHardwareNoError || dataSize == 0 ) {
  719. errorStream_ << "RtApiCore::getDeviceInfo: system error (" << getErrorCode( result ) << ") getting sample rate info.";
  720. errorText_ = errorStream_.str();
  721. error( RtAudioError::WARNING );
  722. return info;
  723. }
  724. UInt32 nRanges = dataSize / sizeof( AudioValueRange );
  725. AudioValueRange rangeList[ nRanges ];
  726. result = AudioObjectGetPropertyData( id, &property, 0, NULL, &dataSize, &rangeList );
  727. if ( result != kAudioHardwareNoError ) {
  728. errorStream_ << "RtApiCore::getDeviceInfo: system error (" << getErrorCode( result ) << ") getting sample rates.";
  729. errorText_ = errorStream_.str();
  730. error( RtAudioError::WARNING );
  731. return info;
  732. }
  733. // The sample rate reporting mechanism is a bit of a mystery. It
  734. // seems that it can either return individual rates or a range of
  735. // rates. I assume that if the min / max range values are the same,
  736. // then that represents a single supported rate and if the min / max
  737. // range values are different, the device supports an arbitrary
  738. // range of values (though there might be multiple ranges, so we'll
  739. // use the most conservative range).
  740. Float64 minimumRate = 1.0, maximumRate = 10000000000.0;
  741. bool haveValueRange = false;
  742. info.sampleRates.clear();
  743. for ( UInt32 i=0; i<nRanges; i++ ) {
  744. if ( rangeList[i].mMinimum == rangeList[i].mMaximum ) {
  745. unsigned int tmpSr = (unsigned int) rangeList[i].mMinimum;
  746. info.sampleRates.push_back( tmpSr );
  747. if ( !info.preferredSampleRate || ( tmpSr <= 48000 && tmpSr > info.preferredSampleRate ) )
  748. info.preferredSampleRate = tmpSr;
  749. } else {
  750. haveValueRange = true;
  751. if ( rangeList[i].mMinimum > minimumRate ) minimumRate = rangeList[i].mMinimum;
  752. if ( rangeList[i].mMaximum < maximumRate ) maximumRate = rangeList[i].mMaximum;
  753. }
  754. }
  755. if ( haveValueRange ) {
  756. for ( unsigned int k=0; k<MAX_SAMPLE_RATES; k++ ) {
  757. if ( SAMPLE_RATES[k] >= (unsigned int) minimumRate && SAMPLE_RATES[k] <= (unsigned int) maximumRate ) {
  758. info.sampleRates.push_back( SAMPLE_RATES[k] );
  759. if ( !info.preferredSampleRate || ( SAMPLE_RATES[k] <= 48000 && SAMPLE_RATES[k] > info.preferredSampleRate ) )
  760. info.preferredSampleRate = SAMPLE_RATES[k];
  761. }
  762. }
  763. }
  764. // Sort and remove any redundant values
  765. std::sort( info.sampleRates.begin(), info.sampleRates.end() );
  766. info.sampleRates.erase( unique( info.sampleRates.begin(), info.sampleRates.end() ), info.sampleRates.end() );
  767. if ( info.sampleRates.size() == 0 ) {
  768. errorStream_ << "RtApiCore::probeDeviceInfo: No supported sample rates found for device (" << device << ").";
  769. errorText_ = errorStream_.str();
  770. error( RtAudioError::WARNING );
  771. return info;
  772. }
  773. // CoreAudio always uses 32-bit floating point data for PCM streams.
  774. // Thus, any other "physical" formats supported by the device are of
  775. // no interest to the client.
  776. info.nativeFormats = RTAUDIO_FLOAT32;
  777. if ( info.outputChannels > 0 )
  778. if ( getDefaultOutputDevice() == device ) info.isDefaultOutput = true;
  779. if ( info.inputChannels > 0 )
  780. if ( getDefaultInputDevice() == device ) info.isDefaultInput = true;
  781. info.probed = true;
  782. return info;
  783. }
  784. static OSStatus callbackHandler( AudioDeviceID inDevice,
  785. const AudioTimeStamp* /*inNow*/,
  786. const AudioBufferList* inInputData,
  787. const AudioTimeStamp* /*inInputTime*/,
  788. AudioBufferList* outOutputData,
  789. const AudioTimeStamp* /*inOutputTime*/,
  790. void* infoPointer )
  791. {
  792. CallbackInfo *info = (CallbackInfo *) infoPointer;
  793. RtApiCore *object = (RtApiCore *) info->object;
  794. if ( object->callbackEvent( inDevice, inInputData, outOutputData ) == false )
  795. return kAudioHardwareUnspecifiedError;
  796. else
  797. return kAudioHardwareNoError;
  798. }
  799. static OSStatus xrunListener( AudioObjectID /*inDevice*/,
  800. UInt32 nAddresses,
  801. const AudioObjectPropertyAddress properties[],
  802. void* handlePointer )
  803. {
  804. CoreHandle *handle = (CoreHandle *) handlePointer;
  805. for ( UInt32 i=0; i<nAddresses; i++ ) {
  806. if ( properties[i].mSelector == kAudioDeviceProcessorOverload ) {
  807. if ( properties[i].mScope == kAudioDevicePropertyScopeInput )
  808. handle->xrun[1] = true;
  809. else
  810. handle->xrun[0] = true;
  811. }
  812. }
  813. return kAudioHardwareNoError;
  814. }
  815. static OSStatus rateListener( AudioObjectID inDevice,
  816. UInt32 /*nAddresses*/,
  817. const AudioObjectPropertyAddress /*properties*/[],
  818. void* ratePointer )
  819. {
  820. Float64 *rate = (Float64 *) ratePointer;
  821. UInt32 dataSize = sizeof( Float64 );
  822. AudioObjectPropertyAddress property = { kAudioDevicePropertyNominalSampleRate,
  823. kAudioObjectPropertyScopeGlobal,
  824. kAudioObjectPropertyElementMaster };
  825. AudioObjectGetPropertyData( inDevice, &property, 0, NULL, &dataSize, rate );
  826. return kAudioHardwareNoError;
  827. }
  828. bool RtApiCore :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels,
  829. unsigned int firstChannel, unsigned int sampleRate,
  830. RtAudioFormat format, unsigned int *bufferSize,
  831. RtAudio::StreamOptions *options )
  832. {
  833. // Get device ID
  834. unsigned int nDevices = getDeviceCount();
  835. if ( nDevices == 0 ) {
  836. // This should not happen because a check is made before this function is called.
  837. errorText_ = "RtApiCore::probeDeviceOpen: no devices found!";
  838. return FAILURE;
  839. }
  840. if ( device >= nDevices ) {
  841. // This should not happen because a check is made before this function is called.
  842. errorText_ = "RtApiCore::probeDeviceOpen: device ID is invalid!";
  843. return FAILURE;
  844. }
  845. AudioDeviceID deviceList[ nDevices ];
  846. UInt32 dataSize = sizeof( AudioDeviceID ) * nDevices;
  847. AudioObjectPropertyAddress property = { kAudioHardwarePropertyDevices,
  848. kAudioObjectPropertyScopeGlobal,
  849. kAudioObjectPropertyElementMaster };
  850. OSStatus result = AudioObjectGetPropertyData( kAudioObjectSystemObject, &property,
  851. 0, NULL, &dataSize, (void *) &deviceList );
  852. if ( result != noErr ) {
  853. errorText_ = "RtApiCore::probeDeviceOpen: OS-X system error getting device IDs.";
  854. return FAILURE;
  855. }
  856. AudioDeviceID id = deviceList[ device ];
  857. // Setup for stream mode.
  858. bool isInput = false;
  859. if ( mode == INPUT ) {
  860. isInput = true;
  861. property.mScope = kAudioDevicePropertyScopeInput;
  862. }
  863. else
  864. property.mScope = kAudioDevicePropertyScopeOutput;
  865. // Get the stream "configuration".
  866. AudioBufferList *bufferList = nil;
  867. dataSize = 0;
  868. property.mSelector = kAudioDevicePropertyStreamConfiguration;
  869. result = AudioObjectGetPropertyDataSize( id, &property, 0, NULL, &dataSize );
  870. if ( result != noErr || dataSize == 0 ) {
  871. errorStream_ << "RtApiCore::probeDeviceOpen: system error (" << getErrorCode( result ) << ") getting stream configuration info for device (" << device << ").";
  872. errorText_ = errorStream_.str();
  873. return FAILURE;
  874. }
  875. // Allocate the AudioBufferList.
  876. bufferList = (AudioBufferList *) malloc( dataSize );
  877. if ( bufferList == NULL ) {
  878. errorText_ = "RtApiCore::probeDeviceOpen: memory error allocating AudioBufferList.";
  879. return FAILURE;
  880. }
  881. result = AudioObjectGetPropertyData( id, &property, 0, NULL, &dataSize, bufferList );
  882. if (result != noErr || dataSize == 0) {
  883. free( bufferList );
  884. errorStream_ << "RtApiCore::probeDeviceOpen: system error (" << getErrorCode( result ) << ") getting stream configuration for device (" << device << ").";
  885. errorText_ = errorStream_.str();
  886. return FAILURE;
  887. }
  888. // Search for one or more streams that contain the desired number of
  889. // channels. CoreAudio devices can have an arbitrary number of
  890. // streams and each stream can have an arbitrary number of channels.
  891. // For each stream, a single buffer of interleaved samples is
  892. // provided. RtAudio prefers the use of one stream of interleaved
  893. // data or multiple consecutive single-channel streams. However, we
  894. // now support multiple consecutive multi-channel streams of
  895. // interleaved data as well.
  896. UInt32 iStream, offsetCounter = firstChannel;
  897. UInt32 nStreams = bufferList->mNumberBuffers;
  898. bool monoMode = false;
  899. bool foundStream = false;
  900. // First check that the device supports the requested number of
  901. // channels.
  902. UInt32 deviceChannels = 0;
  903. for ( iStream=0; iStream<nStreams; iStream++ )
  904. deviceChannels += bufferList->mBuffers[iStream].mNumberChannels;
  905. if ( deviceChannels < ( channels + firstChannel ) ) {
  906. free( bufferList );
  907. errorStream_ << "RtApiCore::probeDeviceOpen: the device (" << device << ") does not support the requested channel count.";
  908. errorText_ = errorStream_.str();
  909. return FAILURE;
  910. }
  911. // Look for a single stream meeting our needs.
  912. UInt32 firstStream, streamCount = 1, streamChannels = 0, channelOffset = 0;
  913. for ( iStream=0; iStream<nStreams; iStream++ ) {
  914. streamChannels = bufferList->mBuffers[iStream].mNumberChannels;
  915. if ( streamChannels >= channels + offsetCounter ) {
  916. firstStream = iStream;
  917. channelOffset = offsetCounter;
  918. foundStream = true;
  919. break;
  920. }
  921. if ( streamChannels > offsetCounter ) break;
  922. offsetCounter -= streamChannels;
  923. }
  924. // If we didn't find a single stream above, then we should be able
  925. // to meet the channel specification with multiple streams.
  926. if ( foundStream == false ) {
  927. monoMode = true;
  928. offsetCounter = firstChannel;
  929. for ( iStream=0; iStream<nStreams; iStream++ ) {
  930. streamChannels = bufferList->mBuffers[iStream].mNumberChannels;
  931. if ( streamChannels > offsetCounter ) break;
  932. offsetCounter -= streamChannels;
  933. }
  934. firstStream = iStream;
  935. channelOffset = offsetCounter;
  936. Int32 channelCounter = channels + offsetCounter - streamChannels;
  937. if ( streamChannels > 1 ) monoMode = false;
  938. while ( channelCounter > 0 ) {
  939. streamChannels = bufferList->mBuffers[++iStream].mNumberChannels;
  940. if ( streamChannels > 1 ) monoMode = false;
  941. channelCounter -= streamChannels;
  942. streamCount++;
  943. }
  944. }
  945. free( bufferList );
  946. // Determine the buffer size.
  947. AudioValueRange bufferRange;
  948. dataSize = sizeof( AudioValueRange );
  949. property.mSelector = kAudioDevicePropertyBufferFrameSizeRange;
  950. result = AudioObjectGetPropertyData( id, &property, 0, NULL, &dataSize, &bufferRange );
  951. if ( result != noErr ) {
  952. errorStream_ << "RtApiCore::probeDeviceOpen: system error (" << getErrorCode( result ) << ") getting buffer size range for device (" << device << ").";
  953. errorText_ = errorStream_.str();
  954. return FAILURE;
  955. }
  956. if ( bufferRange.mMinimum > *bufferSize ) *bufferSize = (unsigned long) bufferRange.mMinimum;
  957. else if ( bufferRange.mMaximum < *bufferSize ) *bufferSize = (unsigned long) bufferRange.mMaximum;
  958. if ( options && options->flags & RTAUDIO_MINIMIZE_LATENCY ) *bufferSize = (unsigned long) bufferRange.mMinimum;
  959. // Set the buffer size. For multiple streams, I'm assuming we only
  960. // need to make this setting for the master channel.
  961. UInt32 theSize = (UInt32) *bufferSize;
  962. dataSize = sizeof( UInt32 );
  963. property.mSelector = kAudioDevicePropertyBufferFrameSize;
  964. result = AudioObjectSetPropertyData( id, &property, 0, NULL, dataSize, &theSize );
  965. if ( result != noErr ) {
  966. errorStream_ << "RtApiCore::probeDeviceOpen: system error (" << getErrorCode( result ) << ") setting the buffer size for device (" << device << ").";
  967. errorText_ = errorStream_.str();
  968. return FAILURE;
  969. }
  970. // If attempting to setup a duplex stream, the bufferSize parameter
  971. // MUST be the same in both directions!
  972. *bufferSize = theSize;
  973. if ( stream_.mode == OUTPUT && mode == INPUT && *bufferSize != stream_.bufferSize ) {
  974. errorStream_ << "RtApiCore::probeDeviceOpen: system error setting buffer size for duplex stream on device (" << device << ").";
  975. errorText_ = errorStream_.str();
  976. return FAILURE;
  977. }
  978. stream_.bufferSize = *bufferSize;
  979. stream_.nBuffers = 1;
  980. // Try to set "hog" mode ... it's not clear to me this is working.
  981. if ( options && options->flags & RTAUDIO_HOG_DEVICE ) {
  982. pid_t hog_pid;
  983. dataSize = sizeof( hog_pid );
  984. property.mSelector = kAudioDevicePropertyHogMode;
  985. result = AudioObjectGetPropertyData( id, &property, 0, NULL, &dataSize, &hog_pid );
  986. if ( result != noErr ) {
  987. errorStream_ << "RtApiCore::probeDeviceOpen: system error (" << getErrorCode( result ) << ") getting 'hog' state!";
  988. errorText_ = errorStream_.str();
  989. return FAILURE;
  990. }
  991. if ( hog_pid != getpid() ) {
  992. hog_pid = getpid();
  993. result = AudioObjectSetPropertyData( id, &property, 0, NULL, dataSize, &hog_pid );
  994. if ( result != noErr ) {
  995. errorStream_ << "RtApiCore::probeDeviceOpen: system error (" << getErrorCode( result ) << ") setting 'hog' state!";
  996. errorText_ = errorStream_.str();
  997. return FAILURE;
  998. }
  999. }
  1000. }
  1001. // Check and if necessary, change the sample rate for the device.
  1002. Float64 nominalRate;
  1003. dataSize = sizeof( Float64 );
  1004. property.mSelector = kAudioDevicePropertyNominalSampleRate;
  1005. result = AudioObjectGetPropertyData( id, &property, 0, NULL, &dataSize, &nominalRate );
  1006. if ( result != noErr ) {
  1007. errorStream_ << "RtApiCore::probeDeviceOpen: system error (" << getErrorCode( result ) << ") getting current sample rate.";
  1008. errorText_ = errorStream_.str();
  1009. return FAILURE;
  1010. }
  1011. // Only change the sample rate if off by more than 1 Hz.
  1012. if ( fabs( nominalRate - (double)sampleRate ) > 1.0 ) {
  1013. // Set a property listener for the sample rate change
  1014. Float64 reportedRate = 0.0;
  1015. AudioObjectPropertyAddress tmp = { kAudioDevicePropertyNominalSampleRate, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster };
  1016. result = AudioObjectAddPropertyListener( id, &tmp, rateListener, (void *) &reportedRate );
  1017. if ( result != noErr ) {
  1018. errorStream_ << "RtApiCore::probeDeviceOpen: system error (" << getErrorCode( result ) << ") setting sample rate property listener for device (" << device << ").";
  1019. errorText_ = errorStream_.str();
  1020. return FAILURE;
  1021. }
  1022. nominalRate = (Float64) sampleRate;
  1023. result = AudioObjectSetPropertyData( id, &property, 0, NULL, dataSize, &nominalRate );
  1024. if ( result != noErr ) {
  1025. AudioObjectRemovePropertyListener( id, &tmp, rateListener, (void *) &reportedRate );
  1026. errorStream_ << "RtApiCore::probeDeviceOpen: system error (" << getErrorCode( result ) << ") setting sample rate for device (" << device << ").";
  1027. errorText_ = errorStream_.str();
  1028. return FAILURE;
  1029. }
  1030. // Now wait until the reported nominal rate is what we just set.
  1031. UInt32 microCounter = 0;
  1032. while ( reportedRate != nominalRate ) {
  1033. microCounter += 5000;
  1034. if ( microCounter > 5000000 ) break;
  1035. usleep( 5000 );
  1036. }
  1037. // Remove the property listener.
  1038. AudioObjectRemovePropertyListener( id, &tmp, rateListener, (void *) &reportedRate );
  1039. if ( microCounter > 5000000 ) {
  1040. errorStream_ << "RtApiCore::probeDeviceOpen: timeout waiting for sample rate update for device (" << device << ").";
  1041. errorText_ = errorStream_.str();
  1042. return FAILURE;
  1043. }
  1044. }
  1045. // Now set the stream format for all streams. Also, check the
  1046. // physical format of the device and change that if necessary.
  1047. AudioStreamBasicDescription description;
  1048. dataSize = sizeof( AudioStreamBasicDescription );
  1049. property.mSelector = kAudioStreamPropertyVirtualFormat;
  1050. result = AudioObjectGetPropertyData( id, &property, 0, NULL, &dataSize, &description );
  1051. if ( result != noErr ) {
  1052. errorStream_ << "RtApiCore::probeDeviceOpen: system error (" << getErrorCode( result ) << ") getting stream format for device (" << device << ").";
  1053. errorText_ = errorStream_.str();
  1054. return FAILURE;
  1055. }
  1056. // Set the sample rate and data format id. However, only make the
  1057. // change if the sample rate is not within 1.0 of the desired
  1058. // rate and the format is not linear pcm.
  1059. bool updateFormat = false;
  1060. if ( fabs( description.mSampleRate - (Float64)sampleRate ) > 1.0 ) {
  1061. description.mSampleRate = (Float64) sampleRate;
  1062. updateFormat = true;
  1063. }
  1064. if ( description.mFormatID != kAudioFormatLinearPCM ) {
  1065. description.mFormatID = kAudioFormatLinearPCM;
  1066. updateFormat = true;
  1067. }
  1068. if ( updateFormat ) {
  1069. result = AudioObjectSetPropertyData( id, &property, 0, NULL, dataSize, &description );
  1070. if ( result != noErr ) {
  1071. errorStream_ << "RtApiCore::probeDeviceOpen: system error (" << getErrorCode( result ) << ") setting sample rate or data format for device (" << device << ").";
  1072. errorText_ = errorStream_.str();
  1073. return FAILURE;
  1074. }
  1075. }
  1076. // Now check the physical format.
  1077. property.mSelector = kAudioStreamPropertyPhysicalFormat;
  1078. result = AudioObjectGetPropertyData( id, &property, 0, NULL, &dataSize, &description );
  1079. if ( result != noErr ) {
  1080. errorStream_ << "RtApiCore::probeDeviceOpen: system error (" << getErrorCode( result ) << ") getting stream physical format for device (" << device << ").";
  1081. errorText_ = errorStream_.str();
  1082. return FAILURE;
  1083. }
  1084. //std::cout << "Current physical stream format:" << std::endl;
  1085. //std::cout << " mBitsPerChan = " << description.mBitsPerChannel << std::endl;
  1086. //std::cout << " aligned high = " << (description.mFormatFlags & kAudioFormatFlagIsAlignedHigh) << ", isPacked = " << (description.mFormatFlags & kAudioFormatFlagIsPacked) << std::endl;
  1087. //std::cout << " bytesPerFrame = " << description.mBytesPerFrame << std::endl;
  1088. //std::cout << " sample rate = " << description.mSampleRate << std::endl;
  1089. if ( description.mFormatID != kAudioFormatLinearPCM || description.mBitsPerChannel < 16 ) {
  1090. description.mFormatID = kAudioFormatLinearPCM;
  1091. //description.mSampleRate = (Float64) sampleRate;
  1092. AudioStreamBasicDescription testDescription = description;
  1093. UInt32 formatFlags;
  1094. // We'll try higher bit rates first and then work our way down.
  1095. std::vector< std::pair<UInt32, UInt32> > physicalFormats;
  1096. formatFlags = (description.mFormatFlags | kLinearPCMFormatFlagIsFloat) & ~kLinearPCMFormatFlagIsSignedInteger;
  1097. physicalFormats.push_back( std::pair<Float32, UInt32>( 32, formatFlags ) );
  1098. formatFlags = (description.mFormatFlags | kLinearPCMFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked) & ~kLinearPCMFormatFlagIsFloat;
  1099. physicalFormats.push_back( std::pair<Float32, UInt32>( 32, formatFlags ) );
  1100. physicalFormats.push_back( std::pair<Float32, UInt32>( 24, formatFlags ) ); // 24-bit packed
  1101. formatFlags &= ~( kAudioFormatFlagIsPacked | kAudioFormatFlagIsAlignedHigh );
  1102. physicalFormats.push_back( std::pair<Float32, UInt32>( 24.2, formatFlags ) ); // 24-bit in 4 bytes, aligned low
  1103. formatFlags |= kAudioFormatFlagIsAlignedHigh;
  1104. physicalFormats.push_back( std::pair<Float32, UInt32>( 24.4, formatFlags ) ); // 24-bit in 4 bytes, aligned high
  1105. formatFlags = (description.mFormatFlags | kLinearPCMFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked) & ~kLinearPCMFormatFlagIsFloat;
  1106. physicalFormats.push_back( std::pair<Float32, UInt32>( 16, formatFlags ) );
  1107. physicalFormats.push_back( std::pair<Float32, UInt32>( 8, formatFlags ) );
  1108. bool setPhysicalFormat = false;
  1109. for( unsigned int i=0; i<physicalFormats.size(); i++ ) {
  1110. testDescription = description;
  1111. testDescription.mBitsPerChannel = (UInt32) physicalFormats[i].first;
  1112. testDescription.mFormatFlags = physicalFormats[i].second;
  1113. if ( (24 == (UInt32)physicalFormats[i].first) && ~( physicalFormats[i].second & kAudioFormatFlagIsPacked ) )
  1114. testDescription.mBytesPerFrame = 4 * testDescription.mChannelsPerFrame;
  1115. else
  1116. testDescription.mBytesPerFrame = testDescription.mBitsPerChannel/8 * testDescription.mChannelsPerFrame;
  1117. testDescription.mBytesPerPacket = testDescription.mBytesPerFrame * testDescription.mFramesPerPacket;
  1118. result = AudioObjectSetPropertyData( id, &property, 0, NULL, dataSize, &testDescription );
  1119. if ( result == noErr ) {
  1120. setPhysicalFormat = true;
  1121. //std::cout << "Updated physical stream format:" << std::endl;
  1122. //std::cout << " mBitsPerChan = " << testDescription.mBitsPerChannel << std::endl;
  1123. //std::cout << " aligned high = " << (testDescription.mFormatFlags & kAudioFormatFlagIsAlignedHigh) << ", isPacked = " << (testDescription.mFormatFlags & kAudioFormatFlagIsPacked) << std::endl;
  1124. //std::cout << " bytesPerFrame = " << testDescription.mBytesPerFrame << std::endl;
  1125. //std::cout << " sample rate = " << testDescription.mSampleRate << std::endl;
  1126. break;
  1127. }
  1128. }
  1129. if ( !setPhysicalFormat ) {
  1130. errorStream_ << "RtApiCore::probeDeviceOpen: system error (" << getErrorCode( result ) << ") setting physical data format for device (" << device << ").";
  1131. errorText_ = errorStream_.str();
  1132. return FAILURE;
  1133. }
  1134. } // done setting virtual/physical formats.
  1135. // Get the stream / device latency.
  1136. UInt32 latency;
  1137. dataSize = sizeof( UInt32 );
  1138. property.mSelector = kAudioDevicePropertyLatency;
  1139. if ( AudioObjectHasProperty( id, &property ) == true ) {
  1140. result = AudioObjectGetPropertyData( id, &property, 0, NULL, &dataSize, &latency );
  1141. if ( result == kAudioHardwareNoError ) stream_.latency[ mode ] = latency;
  1142. else {
  1143. errorStream_ << "RtApiCore::probeDeviceOpen: system error (" << getErrorCode( result ) << ") getting device latency for device (" << device << ").";
  1144. errorText_ = errorStream_.str();
  1145. error( RtAudioError::WARNING );
  1146. }
  1147. }
  1148. // Byte-swapping: According to AudioHardware.h, the stream data will
  1149. // always be presented in native-endian format, so we should never
  1150. // need to byte swap.
  1151. stream_.doByteSwap[mode] = false;
  1152. // From the CoreAudio documentation, PCM data must be supplied as
  1153. // 32-bit floats.
  1154. stream_.userFormat = format;
  1155. stream_.deviceFormat[mode] = RTAUDIO_FLOAT32;
  1156. if ( streamCount == 1 )
  1157. stream_.nDeviceChannels[mode] = description.mChannelsPerFrame;
  1158. else // multiple streams
  1159. stream_.nDeviceChannels[mode] = channels;
  1160. stream_.nUserChannels[mode] = channels;
  1161. stream_.channelOffset[mode] = channelOffset; // offset within a CoreAudio stream
  1162. if ( options && options->flags & RTAUDIO_NONINTERLEAVED ) stream_.userInterleaved = false;
  1163. else stream_.userInterleaved = true;
  1164. stream_.deviceInterleaved[mode] = true;
  1165. if ( monoMode == true ) stream_.deviceInterleaved[mode] = false;
  1166. // Set flags for buffer conversion.
  1167. stream_.doConvertBuffer[mode] = false;
  1168. if ( stream_.userFormat != stream_.deviceFormat[mode] )
  1169. stream_.doConvertBuffer[mode] = true;
  1170. if ( stream_.nUserChannels[mode] < stream_.nDeviceChannels[mode] )
  1171. stream_.doConvertBuffer[mode] = true;
  1172. if ( streamCount == 1 ) {
  1173. if ( stream_.nUserChannels[mode] > 1 &&
  1174. stream_.userInterleaved != stream_.deviceInterleaved[mode] )
  1175. stream_.doConvertBuffer[mode] = true;
  1176. }
  1177. else if ( monoMode && stream_.userInterleaved )
  1178. stream_.doConvertBuffer[mode] = true;
  1179. // Allocate our CoreHandle structure for the stream.
  1180. CoreHandle *handle = 0;
  1181. if ( stream_.apiHandle == 0 ) {
  1182. try {
  1183. handle = new CoreHandle;
  1184. }
  1185. catch ( std::bad_alloc& ) {
  1186. errorText_ = "RtApiCore::probeDeviceOpen: error allocating CoreHandle memory.";
  1187. goto error;
  1188. }
  1189. if ( pthread_cond_init( &handle->condition, NULL ) ) {
  1190. errorText_ = "RtApiCore::probeDeviceOpen: error initializing pthread condition variable.";
  1191. goto error;
  1192. }
  1193. stream_.apiHandle = (void *) handle;
  1194. }
  1195. else
  1196. handle = (CoreHandle *) stream_.apiHandle;
  1197. handle->iStream[mode] = firstStream;
  1198. handle->nStreams[mode] = streamCount;
  1199. handle->id[mode] = id;
  1200. // Allocate necessary internal buffers.
  1201. unsigned long bufferBytes;
  1202. bufferBytes = stream_.nUserChannels[mode] * *bufferSize * formatBytes( stream_.userFormat );
  1203. // stream_.userBuffer[mode] = (char *) calloc( bufferBytes, 1 );
  1204. stream_.userBuffer[mode] = (char *) malloc( bufferBytes * sizeof(char) );
  1205. memset( stream_.userBuffer[mode], 0, bufferBytes * sizeof(char) );
  1206. if ( stream_.userBuffer[mode] == NULL ) {
  1207. errorText_ = "RtApiCore::probeDeviceOpen: error allocating user buffer memory.";
  1208. goto error;
  1209. }
  1210. // If possible, we will make use of the CoreAudio stream buffers as
  1211. // "device buffers". However, we can't do this if using multiple
  1212. // streams.
  1213. if ( stream_.doConvertBuffer[mode] && handle->nStreams[mode] > 1 ) {
  1214. bool makeBuffer = true;
  1215. bufferBytes = stream_.nDeviceChannels[mode] * formatBytes( stream_.deviceFormat[mode] );
  1216. if ( mode == INPUT ) {
  1217. if ( stream_.mode == OUTPUT && stream_.deviceBuffer ) {
  1218. unsigned long bytesOut = stream_.nDeviceChannels[0] * formatBytes( stream_.deviceFormat[0] );
  1219. if ( bufferBytes <= bytesOut ) makeBuffer = false;
  1220. }
  1221. }
  1222. if ( makeBuffer ) {
  1223. bufferBytes *= *bufferSize;
  1224. if ( stream_.deviceBuffer ) free( stream_.deviceBuffer );
  1225. stream_.deviceBuffer = (char *) calloc( bufferBytes, 1 );
  1226. if ( stream_.deviceBuffer == NULL ) {
  1227. errorText_ = "RtApiCore::probeDeviceOpen: error allocating device buffer memory.";
  1228. goto error;
  1229. }
  1230. }
  1231. }
  1232. stream_.sampleRate = sampleRate;
  1233. stream_.device[mode] = device;
  1234. stream_.state = STREAM_STOPPED;
  1235. stream_.callbackInfo.object = (void *) this;
  1236. // Setup the buffer conversion information structure.
  1237. if ( stream_.doConvertBuffer[mode] ) {
  1238. if ( streamCount > 1 ) setConvertInfo( mode, 0 );
  1239. else setConvertInfo( mode, channelOffset );
  1240. }
  1241. if ( mode == INPUT && stream_.mode == OUTPUT && stream_.device[0] == device )
  1242. // Only one callback procedure per device.
  1243. stream_.mode = DUPLEX;
  1244. else {
  1245. #if defined( MAC_OS_X_VERSION_10_5 ) && ( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 )
  1246. result = AudioDeviceCreateIOProcID( id, callbackHandler, (void *) &stream_.callbackInfo, &handle->procId[mode] );
  1247. #else
  1248. // deprecated in favor of AudioDeviceCreateIOProcID()
  1249. result = AudioDeviceAddIOProc( id, callbackHandler, (void *) &stream_.callbackInfo );
  1250. #endif
  1251. if ( result != noErr ) {
  1252. errorStream_ << "RtApiCore::probeDeviceOpen: system error setting callback for device (" << device << ").";
  1253. errorText_ = errorStream_.str();
  1254. goto error;
  1255. }
  1256. if ( stream_.mode == OUTPUT && mode == INPUT )
  1257. stream_.mode = DUPLEX;
  1258. else
  1259. stream_.mode = mode;
  1260. }
  1261. // Setup the device property listener for over/underload.
  1262. property.mSelector = kAudioDeviceProcessorOverload;
  1263. property.mScope = kAudioObjectPropertyScopeGlobal;
  1264. result = AudioObjectAddPropertyListener( id, &property, xrunListener, (void *) handle );
  1265. return SUCCESS;
  1266. error:
  1267. if ( handle ) {
  1268. pthread_cond_destroy( &handle->condition );
  1269. delete handle;
  1270. stream_.apiHandle = 0;
  1271. }
  1272. for ( int i=0; i<2; i++ ) {
  1273. if ( stream_.userBuffer[i] ) {
  1274. free( stream_.userBuffer[i] );
  1275. stream_.userBuffer[i] = 0;
  1276. }
  1277. }
  1278. if ( stream_.deviceBuffer ) {
  1279. free( stream_.deviceBuffer );
  1280. stream_.deviceBuffer = 0;
  1281. }
  1282. stream_.state = STREAM_CLOSED;
  1283. return FAILURE;
  1284. }
  1285. void RtApiCore :: closeStream( void )
  1286. {
  1287. if ( stream_.state == STREAM_CLOSED ) {
  1288. errorText_ = "RtApiCore::closeStream(): no open stream to close!";
  1289. error( RtAudioError::WARNING );
  1290. return;
  1291. }
  1292. CoreHandle *handle = (CoreHandle *) stream_.apiHandle;
  1293. if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) {
  1294. if (handle) {
  1295. AudioObjectPropertyAddress property = { kAudioHardwarePropertyDevices,
  1296. kAudioObjectPropertyScopeGlobal,
  1297. kAudioObjectPropertyElementMaster };
  1298. property.mSelector = kAudioDeviceProcessorOverload;
  1299. property.mScope = kAudioObjectPropertyScopeGlobal;
  1300. if (AudioObjectRemovePropertyListener( handle->id[0], &property, xrunListener, (void *) handle ) != noErr) {
  1301. errorText_ = "RtApiCore::closeStream(): error removing property listener!";
  1302. error( RtAudioError::WARNING );
  1303. }
  1304. #if defined( MAC_OS_X_VERSION_10_5 ) && ( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 )
  1305. if ( stream_.state == STREAM_RUNNING )
  1306. AudioDeviceStop( handle->id[0], handle->procId[0] );
  1307. AudioDeviceDestroyIOProcID( handle->id[0], handle->procId[0] );
  1308. #else // deprecated behaviour
  1309. if ( stream_.state == STREAM_RUNNING )
  1310. AudioDeviceStop( handle->id[0], callbackHandler );
  1311. AudioDeviceRemoveIOProc( handle->id[0], callbackHandler );
  1312. #endif
  1313. }
  1314. }
  1315. if ( stream_.mode == INPUT || ( stream_.mode == DUPLEX && stream_.device[0] != stream_.device[1] ) ) {
  1316. if (handle) {
  1317. AudioObjectPropertyAddress property = { kAudioHardwarePropertyDevices,
  1318. kAudioObjectPropertyScopeGlobal,
  1319. kAudioObjectPropertyElementMaster };
  1320. property.mSelector = kAudioDeviceProcessorOverload;
  1321. property.mScope = kAudioObjectPropertyScopeGlobal;
  1322. if (AudioObjectRemovePropertyListener( handle->id[1], &property, xrunListener, (void *) handle ) != noErr) {
  1323. errorText_ = "RtApiCore::closeStream(): error removing property listener!";
  1324. error( RtAudioError::WARNING );
  1325. }
  1326. #if defined( MAC_OS_X_VERSION_10_5 ) && ( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 )
  1327. if ( stream_.state == STREAM_RUNNING )
  1328. AudioDeviceStop( handle->id[1], handle->procId[1] );
  1329. AudioDeviceDestroyIOProcID( handle->id[1], handle->procId[1] );
  1330. #else // deprecated behaviour
  1331. if ( stream_.state == STREAM_RUNNING )
  1332. AudioDeviceStop( handle->id[1], callbackHandler );
  1333. AudioDeviceRemoveIOProc( handle->id[1], callbackHandler );
  1334. #endif
  1335. }
  1336. }
  1337. for ( int i=0; i<2; i++ ) {
  1338. if ( stream_.userBuffer[i] ) {
  1339. free( stream_.userBuffer[i] );
  1340. stream_.userBuffer[i] = 0;
  1341. }
  1342. }
  1343. if ( stream_.deviceBuffer ) {
  1344. free( stream_.deviceBuffer );
  1345. stream_.deviceBuffer = 0;
  1346. }
  1347. // Destroy pthread condition variable.
  1348. pthread_cond_destroy( &handle->condition );
  1349. delete handle;
  1350. stream_.apiHandle = 0;
  1351. stream_.mode = UNINITIALIZED;
  1352. stream_.state = STREAM_CLOSED;
  1353. }
  1354. void RtApiCore :: startStream( void )
  1355. {
  1356. verifyStream();
  1357. if ( stream_.state == STREAM_RUNNING ) {
  1358. errorText_ = "RtApiCore::startStream(): the stream is already running!";
  1359. error( RtAudioError::WARNING );
  1360. return;
  1361. }
  1362. #if defined( HAVE_GETTIMEOFDAY )
  1363. gettimeofday( &stream_.lastTickTimestamp, NULL );
  1364. #endif
  1365. OSStatus result = noErr;
  1366. CoreHandle *handle = (CoreHandle *) stream_.apiHandle;
  1367. if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) {
  1368. #if defined( MAC_OS_X_VERSION_10_5 ) && ( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 )
  1369. result = AudioDeviceStart( handle->id[0], handle->procId[0] );
  1370. #else // deprecated behaviour
  1371. result = AudioDeviceStart( handle->id[0], callbackHandler );
  1372. #endif
  1373. if ( result != noErr ) {
  1374. errorStream_ << "RtApiCore::startStream: system error (" << getErrorCode( result ) << ") starting callback procedure on device (" << stream_.device[0] << ").";
  1375. errorText_ = errorStream_.str();
  1376. goto unlock;
  1377. }
  1378. }
  1379. if ( stream_.mode == INPUT ||
  1380. ( stream_.mode == DUPLEX && stream_.device[0] != stream_.device[1] ) ) {
  1381. #if defined( MAC_OS_X_VERSION_10_5 ) && ( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 )
  1382. result = AudioDeviceStart( handle->id[1], handle->procId[1] );
  1383. #else // deprecated behaviour
  1384. result = AudioDeviceStart( handle->id[1], callbackHandler );
  1385. #endif
  1386. if ( result != noErr ) {
  1387. errorStream_ << "RtApiCore::startStream: system error starting input callback procedure on device (" << stream_.device[1] << ").";
  1388. errorText_ = errorStream_.str();
  1389. goto unlock;
  1390. }
  1391. }
  1392. handle->drainCounter = 0;
  1393. handle->internalDrain = false;
  1394. stream_.state = STREAM_RUNNING;
  1395. unlock:
  1396. if ( result == noErr ) return;
  1397. error( RtAudioError::SYSTEM_ERROR );
  1398. }
  1399. void RtApiCore :: stopStream( void )
  1400. {
  1401. verifyStream();
  1402. if ( stream_.state == STREAM_STOPPED ) {
  1403. errorText_ = "RtApiCore::stopStream(): the stream is already stopped!";
  1404. error( RtAudioError::WARNING );
  1405. return;
  1406. }
  1407. OSStatus result = noErr;
  1408. CoreHandle *handle = (CoreHandle *) stream_.apiHandle;
  1409. if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) {
  1410. if ( handle->drainCounter == 0 ) {
  1411. handle->drainCounter = 2;
  1412. pthread_cond_wait( &handle->condition, &stream_.mutex ); // block until signaled
  1413. }
  1414. #if defined( MAC_OS_X_VERSION_10_5 ) && ( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 )
  1415. result = AudioDeviceStop( handle->id[0], handle->procId[0] );
  1416. #else // deprecated behaviour
  1417. result = AudioDeviceStop( handle->id[0], callbackHandler );
  1418. #endif
  1419. if ( result != noErr ) {
  1420. errorStream_ << "RtApiCore::stopStream: system error (" << getErrorCode( result ) << ") stopping callback procedure on device (" << stream_.device[0] << ").";
  1421. errorText_ = errorStream_.str();
  1422. goto unlock;
  1423. }
  1424. }
  1425. if ( stream_.mode == INPUT || ( stream_.mode == DUPLEX && stream_.device[0] != stream_.device[1] ) ) {
  1426. #if defined( MAC_OS_X_VERSION_10_5 ) && ( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 )
  1427. result = AudioDeviceStop( handle->id[1], handle->procId[1] );
  1428. #else // deprecated behaviour
  1429. result = AudioDeviceStop( handle->id[1], callbackHandler );
  1430. #endif
  1431. if ( result != noErr ) {
  1432. errorStream_ << "RtApiCore::stopStream: system error (" << getErrorCode( result ) << ") stopping input callback procedure on device (" << stream_.device[1] << ").";
  1433. errorText_ = errorStream_.str();
  1434. goto unlock;
  1435. }
  1436. }
  1437. stream_.state = STREAM_STOPPED;
  1438. unlock:
  1439. if ( result == noErr ) return;
  1440. error( RtAudioError::SYSTEM_ERROR );
  1441. }
  1442. void RtApiCore :: abortStream( void )
  1443. {
  1444. verifyStream();
  1445. if ( stream_.state == STREAM_STOPPED ) {
  1446. errorText_ = "RtApiCore::abortStream(): the stream is already stopped!";
  1447. error( RtAudioError::WARNING );
  1448. return;
  1449. }
  1450. CoreHandle *handle = (CoreHandle *) stream_.apiHandle;
  1451. handle->drainCounter = 2;
  1452. stopStream();
  1453. }
  1454. // This function will be called by a spawned thread when the user
  1455. // callback function signals that the stream should be stopped or
  1456. // aborted. It is better to handle it this way because the
  1457. // callbackEvent() function probably should return before the AudioDeviceStop()
  1458. // function is called.
  1459. static void *coreStopStream( void *ptr )
  1460. {
  1461. CallbackInfo *info = (CallbackInfo *) ptr;
  1462. RtApiCore *object = (RtApiCore *) info->object;
  1463. object->stopStream();
  1464. pthread_exit( NULL );
  1465. }
  1466. bool RtApiCore :: callbackEvent( AudioDeviceID deviceId,
  1467. const AudioBufferList *inBufferList,
  1468. const AudioBufferList *outBufferList )
  1469. {
  1470. if ( stream_.state == STREAM_STOPPED || stream_.state == STREAM_STOPPING ) return SUCCESS;
  1471. if ( stream_.state == STREAM_CLOSED ) {
  1472. errorText_ = "RtApiCore::callbackEvent(): the stream is closed ... this shouldn't happen!";
  1473. error( RtAudioError::WARNING );
  1474. return FAILURE;
  1475. }
  1476. CallbackInfo *info = (CallbackInfo *) &stream_.callbackInfo;
  1477. CoreHandle *handle = (CoreHandle *) stream_.apiHandle;
  1478. // Check if we were draining the stream and signal is finished.
  1479. if ( handle->drainCounter > 3 ) {
  1480. ThreadHandle threadId;
  1481. stream_.state = STREAM_STOPPING;
  1482. if ( handle->internalDrain == true )
  1483. pthread_create( &threadId, NULL, coreStopStream, info );
  1484. else // external call to stopStream()
  1485. pthread_cond_signal( &handle->condition );
  1486. return SUCCESS;
  1487. }
  1488. AudioDeviceID outputDevice = handle->id[0];
  1489. // Invoke user callback to get fresh output data UNLESS we are
  1490. // draining stream or duplex mode AND the input/output devices are
  1491. // different AND this function is called for the input device.
  1492. if ( handle->drainCounter == 0 && ( stream_.mode != DUPLEX || deviceId == outputDevice ) ) {
  1493. RtAudioCallback callback = (RtAudioCallback) info->callback;
  1494. double streamTime = getStreamTime();
  1495. RtAudioStreamStatus status = 0;
  1496. if ( stream_.mode != INPUT && handle->xrun[0] == true ) {
  1497. status |= RTAUDIO_OUTPUT_UNDERFLOW;
  1498. handle->xrun[0] = false;
  1499. }
  1500. if ( stream_.mode != OUTPUT && handle->xrun[1] == true ) {
  1501. status |= RTAUDIO_INPUT_OVERFLOW;
  1502. handle->xrun[1] = false;
  1503. }
  1504. int cbReturnValue = callback( stream_.userBuffer[0], stream_.userBuffer[1],
  1505. stream_.bufferSize, streamTime, status, info->userData );
  1506. if ( cbReturnValue == 2 ) {
  1507. stream_.state = STREAM_STOPPING;
  1508. handle->drainCounter = 2;
  1509. abortStream();
  1510. return SUCCESS;
  1511. }
  1512. else if ( cbReturnValue == 1 ) {
  1513. handle->drainCounter = 1;
  1514. handle->internalDrain = true;
  1515. }
  1516. }
  1517. if ( stream_.mode == OUTPUT || ( stream_.mode == DUPLEX && deviceId == outputDevice ) ) {
  1518. if ( handle->drainCounter > 1 ) { // write zeros to the output stream
  1519. if ( handle->nStreams[0] == 1 ) {
  1520. memset( outBufferList->mBuffers[handle->iStream[0]].mData,
  1521. 0,
  1522. outBufferList->mBuffers[handle->iStream[0]].mDataByteSize );
  1523. }
  1524. else { // fill multiple streams with zeros
  1525. for ( unsigned int i=0; i<handle->nStreams[0]; i++ ) {
  1526. memset( outBufferList->mBuffers[handle->iStream[0]+i].mData,
  1527. 0,
  1528. outBufferList->mBuffers[handle->iStream[0]+i].mDataByteSize );
  1529. }
  1530. }
  1531. }
  1532. else if ( handle->nStreams[0] == 1 ) {
  1533. if ( stream_.doConvertBuffer[0] ) { // convert directly to CoreAudio stream buffer
  1534. convertBuffer( (char *) outBufferList->mBuffers[handle->iStream[0]].mData,
  1535. stream_.userBuffer[0], stream_.convertInfo[0] );
  1536. }
  1537. else { // copy from user buffer
  1538. memcpy( outBufferList->mBuffers[handle->iStream[0]].mData,
  1539. stream_.userBuffer[0],
  1540. outBufferList->mBuffers[handle->iStream[0]].mDataByteSize );
  1541. }
  1542. }
  1543. else { // fill multiple streams
  1544. Float32 *inBuffer = (Float32 *) stream_.userBuffer[0];
  1545. if ( stream_.doConvertBuffer[0] ) {
  1546. convertBuffer( stream_.deviceBuffer, stream_.userBuffer[0], stream_.convertInfo[0] );
  1547. inBuffer = (Float32 *) stream_.deviceBuffer;
  1548. }
  1549. if ( stream_.deviceInterleaved[0] == false ) { // mono mode
  1550. UInt32 bufferBytes = outBufferList->mBuffers[handle->iStream[0]].mDataByteSize;
  1551. for ( unsigned int i=0; i<stream_.nUserChannels[0]; i++ ) {
  1552. memcpy( outBufferList->mBuffers[handle->iStream[0]+i].mData,
  1553. (void *)&inBuffer[i*stream_.bufferSize], bufferBytes );
  1554. }
  1555. }
  1556. else { // fill multiple multi-channel streams with interleaved data
  1557. UInt32 streamChannels, channelsLeft, inJump, outJump, inOffset;
  1558. Float32 *out, *in;
  1559. bool inInterleaved = ( stream_.userInterleaved ) ? true : false;
  1560. UInt32 inChannels = stream_.nUserChannels[0];
  1561. if ( stream_.doConvertBuffer[0] ) {
  1562. inInterleaved = true; // device buffer will always be interleaved for nStreams > 1 and not mono mode
  1563. inChannels = stream_.nDeviceChannels[0];
  1564. }
  1565. if ( inInterleaved ) inOffset = 1;
  1566. else inOffset = stream_.bufferSize;
  1567. channelsLeft = inChannels;
  1568. for ( unsigned int i=0; i<handle->nStreams[0]; i++ ) {
  1569. in = inBuffer;
  1570. out = (Float32 *) outBufferList->mBuffers[handle->iStream[0]+i].mData;
  1571. streamChannels = outBufferList->mBuffers[handle->iStream[0]+i].mNumberChannels;
  1572. outJump = 0;
  1573. // Account for possible channel offset in first stream
  1574. if ( i == 0 && stream_.channelOffset[0] > 0 ) {
  1575. streamChannels -= stream_.channelOffset[0];
  1576. outJump = stream_.channelOffset[0];
  1577. out += outJump;
  1578. }
  1579. // Account for possible unfilled channels at end of the last stream
  1580. if ( streamChannels > channelsLeft ) {
  1581. outJump = streamChannels - channelsLeft;
  1582. streamChannels = channelsLeft;
  1583. }
  1584. // Determine input buffer offsets and skips
  1585. if ( inInterleaved ) {
  1586. inJump = inChannels;
  1587. in += inChannels - channelsLeft;
  1588. }
  1589. else {
  1590. inJump = 1;
  1591. in += (inChannels - channelsLeft) * inOffset;
  1592. }
  1593. for ( unsigned int i=0; i<stream_.bufferSize; i++ ) {
  1594. for ( unsigned int j=0; j<streamChannels; j++ ) {
  1595. *out++ = in[j*inOffset];
  1596. }
  1597. out += outJump;
  1598. in += inJump;
  1599. }
  1600. channelsLeft -= streamChannels;
  1601. }
  1602. }
  1603. }
  1604. }
  1605. // Don't bother draining input
  1606. if ( handle->drainCounter ) {
  1607. handle->drainCounter++;
  1608. goto unlock;
  1609. }
  1610. AudioDeviceID inputDevice;
  1611. inputDevice = handle->id[1];
  1612. if ( stream_.mode == INPUT || ( stream_.mode == DUPLEX && deviceId == inputDevice ) ) {
  1613. if ( handle->nStreams[1] == 1 ) {
  1614. if ( stream_.doConvertBuffer[1] ) { // convert directly from CoreAudio stream buffer
  1615. convertBuffer( stream_.userBuffer[1],
  1616. (char *) inBufferList->mBuffers[handle->iStream[1]].mData,
  1617. stream_.convertInfo[1] );
  1618. }
  1619. else { // copy to user buffer
  1620. memcpy( stream_.userBuffer[1],
  1621. inBufferList->mBuffers[handle->iStream[1]].mData,
  1622. inBufferList->mBuffers[handle->iStream[1]].mDataByteSize );
  1623. }
  1624. }
  1625. else { // read from multiple streams
  1626. Float32 *outBuffer = (Float32 *) stream_.userBuffer[1];
  1627. if ( stream_.doConvertBuffer[1] ) outBuffer = (Float32 *) stream_.deviceBuffer;
  1628. if ( stream_.deviceInterleaved[1] == false ) { // mono mode
  1629. UInt32 bufferBytes = inBufferList->mBuffers[handle->iStream[1]].mDataByteSize;
  1630. for ( unsigned int i=0; i<stream_.nUserChannels[1]; i++ ) {
  1631. memcpy( (void *)&outBuffer[i*stream_.bufferSize],
  1632. inBufferList->mBuffers[handle->iStream[1]+i].mData, bufferBytes );
  1633. }
  1634. }
  1635. else { // read from multiple multi-channel streams
  1636. UInt32 streamChannels, channelsLeft, inJump, outJump, outOffset;
  1637. Float32 *out, *in;
  1638. bool outInterleaved = ( stream_.userInterleaved ) ? true : false;
  1639. UInt32 outChannels = stream_.nUserChannels[1];
  1640. if ( stream_.doConvertBuffer[1] ) {
  1641. outInterleaved = true; // device buffer will always be interleaved for nStreams > 1 and not mono mode
  1642. outChannels = stream_.nDeviceChannels[1];
  1643. }
  1644. if ( outInterleaved ) outOffset = 1;
  1645. else outOffset = stream_.bufferSize;
  1646. channelsLeft = outChannels;
  1647. for ( unsigned int i=0; i<handle->nStreams[1]; i++ ) {
  1648. out = outBuffer;
  1649. in = (Float32 *) inBufferList->mBuffers[handle->iStream[1]+i].mData;
  1650. streamChannels = inBufferList->mBuffers[handle->iStream[1]+i].mNumberChannels;
  1651. inJump = 0;
  1652. // Account for possible channel offset in first stream
  1653. if ( i == 0 && stream_.channelOffset[1] > 0 ) {
  1654. streamChannels -= stream_.channelOffset[1];
  1655. inJump = stream_.channelOffset[1];
  1656. in += inJump;
  1657. }
  1658. // Account for possible unread channels at end of the last stream
  1659. if ( streamChannels > channelsLeft ) {
  1660. inJump = streamChannels - channelsLeft;
  1661. streamChannels = channelsLeft;
  1662. }
  1663. // Determine output buffer offsets and skips
  1664. if ( outInterleaved ) {
  1665. outJump = outChannels;
  1666. out += outChannels - channelsLeft;
  1667. }
  1668. else {
  1669. outJump = 1;
  1670. out += (outChannels - channelsLeft) * outOffset;
  1671. }
  1672. for ( unsigned int i=0; i<stream_.bufferSize; i++ ) {
  1673. for ( unsigned int j=0; j<streamChannels; j++ ) {
  1674. out[j*outOffset] = *in++;
  1675. }
  1676. out += outJump;
  1677. in += inJump;
  1678. }
  1679. channelsLeft -= streamChannels;
  1680. }
  1681. }
  1682. if ( stream_.doConvertBuffer[1] ) { // convert from our internal "device" buffer
  1683. convertBuffer( stream_.userBuffer[1],
  1684. stream_.deviceBuffer,
  1685. stream_.convertInfo[1] );
  1686. }
  1687. }
  1688. }
  1689. unlock:
  1690. //MUTEX_UNLOCK( &stream_.mutex );
  1691. // Make sure to only tick duplex stream time once if using two devices
  1692. if ( stream_.mode != DUPLEX || (stream_.mode == DUPLEX && handle->id[0] != handle->id[1] && deviceId == handle->id[0] ) )
  1693. RtApi::tickStreamTime();
  1694. return SUCCESS;
  1695. }
  1696. const char* RtApiCore :: getErrorCode( OSStatus code )
  1697. {
  1698. switch( code ) {
  1699. case kAudioHardwareNotRunningError:
  1700. return "kAudioHardwareNotRunningError";
  1701. case kAudioHardwareUnspecifiedError:
  1702. return "kAudioHardwareUnspecifiedError";
  1703. case kAudioHardwareUnknownPropertyError:
  1704. return "kAudioHardwareUnknownPropertyError";
  1705. case kAudioHardwareBadPropertySizeError:
  1706. return "kAudioHardwareBadPropertySizeError";
  1707. case kAudioHardwareIllegalOperationError:
  1708. return "kAudioHardwareIllegalOperationError";
  1709. case kAudioHardwareBadObjectError:
  1710. return "kAudioHardwareBadObjectError";
  1711. case kAudioHardwareBadDeviceError:
  1712. return "kAudioHardwareBadDeviceError";
  1713. case kAudioHardwareBadStreamError:
  1714. return "kAudioHardwareBadStreamError";
  1715. case kAudioHardwareUnsupportedOperationError:
  1716. return "kAudioHardwareUnsupportedOperationError";
  1717. case kAudioDeviceUnsupportedFormatError:
  1718. return "kAudioDeviceUnsupportedFormatError";
  1719. case kAudioDevicePermissionsError:
  1720. return "kAudioDevicePermissionsError";
  1721. default:
  1722. return "CoreAudio unknown error";
  1723. }
  1724. }
  1725. //******************** End of __MACOSX_CORE__ *********************//
  1726. #endif
  1727. #if defined(__UNIX_JACK__)
  1728. // JACK is a low-latency audio server, originally written for the
  1729. // GNU/Linux operating system and now also ported to OS-X. It can
  1730. // connect a number of different applications to an audio device, as
  1731. // well as allowing them to share audio between themselves.
  1732. //
  1733. // When using JACK with RtAudio, "devices" refer to JACK clients that
  1734. // have ports connected to the server. The JACK server is typically
  1735. // started in a terminal as follows:
  1736. //
  1737. // .jackd -d alsa -d hw:0
  1738. //
  1739. // or through an interface program such as qjackctl. Many of the
  1740. // parameters normally set for a stream are fixed by the JACK server
  1741. // and can be specified when the JACK server is started. In
  1742. // particular,
  1743. //
  1744. // .jackd -d alsa -d hw:0 -r 44100 -p 512 -n 4
  1745. //
  1746. // specifies a sample rate of 44100 Hz, a buffer size of 512 sample
  1747. // frames, and number of buffers = 4. Once the server is running, it
  1748. // is not possible to override these values. If the values are not
  1749. // specified in the command-line, the JACK server uses default values.
  1750. //
  1751. // The JACK server does not have to be running when an instance of
  1752. // RtApiJack is created, though the function getDeviceCount() will
  1753. // report 0 devices found until JACK has been started. When no
  1754. // devices are available (i.e., the JACK server is not running), a
  1755. // stream cannot be opened.
  1756. #include <jack/jack.h>
  1757. #include <unistd.h>
  1758. #include <cstdio>
  1759. // A structure to hold various information related to the Jack API
  1760. // implementation.
  1761. struct JackHandle {
  1762. jack_client_t *client;
  1763. jack_port_t **ports[2];
  1764. std::string deviceName[2];
  1765. bool xrun[2];
  1766. pthread_cond_t condition;
  1767. int drainCounter; // Tracks callback counts when draining
  1768. bool internalDrain; // Indicates if stop is initiated from callback or not.
  1769. JackHandle()
  1770. :client(0), drainCounter(0), internalDrain(false) { ports[0] = 0; ports[1] = 0; xrun[0] = false; xrun[1] = false; }
  1771. };
  1772. #if !defined(__RTAUDIO_DEBUG__)
  1773. static void jackSilentError( const char * ) {};
  1774. #endif
  1775. RtApiJack :: RtApiJack()
  1776. :shouldAutoconnect_(true) {
  1777. // Nothing to do here.
  1778. #if !defined(__RTAUDIO_DEBUG__)
  1779. // Turn off Jack's internal error reporting.
  1780. jack_set_error_function( &jackSilentError );
  1781. #endif
  1782. }
  1783. RtApiJack :: ~RtApiJack()
  1784. {
  1785. if ( stream_.state != STREAM_CLOSED ) closeStream();
  1786. }
  1787. unsigned int RtApiJack :: getDeviceCount( void )
  1788. {
  1789. // See if we can become a jack client.
  1790. jack_options_t options = (jack_options_t) ( JackNoStartServer ); //JackNullOption;
  1791. jack_status_t *status = NULL;
  1792. jack_client_t *client = jack_client_open( "RtApiJackCount", options, status );
  1793. if ( client == 0 ) return 0;
  1794. const char **ports;
  1795. std::string port, previousPort;
  1796. unsigned int nChannels = 0, nDevices = 0;
  1797. ports = jack_get_ports( client, NULL, JACK_DEFAULT_AUDIO_TYPE, 0 );
  1798. if ( ports ) {
  1799. // Parse the port names up to the first colon (:).
  1800. size_t iColon = 0;
  1801. do {
  1802. port = (char *) ports[ nChannels ];
  1803. iColon = port.find(":");
  1804. if ( iColon != std::string::npos ) {
  1805. port = port.substr( 0, iColon + 1 );
  1806. if ( port != previousPort ) {
  1807. nDevices++;
  1808. previousPort = port;
  1809. }
  1810. }
  1811. } while ( ports[++nChannels] );
  1812. free( ports );
  1813. }
  1814. jack_client_close( client );
  1815. return nDevices;
  1816. }
  1817. RtAudio::DeviceInfo RtApiJack :: getDeviceInfo( unsigned int device )
  1818. {
  1819. RtAudio::DeviceInfo info;
  1820. info.probed = false;
  1821. jack_options_t options = (jack_options_t) ( JackNoStartServer ); //JackNullOption
  1822. jack_status_t *status = NULL;
  1823. jack_client_t *client = jack_client_open( "RtApiJackInfo", options, status );
  1824. if ( client == 0 ) {
  1825. errorText_ = "RtApiJack::getDeviceInfo: Jack server not found or connection error!";
  1826. error( RtAudioError::WARNING );
  1827. return info;
  1828. }
  1829. const char **ports;
  1830. std::string port, previousPort;
  1831. unsigned int nPorts = 0, nDevices = 0;
  1832. ports = jack_get_ports( client, NULL, JACK_DEFAULT_AUDIO_TYPE, 0 );
  1833. if ( ports ) {
  1834. // Parse the port names up to the first colon (:).
  1835. size_t iColon = 0;
  1836. do {
  1837. port = (char *) ports[ nPorts ];
  1838. iColon = port.find(":");
  1839. if ( iColon != std::string::npos ) {
  1840. port = port.substr( 0, iColon );
  1841. if ( port != previousPort ) {
  1842. if ( nDevices == device ) info.name = port;
  1843. nDevices++;
  1844. previousPort = port;
  1845. }
  1846. }
  1847. } while ( ports[++nPorts] );
  1848. free( ports );
  1849. }
  1850. if ( device >= nDevices ) {
  1851. jack_client_close( client );
  1852. errorText_ = "RtApiJack::getDeviceInfo: device ID is invalid!";
  1853. error( RtAudioError::INVALID_USE );
  1854. return info;
  1855. }
  1856. // Get the current jack server sample rate.
  1857. info.sampleRates.clear();
  1858. info.preferredSampleRate = jack_get_sample_rate( client );
  1859. info.sampleRates.push_back( info.preferredSampleRate );
  1860. // Count the available ports containing the client name as device
  1861. // channels. Jack "input ports" equal RtAudio output channels.
  1862. unsigned int nChannels = 0;
  1863. ports = jack_get_ports( client, info.name.c_str(), JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput );
  1864. if ( ports ) {
  1865. while ( ports[ nChannels ] ) nChannels++;
  1866. free( ports );
  1867. info.outputChannels = nChannels;
  1868. }
  1869. // Jack "output ports" equal RtAudio input channels.
  1870. nChannels = 0;
  1871. ports = jack_get_ports( client, info.name.c_str(), JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput );
  1872. if ( ports ) {
  1873. while ( ports[ nChannels ] ) nChannels++;
  1874. free( ports );
  1875. info.inputChannels = nChannels;
  1876. }
  1877. if ( info.outputChannels == 0 && info.inputChannels == 0 ) {
  1878. jack_client_close(client);
  1879. errorText_ = "RtApiJack::getDeviceInfo: error determining Jack input/output channels!";
  1880. error( RtAudioError::WARNING );
  1881. return info;
  1882. }
  1883. // If device opens for both playback and capture, we determine the channels.
  1884. if ( info.outputChannels > 0 && info.inputChannels > 0 )
  1885. info.duplexChannels = (info.outputChannels > info.inputChannels) ? info.inputChannels : info.outputChannels;
  1886. // Jack always uses 32-bit floats.
  1887. info.nativeFormats = RTAUDIO_FLOAT32;
  1888. // Jack doesn't provide default devices so we'll use the first available one.
  1889. if ( device == 0 && info.outputChannels > 0 )
  1890. info.isDefaultOutput = true;
  1891. if ( device == 0 && info.inputChannels > 0 )
  1892. info.isDefaultInput = true;
  1893. jack_client_close(client);
  1894. info.probed = true;
  1895. return info;
  1896. }
  1897. static int jackCallbackHandler( jack_nframes_t nframes, void *infoPointer )
  1898. {
  1899. CallbackInfo *info = (CallbackInfo *) infoPointer;
  1900. RtApiJack *object = (RtApiJack *) info->object;
  1901. if ( object->callbackEvent( (unsigned long) nframes ) == false ) return 1;
  1902. return 0;
  1903. }
  1904. // This function will be called by a spawned thread when the Jack
  1905. // server signals that it is shutting down. It is necessary to handle
  1906. // it this way because the jackShutdown() function must return before
  1907. // the jack_deactivate() function (in closeStream()) will return.
  1908. static void *jackCloseStream( void *ptr )
  1909. {
  1910. CallbackInfo *info = (CallbackInfo *) ptr;
  1911. RtApiJack *object = (RtApiJack *) info->object;
  1912. object->closeStream();
  1913. pthread_exit( NULL );
  1914. }
  1915. static void jackShutdown( void *infoPointer )
  1916. {
  1917. CallbackInfo *info = (CallbackInfo *) infoPointer;
  1918. RtApiJack *object = (RtApiJack *) info->object;
  1919. // Check current stream state. If stopped, then we'll assume this
  1920. // was called as a result of a call to RtApiJack::stopStream (the
  1921. // deactivation of a client handle causes this function to be called).
  1922. // If not, we'll assume the Jack server is shutting down or some
  1923. // other problem occurred and we should close the stream.
  1924. if ( object->isStreamRunning() == false ) return;
  1925. ThreadHandle threadId;
  1926. pthread_create( &threadId, NULL, jackCloseStream, info );
  1927. std::cerr << "\nRtApiJack: the Jack server is shutting down this client ... stream stopped and closed!!\n" << std::endl;
  1928. }
  1929. static int jackXrun( void *infoPointer )
  1930. {
  1931. JackHandle *handle = *((JackHandle **) infoPointer);
  1932. if ( handle->ports[0] ) handle->xrun[0] = true;
  1933. if ( handle->ports[1] ) handle->xrun[1] = true;
  1934. return 0;
  1935. }
  1936. bool RtApiJack :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels,
  1937. unsigned int firstChannel, unsigned int sampleRate,
  1938. RtAudioFormat format, unsigned int *bufferSize,
  1939. RtAudio::StreamOptions *options )
  1940. {
  1941. JackHandle *handle = (JackHandle *) stream_.apiHandle;
  1942. // Look for jack server and try to become a client (only do once per stream).
  1943. jack_client_t *client = 0;
  1944. if ( mode == OUTPUT || ( mode == INPUT && stream_.mode != OUTPUT ) ) {
  1945. jack_options_t jackoptions = (jack_options_t) ( JackNoStartServer ); //JackNullOption;
  1946. jack_status_t *status = NULL;
  1947. if ( options && !options->streamName.empty() )
  1948. client = jack_client_open( options->streamName.c_str(), jackoptions, status );
  1949. else
  1950. client = jack_client_open( "RtApiJack", jackoptions, status );
  1951. if ( client == 0 ) {
  1952. errorText_ = "RtApiJack::probeDeviceOpen: Jack server not found or connection error!";
  1953. error( RtAudioError::WARNING );
  1954. return FAILURE;
  1955. }
  1956. }
  1957. else {
  1958. // The handle must have been created on an earlier pass.
  1959. client = handle->client;
  1960. }
  1961. const char **ports;
  1962. std::string port, previousPort, deviceName;
  1963. unsigned int nPorts = 0, nDevices = 0;
  1964. ports = jack_get_ports( client, NULL, JACK_DEFAULT_AUDIO_TYPE, 0 );
  1965. if ( ports ) {
  1966. // Parse the port names up to the first colon (:).
  1967. size_t iColon = 0;
  1968. do {
  1969. port = (char *) ports[ nPorts ];
  1970. iColon = port.find(":");
  1971. if ( iColon != std::string::npos ) {
  1972. port = port.substr( 0, iColon );
  1973. if ( port != previousPort ) {
  1974. if ( nDevices == device ) deviceName = port;
  1975. nDevices++;
  1976. previousPort = port;
  1977. }
  1978. }
  1979. } while ( ports[++nPorts] );
  1980. free( ports );
  1981. }
  1982. if ( device >= nDevices ) {
  1983. errorText_ = "RtApiJack::probeDeviceOpen: device ID is invalid!";
  1984. return FAILURE;
  1985. }
  1986. unsigned long flag = JackPortIsInput;
  1987. if ( mode == INPUT ) flag = JackPortIsOutput;
  1988. if ( ! (options && (options->flags & RTAUDIO_JACK_DONT_CONNECT)) ) {
  1989. // Count the available ports containing the client name as device
  1990. // channels. Jack "input ports" equal RtAudio output channels.
  1991. unsigned int nChannels = 0;
  1992. ports = jack_get_ports( client, deviceName.c_str(), JACK_DEFAULT_AUDIO_TYPE, flag );
  1993. if ( ports ) {
  1994. while ( ports[ nChannels ] ) nChannels++;
  1995. free( ports );
  1996. }
  1997. // Compare the jack ports for specified client to the requested number of channels.
  1998. if ( nChannels < (channels + firstChannel) ) {
  1999. errorStream_ << "RtApiJack::probeDeviceOpen: requested number of channels (" << channels << ") + offset (" << firstChannel << ") not found for specified device (" << device << ":" << deviceName << ").";
  2000. errorText_ = errorStream_.str();
  2001. return FAILURE;
  2002. }
  2003. }
  2004. // Check the jack server sample rate.
  2005. unsigned int jackRate = jack_get_sample_rate( client );
  2006. if ( sampleRate != jackRate ) {
  2007. jack_client_close( client );
  2008. errorStream_ << "RtApiJack::probeDeviceOpen: the requested sample rate (" << sampleRate << ") is different than the JACK server rate (" << jackRate << ").";
  2009. errorText_ = errorStream_.str();
  2010. return FAILURE;
  2011. }
  2012. stream_.sampleRate = jackRate;
  2013. // Get the latency of the JACK port.
  2014. ports = jack_get_ports( client, deviceName.c_str(), JACK_DEFAULT_AUDIO_TYPE, flag );
  2015. if ( ports[ firstChannel ] ) {
  2016. // Added by Ge Wang
  2017. jack_latency_callback_mode_t cbmode = (mode == INPUT ? JackCaptureLatency : JackPlaybackLatency);
  2018. // the range (usually the min and max are equal)
  2019. jack_latency_range_t latrange; latrange.min = latrange.max = 0;
  2020. // get the latency range
  2021. jack_port_get_latency_range( jack_port_by_name( client, ports[firstChannel] ), cbmode, &latrange );
  2022. // be optimistic, use the min!
  2023. stream_.latency[mode] = latrange.min;
  2024. //stream_.latency[mode] = jack_port_get_latency( jack_port_by_name( client, ports[ firstChannel ] ) );
  2025. }
  2026. free( ports );
  2027. // The jack server always uses 32-bit floating-point data.
  2028. stream_.deviceFormat[mode] = RTAUDIO_FLOAT32;
  2029. stream_.userFormat = format;
  2030. if ( options && options->flags & RTAUDIO_NONINTERLEAVED ) stream_.userInterleaved = false;
  2031. else stream_.userInterleaved = true;
  2032. // Jack always uses non-interleaved buffers.
  2033. stream_.deviceInterleaved[mode] = false;
  2034. // Jack always provides host byte-ordered data.
  2035. stream_.doByteSwap[mode] = false;
  2036. // Get the buffer size. The buffer size and number of buffers
  2037. // (periods) is set when the jack server is started.
  2038. stream_.bufferSize = (int) jack_get_buffer_size( client );
  2039. *bufferSize = stream_.bufferSize;
  2040. stream_.nDeviceChannels[mode] = channels;
  2041. stream_.nUserChannels[mode] = channels;
  2042. // Set flags for buffer conversion.
  2043. stream_.doConvertBuffer[mode] = false;
  2044. if ( stream_.userFormat != stream_.deviceFormat[mode] )
  2045. stream_.doConvertBuffer[mode] = true;
  2046. if ( stream_.userInterleaved != stream_.deviceInterleaved[mode] &&
  2047. stream_.nUserChannels[mode] > 1 )
  2048. stream_.doConvertBuffer[mode] = true;
  2049. // Allocate our JackHandle structure for the stream.
  2050. if ( handle == 0 ) {
  2051. try {
  2052. handle = new JackHandle;
  2053. }
  2054. catch ( std::bad_alloc& ) {
  2055. errorText_ = "RtApiJack::probeDeviceOpen: error allocating JackHandle memory.";
  2056. goto error;
  2057. }
  2058. if ( pthread_cond_init(&handle->condition, NULL) ) {
  2059. errorText_ = "RtApiJack::probeDeviceOpen: error initializing pthread condition variable.";
  2060. goto error;
  2061. }
  2062. stream_.apiHandle = (void *) handle;
  2063. handle->client = client;
  2064. }
  2065. handle->deviceName[mode] = deviceName;
  2066. // Allocate necessary internal buffers.
  2067. unsigned long bufferBytes;
  2068. bufferBytes = stream_.nUserChannels[mode] * *bufferSize * formatBytes( stream_.userFormat );
  2069. stream_.userBuffer[mode] = (char *) calloc( bufferBytes, 1 );
  2070. if ( stream_.userBuffer[mode] == NULL ) {
  2071. errorText_ = "RtApiJack::probeDeviceOpen: error allocating user buffer memory.";
  2072. goto error;
  2073. }
  2074. if ( stream_.doConvertBuffer[mode] ) {
  2075. bool makeBuffer = true;
  2076. if ( mode == OUTPUT )
  2077. bufferBytes = stream_.nDeviceChannels[0] * formatBytes( stream_.deviceFormat[0] );
  2078. else { // mode == INPUT
  2079. bufferBytes = stream_.nDeviceChannels[1] * formatBytes( stream_.deviceFormat[1] );
  2080. if ( stream_.mode == OUTPUT && stream_.deviceBuffer ) {
  2081. unsigned long bytesOut = stream_.nDeviceChannels[0] * formatBytes(stream_.deviceFormat[0]);
  2082. if ( bufferBytes < bytesOut ) makeBuffer = false;
  2083. }
  2084. }
  2085. if ( makeBuffer ) {
  2086. bufferBytes *= *bufferSize;
  2087. if ( stream_.deviceBuffer ) free( stream_.deviceBuffer );
  2088. stream_.deviceBuffer = (char *) calloc( bufferBytes, 1 );
  2089. if ( stream_.deviceBuffer == NULL ) {
  2090. errorText_ = "RtApiJack::probeDeviceOpen: error allocating device buffer memory.";
  2091. goto error;
  2092. }
  2093. }
  2094. }
  2095. // Allocate memory for the Jack ports (channels) identifiers.
  2096. handle->ports[mode] = (jack_port_t **) malloc ( sizeof (jack_port_t *) * channels );
  2097. if ( handle->ports[mode] == NULL ) {
  2098. errorText_ = "RtApiJack::probeDeviceOpen: error allocating port memory.";
  2099. goto error;
  2100. }
  2101. stream_.device[mode] = device;
  2102. stream_.channelOffset[mode] = firstChannel;
  2103. stream_.state = STREAM_STOPPED;
  2104. stream_.callbackInfo.object = (void *) this;
  2105. if ( stream_.mode == OUTPUT && mode == INPUT )
  2106. // We had already set up the stream for output.
  2107. stream_.mode = DUPLEX;
  2108. else {
  2109. stream_.mode = mode;
  2110. jack_set_process_callback( handle->client, jackCallbackHandler, (void *) &stream_.callbackInfo );
  2111. jack_set_xrun_callback( handle->client, jackXrun, (void *) &stream_.apiHandle );
  2112. jack_on_shutdown( handle->client, jackShutdown, (void *) &stream_.callbackInfo );
  2113. }
  2114. // Register our ports.
  2115. char label[64];
  2116. if ( mode == OUTPUT ) {
  2117. for ( unsigned int i=0; i<stream_.nUserChannels[0]; i++ ) {
  2118. snprintf( label, 64, "outport %d", i );
  2119. handle->ports[0][i] = jack_port_register( handle->client, (const char *)label,
  2120. JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0 );
  2121. }
  2122. }
  2123. else {
  2124. for ( unsigned int i=0; i<stream_.nUserChannels[1]; i++ ) {
  2125. snprintf( label, 64, "inport %d", i );
  2126. handle->ports[1][i] = jack_port_register( handle->client, (const char *)label,
  2127. JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0 );
  2128. }
  2129. }
  2130. // Setup the buffer conversion information structure. We don't use
  2131. // buffers to do channel offsets, so we override that parameter
  2132. // here.
  2133. if ( stream_.doConvertBuffer[mode] ) setConvertInfo( mode, 0 );
  2134. if ( options && options->flags & RTAUDIO_JACK_DONT_CONNECT ) shouldAutoconnect_ = false;
  2135. return SUCCESS;
  2136. error:
  2137. if ( handle ) {
  2138. pthread_cond_destroy( &handle->condition );
  2139. jack_client_close( handle->client );
  2140. if ( handle->ports[0] ) free( handle->ports[0] );
  2141. if ( handle->ports[1] ) free( handle->ports[1] );
  2142. delete handle;
  2143. stream_.apiHandle = 0;
  2144. }
  2145. for ( int i=0; i<2; i++ ) {
  2146. if ( stream_.userBuffer[i] ) {
  2147. free( stream_.userBuffer[i] );
  2148. stream_.userBuffer[i] = 0;
  2149. }
  2150. }
  2151. if ( stream_.deviceBuffer ) {
  2152. free( stream_.deviceBuffer );
  2153. stream_.deviceBuffer = 0;
  2154. }
  2155. return FAILURE;
  2156. }
  2157. void RtApiJack :: closeStream( void )
  2158. {
  2159. if ( stream_.state == STREAM_CLOSED ) {
  2160. errorText_ = "RtApiJack::closeStream(): no open stream to close!";
  2161. error( RtAudioError::WARNING );
  2162. return;
  2163. }
  2164. JackHandle *handle = (JackHandle *) stream_.apiHandle;
  2165. if ( handle ) {
  2166. if ( stream_.state == STREAM_RUNNING )
  2167. jack_deactivate( handle->client );
  2168. jack_client_close( handle->client );
  2169. }
  2170. if ( handle ) {
  2171. if ( handle->ports[0] ) free( handle->ports[0] );
  2172. if ( handle->ports[1] ) free( handle->ports[1] );
  2173. pthread_cond_destroy( &handle->condition );
  2174. delete handle;
  2175. stream_.apiHandle = 0;
  2176. }
  2177. for ( int i=0; i<2; i++ ) {
  2178. if ( stream_.userBuffer[i] ) {
  2179. free( stream_.userBuffer[i] );
  2180. stream_.userBuffer[i] = 0;
  2181. }
  2182. }
  2183. if ( stream_.deviceBuffer ) {
  2184. free( stream_.deviceBuffer );
  2185. stream_.deviceBuffer = 0;
  2186. }
  2187. stream_.mode = UNINITIALIZED;
  2188. stream_.state = STREAM_CLOSED;
  2189. }
  2190. void RtApiJack :: startStream( void )
  2191. {
  2192. verifyStream();
  2193. if ( stream_.state == STREAM_RUNNING ) {
  2194. errorText_ = "RtApiJack::startStream(): the stream is already running!";
  2195. error( RtAudioError::WARNING );
  2196. return;
  2197. }
  2198. #if defined( HAVE_GETTIMEOFDAY )
  2199. gettimeofday( &stream_.lastTickTimestamp, NULL );
  2200. #endif
  2201. JackHandle *handle = (JackHandle *) stream_.apiHandle;
  2202. int result = jack_activate( handle->client );
  2203. if ( result ) {
  2204. errorText_ = "RtApiJack::startStream(): unable to activate JACK client!";
  2205. goto unlock;
  2206. }
  2207. const char **ports;
  2208. // Get the list of available ports.
  2209. if ( shouldAutoconnect_ && (stream_.mode == OUTPUT || stream_.mode == DUPLEX) ) {
  2210. result = 1;
  2211. ports = jack_get_ports( handle->client, handle->deviceName[0].c_str(), JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput);
  2212. if ( ports == NULL) {
  2213. errorText_ = "RtApiJack::startStream(): error determining available JACK input ports!";
  2214. goto unlock;
  2215. }
  2216. // Now make the port connections. Since RtAudio wasn't designed to
  2217. // allow the user to select particular channels of a device, we'll
  2218. // just open the first "nChannels" ports with offset.
  2219. for ( unsigned int i=0; i<stream_.nUserChannels[0]; i++ ) {
  2220. result = 1;
  2221. if ( ports[ stream_.channelOffset[0] + i ] )
  2222. result = jack_connect( handle->client, jack_port_name( handle->ports[0][i] ), ports[ stream_.channelOffset[0] + i ] );
  2223. if ( result ) {
  2224. free( ports );
  2225. errorText_ = "RtApiJack::startStream(): error connecting output ports!";
  2226. goto unlock;
  2227. }
  2228. }
  2229. free(ports);
  2230. }
  2231. if ( shouldAutoconnect_ && (stream_.mode == INPUT || stream_.mode == DUPLEX) ) {
  2232. result = 1;
  2233. ports = jack_get_ports( handle->client, handle->deviceName[1].c_str(), JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput );
  2234. if ( ports == NULL) {
  2235. errorText_ = "RtApiJack::startStream(): error determining available JACK output ports!";
  2236. goto unlock;
  2237. }
  2238. // Now make the port connections. See note above.
  2239. for ( unsigned int i=0; i<stream_.nUserChannels[1]; i++ ) {
  2240. result = 1;
  2241. if ( ports[ stream_.channelOffset[1] + i ] )
  2242. result = jack_connect( handle->client, ports[ stream_.channelOffset[1] + i ], jack_port_name( handle->ports[1][i] ) );
  2243. if ( result ) {
  2244. free( ports );
  2245. errorText_ = "RtApiJack::startStream(): error connecting input ports!";
  2246. goto unlock;
  2247. }
  2248. }
  2249. free(ports);
  2250. }
  2251. handle->drainCounter = 0;
  2252. handle->internalDrain = false;
  2253. stream_.state = STREAM_RUNNING;
  2254. unlock:
  2255. if ( result == 0 ) return;
  2256. error( RtAudioError::SYSTEM_ERROR );
  2257. }
  2258. void RtApiJack :: stopStream( void )
  2259. {
  2260. verifyStream();
  2261. if ( stream_.state == STREAM_STOPPED ) {
  2262. errorText_ = "RtApiJack::stopStream(): the stream is already stopped!";
  2263. error( RtAudioError::WARNING );
  2264. return;
  2265. }
  2266. JackHandle *handle = (JackHandle *) stream_.apiHandle;
  2267. if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) {
  2268. if ( handle->drainCounter == 0 ) {
  2269. handle->drainCounter = 2;
  2270. pthread_cond_wait( &handle->condition, &stream_.mutex ); // block until signaled
  2271. }
  2272. }
  2273. jack_deactivate( handle->client );
  2274. stream_.state = STREAM_STOPPED;
  2275. }
  2276. void RtApiJack :: abortStream( void )
  2277. {
  2278. verifyStream();
  2279. if ( stream_.state == STREAM_STOPPED ) {
  2280. errorText_ = "RtApiJack::abortStream(): the stream is already stopped!";
  2281. error( RtAudioError::WARNING );
  2282. return;
  2283. }
  2284. JackHandle *handle = (JackHandle *) stream_.apiHandle;
  2285. handle->drainCounter = 2;
  2286. stopStream();
  2287. }
  2288. // This function will be called by a spawned thread when the user
  2289. // callback function signals that the stream should be stopped or
  2290. // aborted. It is necessary to handle it this way because the
  2291. // callbackEvent() function must return before the jack_deactivate()
  2292. // function will return.
  2293. static void *jackStopStream( void *ptr )
  2294. {
  2295. CallbackInfo *info = (CallbackInfo *) ptr;
  2296. RtApiJack *object = (RtApiJack *) info->object;
  2297. object->stopStream();
  2298. pthread_exit( NULL );
  2299. }
  2300. bool RtApiJack :: callbackEvent( unsigned long nframes )
  2301. {
  2302. if ( stream_.state == STREAM_STOPPED || stream_.state == STREAM_STOPPING ) return SUCCESS;
  2303. if ( stream_.state == STREAM_CLOSED ) {
  2304. errorText_ = "RtApiCore::callbackEvent(): the stream is closed ... this shouldn't happen!";
  2305. error( RtAudioError::WARNING );
  2306. return FAILURE;
  2307. }
  2308. if ( stream_.bufferSize != nframes ) {
  2309. errorText_ = "RtApiCore::callbackEvent(): the JACK buffer size has changed ... cannot process!";
  2310. error( RtAudioError::WARNING );
  2311. return FAILURE;
  2312. }
  2313. CallbackInfo *info = (CallbackInfo *) &stream_.callbackInfo;
  2314. JackHandle *handle = (JackHandle *) stream_.apiHandle;
  2315. // Check if we were draining the stream and signal is finished.
  2316. if ( handle->drainCounter > 3 ) {
  2317. ThreadHandle threadId;
  2318. stream_.state = STREAM_STOPPING;
  2319. if ( handle->internalDrain == true )
  2320. pthread_create( &threadId, NULL, jackStopStream, info );
  2321. else
  2322. pthread_cond_signal( &handle->condition );
  2323. return SUCCESS;
  2324. }
  2325. // Invoke user callback first, to get fresh output data.
  2326. if ( handle->drainCounter == 0 ) {
  2327. RtAudioCallback callback = (RtAudioCallback) info->callback;
  2328. double streamTime = getStreamTime();
  2329. RtAudioStreamStatus status = 0;
  2330. if ( stream_.mode != INPUT && handle->xrun[0] == true ) {
  2331. status |= RTAUDIO_OUTPUT_UNDERFLOW;
  2332. handle->xrun[0] = false;
  2333. }
  2334. if ( stream_.mode != OUTPUT && handle->xrun[1] == true ) {
  2335. status |= RTAUDIO_INPUT_OVERFLOW;
  2336. handle->xrun[1] = false;
  2337. }
  2338. int cbReturnValue = callback( stream_.userBuffer[0], stream_.userBuffer[1],
  2339. stream_.bufferSize, streamTime, status, info->userData );
  2340. if ( cbReturnValue == 2 ) {
  2341. stream_.state = STREAM_STOPPING;
  2342. handle->drainCounter = 2;
  2343. ThreadHandle id;
  2344. pthread_create( &id, NULL, jackStopStream, info );
  2345. return SUCCESS;
  2346. }
  2347. else if ( cbReturnValue == 1 ) {
  2348. handle->drainCounter = 1;
  2349. handle->internalDrain = true;
  2350. }
  2351. }
  2352. jack_default_audio_sample_t *jackbuffer;
  2353. unsigned long bufferBytes = nframes * sizeof( jack_default_audio_sample_t );
  2354. if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) {
  2355. if ( handle->drainCounter > 1 ) { // write zeros to the output stream
  2356. for ( unsigned int i=0; i<stream_.nDeviceChannels[0]; i++ ) {
  2357. jackbuffer = (jack_default_audio_sample_t *) jack_port_get_buffer( handle->ports[0][i], (jack_nframes_t) nframes );
  2358. memset( jackbuffer, 0, bufferBytes );
  2359. }
  2360. }
  2361. else if ( stream_.doConvertBuffer[0] ) {
  2362. convertBuffer( stream_.deviceBuffer, stream_.userBuffer[0], stream_.convertInfo[0] );
  2363. for ( unsigned int i=0; i<stream_.nDeviceChannels[0]; i++ ) {
  2364. jackbuffer = (jack_default_audio_sample_t *) jack_port_get_buffer( handle->ports[0][i], (jack_nframes_t) nframes );
  2365. memcpy( jackbuffer, &stream_.deviceBuffer[i*bufferBytes], bufferBytes );
  2366. }
  2367. }
  2368. else { // no buffer conversion
  2369. for ( unsigned int i=0; i<stream_.nUserChannels[0]; i++ ) {
  2370. jackbuffer = (jack_default_audio_sample_t *) jack_port_get_buffer( handle->ports[0][i], (jack_nframes_t) nframes );
  2371. memcpy( jackbuffer, &stream_.userBuffer[0][i*bufferBytes], bufferBytes );
  2372. }
  2373. }
  2374. }
  2375. // Don't bother draining input
  2376. if ( handle->drainCounter ) {
  2377. handle->drainCounter++;
  2378. goto unlock;
  2379. }
  2380. if ( stream_.mode == INPUT || stream_.mode == DUPLEX ) {
  2381. if ( stream_.doConvertBuffer[1] ) {
  2382. for ( unsigned int i=0; i<stream_.nDeviceChannels[1]; i++ ) {
  2383. jackbuffer = (jack_default_audio_sample_t *) jack_port_get_buffer( handle->ports[1][i], (jack_nframes_t) nframes );
  2384. memcpy( &stream_.deviceBuffer[i*bufferBytes], jackbuffer, bufferBytes );
  2385. }
  2386. convertBuffer( stream_.userBuffer[1], stream_.deviceBuffer, stream_.convertInfo[1] );
  2387. }
  2388. else { // no buffer conversion
  2389. for ( unsigned int i=0; i<stream_.nUserChannels[1]; i++ ) {
  2390. jackbuffer = (jack_default_audio_sample_t *) jack_port_get_buffer( handle->ports[1][i], (jack_nframes_t) nframes );
  2391. memcpy( &stream_.userBuffer[1][i*bufferBytes], jackbuffer, bufferBytes );
  2392. }
  2393. }
  2394. }
  2395. unlock:
  2396. RtApi::tickStreamTime();
  2397. return SUCCESS;
  2398. }
  2399. //******************** End of __UNIX_JACK__ *********************//
  2400. #endif
  2401. #if defined(__WINDOWS_ASIO__) // ASIO API on Windows
  2402. // The ASIO API is designed around a callback scheme, so this
  2403. // implementation is similar to that used for OS-X CoreAudio and Linux
  2404. // Jack. The primary constraint with ASIO is that it only allows
  2405. // access to a single driver at a time. Thus, it is not possible to
  2406. // have more than one simultaneous RtAudio stream.
  2407. //
  2408. // This implementation also requires a number of external ASIO files
  2409. // and a few global variables. The ASIO callback scheme does not
  2410. // allow for the passing of user data, so we must create a global
  2411. // pointer to our callbackInfo structure.
  2412. //
  2413. // On unix systems, we make use of a pthread condition variable.
  2414. // Since there is no equivalent in Windows, I hacked something based
  2415. // on information found in
  2416. // http://www.cs.wustl.edu/~schmidt/win32-cv-1.html.
  2417. #include "asiosys.h"
  2418. #include "asio.h"
  2419. #include "iasiothiscallresolver.h"
  2420. #include "asiodrivers.h"
  2421. #include <cmath>
  2422. static AsioDrivers drivers;
  2423. static ASIOCallbacks asioCallbacks;
  2424. static ASIODriverInfo driverInfo;
  2425. static CallbackInfo *asioCallbackInfo;
  2426. static bool asioXRun;
  2427. struct AsioHandle {
  2428. int drainCounter; // Tracks callback counts when draining
  2429. bool internalDrain; // Indicates if stop is initiated from callback or not.
  2430. ASIOBufferInfo *bufferInfos;
  2431. HANDLE condition;
  2432. AsioHandle()
  2433. :drainCounter(0), internalDrain(false), bufferInfos(0) {}
  2434. };
  2435. // Function declarations (definitions at end of section)
  2436. static const char* getAsioErrorString( ASIOError result );
  2437. static void sampleRateChanged( ASIOSampleRate sRate );
  2438. static long asioMessages( long selector, long value, void* message, double* opt );
  2439. RtApiAsio :: RtApiAsio()
  2440. {
  2441. // ASIO cannot run on a multi-threaded apartment. You can call
  2442. // CoInitialize beforehand, but it must be for apartment threading
  2443. // (in which case, CoInitilialize will return S_FALSE here).
  2444. coInitialized_ = false;
  2445. HRESULT hr = CoInitialize( NULL );
  2446. if ( FAILED(hr) ) {
  2447. errorText_ = "RtApiAsio::ASIO requires a single-threaded apartment. Call CoInitializeEx(0,COINIT_APARTMENTTHREADED)";
  2448. error( RtAudioError::WARNING );
  2449. }
  2450. coInitialized_ = true;
  2451. drivers.removeCurrentDriver();
  2452. driverInfo.asioVersion = 2;
  2453. // See note in DirectSound implementation about GetDesktopWindow().
  2454. driverInfo.sysRef = GetForegroundWindow();
  2455. }
  2456. RtApiAsio :: ~RtApiAsio()
  2457. {
  2458. if ( stream_.state != STREAM_CLOSED ) closeStream();
  2459. if ( coInitialized_ ) CoUninitialize();
  2460. }
  2461. unsigned int RtApiAsio :: getDeviceCount( void )
  2462. {
  2463. return (unsigned int) drivers.asioGetNumDev();
  2464. }
  2465. // We can only load one ASIO driver, so the default output is always the first device.
  2466. unsigned int RtApiAsio :: getDefaultOutputDevice( void )
  2467. {
  2468. return 0;
  2469. }
  2470. // We can only load one ASIO driver, so the default input is always the first device.
  2471. unsigned int RtApiAsio :: getDefaultInputDevice( void )
  2472. {
  2473. return 0;
  2474. }
  2475. RtAudio::DeviceInfo RtApiAsio :: getDeviceInfo( unsigned int device )
  2476. {
  2477. RtAudio::DeviceInfo info;
  2478. info.probed = false;
  2479. // Get device ID
  2480. unsigned int nDevices = getDeviceCount();
  2481. if ( nDevices == 0 ) {
  2482. errorText_ = "RtApiAsio::getDeviceInfo: no devices found!";
  2483. error( RtAudioError::INVALID_USE );
  2484. return info;
  2485. }
  2486. if ( device >= nDevices ) {
  2487. errorText_ = "RtApiAsio::getDeviceInfo: device ID is invalid!";
  2488. error( RtAudioError::INVALID_USE );
  2489. return info;
  2490. }
  2491. // If a stream is already open, we cannot probe other devices. Thus, use the saved results.
  2492. if ( stream_.state != STREAM_CLOSED ) {
  2493. if ( device >= devices_.size() ) {
  2494. errorText_ = "RtApiAsio::getDeviceInfo: device ID was not present before stream was opened.";
  2495. error( RtAudioError::WARNING );
  2496. return info;
  2497. }
  2498. return devices_[ device ];
  2499. }
  2500. char driverName[32];
  2501. ASIOError result = drivers.asioGetDriverName( (int) device, driverName, 32 );
  2502. if ( result != ASE_OK ) {
  2503. errorStream_ << "RtApiAsio::getDeviceInfo: unable to get driver name (" << getAsioErrorString( result ) << ").";
  2504. errorText_ = errorStream_.str();
  2505. error( RtAudioError::WARNING );
  2506. return info;
  2507. }
  2508. info.name = driverName;
  2509. if ( !drivers.loadDriver( driverName ) ) {
  2510. errorStream_ << "RtApiAsio::getDeviceInfo: unable to load driver (" << driverName << ").";
  2511. errorText_ = errorStream_.str();
  2512. error( RtAudioError::WARNING );
  2513. return info;
  2514. }
  2515. result = ASIOInit( &driverInfo );
  2516. if ( result != ASE_OK ) {
  2517. errorStream_ << "RtApiAsio::getDeviceInfo: error (" << getAsioErrorString( result ) << ") initializing driver (" << driverName << ").";
  2518. errorText_ = errorStream_.str();
  2519. error( RtAudioError::WARNING );
  2520. return info;
  2521. }
  2522. // Determine the device channel information.
  2523. long inputChannels, outputChannels;
  2524. result = ASIOGetChannels( &inputChannels, &outputChannels );
  2525. if ( result != ASE_OK ) {
  2526. drivers.removeCurrentDriver();
  2527. errorStream_ << "RtApiAsio::getDeviceInfo: error (" << getAsioErrorString( result ) << ") getting channel count (" << driverName << ").";
  2528. errorText_ = errorStream_.str();
  2529. error( RtAudioError::WARNING );
  2530. return info;
  2531. }
  2532. info.outputChannels = outputChannels;
  2533. info.inputChannels = inputChannels;
  2534. if ( info.outputChannels > 0 && info.inputChannels > 0 )
  2535. info.duplexChannels = (info.outputChannels > info.inputChannels) ? info.inputChannels : info.outputChannels;
  2536. // Determine the supported sample rates.
  2537. info.sampleRates.clear();
  2538. for ( unsigned int i=0; i<MAX_SAMPLE_RATES; i++ ) {
  2539. result = ASIOCanSampleRate( (ASIOSampleRate) SAMPLE_RATES[i] );
  2540. if ( result == ASE_OK ) {
  2541. info.sampleRates.push_back( SAMPLE_RATES[i] );
  2542. if ( !info.preferredSampleRate || ( SAMPLE_RATES[i] <= 48000 && SAMPLE_RATES[i] > info.preferredSampleRate ) )
  2543. info.preferredSampleRate = SAMPLE_RATES[i];
  2544. }
  2545. }
  2546. // Determine supported data types ... just check first channel and assume rest are the same.
  2547. ASIOChannelInfo channelInfo;
  2548. channelInfo.channel = 0;
  2549. channelInfo.isInput = true;
  2550. if ( info.inputChannels <= 0 ) channelInfo.isInput = false;
  2551. result = ASIOGetChannelInfo( &channelInfo );
  2552. if ( result != ASE_OK ) {
  2553. drivers.removeCurrentDriver();
  2554. errorStream_ << "RtApiAsio::getDeviceInfo: error (" << getAsioErrorString( result ) << ") getting driver channel info (" << driverName << ").";
  2555. errorText_ = errorStream_.str();
  2556. error( RtAudioError::WARNING );
  2557. return info;
  2558. }
  2559. info.nativeFormats = 0;
  2560. if ( channelInfo.type == ASIOSTInt16MSB || channelInfo.type == ASIOSTInt16LSB )
  2561. info.nativeFormats |= RTAUDIO_SINT16;
  2562. else if ( channelInfo.type == ASIOSTInt32MSB || channelInfo.type == ASIOSTInt32LSB )
  2563. info.nativeFormats |= RTAUDIO_SINT32;
  2564. else if ( channelInfo.type == ASIOSTFloat32MSB || channelInfo.type == ASIOSTFloat32LSB )
  2565. info.nativeFormats |= RTAUDIO_FLOAT32;
  2566. else if ( channelInfo.type == ASIOSTFloat64MSB || channelInfo.type == ASIOSTFloat64LSB )
  2567. info.nativeFormats |= RTAUDIO_FLOAT64;
  2568. else if ( channelInfo.type == ASIOSTInt24MSB || channelInfo.type == ASIOSTInt24LSB )
  2569. info.nativeFormats |= RTAUDIO_SINT24;
  2570. if ( info.outputChannels > 0 )
  2571. if ( getDefaultOutputDevice() == device ) info.isDefaultOutput = true;
  2572. if ( info.inputChannels > 0 )
  2573. if ( getDefaultInputDevice() == device ) info.isDefaultInput = true;
  2574. info.probed = true;
  2575. drivers.removeCurrentDriver();
  2576. return info;
  2577. }
  2578. static void bufferSwitch( long index, ASIOBool /*processNow*/ )
  2579. {
  2580. RtApiAsio *object = (RtApiAsio *) asioCallbackInfo->object;
  2581. object->callbackEvent( index );
  2582. }
  2583. void RtApiAsio :: saveDeviceInfo( void )
  2584. {
  2585. devices_.clear();
  2586. unsigned int nDevices = getDeviceCount();
  2587. devices_.resize( nDevices );
  2588. for ( unsigned int i=0; i<nDevices; i++ )
  2589. devices_[i] = getDeviceInfo( i );
  2590. }
  2591. bool RtApiAsio :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels,
  2592. unsigned int firstChannel, unsigned int sampleRate,
  2593. RtAudioFormat format, unsigned int *bufferSize,
  2594. RtAudio::StreamOptions *options )
  2595. {////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  2596. bool isDuplexInput = mode == INPUT && stream_.mode == OUTPUT;
  2597. // For ASIO, a duplex stream MUST use the same driver.
  2598. if ( isDuplexInput && stream_.device[0] != device ) {
  2599. errorText_ = "RtApiAsio::probeDeviceOpen: an ASIO duplex stream must use the same device for input and output!";
  2600. return FAILURE;
  2601. }
  2602. char driverName[32];
  2603. ASIOError result = drivers.asioGetDriverName( (int) device, driverName, 32 );
  2604. if ( result != ASE_OK ) {
  2605. errorStream_ << "RtApiAsio::probeDeviceOpen: unable to get driver name (" << getAsioErrorString( result ) << ").";
  2606. errorText_ = errorStream_.str();
  2607. return FAILURE;
  2608. }
  2609. // Only load the driver once for duplex stream.
  2610. if ( !isDuplexInput ) {
  2611. // The getDeviceInfo() function will not work when a stream is open
  2612. // because ASIO does not allow multiple devices to run at the same
  2613. // time. Thus, we'll probe the system before opening a stream and
  2614. // save the results for use by getDeviceInfo().
  2615. this->saveDeviceInfo();
  2616. if ( !drivers.loadDriver( driverName ) ) {
  2617. errorStream_ << "RtApiAsio::probeDeviceOpen: unable to load driver (" << driverName << ").";
  2618. errorText_ = errorStream_.str();
  2619. return FAILURE;
  2620. }
  2621. result = ASIOInit( &driverInfo );
  2622. if ( result != ASE_OK ) {
  2623. errorStream_ << "RtApiAsio::probeDeviceOpen: error (" << getAsioErrorString( result ) << ") initializing driver (" << driverName << ").";
  2624. errorText_ = errorStream_.str();
  2625. return FAILURE;
  2626. }
  2627. }
  2628. // keep them before any "goto error", they are used for error cleanup + goto device boundary checks
  2629. bool buffersAllocated = false;
  2630. AsioHandle *handle = (AsioHandle *) stream_.apiHandle;
  2631. unsigned int nChannels;
  2632. // Check the device channel count.
  2633. long inputChannels, outputChannels;
  2634. result = ASIOGetChannels( &inputChannels, &outputChannels );
  2635. if ( result != ASE_OK ) {
  2636. errorStream_ << "RtApiAsio::probeDeviceOpen: error (" << getAsioErrorString( result ) << ") getting channel count (" << driverName << ").";
  2637. errorText_ = errorStream_.str();
  2638. goto error;
  2639. }
  2640. if ( ( mode == OUTPUT && (channels+firstChannel) > (unsigned int) outputChannels) ||
  2641. ( mode == INPUT && (channels+firstChannel) > (unsigned int) inputChannels) ) {
  2642. errorStream_ << "RtApiAsio::probeDeviceOpen: driver (" << driverName << ") does not support requested channel count (" << channels << ") + offset (" << firstChannel << ").";
  2643. errorText_ = errorStream_.str();
  2644. goto error;
  2645. }
  2646. stream_.nDeviceChannels[mode] = channels;
  2647. stream_.nUserChannels[mode] = channels;
  2648. stream_.channelOffset[mode] = firstChannel;
  2649. // Verify the sample rate is supported.
  2650. result = ASIOCanSampleRate( (ASIOSampleRate) sampleRate );
  2651. if ( result != ASE_OK ) {
  2652. errorStream_ << "RtApiAsio::probeDeviceOpen: driver (" << driverName << ") does not support requested sample rate (" << sampleRate << ").";
  2653. errorText_ = errorStream_.str();
  2654. goto error;
  2655. }
  2656. // Get the current sample rate
  2657. ASIOSampleRate currentRate;
  2658. result = ASIOGetSampleRate( &currentRate );
  2659. if ( result != ASE_OK ) {
  2660. errorStream_ << "RtApiAsio::probeDeviceOpen: driver (" << driverName << ") error getting sample rate.";
  2661. errorText_ = errorStream_.str();
  2662. goto error;
  2663. }
  2664. // Set the sample rate only if necessary
  2665. if ( currentRate != sampleRate ) {
  2666. result = ASIOSetSampleRate( (ASIOSampleRate) sampleRate );
  2667. if ( result != ASE_OK ) {
  2668. errorStream_ << "RtApiAsio::probeDeviceOpen: driver (" << driverName << ") error setting sample rate (" << sampleRate << ").";
  2669. errorText_ = errorStream_.str();
  2670. goto error;
  2671. }
  2672. }
  2673. // Determine the driver data type.
  2674. ASIOChannelInfo channelInfo;
  2675. channelInfo.channel = 0;
  2676. if ( mode == OUTPUT ) channelInfo.isInput = false;
  2677. else channelInfo.isInput = true;
  2678. result = ASIOGetChannelInfo( &channelInfo );
  2679. if ( result != ASE_OK ) {
  2680. errorStream_ << "RtApiAsio::probeDeviceOpen: driver (" << driverName << ") error (" << getAsioErrorString( result ) << ") getting data format.";
  2681. errorText_ = errorStream_.str();
  2682. goto error;
  2683. }
  2684. // Assuming WINDOWS host is always little-endian.
  2685. stream_.doByteSwap[mode] = false;
  2686. stream_.userFormat = format;
  2687. stream_.deviceFormat[mode] = 0;
  2688. if ( channelInfo.type == ASIOSTInt16MSB || channelInfo.type == ASIOSTInt16LSB ) {
  2689. stream_.deviceFormat[mode] = RTAUDIO_SINT16;
  2690. if ( channelInfo.type == ASIOSTInt16MSB ) stream_.doByteSwap[mode] = true;
  2691. }
  2692. else if ( channelInfo.type == ASIOSTInt32MSB || channelInfo.type == ASIOSTInt32LSB ) {
  2693. stream_.deviceFormat[mode] = RTAUDIO_SINT32;
  2694. if ( channelInfo.type == ASIOSTInt32MSB ) stream_.doByteSwap[mode] = true;
  2695. }
  2696. else if ( channelInfo.type == ASIOSTFloat32MSB || channelInfo.type == ASIOSTFloat32LSB ) {
  2697. stream_.deviceFormat[mode] = RTAUDIO_FLOAT32;
  2698. if ( channelInfo.type == ASIOSTFloat32MSB ) stream_.doByteSwap[mode] = true;
  2699. }
  2700. else if ( channelInfo.type == ASIOSTFloat64MSB || channelInfo.type == ASIOSTFloat64LSB ) {
  2701. stream_.deviceFormat[mode] = RTAUDIO_FLOAT64;
  2702. if ( channelInfo.type == ASIOSTFloat64MSB ) stream_.doByteSwap[mode] = true;
  2703. }
  2704. else if ( channelInfo.type == ASIOSTInt24MSB || channelInfo.type == ASIOSTInt24LSB ) {
  2705. stream_.deviceFormat[mode] = RTAUDIO_SINT24;
  2706. if ( channelInfo.type == ASIOSTInt24MSB ) stream_.doByteSwap[mode] = true;
  2707. }
  2708. if ( stream_.deviceFormat[mode] == 0 ) {
  2709. errorStream_ << "RtApiAsio::probeDeviceOpen: driver (" << driverName << ") data format not supported by RtAudio.";
  2710. errorText_ = errorStream_.str();
  2711. goto error;
  2712. }
  2713. // Set the buffer size. For a duplex stream, this will end up
  2714. // setting the buffer size based on the input constraints, which
  2715. // should be ok.
  2716. long minSize, maxSize, preferSize, granularity;
  2717. result = ASIOGetBufferSize( &minSize, &maxSize, &preferSize, &granularity );
  2718. if ( result != ASE_OK ) {
  2719. errorStream_ << "RtApiAsio::probeDeviceOpen: driver (" << driverName << ") error (" << getAsioErrorString( result ) << ") getting buffer size.";
  2720. errorText_ = errorStream_.str();
  2721. goto error;
  2722. }
  2723. if ( isDuplexInput ) {
  2724. // When this is the duplex input (output was opened before), then we have to use the same
  2725. // buffersize as the output, because it might use the preferred buffer size, which most
  2726. // likely wasn't passed as input to this. The buffer sizes have to be identically anyway,
  2727. // So instead of throwing an error, make them equal. The caller uses the reference
  2728. // to the "bufferSize" param as usual to set up processing buffers.
  2729. *bufferSize = stream_.bufferSize;
  2730. } else {
  2731. if ( *bufferSize == 0 ) *bufferSize = preferSize;
  2732. else if ( *bufferSize < (unsigned int) minSize ) *bufferSize = (unsigned int) minSize;
  2733. else if ( *bufferSize > (unsigned int) maxSize ) *bufferSize = (unsigned int) maxSize;
  2734. else if ( granularity == -1 ) {
  2735. // Make sure bufferSize is a power of two.
  2736. int log2_of_min_size = 0;
  2737. int log2_of_max_size = 0;
  2738. for ( unsigned int i = 0; i < sizeof(long) * 8; i++ ) {
  2739. if ( minSize & ((long)1 << i) ) log2_of_min_size = i;
  2740. if ( maxSize & ((long)1 << i) ) log2_of_max_size = i;
  2741. }
  2742. long min_delta = std::abs( (long)*bufferSize - ((long)1 << log2_of_min_size) );
  2743. int min_delta_num = log2_of_min_size;
  2744. for (int i = log2_of_min_size + 1; i <= log2_of_max_size; i++) {
  2745. long current_delta = std::abs( (long)*bufferSize - ((long)1 << i) );
  2746. if (current_delta < min_delta) {
  2747. min_delta = current_delta;
  2748. min_delta_num = i;
  2749. }
  2750. }
  2751. *bufferSize = ( (unsigned int)1 << min_delta_num );
  2752. if ( *bufferSize < (unsigned int) minSize ) *bufferSize = (unsigned int) minSize;
  2753. else if ( *bufferSize > (unsigned int) maxSize ) *bufferSize = (unsigned int) maxSize;
  2754. }
  2755. else if ( granularity != 0 ) {
  2756. // Set to an even multiple of granularity, rounding up.
  2757. *bufferSize = (*bufferSize + granularity-1) / granularity * granularity;
  2758. }
  2759. }
  2760. /*
  2761. // we don't use it anymore, see above!
  2762. // Just left it here for the case...
  2763. if ( isDuplexInput && stream_.bufferSize != *bufferSize ) {
  2764. errorText_ = "RtApiAsio::probeDeviceOpen: input/output buffersize discrepancy!";
  2765. goto error;
  2766. }
  2767. */
  2768. stream_.bufferSize = *bufferSize;
  2769. stream_.nBuffers = 2;
  2770. if ( options && options->flags & RTAUDIO_NONINTERLEAVED ) stream_.userInterleaved = false;
  2771. else stream_.userInterleaved = true;
  2772. // ASIO always uses non-interleaved buffers.
  2773. stream_.deviceInterleaved[mode] = false;
  2774. // Allocate, if necessary, our AsioHandle structure for the stream.
  2775. if ( handle == 0 ) {
  2776. try {
  2777. handle = new AsioHandle;
  2778. }
  2779. catch ( std::bad_alloc& ) {
  2780. errorText_ = "RtApiAsio::probeDeviceOpen: error allocating AsioHandle memory.";
  2781. goto error;
  2782. }
  2783. handle->bufferInfos = 0;
  2784. // Create a manual-reset event.
  2785. handle->condition = CreateEvent( NULL, // no security
  2786. TRUE, // manual-reset
  2787. FALSE, // non-signaled initially
  2788. NULL ); // unnamed
  2789. stream_.apiHandle = (void *) handle;
  2790. }
  2791. // Create the ASIO internal buffers. Since RtAudio sets up input
  2792. // and output separately, we'll have to dispose of previously
  2793. // created output buffers for a duplex stream.
  2794. if ( mode == INPUT && stream_.mode == OUTPUT ) {
  2795. ASIODisposeBuffers();
  2796. if ( handle->bufferInfos ) free( handle->bufferInfos );
  2797. }
  2798. // Allocate, initialize, and save the bufferInfos in our stream callbackInfo structure.
  2799. unsigned int i;
  2800. nChannels = stream_.nDeviceChannels[0] + stream_.nDeviceChannels[1];
  2801. handle->bufferInfos = (ASIOBufferInfo *) malloc( nChannels * sizeof(ASIOBufferInfo) );
  2802. if ( handle->bufferInfos == NULL ) {
  2803. errorStream_ << "RtApiAsio::probeDeviceOpen: error allocating bufferInfo memory for driver (" << driverName << ").";
  2804. errorText_ = errorStream_.str();
  2805. goto error;
  2806. }
  2807. ASIOBufferInfo *infos;
  2808. infos = handle->bufferInfos;
  2809. for ( i=0; i<stream_.nDeviceChannels[0]; i++, infos++ ) {
  2810. infos->isInput = ASIOFalse;
  2811. infos->channelNum = i + stream_.channelOffset[0];
  2812. infos->buffers[0] = infos->buffers[1] = 0;
  2813. }
  2814. for ( i=0; i<stream_.nDeviceChannels[1]; i++, infos++ ) {
  2815. infos->isInput = ASIOTrue;
  2816. infos->channelNum = i + stream_.channelOffset[1];
  2817. infos->buffers[0] = infos->buffers[1] = 0;
  2818. }
  2819. // prepare for callbacks
  2820. stream_.sampleRate = sampleRate;
  2821. stream_.device[mode] = device;
  2822. stream_.mode = isDuplexInput ? DUPLEX : mode;
  2823. // store this class instance before registering callbacks, that are going to use it
  2824. asioCallbackInfo = &stream_.callbackInfo;
  2825. stream_.callbackInfo.object = (void *) this;
  2826. // Set up the ASIO callback structure and create the ASIO data buffers.
  2827. asioCallbacks.bufferSwitch = &bufferSwitch;
  2828. asioCallbacks.sampleRateDidChange = &sampleRateChanged;
  2829. asioCallbacks.asioMessage = &asioMessages;
  2830. asioCallbacks.bufferSwitchTimeInfo = NULL;
  2831. result = ASIOCreateBuffers( handle->bufferInfos, nChannels, stream_.bufferSize, &asioCallbacks );
  2832. if ( result != ASE_OK ) {
  2833. // Standard method failed. This can happen with strict/misbehaving drivers that return valid buffer size ranges
  2834. // but only accept the preferred buffer size as parameter for ASIOCreateBuffers (e.g. Creative's ASIO driver).
  2835. // In that case, let's be naïve and try that instead.
  2836. *bufferSize = preferSize;
  2837. stream_.bufferSize = *bufferSize;
  2838. result = ASIOCreateBuffers( handle->bufferInfos, nChannels, stream_.bufferSize, &asioCallbacks );
  2839. }
  2840. if ( result != ASE_OK ) {
  2841. errorStream_ << "RtApiAsio::probeDeviceOpen: driver (" << driverName << ") error (" << getAsioErrorString( result ) << ") creating buffers.";
  2842. errorText_ = errorStream_.str();
  2843. goto error;
  2844. }
  2845. buffersAllocated = true;
  2846. stream_.state = STREAM_STOPPED;
  2847. // Set flags for buffer conversion.
  2848. stream_.doConvertBuffer[mode] = false;
  2849. if ( stream_.userFormat != stream_.deviceFormat[mode] )
  2850. stream_.doConvertBuffer[mode] = true;
  2851. if ( stream_.userInterleaved != stream_.deviceInterleaved[mode] &&
  2852. stream_.nUserChannels[mode] > 1 )
  2853. stream_.doConvertBuffer[mode] = true;
  2854. // Allocate necessary internal buffers
  2855. unsigned long bufferBytes;
  2856. bufferBytes = stream_.nUserChannels[mode] * *bufferSize * formatBytes( stream_.userFormat );
  2857. stream_.userBuffer[mode] = (char *) calloc( bufferBytes, 1 );
  2858. if ( stream_.userBuffer[mode] == NULL ) {
  2859. errorText_ = "RtApiAsio::probeDeviceOpen: error allocating user buffer memory.";
  2860. goto error;
  2861. }
  2862. if ( stream_.doConvertBuffer[mode] ) {
  2863. bool makeBuffer = true;
  2864. bufferBytes = stream_.nDeviceChannels[mode] * formatBytes( stream_.deviceFormat[mode] );
  2865. if ( isDuplexInput && stream_.deviceBuffer ) {
  2866. unsigned long bytesOut = stream_.nDeviceChannels[0] * formatBytes( stream_.deviceFormat[0] );
  2867. if ( bufferBytes <= bytesOut ) makeBuffer = false;
  2868. }
  2869. if ( makeBuffer ) {
  2870. bufferBytes *= *bufferSize;
  2871. if ( stream_.deviceBuffer ) free( stream_.deviceBuffer );
  2872. stream_.deviceBuffer = (char *) calloc( bufferBytes, 1 );
  2873. if ( stream_.deviceBuffer == NULL ) {
  2874. errorText_ = "RtApiAsio::probeDeviceOpen: error allocating device buffer memory.";
  2875. goto error;
  2876. }
  2877. }
  2878. }
  2879. // Determine device latencies
  2880. long inputLatency, outputLatency;
  2881. result = ASIOGetLatencies( &inputLatency, &outputLatency );
  2882. if ( result != ASE_OK ) {
  2883. errorStream_ << "RtApiAsio::probeDeviceOpen: driver (" << driverName << ") error (" << getAsioErrorString( result ) << ") getting latency.";
  2884. errorText_ = errorStream_.str();
  2885. error( RtAudioError::WARNING); // warn but don't fail
  2886. }
  2887. else {
  2888. stream_.latency[0] = outputLatency;
  2889. stream_.latency[1] = inputLatency;
  2890. }
  2891. // Setup the buffer conversion information structure. We don't use
  2892. // buffers to do channel offsets, so we override that parameter
  2893. // here.
  2894. if ( stream_.doConvertBuffer[mode] ) setConvertInfo( mode, 0 );
  2895. return SUCCESS;
  2896. error:
  2897. if ( !isDuplexInput ) {
  2898. // the cleanup for error in the duplex input, is done by RtApi::openStream
  2899. // So we clean up for single channel only
  2900. if ( buffersAllocated )
  2901. ASIODisposeBuffers();
  2902. drivers.removeCurrentDriver();
  2903. if ( handle ) {
  2904. CloseHandle( handle->condition );
  2905. if ( handle->bufferInfos )
  2906. free( handle->bufferInfos );
  2907. delete handle;
  2908. stream_.apiHandle = 0;
  2909. }
  2910. if ( stream_.userBuffer[mode] ) {
  2911. free( stream_.userBuffer[mode] );
  2912. stream_.userBuffer[mode] = 0;
  2913. }
  2914. if ( stream_.deviceBuffer ) {
  2915. free( stream_.deviceBuffer );
  2916. stream_.deviceBuffer = 0;
  2917. }
  2918. }
  2919. return FAILURE;
  2920. }////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  2921. void RtApiAsio :: closeStream()
  2922. {
  2923. if ( stream_.state == STREAM_CLOSED ) {
  2924. errorText_ = "RtApiAsio::closeStream(): no open stream to close!";
  2925. error( RtAudioError::WARNING );
  2926. return;
  2927. }
  2928. if ( stream_.state == STREAM_RUNNING ) {
  2929. stream_.state = STREAM_STOPPED;
  2930. ASIOStop();
  2931. }
  2932. ASIODisposeBuffers();
  2933. drivers.removeCurrentDriver();
  2934. AsioHandle *handle = (AsioHandle *) stream_.apiHandle;
  2935. if ( handle ) {
  2936. CloseHandle( handle->condition );
  2937. if ( handle->bufferInfos )
  2938. free( handle->bufferInfos );
  2939. delete handle;
  2940. stream_.apiHandle = 0;
  2941. }
  2942. for ( int i=0; i<2; i++ ) {
  2943. if ( stream_.userBuffer[i] ) {
  2944. free( stream_.userBuffer[i] );
  2945. stream_.userBuffer[i] = 0;
  2946. }
  2947. }
  2948. if ( stream_.deviceBuffer ) {
  2949. free( stream_.deviceBuffer );
  2950. stream_.deviceBuffer = 0;
  2951. }
  2952. stream_.mode = UNINITIALIZED;
  2953. stream_.state = STREAM_CLOSED;
  2954. }
  2955. bool stopThreadCalled = false;
  2956. void RtApiAsio :: startStream()
  2957. {
  2958. verifyStream();
  2959. if ( stream_.state == STREAM_RUNNING ) {
  2960. errorText_ = "RtApiAsio::startStream(): the stream is already running!";
  2961. error( RtAudioError::WARNING );
  2962. return;
  2963. }
  2964. #if defined( HAVE_GETTIMEOFDAY )
  2965. gettimeofday( &stream_.lastTickTimestamp, NULL );
  2966. #endif
  2967. AsioHandle *handle = (AsioHandle *) stream_.apiHandle;
  2968. ASIOError result = ASIOStart();
  2969. if ( result != ASE_OK ) {
  2970. errorStream_ << "RtApiAsio::startStream: error (" << getAsioErrorString( result ) << ") starting device.";
  2971. errorText_ = errorStream_.str();
  2972. goto unlock;
  2973. }
  2974. handle->drainCounter = 0;
  2975. handle->internalDrain = false;
  2976. ResetEvent( handle->condition );
  2977. stream_.state = STREAM_RUNNING;
  2978. asioXRun = false;
  2979. unlock:
  2980. stopThreadCalled = false;
  2981. if ( result == ASE_OK ) return;
  2982. error( RtAudioError::SYSTEM_ERROR );
  2983. }
  2984. void RtApiAsio :: stopStream()
  2985. {
  2986. verifyStream();
  2987. if ( stream_.state == STREAM_STOPPED ) {
  2988. errorText_ = "RtApiAsio::stopStream(): the stream is already stopped!";
  2989. error( RtAudioError::WARNING );
  2990. return;
  2991. }
  2992. AsioHandle *handle = (AsioHandle *) stream_.apiHandle;
  2993. if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) {
  2994. if ( handle->drainCounter == 0 ) {
  2995. handle->drainCounter = 2;
  2996. WaitForSingleObject( handle->condition, INFINITE ); // block until signaled
  2997. }
  2998. }
  2999. stream_.state = STREAM_STOPPED;
  3000. ASIOError result = ASIOStop();
  3001. if ( result != ASE_OK ) {
  3002. errorStream_ << "RtApiAsio::stopStream: error (" << getAsioErrorString( result ) << ") stopping device.";
  3003. errorText_ = errorStream_.str();
  3004. }
  3005. if ( result == ASE_OK ) return;
  3006. error( RtAudioError::SYSTEM_ERROR );
  3007. }
  3008. void RtApiAsio :: abortStream()
  3009. {
  3010. verifyStream();
  3011. if ( stream_.state == STREAM_STOPPED ) {
  3012. errorText_ = "RtApiAsio::abortStream(): the stream is already stopped!";
  3013. error( RtAudioError::WARNING );
  3014. return;
  3015. }
  3016. // The following lines were commented-out because some behavior was
  3017. // noted where the device buffers need to be zeroed to avoid
  3018. // continuing sound, even when the device buffers are completely
  3019. // disposed. So now, calling abort is the same as calling stop.
  3020. // AsioHandle *handle = (AsioHandle *) stream_.apiHandle;
  3021. // handle->drainCounter = 2;
  3022. stopStream();
  3023. }
  3024. // This function will be called by a spawned thread when the user
  3025. // callback function signals that the stream should be stopped or
  3026. // aborted. It is necessary to handle it this way because the
  3027. // callbackEvent() function must return before the ASIOStop()
  3028. // function will return.
  3029. static unsigned __stdcall asioStopStream( void *ptr )
  3030. {
  3031. CallbackInfo *info = (CallbackInfo *) ptr;
  3032. RtApiAsio *object = (RtApiAsio *) info->object;
  3033. object->stopStream();
  3034. _endthreadex( 0 );
  3035. return 0;
  3036. }
  3037. bool RtApiAsio :: callbackEvent( long bufferIndex )
  3038. {
  3039. if ( stream_.state == STREAM_STOPPED || stream_.state == STREAM_STOPPING ) return SUCCESS;
  3040. if ( stream_.state == STREAM_CLOSED ) {
  3041. errorText_ = "RtApiAsio::callbackEvent(): the stream is closed ... this shouldn't happen!";
  3042. error( RtAudioError::WARNING );
  3043. return FAILURE;
  3044. }
  3045. CallbackInfo *info = (CallbackInfo *) &stream_.callbackInfo;
  3046. AsioHandle *handle = (AsioHandle *) stream_.apiHandle;
  3047. // Check if we were draining the stream and signal if finished.
  3048. if ( handle->drainCounter > 3 ) {
  3049. stream_.state = STREAM_STOPPING;
  3050. if ( handle->internalDrain == false )
  3051. SetEvent( handle->condition );
  3052. else { // spawn a thread to stop the stream
  3053. unsigned threadId;
  3054. stream_.callbackInfo.thread = _beginthreadex( NULL, 0, &asioStopStream,
  3055. &stream_.callbackInfo, 0, &threadId );
  3056. }
  3057. return SUCCESS;
  3058. }
  3059. // Invoke user callback to get fresh output data UNLESS we are
  3060. // draining stream.
  3061. if ( handle->drainCounter == 0 ) {
  3062. RtAudioCallback callback = (RtAudioCallback) info->callback;
  3063. double streamTime = getStreamTime();
  3064. RtAudioStreamStatus status = 0;
  3065. if ( stream_.mode != INPUT && asioXRun == true ) {
  3066. status |= RTAUDIO_OUTPUT_UNDERFLOW;
  3067. asioXRun = false;
  3068. }
  3069. if ( stream_.mode != OUTPUT && asioXRun == true ) {
  3070. status |= RTAUDIO_INPUT_OVERFLOW;
  3071. asioXRun = false;
  3072. }
  3073. int cbReturnValue = callback( stream_.userBuffer[0], stream_.userBuffer[1],
  3074. stream_.bufferSize, streamTime, status, info->userData );
  3075. if ( cbReturnValue == 2 ) {
  3076. stream_.state = STREAM_STOPPING;
  3077. handle->drainCounter = 2;
  3078. unsigned threadId;
  3079. stream_.callbackInfo.thread = _beginthreadex( NULL, 0, &asioStopStream,
  3080. &stream_.callbackInfo, 0, &threadId );
  3081. return SUCCESS;
  3082. }
  3083. else if ( cbReturnValue == 1 ) {
  3084. handle->drainCounter = 1;
  3085. handle->internalDrain = true;
  3086. }
  3087. }
  3088. unsigned int nChannels, bufferBytes, i, j;
  3089. nChannels = stream_.nDeviceChannels[0] + stream_.nDeviceChannels[1];
  3090. if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) {
  3091. bufferBytes = stream_.bufferSize * formatBytes( stream_.deviceFormat[0] );
  3092. if ( handle->drainCounter > 1 ) { // write zeros to the output stream
  3093. for ( i=0, j=0; i<nChannels; i++ ) {
  3094. if ( handle->bufferInfos[i].isInput != ASIOTrue )
  3095. memset( handle->bufferInfos[i].buffers[bufferIndex], 0, bufferBytes );
  3096. }
  3097. }
  3098. else if ( stream_.doConvertBuffer[0] ) {
  3099. convertBuffer( stream_.deviceBuffer, stream_.userBuffer[0], stream_.convertInfo[0] );
  3100. if ( stream_.doByteSwap[0] )
  3101. byteSwapBuffer( stream_.deviceBuffer,
  3102. stream_.bufferSize * stream_.nDeviceChannels[0],
  3103. stream_.deviceFormat[0] );
  3104. for ( i=0, j=0; i<nChannels; i++ ) {
  3105. if ( handle->bufferInfos[i].isInput != ASIOTrue )
  3106. memcpy( handle->bufferInfos[i].buffers[bufferIndex],
  3107. &stream_.deviceBuffer[j++*bufferBytes], bufferBytes );
  3108. }
  3109. }
  3110. else {
  3111. if ( stream_.doByteSwap[0] )
  3112. byteSwapBuffer( stream_.userBuffer[0],
  3113. stream_.bufferSize * stream_.nUserChannels[0],
  3114. stream_.userFormat );
  3115. for ( i=0, j=0; i<nChannels; i++ ) {
  3116. if ( handle->bufferInfos[i].isInput != ASIOTrue )
  3117. memcpy( handle->bufferInfos[i].buffers[bufferIndex],
  3118. &stream_.userBuffer[0][bufferBytes*j++], bufferBytes );
  3119. }
  3120. }
  3121. }
  3122. // Don't bother draining input
  3123. if ( handle->drainCounter ) {
  3124. handle->drainCounter++;
  3125. goto unlock;
  3126. }
  3127. if ( stream_.mode == INPUT || stream_.mode == DUPLEX ) {
  3128. bufferBytes = stream_.bufferSize * formatBytes(stream_.deviceFormat[1]);
  3129. if (stream_.doConvertBuffer[1]) {
  3130. // Always interleave ASIO input data.
  3131. for ( i=0, j=0; i<nChannels; i++ ) {
  3132. if ( handle->bufferInfos[i].isInput == ASIOTrue )
  3133. memcpy( &stream_.deviceBuffer[j++*bufferBytes],
  3134. handle->bufferInfos[i].buffers[bufferIndex],
  3135. bufferBytes );
  3136. }
  3137. if ( stream_.doByteSwap[1] )
  3138. byteSwapBuffer( stream_.deviceBuffer,
  3139. stream_.bufferSize * stream_.nDeviceChannels[1],
  3140. stream_.deviceFormat[1] );
  3141. convertBuffer( stream_.userBuffer[1], stream_.deviceBuffer, stream_.convertInfo[1] );
  3142. }
  3143. else {
  3144. for ( i=0, j=0; i<nChannels; i++ ) {
  3145. if ( handle->bufferInfos[i].isInput == ASIOTrue ) {
  3146. memcpy( &stream_.userBuffer[1][bufferBytes*j++],
  3147. handle->bufferInfos[i].buffers[bufferIndex],
  3148. bufferBytes );
  3149. }
  3150. }
  3151. if ( stream_.doByteSwap[1] )
  3152. byteSwapBuffer( stream_.userBuffer[1],
  3153. stream_.bufferSize * stream_.nUserChannels[1],
  3154. stream_.userFormat );
  3155. }
  3156. }
  3157. unlock:
  3158. // The following call was suggested by Malte Clasen. While the API
  3159. // documentation indicates it should not be required, some device
  3160. // drivers apparently do not function correctly without it.
  3161. ASIOOutputReady();
  3162. RtApi::tickStreamTime();
  3163. return SUCCESS;
  3164. }
  3165. static void sampleRateChanged( ASIOSampleRate sRate )
  3166. {
  3167. // The ASIO documentation says that this usually only happens during
  3168. // external sync. Audio processing is not stopped by the driver,
  3169. // actual sample rate might not have even changed, maybe only the
  3170. // sample rate status of an AES/EBU or S/PDIF digital input at the
  3171. // audio device.
  3172. RtApi *object = (RtApi *) asioCallbackInfo->object;
  3173. try {
  3174. object->stopStream();
  3175. }
  3176. catch ( RtAudioError &exception ) {
  3177. std::cerr << "\nRtApiAsio: sampleRateChanged() error (" << exception.getMessage() << ")!\n" << std::endl;
  3178. return;
  3179. }
  3180. std::cerr << "\nRtApiAsio: driver reports sample rate changed to " << sRate << " ... stream stopped!!!\n" << std::endl;
  3181. }
  3182. static long asioMessages( long selector, long value, void* /*message*/, double* /*opt*/ )
  3183. {
  3184. long ret = 0;
  3185. switch( selector ) {
  3186. case kAsioSelectorSupported:
  3187. if ( value == kAsioResetRequest
  3188. || value == kAsioEngineVersion
  3189. || value == kAsioResyncRequest
  3190. || value == kAsioLatenciesChanged
  3191. // The following three were added for ASIO 2.0, you don't
  3192. // necessarily have to support them.
  3193. || value == kAsioSupportsTimeInfo
  3194. || value == kAsioSupportsTimeCode
  3195. || value == kAsioSupportsInputMonitor)
  3196. ret = 1L;
  3197. break;
  3198. case kAsioResetRequest:
  3199. // Defer the task and perform the reset of the driver during the
  3200. // next "safe" situation. You cannot reset the driver right now,
  3201. // as this code is called from the driver. Reset the driver is
  3202. // done by completely destruct is. I.e. ASIOStop(),
  3203. // ASIODisposeBuffers(), Destruction Afterwards you initialize the
  3204. // driver again.
  3205. std::cerr << "\nRtApiAsio: driver reset requested!!!" << std::endl;
  3206. ret = 1L;
  3207. break;
  3208. case kAsioResyncRequest:
  3209. // This informs the application that the driver encountered some
  3210. // non-fatal data loss. It is used for synchronization purposes
  3211. // of different media. Added mainly to work around the Win16Mutex
  3212. // problems in Windows 95/98 with the Windows Multimedia system,
  3213. // which could lose data because the Mutex was held too long by
  3214. // another thread. However a driver can issue it in other
  3215. // situations, too.
  3216. // std::cerr << "\nRtApiAsio: driver resync requested!!!" << std::endl;
  3217. asioXRun = true;
  3218. ret = 1L;
  3219. break;
  3220. case kAsioLatenciesChanged:
  3221. // This will inform the host application that the drivers were
  3222. // latencies changed. Beware, it this does not mean that the
  3223. // buffer sizes have changed! You might need to update internal
  3224. // delay data.
  3225. std::cerr << "\nRtApiAsio: driver latency may have changed!!!" << std::endl;
  3226. ret = 1L;
  3227. break;
  3228. case kAsioEngineVersion:
  3229. // Return the supported ASIO version of the host application. If
  3230. // a host application does not implement this selector, ASIO 1.0
  3231. // is assumed by the driver.
  3232. ret = 2L;
  3233. break;
  3234. case kAsioSupportsTimeInfo:
  3235. // Informs the driver whether the
  3236. // asioCallbacks.bufferSwitchTimeInfo() callback is supported.
  3237. // For compatibility with ASIO 1.0 drivers the host application
  3238. // should always support the "old" bufferSwitch method, too.
  3239. ret = 0;
  3240. break;
  3241. case kAsioSupportsTimeCode:
  3242. // Informs the driver whether application is interested in time
  3243. // code info. If an application does not need to know about time
  3244. // code, the driver has less work to do.
  3245. ret = 0;
  3246. break;
  3247. }
  3248. return ret;
  3249. }
  3250. static const char* getAsioErrorString( ASIOError result )
  3251. {
  3252. struct Messages
  3253. {
  3254. ASIOError value;
  3255. const char*message;
  3256. };
  3257. static const Messages m[] =
  3258. {
  3259. { ASE_NotPresent, "Hardware input or output is not present or available." },
  3260. { ASE_HWMalfunction, "Hardware is malfunctioning." },
  3261. { ASE_InvalidParameter, "Invalid input parameter." },
  3262. { ASE_InvalidMode, "Invalid mode." },
  3263. { ASE_SPNotAdvancing, "Sample position not advancing." },
  3264. { ASE_NoClock, "Sample clock or rate cannot be determined or is not present." },
  3265. { ASE_NoMemory, "Not enough memory to complete the request." }
  3266. };
  3267. for ( unsigned int i = 0; i < sizeof(m)/sizeof(m[0]); ++i )
  3268. if ( m[i].value == result ) return m[i].message;
  3269. return "Unknown error.";
  3270. }
  3271. //******************** End of __WINDOWS_ASIO__ *********************//
  3272. #endif
  3273. #if defined(__WINDOWS_WASAPI__) // Windows WASAPI API
  3274. // Authored by Marcus Tomlinson <[email protected]>, April 2014
  3275. // - Introduces support for the Windows WASAPI API
  3276. // - Aims to deliver bit streams to and from hardware at the lowest possible latency, via the absolute minimum buffer sizes required
  3277. // - Provides flexible stream configuration to an otherwise strict and inflexible WASAPI interface
  3278. // - Includes automatic internal conversion of sample rate and buffer size between hardware and the user
  3279. #ifndef INITGUID
  3280. #define INITGUID
  3281. #endif
  3282. #include <mfapi.h>
  3283. #include <mferror.h>
  3284. #include <mfplay.h>
  3285. #include <mftransform.h>
  3286. #include <wmcodecdsp.h>
  3287. #include <audioclient.h>
  3288. #include <avrt.h>
  3289. #include <mmdeviceapi.h>
  3290. #include <functiondiscoverykeys_devpkey.h>
  3291. #ifndef MF_E_TRANSFORM_NEED_MORE_INPUT
  3292. #define MF_E_TRANSFORM_NEED_MORE_INPUT _HRESULT_TYPEDEF_(0xc00d6d72)
  3293. #endif
  3294. #ifndef MFSTARTUP_NOSOCKET
  3295. #define MFSTARTUP_NOSOCKET 0x1
  3296. #endif
  3297. #ifdef _MSC_VER
  3298. #pragma comment( lib, "ksuser" )
  3299. #pragma comment( lib, "mfplat.lib" )
  3300. #pragma comment( lib, "mfuuid.lib" )
  3301. #pragma comment( lib, "wmcodecdspuuid" )
  3302. #endif
  3303. //=============================================================================
  3304. #define SAFE_RELEASE( objectPtr )\
  3305. if ( objectPtr )\
  3306. {\
  3307. objectPtr->Release();\
  3308. objectPtr = NULL;\
  3309. }
  3310. typedef HANDLE ( __stdcall *TAvSetMmThreadCharacteristicsPtr )( LPCWSTR TaskName, LPDWORD TaskIndex );
  3311. #ifndef __IAudioClient3_INTERFACE_DEFINED__
  3312. MIDL_INTERFACE( "00000000-0000-0000-0000-000000000000" ) IAudioClient3
  3313. {
  3314. virtual HRESULT GetSharedModeEnginePeriod( WAVEFORMATEX*, UINT32*, UINT32*, UINT32*, UINT32* ) = 0;
  3315. virtual HRESULT InitializeSharedAudioStream( DWORD, UINT32, WAVEFORMATEX*, LPCGUID ) = 0;
  3316. };
  3317. #ifdef __CRT_UUID_DECL
  3318. __CRT_UUID_DECL( IAudioClient3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 )
  3319. #endif
  3320. #endif
  3321. //-----------------------------------------------------------------------------
  3322. // WASAPI dictates stream sample rate, format, channel count, and in some cases, buffer size.
  3323. // Therefore we must perform all necessary conversions to user buffers in order to satisfy these
  3324. // requirements. WasapiBuffer ring buffers are used between HwIn->UserIn and UserOut->HwOut to
  3325. // provide intermediate storage for read / write synchronization.
  3326. class WasapiBuffer
  3327. {
  3328. public:
  3329. WasapiBuffer()
  3330. : buffer_( NULL ),
  3331. bufferSize_( 0 ),
  3332. inIndex_( 0 ),
  3333. outIndex_( 0 ) {}
  3334. ~WasapiBuffer() {
  3335. free( buffer_ );
  3336. }
  3337. // sets the length of the internal ring buffer
  3338. void setBufferSize( unsigned int bufferSize, unsigned int formatBytes ) {
  3339. free( buffer_ );
  3340. buffer_ = ( char* ) calloc( bufferSize, formatBytes );
  3341. bufferSize_ = bufferSize;
  3342. inIndex_ = 0;
  3343. outIndex_ = 0;
  3344. }
  3345. // attempt to push a buffer into the ring buffer at the current "in" index
  3346. bool pushBuffer( char* buffer, unsigned int bufferSize, RtAudioFormat format )
  3347. {
  3348. if ( !buffer || // incoming buffer is NULL
  3349. bufferSize == 0 || // incoming buffer has no data
  3350. bufferSize > bufferSize_ ) // incoming buffer too large
  3351. {
  3352. return false;
  3353. }
  3354. unsigned int relOutIndex = outIndex_;
  3355. unsigned int inIndexEnd = inIndex_ + bufferSize;
  3356. if ( relOutIndex < inIndex_ && inIndexEnd >= bufferSize_ ) {
  3357. relOutIndex += bufferSize_;
  3358. }
  3359. // the "IN" index CAN BEGIN at the "OUT" index
  3360. // the "IN" index CANNOT END at the "OUT" index
  3361. if ( inIndex_ < relOutIndex && inIndexEnd >= relOutIndex ) {
  3362. return false; // not enough space between "in" index and "out" index
  3363. }
  3364. // copy buffer from external to internal
  3365. int fromZeroSize = inIndex_ + bufferSize - bufferSize_;
  3366. fromZeroSize = fromZeroSize < 0 ? 0 : fromZeroSize;
  3367. int fromInSize = bufferSize - fromZeroSize;
  3368. switch( format )
  3369. {
  3370. case RTAUDIO_SINT8:
  3371. memcpy( &( ( char* ) buffer_ )[inIndex_], buffer, fromInSize * sizeof( char ) );
  3372. memcpy( buffer_, &( ( char* ) buffer )[fromInSize], fromZeroSize * sizeof( char ) );
  3373. break;
  3374. case RTAUDIO_SINT16:
  3375. memcpy( &( ( short* ) buffer_ )[inIndex_], buffer, fromInSize * sizeof( short ) );
  3376. memcpy( buffer_, &( ( short* ) buffer )[fromInSize], fromZeroSize * sizeof( short ) );
  3377. break;
  3378. case RTAUDIO_SINT24:
  3379. memcpy( &( ( S24* ) buffer_ )[inIndex_], buffer, fromInSize * sizeof( S24 ) );
  3380. memcpy( buffer_, &( ( S24* ) buffer )[fromInSize], fromZeroSize * sizeof( S24 ) );
  3381. break;
  3382. case RTAUDIO_SINT32:
  3383. memcpy( &( ( int* ) buffer_ )[inIndex_], buffer, fromInSize * sizeof( int ) );
  3384. memcpy( buffer_, &( ( int* ) buffer )[fromInSize], fromZeroSize * sizeof( int ) );
  3385. break;
  3386. case RTAUDIO_FLOAT32:
  3387. memcpy( &( ( float* ) buffer_ )[inIndex_], buffer, fromInSize * sizeof( float ) );
  3388. memcpy( buffer_, &( ( float* ) buffer )[fromInSize], fromZeroSize * sizeof( float ) );
  3389. break;
  3390. case RTAUDIO_FLOAT64:
  3391. memcpy( &( ( double* ) buffer_ )[inIndex_], buffer, fromInSize * sizeof( double ) );
  3392. memcpy( buffer_, &( ( double* ) buffer )[fromInSize], fromZeroSize * sizeof( double ) );
  3393. break;
  3394. }
  3395. // update "in" index
  3396. inIndex_ += bufferSize;
  3397. inIndex_ %= bufferSize_;
  3398. return true;
  3399. }
  3400. // attempt to pull a buffer from the ring buffer from the current "out" index
  3401. bool pullBuffer( char* buffer, unsigned int bufferSize, RtAudioFormat format )
  3402. {
  3403. if ( !buffer || // incoming buffer is NULL
  3404. bufferSize == 0 || // incoming buffer has no data
  3405. bufferSize > bufferSize_ ) // incoming buffer too large
  3406. {
  3407. return false;
  3408. }
  3409. unsigned int relInIndex = inIndex_;
  3410. unsigned int outIndexEnd = outIndex_ + bufferSize;
  3411. if ( relInIndex < outIndex_ && outIndexEnd >= bufferSize_ ) {
  3412. relInIndex += bufferSize_;
  3413. }
  3414. // the "OUT" index CANNOT BEGIN at the "IN" index
  3415. // the "OUT" index CAN END at the "IN" index
  3416. if ( outIndex_ <= relInIndex && outIndexEnd > relInIndex ) {
  3417. return false; // not enough space between "out" index and "in" index
  3418. }
  3419. // copy buffer from internal to external
  3420. int fromZeroSize = outIndex_ + bufferSize - bufferSize_;
  3421. fromZeroSize = fromZeroSize < 0 ? 0 : fromZeroSize;
  3422. int fromOutSize = bufferSize - fromZeroSize;
  3423. switch( format )
  3424. {
  3425. case RTAUDIO_SINT8:
  3426. memcpy( buffer, &( ( char* ) buffer_ )[outIndex_], fromOutSize * sizeof( char ) );
  3427. memcpy( &( ( char* ) buffer )[fromOutSize], buffer_, fromZeroSize * sizeof( char ) );
  3428. break;
  3429. case RTAUDIO_SINT16:
  3430. memcpy( buffer, &( ( short* ) buffer_ )[outIndex_], fromOutSize * sizeof( short ) );
  3431. memcpy( &( ( short* ) buffer )[fromOutSize], buffer_, fromZeroSize * sizeof( short ) );
  3432. break;
  3433. case RTAUDIO_SINT24:
  3434. memcpy( buffer, &( ( S24* ) buffer_ )[outIndex_], fromOutSize * sizeof( S24 ) );
  3435. memcpy( &( ( S24* ) buffer )[fromOutSize], buffer_, fromZeroSize * sizeof( S24 ) );
  3436. break;
  3437. case RTAUDIO_SINT32:
  3438. memcpy( buffer, &( ( int* ) buffer_ )[outIndex_], fromOutSize * sizeof( int ) );
  3439. memcpy( &( ( int* ) buffer )[fromOutSize], buffer_, fromZeroSize * sizeof( int ) );
  3440. break;
  3441. case RTAUDIO_FLOAT32:
  3442. memcpy( buffer, &( ( float* ) buffer_ )[outIndex_], fromOutSize * sizeof( float ) );
  3443. memcpy( &( ( float* ) buffer )[fromOutSize], buffer_, fromZeroSize * sizeof( float ) );
  3444. break;
  3445. case RTAUDIO_FLOAT64:
  3446. memcpy( buffer, &( ( double* ) buffer_ )[outIndex_], fromOutSize * sizeof( double ) );
  3447. memcpy( &( ( double* ) buffer )[fromOutSize], buffer_, fromZeroSize * sizeof( double ) );
  3448. break;
  3449. }
  3450. // update "out" index
  3451. outIndex_ += bufferSize;
  3452. outIndex_ %= bufferSize_;
  3453. return true;
  3454. }
  3455. private:
  3456. char* buffer_;
  3457. unsigned int bufferSize_;
  3458. unsigned int inIndex_;
  3459. unsigned int outIndex_;
  3460. };
  3461. //-----------------------------------------------------------------------------
  3462. // In order to satisfy WASAPI's buffer requirements, we need a means of converting sample rate
  3463. // between HW and the user. The WasapiResampler class is used to perform this conversion between
  3464. // HwIn->UserIn and UserOut->HwOut during the stream callback loop.
  3465. class WasapiResampler
  3466. {
  3467. public:
  3468. WasapiResampler( bool isFloat, unsigned int bitsPerSample, unsigned int channelCount,
  3469. unsigned int inSampleRate, unsigned int outSampleRate )
  3470. : _bytesPerSample( bitsPerSample / 8 )
  3471. , _channelCount( channelCount )
  3472. , _sampleRatio( ( float ) outSampleRate / inSampleRate )
  3473. , _transformUnk( NULL )
  3474. , _transform( NULL )
  3475. , _mediaType( NULL )
  3476. , _inputMediaType( NULL )
  3477. , _outputMediaType( NULL )
  3478. #ifdef __IWMResamplerProps_FWD_DEFINED__
  3479. , _resamplerProps( NULL )
  3480. #endif
  3481. {
  3482. // 1. Initialization
  3483. MFStartup( MF_VERSION, MFSTARTUP_NOSOCKET );
  3484. // 2. Create Resampler Transform Object
  3485. CoCreateInstance( CLSID_CResamplerMediaObject, NULL, CLSCTX_INPROC_SERVER,
  3486. IID_IUnknown, ( void** ) &_transformUnk );
  3487. _transformUnk->QueryInterface( IID_PPV_ARGS( &_transform ) );
  3488. #ifdef __IWMResamplerProps_FWD_DEFINED__
  3489. _transformUnk->QueryInterface( IID_PPV_ARGS( &_resamplerProps ) );
  3490. _resamplerProps->SetHalfFilterLength( 60 ); // best conversion quality
  3491. #endif
  3492. // 3. Specify input / output format
  3493. MFCreateMediaType( &_mediaType );
  3494. _mediaType->SetGUID( MF_MT_MAJOR_TYPE, MFMediaType_Audio );
  3495. _mediaType->SetGUID( MF_MT_SUBTYPE, isFloat ? MFAudioFormat_Float : MFAudioFormat_PCM );
  3496. _mediaType->SetUINT32( MF_MT_AUDIO_NUM_CHANNELS, channelCount );
  3497. _mediaType->SetUINT32( MF_MT_AUDIO_SAMPLES_PER_SECOND, inSampleRate );
  3498. _mediaType->SetUINT32( MF_MT_AUDIO_BLOCK_ALIGNMENT, _bytesPerSample * channelCount );
  3499. _mediaType->SetUINT32( MF_MT_AUDIO_AVG_BYTES_PER_SECOND, _bytesPerSample * channelCount * inSampleRate );
  3500. _mediaType->SetUINT32( MF_MT_AUDIO_BITS_PER_SAMPLE, bitsPerSample );
  3501. _mediaType->SetUINT32( MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE );
  3502. MFCreateMediaType( &_inputMediaType );
  3503. _mediaType->CopyAllItems( _inputMediaType );
  3504. _transform->SetInputType( 0, _inputMediaType, 0 );
  3505. MFCreateMediaType( &_outputMediaType );
  3506. _mediaType->CopyAllItems( _outputMediaType );
  3507. _outputMediaType->SetUINT32( MF_MT_AUDIO_SAMPLES_PER_SECOND, outSampleRate );
  3508. _outputMediaType->SetUINT32( MF_MT_AUDIO_AVG_BYTES_PER_SECOND, _bytesPerSample * channelCount * outSampleRate );
  3509. _transform->SetOutputType( 0, _outputMediaType, 0 );
  3510. // 4. Send stream start messages to Resampler
  3511. _transform->ProcessMessage( MFT_MESSAGE_COMMAND_FLUSH, 0 );
  3512. _transform->ProcessMessage( MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, 0 );
  3513. _transform->ProcessMessage( MFT_MESSAGE_NOTIFY_START_OF_STREAM, 0 );
  3514. }
  3515. ~WasapiResampler()
  3516. {
  3517. // 8. Send stream stop messages to Resampler
  3518. _transform->ProcessMessage( MFT_MESSAGE_NOTIFY_END_OF_STREAM, 0 );
  3519. _transform->ProcessMessage( MFT_MESSAGE_NOTIFY_END_STREAMING, 0 );
  3520. // 9. Cleanup
  3521. MFShutdown();
  3522. SAFE_RELEASE( _transformUnk );
  3523. SAFE_RELEASE( _transform );
  3524. SAFE_RELEASE( _mediaType );
  3525. SAFE_RELEASE( _inputMediaType );
  3526. SAFE_RELEASE( _outputMediaType );
  3527. #ifdef __IWMResamplerProps_FWD_DEFINED__
  3528. SAFE_RELEASE( _resamplerProps );
  3529. #endif
  3530. }
  3531. void Convert( char* outBuffer, const char* inBuffer, unsigned int inSampleCount, unsigned int& outSampleCount, int maxOutSampleCount = -1 )
  3532. {
  3533. unsigned int inputBufferSize = _bytesPerSample * _channelCount * inSampleCount;
  3534. if ( _sampleRatio == 1 )
  3535. {
  3536. // no sample rate conversion required
  3537. memcpy( outBuffer, inBuffer, inputBufferSize );
  3538. outSampleCount = inSampleCount;
  3539. return;
  3540. }
  3541. unsigned int outputBufferSize = 0;
  3542. if ( maxOutSampleCount != -1 )
  3543. {
  3544. outputBufferSize = _bytesPerSample * _channelCount * maxOutSampleCount;
  3545. }
  3546. else
  3547. {
  3548. outputBufferSize = ( unsigned int ) ceilf( inputBufferSize * _sampleRatio ) + ( _bytesPerSample * _channelCount );
  3549. }
  3550. IMFMediaBuffer* rInBuffer;
  3551. IMFSample* rInSample;
  3552. BYTE* rInByteBuffer = NULL;
  3553. // 5. Create Sample object from input data
  3554. MFCreateMemoryBuffer( inputBufferSize, &rInBuffer );
  3555. rInBuffer->Lock( &rInByteBuffer, NULL, NULL );
  3556. memcpy( rInByteBuffer, inBuffer, inputBufferSize );
  3557. rInBuffer->Unlock();
  3558. rInByteBuffer = NULL;
  3559. rInBuffer->SetCurrentLength( inputBufferSize );
  3560. MFCreateSample( &rInSample );
  3561. rInSample->AddBuffer( rInBuffer );
  3562. // 6. Pass input data to Resampler
  3563. _transform->ProcessInput( 0, rInSample, 0 );
  3564. SAFE_RELEASE( rInBuffer );
  3565. SAFE_RELEASE( rInSample );
  3566. // 7. Perform sample rate conversion
  3567. IMFMediaBuffer* rOutBuffer = NULL;
  3568. BYTE* rOutByteBuffer = NULL;
  3569. MFT_OUTPUT_DATA_BUFFER rOutDataBuffer;
  3570. DWORD rStatus;
  3571. DWORD rBytes = outputBufferSize; // maximum bytes accepted per ProcessOutput
  3572. // 7.1 Create Sample object for output data
  3573. memset( &rOutDataBuffer, 0, sizeof rOutDataBuffer );
  3574. MFCreateSample( &( rOutDataBuffer.pSample ) );
  3575. MFCreateMemoryBuffer( rBytes, &rOutBuffer );
  3576. rOutDataBuffer.pSample->AddBuffer( rOutBuffer );
  3577. rOutDataBuffer.dwStreamID = 0;
  3578. rOutDataBuffer.dwStatus = 0;
  3579. rOutDataBuffer.pEvents = NULL;
  3580. // 7.2 Get output data from Resampler
  3581. if ( _transform->ProcessOutput( 0, 1, &rOutDataBuffer, &rStatus ) == MF_E_TRANSFORM_NEED_MORE_INPUT )
  3582. {
  3583. outSampleCount = 0;
  3584. SAFE_RELEASE( rOutBuffer );
  3585. SAFE_RELEASE( rOutDataBuffer.pSample );
  3586. return;
  3587. }
  3588. // 7.3 Write output data to outBuffer
  3589. SAFE_RELEASE( rOutBuffer );
  3590. rOutDataBuffer.pSample->ConvertToContiguousBuffer( &rOutBuffer );
  3591. rOutBuffer->GetCurrentLength( &rBytes );
  3592. rOutBuffer->Lock( &rOutByteBuffer, NULL, NULL );
  3593. memcpy( outBuffer, rOutByteBuffer, rBytes );
  3594. rOutBuffer->Unlock();
  3595. rOutByteBuffer = NULL;
  3596. outSampleCount = rBytes / _bytesPerSample / _channelCount;
  3597. SAFE_RELEASE( rOutBuffer );
  3598. SAFE_RELEASE( rOutDataBuffer.pSample );
  3599. }
  3600. private:
  3601. unsigned int _bytesPerSample;
  3602. unsigned int _channelCount;
  3603. float _sampleRatio;
  3604. IUnknown* _transformUnk;
  3605. IMFTransform* _transform;
  3606. IMFMediaType* _mediaType;
  3607. IMFMediaType* _inputMediaType;
  3608. IMFMediaType* _outputMediaType;
  3609. #ifdef __IWMResamplerProps_FWD_DEFINED__
  3610. IWMResamplerProps* _resamplerProps;
  3611. #endif
  3612. };
  3613. //-----------------------------------------------------------------------------
  3614. // A structure to hold various information related to the WASAPI implementation.
  3615. struct WasapiHandle
  3616. {
  3617. IAudioClient* captureAudioClient;
  3618. IAudioClient* renderAudioClient;
  3619. IAudioCaptureClient* captureClient;
  3620. IAudioRenderClient* renderClient;
  3621. HANDLE captureEvent;
  3622. HANDLE renderEvent;
  3623. WasapiHandle()
  3624. : captureAudioClient( NULL ),
  3625. renderAudioClient( NULL ),
  3626. captureClient( NULL ),
  3627. renderClient( NULL ),
  3628. captureEvent( NULL ),
  3629. renderEvent( NULL ) {}
  3630. };
  3631. //=============================================================================
  3632. RtApiWasapi::RtApiWasapi()
  3633. : coInitialized_( false ), deviceEnumerator_( NULL )
  3634. {
  3635. // WASAPI can run either apartment or multi-threaded
  3636. HRESULT hr = CoInitialize( NULL );
  3637. if ( !FAILED( hr ) )
  3638. coInitialized_ = true;
  3639. // Instantiate device enumerator
  3640. hr = CoCreateInstance( __uuidof( MMDeviceEnumerator ), NULL,
  3641. CLSCTX_ALL, __uuidof( IMMDeviceEnumerator ),
  3642. ( void** ) &deviceEnumerator_ );
  3643. // If this runs on an old Windows, it will fail. Ignore and proceed.
  3644. if ( FAILED( hr ) )
  3645. deviceEnumerator_ = NULL;
  3646. }
  3647. //-----------------------------------------------------------------------------
  3648. RtApiWasapi::~RtApiWasapi()
  3649. {
  3650. if ( stream_.state != STREAM_CLOSED )
  3651. closeStream();
  3652. SAFE_RELEASE( deviceEnumerator_ );
  3653. // If this object previously called CoInitialize()
  3654. if ( coInitialized_ )
  3655. CoUninitialize();
  3656. }
  3657. //=============================================================================
  3658. unsigned int RtApiWasapi::getDeviceCount( void )
  3659. {
  3660. unsigned int captureDeviceCount = 0;
  3661. unsigned int renderDeviceCount = 0;
  3662. IMMDeviceCollection* captureDevices = NULL;
  3663. IMMDeviceCollection* renderDevices = NULL;
  3664. if ( !deviceEnumerator_ )
  3665. return 0;
  3666. // Count capture devices
  3667. errorText_.clear();
  3668. HRESULT hr = deviceEnumerator_->EnumAudioEndpoints( eCapture, DEVICE_STATE_ACTIVE, &captureDevices );
  3669. if ( FAILED( hr ) ) {
  3670. errorText_ = "RtApiWasapi::getDeviceCount: Unable to retrieve capture device collection.";
  3671. goto Exit;
  3672. }
  3673. hr = captureDevices->GetCount( &captureDeviceCount );
  3674. if ( FAILED( hr ) ) {
  3675. errorText_ = "RtApiWasapi::getDeviceCount: Unable to retrieve capture device count.";
  3676. goto Exit;
  3677. }
  3678. // Count render devices
  3679. hr = deviceEnumerator_->EnumAudioEndpoints( eRender, DEVICE_STATE_ACTIVE, &renderDevices );
  3680. if ( FAILED( hr ) ) {
  3681. errorText_ = "RtApiWasapi::getDeviceCount: Unable to retrieve render device collection.";
  3682. goto Exit;
  3683. }
  3684. hr = renderDevices->GetCount( &renderDeviceCount );
  3685. if ( FAILED( hr ) ) {
  3686. errorText_ = "RtApiWasapi::getDeviceCount: Unable to retrieve render device count.";
  3687. goto Exit;
  3688. }
  3689. Exit:
  3690. // release all references
  3691. SAFE_RELEASE( captureDevices );
  3692. SAFE_RELEASE( renderDevices );
  3693. if ( errorText_.empty() )
  3694. return captureDeviceCount + renderDeviceCount;
  3695. error( RtAudioError::DRIVER_ERROR );
  3696. return 0;
  3697. }
  3698. //-----------------------------------------------------------------------------
  3699. RtAudio::DeviceInfo RtApiWasapi::getDeviceInfo( unsigned int device )
  3700. {
  3701. RtAudio::DeviceInfo info;
  3702. unsigned int captureDeviceCount = 0;
  3703. unsigned int renderDeviceCount = 0;
  3704. std::string defaultDeviceName;
  3705. bool isCaptureDevice = false;
  3706. PROPVARIANT deviceNameProp;
  3707. PROPVARIANT defaultDeviceNameProp;
  3708. IMMDeviceCollection* captureDevices = NULL;
  3709. IMMDeviceCollection* renderDevices = NULL;
  3710. IMMDevice* devicePtr = NULL;
  3711. IMMDevice* defaultDevicePtr = NULL;
  3712. IAudioClient* audioClient = NULL;
  3713. IPropertyStore* devicePropStore = NULL;
  3714. IPropertyStore* defaultDevicePropStore = NULL;
  3715. WAVEFORMATEX* deviceFormat = NULL;
  3716. WAVEFORMATEX* closestMatchFormat = NULL;
  3717. // probed
  3718. info.probed = false;
  3719. // Count capture devices
  3720. errorText_.clear();
  3721. RtAudioError::Type errorType = RtAudioError::DRIVER_ERROR;
  3722. HRESULT hr = deviceEnumerator_->EnumAudioEndpoints( eCapture, DEVICE_STATE_ACTIVE, &captureDevices );
  3723. if ( FAILED( hr ) ) {
  3724. errorText_ = "RtApiWasapi::getDeviceInfo: Unable to retrieve capture device collection.";
  3725. goto Exit;
  3726. }
  3727. hr = captureDevices->GetCount( &captureDeviceCount );
  3728. if ( FAILED( hr ) ) {
  3729. errorText_ = "RtApiWasapi::getDeviceInfo: Unable to retrieve capture device count.";
  3730. goto Exit;
  3731. }
  3732. // Count render devices
  3733. hr = deviceEnumerator_->EnumAudioEndpoints( eRender, DEVICE_STATE_ACTIVE, &renderDevices );
  3734. if ( FAILED( hr ) ) {
  3735. errorText_ = "RtApiWasapi::getDeviceInfo: Unable to retrieve render device collection.";
  3736. goto Exit;
  3737. }
  3738. hr = renderDevices->GetCount( &renderDeviceCount );
  3739. if ( FAILED( hr ) ) {
  3740. errorText_ = "RtApiWasapi::getDeviceInfo: Unable to retrieve render device count.";
  3741. goto Exit;
  3742. }
  3743. // validate device index
  3744. if ( device >= captureDeviceCount + renderDeviceCount ) {
  3745. errorText_ = "RtApiWasapi::getDeviceInfo: Invalid device index.";
  3746. errorType = RtAudioError::INVALID_USE;
  3747. goto Exit;
  3748. }
  3749. // determine whether index falls within capture or render devices
  3750. if ( device >= renderDeviceCount ) {
  3751. hr = captureDevices->Item( device - renderDeviceCount, &devicePtr );
  3752. if ( FAILED( hr ) ) {
  3753. errorText_ = "RtApiWasapi::getDeviceInfo: Unable to retrieve capture device handle.";
  3754. goto Exit;
  3755. }
  3756. isCaptureDevice = true;
  3757. }
  3758. else {
  3759. hr = renderDevices->Item( device, &devicePtr );
  3760. if ( FAILED( hr ) ) {
  3761. errorText_ = "RtApiWasapi::getDeviceInfo: Unable to retrieve render device handle.";
  3762. goto Exit;
  3763. }
  3764. isCaptureDevice = false;
  3765. }
  3766. // get default device name
  3767. if ( isCaptureDevice ) {
  3768. hr = deviceEnumerator_->GetDefaultAudioEndpoint( eCapture, eConsole, &defaultDevicePtr );
  3769. if ( FAILED( hr ) ) {
  3770. errorText_ = "RtApiWasapi::getDeviceInfo: Unable to retrieve default capture device handle.";
  3771. goto Exit;
  3772. }
  3773. }
  3774. else {
  3775. hr = deviceEnumerator_->GetDefaultAudioEndpoint( eRender, eConsole, &defaultDevicePtr );
  3776. if ( FAILED( hr ) ) {
  3777. errorText_ = "RtApiWasapi::getDeviceInfo: Unable to retrieve default render device handle.";
  3778. goto Exit;
  3779. }
  3780. }
  3781. hr = defaultDevicePtr->OpenPropertyStore( STGM_READ, &defaultDevicePropStore );
  3782. if ( FAILED( hr ) ) {
  3783. errorText_ = "RtApiWasapi::getDeviceInfo: Unable to open default device property store.";
  3784. goto Exit;
  3785. }
  3786. PropVariantInit( &defaultDeviceNameProp );
  3787. hr = defaultDevicePropStore->GetValue( PKEY_Device_FriendlyName, &defaultDeviceNameProp );
  3788. if ( FAILED( hr ) ) {
  3789. errorText_ = "RtApiWasapi::getDeviceInfo: Unable to retrieve default device property: PKEY_Device_FriendlyName.";
  3790. goto Exit;
  3791. }
  3792. defaultDeviceName = convertCharPointerToStdString(defaultDeviceNameProp.pwszVal);
  3793. // name
  3794. hr = devicePtr->OpenPropertyStore( STGM_READ, &devicePropStore );
  3795. if ( FAILED( hr ) ) {
  3796. errorText_ = "RtApiWasapi::getDeviceInfo: Unable to open device property store.";
  3797. goto Exit;
  3798. }
  3799. PropVariantInit( &deviceNameProp );
  3800. hr = devicePropStore->GetValue( PKEY_Device_FriendlyName, &deviceNameProp );
  3801. if ( FAILED( hr ) ) {
  3802. errorText_ = "RtApiWasapi::getDeviceInfo: Unable to retrieve device property: PKEY_Device_FriendlyName.";
  3803. goto Exit;
  3804. }
  3805. info.name =convertCharPointerToStdString(deviceNameProp.pwszVal);
  3806. // is default
  3807. if ( isCaptureDevice ) {
  3808. info.isDefaultInput = info.name == defaultDeviceName;
  3809. info.isDefaultOutput = false;
  3810. }
  3811. else {
  3812. info.isDefaultInput = false;
  3813. info.isDefaultOutput = info.name == defaultDeviceName;
  3814. }
  3815. // channel count
  3816. hr = devicePtr->Activate( __uuidof( IAudioClient ), CLSCTX_ALL, NULL, ( void** ) &audioClient );
  3817. if ( FAILED( hr ) ) {
  3818. errorText_ = "RtApiWasapi::getDeviceInfo: Unable to retrieve device audio client.";
  3819. goto Exit;
  3820. }
  3821. hr = audioClient->GetMixFormat( &deviceFormat );
  3822. if ( FAILED( hr ) ) {
  3823. errorText_ = "RtApiWasapi::getDeviceInfo: Unable to retrieve device mix format.";
  3824. goto Exit;
  3825. }
  3826. if ( isCaptureDevice ) {
  3827. info.inputChannels = deviceFormat->nChannels;
  3828. info.outputChannels = 0;
  3829. info.duplexChannels = 0;
  3830. }
  3831. else {
  3832. info.inputChannels = 0;
  3833. info.outputChannels = deviceFormat->nChannels;
  3834. info.duplexChannels = 0;
  3835. }
  3836. // sample rates
  3837. info.sampleRates.clear();
  3838. // allow support for all sample rates as we have a built-in sample rate converter
  3839. for ( unsigned int i = 0; i < MAX_SAMPLE_RATES; i++ ) {
  3840. info.sampleRates.push_back( SAMPLE_RATES[i] );
  3841. }
  3842. info.preferredSampleRate = deviceFormat->nSamplesPerSec;
  3843. // native format
  3844. info.nativeFormats = 0;
  3845. if ( deviceFormat->wFormatTag == WAVE_FORMAT_IEEE_FLOAT ||
  3846. ( deviceFormat->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
  3847. ( ( WAVEFORMATEXTENSIBLE* ) deviceFormat )->SubFormat == KSDATAFORMAT_SUBTYPE_IEEE_FLOAT ) )
  3848. {
  3849. if ( deviceFormat->wBitsPerSample == 32 ) {
  3850. info.nativeFormats |= RTAUDIO_FLOAT32;
  3851. }
  3852. else if ( deviceFormat->wBitsPerSample == 64 ) {
  3853. info.nativeFormats |= RTAUDIO_FLOAT64;
  3854. }
  3855. }
  3856. else if ( deviceFormat->wFormatTag == WAVE_FORMAT_PCM ||
  3857. ( deviceFormat->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
  3858. ( ( WAVEFORMATEXTENSIBLE* ) deviceFormat )->SubFormat == KSDATAFORMAT_SUBTYPE_PCM ) )
  3859. {
  3860. if ( deviceFormat->wBitsPerSample == 8 ) {
  3861. info.nativeFormats |= RTAUDIO_SINT8;
  3862. }
  3863. else if ( deviceFormat->wBitsPerSample == 16 ) {
  3864. info.nativeFormats |= RTAUDIO_SINT16;
  3865. }
  3866. else if ( deviceFormat->wBitsPerSample == 24 ) {
  3867. info.nativeFormats |= RTAUDIO_SINT24;
  3868. }
  3869. else if ( deviceFormat->wBitsPerSample == 32 ) {
  3870. info.nativeFormats |= RTAUDIO_SINT32;
  3871. }
  3872. }
  3873. // probed
  3874. info.probed = true;
  3875. Exit:
  3876. // release all references
  3877. PropVariantClear( &deviceNameProp );
  3878. PropVariantClear( &defaultDeviceNameProp );
  3879. SAFE_RELEASE( captureDevices );
  3880. SAFE_RELEASE( renderDevices );
  3881. SAFE_RELEASE( devicePtr );
  3882. SAFE_RELEASE( defaultDevicePtr );
  3883. SAFE_RELEASE( audioClient );
  3884. SAFE_RELEASE( devicePropStore );
  3885. SAFE_RELEASE( defaultDevicePropStore );
  3886. CoTaskMemFree( deviceFormat );
  3887. CoTaskMemFree( closestMatchFormat );
  3888. if ( !errorText_.empty() )
  3889. error( errorType );
  3890. return info;
  3891. }
  3892. void RtApiWasapi::closeStream( void )
  3893. {
  3894. if ( stream_.state == STREAM_CLOSED ) {
  3895. errorText_ = "RtApiWasapi::closeStream: No open stream to close.";
  3896. error( RtAudioError::WARNING );
  3897. return;
  3898. }
  3899. if ( stream_.state != STREAM_STOPPED )
  3900. stopStream();
  3901. // clean up stream memory
  3902. SAFE_RELEASE( ( ( WasapiHandle* ) stream_.apiHandle )->captureAudioClient )
  3903. SAFE_RELEASE( ( ( WasapiHandle* ) stream_.apiHandle )->renderAudioClient )
  3904. SAFE_RELEASE( ( ( WasapiHandle* ) stream_.apiHandle )->captureClient )
  3905. SAFE_RELEASE( ( ( WasapiHandle* ) stream_.apiHandle )->renderClient )
  3906. if ( ( ( WasapiHandle* ) stream_.apiHandle )->captureEvent )
  3907. CloseHandle( ( ( WasapiHandle* ) stream_.apiHandle )->captureEvent );
  3908. if ( ( ( WasapiHandle* ) stream_.apiHandle )->renderEvent )
  3909. CloseHandle( ( ( WasapiHandle* ) stream_.apiHandle )->renderEvent );
  3910. delete ( WasapiHandle* ) stream_.apiHandle;
  3911. stream_.apiHandle = NULL;
  3912. for ( int i = 0; i < 2; i++ ) {
  3913. if ( stream_.userBuffer[i] ) {
  3914. free( stream_.userBuffer[i] );
  3915. stream_.userBuffer[i] = 0;
  3916. }
  3917. }
  3918. if ( stream_.deviceBuffer ) {
  3919. free( stream_.deviceBuffer );
  3920. stream_.deviceBuffer = 0;
  3921. }
  3922. // update stream state
  3923. stream_.state = STREAM_CLOSED;
  3924. }
  3925. //-----------------------------------------------------------------------------
  3926. void RtApiWasapi::startStream( void )
  3927. {
  3928. verifyStream();
  3929. if ( stream_.state == STREAM_RUNNING ) {
  3930. errorText_ = "RtApiWasapi::startStream: The stream is already running.";
  3931. error( RtAudioError::WARNING );
  3932. return;
  3933. }
  3934. #if defined( HAVE_GETTIMEOFDAY )
  3935. gettimeofday( &stream_.lastTickTimestamp, NULL );
  3936. #endif
  3937. // update stream state
  3938. stream_.state = STREAM_RUNNING;
  3939. // create WASAPI stream thread
  3940. stream_.callbackInfo.thread = ( ThreadHandle ) CreateThread( NULL, 0, runWasapiThread, this, CREATE_SUSPENDED, NULL );
  3941. if ( !stream_.callbackInfo.thread ) {
  3942. errorText_ = "RtApiWasapi::startStream: Unable to instantiate callback thread.";
  3943. error( RtAudioError::THREAD_ERROR );
  3944. }
  3945. else {
  3946. SetThreadPriority( ( void* ) stream_.callbackInfo.thread, stream_.callbackInfo.priority );
  3947. ResumeThread( ( void* ) stream_.callbackInfo.thread );
  3948. }
  3949. }
  3950. //-----------------------------------------------------------------------------
  3951. void RtApiWasapi::stopStream( void )
  3952. {
  3953. verifyStream();
  3954. if ( stream_.state == STREAM_STOPPED ) {
  3955. errorText_ = "RtApiWasapi::stopStream: The stream is already stopped.";
  3956. error( RtAudioError::WARNING );
  3957. return;
  3958. }
  3959. if ( stream_.state == STREAM_STOPPING ) {
  3960. errorText_ = "RtApiWasapi::stopStream: The stream is already stopping.";
  3961. error( RtAudioError::WARNING );
  3962. return;
  3963. }
  3964. // inform stream thread by setting stream state to STREAM_STOPPING
  3965. stream_.state = STREAM_STOPPING;
  3966. WaitForSingleObject( ( void* ) stream_.callbackInfo.thread, INFINITE );
  3967. // close thread handle
  3968. if ( stream_.callbackInfo.thread && !CloseHandle( ( void* ) stream_.callbackInfo.thread ) ) {
  3969. errorText_ = "RtApiWasapi::stopStream: Unable to close callback thread.";
  3970. error( RtAudioError::THREAD_ERROR );
  3971. return;
  3972. }
  3973. stream_.callbackInfo.thread = (ThreadHandle) NULL;
  3974. }
  3975. //-----------------------------------------------------------------------------
  3976. void RtApiWasapi::abortStream( void )
  3977. {
  3978. verifyStream();
  3979. if ( stream_.state == STREAM_STOPPED ) {
  3980. errorText_ = "RtApiWasapi::abortStream: The stream is already stopped.";
  3981. error( RtAudioError::WARNING );
  3982. return;
  3983. }
  3984. if ( stream_.state == STREAM_STOPPING ) {
  3985. errorText_ = "RtApiWasapi::abortStream: The stream is already stopping.";
  3986. error( RtAudioError::WARNING );
  3987. return;
  3988. }
  3989. // inform stream thread by setting stream state to STREAM_STOPPING
  3990. stream_.state = STREAM_STOPPING;
  3991. WaitForSingleObject( ( void* ) stream_.callbackInfo.thread, INFINITE );
  3992. // close thread handle
  3993. if ( stream_.callbackInfo.thread && !CloseHandle( ( void* ) stream_.callbackInfo.thread ) ) {
  3994. errorText_ = "RtApiWasapi::abortStream: Unable to close callback thread.";
  3995. error( RtAudioError::THREAD_ERROR );
  3996. return;
  3997. }
  3998. stream_.callbackInfo.thread = (ThreadHandle) NULL;
  3999. }
  4000. //-----------------------------------------------------------------------------
  4001. bool RtApiWasapi::probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels,
  4002. unsigned int firstChannel, unsigned int sampleRate,
  4003. RtAudioFormat format, unsigned int* bufferSize,
  4004. RtAudio::StreamOptions* options )
  4005. {
  4006. bool methodResult = FAILURE;
  4007. unsigned int captureDeviceCount = 0;
  4008. unsigned int renderDeviceCount = 0;
  4009. IMMDeviceCollection* captureDevices = NULL;
  4010. IMMDeviceCollection* renderDevices = NULL;
  4011. IMMDevice* devicePtr = NULL;
  4012. WAVEFORMATEX* deviceFormat = NULL;
  4013. unsigned int bufferBytes;
  4014. stream_.state = STREAM_STOPPED;
  4015. // create API Handle if not already created
  4016. if ( !stream_.apiHandle )
  4017. stream_.apiHandle = ( void* ) new WasapiHandle();
  4018. // Count capture devices
  4019. errorText_.clear();
  4020. RtAudioError::Type errorType = RtAudioError::DRIVER_ERROR;
  4021. HRESULT hr = deviceEnumerator_->EnumAudioEndpoints( eCapture, DEVICE_STATE_ACTIVE, &captureDevices );
  4022. if ( FAILED( hr ) ) {
  4023. errorText_ = "RtApiWasapi::probeDeviceOpen: Unable to retrieve capture device collection.";
  4024. goto Exit;
  4025. }
  4026. hr = captureDevices->GetCount( &captureDeviceCount );
  4027. if ( FAILED( hr ) ) {
  4028. errorText_ = "RtApiWasapi::probeDeviceOpen: Unable to retrieve capture device count.";
  4029. goto Exit;
  4030. }
  4031. // Count render devices
  4032. hr = deviceEnumerator_->EnumAudioEndpoints( eRender, DEVICE_STATE_ACTIVE, &renderDevices );
  4033. if ( FAILED( hr ) ) {
  4034. errorText_ = "RtApiWasapi::probeDeviceOpen: Unable to retrieve render device collection.";
  4035. goto Exit;
  4036. }
  4037. hr = renderDevices->GetCount( &renderDeviceCount );
  4038. if ( FAILED( hr ) ) {
  4039. errorText_ = "RtApiWasapi::probeDeviceOpen: Unable to retrieve render device count.";
  4040. goto Exit;
  4041. }
  4042. // validate device index
  4043. if ( device >= captureDeviceCount + renderDeviceCount ) {
  4044. errorType = RtAudioError::INVALID_USE;
  4045. errorText_ = "RtApiWasapi::probeDeviceOpen: Invalid device index.";
  4046. goto Exit;
  4047. }
  4048. // if device index falls within capture devices
  4049. if ( device >= renderDeviceCount ) {
  4050. if ( mode != INPUT ) {
  4051. errorType = RtAudioError::INVALID_USE;
  4052. errorText_ = "RtApiWasapi::probeDeviceOpen: Capture device selected as output device.";
  4053. goto Exit;
  4054. }
  4055. // retrieve captureAudioClient from devicePtr
  4056. IAudioClient*& captureAudioClient = ( ( WasapiHandle* ) stream_.apiHandle )->captureAudioClient;
  4057. hr = captureDevices->Item( device - renderDeviceCount, &devicePtr );
  4058. if ( FAILED( hr ) ) {
  4059. errorText_ = "RtApiWasapi::probeDeviceOpen: Unable to retrieve capture device handle.";
  4060. goto Exit;
  4061. }
  4062. hr = devicePtr->Activate( __uuidof( IAudioClient ), CLSCTX_ALL,
  4063. NULL, ( void** ) &captureAudioClient );
  4064. if ( FAILED( hr ) ) {
  4065. errorText_ = "RtApiWasapi::probeDeviceOpen: Unable to retrieve capture device audio client.";
  4066. goto Exit;
  4067. }
  4068. hr = captureAudioClient->GetMixFormat( &deviceFormat );
  4069. if ( FAILED( hr ) ) {
  4070. errorText_ = "RtApiWasapi::probeDeviceOpen: Unable to retrieve capture device mix format.";
  4071. goto Exit;
  4072. }
  4073. stream_.nDeviceChannels[mode] = deviceFormat->nChannels;
  4074. captureAudioClient->GetStreamLatency( ( long long* ) &stream_.latency[mode] );
  4075. }
  4076. // if device index falls within render devices and is configured for loopback
  4077. if ( device < renderDeviceCount && mode == INPUT )
  4078. {
  4079. // if renderAudioClient is not initialised, initialise it now
  4080. IAudioClient*& renderAudioClient = ( ( WasapiHandle* ) stream_.apiHandle )->renderAudioClient;
  4081. if ( !renderAudioClient )
  4082. {
  4083. probeDeviceOpen( device, OUTPUT, channels, firstChannel, sampleRate, format, bufferSize, options );
  4084. }
  4085. // retrieve captureAudioClient from devicePtr
  4086. IAudioClient*& captureAudioClient = ( ( WasapiHandle* ) stream_.apiHandle )->captureAudioClient;
  4087. hr = renderDevices->Item( device, &devicePtr );
  4088. if ( FAILED( hr ) ) {
  4089. errorText_ = "RtApiWasapi::probeDeviceOpen: Unable to retrieve render device handle.";
  4090. goto Exit;
  4091. }
  4092. hr = devicePtr->Activate( __uuidof( IAudioClient ), CLSCTX_ALL,
  4093. NULL, ( void** ) &captureAudioClient );
  4094. if ( FAILED( hr ) ) {
  4095. errorText_ = "RtApiWasapi::probeDeviceOpen: Unable to retrieve render device audio client.";
  4096. goto Exit;
  4097. }
  4098. hr = captureAudioClient->GetMixFormat( &deviceFormat );
  4099. if ( FAILED( hr ) ) {
  4100. errorText_ = "RtApiWasapi::probeDeviceOpen: Unable to retrieve render device mix format.";
  4101. goto Exit;
  4102. }
  4103. stream_.nDeviceChannels[mode] = deviceFormat->nChannels;
  4104. captureAudioClient->GetStreamLatency( ( long long* ) &stream_.latency[mode] );
  4105. }
  4106. // if device index falls within render devices and is configured for output
  4107. if ( device < renderDeviceCount && mode == OUTPUT )
  4108. {
  4109. // if renderAudioClient is already initialised, don't initialise it again
  4110. IAudioClient*& renderAudioClient = ( ( WasapiHandle* ) stream_.apiHandle )->renderAudioClient;
  4111. if ( renderAudioClient )
  4112. {
  4113. methodResult = SUCCESS;
  4114. goto Exit;
  4115. }
  4116. hr = renderDevices->Item( device, &devicePtr );
  4117. if ( FAILED( hr ) ) {
  4118. errorText_ = "RtApiWasapi::probeDeviceOpen: Unable to retrieve render device handle.";
  4119. goto Exit;
  4120. }
  4121. hr = devicePtr->Activate( __uuidof( IAudioClient ), CLSCTX_ALL,
  4122. NULL, ( void** ) &renderAudioClient );
  4123. if ( FAILED( hr ) ) {
  4124. errorText_ = "RtApiWasapi::probeDeviceOpen: Unable to retrieve render device audio client.";
  4125. goto Exit;
  4126. }
  4127. hr = renderAudioClient->GetMixFormat( &deviceFormat );
  4128. if ( FAILED( hr ) ) {
  4129. errorText_ = "RtApiWasapi::probeDeviceOpen: Unable to retrieve render device mix format.";
  4130. goto Exit;
  4131. }
  4132. stream_.nDeviceChannels[mode] = deviceFormat->nChannels;
  4133. renderAudioClient->GetStreamLatency( ( long long* ) &stream_.latency[mode] );
  4134. }
  4135. // fill stream data
  4136. if ( ( stream_.mode == OUTPUT && mode == INPUT ) ||
  4137. ( stream_.mode == INPUT && mode == OUTPUT ) ) {
  4138. stream_.mode = DUPLEX;
  4139. }
  4140. else {
  4141. stream_.mode = mode;
  4142. }
  4143. stream_.device[mode] = device;
  4144. stream_.doByteSwap[mode] = false;
  4145. stream_.sampleRate = sampleRate;
  4146. stream_.bufferSize = *bufferSize;
  4147. stream_.nBuffers = 1;
  4148. stream_.nUserChannels[mode] = channels;
  4149. stream_.channelOffset[mode] = firstChannel;
  4150. stream_.userFormat = format;
  4151. stream_.deviceFormat[mode] = getDeviceInfo( device ).nativeFormats;
  4152. if ( options && options->flags & RTAUDIO_NONINTERLEAVED )
  4153. stream_.userInterleaved = false;
  4154. else
  4155. stream_.userInterleaved = true;
  4156. stream_.deviceInterleaved[mode] = true;
  4157. // Set flags for buffer conversion.
  4158. stream_.doConvertBuffer[mode] = false;
  4159. if ( stream_.userFormat != stream_.deviceFormat[mode] ||
  4160. stream_.nUserChannels[0] != stream_.nDeviceChannels[0] ||
  4161. stream_.nUserChannels[1] != stream_.nDeviceChannels[1] )
  4162. stream_.doConvertBuffer[mode] = true;
  4163. else if ( stream_.userInterleaved != stream_.deviceInterleaved[mode] &&
  4164. stream_.nUserChannels[mode] > 1 )
  4165. stream_.doConvertBuffer[mode] = true;
  4166. if ( stream_.doConvertBuffer[mode] )
  4167. setConvertInfo( mode, firstChannel );
  4168. // Allocate necessary internal buffers
  4169. bufferBytes = stream_.nUserChannels[mode] * stream_.bufferSize * formatBytes( stream_.userFormat );
  4170. stream_.userBuffer[mode] = ( char* ) calloc( bufferBytes, 1 );
  4171. if ( !stream_.userBuffer[mode] ) {
  4172. errorType = RtAudioError::MEMORY_ERROR;
  4173. errorText_ = "RtApiWasapi::probeDeviceOpen: Error allocating user buffer memory.";
  4174. goto Exit;
  4175. }
  4176. if ( options && options->flags & RTAUDIO_SCHEDULE_REALTIME )
  4177. stream_.callbackInfo.priority = 15;
  4178. else
  4179. stream_.callbackInfo.priority = 0;
  4180. ///! TODO: RTAUDIO_MINIMIZE_LATENCY // Provide stream buffers directly to callback
  4181. ///! TODO: RTAUDIO_HOG_DEVICE // Exclusive mode
  4182. methodResult = SUCCESS;
  4183. Exit:
  4184. //clean up
  4185. SAFE_RELEASE( captureDevices );
  4186. SAFE_RELEASE( renderDevices );
  4187. SAFE_RELEASE( devicePtr );
  4188. CoTaskMemFree( deviceFormat );
  4189. // if method failed, close the stream
  4190. if ( methodResult == FAILURE )
  4191. closeStream();
  4192. if ( !errorText_.empty() )
  4193. error( errorType );
  4194. return methodResult;
  4195. }
  4196. //=============================================================================
  4197. DWORD WINAPI RtApiWasapi::runWasapiThread( void* wasapiPtr )
  4198. {
  4199. if ( wasapiPtr )
  4200. ( ( RtApiWasapi* ) wasapiPtr )->wasapiThread();
  4201. return 0;
  4202. }
  4203. DWORD WINAPI RtApiWasapi::stopWasapiThread( void* wasapiPtr )
  4204. {
  4205. if ( wasapiPtr )
  4206. ( ( RtApiWasapi* ) wasapiPtr )->stopStream();
  4207. return 0;
  4208. }
  4209. DWORD WINAPI RtApiWasapi::abortWasapiThread( void* wasapiPtr )
  4210. {
  4211. if ( wasapiPtr )
  4212. ( ( RtApiWasapi* ) wasapiPtr )->abortStream();
  4213. return 0;
  4214. }
  4215. //-----------------------------------------------------------------------------
  4216. void RtApiWasapi::wasapiThread()
  4217. {
  4218. // as this is a new thread, we must CoInitialize it
  4219. CoInitialize( NULL );
  4220. HRESULT hr;
  4221. IAudioClient* captureAudioClient = ( ( WasapiHandle* ) stream_.apiHandle )->captureAudioClient;
  4222. IAudioClient* renderAudioClient = ( ( WasapiHandle* ) stream_.apiHandle )->renderAudioClient;
  4223. IAudioCaptureClient* captureClient = ( ( WasapiHandle* ) stream_.apiHandle )->captureClient;
  4224. IAudioRenderClient* renderClient = ( ( WasapiHandle* ) stream_.apiHandle )->renderClient;
  4225. HANDLE captureEvent = ( ( WasapiHandle* ) stream_.apiHandle )->captureEvent;
  4226. HANDLE renderEvent = ( ( WasapiHandle* ) stream_.apiHandle )->renderEvent;
  4227. WAVEFORMATEX* captureFormat = NULL;
  4228. WAVEFORMATEX* renderFormat = NULL;
  4229. float captureSrRatio = 0.0f;
  4230. float renderSrRatio = 0.0f;
  4231. WasapiBuffer captureBuffer;
  4232. WasapiBuffer renderBuffer;
  4233. WasapiResampler* captureResampler = NULL;
  4234. WasapiResampler* renderResampler = NULL;
  4235. // declare local stream variables
  4236. RtAudioCallback callback = ( RtAudioCallback ) stream_.callbackInfo.callback;
  4237. BYTE* streamBuffer = NULL;
  4238. DWORD captureFlags = 0;
  4239. unsigned int bufferFrameCount = 0;
  4240. unsigned int numFramesPadding = 0;
  4241. unsigned int convBufferSize = 0;
  4242. bool loopbackEnabled = stream_.device[INPUT] == stream_.device[OUTPUT];
  4243. bool callbackPushed = true;
  4244. bool callbackPulled = false;
  4245. bool callbackStopped = false;
  4246. int callbackResult = 0;
  4247. // convBuffer is used to store converted buffers between WASAPI and the user
  4248. char* convBuffer = NULL;
  4249. unsigned int convBuffSize = 0;
  4250. unsigned int deviceBuffSize = 0;
  4251. std::string errorText;
  4252. RtAudioError::Type errorType = RtAudioError::DRIVER_ERROR;
  4253. // Attempt to assign "Pro Audio" characteristic to thread
  4254. HMODULE AvrtDll = LoadLibraryW( L"AVRT.dll" );
  4255. if ( AvrtDll ) {
  4256. DWORD taskIndex = 0;
  4257. TAvSetMmThreadCharacteristicsPtr AvSetMmThreadCharacteristicsPtr =
  4258. ( TAvSetMmThreadCharacteristicsPtr ) (void(*)()) GetProcAddress( AvrtDll, "AvSetMmThreadCharacteristicsW" );
  4259. AvSetMmThreadCharacteristicsPtr( L"Pro Audio", &taskIndex );
  4260. FreeLibrary( AvrtDll );
  4261. }
  4262. // start capture stream if applicable
  4263. if ( captureAudioClient ) {
  4264. hr = captureAudioClient->GetMixFormat( &captureFormat );
  4265. if ( FAILED( hr ) ) {
  4266. errorText = "RtApiWasapi::wasapiThread: Unable to retrieve device mix format.";
  4267. goto Exit;
  4268. }
  4269. // init captureResampler
  4270. captureResampler = new WasapiResampler( stream_.deviceFormat[INPUT] == RTAUDIO_FLOAT32 || stream_.deviceFormat[INPUT] == RTAUDIO_FLOAT64,
  4271. formatBytes( stream_.deviceFormat[INPUT] ) * 8, stream_.nDeviceChannels[INPUT],
  4272. captureFormat->nSamplesPerSec, stream_.sampleRate );
  4273. captureSrRatio = ( ( float ) captureFormat->nSamplesPerSec / stream_.sampleRate );
  4274. if ( !captureClient ) {
  4275. IAudioClient3* captureAudioClient3 = nullptr;
  4276. captureAudioClient->QueryInterface( __uuidof( IAudioClient3 ), ( void** ) &captureAudioClient3 );
  4277. if ( captureAudioClient3 && !loopbackEnabled )
  4278. {
  4279. UINT32 Ignore;
  4280. UINT32 MinPeriodInFrames;
  4281. hr = captureAudioClient3->GetSharedModeEnginePeriod( captureFormat,
  4282. &Ignore,
  4283. &Ignore,
  4284. &MinPeriodInFrames,
  4285. &Ignore );
  4286. if ( FAILED( hr ) ) {
  4287. errorText = "RtApiWasapi::wasapiThread: Unable to initialize capture audio client.";
  4288. goto Exit;
  4289. }
  4290. hr = captureAudioClient3->InitializeSharedAudioStream( AUDCLNT_STREAMFLAGS_EVENTCALLBACK,
  4291. MinPeriodInFrames,
  4292. captureFormat,
  4293. NULL );
  4294. }
  4295. else
  4296. {
  4297. hr = captureAudioClient->Initialize( AUDCLNT_SHAREMODE_SHARED,
  4298. loopbackEnabled ? AUDCLNT_STREAMFLAGS_LOOPBACK : AUDCLNT_STREAMFLAGS_EVENTCALLBACK,
  4299. 0,
  4300. 0,
  4301. captureFormat,
  4302. NULL );
  4303. }
  4304. if ( FAILED( hr ) ) {
  4305. errorText = "RtApiWasapi::wasapiThread: Unable to initialize capture audio client.";
  4306. goto Exit;
  4307. }
  4308. hr = captureAudioClient->GetService( __uuidof( IAudioCaptureClient ),
  4309. ( void** ) &captureClient );
  4310. if ( FAILED( hr ) ) {
  4311. errorText = "RtApiWasapi::wasapiThread: Unable to retrieve capture client handle.";
  4312. goto Exit;
  4313. }
  4314. // don't configure captureEvent if in loopback mode
  4315. if ( !loopbackEnabled )
  4316. {
  4317. // configure captureEvent to trigger on every available capture buffer
  4318. captureEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
  4319. if ( !captureEvent ) {
  4320. errorType = RtAudioError::SYSTEM_ERROR;
  4321. errorText = "RtApiWasapi::wasapiThread: Unable to create capture event.";
  4322. goto Exit;
  4323. }
  4324. hr = captureAudioClient->SetEventHandle( captureEvent );
  4325. if ( FAILED( hr ) ) {
  4326. errorText = "RtApiWasapi::wasapiThread: Unable to set capture event handle.";
  4327. goto Exit;
  4328. }
  4329. ( ( WasapiHandle* ) stream_.apiHandle )->captureEvent = captureEvent;
  4330. }
  4331. ( ( WasapiHandle* ) stream_.apiHandle )->captureClient = captureClient;
  4332. // reset the capture stream
  4333. hr = captureAudioClient->Reset();
  4334. if ( FAILED( hr ) ) {
  4335. errorText = "RtApiWasapi::wasapiThread: Unable to reset capture stream.";
  4336. goto Exit;
  4337. }
  4338. // start the capture stream
  4339. hr = captureAudioClient->Start();
  4340. if ( FAILED( hr ) ) {
  4341. errorText = "RtApiWasapi::wasapiThread: Unable to start capture stream.";
  4342. goto Exit;
  4343. }
  4344. }
  4345. unsigned int inBufferSize = 0;
  4346. hr = captureAudioClient->GetBufferSize( &inBufferSize );
  4347. if ( FAILED( hr ) ) {
  4348. errorText = "RtApiWasapi::wasapiThread: Unable to get capture buffer size.";
  4349. goto Exit;
  4350. }
  4351. // scale outBufferSize according to stream->user sample rate ratio
  4352. unsigned int outBufferSize = ( unsigned int ) ceilf( stream_.bufferSize * captureSrRatio ) * stream_.nDeviceChannels[INPUT];
  4353. inBufferSize *= stream_.nDeviceChannels[INPUT];
  4354. // set captureBuffer size
  4355. captureBuffer.setBufferSize( inBufferSize + outBufferSize, formatBytes( stream_.deviceFormat[INPUT] ) );
  4356. }
  4357. // start render stream if applicable
  4358. if ( renderAudioClient ) {
  4359. hr = renderAudioClient->GetMixFormat( &renderFormat );
  4360. if ( FAILED( hr ) ) {
  4361. errorText = "RtApiWasapi::wasapiThread: Unable to retrieve device mix format.";
  4362. goto Exit;
  4363. }
  4364. // init renderResampler
  4365. renderResampler = new WasapiResampler( stream_.deviceFormat[OUTPUT] == RTAUDIO_FLOAT32 || stream_.deviceFormat[OUTPUT] == RTAUDIO_FLOAT64,
  4366. formatBytes( stream_.deviceFormat[OUTPUT] ) * 8, stream_.nDeviceChannels[OUTPUT],
  4367. stream_.sampleRate, renderFormat->nSamplesPerSec );
  4368. renderSrRatio = ( ( float ) renderFormat->nSamplesPerSec / stream_.sampleRate );
  4369. if ( !renderClient ) {
  4370. IAudioClient3* renderAudioClient3 = nullptr;
  4371. renderAudioClient->QueryInterface( __uuidof( IAudioClient3 ), ( void** ) &renderAudioClient3 );
  4372. if ( renderAudioClient3 )
  4373. {
  4374. UINT32 Ignore;
  4375. UINT32 MinPeriodInFrames;
  4376. hr = renderAudioClient3->GetSharedModeEnginePeriod( renderFormat,
  4377. &Ignore,
  4378. &Ignore,
  4379. &MinPeriodInFrames,
  4380. &Ignore );
  4381. if ( FAILED( hr ) ) {
  4382. errorText = "RtApiWasapi::wasapiThread: Unable to initialize render audio client.";
  4383. goto Exit;
  4384. }
  4385. hr = renderAudioClient3->InitializeSharedAudioStream( AUDCLNT_STREAMFLAGS_EVENTCALLBACK,
  4386. MinPeriodInFrames,
  4387. renderFormat,
  4388. NULL );
  4389. }
  4390. else
  4391. {
  4392. hr = renderAudioClient->Initialize( AUDCLNT_SHAREMODE_SHARED,
  4393. AUDCLNT_STREAMFLAGS_EVENTCALLBACK,
  4394. 0,
  4395. 0,
  4396. renderFormat,
  4397. NULL );
  4398. }
  4399. if ( FAILED( hr ) ) {
  4400. errorText = "RtApiWasapi::wasapiThread: Unable to initialize render audio client.";
  4401. goto Exit;
  4402. }
  4403. hr = renderAudioClient->GetService( __uuidof( IAudioRenderClient ),
  4404. ( void** ) &renderClient );
  4405. if ( FAILED( hr ) ) {
  4406. errorText = "RtApiWasapi::wasapiThread: Unable to retrieve render client handle.";
  4407. goto Exit;
  4408. }
  4409. // configure renderEvent to trigger on every available render buffer
  4410. renderEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
  4411. if ( !renderEvent ) {
  4412. errorType = RtAudioError::SYSTEM_ERROR;
  4413. errorText = "RtApiWasapi::wasapiThread: Unable to create render event.";
  4414. goto Exit;
  4415. }
  4416. hr = renderAudioClient->SetEventHandle( renderEvent );
  4417. if ( FAILED( hr ) ) {
  4418. errorText = "RtApiWasapi::wasapiThread: Unable to set render event handle.";
  4419. goto Exit;
  4420. }
  4421. ( ( WasapiHandle* ) stream_.apiHandle )->renderClient = renderClient;
  4422. ( ( WasapiHandle* ) stream_.apiHandle )->renderEvent = renderEvent;
  4423. // reset the render stream
  4424. hr = renderAudioClient->Reset();
  4425. if ( FAILED( hr ) ) {
  4426. errorText = "RtApiWasapi::wasapiThread: Unable to reset render stream.";
  4427. goto Exit;
  4428. }
  4429. // start the render stream
  4430. hr = renderAudioClient->Start();
  4431. if ( FAILED( hr ) ) {
  4432. errorText = "RtApiWasapi::wasapiThread: Unable to start render stream.";
  4433. goto Exit;
  4434. }
  4435. }
  4436. unsigned int outBufferSize = 0;
  4437. hr = renderAudioClient->GetBufferSize( &outBufferSize );
  4438. if ( FAILED( hr ) ) {
  4439. errorText = "RtApiWasapi::wasapiThread: Unable to get render buffer size.";
  4440. goto Exit;
  4441. }
  4442. // scale inBufferSize according to user->stream sample rate ratio
  4443. unsigned int inBufferSize = ( unsigned int ) ceilf( stream_.bufferSize * renderSrRatio ) * stream_.nDeviceChannels[OUTPUT];
  4444. outBufferSize *= stream_.nDeviceChannels[OUTPUT];
  4445. // set renderBuffer size
  4446. renderBuffer.setBufferSize( inBufferSize + outBufferSize, formatBytes( stream_.deviceFormat[OUTPUT] ) );
  4447. }
  4448. // malloc buffer memory
  4449. if ( stream_.mode == INPUT )
  4450. {
  4451. using namespace std; // for ceilf
  4452. convBuffSize = ( unsigned int ) ( ceilf( stream_.bufferSize * captureSrRatio ) ) * stream_.nDeviceChannels[INPUT] * formatBytes( stream_.deviceFormat[INPUT] );
  4453. deviceBuffSize = stream_.bufferSize * stream_.nDeviceChannels[INPUT] * formatBytes( stream_.deviceFormat[INPUT] );
  4454. }
  4455. else if ( stream_.mode == OUTPUT )
  4456. {
  4457. convBuffSize = ( unsigned int ) ( ceilf( stream_.bufferSize * renderSrRatio ) ) * stream_.nDeviceChannels[OUTPUT] * formatBytes( stream_.deviceFormat[OUTPUT] );
  4458. deviceBuffSize = stream_.bufferSize * stream_.nDeviceChannels[OUTPUT] * formatBytes( stream_.deviceFormat[OUTPUT] );
  4459. }
  4460. else if ( stream_.mode == DUPLEX )
  4461. {
  4462. convBuffSize = std::max( ( unsigned int ) ( ceilf( stream_.bufferSize * captureSrRatio ) ) * stream_.nDeviceChannels[INPUT] * formatBytes( stream_.deviceFormat[INPUT] ),
  4463. ( unsigned int ) ( ceilf( stream_.bufferSize * renderSrRatio ) ) * stream_.nDeviceChannels[OUTPUT] * formatBytes( stream_.deviceFormat[OUTPUT] ) );
  4464. deviceBuffSize = std::max( stream_.bufferSize * stream_.nDeviceChannels[INPUT] * formatBytes( stream_.deviceFormat[INPUT] ),
  4465. stream_.bufferSize * stream_.nDeviceChannels[OUTPUT] * formatBytes( stream_.deviceFormat[OUTPUT] ) );
  4466. }
  4467. convBuffSize *= 2; // allow overflow for *SrRatio remainders
  4468. convBuffer = ( char* ) calloc( convBuffSize, 1 );
  4469. stream_.deviceBuffer = ( char* ) calloc( deviceBuffSize, 1 );
  4470. if ( !convBuffer || !stream_.deviceBuffer ) {
  4471. errorType = RtAudioError::MEMORY_ERROR;
  4472. errorText = "RtApiWasapi::wasapiThread: Error allocating device buffer memory.";
  4473. goto Exit;
  4474. }
  4475. // stream process loop
  4476. while ( stream_.state != STREAM_STOPPING ) {
  4477. if ( !callbackPulled ) {
  4478. // Callback Input
  4479. // ==============
  4480. // 1. Pull callback buffer from inputBuffer
  4481. // 2. If 1. was successful: Convert callback buffer to user sample rate and channel count
  4482. // Convert callback buffer to user format
  4483. if ( captureAudioClient )
  4484. {
  4485. int samplesToPull = ( unsigned int ) floorf( stream_.bufferSize * captureSrRatio );
  4486. convBufferSize = 0;
  4487. while ( convBufferSize < stream_.bufferSize )
  4488. {
  4489. // Pull callback buffer from inputBuffer
  4490. callbackPulled = captureBuffer.pullBuffer( convBuffer,
  4491. samplesToPull * stream_.nDeviceChannels[INPUT],
  4492. stream_.deviceFormat[INPUT] );
  4493. if ( !callbackPulled )
  4494. {
  4495. break;
  4496. }
  4497. // Convert callback buffer to user sample rate
  4498. unsigned int deviceBufferOffset = convBufferSize * stream_.nDeviceChannels[INPUT] * formatBytes( stream_.deviceFormat[INPUT] );
  4499. unsigned int convSamples = 0;
  4500. captureResampler->Convert( stream_.deviceBuffer + deviceBufferOffset,
  4501. convBuffer,
  4502. samplesToPull,
  4503. convSamples,
  4504. convBufferSize == 0 ? -1 : stream_.bufferSize - convBufferSize );
  4505. convBufferSize += convSamples;
  4506. samplesToPull = 1; // now pull one sample at a time until we have stream_.bufferSize samples
  4507. }
  4508. if ( callbackPulled )
  4509. {
  4510. if ( stream_.doConvertBuffer[INPUT] ) {
  4511. // Convert callback buffer to user format
  4512. convertBuffer( stream_.userBuffer[INPUT],
  4513. stream_.deviceBuffer,
  4514. stream_.convertInfo[INPUT] );
  4515. }
  4516. else {
  4517. // no further conversion, simple copy deviceBuffer to userBuffer
  4518. memcpy( stream_.userBuffer[INPUT],
  4519. stream_.deviceBuffer,
  4520. stream_.bufferSize * stream_.nUserChannels[INPUT] * formatBytes( stream_.userFormat ) );
  4521. }
  4522. }
  4523. }
  4524. else {
  4525. // if there is no capture stream, set callbackPulled flag
  4526. callbackPulled = true;
  4527. }
  4528. // Execute Callback
  4529. // ================
  4530. // 1. Execute user callback method
  4531. // 2. Handle return value from callback
  4532. // if callback has not requested the stream to stop
  4533. if ( callbackPulled && !callbackStopped ) {
  4534. // Execute user callback method
  4535. callbackResult = callback( stream_.userBuffer[OUTPUT],
  4536. stream_.userBuffer[INPUT],
  4537. stream_.bufferSize,
  4538. getStreamTime(),
  4539. captureFlags & AUDCLNT_BUFFERFLAGS_DATA_DISCONTINUITY ? RTAUDIO_INPUT_OVERFLOW : 0,
  4540. stream_.callbackInfo.userData );
  4541. // tick stream time
  4542. RtApi::tickStreamTime();
  4543. // Handle return value from callback
  4544. if ( callbackResult == 1 ) {
  4545. // instantiate a thread to stop this thread
  4546. HANDLE threadHandle = CreateThread( NULL, 0, stopWasapiThread, this, 0, NULL );
  4547. if ( !threadHandle ) {
  4548. errorType = RtAudioError::THREAD_ERROR;
  4549. errorText = "RtApiWasapi::wasapiThread: Unable to instantiate stream stop thread.";
  4550. goto Exit;
  4551. }
  4552. else if ( !CloseHandle( threadHandle ) ) {
  4553. errorType = RtAudioError::THREAD_ERROR;
  4554. errorText = "RtApiWasapi::wasapiThread: Unable to close stream stop thread handle.";
  4555. goto Exit;
  4556. }
  4557. callbackStopped = true;
  4558. }
  4559. else if ( callbackResult == 2 ) {
  4560. // instantiate a thread to stop this thread
  4561. HANDLE threadHandle = CreateThread( NULL, 0, abortWasapiThread, this, 0, NULL );
  4562. if ( !threadHandle ) {
  4563. errorType = RtAudioError::THREAD_ERROR;
  4564. errorText = "RtApiWasapi::wasapiThread: Unable to instantiate stream abort thread.";
  4565. goto Exit;
  4566. }
  4567. else if ( !CloseHandle( threadHandle ) ) {
  4568. errorType = RtAudioError::THREAD_ERROR;
  4569. errorText = "RtApiWasapi::wasapiThread: Unable to close stream abort thread handle.";
  4570. goto Exit;
  4571. }
  4572. callbackStopped = true;
  4573. }
  4574. }
  4575. }
  4576. // Callback Output
  4577. // ===============
  4578. // 1. Convert callback buffer to stream format
  4579. // 2. Convert callback buffer to stream sample rate and channel count
  4580. // 3. Push callback buffer into outputBuffer
  4581. if ( renderAudioClient && callbackPulled )
  4582. {
  4583. // if the last call to renderBuffer.PushBuffer() was successful
  4584. if ( callbackPushed || convBufferSize == 0 )
  4585. {
  4586. if ( stream_.doConvertBuffer[OUTPUT] )
  4587. {
  4588. // Convert callback buffer to stream format
  4589. convertBuffer( stream_.deviceBuffer,
  4590. stream_.userBuffer[OUTPUT],
  4591. stream_.convertInfo[OUTPUT] );
  4592. }
  4593. else {
  4594. // no further conversion, simple copy userBuffer to deviceBuffer
  4595. memcpy( stream_.deviceBuffer,
  4596. stream_.userBuffer[OUTPUT],
  4597. stream_.bufferSize * stream_.nUserChannels[OUTPUT] * formatBytes( stream_.userFormat ) );
  4598. }
  4599. // Convert callback buffer to stream sample rate
  4600. renderResampler->Convert( convBuffer,
  4601. stream_.deviceBuffer,
  4602. stream_.bufferSize,
  4603. convBufferSize );
  4604. }
  4605. // Push callback buffer into outputBuffer
  4606. callbackPushed = renderBuffer.pushBuffer( convBuffer,
  4607. convBufferSize * stream_.nDeviceChannels[OUTPUT],
  4608. stream_.deviceFormat[OUTPUT] );
  4609. }
  4610. else {
  4611. // if there is no render stream, set callbackPushed flag
  4612. callbackPushed = true;
  4613. }
  4614. // Stream Capture
  4615. // ==============
  4616. // 1. Get capture buffer from stream
  4617. // 2. Push capture buffer into inputBuffer
  4618. // 3. If 2. was successful: Release capture buffer
  4619. if ( captureAudioClient ) {
  4620. // if the callback input buffer was not pulled from captureBuffer, wait for next capture event
  4621. if ( !callbackPulled ) {
  4622. WaitForSingleObject( loopbackEnabled ? renderEvent : captureEvent, INFINITE );
  4623. }
  4624. // Get capture buffer from stream
  4625. hr = captureClient->GetBuffer( &streamBuffer,
  4626. &bufferFrameCount,
  4627. &captureFlags, NULL, NULL );
  4628. if ( FAILED( hr ) ) {
  4629. errorText = "RtApiWasapi::wasapiThread: Unable to retrieve capture buffer.";
  4630. goto Exit;
  4631. }
  4632. if ( bufferFrameCount != 0 ) {
  4633. // Push capture buffer into inputBuffer
  4634. if ( captureBuffer.pushBuffer( ( char* ) streamBuffer,
  4635. bufferFrameCount * stream_.nDeviceChannels[INPUT],
  4636. stream_.deviceFormat[INPUT] ) )
  4637. {
  4638. // Release capture buffer
  4639. hr = captureClient->ReleaseBuffer( bufferFrameCount );
  4640. if ( FAILED( hr ) ) {
  4641. errorText = "RtApiWasapi::wasapiThread: Unable to release capture buffer.";
  4642. goto Exit;
  4643. }
  4644. }
  4645. else
  4646. {
  4647. // Inform WASAPI that capture was unsuccessful
  4648. hr = captureClient->ReleaseBuffer( 0 );
  4649. if ( FAILED( hr ) ) {
  4650. errorText = "RtApiWasapi::wasapiThread: Unable to release capture buffer.";
  4651. goto Exit;
  4652. }
  4653. }
  4654. }
  4655. else
  4656. {
  4657. // Inform WASAPI that capture was unsuccessful
  4658. hr = captureClient->ReleaseBuffer( 0 );
  4659. if ( FAILED( hr ) ) {
  4660. errorText = "RtApiWasapi::wasapiThread: Unable to release capture buffer.";
  4661. goto Exit;
  4662. }
  4663. }
  4664. }
  4665. // Stream Render
  4666. // =============
  4667. // 1. Get render buffer from stream
  4668. // 2. Pull next buffer from outputBuffer
  4669. // 3. If 2. was successful: Fill render buffer with next buffer
  4670. // Release render buffer
  4671. if ( renderAudioClient ) {
  4672. // if the callback output buffer was not pushed to renderBuffer, wait for next render event
  4673. if ( callbackPulled && !callbackPushed ) {
  4674. WaitForSingleObject( renderEvent, INFINITE );
  4675. }
  4676. // Get render buffer from stream
  4677. hr = renderAudioClient->GetBufferSize( &bufferFrameCount );
  4678. if ( FAILED( hr ) ) {
  4679. errorText = "RtApiWasapi::wasapiThread: Unable to retrieve render buffer size.";
  4680. goto Exit;
  4681. }
  4682. hr = renderAudioClient->GetCurrentPadding( &numFramesPadding );
  4683. if ( FAILED( hr ) ) {
  4684. errorText = "RtApiWasapi::wasapiThread: Unable to retrieve render buffer padding.";
  4685. goto Exit;
  4686. }
  4687. bufferFrameCount -= numFramesPadding;
  4688. if ( bufferFrameCount != 0 ) {
  4689. hr = renderClient->GetBuffer( bufferFrameCount, &streamBuffer );
  4690. if ( FAILED( hr ) ) {
  4691. errorText = "RtApiWasapi::wasapiThread: Unable to retrieve render buffer.";
  4692. goto Exit;
  4693. }
  4694. // Pull next buffer from outputBuffer
  4695. // Fill render buffer with next buffer
  4696. if ( renderBuffer.pullBuffer( ( char* ) streamBuffer,
  4697. bufferFrameCount * stream_.nDeviceChannels[OUTPUT],
  4698. stream_.deviceFormat[OUTPUT] ) )
  4699. {
  4700. // Release render buffer
  4701. hr = renderClient->ReleaseBuffer( bufferFrameCount, 0 );
  4702. if ( FAILED( hr ) ) {
  4703. errorText = "RtApiWasapi::wasapiThread: Unable to release render buffer.";
  4704. goto Exit;
  4705. }
  4706. }
  4707. else
  4708. {
  4709. // Inform WASAPI that render was unsuccessful
  4710. hr = renderClient->ReleaseBuffer( 0, 0 );
  4711. if ( FAILED( hr ) ) {
  4712. errorText = "RtApiWasapi::wasapiThread: Unable to release render buffer.";
  4713. goto Exit;
  4714. }
  4715. }
  4716. }
  4717. else
  4718. {
  4719. // Inform WASAPI that render was unsuccessful
  4720. hr = renderClient->ReleaseBuffer( 0, 0 );
  4721. if ( FAILED( hr ) ) {
  4722. errorText = "RtApiWasapi::wasapiThread: Unable to release render buffer.";
  4723. goto Exit;
  4724. }
  4725. }
  4726. }
  4727. // if the callback buffer was pushed renderBuffer reset callbackPulled flag
  4728. if ( callbackPushed ) {
  4729. // unsetting the callbackPulled flag lets the stream know that
  4730. // the audio device is ready for another callback output buffer.
  4731. callbackPulled = false;
  4732. }
  4733. }
  4734. Exit:
  4735. // clean up
  4736. CoTaskMemFree( captureFormat );
  4737. CoTaskMemFree( renderFormat );
  4738. free ( convBuffer );
  4739. delete renderResampler;
  4740. delete captureResampler;
  4741. CoUninitialize();
  4742. if ( !errorText.empty() )
  4743. {
  4744. errorText_ = errorText;
  4745. error( errorType );
  4746. }
  4747. // update stream state
  4748. stream_.state = STREAM_STOPPED;
  4749. }
  4750. //******************** End of __WINDOWS_WASAPI__ *********************//
  4751. #endif
  4752. #if defined(__WINDOWS_DS__) // Windows DirectSound API
  4753. // Modified by Robin Davies, October 2005
  4754. // - Improvements to DirectX pointer chasing.
  4755. // - Bug fix for non-power-of-two Asio granularity used by Edirol PCR-A30.
  4756. // - Auto-call CoInitialize for DSOUND and ASIO platforms.
  4757. // Various revisions for RtAudio 4.0 by Gary Scavone, April 2007
  4758. // Changed device query structure for RtAudio 4.0.7, January 2010
  4759. #include <windows.h>
  4760. #include <process.h>
  4761. #include <mmsystem.h>
  4762. #include <mmreg.h>
  4763. #include <dsound.h>
  4764. #include <assert.h>
  4765. #include <algorithm>
  4766. #if defined(__MINGW32__)
  4767. // missing from latest mingw winapi
  4768. #define WAVE_FORMAT_96M08 0x00010000 /* 96 kHz, Mono, 8-bit */
  4769. #define WAVE_FORMAT_96S08 0x00020000 /* 96 kHz, Stereo, 8-bit */
  4770. #define WAVE_FORMAT_96M16 0x00040000 /* 96 kHz, Mono, 16-bit */
  4771. #define WAVE_FORMAT_96S16 0x00080000 /* 96 kHz, Stereo, 16-bit */
  4772. #endif
  4773. #define MINIMUM_DEVICE_BUFFER_SIZE 32768
  4774. #ifdef _MSC_VER // if Microsoft Visual C++
  4775. #pragma comment( lib, "winmm.lib" ) // then, auto-link winmm.lib. Otherwise, it has to be added manually.
  4776. #endif
  4777. static inline DWORD dsPointerBetween( DWORD pointer, DWORD laterPointer, DWORD earlierPointer, DWORD bufferSize )
  4778. {
  4779. if ( pointer > bufferSize ) pointer -= bufferSize;
  4780. if ( laterPointer < earlierPointer ) laterPointer += bufferSize;
  4781. if ( pointer < earlierPointer ) pointer += bufferSize;
  4782. return pointer >= earlierPointer && pointer < laterPointer;
  4783. }
  4784. // A structure to hold various information related to the DirectSound
  4785. // API implementation.
  4786. struct DsHandle {
  4787. unsigned int drainCounter; // Tracks callback counts when draining
  4788. bool internalDrain; // Indicates if stop is initiated from callback or not.
  4789. void *id[2];
  4790. void *buffer[2];
  4791. bool xrun[2];
  4792. UINT bufferPointer[2];
  4793. DWORD dsBufferSize[2];
  4794. DWORD dsPointerLeadTime[2]; // the number of bytes ahead of the safe pointer to lead by.
  4795. HANDLE condition;
  4796. DsHandle()
  4797. :drainCounter(0), internalDrain(false) { id[0] = 0; id[1] = 0; buffer[0] = 0; buffer[1] = 0; xrun[0] = false; xrun[1] = false; bufferPointer[0] = 0; bufferPointer[1] = 0; }
  4798. };
  4799. // Declarations for utility functions, callbacks, and structures
  4800. // specific to the DirectSound implementation.
  4801. static BOOL CALLBACK deviceQueryCallback( LPGUID lpguid,
  4802. LPCTSTR description,
  4803. LPCTSTR module,
  4804. LPVOID lpContext );
  4805. static const char* getErrorString( int code );
  4806. static unsigned __stdcall callbackHandler( void *ptr );
  4807. struct DsDevice {
  4808. LPGUID id[2];
  4809. bool validId[2];
  4810. bool found;
  4811. std::string name;
  4812. DsDevice()
  4813. : found(false) { validId[0] = false; validId[1] = false; }
  4814. };
  4815. struct DsProbeData {
  4816. bool isInput;
  4817. std::vector<struct DsDevice>* dsDevices;
  4818. };
  4819. RtApiDs :: RtApiDs()
  4820. {
  4821. // Dsound will run both-threaded. If CoInitialize fails, then just
  4822. // accept whatever the mainline chose for a threading model.
  4823. coInitialized_ = false;
  4824. HRESULT hr = CoInitialize( NULL );
  4825. if ( !FAILED( hr ) ) coInitialized_ = true;
  4826. }
  4827. RtApiDs :: ~RtApiDs()
  4828. {
  4829. if ( stream_.state != STREAM_CLOSED ) closeStream();
  4830. if ( coInitialized_ ) CoUninitialize(); // balanced call.
  4831. }
  4832. // The DirectSound default output is always the first device.
  4833. unsigned int RtApiDs :: getDefaultOutputDevice( void )
  4834. {
  4835. return 0;
  4836. }
  4837. // The DirectSound default input is always the first input device,
  4838. // which is the first capture device enumerated.
  4839. unsigned int RtApiDs :: getDefaultInputDevice( void )
  4840. {
  4841. return 0;
  4842. }
  4843. unsigned int RtApiDs :: getDeviceCount( void )
  4844. {
  4845. // Set query flag for previously found devices to false, so that we
  4846. // can check for any devices that have disappeared.
  4847. for ( unsigned int i=0; i<dsDevices.size(); i++ )
  4848. dsDevices[i].found = false;
  4849. // Query DirectSound devices.
  4850. struct DsProbeData probeInfo;
  4851. probeInfo.isInput = false;
  4852. probeInfo.dsDevices = &dsDevices;
  4853. HRESULT result = DirectSoundEnumerate( (LPDSENUMCALLBACK) deviceQueryCallback, &probeInfo );
  4854. if ( FAILED( result ) ) {
  4855. errorStream_ << "RtApiDs::getDeviceCount: error (" << getErrorString( result ) << ") enumerating output devices!";
  4856. errorText_ = errorStream_.str();
  4857. error( RtAudioError::WARNING );
  4858. }
  4859. // Query DirectSoundCapture devices.
  4860. probeInfo.isInput = true;
  4861. result = DirectSoundCaptureEnumerate( (LPDSENUMCALLBACK) deviceQueryCallback, &probeInfo );
  4862. if ( FAILED( result ) ) {
  4863. errorStream_ << "RtApiDs::getDeviceCount: error (" << getErrorString( result ) << ") enumerating input devices!";
  4864. errorText_ = errorStream_.str();
  4865. error( RtAudioError::WARNING );
  4866. }
  4867. // Clean out any devices that may have disappeared (code update submitted by Eli Zehngut).
  4868. for ( unsigned int i=0; i<dsDevices.size(); ) {
  4869. if ( dsDevices[i].found == false ) dsDevices.erase( dsDevices.begin() + i );
  4870. else i++;
  4871. }
  4872. return static_cast<unsigned int>(dsDevices.size());
  4873. }
  4874. RtAudio::DeviceInfo RtApiDs :: getDeviceInfo( unsigned int device )
  4875. {
  4876. RtAudio::DeviceInfo info;
  4877. info.probed = false;
  4878. if ( dsDevices.size() == 0 ) {
  4879. // Force a query of all devices
  4880. getDeviceCount();
  4881. if ( dsDevices.size() == 0 ) {
  4882. errorText_ = "RtApiDs::getDeviceInfo: no devices found!";
  4883. error( RtAudioError::INVALID_USE );
  4884. return info;
  4885. }
  4886. }
  4887. if ( device >= dsDevices.size() ) {
  4888. errorText_ = "RtApiDs::getDeviceInfo: device ID is invalid!";
  4889. error( RtAudioError::INVALID_USE );
  4890. return info;
  4891. }
  4892. HRESULT result;
  4893. if ( dsDevices[ device ].validId[0] == false ) goto probeInput;
  4894. LPDIRECTSOUND output;
  4895. DSCAPS outCaps;
  4896. result = DirectSoundCreate( dsDevices[ device ].id[0], &output, NULL );
  4897. if ( FAILED( result ) ) {
  4898. errorStream_ << "RtApiDs::getDeviceInfo: error (" << getErrorString( result ) << ") opening output device (" << dsDevices[ device ].name << ")!";
  4899. errorText_ = errorStream_.str();
  4900. error( RtAudioError::WARNING );
  4901. goto probeInput;
  4902. }
  4903. outCaps.dwSize = sizeof( outCaps );
  4904. result = output->GetCaps( &outCaps );
  4905. if ( FAILED( result ) ) {
  4906. output->Release();
  4907. errorStream_ << "RtApiDs::getDeviceInfo: error (" << getErrorString( result ) << ") getting capabilities!";
  4908. errorText_ = errorStream_.str();
  4909. error( RtAudioError::WARNING );
  4910. goto probeInput;
  4911. }
  4912. // Get output channel information.
  4913. info.outputChannels = ( outCaps.dwFlags & DSCAPS_PRIMARYSTEREO ) ? 2 : 1;
  4914. // Get sample rate information.
  4915. info.sampleRates.clear();
  4916. for ( unsigned int k=0; k<MAX_SAMPLE_RATES; k++ ) {
  4917. if ( SAMPLE_RATES[k] >= (unsigned int) outCaps.dwMinSecondarySampleRate &&
  4918. SAMPLE_RATES[k] <= (unsigned int) outCaps.dwMaxSecondarySampleRate ) {
  4919. info.sampleRates.push_back( SAMPLE_RATES[k] );
  4920. if ( !info.preferredSampleRate || ( SAMPLE_RATES[k] <= 48000 && SAMPLE_RATES[k] > info.preferredSampleRate ) )
  4921. info.preferredSampleRate = SAMPLE_RATES[k];
  4922. }
  4923. }
  4924. // Get format information.
  4925. if ( outCaps.dwFlags & DSCAPS_PRIMARY16BIT ) info.nativeFormats |= RTAUDIO_SINT16;
  4926. if ( outCaps.dwFlags & DSCAPS_PRIMARY8BIT ) info.nativeFormats |= RTAUDIO_SINT8;
  4927. output->Release();
  4928. if ( getDefaultOutputDevice() == device )
  4929. info.isDefaultOutput = true;
  4930. if ( dsDevices[ device ].validId[1] == false ) {
  4931. info.name = dsDevices[ device ].name;
  4932. info.probed = true;
  4933. return info;
  4934. }
  4935. probeInput:
  4936. LPDIRECTSOUNDCAPTURE input;
  4937. result = DirectSoundCaptureCreate( dsDevices[ device ].id[1], &input, NULL );
  4938. if ( FAILED( result ) ) {
  4939. errorStream_ << "RtApiDs::getDeviceInfo: error (" << getErrorString( result ) << ") opening input device (" << dsDevices[ device ].name << ")!";
  4940. errorText_ = errorStream_.str();
  4941. error( RtAudioError::WARNING );
  4942. return info;
  4943. }
  4944. DSCCAPS inCaps;
  4945. inCaps.dwSize = sizeof( inCaps );
  4946. result = input->GetCaps( &inCaps );
  4947. if ( FAILED( result ) ) {
  4948. input->Release();
  4949. errorStream_ << "RtApiDs::getDeviceInfo: error (" << getErrorString( result ) << ") getting object capabilities (" << dsDevices[ device ].name << ")!";
  4950. errorText_ = errorStream_.str();
  4951. error( RtAudioError::WARNING );
  4952. return info;
  4953. }
  4954. // Get input channel information.
  4955. info.inputChannels = inCaps.dwChannels;
  4956. // Get sample rate and format information.
  4957. std::vector<unsigned int> rates;
  4958. if ( inCaps.dwChannels >= 2 ) {
  4959. if ( inCaps.dwFormats & WAVE_FORMAT_1S16 ) info.nativeFormats |= RTAUDIO_SINT16;
  4960. if ( inCaps.dwFormats & WAVE_FORMAT_2S16 ) info.nativeFormats |= RTAUDIO_SINT16;
  4961. if ( inCaps.dwFormats & WAVE_FORMAT_4S16 ) info.nativeFormats |= RTAUDIO_SINT16;
  4962. if ( inCaps.dwFormats & WAVE_FORMAT_96S16 ) info.nativeFormats |= RTAUDIO_SINT16;
  4963. if ( inCaps.dwFormats & WAVE_FORMAT_1S08 ) info.nativeFormats |= RTAUDIO_SINT8;
  4964. if ( inCaps.dwFormats & WAVE_FORMAT_2S08 ) info.nativeFormats |= RTAUDIO_SINT8;
  4965. if ( inCaps.dwFormats & WAVE_FORMAT_4S08 ) info.nativeFormats |= RTAUDIO_SINT8;
  4966. if ( inCaps.dwFormats & WAVE_FORMAT_96S08 ) info.nativeFormats |= RTAUDIO_SINT8;
  4967. if ( info.nativeFormats & RTAUDIO_SINT16 ) {
  4968. if ( inCaps.dwFormats & WAVE_FORMAT_1S16 ) rates.push_back( 11025 );
  4969. if ( inCaps.dwFormats & WAVE_FORMAT_2S16 ) rates.push_back( 22050 );
  4970. if ( inCaps.dwFormats & WAVE_FORMAT_4S16 ) rates.push_back( 44100 );
  4971. if ( inCaps.dwFormats & WAVE_FORMAT_96S16 ) rates.push_back( 96000 );
  4972. }
  4973. else if ( info.nativeFormats & RTAUDIO_SINT8 ) {
  4974. if ( inCaps.dwFormats & WAVE_FORMAT_1S08 ) rates.push_back( 11025 );
  4975. if ( inCaps.dwFormats & WAVE_FORMAT_2S08 ) rates.push_back( 22050 );
  4976. if ( inCaps.dwFormats & WAVE_FORMAT_4S08 ) rates.push_back( 44100 );
  4977. if ( inCaps.dwFormats & WAVE_FORMAT_96S08 ) rates.push_back( 96000 );
  4978. }
  4979. }
  4980. else if ( inCaps.dwChannels == 1 ) {
  4981. if ( inCaps.dwFormats & WAVE_FORMAT_1M16 ) info.nativeFormats |= RTAUDIO_SINT16;
  4982. if ( inCaps.dwFormats & WAVE_FORMAT_2M16 ) info.nativeFormats |= RTAUDIO_SINT16;
  4983. if ( inCaps.dwFormats & WAVE_FORMAT_4M16 ) info.nativeFormats |= RTAUDIO_SINT16;
  4984. if ( inCaps.dwFormats & WAVE_FORMAT_96M16 ) info.nativeFormats |= RTAUDIO_SINT16;
  4985. if ( inCaps.dwFormats & WAVE_FORMAT_1M08 ) info.nativeFormats |= RTAUDIO_SINT8;
  4986. if ( inCaps.dwFormats & WAVE_FORMAT_2M08 ) info.nativeFormats |= RTAUDIO_SINT8;
  4987. if ( inCaps.dwFormats & WAVE_FORMAT_4M08 ) info.nativeFormats |= RTAUDIO_SINT8;
  4988. if ( inCaps.dwFormats & WAVE_FORMAT_96M08 ) info.nativeFormats |= RTAUDIO_SINT8;
  4989. if ( info.nativeFormats & RTAUDIO_SINT16 ) {
  4990. if ( inCaps.dwFormats & WAVE_FORMAT_1M16 ) rates.push_back( 11025 );
  4991. if ( inCaps.dwFormats & WAVE_FORMAT_2M16 ) rates.push_back( 22050 );
  4992. if ( inCaps.dwFormats & WAVE_FORMAT_4M16 ) rates.push_back( 44100 );
  4993. if ( inCaps.dwFormats & WAVE_FORMAT_96M16 ) rates.push_back( 96000 );
  4994. }
  4995. else if ( info.nativeFormats & RTAUDIO_SINT8 ) {
  4996. if ( inCaps.dwFormats & WAVE_FORMAT_1M08 ) rates.push_back( 11025 );
  4997. if ( inCaps.dwFormats & WAVE_FORMAT_2M08 ) rates.push_back( 22050 );
  4998. if ( inCaps.dwFormats & WAVE_FORMAT_4M08 ) rates.push_back( 44100 );
  4999. if ( inCaps.dwFormats & WAVE_FORMAT_96M08 ) rates.push_back( 96000 );
  5000. }
  5001. }
  5002. else info.inputChannels = 0; // technically, this would be an error
  5003. input->Release();
  5004. if ( info.inputChannels == 0 ) return info;
  5005. // Copy the supported rates to the info structure but avoid duplication.
  5006. bool found;
  5007. for ( unsigned int i=0; i<rates.size(); i++ ) {
  5008. found = false;
  5009. for ( unsigned int j=0; j<info.sampleRates.size(); j++ ) {
  5010. if ( rates[i] == info.sampleRates[j] ) {
  5011. found = true;
  5012. break;
  5013. }
  5014. }
  5015. if ( found == false ) info.sampleRates.push_back( rates[i] );
  5016. }
  5017. std::sort( info.sampleRates.begin(), info.sampleRates.end() );
  5018. // If device opens for both playback and capture, we determine the channels.
  5019. if ( info.outputChannels > 0 && info.inputChannels > 0 )
  5020. info.duplexChannels = (info.outputChannels > info.inputChannels) ? info.inputChannels : info.outputChannels;
  5021. if ( device == 0 ) info.isDefaultInput = true;
  5022. // Copy name and return.
  5023. info.name = dsDevices[ device ].name;
  5024. info.probed = true;
  5025. return info;
  5026. }
  5027. bool RtApiDs :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels,
  5028. unsigned int firstChannel, unsigned int sampleRate,
  5029. RtAudioFormat format, unsigned int *bufferSize,
  5030. RtAudio::StreamOptions *options )
  5031. {
  5032. if ( channels + firstChannel > 2 ) {
  5033. errorText_ = "RtApiDs::probeDeviceOpen: DirectSound does not support more than 2 channels per device.";
  5034. return FAILURE;
  5035. }
  5036. size_t nDevices = dsDevices.size();
  5037. if ( nDevices == 0 ) {
  5038. // This should not happen because a check is made before this function is called.
  5039. errorText_ = "RtApiDs::probeDeviceOpen: no devices found!";
  5040. return FAILURE;
  5041. }
  5042. if ( device >= nDevices ) {
  5043. // This should not happen because a check is made before this function is called.
  5044. errorText_ = "RtApiDs::probeDeviceOpen: device ID is invalid!";
  5045. return FAILURE;
  5046. }
  5047. if ( mode == OUTPUT ) {
  5048. if ( dsDevices[ device ].validId[0] == false ) {
  5049. errorStream_ << "RtApiDs::probeDeviceOpen: device (" << device << ") does not support output!";
  5050. errorText_ = errorStream_.str();
  5051. return FAILURE;
  5052. }
  5053. }
  5054. else { // mode == INPUT
  5055. if ( dsDevices[ device ].validId[1] == false ) {
  5056. errorStream_ << "RtApiDs::probeDeviceOpen: device (" << device << ") does not support input!";
  5057. errorText_ = errorStream_.str();
  5058. return FAILURE;
  5059. }
  5060. }
  5061. // According to a note in PortAudio, using GetDesktopWindow()
  5062. // instead of GetForegroundWindow() is supposed to avoid problems
  5063. // that occur when the application's window is not the foreground
  5064. // window. Also, if the application window closes before the
  5065. // DirectSound buffer, DirectSound can crash. In the past, I had
  5066. // problems when using GetDesktopWindow() but it seems fine now
  5067. // (January 2010). I'll leave it commented here.
  5068. // HWND hWnd = GetForegroundWindow();
  5069. HWND hWnd = GetDesktopWindow();
  5070. // Check the numberOfBuffers parameter and limit the lowest value to
  5071. // two. This is a judgement call and a value of two is probably too
  5072. // low for capture, but it should work for playback.
  5073. int nBuffers = 0;
  5074. if ( options ) nBuffers = options->numberOfBuffers;
  5075. if ( options && options->flags & RTAUDIO_MINIMIZE_LATENCY ) nBuffers = 2;
  5076. if ( nBuffers < 2 ) nBuffers = 3;
  5077. // Check the lower range of the user-specified buffer size and set
  5078. // (arbitrarily) to a lower bound of 32.
  5079. if ( *bufferSize < 32 ) *bufferSize = 32;
  5080. // Create the wave format structure. The data format setting will
  5081. // be determined later.
  5082. WAVEFORMATEX waveFormat;
  5083. ZeroMemory( &waveFormat, sizeof(WAVEFORMATEX) );
  5084. waveFormat.wFormatTag = WAVE_FORMAT_PCM;
  5085. waveFormat.nChannels = channels + firstChannel;
  5086. waveFormat.nSamplesPerSec = (unsigned long) sampleRate;
  5087. // Determine the device buffer size. By default, we'll use the value
  5088. // defined above (32K), but we will grow it to make allowances for
  5089. // very large software buffer sizes.
  5090. DWORD dsBufferSize = MINIMUM_DEVICE_BUFFER_SIZE;
  5091. DWORD dsPointerLeadTime = 0;
  5092. void *ohandle = 0, *bhandle = 0;
  5093. HRESULT result;
  5094. if ( mode == OUTPUT ) {
  5095. LPDIRECTSOUND output;
  5096. result = DirectSoundCreate( dsDevices[ device ].id[0], &output, NULL );
  5097. if ( FAILED( result ) ) {
  5098. errorStream_ << "RtApiDs::probeDeviceOpen: error (" << getErrorString( result ) << ") opening output device (" << dsDevices[ device ].name << ")!";
  5099. errorText_ = errorStream_.str();
  5100. return FAILURE;
  5101. }
  5102. DSCAPS outCaps;
  5103. outCaps.dwSize = sizeof( outCaps );
  5104. result = output->GetCaps( &outCaps );
  5105. if ( FAILED( result ) ) {
  5106. output->Release();
  5107. errorStream_ << "RtApiDs::probeDeviceOpen: error (" << getErrorString( result ) << ") getting capabilities (" << dsDevices[ device ].name << ")!";
  5108. errorText_ = errorStream_.str();
  5109. return FAILURE;
  5110. }
  5111. // Check channel information.
  5112. if ( channels + firstChannel == 2 && !( outCaps.dwFlags & DSCAPS_PRIMARYSTEREO ) ) {
  5113. errorStream_ << "RtApiDs::getDeviceInfo: the output device (" << dsDevices[ device ].name << ") does not support stereo playback.";
  5114. errorText_ = errorStream_.str();
  5115. return FAILURE;
  5116. }
  5117. // Check format information. Use 16-bit format unless not
  5118. // supported or user requests 8-bit.
  5119. if ( outCaps.dwFlags & DSCAPS_PRIMARY16BIT &&
  5120. !( format == RTAUDIO_SINT8 && outCaps.dwFlags & DSCAPS_PRIMARY8BIT ) ) {
  5121. waveFormat.wBitsPerSample = 16;
  5122. stream_.deviceFormat[mode] = RTAUDIO_SINT16;
  5123. }
  5124. else {
  5125. waveFormat.wBitsPerSample = 8;
  5126. stream_.deviceFormat[mode] = RTAUDIO_SINT8;
  5127. }
  5128. stream_.userFormat = format;
  5129. // Update wave format structure and buffer information.
  5130. waveFormat.nBlockAlign = waveFormat.nChannels * waveFormat.wBitsPerSample / 8;
  5131. waveFormat.nAvgBytesPerSec = waveFormat.nSamplesPerSec * waveFormat.nBlockAlign;
  5132. dsPointerLeadTime = nBuffers * (*bufferSize) * (waveFormat.wBitsPerSample / 8) * channels;
  5133. // If the user wants an even bigger buffer, increase the device buffer size accordingly.
  5134. while ( dsPointerLeadTime * 2U > dsBufferSize )
  5135. dsBufferSize *= 2;
  5136. // Set cooperative level to DSSCL_EXCLUSIVE ... sound stops when window focus changes.
  5137. // result = output->SetCooperativeLevel( hWnd, DSSCL_EXCLUSIVE );
  5138. // Set cooperative level to DSSCL_PRIORITY ... sound remains when window focus changes.
  5139. result = output->SetCooperativeLevel( hWnd, DSSCL_PRIORITY );
  5140. if ( FAILED( result ) ) {
  5141. output->Release();
  5142. errorStream_ << "RtApiDs::probeDeviceOpen: error (" << getErrorString( result ) << ") setting cooperative level (" << dsDevices[ device ].name << ")!";
  5143. errorText_ = errorStream_.str();
  5144. return FAILURE;
  5145. }
  5146. // Even though we will write to the secondary buffer, we need to
  5147. // access the primary buffer to set the correct output format
  5148. // (since the default is 8-bit, 22 kHz!). Setup the DS primary
  5149. // buffer description.
  5150. DSBUFFERDESC bufferDescription;
  5151. ZeroMemory( &bufferDescription, sizeof( DSBUFFERDESC ) );
  5152. bufferDescription.dwSize = sizeof( DSBUFFERDESC );
  5153. bufferDescription.dwFlags = DSBCAPS_PRIMARYBUFFER;
  5154. // Obtain the primary buffer
  5155. LPDIRECTSOUNDBUFFER buffer;
  5156. result = output->CreateSoundBuffer( &bufferDescription, &buffer, NULL );
  5157. if ( FAILED( result ) ) {
  5158. output->Release();
  5159. errorStream_ << "RtApiDs::probeDeviceOpen: error (" << getErrorString( result ) << ") accessing primary buffer (" << dsDevices[ device ].name << ")!";
  5160. errorText_ = errorStream_.str();
  5161. return FAILURE;
  5162. }
  5163. // Set the primary DS buffer sound format.
  5164. result = buffer->SetFormat( &waveFormat );
  5165. if ( FAILED( result ) ) {
  5166. output->Release();
  5167. errorStream_ << "RtApiDs::probeDeviceOpen: error (" << getErrorString( result ) << ") setting primary buffer format (" << dsDevices[ device ].name << ")!";
  5168. errorText_ = errorStream_.str();
  5169. return FAILURE;
  5170. }
  5171. // Setup the secondary DS buffer description.
  5172. ZeroMemory( &bufferDescription, sizeof( DSBUFFERDESC ) );
  5173. bufferDescription.dwSize = sizeof( DSBUFFERDESC );
  5174. bufferDescription.dwFlags = ( DSBCAPS_STICKYFOCUS |
  5175. DSBCAPS_GLOBALFOCUS |
  5176. DSBCAPS_GETCURRENTPOSITION2 |
  5177. DSBCAPS_LOCHARDWARE ); // Force hardware mixing
  5178. bufferDescription.dwBufferBytes = dsBufferSize;
  5179. bufferDescription.lpwfxFormat = &waveFormat;
  5180. // Try to create the secondary DS buffer. If that doesn't work,
  5181. // try to use software mixing. Otherwise, there's a problem.
  5182. result = output->CreateSoundBuffer( &bufferDescription, &buffer, NULL );
  5183. if ( FAILED( result ) ) {
  5184. bufferDescription.dwFlags = ( DSBCAPS_STICKYFOCUS |
  5185. DSBCAPS_GLOBALFOCUS |
  5186. DSBCAPS_GETCURRENTPOSITION2 |
  5187. DSBCAPS_LOCSOFTWARE ); // Force software mixing
  5188. result = output->CreateSoundBuffer( &bufferDescription, &buffer, NULL );
  5189. if ( FAILED( result ) ) {
  5190. output->Release();
  5191. errorStream_ << "RtApiDs::probeDeviceOpen: error (" << getErrorString( result ) << ") creating secondary buffer (" << dsDevices[ device ].name << ")!";
  5192. errorText_ = errorStream_.str();
  5193. return FAILURE;
  5194. }
  5195. }
  5196. // Get the buffer size ... might be different from what we specified.
  5197. DSBCAPS dsbcaps;
  5198. dsbcaps.dwSize = sizeof( DSBCAPS );
  5199. result = buffer->GetCaps( &dsbcaps );
  5200. if ( FAILED( result ) ) {
  5201. output->Release();
  5202. buffer->Release();
  5203. errorStream_ << "RtApiDs::probeDeviceOpen: error (" << getErrorString( result ) << ") getting buffer settings (" << dsDevices[ device ].name << ")!";
  5204. errorText_ = errorStream_.str();
  5205. return FAILURE;
  5206. }
  5207. dsBufferSize = dsbcaps.dwBufferBytes;
  5208. // Lock the DS buffer
  5209. LPVOID audioPtr;
  5210. DWORD dataLen;
  5211. result = buffer->Lock( 0, dsBufferSize, &audioPtr, &dataLen, NULL, NULL, 0 );
  5212. if ( FAILED( result ) ) {
  5213. output->Release();
  5214. buffer->Release();
  5215. errorStream_ << "RtApiDs::probeDeviceOpen: error (" << getErrorString( result ) << ") locking buffer (" << dsDevices[ device ].name << ")!";
  5216. errorText_ = errorStream_.str();
  5217. return FAILURE;
  5218. }
  5219. // Zero the DS buffer
  5220. ZeroMemory( audioPtr, dataLen );
  5221. // Unlock the DS buffer
  5222. result = buffer->Unlock( audioPtr, dataLen, NULL, 0 );
  5223. if ( FAILED( result ) ) {
  5224. output->Release();
  5225. buffer->Release();
  5226. errorStream_ << "RtApiDs::probeDeviceOpen: error (" << getErrorString( result ) << ") unlocking buffer (" << dsDevices[ device ].name << ")!";
  5227. errorText_ = errorStream_.str();
  5228. return FAILURE;
  5229. }
  5230. ohandle = (void *) output;
  5231. bhandle = (void *) buffer;
  5232. }
  5233. if ( mode == INPUT ) {
  5234. LPDIRECTSOUNDCAPTURE input;
  5235. result = DirectSoundCaptureCreate( dsDevices[ device ].id[1], &input, NULL );
  5236. if ( FAILED( result ) ) {
  5237. errorStream_ << "RtApiDs::probeDeviceOpen: error (" << getErrorString( result ) << ") opening input device (" << dsDevices[ device ].name << ")!";
  5238. errorText_ = errorStream_.str();
  5239. return FAILURE;
  5240. }
  5241. DSCCAPS inCaps;
  5242. inCaps.dwSize = sizeof( inCaps );
  5243. result = input->GetCaps( &inCaps );
  5244. if ( FAILED( result ) ) {
  5245. input->Release();
  5246. errorStream_ << "RtApiDs::probeDeviceOpen: error (" << getErrorString( result ) << ") getting input capabilities (" << dsDevices[ device ].name << ")!";
  5247. errorText_ = errorStream_.str();
  5248. return FAILURE;
  5249. }
  5250. // Check channel information.
  5251. if ( inCaps.dwChannels < channels + firstChannel ) {
  5252. errorText_ = "RtApiDs::getDeviceInfo: the input device does not support requested input channels.";
  5253. return FAILURE;
  5254. }
  5255. // Check format information. Use 16-bit format unless user
  5256. // requests 8-bit.
  5257. DWORD deviceFormats;
  5258. if ( channels + firstChannel == 2 ) {
  5259. deviceFormats = WAVE_FORMAT_1S08 | WAVE_FORMAT_2S08 | WAVE_FORMAT_4S08 | WAVE_FORMAT_96S08;
  5260. if ( format == RTAUDIO_SINT8 && inCaps.dwFormats & deviceFormats ) {
  5261. waveFormat.wBitsPerSample = 8;
  5262. stream_.deviceFormat[mode] = RTAUDIO_SINT8;
  5263. }
  5264. else { // assume 16-bit is supported
  5265. waveFormat.wBitsPerSample = 16;
  5266. stream_.deviceFormat[mode] = RTAUDIO_SINT16;
  5267. }
  5268. }
  5269. else { // channel == 1
  5270. deviceFormats = WAVE_FORMAT_1M08 | WAVE_FORMAT_2M08 | WAVE_FORMAT_4M08 | WAVE_FORMAT_96M08;
  5271. if ( format == RTAUDIO_SINT8 && inCaps.dwFormats & deviceFormats ) {
  5272. waveFormat.wBitsPerSample = 8;
  5273. stream_.deviceFormat[mode] = RTAUDIO_SINT8;
  5274. }
  5275. else { // assume 16-bit is supported
  5276. waveFormat.wBitsPerSample = 16;
  5277. stream_.deviceFormat[mode] = RTAUDIO_SINT16;
  5278. }
  5279. }
  5280. stream_.userFormat = format;
  5281. // Update wave format structure and buffer information.
  5282. waveFormat.nBlockAlign = waveFormat.nChannels * waveFormat.wBitsPerSample / 8;
  5283. waveFormat.nAvgBytesPerSec = waveFormat.nSamplesPerSec * waveFormat.nBlockAlign;
  5284. dsPointerLeadTime = nBuffers * (*bufferSize) * (waveFormat.wBitsPerSample / 8) * channels;
  5285. // If the user wants an even bigger buffer, increase the device buffer size accordingly.
  5286. while ( dsPointerLeadTime * 2U > dsBufferSize )
  5287. dsBufferSize *= 2;
  5288. // Setup the secondary DS buffer description.
  5289. DSCBUFFERDESC bufferDescription;
  5290. ZeroMemory( &bufferDescription, sizeof( DSCBUFFERDESC ) );
  5291. bufferDescription.dwSize = sizeof( DSCBUFFERDESC );
  5292. bufferDescription.dwFlags = 0;
  5293. bufferDescription.dwReserved = 0;
  5294. bufferDescription.dwBufferBytes = dsBufferSize;
  5295. bufferDescription.lpwfxFormat = &waveFormat;
  5296. // Create the capture buffer.
  5297. LPDIRECTSOUNDCAPTUREBUFFER buffer;
  5298. result = input->CreateCaptureBuffer( &bufferDescription, &buffer, NULL );
  5299. if ( FAILED( result ) ) {
  5300. input->Release();
  5301. errorStream_ << "RtApiDs::probeDeviceOpen: error (" << getErrorString( result ) << ") creating input buffer (" << dsDevices[ device ].name << ")!";
  5302. errorText_ = errorStream_.str();
  5303. return FAILURE;
  5304. }
  5305. // Get the buffer size ... might be different from what we specified.
  5306. DSCBCAPS dscbcaps;
  5307. dscbcaps.dwSize = sizeof( DSCBCAPS );
  5308. result = buffer->GetCaps( &dscbcaps );
  5309. if ( FAILED( result ) ) {
  5310. input->Release();
  5311. buffer->Release();
  5312. errorStream_ << "RtApiDs::probeDeviceOpen: error (" << getErrorString( result ) << ") getting buffer settings (" << dsDevices[ device ].name << ")!";
  5313. errorText_ = errorStream_.str();
  5314. return FAILURE;
  5315. }
  5316. dsBufferSize = dscbcaps.dwBufferBytes;
  5317. // NOTE: We could have a problem here if this is a duplex stream
  5318. // and the play and capture hardware buffer sizes are different
  5319. // (I'm actually not sure if that is a problem or not).
  5320. // Currently, we are not verifying that.
  5321. // Lock the capture buffer
  5322. LPVOID audioPtr;
  5323. DWORD dataLen;
  5324. result = buffer->Lock( 0, dsBufferSize, &audioPtr, &dataLen, NULL, NULL, 0 );
  5325. if ( FAILED( result ) ) {
  5326. input->Release();
  5327. buffer->Release();
  5328. errorStream_ << "RtApiDs::probeDeviceOpen: error (" << getErrorString( result ) << ") locking input buffer (" << dsDevices[ device ].name << ")!";
  5329. errorText_ = errorStream_.str();
  5330. return FAILURE;
  5331. }
  5332. // Zero the buffer
  5333. ZeroMemory( audioPtr, dataLen );
  5334. // Unlock the buffer
  5335. result = buffer->Unlock( audioPtr, dataLen, NULL, 0 );
  5336. if ( FAILED( result ) ) {
  5337. input->Release();
  5338. buffer->Release();
  5339. errorStream_ << "RtApiDs::probeDeviceOpen: error (" << getErrorString( result ) << ") unlocking input buffer (" << dsDevices[ device ].name << ")!";
  5340. errorText_ = errorStream_.str();
  5341. return FAILURE;
  5342. }
  5343. ohandle = (void *) input;
  5344. bhandle = (void *) buffer;
  5345. }
  5346. // Set various stream parameters
  5347. DsHandle *handle = 0;
  5348. stream_.nDeviceChannels[mode] = channels + firstChannel;
  5349. stream_.nUserChannels[mode] = channels;
  5350. stream_.bufferSize = *bufferSize;
  5351. stream_.channelOffset[mode] = firstChannel;
  5352. stream_.deviceInterleaved[mode] = true;
  5353. if ( options && options->flags & RTAUDIO_NONINTERLEAVED ) stream_.userInterleaved = false;
  5354. else stream_.userInterleaved = true;
  5355. // Set flag for buffer conversion
  5356. stream_.doConvertBuffer[mode] = false;
  5357. if (stream_.nUserChannels[mode] != stream_.nDeviceChannels[mode])
  5358. stream_.doConvertBuffer[mode] = true;
  5359. if (stream_.userFormat != stream_.deviceFormat[mode])
  5360. stream_.doConvertBuffer[mode] = true;
  5361. if ( stream_.userInterleaved != stream_.deviceInterleaved[mode] &&
  5362. stream_.nUserChannels[mode] > 1 )
  5363. stream_.doConvertBuffer[mode] = true;
  5364. // Allocate necessary internal buffers
  5365. long bufferBytes = stream_.nUserChannels[mode] * *bufferSize * formatBytes( stream_.userFormat );
  5366. stream_.userBuffer[mode] = (char *) calloc( bufferBytes, 1 );
  5367. if ( stream_.userBuffer[mode] == NULL ) {
  5368. errorText_ = "RtApiDs::probeDeviceOpen: error allocating user buffer memory.";
  5369. goto error;
  5370. }
  5371. if ( stream_.doConvertBuffer[mode] ) {
  5372. bool makeBuffer = true;
  5373. bufferBytes = stream_.nDeviceChannels[mode] * formatBytes( stream_.deviceFormat[mode] );
  5374. if ( mode == INPUT ) {
  5375. if ( stream_.mode == OUTPUT && stream_.deviceBuffer ) {
  5376. unsigned long bytesOut = stream_.nDeviceChannels[0] * formatBytes( stream_.deviceFormat[0] );
  5377. if ( bufferBytes <= (long) bytesOut ) makeBuffer = false;
  5378. }
  5379. }
  5380. if ( makeBuffer ) {
  5381. bufferBytes *= *bufferSize;
  5382. if ( stream_.deviceBuffer ) free( stream_.deviceBuffer );
  5383. stream_.deviceBuffer = (char *) calloc( bufferBytes, 1 );
  5384. if ( stream_.deviceBuffer == NULL ) {
  5385. errorText_ = "RtApiDs::probeDeviceOpen: error allocating device buffer memory.";
  5386. goto error;
  5387. }
  5388. }
  5389. }
  5390. // Allocate our DsHandle structures for the stream.
  5391. if ( stream_.apiHandle == 0 ) {
  5392. try {
  5393. handle = new DsHandle;
  5394. }
  5395. catch ( std::bad_alloc& ) {
  5396. errorText_ = "RtApiDs::probeDeviceOpen: error allocating AsioHandle memory.";
  5397. goto error;
  5398. }
  5399. // Create a manual-reset event.
  5400. handle->condition = CreateEvent( NULL, // no security
  5401. TRUE, // manual-reset
  5402. FALSE, // non-signaled initially
  5403. NULL ); // unnamed
  5404. stream_.apiHandle = (void *) handle;
  5405. }
  5406. else
  5407. handle = (DsHandle *) stream_.apiHandle;
  5408. handle->id[mode] = ohandle;
  5409. handle->buffer[mode] = bhandle;
  5410. handle->dsBufferSize[mode] = dsBufferSize;
  5411. handle->dsPointerLeadTime[mode] = dsPointerLeadTime;
  5412. stream_.device[mode] = device;
  5413. stream_.state = STREAM_STOPPED;
  5414. if ( stream_.mode == OUTPUT && mode == INPUT )
  5415. // We had already set up an output stream.
  5416. stream_.mode = DUPLEX;
  5417. else
  5418. stream_.mode = mode;
  5419. stream_.nBuffers = nBuffers;
  5420. stream_.sampleRate = sampleRate;
  5421. // Setup the buffer conversion information structure.
  5422. if ( stream_.doConvertBuffer[mode] ) setConvertInfo( mode, firstChannel );
  5423. // Setup the callback thread.
  5424. if ( stream_.callbackInfo.isRunning == false ) {
  5425. unsigned threadId;
  5426. stream_.callbackInfo.isRunning = true;
  5427. stream_.callbackInfo.object = (void *) this;
  5428. stream_.callbackInfo.thread = _beginthreadex( NULL, 0, &callbackHandler,
  5429. &stream_.callbackInfo, 0, &threadId );
  5430. if ( stream_.callbackInfo.thread == 0 ) {
  5431. errorText_ = "RtApiDs::probeDeviceOpen: error creating callback thread!";
  5432. goto error;
  5433. }
  5434. // Boost DS thread priority
  5435. SetThreadPriority( (HANDLE) stream_.callbackInfo.thread, THREAD_PRIORITY_HIGHEST );
  5436. }
  5437. return SUCCESS;
  5438. error:
  5439. if ( handle ) {
  5440. if ( handle->buffer[0] ) { // the object pointer can be NULL and valid
  5441. LPDIRECTSOUND object = (LPDIRECTSOUND) handle->id[0];
  5442. LPDIRECTSOUNDBUFFER buffer = (LPDIRECTSOUNDBUFFER) handle->buffer[0];
  5443. if ( buffer ) buffer->Release();
  5444. object->Release();
  5445. }
  5446. if ( handle->buffer[1] ) {
  5447. LPDIRECTSOUNDCAPTURE object = (LPDIRECTSOUNDCAPTURE) handle->id[1];
  5448. LPDIRECTSOUNDCAPTUREBUFFER buffer = (LPDIRECTSOUNDCAPTUREBUFFER) handle->buffer[1];
  5449. if ( buffer ) buffer->Release();
  5450. object->Release();
  5451. }
  5452. CloseHandle( handle->condition );
  5453. delete handle;
  5454. stream_.apiHandle = 0;
  5455. }
  5456. for ( int i=0; i<2; i++ ) {
  5457. if ( stream_.userBuffer[i] ) {
  5458. free( stream_.userBuffer[i] );
  5459. stream_.userBuffer[i] = 0;
  5460. }
  5461. }
  5462. if ( stream_.deviceBuffer ) {
  5463. free( stream_.deviceBuffer );
  5464. stream_.deviceBuffer = 0;
  5465. }
  5466. stream_.state = STREAM_CLOSED;
  5467. return FAILURE;
  5468. }
  5469. void RtApiDs :: closeStream()
  5470. {
  5471. if ( stream_.state == STREAM_CLOSED ) {
  5472. errorText_ = "RtApiDs::closeStream(): no open stream to close!";
  5473. error( RtAudioError::WARNING );
  5474. return;
  5475. }
  5476. // Stop the callback thread.
  5477. stream_.callbackInfo.isRunning = false;
  5478. WaitForSingleObject( (HANDLE) stream_.callbackInfo.thread, INFINITE );
  5479. CloseHandle( (HANDLE) stream_.callbackInfo.thread );
  5480. DsHandle *handle = (DsHandle *) stream_.apiHandle;
  5481. if ( handle ) {
  5482. if ( handle->buffer[0] ) { // the object pointer can be NULL and valid
  5483. LPDIRECTSOUND object = (LPDIRECTSOUND) handle->id[0];
  5484. LPDIRECTSOUNDBUFFER buffer = (LPDIRECTSOUNDBUFFER) handle->buffer[0];
  5485. if ( buffer ) {
  5486. buffer->Stop();
  5487. buffer->Release();
  5488. }
  5489. object->Release();
  5490. }
  5491. if ( handle->buffer[1] ) {
  5492. LPDIRECTSOUNDCAPTURE object = (LPDIRECTSOUNDCAPTURE) handle->id[1];
  5493. LPDIRECTSOUNDCAPTUREBUFFER buffer = (LPDIRECTSOUNDCAPTUREBUFFER) handle->buffer[1];
  5494. if ( buffer ) {
  5495. buffer->Stop();
  5496. buffer->Release();
  5497. }
  5498. object->Release();
  5499. }
  5500. CloseHandle( handle->condition );
  5501. delete handle;
  5502. stream_.apiHandle = 0;
  5503. }
  5504. for ( int i=0; i<2; i++ ) {
  5505. if ( stream_.userBuffer[i] ) {
  5506. free( stream_.userBuffer[i] );
  5507. stream_.userBuffer[i] = 0;
  5508. }
  5509. }
  5510. if ( stream_.deviceBuffer ) {
  5511. free( stream_.deviceBuffer );
  5512. stream_.deviceBuffer = 0;
  5513. }
  5514. stream_.mode = UNINITIALIZED;
  5515. stream_.state = STREAM_CLOSED;
  5516. }
  5517. void RtApiDs :: startStream()
  5518. {
  5519. verifyStream();
  5520. if ( stream_.state == STREAM_RUNNING ) {
  5521. errorText_ = "RtApiDs::startStream(): the stream is already running!";
  5522. error( RtAudioError::WARNING );
  5523. return;
  5524. }
  5525. #if defined( HAVE_GETTIMEOFDAY )
  5526. gettimeofday( &stream_.lastTickTimestamp, NULL );
  5527. #endif
  5528. DsHandle *handle = (DsHandle *) stream_.apiHandle;
  5529. // Increase scheduler frequency on lesser windows (a side-effect of
  5530. // increasing timer accuracy). On greater windows (Win2K or later),
  5531. // this is already in effect.
  5532. timeBeginPeriod( 1 );
  5533. buffersRolling = false;
  5534. duplexPrerollBytes = 0;
  5535. if ( stream_.mode == DUPLEX ) {
  5536. // 0.5 seconds of silence in DUPLEX mode while the devices spin up and synchronize.
  5537. duplexPrerollBytes = (int) ( 0.5 * stream_.sampleRate * formatBytes( stream_.deviceFormat[1] ) * stream_.nDeviceChannels[1] );
  5538. }
  5539. HRESULT result = 0;
  5540. if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) {
  5541. LPDIRECTSOUNDBUFFER buffer = (LPDIRECTSOUNDBUFFER) handle->buffer[0];
  5542. result = buffer->Play( 0, 0, DSBPLAY_LOOPING );
  5543. if ( FAILED( result ) ) {
  5544. errorStream_ << "RtApiDs::startStream: error (" << getErrorString( result ) << ") starting output buffer!";
  5545. errorText_ = errorStream_.str();
  5546. goto unlock;
  5547. }
  5548. }
  5549. if ( stream_.mode == INPUT || stream_.mode == DUPLEX ) {
  5550. LPDIRECTSOUNDCAPTUREBUFFER buffer = (LPDIRECTSOUNDCAPTUREBUFFER) handle->buffer[1];
  5551. result = buffer->Start( DSCBSTART_LOOPING );
  5552. if ( FAILED( result ) ) {
  5553. errorStream_ << "RtApiDs::startStream: error (" << getErrorString( result ) << ") starting input buffer!";
  5554. errorText_ = errorStream_.str();
  5555. goto unlock;
  5556. }
  5557. }
  5558. handle->drainCounter = 0;
  5559. handle->internalDrain = false;
  5560. ResetEvent( handle->condition );
  5561. stream_.state = STREAM_RUNNING;
  5562. unlock:
  5563. if ( FAILED( result ) ) error( RtAudioError::SYSTEM_ERROR );
  5564. }
  5565. void RtApiDs :: stopStream()
  5566. {
  5567. verifyStream();
  5568. if ( stream_.state == STREAM_STOPPED ) {
  5569. errorText_ = "RtApiDs::stopStream(): the stream is already stopped!";
  5570. error( RtAudioError::WARNING );
  5571. return;
  5572. }
  5573. HRESULT result = 0;
  5574. LPVOID audioPtr;
  5575. DWORD dataLen;
  5576. DsHandle *handle = (DsHandle *) stream_.apiHandle;
  5577. if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) {
  5578. if ( handle->drainCounter == 0 ) {
  5579. handle->drainCounter = 2;
  5580. WaitForSingleObject( handle->condition, INFINITE ); // block until signaled
  5581. }
  5582. stream_.state = STREAM_STOPPED;
  5583. MUTEX_LOCK( &stream_.mutex );
  5584. // Stop the buffer and clear memory
  5585. LPDIRECTSOUNDBUFFER buffer = (LPDIRECTSOUNDBUFFER) handle->buffer[0];
  5586. result = buffer->Stop();
  5587. if ( FAILED( result ) ) {
  5588. errorStream_ << "RtApiDs::stopStream: error (" << getErrorString( result ) << ") stopping output buffer!";
  5589. errorText_ = errorStream_.str();
  5590. goto unlock;
  5591. }
  5592. // Lock the buffer and clear it so that if we start to play again,
  5593. // we won't have old data playing.
  5594. result = buffer->Lock( 0, handle->dsBufferSize[0], &audioPtr, &dataLen, NULL, NULL, 0 );
  5595. if ( FAILED( result ) ) {
  5596. errorStream_ << "RtApiDs::stopStream: error (" << getErrorString( result ) << ") locking output buffer!";
  5597. errorText_ = errorStream_.str();
  5598. goto unlock;
  5599. }
  5600. // Zero the DS buffer
  5601. ZeroMemory( audioPtr, dataLen );
  5602. // Unlock the DS buffer
  5603. result = buffer->Unlock( audioPtr, dataLen, NULL, 0 );
  5604. if ( FAILED( result ) ) {
  5605. errorStream_ << "RtApiDs::stopStream: error (" << getErrorString( result ) << ") unlocking output buffer!";
  5606. errorText_ = errorStream_.str();
  5607. goto unlock;
  5608. }
  5609. // If we start playing again, we must begin at beginning of buffer.
  5610. handle->bufferPointer[0] = 0;
  5611. }
  5612. if ( stream_.mode == INPUT || stream_.mode == DUPLEX ) {
  5613. LPDIRECTSOUNDCAPTUREBUFFER buffer = (LPDIRECTSOUNDCAPTUREBUFFER) handle->buffer[1];
  5614. audioPtr = NULL;
  5615. dataLen = 0;
  5616. stream_.state = STREAM_STOPPED;
  5617. if ( stream_.mode != DUPLEX )
  5618. MUTEX_LOCK( &stream_.mutex );
  5619. result = buffer->Stop();
  5620. if ( FAILED( result ) ) {
  5621. errorStream_ << "RtApiDs::stopStream: error (" << getErrorString( result ) << ") stopping input buffer!";
  5622. errorText_ = errorStream_.str();
  5623. goto unlock;
  5624. }
  5625. // Lock the buffer and clear it so that if we start to play again,
  5626. // we won't have old data playing.
  5627. result = buffer->Lock( 0, handle->dsBufferSize[1], &audioPtr, &dataLen, NULL, NULL, 0 );
  5628. if ( FAILED( result ) ) {
  5629. errorStream_ << "RtApiDs::stopStream: error (" << getErrorString( result ) << ") locking input buffer!";
  5630. errorText_ = errorStream_.str();
  5631. goto unlock;
  5632. }
  5633. // Zero the DS buffer
  5634. ZeroMemory( audioPtr, dataLen );
  5635. // Unlock the DS buffer
  5636. result = buffer->Unlock( audioPtr, dataLen, NULL, 0 );
  5637. if ( FAILED( result ) ) {
  5638. errorStream_ << "RtApiDs::stopStream: error (" << getErrorString( result ) << ") unlocking input buffer!";
  5639. errorText_ = errorStream_.str();
  5640. goto unlock;
  5641. }
  5642. // If we start recording again, we must begin at beginning of buffer.
  5643. handle->bufferPointer[1] = 0;
  5644. }
  5645. unlock:
  5646. timeEndPeriod( 1 ); // revert to normal scheduler frequency on lesser windows.
  5647. MUTEX_UNLOCK( &stream_.mutex );
  5648. if ( FAILED( result ) ) error( RtAudioError::SYSTEM_ERROR );
  5649. }
  5650. void RtApiDs :: abortStream()
  5651. {
  5652. verifyStream();
  5653. if ( stream_.state == STREAM_STOPPED ) {
  5654. errorText_ = "RtApiDs::abortStream(): the stream is already stopped!";
  5655. error( RtAudioError::WARNING );
  5656. return;
  5657. }
  5658. DsHandle *handle = (DsHandle *) stream_.apiHandle;
  5659. handle->drainCounter = 2;
  5660. stopStream();
  5661. }
  5662. void RtApiDs :: callbackEvent()
  5663. {
  5664. if ( stream_.state == STREAM_STOPPED || stream_.state == STREAM_STOPPING ) {
  5665. Sleep( 50 ); // sleep 50 milliseconds
  5666. return;
  5667. }
  5668. if ( stream_.state == STREAM_CLOSED ) {
  5669. errorText_ = "RtApiDs::callbackEvent(): the stream is closed ... this shouldn't happen!";
  5670. error( RtAudioError::WARNING );
  5671. return;
  5672. }
  5673. CallbackInfo *info = (CallbackInfo *) &stream_.callbackInfo;
  5674. DsHandle *handle = (DsHandle *) stream_.apiHandle;
  5675. // Check if we were draining the stream and signal is finished.
  5676. if ( handle->drainCounter > stream_.nBuffers + 2 ) {
  5677. stream_.state = STREAM_STOPPING;
  5678. if ( handle->internalDrain == false )
  5679. SetEvent( handle->condition );
  5680. else
  5681. stopStream();
  5682. return;
  5683. }
  5684. // Invoke user callback to get fresh output data UNLESS we are
  5685. // draining stream.
  5686. if ( handle->drainCounter == 0 ) {
  5687. RtAudioCallback callback = (RtAudioCallback) info->callback;
  5688. double streamTime = getStreamTime();
  5689. RtAudioStreamStatus status = 0;
  5690. if ( stream_.mode != INPUT && handle->xrun[0] == true ) {
  5691. status |= RTAUDIO_OUTPUT_UNDERFLOW;
  5692. handle->xrun[0] = false;
  5693. }
  5694. if ( stream_.mode != OUTPUT && handle->xrun[1] == true ) {
  5695. status |= RTAUDIO_INPUT_OVERFLOW;
  5696. handle->xrun[1] = false;
  5697. }
  5698. int cbReturnValue = callback( stream_.userBuffer[0], stream_.userBuffer[1],
  5699. stream_.bufferSize, streamTime, status, info->userData );
  5700. if ( cbReturnValue == 2 ) {
  5701. stream_.state = STREAM_STOPPING;
  5702. handle->drainCounter = 2;
  5703. abortStream();
  5704. return;
  5705. }
  5706. else if ( cbReturnValue == 1 ) {
  5707. handle->drainCounter = 1;
  5708. handle->internalDrain = true;
  5709. }
  5710. }
  5711. HRESULT result;
  5712. DWORD currentWritePointer, safeWritePointer;
  5713. DWORD currentReadPointer, safeReadPointer;
  5714. UINT nextWritePointer;
  5715. LPVOID buffer1 = NULL;
  5716. LPVOID buffer2 = NULL;
  5717. DWORD bufferSize1 = 0;
  5718. DWORD bufferSize2 = 0;
  5719. char *buffer;
  5720. long bufferBytes;
  5721. MUTEX_LOCK( &stream_.mutex );
  5722. if ( stream_.state == STREAM_STOPPED ) {
  5723. MUTEX_UNLOCK( &stream_.mutex );
  5724. return;
  5725. }
  5726. if ( buffersRolling == false ) {
  5727. if ( stream_.mode == DUPLEX ) {
  5728. //assert( handle->dsBufferSize[0] == handle->dsBufferSize[1] );
  5729. // It takes a while for the devices to get rolling. As a result,
  5730. // there's no guarantee that the capture and write device pointers
  5731. // will move in lockstep. Wait here for both devices to start
  5732. // rolling, and then set our buffer pointers accordingly.
  5733. // e.g. Crystal Drivers: the capture buffer starts up 5700 to 9600
  5734. // bytes later than the write buffer.
  5735. // Stub: a serious risk of having a pre-emptive scheduling round
  5736. // take place between the two GetCurrentPosition calls... but I'm
  5737. // really not sure how to solve the problem. Temporarily boost to
  5738. // Realtime priority, maybe; but I'm not sure what priority the
  5739. // DirectSound service threads run at. We *should* be roughly
  5740. // within a ms or so of correct.
  5741. LPDIRECTSOUNDBUFFER dsWriteBuffer = (LPDIRECTSOUNDBUFFER) handle->buffer[0];
  5742. LPDIRECTSOUNDCAPTUREBUFFER dsCaptureBuffer = (LPDIRECTSOUNDCAPTUREBUFFER) handle->buffer[1];
  5743. DWORD startSafeWritePointer, startSafeReadPointer;
  5744. result = dsWriteBuffer->GetCurrentPosition( NULL, &startSafeWritePointer );
  5745. if ( FAILED( result ) ) {
  5746. errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") getting current write position!";
  5747. errorText_ = errorStream_.str();
  5748. MUTEX_UNLOCK( &stream_.mutex );
  5749. error( RtAudioError::SYSTEM_ERROR );
  5750. return;
  5751. }
  5752. result = dsCaptureBuffer->GetCurrentPosition( NULL, &startSafeReadPointer );
  5753. if ( FAILED( result ) ) {
  5754. errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") getting current read position!";
  5755. errorText_ = errorStream_.str();
  5756. MUTEX_UNLOCK( &stream_.mutex );
  5757. error( RtAudioError::SYSTEM_ERROR );
  5758. return;
  5759. }
  5760. while ( true ) {
  5761. result = dsWriteBuffer->GetCurrentPosition( NULL, &safeWritePointer );
  5762. if ( FAILED( result ) ) {
  5763. errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") getting current write position!";
  5764. errorText_ = errorStream_.str();
  5765. MUTEX_UNLOCK( &stream_.mutex );
  5766. error( RtAudioError::SYSTEM_ERROR );
  5767. return;
  5768. }
  5769. result = dsCaptureBuffer->GetCurrentPosition( NULL, &safeReadPointer );
  5770. if ( FAILED( result ) ) {
  5771. errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") getting current read position!";
  5772. errorText_ = errorStream_.str();
  5773. MUTEX_UNLOCK( &stream_.mutex );
  5774. error( RtAudioError::SYSTEM_ERROR );
  5775. return;
  5776. }
  5777. if ( safeWritePointer != startSafeWritePointer && safeReadPointer != startSafeReadPointer ) break;
  5778. Sleep( 1 );
  5779. }
  5780. //assert( handle->dsBufferSize[0] == handle->dsBufferSize[1] );
  5781. handle->bufferPointer[0] = safeWritePointer + handle->dsPointerLeadTime[0];
  5782. if ( handle->bufferPointer[0] >= handle->dsBufferSize[0] ) handle->bufferPointer[0] -= handle->dsBufferSize[0];
  5783. handle->bufferPointer[1] = safeReadPointer;
  5784. }
  5785. else if ( stream_.mode == OUTPUT ) {
  5786. // Set the proper nextWritePosition after initial startup.
  5787. LPDIRECTSOUNDBUFFER dsWriteBuffer = (LPDIRECTSOUNDBUFFER) handle->buffer[0];
  5788. result = dsWriteBuffer->GetCurrentPosition( &currentWritePointer, &safeWritePointer );
  5789. if ( FAILED( result ) ) {
  5790. errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") getting current write position!";
  5791. errorText_ = errorStream_.str();
  5792. MUTEX_UNLOCK( &stream_.mutex );
  5793. error( RtAudioError::SYSTEM_ERROR );
  5794. return;
  5795. }
  5796. handle->bufferPointer[0] = safeWritePointer + handle->dsPointerLeadTime[0];
  5797. if ( handle->bufferPointer[0] >= handle->dsBufferSize[0] ) handle->bufferPointer[0] -= handle->dsBufferSize[0];
  5798. }
  5799. buffersRolling = true;
  5800. }
  5801. if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) {
  5802. LPDIRECTSOUNDBUFFER dsBuffer = (LPDIRECTSOUNDBUFFER) handle->buffer[0];
  5803. if ( handle->drainCounter > 1 ) { // write zeros to the output stream
  5804. bufferBytes = stream_.bufferSize * stream_.nUserChannels[0];
  5805. bufferBytes *= formatBytes( stream_.userFormat );
  5806. memset( stream_.userBuffer[0], 0, bufferBytes );
  5807. }
  5808. // Setup parameters and do buffer conversion if necessary.
  5809. if ( stream_.doConvertBuffer[0] ) {
  5810. buffer = stream_.deviceBuffer;
  5811. convertBuffer( buffer, stream_.userBuffer[0], stream_.convertInfo[0] );
  5812. bufferBytes = stream_.bufferSize * stream_.nDeviceChannels[0];
  5813. bufferBytes *= formatBytes( stream_.deviceFormat[0] );
  5814. }
  5815. else {
  5816. buffer = stream_.userBuffer[0];
  5817. bufferBytes = stream_.bufferSize * stream_.nUserChannels[0];
  5818. bufferBytes *= formatBytes( stream_.userFormat );
  5819. }
  5820. // No byte swapping necessary in DirectSound implementation.
  5821. // Ahhh ... windoze. 16-bit data is signed but 8-bit data is
  5822. // unsigned. So, we need to convert our signed 8-bit data here to
  5823. // unsigned.
  5824. if ( stream_.deviceFormat[0] == RTAUDIO_SINT8 )
  5825. for ( int i=0; i<bufferBytes; i++ ) buffer[i] = (unsigned char) ( buffer[i] + 128 );
  5826. DWORD dsBufferSize = handle->dsBufferSize[0];
  5827. nextWritePointer = handle->bufferPointer[0];
  5828. DWORD endWrite, leadPointer;
  5829. while ( true ) {
  5830. // Find out where the read and "safe write" pointers are.
  5831. result = dsBuffer->GetCurrentPosition( &currentWritePointer, &safeWritePointer );
  5832. if ( FAILED( result ) ) {
  5833. errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") getting current write position!";
  5834. errorText_ = errorStream_.str();
  5835. MUTEX_UNLOCK( &stream_.mutex );
  5836. error( RtAudioError::SYSTEM_ERROR );
  5837. return;
  5838. }
  5839. // We will copy our output buffer into the region between
  5840. // safeWritePointer and leadPointer. If leadPointer is not
  5841. // beyond the next endWrite position, wait until it is.
  5842. leadPointer = safeWritePointer + handle->dsPointerLeadTime[0];
  5843. //std::cout << "safeWritePointer = " << safeWritePointer << ", leadPointer = " << leadPointer << ", nextWritePointer = " << nextWritePointer << std::endl;
  5844. if ( leadPointer > dsBufferSize ) leadPointer -= dsBufferSize;
  5845. if ( leadPointer < nextWritePointer ) leadPointer += dsBufferSize; // unwrap offset
  5846. endWrite = nextWritePointer + bufferBytes;
  5847. // Check whether the entire write region is behind the play pointer.
  5848. if ( leadPointer >= endWrite ) break;
  5849. // If we are here, then we must wait until the leadPointer advances
  5850. // beyond the end of our next write region. We use the
  5851. // Sleep() function to suspend operation until that happens.
  5852. double millis = ( endWrite - leadPointer ) * 1000.0;
  5853. millis /= ( formatBytes( stream_.deviceFormat[0]) * stream_.nDeviceChannels[0] * stream_.sampleRate);
  5854. if ( millis < 1.0 ) millis = 1.0;
  5855. Sleep( (DWORD) millis );
  5856. }
  5857. if ( dsPointerBetween( nextWritePointer, safeWritePointer, currentWritePointer, dsBufferSize )
  5858. || dsPointerBetween( endWrite, safeWritePointer, currentWritePointer, dsBufferSize ) ) {
  5859. // We've strayed into the forbidden zone ... resync the read pointer.
  5860. handle->xrun[0] = true;
  5861. nextWritePointer = safeWritePointer + handle->dsPointerLeadTime[0] - bufferBytes;
  5862. if ( nextWritePointer >= dsBufferSize ) nextWritePointer -= dsBufferSize;
  5863. handle->bufferPointer[0] = nextWritePointer;
  5864. endWrite = nextWritePointer + bufferBytes;
  5865. }
  5866. // Lock free space in the buffer
  5867. result = dsBuffer->Lock( nextWritePointer, bufferBytes, &buffer1,
  5868. &bufferSize1, &buffer2, &bufferSize2, 0 );
  5869. if ( FAILED( result ) ) {
  5870. errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") locking buffer during playback!";
  5871. errorText_ = errorStream_.str();
  5872. MUTEX_UNLOCK( &stream_.mutex );
  5873. error( RtAudioError::SYSTEM_ERROR );
  5874. return;
  5875. }
  5876. // Copy our buffer into the DS buffer
  5877. CopyMemory( buffer1, buffer, bufferSize1 );
  5878. if ( buffer2 != NULL ) CopyMemory( buffer2, buffer+bufferSize1, bufferSize2 );
  5879. // Update our buffer offset and unlock sound buffer
  5880. dsBuffer->Unlock( buffer1, bufferSize1, buffer2, bufferSize2 );
  5881. if ( FAILED( result ) ) {
  5882. errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") unlocking buffer during playback!";
  5883. errorText_ = errorStream_.str();
  5884. MUTEX_UNLOCK( &stream_.mutex );
  5885. error( RtAudioError::SYSTEM_ERROR );
  5886. return;
  5887. }
  5888. nextWritePointer = ( nextWritePointer + bufferSize1 + bufferSize2 ) % dsBufferSize;
  5889. handle->bufferPointer[0] = nextWritePointer;
  5890. }
  5891. // Don't bother draining input
  5892. if ( handle->drainCounter ) {
  5893. handle->drainCounter++;
  5894. goto unlock;
  5895. }
  5896. if ( stream_.mode == INPUT || stream_.mode == DUPLEX ) {
  5897. // Setup parameters.
  5898. if ( stream_.doConvertBuffer[1] ) {
  5899. buffer = stream_.deviceBuffer;
  5900. bufferBytes = stream_.bufferSize * stream_.nDeviceChannels[1];
  5901. bufferBytes *= formatBytes( stream_.deviceFormat[1] );
  5902. }
  5903. else {
  5904. buffer = stream_.userBuffer[1];
  5905. bufferBytes = stream_.bufferSize * stream_.nUserChannels[1];
  5906. bufferBytes *= formatBytes( stream_.userFormat );
  5907. }
  5908. LPDIRECTSOUNDCAPTUREBUFFER dsBuffer = (LPDIRECTSOUNDCAPTUREBUFFER) handle->buffer[1];
  5909. long nextReadPointer = handle->bufferPointer[1];
  5910. DWORD dsBufferSize = handle->dsBufferSize[1];
  5911. // Find out where the write and "safe read" pointers are.
  5912. result = dsBuffer->GetCurrentPosition( &currentReadPointer, &safeReadPointer );
  5913. if ( FAILED( result ) ) {
  5914. errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") getting current read position!";
  5915. errorText_ = errorStream_.str();
  5916. MUTEX_UNLOCK( &stream_.mutex );
  5917. error( RtAudioError::SYSTEM_ERROR );
  5918. return;
  5919. }
  5920. if ( safeReadPointer < (DWORD)nextReadPointer ) safeReadPointer += dsBufferSize; // unwrap offset
  5921. DWORD endRead = nextReadPointer + bufferBytes;
  5922. // Handling depends on whether we are INPUT or DUPLEX.
  5923. // If we're in INPUT mode then waiting is a good thing. If we're in DUPLEX mode,
  5924. // then a wait here will drag the write pointers into the forbidden zone.
  5925. //
  5926. // In DUPLEX mode, rather than wait, we will back off the read pointer until
  5927. // it's in a safe position. This causes dropouts, but it seems to be the only
  5928. // practical way to sync up the read and write pointers reliably, given the
  5929. // the very complex relationship between phase and increment of the read and write
  5930. // pointers.
  5931. //
  5932. // In order to minimize audible dropouts in DUPLEX mode, we will
  5933. // provide a pre-roll period of 0.5 seconds in which we return
  5934. // zeros from the read buffer while the pointers sync up.
  5935. if ( stream_.mode == DUPLEX ) {
  5936. if ( safeReadPointer < endRead ) {
  5937. if ( duplexPrerollBytes <= 0 ) {
  5938. // Pre-roll time over. Be more aggressive.
  5939. int adjustment = endRead-safeReadPointer;
  5940. handle->xrun[1] = true;
  5941. // Two cases:
  5942. // - large adjustments: we've probably run out of CPU cycles, so just resync exactly,
  5943. // and perform fine adjustments later.
  5944. // - small adjustments: back off by twice as much.
  5945. if ( adjustment >= 2*bufferBytes )
  5946. nextReadPointer = safeReadPointer-2*bufferBytes;
  5947. else
  5948. nextReadPointer = safeReadPointer-bufferBytes-adjustment;
  5949. if ( nextReadPointer < 0 ) nextReadPointer += dsBufferSize;
  5950. }
  5951. else {
  5952. // In pre=roll time. Just do it.
  5953. nextReadPointer = safeReadPointer - bufferBytes;
  5954. while ( nextReadPointer < 0 ) nextReadPointer += dsBufferSize;
  5955. }
  5956. endRead = nextReadPointer + bufferBytes;
  5957. }
  5958. }
  5959. else { // mode == INPUT
  5960. while ( safeReadPointer < endRead && stream_.callbackInfo.isRunning ) {
  5961. // See comments for playback.
  5962. double millis = (endRead - safeReadPointer) * 1000.0;
  5963. millis /= ( formatBytes(stream_.deviceFormat[1]) * stream_.nDeviceChannels[1] * stream_.sampleRate);
  5964. if ( millis < 1.0 ) millis = 1.0;
  5965. Sleep( (DWORD) millis );
  5966. // Wake up and find out where we are now.
  5967. result = dsBuffer->GetCurrentPosition( &currentReadPointer, &safeReadPointer );
  5968. if ( FAILED( result ) ) {
  5969. errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") getting current read position!";
  5970. errorText_ = errorStream_.str();
  5971. MUTEX_UNLOCK( &stream_.mutex );
  5972. error( RtAudioError::SYSTEM_ERROR );
  5973. return;
  5974. }
  5975. if ( safeReadPointer < (DWORD)nextReadPointer ) safeReadPointer += dsBufferSize; // unwrap offset
  5976. }
  5977. }
  5978. // Lock free space in the buffer
  5979. result = dsBuffer->Lock( nextReadPointer, bufferBytes, &buffer1,
  5980. &bufferSize1, &buffer2, &bufferSize2, 0 );
  5981. if ( FAILED( result ) ) {
  5982. errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") locking capture buffer!";
  5983. errorText_ = errorStream_.str();
  5984. MUTEX_UNLOCK( &stream_.mutex );
  5985. error( RtAudioError::SYSTEM_ERROR );
  5986. return;
  5987. }
  5988. if ( duplexPrerollBytes <= 0 ) {
  5989. // Copy our buffer into the DS buffer
  5990. CopyMemory( buffer, buffer1, bufferSize1 );
  5991. if ( buffer2 != NULL ) CopyMemory( buffer+bufferSize1, buffer2, bufferSize2 );
  5992. }
  5993. else {
  5994. memset( buffer, 0, bufferSize1 );
  5995. if ( buffer2 != NULL ) memset( buffer + bufferSize1, 0, bufferSize2 );
  5996. duplexPrerollBytes -= bufferSize1 + bufferSize2;
  5997. }
  5998. // Update our buffer offset and unlock sound buffer
  5999. nextReadPointer = ( nextReadPointer + bufferSize1 + bufferSize2 ) % dsBufferSize;
  6000. dsBuffer->Unlock( buffer1, bufferSize1, buffer2, bufferSize2 );
  6001. if ( FAILED( result ) ) {
  6002. errorStream_ << "RtApiDs::callbackEvent: error (" << getErrorString( result ) << ") unlocking capture buffer!";
  6003. errorText_ = errorStream_.str();
  6004. MUTEX_UNLOCK( &stream_.mutex );
  6005. error( RtAudioError::SYSTEM_ERROR );
  6006. return;
  6007. }
  6008. handle->bufferPointer[1] = nextReadPointer;
  6009. // No byte swapping necessary in DirectSound implementation.
  6010. // If necessary, convert 8-bit data from unsigned to signed.
  6011. if ( stream_.deviceFormat[1] == RTAUDIO_SINT8 )
  6012. for ( int j=0; j<bufferBytes; j++ ) buffer[j] = (signed char) ( buffer[j] - 128 );
  6013. // Do buffer conversion if necessary.
  6014. if ( stream_.doConvertBuffer[1] )
  6015. convertBuffer( stream_.userBuffer[1], stream_.deviceBuffer, stream_.convertInfo[1] );
  6016. }
  6017. unlock:
  6018. MUTEX_UNLOCK( &stream_.mutex );
  6019. RtApi::tickStreamTime();
  6020. }
  6021. // Definitions for utility functions and callbacks
  6022. // specific to the DirectSound implementation.
  6023. static unsigned __stdcall callbackHandler( void *ptr )
  6024. {
  6025. CallbackInfo *info = (CallbackInfo *) ptr;
  6026. RtApiDs *object = (RtApiDs *) info->object;
  6027. bool* isRunning = &info->isRunning;
  6028. while ( *isRunning == true ) {
  6029. object->callbackEvent();
  6030. }
  6031. _endthreadex( 0 );
  6032. return 0;
  6033. }
  6034. static BOOL CALLBACK deviceQueryCallback( LPGUID lpguid,
  6035. LPCTSTR description,
  6036. LPCTSTR /*module*/,
  6037. LPVOID lpContext )
  6038. {
  6039. struct DsProbeData& probeInfo = *(struct DsProbeData*) lpContext;
  6040. std::vector<struct DsDevice>& dsDevices = *probeInfo.dsDevices;
  6041. HRESULT hr;
  6042. bool validDevice = false;
  6043. if ( probeInfo.isInput == true ) {
  6044. DSCCAPS caps;
  6045. LPDIRECTSOUNDCAPTURE object;
  6046. hr = DirectSoundCaptureCreate( lpguid, &object, NULL );
  6047. if ( hr != DS_OK ) return TRUE;
  6048. caps.dwSize = sizeof(caps);
  6049. hr = object->GetCaps( &caps );
  6050. if ( hr == DS_OK ) {
  6051. if ( caps.dwChannels > 0 && caps.dwFormats > 0 )
  6052. validDevice = true;
  6053. }
  6054. object->Release();
  6055. }
  6056. else {
  6057. DSCAPS caps;
  6058. LPDIRECTSOUND object;
  6059. hr = DirectSoundCreate( lpguid, &object, NULL );
  6060. if ( hr != DS_OK ) return TRUE;
  6061. caps.dwSize = sizeof(caps);
  6062. hr = object->GetCaps( &caps );
  6063. if ( hr == DS_OK ) {
  6064. if ( caps.dwFlags & DSCAPS_PRIMARYMONO || caps.dwFlags & DSCAPS_PRIMARYSTEREO )
  6065. validDevice = true;
  6066. }
  6067. object->Release();
  6068. }
  6069. // If good device, then save its name and guid.
  6070. std::string name = convertCharPointerToStdString( description );
  6071. if ( validDevice ) {
  6072. for ( unsigned int i=0; i<dsDevices.size(); i++ ) {
  6073. if ( dsDevices[i].name == name ) {
  6074. if ( probeInfo.isInput && dsDevices[i].id[1] == lpguid)
  6075. {
  6076. dsDevices[i].found = true;
  6077. dsDevices[i].validId[1] = true;
  6078. }
  6079. else if (dsDevices[i].id[0] == lpguid)
  6080. {
  6081. dsDevices[i].found = true;
  6082. dsDevices[i].validId[0] = true;
  6083. }
  6084. return TRUE;
  6085. }
  6086. }
  6087. DsDevice device;
  6088. device.name = name;
  6089. device.found = true;
  6090. if ( probeInfo.isInput ) {
  6091. device.id[1] = lpguid;
  6092. device.validId[1] = true;
  6093. }
  6094. else {
  6095. device.id[0] = lpguid;
  6096. device.validId[0] = true;
  6097. }
  6098. dsDevices.push_back( device );
  6099. }
  6100. return TRUE;
  6101. }
  6102. static const char* getErrorString( int code )
  6103. {
  6104. switch ( code ) {
  6105. case DSERR_ALLOCATED:
  6106. return "Already allocated";
  6107. case DSERR_CONTROLUNAVAIL:
  6108. return "Control unavailable";
  6109. case DSERR_INVALIDPARAM:
  6110. return "Invalid parameter";
  6111. case DSERR_INVALIDCALL:
  6112. return "Invalid call";
  6113. case DSERR_GENERIC:
  6114. return "Generic error";
  6115. case DSERR_PRIOLEVELNEEDED:
  6116. return "Priority level needed";
  6117. case DSERR_OUTOFMEMORY:
  6118. return "Out of memory";
  6119. case DSERR_BADFORMAT:
  6120. return "The sample rate or the channel format is not supported";
  6121. case DSERR_UNSUPPORTED:
  6122. return "Not supported";
  6123. case DSERR_NODRIVER:
  6124. return "No driver";
  6125. case DSERR_ALREADYINITIALIZED:
  6126. return "Already initialized";
  6127. case DSERR_NOAGGREGATION:
  6128. return "No aggregation";
  6129. case DSERR_BUFFERLOST:
  6130. return "Buffer lost";
  6131. case DSERR_OTHERAPPHASPRIO:
  6132. return "Another application already has priority";
  6133. case DSERR_UNINITIALIZED:
  6134. return "Uninitialized";
  6135. default:
  6136. return "DirectSound unknown error";
  6137. }
  6138. }
  6139. //******************** End of __WINDOWS_DS__ *********************//
  6140. #endif
  6141. #if defined(__LINUX_ALSA__)
  6142. #include <alsa/asoundlib.h>
  6143. #include <unistd.h>
  6144. // A structure to hold various information related to the ALSA API
  6145. // implementation.
  6146. struct AlsaHandle {
  6147. snd_pcm_t *handles[2];
  6148. bool synchronized;
  6149. bool xrun[2];
  6150. pthread_cond_t runnable_cv;
  6151. bool runnable;
  6152. AlsaHandle()
  6153. #if _cplusplus >= 201103L
  6154. :handles{nullptr, nullptr}, synchronized(false), runnable(false) { xrun[0] = false; xrun[1] = false; }
  6155. #else
  6156. : synchronized(false), runnable(false) { handles[0] = NULL; handles[1] = NULL; xrun[0] = false; xrun[1] = false; }
  6157. #endif
  6158. };
  6159. static void *alsaCallbackHandler( void * ptr );
  6160. RtApiAlsa :: RtApiAlsa()
  6161. {
  6162. // Nothing to do here.
  6163. }
  6164. RtApiAlsa :: ~RtApiAlsa()
  6165. {
  6166. if ( stream_.state != STREAM_CLOSED ) closeStream();
  6167. }
  6168. unsigned int RtApiAlsa :: getDeviceCount( void )
  6169. {
  6170. unsigned nDevices = 0;
  6171. int result, subdevice, card;
  6172. char name[64];
  6173. snd_ctl_t *handle = 0;
  6174. strcpy(name, "default");
  6175. result = snd_ctl_open( &handle, "default", 0 );
  6176. if (result == 0) {
  6177. nDevices++;
  6178. snd_ctl_close( handle );
  6179. }
  6180. // Count cards and devices
  6181. card = -1;
  6182. snd_card_next( &card );
  6183. while ( card >= 0 ) {
  6184. sprintf( name, "hw:%d", card );
  6185. result = snd_ctl_open( &handle, name, 0 );
  6186. if ( result < 0 ) {
  6187. handle = 0;
  6188. errorStream_ << "RtApiAlsa::getDeviceCount: control open, card = " << card << ", " << snd_strerror( result ) << ".";
  6189. errorText_ = errorStream_.str();
  6190. error( RtAudioError::WARNING );
  6191. goto nextcard;
  6192. }
  6193. subdevice = -1;
  6194. while( 1 ) {
  6195. result = snd_ctl_pcm_next_device( handle, &subdevice );
  6196. if ( result < 0 ) {
  6197. errorStream_ << "RtApiAlsa::getDeviceCount: control next device, card = " << card << ", " << snd_strerror( result ) << ".";
  6198. errorText_ = errorStream_.str();
  6199. error( RtAudioError::WARNING );
  6200. break;
  6201. }
  6202. if ( subdevice < 0 )
  6203. break;
  6204. nDevices++;
  6205. }
  6206. nextcard:
  6207. if ( handle )
  6208. snd_ctl_close( handle );
  6209. snd_card_next( &card );
  6210. }
  6211. return nDevices;
  6212. }
  6213. RtAudio::DeviceInfo RtApiAlsa :: getDeviceInfo( unsigned int device )
  6214. {
  6215. RtAudio::DeviceInfo info;
  6216. info.probed = false;
  6217. unsigned nDevices = 0;
  6218. int result=-1, subdevice=-1, card=-1;
  6219. char name[64];
  6220. snd_ctl_t *chandle = 0;
  6221. result = snd_ctl_open( &chandle, "default", SND_CTL_NONBLOCK );
  6222. if ( result == 0 ) {
  6223. if ( nDevices++ == device ) {
  6224. strcpy( name, "default" );
  6225. goto foundDevice;
  6226. }
  6227. }
  6228. if ( chandle )
  6229. snd_ctl_close( chandle );
  6230. // Count cards and devices
  6231. snd_card_next( &card );
  6232. while ( card >= 0 ) {
  6233. sprintf( name, "hw:%d", card );
  6234. result = snd_ctl_open( &chandle, name, SND_CTL_NONBLOCK );
  6235. if ( result < 0 ) {
  6236. chandle = 0;
  6237. errorStream_ << "RtApiAlsa::getDeviceInfo: control open, card = " << card << ", " << snd_strerror( result ) << ".";
  6238. errorText_ = errorStream_.str();
  6239. error( RtAudioError::WARNING );
  6240. goto nextcard;
  6241. }
  6242. subdevice = -1;
  6243. while( 1 ) {
  6244. result = snd_ctl_pcm_next_device( chandle, &subdevice );
  6245. if ( result < 0 ) {
  6246. errorStream_ << "RtApiAlsa::getDeviceInfo: control next device, card = " << card << ", " << snd_strerror( result ) << ".";
  6247. errorText_ = errorStream_.str();
  6248. error( RtAudioError::WARNING );
  6249. break;
  6250. }
  6251. if ( subdevice < 0 ) break;
  6252. if ( nDevices == device ) {
  6253. sprintf( name, "hw:%d,%d", card, subdevice );
  6254. goto foundDevice;
  6255. }
  6256. nDevices++;
  6257. }
  6258. nextcard:
  6259. if ( chandle )
  6260. snd_ctl_close( chandle );
  6261. snd_card_next( &card );
  6262. }
  6263. if ( nDevices == 0 ) {
  6264. errorText_ = "RtApiAlsa::getDeviceInfo: no devices found!";
  6265. error( RtAudioError::INVALID_USE );
  6266. return info;
  6267. }
  6268. if ( device >= nDevices ) {
  6269. errorText_ = "RtApiAlsa::getDeviceInfo: device ID is invalid!";
  6270. error( RtAudioError::INVALID_USE );
  6271. return info;
  6272. }
  6273. foundDevice:
  6274. // If a stream is already open, we cannot probe the stream devices.
  6275. // Thus, use the saved results.
  6276. if ( stream_.state != STREAM_CLOSED &&
  6277. ( stream_.device[0] == device || stream_.device[1] == device ) ) {
  6278. snd_ctl_close( chandle );
  6279. if ( device >= devices_.size() ) {
  6280. errorText_ = "RtApiAlsa::getDeviceInfo: device ID was not present before stream was opened.";
  6281. error( RtAudioError::WARNING );
  6282. return info;
  6283. }
  6284. return devices_[ device ];
  6285. }
  6286. int openMode = SND_PCM_ASYNC;
  6287. snd_pcm_stream_t stream;
  6288. snd_pcm_info_t *pcminfo;
  6289. snd_pcm_info_alloca( &pcminfo );
  6290. snd_pcm_t *phandle;
  6291. snd_pcm_hw_params_t *params;
  6292. snd_pcm_hw_params_alloca( &params );
  6293. // First try for playback unless default device (which has subdev -1)
  6294. stream = SND_PCM_STREAM_PLAYBACK;
  6295. snd_pcm_info_set_stream( pcminfo, stream );
  6296. if ( subdevice != -1 ) {
  6297. snd_pcm_info_set_device( pcminfo, subdevice );
  6298. snd_pcm_info_set_subdevice( pcminfo, 0 );
  6299. result = snd_ctl_pcm_info( chandle, pcminfo );
  6300. if ( result < 0 ) {
  6301. // Device probably doesn't support playback.
  6302. goto captureProbe;
  6303. }
  6304. }
  6305. result = snd_pcm_open( &phandle, name, stream, openMode | SND_PCM_NONBLOCK );
  6306. if ( result < 0 ) {
  6307. errorStream_ << "RtApiAlsa::getDeviceInfo: snd_pcm_open error for device (" << name << "), " << snd_strerror( result ) << ".";
  6308. errorText_ = errorStream_.str();
  6309. error( RtAudioError::WARNING );
  6310. goto captureProbe;
  6311. }
  6312. // The device is open ... fill the parameter structure.
  6313. result = snd_pcm_hw_params_any( phandle, params );
  6314. if ( result < 0 ) {
  6315. snd_pcm_close( phandle );
  6316. errorStream_ << "RtApiAlsa::getDeviceInfo: snd_pcm_hw_params error for device (" << name << "), " << snd_strerror( result ) << ".";
  6317. errorText_ = errorStream_.str();
  6318. error( RtAudioError::WARNING );
  6319. goto captureProbe;
  6320. }
  6321. // Get output channel information.
  6322. unsigned int value;
  6323. result = snd_pcm_hw_params_get_channels_max( params, &value );
  6324. if ( result < 0 ) {
  6325. snd_pcm_close( phandle );
  6326. errorStream_ << "RtApiAlsa::getDeviceInfo: error getting device (" << name << ") output channels, " << snd_strerror( result ) << ".";
  6327. errorText_ = errorStream_.str();
  6328. error( RtAudioError::WARNING );
  6329. goto captureProbe;
  6330. }
  6331. info.outputChannels = value;
  6332. snd_pcm_close( phandle );
  6333. captureProbe:
  6334. stream = SND_PCM_STREAM_CAPTURE;
  6335. snd_pcm_info_set_stream( pcminfo, stream );
  6336. // Now try for capture unless default device (with subdev = -1)
  6337. if ( subdevice != -1 ) {
  6338. result = snd_ctl_pcm_info( chandle, pcminfo );
  6339. snd_ctl_close( chandle );
  6340. if ( result < 0 ) {
  6341. // Device probably doesn't support capture.
  6342. if ( info.outputChannels == 0 ) return info;
  6343. goto probeParameters;
  6344. }
  6345. }
  6346. else
  6347. snd_ctl_close( chandle );
  6348. result = snd_pcm_open( &phandle, name, stream, openMode | SND_PCM_NONBLOCK);
  6349. if ( result < 0 ) {
  6350. errorStream_ << "RtApiAlsa::getDeviceInfo: snd_pcm_open error for device (" << name << "), " << snd_strerror( result ) << ".";
  6351. errorText_ = errorStream_.str();
  6352. error( RtAudioError::WARNING );
  6353. if ( info.outputChannels == 0 ) return info;
  6354. goto probeParameters;
  6355. }
  6356. // The device is open ... fill the parameter structure.
  6357. result = snd_pcm_hw_params_any( phandle, params );
  6358. if ( result < 0 ) {
  6359. snd_pcm_close( phandle );
  6360. errorStream_ << "RtApiAlsa::getDeviceInfo: snd_pcm_hw_params error for device (" << name << "), " << snd_strerror( result ) << ".";
  6361. errorText_ = errorStream_.str();
  6362. error( RtAudioError::WARNING );
  6363. if ( info.outputChannels == 0 ) return info;
  6364. goto probeParameters;
  6365. }
  6366. result = snd_pcm_hw_params_get_channels_max( params, &value );
  6367. if ( result < 0 ) {
  6368. snd_pcm_close( phandle );
  6369. errorStream_ << "RtApiAlsa::getDeviceInfo: error getting device (" << name << ") input channels, " << snd_strerror( result ) << ".";
  6370. errorText_ = errorStream_.str();
  6371. error( RtAudioError::WARNING );
  6372. if ( info.outputChannels == 0 ) return info;
  6373. goto probeParameters;
  6374. }
  6375. info.inputChannels = value;
  6376. snd_pcm_close( phandle );
  6377. // If device opens for both playback and capture, we determine the channels.
  6378. if ( info.outputChannels > 0 && info.inputChannels > 0 )
  6379. info.duplexChannels = (info.outputChannels > info.inputChannels) ? info.inputChannels : info.outputChannels;
  6380. // ALSA doesn't provide default devices so we'll use the first available one.
  6381. if ( device == 0 && info.outputChannels > 0 )
  6382. info.isDefaultOutput = true;
  6383. if ( device == 0 && info.inputChannels > 0 )
  6384. info.isDefaultInput = true;
  6385. probeParameters:
  6386. // At this point, we just need to figure out the supported data
  6387. // formats and sample rates. We'll proceed by opening the device in
  6388. // the direction with the maximum number of channels, or playback if
  6389. // they are equal. This might limit our sample rate options, but so
  6390. // be it.
  6391. if ( info.outputChannels >= info.inputChannels )
  6392. stream = SND_PCM_STREAM_PLAYBACK;
  6393. else
  6394. stream = SND_PCM_STREAM_CAPTURE;
  6395. snd_pcm_info_set_stream( pcminfo, stream );
  6396. result = snd_pcm_open( &phandle, name, stream, openMode | SND_PCM_NONBLOCK);
  6397. if ( result < 0 ) {
  6398. errorStream_ << "RtApiAlsa::getDeviceInfo: snd_pcm_open error for device (" << name << "), " << snd_strerror( result ) << ".";
  6399. errorText_ = errorStream_.str();
  6400. error( RtAudioError::WARNING );
  6401. return info;
  6402. }
  6403. // The device is open ... fill the parameter structure.
  6404. result = snd_pcm_hw_params_any( phandle, params );
  6405. if ( result < 0 ) {
  6406. snd_pcm_close( phandle );
  6407. errorStream_ << "RtApiAlsa::getDeviceInfo: snd_pcm_hw_params error for device (" << name << "), " << snd_strerror( result ) << ".";
  6408. errorText_ = errorStream_.str();
  6409. error( RtAudioError::WARNING );
  6410. return info;
  6411. }
  6412. // Test our discrete set of sample rate values.
  6413. info.sampleRates.clear();
  6414. for ( unsigned int i=0; i<MAX_SAMPLE_RATES; i++ ) {
  6415. if ( snd_pcm_hw_params_test_rate( phandle, params, SAMPLE_RATES[i], 0 ) == 0 ) {
  6416. info.sampleRates.push_back( SAMPLE_RATES[i] );
  6417. if ( !info.preferredSampleRate || ( SAMPLE_RATES[i] <= 48000 && SAMPLE_RATES[i] > info.preferredSampleRate ) )
  6418. info.preferredSampleRate = SAMPLE_RATES[i];
  6419. }
  6420. }
  6421. if ( info.sampleRates.size() == 0 ) {
  6422. snd_pcm_close( phandle );
  6423. errorStream_ << "RtApiAlsa::getDeviceInfo: no supported sample rates found for device (" << name << ").";
  6424. errorText_ = errorStream_.str();
  6425. error( RtAudioError::WARNING );
  6426. return info;
  6427. }
  6428. // Probe the supported data formats ... we don't care about endian-ness just yet
  6429. snd_pcm_format_t format;
  6430. info.nativeFormats = 0;
  6431. format = SND_PCM_FORMAT_S8;
  6432. if ( snd_pcm_hw_params_test_format( phandle, params, format ) == 0 )
  6433. info.nativeFormats |= RTAUDIO_SINT8;
  6434. format = SND_PCM_FORMAT_S16;
  6435. if ( snd_pcm_hw_params_test_format( phandle, params, format ) == 0 )
  6436. info.nativeFormats |= RTAUDIO_SINT16;
  6437. format = SND_PCM_FORMAT_S24;
  6438. if ( snd_pcm_hw_params_test_format( phandle, params, format ) == 0 )
  6439. info.nativeFormats |= RTAUDIO_SINT24;
  6440. format = SND_PCM_FORMAT_S32;
  6441. if ( snd_pcm_hw_params_test_format( phandle, params, format ) == 0 )
  6442. info.nativeFormats |= RTAUDIO_SINT32;
  6443. format = SND_PCM_FORMAT_FLOAT;
  6444. if ( snd_pcm_hw_params_test_format( phandle, params, format ) == 0 )
  6445. info.nativeFormats |= RTAUDIO_FLOAT32;
  6446. format = SND_PCM_FORMAT_FLOAT64;
  6447. if ( snd_pcm_hw_params_test_format( phandle, params, format ) == 0 )
  6448. info.nativeFormats |= RTAUDIO_FLOAT64;
  6449. // Check that we have at least one supported format
  6450. if ( info.nativeFormats == 0 ) {
  6451. snd_pcm_close( phandle );
  6452. errorStream_ << "RtApiAlsa::getDeviceInfo: pcm device (" << name << ") data format not supported by RtAudio.";
  6453. errorText_ = errorStream_.str();
  6454. error( RtAudioError::WARNING );
  6455. return info;
  6456. }
  6457. // Get the device name
  6458. if (strncmp(name, "default", 7)!=0) {
  6459. char *cardname;
  6460. result = snd_card_get_name( card, &cardname );
  6461. if ( result >= 0 ) {
  6462. sprintf( name, "hw:%s,%d", cardname, subdevice );
  6463. free( cardname );
  6464. }
  6465. }
  6466. info.name = name;
  6467. // That's all ... close the device and return
  6468. snd_pcm_close( phandle );
  6469. info.probed = true;
  6470. return info;
  6471. }
  6472. void RtApiAlsa :: saveDeviceInfo( void )
  6473. {
  6474. devices_.clear();
  6475. unsigned int nDevices = getDeviceCount();
  6476. devices_.resize( nDevices );
  6477. for ( unsigned int i=0; i<nDevices; i++ )
  6478. devices_[i] = getDeviceInfo( i );
  6479. }
  6480. bool RtApiAlsa :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels,
  6481. unsigned int firstChannel, unsigned int sampleRate,
  6482. RtAudioFormat format, unsigned int *bufferSize,
  6483. RtAudio::StreamOptions *options )
  6484. {
  6485. #if defined(__RTAUDIO_DEBUG__)
  6486. struct SndOutputTdealloc {
  6487. SndOutputTdealloc() : _out(NULL) { snd_output_stdio_attach(&_out, stderr, 0); }
  6488. ~SndOutputTdealloc() { snd_output_close(_out); }
  6489. operator snd_output_t*() { return _out; }
  6490. snd_output_t *_out;
  6491. } out;
  6492. #endif
  6493. // I'm not using the "plug" interface ... too much inconsistent behavior.
  6494. unsigned nDevices = 0;
  6495. int result, subdevice, card;
  6496. char name[64];
  6497. snd_ctl_t *chandle;
  6498. if ( device == 0
  6499. || (options && options->flags & RTAUDIO_ALSA_USE_DEFAULT) )
  6500. {
  6501. strcpy(name, "default");
  6502. result = snd_ctl_open( &chandle, "default", SND_CTL_NONBLOCK );
  6503. if ( result == 0 ) {
  6504. if ( nDevices == device ) {
  6505. strcpy( name, "default" );
  6506. snd_ctl_close( chandle );
  6507. goto foundDevice;
  6508. }
  6509. nDevices++;
  6510. }
  6511. }
  6512. else {
  6513. nDevices++;
  6514. // Count cards and devices
  6515. card = -1;
  6516. snd_card_next( &card );
  6517. while ( card >= 0 ) {
  6518. sprintf( name, "hw:%d", card );
  6519. result = snd_ctl_open( &chandle, name, SND_CTL_NONBLOCK );
  6520. if ( result < 0 ) {
  6521. errorStream_ << "RtApiAlsa::probeDeviceOpen: control open, card = " << card << ", " << snd_strerror( result ) << ".";
  6522. errorText_ = errorStream_.str();
  6523. return FAILURE;
  6524. }
  6525. subdevice = -1;
  6526. while( 1 ) {
  6527. result = snd_ctl_pcm_next_device( chandle, &subdevice );
  6528. if ( result < 0 ) break;
  6529. if ( subdevice < 0 ) break;
  6530. if ( nDevices == device ) {
  6531. sprintf( name, "hw:%d,%d", card, subdevice );
  6532. snd_ctl_close( chandle );
  6533. goto foundDevice;
  6534. }
  6535. nDevices++;
  6536. }
  6537. snd_ctl_close( chandle );
  6538. snd_card_next( &card );
  6539. }
  6540. if ( nDevices == 0 ) {
  6541. // This should not happen because a check is made before this function is called.
  6542. errorText_ = "RtApiAlsa::probeDeviceOpen: no devices found!";
  6543. return FAILURE;
  6544. }
  6545. if ( device >= nDevices ) {
  6546. // This should not happen because a check is made before this function is called.
  6547. errorText_ = "RtApiAlsa::probeDeviceOpen: device ID is invalid!";
  6548. return FAILURE;
  6549. }
  6550. }
  6551. foundDevice:
  6552. // The getDeviceInfo() function will not work for a device that is
  6553. // already open. Thus, we'll probe the system before opening a
  6554. // stream and save the results for use by getDeviceInfo().
  6555. if ( mode == OUTPUT || ( mode == INPUT && stream_.mode != OUTPUT ) ) // only do once
  6556. this->saveDeviceInfo();
  6557. snd_pcm_stream_t stream;
  6558. if ( mode == OUTPUT )
  6559. stream = SND_PCM_STREAM_PLAYBACK;
  6560. else
  6561. stream = SND_PCM_STREAM_CAPTURE;
  6562. snd_pcm_t *phandle;
  6563. int openMode = SND_PCM_ASYNC;
  6564. result = snd_pcm_open( &phandle, name, stream, openMode );
  6565. if ( result < 0 ) {
  6566. if ( mode == OUTPUT )
  6567. errorStream_ << "RtApiAlsa::probeDeviceOpen: pcm device (" << name << ") won't open for output.";
  6568. else
  6569. errorStream_ << "RtApiAlsa::probeDeviceOpen: pcm device (" << name << ") won't open for input.";
  6570. errorText_ = errorStream_.str();
  6571. return FAILURE;
  6572. }
  6573. // Fill the parameter structure.
  6574. snd_pcm_hw_params_t *hw_params;
  6575. snd_pcm_hw_params_alloca( &hw_params );
  6576. result = snd_pcm_hw_params_any( phandle, hw_params );
  6577. if ( result < 0 ) {
  6578. snd_pcm_close( phandle );
  6579. errorStream_ << "RtApiAlsa::probeDeviceOpen: error getting pcm device (" << name << ") parameters, " << snd_strerror( result ) << ".";
  6580. errorText_ = errorStream_.str();
  6581. return FAILURE;
  6582. }
  6583. #if defined(__RTAUDIO_DEBUG__)
  6584. fprintf( stderr, "\nRtApiAlsa: dump hardware params just after device open:\n\n" );
  6585. snd_pcm_hw_params_dump( hw_params, out );
  6586. #endif
  6587. // Set access ... check user preference.
  6588. if ( options && options->flags & RTAUDIO_NONINTERLEAVED ) {
  6589. stream_.userInterleaved = false;
  6590. result = snd_pcm_hw_params_set_access( phandle, hw_params, SND_PCM_ACCESS_RW_NONINTERLEAVED );
  6591. if ( result < 0 ) {
  6592. result = snd_pcm_hw_params_set_access( phandle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED );
  6593. stream_.deviceInterleaved[mode] = true;
  6594. }
  6595. else
  6596. stream_.deviceInterleaved[mode] = false;
  6597. }
  6598. else {
  6599. stream_.userInterleaved = true;
  6600. result = snd_pcm_hw_params_set_access( phandle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED );
  6601. if ( result < 0 ) {
  6602. result = snd_pcm_hw_params_set_access( phandle, hw_params, SND_PCM_ACCESS_RW_NONINTERLEAVED );
  6603. stream_.deviceInterleaved[mode] = false;
  6604. }
  6605. else
  6606. stream_.deviceInterleaved[mode] = true;
  6607. }
  6608. if ( result < 0 ) {
  6609. snd_pcm_close( phandle );
  6610. errorStream_ << "RtApiAlsa::probeDeviceOpen: error setting pcm device (" << name << ") access, " << snd_strerror( result ) << ".";
  6611. errorText_ = errorStream_.str();
  6612. return FAILURE;
  6613. }
  6614. // Determine how to set the device format.
  6615. stream_.userFormat = format;
  6616. snd_pcm_format_t deviceFormat = SND_PCM_FORMAT_UNKNOWN;
  6617. if ( format == RTAUDIO_SINT8 )
  6618. deviceFormat = SND_PCM_FORMAT_S8;
  6619. else if ( format == RTAUDIO_SINT16 )
  6620. deviceFormat = SND_PCM_FORMAT_S16;
  6621. else if ( format == RTAUDIO_SINT24 )
  6622. deviceFormat = SND_PCM_FORMAT_S24;
  6623. else if ( format == RTAUDIO_SINT32 )
  6624. deviceFormat = SND_PCM_FORMAT_S32;
  6625. else if ( format == RTAUDIO_FLOAT32 )
  6626. deviceFormat = SND_PCM_FORMAT_FLOAT;
  6627. else if ( format == RTAUDIO_FLOAT64 )
  6628. deviceFormat = SND_PCM_FORMAT_FLOAT64;
  6629. if ( snd_pcm_hw_params_test_format(phandle, hw_params, deviceFormat) == 0) {
  6630. stream_.deviceFormat[mode] = format;
  6631. goto setFormat;
  6632. }
  6633. // The user requested format is not natively supported by the device.
  6634. deviceFormat = SND_PCM_FORMAT_FLOAT64;
  6635. if ( snd_pcm_hw_params_test_format( phandle, hw_params, deviceFormat ) == 0 ) {
  6636. stream_.deviceFormat[mode] = RTAUDIO_FLOAT64;
  6637. goto setFormat;
  6638. }
  6639. deviceFormat = SND_PCM_FORMAT_FLOAT;
  6640. if ( snd_pcm_hw_params_test_format(phandle, hw_params, deviceFormat ) == 0 ) {
  6641. stream_.deviceFormat[mode] = RTAUDIO_FLOAT32;
  6642. goto setFormat;
  6643. }
  6644. deviceFormat = SND_PCM_FORMAT_S32;
  6645. if ( snd_pcm_hw_params_test_format(phandle, hw_params, deviceFormat ) == 0 ) {
  6646. stream_.deviceFormat[mode] = RTAUDIO_SINT32;
  6647. goto setFormat;
  6648. }
  6649. deviceFormat = SND_PCM_FORMAT_S24;
  6650. if ( snd_pcm_hw_params_test_format(phandle, hw_params, deviceFormat ) == 0 ) {
  6651. stream_.deviceFormat[mode] = RTAUDIO_SINT24;
  6652. goto setFormat;
  6653. }
  6654. deviceFormat = SND_PCM_FORMAT_S16;
  6655. if ( snd_pcm_hw_params_test_format(phandle, hw_params, deviceFormat ) == 0 ) {
  6656. stream_.deviceFormat[mode] = RTAUDIO_SINT16;
  6657. goto setFormat;
  6658. }
  6659. deviceFormat = SND_PCM_FORMAT_S8;
  6660. if ( snd_pcm_hw_params_test_format(phandle, hw_params, deviceFormat ) == 0 ) {
  6661. stream_.deviceFormat[mode] = RTAUDIO_SINT8;
  6662. goto setFormat;
  6663. }
  6664. // If we get here, no supported format was found.
  6665. snd_pcm_close( phandle );
  6666. errorStream_ << "RtApiAlsa::probeDeviceOpen: pcm device " << device << " data format not supported by RtAudio.";
  6667. errorText_ = errorStream_.str();
  6668. return FAILURE;
  6669. setFormat:
  6670. result = snd_pcm_hw_params_set_format( phandle, hw_params, deviceFormat );
  6671. if ( result < 0 ) {
  6672. snd_pcm_close( phandle );
  6673. errorStream_ << "RtApiAlsa::probeDeviceOpen: error setting pcm device (" << name << ") data format, " << snd_strerror( result ) << ".";
  6674. errorText_ = errorStream_.str();
  6675. return FAILURE;
  6676. }
  6677. // Determine whether byte-swaping is necessary.
  6678. stream_.doByteSwap[mode] = false;
  6679. if ( deviceFormat != SND_PCM_FORMAT_S8 ) {
  6680. result = snd_pcm_format_cpu_endian( deviceFormat );
  6681. if ( result == 0 )
  6682. stream_.doByteSwap[mode] = true;
  6683. else if (result < 0) {
  6684. snd_pcm_close( phandle );
  6685. errorStream_ << "RtApiAlsa::probeDeviceOpen: error getting pcm device (" << name << ") endian-ness, " << snd_strerror( result ) << ".";
  6686. errorText_ = errorStream_.str();
  6687. return FAILURE;
  6688. }
  6689. }
  6690. // Set the sample rate.
  6691. result = snd_pcm_hw_params_set_rate_near( phandle, hw_params, (unsigned int*) &sampleRate, 0 );
  6692. if ( result < 0 ) {
  6693. snd_pcm_close( phandle );
  6694. errorStream_ << "RtApiAlsa::probeDeviceOpen: error setting sample rate on device (" << name << "), " << snd_strerror( result ) << ".";
  6695. errorText_ = errorStream_.str();
  6696. return FAILURE;
  6697. }
  6698. // Determine the number of channels for this device. We support a possible
  6699. // minimum device channel number > than the value requested by the user.
  6700. stream_.nUserChannels[mode] = channels;
  6701. unsigned int value;
  6702. result = snd_pcm_hw_params_get_channels_max( hw_params, &value );
  6703. unsigned int deviceChannels = value;
  6704. if ( result < 0 || deviceChannels < channels + firstChannel ) {
  6705. snd_pcm_close( phandle );
  6706. errorStream_ << "RtApiAlsa::probeDeviceOpen: requested channel parameters not supported by device (" << name << "), " << snd_strerror( result ) << ".";
  6707. errorText_ = errorStream_.str();
  6708. return FAILURE;
  6709. }
  6710. result = snd_pcm_hw_params_get_channels_min( hw_params, &value );
  6711. if ( result < 0 ) {
  6712. snd_pcm_close( phandle );
  6713. errorStream_ << "RtApiAlsa::probeDeviceOpen: error getting minimum channels for device (" << name << "), " << snd_strerror( result ) << ".";
  6714. errorText_ = errorStream_.str();
  6715. return FAILURE;
  6716. }
  6717. deviceChannels = value;
  6718. if ( deviceChannels < channels + firstChannel ) deviceChannels = channels + firstChannel;
  6719. stream_.nDeviceChannels[mode] = deviceChannels;
  6720. // Set the device channels.
  6721. result = snd_pcm_hw_params_set_channels( phandle, hw_params, deviceChannels );
  6722. if ( result < 0 ) {
  6723. snd_pcm_close( phandle );
  6724. errorStream_ << "RtApiAlsa::probeDeviceOpen: error setting channels for device (" << name << "), " << snd_strerror( result ) << ".";
  6725. errorText_ = errorStream_.str();
  6726. return FAILURE;
  6727. }
  6728. // Set the buffer (or period) size.
  6729. int dir = 0;
  6730. snd_pcm_uframes_t periodSize = *bufferSize;
  6731. result = snd_pcm_hw_params_set_period_size_near( phandle, hw_params, &periodSize, &dir );
  6732. if ( result < 0 ) {
  6733. snd_pcm_close( phandle );
  6734. errorStream_ << "RtApiAlsa::probeDeviceOpen: error setting period size for device (" << name << "), " << snd_strerror( result ) << ".";
  6735. errorText_ = errorStream_.str();
  6736. return FAILURE;
  6737. }
  6738. *bufferSize = periodSize;
  6739. // Set the buffer number, which in ALSA is referred to as the "period".
  6740. unsigned int periods = 0;
  6741. if ( options && options->flags & RTAUDIO_MINIMIZE_LATENCY ) periods = 2;
  6742. if ( options && options->numberOfBuffers > 0 ) periods = options->numberOfBuffers;
  6743. if ( periods < 2 ) periods = 4; // a fairly safe default value
  6744. result = snd_pcm_hw_params_set_periods_near( phandle, hw_params, &periods, &dir );
  6745. if ( result < 0 ) {
  6746. snd_pcm_close( phandle );
  6747. errorStream_ << "RtApiAlsa::probeDeviceOpen: error setting periods for device (" << name << "), " << snd_strerror( result ) << ".";
  6748. errorText_ = errorStream_.str();
  6749. return FAILURE;
  6750. }
  6751. // If attempting to setup a duplex stream, the bufferSize parameter
  6752. // MUST be the same in both directions!
  6753. if ( stream_.mode == OUTPUT && mode == INPUT && *bufferSize != stream_.bufferSize ) {
  6754. snd_pcm_close( phandle );
  6755. errorStream_ << "RtApiAlsa::probeDeviceOpen: system error setting buffer size for duplex stream on device (" << name << ").";
  6756. errorText_ = errorStream_.str();
  6757. return FAILURE;
  6758. }
  6759. stream_.bufferSize = *bufferSize;
  6760. // Install the hardware configuration
  6761. result = snd_pcm_hw_params( phandle, hw_params );
  6762. if ( result < 0 ) {
  6763. snd_pcm_close( phandle );
  6764. errorStream_ << "RtApiAlsa::probeDeviceOpen: error installing hardware configuration on device (" << name << "), " << snd_strerror( result ) << ".";
  6765. errorText_ = errorStream_.str();
  6766. return FAILURE;
  6767. }
  6768. #if defined(__RTAUDIO_DEBUG__)
  6769. fprintf(stderr, "\nRtApiAlsa: dump hardware params after installation:\n\n");
  6770. snd_pcm_hw_params_dump( hw_params, out );
  6771. #endif
  6772. // Set the software configuration to fill buffers with zeros and prevent device stopping on xruns.
  6773. snd_pcm_sw_params_t *sw_params = NULL;
  6774. snd_pcm_sw_params_alloca( &sw_params );
  6775. snd_pcm_sw_params_current( phandle, sw_params );
  6776. snd_pcm_sw_params_set_start_threshold( phandle, sw_params, *bufferSize );
  6777. snd_pcm_sw_params_set_stop_threshold( phandle, sw_params, ULONG_MAX );
  6778. snd_pcm_sw_params_set_silence_threshold( phandle, sw_params, 0 );
  6779. // The following two settings were suggested by Theo Veenker
  6780. //snd_pcm_sw_params_set_avail_min( phandle, sw_params, *bufferSize );
  6781. //snd_pcm_sw_params_set_xfer_align( phandle, sw_params, 1 );
  6782. // here are two options for a fix
  6783. //snd_pcm_sw_params_set_silence_size( phandle, sw_params, ULONG_MAX );
  6784. snd_pcm_uframes_t val;
  6785. snd_pcm_sw_params_get_boundary( sw_params, &val );
  6786. snd_pcm_sw_params_set_silence_size( phandle, sw_params, val );
  6787. result = snd_pcm_sw_params( phandle, sw_params );
  6788. if ( result < 0 ) {
  6789. snd_pcm_close( phandle );
  6790. errorStream_ << "RtApiAlsa::probeDeviceOpen: error installing software configuration on device (" << name << "), " << snd_strerror( result ) << ".";
  6791. errorText_ = errorStream_.str();
  6792. return FAILURE;
  6793. }
  6794. #if defined(__RTAUDIO_DEBUG__)
  6795. fprintf(stderr, "\nRtApiAlsa: dump software params after installation:\n\n");
  6796. snd_pcm_sw_params_dump( sw_params, out );
  6797. #endif
  6798. // Set flags for buffer conversion
  6799. stream_.doConvertBuffer[mode] = false;
  6800. if ( stream_.userFormat != stream_.deviceFormat[mode] )
  6801. stream_.doConvertBuffer[mode] = true;
  6802. if ( stream_.nUserChannels[mode] < stream_.nDeviceChannels[mode] )
  6803. stream_.doConvertBuffer[mode] = true;
  6804. if ( stream_.userInterleaved != stream_.deviceInterleaved[mode] &&
  6805. stream_.nUserChannels[mode] > 1 )
  6806. stream_.doConvertBuffer[mode] = true;
  6807. // Allocate the ApiHandle if necessary and then save.
  6808. AlsaHandle *apiInfo = 0;
  6809. if ( stream_.apiHandle == 0 ) {
  6810. try {
  6811. apiInfo = (AlsaHandle *) new AlsaHandle;
  6812. }
  6813. catch ( std::bad_alloc& ) {
  6814. errorText_ = "RtApiAlsa::probeDeviceOpen: error allocating AlsaHandle memory.";
  6815. goto error;
  6816. }
  6817. if ( pthread_cond_init( &apiInfo->runnable_cv, NULL ) ) {
  6818. errorText_ = "RtApiAlsa::probeDeviceOpen: error initializing pthread condition variable.";
  6819. goto error;
  6820. }
  6821. stream_.apiHandle = (void *) apiInfo;
  6822. apiInfo->handles[0] = 0;
  6823. apiInfo->handles[1] = 0;
  6824. }
  6825. else {
  6826. apiInfo = (AlsaHandle *) stream_.apiHandle;
  6827. }
  6828. apiInfo->handles[mode] = phandle;
  6829. phandle = 0;
  6830. // Allocate necessary internal buffers.
  6831. unsigned long bufferBytes;
  6832. bufferBytes = stream_.nUserChannels[mode] * *bufferSize * formatBytes( stream_.userFormat );
  6833. stream_.userBuffer[mode] = (char *) calloc( bufferBytes, 1 );
  6834. if ( stream_.userBuffer[mode] == NULL ) {
  6835. errorText_ = "RtApiAlsa::probeDeviceOpen: error allocating user buffer memory.";
  6836. goto error;
  6837. }
  6838. if ( stream_.doConvertBuffer[mode] ) {
  6839. bool makeBuffer = true;
  6840. bufferBytes = stream_.nDeviceChannels[mode] * formatBytes( stream_.deviceFormat[mode] );
  6841. if ( mode == INPUT ) {
  6842. if ( stream_.mode == OUTPUT && stream_.deviceBuffer ) {
  6843. unsigned long bytesOut = stream_.nDeviceChannels[0] * formatBytes( stream_.deviceFormat[0] );
  6844. if ( bufferBytes <= bytesOut ) makeBuffer = false;
  6845. }
  6846. }
  6847. if ( makeBuffer ) {
  6848. bufferBytes *= *bufferSize;
  6849. if ( stream_.deviceBuffer ) free( stream_.deviceBuffer );
  6850. stream_.deviceBuffer = (char *) calloc( bufferBytes, 1 );
  6851. if ( stream_.deviceBuffer == NULL ) {
  6852. errorText_ = "RtApiAlsa::probeDeviceOpen: error allocating device buffer memory.";
  6853. goto error;
  6854. }
  6855. }
  6856. }
  6857. stream_.sampleRate = sampleRate;
  6858. stream_.nBuffers = periods;
  6859. stream_.device[mode] = device;
  6860. stream_.state = STREAM_STOPPED;
  6861. // Setup the buffer conversion information structure.
  6862. if ( stream_.doConvertBuffer[mode] ) setConvertInfo( mode, firstChannel );
  6863. // Setup thread if necessary.
  6864. if ( stream_.mode == OUTPUT && mode == INPUT ) {
  6865. // We had already set up an output stream.
  6866. stream_.mode = DUPLEX;
  6867. // Link the streams if possible.
  6868. apiInfo->synchronized = false;
  6869. if ( snd_pcm_link( apiInfo->handles[0], apiInfo->handles[1] ) == 0 )
  6870. apiInfo->synchronized = true;
  6871. else {
  6872. errorText_ = "RtApiAlsa::probeDeviceOpen: unable to synchronize input and output devices.";
  6873. error( RtAudioError::WARNING );
  6874. }
  6875. }
  6876. else {
  6877. stream_.mode = mode;
  6878. // Setup callback thread.
  6879. stream_.callbackInfo.object = (void *) this;
  6880. // Set the thread attributes for joinable and realtime scheduling
  6881. // priority (optional). The higher priority will only take affect
  6882. // if the program is run as root or suid. Note, under Linux
  6883. // processes with CAP_SYS_NICE privilege, a user can change
  6884. // scheduling policy and priority (thus need not be root). See
  6885. // POSIX "capabilities".
  6886. pthread_attr_t attr;
  6887. pthread_attr_init( &attr );
  6888. pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_JOINABLE );
  6889. #ifdef SCHED_RR // Undefined with some OSes (e.g. NetBSD 1.6.x with GNU Pthread)
  6890. if ( options && options->flags & RTAUDIO_SCHEDULE_REALTIME ) {
  6891. stream_.callbackInfo.doRealtime = true;
  6892. struct sched_param param;
  6893. int priority = options->priority;
  6894. int min = sched_get_priority_min( SCHED_RR );
  6895. int max = sched_get_priority_max( SCHED_RR );
  6896. if ( priority < min ) priority = min;
  6897. else if ( priority > max ) priority = max;
  6898. param.sched_priority = priority;
  6899. // Set the policy BEFORE the priority. Otherwise it fails.
  6900. pthread_attr_setschedpolicy(&attr, SCHED_RR);
  6901. pthread_attr_setscope (&attr, PTHREAD_SCOPE_SYSTEM);
  6902. // This is definitely required. Otherwise it fails.
  6903. pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
  6904. pthread_attr_setschedparam(&attr, &param);
  6905. }
  6906. else
  6907. pthread_attr_setschedpolicy( &attr, SCHED_OTHER );
  6908. #else
  6909. pthread_attr_setschedpolicy( &attr, SCHED_OTHER );
  6910. #endif
  6911. stream_.callbackInfo.isRunning = true;
  6912. result = pthread_create( &stream_.callbackInfo.thread, &attr, alsaCallbackHandler, &stream_.callbackInfo );
  6913. pthread_attr_destroy( &attr );
  6914. if ( result ) {
  6915. // Failed. Try instead with default attributes.
  6916. result = pthread_create( &stream_.callbackInfo.thread, NULL, alsaCallbackHandler, &stream_.callbackInfo );
  6917. if ( result ) {
  6918. stream_.callbackInfo.isRunning = false;
  6919. errorText_ = "RtApiAlsa::error creating callback thread!";
  6920. goto error;
  6921. }
  6922. }
  6923. }
  6924. return SUCCESS;
  6925. error:
  6926. if ( apiInfo ) {
  6927. pthread_cond_destroy( &apiInfo->runnable_cv );
  6928. if ( apiInfo->handles[0] ) snd_pcm_close( apiInfo->handles[0] );
  6929. if ( apiInfo->handles[1] ) snd_pcm_close( apiInfo->handles[1] );
  6930. delete apiInfo;
  6931. stream_.apiHandle = 0;
  6932. }
  6933. if ( phandle) snd_pcm_close( phandle );
  6934. for ( int i=0; i<2; i++ ) {
  6935. if ( stream_.userBuffer[i] ) {
  6936. free( stream_.userBuffer[i] );
  6937. stream_.userBuffer[i] = 0;
  6938. }
  6939. }
  6940. if ( stream_.deviceBuffer ) {
  6941. free( stream_.deviceBuffer );
  6942. stream_.deviceBuffer = 0;
  6943. }
  6944. stream_.state = STREAM_CLOSED;
  6945. return FAILURE;
  6946. }
  6947. void RtApiAlsa :: closeStream()
  6948. {
  6949. if ( stream_.state == STREAM_CLOSED ) {
  6950. errorText_ = "RtApiAlsa::closeStream(): no open stream to close!";
  6951. error( RtAudioError::WARNING );
  6952. return;
  6953. }
  6954. AlsaHandle *apiInfo = (AlsaHandle *) stream_.apiHandle;
  6955. stream_.callbackInfo.isRunning = false;
  6956. MUTEX_LOCK( &stream_.mutex );
  6957. if ( stream_.state == STREAM_STOPPED ) {
  6958. apiInfo->runnable = true;
  6959. pthread_cond_signal( &apiInfo->runnable_cv );
  6960. }
  6961. MUTEX_UNLOCK( &stream_.mutex );
  6962. pthread_join( stream_.callbackInfo.thread, NULL );
  6963. if ( stream_.state == STREAM_RUNNING ) {
  6964. stream_.state = STREAM_STOPPED;
  6965. if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX )
  6966. snd_pcm_drop( apiInfo->handles[0] );
  6967. if ( stream_.mode == INPUT || stream_.mode == DUPLEX )
  6968. snd_pcm_drop( apiInfo->handles[1] );
  6969. }
  6970. if ( apiInfo ) {
  6971. pthread_cond_destroy( &apiInfo->runnable_cv );
  6972. if ( apiInfo->handles[0] ) snd_pcm_close( apiInfo->handles[0] );
  6973. if ( apiInfo->handles[1] ) snd_pcm_close( apiInfo->handles[1] );
  6974. delete apiInfo;
  6975. stream_.apiHandle = 0;
  6976. }
  6977. for ( int i=0; i<2; i++ ) {
  6978. if ( stream_.userBuffer[i] ) {
  6979. free( stream_.userBuffer[i] );
  6980. stream_.userBuffer[i] = 0;
  6981. }
  6982. }
  6983. if ( stream_.deviceBuffer ) {
  6984. free( stream_.deviceBuffer );
  6985. stream_.deviceBuffer = 0;
  6986. }
  6987. stream_.mode = UNINITIALIZED;
  6988. stream_.state = STREAM_CLOSED;
  6989. }
  6990. void RtApiAlsa :: startStream()
  6991. {
  6992. // This method calls snd_pcm_prepare if the device isn't already in that state.
  6993. verifyStream();
  6994. if ( stream_.state == STREAM_RUNNING ) {
  6995. errorText_ = "RtApiAlsa::startStream(): the stream is already running!";
  6996. error( RtAudioError::WARNING );
  6997. return;
  6998. }
  6999. MUTEX_LOCK( &stream_.mutex );
  7000. #if defined( HAVE_GETTIMEOFDAY )
  7001. gettimeofday( &stream_.lastTickTimestamp, NULL );
  7002. #endif
  7003. int result = 0;
  7004. snd_pcm_state_t state;
  7005. AlsaHandle *apiInfo = (AlsaHandle *) stream_.apiHandle;
  7006. snd_pcm_t **handle = (snd_pcm_t **) apiInfo->handles;
  7007. if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) {
  7008. state = snd_pcm_state( handle[0] );
  7009. if ( state != SND_PCM_STATE_PREPARED ) {
  7010. result = snd_pcm_prepare( handle[0] );
  7011. if ( result < 0 ) {
  7012. errorStream_ << "RtApiAlsa::startStream: error preparing output pcm device, " << snd_strerror( result ) << ".";
  7013. errorText_ = errorStream_.str();
  7014. goto unlock;
  7015. }
  7016. }
  7017. }
  7018. if ( ( stream_.mode == INPUT || stream_.mode == DUPLEX ) && !apiInfo->synchronized ) {
  7019. result = snd_pcm_drop(handle[1]); // fix to remove stale data received since device has been open
  7020. state = snd_pcm_state( handle[1] );
  7021. if ( state != SND_PCM_STATE_PREPARED ) {
  7022. result = snd_pcm_prepare( handle[1] );
  7023. if ( result < 0 ) {
  7024. errorStream_ << "RtApiAlsa::startStream: error preparing input pcm device, " << snd_strerror( result ) << ".";
  7025. errorText_ = errorStream_.str();
  7026. goto unlock;
  7027. }
  7028. }
  7029. }
  7030. stream_.state = STREAM_RUNNING;
  7031. unlock:
  7032. apiInfo->runnable = true;
  7033. pthread_cond_signal( &apiInfo->runnable_cv );
  7034. MUTEX_UNLOCK( &stream_.mutex );
  7035. if ( result >= 0 ) return;
  7036. error( RtAudioError::SYSTEM_ERROR );
  7037. }
  7038. void RtApiAlsa :: stopStream()
  7039. {
  7040. verifyStream();
  7041. if ( stream_.state == STREAM_STOPPED ) {
  7042. errorText_ = "RtApiAlsa::stopStream(): the stream is already stopped!";
  7043. error( RtAudioError::WARNING );
  7044. return;
  7045. }
  7046. stream_.state = STREAM_STOPPED;
  7047. MUTEX_LOCK( &stream_.mutex );
  7048. int result = 0;
  7049. AlsaHandle *apiInfo = (AlsaHandle *) stream_.apiHandle;
  7050. snd_pcm_t **handle = (snd_pcm_t **) apiInfo->handles;
  7051. if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) {
  7052. if ( apiInfo->synchronized )
  7053. result = snd_pcm_drop( handle[0] );
  7054. else
  7055. result = snd_pcm_drain( handle[0] );
  7056. if ( result < 0 ) {
  7057. errorStream_ << "RtApiAlsa::stopStream: error draining output pcm device, " << snd_strerror( result ) << ".";
  7058. errorText_ = errorStream_.str();
  7059. goto unlock;
  7060. }
  7061. }
  7062. if ( ( stream_.mode == INPUT || stream_.mode == DUPLEX ) && !apiInfo->synchronized ) {
  7063. result = snd_pcm_drop( handle[1] );
  7064. if ( result < 0 ) {
  7065. errorStream_ << "RtApiAlsa::stopStream: error stopping input pcm device, " << snd_strerror( result ) << ".";
  7066. errorText_ = errorStream_.str();
  7067. goto unlock;
  7068. }
  7069. }
  7070. unlock:
  7071. apiInfo->runnable = false; // fixes high CPU usage when stopped
  7072. MUTEX_UNLOCK( &stream_.mutex );
  7073. if ( result >= 0 ) return;
  7074. error( RtAudioError::SYSTEM_ERROR );
  7075. }
  7076. void RtApiAlsa :: abortStream()
  7077. {
  7078. verifyStream();
  7079. if ( stream_.state == STREAM_STOPPED ) {
  7080. errorText_ = "RtApiAlsa::abortStream(): the stream is already stopped!";
  7081. error( RtAudioError::WARNING );
  7082. return;
  7083. }
  7084. stream_.state = STREAM_STOPPED;
  7085. MUTEX_LOCK( &stream_.mutex );
  7086. int result = 0;
  7087. AlsaHandle *apiInfo = (AlsaHandle *) stream_.apiHandle;
  7088. snd_pcm_t **handle = (snd_pcm_t **) apiInfo->handles;
  7089. if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) {
  7090. result = snd_pcm_drop( handle[0] );
  7091. if ( result < 0 ) {
  7092. errorStream_ << "RtApiAlsa::abortStream: error aborting output pcm device, " << snd_strerror( result ) << ".";
  7093. errorText_ = errorStream_.str();
  7094. goto unlock;
  7095. }
  7096. }
  7097. if ( ( stream_.mode == INPUT || stream_.mode == DUPLEX ) && !apiInfo->synchronized ) {
  7098. result = snd_pcm_drop( handle[1] );
  7099. if ( result < 0 ) {
  7100. errorStream_ << "RtApiAlsa::abortStream: error aborting input pcm device, " << snd_strerror( result ) << ".";
  7101. errorText_ = errorStream_.str();
  7102. goto unlock;
  7103. }
  7104. }
  7105. unlock:
  7106. apiInfo->runnable = false; // fixes high CPU usage when stopped
  7107. MUTEX_UNLOCK( &stream_.mutex );
  7108. if ( result >= 0 ) return;
  7109. error( RtAudioError::SYSTEM_ERROR );
  7110. }
  7111. void RtApiAlsa :: callbackEvent()
  7112. {
  7113. AlsaHandle *apiInfo = (AlsaHandle *) stream_.apiHandle;
  7114. if ( stream_.state == STREAM_STOPPED ) {
  7115. MUTEX_LOCK( &stream_.mutex );
  7116. while ( !apiInfo->runnable )
  7117. pthread_cond_wait( &apiInfo->runnable_cv, &stream_.mutex );
  7118. if ( stream_.state != STREAM_RUNNING ) {
  7119. MUTEX_UNLOCK( &stream_.mutex );
  7120. return;
  7121. }
  7122. MUTEX_UNLOCK( &stream_.mutex );
  7123. }
  7124. if ( stream_.state == STREAM_CLOSED ) {
  7125. errorText_ = "RtApiAlsa::callbackEvent(): the stream is closed ... this shouldn't happen!";
  7126. error( RtAudioError::WARNING );
  7127. return;
  7128. }
  7129. int doStopStream = 0;
  7130. RtAudioCallback callback = (RtAudioCallback) stream_.callbackInfo.callback;
  7131. double streamTime = getStreamTime();
  7132. RtAudioStreamStatus status = 0;
  7133. if ( stream_.mode != INPUT && apiInfo->xrun[0] == true ) {
  7134. status |= RTAUDIO_OUTPUT_UNDERFLOW;
  7135. apiInfo->xrun[0] = false;
  7136. }
  7137. if ( stream_.mode != OUTPUT && apiInfo->xrun[1] == true ) {
  7138. status |= RTAUDIO_INPUT_OVERFLOW;
  7139. apiInfo->xrun[1] = false;
  7140. }
  7141. doStopStream = callback( stream_.userBuffer[0], stream_.userBuffer[1],
  7142. stream_.bufferSize, streamTime, status, stream_.callbackInfo.userData );
  7143. if ( doStopStream == 2 ) {
  7144. abortStream();
  7145. return;
  7146. }
  7147. MUTEX_LOCK( &stream_.mutex );
  7148. // The state might change while waiting on a mutex.
  7149. if ( stream_.state == STREAM_STOPPED ) goto unlock;
  7150. int result;
  7151. char *buffer;
  7152. int channels;
  7153. snd_pcm_t **handle;
  7154. snd_pcm_sframes_t frames;
  7155. RtAudioFormat format;
  7156. handle = (snd_pcm_t **) apiInfo->handles;
  7157. if ( stream_.mode == INPUT || stream_.mode == DUPLEX ) {
  7158. // Setup parameters.
  7159. if ( stream_.doConvertBuffer[1] ) {
  7160. buffer = stream_.deviceBuffer;
  7161. channels = stream_.nDeviceChannels[1];
  7162. format = stream_.deviceFormat[1];
  7163. }
  7164. else {
  7165. buffer = stream_.userBuffer[1];
  7166. channels = stream_.nUserChannels[1];
  7167. format = stream_.userFormat;
  7168. }
  7169. // Read samples from device in interleaved/non-interleaved format.
  7170. if ( stream_.deviceInterleaved[1] )
  7171. result = snd_pcm_readi( handle[1], buffer, stream_.bufferSize );
  7172. else {
  7173. void *bufs[channels];
  7174. size_t offset = stream_.bufferSize * formatBytes( format );
  7175. for ( int i=0; i<channels; i++ )
  7176. bufs[i] = (void *) (buffer + (i * offset));
  7177. result = snd_pcm_readn( handle[1], bufs, stream_.bufferSize );
  7178. }
  7179. if ( result < (int) stream_.bufferSize ) {
  7180. // Either an error or overrun occurred.
  7181. if ( result == -EPIPE ) {
  7182. snd_pcm_state_t state = snd_pcm_state( handle[1] );
  7183. if ( state == SND_PCM_STATE_XRUN ) {
  7184. apiInfo->xrun[1] = true;
  7185. result = snd_pcm_prepare( handle[1] );
  7186. if ( result < 0 ) {
  7187. errorStream_ << "RtApiAlsa::callbackEvent: error preparing device after overrun, " << snd_strerror( result ) << ".";
  7188. errorText_ = errorStream_.str();
  7189. }
  7190. }
  7191. else {
  7192. errorStream_ << "RtApiAlsa::callbackEvent: error, current state is " << snd_pcm_state_name( state ) << ", " << snd_strerror( result ) << ".";
  7193. errorText_ = errorStream_.str();
  7194. }
  7195. }
  7196. else {
  7197. errorStream_ << "RtApiAlsa::callbackEvent: audio read error, " << snd_strerror( result ) << ".";
  7198. errorText_ = errorStream_.str();
  7199. }
  7200. error( RtAudioError::WARNING );
  7201. goto tryOutput;
  7202. }
  7203. // Do byte swapping if necessary.
  7204. if ( stream_.doByteSwap[1] )
  7205. byteSwapBuffer( buffer, stream_.bufferSize * channels, format );
  7206. // Do buffer conversion if necessary.
  7207. if ( stream_.doConvertBuffer[1] )
  7208. convertBuffer( stream_.userBuffer[1], stream_.deviceBuffer, stream_.convertInfo[1] );
  7209. // Check stream latency
  7210. result = snd_pcm_delay( handle[1], &frames );
  7211. if ( result == 0 && frames > 0 ) stream_.latency[1] = frames;
  7212. }
  7213. tryOutput:
  7214. if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) {
  7215. // Setup parameters and do buffer conversion if necessary.
  7216. if ( stream_.doConvertBuffer[0] ) {
  7217. buffer = stream_.deviceBuffer;
  7218. convertBuffer( buffer, stream_.userBuffer[0], stream_.convertInfo[0] );
  7219. channels = stream_.nDeviceChannels[0];
  7220. format = stream_.deviceFormat[0];
  7221. }
  7222. else {
  7223. buffer = stream_.userBuffer[0];
  7224. channels = stream_.nUserChannels[0];
  7225. format = stream_.userFormat;
  7226. }
  7227. // Do byte swapping if necessary.
  7228. if ( stream_.doByteSwap[0] )
  7229. byteSwapBuffer(buffer, stream_.bufferSize * channels, format);
  7230. // Write samples to device in interleaved/non-interleaved format.
  7231. if ( stream_.deviceInterleaved[0] )
  7232. result = snd_pcm_writei( handle[0], buffer, stream_.bufferSize );
  7233. else {
  7234. void *bufs[channels];
  7235. size_t offset = stream_.bufferSize * formatBytes( format );
  7236. for ( int i=0; i<channels; i++ )
  7237. bufs[i] = (void *) (buffer + (i * offset));
  7238. result = snd_pcm_writen( handle[0], bufs, stream_.bufferSize );
  7239. }
  7240. if ( result < (int) stream_.bufferSize ) {
  7241. // Either an error or underrun occurred.
  7242. if ( result == -EPIPE ) {
  7243. snd_pcm_state_t state = snd_pcm_state( handle[0] );
  7244. if ( state == SND_PCM_STATE_XRUN ) {
  7245. apiInfo->xrun[0] = true;
  7246. result = snd_pcm_prepare( handle[0] );
  7247. if ( result < 0 ) {
  7248. errorStream_ << "RtApiAlsa::callbackEvent: error preparing device after underrun, " << snd_strerror( result ) << ".";
  7249. errorText_ = errorStream_.str();
  7250. }
  7251. else
  7252. errorText_ = "RtApiAlsa::callbackEvent: audio write error, underrun.";
  7253. }
  7254. else {
  7255. errorStream_ << "RtApiAlsa::callbackEvent: error, current state is " << snd_pcm_state_name( state ) << ", " << snd_strerror( result ) << ".";
  7256. errorText_ = errorStream_.str();
  7257. }
  7258. }
  7259. else {
  7260. errorStream_ << "RtApiAlsa::callbackEvent: audio write error, " << snd_strerror( result ) << ".";
  7261. errorText_ = errorStream_.str();
  7262. }
  7263. error( RtAudioError::WARNING );
  7264. goto unlock;
  7265. }
  7266. // Check stream latency
  7267. result = snd_pcm_delay( handle[0], &frames );
  7268. if ( result == 0 && frames > 0 ) stream_.latency[0] = frames;
  7269. }
  7270. unlock:
  7271. MUTEX_UNLOCK( &stream_.mutex );
  7272. RtApi::tickStreamTime();
  7273. if ( doStopStream == 1 ) this->stopStream();
  7274. }
  7275. static void *alsaCallbackHandler( void *ptr )
  7276. {
  7277. CallbackInfo *info = (CallbackInfo *) ptr;
  7278. RtApiAlsa *object = (RtApiAlsa *) info->object;
  7279. bool *isRunning = &info->isRunning;
  7280. #ifdef SCHED_RR // Undefined with some OSes (e.g. NetBSD 1.6.x with GNU Pthread)
  7281. if ( info->doRealtime ) {
  7282. std::cerr << "RtAudio alsa: " <<
  7283. (sched_getscheduler(0) == SCHED_RR ? "" : "_NOT_ ") <<
  7284. "running realtime scheduling" << std::endl;
  7285. }
  7286. #endif
  7287. while ( *isRunning == true ) {
  7288. pthread_testcancel();
  7289. object->callbackEvent();
  7290. }
  7291. pthread_exit( NULL );
  7292. }
  7293. //******************** End of __LINUX_ALSA__ *********************//
  7294. #endif
  7295. #if defined(__LINUX_PULSE__)
  7296. // Code written by Peter Meerwald, [email protected]
  7297. // and Tristan Matthews.
  7298. #include <pulse/error.h>
  7299. #include <pulse/simple.h>
  7300. #include <pulse/pulseaudio.h>
  7301. #include <cstdio>
  7302. static pa_mainloop_api *rt_pa_mainloop_api = NULL;
  7303. struct PaDeviceInfo {
  7304. PaDeviceInfo() : sink_index(-1), source_index(-1) {}
  7305. int sink_index;
  7306. int source_index;
  7307. std::string sink_name;
  7308. std::string source_name;
  7309. RtAudio::DeviceInfo info;
  7310. };
  7311. static struct {
  7312. std::vector<PaDeviceInfo> dev;
  7313. std::string default_sink_name;
  7314. std::string default_source_name;
  7315. int default_rate;
  7316. } rt_pa_info;
  7317. static const unsigned int SUPPORTED_SAMPLERATES[] = { 8000, 16000, 22050, 32000,
  7318. 44100, 48000, 96000, 192000, 0};
  7319. struct rtaudio_pa_format_mapping_t {
  7320. RtAudioFormat rtaudio_format;
  7321. pa_sample_format_t pa_format;
  7322. };
  7323. static const rtaudio_pa_format_mapping_t supported_sampleformats[] = {
  7324. {RTAUDIO_SINT16, PA_SAMPLE_S16LE},
  7325. {RTAUDIO_SINT24, PA_SAMPLE_S24LE},
  7326. {RTAUDIO_SINT32, PA_SAMPLE_S32LE},
  7327. {RTAUDIO_FLOAT32, PA_SAMPLE_FLOAT32LE},
  7328. {0, PA_SAMPLE_INVALID}};
  7329. struct PulseAudioHandle {
  7330. pa_simple *s_play;
  7331. pa_simple *s_rec;
  7332. pthread_t thread;
  7333. pthread_cond_t runnable_cv;
  7334. bool runnable;
  7335. PulseAudioHandle() : s_play(0), s_rec(0), runnable(false) { }
  7336. };
  7337. static void rt_pa_mainloop_api_quit(int ret) {
  7338. rt_pa_mainloop_api->quit(rt_pa_mainloop_api, ret);
  7339. }
  7340. static void rt_pa_set_server_info(pa_context *context, const pa_server_info *info, void *data){
  7341. (void)context;
  7342. (void)data;
  7343. pa_sample_spec ss;
  7344. if (!info) {
  7345. rt_pa_mainloop_api_quit(1);
  7346. return;
  7347. }
  7348. ss = info->sample_spec;
  7349. rt_pa_info.default_rate = ss.rate;
  7350. rt_pa_info.default_sink_name = info->default_sink_name;
  7351. rt_pa_info.default_source_name = info->default_source_name;
  7352. }
  7353. static void rt_pa_set_sink_info(pa_context * /*c*/, const pa_sink_info *i,
  7354. int eol, void * /*userdata*/)
  7355. {
  7356. if (eol) return;
  7357. PaDeviceInfo inf;
  7358. inf.info.name = pa_proplist_gets(i->proplist, "device.description");
  7359. inf.info.probed = true;
  7360. inf.info.outputChannels = i->sample_spec.channels;
  7361. inf.info.preferredSampleRate = i->sample_spec.rate;
  7362. inf.info.isDefaultOutput = (rt_pa_info.default_sink_name == i->name);
  7363. inf.sink_index = i->index;
  7364. inf.sink_name = i->name;
  7365. for ( const unsigned int *sr = SUPPORTED_SAMPLERATES; *sr; ++sr )
  7366. inf.info.sampleRates.push_back( *sr );
  7367. for ( const rtaudio_pa_format_mapping_t *fm = supported_sampleformats;
  7368. fm->rtaudio_format; ++fm )
  7369. inf.info.nativeFormats |= fm->rtaudio_format;
  7370. for (size_t i=0; i < rt_pa_info.dev.size(); i++)
  7371. {
  7372. /* Attempt to match up sink and source records by device description. */
  7373. if (rt_pa_info.dev[i].info.name == inf.info.name) {
  7374. rt_pa_info.dev[i].sink_index = inf.sink_index;
  7375. rt_pa_info.dev[i].sink_name = inf.sink_name;
  7376. rt_pa_info.dev[i].info.outputChannels = inf.info.outputChannels;
  7377. rt_pa_info.dev[i].info.isDefaultOutput = inf.info.isDefaultOutput;
  7378. /* Assume duplex channels are minimum of input and output channels. */
  7379. /* Uncomment if we add support for DUPLEX
  7380. if (rt_pa_info.dev[i].source_index > -1)
  7381. (inf.info.outputChannels < rt_pa_info.dev[i].info.inputChannels)
  7382. ? inf.info.outputChannels : rt_pa_info.dev[i].info.inputChannels;
  7383. */
  7384. return;
  7385. }
  7386. }
  7387. /* try to ensure device #0 is the default */
  7388. if (inf.info.isDefaultOutput)
  7389. rt_pa_info.dev.insert(rt_pa_info.dev.begin(), inf);
  7390. else
  7391. rt_pa_info.dev.push_back(inf);
  7392. }
  7393. static void rt_pa_set_source_info_and_quit(pa_context * /*c*/, const pa_source_info *i,
  7394. int eol, void * /*userdata*/)
  7395. {
  7396. if (eol) {
  7397. rt_pa_mainloop_api_quit(0);
  7398. return;
  7399. }
  7400. PaDeviceInfo inf;
  7401. inf.info.name = pa_proplist_gets(i->proplist, "device.description");
  7402. inf.info.probed = true;
  7403. inf.info.inputChannels = i->sample_spec.channels;
  7404. inf.info.preferredSampleRate = i->sample_spec.rate;
  7405. inf.info.isDefaultInput = (rt_pa_info.default_source_name == i->name);
  7406. inf.source_index = i->index;
  7407. inf.source_name = i->name;
  7408. for ( const unsigned int *sr = SUPPORTED_SAMPLERATES; *sr; ++sr )
  7409. inf.info.sampleRates.push_back( *sr );
  7410. for ( const rtaudio_pa_format_mapping_t *fm = supported_sampleformats;
  7411. fm->rtaudio_format; ++fm )
  7412. inf.info.nativeFormats |= fm->rtaudio_format;
  7413. for (size_t i=0; i < rt_pa_info.dev.size(); i++)
  7414. {
  7415. /* Attempt to match up sink and source records by device description. */
  7416. if (rt_pa_info.dev[i].info.name == inf.info.name) {
  7417. rt_pa_info.dev[i].source_index = inf.source_index;
  7418. rt_pa_info.dev[i].source_name = inf.source_name;
  7419. rt_pa_info.dev[i].info.inputChannels = inf.info.inputChannels;
  7420. rt_pa_info.dev[i].info.isDefaultInput = inf.info.isDefaultInput;
  7421. /* Assume duplex channels are minimum of input and output channels. */
  7422. /* Uncomment if we add support for DUPLEX
  7423. if (rt_pa_info.dev[i].sink_index > -1) {
  7424. rt_pa_info.dev[i].info.duplexChannels =
  7425. (inf.info.inputChannels < rt_pa_info.dev[i].info.outputChannels)
  7426. ? inf.info.inputChannels : rt_pa_info.dev[i].info.outputChannels;
  7427. }
  7428. */
  7429. return;
  7430. }
  7431. }
  7432. /* try to ensure device #0 is the default */
  7433. if (inf.info.isDefaultInput)
  7434. rt_pa_info.dev.insert(rt_pa_info.dev.begin(), inf);
  7435. else
  7436. rt_pa_info.dev.push_back(inf);
  7437. }
  7438. static void rt_pa_context_state_callback(pa_context *context, void *userdata) {
  7439. (void)userdata;
  7440. auto state = pa_context_get_state(context);
  7441. switch (state) {
  7442. case PA_CONTEXT_CONNECTING:
  7443. case PA_CONTEXT_AUTHORIZING:
  7444. case PA_CONTEXT_SETTING_NAME:
  7445. break;
  7446. case PA_CONTEXT_READY:
  7447. rt_pa_info.dev.clear();
  7448. pa_context_get_server_info(context, rt_pa_set_server_info, NULL);
  7449. pa_context_get_sink_info_list(context, rt_pa_set_sink_info, NULL);
  7450. pa_context_get_source_info_list(context, rt_pa_set_source_info_and_quit, NULL);
  7451. break;
  7452. case PA_CONTEXT_TERMINATED:
  7453. rt_pa_mainloop_api_quit(0);
  7454. break;
  7455. case PA_CONTEXT_FAILED:
  7456. default:
  7457. rt_pa_mainloop_api_quit(1);
  7458. }
  7459. }
  7460. RtApiPulse::~RtApiPulse()
  7461. {
  7462. if ( stream_.state != STREAM_CLOSED )
  7463. closeStream();
  7464. }
  7465. void RtApiPulse::collectDeviceInfo( void )
  7466. {
  7467. pa_context *context = NULL;
  7468. pa_mainloop *m = NULL;
  7469. char *server = NULL;
  7470. int ret = 1;
  7471. if (!(m = pa_mainloop_new())) {
  7472. errorStream_ << "RtApiPulse::DeviceInfo pa_mainloop_new() failed.";
  7473. errorText_ = errorStream_.str();
  7474. error( RtAudioError::WARNING );
  7475. goto quit;
  7476. }
  7477. rt_pa_mainloop_api = pa_mainloop_get_api(m);
  7478. if (!(context = pa_context_new_with_proplist(rt_pa_mainloop_api, NULL, NULL))) {
  7479. errorStream_ << "pa_context_new() failed.";
  7480. errorText_ = errorStream_.str();
  7481. error( RtAudioError::WARNING );
  7482. goto quit;
  7483. }
  7484. pa_context_set_state_callback(context, rt_pa_context_state_callback, NULL);
  7485. if (pa_context_connect(context, server, PA_CONTEXT_NOFLAGS, NULL) < 0) {
  7486. errorStream_ << "RtApiPulse::DeviceInfo pa_context_connect() failed: "
  7487. << pa_strerror(pa_context_errno(context));
  7488. errorText_ = errorStream_.str();
  7489. error( RtAudioError::WARNING );
  7490. goto quit;
  7491. }
  7492. if (pa_mainloop_run(m, &ret) < 0) {
  7493. errorStream_ << "pa_mainloop_run() failed.";
  7494. errorText_ = errorStream_.str();
  7495. error( RtAudioError::WARNING );
  7496. goto quit;
  7497. }
  7498. if (ret != 0) {
  7499. errorStream_ << "could not get server info.";
  7500. errorText_ = errorStream_.str();
  7501. error( RtAudioError::WARNING );
  7502. goto quit;
  7503. }
  7504. quit:
  7505. if (context)
  7506. pa_context_unref(context);
  7507. if (m) {
  7508. pa_mainloop_free(m);
  7509. }
  7510. pa_xfree(server);
  7511. }
  7512. unsigned int RtApiPulse::getDeviceCount( void )
  7513. {
  7514. collectDeviceInfo();
  7515. return rt_pa_info.dev.size();
  7516. }
  7517. RtAudio::DeviceInfo RtApiPulse::getDeviceInfo( unsigned int device )
  7518. {
  7519. if (rt_pa_info.dev.size()==0)
  7520. collectDeviceInfo();
  7521. if (device < rt_pa_info.dev.size())
  7522. return rt_pa_info.dev[device].info;
  7523. return RtAudio::DeviceInfo();
  7524. }
  7525. static void *pulseaudio_callback( void * user )
  7526. {
  7527. CallbackInfo *cbi = static_cast<CallbackInfo *>( user );
  7528. RtApiPulse *context = static_cast<RtApiPulse *>( cbi->object );
  7529. volatile bool *isRunning = &cbi->isRunning;
  7530. #ifdef SCHED_RR // Undefined with some OSes (e.g. NetBSD 1.6.x with GNU Pthread)
  7531. if (cbi->doRealtime) {
  7532. std::cerr << "RtAudio pulse: " <<
  7533. (sched_getscheduler(0) == SCHED_RR ? "" : "_NOT_ ") <<
  7534. "running realtime scheduling" << std::endl;
  7535. }
  7536. #endif
  7537. while ( *isRunning ) {
  7538. pthread_testcancel();
  7539. context->callbackEvent();
  7540. }
  7541. pthread_exit( NULL );
  7542. }
  7543. void RtApiPulse::closeStream( void )
  7544. {
  7545. PulseAudioHandle *pah = static_cast<PulseAudioHandle *>( stream_.apiHandle );
  7546. stream_.callbackInfo.isRunning = false;
  7547. if ( pah ) {
  7548. MUTEX_LOCK( &stream_.mutex );
  7549. if ( stream_.state == STREAM_STOPPED ) {
  7550. pah->runnable = true;
  7551. pthread_cond_signal( &pah->runnable_cv );
  7552. }
  7553. MUTEX_UNLOCK( &stream_.mutex );
  7554. pthread_join( pah->thread, 0 );
  7555. if ( pah->s_play ) {
  7556. pa_simple_flush( pah->s_play, NULL );
  7557. pa_simple_free( pah->s_play );
  7558. }
  7559. if ( pah->s_rec )
  7560. pa_simple_free( pah->s_rec );
  7561. pthread_cond_destroy( &pah->runnable_cv );
  7562. delete pah;
  7563. stream_.apiHandle = 0;
  7564. }
  7565. if ( stream_.userBuffer[0] ) {
  7566. free( stream_.userBuffer[0] );
  7567. stream_.userBuffer[0] = 0;
  7568. }
  7569. if ( stream_.userBuffer[1] ) {
  7570. free( stream_.userBuffer[1] );
  7571. stream_.userBuffer[1] = 0;
  7572. }
  7573. stream_.state = STREAM_CLOSED;
  7574. stream_.mode = UNINITIALIZED;
  7575. }
  7576. void RtApiPulse::callbackEvent( void )
  7577. {
  7578. PulseAudioHandle *pah = static_cast<PulseAudioHandle *>( stream_.apiHandle );
  7579. if ( stream_.state == STREAM_STOPPED ) {
  7580. MUTEX_LOCK( &stream_.mutex );
  7581. while ( !pah->runnable )
  7582. pthread_cond_wait( &pah->runnable_cv, &stream_.mutex );
  7583. if ( stream_.state != STREAM_RUNNING ) {
  7584. MUTEX_UNLOCK( &stream_.mutex );
  7585. return;
  7586. }
  7587. MUTEX_UNLOCK( &stream_.mutex );
  7588. }
  7589. if ( stream_.state == STREAM_CLOSED ) {
  7590. errorText_ = "RtApiPulse::callbackEvent(): the stream is closed ... "
  7591. "this shouldn't happen!";
  7592. error( RtAudioError::WARNING );
  7593. return;
  7594. }
  7595. RtAudioCallback callback = (RtAudioCallback) stream_.callbackInfo.callback;
  7596. double streamTime = getStreamTime();
  7597. RtAudioStreamStatus status = 0;
  7598. int doStopStream = callback( stream_.userBuffer[OUTPUT], stream_.userBuffer[INPUT],
  7599. stream_.bufferSize, streamTime, status,
  7600. stream_.callbackInfo.userData );
  7601. if ( doStopStream == 2 ) {
  7602. abortStream();
  7603. return;
  7604. }
  7605. MUTEX_LOCK( &stream_.mutex );
  7606. void *pulse_in = stream_.doConvertBuffer[INPUT] ? stream_.deviceBuffer : stream_.userBuffer[INPUT];
  7607. void *pulse_out = stream_.doConvertBuffer[OUTPUT] ? stream_.deviceBuffer : stream_.userBuffer[OUTPUT];
  7608. if ( stream_.state != STREAM_RUNNING )
  7609. goto unlock;
  7610. int pa_error;
  7611. size_t bytes;
  7612. if (stream_.mode == OUTPUT || stream_.mode == DUPLEX ) {
  7613. if ( stream_.doConvertBuffer[OUTPUT] ) {
  7614. convertBuffer( stream_.deviceBuffer,
  7615. stream_.userBuffer[OUTPUT],
  7616. stream_.convertInfo[OUTPUT] );
  7617. bytes = stream_.nDeviceChannels[OUTPUT] * stream_.bufferSize *
  7618. formatBytes( stream_.deviceFormat[OUTPUT] );
  7619. } else
  7620. bytes = stream_.nUserChannels[OUTPUT] * stream_.bufferSize *
  7621. formatBytes( stream_.userFormat );
  7622. if ( pa_simple_write( pah->s_play, pulse_out, bytes, &pa_error ) < 0 ) {
  7623. errorStream_ << "RtApiPulse::callbackEvent: audio write error, " <<
  7624. pa_strerror( pa_error ) << ".";
  7625. errorText_ = errorStream_.str();
  7626. error( RtAudioError::WARNING );
  7627. }
  7628. }
  7629. if ( stream_.mode == INPUT || stream_.mode == DUPLEX) {
  7630. if ( stream_.doConvertBuffer[INPUT] )
  7631. bytes = stream_.nDeviceChannels[INPUT] * stream_.bufferSize *
  7632. formatBytes( stream_.deviceFormat[INPUT] );
  7633. else
  7634. bytes = stream_.nUserChannels[INPUT] * stream_.bufferSize *
  7635. formatBytes( stream_.userFormat );
  7636. if ( pa_simple_read( pah->s_rec, pulse_in, bytes, &pa_error ) < 0 ) {
  7637. errorStream_ << "RtApiPulse::callbackEvent: audio read error, " <<
  7638. pa_strerror( pa_error ) << ".";
  7639. errorText_ = errorStream_.str();
  7640. error( RtAudioError::WARNING );
  7641. }
  7642. if ( stream_.doConvertBuffer[INPUT] ) {
  7643. convertBuffer( stream_.userBuffer[INPUT],
  7644. stream_.deviceBuffer,
  7645. stream_.convertInfo[INPUT] );
  7646. }
  7647. }
  7648. unlock:
  7649. MUTEX_UNLOCK( &stream_.mutex );
  7650. RtApi::tickStreamTime();
  7651. if ( doStopStream == 1 )
  7652. stopStream();
  7653. }
  7654. void RtApiPulse::startStream( void )
  7655. {
  7656. PulseAudioHandle *pah = static_cast<PulseAudioHandle *>( stream_.apiHandle );
  7657. if ( stream_.state == STREAM_CLOSED ) {
  7658. errorText_ = "RtApiPulse::startStream(): the stream is not open!";
  7659. error( RtAudioError::INVALID_USE );
  7660. return;
  7661. }
  7662. if ( stream_.state == STREAM_RUNNING ) {
  7663. errorText_ = "RtApiPulse::startStream(): the stream is already running!";
  7664. error( RtAudioError::WARNING );
  7665. return;
  7666. }
  7667. MUTEX_LOCK( &stream_.mutex );
  7668. #if defined( HAVE_GETTIMEOFDAY )
  7669. gettimeofday( &stream_.lastTickTimestamp, NULL );
  7670. #endif
  7671. stream_.state = STREAM_RUNNING;
  7672. pah->runnable = true;
  7673. pthread_cond_signal( &pah->runnable_cv );
  7674. MUTEX_UNLOCK( &stream_.mutex );
  7675. }
  7676. void RtApiPulse::stopStream( void )
  7677. {
  7678. PulseAudioHandle *pah = static_cast<PulseAudioHandle *>( stream_.apiHandle );
  7679. if ( stream_.state == STREAM_CLOSED ) {
  7680. errorText_ = "RtApiPulse::stopStream(): the stream is not open!";
  7681. error( RtAudioError::INVALID_USE );
  7682. return;
  7683. }
  7684. if ( stream_.state == STREAM_STOPPED ) {
  7685. errorText_ = "RtApiPulse::stopStream(): the stream is already stopped!";
  7686. error( RtAudioError::WARNING );
  7687. return;
  7688. }
  7689. stream_.state = STREAM_STOPPED;
  7690. MUTEX_LOCK( &stream_.mutex );
  7691. if ( pah ) {
  7692. pah->runnable = false;
  7693. if ( pah->s_play ) {
  7694. int pa_error;
  7695. if ( pa_simple_drain( pah->s_play, &pa_error ) < 0 ) {
  7696. errorStream_ << "RtApiPulse::stopStream: error draining output device, " <<
  7697. pa_strerror( pa_error ) << ".";
  7698. errorText_ = errorStream_.str();
  7699. MUTEX_UNLOCK( &stream_.mutex );
  7700. error( RtAudioError::SYSTEM_ERROR );
  7701. return;
  7702. }
  7703. }
  7704. }
  7705. stream_.state = STREAM_STOPPED;
  7706. MUTEX_UNLOCK( &stream_.mutex );
  7707. }
  7708. void RtApiPulse::abortStream( void )
  7709. {
  7710. PulseAudioHandle *pah = static_cast<PulseAudioHandle*>( stream_.apiHandle );
  7711. if ( stream_.state == STREAM_CLOSED ) {
  7712. errorText_ = "RtApiPulse::abortStream(): the stream is not open!";
  7713. error( RtAudioError::INVALID_USE );
  7714. return;
  7715. }
  7716. if ( stream_.state == STREAM_STOPPED ) {
  7717. errorText_ = "RtApiPulse::abortStream(): the stream is already stopped!";
  7718. error( RtAudioError::WARNING );
  7719. return;
  7720. }
  7721. stream_.state = STREAM_STOPPED;
  7722. MUTEX_LOCK( &stream_.mutex );
  7723. if ( pah ) {
  7724. pah->runnable = false;
  7725. if ( pah->s_play ) {
  7726. int pa_error;
  7727. if ( pa_simple_flush( pah->s_play, &pa_error ) < 0 ) {
  7728. errorStream_ << "RtApiPulse::abortStream: error flushing output device, " <<
  7729. pa_strerror( pa_error ) << ".";
  7730. errorText_ = errorStream_.str();
  7731. MUTEX_UNLOCK( &stream_.mutex );
  7732. error( RtAudioError::SYSTEM_ERROR );
  7733. return;
  7734. }
  7735. }
  7736. }
  7737. stream_.state = STREAM_STOPPED;
  7738. MUTEX_UNLOCK( &stream_.mutex );
  7739. }
  7740. bool RtApiPulse::probeDeviceOpen( unsigned int device, StreamMode mode,
  7741. unsigned int channels, unsigned int firstChannel,
  7742. unsigned int sampleRate, RtAudioFormat format,
  7743. unsigned int *bufferSize, RtAudio::StreamOptions *options )
  7744. {
  7745. PulseAudioHandle *pah = 0;
  7746. unsigned long bufferBytes = 0;
  7747. pa_sample_spec ss;
  7748. if ( device >= rt_pa_info.dev.size() ) return false;
  7749. if ( firstChannel != 0 ) {
  7750. errorText_ = "PulseAudio does not support channel offset mapping.";
  7751. return false;
  7752. }
  7753. /* these may be NULL for default, but we've already got the names */
  7754. const char *dev_input = NULL;
  7755. const char *dev_output = NULL;
  7756. if (!rt_pa_info.dev[device].source_name.empty())
  7757. dev_input = rt_pa_info.dev[device].source_name.c_str();
  7758. if (!rt_pa_info.dev[device].sink_name.empty())
  7759. dev_output = rt_pa_info.dev[device].sink_name.c_str();
  7760. if (mode==INPUT && rt_pa_info.dev[device].info.inputChannels == 0) {
  7761. errorText_ = "PulseAudio device does not support input.";
  7762. return false;
  7763. }
  7764. if (mode==OUTPUT && rt_pa_info.dev[device].info.outputChannels == 0) {
  7765. errorText_ = "PulseAudio device does not support output.";
  7766. return false;
  7767. }
  7768. if (mode==DUPLEX && rt_pa_info.dev[device].info.duplexChannels == 0) {
  7769. /* Note: will always error, DUPLEX not yet supported */
  7770. errorText_ = "PulseAudio device does not support duplex.";
  7771. return false;
  7772. }
  7773. if (mode==INPUT && rt_pa_info.dev[device].info.inputChannels < channels) {
  7774. errorText_ = "PulseAudio: unsupported number of input channels.";
  7775. return false;
  7776. }
  7777. if (mode==OUTPUT && rt_pa_info.dev[device].info.outputChannels < channels) {
  7778. errorText_ = "PulseAudio: unsupported number of output channels.";
  7779. return false;
  7780. }
  7781. if (mode==DUPLEX && rt_pa_info.dev[device].info.duplexChannels < channels) {
  7782. /* Note: will always error, DUPLEX not yet supported */
  7783. errorText_ = "PulseAudio: unsupported number of duplex channels.";
  7784. return false;
  7785. }
  7786. ss.channels = channels;
  7787. bool sr_found = false;
  7788. for ( const unsigned int *sr = SUPPORTED_SAMPLERATES; *sr; ++sr ) {
  7789. if ( sampleRate == *sr ) {
  7790. sr_found = true;
  7791. stream_.sampleRate = sampleRate;
  7792. ss.rate = sampleRate;
  7793. break;
  7794. }
  7795. }
  7796. if ( !sr_found ) {
  7797. stream_.sampleRate = sampleRate;
  7798. ss.rate = sampleRate;
  7799. }
  7800. bool sf_found = 0;
  7801. for ( const rtaudio_pa_format_mapping_t *sf = supported_sampleformats;
  7802. sf->rtaudio_format && sf->pa_format != PA_SAMPLE_INVALID; ++sf ) {
  7803. if ( format == sf->rtaudio_format ) {
  7804. sf_found = true;
  7805. stream_.userFormat = sf->rtaudio_format;
  7806. stream_.deviceFormat[mode] = stream_.userFormat;
  7807. ss.format = sf->pa_format;
  7808. break;
  7809. }
  7810. }
  7811. if ( !sf_found ) { // Use internal data format conversion.
  7812. stream_.userFormat = format;
  7813. stream_.deviceFormat[mode] = RTAUDIO_FLOAT32;
  7814. ss.format = PA_SAMPLE_FLOAT32LE;
  7815. }
  7816. // Set other stream parameters.
  7817. if ( options && options->flags & RTAUDIO_NONINTERLEAVED ) stream_.userInterleaved = false;
  7818. else stream_.userInterleaved = true;
  7819. stream_.deviceInterleaved[mode] = true;
  7820. stream_.nBuffers = options ? options->numberOfBuffers : 1;
  7821. stream_.doByteSwap[mode] = false;
  7822. stream_.nUserChannels[mode] = channels;
  7823. stream_.nDeviceChannels[mode] = channels + firstChannel;
  7824. stream_.channelOffset[mode] = 0;
  7825. std::string streamName = "RtAudio";
  7826. // Set flags for buffer conversion.
  7827. stream_.doConvertBuffer[mode] = false;
  7828. if ( stream_.userFormat != stream_.deviceFormat[mode] )
  7829. stream_.doConvertBuffer[mode] = true;
  7830. if ( stream_.nUserChannels[mode] < stream_.nDeviceChannels[mode] )
  7831. stream_.doConvertBuffer[mode] = true;
  7832. if ( stream_.userInterleaved != stream_.deviceInterleaved[mode] )
  7833. stream_.doConvertBuffer[mode] = true;
  7834. // Allocate necessary internal buffers.
  7835. bufferBytes = stream_.nUserChannels[mode] * *bufferSize * formatBytes( stream_.userFormat );
  7836. stream_.userBuffer[mode] = (char *) calloc( bufferBytes, 1 );
  7837. if ( stream_.userBuffer[mode] == NULL ) {
  7838. errorText_ = "RtApiPulse::probeDeviceOpen: error allocating user buffer memory.";
  7839. goto error;
  7840. }
  7841. stream_.bufferSize = *bufferSize;
  7842. if ( stream_.doConvertBuffer[mode] ) {
  7843. bool makeBuffer = true;
  7844. bufferBytes = stream_.nDeviceChannels[mode] * formatBytes( stream_.deviceFormat[mode] );
  7845. if ( mode == INPUT ) {
  7846. if ( stream_.mode == OUTPUT && stream_.deviceBuffer ) {
  7847. unsigned long bytesOut = stream_.nDeviceChannels[0] * formatBytes( stream_.deviceFormat[0] );
  7848. if ( bufferBytes <= bytesOut ) makeBuffer = false;
  7849. }
  7850. }
  7851. if ( makeBuffer ) {
  7852. bufferBytes *= *bufferSize;
  7853. if ( stream_.deviceBuffer ) free( stream_.deviceBuffer );
  7854. stream_.deviceBuffer = (char *) calloc( bufferBytes, 1 );
  7855. if ( stream_.deviceBuffer == NULL ) {
  7856. errorText_ = "RtApiPulse::probeDeviceOpen: error allocating device buffer memory.";
  7857. goto error;
  7858. }
  7859. }
  7860. }
  7861. stream_.device[mode] = device;
  7862. // Setup the buffer conversion information structure.
  7863. if ( stream_.doConvertBuffer[mode] ) setConvertInfo( mode, firstChannel );
  7864. if ( !stream_.apiHandle ) {
  7865. PulseAudioHandle *pah = new PulseAudioHandle;
  7866. if ( !pah ) {
  7867. errorText_ = "RtApiPulse::probeDeviceOpen: error allocating memory for handle.";
  7868. goto error;
  7869. }
  7870. stream_.apiHandle = pah;
  7871. if ( pthread_cond_init( &pah->runnable_cv, NULL ) != 0 ) {
  7872. errorText_ = "RtApiPulse::probeDeviceOpen: error creating condition variable.";
  7873. goto error;
  7874. }
  7875. }
  7876. pah = static_cast<PulseAudioHandle *>( stream_.apiHandle );
  7877. int error;
  7878. if ( options && !options->streamName.empty() ) streamName = options->streamName;
  7879. switch ( mode ) {
  7880. pa_buffer_attr buffer_attr;
  7881. case INPUT:
  7882. buffer_attr.fragsize = bufferBytes;
  7883. buffer_attr.maxlength = -1;
  7884. pah->s_rec = pa_simple_new( NULL, streamName.c_str(), PA_STREAM_RECORD,
  7885. dev_input, "Record", &ss, NULL, &buffer_attr, &error );
  7886. if ( !pah->s_rec ) {
  7887. errorText_ = "RtApiPulse::probeDeviceOpen: error connecting input to PulseAudio server.";
  7888. goto error;
  7889. }
  7890. break;
  7891. case OUTPUT: {
  7892. pa_buffer_attr * attr_ptr;
  7893. if ( options && options->numberOfBuffers > 0 ) {
  7894. // pa_buffer_attr::fragsize is recording-only.
  7895. // Hopefully PortAudio won't access uninitialized fields.
  7896. buffer_attr.maxlength = bufferBytes * options->numberOfBuffers;
  7897. buffer_attr.minreq = -1;
  7898. buffer_attr.prebuf = -1;
  7899. buffer_attr.tlength = -1;
  7900. attr_ptr = &buffer_attr;
  7901. } else {
  7902. attr_ptr = nullptr;
  7903. }
  7904. pah->s_play = pa_simple_new( NULL, streamName.c_str(), PA_STREAM_PLAYBACK,
  7905. dev_output, "Playback", &ss, NULL, attr_ptr, &error );
  7906. if ( !pah->s_play ) {
  7907. errorText_ = "RtApiPulse::probeDeviceOpen: error connecting output to PulseAudio server.";
  7908. goto error;
  7909. }
  7910. break;
  7911. }
  7912. case DUPLEX:
  7913. /* Note: We could add DUPLEX by synchronizing multiple streams,
  7914. but it would mean moving from Simple API to Asynchronous API:
  7915. https://freedesktop.org/software/pulseaudio/doxygen/streams.html#sync_streams */
  7916. errorText_ = "RtApiPulse::probeDeviceOpen: duplex not supported for PulseAudio.";
  7917. goto error;
  7918. default:
  7919. goto error;
  7920. }
  7921. if ( stream_.mode == UNINITIALIZED )
  7922. stream_.mode = mode;
  7923. else if ( stream_.mode == mode )
  7924. goto error;
  7925. else
  7926. stream_.mode = DUPLEX;
  7927. if ( !stream_.callbackInfo.isRunning ) {
  7928. stream_.callbackInfo.object = this;
  7929. stream_.state = STREAM_STOPPED;
  7930. // Set the thread attributes for joinable and realtime scheduling
  7931. // priority (optional). The higher priority will only take affect
  7932. // if the program is run as root or suid. Note, under Linux
  7933. // processes with CAP_SYS_NICE privilege, a user can change
  7934. // scheduling policy and priority (thus need not be root). See
  7935. // POSIX "capabilities".
  7936. pthread_attr_t attr;
  7937. pthread_attr_init( &attr );
  7938. pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_JOINABLE );
  7939. #ifdef SCHED_RR // Undefined with some OSes (e.g. NetBSD 1.6.x with GNU Pthread)
  7940. if ( options && options->flags & RTAUDIO_SCHEDULE_REALTIME ) {
  7941. stream_.callbackInfo.doRealtime = true;
  7942. struct sched_param param;
  7943. int priority = options->priority;
  7944. int min = sched_get_priority_min( SCHED_RR );
  7945. int max = sched_get_priority_max( SCHED_RR );
  7946. if ( priority < min ) priority = min;
  7947. else if ( priority > max ) priority = max;
  7948. param.sched_priority = priority;
  7949. // Set the policy BEFORE the priority. Otherwise it fails.
  7950. pthread_attr_setschedpolicy(&attr, SCHED_RR);
  7951. pthread_attr_setscope (&attr, PTHREAD_SCOPE_SYSTEM);
  7952. // This is definitely required. Otherwise it fails.
  7953. pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
  7954. pthread_attr_setschedparam(&attr, &param);
  7955. }
  7956. else
  7957. pthread_attr_setschedpolicy( &attr, SCHED_OTHER );
  7958. #else
  7959. pthread_attr_setschedpolicy( &attr, SCHED_OTHER );
  7960. #endif
  7961. stream_.callbackInfo.isRunning = true;
  7962. int result = pthread_create( &pah->thread, &attr, pulseaudio_callback, (void *)&stream_.callbackInfo);
  7963. pthread_attr_destroy(&attr);
  7964. if(result != 0) {
  7965. // Failed. Try instead with default attributes.
  7966. result = pthread_create( &pah->thread, NULL, pulseaudio_callback, (void *)&stream_.callbackInfo);
  7967. if(result != 0) {
  7968. stream_.callbackInfo.isRunning = false;
  7969. errorText_ = "RtApiPulse::probeDeviceOpen: error creating thread.";
  7970. goto error;
  7971. }
  7972. }
  7973. }
  7974. return SUCCESS;
  7975. error:
  7976. if ( pah && stream_.callbackInfo.isRunning ) {
  7977. pthread_cond_destroy( &pah->runnable_cv );
  7978. delete pah;
  7979. stream_.apiHandle = 0;
  7980. }
  7981. for ( int i=0; i<2; i++ ) {
  7982. if ( stream_.userBuffer[i] ) {
  7983. free( stream_.userBuffer[i] );
  7984. stream_.userBuffer[i] = 0;
  7985. }
  7986. }
  7987. if ( stream_.deviceBuffer ) {
  7988. free( stream_.deviceBuffer );
  7989. stream_.deviceBuffer = 0;
  7990. }
  7991. stream_.state = STREAM_CLOSED;
  7992. return FAILURE;
  7993. }
  7994. //******************** End of __LINUX_PULSE__ *********************//
  7995. #endif
  7996. #if defined(__LINUX_OSS__)
  7997. #include <unistd.h>
  7998. #include <sys/ioctl.h>
  7999. #include <unistd.h>
  8000. #include <fcntl.h>
  8001. #include <sys/soundcard.h>
  8002. #include <errno.h>
  8003. #include <math.h>
  8004. static void *ossCallbackHandler(void * ptr);
  8005. // A structure to hold various information related to the OSS API
  8006. // implementation.
  8007. struct OssHandle {
  8008. int id[2]; // device ids
  8009. bool xrun[2];
  8010. bool triggered;
  8011. pthread_cond_t runnable;
  8012. OssHandle()
  8013. :triggered(false) { id[0] = 0; id[1] = 0; xrun[0] = false; xrun[1] = false; }
  8014. };
  8015. RtApiOss :: RtApiOss()
  8016. {
  8017. // Nothing to do here.
  8018. }
  8019. RtApiOss :: ~RtApiOss()
  8020. {
  8021. if ( stream_.state != STREAM_CLOSED ) closeStream();
  8022. }
  8023. unsigned int RtApiOss :: getDeviceCount( void )
  8024. {
  8025. int mixerfd = open( "/dev/mixer", O_RDWR, 0 );
  8026. if ( mixerfd == -1 ) {
  8027. errorText_ = "RtApiOss::getDeviceCount: error opening '/dev/mixer'.";
  8028. error( RtAudioError::WARNING );
  8029. return 0;
  8030. }
  8031. oss_sysinfo sysinfo;
  8032. if ( ioctl( mixerfd, SNDCTL_SYSINFO, &sysinfo ) == -1 ) {
  8033. close( mixerfd );
  8034. errorText_ = "RtApiOss::getDeviceCount: error getting sysinfo, OSS version >= 4.0 is required.";
  8035. error( RtAudioError::WARNING );
  8036. return 0;
  8037. }
  8038. close( mixerfd );
  8039. return sysinfo.numaudios;
  8040. }
  8041. RtAudio::DeviceInfo RtApiOss :: getDeviceInfo( unsigned int device )
  8042. {
  8043. RtAudio::DeviceInfo info;
  8044. info.probed = false;
  8045. int mixerfd = open( "/dev/mixer", O_RDWR, 0 );
  8046. if ( mixerfd == -1 ) {
  8047. errorText_ = "RtApiOss::getDeviceInfo: error opening '/dev/mixer'.";
  8048. error( RtAudioError::WARNING );
  8049. return info;
  8050. }
  8051. oss_sysinfo sysinfo;
  8052. int result = ioctl( mixerfd, SNDCTL_SYSINFO, &sysinfo );
  8053. if ( result == -1 ) {
  8054. close( mixerfd );
  8055. errorText_ = "RtApiOss::getDeviceInfo: error getting sysinfo, OSS version >= 4.0 is required.";
  8056. error( RtAudioError::WARNING );
  8057. return info;
  8058. }
  8059. unsigned nDevices = sysinfo.numaudios;
  8060. if ( nDevices == 0 ) {
  8061. close( mixerfd );
  8062. errorText_ = "RtApiOss::getDeviceInfo: no devices found!";
  8063. error( RtAudioError::INVALID_USE );
  8064. return info;
  8065. }
  8066. if ( device >= nDevices ) {
  8067. close( mixerfd );
  8068. errorText_ = "RtApiOss::getDeviceInfo: device ID is invalid!";
  8069. error( RtAudioError::INVALID_USE );
  8070. return info;
  8071. }
  8072. oss_audioinfo ainfo;
  8073. ainfo.dev = device;
  8074. result = ioctl( mixerfd, SNDCTL_AUDIOINFO, &ainfo );
  8075. close( mixerfd );
  8076. if ( result == -1 ) {
  8077. errorStream_ << "RtApiOss::getDeviceInfo: error getting device (" << ainfo.name << ") info.";
  8078. errorText_ = errorStream_.str();
  8079. error( RtAudioError::WARNING );
  8080. return info;
  8081. }
  8082. // Probe channels
  8083. if ( ainfo.caps & PCM_CAP_OUTPUT ) info.outputChannels = ainfo.max_channels;
  8084. if ( ainfo.caps & PCM_CAP_INPUT ) info.inputChannels = ainfo.max_channels;
  8085. if ( ainfo.caps & PCM_CAP_DUPLEX ) {
  8086. if ( info.outputChannels > 0 && info.inputChannels > 0 && ainfo.caps & PCM_CAP_DUPLEX )
  8087. info.duplexChannels = (info.outputChannels > info.inputChannels) ? info.inputChannels : info.outputChannels;
  8088. }
  8089. // Probe data formats ... do for input
  8090. unsigned long mask = ainfo.iformats;
  8091. if ( mask & AFMT_S16_LE || mask & AFMT_S16_BE )
  8092. info.nativeFormats |= RTAUDIO_SINT16;
  8093. if ( mask & AFMT_S8 )
  8094. info.nativeFormats |= RTAUDIO_SINT8;
  8095. if ( mask & AFMT_S32_LE || mask & AFMT_S32_BE )
  8096. info.nativeFormats |= RTAUDIO_SINT32;
  8097. #ifdef AFMT_FLOAT
  8098. if ( mask & AFMT_FLOAT )
  8099. info.nativeFormats |= RTAUDIO_FLOAT32;
  8100. #endif
  8101. if ( mask & AFMT_S24_LE || mask & AFMT_S24_BE )
  8102. info.nativeFormats |= RTAUDIO_SINT24;
  8103. // Check that we have at least one supported format
  8104. if ( info.nativeFormats == 0 ) {
  8105. errorStream_ << "RtApiOss::getDeviceInfo: device (" << ainfo.name << ") data format not supported by RtAudio.";
  8106. errorText_ = errorStream_.str();
  8107. error( RtAudioError::WARNING );
  8108. return info;
  8109. }
  8110. // Probe the supported sample rates.
  8111. info.sampleRates.clear();
  8112. if ( ainfo.nrates ) {
  8113. for ( unsigned int i=0; i<ainfo.nrates; i++ ) {
  8114. for ( unsigned int k=0; k<MAX_SAMPLE_RATES; k++ ) {
  8115. if ( ainfo.rates[i] == SAMPLE_RATES[k] ) {
  8116. info.sampleRates.push_back( SAMPLE_RATES[k] );
  8117. if ( !info.preferredSampleRate || ( SAMPLE_RATES[k] <= 48000 && SAMPLE_RATES[k] > info.preferredSampleRate ) )
  8118. info.preferredSampleRate = SAMPLE_RATES[k];
  8119. break;
  8120. }
  8121. }
  8122. }
  8123. }
  8124. else {
  8125. // Check min and max rate values;
  8126. for ( unsigned int k=0; k<MAX_SAMPLE_RATES; k++ ) {
  8127. if ( ainfo.min_rate <= (int) SAMPLE_RATES[k] && ainfo.max_rate >= (int) SAMPLE_RATES[k] ) {
  8128. info.sampleRates.push_back( SAMPLE_RATES[k] );
  8129. if ( !info.preferredSampleRate || ( SAMPLE_RATES[k] <= 48000 && SAMPLE_RATES[k] > info.preferredSampleRate ) )
  8130. info.preferredSampleRate = SAMPLE_RATES[k];
  8131. }
  8132. }
  8133. }
  8134. if ( info.sampleRates.size() == 0 ) {
  8135. errorStream_ << "RtApiOss::getDeviceInfo: no supported sample rates found for device (" << ainfo.name << ").";
  8136. errorText_ = errorStream_.str();
  8137. error( RtAudioError::WARNING );
  8138. }
  8139. else {
  8140. info.probed = true;
  8141. info.name = ainfo.name;
  8142. }
  8143. return info;
  8144. }
  8145. bool RtApiOss :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels,
  8146. unsigned int firstChannel, unsigned int sampleRate,
  8147. RtAudioFormat format, unsigned int *bufferSize,
  8148. RtAudio::StreamOptions *options )
  8149. {
  8150. int mixerfd = open( "/dev/mixer", O_RDWR, 0 );
  8151. if ( mixerfd == -1 ) {
  8152. errorText_ = "RtApiOss::probeDeviceOpen: error opening '/dev/mixer'.";
  8153. return FAILURE;
  8154. }
  8155. oss_sysinfo sysinfo;
  8156. int result = ioctl( mixerfd, SNDCTL_SYSINFO, &sysinfo );
  8157. if ( result == -1 ) {
  8158. close( mixerfd );
  8159. errorText_ = "RtApiOss::probeDeviceOpen: error getting sysinfo, OSS version >= 4.0 is required.";
  8160. return FAILURE;
  8161. }
  8162. unsigned nDevices = sysinfo.numaudios;
  8163. if ( nDevices == 0 ) {
  8164. // This should not happen because a check is made before this function is called.
  8165. close( mixerfd );
  8166. errorText_ = "RtApiOss::probeDeviceOpen: no devices found!";
  8167. return FAILURE;
  8168. }
  8169. if ( device >= nDevices ) {
  8170. // This should not happen because a check is made before this function is called.
  8171. close( mixerfd );
  8172. errorText_ = "RtApiOss::probeDeviceOpen: device ID is invalid!";
  8173. return FAILURE;
  8174. }
  8175. oss_audioinfo ainfo;
  8176. ainfo.dev = device;
  8177. result = ioctl( mixerfd, SNDCTL_AUDIOINFO, &ainfo );
  8178. close( mixerfd );
  8179. if ( result == -1 ) {
  8180. errorStream_ << "RtApiOss::getDeviceInfo: error getting device (" << ainfo.name << ") info.";
  8181. errorText_ = errorStream_.str();
  8182. return FAILURE;
  8183. }
  8184. // Check if device supports input or output
  8185. if ( ( mode == OUTPUT && !( ainfo.caps & PCM_CAP_OUTPUT ) ) ||
  8186. ( mode == INPUT && !( ainfo.caps & PCM_CAP_INPUT ) ) ) {
  8187. if ( mode == OUTPUT )
  8188. errorStream_ << "RtApiOss::probeDeviceOpen: device (" << ainfo.name << ") does not support output.";
  8189. else
  8190. errorStream_ << "RtApiOss::probeDeviceOpen: device (" << ainfo.name << ") does not support input.";
  8191. errorText_ = errorStream_.str();
  8192. return FAILURE;
  8193. }
  8194. int flags = 0;
  8195. OssHandle *handle = (OssHandle *) stream_.apiHandle;
  8196. if ( mode == OUTPUT )
  8197. flags |= O_WRONLY;
  8198. else { // mode == INPUT
  8199. if (stream_.mode == OUTPUT && stream_.device[0] == device) {
  8200. // We just set the same device for playback ... close and reopen for duplex (OSS only).
  8201. close( handle->id[0] );
  8202. handle->id[0] = 0;
  8203. if ( !( ainfo.caps & PCM_CAP_DUPLEX ) ) {
  8204. errorStream_ << "RtApiOss::probeDeviceOpen: device (" << ainfo.name << ") does not support duplex mode.";
  8205. errorText_ = errorStream_.str();
  8206. return FAILURE;
  8207. }
  8208. // Check that the number previously set channels is the same.
  8209. if ( stream_.nUserChannels[0] != channels ) {
  8210. errorStream_ << "RtApiOss::probeDeviceOpen: input/output channels must be equal for OSS duplex device (" << ainfo.name << ").";
  8211. errorText_ = errorStream_.str();
  8212. return FAILURE;
  8213. }
  8214. flags |= O_RDWR;
  8215. }
  8216. else
  8217. flags |= O_RDONLY;
  8218. }
  8219. // Set exclusive access if specified.
  8220. if ( options && options->flags & RTAUDIO_HOG_DEVICE ) flags |= O_EXCL;
  8221. // Try to open the device.
  8222. int fd;
  8223. fd = open( ainfo.devnode, flags, 0 );
  8224. if ( fd == -1 ) {
  8225. if ( errno == EBUSY )
  8226. errorStream_ << "RtApiOss::probeDeviceOpen: device (" << ainfo.name << ") is busy.";
  8227. else
  8228. errorStream_ << "RtApiOss::probeDeviceOpen: error opening device (" << ainfo.name << ").";
  8229. errorText_ = errorStream_.str();
  8230. return FAILURE;
  8231. }
  8232. // For duplex operation, specifically set this mode (this doesn't seem to work).
  8233. /*
  8234. if ( flags | O_RDWR ) {
  8235. result = ioctl( fd, SNDCTL_DSP_SETDUPLEX, NULL );
  8236. if ( result == -1) {
  8237. errorStream_ << "RtApiOss::probeDeviceOpen: error setting duplex mode for device (" << ainfo.name << ").";
  8238. errorText_ = errorStream_.str();
  8239. return FAILURE;
  8240. }
  8241. }
  8242. */
  8243. // Check the device channel support.
  8244. stream_.nUserChannels[mode] = channels;
  8245. if ( ainfo.max_channels < (int)(channels + firstChannel) ) {
  8246. close( fd );
  8247. errorStream_ << "RtApiOss::probeDeviceOpen: the device (" << ainfo.name << ") does not support requested channel parameters.";
  8248. errorText_ = errorStream_.str();
  8249. return FAILURE;
  8250. }
  8251. // Set the number of channels.
  8252. int deviceChannels = channels + firstChannel;
  8253. result = ioctl( fd, SNDCTL_DSP_CHANNELS, &deviceChannels );
  8254. if ( result == -1 || deviceChannels < (int)(channels + firstChannel) ) {
  8255. close( fd );
  8256. errorStream_ << "RtApiOss::probeDeviceOpen: error setting channel parameters on device (" << ainfo.name << ").";
  8257. errorText_ = errorStream_.str();
  8258. return FAILURE;
  8259. }
  8260. stream_.nDeviceChannels[mode] = deviceChannels;
  8261. // Get the data format mask
  8262. int mask;
  8263. result = ioctl( fd, SNDCTL_DSP_GETFMTS, &mask );
  8264. if ( result == -1 ) {
  8265. close( fd );
  8266. errorStream_ << "RtApiOss::probeDeviceOpen: error getting device (" << ainfo.name << ") data formats.";
  8267. errorText_ = errorStream_.str();
  8268. return FAILURE;
  8269. }
  8270. // Determine how to set the device format.
  8271. stream_.userFormat = format;
  8272. int deviceFormat = -1;
  8273. stream_.doByteSwap[mode] = false;
  8274. if ( format == RTAUDIO_SINT8 ) {
  8275. if ( mask & AFMT_S8 ) {
  8276. deviceFormat = AFMT_S8;
  8277. stream_.deviceFormat[mode] = RTAUDIO_SINT8;
  8278. }
  8279. }
  8280. else if ( format == RTAUDIO_SINT16 ) {
  8281. if ( mask & AFMT_S16_NE ) {
  8282. deviceFormat = AFMT_S16_NE;
  8283. stream_.deviceFormat[mode] = RTAUDIO_SINT16;
  8284. }
  8285. else if ( mask & AFMT_S16_OE ) {
  8286. deviceFormat = AFMT_S16_OE;
  8287. stream_.deviceFormat[mode] = RTAUDIO_SINT16;
  8288. stream_.doByteSwap[mode] = true;
  8289. }
  8290. }
  8291. else if ( format == RTAUDIO_SINT24 ) {
  8292. if ( mask & AFMT_S24_NE ) {
  8293. deviceFormat = AFMT_S24_NE;
  8294. stream_.deviceFormat[mode] = RTAUDIO_SINT24;
  8295. }
  8296. else if ( mask & AFMT_S24_OE ) {
  8297. deviceFormat = AFMT_S24_OE;
  8298. stream_.deviceFormat[mode] = RTAUDIO_SINT24;
  8299. stream_.doByteSwap[mode] = true;
  8300. }
  8301. }
  8302. else if ( format == RTAUDIO_SINT32 ) {
  8303. if ( mask & AFMT_S32_NE ) {
  8304. deviceFormat = AFMT_S32_NE;
  8305. stream_.deviceFormat[mode] = RTAUDIO_SINT32;
  8306. }
  8307. else if ( mask & AFMT_S32_OE ) {
  8308. deviceFormat = AFMT_S32_OE;
  8309. stream_.deviceFormat[mode] = RTAUDIO_SINT32;
  8310. stream_.doByteSwap[mode] = true;
  8311. }
  8312. }
  8313. if ( deviceFormat == -1 ) {
  8314. // The user requested format is not natively supported by the device.
  8315. if ( mask & AFMT_S16_NE ) {
  8316. deviceFormat = AFMT_S16_NE;
  8317. stream_.deviceFormat[mode] = RTAUDIO_SINT16;
  8318. }
  8319. else if ( mask & AFMT_S32_NE ) {
  8320. deviceFormat = AFMT_S32_NE;
  8321. stream_.deviceFormat[mode] = RTAUDIO_SINT32;
  8322. }
  8323. else if ( mask & AFMT_S24_NE ) {
  8324. deviceFormat = AFMT_S24_NE;
  8325. stream_.deviceFormat[mode] = RTAUDIO_SINT24;
  8326. }
  8327. else if ( mask & AFMT_S16_OE ) {
  8328. deviceFormat = AFMT_S16_OE;
  8329. stream_.deviceFormat[mode] = RTAUDIO_SINT16;
  8330. stream_.doByteSwap[mode] = true;
  8331. }
  8332. else if ( mask & AFMT_S32_OE ) {
  8333. deviceFormat = AFMT_S32_OE;
  8334. stream_.deviceFormat[mode] = RTAUDIO_SINT32;
  8335. stream_.doByteSwap[mode] = true;
  8336. }
  8337. else if ( mask & AFMT_S24_OE ) {
  8338. deviceFormat = AFMT_S24_OE;
  8339. stream_.deviceFormat[mode] = RTAUDIO_SINT24;
  8340. stream_.doByteSwap[mode] = true;
  8341. }
  8342. else if ( mask & AFMT_S8) {
  8343. deviceFormat = AFMT_S8;
  8344. stream_.deviceFormat[mode] = RTAUDIO_SINT8;
  8345. }
  8346. }
  8347. if ( stream_.deviceFormat[mode] == 0 ) {
  8348. // This really shouldn't happen ...
  8349. close( fd );
  8350. errorStream_ << "RtApiOss::probeDeviceOpen: device (" << ainfo.name << ") data format not supported by RtAudio.";
  8351. errorText_ = errorStream_.str();
  8352. return FAILURE;
  8353. }
  8354. // Set the data format.
  8355. int temp = deviceFormat;
  8356. result = ioctl( fd, SNDCTL_DSP_SETFMT, &deviceFormat );
  8357. if ( result == -1 || deviceFormat != temp ) {
  8358. close( fd );
  8359. errorStream_ << "RtApiOss::probeDeviceOpen: error setting data format on device (" << ainfo.name << ").";
  8360. errorText_ = errorStream_.str();
  8361. return FAILURE;
  8362. }
  8363. // Attempt to set the buffer size. According to OSS, the minimum
  8364. // number of buffers is two. The supposed minimum buffer size is 16
  8365. // bytes, so that will be our lower bound. The argument to this
  8366. // call is in the form 0xMMMMSSSS (hex), where the buffer size (in
  8367. // bytes) is given as 2^SSSS and the number of buffers as 2^MMMM.
  8368. // We'll check the actual value used near the end of the setup
  8369. // procedure.
  8370. int ossBufferBytes = *bufferSize * formatBytes( stream_.deviceFormat[mode] ) * deviceChannels;
  8371. if ( ossBufferBytes < 16 ) ossBufferBytes = 16;
  8372. int buffers = 0;
  8373. if ( options ) buffers = options->numberOfBuffers;
  8374. if ( options && options->flags & RTAUDIO_MINIMIZE_LATENCY ) buffers = 2;
  8375. if ( buffers < 2 ) buffers = 3;
  8376. temp = ((int) buffers << 16) + (int)( log10( (double)ossBufferBytes ) / log10( 2.0 ) );
  8377. result = ioctl( fd, SNDCTL_DSP_SETFRAGMENT, &temp );
  8378. if ( result == -1 ) {
  8379. close( fd );
  8380. errorStream_ << "RtApiOss::probeDeviceOpen: error setting buffer size on device (" << ainfo.name << ").";
  8381. errorText_ = errorStream_.str();
  8382. return FAILURE;
  8383. }
  8384. stream_.nBuffers = buffers;
  8385. // Save buffer size (in sample frames).
  8386. *bufferSize = ossBufferBytes / ( formatBytes(stream_.deviceFormat[mode]) * deviceChannels );
  8387. stream_.bufferSize = *bufferSize;
  8388. // Set the sample rate.
  8389. int srate = sampleRate;
  8390. result = ioctl( fd, SNDCTL_DSP_SPEED, &srate );
  8391. if ( result == -1 ) {
  8392. close( fd );
  8393. errorStream_ << "RtApiOss::probeDeviceOpen: error setting sample rate (" << sampleRate << ") on device (" << ainfo.name << ").";
  8394. errorText_ = errorStream_.str();
  8395. return FAILURE;
  8396. }
  8397. // Verify the sample rate setup worked.
  8398. if ( abs( srate - (int)sampleRate ) > 100 ) {
  8399. close( fd );
  8400. errorStream_ << "RtApiOss::probeDeviceOpen: device (" << ainfo.name << ") does not support sample rate (" << sampleRate << ").";
  8401. errorText_ = errorStream_.str();
  8402. return FAILURE;
  8403. }
  8404. stream_.sampleRate = sampleRate;
  8405. if ( mode == INPUT && stream_.mode == OUTPUT && stream_.device[0] == device) {
  8406. // We're doing duplex setup here.
  8407. stream_.deviceFormat[0] = stream_.deviceFormat[1];
  8408. stream_.nDeviceChannels[0] = deviceChannels;
  8409. }
  8410. // Set interleaving parameters.
  8411. stream_.userInterleaved = true;
  8412. stream_.deviceInterleaved[mode] = true;
  8413. if ( options && options->flags & RTAUDIO_NONINTERLEAVED )
  8414. stream_.userInterleaved = false;
  8415. // Set flags for buffer conversion
  8416. stream_.doConvertBuffer[mode] = false;
  8417. if ( stream_.userFormat != stream_.deviceFormat[mode] )
  8418. stream_.doConvertBuffer[mode] = true;
  8419. if ( stream_.nUserChannels[mode] < stream_.nDeviceChannels[mode] )
  8420. stream_.doConvertBuffer[mode] = true;
  8421. if ( stream_.userInterleaved != stream_.deviceInterleaved[mode] &&
  8422. stream_.nUserChannels[mode] > 1 )
  8423. stream_.doConvertBuffer[mode] = true;
  8424. // Allocate the stream handles if necessary and then save.
  8425. if ( stream_.apiHandle == 0 ) {
  8426. try {
  8427. handle = new OssHandle;
  8428. }
  8429. catch ( std::bad_alloc& ) {
  8430. errorText_ = "RtApiOss::probeDeviceOpen: error allocating OssHandle memory.";
  8431. goto error;
  8432. }
  8433. if ( pthread_cond_init( &handle->runnable, NULL ) ) {
  8434. errorText_ = "RtApiOss::probeDeviceOpen: error initializing pthread condition variable.";
  8435. goto error;
  8436. }
  8437. stream_.apiHandle = (void *) handle;
  8438. }
  8439. else {
  8440. handle = (OssHandle *) stream_.apiHandle;
  8441. }
  8442. handle->id[mode] = fd;
  8443. // Allocate necessary internal buffers.
  8444. unsigned long bufferBytes;
  8445. bufferBytes = stream_.nUserChannels[mode] * *bufferSize * formatBytes( stream_.userFormat );
  8446. stream_.userBuffer[mode] = (char *) calloc( bufferBytes, 1 );
  8447. if ( stream_.userBuffer[mode] == NULL ) {
  8448. errorText_ = "RtApiOss::probeDeviceOpen: error allocating user buffer memory.";
  8449. goto error;
  8450. }
  8451. if ( stream_.doConvertBuffer[mode] ) {
  8452. bool makeBuffer = true;
  8453. bufferBytes = stream_.nDeviceChannels[mode] * formatBytes( stream_.deviceFormat[mode] );
  8454. if ( mode == INPUT ) {
  8455. if ( stream_.mode == OUTPUT && stream_.deviceBuffer ) {
  8456. unsigned long bytesOut = stream_.nDeviceChannels[0] * formatBytes( stream_.deviceFormat[0] );
  8457. if ( bufferBytes <= bytesOut ) makeBuffer = false;
  8458. }
  8459. }
  8460. if ( makeBuffer ) {
  8461. bufferBytes *= *bufferSize;
  8462. if ( stream_.deviceBuffer ) free( stream_.deviceBuffer );
  8463. stream_.deviceBuffer = (char *) calloc( bufferBytes, 1 );
  8464. if ( stream_.deviceBuffer == NULL ) {
  8465. errorText_ = "RtApiOss::probeDeviceOpen: error allocating device buffer memory.";
  8466. goto error;
  8467. }
  8468. }
  8469. }
  8470. stream_.device[mode] = device;
  8471. stream_.state = STREAM_STOPPED;
  8472. // Setup the buffer conversion information structure.
  8473. if ( stream_.doConvertBuffer[mode] ) setConvertInfo( mode, firstChannel );
  8474. // Setup thread if necessary.
  8475. if ( stream_.mode == OUTPUT && mode == INPUT ) {
  8476. // We had already set up an output stream.
  8477. stream_.mode = DUPLEX;
  8478. if ( stream_.device[0] == device ) handle->id[0] = fd;
  8479. }
  8480. else {
  8481. stream_.mode = mode;
  8482. // Setup callback thread.
  8483. stream_.callbackInfo.object = (void *) this;
  8484. // Set the thread attributes for joinable and realtime scheduling
  8485. // priority. The higher priority will only take affect if the
  8486. // program is run as root or suid.
  8487. pthread_attr_t attr;
  8488. pthread_attr_init( &attr );
  8489. pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_JOINABLE );
  8490. #ifdef SCHED_RR // Undefined with some OSes (e.g. NetBSD 1.6.x with GNU Pthread)
  8491. if ( options && options->flags & RTAUDIO_SCHEDULE_REALTIME ) {
  8492. stream_.callbackInfo.doRealtime = true;
  8493. struct sched_param param;
  8494. int priority = options->priority;
  8495. int min = sched_get_priority_min( SCHED_RR );
  8496. int max = sched_get_priority_max( SCHED_RR );
  8497. if ( priority < min ) priority = min;
  8498. else if ( priority > max ) priority = max;
  8499. param.sched_priority = priority;
  8500. // Set the policy BEFORE the priority. Otherwise it fails.
  8501. pthread_attr_setschedpolicy(&attr, SCHED_RR);
  8502. pthread_attr_setscope (&attr, PTHREAD_SCOPE_SYSTEM);
  8503. // This is definitely required. Otherwise it fails.
  8504. pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
  8505. pthread_attr_setschedparam(&attr, &param);
  8506. }
  8507. else
  8508. pthread_attr_setschedpolicy( &attr, SCHED_OTHER );
  8509. #else
  8510. pthread_attr_setschedpolicy( &attr, SCHED_OTHER );
  8511. #endif
  8512. stream_.callbackInfo.isRunning = true;
  8513. result = pthread_create( &stream_.callbackInfo.thread, &attr, ossCallbackHandler, &stream_.callbackInfo );
  8514. pthread_attr_destroy( &attr );
  8515. if ( result ) {
  8516. // Failed. Try instead with default attributes.
  8517. result = pthread_create( &stream_.callbackInfo.thread, NULL, ossCallbackHandler, &stream_.callbackInfo );
  8518. if ( result ) {
  8519. stream_.callbackInfo.isRunning = false;
  8520. errorText_ = "RtApiOss::error creating callback thread!";
  8521. goto error;
  8522. }
  8523. }
  8524. }
  8525. return SUCCESS;
  8526. error:
  8527. if ( handle ) {
  8528. pthread_cond_destroy( &handle->runnable );
  8529. if ( handle->id[0] ) close( handle->id[0] );
  8530. if ( handle->id[1] ) close( handle->id[1] );
  8531. delete handle;
  8532. stream_.apiHandle = 0;
  8533. }
  8534. for ( int i=0; i<2; i++ ) {
  8535. if ( stream_.userBuffer[i] ) {
  8536. free( stream_.userBuffer[i] );
  8537. stream_.userBuffer[i] = 0;
  8538. }
  8539. }
  8540. if ( stream_.deviceBuffer ) {
  8541. free( stream_.deviceBuffer );
  8542. stream_.deviceBuffer = 0;
  8543. }
  8544. stream_.state = STREAM_CLOSED;
  8545. return FAILURE;
  8546. }
  8547. void RtApiOss :: closeStream()
  8548. {
  8549. if ( stream_.state == STREAM_CLOSED ) {
  8550. errorText_ = "RtApiOss::closeStream(): no open stream to close!";
  8551. error( RtAudioError::WARNING );
  8552. return;
  8553. }
  8554. OssHandle *handle = (OssHandle *) stream_.apiHandle;
  8555. stream_.callbackInfo.isRunning = false;
  8556. MUTEX_LOCK( &stream_.mutex );
  8557. if ( stream_.state == STREAM_STOPPED )
  8558. pthread_cond_signal( &handle->runnable );
  8559. MUTEX_UNLOCK( &stream_.mutex );
  8560. pthread_join( stream_.callbackInfo.thread, NULL );
  8561. if ( stream_.state == STREAM_RUNNING ) {
  8562. if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX )
  8563. ioctl( handle->id[0], SNDCTL_DSP_HALT, 0 );
  8564. else
  8565. ioctl( handle->id[1], SNDCTL_DSP_HALT, 0 );
  8566. stream_.state = STREAM_STOPPED;
  8567. }
  8568. if ( handle ) {
  8569. pthread_cond_destroy( &handle->runnable );
  8570. if ( handle->id[0] ) close( handle->id[0] );
  8571. if ( handle->id[1] ) close( handle->id[1] );
  8572. delete handle;
  8573. stream_.apiHandle = 0;
  8574. }
  8575. for ( int i=0; i<2; i++ ) {
  8576. if ( stream_.userBuffer[i] ) {
  8577. free( stream_.userBuffer[i] );
  8578. stream_.userBuffer[i] = 0;
  8579. }
  8580. }
  8581. if ( stream_.deviceBuffer ) {
  8582. free( stream_.deviceBuffer );
  8583. stream_.deviceBuffer = 0;
  8584. }
  8585. stream_.mode = UNINITIALIZED;
  8586. stream_.state = STREAM_CLOSED;
  8587. }
  8588. void RtApiOss :: startStream()
  8589. {
  8590. verifyStream();
  8591. if ( stream_.state == STREAM_RUNNING ) {
  8592. errorText_ = "RtApiOss::startStream(): the stream is already running!";
  8593. error( RtAudioError::WARNING );
  8594. return;
  8595. }
  8596. MUTEX_LOCK( &stream_.mutex );
  8597. #if defined( HAVE_GETTIMEOFDAY )
  8598. gettimeofday( &stream_.lastTickTimestamp, NULL );
  8599. #endif
  8600. stream_.state = STREAM_RUNNING;
  8601. // No need to do anything else here ... OSS automatically starts
  8602. // when fed samples.
  8603. MUTEX_UNLOCK( &stream_.mutex );
  8604. OssHandle *handle = (OssHandle *) stream_.apiHandle;
  8605. pthread_cond_signal( &handle->runnable );
  8606. }
  8607. void RtApiOss :: stopStream()
  8608. {
  8609. verifyStream();
  8610. if ( stream_.state == STREAM_STOPPED ) {
  8611. errorText_ = "RtApiOss::stopStream(): the stream is already stopped!";
  8612. error( RtAudioError::WARNING );
  8613. return;
  8614. }
  8615. MUTEX_LOCK( &stream_.mutex );
  8616. // The state might change while waiting on a mutex.
  8617. if ( stream_.state == STREAM_STOPPED ) {
  8618. MUTEX_UNLOCK( &stream_.mutex );
  8619. return;
  8620. }
  8621. int result = 0;
  8622. OssHandle *handle = (OssHandle *) stream_.apiHandle;
  8623. if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) {
  8624. // Flush the output with zeros a few times.
  8625. char *buffer;
  8626. int samples;
  8627. RtAudioFormat format;
  8628. if ( stream_.doConvertBuffer[0] ) {
  8629. buffer = stream_.deviceBuffer;
  8630. samples = stream_.bufferSize * stream_.nDeviceChannels[0];
  8631. format = stream_.deviceFormat[0];
  8632. }
  8633. else {
  8634. buffer = stream_.userBuffer[0];
  8635. samples = stream_.bufferSize * stream_.nUserChannels[0];
  8636. format = stream_.userFormat;
  8637. }
  8638. memset( buffer, 0, samples * formatBytes(format) );
  8639. for ( unsigned int i=0; i<stream_.nBuffers+1; i++ ) {
  8640. result = write( handle->id[0], buffer, samples * formatBytes(format) );
  8641. if ( result == -1 ) {
  8642. errorText_ = "RtApiOss::stopStream: audio write error.";
  8643. error( RtAudioError::WARNING );
  8644. }
  8645. }
  8646. result = ioctl( handle->id[0], SNDCTL_DSP_HALT, 0 );
  8647. if ( result == -1 ) {
  8648. errorStream_ << "RtApiOss::stopStream: system error stopping callback procedure on device (" << stream_.device[0] << ").";
  8649. errorText_ = errorStream_.str();
  8650. goto unlock;
  8651. }
  8652. handle->triggered = false;
  8653. }
  8654. if ( stream_.mode == INPUT || ( stream_.mode == DUPLEX && handle->id[0] != handle->id[1] ) ) {
  8655. result = ioctl( handle->id[1], SNDCTL_DSP_HALT, 0 );
  8656. if ( result == -1 ) {
  8657. errorStream_ << "RtApiOss::stopStream: system error stopping input callback procedure on device (" << stream_.device[0] << ").";
  8658. errorText_ = errorStream_.str();
  8659. goto unlock;
  8660. }
  8661. }
  8662. unlock:
  8663. stream_.state = STREAM_STOPPED;
  8664. MUTEX_UNLOCK( &stream_.mutex );
  8665. if ( result != -1 ) return;
  8666. error( RtAudioError::SYSTEM_ERROR );
  8667. }
  8668. void RtApiOss :: abortStream()
  8669. {
  8670. verifyStream();
  8671. if ( stream_.state == STREAM_STOPPED ) {
  8672. errorText_ = "RtApiOss::abortStream(): the stream is already stopped!";
  8673. error( RtAudioError::WARNING );
  8674. return;
  8675. }
  8676. MUTEX_LOCK( &stream_.mutex );
  8677. // The state might change while waiting on a mutex.
  8678. if ( stream_.state == STREAM_STOPPED ) {
  8679. MUTEX_UNLOCK( &stream_.mutex );
  8680. return;
  8681. }
  8682. int result = 0;
  8683. OssHandle *handle = (OssHandle *) stream_.apiHandle;
  8684. if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) {
  8685. result = ioctl( handle->id[0], SNDCTL_DSP_HALT, 0 );
  8686. if ( result == -1 ) {
  8687. errorStream_ << "RtApiOss::abortStream: system error stopping callback procedure on device (" << stream_.device[0] << ").";
  8688. errorText_ = errorStream_.str();
  8689. goto unlock;
  8690. }
  8691. handle->triggered = false;
  8692. }
  8693. if ( stream_.mode == INPUT || ( stream_.mode == DUPLEX && handle->id[0] != handle->id[1] ) ) {
  8694. result = ioctl( handle->id[1], SNDCTL_DSP_HALT, 0 );
  8695. if ( result == -1 ) {
  8696. errorStream_ << "RtApiOss::abortStream: system error stopping input callback procedure on device (" << stream_.device[0] << ").";
  8697. errorText_ = errorStream_.str();
  8698. goto unlock;
  8699. }
  8700. }
  8701. unlock:
  8702. stream_.state = STREAM_STOPPED;
  8703. MUTEX_UNLOCK( &stream_.mutex );
  8704. if ( result != -1 ) return;
  8705. error( RtAudioError::SYSTEM_ERROR );
  8706. }
  8707. void RtApiOss :: callbackEvent()
  8708. {
  8709. OssHandle *handle = (OssHandle *) stream_.apiHandle;
  8710. if ( stream_.state == STREAM_STOPPED ) {
  8711. MUTEX_LOCK( &stream_.mutex );
  8712. pthread_cond_wait( &handle->runnable, &stream_.mutex );
  8713. if ( stream_.state != STREAM_RUNNING ) {
  8714. MUTEX_UNLOCK( &stream_.mutex );
  8715. return;
  8716. }
  8717. MUTEX_UNLOCK( &stream_.mutex );
  8718. }
  8719. if ( stream_.state == STREAM_CLOSED ) {
  8720. errorText_ = "RtApiOss::callbackEvent(): the stream is closed ... this shouldn't happen!";
  8721. error( RtAudioError::WARNING );
  8722. return;
  8723. }
  8724. // Invoke user callback to get fresh output data.
  8725. int doStopStream = 0;
  8726. RtAudioCallback callback = (RtAudioCallback) stream_.callbackInfo.callback;
  8727. double streamTime = getStreamTime();
  8728. RtAudioStreamStatus status = 0;
  8729. if ( stream_.mode != INPUT && handle->xrun[0] == true ) {
  8730. status |= RTAUDIO_OUTPUT_UNDERFLOW;
  8731. handle->xrun[0] = false;
  8732. }
  8733. if ( stream_.mode != OUTPUT && handle->xrun[1] == true ) {
  8734. status |= RTAUDIO_INPUT_OVERFLOW;
  8735. handle->xrun[1] = false;
  8736. }
  8737. doStopStream = callback( stream_.userBuffer[0], stream_.userBuffer[1],
  8738. stream_.bufferSize, streamTime, status, stream_.callbackInfo.userData );
  8739. if ( doStopStream == 2 ) {
  8740. this->abortStream();
  8741. return;
  8742. }
  8743. MUTEX_LOCK( &stream_.mutex );
  8744. // The state might change while waiting on a mutex.
  8745. if ( stream_.state == STREAM_STOPPED ) goto unlock;
  8746. int result;
  8747. char *buffer;
  8748. int samples;
  8749. RtAudioFormat format;
  8750. if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) {
  8751. // Setup parameters and do buffer conversion if necessary.
  8752. if ( stream_.doConvertBuffer[0] ) {
  8753. buffer = stream_.deviceBuffer;
  8754. convertBuffer( buffer, stream_.userBuffer[0], stream_.convertInfo[0] );
  8755. samples = stream_.bufferSize * stream_.nDeviceChannels[0];
  8756. format = stream_.deviceFormat[0];
  8757. }
  8758. else {
  8759. buffer = stream_.userBuffer[0];
  8760. samples = stream_.bufferSize * stream_.nUserChannels[0];
  8761. format = stream_.userFormat;
  8762. }
  8763. // Do byte swapping if necessary.
  8764. if ( stream_.doByteSwap[0] )
  8765. byteSwapBuffer( buffer, samples, format );
  8766. if ( stream_.mode == DUPLEX && handle->triggered == false ) {
  8767. int trig = 0;
  8768. ioctl( handle->id[0], SNDCTL_DSP_SETTRIGGER, &trig );
  8769. result = write( handle->id[0], buffer, samples * formatBytes(format) );
  8770. trig = PCM_ENABLE_INPUT|PCM_ENABLE_OUTPUT;
  8771. ioctl( handle->id[0], SNDCTL_DSP_SETTRIGGER, &trig );
  8772. handle->triggered = true;
  8773. }
  8774. else
  8775. // Write samples to device.
  8776. result = write( handle->id[0], buffer, samples * formatBytes(format) );
  8777. if ( result == -1 ) {
  8778. // We'll assume this is an underrun, though there isn't a
  8779. // specific means for determining that.
  8780. handle->xrun[0] = true;
  8781. errorText_ = "RtApiOss::callbackEvent: audio write error.";
  8782. error( RtAudioError::WARNING );
  8783. // Continue on to input section.
  8784. }
  8785. }
  8786. if ( stream_.mode == INPUT || stream_.mode == DUPLEX ) {
  8787. // Setup parameters.
  8788. if ( stream_.doConvertBuffer[1] ) {
  8789. buffer = stream_.deviceBuffer;
  8790. samples = stream_.bufferSize * stream_.nDeviceChannels[1];
  8791. format = stream_.deviceFormat[1];
  8792. }
  8793. else {
  8794. buffer = stream_.userBuffer[1];
  8795. samples = stream_.bufferSize * stream_.nUserChannels[1];
  8796. format = stream_.userFormat;
  8797. }
  8798. // Read samples from device.
  8799. result = read( handle->id[1], buffer, samples * formatBytes(format) );
  8800. if ( result == -1 ) {
  8801. // We'll assume this is an overrun, though there isn't a
  8802. // specific means for determining that.
  8803. handle->xrun[1] = true;
  8804. errorText_ = "RtApiOss::callbackEvent: audio read error.";
  8805. error( RtAudioError::WARNING );
  8806. goto unlock;
  8807. }
  8808. // Do byte swapping if necessary.
  8809. if ( stream_.doByteSwap[1] )
  8810. byteSwapBuffer( buffer, samples, format );
  8811. // Do buffer conversion if necessary.
  8812. if ( stream_.doConvertBuffer[1] )
  8813. convertBuffer( stream_.userBuffer[1], stream_.deviceBuffer, stream_.convertInfo[1] );
  8814. }
  8815. unlock:
  8816. MUTEX_UNLOCK( &stream_.mutex );
  8817. RtApi::tickStreamTime();
  8818. if ( doStopStream == 1 ) this->stopStream();
  8819. }
  8820. static void *ossCallbackHandler( void *ptr )
  8821. {
  8822. CallbackInfo *info = (CallbackInfo *) ptr;
  8823. RtApiOss *object = (RtApiOss *) info->object;
  8824. bool *isRunning = &info->isRunning;
  8825. #ifdef SCHED_RR // Undefined with some OSes (e.g. NetBSD 1.6.x with GNU Pthread)
  8826. if (info->doRealtime) {
  8827. std::cerr << "RtAudio oss: " <<
  8828. (sched_getscheduler(0) == SCHED_RR ? "" : "_NOT_ ") <<
  8829. "running realtime scheduling" << std::endl;
  8830. }
  8831. #endif
  8832. while ( *isRunning == true ) {
  8833. pthread_testcancel();
  8834. object->callbackEvent();
  8835. }
  8836. pthread_exit( NULL );
  8837. }
  8838. //******************** End of __LINUX_OSS__ *********************//
  8839. #endif
  8840. // *************************************************** //
  8841. //
  8842. // Protected common (OS-independent) RtAudio methods.
  8843. //
  8844. // *************************************************** //
  8845. // This method can be modified to control the behavior of error
  8846. // message printing.
  8847. void RtApi :: error( RtAudioError::Type type )
  8848. {
  8849. errorStream_.str(""); // clear the ostringstream
  8850. RtAudioErrorCallback errorCallback = (RtAudioErrorCallback) stream_.callbackInfo.errorCallback;
  8851. if ( errorCallback ) {
  8852. // abortStream() can generate new error messages. Ignore them. Just keep original one.
  8853. if ( firstErrorOccurred_ )
  8854. return;
  8855. firstErrorOccurred_ = true;
  8856. const std::string errorMessage = errorText_;
  8857. if ( type != RtAudioError::WARNING && stream_.state != STREAM_STOPPED) {
  8858. stream_.callbackInfo.isRunning = false; // exit from the thread
  8859. abortStream();
  8860. }
  8861. errorCallback( type, errorMessage );
  8862. firstErrorOccurred_ = false;
  8863. return;
  8864. }
  8865. if ( type == RtAudioError::WARNING && showWarnings_ == true )
  8866. std::cerr << '\n' << errorText_ << "\n\n";
  8867. else if ( type != RtAudioError::WARNING )
  8868. throw( RtAudioError( errorText_, type ) );
  8869. }
  8870. void RtApi :: verifyStream()
  8871. {
  8872. if ( stream_.state == STREAM_CLOSED ) {
  8873. errorText_ = "RtApi:: a stream is not open!";
  8874. error( RtAudioError::INVALID_USE );
  8875. }
  8876. }
  8877. void RtApi :: clearStreamInfo()
  8878. {
  8879. stream_.mode = UNINITIALIZED;
  8880. stream_.state = STREAM_CLOSED;
  8881. stream_.sampleRate = 0;
  8882. stream_.bufferSize = 0;
  8883. stream_.nBuffers = 0;
  8884. stream_.userFormat = 0;
  8885. stream_.userInterleaved = true;
  8886. stream_.streamTime = 0.0;
  8887. stream_.apiHandle = 0;
  8888. stream_.deviceBuffer = 0;
  8889. stream_.callbackInfo.callback = 0;
  8890. stream_.callbackInfo.userData = 0;
  8891. stream_.callbackInfo.isRunning = false;
  8892. stream_.callbackInfo.errorCallback = 0;
  8893. for ( int i=0; i<2; i++ ) {
  8894. stream_.device[i] = 11111;
  8895. stream_.doConvertBuffer[i] = false;
  8896. stream_.deviceInterleaved[i] = true;
  8897. stream_.doByteSwap[i] = false;
  8898. stream_.nUserChannels[i] = 0;
  8899. stream_.nDeviceChannels[i] = 0;
  8900. stream_.channelOffset[i] = 0;
  8901. stream_.deviceFormat[i] = 0;
  8902. stream_.latency[i] = 0;
  8903. stream_.userBuffer[i] = 0;
  8904. stream_.convertInfo[i].channels = 0;
  8905. stream_.convertInfo[i].inJump = 0;
  8906. stream_.convertInfo[i].outJump = 0;
  8907. stream_.convertInfo[i].inFormat = 0;
  8908. stream_.convertInfo[i].outFormat = 0;
  8909. stream_.convertInfo[i].inOffset.clear();
  8910. stream_.convertInfo[i].outOffset.clear();
  8911. }
  8912. }
  8913. unsigned int RtApi :: formatBytes( RtAudioFormat format )
  8914. {
  8915. if ( format == RTAUDIO_SINT16 )
  8916. return 2;
  8917. else if ( format == RTAUDIO_SINT32 || format == RTAUDIO_FLOAT32 )
  8918. return 4;
  8919. else if ( format == RTAUDIO_FLOAT64 )
  8920. return 8;
  8921. else if ( format == RTAUDIO_SINT24 )
  8922. return 3;
  8923. else if ( format == RTAUDIO_SINT8 )
  8924. return 1;
  8925. errorText_ = "RtApi::formatBytes: undefined format.";
  8926. error( RtAudioError::WARNING );
  8927. return 0;
  8928. }
  8929. void RtApi :: setConvertInfo( StreamMode mode, unsigned int firstChannel )
  8930. {
  8931. if ( mode == INPUT ) { // convert device to user buffer
  8932. stream_.convertInfo[mode].inJump = stream_.nDeviceChannels[1];
  8933. stream_.convertInfo[mode].outJump = stream_.nUserChannels[1];
  8934. stream_.convertInfo[mode].inFormat = stream_.deviceFormat[1];
  8935. stream_.convertInfo[mode].outFormat = stream_.userFormat;
  8936. }
  8937. else { // convert user to device buffer
  8938. stream_.convertInfo[mode].inJump = stream_.nUserChannels[0];
  8939. stream_.convertInfo[mode].outJump = stream_.nDeviceChannels[0];
  8940. stream_.convertInfo[mode].inFormat = stream_.userFormat;
  8941. stream_.convertInfo[mode].outFormat = stream_.deviceFormat[0];
  8942. }
  8943. if ( stream_.convertInfo[mode].inJump < stream_.convertInfo[mode].outJump )
  8944. stream_.convertInfo[mode].channels = stream_.convertInfo[mode].inJump;
  8945. else
  8946. stream_.convertInfo[mode].channels = stream_.convertInfo[mode].outJump;
  8947. // Set up the interleave/deinterleave offsets.
  8948. if ( stream_.deviceInterleaved[mode] != stream_.userInterleaved ) {
  8949. if ( ( mode == OUTPUT && stream_.deviceInterleaved[mode] ) ||
  8950. ( mode == INPUT && stream_.userInterleaved ) ) {
  8951. for ( int k=0; k<stream_.convertInfo[mode].channels; k++ ) {
  8952. stream_.convertInfo[mode].inOffset.push_back( k * stream_.bufferSize );
  8953. stream_.convertInfo[mode].outOffset.push_back( k );
  8954. stream_.convertInfo[mode].inJump = 1;
  8955. }
  8956. }
  8957. else {
  8958. for ( int k=0; k<stream_.convertInfo[mode].channels; k++ ) {
  8959. stream_.convertInfo[mode].inOffset.push_back( k );
  8960. stream_.convertInfo[mode].outOffset.push_back( k * stream_.bufferSize );
  8961. stream_.convertInfo[mode].outJump = 1;
  8962. }
  8963. }
  8964. }
  8965. else { // no (de)interleaving
  8966. if ( stream_.userInterleaved ) {
  8967. for ( int k=0; k<stream_.convertInfo[mode].channels; k++ ) {
  8968. stream_.convertInfo[mode].inOffset.push_back( k );
  8969. stream_.convertInfo[mode].outOffset.push_back( k );
  8970. }
  8971. }
  8972. else {
  8973. for ( int k=0; k<stream_.convertInfo[mode].channels; k++ ) {
  8974. stream_.convertInfo[mode].inOffset.push_back( k * stream_.bufferSize );
  8975. stream_.convertInfo[mode].outOffset.push_back( k * stream_.bufferSize );
  8976. stream_.convertInfo[mode].inJump = 1;
  8977. stream_.convertInfo[mode].outJump = 1;
  8978. }
  8979. }
  8980. }
  8981. // Add channel offset.
  8982. if ( firstChannel > 0 ) {
  8983. if ( stream_.deviceInterleaved[mode] ) {
  8984. if ( mode == OUTPUT ) {
  8985. for ( int k=0; k<stream_.convertInfo[mode].channels; k++ )
  8986. stream_.convertInfo[mode].outOffset[k] += firstChannel;
  8987. }
  8988. else {
  8989. for ( int k=0; k<stream_.convertInfo[mode].channels; k++ )
  8990. stream_.convertInfo[mode].inOffset[k] += firstChannel;
  8991. }
  8992. }
  8993. else {
  8994. if ( mode == OUTPUT ) {
  8995. for ( int k=0; k<stream_.convertInfo[mode].channels; k++ )
  8996. stream_.convertInfo[mode].outOffset[k] += ( firstChannel * stream_.bufferSize );
  8997. }
  8998. else {
  8999. for ( int k=0; k<stream_.convertInfo[mode].channels; k++ )
  9000. stream_.convertInfo[mode].inOffset[k] += ( firstChannel * stream_.bufferSize );
  9001. }
  9002. }
  9003. }
  9004. }
  9005. void RtApi :: convertBuffer( char *outBuffer, char *inBuffer, ConvertInfo &info )
  9006. {
  9007. // This function does format conversion, input/output channel compensation, and
  9008. // data interleaving/deinterleaving. 24-bit integers are assumed to occupy
  9009. // the lower three bytes of a 32-bit integer.
  9010. // Clear our duplex device output buffer if there are more device outputs than user outputs
  9011. if ( outBuffer == stream_.deviceBuffer && stream_.mode == DUPLEX && info.outJump > info.inJump )
  9012. memset( outBuffer, 0, stream_.bufferSize * info.outJump * formatBytes( info.outFormat ) );
  9013. int j;
  9014. if (info.outFormat == RTAUDIO_FLOAT64) {
  9015. Float64 *out = (Float64 *)outBuffer;
  9016. if (info.inFormat == RTAUDIO_SINT8) {
  9017. signed char *in = (signed char *)inBuffer;
  9018. for (unsigned int i=0; i<stream_.bufferSize; i++) {
  9019. for (j=0; j<info.channels; j++) {
  9020. out[info.outOffset[j]] = (Float64) in[info.inOffset[j]] / 128.0;
  9021. }
  9022. in += info.inJump;
  9023. out += info.outJump;
  9024. }
  9025. }
  9026. else if (info.inFormat == RTAUDIO_SINT16) {
  9027. Int16 *in = (Int16 *)inBuffer;
  9028. for (unsigned int i=0; i<stream_.bufferSize; i++) {
  9029. for (j=0; j<info.channels; j++) {
  9030. out[info.outOffset[j]] = (Float64) in[info.inOffset[j]] / 32768.0;
  9031. }
  9032. in += info.inJump;
  9033. out += info.outJump;
  9034. }
  9035. }
  9036. else if (info.inFormat == RTAUDIO_SINT24) {
  9037. Int24 *in = (Int24 *)inBuffer;
  9038. for (unsigned int i=0; i<stream_.bufferSize; i++) {
  9039. for (j=0; j<info.channels; j++) {
  9040. out[info.outOffset[j]] = (Float64) in[info.inOffset[j]].asInt() / 8388608.0;
  9041. }
  9042. in += info.inJump;
  9043. out += info.outJump;
  9044. }
  9045. }
  9046. else if (info.inFormat == RTAUDIO_SINT32) {
  9047. Int32 *in = (Int32 *)inBuffer;
  9048. for (unsigned int i=0; i<stream_.bufferSize; i++) {
  9049. for (j=0; j<info.channels; j++) {
  9050. out[info.outOffset[j]] = (Float64) in[info.inOffset[j]] / 2147483648.0;
  9051. }
  9052. in += info.inJump;
  9053. out += info.outJump;
  9054. }
  9055. }
  9056. else if (info.inFormat == RTAUDIO_FLOAT32) {
  9057. Float32 *in = (Float32 *)inBuffer;
  9058. for (unsigned int i=0; i<stream_.bufferSize; i++) {
  9059. for (j=0; j<info.channels; j++) {
  9060. out[info.outOffset[j]] = (Float64) in[info.inOffset[j]];
  9061. }
  9062. in += info.inJump;
  9063. out += info.outJump;
  9064. }
  9065. }
  9066. else if (info.inFormat == RTAUDIO_FLOAT64) {
  9067. // Channel compensation and/or (de)interleaving only.
  9068. Float64 *in = (Float64 *)inBuffer;
  9069. for (unsigned int i=0; i<stream_.bufferSize; i++) {
  9070. for (j=0; j<info.channels; j++) {
  9071. out[info.outOffset[j]] = in[info.inOffset[j]];
  9072. }
  9073. in += info.inJump;
  9074. out += info.outJump;
  9075. }
  9076. }
  9077. }
  9078. else if (info.outFormat == RTAUDIO_FLOAT32) {
  9079. Float32 *out = (Float32 *)outBuffer;
  9080. if (info.inFormat == RTAUDIO_SINT8) {
  9081. signed char *in = (signed char *)inBuffer;
  9082. for (unsigned int i=0; i<stream_.bufferSize; i++) {
  9083. for (j=0; j<info.channels; j++) {
  9084. out[info.outOffset[j]] = (Float32) in[info.inOffset[j]] / 128.f;
  9085. }
  9086. in += info.inJump;
  9087. out += info.outJump;
  9088. }
  9089. }
  9090. else if (info.inFormat == RTAUDIO_SINT16) {
  9091. Int16 *in = (Int16 *)inBuffer;
  9092. for (unsigned int i=0; i<stream_.bufferSize; i++) {
  9093. for (j=0; j<info.channels; j++) {
  9094. out[info.outOffset[j]] = (Float32) in[info.inOffset[j]] / 32768.f;
  9095. }
  9096. in += info.inJump;
  9097. out += info.outJump;
  9098. }
  9099. }
  9100. else if (info.inFormat == RTAUDIO_SINT24) {
  9101. Int24 *in = (Int24 *)inBuffer;
  9102. for (unsigned int i=0; i<stream_.bufferSize; i++) {
  9103. for (j=0; j<info.channels; j++) {
  9104. out[info.outOffset[j]] = (Float32) in[info.inOffset[j]].asInt() / 8388608.f;
  9105. }
  9106. in += info.inJump;
  9107. out += info.outJump;
  9108. }
  9109. }
  9110. else if (info.inFormat == RTAUDIO_SINT32) {
  9111. Int32 *in = (Int32 *)inBuffer;
  9112. for (unsigned int i=0; i<stream_.bufferSize; i++) {
  9113. for (j=0; j<info.channels; j++) {
  9114. out[info.outOffset[j]] = (Float32) in[info.inOffset[j]] / 2147483648.f;
  9115. }
  9116. in += info.inJump;
  9117. out += info.outJump;
  9118. }
  9119. }
  9120. else if (info.inFormat == RTAUDIO_FLOAT32) {
  9121. // Channel compensation and/or (de)interleaving only.
  9122. Float32 *in = (Float32 *)inBuffer;
  9123. for (unsigned int i=0; i<stream_.bufferSize; i++) {
  9124. for (j=0; j<info.channels; j++) {
  9125. out[info.outOffset[j]] = in[info.inOffset[j]];
  9126. }
  9127. in += info.inJump;
  9128. out += info.outJump;
  9129. }
  9130. }
  9131. else if (info.inFormat == RTAUDIO_FLOAT64) {
  9132. Float64 *in = (Float64 *)inBuffer;
  9133. for (unsigned int i=0; i<stream_.bufferSize; i++) {
  9134. for (j=0; j<info.channels; j++) {
  9135. out[info.outOffset[j]] = (Float32) in[info.inOffset[j]];
  9136. }
  9137. in += info.inJump;
  9138. out += info.outJump;
  9139. }
  9140. }
  9141. }
  9142. else if (info.outFormat == RTAUDIO_SINT32) {
  9143. Int32 *out = (Int32 *)outBuffer;
  9144. if (info.inFormat == RTAUDIO_SINT8) {
  9145. signed char *in = (signed char *)inBuffer;
  9146. for (unsigned int i=0; i<stream_.bufferSize; i++) {
  9147. for (j=0; j<info.channels; j++) {
  9148. out[info.outOffset[j]] = (Int32) in[info.inOffset[j]];
  9149. out[info.outOffset[j]] <<= 24;
  9150. }
  9151. in += info.inJump;
  9152. out += info.outJump;
  9153. }
  9154. }
  9155. else if (info.inFormat == RTAUDIO_SINT16) {
  9156. Int16 *in = (Int16 *)inBuffer;
  9157. for (unsigned int i=0; i<stream_.bufferSize; i++) {
  9158. for (j=0; j<info.channels; j++) {
  9159. out[info.outOffset[j]] = (Int32) in[info.inOffset[j]];
  9160. out[info.outOffset[j]] <<= 16;
  9161. }
  9162. in += info.inJump;
  9163. out += info.outJump;
  9164. }
  9165. }
  9166. else if (info.inFormat == RTAUDIO_SINT24) {
  9167. Int24 *in = (Int24 *)inBuffer;
  9168. for (unsigned int i=0; i<stream_.bufferSize; i++) {
  9169. for (j=0; j<info.channels; j++) {
  9170. out[info.outOffset[j]] = (Int32) in[info.inOffset[j]].asInt();
  9171. out[info.outOffset[j]] <<= 8;
  9172. }
  9173. in += info.inJump;
  9174. out += info.outJump;
  9175. }
  9176. }
  9177. else if (info.inFormat == RTAUDIO_SINT32) {
  9178. // Channel compensation and/or (de)interleaving only.
  9179. Int32 *in = (Int32 *)inBuffer;
  9180. for (unsigned int i=0; i<stream_.bufferSize; i++) {
  9181. for (j=0; j<info.channels; j++) {
  9182. out[info.outOffset[j]] = in[info.inOffset[j]];
  9183. }
  9184. in += info.inJump;
  9185. out += info.outJump;
  9186. }
  9187. }
  9188. else if (info.inFormat == RTAUDIO_FLOAT32) {
  9189. Float32 *in = (Float32 *)inBuffer;
  9190. for (unsigned int i=0; i<stream_.bufferSize; i++) {
  9191. for (j=0; j<info.channels; j++) {
  9192. // Use llround() which returns `long long` which is guaranteed to be at least 64 bits.
  9193. out[info.outOffset[j]] = (Int32) std::min(std::llround(in[info.inOffset[j]] * 2147483648.f), 2147483647LL);
  9194. }
  9195. in += info.inJump;
  9196. out += info.outJump;
  9197. }
  9198. }
  9199. else if (info.inFormat == RTAUDIO_FLOAT64) {
  9200. Float64 *in = (Float64 *)inBuffer;
  9201. for (unsigned int i=0; i<stream_.bufferSize; i++) {
  9202. for (j=0; j<info.channels; j++) {
  9203. out[info.outOffset[j]] = (Int32) std::min(std::llround(in[info.inOffset[j]] * 2147483648.0), 2147483647LL);
  9204. }
  9205. in += info.inJump;
  9206. out += info.outJump;
  9207. }
  9208. }
  9209. }
  9210. else if (info.outFormat == RTAUDIO_SINT24) {
  9211. Int24 *out = (Int24 *)outBuffer;
  9212. if (info.inFormat == RTAUDIO_SINT8) {
  9213. signed char *in = (signed char *)inBuffer;
  9214. for (unsigned int i=0; i<stream_.bufferSize; i++) {
  9215. for (j=0; j<info.channels; j++) {
  9216. out[info.outOffset[j]] = (Int32) (in[info.inOffset[j]] << 16);
  9217. //out[info.outOffset[j]] <<= 16;
  9218. }
  9219. in += info.inJump;
  9220. out += info.outJump;
  9221. }
  9222. }
  9223. else if (info.inFormat == RTAUDIO_SINT16) {
  9224. Int16 *in = (Int16 *)inBuffer;
  9225. for (unsigned int i=0; i<stream_.bufferSize; i++) {
  9226. for (j=0; j<info.channels; j++) {
  9227. out[info.outOffset[j]] = (Int32) (in[info.inOffset[j]] << 8);
  9228. //out[info.outOffset[j]] <<= 8;
  9229. }
  9230. in += info.inJump;
  9231. out += info.outJump;
  9232. }
  9233. }
  9234. else if (info.inFormat == RTAUDIO_SINT24) {
  9235. // Channel compensation and/or (de)interleaving only.
  9236. Int24 *in = (Int24 *)inBuffer;
  9237. for (unsigned int i=0; i<stream_.bufferSize; i++) {
  9238. for (j=0; j<info.channels; j++) {
  9239. out[info.outOffset[j]] = in[info.inOffset[j]];
  9240. }
  9241. in += info.inJump;
  9242. out += info.outJump;
  9243. }
  9244. }
  9245. else if (info.inFormat == RTAUDIO_SINT32) {
  9246. Int32 *in = (Int32 *)inBuffer;
  9247. for (unsigned int i=0; i<stream_.bufferSize; i++) {
  9248. for (j=0; j<info.channels; j++) {
  9249. out[info.outOffset[j]] = (Int32) (in[info.inOffset[j]] >> 8);
  9250. //out[info.outOffset[j]] >>= 8;
  9251. }
  9252. in += info.inJump;
  9253. out += info.outJump;
  9254. }
  9255. }
  9256. else if (info.inFormat == RTAUDIO_FLOAT32) {
  9257. Float32 *in = (Float32 *)inBuffer;
  9258. for (unsigned int i=0; i<stream_.bufferSize; i++) {
  9259. for (j=0; j<info.channels; j++) {
  9260. out[info.outOffset[j]] = (Int32) std::min(std::llround(in[info.inOffset[j]] * 8388608.f), 8388607LL);
  9261. }
  9262. in += info.inJump;
  9263. out += info.outJump;
  9264. }
  9265. }
  9266. else if (info.inFormat == RTAUDIO_FLOAT64) {
  9267. Float64 *in = (Float64 *)inBuffer;
  9268. for (unsigned int i=0; i<stream_.bufferSize; i++) {
  9269. for (j=0; j<info.channels; j++) {
  9270. out[info.outOffset[j]] = (Int32) std::min(std::llround(in[info.inOffset[j]] * 8388608.0), 8388607LL);
  9271. }
  9272. in += info.inJump;
  9273. out += info.outJump;
  9274. }
  9275. }
  9276. }
  9277. else if (info.outFormat == RTAUDIO_SINT16) {
  9278. Int16 *out = (Int16 *)outBuffer;
  9279. if (info.inFormat == RTAUDIO_SINT8) {
  9280. signed char *in = (signed char *)inBuffer;
  9281. for (unsigned int i=0; i<stream_.bufferSize; i++) {
  9282. for (j=0; j<info.channels; j++) {
  9283. out[info.outOffset[j]] = (Int16) in[info.inOffset[j]];
  9284. out[info.outOffset[j]] <<= 8;
  9285. }
  9286. in += info.inJump;
  9287. out += info.outJump;
  9288. }
  9289. }
  9290. else if (info.inFormat == RTAUDIO_SINT16) {
  9291. // Channel compensation and/or (de)interleaving only.
  9292. Int16 *in = (Int16 *)inBuffer;
  9293. for (unsigned int i=0; i<stream_.bufferSize; i++) {
  9294. for (j=0; j<info.channels; j++) {
  9295. out[info.outOffset[j]] = in[info.inOffset[j]];
  9296. }
  9297. in += info.inJump;
  9298. out += info.outJump;
  9299. }
  9300. }
  9301. else if (info.inFormat == RTAUDIO_SINT24) {
  9302. Int24 *in = (Int24 *)inBuffer;
  9303. for (unsigned int i=0; i<stream_.bufferSize; i++) {
  9304. for (j=0; j<info.channels; j++) {
  9305. out[info.outOffset[j]] = (Int16) (in[info.inOffset[j]].asInt() >> 8);
  9306. }
  9307. in += info.inJump;
  9308. out += info.outJump;
  9309. }
  9310. }
  9311. else if (info.inFormat == RTAUDIO_SINT32) {
  9312. Int32 *in = (Int32 *)inBuffer;
  9313. for (unsigned int i=0; i<stream_.bufferSize; i++) {
  9314. for (j=0; j<info.channels; j++) {
  9315. out[info.outOffset[j]] = (Int16) ((in[info.inOffset[j]] >> 16) & 0x0000ffff);
  9316. }
  9317. in += info.inJump;
  9318. out += info.outJump;
  9319. }
  9320. }
  9321. else if (info.inFormat == RTAUDIO_FLOAT32) {
  9322. Float32 *in = (Float32 *)inBuffer;
  9323. for (unsigned int i=0; i<stream_.bufferSize; i++) {
  9324. for (j=0; j<info.channels; j++) {
  9325. out[info.outOffset[j]] = (Int16) std::min(std::llround(in[info.inOffset[j]] * 32768.f), 32767LL);
  9326. }
  9327. in += info.inJump;
  9328. out += info.outJump;
  9329. }
  9330. }
  9331. else if (info.inFormat == RTAUDIO_FLOAT64) {
  9332. Float64 *in = (Float64 *)inBuffer;
  9333. for (unsigned int i=0; i<stream_.bufferSize; i++) {
  9334. for (j=0; j<info.channels; j++) {
  9335. out[info.outOffset[j]] = (Int16) std::min(std::llround(in[info.inOffset[j]] * 32768.0), 32767LL);
  9336. }
  9337. in += info.inJump;
  9338. out += info.outJump;
  9339. }
  9340. }
  9341. }
  9342. else if (info.outFormat == RTAUDIO_SINT8) {
  9343. signed char *out = (signed char *)outBuffer;
  9344. if (info.inFormat == RTAUDIO_SINT8) {
  9345. // Channel compensation and/or (de)interleaving only.
  9346. signed char *in = (signed char *)inBuffer;
  9347. for (unsigned int i=0; i<stream_.bufferSize; i++) {
  9348. for (j=0; j<info.channels; j++) {
  9349. out[info.outOffset[j]] = in[info.inOffset[j]];
  9350. }
  9351. in += info.inJump;
  9352. out += info.outJump;
  9353. }
  9354. }
  9355. if (info.inFormat == RTAUDIO_SINT16) {
  9356. Int16 *in = (Int16 *)inBuffer;
  9357. for (unsigned int i=0; i<stream_.bufferSize; i++) {
  9358. for (j=0; j<info.channels; j++) {
  9359. out[info.outOffset[j]] = (signed char) ((in[info.inOffset[j]] >> 8) & 0x00ff);
  9360. }
  9361. in += info.inJump;
  9362. out += info.outJump;
  9363. }
  9364. }
  9365. else if (info.inFormat == RTAUDIO_SINT24) {
  9366. Int24 *in = (Int24 *)inBuffer;
  9367. for (unsigned int i=0; i<stream_.bufferSize; i++) {
  9368. for (j=0; j<info.channels; j++) {
  9369. out[info.outOffset[j]] = (signed char) (in[info.inOffset[j]].asInt() >> 16);
  9370. }
  9371. in += info.inJump;
  9372. out += info.outJump;
  9373. }
  9374. }
  9375. else if (info.inFormat == RTAUDIO_SINT32) {
  9376. Int32 *in = (Int32 *)inBuffer;
  9377. for (unsigned int i=0; i<stream_.bufferSize; i++) {
  9378. for (j=0; j<info.channels; j++) {
  9379. out[info.outOffset[j]] = (signed char) ((in[info.inOffset[j]] >> 24) & 0x000000ff);
  9380. }
  9381. in += info.inJump;
  9382. out += info.outJump;
  9383. }
  9384. }
  9385. else if (info.inFormat == RTAUDIO_FLOAT32) {
  9386. Float32 *in = (Float32 *)inBuffer;
  9387. for (unsigned int i=0; i<stream_.bufferSize; i++) {
  9388. for (j=0; j<info.channels; j++) {
  9389. out[info.outOffset[j]] = (signed char) std::min(std::llround(in[info.inOffset[j]] * 128.f), 127LL);
  9390. }
  9391. in += info.inJump;
  9392. out += info.outJump;
  9393. }
  9394. }
  9395. else if (info.inFormat == RTAUDIO_FLOAT64) {
  9396. Float64 *in = (Float64 *)inBuffer;
  9397. for (unsigned int i=0; i<stream_.bufferSize; i++) {
  9398. for (j=0; j<info.channels; j++) {
  9399. out[info.outOffset[j]] = (signed char) std::min(std::llround(in[info.inOffset[j]] * 128.0), 127LL);
  9400. }
  9401. in += info.inJump;
  9402. out += info.outJump;
  9403. }
  9404. }
  9405. }
  9406. }
  9407. //static inline uint16_t bswap_16(uint16_t x) { return (x>>8) | (x<<8); }
  9408. //static inline uint32_t bswap_32(uint32_t x) { return (bswap_16(x&0xffff)<<16) | (bswap_16(x>>16)); }
  9409. //static inline uint64_t bswap_64(uint64_t x) { return (((unsigned long long)bswap_32(x&0xffffffffull))<<32) | (bswap_32(x>>32)); }
  9410. void RtApi :: byteSwapBuffer( char *buffer, unsigned int samples, RtAudioFormat format )
  9411. {
  9412. char val;
  9413. char *ptr;
  9414. ptr = buffer;
  9415. if ( format == RTAUDIO_SINT16 ) {
  9416. for ( unsigned int i=0; i<samples; i++ ) {
  9417. // Swap 1st and 2nd bytes.
  9418. val = *(ptr);
  9419. *(ptr) = *(ptr+1);
  9420. *(ptr+1) = val;
  9421. // Increment 2 bytes.
  9422. ptr += 2;
  9423. }
  9424. }
  9425. else if ( format == RTAUDIO_SINT32 ||
  9426. format == RTAUDIO_FLOAT32 ) {
  9427. for ( unsigned int i=0; i<samples; i++ ) {
  9428. // Swap 1st and 4th bytes.
  9429. val = *(ptr);
  9430. *(ptr) = *(ptr+3);
  9431. *(ptr+3) = val;
  9432. // Swap 2nd and 3rd bytes.
  9433. ptr += 1;
  9434. val = *(ptr);
  9435. *(ptr) = *(ptr+1);
  9436. *(ptr+1) = val;
  9437. // Increment 3 more bytes.
  9438. ptr += 3;
  9439. }
  9440. }
  9441. else if ( format == RTAUDIO_SINT24 ) {
  9442. for ( unsigned int i=0; i<samples; i++ ) {
  9443. // Swap 1st and 3rd bytes.
  9444. val = *(ptr);
  9445. *(ptr) = *(ptr+2);
  9446. *(ptr+2) = val;
  9447. // Increment 2 more bytes.
  9448. ptr += 2;
  9449. }
  9450. }
  9451. else if ( format == RTAUDIO_FLOAT64 ) {
  9452. for ( unsigned int i=0; i<samples; i++ ) {
  9453. // Swap 1st and 8th bytes
  9454. val = *(ptr);
  9455. *(ptr) = *(ptr+7);
  9456. *(ptr+7) = val;
  9457. // Swap 2nd and 7th bytes
  9458. ptr += 1;
  9459. val = *(ptr);
  9460. *(ptr) = *(ptr+5);
  9461. *(ptr+5) = val;
  9462. // Swap 3rd and 6th bytes
  9463. ptr += 1;
  9464. val = *(ptr);
  9465. *(ptr) = *(ptr+3);
  9466. *(ptr+3) = val;
  9467. // Swap 4th and 5th bytes
  9468. ptr += 1;
  9469. val = *(ptr);
  9470. *(ptr) = *(ptr+1);
  9471. *(ptr+1) = val;
  9472. // Increment 5 more bytes.
  9473. ptr += 5;
  9474. }
  9475. }
  9476. }
  9477. // Indentation settings for Vim and Emacs
  9478. //
  9479. // Local Variables:
  9480. // c-basic-offset: 2
  9481. // indent-tabs-mode: nil
  9482. // End:
  9483. //
  9484. // vim: et sts=2 sw=2