Desenvolupament d'algorismes per a síntesi i processament d'audio sota l'estàndard VST
Full text
Desenvolupament d’algoritmesperasíntesii processamentd’audiosota l’estàndardVST FranciscoJavierRipollEsteve
Agraïments Agraïments Aquestprojectefinaldecarreraharesultatunsacrificipersonalperami,jaqueaquest anyhehagutdefersonarmoltesnotesdelmeusaxòfon.Peròtambéhasigutunsacrificiper totesaquellespersonesqueestanalmeuvoltant,iésperaixò,quevoldriadedicaruneslínies d'aquestamemòriaatoteslespersonesquehanhagutdesuportar‐me,quehanpatitpermii quem'hanajudat. Primerdetot,elmeuagraïmentaltutordelmeuprojecte,D.AlvarDomenech,perquè senseellencaraestariapensantquèferenelprojecte.Alvarhasigutelmeullibreduranttotel tempsderealitzaciódelprojecte. Alameuamare,elmeupare,lameuatiaiaRosabel,quehansuportatelsmals humorsquanlescosesnoeixienbé,im’hanpegatlallandaperaacabarelprojecte. ADiego,quetantesideesemdonavaquantornàvemdeSagunt,iemvaferelfavorde gravar‐meunssegonsdelaseuaguitarraperposarelsexemplesdelplugins. TambéalmeutioJosepManuel,perhaver‐mecorregitlesfaltesiexpressions ortogràfiquesiadequareltextdelmeuprojecte. Finalment,calagrairatotalameuafamíliaelsuportincondicionalqueherebutdurant aquestsúltimssisanysdecarrera,itambéelfetquem'hajaajudataaprendreaaprendre. Doncsatots,moltesgràcies.
Contingut I Contingut 1Introducció.................................................................................................................................1 1.2Motivació.............................................................................................................................1 1.3Contingutdelcd..................................................................................................................1 2Conceptesprevis........................................................................................................................3 2.1Elsodigital..........................................................................................................................3 2.1.1RepresentaciódelsomitjançantPCM.........................................................................3 2.1.2Mostratge.....................................................................................................................3 2.1.3Quantificació................................................................................................................5 2.1.4Estructurad'unainterfícied'àudio...............................................................................5 2.2MIDI .....................................................................................................................................9 2.2.1Història.........................................................................................................................9 2.2.2Hardware......................................................................................................................9 2.2.3Software.....................................................................................................................12 2.3Seqüenciador.....................................................................................................................15 2.3.1Orígens.......................................................................................................................15 2.3.2Funcionament............................................................................................................16 2.4DAW..................................................................................................................................17 2.4.1Història.......................................................................................................................17 2.4.2Actualitat....................................................................................................................18 2.4.3Varietats.....................................................................................................................18 2.4.4Ediciólinealinolineal................................................................................................19 2.4.5Gestiódelesregions..................................................................................................22 2.4.6Acarreramentdelsenyal............................................................................................23 3.Entorndetreball.....................................................................................................................30 3.1Cubase...............................................................................................................................30 3.2VST.....................................................................................................................................32 3.2.1VSTplugins.................................................................................................................32 3.2.2ClasseAudioEffect......................................................................................................32 3.2.3Elprocésnumèric.......................................................................................................34 3.2.4Elsvalorsenl'interfíciegráfica...................................................................................35 3.2.5Obtenciódelsparàmetres..........................................................................................36 3.3Entorndeprogramació.....................................................................................................37
Contingut II 3.3.1Historia.......................................................................................................................37 3.3.2Característiques..........................................................................................................38 3.3.3VisualC++...................................................................................................................38 4Col∙lecciódeplugins.................................................................................................................40 4.1Balanç................................................................................................................................40 4.1.1Descripció...................................................................................................................40 4.1.2Paràmetres.................................................................................................................40 4.1.3Operació.....................................................................................................................40 4.2Distorsió............................................................................................................................42 4.2.1Descripció...................................................................................................................42 4.2.2Paràmetres.................................................................................................................42 4.2.3Operació.....................................................................................................................42 4.3Delay..................................................................................................................................44 4.3.1Descripció...................................................................................................................44 4.3.2Paràmetres.................................................................................................................44 4.3.3Operació.....................................................................................................................44 4.4Eco.....................................................................................................................................46 4.4.1Descripció...................................................................................................................46 4.4.2Paràmetres.................................................................................................................46 4.4.3Operació.....................................................................................................................46 4.5Chorus...............................................................................................................................48 4.5.1Descripció...................................................................................................................48 4.5.2Paràmetres.................................................................................................................48 4.5.3Operació.....................................................................................................................48 4.6Generador.........................................................................................................................50 4.6.1Descripció...................................................................................................................50 4.6.2Paràmetres.................................................................................................................50 4.6.3Operació.....................................................................................................................50 4.7Sintetitzador......................................................................................................................52 4.7.1Descripció...................................................................................................................52 4.7.2Paràmetres.................................................................................................................53 4.7.3Operació.....................................................................................................................53 5Annexos....................................................................................................................................58 AnnexI.........................................................................................................................................58
Contingut III balance.h.................................................................................................................................58 AnnexII........................................................................................................................................59 balance.cpp.............................................................................................................................59 AnnexIII.......................................................................................................................................62 distorsio.h................................................................................................................................62 AnnexIV......................................................................................................................................63 distorsio.cpp............................................................................................................................63 AnnexV.......................................................................................................................................66 delay.h.....................................................................................................................................66 AnnexVI......................................................................................................................................68 delay.cpp.................................................................................................................................68 AnnexVII.....................................................................................................................................72 eco.h ........................................................................................................................................72 AnnexVIII....................................................................................................................................74 eco.cpp....................................................................................................................................74 AnnexIX.......................................................................................................................................78 chorus.h...................................................................................................................................78 AnnexX........................................................................................................................................80 chorus.cpp...............................................................................................................................80 AnnexXI.......................................................................................................................................85 generador.h.............................................................................................................................85 AnnexXII......................................................................................................................................87 generador.cpp.........................................................................................................................87 AnnexXIII.....................................................................................................................................90 sint.h........................................................................................................................................90 AnnexXIV....................................................................................................................................92 sint.cpp....................................................................................................................................92 6Bibliografia.............................................................................................................................101 6.1E‐recursos........................................................................................................................101
Introducció 1 1Introducció Enl'actualitatésmodaparlardemultimèdia,peròquèésrealment? Multimèdiaésl'úsdediversosmitjansperatransmetre,administraropresentar informació.Aquestsmitjanspodensertext,gràfiques,àudioivídeoentrealtres.Peròamb aquesttermerelacionatamblescomputadores,ensreferimal'úsdesoftwareihardwareper aemmagatzemaripresentarcontingutsusantunacombinaciódetext,fotografies,vídeosi àudio. Aquestesaplicacionstecnològiquessónlavertaderanovetat,ihanfetqueelterme multimèdiaestigapopularitzat,jaqueelfenomenmultimèdiaestàpresentenquasitotesles formesdecomunicacióhumana. Comhemesmentat,l'àudioformapartd'aquestpopularterme,iésperaixò,quehiha unagranquantitatdeprogramesperalacreació,edicióipostproducciód'àudio.Unadeles mésprestigiosesempresesdesoftwareenl'edicióicreaciómusicalésSteinbergque,entreels seusproductesméspopulars,téCubaseiNuendo. Cubaseésunsistemacompletdecreaciómusical,jaquepodriadefinir‐secomun híbridentreunseqüenciadorMidi,editord'àudioimesclador. SteinbergCubasenohaaconseguitelnivelldeprestiginomésperpermetregravar, compondreimesclar,sinóperdisposard'unampliconjuntdefuncionalitatsperacadatipus depista.Peròlafuncionalitatmésfamosasónelsplugins.Aquestsplugins,sónxicotets programesques'incrustenenelpropiCubaseitenenduesfuncionalitatsbàsiques,jaquehiha dostipus:elspluginsd'efectesielsInstrumentsVirtuals. 1.2Motivació Lamotivaciód'aquestprojecteéspoderportaralapràcticalacreaciódepluginsVST perapoder‐losutilitzarambSteinbergCubase.Elspluginsconsisteixenenefectesde panorama,tallsdefreqüència,retardsipluginsd'instrumentsvirtuals. Unavegadaparlatambelprofessor,eldesenvolupamentdelspluginsVSTseran utilitzatsambunafinalitatdidàcticaamanerad'exempleperaassignaturesd'àudio,més concretamentl'assignaturaques'imparteixenlaFacultatd'InformàticadelaUniversitat PolitècnicadeValència“IntroduccióalaSíntesi,EdicióiPostproducciód'Àudio”. 1.3Contingutdelcd Elcdambelques'adjuntaaquestprojectecontéunaarxiu.pdfamblamemòriadel projecteitrescarpetesetiquetadesambelsnoms:codi,exemplesiplugins. Lacarpetaetiquetadaambelnomcodicontéalseuinteriorelsarxiusnecessarispera compilarcadaundelspluginscreatsdurantaquestprojecte.Enelsannexosespotobservar tambéelcodiescritdecadaund'ells.
Introducció 2 Al'interiordelacarpetaetiquetaambelnomexemples,hihaunasèried'arxius d'àudioenformat.mp3peraescoltardeformasonoral'efectequeprodueixcadapluginen unamostrad'àudio. Finalmentalacarpetaplugins,estanelsarxius.dllcorresponentsacadaplugin elaboratperapoder‐losutilitzarenunaestaciódetreballquesuportel'estàndardVST.
Conceptesprevis Elsodigital 3 2Conceptesprevis 2.1Elsodigital 2.1.1RepresentaciódelsomitjançantPCM Elmaneigdelsodesd'uncomputadornecessitaunarepresentacióenformatdigital.Hi hamoltestècniquesques'adaptenalesnecessitatsdecadausuari.Alafigura1espot observarl'esquemabàsicdelfluxdel'àudiodigital. figura1.Fluxdel'àudiodigital. Peralarealitzaciód'aquestprojecte,s'utilitzaelmètodedelamodulacióperimpulsos codificats(PCM)perpoderferl'intercanviambelsperifèricsd'entrada/eixidad'àudio. Elmètodedelamodulacióperimpulsoscodificats(PCM),éselmètodepera representardigitalmentunsenyalanalògicquanlamagnituddelsenyalésmostrejada periòdicamentaintervalsuniformes,illavorsquantificadesaunvalor(normalmentbinari). Aquestmètodehasigututilitzatensistemesdetelefoniadigitalienteclatsmusicals electrònics.Tambééslaformaestàndardd'àudiodigitalivídeodigitalalsordinadors. 2.1.2Mostratge Elmostratgeconsisteixaprendremostresdelvalordelsenyalnvegadespersegon, amblaqualcosaquetindremnnivellsdetensióenunsegon. Alafigura2espotobservarlaquantificacióperal'onasinusoïdal(corbaroja) mitjançantPCM.L'onasinusoïdalesmostraaintervalsregulars(eixdelesX).Cadamostraés
Conceptesprevis Elsodigital 4 quantificadamitjançantl'algoritmetriatenl'eixdelesY(enaquestcaslafunciófloor). D'aquestamanera,obtenimaixíunarepresentaciótotalmentdiscretadelsenyald'entrada comespotobservarenl'àreaombrejada,iaixíésmoltfàcilcodificaraquestesdadesdigitals peralseuemmagatzemamentimanipulació. figura2.Mostreigiqüantificaciód'unsenyal(roig)de4bitPCM Ambl'exempledelafigura,comprovemqueelsvalorsdequantitzaciódecada momentserien:7,9,11,12,13,14,14,15,15,15,14,etc.Codificantaquestsvalorsal computadorambvalorsbinarisquedariadelamanerasegüent:0111,1001,1011,1100,1101, 1110,1110,1111,1111,1111,1110,etc,ipertantjapodrienserprocessatsalcomputador. Siensn’adonem,elnombredemostresqueespodenprendreenunminutpotvariar segonslesnecessitats.Peradeterminarelnombredemostresaprendrepersegons'utilitzael teoremademostratgedeNyquist‐Shannon. ElteoremadeNyquist‐Shannonagranstretsdiuquesiesprenenmostresd'unsenyal elèctriccontinuaintervalsregularsiambunafreqüènciadoblealafreqüènciamàximaquees vullgamostrejar,aquestesmostrescontindrantotalainformaciónecessàriaperareconstruir elsenyaloriginal.Alataula1,espodenobservarlesfreqüènciesdemostratgetípiques:
Conceptesprevis MIDI 11 figura8.ConnectorMidi ElcableMIDIserveixperapodertransmetredadesentredosdispositiusoinstruments electrònics. Actualment,fabricantscomCasio,KorgiRoland,unsdelsméspopulars,estan substituintaquestscablespercablesdeconnectorsdetipusUSB,jaquesónmésfàcilsde trobarenelscomerçosipermetenunaconnexiófàcilambelscomputadorspersonals. MIDInoméspottransmetresenyalsenunsentit,laqualcosaesdenominaun funcionamentsimplex.Elsentitd'aquesteséssempredesdeldispositiumestrealdispositiu esclau,onelprimergeneralainformacióielsegonlarep. UnaparellMIDIpottenirfinsatrestipusdeconnectors: ‐ MIDIOUT:éselconnectordelqualixenelsmissatgesgeneratspeldispositiumestrea undispositiuesclau. ‐ MIDIIN:serveixperaintroduirelsmissatgesrebutsdesdeldispositiumestreal dispositiuesclau ‐ MIDITHRU:ésunconnectord'eixida,encaraquelaseuafuncióésenviarunacòpia exactadelsmissatgesrebutspelconnectorMIDIIN. LaformaméssimpledeconnectardosdispositiusMIDIseriaunir‐losambuncable MIDI.EnunextremenelconnectorMIDIOUTdeldispositiumestre(perexempleunteclat MIDI)ial'altreextremenelconnectorMIDIINdeldispositiuesclau(perexempleun sintetitzador).D'estamaneraelsmissatgesixendeldispositiumestrepelconnectorMIDIOUTi aturaranalconnectorMIDIINdeldispositiuesclau,comespotveurealafigura9.
Conceptesprevis MIDI 12 figura9.ConnexióMIDIMaster‐Slave 2.2.3Software MIDI,enlaseuaespecificacióinclouunaorganitzaciódelsbytes. ElbyteMIDIestàcompostperdeubits,afiqueelsdispositiuspuguenportarun comptedetotselsbytesenviatsirebuts.Elprimerbitéseld'iniciisempreés0.L'últimbités elbitdeterminacióisempreés1.Els8bitsrestantsqueestrobenentreelbitd'iniciielbitde terminaciósónelsquecontenenelmissatgeMIDI. Espotferunadiferènciadelstipusdemissatge,jaqueaquestspodenserd'estat (Estatusbyte)od'informació(databyte).Perapoderdiferenciar‐los,noméshemdemirarel primerbitdelmissatgeMIDI,isiés1,elbytedelmissatgeésd'estat;siés0,tenimunbytede dades. Pernormageneral,quanescreaunmissatgeMIDI,sempres'enviaunbyted'estat,el qualpotestarseguitd'unacertaquantitatdebytesdedades.Perexemple,sis'enviael missatged'estat“activarnota”,aquesthad'anarseguitd'unbytededadesinformantquina notaésactivada. Elsmissatgesd'estatpodenserdedostipus:missatgesdecanalomissatgesde sistema.Elsmissatgesdecanalnoméss'envienaundispositiuespecífic,mentrequeels missatgesdesistemas’envienatotselsdispositius.Alataula3tenimunallistaambtotsels missatgesdisponibles. Taula3.MissatgesMIDI ByteestatDescripcióByteestatDescripció 1000ccccDesactivaciódenota 11110101 Indefinit 1001ccccActivaciódenota11110110 Requerimentd'entonació 1010ccccPostpulsaciópolifònica 11110111 Fidemissatgeexclusiu 1011ccccCanvidecontrol11111000 Rellotgedetemporització 1100ccccCanvideprograma11111001 Indefinit
Conceptesprevis MIDI 13 1101ccccPostpulsaciómonofònicadecanal 11111010 Inici 1110ccccPitch11111011 Continuació 11110000Missatgeexclusiudelfabricant 11111100 Aturada 11110001Missatgedetramatemporal 11111101 Indefinit 11110010Punterposiciódecançó 11111110 Esperaactiva 11110011Selecciódecançó11111111 Resetdelsistema 11110100Indefinit Elsbytesqueelsúltimsquatrebitsestanmarcatscom“cccc”,esrefereixenamissatge decanal,larestadebytessónmissatgesdesistema. MIDIestàpensatperacomunicarmitjançantunmateixmitjàdetransmissióunúnic controladorambdiversesunitatsgeneradoresdeso,oncadaunapottenirunomés instruments.Ésperaixòquefafaltaunmètodeperadiferenciarcadaundelsinstruments,que elsdenominaremcanal. ElscanalsMIDIpodentambédenominar‐seveusoinstruments.MIDIpotdireccionar finsa16canals,ipertant,eninstal∙larelsistemaMIDIserànecessariassignarunnombrede canalperacadadispositiu. Existeixen128instrumentsenl'especificacióestàndarddeMIDI,tambéconegutscom GMo“GeneralMIDI”.Espodenveurealataula4. Taula4.InstrumentsMID I 00‐Pianodecuaacústica32‐Baixacústic64‐Saxosoprà96‐Efecte1(pluja) 01‐Pianoacústicbrillant33‐Baixelèctricpolsat65‐Saxoalt97‐Efecte2(bandasonora) 02‐Pianodecuaelèctrica34‐Baixelèctricpunteig66‐Saxotenor98‐Efecte3(cristalls) 03‐Pianodecantina35‐Baixsensetrasts67‐Saxobaríton99‐Efecte4(atmosfera) 04‐PianoRhodes36‐Baixcolpejat168‐Oboè100Efecte5(brillantor) 05‐Pianoamb"chorus"37‐Baixcolpejat269‐Sanguinyolanglès101Efecte6(donyets) 06‐Clavicordi38‐Baixsintetitzat170‐Fagot102Efecte7(ressons) 07‐Clavinet39‐Baixsintetitzat271‐Clarinet103Efecte8(ciència‐ficció) 08‐Celesta40‐Violí72‐Flautí104Sitar 09‐Carilló41‐Viola73‐Flauta105Banjo 10‐Caixademúsica42‐Violoncello74‐Flautadolça106Shamisen 11‐Vibràfon43‐Contrabaix75‐Flautadepa107Koto 12‐Marimba44‐Cordesambtrèmolo76‐Colldebotella108Kalimba 13‐Xilòfon45‐Cordesambpizzicato77‐Shakuhachi(flauta japonesa) 109Gaita 14‐Campanestubulars46‐Arpa78‐Xiulet110Violícelta 15‐Saltiri47‐Timbals79‐Ocarina111Shanai 16‐OrgueHammond48‐Conjuntdecorda180‐Melodia1(onaquadrada)112Campanetes 17‐Orguepercusiu49‐Conjuntdecorda281‐Melodia2(dentdeserra)113Agogó 18‐Orguederock50‐Cordessintetitzades182‐Melodia3(orguedevapor)114Caixesmetàl∙liques 19‐Orgued'església51‐Cordessintetitzades283‐Melodia4(xiuxiueigorgue)115Caixadefusta 20‐Harmònium52‐CorAahs84‐Melodia5(xaranga)116CaixaTaiko 21‐Acordió53‐VeuOohs85‐Melodia6(veu)117Timbalmelòdic
Conceptesprevis MIDI 14 22‐Harmònica54‐Veusintetitzada86‐Melodia7(cinquenes)118Caixasintetitzada 23‐Bandoneón55‐Èxitd'orquestra87‐Melodia8(baiximelodies)119Platetinvertit 24‐Guitarraespanyola56‐Trompeta88‐Fons1(novaera)120Trasteigdeguitarra 25‐Guitarraacústica57‐Trombó89‐Fons2(càlid)121Soderespiració 26‐Guitarraelèctrica(jazz)58‐Tuba90‐Fons3(polisintetitzador)122Platja 27‐Guitarraelèctrica(neta)59‐Trompetaambsordina91‐Fons4(cor)123Piuladad'ocell 28‐Guitarraelèctrica (apagada) 60‐Sanguinyolfrancès (trompa) 92‐Fons5(d'arc)124Timbredetelèfon 29‐Guitarrasaturada (overdrive) 61‐Secciódebronzes93‐Fons6(metàl∙lic)125Helicòpter 30‐Guitarradistorsionada62‐Bronzessintetitzats194‐Fons7(celestial)126Aplaudiment 31‐Harmònicsdeguitarra63‐Bronzessintetitzats295‐Fons8(graneretes)127Tirdefusell Elssintetitzadorscontenenelementsdegeneraciódesodenominatsveus.Perapoder assignarlesveussesegueixunprocésalgorítmicperapoderencaminarlesdades d'activació/desactivaciódenotadesdelteclatacadaunadelesveus.D'estamanera,es preténquelesnotess'executencorrectamentiamblatemporitzacióexacta. Perapoderimplementar‐ho,hadedefinir‐seunarelacióentreelssetzecanalsMIDIi l'assignaciódelesveusdelsintetitzador,peraaixòexisteixen4tipusdemissatgesdemode peraaquestpropòsitqueespodenveurealataula5.Elsditsmissatgespodenseromnion/ omnioff,polyimono.Polyimonosónmútuamentexcloents.Omni,quanestàactiu, l'instrumentrespondràamissatgesenqualsevolcanalMIDI,alcontrari,quanaquest desactivat,l'instrumentrespondrànomésauncanalenparticular(modes2i3)ocadaveu seràassignadaauncanalenparticular(mode4). PeraunreceptorassignatalcanalbàsicN,elsquatremodespossiblesquesorgeixen delsdosmissatgesdemodesón: Taula5.ModesdefuncionamentMIDI NúmeroNomDescripció 1Omnion/polyElsmissatgesdeveuesrebenentotselscanalsdeveui s'assignenalesveuspolifònicament. 2Omnion/monoElsmissatgesdeveuesrebenentotselscanalsdeveui controlennomésunaveumonofònicament. 3Omnioff/polyElsmissatgesdeveuesrebenenelcanaldeveuNnomés,i s'assignenalesveuspolifònicament. 4Omnion/polyElsmissatgesdeveuesrebenenelscanalsdeveudesdeN finsaN+M‐1,is'assignenmonofònicamentalesveus1aN, respectivament.ElnombredeveusMestàespecificatenel tercerbytedelmissatgesdemaneramono.
Conceptesprevis Seqüenciador 15 2.3Seqüenciador Unseqüenciadorésundispositiuelectrònicfísicounaaplicacióinformàticaque permetprogramarireproduiresdevenimentsmusicalsdeformaseqüencialmitjançantuna interfíciedecontrolfísicològicconnectataunomésinstrumentsmusicalselectrònics. L'interfíciedecontrolmésestèsésl'estàndardMIDI. El seqüenciador és una de les ferramentes bàsiques de la Informàtica Musical ja que permet la creació d'unes quantes pistes melòdiques, harmòniques o rítmiques, que poden ser tractades, editades i reproduïdes de forma individual o simultània. A banda de l'afinació, durada i posició de les notes, hi ha molts altres paràmetres que els seqüenciadors ens permeten accedir, com ara volum, efectes, so, etc. tot això sempre amb la possibilitat de tractar no sols la pista en conjunt sinó cada una de les seues notes de forma individual. figura10.FinestraprincipalCubase Ésimportantrecalcarqueelsseqüenciadorsnotenensonspropis,sinóqueutilitzenels delaTargetadeSo.ElqueelseqüenciadorfaésinformarlaTargetadequanhadereproduir unanota,quevolumsonarà,quantdurarà,etc.Pertantlaqualitatdelsonodepèndel Software(seqüenciador)sinódelHardware(Targeta) Hihainfinitatdeseqüenciadors,finsitotalguns"especials"peradeterminatstipusde músicacomarapotsertechnoodance.Totsellstenenencomptelapossiblefaltade coneixementsmusicalsdel'usuari,iperaixò,mostrenlamúsicaambdiferentsllenguatges gràficsquenosónl'estrictamentmusical,comsónlesteclesd'unpiano,odiferentstipusde gràfics. 2.3.1Orígens Encaraquel'origendelseqüenciadoréseminentmentelectrònicespotdirqueundels seqüenciadorsmésbàsicsianticsqueesconeixenéslacaixademúsica.Apartirdelsxicotets pivotsquesobreïxend'uncorrógiratoriesfansonarunasèriedellengüetesmetàl∙liques afinadessegonsl'escalamusical.Pertantlaseqüènciaestroba"gravada"enelcorrógiratori, querealmentésunatranscripciódelapartituraenformadedades(cadapivotcorrespondriaa unesdeveniment).Anàlogamentalfuncionamentdelacaixademúsicatrobemlapianola, encaraqueenaquestcaslaseqüènciaestrobaenelcartóperforat. Elsprimersseqüenciadorselectrònicsvanaparèixerenelsanys1970ierenanalògics, igualqueelsprimerssintetitzadors.L'interfíciequeutilitzaveneral'anomenatCV/Gateo controlpervoltatgeiconsistiaaenviarimpulsosdecorrentcontinuambunnivelldetensióen
Conceptesprevis Seqüenciador 16 funciódel'alturadelanota.Erenmoltlimitatsiardusdeprogramar;noméspermetien controlarunaparellalmateixtempsitenienpocscompassosdisponibles.L'apariciódel sistemaMIDIen1983il'avançdelatecnologiadigitalenmatèriamusicalvansuposaruna vertaderarevolució.Vaserenaquestpuntquanvancomençaracomercialitzar‐seelsprimers seqüenciadorsdigitals(físics)iprogramesseqüenciadorsperaordinadors,quehananat guanyantcomplexitatiprestacionsambelpasdelsanys. ElsseqüenciadorsactualsmespopularssónCubasis,MusicStudio,MicroLogic,Cubase, CakewalkiLogicentrealters. 2.3.2Funcionament Elfuncionamentbàsicd'unseqüenciadorenformad'aplicacióinformàticapassaper unaseccióprincipalonesvisualitzentoteslespistes,oncadapistacorresponaunsooauna fontsonoraexternaielsparàmetresquelesafectendeformaglobalcomelvolum, l'entonació,elpanorama,oelcanalMIDI,aixícomelscontrolsdereproducció(play,stop, loop,tempo,etc)ilesfuncionsbàsiquesdecopiariapegar,mute(silenci),moureparts, fusionarparts,etc.Pelquefaal'ediciótrobemdiversesseccions,sentlesmésrellevantsel corródepiano,lapartituresilallistad'esdeveniments. • Corródepiano:Éslaformad'ediciómésestesa.Consisteixenunteclatvirtualadjunta unaquadrículaonesrepresentenelscompassos,almateixtempsestansubdividitsen unaquantitatpreestablida(blanques,negres,corxeres,semicorxees,etc).Laformade compondreésdibuixantliteralmentlesnotes,variantl'alturailaduradasobrela quadrícula.Coms'apreciaelfuncionamentésmoltsemblatald'unapianola. • Partitures:Mésestesaenusuarisdeformacióclàssicaiacadèmica.Comelnomindica, laseuaformad'edicióéssobreunpentagramaamblasimbologiapròpiadelsolfeig.És precísdirquementreesvacomponent,independentmentdelaformad'edició,el programacreaautomàticamentlapartituracorresponent. • Llistad'esdeveniments:Éselpropicodifontdeprogramació.Ésútilal'horade modificarpuntualmentalguntipusd'esdevenimentenconcret,sobretot,elsqueno afectenal'alturaoaladuradadelanota(aftertouch,modulació,portamento,nivells d'efecte,etc.) figura11.Esquemadelúsd'unseqüenciador
Conceptesprevis DAW 17 2.4DAW Latraduccióliteralde"DigitalÀudioWorkstation"és:Estaciódetreballperaàudio digital,elqualésunsistemaelectrònicdissenyatperagravar,editarireproduiràudiodigital. UnadelescaracterístiquesclaudelesDAWsésl'habilitatdemanipularlliurementsons gravats,semblantaunprocessadordetextosmecanografiatsqueespodenmanipularles paraules. FabricantsidesenvolupadorsusentambéeltermeEstudi(Studio)peradir‐nosquela seuaaplicacióestractad'unentornonrealitzartreballsbasatsenl'àudiodigital. Elterme“DAW”esrefereixsimplementaunacombinaciódesoftwared'àudio multipistaiunhardwared'àudiod'altaqualitat.Aquestúltimésunaunitatdeconversióde senyalsd'àudiod'analògic‐digitali/odigital‐analògic.Perexemple,unaestaciódetreballpot tenirvuitentradesd'àudio,iduesoméseixidesd'àudioperalsmonitorsoacarreramentdel senyalaaltresdispositius.Elssistemespodentenirnomésunparelld'entradesieixidamono. Unconvertidorprofessionald'analògic‐digitaltélamateixafuncióqueunatargetadeso,però generalmentdemajorqualitat. 2.4.1Història LaprimeraestaciódetreballperaàudiodigitalvaserdesenvolupadaperSoundstream afinalsdelssetanta,utilitzantunequipamentdigitalPDP‐11enunaminicomputadorai executantunsoftwarepersonalitzatanomenat“DAP”(Processadord'àudiodigital)pera l'ediciódigitald'àudioiefectesdeso.Unemmagatzemamentd'oscil∙loscopiqueestava connectatalaminicomputadoraactuavacomapantallaperamostrarlaformadel'ona d'àudio. figura12.PDP‐11 En1981,l'enginyerdegravacióRogerNicholsconstruíunaestaciódetreballd'àudio digitalambelseupropidisseny,utilitzantunbusS‐100.Aquestcomputadorestavabasatamb Micropolis8”ambundiscdurde32MBperal'emmagatzemamentdelesdadesdel'àudio
Conceptesprevis DAW 18 digital.RogerNicholsvausaraquestsistemadurantlagravacióiproducciódel'àlbumde DonaldFagenanomenat“TheNightfly”en1982. Afinalsdelsvuitanta,elsordinadorsAppleMacintoshiCommodoreAmigalvan començaratenirungranconsumperquèteniensuficientpoderperamanejarlatascad'edició d'àudiodigital.MacromediaSoundeditvaserelprimersoftwared'ediciód'àudioqueva aparèixerperalMacintoshen1986,peròelconcepteesvaferpopularperunaempresa anomenadaDigidesign,queen1987vapresentarundelsprimersequipsipaquetsdesoftware peralacomputadorapersonald'Applequetambéserviaperal'ediciód'àudio.Elsoftwareva seroriginàriamentanomenatSoundToolsiméstardvaseranomenatProTools.Aquestvaser elpredecessordelanovaindústriaestàndarddelsistemaProTools. Apartird'aqueixmoment,lamajoriad'estacionsdetreballperaàudiodigitalesbasen enAppleMacintosh(ProTools,StuderDyaxis,SonicSolutions).PeraversionsdeMicrosoft Windowsvacomençarapartirdel'any1992,perempresescomSoundscapequeméstardva adquirirMackie,desprésSSL,imestardSadieiSpectralSyntesis.Totselssistemesenaquest momentutilitzenunhardwarededicatalprocessamentd'àudio. En1994,unaempresaanomenadaOSC,juntambelstècnicsdeDigidesign,vallançar unaediciód'ungravadorieditordequatrepistes,ambunsoftwareanomenatDECKII.El primersoftwarebasatenWindowsvaserproducted'ÀudioWorkshop(SAE)ieracapaçde gravar,editarimesclarquatrepistesd'àudio.Esvaconvertirenunaeinamoltusadaenles emissoresderàdiodelsEE.UU. 2.4.2Actualitat Músicsicompositorshantingutsempreundesigd'integrarequipsestèreo,giradiscos, aparellsdegravació,teclatsMIDIifinsitotlesguitarreselèctriquesambelsordinadors. Ordinadorspotentsbasatseneinesdecomposicióvancomençaraaparèixerambl'AtariSTi Amiga.Entusiasmats,vancontinuarcercanteinesperalacreaciódetasquesd'àudiouna miquetamésintegrades,mésfàcilsd'usarid'altrendiment. Quasiqualsevolordinadorpersonalambunsoftwareambmultipistaiediciópot funcionarunpoccomunDAW,jaqueeltermeesrefereixalssistemesinformàticsquetenen unhardwareambunaaltaqualitatexternadeconvertidord'analògic‐digitalidigital‐analògic,i alguntipusdesoftwared'àudiocompodenser:Cubase,Nuendo,LogicPro,ProTools,Adobe Audition,Sadie5,SonySoundForge,Samplitude,soundscape,SONAR,ACIDPro,FLStudio (anteriormentFruityloops),AbletonLive,TracktionoDigitalPerformer,algunsdelsqualssón delliuresoftwarecomAudacityiArdour.Amésdenecessitartargetesdesod'altagamma,es requereixtambéunagranquantitatdememòriaRAM,CPUràpidailliureidesuficientespaien eldiscdur. Sóndiverseseinesenquadradesenunaaplicaciócentralenquèsolenestarpresents: elmescladorotaulademescles,seqüenciador,caixesderitmes,etc..Pernormageneral,solen admetrel'ampliaciódelsseuscomponentspermitjàdeplug‐ins.Aqueststéunformattalcom VST,DX(Microsoft)oRTAS(ProTools). 2.4.3Varietats LesDAWsgeneralmentespodentrobarenduesvarietats:
Conceptesprevis DAW 19 • ComputadorsbasatsenDAW:aquestsconstendetrescomponents:uncomputador, unconvertidoranalògic‐digitalidigital‐analògiciunsoftwared'ediciód'àudiodigital. Lacomputadoraactuacomunamfitriódelatargetadesoielsoftware,iproporciona unapotènciadeprocessamentperal'ediciódel'àudio.Latargetadesoactuacomuna interfícied'àudio,normalmentamblaconversiódesenyalsanalògicsd'àudioaformat digital.Elsoftwarecontrolaelsdoscomponentsdehardwareiproporcionauna interfícied'usuariperapermetrelagravacióiedició. • SistemesDAWintegrats:Consistiràenunataulademescles,unasuperfíciedecontrol, unconvertidord'àudioiunemmagatzemamentdedadestotenunsoldispositiu.Els sistemesIntegratDAWserenméspopularsabansquelescomputadorespersonals forenproupoderosesperaexecutarsoftwareDAW.Comlapotènciadelsordinadors estàenaugmentielpreuestàdisminuint,lapopularitatdelscostosossistemes integratsesvareduint. 2.4.4Ediciólinealinolineal Enl'àreadelamultimèdia,s'enténcomamitjàlinealaquellqueésequivalentauna cinta(d'àudioodevídeo)enelqualnoespotreordenarelmaterialeneltempsniinserirnous contingutssenseesborraraltrescontingutsprevis.Totaixòafectalamaneradetreballaramb elmitjà.Perexemple,l'edicióenelsmitjanslinealsnoofereixlapossibilitatdedesferl'última operació,nidereplicarcontingutsenposicionsdiferentsdelacinta. Enelcasparticulardel'àudio,elsmitjanslinealssónnormalmentcintes.Aquest sistemad'emmagatzemamentproporcionaunaoméspistes,cadaunad'ellesequivalentauna cintamonoaural.Lespistesestandisposadesdeformaparal∙lelaenlacintaipassenper damuntd'unconjuntdetantscapçalsmagnèticscomapistes.Espotobservaralafigura13. figura13.Tascamde16pistes L'accéséssimultaniatoteselles,encaraquecadapistaadmetgravacióoreproducció independent.Lagravaciód'unapistanoafectalesaltres,peròesborraelcontingutprevidela pistaenqüestió.Enelvocabulariusualdel'àudio,esdiuqueunapistaestàarmadaquanel
Conceptesprevis DAW 20 capçalcorresponentestàpreparatperagravar.Alafigura14,espotvoreunesquemadeles pistesd'unacintaielseupasperdamuntdelscapçals. figura14.Pistesd’unacinta Alafigura15alaespotvoreunafotodelscapçalsd'unaunitatStuderde24pistes. figura15.UnitatStuderde24pistes Elsmitjansnolineals,generalmentbasatsenundiscdurambunsistemad'arxius, ofereixenunainterfíciesemblantalacinta,perquèdonenlamateixasensaciódeseqüència temporal;peròenrealitatéslaimatgeconstruïdaperl'entorndetreballapartird'una estructuradedadesquepermetaccésdirecteiflexiblealscontinguts.Enunmitjànolineal, l'edicióésnodestructiva:lareordenacióilareplicaciódelmaterialsónoperacionssenzillesi l'esborramentésreversible.Enelssistemesmodernsdeproducciód'àudioidevídeo,elmedi ésnolineal. Centrant‐noseneltreballambàudio,lapistacontinuasentunaunitatperales operacionsdereproduccióigravaciódelsistema.Laimplementaciód'unapistas'aconsegueix mitjançantunomésarxiusd'àudio,dinsdelsqualsesdefineixenregionsosegments.Lapista ésunacuelistollistadereferènciesalesregions.Lafigura16il∙lustralaidea:enunapista apareixensisfragmentsdistintsnumerats,und'ellsrepetit.Laregió1corresponaunarxiu completA,larestacorresponadiversosfragmentsdistribuïtsentresarxiusB,CiD.Observa comlamateixaregió3apareixduesvegadesalapista,icomlesregions5o6sesolapen parcialmental'arxiuD.Larestadelapistaéssilenci.
Conceptesprevis DAW 27 figura25.Aplicaciódelcanald’efectes Elsenviamentsalscanalsd'efectessolenserdetipuspostfader,perquès'enténquela quantitatdesenyalenviadadesdelcanaldepistahadeserproporcionalalfader. Avegadesésnecessariescoltarunamescladistintaperraonsdeproduccióopertocar endirecte.Perexemple,pothaver‐hiunapistadereferènciaquedueltempsquenoapareix enlamesclaprincipal,queelsmúsicsqueestangravanthandesentirdurantlagravació d'altrespistes.Elprocedimentméscòmodeconsisteixatriarunbusambeixidaaexteriori enviar‐lisodesdelespistesd'interès.Perexemple,aunbaixistaqueestigagravantuncançó, nomésambsentirelritmedelabaterialiserviria,jaquesolsliinteressaelanar‐hi acompanyat.Elsenviaments,arahaurandeserprefader.
Conceptesprevis DAW 28 figura26.Mesclaalternativa Quanhihamoltespistesquehandesercontroladesencomú,potserconvenient agrupar‐lesmitjançantbusos.Lespistesamblesveusdelsfigurantsenunaescenade pel∙lícula,lespistesdelabateriad'ungrupderock,lasecciódeventd'ungrupdemúsica,tots ellsestrobenenaquestcas.Peraformarungrup,esdirigeixl'eixidadelscanalsdepista afectatscapaunbusinternambelseucanalauxiliar. figura27.Grupsdepistes
Conceptesprevis DAW 29 D'aquestamanera,hihadosnivellsdecontrol:acadapistaespotaplicarequalitzaciói efectesindividuals,amésdelpropivolumdinsdelgrup,ialgrupselipodenaplicarefectes comunsivolumgeneral.
Entorndetreball Cubase 30 3.Entorndetreball 3.1Cubase Cubaseésunprogramaperal'ordinadordeproduccióigravaciómusical.Elprograma ofereixlagravació,produccióimescladesonsafideferlamúsicaperalaseuadistribucióen CDoInternet.Cubase,comhemexplicatabansésunaestaciódetreballd'àudiodigital. Cubasevainiciarlaseuavidaafinalsdels80comunseqüenciadorieditorMIDI.El programa,originàriament,vaserdesenvolupatperal'Atari_ST.Méstardesvaferlaversióper aAppleMacintoshiamitjandelsanys90peraMicrosoftWindows. ElCubaseoriginalempravaunsistemaoperatiuanomenatMROS(MIDIReal‐estafe OperatingSystem)quecorriadavallelpropisistemaoperatiunadiu.Permetiaexecutar diversesaplicacionsMIDIal'ordinadoripassarlesdadesentreaquestesatempsreal.ElMROS notreballavabéenWindows3.0,jaqueaquestnovaserprevistperaaplicacionsentemps real.Noobstantaixò,elssistemesoperatiusmodernsestandissenyatsperasuportar aplicacionsmultimèdia,aixíquelesversionsactualsdeCubasenousenMROS. ElllançamentdeCubaseÀudioen1991peral'AtariFalconvaobrirunabretxaenla tecnologiadeprogramesDSPposantal'abastdomèstic,lamanipulaciód'àudioentempsreal senselanecessitatdecostosestargetesaddicionals,comeraelcasdelcostósProToolsialtres sistemessemblants. Elfuncionamentbàsicéselsegüent: Tenimunapantallaambunesquantespistes(àudio,MIDI,Bateries,Pistesmestres...). Alespistesd’àudiopodemgravarqualsevoltipusd'àudio(guitarres,veu,pianos...)controlarel seuvolum,panorama,equalitzacióiefectes. Unsdelsavantatgesd'aquestprogramaésquequalsevolmodificacióquefemsobrela gravacióésnodestructiva,ésadirlesgravacionsqueestanenlesdiferentspistesmainoes modifiquen,sinóqueenqualsevolcosaquehifemCubasecalculaentempsrealelresultatper areproduir‐la.Així,qualsevolefecteoequalitzacióquefemsempreseràtotalmentreversible,i enspermetanarprovantelsmilersd'efectesdelsqualsdisposem,unaun,omoltsalmateix tempssensehaverdepreocupar‐nospernodestruirlanostrapreadagravacióoriginal. Amés,comportamésavantatgesencalcularelresultatentempsreal,jaquesivolem gravaruntrosd'àudioidesprésrepetir‐loenunaltremomentdelacançó,simplementtallem lagravacióentrossostotutilitzantcopiar/apegar,inocreaunnouarxiud'àudio,sinóqueen tempsreallligdel'original. AlespistesdeMIDI,elqueesgravaéssodeformatMIDI,ésadirqueesgravacomsi foraunapartitura.Comjahemexplicatanteriorment,ofereixelgranavantatgequel'arxiu ocuparàmoltpocespai,peròtéeldesavantatgequeésunsistemaaltamentdependentdel hardwareques'usaràperareproduirlespartitures.
Entorndetreball Cubase 31 Entractar‐sedepartitures,ambCubasenocaldisposard'uninstrumentMIDIpera gravar‐les,sinóquelespodemcompondrenosaltresmateixosamàjaqueperaaixò,Cubase disposad'unEditordePatrons,semblantalqueseriacompondreambpentagrames,peròamb unafilosofiaradicalmentdistinta,méssenzillaimésintuïtiva. SiSteinberghaaconseguitelnivelldeprestigiquetéésperunacosa:Cubasenoes limitanomésagravar,compondreimesclar,sinóquedisposad'unampliconjuntde funcionalitatsperacadatipusdepista,iunad'elleséslaquehafetfamósaaquestproducte: Elsplugins. Elspluginssónxicotetsprogramesques'incrustenenelpropiCubase.Hihadostipus: Elspluginsd'efectesielsinstrumentsvirtuals. Elspluginsd'efectessónexclusiusperalespistesd'àudio,iamplienelssetd'efectes quepodeminseriraunapistad'àudio.Cadapluginéstotalmentconfigurable.Perexemple,un plugindedistorsióperaguitarrapodemconfigurarelto,elguany,entrada,eixida,etc...Pera undereverberació,ladistància,lagrandàriadelasala"virtual"...Caldirquehihamilionsde pluginsimoltsensónrealmentespectaculars.AquestsestrobenperInternetimoltssón comercials,encaraquehihaaltresgratuïts. Elspluginsd'instrumentsvirtualssón,comelseupropinomindica,instruments virtuals.SuposemquehemcreatunapistaMIDI,ihifemunapartituraperaunviolíinotenim capsintetitzadorMIDIcapaçdereproduirunviolí.Llavors,podeminstal∙larunpluginquesiga unviolívirtualiescoltaríemelviolí.Igualqueperalviolí,hihainstrumentsmusicalsperala bateria,baix,piano… PeranosaltresCubaseésunproducterealmentmeravellósiexcepcional,amblagran virtutdeseraptetantperaprofessionalscomperaprincipiants,alcontrarid'altresprogrames comProtools,consideratelmillor,peròmoltdifícildemanejariderequerimentstècnicsde hardwaremoltexigentsicars.Cubasefuncionaambqualsevoltargetadesoiambqualsevol versiódeWindows,encaraqueésaltamentrecomanableusarWindows2000oXP. figura28.InterfíciedelCubase
Entorndetreball VST 32 3.2VST Steinberg'sVirtualStudioTechnology(Tecnologiad'estudivirtual)otambéVSTésun interfícieperalaintegraciódesoftwared'àudioipluginsd'efectesambelseditorsd'àudioi sistemesdegravació. VSTutilitzatecnologiessemblantsalesdelProcessamentDigitalde Senyalsperapodersimularunestuditradicionaldegravació. UnVSTésunprogramadesoftwareques'executaenunaaplicacióquesuporta aquestatecnologia. Aaquestaaplicaciósel'anomenaVSTHost. Algunsexemplesd'aquestssón Cubase,LogicProoSonar. HihamilersdePluginsVSTquesónrecolzatsperaquestes aplicacions. ElsVSTstenenlacapacitatdeprocessarigeneraràudio,comtambéinteractuaramb interfíciesMIDI. ElsVST'squeprocessenàudios'anomenenefectesVST,ielsencarregatsde generaràudiosónelsanomenatsVSTimitjançantVSTinstrument. VSTestàdisponibleperalssistemesoperatiusWindowsiMacOS. Comqueelsarxius queescreensónarxiusbinarisisóndependentsdelaplataformaons'executen,unVST compilatperaMacOSnofuncionaràambWindowsiviceversa. AmbelssistemesLinux,poden utilitzar‐seelsarxiuscompilatsambWindowsemprantelprogramaWine. Steinberg'sVSTSDKésunconjuntdeclassesC++basadesenunentornAPIdeC++. El SDKespotdescarregardesdelaseuapàginaweb. Amés,s'hadesenvolupatSteinbergVST GUI,queésunaltreconjuntdeclassesC++,quepotemprar‐seperaconstruirlainterfície gràfica. Hihaclassesperabotons,lliscadors,etc. Caltenirencomptequeentractar‐sede programaciódebaixnivell,l'aspecteilaimatgeéscreadapelpluginfabricant. 3.2.1VSTplugins AmbHardwareidriversadequats,comperexempleunatargetadesoquesuporta ASIO,VSTpluginspodenserutilitzatsentempsreal. ASIOofereixaWindowsunabaixa latència. HihatrestipusdepluginsVST: • InstrumentsVST:ésunpluginVSTquegeneraàudio. Generalment,jasigavirtualo samplerssintetitzadors. • EfectesVST:ésunpluginVSTques'utilitzaperaprocessarunaentradad'àudio,com perexemplel'efectedeldelayoelchorus. Lamajoriadehostspermetenmúltiples efectesencadenats. Moltsd'aquestsefectesestandisponiblescomadescàrregues gratuïtesodecomprapertotalaxarxa. • EfectesMIDIVST:ésunpluginVSTques'utilitzaperaprocessarmissatgesMIDIpera l'acarreramentdelesdadesMIDIentrealtresinstrumentsomaquinariVST. Per exempleperatransportaroperacreararpegis. 3.2.2ClasseAudioEffect Unefected'àudioésunainstànciadelaclasseAudioEffectX,queésunaextensiódela classebaseAudioEffect. Elperfiléselsegüent: AudioEffectX::AudioEffectX(audioMasterCallback audioMaster, VstInt32 numPrograms, VstInt32 numParams)
Entorndetreball VST 33 Alperfilespotobservarqueselihadepreveureelnombredeparàmetres (numParams)iprogrames(numPorgrams)quetindràelnostreefecte. Perexemple,l'efecte dedistorsiósoltenirdosparàmetres,onescontrolaelvalordellindarperaproduirladistorsió ielguany. Elprogramaésunpreset,ésadir,uncasparticulardevalorsdelsparàmetresqueté unautilitatconcreta. Perexemple,espotdefinirelprograma“net”peratocarlaguitarra sensedistorsió,ipertantelvalordellindarestariaenelmàximperquènohagueradistorsió; desprésespotdefinirelprograma“distorsió”onelvalordellindarestigaenunvalormínim perquèexistiscaladistorsió. Alperfilespotobservardiversoselementscom: • audioMaster:ésunafuncióquelapassal'hosteques'encarregaràdeldiàlegamb l'efecte. • VstInt32:éseltipusnumèricsencerde32bitsdeclaratperconveniènciaperaferel codiindependentdelaplataforma. PeracomençaraprogramarunefecteVSTbastad'implementarelsmètodesdelaclasse AudioEffectXqueesmostrenacontinuació: Class Efecte : public AudioEffectX { public: Efecte (audioMasterCallback audioMaster); ~Efecte (); //---from AudioEffect----------------------- virtual void processReplacing (float** inputs, float** outputs, VstInt32 sampleFrames); virtual void setProgram (VstInt32 program); virtual void setProgramName (char* name); virtual void getProgramName (char* name); virtual bool getProgramNameIndexed (VstInt32 category, VstInt32 index, char* text); virtual void setParameter (VstInt32 index, float value); virtual float getParameter (VstInt32 index); virtual void getParameterLabel (VstInt32 index, char* label); virtual void getParameterDisplay (VstInt32 index, char* text); virtual void getParameterName (VstInt32 index, char* text); virtual void resume (); virtual bool getEffectName (char* name); virtual bool getVendorString (char* text); virtual bool getProductString (char* text); virtual VstInt32 getVendorVersion () { return 1000; } virtual VstPlugCategory getPlugCategory () { return kPlugCategEffect; } Perapodercrearunefecte,calderivar‐lodelaclasseAudioEffectX. Enelseu constructorcaldràdefinirelnombred'entradesieixidesiinicialitzarunasèriedeparàmetres. Efecte::Efecte(audioMasterCallback audioMaster) :AudioEffectX(audioMaster, num_programas, num_parametros) { setNumInputs(n); setNumOutputs(m); setUniqueID(nombre); canProcessReplacing(); canDoubleReplacing(); }
Entorndetreball VST 34 Taula3.Funcionsdeconfiguracióenlainicialitzaciód'unVST virtualvoidsetNumInputs(VstInt32inputs); Estableixelnombred'entradesqueel pluginmanejarà. Aquestvaloresfixaen elterminideconstruccióinoespot canviarfinsqueelpluginesdestruïsca. virtualvoidsetNumOutputs(VstInt32outputs); Estableixelnombred'eixidesqueel pluginmanejarà. Aquestvaloresfixaen elterminideconstruccióinoespot canviarfinsqueelpluginesdestruïsca. voidAudioEffect::setUniqueID(VstInt32aneu); Aquestafuncióestableixunnúmero d'identificacióexclusiu. L’hosteutilitza açòperaidentificarcadaplugin. virtualvoidcanProcessReplacing(boolstate= true); IndicaqueprocessReplacingpot utilitzar‐se. EnVST2.4ésobligatori. virtualvoidcanDoubleReplacing(boolstate= true); IndicaqueprocessDoubleReplacingestà implementat. virtualfloatgetSampleRate(); Tornal'actualSampleRate. Enelcasdeldestructor,aquestéstrivial: Efecte:~Efecte() { } 3.2.3Elprocésnumèric LesfuncionsencarregadesdelprocésnumèricsónprocessReplacingi processDoubleReplacing. Aquestesfuncionshanderealitzarelmateixalgoritme,però manejanttipusnumèricsdistints,ambfloatidouble. Elprogramahosteseràl'encarregatde triarunadelesduesfuncionssegonseltipusdedadesqueestigamanejant. Eltipusdedadesfloatestàcompostper32bits,itéunrangderepresentació [1.17549e‐38,3.40288e+38],suportant6dígitsdeprecisió. L’altretipusdedadesqueespotempraréseltipusdedadesdouble,elqualestà compostper67bits,itéunrangderepresentació[2.22507e‐308,1.79769e+308],suportant15 dígitsdeprecisió.
Entorndetreball VST 35 Durantelprocésnumèric,s'handetractarunnombresampleFramesdemostresper cadaunadelesentrades,jaqueelmètodetéunamatriudepuntersalesdadesd'entrada (inputs)alsqualsse’lsaplical’algoritmedeprocessamentdelsenyal,quan,unavegada finalitzats'escriuelresultatenunbufferd'eixida(outpups)ireprènl'operació.Principalment, aquestprocésseràdutatermeperunbuclewhile(‐‐sampleFrames>=0)iterantencada framedemostra. Elrangderepresentaciódelesentradesieixidesés[‐1.0…+1.0]. 3.2.4Elsvalorsenl'interfíciegráfica Alsparàmetresd'entradacalassociar‐losuníndex,peraaixípoderutilitzar‐losen moltesdelesfuncionsqueexplicaremacontinuació. Enlainterfíciegràfica,cadaparàmetrehauràdetenirelseunom,iperaaixòs'utilitza lafunciógetParameterName. Comelsparàmetresd'entradaestannumerats,unapossible utilitzacióserialasegüent: void Efecte::getParameterName (VstInt32 index, char* label) { switch (index) { case KParametre1 : vst_strncpy (label, “Nom parametre 1”, kVstMaxParamStrLen); break; case KParametre2 : vst_strncpy (label, “Nom parametre 2”, kVstMaxParamStrLen); break; } } Perquèpugaaparèixerelvalordecadaparàmetreenlapantallaiaixípoder‐liferles conversionsnecessàries,s'utilitzalafunciógetParameterDisplayd'aquestamanera: void Efecte::getParameterDisplay (VstInt32 index, char* text) { switch (index) { case KParametre1 : dB2string(valor1,text, kVstMaxParamStrLen); break; case KParametre2 : int2string(valor2,text, kVstMaxParamStrLen); break; } } Siensn’adonems'utilitzenunesfuncionsdeconversióentreunitats. Aquestes funcionss'anomenenhelpers,iserveixenperalagestiód'entrada/eixidadelsparàmetres. Els helperssónelssegüents: virtual void dB2string (float value, char* text, VstInt32 maxLen); virtual void Hz2string (float samples, char* text, VstInt32 maxLen) virtual void ms2string (float samples, char* text, VstInt32 maxLen); virtual void float2string (float value, char* text, VstInt32 maxLen);. virtual void int2string (VstInt32 value, char* text, VstInt32 maxLen); inline char* vst_strncat (char* dst, const char* src, size_t maxLen); Unaaltrafuncióempradaéslautilitzadaperaindicarlesunitatsdecadaparàmetre, peraaixòs'utilitzalafunciógetParameterLabel,iespotutilitzardelamanerasegüent: void Efecte::getParameterLabel (VstInt32 index, char* text) {
Entorndetreball VST 36 switch (index) { case KParametre1 : vst_strncpy (label, “Unitat1”, kVstMaxParamStrLen); break; case KParametre2 : vst_strncpy (label, “Unitat2”, kVstMaxParamStrLen); break; } } 3.2.5Obtenciódelsparàmetres Desdelnostrepuntdevistadeprogramador,elsvalorsdetotselsparàmetressónun nombrerealdefinitenl'interval[0.0…1.0]. Enelprogramahosteensixunabarrapera modificarelvalord'unparàmetre.Internament,quanelselectordelabarraestrobaa l'esquerradeltot,val0.0,i,quanestrobaaladretadeltot,val1.0. Perapodertreballar,hem desubministraruncodiquetransformeelvalordelaposicióenlabarraenvalorsque nosaltrespuguemtreballar. Peraaixò,tenimlafunciósetParameter,queésonapareixelcodi peraferl’esmentadaconversió. Aquestafuncióésinvocadaperl'hostecadavegadaque l'usuarimogalabarradecontrol. Unpossibleúsd'aquestafuncióseria: void Efecte::setParameter (VstInt32 index, float value) { switch (index) { case kParametre1 : ValorPrivat1 = value * 100; break; case kParametre2 : ValorPrivat2 = VMin * exp(log(VMax/VMin)*value); break; } } Igualment,ésnecessaricodificarelmètodeinvers,elqualhadesercapaçdepoder convertirunvalord'unavariableenunaposicióenlabarradecontrol. Peraaixòfemúsdela funciógetParameter. Unpossibleússeriaelsegüent: float Efecte::getParameter (VstInt32 index) { float value; switch (index) { case kParametre1 : value = ValorPrivat1 / 100; break; case kParametre2 : value = (ValorPrivat2 - VMin) / (VMax - VMin); break; } }
Col∙lecciódeplug‐ins Distorsió 43 figura31.DistorsióexecutataCubase Potsescoltarunexempled'aquestefecteen/exemples/distorsio.mp3.
Col∙lecciódeplug‐ins Delay 44 4.3Delay 4.3.1Descripció Eldelay(retardenvalencià)ésl'efectequeconsistixenlamultiplicacióiretard modulatd'unsenyalsonorpelqualunavegadaprocessatelsenyalésmesclatambl'original. L'úsdeldelayéscomúenlaindústriadiscogràficaitambémoltutilitzatperguitarristes elèctrics. Encaraqueaquestefectes'anomenedelay,podemferambelldosefectesdesomolt semblants:peruncostateldelaypròpiamentdit,iperunaltrecostatl’Echo(eco). Totsdosesdiferencienúnicamenteneltempsenquès'escoltenelsretardsdelssons, jaqueeldelaytélafuncionalitatdedonarcosalso,mentrequeelecotélafuncionalitat d'enriquirelritme.Peraixòelsretardsdecurtaduració(<200mil∙lisegons)podem denominar‐losdelay,mentreelsretardsperdamuntdels200mil∙lisegonselsconsideremeco. 4.3.2Paràmetres Elsparàmetresperautilitzaraquestefectesón: ‐ Delay:Enspermetdeterminareltempsderetarddesd’1mil∙lisegonsfinsa200 mil∙lisegonsenescalalogarítmica. ‐Dry/Wet:Estractad'uncontrolperamesclarelsenyaloriginalielsenyaldel'efecte deso.Enlapràctica,télaseuafuncióperaubicarelsodinsdelamesclamusical. 4.3.3Operació EldiagramadeblocsespotobservarenlaFigura32.Comespotapreciar,elsenyalpot recórrerdoscamins.L'efectedelretardl'anemaimplementarambunsimplebuffercircular ambunalongitudfixadaperunretardmàximde200mil∙lisegonsicontrolatpelretard sol∙licitatperl'usuari.Elcodiutilitzatperacalcularlaposicióonhemd'agafarelsenyal retardatéselsegüent: //***** Calcul de la posició on es trobarà el frame del retard *****// int posicionretardo = posicion-delay; if (posicionretardo<0) { posicionretardo= L+posicionretardo; } figura32.DiagramadeblocsdelefecteDelay ElbuffercircularespotobservarenlaFigura33.
Col∙lecciódeplug‐ins Delay 45 figura33.Buffercircular Llavors,l'operaciód'eixida,unavegadacalculadaquinaéslaposiciódelsenyald'eixida, ésmoltfàcil,nomésbastadesumaraquestdossenyalsambelpercentatgedelparàmetre wet/dry,acíespotobservarambelcodi. *out1++ = float(inleft*(1-(fDryWet/100))+ buffer1[posicionretardo] * (fDryWet/100.0)); *out2++= float(inright*(1-(fDryWet/100))+ buffer2[posicionretardo] * (fDryWet/100.0)); Elresultatfinaldelainterfíciegràficadepéndel'hosteambquès'executeelplugin.Es potobservarelresultatutilitzantl'hosteSteinbergCubaseenlaFigura34. figura34.EfectedelayexecutataCubase Potsescoltarunexempled'aquestefecteen/exemples/delay.mp3.
Col∙lecciódeplug‐ins Eco 46 4.4Eco 4.4.1Descripció L'ecol'anematractarcomunefecteidènticaldelayexplicatanteriorment.L'única diferènciaestrobaqueelrangderetardestrobaentre200mil∙lisegonsi4segons.Comjaho havíemexplicatanteriorment,eldelaytélafuncionalitatdedonarcosalso,mentresquel'eco télafuncionalitatd'enriquirelritme. Perquènosigatanidènticaldelay,inseriremelparàmetrederetroalimentació (Feedback),jaqueambaquestparàmetrepodremcontrolarelnombrederepeticionsqueli donaremal'eco.Commésaltsigaaquestvalor,mésllargseràl'efected'eco.Sielposemal màxim,lesrepeticionsseraninfinites. 4.4.2Paràmetres Elsparàmetresperautilitzaraquestefectesón: ‐ Delay:Enspermetdeterminareltempsderetarddesde200mil∙lisegonsfinsa4 segonsenescalalogarítmica. ‐Dry/Wet:Estractad'uncontrolperamesclarelsenyaloriginalielsenyaldel'efecte deso.Enlapràcticatélaseuafuncióperaubicarelsodinsdelamesclamusical. ‐Feedback:Enspermetdeterminarelnúmeroderepeticionsqueseliaplicaalecoen unpercentatgederepeticions. 4.4.3Operació Eldiagramadeblocsespotobservarenlafigura35.Comespotapreciar,es pràcticamentigualqueeldiagramadeblocsdel’efectedelay,nomésqueaquestinclouel Feedback.Igualment,elsenyalpotrecórrerdoscamins.L'efectedelretardl'anema implementarambunsimplebuffercircularambunalongitudfixadaperunretardmàximde4 segonsicontrolatpelretardsol∙licitatperl'usuari. figura35.DiagramadeblocsdelefecteEco L'operaciód'eixida,unavegadacalculatquinaéslaposiciódelsenyald'eixidaes idènticaldel’efectedelay,enelqualnomésbastadesumaraquestsdossenyalsambel percentatgedelparàmetrewet/dry.Acíespotobservarambelcodi. *out1++ = float(inleft*(1-(fDryWet/100))+ buffer1[posicionretardo] * (fDryWet/100.0));
Col∙lecciódeplug‐ins Eco 47 *out2++= float(inright*(1-(fDryWet/100))+ buffer2[posicionretardo] * (fDryWet/100.0)); L'únicadiferènciaqueexistixelteniuacontinuació,compodeuobservaraquestcodi: //***** Guardem el in actual en el buffer actual *****// buffer1[posicion]=(1-(fFeed/100))*inleft+(fFeed/100)*outleft; buffer2[posicion]=(1-(fFeed/100))*inright+(fFeed/100)*outright; Al'horadeguardarl'entradaenelbuffer,aquestanoésdirectacomesfeiaabans, sinóqueesguardalasumautilitzantelpercentatgedelparàmetrefeedbackdel'entradasense modificarambl'eixidaenquèhasigutaplicatl'efectedel'eco. Espotobservarelresultatutilitzantl'hosteSteinbergCubaseenlafigura36. figura36.EfecteEcoexecutataCubase Potsescoltarunexempled'aquestefecteen/exemples/eco.mp3.
Col∙lecciódeplug‐ins Chorus 48 4.5Chorus 4.5.1Descripció Ladefiniciódel'efecteChoruséselresultatdemesclarunsenyalsenseprocessaramb unasenyalambvibrato.Enelnostrecas,elresultatseràdemesclarunsenyalretardati modulatperunabaixafreqüènciaambelsenyalsenseprocessar.Aquestefectetépernom Chorusjaques'utilitzaperaferunasolaveuigualquemoltsdeso. ElstempsderetardsutilitzatsperalChorussónalts,ipertantl'efectedelecoés evident.Eldiagramadeblocsespotveureenlafigura1. Elresultatsonord'aquestefecteéselsyrupy,queapareixenmoltesdelesgravacions delsanys60i70. 4.5.2Paràmetres Elsparàmetresperautilitzaraquestefectesón: ‐Dry/Wet:Estractad'uncontrolperamesclarelsenyaloriginalilasenyaldel'efecte deso.Enlapràcticatélaseuafuncióperaubicarelsodinsdelamesclamusical. ‐Guany:Elguany,elpodemutilitzarperacompensaralgunapèrduaenlamodulació delasenyal. ‐DelayFreqüencia:Indicalafreqüènciad’escombratdel’efecte. ‐DelayMin:Establixlaprofunditatmínimadel’efecteenformaderetard. ‐DelayMax:Establixlaprofunditatmínimadel’efecteenformaderetard. 4.5.3Operació Aquestefecteéssemblantalsdosanteriors,jaquecalmodularunsenyalalentit.Pera aixòanemautilitzarlainterpolaciódeLagrange,jaquelafinalitatésqueapartird'unasèrie depunts,puguemobtenirunaequaciódemaneraquelaseuacorbapassepertotsellsotan propcompugaser.Elprimerquecalferéscalcularelscoeficients. nT = 1/44100 * (n++); deltai = (delayMax-delayMin)/2 + delayMin + (delayMax-delayMin)/2 * sin(2 * pi * fFreq * nT); // Delay line emprant Lagrange interpolator di = floorf(deltai) - 1; t0 = deltai - di; t1 = t0 - 1; t2 = t0 - 2; t3 = t0 - 3; b0 = -t1*t2*t3/6; b1 = t0*t2*t3/2; b2 = -t0*t1*t3/2; b3 = t0*t1*t2/6; Seguidamenthauremd’emmagatzemarles4posicionsalentidesqueanemautilitzar: for (int i=0;i<4;i++) { outPoint[i] = (posicion - 1 - di + i); if (outPoint[i] < 0) outPoint[i] += L; else if (outPoint[i] >= L)
Col∙lecciódeplug‐ins Chorus 49 outPoint[i] -= L; listate[i] = buffer1[outPoint[i]]; } Iunavegadatinguemles4posicionsalentidesielscoeficients,noméscalmultiplicar‐ losentreells. feedbackL = (b0*listate[0] + b1*listate[1] + b2*listate[2] + b3*listate[3]); Elresultatfinaldelainterfíciegràficadepéndel'hosteambquès'executeelplugin.Es potobservarelresultatutilitzantl'hosteSteinbergCubaseenlafigura37. figura37.EfecteChorusexecutataCubase Potsescoltarunexempled'aquestefecteen/exemples/chorus.mp3.
Col∙lecciódeplug‐ins Generador 50 4.6Generador 4.6.1Descripció Lafunciód'ungeneradordesenyalésproduirunsenyaldependentdeltempsamb unescaracterístiquesdeterminadesdefreqüència,amplitudiforma.Algunesvegades aquestescaracterístiquessónexternamentcontroladesatravésdesenyalsdecontrol; l'oscil∙ladorcontrolatpertensió(voltage‐controlledoscillatoroVCO)ésunclarexemple. Pera executarlafunciódelsgeneradorsdesenyals'empraalguntipusderealimentació conjuntamentambdispositiusquetinguencaracterístiquesdependentsdeltemps (normalmentcondensadors). Nosaltresconstruiremungeneradorambtrestipusdeformes:sinusoïdal,quadradai triangular. 4.6.2Paràmetres Elsparàmetresperautilitzaraquestefectesón: ‐Freqüència:Onespottriarunafreqüènciaperalgeneradorentre20i20.000Hz. ‐Amplitud:Estriaenpercentatgel'amplituddel'onadelsenyal. ‐ Formadelsenyal:Seseleccionalaformaquetindràelsenyal.Espottriarentre sinusoïdal,quadradaotriangular. 4.6.3Operació Laprimeracosaquecalrealitzaréselcàlculdelafase. fase = fmod(fFrequencia*i,1); i++; Unavegadacalculadalafase,isegonslaformadelsenyalques'hajaseleccionat, s'hauràderealitzarunaoperaciódiferent.Peralaformasinusoïdaléstansimplecom: *out++ = fAmplitud*sin(2*pi*fase); Jaquenomésfafaltal'amplitudquelaseleccional'usuariilafasequejaestàcalculada ambanterioritat. Peralaformaquadrada,caldividir‐hoenduesparts,silafaseésmenorquelameitat osiésmajor.Lesoperacionsperalaformaquadradasónlessegüents: if(fase<0.5) { *out++ = fAmplitud; } else { *out++ = -fAmplitud; } Peralaformatriangularésunpocmesdifícil,jaquecalbasar‐nosenlesformulesde lesrectes.Comespotapreciaralafigura38,hihaduesrectesclaramentdiferenciables,iper tantcaldividirlafaseendosiaplicaracadaunalaformuladelarectay=m*x+b.
Col∙lecciódeplug‐ins Generador 51 figura38.Formatriangular Peralaprimerameitat,calcalcularquinseriaelpendent,queescalculam=∆Y/∆X. ∆Y=2*amplitud∆X=1/2 Unavegadacalculatelpendent,isabentquex=faseib=‐amplitud,noméshauríem d'aplicartotsaquestsvalorsalafórmulay=m*x+b. float m = 2 * fAmplitud / 0.5f; *out++ = m * fase - fAmplitud; Peral'altrameitat,esfariaelmateix,escalculariaelpendentielsvalorsperala fórmulay=m*x+b,quedariaelcodidelamanerasegüent: float m = -2 * fAmplitud / 0.5f; *out++ = m * (fase - 0.5f) + fAmplitud; Elresultatfinaldelainterfíciegràficadepéndel'hosteambquès'executeelplugin.Es potobservarelresultatutilitzantl'hosteSteinbergCubaseenlafigura39. figura39.GeneradoraCubase Potsescoltarunexempled'aquestefecteen/exemples/generador.mp3.
Col∙lecciódeplug‐ins Sintetitzador 52 4.7Sintetitzador 4.7.1Descripció Unsintetitzadorésunaparellquegeneraimanipulasonsartificialspermitjans electrònics,usanttècniquescomlasíntesiadditiva,substractiva,demodulaciódefreqüència, demodelatgefísicomodulaciódefase.Ambaquestartefacteespodencrearsonsnousi tambéreproduirinstrumentsmusicalsconeguts.Laformadel'onageneradaésalteradaenla seuadurada,alturaitimbremitjançantl'úsdedispositius. NosaltresutilitzaremunteclatMIDIdelamarcaEgo‐systems,model25KeyControl (figura40)quetéaquestescaracterístiques: Característiquesfísiques: ‐25teclessensiblessemi‐contrapesades ‐RodesdePitch,ModiDades ‐8botonsrotatiusassignablesi8fadersassignables MIDI: ‐1)1portMIDIUSB(16canals) ‐2)1In/1OutMIDI(16canals) figura40.ControladorEgo‐systems25KeyControl Utilitzemelteclatcomacontroladorperquèéselméspopularperatottipusde sintetitzadors.Ésunafontquesubministratensionsproporcionalsalateclaques'oprimeix. Tambéproporcionatensionsdecontrolperaindicar‐noslavelocitatdepulsaciódelateclaola pressiósobrelamateixa.
Annexos 59 AnnexII balance.cpp //-------------------------------------- // VST Plug-Ins SDK // BALANCE // // Francisco Javier Ripoll Esteve // [email protected] // 13/05/2008 //-------------------------------------- #include "balance.h" AudioEffect* createEffectInstance (audioMasterCallback audioMaster) { return new ABalance (audioMaster); } ABalance::ABalance (audioMasterCallback audioMaster) : AudioEffectX (audioMaster, 1, 1) { setNumInputs (2); // stereo in setNumOutputs (2); // stereo out setUniqueID ('Bal'); // Identificador canProcessReplacing (); canDoubleReplacing (); fBalance = 0; } ABalance::~ABalance () { } void ABalance::setParameter (VstInt32 index, float value) { fBalance = (value*200) -100; } float ABalance::getParameter (VstInt32 index) { float v; v=(fBalance+100.f)/200.f; return v; } void ABalance::getParameterName (VstInt32 index, char* label) { switch (index) { case NumeroProgramBalance : vst_strncpy (label, "Balance", kVstMaxParamStrLen); break; } } void ABalance::getParameterDisplay (VstInt32 index, char* text) { float2string (fBalance, text, kVstMaxParamStrLen); }
Annexos 60 void ABalance::getParameterLabel (VstInt32 index, char* label) { vst_strncpy (label, "%", kVstMaxParamStrLen); } bool ABalance::getEffectName (char* name) { vst_strncpy (name, "Balance", kVstMaxEffectNameLen); return true; } bool ABalance::getProductString (char* text) { vst_strncpy (text, "Balance", kVstMaxProductStrLen); return true; } bool ABalance::getVendorString (char* text) { vst_strncpy (text, "Francisco Javier Ripoll", kVstMaxVendorStrLen); return true; } VstInt32 ABalance::getVendorVersion () { return 1000; } void ABalance::processReplacing (float** inputs, float** outputs, VstInt32 sampleFrames) { float* in1 = inputs[0]; float* in2 = inputs[1]; float* out1 = outputs[0]; float* out2 = outputs[1]; while (--sampleFrames >= 0) { if(fBalance==0.0) { (*out1++) = (*in1++); (*out2++) = (*in2++); } if(fBalance>0.0) { //Dreta float aux=fBalance/100; (*out1++) = (*in1++)*(1-aux); (*out2++) = (*in2++); } if(fBalance<0.0) { //Esquerra float aux=fBalance/100; aux= -aux; (*out1++) = (*in1++); (*out2++) = (*in2++)*(1-aux); } } } void ABalance::processDoubleReplacing (double** inputs, double** outputs, VstInt32 sampleFrames) { double* in1 = inputs[0]; double* in2 = inputs[1]; double* out1 = outputs[0]; double* out2 = outputs[1];
Annexos 61 while (--sampleFrames >= 0) { if(fBalance==0.0) { (*out1++) = (*in1++); (*out2++) = (*in2++); } if(fBalance>0.0) { //Dreta double aux= fBalance/100.0; (*out1++) = (*in1++)*(1-aux); (*out2++) = (*in2++); } if(fBalance>0.0) { //Esquerra double aux=fBalance/100.0; aux= -aux; (*out1++) = (*in1++); (*out2++) = (*in2++)*(1-aux); } } }
Annexos 62 AnnexIII distorsio.h //-------------------------------------- // VST Plug-Ins SDK // DISTORSIÓ // // Francisco Javier Ripoll Esteve // [email protected] // 13/05/2008 //-------------------------------------- #ifndef __ADistorsio__ #define __ADistorsio__ #include "public.sdk/source/vst2.x/audioeffectx.h" enum { kDistorsio = 0, kGain, kNumParams }; class ADistorsio : public AudioEffectX { public: ADistorsio (audioMasterCallback audioMaster); ~ADistorsio (); virtual void processReplacing (float** inputs, float** outputs, VstInt32 sampleFrames); virtual void processDoubleReplacing (double** inputs, double** outputs, VstInt32 sampleFrames); virtual void setProgramName (char* name); virtual void getProgramName (char* name); virtual void setParameter (VstInt32 index, float value); virtual float getParameter (VstInt32 index); virtual void getParameterLabel (VstInt32 index, char* label); virtual void getParameterDisplay (VstInt32 index, char* text); virtual void getParameterName (VstInt32 index, char* text); virtual bool getEffectName (char* name); virtual bool getVendorString (char* text); virtual bool getProductString (char* text); virtual VstInt32 getVendorVersion (); protected: float fGain; float iDistorsio; float fDistorsio; char programName[kVstMaxProgNameLen+1]; float MaxBits; float MinBits; }; #endif
Annexos 63 AnnexIV distorsio.cpp //-------------------------------------- // VST Plug-Ins SDK // DISTORSIÓ // // Francisco Javier Ripoll Esteve // [email protected] // 13/05/2008 //-------------------------------------- #include "distorsio.h" AudioEffect* createEffectInstance (audioMasterCallback audioMaster) { return new ADistorsio (audioMaster); } ADistorsio::ADistorsio (audioMasterCallback audioMaster): AudioEffectX (audioMaster, 1, 2) { setNumInputs (2); // stereo in setNumOutputs (2); // stereo out setUniqueID ('Dist'); // identify canProcessReplacing (); canDoubleReplacing (); MaxBits=1.f; //32767 MinBits=0.0725f; //2376 fGain = 1.f; // default to 0 dB fDistorsio=0.f; iDistorsio=MaxBits; vst_strncpy (programName, "Default", kVstMaxProgNameLen); // default program name } ADistorsio::~ADistorsio () { } void ADistorsio::setProgramName (char* name) { vst_strncpy (programName, name, kVstMaxProgNameLen); } void ADistorsio::getProgramName (char* name) { vst_strncpy (name, programName, kVstMaxProgNameLen); } void ADistorsio::setParameter (VstInt32 index, float value) { switch (index) { case kDistorsio : iDistorsio= MaxBits-value*(MaxBits-MinBits); fDistorsio=value*100; break; case kGain : fGain = value*2; break; } } float ADistorsio::getParameter (VstInt32 index) {
Annexos 64 float v = 0; switch (index) { case kDistorsio : v = fDistorsio/100; break; case kGain : v = fGain/2; break; } return v; } void ADistorsio::getParameterName (VstInt32 index, char* label) { switch (index) { case kDistorsio : strcpy (label, "Distorsio"); break; case kGain : strcpy (label, "Ganancia"); break; } } void ADistorsio::getParameterDisplay (VstInt32 index, char* text) { switch (index) { case kDistorsio : float2string (fDistorsio, text, kVstMaxParamStrLen); break; case kGain : dB2string (fGain, text, kVstMaxParamStrLen); break; } } void ADistorsio::getParameterLabel (VstInt32 index, char* label) { switch (index) { case kDistorsio : strcpy (label, "poca -- molta"); break; case kGain : strcpy (label, "dB"); break; } } bool ADistorsio::getEffectName (char* name) { vst_strncpy (name, "Distorsio", kVstMaxEffectNameLen); return true; } bool ADistorsio::getProductString (char* text) { vst_strncpy (text, "Distorsio", kVstMaxProductStrLen); return true; } bool ADistorsio::getVendorString (char* text) { vst_strncpy (text, "Francisco Javier Ripoll Esteve", kVstMaxVendorStrLen); return true; } VstInt32 ADistorsio::getVendorVersion () { return 1000; } void ADistorsio::processReplacing (float** inputs, float** outputs, VstInt32 sampleFrames) { float* in1 = inputs[0]; float* in2 = inputs[1]; float* out1 = outputs[0]; float* out2 = outputs[1]; float inleft; float inright; float distorsio; while (--sampleFrames >= 0) { inleft = (*in1++); inright = (*in2++); distorsio = iDistorsio;
Annexos 65 if (inleft > distorsio) { inleft=distorsio; } else if (inleft < -distorsio) { inleft = -distorsio; } if (inright > distorsio) { inright=distorsio; } else if (inright < -distorsio ) { inright = -distorsio; } *out1++ = inleft*fGain; *out2++= inright*fGain; } } void ADistorsio::processDoubleReplacing (double** inputs, double** outputs, VstInt32 sampleFrames) { double* in1 = inputs[0]; double* in2 = inputs[1]; double* out1 = outputs[0]; double* out2 = outputs[1]; while (--sampleFrames >= 0) { double inleft = (*in1++); double inright = (*in2++); double distorsio= double(iDistorsio); if (inleft > distorsio) { inleft=distorsio; } else if (inleft < -distorsio) { inleft = -distorsio; } if (inright > distorsio) { inright=distorsio; } else if (inright < -distorsio ) { inright = -distorsio; } *out1++ = inleft*fGain; *out2++= inright*fGain; } }
Annexos 66 AnnexV delay.h //-------------------------------------- // VST Plug-Ins SDK // DELAY // // Francisco Javier Ripoll Esteve // [email protected] // 13/05/2008 //-------------------------------------- #ifndef __again__ #define __again__ #include "public.sdk/source/vst2.x/audioeffectx.h" enum { kDelay = 0, kDryWet, kOut, kNumParams }; class ADelay; class ADelay : public AudioEffectX { public: ADelay (audioMasterCallback audioMaster); ~ADelay (); virtual void processReplacing (float **inputs, float **outputs, VstInt32 sampleFrames); virtual void processDoubleReplacing (double** inputs, double** outputs, VstInt32 sampleFrames); virtual void setParameter (VstInt32 index, float value); virtual float getParameter (VstInt32 index); virtual void getParameterLabel (VstInt32 index, char *label); virtual void getParameterDisplay (VstInt32 index, char *text); virtual void getParameterName (VstInt32 index, char *text); virtual void resume (); virtual bool getEffectName (char* name); virtual bool getVendorString (char* text); virtual bool getProductString (char* text); virtual VstInt32 getVendorVersion () { return 1000; } virtual VstPlugCategory getPlugCategory () { return kPlugCategEffect; } protected: void setDelay (float delay); float *buffer1; float *buffer2; double *buffer1d; double *buffer2d;
Annexos 67 float fDelay, fDryWet,fOut; int delay; int L; long posicion; }; #endif
Annexos 68 AnnexVI delay.cpp //-------------------------------------- // VST Plug-Ins SDK // DELAY // // Francisco Javier Ripoll Esteve // [email protected] // 13/05/2008 //-------------------------------------- #include "delay.h" #include "math.h" AudioEffect* createEffectInstance (audioMasterCallback audioMaster) { return new ADelay (audioMaster); } ADelay::ADelay (audioMasterCallback audioMaster) : AudioEffectX (audioMaster, 1, 2) { L = 8820; //Un segon 44100, 200 mil·lisegons 8820 buffer1 = new float[L]; buffer2 = new float[L]; buffer1d = new double[L]; buffer2d = new double[L]; fDelay = 0.1f; fDryWet = 0; posicion = 0; delay = int(L*fDelay); setNumInputs (2); // stereo input setNumOutputs (2); // stereo output setUniqueID ('ADly'); resume (); // flush buffer } ADelay::~ADelay () { if (buffer1) delete[] buffer1; if (buffer2) delete[] buffer2; } void ADelay::setDelay (float value) { fDelay = float(0.001*exp(value*log(0.200/0.001))); delay= int(fDelay*L); } //void ADelay::setProgramName (char* name) { //vst_strncpy (programName, name, kVstMaxProgNameLen);
Annexos 75 memset (buffer1, 0, L * sizeof (float)); memset (buffer2, 0, L * sizeof (float)); AudioEffectX::resume (); } void AEco::setParameter (VstInt32 index, float value) { switch (index) { case kDelay : setDelay(value); break; case kDryWet : fDryWet = (value*100); break; case kFeed : fFeed = (value*100); break; } } float AEco::getParameter (VstInt32 index) { float v = 0; switch (index) { case kDelay : v = float(log(fDelay/0.002)/(log(4.0/0.002))); break; case kDryWet : v = fDryWet/100; break; case kFeed : v = fFeed/100; break; } return v; } void AEco::getParameterName (VstInt32 index, char* label) { switch (index) { case kDelay : strcpy (label, "Delay"); break; case kDryWet : strcpy (label, "Dry -- Wet"); break; case kFeed : strcpy (label, "FeedBack"); break; } } void AEco::getParameterDisplay (VstInt32 index, char* text) { switch (index) { case kDelay : float2string (fDelay, text, kVstMaxParamStrLen); break; case kDryWet : float2string (fDryWet, text, kVstMaxParamStrLen); break; case kFeed : float2string (fFeed, text, kVstMaxParamStrLen); break; } } void AEco::getParameterLabel (VstInt32 index, char* label) { switch (index) { case kDelay : strcpy (label, "segons"); break; case kDryWet : strcpy (label, "%"); break; case kFeed : strcpy (label, "%"); break; } } bool AEco::getEffectName (char* name) { strcpy (name, "Eco"); return true; }
Annexos 76 bool AEco::getProductString (char* text) { strcpy (text, "Eco"); return true; } bool AEco::getVendorString (char* text) { strcpy (text, "Francisco Javier Ripoll Esteve"); return true; } void AEco::processReplacing (float** inputs, float** outputs, VstInt32 sampleFrames) { float* in1 = inputs[0]; float* in2 = inputs[1]; float* out1 = outputs[0]; float* out2 = outputs[1]; while (--sampleFrames >= 0) { //***** Guardem les entrades en variables*****// float inleft = (*in1++); float inright = (*in2++); //***** Calcul de la posició on es trobarà el frame del retard *****// int posicionretardo = posicion-delay; if (posicionretardo<0) { posicionretardo= L+posicionretardo; } //**** Reproducció amb el in actual i el buffer(posició-retard) ****// float outleft = float(inleft*(1- (fDryWet/100))+buffer1[posicionretardo]*(fDryWet/100)); float outright = float(inright*(1- (fDryWet/100))+buffer2[posicionretardo]*(fDryWet/100)); *out1++ = outleft; *out2++= outright; //***** Guardem el in actual en el buffer actual *****// buffer1[posicion]=(1-(fFeed/100))*inleft+(fFeed/100)*outleft; buffer2[posicion]=(1-(fFeed/100))*inright+(fFeed/100)*outright; posicion++; if (posicion==L) { posicion=0; } } } void AEco::processDoubleReplacing (double** inputs, double** outputs, VstInt32 sampleFrames) { double* in1 = inputs[0]; double* in2 = inputs[1]; double* out1 = outputs[0];
Annexos 77 double* out2 = outputs[1]; while (--sampleFrames >= 0) { //***** Guardem les entrades en variables*****// double inleft = (*in1++); double inright = (*in2++); //***** Calcul de la posició on es trobarà el frame del retard *****// int posicionretardo = posicion-delay; if (posicionretardo<0) { posicionretardo= L+posicionretardo; } //**** Reproducció amb el in actual i el buffer(posició-retard) ****// double outleft = double(inleft*(1.0- (fDryWet/100.0))+buffer1d[posicionretardo]*(fDryWet/100.0)); double outright = double(inright*(1.0- (fDryWet/100.0))+buffer2d[posicionretardo]*(fDryWet/100.0)); *out1++ = outleft; *out2++= outright; //***** Guardem el in actual en el buffer actual *****// buffer1d[posicion]=(1.0- (fFeed/100.0))*inleft+(fFeed/100.0)*outleft; buffer2d[posicion]=(1- (fFeed/100.0))*inright+(fFeed/100.0)*outright; posicion++; if (posicion==L) { posicion=0; } } }
Annexos 78 AnnexIX chorus.h //-------------------------------------- // VST Plug-Ins SDK // CHORUS // // Francisco Javier Ripoll Esteve // [email protected] // 13/05/2008 //-------------------------------------- #ifndef __again__ #define __again__ #include "public.sdk/source/vst2.x/audioeffectx.h" enum { kNumPrograms = 1, kDryWet = 0, kGain, kFreq, kDelayMin, kDelayMax, }; class AChorus; class AChorus : public AudioEffectX { public: AChorus (audioMasterCallback audioMaster); ~AChorus (); virtual void processReplacing (float **inputs, float **outputs, VstInt32 sampleFrames); virtual void processDoubleReplacing (double** inputs, double** outputs, VstInt32 sampleFrames); virtual void setParameter (VstInt32 index, float value); virtual float getParameter (VstInt32 index); virtual void getParameterLabel (VstInt32 index, char *label); virtual void getParameterDisplay (VstInt32 index, char *text); virtual void getParameterName (VstInt32 index, char *text); virtual void resume (); virtual bool getEffectName (char* name); virtual bool getVendorString (char* text); virtual bool getProductString (char* text); virtual VstInt32 getVendorVersion () { return 1000; } virtual VstPlugCategory getPlugCategory () { return kPlugCategEffect; } protected: void setDelayMax (float delay); void setDelayMin (float delay); float *buffer1; float *buffer2;
Annexos 79 double *buffer1d; double *buffer2d; float listate[4]; int outPoint[4]; double feedbackL, feedbackR; float fDryWet,fGain,fFreq,fDelayMin, fDelayMax; float freq; int delayMin, delayMax; int L; int n; long posicion; int sampleCount; }; #endif
Annexos 80 AnnexX chorus.cpp //-------------------------------------- // VST Plug-Ins SDK // CHORUS // // Francisco Javier Ripoll Esteve // [email protected] // 13/05/2008 //-------------------------------------- #include "chorus.h" #include "math.h" AudioEffect* createEffectInstance (audioMasterCallback audioMaster) { return new AChorus (audioMaster); } AChorus::AChorus (audioMasterCallback audioMaster) : AudioEffectX (audioMaster, 1, 5) { L = 44100; sampleCount = 0; buffer1 = new float[L]; buffer2 = new float[L]; buffer1d = new double[L]; buffer2d = new double[L]; //inicialitzem els buffers for (int i=0;i<L;i++) { buffer1[i] = 0.f; buffer2[i] = 0.f; buffer1d[i] = 0; buffer2d[i] = 0; } fGain= 1.f; fFreq = 2.5f; fDelayMin = 0.2f; fDelayMax = 0.3f; fDryWet = 0.5; n=0; posicion = 0; delayMin = int (L*fDelayMin); delayMax = int (L*fDelayMax); setNumInputs (2); // stereo input setNumOutputs (2); // stereo output setUniqueID ('Acho'); resume (); } AChorus::~AChorus () { if (buffer1) delete[] buffer1; if (buffer2) delete[] buffer2;
Annexos 81 if (buffer1d) delete[] buffer1d; if (buffer2d) delete[] buffer2d; } void AChorus::setDelayMin (float value) { fDelayMin = value; delayMin= int(value*L); } void AChorus::setDelayMax (float value) { fDelayMax = value; delayMax= int(value*L); } void AChorus::resume () { memset (buffer1, 0, L * sizeof (float)); memset (buffer2, 0, L * sizeof (float)); AudioEffectX::resume (); } void AChorus::setParameter (VstInt32 index, float value) { switch (index) { case kDryWet : fDryWet = value; break; case kGain : fGain = value*2; break; case kFreq : fFreq = value * 5.f; break; case kDelayMin : setDelayMin(value); break; case kDelayMax : setDelayMax(value); break; } } float AChorus::getParameter (VstInt32 index) { float v = 0; switch (index) { case kDryWet : v = fDryWet; break; case kGain : v = fGain/2; break; case kFreq : v = fFreq / 5.f; break; case kDelayMin : v = fDelayMin; break; case kDelayMax : v = fDelayMax; break; } return v; } void AChorus::getParameterName (VstInt32 index, char* label) { switch (index) { case kDryWet : strcpy (label, "Dry -- Wet"); break; case kGain : strcpy(label, "Ganancia"); break; case kFreq : strcpy(label, "Dealy Freq"); break; case kDelayMin : strcpy (label, "DelayMin"); break; case kDelayMax : strcpy (label, "DelayMax"); break; } } void AChorus::getParameterDisplay (VstInt32 index, char* text) { switch (index) { case kDryWet : float2string (fDryWet*100, text, kVstMaxParamStrLen); break;
Annexos 82 case kGain : dB2string(fGain, text, kVstMaxProgNameLen); break; case kFreq : float2string(fFreq, text, kVstMaxProgNameLen); break; case kDelayMin : float2string (fDelayMin*1000, text, kVstMaxParamStrLen); break; case kDelayMax : float2string (fDelayMax*1000, text, kVstMaxParamStrLen); break; } } void AChorus::getParameterLabel (VstInt32 index, char* label) { switch (index) { case kDryWet : strcpy (label, "%"); break; case kGain : strcpy(label, "dB"); break; case kFreq : strcpy(label, "Hz"); break; case kDelayMin : strcpy (label, "ms"); break; case kDelayMax : strcpy (label, "ms"); break; } } bool AChorus::getEffectName (char* name) { strcpy (name, "Delay"); return true; } bool AChorus::getProductString (char* text) { strcpy (text, "Delay"); return true; } bool AChorus::getVendorString (char* text) { strcpy (text, "Francisco Javier Ripoll Esteve"); return true; } void AChorus::processReplacing (float** inputs, float** outputs, VstInt32 sampleFrames) { float *in1 = inputs[0]; float *in2 = inputs[1]; float *out1 = outputs[0]; float *out2 = outputs[1]; float T = 1/44100; int di=0; double pi = 3.1415926; double nT=0, deltai=0, t0=0, t1=0, t2=0, t3=0, b0=0, b1=0, b2=0, b3=0; while (--sampleFrames >= 0) { nT = 1/44100 * (n++); deltai = (delayMax-delayMin)/2 + delayMin + (delayMax-delayMin)/2 * sin(2 * pi * fFreq * nT); // Delay line emprant Lagrange interpolator di = floorf(deltai) - 1; t0 = deltai - di; t1 = t0 - 1; t2 = t0 - 2; t3 = t0 - 3; b0 = -t1*t2*t3/6; b1 = t0*t2*t3/2; b2 = -t0*t1*t3/2; b3 = t0*t1*t2/6; if (posicion >= L) posicion = 0;
Annexos 83 //Esquerra buffer1[posicion] = fGain*(*in1); for (int i=0;i<4;i++) { outPoint[i] = (posicion - 1 - di + i); if (outPoint[i] < 0) outPoint[i] += L; else if (outPoint[i] >= L) outPoint[i] -= L; listate[i] = buffer1[outPoint[i]]; } feedbackL = (b0*listate[0] + b1*listate[1] + b2*listate[2] + b3*listate[3]); //Dreta buffer2[posicion] = fGain*(*in2); for (int j=0;j<4;j++) { outPoint[j] = (posicion - 1 - di + j); if (outPoint[j] < 0) outPoint[j] += L; if (outPoint[j] >= L) outPoint[j] -= L; listate[j] = buffer2[outPoint[j]]; } feedbackR = (b0*listate[0] + b1*listate[1] + b2*listate[2] + b3*listate[3]); // ixida (*out1++) = (*in1++)*fDryWet + (1-fDryWet) * feedbackL; (*out2++) = (*in2++)*fDryWet + (1-fDryWet) * feedbackR; posicion++; } } void AChorus::processDoubleReplacing (double** inputs, double** outputs, VstInt32 sampleFrames) { double *in1 = inputs[0]; double *in2 = inputs[1]; double *out1 = outputs[0]; double *out2 = outputs[1]; double T = 1/44100; int di=0; double pi = 3.1415926; double nT=0, deltai=0, t0=0, t1=0, t2=0, t3=0, b0=0, b1=0, b2=0, b3=0; while (--sampleFrames >= 0) { nT = 1/44100 * (n++); deltai = (delayMax-delayMin)/2 + delayMin + (delayMax-delayMin)/2 * sin(2 * pi * fFreq * nT); // Delay line emprant Lagrange interpolator di = floorf(deltai) - 1; t0 = deltai - di; t1 = t0 - 1; t2 = t0 - 2; t3 = t0 - 3; b0 = -t1*t2*t3/6; b1 = t0*t2*t3/2; b2 = -t0*t1*t3/2; b3 = t0*t1*t2/6; if (posicion >= L)
Annexos 84 posicion = 0; //Esquerra buffer1[posicion] = fGain*(*in1); for (int i=0;i<4;i++) { outPoint[i] = (posicion - 1 - di + i); if (outPoint[i] < 0) outPoint[i] += L; else if (outPoint[i] >= L) outPoint[i] -= L; listate[i] = buffer1[outPoint[i]]; } feedbackL = (b0*listate[0] + b1*listate[1] + b2*listate[2] + b3*listate[3]); //Dreta buffer2[posicion] = fGain*(*in2); for (int j=0;j<4;j++) { outPoint[j] = (posicion - 1 - di + j); if (outPoint[j] < 0) outPoint[j] += L; if (outPoint[j] >= L) outPoint[j] -= L; listate[j] = buffer2[outPoint[j]]; } feedbackR = (b0*listate[0] + b1*listate[1] + b2*listate[2] + b3*listate[3]); // ixida (*out1++) = (*in1++)*fDryWet + (1-fDryWet) * feedbackL; (*out2++) = (*in2++)*fDryWet + (1-fDryWet) * feedbackR; posicion++; } }
Annexos 91 public: ASinteti (audioMasterCallback audioMaster); ~ASinteti (); virtual void processReplacing (float **inputs, float **outputs, VstInt32 sampleFrames); virtual VstInt32 processEvents (VstEvents* events); virtual void setParameter (VstInt32 index, float value); virtual float getParameter (VstInt32 index); virtual void getParameterLabel (VstInt32 index, char *label); virtual void getParameterDisplay (VstInt32 index, char *text); virtual void getParameterName (VstInt32 index, char *text); virtual void resume (); virtual bool getEffectName (char* name); virtual bool getVendorString (char* text); virtual bool getProductString (char* text); virtual VstInt32 getVendorVersion () { return 1000; } virtual VstPlugCategory getPlugCategory () { return kPlugCategEffect; } protected: int fForma; double i; float f; float pi; nota_struct nota[85]; float volum; int TeclesMaximes; float TTeclesMaximes; int TeclesActives; /*float fPhase1, fPhase2; VstInt32 currentNote; VstInt32 currentVelocity; VstInt32 currentDelta; bool noteIsOn;*/ //int estat; float TAttack, TDecay,TRelease, PSustain; float fHeadRoom; //int CAttack, CDecay, CRelease; float conversorPosicionenFrecuencia(int j); int conversorNotaenPosicion(VstInt32 Nota); void noteOn (VstInt32 note, VstInt32 velocity, VstInt32 delta); void noteOff (VstInt32 note); void noteOffAll(); void initProcess (); }; #endif
Annexos 92 AnnexXIV sint.cpp //-------------------------------------- // VST Plug-Ins SDK // SINTETISADOR // // Francisco Javier Ripoll Esteve // [email protected] // 18/06/2008 //-------------------------------------- #include "sintetisador.h" #include "math.h" #include <stdio.h> AudioEffect* createEffectInstance (audioMasterCallback audioMaster) { return new ASinteti (audioMaster); } void ASinteti::initProcess () { //Inicialitzem totes les posicions en valors inicials for(int pos=0; pos<85; pos++) { nota[pos].noteIsOn = false; nota[pos].estat = EOff; nota[pos].CAttack = 0; nota[pos].CDecay = 0; nota[pos].CRelease = 0; nota[pos].fPhase1 = 0; nota[pos].fPhase2 = 0; nota[pos].Delta = nota[pos].Velocity = 0; nota[pos].NoteFreq = conversorPosicionenFrecuencia(pos); nota[pos].salida = 0.0f; } f = AudioEffectX::updateSampleRate (); fForma = FormaSinus; i=0; TAttack = 22000.f; TDecay = 22000.f; TRelease = 22000.f; PSustain = 0.5f; fHeadRoom = 0.5f; volum = 1.0f; TeclesMaximes = 5; TTeclesMaximes = 0.5f; TeclesActives = 0; pi = 3.141592653589793238462643383f; } ASinteti::ASinteti (audioMasterCallback audioMaster) : AudioEffectX (audioMaster, 1, 6) { if (audioMaster) { setNumInputs (0); setNumOutputs (1); canProcessReplacing (); isSynth ();
Annexos 93 setUniqueID ('Sint'); } initProcess (); suspend (); } ASinteti::~ASinteti () { } void ASinteti::resume () { AudioEffectX::resume (); } void ASinteti::setParameter (VstInt32 index, float value) { switch (index) { case kForma : fForma = int (float (NombreDeFormes - 1) * value ); break; case kAttack : TAttack = value * f; break; case kDecay : TDecay = value * f; break; case kRelease : TRelease = value * f; break; case kSustain : PSustain = value; break; case kTecles : TTeclesMaximes = value; TeclesMaximes = int(TTeclesMaximes*10.0f); break; } } float ASinteti::getParameter (VstInt32 index) { float v = 0; switch (index) { case kForma : v = float (fForma) / float (NombreDeFormes - 1); break; case kAttack : v = TAttack / f; break; case kDecay : v = TDecay / f; break; case kRelease : v = TRelease / f; break; case kSustain : v = PSustain; break; case kTecles : v = TTeclesMaximes; break; } return v; } void ASinteti::getParameterName (VstInt32 index, char* label) { switch (index) { case kForma : strcpy (label, "Forma de senyal"); break; case kAttack : strcpy (label, "Temps Attack"); break; case kDecay : strcpy (label, "Temps Decay"); break; case kRelease : strcpy (label, "Temps Release"); break; case kSustain : strcpy (label, "Sustain"); break;
Annexos 94 case kTecles : strcpy (label, "TeclesMaximes"); break; } } void ASinteti::getParameterDisplay (VstInt32 index, char* text) { switch (index) { case kForma : switch (fForma) { case FormaSinus : vst_strncpy (text, "Sinus", kVstMaxParamStrLen); break; case FormaQuadra : vst_strncpy (text, "Quadrat", kVstMaxParamStrLen); break; case FormaTriangle : vst_strncpy (text, "Triangle", kVstMaxParamStrLen); break; //case FormaSinus : vst_strncpy (text, "Sinus", kVstMaxParamStrLen); break; } break; case kAttack : float2string (TAttack/f, text, kVstMaxParamStrLen); break; case kDecay : float2string (TDecay/f, text, kVstMaxParamStrLen); break; case kRelease : float2string (TRelease/f, text, kVstMaxParamStrLen); break; case kSustain : float2string (PSustain, text, kVstMaxParamStrLen); break; case kTecles : int2string (TeclesMaximes, text, kVstMaxParamStrLen); break; } } void ASinteti::getParameterLabel (VstInt32 index, char* label) { switch (index) { case kForma : strcpy (label, "Tipus"); break; case kAttack : strcpy (label, "ms"); break; case kDecay : strcpy (label, "ms"); break; case kRelease : strcpy (label, "ms"); break; case kSustain : strcpy (label, "%"); break; case kTecles : strcpy (label, "Tecles"); break; } } bool ASinteti::getEffectName (char* name) { strcpy (name, "Generador"); return true; } bool ASinteti::getProductString (char* text) { strcpy (text, "Generador"); return true; } bool ASinteti::getVendorString (char* text) { strcpy (text, "Francisco Javier Ripoll Esteve"); return true; } float ASinteti::conversorPosicionenFrecuencia(int pos) { if (pos == 0) return 32.71f; // C octava1 else if (pos == 1) return 34.65f; else if (pos == 2) return 36.71f; else if (pos == 3) return 38.89f;
Annexos 95 else if (pos == 4) return 41.20f; else if (pos == 5) return 43.65f; else if (pos == 6) return 46.25f; else if (pos == 7) return 49.0f; else if (pos == 8) return 51.91f; else if (pos == 9) return 55.0f; else if (pos == 10) return 58.27f; else if (pos == 11) return 61.74f; else if (pos == 12) return 65.41f; // C octava2 else if (pos == 13) return 69.30f; else if (pos == 14) return 73.42f; else if (pos == 15) return 77.78f; else if (pos == 16) return 82.41f; else if (pos == 17) return 87.31f; else if (pos == 18) return 92.50f; else if (pos == 19) return 98.0f; else if (pos == 20) return 103.83f; else if (pos == 21) return 110.0f; else if (pos == 22) return 116.54f; else if (pos == 23) return 123.47f; else if (pos == 24) return 130.81f; // C octava 3 else if (pos == 25) return 138.59f; else if (pos == 26) return 146.83f; else if (pos == 27) return 155.56f; else if (pos == 28) return 164.81f; else if (pos == 29) return 174.61f; else if (pos == 30) return 185.0f; else if (pos == 31) return 196.0f; else if (pos == 32) return 207.65f; else if (pos == 33) return 220.0f; else if (pos == 34) return 233.08f; else if (pos == 35) return 246.94f; else if (pos == 36) return 261.63f; // C octava 4 else if (pos == 37) return 277.18f; else if (pos == 38) return 293.66f; else if (pos == 39) return 311.13f; else if (pos == 40) return 329.63f; else if (pos == 41) return 349.23f; else if (pos == 42) return 369.99f; else if (pos == 43) return 392.0f; else if (pos == 44) return 415.30f; else if (pos == 45) return 444.0f; else if (pos == 46) return 466.16f; else if (pos == 47) return 493.88f; else if (pos == 48) return 523.25f; // C octava 5 else if (pos == 49) return 554.37f; else if (pos == 50) return 587.33f; else if (pos == 51) return 622.25f; else if (pos == 52) return 659.26f; else if (pos == 53) return 698.46f; else if (pos == 54) return 739.99f; else if (pos == 55) return 783.99f; else if (pos == 56) return 830.61f; else if (pos == 57) return 880.0f; else if (pos == 58) return 932.33f; else if (pos == 59) return 987.77f; else if (pos == 60) return 1046.50f; // C octava 6 else if (pos == 61) return 1108.73f; else if (pos == 62) return 1174.66f; else if (pos == 63) return 1244.51f; else if (pos == 64) return 1318.51f; else if (pos == 65) return 1396.91f; else if (pos == 66) return 1479.98f; else if (pos == 67) return 1567.98f; else if (pos == 68) return 1661.22f; else if (pos == 69) return 1760.0f; else if (pos == 70) return 1864.66f; else if (pos == 71) return 1975.53f;
Annexos 96 else if (pos == 72) return 2093.0f; else if (pos == 73) return 2217.46f; else if (pos == 74) return 2349.32f; else if (pos == 75) return 2489.02f; else if (pos == 76) return 2637.02f; else if (pos == 77) return 2793.83f; else if (pos == 78) return 2959.96f; else if (pos == 79) return 3135.96f; else if (pos == 80) return 3322.44f; else if (pos == 81) return 3520.0f; else if (pos == 82) return 3729.31f; else if (pos == 83) return 3951.07f; else if (pos == 84) return 4186.01f; // C octava 7 } int ASinteti::conversorNotaenPosicion(VstInt32 Nota) { if (Nota == 0x18) return 0; // C octava1 else if (Nota == 0x19) return 1; else if (Nota == 0x1A) return 2; else if (Nota == 0x1B) return 3; else if (Nota == 0x1C) return 4; else if (Nota == 0x1D) return 5; else if (Nota == 0x1E) return 6; else if (Nota == 0x1F) return 7; else if (Nota == 0x20) return 8; else if (Nota == 0x21) return 9; else if (Nota == 0x22) return 10; else if (Nota == 0x23) return 11; else if (Nota == 0x24) return 12; // C octava2 else if (Nota == 0x25) return 13; else if (Nota == 0x26) return 14; else if (Nota == 0x27) return 15; else if (Nota == 0x28) return 16; else if (Nota == 0x29) return 17; else if (Nota == 0x2A) return 18; else if (Nota == 0x2B) return 19; else if (Nota == 0x2C) return 20; else if (Nota == 0x2D) return 21; else if (Nota == 0x2E) return 22; else if (Nota == 0x2F) return 23; else if (Nota == 0x30) return 24; // C octava 3 else if (Nota == 0x31) return 25; else if (Nota == 0x32) return 26; else if (Nota == 0x33) return 27; else if (Nota == 0x34) return 28; else if (Nota == 0x35) return 29; else if (Nota == 0x36) return 30; else if (Nota == 0x37) return 31; else if (Nota == 0x38) return 32; else if (Nota == 0x39) return 33; else if (Nota == 0x3A) return 34; else if (Nota == 0x3B) return 35; else if (Nota == 0x3C) return 36; // C octava 4 else if (Nota == 0x3D) return 37; else if (Nota == 0x3E) return 38; else if (Nota == 0x3F) return 39; else if (Nota == 0x40) return 40; else if (Nota == 0x41) return 41; else if (Nota == 0x42) return 42; else if (Nota == 0x43) return 43; else if (Nota == 0x44) return 44; else if (Nota == 0x45) return 45; else if (Nota == 0x46) return 46; else if (Nota == 0x47) return 47;
Annexos 97 else if (Nota == 0x48) return 48; // C octava 5 else if (Nota == 0x49) return 49; else if (Nota == 0x4A) return 50; else if (Nota == 0x4B) return 51; else if (Nota == 0x4C) return 52; else if (Nota == 0x4D) return 53; else if (Nota == 0x4E) return 54; else if (Nota == 0x4F) return 55; else if (Nota == 0x50) return 56; else if (Nota == 0x51) return 57; else if (Nota == 0x52) return 58; else if (Nota == 0x53) return 59; else if (Nota == 0x54) return 60; // C octava 6 else if (Nota == 0x55) return 61; else if (Nota == 0x56) return 62; else if (Nota == 0x57) return 63; else if (Nota == 0x58) return 64; else if (Nota == 0x59) return 65; else if (Nota == 0x5A) return 66; else if (Nota == 0x5B) return 67; else if (Nota == 0x5C) return 68; else if (Nota == 0x5D) return 69; else if (Nota == 0x5E) return 70; else if (Nota == 0x5F) return 71; else if (Nota == 0x60) return 72; else if (Nota == 0x61) return 73; else if (Nota == 0x62) return 74; else if (Nota == 0x63) return 75; else if (Nota == 0x64) return 76; else if (Nota == 0x65) return 77; else if (Nota == 0x66) return 78; else if (Nota == 0x67) return 79; else if (Nota == 0x68) return 80; else if (Nota == 0x69) return 81; else if (Nota == 0x6A) return 82; else if (Nota == 0x6B) return 83; else if (Nota == 0x6C) return 84; // C octava 7 } void ASinteti::processReplacing (float** inputs, float** outputs, VstInt32 sampleFrames) { float* out = outputs[0]; double fase; float eixida; float PAttack; //Percentatge Attack float PDecay; float PRelease; float fFrequencia; float fAmplitud; while (--sampleFrames >= 0) { for(int pos=0;pos<85;pos++){ if(nota[pos].noteIsOn) { fFrequencia = nota[pos].NoteFreq / f; fase = fmod(fFrequencia*i,1); fAmplitud = double(nota[pos].Velocity)/127.0f; switch (fForma) { case FormaSinus : nota[pos].salida = fAmplitud*sin(2*pi*fase); break; case FormaQuadra : if(fase<0.5) { nota[pos].salida = fAmplitud;
Annexos 98 } else { nota[pos].salida = -fAmplitud; } break; case FormaTriangle : if(fase <= 0.5) { // y = m*x + b // m= DY / DX DY = 2*Amplitud DX = 1/2 // x = fase // b = -Amplitud float m = 2 * fAmplitud / 0.5f; nota[pos].salida = m * fase - fAmplitud; } else { // y = m*x + b // m= DY / DX DY = - 2*Amplitud DX = 1/2 // x = (fase-0.5) per a dur-ho a x=0 // b = Amplitud float m = -2 * fAmplitud / 0.5f; nota[pos].salida = m * (fase - 0.5f) + fAmplitud; } break; } //fi switch (fForma) switch (nota[pos].estat) { case EAttack: PAttack = float(nota[pos].CAttack) / TAttack; nota[pos].salida = nota[pos].salida * PAttack; nota[pos].CAttack++; if (nota[pos].CAttack >= TAttack) { nota[pos].estat = EDecay; } break; case EDecay: // DY DX x b PDecay = ((PSustain-1.0f) / TDecay) * float(nota[pos].CDecay) + 1.0f; nota[pos].salida = nota[pos].salida * PDecay; nota[pos].CDecay++; if (nota[pos].CDecay >= TDecay) { nota[pos].estat = ESustain; } break; case ESustain: nota[pos].salida = nota[pos].salida*PSustain; break; case ERelease: PRelease = (-PSustain / TRelease) * float(nota[pos].CRelease) + PSustain; nota[pos].salida = nota[pos].salida*PRelease; nota[pos].CRelease++; if (nota[pos].CRelease >= TRelease) { nota[pos].estat= EOff; nota[pos].noteIsOn = false;
Annexos 99 } break; } } // fi if(nota[pos].noteIsOn) else nota[pos].salida = 0.0f; } // fi for(int pos=0;pos<85;pos++) float exit = 0.0f; // Suma de totes les notes que estan actives for(pos=0;pos<85;pos++) { if (nota[pos].noteIsOn) { exit = nota[pos].salida*1/TeclesMaximes + exit; } } *out++ = exit * (volum*2); i++; } // fi while } VstInt32 ASinteti::processEvents (VstEvents* ev) { for (VstInt32 i = 0; i < ev->numEvents; i++) { if ((ev->events[i])->type != kVstMidiType) continue; VstMidiEvent* event = (VstMidiEvent*)ev->events[i]; char* midiData = event->midiData; VstInt32 status = midiData[0] & 0xf0; // Seleccionem els 4 primers bits if (status == 0x90 || status == 0x80) { // Comparem que els 4 primers bits siguen activar o desactivar nota VstInt32 note = midiData[1] & 0x7f; VstInt32 velocity = midiData[2] & 0x7f; if (status == 0x80) noteOff (note); else { if (TeclesActives < TeclesMaximes) noteOn (note, velocity, event->deltaFrames); } } else if (status == 0xb0) { if (midiData[1] == 0x7e || midiData[1] == 0x7b) // totes les notes off noteOffAll(); if (midiData[1] == 0x48) { int midiData2 = midiData[2]; setParameter(kRelease,midiData2/127.0f); getParameter(kRelease); } if (midiData[1] == 0x49) { int midiData2 = midiData[2]; setParameter(kAttack,midiData2/127.0f); getParameter(kAttack); } if (midiData[1] == 0x4B) { int midiData2 = midiData[2]; setParameter(kDecay,midiData2/127.0f); getParameter(kDecay); } if (midiData[1] == 0x4F) {
Annexos 100 int midiData2 = midiData[2]; setParameter(kSustain,midiData2/127.0f); getParameter(kSustain); } if (midiData[1] == 0x07) { int midiData2 = midiData[2]; volum = midiData2/127.0f; } } event++; } return 1; } void ASinteti::noteOn (VstInt32 note, VstInt32 velocity, VstInt32 delta) { int pos; pos = conversorNotaenPosicion(note); nota[pos].Velocity = velocity; nota[pos].Delta = delta; nota[pos].noteIsOn = true; nota[pos].fPhase1 = nota[pos].fPhase2 = 0; nota[pos].CAttack = nota[pos].CDecay = nota[pos].CRelease = 0; nota[pos].salida = 0.0f; nota[pos].estat = EAttack; TeclesActives++; } void ASinteti::noteOff (VstInt32 note) { int pos; pos = pos = conversorNotaenPosicion(note); nota[pos].estat = ERelease; if(nota[pos].noteIsOn == true) TeclesActives--; } void ASinteti::noteOffAll() { for(int pos=0; pos<85; pos++) { nota[pos].noteIsOn = false; nota[pos].estat = EOff; nota[pos].CAttack = 0; nota[pos].CDecay = 0; nota[pos].CRelease = 0; nota[pos].fPhase1 = 0; nota[pos].fPhase2 = 0; nota[pos].Delta = nota[pos].Velocity = 0; nota[pos].NoteFreq = conversorPosicionenFrecuencia(pos); nota[pos].salida = 0.0f; } }