I havedone a wholeSirisonworkingwithsoundinmycodeityourselfsynthesizerSirisonthePixelgameengineadopts a verysimilarapproach, but I thoughtitwouldbeusefulfirsttocreate a smalldemonstrationupjusttoshowhowthepixelgameenginehandlesound.
It's theNezemulatorsofar, butyou'llnotice I'veincluded a lotmoremappers.
Now I'lltalkspecificallyaboutadditionalmappersin a latervideoofthisSiri's, butfornow, itjustgivesus a bitmorevariationinthenumberofgamesthatwecontest, and I'm goingtohijackthisprojecttemporarilyjusttobuildthissounddemonstrationvideo, someone's add a newfileand I'llcallitsounddemodotCPPonjusttemporarily.
Youcanchangethemtochangetheperformanceoftherealtimenatureoftheaudio, but I foundthatthesetwosettingsworkedverywellformostapplicationsbecausethesoundPegIXopens a handletosomesoundhardwork.
Thepixelgameenginecreates a threadthatitusestocalltheonuserupdatefunctiononthisthatsitsin a looprepeatedlyrunningasfastasitcanunlessyou'vegotthe V sinkoptionenabledwhenyouconstructedit.
Theproblemwefaceisthatthespeedoffthismainsetconflictyouatedependinguponwhatthefunctionisdoingonnormally, wewouldalleviatethisfluctuationbyexploitingthe F elapsedtimevariablethatcomeswithit.
Whichremindsme, actually, asthisis a videoaboutaudio, uh, I willwarnyouNowwe'regoingtohaveallsortsofsquealsandscratchesoninterestingnoisesandprobablyinappropriatevolumesthroughout, Soconsideryourselfone.
A secondthreadismaintainedinthesoundpegeggsonthespeedatwhichthisthreadoperatesislargelygovernedbythesampleratethatwespecifiedwhenwecreatedtheinstanceofthepeg X.
Thiswaywecanensurethatsoundsamplesaredeliveredtotheaudiodevicehardwareappropriately, buttogetthesamplesthatweneedthePeg X isgoingtorequestfromthemainthread a sampleofsoundwhenitneedsitonthemainsaidwillthenreturnthatsinglesample.
Now I'm quitesurethey'regoingtobemanymoresophisticatedandcleverwaystoehandlethisinteractionbetweenthetwothreats, but I amaimingtokeepthingssimple, so I'm goingtocreate a function, andit's a staticfunctioncalledsoundout.
Thisisthefunctionthatwillbecalledbythesoundextensioneverytimeitwants a singlesample, anditrequestswhatchannelitwantsthatsampletobefore.
Soin a twochannelsystemthat's theleftspeaker, followedbytherightspeaker.
Togenerate a pulsewave, wesimplysubtractonefromtheother, whichwecanseeherewiththeblackwave, whichis a verynicesquarewavein a continuoustimedomainat a 50% dutycycle, itisequallylowonequallyhighonthequalityofthissquarewavedependsonhowmanyharmonicsareinoursorewaves.
Asyoucanseeaswegoto a lowaccount, theschoolwavebecomesrounderondhe.
A and B representsthesamplevaluesfortheunderlyingsinewaveforms.
And P isgoingtorepresentthephasedifferencebetweenthetwo, sincewe'regoingtobesummingup a wholebunchofsinewavesdependingonhowmanyharmonicswereinterestedin a lotoffourloop, bothsinewavesgetthesameargument, so I'llcashthathereinvariable C.
It's thenumberofharmonicstimesthefrequencytimestwotimespitimes t onas I'vejustshowninDismas.
Thetwosinewavesareverysimilar, exceptoneisoffsetbytheface, and I'm alsoscalingbythenumberofharmonics.
Thethirdchannelis a triangleWavechannelsnotquitethesameas a soretoothwaveonthisisusedtogiveyou a moreBasielikesound.
Thenextchannelis a noisechannel.
Thisgivesyou a percussiveinstrumentsoundorexplosionsondhe.
Finally, thereis a sampleplayingchannel.
Sothisplace, whatis a verysimplewayform, forexample, Itmightbesomebodysayingwelldoneorlevelcomplete, becauseinthisvideowe'vespentsometimelookingathowtogetsoundRunningwiththepixelgameengineonwillspendmostoftherestofthisvideolookingathowweimplementsoundintoouremulation.
I'm notgoingtodetailmanyofthesechannels, butwell, lookatthatInparttwoofthisaudioSirisonthehardware, thenestisalsocapableofspecifyingthedurationof a note, itslengthanditsfrequencysowecanseealreadywe'restartingtobuild a persetofparametersthatinfluencethesoundcomingoutof a channel.
We'vealsogotthefrequencysweepingandwe've a fewotherthingsintheretoo.
Butforthisvideo, I don't wanttogetstuckintothosedetailsnecessarily.
I'm badlytheclasstothecodebasecalledOLCtoaothree, whichisthedesignationforthecombinedCPUandsoundhardwork, though I'm onlygoingtoincludesoundstuffinitonbecauseit's a deviceattachedtoourCPUbus.
Itneedsallofthe C B busfunctionswe'vebecomefamiliarwith.
Weneedtobeabletowritetoit, readfromit, clockiton, resetit, and I'vegoneaheadandimplementedsomeblankfunctions.
I'IIworklockingthenestfasterthanrealtime, soit's goingtobetechnicallygeneratingaudiosamplesfarfasterthanthesystemcanprocessthemandreceivethemwereeffectivelycrossing a timedomainboundaryonuniversity.
Andit's forexactlyallofthesereasonswhythisvideoisspecificallyaboutchangingthearchitectureofouremulationratherthangeneratingthissoundsfortheGames, althoughwewillgettothatinthisvideo, we'recurrentlyregulatingthespeedofouremulationinquite a crudeway, wereeffectivelycreating a 60 Hertztickerononeachtick, generatingenoughnurseclockstocreate a singleframeofoutput.
Thishasalwaysbeenapproximate.
Andas I'vemaintainedfromEpisodeone, it's notmyintentiontocreate a cycleperfect, temporallyaccurateemulation.
Andsofar, thishasbeensufficientforustotrygames.
That's a plausibleandplayableframerate.
Theapproachhereisthatinsteadofregulatingtothisartificialonrathervariabletimingsystem, we'regoingtorelyon a veryaccuratetimingsystemthatcomesfromoursoundhardwork.
Thenwe'vegotanaudiosamplereadytobedeliveredtotheaudiosystemso I canresetmy d audiotime.
Accumulatorgetsthecurrentvalidsamplefromthe A P.
U andsetmysamplereadyFlagtootrue, goingbacktothemainemulationsourceinoursoundoutfunction.
Nowitbecomesobviousthat I wanttositrepeatedlyclockinguntilthisfunctionreturnstruebecausethenandonlythenisthere a samplereadyinreallyaudiotimetosendtothesoundhardwork.
Wecantryhaving a playofthegame, butthistimingisnowcompletelygovernedbythesoundsystem.
Infact, itplaysjustfine.
Doesn't necessarilymean I'm playingjustfine.
Butyouknowwhat I meannowbecauseweputthatconstantinofftheNazis.
Clockspeedon.
We'vedeveloped a relationshipbetweentheNazisclockspeedonthespeedthatthesoundhardwareismovingby.
We'veactuallygotthisquiteaccuratespeedforthenez.
No, whichisinterestingtothinkthatsomethingassimplestsoundisgoingtobesoresponsibleforhowtheemulatorbehaves.
Sonowit's timetogetnoisyAttheheartofeachnest, Audiochannelliessomethingcalled a sequenceronfundamentally a sequencerisjust a counterthatcountdownanditonlycountsdown.
So I'm goingtomaintain a clockcountervariablebecausethisiscalledeverypeopieyouclockonwhenthisclockcountervariableisevenlydivisiblebysix, thenwe'regoingtochangethestateofthe A P u.
Now, don't forget, thisrequiredthatwepassedtoit a lambdafunction.
Sothesecondargumentofthisisindeed a lambdafunction, whichallowsustocustomizethefunctionalityforthisparticularsequence.
Irthe s argumentpassedintothelandoffunctionisthesequencevaluestoredinthesequenceInstructonall I wanttodoforthisparticularsequence.
IRisrotatethewordas I showedontheslidesbeforeandthereisn't a convenient c++ syntaxfordoingrotation.
Soyouhavetodoitmanuallywithsomebitwiseoperations.
Buteffectively, whatwe'redoingistakingtheuppersevenbitsofthewordandshiftingthemrightoneontakingthepreviousleastsignificantbitonsettingitinthemostsignificantbitlocationInprinciple, weknowthatthiswillgenerateforus a squarewavewaveform.
So I'm goingtosettheoutputofoursequencerdirectlytoourpulse.
Onesample.
SonowtheclockfunctiondoessomethingAdmittedly, notverymuch, butitisclockingoursecret, sir, Tostartoutputting a wayform, wenowneedtocoupleintheCPUrightfunctioninordertocharacterizewhatthatwayformshouldlooklikewritingtoaddressfor 1000 ontheCPUsaddressbooksisresponsibleforsettingthedutycycleofChannelone's pulsewaveformandsouse a littleswitchcasestatementtodothatonhere, wecansee I'm settingthesequenceofoursecretsaredependingon a specificdutycyclevalue.
Isn't itamazinghowthesethingsallcometogethertothe A.
P.
U had a file I'vecreated a secondstruckcalledalsolaterpulse, whichcontainsexactlythecode I hadatthestartwherewe'reusingharmonicsofsinewavestocreate a pulsewaywith a varyingdutycycle, TheNet's DevWickyactuallygivesus a translationfunctiontoturntherequestedvalueoffthatparticularchannelintotheoutputfrequencythatwewanttolistento, giventheclockstructuresfortheemulationplatformweretargeting, inwhichcaseisNTSCforMay.
So I'm justgoingtodirectlyimplementsthisfunctiontogivemethefrequencythat I needtopasstomyoscillatorwhereweweregeneratingthesequencebefore.
I'm justgoingtocommentthatout.
Andinsteadoflookingattheoutputofthesequence, sir, I'm goingtocalculatethefrequency I needfortheoscillatorondhesamplemyoscillatorgivingit a specificglobaltime.
Conveniently, theglobaltimevariableisinemulationtime, so I justneedtoaccumulatethat.