int21h

Multimédia za použití Jedi SDL (a FMOD)

Poslední díl našeho seriálu o grafice (a vlastně nejen o ní) pod Windows zakončíme knihovnou SDL, která je i pro Linux a další OS, takže aplikaci, kterou napíšete pod SDL, spustíte po novém přeložení pod velkou spoustou dalších OS bez nějaké zvláštní námahy. To je výhoda oproti LX5SUITE, které bylo jen pro Windows a DOS. Stejně, jako LX5SUITE využívá jednotku BASS (pokud nechcete jen WAVe soubory), tak SDL zase může využívat (tak nějak) jednotku FMOD, takže si jí tu probereme také (a asi nejjednodušší způsob, jak se o ní něco zpočátku dozvědět, je přečíst si celou její dokumentaci, uf). Ale opět jen ty části, které jsou využitelné ve Free Pascalu (tedy vynecháme C).

Dokumentace pro FMOD je přístupná jak v HTML, tak jako CHM. Jejím pročtením se dozvíte několik obecných informací:

Pro ty, ketří bohužel nedisponují znalostí angličtiny, přeložím alespoň (část) několik tutorialů, které jim snad pomohou, když už v ničem jiném, tak v začátcích. Budou se týkat základů, 3D zvuku, synchronizace, vlastních samplů a proudů, DSP engine, spektrální analýzy a efekty z DirectX 8. U všeho jsou dokonce i obrázky. Nejsou tam sice hotové programy, zato je tam ale výčet přesně těch funkcí, které budete potřebovat:

Nejprve inicializujete celý systém:

FSOUND_Init(44100,32,0);	{44 kHz, 32 kanálů}


var	Zvuk : PFSoundSample;
	Hudba : PFMusicModule;
	Stream : PFSoundStream;
	Kanal : integer;
	Data : PSingleArray;
	Prac : longint;
	Echo1,Echo2 : integer;  

Zvuky WAV, MP2, MP3, OGG nebo RAW, a hudbu MOD, S3M, XM, IT nebo MID nahrajete funkcí:

Zvuk := FSOUND_Sample_Load(FSOUND_FREE,'Soubor',FSOUND_2D,0);
Hudba := FMUSIC_LoadSong('Soubor');  

Přehrajete je pak pomocí:

Kanal := FSOUND_PlaySound(FSOUND_FREE,Zvuk);
FMUSIC_PlaySong(Hudba);  

Pokud je soubor velký, a nepotřebujete ho přehrávat vícekrát po sobě, použijte Stream:

Stream := FSOUND_Stream_OpenFile(FSOUND_FREE,PChar('Soubor'),
          FSOUND_LOOP_NORMAL or FSOUND_NORMAL,0);
Kanal := FSOUND_Stream_Play(FSOUND_FREE,Stream);  

Pokud máte již nahraná vlastní zvuková data, můžete pomocí funkcí FSOUND_Sample_Alloc, FSOUND_Sample_Lock vytvořit prostor, do kterých nahrajete vlastní signed data (pokud nejsou taková, využijte funkci FSOUND_Sample_Upload, která je zkonvertuje). Pro výběr kanálu, ve kterém chcete přehrát zvuk, použijte funkci FSOUND_FREE. Pro nastavení hlasitosti, nastavení frekvence přehrávání zvuku, nebo pozastavení hudby/zvuků použijte tyto funkce:

FMUSIC_SetMasterVolume(Hudba,256);
FSOUND_SetVolume(Kanal,255);
FSOUND_SetFrequency(Kanal,11025);
FMUSIC_SetPaused(Hudba,True);
FSOUND_SetPaused(Kanal,True);  

Zapnutí a čtení spektrální analýzy se provede:

FSOUND_DSP_SetActive(FSOUND_DSP_GetFFTUnit,TRUE);
Data := PSingleArray(FSOUND_DSP_GetSpectrum);  

Vrátí 512 čísel s pohyblivou řadovou čárkou, která získáte přes Data^[Index*4+x]. Pokud chcete 3D zvuk, nahrajte ho buď HW nebo SW (předdefinované konstanty najdete v sekcích Defines):

Zvuk := FSOUND_Sample_Load(FSOUND_FREE,'zvuk.wav',FSOUND_HW3D or FSOUND_LOOP_NORMAL,0);
Zvuk := FSOUND_Sample_Load(FSOUND_FREE,'zvuk.wav',FSOUND_LOOP_NORMAL,0);  

Pak ve smyčce během hraní hry nastavujete pozici hráče, a jednotlivých zvuků (pokud nechcete doplerův efekt, dejte rychlost na NIL):

FSOUND_3D_Listener_SetAttributes(PoziceVektor,RychlostVektor,fx,fy,fz,tx,ty,tz);
FSOUND_3D_Update;
FSOUND_3D_SetAttributes(Kanal,Pozice,Rychlost);  

Jak vypočítat jednotlivé položky najdete v dokumentaci. Při přehrávání zvuků se lze synchronizovat pomocí CallBack funkcí, které jsou volány vždy, když dojde k přehrávání značek, které vytváří např. Sound Forge. Jinak můžete získat čas v milisekundách:

Prac := FSOUND_Stream_GetTime(Zvuk);  

Pro využití DX8 efektů nesmíte využívat SW 3D zvuky. V následujícím příkladu začneme přehrávat zvuk se dvěma ozvěnami, u kterých si ponecháme handle, abychom mohli měnit jejich parametry, a s Flange efektech, u kterého ponecháme standardní nastavení.

Kanal := FSOUND_PlaySoundEx(FSOUND_FREE,Zvuk,DrySFXUnit,TRUE); 
Echo1 := FSOUND_FX_Enable(Kanal,FSOUND_FX_ECHO);
Echo2 := FSOUND_FX_Enable(Kanal,FSOUND_FX_ECHO);
FSOUND_FX_Enable(Kanal,FSOUND_FX_FLANGER);
FSOUND_SetPaused(Kanal,FALSE);
FSOUND_FX_SetEcho(Echo1,80.0f,70.0f,100.0f,100.0f,TRUE);   

Další efekty jsou sbor, komprese, pokřivení, kloktání a odraz. Efekty lze aplikovat jen pokud je zvuk pozastavený, ale měnit jejich vlastnosti lze kdykoliv. Maximum je 16 efektů na jeden kanál, a nulují se, jakmile zvuk přestane hrát (nebo začne hrát znovu). Jednotlivé položky lze zase z paměti odstranit a celý systém deaktivovat následovně:

FSOUND_Sample_Free(Zvuk);
FMUSIC_FreeSong(Hudba);
FSOUND_Stream_Close(Stream)
FSOUND_Close;  

To je asi tak ze základů všechno... vyšší funkce zahrnují nahrazení standardních efektových jednotek vlastními, kdy si můžete efekty vyrobit vlastními silami. Nutno podotknout, že novější verze jednotky FMOD EX má některé změny, jako že spíše používá objekty a desetinná čísla než integery. Všechny tyto změny jsou v manuálu zachyceny. Hodilo by se také poznamenat, že pokud budete chtít dělat s FMOD vlastními silami, je asi lepší pracovat s nejnovější verzí.

Nevím, proč se mi původně tyto samostatné jednotky zdály těžké, když jsou vlastně snadné. V adresáři "samplesdelphi" najdete i příklady pro Delphi, které tedy můžete využít i pod Free Pascalem (stačí si jen zkompilovat jednotku FMOD.PAS o velikosti 87 kB PAS (resp. 60 kB v novější verzi), a mít někde poblíž knihovnu FMOD.DLL, nebo ještě lépe FMODEX.DLL či FMODEXP.DLL). Jedná se hlavně o 3D zvuk, nahrávání zvuku, přehrávání zvuku s možností volby zařízení a ovladače (DirectX, WaveOut, atd.) a přehrávání Streamů. Přiloženy jsou i některé malé prográmky (mezi jinými např. tvořič zvukových bank pro herní konzole). Pokud Vám tedy z nějakého důvodu nevyhovuje JediSDL nebo LX5SUITE a chcete použít VGFX, můžete k němu použít buď FMOD nebo BASS a mít tak plnohodnotné multimediální centrum (ovšem nevím proč, když LX5SUTITE i JediSDL podporují i další funkce, než "jen" grafiku a zvuky). Nuže, podíváme se tedy na SDL. Její funkce jsou následující:

SDL_Init(SDL_INIT_EVERYTHING);		- aktivuje kompletní SDL
SDL_Quit;				- ukončí SDL


SDL_Delay(ms : longint);		- vytvoří zpoždění (min. 10 ms)
SDL_GetTicks : longint;			- zjistí počet ms od startu SDL (max. 49 dnů)


SDL_CreateThread(Spust : function; Data : pointer) : SDL_Thread;
SDL_KillThread(Vlakno : SDL_Thread);	- start/stop vlákna


SDL_CDOpen(Mechanika : integer) : SDL_CD;
SDL_CDEject(Cislo : SDL_CD) : integer;	- vysune dvířka
SDL_CDClose(Cislo : SDL_CD);		- ukončí používání mechaniky
SDL_CDPlay(Cislo : SDL_CD; Start,Delka : integer);
SDL_CDStop(Cislo : SDL_CD) : integer;	- započne/zastaví hraní
SDL_CDPlayTracks(Cislo : SDL_CD; Prvni,Snimek,Skladeb,Framu : integer) : integer;


SDL_NumJoysticks : integer;		- počet joysticků
SDL_JoystickOpen(Ind : integer) : SDL_Joystick;
SDL_JoystickClose(Ind : SDL_Joystick);	- začne/přestane používat daný joystick
X := SDL_JoystickGetAxis(I : SDL_Joystick, 0);
Y := SDL_JoystickGetAxis(I : SDL_Joystick, 1);
SDL_JoystickGetHat(Cislo : SDL_Joystick; Hat : integer) : byte;
SDL_JoystickGetButton(Cislo : SDL_Joystick; Tlac : integer) : boolean;


SDL_WM_SetCaption(TitulekOkna,Ikona : pchar);
SDL_WM_ToggleFullScreen(Povrch : SDL_Surface) : boolean;


SDL_OpenAudio(A,B : SDL_AudioSpec) : integer;
SDL_CloseAudio;				- nastartuje/zastaví audio systém
SDL_LoadWAV(Soubor : pchar; Vlastn : SDL_AudioSpec;
            Buffer : pointer; Delka : longint) : SDL_AudioSpec;
SDL_FreeWAV(Buffer : byte);		- nahraje do/uvolní z paměti zvuk (vč.ADPCM)
SDL_MixAudio(Cil,Zdroj : byte; Delka : longint; Hlasitost : integer);


SDL_SetVideoMode(x,y,bpp : integer; Vlajky : longint) : SDL_Surface;
SDL_Flip(Povrch : SDL_Surface);		- zobrazí grafický buffer na monitoru
SDL_FreeSurface(Povrch : SDL_Surface);	- smaže buffer
SDL_LoadBMP(Soubor : pchar) : SDL_Surface;
SDL_SetCursor(Kurzor : SDL_Cursor);	- změní kurzor myši
SDL_BlitSurface(Zdroj : SDL_Surface; VyrezZ : SDL_Rect;
                Cil : SDL_Surface; VyrezCil : SDL_Rect) : integer;
SDL_ShowCursor(Zapnout : integer) : integer;
SDL_GL_LoadLibrary(Cesta : pchar) : integer;
SDL_LockSurface(Povrch : SDL_Surface) : integer;
SDL_UnLockSurface(Povrch : SDL_Surface) : integer;
SDL_MapRGB(Pixel : SDL_PixelFormat; r,g,b : byte) : longint;  

To je seznam některých funkcí, které jsem vybral z podrobné dokumentace nové verze. Je to tam sice popsané pro jazyk C, ale snad jsem to přepsal správně. K využití budete zřejmě možná potřebovat SDL.DLL a SDL.pas. Však to již brzy zjistíme dle dostupných příkladů a tutorialů v dokumentaci. Zatím mi vychází, že je lepší používat spíše LX5SUITE (SDL maximálně tak na joystick), ale zvuky raději extra zvláš? pomocí k tomu určených jednotek. Kromě toho se mi zdá, že kompilovat projekt s LX5Suite je jednodušší. Co Vám? :-)

Pokud jsem Vám ještě nerozmluvil použití LX5Suite (možnost DOSu a všech verzí Windows, přívětivější k FP, snadná obsluha grafiky, zvuk pomocí BASS či FMOD, ale zase chybějící podpora Linuxu v něčem víc než zjištění OS), a potřebujete např. Joystick (a nezajistíte si ho jinak), přímou podporu BeOS či Linuxu (spolu s Windows), či potřebu ovládat jednotku CD-ROM, a nevadí Vám o malinko složitější ovládání (přeci jen je SDL trochu více Low-Level), můžete to zkusit (osobně bych dal přednost LX5Suite a tam, kde by to nešlo použít, bych nasadil pro Joystick a CD-ROM SDL - jde totiž inicializovat jen určitá jeho část!). Starší verze má příklady i v dokumentaci pro Pascal, novější (zdá se) už jen pro C. Z toho, co mám stažené, je nejnovější soubor PAS nebo PP z roku 2005. Pro ulehčení se budu od teď věnovat té poslední verzi, ke které jsou FP hlavičky a příklady (navíc i dokumentace má příklady pro Delphi, resp. Free Pascal - příklady jsou také psány v zápisu Dephi! Možná tady trochu pletu ukazatele).

*** Zvukový systém ***

uses SDL;
var	wanted : TSDL_AudioSpec;
	audio_chunk : PUint8;
	audio_len : Uint32;	{délka dat}
	audio_pos : PUint8;	{pozice bufferu}


{funkce jako CALL Back, kterou systém zavolá, vždy když dojdou data}
procedure fill_audio(udata : pointer; stream : PUint8; delka : integer);
begin
 if audio_len = 0 then Exit;		{pokud není co hrát}
 if len > audio_len then len := audio_len;
					{namixujeme data - přehrajeme je}
 SDL_MixAudio(stream,audio_pos,len,SDL_MIX_MAXVOLUME);
 inc(audio_pos,len);			{aktualizujeme pozici}
 dec(audio_len,len);			{odečteme přehranou délku}
end;


begin					{nastartujeme audio systém - s ORem lze i další}
 if SDL_Init(SDL_INIT_AUDIO) < 0 then Halt(3);
					{toto jen 1x, pak používat SDL_InitSubSystem}
 wanted.freq := 22050;			{frekvence}
 wanted.format := AUDIO_S16;
 wanted.channels := 2;			{počet kanálů, tj. stereo}
 wanted.samples := 1024;
 wanted.callback := fill_audio;	{naše call back funkce}
 wanted.userdata := nil;		{inicializujeme zvuky}
 if SDL_OpenAudio(@wanted,Nil) < 0 then Halt(2);
{nahrajeme data}			{opět při Haltu nutno provést SDL_CloseAudio}
 if SDL_LoadWAV('soubor.wav',wanted,@audio_pos,audio_len) = nil then Halt;
 SDL_PauseAudio(0);			{zahájíme přehrávání}
 while audio_len > 0 do
 begin
  SDL_Delay(100);			{hrajeme, dokud je co}
 end;
 SDL_FreeWAV(audio_pos);		{uvolníme buffer}
 SDL_CloseAudio;			{uzavřeme zvukový systém}
 SDL_Quit;				{toto je vhodné na konci vždy i bez předchozích CloseXXX}
end.  

*** Grafický systém ***

(lze použít i OpenGL)

uses SDL;
var	screen_ : PSDL_Surface;
	fmtg : TSDL_PixelFormat;
	screen_,locked : PSDL_Surface;
	imagebmp,image : PSDL_Surface;
	dstrect : TSDL_Rect;
	i : integer;
	buffer : PUint8;


{procedura pro kompletní načtení BMP obrázku a jeho zobrazení}
procedure LoadBmp(Soubor : string);
var	image : PSDL_Surface;
	dest : TSDL_Rect;
	ncolors,i : integer;
	colors : PSDL_Color;
	r,g,b : integer;
begin
{nahrajeme BMP obrázek do paměti}
 image := SDL_LoadBMP(PChar(FileName));
 if image = nil then Exit;
{pokud obsahuje obrázek palety, musíme je přidat do barev}
 if image.format.palette > 0 then
 begin
  ncolors := image.format.palette.ncolors;
  colors := SDL_Color*malloc(ncolors*sizeof(SDL_Color));
  Move(image.format.palette.colors,colors,ncolors);
 end 
  else 
   begin
{jinak zpracujeme vlastní 256 barevnou paletu}
    ncolors := 256;
    SetLength(colors,ncolors*sizeof(SDL_Color));
{vytvoříme vlastní INC paletu, tj. styl 3,3,2}
    for r := 0 to 7 do
     for g := 0 to 7 do
      for b := 0 to 3 do
      begin
       i := (r shl 5) or (g shl 2) or b;
       colors[i].r := r shl 5;
       colors[i].g := g shl 5;
       colors[i].b := b shl 6;
      end;
    end;{nastavíme paletu, pokud jedeme v 256 barvách. Ostatní režimy to ignorují}
 SDL_SetColors(screen,colors,0,ncolors);
 free(colors);		{uvolníme automaticky alokované prostředky}
{zobrazíme obrázek do povrchu na obrazovce}
 dest.x := 0;
 dest.y := 0;
 dest.w := image.w;
 dest.h := image.h;
 SDL_BlitSurface(image,nil,screen_,@dest);
{aktualizujeme zobrazení}
 SDL_UpdateRects(screen_,1,@dest);
{uvolníme obrázek z paměti - pokud ho už nikdy nebudeme potřebovat}
 SDL_FreeSurface(image);
end;


procedure ZobrazPixel(X,Y : Sint32; r,g,b
var	pixel : Uint32;
	bits : PUint8;
	bpp,r,g,b : Uint8;
begin
{namapujeme pixel na aktuální paletu, pokud nějaká je, jinak HC/TC}
 pixel := SDL_MapRGB(screen_.format,r,g,b );
{pokud se musí povrch zamknout, uděláme to}
 if SDL_MUSTLOCK(screen_) > 0 then
  if SDL_LockSurface(screen_) < 0 then Exit;
{získáme nějaké ty informace - rychlejší by bylo brát je přímo a nekopírovat}
 bpp := screen_.format.BytesPerPixel;
{vypočteme offset na obrazovce}
 bits := (PUint8(screen_.pixels))+Y*screen_.pitch+X*bpp;
{zobrazíme pixel dle aktuálního počtu BPP}
 case bpp of
  1 : PUint8(bits^) := Uint8(pixel);
  2 : PUint16(bits^) := Uint16(pixel);
  3 : begin
{v závislosti na počtu bitů u HC 15/16}
       r := (pixel shr screen_.format.Rshift) and $ffF;
       g := (pixel shr screen_.format.Gshift) and $ff;
       b := (pixel shr screen_.format.Bshift) and $ff;
       (bits+(screen_.format.Rshift div 8))^ := r; 
       (bits+(screen_.format.Gshift div 8))^ := g;
       (bits+(screen_.format.Bshift div 8))^ := b;
      end;
  4 : PUInt32(bits^) := Uint32(pixel);
 end;
{odemkneme obrazovku}
 if SDL_MUSTLOCK(screen_) > 0 then 
  SDL_UnlockSurface(screen_);
{aktualizujeme změněnou oblast obrazovky}
 SDL_UpdateRect(screen_,X,Y,1,1);	{1 daný pixel}
{vhodné dělat až po všech změnách, např. zapisovat po řádcích, atd.}
end;


begin
{inicializujeme video režim}
 if SDL_Init(SDL_INIT_VIDEO) < 0 then Halt(2);
 screen_ := SDL_SetVideoMode(640,480,8,SDL_SWSURFACE);
 {or SDL_FULLSCREEN by zapnul Full Screen, BPP=0 by bylo dle plochy Windows}
 if screen_ = nil then Halt(3);	{s "or SDL_ANYFORMAT" bychom vzali i 15/16/24/32 bitů}
{nahrajeme obrázek z disku}
 imagebmp := SDL_LoadBMP('obrazek.bmp');
 if imagebmp = nil then Halt;
{pokud má obrázek paletu, přidáme ji do té systémové}
 if imagebmp.format.palette <> nil then 
  SDL_SetColors(screen_,@imagebmp.format.palette.colors,
                0,imagebmp.format.palette.ncolors);
{převedeme obrázek do formátu obrazovky a uvolníme ten starý}
 image := SDL_DisplayFormat(imagebmp);
 SDL_FreeSurface(imagebmp);
 if image = nil then Halt;
{zamkneme obrazovku, pokud je to potřeba}
 if SDL_MUSTLOCK(screen_) > 0 then
  if SDL_LockSurface(screen_) < 0 then Halt;
{zobrazíme si obrázek napřímo}
 buffer := PUnit8(screen_.pixels);
 for i := 0 to screen_.h-1 do 
 begin
  memset(buffer,(i*255) div screen_.h,screen_.w*screen_.format.BytesPerPixel);
  Inc(buffer,screen_.pitch); end;
{pak zase odemkneme obrazovku}
 if SDL_MUSTLOCK(screen_) > 0 then
  SDL_UnlockSurface(screen_);
{nebo necháme obrázek zobrazit knihovnou na střed obrazovky}
 dstrect.x := (screen_.w-image.w) div 2;
 dstrect.y := (screen_.h-image.h) div 2;
 dstrect.w := image.w;
 dstrect.h := image.h;	{při chybě nezapomínat na SDL_Quit a tady i FreeSurface}
 if SDL_BlitSurface(image,nil,screen_,@dstrect) < 0 then Halt;
{obrázek už nebudeme potřebovat}
 SDL_FreeSurface(image);
{ohlásíme, že jsme změnili obrazovku}
 SDL_UpdateRects(screen_,1, @dstrect );
{pokud podporujeme DoubleBuffer, musíme ještě obraz zobrazit}
 SDL_Flip(screen_):	{jinak to je to samé jako SDL_UpdateRect(screen_,0,0,0,0)}
{vytvoříme zpoždění 5 vteřin}
 SDL_Delay(5000);
 ...	{další nějaké činnosti}
 SDL_Quit;
end.  

*** Systém myši ***

uses SDL;
begin
 SDL_Init(SDL_INIT_EVERYTHING);
 ...
 SDL_PumpEvents;
 if SDL_GetMouseState(nil,nil) and SDL_BUTTON(1) then
  Writeln('Stisknuto tlačítko číslo 1 na myši.');
 ..
 SDL_Quit;
end.  

*** Systém klávesnice ***

uses SDL;
var	event : TSDL_Event;
begin
 SDL_Init(SDL_INIT_EVERYTHING);
 ..
 while SDL_PollEvent(&event) > 0 do
  case event.type_ of
   SDL_KEYDOWN : begin {stisknutá klávesa je v event.keysym.scancode} end;
   SDL_KEYUP : begin {nějaká klávesa byla puštěna} end;
  end;
 ..
 SDL_Quit;
end.  

*** Joystick systém ***

uses SDL;
var	joystick : PSDL_Joystick;
	event : TSDL_Event;	{vše pracuje na systému událostí, jako celý Windows}
begin
 if SDL_Init(SDL_INIT_VIDEO or SDL_INIT_JOYSTICK) < 0 then Halt(2);
 SDL_JoystickEventState(SDL_ENABLE);	{inicializujeme SDL a otevřeme první joystick}
 joystick := SDL_JoystickOpen(0);
 while SDL_PollEvent(&event) do		{čteme v nekonečné smyčce události}
  case event.type_ of  			{teď si vybíráme jen ty z joysticku}
   SDL_KEYDOWN : {klávesnice něco stiskla}
   SDL_QUIT : {požadavek na ukončení programu}
   SDL_JOYAXISMOTION :			{joystick se pohnul, s DeadZone}
    if (event.jaxis.value < -3200) or (event.jaxis.value > 3200 ) ) then {};
   SDL_JOYBUTTONDOWN :			{joystick stiskl tlačítko}
    if event.jbutton.button = 0 then {};{nás zajímá úplně to první}
   SDL_JOYBALLMOTION :			{zpracujeme pohyb prvního kolečka}
    if event.jball.ball = 0 then {};
  end;
 ..
 SDL_Quit; 
end.  

*** Audio CD ***

uses SDL;
var	CDRomJ : string;
	i,m,s,f : integer;
	cdrom : PSDL_CD;	status : TCDstatus;
	status_str : string;
begin
 if SDL_Init(SDL_INIT_CDROM) < 0 then Halt(2);
{zjistíme, jaké mechaniky jsou připojeny}
 CDRomJ := Format('Dostupné mechaniky: %d',[SDL_CDNumDrives])+#13#10;
 for i := 0 to SDL_CDNumDrives-1 do
  CDRomJ := CDRomJ+Format('Mechanika %d : "%s"',[i,SDL_CDName(i)])+#13#10;
 Writeln(CDRomJ);
{otevřeme první mechaniku}
 cdrom := SDL_CDOpen(0);
 if cdrom = nil then Halt;	{opět jen pro zjednodušení, vhodné spíše vypsat chybu}
{zjistíme stav mechaniky}
 status := SDL_CDStatus(cdrom);
 case status of
  CD_TRAYEMPTY : status_str := 'Není médium';
  CD_STOPPED : status_str := 'Zastaveno';
  CD_PLAYING : status_str := 'Přehrává';
  CD_PAUSED : status_str := 'Pozastaveno';
  CD_ERROR : status_str := 'Chyba!';
 end;
{vypíšeme stav formátovaně}
 status_str := Format('Stav mechaniky : %s',status_str)+#13#10;
 if status >= CD_PLAYING then
 begin
  FRAMES_TO_MSF(cdrom->cur_frame,&m,&s,&f);
  Format('Právě přehrávaná stopa %d,%d:%2.2d',[cdrom.track[cdrom.cur_track].id,m,s]);
 end;
{takto se přehraje celé CD}
 if CD_INDRIVE(SDL_CDStatus(cdrom)) then SDL_CDPlayTracks(cdrom,0,0,0,0);
{takto se přehraje poslední písnička}
 if CD_INDRIVE(SDL_CDStatus(cdrom)) then SDL_CDPlayTracks(cdrom,cdrom.numtracks-1,0,0,0);
{takto se přehraje celá první a druhá stopa, a 10 vteřin třetí}
 if CD_INDRIVE(SDL_CDStatus(cdrom)) then SDL_CDPlayTracks(cdrom,0,0,2,10);
 ..
 SDL_Quit;
end.  

A to je vše. Já osobně, až budu někdy něco programovat pro Windows (třeba SW na tvorbu animovaných filmů), použiji LX5Suite spolu s jednou z jednotek na zvuk (buď BASS nebo FMOD). Jedi si mě bohužel moc nezískalo (ani nevím proč - možná kvůli tomu C, nebo přílišnému "nepořádku" ve složkách), i když zase až tak moc těžké není (ale spíše jsem trochu líný programovat až tak moc nízko u OS, kromě DOSu ovšem :-D). Příště se podíváme na tvorbu vlastního překladače pro náš vlastní operační systém, ve kterém budeme moci psát programy jako v Pascalu, ale kompilovat je pro náš OS jako binární soubory pomocí assembleru.

2007-01-03 | Martin Lux
Reklamy: