Tutorial Allegro 5 #7 – Manipulando Áudio

Padrão

Olá, pessoal! Continuando a série sobre Allegro 5, hoje veremos como manipular arquivos de áudio. Para a manipulação de áudio, o Allegro fornece o add-on allegro_audio. É através desta biblioteca que os controles, alocação e demais tarefas relativas a áudio. Porém, somente ela não permite a utilização dos formatos de áudio. Para complementar, utilizamos o add-on allegro_acodec, que nos fornece suporte a alguns formatos, como Ogg, Flac e Wave (não, infelizmente mp3 não está disponível).

Para exemplificar o uso de arquivos de áudio, vamos fazer um aplicativo que tocará uma música de fundo (no formato Ogg) de modo contínuo e toca um sample (no formato Wave) quando você pressiona a barra de espaço.

Vamos dar uma olhada no código e em seguida discutiremos sobre as novas funcionalidades presentes nele.

#include <allegro5/allegro.h>
#include <allegro5/allegro_audio.h>
#include <allegro5/allegro_acodec.h>
#include <stdio.h>

const int LARGURA_TELA = 640;
const int ALTURA_TELA = 480;

ALLEGRO_DISPLAY *janela = NULL;
ALLEGRO_AUDIO_STREAM *musica = NULL;
ALLEGRO_SAMPLE *sample = NULL;
ALLEGRO_EVENT_QUEUE *fila_eventos = NULL;

bool inicializar();

int main(void)
{
    bool sair = false;

    if (!inicializar())
    {
        return -1;
    }

    al_attach_audio_stream_to_mixer(musica, al_get_default_mixer());
    al_set_audio_stream_playing(musica, true);

    while (!sair)
    {
        while (!al_is_event_queue_empty(fila_eventos))
        {
            ALLEGRO_EVENT evento;
            al_wait_for_event(fila_eventos, &evento);

            if (evento.type == ALLEGRO_EVENT_KEY_UP)
            {
                if (evento.keyboard.keycode == ALLEGRO_KEY_SPACE)
                {
                    al_play_sample(sample, 1.0, 0.0, 1.0, ALLEGRO_PLAYMODE_ONCE, NULL);
                }
            }
            else if (evento.type == ALLEGRO_EVENT_DISPLAY_CLOSE)
            {
                sair = true;
            }
        }
    }

    al_destroy_audio_stream(musica);
    al_destroy_sample(sample);
    al_destroy_event_queue(fila_eventos);
    al_destroy_display(janela);

    return 0;
}

bool inicializar()
{
    if (!al_init())
    {
        fprintf(stderr, "Falha ao inicializar Allegro.\n");
        return false;
    }

    if (!al_install_audio())
    {
        fprintf(stderr, "Falha ao inicializar áudio.\n");
        return false;
    }

    if (!al_init_acodec_addon())
    {
        fprintf(stderr, "Falha ao inicializar codecs de áudio.\n");
        return false;
    }

    if (!al_reserve_samples(1))
    {
        fprintf(stderr, "Falha ao alocar canais de áudio.\n");
        return false;
    }

    if (!al_install_keyboard())
    {
        fprintf(stderr, "Falha ao inicializar teclado.\n");
        return false;
    }

    janela = al_create_display(LARGURA_TELA, ALTURA_TELA);
    if (!janela)
    {
        fprintf(stderr, "Falha ao criar a janela.\n");
        return false;
    }

    sample = al_load_sample("palmas.wav");
    if (!sample)
    {
        fprintf(stderr, "Falha ao carregar sample.\n");
        al_destroy_display(janela);
        return false;
    }

    fila_eventos = al_create_event_queue();
    if (!fila_eventos)
    {
        fprintf(stderr, "Falha ao criar fila de eventos.\n");
        al_destroy_display(janela);
        al_destroy_sample(sample);
        return false;
    }

    al_set_window_title(janela, "Testando sons");

    musica = al_load_audio_stream("mus.ogg", 4, 1024);
    if (!musica)
    {
        fprintf(stderr, "Falha ao carregar audio.\n");
        al_destroy_event_queue(fila_eventos);
        al_destroy_display(janela);
        al_destroy_sample(sample);
        return false;
    }

    al_register_event_source(fila_eventos, al_get_keyboard_event_source());
    al_register_event_source(fila_eventos, al_get_display_event_source(janela));

    return true;
}

Olhando o código, podemos perceber a inclusão dos dois arquivos relativos às duas bibliotecas: allegro_audio.h  e allegro_acodec.h. Em seguida, temos dois novos tipos ALLEGRO_SAMPLE e ALLEGRO_AUDIO_STREAM. O tipo ALLEGRO_SAMPLE serve para representar arquivos pequenos, geralmente efeitos sonoros (como um som de pulo, som de soco, etc.) enquanto que o ALLEGRO_AUDIO_STREAM serve para representar arquivos maiores, de forma que o arquivo não é carregado todo de uma vez para a memória. Geralmente representa os arquivos com a trilha sonora.

Na inicialização, temos duas funções relativas ao áudio: al_install_audio(), responsável por inicializar as funções relativas ao áudio e; al_init_acodec_addon() que inicializa os codecs necessários para carregar os diversos formatos de arquivo suportados pela Allegro. Em seguida, temos a função al_reserve_samples(), que recebe a quantidade de canais que devem ser alocados ao mixer principal.

Mais adiante, temos o carregamento dos arquivos de áudio, com a função al_load_sample() que recebe o arquivo que será carregado (neste exemplo, um arquivo wave) e a função al_load_audio_stream(). Esta função, por sua vez, recebe o nome do arquivo, passando-se o valor a quantidade de buffers, e a quantidade de samples. Tais valores devem ser ajustados para o melhor desempenho em cada aplicação, mas por ora, os valores acima devem funcionar.

Voltando à função main(), temos a criação do vínculo da nossa stream ao mixer principal, através da função al_attach_audio_stream_to_mixer() e em seguida declaramos que a música deve começar a tocar, através da função al_set_audio_stream_playing(), que recebe o stream e falso (0 / false) ou verdadeiro (1 / true) para iniciar ou para sua execução.

Dentro de nosso looping temos a execução do efeito sonoro condicionada ao apertar da barra de espaço. Caso tal evento ocorra, o som é executado chamando-se a função al_play_sample() que recebe o sample em questão, o ganho (1.0 representa o volume original do sample), o pan ou balanço (-1.0 totalmente à esquerda, 0.0 centralizado, 1.0 totalmente à direita), a velocidade de execução (1.0 representa a velocidade normal), a forma de execução (ALLEGRO_PLAYMODE_ONCE, ALLEGRO_PLAYMODE_LOOP ou ALLEGRO_PLAYMODE_BIDIR) e por fim um ponteiro para uma referência do sample, caso você deseje armazená-lo (no nosso caso, vamos deixar NULL).

Ao final do aplicativo, temos também as funções para desalocar os arquivos de áudio, al_destroy_audio_stream() e al_destroy_sample().

Para compilar, adicione as seguintes flags ao linker:

  • Windows: -lallegro-5.0.4-mt -lallegro_audio-5.0.4-mt -lallegro_acodec-5.0.4-mt
  • Linux: -lallegro -lallegro_audio -lallegro_acodec

Execute a aplicação para começar a tocar o arquivo mus.ogg e pressione a barra de espaços para tocar o arquivo palmas.wav. Para evitar problemas relativos a direitos autorais, não vou publicar os arquivos de áudio aqui. Caso necessite converter uma Mp3 ou qualquer outro formato para Ogg, aqui você encontra um conversor online gratuito.

Possivelmente em breve eu faça um post sobre a FMOD, outra biblioteca para a manipulação de áudio (essa sim, com suporte a Mp3 e diversos outros formatos).

Até logo, pessoal! 🙂

  • William Okano

    Olá Rafael, tudo bem?
    Primeiramente gostaria de te parabenizar por estes excelentes tutoriais sobre Allegro5, me foram (e estão sendo) bem úteis.

    Como você disse no começo deste tópico que o Allegro não roda mp3, qual seria a alternativa a isso?

    Abraços!