⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 audio.c

📁 Linux游戏编程源码
💻 C
字号:
#include <math.h>#include <stdio.h>#include <stdlib.h>#include "audio.h"#include "resources.h"/* Include the OpenAL headers. */#include <AL/al.h>#include <AL/alc.h>/* Factor to control attenuation of audio.   We'll divide all coordinates by this factor each time we update   the source positions. OpenAL does provide a cleaner way to do this,   but it changed recently. */#define DISTANCE_FACTOR 50.0/* We'll set this flag to 1 after audio has been successfully initialized. */int audio_enabled = 0;/* Our OpenAL context. This is just like an OpenGL context, if you're familiar   with GL's workings. A context represents a combination of a particular   output device, a sampling frequency, and so on. */ALvoid *audio_context = NULL;/* An output device. We'll set this to AL's default in InitAudio().  */ALCdevice *audio_device = NULL;/* Our sources. Sources are objects in 3D space that emit sound.   We're ignoring the fact that there's no sound in space. */static ALuint opponent_engine_source;static ALuint opponent_phaser_source;/* There is no player engine source; see note in StartAudio below. */static ALuint player_phaser_source;void InitAudio(){    int err;    /* Create a context with whatever settings are available.       We could replace NULL with a list of parameters. See the       OpenAL spec for a current list.       We use alcGetError instead of alGetError for error detection.       This is because error conditions are stored within contexts,       and it's pretty meaningless to retrieve an error code from       something that does not yet exist. */    audio_device = alcOpenDevice(NULL);    if (audio_device == NULL)	fprintf(stderr, "Warning: NULL device.\n");    else	fprintf(stderr, "Got a device.\n");    audio_context = alcCreateContext(audio_device, NULL);    err = alcGetError();    if (err != ALC_NO_ERROR || audio_context == NULL) {	fprintf(stderr, "Unable to create an OpenAL context (%s). Audio disabled.\n", alGetString(err));	return;    }    /* Make sure we have a chance to clean up. */    atexit(CleanupAudio);    /* Now make the context current. The current context is the subject       of all OpenAL API calls. Some calls will even segfault if there isn't       a valid current context. */    alcMakeContextCurrent(audio_context);    if (alcGetError() != ALC_NO_ERROR) {	fprintf(stderr, "Unable to make OpenAL context current. Audio disabled.\n");	goto error_cleanup;    }    /* Good. Now create some sources (things that make noise). These will be       given buffers later. Sources don't do anything until you associate       them with buffers (which contain PCM sound data). */    alGenSources(1, &opponent_engine_source);    alGenSources(1, &opponent_phaser_source);    alGenSources(1, &player_phaser_source);    if (alGetError() != AL_NO_ERROR) {	fprintf(stderr, "Unable to allocate audio sources. Audio disabled.\n");	goto error_cleanup;    }    /* Ready to go. */    audio_enabled = 1;    printf("Audio enabled. OpenAL information:\n");    printf("  Version:    %s\n", alGetString(AL_VERSION));    printf("  Renderer:   %s\n", alGetString(AL_RENDERER));    printf("  Vendor:     %s\n", alGetString(AL_VENDOR));    printf("  Extensions: %s\n", alGetString(AL_EXTENSIONS));    return;    /* Invoked on error. Cleans up the context. */ error_cleanup:    alcMakeContextCurrent(NULL);    alcDestroyContext(audio_context);}void CleanupAudio(){    /* If OpenAL is initialized, clean up. */    if (audio_enabled) {	/* Never try to destroy an active context. */	alcMakeContextCurrent(NULL);	alcDestroyContext(audio_context);	alcCloseDevice(audio_device);	audio_context = NULL;	audio_enabled = 0;    }}void UpdateAudio(player_p player, player_p opponent){    ALfloat position[3];    ALfloat velocity[3];    ALfloat orientation[6];    /* Is audio enabled? */    if (!audio_enabled)	return;    /* The player is the listener. Set the listener's position to       the player's position. */    position[0] = (ALfloat)player->world_x / DISTANCE_FACTOR;    position[1] = (ALfloat)player->world_y / DISTANCE_FACTOR;    position[2] = (ALfloat)0.0;    alListenerfv(AL_POSITION, position);    /* Set the player's orientation in space. The first three values are       the "up" vector (sticking out of the ship's cockpit), and the next       three are the "at" vector (sticking out of the ship's nose). */    orientation[0] = 0;    orientation[1] = 0;    orientation[2] = 1.0;    orientation[3] = -cos(player->angle*PI/180.0);    orientation[4] = sin(player->angle*PI/180.0);    orientation[5] = 0;    alListenerfv(AL_ORIENTATION, orientation);    /* To properly simulate the Doppler effect, OpenAL needs to       know the listener's velocity (as a vector). */    velocity[0] = (ALfloat)player->velocity *	cos(player->angle*PI/180.0) / DISTANCE_FACTOR;    velocity[1] = (ALfloat)player->velocity *	-sin(player->angle*PI/180.0) / DISTANCE_FACTOR;    velocity[2] = (ALfloat)0.0;    alListenerfv(AL_VELOCITY, velocity);    /* The player's weapon is obviously at the location of the player.       This source won't do anything until we add weapons to the game. */    alSourcefv(player_phaser_source, AL_POSITION, position);    alSourcefv(player_phaser_source, AL_VELOCITY, velocity);    /* Now for the enemy's information. */    position[0] = (ALfloat)opponent->world_x / DISTANCE_FACTOR;    position[1] = (ALfloat)opponent->world_y / DISTANCE_FACTOR;    position[2] = (ALfloat)0.0;    alSourcefv(opponent_engine_source, AL_POSITION, position);    alSourcefv(opponent_phaser_source, AL_POSITION, position);    velocity[0] = (ALfloat)opponent->velocity *	cos(opponent->angle*PI/180.0) / DISTANCE_FACTOR;    velocity[1] = (ALfloat)opponent->velocity *	-sin(opponent->angle*PI/180.0) / DISTANCE_FACTOR;    velocity[2] = (ALfloat)0.0;    alSourcefv(opponent_engine_source, AL_VELOCITY, velocity);    alSourcefv(opponent_phaser_source, AL_VELOCITY, velocity);}void StartAudio(){    /* Activate the opponent's engine noise. We won't attach an engine noise       to the player, because quite frankly it would be annoying, though perhaps       a bit more realistic. */    if (audio_enabled) {	alSourcei(opponent_engine_source, AL_BUFFER, engine_sound.name); /* assign a buffer */	alSourcei(opponent_engine_source, AL_LOOPING, 1);   /* enable looping */	alSourcePlay(opponent_engine_source); /* set it to playback mode */    }}void StopAudio(){    /* Stop all sources. */    if (audio_enabled) {	alSourceStop(opponent_engine_source);	alSourceStop(opponent_phaser_source);	alSourceStop(player_phaser_source);    }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -