Šta je novo?

kontrola zvucne kartice?

Marvin

Čuven
Učlanjen(a)
26.09.2002
Poruke
356
Poena
620
Hocu da iz nekog viseg programskog jezika pristupim zvucnoj kartici i sa nje da procitam trenutnu vrednost jacine zvuka na ulazu, tj. jacinu zvuka sa line in ili mikrofonskog ulaza.
Takodje hocu da na osnovu te vrednosti kontrolisem jacinu zvuka u sistemu (kao sto je windows volume control).
Bilo bi lepo kada bi to mogao da uradim u nekom visem jeziku, najbolje Delfi ili C#, ali ako ne moze, kao krajnje resenje ostaje C koji bas i ne volim.
Da malo pojasnim. Hocu da napravim program koji pokazuje trenutnu jacinu zvuka (u db?) koji zvucna prima recimo sa mikrofona i da u programu takodje postoji opcija da se pojaca/smanji zvuk na izlazu. Mozda bih napravio i neku granicu preko koje bi se automatski smanjivao/pojacavo zvuk na izlazu, ali to nije primarno.
Ako neko zna kako da uradim navedene stvari neka napise. Znacio bi mi i neki link ili neka kljucna rec za pretragu po netu.
Pozdrav
 
Ako hoces samo da kontrolises jacinu zvuka, nije nikakav problem. Izbor jezika je sekundaran, posto se sve radi API funkcijama; tj. svaki jezik iz kojeg mozes da pozoves API funkcije ce valjati (c++, delphi, vb...)

Ono sta tebi treba su operacije nad sistemskim mixerom. Potpuno resenje je pravljenje sopstvenih klasa. Stvari nisu uopste komplikovane ako si ikada radio sa API odnosno callback funkcijama. Jedino je problem sto ima materije za iscitavanje, pa objasnjenje ne moze da stane u nekoliko postova. Sav materijal je na raspolaganju ovde, pa ti mozes da krenes da citas i da javis kada zapnes negde. Mogu neke osnovne stvari da objasnim, kao i da navedem neke zamke da ne gubis vreme.


Struktura miksera:

Na svaki audio uredjaj u sistemu dolazi po jedan mixer. Obrati paznju na to da audio uredjaj ne mora biti strogo samo zvucna karta, nego bilo sta sto ima audio ulaz ili izlaz. Tu spadaju dakle i TV karte, voice modemi, web kamere sa mikrofonom i razne druge kombinacije. Dakle, danas nije nikakava retkost imati vise od jednog audio uredjaja u sistemu.
Mixer je, grubo receno, sistemska komponena koja lezi izmedju korisnika i drajvera. Sta ce od opcija i kontrola imati mixer za visi samo od toga sta se nalazi u drajveru.

Svaki mixer ima jednu ili vise destinacija. Klasicna zvucna karta ima dve destinacije: playing i recording. Pomenuta web kamera sa mikrofonom ima jednu destinaciju. Ima karti i sa vise od dve destinacije. Nazivi destinacija se vuku iz drajvera, tako da nece biti uvek fixirano na "playback" i "recording". Ukoliko je audio drajver na drugom jeziku, i ti nazivi ce biti na tom jeziku.

Svaka destinacija ima po dve grane - linije i master kontrole. Linije date destinacije su (za recording destinaciju) mic in, line in, cd in, aux in, itd. Linije za playback su npr wave out, line out, itd. Master kontrole za konkretnu destinaciju mogu biti master volume, master mute i sl. Vazno je znati da destinacija mora imati podgranu "linije" - koje linije se tu nalaze zavisi iskljucivo od toga sta uredjaj podrzava odnosno sta se nalazi u drajveru. Master kontrole su opcionalne i promenjive; sto znaci da je firma programirajuci drajver stavila master mute za recording, a mozda i nije.

Svaka linija (wave in, wave out, mic in, itd) sadrzi opet kontrole. To mogu biti uobicajene volume i mute, ali i drugi tipovi - recimo bass, trebble, mic boost, itd. Tj. sve ono sta mozete i sami da vidite u sistemskom mixeru.

Dakle otprilike ovako:


Kod:
mixer0
  |- destinacija0
  |    |- master kontrole
  |    |    |- master kontrola 0
  |    |    |- master kontrola 1
  |    |    |- master kontrola n
  |    |- linije
  |         |- linija 0
  |         |    |- kontrola 0
  |         |    |- kontrola 1
  |         |    |- kontrola n
  |         |- linija 1
  |         |    |- kontrola 0
  |         |    |- kontrola n
  |         |- linija n
  |              |- kontrola 0
  |              |- kontrola 1
  |              |- kontrola n
  |  
  |- destinacija1
  |    |- master kontrole
  |    |    |- master kontrola 1
  |    |    |- master kontrola n
  |    |- linije
  |         |- linija 0
  |         |    |- kontrola 0
  |         |    |- kontrola 1
  |         |    |- kontrola n
  |         |- linija 1
  |         |    |- kontrola 0
  |         |    |- kontrola n
  |         |- linija n
  |              |- kontrola 0
  |              |- kontrola 1
  |              |- kontrola n
...
 
Poslednja izmena:
Covek rece "procitam trenutnu vrednost jacine zvuka na ulazu, tj. jacinu zvuka sa line in ili mikrofonskog ulaza."

Marvine pojasni sta si hteo -- da meris jacinu signala na ovim ulazima ili da ocitas poziciju slajdera u mikseru?
 
Izvin'te ako sam bio nejasan. Hocu da merim koliko glasno neko vice na mikrofon :) Dakle hocu da izmerim koja je to vrednost (jedinica je nebitna) pa shodno tome da kontrolisem jacinu zvuka u OSu. Je li sada jasnije?
Silveru, svaka cast na objasnjenju, citam msdn pa cemo videti.
 
Ako imam vise audio uredjaja, koji je aktivan?

U principu, sistem vodi racuna o tome koja karta je "preferred device" (odvojeno za record i playback), ali na relativno los nacin. Ocigledno da u momentu kada je to u windowsu radjeno, nije bilo uobicajeno da se ima vise uredjaja. Postoje dva nacina za proveru, ali "stucaju" oba:

- procitas iz registryja:
"HKEY_CURRENT_USER\Software\Microsoft\Multimedia\Sound Mapper\PlayBack"
"HKEY_CURRENT_USER\Software\Microsoft\Multimedia\Sound Mapper\Record"

Prvi problem u vezi ovog nacina jeste to sto su ovde sacuvana *imena* audio uredjaja, a ne handle ili neki drugi uniqueID. Konflikt ne isplivava na povrsinu cesto, ali je moguc. Na primer, XP ima svoj univerzalni drajver za USB AudioDevice (fakticki za sve sluske koja imaju u sebi "budzu" sa audio kartom). - ubodi vise od jedne i sve ce biti nazvane "USB Audio Device" (koja je koja?). Drugi primer su univerzalni drajveri za celu porodicu adaptera; drajver za Realtek AC'97 ce pod "Realtek Audio Device" prijaviti i ALC650 i ALC880, itd.

Drugi problem sa registry resenjem je u tome sto je Windows malo lenj da te vrednosti obnavlja. Recimo da imas USB audio uredjaj i on je prijavljen kao preferred device (control panel -> audio and sound -> Audio tab -> use only preferred devices). Izvuces tu USB audio kartu, ali windows to ne osvezi u registryju sve dok ponovo ne otvoris iz control panela podesavanje za defaut audio kartu. To moze da se resi tako sto u svojoj klasi drzis listu svih detektovanih audio uredjaja, pa obradis PnP event WM_DEVICECHANGE za USB klasu uredjaja i kada se potegne DBT_DEVICEARRIVAL ili DBT_DEVICEREMOVECOMPLETE ponovo skeniras sve raspolozive audio uredjaje.



Drugi nacin za odredjivanje preferred audio uredjaja je koriscenje message podsistema:

waveOutMessage( HWAVEOUT(WAVE_MAPPER), DRVM_MAPPER_PREFERRED_GET, dwParam1, dwParam2)

waveInMessage( HWAVEIN(WAVE_MAPPER), DRVM_MAPPER_PREFERRED_GET, dwParam1, dwParam2)

Za playback i za recording. Ovo bi trebalo da je elegantniji nacin, ali (iz meni nepoznatog razloga) ovo puca na pojedinim verzijama windowsa.
 
Poslednja izmena:
Druga zamka potice od pisanja drajvera

Nikada ne pretpostavljaj gde ce se sta naci od kontrola i linija. Moras sve da "skeniras" i detektujes postoji li i ako postoji gde se nalazi - zato nije lose napraviti klasu koja pravi onakvo stablo za svaki audio uredjaj. Drajver jedne kartice ce staviti za recording destinaciju master mute, u drugom drajveru ne postoji master mute, nego za svaku liniju posebno mute kontrola, itd.
Jedan tipican primer su peak kontrole koje dobro dodju ako hoces da pravis one ekvilajzere *po liniji* (ne po frekvenciji, to je nesto drugo). Mnogi drajveri jednostavno ne implementiraju peak kontrole i tada nemas drugog izbora nego da upotrebis i ACM API funkcije; stocereci, koristis waveIn i waveOut set funkcija i (za mikrofon recimo) pustis signal u bafer, pa analiziras taj sempl i sam izracunas min/max/etc.


U rantajmu prema imenima destinacija ne mozes da zakljucis koja je za recording, a koja za playback zato sto se naziv vuce iz drajvera. Cak ne postoji ni fixno pravilo da se npr. sistemu prvo prijavi record destinacija, onda playback, itd. Prvi impuls za odredjivanje koja je koja lezi u tome da nadjes onu destinaciju gde postoji mikrofon linija. Medjutim, mikrofon linija postoji i u recording i u playback destinaciji. Tako da je bolje da se nadje neka uniqe linija, koja postoji samo u jednoj destinaciji. Na primer, wave-out postoji samo i iskljucivo u playbacku; kada time utvrdis koja destinacija je playback, treba samo da nadjes drugu destinaciju u okviru tog mixera koja takodje ima mikrofon liniju - i to ce biti recording destinacija. Neko bi pomislio - zasto ne potrazis onda odmah wave-in liniju? Zato sto wave-in linija ne postoji u svim drajverima, a wave-out postoji.
Dakle, kada nadjes mic-in liniju u recording destinaciji, moras da proveris da li ta linija ima volume kontrolu. Ako ima - vezes se za nju. Ako nema, moras da se vezes za master volume kontrolu recording destinacije. To je to ispipavanje gde se sta nalazi.

Moras da obratis i paznju na generalnu razliku izmedju playbacka i recordinga. REC obicno ima vise linija, ali su one mutually-exclusive. Tj. ako selektujes mic liniju, ostale se sve automatski iskljucuju (zato obicno postoji jedna MUX master kontrola na REC destinaciji). Posto vazi MUX priroda, ukupnu jacinu tona definise volume control te mic-in linije ILI master volume REC destinacije.
Kod PLAY destinacije linije *nisu* mutually-exclusive. U praksi to znaci sledece - ako se koristi wave-out linija za play (i ima svoj volume control) i PLAY destinacija ima master volume, onda je ukupna jacina izlaza definisana kao line-volume * master-volume = 100%
 
Poslednja izmena:
Hvala Silveru na opsirnim objasnjenjima.
Trenutno se razmisljam iz kog jezika cu lakse da pozovem API f-je. Najradije bih Delfi, ali moram da vezbam C#. Iz kojeg bi to lakse uradio od ta dva? Na kraju cu ipak da dodjem na C...
 
Kako to mislis "iz kog jezika ces lakse da pozoves API funkcije"? Pozivaju se isto :)

Sto se delfija tice, mislim da su ti sve funkcije vec definisane u okviru windows.pas i mmsystem.pas junita. Iz C# nisam pokusavao :D
 
za c# ovako se pozivaju win32 funkcije:

1. uključiš "System.Runtime.InteropServices":

using System.Runtime.InteropServices;

2. za funkciju koju želiš da pozoveš moraš da znaš potpis, za ovo je najbolji sajt www.pinvoke.net, na njemu se nalaze potpisi svih win32 funkcija. evo primer za MessageBox:

[DllImport("user32.dll", CharSet=CharSet.Auto)]
public static extern uint MessageBox(IntPtr hWnd, String text, String caption, uint type);
 
Marvin je napisao(la):
Izvin'te ako sam bio nejasan. Hocu da merim koliko glasno neko vice na mikrofon :) Dakle hocu da izmerim koja je to vrednost (jedinica je nebitna) pa shodno tome da kontrolisem jacinu zvuka u OSu. Je li sada jasnije? Silveru, svaka cast na objasnjenju, citam msdn pa cemo videti.

Silvere, ima li neki API (mrzi me sad da gledam) koji vraca jacinu signala sa mikrofonskog ulaza (ne poziciju slajdera na mixeru nego isto ono sto se vidi na VU-metru kad je ukljuceno snimanje/monitoring)?

Ako nema trebace mu snimanje signala sa ulaza i izracunavanje RMS.
 
Od NT4 kernela na ovamo ne moze direktno. Jedino sta mozes jeste da pricas sa API-jem ili sa drajverom ako je to "extra" implementirano. To jest, za neke profi karte drajver predvidja takve stvari i uz njih se obicno dobija ili gotov softver koji time operise ili SDK. Ali, nije onda univerzalno za sve karte.

Za univerzalno za sada jedino pustanje sempla u bafer i onda proracun nad njim, kao sto vec rekoh gore. Uz paznju na velicinu tog bafera, naravno. Tako se i implementiraju vizuelne VU-meter kontrole, uz nesto dodatne zafrkancije za "fiziku" kazaljke.
 
E to me je zanimalo. Probacu varijantu sa baferom pa cemo videti.
Inace, prvo sam probao C# ali je poziv API f-ja komplikovan. Sada pokusavam da sve to odradim iz Delfija (koji bolje poznajem). Trenutno se mucim sa hendlovima tj. koji bi tip HANDLE bio u Pascalu?
Sve mi se cini da cu na kraju morati da radim c, iako ga nisam radio dve godine...
 
Marvine, bez ikakve uvrede, ali ako su ti osnovni tipovi i pozivanje api funkcija problem, bas me zanima kako ces odraditi drugi deo posla. C ti tu sam po sebi nece pomoci, jer (ponavljam) pozivanje api funkcija u delphiju i u c-u je *ista stvar*.

Ljudi iz Borlanda su ti sve te tipove "preveli", treba samo otvoriti taj windows.pas recimo i pogledati, nista vise. Definisali su i sve handle tipove i sve tipove koji zvuce "nepaskalovski", a koriste se u API-ju. Na primer, ako je neki parametar u MSDN-u definisan kao LPCTSTR, ne moras lupati glavu, prijavi ga i ti kao LPCTSTR, iako to nije pascal tip. Otvori windows.pas i lupi search "WINDEF.H" i tu ces videti da su svi ti tipovi MAPIRANI.

Evo i primer konkretne funkcije dokumentovane u MSDN-u:


Kod:
HDC CreateDC(
  LPCTSTR lpszDriver,        // driver name
  LPCTSTR lpszDevice,        // device name
  LPCTSTR lpszOutput,        // not used; should be NULL
  CONST DEVMODE* lpInitData  // optional printer data
);

U windows.pas je ta funkcija vec 'redeklarisana':

Kod:
function CreateDC(
  lpszDriver, 
  lpszDevice, 
  lpszOutput: PChar;
  lpdvmInit: PDeviceMode): HDC; stdcall;

Sve je jasno - HDC je vec definisan tip i ne moras da lupas glavu sta je to - koristi ga kao HDC. Ako te vece zanima sta je, uradi search u tom junitu. Tamo stoje i UINT, i DWORD, i BOOL, itd.
 
Vrh Dno