Merge branch 'raysan5:master' into master
This commit is contained in:
commit
f23eeade37
|
|
@ -6,7 +6,7 @@ exception to this however, and that is Windows, because Windows
|
||||||
doesn't have a built-in C compiler. On Windows, you'll need to install
|
doesn't have a built-in C compiler. On Windows, you'll need to install
|
||||||
[Visual Studio][visual-studio] or the [build tools][vs-tools]. If you
|
[Visual Studio][visual-studio] or the [build tools][vs-tools]. If you
|
||||||
didn't install them in the default location, write your changes around
|
didn't install them in the default location, write your changes around
|
||||||
line 101 of [`build-windows.bat`](build-windows.bat).
|
line 38 of [`build-windows.bat`](build-windows.bat).
|
||||||
|
|
||||||
## Script customization
|
## Script customization
|
||||||
First of all, the scripts have a few variables at the very top, which
|
First of all, the scripts have a few variables at the very top, which
|
||||||
|
|
|
||||||
|
|
@ -94,10 +94,6 @@
|
||||||
} CameraProjection;
|
} CameraProjection;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" { // Prevents name mangling of functions
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Global Variables Definition
|
// Global Variables Definition
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
@ -106,6 +102,11 @@ extern "C" { // Prevents name mangling of functions
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Module Functions Declaration
|
// Module Functions Declaration
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" { // Prevents name mangling of functions
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(CAMERA_STANDALONE)
|
#if defined(CAMERA_STANDALONE)
|
||||||
void SetCameraMode(Camera camera, int mode); // Set camera mode (multiple camera modes available)
|
void SetCameraMode(Camera camera, int mode); // Set camera mode (multiple camera modes available)
|
||||||
void UpdateCamera(Camera *camera); // Update camera position for selected mode
|
void UpdateCamera(Camera *camera); // Update camera position for selected mode
|
||||||
|
|
|
||||||
|
|
@ -16,16 +16,9 @@
|
||||||
* If not defined, the library is in header only mode and can be included in other headers
|
* If not defined, the library is in header only mode and can be included in other headers
|
||||||
* or source files without problems. But only ONE file should hold the implementation.
|
* or source files without problems. But only ONE file should hold the implementation.
|
||||||
*
|
*
|
||||||
* #define PHYSAC_STATIC (defined by default)
|
|
||||||
* The generated implementation will stay private inside implementation file and all
|
|
||||||
* internal symbols and functions will only be visible inside that file.
|
|
||||||
*
|
|
||||||
* #define PHYSAC_DEBUG
|
* #define PHYSAC_DEBUG
|
||||||
* Show debug traces log messages about physic bodies creation/destruction, physic system errors,
|
* Show debug traces log messages about physic bodies creation/destruction, physic system errors,
|
||||||
* some calculations results and NULL reference exceptions
|
* some calculations results and NULL reference exceptions.
|
||||||
*
|
|
||||||
* #define PHYSAC_DEFINE_VECTOR2_TYPE
|
|
||||||
* Forces library to define struct Vector2 data type (float x; float y)
|
|
||||||
*
|
*
|
||||||
* #define PHYSAC_AVOID_TIMMING_SYSTEM
|
* #define PHYSAC_AVOID_TIMMING_SYSTEM
|
||||||
* Disables internal timming system, used by UpdatePhysics() to launch timmed physic steps,
|
* Disables internal timming system, used by UpdatePhysics() to launch timmed physic steps,
|
||||||
|
|
@ -79,14 +72,8 @@
|
||||||
#if !defined(PHYSAC_H)
|
#if !defined(PHYSAC_H)
|
||||||
#define PHYSAC_H
|
#define PHYSAC_H
|
||||||
|
|
||||||
#if defined(PHYSAC_STATIC)
|
#ifndef PHYSACDEF
|
||||||
#define PHYSACDEF static // Functions just visible to module including this file
|
#define PHYSACDEF // We are building or using physac as a static library
|
||||||
#else
|
|
||||||
#if defined(__cplusplus)
|
|
||||||
#define PHYSACDEF extern "C" // Functions visible from other files (no name mangling of functions in C++)
|
|
||||||
#else
|
|
||||||
#define PHYSACDEF extern // Functions visible from other files
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Allow custom memory allocators
|
// Allow custom memory allocators
|
||||||
|
|
@ -127,7 +114,7 @@ typedef enum PhysicsShapeType { PHYSICS_CIRCLE = 0, PHYSICS_POLYGON } PhysicsSha
|
||||||
// Previously defined to be used in PhysicsShape struct as circular dependencies
|
// Previously defined to be used in PhysicsShape struct as circular dependencies
|
||||||
typedef struct PhysicsBodyData *PhysicsBody;
|
typedef struct PhysicsBodyData *PhysicsBody;
|
||||||
|
|
||||||
#if defined(PHYSAC_DEFINE_VECTOR2_TYPE)
|
#if !defined(RL_VECTOR2_TYPE)
|
||||||
// Vector2 type
|
// Vector2 type
|
||||||
typedef struct Vector2 {
|
typedef struct Vector2 {
|
||||||
float x;
|
float x;
|
||||||
|
|
@ -192,13 +179,13 @@ typedef struct PhysicsManifoldData {
|
||||||
float staticFriction; // Mixed static friction during collision
|
float staticFriction; // Mixed static friction during collision
|
||||||
} PhysicsManifoldData, *PhysicsManifold;
|
} PhysicsManifoldData, *PhysicsManifold;
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
|
||||||
extern "C" { // Prevents name mangling of functions
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Module Functions Declaration
|
// Module Functions Declaration
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
extern "C" { // Prevents name mangling of functions
|
||||||
|
#endif
|
||||||
// Physics system management
|
// Physics system management
|
||||||
PHYSACDEF void InitPhysics(void); // Initializes physics system
|
PHYSACDEF void InitPhysics(void); // Initializes physics system
|
||||||
PHYSACDEF void UpdatePhysics(void); // Update physics system
|
PHYSACDEF void UpdatePhysics(void); // Update physics system
|
||||||
|
|
@ -225,7 +212,6 @@ PHYSACDEF int GetPhysicsBodiesCount(void);
|
||||||
PHYSACDEF int GetPhysicsShapeType(int index); // Returns the physics body shape type (PHYSICS_CIRCLE or PHYSICS_POLYGON)
|
PHYSACDEF int GetPhysicsShapeType(int index); // Returns the physics body shape type (PHYSICS_CIRCLE or PHYSICS_POLYGON)
|
||||||
PHYSACDEF int GetPhysicsShapeVerticesCount(int index); // Returns the amount of vertices of a physics body shape
|
PHYSACDEF int GetPhysicsShapeVerticesCount(int index); // Returns the amount of vertices of a physics body shape
|
||||||
PHYSACDEF Vector2 GetPhysicsShapeVertex(PhysicsBody body, int vertex); // Returns transformed position of a body shape (body position + vertex transformed position)
|
PHYSACDEF Vector2 GetPhysicsShapeVertex(PhysicsBody body, int vertex); // Returns transformed position of a body shape (body position + vertex transformed position)
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -255,9 +241,15 @@ PHYSACDEF Vector2 GetPhysicsShapeVertex(PhysicsBody body, int vertex);
|
||||||
// Time management functionality
|
// Time management functionality
|
||||||
#include <time.h> // Required for: time(), clock_gettime()
|
#include <time.h> // Required for: time(), clock_gettime()
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
extern "C" { // Prevents name mangling of functions
|
||||||
|
#endif
|
||||||
// Functions required to query time on Windows
|
// Functions required to query time on Windows
|
||||||
int __stdcall QueryPerformanceCounter(unsigned long long int *lpPerformanceCount);
|
int __stdcall QueryPerformanceCounter(unsigned long long int *lpPerformanceCount);
|
||||||
int __stdcall QueryPerformanceFrequency(unsigned long long int *lpFrequency);
|
int __stdcall QueryPerformanceFrequency(unsigned long long int *lpFrequency);
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#if defined(__linux__) || defined(__FreeBSD__)
|
#if defined(__linux__) || defined(__FreeBSD__)
|
||||||
#if _POSIX_C_SOURCE < 199309L
|
#if _POSIX_C_SOURCE < 199309L
|
||||||
|
|
@ -366,7 +358,7 @@ static Vector2 MathTriangleBarycenter(Vector2 v1, Vector2 v2, Vector2 v3);
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
// Initializes physics values, pointers and creates physics loop thread
|
// Initializes physics values, pointers and creates physics loop thread
|
||||||
PHYSACDEF void InitPhysics(void)
|
void InitPhysics(void)
|
||||||
{
|
{
|
||||||
#if !defined(PHYSAC_AVOID_TIMMING_SYSTEM)
|
#if !defined(PHYSAC_AVOID_TIMMING_SYSTEM)
|
||||||
// Initialize high resolution timer
|
// Initialize high resolution timer
|
||||||
|
|
@ -377,21 +369,21 @@ PHYSACDEF void InitPhysics(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sets physics global gravity force
|
// Sets physics global gravity force
|
||||||
PHYSACDEF void SetPhysicsGravity(float x, float y)
|
void SetPhysicsGravity(float x, float y)
|
||||||
{
|
{
|
||||||
gravityForce.x = x;
|
gravityForce.x = x;
|
||||||
gravityForce.y = y;
|
gravityForce.y = y;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates a new circle physics body with generic parameters
|
// Creates a new circle physics body with generic parameters
|
||||||
PHYSACDEF PhysicsBody CreatePhysicsBodyCircle(Vector2 pos, float radius, float density)
|
PhysicsBody CreatePhysicsBodyCircle(Vector2 pos, float radius, float density)
|
||||||
{
|
{
|
||||||
PhysicsBody body = CreatePhysicsBodyPolygon(pos, radius, PHYSAC_DEFAULT_CIRCLE_VERTICES, density);
|
PhysicsBody body = CreatePhysicsBodyPolygon(pos, radius, PHYSAC_DEFAULT_CIRCLE_VERTICES, density);
|
||||||
return body;
|
return body;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates a new rectangle physics body with generic parameters
|
// Creates a new rectangle physics body with generic parameters
|
||||||
PHYSACDEF PhysicsBody CreatePhysicsBodyRectangle(Vector2 pos, float width, float height, float density)
|
PhysicsBody CreatePhysicsBodyRectangle(Vector2 pos, float width, float height, float density)
|
||||||
{
|
{
|
||||||
// NOTE: Make sure body data is initialized to 0
|
// NOTE: Make sure body data is initialized to 0
|
||||||
PhysicsBody body = (PhysicsBody)PHYSAC_CALLOC(sizeof(PhysicsBodyData), 1);
|
PhysicsBody body = (PhysicsBody)PHYSAC_CALLOC(sizeof(PhysicsBodyData), 1);
|
||||||
|
|
@ -469,7 +461,7 @@ PHYSACDEF PhysicsBody CreatePhysicsBodyRectangle(Vector2 pos, float width, float
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates a new polygon physics body with generic parameters
|
// Creates a new polygon physics body with generic parameters
|
||||||
PHYSACDEF PhysicsBody CreatePhysicsBodyPolygon(Vector2 pos, float radius, int sides, float density)
|
PhysicsBody CreatePhysicsBodyPolygon(Vector2 pos, float radius, int sides, float density)
|
||||||
{
|
{
|
||||||
PhysicsBody body = (PhysicsBody)PHYSAC_MALLOC(sizeof(PhysicsBodyData));
|
PhysicsBody body = (PhysicsBody)PHYSAC_MALLOC(sizeof(PhysicsBodyData));
|
||||||
usedMemory += sizeof(PhysicsBodyData);
|
usedMemory += sizeof(PhysicsBodyData);
|
||||||
|
|
@ -551,19 +543,19 @@ PHYSACDEF PhysicsBody CreatePhysicsBodyPolygon(Vector2 pos, float radius, int si
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adds a force to a physics body
|
// Adds a force to a physics body
|
||||||
PHYSACDEF void PhysicsAddForce(PhysicsBody body, Vector2 force)
|
void PhysicsAddForce(PhysicsBody body, Vector2 force)
|
||||||
{
|
{
|
||||||
if (body != NULL) body->force = MathVector2Add(body->force, force);
|
if (body != NULL) body->force = MathVector2Add(body->force, force);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adds an angular force to a physics body
|
// Adds an angular force to a physics body
|
||||||
PHYSACDEF void PhysicsAddTorque(PhysicsBody body, float amount)
|
void PhysicsAddTorque(PhysicsBody body, float amount)
|
||||||
{
|
{
|
||||||
if (body != NULL) body->torque += amount;
|
if (body != NULL) body->torque += amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shatters a polygon shape physics body to little physics bodies with explosion force
|
// Shatters a polygon shape physics body to little physics bodies with explosion force
|
||||||
PHYSACDEF void PhysicsShatter(PhysicsBody body, Vector2 position, float force)
|
void PhysicsShatter(PhysicsBody body, Vector2 position, float force)
|
||||||
{
|
{
|
||||||
if (body != NULL)
|
if (body != NULL)
|
||||||
{
|
{
|
||||||
|
|
@ -700,13 +692,13 @@ PHYSACDEF void PhysicsShatter(PhysicsBody body, Vector2 position, float force)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the current amount of created physics bodies
|
// Returns the current amount of created physics bodies
|
||||||
PHYSACDEF int GetPhysicsBodiesCount(void)
|
int GetPhysicsBodiesCount(void)
|
||||||
{
|
{
|
||||||
return physicsBodiesCount;
|
return physicsBodiesCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns a physics body of the bodies pool at a specific index
|
// Returns a physics body of the bodies pool at a specific index
|
||||||
PHYSACDEF PhysicsBody GetPhysicsBody(int index)
|
PhysicsBody GetPhysicsBody(int index)
|
||||||
{
|
{
|
||||||
PhysicsBody body = NULL;
|
PhysicsBody body = NULL;
|
||||||
|
|
||||||
|
|
@ -722,7 +714,7 @@ PHYSACDEF PhysicsBody GetPhysicsBody(int index)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the physics body shape type (PHYSICS_CIRCLE or PHYSICS_POLYGON)
|
// Returns the physics body shape type (PHYSICS_CIRCLE or PHYSICS_POLYGON)
|
||||||
PHYSACDEF int GetPhysicsShapeType(int index)
|
int GetPhysicsShapeType(int index)
|
||||||
{
|
{
|
||||||
int result = -1;
|
int result = -1;
|
||||||
|
|
||||||
|
|
@ -739,7 +731,7 @@ PHYSACDEF int GetPhysicsShapeType(int index)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the amount of vertices of a physics body shape
|
// Returns the amount of vertices of a physics body shape
|
||||||
PHYSACDEF int GetPhysicsShapeVerticesCount(int index)
|
int GetPhysicsShapeVerticesCount(int index)
|
||||||
{
|
{
|
||||||
int result = 0;
|
int result = 0;
|
||||||
|
|
||||||
|
|
@ -764,7 +756,7 @@ PHYSACDEF int GetPhysicsShapeVerticesCount(int index)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns transformed position of a body shape (body position + vertex transformed position)
|
// Returns transformed position of a body shape (body position + vertex transformed position)
|
||||||
PHYSACDEF Vector2 GetPhysicsShapeVertex(PhysicsBody body, int vertex)
|
Vector2 GetPhysicsShapeVertex(PhysicsBody body, int vertex)
|
||||||
{
|
{
|
||||||
Vector2 position = { 0.0f, 0.0f };
|
Vector2 position = { 0.0f, 0.0f };
|
||||||
|
|
||||||
|
|
@ -791,7 +783,7 @@ PHYSACDEF Vector2 GetPhysicsShapeVertex(PhysicsBody body, int vertex)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sets physics body shape transform based on radians parameter
|
// Sets physics body shape transform based on radians parameter
|
||||||
PHYSACDEF void SetPhysicsBodyRotation(PhysicsBody body, float radians)
|
void SetPhysicsBodyRotation(PhysicsBody body, float radians)
|
||||||
{
|
{
|
||||||
if (body != NULL)
|
if (body != NULL)
|
||||||
{
|
{
|
||||||
|
|
@ -802,7 +794,7 @@ PHYSACDEF void SetPhysicsBodyRotation(PhysicsBody body, float radians)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unitializes and destroys a physics body
|
// Unitializes and destroys a physics body
|
||||||
PHYSACDEF void DestroyPhysicsBody(PhysicsBody body)
|
void DestroyPhysicsBody(PhysicsBody body)
|
||||||
{
|
{
|
||||||
if (body != NULL)
|
if (body != NULL)
|
||||||
{
|
{
|
||||||
|
|
@ -844,7 +836,7 @@ PHYSACDEF void DestroyPhysicsBody(PhysicsBody body)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Destroys created physics bodies and manifolds and resets global values
|
// Destroys created physics bodies and manifolds and resets global values
|
||||||
PHYSACDEF void ResetPhysics(void)
|
void ResetPhysics(void)
|
||||||
{
|
{
|
||||||
if (physicsBodiesCount > 0)
|
if (physicsBodiesCount > 0)
|
||||||
{
|
{
|
||||||
|
|
@ -886,7 +878,7 @@ PHYSACDEF void ResetPhysics(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unitializes physics pointers and exits physics loop thread
|
// Unitializes physics pointers and exits physics loop thread
|
||||||
PHYSACDEF void ClosePhysics(void)
|
void ClosePhysics(void)
|
||||||
{
|
{
|
||||||
// Unitialize physics manifolds dynamic memory allocations
|
// Unitialize physics manifolds dynamic memory allocations
|
||||||
if (physicsManifoldsCount > 0)
|
if (physicsManifoldsCount > 0)
|
||||||
|
|
@ -912,91 +904,98 @@ PHYSACDEF void ClosePhysics(void)
|
||||||
else TRACELOG("[PHYSAC] Physics module closed successfully\n");
|
else TRACELOG("[PHYSAC] Physics module closed successfully\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update physics system
|
||||||
|
// Physics steps are launched at a fixed time step if enabled
|
||||||
|
void UpdatePhysics(void)
|
||||||
|
{
|
||||||
|
#if !defined(PHYSAC_AVOID_TIMMING_SYSTEM)
|
||||||
|
static double deltaTimeAccumulator = 0.0;
|
||||||
|
|
||||||
|
// Calculate current time (ms)
|
||||||
|
currentTime = GetCurrentTime();
|
||||||
|
|
||||||
|
// Calculate current delta time (ms)
|
||||||
|
const double delta = currentTime - startTime;
|
||||||
|
|
||||||
|
// Store the time elapsed since the last frame began
|
||||||
|
deltaTimeAccumulator += delta;
|
||||||
|
|
||||||
|
// Fixed time stepping loop
|
||||||
|
while (deltaTimeAccumulator >= deltaTime)
|
||||||
|
{
|
||||||
|
UpdatePhysicsStep();
|
||||||
|
deltaTimeAccumulator -= deltaTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Record the starting of this frame
|
||||||
|
startTime = currentTime;
|
||||||
|
#else
|
||||||
|
UpdatePhysicsStep();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetPhysicsTimeStep(double delta)
|
||||||
|
{
|
||||||
|
deltaTime = delta;
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Module Internal Functions Definition
|
// Module Internal Functions Definition
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Finds a valid index for a new physics body initialization
|
#if !defined(PHYSAC_AVOID_TIMMING_SYSTEM)
|
||||||
static int FindAvailableBodyIndex()
|
// Initializes hi-resolution MONOTONIC timer
|
||||||
|
static void InitTimerHiRes(void)
|
||||||
{
|
{
|
||||||
int index = -1;
|
#if defined(_WIN32)
|
||||||
for (int i = 0; i < PHYSAC_MAX_BODIES; i++)
|
QueryPerformanceFrequency((unsigned long long int *) &frequency);
|
||||||
{
|
#endif
|
||||||
int currentId = i;
|
|
||||||
|
|
||||||
// Check if current id already exist in other physics body
|
#if defined(__EMSCRIPTEN__) || defined(__linux__)
|
||||||
for (unsigned int k = 0; k < physicsBodiesCount; k++)
|
struct timespec now;
|
||||||
{
|
if (clock_gettime(CLOCK_MONOTONIC, &now) == 0) frequency = 1000000000;
|
||||||
if (bodies[k]->id == currentId)
|
#endif
|
||||||
{
|
|
||||||
currentId++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If it is not used, use it as new physics body id
|
#if defined(__APPLE__)
|
||||||
if (currentId == (int)i)
|
mach_timebase_info_data_t timebase;
|
||||||
{
|
mach_timebase_info(&timebase);
|
||||||
index = (int)i;
|
frequency = (timebase.denom*1e9)/timebase.numer;
|
||||||
break;
|
#endif
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return index;
|
baseClockTicks = (double)GetClockTicks(); // Get MONOTONIC clock time offset
|
||||||
|
startTime = GetCurrentTime(); // Get current time in milliseconds
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates a default polygon shape with max vertex distance from polygon pivot
|
// Get hi-res MONOTONIC time measure in clock ticks
|
||||||
static PhysicsVertexData CreateDefaultPolygon(float radius, int sides)
|
static unsigned long long int GetClockTicks(void)
|
||||||
{
|
{
|
||||||
PhysicsVertexData data = { 0 };
|
unsigned long long int value = 0;
|
||||||
data.vertexCount = sides;
|
|
||||||
|
|
||||||
// Calculate polygon vertices positions
|
#if defined(_WIN32)
|
||||||
for (unsigned int i = 0; i < data.vertexCount; i++)
|
QueryPerformanceCounter((unsigned long long int *) &value);
|
||||||
{
|
#endif
|
||||||
data.positions[i].x = (float)cosf(360.0f/sides*i*PHYSAC_DEG2RAD)*radius;
|
|
||||||
data.positions[i].y = (float)sinf(360.0f/sides*i*PHYSAC_DEG2RAD)*radius;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate polygon faces normals
|
#if defined(__linux__)
|
||||||
for (int i = 0; i < (int)data.vertexCount; i++)
|
struct timespec now;
|
||||||
{
|
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||||
int nextIndex = (((i + 1) < sides) ? (i + 1) : 0);
|
value = (unsigned long long int)now.tv_sec*(unsigned long long int)1000000000 + (unsigned long long int)now.tv_nsec;
|
||||||
Vector2 face = MathVector2Subtract(data.positions[nextIndex], data.positions[i]);
|
#endif
|
||||||
|
|
||||||
data.normals[i] = CLITERAL(Vector2){ face.y, -face.x };
|
#if defined(__APPLE__)
|
||||||
MathVector2Normalize(&data.normals[i]);
|
value = mach_absolute_time();
|
||||||
}
|
#endif
|
||||||
|
|
||||||
return data;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates a rectangle polygon shape based on a min and max positions
|
// Get current time in milliseconds
|
||||||
static PhysicsVertexData CreateRectanglePolygon(Vector2 pos, Vector2 size)
|
static double GetCurrentTime(void)
|
||||||
{
|
{
|
||||||
PhysicsVertexData data = { 0 };
|
return (double)(GetClockTicks() - baseClockTicks)/frequency*1000;
|
||||||
data.vertexCount = 4;
|
|
||||||
|
|
||||||
// Calculate polygon vertices positions
|
|
||||||
data.positions[0] = CLITERAL(Vector2){ pos.x + size.x/2, pos.y - size.y/2 };
|
|
||||||
data.positions[1] = CLITERAL(Vector2){ pos.x + size.x/2, pos.y + size.y/2 };
|
|
||||||
data.positions[2] = CLITERAL(Vector2){ pos.x - size.x/2, pos.y + size.y/2 };
|
|
||||||
data.positions[3] = CLITERAL(Vector2){ pos.x - size.x/2, pos.y - size.y/2 };
|
|
||||||
|
|
||||||
// Calculate polygon faces normals
|
|
||||||
for (unsigned int i = 0; i < data.vertexCount; i++)
|
|
||||||
{
|
|
||||||
int nextIndex = (((i + 1) < data.vertexCount) ? (i + 1) : 0);
|
|
||||||
Vector2 face = MathVector2Subtract(data.positions[nextIndex], data.positions[i]);
|
|
||||||
|
|
||||||
data.normals[i] = CLITERAL(Vector2){ face.y, -face.x };
|
|
||||||
MathVector2Normalize(&data.normals[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
}
|
||||||
|
#endif // !PHYSAC_AVOID_TIMMING_SYSTEM
|
||||||
|
|
||||||
// Update physics step (dynamics, collisions and position corrections)
|
// Update physics step (dynamics, collisions and position corrections)
|
||||||
void UpdatePhysicsStep(void)
|
static void UpdatePhysicsStep(void)
|
||||||
{
|
{
|
||||||
// Clear previous generated collisions information
|
// Clear previous generated collisions information
|
||||||
for (int i = (int)physicsManifoldsCount - 1; i >= 0; i--)
|
for (int i = (int)physicsManifoldsCount - 1; i >= 0; i--)
|
||||||
|
|
@ -1098,39 +1097,84 @@ void UpdatePhysicsStep(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update physics system
|
// Finds a valid index for a new physics body initialization
|
||||||
// Physics steps are launched at a fixed time step if enabled
|
static int FindAvailableBodyIndex()
|
||||||
PHYSACDEF void UpdatePhysics(void)
|
|
||||||
{
|
{
|
||||||
#if !defined(PHYSAC_AVOID_TIMMING_SYSTEM)
|
int index = -1;
|
||||||
static double deltaTimeAccumulator = 0.0;
|
for (int i = 0; i < PHYSAC_MAX_BODIES; i++)
|
||||||
|
|
||||||
// Calculate current time (ms)
|
|
||||||
currentTime = GetCurrentTime();
|
|
||||||
|
|
||||||
// Calculate current delta time (ms)
|
|
||||||
const double delta = currentTime - startTime;
|
|
||||||
|
|
||||||
// Store the time elapsed since the last frame began
|
|
||||||
deltaTimeAccumulator += delta;
|
|
||||||
|
|
||||||
// Fixed time stepping loop
|
|
||||||
while (deltaTimeAccumulator >= deltaTime)
|
|
||||||
{
|
{
|
||||||
UpdatePhysicsStep();
|
int currentId = i;
|
||||||
deltaTimeAccumulator -= deltaTime;
|
|
||||||
|
// Check if current id already exist in other physics body
|
||||||
|
for (unsigned int k = 0; k < physicsBodiesCount; k++)
|
||||||
|
{
|
||||||
|
if (bodies[k]->id == currentId)
|
||||||
|
{
|
||||||
|
currentId++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Record the starting of this frame
|
// If it is not used, use it as new physics body id
|
||||||
startTime = currentTime;
|
if (currentId == (int)i)
|
||||||
#else
|
{
|
||||||
UpdatePhysicsStep();
|
index = (int)i;
|
||||||
#endif
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
PHYSACDEF void SetPhysicsTimeStep(double delta)
|
// Creates a default polygon shape with max vertex distance from polygon pivot
|
||||||
|
static PhysicsVertexData CreateDefaultPolygon(float radius, int sides)
|
||||||
{
|
{
|
||||||
deltaTime = delta;
|
PhysicsVertexData data = { 0 };
|
||||||
|
data.vertexCount = sides;
|
||||||
|
|
||||||
|
// Calculate polygon vertices positions
|
||||||
|
for (unsigned int i = 0; i < data.vertexCount; i++)
|
||||||
|
{
|
||||||
|
data.positions[i].x = (float)cosf(360.0f/sides*i*PHYSAC_DEG2RAD)*radius;
|
||||||
|
data.positions[i].y = (float)sinf(360.0f/sides*i*PHYSAC_DEG2RAD)*radius;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate polygon faces normals
|
||||||
|
for (int i = 0; i < (int)data.vertexCount; i++)
|
||||||
|
{
|
||||||
|
int nextIndex = (((i + 1) < sides) ? (i + 1) : 0);
|
||||||
|
Vector2 face = MathVector2Subtract(data.positions[nextIndex], data.positions[i]);
|
||||||
|
|
||||||
|
data.normals[i] = CLITERAL(Vector2){ face.y, -face.x };
|
||||||
|
MathVector2Normalize(&data.normals[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates a rectangle polygon shape based on a min and max positions
|
||||||
|
static PhysicsVertexData CreateRectanglePolygon(Vector2 pos, Vector2 size)
|
||||||
|
{
|
||||||
|
PhysicsVertexData data = { 0 };
|
||||||
|
data.vertexCount = 4;
|
||||||
|
|
||||||
|
// Calculate polygon vertices positions
|
||||||
|
data.positions[0] = CLITERAL(Vector2){ pos.x + size.x/2, pos.y - size.y/2 };
|
||||||
|
data.positions[1] = CLITERAL(Vector2){ pos.x + size.x/2, pos.y + size.y/2 };
|
||||||
|
data.positions[2] = CLITERAL(Vector2){ pos.x - size.x/2, pos.y + size.y/2 };
|
||||||
|
data.positions[3] = CLITERAL(Vector2){ pos.x - size.x/2, pos.y - size.y/2 };
|
||||||
|
|
||||||
|
// Calculate polygon faces normals
|
||||||
|
for (unsigned int i = 0; i < data.vertexCount; i++)
|
||||||
|
{
|
||||||
|
int nextIndex = (((i + 1) < data.vertexCount) ? (i + 1) : 0);
|
||||||
|
Vector2 face = MathVector2Subtract(data.positions[nextIndex], data.positions[i]);
|
||||||
|
|
||||||
|
data.normals[i] = CLITERAL(Vector2){ face.y, -face.x };
|
||||||
|
MathVector2Normalize(&data.normals[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finds a valid index for a new manifold initialization
|
// Finds a valid index for a new manifold initialization
|
||||||
|
|
@ -1844,59 +1888,6 @@ static Vector2 MathTriangleBarycenter(Vector2 v1, Vector2 v2, Vector2 v3)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !defined(PHYSAC_AVOID_TIMMING_SYSTEM)
|
|
||||||
// Initializes hi-resolution MONOTONIC timer
|
|
||||||
static void InitTimerHiRes(void)
|
|
||||||
{
|
|
||||||
#if defined(_WIN32)
|
|
||||||
QueryPerformanceFrequency((unsigned long long int *) &frequency);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(__EMSCRIPTEN__) || defined(__linux__)
|
|
||||||
struct timespec now;
|
|
||||||
if (clock_gettime(CLOCK_MONOTONIC, &now) == 0) frequency = 1000000000;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(__APPLE__)
|
|
||||||
mach_timebase_info_data_t timebase;
|
|
||||||
mach_timebase_info(&timebase);
|
|
||||||
frequency = (timebase.denom*1e9)/timebase.numer;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
baseClockTicks = (double)GetClockTicks(); // Get MONOTONIC clock time offset
|
|
||||||
startTime = GetCurrentTime(); // Get current time in milliseconds
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get hi-res MONOTONIC time measure in clock ticks
|
|
||||||
static unsigned long long int GetClockTicks(void)
|
|
||||||
{
|
|
||||||
unsigned long long int value = 0;
|
|
||||||
|
|
||||||
#if defined(_WIN32)
|
|
||||||
QueryPerformanceCounter((unsigned long long int *) &value);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(__linux__)
|
|
||||||
struct timespec now;
|
|
||||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
|
||||||
value = (unsigned long long int)now.tv_sec*(unsigned long long int)1000000000 + (unsigned long long int)now.tv_nsec;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(__APPLE__)
|
|
||||||
value = mach_absolute_time();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get current time in milliseconds
|
|
||||||
static double GetCurrentTime(void)
|
|
||||||
{
|
|
||||||
return (double)(GetClockTicks() - baseClockTicks)/frequency*1000;
|
|
||||||
}
|
|
||||||
#endif // !PHYSAC_AVOID_TIMMING_SYSTEM
|
|
||||||
|
|
||||||
|
|
||||||
// Returns the cross product of a vector and a value
|
// Returns the cross product of a vector and a value
|
||||||
static inline Vector2 MathVector2Product(Vector2 vector, float value)
|
static inline Vector2 MathVector2Product(Vector2 vector, float value)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -99,10 +99,6 @@ typedef struct {
|
||||||
Vector2 position[4];
|
Vector2 position[4];
|
||||||
} GestureEvent;
|
} GestureEvent;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" { // Prevents name mangling of functions
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Global Variables Definition
|
// Global Variables Definition
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
@ -111,9 +107,13 @@ extern "C" { // Prevents name mangling of functions
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Module Functions Declaration
|
// Module Functions Declaration
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" { // Prevents name mangling of functions
|
||||||
|
#endif
|
||||||
|
|
||||||
void ProcessGestureEvent(GestureEvent event); // Process gesture event and translate it into gestures
|
void ProcessGestureEvent(GestureEvent event); // Process gesture event and translate it into gestures
|
||||||
void UpdateGestures(void); // Update gestures detected (must be called every frame)
|
void UpdateGestures(void); // Update gestures detected (must be called every frame)
|
||||||
|
|
||||||
#if defined(GESTURES_STANDALONE)
|
#if defined(GESTURES_STANDALONE)
|
||||||
void SetGesturesEnabled(unsigned int flags); // Enable a set of gestures using flags
|
void SetGesturesEnabled(unsigned int flags); // Enable a set of gestures using flags
|
||||||
bool IsGestureDetected(int gesture); // Check if a gesture have been detected
|
bool IsGestureDetected(int gesture); // Check if a gesture have been detected
|
||||||
|
|
@ -141,9 +141,15 @@ float GetGesturePinchAngle(void); // Get gesture pinch ang
|
||||||
#if defined(GESTURES_IMPLEMENTATION)
|
#if defined(GESTURES_IMPLEMENTATION)
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
extern "C" { // Prevents name mangling of functions
|
||||||
|
#endif
|
||||||
// Functions required to query time on Windows
|
// Functions required to query time on Windows
|
||||||
int __stdcall QueryPerformanceCounter(unsigned long long int *lpPerformanceCount);
|
int __stdcall QueryPerformanceCounter(unsigned long long int *lpPerformanceCount);
|
||||||
int __stdcall QueryPerformanceFrequency(unsigned long long int *lpFrequency);
|
int __stdcall QueryPerformanceFrequency(unsigned long long int *lpFrequency);
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
#elif defined(__linux__)
|
#elif defined(__linux__)
|
||||||
#if _POSIX_C_SOURCE < 199309L
|
#if _POSIX_C_SOURCE < 199309L
|
||||||
#undef _POSIX_C_SOURCE
|
#undef _POSIX_C_SOURCE
|
||||||
|
|
|
||||||
154
src/raudio.c
154
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,7 +1310,7 @@ 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)
|
||||||
|
{
|
||||||
|
#if defined(SUPPORT_FILEFORMAT_XM)
|
||||||
|
if (music.ctxType == MUSIC_MODULE_XM)
|
||||||
|
{
|
||||||
|
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;
|
//ma_uint32 frameSizeInBytes = ma_get_bytes_per_sample(music.stream.buffer->dsp.formatConverterIn.config.formatIn)*music.stream.buffer->dsp.formatConverterIn.config.channels;
|
||||||
unsigned int samplesPlayed = music.stream.buffer->framesProcessed*music.stream.channels;
|
unsigned int framesPlayed = music.stream.buffer->framesProcessed;
|
||||||
secondsPlayed = (float)samplesPlayed/(music.stream.sampleRate*music.stream.channels);
|
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);
|
||||||
|
|
|
||||||
39
src/raudio.h
39
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 {
|
||||||
|
rAudioBuffer *buffer; // Pointer to internal data used by the audio system
|
||||||
|
|
||||||
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, ...)
|
||||||
|
|
||||||
rAudioBuffer *buffer; // Pointer to internal data used by the audio system
|
|
||||||
} 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 {
|
||||||
|
AudioStream stream; // Audio stream
|
||||||
|
unsigned int frameCount; // Total number of frames (considering channels)
|
||||||
|
bool looping; // Music looping enable
|
||||||
|
|
||||||
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
|
||||||
|
|
||||||
bool looping; // Music looping enable
|
|
||||||
unsigned int sampleCount; // Total number of samples
|
|
||||||
|
|
||||||
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
|
||||||
|
|
|
||||||
32
src/raylib.h
32
src/raylib.h
|
|
@ -81,19 +81,18 @@
|
||||||
|
|
||||||
#include <stdarg.h> // Required for: va_list - Only used by TraceLogCallback
|
#include <stdarg.h> // Required for: va_list - Only used by TraceLogCallback
|
||||||
|
|
||||||
#define RAYLIB_VERSION "3.8-dev"
|
#define RAYLIB_VERSION "4.0-dev"
|
||||||
|
|
||||||
|
#ifndef RLAPI
|
||||||
|
#define RLAPI // We are building or using rlgl as a static library (or Linux shared library)
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
// Microsoft attibutes to tell compiler that symbols are imported/exported from a .dll
|
|
||||||
#if defined(BUILD_LIBTYPE_SHARED)
|
#if defined(BUILD_LIBTYPE_SHARED)
|
||||||
#define RLAPI __declspec(dllexport) // We are building raylib as a Win32 shared library (.dll)
|
#define RLAPI __declspec(dllexport) // We are building raylib as a Win32 shared library (.dll)
|
||||||
#elif defined(USE_LIBTYPE_SHARED)
|
#elif defined(USE_LIBTYPE_SHARED)
|
||||||
#define RLAPI __declspec(dllimport) // We are using raylib as a Win32 shared library (.dll)
|
#define RLAPI __declspec(dllimport) // We are using raylib as a Win32 shared library (.dll)
|
||||||
#else
|
|
||||||
#define RLAPI // We are building or using raylib as a static library
|
|
||||||
#endif
|
#endif
|
||||||
#else
|
|
||||||
#define RLAPI // We are building or using raylib as a static library (or Linux shared library)
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
@ -424,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;
|
||||||
|
|
||||||
|
|
@ -439,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)
|
||||||
|
|
@ -894,11 +893,6 @@ typedef bool (*SaveFileDataCallback)(const char *fileName, void *data, unsigned
|
||||||
typedef char *(*LoadFileTextCallback)(const char *fileName); // FileIO: Load text data
|
typedef char *(*LoadFileTextCallback)(const char *fileName); // FileIO: Load text data
|
||||||
typedef bool (*SaveFileTextCallback)(const char *fileName, char *text); // FileIO: Save text data
|
typedef bool (*SaveFileTextCallback)(const char *fileName, char *text); // FileIO: Save text data
|
||||||
|
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
|
||||||
extern "C" { // Prevents name mangling of functions
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
// Global Variables Definition
|
// Global Variables Definition
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
|
|
@ -908,6 +902,10 @@ extern "C" { // Prevents name mangling of functions
|
||||||
// Window and Graphics Device Functions (Module: core)
|
// Window and Graphics Device Functions (Module: core)
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
extern "C" { // Prevents name mangling of functions
|
||||||
|
#endif
|
||||||
|
|
||||||
// Window-related functions
|
// Window-related functions
|
||||||
RLAPI void InitWindow(int width, int height, const char *title); // Initialize window and OpenGL context
|
RLAPI void InitWindow(int width, int height, const char *title); // Initialize window and OpenGL context
|
||||||
RLAPI bool WindowShouldClose(void); // Check if KEY_ESCAPE pressed or Close icon pressed
|
RLAPI bool WindowShouldClose(void); // Check if KEY_ESCAPE pressed or Close icon pressed
|
||||||
|
|
@ -1515,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
|
||||||
|
|
|
||||||
20
src/rlgl.h
20
src/rlgl.h
|
|
@ -457,13 +457,14 @@ typedef enum {
|
||||||
RL_SHADER_ATTRIB_VEC4 // Shader attribute type: vec4 (4 float)
|
RL_SHADER_ATTRIB_VEC4 // Shader attribute type: vec4 (4 float)
|
||||||
} rlShaderAttributeDataType;
|
} rlShaderAttributeDataType;
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
|
// Functions Declaration - Matrix operations
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
extern "C" { // Prevents name mangling of functions
|
extern "C" { // Prevents name mangling of functions
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------
|
|
||||||
// Functions Declaration - Matrix operations
|
|
||||||
//------------------------------------------------------------------------------------
|
|
||||||
RLAPI void rlMatrixMode(int mode); // Choose the current matrix to be transformed
|
RLAPI void rlMatrixMode(int mode); // Choose the current matrix to be transformed
|
||||||
RLAPI void rlPushMatrix(void); // Push the current matrix to stack
|
RLAPI void rlPushMatrix(void); // Push the current matrix to stack
|
||||||
RLAPI void rlPopMatrix(void); // Pop lattest inserted matrix from stack
|
RLAPI void rlPopMatrix(void); // Pop lattest inserted matrix from stack
|
||||||
|
|
@ -642,6 +643,7 @@ RLAPI void rlSetMatrixViewOffsetStereo(Matrix right, Matrix left); // Set e
|
||||||
// Quick and dirty cube/quad buffers load->draw->unload
|
// Quick and dirty cube/quad buffers load->draw->unload
|
||||||
RLAPI void rlLoadDrawCube(void); // Load and draw a cube
|
RLAPI void rlLoadDrawCube(void); // Load and draw a cube
|
||||||
RLAPI void rlLoadDrawQuad(void); // Load and draw a quad
|
RLAPI void rlLoadDrawQuad(void); // Load and draw a quad
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -3465,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
|
||||||
|
|
@ -3580,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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -55,9 +55,7 @@
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Types and Structures Definition
|
// Types and Structures Definition
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
#ifdef __cplusplus
|
//...
|
||||||
extern "C" { // Prevents name mangling of functions
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Global Variables Definition
|
// Global Variables Definition
|
||||||
|
|
@ -67,6 +65,10 @@ extern "C" { // Prevents name mangling of functions
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Module Functions Declaration
|
// Module Functions Declaration
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" { // Prevents name mangling of functions
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(PLATFORM_ANDROID)
|
#if defined(PLATFORM_ANDROID)
|
||||||
void InitAssetManager(AAssetManager *manager, const char *dataPath); // Initialize asset manager from android app
|
void InitAssetManager(AAssetManager *manager, const char *dataPath); // Initialize asset manager from android app
|
||||||
FILE *android_fopen(const char *fileName, const char *mode); // Replacement for fopen() -> Read-only!
|
FILE *android_fopen(const char *fileName, const char *mode); // Replacement for fopen() -> Read-only!
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user