Merge branch 'raysan5:master' into master
This commit is contained in:
commit
0cb2298360
52
src/external/jar_xm.h
vendored
52
src/external/jar_xm.h
vendored
|
|
@ -75,7 +75,7 @@ struct jar_xm_context_s;
|
||||||
typedef struct jar_xm_context_s jar_xm_context_t;
|
typedef struct jar_xm_context_s jar_xm_context_t;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//** Create a XM context.
|
//** Create a XM context.
|
||||||
|
|
@ -363,7 +363,7 @@ struct jar_xm_sample_s {
|
||||||
uint16_t num_patterns;
|
uint16_t num_patterns;
|
||||||
uint16_t num_instruments;
|
uint16_t num_instruments;
|
||||||
uint16_t linear_interpolation;
|
uint16_t linear_interpolation;
|
||||||
uint16_t ramping;
|
uint16_t ramping;
|
||||||
jar_xm_frequency_type_t frequency_type;
|
jar_xm_frequency_type_t frequency_type;
|
||||||
uint8_t pattern_table[PATTERN_ORDER_TABLE_LENGTH];
|
uint8_t pattern_table[PATTERN_ORDER_TABLE_LENGTH];
|
||||||
|
|
||||||
|
|
@ -457,7 +457,7 @@ struct jar_xm_sample_s {
|
||||||
uint16_t default_tempo; // Number of ticks per row
|
uint16_t default_tempo; // Number of ticks per row
|
||||||
uint16_t default_bpm;
|
uint16_t default_bpm;
|
||||||
float default_global_volume;
|
float default_global_volume;
|
||||||
|
|
||||||
uint16_t tempo; // Number of ticks per row
|
uint16_t tempo; // Number of ticks per row
|
||||||
uint16_t bpm;
|
uint16_t bpm;
|
||||||
float global_volume;
|
float global_volume;
|
||||||
|
|
@ -708,7 +708,7 @@ int jar_xm_check_sanity_postload(jar_xm_context_t* ctx) {
|
||||||
if(ctx->module.pattern_table[i] >= ctx->module.num_patterns) {
|
if(ctx->module.pattern_table[i] >= ctx->module.num_patterns) {
|
||||||
if(i+1 == ctx->module.length && ctx->module.length > 1) {
|
if(i+1 == ctx->module.length && ctx->module.length > 1) {
|
||||||
DEBUG("trimming invalid POT at pos %X", i);
|
DEBUG("trimming invalid POT at pos %X", i);
|
||||||
--ctx->module.length;
|
--ctx->module.length;
|
||||||
} else {
|
} else {
|
||||||
DEBUG("module has invalid POT, pos %X references nonexistent pattern %X", i, ctx->module.pattern_table[i]);
|
DEBUG("module has invalid POT, pos %X references nonexistent pattern %X", i, ctx->module.pattern_table[i]);
|
||||||
return 1;
|
return 1;
|
||||||
|
|
@ -823,7 +823,7 @@ char* jar_xm_load_module(jar_xm_context_t* ctx, const char* moddata, size_t modd
|
||||||
pat->slots = (jar_xm_pattern_slot_t*)mempool;
|
pat->slots = (jar_xm_pattern_slot_t*)mempool;
|
||||||
mempool += mod->num_channels * pat->num_rows * sizeof(jar_xm_pattern_slot_t);
|
mempool += mod->num_channels * pat->num_rows * sizeof(jar_xm_pattern_slot_t);
|
||||||
offset += READ_U32(offset); /* Pattern header length */
|
offset += READ_U32(offset); /* Pattern header length */
|
||||||
|
|
||||||
if(packed_patterndata_size == 0) { /* No pattern data is present */
|
if(packed_patterndata_size == 0) { /* No pattern data is present */
|
||||||
memset(pat->slots, 0, sizeof(jar_xm_pattern_slot_t) * pat->num_rows * mod->num_channels);
|
memset(pat->slots, 0, sizeof(jar_xm_pattern_slot_t) * pat->num_rows * mod->num_channels);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -1236,7 +1236,7 @@ static void jar_xm_post_pattern_change(jar_xm_context_t* ctx) {
|
||||||
/* Loop if necessary */
|
/* Loop if necessary */
|
||||||
if(ctx->current_table_index >= ctx->module.length) {
|
if(ctx->current_table_index >= ctx->module.length) {
|
||||||
ctx->current_table_index = ctx->module.restart_position;
|
ctx->current_table_index = ctx->module.restart_position;
|
||||||
ctx->tempo =ctx->default_tempo; // reset to file default value
|
ctx->tempo =ctx->default_tempo; // reset to file default value
|
||||||
ctx->bpm = ctx->default_bpm; // reset to file default value
|
ctx->bpm = ctx->default_bpm; // reset to file default value
|
||||||
ctx->global_volume = ctx->default_global_volume; // reset to file default value
|
ctx->global_volume = ctx->default_global_volume; // reset to file default value
|
||||||
}
|
}
|
||||||
|
|
@ -1586,7 +1586,7 @@ static void jar_xm_trigger_note(jar_xm_context_t* ctx, jar_xm_channel_context_t*
|
||||||
ch->sample_position = 0.f;
|
ch->sample_position = 0.f;
|
||||||
ch->ping = true;
|
ch->ping = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!(flags & jar_xm_TRIGGER_KEEP_VOLUME)) {
|
if (!(flags & jar_xm_TRIGGER_KEEP_VOLUME)) {
|
||||||
if(ch->sample != NULL) {
|
if(ch->sample != NULL) {
|
||||||
ch->volume = ch->sample->volume;
|
ch->volume = ch->sample->volume;
|
||||||
|
|
@ -1665,7 +1665,7 @@ static void jar_xm_row(jar_xm_context_t* ctx) {
|
||||||
/* No E6y loop is in effect (or we are in the first pass) */
|
/* No E6y loop is in effect (or we are in the first pass) */
|
||||||
ctx->loop_count = (ctx->row_loop_count[MAX_NUM_ROWS * ctx->current_table_index + ctx->current_row]++);
|
ctx->loop_count = (ctx->row_loop_count[MAX_NUM_ROWS * ctx->current_table_index + ctx->current_row]++);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Move to next row
|
/// Move to next row
|
||||||
ctx->current_row++; /* uint8 warning: can increment from 255 to 0, in which case it is still necessary to go the next pattern. */
|
ctx->current_row++; /* uint8 warning: can increment from 255 to 0, in which case it is still necessary to go the next pattern. */
|
||||||
if (!ctx->position_jump && !ctx->pattern_break && (ctx->current_row >= cur->num_rows || ctx->current_row == 0)) {
|
if (!ctx->position_jump && !ctx->pattern_break && (ctx->current_row >= cur->num_rows || ctx->current_row == 0)) {
|
||||||
|
|
@ -1721,7 +1721,7 @@ static void jar_xm_tick(jar_xm_context_t* ctx) {
|
||||||
if(ctx->current_tick == 0) {
|
if(ctx->current_tick == 0) {
|
||||||
jar_xm_row(ctx); // We have processed all ticks and we run the row
|
jar_xm_row(ctx); // We have processed all ticks and we run the row
|
||||||
}
|
}
|
||||||
|
|
||||||
jar_xm_module_t* mod = &(ctx->module);
|
jar_xm_module_t* mod = &(ctx->module);
|
||||||
for(uint8_t i = 0; i < ctx->module.num_channels; ++i) {
|
for(uint8_t i = 0; i < ctx->module.num_channels; ++i) {
|
||||||
jar_xm_channel_context_t* ch = ctx->channels + i;
|
jar_xm_channel_context_t* ch = ctx->channels + i;
|
||||||
|
|
@ -1885,7 +1885,7 @@ static void jar_xm_tick(jar_xm_context_t* ctx) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 16: /* Fxy: Set tempo/BPM */
|
case 16: /* Fxy: Set tempo/BPM */
|
||||||
break;
|
break;
|
||||||
case 17: /* Hxy: Global volume slide */
|
case 17: /* Hxy: Global volume slide */
|
||||||
if(ctx->current_tick == 0) break;
|
if(ctx->current_tick == 0) break;
|
||||||
if((ch->global_volume_slide_param & 0xF0) && (ch->global_volume_slide_param & 0x0F)) { break; }; /* Invalid state */
|
if((ch->global_volume_slide_param & 0xF0) && (ch->global_volume_slide_param & 0x0F)) { break; }; /* Invalid state */
|
||||||
|
|
@ -1904,7 +1904,7 @@ static void jar_xm_tick(jar_xm_context_t* ctx) {
|
||||||
if(ctx->current_tick == ch->current->effect_param) { jar_xm_key_off(ch); };
|
if(ctx->current_tick == ch->current->effect_param) { jar_xm_key_off(ch); };
|
||||||
break;
|
break;
|
||||||
case 21: /* Lxx: Set envelope position */
|
case 21: /* Lxx: Set envelope position */
|
||||||
break;
|
break;
|
||||||
case 25: /* Pxy: Panning slide */
|
case 25: /* Pxy: Panning slide */
|
||||||
if(ctx->current_tick == 0) break;
|
if(ctx->current_tick == 0) break;
|
||||||
jar_xm_panning_slide(ch, ch->panning_slide_param);
|
jar_xm_panning_slide(ch, ch->panning_slide_param);
|
||||||
|
|
@ -2105,7 +2105,7 @@ static void jar_xm_next_of_sample(jar_xm_context_t* ctx, jar_xm_channel_context_
|
||||||
// gather all channel audio into stereo float
|
// gather all channel audio into stereo float
|
||||||
static void jar_xm_mixdown(jar_xm_context_t* ctx, float* left, float* right) {
|
static void jar_xm_mixdown(jar_xm_context_t* ctx, float* left, float* right) {
|
||||||
jar_xm_module_t* mod = &(ctx->module);
|
jar_xm_module_t* mod = &(ctx->module);
|
||||||
|
|
||||||
if(ctx->remaining_samples_in_tick <= 0) {
|
if(ctx->remaining_samples_in_tick <= 0) {
|
||||||
jar_xm_tick(ctx);
|
jar_xm_tick(ctx);
|
||||||
};
|
};
|
||||||
|
|
@ -2142,7 +2142,7 @@ static void jar_xm_mixdown(jar_xm_context_t* ctx, float* left, float* right) {
|
||||||
|
|
||||||
// apply brick wall limiter when audio goes beyond bounderies
|
// apply brick wall limiter when audio goes beyond bounderies
|
||||||
if(*left < -1.0) {*left = -1.0;} else if(*left > 1.0) {*left = 1.0;};
|
if(*left < -1.0) {*left = -1.0;} else if(*left > 1.0) {*left = 1.0;};
|
||||||
if(*right < -1.0) {*right = -1.0;} else if(*right > 1.0) {*right = 1.0;};
|
if(*right < -1.0) {*right = -1.0;} else if(*right > 1.0) {*right = 1.0;};
|
||||||
};
|
};
|
||||||
|
|
||||||
void jar_xm_generate_samples(jar_xm_context_t* ctx, float* output, size_t numsamples) {
|
void jar_xm_generate_samples(jar_xm_context_t* ctx, float* output, size_t numsamples) {
|
||||||
|
|
@ -2244,7 +2244,7 @@ int jar_xm_create_context_from_file(jar_xm_context_t** ctx, uint32_t rate, const
|
||||||
return 6;
|
return 6;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2256,7 +2256,7 @@ void jar_xm_reset(jar_xm_context_t* ctx) {
|
||||||
ctx->current_row = 0;
|
ctx->current_row = 0;
|
||||||
ctx->current_table_index = 0;
|
ctx->current_table_index = 0;
|
||||||
ctx->current_tick = 0;
|
ctx->current_tick = 0;
|
||||||
ctx->tempo =ctx->default_tempo; // reset to file default value
|
ctx->tempo =ctx->default_tempo; // reset to file default value
|
||||||
ctx->bpm = ctx->default_bpm; // reset to file default value
|
ctx->bpm = ctx->default_bpm; // reset to file default value
|
||||||
ctx->global_volume = ctx->default_global_volume; // reset to file default value
|
ctx->global_volume = ctx->default_global_volume; // reset to file default value
|
||||||
}
|
}
|
||||||
|
|
@ -2282,7 +2282,7 @@ void jar_xm_table_jump(jar_xm_context_t* ctx, int table_ptr) {
|
||||||
} else {
|
} else {
|
||||||
ctx->current_table_index = 0;
|
ctx->current_table_index = 0;
|
||||||
ctx->module.restart_position = 0; // The reason to jump is to start a new loop or track
|
ctx->module.restart_position = 0; // The reason to jump is to start a new loop or track
|
||||||
ctx->tempo =ctx->default_tempo; // reset to file default value
|
ctx->tempo =ctx->default_tempo; // reset to file default value
|
||||||
ctx->bpm = ctx->default_bpm; // reset to file default value
|
ctx->bpm = ctx->default_bpm; // reset to file default value
|
||||||
ctx->global_volume = ctx->default_global_volume; // reset to file default value
|
ctx->global_volume = ctx->default_global_volume; // reset to file default value
|
||||||
};
|
};
|
||||||
|
|
@ -2383,31 +2383,31 @@ void jar_xm_debug(jar_xm_context_t *ctx) {
|
||||||
y += size; DrawText(TextFormat("LCT = %i", ctx->loop_count), x, y, size, WHITE);
|
y += size; DrawText(TextFormat("LCT = %i", ctx->loop_count), x, y, size, WHITE);
|
||||||
y += size; DrawText(TextFormat("MAX LCT = %i", ctx->max_loop_count), x, y, size, WHITE);
|
y += size; DrawText(TextFormat("MAX LCT = %i", ctx->max_loop_count), x, y, size, WHITE);
|
||||||
x = size * 12; y = 0;
|
x = size * 12; y = 0;
|
||||||
|
|
||||||
y += size; DrawText(TextFormat("CUR TCK = %i", ctx->current_tick), x, y, size, WHITE);
|
y += size; DrawText(TextFormat("CUR TCK = %i", ctx->current_tick), x, y, size, WHITE);
|
||||||
y += size; DrawText(TextFormat("XTR TCK = %i", ctx->extra_ticks), x, y, size, WHITE);
|
y += size; DrawText(TextFormat("XTR TCK = %i", ctx->extra_ticks), x, y, size, WHITE);
|
||||||
y += size; DrawText(TextFormat("TCK/ROW = %i", ctx->tempo), x, y, size, ORANGE);
|
y += size; DrawText(TextFormat("TCK/ROW = %i", ctx->tempo), x, y, size, ORANGE);
|
||||||
y += size; DrawText(TextFormat("SPL TCK = %f", ctx->remaining_samples_in_tick), x, y, size, WHITE);
|
y += size; DrawText(TextFormat("SPL TCK = %f", ctx->remaining_samples_in_tick), x, y, size, WHITE);
|
||||||
y += size; DrawText(TextFormat("GEN SPL = %i", ctx->generated_samples), x, y, size, WHITE);
|
y += size; DrawText(TextFormat("GEN SPL = %i", ctx->generated_samples), x, y, size, WHITE);
|
||||||
y += size * 7;
|
y += size * 7;
|
||||||
|
|
||||||
x = 0;
|
x = 0;
|
||||||
size=16;
|
size=16;
|
||||||
// TIMELINE OF MODULE
|
// TIMELINE OF MODULE
|
||||||
for (int i=0; i < ctx->module.length; i++) {
|
for (int i=0; i < ctx->module.length; i++) {
|
||||||
if (i == ctx->jump_dest) {
|
if (i == ctx->jump_dest) {
|
||||||
if (ctx->position_jump) {
|
if (ctx->position_jump) {
|
||||||
DrawRectangle(i * size * 2, y - size, size * 2, size, GOLD);
|
DrawRectangle(i * size * 2, y - size, size * 2, size, GOLD);
|
||||||
} else {
|
} else {
|
||||||
DrawRectangle(i * size * 2, y - size, size * 2, size, BROWN);
|
DrawRectangle(i * size * 2, y - size, size * 2, size, BROWN);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
if (i == ctx->current_table_index) {
|
if (i == ctx->current_table_index) {
|
||||||
// DrawText(TextFormat("%02X", ctx->current_tick), i * size * 2, y - size, size, WHITE);
|
// DrawText(TextFormat("%02X", ctx->current_tick), i * size * 2, y - size, size, WHITE);
|
||||||
DrawRectangle(i * size * 2, y, size * 2, size, RED);
|
DrawRectangle(i * size * 2, y, size * 2, size, RED);
|
||||||
DrawText(TextFormat("%02X", ctx->current_row), i * size * 2, y - size, size, YELLOW);
|
DrawText(TextFormat("%02X", ctx->current_row), i * size * 2, y - size, size, YELLOW);
|
||||||
} else {
|
} else {
|
||||||
DrawRectangle(i * size * 2, y, size * 2, size, ORANGE);
|
DrawRectangle(i * size * 2, y, size * 2, size, ORANGE);
|
||||||
};
|
};
|
||||||
DrawText(TextFormat("%02X", ctx->module.pattern_table[i]), i * size * 2, y, size, WHITE);
|
DrawText(TextFormat("%02X", ctx->module.pattern_table[i]), i * size * 2, y, size, WHITE);
|
||||||
};
|
};
|
||||||
|
|
@ -2426,19 +2426,19 @@ void jar_xm_debug(jar_xm_context_t *ctx) {
|
||||||
DrawText("FX", x + size * 6, y, size, YELLOW);
|
DrawText("FX", x + size * 6, y, size, YELLOW);
|
||||||
x += 9 * size;
|
x += 9 * size;
|
||||||
};
|
};
|
||||||
x += size;
|
x += size;
|
||||||
for (int j=(ctx->current_row - 14); j<(ctx->current_row + 15); j++) {
|
for (int j=(ctx->current_row - 14); j<(ctx->current_row + 15); j++) {
|
||||||
y += size;
|
y += size;
|
||||||
x = 0;
|
x = 0;
|
||||||
if (j >=0 && j < (cur->num_rows)) {
|
if (j >=0 && j < (cur->num_rows)) {
|
||||||
DrawRectangle(x, y, size * 2, size, BROWN);
|
DrawRectangle(x, y, size * 2, size, BROWN);
|
||||||
DrawText(TextFormat("%02X",j), x, y, size, WHITE);
|
DrawText(TextFormat("%02X",j), x, y, size, WHITE);
|
||||||
x += 2 * size;
|
x += 2 * size;
|
||||||
for(uint8_t i = 0; i < ctx->module.num_channels; i++) {
|
for(uint8_t i = 0; i < ctx->module.num_channels; i++) {
|
||||||
if (j==(ctx->current_row)) {
|
if (j==(ctx->current_row)) {
|
||||||
DrawRectangle(x, y, 8 * size, size, DARKGREEN);
|
DrawRectangle(x, y, 8 * size, size, DARKGREEN);
|
||||||
} else {
|
} else {
|
||||||
DrawRectangle(x, y, 8 * size, size, DARKGRAY);
|
DrawRectangle(x, y, 8 * size, size, DARKGRAY);
|
||||||
};
|
};
|
||||||
jar_xm_pattern_slot_t *s = cur->slots + j * ctx->module.num_channels + i;
|
jar_xm_pattern_slot_t *s = cur->slots + j * ctx->module.num_channels + i;
|
||||||
// jar_xm_channel_context_t *ch = ctx->channels + i;
|
// jar_xm_channel_context_t *ch = ctx->channels + i;
|
||||||
|
|
|
||||||
28
src/models.c
28
src/models.c
|
|
@ -828,16 +828,16 @@ void UnloadModelKeepMeshes(Model model)
|
||||||
BoundingBox GetModelBoundingBox(Model model)
|
BoundingBox GetModelBoundingBox(Model model)
|
||||||
{
|
{
|
||||||
BoundingBox bounds = { 0 };
|
BoundingBox bounds = { 0 };
|
||||||
|
|
||||||
if (model.meshCount > 0)
|
if (model.meshCount > 0)
|
||||||
{
|
{
|
||||||
Vector3 temp = { 0 };
|
Vector3 temp = { 0 };
|
||||||
bounds = GetMeshBoundingBox(model.meshes[0]);
|
bounds = GetMeshBoundingBox(model.meshes[0]);
|
||||||
|
|
||||||
for (int i = 1; i < model.meshCount; i++)
|
for (int i = 1; i < model.meshCount; i++)
|
||||||
{
|
{
|
||||||
BoundingBox tempBounds = GetMeshBoundingBox(model.meshes[i]);
|
BoundingBox tempBounds = GetMeshBoundingBox(model.meshes[i]);
|
||||||
|
|
||||||
temp.x = (bounds.min.x < tempBounds.min.x)? bounds.min.x : tempBounds.min.x;
|
temp.x = (bounds.min.x < tempBounds.min.x)? bounds.min.x : tempBounds.min.x;
|
||||||
temp.y = (bounds.min.y < tempBounds.min.y)? bounds.min.y : tempBounds.min.y;
|
temp.y = (bounds.min.y < tempBounds.min.y)? bounds.min.y : tempBounds.min.y;
|
||||||
temp.z = (bounds.min.z < tempBounds.min.z)? bounds.min.z : tempBounds.min.z;
|
temp.z = (bounds.min.z < tempBounds.min.z)? bounds.min.z : tempBounds.min.z;
|
||||||
|
|
@ -849,7 +849,7 @@ BoundingBox GetModelBoundingBox(Model model)
|
||||||
bounds.max = temp;
|
bounds.max = temp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return bounds;
|
return bounds;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1105,7 +1105,7 @@ void DrawMeshInstanced(Mesh mesh, Material material, Matrix *transforms, int ins
|
||||||
// transforms[0]: model transformation provided (includes DrawModel() params combined with model.transform)
|
// transforms[0]: model transformation provided (includes DrawModel() params combined with model.transform)
|
||||||
// rlGetMatrixTransform(): rlgl internal transform matrix due to push/pop matrix stack
|
// rlGetMatrixTransform(): rlgl internal transform matrix due to push/pop matrix stack
|
||||||
matModel = MatrixMultiply(transforms[0], rlGetMatrixTransform());
|
matModel = MatrixMultiply(transforms[0], rlGetMatrixTransform());
|
||||||
|
|
||||||
// Get model-view matrix
|
// Get model-view matrix
|
||||||
matModelView = MatrixMultiply(matModel, matView);
|
matModelView = MatrixMultiply(matModel, matView);
|
||||||
}
|
}
|
||||||
|
|
@ -1376,7 +1376,7 @@ Material *LoadMaterials(const char *fileName, int *materialCount)
|
||||||
// Set materials shader to default (DIFFUSE, SPECULAR, NORMAL)
|
// Set materials shader to default (DIFFUSE, SPECULAR, NORMAL)
|
||||||
if (materials != NULL)
|
if (materials != NULL)
|
||||||
{
|
{
|
||||||
for (unsigned int i = 0; i < count; i++)
|
for (unsigned int i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
materials[i].shader.id = rlGetShaderIdDefault();
|
materials[i].shader.id = rlGetShaderIdDefault();
|
||||||
materials[i].shader.locs = rlGetShaderLocsDefault();
|
materials[i].shader.locs = rlGetShaderLocsDefault();
|
||||||
|
|
@ -1396,7 +1396,7 @@ Material LoadMaterialDefault(void)
|
||||||
// Using rlgl default shader
|
// Using rlgl default shader
|
||||||
material.shader.id = rlGetShaderIdDefault();
|
material.shader.id = rlGetShaderIdDefault();
|
||||||
material.shader.locs = rlGetShaderLocsDefault();
|
material.shader.locs = rlGetShaderLocsDefault();
|
||||||
|
|
||||||
// Using rlgl default texture (1x1 pixel, UNCOMPRESSED_R8G8B8A8, 1 mipmap)
|
// Using rlgl default texture (1x1 pixel, UNCOMPRESSED_R8G8B8A8, 1 mipmap)
|
||||||
material.maps[MATERIAL_MAP_DIFFUSE].texture = (Texture2D){ rlGetTextureIdDefault(), 1, 1, 1, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8 };
|
material.maps[MATERIAL_MAP_DIFFUSE].texture = (Texture2D){ rlGetTextureIdDefault(), 1, 1, 1, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8 };
|
||||||
//material.maps[MATERIAL_MAP_NORMAL].texture; // NOTE: By default, not set
|
//material.maps[MATERIAL_MAP_NORMAL].texture; // NOTE: By default, not set
|
||||||
|
|
@ -2825,7 +2825,7 @@ void GenMeshTangents(Mesh *mesh)
|
||||||
RL_FREE(tan2);
|
RL_FREE(tan2);
|
||||||
|
|
||||||
if (mesh->vboId != NULL)
|
if (mesh->vboId != NULL)
|
||||||
{
|
{
|
||||||
if (mesh->vboId[SHADER_LOC_VERTEX_TANGENT] != 0)
|
if (mesh->vboId[SHADER_LOC_VERTEX_TANGENT] != 0)
|
||||||
{
|
{
|
||||||
// Upate existing vertex buffer
|
// Upate existing vertex buffer
|
||||||
|
|
@ -2834,15 +2834,15 @@ void GenMeshTangents(Mesh *mesh)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Load a new tangent attributes buffer
|
// Load a new tangent attributes buffer
|
||||||
mesh->vboId[SHADER_LOC_VERTEX_TANGENT] = rlLoadVertexBuffer(mesh->tangents, mesh->vertexCount*4*sizeof(float), false);
|
mesh->vboId[SHADER_LOC_VERTEX_TANGENT] = rlLoadVertexBuffer(mesh->tangents, mesh->vertexCount*4*sizeof(float), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
rlEnableVertexArray(mesh->vaoId);
|
rlEnableVertexArray(mesh->vaoId);
|
||||||
rlSetVertexAttribute(4, 4, RL_FLOAT, 0, 0, 0);
|
rlSetVertexAttribute(4, 4, RL_FLOAT, 0, 0, 0);
|
||||||
rlEnableVertexAttribute(4);
|
rlEnableVertexAttribute(4);
|
||||||
rlDisableVertexArray();
|
rlDisableVertexArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
TRACELOG(LOG_INFO, "MESH: Tangents data computed and uploaded for provided mesh");
|
TRACELOG(LOG_INFO, "MESH: Tangents data computed and uploaded for provided mesh");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3370,7 +3370,7 @@ static Model LoadOBJ(const char *fileName)
|
||||||
if (ret != TINYOBJ_SUCCESS) TRACELOG(LOG_WARNING, "MODEL: [%s] Failed to load OBJ data", fileName);
|
if (ret != TINYOBJ_SUCCESS) TRACELOG(LOG_WARNING, "MODEL: [%s] Failed to load OBJ data", fileName);
|
||||||
else TRACELOG(LOG_INFO, "MODEL: [%s] OBJ data loaded successfully: %i meshes/%i materials", fileName, meshCount, materialCount);
|
else TRACELOG(LOG_INFO, "MODEL: [%s] OBJ data loaded successfully: %i meshes/%i materials", fileName, meshCount, materialCount);
|
||||||
|
|
||||||
model.meshCount = materialCount;
|
model.meshCount = materialCount;
|
||||||
|
|
||||||
// Init model materials array
|
// Init model materials array
|
||||||
if (materialCount > 0)
|
if (materialCount > 0)
|
||||||
|
|
@ -3468,7 +3468,7 @@ static Model LoadOBJ(const char *fileName)
|
||||||
|
|
||||||
// Get default texture, in case no texture is defined
|
// Get default texture, in case no texture is defined
|
||||||
// NOTE: rlgl default texture is a 1x1 pixel UNCOMPRESSED_R8G8B8A8
|
// NOTE: rlgl default texture is a 1x1 pixel UNCOMPRESSED_R8G8B8A8
|
||||||
model.materials[m].maps[MATERIAL_MAP_DIFFUSE].texture = (Texture2D){ rlGetTextureIdDefault(), 1, 1, 1, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8 };
|
model.materials[m].maps[MATERIAL_MAP_DIFFUSE].texture = (Texture2D){ rlGetTextureIdDefault(), 1, 1, 1, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8 };
|
||||||
|
|
||||||
if (materials[m].diffuse_texname != NULL) model.materials[m].maps[MATERIAL_MAP_DIFFUSE].texture = LoadTexture(materials[m].diffuse_texname); //char *diffuse_texname; // map_Kd
|
if (materials[m].diffuse_texname != NULL) model.materials[m].maps[MATERIAL_MAP_DIFFUSE].texture = LoadTexture(materials[m].diffuse_texname); //char *diffuse_texname; // map_Kd
|
||||||
|
|
||||||
|
|
|
||||||
158
src/raudio.c
158
src/raudio.c
|
|
@ -728,11 +728,11 @@ Wave LoadWaveFromMemory(const char *fileType, const unsigned char *fileData, int
|
||||||
|
|
||||||
if (success)
|
if (success)
|
||||||
{
|
{
|
||||||
wave.sampleCount = (unsigned int)wav.totalPCMFrameCount*wav.channels;
|
wave.frameCount = (unsigned int)wav.totalPCMFrameCount;
|
||||||
wave.sampleRate = wav.sampleRate;
|
wave.sampleRate = wav.sampleRate;
|
||||||
wave.sampleSize = 16;
|
wave.sampleSize = 16;
|
||||||
wave.channels = wav.channels;
|
wave.channels = wav.channels;
|
||||||
wave.data = (short *)RL_MALLOC(wave.sampleCount*sizeof(short));
|
wave.data = (short *)RL_MALLOC(wave.frameCount*wave.channels*sizeof(short));
|
||||||
|
|
||||||
// NOTE: We are forcing conversion to 16bit sample size on reading
|
// NOTE: We are forcing conversion to 16bit sample size on reading
|
||||||
drwav_read_pcm_frames_s16(&wav, wav.totalPCMFrameCount, wave.data);
|
drwav_read_pcm_frames_s16(&wav, wav.totalPCMFrameCount, wave.data);
|
||||||
|
|
@ -754,11 +754,11 @@ Wave LoadWaveFromMemory(const char *fileType, const unsigned char *fileData, int
|
||||||
wave.sampleRate = info.sample_rate;
|
wave.sampleRate = info.sample_rate;
|
||||||
wave.sampleSize = 16; // By default, ogg data is 16 bit per sample (short)
|
wave.sampleSize = 16; // By default, ogg data is 16 bit per sample (short)
|
||||||
wave.channels = info.channels;
|
wave.channels = info.channels;
|
||||||
wave.sampleCount = (unsigned int)stb_vorbis_stream_length_in_samples(oggData)*info.channels; // Independent by channel
|
wave.frameCount = (unsigned int)stb_vorbis_stream_length_in_samples(oggData); // NOTE: It returns frames!
|
||||||
wave.data = (short *)RL_MALLOC(wave.sampleCount*sizeof(short));
|
wave.data = (short *)RL_MALLOC(wave.frameCount*wave.channels*sizeof(short));
|
||||||
|
|
||||||
// NOTE: Get the number of samples to process (be careful! we ask for number of shorts!)
|
// NOTE: Get the number of samples to process (be careful! we ask for number of shorts, not bytes!)
|
||||||
stb_vorbis_get_samples_short_interleaved(oggData, info.channels, (short *)wave.data, wave.sampleCount);
|
stb_vorbis_get_samples_short_interleaved(oggData, info.channels, (short *)wave.data, wave.frameCount*wave.channels);
|
||||||
stb_vorbis_close(oggData);
|
stb_vorbis_close(oggData);
|
||||||
}
|
}
|
||||||
else TRACELOG(LOG_WARNING, "WAVE: Failed to load OGG data");
|
else TRACELOG(LOG_WARNING, "WAVE: Failed to load OGG data");
|
||||||
|
|
@ -773,7 +773,7 @@ Wave LoadWaveFromMemory(const char *fileType, const unsigned char *fileData, int
|
||||||
wave.data = drflac_open_memory_and_read_pcm_frames_s16(fileData, dataSize, &wave.channels, &wave.sampleRate, &totalFrameCount, NULL);
|
wave.data = drflac_open_memory_and_read_pcm_frames_s16(fileData, dataSize, &wave.channels, &wave.sampleRate, &totalFrameCount, NULL);
|
||||||
wave.sampleSize = 16;
|
wave.sampleSize = 16;
|
||||||
|
|
||||||
if (wave.data != NULL) wave.sampleCount = (unsigned int)totalFrameCount*wave.channels;
|
if (wave.data != NULL) wave.frameCount = (unsigned int)totalFrameCount;
|
||||||
else TRACELOG(LOG_WARNING, "WAVE: Failed to load FLAC data");
|
else TRACELOG(LOG_WARNING, "WAVE: Failed to load FLAC data");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -791,7 +791,7 @@ Wave LoadWaveFromMemory(const char *fileType, const unsigned char *fileData, int
|
||||||
{
|
{
|
||||||
wave.channels = config.channels;
|
wave.channels = config.channels;
|
||||||
wave.sampleRate = config.sampleRate;
|
wave.sampleRate = config.sampleRate;
|
||||||
wave.sampleCount = (int)totalFrameCount*wave.channels;
|
wave.frameCount = (int)totalFrameCount;
|
||||||
}
|
}
|
||||||
else TRACELOG(LOG_WARNING, "WAVE: Failed to load MP3 data");
|
else TRACELOG(LOG_WARNING, "WAVE: Failed to load MP3 data");
|
||||||
|
|
||||||
|
|
@ -835,7 +835,7 @@ Sound LoadSoundFromWave(Wave wave)
|
||||||
// First option has been selected, format conversion is done on the loading stage.
|
// First option has been selected, format conversion is done on the loading stage.
|
||||||
// The downside is that it uses more memory if the original sound is u8 or s16.
|
// The downside is that it uses more memory if the original sound is u8 or s16.
|
||||||
ma_format formatIn = ((wave.sampleSize == 8)? ma_format_u8 : ((wave.sampleSize == 16)? ma_format_s16 : ma_format_f32));
|
ma_format formatIn = ((wave.sampleSize == 8)? ma_format_u8 : ((wave.sampleSize == 16)? ma_format_s16 : ma_format_f32));
|
||||||
ma_uint32 frameCountIn = wave.sampleCount/wave.channels;
|
ma_uint32 frameCountIn = wave.frameCount;
|
||||||
|
|
||||||
ma_uint32 frameCount = (ma_uint32)ma_convert_frames(NULL, 0, AUDIO_DEVICE_FORMAT, AUDIO_DEVICE_CHANNELS, AUDIO.System.device.sampleRate, NULL, frameCountIn, formatIn, wave.channels, wave.sampleRate);
|
ma_uint32 frameCount = (ma_uint32)ma_convert_frames(NULL, 0, AUDIO_DEVICE_FORMAT, AUDIO_DEVICE_CHANNELS, AUDIO.System.device.sampleRate, NULL, frameCountIn, formatIn, wave.channels, wave.sampleRate);
|
||||||
if (frameCount == 0) TRACELOG(LOG_WARNING, "SOUND: Failed to get frame count for format conversion");
|
if (frameCount == 0) TRACELOG(LOG_WARNING, "SOUND: Failed to get frame count for format conversion");
|
||||||
|
|
@ -850,7 +850,7 @@ Sound LoadSoundFromWave(Wave wave)
|
||||||
frameCount = (ma_uint32)ma_convert_frames(audioBuffer->data, frameCount, AUDIO_DEVICE_FORMAT, AUDIO_DEVICE_CHANNELS, AUDIO.System.device.sampleRate, wave.data, frameCountIn, formatIn, wave.channels, wave.sampleRate);
|
frameCount = (ma_uint32)ma_convert_frames(audioBuffer->data, frameCount, AUDIO_DEVICE_FORMAT, AUDIO_DEVICE_CHANNELS, AUDIO.System.device.sampleRate, wave.data, frameCountIn, formatIn, wave.channels, wave.sampleRate);
|
||||||
if (frameCount == 0) TRACELOG(LOG_WARNING, "SOUND: Failed format conversion");
|
if (frameCount == 0) TRACELOG(LOG_WARNING, "SOUND: Failed format conversion");
|
||||||
|
|
||||||
sound.sampleCount = frameCount*AUDIO_DEVICE_CHANNELS;
|
sound.frameCount = frameCount;
|
||||||
sound.stream.sampleRate = AUDIO.System.device.sampleRate;
|
sound.stream.sampleRate = AUDIO.System.device.sampleRate;
|
||||||
sound.stream.sampleSize = 32;
|
sound.stream.sampleSize = 32;
|
||||||
sound.stream.channels = AUDIO_DEVICE_CHANNELS;
|
sound.stream.channels = AUDIO_DEVICE_CHANNELS;
|
||||||
|
|
@ -908,7 +908,7 @@ bool ExportWave(Wave wave, const char *fileName)
|
||||||
void *fileData = NULL;
|
void *fileData = NULL;
|
||||||
size_t fileDataSize = 0;
|
size_t fileDataSize = 0;
|
||||||
success = drwav_init_memory_write(&wav, &fileData, &fileDataSize, &format, NULL);
|
success = drwav_init_memory_write(&wav, &fileData, &fileDataSize, &format, NULL);
|
||||||
if (success) success = (int)drwav_write_pcm_frames(&wav, wave.sampleCount/wave.channels, wave.data);
|
if (success) success = (int)drwav_write_pcm_frames(&wav, wave.frameCount, wave.data);
|
||||||
drwav_result result = drwav_uninit(&wav);
|
drwav_result result = drwav_uninit(&wav);
|
||||||
|
|
||||||
if (result == DRWAV_SUCCESS) success = SaveFileData(fileName, (unsigned char *)fileData, (unsigned int)fileDataSize);
|
if (result == DRWAV_SUCCESS) success = SaveFileData(fileName, (unsigned char *)fileData, (unsigned int)fileDataSize);
|
||||||
|
|
@ -920,7 +920,7 @@ bool ExportWave(Wave wave, const char *fileName)
|
||||||
{
|
{
|
||||||
// Export raw sample data (without header)
|
// Export raw sample data (without header)
|
||||||
// NOTE: It's up to the user to track wave parameters
|
// NOTE: It's up to the user to track wave parameters
|
||||||
success = SaveFileData(fileName, wave.data, wave.sampleCount*wave.sampleSize/8);
|
success = SaveFileData(fileName, wave.data, wave.frameCount*wave.channels*wave.sampleSize/8);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (success) TRACELOG(LOG_INFO, "FILEIO: [%s] Wave data exported successfully", fileName);
|
if (success) TRACELOG(LOG_INFO, "FILEIO: [%s] Wave data exported successfully", fileName);
|
||||||
|
|
@ -938,7 +938,7 @@ bool ExportWaveAsCode(Wave wave, const char *fileName)
|
||||||
#define TEXT_BYTES_PER_LINE 20
|
#define TEXT_BYTES_PER_LINE 20
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int waveDataSize = wave.sampleCount*wave.channels*wave.sampleSize/8;
|
int waveDataSize = wave.frameCount*wave.channels*wave.sampleSize/8;
|
||||||
|
|
||||||
// NOTE: Text data buffer size is estimated considering wave data size in bytes
|
// NOTE: Text data buffer size is estimated considering wave data size in bytes
|
||||||
// and requiring 6 char bytes for every byte: "0x00, "
|
// and requiring 6 char bytes for every byte: "0x00, "
|
||||||
|
|
@ -966,7 +966,8 @@ bool ExportWaveAsCode(Wave wave, const char *fileName)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bytesCount += sprintf(txtData + bytesCount, "// Wave data information\n");
|
bytesCount += sprintf(txtData + bytesCount, "// Wave data information\n");
|
||||||
bytesCount += sprintf(txtData + bytesCount, "#define %s_SAMPLE_COUNT %u\n", varFileName, wave.sampleCount);
|
bytesCount += sprintf(txtData + bytesCount, "#define %s_FRAME_COUNT %u\n", varFileName, wave.frameCount);
|
||||||
|
bytesCount += sprintf(txtData + bytesCount, "#define %s_SAMPLE_COUNT %u\n", varFileName, wave.frameCount*wave.channels);
|
||||||
bytesCount += sprintf(txtData + bytesCount, "#define %s_SAMPLE_RATE %u\n", varFileName, wave.sampleRate);
|
bytesCount += sprintf(txtData + bytesCount, "#define %s_SAMPLE_RATE %u\n", varFileName, wave.sampleRate);
|
||||||
bytesCount += sprintf(txtData + bytesCount, "#define %s_SAMPLE_SIZE %u\n", varFileName, wave.sampleSize);
|
bytesCount += sprintf(txtData + bytesCount, "#define %s_SAMPLE_SIZE %u\n", varFileName, wave.sampleSize);
|
||||||
bytesCount += sprintf(txtData + bytesCount, "#define %s_CHANNELS %u\n\n", varFileName, wave.channels);
|
bytesCount += sprintf(txtData + bytesCount, "#define %s_CHANNELS %u\n\n", varFileName, wave.channels);
|
||||||
|
|
@ -1111,7 +1112,7 @@ void WaveFormat(Wave *wave, int sampleRate, int sampleSize, int channels)
|
||||||
ma_format formatIn = ((wave->sampleSize == 8)? ma_format_u8 : ((wave->sampleSize == 16)? ma_format_s16 : ma_format_f32));
|
ma_format formatIn = ((wave->sampleSize == 8)? ma_format_u8 : ((wave->sampleSize == 16)? ma_format_s16 : ma_format_f32));
|
||||||
ma_format formatOut = ((sampleSize == 8)? ma_format_u8 : ((sampleSize == 16)? ma_format_s16 : ma_format_f32));
|
ma_format formatOut = ((sampleSize == 8)? ma_format_u8 : ((sampleSize == 16)? ma_format_s16 : ma_format_f32));
|
||||||
|
|
||||||
ma_uint32 frameCountIn = wave->sampleCount/wave->channels;
|
ma_uint32 frameCountIn = wave->frameCount;
|
||||||
|
|
||||||
ma_uint32 frameCount = (ma_uint32)ma_convert_frames(NULL, 0, formatOut, channels, sampleRate, NULL, frameCountIn, formatIn, wave->channels, wave->sampleRate);
|
ma_uint32 frameCount = (ma_uint32)ma_convert_frames(NULL, 0, formatOut, channels, sampleRate, NULL, frameCountIn, formatIn, wave->channels, wave->sampleRate);
|
||||||
if (frameCount == 0)
|
if (frameCount == 0)
|
||||||
|
|
@ -1129,7 +1130,7 @@ void WaveFormat(Wave *wave, int sampleRate, int sampleSize, int channels)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
wave->sampleCount = frameCount*channels;
|
wave->frameCount = frameCount;
|
||||||
wave->sampleSize = sampleSize;
|
wave->sampleSize = sampleSize;
|
||||||
wave->sampleRate = sampleRate;
|
wave->sampleRate = sampleRate;
|
||||||
wave->channels = channels;
|
wave->channels = channels;
|
||||||
|
|
@ -1142,14 +1143,14 @@ Wave WaveCopy(Wave wave)
|
||||||
{
|
{
|
||||||
Wave newWave = { 0 };
|
Wave newWave = { 0 };
|
||||||
|
|
||||||
newWave.data = RL_MALLOC(wave.sampleCount*wave.sampleSize/8);
|
newWave.data = RL_MALLOC(wave.frameCount*wave.channels*wave.sampleSize/8);
|
||||||
|
|
||||||
if (newWave.data != NULL)
|
if (newWave.data != NULL)
|
||||||
{
|
{
|
||||||
// NOTE: Size must be provided in bytes
|
// NOTE: Size must be provided in bytes
|
||||||
memcpy(newWave.data, wave.data, wave.sampleCount*wave.sampleSize/8);
|
memcpy(newWave.data, wave.data, wave.frameCount*wave.channels*wave.sampleSize/8);
|
||||||
|
|
||||||
newWave.sampleCount = wave.sampleCount;
|
newWave.frameCount = wave.frameCount;
|
||||||
newWave.sampleRate = wave.sampleRate;
|
newWave.sampleRate = wave.sampleRate;
|
||||||
newWave.sampleSize = wave.sampleSize;
|
newWave.sampleSize = wave.sampleSize;
|
||||||
newWave.channels = wave.channels;
|
newWave.channels = wave.channels;
|
||||||
|
|
@ -1163,7 +1164,7 @@ Wave WaveCopy(Wave wave)
|
||||||
void WaveCrop(Wave *wave, int initSample, int finalSample)
|
void WaveCrop(Wave *wave, int initSample, int finalSample)
|
||||||
{
|
{
|
||||||
if ((initSample >= 0) && (initSample < finalSample) &&
|
if ((initSample >= 0) && (initSample < finalSample) &&
|
||||||
(finalSample > 0) && ((unsigned int)finalSample < wave->sampleCount))
|
(finalSample > 0) && ((unsigned int)finalSample < (wave->frameCount*wave->channels)))
|
||||||
{
|
{
|
||||||
int sampleCount = finalSample - initSample;
|
int sampleCount = finalSample - initSample;
|
||||||
|
|
||||||
|
|
@ -1182,11 +1183,11 @@ void WaveCrop(Wave *wave, int initSample, int finalSample)
|
||||||
// NOTE 2: Sample data allocated should be freed with UnloadWaveSamples()
|
// NOTE 2: Sample data allocated should be freed with UnloadWaveSamples()
|
||||||
float *LoadWaveSamples(Wave wave)
|
float *LoadWaveSamples(Wave wave)
|
||||||
{
|
{
|
||||||
float *samples = (float *)RL_MALLOC(wave.sampleCount*sizeof(float));
|
float *samples = (float *)RL_MALLOC(wave.frameCount*wave.channels*sizeof(float));
|
||||||
|
|
||||||
// NOTE: sampleCount is the total number of interlaced samples (including channels)
|
// NOTE: sampleCount is the total number of interlaced samples (including channels)
|
||||||
|
|
||||||
for (unsigned int i = 0; i < wave.sampleCount; i++)
|
for (unsigned int i = 0; i < wave.frameCount*wave.channels; i++)
|
||||||
{
|
{
|
||||||
if (wave.sampleSize == 8) samples[i] = (float)(((unsigned char *)wave.data)[i] - 127)/256.0f;
|
if (wave.sampleSize == 8) samples[i] = (float)(((unsigned char *)wave.data)[i] - 127)/256.0f;
|
||||||
else if (wave.sampleSize == 16) samples[i] = (float)(((short *)wave.data)[i])/32767.0f;
|
else if (wave.sampleSize == 16) samples[i] = (float)(((short *)wave.data)[i])/32767.0f;
|
||||||
|
|
@ -1228,7 +1229,7 @@ Music LoadMusicStream(const char *fileName)
|
||||||
if (ctxWav->bitsPerSample == 24) sampleSize = 16; // Forcing conversion to s16 on UpdateMusicStream()
|
if (ctxWav->bitsPerSample == 24) sampleSize = 16; // Forcing conversion to s16 on UpdateMusicStream()
|
||||||
|
|
||||||
music.stream = LoadAudioStream(ctxWav->sampleRate, sampleSize, ctxWav->channels);
|
music.stream = LoadAudioStream(ctxWav->sampleRate, sampleSize, ctxWav->channels);
|
||||||
music.sampleCount = (unsigned int)ctxWav->totalPCMFrameCount*ctxWav->channels;
|
music.frameCount = (unsigned int)ctxWav->totalPCMFrameCount;
|
||||||
music.looping = true; // Looping enabled by default
|
music.looping = true; // Looping enabled by default
|
||||||
musicLoaded = true;
|
musicLoaded = true;
|
||||||
}
|
}
|
||||||
|
|
@ -1249,7 +1250,7 @@ Music LoadMusicStream(const char *fileName)
|
||||||
music.stream = LoadAudioStream(info.sample_rate, 16, info.channels);
|
music.stream = LoadAudioStream(info.sample_rate, 16, info.channels);
|
||||||
|
|
||||||
// WARNING: It seems this function returns length in frames, not samples, so we multiply by channels
|
// WARNING: It seems this function returns length in frames, not samples, so we multiply by channels
|
||||||
music.sampleCount = (unsigned int)stb_vorbis_stream_length_in_samples((stb_vorbis *)music.ctxData)*info.channels;
|
music.frameCount = (unsigned int)stb_vorbis_stream_length_in_samples((stb_vorbis *)music.ctxData);
|
||||||
music.looping = true; // Looping enabled by default
|
music.looping = true; // Looping enabled by default
|
||||||
musicLoaded = true;
|
musicLoaded = true;
|
||||||
}
|
}
|
||||||
|
|
@ -1266,7 +1267,7 @@ Music LoadMusicStream(const char *fileName)
|
||||||
drflac *ctxFlac = (drflac *)music.ctxData;
|
drflac *ctxFlac = (drflac *)music.ctxData;
|
||||||
|
|
||||||
music.stream = LoadAudioStream(ctxFlac->sampleRate, ctxFlac->bitsPerSample, ctxFlac->channels);
|
music.stream = LoadAudioStream(ctxFlac->sampleRate, ctxFlac->bitsPerSample, ctxFlac->channels);
|
||||||
music.sampleCount = (unsigned int)ctxFlac->totalPCMFrameCount*ctxFlac->channels;
|
music.frameCount = (unsigned int)ctxFlac->totalPCMFrameCount;
|
||||||
music.looping = true; // Looping enabled by default
|
music.looping = true; // Looping enabled by default
|
||||||
musicLoaded = true;
|
musicLoaded = true;
|
||||||
}
|
}
|
||||||
|
|
@ -1284,7 +1285,7 @@ Music LoadMusicStream(const char *fileName)
|
||||||
if (result > 0)
|
if (result > 0)
|
||||||
{
|
{
|
||||||
music.stream = LoadAudioStream(ctxMp3->sampleRate, 32, ctxMp3->channels);
|
music.stream = LoadAudioStream(ctxMp3->sampleRate, 32, ctxMp3->channels);
|
||||||
music.sampleCount = (unsigned int)drmp3_get_pcm_frame_count(ctxMp3)*ctxMp3->channels;
|
music.frameCount = (unsigned int)drmp3_get_pcm_frame_count(ctxMp3);
|
||||||
music.looping = true; // Looping enabled by default
|
music.looping = true; // Looping enabled by default
|
||||||
musicLoaded = true;
|
musicLoaded = true;
|
||||||
}
|
}
|
||||||
|
|
@ -1309,9 +1310,9 @@ Music LoadMusicStream(const char *fileName)
|
||||||
|
|
||||||
// NOTE: Only stereo is supported for XM
|
// NOTE: Only stereo is supported for XM
|
||||||
music.stream = LoadAudioStream(AUDIO.System.device.sampleRate, bits, AUDIO_DEVICE_CHANNELS);
|
music.stream = LoadAudioStream(AUDIO.System.device.sampleRate, bits, AUDIO_DEVICE_CHANNELS);
|
||||||
music.sampleCount = (unsigned int)jar_xm_get_remaining_samples(ctxXm)*2; // 2 channels
|
music.frameCount = (unsigned int)jar_xm_get_remaining_samples(ctxXm); // NOTE: Always 2 channels (stereo)
|
||||||
music.looping = true; // Looping enabled by default
|
music.looping = true; // Looping enabled by default
|
||||||
jar_xm_reset(ctxXm); // make sure we start at the beginning of the song
|
jar_xm_reset(ctxXm); // make sure we start at the beginning of the song
|
||||||
musicLoaded = true;
|
musicLoaded = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1330,7 +1331,7 @@ Music LoadMusicStream(const char *fileName)
|
||||||
{
|
{
|
||||||
// NOTE: Only stereo is supported for MOD
|
// NOTE: Only stereo is supported for MOD
|
||||||
music.stream = LoadAudioStream(AUDIO.System.device.sampleRate, 16, AUDIO_DEVICE_CHANNELS);
|
music.stream = LoadAudioStream(AUDIO.System.device.sampleRate, 16, AUDIO_DEVICE_CHANNELS);
|
||||||
music.sampleCount = (unsigned int)jar_mod_max_samples(ctxMod)*2; // 2 channels
|
music.frameCount = (unsigned int)jar_mod_max_samples(ctxMod); // NOTE: Always 2 channels (stereo)
|
||||||
music.looping = true; // Looping enabled by default
|
music.looping = true; // Looping enabled by default
|
||||||
musicLoaded = true;
|
musicLoaded = true;
|
||||||
}
|
}
|
||||||
|
|
@ -1367,10 +1368,10 @@ Music LoadMusicStream(const char *fileName)
|
||||||
{
|
{
|
||||||
// Show some music stream info
|
// Show some music stream info
|
||||||
TRACELOG(LOG_INFO, "FILEIO: [%s] Music file loaded successfully", fileName);
|
TRACELOG(LOG_INFO, "FILEIO: [%s] Music file loaded successfully", fileName);
|
||||||
TRACELOG(LOG_INFO, " > Total samples: %i", music.sampleCount);
|
|
||||||
TRACELOG(LOG_INFO, " > Sample rate: %i Hz", music.stream.sampleRate);
|
TRACELOG(LOG_INFO, " > Sample rate: %i Hz", music.stream.sampleRate);
|
||||||
TRACELOG(LOG_INFO, " > Sample size: %i bits", music.stream.sampleSize);
|
TRACELOG(LOG_INFO, " > Sample size: %i bits", music.stream.sampleSize);
|
||||||
TRACELOG(LOG_INFO, " > Channels: %i (%s)", music.stream.channels, (music.stream.channels == 1)? "Mono" : (music.stream.channels == 2)? "Stereo" : "Multi");
|
TRACELOG(LOG_INFO, " > Channels: %i (%s)", music.stream.channels, (music.stream.channels == 1)? "Mono" : (music.stream.channels == 2)? "Stereo" : "Multi");
|
||||||
|
TRACELOG(LOG_INFO, " > Total frames: %i", music.frameCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
return music;
|
return music;
|
||||||
|
|
@ -1402,7 +1403,7 @@ Music LoadMusicStreamFromMemory(const char *fileType, unsigned char *data, int d
|
||||||
if (ctxWav->bitsPerSample == 24) sampleSize = 16; // Forcing conversion to s16 on UpdateMusicStream()
|
if (ctxWav->bitsPerSample == 24) sampleSize = 16; // Forcing conversion to s16 on UpdateMusicStream()
|
||||||
|
|
||||||
music.stream = LoadAudioStream(ctxWav->sampleRate, sampleSize, ctxWav->channels);
|
music.stream = LoadAudioStream(ctxWav->sampleRate, sampleSize, ctxWav->channels);
|
||||||
music.sampleCount = (unsigned int)ctxWav->totalPCMFrameCount*ctxWav->channels;
|
music.frameCount = (unsigned int)ctxWav->totalPCMFrameCount;
|
||||||
music.looping = true; // Looping enabled by default
|
music.looping = true; // Looping enabled by default
|
||||||
musicLoaded = true;
|
musicLoaded = true;
|
||||||
}
|
}
|
||||||
|
|
@ -1419,7 +1420,7 @@ Music LoadMusicStreamFromMemory(const char *fileType, unsigned char *data, int d
|
||||||
drflac *ctxFlac = (drflac *)music.ctxData;
|
drflac *ctxFlac = (drflac *)music.ctxData;
|
||||||
|
|
||||||
music.stream = LoadAudioStream(ctxFlac->sampleRate, ctxFlac->bitsPerSample, ctxFlac->channels);
|
music.stream = LoadAudioStream(ctxFlac->sampleRate, ctxFlac->bitsPerSample, ctxFlac->channels);
|
||||||
music.sampleCount = (unsigned int)ctxFlac->totalPCMFrameCount*ctxFlac->channels;
|
music.frameCount = (unsigned int)ctxFlac->totalPCMFrameCount;
|
||||||
music.looping = true; // Looping enabled by default
|
music.looping = true; // Looping enabled by default
|
||||||
musicLoaded = true;
|
musicLoaded = true;
|
||||||
}
|
}
|
||||||
|
|
@ -1437,7 +1438,7 @@ Music LoadMusicStreamFromMemory(const char *fileType, unsigned char *data, int d
|
||||||
if (success)
|
if (success)
|
||||||
{
|
{
|
||||||
music.stream = LoadAudioStream(ctxMp3->sampleRate, 32, ctxMp3->channels);
|
music.stream = LoadAudioStream(ctxMp3->sampleRate, 32, ctxMp3->channels);
|
||||||
music.sampleCount = (unsigned int)drmp3_get_pcm_frame_count(ctxMp3)*ctxMp3->channels;
|
music.frameCount = (unsigned int)drmp3_get_pcm_frame_count(ctxMp3);
|
||||||
music.looping = true; // Looping enabled by default
|
music.looping = true; // Looping enabled by default
|
||||||
musicLoaded = true;
|
musicLoaded = true;
|
||||||
}
|
}
|
||||||
|
|
@ -1459,7 +1460,7 @@ Music LoadMusicStreamFromMemory(const char *fileType, unsigned char *data, int d
|
||||||
music.stream = LoadAudioStream(info.sample_rate, 16, info.channels);
|
music.stream = LoadAudioStream(info.sample_rate, 16, info.channels);
|
||||||
|
|
||||||
// WARNING: It seems this function returns length in frames, not samples, so we multiply by channels
|
// WARNING: It seems this function returns length in frames, not samples, so we multiply by channels
|
||||||
music.sampleCount = (unsigned int)stb_vorbis_stream_length_in_samples((stb_vorbis *)music.ctxData)*info.channels;
|
music.frameCount = (unsigned int)stb_vorbis_stream_length_in_samples((stb_vorbis *)music.ctxData);
|
||||||
music.looping = true; // Looping enabled by default
|
music.looping = true; // Looping enabled by default
|
||||||
musicLoaded = true;
|
musicLoaded = true;
|
||||||
}
|
}
|
||||||
|
|
@ -1483,7 +1484,7 @@ Music LoadMusicStreamFromMemory(const char *fileType, unsigned char *data, int d
|
||||||
|
|
||||||
// NOTE: Only stereo is supported for XM
|
// NOTE: Only stereo is supported for XM
|
||||||
music.stream = LoadAudioStream(AUDIO.System.device.sampleRate, bits, 2);
|
music.stream = LoadAudioStream(AUDIO.System.device.sampleRate, bits, 2);
|
||||||
music.sampleCount = (unsigned int)jar_xm_get_remaining_samples(ctxXm)*2; // 2 channels
|
music.frameCount = (unsigned int)jar_xm_get_remaining_samples(ctxXm); // NOTE: Always 2 channels (stereo)
|
||||||
music.looping = true; // Looping enabled by default
|
music.looping = true; // Looping enabled by default
|
||||||
jar_xm_reset(ctxXm); // make sure we start at the beginning of the song
|
jar_xm_reset(ctxXm); // make sure we start at the beginning of the song
|
||||||
|
|
||||||
|
|
@ -1521,7 +1522,7 @@ Music LoadMusicStreamFromMemory(const char *fileType, unsigned char *data, int d
|
||||||
|
|
||||||
// NOTE: Only stereo is supported for MOD
|
// NOTE: Only stereo is supported for MOD
|
||||||
music.stream = LoadAudioStream(AUDIO.System.device.sampleRate, 16, 2);
|
music.stream = LoadAudioStream(AUDIO.System.device.sampleRate, 16, 2);
|
||||||
music.sampleCount = (unsigned int)jar_mod_max_samples(ctxMod)*2; // 2 channels
|
music.frameCount = (unsigned int)jar_mod_max_samples(ctxMod); // NOTE: Always 2 channels (stereo)
|
||||||
music.looping = true; // Looping enabled by default
|
music.looping = true; // Looping enabled by default
|
||||||
musicLoaded = true;
|
musicLoaded = true;
|
||||||
|
|
||||||
|
|
@ -1561,10 +1562,10 @@ Music LoadMusicStreamFromMemory(const char *fileType, unsigned char *data, int d
|
||||||
{
|
{
|
||||||
// Show some music stream info
|
// Show some music stream info
|
||||||
TRACELOG(LOG_INFO, "FILEIO: Music data loaded successfully");
|
TRACELOG(LOG_INFO, "FILEIO: Music data loaded successfully");
|
||||||
TRACELOG(LOG_INFO, " > Total samples: %i", music.sampleCount);
|
|
||||||
TRACELOG(LOG_INFO, " > Sample rate: %i Hz", music.stream.sampleRate);
|
TRACELOG(LOG_INFO, " > Sample rate: %i Hz", music.stream.sampleRate);
|
||||||
TRACELOG(LOG_INFO, " > Sample size: %i bits", music.stream.sampleSize);
|
TRACELOG(LOG_INFO, " > Sample size: %i bits", music.stream.sampleSize);
|
||||||
TRACELOG(LOG_INFO, " > Channels: %i (%s)", music.stream.channels, (music.stream.channels == 1)? "Mono" : (music.stream.channels == 2)? "Stereo" : "Multi");
|
TRACELOG(LOG_INFO, " > Channels: %i (%s)", music.stream.channels, (music.stream.channels == 1)? "Mono" : (music.stream.channels == 2)? "Stereo" : "Multi");
|
||||||
|
TRACELOG(LOG_INFO, " > Total frames: %i", music.frameCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
return music;
|
return music;
|
||||||
|
|
@ -1660,29 +1661,22 @@ void UpdateMusicStream(Music music)
|
||||||
{
|
{
|
||||||
if (music.stream.buffer == NULL) return;
|
if (music.stream.buffer == NULL) return;
|
||||||
|
|
||||||
#if defined(SUPPORT_FILEFORMAT_XM)
|
|
||||||
if (music.ctxType == MUSIC_MODULE_XM) jar_xm_set_max_loop_count(music.ctxData, music.looping ? 0 : 1);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
bool streamEnding = false;
|
bool streamEnding = false;
|
||||||
|
|
||||||
unsigned int subBufferSizeInFrames = music.stream.buffer->sizeInFrames/2;
|
unsigned int subBufferSizeInFrames = music.stream.buffer->sizeInFrames/2;
|
||||||
|
|
||||||
// NOTE: Using dynamic allocation because it could require more than 16KB
|
// NOTE: Using dynamic allocation because it could require more than 16KB
|
||||||
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 frameCountToStream = 0; // Total size of data in frames to be streamed
|
||||||
|
|
||||||
// TODO: Get the sampleLeft using framesProcessed... but first, get total frames processed correctly...
|
// TODO: Get the framesLeft using framesProcessed... 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->framesProcessed*music.stream.channels);
|
int framesLeft = music.frameCount - music.stream.buffer->framesProcessed;
|
||||||
|
|
||||||
if (music.ctxType == MUSIC_MODULE_XM && music.looping) sampleLeft = subBufferSizeInFrames*4;
|
|
||||||
|
|
||||||
while (IsAudioStreamProcessed(music.stream))
|
while (IsAudioStreamProcessed(music.stream))
|
||||||
{
|
{
|
||||||
if ((sampleLeft/music.stream.channels) >= subBufferSizeInFrames) samplesCount = subBufferSizeInFrames*music.stream.channels;
|
if (framesLeft >= subBufferSizeInFrames) frameCountToStream = subBufferSizeInFrames;
|
||||||
else samplesCount = sampleLeft;
|
else frameCountToStream = framesLeft;
|
||||||
|
|
||||||
switch (music.ctxType)
|
switch (music.ctxType)
|
||||||
{
|
{
|
||||||
|
|
@ -1690,8 +1684,8 @@ void UpdateMusicStream(Music music)
|
||||||
case MUSIC_AUDIO_WAV:
|
case MUSIC_AUDIO_WAV:
|
||||||
{
|
{
|
||||||
// NOTE: Returns the number of samples to process (not required)
|
// NOTE: Returns the number of samples to process (not required)
|
||||||
if (music.stream.sampleSize == 16) drwav_read_pcm_frames_s16((drwav *)music.ctxData, samplesCount/music.stream.channels, (short *)pcm);
|
if (music.stream.sampleSize == 16) drwav_read_pcm_frames_s16((drwav *)music.ctxData, frameCountToStream, (short *)pcm);
|
||||||
else if (music.stream.sampleSize == 32) drwav_read_pcm_frames_f32((drwav *)music.ctxData, samplesCount/music.stream.channels, (float *)pcm);
|
else if (music.stream.sampleSize == 32) drwav_read_pcm_frames_f32((drwav *)music.ctxData, frameCountToStream, (float *)pcm);
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -1699,7 +1693,7 @@ void UpdateMusicStream(Music music)
|
||||||
case MUSIC_AUDIO_OGG:
|
case MUSIC_AUDIO_OGG:
|
||||||
{
|
{
|
||||||
// NOTE: Returns the number of samples to process (be careful! we ask for number of shorts!)
|
// NOTE: Returns the number of samples to process (be careful! we ask for number of shorts!)
|
||||||
stb_vorbis_get_samples_short_interleaved((stb_vorbis *)music.ctxData, music.stream.channels, (short *)pcm, samplesCount);
|
stb_vorbis_get_samples_short_interleaved((stb_vorbis *)music.ctxData, music.stream.channels, (short *)pcm, frameCountToStream*music.stream.channels);
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -1707,15 +1701,14 @@ void UpdateMusicStream(Music music)
|
||||||
case MUSIC_AUDIO_FLAC:
|
case MUSIC_AUDIO_FLAC:
|
||||||
{
|
{
|
||||||
// NOTE: Returns the number of samples to process (not required)
|
// NOTE: Returns the number of samples to process (not required)
|
||||||
drflac_read_pcm_frames_s16((drflac *)music.ctxData, samplesCount, (short *)pcm);
|
drflac_read_pcm_frames_s16((drflac *)music.ctxData, frameCountToStream*music.stream.channels, (short *)pcm);
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
#endif
|
#endif
|
||||||
#if defined(SUPPORT_FILEFORMAT_MP3)
|
#if defined(SUPPORT_FILEFORMAT_MP3)
|
||||||
case MUSIC_AUDIO_MP3:
|
case MUSIC_AUDIO_MP3:
|
||||||
{
|
{
|
||||||
// NOTE: samplesCount, actually refers to framesCount and returns the number of frames processed
|
drmp3_read_pcm_frames_f32((drmp3 *)music.ctxData, frameCountToStream, (float *)pcm);
|
||||||
drmp3_read_pcm_frames_f32((drmp3 *)music.ctxData, samplesCount/music.stream.channels, (float *)pcm);
|
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -1723,9 +1716,9 @@ void UpdateMusicStream(Music music)
|
||||||
case MUSIC_MODULE_XM:
|
case MUSIC_MODULE_XM:
|
||||||
{
|
{
|
||||||
// NOTE: Internally we consider 2 channels generation, so samplesCount/2
|
// NOTE: Internally we consider 2 channels generation, so samplesCount/2
|
||||||
if (AUDIO_DEVICE_FORMAT == ma_format_f32) jar_xm_generate_samples((jar_xm_context_t *)music.ctxData, (float *)pcm, samplesCount/2);
|
if (AUDIO_DEVICE_FORMAT == ma_format_f32) jar_xm_generate_samples((jar_xm_context_t *)music.ctxData, (float *)pcm, frameCountToStream);
|
||||||
else if (AUDIO_DEVICE_FORMAT == ma_format_s16) jar_xm_generate_samples_16bit((jar_xm_context_t *)music.ctxData, (short *)pcm, samplesCount/2);
|
else if (AUDIO_DEVICE_FORMAT == ma_format_s16) jar_xm_generate_samples_16bit((jar_xm_context_t *)music.ctxData, (short *)pcm, frameCountToStream);
|
||||||
else if (AUDIO_DEVICE_FORMAT == ma_format_u8) jar_xm_generate_samples_8bit((jar_xm_context_t *)music.ctxData, (char *)pcm, samplesCount/2);
|
else if (AUDIO_DEVICE_FORMAT == ma_format_u8) jar_xm_generate_samples_8bit((jar_xm_context_t *)music.ctxData, (char *)pcm, frameCountToStream);
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -1733,22 +1726,17 @@ void UpdateMusicStream(Music music)
|
||||||
case MUSIC_MODULE_MOD:
|
case MUSIC_MODULE_MOD:
|
||||||
{
|
{
|
||||||
// NOTE: 3rd parameter (nbsample) specify the number of stereo 16bits samples you want, so sampleCount/2
|
// NOTE: 3rd parameter (nbsample) specify the number of stereo 16bits samples you want, so sampleCount/2
|
||||||
jar_mod_fillbuffer((jar_mod_context_t *)music.ctxData, (short *)pcm, samplesCount/2, 0);
|
jar_mod_fillbuffer((jar_mod_context_t *)music.ctxData, (short *)pcm, frameCountToStream, 0);
|
||||||
} break;
|
} break;
|
||||||
#endif
|
#endif
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateAudioStream(music.stream, pcm, samplesCount);
|
UpdateAudioStream(music.stream, pcm, frameCountToStream);
|
||||||
|
|
||||||
if ((music.ctxType == MUSIC_MODULE_XM) || music.ctxType == MUSIC_MODULE_MOD)
|
framesLeft -= frameCountToStream;
|
||||||
{
|
|
||||||
if (samplesCount > 1) sampleLeft -= samplesCount/2;
|
|
||||||
else sampleLeft -= samplesCount;
|
|
||||||
}
|
|
||||||
else sampleLeft -= samplesCount;
|
|
||||||
|
|
||||||
if (sampleLeft <= 0)
|
if (framesLeft <= 0)
|
||||||
{
|
{
|
||||||
streamEnding = true;
|
streamEnding = true;
|
||||||
break;
|
break;
|
||||||
|
|
@ -1795,7 +1783,7 @@ float GetMusicTimeLength(Music music)
|
||||||
{
|
{
|
||||||
float totalSeconds = 0.0f;
|
float totalSeconds = 0.0f;
|
||||||
|
|
||||||
totalSeconds = (float)music.sampleCount/(music.stream.sampleRate*music.stream.channels);
|
totalSeconds = (float)music.frameCount/music.stream.sampleRate;
|
||||||
|
|
||||||
return totalSeconds;
|
return totalSeconds;
|
||||||
}
|
}
|
||||||
|
|
@ -1803,22 +1791,24 @@ float GetMusicTimeLength(Music music)
|
||||||
// Get current music time played (in seconds)
|
// Get current music time played (in seconds)
|
||||||
float GetMusicTimePlayed(Music music)
|
float GetMusicTimePlayed(Music music)
|
||||||
{
|
{
|
||||||
#if defined(SUPPORT_FILEFORMAT_XM)
|
|
||||||
if (music.ctxType == MUSIC_MODULE_XM)
|
|
||||||
{
|
|
||||||
uint64_t samples = 0;
|
|
||||||
jar_xm_get_position(music.ctxData, NULL, NULL, NULL, &samples);
|
|
||||||
samples = samples % (music.sampleCount);
|
|
||||||
|
|
||||||
return (float)(samples)/(music.stream.sampleRate*music.stream.channels);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
float secondsPlayed = 0.0f;
|
float secondsPlayed = 0.0f;
|
||||||
if (music.stream.buffer != NULL)
|
if (music.stream.buffer != NULL)
|
||||||
{
|
{
|
||||||
//ma_uint32 frameSizeInBytes = ma_get_bytes_per_sample(music.stream.buffer->dsp.formatConverterIn.config.formatIn)*music.stream.buffer->dsp.formatConverterIn.config.channels;
|
#if defined(SUPPORT_FILEFORMAT_XM)
|
||||||
unsigned int samplesPlayed = music.stream.buffer->framesProcessed*music.stream.channels;
|
if (music.ctxType == MUSIC_MODULE_XM)
|
||||||
secondsPlayed = (float)samplesPlayed/(music.stream.sampleRate*music.stream.channels);
|
{
|
||||||
|
uint64_t framesPlayed = 0;
|
||||||
|
|
||||||
|
jar_xm_get_position(music.ctxData, NULL, NULL, NULL, &framesPlayed);
|
||||||
|
secondsPlayed = (float)framesPlayed/music.stream.sampleRate;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
//ma_uint32 frameSizeInBytes = ma_get_bytes_per_sample(music.stream.buffer->dsp.formatConverterIn.config.formatIn)*music.stream.buffer->dsp.formatConverterIn.config.channels;
|
||||||
|
unsigned int framesPlayed = music.stream.buffer->framesProcessed;
|
||||||
|
secondsPlayed = (float)framesPlayed/music.stream.sampleRate;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return secondsPlayed;
|
return secondsPlayed;
|
||||||
|
|
@ -1867,7 +1857,7 @@ void UnloadAudioStream(AudioStream stream)
|
||||||
// Update audio stream buffers with data
|
// Update audio stream buffers with data
|
||||||
// NOTE 1: Only updates one buffer of the stream source: unqueue -> update -> queue
|
// NOTE 1: Only updates one buffer of the stream source: unqueue -> update -> queue
|
||||||
// NOTE 2: To unqueue a buffer it needs to be processed: IsAudioStreamProcessed()
|
// NOTE 2: To unqueue a buffer it needs to be processed: IsAudioStreamProcessed()
|
||||||
void UpdateAudioStream(AudioStream stream, const void *data, int samplesCount)
|
void UpdateAudioStream(AudioStream stream, const void *data, int frameCount)
|
||||||
{
|
{
|
||||||
if (stream.buffer != NULL)
|
if (stream.buffer != NULL)
|
||||||
{
|
{
|
||||||
|
|
@ -1896,11 +1886,11 @@ void UpdateAudioStream(AudioStream stream, const void *data, int samplesCount)
|
||||||
|
|
||||||
// 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)frameCount)
|
||||||
{
|
{
|
||||||
ma_uint32 framesToWrite = subBufferSizeInFrames;
|
ma_uint32 framesToWrite = subBufferSizeInFrames;
|
||||||
|
|
||||||
if (framesToWrite > ((ma_uint32)samplesCount/stream.channels)) framesToWrite = (ma_uint32)samplesCount/stream.channels;
|
if (framesToWrite > (ma_uint32)frameCount) framesToWrite = (ma_uint32)frameCount;
|
||||||
|
|
||||||
ma_uint32 bytesToWrite = framesToWrite*stream.channels*(stream.sampleSize/8);
|
ma_uint32 bytesToWrite = framesToWrite*stream.channels*(stream.sampleSize/8);
|
||||||
memcpy(subBuffer, data, bytesToWrite);
|
memcpy(subBuffer, data, bytesToWrite);
|
||||||
|
|
|
||||||
51
src/raudio.h
51
src/raudio.h
|
|
@ -78,49 +78,42 @@
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Wave type, defines audio wave data
|
// Wave, audio wave data
|
||||||
typedef struct Wave {
|
typedef struct Wave {
|
||||||
unsigned int sampleCount; // Total number of samples
|
unsigned int frameCount; // Total number of frames (considering channels)
|
||||||
unsigned int sampleRate; // Frequency (samples per second)
|
unsigned int sampleRate; // Frequency (samples per second)
|
||||||
unsigned int sampleSize; // Bit depth (bits per sample): 8, 16, 32 (24 not supported)
|
unsigned int sampleSize; // Bit depth (bits per sample): 8, 16, 32 (24 not supported)
|
||||||
unsigned int channels; // Number of channels (1-mono, 2-stereo)
|
unsigned int channels; // Number of channels (1-mono, 2-stereo, ...)
|
||||||
void *data; // Buffer data pointer
|
void *data; // Buffer data pointer
|
||||||
} Wave;
|
} Wave;
|
||||||
|
|
||||||
typedef struct rAudioBuffer rAudioBuffer;
|
typedef struct rAudioBuffer rAudioBuffer;
|
||||||
|
|
||||||
// Audio stream type
|
// AudioStream, custom audio stream
|
||||||
// NOTE: Useful to create custom audio streams not bound to a specific file
|
|
||||||
typedef struct AudioStream {
|
typedef struct AudioStream {
|
||||||
unsigned int sampleRate; // Frequency (samples per second)
|
rAudioBuffer *buffer; // Pointer to internal data used by the audio system
|
||||||
unsigned int sampleSize; // Bit depth (bits per sample): 8, 16, 32 (24 not supported)
|
|
||||||
unsigned int channels; // Number of channels (1-mono, 2-stereo)
|
|
||||||
|
|
||||||
rAudioBuffer *buffer; // Pointer to internal data used by the audio system
|
unsigned int sampleRate; // Frequency (samples per second)
|
||||||
|
unsigned int sampleSize; // Bit depth (bits per sample): 8, 16, 32 (24 not supported)
|
||||||
|
unsigned int channels; // Number of channels (1-mono, 2-stereo, ...)
|
||||||
} AudioStream;
|
} AudioStream;
|
||||||
|
|
||||||
// Sound source type
|
// Sound
|
||||||
typedef struct Sound {
|
typedef struct Sound {
|
||||||
unsigned int sampleCount; // Total number of samples
|
AudioStream stream; // Audio stream
|
||||||
AudioStream stream; // Audio stream
|
unsigned int frameCount; // Total number of frames (considering channels)
|
||||||
} Sound;
|
} Sound;
|
||||||
|
|
||||||
// Music stream type (audio file streaming from memory)
|
// Music, audio stream, anything longer than ~10 seconds should be streamed
|
||||||
// NOTE: Anything longer than ~10 seconds should be streamed
|
|
||||||
typedef struct Music {
|
typedef struct Music {
|
||||||
int ctxType; // Type of music context (audio filetype)
|
AudioStream stream; // Audio stream
|
||||||
void *ctxData; // Audio context data, depends on type
|
unsigned int frameCount; // Total number of frames (considering channels)
|
||||||
|
bool looping; // Music looping enable
|
||||||
|
|
||||||
bool looping; // Music looping enable
|
int ctxType; // Type of music context (audio filetype)
|
||||||
unsigned int sampleCount; // Total number of samples
|
void *ctxData; // Audio context data, depends on type
|
||||||
|
|
||||||
AudioStream stream; // Audio stream
|
|
||||||
} Music;
|
} Music;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" { // Prevents name mangling of functions
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Global Variables Definition
|
// Global Variables Definition
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
@ -130,6 +123,10 @@ extern "C" { // Prevents name mangling of functions
|
||||||
// Module Functions Declaration
|
// Module Functions Declaration
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" { // Prevents name mangling of functions
|
||||||
|
#endif
|
||||||
|
|
||||||
// Audio device management functions
|
// Audio device management functions
|
||||||
void InitAudioDevice(void); // Initialize audio device and context
|
void InitAudioDevice(void); // Initialize audio device and context
|
||||||
void CloseAudioDevice(void); // Close the audio device and context
|
void CloseAudioDevice(void); // Close the audio device and context
|
||||||
|
|
|
||||||
12
src/raylib.h
12
src/raylib.h
|
|
@ -423,10 +423,10 @@ typedef struct BoundingBox {
|
||||||
|
|
||||||
// Wave, audio wave data
|
// Wave, audio wave data
|
||||||
typedef struct Wave {
|
typedef struct Wave {
|
||||||
unsigned int sampleCount; // Total number of samples (considering channels!)
|
unsigned int frameCount; // Total number of frames (considering channels)
|
||||||
unsigned int sampleRate; // Frequency (samples per second)
|
unsigned int sampleRate; // Frequency (samples per second)
|
||||||
unsigned int sampleSize; // Bit depth (bits per sample): 8, 16, 32 (24 not supported)
|
unsigned int sampleSize; // Bit depth (bits per sample): 8, 16, 32 (24 not supported)
|
||||||
unsigned int channels; // Number of channels (1-mono, 2-stereo)
|
unsigned int channels; // Number of channels (1-mono, 2-stereo, ...)
|
||||||
void *data; // Buffer data pointer
|
void *data; // Buffer data pointer
|
||||||
} Wave;
|
} Wave;
|
||||||
|
|
||||||
|
|
@ -438,19 +438,19 @@ typedef struct AudioStream {
|
||||||
|
|
||||||
unsigned int sampleRate; // Frequency (samples per second)
|
unsigned int sampleRate; // Frequency (samples per second)
|
||||||
unsigned int sampleSize; // Bit depth (bits per sample): 8, 16, 32 (24 not supported)
|
unsigned int sampleSize; // Bit depth (bits per sample): 8, 16, 32 (24 not supported)
|
||||||
unsigned int channels; // Number of channels (1-mono, 2-stereo)
|
unsigned int channels; // Number of channels (1-mono, 2-stereo, ...)
|
||||||
} AudioStream;
|
} AudioStream;
|
||||||
|
|
||||||
// Sound
|
// Sound
|
||||||
typedef struct Sound {
|
typedef struct Sound {
|
||||||
AudioStream stream; // Audio stream
|
AudioStream stream; // Audio stream
|
||||||
unsigned int sampleCount; // Total number of samples
|
unsigned int frameCount; // Total number of frames (considering channels)
|
||||||
} Sound;
|
} Sound;
|
||||||
|
|
||||||
// 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
|
||||||
unsigned int sampleCount; // Total number of samples
|
unsigned int frameCount; // Total number of frames (considering channels)
|
||||||
bool looping; // Music looping enable
|
bool looping; // Music looping enable
|
||||||
|
|
||||||
int ctxType; // Type of music context (audio filetype)
|
int ctxType; // Type of music context (audio filetype)
|
||||||
|
|
@ -1513,7 +1513,7 @@ RLAPI float GetMusicTimePlayed(Music music); // Get cur
|
||||||
// AudioStream management functions
|
// AudioStream management functions
|
||||||
RLAPI AudioStream LoadAudioStream(unsigned int sampleRate, unsigned int sampleSize, unsigned int channels); // Load audio stream (to stream raw audio pcm data)
|
RLAPI AudioStream LoadAudioStream(unsigned int sampleRate, unsigned int sampleSize, unsigned int channels); // Load audio stream (to stream raw audio pcm data)
|
||||||
RLAPI void UnloadAudioStream(AudioStream stream); // Unload audio stream and free memory
|
RLAPI void UnloadAudioStream(AudioStream stream); // Unload audio stream and free memory
|
||||||
RLAPI void UpdateAudioStream(AudioStream stream, const void *data, int samplesCount); // Update audio stream buffers with data
|
RLAPI void UpdateAudioStream(AudioStream stream, const void *data, int framesCount); // Update audio stream buffers with data
|
||||||
RLAPI bool IsAudioStreamProcessed(AudioStream stream); // Check if any audio stream buffers requires refill
|
RLAPI bool IsAudioStreamProcessed(AudioStream stream); // Check if any audio stream buffers requires refill
|
||||||
RLAPI void PlayAudioStream(AudioStream stream); // Play audio stream
|
RLAPI void PlayAudioStream(AudioStream stream); // Play audio stream
|
||||||
RLAPI void PauseAudioStream(AudioStream stream); // Pause audio stream
|
RLAPI void PauseAudioStream(AudioStream stream); // Pause audio stream
|
||||||
|
|
|
||||||
|
|
@ -1432,7 +1432,7 @@ RMDEF Quaternion QuaternionFromAxisAngle(Vector3 axis, float angle)
|
||||||
{
|
{
|
||||||
Quaternion result = { 0.0f, 0.0f, 0.0f, 1.0f };
|
Quaternion result = { 0.0f, 0.0f, 0.0f, 1.0f };
|
||||||
float axisLength = sqrtf(axis.x*axis.x + axis.y*axis.y + axis.z*axis.z);
|
float axisLength = sqrtf(axis.x*axis.x + axis.y*axis.y + axis.z*axis.z);
|
||||||
|
|
||||||
if (axisLength != 0.0f)
|
if (axisLength != 0.0f)
|
||||||
{
|
{
|
||||||
angle *= 0.5f;
|
angle *= 0.5f;
|
||||||
|
|
|
||||||
58
src/rlgl.h
58
src/rlgl.h
|
|
@ -41,7 +41,7 @@
|
||||||
* #define SUPPORT_GL_DETAILS_INFO
|
* #define SUPPORT_GL_DETAILS_INFO
|
||||||
* Show OpenGL extensions and capabilities detailed logs on init
|
* Show OpenGL extensions and capabilities detailed logs on init
|
||||||
*
|
*
|
||||||
* rlgl capabilities could be customized just defining some internal
|
* rlgl capabilities could be customized just defining some internal
|
||||||
* values before library inclusion (default values listed):
|
* values before library inclusion (default values listed):
|
||||||
*
|
*
|
||||||
* #define RL_DEFAULT_BATCH_BUFFER_ELEMENTS 8192 // Default internal render batch elements limits
|
* #define RL_DEFAULT_BATCH_BUFFER_ELEMENTS 8192 // Default internal render batch elements limits
|
||||||
|
|
@ -54,7 +54,7 @@
|
||||||
* #define RL_CULL_DISTANCE_NEAR 0.01 // Default projection matrix near cull distance
|
* #define RL_CULL_DISTANCE_NEAR 0.01 // Default projection matrix near cull distance
|
||||||
* #define RL_CULL_DISTANCE_FAR 1000.0 // Default projection matrix far cull distance
|
* #define RL_CULL_DISTANCE_FAR 1000.0 // Default projection matrix far cull distance
|
||||||
*
|
*
|
||||||
* When loading a shader, the following vertex attribute and uniform
|
* When loading a shader, the following vertex attribute and uniform
|
||||||
* location names are tried to be set automatically:
|
* location names are tried to be set automatically:
|
||||||
*
|
*
|
||||||
* #define RL_DEFAULT_SHADER_ATTRIB_NAME_POSITION "vertexPosition" // Binded by default to shader location: 0
|
* #define RL_DEFAULT_SHADER_ATTRIB_NAME_POSITION "vertexPosition" // Binded by default to shader location: 0
|
||||||
|
|
@ -246,11 +246,11 @@
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Types and Structures Definition
|
// Types and Structures Definition
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
typedef enum {
|
typedef enum {
|
||||||
OPENGL_11 = 1,
|
OPENGL_11 = 1,
|
||||||
OPENGL_21,
|
OPENGL_21,
|
||||||
OPENGL_33,
|
OPENGL_33,
|
||||||
OPENGL_ES_20
|
OPENGL_ES_20
|
||||||
} rlGlVersion;
|
} rlGlVersion;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
|
@ -1025,7 +1025,7 @@ void rlLoadIdentity(void)
|
||||||
// Multiply the current matrix by a translation matrix
|
// Multiply the current matrix by a translation matrix
|
||||||
void rlTranslatef(float x, float y, float z)
|
void rlTranslatef(float x, float y, float z)
|
||||||
{
|
{
|
||||||
Matrix matTranslation = {
|
Matrix matTranslation = {
|
||||||
1.0f, 0.0f, 0.0f, x,
|
1.0f, 0.0f, 0.0f, x,
|
||||||
0.0f, 1.0f, 0.0f, y,
|
0.0f, 1.0f, 0.0f, y,
|
||||||
0.0f, 0.0f, 1.0f, z,
|
0.0f, 0.0f, 1.0f, z,
|
||||||
|
|
@ -1041,7 +1041,7 @@ void rlTranslatef(float x, float y, float z)
|
||||||
void rlRotatef(float angle, float x, float y, float z)
|
void rlRotatef(float angle, float x, float y, float z)
|
||||||
{
|
{
|
||||||
Matrix matRotation = rlMatrixIdentity();
|
Matrix matRotation = rlMatrixIdentity();
|
||||||
|
|
||||||
// Axis vector (x, y, z) normalization
|
// Axis vector (x, y, z) normalization
|
||||||
float lengthSquared = x*x + y*y + z*z;
|
float lengthSquared = x*x + y*y + z*z;
|
||||||
if ((lengthSquared != 1.0f) && (lengthSquared != 0.0f))
|
if ((lengthSquared != 1.0f) && (lengthSquared != 0.0f))
|
||||||
|
|
@ -1051,7 +1051,7 @@ void rlRotatef(float angle, float x, float y, float z)
|
||||||
y *= inverseLength;
|
y *= inverseLength;
|
||||||
z *= inverseLength;
|
z *= inverseLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rotation matrix generation
|
// Rotation matrix generation
|
||||||
float sinres = sinf(DEG2RAD*angle);
|
float sinres = sinf(DEG2RAD*angle);
|
||||||
float cosres = cosf(DEG2RAD*angle);
|
float cosres = cosf(DEG2RAD*angle);
|
||||||
|
|
@ -1084,11 +1084,11 @@ void rlRotatef(float angle, float x, float y, float z)
|
||||||
// Multiply the current matrix by a scaling matrix
|
// Multiply the current matrix by a scaling matrix
|
||||||
void rlScalef(float x, float y, float z)
|
void rlScalef(float x, float y, float z)
|
||||||
{
|
{
|
||||||
Matrix matScale = {
|
Matrix matScale = {
|
||||||
x, 0.0f, 0.0f, 0.0f,
|
x, 0.0f, 0.0f, 0.0f,
|
||||||
0.0f, y, 0.0f, 0.0f,
|
0.0f, y, 0.0f, 0.0f,
|
||||||
0.0f, 0.0f, z, 0.0f,
|
0.0f, 0.0f, z, 0.0f,
|
||||||
0.0f, 0.0f, 0.0f, 1.0f
|
0.0f, 0.0f, 0.0f, 1.0f
|
||||||
};
|
};
|
||||||
|
|
||||||
// NOTE: We transpose matrix with multiplication order
|
// NOTE: We transpose matrix with multiplication order
|
||||||
|
|
@ -1145,7 +1145,7 @@ void rlOrtho(double left, double right, double bottom, double top, double znear,
|
||||||
// NOTE: If left-right and top-botton values are equal it could create a division by zero,
|
// NOTE: If left-right and top-botton values are equal it could create a division by zero,
|
||||||
// response to it is platform/compiler dependant
|
// response to it is platform/compiler dependant
|
||||||
Matrix matOrtho = { 0 };
|
Matrix matOrtho = { 0 };
|
||||||
|
|
||||||
float rl = (float)(right - left);
|
float rl = (float)(right - left);
|
||||||
float tb = (float)(top - bottom);
|
float tb = (float)(top - bottom);
|
||||||
float fn = (float)(zfar - znear);
|
float fn = (float)(zfar - znear);
|
||||||
|
|
@ -1558,11 +1558,11 @@ void rlActiveDrawBuffers(int count)
|
||||||
// it can be queried with glGet*() but it must be at least 8
|
// it can be queried with glGet*() but it must be at least 8
|
||||||
//GLint maxDrawBuffers = 0;
|
//GLint maxDrawBuffers = 0;
|
||||||
//glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
|
//glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
|
||||||
|
|
||||||
if (count > 0)
|
if (count > 0)
|
||||||
{
|
{
|
||||||
if (count > 8) TRACELOG(LOG_WARNING, "GL: Max color buffers limited to 8");
|
if (count > 8) TRACELOG(LOG_WARNING, "GL: Max color buffers limited to 8");
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
unsigned int buffers[8] = {
|
unsigned int buffers[8] = {
|
||||||
GL_COLOR_ATTACHMENT0,
|
GL_COLOR_ATTACHMENT0,
|
||||||
|
|
@ -2399,10 +2399,10 @@ void rlDrawRenderBatch(rlRenderBatch *batch)
|
||||||
|
|
||||||
// Create modelview-projection matrix and upload to shader
|
// Create modelview-projection matrix and upload to shader
|
||||||
Matrix matMVP = rlMatrixMultiply(RLGL.State.modelview, RLGL.State.projection);
|
Matrix matMVP = rlMatrixMultiply(RLGL.State.modelview, RLGL.State.projection);
|
||||||
float matMVPfloat[16] = {
|
float matMVPfloat[16] = {
|
||||||
matMVP.m0, matMVP.m1, matMVP.m2, matMVP.m3,
|
matMVP.m0, matMVP.m1, matMVP.m2, matMVP.m3,
|
||||||
matMVP.m4, matMVP.m5, matMVP.m6, matMVP.m7,
|
matMVP.m4, matMVP.m5, matMVP.m6, matMVP.m7,
|
||||||
matMVP.m8, matMVP.m9, matMVP.m10, matMVP.m11,
|
matMVP.m8, matMVP.m9, matMVP.m10, matMVP.m11,
|
||||||
matMVP.m12, matMVP.m13, matMVP.m14, matMVP.m15
|
matMVP.m12, matMVP.m13, matMVP.m14, matMVP.m15
|
||||||
};
|
};
|
||||||
glUniformMatrix4fv(RLGL.State.currentShaderLocs[RL_SHADER_LOC_MATRIX_MVP], 1, false, matMVPfloat);
|
glUniformMatrix4fv(RLGL.State.currentShaderLocs[RL_SHADER_LOC_MATRIX_MVP], 1, false, matMVPfloat);
|
||||||
|
|
@ -3467,7 +3467,7 @@ unsigned int rlLoadShaderCode(const char *vsCode, const char *fsCode)
|
||||||
{
|
{
|
||||||
int namelen = -1;
|
int namelen = -1;
|
||||||
int num = -1;
|
int num = -1;
|
||||||
char name[256]; // Assume no variable names longer than 256
|
char name[256] = { 0 }; // Assume no variable names longer than 256
|
||||||
GLenum type = GL_ZERO;
|
GLenum type = GL_ZERO;
|
||||||
|
|
||||||
// Get the name of the uniforms
|
// Get the name of the uniforms
|
||||||
|
|
@ -3582,7 +3582,15 @@ unsigned int rlLoadShaderProgram(unsigned int vShaderId, unsigned int fShaderId)
|
||||||
|
|
||||||
program = 0;
|
program = 0;
|
||||||
}
|
}
|
||||||
else TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Program shader loaded successfully", program);
|
else
|
||||||
|
{
|
||||||
|
// Get the size of compiled shader program (not available on OpenGL ES 2.0)
|
||||||
|
// NOTE: If GL_LINK_STATUS is GL_FALSE, program binary length is zero.
|
||||||
|
//GLint binarySize = 0;
|
||||||
|
//glGetProgramiv(id, GL_PROGRAM_BINARY_LENGTH, &binarySize);
|
||||||
|
|
||||||
|
TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Program shader loaded successfully", program);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
return program;
|
return program;
|
||||||
}
|
}
|
||||||
|
|
@ -3662,10 +3670,10 @@ void rlSetVertexAttributeDefault(int locIndex, const void *value, int attribType
|
||||||
void rlSetUniformMatrix(int locIndex, Matrix mat)
|
void rlSetUniformMatrix(int locIndex, Matrix mat)
|
||||||
{
|
{
|
||||||
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
||||||
float matfloat[16] = {
|
float matfloat[16] = {
|
||||||
mat.m0, mat.m1, mat.m2, mat.m3,
|
mat.m0, mat.m1, mat.m2, mat.m3,
|
||||||
mat.m4, mat.m5, mat.m6, mat.m7,
|
mat.m4, mat.m5, mat.m6, mat.m7,
|
||||||
mat.m8, mat.m9, mat.m10, mat.m11,
|
mat.m8, mat.m9, mat.m10, mat.m11,
|
||||||
mat.m12, mat.m13, mat.m14, mat.m15
|
mat.m12, mat.m13, mat.m14, mat.m15
|
||||||
};
|
};
|
||||||
glUniformMatrix4fv(locIndex, 1, false, matfloat);
|
glUniformMatrix4fv(locIndex, 1, false, matfloat);
|
||||||
|
|
|
||||||
18
src/text.c
18
src/text.c
|
|
@ -899,9 +899,9 @@ void DrawTextPro(Font font, const char *text, Vector2 position, Vector2 origin,
|
||||||
rlTranslatef(position.x, position.y, 0.0f);
|
rlTranslatef(position.x, position.y, 0.0f);
|
||||||
rlRotatef(rotation, 0.0f, 0.0f, 1.0f);
|
rlRotatef(rotation, 0.0f, 0.0f, 1.0f);
|
||||||
rlTranslatef(-origin.x, -origin.y, 0.0f);
|
rlTranslatef(-origin.x, -origin.y, 0.0f);
|
||||||
|
|
||||||
DrawTextEx(font, text, (Vector2){ 0.0f, 0.0f }, fontSize, spacing, tint);
|
DrawTextEx(font, text, (Vector2){ 0.0f, 0.0f }, fontSize, spacing, tint);
|
||||||
|
|
||||||
rlPopMatrix();
|
rlPopMatrix();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1002,7 +1002,7 @@ Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get index position for a unicode character on font
|
// Get index position for a unicode character on font
|
||||||
// NOTE: If codepoint is not found in the font it fallbacks to '?'
|
// NOTE: If codepoint is not found in the font it fallbacks to '?'
|
||||||
int GetGlyphIndex(Font font, int codepoint)
|
int GetGlyphIndex(Font font, int codepoint)
|
||||||
{
|
{
|
||||||
#ifndef GLYPH_NOTFOUND_CHAR_FALLBACK
|
#ifndef GLYPH_NOTFOUND_CHAR_FALLBACK
|
||||||
|
|
@ -1030,24 +1030,24 @@ int GetGlyphIndex(Font font, int codepoint)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get glyph font info data for a codepoint (unicode character)
|
// Get glyph font info data for a codepoint (unicode character)
|
||||||
// NOTE: If codepoint is not found in the font it fallbacks to '?'
|
// NOTE: If codepoint is not found in the font it fallbacks to '?'
|
||||||
GlyphInfo GetGlyphInfo(Font font, int codepoint)
|
GlyphInfo GetGlyphInfo(Font font, int codepoint)
|
||||||
{
|
{
|
||||||
GlyphInfo info = { 0 };
|
GlyphInfo info = { 0 };
|
||||||
|
|
||||||
info = font.chars[GetGlyphIndex(font, codepoint)];
|
info = font.chars[GetGlyphIndex(font, codepoint)];
|
||||||
|
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get glyph rectangle in font atlas for a codepoint (unicode character)
|
// Get glyph rectangle in font atlas for a codepoint (unicode character)
|
||||||
// NOTE: If codepoint is not found in the font it fallbacks to '?'
|
// NOTE: If codepoint is not found in the font it fallbacks to '?'
|
||||||
Rectangle GetGlyphAtlasRec(Font font, int codepoint)
|
Rectangle GetGlyphAtlasRec(Font font, int codepoint)
|
||||||
{
|
{
|
||||||
Rectangle rec = { 0 };
|
Rectangle rec = { 0 };
|
||||||
|
|
||||||
rec = font.recs[GetGlyphIndex(font, codepoint)];
|
rec = font.recs[GetGlyphIndex(font, codepoint)];
|
||||||
|
|
||||||
return rec;
|
return rec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -382,7 +382,7 @@ Image LoadImageFromMemory(const char *fileType, const unsigned char *fileData, i
|
||||||
|
|
||||||
if (image.data != NULL) TRACELOG(LOG_INFO, "IMAGE: Data loaded successfully (%ix%i | %s | %i mipmaps)", image.width, image.height, rlGetPixelFormatName(image.format), image.mipmaps);
|
if (image.data != NULL) TRACELOG(LOG_INFO, "IMAGE: Data loaded successfully (%ix%i | %s | %i mipmaps)", image.width, image.height, rlGetPixelFormatName(image.format), image.mipmaps);
|
||||||
else TRACELOG(LOG_WARNING, "IMAGE: Failed to load image data");
|
else TRACELOG(LOG_WARNING, "IMAGE: Failed to load image data");
|
||||||
|
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2419,28 +2419,28 @@ void ImageDrawPixelV(Image *dst, Vector2 position, Color color)
|
||||||
// Draw line within an image
|
// Draw line within an image
|
||||||
void ImageDrawLine(Image *dst, int startPosX, int startPosY, int endPosX, int endPosY, Color color)
|
void ImageDrawLine(Image *dst, int startPosX, int startPosY, int endPosX, int endPosY, Color color)
|
||||||
{
|
{
|
||||||
// Using Bresenham's algorithm as described in
|
// Using Bresenham's algorithm as described in
|
||||||
// Drawing Lines with Pixels - Joshua Scott - March 2012
|
// Drawing Lines with Pixels - Joshua Scott - March 2012
|
||||||
// https://classic.csunplugged.org/wp-content/uploads/2014/12/Lines.pdf
|
// https://classic.csunplugged.org/wp-content/uploads/2014/12/Lines.pdf
|
||||||
|
|
||||||
int changeInX = (endPosX - startPosX);
|
int changeInX = (endPosX - startPosX);
|
||||||
int absChangeInX = (changeInX < 0)? -changeInX : changeInX;
|
int absChangeInX = (changeInX < 0)? -changeInX : changeInX;
|
||||||
int changeInY = (endPosY - startPosY);
|
int changeInY = (endPosY - startPosY);
|
||||||
int absChangeInY = (changeInY < 0)? -changeInY : changeInY;
|
int absChangeInY = (changeInY < 0)? -changeInY : changeInY;
|
||||||
|
|
||||||
int startU, startV, endU, stepV; // Substitutions, either U = X, V = Y or vice versa. See loop at end of function
|
int startU, startV, endU, stepV; // Substitutions, either U = X, V = Y or vice versa. See loop at end of function
|
||||||
//int endV; // Not needed but left for better understanding, check code below
|
//int endV; // Not needed but left for better understanding, check code below
|
||||||
int A, B, P; // See linked paper above, explained down in the main loop
|
int A, B, P; // See linked paper above, explained down in the main loop
|
||||||
int reversedXY = (absChangeInY < absChangeInX);
|
int reversedXY = (absChangeInY < absChangeInX);
|
||||||
|
|
||||||
if (reversedXY)
|
if (reversedXY)
|
||||||
{
|
{
|
||||||
A = 2*absChangeInY;
|
A = 2*absChangeInY;
|
||||||
B = A - 2*absChangeInX;
|
B = A - 2*absChangeInX;
|
||||||
P = A - absChangeInX;
|
P = A - absChangeInX;
|
||||||
|
|
||||||
if (changeInX > 0)
|
if (changeInX > 0)
|
||||||
{
|
{
|
||||||
startU = startPosX;
|
startU = startPosX;
|
||||||
startV = startPosY;
|
startV = startPosY;
|
||||||
endU = endPosX;
|
endU = endPosX;
|
||||||
|
|
@ -2452,23 +2452,23 @@ void ImageDrawLine(Image *dst, int startPosX, int startPosY, int endPosX, int en
|
||||||
startV = endPosY;
|
startV = endPosY;
|
||||||
endU = startPosX;
|
endU = startPosX;
|
||||||
//endV = startPosY;
|
//endV = startPosY;
|
||||||
|
|
||||||
// Since start and end are reversed
|
// Since start and end are reversed
|
||||||
changeInX = -changeInX;
|
changeInX = -changeInX;
|
||||||
changeInY = -changeInY;
|
changeInY = -changeInY;
|
||||||
}
|
}
|
||||||
|
|
||||||
stepV = (changeInY < 0)? -1 : 1;
|
stepV = (changeInY < 0)? -1 : 1;
|
||||||
|
|
||||||
ImageDrawPixel(dst, startU, startV, color); // At this point they are correctly ordered...
|
ImageDrawPixel(dst, startU, startV, color); // At this point they are correctly ordered...
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
A = 2*absChangeInX;
|
A = 2*absChangeInX;
|
||||||
B = A - 2*absChangeInY;
|
B = A - 2*absChangeInY;
|
||||||
P = A - absChangeInY;
|
P = A - absChangeInY;
|
||||||
|
|
||||||
if (changeInY > 0)
|
if (changeInY > 0)
|
||||||
{
|
{
|
||||||
startU = startPosY;
|
startU = startPosY;
|
||||||
startV = startPosX;
|
startV = startPosX;
|
||||||
|
|
@ -2481,21 +2481,21 @@ void ImageDrawLine(Image *dst, int startPosX, int startPosY, int endPosX, int en
|
||||||
startV = endPosX;
|
startV = endPosX;
|
||||||
endU = startPosY;
|
endU = startPosY;
|
||||||
//endV = startPosX;
|
//endV = startPosX;
|
||||||
|
|
||||||
// Since start and end are reversed
|
// Since start and end are reversed
|
||||||
changeInX = -changeInX;
|
changeInX = -changeInX;
|
||||||
changeInY = -changeInY;
|
changeInY = -changeInY;
|
||||||
}
|
}
|
||||||
|
|
||||||
stepV = (changeInX < 0)? -1 : 1;
|
stepV = (changeInX < 0)? -1 : 1;
|
||||||
|
|
||||||
ImageDrawPixel(dst, startV, startU, color); // ... but need to be reversed here. Repeated in the main loop below
|
ImageDrawPixel(dst, startV, startU, color); // ... but need to be reversed here. Repeated in the main loop below
|
||||||
}
|
}
|
||||||
|
|
||||||
// We already drew the start point. If we started at startU + 0, the line would be crooked and too short
|
// We already drew the start point. If we started at startU + 0, the line would be crooked and too short
|
||||||
for (int u = startU + 1, v = startV; u <= endU; u++)
|
for (int u = startU + 1, v = startV; u <= endU; u++)
|
||||||
{
|
{
|
||||||
if (P >= 0)
|
if (P >= 0)
|
||||||
{
|
{
|
||||||
v += stepV; // Adjusts whenever we stray too far from the direct line. Details in the linked paper above
|
v += stepV; // Adjusts whenever we stray too far from the direct line. Details in the linked paper above
|
||||||
P += B; // Remembers that we corrected our path
|
P += B; // Remembers that we corrected our path
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user