barra horizontal azul
simbolo minerva da ufrj

A Biblioteca Multimídia SDL

Valid HTML 4.0!
barra horizontal azul
©2007 - Bruno Bottino Ferreira

  1. Introdução
  2. Programa básico em SDL
  3. Funções gerais e tratamento de janelas
    1. Inicialização e deinicialização
    2. Tratamento de erros
    3. Tratamento de janelas
  4. O subsistema de vídeo
    1. Definições básicas
    2. Conseguindo informações sobre o hardware de vídeo
    3. Criando uma janela
    4. Atualizando a tela
    5. Ajustando o Gamma da tela
    6. Trabalhando com pixels
    7. Trabalhando com superfícies
    8. Carregando e salvando imagens BMP
    9. Trabalhando com transparências
    10. Máscaras
    11. Convertendo superfícies
    12. Desenhando retângulos
    13. Copiando superfícies (blitting)
    14. O cursor do mouse
  5. Eventos
    1. O que são eventos?
    2. Trabalhando com eventos
    3. Tipos de eventos
  6. Joysticks
  7. Temporizadores (Timers)
  8. Utilizando áudio com SDL_mixer
  9. Carregando imagens com SDL_image
  10. Desenhando texto com SDL_ttf
  11. Apêndice A: Códigos de teclas
  12. Apêndice B: Palestra sobre SDL
barra horizontal azul

Utilizando áudio com SDL_mixer

A própria SDL provê maneiras de se trabalhar com som, mas em um nível muito baixo (preenchimento de um buffer de saída através de uma função callback), então usaremos a biblioteca auxiliar SDL_mixer, que trabalha de uma maneira bem mais intuitiva. Observe que a biblioteca SDL_mixer não será explicada em sua totalidade nem com muita riqueza de detalhes--queremos apenas o suficiente para suprir as deficiências da SDL, ou seja, tocar arquivos de som e músicas sem muitas firulas.

Instalando

Visite http://www.libsdl.org/projects/SDL_mixer/ e baixe a versão de desenvolvimento mais recente para o seu sistema. No Linux, a melhor opção geralmente é baixar o pacote, enquanto no Windows com MinGW sua melhor opção é baixar o ZIP de desenvolvimento para Visual C++ (SDL_mixer-devel-x.y.z-VC8.zip) e copiar as pastas include e lib sobre as respectivas no MinGW. Para compilar então, apenas adicione -lSDL_mixer à linha de comando padrão para compilar programas em SDL; no Windows:

gcc ex1.c -o ex1.exe -Wall -lmingw32 -lSDLmain -lSDL -lSDL_mixer

E no GNU/Linux:

gcc ex1.c -o ex1 -Wall `sdl-config --cflags --libs` -lSDL_mixer

Finalmente, em todos os arquivos onde vocês desejar utilizar funções da biblioteca SDL_mixer, é necessário incluir o header adequado:

#include <SDL_mixer.h>

Inicialização e tratamento de erros

Observe que, antes de poder usar SDL_mixer, é preciso passar SDL_INIT_AUDIO para SDL_Init ou SDL_InitSubsystem.

int Mix_OpenAudio(int frequency, Uint16 format, int channels, int chunksize);
int Mix_QuerySpec(int *frequency, Uint16 *format, int *channels);
void Mix_CloseAudio();

A função Mix_OpenAudio inicializa a biblioteca SDL_mixer e deve ser chamada antes de se utilizar qualquer outra, e após SDL_Init. Existem constantes definidas pela biblioteca como valor padrão que podem ser passadas a a alguns dos parâmetos abaixo. Explicando os parâmetros:
- frequency: A frequência da onda sonora de saída (após a mixagem final), em Hertz. 44100 é qualidade de CD, 22050 é qualidade de fita K7. Em geral use 44100 se puder, ou 22050 para ganhar mais eficiência (a custo da qualidade do som). Padrão: MIX_DEFAULT_FREQUENCY (22050).
- format: O formato em que cada amostra é armazenada. Isto engloba se as amostras terão sinal (signed) ou não (unsigned), se terão 8 ou 16 bits, e caso tenham 16, se os dois bytes serão armazenados em little-endian ou big-endian (para mais detalhes sobre endianness, veja aqui, em inglês). Em geral, o que importa mais é o tamanho da amostra, ou seja, 8 ou 16 bits, que influem na qualidade do som. Além disso, geralmente você usará amostras com sinal. Então, se quiser 8 bits (bixa qualidade, mais velocidade) use AUDIO_S8, e se quiser 16 bits (alta qualidade, menos velocidade) use AUDIO_S16SYS (16 bits com a mesma endianness do sistema hospedeiro). Padrão: MIX_DEFAULT_FORMAT (AUDIO_S16SYS).
- channels: Número de canais de saída. Passe 1 para mono ou 2 para estéreo.
- chunksize:: Tamanho do buffer de saída. Valores entre 1024 e 4096 (1KB e 4KB, respectivamente) são uma boa faixa. Se este valor for muito grande, a reprodução poderá ficar atrasada, e se for muito pequeno, o som poderá "engasgar". 4096 é um valor bem adequado para 16-bits e 44100 hz.

Em geral, uma boa chamada de inicialização (para alta qualidade de som estéreo) seria:

Mix_OpenAudio(44100, MIXER_DEFAULT_FORMAT, 2, 4096);

Após ter inicializado o som, você pode chamar Mix_QuerySpec para descobrir quais foram os valores passados na inicialização, passando endereços (ponteiros) como parâmetros para Mix_QuerySpec--cada valor retornado corresponde ao seu homônimo em Mix_OpenAudio. Exemplo:

int freq, fmt, chan;

Mix_QuerySpec(&freq, &fmt, &channels);
printf("O som foi inicializado em %d Hz, formato = %d em modo %s.\n", freq, fmt, (chan == 1 ? "mono" : "estereo"));

Adicionalmente, você pode chamar Mix_CloseAudio() a qualquer momento para deinicializar o áudio. Provavelmente você fará isto ao final do seu programa, mas esta função pode ser útil também para inicializar novamente o sistema de som com configurações diferentes (por exemplo, estéreo em vez de mono).

char *Mix_GetError();

Você pode utilizar Mix_GetError para ter um string com a descrição do último erro ocorrido dentro da biblioteca SDL_mixer--o seu uso é análogo a SDL_GetError (vide seção respectiva).

Carregando arquivos de som

Mix_Chunk *Mix_LoadWAV(char *file);
int Mix_VolumeChunk(Mix_Chunk *chunk, int volume);
void Mix_FreeChunk(Mix_Chunk *chunk);

Um Mix_Chunk, como é chamado pela biblioteca, é o que chamaremos de "som" daqui em diante--representa um arquivo de som (tipo wave) carregado na memória. Sendo assim, para carregar um som do disco e armazená-lo em uma estrutura Mix_Chunk basta utilizar a função Mix_LoadWAV passando um caminho absoluto ou relativo indicando onde está seu arquivo, em formato .wav ou .voc. Após carregado, você pode alterar o volume de um som previamente carregado utilizando a função Mix_VolumeChunk (que toma como parâmetros um ponteiro para o som e o volume desejado, entre 0 e MIX_MAX_VOLUME = 128). Desta forma, sempre que este som for tocado ele o será com o volume especificado, combinado com o volume geral do canal de saída. Após ter terminado com um som (geralmente ao fim do seu programa, mas poderia ser, por exemplo, ao fim de uma fase), você deve liberá-lo com Mix_FreeChunk, passando seu respectivo ponteiro. Exemplo de utilização segue abaixo. Observe que não é preciso se preocupar com os ponteiros, basta apenas declarar sua variável como um ponteiro e passá-la a todas as funções, assim como uma SDL_Surface:

Mix_Chunk* boom_snd = Mix_LoadWAV("boom.wav"); /* supondo que boom.wav esteja na pasta do seu programa */
Mix_VolumeChunk(boom_snd, 64); /* quero que ele toque com meio volume */

/* seu programa rodando e tocando o som... */

Mix_FreeChunk(boom_snd); /* liberando na saída... */

Trabalhando com canais e tocando sons

Para tocar sons com SDL_mixer, você precisa alocar canais de saída. Estes funcionam analogamente a uma mesa de som: você tem vários canais com uma entrada (por exemplo, um microfone, ou no caso, uma estrutura de som), atributos (volume, efeitos) e uma saída. As saídas serão combinadas pela biblioteca para gerar a saída final que será tocada.

int Mix_AllocateChannels(int numchans);
int Mix_Volume(int channel, int volume);

Antes de poder tocar algum som, precisamos definir quantos canais de saída desejamos. Para isso, basta usar a função Mix_AllocateChannels, passando o número de canais desejado. Após isto, podemos definir o volume da saída de um canal específico com Mix_Volume, passando o número do canal e o volume desejado. Observe que os canais começam a ser contados em zero, e passando -1 como canal significa que o volume de todos os canais será ajustado. Além disso, volume varia entre 0 (mudo) e MIX_MAX_VOLUME(128 - máximo).

int Mix_PlayChannel(int channel, Mix_Chunk *chunk, int loops);
int Mix_FadeInChannel(int channel, Mix_Chunk *chunk, int loops, int ms);

Utilize a função Mix_PlayChannel para tocar um som em um determinado canal, sem fade-in (começando com volume máximo). Observe que cada canal só pode tocar um som de cada vez, ou seja, ao mandar tocar um som em um canal, se outro estiver em execução no momento, esta será interrompida. Passe o canal desejado em channel (ou -1 para o primeiro canal disponível), o ponteiro para o som desejado (previamente carregado) em chunk e em loops o número de vezes que o som será tocado após a primeira (ou seja, 0 toca uma vez, 1 toca duas vezes, e assim por diante). Passe -1 para tocar para sempre.

Da mesma forma, utilize a função Mix_FadeInChannel para tocar um som com um aumento gradual de volume (fade-in). Além dos parâmetros análogos a Mix_PlayChannel, ms indica o número de milissegundos que irá durar o efeito (tempo até o volume chegar a a 100%).

void Mix_Pause(int channel);
void Mix_Resume(int channel);
int Mix_HaltChannel(int channel);
int Mix_FadeOutChannel(int channel, int ms);

Utilize as funções Mix_Pause e Mix_Resume para pausar e "despausar" (voltar a tocar) um canal (channel). Analogamente, Mix_HaltChannel para parar completamente a reprodução de um certo canal, e Mix_FadeOutChannel para fazer um canal parar gradualmente (diminuindo o volume), sendo que ele irá demorar ms milissegundos para parar completamente. Para todas estas, passe -1 em channel para afetar a todos os canais.

int Mix_Playing(int channel);
int Mix_Paused(int channel);

As funções Mix_Playing e Mix_Paused retornam se em um canal há um som sendo tocado no momento, e se ele está pausado, respescitvamente. Observe que se você pausar um canal com Mix_Pause, e depois interrompê-lo com Mix_HaltChannel, Mix_Paused ainda retornará 1 (verdadeiro). Passando -1 em channel retornará quantos canais estão tocando, ou pausados.

Trabalhando com música

Não é preciso reservar canais para tocar música; em uma essência, há um único canal sempre reservado para tocar músicas. Uma música é representada por um ponteiro para Mix_Music. Os formatos de música suportados por SDL_mixer são Ogg Vorbis (.ogg), MPEG-1 Layer 3 (.mp3), .mod, .s3m, .it, .xm e MIDI (.mid). Para tocar MIDI, é preciso instalar os arquivos contidos neste link em /usr/local/lib/ em sistemas Unix/Linux, ou C:\ em sistemas Windows.

Mix_Music *Mix_LoadMUS(const char *file);
void Mix_FreeMusic(Mix_Music *music);

Carregue uma música do arquivo file para um ponteiro Mix_Music com a função Mix_LoadMUS. Quando tiver terminado de usá-la (provavelmente ao fim do programa), chame Mix_FreeMusic para liberar os recursos alocados.

int Mix_PlayMusic(Mix_Music *music, int loops);
int Mix_FadeInMusic(Mix_Music *music, int loops, int ms);
int Mix_VolumeMusic(int volume);

Chame Mix_PlayMusic para tocar uma música previamente carregada em music, repetida loops vezes (analogamente a sons: 0 significa uma reprodução, 1 duas, etc, e -1 infinitamente). Chame Mix_FadeInMusic com os parâmetros análogos a Mix_PlayMusic para iniciar uma música com efeito de fade-in (volume aumentando gradualmente), sendo que a música levará ms milissegundos para atingir seu volume total. Chame Mix_VolumeMusic para ajustar o volume de saída da música (lembrando que é só um canal). Os volumes variam entre 0 e MIX_MAX_VOLUME(128). Passe -1 para retornar o volume atual.

void Mix_PauseMusic();
void Mix_ResumeMusic();
void Mix_RewindMusic();

Chame Mix_PauseMusic para pausar uma música, certificando-se que ela está em execução, e Mix_ResumeMusic para que ela volte a tocar. Chame Mix_RewindMusic para retornar a música ao início, observando que isto só funciona para MOD, OGG, MP3 e MIDI.

int Mix_HaltMusic();
int Mix_FadeOutMusic(int ms);

Mix_HaltMusic pára a música tocando atualmente. Mix_FadeOutMusic a faz parar gradualmente, diminuindo o volume, sobre um tempo de ms milissegundos.

int Mix_PlayingMusic();
int Mix_PausedMusic();

Mix_PlayingMusic retorna se há uma música tocando (ainda que pausada), e Mix_PausedMusic retorna se há uma música pausada (ainda que tenha sido parada enquanto pausada).

barra horizontal azul
Anterior
Topo da página
Próximo