Added 3D Audio System
This commit is contained in:
parent
7e07278368
commit
52d4b5d2f6
203
src/raudio.c
203
src/raudio.c
|
|
@ -299,6 +299,10 @@ typedef struct tagBITMAPINFOHEADER {
|
||||||
#define MAX_AUDIO_BUFFER_POOL_CHANNELS 16 // Audio pool channels
|
#define MAX_AUDIO_BUFFER_POOL_CHANNELS 16 // Audio pool channels
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef MAX_3DSOUND_SOURCES
|
||||||
|
#define MAX_3DSOUND_SOURCES 25 // Max Number of 3D Audio Slots
|
||||||
|
// NOTE: Please change this if you need more Sounds.
|
||||||
|
#endif
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Types and Structures Definition
|
// Types and Structures Definition
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
@ -393,6 +397,31 @@ typedef struct AudioData {
|
||||||
rAudioProcessor *mixedProcessor;
|
rAudioProcessor *mixedProcessor;
|
||||||
} AudioData;
|
} AudioData;
|
||||||
|
|
||||||
|
// NOTE: This is not exposed to raylib.h, meant for backend use only.
|
||||||
|
typedef struct Listener3D {
|
||||||
|
Vector3 position;
|
||||||
|
Vector3 forward;
|
||||||
|
Vector3 up;
|
||||||
|
} Listener3D;
|
||||||
|
|
||||||
|
// NOTE: This is not exposed to raylib.h, meant for backend use only.
|
||||||
|
typedef struct Audio3D {
|
||||||
|
Sound sound;
|
||||||
|
Vector3 position;
|
||||||
|
float maxVolume;
|
||||||
|
float pan;
|
||||||
|
float minDistance;
|
||||||
|
float maxDistance;
|
||||||
|
bool available;
|
||||||
|
} Audio3D;
|
||||||
|
|
||||||
|
// NOTE: This is not exposed to raylib.h, meant for backend use only.
|
||||||
|
typedef struct SoundSystem3D {
|
||||||
|
Audio3D audioSources[MAX_3DSOUND_SOURCES];
|
||||||
|
int audioCount;
|
||||||
|
Listener3D listener;
|
||||||
|
} SoundSystem3D;
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Global Variables Definition
|
// Global Variables Definition
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
@ -406,6 +435,7 @@ static AudioData AUDIO = { // Global AUDIO context
|
||||||
.mixedProcessor = NULL
|
.mixedProcessor = NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static SoundSystem3D AudioSystem3D; // Global 3D Audio System Definition.
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Module specific Functions Declaration
|
// Module specific Functions Declaration
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
@ -2706,6 +2736,179 @@ static void UpdateAudioStreamInLockedState(AudioStream stream, const void *data,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 3D Audio Functionality
|
||||||
|
void InitAudioSystem3D() {
|
||||||
|
if (IsAudioDeviceReady()) {
|
||||||
|
AudioSystem3D.listener.position = (Vector3){ 0, 0, 0 };
|
||||||
|
AudioSystem3D.audioCount = 0;
|
||||||
|
|
||||||
|
TRACELOG(LOG_INFO, "AUDIO: 3D Audio System initialized successfully");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnloadAudioSystem3D() {
|
||||||
|
for (int i = 0; i < AudioSystem3D.audioCount; i++) {
|
||||||
|
UnloadSound(AudioSystem3D.audioSources[i].sound);
|
||||||
|
AudioSystem3D.audioSources[i].available = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BindListenerToCamera(Camera3D camera) {
|
||||||
|
AudioSystem3D.listener.position = camera.position;
|
||||||
|
|
||||||
|
Vector3 forward = {
|
||||||
|
camera.target.x - camera.position.x,
|
||||||
|
camera.target.y - camera.position.y,
|
||||||
|
camera.target.z - camera.position.z
|
||||||
|
};
|
||||||
|
|
||||||
|
float length = sqrtf(forward.x * forward.x + forward.y * forward.y + forward.z * forward.z);
|
||||||
|
if (length > 0.0f) {
|
||||||
|
forward.x /= length;
|
||||||
|
forward.y /= length;
|
||||||
|
forward.z /= length;
|
||||||
|
}
|
||||||
|
|
||||||
|
AudioSystem3D.listener.forward = forward;
|
||||||
|
AudioSystem3D.listener.up = camera.up;
|
||||||
|
}
|
||||||
|
|
||||||
|
Sound3D LoadSound3D(const char *path) {
|
||||||
|
Sound3D audio = { 0 };
|
||||||
|
bool openSpotFound = false;
|
||||||
|
int foundSpot = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < AudioSystem3D.audioCount; i++) {
|
||||||
|
if (AudioSystem3D.audioSources[i].available) {
|
||||||
|
foundSpot = i;
|
||||||
|
openSpotFound = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (openSpotFound) {
|
||||||
|
audio.audioID = foundSpot;
|
||||||
|
AudioSystem3D.audioSources[foundSpot].sound = LoadSound(path);
|
||||||
|
AudioSystem3D.audioSources[foundSpot].available = false;
|
||||||
|
} else {
|
||||||
|
if (AudioSystem3D.audioCount == MAX_3DSOUND_SOURCES) {
|
||||||
|
TraceLog(LOG_WARNING, "AUDIO: Max 3D sound sources reached");
|
||||||
|
return (Sound3D){ .audioID = -1 };
|
||||||
|
}
|
||||||
|
|
||||||
|
audio.audioID = AudioSystem3D.audioCount;
|
||||||
|
AudioSystem3D.audioSources[audio.audioID].sound = LoadSound(path);
|
||||||
|
AudioSystem3D.audioSources[audio.audioID].available = false;
|
||||||
|
AudioSystem3D.audioCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return audio;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnloadSound3D(Sound3D sound3D) {
|
||||||
|
UnloadSound(AudioSystem3D.audioSources[sound3D.audioID].sound);
|
||||||
|
AudioSystem3D.audioSources[sound3D.audioID].available = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateAudioSystem3D() {
|
||||||
|
for (int i = 0; i < AudioSystem3D.audioCount; i++) {
|
||||||
|
if (IsSoundPlaying(AudioSystem3D.audioSources[i].sound)) {
|
||||||
|
Vector3 position = AudioSystem3D.audioSources[i].position;
|
||||||
|
float maxDistance = AudioSystem3D.audioSources[i].maxDistance;
|
||||||
|
float minDistance = AudioSystem3D.audioSources[i].minDistance;
|
||||||
|
float maxVolume = AudioSystem3D.audioSources[i].maxVolume;
|
||||||
|
|
||||||
|
Vector3 toSource = {
|
||||||
|
position.x - AudioSystem3D.listener.position.x,
|
||||||
|
position.y - AudioSystem3D.listener.position.y,
|
||||||
|
position.z - AudioSystem3D.listener.position.z
|
||||||
|
};
|
||||||
|
|
||||||
|
float distance = sqrtf(toSource.x * toSource.x + toSource.y * toSource.y + toSource.z * toSource.z);
|
||||||
|
|
||||||
|
// Volume attenuation
|
||||||
|
float volume = 0.0f;
|
||||||
|
if (distance <= minDistance) {
|
||||||
|
volume = maxVolume;
|
||||||
|
} else if (distance < maxDistance) {
|
||||||
|
float t = (distance - minDistance) / (maxDistance - minDistance);
|
||||||
|
volume = maxVolume * (1.0f - t);
|
||||||
|
}
|
||||||
|
if (volume < 0.0f) volume = 0.0f;
|
||||||
|
if (volume > maxVolume) volume = maxVolume;
|
||||||
|
|
||||||
|
// Orientation vectors
|
||||||
|
Vector3 forward = AudioSystem3D.listener.forward;
|
||||||
|
float forwardLen = sqrtf(forward.x * forward.x + forward.y * forward.y + forward.z * forward.z);
|
||||||
|
if (forwardLen > 0.0f) {
|
||||||
|
forward.x /= forwardLen;
|
||||||
|
forward.y /= forwardLen;
|
||||||
|
forward.z /= forwardLen;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector3 up = AudioSystem3D.listener.up;
|
||||||
|
float upLen = sqrtf(up.x * up.x + up.y * up.y + up.z * up.z);
|
||||||
|
if (upLen > 0.0f) {
|
||||||
|
up.x /= upLen;
|
||||||
|
up.y /= upLen;
|
||||||
|
up.z /= upLen;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector3 right = {
|
||||||
|
up.y * forward.z - up.z * forward.y,
|
||||||
|
up.z * forward.x - up.x * forward.z,
|
||||||
|
up.x * forward.y - up.y * forward.x
|
||||||
|
};
|
||||||
|
|
||||||
|
float rightLen = sqrtf(right.x * right.x + right.y * right.y + right.z * right.z);
|
||||||
|
if (rightLen > 0.0f) {
|
||||||
|
right.x /= rightLen;
|
||||||
|
right.y /= rightLen;
|
||||||
|
right.z /= rightLen;
|
||||||
|
}
|
||||||
|
|
||||||
|
float localX = toSource.x * right.x + toSource.y * right.y + toSource.z * right.z;
|
||||||
|
float localY = toSource.x * up.x + toSource.y * up.y + toSource.z * up.z;
|
||||||
|
float localZ = toSource.x * forward.x + toSource.y * forward.y + toSource.z * forward.z;
|
||||||
|
|
||||||
|
// Panning calculation
|
||||||
|
float pan = 0.0f;
|
||||||
|
float horizDist = sqrtf(localX * localX + localZ * localZ);
|
||||||
|
if (horizDist > 0.001f) {
|
||||||
|
pan = localX / horizDist;
|
||||||
|
}
|
||||||
|
pan += (localY / 20.0f) * 0.2f;
|
||||||
|
|
||||||
|
if (pan < -1.0f) pan = -1.0f;
|
||||||
|
if (pan > 1.0f) pan = 1.0f;
|
||||||
|
|
||||||
|
SetSoundVolume(AudioSystem3D.audioSources[i].sound, volume);
|
||||||
|
SetSoundPan(AudioSystem3D.audioSources[i].sound, pan);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlaySound3D(Sound3D sound3D, Vector3 position, float maxVolume, float minDistance, float maxDistance) {
|
||||||
|
int id = sound3D.audioID;
|
||||||
|
AudioSystem3D.audioSources[id].position = position;
|
||||||
|
AudioSystem3D.audioSources[id].maxDistance = maxDistance;
|
||||||
|
AudioSystem3D.audioSources[id].minDistance = minDistance;
|
||||||
|
AudioSystem3D.audioSources[id].maxVolume = maxVolume;
|
||||||
|
|
||||||
|
PlaySound(AudioSystem3D.audioSources[id].sound);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsSound3DPlaying(Sound3D sound3D) {
|
||||||
|
return IsSoundPlaying(AudioSystem3D.audioSources[sound3D.audioID].sound);
|
||||||
|
}
|
||||||
|
|
||||||
|
void StopSound3D(Sound3D sound3D) {
|
||||||
|
if (IsSoundPlaying(AudioSystem3D.audioSources[sound3D.audioID].sound)) {
|
||||||
|
StopSound(AudioSystem3D.audioSources[sound3D.audioID].sound);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Some required functions for audio standalone module version
|
// Some required functions for audio standalone module version
|
||||||
#if defined(RAUDIO_STANDALONE)
|
#if defined(RAUDIO_STANDALONE)
|
||||||
// Check file extension
|
// Check file extension
|
||||||
|
|
|
||||||
16
src/raylib.h
16
src/raylib.h
|
|
@ -476,6 +476,11 @@ typedef struct Sound {
|
||||||
unsigned int frameCount; // Total number of frames (considering channels)
|
unsigned int frameCount; // Total number of frames (considering channels)
|
||||||
} Sound;
|
} Sound;
|
||||||
|
|
||||||
|
// 3D Sound
|
||||||
|
typedef struct Sound3D {
|
||||||
|
int audioID; // Audio Identifier
|
||||||
|
} Sound3D;
|
||||||
|
|
||||||
// Music, audio stream, anything longer than ~10 seconds should be streamed
|
// Music, audio stream, anything longer than ~10 seconds should be streamed
|
||||||
typedef struct Music {
|
typedef struct Music {
|
||||||
AudioStream stream; // Audio stream
|
AudioStream stream; // Audio stream
|
||||||
|
|
@ -1666,6 +1671,17 @@ RLAPI void WaveFormat(Wave *wave, int sampleRate, int sampleSize, int channels);
|
||||||
RLAPI float *LoadWaveSamples(Wave wave); // Load samples data from wave as a 32bit float data array
|
RLAPI float *LoadWaveSamples(Wave wave); // Load samples data from wave as a 32bit float data array
|
||||||
RLAPI void UnloadWaveSamples(float *samples); // Unload samples data loaded with LoadWaveSamples()
|
RLAPI void UnloadWaveSamples(float *samples); // Unload samples data loaded with LoadWaveSamples()
|
||||||
|
|
||||||
|
// 3D Sound Playback functions
|
||||||
|
RLAPI void InitAudioSystem3D(); // Initialize the 3D Functionality
|
||||||
|
RLAPI void UnloadAudioSystem3D(); // Clears all the allocated 3D Sounds
|
||||||
|
RLAPI void UpdateAudioSystem3D(); // Used to update playback on 3D Sounds
|
||||||
|
RLAPI void BindListenerToCamera(Camera3D camera); // Sets playback to camera position
|
||||||
|
RLAPI Sound3D LoadSound3D(const char *path); // Load from a file
|
||||||
|
RLAPI void UnloadSound3D(Sound3D sound3D); // Free up your memory kids
|
||||||
|
RLAPI void PlaySound3D(Sound3D sound3D, Vector3 position, float maxVolume, float minDistance, float maxDistance); // Play sound at position and parameters
|
||||||
|
RLAPI void StopSound3D(Sound3D sound3D); // Stop sound
|
||||||
|
RLAPI bool IsSound3DPlaying(Sound3D sound3D); // Check if sound is playing.
|
||||||
|
|
||||||
// Music management functions
|
// Music management functions
|
||||||
RLAPI Music LoadMusicStream(const char *fileName); // Load music stream from file
|
RLAPI Music LoadMusicStream(const char *fileName); // Load music stream from file
|
||||||
RLAPI Music LoadMusicStreamFromMemory(const char *fileType, const unsigned char *data, int dataSize); // Load music stream from data
|
RLAPI Music LoadMusicStreamFromMemory(const char *fileType, const unsigned char *data, int dataSize); // Load music stream from data
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user