fixed leaks, also see pbr example review required
This commit is contained in:
parent
65e942e5be
commit
5dd8ee76ba
|
|
@ -98,7 +98,17 @@ int main(void)
|
||||||
|
|
||||||
// De-Initialization
|
// De-Initialization
|
||||||
//--------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------
|
||||||
UnloadMaterial(model.materials[0]); // Unload material: shader and textures
|
//
|
||||||
|
|
||||||
|
// REQUIRES REVIEW
|
||||||
|
// as unload model removes *just* the maps now (user may be using shaders
|
||||||
|
// and textures elsewhere) when using a custom material you need to unload
|
||||||
|
// it then give the model a default model (to avoid double free)
|
||||||
|
// how ever this still results in a small leak....
|
||||||
|
|
||||||
|
UnloadMaterial(model.materials[0]);
|
||||||
|
model.materials[0] = LoadMaterialDefault();
|
||||||
|
|
||||||
UnloadModel(model); // Unload model
|
UnloadModel(model); // Unload model
|
||||||
|
|
||||||
CloseWindow(); // Close window and OpenGL context
|
CloseWindow(); // Close window and OpenGL context
|
||||||
|
|
@ -143,7 +153,7 @@ static Material LoadMaterialPBR(Color albedo, float metalness, float roughness)
|
||||||
mat.maps[MAP_METALNESS].texture = LoadTexture("resources/pbr/trooper_metalness.png");
|
mat.maps[MAP_METALNESS].texture = LoadTexture("resources/pbr/trooper_metalness.png");
|
||||||
mat.maps[MAP_ROUGHNESS].texture = LoadTexture("resources/pbr/trooper_roughness.png");
|
mat.maps[MAP_ROUGHNESS].texture = LoadTexture("resources/pbr/trooper_roughness.png");
|
||||||
mat.maps[MAP_OCCLUSION].texture = LoadTexture("resources/pbr/trooper_ao.png");
|
mat.maps[MAP_OCCLUSION].texture = LoadTexture("resources/pbr/trooper_ao.png");
|
||||||
|
|
||||||
// Load equirectangular to cubemap shader
|
// Load equirectangular to cubemap shader
|
||||||
#if defined(PLATFORM_DESKTOP)
|
#if defined(PLATFORM_DESKTOP)
|
||||||
Shader shdrCubemap = LoadShader("resources/shaders/glsl330/cubemap.vs", "resources/shaders/glsl330/cubemap.fs");
|
Shader shdrCubemap = LoadShader("resources/shaders/glsl330/cubemap.vs", "resources/shaders/glsl330/cubemap.fs");
|
||||||
|
|
@ -171,7 +181,7 @@ static Material LoadMaterialPBR(Color albedo, float metalness, float roughness)
|
||||||
#else
|
#else
|
||||||
Shader shdrBRDF = LoadShader("resources/shaders/glsl100/brdf.vs", "resources/shaders/glsl100/brdf.fs");
|
Shader shdrBRDF = LoadShader("resources/shaders/glsl100/brdf.vs", "resources/shaders/glsl100/brdf.fs");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Setup required shader locations
|
// Setup required shader locations
|
||||||
SetShaderValue(shdrCubemap, GetShaderLocation(shdrCubemap, "equirectangularMap"), (int[1]){ 0 }, UNIFORM_INT);
|
SetShaderValue(shdrCubemap, GetShaderLocation(shdrCubemap, "equirectangularMap"), (int[1]){ 0 }, UNIFORM_INT);
|
||||||
SetShaderValue(shdrIrradiance, GetShaderLocation(shdrIrradiance, "environmentMap"), (int[1]){ 0 }, UNIFORM_INT);
|
SetShaderValue(shdrIrradiance, GetShaderLocation(shdrIrradiance, "environmentMap"), (int[1]){ 0 }, UNIFORM_INT);
|
||||||
|
|
|
||||||
13
src/models.c
13
src/models.c
|
|
@ -669,7 +669,8 @@ Model LoadModel(const char *fileName)
|
||||||
model.materials = (Material *)RL_CALLOC(model.materialCount, sizeof(Material));
|
model.materials = (Material *)RL_CALLOC(model.materialCount, sizeof(Material));
|
||||||
model.materials[0] = LoadMaterialDefault();
|
model.materials[0] = LoadMaterialDefault();
|
||||||
|
|
||||||
model.meshMaterial = (int *)RL_CALLOC(model.meshCount, sizeof(int));
|
// this is a double allocation, as LoadXXX should do it....
|
||||||
|
//model.meshMaterial = (int *)RL_CALLOC(model.meshCount, sizeof(int));
|
||||||
}
|
}
|
||||||
|
|
||||||
return model;
|
return model;
|
||||||
|
|
@ -2797,10 +2798,11 @@ static Model LoadOBJ(const char *fileName)
|
||||||
{
|
{
|
||||||
model.materialCount = materialCount;
|
model.materialCount = materialCount;
|
||||||
model.materials = (Material *)RL_CALLOC(model.materialCount, sizeof(Material));
|
model.materials = (Material *)RL_CALLOC(model.materialCount, sizeof(Material));
|
||||||
}
|
|
||||||
|
|
||||||
|
}
|
||||||
model.meshMaterial = (int *)RL_CALLOC(model.meshCount, sizeof(int));
|
model.meshMaterial = (int *)RL_CALLOC(model.meshCount, sizeof(int));
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
// Multiple meshes data reference
|
// Multiple meshes data reference
|
||||||
// NOTE: They are provided as a faces offset
|
// NOTE: They are provided as a faces offset
|
||||||
|
|
@ -2915,12 +2917,17 @@ static Model LoadOBJ(const char *fileName)
|
||||||
if (materials[m].displacement_texname != NULL) model.materials[m].maps[MAP_HEIGHT].texture = LoadTexture(materials[m].displacement_texname); //char *displacement_texname; // disp
|
if (materials[m].displacement_texname != NULL) model.materials[m].maps[MAP_HEIGHT].texture = LoadTexture(materials[m].displacement_texname); //char *displacement_texname; // disp
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (model.meshMaterial[0]==-1) {
|
||||||
|
model.meshMaterial[0] = 0; // will be given default material by LoadModel
|
||||||
|
}
|
||||||
|
|
||||||
tinyobj_attrib_free(&attrib);
|
tinyobj_attrib_free(&attrib);
|
||||||
tinyobj_shapes_free(meshes, meshCount);
|
tinyobj_shapes_free(meshes, meshCount);
|
||||||
tinyobj_materials_free(materials, materialCount);
|
tinyobj_materials_free(materials, materialCount);
|
||||||
RL_FREE(data); // oh ray how did you miss this...! :-p
|
RL_FREE(data); // oh ray how did you miss this...! :-p
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// NOTE: At this point we have all model data loaded
|
// NOTE: At this point we have all model data loaded
|
||||||
TraceLog(LOG_INFO, "[%s] Model loaded successfully in RAM (CPU)", fileName);
|
TraceLog(LOG_INFO, "[%s] Model loaded successfully in RAM (CPU)", fileName);
|
||||||
|
|
||||||
|
|
@ -3251,6 +3258,8 @@ static Model LoadIQM(const char *fileName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
model.meshMaterial = (int *)RL_CALLOC(model.meshCount, sizeof(int));
|
||||||
|
|
||||||
fclose(iqmFile);
|
fclose(iqmFile);
|
||||||
RL_FREE(imesh);
|
RL_FREE(imesh);
|
||||||
RL_FREE(tri);
|
RL_FREE(tri);
|
||||||
|
|
|
||||||
78
src/raudio.c
78
src/raudio.c
|
|
@ -198,10 +198,10 @@ typedef enum { AUDIO_BUFFER_USAGE_STATIC = 0, AUDIO_BUFFER_USAGE_STREAM } AudioB
|
||||||
// playback device depending on whether or not data is streamed
|
// playback device depending on whether or not data is streamed
|
||||||
struct rAudioBuffer {
|
struct rAudioBuffer {
|
||||||
ma_pcm_converter dsp; // PCM data converter
|
ma_pcm_converter dsp; // PCM data converter
|
||||||
|
|
||||||
float volume; // Audio buffer volume
|
float volume; // Audio buffer volume
|
||||||
float pitch; // Audio buffer pitch
|
float pitch; // Audio buffer pitch
|
||||||
|
|
||||||
bool playing; // Audio buffer state: AUDIO_PLAYING
|
bool playing; // Audio buffer state: AUDIO_PLAYING
|
||||||
bool paused; // Audio buffer state: AUDIO_PAUSED
|
bool paused; // Audio buffer state: AUDIO_PAUSED
|
||||||
bool looping; // Audio buffer looping, always true for AudioStreams
|
bool looping; // Audio buffer looping, always true for AudioStreams
|
||||||
|
|
@ -209,11 +209,11 @@ struct rAudioBuffer {
|
||||||
|
|
||||||
bool isSubBufferProcessed[2]; // SubBuffer processed (virtual double buffer)
|
bool isSubBufferProcessed[2]; // SubBuffer processed (virtual double buffer)
|
||||||
unsigned int frameCursorPos; // Frame cursor position
|
unsigned int frameCursorPos; // Frame cursor position
|
||||||
unsigned int bufferSizeInFrames; // Total buffer size in frames
|
unsigned int bufferSizeInFrames; // Total buffer size in frames
|
||||||
unsigned int totalFramesProcessed; // Total frames processed in this buffer (required for play timming)
|
unsigned int totalFramesProcessed; // Total frames processed in this buffer (required for play timming)
|
||||||
|
|
||||||
unsigned char *buffer; // Data buffer, on music stream keeps filling
|
unsigned char *buffer; // Data buffer, on music stream keeps filling
|
||||||
|
|
||||||
rAudioBuffer *next; // Next audio buffer on the list
|
rAudioBuffer *next; // Next audio buffer on the list
|
||||||
rAudioBuffer *prev; // Previous audio buffer on the list
|
rAudioBuffer *prev; // Previous audio buffer on the list
|
||||||
};
|
};
|
||||||
|
|
@ -289,7 +289,7 @@ static void OnSendAudioDataToDevice(ma_device *pDevice, void *pFramesOut, const
|
||||||
if (!audioBuffer->playing || audioBuffer->paused) continue;
|
if (!audioBuffer->playing || audioBuffer->paused) continue;
|
||||||
|
|
||||||
ma_uint32 framesRead = 0;
|
ma_uint32 framesRead = 0;
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
if (framesRead > frameCount)
|
if (framesRead > frameCount)
|
||||||
|
|
@ -302,7 +302,7 @@ static void OnSendAudioDataToDevice(ma_device *pDevice, void *pFramesOut, const
|
||||||
|
|
||||||
// Just read as much data as we can from the stream
|
// Just read as much data as we can from the stream
|
||||||
ma_uint32 framesToRead = (frameCount - framesRead);
|
ma_uint32 framesToRead = (frameCount - framesRead);
|
||||||
|
|
||||||
while (framesToRead > 0)
|
while (framesToRead > 0)
|
||||||
{
|
{
|
||||||
float tempBuffer[1024]; // 512 frames for stereo
|
float tempBuffer[1024]; // 512 frames for stereo
|
||||||
|
|
@ -387,7 +387,7 @@ static ma_uint32 OnAudioBufferDSPRead(ma_pcm_converter *pDSP, void *pFramesOut,
|
||||||
{
|
{
|
||||||
if (framesRead >= frameCount) break;
|
if (framesRead >= frameCount) break;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (isSubBufferProcessed[currentSubBufferIndex]) break;
|
if (isSubBufferProcessed[currentSubBufferIndex]) break;
|
||||||
}
|
}
|
||||||
|
|
@ -465,16 +465,20 @@ static void MixAudioFrames(float *framesOut, const float *framesIn, ma_uint32 fr
|
||||||
static void InitAudioBufferPool()
|
static void InitAudioBufferPool()
|
||||||
{
|
{
|
||||||
// Dummy buffers
|
// Dummy buffers
|
||||||
for (int i = 0; i < MAX_AUDIO_BUFFER_POOL_CHANNELS; i++)
|
for (int i = 0; i < MAX_AUDIO_BUFFER_POOL_CHANNELS; i++)
|
||||||
{
|
{
|
||||||
audioBufferPool[i] = InitAudioBuffer(DEVICE_FORMAT, DEVICE_CHANNELS, DEVICE_SAMPLE_RATE, 0, AUDIO_BUFFER_USAGE_STATIC);
|
audioBufferPool[i] = InitAudioBuffer(DEVICE_FORMAT, DEVICE_CHANNELS, DEVICE_SAMPLE_RATE, 0, AUDIO_BUFFER_USAGE_STATIC);
|
||||||
|
// Not needed (only the audiobuffer header) - leak prevention!
|
||||||
|
RL_FREE(audioBufferPool[i]->buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close the audio buffers pool
|
// Close the audio buffers pool
|
||||||
static void CloseAudioBufferPool()
|
static void CloseAudioBufferPool()
|
||||||
{
|
{
|
||||||
for (int i = 0; i < MAX_AUDIO_BUFFER_POOL_CHANNELS; i++) RL_FREE(audioBufferPool[i]);
|
for (int i = 0; i < MAX_AUDIO_BUFFER_POOL_CHANNELS; i++) {
|
||||||
|
RL_FREE(audioBufferPool[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
@ -486,7 +490,7 @@ void InitAudioDevice(void)
|
||||||
// Init audio context
|
// Init audio context
|
||||||
ma_context_config contextConfig = ma_context_config_init();
|
ma_context_config contextConfig = ma_context_config_init();
|
||||||
contextConfig.logCallback = OnLog;
|
contextConfig.logCallback = OnLog;
|
||||||
|
|
||||||
ma_result result = ma_context_init(NULL, 0, &contextConfig, &context);
|
ma_result result = ma_context_init(NULL, 0, &contextConfig, &context);
|
||||||
if (result != MA_SUCCESS)
|
if (result != MA_SUCCESS)
|
||||||
{
|
{
|
||||||
|
|
@ -589,7 +593,7 @@ AudioBuffer *InitAudioBuffer(ma_format format, ma_uint32 channels, ma_uint32 sam
|
||||||
{
|
{
|
||||||
AudioBuffer *audioBuffer = (AudioBuffer *)RL_CALLOC(1, sizeof(AudioBuffer));
|
AudioBuffer *audioBuffer = (AudioBuffer *)RL_CALLOC(1, sizeof(AudioBuffer));
|
||||||
audioBuffer->buffer = RL_CALLOC(bufferSizeInFrames*channels*ma_get_bytes_per_sample(format), 1);
|
audioBuffer->buffer = RL_CALLOC(bufferSizeInFrames*channels*ma_get_bytes_per_sample(format), 1);
|
||||||
|
|
||||||
if (audioBuffer == NULL)
|
if (audioBuffer == NULL)
|
||||||
{
|
{
|
||||||
TraceLog(LOG_ERROR, "InitAudioBuffer() : Failed to allocate memory for audio buffer");
|
TraceLog(LOG_ERROR, "InitAudioBuffer() : Failed to allocate memory for audio buffer");
|
||||||
|
|
@ -608,7 +612,7 @@ AudioBuffer *InitAudioBuffer(ma_format format, ma_uint32 channels, ma_uint32 sam
|
||||||
dspConfig.onRead = OnAudioBufferDSPRead; // Callback on data reading
|
dspConfig.onRead = OnAudioBufferDSPRead; // Callback on data reading
|
||||||
dspConfig.pUserData = audioBuffer; // Audio data pointer
|
dspConfig.pUserData = audioBuffer; // Audio data pointer
|
||||||
dspConfig.allowDynamicSampleRate = true; // Required for pitch shifting
|
dspConfig.allowDynamicSampleRate = true; // Required for pitch shifting
|
||||||
|
|
||||||
ma_result result = ma_pcm_converter_init(&dspConfig, &audioBuffer->dsp);
|
ma_result result = ma_pcm_converter_init(&dspConfig, &audioBuffer->dsp);
|
||||||
|
|
||||||
if (result != MA_SUCCESS)
|
if (result != MA_SUCCESS)
|
||||||
|
|
@ -655,7 +659,7 @@ void CloseAudioBuffer(AudioBuffer *buffer)
|
||||||
bool IsAudioBufferPlaying(AudioBuffer *buffer)
|
bool IsAudioBufferPlaying(AudioBuffer *buffer)
|
||||||
{
|
{
|
||||||
bool result = false;
|
bool result = false;
|
||||||
|
|
||||||
if (buffer != NULL) result = (buffer->playing && !buffer->paused);
|
if (buffer != NULL) result = (buffer->playing && !buffer->paused);
|
||||||
else TraceLog(LOG_ERROR, "IsAudioBufferPlaying() : No audio buffer");
|
else TraceLog(LOG_ERROR, "IsAudioBufferPlaying() : No audio buffer");
|
||||||
|
|
||||||
|
|
@ -698,7 +702,7 @@ void StopAudioBuffer(AudioBuffer *buffer)
|
||||||
void PauseAudioBuffer(AudioBuffer *buffer)
|
void PauseAudioBuffer(AudioBuffer *buffer)
|
||||||
{
|
{
|
||||||
if (buffer != NULL) buffer->paused = true;
|
if (buffer != NULL) buffer->paused = true;
|
||||||
else TraceLog(LOG_ERROR, "PauseAudioBuffer() : No audio buffer");
|
else TraceLog(LOG_ERROR, "PauseAudioBuffer() : No audio buffer");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resume an audio buffer
|
// Resume an audio buffer
|
||||||
|
|
@ -722,8 +726,8 @@ void SetAudioBufferPitch(AudioBuffer *buffer, float pitch)
|
||||||
{
|
{
|
||||||
float pitchMul = pitch/buffer->pitch;
|
float pitchMul = pitch/buffer->pitch;
|
||||||
|
|
||||||
// Pitching is just an adjustment of the sample rate.
|
// Pitching is just an adjustment of the sample rate.
|
||||||
// Note that this changes the duration of the sound:
|
// Note that this changes the duration of the sound:
|
||||||
// - higher pitches will make the sound faster
|
// - higher pitches will make the sound faster
|
||||||
// - lower pitches make it slower
|
// - lower pitches make it slower
|
||||||
ma_uint32 newOutputSampleRate = (ma_uint32)((float)buffer->dsp.src.config.sampleRateOut/pitchMul);
|
ma_uint32 newOutputSampleRate = (ma_uint32)((float)buffer->dsp.src.config.sampleRateOut/pitchMul);
|
||||||
|
|
@ -816,7 +820,7 @@ Sound LoadSoundFromWave(Wave wave)
|
||||||
|
|
||||||
if (wave.data != NULL)
|
if (wave.data != NULL)
|
||||||
{
|
{
|
||||||
// When using miniaudio we need to do our own mixing.
|
// When using miniaudio we need to do our own mixing.
|
||||||
// To simplify this we need convert the format of each sound to be consistent with
|
// To simplify this we need convert the format of each sound to be consistent with
|
||||||
// the format used to open the playback device. We can do this two ways:
|
// the format used to open the playback device. We can do this two ways:
|
||||||
//
|
//
|
||||||
|
|
@ -964,7 +968,7 @@ void PlaySoundMulti(Sound sound)
|
||||||
oldAge = audioBufferPoolChannels[i];
|
oldAge = audioBufferPoolChannels[i];
|
||||||
oldIndex = i;
|
oldIndex = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IsAudioBufferPlaying(audioBufferPool[i]))
|
if (!IsAudioBufferPlaying(audioBufferPool[i]))
|
||||||
{
|
{
|
||||||
index = i;
|
index = i;
|
||||||
|
|
@ -976,17 +980,17 @@ void PlaySoundMulti(Sound sound)
|
||||||
if (index == -1)
|
if (index == -1)
|
||||||
{
|
{
|
||||||
TraceLog(LOG_WARNING,"pool age %i ended a sound early no room in buffer pool", audioBufferPoolCounter);
|
TraceLog(LOG_WARNING,"pool age %i ended a sound early no room in buffer pool", audioBufferPoolCounter);
|
||||||
|
|
||||||
if (oldIndex == -1)
|
if (oldIndex == -1)
|
||||||
{
|
{
|
||||||
// Shouldn't be able to get here... but just in case something odd happens!
|
// Shouldn't be able to get here... but just in case something odd happens!
|
||||||
TraceLog(LOG_ERROR,"sound buffer pool couldn't determine oldest buffer not playing sound");
|
TraceLog(LOG_ERROR,"sound buffer pool couldn't determine oldest buffer not playing sound");
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
index = oldIndex;
|
index = oldIndex;
|
||||||
|
|
||||||
// Just in case...
|
// Just in case...
|
||||||
StopAudioBuffer(audioBufferPool[index]);
|
StopAudioBuffer(audioBufferPool[index]);
|
||||||
}
|
}
|
||||||
|
|
@ -997,7 +1001,7 @@ void PlaySoundMulti(Sound sound)
|
||||||
|
|
||||||
audioBufferPoolChannels[index] = audioBufferPoolCounter;
|
audioBufferPoolChannels[index] = audioBufferPoolCounter;
|
||||||
audioBufferPoolCounter++;
|
audioBufferPoolCounter++;
|
||||||
|
|
||||||
audioBufferPool[index]->volume = sound.stream.buffer->volume;
|
audioBufferPool[index]->volume = sound.stream.buffer->volume;
|
||||||
audioBufferPool[index]->pitch = sound.stream.buffer->pitch;
|
audioBufferPool[index]->pitch = sound.stream.buffer->pitch;
|
||||||
audioBufferPool[index]->looping = sound.stream.buffer->looping;
|
audioBufferPool[index]->looping = sound.stream.buffer->looping;
|
||||||
|
|
@ -1020,12 +1024,12 @@ void StopSoundMulti(void)
|
||||||
int GetSoundsPlaying(void)
|
int GetSoundsPlaying(void)
|
||||||
{
|
{
|
||||||
int counter = 0;
|
int counter = 0;
|
||||||
|
|
||||||
for (int i = 0; i < MAX_AUDIO_BUFFER_POOL_CHANNELS; i++)
|
for (int i = 0; i < MAX_AUDIO_BUFFER_POOL_CHANNELS; i++)
|
||||||
{
|
{
|
||||||
if (IsAudioBufferPlaying(audioBufferPool[i])) counter++;
|
if (IsAudioBufferPlaying(audioBufferPool[i])) counter++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return counter;
|
return counter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1208,7 +1212,7 @@ Music LoadMusicStream(const char *fileName)
|
||||||
{
|
{
|
||||||
drmp3 *ctxMp3 = RL_MALLOC(sizeof(drmp3));
|
drmp3 *ctxMp3 = RL_MALLOC(sizeof(drmp3));
|
||||||
music.ctxData = ctxMp3;
|
music.ctxData = ctxMp3;
|
||||||
|
|
||||||
int result = drmp3_init_file(ctxMp3, fileName, NULL);
|
int result = drmp3_init_file(ctxMp3, fileName, NULL);
|
||||||
|
|
||||||
if (result > 0)
|
if (result > 0)
|
||||||
|
|
@ -1239,7 +1243,7 @@ Music LoadMusicStream(const char *fileName)
|
||||||
music.sampleCount = (unsigned int)jar_xm_get_remaining_samples(ctxXm);
|
music.sampleCount = (unsigned int)jar_xm_get_remaining_samples(ctxXm);
|
||||||
music.loopCount = 0; // Infinite loop by default
|
music.loopCount = 0; // Infinite loop by default
|
||||||
musicLoaded = true;
|
musicLoaded = true;
|
||||||
|
|
||||||
music.ctxData = ctxXm;
|
music.ctxData = ctxXm;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1249,7 +1253,7 @@ Music LoadMusicStream(const char *fileName)
|
||||||
{
|
{
|
||||||
jar_mod_context_t *ctxMod = RL_MALLOC(sizeof(jar_mod_context_t));
|
jar_mod_context_t *ctxMod = RL_MALLOC(sizeof(jar_mod_context_t));
|
||||||
music.ctxData = ctxMod;
|
music.ctxData = ctxMod;
|
||||||
|
|
||||||
jar_mod_init(ctxMod);
|
jar_mod_init(ctxMod);
|
||||||
int result = jar_mod_load_file(ctxMod, fileName);
|
int result = jar_mod_load_file(ctxMod, fileName);
|
||||||
|
|
||||||
|
|
@ -1332,7 +1336,7 @@ void PlayMusicStream(Music music)
|
||||||
{
|
{
|
||||||
// For music streams, we need to make sure we maintain the frame cursor position
|
// For music streams, we need to make sure we maintain the frame cursor position
|
||||||
// This is a hack for this section of code in UpdateMusicStream()
|
// This is a hack for this section of code in UpdateMusicStream()
|
||||||
// NOTE: In case window is minimized, music stream is stopped, just make sure to
|
// NOTE: In case window is minimized, music stream is stopped, just make sure to
|
||||||
// play again on window restore: if (IsMusicPlaying(music)) PlayMusicStream(music);
|
// play again on window restore: if (IsMusicPlaying(music)) PlayMusicStream(music);
|
||||||
ma_uint32 frameCursorPos = audioBuffer->frameCursorPos;
|
ma_uint32 frameCursorPos = audioBuffer->frameCursorPos;
|
||||||
PlayAudioStream(music.stream); // WARNING: This resets the cursor position.
|
PlayAudioStream(music.stream); // WARNING: This resets the cursor position.
|
||||||
|
|
@ -1392,7 +1396,7 @@ void UpdateMusicStream(Music music)
|
||||||
void *pcm = RL_CALLOC(subBufferSizeInFrames*music.stream.channels*music.stream.sampleSize/8, 1);
|
void *pcm = RL_CALLOC(subBufferSizeInFrames*music.stream.channels*music.stream.sampleSize/8, 1);
|
||||||
|
|
||||||
int samplesCount = 0; // Total size of data streamed in L+R samples for xm floats, individual L or R for ogg shorts
|
int samplesCount = 0; // Total size of data streamed in L+R samples for xm floats, individual L or R for ogg shorts
|
||||||
|
|
||||||
// TODO: Get the sampleLeft using totalFramesProcessed... but first, get total frames processed correctly...
|
// TODO: Get the sampleLeft using totalFramesProcessed... but first, get total frames processed correctly...
|
||||||
//ma_uint32 frameSizeInBytes = ma_get_bytes_per_sample(music.stream.buffer->dsp.formatConverterIn.config.formatIn)*music.stream.buffer->dsp.formatConverterIn.config.channels;
|
//ma_uint32 frameSizeInBytes = ma_get_bytes_per_sample(music.stream.buffer->dsp.formatConverterIn.config.formatIn)*music.stream.buffer->dsp.formatConverterIn.config.channels;
|
||||||
int sampleLeft = music.sampleCount - (music.stream.buffer->totalFramesProcessed*music.stream.channels);
|
int sampleLeft = music.sampleCount - (music.stream.buffer->totalFramesProcessed*music.stream.channels);
|
||||||
|
|
@ -1446,7 +1450,7 @@ void UpdateMusicStream(Music music)
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateAudioStream(music.stream, pcm, samplesCount);
|
UpdateAudioStream(music.stream, pcm, samplesCount);
|
||||||
|
|
||||||
if ((music.ctxType == MUSIC_MODULE_XM) || (music.ctxType == MUSIC_MODULE_MOD))
|
if ((music.ctxType == MUSIC_MODULE_XM) || (music.ctxType == MUSIC_MODULE_MOD))
|
||||||
{
|
{
|
||||||
if (samplesCount > 1) sampleLeft -= samplesCount/2;
|
if (samplesCount > 1) sampleLeft -= samplesCount/2;
|
||||||
|
|
@ -1546,11 +1550,11 @@ AudioStream InitAudioStream(unsigned int sampleRate, unsigned int sampleSize, un
|
||||||
// The size of a streaming buffer must be at least double the size of a period
|
// The size of a streaming buffer must be at least double the size of a period
|
||||||
unsigned int periodSize = device.playback.internalBufferSizeInFrames/device.playback.internalPeriods;
|
unsigned int periodSize = device.playback.internalBufferSizeInFrames/device.playback.internalPeriods;
|
||||||
unsigned int subBufferSize = AUDIO_BUFFER_SIZE;
|
unsigned int subBufferSize = AUDIO_BUFFER_SIZE;
|
||||||
|
|
||||||
if (subBufferSize < periodSize) subBufferSize = periodSize;
|
if (subBufferSize < periodSize) subBufferSize = periodSize;
|
||||||
|
|
||||||
stream.buffer = InitAudioBuffer(formatIn, stream.channels, stream.sampleRate, subBufferSize*2, AUDIO_BUFFER_USAGE_STREAM);
|
stream.buffer = InitAudioBuffer(formatIn, stream.channels, stream.sampleRate, subBufferSize*2, AUDIO_BUFFER_USAGE_STREAM);
|
||||||
|
|
||||||
if (stream.buffer != NULL)
|
if (stream.buffer != NULL)
|
||||||
{
|
{
|
||||||
stream.buffer->looping = true; // Always loop for streaming buffers
|
stream.buffer->looping = true; // Always loop for streaming buffers
|
||||||
|
|
@ -1575,7 +1579,7 @@ void CloseAudioStream(AudioStream stream)
|
||||||
void UpdateAudioStream(AudioStream stream, const void *data, int samplesCount)
|
void UpdateAudioStream(AudioStream stream, const void *data, int samplesCount)
|
||||||
{
|
{
|
||||||
AudioBuffer *audioBuffer = stream.buffer;
|
AudioBuffer *audioBuffer = stream.buffer;
|
||||||
|
|
||||||
if (audioBuffer != NULL)
|
if (audioBuffer != NULL)
|
||||||
{
|
{
|
||||||
if (audioBuffer->isSubBufferProcessed[0] || audioBuffer->isSubBufferProcessed[1])
|
if (audioBuffer->isSubBufferProcessed[0] || audioBuffer->isSubBufferProcessed[1])
|
||||||
|
|
@ -1584,7 +1588,7 @@ void UpdateAudioStream(AudioStream stream, const void *data, int samplesCount)
|
||||||
|
|
||||||
if (audioBuffer->isSubBufferProcessed[0] && audioBuffer->isSubBufferProcessed[1])
|
if (audioBuffer->isSubBufferProcessed[0] && audioBuffer->isSubBufferProcessed[1])
|
||||||
{
|
{
|
||||||
// Both buffers are available for updating.
|
// Both buffers are available for updating.
|
||||||
// Update the first one and make sure the cursor is moved back to the front.
|
// Update the first one and make sure the cursor is moved back to the front.
|
||||||
subBufferToUpdate = 0;
|
subBufferToUpdate = 0;
|
||||||
audioBuffer->frameCursorPos = 0;
|
audioBuffer->frameCursorPos = 0;
|
||||||
|
|
@ -1601,7 +1605,7 @@ void UpdateAudioStream(AudioStream stream, const void *data, int samplesCount)
|
||||||
// TODO: Get total frames processed on this buffer... DOES NOT WORK.
|
// TODO: Get total frames processed on this buffer... DOES NOT WORK.
|
||||||
audioBuffer->totalFramesProcessed += subBufferSizeInFrames;
|
audioBuffer->totalFramesProcessed += subBufferSizeInFrames;
|
||||||
|
|
||||||
// Does this API expect a whole buffer to be updated in one go?
|
// Does this API expect a whole buffer to be updated in one go?
|
||||||
// Assuming so, but if not will need to change this logic.
|
// Assuming so, but if not will need to change this logic.
|
||||||
if (subBufferSizeInFrames >= (ma_uint32)samplesCount/stream.channels)
|
if (subBufferSizeInFrames >= (ma_uint32)samplesCount/stream.channels)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -432,7 +432,7 @@ typedef struct Sound {
|
||||||
typedef struct Music {
|
typedef struct Music {
|
||||||
int ctxType; // Type of music context (audio filetype)
|
int ctxType; // Type of music context (audio filetype)
|
||||||
void *ctxData; // Audio context data, depends on type
|
void *ctxData; // Audio context data, depends on type
|
||||||
|
|
||||||
unsigned int sampleCount; // Total number of samples
|
unsigned int sampleCount; // Total number of samples
|
||||||
unsigned int loopCount; // Loops count (times music will play), 0 means infinite loop
|
unsigned int loopCount; // Loops count (times music will play), 0 means infinite loop
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user