{"id":1813,"date":"2016-02-24T09:00:49","date_gmt":"2016-02-24T08:00:49","guid":{"rendered":"https:\/\/sii.pl\/blog\/?p=1813"},"modified":"2023-07-25T09:15:33","modified_gmt":"2023-07-25T07:15:33","slug":"niskopoziomowa-obsluga-audio-w-windows","status":"publish","type":"post","link":"https:\/\/sii.pl\/blog\/niskopoziomowa-obsluga-audio-w-windows\/","title":{"rendered":"Niskopoziomowa obs\u0142uga audio w Windows"},"content":{"rendered":"\n<p>Przedmiotem artyku\u0142u b\u0119dzie obs\u0142uga d\u017awi\u0119ku w systemie Windows poprzez natywne API systemu. Na co dzie\u0144 mamy do dyspozycji r\u00f3\u017cnego rodzaju frameworki i biblioteki, kt\u00f3re du\u017co pracy wykonuj\u0105 za nas. Do obs\u0142ugi audio powsta\u0142o ju\u017c wiele takowych &#8211; chocia\u017cby BASS (C++), NAudio (.NET) i wiele innych&#8230; Dzisiaj jednak spr\u00f3bujemy odwo\u0142a\u0107 si\u0119 do karty d\u017awi\u0119kowej niskopoziomowo &#8211; stworzymy prosty program, kt\u00f3ry pozwoli na odtworzenie pewnych danych audio.<br>Zacznijmy od do\u0142\u0105czenia pliku nag\u0142\u00f3wkowego &#8222;mmsystem.h&#8221; oraz poinformowania linkera o u\u017cyciu pliku &#8222;winmm.lib&#8221;, czyli:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\n#include \"mmsystem.h\"\n#pragma comment(lib, \"winmm.lib\"). \/\/oczywi\u015bcie mo\u017cna r\u00f3wnie\u017c zrobi\u0107 to w spos\u00f3b \"klasyczny\" - w opcjach linkera.\n<\/pre><\/div>\n\n\n<p>Zanim przejdziemy do meritum, czyli do samego odtwarzania, zastan\u00f3wmy si\u0119 jakie dane chcemy odtwarza\u0107. Mamy kilka mo\u017cliwo\u015bci &#8211; odtworzenie jakiego\u015b pliku WAV, strumienia danych z sieci, etc&#8230; mo\u017cemy r\u00f3wnie\u017c sami wygenerowa\u0107 sobie d\u017awi\u0119k kt\u00f3ry p\u00f3\u017aniej odtworzymy. Skorzystamy z ostatniej opcji &#8211; przygotujemy prosty algorytm za pomoc\u0105 kt\u00f3rego wygenerowana zostanie tablica bajt\u00f3w b\u0119d\u0105ca \u017ar\u00f3d\u0142em danych wysy\u0142anych do karty d\u017awi\u0119kowej.<br>Dla uproszczenia przyjmiemy, \u017ce dane d\u017awi\u0119kowe zapisane b\u0119d\u0105 w prostym formacie:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>1 kana\u0142 (czyli mono)<\/li>\n\n\n\n<li>8 bit\u00f3w na pr\u00f3bk\u0119<\/li>\n\n\n\n<li>8000 pr\u00f3bek na sekund\u0119.<\/li>\n<\/ul>\n\n\n\n<p>Czyli na ka\u017cd\u0105 sekund\u0119 nale\u017cy wygenerowa\u0107 8000 pr\u00f3bek 1 bajtowych.<br>Algorytm przedstawia si\u0119 nast\u0119puj\u0105co:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\nchar buffer&#x5B;8000 * 10]; \/\/bufor na pr\u00f3bki o wielko\u015bci 10 sekund * 8000 pr\u00f3bek\nfor (DWORD t = 0; t &lt; sizeof(buffer); ++t)\n{\nbuffer&#x5B;t] = (t * 5 &amp; t &gt;&gt; 7) | (t * 3 &amp; t &gt;&gt; 10);\n}\n<\/pre><\/div>\n\n\n<p>Oczywi\u015bcie jest to tylko przyk\u0142ad algorytmu tego rodzaju. Zach\u0119cam czytelnika do eksperymentowania i zapoznania si\u0119 z ciekawymi publikacjami na ten temat, gdy\u017c mo\u017cna osi\u0105gn\u0105\u0107 bardzo ciekawe efekty. Dla zainteresowanych polecam link:<br>http:\/\/countercomplex.blogspot.com\/2011\/10\/algorithmic-symphonies-from-one-line-of.html<\/p>\n\n\n\n<p>Teraz przejd\u0119 do w\u0142a\u015bciwej cz\u0119\u015bci artyku\u0142u, czyli odtwarzania naszego d\u017awieku.<br>Na pocz\u0105tek trzeba wype\u0142ni\u0107 struktur\u0119 opisuj\u0105c\u0105 format audio. Ta struktura to WAVEFORMATEX a przedstawia si\u0119 ona nast\u0119puj\u0105co:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\ntypedef struct tWAVEFORMATEX\n{\nWORD        wFormatTag;         \/* identyfikator formatu *\/\nWORD        nChannels;          \/* liczba kana\u0142\u00f3w (mono, stereo itp...) *\/\nDWORD       nSamplesPerSec;     \/* ilo\u015b\u0107 pr\u00f3bek na sekund\u0119 *\/\nDWORD       nAvgBytesPerSec;    \/* wymagana szybko\u015b\u0107 transferu dancyh. Dla formatu PCM, wynosi nSamplesPerSec \u00d7 nBlockAlign. *\/\nWORD        nBlockAlign;        \/* minimalna wielko\u015b\u0107 paczki danych. Dla formatu PCM, wynosi (nChannels \u00d7 wBitsPerSample) \/ 8. *\/\nWORD        wBitsPerSample;     \/* ilo\u015b\u0107 bit\u00f3w dla jednej pr\u00f3bki *\/\nWORD        cbSize;             \/* ilo\u015b\u0107 (w bajtach) danych dodatkowych (dla innych format\u00f3w) *\/\n\/* dane dodatkowe (je\u015bli s\u0105) *\/\n} WAVEFORMATEX\n<\/pre><\/div>\n\n\n<p>Tutaj powy\u017csza struktura ma posta\u0107:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\nWAVEFORMATEX wfx;\nwfx.wFormatTag = WAVE_FORMAT_PCM; \/\/zdefiniowany w WINAPI identyfikator formatu PCM\nwfx.wBitsPerSample =8;\nwfx.nSamplesPerSec = 8000;\nwfx.nChannels = 1;\nwfx.nBlockAlign = 1;\nwfx.nAvgBytesPerSec = 8000;\nwfx.cbSize = 0;\n<\/pre><\/div>\n\n\n<p>Nast\u0119pn\u0105 struktur\u0105 kt\u00f3r\u0105 musimy wype\u0142ni\u0107 jest WAVEHDR:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\ntypedef struct wavehdr_tag\n{\nLPSTR       lpData;                 \/* bufor z danymi audio *\/\nDWORD       dwBufferLength;         \/* d\u0142ugo\u015b\u0107 bufora audio *\/\nDWORD       dwBytesRecorded;        \/* ilo\u015b\u0107 nagranych danych (tylko do u\u017cytku przy nagrywaniu) *\/\nDWORD_PTR   dwUser;                 \/* inne dane u\u017cytkownika *\/\nDWORD       dwFlags;                \/* flagi stanu, p\u0119tli *\/\nDWORD       dwLoops;                \/* licznik p\u0119tli *\/\nstruct wavehdr_tag FAR *lpNext;     \/* zarezerwowane *\/\nDWORD_PTR   reserved;               \/* zarezerwowane *\/\n} WAVEHDR\n<\/pre><\/div>\n\n\n<p>W tym przypadku b\u0119dziemy u\u017cywa\u0107 tylko dw\u00f3ch p\u00f3l i b\u0119dzie mia\u0142a ona posta\u0107:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\nWAVEHDR header;\nmemset(&header, 0, sizeof(WAVEHDR)); \/\/zerujemy wszystkie pola struktury\nheader.lpData = buffer;\nheader.dwBufferLength = sizeof(buffer);\n<\/pre><\/div>\n\n\n<p>Dane wej\u015bciowe s\u0105 ju\u017c przygotowane, wi\u0119c nadesz\u0142a pora na wydobycie d\u017awi\u0119ku z naszego komputera.<br>Na pocz\u0105tek nale\u017cy sprawdzi\u0107 czy mo\u017cna w og\u00f3le odtworzy\u0107 dane w formacie zdefiniowanym w strukturze WAVEFORMATEX. W tym celu wykorzystamy funkcj\u0119 WaveOutOpen, kt\u00f3ra przedstawia si\u0119 nast\u0119puj\u0105co.<br>(dok\u0142adny opis w MSDN: https:\/\/msdn.microsoft.com\/en-us\/library\/windows\/desktop\/dd743866(v=vs.85).aspx)<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\nMMRESULT waveOutOpen(\nLPHWAVEOUT     phwo, \/\/wska\u017anik do zmiennej typu HWAVEOUT w kt\u00f3rej przechowywany b\u0119dzie uchwyt do urz\u0105dzenia audio\nUINT_PTR       uDeviceID, \/\/identyfikator urz\u0105dzenia audio w systemie. Je\u015bli podamy WAVE_MAPPER (zdefiniowany w WINAPI), system sam wybierze odpowiednie urz\u0105dzenie\nLPWAVEFORMATEX pwfx, \/\/wska\u017anik do struktury WAVEFORMATEX definiuj\u0105cej nasz format audio\nDWORD_PTR      dwCallback, \/\/wska\u017anik do funkcji callback, uchwyt do okna, identyfikator w\u0105tku lub NULL (szczeg\u00f3\u0142y na MSDN)\nDWORD_PTR      dwCallbackInstance, \/\/dane kt\u00f3re zostan\u0105 przekazane do funkcji callback\nDWORD          fdwOpen \/\/Flagi definiuj\u0105ce tryb wywo\u0142ywania tej funkcji (szczeg\u00f3\u0142y na MSDN)\n);\n<\/pre><\/div>\n\n\n<p>Powy\u017csz\u0105 funkcj\u0119 wywo\u0142ujemy z parametrami:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\nwaveOutOpen(NULL, WAVE_MAPPER, &wfx, NULL, 0, WAVE_FORMAT_QUERY);\n<\/pre><\/div>\n\n\n<p>Je\u015bli wywo\u0142anie tej funkcji zwr\u00f3ci MMSYSERR_NOERROR (czyli 0), mo\u017cna pr\u00f3bowa\u0107 otworzy\u0107 urz\u0105dzenie audio. W tym celu wykorzystujemy t\u0105 sam\u0105 funkcj\u0119, tylko z nieco innymi parametrami:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\nHWAVEOUT hWaveOut;\nwaveOutOpen(&hWaveOut, WAVE_MAPPER, &wfx, (DWORD_PTR)waveOutProc, 0, CALLBACK_FUNCTION);\n<\/pre><\/div>\n\n\n<p>Funkcja callback do kt\u00f3rej wska\u017anik przekazujemy, wed\u0142ug dokumentacji przedstawia si\u0119 nast\u0119puj\u0105co:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\nvoid CALLBACK waveOutProc(\nHWAVEOUT  hwo, \/\/uchwyt do urz\u0105dzenia audio\nUINT      uMsg, \/\/wiadomo\u015b\u0107 przekazana do funkcji. Mo\u017ce przyjmowa\u0107 warto\u015bci WOM_OPEN, WOM_DONE, WOM_CLOSE\nDWORD_PTR dwInstance, \/\/dane przekazane w funkcji WaveOutOpen\nDWORD_PTR dwParam1, \/\/ parametr wiadomo\u015bci (zale\u017cy od typu wiadomo\u015bci uMsg)\nDWORD_PTR dwParam2 \/\/ parametr wiadomo\u015bci (zale\u017cy od typu wiadomo\u015bci uMsg)\n);\n<\/pre><\/div>\n\n\n<p>W naszym przypadku, ma ona posta\u0107:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\nvoid CALLBACK waveOutProc(HWAVEOUT  hwo,UINT  uMsg, DWORD_PTR dwInstance,   DWORD_PTR dwParam1, DWORD_PTR dwParam2)\n{\n \nswitch (uMsg)\n{\ncase WOM_DONE:\nSetEvent(onPlaybackEnd);\nbreak;\ncase WOM_CLOSE:\nbreak;\ncase WOM_OPEN:\nbreak;\n}\n}\n<\/pre><\/div>\n\n\n<p>Funkcj\u0119 t\u0105 bardziej szczeg\u00f3\u0142owo om\u00f3wi\u0119 w dalszej cz\u0119\u015bci artyku\u0142u.<br>Skoro mamy ju\u017c zdefiniowan\u0105 funkcj\u0119 callback, oraz mo\u017cemy otworzy\u0107 urz\u0105dzenie audio, nic nie stoi na przeszkodzie aby wys\u0142a\u0107 do niego nasze dane.<br>W tym celu najpierw wywo\u0142ujemy funkcj\u0119 waveOutPrepareHeader kt\u00f3ra ma nast\u0119puj\u0105c\u0105 deklaracj\u0119:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\nMMRESULT waveOutPrepareHeader(\nHWAVEOUT  hwo, \/\/uchwyt do urz\u0105dzenia audio\nLPWAVEHDR pwh, \/\/wska\u017anik do struktury WAVEHDR opisuj\u0105cej blok danych audio\nUINT      cbwh \/\/wielko\u015b\u0107 (w bajtach) struktury WAVEHDR\n);\n<\/pre><\/div>\n\n\n<p>W naszym przypadku mamy:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\nwaveOutPrepareHeader(hWaveOut, &header, sizeof(WAVEHDR));\n<\/pre><\/div>\n\n\n<p>Je\u015bli funkcja nie zwr\u00f3ci nam b\u0142\u0119du, pozostaje ju\u017c tylko wywo\u0142a\u0107 funkcj\u0119 kt\u00f3ra wysy\u0142a dane audio do karty d\u017awi\u0119kowej, czyli funkcj\u0119 waveOutWrite:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\nMMRESULT waveOutWrite(\nHWAVEOUT  hwo, \/\/ uchwyt do urz\u0105dzenia audio\nLPWAVEHDR pwh, \/\/ wska\u017anik do struktury WAVEHDR opisuj\u0105cej blok danych audio\nUINT      cbwh \/\/wielko\u015b\u0107 (w bajtach) struktury WAVEHDR\n);\n<\/pre><\/div>\n\n\n<p>U nas wygl\u0105da to nast\u0119puj\u0105co:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\nwaveOutWrite(hWaveOut, &header, sizeof(WAVEHDR));\n<\/pre><\/div>\n\n\n<p>Je\u015bli wszystko przebieg\u0142o pomy\u015blnie, powinni\u015bmy us\u0142ysze\u0107 efekty naszej pracy. Pozosta\u0142o ju\u017c tylko po sobie posprz\u0105ta\u0107, czyli pozamyka\u0107 odpowiednie uchwyty itp&#8230;<br>Zanim to zrobimy, po\u015bwi\u0119c\u0119 chwil\u0119 na om\u00f3wienie funkcji callback kt\u00f3ra pojawi\u0142a si\u0119 wcze\u015bniej.<br>Funkcja ta posiada parametr uMsg, kt\u00f3ry mo\u017ce przyj\u0105\u0107 jedn\u0105 z trzech warto\u015bci:<\/p>\n\n\n\n<p>WOM_CLOSE &#8211; w przypadku kiedy urz\u0105dzenie jest zamykane przy u\u017cyciu funkcji waveOutClose<br>WOM_DONE &#8211; w przypadku kiedy odtwarzanie bufora zostanie zako\u0144czone<br>WOM_OPEN &#8211; w przypadku kiedy urz\u0105dzenie jest otwierane przy pomocy funkcji waveOutOpen<\/p>\n\n\n\n<p>Interesuje nas przypadek, kiedy przyjdzie wiadomo\u015b\u0107 WOM_DONE &#8211; informacja o zako\u0144czeniu odtwarzania. Jak ju\u017c wcze\u015bniej wspomnia\u0142em, w tym momencie nale\u017cy pozamyka\u0107 u\u017cyte zasoby (b\u0105d\u017a przes\u0142a\u0107 kolejne dane &#8211; ale o tym p\u00f3\u017aniej). Tutaj pojawia si\u0119 pewien problem, gdy\u017c zgodnie z dokumentacj\u0105 &#8211; wywo\u0142anie z poziomu funkcji callback, jakichkolwiek funkcji poza: EnterCriticalSection, LeaveCriticalSection, midiOutLongMsg, midiOutShortMsg, OutputDebugString, PostMessage, PostThreadMessage, SetEvent, timeGetSystemTime, timeGetTime, timeKillEvent, timeSetEvent mo\u017ce spowodowa\u0107 zawieszenie aplikacji (deadlock).<br>Aby unikn\u0105\u0107 k\u0142opot\u00f3w z tym zwi\u0105zanych, pos\u0142u\u017cymy si\u0119 zdarzeniem systemowym.<br>Na pocz\u0105tku programu nale\u017cy utworzy\u0107 uchwyt do zdarzenia (jako zmienna globalna):<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\nHANDLE onPlaybackEnd; \/\/deklarujemy jako zmienn\u0105 globaln\u0105\n\/\/...\nonPlaybackEnd = CreateEvent(NULL, false, false, NULL); \/\/uchwyt musimy utworzy\u0107 przed wywo\u0142aniem funkcji waveOutWrite.\n<\/pre><\/div>\n\n\n<p>Nast\u0119pnie po wywo\u0142aniu funkcji waveOutWrite, wywo\u0142ujemy funkcj\u0119:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\nWaitForSingleObject(onPlaybackEnd, INFINITE);\n<\/pre><\/div>\n\n\n<p>W tym momencie program czeka na zasygnalizowanie zdarzenia onPlaybackEnd, aby mo\u017cna by\u0142o rozpocz\u0105\u0107 zwalnianie u\u017cytych zasob\u00f3w. Teraz ju\u017c wida\u0107 co si\u0119 dzieje w funkcji callback &#8211; w momencie otrzymania wiadomo\u015bci o zako\u0144czeniu odtwarzania (WOM_DONE) ustawiane jest zdarzenie onPlaybackEnd, czyli:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\nSetEvent(onPlaybackEnd);\n<\/pre><\/div>\n\n\n<p>Teraz program mo\u017ce przyst\u0105pi\u0107 do zwalniania zasob\u00f3w, czyli wywo\u0142ania funkcji waveoutUnprepareHeader, oraz waveOutClose. Maj\u0105 one nast\u0119puj\u0105ce deklaracje:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\nMMRESULT waveOutUnprepareHeader(\nHWAVEOUT  hwo, \/\/uchwyt do urz\u0105dzenia audio\nLPWAVEHDR pwh, \/\/wska\u017anik do struktury WAVEHDR opisuj\u0105cej blok danych audio\nUINT      cbwh \/\/wielko\u015b\u0107 (w bajtach) struktury WAVEHDR\n);\n \nMMRESULT waveOutClose(\nHWAVEOUT hwo \/\/uchwyt do urz\u0105dzenia audio\n);\n<\/pre><\/div>\n\n\n<p>Wywo\u0142ujemy je w nast\u0119puj\u0105cy spos\u00f3b:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\nwaveOutUnprepareHeader(hWaveOut, &header, sizeof(WAVEHDR));\n<\/pre><\/div>\n\n\n<p>Je\u015bli nie otrzymamy b\u0142\u0119du, wywo\u0142ujemy:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\nwaveOutClose(hWaveOut);\n<\/pre><\/div>\n\n\n<p>Tutaj r\u00f3wnie\u017c nale\u017cy sprawdzi\u0107, czy funkcja nie zwr\u00f3ci\u0142a warto\u015bci oznaczaj\u0105cej b\u0142\u0105d. Teraz ju\u017c tylko wystarczy zamkn\u0105\u0107 uchwyt do zdarzenia onPlaybackEnd:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\nCloseHandle(onPlaybackEnd);\n<\/pre><\/div>\n\n\n<p>Mamy ju\u017c opanowany najprostszy przypadek w kt\u00f3rym wys\u0142ali\u015bmy jednorazowo do karty d\u017awi\u0119kowej wszystkie dane. Nie uwzgl\u0119dnili\u015bmy jednak jednej bardzo wa\u017cnej kwestii &#8211; danych do odtworzenia mo\u017ce by\u0107 bardzo du\u017co (np. musimy odtworzy\u0107 plik WAV o wielko\u015bci kilkuset megabajt\u00f3w). Nie jest dobr\u0105 praktyk\u0105 wys\u0142anie tak wielkiej porcji danych za pomoc\u0105 funkcji waveOutWrite.<br>Pierwsz\u0105 rzecz\u0105 kt\u00f3ra przychodzi na my\u015bl jest cykliczne wysy\u0142anie danych w cz\u0119\u015bciach, np. po 512 bajt\u00f3w, w skr\u00f3cie:<br>&#8211; przygotowujemy struktur\u0119 WAVEHDR<br>&#8211; wywo\u0142ujemy waveOutPrepareHeader<br>&#8211; wywo\u0142ujemy waveOutWrite<br>&#8211; czekamy na callBack (WOM_DONE)<br>&#8211; wywo\u0142ujemy waveOutUnprepareHeader<br>&#8211; aktualizujemy struktur\u0119 WAVEHDR przestawiaj\u0105c wska\u017anik do danych o 512 bajt\u00f3w<br>&#8211; wywo\u0142ujemy waveOutPrepareHeader<br>&#8211; wywo\u0142ujemy waveOutWrite&#8230;<br>&#8230; i tak a\u017c do zako\u0144czenia danych wej\u015bciowych. Pomys\u0142 wydaje si\u0119 dobry, jednak odtwarzaj\u0105c w ten spos\u00f3b pojawi\u0105 si\u0119 kr\u00f3tkie, aczkolwiek s\u0142yszalne przerwy w pomi\u0119dzy ka\u017cdymi 512 bajtami danych. Jak temu zaradzi\u0107? Z pomoc\u0105 przychodzi algorytm zwany &#8222;double buffering&#8221;.<br>Polega on na tym, \u017ce na pocz\u0105tku przygotowujemy nie jeden, a dwa (lub wi\u0119cej) bufory danych, nast\u0119pnie wysy\u0142amy do karty d\u017awi\u0119kowej dane z obydwu bufor\u00f3w. Potem czekamy na wiadomo\u015b\u0107 o zako\u0144czeniu odtwarzania danych z pierwszego z nich. W tym momencie (podczas gdy dane z drugiego bufora s\u0105 ci\u0105gle odtwarzane) przygotowujemy dane dla pierwszego bufora (aktualizujemy struktur\u0119 WAVEHDR) i wysy\u0142amy dane do karty d\u017awi\u0119kowej. Gdy dostaniemy informacj\u0119 o zako\u0144czeniu przetwarzania drugiego bufora, aktualizujemy go (w tym czasie odtwarzana jest kolejna porcja z bufora pierwszego) i wysy\u0142amy do urz\u0105dzenia audio. Powtarzamy ca\u0142y cykl a\u017c do wyczerpania naszych danych wej\u015bciowych. W ten spos\u00f3b wyeliminowali\u015bmy przerwy pomi\u0119dzy odtwarzaniem kolejnych porcji danych, poniewa\u017c karta d\u017awi\u0119kowa ca\u0142y czas ma dane do odtworzenia i nie musi czeka\u0107 na dostarczenie nowych danych. Analogiczna metoda znajduje r\u00f3wnie\u017c zastosowanie w wy\u015bwietlaniu grafiki na ekranie monitora &#8211; zapobiega &#8222;migotaniu&#8221; obrazu.<\/p>\n\n\n\n<p>Tak w du\u017cym skr\u00f3cie wygl\u0105da odtwarzanie danych audio w przy u\u017cyciu WINAPI. Oczywi\u015bcie nie om\u00f3wi\u0142em tutaj wszystkich aspekt\u00f3w i funkcji API zwi\u0105zanych z tym zagadnieniem. Zach\u0119cam czytelnika do samodzielnego eksperymentowania z tym tematem. Oczywi\u015bcie istniej\u0105 inne &#8211; prostsze interfejsy do obs\u0142ugi multimedi\u00f3w (np. MCI), oraz rozmaite biblioteki. Warto jednak wiedzie\u0107 co kryje si\u0119 &#8222;pod mask\u0105&#8221; tych bibliotek.<\/p>\n\n\n\n<p>Poni\u017cej listing programu z podw\u00f3jnym buforowaniem:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\n#include \u201estdafx.h\u201d\n#include \u201ewindows.h\u201d\n#include \u201estdio.h\u201d\n#include \u201emmsystem.h\u201d\n\n#pragma comment(lib, \u201ewinmm.lib\u201d)\n\n#define BUFFER_LENGTH 8000*10 \/\/10 sekund * 8000 pr\u00f3bek\n#define AUDIO_BUFFER_LENGTH 512\n#define BUFFERS_COUNT 3\n\nvoid CALLBACK waveOutProc(HWAVEOUT hwo, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2);\nvoid PrepareNextBuffer(HWAVEOUT *hWaveOut, WAVEHDR* hdr, char* buffer);\nDWORD CalculateReadLength();\nHANDLE onPlaybackEnd;\nUINT position = 0;\nUINT currentBuffer = 0;\n\nint _tmain(int argc, _TCHAR* argv&#x5B;])\n{\nonPlaybackEnd = CreateEvent(NULL, false, false, NULL);\nif (onPlaybackEnd == NULL)\n{\nprintf(\u201eERROR \u2013 CreateEvent\u201d);\nreturn 0;\n}\n\nHWAVEOUT hWaveOut = 0;\nchar buffer&#x5B;BUFFER_LENGTH];\nfor (DWORD t = 0; t &gt; 7) | (t * 3 &amp; t &gt;&gt; 10);\n}\n\nWAVEFORMATEX wfx;\nmemset(&amp;wfx, 0, sizeof(WAVEFORMATEX));\nwfx.wFormatTag = WAVE_FORMAT_PCM;\nwfx.wBitsPerSample = 8;\nwfx.nSamplesPerSec = 8000;\nwfx.nChannels = 1;\nwfx.nBlockAlign = 1;\nwfx.nAvgBytesPerSec = 8000;\nwfx.cbSize = 0;\n\nWAVEHDR* headers = new WAVEHDR&#x5B;BUFFERS_COUNT];\nfor (int i = 0; i lpData = buffer + (position*AUDIO_BUFFER_LENGTH);\n(headers + i)-&gt;dwBufferLength = CalculateReadLength();\nposition++;\n}\n\nif (waveOutOpen(NULL, WAVE_MAPPER, &amp;wfx, NULL, 0, WAVE_FORMAT_QUERY) != MMSYSERR_NOERROR)\n{\nprintf(\u201eERROR \u2013 waveOutOpen \u2013 format query\u201d);\nCloseHandle(onPlaybackEnd);\ndelete&#x5B;] headers;\nreturn 0;\n}\n\nif (waveOutOpen(&amp;hWaveOut, WAVE_MAPPER, &amp;wfx, (DWORD_PTR)waveOutProc, 0, CALLBACK_FUNCTION) != MMSYSERR_NOERROR)\n{\nprintf(\u201eERROR \u2013 waveOutOpen\u201d);\nCloseHandle(onPlaybackEnd);\ndelete&#x5B;] headers;\n\nreturn 0;\n}\n\nfor (int i = 0; i lpData = buffer + (position*AUDIO_BUFFER_LENGTH);\nhdr-&gt;dwBufferLength = CalculateReadLength();\nif (waveOutPrepareHeader(*hWaveOut, hdr, sizeof(WAVEHDR)) != MMSYSERR_NOERROR)\n{\nprintf(\u201eERROR \u2013 waveotPrepareHeader\u201d);\n}\nif (waveOutWrite(*hWaveOut, hdr, sizeof(WAVEHDR)) != MMSYSERR_NOERROR)\n{\nprintf(\u201eERROR \u2013 waveoutWrite\u201d);\n}\nprintf(\u201ePosition: %i\\n\u201d, position*AUDIO_BUFFER_LENGTH + CalculateReadLength());\nposition++;\n\n}\n\nDWORD CalculateReadLength()\n{\nif ((position + 1)*AUDIO_BUFFER_LENGTH\n<\/pre><\/div>\n\n<div class=\"kk-star-ratings kksr-auto kksr-align-left kksr-valign-bottom\"\n    data-payload='{&quot;align&quot;:&quot;left&quot;,&quot;id&quot;:&quot;1813&quot;,&quot;slug&quot;:&quot;default&quot;,&quot;valign&quot;:&quot;bottom&quot;,&quot;ignore&quot;:&quot;&quot;,&quot;reference&quot;:&quot;auto&quot;,&quot;class&quot;:&quot;&quot;,&quot;count&quot;:&quot;1&quot;,&quot;legendonly&quot;:&quot;&quot;,&quot;readonly&quot;:&quot;&quot;,&quot;score&quot;:&quot;5&quot;,&quot;starsonly&quot;:&quot;&quot;,&quot;best&quot;:&quot;5&quot;,&quot;gap&quot;:&quot;2&quot;,&quot;greet&quot;:&quot;&quot;,&quot;legend&quot;:&quot;5\\\/5&quot;,&quot;size&quot;:&quot;30&quot;,&quot;title&quot;:&quot;Niskopoziomowa obs\u0142uga audio w Windows&quot;,&quot;width&quot;:&quot;159&quot;,&quot;_legend&quot;:&quot;{score}\\\/5&quot;,&quot;font_factor&quot;:&quot;1.25&quot;}'>\n            \n<div class=\"kksr-stars\">\n    \n<div class=\"kksr-stars-inactive\">\n            <div class=\"kksr-star\" data-star=\"1\" style=\"padding-right: 2px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 30px; height: 30px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"2\" style=\"padding-right: 2px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 30px; height: 30px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"3\" style=\"padding-right: 2px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 30px; height: 30px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"4\" style=\"padding-right: 2px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 30px; height: 30px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"5\" style=\"padding-right: 2px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 30px; height: 30px;\"><\/div>\n        <\/div>\n    <\/div>\n    \n<div class=\"kksr-stars-active\" style=\"width: 159px;\">\n            <div class=\"kksr-star\" style=\"padding-right: 2px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 30px; height: 30px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 2px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 30px; height: 30px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 2px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 30px; height: 30px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 2px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 30px; height: 30px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 2px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 30px; height: 30px;\"><\/div>\n        <\/div>\n    <\/div>\n<\/div>\n                \n\n<div class=\"kksr-legend\" style=\"font-size: 24px;\">\n            5\/5    <\/div>\n    <\/div>\n","protected":false},"excerpt":{"rendered":"<p>Przedmiotem artyku\u0142u b\u0119dzie obs\u0142uga d\u017awi\u0119ku w systemie Windows poprzez natywne API systemu. Na co dzie\u0144 mamy do dyspozycji r\u00f3\u017cnego rodzaju &hellip; <a class=\"continued-btn\" href=\"https:\/\/sii.pl\/blog\/niskopoziomowa-obsluga-audio-w-windows\/\">Continued<\/a><\/p>\n","protected":false},"author":77,"featured_media":15438,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_editorskit_title_hidden":false,"_editorskit_reading_time":0,"_editorskit_is_block_options_detached":false,"_editorskit_block_options_position":"{}","inline_featured_image":false,"footnotes":""},"categories":[1314],"tags":[129,249,250],"class_list":["post-1813","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-development-na-twardo","tag-c","tag-audio","tag-windows"],"acf":[],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 4.9.9 - aioseo.com -->\n\t<meta name=\"description\" content=\"Przedmiotem artyku\u0142u b\u0119dzie obs\u0142uga d\u017awi\u0119ku w systemie Windows poprzez natywne API systemu. Na co dzie\u0144 mamy do dyspozycji r\u00f3\u017cnego rodzaju frameworki i biblioteki, kt\u00f3re du\u017co pracy wykonuj\u0105 za nas. Do obs\u0142ugi audio powsta\u0142o ju\u017c wiele takowych - chocia\u017cby BASS (C++), NAudio (.NET) i wiele innych... Dzisiaj jednak spr\u00f3bujemy odwo\u0142a\u0107 si\u0119 do karty d\u017awi\u0119kowej niskopoziomowo -\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Pawe\u0142 Ciuraj\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/sii.pl\/blog\/niskopoziomowa-obsluga-audio-w-windows\/\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 4.9.9\" \/>\n\t\t<meta property=\"og:locale\" content=\"pl_PL\" \/>\n\t\t<meta property=\"og:site_name\" content=\"blogersii\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"Niskopoziomowa obs\u0142uga audio w Windows - blogersii\" \/>\n\t\t<meta property=\"og:description\" content=\"Przedmiotem artyku\u0142u b\u0119dzie obs\u0142uga d\u017awi\u0119ku w systemie Windows poprzez natywne API systemu. Na co dzie\u0144 mamy do dyspozycji r\u00f3\u017cnego rodzaju frameworki i biblioteki, kt\u00f3re du\u017co pracy wykonuj\u0105 za nas. Do obs\u0142ugi audio powsta\u0142o ju\u017c wiele takowych - chocia\u017cby BASS (C++), NAudio (.NET) i wiele innych... Dzisiaj jednak spr\u00f3bujemy odwo\u0142a\u0107 si\u0119 do karty d\u017awi\u0119kowej niskopoziomowo -\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/sii.pl\/blog\/niskopoziomowa-obsluga-audio-w-windows\/\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2016\/02\/windows_audio-1.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2016\/02\/windows_audio-1.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"702\" \/>\n\t\t<meta property=\"og:image:height\" content=\"343\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2016-02-24T08:00:49+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2023-07-25T07:15:33+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/Sii.Polska\" \/>\n\t\t<meta name=\"twitter:card\" content=\"summary\" \/>\n\t\t<meta name=\"twitter:title\" content=\"Niskopoziomowa obs\u0142uga audio w Windows - blogersii\" \/>\n\t\t<meta name=\"twitter:description\" content=\"Przedmiotem artyku\u0142u b\u0119dzie obs\u0142uga d\u017awi\u0119ku w systemie Windows poprzez natywne API systemu. Na co dzie\u0144 mamy do dyspozycji r\u00f3\u017cnego rodzaju frameworki i biblioteki, kt\u00f3re du\u017co pracy wykonuj\u0105 za nas. Do obs\u0142ugi audio powsta\u0142o ju\u017c wiele takowych - chocia\u017cby BASS (C++), NAudio (.NET) i wiele innych... Dzisiaj jednak spr\u00f3bujemy odwo\u0142a\u0107 si\u0119 do karty d\u017awi\u0119kowej niskopoziomowo -\" \/>\n\t\t<meta name=\"twitter:image\" content=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2016\/02\/windows_audio-1.jpg\" \/>\n\t\t<script type=\"application\/ld+json\" class=\"aioseo-schema\">\n\t\t\t{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/sii.pl\\\/blog\\\/niskopoziomowa-obsluga-audio-w-windows\\\/#article\",\"name\":\"Niskopoziomowa obs\\u0142uga audio w Windows - blogersii\",\"description\":\"Przedmiotem artyku\\u0142u b\\u0119dzie obs\\u0142uga d\\u017awi\\u0119ku w systemie Windows poprzez natywne API systemu. Na co dzie\\u0144 mamy do dyspozycji r\\u00f3\\u017cnego rodzaju frameworki i biblioteki, kt\\u00f3re du\\u017co pracy wykonuj\\u0105 za nas. Do obs\\u0142ugi audio powsta\\u0142o ju\\u017c wiele takowych - chocia\\u017cby BASS (C++), NAudio (.NET) i wiele innych... Dzisiaj jednak spr\\u00f3bujemy odwo\\u0142a\\u0107 si\\u0119 do karty d\\u017awi\\u0119kowej niskopoziomowo -\",\"inLanguage\":\"pl-PL\",\"headline\":\"Niskopoziomowa obs\\u0142uga audio w Windows\",\"author\":{\"@id\":\"https:\\\/\\\/sii.pl\\\/blog\\\/author\\\/pawel-ciuraj\\\/#author\"},\"publisher\":{\"@id\":\"https:\\\/\\\/sii.pl\\\/#organization\"},\"datePublished\":\"2016-02-24T08:00:49+01:00\",\"dateModified\":\"2023-07-25T07:15:33+02:00\",\"articleSection\":\"Development na twardo, C#, Audio, Windows\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/sii.pl\\\/blog\\\/niskopoziomowa-obsluga-audio-w-windows\\\/#webpage\"},\"isPartOf\":{\"@id\":\"https:\\\/\\\/sii.pl\\\/blog\\\/niskopoziomowa-obsluga-audio-w-windows\\\/#webpage\"},\"image\":{\"@type\":\"ImageObject\",\"url\":\"https:\\\/\\\/sii.pl\\\/blog\\\/wp-content\\\/uploads\\\/2016\\\/02\\\/windows_audio-1.jpg\",\"@id\":\"https:\\\/\\\/sii.pl\\\/blog\\\/niskopoziomowa-obsluga-audio-w-windows\\\/#articleImage\",\"width\":702,\"height\":343}},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/sii.pl\\\/blog\\\/niskopoziomowa-obsluga-audio-w-windows\\\/#breadcrumblist\",\"itemListElement\":[{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/sii.pl\\\/blog#listItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/sii.pl\\\/blog\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/sii.pl\\\/blog\\\/development-na-twardo\\\/#listItem\",\"name\":\"Development na twardo\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/sii.pl\\\/blog\\\/development-na-twardo\\\/#listItem\",\"position\":2,\"name\":\"Development na twardo\",\"item\":\"https:\\\/\\\/sii.pl\\\/blog\\\/development-na-twardo\\\/\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/sii.pl\\\/blog\\\/niskopoziomowa-obsluga-audio-w-windows\\\/#listItem\",\"name\":\"Niskopoziomowa obs\\u0142uga audio w Windows\"},\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/sii.pl\\\/blog#listItem\",\"name\":\"Home\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/sii.pl\\\/blog\\\/niskopoziomowa-obsluga-audio-w-windows\\\/#listItem\",\"position\":3,\"name\":\"Niskopoziomowa obs\\u0142uga audio w Windows\",\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/sii.pl\\\/blog\\\/development-na-twardo\\\/#listItem\",\"name\":\"Development na twardo\"}}]},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/sii.pl\\\/#organization\",\"name\":\"Sii Polska\",\"url\":\"https:\\\/\\\/sii.pl\\\/blog\\\/\",\"sameAs\":[\"https:\\\/\\\/www.instagram.com\\\/siipolska\\\/\",\"https:\\\/\\\/www.tiktok.com\\\/@siipolska\",\"https:\\\/\\\/www.youtube.com\\\/channel\\\/UCQ3UQ7RJPEYnAWC_rPE5Dxg\",\"https:\\\/\\\/www.linkedin.com\\\/company\\\/sii-polska\",\"https:\\\/\\\/clutch.co\\\/profile\\\/sii-poland\",\"https:\\\/\\\/www.crunchbase.com\\\/organization\\\/sii\",\"https:\\\/\\\/www.wikidata.org\\\/wiki\\\/Q16601096\"]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/sii.pl\\\/blog\\\/niskopoziomowa-obsluga-audio-w-windows\\\/#webpage\",\"url\":\"https:\\\/\\\/sii.pl\\\/blog\\\/niskopoziomowa-obsluga-audio-w-windows\\\/\",\"name\":\"Niskopoziomowa obs\\u0142uga audio w Windows - blogersii\",\"description\":\"Przedmiotem artyku\\u0142u b\\u0119dzie obs\\u0142uga d\\u017awi\\u0119ku w systemie Windows poprzez natywne API systemu. Na co dzie\\u0144 mamy do dyspozycji r\\u00f3\\u017cnego rodzaju frameworki i biblioteki, kt\\u00f3re du\\u017co pracy wykonuj\\u0105 za nas. Do obs\\u0142ugi audio powsta\\u0142o ju\\u017c wiele takowych - chocia\\u017cby BASS (C++), NAudio (.NET) i wiele innych... Dzisiaj jednak spr\\u00f3bujemy odwo\\u0142a\\u0107 si\\u0119 do karty d\\u017awi\\u0119kowej niskopoziomowo -\",\"inLanguage\":\"pl-PL\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/sii.pl\\\/blog\\\/#website\"},\"breadcrumb\":{\"@id\":\"https:\\\/\\\/sii.pl\\\/blog\\\/niskopoziomowa-obsluga-audio-w-windows\\\/#breadcrumblist\"},\"author\":\"https:\\\/\\\/sii.pl\\\/blog\\\/author\\\/pawel-ciuraj\\\/#author\",\"creator\":\"https:\\\/\\\/sii.pl\\\/blog\\\/author\\\/pawel-ciuraj\\\/#author\",\"image\":{\"@type\":\"ImageObject\",\"url\":\"https:\\\/\\\/sii.pl\\\/blog\\\/wp-content\\\/uploads\\\/2016\\\/02\\\/windows_audio-1.jpg\",\"@id\":\"https:\\\/\\\/sii.pl\\\/blog\\\/niskopoziomowa-obsluga-audio-w-windows\\\/#mainImage\",\"width\":702,\"height\":343},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/sii.pl\\\/blog\\\/niskopoziomowa-obsluga-audio-w-windows\\\/#mainImage\"},\"datePublished\":\"2016-02-24T08:00:49+01:00\",\"dateModified\":\"2023-07-25T07:15:33+02:00\"},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/sii.pl\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/sii.pl\\\/blog\\\/\",\"name\":\"blogersii\",\"description\":\"Blog technologiczny Sii \\u2013 praktyczna wiedza od ekspert\\u00f3w\",\"inLanguage\":\"pl-PL\",\"publisher\":{\"@id\":\"https:\\\/\\\/sii.pl\\\/#organization\"}}]}\n\t\t<\/script>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"Niskopoziomowa obs\u0142uga audio w Windows - blogersii","description":"Przedmiotem artyku\u0142u b\u0119dzie obs\u0142uga d\u017awi\u0119ku w systemie Windows poprzez natywne API systemu. Na co dzie\u0144 mamy do dyspozycji r\u00f3\u017cnego rodzaju frameworki i biblioteki, kt\u00f3re du\u017co pracy wykonuj\u0105 za nas. Do obs\u0142ugi audio powsta\u0142o ju\u017c wiele takowych - chocia\u017cby BASS (C++), NAudio (.NET) i wiele innych... Dzisiaj jednak spr\u00f3bujemy odwo\u0142a\u0107 si\u0119 do karty d\u017awi\u0119kowej niskopoziomowo -","canonical_url":"https:\/\/sii.pl\/blog\/niskopoziomowa-obsluga-audio-w-windows\/","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/sii.pl\/blog\/niskopoziomowa-obsluga-audio-w-windows\/#article","name":"Niskopoziomowa obs\u0142uga audio w Windows - blogersii","description":"Przedmiotem artyku\u0142u b\u0119dzie obs\u0142uga d\u017awi\u0119ku w systemie Windows poprzez natywne API systemu. Na co dzie\u0144 mamy do dyspozycji r\u00f3\u017cnego rodzaju frameworki i biblioteki, kt\u00f3re du\u017co pracy wykonuj\u0105 za nas. Do obs\u0142ugi audio powsta\u0142o ju\u017c wiele takowych - chocia\u017cby BASS (C++), NAudio (.NET) i wiele innych... Dzisiaj jednak spr\u00f3bujemy odwo\u0142a\u0107 si\u0119 do karty d\u017awi\u0119kowej niskopoziomowo -","inLanguage":"pl-PL","headline":"Niskopoziomowa obs\u0142uga audio w Windows","author":{"@id":"https:\/\/sii.pl\/blog\/author\/pawel-ciuraj\/#author"},"publisher":{"@id":"https:\/\/sii.pl\/#organization"},"datePublished":"2016-02-24T08:00:49+01:00","dateModified":"2023-07-25T07:15:33+02:00","articleSection":"Development na twardo, C#, Audio, Windows","mainEntityOfPage":{"@id":"https:\/\/sii.pl\/blog\/niskopoziomowa-obsluga-audio-w-windows\/#webpage"},"isPartOf":{"@id":"https:\/\/sii.pl\/blog\/niskopoziomowa-obsluga-audio-w-windows\/#webpage"},"image":{"@type":"ImageObject","url":"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2016\/02\/windows_audio-1.jpg","@id":"https:\/\/sii.pl\/blog\/niskopoziomowa-obsluga-audio-w-windows\/#articleImage","width":702,"height":343}},{"@type":"BreadcrumbList","@id":"https:\/\/sii.pl\/blog\/niskopoziomowa-obsluga-audio-w-windows\/#breadcrumblist","itemListElement":[{"@type":"ListItem","@id":"https:\/\/sii.pl\/blog#listItem","position":1,"name":"Home","item":"https:\/\/sii.pl\/blog","nextItem":{"@type":"ListItem","@id":"https:\/\/sii.pl\/blog\/development-na-twardo\/#listItem","name":"Development na twardo"}},{"@type":"ListItem","@id":"https:\/\/sii.pl\/blog\/development-na-twardo\/#listItem","position":2,"name":"Development na twardo","item":"https:\/\/sii.pl\/blog\/development-na-twardo\/","nextItem":{"@type":"ListItem","@id":"https:\/\/sii.pl\/blog\/niskopoziomowa-obsluga-audio-w-windows\/#listItem","name":"Niskopoziomowa obs\u0142uga audio w Windows"},"previousItem":{"@type":"ListItem","@id":"https:\/\/sii.pl\/blog#listItem","name":"Home"}},{"@type":"ListItem","@id":"https:\/\/sii.pl\/blog\/niskopoziomowa-obsluga-audio-w-windows\/#listItem","position":3,"name":"Niskopoziomowa obs\u0142uga audio w Windows","previousItem":{"@type":"ListItem","@id":"https:\/\/sii.pl\/blog\/development-na-twardo\/#listItem","name":"Development na twardo"}}]},{"@type":"Organization","@id":"https:\/\/sii.pl\/#organization","name":"Sii Polska","url":"https:\/\/sii.pl\/blog\/","sameAs":["https:\/\/www.instagram.com\/siipolska\/","https:\/\/www.tiktok.com\/@siipolska","https:\/\/www.youtube.com\/channel\/UCQ3UQ7RJPEYnAWC_rPE5Dxg","https:\/\/www.linkedin.com\/company\/sii-polska","https:\/\/clutch.co\/profile\/sii-poland","https:\/\/www.crunchbase.com\/organization\/sii","https:\/\/www.wikidata.org\/wiki\/Q16601096"]},{"@type":"WebPage","@id":"https:\/\/sii.pl\/blog\/niskopoziomowa-obsluga-audio-w-windows\/#webpage","url":"https:\/\/sii.pl\/blog\/niskopoziomowa-obsluga-audio-w-windows\/","name":"Niskopoziomowa obs\u0142uga audio w Windows - blogersii","description":"Przedmiotem artyku\u0142u b\u0119dzie obs\u0142uga d\u017awi\u0119ku w systemie Windows poprzez natywne API systemu. Na co dzie\u0144 mamy do dyspozycji r\u00f3\u017cnego rodzaju frameworki i biblioteki, kt\u00f3re du\u017co pracy wykonuj\u0105 za nas. Do obs\u0142ugi audio powsta\u0142o ju\u017c wiele takowych - chocia\u017cby BASS (C++), NAudio (.NET) i wiele innych... Dzisiaj jednak spr\u00f3bujemy odwo\u0142a\u0107 si\u0119 do karty d\u017awi\u0119kowej niskopoziomowo -","inLanguage":"pl-PL","isPartOf":{"@id":"https:\/\/sii.pl\/blog\/#website"},"breadcrumb":{"@id":"https:\/\/sii.pl\/blog\/niskopoziomowa-obsluga-audio-w-windows\/#breadcrumblist"},"author":"https:\/\/sii.pl\/blog\/author\/pawel-ciuraj\/#author","creator":"https:\/\/sii.pl\/blog\/author\/pawel-ciuraj\/#author","image":{"@type":"ImageObject","url":"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2016\/02\/windows_audio-1.jpg","@id":"https:\/\/sii.pl\/blog\/niskopoziomowa-obsluga-audio-w-windows\/#mainImage","width":702,"height":343},"primaryImageOfPage":{"@id":"https:\/\/sii.pl\/blog\/niskopoziomowa-obsluga-audio-w-windows\/#mainImage"},"datePublished":"2016-02-24T08:00:49+01:00","dateModified":"2023-07-25T07:15:33+02:00"},{"@type":"WebSite","@id":"https:\/\/sii.pl\/blog\/#website","url":"https:\/\/sii.pl\/blog\/","name":"blogersii","description":"Blog technologiczny Sii \u2013 praktyczna wiedza od ekspert\u00f3w","inLanguage":"pl-PL","publisher":{"@id":"https:\/\/sii.pl\/#organization"}}]},"og:locale":"pl_PL","og:site_name":"blogersii","og:type":"article","og:title":"Niskopoziomowa obs\u0142uga audio w Windows - blogersii","og:description":"Przedmiotem artyku\u0142u b\u0119dzie obs\u0142uga d\u017awi\u0119ku w systemie Windows poprzez natywne API systemu. Na co dzie\u0144 mamy do dyspozycji r\u00f3\u017cnego rodzaju frameworki i biblioteki, kt\u00f3re du\u017co pracy wykonuj\u0105 za nas. Do obs\u0142ugi audio powsta\u0142o ju\u017c wiele takowych - chocia\u017cby BASS (C++), NAudio (.NET) i wiele innych... Dzisiaj jednak spr\u00f3bujemy odwo\u0142a\u0107 si\u0119 do karty d\u017awi\u0119kowej niskopoziomowo -","og:url":"https:\/\/sii.pl\/blog\/niskopoziomowa-obsluga-audio-w-windows\/","og:image":"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2016\/02\/windows_audio-1.jpg","og:image:secure_url":"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2016\/02\/windows_audio-1.jpg","og:image:width":702,"og:image:height":343,"article:published_time":"2016-02-24T08:00:49+00:00","article:modified_time":"2023-07-25T07:15:33+00:00","article:publisher":"https:\/\/www.facebook.com\/Sii.Polska","twitter:card":"summary","twitter:title":"Niskopoziomowa obs\u0142uga audio w Windows - blogersii","twitter:description":"Przedmiotem artyku\u0142u b\u0119dzie obs\u0142uga d\u017awi\u0119ku w systemie Windows poprzez natywne API systemu. Na co dzie\u0144 mamy do dyspozycji r\u00f3\u017cnego rodzaju frameworki i biblioteki, kt\u00f3re du\u017co pracy wykonuj\u0105 za nas. Do obs\u0142ugi audio powsta\u0142o ju\u017c wiele takowych - chocia\u017cby BASS (C++), NAudio (.NET) i wiele innych... Dzisiaj jednak spr\u00f3bujemy odwo\u0142a\u0107 si\u0119 do karty d\u017awi\u0119kowej niskopoziomowo -","twitter:image":"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2016\/02\/windows_audio-1.jpg"},"aioseo_meta_data":{"post_id":"1813","title":null,"description":null,"keywords":[],"keyphrases":{"focus":{"keyphrase":"","score":0,"analysis":{"keyphraseInTitle":{"score":0,"maxScore":9,"error":1}}},"additional":[]},"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"article","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":"","og_custom_url":null,"og_article_section":null,"og_article_tags":[],"twitter_use_og":false,"twitter_card":"summary","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":{"id":"#aioseo-article-64670e1b6eadc","slug":"article","graphName":"Article","label":"Article","properties":{"type":"BlogPosting","name":"#post_title","headline":"#post_title","description":"#post_excerpt","image":"","keywords":"","author":{"name":"#author_name","url":"#author_url"},"dates":{"include":true,"datePublished":"","dateModified":""}}},"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":"default","schema_type_options":"{\"article\":{\"articleType\":\"BlogPosting\"},\"course\":{\"name\":\"\",\"description\":\"\",\"provider\":\"\"},\"faq\":{\"pages\":[]},\"product\":{\"reviews\":[]},\"recipe\":{\"ingredients\":[],\"instructions\":[],\"keywords\":[]},\"software\":{\"reviews\":[],\"operatingSystems\":[]},\"webPage\":{\"webPageType\":\"WebPage\"}}","pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":"-1","robots_max_videopreview":"-1","robots_max_imagepreview":"large","priority":0,"frequency":"default","local_seo":null,"limit_modified_date":false,"created":"2021-10-15 05:14:45","updated":"2023-07-25 07:24:10","ai":null,"breadcrumb_settings":null,"seo_analyzer_scan_date":null},"aioseo_breadcrumb":"<div class=\"aioseo-breadcrumbs\"><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/sii.pl\/blog\" title=\"Home\">Home<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">&raquo;<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/sii.pl\/blog\/development-na-twardo\/\" title=\"Development na twardo\">Development na twardo<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">&raquo;<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\tNiskopoziomowa obs\u0142uga audio w Windows\n\t\t<\/span><\/div>","aioseo_breadcrumb_json":[{"label":"Home","link":"https:\/\/sii.pl\/blog"},{"label":"Development na twardo","link":"https:\/\/sii.pl\/blog\/development-na-twardo\/"},{"label":"Niskopoziomowa obs\u0142uga audio w Windows","link":"https:\/\/sii.pl\/blog\/niskopoziomowa-obsluga-audio-w-windows\/"}],"republish_history":[],"featured_media_url":"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2016\/02\/windows_audio-1.jpg","category_names":["Development na twardo"],"_links":{"self":[{"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/posts\/1813","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/users\/77"}],"replies":[{"embeddable":true,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/comments?post=1813"}],"version-history":[{"count":2,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/posts\/1813\/revisions"}],"predecessor-version":[{"id":23159,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/posts\/1813\/revisions\/23159"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/media\/15438"}],"wp:attachment":[{"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/media?parent=1813"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/categories?post=1813"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/tags?post=1813"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}